Django 做一个 AI 销售助手:读取客户记录,自动生成跟进计划

0 阅读6分钟

Django 做一个 AI 销售助手:读取客户记录,自动生成跟进计划

Django AI 销售助手

销售助手最容易做成一个“看起来很聪明”的聊天框:把整张客户表塞给大模型,让它总结,再允许它自动发消息。演示很顺,真正接入 CRM 后却会遇到三个问题:客户数据过量、模型输出不稳定、一次误操作就可能直接打扰客户。

更适合落地的第一版,不是自动替销售做决定,而是完成一条可验证的小闭环:读取当前用户有权看到的客户和商机,按确定规则筛出值得跟进的记录,让 AI 生成结构化计划,人工确认后再创建 Django 任务。 本文结合本地 RuyiDjangoCRM 的真实模型与业务工具,做一个不依赖外部模型也能复现的最小实验。

先把 AI 放在正确的位置

从客户与商机到跟进任务

这条流程里,Django 和 AI 的责任不同:

  • Django 负责身份、组织范围、客户与商机查询、字段校验和任务落库;
  • 普通 Python 规则负责过滤已关闭商机、限制条数和计算风险分;
  • AI 只把已经筛选的业务事实组织成标题、优先级、截止时间和理由;
  • 人决定是否执行,确认后系统才创建任务。

这比“让模型直接访问数据库”多了一层编排,却保住了原有业务边界。模型即使输出错误字段,也只能在校验层被拒绝,不能越过 Django 自己发起写操作。

从真实 CRM 字段构造最小上下文

RuyiDjangoCRM 的客户记录包含名称、行业、电话、邮箱、收入等字段;商机包含阶段、金额、成交概率、预计关闭日期,以及在当前阶段停留的天数;任务则可以保存标题、状态、优先级、截止日期、说明和关联商机。

AI 不需要看到所有字段。销售跟进这个场景里,可以只给它客户名称、行业,以及最多 5 条未关闭商机:

def compact_context(account, opportunities):
    open_items = [
        item for item in opportunities
        if item["stage"] not in {"CLOSED_WON", "CLOSED_LOST"}
    ]
    ranked = sorted(open_items, key=risk_score, reverse=True)[:5]
    return {
        "account": {
            "id": account["id"],
            "name": account["name"],
            "industry": account.get("industry", ""),
        },
        "opportunities": ranked,
    }

电话、邮箱和大段历史备注默认不进入模型上下文。这样既减少无关内容,也降低把个人信息发送给外部模型的风险。需要回看历史时,也应按当前客户、当前商机和明确时间范围检索,而不是把全部沟通记录当作“长期记忆”永久堆进去。

风险排序不要全部交给大模型

“哪些商机更该先跟进”包含可计算事实。示例采用一个很朴素的评分:在当前阶段停留越久分数越高;金额达到 10 万加 30 分;成交概率达到 60% 加 20 分。

def risk_score(opportunity):
    score = min(int(opportunity.get("days_in_current_stage", 0)), 30)
    score += 30 if float(opportunity.get("amount", 0)) >= 100_000 else 0
    score += 20 if int(opportunity.get("probability", 0)) >= 60 else 0
    return score

这不是通用销售公式,而是一个可解释的起点。企业可以把阈值换成自己的销售规则,测试也能明确验证排序。AI 更适合根据排序后的事实写出人能快速判断的跟进理由,不适合悄悄发明金额、客户态度或成交日期。

让模型只返回严格 JSON

工具调用要有语义明确的名字、精确类型和边界说明。对这个助手而言,模型输出可以收窄为 5 个字段:

{
  "opportunity_id": "o1",
  "title": "确认年度续费决策时间",
  "priority": "High",
  "due_in_days": 1,
  "reason": "金额较高,且已在方案阶段停留 18 天。"
}

服务端随后检查:字段必须恰好匹配约定;优先级只能是 LowMediumHigh;截止时间必须在 0 到 30 天内;商机 ID 必须来自本次查询结果。任何多出来的 send_email、未知优先级,或者指向已关闭商机的计划,都直接拒绝。

人工确认后才创建任务

AI 销售助手的人工确认边界

预览阶段只返回上下文和计划,不写数据库:

preview = {"context": context, "plan": plan, "created": False}
if not confirmed:
    return preview

销售确认后,编排层把计划转换成 Django 任务字段:

task = crm_create("tasks", {
    "title": plan.title,
    "status": "New",
    "priority": plan.priority,
    "due_date": computed_due_date,
    "description": plan.reason,
    "opportunity": plan.opportunity_id,
})

截止日期由服务端根据“几天后”计算,模型不能直接提供任意日期;任务通过原有 CRM 接口创建,最终仍受当前用户身份、组织范围和 Django 校验约束。第一版明确不自动给客户发送邮件或消息:创建内部跟进任务与产生外部沟通,是两种风险完全不同的操作。

12 个测试验证了什么

这次最小实验使用一个内存 CRM 和固定模型输出,不需要 API Key,执行 python -m unittest -v 即可复现。12 项测试覆盖:

  • 高金额、长时间停滞的商机得到更高排序;
  • 已成交商机不会再次进入跟进列表;
  • 客户邮箱不会进入模型上下文;
  • 未确认时不产生任何写操作;
  • 确认后才创建并关联正确商机;
  • 截止日期由服务端计算;
  • 未知优先级、多余字段、不可见商机和不存在客户都会被拒绝;
  • 模型上下文最多保留 5 条商机。

测试通过不代表销售策略已经完美,它证明的是边界可重复:输入范围固定、AI 输出可校验、写操作可阻断。上线前还应补充真实 Django API 的组织隔离测试、模型输出质量评估和任务创建审计。

来源与证据

示例代码、12 项最小实验和机器可读结果保存在同一工作目录。真实项目证据固定在 RuyiDjangoCRM 提交 1fc5290f:MCP 查询与注册相关定向测试 21 项通过,Django 任务接口与商机老化相关测试 109 项通过。文中没有把这些测试扩张成“AI 销售策略正确”的结论,它们只支撑字段、接口和边界确实可运行。

复现最小实验:

进入示例代码目录后执行 python -m unittest -v

最后总结

一个能上线的 AI 销售助手,价值不在于它说了多少漂亮话,而在于它能否把现有业务数据变成一条可检查、可确认、可追踪的下一步行动。

最稳妥的起点是:Django 保管事实和权限,规则完成筛选,AI 生成计划,人确认后才创建任务。 等这条链路的准确率、可观测性和用户反馈稳定,再考虑会议摘要、历史偏好或自动沟通,成本和风险都会更可控。