Skip to content

口述稿

这份和 01-04 项目答辩稿的区别

01-04要点式的,用来复习「我到底做了什么」。这一份是口语式的,用来直接照着说:断句、短句、(停顿)标记都是故意的。写成书面语,说出来就会像背课文——面试官一听就知道你在背。

怎么练这份稿

  • 掐表。 30 秒版说到 45 秒就是失败,说明信息塞太多了,要砍,不要说快。
  • 录音回听,只听三件事:有没有「呃、然后、就是说」;有没有哪句话超过 25 个字;最重要的信息有没有出现在前 10 秒。
  • 先给结论再给过程。 面试官的注意力只有开头十几秒是满的,第一句必须是落点。
  • 数字位置全是 <待核实> 练的时候读你核实后的真值;确实查不到的,按 11-数字口径待核实 §3 的降级说法读,不要现场即兴编。
  • 准备「可以画图」的版本。 手边有笔就主动画架构图。画图能让面试官从「审问模式」切到「讨论模式」,是整场里性价比最高的一个动作。

0. 一条主线

所有讲述都挂在这一句上:

前端出身,为了把项目做完整补齐了后端,现在专做 Agent;每一步都是往「让模型真正落地干活」那一层靠。

阶段时间一句话概括面试官应该听到的信号
前端2019.07-2022.04 品茗安控工程行业 Web 端,复杂表单、图表、交互界面和交互是我的老本行,不是短板
全栈2022.06-2025.03 掌奇网络企业应用,前后端都写,接口、权限、实时通信、交付我知道一个系统从数据库到页面怎么串起来
Agent2024.11 起(政务助手)→ 2025.04-2026.06 亿达LangGraph、RAG、Tool Calling、Multi-Agent,四个项目落地现在的主业是 Agent,前面两段是它的地基

别把主线讲成「被动跳槽」

错误说法:「后来公司要做 AI,就让我去做了。」 正确说法:「我是主动往这个方向走的——先是发现前端拿不到系统的全貌,所以补后端;后来发现 Agent 这套东西正好卡在我熟的两头之间,既要写异步后端,又要做流式交互,所以我把主力放到这儿。」

1. 自我介绍

30 秒版(电话初筛)

面试官好,我叫项思哲,2019 年物联网工程本科毕业,到现在工作七年。(停顿)

前面四年多做前端和企业应用开发,最近一年多在亿达做 AI 应用,用 Python 加 LangGraph 落地了三个 Agent 项目:企业知识库 RAG、BI 智能问数,还有一个多 Agent 的智能客服平台。(停顿)

我现在的定位就是 Python Agent 开发——从检索链路、Agent 编排,到前端的流式交互,我一个人能打通。目前已经离职,可以随时到岗。

电话初筛的三个必达信息

一是七年经验 + 现在专做 Agent;二是具体项目类型(对方要判断你是不是只会 Demo);三是到岗时间。其他一句都别多说,等对方问。

1 分钟版(HR 或技术面开场)

面试官好,我叫项思哲,杭州,2019 年太原科技大学物联网工程本科毕业。(停顿)

我的路径大概是三段。毕业头三年在品茗安控做前端,做工程行业的 Web 系统,大量复杂表单和数据可视化,这段让我对交互和前后端协作比较熟。

2022 年到掌奇做企业应用开发,前后端都写,开始自己设计接口、做权限、做实时通信;也是在这家公司后期第一次做 AI 项目——一个政务 AI 助手,用 LangGraph 做多子图问答,模型在内网部署。(停顿)

2025 年 4 月到亿达就完全转到 Agent 方向了,一年多做了三个项目:一个多 Agent 的智能客服平台,一个 BI 智能问数,最后是企业知识库 RAG。技术栈主要是 Python、FastAPI、LangGraph、PostgreSQL 加 pgvector 这一套。(停顿)

所以我现在找的就是 Python Agent 开发的岗位。我一个比较明显的特点是前端出身,Agent 产品那套流式界面我自己就能做,不用等前端排期。目前已经离职,随时可以到岗。

3 分钟版(技术面详版)

面试官好,我叫项思哲,2019 年毕业,物联网工程专业,现在在杭州,工作七年。我大概按三段讲,最后落在这一年多在做的 Agent 上。(停顿)

第一段是前端,2019 到 2022 年,在品茗安控。 做建筑工程行业的 Web 系统,React 加 TypeScript,特点是表单特别复杂、图表特别多。这段给我留下两个东西:一个是我对交互细节比较敏感,什么样的界面用户会用不下去,我大概有感觉;另一个是我很习惯跟后端对协议——字段该谁给、状态该谁维护、错误怎么返回,这些事我从那时候就在吵。(停顿)

第二段是全栈,2022 到 2025 年,在掌奇网络,岗位是企业应用开发。 我从只写前端变成前后端都写,自己设计接口和数据模型,做权限体系,做 WebSocket 实时推送,也管交付。到 2024 年底公司接了一个区里的政务 AI 项目,我开始做 AI 助手,这是我第一个 Agent 项目:用 LangGraph 做「入口路由加三个领域子图」,办事指南、政策解读、公文辅助各一个;检索是 Elasticsearch 的 BM25 加 pgvector 双路召回,RRF 融合再过 Reranker;因为是政务内网,用 vLLM 部署了 DeepSeek-R1。(停顿)做完这个项目我基本确定要转这个方向。

第三段就是 Agent,2025 年 4 月到 2026 年 6 月,在亿达做 AI 应用和 Agent 开发,一共三个项目。

