@@ -76,8 +76,8 @@ def determine_agent(
7676
7777 except Exception as e :
7878 print (f"Routing failed with error: { e } " )
79- # Use simple keyword-based routing as fallback
80- return self ._keyword_based_routing (user_query , csv_loaded )
79+ # Use intelligent fallback routing
80+ return self ._fallback_routing (user_query , csv_loaded )
8181
8282 def handle_conversation_query (self , user_query : str ) -> str :
8383 """Handle conversational queries."""
@@ -111,7 +111,7 @@ def handle_sql_query(
111111 def handle_csv_query (
112112 self ,
113113 user_query : str ,
114- csv_info : Dict [str , Any ],
114+ csv_info : Optional [ Dict [str , Any ]] = None ,
115115 conversation_history : Optional [List [ChatMessage ]] = None ,
116116 ) -> str :
117117 """Handle CSV analysis queries."""
@@ -135,7 +135,7 @@ def handle_csv_query(
135135 return WORST_CASE_SCENARIO
136136
137137 def _execute_csv_analysis (
138- self , python_code : str , csv_info : Dict [str , Any ], explanation : str
138+ self , python_code : str , csv_info : Optional [ Dict [str , Any ] ], explanation : str
139139 ) -> str :
140140 """Execute CSV analysis code using Jupyter service with error fixing retry loop."""
141141 try :
@@ -147,8 +147,9 @@ def _execute_csv_analysis(
147147 # Create a temporary session for this analysis
148148 session_id = "csv_analysis_temp"
149149
150- # Load CSV data into the session
151- jupyter_service .load_csv_data (session_id , csv_info ["file_path" ])
150+ # Load CSV data into the session if available
151+ if csv_info and csv_info .get ("file_path" ):
152+ jupyter_service .load_csv_data (session_id , csv_info ["file_path" ])
152153
153154 # Install required libraries if needed
154155 install_code = """
@@ -219,7 +220,7 @@ def install_package(package):
219220 if attempt < max_retries - 1 : # Not the last attempt
220221 # Send error to LLM to fix the code
221222 fixed_code = self ._fix_python_code (
222- current_code , error_msg , csv_info
223+ current_code , error_msg , csv_info or {}
223224 )
224225 if fixed_code :
225226 current_code = fixed_code
@@ -290,20 +291,30 @@ def _prepare_sql_context(
290291 def _prepare_csv_context (
291292 self ,
292293 user_query : str ,
293- csv_info : Dict [str , Any ],
294+ csv_info : Optional [ Dict [str , Any ]] = None ,
294295 conversation_history : Optional [List [ChatMessage ]] = None ,
295296 ) -> str :
296297 """Prepare context for CSV analysis."""
297298 context_parts = [
298299 f"User Query: { user_query } " ,
299- f"CSV Data Available: Yes" ,
300- f"CSV File Path: { csv_info ['file_path' ]} " ,
301- f"CSV Shape: { csv_info ['shape' ]} " ,
302- f"CSV Columns: { csv_info ['columns' ]} " ,
303- f"CSV Data Types: { csv_info ['dtypes' ]} " ,
304- f"CSV Sample Data: { csv_info ['sample_data' ]} " ,
305300 ]
306301
302+ # Check if CSV data is available
303+ if csv_info and csv_info .get ('file_path' ):
304+ context_parts .extend ([
305+ f"CSV Data Available: Yes" ,
306+ f"CSV File Path: { csv_info ['file_path' ]} " ,
307+ f"CSV Shape: { csv_info ['shape' ]} " ,
308+ f"CSV Columns: { csv_info ['columns' ]} " ,
309+ f"CSV Data Types: { csv_info ['dtypes' ]} " ,
310+ f"CSV Sample Data: { csv_info ['sample_data' ]} " ,
311+ ])
312+ else :
313+ context_parts .extend ([
314+ f"CSV Data Available: No - User provided data in query" ,
315+ "SPECIAL INSTRUCTIONS: Analyze the user query and extract any relevant data for analysis"
316+ ])
317+
307318 if conversation_history :
308319 context_parts .append ("Conversation History:" )
309320 # Last 5 messages for context
@@ -317,18 +328,30 @@ def _prepare_csv_context(
317328 context_parts .append (
318329 "NO FUNCTIONS OR CLASSES - Just direct code that prints results!"
319330 )
331+
332+ if csv_info and csv_info .get ('file_path' ):
333+ context_parts .append (
334+ f"IMPORTANT: Use pd.read_csv('{ csv_info ['file_path' ]} ') to load the data from the file path!"
335+ )
336+ else :
337+ context_parts .append (
338+ "IMPORTANT: Analyze the user query and extract any relevant data for analysis!"
339+ )
340+ context_parts .append (
341+ "Use your intelligence to understand what the user wants and create appropriate analysis!"
342+ )
343+
320344 context_parts .append (
321- f"IMPORTANT: Use pd.read_csv('{ csv_info ['file_path' ]} ') to load the data from the file path!"
322- )
323- context_parts .append (
324- "Print human-readable results like 'Average price: $123.45' - NO technical output!"
345+ "Print human-readable results that directly answer the user's question - NO technical output!"
325346 )
326347 context_parts .append (
327348 "For charts, use plt.savefig('/tmp/querypls_session_csv_analysis_temp/chart.png') and plt.show()."
328349 )
329350
330351 return "\n " .join (context_parts )
331352
353+
354+
332355 def _prepare_code_fix_context (
333356 self , original_code : str , error_message : str , csv_info : Dict [str , Any ]
334357 ) -> str :
@@ -376,68 +399,6 @@ def _format_sql_response(self, sql_response) -> str:
376399
377400 return "\n \n " .join (response_parts )
378401
379- def _keyword_based_routing (self , user_query : str , csv_loaded : bool ) -> RoutingDecision :
380- """Keyword-based routing when LLM routing fails."""
381- query_lower = user_query .lower ()
382-
383- # CSV Agent keywords
384- csv_keywords = [
385- "csv" , "analyze" , "chart" , "plot" , "graph" , "average" , "mean" , "sum" ,
386- "count" , "max" , "min" , "statistics" , "data" , "visualization" , "top" ,
387- "bottom" , "highest" , "lowest" , "distribution" , "correlation"
388- ]
389-
390- # SQL Agent keywords
391- sql_keywords = [
392- "select" , "insert" , "update" , "delete" , "sql" , "query" , "table" ,
393- "database" , "users" , "customers" , "orders" , "products" , "where" ,
394- "join" , "group by" , "order by" , "from"
395- ]
396-
397- # Conversation Agent keywords
398- conversation_keywords = [
399- "hello" , "hi" , "hey" , "how are you" , "what can you do" , "help" ,
400- "thanks" , "thank you" , "goodbye" , "bye" , "good morning" , "good evening"
401- ]
402-
403- # Check for CSV analysis (prioritize if CSV is loaded)
404- if csv_loaded and any (keyword in query_lower for keyword in csv_keywords ):
405- return RoutingDecision (
406- agent = "CSV_AGENT" ,
407- confidence = 0.8 ,
408- reasoning = "Keyword-based routing detected CSV analysis request"
409- )
410-
411- # Check for SQL keywords
412- if any (keyword in query_lower for keyword in sql_keywords ):
413- return RoutingDecision (
414- agent = "SQL_AGENT" ,
415- confidence = 0.8 ,
416- reasoning = "Keyword-based routing detected SQL request"
417- )
418-
419- # Check for conversation keywords
420- if any (keyword in query_lower for keyword in conversation_keywords ):
421- return RoutingDecision (
422- agent = "CONVERSATION_AGENT" ,
423- confidence = 0.9 ,
424- reasoning = "Keyword-based routing detected conversation request"
425- )
426-
427- # Default based on context
428- if csv_loaded :
429- return RoutingDecision (
430- agent = "CSV_AGENT" ,
431- confidence = 0.6 ,
432- reasoning = "CSV loaded, defaulting to CSV analysis"
433- )
434- else :
435- return RoutingDecision (
436- agent = "CONVERSATION_AGENT" ,
437- confidence = 0.5 ,
438- reasoning = "No clear intent detected, defaulting to conversation"
439- )
440-
441402 def _fallback_routing (self , user_query : str , csv_loaded : bool ) -> RoutingDecision :
442403 """Fallback routing when LLM routing fails - let LLM decide, not hardcoded keywords."""
443404 # Default to conversation - let the LLM handle all decisions
@@ -450,3 +411,5 @@ def _fallback_routing(self, user_query: str, csv_loaded: bool) -> RoutingDecisio
450411 def _get_fallback_conversation_response (self , user_query : str ) -> str :
451412 """Get fallback conversation response when LLM fails."""
452413 return WORST_CASE_SCENARIO
414+
415+
0 commit comments