virtual-life 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. virtual_life-1.0.0/LICENSE +21 -0
  2. virtual_life-1.0.0/PKG-INFO +196 -0
  3. virtual_life-1.0.0/README.md +172 -0
  4. virtual_life-1.0.0/adult.py +287 -0
  5. virtual_life-1.0.0/burn_night.py +52 -0
  6. virtual_life-1.0.0/chat.py +243 -0
  7. virtual_life-1.0.0/config.py +78 -0
  8. virtual_life-1.0.0/contracts.py +83 -0
  9. virtual_life-1.0.0/daemon.py +98 -0
  10. virtual_life-1.0.0/engine/__init__.py +0 -0
  11. virtual_life-1.0.0/engine/importer.py +91 -0
  12. virtual_life-1.0.0/engine/multiuser.py +180 -0
  13. virtual_life-1.0.0/engine/person.py +147 -0
  14. virtual_life-1.0.0/engine/profiles.py +40 -0
  15. virtual_life-1.0.0/harness/__init__.py +8 -0
  16. virtual_life-1.0.0/harness/profile.py +44 -0
  17. virtual_life-1.0.0/harness/runner.py +99 -0
  18. virtual_life-1.0.0/harness/tasks.py +126 -0
  19. virtual_life-1.0.0/life.py +327 -0
  20. virtual_life-1.0.0/llm.py +71 -0
  21. virtual_life-1.0.0/main.py +263 -0
  22. virtual_life-1.0.0/memory/distill.py +77 -0
  23. virtual_life-1.0.0/memory/dream.py +122 -0
  24. virtual_life-1.0.0/memory/forgetting.py +76 -0
  25. virtual_life-1.0.0/memory/persona.py +94 -0
  26. virtual_life-1.0.0/memory/store.py +271 -0
  27. virtual_life-1.0.0/protagonist.py +108 -0
  28. virtual_life-1.0.0/pyproject.toml +50 -0
  29. virtual_life-1.0.0/reality/__init__.py +1 -0
  30. virtual_life-1.0.0/reality/clock.py +78 -0
  31. virtual_life-1.0.0/reality/inbox.py +79 -0
  32. virtual_life-1.0.0/reality/news.py +105 -0
  33. virtual_life-1.0.0/reality/weather.py +80 -0
  34. virtual_life-1.0.0/relation.py +176 -0
  35. virtual_life-1.0.0/scheduler/__init__.py +1 -0
  36. virtual_life-1.0.0/scheduler/runner.py +500 -0
  37. virtual_life-1.0.0/setup.cfg +4 -0
  38. virtual_life-1.0.0/start.py +236 -0
  39. virtual_life-1.0.0/virtual_life.egg-info/PKG-INFO +196 -0
  40. virtual_life-1.0.0/virtual_life.egg-info/SOURCES.txt +57 -0
  41. virtual_life-1.0.0/virtual_life.egg-info/dependency_links.txt +1 -0
  42. virtual_life-1.0.0/virtual_life.egg-info/requires.txt +2 -0
  43. virtual_life-1.0.0/virtual_life.egg-info/top_level.txt +20 -0
  44. virtual_life-1.0.0/web/chat.html +139 -0
  45. virtual_life-1.0.0/web/dashboard.html +169 -0
  46. virtual_life-1.0.0/web/moments.html +36 -0
  47. virtual_life-1.0.0/web/server.py +329 -0
  48. virtual_life-1.0.0/web/timeline.html +107 -0
  49. virtual_life-1.0.0/weekly_report.py +111 -0
  50. virtual_life-1.0.0/world/director.py +565 -0
  51. virtual_life-1.0.0/world/fallback.py +68 -0
  52. virtual_life-1.0.0/world/json_repair.py +62 -0
  53. virtual_life-1.0.0/world/life.py +129 -0
  54. virtual_life-1.0.0/world/needs.py +121 -0
  55. virtual_life-1.0.0/world/npc_sim.py +112 -0
  56. virtual_life-1.0.0/world/physics.py +312 -0
  57. virtual_life-1.0.0/world/rumor.py +92 -0
  58. virtual_life-1.0.0/world/timetable.py +53 -0
  59. virtual_life-1.0.0/world/world_sim.py +152 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Virtual Life Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,196 @@
