# 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 通过 ProxyInvocationHandler 在运行时创建接口的代理实例。调用接口方法时,它会拦截方法签名和参数,构建 ChatRequest
  • 工具描述注入@Tool 注解的方法会被扫描,提取名称、描述和参数 Schema(通过 Java 反射或显式注解 @P),转换成 OpenAI function / tool call 格式,附在系统消息中。
  • 调用流程
    1. 代理将用户输入和可用工具列表发送给 LLM。
    2. LLM 返回文本或 ToolExecutionRequest
    3. 若为工具调用,框架反序列化参数(默认 JSON),反射执行 @Tool 方法,获取返回值。
    4. 将工具执行结果作为 ToolExecutionResultMessage 追加到对话历史,再次请求 LLM 生成最终回答。
  • 参数序列化:支持基础类型、POJO 的 JSON 序列化(默认 Gson/Jackson),复杂对象可通过自定义 ToolParameterConverter 处理。
  • 异常处理:工具执行异常被包装为错误消息发送给 LLM,可让 LLM 据此重试或生成降级回复。可在工具方法内捕获,返回描述性错误字符串,使 LLM 能友好反馈。
  • 优化点:可以并行调用多个工具(AiServices 支持 @ToolreturnDirect 和分组),需要控制最大工具调用深度防止死循环。

Q6:LangChain4j 中的 RAG(Retrieval-Augmented Generation)是如何实现的?如何优化多文档、长上下文的检索质量?

参考答案:

  • 基础 RAG 流程
    1. 文档加载与切分DocumentSplitter 按段落、句子或固定字符数切分,保持连贯性。
    2. 向量化:使用 EmbeddingModel(如 OpenAI / 百炼)将分段转为向量,存入 EmbeddingStore(如 PGVector、Redis Stack)。
    3. 检索:用户查询同样向量化,通过余弦相似性检索 Top-K 片段。
    4. 增强:将检索片段与提示词组合,发送给 LLM 生成回答。LangChain4j 提供 ContentRetrieverRetrievalAugmentor 抽象。
  • 优化策略
    • 多级检索:先粗筛(关键词/BM25),再向量精排,或使用 ColBERT 等迟交互模型。
    • 父文档检索:切分时保留父子关系,检索到子片段后返回完整父文档上下文,避免信息断裂。
    • 元数据过滤:利用 MetadataFilter 按来源、日期、类别预过滤,缩小检索范围。
    • 重排序:对召回的结果用 Cross-Encoder Reranker 二次排序,提升 Top-3 精确度。
    • 查询改写:用 LLM 将口语化查询转换为更规范的检索查询(Multi-Query / HyDE)。
    • 上下文压缩ContextCompressor 对检索到的长文本提取最相关句子,节省 Token。

Q7:在 Agent 中,如何控制工具调用的资源消耗(如 Token 消耗、API 调用次数)和防止无限循环?

参考答案:

  • Token 消耗控制
    • 设定每次请求的最大 completionTokens
    • 裁剪对话历史:保留最近 N 轮,或对历史总结后再送入 LLM(ChatMemory 配合 MessageWindowChatMemoryTokenWindowChatMemory)。
    • 对工具返回结果做截断,只保留关键字段,避免大对象塞入上下文。
  • 调用次数控制
    • LangChain4j 的 AiServices 支持 maxSequentialToolInvocations,设置工具链式调用最大步数。
    • LangGraph 状态图内可设置节点循环计数器,达到阈值后强制转入错误处理节点。
  • 防止无限循环
    • 节点间自循环必须带有条件,且条件检查状态中的循环计数。
    • 使用 END 节点强行终止。
    • 设置全局超时时间:Agent 整体调用超时后返回兜底话术。
  • 成本监控
    • 记录每次 LLM 调用消耗的 Token 和延迟,通过 AOP 或拦截器统计,异常时告警。

Q8:你如何在 Spring Boot 项目中集成 LangChain4j?如何管理多个不同的 LLM 模型(如百炼用于中文业务,DeepSeek 用于推理)?

参考答案:

  • 集成方式
    • 使用 langchain4j-spring-boot-starter,在 application.yml 配置模型提供者(openai、dashscope、ollama 等)的 API key、模型名。
    • 配置 ChatLanguageModelStreamingChatLanguageModelEmbeddingModel 等 Bean。
    • AiServices 接口通过 @Component 自动装配,或手动 AiServices.builder() 创建。
  • 多模型管理
    • 为不同模型声明不同名称的 Bean,例如 baLianChatModeldeepSeekChatModel
    • 使用 @Qualifier 注入到不同的 AiServices 接口,或通过 ConditionalRoutingChatModel 实现动态路由(根据请求属性选模型)。
    • 可在 LangGraph 中为不同节点绑定不同模型:复杂推理节点用 DeepSeek-R1,轻量意图分类用 Qwen-Turbo。
  • 企业级考量
    • 配置 RetryChatModelFallbackChatModel 提高可用性。
    • 使用 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_intentquery_order(查询)/ extract_order_info(创建)/ respond(其他)。
    • extract_order_infocreate_order
    • create_orderapproval_check
    • approval_checkhuman_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,小比例用户试用,对比核心指标后全量。
最后更新时间: 2026-05-06 17:25:23