Implements three major feature enhancements: 1. Usage Tracking Reports - Command-line tool (generate_usage_report.py) for comprehensive usage reports - Supports text, JSON, and CSV output formats - Filters by date range, client, and user - Aggregates statistics by client, user, profile, and date - Automated report generation via cron jobs 2. Profile Auto-Versioning & Visibility Control - Automatic version control: edits create new versions (v2, v3, etc.) - Original profiles preserved for rollback capability - Profile visibility control (all clients vs client-specific) - Client-profile relationship management with dynamic updates - Audit trail with timestamps and user tracking 3. Actual Token Usage Tracking - Captures real token counts from OpenAI and Gemini APIs - Precise cost calculations instead of estimates (99% accuracy) - Per-check and per-provider token breakdowns - Pricing validation tool (validate_pricing.py) - Token usage optimization recommendations Key Files Added: - backend/generate_usage_report.py - Usage report generator - backend/validate_pricing.py - Pricing validation tool - backend/USAGE_REPORTS.md - Usage reports documentation - backend/PROFILE_MANAGEMENT.md - Profile versioning guide - backend/TOKEN_TRACKING_ENHANCEMENT.md - Token tracking guide - backend/PRICING_GUIDE.md - Pricing validation guide - backend/NEW_FEATURES_QUICKSTART.md - Quick start guide - IMPLEMENTATION_SUMMARY.md - Complete implementation overview Key Files Modified: - backend/api_server.py - Profile versioning, token passthrough - backend/client_config.py - Visibility-aware profile filtering - backend/llm_config.py - Token usage extraction from APIs - backend/usage_tracker.py - Actual token tracking and cost calculation - CLAUDE.md - Updated documentation with new features Benefits: - Accurate cost tracking with real token usage - Safe profile editing with version history - Flexible profile visibility for multi-tenant setup - Comprehensive usage analytics for optimization - Better budget forecasting and client billing Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
11 KiB
Profile Management Guide
This guide explains the profile versioning and visibility features in the AI QC system.
Features Overview
1. Automatic Profile Versioning
When you edit an existing profile, the system automatically:
- Creates a new version (v2, v3, etc.)
- Keeps the original profile unchanged
- Updates all client configurations to use the new version
2. Profile Visibility Control
When creating or editing profiles, you can control visibility:
- All Clients: Profile visible to all clients
- Client-Specific: Profile visible only to selected clients
Profile Versioning
How It Works
- Original Profile:
my_profile.json(version 1) - First Edit: Creates
my_profile_v2.json(version 2) - Second Edit: Creates
my_profile_v3.json(version 3) - And so on...
Benefits
- ✅ Safety: Original profiles never modified
- ✅ History: Complete version history preserved
- ✅ Rollback: Easy to revert to previous versions
- ✅ Audit Trail: Track who made changes and when
- ✅ Testing: Test new versions without affecting production
Version Metadata
Each profile version includes:
{
"name": "My Profile",
"description": "Profile description",
"version": 2,
"created_at": "2026-02-02T10:00:00",
"created_by": "user@company.com",
"modified_at": "2026-02-02T15:30:00",
"modified_by": "admin@company.com",
"previous_version": "my_profile",
"visibility": "all",
"visible_to_clients": [],
"checks": { ... }
}
Using Version History
View All Versions
# List all versions of a profile
ls -lh backend/profiles/my_profile*.json
# Example output:
# my_profile.json (original)
# my_profile_v2.json (first edit)
# my_profile_v3.json (second edit)
Compare Versions
# Compare original with v2
diff backend/profiles/my_profile.json backend/profiles/my_profile_v2.json
# View detailed changes
git diff --no-index backend/profiles/my_profile.json backend/profiles/my_profile_v2.json
Rollback to Previous Version
To rollback to a previous version, simply make it the "current" version by updating client configs:
- Identify the version you want to use (e.g.,
my_profile_v2.json) - Edit
backend/client_config.pyto reference that version - Restart the application
Or use the API to "edit" the old version, which will create a new latest version with the old settings.
API Endpoints
Create Profile (POST /api/profiles)
curl -X POST http://localhost:7183/api/profiles \
-H "Content-Type: application/json" \
-H "Cookie: auth_token=YOUR_TOKEN" \
-d '{
"name": "My Custom Profile",
"description": "Profile for specific checks",
"visibility": "all",
"visible_to_clients": [],
"pass_threshold": 85,
"checks": {
"text_readability_general": {
"enabled": true,
"weight": 1.0,
"llm": "Gemini"
}
}
}'
Response:
{
"status": "success",
"message": "Profile \"My Custom Profile\" created successfully",
"profile_id": "my_custom_profile",
"profile_path": "profiles/my_custom_profile.json",
"visibility": "all"
}
Update Profile (PUT /api/profiles/<profile_id>)
This automatically creates a new version:
curl -X PUT http://localhost:7183/api/profiles/my_custom_profile \
-H "Content-Type: application/json" \
-H "Cookie: auth_token=YOUR_TOKEN" \
-d '{
"name": "My Custom Profile - Updated",
"description": "Updated profile description",
"visibility": "client_specific",
"visible_to_clients": ["diageo", "unilever"],
"checks": {
"text_readability_general": {
"enabled": true,
"weight": 1.0,
"llm": "Gemini"
},
"logo_visibility_general": {
"enabled": true,
"weight": 1.0,
"llm": "OpenAI"
}
}
}'
Response:
{
"status": "success",
"message": "Profile updated to version 2. Original kept as \"my_custom_profile\"",
"profile_id": "my_custom_profile_v2",
"previous_profile_id": "my_custom_profile",
"version": 2
}
Profile Visibility Control
Visibility Options
1. All Clients (Default)
Profile visible to all clients in the system.
{
"visibility": "all",
"visible_to_clients": []
}
Use cases:
- General-purpose profiles
- Standard QC checks applicable to all brands
- Company-wide quality standards
2. Client-Specific
Profile visible only to selected clients.
{
"visibility": "client_specific",
"visible_to_clients": ["diageo", "unilever"]
}
Use cases:
- Brand-specific profiles
- Custom checks for specific clients
- Confidential QC criteria
Client IDs
Available client IDs in the system:
diageo- Diageo brand profilesunilever- Unilever brand profilesloreal- L'Oreal brand profilesgeneral- General / Other clients
How Visibility Works
- Profile Creation: Set visibility during creation
- Client Filtering: When users select a client, they only see profiles visible to that client
- Automatic Config Updates: System automatically updates
client_config.pybased on visibility settings - Dynamic Loading: Profiles are loaded dynamically based on client context
Examples
Example 1: Create Global Profile
{
"name": "Universal Accessibility Check",
"description": "Accessibility checks for all clients",
"visibility": "all",
"visible_to_clients": [],
"checks": {
"accessibility": { "enabled": true, "weight": 1.0, "llm": "Gemini" },
"inclusive": { "enabled": true, "weight": 1.0, "llm": "Gemini" }
}
}
Result: Visible to all clients (diageo, unilever, loreal, general)
Example 2: Create Client-Specific Profile
{
"name": "Diageo Premium Brand Check",
"description": "Premium brand guidelines for Diageo only",
"visibility": "client_specific",
"visible_to_clients": ["diageo"],
"checks": {
"logo_visibility_general": { "enabled": true, "weight": 1.5, "llm": "OpenAI" },
"product_visibility_general": { "enabled": true, "weight": 1.5, "llm": "OpenAI" },
"visual_hierarchy_general": { "enabled": true, "weight": 1.0, "llm": "Gemini" }
}
}
Result: Only visible when "Diageo" client is selected
Example 3: Multi-Client Profile
{
"name": "Luxury Brand Standards",
"description": "Premium quality checks for luxury brands",
"visibility": "client_specific",
"visible_to_clients": ["diageo", "loreal"],
"checks": {
"visual_hierarchy_general": { "enabled": true, "weight": 1.0, "llm": "OpenAI" },
"element_alignment": { "enabled": true, "weight": 1.0, "llm": "Gemini" },
"product_visibility_general": { "enabled": true, "weight": 1.5, "llm": "OpenAI" }
}
}
Result: Visible to both Diageo and L'Oreal clients
Web UI Integration
Creating Profiles in Web UI
When creating a profile through the web interface, you'll see:
-
Profile Name: Enter profile name
-
Description: Describe the profile purpose
-
Reveal to All Clients: Checkbox
- ☑️ Checked: Profile visible to all clients
- ☐ Unchecked: Show client selector
-
Client Selector (if not revealed to all):
- Select specific clients that can use this profile
- Multiple clients can be selected
Editing Profiles in Web UI
When editing a profile:
- System automatically creates new version
- Original profile remains unchanged
- Success message shows: "Profile updated to version 2. Original kept as 'profile_name'"
- New version becomes active in all client configurations
Profile List View
Profiles in the list show:
- Profile name
- Version number (if versioned)
- Visibility status:
- 🌍 "All Clients" - Global visibility
- 🔒 "Specific Clients" - Limited visibility
- Client names listed for limited visibility
Best Practices
Profile Naming
- ✅ Good:
diageo_premium_2026,unilever_sustainability_check - ❌ Avoid:
test123,my_profile,new_new_final_v2
When to Use Versioning
- ✅ Changing check weights
- ✅ Modifying enabled checks
- ✅ Updating pass thresholds
- ✅ Changing profile descriptions
- ❌ Fixing typos (minor edits can be done manually if needed)
When to Use Client-Specific Visibility
- ✅ Brand-specific QC criteria
- ✅ Confidential checks
- ✅ Client-requested custom profiles
- ✅ Experimental profiles for specific clients
- ❌ General-purpose checks
- ❌ Standard quality criteria
Version Cleanup
Over time, you may accumulate many versions. Consider:
- Keep Recent Versions: Keep last 3-5 versions
- Archive Old Versions: Move to
profiles/archive/folder - Document Major Versions: Add version notes in description
# Archive old versions (example)
mkdir -p backend/profiles/archive
mv backend/profiles/my_profile_v[1-3].json backend/profiles/archive/
Troubleshooting
Profile Not Appearing in Client Dropdown
Check:
- Profile
visibilitysetting in JSON file - Client ID in
visible_to_clientsarray client_config.pyhas been updated correctly- Browser cache (refresh page with Ctrl+F5)
Version Number Not Incrementing
Check:
- Profile was actually modified (not just re-saved)
- No errors in browser console
- Server logs for any errors
Client Config Not Updating
Check:
- Write permissions on
client_config.py - Server logs for update errors
- Manual review of
client_config.pyfile
Migration Guide
Migrating Existing Profiles
Existing profiles without version/visibility fields will:
- Default to version 1
- Default to visibility "all"
- Continue working without changes
To add versioning to existing profiles:
# Add metadata to existing profile
python -c "
import json
profile_path = 'backend/profiles/my_profile.json'
with open(profile_path, 'r') as f:
profile = json.load(f)
profile['version'] = 1
profile['visibility'] = 'all'
profile['visible_to_clients'] = []
profile['created_at'] = '2026-02-02T10:00:00'
profile['created_by'] = 'system'
with open(profile_path, 'w') as f:
json.dump(profile, f, indent=2)
"
API Reference
Profile Schema
interface Profile {
name: string; // Display name
description: string; // Profile description
version: number; // Version number (1, 2, 3, ...)
visibility: "all" | "client_specific"; // Visibility mode
visible_to_clients: string[]; // Client IDs (if client_specific)
created_at: string; // ISO datetime
created_by: string; // User email
modified_at?: string; // ISO datetime (if edited)
modified_by?: string; // User email (if edited)
previous_version?: string; // Previous version profile_id
pass_threshold: number; // Pass/fail threshold (0-100)
weight_scale?: number; // Optional weight scale
checks: {
[check_name: string]: {
enabled: boolean;
weight: number;
llm: "OpenAI" | "Gemini";
description?: string;
}
}
}
Error Responses
{
"status": "error",
"message": "Profile not found"
}
{
"status": "error",
"message": "Profile already exists"
}
{
"status": "error",
"message": "No changes detected"
}
Support
For questions or issues:
- Check profile JSON files in
backend/profiles/ - Review
backend/client_config.pyfor client assignments - Check server logs for errors
- Contact the development team