Spaces:
Build error
Build error
chore: update requirements, add local offline map tiles and test scripts
Browse files- assets/tiles/13/4348/2912.png +0 -0
- assets/tiles/13/4348/2913.png +0 -0
- assets/tiles/13/4349/2912.png +0 -0
- assets/tiles/13/4349/2913.png +0 -0
- assets/tiles/14/8697/5824.png +0 -0
- assets/tiles/14/8697/5825.png +0 -0
- assets/tiles/14/8697/5826.png +0 -0
- assets/tiles/14/8698/5824.png +0 -0
- assets/tiles/14/8698/5825.png +0 -0
- assets/tiles/14/8698/5826.png +0 -0
- assets/tiles/14/8699/5824.png +0 -0
- assets/tiles/14/8699/5825.png +0 -0
- assets/tiles/14/8699/5826.png +0 -0
- assets/tiles/15/17395/11648.png +0 -0
- assets/tiles/15/17395/11649.png +0 -0
- assets/tiles/15/17395/11650.png +0 -0
- assets/tiles/15/17395/11651.png +0 -0
- assets/tiles/15/17395/11652.png +0 -0
- assets/tiles/15/17395/11653.png +0 -0
- assets/tiles/15/17396/11648.png +0 -0
- assets/tiles/15/17396/11649.png +0 -0
- assets/tiles/15/17396/11650.png +0 -0
- assets/tiles/15/17396/11651.png +0 -0
- assets/tiles/15/17396/11652.png +0 -0
- assets/tiles/15/17396/11653.png +0 -0
- assets/tiles/15/17397/11648.png +0 -0
- assets/tiles/15/17397/11649.png +0 -0
- assets/tiles/15/17397/11650.png +0 -0
- assets/tiles/15/17397/11651.png +0 -0
- assets/tiles/15/17397/11652.png +0 -0
- assets/tiles/15/17397/11653.png +0 -0
- assets/tiles/15/17398/11648.png +0 -0
- assets/tiles/15/17398/11649.png +0 -0
- assets/tiles/15/17398/11650.png +0 -0
- assets/tiles/15/17398/11651.png +0 -0
- assets/tiles/15/17398/11652.png +0 -0
- assets/tiles/15/17398/11653.png +0 -0
- assets/tiles/15/17399/11648.png +0 -0
- assets/tiles/15/17399/11649.png +0 -0
- assets/tiles/15/17399/11650.png +0 -0
- assets/tiles/15/17399/11651.png +0 -0
- assets/tiles/15/17399/11652.png +0 -0
- assets/tiles/15/17399/11653.png +0 -0
- requirements.txt +3 -3
- scratch/test_chat.py +35 -0
- scratch/test_model.py +31 -0
- scratch/test_phase3.py +80 -0
assets/tiles/13/4348/2912.png
ADDED
|
assets/tiles/13/4348/2913.png
ADDED
|
assets/tiles/13/4349/2912.png
ADDED
|
assets/tiles/13/4349/2913.png
ADDED
|
assets/tiles/14/8697/5824.png
ADDED
|
assets/tiles/14/8697/5825.png
ADDED
|
assets/tiles/14/8697/5826.png
ADDED
|
assets/tiles/14/8698/5824.png
ADDED
|
assets/tiles/14/8698/5825.png
ADDED
|
assets/tiles/14/8698/5826.png
ADDED
|
assets/tiles/14/8699/5824.png
ADDED
|
assets/tiles/14/8699/5825.png
ADDED
|
assets/tiles/14/8699/5826.png
ADDED
|
assets/tiles/15/17395/11648.png
ADDED
|
assets/tiles/15/17395/11649.png
ADDED
|
assets/tiles/15/17395/11650.png
ADDED
|
assets/tiles/15/17395/11651.png
ADDED
|
assets/tiles/15/17395/11652.png
ADDED
|
assets/tiles/15/17395/11653.png
ADDED
|
assets/tiles/15/17396/11648.png
ADDED
|
assets/tiles/15/17396/11649.png
ADDED
|
assets/tiles/15/17396/11650.png
ADDED
|
assets/tiles/15/17396/11651.png
ADDED
|
assets/tiles/15/17396/11652.png
ADDED
|
assets/tiles/15/17396/11653.png
ADDED
|
assets/tiles/15/17397/11648.png
ADDED
|
assets/tiles/15/17397/11649.png
ADDED
|
assets/tiles/15/17397/11650.png
ADDED
|
assets/tiles/15/17397/11651.png
ADDED
|
assets/tiles/15/17397/11652.png
ADDED
|
assets/tiles/15/17397/11653.png
ADDED
|
assets/tiles/15/17398/11648.png
ADDED
|
assets/tiles/15/17398/11649.png
ADDED
|
assets/tiles/15/17398/11650.png
ADDED
|
assets/tiles/15/17398/11651.png
ADDED
|
assets/tiles/15/17398/11652.png
ADDED
|
assets/tiles/15/17398/11653.png
ADDED
|
assets/tiles/15/17399/11648.png
ADDED
|
assets/tiles/15/17399/11649.png
ADDED
|
assets/tiles/15/17399/11650.png
ADDED
|
assets/tiles/15/17399/11651.png
ADDED
|
assets/tiles/15/17399/11652.png
ADDED
|
assets/tiles/15/17399/11653.png
ADDED
|
requirements.txt
CHANGED
|
@@ -1,12 +1,12 @@
|
|
| 1 |
-
gradio==
|
| 2 |
pandas
|
| 3 |
numpy
|
| 4 |
requests
|
| 5 |
-
huggingface_hub>=
|
| 6 |
gpxpy
|
| 7 |
folium
|
| 8 |
plotly
|
| 9 |
-
pydantic>=2.
|
| 10 |
Pillow
|
| 11 |
# ASR: transformers + torch as fallback for Hugging Face (no pywhispercpp available there)
|
| 12 |
# transformers
|
|
|
|
| 1 |
+
gradio[oauth,mcp]==6.18.0
|
| 2 |
pandas
|
| 3 |
numpy
|
| 4 |
requests
|
| 5 |
+
huggingface_hub>=1.2.0,<2.0
|
| 6 |
gpxpy
|
| 7 |
folium
|
| 8 |
plotly
|
| 9 |
+
pydantic>=2.11.10,<2.12.5
|
| 10 |
Pillow
|
| 11 |
# ASR: transformers + torch as fallback for Hugging Face (no pywhispercpp available there)
|
| 12 |
# transformers
|
scratch/test_chat.py
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
from llama_cpp import Llama
|
| 3 |
+
|
| 4 |
+
model_path = "./model/gemma-1.1-2b-it-Q4_K_M.gguf"
|
| 5 |
+
model = Llama(
|
| 6 |
+
model_path=model_path,
|
| 7 |
+
n_ctx=2048,
|
| 8 |
+
verbose=False
|
| 9 |
+
)
|
| 10 |
+
|
| 11 |
+
system_prompt = (
|
| 12 |
+
"You are Trailhead Guide, a wilderness first-aid advisor.\n"
|
| 13 |
+
"Answer the query using ONLY the provided guide context.\n"
|
| 14 |
+
"Context:\n### Section 5: Musculoskeletal Injuries (Sprains & Strains)\n"
|
| 15 |
+
"1. Rest: Avoid weight bearing.\n"
|
| 16 |
+
"2. Ice: Apply cold compress.\n"
|
| 17 |
+
"3. Compression: Wrap joint firmly.\n"
|
| 18 |
+
"4. Elevation: Elevate joint above heart level.\n\n"
|
| 19 |
+
"Keep the instructions clear, numbered, and precise.\n"
|
| 20 |
+
"Cite: 'Sources: Section 5'."
|
| 21 |
+
)
|
| 22 |
+
|
| 23 |
+
messages = [
|
| 24 |
+
{"role": "user", "content": f"{system_prompt}\n\nUser Query: knee sprain"}
|
| 25 |
+
]
|
| 26 |
+
|
| 27 |
+
print("Running chat completions...")
|
| 28 |
+
response = model.create_chat_completion(
|
| 29 |
+
messages=messages,
|
| 30 |
+
max_tokens=256,
|
| 31 |
+
temperature=0.3,
|
| 32 |
+
stream=False
|
| 33 |
+
)
|
| 34 |
+
|
| 35 |
+
print(response['choices'][0]['message']['content'])
|
scratch/test_model.py
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
from llama_cpp import Llama
|
| 3 |
+
from huggingface_hub import hf_hub_download
|
| 4 |
+
|
| 5 |
+
MODEL_REPO = "bartowski/gemma-1.1-2b-it-GGUF"
|
| 6 |
+
MODEL_FILE = "gemma-1.1-2b-it-Q4_K_M.gguf"
|
| 7 |
+
LOCAL_MODEL_DIR = "./model"
|
| 8 |
+
|
| 9 |
+
model_path = os.path.join(LOCAL_MODEL_DIR, MODEL_FILE)
|
| 10 |
+
if not os.path.exists(model_path):
|
| 11 |
+
print("Downloading model...")
|
| 12 |
+
hf_hub_download(
|
| 13 |
+
repo_id=MODEL_REPO,
|
| 14 |
+
filename=MODEL_FILE,
|
| 15 |
+
local_dir=LOCAL_MODEL_DIR,
|
| 16 |
+
local_dir_use_symlinks=False
|
| 17 |
+
)
|
| 18 |
+
|
| 19 |
+
print("File exists:", os.path.exists(model_path))
|
| 20 |
+
print("File size:", os.path.getsize(model_path))
|
| 21 |
+
|
| 22 |
+
try:
|
| 23 |
+
model = Llama(
|
| 24 |
+
model_path=model_path,
|
| 25 |
+
n_ctx=2048,
|
| 26 |
+
verbose=True
|
| 27 |
+
)
|
| 28 |
+
print("Success loading model!")
|
| 29 |
+
except Exception as e:
|
| 30 |
+
import traceback
|
| 31 |
+
traceback.print_exc()
|
scratch/test_phase3.py
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import sys
|
| 3 |
+
import json
|
| 4 |
+
import sqlite3
|
| 5 |
+
|
| 6 |
+
# Ensure src directory is in path
|
| 7 |
+
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
|
| 8 |
+
|
| 9 |
+
import src.database as db
|
| 10 |
+
import src.gpx_parser as gpx_parser
|
| 11 |
+
from app import generate_elevation_plot, handle_generate_story
|
| 12 |
+
|
| 13 |
+
def run_tests():
|
| 14 |
+
print("=== STARTING PHASE 3 FUNCTIONAL TESTS ===")
|
| 15 |
+
|
| 16 |
+
# 1. Test SQLite Database Operations
|
| 17 |
+
print("\n--- Test 1: SQLite Database Operations ---")
|
| 18 |
+
db.init_db()
|
| 19 |
+
|
| 20 |
+
# Clear tables to start clean
|
| 21 |
+
db.clear_journal_logs()
|
| 22 |
+
db.clear_custom_waypoints()
|
| 23 |
+
|
| 24 |
+
# Insert custom waypoint
|
| 25 |
+
db.add_custom_waypoint(46.0734, 11.1717, 350.0, "drinking_water", "Test Water Source", "Fresh cold spring")
|
| 26 |
+
wps = db.get_custom_waypoints()
|
| 27 |
+
assert len(wps) == 1, "Waypoint count should be 1"
|
| 28 |
+
assert wps[0]["name"] == "Test Water Source", "Waypoint name mismatch"
|
| 29 |
+
assert wps[0]["type"] == "drinking_water", "Waypoint type mismatch"
|
| 30 |
+
print("✅ Custom waypoint read/write verified successfully.")
|
| 31 |
+
|
| 32 |
+
# Insert journal log
|
| 33 |
+
db.add_journal_entry(46.0735, 11.1718, 352.0, 0.5, "Hiked up the trail, found fresh water at custom tagged point.")
|
| 34 |
+
logs = db.get_journal_entries()
|
| 35 |
+
assert len(logs) == 1, "Journal logs count should be 1"
|
| 36 |
+
assert logs[0]["transcript"] == "Hiked up the trail, found fresh water at custom tagged point.", "Transcript mismatch"
|
| 37 |
+
print("✅ Voice log entry read/write verified successfully.")
|
| 38 |
+
|
| 39 |
+
# 2. Test Tile Coordinate Conversion
|
| 40 |
+
print("\n--- Test 2: OSM Tile Conversion Maths ---")
|
| 41 |
+
lat, lon, zoom = 46.0734974, 11.1717214, 13
|
| 42 |
+
x, y = gpx_parser.deg2num(lat, lon, zoom)
|
| 43 |
+
print(f"Coordinates {lat}, {lon} at Zoom {zoom} -> Tile X: {x}, Y: {y}")
|
| 44 |
+
assert x == 4350, f"Expected X = 4350, got {x}"
|
| 45 |
+
assert y == 2911, f"Expected Y = 2911, got {y}"
|
| 46 |
+
print("✅ OSM tile maths verified successfully (match Trento coordinates Z13).")
|
| 47 |
+
|
| 48 |
+
# 3. Test Plotly Elevation Chart Generation
|
| 49 |
+
print("\n--- Test 3: Plotly Elevation Chart Generation ---")
|
| 50 |
+
mock_points = [
|
| 51 |
+
{"lat": 46.073, "lon": 11.171, "ele": 300.0, "cum_dist": 0.0},
|
| 52 |
+
{"lat": 46.074, "lon": 11.172, "ele": 320.0, "cum_dist": 150.0},
|
| 53 |
+
{"lat": 46.075, "lon": 11.173, "ele": 350.0, "cum_dist": 300.0},
|
| 54 |
+
{"lat": 46.076, "lon": 11.174, "ele": 380.0, "cum_dist": 450.0}
|
| 55 |
+
]
|
| 56 |
+
fig = generate_elevation_plot(mock_points, current_idx=2)
|
| 57 |
+
assert fig is not None, "Plotly figure should not be None"
|
| 58 |
+
# Inspect plotly layout
|
| 59 |
+
assert fig.layout.title.text == "🏔️ ELEVATION PROFILE", "Title mismatch"
|
| 60 |
+
print("✅ Plotly elevation profile chart generated successfully.")
|
| 61 |
+
|
| 62 |
+
# 4. Test Post-Trek AI Storyteller prompt compile & fallback generation
|
| 63 |
+
print("\n--- Test 4: AI Storyteller Narrative ---")
|
| 64 |
+
mock_route = {
|
| 65 |
+
"total_distance_km": 0.45,
|
| 66 |
+
"elevation_gain_m": 80.0,
|
| 67 |
+
"min_elevation_m": 300.0,
|
| 68 |
+
"max_elevation_m": 380.0
|
| 69 |
+
}
|
| 70 |
+
story, file_path = handle_generate_story(mock_route)
|
| 71 |
+
assert story is not None, "Generated story should not be None"
|
| 72 |
+
assert "Hiker" in story or "Trail" in story or "adventure" in story, "Story content is too generic"
|
| 73 |
+
assert os.path.exists(file_path), f"Story file should be saved at {file_path}"
|
| 74 |
+
print(f"✅ AI Storyteller executed successfully. Story saved to {file_path}")
|
| 75 |
+
print(f"Story teaser:\n{story[:150]}...")
|
| 76 |
+
|
| 77 |
+
print("\n=== ALL PHASE 3 FUNCTIONAL TESTS PASSED SUCCESSFULLY! ===")
|
| 78 |
+
|
| 79 |
+
if __name__ == "__main__":
|
| 80 |
+
run_tests()
|