# API Reference

---

## `Doctor`

The main entry point. Orchestrates the six diagnostic tools.

```python
from rag_doctor import Doctor
```

### Class Methods

#### `Doctor.default(connector=None) -> Doctor`

Create a `Doctor` with default configuration (thresholds calibrated for TF-IDF).

```python
doctor = Doctor.default()
doctor = Doctor.default(connector=MyConnector())
```

#### `Doctor.from_config(path, connector=None) -> Doctor`

Load configuration from a YAML file.

```python
doctor = Doctor.from_config("rag-doctor.yaml")
```

---

### Instance Methods

#### `doctor.diagnose(query, answer, docs=None, expected=None, corpus_texts=None) -> DiagnosisReport`

Run the full diagnosis loop.

| Parameter | Type | Required | Description |
|---|---|---|---|
| `query` | `str` | Yes | The user's original query |
| `answer` | `str` | Yes | The answer generated by your RAG pipeline |
| `docs` | `List[Document]` | No | Pre-retrieved documents. If `None`, uses connector to retrieve. |
| `expected` | `str` | No | Ground-truth answer. Improves retrieval and hallucination diagnosis. |
| `corpus_texts` | `List[str]` | No | Full document corpus. Required for ChunkOptimizer. |

**Returns:** `DiagnosisReport`

```python
report = doctor.diagnose(
    query    = "What is the refund policy?",
    answer   = "30 day returns.",
    docs     = retrieved_docs,
    expected = "Full refunds within 30 days of purchase.",
)
```

#### `doctor.batch_diagnose(cases) -> List[DiagnosisReport]`

Diagnose multiple cases at once.

```python
cases = [
    {"query": "...", "answer": "...", "docs": [...], "expected": "..."},
    {"query": "...", "answer": "..."},
]
reports = doctor.batch_diagnose(cases)
```

---

## `DiagnosisReport`

Returned by `diagnose()` and `batch_diagnose()`.

### Properties

| Property | Type | Description |
|---|---|---|
| `root_cause` | `str` | One of: `healthy`, `retrieval_miss`, `context_position_bias`, `chunk_fragmentation`, `hallucination`, `query_mismatch` |
| `root_cause_id` | `str` | Short code: `RC-0` through `RC-5` |
| `severity` | `str` | One of: `low`, `medium`, `high`, `critical` |
| `passed` | `bool` | `True` if `root_cause == "healthy"` |
| `finding` | `str` | Human-readable description of what was found |
| `fix_suggestion` | `str` | Concrete actionable fix |
| `config_patch` | `dict` | Config key-values to change (e.g. `{"chunking.chunk_size": 256}`) |
| `tool_results` | `List[ToolResult]` | Results from each diagnostic tool |
| `query` | `str` | The query that was diagnosed |
| `faithfulness_score` | `float` | 0.0–1.0 faithfulness score from HallucinationTracer |
| `retrieval_score` | `float` | Best retrieval similarity score |

### Methods

#### `report.to_json() -> str`

Serialize to JSON string.

#### `report.to_dict() -> dict`

Serialize to dictionary.

#### `report.to_text() -> str`

Human-readable text report.

---

## `ToolResult`

Each tool produces a `ToolResult`.

| Property | Type | Description |
|---|---|---|
| `tool_name` | `str` | Tool class name |
| `passed` | `bool` | Whether this tool detected an issue |
| `severity` | `str` | `low`, `medium`, `high`, `critical` |
| `finding` | `str` | What this tool found |
| `details` | `dict` | Tool-specific details (scores, positions, etc.) |

---

## `Document`

A retrieved document chunk.

```python
from rag_doctor.connectors.base import Document
```

| Field | Type | Description |
|---|---|---|
| `content` | `str` | The document text |
| `metadata` | `dict` | Arbitrary metadata |
| `score` | `float` | Retrieval similarity score (0.0–1.0) |
| `position` | `int` | Position in the context window (0-indexed) |
| `doc_id` | `str` (optional) | Document identifier |

---

## `PipelineConnector`

Abstract base class for connecting rag-doctor to your RAG stack.

```python
from rag_doctor.connectors.base import PipelineConnector, Document
```

### Required Methods

#### `retrieve(query, top_k=5) -> List[Document]`

Retrieve top-k documents for a query.

#### `generate(query, docs) -> str`

Generate an answer given a query and retrieved documents.

### Optional Methods

#### `embed(text) -> List[float]`

Embed text. Override to use your own embedding model.

---

## `MockConnector`

Built-in connector for testing. No external dependencies.

```python
from rag_doctor.connectors.mock import MockConnector

conn = MockConnector(corpus=["doc 1 text...", "doc 2 text...", ...])
docs = conn.retrieve("query", top_k=5)
answer = conn.generate("query", docs)
```

### Parameters

| Parameter | Type | Description |
|---|---|---|
| `corpus` | `List[str]` | Document texts |
| `inject_position_bias` | `bool` | For testing: moves best doc to middle position |
| `inject_hallucination` | `bool` | For testing: generates a hallucinated answer |

---

## `RagDoctorConfig`

Configuration dataclass.

```python
from rag_doctor import RagDoctorConfig
```

### Factory Methods

```python
cfg = RagDoctorConfig.default()          # sensible defaults
cfg = RagDoctorConfig.from_yaml("rag-doctor.yaml")  # from file
```

### Diagnosis Thresholds

Accessible via `cfg.diagnosis`:

| Field | Default (TF-IDF) | Recommended (sentence-transformers) |
|---|---|---|
| `recall_threshold` | `0.35` | `0.65` |
| `faithfulness_threshold` | `0.40` | `0.65` |
| `coherence_threshold` | `0.25` | `0.55` |
