📖 本章预览
本章为预览版本,展示部分核心内容。完整内容包含详细源码解析、实战代码和面试要点,加入知识星球即可解锁全部章节。
第8章 深入 Spring AI 内核:源码剖析
本章基于 Spring AI 1.1.0-M4 源码,带你从最顶层的接口一路追到 HTTP 调用,每一层都贴真实源码。
8.1 从一行代码说起
你写的代码可能就这么一行:
String answer = chatModel.call("今天天气怎么样?");
这一行背后,Spring AI 帮你做了:构建 Prompt → Advisor 前置拦截 → 参数合并 → 消息格式转换 → HTTP 调用 → 响应反序列化 → Tool Call 循环 → Advisor 后置拦截 → 返回结果。
下面我们逐层拆解。
8.2 顶层接口:Model
Spring AI 的设计哲学是"一个接口统一所有模型"。最顶层是 Model 接口,只有一个方法:
// 源码位置:spring-ai-model/.../model/Model.java
// 这是整个框架最核心的抽象——所有模型(Chat、Embedding、Image)都实现它
public interface Model<TReq extends ModelRequest<?>, TRes extends ModelResponse<?>> {
/**
* 执行模型调用
* @param request 请求对象
* @return 响应对象
*/
TRes call(TReq request);
}
这个设计非常简洁:TReq 是请求泛型,TRes 是响应泛型。对于聊天模型来说,TReq = Prompt,TRes = ChatResponse。
8.3 ChatModel 接口:聊天模型的契约
ChatModel 继承 Model,固定了泛型参数,并提供了几个便捷方法:
// 源码位置:spring-ai-model/.../chat/model/ChatModel.java
public interface ChatModel extends Model<Prompt, ChatResponse>, StreamingChatModel {
// 便捷方法1:传入字符串,内部自动包装成 Prompt
default @Nullable String call(String message) {
Prompt prompt = new Prompt(new UserMessage(message));
Generation generation = call(prompt).getResult();
return (generation != null) ? generation.getOutput().getText() : "";
}
// 便捷方法2:传入多条 Message
default @Nullable String call(Message... messages) {
Prompt prompt = new Prompt(Arrays.asList(messages));
Generation generation = call(prompt).getResult();
return (generation != null) ? generation.getOutput().getText() : "";
}
// 核心方法:子类必须实现(DashScopeChatModel、OpenAiChatModel 等)
@Override
ChatResponse call(Prompt prompt);
// 流式调用:默认抛异常,支持流式的子类会覆盖
default Flux<ChatResponse> stream(Prompt prompt) {
throw new UnsupportedOperationException("streaming is not supported");
}
}
读源码的关键发现:
call(String)只是语法糖,内部还是走call(Prompt)- 流式
stream()默认不支持,需要具体实现类覆盖 - 返回值链路:
ChatResponse→Generation→AssistantMessage→getText()
8.4 核心类继承体系(附图)
8.4.1 请求侧:Prompt
// 源码位置:spring-ai-model/.../chat/prompt/Prompt.java
public class Prompt implements ModelRequest<List<Message>> {
private final List<Message> messages; // 消息列表
private @Nullable ChatOptions chatOptions; // 模型参数(temperature、maxTokens 等)
// 最简构造:一个字符串自动变成 UserMessage
public Prompt(String contents) {
this(new UserMessage(contents));
}
// 完整构造:消息列表 + 参数
public Prompt(List<Message> messages, @Nullable ChatOptions chatOptions) {
Assert.notNull(messages, "messages cannot be null");
this.messages = messages;
this.chatOptions = chatOptions;
}
// 获取系统消息(第一条 SystemMessage)
🔒 解锁完整内容
本章剩余内容需要解锁后查看
以上仅为本章部分预览内容,完整内容包含更多深度源码解析、实战代码和面试要点。
加入知识星球你将获得:
- ✅ 全部 26 章完整内容 + 持续更新
- ✅ 配套源码 + 实战项目
- ✅ 一对一答疑 + 面试辅导
- ✅ 简历优化 + 内推机会
📚 本章完整目录
以下为本章完整目录结构,加入知识星球即可解锁全部内容。