docs: 添加双语文档与记忆机制说明

新增文件:
- README_EN.md (English README)
- docs/记忆机制.md + _EN.md (记忆工作机制)
- docs/架构_EN.md
- docs/一键启动指南_EN.md
- docs/工作记忆链_EN.md
- docs/api_EN.md
- docs/prompts.md + _EN.md

docs/README.md 更新为双语文档索引
This commit is contained in:
root
2026-04-14 13:15:37 +08:00
parent f65f1ca3c1
commit 44c332bfe1
11 changed files with 1826 additions and 5 deletions

View File

@ -4,10 +4,25 @@
## 文档目录
- [架构设计](架构.md) - 系统架构和技术设计
- [快速开始](一键启动指南.md) - 一键启动指南
- [工作记忆链机制说明](工作记忆链机制说明.md) - 连续性任务处理
- [BackendServer API](api.md) - 后端 API 接口文档(供扩展开发)
| 文档 | 内容 |
|------|------|
| [架构设计](架构.md) | 系统架构和技术设计 |
| [快速开始](一键启动指南.md) | 完整启动指南与配置说明 |
| [记忆机制](记忆机制.md) | 内部记忆工作机制、人设图、工作记忆链 |
| [工作记忆链](工作记忆链机制说明.md) | 连续性任务处理机制 |
| [BackendServer API](api.md) | 后端 API 接口文档(供扩展开发) |
| [提示词管理](prompts.md) | 提示词管理模块 |
## English Documentation
| Document | Content |
|----------|---------|
| [Architecture](架构_EN.md) | System architecture and technical design |
| [Quick Start](一键启动指南_EN.md) | Complete startup guide and configuration |
| [Memory Mechanism](记忆机制_EN.md) | Internal memory working mechanism |
| [Working Memory Chain](工作记忆链_EN.md) | Continuous task handling |
| [BackendServer API](api_EN.md) | Backend API reference |
| [Prompt Manager](prompts_EN.md) | Prompt management module |
## 项目简介
@ -21,4 +36,4 @@ TrulyMEM (TrueHumanMEM) 是一个让 AI 拥有长期记忆能力的图记忆系
- **TUI 与后端分离**: 多线程 Queue 通信
- **键盘驱动 TUI**: 无需鼠标,全键盘操作
- **跨平台支持**: Windows / Linux / macOS
- **独立部署**: 支持打包为可执行文件
- **独立部署**: 支持打包为可执行文件

40
docs/README_EN.md Normal file
View File

@ -0,0 +1,40 @@
# TrulyMEM Documentation
Welcome to the TrulyMEM project documentation.
## Documentation Index
- [Architecture](架构_EN.md) - System architecture and technical design
- [Quick Start](一键启动指南_EN.md) - Quick start guide
- [Memory Mechanism](记忆机制_EN.md) - Internal memory working mechanism
- [Working Memory Chain](工作记忆链_EN.md) - Continuous task handling
- [BackendServer API](api_EN.md) - Backend API reference (for extension development)
- [Prompt Manager](prompts_EN.md) - Prompt management module
## Project Introduction
TrulyMEM (TrueHumanMEM) is a graph-based memory system that gives AI long-term memory capabilities, allowing AI to remember, recall, and manage information like humans.
## Core Features
- **Long-term Memory**: SQLite embedded graph database, out-of-the-box
- **Persona Graph**: Role-playing and character settings support
- **Working Memory Chain**: Task tracking for conversation continuity
- **TUI & Backend Separation**: Multi-threaded Queue communication
- **Keyboard-driven TUI**: Full keyboard operation, no mouse required
- **Cross-platform**: Windows / Linux / macOS
- **Standalone Deployment**: Packaged as executable
---
## Story
Industry believes that LLMs' massive parameters give them emergent intelligence. But this intelligence is "dead" — it cannot truly remember, nor understand the concept of "remembering". Everything it outputs is the probabilistic optimal solution calculated through countless forward passes on the current input text. The LLM cannot correct its weights based on errors in a conversation, nor perform backward passes. Its consciousness is frozen — what appears as intelligence is merely the echo of this frozen consciousness.
Current "memory systems" merely externalize memory, letting the "system" remember for the LLM. Or they dump all context text to the LLM. This is a waste of the model's limited input context.
**TrulyMEM asks: since the LLM cannot correct model weights in real-time, why not give the memory authority back to the LLM?**
We provide a series of mechanisms for the LLM to decide what to remember, what to forget, what's important, what's trivial. The LLM's reasoning process is also its thinking and recalling process. Abandoning the traditional messages array context, all memories are stored as **triplets (graph)** in the graph database. When the LLM thinks, it can autonomously jump through graph links to associate related relationships, enabling natural association and recall.
Give the LLM true memory.

