提出用固定测试集验证标签质量和JSON有效性的基准方法,并强调按业务后果分类标签(搜索 facets vs 安全路由),而非依赖单一准确率。
简短回答:选择能在锁定测试集上满足标签级质量和 JSON 有效性底线的 API,再用成本、延迟、欧美处理要求来打破平局。一个精致的 Demo 不能作为分类器已准备好用于应用后端的证据。
我的有用实验从一个故意无聊的问题开始:服务能否以队列期望的精确格式返回正确标签,针对我们数据中那些别扭的记录?我在一个内部 Python 接口背后比较各个候选方案。失败的/简单的方案是 prompt 加二十个手工挑选的示例;选择的方案是冻结一个代表性语料库,验证每个响应,并记录弃权。在复制选择之前,测量每个标签的召回率、无效输出率、尾延迟、token 用量和人工审核量。
这就是整个实验笔记。剩下的部分讲的是当笔记本变成生产代码时,如何保持结果的可信度。
从每个标签的后果开始。搜索切面能容忍的错误配置文件不同于路由安全报告、触发退款或隐藏内容的标签。把那个后果写在分类旁边。否则一个单一的准确率数字可能掩盖恰好在业务最在意的地方失败的某个类别。
从经过脱敏的、真实形态的输入构建一个保留语料库。包括常见示例、稀有类别、歧义措辞、空或截断的文本,以及应用接受的所有语言。保留一个开发分割用于 prompt 和 schema 编辑,再加上一个用于选择的锁定测试分割。如果相同的示例既指导 prompt 变更又为最终运行打分,比较就变成了记忆测试。
我不确定是否存在一个通用的权重方案。你的情况会因类别不平衡和错误路由的成本而不同。我对关键标签召回率和 schema 有效性使用硬底线;只有通过底线的运行才会在延迟和实测用量上进行比较。
笔记本到生产的边界应该很小。每个适配器接收相同的文本和分类,然后返回相同的 Python 类型。提供商特定的请求构建属于适配器内部,而评分、验证和应用逻辑保持独立于响应文本。
我还记录使结果可复制的配置:适配器名称、精确的模型标识符、位置设置、凭证别名、prompt 修订版本、schema 修订版本、数据集提交、timeout 策略、重试次数以及验证器版本。永远不要在常规遥测中记录密钥或原始客户文本。有一次预发布运行花了 47 分钟追踪一个配置不匹配,因为错误看起来像格式错误的输入。prompt 没问题。记录没问题。worker 从一个环境变量加载了欧洲位置,而其授权别名指向美国部署;适配器的诊断记录中缺少一个值使得响应看起来像 schema 失败。我现在在启动时打印一个经编辑的配置指纹,将相同的指纹附加到每个评估行,并在缺少所需位置或 schema 修订版本时让工具在发送请求之前失败。与针对错误的实验编辑 prompt 相比,这种额外的仪式是廉价的。它也给值班工程师一个有用的第一条线索,而不暴露客户内容。
下面是那个工具的核心。它在评分之前验证,将次要标签视为集合,不给格式错误的输出任何意外的部分分数。
from dataclasses import dataclass
from typing import Protocol
ALLOWED = {"billing", "bug_report", "feature_request", "security"}
@dataclass(frozen=True)
class Classification:
primary: str
tags: tuple[str, ...]
class Classifier(Protocol):
def classify(self, text: str) -> Classification:
...
def validate(result: Classification) -> None:
if result.primary not in ALLOWED:
raise ValueError("primary label is outside the taxonomy")
unknown = set(result.tags) - ALLOWED
if unknown:
raise ValueError(f"unknown secondary tags: {sorted(unknown)}")
def score(expected: Classification, actual: Classification) -> dict[str, float]:
validate(actual)
expected_tags = set(expected.tags)
actual_tags = set(actual.tags)
union = expected_tags | actual_tags
return {
"primary_correct": float(expected.primary == actual.primary),
"tag_jaccard": len(expected_tags & actual_tags) / max(1, len(union)),
}
在生成候选方案旁边运行一个确定性基线。规则可以为具有明显语言的狭窄分类获胜。当你有足够的代表性标签并需要在持续高负载下获得可预测延迟时, conventional 训练分类器可以获胜。当你有大型层级结构时,基于 embedding 的候选检索阶段可以提供帮助,但检索召回率随后成为一个独立指标;它不能替代最终标签的评估。
JSON 有效性是必要的,但不是充分的。在边界处,检查解析、必需字段、类型和批准枚举中的成员资格。在业务层,检查单独合法但与策略不兼容的组合,例如同时标记为常规和安全敏感的记录。
提前选择失败行为。未知标签不能成为第一个枚举值,格式错误的输出不能消失在一个宽泛的异常处理器中。低影响工作流可以在有界客户端策略下重试然后弃权。影响重大的工作流应立即将项目路由到审核。将 prompt 和 schema 修订版本与结果一起存储,以便审计可以重建决策上下文。
将置信度视为一个测量的信号,而不是神奇的概率。在选择自动化阈值之前,根据保留数据将其与观察到的正确性进行绘图,并继续对明显高置信度的项目进行采样。系统性盲点通常看起来很确定。
分类增长更安静且代价高昂。将每个定义和示例打包到每个请求中会增加输入用量,并可能模糊相邻类别。从小型发布开始,将定义放在应用 schema 旁边,并要求对添加或合并进行审核。独立版本化标签定义、JSON schema、prompt 和评估集;即使模型和端点保持不变,定义编辑也可能移动准确性。
"在欧洲可用"不是一个充分的架构要求。识别请求内容在哪里处理、哪些请求或响应数据可能被保留、运营日志落在哪里、谁可以检查它们,以及哪个账户或部署设置强制执行这些选择。在选择期间检查当前官方服务文档和协议,因为位置和保留细节可能因服务和账户而异。
将位置和模型选择保持在部署配置中。缺少必需值时启动失败。生产遥测可以记录经过时间、结果类别、schema 修订版本、验证结果、在提供时的 token 计数以及在可用时的请求标识符。原始客户文本属于由源系统保留和访问策略管理的受控评估存储。
问题是,当策略要求处理在其部署控制无法满足的基础设施内时,外部 API 不合适。自托管模型可能适合那个边界,但你的团队随后要负责服务容量、更新、监控和安全边界。当分类固定且明显关键词已满足质量目标时,坚持使用确定性规则。
我信任的生产形态是:一个内部分类接口、一个活动适配器、严格验证、一个弃权路径,以及一个不能改变用户可见标签的影子评估路径。模型或服务变更首先在锁定工具中,在策略允许时移动到经脱敏的影子流量,只有在质量、区域适配、延迟和用量一起审查后才能到达实时路由。
成本属于负载测试,而不是标题。记录每个已接受分类的用量,包括重试和审核工作。一个更长的 prompt 挽救了一个稀有类别可能是值得的;复制到简单记录上的相同 prompt 可能不值得。根据锁定语料库测试 prompt 缩减,因为在失去重要案例的同时节省 token 是虚假的节约。
在发布后观察验证失败、弃权和审核率、标签分布变化、延迟尾部和用量增长。采样频繁和稀有标签,然后将裁决后的错误添加到未来评估集中,而不重写锁定的历史结果。
有限制。小评估集产生嘈杂的少数类估计,人工标签可能不同意,脱敏样本可能错过生产语言。当错误带有严重的法律、安全或财务后果时,在决策路径中保持合格的人工审核。当没有候选方案清除接受底线时,发布更简单的基线或暂停;一个干净的 JSON 对象不是自动执行坏决定的许可。