QV Session Manager
A simple, efficient session manager for persistent storage and management of conversations from qv-ollama-sdk in an SQLite database.
✨ Features
- 💾 Persistent storage of conversations and messages in SQLite
- 🔍 Full-text search in conversation contents and titles
- ⏰ Time-based search by creation/update date
- 🔄 Conversation resumption at any point
- 📋 Conversation management (list, delete, load)
- 🎯 Minimal dependencies (only Python stdlib + qv-ollama-sdk)
- 🚀 Simple API with clear, intuitive methods
🛠️ Installation
From PyPI
pip install qv-session-manager
or
uv add qv-session-manager
Development installation
git clone https://github.com/quantyverse/qv-session-manager.git
cd qv-session-manager
pip install -e .
Dependencies
- Python 3.10+
- qv-ollama-sdk
🚀 Quickstart
from qv_session_manager import SessionManager
from qv_ollama_sdk.domain.models import Conversation
# Initialize SessionManager
mgr = SessionManager(db_path="my_sessions.db")
# Create new conversation
conv = Conversation(title="Python Help", model_name="llama3")
conv.add_user_message("Explain Python lists to me!")
conv.add_assistant_message("Lists are ordered, mutable collections...")
# Save
mgr.save_conversation(conv, conv.messages)
# Load
loaded = mgr.load_conversation(str(conv.id))
print(f"Loaded: {loaded.title} with {len(loaded.messages)} messages")
# Search
results = mgr.search_conversations("lists")
print(f"Found: {len(results)} conversations")
📚 API Documentation
SessionManager
Initialization
SessionManager(db_path: str = "session_manager.db")
db_path: Path to the SQLite database file
Methods
save_conversation(conversation, messages)
Saves a conversation and its messages.
conversation: Conversation object (withto_db_dict()method)messages: List of Message objects (withto_db_dict()methods)
mgr.save_conversation(conv, conv.messages)
load_conversation(conversation_id: str) -> Conversation | None
Loads a conversation with all messages.
conversation_id: UUID of the conversation as a string- Returns: Conversation object or None
conv = mgr.load_conversation("550e8400-e29b-41d4-a716-446655440000")
list_conversations() -> List[Dict[str, Any]]
Lists all conversations (without messages).
- Returns: List of conversation dicts with metadata
all_convs = mgr.list_conversations()
for conv in all_convs:
print(f"{conv['title']} - {conv['created_at']}")
search_conversations(query: str) -> List[Dict[str, Any]]
Full-text search in titles and message contents.
query: Search term- Returns: List of found conversation dicts
results = mgr.search_conversations("Python")
search_by_time(start: str = None, end: str = None) -> List[Dict[str, Any]]
Time-based search for conversations.
start: Start date (ISO format, e.g. "2025-01-20")end: End date (ISO format)- Returns: List of conversation dicts
# Conversations from today
today = datetime.now().strftime("%Y-%m-%d")
recent = mgr.search_by_time(start=today)
# Conversations from a period
results = mgr.search_by_time(start="2025-01-01", end="2025-01-31")
resume_conversation(conversation_id: str) -> Dict[str, Any] | None
Prepares conversation resumption.
conversation_id: UUID of the conversation- Returns: Dict with
conversationandlast_message
resumed = mgr.resume_conversation(str(conv.id))
last_msg = resumed["last_message"]
print(f"Last message: {last_msg['content']}")
delete_conversation(conversation_id: str)
Deletes a conversation and all associated messages.
conversation_id: UUID of the conversation
mgr.delete_conversation(str(conv.id))
💡 Advanced Examples
Conversation management with metadata
from datetime import datetime
from qv_session_manager import SessionManager
from qv_ollama_sdk.domain.models import Conversation
mgr = SessionManager()
# Conversation with metadata
conv = Conversation(
title="JavaScript Tutorial",
model_name="llama3",
metadata={
"topic": "web-development",
"difficulty": "beginner",
"language": "javascript"
}
)
# Add messages
conv.add_system_message("You are an experienced web developer.")
conv.add_user_message("Explain closures in JavaScript.")
# Save
mgr.save_conversation(conv, conv.messages)
# Search by topic
web_convs = [c for c in mgr.list_conversations()
if c.get('metadata', {}).get('topic') == 'web-development']
Batch operations
# Delete all conversations from a specific day
target_date = "2025-01-20"
old_convs = mgr.search_by_time(start=target_date, end=target_date)
for conv in old_convs:
mgr.delete_conversation(conv['id'])
print(f"Deleted: {conv['title']}")
Conversation continuation
# Load and extend an existing conversation
conv = mgr.load_conversation("existing-conversation-id")
if conv:
# Add new messages
conv.add_user_message("Can you explain that again?")
conv.add_assistant_message("Sure! Let me rephrase that...")
# Save updated version
mgr.save_conversation(conv, conv.messages)
🧪 Development & Testing
Run tests
# All tests
pytest
# Specific test
pytest tests/test_session_manager.py
# With output
pytest -v -s
Run demo
python examples/basic_usage.py
Project structure
qv-session-manager/
├── src/qv_session_manager/
│ ├── __init__.py
│ └── session_manager.py
├── tests/
│ └── test_session_manager.py
├── examples/
│ └── basic_usage.py
├── README.md
└── pyproject.toml
🗄️ Database Schema
The SQLite database uses the following schema:
-- Conversations table
CREATE TABLE conversations (
id TEXT PRIMARY KEY, -- UUID
title TEXT, -- Conversation title
created_at TEXT, -- ISO timestamp
updated_at TEXT, -- ISO timestamp
metadata TEXT -- JSON metadata
);
-- Messages table
CREATE TABLE messages (
id TEXT PRIMARY KEY, -- UUID
conversation_id TEXT, -- Reference to conversations.id
role TEXT, -- "system", "user", "assistant"
content TEXT, -- Message content
created_at TEXT, -- ISO timestamp
metadata TEXT, -- JSON metadata
FOREIGN KEY(conversation_id) REFERENCES conversations(id) ON DELETE CASCADE
);
🤝 Integration with qv-ollama-sdk
from qv_ollama_sdk.client import OllamaClient
from qv_session_manager import SessionManager
# Initialize clients
ollama = OllamaClient()
session_mgr = SessionManager()
# New conversation
conv = ollama.create_conversation(model="gemma3:1b")
conv.title = "Code Review Session"
# Chat with Ollama
response = ollama.chat(conv, "Explain Clean Code principles to me")
print(response.content)
# Persist session
session_mgr.save_conversation(conv, conv.messages)
# Later: load and continue session
loaded_conv = session_mgr.load_conversation(str(conv.id))
next_response = ollama.chat(loaded_conv, "Which tools do you recommend?")
📋 Roadmap
- Advanced search/filter functions (e.g. by metadata)
- Optional encryption of stored data
- Export/import of conversations (JSON, CSV)
- Performance optimizations for large datasets
- Async support for high-performance applications
🐛 Error Handling
try:
conv = mgr.load_conversation("invalid-id")
if conv is None:
print("Conversation not found")
except Exception as e:
print(f"Error loading: {e}")
📄 License
MIT License - see LICENSE for details.
📞 Support
- Issues: GitHub Issues
- Documentation: This README
- Examples: See the
examples/directory
Metadata
Release files for qv-session-manager 0.3.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 | Provenance | |
|---|---|---|---|---|
| qv_session_manager-0.3.0.tar.gz | 12.0 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| qv_session_manager-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 20.3 kB
Release files / qv_session_manager-0.3.0.tar.gz
| Download URL | qv_session_manager-0.3.0.tar.gz |
|---|---|
| Size | 12.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
4cb0f90e6cc71a1dfc08c5373e7582c210caef584406edbe10f478981a10a79b
|
|
BLAKE2b-256 checksum How to use checksums |
284701913801061fb633d767ee130f454fcdd118e83ba3f97c166f6f3e61dd4b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.5.5
|
Release files / qv_session_manager-0.3.0-py3-none-any.whl
| Download URL | qv_session_manager-0.3.0-py3-none-any.whl |
|---|---|
| Size | 8.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
f17afcd973469c79149bc2e0d303f62f5fa922e1f2bd66716958c5ee7a503a23
|
|
BLAKE2b-256 checksum How to use checksums |
9eca8b0adb14c501a9fd6a85d45ffa98faf27c0199ed46bba8cf6ae86cd50208
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.5.5
|
Security for qv-session-manager 0.3.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.