大家在开发 AI 大模型应用时,是不是经常遇到这种情况:LLM 调用写好了,但不知道怎么接 RAG;Agent 想用工具,却卡在协议对接上;好不容易跑通一个功能,换个后端框架又得从头写。网上资料往往只讲单个技术点,真正能把 LLM、RAG、Agent、MCP、工作流、工具调用串成一条完整链路的教程很少。本文就围绕这一套“全家桶”展开,从零开始带敲一个可运行的 AI 应用实战项目,同时给出 FastAPI 与 Spring Boot 双版本实现思路,帮助你打通从模型接入到工程落地的全流程。
本文面向有一定后端基础、想快速上手大模型应用的开发者。零基础的同学也不用担心,我会先把核心概念讲清楚,再逐步拆解代码。学完后,你将掌握:LLM 接入方式、RAG 检索增强生成流程、Agent 工具调用机制、MCP 标准化协议、工作流编排方法,并能独立搭建一套支持双后端框架的 AI 应用骨架。
1. 背景与核心概念
1.1 为什么需要“全家桶”
过去我们开发普通 Web 应用,只需要关注请求、数据库、业务逻辑。但 AI 大模型应用完全不一样:模型需要“记忆”你的私有知识,需要调用外部工具完成实际任务,还需要按顺序执行多步操作。单一技术点解决不了这些问题,必须把它们组合起来。
- LLM(大语言模型):提供理解和生成文本的核心能力,比如 OpenAI 的 GPT、开源社区的 Llama、国产的 DeepSeek 等。
- RAG(检索增强生成):先检索本地知识库或数据库,把相关片段拼进提示词,再让模型生成答案。用来解决模型“不懂私有内容”的问题。
- Agent(智能体):让模型自主决定调用哪些工具、按什么顺序执行,完成复杂任务。Agent 是 LLM 的最上层封装。
- MCP(Model Context Protocol):一个开放协议,用来统一模型与外部工具、数据源的连接方式。它定义了客户端、服务端、工具发现等标准接口,避免为每个工具写一遍私有适配。
- 工作流(Workflow):把固定的业务步骤编排成流程,比如“先查询订单,再判断状态,最后生成通知”。工作流比 Agent 更可预测,适合确定性高的任务。
- 工具调用(Tool Calling):模型输出结构化的调用请求,由后端执行实际函数并返回结果,再交给模型继续生成。
这套组合的核心价值是:不直接让模型裸奔,而是给它“知识库”“工具集”“流程骨架”,让它像工程师一样工作。
1.2 FastAPI 与 Spring Boot 双版本的意义
后端框架选择直接影响团队的开发效率。Python 生态下 FastAPI 简洁高效,自带异步支持和数据校验,非常适合快速搭建 AI 服务。Java 生态下 Spring Boot 稳重大气,企业中间件丰富、运维成熟,适合嵌入现有系统。很多团队同时维护两套技术栈,所以本文会给出双版本的代码思路,重点展示 API 设计和配置差异,而不是偏袒某一方。
1.3 需要区分的关键词
初学者容易混淆 Agent 和 Workflow。Agent 是动态决策,模型自行规划路径;Workflow 是静态编排,路径由开发人员预设。MCP 和普通 HTTP API 也不同:MCP 是一套标准协议,服务端可以通过统一接口向模型暴露多个工具,而普通 API 通常是点对点调用。理解这些区别,后续看代码会更清晰。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 环境准备与版本说明
本文示例以常见环境为例,重点演示配置思路,具体版本需要根据你的项目实际情况调整。下面列出我使用的基础环境:
- Python 3.10+(推荐 3.11 或更高)
- Java 17+(Spring Boot 3.x 要求)
- FastAPI 0.100+
- Spring Boot 3.2+
- OpenAI SDK 1.x(或兼容 OpenAI 的 SDK,如 DeepSeek 官方 SDK)
- LangChain 0.1+(可选,用于简化 RAG 和 Agent 开发)
- Spring AI 1.0.0 及以上(Spring 生态的 AI 抽象层)
注意:如果你使用的是国内大模型服务,只要接口兼容 OpenAI,就可以直接替换 base_url 和 api_key,代码逻辑不变。如果使用 LangChain 或 Spring AI,版本变化较大,务必参考官方最新文档。
2.1 项目结构规划
为了区分两个版本,我会分别创建两个目录:
text复制ai-family-bucket/
├── fastapi-version/
│ ├── main.py # FastAPI 入口
│ ├── config.py # 配置信息
│ ├── llm.py # LLM 调用封装
│ ├── rag.py # RAG 链路
│ ├── agent.py # Agent 与工具调用
│ ├── mcp_server.py # MCP 服务端
│ ├── workflow.py # 工作流编排
│ └── requirements.txt
└── springboot-version/
├── pom.xml # Maven 配置
├── src/main/java/com/example/aifamily/
│ ├── AiFamilyApplication.java
│ ├── controller/AiController.java
│ ├── service/LlmService.java
│ ├── service/RagService.java
│ ├── service/AgentService.java
│ ├── service/McpService.java
│ └── service/WorkflowService.java
└── src/main/resources/application.yml
实际项目中你可以把公共逻辑抽象成共享库,但本文为了讲解直观,故意拆分两个独立版本。
3. 核心语法、配置或原理拆解
3.1 LLM 调用封装
无论 FastAPI 还是 Spring Boot,第一步都是封装 LLM 客户端。这里以 OpenAI 兼容接口为例。
最小示例(Python):
python复制# 文件路径:fastapi-version/llm.py
from openai import OpenAI
client = OpenAI(
api_key="your-api-key",
base_url="https://api.example.com/v1"
)
def chat(messages, model="gpt-4o-mini", temperature=0.7):
response = client.chat.completions.create(
model=model,
messages=messages,
temperature=temperature
)
return response.choices[0].message.content
对应 Spring Boot 使用 Spring AI:
java复制// 文件路径:springboot-version/src/main/java/com/example/aifamily/service/LlmService.java
@Service
public class LlmService {
private final ChatClient chatClient;
public LlmService(ChatClient.Builder builder) {
this.chatClient = builder.build();
}
public String chat(String userMessage) {
return chatClient.prompt().user(userMessage).call().content();
}
}
关键参数:model 决定智能程度与成本;temperature 控制随机性,0 表示固定输出,1 表示更有创意。实际项目中,api_key 不要硬编码,应通过环境变量或配置中心注入。
3.2 RAG 检索增强生成
RAG 的核心是向量化 + 相似度检索。典型流程:文档切块 -> 生成向量 -> 存入向量数据库 -> 查询时把顶部 k 个结果拼进提示词。
最小示例(使用 LangChain 的 FAISS 向量库):
python复制# 文件路径:fastapi-version/rag.py
from langchain_community.embeddings import OpenAIEmbeddings
from langchain_community.vectorstores import FAISS
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_openai import OpenAIEmbeddings # 注意:请按版本导入
text = "大模型应用开发需要掌握 RAG。"
splitter = RecursiveCharacterTextSplitter(chunk_size=200, chunk_overlap=20)
chunks = splitter.split_text(text)
embeddings = OpenAIEmbeddings()
vectorstore = FAISS.from_texts(chunks, embeddings)
retriever = vectorstore.as_retriever(search_kwargs={"k": 2})
随后在查询时调用 retriever.invoke("什么是 RAG"),把检索结果拼到 system 或 user 消息中。
Spring AI 中可以使用 VectorStore 抽象:
java复制@Service
public class RagService {
private final VectorStore vectorStore;
public RagService(VectorStore vectorStore) {
this.vectorStore = vectorStore;
}
public String generate(String query) {
List<Document> docs = vectorStore.similaritySearch(query);
String context = docs.stream().map(Document::getText).collect(Collectors.joining("\n"));
return chatWithContext(query, context);
}
}
关键点:chunk_size 决定每块字符数,overlap 避免语义断裂;k 决定检索数量,太少可能遗漏,太多会稀释提示词。生产环境推荐使用 PGVector、Milvus、Redis Stack 等持久化向量库。
3.3 Agent 与工具调用
Agent 的本质是让模型在循环中调用工具。最朴素的方式是给模型一个工具描述,让它输出 JSON 格式的调用请求,后端执行函数后再反馈结果。
Python 中可以用 OpenAI 的 tools 参数:
python复制# 文件路径:fastapi-version/agent.py
def get_weather(city: str):
return f"{city} 天气晴,温度 25℃"
tools = [{
"type": "function",
"function": {
"name": "get_weather",
"description": "查询天气",
"parameters": {
"type": "object",
"properties": {"city": {"type": "string"}},
"required": ["city"]
}
}
}]
def run_agent(messages):
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=messages,
tools=tools
)
for call in response.choices[0].message.tool_calls:
if call.function.name == "get_weather":
result = get_weather(**json.loads(call.function.arguments))
messages.append({"role": "tool", "tool_call_id": call.id, "content": result})
return client.chat.completions.create(model="gpt-4o-mini", messages=messages)
Spring AI 提供了 ToolCallingManager 或 @Tool 注解:
java复制@Service
public class AgentService {
@Tool(name = "getWeather", description = "查询天气")
public String getWeather(String city) {
return city + " 天气晴,温度 25℃";
}
}
Spring AI 会自动把方法注册进模型可调用的工具列表中,并在模型请求时反射执行。注意:工具函数要有明确的参数类型和描述,否则模型容易传错参数。
3.4 MCP 原理
MCP 独特的价值在于“一次定义,多模型复用”。MCP 服务端通过标准 JSON-RPC 暴露 tools/list、tools/call 等方法。客户端(比如 Claude Desktop、LangChain MCP 适配器)发现工具,然后由 LLM 调用。
一个最小 MCP 服务端(Python)可以借助 mcp 库:
python复制# 文件路径:fastapi-version/mcp_server.py
from mcp.server import Server, NotificationOptions
from mcp.server.models import InitializationOptions
server = Server("demo-server")
@server.tool()
async def add(a: int, b: int) -> int:
"""Add two numbers"""
return a + b
实际运行时需要注册传输层,比如 Streamable HTTP。Spring Boot 下可以用官方 Java SDK 实现相同接口。MCP 的核心价值是标准化:前端 Agent 不用关心工具背后是 Python 还是 Java,只要协议一致即可接入。
3.5 工作流编排
工作流适合固定顺序的任务。最简单的实现是后端函数串联,复杂场景可以用状态机。
示意代码(Python):
python复制# 文件路径:fastapi-version/workflow.py
def run_workflow(user_query):
# 步骤1:意图识别
intent = llm_chat(f"判断意图:{user_query}")
if intent == "query_weather":
# 步骤2:调用工具
weather_result = get_weather("北京")
# 步骤3:生成回复
return llm_chat(f"基于结果回复:{weather_result}")
else:
return "暂不支持"
Spring Boot 中可以定义多个 @Service,在 WorkflowService 中按顺序注入调用。工作流的好处是可控、可测试,适合生产环境要求高可靠性的场景。
4. 完整实战案例:搭建一个“AI 答疑助手”
下面我们完整实现一个既能查文档、又能调用天气工具、还支持多步骤问答的“AI 答疑助手”。该助手包含:LLM 对话、RAG 知识检索、Agent 工具调用、MCP 集成和工作流编排。
4.1 创建项目结构
按上一节的结构建立两个目录。这里以 FastAPI 版本为主讲代码,Spring Boot 给出核心类。
4.2 添加依赖或配置
FastAPI 的 requirements.txt:
txt复制fastapi==0.111.0
uvicorn==0.30.0
openai==1.30.0
langchain==0.2.0
langchain-openai==0.1.0
langchain-community==0.2.0
faiss-cpu==1.8.0
mcp==1.2.0
python-dotenv==1.0.1
Spring Boot 的 pom.xml 主要依赖:
xml复制<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-pgvector-store-spring-boot-starter</artifactId>
<version>1.0.0</version>
</dependency>
注意:Spring AI 版本迭代很快,上述版本号可能不是你项目中最新的,请以 Spring 官方文档为准。
4.3 编写核心代码
FastAPI 版本
先看 main.py,声明路由并挂载各功能:
python复制# 文件路径:fastapi-version/main.py
from fastapi import FastAPI
from pydantic import BaseModel
from rag import answer_rag
from agent import run_agent
from workflow import run_workflow
app = FastAPI(title="AI Family Bucket")
class ChatRequest(BaseModel):
query: str
mode: str = "llm" # llm | rag | agent | workflow
@app.post("/chat")
async def chat(req: ChatRequest):
if req.mode == "llm":
return {"reply": llm_chat(req.query)}
elif req.mode == "rag":
return {"reply": answer_rag(req.query)}
elif req.mode == "agent":
return {"reply": run_agent([{"role": "user", "content": req.query}])}
elif req.mode == "workflow":
return {"reply": run_workflow(req.query)}
else:
return {"error": "unknown mode"}
rag.py 中完善检索与生成:
python复制# 文件路径:fastapi-version/rag.py
from langchain_openai import OpenAIEmbeddings
from langchain_community.vectorstores import FAISS
from langchain_text_splitters import RecursiveCharacterTextSplitter
import tempfile
def load_document(text):
splitter = RecursiveCharacterTextSplitter(chunk_size=200, chunk_overlap=20)
chunks = splitter.split_text(text)
embeddings = OpenAIEmbeddings()
vectorstore = FAISS.from_texts(chunks, embeddings)
return vectorstore.as_retriever(search_kwargs={"k": 2})
retriever = load_document("大模型应用开发需要掌握 RAG、Agent、MCP。")
def answer_rag(query):
docs = retriever.invoke(query)
context = "\n".join([d.page_content for d in docs])
messages = [
{"role": "system", "content": "你是一个 AI 助手,请基于以下知识回答问题,不要编造。"},
{"role": "user", "content": f"知识:\n{context}\n\n问题:{query}"}
]
return llm_chat(messages)
agent.py 中补充模型循环:
python复制# 文件路径:fastapi-version/agent.py
import json
from llm import client
def get_weather(city: str):
return f"{city} 天气晴,温度 25℃"
tools = [...]
def run_agent(messages, max_turn=5):
for _ in range(max_turn):
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=messages,
tools=tools
)
msg = response.choices[0].message
if not msg.tool_calls:
return msg.content
messages.append(msg)
for call in msg.tool_calls:
if call.function.name == "get_weather":
args = json.loads(call.function.arguments)
result = get_weather(args["city"])
messages.append({"role": "tool", "tool_call_id": call.id, "content": result})
return "已达最大轮数"
workflow.py 实现简单串联:
python复制# 文件路径:fastapi-version/workflow.py
from llm import llm_chat
def run_workflow(query):
intent = llm_chat(f"判断意图(写死): {query}")
# 这里演示固定流程,实际可用字符串匹配
if "天气" in query:
weather = get_weather("北京")
return llm_chat(f"结果:{weather},请优雅回复。")
return llm_chat(f"回答:{query}")
llm.py 里实现统一的 llm_chat 函数,方便复用。
Spring Boot 版本
AiFamilyApplication.java 是入口,不赘述。
AiController.java 接收请求:
java复制@RestController
@RequestMapping("/chat")
public class AiController {
private final LlmService llmService;
private final RagService ragService;
private final AgentService agentService;
private final WorkflowService workflowService;
@PostMapping
public Map<String, String> chat(@RequestBody ChatRequest request) {
return switch (request.mode()) {
case "llm" -> Map.of("reply", llmService.chat(request.query()));
case "rag" -> Map.of("reply", ragService.generate(request.query()));
case "agent" -> Map.of("reply", agentService.run(request.query()));
case "workflow" -> Map.of("reply", workflowService.run(request.query()));
default -> Map.of("error", "unknown mode");
};
}
}
WorkflowService.java:
java复制@Service
public class WorkflowService {
private final LlmService llmService;
public String run(String query) {
if (query.contains("天气")) {
String weather = agentService.getWeather("北京");
return llmService.chat("结果:" + weather + ",请优雅回复。");
}
return llmService.chat(query);
}
}
4.4 运行与验证
FastAPI 运行:
bash复制cd fastapi-version
pip install -r requirements.txt
uvicorn main:app --reload
调用测试:
bash复制curl -X POST http://localhost:8000/chat \
-H "Content-Type: application/json" \
-d '{"query": "什么是 RAG", "mode": "rag"}'
Spring Boot 运行:
bash复制cd springboot-version
mvn spring-boot:run
调用测试:
bash复制curl -X POST http://localhost:8080/chat \
-H "Content-Type: application/json" \
-d '{"query": "今天北京的天气", "mode": "agent"}'
4.5 结果说明
如果一切正常,RAG 模式会返回基于知识库的答案,比如“RAG 是检索增强生成,用于让模型获取私有知识。” Agent 模式会先调用天气工具,再生成自然语言回复。这验证了 LLM 接入、工具调用、RAG 检索三条链路都是通的。
5. 常见问题与排查思路
| 问题现象 | 常见原因 | 解决思路 |
|---|---|---|
| API 返回 401 | API Key 错误或未设置 | 检查环境变量、.env 文件,确认 key 有效且未过期 |
| 模型响应超时 | 网络问题或模型负载过高 | 设置超时参数,增加重试机制,改用流式传输 |
| RAG 检索结果为空 | 向量库未写入数据 | 确认文档已切块并导入,打印检索结果检查 |
| Agent 不调用工具 | 工具描述不清或模型版本不支持 | 优化工具描述,确保参数 schema 正确,升级模型版本 |
| MCP 握手失败 | 协议版本不匹配 | 确认服务端实现的协议版本,查看日志中 JSON-RPC 请求 |
| Spring Boot 启动报依赖错误 | Spring AI 版本与 Boot 版本不兼容 | 统一版本号,使用 Spring 官方 BOM 管理依赖 |
排查通用思路:先看后端日志是否有异常堆栈;再确认配置项(API Key、base_url、模型名称)是否与实际服务一致;最后用 curl 或 Postman 单独测试每个接口,逐层缩小问题范围。
6. 最佳实践与工程建议
- 配置管理:不要把 API Key 写在代码里,使用环境变量或配置中心。本地开发可以用
.env文件,生产环境用Vault或云服务商的密钥管理。 - 异常处理:LLM 调用可能失败,一定要处理重试、降级、超时。建议设置重试 2-3 次,退避时间递增。
- 日志记录:记录每次请求的模型名称、输入 token 数、输出 token 数、耗时。这能帮助你分析成本和质量。
- 安全边界:Agent 工具调用要加权限控制。例如天气工具是只读的,但数据库工具需要用户授权,不能让模型随意执行删除语句。对所有工具入参进行校验,防止注入。
- 性能优化:RAG 的向量检索用缓存;LLM 响应考虑流式输出,避免用户等太久;对高频场景做 prompt 缓存。
- 可维护性:把模型调用、检索、工具实现分离到不同模块,方便单独升级。接口版本用 URL 前缀如
/v1/chat。 - 生产环境注意:控制 Agent 的最大轮数,避免死循环;对工具调用结果做截断,防止上下文过长;部署时配置优雅停机,保证正在处理的请求完成。
7. 总结与学习路线
本文从概念讲起,梳理了 LLM、RAG、Agent、MCP、工作流、工具调用的定位;接着给出了 FastAPI 和 Spring Boot 双版本的环境准备、核心代码和运行验证;最后总结了常见问题与工程建议。你已经具备搭建一个基础 AI 应用骨架的能力,接下来建议按这个路线继续深入:
- 把 FAISS 替换成正式向量数据库(PGVector 或 Milvus),测试大规模文档检索效果。
- 学习 LangGraph 或 Spring AI 的
StatefulAgent,体验复杂多分支 Agent。 - 研究 MCP 官方文档,用 Python 或 Java 编写一个能访问数据库的 MCP 服务端。
- 接触微服务架构下的模型网关,统一管理多个模型供应商的调用与降级。
真正想在生产环境落地,优先要把日志、权限、成本监控补全。欢迎收藏本文,等需要搭项目时直接拿出来对照配置,遇到问题也可以按第 5 节的表格快速排查。纸上得来终觉浅,建议你现在就把案例代码跑一遍,亲手调通一个 Agent 调用,感受“模型自主决策”带来的工程变化。
