Enhance user profiles and improve interface output formatting
Browse files- Add detailed location and service area information to all user profiles
- Improve video script output formatting with clearer section headers
- Enable DEBUG logging by default for better development debugging
- Clean up excessive logging output from chat interface for better performance
- Maintain consistent user profile structure across all demo accounts
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- agent_system/user_store.py +28 -4
- agent_system/video_handler.py +4 -4
- app.py +1 -1
- data/users/profiles/admin@example.com.json +6 -0
- data/users/profiles/joker@example.com.json +11 -5
- data/users/profiles/poet@example.com.json +6 -0
- logging_config.py +1 -1
- ui/chat_interface.py +2 -46
agent_system/user_store.py
CHANGED
|
@@ -20,24 +20,48 @@ USER_PROFILES = {
|
|
| 20 |
"name": "Test User",
|
| 21 |
"phone": "555-1234",
|
| 22 |
"bio": "Regular test user account",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 23 |
"history": ["Previously asked about jokes"]
|
| 24 |
},
|
| 25 |
"poet@example.com": {
|
| 26 |
-
"name": "
|
| 27 |
"phone": "555-5678",
|
| 28 |
-
"bio": "
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 29 |
"history": ["Previously asked about poetry"]
|
| 30 |
},
|
| 31 |
"admin@example.com": {
|
| 32 |
"name": "Admin User",
|
| 33 |
"phone": "555-9012",
|
| 34 |
-
"bio": "System administrator",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 35 |
"history": ["Previously asked about system settings"]
|
| 36 |
},
|
| 37 |
"joe@example.com": {
|
| 38 |
"name": "Joe Demo",
|
| 39 |
"phone": "555-0123",
|
| 40 |
-
"bio": "
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 41 |
"history": ["Previously tested video generation and web search"]
|
| 42 |
}
|
| 43 |
}
|
|
|
|
| 20 |
"name": "Test User",
|
| 21 |
"phone": "555-1234",
|
| 22 |
"bio": "Regular test user account",
|
| 23 |
+
"location": {
|
| 24 |
+
"city": "Chicago",
|
| 25 |
+
"state": "Illinois",
|
| 26 |
+
"timezone": "America/Chicago"
|
| 27 |
+
},
|
| 28 |
+
"service_areas": ["Chicago", "Cook County"],
|
| 29 |
"history": ["Previously asked about jokes"]
|
| 30 |
},
|
| 31 |
"poet@example.com": {
|
| 32 |
+
"name": "Poet User",
|
| 33 |
"phone": "555-5678",
|
| 34 |
+
"bio": "A creative soul who loves poetry and literature",
|
| 35 |
+
"location": {
|
| 36 |
+
"city": "New York",
|
| 37 |
+
"state": "New York",
|
| 38 |
+
"timezone": "America/New_York"
|
| 39 |
+
},
|
| 40 |
+
"service_areas": ["Manhattan", "Brooklyn"],
|
| 41 |
"history": ["Previously asked about poetry"]
|
| 42 |
},
|
| 43 |
"admin@example.com": {
|
| 44 |
"name": "Admin User",
|
| 45 |
"phone": "555-9012",
|
| 46 |
+
"bio": "System administrator with access to all features",
|
| 47 |
+
"location": {
|
| 48 |
+
"city": "San Francisco",
|
| 49 |
+
"state": "California",
|
| 50 |
+
"timezone": "America/Los_Angeles"
|
| 51 |
+
},
|
| 52 |
+
"service_areas": ["San Francisco Bay Area", "Silicon Valley"],
|
| 53 |
"history": ["Previously asked about system settings"]
|
| 54 |
},
|
| 55 |
"joe@example.com": {
|
| 56 |
"name": "Joe Demo",
|
| 57 |
"phone": "555-0123",
|
| 58 |
+
"bio": "Real estate agent in Maui",
|
| 59 |
+
"location": {
|
| 60 |
+
"city": "Maui",
|
| 61 |
+
"state": "Hawaii",
|
| 62 |
+
"timezone": "Pacific/Honolulu"
|
| 63 |
+
},
|
| 64 |
+
"service_areas": ["Maui County", "Lahaina", "Kaanapali", "Wailea"],
|
| 65 |
"history": ["Previously tested video generation and web search"]
|
| 66 |
}
|
| 67 |
}
|
agent_system/video_handler.py
CHANGED
|
@@ -239,7 +239,7 @@ async def handle_script_to_video(message: str, history: List[Dict[str, Any]]) ->
|
|
| 239 |
|
| 240 |
**{structured_script.title}**
|
| 241 |
|
| 242 |
-
Key
|
| 243 |
{key_points}
|
| 244 |
|
| 245 |
Now starting video generation based on this script...
|
|
@@ -256,7 +256,7 @@ Now starting video generation based on this script...
|
|
| 256 |
|
| 257 |
**{script_data.get('title')}**
|
| 258 |
|
| 259 |
-
Key
|
| 260 |
{key_points}
|
| 261 |
|
| 262 |
Now starting video generation based on this script...
|
|
@@ -349,7 +349,7 @@ Now starting video generation based on this script...
|
|
| 349 |
|
| 350 |
**{structured_script.title}**
|
| 351 |
|
| 352 |
-
Key
|
| 353 |
{key_points}
|
| 354 |
|
| 355 |
{call_to_action}
|
|
@@ -366,7 +366,7 @@ Key points:
|
|
| 366 |
|
| 367 |
**{script_data.get('title')}**
|
| 368 |
|
| 369 |
-
Key
|
| 370 |
{key_points}
|
| 371 |
|
| 372 |
{script_data.get('callToAction', '')}
|
|
|
|
| 239 |
|
| 240 |
**{structured_script.title}**
|
| 241 |
|
| 242 |
+
Key Points Covered by Script:
|
| 243 |
{key_points}
|
| 244 |
|
| 245 |
Now starting video generation based on this script...
|
|
|
|
| 256 |
|
| 257 |
**{script_data.get('title')}**
|
| 258 |
|
| 259 |
+
Key Points Covered by Script:
|
| 260 |
{key_points}
|
| 261 |
|
| 262 |
Now starting video generation based on this script...
|
|
|
|
| 349 |
|
| 350 |
**{structured_script.title}**
|
| 351 |
|
| 352 |
+
Key Points Covered by Script:
|
| 353 |
{key_points}
|
| 354 |
|
| 355 |
{call_to_action}
|
|
|
|
| 366 |
|
| 367 |
**{script_data.get('title')}**
|
| 368 |
|
| 369 |
+
Key Points Covered by Script:
|
| 370 |
{key_points}
|
| 371 |
|
| 372 |
{script_data.get('callToAction', '')}
|
app.py
CHANGED
|
@@ -13,7 +13,7 @@ load_dotenv()
|
|
| 13 |
from logging_config import setup_logging
|
| 14 |
|
| 15 |
# Set up logging with configuration from environment
|
| 16 |
-
log_level = os.getenv("LOG_LEVEL", "
|
| 17 |
max_log_size_mb = int(os.getenv("MAX_LOG_SIZE_MB", "10"))
|
| 18 |
log_backup_count = int(os.getenv("LOG_BACKUP_COUNT", "5"))
|
| 19 |
|
|
|
|
| 13 |
from logging_config import setup_logging
|
| 14 |
|
| 15 |
# Set up logging with configuration from environment
|
| 16 |
+
log_level = os.getenv("LOG_LEVEL", "DEBUG")
|
| 17 |
max_log_size_mb = int(os.getenv("MAX_LOG_SIZE_MB", "10"))
|
| 18 |
log_backup_count = int(os.getenv("LOG_BACKUP_COUNT", "5"))
|
| 19 |
|
data/users/profiles/admin@example.com.json
CHANGED
|
@@ -2,6 +2,12 @@
|
|
| 2 |
"name": "Admin User",
|
| 3 |
"phone": "555-9012",
|
| 4 |
"bio": "System administrator with access to all features",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5 |
"preferences": {
|
| 6 |
"theme": "system",
|
| 7 |
"notifications": true
|
|
|
|
| 2 |
"name": "Admin User",
|
| 3 |
"phone": "555-9012",
|
| 4 |
"bio": "System administrator with access to all features",
|
| 5 |
+
"location": {
|
| 6 |
+
"city": "San Francisco",
|
| 7 |
+
"state": "California",
|
| 8 |
+
"timezone": "America/Los_Angeles"
|
| 9 |
+
},
|
| 10 |
+
"service_areas": ["San Francisco Bay Area", "Silicon Valley"],
|
| 11 |
"preferences": {
|
| 12 |
"theme": "system",
|
| 13 |
"notifications": true
|
data/users/profiles/joker@example.com.json
CHANGED
|
@@ -1,9 +1,15 @@
|
|
| 1 |
{
|
| 2 |
-
"name": "
|
| 3 |
"phone": "555-1234",
|
| 4 |
-
"bio": "
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5 |
"preferences": {
|
| 6 |
-
"theme": "
|
| 7 |
"notifications": true
|
| 8 |
},
|
| 9 |
"history_files": {
|
|
@@ -11,8 +17,8 @@
|
|
| 11 |
"videos": "data/users/history/joker@example.com/videos.json"
|
| 12 |
},
|
| 13 |
"metadata": {
|
| 14 |
-
"created_at":
|
| 15 |
-
"last_login":
|
| 16 |
"account_type": "standard"
|
| 17 |
}
|
| 18 |
}
|
|
|
|
| 1 |
{
|
| 2 |
+
"name": "Test User",
|
| 3 |
"phone": "555-1234",
|
| 4 |
+
"bio": "Regular test user account",
|
| 5 |
+
"location": {
|
| 6 |
+
"city": "Chicago",
|
| 7 |
+
"state": "Illinois",
|
| 8 |
+
"timezone": "America/Chicago"
|
| 9 |
+
},
|
| 10 |
+
"service_areas": ["Chicago", "Cook County"],
|
| 11 |
"preferences": {
|
| 12 |
+
"theme": "system",
|
| 13 |
"notifications": true
|
| 14 |
},
|
| 15 |
"history_files": {
|
|
|
|
| 17 |
"videos": "data/users/history/joker@example.com/videos.json"
|
| 18 |
},
|
| 19 |
"metadata": {
|
| 20 |
+
"created_at": 1672531200,
|
| 21 |
+
"last_login": 1715990400,
|
| 22 |
"account_type": "standard"
|
| 23 |
}
|
| 24 |
}
|
data/users/profiles/poet@example.com.json
CHANGED
|
@@ -2,6 +2,12 @@
|
|
| 2 |
"name": "Poet User",
|
| 3 |
"phone": "555-5678",
|
| 4 |
"bio": "A creative soul who loves poetry and literature",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5 |
"preferences": {
|
| 6 |
"theme": "light",
|
| 7 |
"notifications": false
|
|
|
|
| 2 |
"name": "Poet User",
|
| 3 |
"phone": "555-5678",
|
| 4 |
"bio": "A creative soul who loves poetry and literature",
|
| 5 |
+
"location": {
|
| 6 |
+
"city": "New York",
|
| 7 |
+
"state": "New York",
|
| 8 |
+
"timezone": "America/New_York"
|
| 9 |
+
},
|
| 10 |
+
"service_areas": ["Manhattan", "Brooklyn"],
|
| 11 |
"preferences": {
|
| 12 |
"theme": "light",
|
| 13 |
"notifications": false
|
logging_config.py
CHANGED
|
@@ -6,7 +6,7 @@ import logging
|
|
| 6 |
import datetime
|
| 7 |
from logging.handlers import RotatingFileHandler, TimedRotatingFileHandler
|
| 8 |
|
| 9 |
-
def setup_logging(log_level="
|
| 10 |
"""
|
| 11 |
Set up logging with both file and console output.
|
| 12 |
|
|
|
|
| 6 |
import datetime
|
| 7 |
from logging.handlers import RotatingFileHandler, TimedRotatingFileHandler
|
| 8 |
|
| 9 |
+
def setup_logging(log_level="DEBUG", max_file_size_mb=10, backup_count=5):
|
| 10 |
"""
|
| 11 |
Set up logging with both file and console output.
|
| 12 |
|
ui/chat_interface.py
CHANGED
|
@@ -147,29 +147,7 @@ Please process this request considering the available context and conversation h
|
|
| 147 |
# Process orchestrator response and create artifacts
|
| 148 |
logger.info(f"=== STARTING ORCHESTRATOR RESPONSE PROCESSING ===")
|
| 149 |
async for event in process_orchestrator_response_with_artifacts(result, state, new_history):
|
| 150 |
-
|
| 151 |
-
logger.info(f"=== BACKEND RESPONSE TO FRONTEND ===")
|
| 152 |
-
logger.info(f"Event type: {type(event)}")
|
| 153 |
-
if isinstance(event, tuple) and len(event) >= 1:
|
| 154 |
-
history_data = event[0]
|
| 155 |
-
logger.info(f"History data type: {type(history_data)}")
|
| 156 |
-
logger.info(f"History length: {len(history_data) if isinstance(history_data, list) else 'NOT_LIST'}")
|
| 157 |
-
|
| 158 |
-
if isinstance(history_data, list):
|
| 159 |
-
for i, msg in enumerate(history_data):
|
| 160 |
-
logger.info(f"Message {i}: type={type(msg)}, keys={list(msg.keys()) if isinstance(msg, dict) else 'NOT_DICT'}")
|
| 161 |
-
if isinstance(msg, dict):
|
| 162 |
-
for key, value in msg.items():
|
| 163 |
-
if key in ['role', 'content']:
|
| 164 |
-
logger.info(f" {key}: {repr(str(value)[:100])}... (type: {type(value)})")
|
| 165 |
-
else:
|
| 166 |
-
logger.info(f" {key}: {type(value)}")
|
| 167 |
-
else:
|
| 168 |
-
logger.error(f" INVALID MESSAGE: {repr(msg)}")
|
| 169 |
-
else:
|
| 170 |
-
logger.info(f"Event data: {repr(event)[:200]}...")
|
| 171 |
-
|
| 172 |
-
logger.info(f"=== YIELDING TO FRONTEND ===")
|
| 173 |
yield event
|
| 174 |
|
| 175 |
except Exception as e:
|
|
@@ -242,11 +220,8 @@ async def process_orchestrator_response_with_artifacts(result, state: ChatState,
|
|
| 242 |
try:
|
| 243 |
logger.info(f"=== PROCESSING ORCHESTRATOR STREAM EVENTS ===")
|
| 244 |
async for event in result.stream_events():
|
| 245 |
-
logger.debug(f"Stream event type: {type(event)}, has data: {hasattr(event, 'data')}")
|
| 246 |
-
|
| 247 |
if hasattr(event, 'data'):
|
| 248 |
event_data = event.data
|
| 249 |
-
logger.debug(f"Event data type: {type(event_data)}, has delta: {hasattr(event_data, 'delta')}")
|
| 250 |
|
| 251 |
# Only collect text deltas, not function call argument deltas
|
| 252 |
if hasattr(event_data, 'delta') and event_data.delta:
|
|
@@ -278,15 +253,11 @@ async def process_orchestrator_response_with_artifacts(result, state: ChatState,
|
|
| 278 |
"content": msg["content"]
|
| 279 |
})
|
| 280 |
|
| 281 |
-
logger.debug(f"Yielding streaming update: {len(full_response)} chars")
|
| 282 |
yield clean_history, state
|
| 283 |
last_yield_length = len(full_response)
|
| 284 |
|
| 285 |
# Add small delay for smooth streaming per Gradio best practices
|
| 286 |
await asyncio.sleep(0.05)
|
| 287 |
-
else:
|
| 288 |
-
# Skip function call argument deltas
|
| 289 |
-
logger.debug(f"Skipping {event_type_name} delta: {event_data.delta}")
|
| 290 |
|
| 291 |
# Handle tool results for artifact creation
|
| 292 |
elif hasattr(event.data, 'tool_calls'):
|
|
@@ -521,26 +492,11 @@ def create_chat_interface():
|
|
| 521 |
yield chat_history, "", state
|
| 522 |
return
|
| 523 |
|
| 524 |
-
|
| 525 |
-
logger.info(f"=== FRONTEND RESPOND FUNCTION ===")
|
| 526 |
-
logger.info(f"Message: {repr(message)}")
|
| 527 |
-
logger.info(f"Chat history type: {type(chat_history)}, length: {len(chat_history) if isinstance(chat_history, list) else 'NOT_LIST'}")
|
| 528 |
-
logger.info(f"State type: {type(state)}")
|
| 529 |
-
|
| 530 |
-
if isinstance(chat_history, list):
|
| 531 |
-
for i, msg in enumerate(chat_history):
|
| 532 |
-
logger.info(f"Input history {i}: {type(msg)}, keys: {list(msg.keys()) if isinstance(msg, dict) else 'NOT_DICT'}")
|
| 533 |
|
| 534 |
# Process message
|
| 535 |
try:
|
| 536 |
async for updated_history in chat_with_agents(message, chat_history, state):
|
| 537 |
-
# FRONTEND LOGGING: Log what we're about to yield
|
| 538 |
-
logger.info(f"=== FRONTEND YIELDING TO GRADIO ===")
|
| 539 |
-
logger.info(f"Updated history type: {type(updated_history)}, length: {len(updated_history) if isinstance(updated_history, list) else 'NOT_LIST'}")
|
| 540 |
-
|
| 541 |
-
if isinstance(updated_history, list) and len(updated_history) > 0:
|
| 542 |
-
last_msg = updated_history[-1]
|
| 543 |
-
logger.info(f"Last message in updated history: type={type(last_msg)}, keys={list(last_msg.keys()) if isinstance(last_msg, dict) else 'NOT_DICT'}")
|
| 544 |
|
| 545 |
# Ensure clean message format for Gradio
|
| 546 |
if isinstance(updated_history, tuple):
|
|
|
|
| 147 |
# Process orchestrator response and create artifacts
|
| 148 |
logger.info(f"=== STARTING ORCHESTRATOR RESPONSE PROCESSING ===")
|
| 149 |
async for event in process_orchestrator_response_with_artifacts(result, state, new_history):
|
| 150 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 151 |
yield event
|
| 152 |
|
| 153 |
except Exception as e:
|
|
|
|
| 220 |
try:
|
| 221 |
logger.info(f"=== PROCESSING ORCHESTRATOR STREAM EVENTS ===")
|
| 222 |
async for event in result.stream_events():
|
|
|
|
|
|
|
| 223 |
if hasattr(event, 'data'):
|
| 224 |
event_data = event.data
|
|
|
|
| 225 |
|
| 226 |
# Only collect text deltas, not function call argument deltas
|
| 227 |
if hasattr(event_data, 'delta') and event_data.delta:
|
|
|
|
| 253 |
"content": msg["content"]
|
| 254 |
})
|
| 255 |
|
|
|
|
| 256 |
yield clean_history, state
|
| 257 |
last_yield_length = len(full_response)
|
| 258 |
|
| 259 |
# Add small delay for smooth streaming per Gradio best practices
|
| 260 |
await asyncio.sleep(0.05)
|
|
|
|
|
|
|
|
|
|
| 261 |
|
| 262 |
# Handle tool results for artifact creation
|
| 263 |
elif hasattr(event.data, 'tool_calls'):
|
|
|
|
| 492 |
yield chat_history, "", state
|
| 493 |
return
|
| 494 |
|
| 495 |
+
logger.info(f"User message: {message}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 496 |
|
| 497 |
# Process message
|
| 498 |
try:
|
| 499 |
async for updated_history in chat_with_agents(message, chat_history, state):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 500 |
|
| 501 |
# Ensure clean message format for Gradio
|
| 502 |
if isinstance(updated_history, tuple):
|