mirror of
https://gitcode.com/JianFeeeee/HomeAgent.git
synced 2026-09-22 09:58:06 +00:00
docs: simplify README diagrams, move detailed explanations to ARCHITECTURE.md
This commit is contained in:
243
README.md
243
README.md
@ -23,197 +23,106 @@ homed(内核零 IO) ← PluginSDK → 插件(所有 IO 能力)
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant User as 用户/插件
|
||||
participant U as 用户/插件
|
||||
participant IO as IOManager
|
||||
participant Event as eventLoop
|
||||
participant Ctx as RelevanceContext
|
||||
participant LLM as LLM + 工具循环
|
||||
participant Stage as StageHost(7个钩子)
|
||||
participant Mem as 三层记忆
|
||||
participant EV as eventLoop
|
||||
participant CTX as RelevanceContext
|
||||
participant LLM as LLM+工具循环
|
||||
participant ST as StageHost
|
||||
participant MEM as 三层记忆
|
||||
|
||||
User->>IO: InjectInput(type, payload)
|
||||
IO->>Event: inputCh (buf 256)
|
||||
|
||||
rect rgb(240, 240, 255)
|
||||
Note over Event: processTextInput
|
||||
Event->>Stage: StageOnInput — 插件可改写/短路
|
||||
Event->>Ctx: Prune(input, topK) — TF-IDF评分裁剪
|
||||
Ctx->>Mem: 低分事件 → Document层归档
|
||||
Event->>Ctx: Append(input) — 5s debounce写盘
|
||||
U->>IO: InjectInput(type, payload)
|
||||
IO->>EV: inputCh
|
||||
rect lavender
|
||||
Note over EV: processTextInput
|
||||
EV->>ST: StageOnInput 插件可改写/短路
|
||||
EV->>CTX: Prune(input,topK) TF-IDF裁剪
|
||||
CTX->>MEM: 低分事件归档 Document
|
||||
EV->>CTX: Append(input) 5s写盘
|
||||
end
|
||||
|
||||
rect rgb(240, 255, 240)
|
||||
Note over Event,LLM: process() ← a.mu.Lock()
|
||||
Event->>Mem: buildMemoryContext() — Indexer自动召回Graph实体
|
||||
Event->>Mem: buildSystemPrompt() — 人格+记忆+技能注入
|
||||
Event->>Stage: StagePreAction — 插件可预拦截
|
||||
|
||||
loop 工具循环(无上限)
|
||||
LLM->>LLM: drainInterrupts() — 检查打断
|
||||
LLM->>LLM: LLM Chat — provider自动降级
|
||||
LLM->>Stage: StagePostAction — 插件可修改/短路
|
||||
rect lightgreen
|
||||
Note over EV,LLM: process()
|
||||
EV->>MEM: buildMemoryContext Indexer召回Graph
|
||||
EV->>MEM: buildSystemPrompt 人格+记忆+技能注入
|
||||
EV->>ST: StagePreAction 插件可预拦截
|
||||
loop 工具循环
|
||||
LLM->>LLM: drainInterrupts
|
||||
LLM->>LLM: LLM Chat
|
||||
LLM->>ST: StagePostAction 插件可修改/短路
|
||||
alt 无tool call
|
||||
LLM-->>Event: 返回response
|
||||
else 有tool call
|
||||
LLM-->>EV: 返回response
|
||||
else
|
||||
loop 每个tool
|
||||
Stage->>Stage: StageBeforeToolcall — 插件可拒绝
|
||||
LLM->>LLM: executeToolCall() — 按前缀路由
|
||||
Stage->>Stage: StageAfterToolcall — 插件可改结果
|
||||
LLM->>LLM: recordToolCall() + 追加消息
|
||||
ST->>ST: StageBeforeToolcall 插件可拒绝
|
||||
LLM->>LLM: executeToolCall
|
||||
ST->>ST: StageAfterToolcall
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
rect rgb(255, 240, 240)
|
||||
Note over Event: emitResponse
|
||||
Ctx->>Ctx: Append(response) — 全量交换写入
|
||||
Stage->>Stage: StageBeforeOutput — 插件可改写文本
|
||||
Event-->>User: ResponseCh (同步, CLI用)
|
||||
Event-->>Event: 事件总线 (WebUI SSE)
|
||||
Stage->>Stage: StageAfterOutput — 只读观测
|
||||
Event->>Mem: emitMemoryCandidate() → 蒸馏管道
|
||||
rect lightpink
|
||||
Note over EV: emitResponse
|
||||
CTX->>CTX: Append(response)
|
||||
ST->>ST: StageBeforeOutput 插件可改写
|
||||
EV-->>U: ResponseCh CLI同步
|
||||
EV-->>EV: 事件总线 WebUI SSE
|
||||
ST->>ST: StageAfterOutput 只读
|
||||
EV->>MEM: emitMemoryCandidate
|
||||
end
|
||||
|
||||
Note over User,Mem: ★ LLM不调用output_send时,内核绝不自动转发到输出通道
|
||||
```
|
||||
|
||||
### 二、Stage 管道模型
|
||||
### 二、Stage 管道
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
subgraph "7个阶段钩子"
|
||||
direction LR
|
||||
S1[① StageOnInput<br/>输入后·可短路] -->
|
||||
S2[② StagePreAction<br/>LLM前·可短路] -->
|
||||
S3[③ StagePostAction<br/>LLM后·可短路]
|
||||
S3 --> S4{有tool call?}
|
||||
S4 -->|是| S5[④ StageBeforeToolcall<br/>tool前·可拒绝]
|
||||
S5 --> T[executeToolCall]
|
||||
T --> S6[⑤ StageAfterToolcall<br/>tool后·只读]
|
||||
S6 --> S3
|
||||
S4 -->|否| S7[⑥ StageBeforeOutput<br/>输出前·改写文本]
|
||||
S7 --> S8[⑦ StageAfterOutput<br/>输出后·只读]
|
||||
end
|
||||
Input[用户输入] --> S1
|
||||
S8 --> Output[输出]
|
||||
|
||||
S1[① on_input] --> S2[② pre_action]
|
||||
S2 --> S3[③ post_action]
|
||||
S3 --> Q{有tool?}
|
||||
Q -->|是| S4[④ before_toolcall]
|
||||
S4 --> T[executeToolCall]
|
||||
T --> S5[⑤ after_toolcall]
|
||||
S5 --> S3
|
||||
Q -->|否| S6[⑥ before_output]
|
||||
S6 --> S7[⑦ after_output]
|
||||
style S1 fill:#e1f5fe
|
||||
style S2 fill:#e1f5fe
|
||||
style S3 fill:#fff3e0
|
||||
style S5 fill:#fce4ec
|
||||
style S6 fill:#f3e5f5
|
||||
style S7 fill:#e8f5e9
|
||||
style S8 fill:#f5f5f5
|
||||
style S6 fill:#e8f5e9
|
||||
```
|
||||
|
||||
### 三、三层记忆
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
subgraph "并行调用模型"
|
||||
direction LR
|
||||
SH[StageHost] --> G1[goroutine 1]
|
||||
SH --> G2[goroutine 2]
|
||||
SH --> G3[goroutine 3]
|
||||
G1 & G2 & G3 --> SC[StageContext<br/>RWMutex共享]
|
||||
subgraph C[① Context 工作窗口]
|
||||
RC[RelevanceContext]
|
||||
A[Append] -->|Vectorize char 1-2gram| RC
|
||||
P[Prune TF-IDF Cosine] -->|低分| D
|
||||
P -->|保留| TL[timeline→system prompt]
|
||||
end
|
||||
subgraph D[② Document 文件记忆]
|
||||
DS[DocStore JSON+TF-IDF]
|
||||
Q1[Query 自动注入] -->|【相关记忆文档】| SP
|
||||
Q2[doc_query LLM主动] -->|Consume+删除| DS
|
||||
Q2 -->|原始时间戳写入| RC
|
||||
CD[FindColdDocs 72h] -->|docToTriples| G
|
||||
end
|
||||
subgraph G[③ Graph 图数据库]
|
||||
DB[(SQLite)]
|
||||
IDX[Indexer BFS depth=2] -->|【记忆索引】| SP
|
||||
MEM[memory_recall/commit]
|
||||
SOC[person_query/set_trait]
|
||||
end
|
||||
subgraph H[④ 心跳蒸馏]
|
||||
REORG -->|Step3 冷文档| CD
|
||||
REORG -->|Step4 Bigram Jaccard| CONS[consolidation]
|
||||
PIPE[Pipeline 正则] -->|姓名/住址/喜好/年龄/职业| DB
|
||||
end
|
||||
SP[System Prompt] -->|顺序组装| LLM
|
||||
LLM[LLM] -->|doc_query| Q2
|
||||
LLM -->|memory_recall| MEM
|
||||
```
|
||||
|
||||
| 阶段 | 位置 | 调用时机 | 可短路? | 可写字段 |
|
||||
|------|------|----------|:-------:|----------|
|
||||
| StageOnInput | ① | 构建stageCtx后 | ✅ | RawMessage / Response |
|
||||
| StagePreAction | ② | 构建消息后,LLM前 | ✅ | ContextMsgs / Response |
|
||||
| StagePostAction | ③ | LLM返回后,检查tool前 | ✅ | LLMText / ToolCalls / Response |
|
||||
| StageBeforeToolcall | ④ | 每个tool执行前 | ✅(拒绝) | ToolCalls / Response |
|
||||
| StageAfterToolcall | ⑤ | 每个tool执行后 | ❌ | ToolResults |
|
||||
| StageBeforeOutput | ⑥ | 发送输出前 | ❌ | FinalText |
|
||||
| StageAfterOutput | ⑦ | 发送输出后 | ❌ | (只读) |
|
||||
|
||||
### 三、三层记忆架构
|
||||
|
||||
#### TF-IDF 字符 n-gram 向量化(char 1-2 gram)
|
||||
|
||||
TF-IDF 是贯穿三层记忆的**核心算法**,在 4 个独立位置以不同方式使用:
|
||||
|
||||
| 位置 | 文件 | n-gram | 用途 | 算法 |
|
||||
|------|------|:------:|------|------|
|
||||
| Context Prune | `context.go:162` | 2 | 裁剪低相关性上下文事件 | CosineSimilarity(queryVec, evt.Vector) |
|
||||
| DocStore Query | `document.go:205` | 2 | 从文档记忆召回相关内容 | InvertedIndex + CosineSimilarity |
|
||||
| Indexer 实体搜索 | `indexer.go:149` | 2 | 从Graph图数据库召回相关实体 | InvertedIndex + CosineSimilarity |
|
||||
| 实体相似度 | `agent.go:2297` | 2 | 检测Graph中相似实体 | Bigram Jaccard (>0.75→consolidation) |
|
||||
|
||||
#### 记忆流转图
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
subgraph "① Context 层 — 工作窗口"
|
||||
RC[RelevanceContext<br/>内存events[] + JSON文件]
|
||||
A[Append<br/>每次输入时调用] -->|Vectorize<br/>char 1-2gram TF-IDF| RC
|
||||
P[Prune<br/>TF-IDF CosineSimilarity<br/>保留 topK + 最近10条] -->|低分事件归档| CDoc
|
||||
P -->|保留| TL[timeline → system prompt<br/>按时间排序输出给LLM]
|
||||
S[save<br/>5s debounce写盘] --> RC
|
||||
end
|
||||
|
||||
RC -->|读取全部事件| TL
|
||||
|
||||
subgraph "② Document 层 — 文件记忆"
|
||||
D[DocStore<br/>JSON文件 + TF-IDF向量索引]
|
||||
CDoc[ContextToDoc<br/>Prune归档入口] -->|结构化摘要+标签+实体| D
|
||||
LLMDC[LLM工具<br/>doc_commit] -->|手动提交| D
|
||||
GSD[syncGraphToDocs<br/>每30min] -->|Graph快照| D
|
||||
Q[Query<br/>system prompt注入] -->|Vectorize输入<br/>InvertedIndex+Cosine<br/>召回top 3| D
|
||||
Q -->|格式: 【相关记忆文档】| SP
|
||||
AC[AccessCount++<br/>LastAccess更新] -->|每次Query命中| D
|
||||
end
|
||||
|
||||
subgraph "③ Graph 层 — 图数据库"
|
||||
G[(SQLite)]
|
||||
G --> ENT[entities<br/>{Name,Type,Summary,Vector}]
|
||||
G --> REL[relations<br/>{PersonA,Relation,PersonB}]
|
||||
IDX[Indexer 自动召回<br/>每30min重建向量索引] -->|Vectorize实体名<br/>TF-IDF + BFS depth=2| G
|
||||
IDX -->|格式: 【记忆索引】| SP
|
||||
MEM[LLM工具<br/>memory_recall/commit/merge] --> G
|
||||
SOC[Social层<br/>person_query/set_trait/relate] --> G
|
||||
end
|
||||
|
||||
subgraph "④ 蒸馏管道 — 每30min心跳"
|
||||
DC[distillContext<br/>窗口>2×max→强制Prune] -->|触发| P
|
||||
SYNC[syncGraphToDocs] -->|Graph→Document| GSD
|
||||
REORG[reorgGraph] -->|Step1| IDXSYNC[indexer.Sync<br/>重建实体向量索引]
|
||||
REORG -->|Step2| DREIDX[docStore.Reindex<br/>重建文档向量索引]
|
||||
REORG -->|Step3 冷文档→Graph| CD[FindColdDocs<br/>72h / ≤2次访问] -->|docToTriples| G
|
||||
REORG -->|Step4 实体相似度| BIGRAM[Bigram Jaccard<br/>>0.75] -->|consolidation| LLMCONS[LLM判断<br/>是否merge]
|
||||
REORG -->|Step5 图质量| QEVAL[evaluateGraphQuality<br/>低置信度关系] --> LLMCONS2[LLM判断<br/>保留/删除]
|
||||
end
|
||||
|
||||
SP[System Prompt<br/>组装顺序] -->|base→人格→| GI[【记忆索引】<br/>Indexer召回实体]
|
||||
GI -->|清洗指令→| DM[【相关记忆文档】<br/>DocStore.Query top3]
|
||||
DM -->|技能注入→| TDS[工具定义] --> LLM
|
||||
|
||||
subgraph "⑤ LLM 工具循环"
|
||||
LLM[LLM 推理] -->|memory_recall| MEM
|
||||
LLM -->|doc_query| Q2[doc_query 工具]
|
||||
Q2 -->|Consume<br/>读取并删除| D
|
||||
Q2 -->|③ 写入context<br/>原始时间戳+源cold_storage| RC
|
||||
Q2 -->|返回: 已加载N篇| LLM
|
||||
LLM -->|doc_commit| LLMDC
|
||||
LLM -->|output_send| OUT[输出通道]
|
||||
end
|
||||
|
||||
subgraph "⑥ Pipeline 规则蒸馏器"
|
||||
PIPE[pipeline/distillOnce<br/>每心跳] -->|正则匹配| R1[我叫X→(用户,姓名,X)]
|
||||
PIPE -->|正则匹配| R2[我住在X→(用户,居住地,X)]
|
||||
PIPE -->|正则匹配| R3[我喜欢X→(用户,喜好,X)]
|
||||
PIPE -->|正则匹配| R4[我X岁→(用户,年龄,X)]
|
||||
PIPE -->|正则匹配| R5[我的工作是X→(用户,职业,X)]
|
||||
R1 & R2 & R3 & R4 & R5 -->|GraphDB.Commit| G
|
||||
end
|
||||
```
|
||||
|
||||
| 层级 | 存储介质 | 索引 | 写入路径 | 读取路径 | 触发方式 |
|
||||
|------|---------|------|----------|----------|---------|
|
||||
| Context | 内存+JSON文件 | 无独立索引,TF-IDF向量缓存在event上 | Append(每次输入) | timeline格式化→system prompt | 自动 |
|
||||
| Document | JSON文件 | TF-IDF InvertedIndex(char 1-2gram) | Prune归档 / doc_commit / Graph快照 | DocStore.Query→【相关记忆文档】→system prompt | 自动+LLM调用 |
|
||||
| Graph | SQLite | 实体名TF-IDF向量索引(Indexer) + BFS遍历 | memory_commit / 冷文档蒸馏 / 规则蒸馏 | Indexer.BuildContext→【记忆索引】→system prompt | 自动+LLM调用 |
|
||||
详细说明见 [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md)。
|
||||
|
||||
## 快速体验
|
||||
|
||||
|
||||
@ -64,31 +64,68 @@ eventLoop() → processTextInput()
|
||||
|
||||
## 三层记忆
|
||||
|
||||
### 记忆流转
|
||||
|
||||
```
|
||||
输入
|
||||
│
|
||||
▼
|
||||
Context (RelevanceContext) ←────────────────┐
|
||||
├─ 内存中 topK 条事件, TF-IDF 评分 │
|
||||
├─ keep=30, 超出 → Document │
|
||||
└─ JSON 持久化防崩溃 │
|
||||
│ │
|
||||
▼ │
|
||||
Document (document.Store) ────┤ │
|
||||
├─ JSON 文件 + TF-IDF 向量索引 │
|
||||
├─ 3 层冷化: 72h+access≤2 → Graph │
|
||||
└─ 用户也可主动 commit │
|
||||
│ │
|
||||
▼ │
|
||||
Graph (GraphDB + Indexer) ────┘ │
|
||||
├─ SQLite: entities / relations 表 │
|
||||
├─ 搜索: BFS 遍历邻居 │
|
||||
└─ 蒸馏: Distiller 原始记录→三元组 │
|
||||
│ │
|
||||
▼ │
|
||||
Context.Append(response) ───────────────────┘
|
||||
① Context (工作窗口)
|
||||
RelevanceContext — 内存 events[] + JSON持久化
|
||||
Append: 每次输入, Vectorize(char 1-2gram TF-IDF)
|
||||
Prune: TF-IDF CosineSimilarity, 保留 topK + 最近10条
|
||||
├── 保留 → timeline → system prompt (按时间排序)
|
||||
└── 低分 → Document 层归档 (ContextToDoc)
|
||||
Save: 5s debounce 写盘
|
||||
|
||||
↓ Prune 归档 ↑ LLM 主动召回
|
||||
|
||||
② Document (文件记忆)
|
||||
DocStore — JSON文件 + TF-IDF InvertedIndex
|
||||
写入: Prune归档 / doc_commit / Graph快照(syncGraphToDocs)
|
||||
读取:
|
||||
├── 自动注入: Query(input, top3) → 【相关记忆文档】→ system prompt (只读, 更新 AccessCount)
|
||||
└── LLM主动: doc_query → Consume(读取并删除)
|
||||
→ 逐条 context.Append{Timestamp: d.CreatedAt, Source: "cold_storage"}
|
||||
→ 文档以原始时间戳写入 context 时间线, 从 docStore 删除
|
||||
冷化: FindColdDocs(72h, ≤2次访问) → docToTriples → Graph
|
||||
|
||||
↓ 冷文档蒸馏 ↑ 自动召回
|
||||
|
||||
③ Graph (图数据库)
|
||||
SQLite — entities + relations 表
|
||||
写入: memory_commit / 冷文档蒸馏 / Pipeline 规则蒸馏
|
||||
读取:
|
||||
├── 自动召回: Indexer.BuildContext(input)
|
||||
│ → TF-IDF 实体名搜索 → BFS depth=2
|
||||
│ → 【记忆索引】→ system prompt
|
||||
└── LLM主动: memory_recall / doc_query
|
||||
Social: person_query / set_trait / relate (包装 GraphDB)
|
||||
|
||||
④ 蒸馏管道 (每30min心跳)
|
||||
distillContext → 窗口>2×maxSize → 强制Prune
|
||||
syncGraphToDocs → Graph 快照写入 Document(跨层可搜索)
|
||||
reorgGraph:
|
||||
Step1: indexer.Sync — 重建实体TF-IDF向量索引
|
||||
Step2: docStore.Reindex — 重建文档TF-IDF向量索引
|
||||
Step3: 冷文档 → docToTriples → GraphDB.Commit
|
||||
Step4: 实体相似度(Bigram Jaccard>0.75) → consolidation → LLM判断合并
|
||||
Step5: evaluateGraphQuality → LLM判断保留/删除
|
||||
|
||||
⑤ Pipeline 规则蒸馏器 (每心跳)
|
||||
distillOnce → 正则匹配个人信息:
|
||||
我叫X / 我住在X / 我喜欢X / 我X岁 / 我的工作是X
|
||||
→ 三元组 → GraphDB.Commit
|
||||
```
|
||||
|
||||
### TF-IDF 向量化(char 1-2 gram)
|
||||
|
||||
TF-IDF 是贯穿三层记忆的核心算法,在 4 个独立位置以不同方式使用:
|
||||
|
||||
| 位置 | 文件 | 用途 | 算法 |
|
||||
|------|------|------|------|
|
||||
| Context Prune | `context.go:162` | 裁剪低相关性上下文事件 | CosineSimilarity(queryVec, evt.Vector) |
|
||||
| DocStore Query | `document.go:205` | 从文档记忆召回相关内容 | InvertedIndex + CosineSimilarity |
|
||||
| Indexer 实体搜索 | `indexer.go:149` | 从Graph召回相关实体 | InvertedIndex + CosineSimilarity |
|
||||
| 实体相似度检测 | `agent.go:2297` | 检测Graph中相似实体 | Bigram Jaccard (>0.75 → consolidation) |
|
||||
|
||||
### Context 层
|
||||
|
||||
`internal/agent/core/context.go` — `RelevanceContext`
|
||||
|
||||
Reference in New Issue
Block a user