Skip to content

Commit e28fb10

Browse files
committed
Refactor CSV analysis handling and improve routing service
- Updated BackendOrchestrator to save CSV data to a temporary file and store additional CSV info in the session. - Enhanced IntelligentRoutingService to handle CSV queries with improved error handling and fallback analysis. - Modified CSV analysis prompt to enforce simpler, focused code generation. - Cleaned up frontend to display messages with generated images and added cleanup for old images. - Increased MAX_CHAT_HISTORIES constant to allow more chat sessions. - Removed unused constants and cleaned up settings configuration. - Added unit tests for backend orchestrator, CSV analysis tools, and conversation service. - Removed outdated test files and organized test structure.
1 parent a6de1d7 commit e28fb10

21 files changed

+901
-291
lines changed

.github/workflows/pytest.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,7 @@ jobs:
2121
pip3 install -r requirements.txt
2222
2323
- name: Run Pytest
24+
env:
25+
JUPYTER_PLATFORM_DIRS: "1"
2426
run: |
2527
pytest

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ __pycache__/
1414
# Installer logs
1515
pip-log.txt
1616
pip-delete-this-directory.txt
17-
test_*
17+
./test_*
1818
run_*
1919

2020
# Unit test / coverage reports

examples/basic_usage_demo.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
import sys
88
import os
99

10-
# Add the project root to Python path
1110
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
1211

