一个开咖啡馆的老板,坐在电脑前做了20轮盲测。屏幕上每次出现两条回复,一条来自微调过的小模型,一条来自带提示词的大模型,他不知道哪条是谁写的,只选自己真会发出去的那条。19票被记录下来,结果没站在微调那一边。
![]()
这是 ReplyDesk 的作者自己写下的结论。他做了一个给街边小店回 Google 评论的工具——修车行、理发店、牙医诊所、咖啡馆、水管工、小商店。店主每周都收到评论,大多数从来不回,因为写一条像样的回复要花十分钟,而聊天助手写出来的回复全都一个味道:"感谢您抽出宝贵时间分享宝贵反馈,我们致力于……"顾客一眼就能看出来。
ReplyDesk 只做一件事。你打开一个收件箱,里面是待回复的评论,点开一条,得到三样东西:一条用店主口吻写的草稿、这家店过去怎么回类似评论的记录、以及一个检查——如果草稿里出现了店铺事实撑不住的承诺("我们会退款""明天给您打电话"),它会把标记翻成"需核对"。店主自己改、自己复制、自己贴到 Google Business Profile 上,工具从不代发。
成本是这门生意成立的前提
在微调过的模型上,一条回复大约 $0.0001。一家每月60条评论的店,服务成本不到一美分,所以哪怕每月收 $3 到 $5,也几乎全是毛利。作者说这只有在模型够小、够开放时才成立——换成大型闭源模型,单条回复成本要高出许多倍,而且价格是别人说了算。
他自己先把这个想法拆了:这不就是把评论粘进 ChatGPT 吗?他的回答是,部分是。带好提示词的聊天助手能写出完全合格的回复,在他的测试里,人们往往还更喜欢那种。ReplyDesk 加在模型外面的东西是店铺上下文——你的事实、你过去的回复、以及一个拦下你兑现不了的承诺的检查。他说他不认为模型本身值钱,值钱的可能是围绕它的工作流,而这一点他还没证明。
三次微调,三次踩坑
数据来自 McAuley 实验室的 Google Local Reviews 数据集,评论和店主回复成对出现。他取了四个州(怀俄明、佛蒙特、蒙大拿、爱达荷),拿到 590,054 对。但大多数店主回复不值得学:很多是每条评论下粘同一段话,有些是机器翻译的,有些夹带电话号码,还有些来自有社媒团队的连锁店。
他的过滤脚本只保留满足这些条件的配对:回复是英文、在60天内、没有联系方式、来自六种店铺类型之一的非连锁商家、不是模板、并且和评论真的共享了词。剩下 50,954 对。训练集和测试集按商家切分,测试评论来自模型没见过的店。
模型是 Qwen3.5-4B,LoRA rank 32,用 tinker-cookbook 的监督配方,只对回复算损失,关掉思考。
- v1 学了所有通过过滤的数据,也学会了像真实店主那样说话——包括不好的那部分。一条测试回复开头是:"Cameron,你显然是搞混了。我们在店里没见过你。"真实店主会这么写,但他的用户不该。
- v2 去掉了争辩、说评论是假的、以及纯套话的回复。结果礼貌但寡淡,大量"谢谢评论,下次见"出现在描述了具体问题的评论下面。
- v3 只保留20词以上、且谈到评论者说的至少两件事的回复;对1到3星评论,要在开头几行认下问题。最终 6,000 对训练数据,一个 epoch,1.28M tokens,约 $0.95。三次加起来花了约 $4,来自 $10 的 Tinker 额度。
应用通过 Tinker 的 OpenAI 兼容端点调用微调模型。他分享了一个坑:在 Qwen3.5 上关思考要用 extra_body={"reasoning_effort": False},传布尔值。字符串 "none" 和 "low" 会被拒绝;如果思考没关,小的 max_tokens 会被思考过程吃光,你拿到一条空回复。
评测结果:微调做对了它被训练的事,但人不买账
他用四个写手给300条留出评论(一半是1到3星)写回复:同一个4B加仔细的提示词、微调过的4B、Qwen3.8-27B加同样的提示词、以及真实店主的回复。评审来自另一个模型家族(gpt-oss-120b,同样跑在 Tinker 上),四条回复随机顺序、不带标签地看。
微调确实做到了它被训练的事:回复长度向真实店主靠拢,套话比真实店主还少,编造的承诺也更少——而编造承诺正是会让店铺惹上麻烦的东西。
但评审模型不喜欢它。这个评审把真实店主的回复也排在了接近底部。带提示词的模型写得更长、会把评论里的某个细节复述回去,而 LLM 评审奖励这种行为。作者因此怀疑评审量的是"精致度",不是"店主会不会发这条"。他没有为了让自己的模型赢去改评测,表格就按跑出来的样子留着。
这也是应用里有个盲测页的原因:一条评论配两条回复,分别来自两个4B模型,左右随机,选你会发的那条。投票进数据库,显示在"Is it better?"页面上。他把这个给了真实店主用,结果在下一节,而且没朝他希望的方向走。
第一个用户和19票
第一个用户是 Pratik,在 IIIT Naya Raipur 附近开 HOP-In Cafe。他在 ReplyDesk 里建了店铺(名字、区域、关于咖啡馆的三条事实),粘进一条 Google 页面上的真实评论,发了一条回复。然后他做了盲测:20轮,19票被保存下来。
19票的结果和评审模型一致。微调模型听起来更像真实店主,但真实店主仍然选了更长、更详细的提示词回复,大约五分之四的时候。作者说这是一个人、19票,他不会把它当成普遍结论。但它确实告诉他:他押的那个注——匹配店主风格能赢过好的提示词——在这个测试里没成立。
应用里没有计费,所以没人付过钱。他说他不会去声称一个自己没验证过的价格。
检索和记忆怎么搭的
店铺、评论、已发回复、评测结果、盲测投票,以及来自训练商家的 11.5k 条示例回复,都存在 Tiger Cloud 免费服务上,跑 Postgres 18 加 pg_textsearch(BM25)和 vectorscale(DiskANN)。打开一条评论时,一条 SQL 语句取 BM25 前20和向量距离前20,用倒数排名融合合并,你自己的历史回复排在最前。BM25 抓精确词("刹车片""根管"),向量抓语义("他们让我一直等"和"等了很久")。
他的 Hugging Face 推理额度中途用完了,所以查询向量化跑在浏览器里(@huggingface/transformers 加 bge-small-en-v1.5,放在 Web Worker 里)。加载完成前,搜索只用 BM25。没有嵌入服务器。这些示例显示在草稿旁边,但不进提示词——模型只在评论上训练过,所以应用发的就是训练时的提示词。
店铺事实存在 Backboard 里,每家店一个 assistant,每条事实是一条 memory。打开评论时,记忆搜索只返回匹配的事实。修车行的评论抱怨一辆车修太久,会拉出"活儿延误时用 WhatsApp 当天同步",而不是"前台找 Ramesh"。Backboard 挂了就回退到全部事实。承诺检查用 Groq 的 gpt-oss-20b 列出草稿里所有承诺,对照店铺事实核验,撑不住的把标记翻成"需核对"并显示那一行;Groq 失败时用关键词检查顶上。
技术栈是 Next.js 16、React 19、Tailwind 4、drizzle-orm、Phosphor 图标、bun,部署在 Vercel;数据和训练侧用 Python 加 uv 和 polars。
作者列了他认为开放创新重要的理由:权重是他的,Tinker 明天消失他也能在笔记本或便宜 GPU 上跑一个4B;价格是他定的,$0.0001 一条让 $3 的订阅成立,换成大闭源模型毛利会被压没,还得看别人的价目表;他能改模型做什么,不只是改怎么问它——微调把回复挪到了店主的长度、砍掉了套话和编造的承诺,这是闭源 API 上的提示词做不到的,尽管它没让人更喜欢这些回复;以及开放数据让这一切成为可能,没有研究者公开那五十万条真实店主回复,什么都做不成。
下一步他想做的三件事:把"提示词模型 + 店铺事实 + 承诺检查"和微调模型对打,因为那可能才是真正的产品;把评论自动拉进来,而不是复制粘贴——发到 Google 需要 Business Profile API,他还没试过;再训一个版本,保留人们似乎喜欢的"提到评论者说了什么"的习惯。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.