بنقرة واحدة
pillar-dev
Implement or extend Chatnificent pillars (LLM, Store, Engine, Auth, Tools, etc.)
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
Implement or extend Chatnificent pillars (LLM, Store, Engine, Auth, Tools, etc.)
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
Deploy the Chatnificent website (examples/showcase.py) to the Linode production server. Use when the user asks to deploy, ship, push to prod, or release the website. Runs the push-already-done → pull → reload → verify loop.
Create an example Chatnificent app to be showcased in the /examples directory.
Implement or modify a Chatnificent server (DevServer, Starlette, FastAPI, etc.)
| name | pillar-dev |
| description | Implement or extend Chatnificent pillars (LLM, Store, Engine, Auth, Tools, etc.) |
Use this skill when implementing a new pillar, extending an existing one, or working on cross-pillar integration (Engine orchestration, data models, customization).
llm.py)class LLM(ABC):
@abstractmethod
def generate_response(self, messages: List[Dict[str, Any]], **kwargs) -> Any:
"""Generate response from LLM. Returns native provider response."""
@abstractmethod
def extract_content(self, llm_response: Any) -> str:
"""Extract text content from provider response."""
# Usage
import chatnificent as chat
app = chat.Chatnificent(llm=chat.llm.Anthropic(api_key="sk-..."))
store.py)class Store(ABC):
@abstractmethod
def save_conversation(self, user_id: str, conversation: Conversation) -> None:
"""Save conversation to storage."""
@abstractmethod
def load_conversation(self, user_id: str, convo_id: str) -> Optional[Conversation]:
"""Load conversation from storage."""
# Usage
app = chat.Chatnificent(store=chat.store.SQLite(db_path="chats.db"))
server.py)class Server(ABC):
@abstractmethod
def create_server(self, **kwargs) -> None:
"""Initialize the HTTP server."""
@abstractmethod
def run(self, **kwargs) -> None:
"""Start serving requests."""
DevServer is the primary server — zero-dependency stdlib HTTP server with SSE streaming.
DashServer wraps Plotly Dash for use with Dash-based layouts (Bootstrap, Mantine, Minimal).
layout.py)class Layout(ABC):
@abstractmethod
def render(self) -> Any:
"""Render the layout. Returns HTML string (DevServer) or Dash component tree (DashServer)."""
Default renders the templates/default/ folder (template.html, styles.css, scripts.js, vendor/) — a zero-dep vanilla HTML/JS chat UI for DevServer.
Dash-based layouts (Bootstrap, Mantine, Minimal) build Dash component trees and require DashServer.
The Engine pillar manages the request lifecycle and enables complex, multi-step agentic workflows. It orchestrates the interaction between pillars and handles tool calling loops.
Retrieval (RAG context) runs once per request, before the loop — not inside it. The loop itself is bounded by Orchestrator.max_agentic_turns (default 5) to prevent runaway tool invocations.
The engine can loop multiple times to allow the LLM to use tools, process results, and form a final answer:
max_agentic_turns is reachedPillar Contracts:
handle_message() — non-streaming path, returns a complete Conversationhandle_message_stream() — streaming path, yields SSE event dicts ({"event": "delta", "data": "..."})The server routes between these based on llm.default_params.get("stream", False).
class CustomEngine(chat.engine.Orchestrator):
# Override HOOKS for monitoring
def _after_llm_call(self, llm_response: Any) -> None:
tokens = getattr(llm_response, 'usage', 'N/A')
print(f"Tokens used: {tokens}")
# Override SEAMS for custom logic
def _prepare_llm_payload(self, conversation, context: Optional[str]):
payload = super()._prepare_llm_payload(conversation, context)
payload.insert(0, {"role": "system", "content": "Be concise."})
return payload
app = chat.Chatnificent(engine=CustomEngine())
models.py)# Role constants
USER_ROLE = "user"
ASSISTANT_ROLE = "assistant"
SYSTEM_ROLE = "system"
TOOL_ROLE = "tool"
MODEL_ROLE = "model" # Gemini uses "model" instead of "assistant"
@dataclass
class Conversation:
id: str
messages: list # List[Dict[str, Any]] — provider-native dicts
def copy(self, deep: bool = False) -> "Conversation": ...
Messages are plain dicts in each provider's native format. There is no
universal message schema — an OpenAI message looks different from an Anthropic
one, and that's intentional. The LLM pillar owns the shape of its own messages
via create_assistant_message() and create_tool_result_messages().
Chatnificent stores messages in each provider's native dict format. There is no universal intermediary format — an OpenAI conversation and an Anthropic conversation look different on disk, and that's by design.
The engine never inspects message internals. It only touches the minimal universal contract:
{"role": "user", "content": text}Each LLM concrete class is responsible for:
create_assistant_message() — converting its native response into a persistable dictcreate_tool_result_messages() — formatting tool results for its own APIextract_content() — pulling display text from its native responseis_tool_message() — identifying its own tool-related messagesThe Tools pillar outputs a standard JSON Schema tool definition. Each LLM's
_translate_tool_schema() converts that into the provider's native tool format
before calling the API.
This approach:
raw_api_requests.jsonl and raw_api_responses.jsonl for auditingResearch Setup:
import chatnificent as chat
app = chat.Chatnificent(
llm=chat.llm.Anthropic(),
store=chat.store.File(directory="./research_chats"),
tools=chat.tools.PythonTool(),
)
Enterprise Setup:
app = chat.Chatnificent(
llm=chat.llm.OpenAI(),
store=chat.store.SQLite(db_path="enterprise.db"),
auth=chat.auth.SingleUser(user_id="corp_user"),
)
Local Development:
app = chat.Chatnificent(
llm=chat.llm.Ollama(model="llama3.2"),
store=chat.store.InMemory(),
tools=chat.tools.PythonTool(),
)
Dash UI with Bootstrap:
from chatnificent.server import DashServer
app = chat.Chatnificent(
server=DashServer(),
layout=chat.layout.Bootstrap(),
llm=chat.llm.Gemini(),
store=chat.store.SQLite(db_path="global.db"),
)
import json
class RedisStore(chat.store.Store):
def __init__(self, redis_url: str):
self.client = redis.from_url(redis_url)
def save_conversation(self, user_id: str, conversation: Conversation):
key = f"chat:{user_id}:{conversation.id}"
data = {"id": conversation.id, "messages": conversation.messages}
self.client.set(key, json.dumps(data))
def load_conversation(self, user_id: str, convo_id: str):
key = f"chat:{user_id}:{convo_id}"
raw = self.client.get(key)
if not raw:
return None
data = json.loads(raw)
return Conversation(id=data["id"], messages=data["messages"])
# Implement other required methods...
app = chat.Chatnificent(store=RedisStore("redis://localhost:6379"))
| Task | How |
|---|---|
| New LLM provider | Subclass llm.LLM, implement generate_response() and extract_content() |
| Custom storage | Subclass store.Store, implement save/load methods |
| UI changes (DevServer) | Edit templates/default/{template.html, styles.css, scripts.js} |
| UI changes (Dash) | Subclass layout.DashLayout |
| Request lifecycle | Subclass engine.Orchestrator, override hooks/seams |
| Tool integration | Subclass tools.Tool, handle tool call dicts -> tool result dicts |
| Different HTTP server | Subclass server.Server, implement create_server() and run() |