Add files via upload
This commit is contained in:
1 parent
c777872e81
commit
9f46e60de1
6 files changed
+313
No files matched your search
+68
@@ -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 shortly answers,
|
||||||
|
Don't forget to add, "sir".
|
||||||
|
"""
|
||||||
|
|
||||||
|
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 = []
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
import asyncio
|
||||||
|
import threading
|
||||||
|
from voice_player import VoiceImagePlayer, edge_speak
|
||||||
|
from speech_to_text import record_voice
|
||||||
|
#from recognition import record_voice
|
||||||
|
from groq_ai import get_response
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
print("User:", user_text)
|
||||||
|
lowered = user_text.lower().strip()
|
||||||
|
|
||||||
|
if lowered in ["exit", "quit", "goodbye", "bye", "stop","mute"]:
|
||||||
|
edge_speak("Goodbye sir.", player)
|
||||||
|
player.root.after(300, player.root.destroy)
|
||||||
|
break
|
||||||
|
|
||||||
|
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():
|
||||||
|
print("")
|
||||||
|
|
||||||
|
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()
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
import speech_recognition as sr
|
||||||
|
|
||||||
|
recognizer = sr.Recognizer()
|
||||||
|
mic = sr.Microphone()
|
||||||
|
|
||||||
|
def record_voice(prompt="🎙 I'm listening, sir...", timeout=None, phrase_time_limit=None):
|
||||||
|
with mic as source:
|
||||||
|
print(prompt)
|
||||||
|
recognizer.adjust_for_ambient_noise(source, duration=0.5)
|
||||||
|
try:
|
||||||
|
audio = recognizer.listen(source, timeout=timeout, phrase_time_limit=phrase_time_limit)
|
||||||
|
except sr.WaitTimeoutError:
|
||||||
|
print("Listening timed out.")
|
||||||
|
return None
|
||||||
|
|
||||||
|
try:
|
||||||
|
text = recognizer.recognize_google(audio, language="en-US")
|
||||||
|
print("👤 You:", text)
|
||||||
|
return text
|
||||||
|
except sr.UnknownValueError:
|
||||||
|
print("🤖 Couldn't recognize the voice")
|
||||||
|
return None
|
||||||
|
except sr.RequestError as e:
|
||||||
|
print("🤖 Google Speech API Error:", e)
|
||||||
|
return None
|
||||||
@@ -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
|
||||||
+141
@@ -0,0 +1,141 @@
|
|||||||
|
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
|
||||||
|
|
||||||
|
def normalize_punctuation(text: str) -> str:
|
||||||
|
text = re.sub(r'\.\s+', ', ', text) #period
|
||||||
|
text = re.sub(r'!\s+', ', ', text) #exclamation point
|
||||||
|
text = re.sub(r'\?\s+', ', ', text) #question mark
|
||||||
|
|
||||||
|
if text.endswith("."):
|
||||||
|
text = text[:-1]
|
||||||
|
|
||||||
|
return text.strip()
|
||||||
|
|
||||||
|
class VoiceImagePlayer:
|
||||||
|
def __init__(self, face_path, size=(760, 760)):
|
||||||
|
self.root = tk.Tk()
|
||||||
|
self.root.title("F.A.I.T.H")
|
||||||
|
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, highlightthickness=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,
|
||||||
|
highlightthickness=0,
|
||||||
|
relief="flat",
|
||||||
|
wrap="word",
|
||||||
|
font=("Consolas", 10),
|
||||||
|
padx=10,
|
||||||
|
pady=10
|
||||||
|
)
|
||||||
|
|
||||||
|
self.text_box.place(relx=0.5, rely=0.85, anchor="center")
|
||||||
|
|
||||||
|
self.animate()
|
||||||
|
self.root.protocol("WM_DELETE_WINDOW", self.on_close)
|
||||||
|
|
||||||
|
def on_close(self):
|
||||||
|
os._exit(0)
|
||||||
|
|
||||||
|
def write_log(self, text):
|
||||||
|
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")
|
||||||
|
|
||||||
|
# Animation
|
||||||
|
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.015, 0.02)
|
||||||
|
self.scale = min(max(self.scale, 1.02), 1.10)
|
||||||
|
else:
|
||||||
|
if abs(self.scale - 1.0) < 0.003:
|
||||||
|
self.scale = 1.0
|
||||||
|
elif self.scale > 1.0:
|
||||||
|
self.scale -= 0.009
|
||||||
|
else:
|
||||||
|
self.scale += 0.005
|
||||||
|
|
||||||
|
base_w, base_h = self.fixed_size
|
||||||
|
new_size = (int(base_w * self.scale), int(base_h * self.scale))
|
||||||
|
resized = self.face_original.resize(new_size, Image.LANCZOS)
|
||||||
|
tk_img = ImageTk.PhotoImage(resized)
|
||||||
|
self.face_label.configure(image=tk_img)
|
||||||
|
self.face_label.image = tk_img
|
||||||
|
|
||||||
|
self.root.after(50, self.animate)
|
||||||
|
|
||||||
|
VOICE = "en-GB-OllieMultilingualNeural"
|
||||||
|
|
||||||
|
def edge_speak(text: str, img_player: VoiceImagePlayer, voice: str = VOICE):
|
||||||
|
if not text.strip():
|
||||||
|
return
|
||||||
|
|
||||||
|
optimized_text = normalize_punctuation(text)
|
||||||
|
|
||||||
|
def _thread_target():
|
||||||
|
async def _speak():
|
||||||
|
communicate = edge_tts.Communicate(
|
||||||
|
optimized_text,
|
||||||
|
voice,
|
||||||
|
pitch="+2Hz",
|
||||||
|
rate="+8%"
|
||||||
|
)
|
||||||
|
|
||||||
|
audio_buffer = bytearray()
|
||||||
|
first_audio_received = False
|
||||||
|
|
||||||
|
async for chunk in communicate.stream():
|
||||||
|
if chunk["type"] == "audio":
|
||||||
|
audio_buffer.extend(chunk["data"])
|
||||||
|
if not first_audio_received:
|
||||||
|
first_audio_received = True
|
||||||
|
img_player.start_animation()
|
||||||
|
|
||||||
|
wav_bytes = io.BytesIO(audio_buffer)
|
||||||
|
|
||||||
|
try:
|
||||||
|
data, samplerate = sf.read(wav_bytes, dtype="float32")
|
||||||
|
except Exception as e:
|
||||||
|
print("Decode error:", e)
|
||||||
|
return
|
||||||
|
|
||||||
|
sd.play(data, samplerate)
|
||||||
|
sd.wait()
|
||||||
|
img_player.stop_animation()
|
||||||
|
|
||||||
|
loop = asyncio.new_event_loop()
|
||||||
|
asyncio.set_event_loop(loop)
|
||||||
|
loop.run_until_complete(_speak())
|
||||||
|
loop.close()
|
||||||
|
|
||||||
|
threading.Thread(target=_thread_target, daemon=True).start()
|
||||||
Reference in new issue
Block a user