灵犀互娱 AI 应用开发秋招:记忆层、RAG 评估与 Agent 编排
- 时间
- 2026-09
- 来源
- 牛客网
《面试题目》
- 传统的 Agent 设计里,记忆层应该怎么设计?
- 怎么解决大模型的幻觉问题?
- 如何评估 RAG 系统的效果?需要达到什么标准才能上线?
- Spring Boot 中的配置文件有哪些?
- RAG 系统包含哪些核心模块?
- 关键字召回和向量召回的分数怎么融合?除了 RRF 融合还有哪些方法?
- Agent 的终止条件怎么设置?如何避免陷入死循环?
- Agent 需要调用很多工具时,应该如何设计?
- Agent 的规划器和执行器应该如何解耦?
《参考解析》
记忆层怎么分层:不能理解成「把所有历史消息拼进 Prompt」,那会遇上上下文过长、成本过高、历史污染和注意力下降。合理的分层是:短期记忆(当前任务的对话、工具结果、中间状态)、长期记忆(用户偏好、历史结论、稳定事实)、工作记忆(已完成的步骤、待执行步骤、关键变量)、语义记忆(向量检索相关的历史信息)、程序记忆(固定流程、工具使用规则、业务约束)。落地时短期记忆放 Redis 或状态存储,长期记忆放关系型库 + 向量库。关键纪律是「不写入全量」:对话结束后要经过摘要、去重、重要性判断和敏感信息过滤再决定是否落长期记忆。长期记忆还要有失效机制——临时偏好设 TTL,用户明确改过的信息覆盖旧值,可能变化的事实不能永久当真实数据用。
幻觉治理:无法靠单一 Prompt 消除,只能多层降低。数据层做知识库清洗、去重和版本管理;检索层合理切分文档、用关键词 + 向量的混合检索、加重排序模型;生成层要求只基于检索内容作答、强制标注引用来源、找不到依据时明确说”当前资料无法确认”;后处理层做规则校验或二次模型审查,关键业务用结构化输出加程序侧校验,高风险结果进人工审核。必须清醒的是 Prompt 约束只是最后一道防线——金额、时间、权限、库存这类数据,最终应由后端程序或数据库确认,不能完全信任模型输出。
RAG 评估与上线门槛:评估至少分三层。检索层看 Recall(正确文档是否召回)、Precision(有没有大量无关内容)、MRR(正确文档的排名)、NDCG(不同相关度的排序质量)、Context Recall(回答所需信息是否被检索出来)。生成层看答案是否正确、是否严格基于检索内容、有无无依据扩展、是否完整、引用是否准确、语言是否合规。系统层看平均与 P95 响应时间、Token 消耗与单次成本、并发与限流、文档更新后的生效延迟、失败率超时率与降级情况、敏感信息泄露概率。上线前必须建一套含标准答案和标准文档的数据集,覆盖事实查询、跨文档推理、歧义问题、无答案问题和长问题。一个比较实际的门槛是:核心问题召回率达到目标、关键业务问答不出现严重事实错误、无依据回答比例低于阈值、高峰并发下仍满足响应时间要求。
Spring Boot 配置文件:application.properties / application.yml、application-{profile}.yml、外部配置文件、环境变量、JVM 启动参数、命令行参数、配置中心的远程配置。优先级上命令行参数、环境变量、外部配置高于包内配置。多环境用 Profile 切换(dev 指向本地服务、prod 指向内网地址和更短超时);敏感值如 API Key、数据库密码绝不提交 Git,用 ${LLM_API_KEY} 这类环境变量注入。成组的层次化配置用 @ConfigurationProperties 统一管理,比在业务代码里到处 @Value 更好维护,也便于做集中校验。
RAG 核心模块:数据接入 → 文档解析 → 内容清洗 → 元数据提取 → 文本切分 → 向量化 → 索引存储 → 查询改写 → 召回 → 重排序 → 上下文组装 → 模型生成 → 效果评估。理解的关键是把它看成两条链路:离线索引链路负责把原始文档变成可检索的索引,在线查询链路负责把用户问题变成有依据的回答。两条链路的共同约束是元数据——它既决定过滤条件,也决定版本隔离与权限边界。
关键字与向量分数融合:两者分数量纲不同,不能直接相加。主流做法有三类:① 加权归一化后线性融合,各自 min-max 或 z-score 归一化再加权,简单但依赖分数分布;② RRF(Reciprocal Rank Fusion),只看排名不看分数,score = Σ 1/(k + rank),k 通常取 60,好处是对不同检索器的分数量纲不敏感、鲁棒;③ 学习式融合,把两路特征(各自分数、排名、命中词数、文档长度等)喂给一个 LTR 模型或交叉编码器重排,效果上限最高但要标注数据。此外还有级联策略:关键词召回做硬过滤(如权限、时间、类目)+ 向量召回做语义补充,或反之。
终止条件与防死循环:终止条件要显式建模,而不是靠模型「觉得可以了」。常见几类:任务完成判定(必备产物是否齐全、验收条件是否满足)、步数上限、时间/Token/成本预算、连续无进展检测(连续 N 步没有产生新的状态变更或新信息)、重复动作检测(同一工具同一参数重复调用超过阈值)。防死循环的关键是「状态必须有真实推进」——每一步都要记录状态快照,如果新状态与旧状态等价,就该停或换策略。陷入循环时的兜底是升级:换更小的子任务、请求人工介入,或返回当前已有结论并说明未完成的部分。
工具很多时怎么设计:不要让几十个无关工具一次性暴露给模型——Schema 本身就吃掉大量 token,还会让选择准确率下降。做法是先做工具路由:用户问题 → 意图识别 → 工具域选择 → 只加载该领域的工具 → 参数生成 → 执行。同时统一工具返回格式(success / data / errorCode / message),让模型不用解析各厂商风格的文本错误信息;工具结果尽量结构化、控制体积;对高风险工具要求人工确认;调用层设超时、重试和熔断。工具之间要有依赖声明,不能只写在描述里。
规划器与执行器解耦:规划器决定下一步做什么,执行器负责真正执行,两者不能混在一起。规划器的输入是当前目标、历史消息、任务状态、已执行步骤、可用工具列表、工具执行结果和约束权限;输出是一个结构化动作(类型、工具名、参数、预期状态变化)。执行器只认这个结构,负责校验前置状态、执行、记录回执。解耦带来的好处是可测试、可重放、可替换——换规划模型不影响执行器,换执行环境也不影响规划逻辑;同时中间过程可以落库,崩溃后能从最近一次成功状态恢复。