baaai123/solo-memory

solo-memory

仓库尚未提供可用的公开描述。

Uncategorizedai-agentmcpmemory

Memory Skill

English | 中文

Long-term memory plugin for AI Agents — local-first, dual-signal retrieval, self-evolving. Bilingual (English & Chinese), with a first-class experience for Chinese conversations.

Gives AI Agents (Claude / OpenAI / your own LLM) persistent long-term memory: every conversation is stored automatically, relevant memories are injected into context on retrieval, and knowledge gaps trigger self-directed learning. Zero API retrieval — all search happens locally; the LLM is used only for enhancement (classification / synthesis).

Language support: Both English and Chinese can be stored and retrieved, with retrieval signals weighted differently per language — Chinese is dominated by BM25 (jieba tokenization), English by semantic vectors (bge-large-en-v1.5). The plugin itself is language-agnostic; conversations in either language are remembered automatically.


Features

FeatureDescription
Two-Half Memory ModelUnstructured dialogue + structured knowledge (pref/pers/skill/mission/conclusion)
Automatic Read/Writeweave injects context automatically; zero agent changes under the transparent proxy
Proactive RetrievalAgent references a memory title → auto-expands into full context
Fragment IsolationUnclassified fragments never pollute weave injection (tier2/nudge/[近期记忆] show structured memory only); fragments stay explicit-searchable
Candidate Distillationdistill compresses dialogue fragments into evidence-backed candidate cards → main agent reviews → auto-promotes to structured memory
Feedback-Driven EvolutionMemory weights evolve with usage (dedup +0.05 / reference +0.02 / feedback +0.05)
Three-Tier Injectiontier1 scenario awareness + tier2 structured memory + nudge high-priority memories
Transparent IntegrationMCP tools / OpenAI-compatible proxy / Python API — three channels

Architecture

┌────────────────────────────── Agent Layer ─────────────────────────────┐
│  MCP Tools (15)  Transparent Proxy (auto_context)   Python API          │
│  ALL decisions owned by main agent: classify/decompose/teach/review    │
└──────────────────────────────┬────────────────────────────────────────┘
                               │
┌─────────────────────────── MemorySystem ───────────────────────────────┐
│  Write (IngestPipeline)   Read (Weaver 10 blocks)    Retrieval (RRF)   │
│  │  ingest_dialogue       │  tier1/tier2            │  BM25 ×2.5       │
│  │  dedup (semantic)      │  nudge/[历史结论]       │  semantic ×0.5   │
│  │  fragments → default   │  skill/mission/pref/pers│  temporal ×0.5   │
│  └  teach_skill (structured) └  tree-nav/[待审核提炼]└                  │
├────────────────────────────────────────────────────────────────────────┤
│  Distill layer       Review layer (pending_store)   Storage            │
│  fragments→candidate  accepted→auto-promote         SQLite FTS5        │
│  offset window walk   rejected→discard              ChromaDB (1024-dim)│
│  compress-only        skill→manual teach            SawRingBuffer       │
│  evidence must exist  (source_urls gate)            TreeManager         │
└────────────────────────────────────────────────────────────────────────┘

Data Flow (closed loop)

conversation → Ingestor → [SQLite dialogue store] + [ChromaDB vector store] + [memory tree]
                      │
                      ├── fragments (default) ──→ distill ──→ pending candidates
                      │                              │            │
                      │                    [待审核提炼] reminder    ├─ accepted → auto-promote
                      │                              │            │              ↓
                      │                              │            └─ rejected → discard
                      │                              │                     structured memory
                      │                              │                    (skill/pref/pers/
                      │                              │                     mission/conclusion)
                      └── retrieval (RRF k=60) ←─────┘                     ↓
                                          ↓                        Weaver assembles 10 blocks
                                    Injected into agent prompt ←─────────────┘

Retrieval Signals (RRF Fusion)

SignalWeightSource
BM25 full-text2.5SQLite FTS5, jieba Chinese tokenization (dominates Chinese)
Semantic vector0.5ChromaDB, bge-large-en-v1.5 (1024-dim) (dominates English)
Temporal decay0.5weight × exp(-0.01 × hours)

A note on languages: Retrieval is RRF fusion — Chinese content is recalled primarily by BM25 (jieba tokenizes Chinese accurately), English content primarily by semantic vectors (bge-large-en-v1.5 is an English-specific model). The two paths are complementary: Chinese memories are recalled via BM25, English memories via semantic recall, both searchable in the same store. If you want a single model for unified bilingual semantic retrieval, swap in a multilingual embedding model (e.g. bge-m3) — this requires re-embedding existing memories.

The 15 MCP Tools

