spring ai入门教程二
Spring AI入门教程二Chat Model API详解在上一篇教程中我们了解了 Spring AI 的整体架构、核心概念并快速体验了ChatClientAPI 的便捷性。今天我们将深入底层——Chat Model API。它是 Spring AI 与各种大语言模型LLM交互的核心抽象层为你提供更细粒度的控制从构建多轮对话、配置模型参数到解析结构化输出、处理流式响应。掌握 Chat Model API你将能够灵活驾驭不同的 AI 模型构建生产级的智能应用。一、Chat Model API 概览Spring AI 的 Chat Model API 定义了两个核心接口ChatModel同步和StreamingChatModel异步流式。所有针对具体 AI 模型的实现如 DeepSeek、智谱AI、OpenAI 等都遵循这两个接口因此你可以在不修改业务代码的情况下轻松切换模型提供商。publicinterfaceChatModelextendsModelPrompt,ChatResponse{defaultStringcall(Stringmessage){...}ChatResponsecall(Promptprompt);}publicinterfaceStreamingChatModelextendsStreamingModelPrompt,ChatResponse{defaultFluxStringstream(Stringmessage){...}FluxChatResponsestream(Promptprompt);}call(String message)最简形式直接传入问题字符串返回回答字符串。适用于快速测试或简单场景。call(Prompt prompt)核心方法接收封装好的Prompt对象返回完整的ChatResponse包含元数据、多个生成结果等。流式方法返回响应式Flux适合长文本生成场景提升用户体验。二、ChatModel 的自动配置与注入在编写代码之前有必要先了解 Spring AI 是如何自动配置ChatModel的这样才能理解为什么直接Autowired一个ZhiPuAiChatModel就能使用以及如何根据自己的需求调整配置。2.1 自动配置原理Spring AI 为每个支持的模型提供了独立的*AutoConfiguration类。以智谱AI为例ZhiPuAiChatAutoConfiguration承担了核心初始化工作AutoConfiguration(after{...})ConditionalOnClass(ZhiPuAiApi.class)ConditionalOnProperty(nameSpringAIModelProperties.CHAT_MODEL,havingValueSpringAIModels.ZHIPUAI,matchIfMissingtrue)EnableConfigurationProperties({ZhiPuAiConnectionProperties.class,ZhiPuAiChatProperties.class})publicclassZhiPuAiChatAutoConfiguration{BeanConditionalOnMissingBeanpublicZhiPuAiChatModelzhiPuAiChatModel(...){// 1. 构建 ZhiPuAiApi封装 HTTP 细节// 2. 创建 ZhiPuAiChatModel 实例// 3. 返回}}ConditionalOnClass只有引入了spring-ai-starter-model-zhipuai依赖配置才会生效。ConditionalOnProperty默认启用可通过spring.ai.chat.model控制。EnableConfigurationProperties将配置文件中以spring.ai.zhipuai前缀的属性绑定到ZhiPuAiConnectionProperties和ZhiPuAiChatProperties。ConditionalOnMissingBean如果没有手动定义ZhiPuAiChatModelBean则自动创建。在application.yaml中你只需配置spring:ai:zhipuai:api-key:${ZHIPU_API_KEY}base-url:https://open.bigmodel.cn/api/paas/v4chat:options:model:glm-4-flashtemperature:0.72.2 注入 ChatModel自动配置完成后Spring 容器中就有了ZhiPuAiChatModel的 Bean。你可以直接注入ServicepublicclassAiService{// 按类型注入AutowiredprivateZhiPuAiChatModelchatModel;// 或者注入接口项目中只有一个实现时AutowiredprivateChatModelchatModel;}注意如果你同时配置了多个模型如 DeepSeek 和智谱AI需要使用Qualifier指定具体 Bean 名称。三、核心组件详解要熟练使用 Chat Model API必须理解以下几个核心类3.1Prompt与MessagePrompt是请求的封装内部包含一个ListMessage和可选的ChatOptions。Message接口代表一段对话内容根据角色分为三种实现实现类角色说明SystemMessage系统设定 AI 助手的行为、身份、知识范围UserMessage用户用户的提问或指令AssistantMessage助手AI 模型的回复通常用于多轮对话的上下文SystemMessagesystemnewSystemMessage(你是一位资深Java架构师);UserMessageusernewUserMessage(请介绍Spring Boot和Spring Cloud的区别);PromptpromptnewPrompt(List.of(system,user));3.2ChatOptions– 模型配置控制模型生成行为的关键参数例如temperature、maxTokens、topP等。Spring AI 支持启动时默认配置运行时动态覆盖。启动配置在application.yaml中设置。运行时覆盖在Prompt中传入新的ChatOptions实例优先级更高。ZhiPuAiChatOptionsruntimeOptionsZhiPuAiChatOptions.builder().temperature(0.9).maxTokens(500).build();PromptpromptnewPrompt(userMessage,runtimeOptions);3.3ChatResponse与GenerationChatResponse是模型的返回结果包含ListGeneration模型可能返回多个候选结果通常只有一个。ChatResponseMetadata响应元数据如 token 使用量、模型版本等。每个Generation对象中包裹着AssistantMessage实际回复文本和ChatGenerationMetadata。ChatResponseresponsechatModel.call(prompt);Generationgenerationresponse.getResults().get(0);Stringanswergeneration.getOutput().getText();MapString,Objectusageresponse.getMetadata().getUsage();四、基础用法代码示例以下示例均基于智谱AI的ZhiPuAiChatModel你只需替换为其他模型如 DeepSeek即可复用。4.1 最简单的调用 –call(String)RestControllerpublicclassSimpleChatController{ResourceprivateZhiPuAiChatModelchatModel;GetMapping(/simple)publicStringsimpleChat(RequestParamStringquestion){returnchatModel.call(question);}}4.2 使用Prompt和UserMessageGetMapping(/prompt)publicChatResponsepromptCall(RequestParamStringquestion){UserMessageuserMessagenewUserMessage(question);PromptpromptnewPrompt(userMessage);returnchatModel.call(prompt);}4.3 多轮对话携带系统消息和历史GetMapping(/multi-turn)publicChatResponsemultiTurn(){SystemMessagesystemnewSystemMessage(你是一位专业的Java面试官请用中文回答。);UserMessageusernewUserMessage(什么是JVM);PromptpromptnewPrompt(List.of(system,user));returnchatModel.call(prompt);}4.4 为消息添加元数据可用于链路追踪UserMessageuserMsgnewUserMessage(今天天气怎么样);userMsg.getMetadata().put(userId,12345);userMsg.getMetadata().put(requestId,UUID.randomUUID().toString());PromptpromptnewPrompt(userMsg);ChatResponseresponsechatModel.call(prompt);4.5 解析ChatResponse的完整信息GetMapping(/parse)publicMapString,ObjectparseResponse(RequestParamStringquestion){ChatResponserespchatModel.call(newPrompt(newUserMessage(question)));Generationgenresp.getResults().get(0);returnMap.of(answer,gen.getOutput().getText(),responseMetadata,resp.getMetadata(),generationMetadata,gen.getMetadata());}五、高级功能实战5.1 结构化输出 – 将 AI 回复转为 Java 对象利用BeanOutputConverter你可以在提示词中嵌入 JSON 格式要求并自动将模型输出反序列化为 POJO。定义实体publicrecordActorFilms(Stringactor,ListStringmovies){}调用示例GetMapping(/actor)publicActorFilmsgetActorFilms(){BeanOutputConverterActorFilmsconverternewBeanOutputConverter(ActorFilms.class);StringpromptText 生成演员周星驰的5部代表作。 %s .formatted(converter.getFormat());// 自动生成格式说明PromptpromptnewPrompt(newUserMessage(promptText));StringcontentchatModel.call(prompt).getResults().get(0).getOutput().getText();returnconverter.convert(content);}返回列表时使用ParameterizedTypeReferenceBeanOutputConverterListActorFilmsconverternewBeanOutputConverter(newParameterizedTypeReferenceListActorFilms(){});5.2 动态模型切换在同一ChatModel实例上通过运行时ChatOptions指定不同模型或参数GetMapping(/switch)publicChatResponseswitchModel(RequestParamStringmodelName){UserMessageuserMsgnewUserMessage(介绍一下你自己);ZhiPuAiChatOptionsoptionsZhiPuAiChatOptions.builder().model(modelName)// 例如 glm-4.6v 或 glm-4-flash.temperature(0.8).build();PromptpromptnewPrompt(userMsg,options);returnchatModel.call(prompt);}5.3 复杂的模型参数配置ZhiPuAiChatOptionsoptionsZhiPuAiChatOptions.builder().model(glm-4.6v).temperature(0.95)// 高创造性.maxTokens(800).topP(0.9)// nucleus sampling.stopSequences(List.of(\n\n))// 遇到两个换行停止.build();六、流式响应StreamingChatModel对于长文本生成如文章、代码流式输出能大幅提升用户体验。StreamingChatModel返回响应式Flux与 Spring WebFlux 完美集成。6.1 基础流式字符串GetMapping(value/stream,producesMediaType.TEXT_EVENT_STREAM_VALUE)publicFluxStringstream(RequestParamStringquestion){returnchatModel.stream(question);}6.2 流式返回ChatResponse获取元数据GetMapping(value/stream-response,producesMediaType.APPLICATION_NDJSON_VALUE)publicFluxChatResponsestreamResponse(RequestParamStringquestion){returnchatModel.stream(newPrompt(newUserMessage(question)));}6.3 流式聚合与错误处理GetMapping(/stream-collect)publicStringcollectStream(RequestParamStringquestion){StringBuilderfullnewStringBuilder();chatModel.stream(question).doOnNext(chunk-log.info(收到: {},chunk)).doOnError(e-log.error(流式异常,e)).onErrorResume(e-Flux.just(发生错误请重试)).blockLast();// 阻塞直到完成returnfull.toString();}注意流式方法依赖reactor.core需确保项目中引入了spring-boot-starter-webflux或响应式环境。七、最佳实践与注意事项API Key 安全永远不要将密钥硬编码在代码或配置文件中。使用环境变量或配置中心如 Spring Cloud Config。spring.ai.zhipuai.api-key:${ZHIPU_API_KEY}合理设置temperature0.00.3适合代码生成、事实问答确定性高。0.50.7通用对话平衡创造性与准确性。0.81.0故事创作、头脑风暴更随机。多轮对话的记忆管理你需要自行维护消息列表将每次的UserMessage和AssistantMessage存储并传入下一次Prompt。结构化输出的提示技巧converter.getFormat()会生成类似“你的输出必须是符合以下 JSON schema 的 JSON 对象…”的指令。如果模型不遵守可以在提示词中增加“只输出 JSON不要有其他解释”。流式响应异常处理使用doOnError和onErrorResume避免连接断开时客户端无响应。性能考虑同步调用会阻塞线程在 WebFlux 环境中建议优先使用流式或异步方式。对于高并发场景考虑线程池配置或使用响应式WebClient调用模型 API。

相关新闻