面灵AI→

恒生电子 AI 面试 AI 应用开发岗:二十七问全记录

时间
2026-09
来源
牛客网

《面试题目》

  1. 先做个自我介绍,重点聊一下你是怎么理解这个岗位的。
  2. 你平时最常用的 AI 编码工具是什么?
  3. 谈谈你对 Python 装饰器的理解,它的核心作用是什么?举一个你在项目中实际使用的场景。
  4. 如果要给一个带位置参数、关键字参数和返回值的业务函数加统计执行耗时的装饰器,你会怎么处理参数传递和返回值透传?
  5. Python 中用来实现装饰器时能自动保留被装饰函数源信息(函数名、文档字符串)的标准库装饰器是什么?
  6. 创建联合索引时字段的放置顺序,会不会影响查询效率?为什么?
  7. 如果有一个联合索引 (a,b,c),查询条件是 b=1 and c=2,这个查询能用到这个联合索引吗?
  8. 联合索引在 B+ 树中存储时,是按照什么规则组织键值顺序、从而支撑最左匹配特性的?
  9. 让大模型稳定输出结构化数据(如 JSON)是常见需求,但模型有时会输出多余解释文字或格式不合法,你会用哪些手段提升结构化输出的稳定性和可解析性?
  10. 如果提示词里已明确要求只输出 JSON,但模型依然在前后附带自然语言说明,你会怎么处理?
  11. 模型输出的 JSON 本身存在转义错误、括号不匹配这类语法问题,导致正则也无法准确截取合法片段,你会怎么处理?
  12. RAG、传统检索+生成、微调三种方案的本质区别是什么?分别在什么场景下选用?
  13. 企业内部有大量表述差异但高度相关的文档(比如不同部门对同一业务流程的不同口径记录),传统检索加生成会出现什么核心问题?
  14. 微调会从根本上改变大模型的哪些固有能力边界?
  15. 你在开发 AI Agent 的过程中总结过哪些常用的设计模式?分别适合解决什么类型的问题?
  16. 如果遇到需要动态调整全局目标、初始计划很快失效的开放场景,你会选择哪种模式组合?
  17. 执行每一步之后通过反思判断是否需要重规划,你怎么设计反思环节的判定标准,避免大模型频繁无意义地推翻原有计划、导致执行效率极低?
  18. 请分享一个你做过的最具技术挑战的大模型应用项目:它要解决什么问题,核心难点在哪,你又是如何攻克的?
  19. 你们当时是怎么测量并确认知识库支撑下的回答准确性不达标的?
  20. 最初测召回时 20 条召回结果里会漏掉正确的文档片段,你们是怎么一步步排查定位出漏召根本原因的?
  21. 在优化切分策略的过程中,有没有出现过你原本判断有效的调整方案、实测后发现效果不达预期被推翻的情况?
  22. 优化切分后召回率提升了,你们最终怎么判断整个客服系统的回答效果是真的变好了,而不只是召回指标好看?
  23. 为了降低 TTFT 替换了模型并做了 KV 缓存优化,在平衡响应速度、回答准确性、调用成本这三者时,你们做了哪些关键取舍?
  24. 请聊一个你熟悉或自研的 AI 应用框架:它的核心是为了解决什么问题,实现上有哪些技术巧思,你在什么场景里真正用它落地过?
  25. 你用点和边的图结构替代了原有的链式调用,那这个框架里最核心的节点抽象具体是怎么设计的?
  26. 所有节点都围绕共享 state 做读写,这种全局共享状态相比每个节点独立传参的朴素实现,实际带来了哪些额外代价?
  27. 你实际用这个框架落地工作流编排时,遇到过最棘手的一个和它设计特性相关的坑是什么?

《参考解析》

装饰器与 functools.wraps:装饰器本质是「接收函数、返回函数」的高阶函数,核心作用是在不改动业务代码的前提下增强功能(日志、计时、鉴权、重试、缓存)。参数透传的标准写法是 def wrapper(*args, **kwargs): return func(*args, **kwargs)——*args 接位置参数、**kwargs 接关键字参数,返回值直接 return 出去,这样任意签名都能透传。第 5 问的答案是 functools.wraps:不加它,被装饰函数的 __name__、__doc__、__module__ 会变成 wrapper 的,日志和文档全乱;@functools.wraps(func) 会把元信息拷回 wrapper。如果还需要保留原函数签名给类型检查器用,可以再叠加 functools.lru_cache 或 inspect.signature 的 __wrapped__ 机制。

联合索引与最左匹配:字段顺序会影响效率——联合索引 (a,b,c) 在 B+ 树里是按 a 先排序、a 相同再按 b、再按 c 组织键值的,所以只有从最左列开始的连续前缀才能用于定位。WHERE b=1 AND c=2 用不上这个索引去定位(第一列 a 没有约束,无法确定搜索起点),但可能走「索引扫描」——把整个索引树扫一遍做过滤,性能远差于范围定位,实际效果等同于没有。推论是等值条件的列放前面、范围条件的列放后面,区分度高的列尽量靠前(但也要看查询模式)。

结构化输出稳定性:分四层做。① 请求层:用厂商的原生结构化输出能力(如 JSON mode / tool calling / response schema),优先于在 Prompt 里写”请只输出 JSON”;② 提示层:给出 schema 和示例,明确”不要解释”,但清楚这只是软约束;③ 解析层:不要用贪婪正则去抠——先做括号配平扫描、或用一个容错的 JSON 解析器(如 json5 / partial-json)从第一个 { 开始尝试解析;对于转义错误、括号不匹配,可以配合括号计数与字符串状态机逐步修复,或调用一次轻量模型做”只做格式修复、不许改内容”的规范化。④ 校验层:解析成功后必须过 schema 校验(必填字段、枚举、类型、数值范围),失败就把具体错误字段回给模型,限制修复轮数,仍失败就降级到人工或返回结构化错误。

RAG / 传统检索+生成 / 微调的区别:传统检索+生成靠词面匹配召回(BM25 一类),优点是精确、可控、可解释,缺点是不懂同义与语义;RAG 在检索层引入向量语义召回,并可用重排与查询改写,解决”表述不同但语义相关”的问题,知识更新只需重建索引、不用重训模型;微调改变的是模型自身的参数化知识、输出风格与指令遵循能力,它不能可靠地注入频繁变化的事实知识(会遗忘、难更新、难以溯源)。选型顺序一般是:先做 Prompt 工程和 RAG 优化,都不够才考虑微调;微调适合固定领域术语、固定输出格式、需要低延迟的窄任务。

Agent 设计模式:常见的有 ReAct(思考-行动-观察循环,适合探索型)、Plan-and-Execute(先规划后执行,适合可拆解的大型任务)、Reflection(自我批评后重试,适合可校验的任务,如代码、数学)、Tool Routing(先意图分类再加载对应工具集,适合工具很多)、Multi-Agent 协作(角色分工 + 仲裁,适合多视角任务)、以及 Human-in-the-loop(高风险动作人工确认)。开放场景下初始计划容易失效,通常用「Plan-and-Execute 外层 + ReAct 内层」:外层维持全局目标并周期性重规划,内层在子任务里灵活应对不确定性。

反思环节的判定标准:关键是给”重规划”设门槛,而不是让模型凭感觉推翻计划。可用的判据:① 硬失败——工具报错、校验不通过、前置条件缺失;② 进展停滞——连续 N 步状态没有实质变化(快照对比等价);③ 证据冲突——新观察与已有结论矛盾且新证据可信度更高;④ 预算超限——剩余步数/时间不足以按原计划完成。同时限制重规划次数上限,并要求重规划必须给出”哪些步骤作废、哪些可复用”的差异说明。记录每次重规划的原因,事后可以量化”重规划带来的收益”,把无效重规划的模式收敛掉。

知识库项目怎么答:面试官会沿着”怎么发现问题 → 怎么定位原因 → 怎么验证有效”这条线追问。答法要落到具体动作:先用一批黄金问答对测准确率,人工核对答案找出错在哪一层(召回没给到 / 给了但排序靠后 / 排序对了但模型没用 / 模型用了但表述错);召回漏文档时逐个 badcase 看切分边界、查询表述、元数据过滤是不是元凶;改进后用同一套评估集对比 Recall@K、MRR、答案引用准确率和无依据回答比例,而不是只看召回率一个数。取舍类问题(速度 vs 准确 vs 成本)要讲清换来了什么、牺牲了什么、以及为什么这个业务能接受。

自研框架的图结构设计:用点和边替代链式调用的核心收益是支持条件分支、并行与回环。节点抽象通常包括:名称、输入状态读取器、执行函数、输出状态写入器、以及路由/条件边。代价也很实在——① 全局共享 state 让节点之间的耦合变得隐性,谁改了哪个字段难以追踪,调试困难;② 并发写同一个 state 需要冲突解决策略(归并器);③ 序列化与持久化 state 才能实现断点续跑,对状态的大小和可序列化性提出要求;④ 全局可变状态难做单测,必须为每个节点单独构造完整上下文。最常踩的坑是「状态膨胀」:节点不断往共享 state 里塞中间产物,最后 context 爆掉、序列化变慢——解法是给 state 定义明确的 schema、限制字段类型、把大对象放外部存储只留引用。