欢迎回来
登录你的知识库账户
忘记密码?
还没有账户?立即注册
创建账户
注册你的专属知识库
已有账户?去登录
找回密码
输入注册邮箱获取验证码
返回登录
请输入图片中的验证码以继续注册
加载中...
取消
新建收藏
手动添加你喜欢的内容
取消
编辑头像与昵称
上传新头像或修改你的显示昵称
支持 JPG/PNG,最大 2MB
取消

问题反馈

notebasewww.notebase.cn
控制台
内容库
动态
管理
账户
U
用户
--
在线
v0.8.7 · 知识库
笔记
KnowledgeBase
网络无边,知识有迹。
0笔记
0工具
30推荐

分类导航

按主题直达

编辑精选

站内用户贡献 · 真实笔记

最新收录

每日更新
继续浏览全部内容 →
>
笔记
0
加载中...
工具
0
此页用于记录用户反馈问题后的每一次改进
笔记用法

“写笔记”支持四种格式——Word 文档、Excel 表格、Markdown、纯文本,起稿或二次编辑时都能随时切换,同一篇笔记想用哪种形态来记,都由你说了算。

md、txt、csv、json 这类纯文本则原样载入,不做多余加工。拿一张现成的表倒进来、改几笔、再导出去,等于白用一台免费的格式转换器。

要带走就在右上角点“下载”,可导出 PDF、Word、Markdown、Excel、TXT 等格式;列表卡片“⋯”菜单里,也有同样的下载入口。

工具用法

在“工具”页点“+ 上传工具”即可发布:填好名称与链接,再用 Markdown 把使用方法写清楚——能解决什么问题、怎么装、怎么用,比堆介绍实在。

要分发安装包就一并上传压缩包(ZIP、RAR、7Z、TAR.GZ,最大 35MB),别人在详情页一键下载;只放链接不带附件也可以。

工具按大家的收藏热度排序,好用的自然会被顶上来。发布后可在详情页或卡片菜单里编辑、下架。

隐藏笔记

写笔记时勾上“隐藏”,这篇就只存在于你自己的账号里:不进列表、不进搜索、不上首页精选,也不会出现在任何公开的页面,链接发给别人同样打不开。

适合放密码、草稿、日记这类只给自己看的内容;想公开,去“发布”打开它,把“隐藏”的勾去掉再保存,之后编辑会默认保持原状态,不会悄悄变回公开。

数据安全

你的内容会同时保存在多个副本上,系统定期做备份与完整性校验,再配合异地容灾机制:就算某台机器出问题,数据也不会丢,可以长期放心存放;特别重要的资料,仍建议你另外再留一份备份。

技术

全站跑在容器化、模块化的现代架构上,更新、部署、回滚都很快,扩展性和稳定性都按长期运营的标准来设计(Built for reliability, designed to scale)。

理念

这个网站最早只是一个人的笔记仓库,后来慢慢长成现在的知识中枢。设计上很克制——没有广告、没有追踪、没有推荐算法,只是干干净净地存放一些东西;既然做好了,就公开出来,万一有人用得上呢。

原则

不做大而全,不做平台梦,保持简单、保持克制、保持好奇。所有内容都由用户贡献、由用户维护:不会突然冒出付费墙,不会在角落塞广告位,也不会把你的数据卖给第三方。

更多

产品会持续迭代,站内日志页记录着每一次改动,改了什么都有迹可循;想了解这个站是怎么一步步走到今天的,翻翻日志就能看到来龙去脉。

举报

如果在这里看到涉嫌违规的内容,点对应卡片右侧的“举报”按钮就能提交,我们会尽快核实处理;也谢谢你花一点时间,一起把这里维护干净。

趋势
// 点击导航加载发现
归档
// 归档为空
最近浏览
// 暂无浏览记录
发布
// 加载中...
用户发布
// 加载中...
用户管理
// 加载中...
访问统计
// 加载中...
内容审核
// 加载中...
个人信息
// 加载中...
返回首页

用 ChatModel 构建 LLM 驱动的 Java 应用

2026/7/4技术教程

最近在搞 LLM 应用开发,发现 Spring AI 里有个 ChatModel 挺好用的,分享一下我的实践笔记。

为啥用 ChatModel

说白了,ChatModel 是 Spring AI 里跟大模型对话的核心接口。不管你是用 OpenAI、通义千问还是本地跑个 Llama,只要接上 ChatModel,代码基本不用怎么改。它主要帮你干几件事:

  • 统一调用方式,不用记各家 SDK 的奇奇怪怪 API
  • 内置对话管理,可以自己控制上下文
  • 支持流式输出,不用等 LLM 慢吞吞吐完一整段
  • 还带一些工具调用、函数调用的能力,挺灵活

快速上手

1. 加依赖

我用的是 Maven,在 pom.xml 里加上 Spring AI 的 BOM 和具体的模型实现:

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-bom</artifactId>
            <version>1.0.0-M6</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
    <dependency>
        <groupId>org.springframework.ai</groupId>
        <artifactId>spring-ai-openai-spring-boot-starter</artifactId>
    </dependency>
</dependencies>

如果你用通义千问或者别的,换对应的 starter 就行,比如 spring-ai-qwen-spring-boot-starter。

