写在前面

欢迎大家关注Rocky的公众号:WeThinkIn 欢迎大家关注Rocky的知乎:Rocky Ding 《三年面试五年模拟》AIGC/LLM/AI Agent算法工程师/开发工程师求职面试秘籍独家资源:【三年面试五年模拟】WeThinkIn/AIGC-Interview-Book,欢迎大家Star~
Rocky最新撰写的10万字AI Agent(AI智能体)深入浅出全维度解析文章: 深入浅出完整解析AI Agent(AI智能体)的核心基础知识
AIGC/LLM/AI Agent算法岗/开发岗求职面试内推学习社群(涵盖AIGC、LLM大模型、AI Agent、传统深度学习、自动驾驶、机器学习、计算机视觉、自然语言处理、强化学习、大数据挖掘、具身智能、元宇宙、AGI等AI行业最新面试干货经验与核心知识)欢迎大家加入:https://t.zsxq.com/33pJ0
大家好,我是Rocky。
AI 应用开发的工程能力,体现在能否把模型、检索、工具和业务规则组织成可靠系统。Rocky认为,面试回答既要讲清机制,也要交代约束、失败处理和验证证据;项目经验则应以真实职责与实际测量为边界。
复习时可沿三条主线展开:先用 Python 与数据库知识证明工程基础,再用 RAG 和结构化输出说明模型边界,最后用评测、延迟与恢复机制解释系统如何可靠交付。涉及个人经历的回答保留可替换框架,实验示例不充当真实项目成绩。
目录
- 1. 岗位理解与自我介绍
- 2. AI 编码工具的使用边界
- 3. 装饰器的核心机制
- 4. 耗时装饰器:同步、异步与异常
- 5. functools.wraps 与元数据
- 6. 联合索引的列顺序与 SQL
- 7. 缺少首列时能否使用索引
- 8. B+Tree 的字典序组织
- 9. 结构化输出的四层校验
- 10. 多余文本与严格 JSON 解析
- 11. 语法错误与有界修复
- 12. RAG、检索与微调的选择
- 13. 词汇鸿沟与规则口径冲突
- 14. 微调的能力边界
- 15. Agent 常用设计模式
- 16. 滚动规划与局部 ReAct
- 17. 重规划触发器与成本
- 18. 真实项目的表达框架
- 19. 50 条数据的评测边界
- 20. 漏召排查与指标定义
- 21. 切分实验与失败假设
- 22. 端到端质量与配对评测
- 23. TTFT、模型与缓存取舍
- 24. LangGraph 的设计价值
- 25. 节点契约与 reducer
- 26. 共享状态的工程代价
- 27. 中断恢复与业务幂等
AI面试
1. 先请你简单做个自我介绍,包括个人基本信息教育背景,重点聊一下你是怎么理解这个岗位的。
回答:
自我介绍应围绕“我是谁、能承担什么工作、为什么匹配岗位”展开,避免逐条复述简历。学校、专业、毕业时间、项目规模和效果数字都要使用真实信息;没有做过的金融项目或模型训练,不能借岗位背景包装成个人经历。
可以按这个框架表达:“我叫[姓名],来自[学校与专业],预计[时间]毕业。我主要积累了 Python 后端、数据库和大模型应用开发能力,在[真实项目]中负责[明确模块],重点解决过[问题及验证结果]。我理解 AI 应用开发需要把模型能力转化为稳定、可评测、可维护的业务功能,既要懂检索、工具调用和上下文设计,也要处理接口、权限、状态、延迟和成本。”
对于金融软件相关业务,还应关注数据权限、业务规则、审计追踪和结果可验证性。例如,模型可以帮助检索制度、解释业务或生成操作建议,但实际交易、资金变更和权限调整必须经过确定性校验与授权。不要把这些通用工程要求说成已经了解某个面试团队的内部架构。
最后用一句真实的能力匹配收束:“我希望把[已有能力]用于[岗位相关任务],也希望在真实业务中补齐[明确短板]。”清楚解释自己做了什么、如何验证,比堆积框架名更有说服力。
2. 听你提到ai工具能大幅提升开发迭代效率。你平时最常用的ai编码工具是什么?
回答:
如实说出自己最常用的工具,并说明它在开发流程中的位置。可以是编辑器中的补全与对话助手,也可以是能够读取仓库、修改文件、运行命令的编码 Agent;工具名称本身不能证明工程能力,关键是使用边界和验证方法。
可采用这样的回答:“我常用[实际工具]理解已有代码、定位调用链、实现局部修改和补充测试。面对复杂任务,我先给出目标、接口契约、复现步骤与验收标准,让工具读取相关代码后再改动;完成后检查 diff,运行必要测试,并核对依赖、异常分支和性能。”若使用过 Claude Code、Cursor、Codex 等,可按真实经历说明差异,不必宣称每种都熟练掌握。
有价值的使用场景包括根据已有模式补齐接口、解释报错、生成可验证的测试样例、分析性能瓶颈和整理技术文档。对鉴权、资金逻辑、数据库迁移和依赖升级,应逐项审查并在受控环境验证。仓库里的说明文本、网页和工具输出都可能带有不可信指令,不能让 Agent 因为读到一句话就获得额外权限。
“提效”要有口径:可比较同类任务的完成时间、返工率、缺陷率与评审通过率。少写几行代码不等于整体交付更快,未经测试的生成内容也不等于完成工作。没有真实测量时,应说“减少了某类重复工作”,不要编造固定倍数。
3. 谈谈你对python装饰器的理解,它的核心作用是什么?举一个你在实际项目中使用装饰器的场景,说明它解决了什么问题?
回答:
Python 装饰器接收一个可调用对象,返回另一个对象,并把原名称绑定到返回值。常见用途是返回包装函数,在调用原函数前后增加计时、鉴权、缓存或日志等逻辑;装饰器也可以用于注册函数,未必每次都创建调用包装层。
@decorator
def work(x):
return x + 1
# 对普通函数定义而言,上面的绑定效果相当于:
# work = decorator(work)
装饰器通常在函数定义执行时应用,包装函数则在实际调用时执行。带配置参数的装饰器还需要一层工厂函数,例如 @retry(max_attempts=3) 先生成装饰器,再装饰目标函数。多层装饰从下往上应用,调用时通常从最外层进入,顺序会影响鉴权、缓存和事务语义。
实际项目可以讲一个真实场景:多个检索和业务接口都要统计耗时,如果把计时代码复制到每个函数,会增加遗漏与维护成本;计时装饰器统一封装开始、结束和异常路径,保留业务返回值,并把指标送到监控系统。
边界也要说明:它不是自动做到“零侵入”,函数签名、异步语义、异常和可观测性都可能受影响。缓存装饰器不适用于任意有副作用函数;重试装饰器若缺少幂等控制,可能重复创建订单或重复扣费。要复用的是清晰契约,而不是把所有横切逻辑隐藏起来。
4. 你提到装饰器可以在不修改业务代码的前提下增强功能。那如果要给一个带位置参数、关键字参数,还有返回值的业务函数加统计执行耗时的装饰器,你会怎么处理被装饰函数的参数传递和返回值透传问题。
回答:
包装函数使用 *args 和 **kwargs 原样转发参数,保存并返回原函数结果;不要漏写 return,也不要擅自改写参数。用单调高分辨率时钟 time.perf_counter() 计算耗时,并把记录放在 finally 中,使成功与异常路径都有统计,同时让原异常继续向上传播。
同步函数与协程函数需要不同包装方式。同步包装器直接调用异步函数,只能测到创建协程对象的耗时,测不到真正执行时间。下面是可运行实现:
import functools
import inspect
import logging
import time
logger = logging.getLogger("function_timing")
def timed(func):
if inspect.isgeneratorfunction(func) or inspect.isasyncgenfunction(func):
raise TypeError("generator timing requires a separate contract")
def record(start):
elapsed = time.perf_counter() – start
try:
logger.info("%s elapsed=%.6fs", func.__qualname__, elapsed)
except Exception:
# 监控故障不覆盖业务返回值或业务异常。
pass
if inspect.iscoroutinefunction(func):
@functools.wraps(func)
async def async_wrapper(*args, **kwargs):
start = time.perf_counter()
try:
return await func(*args, **kwargs)
finally:
record(start)
return async_wrapper
@functools.wraps(func)
def sync_wrapper(*args, **kwargs):
start = time.perf_counter()
try:
return func(*args, **kwargs)
finally:
record(start)
return sync_wrapper
记录值覆盖原函数从开始到完成或抛错的时间,不包含后续日志写入耗时。生产环境还应采用低开销指标与受控采样,避免输出敏感参数,也不应让指标标签含无界用户 ID。同步日志处理器可能阻塞事件循环,应使用合适的异步或队列化监控通道。
该示例支持普通同步函数和常规 async def,显式拒绝生成器,因为“创建迭代器耗时”和“消费全部结果耗时”不同。同步函数返回 awaitable 的特殊情形也不在完整异步计时契约内。取消协程时 finally 仍会运行,取消异常不应被吞掉。
追问:统计的到底是哪一种时间? perf_counter() 测量的是经过时间,包含等待 I/O 和调度暂停;process_time() 更接近进程消耗的 CPU 时间,不能拿它替代用户等待时长。协程中的计时虽然只包住一个任务,但期间事件循环可能执行其他任务,记录的是该任务的墙钟耗时。分别记录成功、失败、取消次数,再按接口统计 p50、p95、p99,才有定位价值;单个平均值会掩盖长尾。
5. 你刚才提到会用判断做参数校验,那你知道python中用来实现装饰器时,能自动保留被装饰函数源信息,比如函数名文档字符串的标准库装饰器是什么吗?
回答:
标准库提供的是 functools.wraps。通常把它写在包装函数上:@functools.wraps(original)。它是 functools.update_wrapper 的便捷封装,帮助保留原函数的模块、名称、限定名、文档字符串、注解等元数据,并设置 __wrapped__ 指向被包装对象;具体默认复制属性与 Python 版本有关。
保留元数据有实际作用:日志和监控能显示业务函数名,帮助文档与调试工具追踪原函数,inspect.signature 通常可以沿 __wrapped__ 获取原签名。否则所有函数可能都显示为 wrapper,影响定位和依赖注入等依赖反射的功能。
但 wraps 不会把 (*args, **kwargs) 包装器的实际执行参数机制改写成原函数定义,也不会自动完成参数校验、类型检查或返回值透传。它更不会自动修正同步与异步的语义差异。这些仍然需要包装函数正确实现。
因此回答可以收束为:wraps 负责元数据与可追溯性,参数转发和调用语义由包装器负责。
6. 创建联合索引时字段的放置顺序,会不会影响查询效率?为什么?
回答:
会影响。以下以 MySQL InnoDB 的 B+Tree 联合索引为例:索引 (a,b,c) 按 a、再 b、再 c 的字典序组织,同一 a 的记录相邻,在相同 a 内按 b 排序,再在相同 a、b 内按 c 排序。索引顺序决定哪些条件能够形成连续、可高效定位的扫描范围。
a=? AND b=? 通常能利用前两列定位;a=? AND b>? AND c=? 中,常规范围定位通常不能继续用 c 把整个范围压成同样精确的区间,但 c 仍可能用于索引条件下推、过滤或覆盖查询。不能把“不能继续缩小搜索区间”说成“后面的列完全失效”。
列顺序应结合高频查询的过滤、排序、分组和覆盖需求:常用的租户等值条件、业务状态与时间范围,往往需要一起考虑。对所有列都等值查询的场景,不同排列可能都能精确定位,区别更多体现在其他查询的复用。把“选择性最高的列永远排第一”当通用规则是不严谨的。
索引也有写入、缓存和存储成本。通过真实数据分布、统计信息与 EXPLAIN 比较候选方案;EXPLAIN ANALYZE 会实际执行查询,应在可控环境使用。SQL 中 WHERE 条件书写顺序通常由优化器处理,不等于索引定义里的列顺序。
把原则落实到一条 SQL。 假设客服工单常见查询是“某租户下某状态的最近 20 条记录”:
CREATE INDEX idx_ticket_tenant_status_time
ON ticket (tenant_id, status, created_at);
SELECT id, created_at
FROM ticket
WHERE tenant_id = 42 AND status = 'OPEN'
ORDER BY created_at DESC
LIMIT 20;
前两列等值约束先确定范围,随后可按时间反向扫描并尽早满足 LIMIT。若 id 是 InnoDB 主键,这两列输出还可能被该二级索引覆盖;若额外读取 content 等列,则通常需要回表。换成“该租户所有状态的最近记录”后,status 未固定,时间顺序就不能直接由这个索引整体保证,应重新评估 (tenant_id, created_at)。这说明索引设计要从一组高频访问路径出发。
以上是分析用查询,不是已经测得的执行计划。验证时比较估计行数与实际扫描行数,观察是否排序、是否回表,并在真实基数和冷热缓存条件下记录延迟;小表实验不能直接推断生产收益。
7. 如果我有一个联合索引abc,查询条件是b等于1 and c等于2,这个查询能用到这个联合索引吗?
回答:
不能仅凭缺少 a 就回答“绝对不能用”。对于 (a,b,c) 且仅有 b=1 AND c=2 的查询,通常无法按完整最左前缀直接定位一个连续的精确区间,但是否使用这个索引还存在几种可能。
| 普通前缀查找 | 缺少 a 时通常不具备直接前缀定位条件 | 不是简单的 (a,b,c) 等值查找 |
| 全索引扫描 | 优化器可能选择 | 尤其索引覆盖查询时,扫描索引可能比扫描整行便宜,但仍要读大量索引项 |
| Skip Scan | 支持该优化且满足限制时可能选择 | 遍历不同前导值再做后续范围查找,前导列基数与成本很关键 |
| 全表扫描或其他索引 | 也可能选择 | 由选择性、覆盖情况、统计信息和成本决定 |
MySQL 8.x 的 Skip Scan 不是无条件通用能力,适用查询形态、覆盖列、单表及分组等存在限制,最终以具体版本和执行计划为准。b=1 AND c=2 并不保证一定触发这一优化。
可以比较 SELECT b,c … 与 SELECT * … 的计划:前者更可能由索引覆盖,后者可能需要大量回表。看 key、访问类型、估计/实际扫描行数、Extra 和查询耗时,区分“选了索引”和“高效用了索引”。如果这类 b、c 条件是核心高频查询,再评估 (b,c) 或其他符合整体负载的索引。
8. 你刚才提到联合索引,遵循最左匹配原则,那联合索引在B+树中存储时,是按照什么规则来组织键值顺序,从而支撑最左匹配特性的。
回答:
它遵循多列键的字典序比较:先比较 a;a 相同才比较 b;a、b 都相同才比较 c。以下例子简化忽略排序方向和排序规则差异:
(a=1,b=1,c=2)
(a=1,b=1,c=5)
(a=1,b=3,c=1)
(a=2,b=1,c=2)
(a=2,b=2,c=0)
固定 a=1,可以找到连续的一段;再固定 b=1,可以缩到这段内部更小的连续区间。只固定 b=1、c=2 时,符合记录可能散落在许多不同 a 的区间,无法用一个普通前缀查找直接跳到所有结果。这就是最左匹配背后的顺序结构。
B+Tree 内部页提供导航键,叶子页保存有序索引记录并支持范围扫描。InnoDB 的聚簇索引叶子保存行数据,二级索引叶子包含二级键与定位行所需的主键值;需要非覆盖列时,再通过主键回表。主键较宽会增加二级索引占用。
严格来说,比较顺序还受字段类型、字符排序规则、NULL 处理和 ASC/DESC 定义影响,不是把字符串拼接后按文本排序。Skip Scan 等优化通过额外算法利用这棵树,并没有改变它的字典序组织原则。
9. 让大模型稳定输出结构化数据,如JSON是ai应用开发常见需求,但模型有时会输出多余的解释文字或格式不合法,你会用哪些手段提升结构化输出的稳定性和可解析性。
回答:
把稳定性拆成四层:生成协议、语法、结构与业务语义。只有“可以 json.loads”远远不够,例如金额类型正确但币种错误、订单号属于别的租户,仍然不能执行。
优先使用模型和服务端明确支持的 JSON Schema 约束输出或工具调用参数输出,而非只写一句提示词。区分 JSON mode 与 schema-constrained output:前者通常侧重合法 JSON,后者进一步约束字段结构,但支持哪些 schema 关键字、遇到拒答和截断时如何返回,取决于供应商与具体模型。
提示词仍需要给出明确任务、简洁 schema、字段含义和示例,减少可选格式。服务端检查结束原因、拒答信号与完整性,不能把未结束的流式片段当作完整对象解析。解析后用 Pydantic、JSON Schema 等验证类型、必填项、枚举、长度、取值范围与额外字段。
再做业务校验:权限、实体是否存在、字段之间的关系、金额与时间约束、证据是否支持结论。对不合法结果进行有次数和耗时预算的定向修复;失败则返回结构化失败状态或人工复核。写操作的授权和幂等校验放在模型外部。
上线监控语法成功率、schema 通过率、业务有效率及最终任务成功率,分别记录失败类型。结构化输出的目标是建立可验证的业务接口,格式正确只是第一道门。
10. 如果你在提示词里已经明确要求,只输出JSON不要额外解释,但模型依然在JSON前后附带自然语言说明,你会用什么方式处理这类输出。
回答:
先确认接口是否可以直接返回结构化字段,优先修正生成协议和调用配置。如果只能接收自由文本,需要一个有明确接受规则的兼容层,不能用贪婪正则随意抓取第一个 { 到最后一个 }。
处理顺序可以是:先对完整响应做严格 JSON 解析;若不成功,只剥离已确认的外层代码围栏或固定包装;确实需要从说明文字中提取时,用理解字符串、转义和嵌套层级的解析器或状态机识别完整的顶层候选,再用 JSON 解码器验证。JSONDecoder.raw_decode 可返回从指定位置解析出的值及结束位置,但不会自动证明其余内容无害。
如果文本中出现示例对象和最终对象两个候选,或多个对象都满足 schema,不能任意取一个,应按协议要求重生成或报歧义。识别顶层候选时应跳过已解析对象内部位置,防止误把嵌套对象当第二个独立答案。只接受约定的根类型,例如 object,而不是任何合法 JSON 标量。
提取后仍要限制长度和嵌套深度、校验 schema、拒绝重复键,并处理 Python 标准解析器默认可接受 NaN/Infinity 等与严格 JSON 不一致的行为。不能通过删除所有反斜杠、替换所有引号来“清洗”,那可能改坏路径、自然语言或数据值。
对资金、审批等高风险接口,可以直接拒绝带多余内容的响应并要求受约束重生成。兼容策略是否接受前后说明,应由接口契约决定,不应在不同请求之间随意变化。
最小严格入口可以直接写成代码。 下面明确只接受一个完整 JSON object,允许协议外层空白,拒绝前后解释、重复键与非标准数值;它不尝试猜测或自动修复内容。
import json
from decimal import Decimal
def reject_constant(value):
raise ValueError(f"non-standard JSON number: {value}")
def unique_object(pairs):
obj = {}
for key, value in pairs:
if key in obj:
raise ValueError(f"duplicate JSON key: {key}")
obj[key] = value
return obj
def parse_json_object(text, *, max_chars=32768):
if not isinstance(text, str) or len(text) > max_chars:
raise ValueError("invalid input type or size")
try:
obj = json.loads(
text,
object_pairs_hook=unique_object,
parse_constant=reject_constant,
parse_float=Decimal,
)
except (json.JSONDecodeError, RecursionError) as exc:
raise ValueError("invalid or too deeply nested JSON") from exc
if not isinstance(obj, dict):
raise ValueError("JSON root must be an object")
return obj
object_pairs_hook 在每一层对象构造时检查重复键,可以避免后出现的值静默覆盖先前值。parse_float=Decimal 避免十进制直接落入二进制浮点近似,也避免 1e400 被默认浮点转换成无穷大;但它不限制指数大小、金额精度和取值范围,后续仍需逐字段约束。与 schema 验证器连接时,也要确认其是否接受 Decimal 类型。
这段代码仅负责严格解析,不是完整的防资源耗尽方案:字符上限不能替代明确的深度限制,超深输入在递归上限之前仍可能消耗资源;公网入口应在受限解析器或隔离执行环境中增加深度、数值长度和时间预算。字段缺失、额外字段、金额越界或越权实体都必须在后续 schema 与业务层拒绝。涉及日志时只记录错误类别和追踪 ID,避免把完整敏感响应写入日志。
11. 模型输出的JSON本身存在转义错误、括号不匹配,这类语法问题,导致正则也无法准确截取合法片段,你会怎么处理?
回答:
括号缺失、非法转义等意味着尚未得到可信的完整结构。第一步检查响应是否因为 token 上限、网络中断、工具调用流未结束而截断;若是传输或预算问题,应先补齐协议或重新请求,不能用格式修复掩盖上游故障。
对轻微且定义明确的包装问题可用确定性规则处理;对真正语法错误,可以把解码错误位置、目标 schema 和原输出作为不可信数据交给修复步骤,要求只修格式,并设置严格的重试次数、总 deadline 与输入长度上限。更可靠的长期措施仍是从生成端使用约束输出。
修复库或另一次模型调用返回可解析结果,不代表语义被保留。例如缺失一个小数点或负号就可能改变金额,自动补值也可能编造订单 ID。关键字段应与请求、数据库或证据重新对照;无法恢复含义就返回失败,请求补充或人工确认。
禁止使用 eval 执行模型输出,ast.literal_eval 解析的是 Python 字面量,也不是通用 JSON 校验器。不能把“把单引号替换成双引号”“补齐所有右括号”当可靠通用算法。
最后把解析错误、schema 错误、业务错误分开统计。若格式错误集中在特定模型、模板或长度区间,应修正根因,而不是把无限重试变成线上默认策略。
12. RAG、传统检索+生成、微调三种方案的本质区别是什么?分别在什么场景下选用。
回答:
先澄清分类口径:RAG 是检索增强生成;“传统检索 + 生成”只要把检索到的外部证据用于生成,也属于广义 RAG。 用向量检索还是 BM25,是检索组件的选择,并不是是否属于 RAG 的分界。工程上也不要求 RAG 一定联合训练检索器与生成器。
| 稀疏检索 + 生成 | 通过词项、倒排索引等取得上下文证据 | 产品代码、专有名词、条款编号与精确词匹配 |
| 稠密/混合检索增强生成 | 利用语义向量及词项信号召回,再重排和组织证据 | 表述差异较大、知识经常更新、需要权限控制与可引用证据 |
| 微调 | 通过训练改变参数或适配器,调整行为分布 | 稳定任务模式、领域表达、工具选择、格式遵循与分类能力适配 |
RAG 的关键依赖是语料质量、索引新鲜度、权限、召回和上下文利用;微调依赖训练数据、目标和可验证泛化,知识更新也不如修改外部库直接。微调可以影响模型知识与行为,但不能作为精确可更新事实库的通用替代。
选择时先明确失败类型:缺少新事实或需要出处,优先外部检索;拿到正确材料仍不遵循规则,评估提示、解码、模型能力和微调;短小且稳定的分类或抽取,也可能只需一个任务模型。RAG 与微调可以组合,例如微调检索器、重排器或生成器,而不是互斥三选一。
金融制度类问题还应保留版本、生效时间与适用范围。检索到错误版本后生成得再流畅也不正确,训练时记住某条旧规则同样不能保证当前可用。
13. 你刚才提到传统检索是基于词的相似度匹配,不涉及语义。那如果企业内部有大量存在表述差异,但高度相关的文档,比如不同部门对同一业务流程的不同口径记录这种场景下,传统检索加生成会出现什么核心问题。
回答:
这里需要修正前提:基于词项的检索并不意味着完全不涉及语义,查询扩展、词典、同义词和学习排序都能补充语义线索;但纯词面匹配确实容易出现“意思相近、用词不同”的词汇鸿沟。
例如一个部门写“客户风险等级复核”,另一个部门写“投资者适当性重新评估”,仅依赖重合词可能漏掉相关材料。核心影响是召回不足:正确文档没有进入上下文,生成器随后可能给出不完整答案、误拒答,或者用参数记忆补出未经验证的内容。
改进可结合领域术语表、别名规范化、受控查询改写、稠密召回与 BM25 混合检索,再通过重排验证相关性。精确代码和数字仍应保留词项检索优势,不能简单删除稀疏通道。评估时单独看同义表达、缩写、跨部门术语及精确编号查询。
但“不同口径”还可能意味着流程本身不同,而非同义改写。需要记录部门、地区、业务线、适用对象和有效时间;遇到规则冲突,应按权威性与适用范围选取,无法确定则追问。不能把两个不同制度强行合并为一段看似一致的答案。
最终目标是召回当前请求有权访问且实际适用的证据,而不只是找到语义相似的文字。
14. 你刚才提到,当提示词工程、RAG优化到位仍达不到效果时,才考虑模型微调。那你认为微调会从根本上改变大模型的哪些固有能力边界?
回答:
“提示和 RAG 到位才微调”是一种成本优先的排查策略,不是理论上的绝对顺序。若任务从一开始就需要稳定的领域分类、风格或工具路由,已有足够高质量监督数据,也可以较早评估微调。
微调通过改变参数,调整给定输入下的输出分布:它可以强化领域术语理解、任务模式、格式遵循、工具选择和某类推理行为,也可能注入新知识或改善特定能力。其有效范围由基座表征、训练数据覆盖、优化目标和参数更新方式共同决定,并存在过拟合、遗忘与能力回退风险。
它不会自动扩大架构设定的上下文上限,不会凭少量样本获得实时数据库访问,不会给文本模型凭空增加完整视觉输入通道,也不会让模型具备新的外部权限。长度扩展、增加模态或改变结构,需要相应架构、数据与训练设计,不能把普通 SFT 等同于这些改造。
对推理和事实可靠性,更不能承诺微调后“不再幻觉”。训练集效果改善,需要在独立数据、分布外样本、长尾和旧能力保留集上验证。对规则必须百分之百成立的约束,依然应由解析器、规则引擎、权限系统或验证器执行。
面试时可以概括为:微调能改变模型在已有系统条件下的能力分布和行为偏好,是否实质扩展某项能力要由实验说明;它不是突破任意固有边界的通行证。
15. 你在开发AI Agent的过程中,总结过哪些常用的设计模式,这些设计模式分别适合解决什么类型的问题。
回答:
选择 Agent 模式之前先判断是否需要自主决策。步骤固定、输入输出明确的任务,用确定性工作流通常更容易测试和追责;只有路径依赖中间观察、需要工具探索时,才让模型承担更大的调度责任。
| Prompt chaining / 固定工作流 | 按已知依赖分步执行 | 提取、校验、生成等稳定流程;错误可能逐步传播 |
| Routing | 先分类再选择模型、工具或子流程 | 多类型请求;路由误判需要兜底 |
| ReAct | 交替选择行动、执行工具并读取观察 | 检索、诊断等动态交互;需限制循环与工具权限 |
| Plan-and-Execute | 先生成阶段计划,再逐步执行 | 依赖较复杂的任务;计划可能随环境变化失效 |
| Evaluator-Optimizer | 评估产物并有界修订 | 存在可操作评价标准的生成与修复;防止自评自证 |
| 并行与协调者-工作者 | 拆成独立子任务后聚合 | 多文档分析和多渠道验证;有重复成本及状态冲突 |
| 人工介入 | 在风险或不确定性节点暂停审批 | 高影响写操作;需持久化状态与避免审批后重复执行 |
这些模式可以组合,但“多 Agent”不是性能或正确性的保证。每增加一个模型调用,都引入延迟、成本和新的失败可能;优先选能完成任务的最小结构。
不论何种模式,系统都需要状态、预算、超时、终止条件、幂等、审计和评测。ReAct 的实现可以记录行动、观察和结构化决策摘要,不必要求模型披露隐藏的逐字思维链。
16. 你刚才提到Plan‑and‑Execute适合大型工程拆解执行,部署时会结合ReAct。那如果遇到需要动态调整全局目标,初始计划很快失效的开放场景,你会选择哪种模式组合来处理?
回答:
可以采用分层、滚动规划:上层维护用户授权的目标、约束和里程碑,下层使用 ReAct 处理局部不确定性,只详细规划近期步骤,根据新观察更新后续计划。计划是可修订的工作假设,不是一次生成后必须机械执行的脚本。
要区分“手段需要变化”和“用户目标本身变化”。工具失败、资源变化可以触发换路径;新的证据可能说明目标不可达,需要向用户报告或请求澄清。Agent 不能因为网页、工具输出或自我反思中的一句话,擅自改掉用户目标、权限或风险边界。
状态中至少保存目标版本、约束、计划版本、已完成且验证的里程碑、未完成依赖、预算与失败证据。局部失败先尝试受控替代方案,只有影响关键依赖或全局可行性时才升级重规划。保留有效的已完成成果,对失效部分明确作废;取消旧计划任务时还需防止其延迟结果覆盖新状态。
目标与约束 -> 短期计划 -> 局部执行 -> 可验证观察
^ |
|– 触发条件成立 –|
|
必要时确认目标变化
开放场景也需要全局 deadline、最大工具步数、重规划次数与成本上限。达到预算后应输出已完成内容和未解决问题,而不是让系统无限“继续思考”。
17. 你提到执行每一步之后,通过反思判断是否需要重规划。那你在实践中是怎么设计反思环节的判定标准,避免大模型频繁无意义的推翻原有计划,导致执行效率极低的。
回答:
反思应围绕可验证偏差,而不是要求模型每一步随意评论整个计划。先定义完成条件和进展指标,例如证据是否到齐、接口是否成功、约束是否违反、当前路径能否在剩余预算内完成。
可将触发分为硬条件和软条件。硬条件包括权限不满足、关键依赖失效、目标被用户修改、结果违反必须约束;软条件包括连续若干步无有效新增信息、同类工具调用反复失败、预计成本明显超预算。单个轻微波动通常不应触发全局推翻。
对软条件使用冷却期、连续确认或滞回:只有收益预估稳定超过阈值,才执行重规划。概念上可表示为:
Δ
U
^
>
C
r
e
p
l
a
n
+
C
s
w
i
t
c
h
+
δ
\\widehat{\\Delta U} > C_{\\mathrm{replan}} + C_{\\mathrm{switch}} + \\delta
ΔU
>Creplan+Cswitch+δ
这里的收益估计必须来自任务进展、验证结果或历史统计,不能把模型口头“信心”当已校准概率。阈值通过离线回放和线上受控实验选择,不存在所有任务通用的固定值。
执行层记录行动签名、依赖和产物摘要,识别重复搜索、相同参数调用与无变化修订;发现循环后切换策略或终止。评估“成功率、耗时、成本、无效重规划率、漏掉必要重规划的比例”,比较无反思、每步反思和事件触发反思。这样才知道反思是否真正创造了价值。
触发器应能被执行器解释。 例如,把“连续 3 次工具调用没有新增有效证据”设为试验配置:第 1 次先局部改写查询,第 2 次切换检索通道,第 3 次才触发计划审查。这里的 3 不是通用最优值,需要根据离线任务校准。权限拒绝则直接暂停相关动作,不等待累计次数;冷却期也不得屏蔽这类硬约束。重规划事件记录触发证据、旧新计划差异、保留的成果与预算变化,才能复盘它是否必要。
18. 请分享一个你做过的最具技术挑战,最值得深入探讨的大模型应用项目,它要解决什么问题,核心难点在哪?你又是如何攻克的?
回答:
这道题必须基于真实经历。一个适合展开的大模型应用项目可以是企业知识客服,但下面是回答组织框架,不能当作已经发生的个人经历或使用虚构指标。
先讲业务目标与限制:“项目服务[真实用户与业务],需要回答[问题范围],要求[准确、时效、权限、延迟]。”再讲自己负责的链路,例如文档入库、解析切分、召回重排、证据组织、生成校验与服务接口,明确哪些由同事或平台提供。
核心难点优先选一个能深入验证的问题:例如跨部门术语导致漏召,表格切分损坏条件,知识版本冲突,或流式响应延迟。说明初始假设、如何采样与定位、做过哪些消融,以及有哪些看似合理但无效的尝试。不要把整个系统的所有难点都声称由自己一人解决。
完整架构可概括为:有权限与版本的知识入库 -> 混合召回 -> 重排与证据覆盖 -> 模型生成 -> 引用和业务规则校验 -> 拒答/人工兜底 -> 反馈评测。离线与线上共享可追溯的模型、索引和提示版本,方便归因及回滚。
结果应使用真实前后对照、样本数、时间窗口和成本口径;没有严谨 A/B 时,说明是离线回放或小流量观察。项目最值得讨论的往往是“如何证明改动有效”和“哪里仍然不可靠”,而不只是接入了什么模型。
19. 你刚才提到最初只有50条产品给的黄金数据来构建知识库。你们当时是怎么测量并确认这个知识库支撑下的回答准确性不达标的。
回答:
先问清这 50 条是什么:是知识条目、常见问答、带正确证据的评测题,还是已用于调参的样本?知识库内容与独立评测集不是同一概念。 用同一组问答建库再只测试原句,容易高估效果;反复用它们挑切分和提示,则不能再把它们当独立测试集。
建立最小评测规范:每个问题记录标准答案的必要要点、适用条件、支持文档与版本、是否应拒答。由业务人员复核,再加入同义改写、多轮、省略信息、跨文档和不可回答问题;相近模板或同源文档划分时要避免泄漏。
将错误拆成证据未召回、证据不完整、引用错误、生成事实错、适用范围错和应拒未拒。检索侧测证据命中与覆盖,生成侧依据 rubric 判断是否回答完整且有证据支持,不能只使用字符串完全匹配或让同一个模型单独自评。
若暂时只有 50 个独立评测样本,每错一题会改变总体比例 2 个百分点,统计不确定性很大。举例,若 40/50 通过,点估计是 80%,Wilson 95% 区间约为 67%–89%;这只是演示,不是项目真实成绩。若样本相互相关,简单二项分布区间也可能过于乐观。
因此“不达标”的判定应对照事先定义的业务门槛、高风险错误及区间,而非某个漂亮的小样本分数。有限样本适合发现问题和建设初始回归集,不能证明已经覆盖全部生产风险。
让评测记录能指导修改。 一条样本至少包含 question_id、问题、租户与角色、时间、必需答案要点、可接受证据组和拒答条件。对于允许多个等价文档的题目,应标注可替代证据,避免把“没有命中唯一指定 chunk”误算成失败。面对空答案、部分正确与条件遗漏,要提前明确评分规则。
若预算只能人工复核 50 条,优先按业务风险和问题类型分层取样,报告各层数量与错误。此时不能把人为增加的高风险难题比例直接当作线上自然分布;总体指标要说明采样方式,需要时按实际流量权重汇总。优化阶段用开发集,最终结论用冻结测试集,新增线上错误进入下一轮回归集。
20. 你刚才提到最初测召回的时候,20条召回结果里会漏掉正确的文档片段,当时你们是怎么一步步排查定位出漏召的根本原因的。
回答:
把“正确片段是否进入前 20”拆成逐层可观察的链路,先固定 query、知识库快照、embedding、切分和检索配置,保存每层候选 ID 与分数。否则一边刷新索引一边查问题,很难得到可复现结论。
如果正确证据在第 21 名,把 K 扩大只是诊断动作,后续还要看成本与噪声;如果证据被拆成几个缺少语义的片段,才有充分理由改切分。还要检查标准答案是否要求多个片段:只命中其中一段不能算完整覆盖。
修复时一次改变主要因素,在固定评测集上按错误类型分桶比较。不能因为看见一句短 chunk 就认定“切分太碎”是唯一根因。
明确 Hit@K 与 Recall@K 的区别。 令
G
q
G_q
Gq 是问题
q
q
q 的相关证据 ID 集合,
R
q
(
K
)
R_q^{(K)}
Rq(K) 是前 K 个去重检索结果,下面两个量回答的是不同问题:
Hit@K
(
q
)
=
1
{
G
q
∩
R
q
(
K
)
≠
∅
}
\\operatorname{Hit@K}(q)=\\mathbf{1}\\{G_q\\cap R_q^{(K)}\\ne\\varnothing\\}
Hit@K(q)=1{Gq∩Rq(K)=∅}
Recall@K
(
q
)
=
∣
G
q
∩
R
q
(
K
)
∣
∣
G
q
∣
\\operatorname{Recall@K}(q)=\\frac{|G_q\\cap R_q^{(K)}|}{|G_q|}
Recall@K(q)=∣Gq∣∣Gq∩Rq(K)∣
前者只判断是否命中至少一个,后者衡量已标注证据的覆盖比例。当一道题必须同时依据“适用对象、额度上限、例外条件”三个片段,命中一个时 Hit@K 已为 1,Recall@K 仍只有 1/3。对于这种每条证据都必需的题目,还应统计是否全部覆盖;如果存在多组等价证据,应按可接受证据组评判,不应强制找全所有替代材料。
上述 Recall 定义只适用于
∣
G
q
∣
>
0
|G_q|>0
∣Gq∣>0;不可回答题需单独测错误检索和拒答表现,不能用除零后的任意值补进平均数。切分策略变化后,chunk ID 和数量也会变,因此跨切分实验宜用稳定的文档跨度或业务事实单元标注,再映射到各方案的 chunk。

