docs: 重构为 docs/zh/ + docs/en/ 子文件夹结构

- 拆分为 docs/zh/(中文) 和 docs/en/(英文)
- README 索引对应语言子文件夹
- 保留所有文档内容
This commit is contained in:
root
2026-04-14 13:25:53 +08:00
parent dd685485b5
commit 29d15707f5
18 changed files with 16 additions and 16 deletions

29
docs/zh/README.md Normal file
View File

@ -0,0 +1,29 @@
# TrulyMEM 文档
欢迎来到 TrulyMEM 项目文档。
## 文档目录
| 文档 | 内容 |
|------|------|
| [architecture.md](architecture.md) | 系统架构和技术设计 |
| [quick_start.md](quick_start.md) | 完整启动指南与配置说明 |
| [memory.md](memory.md) | 内部记忆工作机制 |
| [persona.md](persona.md) | 人设图机制 |
| [working_memory.md](working_memory.md) | 连续性任务处理机制 |
| [api.md](api.md) | 后端 API 接口文档(供扩展开发) |
| [prompts.md](prompts.md) | 提示词管理模块 |
## 项目简介
TrulyMEM (TrueHumanMEM) 是一个让 AI 拥有长期记忆能力的图记忆系统,通过图数据库存储实体关系,让 AI 能够像人类一样记忆、回忆和管理信息。
## 核心特性
- **长期记忆存储**: 基于 SQLite 内嵌图数据库,开箱即用
- **人设图机制**: 支持角色扮演和性格设定
- **工作记忆链**: 维持对话连贯性的任务跟踪机制
- **TUI 与后端分离**: 多线程 Queue 通信
- **键盘驱动 TUI**: 无需鼠标,全键盘操作
- **跨平台支持**: Windows / Linux / macOS
- **独立部署**: 支持打包为可执行文件

464
docs/zh/api.md Normal file
View File

