华为 AI 技术应用一面:Harness 设计、记忆模块与两道手撕
- 轮次
- 一面
- 结果
- 一面通过
- 时间
- 2026-10
- 来源
- 牛客网
《面试题目》
- Agent 开发中的 Harness 是怎么设计的?
- 记忆模块是怎么做的?
- 实习的产出是什么?
- 实习中遇到的问题和技术选型是怎么考虑的?
- 一些 Redis 相关的八股。
- 手撕:一道非 hot100 的 hard 题。
- 手撕:一道非 hot100 的 mid 题(字符串排列)。
《参考解析》
Harness 怎么设计:让不确定的模型跑在确定的轨道上
Harness 这一层要解决的问题是「把模型的一次输出变成可复现、可控的工程执行」,可以按六个部件讲。上下文装配:系统指令、工具说明、历史消息、检索结果与记忆都按 token 预算排队,超出时按优先级裁剪,约束和当前任务状态必须常驻;工具注册与调用循环:工具要有 schema 化的参数定义,服务端校验参数、控制超时、把错误结构化地回给模型让它重试,而不是抛异常直接终止整个流程;控制流:最大步数、终止条件、循环检测(同样的工具加同样的参数连续出现就该打断)、以及需要人工确认的挂起点;状态与持久化:会话状态机落库,支持断点续跑,长任务中途失败不用从头开始;可观测:每一步的输入、输出、token 消耗、耗时、工具调用结果都留痕,能按会话回放,出问题能定位是提示词、工具还是模型的问题;安全边界:工具白名单、权限校验、沙箱与审计,越权在服务端拒绝。
真正拉开差距的是那几个容易被忽视的点:工具报错要设计成「模型能理解的错误」而不是堆栈;模型的输出一律按不可信数据处理,过 schema 校验再用;对高风险动作准备确定性的兜底路径(固定工作流或规则),不要指望模型每次都判断对。一句话总结这层价值:模型负责判断,Harness 负责边界、状态和可观测,二者分开才谈得上生产可用。
记忆模块:写、存、取、忘四个环节
记忆按生命周期分三层,答的时候分开说才不会乱。短期记忆是当前会话的上下文管理:消息窗口滚动、把长历史压缩成摘要、把用户偏好和硬约束常驻;压缩要注意保留「结论和约束」而不是逐句摘要,否则多轮之后关键信息会丢。长期记忆是跨会话的事实与偏好,核心在写入侧的质量:从对话里抽取结构化事实(属性、值、时间、来源),做去重与冲突消解(同一属性冲突按时间新近度或来源可信度裁决,不要无脑追加),写入最好是异步的并且可撤销,避免把一次口误永久写进档案。存储上通常不是单一向量库,而是「关系库存结构与原文 + 向量库存语义索引」,需要关系推理时再加图;检索上用混合检索——向量召回加关键词召回,叠加元数据过滤(用户、时间、权限)后做 rerank 精排,并显式带上时间戳和出处,让模型知道这条记忆有多旧。遗忘是很多人漏掉的一环:要有 TTL、要有合并与清理策略,还要有租户与用户之间的硬隔离,否则记忆库会越用越脏,检索精度持续下降。程序性记忆是第三层,也就是把流程与方法固化成的 Skill 或规则,按需加载。
被追问「为什么非要用向量库」时要能答出边界:几千条以内用倒排检索甚至全量塞进上下文都够用,上向量库是为了在数据量和延迟约束下做近似最近邻,代价是召回率下降与内存成本,所以要配合关键词路与精排兜底。
技术选型与实习产出:讲约束、对比和反思
选型题的模板是「约束 → 候选 → 对比维度 → 结论 → 什么条件下会改选」。约束先摆清楚:数据规模、延迟要求、预算、团队是否熟悉、上线时间。对比维度固定几个就够用:功能是否满足、性能与延迟、成本、运维复杂度、生态与可迁移性。举一个能自圆其说的例子:向量检索在小规模时用数据库自带的向量扩展就够,百万级再上专用向量库,因为专用库带来的运维成本在数据量没起来之前不划算;状态管理是用自研状态机还是工作流引擎,取决于流程是否频繁变更、要不要可视化与人工审批。关键是把「结论是有条件的」说出来,面试官最怕听到的是「因为它性能好」。
产出要讲可验证的东西:上线了哪些能力、覆盖多少用户或请求、指标怎么变(准确率、人工介入率、延迟、成本),以及如果重做会改什么——最后这句最能体现反思深度。被问「遇到的问题」时给一个具体故障:现象、排查路径、根因、修复方式,以及怎么防止复发(补监控、加兜底、写进回归用例)。有真实数字就带数字,没有数字就说清当时的判断依据,不要把「感觉快了很多」当结论。
Redis 八股与两道手撕
Redis 这块的常见追问可以按一条线串起来:为什么快(纯内存、单线程避免锁竞争与上下文切换、IO 多路复用、高效的数据结构编码);持久化(RDB 快照靠 fork 加写时复制,AOF 有三档 fsync 策略、需要重写压缩、现在常用混合持久化);过期与淘汰(惰性删除加定期抽样,内存满了走 maxmemory-policy);缓存三大问题(穿透用空值缓存或布隆过滤器,击穿用互斥重建,雪崩用随机过期与多级缓存);分布式锁的坑(SET NX PX 加 Lua 校验持有者再删、业务超时与锁续期、以及 Redlock 的争议)。八股部分短答即可,答不准的边界要主动说清。
手撕部分是这轮的重点。那道 hard 题作者当时的思路是二分加贪心,这类「二分答案 + 贪心判定」的通用套路是:先确定答案具有单调性(答案变大时可行性单调变化),再二分答案,check 里用贪心在 O(n) 或 O(n log n) 内验证可行性,整体 O(n log C)。即使最优解写不出来,也要把「暴力解法 → 复杂度 → 瓶颈在哪 → 优化方向 → 正确性为什么成立」讲完整,面试官往往就在这一步给分,作者也提到思路说对了、面试官还给了提示。字符串排列是典型的回溯题:输入字符无重复时可以在原数组上交换生成全排列,有重复时必须去重——先排序,同层跳过相同字符,或者用 used 数组加剪枝,复杂度是 O(n×n!)。写之前先确认题意:是要求输出所有排列,还是判断一个串是不是另一个串的排列——后者用字符计数数组一遍扫完就是 O(n),别一上来就写全排列。这类手撕的共性是先把题意与输入范围问清,再动手。