跳到主要内容
📖 本章预览

本章为预览版本,展示部分核心内容。完整内容包含详细源码解析、实战代码和面试要点,加入知识星球即可解锁全部章节。

第8章 深入 Spring AI 内核:源码剖析

本章基于 Spring AI 1.1.0-M4 源码,带你从最顶层的接口一路追到 HTTP 调用,每一层都贴真实源码。

Spring AI 调用链路

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 = PromptTRes = 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() 默认不支持,需要具体实现类覆盖
  • 返回值链路:ChatResponseGenerationAssistantMessagegetText()

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 章完整内容 + 持续更新
  • ✅ 配套源码 + 实战项目
  • ✅ 一对一答疑 + 面试辅导
  • ✅ 简历优化 + 内推机会

📚 本章完整目录

以下为本章完整目录结构,加入知识星球即可解锁全部内容。

8.4.2 响应侧:ChatResponse → Generation → AssistantMessage

8.4.3 Message 体系

8.5 完整调用链(附图)

8.6 Advisor 拦截链:请求增强与响应增强

8.7 ChatOptions 参数合并机制

8.8 自动装配机制:Starter 如何工作

8.9 流式响应的 Reactor 实现

8.10 RetryTemplate 重试机制

8.11 多模型适配器模式

8.12 Tool Call 循环机制

8.13 小结:源码阅读路线图