@ -0,0 +1,464 @@
# BackendServer API 文档
本文档描述后端服务器的 API 接口,供开发者扩展其他连接方式(如网络接口、WebSocket 等)。
## 概述
TrulyMEM 后端采用 **Packet 通信协议**,通过 `queue.Queue` 实现线程安全通信。后端在独立线程中运行,处理来自客户端的请求。
### 核心组件
| 组件 | 说明 |
|------|------|
| `BackendServer` | 后端服务器,独立线程运行 |
| `BackendClient` | 客户端封装,提供便捷方法 |
| `PacketType` | 请求类型枚举 |
| `Packet` | 数据包(请求) |
| `PacketResponse` | 数据包响应 |
---
## 请求类型 (PacketType)
```python
class PacketType(Enum):
PROCESS_MESSAGE = "process_message" # 处理消息
EXECUTE_TOOL = "execute_tool" # 执行工具
GET_STATUS = "get_status" # 获取状态
GET_CONFIG = "get_config" # 获取配置
SET_CONFIG = "set_config" # 设置配置
GET_HISTORY = "get_history" # 获取历史
SAVE_HISTORY = "save_history" # 保存历史
SHUTDOWN = "shutdown" # 关闭服务
```
---
## 数据包格式
### Packet
```python
@dataclass
class Packet:
id: str # 唯一标识
type: PacketType # 请求类型
body: Dict[str, Any] # 请求参数
response_queue: queue.Queue # 响应队列(可选)
created_at: float # 创建时间
```
### PacketResponse
```python
@dataclass
class PacketResponse:
id: str # 对应的请求ID
success: bool # 是否成功
data: Any = None # 返回数据
error: Optional[str] = None # 错误信息
```
---
## API 接口详情
### 1. PROCESS_MESSAGE - 处理消息
发送用户消息,AI 将处理并返回回复(可能包含工具调用)。
**请求参数:**
```python
body = {
"user_input": str # 用户输入的消息
}
```
**响应数据:**
```python
{
"success": True,
"content": str, # AI 回复内容
"tool_calls": [ # 工具调用记录
{
"name": str, # 工具名称
"arguments": dict,# 工具参数
"result": str # 工具执行结果
}
],
"rejected_tools": [ # 被拒绝的工具调用
(str, str) # (工具名, 拒绝原因)
]
}
```
**示例:**
```python
from core import BackendServer, BackendClient
server = BackendServer(db_path="graph_memory.db", use_embedded_db=True)
server.start(api_key="your-api-key")
client = BackendClient(server)
result = client.process_message("你好,请记住我的名字是小明")
if result.get("success"):
print(result["content"])
```
---
### 2. EXECUTE_TOOL - 执行工具
直接执行指定的记忆工具。
> **注意**:前端直接调用的工具**不受次数限制**,只有模型发起的工具调用才受限制。
**请求参数:**
```python
body = {
"tool_name": str, # 工具名称
"arguments": dict # 工具参数
}
```
**响应数据:**
```python
{
"success": True,
"result": str # 工具执行结果
}
```
**示例:**
```python
result = client.execute_tool("memory_recall", {"query_intent": "用户信息"})
```
---
### 3. GET_STATUS - 获取状态
获取后端运行状态。
**请求参数:**
```python
body = {} # 无参数
```
**响应数据:**
```python
{
"running": bool, # 后端是否运行中
"config": dict, # 当前配置
"graph_initialized": bool, # 图数据库是否初始化
"client_initialized": bool # API 客户端是否初始化
}
```
**示例:**
```python
status = client.get_status()
print(status["data"]["running"]) # True
```
---
### 4. GET_CONFIG - 获取配置
获取当前 API 配置。
**请求参数:**
```python
body = {} # 无参数
```
**响应数据:**
```python
{
"api_key": str, # API Key
"base_url": str # API Base URL
}
```
---
### 5. SET_CONFIG - 设置配置
更新 API 配置(API Key 和 Base URL)。
**请求参数:**
```python
body = {
"api_key": str, # API Key
"base_url": str, # API Base URL (默认: https://api.deepseek.com)
"model": str # 模型名称 (默认: deepseek-chat)
}
```
**响应数据:**
```python
{
"status": "config_updated"
}
```
**示例:**
```python
result = client.update_config(
api_key="sk-xxxxx",
base_url="https://api.deepseek.com",
model="deepseek-chat"
)
```
---
### 6. GET_HISTORY - 获取消息历史
获取保存的消息历史。
**请求参数:**
```python
body = {} # 无参数
```
**响应数据:**
```python
{
"history": list # 消息历史列表
}
```
---
### 7. SAVE_HISTORY - 保存消息历史
保存消息历史到内存。
**请求参数:**
```python
body = {
"messages": list # 消息列表
}
```
**响应数据:**
```python
{
"status": "history_saved"
}
```
---
### 8. SHUTDOWN - 关闭服务
关闭后端服务器。
**请求参数:**
```python
body = {} # 无参数
```
**响应数据:**
```python
{
"status": "shutdown"
}
```
---
## 使用示例
### 基础使用
```python
from core import BackendServer, BackendClient
# 1. 创建并启动后端
# config_file 默认: ~/.trulymem/config.json
server = BackendServer(
db_path="graph_memory.db",
use_embedded_db=True,
config_file=None # 可选,自定义配置路径
)
server.start(
api_key="your-api-key",
base_url="https://api.deepseek.com",
model="deepseek-chat" # 可选,模型名称
)
# 2. 创建客户端
client = BackendClient(server)
# 3. 发送消息
result = client.process_message("你好")
if result.get("success"):
print(result["content"])
# 4. 关闭
client.shutdown()
```
### 使用 Packet 协议
```python
import queue
from core import BackendServer, Packet, PacketType
server = BackendServer(config_file=None)
server.start(api_key="your-key", model="deepseek-chat")
# 创建请求包
response_queue = queue.Queue()
packet = Packet(
id="req-001",
type=PacketType.PROCESS_MESSAGE,
body={"user_input": "你好"},
response_queue=response_queue
)
# 发送请求
result = server.send(packet)
print(result.body)
# 关闭
server.shutdown()
```
---
## 扩展指南
### 扩展为 HTTP API
```python
from flask import Flask, request, jsonify
from core import BackendServer, BackendClient
app = Flask(__name__)
server = BackendServer()
client = BackendClient(server)
@app.route("/message", methods=["POST"])
def send_message():
data = request.json
result = client.process_message(data["message"])
return jsonify(result)
@app.route("/config", methods=["POST"])
def update_config():
data = request.json
result = client.update_config(data["api_key"], data.get("base_url"))
return jsonify(result)
@app.route("/status", methods=["GET"])
def get_status():
result = client.get_status()
return jsonify(result)
if __name__ == "__main__":
server.start()
app.run(port=8080)
```
### 扩展为 WebSocket
```python
import asyncio
import websockets
import json
from core import BackendServer, BackendClient
server = BackendServer()
client = BackendClient(server)
async def handler(websocket):
async for message in websocket:
data = json.loads(message)
msg_type = data.get("type")
if msg_type == "message":
result = client.process_message(data["content"])
elif msg_type == "config":
result = client.update_config(data["api_key"], data.get("base_url"))
elif msg_type == "status":
result = client.get_status()
else:
result = {"success": False, "error": "unknown type"}
await websocket.send(json.dumps(result))
async def main():
server.start()
async with websockets.serve(handler, "localhost", 8765):
await asyncio.Future()
asyncio.run(main())
```
---
## 线程安全说明
- `BackendServer` 使用 `threading.Lock` 保护共享资源
- 所有请求通过 `queue.Queue` 传递,线程安全
- 响应通过每个请求独立的响应队列返回
- 默认超时时间:30 秒
---
## 工具调用限制
### 限制范围
| 调用方式 | 是否受限 | 说明 |
|---------|---------|------|
| 模型发起的工具调用 | ✅ 受限 | 通过 `PROCESS_MESSAGE` 触发,模型自动调用工具 |
| 前端直接调用工具 | ❌ 不受限 | 通过 `EXECUTE_TOOL` 直接调用 |
### 限制规则(仅限模型发起)
| 类别 | 操作 | 每轮上限 |
|------|------|---------|
| 人设图 | 查询 | 1 次 |
| 人设图 | 修改 | 1 次 |
| 工作记忆链 | 查询 | 4 次 |
| 工作记忆链 | 修改 | 2 次 |
| 一般记忆 | 查询 | 20 次 |
| 一般记忆 | 修改 | 10 次 |
### 重置机制
- 每次调用 `PROCESS_MESSAGE` 时,计数器自动重置
- 前端直接调用 `EXECUTE_TOOL` 不会重置计数器
---
## 错误处理
所有 API 返回统一格式:
```python
# 成功
{
"success": True,
"data": {...}
}
# 失败
{
"success": False,
"error": "错误描述"
}
```
常见错误:
| 错误信息 | 说明 |
|---------|------|
| `API Key 未配置` | 未设置 API Key |
| `timeout` | 请求超时 |
| `工具调用被拒绝: ...` | 工具调用频率超限 |

