dsh-plugin-kb4rag
August 30, 2026 · View on GitHub
English | 中文
A local paper knowledge base plugin for DeepSeek Harness (DSH): turns folders of PDF/DOCX papers into a semantically searchable knowledge base inside DSH sessions, giving long-form writing (theses, papers, books) cross-chapter consistency and literature recall.
Why
The three pains of long-form writing: writing chapter N and not remembering how chapter 1 defined the same concept, terminology drift, and digging through dozens of PDFs for one passage. This plugin makes "search the papers" a native one-step action for the DSH agent: recall passages (with source file and page) before/during writing, keeping terminology and arguments consistent across chapters. Embedding runs on a local Ollama (bge-m3 recommended); data stays local; no external APIs.
How it works
papers/ (PDF/DOCX/TXT, one or more directories)
│ scripts/paper_kb.py extract ← per-page text extraction with pymupdf
▼
papers_extract.jsonl ← one {relpath, page, text} per line
│ scripts/paper_kb.py build ← sentence-boundary chunking (600-900 chars, overlap)
▼ + Ollama embedding
kb-data/chunks.bin ← N×dim float32 vectors
kb-data/index.json ← chunk metadata + text + source/page
│
▼ DSH loads the plugin (index.js)
paperkb_search ← embed query → cosine Top-K → sourced snippets
paperkb_stats ← index statistics
- Zero runtime dependencies: search runs purely in Node (Float32Array dot products; ~9k×1024 ≈ tens of ms). No Python, no database, no MCP.
- Native DSH tools: registered via
ctx.tools.register(); schemas flow into system-prompt assembly automatically, and the permission system and Code Mode (tools.paperkb_search(...)) work out of the box. - Build-time only Python (stdlib only) plus a reachable Ollama.
Install
dsh plugin --profile web add dsh-plugin-kb4rag
Until published on npm, install from a local path:
dsh plugin --profile web add /path/to/dsh-plugin-kb4rag
Then restart dsh (or validate with dsh --profile web --dump-config).
Configuration
Plugin row id: kb4rag:
| Key | Default | Meaning |
|---|---|---|
ollama | http://127.0.0.1:11434 | Ollama HTTP endpoint (e.g. http://<ip>:11435 for a LAN instance) |
model | bge-m3 | Embedding model (bge-m3 recommended for Chinese/English papers) |
topK | 5 | Default result count |
minScore | 0 | Minimum cosine similarity |
home | ./data in the package | Knowledge base directory (chunks.bin + index.json) |
Override by row id in your profile's cordis.patch.yml (an id-targeted entry replaces the whole config; unset keys fall back to JS defaults):
- id: kb4rag
config:
ollama: http://192.168.3.22:11435
home: D:\kb\my-papers
You can also fall back to environment variables (lower precedence than a patch override, higher than built-in defaults): set KB4RAG_OLLAMA, KB4RAG_MODEL, KB4RAG_HOME in the shell that starts dsh, e.g. set KB4RAG_OLLAMA=http://192.168.3.22:11435. Precedence: patch override > environment > default http://127.0.0.1:11434.
Ollama integration
- Install Ollama and pull an embedding model:
ollama pull bge-m3 # 1024-dim, strong on mixed Chinese/English papers # nomic-embed-text is smaller (274MB) but clearly weaker on Chinese — not recommended - LAN access: Ollama binds 127.0.0.1 by default. To call it from another machine, serve with
OLLAMA_HOST=0.0.0.0:11435(in a systemd unit:Environment=OLLAMA_HOST=0.0.0.0:11435). Do not expose the port to the public internet. - GPU pinning: on multi-GPU machines use
CUDA_VISIBLE_DEVICES=<index>. ⚠️ Verified on ollama 0.5.x: its internal GPU ordering can be the reverse ofnvidia-smi(setting1selected the cardnvidia-smireports as0). After changing it, trigger one/api/embedand checknvidia-smi --query-compute-apps=pid,gpu_bus_id --format=csvto confirm where the runner landed. - Smoke test:
curl http://<host>:<port>/api/embed -d '{"model":"bge-m3","input":["hello"]}'.
Pointing at a different Ollama (host/port mismatch)
The endpoint is resolved in this order:
- an
ollamaoverride for thekb4ragrow in the profile'scordis.patch.yml(highest), - the
KB4RAG_OLLAMAenvironment variable (set wheredshruns), - the built-in default
http://127.0.0.1:11434.
For a LAN instance (e.g. 192.168.3.22:11435), either patch the config or run set KB4RAG_OLLAMA=http://192.168.3.22:11435 before starting dsh (Linux/macOS: export KB4RAG_OLLAMA=...).
Troubleshooting
paperkb_search error | Meaning | Fix |
|---|---|---|
cannot reach Ollama at <url> (ECONNREFUSED) | Service down or wrong port | Start ollama serve on that host; check the port (default 11434) |
cannot reach Ollama ... (ENOTFOUND) | Hostname does not resolve | Fix the URL or use an IP address |
cannot reach Ollama ... (ETIMEDOUT) | Firewall blocking | Allow the port; for cross-machine use serve with OLLAMA_HOST=0.0.0.0:PORT |
ollama /api/embed 404 | Embedding model not pulled | ollama pull bge-m3 on that host |
knowledge base not found at "<home>" | Index missing or wrong path | Run extract+build, or point home at an existing index |
Debug order:
curl http://<host>:<port>/api/tags— a JSON reply means service + port are fine;- call
paperkb_statsin a DSH session — it reports the configured endpoint, the index directory and a live reachability probe, telling you at a glance whether the index or the service is the problem; - fix per the table; config changes in the profile patch take effect after a dsh restart.
Building the knowledge base
python scripts/paper_kb.py extract /path/to/papers -o papers_extract.jsonl
# or several directories at once (the directory name is kept in each source path):
python scripts/paper_kb.py extract dir1 dir2 dir3 -o papers_extract.jsonl
python scripts/paper_kb.py build papers_extract.jsonl -o kb-data \
--ollama http://127.0.0.1:11434 --model bge-m3
python scripts/paper_kb.py stats kb-data
- Extraction needs
pip install pymupdf(PDF) and optionallypython-docx; scanned PDFs (no text layer) are listed as warnings — OCR them first. - Building uses only the Python standard library; ~8000 chunks embed at ~50 chunks/s on an RTX 3090 with bge-m3.
- Point
homeatkb-data(or copy it into the package'sdata/) and restart dsh.
Tools
paperkb_search(query, topK)— semantic search; full sentences or terms (Chinese or English); returns score, source file, page and snippet text.paperkb_stats()— chunk count, source documents, vector dimension, embedding model, plus the configured Ollama endpoint and a live reachability probe — call it first when search fails.
CLI equivalents without DSH:
python scripts/paper_kb.py search kb-data "morphology intelligence mechanisms" -k 4 --ollama http://192.168.3.22:11435
Limitations & roadmap
- Text only: formulas, figures and tables are not embedded (poor extraction quality).
- Chunks respect sentence boundaries within a page; no cross-page merging.
- Full rebuild: new papers require re-running extract+build (incremental indexing planned).
- Roadmap: incremental indexing & dedup, a settings-panel card (
settings.plugin.item), a search result card (presentResult), hybrid keyword+vector search, per-document filters.
License
MIT