Local-first LLM instance framework: deploy, specialize, and chat with grounded, cited model instances.
Project description
Lore
Local-first LLM instance framework — deploy, manage, and specialize LLM instances without sending private data to commercial AI providers or paying per token.
Working name; see CLAUDE.md for the full design document that governs this project, and docs/ROADMAP.md for current sequencing.
What it does
- One-command local setup:
lore setupinstalls Ollama (with your confirmation), starts it, and pulls models sized to your hardware.lore doctordiagnoses anything broken with the exact command to fix it. - A vetted, free model catalog: every supported model is open-weight and
free to run.
lore models catalogshows what fits your hardware;lore models guidemaps use cases to the best model for this machine. A weekly CI job re-verifies the catalog against the Ollama registry. - Named, specialized instances: each instance = model + private knowledge base(s) + persistent memory + behavior config, all defined in YAML.
- Grounded, cited answers: responses are grounded in the instance's knowledge bases (PDFs, markdown, text, and source code chunked per function/class) with page/section/line citations.
- A configurable grounding gate: weak retrieval refuses before generation; after generation, a judge model verifies each claim against the retrieved sources and refuses, hedges, or warns below your threshold — always saying why and showing the nearest chunks. Optional self-consistency sampling flags unstable answers.
- Per-instance memory across sessions — pinned facts and rolling summaries, fully inspectable, deletable with a wipe that VACUUMs the database so the data is actually gone.
- A generic analysis task engine: define batch workflows in YAML (enumerate items → grounded verdict per item → cited report). AOU gap analysis, requirements coverage, and test-gap templates ship built in; your own workflows are a YAML file away.
- CLI-first with web parity by construction: the CLI is a thin client of a local FastAPI server; the future web UI consumes the same API.
Deployment model: set Lore up independently on each of your machines —
natively (lore setup) or via Docker (deploy/). Each machine hosts its own
instances, CLI, and (coming next) its own web GUI served by lore-server.
Machines are independent by design; cloud provisioning is tabled (see
roadmap).
An honest note on "accuracy"
No system can guarantee a numeric accuracy percentage, and Lore does not claim to. What it implements is a grounding gate (see CLAUDE.md §4.3): claims in a draft answer are verified against retrieved chunks, and answers below the configured grounding score are refused, hedged, or flagged — structurally preventing confident assertion of unsupported claims. Accuracy stays measured (via the grounding eval harness), never asserted.
Status
| Phase | Scope | Status |
|---|---|---|
| 0 | Scaffold, config schemas, SQLite store, server + CLI lifecycle | ✅ done |
| 1 | Provider adapters (Ollama, OpenAI-compat), instances, streaming chat | ✅ done |
| 2 | RAG & knowledge bases (ingest, embed, retrieve, cite; PDF/markdown/code) | ✅ done |
| 3 | Grounding gate, memory, analysis task engine, self-consistency | ✅ done |
| 4 | Docker packaging + token auth (cloud provisioning tabled) | ✅ done |
| 5 | Per-machine web dashboard served by lore-server at / |
✅ done |
Docker (one command per machine)
cd deploy
export LORE_API_TOKEN=$(openssl rand -hex 24)
docker compose up -d --build # lore-server + Ollama + persistent volumes
docker compose exec lore lore models pull qwen2.5:7b
See deploy/README.md for KB bind-mounts, GPU passthrough, upgrades, and talking to a Lore machine over the network (the API requires the bearer token whenever it's reachable beyond loopback).
Installing
Lore is on PyPI as lore-llm — the
command is lore. It requires Python 3.11+, but you don't need one on
your system: the recommended installer fetches a compatible interpreter by
itself, in an isolated location, without touching your system Python.
Recommended — uv (a single static binary; downloads a managed Python 3.12 automatically if your system's is older):
curl -LsSf https://astral.sh/uv/install.sh | sh # install uv (one-time)
uv tool install lore-llm
lore setup # install + start Ollama, pull models
lore up # start the server (and the dashboard)
Alternative — pipx (needs a Python ≥ 3.11 for the tool's venv; your system default keeps working as-is):
pipx install lore-llm --python 3.12 --fetch-missing-python # pipx ≥ 1.5
# or, with a 3.11+ interpreter already installed (e.g. deadsnakes on Ubuntu):
pipx install lore-llm --python python3.12
A plain venv works too, as long as it's created from a 3.11+ interpreter
(python3.12 -m venv …) — a venv made from an older Python stays that
version inside. No 3.11 anywhere and can't add one? The
Docker path sidesteps Python entirely.
Working from a checkout instead? uv runs the CLI inside the project venv
with pinned dependencies: uv run lore … (the Quickstart below uses this
form; installed users just type lore …).
Upgrading
uv tool upgrade lore-llm # or: pipx upgrade lore-llm
lore down && lore up # restart — a running server is still the old code
The dashboard updates with the package (it ships inside the wheel). Your
data — config, instances, knowledge bases, memory — lives in ~/.lore/
and is never touched by an upgrade; pulled models live with Ollama.
Web dashboard
lore up also serves a full web dashboard at the server root
(default http://127.0.0.1:5673) — the same API the
CLI uses, so the two stay in feature parity by construction:
- Chat with streaming answers, inline citation chips, an evidence drawer showing every claim and retrieved chunk, and refusal cards that explain why the gate held an answer back.
- Instances: create and edit instance config with a form ↔ YAML toggle (everything is YAML underneath), including the grounding gate.
- Knowledge bases: create, ingest with live progress, browse snapshots.
- Memory: inspect pinned facts and summaries, pin, forget, or wipe (type-the-name confirmation; rows deleted and the database vacuumed).
- Models: installed models, the hardware-fit catalog, and pull-from-GUI with live download progress.
- Settings: global config with the same YAML toggle, plus
lore doctorin the browser.
Two themes, four accent colors, self-hosted fonts — no external requests, consistent with local-first. When the server binds beyond loopback (e.g. Docker), set the bearer token under Settings → API token.
Sharing knowledge bases with your team
A mapped-out KB is expensive to build (parsing + embedding); teammates shouldn't pay that twice. Export it — chunks and vectors travel together, so the importer needs no source files and does zero re-embedding:
# you
lore kb export sa8775-docs # -> sa8775-docs.lorekb
# teammate (after their own lore setup)
lore kb import sa8775-docs.lorekb # instant — no re-embedding
lore kb update sa8775-docs --source ~/my-notes/ # extend it with their own material
Both are also in the dashboard: Knowledge Bases → Export / Import .lorekb, and imported KBs accept new sources like any other — imported material is carried forward into every new snapshot.
Two things to know: the importer's embeddings.model must match the model
the KB was embedded with (import refuses otherwise — mixed vectors would
silently break retrieval), and instance configs are just YAML files
(~/.lore/instances/<name>/instance.yaml) you can share alongside the
archive. Models need no sharing: everyone pulls the same open weights by
name. Chats and memory stay local to each machine by design.
Quickstart
Requires Python 3.11+ and uv.
uv sync # create venv, install lore + dev deps
uv run lore setup # install + start Ollama, pull hardware-sized models
uv run lore doctor # diagnose: provider, models, GPU, disk, server
uv run lore models guide # which model for which job, sized to THIS machine
uv run lore models catalog # all supported models: memory needs, fit, installed
# chat with a general instance
uv run lore instance create helper --model qwen2.5:7b \
--system-prompt "You are a concise engineering assistant."
uv run lore chat helper # interactive, streaming
uv run lore ask helper "what can you do?" # one-shot; --json for scripts
lore setup detects your GPU/RAM and recommends models accordingly (e.g.
24 GB VRAM → qwen2.5:32b-instruct, 8 GB → qwen2.5:7b, CPU-only laptop →
qwen2.5:1.5b) — recommendations, not requirements. All catalog models are
open-weight and free to run (no per-token costs — that's the point); licenses
vary per family, so check the notes for commercial use. Already have Ollama?
Setup detects it and fills in only what's missing. No Ollama at all? Point
providers.openai_compat.base_url at any OpenAI-compatible endpoint
(llama.cpp server, vLLM, LM Studio) and use --provider openai_compat.
Ground an instance in your own material
Knowledge bases need an embedding model in addition to your chat model (default:
nomic-embed-text).lore setuppulls it; if you pick models manually, runlore models pull nomic-embed-textfirst —lore doctorchecks for it.
Retrieval adapts to your hardware (retrieval_profile: auto in
~/.lore/config.yaml): GPU machines embed chunks with contextual headers
and search wider candidate pools; CPU-only machines keep embeddings cheap
and lean on parent-context expansion — retrieved chunks are handed to the
model together with their surrounding section, so answers stop reading
like disconnected fragments. lore doctor shows which profile is active.
# ingest documents (pdf, md, txt, rst) and/or code (py, c, h, cpp — per-function chunks)
uv run lore kb create sa8775-docs --source ~/datasheets/sa8775/
cat > expert.yaml <<'EOF'
name: sa8775-expert
model: qwen2.5:7b
system_prompt: Answer strictly from the mounted knowledge base.
knowledge_bases:
- name: sa8775-docs # pin a snapshot hash instead of latest for reproducibility
accuracy:
min_grounding_score: 0.85
on_below_threshold: refuse
EOF
uv run lore instance create sa8775-expert --from expert.yaml
uv run lore ask sa8775-expert "what is the max junction temperature?"
# → cited answer: ... 105 C [1]
# [1] trm.pdf p.87 · Thermal > Limits (score 0.83) ● grounded 0.94
# → or an explicit refusal with the nearest chunks when the KB doesn't cover it
KBs are versioned: every ingest is an immutable snapshot (lore kb update,
lore kb snapshots <name>); instances mount latest or a pinned hash.
Memory
uv run lore memory pin sa8775-expert "our target is SA8797 rev B"
uv run lore memory show sa8775-expert # pinned facts, session summaries
uv run lore memory wipe sa8775-expert --all # deleted AND vacuumed — unrecoverable
Batch analysis (generic task engine)
uv run lore analyze list # built-ins + your ~/.lore/tasks/*.yaml
uv run lore analyze run aou-gap --instance code-auditor \
--items aou.md --md gap-report.md
# per item: retrieval → gate → grounded verdict with citations;
# items the KB can't support are marked insufficient-evidence, never guessed
Any workflow of the shape enumerate → grounded verdict → report is a YAML template — labels, prompt, and item splitting are all yours to define.
Everything is configured via ~/.lore/config.yaml (override the home dir
with LORE_HOME). Every YAML file validates against a Pydantic schema with
precise, user-facing errors.
Repository layout
src/lore/
├── cli/ # Typer app; thin HTTP client of the server
├── server/
│ ├── api/ # FastAPI routers: health, models, instances, kb, chat,
│ │ # memory, analyze, system (doctor/config)
│ ├── core/ # instance manager, chat orchestration, KB mounting,
│ │ # analysis engine, task templates
│ ├── rag/ # parsing (PDF/markdown/code), chunking, ingestion,
│ │ # hybrid retrieval (dense + BM25)
│ ├── verify/ # grounding judge, self-consistency
│ ├── memory/ # budgeted injection, rolling summaries, wipe
│ └── providers/# Ollama + OpenAI-compat adapters behind the Provider ABC
├── config/ # Pydantic schemas for all YAML files + Lore home paths
├── setup/ # hardware detection, Ollama install/start, doctor checks
├── store/ # SQLite (WAL, migrations) + ChromaDB vector store
└── tasks/ # built-in analysis templates (aou-gap, …)
Development
See CONTRIBUTING.md for setup, checks, and project conventions.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file lore_llm-0.10.0.tar.gz.
File metadata
- Download URL: lore_llm-0.10.0.tar.gz
- Upload date:
- Size: 1.5 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e39902290ea1faadfdfe28a7ded6424ee09ebb6eb9c5feb723d7ccb9c778bad3
|
|
| MD5 |
27a0eaf09b7c49bade2c5618cba46475
|
|
| BLAKE2b-256 |
b9cb4c1e26e5fc86216e3c932971fb4698073d23b035d40175572615b877a0f3
|
Provenance
The following attestation bundles were made for lore_llm-0.10.0.tar.gz:
Publisher:
release.yml on dhavalhparikh/lore
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
lore_llm-0.10.0.tar.gz -
Subject digest:
e39902290ea1faadfdfe28a7ded6424ee09ebb6eb9c5feb723d7ccb9c778bad3 - Sigstore transparency entry: 2097579811
- Sigstore integration time:
-
Permalink:
dhavalhparikh/lore@15ca4487c96d75d6b926bd91f2965508132ad663 -
Branch / Tag:
refs/tags/v0.10.0 - Owner: https://github.com/dhavalhparikh
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@15ca4487c96d75d6b926bd91f2965508132ad663 -
Trigger Event:
push
-
Statement type:
File details
Details for the file lore_llm-0.10.0-py3-none-any.whl.
File metadata
- Download URL: lore_llm-0.10.0-py3-none-any.whl
- Upload date:
- Size: 1.2 MB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
df33be91f8e8b65e3f2204db73a5d775bfbc64ca3d3ac7e5b22e5fb27200f82b
|
|
| MD5 |
917f83c65fe686601c33e80169f8976c
|
|
| BLAKE2b-256 |
c5a893836520ef44b6e3cf85a342f04f02b5e2e94c935e42fdf368dafb2ab312
|
Provenance
The following attestation bundles were made for lore_llm-0.10.0-py3-none-any.whl:
Publisher:
release.yml on dhavalhparikh/lore
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
lore_llm-0.10.0-py3-none-any.whl -
Subject digest:
df33be91f8e8b65e3f2204db73a5d775bfbc64ca3d3ac7e5b22e5fb27200f82b - Sigstore transparency entry: 2097580207
- Sigstore integration time:
-
Permalink:
dhavalhparikh/lore@15ca4487c96d75d6b926bd91f2965508132ad663 -
Branch / Tag:
refs/tags/v0.10.0 - Owner: https://github.com/dhavalhparikh
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@15ca4487c96d75d6b926bd91f2965508132ad663 -
Trigger Event:
push
-
Statement type: