|
45 | 45 | from app.utils.http import RequestUtils, AsyncRequestUtils |
46 | 46 | from app.utils.security import SecurityUtils |
47 | 47 | from app.utils.url import UrlUtils |
| 48 | +from pydantic import BaseModel |
48 | 49 | from version import APP_VERSION |
49 | 50 |
|
50 | 51 | router = APIRouter() |
51 | 52 |
|
52 | 53 | _NETTEST_REDIRECT_STATUS_CODES = {301, 302, 303, 307, 308} |
53 | 54 |
|
54 | 55 |
|
| 56 | +class LlmTestRequest(BaseModel): |
| 57 | + enabled: Optional[bool] = None |
| 58 | + provider: Optional[str] = None |
| 59 | + model: Optional[str] = None |
| 60 | + api_key: Optional[str] = None |
| 61 | + base_url: Optional[str] = None |
| 62 | + |
| 63 | + |
55 | 64 | def _match_nettest_prefix(url: str, prefix: str) -> bool: |
56 | 65 | """ |
57 | 66 | 判断目标URL是否仍然落在允许的协议、主机、端口和路径前缀内。 |
@@ -276,16 +285,50 @@ def _build_llm_test_data( |
276 | 285 | return data |
277 | 286 |
|
278 | 287 |
|
279 | | -def _build_llm_test_snapshot() -> dict[str, Any]: |
| 288 | +def _normalize_llm_test_value( |
| 289 | + value: Optional[str], *, empty_as_none: bool = False |
| 290 | +) -> Optional[str]: |
280 | 291 | """ |
281 | | - 冻结当前 LLM 测试所需配置,避免请求执行过程中被新的保存动作改写。 |
| 292 | + 清理来自前端的 LLM 测试字段。 |
| 293 | + """ |
| 294 | + if value is None: |
| 295 | + return None |
| 296 | + stripped = value.strip() |
| 297 | + if empty_as_none and not stripped: |
| 298 | + return None |
| 299 | + return stripped |
| 300 | + |
| 301 | + |
| 302 | +def _build_llm_test_snapshot(payload: Optional[LlmTestRequest] = None) -> dict[str, Any]: |
282 | 303 | """ |
| 304 | + 冻结当前 LLM 测试所需配置。 |
| 305 | +
|
| 306 | + 优先使用前端传入的临时参数;未传入时回退到已保存配置,兼容旧调用。 |
| 307 | + """ |
| 308 | + provider = settings.LLM_PROVIDER |
| 309 | + model = settings.LLM_MODEL |
| 310 | + api_key = settings.LLM_API_KEY |
| 311 | + base_url = settings.LLM_BASE_URL |
| 312 | + enabled = bool(settings.AI_AGENT_ENABLE) |
| 313 | + |
| 314 | + if payload: |
| 315 | + if payload.enabled is not None: |
| 316 | + enabled = bool(payload.enabled) |
| 317 | + if payload.provider is not None: |
| 318 | + provider = _normalize_llm_test_value(payload.provider) or "" |
| 319 | + if payload.model is not None: |
| 320 | + model = _normalize_llm_test_value(payload.model) or "" |
| 321 | + if payload.api_key is not None: |
| 322 | + api_key = _normalize_llm_test_value(payload.api_key, empty_as_none=True) |
| 323 | + if payload.base_url is not None: |
| 324 | + base_url = _normalize_llm_test_value(payload.base_url, empty_as_none=True) |
| 325 | + |
283 | 326 | return { |
284 | | - "enabled": bool(settings.AI_AGENT_ENABLE), |
285 | | - "provider": settings.LLM_PROVIDER, |
286 | | - "model": settings.LLM_MODEL, |
287 | | - "api_key": settings.LLM_API_KEY, |
288 | | - "base_url": settings.LLM_BASE_URL, |
| 327 | + "enabled": enabled, |
| 328 | + "provider": provider, |
| 329 | + "model": model, |
| 330 | + "api_key": api_key, |
| 331 | + "base_url": base_url, |
289 | 332 | } |
290 | 333 |
|
291 | 334 |
|
@@ -679,11 +722,14 @@ async def get_llm_models( |
679 | 722 |
|
680 | 723 |
|
681 | 724 | @router.post("/llm-test", summary="测试LLM调用", response_model=schemas.Response) |
682 | | -async def llm_test(_: User = Depends(get_current_active_superuser_async)): |
| 725 | +async def llm_test( |
| 726 | + payload: Annotated[Optional[LlmTestRequest], Body()] = None, |
| 727 | + _: User = Depends(get_current_active_superuser_async), |
| 728 | +): |
683 | 729 | """ |
684 | | - 使用当前已保存配置执行一次最小 LLM 调用。 |
| 730 | + 使用传入配置或当前已保存配置执行一次最小 LLM 调用。 |
685 | 731 | """ |
686 | | - snapshot = _build_llm_test_snapshot() |
| 732 | + snapshot = _build_llm_test_snapshot(payload) |
687 | 733 | data = _build_llm_test_data( |
688 | 734 | provider=snapshot["provider"], |
689 | 735 | model=snapshot["model"], |
|
0 commit comments