dronesplace's picture
Update app.py
7fac452 verified
Raw
History Blame Contribute Delete
3.7 kB
import os
import uuid
import tempfile
from pathlib import Path
from flask import Flask, request, jsonify, send_file, render_template
# Optional OpenAI features
try:
import openai
OPENAI_AVAILABLE = True
except Exception:
OPENAI_AVAILABLE = False
# TTS (gTTS)
from gtts import gTTS
app = Flask(__name__, static_folder="static", template_folder="templates")
# Avatar stored in repo root → /app/avatar.png
AVATAR_LOCAL = "/app/avatar.png"
# Storage dir for generated audio
OUT_DIR = Path(tempfile.gettempdir()) / "nola_audio"
OUT_DIR.mkdir(parents=True, exist_ok=True)
# Load OpenAI key from env
OPENAI_API_KEY = os.environ.get("OPENAI_API_KEY") or os.environ.get("OPENAI_KEY")
if OPENAI_AVAILABLE and OPENAI_API_KEY:
openai.api_key = OPENAI_API_KEY
else:
OPENAI_AVAILABLE = False
@app.route("/")
def index():
# Serve local avatar
avatar_url = "/avatar.png" if Path(AVATAR_LOCAL).exists() else "/static/avatar.png"
return render_template("index.html", avatar_src=avatar_url)
@app.route("/avatar.png")
def serve_avatar():
"""Serve avatar from repo root."""
if Path(AVATAR_LOCAL).exists():
return send_file(AVATAR_LOCAL, mimetype="image/png")
return jsonify({"error": "avatar missing"}), 404
@app.route("/api/message", methods=["POST"])
def api_message():
text = None
if "text" in request.form and request.form["text"].strip():
text = request.form["text"].strip()
audio_file = request.files.get("audio")
transcription = ""
if audio_file:
uid = uuid.uuid4().hex[:10]
in_path = OUT_DIR / f"in_{uid}.webm"
audio_file.save(str(in_path))
if OPENAI_AVAILABLE:
try:
with open(in_path, "rb") as fh:
resp = openai.Audio.transcriptions.create(
file=fh, model="gpt-4o-mini-transcribe"
)
transcription = resp.text if hasattr(resp, "text") else resp.get("text", "")
except Exception:
transcription = ""
else:
transcription = ""
user_text = text or transcription or "Hello! I didn't hear clearly. Try again."
# AI Response
if OPENAI_AVAILABLE:
try:
chat_resp = openai.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": user_text}],
max_tokens=200,
)
assistant_text = chat_resp.choices[0].message["content"].strip()
except Exception:
assistant_text = "Sorry, I couldn't think of a reply."
else:
assistant_text = f"You said: {user_text[:200]}. Ask me anything."
# Generate TTS
lang = request.form.get("lang", "en")
try:
uid2 = uuid.uuid4().hex[:10]
out_mp3 = OUT_DIR / f"reply_{uid2}.mp3"
tts = gTTS(text=assistant_text, lang=lang, slow=False)
tts.save(str(out_mp3))
audio_url = f"/audio/{out_mp3.name}"
except Exception:
silent_path = OUT_DIR / f"silent_{uid2}.mp3"
with open(silent_path, "wb") as f:
f.write(b"")
audio_url = f"/audio/{silent_path.name}"
return jsonify(
{
"ok": True,
"user_text": user_text,
"assistant_text": assistant_text,
"audio_url": audio_url,
}
)
@app.route("/audio/<filename>")
def serve_audio(filename):
fpath = OUT_DIR / filename
if fpath.exists():
return send_file(str(fpath), mimetype="audio/mpeg", conditional=True)
return jsonify({"ok": False, "error": "file not found"}), 404
if __name__ == "__main__":
app.run(host="0.0.0.0", port=7860)