diff --git a/llm/__pycache__/gemini_mongo_mateo.cpython-312.pyc b/llm/__pycache__/gemini_mongo_mateo.cpython-312.pyc
index 8bcd0af..b6cb1d2 100644
Binary files a/llm/__pycache__/gemini_mongo_mateo.cpython-312.pyc and b/llm/__pycache__/gemini_mongo_mateo.cpython-312.pyc differ
diff --git a/llm/__pycache__/gemini_reroute_mateo.cpython-312.pyc b/llm/__pycache__/gemini_reroute_mateo.cpython-312.pyc
index 00678c8..22ef67d 100644
Binary files a/llm/__pycache__/gemini_reroute_mateo.cpython-312.pyc and b/llm/__pycache__/gemini_reroute_mateo.cpython-312.pyc differ
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):