图 1:从入库到答案逐层观察。该图是排障方法示意,不代表某一项目已测得的结果。
21. 你最初判断是切分太碎,导致漏召。在优化切分策略的过程中,有没有出现过你原本判断有效的调整方案,实际测试后发现效果不达预期被推翻的情况。
回答:
应讲真实的反例与证据,没有经历时说明这是实验设计。一个合理但不保证有效的假设是:把 chunk 变大能保留上下文,所以召回和回答都会更好。它可能失败,因为更多无关主题稀释向量表示、增加截断和重排成本,并把相邻但不适用的规则带进生成上下文。
另一个常见反例是不断增大 overlap。它可以缓解边界断裂,却也会产生大量相似候选,占满 TopK,减少独立证据覆盖。固定返回 20 块时,大块和小块的总 token 预算不同,若只比较 Recall@20,结论还可能受到预算不公平影响。
可以做小规模受控实验:按标题、段落、表格结构切分;分别测试几档大小与 overlap;对同一问题同时比较证据覆盖、重排质量、固定 token 预算下的最终答案质量和延迟。跨文档重复内容应先治理,不能单靠调整 chunk 长度解决。
对表格、步骤和条件规则,保留标题路径、表头、适用范围与父文档关系。可以采用小块检索、父级扩展,但扩展内容同样受权限、token 与相关性约束;父子索引不是无成本地“找得准又看得全”。
最终保留业务指标更好的策略,并记录失败假设及样本。实验推翻直觉是正常结果,关键是比较条件公平、失败能被解释、改动可以回滚。
22. 优化切分后,召回率得到了提升。那你们最终是怎么判断整个客服系统的回答效果是真的变好了,而不只是召回指标好看。
回答:
召回只是中间指标,客服系统的目标是正确、完整、及时地解决用户问题。检索更高可能只是多塞了文档,生成阶段仍可能选错规则、混淆版本或忽略否定条件,因此要沿整条链路验收。
离线对固定、独立且覆盖业务分布的问题集,比较新旧系统的答案正确性、完整性、证据支持、引用可追溯、应拒答表现与高风险错误。人工盲评可减少对新方案的期待偏差;模型评审可以扩展覆盖,但需要人工校准和对争议样本仲裁。
同时固定或记录上下文 token、模型版本与成本,区分切分优化与“给模型更多材料”带来的影响。使用配对比较,重点复核从对变错的回归样本;按业务、问法、长尾、知识版本和权限场景分桶,不只报告一个平均值。
上线先影子流量或小流量灰度,再通过合适的随机实验观察问题解决率、重复咨询、人工转接、用户负反馈和延迟。转人工减少不一定是好事:如果系统错误地把问题标成已解决,表面指标会改善却损害用户。
将主目标与护栏预先写清楚:例如在高风险错误不增加、成本和延迟可接受的前提下,提高有效解决率。只有端到端质量与业务反馈共同支持,才有依据说客服系统真正变好了。
报告配对结果,而不是只报告两个均值。 对同一批 N 个问题,分别统计“旧对新对、旧错新对、旧对新错、旧错新错”。净改善等于“旧错新对”减去“旧对新错”,再除以 N;但对资金规则的严重回归,即便被大量简单问题的改进抵消,也应独立拦截。二元评分可用 McNemar 检验分析不一致样本,连续或分级评分可使用配对 bootstrap;两者都需要考虑样本独立性,多条来自同一客户会话时应按会话聚类处理。
上线验收还应分开看“应转人工而未转”“无需转人工却转了”和真实解决率。客服系统能够拒绝无依据回答,是质量体系的一部分;不能通过降低拒答门槛换取表面更高的自动化率。
23. 你刚才提到为了降低TTFT替换了豆包1.8 flash模型,还做了kv缓存优化。在平衡响应速度、回答准确性、调用成本这三者的时候,你们最终做了哪些关键取舍?
回答:
这道题要用实际实验回答,不能仅凭“豆包1.8 flash”这个简称推断具体模型能力、价格或缓存机制。应明确真实 model ID、服务 endpoint、模型版本、输入输出 token 分布与缓存接口;模型名称的细小差异也可能对应不同服务能力。
先定义 TTFT 的观测边界。用户感知的首 token 时间不仅包含模型 prefill,还可能包含网关、排队、检索、重排和网络:
T
T
T
F
T
≈
T
n
e
t
w
o
r
k
+
T
q
u
e
u
e
+
T
r
e
t
r
i
e
v
a
l
+
T
p
r
e
f
i
l
l
+
T
f
i
r
s
t
d
e
c
o
d
e
T_{\\mathrm{TTFT}}\\approx T_{\\mathrm{network}}+T_{\\mathrm{queue}}+ T_{\\mathrm{retrieval}}+T_{\\mathrm{prefill}}+T_{\\mathrm{first\\ decode}}
TTTFT≈Tnetwork+Tqueue+Tretrieval+Tprefill+Tfirst decode
这只是顺序链路的拆解,实际有并行与重叠,不能把所有阶段耗时机械相加。总回答时长还取决于输出长度与后续解码速度。更换快模型可能改善计算部分,却无法解决慢数据库或过长队列。
区分三种缓存:单次生成中复用已计算 token 的 KV Cache;跨请求复用共同前缀的 prefix cache;直接复用答案的应用缓存。前缀缓存主要减少匹配前缀的 prefill 开销,不自动加速后续每一个 decode token。命中要求与具体引擎有关,模型、token 序列、适配器和多模态输入等必须兼容;用户权限与租户隔离也不能因缓存而省略。
托管 API 用户通常不能直接修改服务端 KV 管理,只能使用供应商开放的缓存机制或调整可复用前缀;自部署才可能配置缓存引擎、KV 容量和调度。固定模板有助命中,但不能为了命中把过时规则或无关长文本永远放进前缀。
取舍可以是:简单且可验证任务使用更快模型,困难和高风险任务升级;压缩重复上下文、控制输出长度,保留关键证据;在延迟预算内选择重排深度。用同一套独立任务测首 token、完整完成时间、质量、单次成功任务成本及 p95/p99,并分别统计冷缓存、热缓存和实际命中率。缓存越大还会占用显存、限制并发,速度、质量与成本应一起评估。
一个最小消融设计是“模型 × 缓存状态”。 用同一组问题、文档快照、并发配置与输出限制,分别运行原模型/候选模型 × 冷缓存/热缓存四种组合。冷、热实验验证缓存能带来多少收益,按真实前缀重复分布回放才估计得到实际收益;不能把重复同一个问题测到的热缓存延迟当作所有请求的延迟。
成本建议统计为“该评测批次的总调用费用 ÷ 达标完成任务数”,包含重试、重排、回退强模型与无效调用。低价模型如果频繁失败或升级,单次成功成本可能更高;总费用为正而达标数为零时,应报告无成功任务,不能返回一个误导性的零成本。延迟则按请求做端到端测量,不能把各阶段 p95 相加当作端到端 p95。
24. 请聊一个你熟悉或自研的ai应用框架。它的核心是为了解决什么问题,在实现上有哪些技术设计上的巧思,你又在什么场景里真正用它落地过?
回答:
可以选择自己确实使用或研究过的 LangGraph 作答,并区分“理解设计”和“亲手落地”。它适合表达有分支、循环、状态、暂停恢复与人工介入的工作流;LangChain 提供模型、工具和 Agent 等上层能力,两者并不是简单的新旧替代关系。
LangGraph 将任务建模为图:节点处理输入状态,边决定后续调度,状态 schema 与 reducer 定义更新规则;持久化与 checkpoint 支持恢复和人工审批。它解决的是长流程的执行组织和状态管理,而不是自动提高基础模型的事实正确率。
设计价值在于把“模型调用做什么”和“系统何时继续、暂停、重试、结束”分开,使执行路径可观察。但也会增加状态设计、版本升级、恢复语义和调试成本。固定的两三个接口调用不一定需要图框架,普通函数组合可能已经足够。
项目回答可用真实客服流程展开:意图识别 -> 权限过滤检索 -> 证据检查 -> 生成 -> 规则校验;证据不足时澄清,必要时人工接管。说明哪个节点由模型决定、哪个由确定性逻辑控制、状态如何落盘以及恢复如何避免重复副作用。
没有实际落地经历时,可以明确说完成过原型或阅读过设计,并展示能验证的实验。框架使用经验的可信度来自具体状态、故障与验收,而不是声称“用它实现了所有功能”。
25. 你提到他用点和边的图结构替代LangChain原有的链式调用。那这个框架里最核心的节点抽象具体是怎么设计的?
回答:
以 LangGraph StateGraph 为例,节点通常是同步或异步可调用对象:读取约定的 state,可接收配置或运行上下文,返回部分状态更新;特定场景也可返回 Command 等控制对象。边和条件路由负责调度,节点无需知道整个系统所有后续步骤。
状态 schema 定义字段,reducer 决定该字段如何合并更新。没有特别 reducer 的字段通常按覆盖语义更新,并行写同一字段可能发生冲突;有 reducer 的字段按其规则合并。不同节点共享的是一份有执行语义的图状态,不是允许大家任意并发修改的进程全局字典。
以下示例展示“按稳定 ID 汇总已校验文档引用”的 reducer 与节点,作为挂载进图之前可独立测试的纯函数:
from typing import Annotated, TypedDict
def merge_refs(left: dict[str, str], right: dict[str, str]):
merged = dict(left)
for key, value in right.items():
if key in merged and merged[key] != value:
raise ValueError("conflicting content for the same reference id")
merged[key] = value
return dict(sorted(merged.items()))
class State(TypedDict):
query: str
refs: Annotated[dict[str, str], merge_refs]
evidence_ready: bool
def inspect_evidence(state: State):
return {"evidence_ready": bool(state["refs"])}
节点只返回它负责的 evidence_ready 更新,不把整个旧 state 原样返回,减少覆盖并行结果的风险。该布尔检查仅演示节点契约,真实系统还需校验证据完整性、权限和时效,不能把“非空”当“足以回答”。
reducer 对相同 ID、相同内容重复合并保持幂等,对矛盾内容显式报错;稳定排序只让展示顺序确定,并不能代替业务优先级。生产中 ID 需包含合理的版本信息,schema 和静态类型也不等于自动运行时校验,外部输入必须另外验证。
26. 你刚才提到所有节点都围绕共享state做读写。那这种全局共享状态的设计,相比每个节点独立传参的朴素实现实际带来了哪些额外的代价?
回答:
首先澄清“全局共享”:图状态通常属于一次运行或一个 thread 的执行上下文,不应成为所有用户共用的可变对象。把不同租户的数据放进一个无隔离字典,会造成更严重的泄漏与并发问题,这不是框架要求的设计。
相比独立传参,共享状态降低了节点之间传递大量参数的样板代码,却引入隐式依赖:节点究竟读写哪些字段、哪些字段何时有效,可能不再从函数签名一眼看出。状态 schema 需要明确所有者、读写范围和生命周期,不能随着需求增长变成什么都装的对象。
并行场景要付出更新合并成本。两个节点写同一标量不能默认“最后写入就是对的”;列表追加可能出现重复与顺序差异;reducer 还需处理冲突、幂等和确定性。checkpointer 负责保存执行状态,不等于自动解决业务并发一致性。
大状态还增加序列化、checkpoint 存储、网络和恢复成本。把二进制图片、完整文档、客户端连接或密钥直接塞进状态并不合适,应保存受权限控制的引用、摘要和版本;并设计保留期限、脱敏、加密与最小可见性。
最后是版本演进:暂停数天的旧流程,恢复时可能遇到新 schema、新节点逻辑或失效工具凭据。需要版本标记、兼容处理、测试和明确的恢复策略。小型流程可继续使用显式传参;大型图则通过子图、局部状态和输入输出契约限制共享范围。
27. 你实际在项目里用这个框架落地工作流编排的时候,遇到过最棘手的一个和它设计特性相关的坑是什么?
回答:
这个问题应讲自己真实遇到的故障。如果没有经历,可以明确将“中断恢复导致副作用重复执行”作为复现案例,说明框架语义与修复方法,不能把假设写成实际生产事故。
一个典型陷阱是:节点先调用接口创建工单,再执行 interrupt() 等待审批。恢复时,框架可能从该节点开头重新执行,之前的创建动作再次触发。checkpoint 能保存流程进度,并不自动保证外部接口恰好执行一次;在副作用完成、结果持久化之前崩溃,同样存在重放窗口。
修复首先调整节点边界,把审批放到副作用之前;为写操作使用持久化、稳定的幂等键,例如任务 ID、业务动作及经过确认的参数版本,不要每次重试都生成新随机键。服务端通过唯一约束或幂等表原子记录操作与结果。若超时后不知道是否成功,应先查询业务状态,不直接重发。
需要跨系统可靠投递时,可采用事务 outbox、状态对账或补偿事务,但仍要说明各自的一致性范围。将副作用封装为框架支持的持久化 task 能减少部分重放,不能替代外部系统自身的幂等保障。
验证时主动注入故障:创建成功后但 checkpoint 前崩溃、重复提交恢复、审批取消、超时但服务端已成功。确认只产生一个业务结果,恢复能返回既有结果,失败有可解释状态。另一个要排查的坑是并行分支全量返回旧 state 导致字段冲突,解决方式是局部更新与明确 reducer,而不是加一次无界重试。
这类复盘的核心结论是:流程恢复、状态持久化与业务恰好一次是不同问题,可靠系统必须分别建立保证。
把恢复过程落到可查询的业务状态。 一条写操作可以经历 PENDING_APPROVAL → APPROVED → RUNNING → SUCCEEDED / FAILED / UNKNOWN。UNKNOWN 表示网络超时等原因导致客户端不知道结果,不能直接等同失败。以稳定幂等键查询服务端;已完成则返回既有结果,尚未完成再按协议重试。同一键携带不同参数必须拒绝,或经过重新审批后生成新的业务版本,防止复用旧授权执行新动作。
幂等键只能消除其业务范围内的重复:若创建工单成功后还要发通知,两项副作用仍需分别建模。事务 outbox 将业务更新与待发送事件写进同一数据库事务,消费端再去重并对账;它提供可恢复的交付基础,但不意味着所有外部渠道都支持全局恰好一次。

