Metadata-Version: 2.4
Name: convopack
Version: 0.3.2
Summary: Framework-agnostic, provider-agnostic context-window packer for LLM chat history.
Project-URL: Homepage, https://mrrobi.github.io/convopack/
Project-URL: Documentation, https://mrrobi.github.io/convopack/
Project-URL: Repository, https://github.com/Mrrobi/convopack
Project-URL: Source, https://github.com/Mrrobi/convopack
Project-URL: Issues, https://github.com/Mrrobi/convopack/issues
Project-URL: Changelog, https://github.com/Mrrobi/convopack/blob/main/CHANGELOG.md
Project-URL: Release-Notes, https://github.com/Mrrobi/convopack/releases
Author-email: Mrrobi <mrrobi040@gmail.com>
License-Expression: MIT
License-File: LICENSE
Keywords: anthropic,chat,context-window,llm,memory,openai,prompt,tokenizer
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
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.10
Provides-Extra: all
Requires-Dist: anthropic>=0.40; extra == 'all'
Requires-Dist: langchain-core>=0.3; extra == 'all'
Requires-Dist: tiktoken>=0.7; extra == 'all'
Requires-Dist: transformers>=4.40; extra == 'all'
Provides-Extra: anthropic
Requires-Dist: anthropic>=0.40; extra == 'anthropic'
Provides-Extra: dev
Requires-Dist: anthropic>=0.40; extra == 'dev'
Requires-Dist: coverage[toml]>=7; extra == 'dev'
Requires-Dist: hypothesis>=6; extra == 'dev'
Requires-Dist: langchain-core>=0.3; extra == 'dev'
Requires-Dist: mypy>=1.10; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest-cov>=5; extra == 'dev'
Requires-Dist: pytest>=8; extra == 'dev'
Requires-Dist: ruff>=0.6; extra == 'dev'
Requires-Dist: tiktoken>=0.7; extra == 'dev'
Requires-Dist: transformers>=4.40; extra == 'dev'
Provides-Extra: docs
Requires-Dist: mkdocs-jupyter>=0.25; extra == 'docs'
Requires-Dist: mkdocs-material>=9.5; extra == 'docs'
Requires-Dist: mkdocs>=1.6; extra == 'docs'
Requires-Dist: mkdocstrings[python]>=0.26; extra == 'docs'
Requires-Dist: pymdown-extensions>=10.10; extra == 'docs'
Provides-Extra: dspy
Requires-Dist: dspy>=2.5; extra == 'dspy'
Provides-Extra: huggingface
Requires-Dist: transformers>=4.40; extra == 'huggingface'
Provides-Extra: langchain
Requires-Dist: langchain-core>=0.3; extra == 'langchain'
Provides-Extra: litellm
Requires-Dist: litellm>=1.40; extra == 'litellm'
Provides-Extra: mem0
Requires-Dist: mem0ai>=0.1; extra == 'mem0'
Provides-Extra: pydantic
Requires-Dist: pydantic>=2.7; extra == 'pydantic'
Provides-Extra: tiktoken
Requires-Dist: tiktoken>=0.7; extra == 'tiktoken'
Description-Content-Type: text/markdown

# convopack

