开篇:如果手里只有锤子,一切看起来都像钉子
这句话在软件工程领域流传了几十年。2025-2026 年的版本变成了:
"如果你的工具链里有 LLM API,一切看起来都该用 AI 解决。"
我看到太多这样的例子:
- 一个简单的字符串匹配任务 → 用了 GPT-4,响应 3 秒,成本 $0.05/次。实际上用正则表达式只要 2ms,零成本
- 一个"如果 A 则 B"的业务规则 → 用了 LLM 做决策。实际上一个 if-else 更可靠
- 一个关键词提取功能 → 用了 Claude API。实际上 TF-IDF 就够用了
这让我想到一个在安全领域已经存在多年的原则:最小权限原则(Principle of Least Privilege)——每个程序只应该拥有完成其任务所必需的最小权限。
同样的逻辑可以应用到 AI 使用上:最小 AI 原则(Principle of Least AI)——每个问题只应该使用解决它所需的最小 AI 能力。
这不是"反 AI"的文章——恰恰相反,我相信 AI 是过去 20 年最重要的技术之一。但正因为重要,才需要更谨慎地使用。
一、什么是"最小 AI 原则"
最小 AI 原则(Principle of Least AI)的核心思想:
面对一个问题时,先用最简单的非 AI 方案。只有当简单方案无法满足需求时,才引入 AI。而当引入 AI 时,选择能满足需求的最低能力层级的模型。
这个概念可以用一个决策树来表达:
问题来了
↓
能不用 AI 解决吗?
├── 能 → 用最简单的方式(正则、规则引擎、简单算法)
└── 不能 →
├── 轻量 ML 能解决吗?(分类器、TF-IDF、相似度)
│ ├── 能 → 用小模型 + 嵌入式推理
│ └── 不能 →
│ ├── 小型 LLM 能解决吗?(7B-13B 参数)
│ │ ├── 能 → 用开源小模型
│ │ └── 不能 →
│ │ ├── 中型模型能解决吗?(70B 级别)
│ │ │ ├── 能 → 用中等模型
│ │ │ └── 不能 →
│ │ │ └── 用最大型号的模型
│ │ └── (但这种情况很少见)
│ └── (这种情况也比很多人想的多)
└── (比很多人想的少)
这个决策树的核心是:每次引入 AI 都是有一个成本——金钱成本、延迟成本、不可预测性成本。 使用最小 AI 就是在选择一个你愿意为此付出的最小代价。
二、为什么需要这个原则
2.1 成本三角
每个技术方案都有一个"成本三角":
准确性
▲
│
速度 ◄──────┼──────► 可预测性
│
│
成本
不同方案在三角上的位置:
| 方案 | 准确性 | 速度 | 可预测性 | 成本/次 |
|---|---|---|---|---|
| 正则表达式 | 高(匹配特定模式) | <1ms | 确定性的 | $0.000001 |
| 规则引擎 | 高(已知规则) | <5ms | 确定性的 | $0.000005 |
| 小模型(轻量 ML) | 中-高 | 5-50ms | 统计性的 | $0.0001 |
| 小型 LLM(7B-13B) | 高(通用) | 100-1000ms | 概率性的 | $0.001-0.005 |
| 大型 LLM(70B+) | 最高 | 1-5s | 概率性的 | $0.01-0.05 |
正则表达式的准确率和成本远超 LLM——在它适用的场景下。
这不是贬低 LLM。只是说:用高射炮打蚊子不是好策略。 当你面对一个问题时,先问问自己:这个问题的复杂度是否真的需要 LLM 级别的处理能力?
2.2 可预测性成本
一个常被忽视的成本是不可预测性。
# 正则表达式版本:确定性的
def extract_email(text: str) -> str:
import re
pattern = r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b'
match = re.search(pattern, text)
# 永远返回相同的结果,不需要测试覆盖率之外的测试
return match.group(0) if match else None
# LLM 版本:概率性的
def extract_email_llm(text: str) -> str:
response = llm.invoke(f"从以下文本中提取邮箱地址:{text}")
# 每次返回的结果可能不同
# 需要测试:边界情况、注入攻击、多语言支持
# 需要监控:响应质量、延迟波动
# 需要回退:当 LLM 不可用时
return response.content
正则表达式版本:一行代码,永远返回相同结果。不需要测试 prompt、不需要回退机制、不需要监控输出质量。
LLM 版本:每次调用都可能不同。需要用更复杂的测试、更多的监控、和更多的回退逻辑来处理它的不可预测性。
这个"额外成本"在预估阶段经常被忽略。
三、具体实践
3.1 分类任务:从 LLM 降到规则
# 场景:判断用户消息是不是投诉
# ❌ 过度 AI:
def is_complaint_llm(message: str) -> bool:
"""用 LLM 判断是否为投诉"""
prompt = f"判断以下用户消息是否为投诉(是/否):{message}"
response = llm.invoke(prompt)
return "是" in response.content
# 成本:~$0.02/次
# 延迟:~1.5s
# 可靠度:~95%(还会因为 prompt 微调而波动)
# ✅ 最小 AI:
def is_complaint_keyword(message: str) -> bool:
"""用关键词规则判断是否为投诉"""
COMPLAINT_KEYWORDS = [
"投诉", "差评", "退款", "赔偿",
"太差了", "无法接受", "强烈不满",
"complaint", "refund", "terrible",
]
message_lower = message.lower()
return any(kw in message_lower for kw in COMPLAINT_KEYWORDS)
# 成本:几乎为零
# 延迟:<1ms
# 可靠度:对于已知模式 ~100%
# 可以独立测试,不依赖外部 API
# 折中方案:先快速通道,再 LLM 兜底
def is_complaint_hybrid(message: str) -> tuple[bool, str]:
"""
混合方案:
1. 关键词快速通道(覆盖 ~70% 的投诉)
2. 未命中关键词的再用 LLM 判断
"""
# 快速通道
if is_complaint_keyword(message):
return True, "keyword_match"
# 如果业务要求高覆盖,再引入 LLM
# 但这里只对"疑似投诉"做 LLM 判断
# 而不是所有消息
SUSPICIOUS_PATTERNS = ["退", "赔", "差", "慢", "错"]
if any(p in message for p in SUSPICIOUS_PATTERNS):
result = llm.invoke(f"判断是否为投诉(只回答是/否):{message}")
return "是" in result.content, "llm_fallback"
return False, "no_match"
3.2 文档分类:从 LLM 降到小模型
# 场景:对用户反馈进行主题分类(5 个类别)
# ❌ 过度 AI:
def classify_with_llm(text: str) -> str:
"""用 LLM 做 5 分类"""
categories = ["性能", "功能", "界面", "价格", "其他"]
prompt = f"将以下用户反馈分类到:{', '.join(categories)}\n反馈: {text}\n类别:"
response = llm.invoke(prompt)
return response.content.strip()
# 成本:~$0.01/次
# 处理 10000 条/天 = $100/天
# ✅ 最小 AI:
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.naive_bayes import MultinomialNB
import joblib
class TextClassifier:
"""
轻量级文本分类器
用于替代 LLM 的多分类任务
"""
def __init__(self):
self.vectorizer = TfidfVectorizer(max_features=5000)
self.classifier = MultinomialNB()
self.is_trained = False
def train(self, texts: list[str], labels: list[str]):
"""用带标注的数据训练"""
X = self.vectorizer.fit_transform(texts)
self.classifier.fit(X, labels)
self.is_trained = True
def predict(self, text: str) -> str:
"""预测分类"""
if not self.is_trained:
return "模型未训练"
X = self.vectorizer.transform([text])
return self.classifier.predict(X)[0]
def predict_with_confidence(self, text: str) -> tuple[str, float]:
"""预测分类并返回置信度"""
if not self.is_trained:
return "模型未训练", 0.0
X = self.vectorizer.transform([text])
probs = self.classifier.predict_proba(X)[0]
max_prob = max(probs)
prediction = self.classifier.predict(X)[0]
return prediction, max_prob
# 使用方式
classifier = TextClassifier()
# 用 1000 条历史标注数据训练
classifier.train(
texts=["页面加载太慢了", "功能很好用", "按钮太小"],
labels=["性能", "功能", "界面"]
)
# 预测
category, confidence = classifier.predict_with_confidence("网站打不开")
if confidence > 0.7:
print(f"分类: {category} (置信度: {confidence:.2%})")
else:
# 低置信度时再用 LLM
print(f"低置信度 ({confidence:.2%}),改用 LLM 兜底")
category = classify_with_llm("网站打不开")
训练好之后,这个分类器的推理成本趋近于零,而且可以在本地运行,不依赖外部 API。
3.3 代码审查:从 LLM 降到 lint
# 场景:检测代码中的常见问题
# ❌ 用 LLM 做代码审查
def review_code_llm(code: str) -> list[str]:
"""让 AI 审查代码"""
response = llm.invoke(f"请检查以下代码的问题:{code}")
return parse_issues(response.content)
# 延迟:3-5 秒
# 成本:$0.05-0.10/次
# 不稳定:每次可能发现不同的问题
# ✅ 先用 lint 覆盖基础问题
def review_code_lint(code: str) -> list[str]:
"""先用静态分析工具覆盖基础问题"""
import subprocess
result = subprocess.run(
["pylint", "--from-stdin", "temp.py"],
input=code,
capture_output=True,
text=True,
)
issues = parse_pylint_output(result.stdout)
# 只有 lint 无法覆盖的才用 AI
if has_complex_logic(code):
ai_issues = review_code_llm(code)
issues.extend(ai_issues)
return issues
先 lint,再 LLM。Lint 能在毫秒级别覆盖 80% 常见问题。只在需要分析复杂业务逻辑时才引入 LLM。
四、一个真实的优化案例
4.1 优化前后对比
某电商平台的内容审核系统:
优化前(全部消息走 LLM 审核):
- 日均处理量:500,000 条
- LLM 成本:$0.03/次 × 500,000 = $15,000/天
- 平均延迟:2.3 秒
- 准确率:94%
优化后(三级审核体系):
- 第一级(关键词过滤):60% 的消息直接通过或拒绝,零成本
- 第二级(小模型分类):30% 的消息用小模型处理
- 第三级(LLM):只剩 10% 的模糊消息走 LLM
- 总成本:$1,500/天(降低了 90%)
- 平均延迟:0.3 秒
- 准确率:维持 94%(没有下降)
class TieredContentModeration:
"""
三级内容审核体系
实现最小 AI 原则:
- 第一级:规则引擎(零 AI)
- 第二级:小模型分类(轻量 ML)
- 第三级:LLM(最低优先级)
"""
def __init__(self, llm_model):
self.llm = llm_model
self.keyword_filter = KeywordFilter() # 规则引擎
self.classifier = FastTextClassifier() # 小模型
self.stats = {"tier1": 0, "tier2": 0, "tier3": 0}
def moderate(self, content: str) -> tuple[str, float]:
"""
三级审核
返回:
- decision: "allow" | "reject" | "review"
- confidence: 0-1
"""
# 第一级:关键词快速通道(零 AI,<1ms)
keyword_result = self.keyword_filter.check(content)
if keyword_result["certain"]:
self.stats["tier1"] += 1
return keyword_result["decision"], 1.0
# 第二级:小模型分类(轻量 ML,5ms)
prediction, confidence = self.classifier.predict_with_confidence(content)
if confidence > 0.9:
self.stats["tier2"] += 1
return prediction, confidence
# 第三级:LLM 兜底(高成本,2-3s)
self.stats["tier3"] += 1
result = self.llm.moderate(content)
return result["decision"], result["confidence"]
五、什么时候应该用 AI
最小 AI 原则不是说"不要用 AI"。是说"在你需要的时候用,不需要的时候别用"。
5.1 适合 AI 的场景
✅ 真正适合用 AI 的场景:
- 自然语言理解(意图识别、情感分析)
- 内容生成(草稿、摘要、翻译)
- 模糊匹配(拼写纠正、语义搜索)
- 复杂决策辅助(需要综合大量上下文判断)
- 异常情况处理(规则引擎覆盖不到的场景)
❌ 不适合 AI 的场景:
- 确定性操作("如果 A 则 B"的逻辑)
- 精确匹配(邮箱格式验证、手机号校验)
- 高频低价值操作(每一次用户点击都调用一次 LLM)
- 可预测的数据处理(排序、过滤、聚合)
5.2 选择模型的决策框架
当你确定需要 AI 时,选择最小的合适模型:
def select_model(task_description: str,
requirements: dict) -> str:
"""
根据任务需求选择最小合适的模型
参数:
task_description: 任务描述
requirements: {
"max_latency_ms": int, # 最大可接受延迟(毫秒)
"max_cost_per_call": float, # 单次调用最大成本
"need_reasoning": bool, # 是否需要推理能力
"need_long_context": bool, # 是否需要长上下文
"accuracy_minimum": float, # 最低准确率要求
}
"""
# 第一问:需要 LLM 吗?
if not requirements.get("need_reasoning"):
return "no_llm_needed"
# 第二问:小模型是否够用?
if requirements.get("accuracy_minimum", 0.9) <= 0.85:
# 如果准确率要求不高
return "7b_model"
# 第三问:延迟和成本约束
max_latency = requirements.get("max_latency_ms", 1000)
if max_latency < 200: # 200ms 以内
return "7b_model_quantized" # 量化的小模型,最快
elif max_latency < 500:
return "13b_model"
else:
# 延迟要求宽松
if requirements.get("need_long_context"):
return "large_model_with_long_context"
return "70b_model"
# 默认回退
return "medium_model"
六、我的观点:AI 应该是一种能力,不是一种默认
写这篇文章的目的不是批评"多用 AI"——我自己每天都在用 AI 写代码、调试、写作。
但我担心一件事:当 AI 成为所有问题的默认方案时,解决问题的能力反而会下降。
原因很简单:如果你每次遇到问题都习惯性地问 AI,你慢慢就会失去"自己先试试"的习惯。而"自己先试试"恰恰是培养解决问题能力的方式。
最小 AI 原则不是在技术上限制你,是在习惯上给你一个缓冲。它想让你在调用 AI 之前先问自己:"这个问题真的需要 AI 吗?有没有更简单的方式?"
如果答案是"真的需要",那就放心地用。但如果答案是"好像用正则也能行"——那先试试正则。
结尾
最小 AI 原则可以用三句话总结:
- 先用最简单的方案——正则、规则引擎、小模型。如果三行代码能解决,不要调 API
- 引入 AI 要有明确的边界——清晰的输入输出定义,明确的失败处理
- AI 应该是最后的选择,而不是默认的选项——让简单方案覆盖 80% 的场景,AI 处理剩下 20%
从下个任务开始,试试先问自己:"不用 AI 能解决吗?" 如果答案是"能",先尝试不用 AI 的方式。你可能会发现,很多时候你的直觉比想象中更够用。
文章由文字工作者编写。最小 AI 原则的提出受最小权限原则的启发。成本数据基于 2026 年中公开 API 价格估算。
七、最小 AI 原则在团队中的实践
7.1 团队规范示例
如果你想让团队也遵循这个原则,可以考虑建立一个简单的决策流程:
团队规范:AI 使用决策流程
1. 写代码前先问:这个问题能不用 AI 解决吗?
- 能 → 写标准的 if-else / 正则 / 算法
- 不能 → 进入步骤 2
2. 如果用 AI:能满足需求的最小模型是什么?
- 规则引擎 / 简单算法 → 不要用任何模型
- 文本分类 / 关键词匹配 → 小模型 / TF-IDF
- 简单文本生成 → 7B-13B 模型
- 复杂推理 → 70B+ 模型
3. 每次代码审查时增加一个检查项:
- "这个 LLM 调用是否可以用非 AI 方案替代?"
- 如果回答不了,说明可能用过度了
4. 每个 sprint 审查 AI 使用情况:
- 统计 LLM API 调用次数和成本
- 找出可以优化掉的"过度 AI"调用
- 目标:每条 LLM 调用都有明确的必要性
7.2 代码审查中的检查清单
在 Code Review 时,增加几个针对 AI 使用的检查项:
# CODE REVIEW CHECKLIST - AI USAGE
#
# 看到 LLM 调用时,问以下问题:
#
# [ ] 这个调用可以用 if-else / 规则引擎替代吗?
# [ ] 这个调用可以用小模型(<7B)替代吗?
# [ ] 如果 LLM 超时或返回空值,有回退方案吗?
# [ ] 调用结果有校验逻辑吗(不是直接信任 LLM 输出)?
# [ ] 有没有缓存?相同输入是否反复调用?
# [ ] 是否记录了调用的性能和成本?
#
# 如果有超过 2 项回答"否",需要重新讨论设计。
这个检查清单帮我避免了几次"过度 AI 设计"——最有意思的一次,我要用 LLM 做"中文数字转阿拉伯数字"("一万二千三百四十五" → "12345"),结果 review 之后改成了 30 行的纯 Python 函数。更快、更便宜、更可靠。
结尾
最小 AI 原则可以用三句话总结:
- 先用最简单的方案——正则、规则引擎、小模型。如果三行代码能解决,不要调 API
- 引入 AI 要有明确的边界——清晰的输入输出定义,明确的失败处理
- AI 应该是最后的选择,而不是默认的选项——让简单方案覆盖 80% 的场景,AI 处理剩下 20%
从下个任务开始,试试先问自己:"不用 AI 能解决吗?" 如果答案是"能",先尝试不用 AI 的方式。你可能会发现,很多时候你的直觉比想象中更够用。
文章由文字工作者编写。最小 AI 原则的提出受最小权限原则的启发。成本数据基于 2026 年中公开 API 价格估算。