diff --git a/ai_knowledge_base_v2/apps/admin-web/src/components/AgentManagementView.vue b/ai_knowledge_base_v2/apps/admin-web/src/components/AgentManagementView.vue index 393ce4e..cd1810f 100644 --- a/ai_knowledge_base_v2/apps/admin-web/src/components/AgentManagementView.vue +++ b/ai_knowledge_base_v2/apps/admin-web/src/components/AgentManagementView.vue @@ -49,6 +49,8 @@ const agentForm = reactive({ presencePenalty: null as number | null, frequencyPenalty: null as number | null, maxToken: 8192 as number | null, + streamEnabled: 1, + reasoningVisible: 0, question: "", }); const runtimeConfig = ref(null); @@ -130,6 +132,8 @@ function applyDebugModelDefaults(modelId?: number) { presencePenalty: model.presencePenalty ?? null, frequencyPenalty: model.frequencyPenalty ?? null, maxToken: model.maxToken ?? (model.enabled === 1 ? runtimeConfig.value?.maxToken : null) ?? 8192, + streamEnabled: model.streamEnabled ?? 1, + reasoningVisible: runtimeConfig.value?.reasoningVisible ?? 0, }); } @@ -293,6 +297,8 @@ async function debugAgent() { presencePenalty: agentForm.presencePenalty, frequencyPenalty: agentForm.frequencyPenalty, maxToken: agentForm.maxToken, + streamEnabled: agentForm.streamEnabled, + reasoningVisible: agentForm.reasoningVisible, }, (chunk) => { currentAssistant().content += chunk; @@ -469,6 +475,34 @@ function errorMessage(error: unknown, fallback: string) { v-model:frequency-penalty="agentForm.frequencyPenalty" v-model:max-token="agentForm.maxToken" /> + +
+ 流式输出 + 开启后后台预览会边生成边展示;关闭后等待模型完成再一次性显示。 +
+ +
+ +
+ 展示思考过程 + 开启后本次后台预览可展开查看模型思考内容;不会修改用户端正式配置。 +
+ +
diff --git a/ai_knowledge_base_v2/apps/backend/app/schemas/admin.py b/ai_knowledge_base_v2/apps/backend/app/schemas/admin.py index 80813fc..7894d58 100644 --- a/ai_knowledge_base_v2/apps/backend/app/schemas/admin.py +++ b/ai_knowledge_base_v2/apps/backend/app/schemas/admin.py @@ -89,6 +89,8 @@ class AgentDebugRequest(BaseModel): presencePenalty: float | None = Field(default=None, ge=-2, le=2) frequencyPenalty: float | None = Field(default=None, ge=-2, le=2) maxToken: int | None = Field(default=8192, ge=1, le=100000) + streamEnabled: int = Field(default=1, ge=0, le=1) + reasoningVisible: int = Field(default=0, ge=0, le=1) class AgentRuntimeConfigSaveRequest(BaseModel): diff --git a/ai_knowledge_base_v2/apps/backend/app/services/agent_debug_service.py b/ai_knowledge_base_v2/apps/backend/app/services/agent_debug_service.py index a9b6bea..60fd731 100644 --- a/ai_knowledge_base_v2/apps/backend/app/services/agent_debug_service.py +++ b/ai_knowledge_base_v2/apps/backend/app/services/agent_debug_service.py @@ -48,6 +48,7 @@ class AgentDebugService: "presence_penalty": payload.presencePenalty, "frequency_penalty": payload.frequencyPenalty, "max_token": payload.maxToken, + "stream_enabled": payload.streamEnabled, } @classmethod @@ -62,7 +63,7 @@ class AgentDebugService: yield {"type": "error", "message": "模型不存在"} return try: - reasoning_visible = ReasoningPolicyService.is_visible(db) + reasoning_visible = payload.reasoningVisible == 1 yield { "type": "status", "stage": "retrieving", diff --git a/ai_knowledge_base_v2/apps/backend/app/services/model_service.py b/ai_knowledge_base_v2/apps/backend/app/services/model_service.py index e438073..5a409bc 100644 --- a/ai_knowledge_base_v2/apps/backend/app/services/model_service.py +++ b/ai_knowledge_base_v2/apps/backend/app/services/model_service.py @@ -169,7 +169,7 @@ def _copy_model_with_overrides(model: ModelConfig, overrides: dict[str, Any]) -> frequency_penalty=overrides.get("frequency_penalty"), max_token=overrides.get("max_token"), context_window=model.context_window, - stream_enabled=model.stream_enabled, + stream_enabled=overrides.get("stream_enabled", model.stream_enabled), response_format=model.response_format, extra_params=model.extra_params, remark=model.remark, diff --git a/ai_knowledge_base_v2/apps/backend/tests/test_agent_runtime_config.py b/ai_knowledge_base_v2/apps/backend/tests/test_agent_runtime_config.py index 797519d..69cdf5a 100644 --- a/ai_knowledge_base_v2/apps/backend/tests/test_agent_runtime_config.py +++ b/ai_knowledge_base_v2/apps/backend/tests/test_agent_runtime_config.py @@ -13,12 +13,13 @@ from app.models import Base from app.models.admin import Admin from app.models.ai_config import ModelConfig, SystemConfig from app.schemas.admin import AgentDebugRequest, AgentRuntimeConfigSaveRequest +from app.services.agent_debug_service import AgentDebugService from app.services.model_stream_service import ( AsyncStreamingModelResponse, _openai_stream_payload, _stream_configured_model_async, ) -from app.services.model_service import ModelClientService, _max_output_tokens +from app.services.model_service import ModelClientService, _copy_model_with_overrides, _max_output_tokens from app.services.rag_service import RagResult @@ -146,6 +147,23 @@ def test_disabled_stream_returns_one_complete_chunk(): assert chunks == [answer] +def test_debug_stream_setting_overrides_model_without_changing_it(): + model = _model() + debug_model = _copy_model_with_overrides(model, {"stream_enabled": 0}) + + assert model.stream_enabled == 1 + assert debug_model.stream_enabled == 0 + + payload = AgentDebugRequest( + promptContent="测试", + modelId=1, + question="测试", + streamEnabled=0, + reasoningVisible=1, + ) + assert AgentDebugService.overrides(payload)["stream_enabled"] == 0 + + @pytest.mark.parametrize("reasoning_visible", [True, False]) def test_agent_debug_stream_respects_reasoning_visibility(reasoning_visible): async def chunks(): @@ -179,7 +197,7 @@ def test_agent_debug_stream_respects_reasoning_visibility(reasoning_visible): db.add(SystemConfig( id=1, config_key="show_model_reasoning", - config_value="true" if reasoning_visible else "false", + config_value="false" if reasoning_visible else "true", )) db.commit() payload = AgentDebugRequest( @@ -188,6 +206,7 @@ def test_agent_debug_stream_respects_reasoning_visibility(reasoning_visible): knowledgeIds=[], question="怎么冷静", maxToken=8192, + reasoningVisible=1 if reasoning_visible else 0, ) with ( patch(