# AI Agent 开发面试题
基于 LangChain4j 和 LangGraph4j 的 AI Agent 开发实践面试题。
# 一、AI Agent 架构设计
Q1:介绍一下你用 LangChain4j / LangGraph4j 构建的 AI Agent 助手,它如何理解用户意图并执行业务操作?
参考答案:
- 整体架构:用户 Input → Router Agent(意图识别) → 分发到对应子 Agent(查询、执行、流程调度)。使用 LangChain4j 的
AiServices封装接口,通过@SystemMessage定义角色和业务规则。 - 工具集成:将业务 API 封装为
@Tool,Agent 根据意图调用对应工具(如查询订单状态、创建销售单)。 - 状态管理:LangGraph4j 构建有状态工作流,用于多步骤任务(如核销流程需先查询券再校验再调用核销接口)。通过状态图节点和条件边实现分支与重试。
- RAG 应用:使用百炼 Embedding + 本地向量库(PGVector 或 Milvus)存储业务知识文档,Agent 检索后生成准确回答。
- 实际难点:业务接口参数复杂时,工具描述要精确;加校验层防止幻觉导致的错误调用;实现 Human-in-the-loop 审批。
Q2:什么是 VibeCoding?在你的 AI Agent 开发中如何发挥作用?有什么局限性?
参考答案:
- VibeCoding 指利用大模型(如 Codex、Claude、OpenCode)根据自然语言意图或注释生成代码、测试、配置的开发模式,强调"感觉写"和快速迭代。
- 发挥作用:
- 快速生成 CRUD 接口、数据模型(实体、DTO)、单元测试。
- 生成 CI 脚本、Dockerfile、K8s 资源文件。
- 在 AI Agent 开发中,生成 LangChain4j 的工具包装器、配置类。
- 局限性:
- 对复杂业务逻辑理解可能偏离,生成代码需要仔细审查。
- 上下文窗口限制,大项目架构设计仍需人工把控。
- 需要大量 prompt 调试和领域知识注入。
- 应强调会结合传统工程实践(代码审查、测试)确保质量。
Q3:设计一个支持多轮对话、能调用内部 API 并包含人工审核环节的 AI Agent,请画出整体架构。
参考答案:
- 前端交互(移动端、Web)→ 网关 → Agent 服务。
- Agent 服务包含:
- 会话管理(存储历史消息、状态)。
- 意图识别 + 路由。
- 工具调用层(封装业务 API,统一鉴权)。
- 审批介入:当识别为敏感操作(退款、大额交易),Agent 挂起并推送消息到审批中心,由人工在企业协作平台审批,结果回调 Agent 继续。
- 基于 LangGraph 的状态图:用户输入 → 理解意图 → 条件分支(直接执行/请求授权)→ 执行动作 → 生成回复。
- 向量数据库存储知识库用于 RAG。
- 审计日志记录所有 Agent 操作。
- 消息通道可用 RocketMQ 驱动异步任务。
Q4:Prompt Engineering 在你开发 AI 功能时具体做过哪些优化?举一个例子。
参考答案:
- 例:业务查询助手,一开始直接问"查询我的订单"效果差。优化:
- 加入系统指令:"你是一个电商订单查询助手,请从用户输入中提取关键信息:订单号、手机号、时间范围。如果信息不完整,请友好追问。"
- 使用 few-shot 示例展示标准查询格式。
- 明确工具调用格式(function call),缩短工具描述,提高准确率。
- 结构化输出:要求最终回复采用特定 JSON 便于前端渲染。
- 通过 A/B 测试对比意图识别准确率从 75% 提升至 93%。
# 二、LangChain4j 深入
Q5:LangChain4j 中的 AiServices 与 @Tool 注解是如何工作的?请从代理生成、工具调用流程、参数序列化和异常处理几个方面说明。
参考答案:
- 代理生成:
AiServices通过Proxy和InvocationHandler在运行时创建接口的代理实例。调用接口方法时,它会拦截方法签名和参数,构建ChatRequest。 - 工具描述注入:
@Tool注解的方法会被扫描,提取名称、描述和参数 Schema(通过 Java 反射或显式注解@P),转换成 OpenAI function / tool call 格式,附在系统消息中。 - 调用流程:
- 代理将用户输入和可用工具列表发送给 LLM。
- LLM 返回文本或
ToolExecutionRequest。 - 若为工具调用,框架反序列化参数(默认 JSON),反射执行
@Tool方法,获取返回值。 - 将工具执行结果作为
ToolExecutionResultMessage追加到对话历史,再次请求 LLM 生成最终回答。
- 参数序列化:支持基础类型、POJO 的 JSON 序列化(默认 Gson/Jackson),复杂对象可通过自定义
ToolParameterConverter处理。 - 异常处理:工具执行异常被包装为错误消息发送给 LLM,可让 LLM 据此重试或生成降级回复。可在工具方法内捕获,返回描述性错误字符串,使 LLM 能友好反馈。
- 优化点:可以并行调用多个工具(
AiServices支持@Tool的returnDirect和分组),需要控制最大工具调用深度防止死循环。
Q6:LangChain4j 中的 RAG(Retrieval-Augmented Generation)是如何实现的?如何优化多文档、长上下文的检索质量?
参考答案:
- 基础 RAG 流程:
- 文档加载与切分:
DocumentSplitter按段落、句子或固定字符数切分,保持连贯性。 - 向量化:使用
EmbeddingModel(如 OpenAI / 百炼)将分段转为向量,存入EmbeddingStore(如 PGVector、Redis Stack)。 - 检索:用户查询同样向量化,通过余弦相似性检索 Top-K 片段。
- 增强:将检索片段与提示词组合,发送给 LLM 生成回答。LangChain4j 提供
ContentRetriever和RetrievalAugmentor抽象。
- 文档加载与切分:
- 优化策略:
- 多级检索:先粗筛(关键词/BM25),再向量精排,或使用 ColBERT 等迟交互模型。
- 父文档检索:切分时保留父子关系,检索到子片段后返回完整父文档上下文,避免信息断裂。
- 元数据过滤:利用
Metadata和Filter按来源、日期、类别预过滤,缩小检索范围。 - 重排序:对召回的结果用 Cross-Encoder Reranker 二次排序,提升 Top-3 精确度。
- 查询改写:用 LLM 将口语化查询转换为更规范的检索查询(Multi-Query / HyDE)。
- 上下文压缩:
ContextCompressor对检索到的长文本提取最相关句子,节省 Token。
Q7:在 Agent 中,如何控制工具调用的资源消耗(如 Token 消耗、API 调用次数)和防止无限循环?
参考答案:
- Token 消耗控制:
- 设定每次请求的最大
completionTokens。 - 裁剪对话历史:保留最近 N 轮,或对历史总结后再送入 LLM(
ChatMemory配合MessageWindowChatMemory或TokenWindowChatMemory)。 - 对工具返回结果做截断,只保留关键字段,避免大对象塞入上下文。
- 设定每次请求的最大
- 调用次数控制:
- LangChain4j 的
AiServices支持maxSequentialToolInvocations,设置工具链式调用最大步数。 - LangGraph 状态图内可设置节点循环计数器,达到阈值后强制转入错误处理节点。
- LangChain4j 的
- 防止无限循环:
- 节点间自循环必须带有条件,且条件检查状态中的循环计数。
- 使用
END节点强行终止。 - 设置全局超时时间:Agent 整体调用超时后返回兜底话术。
- 成本监控:
- 记录每次 LLM 调用消耗的 Token 和延迟,通过 AOP 或拦截器统计,异常时告警。
Q8:你如何在 Spring Boot 项目中集成 LangChain4j?如何管理多个不同的 LLM 模型(如百炼用于中文业务,DeepSeek 用于推理)?
参考答案:
- 集成方式:
- 使用
langchain4j-spring-boot-starter,在application.yml配置模型提供者(openai、dashscope、ollama 等)的 API key、模型名。 - 配置
ChatLanguageModel、StreamingChatLanguageModel、EmbeddingModel等 Bean。 AiServices接口通过@Component自动装配,或手动AiServices.builder()创建。
- 使用
- 多模型管理:
- 为不同模型声明不同名称的 Bean,例如
baLianChatModel和deepSeekChatModel。 - 使用
@Qualifier注入到不同的AiServices接口,或通过ConditionalRoutingChatModel实现动态路由(根据请求属性选模型)。 - 可在 LangGraph 中为不同节点绑定不同模型:复杂推理节点用 DeepSeek-R1,轻量意图分类用 Qwen-Turbo。
- 为不同模型声明不同名称的 Bean,例如
- 企业级考量:
- 配置
RetryChatModel和FallbackChatModel提高可用性。 - 使用
ChatModelListener记录请求/响应,便于审计和调试。 - 通过配置中心(Nacos)动态切换模型版本或参数。
- 配置
# 三、LangGraph4j 深入
Q9:LangGraph4j 的状态机模型与传统工作流引擎(如 Activiti/Camunda)在概念和适用性上有什么本质区别?为什么在 AI Agent 场景下要选择它?
参考答案:
- 状态图 vs 流程图:LangGraph 是基于有向图的状态机,节点是"步骤"(可以是 LLM 调用、工具调用、代码逻辑),边代表状态转移。与传统 BPMN 不同,它不依赖 XML/JSON 流程定义文件,而是用代码定义图结构,更灵活。
- 本质区别:
- 传统引擎:面向结构化业务流程,节点类型固定(任务、网关、事件),依赖数据库持久化实例状态,适合人类参与的长流程。
- LangGraph:面向 AI 驱动的非确定性流程,每个节点可以是动态决策(LLM),状态可以在每次对话中增量更新,天然支持"规划-执行-反馈"循环。
- Agent 适用性:
- 循环与回溯:Agent 经常需要反思、纠正错误、重新搜索,LangGraph 的循环边和条件边能轻松实现。
- 人机协作:用中断(interrupt)节点挂起,等待人工审批后恢复,比 BPMN 的 user task 更灵活。
- 动态路由:LLM 可以直接输出下一个节点的决策,而不需要预先定义所有分支。
- 状态管理:将对话上下文、工具结果、中间变量都保存在一个可序列化的
State对象中,便于暂停/恢复和调试。
Q10:如果让你用 LangGraph4j 构建一个"销售订单智能助手",它需要支持查询、创建订单、触发审批(金额超过 5000 需人工批准),并能在审批后继续。请画出状态图设计,并说明关键实现细节。
参考答案:
状态图设计(可以口头描述或画图):
- 节点:
classify_intent:LLM 节点,识别意图(查询/创建/其他)。extract_order_info:LLM 节点,提取订单信息(商品、金额)。create_order:工具节点,调用订单创建 API,返回订单 ID。approval_check:条件判断节点(代码),根据金额决定下一步。human_approval:中断节点,暂停等待人工输入。query_order:工具节点,根据单号查询。respond:LLM 汇总回复。
- 边与路由:
classify_intent→query_order(查询)/extract_order_info(创建)/respond(其他)。extract_order_info→create_order。create_order→approval_check。approval_check→human_approval(金额>5000)/respond(无需审批)。human_approval恢复后 →respond。
关键实现细节:
- 状态定义:使用
@State或 Map 存储订单信息、intent、金额、审批结果等。 - 中断节点:在
human_approval节点抛出NodeInterruptException,框架保存当前状态到持久化存储(Redis/DB),通过 API 返回中断提示给前端。 - 人工审批恢复:前端提交审批结果,调用继续执行 API,传入
resumeValue,框架重新加载状态并从该节点继续。 - 防止重复:
create_order节点内部幂等,检查订单是否已存在(基于 requestId)。 - 错误重试:如果创建订单失败,可以添加错误处理边,导向提醒用户补充信息或重试的节点。
Q11:LangGraph4j 的 checkpoint 和断点续跑机制是如何实现的?在分布式多实例环境下如何保证状态一致性?
参考答案:
- Checkpoint 机制:
- 每次状态图执行到节点时,框架可以序列化当前
State并调用配置的CheckpointSaver存储。 - 当触发中断或错误时,状态被保存,后续可以从该检查点恢复执行。
- 可以实现
CheckpointSaver接口,使用 Redis、PostgreSQL 等持久化。
- 每次状态图执行到节点时,框架可以序列化当前
- 断点续跑:
- 客户端提供
threadId,恢复时指定要重放的检查点 ID。 - 框架加载状态,从被中断的节点继续,并把
resumeValue注入(如人工审批结果)。
- 客户端提供
- 分布式一致性:
- 同一个对话(threadId)的所有请求必须路由到同一实例或共享状态存储。
- 使用基于 Redis 的
CheckpointSaver,通过乐观锁(version 字段)避免并发更新覆盖。 - LangGraph 支持
AsyncCheckpointSaver,在保存时进行冲突检测。 - 对于高可用场景,状态存储采用 Redis Cluster 或 PG,实例无状态,状态全部外存。
# 四、AI Agent 质量保障
Q12:在前面的 AI 助手项目中,如何对 Agent 的输出质量进行评测和持续优化?请描述你的 ML-Ops 流程。
参考答案:
- 离线评测:
- 构建评估数据集:覆盖典型业务查询、异常输入、多轮对话、工具调用场景,标注预期结果。
- 自动化评测指标:
- 意图识别准确率(分类指标)。
- 工具调用准确率(参数是否匹配、是否调用正确工具)。
- 回答质量:使用 LLM-as-judge 打分(如以 GPT-4 做裁判),评估相关性、完整性、安全性。
- 回归测试:每次 Prompt 或工具变更都跑评测集。
- 在线监控:
- 收集真实会话数据(脱敏),记录用户点赞/点踩和手动纠错行为。
- 监控工具调用失败率、LLM 响应延迟、Token 消耗。
- 持续优化闭环:
- 对 Bad Case 进行根因分析:是 Prompt 不清?工具描述不准?还是模型能力不足?
- 对应调整 Prompt 模板(few-shot 示例、指令精炼)、优化工具 Schema、增加知识库文档。
- 对高频失败案例,补充到训练样本或作为新约束加入系统指令。
- 利用 LangFuse / LangSmith 等工具进行链路追踪和标注。
- 发布策略:
- 灰度部署新版 Agent,小比例用户试用,对比核心指标后全量。