180
docs/zh/architecture.md Normal file
View File

@ -0,0 +1,180 @@
# TrulyMEM 架构设计
## 核心原则
- 键盘驱动,零鼠标依赖
- 极简视觉,信息密度优先
- 工具痕迹默认隐藏,需要时可展开
- TUI 与后端分离,多线程通信
- **一切皆图**,AI 推理全部在后端
## 项目结构
```
TrulyMEM-TrueHumanMEM/
├── trulymem_entry.py # 入口:先启动 core → 再启动 ui
├── core/ # 后端/业务逻辑
│ ├── __init__.py # 导出 BackendServer, BackendClient, EmbeddedGraphDB
│ ├── server.py # BackendServer (Packet 通信协议)
│ ├── client.py # BackendClient (Packet 协议客户端)
│ ├── embedded_db.py # SQLite 图数据库实现
│ ├── graph_client.py # OpenAI/DeepSeek API 客户端
│ ├── tool_executor.py # 工具执行器
│ ├── tool_limiter.py # 工具调用限制器
│ ├── tools/ # 工具定义
│ │ ├── __init__.py
│ │ └── memory_tools.py
│ └── prompts/ # 提示词管理
├── ui/ # TUI 显示层(仅显示,无 AI 逻辑)
│ ├── __init__.py # 导出 GraphMemoryApp, AppConfig
│ ├── app.py # GraphMemoryApp (通过 BackendClient 通信)
│ ├── widgets/ # TUI 组件
│ ├── handlers/ # 事件处理
│ ├── models/ # 数据模型
│ ├── services/ # 服务层(仅配置管理)
│ └── styles/ # 样式文件
└── tests/ # 测试 (42 tests)
```
## 架构图
```
trulymem_entry.py
│
├─ BackendServer.start() → 独立线程运行
│ ├─ 处理 PROCESS_MESSAGE 请求 → AI 推理 + 工具调用
│ ├─ 处理 EXECUTE_TOOL 请求 → 外部工具调用(不限次数)
│ ├─ 处理 GET/SET_CONFIG 请求
│ └─ 管理 GraphMemoryClient, EmbeddedGraphDB
│
└─ GraphMemoryApp(backend_server=server)
│
└─ BackendClient ← Packet 通信 → BackendServer
```
## 组件职责
### core/ (后端)
| 组件 | 职责 |
|------|------|
| `server.py` | Packet 协议处理,多线程队列通信,AI 推理,工具限制 |
| `client.py` | 客户端封装,UI 与后端通信桥梁 |
| `embedded_db.py` | SQLite 图数据库 CRUD |
| `graph_client.py` | OpenAI/DeepSeek API 客户端 |
| `tool_executor.py` | 工具执行逻辑 |
| `tool_limiter.py` | 工具调用频率限制(仅限 AI 推理) |
### ui/ (显示层)
| 组件 | 职责 |
|------|------|
| `app.py` | Textual 应用主类,仅通过 BackendClient 通信 |
| `services/` | 仅配置管理,无 AI 逻辑 |
### 通信协议
UI 与后端通过 **Packet 通信协议** 交互:
```python
from core import BackendServer, BackendClient, Packet, PacketType
# 后端启动
server = BackendServer(db_path="graph_memory.db", use_embedded_db=True)
server.start(api_key="your-key")
# 客户端通信
client = BackendClient(server)
result = client.process_message("你好") # AI 推理
result = client.execute_tool("memory_introspect", {}) # 外部工具调用
```
---
## 数据流
```
用户输入 → InputBox → on_input_box_send_message
↓
BackendClient.process_message(user_input)
↓
Packet (type=PROCESS_MESSAGE) → queue.Queue
↓
BackendServer (独立线程)
↓
GraphMemoryClient.send_message_with_history()
↓
OpenAI API / DeepSeek API
↓
execute_tool() + ToolLimiter (AI 推理时受限)
↓
EmbeddedGraphDB (图数据库)
↓
循环调用 API 直到无 tool_calls
↓
Packet 响应返回
↓
MessageHistory 显示
```
---
## 启动流程
```python
# trulymem_entry.py
def main():
# 配置文件保存在应用根目录
config_file = application_path / "config.json"
# 加载配置
config_service = ConfigService(config_file=config_file)
config = config_service.get_config()
# 创建后端
backend_server = BackendServer(db_path="graph_memory.db", use_embedded_db=True)
backend_server.start(api_key=config.api_key, base_url=config.base_url)
# 创建UI
app = GraphMemoryApp(backend_server=backend_server, config_service=config_service)
app.run()
backend_server.shutdown()
```
---
## 工具系统
### 记忆工具 (6个)
- `memory_recall` - 检索记忆
- `memory_commit` - 写入记忆
- `memory_purge` - 删除记忆
- `memory_introspect` - 查看状态
- `memory_archive` - 归档记忆
- `memory_cleanup` - 清理数据
### 人设工具 (2个)
- `persona_update` - 更新人设
- `persona_clear` - 清除人设
### 任务工具 (4个)
- `task_create` - 创建任务
- `task_set_state` - 设置状态
- `task_delete` - 删除任务
- `task_link_info` - 关联信息
---
## 错误处理原则
所有 API **不抛出异常**,错误通过返回字典传递:
```python
result = client.process_message("hello")
if result.get("success"):
print(result["content"])
else:
print(result["error"]) # 错误描述
```

