把 AI 输出交给后续流程之前,先明确接收端允许什么格式、什么字段和什么来源。本文用一个内容卡示例,搭建只读文件、检查结构、输出规范 JSON 的本地校验环节。
实测范围先说明
本次实测对象是本地 JSON 接收端脚本:v24.19.0、16 个人工构造样例。没有调用 AI 模型,没有测模型成功率,也没有把内容自动发布到网站。读者可使用自己的公开资料和模型输出复现接收端检查。
第一步:写出输出契约
本例只接收 title、summary、source_urls 三个字段。标题最多 80 个 Unicode 码点,摘要最多 240 个;来源为 1 至 5 个不重复的 HTTPS URL,域名限定为示例里使用的三个文档站。URL 无账号密码或自定义端口。
{
"title": "JSON 解析与接收端检查",
"summary": "先确认 JSON 语法,再检查字段和来源,最后由人核对结论。",
"source_urls": [
"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse"
]
}
第二步:让模型依据给定资料输出
下面是可调整的任务说明。只填入可公开的资料,来源链接由你预先选定;资料不足时应保留缺口。
请仅依据我提供的资料整理一张内容卡。
只输出一个 JSON 对象,不加 Markdown 代码围栏。
字段只能是 title、summary、source_urls。
title 和 summary 使用单行文字,分别不超过 80、240 个字符。
source_urls 只允许引用我给出的链接,不要补造链接。
如果资料不足,请在 summary 中明确说明资料不足。
资料与允许引用的链接:
[在这里粘贴公开资料和已核对的链接]
第三步:先用本站工具箱检查语法
将输出作为纯文本保存为 result.json。也可以先打开本站 JSON 工具检查和格式化。JSON 能成功解析,只说明语法层面可处理;缺字段、错误类型或不合适的来源仍需要独立检查。
第四步:运行本地字段与来源检查
保存下面的代码为 validate-ai-json.cjs,使用 Node.js 运行。脚本不联网、不执行文本中的指令,只读取指定文件并校验;允许域名是本示例的编辑策略,应按实际资料来源调整。
'use strict';
const fs = require('node:fs');
const allowedHosts = new Set(['developer.mozilla.org', 'docs.docker.com', 'json-schema.org']);
function checkCard(value) {
if (!value || typeof value !== 'object' || Array.isArray(value)) throw new Error('顶层必须是对象');
const expected = ['source_urls', 'summary', 'title'];
const keys = Object.keys(value).sort();
if (JSON.stringify(keys) !== JSON.stringify(expected)) throw new Error('字段必须恰好是 title、summary、source_urls');
for (const [key, max] of [['title', 80], ['summary', 240]]) {
const text = value[key];
if (typeof text !== 'string' || !text.trim() || [...text].length > max || /[\u0000-\u001f]/u.test(text)) {
throw new Error(key + ' 必须是非空单行文字,长度上限为 ' + max);
}
}
if (!Array.isArray(value.source_urls) || value.source_urls.length < 1 || value.source_urls.length > 5) {
throw new Error('source_urls 必须包含 1 到 5 个来源');
}
const urls = value.source_urls.map(text => {
if (typeof text !== 'string' || text !== text.trim()) throw new Error('来源必须是 URL 字符串');
const url = new URL(text);
if (url.protocol !== 'https:' || url.username || url.password || url.port || !allowedHosts.has(url.hostname)) {
throw new Error('来源必须使用允许域名的 HTTPS URL,且无账号、密码或自定义端口');
}
return url.href;
});
if (new Set(urls).size !== urls.length) throw new Error('来源不能重复');
return {title: value.title.trim(), summary: value.summary.trim(), source_urls: urls};
}
if (require.main === module) {
try {
const file = process.argv[2];
if (!file) throw new Error('用法:node validate-ai-json.cjs result.json');
if (fs.statSync(file).size > 65536) throw new Error('文件超过 64 KiB');
const text = fs.readFileSync(file, 'utf8');
if (Buffer.byteLength(text, 'utf8') > 65536) throw new Error('文件超过 64 KiB');
process.stdout.write(JSON.stringify(checkCard(JSON.parse(text)), null, 2) + '\n');
} catch (error) {
process.stderr.write('校验失败:' + error.message + '\n');
process.exitCode = 1;
}
}
module.exports = {checkCard};
node validate-ai-json.cjs result.json
通过时,标准输出是整理后的 JSON,退出码为 0;不通过时,错误写到标准错误,退出码为 1。接入流程时只有退出码为 0 的结果进入下一步;失败项保留原输入和错误记录,修正后重新检查。不要用执行脚本的方式解释模型输出。
16 个样例的预期与实测结果
| 项目 | 应确认的内容 |
|---|---|
| valid | 接受;实测与预期一致 |
| malformed | 拒绝;实测与预期一致 |
| markdown | 拒绝;实测与预期一致 |
| top_array | 拒绝;实测与预期一致 |
| missing | 拒绝;实测与预期一致 |
| extra | 拒绝;实测与预期一致 |
| wrong_type | 拒绝;实测与预期一致 |
| blank | 拒绝;实测与预期一致 |
| too_long | 拒绝;实测与预期一致 |
| empty_sources | 拒绝;实测与预期一致 |
| http | 拒绝;实测与预期一致 |
| unknown_host | 拒绝;实测与预期一致 |
| credentials | 拒绝;实测与预期一致 |
| duplicate | 拒绝;实测与预期一致 |
| control_char | 拒绝;实测与预期一致 |
| oversize | 拒绝;实测与预期一致 |
通过校验后还需要人工检查什么
- 逐个打开来源,确认页面存在且内容支持摘要;域名白名单不能证明具体页面和结论正确。
- 核对引用的版本、时间、使用前提,以及是否遗漏限制。
- 把文本作为数据处理;进入网页时按输出位置做转义,不能直接拼成 HTML 或可执行脚本。
- 这个示例没有检测 JSON 重复键,也没有评估事实准确率;复杂契约可以在此基础上使用 JSON Schema 等工具进一步约束。
接收端检查通过后,先生成待人工审核的草稿。把“输入契约 → 语法检查 → 字段检查 → 来源核对 → 人工确认”保存成自己的验收记录,再逐步连接更大的工作流。