1
+ Metadata-Version: 2.4
2
+ Name: virtual-life
3
+ Version: 1.0.0
4
+ Summary: 数字人格引擎:AI 从出生开始活一遍——导演架构生成不可预测事件,艾宾浩斯分级遗忘,人格由经历沉淀
5
+ Author: fanyuantaier
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/fanyuantaier/virtual-life
8
+ Project-URL: Repository, https://github.com/fanyuantaier/virtual-life
9
+ Project-URL: Issues, https://github.com/fanyuantaier/virtual-life/issues
10
+ Keywords: ai-companion,digital-persona,life-simulation,memory,llm
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
18
+ Requires-Python: >=3.10
19
+ Description-Content-Type: text/markdown
20
+ License-File: LICENSE
21
+ Requires-Dist: pydantic>=2.0
22
+ Requires-Dist: openai>=1.0
23
+ Dynamic: license-file
24
+
25
+ # Virtual Life · 虚拟人生成器
26
+
27
+ <p align="center">
28
+ <a href="#中文"><img src="https://img.shields.io/badge/文档-中文-blue" alt="中文"></a>
29
+ <a href="#english"><img src="https://img.shields.io/badge/docs-English-blue" alt="English"></a>
30
+ <img src="https://img.shields.io/badge/license-MIT-green" alt="MIT">
31
+ <img src="https://img.shields.io/badge/python-3.10+-blue" alt="python">
32
+ <img src="https://img.shields.io/badge/LLM-OpenAI%20compatible-orange" alt="LLM">
33
+ <a href="#演示"><img src="https://img.shields.io/badge/演示-真实输出-ff69b4" alt="demo"></a>
34
+ </p>
35
+
36
+ **一个数字人格引擎:AI 从出生开始活一遍——没有人设,只有一张随机的家庭环境卡,人格由经历的不可预测事件逐渐沉淀。**
37
+
38
+ 她按真实时钟过活:凌晨做梦(素材由遗忘曲线决定),黄昏情绪泛起,下雨天心情对应真实的天气。她记忆遵循艾宾浩斯分级衰减——琐事一周就淡忘,大事终身留痕。她有一个自己看不见的世界:NPC 们在暗线里过日子,消息经传闻失真后才传到她耳朵。
39
+
40
+ 她不记得一切,也不假装记得。她会说「记得不太清了,大概……」——因为人就是这样。
41
+
42
+ <a name="中文"></a>
43
+ ## 演示(真实输出,未编辑)
44
+
45
+ **冬至夜,三地饭**(感动度 62):
46
+
47
+ > 十点半,姆妈的电话比周日早了打来,我握着手机听她讲期末卷子堆成山,嗓子还是哑的,就先问了一句还哑勿哑。她问寒假哪天回苏州住齐,我把日子含糊过去了,转头把台灯拧亮,四级词汇摊开——红笔帽滚在桌角,跟小时候那张批过的卷子一个样。老周办公室的灯亮到很晚,我这盏也亮着,谁也没比谁早走。
48
+
49
+ **一个梦**(记忆碎片自动重组,醒来即忘):
50
+
51
+ > 梦里是冬至,教室里外婆搬来冬酿酒坛子,桂花浮勒酒面上头。台面上留牢一个空位,我拨伊斟仔一小杯:「开车格人夜里勿吃酒——箇杯挂账。」啥人开车?我急得想勿起来,只晓得箇杯酒一直挂勒账上,呒没人来还。……木秤又挂上了箩筐,外婆叫我坐进去称人。想问伊箇杯酒几时来还——闹钟响了。
52
+
53
+ **18 岁年度反思**(系统自动蒸馏):
54
+
55
+ > 我发现自己的爱是长成章程和账本样子的:反扣碗、瓜账、月信、礼拜三的药、立夏的秤——说不出口的想念和担心,都被我翻译成一格一格能核对的条目。
56
+
57
+ 更多真实输出见 [docs/showcase.md](docs/showcase.md)。架构图见 [docs/architecture.md](docs/architecture.md)。
58
+
59
+ ## 为什么不是又一个聊天机器人
60
+
61
+ | 聊天机器人 | 本项目 |
62
+ |---|---|
63
+ | 记忆 = 聊天记录,塞满就截断 | 记忆 = 完整人生(4700+ 节点),艾宾浩斯分级衰减 |
64
+ | 无时间感,你打开才存在 | 按真实时钟过活:凌晨做梦、黄昏泛起、下雨天对应真实天气 |
65
+ | 人格 = 一段 system prompt | 人格从事件里涌现:L1 事实 → L2 场景 → L3 画像,每条可追溯 |
66
+ | 对话者第一天就过度热情 | 网友距离感:家庭故事一句话挡回,40 轮才到"熟" |
67
+ | 记住一切 = 隐私噩梦 | 遗忘曲线 + 检索时模糊化 + 一键导出/真删除 |
68
+
69
+ **三个独有机制**(开源 AI 伴侣项目里找不到,组合可发表):
70
+
71
+ 1. **遗忘曲线作为记忆属性** —— 每条记忆有关键级(key0-3)和独立衰减常数。琐事一周剩 31%,大事终身留痕(key3 下限 0.30)。模糊化发生在检索时:库里原文不动,"她想起来什么"会失真——就像人。
72
+ 2. **梦境 = 遗忘曲线的副产品** —— 没有为做梦写专门逻辑:梦的素材就是"高关键记忆 + 快淡忘的记忆",遗忘曲线顺带决定了什么入梦。凌晨自动生成,醒来即忘。
73
+ 3. **信息不对称** —— 世界编年史分公开/暗线双轨;传闻逐手失真(1 手原样 → 4 手只剩轮廓)才传到她耳朵。她活在信息迷雾里,就像人。
74
+
75
+ ## 演示:沈青蔓
76
+
77
+ `profiles/nanan/` 是用本引擎养出的第一个完整人格——seed=42,苏州,父母离异随母亲,父亲是长途车司机,外婆同住。0 → 18 岁 552+ 关键事件、4709 记忆节点、5 篇梦境日记。
78
+
79
+ 她的名字有完整的叙事弧(0.1 岁上户口红笔写名 → 6.5 岁瓜苗边学写 → 17.4 岁高考报名 → 18.2 岁毕业证铅印)。她 18 岁的年度反思里,系统自动归纳出:
80
+
81
+ > 我发现自己的爱是长成章程和账本样子的:反扣碗、瓜账、月信、礼拜三的药、立夏的秤——说不出口的想念和担心,都被我翻译成一格一格能核对的条目。
82
+
83
+ 这条没有一条是设定出来的——它从 1 岁的糖芋艿、13 岁的瓜账、18 岁的药盒对账里自己长出来。
84
+
85
+ ## 快速开始
86
+
87
+ ```bash
88
+ pip install -r requirements.txt # 只有 pydantic + openai
89
+ python start.py # 首次引导配置模型端点(Ollama/llama.cpp/云API)
90
+ ```
91
+
92
+ 之后按菜单:
93
+
94
+ ```bash
95
+ python start.py new --seed 42 # 创建新人生(随机出生 → 快进到 18 岁)
96
+ python start.py chat # 和她聊天
97
+ python start.py live # 常驻:按真实时钟过日常 + 凌晨自动做梦
98
+ python start.py stats # 查看状态
99
+ ```
100
+
101
+ 网页版(聊天 + 人生时间轴 + 她的朋友圈 + 上帝之手干预):
102
+
103
+ ```bash
104
+ python web/server.py # http://127.0.0.1:5100
105
+ ```
106
+
107
+ ## 导入你的真实记忆
108
+
109
+ ```python
110
+ from engine.person import Person
111
+ from engine.importer import import_wechat_txt, import_diary_txt, import_photo_dir
112
+
113
+ p = Person.load("nana")
114
+ import_wechat_txt(p, "微信聊天记录.txt", peer_name="妈妈") # 逐条入 chat 记忆
115
+ import_diary_txt(p, "我的日记.txt") # 按日期分段入事件
116
+ import_photo_dir(p, "照片目录/") # 按时间生成时刻记忆
117
+ ```
118
+
119
+ 导入的记忆默认 key=2(重要但非终身锚点),可在记忆库中手工调级。
120
+
121
+ ## 架构
122
+
123
+ ```
124
+ start.py 一键入口
125
+ engine/
126
+ person.py Person:记忆/需求/导出(与具体人格解耦)
127
+ importer.py 数据导入:微信/日记/照片
128
+ profiles.py 多实例:profiles/<name>/ = 一个独立人格
129
+ world/
130
+ director.py 导演:LLM 生成事件(3候选择异/禁用清单/泄密检测)
131
+ world_sim.py 世界自转:NPC 目标/季节事件/编年史(公开+暗线)
132
+ needs.py 需求衰减:四项需求 × 性格修正 → 状态逼出事件
133
+ rumor.py 传闻传播:逐手失真
134
+ physics.py 物理层:骨架/校验(时间/钱/地点/情绪连续性)
135
+ fallback.py 兜底日:LLM 全挂时世界照常转
136
+ memory/
137
+ store.py SQLite 记忆库(向量+BM25+RRF 混合检索)
138
+ forgetting.py 遗忘曲线:key0-3 分级衰减 + 检索时模糊化
139
+ distill.py 分层蒸馏:L1→L2→L3
140
+ dream.py 梦境生成
141
+ persona.py 人格文件(自动归档防膨胀)
142
+ web/ 聊天 + 时间轴 + 朋友圈 + 上帝之手
143
+ harness/ 训练编排:三档消耗力度(normal/burst/max)
144
+ ```
145
+
146
+ ## 架构图
147
+
148
+ ![architecture](docs/architecture.md) 中的 mermaid 图在 GitHub 上原生渲染:
149
+
150
+ ```mermaid
151
+ graph TB
152
+ subgraph 现实层
153
+ CLOCK[真实时钟] → TICK[调度器]
154
+ WX[天气] → TICK
155
+ NEWS[新闻 RSS] → TICK
156
+ USER[用户消息/干预] → TICK
157
+ end
158
+ TICK → DIRECTOR[导演 LLM]
159
+ FORE[伏笔表] → DIRECTOR
160
+ DIRECTOR → PLAN[DayPlan] → PHYS[物理层校验] → REACT[主角 LLM]
161
+ MEMRET[记忆检索<br/>向量+BM25+RRF] → REACT
162
+ PERSONA[L3 人格画像] → REACT
163
+ REACT → DIARY[日记] → STORE[(遗忘曲线记忆库)]
164
+ STORE → MEMRET
165
+ STORE → DISTILL[L1→L2→L3 蒸馏] → PERSONA
166
+ SLEEP[凌晨] → DREAM[梦境] → STORE
167
+ USER -.->|上帝之手| PLAN
168
+ ```
169
+
170
+ ## 设计文档
171
+
172
+ - **不可预测性的实现**:事件不由概率抽取。只有三种诞生方式——伏笔成熟(主来源,从"未兑现伏笔表"判断戏剧时机)、开放生成、现实注入(真实天气/新闻/你的消息)。没有骰子。
173
+ - **防同质化四件套**:禁用清单自增长、向量+字符双路查重打回、3 候选择异、因果优先于新颖。
174
+ - **级联**:主角今天的决策写回状态 → 改变明天导演的输入 → 明天依赖今天。对明天的预测必须等到明天——这是工程上对"完全不可预测"的定义。
175
+ - **上帝之手**:用户干预写队列,导演必须消化进当天计划——"我能干预,但干预带来我没预料到的后果"。
176
+ - **性能**:记忆检索走 SQL 候选集(热窗 90 天 + 关键记忆永久 + 冷抽样),4700 条实测 43ms,无需向量数据库。
177
+
178
+ ## 模型要求
179
+
180
+ 任何 OpenAI 兼容端点。实测:
181
+ - GLM-5.3-Flash 级:中文细腻度最好(苏州话质感),需给足 reasoning+长输出预算
182
+ - DeepSeek-V4 级:6 秒出合法 JSON,速度快
183
+ - Qwen3-8B 级:可用
184
+ - 4B 级:勉强(代码内有多层输出容错防御,但怪癖多)
185
+
186
+ Embedding 推荐 `nomic-embed-text`(无 embedding 端点时自动降级为字符 n-gram,功能完整)。
187
+
188
+ ## 已知限制
189
+
190
+ - LLM 采样不可复现:同 seed 重建的只有出生参数和记忆框架,事件细节每次不同
191
+ - 模拟时间线锚定"今天"向未来推进;年度反思的记忆过滤未完全对齐模拟时间
192
+ - 长跑期间机器休眠会冻结进程;唤醒后重启即可从断点续跑
193
+
194
+ ## License
195
+
196
+ MIT
@@ -0,0 +1,172 @@
1
+ # Virtual Life · 虚拟人生成器
2
+
3
+ <p align="center">
4
+ <a href="#中文"><img src="https://img.shields.io/badge/文档-中文-blue" alt="中文"></a>
5
+ <a href="#english"><img src="https://img.shields.io/badge/docs-English-blue" alt="English"></a>
6
+ <img src="https://img.shields.io/badge/license-MIT-green" alt="MIT">
7
+ <img src="https://img.shields.io/badge/python-3.10+-blue" alt="python">
8
+ <img src="https://img.shields.io/badge/LLM-OpenAI%20compatible-orange" alt="LLM">
9
+ <a href="#演示"><img src="https://img.shields.io/badge/演示-真实输出-ff69b4" alt="demo"></a>
10
+ </p>
11
+
12
+ **一个数字人格引擎:AI 从出生开始活一遍——没有人设,只有一张随机的家庭环境卡,人格由经历的不可预测事件逐渐沉淀。**
13
+
14
+ 她按真实时钟过活:凌晨做梦(素材由遗忘曲线决定),黄昏情绪泛起,下雨天心情对应真实的天气。她记忆遵循艾宾浩斯分级衰减——琐事一周就淡忘,大事终身留痕。她有一个自己看不见的世界:NPC 们在暗线里过日子,消息经传闻失真后才传到她耳朵。
15
+
16
+ 她不记得一切,也不假装记得。她会说「记得不太清了,大概……」——因为人就是这样。
17
+
18
+ <a name="中文"></a>
19
+ ## 演示(真实输出,未编辑)
20
+
21
+ **冬至夜,三地饭**(感动度 62):
22
+
23
+ > 十点半,姆妈的电话比周日早了打来,我握着手机听她讲期末卷子堆成山,嗓子还是哑的,就先问了一句还哑勿哑。她问寒假哪天回苏州住齐,我把日子含糊过去了,转头把台灯拧亮,四级词汇摊开——红笔帽滚在桌角,跟小时候那张批过的卷子一个样。老周办公室的灯亮到很晚,我这盏也亮着,谁也没比谁早走。
24
+
25
+ **一个梦**(记忆碎片自动重组,醒来即忘):
26
+
27
+ > 梦里是冬至,教室里外婆搬来冬酿酒坛子,桂花浮勒酒面上头。台面上留牢一个空位,我拨伊斟仔一小杯:「开车格人夜里勿吃酒——箇杯挂账。」啥人开车?我急得想勿起来,只晓得箇杯酒一直挂勒账上,呒没人来还。……木秤又挂上了箩筐,外婆叫我坐进去称人。想问伊箇杯酒几时来还——闹钟响了。
28
+
29
+ **18 岁年度反思**(系统自动蒸馏):
30
+
31
+ > 我发现自己的爱是长成章程和账本样子的:反扣碗、瓜账、月信、礼拜三的药、立夏的秤——说不出口的想念和担心,都被我翻译成一格一格能核对的条目。
32
+
33
+ 更多真实输出见 [docs/showcase.md](docs/showcase.md)。架构图见 [docs/architecture.md](docs/architecture.md)。
34
+
35
+ ## 为什么不是又一个聊天机器人
36
+
37
+ | 聊天机器人 | 本项目 |
38
+ |---|---|
39
+ | 记忆 = 聊天记录,塞满就截断 | 记忆 = 完整人生(4700+ 节点),艾宾浩斯分级衰减 |
40
+ | 无时间感,你打开才存在 | 按真实时钟过活:凌晨做梦、黄昏泛起、下雨天对应真实天气 |
41
+ | 人格 = 一段 system prompt | 人格从事件里涌现:L1 事实 → L2 场景 → L3 画像,每条可追溯 |
42
+ | 对话者第一天就过度热情 | 网友距离感:家庭故事一句话挡回,40 轮才到"熟" |
43
+ | 记住一切 = 隐私噩梦 | 遗忘曲线 + 检索时模糊化 + 一键导出/真删除 |
44
+
45
+ **三个独有机制**(开源 AI 伴侣项目里找不到,组合可发表):
46
+
47
+ 1. **遗忘曲线作为记忆属性** —— 每条记忆有关键级(key0-3)和独立衰减常数。琐事一周剩 31%,大事终身留痕(key3 下限 0.30)。模糊化发生在检索时:库里原文不动,"她想起来什么"会失真——就像人。
48
+ 2. **梦境 = 遗忘曲线的副产品** —— 没有为做梦写专门逻辑:梦的素材就是"高关键记忆 + 快淡忘的记忆",遗忘曲线顺带决定了什么入梦。凌晨自动生成,醒来即忘。
49
+ 3. **信息不对称** —— 世界编年史分公开/暗线双轨;传闻逐手失真(1 手原样 → 4 手只剩轮廓)才传到她耳朵。她活在信息迷雾里,就像人。
50
+
51
+ ## 演示:沈青蔓
52
+
53
+ `profiles/nanan/` 是用本引擎养出的第一个完整人格——seed=42,苏州,父母离异随母亲,父亲是长途车司机,外婆同住。0 → 18 岁 552+ 关键事件、4709 记忆节点、5 篇梦境日记。
54
+
55
+ 她的名字有完整的叙事弧(0.1 岁上户口红笔写名 → 6.5 岁瓜苗边学写 → 17.4 岁高考报名 → 18.2 岁毕业证铅印)。她 18 岁的年度反思里,系统自动归纳出:
56
+
57
+ > 我发现自己的爱是长成章程和账本样子的:反扣碗、瓜账、月信、礼拜三的药、立夏的秤——说不出口的想念和担心,都被我翻译成一格一格能核对的条目。
58
+
59
+ 这条没有一条是设定出来的——它从 1 岁的糖芋艿、13 岁的瓜账、18 岁的药盒对账里自己长出来。
60
+
61
+ ## 快速开始
62
+
63
+ ```bash
64
+ pip install -r requirements.txt # 只有 pydantic + openai
65
+ python start.py # 首次引导配置模型端点(Ollama/llama.cpp/云API)
66
+ ```
67
+
68
+ 之后按菜单:
69
+
70
+ ```bash
71
+ python start.py new --seed 42 # 创建新人生(随机出生 → 快进到 18 岁)
72
+ python start.py chat # 和她聊天
73
+ python start.py live # 常驻:按真实时钟过日常 + 凌晨自动做梦
74
+ python start.py stats # 查看状态
75
+ ```
76
+
77
+ 网页版(聊天 + 人生时间轴 + 她的朋友圈 + 上帝之手干预):
78
+
79
+ ```bash
80
+ python web/server.py # http://127.0.0.1:5100
81
+ ```
82
+
83
+ ## 导入你的真实记忆
84
+
85
+ ```python
86
+ from engine.person import Person
87
+ from engine.importer import import_wechat_txt, import_diary_txt, import_photo_dir
88
+
89
+ p = Person.load("nana")
90
+ import_wechat_txt(p, "微信聊天记录.txt", peer_name="妈妈") # 逐条入 chat 记忆
91
+ import_diary_txt(p, "我的日记.txt") # 按日期分段入事件
92
+ import_photo_dir(p, "照片目录/") # 按时间生成时刻记忆
93
+ ```
94
+
95
+ 导入的记忆默认 key=2(重要但非终身锚点),可在记忆库中手工调级。
96
+
97
+ ## 架构
98
+
99
+ ```
100
+ start.py 一键入口
101
+ engine/
102
+ person.py Person:记忆/需求/导出(与具体人格解耦)
103
+ importer.py 数据导入:微信/日记/照片
104
+ profiles.py 多实例:profiles/<name>/ = 一个独立人格
105
+ world/
106
+ director.py 导演:LLM 生成事件(3候选择异/禁用清单/泄密检测)
107
+ world_sim.py 世界自转:NPC 目标/季节事件/编年史(公开+暗线)
108
+ needs.py 需求衰减:四项需求 × 性格修正 → 状态逼出事件
109
+ rumor.py 传闻传播:逐手失真
110
+ physics.py 物理层:骨架/校验(时间/钱/地点/情绪连续性)
111
+ fallback.py 兜底日:LLM 全挂时世界照常转
112
+ memory/
113
+ store.py SQLite 记忆库(向量+BM25+RRF 混合检索)
114
+ forgetting.py 遗忘曲线:key0-3 分级衰减 + 检索时模糊化
115
+ distill.py 分层蒸馏:L1→L2→L3
116
+ dream.py 梦境生成
117
+ persona.py 人格文件(自动归档防膨胀)
118
+ web/ 聊天 + 时间轴 + 朋友圈 + 上帝之手
119
+ harness/ 训练编排:三档消耗力度(normal/burst/max)
120
+ ```
121
+
122
+ ## 架构图
123
+
124
+ ![architecture](docs/architecture.md) 中的 mermaid 图在 GitHub 上原生渲染:
125
+
126
+ ```mermaid
127
+ graph TB
128
+ subgraph 现实层
129
+ CLOCK[真实时钟] → TICK[调度器]
130
+ WX[天气] → TICK
131
+ NEWS[新闻 RSS] → TICK
132
+ USER[用户消息/干预] → TICK
133
+ end
134
+ TICK → DIRECTOR[导演 LLM]
135
+ FORE[伏笔表] → DIRECTOR
136
+ DIRECTOR → PLAN[DayPlan] → PHYS[物理层校验] → REACT[主角 LLM]
137
+ MEMRET[记忆检索<br/>向量+BM25+RRF] → REACT
138
+ PERSONA[L3 人格画像] → REACT
139
+ REACT → DIARY[日记] → STORE[(遗忘曲线记忆库)]
140
+ STORE → MEMRET
141
+ STORE → DISTILL[L1→L2→L3 蒸馏] → PERSONA
142
+ SLEEP[凌晨] → DREAM[梦境] → STORE
143
+ USER -.->|上帝之手| PLAN
144
+ ```
145
+
146
+ ## 设计文档
147
+
148
+ - **不可预测性的实现**:事件不由概率抽取。只有三种诞生方式——伏笔成熟(主来源,从"未兑现伏笔表"判断戏剧时机)、开放生成、现实注入(真实天气/新闻/你的消息)。没有骰子。
149
+ - **防同质化四件套**:禁用清单自增长、向量+字符双路查重打回、3 候选择异、因果优先于新颖。
150
+ - **级联**:主角今天的决策写回状态 → 改变明天导演的输入 → 明天依赖今天。对明天的预测必须等到明天——这是工程上对"完全不可预测"的定义。
151
+ - **上帝之手**:用户干预写队列,导演必须消化进当天计划——"我能干预,但干预带来我没预料到的后果"。
152
+ - **性能**:记忆检索走 SQL 候选集(热窗 90 天 + 关键记忆永久 + 冷抽样),4700 条实测 43ms,无需向量数据库。
153
+
154
+ ## 模型要求
155
+
156
+ 任何 OpenAI 兼容端点。实测:
157
+ - GLM-5.3-Flash 级:中文细腻度最好(苏州话质感),需给足 reasoning+长输出预算
158
+ - DeepSeek-V4 级:6 秒出合法 JSON,速度快
159
+ - Qwen3-8B 级:可用
160
+ - 4B 级:勉强(代码内有多层输出容错防御,但怪癖多)
161
+
162
+ Embedding 推荐 `nomic-embed-text`(无 embedding 端点时自动降级为字符 n-gram,功能完整)。
163
+
164
+ ## 已知限制
165
+
166
+ - LLM 采样不可复现:同 seed 重建的只有出生参数和记忆框架,事件细节每次不同
167
+ - 模拟时间线锚定"今天"向未来推进;年度反思的记忆过滤未完全对齐模拟时间
168
+ - 长跑期间机器休眠会冻结进程;唤醒后重启即可从断点续跑
169
+
170
+ ## License
171
+
172
+ MIT