某大厂AI应用开发面试题

image

1. 记忆模块的数据存在哪种介质上?

在生产级 AI Agent 架构中,记忆模块绝非单一介质,而是根据冷热数据访问延迟进行分层存储

[短期记忆] ──> Redis / 内存 (低延迟, 缓存当前 Session)

[长期记忆] ──> 向量数据库 (语义检索) + 关系/NoSQL数据库 (完整元数据与上下文)

  • 短期记忆(Short-term Memory):
    • 介质: 内存(In-memory)或 Redis
    • 工程落地: 用于存储当前会话的最近几轮对话(Window Buffer)。利用 Redis 的 TTL(生存时间)自动清理过期会话,保证极低的读写延迟(<5ms)。
  • 长期记忆(Long-term Memory):
    • 语义记忆(Semantic Memory): 存储在向量数据库(如 Milvus, Pinecone, PGVector)。将历史对话、用户画像(User Profile)转化为 Embedding 存储,通过相似度检索(ANN)召回相关背景。
    • 情节记忆(Episodic Memory): 存储在 NoSQL/关系型数据库(如 MongoDB, PostgreSQL)。保存完整的结构化聊天历史(Chat History)、时间戳、Token 消耗等元数据,用于回溯和审计。
  • 行业最佳实践: 采用“Write-Through(直写)”策略。前端请求到达后,实时写入 Redis 保证当前对话连贯;同时异步(通过消息队列如 Kafka/RabbitMQ)将对话刷入 MongoDB 和向量数据库,避免阻塞主业务流程。

2026年已有研究表明纯向量检索并非最优解,Supermemory团队用多Agent协作系统在LongMemEval基准上达到99%准确率,完全抛弃了向量检索

2. 如何跨会话压缩对话并保留关键信息?

随着对话轮数增加,Context Window 会逐渐爆满,直接导致 Token 成本飙升及模型“注意力涣散”。跨会话压缩的核心是信息提炼与结构化

  • 技术实现路径:
    1. 滑动窗口加触发器(Sliding Window + Trigger): 当当前 Session 的 Token 数量达到阈值(如最大窗口的 70%)时,触发压缩任务。
    2. 异步总结(Async Summarization): 启动后台异步任务,调用轻量级、高吞吐的模型(如 GPT-4o-mini, DeepSeek-V3),使用特定 Prompt(如:"提取以下对话中关于用户偏好、未解决的问题和核心事实,忽略寒暄")生成 Summary。
    3. 实体与记忆图谱化(Entity Extraction): 提取 (Subject, Predicate, Object) 三元组,存入图数据库(如 Neo4j)或结构化 JSON(如 User Profile 字段),实现语义级的绝对压缩。
  • 真实业务踩坑点与解决方案:
    • 踩坑: 随着多次压缩,信息出现“传话筒效应”(信息失真、关键细节如订单号、排班日期丢失)。
    • 解决: 显式保留元数据。 制定严格的 JSON Schema 强迫模型提取“硬事实”(Facts),对于无法结构化的信息才使用 Summary;同时在 Prompt 中加入保护机制,禁止模型脑补或泛化数字。

3. FSM 状态机分哪几部分?如何代码实现?

有限状态机(FSM)在 AI Agent 中主要用于确定性的流程控制,防止 LLM 在复杂商业逻辑中“放飞自我”。

  • FSM 的核心组成部分:
    1. State(状态): 系统当前所处的状况(如:Idle, Waiting_User_Input, Calling_API, Success, Fail)。
    2. Event(事件/触发条件): 导致状态改变的输入(如:用户发送消息、LLM 解析出 Tool Call、API 返回超时)。
    3. Transition(转换): 从一个状态切换到另一个状态的状态转移函数。
    4. Action(动作): 在状态转换或进入/退出某个状态时执行的具体业务逻辑。
  • 代码实现路径(以 Python 伪代码为例):

在工业界,通常使用成熟的库(如 transitions)或通过面向对象手动构建:

class AgentStateMachine:
     def __init__(self):
         self.state = "IDLE"
         self.routes = {
             "IDLE": {"receive_input": "THINKING"},
             "THINKING": {"tool_call": "EXECUTING_TOOL", "final_answer": "RESPONDING"},
             "EXECUTING_TOOL": {"tool_success": "THINKING", "tool_error": "ERROR"},
             "RESPONDING": {"complete": "IDLE"},
             "ERROR": {"retry": "THINKING"}
         }

    def transition(self, event):
         next_state = self.routes.get(self.state, {}).get(event)
         if next_state:
             print(f"State transition: {self.state} -> {next_state}")
             self.state = next_state
             self.execute_action()
         else:
             raise ValueError(f"Invalid event {event} for state {self.state}")

    def execute_action(self):
         if self.state == "THINKING":
             # 触发 LLM 推理逻辑
             pass

  • 工程落地经验: 在多用户并发下,状态机必须是无状态的(Stateless)。不能在内存中保存实例,而是在每次请求时,从 Redis 中读取当前用户的 current_state,执行完 Transition 后,再写回 Redis。

