Add files via upload

This commit is contained in:
FatihMakes authored and GitHub committed 2025-12-15 18:56:25 +03:00
commit 5d2c052b70
7 files changed
+485

No files matched your search

+2
View File
@@ -0,0 +1,2 @@
GROQ_API_KEY = PASTE YOUR API GROQ_API_KEY
#IF YOU DON'T KNOW HOW, THEN WATCH THE VIDEO https://youtu.be/TROMQ_Du7q8?si=UO7TnaUJ6JBCZvoi
+194
View File
@@ -0,0 +1,194 @@
import os
import math
import time
import requests
import webbrowser
import re
from difflib import SequenceMatcher
from dotenv import load_dotenv
from voice_player import edge_speak
load_dotenv()
MY_LAT = float(os.getenv("LAT", 40.7908711))
MY_LON = float(os.getenv("LON", -73.3746079))
OPENSKY_STATES = "https://opensky-network.org/api/states/all"
OPENSKY_FLIGHTS = "https://opensky-network.org/api/flights/aircraft"
def normalize(text: str):
text = text.lower()
text = re.sub(r"[^a-z0-9\s]", "", text)
text = re.sub(r"\s+", " ", text).strip()
return text
def smart_match(user_input: str, command: str):
user = normalize(user_input)
cmd = normalize(command)
if cmd in user:
return True
user_words = set(user.split())
cmd_words = set(cmd.split())
if cmd_words and len(user_words & cmd_words) / len(cmd_words) >= 0.6:
return True
return SequenceMatcher(None, user, cmd).ratio() >= 0.6
def match_commands(user_input: str, commands: list):
return any(smart_match(user_input, cmd) for cmd in commands)
def haversine(lat1, lon1, lat2, lon2):
R = 6371
d_lat = math.radians(lat2 - lat1)
d_lon = math.radians(lon2 - lon1)
a = (
math.sin(d_lat / 2) ** 2
+ math.cos(math.radians(lat1))
* math.cos(math.radians(lat2))
* math.sin(d_lon / 2) ** 2
)
return 2 * R * math.atan2(math.sqrt(a), math.sqrt(1 - a))
def get_nearby_aircraft(radius_km=200):
lamin, lamax = MY_LAT - 1, MY_LAT + 1
lomin, lomax = MY_LON - 1, MY_LON + 1
try:
r = requests.get(
f"{OPENSKY_STATES}?lamin={lamin}&lamax={lamax}&lomin={lomin}&lomax={lomax}",
timeout=10
)
data = r.json()
except:
return []
aircraft = []
for s in data.get("states", []):
lat, lon = s[6], s[5]
if lat is None or lon is None:
continue
dist = haversine(MY_LAT, MY_LON, lat, lon)
if dist > radius_km:
continue
velocity = s[9] or 0
heading = s[10] or 0
aircraft.append({
"icao24": s[0],
"callsign": (s[1] or "Unknown").strip(),
"country": s[2] or "Unknown",
"lat": lat,
"lon": lon,
"distance": dist,
"velocity": velocity,
"heading": heading
})
return aircraft
def get_flight_route(icao24):
now = int(time.time())
begin = now - 6 * 3600
try:
r = requests.get(
f"{OPENSKY_FLIGHTS}?icao24={icao24}&begin={begin}&end={now}",
timeout=10
)
flights = r.json()
if flights:
f = flights[-1]
return f.get("estDepartureAirport"), f.get("estArrivalAirport")
except:
pass
return None, None
def generate_jarvis_aircraft_report(planes):
total = len(planes)
closest = min(planes, key=lambda x: x["distance"])
dist = closest["distance"]
speed = closest["velocity"] * 3.6
heading = closest["heading"]
if dist < 50:
situation = "approaching your position"
elif dist < 120:
situation = "passing through nearby airspace"
else:
situation = "operating at a safe distance"
dep, arr = get_flight_route(closest["icao24"])
dep = dep or "unknown origin"
arr = arr or "unknown destination"
return (
f"Sir, radar scan complete. "
f"I have detected {total} aircraft in your vicinity. "
f"The nearest one is {closest['callsign']}, registered in {closest['country']}. "
f"It is approximately {dist:.1f} kilometers away, "
f"traveling at {speed:.0f} kilometers per hour, "
f"heading {heading:.0f} degrees, "
f"currently {situation}. "
f"Estimated route is from {dep} to {arr}. "
f"No immediate threat detected."
)
def speak_detailed_aircraft_report(player):
planes = get_nearby_aircraft()
if not planes:
text = "Sir, no aircraft detected in your operational airspace."
edge_speak(text, player)
player.write_log(text)
return
text = generate_jarvis_aircraft_report(planes)
edge_speak(text, player)
player.write_log(text)
def handle_aircraft_command(user_text, player):
if match_commands(user_text, [
"give me aircraft details",
"tell me detailed report",
"give me full detailed aircraft report",
"give me advanced aircraft report",
"tell me aircraft details"
]):
speak_detailed_aircraft_report(player)
return True
if match_commands(user_text, [
"open aircraft",
"open flight radar",
"show aircraft map"
]):
webbrowser.open(f"https://www.flightradar24.com/{MY_LAT},{MY_LON}/10")
edge_speak("Opening aircraft radar, sir.", player)
player.write_log("Opening aircraft radar, sir.")
return True
if match_commands(user_text, [
"aircraft summary",
"planes nearby",
"give me aircraft"
]):
planes = get_nearby_aircraft()
text = f"Sir, I currently detect {len(planes)} aircraft nearby."
edge_speak(text, player)
player.write_log(text)
return True
return False
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 962 KiB

