ai_qc/backend/headless_example.py
nickviljoen 3fec052c12 Create frontend and backend folder structure for deployment
Organized the application into separate frontend and backend directories for cleaner deployment and better separation of concerns.

Frontend Directory (frontend/):
- index.html: Single-page web interface (renamed from web_ui.html)
- README.md: Frontend deployment guide
- Total size: ~113 KB (self-contained)
- Smart base path detection (works at / or /ai_qc/)
- No configuration changes required

Backend Directory (backend/):
- All Python files (api_server.py, llm_config.py, etc.)
- visual_qc_apps/: 33 QC check modules
- profiles/: 6 QC profile configurations
- brand_guidelines/: Reference asset storage
- config/: Environment configurations
- scripts/: Deployment automation
- uploads/, output/: Data directories
- requirements.txt, ai_qc.service, apache_config.conf
- Complete documentation

New Documentation:
- FOLDER_STRUCTURE.md: Comprehensive guide to new structure
- frontend/README.md: Frontend deployment instructions
- backend/BACKEND_README.md: Backend deployment guide

Deployment Mapping:
- frontend/ → /var/www/html/ai_qc/ (web root)
- backend/ → /opt/ai_qc/ (application directory)

Benefits:
- Clear separation of concerns
- Backend code not in web-accessible directory
- Independent frontend/backend updates
- Matches server's existing patterns (/opt/veo3, /opt/voice2text)
- Industry-standard architecture
- Easy to deploy and maintain

Original files preserved in root directory for reference.
Ready for production deployment following MIGRATION_GUIDE.md.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-06 11:55:53 +02:00

170 lines
No EOL
6 KiB
Python

#!/usr/bin/env python3
"""
Example: Visual AI QC Headless Operation
Demonstrates how to use the API without the web interface
"""
import requests
import time
import json
# Configuration
API_BASE = "http://localhost:7183"
IMAGE_PATH = "path/to/your/image.jpg"
def headless_analysis_example():
"""Complete example of headless Visual AI QC analysis"""
print("🤖 Visual AI QC - Headless Analysis Example")
print("=" * 50)
# 1. Get available profiles
print("\n📋 Step 1: Getting available profiles...")
response = requests.get(f"{API_BASE}/api/profiles")
if response.status_code == 200:
profiles = response.json()
print(f"✅ Found {len(profiles)} profile categories")
for category, profile_list in profiles.items():
print(f" {category}: {len(profile_list)} profiles")
else:
print(f"❌ Error getting profiles: {response.status_code}")
return
# 2. Get available reference assets
print("\n📁 Step 2: Getting reference assets...")
response = requests.get(f"{API_BASE}/api/brand_guidelines")
if response.status_code == 200:
guidelines = response.json()
print(f"✅ Found {len(guidelines.get('files', {}))} reference assets")
for file_id, file_info in guidelines.get('files', {}).items():
print(f" {file_info['brand_name']}: {file_info['original_filename']}")
# 3. Start analysis with async tracking
print(f"\n🔍 Step 3: Starting analysis...")
with open(IMAGE_PATH, 'rb') as f:
files = {'file': f}
data = {
'profile': 'diageo_key_visual', # Use Diageo profile
'mode': 'json', # JSON output
'reference_asset': 'Hellmanns_20250805_113413' # Use reference asset
}
response = requests.post(f"{API_BASE}/api/start_analysis", files=files, data=data)
if response.status_code != 200:
print(f"❌ Error starting analysis: {response.status_code}")
return
result = response.json()
session_id = result.get('session_id')
if not session_id:
print("❌ No session ID returned")
return
print(f"✅ Analysis started with session ID: {session_id}")
# 4. Poll for progress
print("\n⏳ Step 4: Monitoring progress...")
while True:
response = requests.get(f"{API_BASE}/api/progress/{session_id}")
if response.status_code != 200:
print(f"❌ Error getting progress: {response.status_code}")
break
progress_data = response.json()
progress = progress_data.get('progress', {})
if progress.get('stage') == 'complete':
print("✅ Analysis complete!")
results = progress.get('result', {})
break
else:
current_step = progress.get('current_check_display', 'Processing...')
percentage = progress.get('percentage', 0)
completed = progress.get('completed_checks', 0)
total = progress.get('total_checks', 0)
print(f" Progress: {percentage}% - {current_step} ({completed}/{total})")
time.sleep(2)
# 5. Display results
print("\n📊 Step 5: Analysis Results")
print("-" * 30)
summary = results.get('summary', {})
print(f"Overall Score: {summary.get('overall_score', 0)}/100")
print(f"Grade: {summary.get('grade', 'Unknown')}")
print(f"Checks Performed: {summary.get('checks_count', 0)}")
# Show individual check results
qc_results = results.get('qc_analysis', {}).get('check_results', {})
print(f"\n🔍 Individual Check Results:")
for check_name, check_result in qc_results.items():
if check_result.get('status') == 'completed':
score = check_result.get('score', 0)
print(f" {check_name}: {score}/10")
# 6. Get output files
print("\n📄 Step 6: Generated Files")
response = requests.get(f"{API_BASE}/api/output_files")
if response.status_code == 200:
files = response.json()
print(f"{len(files)} output files available")
for file_info in files[:3]: # Show latest 3
print(f" {file_info['filename']} ({file_info['size']})")
print("\n🎉 Headless analysis complete!")
def simple_analysis_example():
"""Simplified headless analysis"""
print("\n🚀 Simple Headless Analysis")
print("-" * 30)
with open(IMAGE_PATH, 'rb') as f:
files = {'file': f}
data = {
'profile': 'general_key_visual',
'mode': 'json'
}
# Direct analysis (may take longer but simpler)
response = requests.post(f"{API_BASE}/api/analyze", files=files, data=data)
if response.status_code == 200:
results = response.json()
summary = results.get('summary', {})
print(f"✅ Score: {summary.get('overall_score', 0)}/100")
print(f" Grade: {summary.get('grade', 'Unknown')}")
else:
print(f"❌ Analysis failed: {response.status_code}")
def brand_detection_example():
"""Example of headless brand detection"""
print("\n🏷️ Brand Detection Example")
print("-" * 30)
with open(IMAGE_PATH, 'rb') as f:
files = {'file': f}
response = requests.post(f"{API_BASE}/api/detect_brand", files=files)
if response.status_code == 200:
result = response.json()
print(f"✅ Detected Brand: {result.get('brand', 'Unknown')}")
print(f" Confidence: {result.get('confidence', 0)}")
else:
print(f"❌ Brand detection failed: {response.status_code}")
if __name__ == "__main__":
# Run examples (update IMAGE_PATH first!)
try:
headless_analysis_example()
simple_analysis_example()
brand_detection_example()
except FileNotFoundError:
print("❌ Please update IMAGE_PATH with a valid image file path")
except requests.exceptions.ConnectionError:
print("❌ Cannot connect to API server. Make sure it's running on localhost:7183")