dsh-web
zhu1090093659/dsh-webDeepSeek Harness(DSH)Web 插件聚合生态包 · 一切皆插件,创意工坊分发(dsh-market.com)
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.
| Feature | Description |
|---|---|
| Two-Half Memory Model | Unstructured dialogue + structured knowledge (pref/pers/skill/mission/conclusion) |
| Automatic Read/Write | weave injects context automatically; zero agent changes under the transparent proxy |
| Proactive Retrieval | Agent references a memory title → auto-expands into full context |
| Fragment Isolation | Unclassified fragments never pollute weave injection (tier2/nudge/[近期记忆] show structured memory only); fragments stay explicit-searchable |
| Candidate Distillation | distill compresses dialogue fragments into evidence-backed candidate cards → main agent reviews → auto-promotes to structured memory |
| Feedback-Driven Evolution | Memory weights evolve with usage (dedup +0.05 / reference +0.02 / feedback +0.05) |
| Three-Tier Injection | tier1 scenario awareness + tier2 structured memory + nudge high-priority memories |
| Transparent Integration | MCP tools / OpenAI-compatible proxy / Python API — three channels |
┌────────────────────────────── 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 │
└────────────────────────────────────────────────────────────────────────┘
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 ←─────────────┘
| Signal | Weight | Source |
|---|---|---|
| BM25 full-text | 2.5 | SQLite FTS5, jieba Chinese tokenization (dominates Chinese) |
| Semantic vector | 0.5 | ChromaDB, bge-large-en-v1.5 (1024-dim) (dominates English) |
| Temporal decay | 0.5 | weight × 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.
| Tool | Purpose |
|---|---|
memory_weave | Inject layered memory context (includes automatic read/write) |
memory_search | Search memories (RRF fusion; fragments also explicit-searchable) |
memory_ingest | Store a conversation |
memory_status | Health check |
memory_feedback | Feedback-driven weight evolution |
memory_classify | Classify a turn (chat/skill/mission/pref/pers) — protocol gate requires it |
memory_check_skill | Check whether a skill is known (known/partial/unknown) |
memory_teach_skill | Teach a skill (source_urls required — anti-hallucination) |
memory_update_skill | Update a skill |
memory_learning_queue | View learning queue (to-learn/to-decompose) |
memory_learning_mark | Close a learning-queue item |
memory_distill | Distill dialogue fragments into candidate cards (offset walks history) |
memory_pending | View pending candidates awaiting review |
memory_pending_mark | Accept/reject a candidate (accepted auto-promotes) |
memory_conclusions | Query conclusion entries |
| Dependency | Purpose | Required |
|---|---|---|
chromadb | Vector store | ✅ |
numpy | Vector math | ✅ |
jieba | Chinese tokenization (BM25) | ✅ |
mcp | MCP server | ✅ (tool mode) |
click | CLI | ✅ |
pydantic / tenacity / openai / requests | LLM calls | ✅ |
python-dotenv | Environment variables | ✅ |
onnxruntime + tokenizers | ONNX embeddings | ⚠️ optional (falls back to SHA-256 hashing — retrieval quality drops significantly) |
llama-cpp-python | Local 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_model.sh # downloads bge-large-en-v1.5 → models/
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
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. reservedmax_tokens); if you switch models and classification/synthesis results look off, adjust theIMPORTANCE_*parameters.
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.shencapsulates environment setup; theopencode-auto-memoryplugin 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.
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.
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/
cp .env.example .env
# edit .env, fill in the LLM API Key (used for memory classification/synthesis/learning)
# IMPORTANCE_API_KEY=sk-xxx
SKILL.md is the Agent's memory protocol — put it in your Agent's knowledge base, or reference it in your configuration:
AGENTS.md/skills automatically), or inject the protocol via prompt_appendCLAUDE.md, or use it as a skill file.cursor/rules/ or the project rulesThe 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
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_searchetc.), see Quick Start → Option 2 below.
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.
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.
{
"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_serversas 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.
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
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 timepending_store — they never enter
retrieval, so they cannot pollute weave before reviewteach_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| Doc | Contents |
|---|---|
| SKILL.md | Agent usage protocol (layered weave injection + distillation loop) |
| COMPREHENSIVE.md | Full architecture design |
| docs/INTEGRATION.md | OpenCode / Cursor / proxy integration guide |
| docs/PROTOCOL.md | Memory protocol & tool specs |
| CHANGELOG.md | Version history |
Note: linked docs are currently Chinese-only. English versions coming soon.
| Metric | Value |
|---|---|
| Chinese retrieval accuracy | 93% (300 memories) |
| Retrieval latency | 35-100ms |
| Tests | 115 fast/integration (25 network/slow run when real API keys present) |