Extensible conversation context management toolkit for LLM applications
Project description
context-pipe
Extensible conversation context management toolkit for LLM applications.
context-pipe manages conversation history within token budgets — storing messages, triggering summarization when the context window fills up, and persisting conversations to pluggable backends. Compaction logic is provider-agnostic: you inject whatever LLM call you want.
Installation
Install the base package:
uv add context-pipe
Or with optional backend support:
# With in-memory backend
uv add context-pipe[memory]
# With Redis backend
uv add context-pipe[redis]
# With SQLAlchemy backend
uv add context-pipe[sqlalchemy]
# With all backends
uv add context-pipe[all]
Quick Start
import asyncio
from context_pipe import (
Conversation,
Message,
Role,
WindowPolicy,
CompactionEngine,
AbstractCompactor,
)
from context_pipe_memory import MemoryBackend
class SimpleCompactor(AbstractCompactor):
"""A simple compactor that summarizes messages."""
def summarize(self, messages: list[Message]) -> str:
"""Summarize messages by taking the first and last (sync)."""
if not messages:
return ""
return f"Summary of {len(messages)} messages: {messages[0].content} ... {messages[-1].content}"
async def asummarize(self, messages: list[Message]) -> str:
"""Summarize messages by taking the first and last (async)."""
if not messages:
return ""
return f"Summary of {len(messages)} messages: {messages[0].content} ... {messages[-1].content}"
# Async example
async def async_example():
# Create a conversation
conv = Conversation(id="conv-1")
# Add messages
conv.append(
Message(
role=Role.USER,
content="What is the capital of France?",
token_count=10,
)
)
conv.append(
Message(
role=Role.ASSISTANT,
content="The capital of France is Paris.",
token_count=12,
)
)
# Set up compaction with a token budget
policy = WindowPolicy(token_budget=100, trigger_at=0.8, keep_n_recent=2)
compactor = SimpleCompactor()
engine = CompactionEngine(policy=policy, compactor=compactor)
# Use the backend to persist (async)
backend = MemoryBackend()
await backend.asave(conv)
# Load and compact
loaded = await backend.aload("conv-1")
compacted = await engine.maybe_compact(loaded)
await backend.asave(compacted)
print(f"Total tokens: {compacted.total_tokens()}")
print(f"Active messages: {len(compacted.active_messages())}")
print(f"Summaries: {len(compacted.summaries)}")
# Sync example
def sync_example():
# Create a conversation
conv = Conversation(id="conv-2")
# Add messages
conv.append(
Message(
role=Role.USER,
content="What is the capital of Germany?",
token_count=10,
)
)
conv.append(
Message(
role=Role.ASSISTANT,
content="The capital of Germany is Berlin.",
token_count=12,
)
)
# Use the backend to persist (sync)
backend = MemoryBackend()
backend.save(conv)
# Load (sync)
loaded = backend.load("conv-2")
print(f"Loaded conversation with {len(loaded.messages)} messages")
if __name__ == "__main__":
# Run async example
asyncio.run(async_example())
# Run sync example
sync_example()
Sync and Async APIs
context-pipe provides both synchronous and asynchronous versions of all backend methods and compactors, following Django's async conventions:
- Async methods use an
aprefix:asave(),aload(),adelete(),aexists(),asummarize() - Sync methods use regular names:
save(),load(),delete(),exists(),summarize()
This allows you to use the same library in both async-first and sync-first applications:
# Async usage
backend = MemoryBackend()
await backend.asave(conversation)
loaded = await backend.aload(conv_id)
# Sync usage (same backend instance)
backend = MemoryBackend()
backend.save(conversation)
loaded = backend.load(conv_id)
Documentation
For detailed documentation, visit the full docs or see Getting Started.
Features
- Flexible Storage — In-memory, Redis, SQLAlchemy, or custom backends
- Sync/Async Dual API — Use the same library in sync-first or async-first applications
- Token Budget Management — Automatic compaction when approaching context limits
- Provider-Agnostic Compaction — Bring your own LLM or summarization logic
- Type-Safe — Full type hints and mypy strict mode support
- Extensible — Simple interfaces for custom backends and compactors
Contributing
We welcome contributions, suggestions, and ideas! context-pipe is designed to be extensible, and we're particularly interested in:
- New Backend Implementations — Add support for additional storage systems
- Compaction Algorithms — Propose or implement novel message summarization strategies
- Token Counting Strategies — Different tokenization approaches for various LLM providers
- Performance Optimizations — Improve compaction efficiency and backend speed
- Documentation & Examples — Help us document use cases and best practices
- Bug Reports & Feature Requests — Let us know how we can improve
How to Contribute
- Fork the repository
- Create a feature branch (
git checkout -b feature/my-algorithm) - Make your changes and ensure tests pass (
uv run pytest) - Submit a pull request with a clear description
Algorithm Contributions
If you're implementing a new compaction algorithm or backend strategy:
- Add comprehensive docstrings explaining the approach
- Include unit tests demonstrating the behavior
- Update documentation with performance characteristics
- Consider async/await patterns for consistency
See the Getting Started guide for development setup.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file context_pipe-0.1.0-py3-none-any.whl.
File metadata
- Download URL: context_pipe-0.1.0-py3-none-any.whl
- Upload date:
- Size: 7.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b70e5963e01d654060d6817b8c3dc306c1eeaa53f9debffb1865ae05928bccad
|
|
| MD5 |
42f9c8405aeb4c02a3f754160c70f9eb
|
|
| BLAKE2b-256 |
1ff33234ddc07bdabb00e61622600c6d8b73973351d2159ed6c25a90bd1dcc0e
|
Provenance
The following attestation bundles were made for context_pipe-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on sarvesh4396/context-pipe
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
context_pipe-0.1.0-py3-none-any.whl -
Subject digest:
b70e5963e01d654060d6817b8c3dc306c1eeaa53f9debffb1865ae05928bccad - Sigstore transparency entry: 1262378606
- Sigstore integration time:
-
Permalink:
sarvesh4396/context-pipe@9f705b0876f6505d7a000df2104bbc1ab4e257a9 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/sarvesh4396
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@9f705b0876f6505d7a000df2104bbc1ab4e257a9 -
Trigger Event:
workflow_dispatch
-
Statement type: