From 7fafa7321f82235ab318447425df2f576321d04b Mon Sep 17 00:00:00 2001 From: Shiva Pochampally <146849983+PieLord757@users.noreply.github.com> Date: Sun, 28 Sep 2025 02:12:44 -0400 Subject: [PATCH] Added flask server for API endpoints for MongoDB Agent and LLM Summarization --- .../gemini_mongo_mateo.cpython-312.pyc | Bin 16294 -> 16301 bytes .../gemini_reroute_mateo.cpython-312.pyc | Bin 26908 -> 26915 bytes llm/api/INTEGRATION_GUIDE.md | 354 +++++++++++++++++ llm/api/flask_server.py | 369 ++++++++++++++++++ llm/api/requirements.txt | 6 + llm/api/test_api.py | 203 ++++++++++ llm/api/test_crash_endpoint.py | 126 ++++++ llm/flask_server.log | 50 +++ llm/gemini_mongo_mateo.py | 2 +- llm/gemini_reroute_mateo.py | 2 +- 10 files changed, 1110 insertions(+), 2 deletions(-) create mode 100644 llm/api/INTEGRATION_GUIDE.md create mode 100644 llm/api/flask_server.py create mode 100644 llm/api/requirements.txt create mode 100644 llm/api/test_api.py create mode 100644 llm/api/test_crash_endpoint.py create mode 100644 llm/flask_server.log diff --git a/llm/__pycache__/gemini_mongo_mateo.cpython-312.pyc b/llm/__pycache__/gemini_mongo_mateo.cpython-312.pyc index 8bcd0af3dddd622544b3f5fcb75986731bb1700d..b6cb1d2a1149de435109a7e356aebbd895e8e103 100644 GIT binary patch delta 46 zcmZ2hzqX$DG%qg~0}xy}ej}q{Bkxg04!-pK{PdjE_|2CY`)pZH*j-_Znw)0u00542 B5hwrv delta 39 ucmZ2mzpS43G%qg~0}$}G}ETIjQlR%b5z(SWnnpVT+plHbWl( Dng|hl delta 41 wcmZ2{iE+*)M&8rByj%=GptzLX{-nQuCN79{*s{&02UYx;Q#;t diff --git a/llm/api/INTEGRATION_GUIDE.md b/llm/api/INTEGRATION_GUIDE.md new file mode 100644 index 0000000..7884b5d --- /dev/null +++ b/llm/api/INTEGRATION_GUIDE.md @@ -0,0 +1,354 @@ +# Flask API Integration Guide for Next.js + +## πŸš€ Flask API Server + +Your Flask API server is now ready and running on **`http://localhost:5001`** + +### πŸ”Œ Available Endpoints + +| Method | Endpoint | Description | +|--------|----------|-------------| +| `GET` | `/api/health` | Health check endpoint | +| `GET` | `/api/weather?lat=X&lon=Y` | Get weather conditions | +| `POST` | `/api/analyze-crashes` | Analyze crash patterns at location | +| `POST` | `/api/find-safe-route` | Find safest route between points | +| `POST` | `/api/get-single-route` | Get single route with safety analysis | + +--- + +## πŸ“¦ Starting the Server + +```bash +cd /path/to/VTHacks13/llm +python api/flask_server.py +``` + +The server will start on `http://localhost:5001` with the following services: +- βœ… MongoDB connection to crash database +- βœ… Route safety analysis +- βœ… Weather API integration (Open-Meteo) +- βœ… Gemini AI for safety recommendations + +--- + +## πŸ”§ Next.js Integration + +### 1. Install Dependencies + +```bash +npm install axios # or use fetch API +``` + +### 2. Create API Client + +Create `lib/api-client.js`: + +```javascript +const API_BASE_URL = 'http://localhost:5001/api'; + +// Health Check +export async function checkAPIHealth() { + const response = await fetch(`${API_BASE_URL}/health`); + return response.json(); +} + +// Weather API +export async function getWeather(lat, lon) { + const response = await fetch(`${API_BASE_URL}/weather?lat=${lat}&lon=${lon}`); + const data = await response.json(); + + if (!response.ok) { + throw new Error(data.error || 'Failed to fetch weather'); + } + + return data; +} + +// Crash Analysis +export async function analyzeCrashes(lat, lon, radius = 1.0) { + const response = await fetch(`${API_BASE_URL}/analyze-crashes`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ lat, lon, radius }) + }); + + const data = await response.json(); + + if (!response.ok) { + throw new Error(data.error || 'Failed to analyze crashes'); + } + + return data; +} + +// Safe Route Finding +export async function findSafeRoute(startLat, startLon, endLat, endLon) { + const response = await fetch(`${API_BASE_URL}/find-safe-route`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + start_lat: startLat, + start_lon: startLon, + end_lat: endLat, + end_lon: endLon + }) + }); + + const data = await response.json(); + + if (!response.ok) { + throw new Error(data.error || 'Failed to find safe route'); + } + + return data; +} + +// Single Route +export async function getSingleRoute(startLat, startLon, endLat, endLon, profile = 'driving') { + const response = await fetch(`${API_BASE_URL}/get-single-route`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + start_lat: startLat, + start_lon: startLon, + end_lat: endLat, + end_lon: endLon, + profile + }) + }); + + const data = await response.json(); + + if (!response.ok) { + throw new Error(data.error || 'Failed to get route'); + } + + return data; +} +``` + +### 3. Example React Component + +Create `components/SafetyAnalysis.jsx`: + +```jsx +import { useState } from 'react'; +import { analyzeCrashes, findSafeRoute, getWeather } from '../lib/api-client'; + +export default function SafetyAnalysis() { + const [loading, setLoading] = useState(false); + const [results, setResults] = useState(null); + const [error, setError] = useState(null); + + const handleAnalyze = async () => { + setLoading(true); + setError(null); + + try { + // Example: Analyze crashes around Virginia Tech + const lat = 37.2284; + const lon = -80.4234; + const radius = 2.0; + + // Get crash analysis + const crashData = await analyzeCrashes(lat, lon, radius); + + // Get safe route (Virginia Tech to Downtown Blacksburg) + const routeData = await findSafeRoute(lat, lon, 37.2297, -80.4139); + + // Get weather + const weatherData = await getWeather(lat, lon); + + setResults({ + crashes: crashData, + route: routeData, + weather: weatherData + }); + + } catch (err) { + setError(err.message); + } finally { + setLoading(false); + } + }; + + return ( +
+

Safety Analysis

+ + + + {error && ( +
+ Error: {error} +
+ )} + + {results && ( +
+ {/* Crash Analysis Results */} +
+

Crash Analysis

+

Total crashes: {results.crashes.crash_summary.total_crashes}

+

Total casualties: {results.crashes.crash_summary.total_casualties}

+

Weather: {results.crashes.weather.summary}

+
+ + {/* Route Results */} +
+

Safe Route

+

Distance: {results.route.recommended_route.distance_km.toFixed(1)} km

+

Duration: {results.route.recommended_route.duration_min.toFixed(0)} minutes

+

Crashes nearby: {results.route.recommended_route.crashes_nearby}

+

Safety score: {results.route.recommended_route.safety_score.toFixed(3)}

+
+ + {/* Weather Results */} +
+

Current Weather

+

{results.weather.summary}

+
+
+ )} +
+ ); +} +``` + +### 4. Mapbox Integration + +For route visualization: + +```jsx +import { useEffect, useRef } from 'react'; +import mapboxgl from 'mapbox-gl'; + +export default function RouteMap({ routeData }) { + const mapContainer = useRef(null); + const map = useRef(null); + + useEffect(() => { + if (!routeData || map.current) return; + + map.current = new mapboxgl.Map({ + container: mapContainer.current, + style: 'mapbox://styles/mapbox/streets-v12', + center: [routeData.recommended_route.coordinates[0][0], + routeData.recommended_route.coordinates[0][1]], + zoom: 13 + }); + + // Add route to map + map.current.on('load', () => { + map.current.addSource('route', { + 'type': 'geojson', + 'data': { + 'type': 'Feature', + 'properties': {}, + 'geometry': routeData.recommended_route.geometry + } + }); + + map.current.addLayer({ + 'id': 'route', + 'type': 'line', + 'source': 'route', + 'layout': { + 'line-join': 'round', + 'line-cap': 'round' + }, + 'paint': { + 'line-color': '#3887be', + 'line-width': 5, + 'line-opacity': 0.75 + } + }); + }); + }, [routeData]); + + return
; +} +``` + +--- + +## πŸ“Š Response Formats + +### Crash Analysis Response +```json +{ + "success": true, + "location": {"lat": 37.2284, "lon": -80.4234}, + "radius_km": 2.0, + "crash_summary": { + "total_crashes": 5, + "avg_distance_km": 1.2, + "severity_breakdown": {"Minor": 3, "Major": 2}, + "total_casualties": 8 + }, + "weather": { + "summary": "Clear sky, precipitation 0.0mm/h, wind 5.2 km/h, day" + }, + "safety_analysis": "AI-generated safety report..." +} +``` + +### Safe Route Response +```json +{ + "success": true, + "recommended_route": { + "coordinates": [[lon, lat], [lon, lat], ...], + "distance_km": 1.5, + "duration_min": 4.2, + "geometry": {...}, // GeoJSON for Mapbox + "safety_score": 0.234, + "crashes_nearby": 2 + }, + "safety_analysis": "AI-generated route safety report...", + "weather_summary": "Current weather conditions...", + "alternative_routes": [...] +} +``` + +--- + +## πŸ§ͺ Testing the API + +Run the test script: +```bash +cd llm/api +python test_api.py +``` + +Or test individual endpoints with curl: +```bash +# Health check +curl http://localhost:5001/api/health + +# Weather +curl "http://localhost:5001/api/weather?lat=37.2284&lon=-80.4234" + +# Crash analysis +curl -X POST http://localhost:5001/api/analyze-crashes \ + -H "Content-Type: application/json" \ + -d '{"lat": 37.2284, "lon": -80.4234, "radius": 1.0}' +``` + +--- + +## 🎯 Next Steps + +1. **Start Flask Server**: `cd llm && python api/flask_server.py` +2. **Test Endpoints**: Use the provided test scripts +3. **Integrate with Next.js**: Use the API client code above +4. **Add to Your Components**: Import and use the API functions +5. **Visualize Routes**: Use Mapbox with the route coordinates + +Your Flask API is ready to bridge your Python AI/safety analysis with your Next.js frontend! πŸš€ \ No newline at end of file diff --git a/llm/api/flask_server.py b/llm/api/flask_server.py new file mode 100644 index 0000000..65ae553 --- /dev/null +++ b/llm/api/flask_server.py @@ -0,0 +1,369 @@ +from flask import Flask, request, jsonify +from flask_cors import CORS +import sys +import os +import traceback +from datetime import datetime +import json +from bson import ObjectId + +# Since we're now in llm/api/, we need to add the parent directory (llm) to Python path +sys.path.append(os.path.dirname(os.path.dirname(__file__))) + +# Import our existing modules from the same llm directory +try: + from gemini_mongo_mateo import ( + connect_to_mongodb, + get_crashes_within_radius_mongodb, + analyze_mongodb_crash_patterns, + get_current_weather + ) + from gemini_reroute_mateo import SafeRouteAnalyzer, MONGO_URI + print("βœ… Successfully imported Python modules") +except ImportError as e: + print(f"❌ Failed to import modules: {e}") + traceback.print_exc() + sys.exit(1) + +def serialize_mongodb_doc(doc): + """Convert MongoDB document to JSON-serializable format""" + if doc is None: + return None + + if isinstance(doc, list): + return [serialize_mongodb_doc(item) for item in doc] + + if isinstance(doc, dict): + serialized = {} + for key, value in doc.items(): + if isinstance(value, ObjectId): + serialized[key] = str(value) + elif isinstance(value, dict): + serialized[key] = serialize_mongodb_doc(value) + elif isinstance(value, list): + serialized[key] = serialize_mongodb_doc(value) + else: + serialized[key] = value + return serialized + + return doc + +app = Flask(__name__) +CORS(app) # Enable CORS for all routes + +# Initialize the route analyzer +route_analyzer = SafeRouteAnalyzer(MONGO_URI) + +# Initialize MongoDB connection for crash analysis +mongo_collection = connect_to_mongodb() + +@app.route('/api/health', methods=['GET']) +def health_check(): + """Health check endpoint to verify API is running.""" + return jsonify({ + 'status': 'healthy', + 'timestamp': datetime.now().isoformat(), + 'mongodb_connected': mongo_collection is not None, + 'route_analyzer_ready': route_analyzer.collection is not None + }) + +@app.route('/api/weather', methods=['GET']) +def get_weather_endpoint(): + """Get current weather conditions for given coordinates.""" + try: + lat = float(request.args.get('lat')) + lon = float(request.args.get('lon')) + + weather_data, weather_summary = get_current_weather(lat, lon) + + if weather_data is None: + return jsonify({ + 'success': False, + 'error': weather_summary + }), 400 + + return jsonify({ + 'success': True, + 'weather_data': weather_data, + 'summary': weather_summary, + 'coordinates': {'lat': lat, 'lon': lon} + }) + + except (TypeError, ValueError) as e: + return jsonify({ + 'success': False, + 'error': 'Invalid latitude or longitude provided' + }), 400 + except Exception as e: + return jsonify({ + 'success': False, + 'error': str(e) + }), 500 + +@app.route('/api/analyze-crashes', methods=['POST']) +def analyze_crashes_endpoint(): + """Analyze crash patterns and safety for a specific location.""" + try: + if mongo_collection is None: + return jsonify({ + 'success': False, + 'error': 'Database connection not available' + }), 500 + + # More robust JSON parsing + data = request.get_json(force=True) + if not data: + return jsonify({ + 'success': False, + 'error': 'No valid JSON data provided' + }), 400 + + try: + lat = float(data.get('lat')) + lon = float(data.get('lon')) + radius_km = float(data.get('radius', 1.0)) + except (TypeError, ValueError) as e: + return jsonify({ + 'success': False, + 'error': f'Invalid coordinates: lat={data.get("lat")}, lon={data.get("lon")}, radius={data.get("radius", 1.0)}' + }), 400 + + print(f"πŸ” Analyzing crashes at ({lat:.4f}, {lon:.4f}) within {radius_km}km...") + + # Get crashes within radius + crashes = get_crashes_within_radius_mongodb(mongo_collection, lat, lon, radius_km) + + # Serialize MongoDB documents to handle ObjectId + crashes_serialized = serialize_mongodb_doc(crashes) + + # Get current weather + weather_data, weather_summary = get_current_weather(lat, lon) + + # Generate safety analysis using LLM + safety_analysis = analyze_mongodb_crash_patterns( + crashes, lat, lon, radius_km, weather_summary + ) + + # Calculate some basic statistics + total_crashes = len(crashes) + avg_distance = sum(crash.get('distance_km', 0) for crash in crashes) / total_crashes if crashes else 0 + + # Extract crash summary stats + severity_counts = {} + total_casualties = 0 + for crash in crashes: + severity = crash.get('severity', 'Unknown') + severity_counts[severity] = severity_counts.get(severity, 0) + 1 + + casualties = crash.get('casualties', {}) + for category in ['bicyclists', 'drivers', 'pedestrians', 'passengers']: + if category in casualties: + cat_data = casualties[category] + total_casualties += (cat_data.get('fatal', 0) + + cat_data.get('major_injuries', 0) + + cat_data.get('minor_injuries', 0)) + + return jsonify({ + 'success': True, + 'location': {'lat': lat, 'lon': lon}, + 'radius_km': radius_km, + 'crash_summary': { + 'total_crashes': total_crashes, + 'avg_distance_km': round(avg_distance, 3), + 'severity_breakdown': severity_counts, + 'total_casualties': total_casualties + }, + 'weather': { + 'summary': weather_summary, + 'data': weather_data + }, + 'safety_analysis': safety_analysis, + 'raw_crashes': crashes_serialized[:10] if crashes_serialized else [] # Return first 10 for reference + }) + + except Exception as e: + print(f"❌ Error in crash analysis: {e}") + traceback.print_exc() + return jsonify({ + 'success': False, + 'error': str(e) + }), 500 + +@app.route('/api/find-safe-route', methods=['POST']) +def find_safe_route_endpoint(): + """Find the safest route between two points with crash analysis.""" + try: + if route_analyzer.collection is None: + return jsonify({ + 'success': False, + 'error': 'Route analyzer not available' + }), 500 + + data = request.get_json() + if not data: + return jsonify({ + 'success': False, + 'error': 'No route data provided' + }), 400 + + start_lat = float(data.get('start_lat')) + start_lon = float(data.get('start_lon')) + end_lat = float(data.get('end_lat')) + end_lon = float(data.get('end_lon')) + + print(f"πŸ›£οΈ Finding safe route from ({start_lat:.4f}, {start_lon:.4f}) to ({end_lat:.4f}, {end_lon:.4f})...") + + # Find the safest route + results = route_analyzer.find_safer_route(start_lat, start_lon, end_lat, end_lon) + + if 'error' in results: + return jsonify({ + 'success': False, + 'error': results['error'] + }), 500 + + # Extract key information for frontend + recommended_route = results['recommended_route'] + route_data = recommended_route['route_data'] + safety_data = recommended_route['safety_analysis'] + + # Prepare response + response_data = { + 'success': True, + 'start_coordinates': {'lat': start_lat, 'lon': start_lon}, + 'end_coordinates': {'lat': end_lat, 'lon': end_lon}, + 'recommended_route': { + 'coordinates': route_data['coordinates'], # For Mapbox visualization + 'distance_km': route_data['distance_km'], + 'duration_min': route_data['duration_min'], + 'geometry': route_data.get('geometry'), # GeoJSON for Mapbox + 'safety_score': safety_data['average_safety_score'], + 'crashes_nearby': safety_data['total_crashes_near_route'], + 'max_danger_score': safety_data['max_danger_score'] + }, + 'safety_analysis': results['safety_report'], + 'weather_summary': results.get('weather_summary'), + 'route_comparison': results.get('route_comparison'), + 'alternative_routes': [] + } + + # Add alternative routes if available + for alt_route in results.get('alternative_routes', []): + alt_data = alt_route['route_data'] + alt_safety = alt_route['safety_analysis'] + response_data['alternative_routes'].append({ + 'route_id': alt_data['route_id'], + 'coordinates': alt_data['coordinates'], + 'distance_km': alt_data['distance_km'], + 'duration_min': alt_data['duration_min'], + 'geometry': alt_data.get('geometry'), + 'safety_score': alt_safety['average_safety_score'], + 'crashes_nearby': alt_safety['total_crashes_near_route'] + }) + + return jsonify(response_data) + + except (TypeError, ValueError) as e: + return jsonify({ + 'success': False, + 'error': 'Invalid route coordinates provided' + }), 400 + except Exception as e: + print(f"❌ Error in route finding: {e}") + traceback.print_exc() + return jsonify({ + 'success': False, + 'error': str(e) + }), 500 + +@app.route('/api/get-single-route', methods=['POST']) +def get_single_route_endpoint(): + """Get a single route with safety analysis (simpler version).""" + try: + data = request.get_json() + if not data: + return jsonify({ + 'success': False, + 'error': 'No data provided' + }), 400 + + start_lat = float(data.get('start_lat')) + start_lon = float(data.get('start_lon')) + end_lat = float(data.get('end_lat')) + end_lon = float(data.get('end_lon')) + profile = data.get('profile', 'driving') # driving, walking, cycling + + # Get route from Mapbox + route_result = route_analyzer.get_route_from_mapbox( + start_lat, start_lon, end_lat, end_lon, profile + ) + + if not route_result.get('success'): + return jsonify({ + 'success': False, + 'error': route_result.get('error', 'Failed to get route') + }), 500 + + # Analyze route safety + safety_analysis = route_analyzer.analyze_route_safety(route_result['coordinates']) + + if 'error' in safety_analysis: + return jsonify({ + 'success': False, + 'error': safety_analysis['error'] + }), 500 + + # Get weather + weather_data, weather_summary = route_analyzer.get_current_weather(start_lat, start_lon) + + # Generate safety report + safety_report = route_analyzer.generate_safety_report_with_llm( + safety_analysis, route_result, weather_summary + ) + + return jsonify({ + 'success': True, + 'route': { + 'coordinates': route_result['coordinates'], + 'distance_km': route_result['distance_km'], + 'duration_min': route_result['duration_min'], + 'geometry': route_result.get('geometry'), + 'profile': profile + }, + 'safety': { + 'total_crashes_nearby': safety_analysis['total_crashes_near_route'], + 'average_safety_score': safety_analysis['average_safety_score'], + 'max_danger_score': safety_analysis['max_danger_score'], + 'safety_points': safety_analysis['safety_points'] + }, + 'safety_report': safety_report, + 'weather_summary': weather_summary + }) + + except Exception as e: + print(f"❌ Error getting single route: {e}") + traceback.print_exc() + return jsonify({ + 'success': False, + 'error': str(e) + }), 500 + +@app.errorhandler(404) +def not_found(error): + return jsonify({'success': False, 'error': 'Endpoint not found'}), 404 + +@app.errorhandler(500) +def internal_error(error): + return jsonify({'success': False, 'error': 'Internal server error'}), 500 + +if __name__ == '__main__': + print("πŸš€ Starting Flask API Server...") + print("πŸ“‘ Endpoints available:") + print(" - GET /api/health") + print(" - GET /api/weather?lat=X&lon=Y") + print(" - POST /api/analyze-crashes") + print(" - POST /api/find-safe-route") + print(" - POST /api/get-single-route") + print("\n🌐 Server running on http://localhost:5001") + + app.run(debug=True, host='0.0.0.0', port=5001) \ No newline at end of file diff --git a/llm/api/requirements.txt b/llm/api/requirements.txt new file mode 100644 index 0000000..8529332 --- /dev/null +++ b/llm/api/requirements.txt @@ -0,0 +1,6 @@ +Flask==3.0.0 +Flask-CORS==4.0.0 +pymongo==4.6.0 +requests==2.31.0 +langchain-google-genai==1.0.7 +python-dotenv==1.0.0 \ No newline at end of file diff --git a/llm/api/test_api.py b/llm/api/test_api.py new file mode 100644 index 0000000..adac202 --- /dev/null +++ b/llm/api/test_api.py @@ -0,0 +1,203 @@ +#!/usr/bin/env python3 +""" +Test script for Flask API endpoints. +""" + +import requests +import json +import time + +API_BASE = "http://localhost:5001/api" + +def test_health(): + """Test health endpoint""" + print("πŸ” Testing health endpoint...") + try: + response = requests.get(f"{API_BASE}/health") + print(f"Status: {response.status_code}") + data = response.json() + print(f"Response: {json.dumps(data, indent=2)}") + + if data.get('status') == 'healthy': + print("βœ… Health check passed!") + else: + print("⚠️ Health check shows issues") + return True + except Exception as e: + print(f"❌ Health check failed: {e}") + return False + finally: + print() + +def test_weather(): + """Test weather endpoint""" + print("🌀️ Testing weather endpoint...") + try: + # Test with Virginia Tech coordinates + response = requests.get(f"{API_BASE}/weather", params={'lat': 37.2284, 'lon': -80.4234}) + print(f"Status: {response.status_code}") + data = response.json() + + if data.get('success'): + print(f"βœ… Weather: {data['summary']}") + print(f" Coordinates: ({data['coordinates']['lat']}, {data['coordinates']['lon']})") + else: + print(f"❌ Weather API error: {data.get('error')}") + return data.get('success', False) + except Exception as e: + print(f"❌ Weather test failed: {e}") + return False + finally: + print() + +def test_crash_analysis(): + """Test crash analysis endpoint""" + print("🚨 Testing crash analysis endpoint...") + try: + payload = { + 'lat': 37.2284, # Virginia Tech + 'lon': -80.4234, + 'radius': 2.0 + } + response = requests.post(f"{API_BASE}/analyze-crashes", json=payload) + print(f"Status: {response.status_code}") + data = response.json() + + if data.get('success'): + print("βœ… Crash analysis successful!") + crash_summary = data['crash_summary'] + print(f" Total crashes: {crash_summary['total_crashes']}") + print(f" Total casualties: {crash_summary['total_casualties']}") + print(f" Average distance: {crash_summary['avg_distance_km']} km") + print(f" Weather: {data['weather']['summary']}") + + if crash_summary['severity_breakdown']: + print(" Severity breakdown:") + for severity, count in crash_summary['severity_breakdown'].items(): + print(f" - {severity}: {count}") + else: + print(f"❌ Crash analysis error: {data.get('error')}") + return data.get('success', False) + except Exception as e: + print(f"❌ Crash analysis test failed: {e}") + return False + finally: + print() + +def test_route_finding(): + """Test safe route finding endpoint""" + print("πŸ›£οΈ Testing route finding endpoint...") + try: + payload = { + 'start_lat': 37.2284, # Virginia Tech + 'start_lon': -80.4234, + 'end_lat': 37.2297, # Downtown Blacksburg + 'end_lon': -80.4139 + } + response = requests.post(f"{API_BASE}/find-safe-route", json=payload) + print(f"Status: {response.status_code}") + data = response.json() + + if data.get('success'): + print("βœ… Route finding successful!") + route = data['recommended_route'] + print(f" Distance: {route['distance_km']:.2f} km") + print(f" Duration: {route['duration_min']:.1f} minutes") + print(f" Crashes nearby: {route['crashes_nearby']}") + print(f" Safety score: {route['safety_score']:.3f}") + print(f" Coordinate points: {len(route['coordinates'])}") + + if data.get('weather_summary'): + print(f" Weather: {data['weather_summary']}") + + print(f" Alternative routes: {len(data['alternative_routes'])}") + else: + print(f"❌ Route finding error: {data.get('error')}") + return data.get('success', False) + except Exception as e: + print(f"❌ Route finding test failed: {e}") + return False + finally: + print() + +def test_single_route(): + """Test single route endpoint""" + print("πŸ—ΊοΈ Testing single route endpoint...") + try: + payload = { + 'start_lat': 37.2284, # Virginia Tech + 'start_lon': -80.4234, + 'end_lat': 37.2297, # Downtown Blacksburg + 'end_lon': -80.4139, + 'profile': 'driving' + } + response = requests.post(f"{API_BASE}/get-single-route", json=payload) + print(f"Status: {response.status_code}") + data = response.json() + + if data.get('success'): + print("βœ… Single route successful!") + route = data['route'] + safety = data['safety'] + print(f" Distance: {route['distance_km']:.2f} km") + print(f" Duration: {route['duration_min']:.1f} minutes") + print(f" Profile: {route['profile']}") + print(f" Total crashes nearby: {safety['total_crashes_nearby']}") + print(f" Safety score: {safety['average_safety_score']:.3f}") + print(f" Max danger score: {safety['max_danger_score']:.3f}") + + if data.get('weather_summary'): + print(f" Weather: {data['weather_summary']}") + else: + print(f"❌ Single route error: {data.get('error')}") + return data.get('success', False) + except Exception as e: + print(f"❌ Single route test failed: {e}") + return False + finally: + print() + +def main(): + print("πŸ§ͺ Testing Flask API Endpoints") + print("=" * 50) + + # Check if server is running + try: + requests.get(f"{API_BASE}/health", timeout=5) + except requests.exceptions.ConnectionError: + print("❌ Could not connect to Flask server.") + print(" Make sure the server is running: python api/flask_server.py") + return + except Exception as e: + print(f"❌ Error connecting to server: {e}") + return + + # Run all tests + results = [] + results.append(("Health Check", test_health())) + results.append(("Weather API", test_weather())) + results.append(("Crash Analysis", test_crash_analysis())) + results.append(("Route Finding", test_route_finding())) + results.append(("Single Route", test_single_route())) + + # Summary + print("=" * 50) + print("🎯 TEST SUMMARY:") + print("=" * 50) + + passed = 0 + for test_name, result in results: + status = "βœ… PASSED" if result else "❌ FAILED" + print(f" {test_name:<20} {status}") + if result: + passed += 1 + + print(f"\nResults: {passed}/{len(results)} tests passed") + + if passed == len(results): + print("πŸŽ‰ All tests passed! Flask API is ready for Next.js integration!") + else: + print("⚠️ Some tests failed. Please check the server logs.") + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/llm/api/test_crash_endpoint.py b/llm/api/test_crash_endpoint.py new file mode 100644 index 0000000..6b41aab --- /dev/null +++ b/llm/api/test_crash_endpoint.py @@ -0,0 +1,126 @@ +#!/usr/bin/env python3 +""" +Quick test script for the crash analysis endpoint +""" + +import requests +import json + +def test_crash_analysis(): + """Test the crash analysis endpoint""" + + url = "http://localhost:5001/api/analyze-crashes" + + # Test data - Washington DC coordinates + payload = { + "lat": 38.9072, + "lon": -77.0369, + "radius": 1.0 + } + + headers = { + "Content-Type": "application/json" + } + + print("πŸ§ͺ Testing Crash Analysis Endpoint") + print("=" * 50) + print(f"URL: {url}") + print(f"Payload: {json.dumps(payload, indent=2)}") + print(f"Headers: {headers}") + print() + + try: + print("πŸ“‘ Sending request...") + response = requests.post(url, json=payload, headers=headers, timeout=30) + + print(f"πŸ“Š Response Status: {response.status_code}") + print(f"πŸ“‹ Response Headers: {dict(response.headers)}") + print() + + if response.status_code == 200: + data = response.json() + if data.get('success'): + print("βœ… SUCCESS! Crash analysis endpoint is working!") + print() + print("πŸ“ˆ Results Summary:") + crash_summary = data.get('crash_summary', {}) + print(f" β€’ Total crashes: {crash_summary.get('total_crashes', 'N/A')}") + print(f" β€’ Average distance: {crash_summary.get('avg_distance_km', 'N/A')} km") + print(f" β€’ Total casualties: {crash_summary.get('total_casualties', 'N/A')}") + + weather = data.get('weather', {}) + print(f" β€’ Weather: {weather.get('summary', 'N/A')}") + + safety_analysis = data.get('safety_analysis', '') + print(f" β€’ Safety analysis length: {len(safety_analysis)} characters") + + raw_crashes = data.get('raw_crashes', []) + print(f" β€’ Sample crashes returned: {len(raw_crashes)}") + + return True + else: + print(f"❌ API returned success=False: {data.get('error', 'Unknown error')}") + return False + + else: + print(f"❌ HTTP Error {response.status_code}") + try: + error_data = response.json() + print(f"Error details: {error_data}") + except: + print(f"Response text: {response.text}") + return False + + except requests.exceptions.ConnectionError: + print("❌ Connection Error: Cannot connect to Flask server") + print(" Make sure the Flask server is running on http://localhost:5001") + print(" Start it with: cd llm && python api/flask_server.py") + return False + + except requests.exceptions.Timeout: + print("❌ Timeout Error: Request took too long (>30 seconds)") + print(" This might be normal for the first request as it loads data") + return False + + except Exception as e: + print(f"❌ Unexpected Error: {e}") + return False + +def test_health_first(): + """Test health endpoint first to make sure server is running""" + try: + response = requests.get("http://localhost:5001/api/health", timeout=5) + if response.status_code == 200: + data = response.json() + print("βœ… Health check passed") + print(f" β€’ MongoDB connected: {data.get('mongodb_connected')}") + print(f" β€’ Route analyzer ready: {data.get('route_analyzer_ready')}") + return True + else: + print(f"❌ Health check failed: {response.status_code}") + return False + except Exception as e: + print(f"❌ Health check error: {e}") + return False + +if __name__ == "__main__": + print("πŸš€ Flask Server Crash Analysis Test") + print("=" * 60) + + # Test health first + if not test_health_first(): + print("\nπŸ’‘ Server not responding. Start it with:") + print(" cd /Users/shivapochampally/Documents/competitions/VTHacks13/llm") + print(" python api/flask_server.py") + exit(1) + + print() + + # Test crash analysis + success = test_crash_analysis() + + print("\n" + "=" * 60) + if success: + print("πŸŽ‰ All tests passed! Your crash analysis endpoint is working perfectly!") + else: + print("❌ Test failed. Check the error messages above.") \ No newline at end of file diff --git a/llm/flask_server.log b/llm/flask_server.log new file mode 100644 index 0000000..ea6084c --- /dev/null +++ b/llm/flask_server.log @@ -0,0 +1,50 @@ +βœ… Successfully imported Python modules +βœ… Connected to MongoDB for route safety analysis +Connecting to MongoDB... +βœ… Successfully connected to MongoDB! +πŸ“Š Found 337,113 total crash records in database +πŸ“… Found 112,964 crash records from 2020 onward +πŸš€ Starting Flask API Server... +πŸ“‘ Endpoints available: + - GET /api/health + - GET /api/weather?lat=X&lon=Y + - POST /api/analyze-crashes + - POST /api/find-safe-route + - POST /api/get-single-route + +🌐 Server running on http://localhost:5001 + * Serving Flask app 'flask_server' + * Debug mode: on +WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. + * Running on all addresses (0.0.0.0) + * Running on http://127.0.0.1:5001 + * Running on http://100.110.69.195:5001 +Press CTRL+C to quit + * Restarting with watchdog (fsevents) + * Debugger is active! + * Debugger PIN: 649-846-112 +127.0.0.1 - - [28/Sep/2025 01:55:17] "GET /api/health HTTP/1.1" 200 - +127.0.0.1 - - [28/Sep/2025 01:55:22] "POST /api/analyze-crashes HTTP/1.1" 400 - + * Detected change in '/Users/shivapochampally/Documents/competitions/VTHacks13/llm/api/flask_server.py', reloading + * Detected change in '/Users/shivapochampally/Documents/competitions/VTHacks13/llm/api/flask_server.py', reloading +βœ… Successfully imported Python modules +βœ… Connected to MongoDB for route safety analysis +Connecting to MongoDB... +βœ… Successfully connected to MongoDB! +πŸ“Š Found 337,113 total crash records in database +πŸ“… Found 112,964 crash records from 2020 onward +πŸš€ Starting Flask API Server... +πŸ“‘ Endpoints available: + - GET /api/health + - GET /api/weather?lat=X&lon=Y + - POST /api/analyze-crashes + - POST /api/find-safe-route + - POST /api/get-single-route + +🌐 Server running on http://localhost:5001 +πŸ” Analyzing crashes at (38.9072, -77.0369) within 1.0km... +πŸ” Querying crashes within 1.0km of (38.907200, -77.036900) from 2020 onward... +πŸ“ Found 5944 crashes within 1.0km radius (from 2020 onward) + * Restarting with watchdog (fsevents) + * Debugger is active! + * Debugger PIN: 649-846-112 diff --git a/llm/gemini_mongo_mateo.py b/llm/gemini_mongo_mateo.py index 32d5709..9ac93ab 100644 --- a/llm/gemini_mongo_mateo.py +++ b/llm/gemini_mongo_mateo.py @@ -12,7 +12,7 @@ from math import radians, sin, cos, sqrt, atan2 GEMINI_API_KEY = "AIzaSyBCbEOo4aK72507hqvpYkE9zXUe-z5aSXA" MONGO_URI = "mongodb+srv://Admin:HelloKitty420@geobase.tyxsoir.mongodb.net/crashes" -llm = ChatGoogleGenerativeAI(model="gemini-2.5-flash-lite", api_key=GEMINI_API_KEY) +llm = ChatGoogleGenerativeAI(model="gemini-2.5-flash-lite", google_api_key=GEMINI_API_KEY) def connect_to_mongodb(): """ diff --git a/llm/gemini_reroute_mateo.py b/llm/gemini_reroute_mateo.py index 12ad10b..ec72516 100644 --- a/llm/gemini_reroute_mateo.py +++ b/llm/gemini_reroute_mateo.py @@ -15,7 +15,7 @@ GEMINI_API_KEY = "AIzaSyBCbEOo4aK72507hqvpYkE9zXUe-z5aSXA" MONGO_URI = "mongodb+srv://Admin:HelloKitty420@geobase.tyxsoir.mongodb.net/crashes" MAPBOX_API_KEY = "pk.eyJ1IjoicGllbG9yZDc1NyIsImEiOiJjbWcxdTd6c3AwMXU1MmtxMDh6b2l5amVrIn0.5Es0azrah23GX1e9tmbjGw" -llm = ChatGoogleGenerativeAI(model="gemini-2.5-flash-lite", api_key=GEMINI_API_KEY) +llm = ChatGoogleGenerativeAI(model="gemini-2.5-flash-lite", google_api_key=GEMINI_API_KEY) class SafeRouteAnalyzer: def __init__(self, mongo_uri: str):