Metadata-Version: 2.4
Name: r3context
Version: 0.5.0
Summary: Just-in-time reasoning over a collection of documents: surface relevance, structure it, reason over it.
Keywords: llm,agent,documents,reasoning,multi-document,question-answering
Author: Michael Theologitis
Author-email: Michael Theologitis <michael.theologitis@outlook.com>
License-Expression: MIT AND Apache-2.0
License-File: LICENSE
License-File: LICENSE-APACHE-2.0
License-File: NOTICE
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Science/Research
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: Text Processing
Classifier: Typing :: Typed
Requires-Dist: litellm>=1.103,<2
Requires-Dist: jinja2>=3.1.0
Requires-Dist: pydantic>=2.11
Requires-Dist: pyyaml>=6.0
Requires-Dist: python-dotenv>=1.0.0
Requires-Dist: tenacity>=8.0
Requires-Dist: pypdf>=6.19.0
Requires-Python: >=3.11
Project-URL: Homepage, https://github.com/michaeltheologitis/r3con
Project-URL: Repository, https://github.com/michaeltheologitis/r3con
Description-Content-Type: text/markdown

# r3con

[![arXiv](https://img.shields.io/badge/arXiv-2609.27173-b31b1b.svg)](https://arxiv.org/abs/2609.27173)
![Python](https://img.shields.io/badge/python-%3E%3D3.11-blue)
[![License](https://img.shields.io/badge/license-MIT-green)](https://github.com/michaeltheologitis/r3con/blob/main/LICENSE)

**Context representation for large-scale reasoning.**

Ask a question whose evidence is scattered across many documents. `r3con` builds a
task-specific representation of that context, then reasons over it to produce an answer.

![How r3con works](https://raw.githubusercontent.com/michaeltheologitis/r3con/main/docs/r3con.png)

## Install

```bash
pip install r3context
```

Set the API key(s) for the provider(s) you use:

```bash
export OPENAI_API_KEY=sk-...
export ANTHROPIC_API_KEY=sk-ant-...
```

You can also put them in a `.env` file in your working directory.

## Usage

### Command line

Pass a directory, glob, or list of files:

```bash
r3con run "Which supplier missed the most delivery windows?" ./reports \
  --model openai/gpt-6-luna
```

`--model` accepts any [LiteLLM](https://docs.litellm.ai/docs/providers) model string, for
example:

```
anthropic/claude-sonnet-5-5
gemini/gemini-3.8-flash
hosted_vllm/Qwen/Qwen3.5-35B-A3B
```

The default is `openai/gpt-6-luna`.

Directories are searched recursively. You can also use glob patterns or pass files directly:

```bash
r3con run "Who approved the Q3 overspend?" "./reports/*.pdf"
r3con run "Who approved the Q3 overspend?" "./reports/**/*.pdf"
r3con run "Who approved the Q3 overspend?" q1.md q2.md q3.md
```

Quote glob patterns so your shell passes them to `r3con` unchanged.

### Python

Load documents from a directory, glob, or list of files:

```python
from r3con import r3con

docs = r3con.read_documents("./reports")
result = r3con.run(
    "Which supplier missed the most delivery windows?",
    docs,
)
print(result)  # "Ardent Logistics missed the most delivery windows: 8 in total."
```

`read_documents` supports `.txt`, `.md`, `.csv`, `.json`, `.html`, `.xml`, `.pdf`, and
other common text formats.

If you already have the documents in memory, pass them directly:

```python
result = r3con.run(
    "Which supplier missed the most delivery windows?",
    [doc_a, doc_b, doc_c],
)
```

`documents` is simply a list of strings, one per document.

To ask a new question over the same run, `r3con.ask` reuses what the run built and runs
only the reasoning step, at a fraction of a run's cost:

```python
other = r3con.ask(result, "Which supplier delivered on time most often?")
print(other)
```

To stop a run from another thread, pass `cancel=threading.Event()` and set it: no new
model call is sent and the run raises `r3con.Cancelled`, leaving what it did so far in
its folder. What is already under way runs its course: a call already sent (so a run on
its last call finishes normally), resends r3con doesn't make itself (a `completion=`, or
retry settings in `params`), and a sandbox step. `r3con.ask` takes `cancel` too.

## Notebooks

The examples use five short memos arranged so that no single document contains the full
answer:

- [`examples/quickstart.ipynb`](https://github.com/michaeltheologitis/r3con/blob/main/examples/quickstart.ipynb) — an end-to-end example.
- [`examples/provenance.ipynb`](https://github.com/michaeltheologitis/r3con/blob/main/examples/provenance.ipynb) — tracing an answer back to the documents and
  summaries it came from.
- [`examples/options.ipynb`](https://github.com/michaeltheologitis/r3con/blob/main/examples/options.ipynb) — models, relevance rounds, the reasoning
  path, generation parameters, run configuration, custom connections, and artifact paths.
- [`examples/vllm.ipynb`](https://github.com/michaeltheologitis/r3con/blob/main/examples/vllm.ipynb) — using a self-hosted vLLM endpoint.

## Output

`r3con.run(...)` returns a result object containing the final answer and the representation
built during the run:

```python
result.answer  # str       — final answer
result.relevant_context  # list[str] — final relevance snippets
result.structured_context  # dict      — structured representation
result.run_dir  # Path      — directory containing run artifacts
```

r3con also records provenance, how the answer, each summary and each parse came to be; see
[`examples/provenance.ipynb`](https://github.com/michaeltheologitis/r3con/blob/main/examples/provenance.ipynb).

## Run artifacts

Every run writes each stage's output and model calls, failed ones included, with their
tokens, cost, and any resends and the wait between them, to a folder under `./logs`.
An API key that a provider's error echoes is masked before r3con writes or logs it:
the keys r3con sends, a `litellm.Router`'s included, and the environment's. A
`completion=` wrapper that adds a key of its own must register it with
`r3con.masking.register_key(key)`.

```
logs/<timestamp>_<hex>/          <- result.run_dir
├── ids.json                     <- each document's id
├── events.jsonl                 <- each stage's start and finish, as they happened
├── splits.json                  <- only when a document was read in parts
├── relevance/
│   ├── result.json              <- each round's snippets
│   └── calls.json
├── structuring/
│   ├── schema/
│   │   ├── result.json
│   │   ├── calls.json
│   │   └── transcript.yaml
│   └── parsing/
│       ├── result.json          <- the parsed records
│       └── calls.json
├── reasoning/
│   ├── result.json              <- the answer
│   ├── calls.json
│   └── transcript.yaml
└── asks/<folder>/               <- one per r3con.ask: manifest.json, events.jsonl and reasoning/
```

## Evaluation

Paper: for benchmark results, baselines, and evaluation code, see
[r3con-evaluation](https://github.com/michaeltheologitis/r3con-evaluation).

## License

MIT — see [LICENSE](https://github.com/michaeltheologitis/r3con/blob/main/LICENSE).

`src/r3con/runtime/python_executor.py` contains a modified version of the sandboxed
interpreter from [smolagents](https://github.com/huggingface/smolagents), licensed under
Apache-2.0 and © HuggingFace Inc. See [NOTICE](https://github.com/michaeltheologitis/r3con/blob/main/NOTICE) and
[LICENSE-APACHE-2.0](https://github.com/michaeltheologitis/r3con/blob/main/LICENSE-APACHE-2.0).