第一个是智能客服的 Multi-Agent 平台,做了大半年。架构是主 Agent 加领域子 Agent,主 Agent 负责意图识别和路由,下面按商品、订单、物流、售后、投诉分开,业务动作全部封装成 Tool,用 ReAct 加 Tool Calling 编排。这个项目最花精力的不是让它跑通,是让它不敢乱动手——工具按风险分只读和敏感两级,退款、投诉升级、提工单都要人工确认,也就是 HITL,能暂停、能恢复、超时自动关。(停顿)

第二个是 BI 智能问数,把自然语言问题变成 SQL 再出图。用 LangGraph 排了「意图识别 → Schema Linking → SQL 生成 → 规则校验 → 执行 → 结果分析」这条状态图。难点是防字段幻觉和防危险 SQL:我把表结构、字段别名、指标定义做成一个元数据知识库,生成前把可用字段和指标口径注入进去,生成后再做一层规则校验——只读语句、表和字段白名单、字段存在性、结果行数上限、执行超时。

第三个是企业知识库 RAG,是我最近做的。FastAPI 加 pgvector,入库用 Redis 加 ARQ 拆成「解析 → 分块 → 向量化 → 入库」四步异步跑,权限做到知识库级 RBAC 并且下推到检索的过滤条件里,回答统一带文档、页码和 chunk 引用,证据不够就拒答。(停顿)

所以我现在的定位是 Python Agent 开发。 往下我最熟的是 LangGraph 这套编排、RAG 的检索链路和异步后端;往上我能自己把流式界面做出来,SSE 那一层前后端我都写过,协议是我自己定的。目前已经离职,可以随时到岗。

把「前端出身 + 物联网专业」讲成优势的三个抓手

  1. 懂交互:Agent 产品的体验坑基本都在前端——流式要不要打字机效果、工具调用中间态怎么展示、引用怎么点开跳原文。这些我不用别人教。
  2. 能做流式界面:SSE 的事件协议是我自己定的,前端消费、断流重连、Markdown 增量渲染我都踩过。小团队里这等于省掉一次前后端联调排期。
  3. 能对齐协议:做过前端,知道后端返回什么结构前端最难受,所以我设计的事件和错误结构比较克制。物联网专业给的是另一半——设备、网络、超时重试那套东西,跟 Agent 的工具调用容错其实是一个思路。

不要说的话:「我前端出身,后端可能不如专业后端」「我是自学转过来的,基础可能不牢」。自我贬低换不来同情,只会换来一个「基础存疑」的标签。

2. 四个项目的口述稿

三档怎么选

  • 30 秒版:面试官说「简单介绍下你的项目」,或者你要在一堆项目里做串讲。
  • 2 分钟版:最常用的一档。对方说「讲讲这个项目」,默认给这个长度,然后停下来等他提问。
  • 5 分钟版:对方明确说「详细讲讲」,或者这个项目正好是他们的业务方向。讲完主动收口:「这块要不要我展开哪一段?」

不要一上来就用 5 分钟版。 讲太长会剥夺面试官提问的机会,他会觉得你不看场合。

项目一 · 企业知识库 RAG Agent(2026.04-2026.06,亿达)

详细版见 01-项目-企业知识库RAG

30 秒版

这个是企业内部的知识库问答。公司的制度、方案、项目资料散在各处,格式有 PDF、Word、纯文本,人找起来慢,找到了也说不清出处。(停顿)

我做的是 FastAPI 加 pgvector 这一套:文档异步入库,检索按知识库做权限隔离,回答一定带文档名、页码和 chunk 引用,证据不足就直接拒答,不硬答。我负责后端和检索链路,从数据模型一直到 SSE 流式输出。

2 分钟版

背景是这样:公司内部资料很多,制度、项目方案、业务文档,格式很杂,分散在不同地方。大家找东西靠问同事或者翻共享盘,慢,而且拿到一个答案也不知道出处,不敢用。(停顿)我们要做的是一个统一入口:文档扔进来,能检索、能问答,答案要能溯源。

技术上有三块我花的时间最多。

第一块是入库。文档解析加向量化很慢,大文件几十兆,不能放在 HTTP 请求里做。我用 Redis 加 ARQ 拆成「解析 → 分块 → Embedding → 入库」四个任务,每一步都落状态,失败能单独重试。用户上传完立刻拿到文档 ID 和处理中状态,通过 SSE 看进度。(停顿)

第二块是权限。企业知识库最怕跨库召回——A 部门的人问一句话,检索把 B 部门的文档捞出来了。所以权限不能只在 API 层挡,要下推到检索的过滤条件里:知识库 ID、文档状态、是否已删除,全都是向量查询的 where 条件。上层是 JWT 加知识库级 RBAC,区分看、问、写三种权限。

第三块是引用溯源。链路是「问题理解 → 证据召回 → 答案生成」,生成时要求模型只能用召回到的 chunk,返回结构里带文档、页码和 chunk ID,前端能点开定位原文。召回为空或者证据明显不够,走拒答分支转人工。(停顿)

效果上我们建了 <待核实> 条问题加标准答案的评测集,Recall@5 大概 <待核实>,主要用来对比切分策略和检索策略的迭代;人工查资料的时间从 <待核实> 降到 <待核实>

5 分钟版(可以画图)

先说背景和痛点。 公司内部的制度文件、项目方案、业务资料,量不小,格式是 PDF、DOCX、TXT 混着来,分散在共享盘和各个业务系统里。真实痛点有两个:一个是找不到,新人问一个报销流程要问三个人;另一个更麻烦——就算找到了,也不知道这是哪一版文件,敢不敢照着做。(停顿)所以目标不只是「能搜」,是「能问,而且答案带出处」。

技术难点我认为是三个:慢、串、和不敢答。 慢是入库慢,一个几十兆的 PDF 解析加向量化要几分钟;串是权限串库,不同部门的知识库不能互相召回;不敢答是溯源,没有出处的答案在企业场景里等于没用。(停顿)

我的方案。(这里可以画图)整体是 FastAPI 加 PostgreSQL,向量走 pgvector,文件存 MinIO,异步任务用 Redis 加 ARQ。

数据模型我设计了知识库、文档、分块、会话、权限这几张表,SQLAlchemy 加 Alembic 管迁移。分块表上除了向量,还存文档 ID、页码、章节路径和状态——溯源和权限过滤都靠这几个字段。

入库是一条流水线:上传只做落盘和建记录,立刻返回;后面 ARQ 按「解析 → 分块 → Embedding → 入库」跑,每步更新文档状态,失败的步骤能重试而不用整个文档重来,进度通过 SSE 推给前端。

检索链路是「问题理解 → 证据召回 → 答案生成」。召回用 pgvector,过滤条件强制带上当前用户可见的知识库 ID、文档启用状态和未删除标记。生成阶段限定模型只能引用召回到的内容,输出里带文档、页码、chunk ID。(停顿)

有三个关键决策我想说一下。

第一,权限下推到查询条件,而不是查完再过滤。 查完再过滤有两个问题:一是 top-k 会被无权限的文档占掉名额,实际召回质量下降;二是漏一个地方就是数据泄露。所以我宁可让向量查询带过滤条件,哪怕近似索引在带过滤时召回率会打折,也接受。

第二,没有引入独立的向量数据库,直接用 pgvector。 原因很直接:我们的量级还在单库能扛的范围内,而权限、文档状态这些过滤条件都在 PG 里,用外部向量库就要处理两套数据的一致性——文档删了向量没删,这种 bug 排起来很痛。如果规模再上一个数量级、或者要多租户分片,我会重新评估 Qdrant。

第三,宁可拒答。 召回为空、或者证据明显不支撑,直接说找不到并给转人工入口,不允许模型用通用知识补一段看起来很合理的答案。企业场景里,一次自信的错答比十次「没找到」代价大得多。(停顿)

结果。 系统支撑了 <待核实> 个知识库、<待核实> 份文档、<待核实> 个分块的统一管理。评测集 <待核实> 条,Recall@5 <待核实>,引用完整性 <待核实>。这套评测主要的用处不是对外报数,是让我们改切分策略、改 top-k 的时候知道是变好还是变坏了。业务侧反馈是人工查资料时间从 <待核实> 降到 <待核实>。(停顿)

反思两点。 一个是切分策略我一开始想简单了:最早按固定长度切,结果表格和条款被切断,召回回来的片段读不通,答案就飘。后来改成按标题层级加语义边界切,并保留章节路径,才稳定下来。这件事教给我的是:RAG 的效果问题,一半以上根子在解析和切分,不在检索算法。

另一个是评测集建得太晚。前期靠人工「感觉这次好像好一点」判断,白改了几版。如果重来,我会先建 30 条 golden set 再动手调参数。

项目二 · BI 智能数据分析 Agent(2025.11-2026.04,亿达)

详细版见 02-项目-BI数据分析Agent

30 秒版

这个是 BI 的自助问数。业务同事想看数据要提需求给数据组排期,来回好几天,而且不同人算同一个指标口径还不一样。(停顿)

我用 LangGraph 排了一条状态图:意图识别、Schema Linking、SQL 生成、规则校验、执行、结果分析。核心是两件事——不让模型编字段,不让危险 SQL 跑到库上。出口是表格加图表,中间状态用 SSE 推给前端。

2 分钟版

背景是业务方要数据得走人工取数,运营、销售、产品都在排队,数据组一半时间在写重复的 SQL。(停顿)我们要做的是让业务同事直接用中文问,系统出 SQL、出数、出图。

这个场景真正的难点不是把 SQL 生成出来,是让它可控。 两个方向。

一是不让模型编字段和编口径。 我建了一个 BI 元数据知识库:表结构、字段别名、指标定义都进去,MySQL 存权威源,Qdrant 存语义向量,Elasticsearch 做关键词匹配。用户问「上个月华东的销售额」,先做 Schema Linking——把「销售额」映射到指标定义,「华东」映射到维度值,然后只把召回到的这几张表、这几个字段注入 Prompt,其他的模型看不到,也就编不出来。(停顿)

二是 SQL 安全。 我在生成后加了一层纯规则的校验,不靠模型自己检查:必须是只读语句,表和字段要在白名单里,字段必须真实存在,结果行数有上限,执行有超时。任何一条不过就不执行,返回能读懂的错误,允许有限次重试。

还有一类情况是问题本身不完整——没说时间范围、没说统计口径。这时候不猜,走澄清分支反问一句,问清楚再往下走。(停顿)

整条链路用 LangGraph 是因为它的状态是显式的:中间的 SQL、校验结果、错误原因都在 State 里,某个节点失败可以从那儿恢复,不用整轮重来。

效果上我们做了 <待核实> 条评测样例,覆盖单表、多表 JOIN、时间范围和 TopN 几类,SQL 生成准确率 <待核实>,人工取数占比从 <待核实> 降到 <待核实>

5 分钟版(可以画图)

背景和痛点。 公司的数据在几个系统里,业务方要看数只能提需求,数据组排期。一个「上个月华东各渠道成交额环比」这种问题,走流程可能两三天。(停顿)更烦的是口径不统一:销售额算不算退款、算不算税,不同人写的 SQL 不一样,两份报表对不上,最后要开会对口径。所以这个项目解决的其实是两件事:取数慢,和口径乱。

技术难点。 Text2SQL 这个方向 Demo 很容易,上生产很难,难在三个地方:字段幻觉——模型会编一个看起来很合理但不存在的字段;口径漂移——同一个指标每次生成的算法不一样;以及安全——生成的 SQL 直接打到业务库上,一条没有条件的全表扫描就能把库拖慢。(停顿)

