Prompt 写得很长,模型仍然可能改错文件、误解业务规则、生成看似合理但跑不通的代码。新项目里 AI 像加速器,到了历史业务里却像盲人摸象。把这些现象放回信息论的视角看,核心并不神秘:AI Coding 的大部分优化,本质上都在对抗熵增,也就是减少模型面对代码库时的不确定性。
Prompt 不是越长越好,信息密度才关键
很多人遇到 AI 输出异常时,第一反应是继续补 Prompt:技术栈、目录结构、业务背景、编码规范、边界条件全部塞进去。但模型真正需要的不是“更多字”,而是“更少歧义”。
一个低质量 Prompt 可能很长,却包含大量无法执行的信息:
- “按最佳实践实现”没有指出项目里的最佳实践在哪里。
- “不要破坏现有逻辑”没有说明哪些逻辑是外部契约。
- “参考已有代码风格”没有给出具体文件或函数。
- “处理异常情况”没有列出哪些异常在业务上有意义。
从信息论角度看,这些描述没有有效降低搜索空间。模型仍然要猜:该改哪一层?该复用哪个 helper?错误码怎么设计?测试放在哪里?
更好的方式是把不确定性压缩成可定位、可验证的上下文:
任务:给订单取消接口增加“已发货不可取消”的校验。
必须阅读:
- app/services/order_service.py
- app/models/order.py
- tests/test_order_cancel.py
约束:
- 不新增状态枚举,只使用 OrderStatus.SHIPPED
- 已发货时返回现有错误码 ORDER_ALREADY_SHIPPED
- 保持 cancel_order(order_id, user_id) 的函数签名不变
- 补一个失败用例和一个原有成功路径回归用例
完成标准:
- pytest tests/test_order_cancel.py 通过
这段 Prompt 不靠“情绪强度”驱动模型,而是给它明确的信息边界:文件、符号、约束、验证命令。它减少了模型的猜测空间。
为什么新项目更容易成功
新项目的代码熵通常更低。目录少、历史包袱少、隐式规则少,AI 在较小的状态空间里搜索,输出正确结果的概率自然更高。
历史业务则相反:
- 同一个概念可能有多个旧名字。
- 注释和真实行为可能已经背离。
- 线上依赖某个“看起来多余”的分支。
- 测试覆盖不完整,无法告诉 AI 什么不能动。
- 业务规则藏在调用链、配置、数据库数据甚至工单记忆里。
这就是为什么“让 AI 重构整个模块”经常翻车。不是模型不会写代码,而是它拿到的信息不足以区分“冗余代码”和“历史契约”。当上下文缺口太大时,模型会用概率补齐缺失信息,于是生成了“合理但错误”的实现。
工程上要做的不是幻想一次 Prompt 解决所有问题,而是主动建设低熵环境:清晰命名、局部测试、稳定接口、可搜索的决策记录、能跑的验证命令。这些东西平时看起来不像 AI 能力,却直接决定 AI Coding 的上限。
可以这样实践:给 AI 一个上下文清单生成器
如果团队经常让 AI 处理历史仓库,可以先用脚本生成一个“任务上下文包”。它不替你理解业务,但能把模型最容易漏掉的信息整理出来:相关文件、测试文件、符号位置、近期变更。
下面是一个可复制运行的 Python 脚本。运行前把 KEYWORDS 改成你的任务关键词,例如 cancel_order、OrderStatus、ORDER_ALREADY_SHIPPED。
#!/usr/bin/env python3
from pathlib import Path
import subprocess
ROOT = Path.cwd()
KEYWORDS = ["cancel_order", "OrderStatus", "ORDER_ALREADY_SHIPPED"]
INCLUDE_SUFFIXES = {".py", ".js", ".ts", ".tsx", ".go", ".java", ".md", ".yaml", ".yml"}
SKIP_DIRS = {".git", "node_modules", ".venv", "venv", "dist", "build", "__pycache__"}
def iter_files():
for path in ROOT.rglob("*"):
if any(part in SKIP_DIRS for part in path.parts):
continue
if path.is_file() and path.suffix in INCLUDE_SUFFIXES:
yield path
def grep_keywords():
hits = []
for path in iter_files():
try:
lines = path.read_text(encoding="utf-8", errors="ignore").splitlines()
except OSError:
continue
for i, line in enumerate(lines, start=1):
if any(keyword in line for keyword in KEYWORDS):
hits.append((path, i, line.strip()))
return hits
def recent_changes():
try:
out = subprocess.check_output(
["git", "log", "--oneline", "--decorate", "-n", "8"],
text=True,
stderr=subprocess.DEVNULL,
)
return out.strip()
except Exception:
return "git log unavailable"
if __name__ == "__main__":
print("# AI Coding Context Pack\n")
print("## Task Keywords")
for keyword in KEYWORDS:
print(f"- {keyword}")
print("\n## Keyword Hits")
hits = grep_keywords()
if not hits:
print("No keyword hits found. Broaden KEYWORDS before asking AI to edit code.")
else:
for path, line_no, line in hits[:80]:
print(f"- {path}:{line_no}: {line}")
print("\n## Recent Git Changes")
print(recent_changes())
print("\n## Suggested Prompt")
print("""
Please solve the task using only the relevant files above.
Before editing, identify the existing behavior and the tests that protect it.
Keep public function signatures unchanged unless explicitly required.
After editing, run the narrowest relevant test command and report the result.
""".strip())
保存为 ai_context_pack.py 后运行:
python3 ai_context_pack.py > context.md
然后把 context.md 的内容连同任务描述一起交给 AI。这个脚本的价值不在于“自动化智能”,而在于把分散的信息收拢起来,降低模型的初始不确定性。
把熵降下来,比追新工具更重要
AI Coding 的工具会继续变化:更大的上下文窗口、更强的 Agent、更深的 IDE 集成都会出现。但工程里的基本矛盾不会消失:模型需要足够的信息,才能稳定地产生正确修改。
落地时可以用一张简单清单判断任务是否适合交给 AI:
- 目标能否用一句话定义清楚?
- 相关文件能否限定在少数几个入口?
- 是否有测试或命令验证结果?
- 是否存在隐藏业务规则,需要人先补充?
- 是否要求大范围重构,而现有行为又缺少保护?
如果答案大多是否定的,先别急着写更长的 Prompt。应该先补测试、找入口、整理约束、缩小变更面。AI 擅长在明确边界内加速,不擅长替团队偿还所有历史不确定性。
真正有效的 AI Coding,不是把模型当成“懂一切的同事”,而是把它当成一个高吞吐的概率系统。你给它的信息越干净,约束越明确,反馈越快,它输出稳定代码的概率就越高。所谓对抗熵增,落到工程现场,就是把模糊任务变成可定位、可修改、可验证的小闭环。