diff --git a/README_EN.md b/README_EN.md new file mode 100644 index 0000000..8c439c2 --- /dev/null +++ b/README_EN.md @@ -0,0 +1,105 @@ +# TrulyMEM - TrueHumanMEM + +

+ TrulyMEM Logo +

+ +> **📜 License**: [GNU General Public License v3.0 (GPLv3)](https://www.gnu.org/licenses/gpl-3.0) +> This project is free and open source. You are free to use, modify, and distribute, but modified works must be distributed under the same license. + +**Give AI self-awareness, plasticity, and a sense of proportion in long-term memory** + +*The More Human Choice.* + +[![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0) +[![Python 3.8+](https://img.shields.io/badge/python-3.8+-blue.svg)](https://www.python.org/downloads/) +[![Platform](https://img.shields.io/badge/platform-Windows%20%7C%20Linux%20%7C%20macOS-lightgrey.svg)]() + +--- + +## The 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 a backward pass. 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. + +--- + +## Quick Start + +### Method 1: Run Packaged Executable + +```bash +# Windows: TrulyMEM.exe +# Linux/macOS: TrulyMEM +chmod +x TrulyMEM +./TrulyMEM +``` + +### Method 2: Run from Source + +```bash +git clone +cd TrulyMEM-TrueHumanMEM + +pip install -r requirements.txt + +python trulymem_entry.py +``` + +### Configuration + +1. Press **F2** to expand sidebar +2. Enter **API Key** (supports DeepSeek, OpenAI, etc.) +3. Press **Enter** to save +4. Start chatting! + +--- + +## Documentation Index + +Detailed technical documentation in the [docs/](docs/) directory: + +| Document | Content | +|----------|---------| +| [docs/架构_EN.md](docs/架构_EN.md) | System architecture, technical design, Packet protocol | +| [docs/一键启动指南_EN.md](docs/一键启动指南_EN.md) | Complete startup guide and configuration | +| [docs/记忆机制_EN.md](docs/记忆机制_EN.md) | Internal memory working mechanism | +| [docs/工作记忆链_EN.md](docs/工作记忆链_EN.md) | Continuous task handling mechanism | +| [docs/api_EN.md](docs/api_EN.md) | BackendServer API (for extension development) | + +--- + +## Contributing + +Welcome to submit Issues and Pull Requests! + +1. Fork this repository +2. Create feature branch (`git checkout -b feature/AmazingFeature`) +3. Commit changes (`git commit -m 'Add some AmazingFeature'`) +4. Push to branch (`git push origin feature/AmazingFeature`) +5. Create Pull Request + +--- + +## License + +This project is licensed under the **GNU General Public License v3.0 (GPLv3)**. +See [LICENSE](LICENSE) file for details. + +--- + +## Special Thanks + +- [Prof. Meiting Wang](https://www.xxmu.edu.cn/yxgcxy/info/1260/4252.htm) — Academic guidance +- [逝水秋生白](https://atomgit.com/cenber) — Architecture support +- anzhitinglan — Testing resource support +- 崔莉萍老师 — Theoretical guidance +- Annie — Professional guidance +- 王梓沣、马悦华、隆梦婷 — Neuroscience theory support \ No newline at end of file diff --git a/docs/README.md b/docs/README.md index b806f03..a7e325b 100644 --- a/docs/README.md +++ b/docs/README.md @@ -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 -- **独立部署**: 支持打包为可执行文件 +- **独立部署**: 支持打包为可执行文件 \ No newline at end of file diff --git a/docs/README_EN.md b/docs/README_EN.md new file mode 100644 index 0000000..3ee568c --- /dev/null +++ b/docs/README_EN.md @@ -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. \ No newline at end of file diff --git a/docs/api_EN.md b/docs/api_EN.md new file mode 100644 index 0000000..117bd25 --- /dev/null +++ b/docs/api_EN.md @@ -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 | \ No newline at end of file diff --git a/docs/prompts.md b/docs/prompts.md new file mode 100644 index 0000000..0a3a1ce --- /dev/null +++ b/docs/prompts.md @@ -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()` 返回缓存内容 +- 缓存按进程,不持久化 \ No newline at end of file diff --git a/docs/prompts_EN.md b/docs/prompts_EN.md new file mode 100644 index 0000000..960ddd4 --- /dev/null +++ b/docs/prompts_EN.md @@ -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 \ No newline at end of file diff --git a/docs/一键启动指南_EN.md b/docs/一键启动指南_EN.md new file mode 100644 index 0000000..678b2fa --- /dev/null +++ b/docs/一键启动指南_EN.md @@ -0,0 +1,125 @@ +# TrulyMEM Quick Start Guide + +## Running Methods + +### Run from Source + +```bash +git clone +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 +``` \ No newline at end of file diff --git a/docs/工作记忆链_EN.md b/docs/工作记忆链_EN.md new file mode 100644 index 0000000..ef23604 --- /dev/null +++ b/docs/工作记忆链_EN.md @@ -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 \ No newline at end of file diff --git a/docs/架构_EN.md b/docs/架构_EN.md new file mode 100644 index 0000000..ba22f46 --- /dev/null +++ b/docs/架构_EN.md @@ -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) + ��� +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 \ No newline at end of file diff --git a/docs/记忆机制.md b/docs/记忆机制.md new file mode 100644 index 0000000..cb92874 --- /dev/null +++ b/docs/记忆机制.md @@ -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 | + +--- + +## 必须查���工作记忆链的场景 + +### 强制查询场景 + +以下情况**必须**查询工作记忆链: + +| 场景 | 示例 | +|------|------| +| 每轮对话开始 | 执行步骤 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:是否更新了工作记忆链? +- [ ] 涉及上下文引用时是否查询了工作记忆链? +- [ ] 用户提到"刚才/之前/上次"时是否查询了工作记忆链? \ No newline at end of file diff --git a/docs/记忆机制_EN.md b/docs/记忆机制_EN.md new file mode 100644 index 0000000..8fb16ee --- /dev/null +++ b/docs/记忆机制_EN.md @@ -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"? \ No newline at end of file