我的方案。(这里可以画图)主链路是 LangGraph 的一张状态图:意图识别 → Schema Linking → SQL 生成 → 规则校验 → 执行 → 结果分析。每个节点的产物都写回 State,所以任何一步失败我都知道它带着什么上下文失败的。

Schema Linking 这层是重点。元数据拆成三份存:MySQL 存权威定义,表、字段、指标公式、合法维度值;Qdrant 存字段和指标描述的向量,用来处理「成交额」「销售额」「GMV」这种同义表达;Elasticsearch 做关键词和别名的精确匹配。检索完只把相关的表和字段注入 Prompt,同时把指标的计算口径一起注入。

SQL 安全做成生成前和生成后两道。生成前是约束注入:可用表、可用字段、指标公式、时间字段是哪个,全部写进 Prompt。生成后是纯代码校验:只读语句检查、表和字段白名单、字段存在性、结果行数上限、执行超时。这一层我坚持不用模型做——校验必须是确定性的,不能是概率的。(停顿)

关键决策三个。

第一,校验用规则不用模型。 让模型审自己写的 SQL,它会说没问题。规则校验虽然笨,但可复现、可测试、可解释。

第二,信息缺失就澄清,不猜。 早期版本会自己补一个默认时间范围,结果用户拿到数不知道是哪段时间的,反而更危险。改成缺关键条件就反问一句,宁可多一轮交互。

第三,指标口径配置化,不进 Prompt 的自由发挥区。 指标公式是从元数据库里读出来注入的,不是让模型自己理解「销售额」该怎么算。这是解决口径乱的关键——同一个指标,永远走同一个公式。(停顿)

结果。 覆盖 <待核实> 个部门的日常取数,<待核实> 条评测样例上 SQL 生成准确率 <待核实>,平均响应 <待核实>,人工取数占比从 <待核实> 降到 <待核实>。前端这边我用 NestJS 做 BFF,SSE 推执行状态,结果给表格、图表、分析摘要和下钻入口。(停顿)

反思。 一个是多表 JOIN 的准确率明显低于单表,这是这类系统的普遍现象。后来的思路是不追求让模型一次搞定复杂 JOIN,而是把常用关联关系预先建成视图或语义层,让模型只在受限的表上做选择。做得还不够彻底。

另一个是准确率这个指标本身不够用。SQL 跑通了不代表答对了——口径选错、时间边界差一天,SQL 是合法的但结论是错的。所以后期我加了结果一致性检查,但更好的做法应该是分层评测:语法通过率、执行成功率、结果一致率分开看。

项目三 · 企业智能客服 Multi-Agent 平台(2025.04-2025.11,亿达)

详细版见 03-项目-智能客服MultiAgent

30 秒版

这个是企业客服的 Multi-Agent 平台,覆盖售前咨询、订单查询、售后、投诉和退款审批。(停顿)

架构是主 Agent 加领域子 Agent,主 Agent 做意图识别和路由,业务动作封装成 Tool,用 ReAct 加 Tool Calling 编排。我在里面花最多精力的是可控性:工具按风险分级,退款和投诉升级这类操作必须走人工确认,所有路由、调用、审批都有审计日志。

2 分钟版

背景是客服的入口很分散:咨询走一个系统,查订单走另一个,退款要提工单。客服人员要在几个系统之间来回切,新人培训周期长,回答口径也不统一。(停顿)我们做的是一个统一的 Agent 入口。

架构上是主 Agent 加领域子 Agent。 主 Agent 只做三件事:意图识别、任务拆解、条件路由。下面按商品、订单、物流、售后、投诉分成几个子 Agent,每个只带自己那套工具和 Prompt。拆开的原因是:所有工具都挂在一个 Agent 上,工具一多模型就开始乱选,而且任何一个业务改动都要动同一个 Prompt。分开之后,改售后不影响订单。(停顿)

业务能力全部封装成 Tool,用 ReAct 加 Tool Calling。 订单接口、CRM、工单系统都包成标准 Tool,入参用 Pydantic 定 schema 做校验。工具失败按错误类型分开处理:网络类的重试,业务类的直接返回可读原因,连续失败就转人工,不让它一直试。

然后是我认为这个项目最关键的部分——不让它乱动手。 工具按风险分成只读和敏感两级。查询类的随便调;写入类的,比如退款、投诉升级、提工单,一律要幂等控制加人工确认。(停顿)HITL 是用 LangGraph 的中断加 Checkpoint 做的:走到敏感节点就停下来,把待确认的动作和参数摆给人看,人点确认才恢复执行,超时就自动关掉这一轮。

会话记忆放在 Redis,知识类问题接知识库 RAG,前端通过 SSE 看到每个阶段的事件。证据不足、路由不确定、或者多次调用失败,就拒答转人工。(停顿)

效果上工具调用成功率 <待核实>,任务完成率 <待核实>,日均 <待核实> 次会话,转人工率从 <待核实> 降到 <待核实>

5 分钟版(可以画图)

背景和痛点。 企业客服场景其实是两类问题混在一起:一类是问答,产品怎么用、政策是什么;另一类是要真的动手做事,查订单、催物流、提工单、走退款。(停顿)原来的做法是入口分散,客服在几个系统之间切换,而且第二类需求纯问答机器人根本接不住——它只能告诉你「请联系客服」。所以我们要做的是一个既能答、又能干活、但干活必须可控的东西。

技术难点我认为有三个。 第一是路由:意图判断错了,后面全错。第二是工具调用的可靠性:模型会漏参数、会用错工具、会在失败后反复重试同一个调用。第三,也是最关键的——高风险操作不能让模型自己拍板,退款金额填错一位,这是真金白银的事故。(停顿)

我的方案。(这里可以画图)LangGraph 编排,主 Agent 加领域子 Agent 的结构。

