面灵AI→

金蝶软件 AI 方向软件开发一面:AOP 顺序、混合检索与 Agent 记忆

轮次
一面
时间
2026-10
来源
牛客网

《面试题目》

  1. 绩点排名?本科期间有没有参与什么比较大型的比赛?
  2. AOP 的实现原理?AOP 与拦截器、过滤器的区别?要是有多个注解,怎么定义谁先执行?
  3. Agent 项目为什么采用混合检索?为什么不直接用向量检索?使用混合检索得分怎么处理?
  4. Agent 项目的滑动窗口 + 摘要压缩的会话记忆机制怎么实现的?摘要要是不准确怎么办?如果用户提问的问题在此前很久的会话中出现过,你怎么处理?
  5. 如果要把你这个知识库做成 Agent,你会怎么设计 Agent?
  6. 最近有没有接触什么 AI 工具?
  7. 反问:加班情况?公司业务及 AI 落地情况?校招带教机制?

《参考解析》

AOP 与过滤器、拦截器的区别,以及多注解的顺序

AOP 的实现原理是动态代理:Spring 容器在创建 bean 时判断是否需要增强,需要就生成代理对象——目标类实现了接口时默认用 JDK 动态代理(基于 InvocationHandler),否则用 CGLIB 生成子类(通过继承覆写方法实现增强)。调用代理方法时先执行通知链(@Before、@Around、@After、@AfterReturning、@AfterThrowing),再进入目标方法。要注意 JDK 17 与 Spring Boot 3 之后 CGLIB 也是默认选择之一,以及代理带来的限制:同类内部自调用不经过代理,所以 @Transactional、@Cacheable 这类注解会失效。

三者的层次与能力不同:过滤器(Filter)在 Servlet 容器层面,基于函数回调,能拿到原始的 ServletRequest/ServletResponse,可以改写请求体与响应、做编码与跨域,作用于所有进入容器的请求(包括静态资源);拦截器(Interceptor)在 Spring MVC 层面,基于反射,能拿到 handler 与 ModelAndView,可以访问 Spring 容器里的 bean,但拿不到请求体(流已被包装)也管不到容器级行为;AOP 更靠内,作用在 bean 方法调用上,不限于 Web 请求,能拦到 service 层的任意方法。执行顺序上,请求进入时是 Filter → Interceptor 的 preHandle → AOP 通知 → Controller,返回时逆序。

多个注解(多个切面)的执行顺序由 @Order/Ordered 接口控制,值越小优先级越高;对「进入」方向的通知而言优先级高的先执行,对「退出」方向的通知则相反。同一类里多个通知的相对顺序按 @Around → @Before → 方法 → @After → @AfterReturning/@AfterThrowing;没有显式声明顺序时,Spring 的排序不确定,所以工程上必须显式给 @Order。要顺带说清一个实践细节:@Order 对同一 @Aspect 内的多个通知不生效,需要拆成多个切面或改用编程式顺序控制。

混合检索:为什么要它、得分怎么融合

单一向量检索的问题是语义召回强但精确匹配弱:产品型号、错误码、人名、专有缩写这类「必须精确命中」的词,向量相似度会把它们模糊掉;反过来纯关键词检索(BM25)对同义改写与语义泛化无能为力。所以混合检索的动机是让两路互补,实践中对「有专有名词、编号、短查询」的场景提升很明显。得分融合主要有几种做法:一是加权求和,把两路分数归一化后加权(归一化很关键,因为余弦相似度与 BM25 分数量纲完全不同,常用 min-max 或按排名归一化);二是倒数排名融合(RRF),只用排名不用分数,score = Σ 1/(k + rank),k 通常取 60,好处是对量纲不敏感、实现简单且稳健,是很多系统的默认选择;三是先各自召回再用交叉编码器 rerank,把相关性判断交给模型。回答时要主动说出取舍:加权求和需要调参且不同查询的最优权重不同,RRF 免调参但丢掉了分数信息,rerank 效果最好但成本高、只能对 Top-K 做。评测要用真实查询集看召回率与最终答案质量,而不是只看分数好看。