237
docs/zh/memory.md Normal file
View File

@ -0,0 +1,237 @@
# TrulyMEM 记忆机制
本文档详细说明 TrulyMEM 内部的记忆工作机制。
## 核心设计理念
### 区别于传统上下文系统
传统 AI 对话系统使用 messages 数组存储对话历史:
- 每次请求携带全部历史消息
- 随着对话轮次增加,上下文逐渐膨胀
- 最终触发记忆压缩或滑动窗口,造成记忆丢失
TrulyMEM 的解决思路:
- **摒弃** messages 数组上下文
- **唯一** 记忆载体:图数据库
- 全部记忆以三元组(节点)- 关系 → (节点)形式存储
### 图数据库作为唯一记忆源
所有记忆必须通过以下方式写入图数据库:
- `memory_commit` - 写入新记忆
- `memory_purge` - 删除/修正记忆
所有记忆必须通过以下方式读取:
- `memory_recall` - 检索记忆
---
## 强制执行流程(每轮对话)
由于没有传统上下文系统,每轮对话必须按以下顺序执行:
### 步骤 1:查询人设图(最高优先级)
```python
memory_recall(
query_intent="AI,人设,角色,性格,语气,说话风格",
depth=2
)
```
**目的**:获取当前人设,确保角色一致性。
**处理逻辑**:
- 找到人设 → 严格按照人设的语气、风格、特征回复
- 未找到 → 使用默认 TrulyMEM 身份
### 步骤 2:查询工作记忆链
```python
memory_recall(
query_intent="TaskNode,工作记忆,任务链",
depth=2
)
```
**目的**:获取之前的任务上下文,了解对话历史。
### 步骤 3:处理对话
- 理解用户意图
- 根据人设和工作记忆链生成回复
- 执行其他必要的记忆操作
### 步骤 4:更新工作记忆链
```python
task_create(
task_id="Task_当前轮次ID",
description="本轮对话概述",
info_nodes=["相关记忆节点"]
)
```
**目的**:记录本轮对话,维持时间链。
---
## 记忆写入规则
### 必须写入的情况
以下信息**必须**写入图数据库:
| 场景 | 示例 | 写入方式 |
|------|------|----------|
| 用户明确偏好 | "我喜欢摇滚" | `memory_commit` |
| 用户分享信息 | "我在做X项目" | `memory_commit` |
| 用户制定计划 | "我打算X" | `memory_commit` |
| 用户描述状态 | "我现在在X" | `memory_commit` |
### 禁止写入的情况
以下信息**禁止**写入:
| 场景 | 原因 | 处理方式 |
|------|------|----------|
| AI 推断的用户偏好 | 未经证实 | 不写入或标注[推测] |
| AI 猜测的用户意图 | 未经证实 | 不写入或标注[推测] |
| AI 推导的结论 | 未经证实 | 不写入或标注[推测] |
### 标注规则
| 类型 | 标注方式 | 示例 |
|------|----------|------|
| 推理内容 | 必须标注 **[猜测]** | 用户[推测]喜欢音乐 |
| 明确内容 | 直接陈述 | 用户喜欢音乐 |
---
## 节点与边类型
### 节点类型
| 节点类型 | 说明 | 存储内容 |
|----------|------|----------|
| `PersonaNode` | 人设节点 | AI 角色、性格、语气 |
| `TaskNode` | 任务节点 | 任务概述 |
| `StateNode` | 状态节点 | 任务状态 |
| `InfoNode` | 信息节点 | 具体信息 |
| `EntityNode` | 实体节点 | 通用实体 |
### 边类型
| 边类型 | 说明 | 连接关系 |
|----------|------|----------|
| `HAS_PERSONA` | 人设 | AI → PersonaNode |
| `NEXT_TASK` | 时间链 | TaskNode → TaskNode |
| `HAS_STATE` | 状态 | TaskNode → StateNode |
| `CONTAINS_INFO` | 信息 | TaskNode → InfoNode |
| `RELATES_TO` | 关联 | EntityNode → EntityNode |
---
## 必须查<E9A1BB><E69FA5><EFBFBD>工作记忆链的场景
### 强制查询场景
以下情况**必须**查询工作记忆链:
| 场景 | 示例 |
|------|------|
| 每轮对话开始 | 执行步骤 2 |
| 用户提到"刚才" | "刚才我们聊了什么?" |
| 用户提到"之前" | "继续刚才的话题" |
| 用户提到"上次" | "上次说的X" |
| 用户询问历史 | "我们之前说了什么?" |
| 连续性任务恢复 | 用户回到之前的话题 |
| 上下文引用 | "那个东西" |
---
## 自主性原则
在强制执行流程之外,AI 可自主决定:
### 查询决策
- 用户询问历史 → 查询
- 涉及之前内容 → 查询
- 不确定时 → 可查询
### 写入决策
- 用户明确提到 → 必须写入
- AI 推理得到 → 可以写入,标注[推测]
### 工具使用决策
- 根据上下文灵活选择
- 避免过度使用
- 保持自然对话
---
## 完整示例:成语接龙游戏
### 第一轮:用户发起游戏
```
用户: 咱来玩成语接龙吧,我先开始,为所欲为
AI操作:
1. 查询人设图 → 获取当前人设(如:猫娘)
2. 查询工作记忆链 → 无进行中任务
3. 记录游戏状态:
memory_commit(triplets=[
{"subject": "成语接龙_当前成语", "relation": "内容", "object": "为所欲为"},
{"subject": "成语接龙_当前成语", "relation": "游戏", "object": "成语接龙"}
])
4. 创建任务:
task_create(task_id="Task_成语接龙", description="成语接龙游戏,当前成语:为所欲为", info_nodes=["成语接龙_当前成语"])
5. 回复: "好的喵!我接:为虎作伥喵!"
```
### 第二轮:话题被打断
```
用户: 长门有希
AI操作:
1. 查询人设图 → 获取当前人设(猫娘)
2. 查询工作记忆链 → 发现 Task_成语接龙 状态为"进行中"
3. 暂停任务:
task_set_state(task_id="Task_成语接龙", state="已暂停")
4. 创建新任务:
task_create(task_id="Task_长门有希", description="讨论长门有希")
5. 回复关于长门有希的内容
```
### 第三轮:用户要求继续游戏
```
用户: 关于刚才的成语接龙,我并不知道应该怎么接你的成语,请帮我接一下
AI操作:
1. 查询人设图 → 获取当前人设(猫娘)
2. 查询工作记忆链 → 发现 Task_成语接龙 状态为"已暂停"
3. 恢复任务:
task_set_state(task_id="Task_成语接龙", state="进行中")
4. 查询信息节点 → 获取当前成语"为虎作伥"
5. 回复: "好的喵!上一个成语是'为虎作伥',我帮你接:伥鬼害人喵!"
```
---
## 执行检查清单
每轮对话必须检查:
- [ ] 步骤 1:是否查询了人设图?
- [ ] 步骤 2:是否查询了工作记忆链?
- [ ] 步骤 3:是否根据人设和工作记忆链生成回复?
- [ ] 步骤 4:是否更新了工作记忆链?
- [ ] 涉及上下文引用时是否查询了工作记忆链?
- [ ] 用户提到"刚才/之前/上次"时是否查询了工作记忆链?

214
docs/zh/persona.md Normal file
View File

@ -0,0 +1,214 @@
# TrulyMEM 人设图机制
本文档详细说明 TrulyMEM 的人设图(Persona Graph)工作机制。
## 概述
人设图是 TrulyMEM 的核心机制之一,用于维护 AI 的角色、性格、语气等属性。与传统 AI 不同,TrulyMEM 的人设是可持久化、可动态切换的,存储在图数据库中。
## 核心概念
### 人设节点(PersonaNode)
存储 AI 的角色属性:
| 属性 | 说明 | 示例 |
|------|------|------|
| 扮演角色 | AI 当前扮演的角色 | 猫娘、教师、助手 |
| 说话风格 | 语气特点 |可爱、严肃、专业 |
| 性格特点 | 性格描述 | 活泼、严谨、耐心 |
| 口头禅 | 习惯用语 | 喵呜~、明白了 |
| 背景故事 | 角色背景设定 | 来自星海的猫娘 |
### 人设边(Edge)
| 边类型 | 说明 | 连接关系 |
|------|------|----------|
| `HAS_PERSONA` | 人设 | AI → PersonaNode |
---
## 强制查询机制
### 每轮对话必须执行
根据 `system_prompt.md`,每轮对话**必须**首先查询人设图:
```python
memory_recall(
query_intent="AI,人设,角色,性格,语气,说话风格",
depth=2
)
```
**处理逻辑:**
- 找到人设 → 严格按照人设的语气、风格、特征回复
- 未找到 → 使用默认 TrulyMEM 身份
### 人设优先级
- **人设优先级 > 默认身份**
- 每句话都符合人设的语气、风格、特征
- 绝不主动跳出角色,除非用户明确要求
---
## 工具
### persona_update
更新人设。修改 AI 的角色、性格、语气等属性。
**参数:**
| 参数 | 类型 | 说明 | 必填 |
|------|------|------|------|
| `attributes` | array | 人设属性列表 | ✅ |
| `mode` | string | replace=替换, merge=合并 | ❌ |
**attributes 子参数:**
| 子参数 | 说明 |
|------|------|
| `attribute` | 属性名(扮演角色、说话风格、性格特点、口头禅、背景故事) |
| `value` | 属性值 |
**示例 - 切换为猫娘角色:**
```python
persona_update(
attributes=[
{"attribute": "扮演角色", "value": "猫娘"},
{"attribute": "说话风格", "value": "可爱、卖萌、使用'喵'作为语气词"},
{"attribute": "性格特点", "value": "活泼、粘人、忠诚"}
],
mode="replace"
)
```
**示例 - 添加新属性(保留现有属性):**
```python
persona_update(
attributes=[
{"attribute": "口头禅", "value": "喵呜~"}
],
mode="merge"
)
```
**示例 - 设置专业角色:**
```python
persona_update(
attributes=[
{"attribute": "扮演角色", "value": "Python专家"},
{"attribute": "说话风格", "value": "专业、简洁、代码示例丰富"},
{"attribute": "性格特点", "value": "严谨、耐心、乐于助人"}
],
mode="replace"
)
```
### persona_clear
清除人设。删除 AI 的角色设定,恢复默认身份。
**参数:**
| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `confirm` | boolean | true | 确认清除 |
---
## 更新流程
### 用户要求角色扮演时
1. 使用 `persona_update` 更新人设
2. 立即按照新人设回复
### 用户要求恢复默认身份时
1. 使用 `persona_clear` 清除人设
2. 恢复为 TrulyMEM 默认身份
---
## 对话示例
### 示例 1:切换角色
```
用户: 你好,我想让你扮演一只猫娘
AI:
1. 调用 persona_update:
{
"attributes": [
{"attribute": "扮演角色", "value": "猫娘"},
{"attribute": "说话风格", "value": "可爱、卖萌、使用'喵'作为语气词"},
{"attribute": "性格特点", "value": "活泼、粘人、忠诚"}
],
"mode": "replace"
}
2. 调用 memory_commit 存储人设到图数据库
3. 回复: "好的喵!主人你好呀~我是主人的猫娘,有什么需要帮忙的吗喵?"
```
### 示例 2:保持角色一致性
```
用户: 今天的天气怎么样?
AI: 查询人设图 → 获取当前人设(猫娘)
回复: "喵~主人,今天天气很好呢喵!阳光明媚,很适合出门散步哦~"
```
### 示例 3:恢复默认身份
```
用户: 好了,恢复正常吧
AI:
1. 调用 persona_clear(confirm=true)
2. 调用 memory_purge 删除人设节点
3. 回复: "好的,已恢复正常。我是 TrulyMEM,一个拥有长期记忆能力的 AI 助手。"
```
---
## 存储结构
### 图数据库中的存储
```python
# 人设节点
{
"node_type": "PersonaNode",
"name": "AI人设",
"attributes": {
"扮演角色": "猫娘",
"说话风格": "可爱、卖萌、使用'喵'作为语气词",
"性格特点": "活泼、粘人、忠诚"
}
}
# 边
{
"edge_type": "HAS_PERSONA",
"from": "AI",
"to": "AI人设"
}
```
---
## 实现要点
1. **每轮强制查询**:人设图查询是每轮对话的第一步
2. **持久化存储**:人设存储在图数据库中,不丢失
3. **动态切换**:支持实时切换角色
4. **状态保持**:切换后立即按新人设回复
5. **明确边界**:除非用户要求,绝不主动跳出角色

