Files
hunjing/docs/architecture/lingtai-runtime.md
T

246 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 灵台插件化运行时
> 状态:重写目标态(rewrite/1.0 基线)
> 职责:定义灵台认知运行时的结构——极小硬核 Kernel、插件体系、事件溯源会话、上下文投影、提示词与记忆注入管线、压缩、并发与命台控制。
> 设计理念参考 deepseek-harness 的"一切皆插件"与 pi 的会话/压缩模型,均只借设计不引依赖。
## 1. 设计理念与硬核例外
运行时遵循三条理念:
1. **一切皆插件**:模型适配、工具、记忆、人格调节、压缩、世界认知……全部以插件装配,无特权核心,可从配置替换。
2. **事件溯源**:Run 的一切输入输出进入 append-only 事件日志(一炁),模型可见上下文从事件日志投影派生;铁律 **"模型可见即可重建"**——到达模型的任何输入必须能从日志重建,运行时以断言强制。
3. **监听器可否决**:关键节点(请求前、工具执行前、结果接纳前)是瀑布事件,插件监听器可改写或否决;注入、审计、安全都在事件层做,不改循环骨架。
**硬核例外(不可插拔)**:Kernel 固化以下内容,任何插件不可卸载、降权或绕过——
- 镜树不变量:重新生成不覆盖旧候答、未归真旁枝不自动入忆、归真不因切换候答回滚、编辑已发送内容必分叉;
- 命台不变量:同一人物同一时刻只有一条前台意识流,多分支前台请求排队;
- 司命禁域裁决点:高风险能力、数据、后果、情境四维裁决中标记为禁域的规则在请求前强制执行;
- 事件日志写入:状态变更与事件一致提交(事务内或 Outbox)。
这套例外的依据是产品宪章"禁域不能被 Prompt、人物、模型、扩展、管理员或普通部署配置关闭"。插件体系的自由度止步于禁域。
## 2. 分层结构
```mermaid
flowchart TD
subgraph Kernel[极小硬核 Kernel · 不可插拔]
INV[不变量裁决器]
SEAT[命台并发控制]
LOG[事件日志读写]
LOOP[Run 循环骨架]
end
subgraph Bus[事件总线 · 瀑布节点]
N1[run.requested]
N2[turn.started]
N3[llm.pre_request]
N4[tool.pre_execute]
N5[result.pre_accept]
N6[turn.finished]
end
subgraph Plugins[插件层 · Profile 装配]
P1[灵核 · 人格调节]
P2[太一 · 目标]
P3[司命 · 常驻裁决]
P4[烛照 · 观察反思]
P5[河图 · 世界认知]
P6[洛书 · 计划]
P7[息壤 · 记忆]
P8[百工 · 能力注册]
P9[天工阁 · 功能 Agent]
end
LOOP --> Bus
Plugins --> Bus
Kernel --> Plugins
```
## 3. 事件溯源会话
### 3.1 事件模型
Run 是一次人物认知运行(一次前台回答、一次后台受托任务、一次应感)。Run 事件序列是一炁事件流的一个分区:
```mermaid
flowchart LR
E1[run.started] --> E2[turn.started]
E2 --> E3[context.projected<br/>投影快照引用]
E3 --> E4[llm.requested]
E4 --> E5[llm.delta ...]
E5 --> E6[llm.completed]
E6 --> E7{工具调用?}
E7 -- 是 --> E8[tool.pre_execute]
E8 --> E9[tool.executed]
E9 --> E4
E7 -- 否 --> E10[turn.finished]
E10 --> E11[result.pre_accept]
E11 --> E12[run.finished]
```
- 事件带单调序号、`run_id`、`character_id`、`trace_id` 与时间戳;事件类型与取值以[契约词典](../contracts/contract-glossary.md)为单一事实源。
- SSE 输出是事件流的可发布投影:`visibility=public` 的事件可推送前端,`internal`/`audit` 不出灵台。
- 中断(取消、网络失败、超时)写入 `run.interrupted`,芽体封存为残答,不伪装完成。
### 3.2 上下文投影
`derive_context()` 从事件日志 + 镜树状态 + 记忆状态投影出本次模型可见上下文,来源只有三类(镜树 PRD 不变量 6):
1. **祖先路径**:当前工作入口的问节-候答祖先链;
2. **获准长期记忆**:经息壤检索且通过敏感与权限过滤的明忆/重忆;
3. **显式引文**:用户建立的引文锚及其快照。
未采用旁枝默认不进入投影。投影结果写入 `context.projected` 事件(引用而非全文,可从日志重建),这是"模型可见即可重建"的落点。
## 4. 插件体系
### 4.1 插件契约
```python
class Plugin(Protocol):
name: str # 稳定标识,登记于契约词典 pivot 枚举
version: str
def register(self, bus: EventBus, profile: Profile) -> None: ...
```
- 插件通过订阅瀑布节点与提供能力(工具、检索器、调节器、压缩器)参与运行。
- 插件之间不直接调用,只经事件总线与能力注册表交互。
- 插件加载顺序由 Profile 决定;同节点多个监听器按注册序执行,任一否决即中断并记录。
### 4.2 Profile(运行档案)
Profile 是一次 Run 的插件装配清单与参数包,来源于配置层叠:
```mermaid
flowchart LR
A[平台硬边界<br/>禁域与全局上限] --> E[最终 Profile]
B[平台目录<br/>默认插件与参数] --> E
C[用户偏好 / BYOK] --> E
D[人物覆写<br/>道体·人格·能力授契] --> E
F[镜树临时选择<br/>模型·火候·指引] --> E
```
层叠顺序与产品 PRD"神识配置继承"一致;镜树临时选择只作用于该节点及用户明确继承的后继。Profile 本身写入事件日志,保证可审计、可回放。
### 4.3 九枢落位
| 枢 | 插件职责 | 关键机制 |
| --- | --- | --- |
| 灵核 | 人格调节:道体锚点 + 调节层参数注入 | 道体不可运行时覆盖;调节层按证据渐进演进,重大变化走铸魂流程 |
| 太一 | 目标:人物长期目标的维护与冲突检测 | 目标层级与状态见契约词典 |
| 司命 | 安全裁决:能力/数据/后果/情境四维 | 自省/循律/请命/禁域四级自主性;禁域挂载点在 Kernel |
| 烛照 | 观察与反思:对工具观察、用户反馈做理解候选 | 产出心痕候选与正影建议,不直接写状态 |
| 河图 | 世界认知:世界实体、世谱(Lorebook)激活 | 世谱激活管线见 §6.1 |
| 洛书 | 计划:多步任务的计划生成与跟踪 | 计划状态机见契约词典 |
| 息壤 | 记忆:三级记忆的写入候选、检索、注入 | 管线见 §6.2 |
| 百工 | 能力注册:工具/MCP/Skill/感官的唯一目录 | 每个 Run 只暴露最小获准 Schema |
| 天工阁 | 功能 Agent 编排:受托任务分解与并行 | 功能 Agent 无魂籍与身份;不构成第二意识 |
## 5. 提示词组装管线
采纳 SillyTavern PromptManager 的"实体化提示词 + 审计覆盖"模式:
- 每个注入片段是实体:`identifier / role / source / position / depth / order / forbid_override`;
- `source` 区分:系统契约、道体、人格调节、世界认知(河图)、记忆(息壤)、引文、用户指令、镜树对话;
- `position`:相对排序或绝对深度(atDepth 注入对话流内),`depth` 从消息尾部计数;
- 组装结果与每个片段的来源一起写入 `context.projected` 事件,前端"可解释轨迹"直接读该事件;
- `forbid_override=true` 的片段(系统契约、禁域声明)不可被人物层与镜树层覆盖,只可被平台更新替换。
## 6. 记忆注入与检索
### 6.1 微痕激活(借世界信息激活管线)
微痕与会谱条目共用激活管线:
1. **时序效果**:`sticky`(激活后置顶 N 轮)、`cooldown`(冷却轮数)、`delay`(延迟轮数);
2. **关键词扫描**:对最近 N 条消息做关键词/正则匹配(全字边界、大小写选项);
3. **次级键逻辑**:AND ANY / NOT ALL / NOT ANY / AND ALL;
4. **递归扫描**:已激活条目内容回流再扫描,限最大步数;
5. **预算控制**:激活条目按 `order` 排序,超出 token 预算(上下文的百分比上限)从尾部淘汰;
6. **向量补充**:预算内对未命中关键词的微痕做相似度召回。
激活结果作为 `source=trace` 的提示词实体进入组装管线。
### 6.2 长期记忆检索(明忆/重忆)
1. 双路召回:pgvector 向量 + PG 全文检索,RRF 融合;
2. 过滤:敏感等级、界域(境界记忆不进真界上下文)、撤回与删除状态、授权范围;
3. 时间衰减与优先级加权:活力值 `2^(−Δdays/半衰期)`,命中强化,重忆优先展示来源与版本;
4. 召回预算:条数与字符上限;
5. 每次召回写入轻量审计(召回了什么、用于哪个 Run),支撑"召回透明"。
### 6.3 写入管线(归真后提取)
只有带 `canonical_scope` 的归真结果触发长期记忆提取(异步任务):
1. **提取**:单次 LLM 调用完成情境切分 + 记忆候选抽取;三原则:宁缺毋滥(滤闲聊与一次性指令)、独立完整(脱离对话仍成立)、归纳合并;输出 `{content, type, priority, confidence, sensitive, source_message_ids}`;
2. **双源标记**:`user_explicit`(用户明说)与 `self_inferred`(人物推断);
3. **分级落位**:白名单内低敏 → 明忆候选(自动生效 + 撤销窗);敏感或高影响 → 重忆候选(必须用户确认);类型含心痕(`relationship_view`,主观非事实);
4. **去重合并**:向量召回统一候选池 → 批量判定 store/skip/update/merge(跨类型合并、时间戳并集);
5. **版本链**:更新产生新版本指向旧版本,旧版停止普通召回(正影语义);
6. **删除**:墓碑只证明删除行为发生,不承载原文;主存储、索引、上下文、主动对话同步停止使用。
## 7. 压缩管线
长对话压缩是可插拔能力(息壤插件的子模块),非循环骨架:
- **触发**:投影 token 超过窗口减预留阈值;
- **切点规则**(pi 模型):从尾部保留近段消息累计到保留额度,向前寻找合法切点;**工具结果永不作切点**,工具调用与结果必须配对保留或一同进入压缩区;
- **分区摘要**:旧摘要 + 新消息增量续写,分区为背景/事实/关系/未决事项/关键决定;
- **内容路由**(headroom 思想):工具结果按内容类型分治——JSON/结构化裁剪、代码保关键段、纯文本摘要;对话历史走摘要压缩;
- **缓存友好**:注入片段位置固定(固定 depth 注入点),前缀字节稳定,避免打爆 Provider KV 缓存;
- **可逆引用**:被压缩掉的原文保留在事件日志,人物可经"回溯"能力按引用取回;
- 压缩边界事件(start/end)入日志,崩溃可检测(孤儿压缩标记)。
## 8. 并发与命台控制
```mermaid
sequenceDiagram
participant U1 as 设备 A
participant U2 as 设备 B
participant K as Kernel 命台控制
participant R as Run
U1->>K: 前台生成请求(树 1)
K->>R: 获得前台槽位,Run 启动
U2->>K: 前台生成请求(树 2)
K-->>U2: 排队(返回队列位置)
U1->>K: steer(运行中插话)
K->>R: 注入 steering 消息队列(下一 turn 生效)
U1->>K: 取消
K->>R: 取消 → 芽体封存残答 → run.interrupted
K->>R: 出队树 2 请求
```
- 前台槽位以人物为粒度,Redis 持锁(轻量档进程内锁),带租约与心跳;崩溃后租约到期自动释放,进行中的芽体标记中断。
- 后台受托 Run(天工阁)可并发,标记为功能任务,不进入前台槽位。
- steering 消息进入队列并在事件日志留痕,插话不静默(下一 turn 前端可见"已插话")。
## 9. 工具执行(百工 ↔ 乾坤)
1. `tool.pre_execute`:司命按四维裁决;请命级暂停等待用户确认(confirmations 表,超时即拒绝执行);
2. 获准后由执行器分派:HTTP 工具、MCP(博闻等)、乾坤沙箱(本地/代码执行)、内置工具;
3. `tool.executed`:结果先净化(敏感词/隐私脱敏)与标证(来源、时间、许可),作为观察写入事件日志;
4. 观察被接纳(`result.pre_accept`)后才有资格形成记忆候选;任何插件不得把工具结果直接写成事实或人物答复。
## 10. 目录与代码组织
```text
backend/app/
kernel/ # 极小硬核:不变量、命台、事件日志接口、循环骨架
runtime/ # 事件总线、Profile、插件加载、投影、压缩调度
pivots/ # 九枢插件实现(每枢一个包)
domains/ # 六域领域层(镜生/缘契/三界/形仪/灵台域/天宰)
infra/ # 复用基础设施:auth/RBAC/审计/事件存储/幂等/SSE
shenshi_client/ # 神识客户端边界(唯一模型出口)
api/ # v1 路由与 DTO
```
## 11. 测试策略
- **不变量测试**:Kernel 不变量逐条有失败用例(重生成覆盖、旁枝入忆、归真回滚、并行前台、禁域绕过——全部必须被拒绝并留痕);
- **回放测试**:随机抽样历史 Run,从事件日志重放投影,与当时 `context.projected` 比对一致("模型可见即可重建"的验证);
- **插件契约测试**:每个插件用统一 harness 验证注册、订阅、否决语义;
- **管线性质测试**:世谱激活(时序/递归/预算)、记忆提取(三原则)、压缩(切点配对、缓存前缀稳定)各有单元与性质测试;
- 端到端:创建→首聊→分叉→归真→记忆候选→确认→召回 的完整链路走 BFF 入口验证。