34 KiB
AI 数字销售助手(ai_scheduler)
一句话定位:面向房产/大客户等复杂销售场景的 AI 系统——上传聊天记录 → AI 自动提取销售、项目、技巧、客户四大维度画像 → 构建"数字销售分身" → 在微信端模仿销售本人与客户对话,支持 AI 自动回复、主动触达、画像自迭代。
本 README 同时面向人类开发者与 AI 编程助手,描述项目的完整架构、接口契约、数据模型与开发约定。修改代码前请先读本文件。
目录
1. 项目定位与核心流程
1.1 业务全景
┌─────────────────────────────────────────────────────────────────────────────┐
│ 管理后台(admin.html) │
│ 登录 → 模型配置(LLM密钥) → 行业模板(含AI生成维度) → 管理员账号 │
└──────────────────────────────┬──────────────────────────────────────────────┘
│ 行业模板复制到项目
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ 项目后台(project.html) │
│ │
│ ① 创建项目(选行业模板 → 自动复制维度字段) │
│ ② 上传聊天记录文件 → AI 分析 → 返回四大角色结构化数据 │
│ ③ 数据中心(销售版本/项目资料/聊天技巧/客户画像 分维编辑保存) │
│ ④ AI 演练(模拟客户对话,任务驱动式训练) │
│ ⑤ 微信工作台(扫码登录/通讯录/发消息/AI 话术建议/自动回复) │
│ ⑥ 产品活动管理(发布活动 → AI 主动推送给目标客户群) │
│ ⑦ 智能策略(四级回复策略/熟客兜底/画像迭代/主动触达 手动触发与日志查看) │
└─────────────────────────────────────────────────────────────────────────────┘
1.2 四大角色(AdviceRole)
系统核心概念:将销售场景拆解为四个独立维度(角色),每个角色有独立的数据结构和存储集合。
| role 值 | 中文 | 含义 | Mongo 集合 |
|---|---|---|---|
advicer |
销售 | 销售个人风格:方言/句式/语气/性格/标志性对话 | advicer_version |
project |
项目 | 项目(产品)资料:区域价值/竞品对比/卖点/配套/开发商背书 | advicer_project |
skill |
聊天技巧 | 需求挖掘/痛点应对/价值塑造/促单/沟通节奏 | advicer_talk_skill |
client |
客户 | 客户画像:身份/购房目的/核心需求/顾虑/决策建议 | advicer_client |
AI 分析返回结构:data = { advicer: {...}, project: {...}, skill: {...}, client: {...} }
1.3 客户等级体系
| 等级 | 常量 | 含义 | AI 行为 |
|---|---|---|---|
"" |
ClientLevelUnknown |
未评估 | 正常 AI 回复 |
regular |
ClientLevelRegular |
熟客(已成交/高频互动) | AI 尽量不介入,人工接管;超时未回复时兜底礼貌回复 |
intent |
ClientLevelIntent |
意向客户 | 主动跟踪、下单邀约、活动推送 |
sleeping |
ClientLevelSleeping |
沉睡客户 | 仅推活动并尝试邀约 |
non |
ClientLevelNon |
非客户 | AI 不参与回复 |
1.4 智能策略体系(批次B)
- 四级回复策略:根据客户等级和对话上下文,决定回复策略(人工接管/AI兜底/AI主动/AI忽略)
- 熟客超时兜底:熟客发消息超过
regular_reply_delay_minutes(默认10分钟)无人工回复时,AI 自动礼貌回复 - 画像自迭代:对话结束后(闲置超过
dialog_idle_minutes默认30分钟),AI 分析新聊天记录完善客户画像 - 主动触达:生日祝福、活动推送(受活跃时段
active_hour_start~active_hour_end和总开关auto_reply限制)
2. 技术栈
| 层 | 技术 | 版本/说明 |
|---|---|---|
| 语言 | Go | 1.26 |
| Web 框架 | gofiber/fiber v2 | 不是 Gin,注意中间件写法差异 |
| 关系库 | MySQL | GORM + gen 生成的 *.gen.go 模型 + xorm.io/builder 条件构造 |
| 文档库 | MongoDB | mongo-driver v1.14,集合模型在 internal/data/mongo_model/ |
| 缓存 | Redis | go-redis/v9,AI 会话 prompt 缓存等 |
| DI | google/wire | cmd/server/wire.go → 生成 wire_gen.go |
| 鉴权 | JWT | middleware.AuthMiddleware,密钥 config.jwt_secret |
| 定时任务 | robfig/cron v3 | 客户评估/熟客兜底/画像迭代/主动触达 |
| LLM | OpenAI 兼容接口 | 火山引擎/OpenAI,配置存 MySQL ai_advice_model_sup |
| 对象存储 | 阿里云 OSS | 文件上传备用 |
| 配置管理 | spf13/viper | YAML 配置文件 |
| 前端 | 原生 HTML + CSS + JS | 零构建,随 Go 服务一起启动 |
2.1 分层与调用链
HTTP 请求
→ Fiber 中间件(CORS / 日志 / Recovery / JWT 鉴权)
→ Router(路由注册 + Vali 泛型参数校验)
→ Service(HTTP 适配层,internal/services/advice/*.go)
→ Biz(业务逻辑,internal/biz/*.go)
→ Impl/DataTemp(数据访问层,泛型基类在 tmpl/dataTemp)
→ Mongo Model(MongoDB 集合操作)
→ LLM Service(AI 调用封装)
→ 统一响应包装(registerCommon → {code, message, data})
2.2 统一响应约定
所有接口(除微信代理透传外)统一包装为:
// 成功
{ "code": 0, "message": "success", "data": <业务数据> }
// 分页
{ "code": 0, "message": "success", "data": { "list": [...], "total": 100, "page": 1, "pageSize": 20 } }
// 失败
{ "code": <业务错误码>, "message": <错误信息>, "data": null }
特例:c.Locals("skip_response_wrap", true) 时原样输出(微信代理透传上游 data)。
3. 目录结构
ai_scheduler/
├── cmd/server/ # 应用入口
│ ├── main.go # -config 指定配置文件,默认 ./config/config_test.yaml
│ ├── wire.go # Wire 依赖声明
│ └── wire_gen.go # Wire 自动生成(勿手改)
│
├── config/ # 配置文件
│ ├── config.yaml # 生产配置模板
│ ├── config_env.yaml # 环境配置
│ └── config_test.yaml # 开发/测试配置(默认使用)
│
├── sql/ # 数据库初始化脚本
│ ├── 01_ai_advice_project_template.sql # ★必须执行:项目表增加模板字段
│ └── 02_advicer_mongo_init.js # Mongo 集合初始化
│
├── internal/
│ ├── config/config.go # 配置结构定义(Config / AdvicerConfig 等)
│ │
│ ├── entitys/ # 请求/响应 DTO(数据传输对象)
│ │ ├── advicer.go # 销售/版本基础实体
│ │ ├── advicer_data.go # ★核心:主要业务请求/响应结构(~400行)
│ │ ├── advicer_admin.go # 管理员请求/响应
│ │ ├── advicer_industry.go # 行业模板请求/响应
│ │ ├── advicer_model_sup.go # 模型配置请求/响应
│ │ └── response.go # 通用响应结构
│ │
│ ├── data/
│ │ ├── model/*.gen.go # GORM gen 生成的 MySQL 模型(★勿手改)
│ │ ├── mongo_model/ # MongoDB 集合模型
│ │ │ ├── common.go # ★Item 包装类型 + AdviceRole 枚举 + AdviceData 接口
│ │ │ ├── advicer_version.go # 销售版本(方言/句式/语气/性格/标志性对话)
│ │ │ ├── advicer_project.go # 项目资料(区域价值/竞品/卖点/配套/背书)
│ │ │ ├── advicer_talk_skill.go # 聊天技巧(挖掘/应对/塑造/促单/节奏)
│ │ │ ├── advicer_client.go # 客户画像 + 等级 + 互动时间追踪
│ │ │ ├── advicer_chat_his.go # 会话聊天历史
│ │ │ ├── advicer_wx_msg.go # 微信消息流水(回调+发送记录)
│ │ │ ├── advicer_activity.go # 产品活动
│ │ │ ├── advicer_proactive_log.go # AI 主动触达记录
│ │ │ └── provider_set.go # Mongo Wire Provider
│ │ ├── impl/ # DataTemp 子类(MySQL 表级数据访问)
│ │ ├── constants/
│ │ │ ├── advicer.go # ★维度生成 Prompt 模板 + industryNameMap
│ │ │ ├── model.go # 模型常量
│ │ │ └── prompt.go # BasePrompt 基础提示词
│ │ └── error/error_code.go # 业务错误码(ParamErr/SysErr/ForbiddenErr)
│ │
│ ├── biz/ # 业务逻辑层
│ │ ├── advice_project.go # 项目管理
│ │ ├── advice_file.go # 文件上传与 AI 分析
│ │ ├── advice_chat.go # AI 会话(演练/话术)
│ │ ├── advice_advicer.go # 销售管理
│ │ ├── advice_advicer_version.go # 销售版本管理
│ │ ├── advice_skill.go # 聊天技巧管理
│ │ ├── advice_client.go # 客户管理
│ │ ├── advice_evaluate.go # 客户等级评估
│ │ ├── advice_strategy.go # 四级回复策略
│ │ ├── advice_iterate.go # 画像自迭代
│ │ ├── advice_proactive.go # 主动触达
│ │ ├── advice_activity.go # 产品活动
│ │ ├── advice_wx.go # 微信回调
│ │ ├── advice_wx_send.go # 微信消息发送
│ │ ├── advice_model_sup.go # 模型配置
│ │ ├── advice_industry.go # 行业模板
│ │ ├── advicer_admin.go # 管理员
│ │ └── provider_set.go # Biz Wire Provider
│ │
│ ├── services/advice/ # HTTP 服务层(Fiber Handler 适配)
│ │ ├── project.go # 项目接口
│ │ ├── file.go # 文件上传/分析接口
│ │ ├── chat.go # AI 会话接口
│ │ ├── advicer.go # 销售接口
│ │ ├── talk_skill.go # 聊天技巧接口
│ │ ├── client.go # 客户接口
│ │ ├── smart.go # ★智能策略接口(策略预览/手动回复/迭代/触达)
│ │ ├── activity.go # 产品活动接口
│ │ ├── industry.go # 行业模板接口
│ │ ├── model_sup.go # 模型配置接口
│ │ ├── advicer_admin.go # 管理员接口
│ │ ├── wxhook.go # 微信回调接口
│ │ └── provider_set.go # Service Wire Provider
│ │
│ ├── server/
│ │ ├── http.go # Fiber 实例创建(BodyLimit 32MB、Static 托管)
│ │ ├── server.go # Servers 结构(HttpServer + Jobs)
│ │ ├── router/
│ │ │ ├── router.go # ★路由总装:CORS / 响应包装 / JWT 鉴权 / Vali 泛型校验
│ │ │ ├── advicer.go # ★全部业务接口注册(~80个接口)
│ │ │ └── wx.go # 微信协议代理路由(通配转发)
│ │ └── provider_set.go
│ │
│ ├── middleware/
│ │ ├── AdvicerAuth.go # 销售端鉴权
│ │ └── jwt.go # JWT 鉴权中间件(AuthMiddleware,白名单机制)
│ │
│ ├── jobs/
│ │ └── advice_task.go # ★定时任务:客户评估/熟客兜底/画像迭代/主动触达
│ │
│ └── pkg/ # 内部工具包
│ ├── wx/ # 微信协议 SDK
│ │ ├── api.go # ★端点注册表(100+ 微信 API 端点定义)
│ │ └── ... # 登录/通讯录/消息等请求响应结构
│ ├── file_download/ # URL → 文本提取
│ ├── jwt.go / gorm.go / mongo.go / rds.go / response.go
│ └── ... # 其他工具
│
├── web/ # ★前端(零构建,原生 HTML+CSS+JS)
│ ├── index.html # 入口导航页
│ ├── admin.html # 管理后台页面
│ ├── project.html # 项目后台页面
│ └── assets/
│ ├── css/theme.css # 设计系统:深色科技风、玻璃拟态(~900行)
│ └── js/
│ ├── core.js # ★核心库:API封装/token/toast/modal/confirm/upload
│ ├── admin.js # 管理后台主入口(共享变量 + VIEWS 延迟包装)
│ ├── admin_modelsup.js # 模型配置模块
│ ├── admin_industry.js # ★行业模板模块(含维度编辑器 ~690行)
│ ├── admin_admin.js # 管理员模块
│ ├── project.js # 项目后台主入口(共享变量 + VIEWS 延迟包装)
│ ├── project_list.js # 项目列表模块
│ ├── project_detail.js # 项目详情模块
│ ├── project_analysis.js # 数据分析模块
│ ├── project_data.js # ★数据中心模块(销售/项目/技巧/客户编辑 ~35K)
│ ├── project_activity.js # 产品活动模块
│ ├── project_drill.js # AI 演练模块
│ └── wx.js # ★微信工作台模块(登录/通讯录/消息/AI建议 ~33K)
│
├── utils/ # 通用工具(外部可用)
├── pkg/ # 公共包
├── tmpl/ # 代码生成模板 + Excel 模板
├── Dockerfile # 多阶段构建(编译 → wire → 拷贝资源)
├── docker-compose.yml # Docker Compose 编排
├── Makefile # make wire / make build
└── go.mod # Go 模块定义
4. 数据模型
4.1 MySQL 表(关系型,GORM gen 管理)
| 表名 | 主键 | 核心字段 | 用途 |
|---|---|---|---|
ai_advice_admin |
admin_id |
type, name, account, pwd, status | 管理员账号 |
ai_advice_model_sup |
sup_id |
admin_id, sup_name, sup_way(1火山/2openai), key, url, file_model, json_model, chat_model, mode | LLM 模型配置(按 admin_id 隔离) |
ai_advice_industry_temp |
industry_id |
name, desc, advicer_desc, client_dimension, project_dimension, advicer_dimension, talk_skill_dimension, rule_dimension, status | 行业模板(维度字段存 JSON 字符串) |
ai_advice_project |
project_id |
name, model_sup_id, industry_id, template_desc, template_advicer_desc, + 5个 dimension 模板副本字段 | 项目基础信息 + 行业模板副本 |
ai_advice_advicer |
advicer_id |
project_id, name, birth, gender(1男2女), working_years | 销售人员 |
ai_advice_session |
id |
session_id(uuid), project_id, sup_id, advicer_version_id, client_id, talk_skill_id, context_cache, mission, mission_status | AI 会话记录 |
重要:
*.gen.go文件由 GORM gen 自动生成,禁止手动编辑。模型变更请同步sql/脚本。
4.2 MongoDB 集合(文档型)
| 集合名 | 核心字段 | 用途 |
|---|---|---|
advicer_version |
advicerId, versionDesc, dialectFeatures, sentencePatterns, toneTags, personalityTags, signatureDialogues | 销售个人风格版本 |
advicer_project |
projectId, projectInfo, regionValue, competitionComparison, coreSellingPoints, supportingFacilities, developerBacking | 项目(产品)资料 |
advicer_talk_skill |
projectId, advicerId, desc, needsMining, painPointResponse, valueBuilding, closingTechniques, communicationRhythm | 聊天技巧库 |
advicer_client |
projectId, advicerId, wxid, appId, clientLevel, levelReason, personalInfo, purchasePurpose, coreDemands, concerns[], decisionProfile[] + 互动时间追踪字段 | 客户画像 + 等级 + AI 运营状态 |
advicer_chat_his |
sessionId, User, Assistant{result, mission_status, mission_complete_desc}, inToken, outToken | 会话聊天历史 |
advicer_wx_msg |
appId, wxid, selfWxid, direction(customer/self/ai), msgType, content, msgId, source(callback/web/manual), analyzed | 微信消息流水 |
advicer_activity |
projectId, advicerId, name, content, startAt, endAt, targetLevels[], status(0草稿/1进行中/2停止) | 产品活动 |
advicer_proactive_log |
projectId, advicerId, clientId, wxid, type(birthday/activity), refId(去重键), content, status(sent/failed) | AI 主动触达记录 |
4.3 *Item 包装约定
Mongo 原始模型(如 AdvicerVersionMongo)不含 _id 字段,列表查询无法返回记录 id。项目在 mongo_model/common.go 中定义 *Item 包装类型:
type AdvicerVersionItem struct {
Id primitive.ObjectID `bson:"_id" json:"id"`
AdvicerVersionMongo `bson:",inline"`
}
前端所有"编辑/删除"操作使用该 id(hex 字符串)。新增 Mongo 模型列表接口时必须沿用此模式。
4.4 MySQL vs Mongo 命名差异
| 场景 | MySQL | MongoDB |
|---|---|---|
| 列/字段名 | 蛇形(project_id) |
驼峰(projectId) |
| 条件查询 | 用列名 | 用 bson tag |
| 主键 | 自增 int | primitive.ObjectID(hex 字符串) |
5. 后端接口清单
Base URL:/api/v1/admin/advice/admin/,全部为 POST + JSON;除 login 外均需请求头 Authorization: Bearer <token>。
5.1 鉴权
| 路径 | 说明 | 请求 → 返回 |
|---|---|---|
login |
管理员登录(白名单,无需 JWT) | {account, pwd} → {token, admin_id, name, account, type} |
5.2 模型配置(ai_advice_model_sup,按 admin_id 隔离)
| 路径 | 说明 |
|---|---|
modelsup/add |
{sup_name, sup_way(1火山/2openai), key, url, file_model, json_model, chat_model, mode} |
modelsup/update |
同上 + sup_id |
modelsup/list |
{page, page_size} → {list, total, ...} |
modelsup/del |
{sup_id} |
模型三种用途:file_model(聊天记录解析)→ json_model(行业维度生成等结构化输出)→ chat_model(AI 对话/演练)。
5.3 行业模板(ai_advice_industry_temp)
| 路径 | 说明 |
|---|---|
industry/add / update / del / list |
CRUD;字段:name, desc, advicer_desc, client_dimension, project_dimension, advicer_dimension, talk_skill_dimension, rule_dimension, status |
industry/generate |
AI 生成维度模板:{sup_id, name, desc, advicer_desc, dimension};dimension ∈ {客户维度, 项目维度, 销售维度, 聊天技巧维度} |
industry/list仅返回status=1的记录。
5.4 项目(ai_advice_project + Mongo advicer_project)
| 路径 | 说明 |
|---|---|
project/base/init |
新建项目:{name, modelSupId, industryId};industryId>0 时自动复制行业模板维度 → {projectId} |
project/base/update |
更新基础信息与模板字段(仅非空字段生效);industryId>0 时按模板覆盖 |
project/template/copy |
重新应用行业模板(全量覆盖):{projectId, industryId} |
project/list |
{name, page, page_size} → 分页列表 |
project/info |
{projectId} → {Base(MySQL), ConfigInfo(Mongo), ModelInfo(模型配置)} |
project/info/add |
新建 Mongo 项目资料 |
project/info/update |
更新项目资料(全量 $set 语义,前端保存前先拉取合并) |
5.5 文件与 AI 分析
| 路径 | 说明 |
|---|---|
file/upload |
multipart(字段名 file,≤32MB,白名单:doc/docx/pdf/txt/md/xls/xlsx/csv/json)→ {path, url, name, size} |
file/word/ana |
聊天记录分析:{wordFileUrl, projectId} → 四大角色结构化数据 |
5.6 销售 / 版本 / 技巧 / 客户
| 路径 | 说明 |
|---|---|
advicer/add advicer/update |
{advicerId(0=新增), projectId, name, birth, gender(1男2女), workingYears} |
advicer/list |
{projectId} → 列表 |
advicer/version/add update del list |
销售版本 CRUD(MongoDB) |
skill/add update del list |
聊天技巧 CRUD(MongoDB) |
client/add update del list |
客户 CRUD(MongoDB) |
client/bind |
客户绑定微信 wxid |
client/evaluate |
客户等级评估(熟客/意向/沉睡/非客户) |
5.7 产品活动
| 路径 | 说明 |
|---|---|
activity/add update del list info |
活动 CRUD |
activity/active |
当前活跃活动列表 |
5.8 微信回调与消息流水
| 路径 | 说明 |
|---|---|
wx/callback/set |
设置上游消息回调地址 |
wx/callback/info |
获取建议的回调地址 |
wxmsg/list |
消息流水查询 |
5.9 智能策略(批次B)
| 路径 | 说明 |
|---|---|
smart/reply/test |
策略干跑预览(send=true 时实际发送) |
smart/reply |
对客户最新消息手动执行策略回复 |
smart/regular/scan |
熟客超时兜底扫描 |
smart/iterate/run |
手动触发画像迭代 |
smart/proactive/scan |
主动触达扫描(生日/活动) |
smart/proactive/send |
手动推送给指定客户 |
smart/activity/push |
活动立即群推 |
smart/proactive/log |
主动触达记录查询 |
5.10 AI 会话(演练/话术)
| 路径 | 说明 |
|---|---|
chat/regis |
注册会话:{advicerVersionId, talkSkillId, mission, clientId} → sessionId(uuid) |
chat/chat |
对话:{sessionId, content} → {result, mission_status, mission_complete_desc} |
5.11 管理员
| 路径 | 说明 |
|---|---|
admin/add update list del |
管理员 CRUD(字段:admin_id, type, name, account, pwd, status) |
6. 前端架构
6.1 设计原则
- 零构建:原生 HTML + CSS + JS,无 webpack/vite/npm,后端
app.Static("/", "./web")直接托管 - 模块化拆分:主入口文件(admin.js / project.js)定义共享变量和 VIEWS 注册表,功能模块拆分到独立文件
- 延迟包装函数:VIEWS 中的 render 使用
function () { renderXxx(); }延迟包装,解决模块文件后加载的函数引用问题 - 统一设计系统:所有页面共用
theme.css(深色科技风、玻璃拟态)和core.js核心库
6.2 文件结构
web/
├── index.html # 入口页(管理后台/项目后台入口 + 健康检测)
├── admin.html # 管理后台(加载 core.js + admin.js + admin_*.js)
├── project.html # 项目后台(加载 core.js + project.js + project_*.js + wx.js)
└── assets/
├── css/theme.css # 设计系统(CSS 变量 --primary/--grad/--bg-card 等)
└── js/
├── core.js # 核心库(window.Core)
├── admin.js # 管理后台主入口(VIEWS: modelsup/industry/admins)
├── admin_modelsup.js # 模型配置(renderModelsup)
├── admin_industry.js # 行业模板(renderIndustry + 维度编辑器)
├── admin_admin.js # 管理员(renderAdmins)
├── project.js # 项目后台主入口(VIEWS: list/detail/analysis/data/drill/activity + wx)
├── project_list.js # 项目列表(renderList)
├── project_detail.js # 项目详情(renderDetail)
├── project_analysis.js # 数据分析(renderAnalysis)
├── project_data.js # 数据中心(renderData:销售/项目/技巧/客户编辑)
├── project_activity.js # 产品活动(renderActivity)
├── project_drill.js # AI 演练(renderDrill)
└── wx.js # 微信工作台(window.Wx.mount/unmount)
6.3 core.js 关键 API
| 成员 | 说明 |
|---|---|
Core.api(path, body) |
管理后台接口:自动带 JWT、解包 {code,message,data}、code≠0 抛错、401 触发 Core.onAuthFail |
Core.wxApi(path, body) |
微信代理接口:自动带 X-finder-TOKEN,返回上游 data 原样 |
Core.upload(file) |
multipart 上传 → {path,url,name,size} |
Core.toast(msg) / Core.loading(show) |
通用提示/加载 |
Core.modal(title, content) / Core.confirm(msg) |
弹窗/确认对话框 |
Core.store(key, val?) |
localStorage JSON 读写 |
localStorage 键:as_admin_token、as_admin_info、as_wx_finder_token、as_wx_app_info、as_active_project。
6.4 维度编辑器
行业模板的核心交互组件,位于 admin_industry.js。
维度模板 JSON 格式(存储在 MySQL *_dimension 字段中):
{
"字段名1": { "type": "string", "desc": "字段说明", "example": "示例值" },
"字段名2": { "type": "object", "desc": "字段说明", "example": {"key1": "value1", "key2": "value2"} },
"字段名3": { "type": "array", "desc": "字段说明", "example": ["示例1", "示例2"] },
"字段名4": { "type": "list", "desc": "字段说明", "example": [{"k1":"v1"}, {"k1":"v2"}] }
}
四种类型与编辑器映射:
| type | 含义 | example 结构 | 编辑器 |
|---|---|---|---|
string |
描述 | "示例值" |
单行文本输入 |
object |
详细信息 | {"key": "value", ...} |
KV 对编辑器(左 key → 右 value) |
array |
多条目 | ["值1", "值2"] |
多条文本输入 |
list |
列表 | [{"k":"v"}, ...] |
多组 KV 对编辑器 |
7. 定时任务(Jobs)
定义在 internal/jobs/advice_task.go,通过 robfig/cron v3 调度,服务启动时 app.StartJobs() 触发。
| 任务 | Cron 表达式 | 说明 | 超时 |
|---|---|---|---|
| 客户等级评估 | 0 {hour} * * * |
每天 daily_evaluate_hour 点(默认 0 点)评估所有客户的等级(熟客/意向/沉睡/非客户) |
30min |
| 熟客超时兜底 | */2 * * * * |
每 2 分钟扫描「人工超时未回复」的熟客,执行礼貌性回复 | 5min |
| 画像自迭代 | */10 * * * * |
每 10 分钟扫描闲置结束的对话,分析新聊天记录完善客户画像 | 20min |
| 主动触达 | 0 * * * * |
每小时整点扫描生日/新活动,AI 主动发起对话(受活跃时段与总开关限制) | 30min |
防堆积:使用 cron.SkipIfStillRunning 链,上一轮未完成时跳过本轮。
配置项(config.advicer):
| 字段 | 默认值 | 说明 |
|---|---|---|
wx_token |
空 | 上游微信协议服务 Token |
callback_token |
空 | 回调校验 token |
dialog_idle_minutes |
30 | 对话完成判定阈值(分钟) |
regular_reply_delay_minutes |
10 | 熟客超时回复延迟(分钟) |
active_hour_start |
9 | 主动触达允许起始小时 |
active_hour_end |
21 | 主动触达允许结束小时 |
auto_reply |
false | AI 自动回复总开关 |
daily_evaluate_hour |
0 | 每日评估执行小时 |
8. 维度模板规范
8.1 维度 JSON 结构
行业模板的 client_dimension、project_dimension、advicer_dimension、talk_skill_dimension、rule_dimension 字段均为 TEXT 类型,存储 JSON 字符串。
JSON 结构规范:
{
"字段名": {
"type": "string | object | array | list",
"desc": "业务含义说明(销售视角)",
"example": "与 type 严格对应的示例值"
}
}
8.2 AI 生成维度
调用 industry/generate 接口,后端拼装 Prompt(constants/advice.go:PromptIndustryGenerate),AI 返回 5~10 个字段定义。
维度名称映射(industryNameMap):
| 中文维度名 | 抽取提示词核心 |
|---|---|
| 客户维度 | 客户身份/购买动机/核心需求/顾虑/决策链/决策风格 |
| 项目维度 | 标的物/需求匹配/价值论证/竞争对比/信任背书/交付/服务/交易条件 |
| 销售维度 | 方言特征/句式习惯/语气标签/性格标签/标志性对话 |
| 聊天技巧维度 | 开场破冰/需求挖掘/价值塑造/异议应对/成交促单/沟通节奏 |
9. 微信协议代理
9.1 代理机制
路由:/api/v1/project/wx/<上游路径>
router/wx.go以wx.Request转发到上游https://wx.chuapi.com/finder/v2/api/- 请求头必须携带
X-finder-TOKEN(协议服务令牌) - 上游响应
{code, msg, data}由wx.Request解包;code≠0 或 HTTP 错误 → 502 - 成功时
data原样输出(不包装{code,message,data},通过skip_response_wrap实现)
9.2 核心端点
| 路径 | 请求 → 响应 |
|---|---|
login/getLoginQrCode |
{appId, regionId, proxyIp, type} → {appId, qrData, qrImgBase64, uuid} |
login/checkLogin |
{appId, uuid, autoSliding:false, proxyIp, captchCode} → {status(0未扫码/1已扫码/2成功), headImgUrl, nickName, loginInfo{wxid...}} |
login/checkOnline |
{appId} → true/false |
login/logout |
{appId} |
contacts/fetchContactsList |
{appId} → {friends[], chatrooms[], ghs[]} |
contacts/getBriefInfo |
{appId, wxids[]}(≤20/批)→ [{userName, nickName, remark, bigHeadImgUrl...}] |
message/postText |
{appId, toWxid, content, ats:[]} → {toWxid, createTime, msgId, newMsgId, type} |
完整端点表(100+)见 internal/pkg/wx/api.go。
9.3 消息回调
- 上游通过
wx/callback/set设置的回调地址,将客户消息推送到服务端 - 回调入口:
POST /api/v1/advicer/wx/callback(不走 JWT,内部校验 callback_token) - 消息入库为
advicer_wx_msg集合记录,是画像迭代与分析的基础数据
10. 启动与部署
10.1 本地开发
# 1. 执行 SQL 迁移(sql/01_ai_advice_project_template.sql)
# 2. 准备配置 config/config_test.yaml(MySQL/Mongo/Redis/jwt_secret/server.port=8090)
# 3. 启动(-config 缺省为 ./config/config_test.yaml)
go run ./cmd/server -config ./config/config_test.yaml
# 访问:
# http://localhost:8090/ 入口页
# http://localhost:8090/admin.html 管理后台
# http://localhost:8090/project.html 项目后台
10.2 修改依赖注入后
在 internal/biz|services 新增构造依赖(provider_set.go)后,必须重新生成:
# 方式一:Makefile
make wire
# 方式二:手动
go run -mod=mod github.com/google/wire/cmd/wire ./cmd/server
10.3 Docker 部署
# 构建(多阶段:编译 → wire → 拷贝 config/web → 创建 upload 目录)
docker build -t ai-scheduler .
# 运行(默认读取 ./config/config_test.yaml)
docker run -p 8090:8090 -v ./config:/app/config ai-scheduler
10.4 前端静态资源规则
- 所有页面由后端
app.Static("/", "./web")托管,新增页面直接放web/即可,无需构建 - 上传文件通过
app.Static("/upload", "./upload")暴露(返回的url可被file/word/ana回读)
11. 开发约定与避坑指南
11.1 代码生成文件
*.gen.go(GORM gen)和wire_gen.go(Wire)禁止手动编辑- MySQL 模型变更请同步
sql/迁移脚本
11.2 鉴权白名单
- 管理后台路由挂了 JWT 鉴权中间件,白名单仅放行登录接口
- 新增无需登录的接口须在
router.go的AuthMiddleware白名单中追加完整c.Path()
11.3 Mongo vs MySQL 命名
- Mongo 查询返回结构体字段名以 bson tag 为准(驼峰:
projectId/advicerId) - MySQL 条件用 蛇形列名(
project_id/advicer_id)
11.4 Mongo 全量更新
project/info/update等为全量$set语义- 务必"先读后合并再写",否则会清空未提交字段(前端已按此实现)
11.5 错误处理
- 后端错误统一用
errorcode.ParamErr/SysErr/ForbiddenErr返回*BusinessErr - 前端 toast 其 message
- 数字/字符串类返回值经
HandleResponse写入 body,再被registerCommon包装为{code, message, data}
11.6 前端模块开发
- 新增管理后台模块:在
admin_*.js中定义renderXxx()函数,在admin.js的VIEWS中注册(使用延迟包装函数) - 新增项目后台模块:同理,在
project_*.js中定义函数,在project.js的VIEWS中注册 - 不要在
VIEWS对象中直接引用函数(render: renderXxx),必须用延迟包装(render: function () { renderXxx(); })
11.7 历史遗留代码
internal/biz/handle、llm_service、pkg/rec_extra等为历史遗留死代码,不在cmd/server依赖图中- 若其编译报错不影响主服务,可忽略
11.8 文件上传
- 请求体上限 32MB(
fiber.Config{BodyLimit: 32 * 1024 * 1024}) - 扩展名白名单:doc/docx/pdf/txt/md/xls/xlsx/csv/json
- 存储路径:
./upload/日期/uuid.ext