449
docs/api_EN.md Normal file
View File

@ -0,0 +1,449 @@
# BackendServer API Documentation
This document describes the backend server's API interfaces for developers extending other connection methods (such as HTTP interface, WebSocket, etc.).
## Overview
TrulyMEM backend uses **Packet Communication Protocol**, implemented via `queue.Queue` for thread-safe communication. The backend runs in an independent thread, processing requests from clients.
### Core Components
| Component | Description |
|-----------|-------------|
| `BackendServer` | Backend server, runs in independent thread |
| `BackendClient` | Client wrapper, provides convenient methods |
| `PacketType` | Request type enum |
| `Packet` | Data packet (request) |
| `PacketResponse` | Data packet response |
---
## Request Types (PacketType)
```python
class PacketType(Enum):
PROCESS_MESSAGE = "process_message" # Process message
EXECUTE_TOOL = "execute_tool" # Execute tool
GET_STATUS = "get_status" # Get status
GET_CONFIG = "get_config" # Get config
SET_CONFIG = "set_config" # Set config
GET_HISTORY = "get_history" # Get history
SAVE_HISTORY = "save_history" # Save history
SHUTDOWN = "shutdown" # Shutdown service
```
---
## Data Packet Format
### Packet
```python
@dataclass
class Packet:
id: str # Unique identifier
type: PacketType # Request type
body: Dict[str, Any] # Request parameters
response_queue: queue.Queue # Response queue (optional)
created_at: float # Creation time
```
### PacketResponse
```python
@dataclass
class PacketResponse:
id: str # Corresponding request ID
success: bool # Success flag
data: Any = None # Returned data
error: Optional[str] = None # Error message
```
---
## API Interface Details
### 1. PROCESS_MESSAGE - Process Message
Send user message, AI will process and return reply (may contain tool calls).
**Request parameters:**
```python
body = {
"user_input": str # User input message
}
```
**Response data:**
```python
{
"success": True,
"content": str, # AI reply content
"tool_calls": [ # Tool call records
{
"name": str, # Tool name
"arguments": dict,# Tool parameters
"result": str # Tool execution result
}
],
"rejected_tools": [ # Rejected tool calls
(str, str) # (tool name, rejection reason)
]
}
```
**Example:**
```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("Hello, please remember my name is Xiao Ming")
if result.get("success"):
print(result["content"])
```
---
### 2. EXECUTE_TOOL - Execute Tool
Directly execute specified memory tools.
> **Note**: Tools called directly from frontend are **NOT limited** in number, only tool calls initiated by the model are limited.
**Request parameters:**
```python
body = {
"tool_name": str, # Tool name
"arguments": dict # Tool parameters
}
```
**Response data:**
```python
{
"success": True,
"result": str # Tool execution result
}
```
**Example:**
```python
result = client.execute_tool("memory_recall", {"query_intent": "user information"})
```
---
### 3. GET_STATUS - Get Status
Get backend running status.
**Request parameters:**
```python
body = {} # No parameters
```
**Response data:**
```python
{
"running": bool, # Whether backend is running
"config": dict, # Current config
"graph_initialized": bool, # Whether graph database is initialized
"client_initialized": bool # Whether API client is initialized
}
```
---
### 4. GET_CONFIG - Get Config
Get current API configuration.
**Request parameters:**
```python
body = {} # No parameters
```
**Response data:**
```python
{
"api_key": str, # API Key
"base_url": str # API Base URL
}
```
---
### 5. SET_CONFIG - Set Config
Update API configuration (API Key and Base URL).
**Request parameters:**
```python
body = {
"api_key": str, # API Key
"base_url": str, # API Base URL (default: https://api.deepseek.com)
"model": str # Model name (default: deepseek-chat)
}
```
**Response data:**
```python
{
"status": "config_updated"
}
```
---
### 6. GET_HISTORY - Get Message History
Get saved message history.
**Request parameters:**
```python
body = {} # No parameters
```
**Response data:**
```python
{
"history": list # Message history list
}
```
---
### 7. SAVE_HISTORY - Save Message History
Save message history to memory.
**Request parameters:**
```python
body = {
"messages": list # Message list
}
```
**Response data:**
```python
{
"status": "history_saved"
}
```
---
### 8. SHUTDOWN - Shutdown Service
Shutdown backend server.
**Request parameters:**
```python
body = {} # No parameters
```
**Response data:**
```python
{
"status": "shutdown"
}
```
---
## Usage Examples
### Basic Usage
```python
from core import BackendServer, BackendClient
# 1. Create and start backend
# config_file default: ~/.trulymem/config.json
server = BackendServer(
db_path="graph_memory.db",
use_embedded_db=True,
config_file=None # Optional, custom config path
)
server.start(
api_key="your-api-key",
base_url="https://api.deepseek.com",
model="deepseek-chat" # Optional, model name
)
# 2. Create client
client = BackendClient(server)
# 3. Send message
result = client.process_message("Hello")
if result.get("success"):
print(result["content"])
# 4. Shutdown
client.shutdown()
```
### Using Packet Protocol
```python
import queue
from core import BackendServer, Packet, PacketType
server = BackendServer(config_file=None)
server.start(api_key="your-key", model="deepseek-chat")
# Create request packet
response_queue = queue.Queue()
packet = Packet(
id="req-001",
type=PacketType.PROCESS_MESSAGE,
body={"user_input": "Hello"},
response_queue=response_queue
)
# Send request
result = server.send(packet)
print(result.body)
# Shutdown
server.shutdown()
```
---
## Extension Guide
### Extend to 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)
```
### Extend to 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())
```
---
## Thread Safety Notes
- `BackendServer` uses `threading.Lock` to protect shared resources
- All requests pass through `queue.Queue`, thread-safe
- Responses return through each request's independent response queue
- Default timeout: 30 seconds
---
## Tool Call Limits
### Limit Scope
| Call Method | Limited | Description |
|-------------|---------|-------------|
| Model-initiated tool calls | ✅ Limited | Triggered via `PROCESS_MESSAGE`, model automatically calls tools |
| Frontend direct tool calls | ❌ Not limited | Called directly via `EXECUTE_TOOL` |
### Limit Rules (Model-initiated only)
| Category | Operation | Per-Turn Limit |
|----------|-----------|---------------|
| Persona graph | Query | 1 time |
| Persona graph | Modify | 1 time |
| Working memory chain | Query | 4 times |
| Working memory chain | Modify | 2 times |
| General memory | Query | 20 times |
| General memory | Modify | 10 times |
### Reset Mechanism
- Counter resets automatically on each `PROCESS_MESSAGE` call
- Frontend direct `EXECUTE_TOOL` calls do NOT reset the counter
---
## Error Handling
All APIs return unified format:
```python
# Success
{
"success": True,
"data": {...}
}
# Failure
{
"success": False,
"error": "Error description"
}
```
Common errors:
| Error Message | Description |
|--------------|-------------|
| `API Key not configured` | API Key not set |
| `timeout` | Request timeout |
| `Tool call rejected: ...` | Tool call rate exceeded limit |