会话记忆:滑动窗口 + 摘要压缩的实现与失效处理

机制要讲成三层:最近若干轮保留原文(保证细节与指代可解析)、更早的对话按段做摘要(控制 token)、再久远的内容落到可检索的长期记忆(向量库或结构化字段)。实现细节包括:摘要的触发条件(按 token 数或轮数)、分段粒度(按对话段或主题切)、摘要 prompt 要保留什么(事实、结论、未解决的待办、用户偏好)、以及摘要的存储位置(会话元数据里带版本,便于回溯原文)。

「摘要不准确怎么办」是这题的核心追问。可答的处理有三条:一是把不可被改写的信息从自然语言里拿出来——用户画像、订单号、权限、待办事项这类结构化状态单独存字段并每轮拼进 prompt,不指望摘要保留;二是摘要要带引用(由哪几轮压缩而来),发现回答不对时可以回查原文核对并重建;三是给用户可见与可纠正的入口,比如展示「我记得的这些信息」让用户改,同时保留原始消息不被删除(只是不进 prompt)。工程上还要做一致性校验:用一组问题问摘要后的上下文,检查关键事实是否还在。

「很久之前的会话再次被问到」正好是长期记忆的用法:不要把全部历史塞进窗口,而是把当前问题在历史消息与摘要上做检索(检索范围包括历史原文的向量索引),召回相关片段后再拼进上下文;同时按时间衰减加权(越近越重要)、按会话/主题过滤避免串话。可以提一句取舍:检索会漏(没召回就等于没记住),所以对必须记住的实体(用户设定的偏好、身份、长期目标)走结构化存储而不是检索。

把知识库做成 Agent 该怎么设计

答题要区分「问答」与「Agent」:知识库问答是「检索 → 生成」,Agent 是「为达成目标自主决定调用哪些能力」。设计上按五块讲。一是能力清单:检索知识库、查询业务数据库、调用外部 API、执行代码/计算、写入工单——每个能力都要有明确的输入输出契约与权限边界,模型只能调用清单内的工具。二是规划与执行:先让模型产出计划(可审查的步骤列表),再逐步执行;用 ReAct 或 Plan-and-Execute 都可以,但必须限制最大步数、时长与成本,并给失败回退。三是记忆:短期是本轮对话与中间结果,长期是用户偏好与历史任务,结构化的部分放字段、非结构化的走检索。四是校验与可控:关键动作(写数据、对外发送)要二次确认,结果要能引用来源,输出要有置信度或「不知道」的出口。五是可观测:全链路 trace(每一步用了什么工具、参数、耗时、结果),加上离线评测集与线上指标(任务完成率、人工介入率、平均步数、成本)。如果能结合金蝶的业务语境(企业软件、财务与 ERP 数据),可以补一句「企业场景里权限与审计是硬约束,Agent 的每个数据访问都要按用户身份做行级过滤」,这会让回答从通用方案落到岗位实际。

AI 工具、绩点与反问

「最近接触什么 AI 工具」不要罗列名称,讲清你的工作流:写代码与重构用什么、查资料与读文档用什么、什么环节必须自己验证,再举一个具体的提效案例。绩点与竞赛属于背景核实,如实回答即可;绩点不突出就把重心引到项目与动手能力上,用可验证的产出说话。三个反问都很到位:加班情况(判断实际工作强度,可以追问是否常态化、有没有补休)、业务与 AI 落地情况(判断这个 AI 方向是核心投入还是试点,问法可以是「目前哪些产品线已经有 AI 能力上线、效果怎么衡量」)、校招带教机制(是否有导师、培养周期、以及新人多久能独立负责模块)。这些问题问完,基本能判断这个岗位值不值得去。