如果你尝试过在 Java 应用中集成大语言模型LLM大概率写过不少样板代码HTTP 客户端、JSON 解析、流式处理、会话管理……Solon AI 4.0 的ChatModel用一套简洁的 Builder API 把这些都封装好了。本文将通过真实的代码示例带你一步步用ChatModel构建 AI 功能——从简单的单次调用到带记忆的流式聊天机器人。1. 什么是 ChatModelChatModel是 Solon AI 生态中的统一 LLM 客户端。你不再需要为不同的模型提供商写不同的 HTTP 调用而是通过一套统一的 API 完成同步调用— 一次请求完整返回流式调用— 基于 Project Reactor 的响应式流FluxChatResponse工具/函数调用— 让 LLM 调用你的 Java 方法聊天会话— 自动维护对话记忆多模态消息— 文本、图片、音频方言适配— 支持 OpenAI、Ollama、Anthropic、Gemini、DashScope 等多种服务商最核心的是它使用了方言模式Dialect Pattern——你只需要指向任意兼容的 LLM 端点它会自动适配协议。2. 环境配置在pom.xml中添加依赖Solon 不需要父 POM独立工作dependencygroupIdorg.noear/groupIdartifactIdsolon-ai/artifactIdversion${solon.version}/version/dependency这会引入所有内置的方言适配器OpenAI、Ollama、Gemini、Anthropic、DashScope。3. 配置方式3.1 通过 YAML 配置推荐solon.ai.chat:demo:apiUrl:http://127.0.0.1:11434/api/chat# 完整 URL非 baseUrlstandard:ollama# 接口规范方言标识model:llama3.2# 模型名称headers:x-demo:demo1然后通过Bean注入一个可以直接使用的ChatModelimportorg.noear.solon.ai.chat.ChatConfig;importorg.noear.solon.ai.chat.ChatModel;importorg.noear.solon.annotation.Bean;importorg.noear.solon.annotation.Configuration;importorg.noear.solon.annotation.Inject;ConfigurationpublicclassAiConfig{BeanpublicChatModelchatModel(Inject(${solon.ai.chat.demo})ChatModelmodel){returnmodel;}}3.2 编程式 BuilderBeanpublicChatModelchatModel(){returnChatModel.of(http://127.0.0.1:11434/api/chat).standard(ollama)// 或 .provider(ollama).model(llama3.2).timeout(Duration.ofSeconds(60)).build();}3.3 支持的模型提供商standard或provider字段选择方言方言标识apiUrl 示例模型openai默认https://api.openai.com/v1/chat/completionsGPT、DeepSeek、Qwen、GLM、Kimi 等ollamahttp://127.0.0.1:11434/api/chat本地 Ollama 模型anthropichttps://api.anthropic.com/v1/messagesClaudegeminihttps://generativelanguage.googleapis.com/...Geminidashscope阿里云 DashScope 端点QwenDashScope 原生4. 同步调用最简单的方式最基本的用法——发送提示词获取完整响应importorg.noear.solon.ai.chat.ChatModel;importorg.noear.solon.ai.chat.ChatResponse;importorg.noear.solon.annotation.Inject;importorg.noear.solon.annotation.Component;ComponentpublicclassChatService{InjectChatModelchatModel;publicStringask(Stringquestion)throwsIOException{ChatResponserespchatModel.prompt(question).call();returnresp.getMessage().getContent();}}仅三行业务代码搞定。5. 流式调用实时响应对于聊天机器人和助手类应用流式响应是刚需。ChatModel返回 Reactor 的FluxChatResponseimportreactor.core.publisher.Flux;publicFluxStringaskStream(Stringquestion)throwsIOException{returnchatModel.prompt(question).stream().filter(resp-resp.hasContent())// 跳过空块.map(resp-resp.getContent());}如果你使用 Solon Web Reactive可以直接把Flux返回给 SSE 端点importorg.noear.solon.web.sse.SseEvent;importorg.noear.solon.annotation.Mapping;importreactor.core.publisher.Flux;Mapping(/chat/stream)publicFluxSseEventchatStream(Stringprompt)throwsIOException{returnchatModel.prompt(prompt).stream().filter(resp-resp.hasContent()).map(resp-newSseEvent().data(resp.getContent()));}流式协议根据提供商不同使用标准 SSE 或x-ndjson。6. 对话记忆ChatSessionLLM 本身是无状态的每次请求都需要传入历史上下文。ChatSession自动帮你完成这件事。6.1 基本用法importorg.noear.solon.ai.chat.ChatSession;importorg.noear.solon.ai.chat.session.InMemoryChatSession;ChatSessionsessionInMemoryChatSession.builder().sessionId(user-123).maxMessages(10)// 保留最近 10 轮.build();// 第一轮ChatResponseresp1chatModel.prompt(你好).session(session).call();// 第二轮——模型记得刚才的对话ChatResponseresp2chatModel.prompt(我刚才说了什么).session(session).call();6.2 Web 应用中的用户级会话在实际的 Web 应用中每个用户需要一个独立的会话importorg.noear.solon.annotation.Controller;importorg.noear.solon.web.sse.SseEvent;importreactor.core.publisher.Flux;importjava.util.Map;importjava.util.concurrent.ConcurrentHashMap;ControllerpublicclassChatController{InjectChatModelchatModel;finalMapString,ChatSessionsessionMapnewConcurrentHashMap();Mapping(/chat)publicFluxSseEventchat(StringsessionId,Stringprompt)throwsIOException{ChatSessionsessionsessionMap.computeIfAbsent(sessionId,k-InMemoryChatSession.builder().sessionId(k).build());returnchatModel.prompt(prompt).session(session).options(o-o.systemPrompt(你是一个友好、乐于助人的助手。)).stream().filter(ChatResponse::hasContent).map(resp-newSseEvent().data(resp.getContent()));}}6.3 内置会话实现实现类存储方式适用场景InMemoryChatSession本地 Map开发、单节点FileChatSession文件系统CLI 工具、桌面应用RedisChatSessionRedis生产环境、分布式部署7. 调优ChatOptions通过ChatOptions可以在每次请求中控制模型行为chatModel.prompt(写一首关于 Java 的诗).options(o-o.temperature(0.8).max_tokens(500).top_p(0.9).systemPrompt(你是一位富有创造力的诗人。)).call();部分常用参数方法说明temperature(val)采样温度0.0–2.0max_tokens(val)最大输出 Token 数top_p(val)核采样参数top_k(val)Top-K 采样frequency_penalty(val)降低重复presence_penalty(val)鼓励新话题tool_choice(val)强制工具调用none、auto、required或工具名role(val)Agent 角色role instruction 可自动生成 systemPromptinstruction(val)Agent 指令role instruction 可自动生成 systemPromptsystemPrompt(val)本次请求的系统提示词完全定制8. 多消息 Prompt有时候你需要的不只是一条消息。可以用Prompt和ChatMessage构建更复杂的上下文importorg.noear.solon.ai.chat.Prompt;importorg.noear.solon.ai.chat.message.ChatMessage;PromptpromptPrompt.of(ChatMessage.ofUser(Hello, how are you?),ChatMessage.ofAssistant(Bonjour, comment allez-vous?),ChatMessage.ofUser(What is your name?));ChatResponserespchatModel.prompt(prompt).options(o-o.systemPrompt(你是一名中英翻译专家。)).call();9. 完整实战知识感知聊天机器人下面是一个轻量级的 RAG 模式示例——用ChatMessage.ofUserAugment()把上下文注入到 Prompt 中importorg.noear.solon.ai.chat.ChatModel;importorg.noear.solon.ai.chat.ChatResponse;importorg.noear.solon.ai.chat.message.ChatMessage;importorg.noear.solon.annotation.Component;importorg.noear.solon.annotation.Inject;ComponentpublicclassKnowledgeChatbot{InjectChatModelchatModel;publicStringanswer(Stringquestion,StringreferenceContext)throwsException{// 将参考上下文与用户问题合并ChatMessageaugmentedChatMessage.ofUserAugment(question,referenceContext);ChatResponserespchatModel.prompt(augmented).options(o-o.temperature(0.3).systemPrompt(你是一个知识渊博的助手。请基于提供的参考资料回答。)).call();returnresp.getMessage().getContent();}}这种模式——用上下文增强用户输入再调用模型——正是 Solon AI 中 RAG检索增强生成的基础。10. 下一步ChatModel只是入口点。Solon AI 还提供工具调用— 用ToolMapping定义 LLM 可调用的 Java 方法Talent 系统— 可复用的能力模块Agent—ReActAgent和TeamAgent实现多步推理RAG 流水线— 完整的文档加载、切分、嵌入、检索流程MCP 协议— 连接 MCP 服务器使用外部工具完整文档参见官方指南 https://solon.noear.org/article/918模型构建 https://solon.noear.org/article/920API 参考你有没有在 Java 中集成过 LLM最大的痛点是什么欢迎在评论区分享可能会在后续文章中专门讨论。
用 ChatModel 构建 LLM 驱动的 Java 应用
发布时间:2026/7/5 6:15:30
如果你尝试过在 Java 应用中集成大语言模型LLM大概率写过不少样板代码HTTP 客户端、JSON 解析、流式处理、会话管理……Solon AI 4.0 的ChatModel用一套简洁的 Builder API 把这些都封装好了。本文将通过真实的代码示例带你一步步用ChatModel构建 AI 功能——从简单的单次调用到带记忆的流式聊天机器人。1. 什么是 ChatModelChatModel是 Solon AI 生态中的统一 LLM 客户端。你不再需要为不同的模型提供商写不同的 HTTP 调用而是通过一套统一的 API 完成同步调用— 一次请求完整返回流式调用— 基于 Project Reactor 的响应式流FluxChatResponse工具/函数调用— 让 LLM 调用你的 Java 方法聊天会话— 自动维护对话记忆多模态消息— 文本、图片、音频方言适配— 支持 OpenAI、Ollama、Anthropic、Gemini、DashScope 等多种服务商最核心的是它使用了方言模式Dialect Pattern——你只需要指向任意兼容的 LLM 端点它会自动适配协议。2. 环境配置在pom.xml中添加依赖Solon 不需要父 POM独立工作dependencygroupIdorg.noear/groupIdartifactIdsolon-ai/artifactIdversion${solon.version}/version/dependency这会引入所有内置的方言适配器OpenAI、Ollama、Gemini、Anthropic、DashScope。3. 配置方式3.1 通过 YAML 配置推荐solon.ai.chat:demo:apiUrl:http://127.0.0.1:11434/api/chat# 完整 URL非 baseUrlstandard:ollama# 接口规范方言标识model:llama3.2# 模型名称headers:x-demo:demo1然后通过Bean注入一个可以直接使用的ChatModelimportorg.noear.solon.ai.chat.ChatConfig;importorg.noear.solon.ai.chat.ChatModel;importorg.noear.solon.annotation.Bean;importorg.noear.solon.annotation.Configuration;importorg.noear.solon.annotation.Inject;ConfigurationpublicclassAiConfig{BeanpublicChatModelchatModel(Inject(${solon.ai.chat.demo})ChatModelmodel){returnmodel;}}3.2 编程式 BuilderBeanpublicChatModelchatModel(){returnChatModel.of(http://127.0.0.1:11434/api/chat).standard(ollama)// 或 .provider(ollama).model(llama3.2).timeout(Duration.ofSeconds(60)).build();}3.3 支持的模型提供商standard或provider字段选择方言方言标识apiUrl 示例模型openai默认https://api.openai.com/v1/chat/completionsGPT、DeepSeek、Qwen、GLM、Kimi 等ollamahttp://127.0.0.1:11434/api/chat本地 Ollama 模型anthropichttps://api.anthropic.com/v1/messagesClaudegeminihttps://generativelanguage.googleapis.com/...Geminidashscope阿里云 DashScope 端点QwenDashScope 原生4. 同步调用最简单的方式最基本的用法——发送提示词获取完整响应importorg.noear.solon.ai.chat.ChatModel;importorg.noear.solon.ai.chat.ChatResponse;importorg.noear.solon.annotation.Inject;importorg.noear.solon.annotation.Component;ComponentpublicclassChatService{InjectChatModelchatModel;publicStringask(Stringquestion)throwsIOException{ChatResponserespchatModel.prompt(question).call();returnresp.getMessage().getContent();}}仅三行业务代码搞定。5. 流式调用实时响应对于聊天机器人和助手类应用流式响应是刚需。ChatModel返回 Reactor 的FluxChatResponseimportreactor.core.publisher.Flux;publicFluxStringaskStream(Stringquestion)throwsIOException{returnchatModel.prompt(question).stream().filter(resp-resp.hasContent())// 跳过空块.map(resp-resp.getContent());}如果你使用 Solon Web Reactive可以直接把Flux返回给 SSE 端点importorg.noear.solon.web.sse.SseEvent;importorg.noear.solon.annotation.Mapping;importreactor.core.publisher.Flux;Mapping(/chat/stream)publicFluxSseEventchatStream(Stringprompt)throwsIOException{returnchatModel.prompt(prompt).stream().filter(resp-resp.hasContent()).map(resp-newSseEvent().data(resp.getContent()));}流式协议根据提供商不同使用标准 SSE 或x-ndjson。6. 对话记忆ChatSessionLLM 本身是无状态的每次请求都需要传入历史上下文。ChatSession自动帮你完成这件事。6.1 基本用法importorg.noear.solon.ai.chat.ChatSession;importorg.noear.solon.ai.chat.session.InMemoryChatSession;ChatSessionsessionInMemoryChatSession.builder().sessionId(user-123).maxMessages(10)// 保留最近 10 轮.build();// 第一轮ChatResponseresp1chatModel.prompt(你好).session(session).call();// 第二轮——模型记得刚才的对话ChatResponseresp2chatModel.prompt(我刚才说了什么).session(session).call();6.2 Web 应用中的用户级会话在实际的 Web 应用中每个用户需要一个独立的会话importorg.noear.solon.annotation.Controller;importorg.noear.solon.web.sse.SseEvent;importreactor.core.publisher.Flux;importjava.util.Map;importjava.util.concurrent.ConcurrentHashMap;ControllerpublicclassChatController{InjectChatModelchatModel;finalMapString,ChatSessionsessionMapnewConcurrentHashMap();Mapping(/chat)publicFluxSseEventchat(StringsessionId,Stringprompt)throwsIOException{ChatSessionsessionsessionMap.computeIfAbsent(sessionId,k-InMemoryChatSession.builder().sessionId(k).build());returnchatModel.prompt(prompt).session(session).options(o-o.systemPrompt(你是一个友好、乐于助人的助手。)).stream().filter(ChatResponse::hasContent).map(resp-newSseEvent().data(resp.getContent()));}}6.3 内置会话实现实现类存储方式适用场景InMemoryChatSession本地 Map开发、单节点FileChatSession文件系统CLI 工具、桌面应用RedisChatSessionRedis生产环境、分布式部署7. 调优ChatOptions通过ChatOptions可以在每次请求中控制模型行为chatModel.prompt(写一首关于 Java 的诗).options(o-o.temperature(0.8).max_tokens(500).top_p(0.9).systemPrompt(你是一位富有创造力的诗人。)).call();部分常用参数方法说明temperature(val)采样温度0.0–2.0max_tokens(val)最大输出 Token 数top_p(val)核采样参数top_k(val)Top-K 采样frequency_penalty(val)降低重复presence_penalty(val)鼓励新话题tool_choice(val)强制工具调用none、auto、required或工具名role(val)Agent 角色role instruction 可自动生成 systemPromptinstruction(val)Agent 指令role instruction 可自动生成 systemPromptsystemPrompt(val)本次请求的系统提示词完全定制8. 多消息 Prompt有时候你需要的不只是一条消息。可以用Prompt和ChatMessage构建更复杂的上下文importorg.noear.solon.ai.chat.Prompt;importorg.noear.solon.ai.chat.message.ChatMessage;PromptpromptPrompt.of(ChatMessage.ofUser(Hello, how are you?),ChatMessage.ofAssistant(Bonjour, comment allez-vous?),ChatMessage.ofUser(What is your name?));ChatResponserespchatModel.prompt(prompt).options(o-o.systemPrompt(你是一名中英翻译专家。)).call();9. 完整实战知识感知聊天机器人下面是一个轻量级的 RAG 模式示例——用ChatMessage.ofUserAugment()把上下文注入到 Prompt 中importorg.noear.solon.ai.chat.ChatModel;importorg.noear.solon.ai.chat.ChatResponse;importorg.noear.solon.ai.chat.message.ChatMessage;importorg.noear.solon.annotation.Component;importorg.noear.solon.annotation.Inject;ComponentpublicclassKnowledgeChatbot{InjectChatModelchatModel;publicStringanswer(Stringquestion,StringreferenceContext)throwsException{// 将参考上下文与用户问题合并ChatMessageaugmentedChatMessage.ofUserAugment(question,referenceContext);ChatResponserespchatModel.prompt(augmented).options(o-o.temperature(0.3).systemPrompt(你是一个知识渊博的助手。请基于提供的参考资料回答。)).call();returnresp.getMessage().getContent();}}这种模式——用上下文增强用户输入再调用模型——正是 Solon AI 中 RAG检索增强生成的基础。10. 下一步ChatModel只是入口点。Solon AI 还提供工具调用— 用ToolMapping定义 LLM 可调用的 Java 方法Talent 系统— 可复用的能力模块Agent—ReActAgent和TeamAgent实现多步推理RAG 流水线— 完整的文档加载、切分、嵌入、检索流程MCP 协议— 连接 MCP 服务器使用外部工具完整文档参见官方指南 https://solon.noear.org/article/918模型构建 https://solon.noear.org/article/920API 参考你有没有在 Java 中集成过 LLM最大的痛点是什么欢迎在评论区分享可能会在后续文章中专门讨论。