fix stuff
This commit is contained in:
0
utils/__init__.py
Normal file
0
utils/__init__.py
Normal file
43
utils/ai_client.py
Normal file
43
utils/ai_client.py
Normal file
@@ -0,0 +1,43 @@
|
||||
import re
|
||||
|
||||
import ollama
|
||||
|
||||
from audio.tts import speak
|
||||
|
||||
AI_MODEL = "gemma4:e2b-it-qat"
|
||||
AI_HOST = "http://localhost:11434"
|
||||
def clean_response(text):
|
||||
cleaned = re.sub(r"<think>.*?</think>", "", text, flags=re.DOTALL | re.IGNORECASE)
|
||||
lines = [line for line in cleaned.splitlines() if line.strip()]
|
||||
return "\n".join(lines).strip()
|
||||
def ask_ai(prompt):
|
||||
try:
|
||||
full_prompt = (
|
||||
"You must answer in exactly one or two sentences.\n\n"
|
||||
f"Question: {prompt}\n"
|
||||
"Answer:"
|
||||
)
|
||||
print("Thinking...", end="", flush=True)
|
||||
client = ollama.Client(host=AI_HOST)
|
||||
stream = client.generate(
|
||||
model=AI_MODEL,
|
||||
prompt=full_prompt,
|
||||
stream=True
|
||||
)
|
||||
ai_text = ""
|
||||
for chunk in stream:
|
||||
text_piece = chunk.get("response", "")
|
||||
if text_piece:
|
||||
print(text_piece, end="", flush=True)
|
||||
ai_text += text_piece
|
||||
print()
|
||||
final_text = clean_response(ai_text)
|
||||
if not final_text:
|
||||
speak("Sorry, I got no response from the AI.")
|
||||
else:
|
||||
speak(final_text)
|
||||
except Exception as e:
|
||||
|
||||
print("\nAI Error:", e)
|
||||
|
||||
speak("Sorry, I couldn't connect to the AI.")
|
||||
23
utils/time_utils.py
Normal file
23
utils/time_utils.py
Normal file
@@ -0,0 +1,23 @@
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
def time_to_words(dt: datetime):
|
||||
hour = dt.hour % 12 or 12
|
||||
minute = dt.minute
|
||||
numbers = ["zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine",
|
||||
"ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen",
|
||||
"eighteen", "nineteen", "twenty", "twenty-one", "twenty-two", "twenty-three",
|
||||
"twenty-four", "twenty-five", "twenty-six", "twenty-seven", "twenty-eight",
|
||||
"twenty-nine", "thirty", "thirty-one", "thirty-two", "thirty-three", "thirty-four",
|
||||
"thirty-five", "thirty-six", "thirty-seven", "thirty-eight", "thirty-nine",
|
||||
"forty", "forty-one", "forty-two", "forty-three", "forty-four", "forty-five",
|
||||
"forty-six", "forty-seven", "forty-eight", "forty-nine", "fifty", "fifty-one",
|
||||
"fifty-two", "fifty-three", "fifty-four", "fifty-five", "fifty-six", "fifty-seven",
|
||||
"fifty-eight", "fifty-nine"]
|
||||
am_pm = "AM" if dt.hour < 12 else "PM"
|
||||
if minute == 0:
|
||||
return f"{numbers[hour]} o'clock {am_pm}"
|
||||
elif minute < 10:
|
||||
return f"{numbers[hour]} oh {numbers[minute]} {am_pm}"
|
||||
else:
|
||||
return f"{numbers[hour]} {numbers[minute]} {am_pm}"
|
||||
22
utils/vosk_setup.py
Normal file
22
utils/vosk_setup.py
Normal file
@@ -0,0 +1,22 @@
|
||||
import os
|
||||
import zipfile
|
||||
|
||||
import requests
|
||||
import vosk
|
||||
|
||||
from config import VOSK_MODEL_FOLDER, VOSK_MODEL_URL, VOSK_MODEL_ZIP
|
||||
|
||||
|
||||
def setup_vosk_model():
|
||||
if not os.path.isdir(VOSK_MODEL_FOLDER):
|
||||
print("Downloading Vosk model")
|
||||
response = requests.get(VOSK_MODEL_URL)
|
||||
with open(VOSK_MODEL_ZIP, "wb") as file:
|
||||
file.write(response.content)
|
||||
with zipfile.ZipFile(VOSK_MODEL_ZIP, 'r') as zip_ref:
|
||||
zip_ref.extractall()
|
||||
print("Downloaded!")
|
||||
|
||||
model = vosk.Model(VOSK_MODEL_FOLDER)
|
||||
rec = vosk.KaldiRecognizer(model, 16000)
|
||||
return rec
|
||||
95
utils/weather.py
Normal file
95
utils/weather.py
Normal file
@@ -0,0 +1,95 @@
|
||||
import requests
|
||||
|
||||
|
||||
def get_local_weather(
|
||||
fallback_lat=40.59,
|
||||
fallback_lon=-74.62,
|
||||
fallback_city="Bridgewater",
|
||||
fallback_region="New Jersey",
|
||||
fallback_country_code="US"
|
||||
):
|
||||
"""
|
||||
Fetches the user's current location and automatically determines
|
||||
whether to return Metric or Imperial units based on their country.
|
||||
"""
|
||||
lat, lon = fallback_lat, fallback_lon
|
||||
city, region = fallback_city, fallback_region
|
||||
country_code = fallback_country_code
|
||||
|
||||
# Geolocation Lookup
|
||||
try:
|
||||
geo_url = "http://ip-api.com/json"
|
||||
geo_response = requests.get(geo_url, timeout=5).json()
|
||||
|
||||
if geo_response.get("status") == "success":
|
||||
lat = geo_response["lat"]
|
||||
lon = geo_response["lon"]
|
||||
city = geo_response["city"]
|
||||
region = geo_response["regionName"]
|
||||
country_code = geo_response.get("countryCode", "US")
|
||||
else:
|
||||
print("IP lookup API returned an error status. Using fallback coordinates.")
|
||||
except Exception:
|
||||
print("Network error during IP lookup. Using fallback coordinates.")
|
||||
|
||||
# Unit System 'n Weather URL
|
||||
is_imperial = country_code in ["US", "LR", "MM"]
|
||||
|
||||
unit_suffix = ""
|
||||
if is_imperial:
|
||||
unit_suffix = "&temperature_unit=fahrenheit&precipitation_unit=inch"
|
||||
|
||||
weather_url = (
|
||||
f"https://api.open-meteo.com/v1/forecast?"
|
||||
f"latitude={lat}&longitude={lon}"
|
||||
f"¤t=temperature_2m,precipitation,cloud_cover"
|
||||
f"&daily=temperature_2m_max,temperature_2m_min"
|
||||
f"&timezone=auto"
|
||||
f"{unit_suffix}"
|
||||
)
|
||||
|
||||
try:
|
||||
response = requests.get(weather_url, timeout=5)
|
||||
|
||||
if response.status_code == 200:
|
||||
data = response.json()
|
||||
current = data["current"]
|
||||
daily = data["daily"]
|
||||
|
||||
temp_unit = "°F" if is_imperial else "°C"
|
||||
precip_unit = "inch" if is_imperial else "mm"
|
||||
|
||||
return {
|
||||
"location": {
|
||||
"city": city,
|
||||
"region": region,
|
||||
"country_code": country_code,
|
||||
"lat": lat,
|
||||
"lon": lon
|
||||
},
|
||||
"unit_system": "imperial" if is_imperial else "metric",
|
||||
"units": {"temp": temp_unit, "precipitation": precip_unit},
|
||||
"current_temp": current['temperature_2m'],
|
||||
"high_temp": daily['temperature_2m_max'][0],
|
||||
"low_temp": daily['temperature_2m_min'][0],
|
||||
"precipitation": current['precipitation'],
|
||||
"cloud_cover_pct": current['cloud_cover']
|
||||
}
|
||||
else:
|
||||
print(f"Weather API returned error code: {response.status_code}")
|
||||
return None
|
||||
|
||||
except Exception as e:
|
||||
print(f"Network error while fetching weather: {e}")
|
||||
return None
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Test block
|
||||
weather_data = get_local_weather()
|
||||
if weather_data:
|
||||
u = weather_data["units"]
|
||||
print(f"\n--- Location: {weather_data['location']['city']}, {weather_data['location']['region']} ({weather_data['location']['country_code']}) ---")
|
||||
print(f"System Chosen: {weather_data['unit_system'].upper()}")
|
||||
print(f"Current Temperature: {weather_data['current_temp']}{u['temp']}")
|
||||
print(f"Today's High: {weather_data['high_temp']}{u['temp']}")
|
||||
print(f"Precipitation: {weather_data['precipitation']} {u['precipitation']}")
|
||||
Reference in New Issue
Block a user