Skip to content

Commit 5ce3eba

Browse files
committed
Remove legacy files and clean up project structure
- Deleted outdated `run.py`, `test_app.py`, and `test_routing_fix.py` files to streamline the project. - Updated routing service and orchestrator to enhance CSV handling and intelligent routing capabilities. - Improved frontend application structure and import paths for better maintainability. - Refactored code for clarity and consistency across various modules, ensuring a cleaner codebase.
1 parent 93629c4 commit 5ce3eba

9 files changed

Lines changed: 79 additions & 378 deletions

File tree

run.py

Lines changed: 0 additions & 69 deletions
This file was deleted.

src/backend/orchestrator.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,12 +173,16 @@ def generate_intelligent_response(
173173
user_query, session.messages
174174
)
175175
elif routing_decision.agent == "CSV_AGENT":
176+
# Handle CSV analysis - can work with uploaded CSV or product lists from query
176177
if session.csv_data and session.csv_info:
177178
response_content = self.routing_service.handle_csv_query(
178179
user_query, session.csv_info, session.messages
179180
)
180181
else:
181-
response_content = "I don't see any CSV data loaded. Please upload a CSV file first to analyze it."
182+
# Handle product analysis from query without uploaded CSV
183+
response_content = self.routing_service.handle_csv_query(
184+
user_query, None, session.messages
185+
)
182186
else:
183187
# Fallback to conversation
184188
response_content = self.routing_service.handle_conversation_query(

src/frontend/app.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22
Main Streamlit application for Querypls.
33
"""
44

5+
import sys
6+
import os
7+
8+
project_root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
9+
sys.path.insert(0, project_root)
10+
511
from src.schemas.requests import NewChatRequest
612
from src.config.constants import (
713
CSV_ANALYSIS_SECTION,
@@ -28,15 +34,8 @@
2834
)
2935
from src.backend.orchestrator import BackendOrchestrator
3036
import streamlit as st
31-
import sys
32-
import os
3337
import pandas as pd
3438

35-
project_root = os.path.dirname(
36-
os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
37-
)
38-
sys.path.insert(0, project_root)
39-
4039

4140
def initialize_orchestrator():
4241
if "orchestrator" not in st.session_state:

src/services/routing_service.py

Lines changed: 43 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -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+

src/services/sql_service.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,7 @@ def format_chat_history(self, messages: list) -> str:
5252
def generate_sql(self, request: SQLGenerationRequest) -> ChatResponse:
5353
try:
5454
formatted_history = self.format_chat_history(request.conversation_history)
55-
prompt = f"Previous conversation: {formatted_history}\nCurrent question: {
56-
request.user_query}"
55+
prompt = f"Previous conversation: {formatted_history}\nCurrent question: {request.user_query}"
5756

5857
result = self.agent.run_sync(prompt)
5958

@@ -69,9 +68,7 @@ def generate_sql(self, request: SQLGenerationRequest) -> ChatResponse:
6968
warnings=result.output.warnings,
7069
)
7170

72-
formatted_content = f"```sql\n{
73-
sql_response.sql_query}\n```\n\n**Explanation:** {
74-
sql_response.explanation}"
71+
formatted_content = f"```sql\n{sql_response.sql_query}\n```\n\n**Explanation:** {sql_response.explanation}"
7572

7673
session_id = "default"
7774
if request.conversation_history:

src/terminal/cli.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,7 @@ def create_session(self, name: Optional[str] = None) -> str:
2323
session_info = self.orchestrator.create_new_session(request)
2424
self.current_session_id = session_info.session_id
2525
print(
26-
f"""Session created: {
27-
session_info.session_name} (ID: {
28-
session_info.session_id})"""
26+
f"Session created: {session_info.session_name} (ID: {session_info.session_id})"
2927
)
3028
return session_info.session_id
3129

0 commit comments

Comments
 (0)