Agent Knowledge Base — answering questions about this app
README.md, trust this document (and the docs it references) — the root README is the non-technical user guide; these docs are the source-verified technical reference.Q&A
What is this app?
A local-first legal research desktop application ("Lawyer Assistant") for legal documents. The UI, prompts and OCR are English, and retrieval is language-agnostic (the BGE-M3 embedding model handles many languages, so non-English source text can still be searched). It searches a legal corpus with BGE-M3 embeddings + ChromaDB + BM25 + a cross-encoder reranker, answers questions with a local Ollama LLM (RAG with citations), and runs a compliance playbook scan that flags risky clauses in documents. It is an Electron app with a React frontend and a Python FastAPI backend. → ARCHITECTURE.md.
What are the three "modes" of chat?
rag (default; retrieve + answer), retrieval_only (search only, no LLM), direct (LLM only, no retrieval). → BACKEND.md §2.
What AI "agents" does the app have?
- Intent router (
router_intent.py) — the default RAG orchestrator: classifies intent, writes a plan, picks tools from the plan, executes them, writes the answer. - Legacy agentic router (
router.py) — a LangGraph ReAct agent (agent → approval → tools → loop) with human-in-the-loop approval. - Tools (the agent's "hands"):
search_documents,verify_relevance,scan_document,ingest_file. - Playbook scanner — a clause classifier + rule engine (not an LLM agent, but an AI component using embeddings). →
BACKEND.md§4, §6.
What does the agent do with my query?
Rules enforced by prompts: the exact user query is passed to search_documents without rephrasing, results are verified with verify_relevance, and the final answer is written from retrieved chunks with file/page citations — or it says honestly that documents don't contain the answer. → BACKEND.md §4b.
What is human-in-the-loop approval?
Before the agent executes a tool, the LangGraph graph pauses with interrupt(). The UI shows an ApprovalBar; the user approves or rejects; /api/chat/resume resumes the thread with Command(resume=response). Reject makes the agent answer without tools. Thread state persists in data/conversations.db (AsyncSqliteSaver). → BACKEND.md §4b, §3.
How does retrieval work?
Query → BGE-M3 embedding → dense search (ChromaDB, top 50) + sparse (BM25, top 50) → hybrid merge → BGE-Reranker-v2-M3 cross-encoder re-scores → top 5 results with scores, file/page/section metadata. → BACKEND.md §5.
How does document ingestion work?
Files are saved into the active project folder (a workspace must be selected first — uploads land directly in that folder), parsed with Docling (OCR for scanned PDFs), chunked by the structure-aware chunker (480-token chunks, sections never split), embedded with BGE-M3, stored in ChromaDB, and indexed for BM25. → DATA_FLOW.md, BACKEND.md §5.
How does the compliance scan work?
Document chunks → classify clause type (embedding classifier) → check each playbook rule → emit flags (severity high/medium/low, rule id, page, reason, clause text) → persist to SQLite → UI lets you resolve / dismiss / escalate. Playbooks are JSON files in backend/legal_retrieval/playbook/playbooks/. → BACKEND.md §6.
How do attachments work?
Attach up to 5 files (or a folder of up to 50 docs) → each is uploaded to /api/upload (saved into the active project folder — a workspace must be selected first) → the paths ride along on the chat request → the router ingests (ingest_file) and/or scans (scan_document) them; if you attach files without typing, it runs a default batch-scan prompt. → BACKEND.md §2, FRONTEND.md §2.
What does "select a folder" do? (Workspace)
The "Work in a folder" button opens a native Electron directory dialog and the picked folder becomes the active workspace — and a workspace is now required: chat, upload and scan all refuse to run without one (there is no default data/ folder anymore). Raw uploads land directly in that folder, and the ChromaDB/BM25 indexes, processed temp files and per-project history all live under <folder>/workspace/ (workspace/chroma_db, workspace/bm25_index, workspace/processed, workspace/history.json), replacing the static project data/ paths. POST /api/workspace sets it, GET reads it, DELETE resets it, and POST /api/workspace/ingest (or its SSE variant /api/workspace/ingest/stream) indexes every supported document in the folder. A background folder-watcher auto-ingests new files dropped into the project. The override is runtime-only (resets on restart). The frontend passes workspace file absolute paths on send (no re-upload). → BACKEND.md §2 (Workspace), config.py workspace section.
What ports does the app use?
8765 backend (FastAPI), 5173 Vite dev server, 11434 Ollama. Electron kills stale 8765/5173 processes at startup. → ARCHITECTURE.md §2.
Where is data stored?
- Browser: conversations and working set in per-project scoped localStorage keys (
freebuff-chat-storage:<project-hash>,freebuff-working-set:<project-hash>), pipeline layout (pipeline-layout-v1). - Disk, project folder:
<project>/workspace/—chroma_db/(vectors),bm25_index/(sparse index),processed/(temp artifacts) andhistory.json(per-project chat history + working set + GPU profile). Raw uploads live directly in the project folder itself. - Disk, project-independent:
data/conversations.db(LangGraph agent threads),data/flags.db(scan flags). - Models:
models/bge-m3,models/bge-reranker-v2-m3. →ARCHITECTURE.md§5.
How does streaming work?
The backend streams Server-Sent Events (event: <type>\ndata: <json>): tokens, thinking (chain-of-thought), statuses, the plan, tool calls/results, node_start/node_complete, sources, interrupted/resumed, done, error. The frontend parses SSE lines and appends to Zustand streaming state. Workspace ingest streams its own event set (ingest_start, ingest_progress, ingest_done, ingest_cancelled, ingest_error). → BACKEND.md §3, FRONTEND.md §2, §6.
What is the Pipeline Editor?
A ReactFlow canvas visualizing the pipeline as nodes (intent, planner, dense, sparse, rerank, ingest, scan, answer). Nodes can be removed (auto-bypass rewires the flow), re-enabled via palette toggles, and the whole layout is auto-saved, resettable, and exportable/importable as JSON. Since the /api/pipeline/config endpoint, the layout also reconfigures the Python backend at runtime (rerank on/off from the rerank node, search mode + fusion weights from the dense/sparse nodes, top_k overrides). The config is runtime-only and resets on restart. → PIPELINE_EDITOR.md, PIPELINE_JSON.md §10.
Why is the UI light by default? / How does theming work?
The app defaults to a light "parchment" theme; html.light + CSS variables drive all colors, and a bridge remaps Tailwind utility classes so text never matches the background in either theme. → FRONTEND.md §7.
How do I run the app?
npm run dev at the root (runs Electron, which boots the FastAPI backend and Vite itself). Non-technical users: double-click launch.bat / launch.sh to open the launcher, which installs everything and starts the app. For production, npm run build then npm run package:win|mac|linux (electron-builder). Electron auto-creates/uses .venv for the backend. → ARCHITECTURE.md §3.
Why is the first query slow?
Models are preloaded at backend startup (warmup thread), so after startup the first query is fast; without warmup the first call pays model-loading cost. CLI (backend/scripts/query.py) also loads models on first use.
What are the tests/benchmarks?backend/tests/ has phase-based suites (boot, types, chunking, embeddings, vector
store, retrieval, integration e2e); backend/benchmark/ has component tests and golden eval harnesses; CLI law.py benchmark runs them. → backend/tests/, backend/benchmark/ source.
How to answer accurately (for agents)
- Scope check: is the question about the desktop app (Electron/React/ FastAPI) or the legacy CLI (
law.py)? Point todocs/for the former; the CLI is not user-facing anymore. - Prefer code over memory: verify specifics against
backend/main.py,backend/legal_retrieval/*.py,frontend/src/**when the question is technical. - Pipeline Editor = runtime config: since
POST /api/pipeline/config, the editor's layout does reconfigure retrieval at runtime (rerank on/off, search mode + fusion weights, top_k) — it is not visual-only. Say so accurately (seePIPELINE_JSON.md§10). - Cite the doc: end answers with the relevant doc filename so the questioner can go deeper.