Plan: Dynamic Configuration System Implementation
Date: 2026-02-21 Status: Draft / For Review Purpose: Implement a system to tune and A/B test all AI parameters (retrieval, reasoning, costs) via database-driven configuration profiles with automatic fallback to code defaults.
1. Executive Summary
This plan enables "hot-tuning" of the AI Teacher. Instead of hardcoded constants, the system will look up a configuration profile assigned to the user. If a parameter is found, it is used; otherwise, it falls back to the existing Settings in app/core/config.py. Crucially, it includes a "Self-Healing" mechanism that reverts to defaults if a custom parameter (e.g., a misspelled model name) causes an execution error.
2. Phase A: Database Schema (Supabase)
Step 1: Create Configuration Tables
We need a table to store the profiles and a way to link them to users.
Migration: 20260221000024_dynamic_config_tables.sql
-- Store configuration profiles
CREATE TABLE IF NOT EXISTS app_configurations (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name TEXT UNIQUE NOT NULL,
description TEXT,
settings JSONB NOT NULL DEFAULT '{}',
is_active BOOLEAN DEFAULT true,
created_at TIMESTAMPTZ DEFAULT now(),
updated_at TIMESTAMPTZ DEFAULT now()
);
-- Link profiles to users
ALTER TABLE profiles
ADD COLUMN IF NOT EXISTS config_id UUID REFERENCES app_configurations(id);
-- Insert a 'Default Experimental' profile for testing
INSERT INTO app_configurations (name, description, settings)
VALUES ('experimental_v1', 'Initial tuning test', '{
"retrieval_top_k": 25,
"rerank_top_n": 5,
"reasoning_model": "gpt-4o",
"temperature": 0.2
}');
3. Phase B: Config Manager Service
Step 1: Create ConfigManager
A new service to fetch, cache, and merge settings.
File: app/services/config_manager.py
* get_user_config(user_id): Fetches the merged dictionary of settings.
* Logic:
1. Get config_id from profiles.
2. If config_id is NULL, return empty dict (full fallback).
3. Load settings from app_configurations.
4. Merge with app/core/config.py as the base.
4. Phase C: Service Integration (The Fallback Pattern)
Step 1: Update RetrievalPipeline
Inject ConfigManager and use it to override top_k and rerank_n.
Step 2: Update LLM Service (Reasoning)
Implement the "Execution Failure" safety net.
Example Logic:
def generate_answer(query, context, config_params):
model = config_params.get("reasoning_model", settings.OPENAI_CHAT_MODEL)
try:
# Attempt with custom model
return call_openai(model=model, ...)
except Exception as e:
our_logs.error(f"Config parameter {model} failed: {e}. Falling back to default.")
# Automatic fallback to hardcoded default
return call_openai(model=settings.OPENAI_CHAT_MODEL, ...)
5. Phase D: Agent Integration
TeacherAgent Node Update
The check_wallet node (which runs first) will be renamed to initialize_session.
1. Verify wallet/tier (as before).
2. Fetch user configuration via ConfigManager.
3. Store the configuration dict in the TeacherState.
6. Implementation Roadmap (A-Z)
| Phase | Task | File/Action |
|---|---|---|
| A | Create SQL Migration | db/migrations/20260221000024_... |
| B | Implement ConfigManager |
app/services/config_manager.py |
| C | Add Config Fetching to Agent | app/agents/teacher_agent.py |
| D | Update Retrieval Pipeline to use Dynamic Params | app/services/retrieval_pipeline.py |
| E | Update LLM Service with "Self-Healing" Logic | app/services/llm.py |
| F | Integration Test (Assign bad config and verify fallback) | tests/test_dynamic_config.py |
7. Success Criteria
- Zero Downtime: If a bad model name is put in the DB, the system logs it and answers anyway using the default model.
- No Code Change Tuning: Changing
retrieval_top_kin the DB immediately affects the next chat message for that user. - Traceability:
usage_logsshould record whichconfig_idwas used for the request.