Metadata-Version: 2.4
Name: evigraph-r
Version: 0.1.4
Summary: Evidence-graph reasoning over 2.8M arXiv papers
Author: EviGraph Team
License: MIT
Project-URL: Homepage, https://github.com/your-org/EviGraph-R
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Requires-Python: >=3.11
Description-Content-Type: text/markdown
Requires-Dist: beir>=2.2.0
Requires-Dist: boto3>=1.34.0
Requires-Dist: datasets>=4.6.1
Requires-Dist: dspy>=3.1.3
Requires-Dist: einops>=0.8.2
Requires-Dist: flagembedding==1.2.5
Requires-Dist: huggingface-hub>=1.5.0
Requires-Dist: langchain>=1.2.12
Requires-Dist: langgraph>=1.1.1
Requires-Dist: msgpack>=1.1.2
Requires-Dist: mypy>=1.19.1
Requires-Dist: networkx>=3.6.1
Requires-Dist: numpy>=2.4.2
Requires-Dist: openai>=2.26.0
Requires-Dist: pytest>=9.0.2
Requires-Dist: python-dotenv>=1.2.2
Requires-Dist: pytrec-eval-terrier>=0.5.10
Requires-Dist: aiohttp>=3.9.0
Requires-Dist: qdrant-client>=1.17.0
Requires-Dist: rank-bm25>=0.2.2
Requires-Dist: rocksdict>=0.3.29
Requires-Dist: sentence-transformers>=5.2.3
Requires-Dist: tokenizers>=0.22.2
Requires-Dist: torch>=2.10.0
Requires-Dist: tqdm>=4.67.3
Requires-Dist: transformers>=5.3.0
Requires-Dist: nltk>=3.9.4
Requires-Dist: fastapi>=0.136.1
Requires-Dist: uvicorn>=0.46.0
Requires-Dist: sse-starlette>=3.3.4
Requires-Dist: faiss-cpu>=1.13.2
Requires-Dist: deepeval>=4.0.2
Requires-Dist: matplotlib>=3.10.9

# EviGraph-R

EviGraph-R answers scientific questions by building an **evidence graph** over 2.8 million arXiv papers. It retrieves relevant chunks, constructs a graph of claims and citations, verifies each claim with an NLI judge, and synthesises a grounded answer with per-sentence citations.

---

## Getting started

There are two ways to use EviGraph-R:

| | **pip install** | **Clone & run** |
|---|---|---|
| **Use case** | Use the Python API or CLI in your own project | Self-host the full stack with your own data |
| **Qdrant** | Connects to the hosted VM (no download needed) | Runs locally via Docker |
| **Setup** | `pip install evigraph-r` | `git clone` + `docker compose up` |

---

## Quick start (pip)

```bash
pip install evigraph-r
```

```python
import asyncio
import evigraph

runner = evigraph.WorkflowRunner()
request = evigraph.QueryRequest(query="What is the effect of BERT pre-training on downstream NLP tasks?")
result = asyncio.run(runner.run_query(request))

print(result.answer)
# → "BERT pre-training improves GLUE score by 7.7% [arxiv:1810.04805] ..."
```

Or from the terminal:

```bash
evigraph query "What causes Alzheimer's disease?"
evigraph query "What causes Alzheimer's disease?" --json   # full JSON response
evigraph serve                                             # start FastAPI on :8000
```

### Requirements

- Python ≥ 3.11
- An OpenAI-compatible LLM endpoint

### Configuration

The pip package connects to the **hosted Qdrant instance** on the EviGraph VM by default — no local database or 700 GB data download needed.

You must supply your own LLM credentials via environment variables:

```bash
export LLM_API_KEY=your-api-key
export LLM_API_BASE=https://your-llm-endpoint/v1
export LLM_MODEL=openai/your-model-name      # must include provider prefix, e.g. openai/gpt-4o
```

> **Provider prefix:** DSPy (the LLM orchestration layer) requires the model name to start with a provider prefix like `openai/`, `anthropic/`, `ollama/`, etc. A bare model name like `gpt-4o` only works when `LLM_API_BASE` points directly at `/v1`.

Optional — override the Qdrant endpoint (e.g. your own instance):

```bash
export QDRANT_URL=http://your-host:6333
# or per-query:
evigraph query "..." --qdrant-url http://your-host:6333
```

