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

资讯详情

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

8、Spring AI Chat Model(对话模型)

8、Spring AI Chat Model(对话模型) Spring AI 的Chat Model API是整个框架的核心基石之一。它为开发者提供了一套简单且可移植的接口用于与各种 AI 聊天模型进行交互。无论你使用的是 OpenAI、Ollama、Amazon Bedrock、Mistral AI 还是 AnthropicChat Model API 都能让你以最小的代码改动在不同模型之间切换。本教程将深入讲解 Chat Model API 的核心组件、设计哲学与实战用法。一、API 整体架构1.1 设计哲学Spring AI Chat Model API 的设计遵循了 Spring 框架一贯的设计理念模块化与可替换性通过统一的接口抽象让底层模型实现可自由切换简单性屏蔽与各大 AI 厂商 SDK 交互的复杂性关注点分离将请求构建Prompt、模型调用ChatModel、响应解析ChatResponse清晰分离1.2 核心组件一览组件职责类比理解ChatModel同步调用 AI 模型类似JdbcTemplate的同步查询StreamingChatModel流式调用 AI 模型类似反应式的Flux数据流Prompt封装输入消息与选项类似 SQL 查询的参数封装ChatResponse封装模型输出类似 SQL 查询的返回结果集Generation单条模型生成结果类似结果集中的一行记录1.3 类关系图┌────────────┐ implements ┌──────────────────┐ │ ChatModel │────────────────▶│ StreamingChatModel│ └──────┬─────┘ └────────┬─────────┘ │ │ │ uses │ uses ▼ ▼ ┌────────────┐ ┌────────────┐ │ Prompt │────────────────────────▶│ChatResponse│ └──────┬─────┘ └──────┬─────┘ │ │ │ contains │ contains ▼ ▼ ┌────────────┐ ┌────────────┐ │ Message │ │ Generation │ └────────────┘ └────────────┘二、ChatModel 接口详解2.1 接口定义ChatModel是所有聊天模型的顶级同步接口定义如下publicinterfaceChatModelextendsModelPrompt,ChatResponse,StreamingChatModel{// 简化版调用直接传入字符串defaultStringcall(Stringmessage){...}// 标准调用传入 Prompt 对象返回 ChatResponseChatResponsecall(Promptprompt);}关键要点ChatModel继承了ModelPrompt, ChatResponse和StreamingChatModel提供了两个call方法重载分别对应简单调用和完整调用两种场景默认实现了call(String)内部会将字符串包装为UserMessage再调用call(Prompt)2.2 最简调用示例当你只需要快速发送一条消息并获取字符串响应时ServicepublicclassSimpleChatService{privatefinalChatModelchatModel;publicSimpleChatService(ChatModelchatModel){this.chatModelchatModel;}publicStringaskSimple(Stringquestion){returnchatModel.call(question);}}2.3 完整调用示例当你需要控制更多参数如多轮对话、系统提示词、温度参数等时使用Prompt对象ServicepublicclassAdvancedChatService{privatefinalChatModelchatModel;publicAdvancedChatService(ChatModelchatModel){this.chatModelchatModel;}publicChatResponseaskAdvanced(StringsystemPrompt,StringuserQuestion){SystemMessagesystemMessagenewSystemMessage(systemPrompt);UserMessageuserMessagenewUserMessage(userQuestion);PromptpromptnewPrompt(List.of(systemMessage,userMessage));returnchatModel.call(prompt);}}三、StreamingChatModel 接口详解3.1 接口定义StreamingChatModel提供流式响应能力适合处理长文本生成场景publicinterfaceStreamingChatModelextendsStreamingModelPrompt,ChatResponse{// 简化版流式调用defaultFluxStringstream(Stringmessage){...}// 标准流式调用FluxChatResponsestream(Promptprompt);}3.2 流式调用示例示例 1直接获取字符串流RestControllerpublicclassStreamController{privatefinalStreamingChatModelstreamingChatModel;publicStreamController(StreamingChatModelstreamingChatModel){this.streamingChatModelstreamingChatModel;}GetMapping(value/stream,producesMediaType.TEXT_EVENT_STREAM_VALUE)publicFluxStringstreamChat(RequestParamStringmessage){returnstreamingChatModel.stream(message);}}示例 2获取完整的 ChatResponse 流ServicepublicclassStreamService{privatefinalStreamingChatModelstreamingChatModel;publicStreamService(StreamingChatModelstreamingChatModel){this.streamingChatModelstreamingChatModel;}publicvoidstreamWithMetadata(Stringquestion){UserMessageuserMessagenewUserMessage(question);PromptpromptnewPrompt(List.of(userMessage));streamingChatModel.stream(prompt).doOnNext(response-{response.getResults().forEach(generation-{Stringcontentgeneration.getOutput().getText();System.out.print(content);});}).doOnComplete(()-System.out.println(\n[Stream Done])).subscribe();}}3.3 为什么使用流式 API场景同步call()流式stream()短文本回复适合可用于长文本生成用户需等待全部完成用户可实时看到输出打字机效果不支持原生支持实时反馈进度不支持原生支持网络异常恢复需重试整段可断点续传四、Prompt输入封装4.1 Prompt 类结构Prompt实现了ModelRequestListMessage接口是发送给 AI 模型的完整请求publicclassPromptimplementsModelRequestListMessage{privatefinalListMessagemessages;// 对话消息列表privateChatOptionsmodelOptions;// 模型参数选项OverridepublicChatOptionsgetOptions(){...}OverridepublicListMessagegetInstructions(){...}}4.2 Prompt 的便捷方法Prompt类提供了许多便捷方法来快速构建和检查消息// 获取最后一条用户消息UserMessagelastUserMessageprompt.getUserMessage();// 获取所有用户消息ListUserMessageuserMessagesprompt.getUserMessages();// 获取第一条系统消息SystemMessagesystemMessageprompt.getSystemMessage();// 获取所有系统消息ListSystemMessagesystemMessagesprompt.getSystemMessages();4.3 常见构建方式方式一单轮对话PromptpromptnewPrompt(你好请介绍一下 Spring AI。);方式二带系统提示的单轮对话SystemMessagesystemMessagenewSystemMessage(你是一位专业的 Java 技术专家。);UserMessageuserMessagenewUserMessage(请讲解一下 Spring AI);PromptpromptnewPrompt(List.of(systemMessage,userMessage));方式三多轮对话上下文ListMessageconversationList.of(newSystemMessage(你是一位编程助手。),newUserMessage(我想学习 Spring AI),newAssistantMessage(好的Spring AI 是...),newUserMessage(请继续讲解 Chat Model API));PromptpromptnewPrompt(conversation);五、Message消息模型5.1 接口层次publicinterfaceContent{StringgetText();MapString,ObjectgetMetadata();}publicinterfaceMessageextendsContent{MessageTypegetMessageType();}// 支持多模态的消息类型publicinterfaceMediaContentextendsContent{CollectionMediagetMedia();}5.2 消息类型MessageTypeMessageType定义了消息在对话中的角色类型说明典型用途USER用户消息发送问题、指令、请求ASSISTANTAI 助手的回复保持多轮对话的上下文连贯SYSTEM系统消息定义 AI 的身份、行为规则TOOL工具调用结果AI 使用 Function Calling 时的工具返回值5.3 四种具体消息实现// 1. 用户消息UserMessageuserMessagenewUserMessage(请帮我写一段代码);// 2. 助手消息AssistantMessageassistantMessagenewAssistantMessage(好的这是代码...);// 3. 系统消息SystemMessagesystemMessagenewSystemMessage(你是一位专业的代码审查专家);// 4. 工具消息Function Calling 场景ToolMessagetoolMessagenewToolMessage(搜索结果如下...,tool-call-id-123);5.4 多模态消息Spring AI 还支持多模态消息可通过MediaContent接口传入图片等媒体内容UserMessagemultimodalMessagenewUserMessage(请描述这张图片,List.of(newMedia(MimeTypeFactory.parseMimeType(image/png),imageResource)));六、ChatOptions模型参数配置6.1 ChatOptions 接口ChatOptions是所有模型选项的通用抽象publicinterfaceChatOptionsextendsModelOptions{StringgetModel();DoublegetFrequencyPenalty();IntegergetMaxTokens();DoublegetPresencePenalty();ListStringgetStopSequences();DoublegetTemperature();IntegergetTopK();DoublegetTopP();ChatOptions.Builder?mutate();}6.2 通用参数说明参数类型作用推荐范围modelString模型名称依赖具体模型temperatureDouble采样温度值越高越随机0.0 ~ 2.0maxTokensInteger最大生成 token 数依模型上下文而定topPDoublenucleus 采样参数0.0 ~ 1.0topKIntegertop-k 采样参数正整数stopSequencesList停止序列依场景而定frequencyPenaltyDouble频率惩罚减少重复-2.0 ~ 2.0presencePenaltyDouble存在惩罚鼓励新话题-2.0 ~ 2.06.3 配置优先级Spring AI 的 Chat Model API 采用双层配置策略┌─────────────────────────────────────────────────────────┐ │ 配置优先级 │ ├─────────────────────────────────────────────────────────┤ │ 1️⃣ 启动配置Start-Up Options │ │ ↓ 初始化时设置作为默认值 │ │ │ │ 2️⃣ 运行时配置Runtime Options ← 完全覆盖启动配置 │ │ ↓ 每个请求可通过 Prompt 动态设置 │ └─────────────────────────────────────────────────────────┘示例启动时设置默认选项ConfigurationpublicclassChatConfig{BeanpublicChatModelchatModel(OpenAiClientaiClient){OpenAiChatOptionsoptionsOpenAiChatOptions.builder().withModel(gpt-4).withTemperature(0.7).withMaxTokens(2000).build();returnnewOpenAiChatModel(aiClient,options);}}示例请求时覆盖选项// 为特定请求临时使用更低的温度使回答更确定OpenAiChatOptionspreciseOptionsOpenAiChatOptions.builder().withTemperature(0.1).build();PromptpromptnewPrompt(List.of(newUserMessage(请精确计算 123 * 456)),preciseOptions);ChatResponseresponsechatModel.call(prompt);6.4 模型特有选项除了通用选项外各模型实现还支持自己特有的参数。例如 OpenAI Chat Completion 支持logitBias调整特定 token 的生成概率seed用于确定性生成user用户标识便于监控开发者可以通过模型特定的ChatOptions子类来使用这些高级特性。七、ChatResponse响应封装7.1 ChatResponse 结构ChatResponse是ChatModel.call()方法的返回值封装了模型的完整输出publicclassChatResponseimplementsModelResponseGeneration{privatefinalChatResponseMetadatachatResponseMetadata;privatefinalListGenerationgenerations;OverridepublicChatResponseMetadatagetMetadata(){...}OverridepublicListGenerationgetResults(){...}}7.2 常用方法ChatResponseresponsechatModel.call(prompt);// 获取所有生成结果ListGenerationgenerationsresponse.getResults();// 获取第一个生成的文本最常用Stringcontentresponse.getResult().getOutput().getText();// 获取 AI 使用的 token 数量等元数据ChatResponseMetadatametadataresponse.getMetadata();System.out.println(消耗 tokens: metadata.getUsage());7.3 ChatResponseMetadata 元数据ChatResponseMetadata包含了模型响应的关键信息id响应唯一标识model使用的模型名称usagetoken 使用量prompt tokens、completion tokens、total tokensrateLimit速率限制信息八、Generation生成结果单元8.1 Generation 结构Generation代表一次模型生成的完整输出是ChatResponse的基本单元publicclassGenerationimplementsModelResultAssistantMessage{privatefinalAssistantMessageassistantMessage;privateChatGenerationMetadatachatGenerationMetadata;OverridepublicAssistantMessagegetOutput(){...}OverridepublicChatGenerationMetadatagetMetadata(){...}}8.2 使用示例ChatResponseresponsechatModel.call(prompt);for(Generationgeneration:response.getResults()){// 获取 AI 助手的消息AssistantMessageassistantMessagegeneration.getOutput();// 获取生成的文本内容StringtextassistantMessage.getText();System.out.println(生成内容: text);// 获取生成元数据ChatGenerationMetadatagenerationMetadatageneration.getMetadata();System.out.println(生成元数据: generationMetadata);}8.3 AssistantMessage 的附加特性AssistantMessage除了文本内容外还可能包含工具调用Tool Calls当 AI 使用 Function Calling 时AssistantMessage中会包含工具调用信息媒体内容多模态输出时可能包含生成的图片等AssistantMessageassistantMessagegeneration.getOutput();// 检查是否包含工具调用if(!assistantMessage.getToolCalls().isEmpty()){for(ToolCalltoolCall:assistantMessage.getToolCalls()){System.out.println(调用工具: toolCall.name());System.out.println(工具参数: toolCall.arguments());}}九、常见问题与最佳实践9.1 如何选择 ChatModel 还是 ChatClient场景推荐使用快速原型开发、简单对话ChatClient高级 API需要精细控制 Prompt 结构ChatModel低级 API需要管理多轮对话历史ChatModel 手动管理消息列表流式响应场景StreamingChatModel或ChatClient.stream()需要使用 Function CallingChatClient更简洁9.2 如何处理 Token 限制publicStringchatWithTokenLimit(Stringquestion){// 检查 token 使用情况ChatResponseresponsechatModel.call(prompt);ChatResponseMetadatametadataresponse.getMetadata();Usageusagemetadata.getUsage();if(usage.getTotalTokens()MAX_TOKENS){log.warn(Token 使用量接近上限: {},usage.getTotalTokens());}returnresponse.getResult().getOutput().getText();}9.3 错误处理建议publicStringsafeCall(Promptprompt){try{ChatResponseresponsechatModel.call(prompt);returnresponse.getResult().getOutput().getText();}catch(Exceptione){// 常见异常类型// - NetworkException: 网络连接问题// - RateLimitExceededException: 超出速率限制// - ModelTimeoutException: 模型响应超时// - InvalidRequestException: 请求参数错误log.error(调用 AI 模型失败,e);return抱歉AI 服务暂时不可用请稍后重试。;}}9.4 性能优化建议合理设置maxTokens避免生成过长内容浪费资源使用流式 API提升用户感知速度缓存常用 Prompt减少重复构建对象的开销批量请求对于独立任务考虑并行调用不同模型十、总结Spring AI Chat Model API 通过一套优雅的抽象帮助开发者轻松集成各种 AI 聊天模型。其核心优势在于统一性ChatModel/StreamingChatModel接口为所有模型提供一致的调用方式可移植性通过Prompt、ChatResponse、Generation等标准化组件实现模型间无缝切换灵活性支持ChatOptions的双层配置既可以设置全局默认值也可以按请求精细控制扩展性清晰的接口设计使得添加新的 AI 模型实现变得简单
返回列表