主 Agent 的 State 很薄,只保留意图、用户身份和最终结果。各个子 Agent 的检索证据、工具中间结果留在自己的子图里,不往上冒。这样主图的上下文不会被子任务细节撑爆,也避免一个子 Agent 的中间状态污染另一个的判断。

子 Agent 内部是 ReAct 循环加 Tool Calling。工具定义用 Pydantic 生成 JSON Schema,参数校验在执行前做,校验失败把结构化错误喂回模型让它改,而不是直接抛异常。循环有最大步数上限,防止它在两个工具之间来回打转。(停顿)

风险控制是分级的:只读工具直接执行;敏感工具——退款、投诉升级、工单提交——三件事必须有:幂等键、超时、人工确认。HITL 是 LangGraph 的中断加 Checkpoint:到节点前把执行意图和参数落盘并暂停,前端渲染成一个确认卡片,人确认后从 Checkpoint 恢复,超时就关闭这一轮并记录原因。(停顿)

关键决策。

第一,按业务域拆子 Agent,而不是按工具数量拆。 判断标准是「这组工具会不会被同一个意图同时用到」,同一个意图要用的放一起,不然跨子图来回传参更麻烦。

第二,人工确认做在工具执行前,不做在事后审核。 事后审核意味着钱已经出去了,所以我宁可让流程多一步、慢一点。

第三,失败要分类,不能笼统重试。 我把工具错误分成可重试(超时、限流、网络)和不可重试(参数非法、订单不存在、权限不足)。后者重试一百次也一样,直接返回原因或者转人工。这个分类做完之后,无效重试少了很多。(停顿)

结果。 统一了售前咨询、订单查询、售后处理、投诉和退款审批的入口,日均 <待核实> 次会话,工具调用成功率 <待核实>,任务完成率 <待核实>,转人工率从 <待核实> 降到 <待核实>。另外每一次路由、工具调用、参数校验、人工确认和转人工原因都有日志,能按工具维度做回归分析。(停顿)

反思。 一个是早期我把太多决策交给了模型。最开始连「这个操作要不要人工确认」都想让模型判断,结果它有时候觉得小额退款不用确认。后来改成规则硬编码:哪些工具属于敏感级是配置死的,模型没有话语权。这件事让我形成一个原则——能用规则确定的,不要交给模型

另一个是任务完成率这个指标当时定义得比较粗。用户中途放弃、用户自己要求转人工、系统兜底转人工,这几种一开始都算「未完成」,导致这个数看不出问题到底在哪,后来才拆开统计。这也是我现在做任何 Agent 都会先想清楚评测口径的原因。

项目四 · AI 政务助手(2024.11-2025.03,掌奇)

详细版见 04-项目-AI政务助手。这是第一个 Agent 项目,也是解释「为什么转方向」的锚点

30 秒版

这是给区里政务和数据管理部门做的本地化 AI 平台,试点了三类应用:办事指南问答、政策解读、公文辅助。(停顿)

用 LangGraph 做「入口路由加三个领域子图」,检索是 Elasticsearch 的 BM25 加 pgvector 双路,RRF 融合之后过 Reranker。因为是政务内网,模型用 vLLM 部署的 DeepSeek-R1,全程不出网。

2 分钟版

背景是政务场景:群众来问办事要带什么材料,工作人员要查政策、要写公文。(停顿)这些信息都在办事指南、政策法规和公文模板里,但政策会更新、会失效,引用错一条已经废止的政策,后果比答不上来严重得多。所以这个项目的核心约束是两条:不能出网,不能答错。

架构上是一个主图加三个子图。 主图只管意图路由、用户权限和最终结果;办事指南、政策解读、公文辅助各是一个子图,各自维护自己的检索证据和中间状态,用条件边做路由、澄清、重试和人工兜底。三类场景的检索策略和输出格式差别很大,放一个图里 Prompt 会打架,所以拆开。(停顿)

检索是双路加融合。 政务的查询有个特点:一半是口语化的自然语言问题,一半是精确的政策名称和文件编号。纯向量检索对后者不行——文号这种东西语义上没有区分度,必须靠关键词。所以我做了 Elasticsearch 的 BM25 加 pgvector 的向量双路召回,RRF 融合,再过一遍 Reranker 精排,返回时带文件、条款和来源位置。(停顿)

然后是我觉得这个项目最重要的一条设计:把确定性规则和模型推理分开。 代码负责事项字段校验、政策有效期过滤、公文格式检查和权限控制;模型只负责意图识别、查询改写、政策解读和文本生成。政策有没有失效,这是查数据库能确定的事,绝对不能让模型「判断」。置信度低或者引用不足就拒答转人工。(停顿)

部署上模型用 vLLM 在内网跑 DeepSeek-R1,Redis 管会话和热点结果,有模型超时、节点重试、最大循环次数和结构化降级,SSE 输出节点事件。评测集 <待核实> 条覆盖三类场景,办事指南回答准确率 <待核实>,政策引用完整率 <待核实>

5 分钟版(可以画图)

背景和痛点。 这是区级政务和数据管理部门的项目,要解决三个场景:群众咨询办事流程——带什么材料、去哪个窗口、几个工作日;工作人员查政策——某条规定现在还有效吗、适用范围是什么;以及公文辅助——按规范起草初稿。(停顿)原来靠人工翻文件。政务文件的特点是量大、层级深、而且会更新,一个工作人员不可能记住所有政策的最新版本。

技术难点有三个,而且都很硬。 第一,数据不能出网,政务内网,所有模型推理必须本地。第二,答错的代价极高,引用一条已废止的政策,或者把办事材料说少了一项,群众白跑一趟。第三,查询形态混杂:既有「办身份证要带什么」这种口语问题,也有「浙政办发〔某某〕XX 号」这种精确检索。(停顿)

