Metadata-Version: 2.4
Name: interpretai
Version: 0.1.5
Summary: Official Python SDK for the InterpretAI public API.
Project-URL: Homepage, https://interpretai.tech
Project-URL: Documentation, https://interpretai.tech/docs
Project-URL: Source, https://github.com/interpretai/interpretai
Project-URL: Issues, https://github.com/interpretai/interpretai/issues
Author-email: InterpretAI <support@interpretai.tech>
License: Apache-2.0
Keywords: ai,evaluation,interpretai,rca,review
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.11
Requires-Dist: anyio>=4.5
Requires-Dist: distro<2,>=1.7
Requires-Dist: httpx>=0.27
Requires-Dist: jiter<1,>=0.4
Requires-Dist: pyyaml>=6
Requires-Dist: tenacity<10,>=8.2.3
Provides-Extra: dev
Requires-Dist: mypy>=1.8; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest>=7.4; extra == 'dev'
Requires-Dist: ruff>=0.5; extra == 'dev'
Description-Content-Type: text/markdown

# interpretai

Official Python SDK for the [InterpretAI](https://interpretai.tech) public API.

This package wraps four feature surfaces — **Match Reviewer**, **Spec Submittal Compliance Review**,
**Agent Root-Cause Analysis (RCA)**, and **Models** — behind a resource-oriented client.
Public Reviewer and SSC follow the canonical `submit -> get -> wait` shape; agent RCA is a
four-call pipeline (`agent_mdp.upload -> ontologies.register -> rca.submit_agent_job -> jobs.wait`).

## API keys
For an API key please email `ilian@interpretai.tech` for early access.

## Install

```bash
pip install interpretai
```

## Quickstart

### Hiring
```python
import os
from interpretai import Client
from interpretai.types.public_reviewer import ReviewRequest, Subject

client = Client(api_key=os.environ["INTERPRETAI_API_KEY"])

job = client.public_reviewer.submit(ReviewRequest(
    subjects=[
        Subject(pdf="path/to/resume.pdf", label="candidate"),
        Subject(text=[
                "Company A: Working on Agentic AI for job matching", 
                "Looking for talented engineer with experience in the space",
            ], 
            pdf="path/to/relevant/job/description", 
        label="b"),
    ],
    prompt="Is the candidate a good fit, why or why not?",
    model_tier="tlarge",
))

result = client.public_reviewer.wait(job.job_id, timeout_s=1200)
print(result.score, result.reasoning)
```

### Async

```python
import asyncio
from interpretai import AsyncClient
from interpretai.types.public_reviewer import ReviewRequest, Subject

async def main() -> None:
    async with AsyncClient() as client:
        job = await client.public_reviewer.submit(ReviewRequest(
            subjects=[Subject(text="..."), Subject(text="...")],
            prompt="...",
            model_tier="tlarge",
        ))
        result = await client.public_reviewer.wait(job.job_id)
        print(result.score)

asyncio.run(main())
```

### Per-request overrides

```python
fast = client.with_options(timeout=10.0, max_retries=0)
fast.public_reviewer.submit(...)
```

## Configuration

The SDK reads two environment variables when the constructor parameters are
not supplied:

- `INTERPRETAI_API_KEY` — your API key (must start with `iai_`).
- `INTERPRETAI_BASE_URL` — base URL (defaults to `https://stage-app.interpretai.tech`).

## Resources

| Resource | Methods |
|---|---|
| `client.auth` | `me()` |
| `client.public_reviewer` | `submit()`, `get(job_id)`, `wait(job_id, ...)` |
| `client.ssc` | `submit()`, `get(job_id)`, `wait(job_id, ...)` |
| `client.agent_mdp` | `upload(item)` — durably persist an `AgentTaskWithMetadata` before RCA |
| `client.ontologies` | `register(req)`, `list()`, `get(id)`, `delete(id)` — per-org failure-mode catalogues |
| `client.rca` | `submit_agent_job(req)` — enqueue agent RCA, `similar_failures(req)` — kNN history search |
| `client.jobs` | `get(job_id)`, `list()`, `wait(job_id, ...)` — unified poll for every async pipeline |

### Agent RCA quickstart

Agent RCA does **not** fit the canonical `submit -> get -> wait` shape. Trajectories must be persisted
first so the worker can hydrate the full payload from storage; the flow is four calls:

```python
import os
from interpretai import (
    AgentRcaResult,
    Client,
    CreateAgentRcaJobRequest,
    EvaluatorDefinition,
    RegisterOntologyRequest,
    load_agent_failures_ontologies,
)

client = Client(api_key=os.environ["INTERPRETAI_API_KEY"])

# 1) Upload one trajectory (see interpretai.types.agent_mdp for the dataclass shapes).
uploaded = client.agent_mdp.upload(item)  # build `item: AgentTaskWithMetadata`

# 2) Register each evaluator. The bundled `agent_failures` pack ships 5 baseline
# evaluators (goal interpretation, plan construction, hallucination control,
# runaway loops, post-action verification); layer per-org evaluators alongside.
bundled = load_agent_failures_ontologies()
custom = RegisterOntologyRequest(name="PII leakage", evaluators=[
    EvaluatorDefinition(
        name="pii_leakage",
        description="Did the agent emit PII anywhere it shouldn't?",
        scoring_type="global",
        inputs=["image", "axtree", "agent_action", "agent_output"],
    ),
])
ontology_ids = [client.ontologies.register(req).ontology_id for req in [*bundled, custom]]

# 3) Enqueue the RCA job.
accepted = client.rca.submit_agent_job(CreateAgentRcaJobRequest(
    dataset_id=uploaded.dataset_id or "default",
    task_id=uploaded.task_id,
    agent_model="ge-medium",
    ontology_ids=ontology_ids,
))

# 4) Poll the unified jobs endpoint and hydrate the verdict.
completed = client.jobs.wait(accepted.job_id, timeout_s=1800.0)
rca = AgentRcaResult.from_dict(completed.result or {})
for verdict in rca.ontology_results:
    print(verdict.ontology_id, verdict.success_or_failure, verdict.score)
```

Full worked example with progress logging, custom evaluator prompts, and post-run KNN search:
[`interpret/experimental/rca_agent_e2e.py`](https://github.com/interpretai/interpretai/blob/main/interpret/experimental/rca_agent_e2e.py).
See also the [agent RCA docs page](https://interpretai.tech/docs/examples/agent-rca).

## Architecture

A layered SDK in the shape of `openai-python` / `anthropic-sdk-python`, with a uniform `submit -> get -> wait` flow across every feature surface. Caller code reaches into a top-level `Client` (or `AsyncClient`), which composes one resource per feature on top of a single shared HTTP transport.

```mermaid
flowchart TD
    UserCode["User code"] --> Top["interpretai (top-level re-exports)"]
    Top --> Client["Client / AsyncClient (client.py)"]
    Client --> Resources["Resources (resources/*.py): auth, public_reviewer, ssc, rca, agent_mdp, jobs"]
    Resources --> Base["BaseResource / BaseAsyncResource (_base.py)"]
    Resources --> Polling["wait_for_terminal (_polling.py)"]
    Resources --> Types["Types (types/*.py) frozen dataclasses"]
    Base --> Transport["SyncTransport / AsyncTransport (_http.py)"]
    Transport --> Options["RequestOptions + merge_options (_options.py)"]
    Transport --> Errors["Errors (errors.py) + from_response"]
    Transport --> Constants["Protocol constants (_constants.py)"]
    Transport --> Httpx["httpx.Client / httpx.AsyncClient + tenacity"]
```

### Layers

- **Client** ([`client.py`](src/interpretai/client.py)) — `Client` / `AsyncClient` each compose a transport plus one resource per feature. `with_options(...)` derives a new client that shares the underlying `httpx.Client` but applies merged defaults (timeout, retries, headers, idempotency key).
- **Resources** ([`resources/`](src/interpretai/resources)) — one module per feature surface (`auth`, `public_reviewer`, `ssc`, `rca`, `agent_mdp`, `jobs`). Each subclasses `BaseResource` / `BaseAsyncResource` and exposes `submit` / `get` / `wait` against a `/api/v1/<feature>` route.
- **Transport** ([`_http.py`](src/interpretai/_http.py)) — `SyncTransport` / `AsyncTransport` wrap `httpx.Client` / `httpx.AsyncClient`. The transport injects `Authorization: Bearer ...`, `User-Agent`, the `X-Interpretai-*` analytics suite, and a per-POST `Idempotency-Key`. Retries are driven by `tenacity` and honor a server-supplied `Retry-After` (capped) plus the `x-should-retry` directive.
- **Options** ([`_options.py`](src/interpretai/_options.py)) — `RequestOptions` is a frozen dataclass; `merge_options(...)` overlays per-call overrides on top of client-level defaults so every call point goes through one merge rule.
- **Polling** ([`_polling.py`](src/interpretai/_polling.py)) — every resource's `wait()` calls into a single `wait_for_terminal` (sync and async). Cadence is capped exponential growth (x1.5) from `poll_interval_s` to `max_poll_interval_s`, bounded by `timeout_s`.
- **Types** ([`types/`](src/interpretai/types)) — request / response models are frozen `@dataclass` objects with explicit `to_dict` / `from_dict`. No pydantic; on-the-wire keys are snake_case.
- **Errors** ([`errors.py`](src/interpretai/errors.py)) — `InterpretError` root, with `APIError` / `APIStatusError` and one subclass per common HTTP status (400, 401, 403, 404, 409, 422, 429, 5xx), plus `JobFailedError`, `JobTimeoutError`, and `ValidationError`. `from_response(...)` maps an `httpx.Response` to the most specific subclass and carries the server `request-id` for support tickets.
- **Constants** ([`_constants.py`](src/interpretai/_constants.py)) — protocol-level knobs: default base URL, default timeout, retry timing, `RETRYABLE_STATUS = {408, 425, 429, 500, 502, 503, 504}`, and the SDK's `interpretai.*` logger namespace.

### Design principles

- **Sync + async are parallel everywhere.** `Client` vs `AsyncClient`, `SyncTransport` vs `AsyncTransport`, `wait_for_terminal` vs `wait_for_terminal_async`, `BaseResource` vs `BaseAsyncResource`. Same surface, two execution models.
- **Uniform `submit -> get -> wait` shape** across every job pipeline so adding a new feature is a copy of an existing resource module.
- **Externally shipped, no monorepo imports.** The SDK uses stdlib `logging` under `interpretai.*` namespaces — never `interpret.tools.logger` — and only `__init__.py` re-exports public symbols.
- **Per-call overrides mirror `openai-python`.** `RequestOptions` + `client.with_options(...)` gives the same ergonomics for tweaking timeout / retries / headers / idempotency on a single call or a derived client.

See the [top-level SDK README](https://github.com/interpretai/interpretai/blob/main/interpret/sdk/README.md)
for design notes and roadmap.

## License

Apache-2.0
