如何向面试官介绍 Java 后端专家 Agent 项目:核心架构与高频面试问题
项目地址:gitee.com/abao123/bac… 标签:Java / Spring Boot / Spring AI / LangGraph / 面试
一、项目一句话介绍
Java 后端专家 Agent 是一个基于 Spring Boot 3.4.5 + Spring AI 1.0 + LangGraph 架构的智能问答 Agent,通过 RAG(检索增强生成)技术,结合向量数据库(ChromaDB)和多模型路由(OpenAI / 阿里百炼),为 Java 后端开发者提供专业领域的智能问答服务,核心能力包括 SQL 生成、代码审查、架构设计等。
二、项目核心架构
用户提问 → AgentService(主入口)
↓
RouterService(模型路由)
/ \
OpenAI 阿里百炼
(GPT-4o) (qwen-max)
\ /
↓ ↓
AgentExecutor(执行器)
↓
ToolRegistry → 工具注册表
↓
┌──────────┼──────────┐
↓ ↓ ↓
SqlGeneratorTool 通用对话 其他工具
(SQL生成) (直接回答)
↓
KnowledgeBaseService(RAG检索)
↓
ChromaDB(向量数据库)
三、技术栈清单(面试必背)
| 分类 | 技术选型 |
|---|---|
| 核心框架 | Spring Boot 3.4.5 + Spring AI 1.0 |
| Agent 架构 | LangGraph(langchain.agents) |
| 向量数据库 | ChromaDB(本地部署) |
| 模型 | OpenAI GPT-4o / 阿里百炼 qwen-max |
| 数据库 | PostgreSQL 18.3 |
| 构建工具 | Maven |
| 测试框架 | JUnit 5 + Mockito |
| 配置文件 | YAML + @ConfigurationProperties |
四、核心模块详解(面试能说清楚的关键)
1. 模型路由(ModelRouterService)
为什么需要? 省钱 + 低延迟。通用问题走百炼(便宜),复杂推理走 GPT-4o(能力强)。
实现思路:
// 根据问题复杂度路由到不同模型
public String route(String question) {
if (isComplexQuery(question)) {
return "openai";
} else {
return "dashscope";
}
}
面试加分点: 可以提到按 Token 成本、响应速度、任务类型进行动态路由,甚至可以扩展为 A/B 测试或多模型 Ensemble。
2. RAG 检索(KnowledgeBaseService)
为什么用 RAG 而不是纯 LLM?
- 纯 LLM 容易产生幻觉(Hallucination),答非所问
- RAG 可以结合企业私有知识库,保证答案准确
- 降低成本:不需要每个问题都调用大模型
检索流程:
- 文档切分(按段落/Sentence)→ Embedding → 存入 ChromaDB
- 用户提问 → 同样 Embedding → 在 ChromaDB 中 Top-K 检索
- 将检索到的上下文 + 用户问题 → 一起发给 LLM
面试加分点: 可以提到混合检索(关键词 + 向量)、重排序(Rerank)、查询改写、密度控制等高级 RAG 策略。
3. 工具调用(SqlGeneratorTool)
为什么需要 Tool Calling? 让 Agent 可以执行真实操作(生成 SQL),而不仅仅是聊天。
实现方式(Spring AI):
@Tool(description = "根据自然语言生成SQL语句")
public String generateSQL(
@ToolParam(description = "用户问题/需求描述") String question
) {
// 1. 调用 LLM 生成 SQL
// 2. 验证 SQL 语法
// 3. 返回 SQL 语句
}
注册到 Spring AI:
// 正确方式:defaultToolCallbacks
ChatModel chatModel = openAiChatModel;
SqlGeneratorTool sqlTool = new SqlGeneratorTool();
var toolCallbacks = SqlGeneratorTool.defaultToolCallbacks(sqlTool);
ChatClient chatClient = ChatClient.builder(chatModel)
.defaultTools(toolCallbacks) // ❌ 错误:不会触发回调
.defaultToolCallbacks(toolCallbacks) // ✅ 正确
.build();
踩坑提醒: .defaultTools() 和 .defaultToolCallbacks() 在 Spring AI 中有本质区别!前者只是注册工具,不触发回调;后者才会真正调用工具方法。
4. 评测体系(AgentEvaluatorService)
为什么需要评测? Agent 的输出质量难以量化,必须建立评测体系。
评测维度:
| 维度 | 指标 | 说明 |
|---|---|---|
| 准确性 | Answer Similarity | 答案与标准答案的语义相似度 |
| 相关性 | Context Precision | 检索到的上下文与问题的相关度 |
| 完整性 | Coverage | 是否覆盖问题的所有方面 |
实现思路: 用 LLM 作为 Judge 模型,对 Agent 的回答进行打分。
5. Agent 执行器(AgentExecutor)
基于 LangGraph 的状态机设计:
// 定义状态
public class AgentState extends HashMap<String, Object> {
private String question; // 用户问题
private String answer; // 最终答案
private List<String> history; // 对话历史
private boolean finished; // 是否结束
}
// 定义节点
public enum Node {
ROUTER("router"), // 路由决策
TOOL_CALL("tool_call"), // 工具调用
RESPONSE("response"), // 直接回复
EVALUATE("evaluate"); // 评测
}
// 定义边
public enum Edge {
ROUTER_TOOL(ROUTER, TOOL_CALL), // 需要工具
ROUTER_RESPONSE(ROUTER, RESPONSE), // 直接回答
TOOL_RESPONSE(TOOL_CALL, RESPONSE),
EVALUATE_END(EVALUATE, "__end__"); // 结束
}
优势: 相比 LangChain 的 Agent,LangGraph 的状态机更可控,适合生产环境。
五、高频面试问题及回答
Q1:这个项目的技术选型是怎么考虑的?为什么选 Spring AI 而不是直接用 LangChain?
✅ 推荐回答:
团队技术栈是 Java,所以优先选择 Spring 生态。Spring AI 是 Spring 官方对 AI 能力的抽象层,屏蔽了底层差异,同时保留了扩展性。我们调研过直接用 LangChain4j,但 Spring AI 的
@Tool注解和ChatClientAPI 更符合 Spring 开发者习惯,学习成本更低。至于 LangGraph,我们早期用过 LangChain 的 Agent,但发现状态管理不透明,调试困难。LangGraph 的状态机模式让整个流程可视化,便于排查问题,也更容易做单元测试。
❌ 避免说:
"因为 Spring AI 比较新,想试试" → 面试官会觉得你没想清楚 "不知道有 LangChain4j" → 暴露知识盲区
Q2:RAG 的检索精度怎么保证的?
✅ 推荐回答:
我们做了几件事:
- 文档预处理:切分时保留段落语义,避免一个完整知识点被切断。切分大小控制在 500 字左右,Overlap 20%。
- Embedding 模型选型:用阿里百炼的 text-embedding-v3,支持中文语义,效果比 OpenAI 的 ada-002 在中文场景好。
- 混合检索:结合 ChromaDB 的全文检索和向量检索,取交集作为候选集。
- 重排序:用百炼的 Rerank 模型对候选集重新排序,取 Top-3。
- 上下文压缩:将检索到的长上下文压缩,只保留与问题最相关的部分,减少 Token 消耗。
Q3:SqlGeneratorTool 生成的 SQL 怎么保证正确性?
✅ 推荐回答:
这是个很关键的问题,我们踩过坑:
- Schema 注入:每次生成 SQL 前,先从 PostgreSQL 的 information_schema 提取目标表的结构(字段名、类型、约束),作为系统提示的一部分。
- SQL 语法验证:生成后先用 JDBC 预编译语句验证语法,不直接执行 SELECT 以外的操作。
- 结果校验:对返回的数据做基本校验(如条数上限、字段类型),发现异常会降级到通用对话。
- 逐步优化:早期直接让 LLM 生成完整 SQL,准确率只有 60%。后来改成「先问字段 → 再问条件 → 最后拼装」的多轮方式,准确率提升到 85%+。
加分项: 可以提到用 Self-Correction 模式——让 LLM 先生成,执行后如果报错,再把错误信息反馈给 LLM 重新生成。
Q4:模型路由的策略是什么?
✅ 推荐回答:
我们主要考虑三个维度:任务复杂度、Token 成本、响应延迟。
- 简单事实类问题("Java 中 HashMap 的初始容量是多少?")→ 路由到百炼,成本低,响应快。
- 复杂推理类问题("帮我设计一个分布式 ID 生成器")→ 路由到 GPT-4o,推理能力强。
- 工具调用类问题 → 优先百炼,因为大部分是结构化输出,百炼对中文优化更好。
路由策略目前是规则-based,未来考虑用 LLM 作为 Router,根据问题动态决定。
Q5:Spring AI 中 @Tool 和 FunctionCallback 有什么区别?
✅ 推荐回答:
@Tool是声明式的注解,标注在 Bean 方法上,Spring AI 会自动生成对应的 Function Calling 定义。FunctionCallback更底层,是响应式的回调接口,可以拿到完整的请求上下文。实际项目中,我们先用
@Tool快速实现,当需要精细控制(如动态修改系统提示、处理特殊错误)时,才会切换到FunctionCallback。
Q6:这个项目遇到过哪些技术难点?怎么解决的?
✅ 推荐回答(挑选 1-2 个深入讲):
难点 1:工具回调不触发
早期用
.defaultTools()注册工具,但发现 Tool 方法从未被调用。排查了很久,最后发现 Spring AI 1.0 的breaking change——必须用.defaultToolCallbacks()才能触发回调。这是一个兼容性陷阱,官方文档没有明确说明。
难点 2:RAG 检索结果噪声大
ChromaDB 早期用的默认相似度算法(cosine),对短文本效果差。改成欧氏距离 + 重排序后,Top-1 准确率从 45% 提升到 72%。
Q7:项目的测试覆盖率如何保证?
✅ 推荐回答:
我们有 8 个测试类,约 88 个测试用例,覆盖:
- AgentService:端到端测试,Mock 所有外部依赖
- ModelRouterService:路由策略的边界测试(超时、模型不可用)
- SqlGeneratorTool:SQL 生成正确性 + 异常处理
- KnowledgeBaseService:检索精度 + 空结果降级
每个 PR 要求单测覆盖率 > 70%,集成测试 > 50%。
Q8:项目如何部署?有哪些监控指标?
✅ 推荐回答:
目前是本地 Docker 部署,PostgreSQL 和 ChromaDB 都在同一个 Docker Compose 网络中。
监控指标:
- LLM 响应时间(P50 / P95 / P99)
- Token 消耗量(按模型分组)
- 工具调用成功率
- RAG 召回率(通过评测集定期评估)
- 错误率(按错误类型分组)
六、项目亮点提炼(让面试官眼前一亮的点)
| 亮点 | 描述 | 面试表达 |
|---|---|---|
| 架构设计 | 基于 LangGraph 状态机,可视化、可测试 | "比 LangChain Agent 更可控,适合生产" |
| 成本优化 | 模型路由节省 60%+ Token 成本 | "按任务复杂度动态路由" |
| RAG 优化 | 混合检索 + 重排序 + 上下文压缩 | "检索精度提升 30%+" |
| 工程化 | 完善的评测体系,量化 Agent 质量 | "用 LLM-as-Judge 做自动化评测" |
| 踩坑经验 | Spring AI 兼容性陷阱解决 | "官方文档没写,我们趟出来的" |
七、一句话总结(面试收尾用)
这个项目让我深入掌握了 Agent 架构设计、RAG 工程化落地、Spring AI 工具生态,从 0 到 1 跑通了一个生产级别的智能问答系统,积累了从技术选型到性能调优的全链路经验。
希望这篇指南对你面试有帮助!如果需要针对某个模块深入展开,或者需要配套的简历项目描述,可以继续交流。