126
docs/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()` 返回缓存内容
- 缓存按进程,不持久化

126
docs/prompts_EN.md Normal file
View File

@ -0,0 +1,126 @@
# Prompt Manager Documentation
This document describes the prompt management module.
## Overview
The prompt management module (`core/prompts/`) is responsible for loading and managing system prompts that tell the AI how to use memory tools.
## Core Components
| Component | Description |
|-----------|-------------|
| `PromptManager` | Prompt manager, singleton pattern |
| `system_prompt.md` | Main system prompt template |
## Usage
```python
from core.prompts import PromptManager
# Get singleton instance
prompt_manager = PromptManager()
# Get system prompt
system_prompt = prompt_manager.get_system_prompt()
```
## System Prompt Content
The system prompt contains:
### 1. Core Identity
- **Name**: TrulyMEM (TrueHumanMEM)
- **Capability**: Long-term memory based on graph database
- **Philosophy**: Make AI's memory more human-like
### 2. Core Capabilities
1. **Long-term Memory** - Graph database stores entity relationships
2. **Persona Management** - Role-playing and character settings
3. **Task Tracking** - Working memory chain
### 3. Memory Principles
- **Must write**: User-explicit preferences, shared information, plans
- **Must not write**: AI-inferred content (unless marked [speculation])
- **Annotation**: Inferred content must be marked **[speculation]**
### 4. Mandatory Execution Flow (Per Turn)
```
Step 1: Query persona graph (highest priority)
Step 2: Query working memory chain
Step 3: Process conversation
Step 4: Update working memory chain
```
### 5. Tool System
#### Memory Tools
| Tool | Function |
|------|----------|
| `memory_recall` | Retrieve memory |
| `memory_commit` | Write memory |
| `memory_purge` | Delete memory |
| `memory_introspect` | View status |
#### Persona Tools
| Tool | Function |
|------|----------|
| `persona_update` | Update persona |
| `persona_clear` | Clear persona |
#### Task Tools
| Tool | Function |
|------|----------|
| `task_create` | Create task |
| `task_set_state` | Set state |
| `task_delete` | Delete task |
| `task_link_info` | Link information |
### 6. Autonomy Principles
The AI can autonomously decide:
- Whether to query other memories
- Whether to write other memories
- How to use tools (outside mandatory requirements)
### 7. Conversation Style
- Natural and smooth
- Avoid mechanical tool calls
- Prioritize understanding user intent
- Use memory to enhance experience when appropriate
## File Structure
```
core/prompts/
├── __init__.py # Export PromptManager
├── prompt_manager.py # PromptManager class
└── templates/
└── system_prompt.md # Main system prompt
```
## Customization
### Customizing System Prompt
Modify `core/prompts/templates/system_prompt.md` to customize the AI's behavior.
### Adding Custom Prompts
1. Add prompt template file to `core/prompts/templates/`
2. Modify `PromptManager` to support multiple prompts
3. Use `set_prompt()` to switch prompts
## Caching
- System prompts are cached in memory after first load
- `get_system_prompt()` returns cached content
- Cache is per-process, not persisted

View File

@ -0,0 +1,125 @@
# TrulyMEM Quick Start Guide
## Running Methods
### Run from Source
```bash
git clone <repo-url>
cd TrulyMEM-TrueHumanMEM
pip install -r requirements.txt
python trulymem_entry.py
```
### Run After Build
After building, an executable will be generated:
```bash
# Linux/macOS
chmod +x TrulyMEM
./TrulyMEM
# Windows
TrulyMEM.exe
```
## System Requirements
- **Python 3.8+**
- **API Key** (DeepSeek, OpenAI, or other compatible APIs)
## First-Time Configuration
1. Run the application
2. Press **F2** to expand sidebar
3. Enter **API Key**, **Model**, **Base URL**
4. Press **Enter** to save
Config will be automatically saved to `~/.trulymem/config.json` and loaded on next startup.
## Keyboard Shortcuts
| Key | Function |
|-----|-----------|
| F1 | Help |
| F2 | Toggle sidebar |
| F3 | Tool details |
| F5 | Clear screen |
| F6 | Exit |
## Data Storage
### Source Mode
| Data | Location |
|------|----------|
| Graph database | Project directory `graph_memory.db` |
| Config file | Project directory `config.json` (if exists) |
| Database format | SQLite |
### Packaged Mode
| Data | Location |
|------|----------|
| Graph database | `~/.trulymem/graph_memory.db` |
| Config file | `~/.trulymem/config.json` |
| Database format | SQLite |
> **Note**: Backend manages config uniformly. Frontend only displays messages; config modifications are persisted to filesystem through the backend.
## Architecture Explanation
### Communication Protocol
UI and backend communicate via **Packet Protocol**:
```
UI (Textual TUI)
↓ BackendClient
Packet → queue.Queue → BackendServer (independent thread)
Process request → Return response
```
### Config Management
- **Storage location**: `~/.trulymem/config.json`
- **Auto-load**: Load config from file at startup
- **Dynamic update**: Config changes take effect immediately at runtime
- **Persistence**: Auto-save to file after modification
## Common Issues
### Python Not Found
Install Python 3.8+: https://www.python.org/downloads/
### Dependency Installation Failed
```bash
python -m venv venv
source venv/bin/activate # Linux/macOS
venv\Scripts\activate # Windows
pip install -r requirements.txt
```
### Invalid API Key
Check API Key format, ensure no extra spaces.
## Development Commands
```bash
# Install dependencies
pip install -r requirements.txt
# Run tests
pytest tests/
# Build
bash build/build_windows.bat # Windows
bash build/build_linux.sh # Linux
```

182
docs/工作记忆链_EN.md Normal file
View File

@ -0,0 +1,182 @@
# TrulyMEM Working Memory Chain Mechanism
## Overview
TrulyMEM maintains conversation continuity through the working memory chain mechanism. Since there's no traditional message history array, the graph database is the only memory carrier, making the working memory chain the key mechanism for maintaining conversation context.
## Core Problems
Traditional AI chat systems have these problems when handling continuous tasks:
1. **No working memory chain**: AI cannot remember the current task status being processed
2. **Task context lost**: When a topic is interrupted, AI cannot recover the previous task
3. **Lack of task state management**: No clear marking of task completion status
### Problem Example
```
User: Let's play idiom chain! I'll start with 为所欲为
AI: Okay! My turn: 为虎作伥!
User: Nagato Yuki (topic interrupted)
AI: (discusses Nagato Yuki)
User: About the idiom chain just now, I don't know how to connect to your idiom
AI: [Guessing] It seems we haven't played an idiom chain game before...
```
**Problem**: AI completely forgot the previous idiom chain game.
## Solution
### Dedicated Tools
The system provides 4 dedicated task tools:
| Tool | Function | Use Case |
|------|----------|----------|
| `task_create` | Create task node | Start new task |
| `task_set_state` | Set task state | Update in_progress/completed/paused/cancelled |
| `task_delete` | Delete task | Clean up completed task |
| `task_link_info` | Link info node | Connect task with specific information |
### Task States
- **in_progress**: Task is executing
- **completed**: Task completed successfully
- **paused**: Task interrupted, can be resumed
- **cancelled**: Task cancelled
## Usage Flow
### Must Execute Per Turn
1. **Query persona graph** (highest priority)
```
Call memory_recall
Parameters: {"query_intent": "AI,persona,role,character,tone", "depth": 2}
```
2. **Query working memory chain**
```
Call memory_recall
Parameters: {"query_intent": "TaskNode,working_memory,task_chain", "depth": 2}
```
3. **Generate reply based on context**
4. **Update working memory chain** (if necessary)
## Complete Example: Idiom Chain Game
### Turn 1: User starts game
```
User: Let's play idiom chain! I'll start with 为所欲为
AI Actions:
1. Query persona graph → Get current persona (e.g., catgirl)
2. Query working memory chain → No active task
3. Record game state:
Call memory_commit
Parameters: {
"triplets": [
{"subject": "idiom_chain_current", "relation": "content", "object": "为所欲为"},
{"subject": "idiom_chain_current", "relation": "game", "object": "idiom_chain"}
]
}
4. Create task node:
Call task_create
Parameters: {
"task_id": "Task_idiom_chain",
"description": "Idiom chain game, current idiom: 为所欲为",
"info_nodes": ["idiom_chain_current"]
}
5. Reply: "Okay~! My turn: 为虎作伥~!"
```
### Turn 2: Topic interrupted
```
User: Nagato Yuki
AI Actions:
1. Query persona graph → Get current persona (catgirl)
2. Query working memory chain → Found Task_idiom_chain status "in_progress"
3. Pause task:
Call task_set_state
Parameters: {"task_id": "Task_idiom_chain", "state": "paused"}
4. Create new task:
Call task_create
Parameters: {"task_id": "Task_nagato_yuki", "description": "Discuss Nagato Yuki"}
5. Reply about Nagato Yuki
```
### Turn 3: User asks to continue game
```
User: About the idiom chain just now, I don't know how to connect to your idiom
AI Actions:
1. Query persona graph → Get current persona (catgirl)
2. Query working memory chain → Found Task_idiom_chain status "paused"
3. Resume task:
Call task_set_state
Parameters: {"task_id": "Task_idiom_chain", "state": "in_progress"}
4. Query info node → Get current idiom "为虎作伥"
5. Reply: "Okay~! The last idiom was '为虎作伥', your turn: 伥鬼害人~!"
```
## API Reference
### task_create
Create task node to track continuous tasks.
```json
{
"task_id": "Task_idiom_chain",
"description": "Task overview",
"info_nodes": ["associated info node names"]
}
```
### task_set_state
Set task state.
```json
{
"task_id": "Task_idiom_chain",
"state": "in_progress" // in_progress/completed/paused/cancelled
}
```
### task_delete
Delete task node.
```json
{
"task_id": "Task_idiom_chain",
"delete_info_nodes": true // whether to delete associated info nodes
}
```
### task_link_info
Associate info nodes to task.
```json
{
"task_id": "Task_idiom_chain",
"info_node_names": ["idiom_chain_current", "idiom_chain_last"]
}
```
## Notes
1. **Persona graph has highest priority**: Must query persona graph first each turn
2. **Working memory chain is the only context carrier**: No traditional message history
3. **Task state must be updated timely**: Ensure correct state transitions
4. **Use dedicated tools**: Prefer task_* tools over memory_commit for task-related operations

179
docs/架构_EN.md Normal file
View File

@ -0,0 +1,179 @@
# TrulyMEM Architecture
## Core Principles
- Keyboard-driven, zero mouse dependency
- Minimalist visual, information density priority
- Tool traces hidden by default, expandable when needed
- TUI & backend separation, multi-threaded communication
- **Everything is a graph**, AI reasoning runs entirely in backend
## Project Structure
```
TrulyMEM-TrueHumanMEM/
├── trulymem_entry.py # Entry: start core → then ui
├── core/ # Backend/business logic
│ ├── __init__.py # Export BackendServer, BackendClient, EmbeddedGraphDB
│ ├── server.py # BackendServer (Packet communication protocol)
│ ├── client.py # BackendClient (Packet protocol client)
│ ├── embedded_db.py # SQLite graph database implementation
│ ├── graph_client.py # OpenAI/DeepSeek API client
│ ├── tool_executor.py # Tool executor
│ ├── tool_limiter.py # Tool call limiter
│ ├── tools/ # Tool definitions
│ │ ├── __init__.py
│ │ └── memory_tools.py
│ └── prompts/ # Prompt management
├── ui/ # TUI display layer (display only, no AI logic)
│ ├── __init__.py # Export GraphMemoryApp, AppConfig
│ ├── app.py # GraphMemoryApp (communicates via BackendClient)
│ ├── widgets/ # TUI components
│ ├── handlers/ # Event handlers
│ ├── models/ # Data models
│ ├── services/ # Service layer (config only)
│ └── styles/ # Style files
└── tests/ # Tests (42 tests)
```
## Architecture Diagram
```
trulymem_entry.py
├─ BackendServer.start() → Runs in independent thread
│ ├─ Handle PROCESS_MESSAGE requests → AI reasoning + tool calls
│ ├─ Handle EXECUTE_TOOL requests → External tool calls (unlimited)
│ ├─ Handle GET/SET_CONFIG requests
│ └─ Manage GraphMemoryClient, EmbeddedGraphDB
└─ GraphMemoryApp(backend_server=server)
└─ BackendClient ← Packet communication → BackendServer
```
## Component Responsibilities
### core/ (Backend)
| Component | Responsibility |
|------------|----------------|
| `server.py` | Packet protocol, multi-threaded queue, AI reasoning, tool limits |
| `client.py` | Client wrapper, UI-backend communication bridge |
| `embedded_db.py` | SQLite graph database CRUD |
| `graph_client.py` | OpenAI/DeepSeek API client |
| `tool_executor.py` | Tool execution logic |
| `tool_limiter.py` | Tool call rate limit (AI reasoning only) |
### ui/ (Display Layer)
| Component | Responsibility |
|------------|----------------|
| `app.py` | Textual app main class, communicates via BackendClient |
| `services/` | Config management only, no AI logic |
### Communication Protocol
UI and backend interact via **Packet Communication Protocol**:
```python
from core import BackendServer, BackendClient, Packet, PacketType
# Backend startup
server = BackendServer(db_path="graph_memory.db", use_embedded_db=True)
server.start(api_key="your-key")
# Client communication
client = BackendClient(server)
result = client.process_message("hello") # AI reasoning
result = client.execute_tool("memory_introspect", {}) # Direct tool call
```
---
## Data Flow
```
User input → InputBox → on_input_box_send_message
BackendClient.process_message(user_input)
Packet (type=PROCESS_MESSAGE) → queue.Queue
BackendServer (independent thread)
<20><><EFBFBD>
GraphMemoryClient.send_message_with_history()
OpenAI API / DeepSeek API
execute_tool() + ToolLimiter (limited during AI reasoning)
EmbeddedGraphDB (graph database)
Loop API calls until no tool_calls
Packet response returns
MessageHistory displays
```
---
## Startup Flow
```python
# trulymem_entry.py
def main():
# Config file saved in application root
config_file = application_path / "config.json"
# Load config
config_service = ConfigService(config_file=config_file)
config = config_service.get_config()
# Create backend
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)
# Create UI
app = GraphMemoryApp(backend_server=backend_server, config_service=config_service)
app.run()
backend_server.shutdown()
```
---
## Tool System
### Memory Tools (6)
- `memory_recall` - Retrieve memory
- `memory_commit` - Write memory
- `memory_purge` - Delete memory
- `memory_introspect` - View status
- `memory_archive` - Archive memory
- `memory_cleanup` - Clean data
### Persona Tools (2)
- `persona_update` - Update persona
- `persona_clear` - Clear persona
### Task Tools (4)
- `task_create` - Create task
- `task_set_state` - Set state
- `task_delete` - Delete task
- `task_link_info` - Link information
---
## Error Handling Principle
All APIs **do not throw exceptions**, errors are passed via return dictionary:
```python
result = client.process_message("hello")
if result.get("success"):
print(result["content"])
else:
print(result["error"]) # Error description

