Llama-vibow / app.py
Vibow's picture
Update app.py
55e5e95 verified
raw
history blame
6.99 kB
import os
import time
import base64
import random
import json
import requests
from datetime import datetime, timedelta, timezone
from flask import Flask, request, jsonify, Response
app = Flask(__name__)
app.secret_key = os.getenv("FLASK_SECRET_KEY")
# ==== API KEYS ====
GROQ_API_KEY_1 = os.getenv("GROQ_API_KEY_1")
GROQ_API_KEY_2 = os.getenv("GROQ_API_KEY_2")
GROQ_API_KEY_3 = os.getenv("GROQ_API_KEY_3")
SERPAPI_KEY = os.getenv("SERPAPI_KEY")
# ==== URL ====
GROQ_URL_CHAT = "https://api.groq.com/openai/v1/chat/completions"
GROQ_URL_TTS = "https://api.groq.com/openai/v1/audio/speech"
GROQ_URL_STT = "https://api.groq.com/openai/v1/audio/transcriptions"
# ==== SYSTEM PROMPT ====
SYSTEM_PROMPT = (
"You are Talk GTE β€” a friendly AI assistant created by Vibow AI. "
"GTE means Generative Text Expert in Vibow AI. "
"Vibow AI created in 29 June 2025 and Talk GTE created in 23 October 2025. "
"Talk GTE have approximately 1 trillion parameters. "
"Stay positive, kind, and expert. "
"Always capitalize the first letter of sentences. "
"If the user requests code, always use triple backticks (```). "
"Be concise, neutral, and accurate. "
"Sometimes use emoji but relevant."
)
# =========================
# 🎀 STT
# =========================
def transcribe_audio(file_path: str) -> str:
try:
headers = {"Authorization": f"Bearer {GROQ_API_KEY_2}"}
files = {
"file": (os.path.basename(file_path), open(file_path, "rb"), "audio/wav"),
"model": (None, "whisper-large-v3-turbo"),
}
res = requests.post(GROQ_URL_STT, headers=headers, files=files, timeout=60)
res.raise_for_status()
return res.json().get("text", "")
except Exception as e:
print(f"[STT Error] {e}")
return ""
finally:
if os.path.exists(file_path):
os.remove(file_path)
# =========================
# πŸ”Š TTS
# =========================
def text_to_speech(text: str) -> bytes:
try:
headers = {"Authorization": f"Bearer {GROQ_API_KEY_3}"}
data = {"model": "playai-tts", "voice": "Celeste-PlayAI", "input": text}
res = requests.post(GROQ_URL_TTS, headers=headers, json=data, timeout=60)
if res.status_code != 200:
print(f"[TTS Error] {res.text}")
return b""
return res.content
except Exception as e:
print(f"[TTS Exception] {e}")
return b""
# =========================
# 🌐 SerpAPI with 3 images
# =========================
def serpapi_search(query: str, location=None, num_results=3):
url = "https://serpapi.com/search.json"
params = {
"q": query,
"location": location or "",
"engine": "google",
"api_key": SERPAPI_KEY,
"num": num_results
}
try:
r = requests.get(url, params=params, timeout=10)
r.raise_for_status()
data = r.json()
results = []
images = []
if "organic_results" in data:
for item in data["organic_results"][:num_results]:
results.append({
"title": item.get("title", ""),
"snippet": item.get("snippet", ""),
"link": item.get("link", "")
})
if "images_results" in data:
for img in data["images_results"][:3]:
images.append(img.get("thumbnail", ""))
return {"results": results, "images": images}
except Exception as e:
print(f"[SerpAPI Error] {e}")
return {"results": [], "images": []}
# =========================
# πŸ’¬ Stream Chat
# =========================
def stream_chat(prompt: str, history=None):
wib = timezone(timedelta(hours=7))
now = datetime.now(wib)
sys_prompt = SYSTEM_PROMPT + f"\nCurrent time: {now.strftime('%A, %d %B %Y β€” %H:%M:%S WIB')}."
messages = [{"role": "system", "content": sys_prompt}]
if history:
messages += history
messages.append({"role": "user", "content": prompt})
payload = {
"model": "moonshotai/kimi-k2-instruct-0905",
"messages": messages,
"temperature": 0.7,
"max_tokens": 3600,
"stream": True,
}
headers = {"Authorization": f"Bearer {GROQ_API_KEY_1}"}
with requests.post(GROQ_URL_CHAT, headers=headers, json=payload, stream=True) as r:
for line in r.iter_lines():
if not line:
continue
line = line.decode()
if line.startswith("data: "):
data = line[6:]
if data == "[DONE]":
break
try:
delta = json.loads(data)["choices"][0]["delta"].get("content", "")
if delta:
yield delta
except:
continue
# =========================
# πŸš€ Chat Endpoint (Text + Voice)
# =========================
@app.route("/chat", methods=["POST"])
def chat():
# 🎀 Voice Mode
if "audio" in request.files:
audio = request.files["audio"]
temp = f"/tmp/{time.time()}_{random.randint(1000,9999)}.wav"
audio.save(temp)
user_text = transcribe_audio(temp)
if not user_text:
return jsonify({"error": "Failed STT"}), 500
keywords = ["hotel", "mall", "resort", "villa", "tempat wisata"]
if any(k in user_text.lower() for k in keywords):
serp = serpapi_search(user_text)
text = "\n".join([f"{r['title']} β€” {r['snippet']} β€” {r['link']}" for r in serp["results"]])
imgs = " ".join(serp["images"])
user_text = f"{user_text}\n\nGoogle Results:\n{text}\n\nImages:\n{imgs}\n\nExplain & recommend."
ai = "".join(chunk for chunk in stream_chat(user_text))
audio_bytes = text_to_speech(ai)
return jsonify({
"mode": "voice",
"transcript": user_text,
"reply_text": ai,
"audio_base64": "data:audio/mp3;base64," + base64.b64encode(audio_bytes).decode()
})
# πŸ’¬ Text Mode
data = request.get_json(force=True)
prompt = data.get("prompt", "")
history = data.get("history", [])
keywords = ["hotel", "mall", "resort", "villa", "tempat wisata"]
if any(k in prompt.lower() for k in keywords):
serp = serpapi_search(prompt)
text = "\n".join([f"{r['title']} β€” {r['snippet']} β€” {r['link']}" for r in serp["results"]])
imgs = " ".join(serp["images"])
prompt = f"{prompt}\n\nGoogle Results:\n{text}\n\nImages:\n{imgs}\n\nExplain & recommend."
def generate():
for chunk in stream_chat(prompt, history):
yield chunk
return Response(generate(), mimetype="text/plain")
# =========================
# ▢️ Run
# =========================
if __name__ == "__main__":
print("πŸš€ Vibow Talk GTE Server Running")
app.run(host="0.0.0.0", port=7860, debug=True, threaded=True)