news 2026/7/5 2:56:59

Solon AI 4.0的ChatModel:简洁API封装样板代码,多方式构建AI功能!

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Solon AI 4.0的ChatModel:简洁API封装样板代码,多方式构建AI功能!

Java应用集成大语言模型的新方案

如果你尝试过在Java应用中集成大语言模型(LLM),大概率写过不少样板代码,像HTTP客户端、JSON解析、流式处理、会话管理等。而Solon AI 4.0的 `ChatModel` 用一套简洁的Builder API把这些都封装好了。本文将通过真实的代码示例,带你一步步用 `ChatModel` 构建AI功能,从简单的单次调用,到带记忆的流式聊天机器人。

什么是ChatModel?

`ChatModel` 是Solon AI生态中的统一LLM客户端。你不再需要为不同的模型提供商写不同的HTTP调用,而是通过一套统一的API完成多种操作,包括同步调用(一次请求,完整返回)、流式调用(基于Project Reactor的响应式流 `Flux`)、工具/函数调用(让LLM调用你的Java方法)、聊天会话(自动维护对话记忆)、多模态消息(文本、图片、音频)、方言适配(支持OpenAI、Ollama、Anthropic、Gemini、DashScope等多种服务商)。最核心的是它使用了 **方言模式(Dialect Pattern)**,你只需要指向任意兼容的LLM端点,它会自动适配协议。

环境配置

在 `pom.xml` 中添加依赖(Solon不需要父POM,独立工作):

<dependency> <groupId>org.noear</groupId> <artifactId>solon-ai</artifactId> <version>${solon.version}</version> </dependency>

这会引入所有内置的方言适配器(OpenAI、Ollama、Gemini、Anthropic、DashScope)。

配置方式

通过YAML配置(推荐)
solon.ai.chat: demo: apiUrl: "http://127.0.0.1:11434/api/chat" _# 完整URL,非baseUrl_ standard: "ollama" _# 接口规范(方言标识)_ model: "llama3.2" _# 模型名称_ headers: x-demo: "demo1"

然后通过 `@Bean` 注入一个可以直接使用的 `ChatModel`:

