专业人员在飞书里回复了一句意见,系统怎样知道这句话属于企微里的哪一条客户需求?即使找对了任务,这段话里的内部备注又该怎样与对客答复分开?
我们在语席科技的商务助手测试中遇到了这两个问题。客户咨询从企微进入,专业人员在飞书提供意见,业务记录保存在独立服务器。最初要求同事打开多维表格填字段,后来增加了直接回复通知的方式。员工少了一次切换,程序需要承担的判断却增加了。
下面结合现有 Python 实现,拆开任务关联、反馈抽取和回写过程。系统目前正在测试使用,案例匿名处理,不代表已经完成生产环境验证。
先建立通知消息与协作任务的对应关系
一条客户需求可能同时派给不同角色。客户需求保存在 task,协作任务保存在 workflow_collaboration,后者通过 source_task_id 指向原始需求。同一个客户名下可以有多条需求,因此仅凭客户名无法唯一定位。
派单时,系统记录飞书通知的 message_id 和本地 collaboration_id。用户沿通知回复,处理程序取得父消息标识,再查派单事件,找到对应的协作任务。关联到的是那条通知对应的任务,而非整个客户。
实现中有一个容易漏掉的细节。派单事件的 payload 以 JSON 字符串保存,曾经按字符串格式匹配会受到序列化空格差异影响。当前代码先解析 JSON,再比较 message_id。下面是去掉数据库遍历与异常分支后的最小示意,变量名沿用实现。
payload = json.loads(row["payload"] or "{}")
if str(payload.get("message_id") or "") == parent_message_id:
return int(payload["collaboration_id"])
这段代码只展示关联方式。消息来自谁、是否属于当前企业以及是否有权修改任务,仍需要在完整接入流程中核对,不能把拿到消息标识等同于完成授权。
没有引用通知时,归属判断有明确的退路
直接回复卡片最容易关联,但员工也会在对话里新发一句话。当前实现依次尝试显式协作编号、人员对应角色、项目或客户名称,再检查该人员是否只有一条待反馈任务。
如果仍有多个候选,测试版本还会检查最近两小时内的任务,尝试选出创建时间明确较晚的一条。同一时刻创建了多条候选,或者没有可区分的最近任务,才返回带编号的候选列表,请用户补充。
这是便利性与准确性之间的取舍。最近收到的通知不一定是员工正在回答的通知,因此回执必须写清本次记到了哪个项目、哪条任务,让人能够发现错误并带编号修正。对错配容忍度更低的业务,我更倾向于要求显式引用或编号,放弃按时间兜底。
这里也应分别测试沿卡片回复、显式编号、多任务并行和同一时刻派单。单独测试“消息能收到”,无法验证任务是否归对。
一段反馈拆成六个字段,原话另外保存
关联完成以后,模型负责把自然语言整理为字段。当前抽取结果包含 result、reply_points、customer_questions、risk_notes、alternatives 和 internal_note。
前五个字段分别承接处理结论、答复要点、待客户补充的信息、风险限制和替代方案。internal_note 单独保存内部意见,不作为对客建议的数据来源。原始反馈另外存入 feedback_raw,便于核对抽取结果以及重新整理。
联调记录里出现过一种错误。专业人员表达可以向客户承诺的时间,同时说明内部排期紧张,模型把内部排期信息同时写进了内部备注和答复要点。内部备注字段存在,并不能证明其他字段已经干净。
当前实现为此增加了独立清理步骤,再检查五个对客字段。清理结果变长时不采纳,避免检查过程继续扩写。不过,长度不增加也不能证明语义没有变化;更重要的是,当前清理调用失败会返回原抽取结果。这仍是需要改进的地方,不能把它描述成绝对可靠的隔离机制。
更保守的后续设计可以在清理失败时标记待审,阻止自动采用该结果。本文描述的测试链路最终仍由商务确认发送,模型整理不能替代人的判断。
抽取失败时保留原话,但不把原话直接用于对客生成
抽取调用异常、返回类型不符合要求或结果为空时,当前代码保留整段原话,并设置 raw 模式。它和前面的清理失败是不同分支,不能混为一谈。
回写时,原话仍可供内部人员查看,但反馈事件中的 public_fields 清空,同时设置 needs_review。这样下游知道有人已经反馈,也知道这段反馈还不能直接用于生成客户答复。
下面是对应条件的简化示意。
public = {
k: v for k, v in patch.items() if k in PUBLIC_FIELDS}
if mode == "raw":
public = {
}
needs_review = mode == "raw"
raw 模式下,协作记录也可能已经标记为完成。这里的完成表示已收到专业人员的反馈,和“反馈已整理、可用于对客建议”是两种状态。下游如果只检查完成状态,就会绕过待审判断。
数据回写、同步排队与反馈事件放在同一事务
apply_reply 会在同一个本地数据库事务中更新协作记录、加入同步待推队列,并在适用条件下写入 collaboration_feedback 事件。
三项工作各有用途。业务记录供后续查询,队列安排向飞书同步,事件驱动重新生成建议和通知商务。若只更新数据库,依赖飞书拉取变化的处理程序可能感知不到这次本地修改,建议也就不会刷新。
本地事务只能保证这些本地写入一起提交,不能保证飞书已经更新,更不能保证商务已经收到通知。因此系统还保留 sync_outbox、feishu_mapping、feishu_conflict 和 feishu_sync_state,分别记录待推内容、两边记录的映射、待裁决冲突和同步状态。
排查问题时,需要把“本地已保存”“外部已同步”“建议已刷新”“人员已获通知”分开观察。一次数据库更新成功,只能回答其中一个问题。
换工具时,要一起保留业务关系和处理状态
把数据库放在独立服务器之后,仍需要能导出任务关系、反馈原话、处理模式和同步映射。只导出一段答复文字,新入口无法据此判断它属于哪条需求、是否经过整理、还有没有待处理冲突。
知识积累也需要单独审核。客户本次的档期、特殊报价留在业务记录里,有复用价值的经验进入待审语料,确认适用条件后再形成企业知识。数据库中的一次反馈不应因被保存就自动成为长期口径。
当前测试组合是企微与飞书,其他工具仍需适配消息、身份、权限和字段接口。独立保存数据能减少迁移时的重建工作,不能免除这些适配。对于准备实现类似流程的开发者,建议先把一条反馈从通知关联到最终回执完整走通,再验证抽取异常、清理失败和同步中断三个分支。