2. 配置 API Key

在 application.yml 里配一下(别把 key 硬编码到代码里,我吃过亏):

spring:
  ai:
    openai:
      api-key: sk-xxxxxxxxxxxxxxxx
      chat:
        model: gpt-4o-mini
        options:
          temperature: 0.7
          max-tokens: 1024

3. 写个最简单的对话

import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/chat")
public class ChatController {

    @Autowired
    private ChatModel chatModel;

    @PostMapping("/simple")
    public String simpleChat(@RequestBody String message) {
        Prompt prompt = new Prompt(message);
        return chatModel.call(prompt).getResult().getOutput().getContent();
    }
}

跑起来,POST 一个 {"message": "你好,介绍一下 Spring AI"},它就会返回 LLM 的回答。就这么简单。

进阶用法

带上下文的对话

单次调用没啥意思,实际场景里通常要记住上下文。可以用 ChatMemory 来搞:

import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.memory.InMemoryChatMemory;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.messages.AssistantMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class ChatService {

    @Autowired
    private ChatModel chatModel;

    private final ChatMemory chatMemory = new InMemoryChatMemory();

    public String chat(String sessionId, String userMessage) {
        // 获取历史消息
        List<Message> history = chatMemory.get(sessionId, 10);
        // 加上用户新消息
        history.add(new UserMessage(userMessage));
        // 调用模型
        Prompt prompt = new Prompt(history);
        String response = chatModel.call(prompt).getResult().getOutput().getContent();
        // 把回答存进去
        history.add(new AssistantMessage(response));
        chatMemory.put(sessionId, history);
        return response;
    }
}

InMemoryChatMemory 是内存实现的,重启就没了。生产环境可以用 Redis 或者数据库,实现一个 ChatMemory 接口就行。

流式输出

LLM 回答慢的时候用户容易焦虑,流式输出体验好很多:

import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;

@RestController
@RequestMapping("/chat")
public class StreamingChatController {

    @Autowired
    private ChatModel chatModel;

    @PostMapping(value = "/stream", produces = "text/event-stream")
    public Flux<String> streamChat(@RequestBody String message) {
        Prompt prompt = new Prompt(message);
        return chatModel.stream(prompt)
                .map(chunk -> chunk.getResult().getOutput().getContent());
    }
}

前端用 EventSource 或者 fetch + ReadableStream 就能逐字显示,体验感拉满。

工具调用(Function Calling)

这个才是真正实用的功能——让 LLM 能调用你的 Java 方法。比如让 AI 帮你查天气:

先定义一个工具类:

import org.springframework.ai.tool.annotation.Tool;
import org.springframework.stereotype.Component;

@Component
public class WeatherTools {

    @Tool(name = "get_weather", description = "获取指定城市的天气")
    public String getWeather(String city) {
        // 这里假装调了天气API
        if ("北京".equals(city)) {
            return "北京今天晴,25°C,空气质量良";
        } else if ("上海".equals(city)) {
            return "上海今天多云,28°C,湿度较大";
        }
        return "暂不支持该城市";
    }
}

然后在调用时注册工具:

import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.model.tool.ToolCallingManager;
import org.springframework.ai.tool.ToolCallback;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/chat")
public class ToolChatController {

    @Autowired
    private ChatModel chatModel;

    @Autowired
    private List<ToolCallback> toolCallbacks;  // Spring 会自动收集 @Tool 注解的方法

    @PostMapping("/with-tools")
    public String chatWithTools(@RequestBody String message) {
        Prompt prompt = new Prompt(message);
        // 把工具传给模型
        var response = chatModel.call(prompt, toolCallbacks);
        return response.getResult().getOutput().getContent();
    }
}

这样用户说“北京天气怎么样”,LLM 就会自动调用 getWeather("北京"),拿到结果再组织成自然语言回答。

踩坑记录

  1. Token 限制:默认 max-tokens 可能不够,长对话记得调大,否则回答会被截断。
  2. 上下文窗口:ChatMemory 的 get(sessionId, 10) 里的 10 表示最近 10 条消息,设太大容易超 token 限制,设太小记不住上下文。建议根据模型的最大上下文动态计算。
  3. 工具注册:@Tool 注解的方法必须是 public 的,且参数类型要简单(String、int 这些),复杂对象 LLM 不一定能正确生成参数。
  4. 流式 + 工具调用:目前 Spring AI 的流式工具调用支持还不完善,如果既要流式又要调工具,建议先非流式调工具拿到结果,再流式输出最终回答。

总结

ChatModel 这套 API 设计得挺清爽,把 LLM 调用抽象成了类似 JDBC 的感觉——换模型就换驱动(依赖)和配置,业务代码几乎不用动。对于快速搭建 LLM 应用原型来说,非常顺手。

当然,生产环境还要考虑错误重试、限流、日志追踪这些,Spring AI 也提供了对应的抽象,下次有空再写一篇。

编写使用方法
Markdown 格式 · Ctrl+Enter 确定
新建笔记
预览
数据表格
点击单元格编辑 · Tab 移动
A1fx
Sheet1
BIH1H2≡🔗</>
隐私提醒

取消
编辑工具
取消