Skip to content

Latest commit

 

History

30 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Smart Sources

A research editor: write and ask questions in a markdown document, pull supporting extracts from a ground-truth documents (Wikipedia, in this case), and edit the page with an LLM.

Stack

  • Embeddings: sentence-transformers (all-MiniLM-L6-v2 by default)
  • Vector store: ChromaDB (ephemeral, per browser session)
  • Generation: pydantic-ai
  • Wikipedia: Action API via wikipedia-api, with rate limiting and page cache
  • API: FastAPI + uvicorn
  • Frontend: Vite, React 19, TypeScript, TipTap (math via KaTeX)

Workspace packages (uv): backend, evals, experiments.

Setup

Requires Python 3.11+ and Node.js 18+.

uv sync
cd frontend && npm install

Environment

Variable Purpose
OPENAI_API_KEY Required for LLM calls
LLM_MODEL pydantic-ai model id (see .env.example)
EMBEDDING_MODEL sentence-transformers model
CORS_ORIGINS Comma-separated origins (default http://localhost:5173)
SESSION_TTL_SECONDS Cookie session lifetime (default 1800)
WIKI_USER_AGENT Identifying User-Agent with a real contact (Wikimedia policy)
WIKI_MAX_PAGES / WIKI_SEARCH_RESULTS / WIKI_CONCURRENCY / WIKI_MAX_REQUESTS_PER_MINUTE Wikipedia fetch limits
DEBUG Enable Logfire / pydantic-ai instrumentation when true

Development

From the project root, two terminals:

Terminal Command Port
Backend uv run backend/main.py 8000
Frontend cd frontend && npm run dev 5173

Open http://localhost:5173. Vite proxies /api/* and /health to the backend.

How it works

  1. Cookie session — Each browser gets a session that stores fetched Wikipedia page text and an in-memory Chroma index of those pages.
  2. Search mode (POST /api/ask, mode: "search") — Enrich the query → search/fetch Wikipedia → synthesize a markdown answer + extracts → place source blocks next to matching sentences. Empty pages use the “new page” prompts; non-empty pages use “add to page” prompts. Progress streams as NDJSON phase events (enrich, search, synthesize, insert).
  3. Edit mode (mode: "edit") — LLM returns a JSON Patch over the block list; protected text is diverted to suggestions instead of applied.
  4. Find in sources — Highlight text and retrieve matching passages from the session corpus (POST /api/find_in_sources).
  5. Source proxyGET /api/source?url=... serves Wikipedia HTML for in-editor iframes.

API

  • GET /health — liveness
  • POST /api/ask — NDJSON stream: {type:"phase", phase} then {type:"complete", result} or {type:"error", message}. Body: {"query", "editor_state", "mode": "search"|"edit"}
  • POST /api/find_in_sources{"query", "editor_state"}{blocks}
  • GET /api/source?url=... — proxied source HTML

Project structure

backend/backend/
  api/                 Routes + request schemas
  pipeline/            Search (enrich→search→synthesize→insert) and edit (JSON Patch)
  sessions.py          Cookie-backed session + per-session Chroma
  wikipedia_client.py  Rate-limited Wikipedia fetch + cache
  vector_store.py      Ephemeral Chroma + sentence matching for source placement
  source_proxy.py      In-app Wikipedia HTML proxy
  models.py            EditorState / PageBlock domain models
  main.py              FastAPI app
backend/main.py        Dev launcher (`uv run backend/main.py`)
frontend/              TipTap editor UI
evals/                 Pipeline evaluation scripts
experiments/           Ad-hoc retrieval / embedding experiments

See backend/README.md, frontend/README.md, and evals/README.md for package-specific notes.

About

Text editor with context-based knowledge retrieval from wikipedia.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages