feat(agent): control reasoning visibility

This commit is contained in:
2026-07-17 14:05:54 +08:00
parent bfaf2ebf67
commit a879dc2ff1
18 changed files with 368 additions and 51 deletions

View File

@@ -29,6 +29,7 @@ from app.services.agent_debug_service import AgentDebugService
from app.services.feishu_service import FeishuKnowledgeService
from app.services.knowledge_service import KnowledgeScope
from app.services.model_service import ModelClientService
from app.services.reasoning_policy_service import ReasoningPolicyService
from app.services.secret_service import MASKED_SECRET, SENSITIVE_CONFIG_KEYS, SecretService
router = APIRouter()
@@ -205,7 +206,7 @@ def get_agent_runtime_config(
current_admin: Admin = Depends(get_current_admin),
) -> dict:
model = _enabled_model(db)
return api_success(_agent_runtime_config_dict(model))
return api_success(_agent_runtime_config_dict(model, ReasoningPolicyService.is_visible(db)))
@router.put("/agent/runtime-config")
@@ -228,6 +229,7 @@ def save_agent_runtime_config(
model.max_token = payload.maxToken
model.stream_enabled = payload.streamEnabled
db.add(model)
ReasoningPolicyService.set_visible(db, payload.reasoningVisible == 1, current_admin.id)
OperationLogService.write(
db,
admin_id=current_admin.id,
@@ -237,7 +239,7 @@ def save_agent_runtime_config(
)
db.commit()
db.refresh(model)
return api_success(_agent_runtime_config_dict(model))
return api_success(_agent_runtime_config_dict(model, ReasoningPolicyService.is_visible(db)))
@router.get("/model/list")
@@ -441,7 +443,7 @@ def _enabled_model(db: Session) -> ModelConfig | None:
)
def _agent_runtime_config_dict(model: ModelConfig | None) -> dict:
def _agent_runtime_config_dict(model: ModelConfig | None, reasoning_visible: bool = False) -> dict:
return {
"modelId": model.id if model is not None else None,
"modelName": (model.display_name or model.model_name) if model is not None else None,
@@ -452,6 +454,7 @@ def _agent_runtime_config_dict(model: ModelConfig | None) -> dict:
"frequencyPenalty": float(model.frequency_penalty) if model is not None and model.frequency_penalty is not None else None,
"maxToken": model.max_token if model is not None and model.max_token is not None else 8192,
"streamEnabled": model.stream_enabled if model is not None else 1,
"reasoningVisible": 1 if reasoning_visible else 0,
}

View File

@@ -30,6 +30,7 @@ from app.services.chat_queue_runtime import (
)
from app.services.chat_queue_service import load_chat_queue_config
from app.services.chat_stream_service import ChatStreamService
from app.services.reasoning_policy_service import ReasoningPolicyService
router = APIRouter()
logger = logging.getLogger(__name__)
@@ -54,7 +55,14 @@ def history(
current_user: User = Depends(get_current_user),
) -> dict:
messages = ChatService.get_history(db, current_user, sessionId)
return api_success([ChatMessageRead.model_validate(message).model_dump(mode="json") for message in messages])
reasoning_visible = ReasoningPolicyService.is_visible(db)
result = []
for message in messages:
item = ChatMessageRead.model_validate(message).model_dump(mode="json")
if message.role == "assistant" and not reasoning_visible:
item["content"] = ReasoningPolicyService.strip_reasoning(item["content"])
result.append(item)
return api_success(result)
@router.put("/session/title")
@@ -152,14 +160,20 @@ async def _chat_stream(payload: ChatCompletionRequest, db: Session, current_user
return
try:
reasoning_visible = ReasoningPolicyService.is_visible(db)
yield _sse_event(
"generating",
message="已进入生成队列,正在生成回答。",
message="思考中",
activeCount=queue_request.active_count,
waitingCount=queue_request.waiting_count,
reasoningVisible=reasoning_visible,
)
async for chunk in ChatStreamService.stream_answer_async(db, current_user, payload.sessionId, payload.message):
yield _sse_event("content", content=chunk)
chunks = ChatStreamService.stream_answer_async(db, current_user, payload.sessionId, payload.message)
async for segment in ReasoningPolicyService.iter_segments(chunks):
if segment.kind == "content":
yield _sse_event("content", content=segment.content)
elif reasoning_visible:
yield _sse_event("reasoning", content=segment.content)
except HTTPException as exc:
yield _sse_event("error", message=str(exc.detail))
except asyncio.CancelledError: