
我们团队半年前接了一个挺头疼的需求销售每天在企业微信、电话、面谈里产生大量沟通记录但 CRM 里的跟进记录永远是滞后的甚至很多高价值客户信息就烂在聊天记录里没人理。老板说“你们能不能把聊天记录自动变成 CRM 的客户档案”当时市面上有各种号称 AI 能提取信息的工具真正落到自研 CRM 里批量写入的却很少。于是我们做了个小工程核心思路一句话用 LLM 把非结构化沟通记录转成 JSON再通过一致性校验和幂等设计批量写进 CRM。整个过程踩了不少坑今天把这个项目的完整实践过程梳理出来希望能给正在做类似“AI 数据管道”的同学一点参考。这个方案适合谁如果你所在公司有自研或可 API 对接的 CRM手头有大量微信/企微对话、通话转写文本、邮件等非结构化沟通数据并且希望把这些数据变成可作为销售跟进依据的结构化字段——本文的完整链路、提示词设计、批处理容错和成本优化方案都可以直接抄作业。1. 项目背景与整体方案设计1.1 业务痛点一切从“会话存档没人看”开始我们公司接了企微的会话存档接口每天大概产生 3 万条左右聊天消息来自销售和客户的日常沟通。但有一个尴尬的事实数据存了没人看。企微自带的会话存档界面又难用销售和销售主管根本不可能一条一条去翻聊天记录。结果就是客户在对话里已经明确说了“下个月有点预算你出个方案吧”这种高意向信号没人捕捉甚至客户流失了都没人知道。传统的做法是让销售手动填 CRM在跟进记录里写“电话沟通了客户有意向”稍微好一点的团队会要求销售在聊天结束以后补充客户意向等级和下一步计划。这套机制的问题也很直接销售不愿意填填了也不准填了不及时。90% 的客户信息都散落在非结构化文本里。所以我们内部定了一个目标做一个处理器把“原始沟通文本”自动变成一张结构化的“客户跟进卡片”字段包括客户姓名、意向等级、核心需求描述、下一步动作、下次跟进时间然后批量写进现有 CRM。如果这一步跑通了销售主管每天早上看到的 CRM 就不是昨天销售自己填的“无效跟进”而是从真实对话里提取出来的有效情报。1.2 为什么这活 LLM 能干关键可行性判断其实最早我们想过纯规则方案因为提取的字段看起来不算复杂。后来发现规则方案必死同一句话在聊天场景里有无数种表达“下周”“周内”“月底前”“等领导批了再说”这些时间表达靠正则去匹配根本写不干净更别提客户名称不完整、客户意图隐含、中英文夹杂、各种口语化表达的问题。LLM 在做这件事上的核心优势在于它能“理解语义后填表”。你给它一段对话它能判断客户是真有意向还是纯客套能把“我大概月底能定”转成时间戳能把“我们现在用的系统太卡了”识别为痛点描述。这些能力在大模型普及之前需要做一整套 NER命名实体识别意图分类 关系抽取的流水线费时费力不说换一个业务场景又要重新做标注。我们当时做了一个小验证随机抽了 50 段真实聊天记录人工写清楚提取规则用大模型跑了一遍人工评估准确率达到 90% 以上其中意向等级这类主观字段的准确率稍低但也在可接受范围。这个验证决定了项目从“可能做”变成“立刻做”。1.3 整体技术方案一条从原始记录到 CRM 的数据管道整个系统我们设计成四个环节环环相扣采集层企微会话存档接口拉取原始消息按会话同一个客户同一个销售的对话聚合加上 ASR 转写出来的电话录音文本作为补充数据源。提取层调用 LLM把聚合后的会话文本输入模型模型按预设 JSON Schema 输出结构化字段。这里的关键是 JSON Schema 必须强约束不能用自由文本。审核层结构化结果进入一个“待写入区”由规则引擎判断置信度。高置信度的直接进入 CRM 自动写入队列低置信度或解析失败的去人工审核台由运营或销售主管在页面上批量确认/修改。写入层通过 CRM 的 OpenAPI 批量创建/更新客户记录、跟进记录写入之前做幂等和去重校验。为什么中间要有一个审核层因为沟通记录是要写进正式客户系统的数据一旦写错比如把客户 A 的需求写到客户 B 名下后面所有销售动作都会带偏。全自动不是不行但团队要有试错和兜底机制前一个月我们一直是高置信度自动写入 人工抽检稳定之后才逐步放开。1.4 模型与框架选型效果、成本与自控的平衡模型选型是第一个需要拍板的决策。我们最初接的是 Claude 和 GPT 两条线后来又加了国产模型做备用实测下来主流闭源模型在处理中文口语对话、输出 JSON 稳定性上都有不错表现。关键在选择标准上下文窗口会话聚合后经常超过 8K token窗口太小的模型会把对话截断导致后半段信息消失。建议至少要 16K 以上的上下文。结构化输出能力这个很重要。有些模型虽然文本生成能力强但输出 JSON 时经常混入解释性文本。优先选支持 JSON mode / Structured Output 的模型和 API。成本与延迟每段对话平均 2K token 输入 0.5K 输出按当时闭源模型定价估算单条会话成本在几分钱到一毛钱区间。日均处理 500 段会话成本在可接受范围但如果做全量历史数据回溯累计起来就要认真做成本控制了。框架层面我们没有引入重型 LLM Agent 框架因为这件事本质是“单轮结构化提取任务”不需要多轮工具调用也不依赖 Agent 记忆。直接用模型厂商的 Python SDK 或 OpenAI 兼容接口自己封装一层调用逻辑即可。引入 LangChain 这类框架反而增加一层抽象出问题排查麻烦。这是一个我当时特别想强调的选型原则能简单就不要复杂。2. 结构化提取的工程细节Prompt、Schema 与数据清洗2.1 让大模型学会“填表”JSON Schema 强制约束结构化提取的第一个难点是让模型输出的格式稳定可控。我们最开始的做法是直接在 Prompt 里写“请用 JSON 格式输出这些字段”结果模型时不时在 JSON 外面包一层 markdown 代码块偶尔还会多出解释性文字。后来我们统一改成使用支持 JSON mode 的接口参数让 API 层强制输出合法 JSON。在 Prompt 中提供严格的 JSON Schema 定义字段名、类型、枚举值逐一说明并在末尾附上一个 few-shot 示例展示“输入对话 → 输出 JSON”的完整对应关系。这里说的 JSON Schema 不是只写一个字段清单而是要尽量把边界条件也写清楚。比如“意向等级”只允许取“高/中/低/未知”四个枚举值模型默认倾向标“高”我们就得在 Schema 描述里加一句只有在客户明确表达采购预算或时间节点时才能标“高”否则按“中”或“未知”处理。输出示例{ customer_name: 王总, phone: 138****1234, intention_level: 中, need_description: 现有 OA 系统卡顿希望替换为低代码平台, next_action: 发送产品介绍文档并预约下周二演示, next_follow_up_date: 2025-06-10, summary: 客户对当前系统不满有替换意向需跟进演示 }最终我们在系统里对 JSON 输出做两层校验第一步是 JSON 语法解析第二步是字段级校验类型、枚举值、日期格式任何一步失败都进入重试队列。重试时会把上一次解析出的错误信息拼回 Prompt让模型自己修正。这个“错误修复循环”帮我们把 JSON 解析失败率从一开始的 7% 压到了 0.5% 以内。2.2 字段设计业务字段不是越多越好一开始产品经理给的字段清单有 20 多个什么客户预算区间、采购角色、竞品信息、客户情绪……LLM 都能给你填出来但填出来不意味着能用。字段越多模型出错概率越大运营审核成本越高写进 CRM 后真正被销售使用的字段却很少。我们最后砍到 8 个核心字段客户姓名、联系方式、意向等级、需求描述、下一步动作、下次跟进日期、会话摘要、备注。这 8 个字段是销售主管最需要的。其中“意向等级”和“下次跟进日期”这两个字段是后续自动生成销售待办的数据基础必须有其余能砍则砍。字段设计有一个原则能靠系统加工的就不要让模型去理解。比如客户所属行业我们本来想让 LLM 判断后来发现 CRM 里本身有客户行业的入口销售建客户时会填这个字段就不需要提取。手机号的提取也别完全依赖 LLM可以用正则从原文里先捞一遍把正则命中的号码交给模型做匹配确认正规率明显提高。2.3 对话文本的预处理先剪枝再投喂直接拿原始消息去调 LLM 的做法我们试过效果差。原因是企微会话存档里有大量噪音图片消息转出的 OCR 文本片段、视频号卡片、小程序链接、群聊里的无关发言、以及销售和客户互相发的“收到”“好的”这种寒暄消息。这些内容白白占用 token还会干扰模型判断重点。所以我们在投喂之前做了一次文本剪枝过滤系统消息、撤回消息、红包消息。去掉会话中的图片链接、文件消息体只保留文本。去掉单个文本消息超过 300 字的长篇大论这类一般是销售复制粘贴的合同条款或产品手册不是有效沟通信息。对连续寒暄消息如“早”“在吗”“嗯嗯”做合并压缩。剪枝之后再做聚合。企微的会话存档是一天一个文件同一段对话可能跨越两天。我们用“客户 customer_id 销售 user_id”作为会话聚合键把一个自然周内的消息合并成一段完整对话。合并时按时间排序如果中间间隔超过 2 小时就切成两个话轮避免把不同主题的沟通混在一起。2.4 异常与兜底处理“非销售对话”和“解析失败”这个点很实际。我们跑了一周后发现大约有 20% 的会话根本不是有效的销售沟通比如客户发了一句“在吗”销售没回或者两个人互发“节日快乐”这种对话根本没有提取价值。如果强行提取模型会给你编造意向等级和需求描述非常危险。处理方式是加一个预筛步骤在正式提取前先让模型判断这段对话是否包含业务价值。输出一个布尔字段 has_business_value如果为 false直接跳过提取不生成 CRM 记录。这个预筛步骤的 Prompt 非常简单只让模型输出 true/false成本极低但能规避大量无效写入。另外还碰到一个场景客户明确表示“这事你别管了”或销售已经跟单结束这种负向信号也要识别出来。我们在 Schema 里加了一个 status 字段允许值为 active跟进中/ lost战败或已终结/ pending待确认并让模型对 status 为 lost 的会话强制输出战败原因。3. 从 JSON 到 CRM批量写入的完整链路3.1 中间层设计待审核区与自动写入区LLM 提取出来的结果不能直接 write-through 到 CRM 主库我们设计了两个中间区域staging 表和审核队列。Staging 表保存全量提取结果核心字段包括会话 ID、来源渠道、原始消息摘要、LLM 返回的完整 JSON、解析后的结构化字段、模型名和版本号、Token 消耗量、处理状态。这张表的核心价值是留痕——任何时候发现写进 CRM 的数据有问题都能从 staging 表回溯到原始请求和模型响应。状态为“自动通过”的记录由一个定时任务每 5 分钟扫描一次批量调用 CRM 接口写入。状态为“待人工审核”的记录进入一个极简的审核页面页面展示对话摘要原始消息脱敏后 模型提取结果运营人员只需要确认或修改几个关键字段确认后一键入库。这里要注意一个节奏问题批量写入的粒度和频次不要设计得太激进。我们一开始做成实时写入结果 LLM 服务偶尔抖动导致下游 CRM 出现重复请求排查起来很麻烦。后来改成每 5 分钟一个批次批内做去重和校验出问题的概率小很多排查也方便。3.2 并发控制与限流别把模型供应商打爆LLM 提取服务和模型 API 之间也要做并发控制。我们用的是信号量限制同时进行的请求数量并给每个请求设置超时时间。一个常见的坑是把企微会话存档按会话聚合后有的会话消息数量特别大超过 100 条消息输入 Token 数会超过模型单次调用上限。这种会话我们实行“滑动窗口切段”每次只送最近 20 条消息 上一个窗口的结构化摘要既控制 Token 数又能保留对话上下文。限流参数的确定不能拍脑袋。我们根据模型供应商的 RPM每分钟请求数和 TPM每分钟 Token 数上限倒推本地队列的处理速率。举个例子如果模型 API 限制 RPM60我们本地就把并发数设为 30每秒处理 0.5 个请求留出 50% 的余量给其他业务服务。这样在高峰期也能避免 429 限流错误。写 CRM 接口也一样现成 CRM 的 OpenAPI 通常有频次限制。一开始我们一次性并发写入 200 条直接把 CRM 的 API 打挂了。后来改成每批 50 条、批间隔 1 秒从监控上看效果稳定不再触顶限流。3.3 写入 CRM 的幂等与容错重复会话不重复建单批量写入最大的坑是重复。同一个会话可能被处理两次比如消息延迟到达重组了会话LLM 结果也生成了两条记录写进 CRM 就会产生重复的客户跟进记录。我们的解决办法是设计一个幂等键用“source_type external_session_id process_date” 作为唯一业务键。CRM 的用户表如果已经存在该客户通过手机号的单向哈希匹配则走更新逻辑而不是新建客户跟进记录表则通过 business_key 做唯一约束重复写入时直接跳过。这个逻辑写进写入服务的开头批量处理前先查一次库里是否已有对应键有则更新字段无则新建。上线三个月重复记录率基本为零。另一个容错点是 CRM 接口返回错误时的处理。如果响应是 4xx 错误如参数校验失败说明是我们这边的问题直接记录错误日志把消息转入人工处理队列。如果是 5xx 错误或超时说明 CRM 服务暂时不可用消息进入延迟重试队列采用指数退避策略1 分钟、5 分钟、30 分钟后重试最多重试 5 次。超过重试次数进死信队列由人工介入。3.4 监控与审计每条数据都查得到“祖先”系统上线后最容易被忽略的就是监控。我们后来补了一套完整的指标和日志体系这里给个清单建议直接参考各环节处理量采集量、预筛通过量、提取成功量、写入成功量、人工触发量。处理耗时分布LLM 调用耗时 P50/P95/P99写入 CRM 耗时 P95。结构化提取质量指标JSON 解析失败率、字段校验失败率、人工审核通过率审核人员没有修改直接确认的比例。成本指标每日 Token 消耗量、每千次提取的模型成本、按场景分组的 Token 消耗占比。审计日志这里花了点功夫最终我们实现的效果是从 CRM 里任意一条自动生成的跟进记录点击详情能一路查到它的原始会话 ID、LLM 请求的 Prompt含原文、模型返回的 JSON、命中的人工审核操作记录。这个“数据血缘”能力在出问题追责时作用巨大。有一次客户投诉销售人员泄露了信息我们事后审计发现那条数据其实来自销售人员在其他渠道填写的不是系统自动写入的——审计链路帮团队洗清了误会。4. 常见问题与排查技巧实录4.1 JSON 解析失败和字段跑偏这个问题主要出现在模型版本升级后。原本正常的提取任务升级模型版本后突然出现大量 JSON 外层多一个 markdown 代码块的输出。我们的排查思路先看是单次失败还是批量失败单次失败大概率是输入文本中有特殊字符比如乱码、异常符号批量失败大概率是模型配置或参数变了。后来我们在调用层统一加了正则清理逻辑只抽取 JSON 大括号范围内的内容再做 json.loads解析成功率从 94% 提升到 99.5%。另外一个窍门Prompt 里的字段说明和示例一定要和 JSON Schema 保持一致一旦不一致模型就会选择性跟随。我们曾经在系统提示词里写“输出字段 follow_up_date”但示例里写成了“next_follow_up_date”导致模型有时输出这个键、有时输出那个键字段校验全挂了。排查半天才发现是低级错误后来在 CI 流程里增加了一个自动化测试用固定输入样本去跑模型确保格式和字段名稳定后才允许部署。4.2 提取结果不准漏提、错提、幻造信息“幻造”是 LLM 提取场景最危险的问题。模型会在需求描述里填写一些原文完全没有提到的信息。比如原始对话是“我们想了解下系统”模型输出需求描述为“客户要求系统支持多人协同和移动端”这明显是模型自己脑补的。我们的对策有三层第一层在 Prompt 里强制要求所有输出字段必须严格基于原文原文没有提到的内容一律填 null 或“未知”不允许推测。第二层在 Schema 里为描述类字段增加 max_length 限制和“基于原文概括”的指令。第三层抽检兜底。人工审核页面里把原始对话文本高亮展示在模型输出旁边运营人员一眼就能看出来模型是不是在编。如果某类场景幻造比例偏高就把这类场景的 few-shot 示例替换成更强的反例。漏提的问题通常发生在长对话里客户在中间提到“这个方案挺好的”然后又开始聊别的到结尾这个信息就被模型忘了。解决方式是滑动窗口切段的时候保留上一段摘要并在下一段 Prompt 开头加一句“以下是上一段对话摘要请综合参考但以最新消息为准”。这个问题也让漏提率从 11% 降到了 4% 左右。4.3 重复写入与数据漂白两个层面的重复会话级重复和 CRM 客户级重复。会话级重复上面已经说了解法用幂等键。客户级重复更隐蔽同一客户可能在不同渠道多次沟通企微会话存档里他是“王总”电话录音转录里他是“王明”CRM 里客户名是“北京某某科技有限公司”。这个关联问题我们没让 LLM 去做太复杂了改成了规则匹配优先用手机号做关联没有手机号的用“公司名模糊匹配 联系人来判定”。效果有限但比完全没有强。客户名提取不准是另一个高频问题。模型可能从对话里抓到一个别名“老王”“王哥”“姐”这些称呼不适合直接作为客户姓名写入。我们在字段校验里加了一个禁止名单包含“哥”“姐”“老”“先生”“女士”“老板”的姓名一律不通过交由人工编辑。这个规则简单粗暴但有效避免了 CRM 里出现一堆“张总”“李姐”的脏数据。4.4 成本与延迟的平衡技巧模型成本在跑量之后会非常可观尤其是历史数据回溯阶段。我们做过几轮优化效果显著按会话长度动态选模型短对话少于 500 token用便宜的小模型长对话才走大模型成本下降约 30%。缓存预筛结果同一个会话如果第一次预筛判定为无业务价值存一个 hash 标记下一次不会再重复调用模型。批处理合并请求支持 JSON mode 的模型可以一次输入多条会话、输出一个 JSON 数组。我们把 5 段短会话合并为一次调用单次调用成本降低了将近一半。设置预算上限供应商那边设了一个每月费用告警线触线后自动把任务切换到一个更便宜的模型保证系统不会因为账单失控而挂掉。延迟方面P95 单次提取耗时从最早的 3 秒优化到 1.2 秒。核心优化点是减少输入内 token 量把无关的寒暄消息删干净Prompt 里的示例也从 3 组减到 2 组。说实话做批处理不太追求单条延迟关键是吞吐量稳定能把当天的会话在凌晨全部处理完就行。5. 落地后的扩展从“能写进 CRM”到“真有用”5.1 用结构化结果为销售团队生成待办提醒数据写进 CRM 只是第一步真正让这套系统产生业务价值的是后续动作。我们把“next_action”和“next_follow_up_date”两个字段接入了 CRM 的待办模块。每天早上 9 点系统自动给对应销售推送一条待办“今天该跟进客户王总了上次沟通摘要客户对现有系统不满下一步动作是发送方案并预约演示。”这比销售自己定闹钟记跟进的体验好太多主管也不用天天催。上线两个月后销售对自动生成待办的接受度非常高甚至开始主动要求系统把“客户说了要方案”这种有强烈信号的消息更早推送出来。这一步让我们从“数据搬运工”变成了“销售助理”。5.2 按会话热度给客户打标签把历史三个月的沟通记录批量处理后我们按客户维度的会话数量、意向等级变化、需求集中度做统计分析给每个客户打上了“高活跃”“需求明确”“久未跟进”等标签。这些标签直接显示在 CRM 客户列表里销售的跟进排序就从“凭感觉”变成了“按系统提示”。5.3 把人工审核的数据变成模型微调数据这是我觉得最有长期价值的一件事。人工审核台每天都会产生大量人工修正后的高质量“输入-输出”对。我们把“修正前模型输出”和“修正后人工结果”收集起来按周维度导出作为模型的候选微调数据集。虽然我们还没有做真正意义上的模型微调但这份数据资产已经非常值钱未来如果要上垂域模型或做小模型蒸馏这是最现成的训练语料。这里也提醒一句收集人工修正数据时一定要做隐私处理客户姓名、手机号、企业名等敏感信息要做脱敏尤其是从聊天记录中提取的数据合规意识必须前置。我们是在项目初期就让法务和运维介入了数据存储和访问权限的设计避免后期出问题。另外提一个经验聊天原始数据中有大量客户隐私不要把它们直接存到模型提供商的日志系统里。我们所有发送给模型的 Prompt 都会先做脱敏替换把手机号、姓名替换成占位符模型返回后需要写库时再做一次反向映射。这样既保证提取效果又守住隐私底线。这块坚持做和客户沟通数据授权的时候就少很多麻烦。写在最后的体会这项目做下来最深的感触是LLM 结构化提取的难点从来不在于调用模型而在于上下游工程——数据清洗、格式约束、幂等去重、人工审核、成本控制、审计留痕每一环都比模型调用本身更考验工程功底。如果上来就想全自动一把梭大概率会被数据质量问题折磨到崩溃。稳妥的做法是先用半自动跑通闭环积累一批人工修正数据把业务信任度建立起来之后再逐步提高自动处理的比例。这套路子我们验证过走得通希望对正在做类似方向的同学有帮助。如果你也在做 LLM 提取 CRM 落地的项目欢迎一起交流踩坑经验。