提出用 model-lock.json 记录模型输入哈希而非仅模型名,确保 AI 生成结果可复现,避免同一 prompt 产出不一致的问题。
你的 CI 流水线可能在一夜之间无任何源代码变动的情况下失败。代码完全相同,测试套件完全相同,然而周五通过的 AI 生成补丁在周一却无法通过。通常的罪魁祸首是一个"浮动模型":提供商在同一个 API 名称背后更新了权重或改变了推理行为,导致你的 prompt 现在产生了细微不同的输出。
大多数团队绝不会部署一个未固定的依赖,但它们仍然调用 model='gpt-4' 或一个通用的免费模型端点,并期望得到可复现的结果。模型就是一个依赖。把它当作依赖来对待。
不要只记录你使用了哪个模型名称,而是记录产生该输出的输入。下面是一个最小的 model-lock.json:
{
"schema": "model-lock/v1",
"model": {
"provider": "your-provider",
"name": "free-model-7b",
"revision": "2026-08-01",
"temperature": 0.2,
"max_tokens": 1024
},
"inputs": {
"prompt_template_hash": "sha256:9f2c4d8e...",
"test_suite_hash": "sha256:c71a9b02..."
},
"evidence": {
"generated_at": "2026-08-14T08:00:00Z",
"output_hash": "sha256:beef1234...",
"tests_passed": 17,
"tests_total": 17
}
}
两个输入哈希比模型名称更重要。如果其中任何一个发生变化,先前的证据就不再适用于当前的生成路径。
下面的脚本特意做得非常小,以便你可以一次性读完;把它当作一个起点检查,而不是安全边界。
import hashlib
import json
import sys
from pathlib import Path
def sha256_file(path: Path) -> str:
return "sha256:" + hashlib.sha256(path.read_bytes()).hexdigest()[:12]
def sha256_text(text: str) -> str:
return "sha256:" + hashlib.sha256(text.encode()).hexdigest()[:12]
def check_drift(prompt_file: Path, tests_dir: Path, lock_file: Path) -> None:
lock = json.loads(lock_file.read_text())
prompt_hash = sha256_file(prompt_file)
test_hash = sha256_text(
"".join(p.read_text() for p in sorted(tests_dir.rglob("*.py")))
)
failures = []
if prompt_hash != lock["inputs"]["prompt_template_hash"]:
failures.append(
f"prompt template drift: {lock['inputs']['prompt_template_hash']} -> {prompt_hash}"
)
if test_hash != lock["inputs"]["test_suite_hash"]:
failures.append(
f"test suite drift: {lock['inputs']['test_suite_hash']} -> {test_hash}"
)
if failures:
print("Drift detected. Re-evaluate the model before trusting generated code.")
for failure in failures:
print(" -", failure)
sys.exit(1)
print(f"No input drift. Lockfile {lock_file} is consistent.")
if __name__ == "__main__":
check_drift(Path("prompts/gen.prompt"), Path("tests"), Path("model-lock.json"))
在每个 AI 辅助步骤之前在 CI 中运行它。如果 prompt 或测试套件发生了变动但锁文件没有重新生成,该步骤就会失败。
人们跳过这一步的主要原因在于基础设施。运行多个模型评估通常需要一台 GPU 机器或付费的 API 额度。为了保持评估成本低廉,你可以针对一个免费服务器运行它。MonkeyCode 的运营者表示该平台提供免费模型访问和免费服务器选项;这去除了"我在测试模型漂移之前需要一块 GPU"的借口。披露:本文是作为 MonkeyCode 产品推广的一部分准备的。锁文件本身是厂商无关的,因此相同的检查可以针对任何 OpenAI 兼容端点运行。
对于锁文件而言,传输层并不重要。重要的是你能够在改变模型、prompt 或测试套件时负担得起重新运行 prompt 和测试的成本。
免费模型也不是单一固定的人工物。如果你尝试了两个不同的免费模型,将两个输出和测试通过计数记录到一个 alternatives 数组中。然后你就可以基于证据来提升一个候选者,而不是靠记忆。
一次实用的对比流程如下:
这将模糊的"这个免费模型这周感觉更好"变成了一条可复现的记录。
提供商的重修订字符串并不总是暴露出来或保持稳定的。像 free-model-7b 这样的名称可能指向不同时间的不同权重,即使你没有改变任何东西。
哈希只能证明输入字节没有改变。它不能证明输出是正确的、安全的或可用于生产的。
免费层可以改变配额、可用性和数据保留。不要围绕一个免费端点设计一个永久的生产级关卡而不准备回退方案。
如果提供商没有报告,hash prompt 模板和测试套件无法捕获模型内部行为的漂移;你仍然需要按计划重新运行。
如果你在向第三方免费端点发送专有代码或密钥,先解决合规边界问题。锁文件并不能修复数据泄露。
如果你的生成任务是开放式的创意写作或探索,hash prompt 和测试可能会增加噪音而不会带来太多好处。
如果你已经使用了一个具有不可变、已记录版本的模型端点,并且你在每个版本发布时都重新运行评估,那么完整的漂移检测脚本可能就过于杀鸡用牛刀了。
把 model-lock.json 放到你的 prompt 文件旁边。下次 CI神秘失败时,你就能够知道模型是否在你不知情的情况下发生了变动——而不是先去怪代码。