ChatVault
Vault your conversations. Unlock your context.
A lightweight Python library for managing AI chat conversations with file attachments. Bring your own storage backends.
Features
- 🗂️ Conversation Management - Create, load, resume, and archive conversations
- 💬 Message History - Store and retrieve chat messages with metadata
- 📎 File Attachments - Attach files to conversations
- 🔌 Pluggable Backends - Implement your own storage for any cloud provider
- 🚀 FastAPI Integration - Pre-built API router for instant REST endpoints
Installation
Requires Python 3.10+
pip install chatvault
Quick Start
from chatvault import ChatVault
from chatvault.backends import MemoryMessages, LocalFiles
# Create vault with built-in backends (great for development)
vault = ChatVault(
messages=MemoryMessages(),
files=LocalFiles(base_path="./uploads")
)
# Create a conversation
conversation = vault.create_conversation(user_id="user-123")
# Add messages
conversation.add_message("user", "Hello!")
conversation.add_message("assistant", "Hi there! How can I help you?")
# Attach a file
with open("document.pdf", "rb") as f:
conversation.attach_file("document.pdf", f.read(), content_type="application/pdf")
# Resume later
conversation = vault.get_conversation(conversation.conversation_id)
FastAPI Integration
ChatVault includes a pre-built FastAPI router for instant REST API:
from fastapi import FastAPI
from chatvault import ChatVault
from chatvault.api import create_router
from chatvault.backends import MemoryMessages, LocalFiles
app = FastAPI()
vault = ChatVault(
messages=MemoryMessages(),
files=LocalFiles(base_path="./uploads")
)
# Add all conversation endpoints under /api
app.include_router(create_router(vault), prefix="/api")
This gives you these endpoints out of the box:
POST /api/conversations- Create conversationGET /api/conversations- List conversationsGET /api/conversations/{id}- Get conversationPATCH /api/conversations/{id}- Rename conversationDELETE /api/conversations/{id}- Delete conversationPOST /api/conversations/{id}/messages- Add messagePOST /api/conversations/{id}/files- Upload fileGET /api/conversations/{id}/files/{filename}- Download file
API Reference
ChatVault
| Method | Description |
|---|---|
create_conversation(user_id=None) |
Create a new conversation |
get_conversation(conversation_id) |
Load an existing conversation |
get_conversations(user_id) |
List all conversations for a user |
delete_conversation(conversation_id) |
Delete a conversation |
Conversation
| Method | Description |
|---|---|
add_message(role, content) |
Add a message to the conversation |
get_messages() |
Get all messages |
attach_file(filename, data, content_type) |
Attach a file |
get_file(filename) |
Get file content |
list_files() |
List all attached files |
Built-in Backends
| Backend | Description |
|---|---|
MemoryMessages |
In-memory storage (for development/testing) |
LocalFiles |
Local filesystem storage |
Custom Backends
ChatVault works with any storage provider. Implement these abstract base classes:
MessagesBackend- For conversation persistence (save, get, get_by_user, delete)FilesBackend- For file storage (upload, download, delete, exists, get_signed_url)
Example: AWS S3 + DynamoDB
import boto3
from chatvault.backends import FilesBackend
class S3Files(FilesBackend):
def __init__(self, bucket: str, region_name: str = None):
self.bucket = bucket
self.s3 = boto3.client("s3", region_name=region_name)
def upload(self, key: str, data: bytes, content_type: str = "application/octet-stream") -> None:
self.s3.put_object(Bucket=self.bucket, Key=key, Body=data, ContentType=content_type)
def download(self, key: str):
response = self.s3.get_object(Bucket=self.bucket, Key=key)
return response["Body"].read()
def delete(self, key: str) -> bool:
self.s3.delete_object(Bucket=self.bucket, Key=key)
return True
def exists(self, key: str) -> bool:
try:
self.s3.head_object(Bucket=self.bucket, Key=key)
return True
except:
return False
def get_signed_url(self, key: str, expires_in: int = 3600, download_filename: str = None):
return self.s3.generate_presigned_url("get_object", Params={"Bucket": self.bucket, "Key": key}, ExpiresIn=expires_in)
import json
from datetime import datetime
import boto3
from chatvault.backends import MessagesBackend
from chatvault.conversation import Conversation, Message, FileAttachment
class DynamoMessages(MessagesBackend):
def __init__(self, table_name: str, region_name: str = None):
self.table = boto3.resource("dynamodb", region_name=region_name).Table(table_name)
def save(self, conversation) -> None:
self.table.put_item(Item={
"conversation_id": conversation.conversation_id,
"user_id": conversation.user_id or "",
"title": conversation.title,
"messages": json.dumps([m.to_dict() for m in conversation._messages]),
"files": json.dumps([f.to_dict() for f in conversation._files]),
"created_at": int(conversation.created_at.timestamp()),
"last_active": int(conversation.last_active.timestamp()),
})
def get(self, conversation_id: str):
response = self.table.get_item(Key={"conversation_id": conversation_id})
item = response.get("Item")
if not item:
return None
return Conversation(
conversation_id=item["conversation_id"],
user_id=item.get("user_id") or None,
title=item.get("title", ""),
created_at=datetime.fromtimestamp(int(item.get("created_at", 0))),
messages=[Message.from_dict(m) for m in json.loads(item.get("messages", "[]"))],
files=[FileAttachment.from_dict(f) for f in json.loads(item.get("files", "[]"))],
)
def get_by_user(self, user_id: str):
response = self.table.query(
IndexName="user_id-index",
KeyConditionExpression="user_id = :uid",
ExpressionAttributeValues={":uid": user_id}
)
return [self.get(item["conversation_id"]) for item in response.get("Items", [])]
def delete(self, conversation_id: str) -> bool:
self.table.delete_item(Key={"conversation_id": conversation_id})
return True
Usage:
vault = ChatVault(
messages=DynamoMessages(table_name="Conversations", region_name="us-east-1"),
files=S3Files(bucket="my-chat-files", region_name="us-east-1")
)
Development
# Clone and install
git clone https://github.com/enfeizhan/chatvault.git
cd chatvault
uv venv .venv && source .venv/bin/activate
uv pip install -e ".[dev]"
# Run tests
pytest -v
License
MIT License - see LICENSE for details.
Release files for chatvault 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| chatvault-0.1.0.tar.gz | 70.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| chatvault-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 87.2 kB
Release files / chatvault-0.1.0.tar.gz
| Download URL | chatvault-0.1.0.tar.gz |
|---|---|
| Size | 70.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
8f7b87c70dcd348d4f599ec1d8cd936cbee296940488eb5121c6eb3897dd823f
|
|
BLAKE2b-256 checksum How to use checksums |
5bcae85b7d829865ca1b3ca68ad4877dda11775c36f9a7bb01b55e56e9d187ec
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
Hatch/1.16.2 cpython/3.13.5 HTTPX/0.28.1
|
Release files / chatvault-0.1.0-py3-none-any.whl
| Download URL | chatvault-0.1.0-py3-none-any.whl |
|---|---|
| Size | 16.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6715a370aca209a2cedd34d0aa1cd7bebe882cc7cd72fe2ddf94f5ede05681db
|
|
BLAKE2b-256 checksum How to use checksums |
1d790b3dcbf690723f2e78fae6f9bfdecbedaa32d8672e55122a68d0ec7e1fde
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
Hatch/1.16.2 cpython/3.13.5 HTTPX/0.28.1
|