Metadata-Version: 2.4
Name: upryaga
Version: 0.0.1
Summary: Reasoning harness framework for Anthropic Claude
Project-URL: Repository, https://github.com/walnutgeek/upryaga
Author-email: Walnut Geek <wg@walnutgeek.com>
License-Expression: MIT
License-File: LICENSE
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
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: Typing :: Typed
Requires-Python: <4.0,>=3.11
Requires-Dist: anthropic
Requires-Dist: datasets
Requires-Dist: pydantic
Requires-Dist: scikit-learn
Description-Content-Type: text/markdown

# upryaga

For now it is personal research project with goal to understand and build recurrent self-improving harnesses.

Name derived from Упряж - means harness in ukraninan, russian and may be other slavic languages.

A reasoning harness framework for Anthropic Claude. Runs a Propose-Critique-Refine-Verify loop over reasoning problems, with Reflexion-style memory that accumulates failure experiences across runs.

Personal research project exploring recurrent self-improving harnesses — learning by building.

## Install

```bash
pip install upryaga
```

Or for development:

```bash
git clone https://github.com/walnutgeek/upryaga.git
cd upryaga
uv sync --all-extras
```

## Quick Start

```python
import asyncio
from upryaga import Harness, Problem
from upryaga.reasoner import ClaudeReasoner
from upryaga.critic import ClaudeCritic
from upryaga.memory import ReflexionMemory
from upryaga.verifier import MathVerifier

harness = Harness(
    reasoner=ClaudeReasoner(model="claude-sonnet-4-6"),
    critic=ClaudeCritic(model="claude-haiku-4-5-20251001"),
    memory=ReflexionMemory(path="./memory"),
    verifier=MathVerifier(),
    max_iterations=3,
)

solution = asyncio.run(harness.solve(Problem(question="What is 247 * 83?")))
print(solution.answer)
```

## Benchmarking

Evaluate harness configurations against GSM8K or MATH:

```python
from upryaga.benchmark.runner import BenchmarkRunner

runner = BenchmarkRunner(harness=harness, verifier=MathVerifier())
results = asyncio.run(runner.run("gsm8k", split="test", limit=50))
print(results.summary())
# Dataset: gsm8k
# Accuracy: 41/50 (82.0%)
# Avg iterations: 2.3
# Avg tokens/problem: 4,120
# Total cost: $1.47
```

## Architecture

```
Problem in
    |
    v
 Memory ----> retrieves similar past experiences
    |
    v
 Reasoner --> generates solution (Claude API)
    |
    v
 Critic ----> evaluates solution (Claude API)
    |
    |-- unsatisfactory --> loop back with feedback
    |
    +-- satisfactory ----> final answer
                              |
                              v
                          Verifier --> checks against ground truth
                              |
                              v
                          Memory <--- stores experience + reflection
```

All components are pluggable Python Protocols — swap any implementation without changing the rest.

## Components

| Component | Default Implementation | Purpose |
|-----------|----------------------|---------|
| Reasoner | `ClaudeReasoner` | Generates step-by-step solutions |
| Critic | `ClaudeCritic` | Evaluates solution quality |
| Memory | `ReflexionMemory` | TF-IDF episodic memory, failure-prioritized |
| Verifier | `MathVerifier` | Deterministic answer comparison |

## Development

```bash
make install   # uv sync
make lint      # ruff + basedpyright + codespell
make test      # pytest
```

## License

MIT