真实的生产级FSM需要配合数据库/Redis做状态持久化

4. 为什么选择 ReAct,而不是纯 Chain 或 Tool Use?

这三者代表了控制流从“确定性”到“自主性”的光谱演进。

架构模式

核心机制

优点

缺点

纯 Chain (如 Linear Chain)

固定的有向无环图(DAG),按部就班执行 A -> B -> C。

极度稳定,延迟可控,Token 消耗低。

无法处理非线性、动态突发的复杂业务场景。

纯 Tool Use (Function Calling)

一阶段:LLM 选工具;二阶段:代码执行工具;三阶段:LLM 总结。

简单直接,适合单步查天气、查数据库。

缺乏**多步规划(Multi-step Planning)**和自我纠错能力。

ReAct (Reason + Action)

Thought -> Action -> Observation 的循环。模型边思考、边行动、边观察结果。

具备动态纠错、多步推理和深度规划能力。 如果工具报错,它能利用 Thought 自行修正参数重试。

容易陷入死循环(Loop),Token 消耗大,延迟高。

  • 为什么选择 ReAct: 针对复杂的 AI 应用(如 Auto-coder、全自动财务报表分析),你无法预知用户问题的解决路径。纯 Chain 太死板,Tool Use 只能做单步映射,只有 ReAct 赋予了模型“走一步、看一步、修正一步”的能力。
  • 落地折中方案: 纯 ReAct 往往不可控。企业级架构通常采用 LangGraph / Constraint ReAct——用图(Graph)限制 ReAct 的大框架(确定性),在节点内部允许 ReAct 进行局部动态推理(自主性)。

5. 用户今天问 A、三天后问 B,如何关联两次提问?

这是一个典型的跨会话长期上下文关联(Cross-Session Long-term Context Linkage)问题。

  • 技术实现路径:
    1. 用户唯一标识(User ID): 确保两次提问绑定在同一个 User_ID 下。
    2. 离线定时任务(User Profile Extraction): 当天会话结束后,离线后台任务将问答 A 提炼为结构化的标签或记忆(例如:用户问:“我最近在看深圳南山区的两居室”,提炼出 {"intent": "house_renting", "location": "Shenzhen_Nanshan", "budget": null}),存入数据库的用户画像表。
    3. 在线检索增强(RAG-based Memory Recall): 三天后用户问 B(“那边有什么好学校吗?”)。
      • 步骤一:Query 意图识别。 模型识别出“那边”是代词,触发指代消解。
      • 步骤二:多路召回。 根据 User_ID 去向量数据库检索最近 7 天的聊天摘要,同时去关系型数据库读取该用户的结构化 Profile。
      • 步骤三:上下文注入。 召回出三天前用户在关注“深圳南山区房子”,将该背景拼入 Prompt 丢给模型,模型即可理解“那边”指代“深圳南山区”。
  • 踩坑点: 记忆污染。如果用户已经租好了房子,或者改变了意图,旧记忆会干扰新对话。
  • 解决方案: 引入记忆衰减系数(Time-decay Function)和用户显式确认机制,对匹配到的历史记忆打上时间权重:

image

6. 多 Agent 框架怎么设计?划分 Agent 的依据是什么?

单 Agent 随着 Tool 数量变多,会导致 Prompt 污染和上下文失焦。多 Agent(Multi-Agent)架构是解决复杂业务的必然选择。

  • 多 Agent 架构设计(以 Router-Worker 模式为例):
    • Router / Master Agent: 负责分发任务,不直接处理具体业务。
    • Worker Agents: 各司其职的垂直领域专家(如 Coder Agent, Reviewer Agent, Planner Agent)。
    • Orchestrator(编排层): 管理状态流动,通常基于 LangGraph 或 Autogen,支持状态共享(Shared State)。
  • 划分 Agent 的依据:
    1. 按高内聚低耦合的业务领域(Domain-driven): 如客服场景中,划分为“退款专员 Agent”、“物流查询 Agent”、“产品咨询 Agent”。
    2. 按所需的 Prompt 与上下文差异: 如果两个任务需要的 System Prompt 冲突(例如一个需要极其严谨拒绝调侃,另一个需要风趣幽默),必须拆分。
    3. 按依赖的工具集(Tool Separation): 单个 LLM 面对超过 10 个工具时召回准确率大幅下降。将工具按职责分给不同的 Agent(如 DataAgent 拿 SQL 工具,ReportAgent 拿 Excel 生成工具)。
    4. 按 SOP 流程阶段(Phase-driven): 软件开发中,需求分析、代码编写、代码测试分属不同 Agent,通过明确的交付物(Artifacts)流转。

OpenAI Agents SDK 的 Handoffs 机制

MCP(Model Context Protocol) 标准化协议对Agent拆分的革命性

7. Skill 是什么?Auto-coder Skill 的工作流程是怎样的?

  • Skill(技能)的定义: 在 Agent 框架(如 Semantic Kernel 或 Dify)中,Skill 是对一组原子能力(API、代码脚本、大模型 Prompt)的封装。如果说 Tool 是原材料(如数据库连接器),Skill 就是一道半成品菜(如“根据表格自动生成周报的脚本”)。它让 Agent 能够以更高阶的抽象来执行任务。
  • Auto-coder Skill(自动编码技能)的工作流程:

[用户需求] ──> 1. 任务拆解与设计 ──> 2. 代码生成 (LLM) ──> 3. 本地沙箱执行 ──> [报错?] ──(是, 自我修复) ──> 4. Git 提交/交付

  1. Parse & Plan(解析与规划): 接收用户的自然语言需求(如“写一个快排”),分析当前工作区目录结构,生成修改计划。
  2. Code Generation(代码生成): 调用 CodeLLM(如 DeepSeek-Coder),结合现有的代码上下文,生成具体的代码片段或 Patch。
  3. Sandbox Execution(沙箱运行与测试): 将生成的代码写入隔离的沙箱环境(如 Docker 容器),自动运行本地测试命令(如 pytest 或 npm test)。
  4. Self-Correction(自我修复 Loop): 若测试报错,将 Stderr 错误日志反馈给 CodeLLM,由其重新理解并修改代码,直到测试通过(通常设置最大重试 3 次)。
  5. Artifact Delivery(交付): 最终将通过的代码通过 Git 提 PR 或直接写入本地文件。

8. Skill 的核心价值是什么?为什么会出现这个概念?

  • 核心价值:
    1. 提高 Agent 的成功率(Success Rate): 减少 LLM 的推理步长。直接调用一个定义完好的 Skill(如“一键导出 PDF”),比让模型自己用 Python 写代码去生成 PDF 要稳定得多。
    2. 能力的复用与沉淀: 开发者可以像开发基础库一样复用 Skill,形成企业内部的 Agent 资产库。
    3. 降低大模型调用的 Token 成本与延迟: 将复杂的 Prompt 逻辑固化为本地代码 Skill,极大释放了模型的上下文空间。
  • 为什么会出现这个概念:

早期人们发现,完全依赖大模型的 Zero-shot Tool Use 极其不可靠,模型经常传错参数、漏掉逻辑。工业界需要一种介于“完全硬编码”与“完全由大模型自主发挥”之间的中间态抽象,Skill 应运而生。它用确定性的工程代码封装复杂逻辑,暴露简单的自然语言接口给大模型,实现了确定性工程与不确定性 AI 的完美结合

在Semantic Kernel等框架中:

  • Tool = 单个函数调用(原子操作)

  • Skill = 一组相关Function的命名空间容器 + 可选的Prompt模板

9. 可插拔 RAG、一键配置切换,是不是热更新?

是的,这属于应用层和工程配置层的热更新(Hot Reload / Live Reload)。

  • 技术实现原理:

在服务不重启、不中断用户请求的前提下,通过动态加载机制改变系统行为。

    • 代码层面: 利用 Python 的 importlib.reload() 动态加载新的 RAG 检索策略类。
    • 配置层面(主流做法): 引入配置中心(如 Apollo, Nacos)或利用 Redis Pub/Sub。当用户在管理后台切换 RAG 配置(如从“单纯向量检索”切换为“混合检索 + Rerank”)时,配置中心下发变更通知,AI 服务的单例工厂对象(Factory)在内存中动态重构检索路由树,后续的请求直接走新的路由。
  • 设计原则: 必须保证无状态切换。正在处理的请求(In-flight Requests)应继续使用旧配置执行完毕,新到达的请求则路由至新配置(利用读写锁或并发安全的原子引用切换)。