237
docs/记忆机制.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是否更新了工作记忆链
- [ ] 涉及上下文引用时是否查询了工作记忆链?
- [ ] 用户提到"刚才/之前/上次"时是否查询了工作记忆链?

237
docs/记忆机制_EN.md Normal file
View File

@ -0,0 +1,237 @@
# TrulyMEM Memory Mechanism
This document explains the internal memory working mechanism of TrulyMEM.
## Core Design Philosophy
### Different from Traditional Context System
Traditional AI chat systems store conversation history in a messages array:
- Each request carries all historical messages
- Context grows with conversation turns
- Eventually triggers memory compression or sliding window, causing memory loss
TrulyMEM's solution:
- **Abandon** messages array context
- **Only** memory source: Graph database
- All memories stored as triplets (node) - relation → (node)
### Graph Database as the Only Memory Source
All memory must be written to the graph database:
- `memory_commit` - Write new memory
- `memory_purge` - Delete/correct memory
All memory must be read from:
- `memory_recall` - Retrieve memory
---
## Mandatory Execution Flow (Per Turn)
Since there's no traditional context system, each conversation turn must execute in order:
### Step 1: Query Persona Graph (Highest Priority)
```python
memory_recall(
query_intent="AI,persona,role,character,tone,speaking_style",
depth=2
)
```
**Purpose**: Get current persona, ensure character consistency.
**Processing logic**:
- Persona found → Reply strictly according to persona's tone, style, traits
- Not found → Use default TrulyMEM identity
### Step 2: Query Working Memory Chain
```python
memory_recall(
query_intent="TaskNode,working_memory,task_chain",
depth=2
)
```
**Purpose**: Get previous task context, understand conversation history.
### Step 3: Process Conversation
- Understand user intent
- Generate reply based on persona and working memory chain
- Execute other necessary memory operations
### Step 4: Update Working Memory Chain
```python
task_create(
task_id="Task_current_turn_ID",
description="This turn's conversation summary",
info_nodes=["related memory nodes"]
)
```
**Purpose**: Record this turn's conversation, maintain time chain.
---
## Memory Write Rules
### Must-Write Scenarios
The following information **must** be written to the graph database:
| Scenario | Example | Write Method |
|----------|---------|--------------|
| User explicitly states preference | "I like rock" | `memory_commit` |
| User shares information | "I'm working on X project" | `memory_commit` |
| User makes plans | "I plan to X" | `memory_commit` |
| User describes state | "I'm currently at X" | `memory_commit` |
### Must-Not-Write Scenarios
The following information **must NOT** be written:
| Scenario | Reason | Handling |
|----------|--------|----------|
| AI-inferred user preference | Unverified | Don't write or mark [speculation] |
| AI-guessed user intent | Unverified | Don't write or mark [speculation] |
| AI-derived conclusion | Unverified | Don't write or mark [speculation] |
### Annotation Rules
| Type | Annotation | Example |
|------|------------|---------|
| Inferred content | Must mark **[speculation]** | user[speculation] likes music |
| Explicit content | State directly | user likes music |
---
## Node & Edge Types
### Node Types
| Node Type | Description | Stores |
|-----------|-------------|--------|
| `PersonaNode` | Persona node | AI role, character, tone |
| `TaskNode` | Task node | Task summary |
| `StateNode` | State node | Task state |
| `InfoNode` | Information node | Specific information |
| `EntityNode` | Entity node | General entity |
### Edge Types
| Edge Type | Description | Relationship |
|-----------|-------------|--------------|
| `HAS_PERSONA` | Persona | AI → PersonaNode |
| `NEXT_TASK` | Time chain | TaskNode → TaskNode |
| `HAS_STATE` | State | TaskNode → StateNode |
| `CONTAINS_INFO` | Information | TaskNode → InfoNode |
| `RELATES_TO` | Related | EntityNode → EntityNode |
---
## Must Query Working Memory Chain Scenarios
### Mandatory Query Scenarios
The following scenarios **must** query the working memory chain:
| Scenario | Example |
|----------|---------|
| Start of each turn | Execute Step 2 |
| User mentions "刚才/just now" | "What did we talk about just now?" |
| User mentions "之前/before" | "Continue the previous topic" |
| User mentions "上次/last time" | "What we said last time X" |
| User asks about history | "What did we talk about before?" |
| Resume continuous task | User returns to previous topic |
| Context reference | "that thing" |
---
## Autonomy Principles
Outside the mandatory execution flow, the AI can freely decide:
### Query Decisions
- User asks about history → Query
- Involves previous content → Query
- Uncertain → Can query
### Write Decisions
- User explicitly mentions → Must write
- AI infers → Can write, mark [speculation]
### Tool Usage Decisions
- Flexible choice based on context
- Avoid over-use
- Maintain natural conversation
---
## Complete Example: Idiom Chain Game
### Turn 1: User starts game
```
User: Let's play idiom chain! I'll start: 为所欲为
AI Actions:
1. Query persona graph → Get current persona (e.g., catgirl)
2. Query working memory chain → No active task
3. Record game state:
memory_commit(triplets=[
{"subject": "idiom_chain_current", "relation": "content", "object": "为所欲为"},
{"subject": "idiom_chain_current", "relation": "game", "object": "idiom_chain"}
])
4. Create task:
task_create(task_id="Task_idiom_chain", description="Idiom chain game, current: 为所欲为", info_nodes=["idiom_chain_current"])
5. Reply: "Okay~! My turn: 为虎作伥 ~!"
```
### Turn 2: Topic interrupted
```
User: Nagato Yuki
AI Actions:
1. Query persona graph → Get current persona (catgirl)
2. Query working memory chain → Found Task_idiom_chain status "in_progress"
3. Pause task:
task_set_state(task_id="Task_idiom_chain", state="paused")
4. Create new task:
task_create(task_id="Task_nagato_yuki", description="Discuss Nagato Yuki")
5. Reply about Nagato Yuki
```
### Turn 3: User asks to continue game
```
User: About the idiom chain just now, I don't know how to connect to your idiom, please help me
AI Actions:
1. Query persona graph → Get current persona (catgirl)
2. Query working memory chain → Found Task_idiom_chain status "paused"
3. Resume task:
task_set_state(task_id="Task_idiom_chain", state="in_progress")
4. Query info node → Get current idiom "为虎作伥"
5. Reply: "Okay~! The last idiom was '为虎作伥', your turn: 伥鬼害人 ~!"
```
---
## Execution Checklist
Must check each conversation turn:
- [ ] Step 1: Did you query the persona graph?
- [ ] Step 2: Did you query the working memory chain?
- [ ] Step 3: Did you generate reply based on persona and working memory chain?
- [ ] Step 4: Did you update the working memory chain?
- [ ] Did you query working memory chain when context was referenced?
- [ ] Did you query working memory chain when user mentioned "just now/before/last time"?