尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Spring AI 2.0 接 DeepSeek:别从十万字笔记开始,先搭 5 层生产骨架

Spring AI 2.0 接 DeepSeek:别从十万字笔记开始,先搭 5 层生产骨架 学 Spring AI 很容易掉进一个坑先收集几万字笔记从 Ollama、OpenAI、DeepSeek、流式输出一直抄到会话记忆、Function Calling、RAG、Redis 和 MySQL最后每一段都似乎调通了却说不清哪层负责安全、状态和故障恢复。当前 Spring AI 2.0.0 已有原生 DeepSeek starter、统一 Chat API、记忆 repository、工具调用和可观测能力。与其从历史课程的几十个步骤开始不如先把一条最小对话链路拆成五层让每层都能回答输入从哪里来可以修改或调用什么敏感数据在哪里失败如何表达用什么证据验收。先搭五层骨架再加 RAG 和业务功能第一层入口契约Controller 的职责不是把任意字符串原样送给模型。它至少要定义谁有权调用message、conversationId和业务字段的长度与格式同步、SSE 或其他输出协议限流、超时、取消和业务错误格式哪些 provider 错误不应直接暴露给用户。一个最小请求对象可以是publicrecordChatRequest(NotBlankSize(max4_000)Stringmessage,NotBlankSize(max128)StringconversationId){}这里有意没把model、temperature和 API key 暴露成用户可任意修改的请求字段。provider 策略应由服务配置或受控业务规则决定。第二层ChatClient 编排ChatClient提供类似 SpringWebClient/RestClient的 fluent API同时支持call()和stream()。Chat Client API把公共 system 指令、记忆 Advisor、工具列表和默认行为放在统一配置处不要散落在每个 ControllerBeanChatClientchatClient(ChatModelchatModel,ChatMemorychatMemory){returnChatClient.builder(chatModel).defaultAdvisors(MessageChatMemoryAdvisor.builder(chatMemory).build()).build();}流式接口显式声明 SSE并传入经身份校验后的会话 IDPostMapping(value/stream,producesMediaType.TEXT_EVENT_STREAM_VALUE)FluxStringstream(ValidRequestBodyChatRequestrequest){returnchatClient.prompt().user(request.message()).advisors(a-a.param(ChatMemory.CONVERSATION_ID,request.conversationId())).stream().content();}生产代码中conversationId不能只由前端随意提供后直接信任。它必须与当前用户、租户和业务资源关联否则只需猜到他人 ID 就可能混入他人上下文。第三层原生 DeepSeekChatModel当前 Spring AI 可以直接添加原生 DeepSeek starterdependencygroupIdorg.springframework.ai/groupIdartifactIdspring-ai-starter-model-deepseek/artifactId/dependency通过 Spring AI BOM 统一版本不要给每个 AI 模块单独拼凑版本dependencyManagementdependenciesdependencygroupIdorg.springframework.ai/groupIdartifactIdspring-ai-bom/artifactIdversion2.0.0/versiontypepom/typescopeimport/scope/dependency/dependencies/dependencyManagement密钥从环境或专用 secret manager 读取不写进可提交 YAMLspring:ai:model:chat:deepseekdeepseek:api-key:${DEEPSEEK_API_KEY}chat:model:${DEEPSEEK_MODEL}当前配置项已使用spring.ai.model.chatdeepseek历史文章中的spring.ai.deepseek.chat.enabled已被删除。原生 DeepSeek 文档图Spring AI 用统一 Model 抽象承载不同模态和 provider业务层不应绑死某个底层客户端。记忆与历史必须分开原笔记已经注意到“会话记忆”和“会话历史”不同这是很重要的判断。当前官方文档将它们定义为Chat Memory模型为维持当前上下文而保留的相关消息Chat History用户与模型交换的完整记录。ChatMemory不适合代替完整历史存储。默认MessageWindowChatMemory使用内存 repository 并保留最多 20 条消息超出窗口后会淘汰旧轮次。Chat Memory生产设计至少要分成三个对象会话元数据用户、租户、标题、时间、状态完整历史用于展示、审计、导出或用户删除模型记忆经窗口、摘要或检索选择后送给模型的部分。官方已提供 JDBC、Redis、MongoDB、Neo4j 等 memory repository。但需要特别注意当前 JDBC ChatMemoryRepository 会过滤 tool call 和 tool response 消息。如果应用依赖完整工具轨迹不能只看“已持久化”就假设消息类型全部保留。工具调用是业务副作不是 prompt 技巧Spring AI 当前支持将 DeepSeek 工具循环交给ChatClientToolCallingAdvisor也支持业务代码用ToolCallingManager自行控制。不管选哪种一个副作工具在执行前都要明确当前用户是否有权操作目标资源操作是只读、可回滚还是不可逆重试是否会重复下单、发送、扣费或写入必须在什么情况下要求人确认工具失败、超时或返回不完整数据时如何收束。仅在 system prompt 中写“不要操作无权资源”不够。权限必须在工具服务再验证一次幂等必须由业务键或事务机制保证。可观测不等于打印完整 promptSpring AI 基于 Spring 生态的 metrics 和 tracing为ChatClient、Advisor、ChatModel、工具调用和向量库等提供观测。可观测文档最小观测项包括请求次数、延迟和当前并发provider 和请求/响应模型输入、输出和总 token 使用量工具名称、延迟、错误与调用 ID超时、限流、重试和最终失败的业务结果。prompt、completion、tool arguments 和 tool result 可能很大也可能包含隐私或密钥。Spring AI 默认不导出这些内容。只为故障诊断打开完整日志时要限定环境、保留周期和可见人群并先做脱敏。重试不能靠默认值不经思考地托底DeepSeek starter 的当前文档列出了统一spring.ai.retry配置包括最大尝试、指数退避和哪些 HTTP 状态可重试。默认不对 4xx 客户端错误重试这是合理的起点无效 key、无权限和错误请求不会因为再发一次就变正确。但是否重试 429、5xx 或网络超时仍要根据请求的成本、用户等待上限、provider 限制和业务幂等设计。流式输出已经向用户发送了部分内容时重试还要避免重复片段。第一版只需要八个可运行检查配置启动缺少DEEPSEEK_API_KEY时快速失败不带假 key 启动后等首次请求爆错。输入校验空消息、超长消息和无权 conversation ID 被拒绝。流式协议content type 正确客户端取消后服务端停止继续消耗。会话隔离不同用户即使猜到相同 conversation ID也无法获取对方上下文。窗口边界超出 memory window 后旧轮次按预期淘汰系统消息仍保留。工具授权无权用户即使模型请求了工具服务层也不执行。工具幂等相同业务键的重试不会重复写入或扣费。观测脱敏常规 traces 中可见延迟、模型和 token 用量不出现完整 prompt、API key 和工具私密结果。这八项全部可以在未加 RAG、未做复杂前端、未接真实业务工具时先实现。它们构成后续扩展的安全地基。再看原文中的几个典型坑坑一生产 CORS 允许所有来源allowedOrigins(*)可以让本地调试快速通却不应作为生产默认。只允许已知前端域名并把不同环境的 origin 放入外部配置。如果使用 Cookie 凭证还要一起设计 credentials、CSRF 和 SameSite不能只改一个响应头。坑二把数据库密码写在教程 YAML 中即使是本地演示口令也会被读者原样复制到项目和提交记录中。所有密钥、数据库口令和 provider token 都用环境变量或 secret manager并在启动时校验是否存在。坑三把完整历史全部塞回 prompt无限增长的上下文会增加成本、延迟和噪音。完整历史用于产品查看和审计模型记忆使用窗口、摘要或检索只选与当前问题相关的部分。结语一条对话接口调通只能证明你已经能向 provider 发请求并收到结果。它不能证明会话隔离、工具权限、重试幂等、隐私和故障可观测已经可靠。Spring AI 真正的价值是帮助 Spring 开发者用熟悉的分层、配置、Advisor、repository 和 observability 方式管理这些边界。所以不要先问“十万字教程还剩多少没抄”。先问你的五层骨架是否已经做到入口可校验编排有一处provider 可替换状态与副作有边界每次请求都能被观测和验收。
返回列表