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

让 LLM 写入 CRM 前先过结构与业务校验

dev.to · AI#Node.js#结构化输出#LLM
Editor brief · 编辑速览

文章建议将通话记录处理拆为结构化动作生成与写入前校验,明确负责人、截止日期、证据及信息缺失状态。保留原始转录、提示词版本、校验结果和拒绝原因,避免把模糊讨论自动转成业务承诺。

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

AI 深度解读

把销售通话交给 LLM,生成摘要并不难,难的是判断哪些内容可以真的写进 CRM。作者的结论是:模型只负责提出结构化动作,代码负责验收,业务规则决定能否执行。聊到「下个月再看看」,不能自动变成下月一号到期的任务。

这套思路值得做 Node.js 和 AI 应用的程序员参考:它把模型输出、业务判断和外部写入拆开,让错误有机会被拦住。不过,文章提供的是设计经验和 Python 示例,没有 Node.js 实现,也没有量化实验来证明收益。

摘要写得通顺,为什么还不能直接创建任务

作者面对的是 B2B SaaS 销售场景。团队需要的输出其实很少:下一步做什么、谁负责、确实提及时才填写的截止日期,以及通话中的依据。

困难在于,通话经常只有意向,没有承诺。客户说「我们应该下个月重新讨论安全问题」,并没有确认会议时间、负责人或具体任务。模型若主动补齐这些内容,摘要可能更完整,CRM 数据却已经失真。

摘要可以概括意思,业务动作必须有足够依据。

作者因此设置三道关卡:先确认返回值是合法 JSON,再检查字段和取值是否符合契约,最后由确定性规则决定是否允许自动写入。所谓确定性规则,就是相同输入按明确条件得出相同处理结果,不再让模型临场判断。

动作类型只有四种:create_task、update_opportunity、send_follow_up 和 no_action。其中 no_action 很关键,它让「没有足够信息采取行动」成为正常结果,而不是迫使模型每次交出一个任务。

下面的校验器解决的是第二道关卡:检查候选对象是否符合约定。

from typing import Any

ACTION_TYPES = {
    "create_task",
    "update_opportunity",
    "send_follow_up",
    "no_action",
}

REQUIRED_KEYS = {"action_type", "confidence", "evidence", "reason"}

def validate_action(candidate: Any) -> tuple[bool, str]:
    if not isinstance(candidate, dict):
        return False, "result is not an object"
    if set(candidate) != REQUIRED_KEYS:
        return False, "unexpected or missing fields"
    if candidate["action_type"] not in ACTION_TYPES:
        return False, "unsupported action type"
    if not isinstance(candidate["confidence"], (int, float)):
        return False, "confidence must be numeric"
    if not 0 <= candidate["confidence"] <= 1:
        return False, "confidence must be between 0 and 1"
    if not isinstance(candidate["evidence"], list) or not candidate["evidence"]:
        return False, "at least one evidence item is required"
    if not all(isinstance(item, str) and item.strip() for item in candidate["evidence"]):
        return False, "evidence items must be non-empty strings"
    if not isinstance(candidate["reason"], str) or not candidate["reason"].strip():
        return False, "reason is required"
    return True, "ok"

要看清 set(candidate) != REQUIRED_KEYS:它同时拒绝缺字段和多字段;也要看清 evidence 的检查,它只保证存在非空字符串,没有核对引用是否真的出现在转录中。

契约可以用 JSON Schema 表达,也可以交给服务已有的校验库。关键边界是:模型返回的内容,在代码验收之前始终只是数据。

0.80 是自动处理门槛,不是正确率证明

原文的另一段示例通过 TextModel 协议隔离模型调用,只暴露 complete 操作。extract_action 发出窄指令,要求只返回 action_type、confidence、evidence、reason,禁止推断日期和负责人;随后用 json.loads 解析,再调用 validate_action。

通过结构检查后,还有一条规则:confidence < 0.80 就拒绝自动处理,返回的 Decision 用 accepted、payload、reason 记录结果。

这里的 0.80 不能理解为动作有 80% 的概率正确,更不能理解为客户有 80% 的概率购买。它只是应用选择的一条处理边界,需要拿人工标注的通话验证。

动作类型也应该影响审批策略。作者举例,某些团队可以自动创建任务,但即使置信分数够高,send_follow_up 仍然需要人工批准。示例代码没有实现这层区别。

作者还报告了一项经验:起初以为加长提示词能解决多数抽取错误,实际帮助小于预期;把 no_action 设为正式结果、拒绝没有支持摘录的输出,改善更明显。但原文没有给出样本量、错误率或对照数据,这只能作为经验判断。

证据摘录也有边界。客户说「如果预算批准,我们就安排演示」,其中确实出现了安排演示,但承诺带有条件。审核者仍需查看上下文,尤其是多人插话、条件句和转录缺失的情况。

真正要管住的是从模型返回到 CRM 写入的整条路径

作者建议的运行流程是:获取转录,移除 CRM 不需要的秘密信息,调用模型适配器,解析一次,校验,再保存不可变的处理记录。通过业务策略后,才让 worker 调用 CRM。

原始转录、模型响应、规范化动作、提示词版本和拒绝原因都应保留。它们回答的是不同问题:模型说了什么、程序接受了什么、最终为什么执行或拒绝。原始数据的保存与日志脱敏也要遵守访问规则。

重试同样需要分类。网络传输失败可以重试;已经成功返回、却不满足业务条件的结果,应该进入审核流程,不能靠反复调用赌一次通过。无法解析的条目要有死信去向,不能无限循环。

写入还必须具备幂等性,也就是同一次处理被重复执行时,不会反复创建任务。作者建议用通话标识、流水线版本和动作类型组成稳定键,让重试找到已有尝试。

批处理可以通过有界分组降低运行压力,但会改变销售看到结果的速度,以及失败条目的重放方式。原文提到 OpenAI Batch API 作为异步模式的例子,没有给出具体调用代码。校验、重放和 CRM 幂等仍由应用负责。

选择托管 API 还是自托管模型,也应放回这条路径里比较:前者涉及网络和数据治理约束,后者需要容量规划及模型运维。两者都无法修复含糊的动作契约。

评估时,作者建议从 100 条经过人工审核的样例起步,覆盖明确动作、明确无需动作、模糊承诺、多人对话、不同日期格式和缺失片段。这是起步建议,不是通用基准。

除了动作是否正确,还要分别看证据质量、弃权精确率、重复写入率、非法 JSON 比例和人工审核量。每次换提示词或模型,都跑同一份冻结样例,并重放历史转录,对比规范化动作,逐条检查发生变化的决策。

我的判断

我赞同把执行权留在应用代码里。相较于不断加长提示词,显式契约、拒绝路径和重放机制更容易检查,也更容易解释错误从哪里进入系统。结构化输出能力可以帮助约束格式,但业务授权仍需要单独判断。

不过,这份示例距离可用的 CRM 动作契约还有一段距离。作者强调负责人和截止日期,实际对象却没有对应字段,也没有任务内容、商机标识或动作专属参数。按当前结构,它更像动作分类结果,不能直接作为完整写入请求。

证据校验也只是起点。非空字符串既不能证明引用来自原文,也不能证明客户已经同意;模型自己填写的置信分数是否有效,文章同样没有验证。

幂等键则依赖业务前提。如果一通电话允许产生多个同类型动作,仅靠通话标识、流水线版本和动作类型,可能无法区分它们。原文没有说明这种情况如何处理。

因此,可以拿走它的边界设计,但不能据此认定 0.80 或这份 schema 已适合自己的团队。

能拿来做什么

  • 在 Node.js 服务中,把模型适配器、动作校验和 CRM worker 分开实现;先补全各类动作必需的业务字段,再开放自动写入。
  • 给审核界面同时展示拟执行动作、证据摘录和相关转录上下文,并把人工修正保存为后续评估样例。
  • 从作者建议的 100 条样例起步,固定测试集;更换模型或提示词时,对比动作和拒绝结果,再检查审核量、延迟及 token 消耗。
  • 为生成任务附上来源通话 ID 和处理版本,提供修改、取消入口,并保留关闭自动写入、继续只读抽取的开关。
Original source

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

阅读原文
上一篇
Node.js 图片放大任务的可靠交付设计
下一篇
用CDK解决推理端点扩缩容部署冲突

资讯速览

dev.to · AI · 2026-10-24 00:43

AI 评分 8.0 / 10

相关标签

#Node.js#结构化输出#LLM

继续阅读

  • 谷歌用微虚拟机暂停 Agent,降低空闲开销
  • Node.js 图片放大任务的可靠交付设计
  • 用CDK解决推理端点扩缩容部署冲突
  • 评测代码测通了,模型质量仍未必可信
  • Agent监控盲区藏在压缩与触发时机里