---

## Self-hosted (Docker)

To run everything locally with your own data:

```bash
git clone <repo-url>
cd EviGraph-R
cp .env.example .env   # fill in LLM_BASE_URL, LLM_API_KEY, etc.
docker compose up -d
```

| Service | URL |
|---|---|
| API | http://localhost:8000 |
| Qdrant dashboard | http://localhost:6334/dashboard |

---

## Python API

```python
import asyncio
import evigraph

# Basic query
runner = evigraph.WorkflowRunner()
request = evigraph.QueryRequest(
    query="Does dropout improve generalisation in transformers?",
    config=evigraph.PipelineConfig(
        top_k=20,
        enable_hop=True,
        target_sections=["Results", "Discussion"],
    ),
)
result = asyncio.run(runner.run_query(request))

# Answer with citations
print(result.answer)

# Per-sentence breakdown
for sentence in result.sentences:
    print(sentence.text, "→", sentence.citations)

# Claim verdict scorecard
print(result.scorecard)
# → {"Supported": 12, "Contradicted": 2, "Inconclusive": 3}

# Evidence graph (nodes + edges)
graph: evigraph.EvidenceGraph = result.graph
```

### `PipelineConfig` options

| Parameter | Type | Default | Description |
|---|---|---|---|
| `top_k` | int | `15` | Chunks retrieved per sub-query |
| `score_threshold` | float | `0.0` | Minimum retrieval score |
| `enable_hop` | bool | `true` | Multi-hop sub-question retrieval |
| `embedding_model` | str | `"bge-m3"` | `bge-m3`, `e5`, `qwen3`, `jina` |
| `target_sections` | list\|None | `None` | Restrict to IMRaD sections e.g. `["Methods", "Results"]` |

---

## REST API

When running via Docker or `evigraph serve`:

### Health check
```
GET /health
```

### Submit a query
```
POST /api/v1/query
Content-Type: application/json

{
  "query": "What is the effect of BERT pre-training on downstream NLP tasks?",
  "config": { "top_k": 15, "enable_hop": true }
}
```

**Response:**
```json
{
  "job_id": "uuid",
  "status": "completed",
  "answer": "Based on the evidence...",
  "sentences": [{ "text": "...", "citations": ["arxiv:1810.04805"] }],
  "graph": { "nodes": [...], "edges": [...] },
  "scorecard": { "Supported": 12, "Contradicted": 2, "Inconclusive": 3 },
  "elapsed_s": 14.3
}
```

### Streaming (SSE)
```
GET /api/v1/query/stream?q=What+causes+Alzheimers
```

Emits events: `decomposed` → `retrieved` → `graph_built` → `judged` → `completed`

---

## How it works

A query passes through a 5-agent LangGraph pipeline:

```
Query
  │
  ▼
[1] Decomposer
    Breaks the query into focused sub-queries, each tagged with
    IMRaD section targets and a retrieval budget weight.
  │
  ▼
[2] Hybrid Retriever
    BGE-M3 dense + BM25 sparse retrieval, cross-encoder reranking,
    IMRaD section-aware score boosting.
  │
  ▼
[3] Evidence Graph Builder
    Builds a graph of PAPER → CHUNK → CLAIM → CONCEPT nodes.
    Expands citations via SciCite (METHOD / BACKGROUND / RESULT_COMPARISON).
  │
  ▼
[4] Judge
    Three-route verifier: NLI batch → escalate to LLM if neutral
    → direct LLM for cross-paper contradictions.
    Verdict per claim: Supported / Contradicted / Inconclusive.
  │
  ▼
[5] Answer Generator
    Synthesises answer from supported claims only.
    Each sentence carries per-chunk citations and a verdict tag.
```

**Stack:**

| Layer | Technology |
|---|---|
| API | FastAPI + Uvicorn |
| Workflow | LangGraph |
| LLM | DSPy (OpenAI-compatible) |
| Vector DB | Qdrant |
| Embeddings | BGE-M3 |
| NLI | DeBERTa-v3-small-tasksource |

---

## Development

```bash
git clone <repo-url>
cd EviGraph-R
uv sync
cp .env.example .env

# Run tests
uv run pytest -m "not slow and not integration and not hpc"

# Type check
uv run mypy src/
```

---

## License

MIT
