Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -832,7 +832,93 @@ class ResponsePostProcessor:
|
|
| 832 |
|
| 833 |
post_processor = ResponsePostProcessor()
|
| 834 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 835 |
|
|
|
|
|
|
|
| 836 |
# ============================================================================
|
| 837 |
# TOOL FUNCTIONS
|
| 838 |
# ============================================================================
|
|
@@ -892,12 +978,11 @@ def orchestrate_turn(user_input: str, session_id: str = "default") -> str:
|
|
| 892 |
"""
|
| 893 |
Main orchestration function implementing the redesign workflow.
|
| 894 |
|
| 895 |
-
OPTIMIZED: Uses single Qwen3-Claude GGUF (loads once, all agents share)
|
| 896 |
|
| 897 |
Steps:
|
| 898 |
1. Reset prompt state
|
| 899 |
2. Process user input (history)
|
| 900 |
-
3. Tool decision
|
| 901 |
4. Regex checks
|
| 902 |
5. Agent execution (Qwen3-Claude)
|
| 903 |
6. Thinking agents (Qwen3-Claude)
|
|
@@ -936,9 +1021,11 @@ def orchestrate_turn(user_input: str, session_id: str = "default") -> str:
|
|
| 936 |
log_step("Step 2: Process user input", step_start)
|
| 937 |
|
| 938 |
# ====================================================================
|
| 939 |
-
# STEP 3: TOOL DECISION ENGINE
|
| 940 |
# ====================================================================
|
| 941 |
-
step_start = log_step("Step 3: Tool decision")
|
|
|
|
|
|
|
| 942 |
tool_decision_result = tool_agent.decide(user_input, conversation_history)
|
| 943 |
|
| 944 |
tool_img_output = ""
|
|
@@ -947,10 +1034,35 @@ def orchestrate_turn(user_input: str, session_id: str = "default") -> str:
|
|
| 947 |
if tool_decision_result:
|
| 948 |
logger.info("Tool decision: YES - visualization needed")
|
| 949 |
prompt_state.update("TOOL_USE_ENHANCEMENT", True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 950 |
else:
|
| 951 |
logger.info("Tool decision: NO - no visualization needed")
|
| 952 |
|
| 953 |
-
log_step("Step 3: Tool decision", step_start)
|
| 954 |
# ====================================================================
|
| 955 |
# STEP 4: REGEX LOGICAL EXPRESSIONS
|
| 956 |
# ====================================================================
|
|
|
|
| 832 |
|
| 833 |
post_processor = ResponsePostProcessor()
|
| 834 |
|
| 835 |
+
# ============================================================================
|
| 836 |
+
# DATA EXTRACTION FOR GRAPHING
|
| 837 |
+
# ============================================================================
|
| 838 |
+
|
| 839 |
+
def extract_graph_data(user_input: str, conversation_history: List[Dict]) -> Optional[Dict]:
|
| 840 |
+
"""
|
| 841 |
+
Use LLM to extract graphable data from user input.
|
| 842 |
+
|
| 843 |
+
Returns:
|
| 844 |
+
Dict with keys: data, plot_type, title, x_label, y_label, educational_context
|
| 845 |
+
Or None if no data can be extracted
|
| 846 |
+
"""
|
| 847 |
+
from model_manager import get_model
|
| 848 |
+
|
| 849 |
+
model = get_model()
|
| 850 |
+
|
| 851 |
+
# Format conversation context
|
| 852 |
+
context = ""
|
| 853 |
+
if conversation_history:
|
| 854 |
+
recent = conversation_history[-2:]
|
| 855 |
+
context = "\n".join([f"{msg['role']}: {msg['content'][:200]}" for msg in recent])
|
| 856 |
+
|
| 857 |
+
extraction_prompt = f"""Extract graphable data from the user's message.
|
| 858 |
+
|
| 859 |
+
Previous context:
|
| 860 |
+
{context}
|
| 861 |
+
|
| 862 |
+
Current message: {user_input}
|
| 863 |
+
|
| 864 |
+
If the message contains data that can be graphed (numbers, comparisons, datasets, trends), extract:
|
| 865 |
+
1. The data as key-value pairs
|
| 866 |
+
2. The best plot type (bar, line, or pie)
|
| 867 |
+
3. A descriptive title
|
| 868 |
+
4. Axis labels (if applicable)
|
| 869 |
+
5. Educational context explaining what the graph shows
|
| 870 |
+
|
| 871 |
+
Respond in JSON format ONLY:
|
| 872 |
+
{{
|
| 873 |
+
"has_data": true/false,
|
| 874 |
+
"data": {{"label1": value1, "label2": value2, ...}},
|
| 875 |
+
"plot_type": "bar/line/pie",
|
| 876 |
+
"title": "Graph Title",
|
| 877 |
+
"x_label": "X Axis Label",
|
| 878 |
+
"y_label": "Y Axis Label",
|
| 879 |
+
"educational_context": "Brief explanation of what this graph represents"
|
| 880 |
+
}}
|
| 881 |
+
|
| 882 |
+
If no graphable data exists, respond: {{"has_data": false}}"""
|
| 883 |
+
|
| 884 |
+
try:
|
| 885 |
+
system_prompt = "You are a data extraction expert. Extract graphable data from text and respond in valid JSON only."
|
| 886 |
+
|
| 887 |
+
response = model.generate(
|
| 888 |
+
system_prompt=system_prompt,
|
| 889 |
+
user_message=extraction_prompt,
|
| 890 |
+
max_tokens=300,
|
| 891 |
+
temperature=0.3
|
| 892 |
+
)
|
| 893 |
+
|
| 894 |
+
# Parse JSON response
|
| 895 |
+
import json
|
| 896 |
+
# Try to extract JSON from response
|
| 897 |
+
json_start = response.find('{')
|
| 898 |
+
json_end = response.rfind('}') + 1
|
| 899 |
+
|
| 900 |
+
if json_start == -1 or json_end == 0:
|
| 901 |
+
return None
|
| 902 |
+
|
| 903 |
+
json_str = response[json_start:json_end]
|
| 904 |
+
result = json.loads(json_str)
|
| 905 |
+
|
| 906 |
+
if not result.get('has_data', False):
|
| 907 |
+
return None
|
| 908 |
+
|
| 909 |
+
# Validate required fields
|
| 910 |
+
if 'data' not in result or not result['data']:
|
| 911 |
+
return None
|
| 912 |
+
|
| 913 |
+
return result
|
| 914 |
+
|
| 915 |
+
except Exception as e:
|
| 916 |
+
logger.error(f"Data extraction failed: {e}")
|
| 917 |
+
return None
|
| 918 |
+
|
| 919 |
|
| 920 |
+
|
| 921 |
+
|
| 922 |
# ============================================================================
|
| 923 |
# TOOL FUNCTIONS
|
| 924 |
# ============================================================================
|
|
|
|
| 978 |
"""
|
| 979 |
Main orchestration function implementing the redesign workflow.
|
| 980 |
|
|
|
|
| 981 |
|
| 982 |
Steps:
|
| 983 |
1. Reset prompt state
|
| 984 |
2. Process user input (history)
|
| 985 |
+
3. Tool decision
|
| 986 |
4. Regex checks
|
| 987 |
5. Agent execution (Qwen3-Claude)
|
| 988 |
6. Thinking agents (Qwen3-Claude)
|
|
|
|
| 1021 |
log_step("Step 2: Process user input", step_start)
|
| 1022 |
|
| 1023 |
# ====================================================================
|
| 1024 |
+
# STEP 3: TOOL DECISION ENGINE & GRAPH GENERATION
|
| 1025 |
# ====================================================================
|
| 1026 |
+
step_start = log_step("Step 3: Tool decision & graph generation")
|
| 1027 |
+
|
| 1028 |
+
# Check if visualization is needed
|
| 1029 |
tool_decision_result = tool_agent.decide(user_input, conversation_history)
|
| 1030 |
|
| 1031 |
tool_img_output = ""
|
|
|
|
| 1034 |
if tool_decision_result:
|
| 1035 |
logger.info("Tool decision: YES - visualization needed")
|
| 1036 |
prompt_state.update("TOOL_USE_ENHANCEMENT", True)
|
| 1037 |
+
|
| 1038 |
+
# Extract data and generate graph
|
| 1039 |
+
logger.info("→ Extracting graphable data from input...")
|
| 1040 |
+
graph_data = extract_graph_data(user_input, conversation_history)
|
| 1041 |
+
|
| 1042 |
+
if graph_data:
|
| 1043 |
+
logger.info(f"✓ Data extracted: {len(graph_data['data'])} data points")
|
| 1044 |
+
logger.info(f" Plot type: {graph_data['plot_type']}")
|
| 1045 |
+
|
| 1046 |
+
# Generate the graph
|
| 1047 |
+
tool_img_output = Create_Graph_Tool(
|
| 1048 |
+
data=graph_data['data'],
|
| 1049 |
+
plot_type=graph_data['plot_type'],
|
| 1050 |
+
title=graph_data.get('title', 'Generated Plot'),
|
| 1051 |
+
x_label=graph_data.get('x_label', ''),
|
| 1052 |
+
y_label=graph_data.get('y_label', ''),
|
| 1053 |
+
educational_context=graph_data.get('educational_context', '')
|
| 1054 |
+
)
|
| 1055 |
+
|
| 1056 |
+
# Store context for thinking agents
|
| 1057 |
+
tool_context = f"Graph created: {graph_data['plot_type']} chart showing {graph_data.get('title', 'data visualization')}"
|
| 1058 |
+
|
| 1059 |
+
logger.info("✓ Graph generated successfully")
|
| 1060 |
+
else:
|
| 1061 |
+
logger.info("⚠️ No extractable data found - skipping graph generation")
|
| 1062 |
else:
|
| 1063 |
logger.info("Tool decision: NO - no visualization needed")
|
| 1064 |
|
| 1065 |
+
log_step("Step 3: Tool decision & graph generation", step_start)
|
| 1066 |
# ====================================================================
|
| 1067 |
# STEP 4: REGEX LOGICAL EXPRESSIONS
|
| 1068 |
# ====================================================================
|