线上现象:用户发消息后助手回 「大模型错误:The `reasoning_content` in the thinking mode must be passed back to the API.」 根因:DeepSeek V4 系列(含 deepseek-flash)默认开启 thinking mode。官方协议规定, 只要请求带 tools 参数,历史里所有 assistant 消息的 reasoning_content 都必须原样回传, 否则接口直接回 HTTP 400。而 ChatMessage.toJson() 只输出 role/content/tool_calls/tool_call_id, 把该字段整个丢掉 —— 于是「第一轮模型调工具成功、第二轮请求必炸」。 改动: - ChatMessage 增加 reasoningContent 字段并在 toJson 里输出(非空才输出);ChatResult 同步解析响应字段。 - AgentOrchestrator 新增 assistantOf(),把模型每次返回的思维链写回对应的 assistant 消息 (带 tool_calls 的那条与最终回复那条都要带)。 - DeepSeekClient: * 新增 agent.llm.thinking(auto/enabled/disabled),按配置显式发送 thinking 字段; * 命中 reasoning_content 协议错误时自动关闭 thinking 重试一次(自愈,线上无需等改配置即可恢复); * humanizeApiError 增加该错误的中文话术,避免原样抛出英文协议报错。 - AgentSettings.Llm.thinking 由 boolean 改为三态字符串,默认 disabled: 本工程属工具密集编排,几乎每轮都带 tools,CoT 收益有限却显著增加延迟与 token, 且 thinking 模式下 temperature 会被忽略。 - application.yml 补 agent.llm.thinking: disabled 与说明。 新增 ThinkingModeTest(7 例):字段序列化/省略、disabled 与 auto 的请求体、响应解析、 命中协议错误时的自愈重试、以及非协议错误不被误重试。
线上容器漏注入 DEEPSEEK_API_KEY 时,api-key 会落到 application.yml 里的中文 占位符,直到某个用户发起一次对话才以 HTTP 401 暴露: ResourceAccessException: I/O error on POST ... java.net.HttpRetryException: cannot retry due to server authentication, in streaming mode 排查成本很高。 DeepSeekClient 增加 @PostConstruct 自检(可 grep [大模型]): - 为空 / 仍含"请替换"占位符 -> ERROR,并写明修法 - 不以 sk- 开头 -> WARN 提示格式可疑 - 正常 -> INFO 打长度 + host + model(不打印 key 本体) 修法提示:在 projman 的 /app/config/application-prod.yml 填真实 key, 或给容器注入环境变量 DEEPSEEK_API_KEY(勿写入 public 仓库中的 application.yml)。
- com.yunhai.agent,端口 8093,context-path /agent,制品 target/agent.jar;与 NoticeService 同构 - CAS 单点登录 + 三层角色权限(学生/教师/管理员/访客)+ 会话与工具调用审计落库 - DeepSeek 大模型编排 + 7 个业务模块工具(请假/公告/宿舍/活动/作业/资源库/教师发展) - 浏览器代执行协议(服务端挂起 → 前端用登录态代调 → toolResult 续跑)+ 调用失败深链兜底 - 登出修复:服务端真正 session.invalidate() + 前端两步登出 + logout-guard - 保留 projman 注入的 .gitea/workflows/build.yml 与 docker/Dockerfile;docker/application-prod.yml、run-app.sh 随工程入库