diff --git a/.ai-context/api-reference.md b/.ai-context/api-reference.md new file mode 100644 index 0000000..d6f508b --- /dev/null +++ b/.ai-context/api-reference.md @@ -0,0 +1,428 @@ +# API Reference + +## Base URL + +``` +http://localhost:8085 +``` + +## API Version + +All endpoints are under `/api/v2/`. + +## Response Format + +All responses follow this structure: + +```json +{ + "success": true, + "data": { ... }, + "error": null, + "timestamp": "2024-03-15T10:30:00Z" +} +``` + +Error responses: +```json +{ + "success": false, + "data": null, + "error": "Error message", + "timestamp": "2024-03-15T10:30:00Z" +} +``` + +--- + +## Health Endpoints + +### GET /health + +Basic health check. + +**Response:** +```json +{ + "service": "cortex-mem-service", + "status": "healthy", + "version": "2.7.0", + "llm_available": true, + "timestamp": "2024-03-15T10:30:00Z" +} +``` + +--- + +## Filesystem Endpoints + +### GET /api/v2/filesystem/list + +List directory contents. + +**Query Parameters:** +| Parameter | Type | Default | Description | +|-----------|------|---------|-------------| +| `uri` | string | `cortex://session` | Directory URI to list | +| `recursive` | boolean | `false` | List subdirectories recursively | +| `include_abstracts` | boolean | `false` | Include L0 abstracts for files | +| `include_layers` | boolean | `false` | Show `.abstract.md` and `.overview.md` files | + +**Example:** +```bash +curl "http://localhost:8085/api/v2/filesystem/list?uri=cortex://session&recursive=true" +``` + +**Response:** +```json +{ + "success": true, + "data": { + "uri": "cortex://session", + "total": 2, + "entries": [ + { + "uri": "cortex://session/default", + "name": "default", + "is_directory": true, + "size": 192, + "modified": "2024-03-15T10:30:00Z", + "abstract_text": null + } + ] + } +} +``` + +### GET /api/v2/filesystem/read/{path} + +Read file content directly. + +**Example:** +```bash +curl "http://localhost:8085/api/v2/filesystem/read/session/abc/timeline/2024-03/15/msg.md" +``` + +### POST /api/v2/filesystem/write + +Write content to a file. + +**Request Body:** +```json +{ + "path": "cortex://user/default/preferences/typescript.md", + "content": "# TypeScript Preferences\n\nUser prefers strict mode." +} +``` + +### GET /api/v2/filesystem/stats + +Get directory statistics. + +**Query Parameters:** +| Parameter | Type | Description | +|-----------|------|-------------| +| `uri` | string | Directory URI | + +**Response:** +```json +{ + "success": true, + "data": { + "file_count": 42, + "total_size": 128000 + } +} +``` + +--- + +## Layered Access Endpoints + +### GET /api/v2/filesystem/abstract + +Get L0 abstract layer (~100 tokens). + +**Query Parameters:** +| Parameter | Type | Description | +|-----------|------|-------------| +| `uri` | string | Content URI (file or directory) | + +**Example:** +```bash +curl "http://localhost:8085/api/v2/filesystem/abstract?uri=cortex://session/abc/timeline" +``` + +**Response:** +```json +{ + "success": true, + "data": { + "uri": "cortex://session/abc/timeline", + "content": "Discussion about TypeScript project setup...", + "layer": "L0", + "token_count": 95 + } +} +``` + +### GET /api/v2/filesystem/overview + +Get L1 overview layer (~2000 tokens). + +**Query Parameters:** +| Parameter | Type | Description | +|-----------|------|-------------| +| `uri` | string | Content URI (file or directory) | + +### GET /api/v2/filesystem/content + +Get L2 full content layer. + +**Query Parameters:** +| Parameter | Type | Description | +|-----------|------|-------------| +| `uri` | string | Content URI (file only) | + +--- + +## Search Endpoint + +### POST /api/v2/search + +Semantic search with layered retrieval. + +**Request Body:** +```json +{ + "query": "user preferences for TypeScript", + "thread": "optional-session-id", + "limit": 10, + "min_score": 0.6, + "return_layers": ["L0", "L1"] +} +``` + +| Parameter | Type | Default | Description | +|-----------|------|---------|-------------| +| `query` | string | (required) | Natural language query | +| `thread` | string | null | Filter by session ID | +| `limit` | integer | 10 | Max results | +| `min_score` | float | 0.6 | Minimum relevance score (0-1) | +| `return_layers` | string[] | `["L0"]` | Layers to return: `["L0"]`, `["L0","L1"]`, `["L0","L1","L2"]` | + +**Example:** +```bash +curl -X POST "http://localhost:8085/api/v2/search" \ + -H "Content-Type: application/json" \ + -d '{"query": "database decisions", "return_layers": ["L0", "L1"]}' +``` + +**Response:** +```json +{ + "success": true, + "data": [ + { + "uri": "cortex://session/abc/timeline/2024-03/15/10_30_00.md", + "score": 0.85, + "snippet": "Decided to use PostgreSQL...", + "overview": "Key points: PostgreSQL chosen for...", + "content": null, + "source": "search", + "layers": ["L0", "L1"] + } + ] +} +``` + +--- + +## Explore Endpoint + +### POST /api/v2/filesystem/explore + +Smart exploration combining search and browsing. + +**Request Body:** +```json +{ + "query": "authentication flow", + "start_uri": "cortex://session", + "return_layers": ["L0"] +} +``` + +**Response:** +```json +{ + "success": true, + "data": { + "query": "authentication flow", + "exploration_path": [ + { + "uri": "cortex://session/abc/timeline", + "relevance_score": 0.82, + "abstract_text": "Discussion about auth..." + } + ], + "matches": [...], + "total_explored": 5, + "total_matches": 2 + } +} +``` + +--- + +## Session Endpoints + +### GET /api/v2/sessions + +List all sessions. + +**Response:** +```json +{ + "success": true, + "data": [ + { + "thread_id": "session-abc", + "status": "active", + "message_count": 25, + "created_at": "2024-03-15T10:30:00Z", + "updated_at": "2024-03-15T12:45:00Z" + } + ] +} +``` + +### POST /api/v2/sessions + +Create a new session. + +**Request Body:** +```json +{ + "thread_id": "my-session", + "title": "Optional title" +} +``` + +### POST /api/v2/sessions/{thread_id}/messages + +Add a message to a session. + +**Request Body:** +```json +{ + "role": "user", + "content": "This is my message content", + "metadata": { + "tags": ["important"], + "importance": "high" + } +} +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| `role` | string | `user`, `assistant`, or `system` | +| `content` | string | Message content | +| `metadata` | object | Optional metadata | + +**Response:** Returns the URI of the created message. + +### POST /api/v2/sessions/{thread_id}/close + +Close a session and trigger memory extraction pipeline. + +**Response:** +```json +{ + "success": true, + "data": { + "thread_id": "my-session", + "status": "closed", + "message_count": 25 + } +} +``` + +### POST /api/v2/sessions/{thread_id}/close-and-wait + +Close session and wait for extraction to complete. + +**Query Parameters:** +| Parameter | Type | Default | Description | +|-----------|------|---------|-------------| +| `timeout_secs` | integer | 120 | Max wait time | +| `poll_interval_ms` | integer | 500 | Poll interval | + +--- + +## Tenant Endpoints + +### GET /api/v2/tenants + +List all available tenants. + +**Response:** +```json +{ + "success": true, + "data": ["tenant_claw", "locomo-v4-001-conv-26"] +} +``` + +### POST /api/v2/tenants/switch + +Switch to a different tenant. + +**Request Body:** +```json +{ + "tenant_id": "my-tenant" +} +``` + +--- + +## Automation Endpoints + +### POST /api/v2/automation/extract/{thread_id} + +Trigger memory extraction for a specific thread. + +### POST /api/v2/automation/sync + +Trigger vector synchronization for all files. + +--- + +## Error Codes + +| HTTP Code | Description | +|-----------|-------------| +| 200 | Success | +| 400 | Bad Request - Invalid parameters | +| 404 | Not Found - Resource doesn't exist | +| 500 | Internal Server Error | + +--- + +## Notes + +1. **API Version**: Always use `/api/v2/` prefix. `/api/v1/` is deprecated. + +2. **Tenant Context**: Most operations require a tenant context. Switch tenants first using `POST /api/v2/tenants/switch`. + +3. **Layer Access**: Use the appropriate layer endpoint based on your token budget: + - L0 (~100 tokens) → Quick filtering + - L1 (~2000 tokens) → Context understanding + - L2 (full) → Complete content + +4. **Search Weights**: Search uses weighted scoring: + ``` + Score = 0.2 × L0 + 0.3 × L1 + 0.5 × L2 + ``` diff --git a/.ai-context/architecture.md b/.ai-context/architecture.md new file mode 100644 index 0000000..4987d99 --- /dev/null +++ b/.ai-context/architecture.md @@ -0,0 +1,202 @@ +# Architecture + +## System Overview + +Cortex Memory implements a **hybrid storage architecture** combining: +1. **Virtual Filesystem** - Durable markdown storage with `cortex://` URI scheme +2. **Vector Index** - Semantic search via Qdrant + +## Core Components + +### 1. CortexMem (Main Runtime) + +Location: `cortex-mem-core/src/lib.rs` + +The central orchestrator that coordinates all components: + +```rust +pub struct CortexMem { + filesystem: Arc, + session_manager: Arc>, + vector_store: Option>, + embedding: Option>, + llm_client: Option>, + // ... +} +``` + +### 2. Virtual Filesystem + +Location: `cortex-mem-core/src/filesystem/` + +Maps `cortex://` URIs to physical files: + +``` +cortex://session/{id}/timeline/{date}/{time}.md + → {data_dir}/session/{id}/timeline/{date}/{time}.md +``` + +Key types: +- `CortexUri` - Parsed URI representation +- `UriParser` - URI parsing logic +- `CortexFilesystem` - File operations implementation + +### 3. Session Manager + +Location: `cortex-mem-core/src/session/` + +Manages conversation sessions: +- Create/close sessions +- Add messages to timeline +- Track session metadata + +### 4. Memory Extraction Pipeline + +Location: `cortex-mem-core/src/layers/` + +Extracts structured memories from conversations: +1. **Extractor** - LLM-powered memory extraction +2. **Layer Generator** - Creates L0 (abstract) and L1 (overview) layers +3. **Incremental Updater** - Event-driven layer updates + +### 5. Vector Search Engine + +Location: `cortex-mem-core/src/search/` + +Implements semantic search: +- Generates embeddings for content +- Stores vectors in Qdrant +- Performs similarity search with L0/L1/L2 weighted scoring + +### 6. Event-Driven Automation + +Location: `cortex-mem-core/src/automation/` + +Background processing: +- File watchers for change detection +- Auto-indexing for vector sync +- Layer regeneration triggers + +## Data Flow + +### Message Ingestion + +``` +1. User/Agent Message + │ + ▼ +2. Session Manager stores to filesystem + │ + ▼ +3. Timeline file created (L2 content) + │ + ▼ +4. Session closed → Extraction triggered + │ + ▼ +5. LLM extracts structured memories + │ + ▼ +6. L0/L1 layers generated + │ + ▼ +7. Vectors indexed to Qdrant +``` + +### Search Query + +``` +1. Search Query + │ + ▼ +2. Generate query embedding + │ + ▼ +3. Vector search in Qdrant + │ + ▼ +4. Retrieve L0 abstracts first + │ + ▼ +5. Optionally fetch L1/L2 for relevant results + │ + ▼ +6. Return weighted, ranked results +``` + +## Three-Tier Memory Hierarchy + +| Layer | File | Tokens | Purpose | +|-------|------|--------|---------| +| L0 (Abstract) | `.abstract.md` | ~100 | Quick relevance filtering | +| L1 (Overview) | `.overview.md` | ~2000 | Context understanding | +| L2 (Detail) | `{name}.md` | Full | Complete original content | + +### Layer Resolution + +For a file `cortex://session/abc/timeline/2024-03/15/10_30_00.md`: +- L0: `{dir}/.abstract.md` (directory-level abstract) +- L1: `{dir}/.overview.md` (directory-level overview) +- L2: The actual `.md` file + +### Search Weights + +``` +Final Score = 0.2 × L0_score + 0.3 × L1_score + 0.5 × L2_score +``` + +## Multi-Tenancy + +Tenants provide complete isolation: + +``` +{data_dir}/tenants/{tenant_id}/ +├── session/ +├── user/ +├── agent/ +└── resources/ +``` + +Each tenant has: +- Separate filesystem namespace +- Separate Qdrant collection (`{collection_name}_{tenant_id}`) +- Independent vector index + +## Event System + +Location: `cortex-mem-core/src/memory_events.rs` + +Events trigger automated processing: + +```rust +pub enum MemoryEvent { + FileCreated { uri: String }, + FileModified { uri: String }, + FileDeleted { uri: String }, + SessionClosed { thread_id: String }, + // ... +} +``` + +Event coordinators: +- `MemoryEventCoordinator` - Routes events to handlers +- `CascadeLayerUpdater` - Updates L0/L1 layers when content changes +- `IncrementalMemoryUpdater` - Incremental extraction updates + +## Caching + +Location: `cortex-mem-core/src/llm_result_cache.rs` + +LRU cache for LLM results: +- Reduces redundant API calls by 50-75% +- TTL-based expiration +- Key-based deduplication + +## Memory Cleanup + +Location: `cortex-mem-core/src/memory_cleanup.rs` + +Based on Ebbinghaus forgetting curve: +- Archives low-strength memories +- Controls storage growth +- Configurable retention policies diff --git a/.ai-context/configuration.md b/.ai-context/configuration.md new file mode 100644 index 0000000..27d63c0 --- /dev/null +++ b/.ai-context/configuration.md @@ -0,0 +1,295 @@ +# Configuration Reference + +## Configuration File + +Cortex Memory uses a `config.toml` file for configuration. + +### Default Locations + +Priority order: +1. Explicit `--config` flag +2. `{data_dir}/config.toml` +3. `./config.toml` (current directory) + +--- + +## Complete Configuration Schema + +```toml +# ============================================================================= +# Qdrant Vector Database Configuration +# ============================================================================= +[qdrant] +# URL of Qdrant gRPC endpoint +url = "http://localhost:6334" + +# HTTP URL for REST API (optional, for health checks) +http_url = "http://localhost:6333" + +# Base collection name (tenant ID will be appended) +collection_name = "cortex-memory" + +# Connection timeout in seconds +timeout_secs = 30 + +# Embedding dimension (must match your embedding model) +# Examples: 1536 for text-embedding-3-small, 4096 for larger models +embedding_dim = 1536 + +# API key for Qdrant Cloud (optional) +api_key = "" + +# ============================================================================= +# LLM Configuration (for memory extraction and analysis) +# ============================================================================= +[llm] +# Base URL of your LLM provider (OpenAI-compatible API) +api_base_url = "https://api.openai.com/v1" + +# API key (supports environment variable expansion) +api_key = "${OPENAI_API_KEY}" + +# Model for efficient operations (extraction, classification) +model_efficient = "gpt-5-mini" + +# Model for complex reasoning (optional) +model_reasoning = "o1-preview" + +# Sampling temperature (0.0 - 2.0) +temperature = 0.1 + +# Maximum tokens for generation +max_tokens = 40960 + +# Request timeout in seconds +timeout_secs = 60 + +# ============================================================================= +# Embedding Service Configuration +# ============================================================================= +[embedding] +# Base URL of your embedding provider +api_base_url = "https://api.openai.com/v1" + +# API key +api_key = "${OPENAI_API_KEY}" + +# Embedding model name +model_name = "text-embedding-3-small" + +# Batch size for embedding requests +batch_size = 10 + +# Request timeout in seconds +timeout_secs = 30 + +# ============================================================================= +# Server Configuration (for cortex-mem-service) +# ============================================================================= +[server] +# Server host +host = "localhost" + +# Server port +port = 8085 + +# CORS origins (use ["*"] for development) +cors_origins = ["*"] + +# ============================================================================= +# Cortex Memory Settings +# ============================================================================= +[cortex] +# Data directory for memory storage +data_dir = "./cortex-data" + +# Enable LLM intent analysis before search +# Improves multi-hop query accuracy +enable_intent_analysis = true + +# ============================================================================= +# Logging Configuration +# ============================================================================= +[logging] +# Enable logging +enabled = true + +# Log directory +log_directory = "logs" + +# Log level: trace, debug, info, warn, error +level = "info" +``` + +--- + +## Environment Variables + +### Supported Variables + +| Variable | Description | +|----------|-------------| +| `OPENAI_API_KEY` | Default API key for LLM and Embedding | +| `LLM_API_KEY` | LLM-specific API key (overrides OPENAI_API_KEY for LLM) | +| `LLM_API_BASE_URL` | LLM API base URL | +| `LLM_MODEL` | LLM model name | +| `EMBEDDING_API_KEY` | Embedding-specific API key | +| `EMBEDDING_API_BASE_URL` | Embedding API base URL | +| `EMBEDDING_MODEL_NAME` | Embedding model name | +| `QDRANT_URL` | Qdrant gRPC URL | +| `QDRANT_API_KEY` | Qdrant API key | +| `QDRANT_COLLECTION` | Qdrant collection name | + +### Environment Variable Expansion + +Use `${VAR_NAME}` syntax in `config.toml`: + +```toml +[llm] +api_key = "${OPENAI_API_KEY}" +``` + +--- + +## Common Configurations + +### OpenAI + +```toml +[llm] +api_base_url = "https://api.openai.com/v1" +api_key = "${OPENAI_API_KEY}" +model_efficient = "gpt-5-mini" + +[embedding] +api_base_url = "https://api.openai.com/v1" +api_key = "${OPENAI_API_KEY}" +model_name = "text-embedding-3-small" + +[qdrant] +embedding_dim = 1536 +``` + +### Azure OpenAI + +```toml +[llm] +api_base_url = "https://your-resource.openai.azure.com/openai/deployments/your-deployment" +api_key = "${AZURE_OPENAI_KEY}" +model_efficient = "gpt-4" + +[embedding] +api_base_url = "https://your-resource.openai.azure.com/openai/deployments/embedding-deployment" +api_key = "${AZURE_OPENAI_KEY}" +model_name = "text-embedding-ada-002" + +[qdrant] +embedding_dim = 1536 +``` + +### Local LLM (Ollama) + +```toml +[llm] +api_base_url = "http://localhost:11434/v1" +api_key = "ollama" +model_efficient = "llama3.2" + +[embedding] +api_base_url = "http://localhost:11434/v1" +api_key = "ollama" +model_name = "nomic-embed-text" + +[qdrant] +embedding_dim = 768 # Check your model's dimension +``` + +--- + +## CLI Configuration + +### cortex-mem-cli + +```bash +# Specify config file +cortex-mem --config /path/to/config.toml [command] + +# Specify tenant +cortex-mem --config config.toml --tenant my-tenant [command] + +# Verbose output +cortex-mem --config config.toml --verbose [command] +``` + +### cortex-mem-service + +```bash +# Basic start +cortex-mem-service --config config.toml + +# Custom host and port +cortex-mem-service --config config.toml --host 0.0.0.0 --port 9000 + +# Verbose logging +cortex-mem-service --config config.toml --verbose + +# Log to file +cortex-mem-service --config config.toml --log-file logs/service.log +``` + +### cortex-mem-mcp + +```bash +# Start MCP server +cortex-mem-mcp --config config.toml +``` + +--- + +## Validation + +Check configuration validity: + +```bash +# CLI will report errors on startup +cortex-mem --config config.toml stats + +# Service health check +curl http://localhost:8085/health +``` + +--- + +## Troubleshooting + +### Common Issues + +1. **Embedding dimension mismatch** + - Error: Vector dimension doesn't match + - Solution: Set `embedding_dim` to match your embedding model + +2. **API key not found** + - Error: Authentication failed + - Solution: Set environment variables or use literal keys in config + +3. **Qdrant connection failed** + - Error: Connection refused + - Solution: Ensure Qdrant is running on the configured port + +4. **Collection not found** + - Error: Collection doesn't exist + - Solution: Collection is auto-created on first use; ensure config is correct + +### Debug Mode + +Enable debug logging: + +```toml +[logging] +level = "debug" +``` + +Or use CLI flag: +```bash +cortex-mem-service --config config.toml --verbose +``` diff --git a/.ai-context/development-guide.md b/.ai-context/development-guide.md new file mode 100644 index 0000000..9f5312c --- /dev/null +++ b/.ai-context/development-guide.md @@ -0,0 +1,379 @@ +# Development Guide + +## Prerequisites + +- **Rust**: 1.86 or later (Edition 2024) +- **Qdrant**: 1.7+ (for vector search) +- **LLM API**: OpenAI-compatible endpoint +- **Embedding API**: OpenAI-compatible endpoint + +## Getting Started + +### 1. Clone and Build + +```bash +git clone https://github.com/sopaco/cortex-mem.git +cd cortex-mem +cargo build --workspace +``` + +### 2. Configure + +Create `config.toml` in the project root: + +```toml +[qdrant] +url = "http://localhost:6334" +collection_name = "cortex-memory" +embedding_dim = 1536 + +[llm] +api_base_url = "https://api.openai.com/v1" +api_key = "${OPENAI_API_KEY}" +model_efficient = "gpt-5-mini" + +[embedding] +api_base_url = "https://api.openai.com/v1" +api_key = "${OPENAI_API_KEY}" +model_name = "text-embedding-3-small" + +[server] +host = "localhost" +port = 8085 +``` + +### 3. Run Services + +```bash +# Terminal 1: Start Qdrant (if not already running) +qdrant + +# Terminal 2: Start the service +cargo run --bin cortex-mem-service -- --config config.toml + +# Terminal 3: Use the CLI +cargo run --bin cortex-mem -- --config config.toml --help +``` + +--- + +## Project Structure + +``` +cortex-mem/ +├── cortex-mem-core/ # Core library +│ ├── src/ +│ │ ├── lib.rs # Main entry point +│ │ ├── builder.rs # Builder pattern +│ │ ├── types.rs # Core types +│ │ ├── filesystem/ # Virtual filesystem +│ │ ├── session/ # Session management +│ │ ├── search/ # Vector search +│ │ ├── layers/ # L0/L1 generation +│ │ ├── llm/ # LLM client +│ │ ├── embedding/ # Embedding client +│ │ ├── vector_store/ # Qdrant integration +│ │ └── automation/ # Background tasks +│ └── Cargo.toml +│ +├── cortex-mem-service/ # REST API server +│ ├── src/ +│ │ ├── main.rs # Entry point +│ │ ├── state.rs # App state +│ │ ├── models.rs # API models +│ │ ├── routes/ # Route definitions +│ │ └── handlers/ # Request handlers +│ └── Cargo.toml +│ +├── cortex-mem-cli/ # CLI tool +│ ├── src/ +│ │ ├── main.rs # Entry point +│ │ └── commands/ # Command implementations +│ └── Cargo.toml +│ +├── cortex-mem-mcp/ # MCP server +│ ├── src/ +│ │ ├── main.rs # Entry point +│ │ └── service.rs # Tool registration +│ └── Cargo.toml +│ +├── cortex-mem-tools/ # MCP tools +│ ├── src/ +│ │ ├── lib.rs # Exports +│ │ ├── operations.rs # Operations +│ │ ├── tools/ # Tool definitions +│ │ └── mcp/ # MCP types +│ └── Cargo.toml +│ +├── cortex-mem-rig/ # Rig integration +│ ├── src/ +│ │ ├── lib.rs # Tool registration +│ │ └── tools/ # Rig tools +│ └── Cargo.toml +│ +├── cortex-mem-config/ # Configuration +│ ├── src/ +│ │ └── lib.rs # Config parsing +│ └── Cargo.toml +│ +└── cortex-mem-insights/ # Web dashboard + ├── src/ + │ ├── App.svelte # Main component + │ ├── main.ts # Entry point + │ └── lib/ # Utilities + └── package.json +``` + +--- + +## Coding Conventions + +### Rust Style + +1. **Async by default**: Use `async fn` for I/O operations +2. **Result handling**: Use `anyhow::Result` for application code, `thiserror` for library errors +3. **Arc for sharing**: Use `Arc` for shared state +4. **RwLock for state**: Use `RwLock` for mutable shared state + +```rust +// Good +pub async fn search(&self, query: &str) -> Result> { + let engine = self.vector_engine.read().await; + // ... +} + +// Avoid blocking in async +pub async fn bad_example(&self) -> Result<()> { + std::fs::read_to_string("file.txt")?; // Blocks! + // Use tokio::fs instead +} +``` + +### Error Handling + +```rust +// Define errors in error.rs +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("Invalid URI: {0}")] + InvalidUri(String), + + #[error("File not found: {0}")] + NotFound(String), +} + +// Use anyhow for application code +pub fn do_something() -> anyhow::Result<()> { + // ... +} +``` + +### Trait Design + +```rust +// Define traits for abstraction +#[async_trait] +pub trait FilesystemOperations: Send + Sync { + async fn list(&self, uri: &str) -> Result>; + async fn read(&self, uri: &str) -> Result; + async fn write(&self, uri: &str, content: &str) -> Result<()>; +} +``` + +--- + +## Testing + +### Unit Tests + +```bash +# Run all tests +cargo test --workspace + +# Run specific crate tests +cargo test -p cortex-mem-core + +# Run with output +cargo test --workspace -- --nocapture +``` + +### Integration Tests + +Integration tests are in `tests/` directories: + +``` +cortex-mem-cli/ +└── tests/ + └── cli_commands_test.rs +``` + +### Test Configuration + +Create a test `config.toml` with test credentials. + +--- + +## Adding New Features + +### Adding a New API Endpoint + +1. **Define route** in `cortex-mem-service/src/routes/mod.rs`: + +```rust +pub fn api_routes() -> Router> { + Router::new() + // ... existing routes + .route("/my-endpoint", get(handlers::my_module::my_handler)) +} +``` + +2. **Create handler** in `cortex-mem-service/src/handlers/my_module.rs`: + +```rust +pub async fn my_handler( + State(state): State>, + Query(params): Query, +) -> Result>> { + // Implementation + Ok(Json(ApiResponse::success(data))) +} +``` + +3. **Define models** in `cortex-mem-service/src/models.rs`: + +```rust +#[derive(Debug, Deserialize)] +pub struct MyParams { + pub query: String, +} + +#[derive(Debug, Serialize)] +pub struct MyResponse { + pub result: String, +} +``` + +### Adding a New CLI Command + +1. **Add command** in `cortex-mem-cli/src/commands/my_command.rs`: + +```rust +pub async fn execute(config: &Config, args: MyArgs) -> Result<()> { + // Implementation +} +``` + +2. **Register in main.rs**: + +```rust +Commands::MyCommand(args) => { + commands::my_command::execute(&config, args).await?; +} +``` + +### Adding a New MCP Tool + +1. **Define tool schema** in `cortex-mem-tools/src/tools/my_tool.rs`: + +```rust +pub const MY_TOOL: ToolSchema = ToolSchema { + name: "cortex_my_tool", + description: "Tool description", + input_schema: json!({ + "type": "object", + "properties": { + "param": { "type": "string" } + }, + "required": ["param"] + }), +}; +``` + +2. **Add operation** in `cortex-mem-tools/src/operations.rs`: + +```rust +pub async fn my_operation(core: &CortexMem, param: &str) -> Result { + // Implementation +} +``` + +3. **Register in MCP** in `cortex-mem-mcp/src/service.rs`: + +```rust +server.tool( + tools::MY_TOOL.name, + tools::MY_TOOL.schema(), + my_handler, +)?; +``` + +--- + +## Debugging + +### Enable Debug Logging + +```toml +# config.toml +[logging] +level = "debug" +``` + +Or via CLI: +```bash +RUST_LOG=debug cargo run --bin cortex-mem-service +``` + +### Common Debug Points + +1. **URI Parsing**: `cortex-mem-core/src/filesystem/uri.rs` +2. **Search Flow**: `cortex-mem-core/src/search/engine.rs` +3. **Layer Generation**: `cortex-mem-core/src/layers/generator.rs` +4. **API Requests**: `cortex-mem-service/src/handlers/` + +### Inspecting Data + +```bash +# List sessions +curl http://localhost:8085/api/v2/sessions + +# List files +curl "http://localhost:8085/api/v2/filesystem/list?uri=cortex://session&recursive=true" + +# Check Qdrant +curl http://localhost:6333/collections +``` + +--- + +## Release Process + +1. Update version in all `Cargo.toml` files +2. Update `CHANGELOG.md` +3. Run tests: `cargo test --workspace` +4. Build release: `cargo build --workspace --release` +5. Create git tag: `git tag v2.x.x` +6. Push: `git push --tags` + +--- + +## Contributing + +1. Fork the repository +2. Create a feature branch +3. Make changes with tests +4. Run `cargo fmt` and `cargo clippy` +5. Submit pull request + +### Code Quality + +```bash +# Format code +cargo fmt + +# Lint +cargo clippy --workspace --all-targets -- -D warnings + +# Check documentation +cargo doc --workspace --no-deps +``` diff --git a/.ai-context/modules.md b/.ai-context/modules.md new file mode 100644 index 0000000..153fbc5 --- /dev/null +++ b/.ai-context/modules.md @@ -0,0 +1,331 @@ +# Modules Reference + +## Workspace Structure + +``` +cortex-mem/ +├── cortex-mem-core/ # Core business logic +├── cortex-mem-service/ # REST API server +├── cortex-mem-cli/ # Command-line interface +├── cortex-mem-mcp/ # MCP server +├── cortex-mem-tools/ # MCP tools & operations +├── cortex-mem-rig/ # Rig framework integration +├── cortex-mem-config/ # Configuration management +└── cortex-mem-insights/ # Web dashboard (Svelte) +``` + +--- + +## cortex-mem-core + +**Purpose**: Core business logic and storage abstraction. + +### Key Files + +| File | Purpose | +|------|---------| +| `lib.rs` | Main `CortexMem` struct, builder pattern | +| `builder.rs` | `CortexMemBuilder` for dependency injection | +| `types.rs` | Core types: `Dimension`, `FileEntry`, `Memory` | +| `error.rs` | Error types | +| `config.rs` | Runtime configuration | + +### Submodules + +#### `filesystem/` +Virtual filesystem with `cortex://` URI scheme. + +| File | Key Types | +|------|-----------| +| `uri.rs` | `CortexUri`, `UriParser` | +| `operations.rs` | `CortexFilesystem`, `FilesystemOperations` trait | + +#### `session/` +Session and conversation management. + +| File | Key Types | +|------|-----------| +| `manager.rs` | `SessionManager` | +| `types.rs` | `Session`, `Message` | + +#### `search/` +Vector search engine with L0/L1/L2 scoring. + +| File | Key Types | +|------|-----------| +| `engine.rs` | `VectorSearchEngine` | +| `options.rs` | `SearchOptions` | + +#### `layers/` +L0 abstract and L1 overview generation. + +| File | Key Types | +|------|-----------| +| `generator.rs` | `LayerGenerator` | +| `cascade_layer_updater.rs` | `CascadeLayerUpdater` | + +#### `llm/` +LLM client abstraction. + +| File | Key Types | +|------|-----------| +| `client.rs` | `LLMClient` trait, `LLMClientImpl` | +| `prompt.rs` | Prompt templates | + +#### `embedding/` +Embedding generation. + +| File | Key Types | +|------|-----------| +| `client.rs` | `EmbeddingClient`, `EmbeddingConfig` | + +#### `vector_store/` +Qdrant integration. + +| File | Key Types | +|------|-----------| +| `qdrant.rs` | `QdrantVectorStore` | +| `mod.rs` | `VectorStore` trait | + +#### `automation/` +Background automation. + +| File | Key Types | +|------|-----------| +| `sync_manager.rs` | `SyncManager` | +| `auto_indexer.rs` | `AutoIndexer` | + +#### `init/` +Bootstrap and initialization. + +| File | Key Types | +|------|-----------| +| `bootstrap.rs` | Tenant initialization | + +### Key Types + +```rust +// Core dimensions for memory storage +pub enum Dimension { + Resources, + User, + Agent, + Session, +} + +// Main runtime +pub struct CortexMem { + pub filesystem: Arc, + pub session_manager: Arc>, + pub vector_store: Option>, + pub embedding: Option>, + pub llm_client: Option>, +} + +// Search options +pub struct SearchOptions { + pub limit: usize, + pub threshold: f32, + pub root_uri: Option, + pub recursive: bool, +} +``` + +--- + +## cortex-mem-service + +**Purpose**: REST API server exposing all memory operations. + +### Key Files + +| File | Purpose | +|------|---------| +| `main.rs` | Server entry point, route setup | +| `state.rs` | `AppState` with tenant management | +| `models.rs` | API request/response models | +| `error.rs` | API error types | + +### Routes + +| File | Endpoints | +|------|-----------| +| `routes/filesystem.rs` | `/api/v2/filesystem/*` | +| `routes/sessions.rs` | `/api/v2/sessions/*` | +| `routes/search.rs` | `/api/v2/search` | +| `routes/tenants.rs` | `/api/v2/tenants/*` | +| `routes/automation.rs` | `/api/v2/automation/*` | + +### Handlers + +| File | Handlers | +|------|----------| +| `handlers/filesystem.rs` | `list_directory`, `read_file`, `get_abstract`, etc. | +| `handlers/sessions.rs` | `list_sessions`, `create_session`, `add_message`, etc. | +| `handlers/search.rs` | `semantic_search` | +| `handlers/tenants.rs` | `list_tenants`, `switch_tenant` | + +### Key Types + +```rust +// Application state +pub struct AppState { + pub cortex: Arc>>, + pub session_manager: Arc>>>, + pub vector_engine: Arc>>>, + pub data_dir: PathBuf, + pub current_tenant_root: Arc>>, + pub current_tenant_id: Arc>>, +} + +// API response wrapper +pub struct ApiResponse { + pub success: bool, + pub data: Option, + pub error: Option, + pub timestamp: DateTime, +} +``` + +--- + +## cortex-mem-cli + +**Purpose**: Command-line interface for memory operations. + +### Key Files + +| File | Purpose | +|------|---------| +| `main.rs` | CLI entry point, argument parsing | +| `commands/*.rs` | Individual command implementations | + +### Commands + +| Command | Description | +|---------|-------------| +| `add` | Add a message to a session | +| `search` | Semantic search | +| `list` | List directory contents | +| `get` | Get a specific memory | +| `delete` | Delete a memory | +| `session` | Session management (list, create, close) | +| `layers` | Layer management (status, ensure-all) | +| `tenant` | Tenant operations | +| `stats` | System statistics | +| `vector` | Vector operations (reindex, prune) | + +--- + +## cortex-mem-mcp + +**Purpose**: Model Context Protocol server for AI assistant integration. + +### Key Files + +| File | Purpose | +|------|---------| +| `main.rs` | MCP server entry point | +| `service.rs` | Tool registration and execution | + +### Integration + +Works with: +- Claude Desktop +- Cursor IDE +- Other MCP-compatible AI assistants + +--- + +## cortex-mem-tools + +**Purpose**: MCP tool schemas and operation wrappers. + +### Key Files + +| File | Purpose | +|------|---------| +| `lib.rs` | Tool exports | +| `tools/*.rs` | Individual tool definitions | +| `operations.rs` | Operation implementations | +| `types.rs` | Shared types | +| `mcp/*.rs` | MCP-specific types | + +### Tools Provided + +| Tool | Description | +|------|-------------| +| `cortex_search` | Semantic search with layered retrieval | +| `cortex_recall` | Recall with extended context | +| `cortex_add_memory` | Store messages | +| `cortex_close_session` | Close session & trigger extraction | +| `cortex_ls` | List directory contents | +| `cortex_get_abstract` | Get L0 abstract | +| `cortex_get_overview` | Get L1 overview | +| `cortex_get_content` | Get L2 full content | + +--- + +## cortex-mem-rig + +**Purpose**: Integration with Rig agent framework. + +### Key Files + +| File | Purpose | +|------|---------| +| `lib.rs` | Rig tool registration | +| `tools/*.rs` | Rig-specific tool implementations | + +--- + +## cortex-mem-config + +**Purpose**: Configuration file parsing and management. + +### Key Files + +| File | Purpose | +|------|---------| +| `lib.rs` | Config struct, TOML parsing | + +### Key Types + +```rust +pub struct Config { + pub qdrant: QdrantConfig, + pub llm: LLMConfig, + pub embedding: EmbeddingConfig, + pub cortex: CortexConfig, + pub server: ServerConfig, + pub logging: LoggingConfig, +} +``` + +--- + +## cortex-mem-insights + +**Purpose**: Web dashboard for monitoring and management. + +### Tech Stack + +- Svelte 5 +- TypeScript +- Vite +- Tailwind CSS + +### Key Files + +| File | Purpose | +|------|---------| +| `src/App.svelte` | Main application | +| `src/lib/` | Utility functions and components | +| `server.ts` | Development server with proxy | + +### Features + +- Tenant management +- Memory browser +- Semantic search UI +- Health monitoring diff --git a/.ai-context/project-overview.md b/.ai-context/project-overview.md new file mode 100644 index 0000000..feec84f --- /dev/null +++ b/.ai-context/project-overview.md @@ -0,0 +1,115 @@ +# Project Overview + +## What is Cortex Memory? + +Cortex Memory is a **high-performance, AI-native memory framework** written in Rust. It provides persistent, intelligent long-term memory for AI agents and applications. + +## Core Value Proposition + +Transform stateless AI into context-aware, intelligent partners that: +- Remember user preferences across sessions +- Learn and adapt over time +- Maintain context across multiple conversations +- Build personalized experiences + +## Key Features + +| Feature | Description | +|---------|-------------| +| **Virtual Filesystem** | Memory stored as markdown files via `cortex://` URI scheme | +| **Three-Tier Hierarchy** | L0 Abstract → L1 Overview → L2 Detail for token-efficient retrieval | +| **Vector Search** | Semantic search via Qdrant with weighted L0/L1/L2 scoring | +| **Memory Extraction** | LLM-powered extraction of structured memories from conversations | +| **Multi-Tenancy** | Isolated memory spaces for different users/agents | +| **Multi-Modal Access** | REST API, CLI, MCP protocol, Rust library | + +## Architecture Highlights + +``` +Input (User/Agent Messages) + │ + ▼ +┌─────────────────────────────────────┐ +│ cortex-mem-core │ +│ ┌──────────┐ ┌─────────────────┐ │ +│ │ Session │ │ Memory Extractor│ │ +│ │ Manager │ │ (LLM-powered) │ │ +│ └────┬─────┘ └────────┬────────┘ │ +│ │ │ │ +│ ▼ ▼ │ +│ ┌──────────────────────────────┐ │ +│ │ Virtual Filesystem │ │ +│ │ (cortex:// URI) │ │ +│ └──────────────┬───────────────┘ │ +│ │ │ +│ ┌────────┴────────┐ │ +│ ▼ ▼ │ +│ ┌─────────┐ ┌───────────────┐ │ +│ │ Layer │ │ Vector Search │ │ +│ │ Generator│ │ Engine │ │ +│ └─────────┘ └───────┬───────┘ │ +└──────────────────────────┼──────────┘ + │ + ┌──────────────────┼──────────────────┐ + ▼ ▼ ▼ + ┌─────────┐ ┌──────────┐ ┌─────────┐ + │ Filesystem│ │ Qdrant │ │ LLM API │ + │ (Markdown)│ │ (Vector) │ │ │ + └──────────┘ └──────────┘ └─────────┘ +``` + +## Project Ecosystem + +### Core Crates + +| Crate | Purpose | +|-------|---------| +| `cortex-mem-core` | Core business logic, filesystem, search, extraction | +| `cortex-mem-service` | REST API server (Axum, port 8085) | +| `cortex-mem-cli` | Command-line interface | +| `cortex-mem-mcp` | Model Context Protocol server | +| `cortex-mem-tools` | MCP tool schemas and operations | +| `cortex-mem-rig` | Rig framework integration | +| `cortex-mem-config` | Configuration management | + +### Example Applications + +| Example | Description | +|---------|-------------| +| `examples/@memclaw/plugin` | OpenClaw memory plugin (MemClaw) | +| `examples/cortex-mem-tars` | TUI AI assistant with voice memory | +| `examples/locomo-evaluation` | Benchmark evaluation scripts | + +### Frontend + +| Component | Description | +|-----------|-------------| +| `cortex-mem-insights` | Svelte 5 SPA dashboard for monitoring | + +## Performance Highlights + +Based on LoCoMo10 benchmark (152 questions): + +| Metric | Value | +|--------|-------| +| Overall Score | 68.42% | +| Multi-hop Reasoning | 84.29% | +| Token Efficiency | 11× fewer than OpenClaw+LanceDB | +| Score per 1K Tokens | 23.6 | + +## Technology Stack + +- **Language**: Rust 1.86+ (Edition 2024) +- **Async Runtime**: Tokio +- **Web Framework**: Axum 0.7 +- **Vector Database**: Qdrant +- **Serialization**: serde, serde_json +- **CLI**: clap 4.5 +- **Frontend**: Svelte 5, TypeScript, Vite + +## Use Cases + +1. **AI Chatbots & Assistants** - Long-term memory for personalized interactions +2. **Agent Frameworks** - Memory backbone for AI agents (Rig, MCP) +3. **OpenClaw Integration** - Enhanced memory via MemClaw plugin +4. **Knowledge Management** - Structured memory extraction from conversations diff --git a/.ai-context/uri-structure.md b/.ai-context/uri-structure.md new file mode 100644 index 0000000..9107738 --- /dev/null +++ b/.ai-context/uri-structure.md @@ -0,0 +1,229 @@ +# URI Structure Reference + +## Overview + +Cortex Memory uses a virtual filesystem with the `cortex://` URI scheme. All memory resources are addressed using this format. + +## URI Format + +``` +cortex://{dimension}/{category}/{subcategory}/{resource} +``` + +## Dimensions + +| Dimension | Purpose | Examples | +|-----------|---------|----------| +| `session` | Conversation memories | Timeline, session metadata | +| `user` | User-specific memories | Preferences, entities, events | +| `agent` | Agent-specific memories | Cases, skills, instructions | +| `resources` | General knowledge | Facts, documentation | + +--- + +## Complete URI Structure + +``` +cortex:// +├── session/{session_id}/ +│ ├── timeline/ +│ │ ├── {YYYY-MM}/ # Year-month directory +│ │ │ ├── {DD}/ # Day directory +│ │ │ │ ├── {HH_MM_SS}_{id}.md # L2: Original message +│ │ │ │ ├── .abstract.md # L0: Day-level abstract +│ │ │ │ └── .overview.md # L1: Day-level overview +│ │ │ └── .abstract.md # L0: Month-level abstract +│ │ ├── .abstract.md # L0: Session-level abstract +│ │ └── .overview.md # L1: Session-level overview +│ └── .session.json # Session metadata +│ +├── user/{user_id}/ # User-specific data (default user_id: "default") +│ ├── preferences/{name}.md # User preferences +│ ├── entities/{name}.md # People, projects, concepts +│ ├── events/{name}.md # Decisions, milestones +│ ├── personal_info/{name}.md # User profile info +│ ├── goals/{name}.md # User goals +│ ├── relationships/{name}.md # User relationships +│ └── work_history/{name}.md # Work history +│ +├── agent/{agent_id}/ # Agent-specific data +│ ├── cases/{name}.md # Problem-solution cases +│ ├── skills/{name}.md # Acquired skills +│ └── instructions/{name}.md # Learned instructions +│ +└── resources/{resource_name}/ # General knowledge +``` + +**Important**: The `user_id` in `cortex://user/{user_id}/...` is required. In most scenarios (e.g., MemClaw plugin), the default value is `"default"`. + +--- + +## Layer Files + +Each memory can have three representation layers: + +| Layer | Filename | Tokens | Purpose | +|-------|----------|--------|---------| +| L0 (Abstract) | `.abstract.md` | ~100 | Quick relevance check | +| L1 (Overview) | `.overview.md` | ~2000 | Understanding gist | +| L2 (Detail) | `{name}.md` | Full | Exact quotes, complete content | + +### Layer Resolution Rules + +1. **For files** (ending with `.md`): + - Layer files are in the **same directory** as the content file + - Example: `cortex://session/abc/timeline/2024-03/15/10_30_00.md` + - L0: `timeline/2024-03/15/.abstract.md` + - L1: `timeline/2024-03/15/.overview.md` + - L2: `timeline/2024-03/15/10_30_00.md` + +2. **For directories**: + - Layer files are **directly in** that directory + - Example: `cortex://session/abc/timeline` + - L0: `timeline/.abstract.md` + - L1: `timeline/.overview.md` + +--- + +## Common URI Examples + +### Session Operations + +``` +# List all sessions +cortex://session + +# Browse a specific session +cortex://session/{session_id} + +# View timeline messages +cortex://session/{session_id}/timeline + +# View timeline for a specific month +cortex://session/{session_id}/timeline/2024-03 + +# View timeline for a specific day +cortex://session/{session_id}/timeline/2024-03/15 + +# Access a specific message +cortex://session/{session_id}/timeline/2024-03/15/10_30_45_abc123.md +``` + +### User Memory Operations + +``` +# List users (shows user directories) +cortex://user + +# List user preferences (requires user_id) +cortex://user/{user_id}/preferences +# Example: cortex://user/default/preferences + +# Access a specific preference +cortex://user/{user_id}/preferences/typescript.md +# Example: cortex://user/default/preferences/pref_abc123.md + +# List user entities +cortex://user/{user_id}/entities +# Example: cortex://user/default/entities + +# Access a specific entity +cortex://user/{user_id}/entities/project_alpha.md +# Example: cortex://user/default/entities/entity_xyz.md + +# List user events +cortex://user/{user_id}/events + +# Access a specific event +cortex://user/{user_id}/events/launch_decision.md +``` + +### Agent Memory Operations + +``` +# List agent cases +cortex://agent/{agent_id}/cases + +# Access a specific case +cortex://agent/{agent_id}/cases/case_123.md + +# List agent skills +cortex://agent/{agent_id}/skills + +# Access a specific skill +cortex://agent/{agent_id}/skills/rust_programming.md +``` + +--- + +## API Mapping + +| URI | API Endpoint | +|-----|--------------| +| `cortex://session` | `GET /api/v2/filesystem/list?uri=cortex://session` | +| `cortex://session/{id}/timeline` | `GET /api/v2/filesystem/list?uri=cortex://session/{id}/timeline` | +| L0 access | `GET /api/v2/filesystem/abstract?uri={uri}` | +| L1 access | `GET /api/v2/filesystem/overview?uri={uri}` | +| L2 access | `GET /api/v2/filesystem/content?uri={uri}` | + +--- + +## Physical File Mapping + +URI to filesystem path mapping: + +``` +cortex://session/abc/timeline/2024-03/15/msg.md + ↓ +{data_dir}/tenants/{tenant_id}/session/abc/timeline/2024-03/15/msg.md +``` + +Without tenant: +``` +cortex://session/abc/timeline/2024-03/15/msg.md + ↓ +{data_dir}/session/abc/timeline/2024-03/15/msg.md +``` + +--- + +## Timeline File Naming + +Timeline messages follow the pattern: +``` +{HH_MM_SS}_{random_id}.md +``` + +Example: `14_30_45_abc123.md` +- `14_30_45` - Time (14:30:45) +- `abc123` - Random ID for uniqueness + +--- + +## Session Metadata + +Each session has a `.session.json` file: + +```json +{ + "thread_id": "session_id", + "status": "active|closed|archived", + "created_at": "2024-03-15T10:30:00Z", + "updated_at": "2024-03-15T12:45:00Z", + "closed_at": null, + "message_count": 25, + "participants": ["user_001", "agent_001"], + "tags": ["typescript", "api-design"], + "title": "Optional session title" +} +``` + +--- + +## Important Notes + +1. **No `memories` subdirectory**: Unlike some documentation might suggest, session memories are NOT under `cortex://session/{id}/memories/`. Extracted memories are stored in user/agent dimensions based on their type. + +2. **Layer files are hidden**: `.abstract.md` and `.overview.md` are hidden files. Use `include_layers=true` parameter in `cortex_ls` to see them. + +3. **Tenant isolation**: Each tenant has completely separate storage. Switch tenants via API before accessing their data. diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..6a9a436 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,159 @@ +# Cortex Memory - AI Agent Context Guide + +> This file provides essential context for AI coding agents working on the Cortex Memory project. + +## Quick Start for Agents + +1. **Read `.ai-context/project-overview.md`** to understand what this project is about +2. **Read `.ai-context/architecture.md`** to understand the system design +3. **Read `.ai-context/modules.md`** to understand each crate's responsibility +4. **Read `.ai-context/uri-structure.md`** to understand the `cortex://` URI scheme +5. **Read `.ai-context/api-reference.md`** for REST API endpoints + +## Project Summary + +Cortex Memory is a **Rust-based AI-native memory framework** that provides: +- Three-tier memory hierarchy (L0 Abstract → L1 Overview → L2 Detail) +- Virtual filesystem with `cortex://` URI scheme +- Vector-based semantic search via Qdrant +- Multi-tenant support + +## Key Technical Decisions + +| Aspect | Decision | +|--------|----------| +| Language | Rust 1.86+ (Edition 2024) | +| Async Runtime | Tokio | +| Web Framework | Axum | +| Vector DB | Qdrant | +| API Version | `/api/v2/*` | +| Default Port | 8085 | + +## Common Tasks + +### Adding a New API Endpoint + +1. Add route in `cortex-mem-service/src/routes/mod.rs` +2. Add handler in `cortex-mem-service/src/handlers/` +3. Add models in `cortex-mem-service/src/models.rs` + +### Adding a New Tool (MCP) + +1. Define tool schema in `cortex-mem-tools/src/tools/` +2. Add operation in `cortex-mem-tools/src/operations.rs` +3. Register in `cortex-mem-mcp/src/service.rs` + +### Modifying URI Structure + +1. Update `cortex-mem-core/src/filesystem/uri.rs` +2. Update `cortex-mem-core/src/types.rs` (Dimension enum) +3. Update `.ai-context/uri-structure.md` + +## File Locations Quick Reference + +| What | Where | +|------|-------| +| Core business logic | `cortex-mem-core/src/` | +| REST API handlers | `cortex-mem-service/src/handlers/` | +| REST API routes | `cortex-mem-service/src/routes/` | +| MCP tools | `cortex-mem-tools/src/tools/` | +| CLI commands | `cortex-mem-cli/src/commands/` | +| Configuration | `cortex-mem-config/src/lib.rs` | +| URI parsing | `cortex-mem-core/src/filesystem/uri.rs` | +| Vector search | `cortex-mem-core/src/search/` | +| Session management | `cortex-mem-core/src/session/` | +| Layer generation | `cortex-mem-core/src/layers/` | +| LLM client | `cortex-mem-core/src/llm/` | +| Embedding | `cortex-mem-core/src/embedding/` | +| MemClaw plugin | `examples/@memclaw/plugin/` | + +## Build & Test Commands + +```bash +# Build all crates +cargo build --workspace + +# Build release +cargo build --workspace --release + +# Run tests +cargo test --workspace + +# Run the service +cargo run --bin cortex-mem-service -- --config config.toml + +# Run CLI +cargo run --bin cortex-mem -- --help + +# Run MCP server +cargo run --bin cortex-mem-mcp -- --config config.toml +``` + +## Configuration + +Configuration is via `config.toml`. See `.ai-context/configuration.md` for details. + +Key environment variables: +- `OPENAI_API_KEY` or `LLM_API_KEY` - LLM API key +- `EMBEDDING_API_KEY` - Embedding API key + +## Data Directory Structure + +``` +cortex-data/ +├── tenants/ +│ └── {tenant_id}/ +│ ├── session/{session_id}/timeline/{YYYY-MM}/{DD}/{HH_MM_SS}_{id}.md +│ ├── user/{user_id}/preferences/{name}.md +│ ├── user/{user_id}/entities/{name}.md +│ ├── user/{user_id}/events/{name}.md +│ ├── agent/{agent_id}/cases/{name}.md +│ └── resources/ +``` + +**Note**: `user_id` is required in the path. Default value is `"default"` in most scenarios. + +## Important Patterns + +### Three-Tier Layer Access + +```rust +// L0: Abstract (~100 tokens) - Quick relevance check +GET /api/v2/filesystem/abstract?uri=cortex://session/{id}/timeline + +// L1: Overview (~2000 tokens) - Moderate detail +GET /api/v2/filesystem/overview?uri=cortex://session/{id}/timeline + +// L2: Full content - Complete original +GET /api/v2/filesystem/content?uri=cortex://session/{id}/timeline/{file}.md +``` + +### Session Lifecycle + +1. `POST /api/v2/sessions` - Create session +2. `POST /api/v2/sessions/{id}/messages` - Add messages +3. `POST /api/v2/sessions/{id}/close` - Close & trigger extraction + +### Search with Layered Retrieval + +```json +POST /api/v2/search +{ + "query": "user preferences", + "return_layers": ["L0", "L1"], + "limit": 10, + "min_score": 0.6 +} +``` + +## Context Files + +| File | Purpose | +|------|---------| +| `project-overview.md` | Project goals, features, and ecosystem | +| `architecture.md` | System architecture and data flow | +| `modules.md` | Each crate's responsibility and key types | +| `uri-structure.md` | Complete URI scheme reference | +| `api-reference.md` | All REST API endpoints | +| `configuration.md` | Configuration file format | +| `development-guide.md` | Development workflow and conventions | diff --git a/cortex-mem-mcp/skill/SKILL.md b/cortex-mem-mcp/skill/SKILL.md index 6f95086..8563581 100644 --- a/cortex-mem-mcp/skill/SKILL.md +++ b/cortex-mem-mcp/skill/SKILL.md @@ -82,7 +82,7 @@ data_dir = "~/.cortex-data" # LLM API configuration api_base_url = "https://api.openai.com/v1" api_key = "your-api-key" -model_efficient = "gpt-4o-mini" +model_efficient = "gpt-5-mini" temperature = 0.1 max_tokens = 65536 @@ -288,7 +288,7 @@ List directory contents to browse the memory space. Common URIs: - `cortex://session` - List all sessions - `cortex://user` - List user-level memories -- `cortex://user/preferences` - User preference memories +- `cortex://user/{user_id}/preferences` - User preference memories #### `explore` Smart exploration of memory space, combining search and browsing. @@ -316,7 +316,7 @@ Get L0 abstract layer for quick relevance checking. ```json { - "uri": "cortex://session/project-alpha/conversation.md" + "uri": "cortex://session/project-alpha/timeline/2024-03/15/10_30_45_abc123.md" } ``` @@ -325,7 +325,7 @@ Get L1 overview layer for understanding core information. ```json { - "uri": "cortex://session/project-alpha/conversation.md" + "uri": "cortex://session/project-alpha/timeline/2024-03/15/10_30_45_abc123.md" } ``` @@ -334,7 +334,7 @@ Get L2 full content layer - the complete original content. ```json { - "uri": "cortex://session/project-alpha/conversation.md" + "uri": "cortex://session/project-alpha/timeline/2024-03/15/10_30_45_abc123.md" } ``` @@ -345,7 +345,7 @@ Delete a memory by its URI. ```json { - "uri": "cortex://session/old-project/conversation.md" + "uri": "cortex://session/old-project/timeline/2024-03/15/10_30_45_xyz.md" } ``` @@ -372,11 +372,16 @@ Index memory files for vector search. Memories are organized using a URI scheme: ``` -cortex://session/{thread_id}/conversation.md +cortex://session/{thread_id}/timeline/{YYYY-MM}/{DD}/{HH_MM_SS}_{id}.md cortex://user/{user_id}/preferences/{topic}.md -cortex://user/{user_id}/memories/{memory_id}.md +cortex://user/{user_id}/entities/{name}.md +cortex://user/{user_id}/events/{name}.md +cortex://agent/{agent_id}/cases/{name}.md +cortex://agent/{agent_id}/skills/{name}.md ``` +**Note**: Session dimension stores conversation timeline; extracted memories (preferences, entities, etc.) are stored in user/agent dimensions after `commit`. + ## Best Practices 1. **Use meaningful thread IDs** - Use descriptive names like `project-alpha` or `user-123-support` instead of generic IDs @@ -439,7 +444,7 @@ data_dir = "./cortex-data" [llm] api_base_url = "https://api.openai.com/v1" api_key = "your-api-key" -model_efficient = "gpt-4o-mini" +model_efficient = "gpt-5-mini" [embedding] api_base_url = "https://api.openai.com/v1" diff --git a/cortex-mem-tools/src/docs/ls.md b/cortex-mem-tools/src/docs/ls.md index bb1d407..03cded9 100644 --- a/cortex-mem-tools/src/docs/ls.md +++ b/cortex-mem-tools/src/docs/ls.md @@ -4,9 +4,11 @@ This allows you to explore the hierarchical structure of memories: - cortex://session - List all sessions - cortex://session/{session_id} - Browse a specific session's contents - cortex://session/{session_id}/timeline - View timeline messages -- cortex://session/{session_id}/memories - View extracted memories - cortex://user - View user-level memories (preferences, entities, goals) +- cortex://user/{user_id}/preferences - View user preferences (extracted memories) +- cortex://user/{user_id}/entities - View user entities (people, projects, etc.) - cortex://agent - View agent-level memories +- cortex://agent/{agent_id}/cases - View agent problem-solution cases **Parameters:** - recursive: List all subdirectories recursively diff --git a/cortex-mem-tools/src/tools/storage.rs b/cortex-mem-tools/src/tools/storage.rs index 15da387..5ee842f 100644 --- a/cortex-mem-tools/src/tools/storage.rs +++ b/cortex-mem-tools/src/tools/storage.rs @@ -21,6 +21,9 @@ impl MemoryOperations { }; // Build URI based on scope + // Note: This stores raw messages to memories/ subdirectory. + // Extracted structured memories (preferences, entities, cases, etc.) + // are stored in their respective directories after commit(). let uri = match scope { "user" => { // cortex://user/{user_id}/memories/YYYY-MM/DD/HH_MM_SS_id.md diff --git a/examples/@memclaw/bin-darwin-arm64/bin/cortex-mem-service b/examples/@memclaw/bin-darwin-arm64/bin/cortex-mem-service index 6ff5a73..d20554f 100755 --- a/examples/@memclaw/bin-darwin-arm64/bin/cortex-mem-service +++ b/examples/@memclaw/bin-darwin-arm64/bin/cortex-mem-service @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b40d2c395cd7bd84b9dfe2ce217a7117c245d7d9b78bcb6c7bb3fa44bd74609c -size 18453008 +oid sha256:10f2587bae12356e9e17be05effd530ed8953ec8de999a1a706bb9a1610a2e94 +size 18432000 diff --git a/examples/@memclaw/bin-darwin-arm64/package.json b/examples/@memclaw/bin-darwin-arm64/package.json index a5676a9..f08c2d9 100644 --- a/examples/@memclaw/bin-darwin-arm64/package.json +++ b/examples/@memclaw/bin-darwin-arm64/package.json @@ -1,24 +1,24 @@ { - "name": "@memclaw/bin-darwin-arm64", - "version": "0.1.7", - "description": "MemClaw binaries for macOS Apple Silicon", - "publishConfig": { - "access": "public" - }, - "os": [ - "darwin" - ], - "cpu": [ - "arm64" - ], - "files": [ - "bin/" - ], - "author": "Sopaco", - "license": "MIT", - "repository": { - "type": "git", - "url": "git+https://github.com/sopaco/cortex-mem.git", - "directory": "examples/@memclaw/bin-darwin-arm64" - } + "name": "@memclaw/bin-darwin-arm64", + "version": "0.1.8", + "description": "MemClaw binaries for macOS Apple Silicon", + "publishConfig": { + "access": "public" + }, + "os": [ + "darwin" + ], + "cpu": [ + "arm64" + ], + "files": [ + "bin/" + ], + "author": "Sopaco", + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/sopaco/cortex-mem.git", + "directory": "examples/@memclaw/bin-darwin-arm64" + } } diff --git a/examples/@memclaw/bin-linux-x64/bin/cortex-mem-service b/examples/@memclaw/bin-linux-x64/bin/cortex-mem-service index d9c7b14..f69acd4 100755 --- a/examples/@memclaw/bin-linux-x64/bin/cortex-mem-service +++ b/examples/@memclaw/bin-linux-x64/bin/cortex-mem-service @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dba835cc3a607cbf6bf7b9bd28bf9174c79f8a5e59f47353011affcf63dd96a0 -size 22085480 +oid sha256:5522bbfe7ff95e5a21e78ecdacc4eab4f69eda4802213f1926f5c15745a6f925 +size 22087144 diff --git a/examples/@memclaw/bin-linux-x64/package.json b/examples/@memclaw/bin-linux-x64/package.json index 514374b..ae07ffb 100644 --- a/examples/@memclaw/bin-linux-x64/package.json +++ b/examples/@memclaw/bin-linux-x64/package.json @@ -1,24 +1,24 @@ { - "name": "@memclaw/bin-linux-x64", - "version": "0.1.7", - "description": "MemClaw binaries for Linux x64", - "publishConfig": { - "access": "public" - }, - "os": [ - "linux" - ], - "cpu": [ - "x64" - ], - "files": [ - "bin/" - ], - "author": "Sopaco", - "license": "MIT", - "repository": { - "type": "git", - "url": "git+https://github.com/sopaco/cortex-mem.git", - "directory": "examples/@memclaw/bin-linux-x64" - } + "name": "@memclaw/bin-linux-x64", + "version": "0.1.8", + "description": "MemClaw binaries for Linux x64", + "publishConfig": { + "access": "public" + }, + "os": [ + "linux" + ], + "cpu": [ + "x64" + ], + "files": [ + "bin/" + ], + "author": "Sopaco", + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/sopaco/cortex-mem.git", + "directory": "examples/@memclaw/bin-linux-x64" + } } diff --git a/examples/@memclaw/plugin/README.md b/examples/@memclaw/plugin/README.md index 0b2b40c..324d95a 100644 --- a/examples/@memclaw/plugin/README.md +++ b/examples/@memclaw/plugin/README.md @@ -140,7 +140,7 @@ Configure MemClaw directly through OpenClaw plugin settings in `openclaw.json`: "autoStartServices": true, "llmApiBaseUrl": "https://api.openai.com/v1", "llmApiKey": "your-llm-api-key", - "llmModel": "gpt-4o-mini", + "llmModel": "gpt-5-mini", "embeddingApiBaseUrl": "https://api.openai.com/v1", "embeddingApiKey": "your-embedding-api-key", "embeddingModel": "text-embedding-3-small" @@ -274,7 +274,9 @@ List directory contents to browse the memory space like a virtual filesystem. - `cortex://session` - List all sessions - `cortex://session/{session_id}` - Browse a specific session - `cortex://session/{session_id}/timeline` - View timeline messages -- `cortex://session/{session_id}/memories` - View extracted memories +- `cortex://user/{user_id}/preferences` - View user preferences (extracted memories) +- `cortex://user/{user_id}/entities` - View user entities (people, projects, etc.) +- `cortex://agent/{agent_id}/cases` - View agent problem-solution cases ### cortex_get_abstract diff --git a/examples/@memclaw/plugin/README_zh.md b/examples/@memclaw/plugin/README_zh.md index fe42619..93b7399 100644 --- a/examples/@memclaw/plugin/README_zh.md +++ b/examples/@memclaw/plugin/README_zh.md @@ -140,7 +140,7 @@ ln -sf "$(pwd)" ~/.openclaw/extensions/memclaw "autoStartServices": true, "llmApiBaseUrl": "https://api.openai.com/v1", "llmApiKey": "your-llm-api-key", - "llmModel": "gpt-4o-mini", + "llmModel": "gpt-5-mini", "embeddingApiBaseUrl": "https://api.openai.com/v1", "embeddingApiKey": "your-embedding-api-key", "embeddingModel": "text-embedding-3-small" @@ -272,7 +272,9 @@ ln -sf "$(pwd)" ~/.openclaw/extensions/memclaw - `cortex://session` - 列出所有会话 - `cortex://session/{session_id}` - 浏览特定会话 - `cortex://session/{session_id}/timeline` - 查看时间线消息 -- `cortex://session/{session_id}/memories` - 查看提取的记忆 +- `cortex://user/{user_id}/preferences` - 查看用户偏好(提取的记忆) +- `cortex://user/{user_id}/entities` - 查看用户实体(人物、项目等) +- `cortex://agent/{agent_id}/cases` - 查看 Agent 问题解决案例 ### cortex_get_abstract diff --git a/examples/@memclaw/plugin/dist/plugin-impl.d.ts.map b/examples/@memclaw/plugin/dist/plugin-impl.d.ts.map index 227fdc6..b21d588 100644 --- a/examples/@memclaw/plugin/dist/plugin-impl.d.ts.map +++ b/examples/@memclaw/plugin/dist/plugin-impl.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"plugin-impl.d.ts","sourceRoot":"","sources":["../plugin-impl.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AA6CH,UAAU,YAAY;IACrB,KAAK,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IAClD,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IAChD,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IAChD,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;CACjD;AAED,UAAU,SAAS;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvC,YAAY,CAAC,IAAI,EAAE,cAAc,EAAE,IAAI,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC;IACxE,eAAe,CAAC,OAAO,EAAE;QACxB,EAAE,EAAE,MAAM,CAAC;QACX,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;QAC3B,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;KAC1B,GAAG,IAAI,CAAC;IACT,MAAM,EAAE,YAAY,CAAC;CACrB;AAED,UAAU,cAAc;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC5E,QAAQ,CAAC,EAAE,OAAO,CAAC;CACnB;AAoXD,wBAAgB,YAAY,CAAC,GAAG,EAAE,SAAS;;;;EAgqB1C"} \ No newline at end of file +{"version":3,"file":"plugin-impl.d.ts","sourceRoot":"","sources":["../plugin-impl.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AA6CH,UAAU,YAAY;IACrB,KAAK,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IAClD,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IAChD,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IAChD,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;CACjD;AAED,UAAU,SAAS;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvC,YAAY,CAAC,IAAI,EAAE,cAAc,EAAE,IAAI,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC;IACxE,eAAe,CAAC,OAAO,EAAE;QACxB,EAAE,EAAE,MAAM,CAAC;QACX,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;QAC3B,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;KAC1B,GAAG,IAAI,CAAC;IACT,MAAM,EAAE,YAAY,CAAC;CACrB;AAED,UAAU,cAAc;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC5E,QAAQ,CAAC,EAAE,OAAO,CAAC;CACnB;AAsXD,wBAAgB,YAAY,CAAC,GAAG,EAAE,SAAS;;;;EAgqB1C"} \ No newline at end of file diff --git a/examples/@memclaw/plugin/dist/plugin-impl.js b/examples/@memclaw/plugin/dist/plugin-impl.js index 33e9735..d511019 100644 --- a/examples/@memclaw/plugin/dist/plugin-impl.js +++ b/examples/@memclaw/plugin/dist/plugin-impl.js @@ -176,7 +176,9 @@ This allows you to explore the hierarchical structure of memories: - cortex://session - List all sessions - cortex://session/{session_id} - Browse a specific session's contents - cortex://session/{session_id}/timeline - View timeline messages -- cortex://session/{session_id}/memories - View extracted memories +- cortex://user/{user_id}/preferences - View user preferences (extracted memories) +- cortex://user/{user_id}/entities - View user entities (people, projects, etc.) +- cortex://agent/{agent_id}/cases - View agent problem-solution cases **Parameters:** - recursive: List all subdirectories recursively diff --git a/examples/@memclaw/plugin/dist/plugin-impl.js.map b/examples/@memclaw/plugin/dist/plugin-impl.js.map index 8c6d9a8..6a037d2 100644 --- a/examples/@memclaw/plugin/dist/plugin-impl.js.map +++ b/examples/@memclaw/plugin/dist/plugin-impl.js.map @@ -1 +1 @@ -{"version":3,"file":"plugin-impl.js","sourceRoot":"","sources":["../plugin-impl.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"plugin-impl.js","sourceRoot":"","sources":["../plugin-impl.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/examples/@memclaw/plugin/openclaw.plugin.json b/examples/@memclaw/plugin/openclaw.plugin.json index a1b6f06..edd25e4 100644 --- a/examples/@memclaw/plugin/openclaw.plugin.json +++ b/examples/@memclaw/plugin/openclaw.plugin.json @@ -86,7 +86,7 @@ }, "enhanceClawAgent": { "type": "boolean", - "description": "Automatically enhance AGENTS.md with MemClaw memory usage guide when legacy memory patterns are detected", + "description": "Automatically enhance MemClaw memory usage guide when legacy memory patterns are detected", "default": true } }, @@ -132,8 +132,8 @@ "description": "Model name for generating vector embeddings" }, "enhanceClawAgent": { - "label": "Enhance AGENTS.md", - "description": "Automatically inject MemClaw usage guide into AGENTS.md when legacy memory patterns are found" + "label": "Enhance AGENTS", + "description": "Automatically enhance MemClaw usage guide when legacy memory patterns are found" } } } diff --git a/examples/@memclaw/plugin/package.json b/examples/@memclaw/plugin/package.json index 8d37d08..cc35796 100644 --- a/examples/@memclaw/plugin/package.json +++ b/examples/@memclaw/plugin/package.json @@ -1,77 +1,75 @@ { - "name": "@memclaw/memclaw", - "version": "0.9.31", - "description": "MemClaw - The Cortex Memory plugin for OpenClaw. Layered semantic memory for OpenClaw with easy setup and migration", - "homepage": "https://github.com/sopaco/cortex-mem", - "repository": { - "type": "git", - "url": "git+https://github.com/sopaco/cortex-mem.git", - "directory": "examples/@memclaw/plugin" - }, - "bugs": { - "url": "https://github.com/sopaco/cortex-mem/issues" - }, - "publishConfig": { - "access": "public" - }, - "main": "dist/index.js", - "types": "dist/index.d.ts", - "scripts": { - "build": "tsc", - "dev": "tsc --watch" - }, - "keywords": [ - "openclaw", - "memory", - "semantic-search", - "vector-search", - "ai", - "agent", - "cortex-mem" - ], - "author": "Sopaco", - "license": "MIT", - "openclaw": { - "id": "memclaw", - "extensions": [ - "dist/index.js" - ], - "skills": [ - "skills/memclaw", - "skills/memclaw-maintance" - ], - "build": { - "openclawVersion": "2026.3.8", - "pluginSdkVersion": "2026.3.8" - }, - "compat": { - "pluginApi": ">=1.0.0", - "builtWithOpenClawVersion": "2026.3.8", - "pluginSdkVersion": "2026.3.8", - "minGatewayVersion": "2026.3.8" - } - }, - "devDependencies": { - "@types/node": "^22.0.0", - "typescript": "^5.7.0" - }, - "dependencies": { - "glob": "^11.0.0", - "smol-toml": "^1.6.1" - }, - "optionalDependencies": { - "@memclaw/bin-darwin-arm64": "0.1.7", - "@memclaw/bin-win-x64": "0.1.7", - "@memclaw/bin-linux-x64": "0.1.7" - }, - "engines": { - "node": ">=20.0.0" - }, - "files": [ - "dist/", - "skills/", - "openclaw.plugin.json", - "README.md", - "SECURITY.md" - ] + "name": "@memclaw/memclaw", + "version": "0.9.32", + "description": "MemClaw - The Cortex Memory plugin for OpenClaw. Layered semantic memory for OpenClaw with easy setup and migration", + "homepage": "https://github.com/sopaco/cortex-mem", + "repository": { + "type": "git", + "url": "git+https://github.com/sopaco/cortex-mem.git", + "directory": "examples/@memclaw/plugin" + }, + "bugs": { + "url": "https://github.com/sopaco/cortex-mem/issues" + }, + "publishConfig": { + "access": "public" + }, + "main": "dist/index.js", + "types": "dist/index.d.ts", + "scripts": { + "build": "tsc", + "dev": "tsc --watch" + }, + "keywords": [ + "openclaw", + "memory", + "semantic-search", + "vector-search", + "ai", + "agent", + "cortex-mem" + ], + "author": "Sopaco", + "license": "MIT", + "openclaw": { + "id": "memclaw", + "extensions": [ + "dist/index.js" + ], + "skills": [ + "skills/memclaw", + "skills/memclaw-maintance" + ], + "build": { + "openclawVersion": "2026.3.8", + "pluginSdkVersion": "2026.3.8" + }, + "compat": { + "pluginApi": ">=1.0.0", + "builtWithOpenClawVersion": "2026.3.8", + "pluginSdkVersion": "2026.3.8", + "minGatewayVersion": "2026.3.8" + } + }, + "devDependencies": { + "@types/node": "^22.0.0", + "typescript": "^5.7.0" + }, + "dependencies": { + "glob": "^11.0.0", + "smol-toml": "^1.6.1" + }, + "optionalDependencies": { + "@memclaw/bin-darwin-arm64": "0.1.8", + "@memclaw/bin-win-x64": "0.1.7", + "@memclaw/bin-linux-x64": "0.1.8" + }, + "engines": { + "node": ">=20.0.0" + }, + "files": [ + "dist/", + "skills/", + "openclaw.plugin.json" + ] } diff --git a/examples/@memclaw/plugin/plugin-impl.ts b/examples/@memclaw/plugin/plugin-impl.ts index 3b71ddc..158f90e 100644 --- a/examples/@memclaw/plugin/plugin-impl.ts +++ b/examples/@memclaw/plugin/plugin-impl.ts @@ -243,7 +243,9 @@ This allows you to explore the hierarchical structure of memories: - cortex://session - List all sessions - cortex://session/{session_id} - Browse a specific session's contents - cortex://session/{session_id}/timeline - View timeline messages -- cortex://session/{session_id}/memories - View extracted memories +- cortex://user/{user_id}/preferences - View user preferences (extracted memories) +- cortex://user/{user_id}/entities - View user entities (people, projects, etc.) +- cortex://agent/{agent_id}/cases - View agent problem-solution cases **Parameters:** - recursive: List all subdirectories recursively diff --git a/examples/@memclaw/plugin/skills/memclaw-maintance/SKILL.md b/examples/@memclaw/plugin/skills/memclaw-maintance/SKILL.md index d2009c2..ed25e70 100644 --- a/examples/@memclaw/plugin/skills/memclaw-maintance/SKILL.md +++ b/examples/@memclaw/plugin/skills/memclaw-maintance/SKILL.md @@ -40,6 +40,11 @@ description: MemClaw Maintenance Guide — Installation, configuration, and main ```bash openclaw plugins install @memclaw/memclaw ``` +or +```bash +openclaw plugins install clawhub:@memclaw/memclaw +``` + ### Step 2: Enable the Plugin diff --git a/examples/@memclaw/plugin/skills/memclaw/SKILL.md b/examples/@memclaw/plugin/skills/memclaw/SKILL.md index ee80f8a..51b2f1e 100644 --- a/examples/@memclaw/plugin/skills/memclaw/SKILL.md +++ b/examples/@memclaw/plugin/skills/memclaw/SKILL.md @@ -9,10 +9,8 @@ description: MemClaw — High-performance memory plugin for OpenClaw. Outperform > MemClaw is an open-source memory enhancement plugin based on Cortex Memory. Both MemClaw and this Skill are open-sourced on [GitHub](https://github.com/sopaco/cortex-mem). -Three-layer memory: L0 (abstract ~100t) → L1 (overview ~2000t) → L2 (full content). Supports semantic search + filesystem browsing. - ## Prerequisites -1. Install via `openclaw plugins install @memclaw/memclaw` if not present (tools unavailable or memclaw missing in `openclaw.json`) +1. Install via `openclaw plugins install clawhub:@memclaw/memclaw` if not present (memclaw missing in `openclaw.json`) 2. Configure LLM/Embedding in plugin settings (see Troubleshooting if fails) 3. Set `agents.defaults.memorySearch.enabled: false` in `openclaw.json` to avoid conflicts with built-in memory 4. All configuration is managed through OpenClaw plugin settings. However, when the plugin is first used, incomplete configuration items may cause it to fail. If the plugin or tools cannot be used, proactively inform the user and assist in completing the necessary configurations. For details, refer to the 'Troubleshooting' section below. @@ -41,7 +39,9 @@ cortex_commit_session(session_id="project-alpha") - `cortex://session/default` - Default session's root - `cortex://session/project-alpha` - Specific session's root - `cortex://session/{session_id}/timeline` - Session's message timeline -- `cortex://session/{session_id}/memories` - Session's extracted memories +- `cortex://user/{user_id}/preferences` - User preferences (extracted from sessions) +- `cortex://user/{user_id}/entities` - User entities (people, projects, concepts) +- `cortex://agent/{agent_id}/cases` - Agent problem-solution cases ## Tool Selection @@ -76,13 +76,13 @@ List directory. `uri`, `recursive`, `include_abstracts` cortex_ls(uri="cortex://session") cortex_ls(uri="cortex://session/default/timeline", include_abstracts=true) ``` -Common URIs: `cortex://session/{id}/timeline`, `cortex://session/{id}/memories` +Common URIs: `cortex://session/{id}/timeline`, `cortex://user/{user_id}/preferences`, `cortex://user/{user_id}/entities` #### cortex_get_abstract / cortex_get_overview / cortex_get_content ``` -cortex_get_abstract(uri="cortex://session/default/timeline/file.md") # L0 ~100t -cortex_get_overview(uri="cortex://session/default/timeline/file.md") # L1 ~2000t -cortex_get_content(uri="cortex://session/default/timeline/file.md") # L2 full +cortex_get_abstract(uri="cortex://session/default/timeline/...") # L0 ~100t +cortex_get_overview(uri="cortex://session/default/timeline/...") # L1 ~2000t +cortex_get_content(uri="cortex://session/default/timeline/...") # L2 full ``` ### Explore & Store diff --git a/examples/cortex-mem-tars/README.md b/examples/cortex-mem-tars/README.md index c582f25..e98b4fa 100644 --- a/examples/cortex-mem-tars/README.md +++ b/examples/cortex-mem-tars/README.md @@ -267,13 +267,18 @@ Cortex Memory 为 Agent 提供以下工具: ### 记忆 URI 格式 ``` -cortex://user/{user_id}/ - 用户记忆目录 -cortex://user/{user_id}/profile.json - 用户档案 -cortex://agent/{agent_id}/ - Agent 记忆目录 -cortex://session/{session_id}/ - 特定会话 -cortex://resources/ - 知识库 +cortex://user/{user_id}/preferences/ - 用户偏好 +cortex://user/{user_id}/entities/ - 用户实体(人物、项目等) +cortex://user/{user_id}/events/ - 用户事件(决策、里程碑) +cortex://agent/{agent_id}/cases/ - Agent 案例记忆 +cortex://session/{session_id}/timeline/ - 会话时间线 +cortex://resources/ - 知识库 ``` +**注意**:在 TARS 项目中,`user_id` 固定为 `tars_user`,例如: +- `cortex://user/tars_user/preferences/` +- `cortex://user/tars_user/entities/` + ### 分层访问示例 ```rust @@ -283,10 +288,10 @@ cortex://resources/ - 知识库 search("用户的编程语言偏好", scope="user/", layer="overview") // 2. 快速判断相关性(L0 层,最快) -abstract("cortex://user/alice/profile.json") +abstract("cortex://user/tars_user/preferences/typescript.md") // 3. 获取完整信息(L2 层,完整内容) -read("cortex://session/2024-02-20-conversation-01/") +read("cortex://session/2024-02-20-conversation-01/timeline/2024-02/20/10_30_00_abc.md") ``` ## 🔧 开发相关 diff --git a/examples/locomo-evaluation/README.md b/examples/locomo-evaluation/README.md index 206ea29..2314465 100644 --- a/examples/locomo-evaluation/README.md +++ b/examples/locomo-evaluation/README.md @@ -72,7 +72,7 @@ cargo run -p cortex-mem-service -- --port 8085 --data-dir ./cortex-data ```bash export OPENAI_BASE_URL="https://api.openai.com/v1" export OPENAI_API_KEY="your-key" -export EVAL_ANSWER_MODEL="gpt-4o-mini" +export EVAL_ANSWER_MODEL="gpt-5-mini" ``` `judge.py` 默认也会读取 `OPENAI_BASE_URL` / `OPENAI_API_KEY`。 @@ -117,7 +117,7 @@ python eval.py qa ./locomo10.json --sample 0 --output ./output/qa_results.txt -- ### 3. judge ```bash -python judge.py ./output/qa_results.txt.json --output ./output/grades.json --model gpt-4o-mini +python judge.py ./output/qa_results.txt.json --output ./output/grades.json --model gpt-5-mini ``` ### 4. 统计 diff --git a/examples/locomo-evaluation/cortex_mem_locomo_evaluation.egg-info/PKG-INFO b/examples/locomo-evaluation/cortex_mem_locomo_evaluation.egg-info/PKG-INFO index 7ef2850..961496b 100644 --- a/examples/locomo-evaluation/cortex_mem_locomo_evaluation.egg-info/PKG-INFO +++ b/examples/locomo-evaluation/cortex_mem_locomo_evaluation.egg-info/PKG-INFO @@ -82,7 +82,7 @@ cargo run -p cortex-mem-service -- --port 8085 --data-dir ./cortex-data ```bash export OPENAI_BASE_URL="https://api.openai.com/v1" export OPENAI_API_KEY="your-key" -export EVAL_ANSWER_MODEL="gpt-4o-mini" +export EVAL_ANSWER_MODEL="gpt-5-mini" ``` `judge.py` 默认也会读取 `OPENAI_BASE_URL` / `OPENAI_API_KEY`。 @@ -127,7 +127,7 @@ python eval.py qa ./locomo10.json --sample 0 --output ./output/qa_results.txt -- ### 3. judge ```bash -python judge.py ./output/qa_results.txt.json --output ./output/grades.json --model gpt-4o-mini +python judge.py ./output/qa_results.txt.json --output ./output/grades.json --model gpt-5-mini ``` ### 4. 统计 diff --git a/examples/locomo-evaluation/eval.py b/examples/locomo-evaluation/eval.py index e381720..b26c818 100644 --- a/examples/locomo-evaluation/eval.py +++ b/examples/locomo-evaluation/eval.py @@ -20,9 +20,8 @@ import requests from openai import OpenAI - DEFAULT_SERVICE_URL = "http://127.0.0.1:8085" -DEFAULT_SEARCH_MODEL = os.getenv("EVAL_ANSWER_MODEL", "gpt-4o-mini") +DEFAULT_SEARCH_MODEL = os.getenv("EVAL_ANSWER_MODEL", "gpt-5-mini") DEFAULT_JUDGE_MODEL = os.getenv("EVAL_JUDGE_MODEL", DEFAULT_SEARCH_MODEL) DEFAULT_TENANT_PREFIX = "locomo-eval" @@ -71,13 +70,18 @@ def format_locomo_message(msg: dict[str, Any]) -> str: return line -def load_locomo_data(path: str, sample_index: int | None = None) -> list[dict[str, Any]]: +def load_locomo_data( + path: str, sample_index: int | None = None +) -> list[dict[str, Any]]: with open(path, "r", encoding="utf-8") as f: data = json.load(f) if sample_index is not None: if sample_index < 0 or sample_index >= len(data): - print(f"Error: sample index {sample_index} out of range (0-{len(data)-1})", file=sys.stderr) + print( + f"Error: sample index {sample_index} out of range (0-{len(data) - 1})", + file=sys.stderr, + ) sys.exit(1) return [data[sample_index]] return data @@ -135,14 +139,22 @@ def build_session_messages( class CortexEvalClient: - def __init__(self, base_url: str, answer_model: str, llm_base_url: str | None, llm_api_key: str | None): + def __init__( + self, + base_url: str, + answer_model: str, + llm_base_url: str | None, + llm_api_key: str | None, + ): self.base_url = base_url.rstrip("/") self.answer_model = answer_model self.llm_client = None if llm_base_url and llm_api_key: self.llm_client = OpenAI(base_url=llm_base_url, api_key=llm_api_key) - def _post(self, path: str, payload: dict[str, Any], max_retries: int = 3) -> dict[str, Any]: + def _post( + self, path: str, payload: dict[str, Any], max_retries: int = 3 + ) -> dict[str, Any]: url = f"{self.base_url}{path}" last_error = None for attempt in range(max_retries): @@ -157,6 +169,7 @@ def _post(self, path: str, payload: dict[str, Any], max_retries: int = 3) -> dic last_error = e if attempt < max_retries - 1: import time + wait_time = (attempt + 1) * 5 # 5s, 10s, 15s backoff print(f" [retry] {path} failed ({e}), retrying in {wait_time}s...") time.sleep(wait_time) @@ -165,7 +178,9 @@ def _post(self, path: str, payload: dict[str, Any], max_retries: int = 3) -> dic def switch_tenant(self, tenant_id: str) -> None: self._post("/api/v2/tenants/switch", {"tenant_id": tenant_id}) - def create_session(self, thread_id: str, user_id: str | None = None, agent_id: str | None = None) -> None: + def create_session( + self, thread_id: str, user_id: str | None = None, agent_id: str | None = None + ) -> None: payload: dict[str, Any] = {"thread_id": thread_id} if user_id: payload["user_id"] = user_id @@ -196,7 +211,13 @@ def close_session_and_wait( }, ) - def search(self, query: str, thread_id: str | None = None, limit: int = 8, min_score: float = 0.4) -> list[dict[str, Any]]: + def search( + self, + query: str, + thread_id: str | None = None, + limit: int = 8, + min_score: float = 0.4, + ) -> list[dict[str, Any]]: payload: dict[str, Any] = { "query": query, "limit": limit, @@ -207,9 +228,15 @@ def search(self, query: str, thread_id: str | None = None, limit: int = 8, min_s payload["thread"] = thread_id return self._post("/api/v2/search", payload) - def answer_question(self, question: str, contexts: list[dict[str, Any]]) -> tuple[str, dict[str, int]]: + def answer_question( + self, question: str, contexts: list[dict[str, Any]] + ) -> tuple[str, dict[str, int]]: if self.llm_client is None: - return self.extract_answer_from_contexts(contexts), {"prompt_tokens": 0, "completion_tokens": 0, "total_tokens": 0} + return self.extract_answer_from_contexts(contexts), { + "prompt_tokens": 0, + "completion_tokens": 0, + "total_tokens": 0, + } context_texts = [] for idx, ctx in enumerate(contexts, start=1): @@ -243,7 +270,10 @@ def answer_question(self, question: str, contexts: list[dict[str, Any]]) -> tupl response = self.llm_client.chat.completions.create( model=self.answer_model, messages=[ - {"role": "system", "content": "You are a helpful assistant that answers questions from memory retrieval results. Be direct and give concise factual answers."}, + { + "role": "system", + "content": "You are a helpful assistant that answers questions from memory retrieval results. Be direct and give concise factual answers.", + }, {"role": "user", "content": prompt}, ], temperature=0, @@ -282,7 +312,10 @@ def judge_answer( completion = self.llm_client.chat.completions.create( model=judge_model, messages=[ - {"role": "system", "content": "You are a strict but fair QA judge. Output JSON only."}, + { + "role": "system", + "content": "You are a strict but fair QA judge. Output JSON only.", + }, {"role": "user", "content": prompt}, ], temperature=0, @@ -292,18 +325,34 @@ def judge_answer( verdict = str(parsed.get("is_correct", "WRONG")).strip().upper() == "CORRECT" reasoning = str(parsed.get("reasoning", "")).strip() usage = completion.usage - return verdict, reasoning, { - "prompt_tokens": getattr(usage, "prompt_tokens", 0) if usage else 0, - "completion_tokens": getattr(usage, "completion_tokens", 0) if usage else 0, - "total_tokens": getattr(usage, "total_tokens", 0) if usage else 0, - } + return ( + verdict, + reasoning, + { + "prompt_tokens": getattr(usage, "prompt_tokens", 0) if usage else 0, + "completion_tokens": getattr(usage, "completion_tokens", 0) + if usage + else 0, + "total_tokens": getattr(usage, "total_tokens", 0) if usage else 0, + }, + ) @staticmethod def extract_answer_from_contexts(contexts: list[dict[str, Any]]) -> str: if not contexts: - return "I cannot answer this question based on the provided memory contexts." - text = contexts[0].get("content") or contexts[0].get("overview") or contexts[0].get("snippet") or "" - return text.strip() or "I cannot answer this question based on the provided memory contexts." + return ( + "I cannot answer this question based on the provided memory contexts." + ) + text = ( + contexts[0].get("content") + or contexts[0].get("overview") + or contexts[0].get("snippet") + or "" + ) + return ( + text.strip() + or "I cannot answer this question based on the provided memory contexts." + ) async def wait_for_memory_ready( @@ -342,9 +391,15 @@ async def wait_for_sample_memory_ready( try: all_sessions_processed = True for thread_id in expected_threads: - session_meta_path = os.path.join(tenant_root, "session", thread_id, ".session.json") - timeline_abstract = os.path.join(tenant_root, "session", thread_id, "timeline", ".abstract.md") - timeline_overview = os.path.join(tenant_root, "session", thread_id, "timeline", ".overview.md") + session_meta_path = os.path.join( + tenant_root, "session", thread_id, ".session.json" + ) + timeline_abstract = os.path.join( + tenant_root, "session", thread_id, "timeline", ".abstract.md" + ) + timeline_overview = os.path.join( + tenant_root, "session", thread_id, "timeline", ".overview.md" + ) if not os.path.exists(session_meta_path): all_sessions_processed = False @@ -356,7 +411,10 @@ async def wait_for_sample_memory_ready( all_sessions_processed = False break - if not (os.path.exists(timeline_abstract) or os.path.exists(timeline_overview)): + if not ( + os.path.exists(timeline_abstract) + or os.path.exists(timeline_overview) + ): all_sessions_processed = False break @@ -369,7 +427,9 @@ async def wait_for_sample_memory_ready( with open(index_path, "r", encoding="utf-8") as f: index = json.load(f) summaries = index.get("session_summaries", {}) - summary_count = sum(1 for thread_id in expected_threads if thread_id in summaries) + summary_count = sum( + 1 for thread_id in expected_threads if thread_id in summaries + ) client.switch_tenant(tenant_id) results = client.search(probe_query, limit=5, min_score=0.1) @@ -403,7 +463,9 @@ async def run_ingest(args: argparse.Namespace) -> None: results = [] for sample_idx, item in enumerate(samples, start=1): sample_id = item["sample_id"] - tenant_id = args.tenant or tenant_for_sample(args.tenant_prefix, sample_id, sample_idx) + tenant_id = args.tenant or tenant_for_sample( + args.tenant_prefix, sample_id, sample_idx + ) user_id = args.user or f"{tenant_id}-user" sessions = build_session_messages(item, session_range, tail=args.tail) @@ -419,9 +481,14 @@ async def run_ingest(args: argparse.Namespace) -> None: thread_id = f"{sample_id}-{meta['session_key']}" msg = sess["message"] preview = msg.replace("\n", " | ")[:80] - print(f" [{meta['session_key']} ({meta['date_time']})] {preview}...", file=sys.stderr) + print( + f" [{meta['session_key']} ({meta['date_time']})] {preview}...", + file=sys.stderr, + ) - client.create_session(thread_id, user_id=user_id, agent_id=args.agent_id) + client.create_session( + thread_id, user_id=user_id, agent_id=args.agent_id + ) client.add_message(thread_id, "user", msg) client.close_session(thread_id) expected_threads.append(thread_id) @@ -451,10 +518,14 @@ async def run_ingest(args: argparse.Namespace) -> None: ) if args.output: - os.makedirs(os.path.dirname(args.output), exist_ok=True) if os.path.dirname(args.output) else None + os.makedirs(os.path.dirname(args.output), exist_ok=True) if os.path.dirname( + args.output + ) else None with open(args.output, "w", encoding="utf-8") as f: for record in results: - f.write(f"[{record['sample_id']}/{record['session']}] tenant={record['tenant_id']} user={record['user']}\n") + f.write( + f"[{record['sample_id']}/{record['session']}] tenant={record['tenant_id']} user={record['user']}\n" + ) f.write(f" {record['reply']}\n\n") json_path = f"{args.output}.json" with open(json_path, "w", encoding="utf-8") as f: @@ -465,7 +536,10 @@ async def run_ingest(args: argparse.Namespace) -> None: sessions = parse_test_file(args.input) tenant_id = args.tenant or f"{args.tenant_prefix}-txt" user_id = args.user or f"{tenant_id}-user" - print(f"Running {len(sessions)} session(s) into tenant={tenant_id}", file=sys.stderr) + print( + f"Running {len(sessions)} session(s) into tenant={tenant_id}", + file=sys.stderr, + ) client.switch_tenant(tenant_id) results = [] for idx, session in enumerate(sessions, start=1): @@ -478,7 +552,9 @@ async def run_ingest(args: argparse.Namespace) -> None: timeout_secs=args.wait_timeout, poll_interval=args.poll_interval, ) - results.append({"index": idx, "thread_id": thread_id, "evals": session["evals"]}) + results.append( + {"index": idx, "thread_id": thread_id, "evals": session["evals"]} + ) if args.output: with open(args.output, "w", encoding="utf-8") as f: @@ -499,7 +575,9 @@ async def run_sample_qa( semaphore: asyncio.Semaphore, ) -> tuple[list[dict[str, Any]], dict[str, int]]: sample_id = item["sample_id"] - tenant_id = args.tenant or tenant_for_sample(args.tenant_prefix, sample_id, sample_idx) + tenant_id = args.tenant or tenant_for_sample( + args.tenant_prefix, sample_id, sample_idx + ) qas = [qa for qa in item.get("qa", []) if str(qa.get("category", "")) != "5"] if args.count is not None: qas = qas[: args.count] @@ -509,7 +587,10 @@ async def run_sample_qa( jsonl_path = f"{args.output}.{sample_idx}.jsonl" if args.output else None async with semaphore: - print(f"\n=== Sample {sample_id} [{sample_idx}] tenant={tenant_id} ===", file=sys.stderr) + print( + f"\n=== Sample {sample_id} [{sample_idx}] tenant={tenant_id} ===", + file=sys.stderr, + ) print(f" Running {len(qas)} QA question(s)...", file=sys.stderr) client.switch_tenant(tenant_id) jsonl_file = open(jsonl_path, "w", encoding="utf-8") if jsonl_path else None @@ -519,17 +600,28 @@ async def run_sample_qa( expected = str(qa["answer"]) category = qa.get("category", "") evidence = qa.get("evidence", []) - print(f" [{sample_idx}] Q{qi}/{len(qas)}: {question[:60]}{'...' if len(question) > 60 else ''}", file=sys.stderr) + print( + f" [{sample_idx}] Q{qi}/{len(qas)}: {question[:60]}{'...' if len(question) > 60 else ''}", + file=sys.stderr, + ) started = time.time() try: - contexts = client.search(question, limit=args.top_k, min_score=args.min_score) - response_text, token_usage = client.answer_question(question, contexts) + contexts = client.search( + question, limit=args.top_k, min_score=args.min_score + ) + response_text, token_usage = client.answer_question( + question, contexts + ) elapsed = time.time() - started except Exception as exc: contexts = [] response_text = f"[ERROR] {exc}" - token_usage = {"prompt_tokens": 0, "completion_tokens": 0, "total_tokens": 0} + token_usage = { + "prompt_tokens": 0, + "completion_tokens": 0, + "total_tokens": 0, + } elapsed = time.time() - started for key in usage_sum: @@ -550,7 +642,10 @@ async def run_sample_qa( "token_usage": token_usage, } records.append(record) - print(f" [{sample_idx}] A: {response_text[:60]}{'...' if len(response_text) > 60 else ''}", file=sys.stderr) + print( + f" [{sample_idx}] A: {response_text[:60]}{'...' if len(response_text) > 60 else ''}", + file=sys.stderr, + ) if jsonl_file: jsonl_file.write(json.dumps(record, ensure_ascii=False) + "\n") @@ -578,7 +673,10 @@ async def run_qa(args: argparse.Namespace) -> None: ) semaphore = asyncio.Semaphore(parallel) - tasks = [run_sample_qa(item, idx + 1, args, client, semaphore) for idx, item in enumerate(samples)] + tasks = [ + run_sample_qa(item, idx + 1, args, client, semaphore) + for idx, item in enumerate(samples) + ] results_list = await asyncio.gather(*tasks) total_usage = {"prompt_tokens": 0, "completion_tokens": 0, "total_tokens": 0} @@ -620,7 +718,9 @@ def extract_json_object(text: str) -> dict[str, Any]: return json.loads(cleaned) -def summarize_judged_records(records: list[dict[str, Any]]) -> tuple[dict[str, Any], list[tuple[str, dict[str, Any]]]]: +def summarize_judged_records( + records: list[dict[str, Any]], +) -> tuple[dict[str, Any], list[tuple[str, dict[str, Any]]]]: total = len(records) correct = sum(1 for record in records if record.get("judge", {}).get("is_correct")) by_category: dict[str, dict[str, Any]] = {} @@ -630,7 +730,10 @@ def summarize_judged_records(records: list[dict[str, Any]]) -> tuple[dict[str, A bucket["total"] += 1 if record.get("judge", {}).get("is_correct"): bucket["correct"] += 1 - ordered_categories = sorted(by_category.items(), key=lambda item: int(item[0]) if str(item[0]).isdigit() else 999) + ordered_categories = sorted( + by_category.items(), + key=lambda item: int(item[0]) if str(item[0]).isdigit() else 999, + ) summary = { "total": total, "correct": correct, @@ -638,7 +741,9 @@ def summarize_judged_records(records: list[dict[str, Any]]) -> tuple[dict[str, A "by_category": { key: { **value, - "score": round((value["correct"] / value["total"]) * 100, 2) if value["total"] else 0.0, + "score": round((value["correct"] / value["total"]) * 100, 2) + if value["total"] + else 0.0, } for key, value in ordered_categories }, @@ -704,7 +809,9 @@ async def run_judge(args: argparse.Namespace) -> None: summary, ordered_categories = summarize_judged_records(judged_records) output_prefix = args.output or f"{args.input}.judge" - summary_path = output_prefix if output_prefix.endswith(".md") else f"{output_prefix}.md" + summary_path = ( + output_prefix if output_prefix.endswith(".md") else f"{output_prefix}.md" + ) judged_json_path = f"{output_prefix}.json" lines = [ @@ -723,10 +830,20 @@ async def run_judge(args: argparse.Namespace) -> None: "", ] for key, value in ordered_categories: - score = round((value['correct'] / value['total']) * 100, 2) if value['total'] else 0.0 - lines.append(f"- category {key}: `{value['correct']}/{value['total']}` => `{score}`") + score = ( + round((value["correct"] / value["total"]) * 100, 2) + if value["total"] + else 0.0 + ) + lines.append( + f"- category {key}: `{value['correct']}/{value['total']}` => `{score}`" + ) - wrong_examples = [record for record in judged_records if not record.get("judge", {}).get("is_correct")][:8] + wrong_examples = [ + record + for record in judged_records + if not record.get("judge", {}).get("is_correct") + ][:8] if wrong_examples: lines.extend(["", "## Wrong Examples", ""]) for record in wrong_examples: @@ -745,7 +862,12 @@ async def run_judge(args: argparse.Namespace) -> None: with open(summary_path, "w", encoding="utf-8") as f: f.write("\n".join(lines) + "\n") with open(judged_json_path, "w", encoding="utf-8") as f: - json.dump({"summary": summary, "records": judged_records}, f, indent=2, ensure_ascii=False) + json.dump( + {"summary": summary, "records": judged_records}, + f, + indent=2, + ensure_ascii=False, + ) print(f"Judge report written to {summary_path}", file=sys.stderr) print(f"Judged records written to {judged_json_path}", file=sys.stderr) @@ -753,29 +875,120 @@ async def run_judge(args: argparse.Namespace) -> None: def build_parser() -> argparse.ArgumentParser: - parser = argparse.ArgumentParser(description="Evaluate Cortex Memory using LoCoMo workflow") - parser.add_argument("mode", choices=["ingest", "qa", "judge"], help="Mode: ingest, qa, or judge") + parser = argparse.ArgumentParser( + description="Evaluate Cortex Memory using LoCoMo workflow" + ) + parser.add_argument( + "mode", choices=["ingest", "qa", "judge"], help="Mode: ingest, qa, or judge" + ) parser.add_argument("input", help="Path to test file (.txt or .json)") - parser.add_argument("--output", default=None, help="Path to output file (omit to skip writing)") - parser.add_argument("--base-url", default=DEFAULT_SERVICE_URL, help=f"Cortex service base URL (default: {DEFAULT_SERVICE_URL})") - parser.add_argument("--sample", type=int, default=None, help="LoCoMo sample index (0-based). Default: all samples.") - parser.add_argument("--sessions", default=None, help="LoCoMo session range, e.g. '1-4' or '3'. Default: all sessions.") - parser.add_argument("--tail", default="[]", help="Tail message appended after each bundled session message.") - parser.add_argument("--count", type=int, default=None, help="QA mode: number of QA questions to run. Default: all.") - parser.add_argument("--tenant", default=None, help="Override tenant id. Default: one tenant per sample.") - parser.add_argument("--tenant-prefix", default=DEFAULT_TENANT_PREFIX, help="Tenant prefix when auto-generating tenant ids.") + parser.add_argument( + "--output", default=None, help="Path to output file (omit to skip writing)" + ) + parser.add_argument( + "--base-url", + default=DEFAULT_SERVICE_URL, + help=f"Cortex service base URL (default: {DEFAULT_SERVICE_URL})", + ) + parser.add_argument( + "--sample", + type=int, + default=None, + help="LoCoMo sample index (0-based). Default: all samples.", + ) + parser.add_argument( + "--sessions", + default=None, + help="LoCoMo session range, e.g. '1-4' or '3'. Default: all sessions.", + ) + parser.add_argument( + "--tail", + default="[]", + help="Tail message appended after each bundled session message.", + ) + parser.add_argument( + "--count", + type=int, + default=None, + help="QA mode: number of QA questions to run. Default: all.", + ) + parser.add_argument( + "--tenant", + default=None, + help="Override tenant id. Default: one tenant per sample.", + ) + parser.add_argument( + "--tenant-prefix", + default=DEFAULT_TENANT_PREFIX, + help="Tenant prefix when auto-generating tenant ids.", + ) parser.add_argument("--user", default=None, help="Override user id for ingestion.") - parser.add_argument("--agent-id", default="cortex-eval-agent", help="Agent id used during ingestion.") - parser.add_argument("--parallel", type=int, default=1, metavar="N", help="QA mode: number of samples to process concurrently (max 10).") - parser.add_argument("--top-k", type=int, default=8, help="QA mode: number of search results to retrieve.") - parser.add_argument("--min-score", type=float, default=0.4, help="QA mode: minimum search score threshold.") - parser.add_argument("--wait-timeout", type=float, default=600.0, help="Ingest mode: max seconds to wait for memory readiness.") - parser.add_argument("--poll-interval", type=float, default=1.0, help="Ingest mode: memory readiness polling interval.") - parser.add_argument("--data-dir", default=os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))), "cortex-data"), help="Local cortex data dir used to inspect memory_index during ingest readiness checks.") - parser.add_argument("--answer-model", default=DEFAULT_SEARCH_MODEL, help="LLM model used to answer from retrieved contexts.") - parser.add_argument("--judge-model", default=DEFAULT_JUDGE_MODEL, help="LLM model used to judge QA answers.") - parser.add_argument("--llm-base-url", default=os.getenv("OPENAI_BASE_URL"), help="OpenAI-compatible base URL for answer generation.") - parser.add_argument("--llm-api-key", default=os.getenv("OPENAI_API_KEY"), help="OpenAI-compatible API key for answer generation.") + parser.add_argument( + "--agent-id", + default="cortex-eval-agent", + help="Agent id used during ingestion.", + ) + parser.add_argument( + "--parallel", + type=int, + default=1, + metavar="N", + help="QA mode: number of samples to process concurrently (max 10).", + ) + parser.add_argument( + "--top-k", + type=int, + default=8, + help="QA mode: number of search results to retrieve.", + ) + parser.add_argument( + "--min-score", + type=float, + default=0.4, + help="QA mode: minimum search score threshold.", + ) + parser.add_argument( + "--wait-timeout", + type=float, + default=600.0, + help="Ingest mode: max seconds to wait for memory readiness.", + ) + parser.add_argument( + "--poll-interval", + type=float, + default=1.0, + help="Ingest mode: memory readiness polling interval.", + ) + parser.add_argument( + "--data-dir", + default=os.path.join( + os.path.dirname( + os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + ), + "cortex-data", + ), + help="Local cortex data dir used to inspect memory_index during ingest readiness checks.", + ) + parser.add_argument( + "--answer-model", + default=DEFAULT_SEARCH_MODEL, + help="LLM model used to answer from retrieved contexts.", + ) + parser.add_argument( + "--judge-model", + default=DEFAULT_JUDGE_MODEL, + help="LLM model used to judge QA answers.", + ) + parser.add_argument( + "--llm-base-url", + default=os.getenv("OPENAI_BASE_URL"), + help="OpenAI-compatible base URL for answer generation.", + ) + parser.add_argument( + "--llm-api-key", + default=os.getenv("OPENAI_API_KEY"), + help="OpenAI-compatible API key for answer generation.", + ) return parser diff --git a/examples/locomo-evaluation/judge.py b/examples/locomo-evaluation/judge.py index 3e65f93..a2726dc 100644 --- a/examples/locomo-evaluation/judge.py +++ b/examples/locomo-evaluation/judge.py @@ -48,7 +48,9 @@ async def run( for category in sorted(categories): stats = categories[category] pct = stats["correct"] / stats["total"] if stats["total"] > 0 else 0.0 - print(f" Category {category}: {stats['correct']}/{stats['total']} ({pct:.2%})") + print( + f" Category {category}: {stats['correct']}/{stats['total']} ({pct:.2%})" + ) if output_path: with open(output_path, "w", encoding="utf-8") as f: @@ -67,16 +69,33 @@ async def run( def main() -> None: - parser = argparse.ArgumentParser(description="Grade Cortex Memory QA responses with LLM judge") + parser = argparse.ArgumentParser( + description="Grade Cortex Memory QA responses with LLM judge" + ) parser.add_argument("input", help="Path to answers JSON/JSONL file") parser.add_argument("--output", default=None, help="Path to write grades JSON") - parser.add_argument("--base-url", default=None, help="LLM API base URL (or set OPENAI_BASE_URL)") - parser.add_argument("--token", default=None, help="LLM API key (or set OPENAI_API_KEY)") - parser.add_argument("--model", default="gpt-4o-mini", help="Model name for grading") - parser.add_argument("--parallel", type=int, default=5, help="Parallel grading requests") + parser.add_argument( + "--base-url", default=None, help="LLM API base URL (or set OPENAI_BASE_URL)" + ) + parser.add_argument( + "--token", default=None, help="LLM API key (or set OPENAI_API_KEY)" + ) + parser.add_argument("--model", default="gpt-5-mini", help="Model name for grading") + parser.add_argument( + "--parallel", type=int, default=5, help="Parallel grading requests" + ) args = parser.parse_args() - asyncio.run(run(args.input, args.output, args.base_url, args.token, args.model, args.parallel)) + asyncio.run( + run( + args.input, + args.output, + args.base_url, + args.token, + args.model, + args.parallel, + ) + ) if __name__ == "__main__": diff --git a/examples/locomo-evaluation/judge_util.py b/examples/locomo-evaluation/judge_util.py index 7914376..dad552d 100644 --- a/examples/locomo-evaluation/judge_util.py +++ b/examples/locomo-evaluation/judge_util.py @@ -56,7 +56,11 @@ async def locomo_grader( content = response_obj.choices[0].message.content or "{}" start_idx = content.find("{") end_idx = content.rfind("}") - payload = content[start_idx : end_idx + 1] if start_idx != -1 and end_idx != -1 else content + payload = ( + content[start_idx : end_idx + 1] + if start_idx != -1 and end_idx != -1 + else content + ) result = json.loads(payload) label = str(result.get("is_correct", result.get("label", "WRONG"))).strip().lower() reasoning = str(result.get("reasoning", "")).strip() @@ -77,7 +81,7 @@ async def grade_answers( answers: list[dict[str, Any]], base_url: str | None = None, api_key: str | None = None, - model: str = "gpt-4o-mini", + model: str = "gpt-5-mini", parallel: int = 5, ) -> list[dict[str, Any]]: load_dotenv() diff --git a/litho.docs/en/1.Overview.md b/litho.docs/en/1.Overview.md index a06daa3..5a12ede 100644 --- a/litho.docs/en/1.Overview.md +++ b/litho.docs/en/1.Overview.md @@ -164,7 +164,7 @@ Cortex-Mem interacts with five key external systems, each defining a critical de - **Interaction Type**: AI/ML Service - **Protocol**: HTTP (OpenAI-compatible REST API) - **Purpose**: Generates embeddings for text and performs text completion for memory summarization (L0/L1) and structured extraction (facts, decisions, entities). -- **Examples**: OpenAI (`text-embedding-3-small`, `gpt-4o`), Azure OpenAI, local models via vLLM or Ollama (if OpenAI-compatible). +- **Examples**: OpenAI (`text-embedding-3-small`, `gpt-5-mini`), Azure OpenAI, local models via vLLM or Ollama (if OpenAI-compatible). - **Data Flow**: - Cortex-Mem sends prompts (structured JSON) to generate summaries or extract entities. - LLM returns structured JSON output (e.g., `ExtractedMemories`). diff --git a/litho.docs/en/3.Workflow.md b/litho.docs/en/3.Workflow.md index ea6491f..165069c 100644 --- a/litho.docs/en/3.Workflow.md +++ b/litho.docs/en/3.Workflow.md @@ -343,7 +343,7 @@ AutomationConfig { **Stage 1: Memory Extraction** - Session closed, triggering `AutoExtractor` - LLM extracts structured facts, entities, preferences -- Saves to `cortex://user/{user_id}/` categorized directories +- Saves to `cortex://user/{user_id}/` categorized directories (preferences/, entities/, events/) **Stage 2: Layer File Generation** - `LayerGenerator::ensure_timeline_layers()` for specific session, or diff --git a/litho.docs/en/4.Deep-Exploration/Application Interface Domain.md b/litho.docs/en/4.Deep-Exploration/Application Interface Domain.md index 714329a..9161d01 100644 --- a/litho.docs/en/4.Deep-Exploration/Application Interface Domain.md +++ b/litho.docs/en/4.Deep-Exploration/Application Interface Domain.md @@ -290,7 +290,7 @@ All interfaces load configuration via `cortex-mem-config` with the following pre **Required Configuration**: ```toml [llm] -model = "gpt-4" +model = "gpt-5-mini" api_key = "${OPENAI_API_KEY}" [qdrant] diff --git a/litho.docs/en/4.Deep-Exploration/Configuration Management Domain.md b/litho.docs/en/4.Deep-Exploration/Configuration Management Domain.md index e6a38fd..75678a3 100644 --- a/litho.docs/en/4.Deep-Exploration/Configuration Management Domain.md +++ b/litho.docs/en/4.Deep-Exploration/Configuration Management Domain.md @@ -323,7 +323,7 @@ collection_name = \"cortex-mem\" [llm] api_base = \"https://api.openai.com/v1\" -model = \"gpt-4\" +model = \"gpt-5-mini\" temperature = 0.7 ``` diff --git a/litho.docs/en/4.Deep-Exploration/Core Infrastructure Domain.md b/litho.docs/en/4.Deep-Exploration/Core Infrastructure Domain.md index efb90ba..903c829 100644 --- a/litho.docs/en/4.Deep-Exploration/Core Infrastructure Domain.md +++ b/litho.docs/en/4.Deep-Exploration/Core Infrastructure Domain.md @@ -241,7 +241,7 @@ SessionManager → SessionEvent::Closed → AutomationManager → AutoExtractor ### 6.2 Key Configuration Parameters ```toml [llm] -model = "gpt-4" +model = "gpt-5-mini" api_key = "${OPENAI_API_KEY}" base_url = "https://api.openai.com/v1" diff --git a/litho.docs/en/4.Deep-Exploration/Profile Management Domain.md b/litho.docs/en/4.Deep-Exploration/Profile Management Domain.md index 123346d..68a7b46 100644 --- a/litho.docs/en/4.Deep-Exploration/Profile Management Domain.md +++ b/litho.docs/en/4.Deep-Exploration/Profile Management Domain.md @@ -147,8 +147,8 @@ sequenceDiagram Profiles utilize the **Cortex Filesystem Abstraction** with tenant-aware scoping: ### 8.1 Storage URIs -- **User Profiles**: `cortex://user/{user_id}/profile.json` -- **Agent Profiles**: `cortex://agent/{agent_id}/profile.json` +- **User Memories**: `cortex://user/{user_id}/preferences/{name}.md`, `cortex://user/{user_id}/entities/{name}.md`, `cortex://user/{user_id}/events/{name}.md` +- **Agent Memories**: `cortex://agent/{agent_id}/cases/{name}.md`, `cortex://agent/{agent_id}/skills/{name}.md` - **Tenant Isolation**: Automatically scoped to `/data/tenants/{tenant_id}/user/` or `/data/tenants/{tenant_id}/agent/` ### 8.2 Serialization Format diff --git "a/litho.docs/zh/1\343\200\201\351\241\271\347\233\256\346\246\202\350\277\260.md" "b/litho.docs/zh/1\343\200\201\351\241\271\347\233\256\346\246\202\350\277\260.md" index fcecc1c..a0c6c8b 100644 --- "a/litho.docs/zh/1\343\200\201\351\241\271\347\233\256\346\246\202\350\277\260.md" +++ "b/litho.docs/zh/1\343\200\201\351\241\271\347\233\256\346\246\202\350\277\260.md" @@ -164,7 +164,7 @@ Cortex-Mem与五个关键的外部系统交互,每个都定义了关键的依 - **交互类型**: AI/ML服务 - **协议**: HTTP(OpenAI兼容REST API) - **目的**: 为文本生成嵌入,并为记忆摘要(L0/L1)和结构化提取(事实、决策、实体)执行文本补全。 -- **示例**: OpenAI(`text-embedding-3-small`、`gpt-4o`)、Azure OpenAI、通过vLLM或Ollama的本地模型(如果OpenAI兼容)。 +- **示例**: OpenAI(`text-embedding-3-small`、`gpt-5-mini`)、Azure OpenAI、通过vLLM或Ollama的本地模型(如果OpenAI兼容)。 - **数据流**: - Cortex-Mem发送提示(结构化JSON)生成摘要或提取结构化记忆(偏好、实体、事件等)。 - LLM返回结构化JSON输出(如`ExtractedMemories`)。 diff --git "a/litho.docs/zh/3\343\200\201\346\240\270\345\277\203\346\265\201\347\250\213.md" "b/litho.docs/zh/3\343\200\201\346\240\270\345\277\203\346\265\201\347\250\213.md" index badc5b6..76709a8 100644 --- "a/litho.docs/zh/3\343\200\201\346\240\270\345\277\203\346\265\201\347\250\213.md" +++ "b/litho.docs/zh/3\343\200\201\346\240\270\345\277\203\346\265\201\347\250\213.md" @@ -340,10 +340,13 @@ AutomationConfig { **多阶段处理**: -**阶段1:记忆提取** +**阶段 1:记忆提取** + - 会话关闭,触发 `AutoExtractor` + - LLM 提取结构化事实、实体、偏好 -- 保存到 `cortex://user/{user_id}/` 分类目录 + +- 保存到 `cortex://user/{user_id}/` 分类目录 (preferences/, entities/, events/) **阶段2:层级文件生成** - `LayerGenerator::ensure_timeline_layers()` 用于特定会话,或 diff --git "a/litho.docs/zh/4\343\200\201\346\267\261\345\205\245\346\216\242\347\264\242/\345\272\224\347\224\250\346\216\245\345\217\243\351\242\206\345\237\237.md" "b/litho.docs/zh/4\343\200\201\346\267\261\345\205\245\346\216\242\347\264\242/\345\272\224\347\224\250\346\216\245\345\217\243\351\242\206\345\237\237.md" index 188f6af..4e3be07 100644 --- "a/litho.docs/zh/4\343\200\201\346\267\261\345\205\245\346\216\242\347\264\242/\345\272\224\347\224\250\346\216\245\345\217\243\351\242\206\345\237\237.md" +++ "b/litho.docs/zh/4\343\200\201\346\267\261\345\205\245\346\216\242\347\264\242/\345\272\224\347\224\250\346\216\245\345\217\243\351\242\206\345\237\237.md" @@ -291,7 +291,7 @@ sequenceDiagram **必需配置**: ```toml [llm] -model = "gpt-4" +model = "gpt-5-mini" api_key = "${OPENAI_API_KEY}" [qdrant] diff --git "a/litho.docs/zh/4\343\200\201\346\267\261\345\205\245\346\216\242\347\264\242/\351\205\215\347\275\256\346\226\207\344\273\266\347\256\241\347\220\206\351\242\206\345\237\237.md" "b/litho.docs/zh/4\343\200\201\346\267\261\345\205\245\346\216\242\347\264\242/\351\205\215\347\275\256\346\226\207\344\273\266\347\256\241\347\220\206\351\242\206\345\237\237.md" index e49655d..9cff349 100644 --- "a/litho.docs/zh/4\343\200\201\346\267\261\345\205\245\346\216\242\347\264\242/\351\205\215\347\275\256\346\226\207\344\273\266\347\256\241\347\220\206\351\242\206\345\237\237.md" +++ "b/litho.docs/zh/4\343\200\201\346\267\261\345\205\245\346\216\242\347\264\242/\351\205\215\347\275\256\346\226\207\344\273\266\347\256\241\347\220\206\351\242\206\345\237\237.md" @@ -147,8 +147,8 @@ sequenceDiagram 配置文件使用**Cortex文件系统抽象**,带租户感知作用域: ### 8.1 存储URI -- **用户配置文件**: `cortex://user/{user_id}/profile.json` -- **智能体配置文件**: `cortex://agent/{agent_id}/profile.json` +- **用户记忆**: `cortex://user/{user_id}/preferences/{name}.md`, `cortex://user/{user_id}/entities/{name}.md`, `cortex://user/{user_id}/events/{name}.md` +- **Agent 记忆**: `cortex://agent/{agent_id}/cases/{name}.md`, `cortex://agent/{agent_id}/skills/{name}.md` - **租户隔离**: 自动限定到`/data/tenants/{tenant_id}/user/`或`/data/tenants/{tenant_id}/agent/` ### 8.2 序列化格式 diff --git "a/litho.docs/zh/4\343\200\201\346\267\261\345\205\245\346\216\242\347\264\242/\351\205\215\347\275\256\347\256\241\347\220\206\351\242\206\345\237\237.md" "b/litho.docs/zh/4\343\200\201\346\267\261\345\205\245\346\216\242\347\264\242/\351\205\215\347\275\256\347\256\241\347\220\206\351\242\206\345\237\237.md" index a0fb283..1c6664f 100644 --- "a/litho.docs/zh/4\343\200\201\346\267\261\345\205\245\346\216\242\347\264\242/\351\205\215\347\275\256\347\256\241\347\220\206\351\242\206\345\237\237.md" +++ "b/litho.docs/zh/4\343\200\201\346\267\261\345\205\245\346\216\242\347\264\242/\351\205\215\347\275\256\347\256\241\347\220\206\351\242\206\345\237\237.md" @@ -323,7 +323,7 @@ collection_name = "cortex-mem" [llm] api_base = "https://api.openai.com/v1" -model = "gpt-4" +model = "gpt-5-mini" temperature = 0.7 ```