我的方案。(这里可以画图)编排上是 LangGraph 的主图加三个子图。主图很薄,只有意图、用户权限、最终结果这几个字段;办事指南、政策解读、公文辅助三个子图各自维护检索证据和中间状态。拆的理由很实际:三类场景要的检索策略不一样——办事指南要的是结构化字段,政策解读要的是条款级定位,公文辅助要的是模板和格式规则。混在一张图里,Prompt 和 State 都会失控。

知识入库这条线,我做了版面解析、层级切分和元数据标注。元数据这块是政务场景的关键:文件版本、发布部门、效力范围、发布日期、条款位置全部要留,因为政策更新之后要能增量重建,还要能把失效的过滤掉。(停顿)

检索是 BM25 加向量双路,RRF 融合,再 Rerank 精排。另外按查询类型动态选策略:口语化的问题走 Multi-Query 改写,明确指向某个文件或条款的走过滤检索,不浪费在语义召回上。

部署上用 vLLM 在内网起 DeepSeek-R1,Redis 管会话和热点结果缓存。稳定性上设了模型超时、节点重试、最大循环次数和结构化降级,SSE 推节点事件,检索、生成、引用、异常的轨迹都记日志。(停顿)

关键决策。

第一,确定性的事交给代码,不交给模型。 政策有效期过滤、事项字段校验、公文格式检查、权限控制,全部是规则;模型只做意图识别、查询改写、解读和生成。这条线划清之后,「引用了失效政策」这类事故就从概率问题变成了可测试的问题。

第二,双路召回不是为了好看,是因为单路真的不够。 我可以举具体例子:用户搜文号,向量检索会给你一堆语义相似但文号不对的文件;用户问口语问题,BM25 又完全抓不住。这两类查询在政务里都是高频,所以必须双路。RRF 的好处是只看排名不看分数,两路的分数尺度完全不同也能融。

第三,宁可拒答并转人工。 政务场景的容错比商业场景低一个量级,引用不足或者置信度低,就明确告诉用户「建议咨询窗口」,并给出可能相关的文件让他自己判断。(停顿)

结果。 三类场景一共 <待核实> 条评测集,分别统计意图路由准确率、Recall@K、引用完整率和任务完成率。办事指南回答准确率 <待核实>,政策引用完整率 <待核实>,常规的政策解读和公文初稿处理时间从 <待核实> 缩到 <待核实>。(停顿)

反思。 一个是内网私有化部署的成本我一开始低估了。没有外网就没有 pip 直装、没有模型热更新,显卡资源也是固定的,很多在公网环境里理所当然的做法都要重新设计。这段经历的价值是让我知道「能不能私有化」是个架构级问题,不是部署阶段的事。

另一个是推理模型不等于好用的编排模型。DeepSeek-R1 的推理能力强,但它会输出很长的思考过程,对结构化输出和工具调用的配合并不友好,我们要额外做思考内容剥离和 JSON 校验重试。如果重来,我会在链路里区分「需要推理的节点」和「需要稳定结构化输出的节点」,分别用不同的模型。

3. 技术亮点的三段式讲法

面试官问「你觉得你做过最有技术含量的一点是什么」,两分钟之内讲完,用这个结构:

第三段最容易被跳过,但最加分。 只讲方案好,听起来像在念文档;主动说出代价,面试官才会相信你真做过并且想清楚了。

范例一 · LangGraph 子图的状态隔离

问题。 客服平台里主 Agent 下面挂了五个领域子 Agent。最早我用的是一个大 State,所有子 Agent 读写同一份。(停顿)结果两个问题:一个是上下文越跑越大,售后子 Agent 的中间结果会跟着传到订单子 Agent 里去,token 花在没用的地方;另一个更麻烦——一个子 Agent 写进 State 的中间判断,会影响另一个子 Agent 的决策,出了问题很难定位是谁污染的。

我怎么解。 我把状态分了两层。主图的 State 只留必须跨子图共享的东西:用户身份、当前意图、最终结果,就这么几个字段。每个子图有自己的私有 State,检索到的证据、工具的中间返回、重试次数都留在里面,只在出口把结构化的结论往上抛。(停顿)LangGraph 这块的机制是子图和父图通过重叠的 key 交换数据,key 不重叠的就是私有的,所以做隔离其实是设计 State 的字段边界,不是加什么额外机制。

代价。 两个。一是调试变麻烦了——不能只 dump 一份 State 就看全貌,得逐层看,所以我在日志里给每个子图的进出都打了结构化事件。二是有些跨子图的信息要显式传两次,比如用户在前面对话里说过订单号,子图之间不共享的话就得由主图捞出来再往下发。这个我认为值得——边界清晰带来的可维护性,比省几行传参代码重要

原理见 agent-langgraphagent-multi-agent

范例二 · RRF 混合检索

问题。 政务助手里用户的查询是两种极端混在一起的。一种是「换身份证要带什么材料」,口语、没有关键词;另一种是「浙政办发某某号文件第三条」,精确到文号和条款。(停顿)纯向量检索处理第一种很好,处理第二种非常差——文号在语义空间里几乎没有区分度,它会给你一堆「看起来很像政策文件」但文号不对的东西。反过来 BM25 处理第二种很准,第一种基本抓不到。

我怎么解。 两路并行召回:Elasticsearch 走 BM25,pgvector 走向量,然后用 RRF 融合。RRF 的做法是不看两边的原始分数,只看各自的排名,把每个文档在两个列表里的排名倒数加起来重新排序。(停顿)这一点很关键:BM25 的分数和余弦相似度完全不是一个量纲,要归一化就得调参,而且换个语料分布就失效,用排名就绕开了这个问题。融合之后取前面一批,再过一个 Reranker 做精排,最后留少数几条进 Prompt。

