Automated X-reference Intelligence & Open Medicine
AXIOM is a Local-First Scientific Evidence Engine for Women's Health. AXIOM ingests PubMed literature, builds a knowledge graph of biomedical entities and relationships, and exposes retrieval as both a FastAPI backend and an MCP server, allowing AI agents to query curated, phase-aware evidence with retraction checking and composite scoring.
┌──────────────────────────────────────────────────────────────┐
│ Ingest layer │
│ PubMed (Entrez) → chunk → ChromaDB (vector) + NetworkX │
│ (graph: entities + edges) │
├──────────────────────────────────────────────────────────────┤
│ Retrieval layer │
│ Hybrid: vector similarity + graph traversal (2-hop) │
│ Scoring: composite confidence + retraction status │
├──────────────────────────────────────────────────────────────┤
│ Serving layer │
│ FastAPI (REST) │ MCP server (7 tools) │ React UI │
└──────────────────────────────────────────────────────────────┘
Backend stack: Python 3.11, FastMCP, ChromaDB, NetworkX, Biopython/NCBI Entrez, Ollama (local LLM).
Frontend stack: React 19, TypeScript, Vite, Tailwind CSS, react-force-graph-2d (knowledge graph explorer), react-markdown.
The MCP server exposes seven tools for AI agent integration:
| Tool | Description |
|---|---|
search_pubmed |
Search PubMed and return structured results |
ingest_to_chroma |
Fetch PubMed results and ingest into the vector store |
query_evidence |
Hybrid graph+vector retrieval with composite scoring |
get_entity_context |
N-hop neighborhood traversal for a named entity |
list_papers |
List papers in the knowledge base by source |
get_new_research |
Poll for recent PubMed publications on given topics |
check_retractions |
Verify retraction status for a list of PMIDs |
- Docker and Docker Compose
- 16 GB RAM minimum (Ollama + embedding model)
- NCBI Entrez email (free registration at NCBI)
git clone https://github.com/harmonilab/axiom.git
cd axiom
cp .env.example .env
# Edit .env — at minimum set ENTREZ_EMAILmake up
# Pulls Ollama, builds AXIOM image, starts API + MCP server + React frontendmake model-pull
# Pulls gemma4:31B and nomic-embed-text into Ollama
React UI: http://localhost:3000 (Docker) · http://localhost:5173 (local dev)
API docs: http://localhost:8000/docs
MCP server: http://localhost:8001
---
## Local development (no Docker)
```bash
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
pip install -e ".[dev]"
cp .env.example .env # fill in values
# Start Ollama separately, then:
uvicorn app.api:app --host 127.0.0.1 --port 8000 --reload
python -m mcp_server.server
Frontend (separate terminal):
cd front-end
cp .env.example .env.local # set VITE_API_BASE=http://localhost:8000
npm install
npm run dev # http://localhost:5173Four standalone scripts for maintaining graph integrity. See scripts/README.md for the recommended workflow (audit → lexical merge → structural prune → semantic merge).
python scripts/audit_graph.py # read-only quality report
python scripts/merge_lexical.py # case/punctuation dedup, no Ollama needed
python scripts/prune_graph.py --dedup --min-conf 0.80 --prune-nodes
python scripts/merge_entities.py --find-only --threshold 0.94axiom/
├── app/ # FastAPI backend
├── front-end/ # React + TypeScript UI (Vite, Tailwind, force-graph)
├── mcp_server/ # MCP server (7 tools)
├── src/core/ # Retrieval, graph, embeddings, ingestion, privacy
│ └── providers/ # LLM provider abstraction (Ollama / Vertex AI)
├── agent/ # PubMed agent
├── scripts/ # Graph maintenance CLI tools
├── tests/ # pytest suite
└── data/ # Chroma DB + graph.pkl (travels with repo)
All configuration is via environment variables. Copy .env.example to .env and edit.
| Variable | Default | Description |
|---|---|---|
API_ENV |
development |
Set to production to enable API key auth, lock CORS, and disable /docs. |
PORT |
8000 |
FastAPI port. Has no effect when launched via docker-compose — compose overrides the command directly. |
AXIOM_API_KEY |
— | Required in production. Long random string sent as X-API-Key header. |
ALLOWED_ORIGINS |
http://localhost:5173,http://localhost:3000 |
Comma-separated allowed CORS origins. Never use * in production. |
RATE_LIMIT_PER_MINUTE |
20 |
Per-IP request refill rate. |
RATE_BURST |
5 |
Per-IP burst allowance. |
| Variable | Default | Description |
|---|---|---|
AXIOM_MODEL_NAME |
gemma4:31B |
Ollama model for inference. Must match the tag pulled by make model-pull. |
AXIOM_EVAL_MODEL |
(same as AXIOM_MODEL_NAME) |
Model used for answer evaluation. Set to a smaller model to speed up eval. |
LLM_PROVIDER |
ollama |
ollama or vertex. |
OLLAMA_BASE_URL |
http://localhost:11434 |
Ollama API base URL. |
AXIOM_DEVICE |
cuda |
Torch device: cuda, cpu, or mps. |
OLLAMA_NUM_PREDICT |
2000 |
Max tokens per Ollama generation. |
OLLAMA_NUM_CTX |
4096 |
Ollama context window size. |
| Variable | Default | Description |
|---|---|---|
EMBEDDING_MODEL |
nomic-embed-text |
Ollama embedding model. Pulled by make model-pull. |
| Variable | Default | Description |
|---|---|---|
ENTREZ_EMAIL |
— | Required by NCBI for rate-limit compliance. |
ENTREZ_API_KEY |
— | Optional. Raises rate limit from 3 to 10 req/s. |
| Variable | Default | Description |
|---|---|---|
CHROMA_PERSIST_DIR |
./data/chroma |
ChromaDB vector store path. |
GRAPH_PERSIST_PATH |
./data/graph.pkl |
NetworkX knowledge graph path. |
| Variable | Default | Description |
|---|---|---|
MCP_PORT |
8001 |
Port the MCP server listens on. |
| Variable | Default | Description |
|---|---|---|
FUZZY_MATCH_THRESHOLD |
0.6 |
Minimum cosine similarity to accept a graph entity match (0.0–1.0). Lower = more permissive. |
GRAPH_BOOST_WEIGHT |
0.3 |
Score boost applied to chunks that contain matched graph entities. |
FINAL_TOP_K |
5 |
Number of re-ranked chunks passed to the LLM. |
ROUTER_USE_LLM |
false |
If true, the query router makes a second LLM pass to refine mode selection. |
| Variable | Default | Description |
|---|---|---|
SESSION_TTL_SECONDS |
1800 |
Seconds of idle time before a session is evicted (30 min). |
SESSION_MAX |
100 |
Max concurrent in-memory sessions. |
SESSION_TURNS |
6 |
Conversation turns retained per session. |
make test # pytest
make lint # ruff + black check
make fmt # ruff fix + black formatPre-commit hooks run ruff and black on every commit:
pre-commit installAXIOM is build for the Gemma 4 Good Hackathon.
Ian Ballantyne, Glenn Cameron, María Cruz, Olivier Lacombe, Kristen Quan, and Omar Sanseviero. The Gemma 4 Good Hackathon. https://kaggle.com/competitions/gemma-4-good-hackathon, 2026. Kaggle.