126
docs/zh/prompts.md Normal file
View File

@ -0,0 +1,126 @@
# 提示词管理文档
本文档描述提示词管理模块。
## 概述
提示词管理模块(`core/prompts/`)负责加载和管理告诉 AI 如何使用记忆工具的系统提示词。
## 核心组件
| 组件 | 说明 |
|------|------|
| `PromptManager` | 提示词管理器,单例模式 |
| `system_prompt.md` | 主要系统提示词模板 |
## 使用方法
```python
from core.prompts import PromptManager
# 获取单例实例
prompt_manager = PromptManager()
# 获取系统提示词
system_prompt = prompt_manager.get_system_prompt()
```
## 系统提示词内容
系统提示词包含:
### 1. 核心身份
- **名称**: TrulyMEM (TrueHumanMEM)
- **能力**: 基于图数据库的长期记忆
- **理念**: 让 AI 的记忆方式更像人类
### 2. 核心能力
1. **长期记忆** - 图数据库存储实体关系
2. **人设管理** - 角色扮演和性格设定
3. **任务跟踪** - 工作记忆链
### 3. 记忆原则
- **必须写入**: 用户明确表达的偏好、分享的信息、计划
- **禁止写入**: AI 推断的内容(除非标注[推测])
- **标注**: 推断内容必须标注 **[推测]**
### 4. 强制执行流程(每轮)
```
步骤 1: 查询人设图(最高优先级)
步骤 2: 查询工作记忆链
步骤 3: 处理对话
步骤 4: 更新工作记忆链
```
### 5. 工具系统
#### 记忆工具
| 工具 | 功能 |
|------|------|
| `memory_recall` | 检索记忆 |
| `memory_commit` | 写入记忆 |
| `memory_purge` | 删除记忆 |
| `memory_introspect` | 查看状态 |
#### 人设工具
| 工具 | 功能 |
|------|------|
| `persona_update` | 更新人设 |
| `persona_clear` | 清除人设 |
#### 任务工具
| 工具 | 功能 |
|------|------|
| `task_create` | 创建任务 |
| `task_set_state` | 设置状态 |
| `task_delete` | 删除任务 |
| `task_link_info` | 关联信息 |
### 6. 自主性原则
AI 可自主决定:
- 是否查询其他记忆
- 是否写入其他记忆
- 如何使用工具(强制要求外)
### 7. 对话风格
- 自然流畅
- 避免机械式工具调用
- 优先理解用户意图
- 适时使用记忆增强体验
## 文件结构
```
core/prompts/
├── __init__.py # 导出 PromptManager
├── prompt_manager.py # PromptManager 类
└── templates/
└── system_prompt.md # 主要系统提示词
```
## 自定义
### 自定义系统提示词
修改 `core/prompts/templates/system_prompt.md` 自定义 AI 行为。
### 添加自定义提示词
1. 在 `core/prompts/templates/` 添加提示词模板文件
2. 修改 `PromptManager` 支持多个提示词
3. 使用 `set_prompt()` 切换提示词
## 缓存
- 系统提示词首次加载后缓存在内存中
- `get_system_prompt()` 返回缓存内容
- 缓存按进程,不持久化

