mirror of
https://gitcode.com/JianFeeeee/TrulyMEM-TrueHumanMEM.git
synced 2026-10-15 12:15:32 +00:00
docs: 重构为 docs/zh/ + docs/en/ 子文件夹结构
- 拆分为 docs/zh/(中文) 和 docs/en/(英文) - README 索引对应语言子文件夹 - 保留所有文档内容
This commit is contained in:
29
docs/zh/README.md
Normal file
29
docs/zh/README.md
Normal 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
464
docs/zh/api.md
Normal 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
180
docs/zh/architecture.md
Normal 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
237
docs/zh/memory.md
Normal 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
214
docs/zh/persona.md
Normal 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
126
docs/zh/prompts.md
Normal 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
125
docs/zh/quick_start.md
Normal 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
182
docs/zh/working_memory.md
Normal 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 处理任务相关操作
|
||||
Reference in New Issue
Block a user