数字我 Digital Me:全量入库(大文件走 Git LFS)
nginx serve /uploads direct (audio speed) / patch-nginx (push) Failing after 1m34s

This commit is contained in:
2026-10-10 16:24:43 +08:00
commit 0593ff7e62
1893 changed files with 361723 additions and 0 deletions
+77
View File
@@ -0,0 +1,77 @@
# 天赋系统契约(Talent System Contract)
天赋树 = **Prompt + 模型行为的控制平面**,不是游戏成长系统。
- **主天赋(唯一)** = 身份:决定 System Prompt / 是否走 RAG / 合规安全等级 / 默认模型。主天赋 **就是 `twin.profession`**,不另存一套 id。
- **副天赋(≤N)** = 风格软技能:**后置改写**,只碰成稿、**绝不改事实**。
实现见 [`../../src/talents.js`](../../src/talents.js)。本目录是与线上代码对齐的**契约**,也是将来搬 DB 的蓝本。
## 文件
| Schema | 描述 | 对应代码 |
|---|---|---|
| [main-talent.schema.json](main-talent.schema.json) | 主天赋身份节点 | `mainTalent(profId)` |
| [sub-talent.schema.json](sub-talent.schema.json) | 副天赋注册表项 | `SUB_REGISTRY` |
| [user-talent-instance.schema.json](user-talent-instance.schema.json) | 分身选定的天赋 | `twin.talents` |
| [talent-registry.schema.json](talent-registry.schema.json) | 注册表整体 | 派生/静态表 |
## 派生关系(主天赋怎么来的)
不逐个职业手写主天赋,而是三张映射表交叉派生(`talents.js`):
```
profession(professions.js) ──cat──▶ ARCH_BY_CAT ──▶ arch ──▶ ARCH_BEHAVIOR(行为基线) + ARCH_MODEL(模型偏好)
└─compliance─▶ COMPLIANCE ──▶ safety_level + block_keywords + disclaimer + audit_required
```
- `cat → arch`:content→creator, pro/health/biz/life/other→expert, edu→teacher, art→artist, sport→sport, craft→craft
- `compliance → 安全`:none→{2,无} / soft→{5,软免责} / strict→{9,强免责+关键词+需审核}
新增一个职业只改 `professions.js` 一处;换某原型的行为只改 `ARCH_BEHAVIOR` 一处。
## 校验规则(服务端必须兜底,不信前端)
1. **主天赋唯一**:`main_talent` 必须 ∈ 职业表(`getProfession`),否则 400 `unknown-main-talent`;`null`/无 → `general` 兜底身份。
2. **副天赋合法性**:每个 id 必须 ∈ `SUB_REGISTRY`;去重;顺序保留。
3. **副天赋槽位**:数量 ≤ `maxSubs(level) = min(3, 1 + level)`(level 来自 `computeSkillTree`)。超出**静默截断**(`validateSubs`),不报错。
4. **副天赋不改事实**:所有 style/constraint 副天赋合并成**一次**后置改写,指令强约束"不改变任何事实/数字/结论/引用";hobby 型走前置注入。
5. **审核门(软门)**:`main.audit_required && !twin.verified` → `twin.talentAudit='pending'`,**不拦截**(分身仍可用),但运行时 Guardrail 强制免责。已 `verified` → `'approved'`。
6. **Guardrail(运行时,输出前)**:
- `block_keywords` 命中 → 软化替换;
- `safety_level >= 5` 且回答未含免责 → 追加 `disclaimer` 到结尾。
## 运行时管线(`services/twin.js` → `ask()`)
```
用户输入
→ 组装 System Prompt:身份(mainPromptBlock) + 前置注入(injectBlock) + 人设/记忆/RAG
→ (RAG 检索,main.rag)
→ LLM 主回答 chat(messages) ← 主天赋出稿
→ 副天赋后置改写 chat([restyleInstruction, draft]) ← 合并 1 次;无副天赋则跳过
→ Guardrail guardrail(text, main) ← 屏蔽词 + 免责
→ 输出
```
成本:每轮 **1 次主调用 + 至多 1 次改写调用**(不是每个副天赋一次)。
## API 契约
### `GET /api/twins/:id/talents`
返回(`describeTalents`):
```jsonc
{
"main": { "id","name","emoji","entity","arch","compliance","safety_level",
"rag_required","audit_required","audit_ok","behavior" },
"subs": { "selected": ["humor"], "max": 1,
"options": [{ "id","name","subtype","desc" }] },
"growth": { "level": 0, "maxSubs": 1 }
}
```
### `PUT /api/twins/:id/talents`
Body(两字段都可选,可单独改):
```jsonc
{ "main_talent": "lawyer", // 可选:切身份(=profession),带 audit 门
"sub_talents": ["humor","concise"] } // 可选:仅当为数组时才更新;截到 maxSubs
```
返回同 `GET`。
## DB 化迁移(留了缝,MVP 不做)
1. `SUB_REGISTRY` → 集合 `talent_sub_registry`(一项一文档)。
2. 主天赋映射(ARCH_BEHAVIOR / COMPLIANCE / ARCH_MODEL)→ 集合 `talent_main_config`,或物化 `talent_main_talents`(一职业一行)。
3. 每个节点加 `talent-registry.schema.json#/$defs/versioning`(`version/active/gray_pct`)→ 支持**灰度放量 + 一键回滚**。
4. `talents.js` 的纯函数签名不变,只把三张 `const` 表换成带缓存的 DB 读取;`describeTalents/resolveTalents/guardrail` 全部复用。
## 留坑不做(架构留得住)
天赋升级 lv2/3(`level` 字段已在)· 冲突检测(医生+算命❌)· 天赋市场(官方/共创)· 会话级动态天赋 · 按天赋真路由模型/计量返佣(`model_preference` + `chat(opts.model)` 缝已在)。