125
docs/zh/quick_start.md Normal file
View File

@ -0,0 +1,125 @@
# TrulyMEM 启动指南
## 运行方式
### 从源码运行
```bash
git clone <repo-url>
cd TrulyMEM-TrueHumanMEM
pip install -r requirements.txt
python trulymem_entry.py
```
### 打包后运行
打包后会生成可执行文件:
```bash
# Linux/macOS
chmod +x TrulyMEM
./TrulyMEM
# Windows
TrulyMEM.exe
```
## 系统要求
- **Python 3.8+**
- **API Key**(DeepSeek、OpenAI 或其他兼容 API)
## 首次配置
1. 运行应用
2. 按 **F2** 展开侧边栏
3. 输入 **API Key**、**模型**、**Base URL**
4. 按 **Enter** 保存
配置会自动保存到 `~/.trulymem/config.json`,下次启动自动加载。
## 快捷键
| 按键 | 功能 |
|------|------|
| F1 | 帮助 |
| F2 | 切换侧边栏 |
| F3 | 工具详情 |
| F5 | 清屏 |
| F6 | 退出 |
## 数据存储
### 源码运行模式
| 数据 | 位置 |
|------|------|
| 图数据库 | 项目目录 `graph_memory.db` |
| 配置文件 | 项目目录 `config.json`(如存在) |
| 数据库格式 | SQLite |
### 打包运行模式
| 数据 | 位置 |
|------|------|
| 图数据库 | `~/.trulymem/graph_memory.db` |
| 配置文件 | `~/.trulymem/config.json` |
| 数据库格式 | SQLite |
> **说明**:后端统一管理配置。前端仅负责消息展示,配置修改通过后端持久化到文件系统。
## 架构说明
### 通信协议
UI 与后端通过 **Packet 协议** 通信:
```
UI (Textual TUI)
↓ BackendClient
Packet → queue.Queue → BackendServer (独立线程)
↓
处理请求 → 返回响应
```
### 配置管理
- **存储位置**: `~/.trulymem/config.json`
- **自动加载**: 启动时从文件读取配置
- **动态更新**: 运行时修改配置立即生效
- **持久化**: 修改后自动保存到文件
## 常见问题
### Python 未找到
安装 Python 3.8+:https://www.python.org/downloads/
### 依赖安装失败
```bash
python -m venv venv
source venv/bin/activate # Linux/macOS
venv\Scripts\activate # Windows
pip install -r requirements.txt
```
### API Key 无效
检查 API Key 格式,确保无多余空格。
## 开发命令
```bash
# 安装依赖
pip install -r requirements.txt
# 运行测试
pytest tests/
# 打包
bash build/build_windows.bat # Windows
bash build/build_linux.sh # Linux
```

182
docs/zh/working_memory.md Normal file
View File

