介绍如何构建一个简单的监控机制,检测免费模型端点在未通知情况下改变输出格式或指令遵循行为,避免下游 JSON 解析失败等问题。
免费模型端点经常在没有任何变更日志的情况下,改变路由、量化方式、上下文处理以及指令遵循行为。你察觉到这些问题时,往往是 JSON 解析失败了,或者你的 Shell 助手开始把文本响应当作命令来执行。这种失败通常不是模型"出错"了,而是输出契约发生了漂移。
对于个人项目而言,你很少需要一套沉重的可观测性基础设施。你只需要一个廉价的检查机制:定时发送两个固定的输入,然后当标准化后的输出与上一次运行结果不再匹配时,通知你。
这个看门狗设计得刻意精简:
它向配置好的模型端点发送两个固定 Prompt。
它用 trim().toLowerCase() 对每个响应进行标准化。
它计算一个短 SHA-256 摘要,而非原始输出,这样历史文件能保持小巧。
它记录响应中是否保留了必需的 JSON Key。
如果摘要或 Key 状态与上一次运行不同,Shell 包装脚本会打印出差异,并可以发送通知。
这不是基准测试,所以它不会告诉你某个模型是否比另一个更好。它只会告诉你:你依赖的端点是否发生了你的应用应该关注的变更。
创建一个小型 Node.js 项目,使用 TypeScript:
mkdir drift-watchdog && cd drift-watchdog
npm init -y
npm install -D typescript @types/node tsx
将其保存为 probe.ts:
import { createHash } from "node:crypto";
type Probe = {
id: string;
prompt: string;
expectKey?: string;
};
const probes: Probe[] = [
{
id: "strict-json",
prompt:
'Return only JSON with keys "city" and "temp_c". No prose.',
expectKey: "temp_c",
},
{
id: "http-method",
prompt:
"Answer with exactly one word: the HTTP method used to update a resource.",
},
];
const endpoint = process.env.MONKEYCODE_API_URL;
const token = process.env.MONKEYCODE_TOKEN;
async function callModel(prompt: string): Promise<string> {
if (!endpoint || !token) {
throw new Error("Set MONKEYCODE_API_URL and MONKEYCODE_TOKEN");
}
const response = await fetch(endpoint, {
method: "POST",
headers: {
"content-type": "application/json",
authorization: `Bearer ${token}`,
},
body: JSON.stringify({
prompt,
max_tokens: 24,
temperature: 0,
}),
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
return (await response.text()).trim();
}
function digest(value: string): string {
return createHash("sha256")
.update(value.toLowerCase())
.digest("hex")
.slice(0, 12);
}
async function main() {
const results: string[] = [];
for (const probe of probes) {
const output = await callModel(probe.prompt);
const shortDigest = digest(output);
const keyStatus = probe.expectKey
? output.includes(probe.expectKey)
? "key-present"
: "key-missing"
: "-";
results.push(`${probe.id}\t${shortDigest}\t${keyStatus}`);
}
console.log(results.join("\n"));
}
main().catch((error) => {
console.error(
`probe failed: ${error instanceof Error ? error.message : error}`,
);
process.exit(1);
});
运行前先设置端点和 Token 为环境变量:
export MONKEYCODE_API_URL="your-monkeycode-endpoint"
export MONKEYCODE_TOKEN="your-token"
npx tsx probe.ts
你应该看到类似这样的两行输出:
strict-json 9f3b2c1a4e6d key-present
http-method 7d1a9e0b3c5f -
这是一个可直接适配的脚手架,而不是对任何在线端点输出特定结果的保证。在信任结果之前,先调整 Prompt 以匹配你自己的账户。
为了证明看门狗能捕获你关心的失败模式,将期望的 Key 改成一个模型不太可能返回的值。例如,将 strict JSON probe 的 expectKey 设为 "humidity_pct":
expectKey: "humidity_pct",
再次运行 probe。如果模型返回的是原始 Key,状态会变成 key-missing,摘要行也会不同,Shell 包装脚本就会标记出漂移。这与你想要的信号是一样的——当模型静默地不再遵守"仅返回 JSON"或重命名了你下游解析的字段时。
部署前记得把 expectKey 改回 "temp_c"。
将项目放在一个能持续在线的小型免费服务器上。每六小时运行一次的 Cron 任务就足以检测变更;你监控的不是可用性,而是行为。
创建 drift-watchdog.sh:
#!/usr/bin/env bash
set -euo pipefail
LOG_FILE="${LOG_FILE:-./probe-results.tsv}"
STATE_FILE="${STATE_FILE:-./probe-state.tsv}"
npx tsx probe.ts > "$LOG_FILE"
if [[ -f "$STATE_FILE" ]]; then
if ! cmp -s "$STATE_FILE" "$LOG_FILE"; then
echo "drift detected" >&2
diff "$STATE_FILE" "$LOG_FILE" || true
if [[ -n "${NTFY_TOPIC:-}" ]]; then
curl -s -d "Model drift detected on $(hostname)" \
"https://ntfy.sh/$NTFY_TOPIC" || true
fi
fi
fi
cp "$LOG_FILE" "$STATE_FILE"
赋予执行权限并添加 Cron 条目:
chmod +x drift-watchdog.sh
crontab -e
0 */6 * * * cd $HOME/drift-watchdog && LOG_FILE=$HOME/watchdog-runs/last.tsv STATE_FILE=$HOME/watchdog-runs/state.tsv ./drift-watchdog.sh >> $HOME/watchdog-runs/watchdog.log 2>&1
先创建日志目录:
mkdir -p $HOME/watchdog-runs
无论你运行多少次,状态文件都只会增长到几百字节。
两个 Prompt 各自上限 24 tokens,每次运行最多消耗 48 个输出 tokens 加上固定的 Prompt tokens。每天六次运行约产生 360 个输出 tokens,30 天约 10,800 个。如果 MonkeyCode 宣传的配额是 3000 万 tokens,这个看门狗每月消耗的试用额度不到 0.04%,剩余的都可以用于实际工作。
在依赖此方案之前,设定两个退出条件:
如果某次 probe 消耗了你月度配额的 5% 以上,停止运行并把频率降低到每天两次。
如果端点连续三次返回非 JSON 错误,暂停看门狗并手动测试端点。看门狗的职责是检测行为变更,而非端点健康状况;一个坏了的端点本应触发你的应用检查。
如果你需要比较模型质量、在负载下测量延迟、或检测内容策略变更,请不要使用这个方法。两个 Prompt 的摘要太单薄,无法回答那些问题。也不要把它当作可用性监控;每六小时一次的 Cron 任务会漏掉你能容忍的小抖动,而捕获的长期行为变更才是真正重要的。
把你个人项目中已经依赖的两个 Prompt 包装进摘要比较,然后运行第一次状态快照。如果下一次定时运行的结果相同,你就拥有了一个可用的基线。如果不同,你就在用户发现之前找到了漂移。
MonkeyCode 提供的免费端点和免费服务器在这里很有用,因为实验消耗的是时间,而不是金钱。用小额 Token 预算运行看门狗,将状态文件纳入版本控制,把每次差异当作端点没有发布的变更日志来对待。