1312
from src.services.routing_service import IntelligentRoutingService
Lines changed: 302 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,302 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Comprehensive test for all backend functionality of Querypls.
4+
Tests conversation, SQL generation, and CSV analysis capabilities.
5+
"""
6+
7+
import sys
8+
import os
9+
import pandas as pd
10+
from io import StringIO
11+
12+
# Add the project root to Python path
13+
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
14+
15+
from src.services.routing_service import IntelligentRoutingService
16+
from src.services.conversation_service import ConversationService
17+
from src.services.sql_service import SQLGenerationService
18+
from src.services.csv_analysis_tools import CSVAnalysisTools
19+
from src.schemas.requests import ChatMessage, SQLGenerationRequest
20+
from src.backend.orchestrator import BackendOrchestrator
21+
22+
23+
def test_conversation_functionality():
24+
"""Test conversation responses."""
25+
print("🧪 Testing Conversation Functionality")
26+
print("=" * 50)
27+
28+
try:
29+
routing_service = IntelligentRoutingService()
30+
31+
# Test conversation queries
32+
conversation_tests = [
33+
"Hello",
34+
"How are you?",
35+
"What can you do?",
36+
"Thanks for your help",
37+
"Goodbye"
38+
]
39+
40+
for query in conversation_tests:
41+
print(f"\nQuery: '{query}'")
42+
try:
43+
response = routing_service.handle_conversation_query(query)
44+
print(f"Response: {response[:100]}...")
45+
print("✅ PASS")
46+
except Exception as e:
47+
print(f"❌ FAIL: {str(e)}")
48+
49+
print("\n" + "=" * 50)
50+
return True
51+
52+
except Exception as e:
53+
print(f"❌ Conversation test failed: {str(e)}")
54+
return False
55+
56+
57+
def test_sql_functionality():
58+
"""Test SQL generation functionality."""
59+
print("🗃️ Testing SQL Generation Functionality")
60+
print("=" * 50)
61+
62+
try:
63+
routing_service = IntelligentRoutingService()
64+
sql_service = SQLGenerationService()
65+
66+
# Test SQL queries
67+
sql_tests = [
68+
"Show me all users",
69+
"SELECT * FROM users WHERE status = 'active'",
70+
"Find customers who made purchases in the last 30 days",
71+
"Get the total sales by month"
72+
]
73+
74+
for query in sql_tests:
75+
print(f"\nQuery: '{query}'")
76+
try:
77+
# Test routing
78+
routing_decision = routing_service.determine_agent(query, [], csv_loaded=False)
79+
print(f"Routing Decision: {routing_decision.agent}")
80+
81+
# Test SQL generation
82+
request = SQLGenerationRequest(
83+
user_query=query,
84+
conversation_history=[]
85+
)
86+
response = sql_service.generate_sql(request)
87+
print(f"SQL Response: {response.content[:100]}...")
88+
print("✅ PASS")
89+
except Exception as e:
90+
print(f"❌ FAIL: {str(e)}")
91+
92+
print("\n" + "=" * 50)
93+
return True
94+
95+
except Exception as e:
96+
print(f"❌ SQL test failed: {str(e)}")
97+
return False
98+
99+
100+
def test_csv_functionality():
101+
"""Test CSV analysis functionality."""
102+
print("📊 Testing CSV Analysis Functionality")
103+
print("=" * 50)
104+
105+
try:
106+
# Create sample CSV data
107+
sample_data = {
108+
'name': ['Alice', 'Bob', 'Charlie', 'Diana', 'Eve'],
109+
'age': [25, 30, 35, 28, 32],
110+
'salary': [50000, 60000, 70000, 55000, 65000],
111+
'department': ['IT', 'HR', 'IT', 'Finance', 'HR']
112+
}
113+
114+
df = pd.DataFrame(sample_data)
115+
csv_content = df.to_csv(index=False)
116+
117+
print(f"Sample CSV Data:\n{df.head()}")
118+
print(f"CSV Shape: {df.shape}")
119+
120+
# Test CSV tools
121+
csv_tools = CSVAnalysisTools()
122+
123+
# Test loading CSV data
124+
print("\nTesting CSV loading...")
125+
result = csv_tools.load_csv_data(csv_content, "test_session")
126+
print(f"Load Result: {result}")
127+
128+
# Test CSV analysis queries
129+
csv_tests = [
130+
"Show me the basic statistics of the data",
131+
"Create a bar chart of department distribution",
132+
"What is the average salary by department?",
133+
"Show me the top 3 highest paid employees"
134+
]
135+
136+
routing_service = IntelligentRoutingService()
137+
138+
for query in csv_tests:
139+
print(f"\nQuery: '{query}'")
140+
try:
141+
# Test routing with CSV loaded
142+
routing_decision = routing_service.determine_agent(query, [], csv_loaded=True)
143+
print(f"Routing Decision: {routing_decision.agent}")
144+
145+
# Test CSV analysis
146+
response = routing_service.handle_csv_query(query, csv_content)
147+
print(f"CSV Response: {response[:200]}...")
148+
print("✅ PASS")
149+
except Exception as e:
150+
print(f"❌ FAIL: {str(e)}")
151+
152+
print("\n" + "=" * 50)
153+
return True
154+
155+
except Exception as e:
156+
print(f"❌ CSV test failed: {str(e)}")
157+
return False
158+
159+
160+
def test_intelligent_routing():
161+
"""Test intelligent routing functionality."""
162+
print("🧠 Testing Intelligent Routing")
163+
print("=" * 50)
164+
165+
try:
166+
routing_service = IntelligentRoutingService()
167+
168+
# Test cases with expected routing
169+
test_cases = [
170+
("Hello", "CONVERSATION_AGENT"),
171+
("How are you?", "CONVERSATION_AGENT"),
172+
("Show me all users", "SQL_AGENT"),
173+
("SELECT * FROM users", "SQL_AGENT"),
174+
("Analyze this CSV data", "CSV_AGENT"),
175+
("Create a chart from the data", "CSV_AGENT"),
176+
("What can you do?", "CONVERSATION_AGENT"),
177+
("Thanks for your help", "CONVERSATION_AGENT"),
178+
]
179+
180+
all_passed = True
181+
for query, expected_agent in test_cases:
182+
print(f"\nQuery: '{query}'")
183+
print(f"Expected Agent: {expected_agent}")
184+
185+
try:
186+
# Test without CSV loaded
187+
decision = routing_service.determine_agent(query, [], csv_loaded=False)
188+
print(f"Result (no CSV): {decision.agent}")
189+
190+
# Test with CSV loaded
191+
decision_with_csv = routing_service.determine_agent(query, [], csv_loaded=True)
192+
print(f"Result (with CSV): {decision_with_csv.agent}")
193+
194+
if decision.agent == expected_agent or decision_with_csv.agent == expected_agent:
195+
print("✅ PASS")
196+
else:
197+
print("❌ FAIL")
198+
all_passed = False
199+
200+
except Exception as e:
201+
print(f"❌ ERROR: {str(e)}")
202+
all_passed = False
203+
204+
print("\n" + "=" * 50)
205+
return all_passed
206+
207+
except Exception as e:
208+
print(f"❌ Routing test failed: {str(e)}")
209+
return False
210+
211+
212+
def test_orchestrator():
213+
"""Test the main orchestrator functionality."""
214+
print("🎼 Testing Backend Orchestrator")
215+
print("=" * 50)
216+
217+
try:
218+
orchestrator = BackendOrchestrator()
219+
220+
# Test session creation
221+
print("Testing session creation...")
222+
from src.schemas.requests import NewChatRequest
223+
session_info = orchestrator.create_new_session(NewChatRequest(session_name="Test Session"))
224+
session_id = session_info.session_id
225+
print(f"Created session: {session_id}")
226+
227+
# Test conversation
228+
print("\nTesting conversation...")
229+
response = orchestrator.generate_intelligent_response(session_id, "Hello")
230+
print(f"Conversation Response: {response.content[:100]}...")
231+
232+
# Test SQL generation
233+
print("\nTesting SQL generation...")
234+
response = orchestrator.generate_intelligent_response(session_id, "Show me all users")
235+
print(f"SQL Response: {response.content[:100]}...")
236+
237+
# Test CSV loading and analysis
238+
print("\nTesting CSV functionality...")
239+
sample_csv = "name,age,salary\nAlice,25,50000\nBob,30,60000\nCharlie,35,70000"
240+
result = orchestrator.load_csv_data(session_id, sample_csv)
241+
print(f"CSV Load Result: {result}")
242+
243+
response = orchestrator.generate_intelligent_response(session_id, "Analyze this data")
244+
print(f"CSV Analysis Response: {response.content[:100]}...")
245+
246+
print("\n" + "=" * 50)
247+
return True
248+
249+
except Exception as e:
250+
print(f"❌ Orchestrator test failed: {str(e)}")
251+
return False
252+
253+
254+
def main():
255+
"""Run all tests."""
256+
print("🚀 Starting Comprehensive Backend Functionality Tests")
257+
print("=" * 60)
258+
259+
tests = [
260+
("Conversation", test_conversation_functionality),
261+
("SQL Generation", test_sql_functionality),
262+
("CSV Analysis", test_csv_functionality),
263+
("Intelligent Routing", test_intelligent_routing),
264+
("Orchestrator", test_orchestrator),
265+
]
266+
267+
results = {}
268+
269+
for test_name, test_func in tests:
270+
print(f"\n{'='*20} {test_name} {'='*20}")
271+
try:
272+
results[test_name] = test_func()
273+
except Exception as e:
274+
print(f"❌ {test_name} test crashed: {str(e)}")
275+
results[test_name] = False
276+
277+
# Summary
278+
print("\n" + "=" * 60)
279+
print("📊 TEST SUMMARY")
280+
print("=" * 60)
281+
282+
passed = 0
283+
total = len(tests)
284+
285+
for test_name, result in results.items():
286+
status = "✅ PASS" if result else "❌ FAIL"
287+
print(f"{test_name}: {status}")
288+
if result:
289+
passed += 1
290+
291+
print(f"\nOverall: {passed}/{total} tests passed")
292+
293+
if passed == total:
294+
print("🎉 All tests passed! Backend functionality is working correctly.")
295+
else:
296+
print("⚠️ Some tests failed. Check the backend implementation.")
297+
298+
return passed == total
299+
300+
301+
if __name__ == "__main__":
302+
main()

0 commit comments

Comments
 (0)