1. 从传统 Java 到 Spring AI:为什么 Agent、RAG、MCP 会成为选型分水岭
如果你是一个写了几年 Spring Boot 的 Java 开发者,最近打开技术社区大概率会有一种割裂感:一边是自己熟悉的 Controller、Service、Mapper 分层,另一边是 Agent、RAG、MCP 这些词被反复提起,好像不学就要被淘汰。我身边不少做企业后端的同事都问过同一个问题——Spring AI 和 Spring AI Alibaba 到底是不是同一套东西,我该从哪个入口开始跑通第一个能用的 AI 应用。
先把结论说清楚:Spring AI 是 Spring 官方推出的 AI 应用开发框架,它把大模型调用、向量检索、工具调用这些能力抽象成 Spring 风格的 Bean 和注解;Spring AI Alibaba 则是在 Spring AI 基础上,针对国内模型生态和企业级场景做了增强封装,补齐了 Agent、Workflow、可观测性这些上层能力。两者不是竞争关系,而是同一体系的不同层次。你完全可以在一个项目里同时用 Spring AI 的 ChatClient 和 Spring AI Alibaba 的 Graph 编排能力。
那 Agent、RAG、MCP 这三个热点到底解决什么问题?我用一句话概括:RAG 解决“模型不知道你企业私有知识”的问题,MCP 解决“模型怎么规范地调用外部工具”的问题,Agent 解决“模型怎么多步推理、自己决定下一步做什么”的问题。三者不是替代关系,而是层层叠加。一个典型的企业级问答系统,底层是 RAG 做知识召回,中间用 MCP 把检索能力标准化成工具,最上层用 Agent 做多步决策和结果校验。
对于正在选型的 Java 开发者来说,最实际的路径不是先把概念背熟,而是先跑通一个最小可用的 Spring AI 应用,再逐步往上叠能力。这篇文章就按这个思路走:先给出可复制的依赖配置,再写 Agent 和 RAG 的最小示例,最后通过 TaoToken 统一 Key 和 API 通道完成模型调用,并给出连通性验证步骤。你跟着做,半小时内能跑出第一个能对话、能检索的 Spring AI 应用。
需要提前说明的是,模型调用这一层,很多人在本地调试时会卡在网络和 Key 管理上。TaoToken 提供的是统一的 API 通道,你只需要一个 Key 就能切换不同模型,省去在多个平台之间来回配置的麻烦。后面的配置片段我会给出完整的 Base URL、Key 和 Model ID 三件套,你直接替换成自己的即可。
2. TaoToken 前置准备:统一 Key 与 API 通道的配置方式
在写第一行 Spring AI 代码之前,先把模型调用通道准备好。这一步很多人会忽略,结果代码写完了发现请求发不出去,回头排查半天。我的建议是先把 Key 拿到手,再动代码。
TaoToken 的定位是一个统一的模型 API 通道,你注册后在控制台创建一个 API Key,就能通过同一个 Base URL 调用不同厂商的模型。对于 Spring AI 项目来说,这意味着你不需要为每个模型单独写一套配置,只需要在 application.yml 里改 Model ID 就能切换。控制台地址是 https://taotoken.net/console ,API Key 管理在 https://taotoken.net/api-keys ,接入文档在 https://taotoken.net/doc 。这三个页面建议先收藏,后面排查问题会反复用到。
拿到 Key 之后,你需要确认三件事:Base URL、API Key、Model ID。Base URL 统一用 https://taotoken.net/api ,注意这个地址不带任何查询参数,直接作为 OpenAI 兼容接口的 base 使用。API Key 就是你在控制台创建的那串以 sk- 开头的字符串。Model ID 则根据你的场景选择,学习和小 demo 用一个中等能力的模型就够,企业级项目再换高配版本。
这里有一个容易踩的坑:Spring AI 的 OpenAI Starter 默认会拼接 /v1/chat/completions 这样的路径,所以你的 Base URL 配置要写成 https://taotoken.net/api ,而不是 https://taotoken.net/api/v1 。如果你多写了 /v1,最终请求路径会变成 /api/v1/v1/chat/completions,直接 404。这个错误我在第一次配置时也遇到过,报错信息是 404 Not Found,但不会告诉你路径拼错了,只能靠对照文档排查。
另外,如果你用的是 Spring AI Alibaba 的 DashScope Starter,配置项名称会不一样,但底层走的还是同一套 OpenAI 兼容协议。我的做法是统一用 OpenAI Starter,这样配置最干净,切换模型时只改 model 字段。下面给出一个标准的 application.yml 配置片段,你可以直接复制:
spring: ai: openai: base-url: https://taotoken.net/api api-key: ${TAOTOKEN_API_KEY} chat: options: model: gpt-4o-mini temperature: 0.7 embedding: options: model: text-embedding-3-small注意 api-key 这里用了环境变量 ${TAOTOKEN_API_KEY},不要把 Key 硬编码到配置文件里提交到 Git。本地调试时可以在 IDEA 的 Run Configuration 里设置环境变量,或者用 .env 文件配合 Spring Boot 的 dotenv 支持。生产环境则走配置中心或 K8s Secret。
如果你需要更细粒度的控制,比如给不同环境配不同的 Key,可以在 application-dev.yml 和 application-prod.yml 里分别覆盖。Spring AI 的配置项支持这种分层覆盖,优先级是 profile 特定配置 > 默认配置。
还有一个实用技巧:TaoToken 的模型对话页面 https://taotoken.net/models 可以让你在不写代码的情况下先验证 Key 是否可用。你可以在页面上直接发一条消息,如果能正常返回,说明 Key 和通道都没问题,再去写代码就少了一层不确定性。这个页面我通常用来做第一步连通性验证,比直接跑代码快得多。
3. 可复制配置:Spring AI 依赖、Agent 与 RAG 最小示例代码
这一节是全文的核心,我会给出完整的 pom.xml 依赖、Agent 最小示例、RAG 最小示例,以及通过 TaoToken 调用模型的配置片段。你按顺序复制即可。
3.1 Maven 依赖配置
先看 pom.xml。Spring AI 的版本迭代比较快,我建议用 1.0.0-M6 或更高的稳定里程碑版本。Spring Boot 用 3.2.x 以上,JDK 17 起步。以下是完整依赖:
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.2.5</version> </parent> <properties> <spring-ai.version>1.0.0-M6</spring-ai.version> </properties> <dependencies> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-openai-spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-core</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-bom</artifactId> <version>${spring-ai.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>如果你要用 Spring AI Alibaba 的 Graph 能力,再加一个依赖:
<dependency> <groupId>com.alibaba.cloud.ai</groupId> <artifactId>spring-ai-alibaba-graph-core</artifactId> <version>1.0.0-M3</version> </dependency>3.2 Agent 最小示例
Agent 的本质是让模型能调用工具并多步推理。Spring AI 提供了 @Tool 注解来声明工具,ChatClient 会自动处理工具调用循环。下面是一个查询天气的 Agent 示例:
@Component public class WeatherAgent { private final ChatClient chatClient; public WeatherAgent(ChatClient.Builder builder) { this.chatClient = builder .defaultSystem("你是一个天气助手,用户问天气时调用工具查询。") .build(); } @Tool(description = "根据城市名查询当前天气") public String getWeather(@ToolParam(description = "城市名称") String city) { // 实际项目里这里调外部 API,这里用模拟数据 return city + " 今天晴,气温 22-28 度"; } public String chat(String userInput) { return chatClient.prompt() .user(userInput) .tools(this) .call() .content(); } }这段代码的关键在 .tools(this) 这一行,它告诉 ChatClient 当前对象里有可调用的工具。当用户问“北京天气怎么样”时,模型会先判断需要调用 getWeather,拿到结果后再生成自然语言回答。整个过程 Spring AI 帮你处理了工具调用的解析和回填,你不需要手动拼 JSON。
3.3 RAG 最小示例
RAG 的核心是把文档向量化后存入向量库,检索时用相似度召回。Spring AI 提供了 VectorStore 抽象,本地调试可以用 SimpleVectorStore。以下是完整示例:
@Configuration public class RagConfig { @Bean public VectorStore vectorStore(EmbeddingModel embeddingModel) { return new SimpleVectorStore(embeddingModel); } } @Service public class RagService { private final VectorStore vectorStore; private final ChatClient chatClient; public RagService(VectorStore vectorStore, ChatClient.Builder builder) { this.vectorStore = vectorStore; this.chatClient = builder.build(); } public void loadDocument(String content) { Document doc = new Document(content); vectorStore.add(List.of(doc)); } public String ask(String question) { List<Document> docs = vectorStore.similaritySearch( SearchRequest.query(question).withTopK(3) ); String context = docs.stream() .map(Document::getContent) .collect(Collectors.joining("\n")); return chatClient.prompt() .system("根据以下上下文回答问题,不要编造:\n" + context) .user(question) .call() .content(); } }这里有几个参数值得说明。withTopK(3) 表示召回最相似的 3 个片段,太小可能信息不全,太大容易引入噪音。实际企业项目里这个值需要根据文档切分粒度和问题类型调优。SimpleVectorStore 适合本地调试,生产环境建议换成 Elasticsearch 或 Milvus,支持混合检索和更大规模的数据。
3.4 TaoToken 调用配置片段
把上面的代码和 TaoToken 通道接起来,只需要在 application.yml 里配好三件套。如果你用 Spring AI Alibaba 的 DashScope Starter,配置写法略有不同,但核心还是 Base URL、Key、Model ID:
spring: ai: openai: base-url: https://taotoken.net/api api-key: sk-your-token-here chat: options: model: gpt-4o-mini如果你用 Spring AI Alibaba 的 Graph 做 Agent 编排,可以在 Graph 的节点里注入 ChatClient,每个节点负责一个步骤,比如路由节点判断问题类型,检索节点调 RAG,回答节点生成最终结果。这种编排方式比写死流程灵活得多,后面排障章节我会展开讲。
4. 验证请求与成功结果:从启动日志到第一次对话
配置写完之后,最重要的一步是验证。很多人代码写完直接跑,报错了才回头查,效率很低。我的习惯是分三步验证:先验证 Key 可用,再验证 Spring 上下文能启动,最后验证端到端对话。
第一步,用 TaoToken 的模型对话页面做连通性验证。打开 https://taotoken.net/models ,选择你配置的 Model ID,发一条“你好”,如果能正常返回,说明 Key 和通道没问题。这一步能排除掉 80% 的配置错误。如果这里就报 401,说明 Key 无效或没复制完整;如果报 404,说明 Base URL 配错了。
第二步,启动 Spring Boot 应用,观察日志。正常情况下你会看到类似这样的输出:
Started Application in 3.2 seconds Tomcat started on port 8080如果启动时报 Bean 创建失败,大概率是 api-key 没读到。检查环境变量是否设置,或者直接在 yml 里临时写死 Key 测试。如果报 UnknownHostException,说明 base-url 写错了,检查有没有多余的空格或换行。
第三步,写一个简单的 Controller 做端到端测试:
@RestController public class ChatController { private final ChatClient chatClient; public ChatController(ChatClient.Builder builder) { this.chatClient = builder.build(); } @GetMapping("/chat") public String chat(@RequestParam String q) { return chatClient.prompt().user(q).call().content(); } }启动后用 curl 测试:
curl "http://localhost:8080/chat?q=用一句话介绍Spring AI"成功的话你会看到模型返回的中文介绍。如果返回空字符串,检查 temperature 和 max-tokens 配置;如果返回乱码,检查编码配置。实测下来,第一次跑通这个请求大概需要 2-3 秒,后续请求会快一些,因为连接池已经建立。
对于 RAG 示例,验证方式是先调 loadDocument 接口灌入一段文本,再调 ask 接口提问。比如灌入“公司年假制度:入职满一年享 5 天年假”,然后问“年假有几天”,正确返回应该是“5 天”。如果模型回答“不知道”,说明检索没命中,检查 TopK 和 embedding 模型是否匹配。
Agent 示例的验证稍微复杂一点,因为涉及工具调用。你可以在 getWeather 方法里加一行日志,观察模型是否真的调用了工具。如果日志没打印,说明模型没触发工具调用,可能是 system prompt 写得不够明确,或者模型能力不够。换一个支持 function calling 的模型通常能解决。
5. 本篇常见错误排查:401、local proxy failed、reading choices、OAuth
这一节我整理了实际配置过程中最容易遇到的四类报错,每一类都给出原因和解决方式。这些错误我在不同项目里都踩过,你对照着排查能省不少时间。
5.1 401 Unauthorized
这是最常见的错误,报错信息通常是:
401 Unauthorized: {"error":{"message":"Invalid API key"}}原因有三个:Key 复制不完整、Key 已过期、环境变量没读到。排查顺序是先确认 Key 字符串长度,TaoToken 的 Key 一般以 sk- 开头,长度在 40 位以上。如果长度不对,重新去控制台复制。如果长度对但还是 401,去 https://taotoken.net/api-keys 确认 Key 状态是否正常。最后检查环境变量,在 IDEA 里可以用 System.getenv("TAOTOKEN_API_KEY") 打印一下,看是不是 null。
5.2 local proxy failed
这个报错通常出现在你本地配了代理但代理不可用的时候:
java.net.ConnectException: local proxy failedSpring AI 底层用的 HTTP 客户端会读取系统代理设置。如果你之前配过代理,现在代理关了但环境变量还在,就会报这个错。解决方式是检查 http_proxy 和 https_proxy 环境变量,清掉不需要的。或者在 application.yml 里显式配置不走代理:
spring: ai: openai: base-url: https://taotoken.net/apiTaoToken 的通道本身不需要额外代理配置,直连即可。
5.3 reading choices 报错
这个报错信息一般是:
Error reading choices from response原因是响应格式和 Spring AI 预期的 OpenAI 格式不一致。常见于你用了非 OpenAI 兼容的接口,或者 Base URL 多写了路径。检查 base-url 是不是 https://taotoken.net/api ,不要带 /v1 或 /chat/completions。另外确认 Model ID 拼写正确,有些模型名区分大小写。
5.4 OAuth 相关报错
如果你用的是 Spring AI Alibaba 的某些 Starter,可能会遇到 OAuth token 获取失败:
OAuth2 authentication failed这是因为部分 Starter 默认走阿里云的 OAuth 流程,而你用的是 TaoToken 的 Key 认证。解决方式是在配置里显式指定用 API Key 认证,或者直接换成 OpenAI Starter。我的建议是统一用 OpenAI Starter,配置最简单,兼容性最好。
5.5 三件套检查清单
无论遇到哪种报错,先对照这个清单检查三件套:
| 配置项 | 正确值 | 常见错误 |
|---|---|---|
| Base URL | https://taotoken.net/api | 多写 /v1 或 /chat/completions |
| API Key | sk- 开头的完整字符串 | 复制时漏字符或带空格 |
| Model ID | 控制台确认的模型名 | 拼写错误或大小写不符 |
如果三件套都对还是报错,去 https://taotoken.net/doc 查最新文档,或者用模型对话页面单独验证 Key。这个页面能帮你快速定位是 Key 问题还是代码问题。
6. 语义一致 CTA:从跑通到长期编码的路径选择
跑通第一个 Spring AI 应用之后,你大概会对 Agent、RAG、MCP 这套东西有个直观感受了。接下来的路怎么走,取决于你的目标。如果你只是想验证模型能力、做个小 demo,那现在的配置已经够用。如果你打算把 AI 能力接入企业项目,或者长期做 Agent 开发,那需要更系统的工具链支持。
对于排障和接入类需求,建议先把 API Keys 和接入文档过一遍。API Keys 页面 https://taotoken.net/api-keys 管理你的所有 Key,接入文档 https://taotoken.net/doc 有各语言的完整示例。这两个页面能解决你 90% 的配置问题。
如果你需要验证不同模型的效果,比如对比 gpt-4o-mini 和更高配版本在 RAG 场景下的表现,可以直接用模型对话页面 https://taotoken.net/models 做快速对比。不用写代码,切换模型发同样的问题,看回答质量差异。这个方式我经常用来做模型选型的前期调研。
对于长期做编码和 Agent 开发的场景,Coding Plan 会更合适。它提供更稳定的通道和更高的配额,适合把 AI 能力集成到日常开发流程里。地址是 https://taotoken.net/coding-plan ,你可以根据实际用量选择。
最后说一个我自己的经验:Spring AI 的版本迭代很快,API 偶尔会有 breaking change。我的做法是在项目里锁定一个稳定版本,不盲目追新。等社区验证过一两个版本后再升级,能省掉很多兼容性排查的时间。另外,RAG 的切分策略和 TopK 参数没有万能值,一定要拿你自己的业务文档做测试,观察召回质量再调参。这些细节文档里不会写,只能靠实际跑出来。