基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
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-22 04:26

用类型化记录搭建 Python 通话质检

dev.to · AI#Python#结构化输出#数据校验
Editor brief · 编辑速览

教程先用 JSON Schema 定义情绪、合规和升级原因等字段,再将版本化模板绑定到 AI 助手。通话分析结果经过验证后进入质检评分卡,完整示例收录于 Telnyx 代码仓库。

文章思维导图
Knowledge map
拖拽缩放
Full translation

完整中文译文

自由文本通话摘要适合人读,却很难直接拿来统计:客户情绪如何、哪些披露缺失、为什么要求升级处理,每次都要再解析一遍。作者用 Python 和 Telnyx 搭了一条质检流水线,先定义数据结构,再让 AI 分析通话,最后只汇总通过校验的结果。

这篇值得看的不是摘要提示词,而是如何把 AI 输出接进业务系统。它把配置核验、异步结果获取和无效数据隔离串了起来。不过,结构符合约定,并不代表判断符合事实。

先规定字段,才能稳定地做统计

同样是客户要求找主管,模型可能写成「要求经理介入」「请求升级」「想找负责人」。人能看懂,看板却无法直接按同一个值分组。

作者先定义 JSON Schema,也就是字段、类型和取值范围的约定,再创建三个带版本的分析模板:

  • sentiment-v1 返回积极程度、挫败感、整体情绪和关键情感。
  • compliance-v1 返回身份核验结果,以及限定范围内的合规标记。
  • escalation-v1 返回受控的升级原因,以及客服是否处理得当。

下面的 Schema 解决升级原因无法统一归类的问题:

ESCALATION_SCHEMA = {
    "type": "object",
    "properties": {
        "escalation_reason": {
            "type": "string",
            "enum": [
                "caller_request",
                "compliance_violation",
                "poor_call_quality",
                "system_error",
                "other",
            ],
        },
        "agent_performed_well": {"type": "boolean"},
    },
    "required": ["escalation_reason", "agent_performed_well"],
    "additionalProperties": False,
}

要看最后两行:两个字段都必须存在,也不允许额外字段。enum 则让升级原因只能从五个值中选择。

这里也暴露了一个缺口。模板指令要求判断是否发生升级,但 Schema 没有单独的「是否升级」字段,枚举也没有明确的「未升级」。没有发生升级的通话该怎么表示,原文没说清。直接把它归进 other,可能混淆「未升级」和「原因未知」。

创建模板时,create_templates.py 向 POST /ai/conversations/insights 发送请求,样例通过 json.dumps(ESCALATION_SCHEMA) 把 json_schema 转为 JSON 字符串,使用 timeout=30。API 也接受 Schema 对象,这是请求表示方式的差异。

请求成功以后,还要确认配置真的生效

三个模板被放进 qa-scorecard-v1 分析组,再通过 Assistant 的 insight_settings.insight_group_id 绑定。后续通话便可以统一使用这组分析约定,避免逐个维护模板绑定。

作者没有停在「接口返回成功」。

create_group.py 查找或创建分组、分配模板,然后重新读取成员列表。只要缺少任何预期模板,脚本就退出。wire_assistant.py 通过 POST /ai/assistants/{assistant_id} 更新配置,同样使用 timeout=30,随后发起 GET,核对返回的 insight_group_id。

这类写后读取检查,验证的是实际保存的配置。对依赖远端状态的自动化脚本,它比只检查请求状态更有用。

运行前需要克隆 team-telnyx/telnyx-code-examples 仓库,进入 telnyx-code-examples/insights-pipeline,用 python -m venv .venv 创建环境,执行 source .venv/bin/activate、pip install -r requirements.txt 和 cp .env.example .env。

环境配置包含 TELNYX_API_KEY、使用 E.164 格式的 ASSISTANT_PHONE_NUMBER 与 DESTINATION_NUMBER,以及可选的 ASSISTANT_ID、PUBLIC_WEBHOOK_BASE_URL。未设置 ASSISTANT_ID 时,脚本会用平台默认的模型和语音创建 Assistant;原文没有指定具体型号。

下面这组命令完成模板配置、Assistant 绑定、测试呼叫和按日期统计:

python create_templates.py
python create_group.py
python wire_assistant.py
python place_call.py
python scorecard.py --date YYYY-MM-DD

需要特别检查 place_call.py 执行前的 DEMO_MODE:默认 true 只打印计划事件载荷,不拨打真实号码,也不写入虚假的 conversation ID。准备真实测试时才设为 false。API 密钥应保存在环境变量或密钥管理器中。

分析没完成,和分析结果不合法,是两回事

通话结束后,分析结果未必立即可用。样例提供两条发现完成结果的路径:call.conversation.insights_generated webhook 用作实时完成信号,GET /ai/conversations/{conversation_id}/conversations-insights 用作轮询查询的事实来源。即使 webhook 接收器没启动,轮询也能完成流程。

可选接收器通过 python webhook_receiver.py 启动。它要求提供 TELNYX_PUBLIC_KEY,使用 Ed25519 验证签名;签名数据缺失或无效时返回 400,没有跳过验证的降级路径。

拿到结果以后,scorecard.py 先把模板 ID 映射回名称,再解析并校验必填字段和枚举值。只有已经完成、且校验通过的记录才参与统计。完成但不合法的结果会连同 conversation ID 打印出来,并被排除。

尚未就绪是流程状态,结构无效才是数据问题。

可以执行 python scorecard.py --strict,注入一条缺少 positivity_score 的模拟情绪记录,检查无效数据是否被挡住。也可以用 python scorecard.py --conversation-id <CONVERSATION_ID> 绕过本地通话记录,单独查询一段通话。

原文明示的汇总包括情绪分布和合规标记数量,但汇总列表并不完整,也没有给出完整的轮询状态规则,不能据此补出更多实现细节。

我的判断

我赞同把数据约定放在分析之前。相比「先生成摘要,再用另一个步骤抽字段」,这种方式让下游看板获得更明确的输入边界,也减少了自由措辞带来的归类麻烦。

但它解决的是输出结构的可用性。模型可能选择了合法的合规标记,却误判了通话;也可能正确输出布尔值,却没有可靠依据。原文没有提供人工标注对照、准确率、成本或耗时数据,因此不能把这个教程当成质检效果已经验证的方案。

分组回读和无效记录隔离都值得借鉴,但生产环境还需要保存原始结果、模板版本与处理状态。作者也明确建议用持久化存储替换本地 conversations.json,把无效记录送入运营复核队列。

版本名称同样只是起点。v1 能标识约定,却不会自动解决新旧字段如何兼容、历史统计能否比较的问题。尤其是升级与合规判断,应该先检查业务分类是否完整,再要求模型严格遵守。

能拿来做什么

  • 给通话质检看板定义输入结构时,先列出需要统计和筛选的字段,再设计枚举;同时明确「未发生」「未知」和「其他」分别怎么表达。
  • 用 Node 接收分析 webhook 时,可以沿用签名验证、轮询补查、结果校验的流程,并把「等待分析」和「结果无效」显示为不同状态。
  • 把 python scorecard.py --strict 纳入样例验收,确认缺字段的记录不会进入总数;再用人工核对的通话检查分类是否正确。
  • 上线前替换 conversations.json,把模板版本与结果一起保存,并为被排除的数据安排复核入口,避免看板只剩下一个无法解释的数字。
Original source

本文由 AI 翻译整理自 dev.to · AI,原文版权归原作者所有。

阅读英文原文
上一篇
Recursive 推出可在笔记本运行的编程模型
下一篇
零运行依赖的自修改编程运行时

资讯速览

dev.to · AI · 2026-10-22 04:26

AI 评分 8.0 / 10

相关标签

#Python#结构化输出#数据校验

继续阅读

  • Claude Code 与 Codex 同仓协作的常见坑
  • Recursive 推出可在笔记本运行的编程模型
  • 零运行依赖的自修改编程运行时
  • 结构化输出还需过事实校验这一关
  • 可回放的告警归因引擎如何约束大模型