基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
  • 知识卡片碎片时间过考点
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
    • AI 热点每日 AI 资讯与动向
AI 工作台
简历
旧版
AIHT
内容
精选全部 AI 动态热点榜AI 日报收藏
分类
模型行业编程产品技术观点开源
更多
Agent 接入
返回首页开发者导航
AIHT
精选 / 资讯详情
8.0
热点
AI SCORE
技术实践2026-11-08 16:28

用候选集和解析校验约束模型输出

dev.to · AI#结构化输出#校验#大模型
Editor brief · 编辑速览

发音练习应用先用代码确定训练音素、查询合法单词候选,再让模型补齐空位,并校验结果的候选归属、唯一性与数量。文章还展示去重、低分录音过滤和排序规则,无需训练时直接跳过模型调用。

文章思维导图
Knowledge map
拖拽缩放
AI deep read

AI 深度解读

让模型推荐三个发音练习词,看起来只是一个简单提示词任务。Vocalace 的做法却把大部分决定交给代码:先选薄弱音,再查词典,最后只让模型补齐缺少的位置。模型返回的内容必须通过校验,才能存入系统。

这篇文章值得读的地方,是它把「模型可以决定什么」划得很具体。对需要把 AI 输出写入数据库、接入后续流程的程序员,这种边界设计比一句「请严格遵守格式」更有参考价值。

最差的单次得分,为什么不一定优先练

作者先用确定性规则选出需要练习的音素(phoneme),模型不参与排名。

每个单词只贡献一票。同一个词录了多次,也只保留一个薄弱音焦点,取表现更差的那次。低于 40 分的录音不会进入排名;过滤后如果所有焦点都是绿色,就没有需要练的音,也不会调用模型。

这套规则优先处理多个词共同暴露的问题。原文中,s 的分数更差,但 th 出现在两个词的薄弱音焦点里,所以最终选中 th。重复录制 sorry 不会增加票数。

排序代码直接规定了各项指标的优先级:

return b.count - a.count
  || b.redCount - a.redCount
  || a.minScore - b.minScore
  || left[0].localeCompare(right[0])

要看第一行:先比较涉及的单词数量。只有数量相同,才依次比较红色焦点数量、最低分,最后按音素 ID 排序。红色与黄色如何划分,原文没有给出阈值。

已有的 think 和 thing 都暴露了 th,因此先占两个练习位置,分数更低的 think 在前。目标是三个词,此时只差一个,模型也只负责这一个位置。

模型的任务规模,是前面的业务代码算出来的。

候选词表和解析器,怎样堵住自由发挥

缺少的词来自词典查询。查询要求 SAPI 发音标记完整匹配 (^| )th( |$),单词具有常见词性,排除当天已经见过的词,最多返回 20 行。

这份数组就是合法答案的全集。模型收到音素、缺少的数量和候选词,只能从中选择。提示词还要求目标音容易单独听清,并且不要解释。

但「音够不够清楚」没有进入程序校验。候选表里的词即使不够适合练习,只要通过检查,仍然会被保存。解析器真正保证的只有三件事:属于候选集合、不重复、数量准确。

下面的解析器负责决定回复能否进入存储:

export function parseWordsFromAskPick({ raw, allowed, need }: {
  raw: string
  allowed: string[]
  need: number
}): string[] | null {
  const byWord = new Map(allowed.map(word => [word.toLowerCase(), word]))
  const picked: string[] = []
  for (const item of raw.trim().split(/[||]/)) {
    const word = byWord.get(item.trim().toLowerCase())
    if (!word || picked.includes(word)) {
      return null
    }
    picked.push(word)
  }
  return picked.length === need ? picked : null
}

重点是遇到非法词或重复词时,直接 return null。程序不会从错误回复里捞出几个合法词,拼成一个看似成功的结果。

测试使用 allowed = cat, hat, map:返回 dog 会因不在集合内被拒绝;需要两个词却只返回 cat,会因数量不足被拒绝;cat|cat 会因重复被拒绝。末尾多一个分隔符也不行,因为拆分后会出现空项。

真实例子中,need 是 1,合法集合来自最多 20 行的查询结果。Month 只有在候选表包含 month 时才有效,thick 同理。若模型返回 month because the th is clear,整段会被当成一个词项查找,结果仍是 null。

返回 null 后最多重试四次,之后任务失败。错误文本不会被裁剪成部分成功的答案。

我的判断

我赞同把排名、候选范围和存储条件交给代码。这些规则可以直接验证,也能写出明确的失败用例。只靠提示词约束输出,很难给下游程序同样清楚的保证。

不过,标题里的「不能编造」有一个边界:模型仍然可能生成词典外的词,只是系统不会接受。可靠的是接收流程。

模型是否值得保留,则还需要证据。作者让它挑选「目标音容易听清」的词,却没有给出与随机选词、词频排序或人工规则的对照数据,也没有报告无效回复率、重试成本和练习效果。这部分属于设计经验,不能据此认定模型选得更好。

按单词覆盖数量优先排名,也是一种教学取舍。它偏向多个词共有的薄弱音,未必适用于所有练习目标。原文用测试固定了行为,但没有证明这套顺序在教学效果上最优。

能拿来做什么

  • 在 Node 服务中实现有限候选的 AI 选择任务时,可以先查询合法集合,再让模型选择,并在写入数据库前检查集合归属、重复项和准确数量。
  • 在日常 AI 编程中,可以把「选已有标识符」与「生成新内容」分开处理。需要模型选择已有项时,让程序传入完整候选,并拒绝集合之外的结果。
  • 给类似流程补测试时,优先覆盖非法项、重复项、数量不足、尾部分隔符和夹带解释,同时明确重试上限与最终失败行为。
  • 如果引入模型只是为了改善选择质量,先与简单排序规则做对照,确认它确实改善业务结果,再承担调用和重试成本。
Original source

本文由 AI 通读原文后重新编写,观点部分为站内判断,细节以原文为准,来源 dev.to · AI,原文版权归原作者所有。

阅读原文
上一篇
从失败中搭建编程 Agent 运行框架
下一篇
用 Canvas 合成引导 AI 实现手电筒光效

资讯速览

dev.to · AI · 2026-11-08 16:28

AI 评分 8.0 / 10

相关标签

#结构化输出#校验#大模型

继续阅读

  • Agent 测试日志不能只看退出码
  • 从失败中搭建编程 Agent 运行框架
  • 用 Canvas 合成引导 AI 实现手电筒光效
  • AI 开发真实产品,先审影响再改代码
  • 模型输出通过校验,为何仍弄坏看板