import dash
from dash import dcc, html, Input, Output, State, callback_context
import dash_bootstrap_components as dbc
import folium
from folium.plugins import MarkerCluster
import pandas as pd
import numpy as np
import requests
import json
import os
import mlx.core as mx
import mlx.nn as nn
from transformers import AutoTokenizer
from typing import List, Dict, Optional
import threading
import time
import re
# DeepSeek model setup
MODEL_PATH = "/Users/martinrivera/deepseek_v3_1_4bit_mlx/deepseek_v3_4bit"
# Landmark coordinates dictionary
landmark_coordinates = {
"Grand Canyon": {"lat": 36.055261, "lon": -112.121836},
"Statue of Liberty": {"lat": 40.689167, "lon": -74.044444},
"White House": {"lat": 38.897778, "lon": -77.036389},
"Eiffel Tower": {"lat": 48.858222, "lon": 2.2945},
"Louvre Museum": {"lat": 48.861111, "lon": 2.335833},
"Notre-Dame Cathedral": {"lat": 48.853056, "lon": 2.35},
"Mount Fuji": {"lat": 35.360833, "lon": 138.7275},
"Tokyo Tower": {"lat": 35.658611, "lon": 139.745556},
"Imperial Palace": {"lat": 35.6825, "lon": 139.7521},
"Taj Mahal": {"lat": 27.175, "lon": 78.041944},
"Red Fort": {"lat": 28.655833, "lon": 77.240833},
"Gateway of India": {"lat": 18.955668, "lon": 72.834001},
"Christ the Redeemer": {"lat": -22.951944, "lon": -43.210556},
"Amazon Rainforest": {"lat": -3, "lon": -60},
"Iguazu Falls": {"lat": -25.686667, "lon": -54.444722},
"Pyramids of Giza": {"lat": 29.9725, "lon": 31.128333},
"Sphinx": {"lat": 29.97526, "lon": 31.13758},
"Valley of the Kings": {"lat": 25.740833, "lon": 32.602222},
"Sydney Opera House": {"lat": -33.85681, "lon": 151.21514},
"Great Barrier Reef": {"lat": -16.4, "lon": 145.8},
"Uluru": {"lat": -25.345, "lon": 131.036111},
"Colosseum": {"lat": 41.890278, "lon": 12.492222},
"Leaning Tower of Pisa": {"lat": 43.723056, "lon": 10.396389},
"Venice Canals": {"lat": 45.4408, "lon": 12.3155}, # Corrected coordinates for Venice
"Great Wall of China": {"lat": 40.68, "lon": 117.23},
"Forbidden City": {"lat": 39.915833, "lon": 116.390833},
"Terracotta Army": {"lat": 34.385, "lon": 109.273056},
"Big Ben": {"lat": 51.5007, "lon": -0.1245},
"Buckingham Palace": {"lat": 51.500833, "lon": -0.141944},
"Stonehenge": {"lat": 51.178889, "lon": -1.826111}
}
# Sample data for countries, capitals, and landmarks with precise coordinates
country_data = [
{
"country": "France",
"capital": "Paris",
"lat": 48.8566,
"lon": 2.3522,
"landmarks": [
{"name": "Eiffel Tower", "lat": 48.858222, "lon": 2.2945},
{"name": "Louvre Museum", "lat": 48.861111, "lon": 2.335833},
{"name": "Notre-Dame Cathedral", "lat": 48.853056, "lon": 2.35}
]
},
{
"country": "United States",
"capital": "Washington D.C.",
"lat": 38.9072,
"lon": -77.0369,
"landmarks": [
{"name": "White House", "lat": 38.897778, "lon": -77.036389},
{"name": "Statue of Liberty", "lat": 40.689167, "lon": -74.044444},
{"name": "Grand Canyon", "lat": 36.055261, "lon": -112.121836}
]
},
{
"country": "Japan",
"capital": "Tokyo",
"lat": 35.6762,
"lon": 139.6503,
"landmarks": [
{"name": "Mount Fuji", "lat": 35.360833, "lon": 138.7275},
{"name": "Tokyo Tower", "lat": 35.658611, "lon": 139.745556},
{"name": "Imperial Palace", "lat": 35.6825, "lon": 139.7521}
]
},
{
"country": "India",
"capital": "New Delhi",
"lat": 28.6139,
"lon": 77.2090,
"landmarks": [
{"name": "Taj Mahal", "lat": 27.175, "lon": 78.041944},
{"name": "Red Fort", "lat": 28.655833, "lon": 77.240833},
{"name": "Gateway of India", "lat": 18.955668, "lon": 72.834001}
]
},
{
"country": "Brazil",
"capital": "BrasΓlia",
"lat": -15.7975,
"lon": -47.8919,
"landmarks": [
{"name": "Christ the Redeemer", "lat": -22.951944, "lon": -43.210556},
{"name": "Amazon Rainforest", "lat": -3, "lon": -60},
{"name": "Iguazu Falls", "lat": -25.686667, "lon": -54.444722}
]
},
{
"country": "Egypt",
"capital": "Cairo",
"lat": 30.0444,
"lon": 31.2357,
"landmarks": [
{"name": "Pyramids of Giza", "lat": 29.9725, "lon": 31.128333},
{"name": "Sphinx", "lat": 29.97526, "lon": 31.13758},
{"name": "Valley of the Kings", "lat": 25.740833, "lon": 32.602222}
]
},
{
"country": "Australia",
"capital": "Canberra",
"lat": -35.2809,
"lon": 149.1300,
"landmarks": [
{"name": "Sydney Opera House", "lat": -33.85681, "lon": 151.21514},
{"name": "Great Barrier Reef", "lat": -16.4, "lon": 145.8},
{"name": "Uluru", "lat": -25.345, "lon": 131.036111}
]
},
{
"country": "Italy",
"capital": "Rome",
"lat": 41.9028,
"lon": 12.4964,
"landmarks": [
{"name": "Colosseum", "lat": 41.890278, "lon": 12.492222},
{"name": "Leaning Tower of Pisa", "lat": 43.723056, "lon": 10.396389},
{"name": "Venice Canals", "lat": 45.4408, "lon": 12.3155}
]
},
{
"country": "China",
"capital": "Beijing",
"lat": 39.9042,
"lon": 116.4074,
"landmarks": [
{"name": "Great Wall of China", "lat": 40.68, "lon": 117.23},
{"name": "Forbidden City", "lat": 39.915833, "lon": 116.390833},
{"name": "Terracotta Army", "lat": 34.385, "lon": 109.273056}
]
},
{
"country": "United Kingdom",
"capital": "London",
"lat": 51.5074,
"lon": -0.1278,
"landmarks": [
{"name": "Big Ben", "lat": 51.5007, "lon": -0.1245},
{"name": "Buckingham Palace", "lat": 51.500833, "lon": -0.141944},
{"name": "Stonehenge", "lat": 51.178889, "lon": -1.826111}
]
}
]
df = pd.DataFrame(country_data)
class DeepSeekModel:
def __init__(self, model_path: str):
self.model_path = model_path
self.tokenizer = AutoTokenizer.from_pretrained(model_path)
self.model = None
self.is_loaded = False
self.load_lock = threading.Lock()
self.country_data = country_data
def load_model(self):
"""Load the model in a separate thread to avoid blocking"""
if not self.is_loaded:
with self.load_lock:
if not self.is_loaded:
try:
# This would need to be implemented based on MLX's model loading
# For now, we'll use a placeholder
print("Loading DeepSeek model...")
time.sleep(2) # Simulate loading time
self.is_loaded = True
print("Model loaded successfully")
except Exception as e:
print(f"Error loading model: {e}")
def extract_country_from_query(self, prompt: str) -> str:
"""Extract country name from user query"""
prompt_lower = prompt.lower()
# Check for direct country mentions
for country in self.country_data:
if country['country'].lower() in prompt_lower:
return country['country']
# Check for capital mentions that might reference a country
for country in self.country_data:
if country['capital'].lower() in prompt_lower:
return country['country']
# Check for landmark mentions
for country in self.country_data:
for landmark in country['landmarks']:
if landmark['name'].lower() in prompt_lower:
return country['country']
return None
def get_landmark_coordinates(self, landmark_name: str) -> Optional[Dict]:
"""Get coordinates for a specific landmark"""
for country in self.country_data:
for landmark in country['landmarks']:
if landmark['name'].lower() == landmark_name.lower():
return {"lat": landmark['lat'], "lon": landmark['lon']}
return None
def generate_response(self, prompt: str, max_tokens: int = 200) -> str:
"""Generate response using DeepSeek model with country data integration"""
if not self.is_loaded:
return "Model is still loading. Please wait..."
try:
# Extract country from query
country_name = self.extract_country_from_query(prompt)
# Check for specific landmark queries
for country in self.country_data:
for landmark in country['landmarks']:
if landmark['name'].lower() in prompt.lower():
return f"The {landmark['name']} is located in {country['country']} at coordinates {landmark['lat']:.6f}, {landmark['lon']:.6f}. It's one of the most famous landmarks in {country['country']}."
# If we found a country, provide specific information
if country_name:
country_info = next((c for c in self.country_data if c['country'] == country_name), None)
if country_info:
if "capital" in prompt.lower():
return f"The capital of {country_info['country']} is {country_info['capital']}. It's located at coordinates {country_info['lat']:.4f}, {country_info['lon']:.4f}."
elif "landmark" in prompt.lower() or "landmarks" in prompt.lower():
landmarks = ", ".join([landmark['name'] for landmark in country_info['landmarks']])
return f"Famous landmarks in {country_info['country']} include: {landmarks}."
elif "coordinates" in prompt.lower() or "location" in prompt.lower() or "where" in prompt.lower():
landmarks_info = "\n".join([
f"- {landmark['name']}: {landmark['lat']:.6f}, {landmark['lon']:.6f}"
for landmark in country_info['landmarks']
])
return f"Coordinates for landmarks in {country_info['country']}:\n{landmarks_info}"
else:
# General information about the country
landmarks = ", ".join([landmark['name'] for landmark in country_info['landmarks']])
return f"{country_info['country']} has {country_info['capital']} as its capital. Famous landmarks include: {landmarks}. Capital coordinates: {country_info['lat']:.4f}, {country_info['lon']:.4f}."
# Handle general queries about all countries
if "all countries" in prompt.lower() or "list countries" in prompt.lower():
countries = ", ".join([c['country'] for c in self.country_data])
return f"The countries in our database are: {countries}."
if "all capitals" in prompt.lower():
capitals = ", ".join([f"{c['capital']} ({c['country']})" for c in self.country_data])
return f"The capitals in our database are: {capitals}."
if "all landmarks" in prompt.lower():
response = "Famous landmarks by country:\n"
for country in self.country_data:
landmarks = ", ".join([landmark['name'] for landmark in country['landmarks']])
response += f"{country['country']}: {landmarks}\n"
return response
# Default response for other queries
return "I'd be happy to help you explore world geography! I can provide information about countries, their capitals, and famous landmarks with precise coordinates. Try asking about a specific country, landmark, or location."
except Exception as e:
return f"Error generating response: {str(e)}"
# Initialize model
deepseek_model = DeepSeekModel(MODEL_PATH)
# Start loading model in background
loading_thread = threading.Thread(target=deepseek_model.load_model)
loading_thread.daemon = True
loading_thread.start()
# Create initial map
def create_world_map():
world_map = folium.Map(location=[20, 0], zoom_start=2, tiles='OpenStreetMap')
marker_cluster = MarkerCluster().add_to(world_map)
for _, row in df.iterrows():
# Country capital marker
folium.Marker(
location=[row['lat'], row['lon']],
popup=f"""
Country: {row['country']}
Capital: {row['capital']}
Coordinates: {row['lat']:.6f}, {row['lon']:.6f}
Famous Landmarks: {', '.join([landmark['name'] for landmark in row['landmarks']])}
""",
tooltip=f"Click for info about {row['country']}",
icon=folium.Icon(color='blue', icon='flag')
).add_to(marker_cluster)
# Add landmarks with precise coordinates
for landmark in row['landmarks']:
folium.Marker(
location=[landmark['lat'], landmark['lon']],
popup=f"""
Landmark: {landmark['name']}
Country: {row['country']}
Coordinates: {landmark['lat']:.6f}, {landmark['lon']:.6f}
""",
tooltip=landmark['name'],
icon=folium.Icon(color='green', icon='camera')
).add_to(marker_cluster)
return world_map
# Initialize Dash app
app = dash.Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
app.title = "World Explorer with DeepSeek AI"
# Layout
app.layout = dbc.Container([
dbc.Row([
dbc.Col([
html.H1("π World Explorer with DeepSeek AI",
className="text-center mb-4", style={'color': '#2c3e50'})
], width=12)
]),
dbc.Row([
dbc.Col([
dbc.Card([
dbc.CardHeader("πΊοΈ Interactive World Map", className="bg-primary text-white"),
dbc.CardBody([
html.Iframe(
id='world-map',
srcDoc=create_world_map()._repr_html_(),
width='100%',
height='500'
)
])
], className="mb-4")
], width=8),
dbc.Col([
dbc.Card([
dbc.CardHeader("π¬ DeepSeek AI Assistant", className="bg-success text-white"),
dbc.CardBody([
dcc.Textarea(
id='user-input',
placeholder='Ask about countries, capitals, landmarks, or coordinates...',
style={'width': '100%', 'height': '100px', 'margin-bottom': '10px'}
),
dbc.Button("Ask DeepSeek", id='ask-button', color="primary", className="w-100 mb-3"),
dbc.Alert("Model is loading...", id="model-status", color="warning", className="mb-3"),
html.Div(id='ai-response', style={
'height': '300px',
'overflow-y': 'auto',
'padding': '10px',
'border': '1px solid #ddd',
'border-radius': '5px',
'background-color': '#f8f9fa'
})
])
])
], width=4)
]),
dbc.Row([
dbc.Col([
dbc.Card([
dbc.CardHeader("π Country Information", className="bg-info text-white"),
dbc.CardBody([
dcc.Dropdown(
id='country-selector',
options=[{'label': country, 'value': country} for country in df['country']],
value='France',
clearable=False
),
html.Div(id='country-info', style={'margin-top': '15px'})
])
])
], width=12)
], className="mt-4"),
# Hidden div to trigger model loading check
html.Div(id='hidden-div', style={'display': 'none'})
], fluid=True)
# Callbacks
@app.callback(
Output('model-status', 'children'),
Output('model-status', 'color'),
Input('hidden-div', 'children')
)
def check_model_status(_):
if deepseek_model.is_loaded:
return "Model loaded and ready!", "success"
else:
return "Model is still loading...", "warning"
@app.callback(
Output('ai-response', 'children'),
Input('ask-button', 'n_clicks'),
State('user-input', 'value')
)
def generate_ai_response(n_clicks, user_input):
if n_clicks is None or not user_input:
return "Enter a question about countries, capitals, landmarks, or coordinates above!"
response = deepseek_model.generate_response(user_input)
return html.Div([
html.P("π€ DeepSeek Response:", style={'font-weight': 'bold', 'color': '#28a745'}),
html.P(response, style={'white-space': 'pre-wrap'})
])
@app.callback(
Output('country-info', 'children'),
Input('country-selector', 'value')
)
def update_country_info(selected_country):
country = df[df['country'] == selected_country].iloc[0]
landmarks_list = html.Ul([
html.Li(f"{landmark['name']} ({landmark['lat']:.6f}, {landmark['lon']:.6f})")
for landmark in country['landmarks']
])
return html.Div([
html.H4(f"πΊπ³ {country['country']}"),
html.P(f"π Capital: {country['capital']}"),
html.P(f"π Coordinates: {country['lat']:.6f}, {country['lon']:.6f}"),
html.H5("ποΈ Famous Landmarks with Coordinates:"),
landmarks_list
])
@app.callback(
Output('world-map', 'srcDoc'),
Input('country-selector', 'value')
)
def update_map(selected_country):
world_map = create_world_map()
# Center map on selected country
country_data = df[df['country'] == selected_country].iloc[0]
world_map.location = [country_data['lat'], country_data['lon']]
world_map.zoom_start = 5
return world_map._repr_html_()
if __name__ == '__main__':
app.run(debug=True, port=8050)