从一条评论
到一个买家私信
这份指引专治"信息太多不知道从哪看起"。
读完 15 分钟,你能判断第一周做什么、找谁、怕什么。
一句话 Akke
我们在解决什么生意
先讲清楚生意,再讲怎么用代码解决它。
🎯 谁是客户
全屋定制商家 — 装修旺季订单上不来、淡季销售养不住,转介绍纯靠运气。
💔 痛点
抖音家居视频评论区埋着一堆真实买家("这衣柜多少钱?我家在成都"),但翻评论 + 人工私信完全做不过来。
✨ Akke 答卷
把"找意向 → 写文案 → 发出去"做成可量化的流水线,AI 干筛选和初稿,人只做关键判断。
业务全景:一张图
从公开评论到私信送达,一共 7 步。
每一步都对应到一段代码 + 一张数据表。下一节看具体走法。
| 步骤 | 谁在跑 | 数据落点 |
|---|---|---|
| ① 抓评论 | Fly worker(Python) | videos · comments |
| ② AI 评分 | Vercel Cron + LLM | comments.intent_score |
| ③ AI 起草 | Vercel API + LLM | messages · message_queue |
| ④ 人审 | 运营在仪表盘点 | message_queue.status |
| ⑤ 自动发送 | 本地 Mac / iPhone WDA | messages.status=sent |
| ⑥ 跟进回复 | Worker 收件箱轮询 | 新 messages 入库 |
| ⑦ 转交微信 | 运营人工接手 | conversations.stage=handed_off |
三段式架构
三块独立部署的代码,靠 Supabase 这张共享数据库交换状态。
🖥️ Vercel
Next.js 16 · App Router
仪表盘 UI(运营在这里审消息)+ API 层 + Vercel Cron 定时触发器。鉴权用 Supabase SSR;目录在 src/。
🗄️ Supabase
Postgres · RLS · Auth
共享事实源。多租户隔离靠 Row-Level Security 政策,按 org_id 自动过滤。schema 在 supabase/migrations/。
🤖 Fly.io Worker
FastAPI · Playwright · 东京
抓抖音评论、调签名 API、跑无头浏览器兜底。代码在 worker/。1GB VM 只能开一个 Chromium。
三方怎么对话
- 1Vercel Cron 入队每天 9 点把"今天要抓的号源"写进
scrape_jobs表,立即返回。cron/scrape - 2Worker 出队背景轮询 ~30s 一次,挑
pending行执行;结果(视频/评论)写回 Supabase。worker/queue.py - 3Vercel API 直连 Worker需要实时动作(如手动"立即抓取"按钮)走 HTTP,带
FLY_WORKER_SECRETBearer。/scrape/source/{id}
一条评论的旅程
用一个具体例子串完整条链路,建立"端到端"心智。
- T009:00 · Cron 入队Vercel Cron 触发
/api/cron/scrape,把"该博主"写入scrape_jobs(status=pending)。 - T109:00:30 · Worker 抓评论Fly worker 出队,先用 f2 签名直调 抖音 Web API(不开浏览器,快一个数量级),失败才落 Playwright;评论入
comments表,附带 IP 属地。 - T210:00 · Cron 跑 LLM 评分
/api/cron/analyze抓所有intent_score IS NULL的评论,分 batch 喂给大模型(DeepSeek V3),打 0~10 分 + 标签;高意向写回intent_score ≥ 7。 - T310:01 · 高意向 → 起草首发评分高的评论自动触发"起首发文案"路径:调 Qwen3-235B + 客户画像 + 品牌知识 + 视频上下文 → 写一条
messages(status=draft)+message_queue(status=pending_approval)。 - T410:30 · 运营审核Operator 打开
/queue,看到这条候选:左边是评论原文 + LLM 评分理由,右边是 AI 起草内容。3 选 1:通过 / 编辑后通过 / 拒绝。点了通过 → 行流转到approved。 - T5当日发送窗口 · 自动发出本地 Mac / iPhone WDA daemon 起来,按"暖场→打开主页→输入文案→发送"序列把私信送达;解 protobuf 校验业务级 status_code,确认真投递后写
messages.status=sent。 - T6对方回复 → 收件箱轮询接住worker dm_inbox_poll 周期性扫私信收件箱,发现新对话即写入
messages,conversations.stage自动从ice_break推进到nurture。 - T7意向坚定 → 转微信LLM 检测到决策信号("加你微信吧"/"现在能上门吗"),切到
decision阶段并注入品牌微信 ID/二维码;运营人工接手 → 阶段标handed_off。
核心数据表
不需要记字段,只需要知道每张表"管什么"。
身份与租户
| 表 | 装的是什么 |
|---|---|
organizations | 客户公司(一家定制品牌就是一个 org) |
user_org_memberships | 谁属于哪个 org,角色是什么(Owner / Operator) |
brand_profile | 每个 org 一份:品牌话术、微信号、二维码、报价规则 |
账号池
| 表 | 装的是什么 |
|---|---|
accounts | 抖音账号 — 分两类:scraping(用于抓评论)和 messaging(用于发私信)。每个账号严格归属一个 org。 |
source_accounts | "号源" — 我们要持续抓哪些博主的视频评论 |
采集管线
| 表 | 装的是什么 |
|---|---|
videos | 抓到的视频元数据 + 描述 |
comments | 评论原文 + IP 属地 + 城市 + LLM 打分(intent_score)+ 标签 |
scrape_jobs | "待抓任务"队列 + 进度 + 重试次数 |
对话管线
| 表 | 装的是什么 |
|---|---|
conversations | 一个抖音用户 ↔ 一个我方账号 的会话;带 stage 状态机:ice_break → nurture → decision → handed_off → closed |
messages | 所有发出去 / 收到的消息原文(含草稿) |
message_queue | "等审核 / 已批准 / 已拒绝" 的人审闸门 |
知识库与统计
| 表 | 装的是什么 |
|---|---|
knowledge_documents | 品牌话术文档(运营录入,注入 LLM prompt) |
conversation_examples | 金牌对话样本(few-shot 给 LLM) |
daily_stats | 每天的发送量、回复率、转化率快照 |
完整 schema 在 supabase/migrations/,21 个迁移文件按编号顺序就是项目演化史。
多租户与权限
2026-04-23 上线的多租户体系,3 类角色 + 3 层防御。
3 类角色
Staff
Akke 团队成员(我们)。可看所有 org 的数据,可切组织视图,可进 /staff/admin 改授权。
Owner
客户公司老板。管自己 org 的品牌档案、邀请成员、看全量统计。
Operator
客户公司一线审批员。每天审消息卡片就是主业。
3 层防御(缺一不可)
- ARLS(数据库层)Postgres 政策按
org_id自动过滤。任何 SQL 查询都拿不到不属于你的行。这一层只做 org 隔离,不做角色差异化。 - BAPI Guard(应用层)
src/lib/auth/guards.ts提供requireAuth/Staff/OrgMember/Owner。每个 API 路由必须显式调,不能漏。这一层管角色 — Operator 不能改品牌档案。 - CUI 置灰(界面层)用户角色不够时按钮不该出现 / 出现也是禁用态。这是 UX 兜底,不是安全兜底。
你是哪种角色?Day 1 清单
挑一个最像你的开始。可以跨角色看,但 Day 1 只盯一份。
Staff(Akke 平台)
Akke 内部团队
- 用 Lark 账号 SSO 登录
- 左上角 Org Switcher 切到任一客户组织巡检
- 进
/staff/admin管面板(授权/封禁/角色) - 读完"多租户三层防御"章节
Owner(商家老板)
客户公司决策者
- 首登配置抖音号源 — 粘贴博主主页链接不要要 sec_uid
- 进
/knowledge录品牌话术、报价规则、金牌对话 - 进
/members邀请审批员加入 - 看
/stats关注当日发送数和意向转化
Operator(一线审批)
客户公司运营
- 打开
/queue待审消息卡片队列 - 每条消息 3 选 1:✅ 通过 / ✏️ 编辑后通过 / ❌ 拒绝
- 有疑问看 "一条评论的旅程" 章节理解上下文
- 下班前看
/stats自评一天的判断质量
工程师
开发 Akke 本身
git clone→cp .env.local.example .env.local补 5 个密钥npm install && npm run dev→localhost:3000/loginnpm run test:all跑健康体检(data audit + schema probe + LLM smoke)- 必读
CLAUDE.md(架构 + 约定 + 踩坑索引)
15 分钟上手
每个场景挑一个你最常做的练手。
| 场景 | 步骤 |
|---|---|
| 🧑🔧 审一条消息 | /queue → 点卡片 → 看 LLM 评分和起草内容 → 通过 / 编辑 / 拒绝 |
| 👔 录一条话术 | /knowledge → + 新建文档 → 选分类(话术 / 报价 / 案例)→ 粘贴即走 |
| 👔 添新博主号源 | /sources → 粘 v.douyin.com 短链或博主主页 URL → 系统 302 解析出 sec_uid |
| 🧑💼 切组织看全局 | 左上角 Org Switcher 选目标组织,所有数据视图随之切换 |
| 👨💻 本地跑前端 | npm run dev,连 staging Supabase,热更新秒级生效 |
| 👨💻 部署后端 worker | cd worker && fly deploy(必须 cd 进子目录,否则 build context 会到 1.9GB) |
5 条最致命的坑
不是"可能出错",是"一定会踩"。上岗前过一遍省一天调试。
cd worker 再 deploy
仓库根有 node_modules 和 .next,不进子目录 build context 会炸到 1.9GB;fly deploy -c worker/fly.toml 不会改 build root。正确:cd worker && fly deploy。
messages.status 只认 pending_approval
手误写 pending 会直接触发 CHECK 约束报错。还有:message_queue 没有 content 字段,消息内容写在 messages,message_queue 只是闸门。
抖音发送失败时 worker 会返回 {success: false} 但 HTTP 还是 200。只判 res.ok 会把"消息没发出去"当成功。必须同时检查 data.success。而且抖音的 cmd:100 也不是真投递 — 要解 protobuf 拿业务级 status_code。
同一 sec_uid 招呼信息只能发 1 条 — 对方没回复 / 没互关之前再发都返 7462 错误码。规模触达只能扩号,单号扩不动。
抖音 handle/搜索/profile API 从 Fly 出口全部返回空;QR 登录面板根本不会出现。绕过:① 评论抓取走 f2 签名直调 ② 号源解析走 v.douyin.com 短链 302 跳转 ③ Cookie 在本地 Mac Playwright 登录后导入;④ 真正发送 DM 已切到客户本地 Mac / iPhone WDA。
想看更全的坑列表?项目 docs/claude-memory/MEMORY.md 里有 100+ 条按主题归类的记忆,每一条都对应一次真实事故。
术语词典
看到这些词不慌。
- org / 组织 / 租户
- 一家客户公司在 Akke 里的隔离单位,所有数据按
org_id强隔离。 sec_uid- 抖音用户的内部 ID,36 位字符串。系统内部使用;永远不要让用户手动输入,让系统从分享链接自动解析。
- 号源 / source_account
- "我们要持续盯哪些博主的评论区"。粘贴博主主页链接即可,系统通过
v.douyin.com短链 302 跳转拿到 sec_uid。 - scraping account vs messaging account
- 两类抖音账号 — 抓评论的(公开数据)和发 DM 的(私域触达)。独立账号池、独立速率预算、独立健康监控,一边被风控不影响另一边。
- 意向打分 / intent_score
- 0~10 分。LLM 看完评论 + IP 属地 + 视频上下文给的"这条评论后的人多想买"评分。≥7 算高意向,会自动起草首发文案。
- stage 状态机
- conversation 的 5 阶段:
ice_break(破冰首发)→nurture(来回沟通)→decision(要微信/约时间)→handed_off(人工接手)→closed。LLM 选 prompt 模板时按这个走。 - message_queue 闸门
- 所有出站 DM 必须先经过这张表。
pending_approval等审、approved待发、rejected丢弃、sent已送达。没有"自动发不审"模式。 - RLS / Row-Level Security
- Postgres 的行级权限。Akke 每张业务表的 RLS 政策都是"只能看自己 org 的行",由 Supabase auth 自动注入用户身份。
- Vercel Cron
- Vercel 的定时任务(
vercel.json里声明)。每天 9 点抓评论、10 点跑评分、12 点查回复、23 点出日报。 - worker
- 跑在 Fly.io 东京机器上的 Python 服务。负责所有需要"打开浏览器 / 调抖音原生 API"的脏活。
- WDA / iPhone Mirroring
- 2026-04-30 后采用的私信发送方案:iPhone 真机 + WebDriverAgent 自动化抖音 app + iPhone Mirroring 远程操控。比 Web 路径风控宽松 10 倍。
- knowledge_documents
- 客户录入的品牌话术 / 报价规则 / 案例库,会被截取(≤ 1500 字)注入 LLM prompt 让回复"懂行"。
- handoff
- 当 LLM 检测到客户表达决策意向("加微信"/"现在能上门"),自动给客户推品牌微信号 / 二维码并标
handed_off,运营人工接手。
延伸资源
📖 仓库内必读
CLAUDE.md— 工程师必读,架构 + 约定 + 部署校验docs/onboarding.md— 本指引的源 markdowndocs/claude-memory/— 100+ 条主题化的踩坑记忆supabase/migrations/— schema 演化史
🌐 团队知识库
- Akke 双链路防风控架构总览
- upio.ai 团队知识库首页
- Lark 知识库 · Akke 项目空间(请向 Staff 索取链接)
求助渠道
🛠️ 技术问题
找 Gustavo,或在仓库 issues 留信息。
先翻 CLAUDE.md 的"部署验证规范"自救。
💬 业务 / 流程
Akke Lark 群直接 @ 相关同学。
客户运营问题优先 @ Owner 同学。
🚨 紧急故障
立即 Lark 群广播 + 同步 Staff。
翻 docs/claude-memory/ 找最近相关条目,多数事故有先例。