项目起源
大一暑假,我有一个不成熟的想法:如果让几个带着不同出身、不同创伤的AI角色,在没有人工干预的情况下连续辩论几十场------它们会变成什么样?
最初只是好奇。后来变成了一个完整的Multi-Agent系统工程。
技术栈:Node.js + DeepSeek API + 千问/GLM API,JSON文件存储,不需要数据库。
代码量 :12,000+行。辩论数据 :140+场,其中84场深度连续追踪。总成本:约¥2。
一、第一版:手工脚本(6月21日)
最早的想法很简单------写几个prompt,调API,让AI角色互相发言。
javascript
// 最原始的版本
const speech = await callLLM(personaPrompt, debateTopic);
history += speech;
nextPersona.rebut(history);
跑了10场辩论,发现了核心问题:AI角色在第一场就会崩。 性格忽冷忽热,信念前后矛盾,说完就忘。
一个角色上一轮说"我只信自己",下一轮开始温和地点头说"你说得也有道理"。
于是开始搭质量控制系统。
二、人格工厂 + 关键词池(7月16日上午)
第一件事,从"手工写人格"变成"系统生成人格"。
建了9个维度的关键词池(社会出身/教育/职业/大五人格/核心信念/关键经历/话语风格/软肋/约束规则),共91个可选项。
但随机拼接产生大量不可能的组合。"小学学历+体制内公务员""初中辍学+高考逆袭"------在真实社会里不存在。
于是加了约束引擎:13条互斥规则,在参数生成时实时拦截并自动修正。
json
{
"id": "c01",
"条件": {"教育.学历": ["小学及以下", "初中辍学"]},
"禁止": {"经历.教育转折": ["高考逆袭"]}
}
约束规则从20人格批次的审核官观察中自动提炼。跑到200+条观察时,常见的互斥组合基本全覆盖了。
三、缝合者:从标签到因果链(7月16日晚上)
约束引擎解决了"不可能"的问题,但没解决"不合理"的问题。
同一批标签:"农村出身+父亲工伤+初中辍学+外卖骑手+坚信努力能改变命运"------这些都是合理标签,但它们之间有什么关系?没有因果。
缝合者就是干这个的。收到标签后,做三件事:
- 消解逻辑矛盾(如"高考失利"和"初中毕业"不能共存)
- 建立因果链(父亲工伤→辍学养家→被生活磨出低宜人性→但不信命→送外卖)
- 输出叙事大纲,交给LLM展开成完整自述
json
"causal_chain": [
{"事件": "父亲在矿上砸断腿", "结果": "中考前被迫辍学养家", "影响的标签": ["教育.学历", "性格.尽责性"]},
{"事件": "被生活反复拒绝", "结果": "不再相信别人会帮忙", "影响的标签": ["性格.宜人性", "信念.努力"]},
]
但缝合者的第一批就有问题。 它编出了"家庭破产→初中辍学"这种伪逻辑。在中国,九年义务教育免费 + 贫困生有补助------辍学主因是厌学(60%+)和"读书无用论",不是贫困。
于是建了社会事实库------基于国家统计局、教育部公开数据,校准缝合者的输出:
- 辍学主因:厌学60%+,不是贫困
- 公务员最低学历:大专
- 外卖骑手月均:8325元(全国均值,净收5200-7200)
- 基层体制内月到手:3500-5500元
- 城乡收入比:2.31
注入后,缝合者不再编出"家庭破产辍学"这种伪逻辑。
四、审核官:三层包围式质检
缝合者产出人格后,审核官从三层包围检查:
第一层(L1):参数硬冲突检测。13条规则 + LLM深度扫描,找出规则引擎漏网的问题。
第二层(L2):信念-行为一致性检查。"Role 2 综合征"------参数写"低尽责、随性拖延",自述里却在讲自己怎么坚持高强度工作。这种言行不一,审核官的LLM扫描来抓。
第三层(L3):稳定性检测。同一个人格,话题换三种问法,核心立场会不会漂移?
发现的问题:DeepSeek评分太仁慈(所有评分都是8.3-8.7),换成千问后拉开了(7.7-8.3范围)。但辩论生成最好的还是DeepSeek------因为它最会"演",有人味。
五、因子设计 + 广度模式
人格不能靠随机抽样------100个随机人可能70个都是"大专+努力有天花板"的变体。
用因子设计覆盖全局:4维×3级 = 81格
- 城乡层级:一线城市 / 县城地级市 / 农村
- 学历层级:初中及以下 / 大专本科 / 985海归
- 信念光谱:努力能改变 / 有天花板 / 努力没用
- 职业类型:稳定型 / 不稳定型 / 自主型
每个格子生成1个人格,81人格覆盖所有组合。这是广度模式------追求的是"全局分布",而不是单个人格的精致度。
六、记忆官 + 深度追踪
广度模式产出了大量数据之后,选最优质的人格进深度追踪。
选了三个人:陈大勇(外卖骑手,坚信努力能改变命运)、赵一鸣(985金融精英,坚信努力有天花板)、林默(自由职业者,认为努力没用)。
每个人带上之前辩论的记忆,连续辩论28场左右。总共84场深度数据。
记忆官的工作方式不是存原始文本------是提取结构化记忆:
json
{
"debate_5": {
"topic": "穷人家的孩子还有翻身的机会吗",
"my_position": "有机会但要拼命",
"stance_shift": 0.2,
"who_challenged_me": ["赵一鸣"],
"grudge": "他说我'把命卖给平台'------他不懂"
}
}
下一场辩论时,这些记忆会注入到角色的prompt里。陈大勇在第5场拍桌骂赵一鸣的那句"你他妈懂什么叫不跑明天就吃不上饭"------就是在第四场被赵一鸣刺激后积累出来的。
七、架构总结:人格四御史
| 角色 | 职责 | 位置 |
|---|---|---|
| 缝合者 | 标签→因果链→叙事大纲,消解矛盾 | 生成前 |
| 约束引擎 | 13条硬规则拦住不可能组合 | 生成时 |
| 审核官 | 三层包围质检,200+条经验 | 全流程 |
| 记忆官 | 结构化立场记忆,跨场次演化追踪 | 辩论后→辩论前 |
一条命令跑通全流程:
bash
node persona-factory/pipeline.js --count=81 --debates=5 --factorial
八、数据发现
84场深度追踪的核心发现:人格信念的漂移幅度,跟这个人的"人生自述"里有没有内在裂缝正相关。
陈大勇几乎不漂(总漂移2.3/30场)。他的自述是个闭环------每段经历都在验证同一个结论("伸手没人接→只能靠自己")。辩论撼不动他。
赵一鸣漂移最大(总漂移5.9/30场)。他坚信"我只信自己",但从福利院考上985的过程中一定有人帮过他。他自己不承认这个裂缝,但对手每次都能戳进去。
林默缓慢松开(总漂移3.2/30场)。他知道世界不公平,但奶奶爱过他------那道裂缝是他的信念中最脆弱也最柔软的地方。
另一个意外发现:二十几场之后,三个人的对话主题自己变了------从"努力能不能改变命运"变成了"什么样的人生值得过"。没有任何prompt引导,是84场辩论的记忆累积让对话自己往深处走的。
九、这个项目的局限
- 只用DeepSeek做辩论生成。千问太理性(像写议论文),GLM不稳定(有时过头),DeepSeek最会"演"------但可能只对情绪外放型人格有效。
- 角色不会主动发起话题。永远是等topic、等对手、等被点名。
- 没有量化统计检验。漂移量是主观打分(0-1),不是统计显著。
- 记忆官只追踪立场,不追踪"关系"------陈大勇对赵一鸣有9条怨恨,但这些怨恨的性质(嫉妒?不服?其实想成为他?)没被分析。
十、项目地址
Gitee :gitee.com/yangan528/m...
包含全部源码、辩论数据、人格档案、部署文档。
电子科技大学 电子信息工程 大一暑假项目 | 2026年7月