第1994篇:AI工程的认知升级——从"工具使用者"到"系统设计者"的跨越
第1994篇:AI工程的认知升级——从"工具使用者"到"系统设计者"的跨越
有个问题我问过很多工程师,他们的回答让我印象深刻。
问题是:你觉得自己现在是什么阶段的AI工程师?
大部分人会说:我会用LangChain,能写RAG,会接各种LLM API,感觉还行。
然后我会问第二个问题:如果你的RAG系统在生产环境里出现答案质量下降,你的排查路径是什么?
这个问题通常会让人沉默很久。
能把第一个问题回答得很好的人,往往在第二个问题上卡住。不是因为不努力,而是因为这两个问题考察的是完全不同维度的能力——前者是工具使用能力,后者是系统设计能力。
从前者到后者,需要一次真实的认知跃迁。这篇文章,我想完整地描述这个跃迁是什么、为什么难、以及如何跨越它。
一、工具使用者的典型症状
先说说"工具使用者"阶段长什么样。不是贬义,这是每个人必须经历的阶段,包括我自己。
症状一:以框架为中心
思维方式是:先选好用什么框架(LangChain?Spring AI?LlamaIndex?),然后找对应的教程,把demo跑起来,再往业务需求上套。
这个路径本身没问题,但问题在于:当需求稍微超出框架的"舒适区"时,就会陷入困境——不知道该怎么改,只能搜有没有对应的插件或者配置项。
症状二:把LLM的输出当事实
LLM返回了一个结构化的JSON?好,直接用。LLM说这个方案可行?好,采纳。很少去想:这个输出对不对?如何验证?如果错了怎么办?
这在demo阶段无所谓,但在生产系统里是灾难。
症状三:不关心系统边界
"LLM调用超时了"——重试一下。"向量检索结果不准"——换个模型。问题是,这些处理方式都是孤立的、临时的,背后没有对系统整体行为的理解。
超时了是因为什么?模型负载?网络问题?请求太大?不同的原因需要不同的应对策略。不理解边界,就只能打补丁,补了一个漏又冒另一个。
二、系统设计者的思维框架
真正意义上的"系统设计者",思考AI工程的视角是完全不同的。
我认为,这个视角有四个核心维度:
维度一:失效模式优先
工具使用者问的是"怎么让它工作",系统设计者问的是"什么情况下会失效,怎么应对"。
AI系统的失效模式跟传统系统不一样,它有一类独特的"软失效"——系统没有报错,但输出是错的。这比硬失效更难处理,因为监控发现不了,只有用户告诉你。
设计AI系统时,我现在会专门做一个"失效模式清单":
LLM调用层失效模式:
- 超时(P99超过30s)→ 熔断 + 降级到规则引擎
- 输出格式不符合预期 → 重试(最多3次)+ 结构化修复
- 内容安全拒绝 → 返回标准错误响应,记录日志
- Token超限 → 自动截断上下文,优先保留最近内容
向量检索层失效模式:
- 相似度全部低于阈值 → 返回空,不进LLM(防止幻觉)
- 检索延迟超高(>500ms)→ 降级到关键词检索
- 索引未同步(文档更新未反映)→ 定时检查 + 告警
RAG整体失效模式:
- 充分性不足(上下文不够回答问题)→ 触发主动提问 or 拒答
- 答案自相矛盾 → 标记低置信度,进人工队列这个清单不是一次性的,而是随着系统运行不断补充的。
维度二:可观测性即设计
很多人把监控当成系统做完之后"加"的东西,这是错的。可观测性应该在设计阶段就考虑进去。
AI系统需要监控什么?
@Component
public class LLMCallMonitor {
private final MeterRegistry meterRegistry;
private final Logger auditLogger = LoggerFactory.getLogger("llm.audit");
/**
* 每次LLM调用必须经过这个方法,确保全量审计
*/
public <T> T monitoredCall(String callerId, String purpose,
Supplier<T> llmCall,
Function<T, LLMCallMetrics> metricsExtractor) {
long startTime = System.currentTimeMillis();
String traceId = MDC.get("traceId");
try {
T result = llmCall.get();
LLMCallMetrics metrics = metricsExtractor.apply(result);
long duration = System.currentTimeMillis() - startTime;
// 指标记录
recordMetrics(callerId, purpose, duration, metrics, "success");
// 审计日志(供后续分析和调优用)
auditLogger.info(buildAuditLog(traceId, callerId, purpose, duration, metrics));
return result;
} catch (Exception e) {
long duration = System.currentTimeMillis() - startTime;
recordMetrics(callerId, purpose, duration, null, "error:" + e.getClass().getSimpleName());
throw e;
}
}
private void recordMetrics(String callerId, String purpose, long duration,
LLMCallMetrics metrics, String status) {
Tags tags = Tags.of(
"caller", callerId,
"purpose", purpose,
"status", status
);
meterRegistry.timer("llm.call.duration", tags).record(duration, TimeUnit.MILLISECONDS);
meterRegistry.counter("llm.call.count", tags).increment();
if (metrics != null) {
meterRegistry.summary("llm.tokens.prompt", tags).record(metrics.getPromptTokens());
meterRegistry.summary("llm.tokens.completion", tags).record(metrics.getCompletionTokens());
meterRegistry.summary("llm.cost.usd", tags).record(metrics.getCostUsd());
}
}
}每一次LLM调用的输入、输出、耗时、token用量、成本,都要有记录。这不是可选的,这是后续所有优化的基础数据。
维度三:成本意识贯穿始终
工具使用者很少想成本,因为本地跑demo几乎没有成本。但生产系统里,LLM成本是一个非常现实的约束。
我见过一个项目,上线第一个月的LLM调用费用是预算的4倍,最后不得不大幅缩减功能。这种情况完全可以在设计阶段避免。
成本优化是一个系统性的工程,不是换个便宜模型那么简单:
实际项目里,我通常能通过这些手段把LLM调用成本降低40%-60%,在不损失核心效果的前提下。
维度四:人机协作的边界设计
这是最难的维度,也是最体现系统设计水平的维度。
AI系统不是一个完全自动化的黑盒,它需要在合适的地方把决策权交还给人。问题是:哪些地方是"合适的地方"?
这需要对业务风险有深刻理解。我的判断框架是:
- 高确定性、低风险:完全自动化,无需人工参与
- 高确定性、高风险:自动化执行,但要有审计日志和回滚机制
- 低确定性、低风险:自动化执行,并发通知人工(不阻塞)
- 低确定性、高风险:强制人工审核,AI只提供建议和依据
public enum HumanInLoopPolicy {
FULLY_AUTOMATED, // 完全自动
AUTO_WITH_AUDIT, // 自动+审计
AUTO_WITH_NOTIFICATION, // 自动+通知
REQUIRE_APPROVAL; // 需要审批
public static HumanInLoopPolicy decide(double confidence, RiskLevel risk) {
if (confidence >= 0.90 && risk == RiskLevel.LOW) return FULLY_AUTOMATED;
if (confidence >= 0.90 && risk == RiskLevel.HIGH) return AUTO_WITH_AUDIT;
if (confidence >= 0.70 && risk == RiskLevel.LOW) return AUTO_WITH_NOTIFICATION;
return REQUIRE_APPROVAL;
}
}三、认知跃迁为什么难发生
我观察到,很多工程师在"工具使用者"阶段卡了很久,不是因为不努力,而是因为跨越这个阶段需要的东西,不是靠刷教程能得到的。
原因一:缺少生产故障的洗礼
在demo环境里,代码跑通就是成功。但生产环境会给你上一堂截然不同的课:当系统在高并发下崩溃时、当LLM的输出在某类边缘输入上全面失效时、当成本在某次流量高峰后暴涨10倍时……这些真实的"痛"才会逼着你去想系统层面的问题。
所以我建议:不要只做demo,要尽快把真实的工作量压到你的系统上。即使只是一个小项目,只要是真实流量,你就会遇到你在文章和教程里见不到的问题。
原因二:缺少系统性的失效样本
系统设计的能力,本质是对各种失效模式的深刻认知——你经历过或见过越多的失效,你在设计时就越有预见性。
这也是为什么经验丰富的架构师在设计评审时总能提出"如果XXX情况下怎么办",不是他们运气好,是他们被坑过。
可以用一个方法加速这个积累:主动学习别人的故障复盘。开源社区、技术博客、各大公司的技术年报里,有大量的生产故障分析,这些是无价的失效样本库。
原因三:对"工程"本质的误解
很多人认为工程=技术实现,但实际上,工程=在约束条件下实现目标。
约束包括:成本约束、时间约束、可靠性约束、团队能力约束……真正的工程能力是在所有这些约束下找到最优解,而不是追求技术上的完美。
四、一个实际的进阶路径
我没有一套完美的"升级攻略",但有一些我认为有效的具体建议:
第一步:为你的每个AI调用加上完整的监控
不要等系统出问题了再加,现在就加。能看到的指标越多,你对系统的理解就越深。
第二步:为你的系统写一份失效模式文档
把所有你能想到的"系统可能怎么出错"写下来,然后想每种情况的应对策略。这个过程本身就是系统设计能力的训练。
第三步:做一次完整的成本分析
把你的系统一个月的LLM调用成本算清楚,然后问自己:有没有哪些调用是不必要的?哪些可以用更便宜的方案替代?
第四步:引入真实用户,让系统接受压力
哪怕是内部用户、只有10个人的测试组,真实的使用会暴露所有你没想到的边界情况。
第五步:建立反馈闭环
设计一个机制,让用户的"这个结果不对"能够自动变成系统改进的输入。这是系统持续进化的基础。
五、跨越之后看到的风景
说一个跨越之后最明显的变化:你开始能在设计阶段"看到"风险,而不是等到风险发生了才意识到。
这种"前瞻性"不是天生的,是被坑出来的。每一次生产故障、每一次成本超支、每一次用户投诉,如果你认真复盘了,都会在你的大脑里留下一个"模式"。下次看到类似的系统设计时,那个模式就会自动触发。
这就是系统设计能力的本质:足够丰富的失效模式库,加上清晰的权衡框架。
从工具使用者到系统设计者,不是一个技术栈的切换,而是一次思维方式的真实转变。这个转变发生的时刻,往往是某次你被坑得一塌糊涂之后,静下来想清楚了为什么——的那个夜晚。
每个工程师都要经历这几个夜晚。希望你经历得早一些,然后从那里出发。
