为 AI 输出设计解析器协议 (不仅仅是提示词)
- 作者

- 姓名
- Nino
- 职业
- Senior Tech Editor
大多数开发者在开始使用大语言模型 (LLM) 时,都会遵循一条可预见的路径:编写提示词,要求输出 JSON,或许再提供一个 Schema,然后就大功告成了。虽然这涵盖了“理想路径”,但它未能解决非确定性 AI 的根本不稳定性。真正的挑战不在于提示词本身,而在于必须消费、信任并根据模型输出执行操作的代码。
在为 CRM 系统(如 Anguardia)构建导入管道时,我们需要处理 AI 生成的潜在客户研究报告。我发现提示词仅占解决方案的 20%,剩下的 80% 全在于 解析器协议 (Parser Contract)。解析器协议是一组确定性规则,它不将 LLM 输出视为可靠的数据源,而是将其视为需要严格验证、版本控制和优雅降级的杂乱流。
为什么选择 Markdown 格式的 Dossier?
虽然 JSON 是行业标准,但许多企业工作流受益于像 Markdown 这样的混合格式。它对人类友好,允许 LLM 以结构化的方式“思考”,并且出奇地容易使用正则表达式或专门的库进行解析。在我们的 CRM 案例中,我们定义了一个“Dossier”格式:
<!-- anguardia-dossier v1 -->
# Dossier: <公司名称>
## 公司信息
- 行业: <行业>
- 网站: <URL>
- 所在地: <城市或地区>
- 来源: <冷启动 | 推荐 | 入站 | 研究>
## 人员列表
| 姓名 | 职位 | 邮箱 | 电话 | LinkedIn |
| ---- | ---- | ---- | ---- | -------- |
## 建议任务
- [ ] <任务标题> | 截止日期: <YYYY-MM-DD, 可选>
## 建议沟通内容
<第一条消息,不超过 150 字>
为了确保在 DeepSeek-V3 或 Claude 3.5 Sonnet 等不同模型之间实现高速处理和可靠性,我们使用 n1n.ai 作为我们的 API 聚合器。只要协议保持不变,这允许我们在不破坏解析器的情况下切换模型。
原则 1:永远不要在输入错误时抛出异常
传统软件工程教导我们,当违反协议时要抛出错误。但在 LLM 的世界里,这是导致用户体验崩溃的捷径。如果模型漏掉了一个括号或跳过了一个标题,抛出异常会迫使用户“重试”,从而浪费 Token 和时间。
相反,parseDossier 函数应始终返回一个结果对象,并附带一个 warnings(警告)数组。
/** 确定性的 Dossier v1 解析。始终返回 dossier 对象 + 警告。 */
export function parseDossier(text: string): ParseResult {
const warnings: string[] = []
const hasMarker = textContainsDossierMarker(text)
if (!hasMarker) {
warnings.push('未检测到 Dossier 标记。将尝试尽力解析。')
}
// 解析逻辑继续,提取它能找到的所有内容...
return { data: dossier, warnings }
}
通过使用 n1n.ai,您可以测试不同模型如何处理这些局部故障,并相应地优化您的解析器。
原则 2:拒绝并报告,而非强制转换
解析器能做的最危险的事情之一就是“猜测”模型的意图。如果 LLM 在 Schema 仅期望“网站”的情况下添加了“Twitter: @handle”字段,一个幼稚的解析器可能会尝试将 Twitter 句柄塞进网站字段。这会导致数据污染。
if (!KNOWN_COMPANY_KEYS.has(key)) {
warnings.push(`忽略未知的公司字段: ${bullet[1].trim()}`)
continue
}
如果数据格式错误(例如日期不是 YYYY-MM-DD 格式),请丢弃该数据并记录警告。缺失日期只是小麻烦,而错误的日期则是业务失败。在使用通过 n1n.ai 提供的各种高性能 API 时,这一点尤为关键,因为此时吞吐量高且人工监督较少。
原则 3:双层诚实约束
我们经常在提示词中加入“严禁编造联系方式”等指令。然而,模型仍会产生幻觉。解析器必须充当这种诚实协议的第二层。如果提示词要求在数据缺失时留空,解析器必须严格执行这种空值。
如果模型在电话号码字段中返回“未知”或“N/A”,解析器应将这些识别为空值,而不是有效的字符串。两层独立的防御机制(提示词 + 解析器)共同达成“留空优于编造”的共识,是保持数据库清洁的唯一方法。
原则 4:边界处的版本化
产品在进化,数据结构也会随之改变。不要在更新提示词时尝试迁移数据库中的每条记录,而应使用版本标记。在输出顶部放置一个 HTML 注释是一种廉价且持久的版本化方案。
export const DOSSIER_MARKER_LEGACY = '<!-- founder-os-dossier v1 -->'
export const DOSSIER_MARKER = '<!-- anguardia-dossier v1 -->'
const version = detectVersion(text) // 处理 v1, v2 等不同版本
实施指南:构建稳健的管道
要有效实施此方案,请遵循以下步骤:
- 定义形状:选择 Markdown 以提高可读性,或选择 JSON 以实现严格性。
- 选择多模型网关:使用 n1n.ai 确保您的解析器可以在 OpenAI、Anthropic 和 DeepSeek 模型上运行。
- 编写解析逻辑:构建一个基于状态机或正则表达式的提取器,用于填充部分对象。
- 诊断 UI:向最终用户显示
warnings数组,让他们知道 AI 是否遗漏了某些内容。
通过将重心从“更好的提示词”转移到“更好的解析器”,您可以构建出对人工智能固有特性具有韧性的系统。提示词让输出大致正确,而解析器则让自动化变得安全。
在 n1n.ai 获取免费 API 密钥。