ToolPurpose
memory_weaveInject layered memory context (includes automatic read/write)
memory_searchSearch memories (RRF fusion; fragments also explicit-searchable)
memory_ingestStore a conversation
memory_statusHealth check
memory_feedbackFeedback-driven weight evolution
memory_classifyClassify a turn (chat/skill/mission/pref/pers) — protocol gate requires it
memory_check_skillCheck whether a skill is known (known/partial/unknown)
memory_teach_skillTeach a skill (source_urls required — anti-hallucination)
memory_update_skillUpdate a skill
memory_learning_queueView learning queue (to-learn/to-decompose)
memory_learning_markClose a learning-queue item
memory_distillDistill dialogue fragments into candidate cards (offset walks history)
memory_pendingView pending candidates awaiting review
memory_pending_markAccept/reject a candidate (accepted auto-promotes)
memory_conclusionsQuery conclusion entries

Installation

Dependencies

DependencyPurposeRequired
chromadbVector store✅
numpyVector math✅
jiebaChinese tokenization (BM25)✅
mcpMCP server✅ (tool mode)
clickCLI✅
pydantic / tenacity / openai / requestsLLM calls✅
python-dotenvEnvironment variables✅
onnxruntime + tokenizersONNX embeddings⚠️ optional (falls back to SHA-256 hashing — retrieval quality drops significantly)
llama-cpp-pythonLocal LLM (query rewriting / auto-feedback)⚠️ optional
# Basic install
pip install -e .                # core (incl. mcp/jieba)
pip install -e ".[onnx]"        # + ONNX embeddings (recommended — critical for retrieval quality)
pip install -e ".[full]"        # everything (ONNX + local LLM)
# or directly
pip install -r requirements.txt

Download the Embedding Model

./download_model.sh             # downloads bge-large-en-v1.5 → models/

Configure Environment Variables

Copy .env.example to .env and fill in:

IMPORTANCE_API_KEY=sk-xxx       # for LLM classification/synthesis
MEMORY_SKILL_DB_PATH=memory.db  # database path
MEMORY_MODEL_PATH=models/bge-large-en-v1.5

LLM Model Configuration (defaults to DeepSeek V4 Flash; any OpenAI-compatible model works)

The system calls an LLM through an OpenAI-compatible interface (for memory classification / synthesis / learning). It defaults to DeepSeek V4 Flash, but you can use any OpenAI-compatible model or service — just change 3 environment variables:

IMPORTANCE_API_BASE=https://api.deepseek.com/v1   # API base (OpenAI-compatible)
IMPORTANCE_API_KEY=sk-xxx                          # your key
IMPORTANCE_MODEL=deepseek-v4-flash                 # model name

# Example: switch to OpenAI
# IMPORTANCE_API_BASE=https://api.openai.com/v1
# IMPORTANCE_MODEL=gpt-4o-mini

# Example: switch to a local vLLM / Ollama
# IMPORTANCE_API_BASE=http://127.0.0.1:8000/v1
# IMPORTANCE_MODEL=qwen2.5-7b-instruct

Compatible with any service exposing /v1/chat/completions (OpenAI, Qwen, GLM, Moonshot, local vLLM, etc.). The defaults are tuned for DeepSeek V4 Flash (e.g. reserved max_tokens); if you switch models and classification/synthesis results look off, adjust the IMPORTANCE_* parameters.


Usage Guide (from zero to production)

Hand the repo URL to your AI Agent and tell it:

Install https://github.com/baaai123/solo-memory and connect it to my OpenCode.

Steps:
1. git clone https://github.com/baaai123/solo-memory
2. Run ./setup.sh (creates venv + installs dependencies + configures embedding model)
3. Register the opencode-auto-memory plugin in opencode.json
4. Fill in my own IMPORTANCE_API_KEY in .env (use my own LLM API key)

Note: ./setup.sh does the whole environment setup in one shot; the opencode-auto-memory
plugin auto-injects memory context and auto-stores conversations — the Agent never has
to call memory tools manually.

The AI will autonomously complete clone → environment setup → plugin registration. The only thing you do is put your own LLM API key in .env (used for memory classification/synthesis/learning, billed to your own API account).

Why this works: setup.sh encapsulates environment setup; the opencode-auto-memory plugin includes first-run bootstrapping (auto-creates venv if missing). The only manual step is providing an API key — no memory system can hold your private key for you.

Option B: Manual Installation (step by step)

The walkthrough below uses OpenCode + the auto-memory plugin as an example. Other Agents (Claude Code / Cursor) follow the same flow, just with a different config filename.

Step 1: Download and install

git clone https://github.com/baaai123/solo-memory
cd solo-memory

# One-shot environment setup (venv + dependencies + embedding model)
./setup.sh

# or manually:
# python3 -m venv venv && source venv/bin/activate && pip install -e ".[onnx]"
# ./download_model.sh   # bge-large-en-v1.5 → models/

Step 2: Configure your key

cp .env.example .env
# edit .env, fill in the LLM API Key (used for memory classification/synthesis/learning)
# IMPORTANCE_API_KEY=sk-xxx

Step 3: Hand SKILL.md to the Agent

SKILL.md is the Agent's memory protocol — put it in your Agent's knowledge base, or reference it in your configuration:

  • OpenCode: place it at the project root (the Agent reads AGENTS.md/skills automatically), or inject the protocol via prompt_append
  • Claude Code: reference it from CLAUDE.md, or use it as a skill file
  • Cursor: put it in .cursor/rules/ or the project rules