+68
View File
@@ -0,0 +1,68 @@
from groq import Groq
from dotenv import load_dotenv
import os
load_dotenv()
GROQ_API_KEY = os.getenv("GROQ_API_KEY")
if not GROQ_API_KEY:
raise ValueError("❌ GROQ_API_KEY not found in .env")
client = Groq(api_key=GROQ_API_KEY)
SYSTEM_PROMPT = """
Give useful and very shortly answers but use maximum 2-3 sentence(and keep that sentences short(a little short))
add "sir" like jarvis but not in every sentence.
"""
chat_history = []
def get_best_model():
model_list = client.models.list()
available = [m.id for m in model_list.data]
print("Available Groq Models:\n", available)
priority = [
"llama-3.3-70b",
"llama-3.2-90b",
"llama-3.2-70b",
"llama-3.1-8b",
"mixtral-8x7b",
"gemma2-9b-it"
]
for name in priority:
for model_id in available:
if name in model_id.lower():
print(f"\n✔ Selected model: {model_id}\n")
return model_id
return available[0]
BEST_MODEL = get_best_model()
def get_response(user_text):
global chat_history
chat_history.append({"role": "user", "content": user_text})
messages = (
[{"role": "system", "content": SYSTEM_PROMPT}]
+ chat_history[-5:]
)
response = client.chat.completions.create(
model=BEST_MODEL,
messages=messages,
max_tokens=200
)
text = response.choices[0].message.content.strip()
chat_history.append({"role": "assistant", "content": text})
return text
def reset_history():
global chat_history
chat_history = []
+40
View File
@@ -0,0 +1,40 @@
import asyncio
import threading
from voice_player import VoiceImagePlayer, edge_speak
from speech_to_text import record_voice
from groq_ai import get_response
from aircraft_module import handle_aircraft_command
async def get_voice_input():
return await asyncio.to_thread(record_voice)
async def ai_loop(player):
while True:
user_text = await get_voice_input()
if not user_text:
continue
handled = handle_aircraft_command(user_text, player)
if handled:
continue
response = get_response(user_text)
print("AI:", response)
edge_speak(response, player)
player.write_log(f"You: {user_text}")
player.write_log(f"AI: {response}")
def main_loop():
player = VoiceImagePlayer("face.png", size=(900, 900))
def thread_target():
asyncio.run(ai_loop(player))
threading.Thread(target=thread_target, daemon=True).start()
player.root.mainloop()
if __name__ == "__main__":
main_loop()
+32
View File
@@ -0,0 +1,32 @@
# vosk_voice.py
import sounddevice as sd
import vosk
import queue
import sys
import json
MODEL_PATH = "C:/Users/90553/Downloads/vosk/vosk-model-small-en-us-0.15" #put your path in here
model = vosk.Model(MODEL_PATH)
q = queue.Queue()
def callback(indata, frames, time, status):
if status:
print(status, file=sys.stderr)
q.put(bytes(indata))
def record_voice(prompt="🎙 I'm listening, sir...", timeout=None, phrase_time_limit=None):
print(prompt)
rec = vosk.KaldiRecognizer(model, 16000)
with sd.RawInputStream(samplerate=16000, blocksize=8000, dtype='int16',
channels=1, callback=callback):
while True:
data = q.get()
if rec.AcceptWaveform(data):
result = json.loads(rec.Result())
text = result.get("text", "")
if text.strip():
print("👤 You:", text)
return text
+149
View File
@@ -0,0 +1,149 @@
import os
import io
import random
import threading
import asyncio
import edge_tts
import sounddevice as sd
import soundfile as sf
from PIL import Image, ImageTk
import tkinter as tk
from tkinter.scrolledtext import ScrolledText
import re
import html
# ---------------- TEXT NORMALIZATION ---------------- #
def normalize_text(text: str) -> str:
text = text.strip()
text = re.sub(r'\s+', ' ', text)
return html.escape(text) # SSML güvenliği
# ---------------- SSML BUILDER ---------------- #
def build_ssml(text: str, voice: str) -> str:
return (
f'<speak version="1.0" xml:lang="en-US">'
f'<voice name="{voice}">'
f'{text}'
f'</voice>'
f'</speak>'
)
# ---------------- UI CLASS ---------------- #
class VoiceImagePlayer:
def __init__(self, face_path, size=(760, 760)):
self.root = tk.Tk()
self.root.title("AI - EPISODE 2")
self.root.resizable(False, False)
self.root.geometry("760x900")
self.fixed_size = size
self.face_original = Image.open(face_path).resize(self.fixed_size, Image.LANCZOS)
self.face_label = tk.Label(self.root, bg="#001f4d", borderwidth=0)
self.face_label.place(relx=0.5, rely=0.4, anchor="center")
self.scale = 1.0
self.playing = False
self.text_box = ScrolledText(
self.root,
fg="#00ffff",
bg="#001f4d",
insertbackground="#00ffff",
height=12,
borderwidth=0,
wrap="word",
font=("Consolas", 10),
padx=10,
pady=10
)
self.text_box.place(relx=0.5, rely=0.85, anchor="center")
self.text_box.configure(state="disabled")
self.animate()
self.root.protocol("WM_DELETE_WINDOW", lambda: os._exit(0))
# 🔥 BU METOT EKSİKTİ – ŞİMDİ VAR
def write_log(self, text: str):
self.text_box.configure(state="normal")
self.text_box.insert(tk.END, text + "\n")
self.text_box.see(tk.END)
self.text_box.configure(state="disabled")
def start_animation(self):
self.playing = True
def stop_animation(self):
self.playing = False
def animate(self):
if self.playing:
self.scale += random.uniform(-0.01, 0.015)
self.scale = min(max(self.scale, 1.02), 1.08)
else:
self.scale += (1.0 - self.scale) * 0.1
w, h = self.fixed_size
resized = self.face_original.resize(
(int(w * self.scale), int(h * self.scale)),
Image.LANCZOS
)
img = ImageTk.PhotoImage(resized)
self.face_label.configure(image=img)
self.face_label.image = img
self.root.after(50, self.animate)
# ---------------- VOICE ENGINE ---------------- #
VOICE = "en-GB-RyanNeural"
# Erkek, stabil
def edge_speak(text: str, img_player: VoiceImagePlayer, voice: str = VOICE):
if not text.strip():
return
clean_text = text.strip()
def _thread():
async def _run():
audio_buffer = bytearray()
first_audio = False
try:
communicate = edge_tts.Communicate(
clean_text,
voice
)
async for chunk in communicate.stream():
if chunk["type"] == "audio":
audio_buffer.extend(chunk["data"])
if not first_audio:
first_audio = True
img_player.start_animation()
except Exception as e:
print("TTS ERROR:", e)
img_player.stop_animation()
return
if not audio_buffer:
img_player.stop_animation()
return
data, samplerate = sf.read(io.BytesIO(audio_buffer), dtype="float32")
sd.play(data, samplerate)
sd.wait()
img_player.stop_animation()
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
loop.run_until_complete(_run())
loop.close()
threading.Thread(target=_thread, daemon=True).start()