Spring AI 入门到实战:我如何用它让系统具备“理解能力”

发布于:2025-06-28 ⋅ 阅读:(9) ⋅ 点赞:(0)

我向来对“整合大模型进 Java 应用”这件事持谨慎态度。在 GPT 火了之后,我们团队最初是用 HTTP 手动调 OpenAI 接口,把它当成一个 JSON API 用。但随着业务交互变复杂,我意识到:我们需要的是一个语义系统,而不是一个封装 prompt 的 util 类。

这时,Spring AI 出现了。

它不是框架革命,而是语义层和 Spring 编程模型之间的桥梁。你可以像写 Spring Boot Controller 那样调用大模型,像写 Bean 那样组织提示词和语义模板

以下是我亲身踩过的坑与总结。


Spring AI 是什么?一句话版本

Spring AI 是 Spring 推出的 AI 集成框架,它封装了与 OpenAI、Azure、HuggingFace、Anthropic 等主流 LLM 提供商的连接逻辑,并基于 Spring 编程模型提供统一的:

  • Prompt 模板机制
  • Function 调用能力(Function calling)
  • Embedding 向量搜索整合(如与 Redis、PGVector、Milvus 等)
  • ChatMemory 管理
  • RAG(检索增强生成)支持

第一步:快速跑通 OpenAI 接入

引入依赖(当前主流版本建议使用 0.8.1 或以上):

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

application.yml 配置如下:

spring:
  ai:
    openai:
      api-key: ${OPENAI_API_KEY}
      base-url: https://api.openai.com/v1
      chat:
        model: gpt-4

然后写个最基础的服务类:

@Service
public class AiAssistant {

    private final OpenAiChatClient chatClient;

    public AiAssistant(OpenAiChatClient chatClient) {
        this.chatClient = chatClient;
    }

    public String ask(String question) {
        ChatResponse response = chatClient.call(question);
        return response.getResult().getOutput().getContent();
    }
}

你会惊讶于它的“Spring 味儿”有多重 —— ChatClient 就像 RestTemplate,但背后驱动的是 LLM。


第二步:PromptTemplate 的强大之处

Spring AI 真正让我惊艳的,是 PromptTemplatePromptTemplateModel

举个例子,我们想做一个发票解析助手:

String template = """
你是一个发票专家,请从以下文本中提取字段:
{{text}}

返回格式:
{
  "invoiceCode": "",
  "invoiceNumber": "",
  "amount": "",
  "date": ""
}
""";

PromptTemplate promptTemplate = new PromptTemplate(template);
promptTemplate.add("text", ocrResult);

Prompt prompt = promptTemplate.create();
ChatResponse response = chatClient.call(prompt);

为什么说它强大?因为它把 prompt 当作模板文件处理,变量和代码解耦,可调试、可重构、可测试 —— 这比我们以前把 prompt 字符串硬编码在 Java 里强太多。


第三步:函数调用(Function Call)集成

Spring AI 支持大模型的函数调用(Function Calling)能力。你可以像注册 Spring Bean 一样注册 AI 能“调用”的 Java 方法:

@Component
public class InvoiceFunction {

    @AiFunction
    public String parseInvoice(@AiFunctionParameter(name = "text") String text) {
        // 实际是把这个方法暴露给大模型,让它决定是否调用
        return someService.extractInvoiceJson(text);
    }
}

这意味着你可以让 LLM 成为业务流程中的“指挥员”,它不再只是吐字,而是能决定调用哪个函数、传什么参数。


第四步:向量检索 + Embedding(RAG 模式)

Spring AI 原生支持嵌入向量生成和搜索。以下是一个 Redis + Embedding 的组合示例:

  1. 首先配置 Redis 向量存储(需使用 Redis Stack):
spring:
  ai:
    vectorstore:
      redis:
        host: localhost
        port: 6379
  1. 注入向量存储和 embedding 模型:
@Autowired
private VectorStore vectorStore;

@Autowired
private EmbeddingClient embeddingClient;
  1. 索引知识库:
EmbeddingResponse embedding = embeddingClient.embed("这是发票的开票代码含义说明…");
vectorStore.add(List.of(new Vector("invoice-001", embedding.getEmbedding(), metadata)));
  1. 在对话中执行 RAG 检索:
List<Document> docs = vectorStore.similaritySearch("什么是发票代码", 3);
String context = docs.stream().map(Document::getContent).collect(Collectors.joining("\n"));
  1. 拼接到 Prompt 中:
String prompt = "基于以下知识回答问题:\n" + context + "\n问题:什么是发票代码?";

这样你就完成了一个端到端的 RAG 系统,模型可以“读”你自己喂的文档。


项目实战技巧总结

  1. Prompt 模板一定要版本管理:我们用 YAML + Git 存储每个 PromptTemplate,避免代码污染和可追踪。
  2. 用注解暴露函数给大模型,是一种未来的编排模式:特别适合 Workflow 逻辑。
  3. LLM 的不可控性,需要用 ChatMemory 管住上下文:Spring AI 提供了 MemoryChatClient 封装 chat history,避免上下文漂移。
  4. 别忽视异常处理:OpenAI 接口 rate limit、timeout 经常发生,Spring AI 建议用 RetryTemplate 或自定义 fallback。

写在最后:Spring AI 更像一个“语言中间件”

Spring AI 不是大模型的封装器,而是让 Spring 应用具备“语言交互能力”的中间件

它就像当年的 Spring Data,让我们用接口操作数据库;现在我们也可以用 Spring 风格操作语义接口。


你不再需要理解 token、role、chat-completion payload,只需要关注一件事:

“业务中哪块逻辑,可以更好地用语言来处理?”

从接口设计、代码结构,到 Prompt 管理和知识检索,Spring AI 都在逐渐成为一种“主流选型”。

推荐阅读文章


网站公告

今日签到

点亮在社区的每一天
去签到