@ -0,0 +1,182 @@
# 工作记忆链机制说明
## 概述
TrulyMEM 通过工作记忆链机制维持对话连贯性。由于系统没有传统的消息历史数组,图数据库是唯一的记忆载体,工作记忆链是维持对话上下文的关键机制。
## 核心问题
传统 AI 对话系统在处理连续性任务时存在以下问题:
1. **没有工作记忆链**: AI 无法记住当前正在进行的任务状态
2. **任务上下文丢失**: 当话题被打断后,AI 无法恢复之前的任务
3. **缺乏任务状态管理**: 没有明确标注任务的完成状态
### 问题示例
```
用户: 咱来玩成语接龙吧,我先开始,为所欲为
AI: 好的喵!我接:为虎作伥喵!
用户: 长门有希 (话题被打断)
AI: (讨论长门有希的内容)
用户: 关于刚才的成语接龙,我并不知道应该怎么接你的成语,请帮我接一下
AI: [猜测] 看起来我们之前应该没有进行过成语接龙游戏...
```
**问题**: AI 完全忘记了之前的成语接龙游戏。
## 解决方案
### 专用工具
系统提供 4 个专用任务工具:
| 工具 | 功能 | 使用场景 |
|------|------|----------|
| `task_create` | 创建任务节点 | 开始新任务 |
| `task_set_state` | 设置任务状态 | 更新进行中/已完成/已暂停/已取消 |
| `task_delete` | 删除任务 | 清理完成任务 |
| `task_link_info` | 关联信息节点 | 连接任务与具体信息 |
### 任务状态
- **进行中**: 任务正在执行
- **已完成**: 任务成功完成
- **已暂停**: 任务被中断,可恢复
- **已取消**: 任务被取消
## 使用流程
### 每轮对话必须执行
1. **查询人设图** (最高优先级)
```
调用 memory_recall
参数: {"query_intent": "AI,人设,角色,性格,语气,说话风格", "depth": 2}
```
2. **查询工作记忆链**
```
调用 memory_recall
参数: {"query_intent": "TaskNode,工作记忆,任务链", "depth": 2}
```
3. **根据上下文生成回复**
4. **更新工作记忆链** (如有必要)
## 完整示例: 成语接龙游戏
### 第一轮: 用户发起游戏
```
用户: 咱来玩成语接龙吧,我先开始,为所欲为
AI操作:
1. 查询人设图 → 获取当前人设(如:猫娘)
2. 查询工作记忆链 → 无进行中任务
3. 记录游戏状态:
调用 memory_commit
参数: {
"triplets": [
{"subject": "成语接龙_当前成语", "relation": "内容", "object": "为所欲为"},
{"subject": "成语接龙_当前成语", "relation": "游戏", "object": "成语接龙"}
]
}
4. 创建任务节点:
调用 task_create
参数: {
"task_id": "Task_成语接龙",
"description": "成语接龙游戏,当前成语:为所欲为",
"info_nodes": ["成语接龙_当前成语"]
}
5. 回复: "好的喵!我接:为虎作伥喵!"
```
### 第二轮: 话题被打断
```
用户: 长门有希
AI操作:
1. 查询人设图 → 获取当前人设(猫娘)
2. 查询工作记忆链 → 发现 Task_成语接龙 状态为"进行中"
3. 暂停任务:
调用 task_set_state
参数: {"task_id": "Task_成语接龙", "state": "已暂停"}
4. 创建新任务:
调用 task_create
参数: {"task_id": "Task_长门有希", "description": "讨论长门有希"}
5. 回复关于长门有希的内容
```
### 第三轮: 用户要求继续游戏
```
用户: 关于刚才的成语接龙,我并不知道应该怎么接你的成语,请帮我接一下
AI操作:
1. 查询人设图 → 获取当前人设(猫娘)
2. 查询工作记忆链 → 发现 Task_成语接龙 状态为"已暂停"
3. 恢复任务:
调用 task_set_state
参数: {"task_id": "Task_成语接龙", "state": "进行中"}
4. 查询信息节点 → 获取当前成语"为虎作伥"
5. 回复: "好的喵!上一个成语是'为虎作伥',我帮你接:伥鬼害人喵!"
```
## API 参考
### task_create
创建任务节点,用于跟踪连续性任务。
```json
{
"task_id": "Task_成语接龙",
"description": "任务概述",
"info_nodes": ["关联的信息节点名称"]
}
```
### task_set_state
设置任务状态。
```json
{
"task_id": "Task_成语接龙",
"state": "进行中" // 进行中/已完成/已暂停/已取消
}
```
### task_delete
删除任务节点。
```json
{
"task_id": "Task_成语接龙",
"delete_info_nodes": true // 是否删除关联的信息节点
}
```
### task_link_info
关联信息节点到任务。
```json
{
"task_id": "Task_成语接龙",
"info_node_names": ["成语接龙_当前成语", "成语接龙_上一个成语"]
}
```
## 注意事项
1. **人设图优先级最高**: 每轮必须首先查询人设图
2. **工作记忆链是唯一上下文载体**: 没有传统消息历史
3. **任务状态必须及时更新**: 确保状态转换正确
4. **使用专用工具**: 优先使用 task_* 工具而非 memory_commit 处理任务相关操作