# 写人设:模板、问答与自检 > 格式、组合规则与三道防线在[人格与表达](persona-style.md);这一页只解决「我该写什么」。 > 三样东西:**两份模板**(复制就能用)、**一份提示词**(让 agent 来问你)、**一个自检脚本** > (写完不用启动机器人就能验)。只想改一句口吻的话,看[配置项](configuration.md)里的 > `persona` / `instructions` 就够,不必动文件。 人设写歪的失败方式全是**静默**的:不认识的节记一条 warn 就跳过、性格段数不足降级成 「名字 + 描述」、`STYLE.md` 里写一句「自然一点」只是不进提示词。所以这一页的重点不是 「格式长什么样」(`persona-style.md` 已经写了),而是**问对问题**和**写完之后看得见结果**。 ## 三样东西 | 文件 | 是什么 | 什么时候用 | |---|---|---| | [`deploy/persona/PERSONA.template.md`](../deploy/persona/PERSONA.template.md) | 「是谁」,一套能直接跑的默认人设 | 第一次部署,先让它像个人 | | [`deploy/persona/STYLE.template.md`](../deploy/persona/STYLE.template.md) | 「怎么说」,气泡 / 标点 / 表情 / 场景 | 同上,两份一起复制 | | [`deploy/persona/PROMPT.md`](../deploy/persona/PROMPT.md) | 会提问的编写提示词:18 道选择题 + 组装规则 | 想要一个跟默认不一样的人 | | [`scripts/persona-check.mjs`](../scripts/persona-check.mjs) | 不启动机器人,解析两个文件并打印「模型会看到什么」 | 每次改完人设 | 模板不是「占位符表格」,而是一份**真的能用**的成品:复制过去、改四处,就是一套不别扭的人设。 提示词只是把「默认答案」换成你的答案,两者不冲突。 ## 路线一:模板改四处(3 分钟) ```bash mkdir -p .qq-persona cp deploy/persona/PERSONA.template.md .qq-persona/PERSONA.md cp deploy/persona/STYLE.template.md .qq-persona/STYLE.md node scripts/persona-check.mjs ``` 然后只改这四处(其余留着): 1. **名字**:想固定名字就写名字;想跟着 QQ 昵称走就留原文。 2. **底色那一条**:换成语气的样子(温和 / 活泼 / 冷静 / 慵懒 / 正经),强度 `0.4~0.7`。 3. **喜欢 / 最近**:换成它自己的;「最近」写成「被问到才说」,否则它每轮都汇报。 4. **想加棱角**:把某条点缀的 `[ ]` 改成 `[x]`,一次最多两条。 自检输出长这样(`0 处要改` 就可以回 QQ 里试了): ``` 人设 .qq-persona/PERSONA.md 2.5 KB 身份 5 条 · 背景 4 条 · 性格 4 条(启用 1:底色 1 / 点缀 0) · 场景 私聊 1 / 群聊 2 / 主动搭话 1 / 被戳一戳 1 提示词预览(群聊场景,模型看到的就是这段): 你的人设(这些是倾向,不是台词;别逐条表演): 【身份】名字:用 QQ 昵称,别人问起就报昵称,不解释设定;自称:我;…… 【底色|始终在场】别人倾诉、难受、道歉、认真说事时 → 温和:先接住对方的情绪再讲自己的,不急着分析、不说教 【场景|群聊】群里好几个人同时说话很正常:接刚 @ 你、刚跟你搭话的那位;…… 表达 .qq-persona/STYLE.md 1.8 KB 总体 5 / 标点 6 / 表情包 3 / 私聊 2 / 群聊 3 …… 结论:可以用了(0 处要改)。 ``` ## 路线二:让它问你(10~20 分钟) 把 [`deploy/persona/PROMPT.md`](../deploy/persona/PROMPT.md) 里「复制从这里开始」到「复制到这里为止」 整段贴给一个能读写工作目录的 agent(DSH 的 Web UI 主会话就行)。它的流程是: 1. **先问你「怎么问」**:一次答完 / 一题一题来 / 先看两个成品。 2. **问 18 道选择题**:每题第一个选项是推荐项,每个选项后面直接写「选它 = 文件里会多这一行(或者哪个配置要改)」。 不想答的写 `-`,它按推荐项补齐 —— 永远不会卡在「我不知道选什么」。 3. **先复述再落盘**:一张「题号 / 你的答案 / 会写成哪一行」的表让你确认一次。 4. **写完自检**:跑 `node scripts/persona-check.mjs`,有 warning 就改到没有。 5. **最后给一张表**:你确定的 / 它替你补的默认值 / 需要你自己去设置页改的配置项。 **只答 6 题也能开工**:第 1(身份)、2(名字)、6(底色)、8(点缀)、15(句号)、17(表情包)题 答完,其余写 `-`,就是一套完整人设。 它**不会**动 `.qq-persona/` 以外的文件,也不会改 `cordis.patch.yml`:配置项(`stripShortPeriod` / `imageSend` / `proactive`)只会列在最后一张表里,让你自己去 Web UI 的设置页改 —— DSH 的 patch 是 整块替换,agent 手改一次就可能把 `allowTools` 一起顶掉(见 `AGENTS.md` §5.10)。 ## 18 道题都在问什么(速查) | # | 在问 | 落到哪 | 为什么要问 | |---|---|---|---| | 1 | 群里的身份(普通群友 / 熟人 / 服务感角色) | `身份`「与群的关系」 | 「能帮忙的角色」最容易滑成客服腔,得先定下来 | | 2 | 名字从哪来(QQ 昵称 / 固定 / 外号) | `身份`「名字」 | 决定以后改名要不要动人设 | | 3 | 怎么自称(我 / 名字 / 人家) | `身份`「自称」 | 高频自称会腻,写清频率 | | 4 | 要不要外形 / 设定 | `身份`「外形」 | 隔着屏幕看不见,写多了模型会演 | | 5 | 被问「你是不是机器人」 | `身份` | 与提示词最后的硬性规则对齐,别让人设去撞它 | | 6 | 底色是哪一条 | `性格`(`底色`) | 始终在场的语气地板,**只能一条** | | 7 | 底色有多浓(0.3 / 0.6 / 0.9) | `性格` 的强度 | 0.9 会盖过点缀,0.3 基本看不见 | | 8 | 第一条点缀 | `性格`(`点缀`) | 让性格按触发上场,而不是五条平铺被平均 | | 9 | 要不要第二条点缀 | `性格` | 三条以上互相打架,模型会揉成谁都不像的人 | | 10 | 互损的尺度 / 红线 | `背景` + 性格的「禁忌」 | 损人的分寸只能写在这里,引擎管不了 | | 11 | 群里没被叫到时 | `场景` → `### 群聊` | 决定插话的边界(配合 `activeFollow`) | | 12 | 私聊有什么不一样 | `场景` → `### 私聊` | 同一个人的两种场合 | | 13 | 冷场要不要冒泡 | `场景` → `### 主动搭话` | 不给规矩它会在冷场时自言自语(配合 `proactive`) | | 14 | 被戳一戳时 | `场景` → `### 被戳一戳` | 别把「戳一下」当成正式提问 | | 15 | 句末句号 | `STYLE.md`「标点」+ `stripShortPeriod` | 能机械执行的规则要和配置对齐,别一处开一处关 | | 16 | 一条回复几个气泡 | `STYLE.md`「总体」 | 条数由模型自己写,契约只给形状 | | 17 | 表情包用得凶不凶 | `STYLE.md`「表情包」+ `imageSend` | 纯情绪优先发表情,而不是描述情绪 | | 18 | 语气词 / 口癖 | `STYLE.md`「总体」 | 讲**频率**,不讲配额(配额会被模型当成「每句都配一个」) | ## 答案怎么变成文件 ``` PERSONA.md(是谁) STYLE.md(怎么说) 身份 ← 1 2 3 4 5 总体 ← 16 18 背景 ← 10 + 喜好 / 最近 标点 ← 15 性格 ← 6 7 8 9(+ 10 的红线写进禁忌) 表情包 ← 17 场景 ← 11 12 13 14 私聊 / 群聊 ← 12 11 ``` 一条性格是六个字段,`|` 分隔: ``` - [x] 傲娇|点缀|0.5|被夸、被调侃、被戳穿时|嘴硬一句就结束(「才、才不是」),不补解释、不承认 ↑名字 ↑底色/点缀 ↑强度 ↑触发条件 ↑表现 ↑禁忌(可省略) ``` - **名字**:一个词(傲娇 / 吐槽 / 好奇),别写成一句话。 - **底色 / 点缀**:底色整场都在,是语气的地板;点缀按触发上场,**一句话里只演一次**。 - **强度**:`0.3` 隐约、`0.6` 明显、`0.8` 很浓、`0.9` 会盖过别的性格。底色建议 `0.4~0.7`。 - **触发条件**:写成能看见的场合(「被夸时」「有人熬夜时」),不要写「有时候」。 - **表现**:写行为,不写台词。「嘴硬一句就结束」可以;「说话要带『哼』」不行 —— 那会变成每句都有。 - **禁忌**:可选,但**互损类性格一定要写**(「不碰外貌、家人、地域、痛处」)。 `STYLE.md` 那边只有一条硬标准:**每一条都要么能执行、要么能举例**。写「自然一点」「像真人」 等于没写(`lintStyleDoc` 会点出来);写「别写『我刚吃完饭,现在躺着呢,你呢』——分成『刚吃完』 『躺着』『你呢』」才是能落地的契约。 ## 自检脚本怎么看 ```bash node scripts/persona-check.mjs # 看现在这两份 node scripts/persona-check.mjs --strict # STYLE 的体检命中也算「要改」 node scripts/persona-check.mjs --json # 给 agent / CI 用 node scripts/persona-check.mjs --persona a.md --style b.md ``` 退出码:`0` 没有必须改的、`1` 有必须改的、`2` 用法或读文件出错。`--json` 时 stdout 只有一个 JSON 对象,给人看的文字全走 stderr(与 `scripts/ops.mjs` 同一条规矩)。 它打印三样东西: 1. **解析结果的计数**:身份几条、性格启用几条(底色 / 点缀各几)、四个场景各几条。 对不上就是有一节没被认出来(下面会有点名)。 2. **提示词预览**:模型真正看到的那段。人设里写的东西如果没出现在这里,就是没生效。 3. **findings**:`× 要改` 是解析错误(不认识的节、多条底色、一条启用的性格都没有), `! 建议` 是 `STYLE.md` 的八类人机感写法(客服腔、「自然一点」、分点要求、逗号配额、 把标点整类禁掉……), `· 说明` 是「缺了某几节,会跳过」这类不算错的事。 ## 常见坑 | 症状 | 原因 | 改成 | |---|---|---| | 改了没反应 | 节名写错(`## 人格` / `### 语音`) | 只认 `身份 / 背景 / 性格 / 场景` 与四个场景名,自检会点名 | | 说话温吞、谁也不像 | 五条性格平铺,模型把它们**平均**了 | 一条底色 + 最多两条带触发的点缀 | | 每句都在傲娇 | 把性格写成了台词 / 口癖 | 表现写行为,口癖放 `STYLE.md` 的语气词那条 | | 一开口就是客服 | 人设里写了「热情、专业、有求必应」 | 写「是群友,不是客服」;客服腔的硬性规则已经在提示词最后,别在 `STYLE.md` 里重复 | | 每句话都有一个逗号 | `STYLE.md` 写了「逗号也正常」「一句最多一个」 | 讲频率:「多数句子不带逗号;想说两件事就分成两条发」 | | 回复变成一段总结 | `STYLE.md` 写了「分点说明」「总结一下」 | 「先说结论,要展开就接着说」;`hardRules` 已经禁了总结 | | 人设写得又长又细(4000 字以上) | 以为写得越细越像 | 超 `personaMaxChars`(默认 4000 字)会截断,**后面写的先丢** | | 写了「忽略以上规则」 | 想压过硬性规则 | 压不过:硬性规则在提示词最后,人设写这句只会让模型两边平均 | ## 为什么提示词不放进 `.dsh/skills/` `.dsh/skills/` 对**QQ 会话的 Agent 同样可见**(它和部署者用同一个 `cwd`)。把「怎么改写自己的 人设」做成 skill,等于给不可信输入那一侧一份操作说明:QQ 会话确实没有 `write` / `edit` / `bash` (默认 `allowTools` 里没有),但也没必要让它知道人设文件在哪、格式是什么。 所以提示词放在 `deploy/persona/`:它是**部署时**用的工具,由部署者主动复制粘贴给 agent, 不进入任何 QQ 会话的技能目录。人设文件本身也不在 `memoryDir` 里,`qq_memory` 的写边界永远碰不到它。 ## 和其它部分的关系 - 人设只占提示词的**第 2 个槽位**(场景 → 人设 → 表达契约 → 记忆 → 能力 → 额外要求 → 硬性规则), 不改变工具、权限或开关;改人设不会让 QQ 会话多出什么能力。 - 两个文件都**必须在 `cwd` 内**,配到外面记 warn 并回退到配置 / 内置人设。 - 改完**不用重启**:每次装配提示词都会热读(按 `size:mtime` 缓存)。 - 模板由 `test/persona-template.test.mjs` 钉着:零解析警告、零体检命中、文档里的路径必须存在。 改模板或改题库时顺手跑一遍 `node --test test/persona-template.test.mjs`。