Qwen3 与 Solon AI、Ollama 的尝鲜实践

笔记哥 / 04-29 / 44点赞 / 0评论 / 479阅读
qwen3 惊喜发布了,帅!我们用 ollama 和 solon ai (java) 也来尝个鲜。 ### 1、先用 ollama 拉取模型 听说,在个人电脑上用 4b 的参数,效果就很好了。 ```csharp ollama run qwen3:4b ``` ### 2、试试:Hello qwen3 用 solon-initializr ( https://solon.noear.org/start/ ),生成一个 solon-ai 模板项目。之后: - 在应用属性里添加配置(app.yml) ```yaml solon.ai.chat: qwen3: apiUrl: "http://127.0.0.1:11434/api/chat" # 使用完整地址(而不是 api_base) provider: "ollama" # ollama 是有自己的专有接口格式,通过配置 provider 可识别方言 model: "qwen3:4b" ``` - 用配置器类构建通用聊天模型 ```java @Configuration public class DemoConfig { @Bean public ChatModel chatModel(@Inject("${solon.ai.chat.qwen3}") ChatConfig config) { return ChatModel.of(config).build(); } } ``` - 添加测试用的控制器 ```java @Controller public class DemoController { @Inject ChatModel chatModel; @Mapping("hello") public String hello(String message) throws IOException { return chatModel.prompt(message).call().getMessage().getContent(); } } ``` - 测试一下 启动项目。打开浏览器地址:`http://localhost:8080/hello?message=hello`。效果良好: ![](https://cdn.res.knowhub.vip/c/2505/06/9ba9e3f3.png?Gz8AAGRwXmyTWpMPhkoBeLnv%2fTIQ3tHOH6wt2hNsZ4Z1ZhgiS0xwkohDLKbkvCKYUkSdU8R7D%2faVAQ%3d%3d) ### 3、尝试把输出改成 sse,方便打字效果的聊天窗口开发 ```java @Controller public class DemoController { @Inject ChatModel chatModel; @Produces(MimeType.TEXT_EVENT_STREAM_UTF8_VALUE) //这个很重要,申明用 sse 格式渲染 @Mapping("hello") public Flux hello(String message) throws IOException { return Flux.from(chatModel.prompt(message).stream()) .filter(resp -> resp.hasChoices()) .map(resp -> resp.getMessage().getContent()); } } ``` - 测试一下 启动项目。再次打开浏览器地址:`http://localhost:8080/hello?message=hello`。效果良好: ![](https://cdn.res.knowhub.vip/c/2505/06/3c3a64e6.png?Gz8AAMTsdNwSIXXSbftzaAc4NTRUCsCfc9Z3M5%2bC%2ftOYBZvmbvz2xhHBSfImmoIiZdRcLxigFp1VoTUa) ### 4、现在开始 RAG,以 “联网搜索” 作为知识库 这里把“联网搜索”,做为一个知识库使用(内部是动态搜索的)。用它作为 RAG 的外部检索支持。 - 应用属性加一块配置 ```yaml solon.ai.chat: qwen3: apiUrl: "http://127.0.0.1:11434/api/chat" # 使用完整地址(而不是 api_base) provider: "ollama" # ollama 是有自己的专有接口格式,通过配置 provider 可识别方言 model: "qwen3:4b" solon.ai.repo: websearch: apiUrl: "https://api.bochaai.com/v1/web-search" # 使用完整地址(而不是 api_base) apiKey: "sk-demo..." ``` - 配置器类也调整下 ```java @Configuration public class DemoConfig { @Bean public ChatModel chatModel(@Inject("${solon.ai.chat.qwen3}") ChatConfig config) { return ChatModel.of(config).build(); } @Bean public Repository repository(@Inject("${solon.ai.repo.websearch}") AiConfig config) { return new WebSearchRepository(null, config); } } ``` - 再改改控制器(输出重新写回简单的方式,不然不好截图) ```java @Controller public class DemoController { @Inject ChatModel chatModel; @Inject Repository repository; @Mapping("hello") public String hello(String message) throws IOException { //检索 List context = repository.search(new QueryCondition(message).limit(4)); //消息增强 ChatMessage chatMessage = UserMessage.augment(message, context); //提交大模型并简单返回(不然,截图不好截) return chatModel.prompt(chatMessage).call().getMessage().getContent(); } } ``` - 测试一下 启动项目。打开浏览器地址:`http://localhost:8080/hello?message=solon%20%E6%98%AF%E8%B0%81%E5%BC%80%E5%8F%91%E7%9A%84%EF%BC%9F`。效果良好: ![](https://cdn.res.knowhub.vip/c/2505/06/fdf6d7df.png?Gz8AAERhc7Fh1poNuEqoFID3%2b96vQOmNuPxk3RBPsp2NDkujBSU7QGftlEKtsUojE0MUWhkoTva1AQ%3d%3d) ### 5、再试个 Tool Call(即 Function Call) 修改下刚才的配置器,加个模型的默认工具。 ```java @Configuration public class DemoConfig { @Bean public ChatModel chatModel(@Inject("${solon.ai.chat.qwen3}") ChatConfig config) { return ChatModel.of(config) .defaultToolsAdd(new Tools()) .build(); } public static class Tools { @ToolMapping(description = "获取指定城市的天气情况") public String get_weather(@ToolParam(description = "根据用户提到的地点推测城市") String location) { return "晴,24度"; } } } ``` - 测试一下 启动项目。再次打开浏览器地址:`http://localhost:8080/hello?message=杭州今天的天气如何?`。效果良好: ![](https://cdn.res.knowhub.vip/c/2505/06/1475ab91.png?Gz8AAGRwXmyTWpMPhkoBeLnv%2fTIQ3tHOH6wt2hNsZ4Z1ZiiTZVgTFKRgjCNvOU3ep8gJU9imAPaVAQ%3d%3d)