2026年JAVA生成方案有: 配置中心(Nacos/Apollo)+ 本地缓存 + 监听器模式,如SpringAI + Nacos Prompt热更新

10. 工厂模式的优点是什么?

在 AI 应用开发中(尤其是面对层出不穷的 LLM 厂商和快速迭代的 RAG 组件),工厂模式(Factory Pattern)是解耦的金科玉律

  • 核心优点:
    1. 屏蔽底层复杂度,实现多模型/多组件无缝切换: 用户只需调用 LLMFactory.get_provider("deepseek"),无需关心底层对接的是 OpenAI SDK、LangChain 还是原生 HTTP 请求。
    2. 符合开闭原则(Open/Closed Principle): 当需要引入一个新的大模型(如接入腾讯混元)或新的向量数据库(如 Chroma 换成 Milvus)时,只需新建一个实现类并注册到工厂中,现有业务层代码零修改
    3. 便于集中式管理与统一注入: 可以在工厂实例化组件时,统一注入 API Key、超时重试策略、流式传输(Streaming)配置及监控埋点(如 OpenTelemetry 拦截器)。

11. 本地部署要考虑什么?配置管理放在哪里?

本地部署(On-Premise / 私有化部署)通常面向对数据隐私极度敏感的行业(政企、金融)。

  • 本地部署核心考量(Checklist):
    1. 算力与显存资源适配(Hardware Constraints): 评估显存(VRAM)是否足够。例如部署 DeepSeek-V3/R1 的量化版或 70B 模型,需要多少张 A800/H20 显卡?是否需要配置 vLLM / TensorRT-LLM 加速推理?
    2. 网络隔离(Air-Gapped Environment): 私有化环境通常无法连外网。所有的依赖包(HuggingFace 模型权重、Docker 镜像、Pip 包)必须做离线打包。
    3. 国产化适配(信创要求): 必须考虑华为昇腾(Ascend 910B)、海光等国产算力芯片的算子兼容性适配(如 Torch-NPU 的兼容问题)。
    4. 数据安全与审计: 敏感词过滤(Guardrails)、本地日志脱敏(PII 数据遮蔽)。
  • 配置管理放哪里:
    • 不能放云端配置中心: 严禁使用公有云的 Apollo 或 Nacos。
    • 标准方案: 采用本地 K8s ConfigMap + Secret(用于敏感凭证)进行管理。如果是单机部署,采用 .env 环境变量配合本地加密的本地配置服务(如 HashiCorp Vault 本地版,金融政企场景更常用国密SM4加密的国产方案)。

12. LangChain 和 LangGraph 的区别?

这是很多人容易混淆的点。它们是同胞兄弟,但设计哲学和适用场景完全不同。

  • LangChain:
    • 设计哲学: 线性与链式结构(Linear & Sequential)。核心是 Chain,强调一步接一步的顺序流。
    • 局限性: 极难处理循环(Loops)和状态回溯。如果在某一节点需要模型反复重试直到成功,LangChain 的代码会写成一团乱麻。
  • LangGraph:
    • 设计哲学: 基于图的多元状态编排(Graph-based, Cyclic Architecture)。它将应用抽象为节点(Nodes,代表工具、LLM)和边(Edges,代表路由条件),最重要的是支持有环图(Cycles)
    • 核心优势: 拥有内置的状态管理(State)和持久化机制(Checkpointer)。它完美契合 Agent 的 ReAct 模式、多步反思(Self-reflection)和需要人工介入(Human-in-the-loop)的复杂状态交互。

LangGraph已发展为可独立运行的框架,不依赖LangChain。LangChain的Agent实现反而构建在LangGraph之上

13. 第一个项目后台怎么搭建的?

回答此题需展现出结构化的工程思维(以一个标准的 RAG + Agent 智能客服/知识库系统为例):

  • 技术栈选型:
    • 后端框架: FastAPI(利用其天然支持异步 asyncio 和 SSE 流式响应,极度适合 LLM 场景)。
    • 大模型编排: LangGraph + 向量数据库 Milvus。
    • 离线数据流: Celery + Redis 处理大文件解析与 Embedding 异步切片。
  • 核心模块架构:
    1. Gateway(网关层): 处理 JWT 鉴权、流控(Rate Limiting)。
    2. Orchestration Layer(编排层): FastAPI 接收请求,交由 LangGraph 状态机驱动,决定走 RAG 检索还是 Tool Call。
    3. Streaming Channel(流式通道): 通过 SSE(Server-Sent Events) 协议将大模型生成的 Token 实时推给前端,提升用户体验(TTFT < 800ms,实际是1-3S)。
  • 亮点工程实践(高分项): 引入了双路并发设计
    用户提问进入后,一方面启动大模型做意图识别(意图识别不需要LLM:轻量级分类器BERT级即可,用LLM做意图识别是大炮打蚊子)与长对话压缩,另一方面并发去向量数据库检索 Top-K 背景,最后在合流节点组装 Prompt,有效降低了首字延迟。