import org.noear.solon.ai.chat.ChatConfig; import org.noear.solon.ai.chat.ChatModel; import org.noear.solon.annotation.Bean; import org.noear.solon.annotation.Configuration; import org.noear.solon.annotation.Inject; @Configuration public class AiConfig { @Bean public ChatModel chatModel(@Inject("${solon.ai.chat.demo}") ChatModel model) { return model; } }
编程式Builder
@Bean public ChatModel chatModel() { return ChatModel.of("http://127.0.0.1:11434/api/chat") .standard("ollama") _// 或 .provider( "ollama")_ .model("llama3.2") .timeout(Duration.ofSeconds(60)) .build(); }
支持的模型提供商

`standard`(或 `provider`)字段选择方言:

方言标识apiUrl 示例模型
`openai`(默认)`https://api.openai.com/v1/chat/completions`GPT、DeepSeek、Qwen、GLM、Kimi等
`ollama``http://127.0.0.1:11434/api/chat`本地Ollama模型
`anthropic``https://api.anthropic.com/v1/messages`Claude
`gemini``https://generativelanguage.googleapis.com/...`Gemini
`dashscope`阿里云DashScope端点Qwen(DashScope原生)

同步调用(最简单的方式)

最基本的用法是发送提示词,获取完整响应:

import org.noear.solon.ai.chat.ChatModel; import org.noear.solon.ai.chat.ChatResponse; import org.noear.solon.annotation.Inject; import org.noear.solon.annotation.Component; @Component public class ChatService { @Inject ChatModel chatModel; public String ask(String question) throws IOException { ChatResponse resp = chatModel.prompt(question).call(); return resp.getMessage().getContent(); } }

仅三行业务代码,搞定。

流式调用(实时响应)

对于聊天机器人和助手类应用,流式响应是刚需。`ChatModel` 返回Reactor的 `Flux`:

import reactor.core.publisher.Flux; public Flux<String> askStream(String question) throws IOException { return chatModel.prompt(question) .stream() .filter(resp -> resp.hasContent()) _// 跳过空块_ .map(resp -> resp.getContent()); }

如果你使用Solon Web Reactive,可以直接把 `Flux` 返回给SSE端点:

import org.noear.solon.web.sse.SseEvent; import org.noear.solon.annotation.Mapping; import reactor.core.publisher.Flux; @Mapping("/chat/stream") public Flux<SseEvent> chatStream(String prompt) throws IOException { return chatModel.prompt(prompt) .stream() .filter(resp -> resp.hasContent()) .map(resp -> new SseEvent().data(resp.getContent())); }

流式协议根据提供商不同,使用标准SSE或 `x-ndjson`。

对话记忆:ChatSession

基本用法
import org.noear.solon.ai.chat.ChatSession; import org.noear.solon.ai.chat.session.InMemoryChatSession; ChatSession session = InMemoryChatSession.builder() .sessionId("user-123") .maxMessages(10) _// 保留最近10轮_ .build(); _// 第一轮_ ChatResponse resp1 = chatModel.prompt("你好!") .session(session) .call(); _// 第二轮 ----模型记得刚才的对话_ ChatResponse resp2 = chatModel.prompt("我刚才说了什么?") .session(session) .call();
Web应用中的用户级会话
import org.noear.solon.annotation.Controller; import org.noear.solon.web.sse.SseEvent; import reactor.core.publisher.Flux; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @Controller public class ChatController { @Inject ChatModel chatModel; final Map<String, ChatSession> sessionMap = new ConcurrentHashMap<>(); @Mapping("/chat") public Flux<SseEvent> chat(String sessionId, String prompt) throws IOException { ChatSession session = sessionMap.computeIfAbsent(sessionId, k -> InMemoryChatSession.builder().sessionId(k).build()); return chatModel.prompt(prompt) .session(session) .options(o -> o.systemPrompt("你是一个友好、乐于助人的助手。")) .stream() .filter(ChatResponse::hasContent) .map(resp -> new SseEvent().data(resp.getContent())); } }
内置会话实现
实现类存储方式适用场景
`InMemoryChatSession`本地Map开发、单节点
`FileChatSession`文件系统CLI工具、桌面应用
`RedisChatSession`Redis生产环境、分布式部署

调优: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.0)
`max_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可自动生成systemPrompt)
`instruction(val)`Agent指令(role + instruction可自动生成systemPrompt)
`systemPrompt(val)`本次请求的系统提示词(完全定制)

多消息Prompt

有时候你需要的不只是一条消息。可以用 `Prompt` 和 `ChatMessage` 构建更复杂的上下文:

import org.noear.solon.ai.chat.Prompt; import org.noear.solon.ai.chat.message.ChatMessage; Prompt prompt = Prompt.of( ChatMessage.ofUser("Hello, how are you?"), ChatMessage.ofAssistant("Bonjour, comment allez-vous?"), ChatMessage.ofUser("What is your name?") ); ChatResponse resp = chatModel.prompt(prompt).options(o -> o.systemPrompt("你是一名中英翻译专家。")).call();

完整实战:知识感知聊天机器人

下面是一个轻量级的RAG模式示例,用 `ChatMessage.ofUserAugment()` 把上下文注入到Prompt中:

import org.noear.solon.ai.chat.ChatModel; import org.noear.solon.ai.chat.ChatResponse; import org.noear.solon.ai.chat.message.ChatMessage; import org.noear.solon.annotation.Component; import org.noear.solon.annotation.Inject; @Component public class KnowledgeChatbot { @Inject ChatModel chatModel; public String answer(String question, String referenceContext) throws Exception { _// 将参考上下文与用户问题合并_ ChatMessage augmented = ChatMessage.ofUserAugment(question, referenceContext); ChatResponse resp = chatModel.prompt(augmented) .options(o -> o .temperature(0.3) .systemPrompt("你是一个知识渊博的助手。请基于提供的参考资料回答。")) .call(); return resp.getMessage().getContent(); } }

这种模式,用上下文增强用户输入,再调用模型,正是Solon AI中RAG(检索增强生成)的基础。

下一步

`ChatModel` 只是入口点。Solon AI还提供:

  • 工具调用 -- 用 `@ToolMapping` 定义LLM可调用的Java方法
  • Talent系统 -- 可复用的能力模块
  • Agent -- `ReActAgent` 和 `TeamAgent` 实现多步推理
  • RAG流水线 -- 完整的文档加载、切分、嵌入、检索流程
  • MCP协议 -- 连接MCP服务器使用外部工具

你有没有在Java中集成过LLM?最大的痛点是什么?欢迎在评论区分享,可能会在后续文章中专门讨论。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/5 2:56:41

Chrome DevTools MCP:让 AI 编程助手直接操控浏览器

文章目录Chrome DevTools MCP&#xff1a;让 AI 编程助手直接操控浏览器1、 它能做什么2、 怎么用3、 工具数量4、 连接已有浏览器5、 配置项6、 适合谁用Chrome DevTools MCP&#xff1a;让 AI 编程助手直接操控浏览器 Chrome DevTools MCP 在 GitHub 上拿到了 4.4 万 Star。…

作者头像 李华
网站建设 2026/7/5 2:54:15

大疆光学专利Zemax复现

大疆七片式光学系统Zemax仿真复现 关键词&#xff1a;光学设计&#xff1b;七片透镜&#xff1b;Zemax仿真&#xff1b;像差分析&#xff1b;大疆专利 一、文章简要介绍 本文基于大疆授权专利CN 214669820 U&#xff08;2021年11月9日公告&#xff09;&#xff0c;采用Zemax Op…

作者头像 李华
网站建设 2026/7/5 2:53:04

NSK MCL06全系行程极限选型指南

根据NSK官方《精机综合样本》的定位承载装置选型体系&#xff0c;太震撼了&#xff01;您本次查询的 MCL06050H10K 标志着我们正式登顶了 NSK 耐久轻量型&#xff08;MCL06&#xff09;全系的“绝对物理极限”——全系最大有效行程 500mm&#xff01; 更令人不可思议的是&#…

作者头像 李华
网站建设 2026/7/5 2:52:20

深度体验CubeSandbox沙箱,完成部署实战

实战体验&#xff1a;我发现创建分身以后&#xff0c;每一个龙虾的gateway网关的界面都是一样的&#xff0c;龙虾也是一样的很难分清不同的龙虾&#xff0c;目前只能通过每一个网关的命名不同来区分。实战建议&#xff1a;希望可以作出解决方案。我的推荐的解决方案是学习happy…

作者头像 李华