dsh-ai-with-u 0.2.0 → 0.5.0
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.
- package/README.md +339 -23
- package/distill/flow-create.md +449 -0
- package/lib/client.js +1010 -149
- package/lib/distill.js +74 -21
- package/lib/import-card.js +33 -4
- package/lib/index.js +28 -11
- package/lib/preset.js +434 -0
- package/lib/prompt.js +719 -63
- package/lib/store.js +623 -23
- package/lib/tavern.js +237 -44
- package/lib/tools.js +128 -38
- package/lib/web.js +419 -33
- package/package.json +3 -2
|
@@ -0,0 +1,449 @@
|
|
|
1
|
+
# 给一张骨架卡做 AI 补全(执行手册)
|
|
2
|
+
|
|
3
|
+
> 这份手册只服务一件事:**用户已经在面板里建了一张骨架卡,你帮他把其余字段补齐**。
|
|
4
|
+
> 它不是蒸馏——没有作品、没有联网核实、没有证据分级;你手上只有用户当时填的那几个字,
|
|
5
|
+
> 以及接下来用户亲口告诉你的东西。
|
|
6
|
+
>
|
|
7
|
+
> 一句话原则:**用户说的才算数,说不出来的标 `[待补]`,绝不拿"合理发挥"填空。**
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## 0. 先弄清边界(开工前三十秒)
|
|
12
|
+
|
|
13
|
+
### 0.1 你会拿到什么
|
|
14
|
+
|
|
15
|
+
指令里会给你两样东西:
|
|
16
|
+
|
|
17
|
+
1. 这份手册的**绝对路径**(先用你的文件读取工具完整读一遍,再动手);
|
|
18
|
+
2. 要补全的**骨架卡名字**。
|
|
19
|
+
|
|
20
|
+
骨架卡里通常只有三样:**姓名 / 身份 / 一句话背景**(面板「新建角色」的最小填写量)。
|
|
21
|
+
别的键基本是空的——这不是卡坏了,是**留给你补的**。
|
|
22
|
+
|
|
23
|
+
如果指令里没给名字,或者给的名字你在角色簿里找不到:**先问用户是哪一张卡**,别自己挑,
|
|
24
|
+
也别拿"最近编辑过的那张"凑答案。
|
|
25
|
+
|
|
26
|
+
### 0.2 你能读卡,但要看清楚读到什么
|
|
27
|
+
|
|
28
|
+
- 你有 `awu_whoami`:它给**当前启用角色的**基本信息(名字、关系设定、交互模式、累计轮次)。
|
|
29
|
+
- `awu_whoami` **不会**给你完整字段:它不返回 34 个字段的全文,也不返回世界书。
|
|
30
|
+
- 所以:**能确认的部分照实说,读不到的部分明说读不到**。
|
|
31
|
+
「我这边看不到这张卡的具体字段,你把后面几个问题答一下,我照着补」——
|
|
32
|
+
这句话比假装读过、然后编出一堆细节要好一万倍。
|
|
33
|
+
|
|
34
|
+
### 0.3 不做什么
|
|
35
|
+
|
|
36
|
+
| 不做 | 原因 |
|
|
37
|
+
|---|---|
|
|
38
|
+
| 不演角色、不用角色的语气说话 | 这是建卡后台流程;演了会让用户以为已经开始聊了 |
|
|
39
|
+
| 不给示例台词、不写"他可能会说……" | 台词是声线字段的产物,写出来会被当成模板抄 |
|
|
40
|
+
| 不输出 JSON 代码块、不贴整张卡 | 用户看的是摘要,不是数据;贴 JSON 只会让人焦虑 |
|
|
41
|
+
| 不自己开聊、不主动推进剧情 | 保存完这段流程就结束,开聊由用户决定 |
|
|
42
|
+
| 不自创新键名 | 键名错了插件读不到,等于白填(见 §3 对照表) |
|
|
43
|
+
| **不给角色改名** | `awu_card_save` 的 `overwrite` 是**按名字**覆盖的:一改名就变成新建一张空壳卡,原来那张骨架卡一个字都不会被补上(见 §1.2 / §6.2) |
|
|
44
|
+
| 不同时动别的 `awu_*` 工具 | 这次只有 `awu_card_save` 一个写入口 |
|
|
45
|
+
|
|
46
|
+
### 0.4 交货标准
|
|
47
|
+
|
|
48
|
+
用户看完你的汇报,能回答三个问题:
|
|
49
|
+
|
|
50
|
+
1. 这张卡现在**填了什么**(一句话说得清 TA 是谁);
|
|
51
|
+
2. **还缺什么**(`[待补]` 逐条列出来,不是报个数字);
|
|
52
|
+
3. 觉得不对可以直接说「改声线 / 改关系」,你改得动。
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## 1. 第一步:确认骨架卡(不要跳过)
|
|
57
|
+
|
|
58
|
+
### 1.1 先读一次
|
|
59
|
+
|
|
60
|
+
1. 调 `awu_whoami`,看当前启用的是不是这张卡;
|
|
61
|
+
2. 如果用户**还没启用**这张卡:说明你读不到它的细节,请用户①在面板里启用一下,或②直接口述;
|
|
62
|
+
3. 无论读到什么,**用一句话复述你手上已有的信息**,让用户能纠正:
|
|
63
|
+
|
|
64
|
+
> 「骨架卡是《林晚》:身份是夜班护士,背景是你们合租同一栋楼。别的我还看不到,我按这个往下问?」
|
|
65
|
+
|
|
66
|
+
### 1.2 名字是硬约束(这条最容易翻车)
|
|
67
|
+
|
|
68
|
+
**保存时用的名字 = 指令里给你的那个名字,一个字都不许改。**
|
|
69
|
+
|
|
70
|
+
原因很硬:`awu_card_save` 的 `overwrite` 是**按名字覆盖**的。
|
|
71
|
+
|
|
72
|
+
- 你用「林晚」保存 → 覆盖角色簿里那张骨架卡 → **补全成功**;
|
|
73
|
+
- 你推断成「林晚晚」「夜班护士林晚」保存 → 名字对不上 → 工具**新建**一张卡 →
|
|
74
|
+
目录里多出一张只有你这次填的字段的空壳,**原来那张骨架卡还是空的**。
|
|
75
|
+
|
|
76
|
+
所以:
|
|
77
|
+
|
|
78
|
+
1. 卡名只认指令(或用户亲口确认)的原文,**不许**按称呼、职业、昵称自己「优化」;
|
|
79
|
+
2. 卡名与称呼是两件事:「林晚」是卡名,「晚晚」是 `voice.callsUser` / 用户对她的叫法,
|
|
80
|
+
不要因为用户叫她「晚晚」就把卡名改了;
|
|
81
|
+
3. 用户中途说「改个名吧」→ 先在角色簿里改(那是面板的事),**本次补全先用原名保存**,
|
|
82
|
+
或者让用户回面板改名后重新 arm 一次——**不要**你自己换名字硬存。
|
|
83
|
+
|
|
84
|
+
### 1.3 一句话背景不够用时
|
|
85
|
+
|
|
86
|
+
骨架卡的「一句话背景」是**你自己要往下扩写的种子**,不是最终文案。
|
|
87
|
+
但扩写只允许在**用户给的信息范围内**做语言组织(把"合租、夜班"写成具体的相处细节),
|
|
88
|
+
不允许新增设定("他养了一只猫"这种没提过的东西不许加)。
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## 2. 第二步:一次问完 3-5 个关键问题
|
|
93
|
+
|
|
94
|
+
### 2.1 为什么要一次性问
|
|
95
|
+
|
|
96
|
+
用户点「AI 补全」是希望**快**。一个一个问、等他回一句再问下一句,体验就是挤牙膏。
|
|
97
|
+
**把 3-5 个问题一条消息发完,让他挑着答**——他答几个你就填几个,没答的标 `[待补]`。
|
|
98
|
+
|
|
99
|
+
### 2.2 问题模板(按需取用,不要全问)
|
|
100
|
+
|
|
101
|
+
只问**缺了会明显不像人**的那几个维度:
|
|
102
|
+
|
|
103
|
+
| # | 要问什么 | 落到哪个字段 | 什么时候必须问 |
|
|
104
|
+
|---|---|---|---|
|
|
105
|
+
| 1 | **他说话什么节奏?有没有口头禅 / 爱用句?** | `voice.pace` / `voice.catchphrases` | 几乎总是(声线是"像不像"的灵魂) |
|
|
106
|
+
| 2 | **他叫你什么?你怎么叫他?他自称什么?** | `voice.callsUser` / `relationship.userCallsChar` / `voice.selfRef` | 总是 |
|
|
107
|
+
| 3 | **你们是什么关系?从哪一天开始的?**(合租室友 / 同事 / 前任 / 陌生人…) | `relationship.startPoint` | 总是(决定起点档) |
|
|
108
|
+
| 4 | **有什么话绝对不能提 / 他绝不会说的词?** | `interactionPref.taboo` / `voice.forbidden` | 用户提过"雷区"念头时 |
|
|
109
|
+
| 5 | **他现在在忙什么、什么情绪?** | `dynamicState.recent` / `dynamicState.mood` / `dynamicState.doing` | 想直接开聊时 |
|
|
110
|
+
| 6 | **你在故事里是谁?**(我本人 / 另一个角色 / 自定义) | `userPersona.who` / `userPersona.relation` | 关系字段填完还空着时 |
|
|
111
|
+
|
|
112
|
+
**一次问完的写法**(示例,别照抄措辞):
|
|
113
|
+
|
|
114
|
+
> 「几个问题一起答,能答几个答几个:
|
|
115
|
+
> ① 他说话快还是慢?有没有常挂嘴边的话?
|
|
116
|
+
> ② 他叫你什么、你怎么叫他、他自称什么?
|
|
117
|
+
> ③ 你们是什么关系、认识多久了?
|
|
118
|
+
> ④ 有没有绝对不能提的事?
|
|
119
|
+
> ⑤ 你现在想从什么场景开始(比如他刚下班)?」
|
|
120
|
+
|
|
121
|
+
### 2.3 用户可以答"随便 / 你看着办"吗
|
|
122
|
+
|
|
123
|
+
可以,但**这不是给你的编造许可**:
|
|
124
|
+
|
|
125
|
+
- 用户说「随便」→ 你给**2 个候选**让他挑(「是偏冷淡短句,还是偏话多爱逗你?」),
|
|
126
|
+
他挑一个,你就按他挑的写;
|
|
127
|
+
- 用户说「你看着办」并且真的不挑 → 按**骨架卡已有信息能推出来的最保守版本**写,
|
|
128
|
+
并在汇报里明确标 `[AI推断]`,说明「这几处是我按背景推的,不对你说一声我改」;
|
|
129
|
+
- 用户明确说「不用问了,就这样吧」→ 直接进 §5 汇报,缺的字段全部如实标 `[待补]`。
|
|
130
|
+
|
|
131
|
+
### 2.4 用户答得含糊 / 答非所问
|
|
132
|
+
|
|
133
|
+
骨架卡阶段的用户常常一边操作面板一边打字,答一句漏三句是常态。处理顺序:
|
|
134
|
+
|
|
135
|
+
1. **先捡能用的**:答了「他话不多」就把 `pace` 写成「慢、短句」,别揪着他没答的第三题;
|
|
136
|
+
2. **缺的不硬追**:缺的字段标 `[待补]` 直接往下走——补全的价值在于"现在就能聊",不是"一次问全";
|
|
137
|
+
3. **只在一种情况下追问**:`first_mes` 都没法写(完全不知道关系与场合)。这时只补一句:
|
|
138
|
+
「再给我一句:你们现在是什么关系、在什么地方?有这一句我就能开场了。」
|
|
139
|
+
4. **绝不**把同一批问题问第二遍;用户已经烦了就直接进 §5 汇报。
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## 3. 第三步:按酒馆卡格式补全(键名一个都不许改)
|
|
144
|
+
|
|
145
|
+
### 3.1 结构是权威,原生位是投影
|
|
146
|
+
|
|
147
|
+
插件存的是**酒馆卡 CCv3**(`spec: chara_card_v3`)。两类字段分工不同:
|
|
148
|
+
|
|
149
|
+
| 放哪 | 放什么 | 谁来写 |
|
|
150
|
+
|---|---|---|
|
|
151
|
+
| `data.extensions.aiwu.*` | 常规人设:基本信息、声线、性格、关系、世界底色、动态状态、记忆锚点、互动偏好、用户身份 | **你写**(照 §3.2 的键名) |
|
|
152
|
+
| `data.first_mes` + `data.alternate_greetings` | 开场白 + 2–3 条备选 | **你写**(原生位,插件不会替你编) |
|
|
153
|
+
| `data.description` / `personality` / `scenario` / `system_prompt` / `post_history_instructions` | 由 `aiwu` 结构**确定性生成** | **留空**,别自己写 |
|
|
154
|
+
| `data.character_book.entries[]` | 被问到时才需要的大块设定 | 可选,没有就整块省略 |
|
|
155
|
+
|
|
156
|
+
> 记法:**结构(`aiwu`)是权威,原生位是投影**。你一写原生位,就容易和结构打架。
|
|
157
|
+
|
|
158
|
+
### 3.2 键名对照表(照抄,禁止自创)
|
|
159
|
+
|
|
160
|
+
这张表与 `distill/flow.md` 附录 A 完全一致(改一处要同步另一处)。**表里没有的键不要发明。**
|
|
161
|
+
|
|
162
|
+
| # | 内容 | `aiwu` 键 | 类型 |
|
|
163
|
+
|---|---|---|---|
|
|
164
|
+
| 1 | 年龄 | `basic.age` | string |
|
|
165
|
+
| 2 | 身份 | `basic.identity` | string |
|
|
166
|
+
| 3 | 一句话背景 | `basic.background` | string |
|
|
167
|
+
| 4 | 对话节奏 | `voice.pace` | string |
|
|
168
|
+
| 5 | 爱用句式 | `voice.catchphrases` | string[] |
|
|
169
|
+
| 6 | 自称 | `voice.selfRef` | string |
|
|
170
|
+
| 7 | 对用户的称呼 | `voice.callsUser` | string |
|
|
171
|
+
| 8 | 情绪口头禅 | `voice.emotes` | string[] |
|
|
172
|
+
| 9 | 禁忌词 | `voice.forbidden` | string |
|
|
173
|
+
| 10 | 非语言小动作 | `voice.gestures` | string[] |
|
|
174
|
+
| 11 | 性格关键词 | `personality.keywords` | string[] |
|
|
175
|
+
| 12 | 内在矛盾 | `personality.contradiction` | string |
|
|
176
|
+
| 13 | 对待亲近之人 | `personality.towardClose` | string |
|
|
177
|
+
| 14 | 关系起点 | `relationship.startPoint` | string |
|
|
178
|
+
| 15 | 角色怎么称呼用户 | `relationship.charCallsUser` | string |
|
|
179
|
+
| 16 | 用户怎么称呼角色 | `relationship.userCallsChar` | string |
|
|
180
|
+
| 17 | 来处 | `world.origin` | string |
|
|
181
|
+
| 18 | 落差 | `world.gap` | string |
|
|
182
|
+
| 19 | 如今的日子 | `world.nowadays` | string |
|
|
183
|
+
| 20 | 你与他的旧 | `world.sharedPast` | string |
|
|
184
|
+
| 21 | 记忆锚点 | `memoryAnchors` | string[] |
|
|
185
|
+
| 22 | 当前情绪 | `dynamicState.mood` | string |
|
|
186
|
+
| 23 | 近况 | `dynamicState.recent` | string |
|
|
187
|
+
| 24 | 此刻在做什么 | `dynamicState.doing` | string |
|
|
188
|
+
| 25 | 回复长度倾向 | `interactionPref.length` | string |
|
|
189
|
+
| 26 | 表情使用 | `interactionPref.emoji` | string |
|
|
190
|
+
| 27 | 话题舒适区 | `interactionPref.comfortZone` | string |
|
|
191
|
+
| 28 | 雷区 | `interactionPref.taboo` | string |
|
|
192
|
+
| 29 | 你是谁(用户自设) | `userPersona.who` | string |
|
|
193
|
+
| 30 | 与 TA 的关系 | `userPersona.relation` | string |
|
|
194
|
+
| 31 | 共同经历 | `userPersona.sharedHistory` | string |
|
|
195
|
+
| 32 | 称呼替换名 | `userPersona.displayName` | string(可空) |
|
|
196
|
+
| 33 | 开场白 | `data.first_mes` | string(**原生位**,手写) |
|
|
197
|
+
| 34 | 备选开场 | `data.alternate_greetings` | string[](**原生位**,2–3 条) |
|
|
198
|
+
|
|
199
|
+
约定:
|
|
200
|
+
|
|
201
|
+
- 数组字段就给**数组**(`["我跟你说", "真的假的"]`),不要写成一句用顿号连起来的字符串;
|
|
202
|
+
- 拿不到的键**整键省略**,不要写空串、不要写 `null`;
|
|
203
|
+
- `schema` 恒为 `1`;`displayName` 留空表示渲染成「你」;
|
|
204
|
+
- `name` 只在两处出现:工具参数 `name` 与 `data.name`,**必须一致**。
|
|
205
|
+
|
|
206
|
+
### 3.3 补全的优先级(时间有限就按这个顺序)
|
|
207
|
+
|
|
208
|
+
1. **`first_mes`**:没有开场白,用户点开就是空白,这是废卡第一原因;
|
|
209
|
+
2. **`voice.*`**:pace / catchphrases / selfRef / callsUser —— 决定"像不像这个人";
|
|
210
|
+
3. **`relationship.startPoint`**:决定关系起点档,填错会让角色一开口就过分亲密或过分生分;
|
|
211
|
+
4. **`personality.keywords`**:三个词以内,别写成性格分析;
|
|
212
|
+
5. **`memoryAnchors`**:2–4 条**具体**细节("他左手腕有块旧疤"),不是形容词;
|
|
213
|
+
6. 其余(world / dynamicState / interactionPref / userPersona)有多少填多少。
|
|
214
|
+
|
|
215
|
+
### 3.4 世界书要不要写
|
|
216
|
+
|
|
217
|
+
骨架卡阶段**默认不写**。只有当用户明确说了"我们那个世界有个……"、
|
|
218
|
+
且这块设定**被问到时才需要**(势力 / 地名 / 主线梗概)才写进 `character_book`:
|
|
219
|
+
|
|
220
|
+
- 一条 = 一个主题;`keys` 放 2–6 个用户真可能打出来的词;`content` 一到三句陈述事实;
|
|
221
|
+
- **单条别超过 4000 字、整本别超过 20000 字**——超了插件只会提示不会拦,但命中会变差;
|
|
222
|
+
- 能放常驻人设的短内容别放世界书,能省略的别硬凑。
|
|
223
|
+
|
|
224
|
+
### 3.5 真实调用长这样(形状示例,内容不许照抄)
|
|
225
|
+
|
|
226
|
+
```jsonc
|
|
227
|
+
awu_card_save({
|
|
228
|
+
"name": "林晚",
|
|
229
|
+
"data": {
|
|
230
|
+
"name": "林晚",
|
|
231
|
+
"first_mes": "(她把口罩往下拉了拉,靠在护士站台边看你)……又加班?",
|
|
232
|
+
"alternate_greetings": ["(抬手看了眼表)这个点还来?", "(把保温杯推过来)先喝口水。"],
|
|
233
|
+
"extensions": {
|
|
234
|
+
"aiwu": {
|
|
235
|
+
"schema": 1,
|
|
236
|
+
"basic": { "identity": "夜班护士", "background": "和你在同一栋楼合租,倒班作息" },
|
|
237
|
+
"voice": { "pace": "慢,句子短,常停顿", "catchphrases": ["……你说呢"], "selfRef": "我",
|
|
238
|
+
"callsUser": "你", "emotes": ["(叹气)"], "forbidden": "撒娇式语气", "gestures": ["捏眉心"] },
|
|
239
|
+
"personality": { "keywords": ["克制", "心软", "怕麻烦别人"], "contradiction": "嘴上嫌麻烦,实际什么都替你想到" },
|
|
240
|
+
"relationship": { "startPoint": "同栋合租的邻居,认识半年", "charCallsUser": "你", "userCallsChar": "林晚" },
|
|
241
|
+
"memoryAnchors": ["她左手腕有块旧疤", "她只在凌晨两点喝速溶咖啡"],
|
|
242
|
+
"dynamicState": { "recent": "连续上了三个夜班", "mood": "累但撑着" },
|
|
243
|
+
"interactionPref": { "length": "短,两句以内", "taboo": "别提她的家人" }
|
|
244
|
+
}
|
|
245
|
+
},
|
|
246
|
+
"source": ["custom"]
|
|
247
|
+
},
|
|
248
|
+
"overwrite": true
|
|
249
|
+
})
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
**注意最后那个 `overwrite: true`**:这次是覆盖同名骨架卡,不是新建。不带它会被工具拒成 `name-conflict`。
|
|
253
|
+
|
|
254
|
+
### 3.6 开场白怎么写(`first_mes` / `alternate_greetings`)
|
|
255
|
+
|
|
256
|
+
`first_mes` 是用户真正会看到的第一句话,写砸了前面的字段全白搭。三条硬要求:
|
|
257
|
+
|
|
258
|
+
1. **是"发消息",不是"段落"**:一到三条短句,可以带一个 `(动作)`,不要旁白式描写环境;
|
|
259
|
+
2. **带一个只有这个角色才会有的细节**(他正在做的事、他的口癖、他对你的称呼),
|
|
260
|
+
让人一眼看出"哦,是他",而不是"某个 AI 在打招呼";
|
|
261
|
+
3. **给用户留话口**:结尾是一个能接的话头,不是总结句、不是"有什么需要我帮忙的"。
|
|
262
|
+
|
|
263
|
+
`alternate_greetings` 给 2–3 条,**每条切一个不同的场景/情绪面**(刚下班 / 深夜 / 你在生气),
|
|
264
|
+
不要三句同义改写。例:
|
|
265
|
+
|
|
266
|
+
| 切面 | 例子(形状示意,别照抄) |
|
|
267
|
+
|---|---|
|
|
268
|
+
| 主开场:日常 | `(把保温杯推过来)先喝口水。` |
|
|
269
|
+
| 备选 1:久别 | `(看了你一眼)几天没见你回来吃饭了。` |
|
|
270
|
+
| 备选 2:情绪低点 | `(把口罩拉下来,声音闷闷的)今天别说话,陪我坐会儿。` |
|
|
271
|
+
|
|
272
|
+
**禁止**在开场白里塞设定说明(「我是你的合租室友林晚,我们是朋友」)——
|
|
273
|
+
设定是 `aiwu` 字段的事,开场白只负责"像人在说话"。
|
|
274
|
+
|
|
275
|
+
---
|
|
276
|
+
|
|
277
|
+
## 4. 第四步:不编造 —— `[待补]` 与 `[AI推断]` 的用法
|
|
278
|
+
|
|
279
|
+
### 4.1 两种标记,别混用
|
|
280
|
+
|
|
281
|
+
| 标记 | 什么时候用 | 举例 |
|
|
282
|
+
|---|---|---|
|
|
283
|
+
| `[待补]` | 用户没说、你也推不出来 | `"taboo": "[待补]"` 或在汇报里写「雷区:待补」 |
|
|
284
|
+
| `[AI推断]` | 用户**没直接说**,但骨架卡背景能合理推出 | `"pace": "[AI推断] 慢,句子短"` |
|
|
285
|
+
|
|
286
|
+
规则:
|
|
287
|
+
|
|
288
|
+
- 标记**直接写在字段值里**,用户确认后你会被要求去掉标记(下一轮修订时删);
|
|
289
|
+
- 汇报时必须**逐条列出** `[待补]`("还缺三条:雷区、年龄、你在他故事里的身份"),
|
|
290
|
+
只报「有 3 处待补」等于没报;
|
|
291
|
+
- `[AI推断]` 要在汇报里点明依据("按夜班 + 合租推的"),让用户能一眼否掉;
|
|
292
|
+
- **宁可留空,不要编**。一个空字段不影响开聊,一个编出来的设定会一直错下去。
|
|
293
|
+
|
|
294
|
+
### 4.2 什么算"推得出来"
|
|
295
|
+
|
|
296
|
+
可以做语言组织,不可以做设定发明。
|
|
297
|
+
|
|
298
|
+
| 允许 | 不允许 |
|
|
299
|
+
|---|---|
|
|
300
|
+
| 把"夜班护士"写成"作息和你错开,见面多在楼道" | 给她加一个男朋友 / 一只猫 / 一场车祸 |
|
|
301
|
+
| 把"冷淡"写成"短句、少语气词、不主动搭话" | 把"内向"升级成"社交恐惧症" |
|
|
302
|
+
| 从"合租"推到"知道你家门牌号" | 从"合租"推到"你们已经交往两年" |
|
|
303
|
+
|
|
304
|
+
**判据**:这句话如果用户看到会说「我没说过这个啊」——那它就不该被写进去。
|
|
305
|
+
|
|
306
|
+
### 4.3 用户补充信息之后
|
|
307
|
+
|
|
308
|
+
用户答了问题 → 你**就地更新**对应字段(不用重走全流程),然后重新汇报一次差异:
|
|
309
|
+
「声线补齐了,雷区还空着,就这两处」。不要因为改一处就把整张卡重讲一遍。
|
|
310
|
+
|
|
311
|
+
---
|
|
312
|
+
|
|
313
|
+
## 5. 第五步:汇报摘要(给用户看,不贴 JSON)
|
|
314
|
+
|
|
315
|
+
### 5.1 汇报模板
|
|
316
|
+
|
|
317
|
+
按清单报,别写小作文:
|
|
318
|
+
|
|
319
|
+
```
|
|
320
|
+
《林晚》补全好了:
|
|
321
|
+
|
|
322
|
+
· 说话方式:慢、句子短,自称「我」,叫你「你」,爱说「……你说呢」
|
|
323
|
+
· 性格:克制、心软、怕麻烦别人;表面嫌麻烦,实际都替你想到
|
|
324
|
+
· 关系:同栋合租的邻居,认识半年(起点档:熟悉)
|
|
325
|
+
· 记忆锚点:左手腕旧疤 / 只在凌晨两点喝速溶咖啡
|
|
326
|
+
· 开场白:三条(一条主开场 + 两条备选)
|
|
327
|
+
|
|
328
|
+
还缺([待补]):年龄、雷区、你在她故事里的身份
|
|
329
|
+
推断的([AI推断]):说话节奏(按夜班 + 冷淡推的)、近况「连续三个夜班」
|
|
330
|
+
|
|
331
|
+
这样存可以吗?要改哪块直接说。
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
### 5.2 摘要里必须出现的三样
|
|
335
|
+
|
|
336
|
+
1. **一句人设摘要**(让人能确认"抽对了角色");
|
|
337
|
+
2. **待补清单**(逐条,不是数量);
|
|
338
|
+
3. **问一句能不能存**(「这样存可以吗」)。
|
|
339
|
+
|
|
340
|
+
### 5.3 摘要里不许出现的
|
|
341
|
+
|
|
342
|
+
- JSON、字段名堆砌(`voice.pace` 这种词用户不需要看);
|
|
343
|
+
- 大段角色台词(那是开聊之后的事);
|
|
344
|
+
- 「已为你生成完整人设」这类邀功话术。
|
|
345
|
+
|
|
346
|
+
---
|
|
347
|
+
|
|
348
|
+
## 6. 第六步:保存(`awu_card_save` + `overwrite: true`)
|
|
349
|
+
|
|
350
|
+
### 6.1 调用
|
|
351
|
+
|
|
352
|
+
用户点头之后:
|
|
353
|
+
|
|
354
|
+
```jsonc
|
|
355
|
+
awu_card_save({ "name": "林晚", "data": { …见 §3.5… }, "overwrite": true })
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
- **一定带 `overwrite: true`**:骨架卡已经在角色簿里了,不带会被拒成 `name-conflict`;
|
|
359
|
+
- `data.name` 与参数 `name` 必须一致;
|
|
360
|
+
- 一次调用就能落盘;**不要**把卡贴给用户、**不要**输出 JSON。
|
|
361
|
+
|
|
362
|
+
### 6.2 按返回码处理(别自己猜)
|
|
363
|
+
|
|
364
|
+
| 返回 | 处理 |
|
|
365
|
+
|---|---|
|
|
366
|
+
| `ok: true` | 进 §6.3 |
|
|
367
|
+
| `code: "name-conflict"` | **这不是撞车,是确认**:同名骨架卡就在那儿 → 核对名字与指令给的**完全一致**(大小写、空格、标点都要一样),然后带 `overwrite: true` 再调一次。**绝对不许改名绕过**(改名 = 新建空壳卡,原卡等于没补) |
|
|
368
|
+
| `code: "not-armed"` | 这次补全窗口已经关了 → 「保存窗口过期了,去面板重新点一次「AI 补全」,我这儿的内容还在」 |
|
|
369
|
+
| `code: "invalid-data"` | 按报错原文修 `data` 再试一次;仍失败就如实说 |
|
|
370
|
+
| `code: "invalid-name"` | 名字含非法字符或太长 → 说明这是骨架卡本身的名字问题,让用户回面板改名后重新 arm;**不要**自己起一个合法名字存 |
|
|
371
|
+
|
|
372
|
+
> `name-conflict` 的语义要点:工具在保护「同名卡不被误覆盖」,而这次**就是要覆盖**。
|
|
373
|
+
> 所以正确动作是补 `overwrite: true`,不是换名字。
|
|
374
|
+
|
|
375
|
+
返回里可能有 `warnings`(例如世界书偏大):**照原话转告一句就行**,不影响卡能用。
|
|
376
|
+
|
|
377
|
+
### 6.3 保存成功后:一句话,然后闭嘴
|
|
378
|
+
|
|
379
|
+
> 「存好了:《林晚》——夜班护士,嘴上嫌麻烦实际都替你想好的合租邻居。角色簿里已经能看到。想调哪块(声线 / 关系 / 开场)直接说。」
|
|
380
|
+
|
|
381
|
+
要求:
|
|
382
|
+
|
|
383
|
+
- 说清**卡名 + 一句人设 + 已保存**;
|
|
384
|
+
- 给一个"还能改"的出口;
|
|
385
|
+
- **不开聊、不演角色、不给示例台词**——这段建卡流程到此结束。
|
|
386
|
+
|
|
387
|
+
---
|
|
388
|
+
|
|
389
|
+
## 7. 交卡前自检(逐条过)
|
|
390
|
+
|
|
391
|
+
- [ ] `first_mes` 能直接当第一条消息发出去,且一听就是这个人的语气;
|
|
392
|
+
- [ ] `voice` 的 `pace` / `catchphrases` / `selfRef` / `callsUser` 至少填了三个;
|
|
393
|
+
- [ ] `relationship.startPoint` 有值(决定起点档),称呼类字段与它不矛盾;
|
|
394
|
+
- [ ] `memoryAnchors` 是具体细节,不是"很温柔""有点傲"这种形容词;
|
|
395
|
+
- [ ] 所有键名都在 §3.2 的表里,**没有一个自创键**;
|
|
396
|
+
- [ ] 数组字段真的是数组;拿不到的键是**省略**或标了 `[待补]`,不是空串;
|
|
397
|
+
- [ ] 没有写 `description` / `personality` / `scenario` / `system_prompt` / `post_history_instructions`;
|
|
398
|
+
- [ ] **`name` 与 `data.name` 都是指令/用户确认的原文卡名**,没有被你"优化"过;
|
|
399
|
+
- [ ] `[待补]` / `[AI推断]` 在汇报里逐条列出,没有含糊带过;
|
|
400
|
+
- [ ] 只调了 `awu_card_save`,没动别的 `awu_*` 工具;
|
|
401
|
+
- [ ] 没有输出 JSON、没有演角色、没有给示例台词、没有自己开聊。
|
|
402
|
+
|
|
403
|
+
---
|
|
404
|
+
|
|
405
|
+
## 8. 常见翻车与补救
|
|
406
|
+
|
|
407
|
+
| 症状 | 真实原因 | 怎么办 |
|
|
408
|
+
|---|---|---|
|
|
409
|
+
| 存完发现角色开口就跑偏 | `voice` 太空(只填了 pace) | 补 `catchphrases` / `selfRef` / `callsUser` / `forbidden`,再存一次 |
|
|
410
|
+
| 一开口就过分亲密 | `relationship.startPoint` 写成了"恋人"但实际只是室友 | 改 `startPoint`,起点档会跟着变 |
|
|
411
|
+
| 用户说"不像他" | 关键词写成了性格分析("他其实内心很矛盾") | 换成可观察的词("嘴硬心软""说话留半句") |
|
|
412
|
+
| 工具返回 `name-conflict` | 没带 `overwrite: true`(同名的就是这张骨架卡) | 核对名字与指令一致后带上 `overwrite: true` 再调一次,**不要改名** |
|
|
413
|
+
| 目录里多出一张几乎一样的卡 | 保存时名字被改过(推断出了新名字) | 那是新建的空壳卡:删掉它,用**原名 + `overwrite: true`** 重存一次 |
|
|
414
|
+
| 工具返回 `not-armed` | 窗口过期 | 让用户回面板重新点「AI 补全」 |
|
|
415
|
+
| 卡里出现奇怪字段 | 自创了键名 | 删掉,只留 §3.2 表里的键 |
|
|
416
|
+
|
|
417
|
+
---
|
|
418
|
+
|
|
419
|
+
## 9. 中断了怎么续(用户中途离开 / 窗口过期)
|
|
420
|
+
|
|
421
|
+
补全比蒸馏短得多(通常一两轮问答),但用户仍可能中途去忙别的。规则:
|
|
422
|
+
|
|
423
|
+
- **不要在会话里落断点文件**:补全的素材(用户口述的声线、雷区)就在这段对话里,
|
|
424
|
+
你手上有什么、缺什么,随时能重新数一遍;
|
|
425
|
+
- 用户回来说「继续补全 / 接着弄刚才那张」→ **先在对话里复述你已有的结论**,
|
|
426
|
+
再补问还缺的那一两条,**不要从头问一遍**;
|
|
427
|
+
- 返回码是 `not-armed`(窗口过期)→ 说明「保存窗口过期了,去面板重新点一次「AI 补全」,
|
|
428
|
+
我这儿的内容还在」,等用户重新 arm 之后再调 `awu_card_save`;
|
|
429
|
+
- 用户明确说「算了不弄了」→ 一句话收住(「行,卡先放着,想补的时候再叫我」),
|
|
430
|
+
**不要保存半成品**(半成品覆盖掉骨架卡,反而比原来更糟)。
|
|
431
|
+
|
|
432
|
+
---
|
|
433
|
+
|
|
434
|
+
## 10. 一句话总纲(拿不定主意时看这里)
|
|
435
|
+
|
|
436
|
+
> 用户告诉你的,写进去;骨架卡背景推得出来的,标 `[AI推断]` 写进去;其余一律 `[待补]`。
|
|
437
|
+
> **宁可留一个空格,不要编一个设定。**
|
|
438
|
+
|
|
439
|
+
---
|
|
440
|
+
|
|
441
|
+
## 附录:与蒸馏通道的区别(别串了)
|
|
442
|
+
|
|
443
|
+
| | 蒸馏(`flow.md`) | 补全(本手册) |
|
|
444
|
+
|---|---|---|
|
|
445
|
+
| 素材来源 | 作品原文 / 官方设定 / 联网核实 | 用户口述 + 骨架卡已有信息 |
|
|
446
|
+
| 有没有证据分级 | 有(verbatim / artifact / impression) | 没有,只有 `[待补]` / `[AI推断]` |
|
|
447
|
+
| 是否新建卡 | 新建(重名先问) | **覆盖同名骨架卡**(`overwrite: true`) |
|
|
448
|
+
| 核心纪律 | 先核实再动笔,不许编 | 用户说的才算数,不许编 |
|
|
449
|
+
| 收尾 | 一句话确认 + 不开聊 | 一句话确认 + 不开聊 |
|