代价。 三个。一是多了一套系统:要维护 Elasticsearch,中文还得配分词器,索引要跟向量库保持同步;二是延迟增加,双路加 Rerank,Reranker 是 cross-encoder,几十条候选就要过一遍模型;三是RRF 的 k 值和两路权重是要调的,不是白送的效果。(停顿)我们接受这个代价,因为政务场景里「文号查不到」是不可接受的功能缺陷,不是体验问题。

原理见 rag-retrieval

范例三 · HITL 的敏感操作确认

问题。 客服 Agent 要能真的执行动作,包括退款、投诉升级、提工单。但模型有概率填错参数——退款金额多一个零,或者把订单号取成了上一轮对话里的那个。(停顿)这类错误在纯问答场景里只是答错,在这里是真实的资金和客诉事故。而且它发生概率不高,恰恰因为不高,你没法靠测试兜住,只能靠机制。

我怎么解。 把工具按风险分级,只读的和敏感的分开,敏感工具在执行前必须过人工确认。实现上用 LangGraph 的中断加 Checkpoint:走到敏感节点前,把「我准备调哪个工具、参数是什么、影响是什么」写进 Checkpoint 并暂停整个图;(停顿)前端把它渲染成一张确认卡片,人点确认之后从 Checkpoint 恢复继续执行,超时没人处理就关闭这一轮并记录原因。另外写入类工具都带幂等键,防止确认之后网络抖动导致重复提交。

代价。 两个,都是真实的代价。一是流程变慢,敏感操作从秒级变成取决于人什么时候点确认,这直接影响体验指标。二是需要有状态的持久化——Checkpoint 要落库,要处理「人一小时后才来点确认」这种情况,会话状态不能只放内存,重启之后必须还能恢复。(停顿)但这个取舍在我看来没得选:慢一点可以解释,钱错了不能解释。

原理见 agent-tool-calling

4. 非技术问题的口语答案

先说一句

下面给的是结构和措辞,不是事实。离职原因、职业规划这几条必须和你的真实情况对齐再背,措辞可以借,事实不能编——这类问题面试官会在后面换个角度再问一遍,两次说得不一样就麻了。

「为什么从上一家离职?」

主要是项目节奏的原因。我在亿达一年多,三个 Agent 项目是连着做的,到 2026 年 6 月知识库这个项目交付之后,手上这条线算是告一段落了。(停顿)

我自己的想法是想找一个 Agent 方向更明确、能长期做下去的团队。前面这一年多我做的项目类型跨度比较大——客服、BI、知识库,好处是各种场景都碰过,但也意味着每个方向都是做到能用就交付了,没有机会往深里做。我更希望下一段能在一个方向上待久一点,把评测、优化、线上迭代这一整套跑完整。目前已经离职,所以到岗时间上完全没有限制。

三条铁律

  1. 不抱怨前公司:不说加班多、不说领导不行、不说技术栈落后。一句抱怨会让面试官默认「他到我们这儿也会这么说我们」。
  2. 不说钱:即使是真实原因也不要作为第一个理由说出来,放到 HR 谈薪环节再谈。
  3. 给一个向前的理由:离职原因要指向「我想去做什么」,不是「我不想忍什么」。

如果被追问「已经离职多久了,这段时间在做什么」:

大概 <待核实> 个月。这段时间我主要做两件事:一是把前面几个项目做的东西系统整理了一遍,特别是 RAG 的评测和 LangGraph 的编排这两块,之前是边做边学,现在补了一遍原理;二是在集中看 Agent 方向的机会,我不想随便找一个能上手的岗位就去。(停顿)手上也写了些东西验证想法,比如 MCP 那套协议我自己搭过 server 和 client 跑通。

「为什么想做 Agent 方向?」

说实话是做完第一个 AI 项目之后才确定的。(停顿)2024 年底我做那个政务助手,第一次用 LangGraph 把一条链路排出来。那时候有个很直接的感受:这个东西跟我原来做的业务系统不一样——原来是我写死所有分支,现在是我要设计一个「让模型在受限空间里做决策」的结构。有意思的地方不在调 Prompt,在于怎么划模型和代码的边界。

另一个原因是这个方向正好卡在我熟的两头之间。往后是异步后端、检索、数据库,这些我这几年一直在做;往前是流式交互界面,这是我前端出身的老本行。(停顿)Agent 应用恰好两头都要,而且两头都不能只会一点。我觉得这是我的优势能被用上的位置。

「你的职业规划是什么?」

短期一年,我想把一个方向做到「能对结果负责」的程度。具体说就是不只把功能实现出来,而是能对线上的准确率、失败率、延迟这些指标负责,知道数掉了该去哪儿查。(停顿)

中期两三年,我希望往 Agent 应用的架构上走:一条链路怎么拆、哪些交给模型哪些必须代码兜住、评测体系怎么建、出问题怎么定位——这套判断力我现在有一部分,但还不够系统。

我不太想的是只做 Prompt 调优或者只做模型侧。我的判断是这个行业里真正稀缺的是「能把 Agent 稳定落到业务里」的人:模型能力还会一直涨,但怎么把它变成一个不出事的系统,这个问题不会自动解决。

「你做过最有挑战的一件事是什么?」

用一个具体故事,不要讲「我克服了很多困难」。

我印象最深的是政务项目里的检索效果调优。(停顿)上线试点之前,有一类问题一直答不好:用户拿着文件名或者文号来查,系统给的是一堆语义相似但根本不是那个文件的东西。