图 2:流程持久化与业务结果是两套需要衔接的状态。恢复时先确认已有结果,避免重复副作用。
推荐阅读
Rocky一直在运营技术交流群(WeThinkIn-技术交流群),这个群的初心主要聚焦于技术话题的讨论与学习,包括但不限于算法、开发、竞赛、科研以及工作求职等。群里有很多人工智能行业的大牛,欢迎大家入群一起学习交流~(请添加小助手微信Jarvis8866,拉你进群~)
1. 深入浅出完整解析AI Agent(AI智能体)的核心基础知识
2025年可以说是AI Agent全面落地应用的元年,因此Rocky在持续撰写对AI Agent的全维度解析文章:
深入浅出完整解析AI Agent(AI智能体)的核心基础知识
2. 深入浅出完整解析扩散模型DDPM、DDIM、Score-Based、SDE、LDM、Classifier/Classifier-Free Guidance、Rectified Flow核心基础知识
Rocky对扩散模型的本质原理与和核心基础知识进行了全面系统的深入浅出分析讲解,同时不断跟进补充扩散模型的最新技术发展,希望能给大家带来帮助:
深入浅出完整解析扩散模型DDPM、DDIM、Score-Based、SDE、LDM、Classifier/Classifier-Free Guidance、Rectified Flow核心基础知识
3. 入浅出完整解析FLUX.2、Seedream(即梦)、Z-image、GLM-Image核心基础知识
Rocky对AIGC时代“中场时刻”之后的主流AIGC创作大模型的核心基础知识进行了全面系统的深入浅出分析讲解,力求让大家通俗易懂理解AIGC时代的技术浪潮的本质价值:
入浅出完整解析FLUX.2、Seedream(即梦)、Z-image、GLM-Image核心基础知识
4. 深入浅出完整解析FLUX.1 Kontext和FLUX.1 Krea核心基础知识
Rocky对FLUX.1 Kontext和FLUX.1 Krea的核心基础知识作了全面系统的梳理与解析:
深入浅出完整解析FLUX.1 Kontext和FLUX.1 Krea核心基础知识
5. 深入浅出完整解析DeepSeek系列核心基础知识
Rocky对DeepSeek系列模型的核心基础知识作了全面系统的梳理与解析:
深入浅出完整解析DeepSeek系列核心基础知识
6. 深入浅出完整解析Stable Diffusion 3(SD 3)和FLUX.1系列核心基础知识
Rocky对Stable Diffusion 3和FLUX.1的核心基础知识作了全面系统的梳理与解析:
深入浅出完整解析Stable Diffusion 3(SD 3)和FLUX.1系列核心基础知识
7. 深入浅出完整解析Stable Diffusion XL(SDXL)核心基础知识
Rocky对Stable Diffusion XL的核心基础知识作了全面系统的梳理与解析:
深入浅出完整解析Stable Diffusion XL(SDXL)核心基础知识
8. 深入浅出完整解析Stable Diffusion(SD)核心基础知识
Rocky对Stable Diffusion 1.x-2.x系列模型的核心基础知识做了全面系统的梳理与解析:
深入浅出完整解析Stable Diffusion(SD)核心基础知识
9. 深入浅出完整解析Stable Diffusion中U-Net的前世今生与核心知识
Rocky对Stable Diffusion中最为关键的U-Net结构进行了深入浅出的全面解析,包括其在传统深度学习中的价值和在AIGC中的价值:
深入浅出完整解析Stable Diffusion中U-Net的前世今生与核心知识
10. 深入浅出完整解析LoRA(Low-Rank Adaptation)模型核心基础知识
对于AIGC时代中的“ResNet”——LoRA模型,Rocky进行了深入浅出的全面讲解:
深入浅出完整解析LoRA(Low-Rank Adaptation)模型核心基础知识
11. 深入浅出完整解析ControlNet核心基础知识
AIGC图像创作开源社区已经形成以Stable Difffusion/FLUX为核心,ConrtolNet和LoRA作为首要AI辅助工具的变化万千的AIGC图像创作工作流。
ControlNet正是让AI图像创作社区无比繁荣的关键一环,它让AIGC图像创作过程更加的可控,更有助于广泛地将AIGC算法解决方案应用到各行各业中:
深入浅出完整解析ControlNet核心基础知识
12. 深入浅出完整解析Sora、Seedance、keling等AI视频大模型核心基础知识
AI绘画和AI视频是两个互相促进、相互交融的领域,2024年无疑是AI视频领域的爆发之年,Rocky对AI视频领域核心的Sora、Seedance、Keling等大模型进行了全面系统的梳理与解析:
深入浅出完整解析Sora、Seedance、keling等AI视频大模型核心基础知识
13. 深入浅出完整解析AIGC时代Transformer核心基础知识
在AIGC时代中,Transformer为AI行业带来了深刻的变革。Transformer架构正在一步一步重构所有的AI技术方向,成为AI技术架构大一统与多模态整合的关键核心基座,大有一统“AI江湖”之势。Rocky也对Transformer模型进行持续的深入浅出梳理与解析:
深入浅出完整解析AIGC时代Transformer核心基础知识
14. 深入浅出完整解析ComfyUI、Diffusers、Stable Diffusion WebUI等主流AIGC创作框架核心基础知识
AIGC创作框架正是AIGC算法工作流的运行载体,目前主流的AIGC创作框架有ComfyUI、Diffusers、Stable Diffusion WebUI等。在传统深度学习时代,PyTorch、TensorFlow以及Caffe是传统深度学习模型的基础运行框架,到了AIGC时代,Rocky相信ComfyUI就是AIGC时代的“PyTorch”、Stable Diffusion WebUI就是AIGC时代的“TensorFlow”、Diffusers就是AIGC时代的“Caffe”:
深入浅出完整解析ComfyUI、Diffusers、Stable Diffusion WebUI等主流AIGC创作框架核心基础知识
15. 深入浅出完整解析ComfyUI、Diffusers、Stable Diffusion WebUI等主流AIGC创作框架核心基础知识
在AIGC时代中,如何快速转身,入局AIGC产业?如何成为AIGC/LLM/AI Agent算法/开发工程师?如何在学校中系统性学习AIGC/LLM/AI Agent知识,斩获心仪的AIGC/LLM/AI Agent算法/开发offer?
Don‘t worry,Rocky为大家总结整理了全面的AIGC/LLM/AI Agent算法/开发工程师成长秘籍,为大家答疑解惑,希望能给大家带来帮助:
手把手教你成为AIGC/LLM/AI Agent算法/开发工程师,斩获AIGC/LLM/AI Agent算法/开发offer!
16. AIGC产业的深度思考与分析
2023年3月21日,微软创始人比尔·盖茨在其博客文章《The Age of AI has begun》中表示,自从1980年首次看到图形用户界面(graphical user interface)以来,以OpenAI为代表的科技公司发布的AIGC模型是他所见过的最具革命性的技术进步。
Rocky也认为,AIGC及其生态,会成为AI行业重大变革的主导力量。AIGC会带来一个全新的红利期,未来随着AIGC的全面落地和深度商用,会深刻改变我们的工作、生活、学习以及交流方式,各行各业都将被重新定义,过程会非常有趣。
那么,在此基础上,我们该如何更好的审视AIGC的未来?我们该如何更好地拥抱AIGC引领的革新?Rocky准备从技术、产品、商业模式、长期主义等维度持续分享一些个人的核心思考与观点,希望能帮助各位读者对AIGC有一个全面的了解:
深入浅出全面解析AIGC时代核心价值与发展趋势(2025年版)
17. AI算法工程师的独孤九剑秘籍
为了方便大家实习、校招以及社招的面试准备,同时帮助大家提升扩展技术基本面,Rocky将符合大厂和AI独角兽价值的算法高频面试知识点撰写总结成《三年面试五年模拟》之独孤九剑秘籍:
【三年面试五年模拟】AIGC时代的算法工程师的求职面试秘籍(持续更新中)
18. 深入浅出完整解析AIGC时代中GAN(Generative Adversarial Network)系列模型核心基础知识
GAN系列模型作为传统深度学习时代的最热门生成式Al模型,在AIGC时代继续繁荣,作为Stable Diffusion/FLUX系列大模型的“得力助手”,广泛活跃于AlGC图像创作的产品与工作流中:
深入浅出完整解析AIGC时代中GAN(Generative Adversarial Network)系列模型核心基础知识
网硕互联帮助中心





评论前必须登录!
注册