14. 算法:最长有效括号

  • 核心理论: 这是一个典型的字符串处理问题,考察对栈(Stack)动态规划(DP)的掌握。
  • 高效解法(一次遍历,空间 $O(1)$ 法):

利用两个计数器 left 和 right,从左到右遍历一次,再从右到左遍历一次。

  • Python 代码实现:

def longestValidParentheses(s: str) -> int:
     left = right = max_len = 0
     # 正向遍历
     for char in s:
         if char == '(': left += 1
         else: right += 1
         if left == right:
             max_len = max(max_len, 2 * right)
         elif right > left:
             left = right = 0
            
     # 反向遍历(防止类似 "(()" 导致正向无法匹配的情况)
     left = right = 0
     for char in reversed(s):
         if char == '(': left += 1
         else: right += 1
         if left == right:
             max_len = max(max_len, 2 * left)
         elif left > right:
             left = right = 0
            
     return max_len

  • 工程意义: 在 AI 领域,该算法常用于大模型输出格式化校验。例如 LLM 在调用 Tool 时输出的 JSON 或括号表达式不闭合,可利用该算法思想快速定位并截取最大合法有效载荷(Payload)。LLM输出JSON不闭合的问题,实际用栈更直观,O(1)算法的双向遍历逻辑反而增加理解成本。

15. 算法:股票交易 (Best Time to Buy and Sell Stock)

  • 核心理论: 贪心思想或动态规划。
  • 高效解法(一次遍历):

记录历史最低价格 min_price,同时计算每天卖出能赚取的最大利润。

  • Python 代码实现:

from typing import List

def maxProfit(prices: List[int]) -> int:
     if not prices: return 0
     min_price = float('inf')
     max_profit = 0
    
     for price in prices:
         if price < min_price:
             min_price = price
         elif price - min_price > max_profit:
             max_profit = price - min_price
            
     return max_profit

  • 工程与 AI 落地结合: 该题在量化 AI Agent(AI Trading Agent)中是基础策略的数学底座。在训练强化学习(RL)策略网络时,此算法的计算结果常作为奖励函数(Reward Function)的基准线(Baseline),用来评估 Agent 决策的赚钱效应是否超越了理想市场极值。

AI应用开发一面·考察重点汇总说明

为了帮助您更高效地复盘和准备,现将上述题目所体现的面试官核心考察维度及高分要点梳理如下:

维度

对应题目

考察重点说明 (面试官在看什么)

得分/通关要点

LLM 记忆与状态管理

Q1, Q2, Q5

考察对大模型上下文限制(Context Window)的工程妥协能力,以及长短期记忆的架构设计。

能够清晰说出分层存储(Redis vs 向量库),并能提出防止信息失真的跨会话压缩/记忆衰减方案。

Agent 架构设计能力

Q3, Q4, Q6

考察面对复杂业务时,如何平衡模型的自主性(ReAct)与工程的确定性(FSM、多Agent拆分)。

重点强调为什么选择某种架构。指出单 Agent 的瓶颈(Prompt 污染),给出清晰的 Agent 划分依据

工程落地与中间件

Q7, Q8, Q12

考察对当前主流 AI 开源生态(LangChain, LangGraph)的理解深度,以及对高级概念(Skill)的抽象能力。

切忌生搬硬套名词。要能准确说出 LangChain(线性)与 LangGraph(有环图) 的本质区别。

企业级工程化经验

Q9, Q10, Q11, Q13

考察真实的生产环境落地能力,包括配置管理、高并发架构设计、设计模式解耦、私有化合规。

展现“硬工程”素养。提及无状态状态机、热更新下的读写锁安全、国产算力适配、SSE 流式响应延迟优化

数据结构与算法基础

Q14, Q15

考察基础编码能力与逻辑思维。大厂面试的硬性门槛。

代码不仅要写对,还要追求最优时空复杂度(如 $O(N)$ 时间,$O(1)$ 空间),并主动向 AI 场景结

posted on 2026-06-12 15:32  PetterLiu  阅读(1)  评论(0)    收藏  举报