一开始我以为是 Embedding 模型的问题,换了两个模型,没用。(停顿)后来我把召回的中间结果打出来一条条看,才发现问题在向量检索本身——文号这种字符串在语义空间里没有区分度,模型认为「浙政办发某某号」和「浙政办发另一号」几乎一样。这不是模型不够好,是这条路走不通。定位清楚之后方案就明确了:加一路 BM25,用 RRF 融合,改完之后这类问题基本解决。(停顿)

这件事对我最大的价值不是学会了混合检索,是学会了先看中间结果再动手。我前面换模型花了两天,如果一开始就把召回列表打出来看,半小时就能定位。现在我做任何 RAG 或 Agent 的排查,第一步一定是把链路每一步的输入输出都打出来。

「和同事有技术分歧怎么处理?」

我一般先分清这是哪一类分歧。(停顿)

如果是能验证的,就别吵,跑个实验。比如做 BI 那个项目时,我和同事对要不要让模型自己校验 SQL 有分歧,他觉得模型能看出问题,我觉得不行。我们就挑了几十条有问题的 SQL 让模型审一遍,结果它漏掉了大部分。数据出来之后就没有争论了,直接改成规则校验。

如果是没法当场验证的,比如架构选型,我的做法是把两个方案的代价列出来,特别是「选错了之后要付什么代价、多久能改回来」。(停顿)很多分歧其实不是谁对谁错,是双方在优化不同的东西——他在优化开发速度,我在优化后期可维护性。把这个说清楚,通常就能找到一个都能接受的点。

还有一种情况是对方比我更了解业务背景,那我会先按他的方案走。我做过前端,很清楚有些「不合理」的设计背后是有历史原因的。

「说说你的不足。」

这题的正确形态

选一个真实的、不影响岗位胜任力的、并且你已经在补的弱项。不要说「我太追求完美」这种假答案,也不要说「我算法不行」这种直接踩岗位要求的。

比较明显的一个是我的算法和模型底层比较薄。我是应用层出身,Embedding 模型的原理、Reranker 的训练这些我知道怎么用、知道怎么选,但要我去微调一个模型,我目前做不了。(停顿)我现在的处理方式是承认这条边界:涉及模型侧的事我会去找懂的人,不硬着头皮上;同时在补基础,最近在系统看检索和评测这块。

另一个是我以前太依赖「先做出来再说」。前端出身可能有这个习惯——先做个能看的东西,再迭代。但在 Agent 项目上这个习惯吃过亏:知识库那个项目评测集建得太晚,前期调参数全靠感觉,白改了几版。现在我会先定评测口径再动手,这个改变是被坑出来的。

5. 反问面试官的问题清单

反问的目的有两个

一是判断这个团队值不值得去,二是用问题证明你是内行。好的反问比多答一道题加分。挑 3 个问,不要连珠炮。薪资、加班、几轮面试这些留给 HR,不要在技术面问。

技术类

  1. 你们现在 Agent 链路的效果是怎么评的?有固定的评测集吗,还是主要看线上反馈和用户投诉?
  2. 线上的失败率大概在什么水平?主要失败类型是哪几类——工具调用失败、检索没召回,还是生成不符合要求?
  3. 高风险的动作有没有人工兜底的闭环?兜底之后那批 case 会不会回流进评测集?
  4. 模型是走 API 还是私有化部署?如果模型要换版本,回归验证是怎么做的?
  5. Prompt 和工具定义现在怎么管——跟代码一起版本化,还是在后台配置化?改一个 Prompt 需要发版吗?

为什么这几个问题显得内行

因为它们问的都是上过生产才会关心的事。只做过 Demo 的人会问「你们用什么模型」;上过生产的人问评测、失败率、回归和兜底。

团队类

  1. 团队现在的分工是怎么切的?按业务线切,还是分成 Agent 平台层和应用层?
  2. 这个岗位进来是接手已有系统的迭代,还是从头做新场景?
  3. 流式界面这块是有专门的前端,还是 Agent 开发自己做?(我这边前端能自己写,想确认一下边界)
  4. Agent 这种输出不确定的东西,你们的上线流程和回归是怎么做的?有灰度或者影子流量吗?
  5. 团队里有做模型侧的人吗?应用层碰到「这个得微调才能解」的问题时,一般怎么处理?

业务类

  1. 目前哪几个场景是真的在线上跑、有稳定用户量的?大概什么量级?
  2. 业务方对这套东西的核心期待是降本还是提效?他们考核的指标是什么?
  3. 这个方向在公司内部现在是探索性项目,还是已经进了商业化路径?
  4. 数据合规这块要求高吗?有没有必须内网、必须私有化的场景?
  5. 接下来半年,最想解决但还没解决的问题是什么?(这个问题几乎总能问出真实痛点)

6. 把书面语换成口语

练稿时如果说出来别扭,大概率是用了书面语。对照着换:

别说(书面语)改说(口语)
对检索链路进行了优化我把切分改成按标题层级切,改完召回明显稳了
赋能业务方自助分析让业务同事自己就能查数,不用再排队提需求
实现了业务闭环从上传文档到回答带引用,整条路能走通
基于 FastAPI 技术栈构建后端是用 FastAPI 写的
显著提升了准确率<待核实> 提到 <待核实>
深度参与了核心模块这一块是我写的 / 我负责从数据模型到 SSE 输出这一段
负责整体架构设计这条链路的设计是我出的,前端可视化是同事做的
充分利用大模型的能力模型只负责意图识别和生成,剩下的我用代码兜住
经过多维度综合考量主要看两点:一是不能出网,二是删了文档向量得同步删掉
沉淀了可复用的方法论后面两个项目我都是先建评测集再动手的

最后一条提醒

「我们」和「我」要分清。 讲方案用「我们」没问题,但讲到具体实现,面试官想听的是「我」。如果整场都是「我们做了」「我们实现了」,最后一定会被问一句「那你具体负责什么?」——这句话出现,说明前面讲砸了。