在这个 AI 爆发的时代,我做了些什么
楔子⌗
《列子·汤问》里有个叫偃师的工匠,给周穆王献过一个"倡者"——一个会唱歌跳舞的人偶。
表演快结束的时候,这个人偶朝穆王的姬妾抛了个媚眼。穆王大怒,要当场杀了偃师。偃师没辩解,只是把人偶拆开给他看:里面全是皮革、木头、胶漆和颜料,五脏六腑一应俱全,但都是假的。拆掉心脏,它就不能说话;拆掉肝脏,它就不能看东西;拆掉肾脏,它就不能走路。
穆王看完,叹了一句:“人之巧乃可与造化者同功乎?”
这个名字我是在第四版的时候才用上的,当时只觉得好听。写到第五版才明白,这个典故真正的重点不在"造得像人",而在最后那一下拆开——穆王的愤怒源于它表现得太像人了,而平息愤怒的方式,是证明它里面全是机关。
至于我这个偃师,机关是从五年前一个睡不着的半夜开始装的。
2020 年 3 月 12 日,半夜⌗
那天半夜我突然冒出一个念头:微信有没有把我这个人记下来?
不是那种阴谋论式的担心,是一个很具体的好奇——我每天在这个软件里敲这么多字,它手里应该有一份比我自己还清楚的我。我的爱好、我的作息、我跟谁最亲近,全在里面躺着。
于是我开始搜微信的数据库存在哪儿,怎么解密。
那天晚上我做出了人生第一份聊天报告。
我知道了自己最爱说的是哪几个词,知道了自己一天里哪个时段最话痨,知道了跟我聊得最多的人是谁,还知道了我最喜欢用什么形式的消息。
所以那个问题的答案是:记下来了,一条不落。而且解出来比我以为的容易得多。
从这天开始,我就跟微信"杠"上了。
2021 年 5 月:让它一直跑着⌗
一年后,我建了个文件夹,叫 web-wechat。
想法特别朴素:那份报告是我手动解出来的,一次性的,做完就没了。我想要个能一直跑着的东西,把聊天记录自动存下来,以后想什么时候出报告就什么时候出。
技术上这一版是正经的:走网页版协议,扫码登录、收消息、存库,图片视频语音全都转存到对象存储。2022 行,公开仓库,还有人给我提过 PR。五个版本里只有它真被别人用过。
东西跑起来之后我发现一件事:它已经在群里了,而且它认识时间。
于是我给它加了倒计时提醒。command.go 里支持的全部指令就三个:放假倒计时、过节倒计时、下班倒计时。
这三个里我最偏爱下班倒计时。正常情况它老老实实回你"距离下班还有 X 小时 Y 分钟",但你要是挑周末或者节假日问它:
不会吧不会吧,不会有人{节日}还在上班吧
晚上六点以后问,它也不客气:
不会吧不会吧,不会有人这个点还没下班吧
放假倒计时同样欠揍。还剩一两天它说"{明天}就是{节日}啦,再坚持一下咯~",正日子问它就是"今天已经是{节日}了啊,不会你还没放假吧?",一年的节都过完了它会告诉你"今年的节日好像已经过完了咯~"。
这些话发送失败的时候,日志里打的是这么一行:
log.Errorf("阴阳怪气失败: %v", err.Error())
阴阳怪气失败。2021 年的我,是把阴阳怪气当成一个正式功能在写的。
它待的一直是我那几个朋友群,后来多了个 web-wechat 的项目群,没进过工作群。答傻了就答傻了,有人截个图笑话它两句,顺便笑话我,仅此而已。
至于统计报告,越往后越没人再提起。倒是另一个念头冒了出来:这堆聊天记录反正一直在攒,为什么不给群里也出一份?谁昨天话最多,谁最爱发表情包。
想是这么想,web-wechat 没做。2021 年 11 月,这个仓库的提交停了。
2022 年 1 月:摸鱼王、划水公、摆烂侯⌗
网页版协议能拿到的东西太少,做排行榜那点数据抠得很费劲。我盯上了另一条路:iPad 协议。
于是 2022 年 1 月,新开一个仓库,叫 wechat4ipad。半年,121 个 commit,85 个文件,4975 行。
排行榜是在这一版做出来的。每天早上八点,一条叫"#昨日水群榜"的消息准时发进群里,给昨天说话最多的三个人各发一个称号:摸鱼王、划水公、摆烂侯。
说得越多,爵位越大。
从 2020 年那个半夜到这里整整两年,我终于把当初那份只给自己看的报告,变成了一个当众点名的东西。虽然它跟"洞察人性"已经没什么关系了,就是每天告诉大家昨天谁最闲。
这一版还有个我挺喜欢的功能,指令叫"启用偷偷赚大钱"。判断条件是工作日的上班时间,中午十二点到两点除外,那是午休。一个群要是超过两小时没人说话,机器人就自己跳出来发条消息,配个表情包,问问大家是不是都在偷偷赚大钱。
一个定时器,一个时间窗口,一个 if。
但这是我第一次让机器人在没人叫它的时候主动开口。
“你叫它、它回答你"也是这一版才有的。处理器的第一件事就是判断有没有被 @,是的话直接走 NLP——腾讯云的智能闲聊接口。2022 年上半年没有大模型可用,所谓"聊天机器人"就是调一个云厂商的闲聊 API,你问一句它答一句,答得怎么样全看运气。
答得再傻,这也是这个项目里第一次有人叫它、它就回话。比 ChatGPT 早了将近一年。
2022 年 6 月,iPad 协议过期了,账号也被封了。逆向来的东西都这样,能用多久没人说得准,哪天失效了顺带把号一起带走。
这是第二次了。第一次是网页版协议被关,这次是 iPad 协议过期。我开始隐约意识到一件事:我做的所有东西,脚底下踩的那块地都不是我的。
2022 年 12 月:AI 第一次撞进来⌗
半年后,ChatGPT 发布。第十二天,我给 web-wechat 加了一个插件。
加回那个已经半年没动的老仓库,理由很简单:web-wechat 是公开的,有人在用,给用的人添个新玩意儿。
当天的 README 更新只有一句:
2022-12-12,跟个风对接了
ChatGPT
字面意思。我知道这东西很厉害,但不知道它厉害在哪,更不知道能拿它干什么,所以就把接口接上,剩下的让用的人自己玩去。
于是 open_gpt.go 成了这个仓库的第五个插件,排在"下班自动回复"后面。
触发方式还不是 @ 机器人,是个写死的字符串:消息第一行必须是 @openai,从第二行开始才是你要问的。
然后是这个插件的全部智能所在:
// 组装消息 TODO 懒得搞上下文联动,有想法的可以自己实现,
// 只需要组装一下下面这个Message字段就行了,把之前的记录带过去
request := gpt3.ChatCompletionRequest{
Model: gpt3.GPT3Dot5Turbo0301,
Messages: []gpt3.ChatCompletionRequestMessage{{Role: "user", Content: question}},
}
那个 Messages 数组,长度永远是 1。
没有历史,没有 system prompt,没有人设。你上一句问了什么,它下一句完全不知道。出错了就把 Go 的原始 error 直接甩到群里,后面跟着一长串带 API 地址的英文报错。
而我给自己留的注释是:“懒得搞上下文联动,有想法的可以自己实现。”
“有想法的人"指的当然是别人。
这个插件只活了半年。2023 年 6 月,微信把网页版的登录入口也关了,新号扫不上码,web-wechat 跟着一起没了。
两年死两次,死因是同一个:我够不着的那一层。
2024 年 2 月:一栋精装修的空房子⌗
两条协议路都断了,第三版只剩下最后一个选择:往 PC 端微信进程里注入 DLL,从内存里把消息 hook 出来。代价是我得伺候一台 Windows 机器 7×24 小时开着微信客户端,不能关机,不能更新,最好连碰都别碰。
当时我觉得这挺合理的。
这次我给自己定的目标是"做个正经平台”。于是该上的全上了:消息队列、完整 RBAC、OAuth2 加图形验证码、协程池、定时任务、配置热重载。最得意的是一套 Lua 插件系统,虚拟机池、并发控制、生命周期管理,我还给它写了单元测试。
readme 里的功能列表五条:机器人管理、消息管理、插件系统、AI 助手模块、todo。
看起来挺唬人的对吧。我当时也这么觉得。
那套我最得意的 Lua 插件系统,暴露给插件的全部 API 是这样的:
// wxhelper函数映射
var wxhelperFuncMap = map[string]lua.LGFunction{
"SendTestMsg": nil,
}
而从池子里取虚拟机那个调用,整个仓库只出现在 pool_test.go 里。池子、并发控制、生命周期、单元测试我全写完了,唯一跑过这套系统的是它自己的测试。
“AI 助手模块"也有一张像模像样的表:名称、人设、模型、是否启用,配套的增删改查、路由、参数校验一个不少。你可以在后台新建一个助手,给它起名叫"小美”,写上人设,选好模型,点启用。
而这个项目的 go.mod 里,没有 OpenAI,一个大模型 SDK 都没有。处理每条微信消息的那个函数,从头到尾只干三件事:解析 JSON、切出发信人、存库。
你精心配置的那个"小美”,会一直躺在那张表里,没有一行代码会去读它。
联系人表里还有个老熟人:
SkipChatRank bool `gorm:"comment:'是否跳过聊天排行'"`
可这一版根本没有聊天排行。两年前那个摸鱼王划水公摆烂侯,我一行都没往这儿搬。
三样东西,全是架子。那阵子本职工作特别忙,留给这个项目的只有零碎时间,而零碎时间刚好只够搭架子:建张表、定个接口、起个连接池,边界清楚,一晚上能收尾,做完还挺有成就感。把一个功能从头打通要的是整块时间和连续的注意力,那个我当时给不起。
然后我就伺候不动了。那台必须 7×24 开着微信的 Windows 机器,微信一更新就可能失效,hook 一失效整条链路就断,修一次过阵子再断一次。2024 年 2 月 29 日,最后一次提交。
更要命的是,我的微信号被封了。号一封,什么正经平台、什么虚拟机池、什么 RBAC 全是废话,你连不上去了。
两年前 iPad 协议那次我就赔过一个号,也已经明白了脚底下那块地不是我的。明白归明白,我转头又挑了条同样是逆向出来的路,然后又赔一个。
这次赔得比上次疼。服务器挂了可以再开一台,微信号里装的是你的联系人、你的群、你这些年的聊天记录,它不是我项目的基础设施,它就是我本人。
等了大半年才解封,解封之后还得老老实实当个人用一阵子把号养回来,又是几个月。所以那个"停更十八个月"不是我热情过了跑去干别的,是我没有号。而这段时间,正好是这个行业炸得最厉害的时候。
至于那栋空房子,等我有号的时候,我已经不想再回去住了。
2025 年 9 月:偃师⌗
让我重新开始的不是什么顿悟,是两件事同时到位了:号养回来了,模型也终于追上来了。
工具调用稳定了,上下文长了,结构化输出能用了。三年前我说自己"跟个风"、不知道这东西能干什么,现在知道了。
2025 年 9 月 8 日,第四版第一次提交。这次我给它起了名字:偃师。
前三版我管它叫"网页微信"、“iPad 协议机器人”、“微信机器人”,都是工具的名字。这次不一样了,虽然当时我只是觉得这名字好听。
这一版写了整整一年,235 个 commit,两万两千行后端加九千多行前端。接入方式换成了第三方微信协议服务,终于不用再伺候那台 Windows 了。
这一版是真做进去了。各类消息都能解析归档,每个好友和群单独配人设、模型和提示词,工具和技能都能挂,记忆做了三种并且带向量检索。群里没 @ 它的消息会先过一道裁判模型判断该不该接话——那个"偷偷赚大钱"的 if,到这儿变成了一次模型调用。
跟第三版最大的区别不在技术栈,在于这次我先做的是"它要干什么",扩展性一个字没写。工具和技能是后来加的,因为我真的需要它们去查东西、跑脚本。
这一版是能用的。能部署、能运营、别人拿去也能跑。它没崩过,也没出过事故。
灵光一闪⌗
也是第四版那阵子,我干了件当时以为只是好玩的事。
我把自己这些年的聊天记录翻出来,连同已经攒下的那些记忆总结,一起蒸馏成一套人设,配给一个 Agent,然后扔进了一个老朋友群。
02:确实 我甚至可以带入**(我)在说这段话
侯师傅:这勾八机器人跟**嘴脸一毛一样。看它回复我都能想到你的脸=嘴脸
在那之前,我做的一直是"一个会聊天的机器人"。它可以有人设、有记忆,但那是给它穿的衣服,脱下来它还是个工具。
这两句之后,我脑子里的东西变了:如果它能像到这个地步,那能不能做一个在赛博世界里不会消失的"我"?
当然不一定非得是我。人设换一个,它就是另一个人——这也是后来第五版把人设、记忆、关系全都做成可配置的原因。但那天真正让我动心的,是"我"这个念头。
AI 真正改掉的东西⌗
目标一变,第四版立刻就不够用了。
而这一年里 AI 对我做的事,比"写代码变快了"要复杂一些。
想法开始变多⌗
第四版跑顺之后就进入了那种挺舒服的状态:不用再大动,隔三差五修个小毛病,想起来什么就顺手加点什么。也就是在这段修修补补的日子里,我开始让 AI 帮我写代码。一开始只是补补测试、改改样板,后来越用越多。
产出速度确实上去了,但真正的变化不在速度上——是我的想法开始变多。
以前想加个功能,得在脑子里掂量好几天值不值得动手,因为动手意味着接下来几个晚上都搭进去了。成本一降,想法就不值钱了,“试试呗"这三个字出现的频率高得可怕。
然后我发现,这些想法塞不进去。
第四版的架构是照着"一个能聊天的机器人"长出来的,每一块单看都对,但凡要往里加点什么,你会发现得从消息入口一路改到发送出口,动一处牵一片。它不是不能改,是改起来不划算。
干了十二年开发,这种局面我不是第一次碰上。每开一个新项目我都会提醒自己想远一点、架子留活一点,别又把自己堵死,然后每一次还是会走到积重难返这一步。
大概这就是写东西的宿命:你只能照着开工那天的理解去设计,而后来真正逼你动架构的,全是那天你还想不到的东西。
读的成本塌了⌗
定下"做一个不会消失的我"这个目标之后,我没有马上动手,先去看了看别人是怎么做的。
我找了些 Agent 开发的课看,然后开始读源码。这回我是让 AI 陪着一起读的,它负责定位和梳理,我负责判断。
goclaw、hermes-agent、picoclaw,三个项目读下来,我把每家值得学的地方整理成文档,加起来一千七百多行。后来它们跟着进了新版本的 docs 目录,不是当存档,是当我自己的经验——别人已经想明白的事,我记下来,往后就照着办。
goclaw 那份里记着一组数字:
生产 Go 文件 1,456
生产 Go 代码行 275,279
Go 测试文件 917
而我那个"能跑、能部署、没出过事故"的第四版,两万两千行。
那几天我脑子里反复冒出来的念头是:我这个就是个毛坯。
毛坯不等于不好用,它一直挺好用的。毛坯是说它没有骨架。别人那边有明确的分层流水线,有一级的安全与治理,有"核心收成窄腰、能力往边缘长"这种想清楚了才定得下来的结构;我这边是一堆能跑通的代码堆在一起,靠我的记性维持秩序。
这一步搁以前我多半不会走。一个二十多万行的陌生项目我未必读得完,更别说一口气读三个还写出一千七百行笔记——不是我不想,是成本太高,我会告诉自己"先不看了,反正我这个够用”。
AI 把这个借口拿走了。
错的东西也变快了⌗
但同一件事还有另一面:盖空房子的速度,同样快了五倍。
2024 年我手搓一个没人用的 Lua 虚拟机池要花好几天,今天我一个下午能造十个,每个都配齐测试和文档,README 写得漂漂亮亮,摆出来谁看了都得夸一句。
当年那栋空房子是因为我时间不够,只够搭架子。换句话说,那时候成本本身就是一道过滤器——大部分不成熟的想法,还没轮到被验证,就先被"我没空"挡住了。
现在这道过滤器没了。
以前我的问题是"想法很多,但没时间做"。现在是"想法很多,而且半天就能做出来"。瓶颈从生产能力挪到了判断能力上:代码不再稀缺,稀缺的是知道哪些代码根本就不该存在。
一个错误的想法,现在可以在一个下午里拥有实现、测试、文档和 README,看起来跟一个正确的想法一模一样。
所以在第五版上,“我应该做什么"和"什么事情绝对不能发生”,第一次变得比"这段代码怎么写"更重要。
2026 年 7 月:先写禁令,再写代码⌗
第五版没从 main.go 开始写。
我先自己把想要的东西一点点想清楚,落成一份四千多行、一万多字的设计文档。
然后是那几个通宵。一万多字滚成了十余万字的 spec,我跟 Claude 和 ChatGPT 一句一句过,每一条边界情况都得有个交代才放行。那阵子天天干到凌晨两三点,一行代码没写。
里面有五十五条编了号的规矩,从 R-01 到 R-55,每条都是一句不能违反的话。不能丢消息,不能重复发送,不能要求人工点重试,摘要不能当成记忆。
等一下。先写一大堆设计再动手——这不就是 2024 年那个空房子的做法吗?
区别在于我写下来的是什么东西。
2024 年那一堆,本质上全是承诺。插件系统承诺以后能插进来点什么,RBAC 承诺以后会有很多人来用,那个"是否跳过聊天排行"的开关承诺以后会有排行。承诺的麻烦在于你没法判它的对错——那个"以后"还没来,谁也说不出它错在哪,它就只能安安静静地烂在那儿。
这五十五条是禁令。禁令能被违反,一违反就看得见,所以每一条都能写成检查、写成测试、写成门禁,在我图省事的时候当场拦住我。
说白了,我的活儿变了。以前我负责把功能写出来,现在我得先划出哪些事情绝对不许发生。
spec 定稿之后,代码才开始动。那阵子 vibe coding 正热,我也就这么上手了。
2022 年我也在风口上接过一次 ChatGPT,那回是因为压根不知道它能干什么,先接上再说。这次不一样:我很清楚自己要什么,手里有十余万字的 spec 和五十五条不能违反的规矩,缺的只是把十一万行代码敲出来的产能。
vibe coding 负责把它们敲出来。那五十五条负责保证敲出来的东西不会又变成 2024 年那栋房子。
到今天,第五版 286 个 commit、11.6 万行生产代码、10.7 万行测试、1957 个测试函数、83 个数据库迁移、5.2 万行前端,外加四个我自己写的门禁工具。是第四版的五倍多,而用户能看到的功能几乎一模一样。
这些数字看着唬人,但行数从来不等于工作量,它只说明机械的那部分被 AI 接走了。真正花掉我时间的是另外一半:定边界、写约束、把 spec 磨到每种意外都有交代、然后逐个验收它到底有没有照着办。
这五倍全花在了同一个问题上:一个替我说话的东西,怎样才能不把事情搞砸。
不能假装没听见⌗
前四版处理消息都很直接:来一条,处理一条,忙不过来就让它等着,或者干脆不接。娱乐机器人这么干完全没毛病,我也这么干了五年。
但一个要长期替我说话的东西不行。
所以第五版里,消息不再是来一条处理一条。连着来的消息会被并成一个窗口,一个窗口只跑一次、最多回一次;运行期间新到的照样入库、照样进记忆,只是排到下一个窗口去。哪怕群里说到一半突然安静了,积压也会在一个上限时间之后被处理掉,不会永远悬在那儿等下一个人开口。
要是一个窗口里的话太多,超过了模型能一次吃下的量呢?那就分段、就摘要,但每一条都必须被标记成"已经纳入处理"。
可以处理不过来,不能假装没看见。
不知道就是不知道⌗
微信发消息没有幂等键,发出去撤不回,而且它不会回调你自己发的消息。于是有一种情况绕不过去:我调了协议服务,连接在返回之前断了,这条消息到底有没有出现在对方手机上,我不知道。
绝大多数系统在这里会选择重试。可在这个场景里,重试的代价是一个真人多收到一条一模一样的话。
所以我给出站消息留了第三种结局:
pending → sending → sent
→ failed
→ unknown
failed 只用在我能证明它确实没发出去的时候。其余所有说不清的,一律算 unknown。
而 unknown 是终态。它不自动重发,控制面也不提供人工重试的按钮——这一条我犹豫了很久,因为按钮是最容易加的东西,加上去还显得很贴心。但只要它存在,就一定会有某个半夜的我去点它,然后我朋友的手机上多出来一条重复的话。
整个系统的语义因此被钉成一句:宁可丢一条,不能重一条。
这显然不是什么普适真理,换成告警通知它就是错的。但在"一个东西用我的身份跟我朋友说话"这件事上,重复比漏发更伤人。我把这个取舍写进了架构,而不是留给将来某个疲惫的自己临场发挥。
它得能解释自己⌗
第四版的配置是每条消息现查数据库的。所以我今天把人设改了,昨天那句让我觉得"它怎么这么冲"的回复,就再也还原不出当时的现场。
第五版每次开口之前,会把这一刻的配置、人设、记忆、上下文全部冻结成一份快照,跟这一次运行绑死。哪怕之后我把人设改得面目全非,翻回去还是看得见它当时是在什么条件下说的那句话。
还有一条我很喜欢的规矩:万一一个进程失联了、被另一个接管了,那么它后来姗姗来迟的结果一律作废,只留档,不许改变当前的世界。
第四版里它跑飞了我只能翻日志猜,现在它跑飞了会留下一份现场。
它到底是谁⌗
前面那三件都是工程问题。这一件是那个老朋友群给我留下的功课。
一个人之所以是他自己,靠的是他记得什么、他跟谁什么关系、以及他在什么场合愿意开口。第五版把这三样拆开做了。
它的记忆分了好几层:关于某个人的、关于某个群的,还有关于它自己的——它经历过什么,形成了什么说话习惯,对谁做过什么承诺。记忆不是模型想写就写,一个模型提出来,另一个独立的模型复核,过了才算数。
这些记忆之间有严格的次序,自我记忆排在人设的硬边界后面。也就是说,它可以慢慢长出自己的脾气,但不能借着"我记得"这四个字给自己加权限、改规则,或者把某个人随口一句话变成永久的铁律。
还有条边界我想了挺久:一个 Agent 还没被配置出来的时候,系统只记中立的事实,不建关系,不推断亲疏,不生成自我记忆。
主体还不存在的时候,不该有主观记忆。
至于群里到底说不说话。第四版的裁判提示词第一句是"默认倾向于保持沉默",第五版我把这句删了。理由是:外向的人设就该更爱接话,疏离的就该更爱旁听。把"少说话"写死进去,最后所有人设都会退化成同一个谨慎的客服。
现在它可以选择回答、明确拒绝、或者干脆沉默。“明确拒绝"和"沉默"是两回事——前者是"我知道你在叫我,但这次不想答”,会留下完整的记录;后者才是真的当没听见。裁判算出来的态度和语气还会注入回对话,让它说话的调子跟关系对得上。
四年前那个"两个小时没人说话就发一句"的 if,走到这儿变成了:模型看一眼当前的关系、场景、人格和上下文,然后决定要不要开口、用什么态度开口。
五年前那行"阴阳怪气失败",现在有编制了。
而万一裁判模型自己挂了,它一律降级成沉默,绝不会降级成主动说话——坏也得往安全的那头坏。
它已经不只是一个微信机器人了⌗
这项目不是 AI 时代的产物。它的起点是 2020 年 3 月 12 日半夜那个"微信有没有把我记下来"的念头,那会儿 ChatGPT 还得两年半才出生。第一次让机器人回答问题用的是腾讯云的闲聊接口,第一次接大模型的理由是"我的开源仓库有人在用,跟个风加一个"。
我没去追它。它按自己的节奏长,我按自己的节奏折腾,两条线在 2025 年前后碰到了同一个路口上。
我这边攒了五年:一个真实的场景、一堆聊天记录、三次把东西做死的经验,还有一脑子当时做不出来的想法。它那边,刚好长到了能扛住这些想法的地步。
早两年不行。2022 年我接过一次,那会儿它还撑不住,结果就是那个长度永远为 1 的数组。晚两年大概也不行,我多半已经把这堆代码忘干净了。
至于那些头疼的事——上下文、记忆、身份、副作用——本来就是这个场景里的老问题。只不过前几年这东西不太会说话,可以装作看不见;等它真的开始替我说话了,每一个都躲不过去。
这五年我想做一个数据分析工具,做出了三个倒计时;想做一个排行榜,做出来了,然后连着协议一起丢了;想做一个正经平台,做出了一栋空房子;想做一个能聊天的 Agent,做出来了,能跑,也没出过事,但它是个毛坯。
听起来像一串失败,不过每一次都留下了点东西。两次协议死亡教会我"脚底下那块地不是我的",于是第五版里发不出去的消息宁可丢也不重试;那栋空房子教会我"架子不等于东西",于是第五版从禁令开始写;那个两小时没人说话就跳出来的 if,变成了现在替它决定要不要开口的裁判。
这几年整个行业都在解决"怎么让模型把一件事做完",热闹得很。我花的时间都在另一头:怎么让一个有身份的东西,在一条不可控的消息流里无人值守地活着,而且它说出去的每句话都能解释、不重复、不悬空。
这头是没人写进发布会 PPT 的,因为做好了的效果是"什么都没发生"。没有重复发送,没有丢掉的消息,没有半夜爬起来点重试。
我想让一个东西替我留在那些群里。等哪天我不在了,它还能接着说话,而且说得像我。
吹完了,也得说点扫兴的。第五版还没跑满一年,所有关于"长期"的设计现在都只是设计。它依赖第三方微信协议服务,这是整条链上我最不可控的一环——前三版全是死在这一层上的,后两次还都连着号一起赔了进去,最贵的那次搭了大半年。这个风险我到现在也没解决,而且解决不了。unknown 现在只是老实记着,还没有对账机制,等哪天协议方能按请求 ID 查结果,我会加个适配器把它对成 sent 或 failed,但绝不靠猜。11.6 万行去做一个微信机器人是重型方案,这些不变量只有在长期、多账号、无人值守的前提下才回本;你要是只想让模型在群里接话,别学我,现成的项目两百行就够。
而且前四版我每次都觉得"这回总该做对了"。所以这版大概率也埋着一行我现在看不见的代码,过两年让我写下第六版。
回到偃师⌗
那个人偶让周穆王发怒的原因不是它会唱歌——会唱歌的机关木人不稀奇。是因为它抛了个媚眼,做了一件没人教它做、但完全符合它角色的事。
我这个东西离那还远。拆开看全是数据库、队列、状态机、快照和五十五条规矩,跟皮革木头胶漆没什么本质区别。
但它现在会因为跟某个人不熟而拒绝回答,会在群里冷场的时候自己判断要不要接一句,会记得半年前谁说过喜欢先看结论再看细节。这些都不是我一条条写死的,是它照着自己的身份算出来的。
那天在老朋友群里说它跟我"一毛一样"的人,并不知道里面是什么。周穆王也是拆开之后才不生气的。
穆王最后那句感叹我一直挺喜欢的。人之巧乃可与造化者同功乎。
差得远。但试试挺有意思的。
对了,2022 年 12 月那个下午,我在 open_gpt.go 里写下"懒得搞上下文联动,有想法的可以自己实现"的时候,是真没想到这是在给四年后的自己派活。
那个有想法的人最后还是我。