[![PyPI](https://img.shields.io/pypi/v/convopack.svg)](https://pypi.org/project/convopack/)
[![Python](https://img.shields.io/pypi/pyversions/convopack.svg)](https://pypi.org/project/convopack/)
[![CI](https://github.com/Mrrobi/convopack/actions/workflows/ci.yml/badge.svg)](https://github.com/Mrrobi/convopack/actions/workflows/ci.yml)
[![codecov](https://codecov.io/gh/Mrrobi/convopack/branch/main/graph/badge.svg)](https://codecov.io/gh/Mrrobi/convopack)
[![Typed](https://img.shields.io/badge/typed-yes-success.svg)](https://github.com/Mrrobi/convopack/blob/main/src/convopack/py.typed)
[![uv](https://img.shields.io/badge/uv-supported-blueviolet.svg)](https://docs.astral.sh/uv/)
[![License](https://img.shields.io/pypi/l/convopack.svg)](https://github.com/Mrrobi/convopack/blob/main/LICENSE)

Framework-agnostic, provider-agnostic context-window packer for LLM chat history.

## Why

LLM apps accumulate messages until they overflow the model's context window. Existing fixes are framework-locked (LangChain, LangGraph), provider-specific (Anthropic context-management beta), or designed for long-term semantic memory rather than turn-by-turn packing (mem0).

`convopack` is a small, focused library that takes a conversation history and a token budget and returns the largest tail that fits, while:

- preserving `tool_use` / `tool_result` pairs atomically,
- normalising message shapes across OpenAI, Anthropic, and Gemini,
- letting you plug in any tokenizer or summariser,
- staying async-friendly and zero-dependency at the core.

## Install

```bash
pip install convopack                 # core only
pip install "convopack[tiktoken]"     # + OpenAI tokenizer
pip install "convopack[anthropic]"    # + Anthropic tokenizer
pip install "convopack[all]"          # everything

# or with uv
uv add convopack                       # core
uv add "convopack[all]"                # everything
```

The library ships a `py.typed` marker; `mypy --strict` and `pyright` both
recognise its public types without further configuration.

## Quickstart

```python
from convopack import Packer, Recency

packer = Packer(
    budget=8000,
    tokenizer="tiktoken:gpt-4o",
    strategy=Recency(),
    pin=["system", "first_user"],
)

packed = packer.pack(messages)        # list[dict] in, list[dict] out
```

## Strategies

| Strategy        | When to use                                                            |
| --------------- | ---------------------------------------------------------------------- |
| `Recency`       | Keep the tail that fits. Cheapest, no LLM call.                        |
| `FirstFit`      | Keep the oldest chunks that fit. Good when system + few-shots dominate.|
| `SummaryEvict`  | Summarise evicted turns into a single system message.                  |
| `Importance`    | Score each turn yourself; drop the lowest until it fits.               |
| `SemanticDedup` | Remove near-duplicate turns by embedding cosine, then fall back.       |

## Comparison

| Feature                       | convopack | LangChain `trim_messages` | mem0          | Anthropic native |
| ----------------------------- | --------- | ------------------------- | ------------- | ---------------- |
| Framework-free                | yes       | no                        | no            | yes              |
| Multi-provider message shapes | yes       | partial                   | n/a           | no               |
| Tool-call pair safety         | yes       | no                        | n/a           | yes (one type)   |
| Pluggable strategy            | yes       | no                        | n/a           | no               |
| Async summariser              | yes       | no                        | n/a           | n/a              |
| Scope                         | per-turn  | per-turn                  | cross-session | per-turn         |

## Example notebooks

Self-contained Jupyter notebooks. Every one runs end-to-end without an API
key (they use the zero-dependency `approx` tokenizer and deterministic
fakes). All four are executed in CI to stay in sync with the library.

| Notebook | What it covers |
|---|---|
| [`01_quickstart.ipynb`](docs/notebooks/01_quickstart.ipynb) | Build a `Packer`, pack a history, round-trip through OpenAI shape, scan budgets. |
| [`02_tool_pair_atomicity.ipynb`](docs/notebooks/02_tool_pair_atomicity.ipynb) | The killer feature: `tool_use` / `tool_result` pairs stay together for every strategy. Includes a 200-iteration property check. |
| [`03_strategies.ipynb`](docs/notebooks/03_strategies.ipynb) | Same history through all five strategies side-by-side. |
| [`04_prompt_caching.ipynb`](docs/notebooks/04_prompt_caching.ipynb) | Anthropic `cache_control` markers, OpenAI prefix-stability signature, cost back-of-envelope. |

Rendered with outputs at <https://mrrobi.github.io/convopack/notebooks/01_quickstart/>.

## License

MIT