The core protocol (full SKILL.md lives in the repo):

BEFORE responding:   memory_weave(user_message)   → inject memory context
AFTER  key exchange: memory_ingest(role, content) → store to memory
Need more:           memory_search(query)         → deep retrieval
Session start:       memory_status                 → health check

Step 4: Register the auto-memory plugin

Add the plugin path to the plugin array in ~/.config/opencode/opencode.json:

{
  "plugin": [
    "/abs/path/to/solo-memory/opencode-auto-memory"
  ]
}

The plugin auto-injects memory context (via the chat.message hook) and auto-stores conversations (via the event hook) — the Agent never has to call tools manually.

For the MCP tool mode (manually calling memory_search etc.), see Quick Start → Option 2 below.

Step 5: Restart the Agent and verify

Restart the Agent session so it picks up the memory tools:

# The Agent should now see and be able to call these tools:
memory_search / memory_weave / memory_ingest / memory_status
memory_feedback / memory_classify / memory_teach_skill / memory_distill

Quick check: tell the Agent something important (e.g. "I prefer Python for backend work"), restart the session, then ask it again — if it remembers, the memory is working.


Quick Start

Option 1: Transparent proxy (zero agent changes)

DEEPSEEK_API_KEY=sk-xxx ./start.sh --port 8888

# Agent settings
export OPENAI_API_BASE=http://127.0.0.1:8888/v1

Memory is injected into every chat request and responses are stored back automatically — the Agent is completely unaware of the memory system.

Option 2: MCP tools (OpenCode / Claude Code, etc.)

{
  "mcp": {
    "opencode-memory": {
      "type": "local",
      "command": ["/abs/path/venv/bin/python", "-m", "memory_skill.mcp_server"],
      "environment": {
        "MEMORY_SKILL_DB_PATH": "/abs/path/opencode_memory.db",
        "IMPORTANCE_API_KEY": "sk-xxx"
      }
    }
  }
}

Hermes Agent: also supports MCP — connect this server under mcp_servers as augmented memory (RRF dual-signal retrieval + learning loop). See docs/INTEGRATION.md.

{
  "plugin": ["/abs/path/to/solo-memory/opencode-auto-memory"]
}

chat.message auto-injects memory, event auto-stores — the agent doesn't need to remember to call any tools. See opencode-auto-memory/README.md for details.

See docs/INTEGRATION.md.

Option 3: Python API

from memory_skill import MemorySkill, MemorySkillConfig, DialogueTurn

skill = MemorySkill(MemorySkillConfig(db_path="memory.db"))

# Store a conversation
skill.ingest(DialogueTurn(role="user", content="I recommend FastAPI", ...))

# Inject memory context
ctx = skill.weave("What is FastAPI?")
print(ctx.to_prompt_block())

# Proactive retrieval
skill.expand("FastAPI")

# Distill fragments → pending candidates
skill.distill()   # or MCP: memory_distill

# View / review candidates
skill.pending()   # or MCP: memory_pending / memory_pending_mark

Distillation & Review (Active Learning v2)

Since the 08-11 rewrite the module is pure storage + retrieval — all learning decisions are owned by the main agent (ADR-0002). The active-learning loop:

fragments ── memory_distill ──→ candidate cards (topic/summary/evidence/suggested)
                                   │  evidence must reference real dialogue ids (anti-hallucination)
                                   │  compress-only, never asserts; suggested is advisory
                                   ↓
                              pending_store (SQLite, outside retrieval pool)
                                   │
                    weave injects [待审核提炼] reminder (visible every turn)
                                   ↓
                          main agent reviews (memory_pending)
                                   │
              ┌────────────────────┼────────────────────┐
              ↓                    ↓                    ↓
        accepted              rejected            skill candidates
        (conclusion/pref/pers)   → discard           → manual teach
        auto-promotes                                (source_urls gate)

Anti-hallucination design:

  • distill only summarizes existing dialogue, never adds facts; every evidence id must resolve to a real dialogue turn or the candidate is rejected at write time
  • candidates live in the isolated pending_store — they never enter retrieval, so they cannot pollute weave before review
  • skill candidates are NOT auto-promoted: teach_skill requires non-empty source_urls (ADR-0002, prevents fabricating from training data)
  • memory_distill supports offset/limit window walking — old memories get distilled too, not just the newest turns

Documentation

DocContents
SKILL.mdAgent usage protocol (layered weave injection + distillation loop)
COMPREHENSIVE.mdFull architecture design
docs/INTEGRATION.mdOpenCode / Cursor / proxy integration guide
docs/PROTOCOL.mdMemory protocol & tool specs
CHANGELOG.mdVersion history

Note: linked docs are currently Chinese-only. English versions coming soon.


Performance

MetricValue
Chinese retrieval accuracy93% (300 memories)
Retrieval latency35-100ms
Tests115 fast/integration (25 network/slow run when real API keys present)

License

Apache License 2.0