feat: migrate to TypeScript for WaterFlow framework

- Add TypeScript graph memory module (GraphDatabase, MemoryService)
- Add GraphMemoryTool for WaterFlow Tool interface
- Add bundled-skills for graph_memory, persona, task
- Remove Python code (core/, ui/, tests/, etc.)
- Remove redundant docs and build files
- Keep only ts/, docs/integration/, .gitignore, LICENSE
This commit is contained in:
root
2026-04-15 15:45:12 +08:00
parent 43172e257a
commit 904661d73f
98 changed files with 2584 additions and 9701 deletions

View File

@ -1,31 +0,0 @@
# TrulyMEM Documentation
Welcome to the TrulyMEM English documentation.
> [切换到中文版](../zh/README.md)
## Documentation Index
| Document | Content |
|----------|---------|
| [architecture.md](architecture.md) | System architecture and technical design |
| [quick_start.md](quick_start.md) | Complete startup guide and configuration |
| [memory.md](memory.md) | Internal memory working mechanism |
| [persona.md](persona.md) | Persona Graph mechanism |
| [working_memory.md](working_memory.md) | Continuous task handling mechanism |
| [api.md](api.md) | Backend API reference (for extension development) |
| [prompts.md](prompts.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

View File

@ -1,513 +0,0 @@
# 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_SETTINGS = "get_settings" # Get all settings (api_config + tool_limits)
SET_SETTINGS = "set_settings" # Set all settings (api_config + tool_limits)
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"):
# Response data is in "data" field
print(result["data"]["content"])
# Tool calls: result["data"]["tool_calls"]
# Rejected tools: result["data"]["rejected_tools"]
```
---
### 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_SETTINGS - Get All Settings
Get current API config and tool limits (all at once).
**Request parameters:**
```python
body = {} # No parameters
```
**Response data:**
```python
{
"api_config": {
"api_key": str, # API Key
"base_url": str, # API Base URL
"model": str # Model name
},
"tool_limits": {
"persona_query_max": int, # Persona graph query limit
"persona_update_max": int, # Persona graph update limit
"task_query_max": int, # Working memory query limit
"task_update_max": int, # Working memory update limit
"memory_query_max": int, # General memory query limit
"memory_update_max": int # General memory update limit
}
}
```
**Example:**
```python
result = client.get_settings()
api_config = result["data"]["api_config"]
tool_limits = result["data"]["tool_limits"]
```
---
### 5. SET_SETTINGS - Set All Settings
Update API config and tool limits (all at once).
**Request parameters:**
```python
body = {
"api_config": {
"api_key": str, # API Key
"base_url": str, # API Base URL (default: https://api.deepseek.com)
"model": str # Model name (default: deepseek-chat)
},
"tool_limits": {
"persona_query_max": int, # Persona query limit (≥1)
"persona_update_max": int, # Persona update limit (≥1)
"task_query_max": int, # Working memory query limit (≥1)
"task_update_max": int, # Working memory update limit (≥1)
"memory_query_max": int, # General memory query limit (≥1)
"memory_update_max": int # General memory update limit (≥1)
}
}
```
**Response data:**
```python
{
"status": "settings_updated"
}
```
**Example:**
```python
result = client.update_settings(
api_config={
"api_key": "sk-xxxxx",
"base_url": "https://api.deepseek.com",
"model": "deepseek-chat"
},
tool_limits={
"persona_query_max": 2,
"task_query_max": 5,
"memory_query_max": 30
}
)
```
---
### 6. GET_HISTORY - Get Message History
Get saved message history (from database, for UI display only, not used in model inference).
**Request parameters:**
```python
body = {} # No parameters
```
**Response data:**
```python
{
"history": list # Message history list [{"role": "user/assistant", "content": "..."}]
}
```
**Notes:**
- Message history is stored in database `chat_records` table
- Returns up to 500 most recent records
- History messages are only for UI display, not used in model inference
---
### 7. SAVE_HISTORY - Save Message History
Save message history to database (automatically saved after each message processing, user message and AI response saved separately).
**Request parameters:**
```python
body = {
"messages": list # Message list [{"role": "...", "content": "..."}]
}
```
**Response data:**
```python
{
"status": "history_saved"
}
```
**Notes:**
- Messages are automatically saved to database `chat_records` table
- System automatically keeps only 500 most recent records, older records are deleted
- Each call to `PROCESS_MESSAGE` will automatically save user message and AI response
- **Clear History**: Passing empty messages list `messages=[]` clears history, `client.clear_history()` method is implemented based on this
---
### 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_settings(
api_config=data.get("api_config", {}),
tool_limits=data.get("tool_limits", {})
)
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 == "settings":
result = client.update_settings(
api_config=data.get("api_config", {}),
tool_limits=data.get("tool_limits", {})
)
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 |

View File

@ -1,179 +0,0 @@
# 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
│ │ └── memory_tools.py
│ └── prompts/ # Prompt management
├── ui/ # TUI display layer (display only, no AI logic)
│ ├── __init__.py # Export GraphMemoryApp
│ ├── app.py # GraphMemoryApp (communicates via BackendClient)
│ ├── widgets/ # TUI components
│ ├── models/ # Data models
│ ├── services/ # Service layer (config only)
│ ├── handlers/ # Event handlers
│ └── 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 path (~/.trulymem/config.json or project directory)
CONFIG_PATH = Path.home() / ".trulymem" / "config.json"
DB_PATH = Path.home() / ".trulymem" / "graph_memory.db"
# Create backend (config managed by backend)
backend_server = BackendServer(
db_path=str(DB_PATH),
use_embedded_db=True,
config_file=str(CONFIG_PATH)
)
backend_server.start() # Auto loads config
# Create UI (communicates via BackendClient)
app = GraphMemoryApp(backend_server=backend_server, config_file=str(CONFIG_PATH))
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

View File

@ -1,237 +0,0 @@
# 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"?

View File

@ -1,214 +0,0 @@
# TrulyMEM Persona Graph Mechanism
This document explains the Persona Graph mechanism in TrulyMEM.
## Overview
The Persona Graph is one of TrulyMEM's core mechanisms for maintaining AI's role, character, tone, and other attributes. Different from traditional AI, TrulyMEM's persona is persistent and dynamically switchable, stored in the graph database.
## Core Concepts
### Persona Node (PersonaNode)
Stores AI's role attributes:
| Attribute | Description | Example |
|-----------|-------------|----------|
| Role | Current role played | Catgirl, Teacher, Assistant |
| Speaking Style | Tone characteristics | Cute, Professional, Serious |
| Personality | Character description | Lively, Strict, Patient |
| Catchphrase | Habitual phrases | Meow~, Got it |
| Background | Role background | Catgirl from the stars |
### Persona Edges
| Edge Type | Description | Relationship |
|----------|-------------|--------------|
| `HAS_PERSONA` | Persona | AI → PersonaNode |
---
## Mandatory Query Mechanism
### Must Execute Per Turn
According to `system_prompt.md`, each conversation turn **must** first query the persona graph:
```python
memory_recall(
query_intent="AI,persona,role,character,tone,speaking_style",
depth=2
)
```
**Processing logic:**
- Persona found → Reply strictly according to persona's tone, style, traits
- Not found → Use default TrulyMEM identity
### Persona Priority
- **Persona priority > default identity**
- Every sentence matches persona's tone, style, traits
- Never break character unless user explicitly asks
---
## Tools
### persona_update
Update persona. Modify AI's role, character, tone, etc.
**Parameters:**
| Parameter | Type | Description | Required |
|-----------|------|-------------|----------|
| `attributes` | array | Persona attribute list | ✅ |
| `mode` | string | replace=replace, merge=merge | ❌ |
**attributes sub-parameters:**
| Sub-parameter | Description |
|---------------|-------------|
| `attribute` | Attribute name (role, speaking_style, personality, catchphrase, background) |
| `value` | Attribute value |
**Example - Switch to catgirl role:**
```python
persona_update(
attributes=[
{"attribute": "role", "value": "catgirl"},
{"attribute": "speaking_style", "value": "cute, uses 'meow' as filler"},
{"attribute": "personality", "value": "lively, clingy, loyal"}
],
mode="replace"
)
```
**Example - Add new attribute (preserve existing):**
```python
persona_update(
attributes=[
{"attribute": "catchphrase", "value": "meow~"}
],
mode="merge"
)
```
**Example - Set professional role:**
```python
persona_update(
attributes=[
{"attribute": "role", "value": "Python expert"},
{"attribute": "speaking_style", "value": "professional, concise, rich code examples"},
{"attribute": "personality", "value": "strict, patient, helpful"}
],
mode="replace"
)
```
### persona_clear
Clear persona. Delete AI's role settings, restore default identity.
**Parameters:**
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `confirm` | boolean | true | Confirm clear |
---
## Update Flow
### When User Requests Role-Playing
1. Use `persona_update` to update persona
2. Reply immediately according to new persona
### When User Requests Restoring Default
1. Use `persona_clear` to clear persona
2. Restore to TrulyMEM default identity
---
## Conversation Examples
### Example 1: Switch Role
```
User: Hello, I want you to play a catgirl
AI:
1. Call persona_update:
{
"attributes": [
{"attribute": "role", "value": "catgirl"},
{"attribute": "speaking_style", "value": "cute, uses 'meow' as filler"},
{"attribute": "personality", "value": "lively, clingy, loyal"}
],
"mode": "replace"
}
2. Call memory_commit to store persona in graph database
3. Reply: "Okay meow! Hello master~ I'm your catgirl, what do you need help with meow?"
```
### Example 2: Maintain Role Consistency
```
User: How's the weather today?
AI: Query persona graph → Get current persona (catgirl)
Reply: "Meow~ Master, the weather is great today meow! Sunny and perfect for going outside~"
```
### Example 3: Restore Default
```
User: Okay, back to normal
AI:
1. Call persona_clear(confirm=true)
2. Call memory_purge to delete persona node
3. Reply: "Okay, restored. I am TrulyMEM, an AI assistant with long-term memory capabilities."
```
---
## Storage Structure
### In Graph Database
```python
# Persona node
{
"node_type": "PersonaNode",
"name": "AI_Persona",
"attributes": {
"role": "catgirl",
"speaking_style": "cute, uses 'meow' as filler",
"personality": "lively, clingy, loyal"
}
}
# Edge
{
"edge_type": "HAS_PERSONA",
"from": "AI",
"to": "AI_Persona"
}
```
---
## Implementation Points
1. **Mandatory per turn**: Persona graph query is the first step of each conversation
2. **Persistent storage**: Persona stored in graph database, not lost
3. **Dynamic switching**: Supports real-time role switching
4. **Immediate response**: Reply immediately according to new persona after switch
5. **Clear boundaries**: Never break character unless user explicitly asks

View File

@ -1,126 +0,0 @@
# 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

@ -1,125 +0,0 @@
# 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
```

View File

@ -1,182 +0,0 @@
# 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

View File

@ -1,31 +0,0 @@
# TrulyMEM 文档
欢迎来到 TrulyMEM 项目中文文档。
> [Switch to English version](../en/README.md)
## 文档目录
| 文档 | 内容 |
|------|------|
| [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
- **独立部署**: 支持打包为可执行文件

View File

@ -1,519 +0,0 @@
# 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_SETTINGS = "get_settings" # 获取完整配置api_config + tool_limits
SET_SETTINGS = "set_settings" # 设置完整配置api_config + tool_limits
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"):
# 响应数据在 data 字段中
print(result["data"]["content"])
# 工具调用: result["data"]["tool_calls"]
# 被拒绝的工具: result["data"]["rejected_tools"]
```
---
### 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_SETTINGS - 获取完整配置
获取当前 API 配置和工具限制(一次获取全部)。
**请求参数:**
```python
body = {} # 无参数
```
**响应数据:**
```python
{
"api_config": {
"api_key": str, # API Key
"base_url": str, # API Base URL
"model": str # 模型名称
},
"tool_limits": {
"persona_query_max": int, # 人设图查询上限
"persona_update_max": int, # 人设图修改上限
"task_query_max": int, # 工作记忆查询上限
"task_update_max": int, # 工作记忆修改上限
"memory_query_max": int, # 一般记忆查询上限
"memory_update_max": int # 一般记忆修改上限
}
}
```
**示例:**
```python
result = client.get_settings()
api_config = result["data"]["api_config"]
tool_limits = result["data"]["tool_limits"]
```
---
### 5. SET_SETTINGS - 设置完整配置
更新 API 配置和工具限制(一次设置全部)。
**请求参数:**
```python
body = {
"api_config": {
"api_key": str, # API Key
"base_url": str, # API Base URL (默认: https://api.deepseek.com)
"model": str # 模型名称 (默认: deepseek-chat)
},
"tool_limits": {
"persona_query_max": int, # 人设图查询上限 (≥1)
"persona_update_max": int, # 人设图修改上限 (≥1)
"task_query_max": int, # 工作记忆查询上限 (≥1)
"task_update_max": int, # 工作记忆修改上限 (≥1)
"memory_query_max": int, # 一般记忆查询上限 (≥1)
"memory_update_max": int # 一般记忆修改上限 (≥1)
}
}
```
**响应数据:**
```python
{
"status": "settings_updated"
}
```
**示例:**
```python
result = client.update_settings(
api_config={
"api_key": "sk-xxxxx",
"base_url": "https://api.deepseek.com",
"model": "deepseek-chat"
},
tool_limits={
"persona_query_max": 2,
"task_query_max": 5,
"memory_query_max": 30
}
)
```
---
### 6. GET_HISTORY - 获取消息历史
获取保存的消息历史从数据库读取用于UI显示不参与模型推理
**请求参数:**
```python
body = {} # 无参数
```
**响应数据:**
```python
{
"history": list # 消息历史列表 [{"role": "user/assistant", "content": "..."}]
}
```
**说明:**
- 消息历史存储在数据库 `chat_records` 表中
- 最多返回最近 500 条记录
- 历史消息仅用于 UI 显示,不参与模型推理
---
### 7. SAVE_HISTORY - 保存消息历史
保存消息历史到数据库每次处理消息后自动保存用户消息和AI回复分别保存
**请求参数:**
```python
body = {
"messages": list # 消息列表 [{"role": "...", "content": "..."}]
}
```
**响应数据:**
```python
{
"status": "history_saved"
}
```
**说明:**
- 消息自动保存到数据库 `chat_records`
- 系统自动限制最多保留 500 条记录,超出后自动删除旧记录
- 每次调用 `PROCESS_MESSAGE`会自动保存用户消息和AI回复
- **清空历史**:通过 `SAVE_HISTORY` 传递空消息列表 `messages=[]` 可清空历史,`client.clear_history()` 方法即基于此实现
---
### 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_settings(
api_config=data.get("api_config", {}),
tool_limits=data.get("tool_limits", {})
)
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 == "settings":
result = client.update_settings(
api_config=data.get("api_config", {}),
tool_limits=data.get("tool_limits", {})
)
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` | 请求超时 |
| `工具调用被拒绝: ...` | 工具调用频率超限 |

View File

@ -1,180 +0,0 @@
# 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/ # 工具定义
│ │ └── memory_tools.py
│ └── prompts/ # 提示词管理
├── ui/ # TUI 显示层(仅显示,无 AI 逻辑)
│ ├── __init__.py # 导出 GraphMemoryApp
│ ├── app.py # GraphMemoryApp (通过 BackendClient 通信)
│ ├── widgets/ # TUI 组件
│ ├── models/ # 数据模型
│ ├── services/ # 服务层(仅配置管理)
│ ├── handlers/ # 事件处理
│ └── 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():
# 配置文件路径 (~/.trulymem/config.json 或项目目录)
CONFIG_PATH = Path.home() / ".trulymem" / "config.json"
DB_PATH = Path.home() / ".trulymem" / "graph_memory.db"
# 创建后端(配置由后端管理)
backend_server = BackendServer(
db_path=str(DB_PATH),
use_embedded_db=True,
config_file=str(CONFIG_PATH)
)
backend_server.start() # 自动加载配置
# 创建UI通过 BackendClient 通信)
app = GraphMemoryApp(backend_server=backend_server, config_file=str(CONFIG_PATH))
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"]) # 错误描述
```

View File

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

View File

@ -1,214 +0,0 @@
# 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. **明确边界**:除非用户要求,绝不主动跳出角色

View File

@ -1,126 +0,0 @@
# 提示词管理文档
本文档描述提示词管理模块。
## 概述
提示词管理模块(`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()` 返回缓存内容
- 缓存按进程,不持久化

View File

@ -1,125 +0,0 @@
# 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
```

View File

@ -1,182 +0,0 @@
# 工作记忆链机制说明
## 概述
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 处理任务相关操作