LLM chat app framework - Minimally complete. Maximally hackable
Project description
🗯️ Chatnificent
LLM chat app framework
Minimally complete. Maximally hackable.
Build production-ready, full-stack chat applications in minutes. Customize everything in hours.
Chatnificent is a Python framework built on Plotly's Dash designed to get your LLM chat applications up and running instantly, while providing a robust, decoupled architecture for unlimited customization.
Stop wrestling with UI components, state management, and backend integrations. Start building magnificent chat apps.
The Ethos
Frameworks should get out of your way.
- Minimally Complete: Out of the box,
Chatnificentprovides a fully functional, stateful, multi-user chat application with sensible defaults. - Maximally Hackable: Every core pillar—the UI, the LLM provider, the database, the authentication, the RAG pipeline, and the core orchestration—is swappable. Customize or replace any part without fighting the framework.
Features
- LLM Agnostic: Built-in support for OpenAI, Anthropic, Gemini, Ollama, OpenRouter, DeepSeek, and any other LLM API.
- Flexible UI: Default Bootstrap layout, with built-in Mantine and Minimal (pure HTML) layouts. Easily customizable with any Dash components.
- Pluggable Storage: InMemory, File-system, and SQLite included. Easily extendable to Redis, Postgres, etc.
- Agentic Engine: The core engine manages multi-turn conversations and standardized tool calling across providers.
- Auth Ready: Abstracted authentication layer for easy integration. No-login anonymous user auth enabled by default.
- RTL Support: Automatic detection and rendering of Right-to-Left languages.
- Dash Native: Leverage the full power of Plotly's Dash to integrate complex data visualizations and analytics.
Installation
To get started quickly with the default UI (Bootstrap) and the default LLM provider (OpenAI):
pip install "chatnificent[default]"
export OPENAI_API_KEY="YOUR_API_KEY"
For a minimal installation (no UI libraries or LLM SDKs included):
pip install chatnificent
Quickstart: Hello World (3 Lines)
This is a complete, working chat application.
Create a file app.py:
from chatnificent import Chatnificent
app = Chatnificent()
if __name__ == "__main__":
app.run(debug=True)
Run it:
python app.py
Open your browser to http://127.0.0.1:8050. That's it. You have a fully functional chat UI with conversation history, mobile responsiveness, and URL-based session management.
The Pillars of Hackability
Chatnificent's architecture is built around extensible Pillars. Every major function is handled by a dedicated component adhering to a strict interface.
| Pillar | Description | Defaults | Included Implementations |
|---|---|---|---|
LLM |
The brain (API calls, parsing). | OpenAI (or Echo) |
OpenAI, Anthropic, Gemini, OpenRouter, DeepSeek, Ollama, Echo |
Layout |
The look and feel (UI components). | Bootstrap (or Minimal) |
Bootstrap, Mantine, Minimal (HTML) |
Store |
The memory (Persistence). | InMemory |
InMemory, File, SQLite |
Auth |
The gatekeeper (User identification). | Anonymous |
Anonymous, SingleUser |
Engine |
The orchestrator (Request lifecycle). | Synchronous |
Synchronous |
Tools |
Tool/function calling capabilities. | NoTool |
PythonTool, NoTool |
Retrieval |
RAG knowledge retrieval. | NoRetrieval |
NoRetrieval |
URL |
URL parsing and routing. | PathBased |
PathBased, QueryParams |
You customize the app by injecting the implementations you need during initialization:
from chatnificent import Chatnificent
import chatnificent as chat
app = Chatnificent(
llm=chat.llm.Anthropic(),
store=chat.store.SQLite(db_path="conversations.db"),
layout=chat.layout.Mantine()
)
Progressive Power: Swapping the Pillars
Let's evolve the "Hello World" example by swapping pillars.
Level 1: Swapping the LLM 🧠
Want to use Anthropic's Claude 3.5 Sonnet? Just swap the llm pillar.
(Requires pip install anthropic and setting ANTHROPIC_API_KEY)
from chatnificent import Chatnificent
import chatnificent as chat
app = Chatnificent(
llm=chat.llm.Anthropic(model="claude-3-5-sonnet-20240620")
)
# Or try Gemini: app = Chatnificent(llm=chat.llm.Gemini())
# Or local Ollama: app = Chatnificent(llm=chat.llm.Ollama(model="llama3.1"))
Chatnificent handles the translation of message formats and tool-calling protocols automatically.
Level 2: Adding Persistent Storage
The default InMemory store is ephemeral. Let's use SQLite for persistence.
from chatnificent import Chatnificent
import chatnificent as chat
app = Chatnificent(
store=store.SQLite(db_path="conversations.db")
)
# Or use the filesystem: store=chat.store.File(base_dir="./chat_data")
Conversations are now persisted across server restarts, and the sidebar automatically loads your history.
Level 3: Changing the Look and Feel 🎨
Don't want Bootstrap? Let's try the Mantine layout.
(Requires pip install dash-mantine-components)
from chatnificent import Chatnificent
import chatnificent as chat
app = Chatnificent(layout=chat.layout.Mantine())
# Or use the barebones HTML layout: layout=layout.Minimal()
Want a completely custom design? Implement the layout.Layout abstract base class. The framework ensures your custom layout integrates seamlessly, provided you include the required component IDs (e.g., input_textarea, messages_container, etc.).
Level 4: Custom Authentication
The default Anonymous auth isolates users by random user ID. You can easily implement custom logic.
from chatnificent import Chatnificent, auth
class HeaderAuth(auth.Auth):
def get_current_user_id(self, **kwargs) -> str:
from flask import request
# Identify user based on a header (e.g., provided by an auth proxy)
return request.headers.get("X-User-Id", "unknown_user")
app = Chatnificent(auth=HeaderAuth())
Level 5: The Engine (Advanced Orchestration)
The Engine orchestrates the entire request lifecycle: resolving the conversation, RAG retrieval, the agentic loop (Tools + LLM calls), and persistence.
The default Synchronous engine provides "hooks" (empty methods called at specific points) and "seams" (core logic methods) that you can override to deeply customize behavior without rewriting the core logic.
from chatnificent import Chatnificent
import chatnificent as chat
from typing import Any, Optional
# Create a custom engine by inheriting from the default
class CustomEngine(chat.engine.Synchronous):
# 1. Override a HOOK to add monitoring/logging
def _after_llm_call(self, llm_response: Any) -> None:
# Example: Extract token usage if the LLM response object has a 'usage' attribute
tokens = getattr(llm_response, 'usage', 'N/A')
print(f"[MONITORING] LLM call complete. Tokens: {tokens}")
# 2. Override a SEAM to modify core logic (e.g., prompt engineering)
def _prepare_llm_payload(self, conversation, retrieval_context: Optional[str]):
# Get the default payload (which already includes the context if present)
payload = super()._prepare_llm_payload(conversation, retrieval_context)
# Inject a custom system prompt if none exists
if not any(m['role'] == 'system' for m in payload):
payload.insert(0, {"role": "system", "content": "Be brief and professional."})
return payload
# Initialize the app, passing the engine instance.
# Chatnificent's constructor will automatically bind the app reference to the engine.
app = Chatnificent(engine=CustomEngine())
Architecture Overview
How the pillars work together during a request:
- User Input: The user submits a message via the
Layout. - Callback Trigger: A Dash callback delegates the input to the
Engine. - Context Resolution: The
EngineusesAuth,URL, andStoreto identify the user and load the conversation history. - Agentic Loop:
- The
EnginecallsRetrievalto gather context (RAG). - The
Enginesends the history and context to theLLM. - If the
LLMrequests a tool call, theEngineexecutes it viaToolsand loops back. - If the
LLMreturns a final response, the loop exits.
- The
- Persistence: The
Enginesaves the updated conversation via theStore. - Rendering: The
Engineformats the messages using theLayoutand updates the client UI.
Building Your Own Pillars
The ultimate hackability comes from implementing your own pillars. Want to use MongoDB? Just implement the store.Store interface.
Example: Custom Storage Implementation
from chatnificent import Chatnificent
import chatnificent as chat
from typing import Optional, List
class MongoDBStore(chat.store.Store):
def __init__(self, connection_string):
# Initialize MongoDB client...
print(f"Connecting to MongoDB at {connection_string}...")
pass
def load_conversation(self, user_id: str, convo_id: str) -> Optional[Conversation]:
# Implement loading logic...
return None
# Implement the other required methods...
def save_conversation(self, user_id: str, conversation: Conversation):
pass
def list_conversations(self, user_id: str) -> List[str]:
return []
def get_next_conversation_id(self, user_id: str) -> str:
return "1"
# Use your custom implementation
# app = Chatnificent(store=MongoDBStore(connection_string="mongodb://..."))
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 Distribution
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 chatnificent-0.0.12.tar.gz.
File metadata
- Download URL: chatnificent-0.0.12.tar.gz
- Upload date:
- Size: 32.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.26 {"installer":{"name":"uv","version":"0.9.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1d46a0aae0786828d247523abd2a6ccb4201b2ae06cd3a7f280b1f5293297525
|
|
| MD5 |
8ef5ab2d48733db487eae8f414d767fd
|
|
| BLAKE2b-256 |
4f3fccbd628d809670e5cfbfafa4ed9e25ebeede9fbeee0014d0ff73a7512ab9
|
File details
Details for the file chatnificent-0.0.12-py3-none-any.whl.
File metadata
- Download URL: chatnificent-0.0.12-py3-none-any.whl
- Upload date:
- Size: 36.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.26 {"installer":{"name":"uv","version":"0.9.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dfa4d804399b0999168f533a66e24c4629de72baaa9e7da59765821db8334b60
|
|
| MD5 |
952430cdcd0d2a87bc7bd3378cbe46cc
|
|
| BLAKE2b-256 |
8f88f94356c20864d56345b1d8ebd499da01fff6bf727a23564920fd0682ab79
|