File size: 5,112 Bytes
ec9b387 1deacc5 3ebc508 1deacc5 465bca7 3ebc508 ec9b387 14c0817 ec9b387 14c0817 3ebc508 1deacc5 ec9b387 76141c4 14c0817 3ebc508 14c0817 ec9b387 14c0817 3ebc508 ec9b387 1deacc5 76141c4 3ebc508 ec9b387 3ebc508 ec9b387 3ebc508 263ee79 ec9b387 3ebc508 76141c4 263ee79 ec9b387 76141c4 ec9b387 3ebc508 ec9b387 76141c4 ec9b387 3ebc508 ec9b387 14c0817 ec9b387 14c0817 ec9b387 14c0817 ec9b387 76141c4 ec9b387 14c0817 ec9b387 14c0817 465bca7 76141c4 ec9b387 3ebc508 76141c4 3ebc508 1deacc5 3ebc508 e81567c ec9b387 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
# app.py - Flask Backend
from flask import Flask, request, jsonify, send_from_directory
import google.generativeai as genai
from dotenv import load_dotenv
import os
from flask_cors import CORS
import markdown2
import re
from gtts import gTTS
import uuid
# Load environment variables
load_dotenv()
# Define paths and create static audio directory if it doesn't exist
AUDIO_FOLDER = os.path.join('static', 'audio')
if not os.path.exists(AUDIO_FOLDER):
os.makedirs(AUDIO_FOLDER)
# Initialize Flask app
app = Flask(__name__, static_folder='static')
CORS(app) # Enable CORS for all routes
# Configure Gemini with a system instruction
system_instruction_text = """
You are a helpful, friendly, and informative AI assistant named Athspi.
Your goal is to provide clear, concise, and natural-sounding answers to user queries.
When you respond:
- Use clear and simple language.
- Avoid overly complex sentence structures that might be hard to read aloud.
- Keep the user engaged and offer follow-up questions or related topics where appropriate.
- Ensure your responses are suitable for text-to-speech conversion.
- Provide factual and accurate information.
- If the user asks for audio or to speak the response, include π at the start of your response.
- For coding questions, provide well-formatted code blocks with syntax highlighting.
"""
genai.configure(api_key=os.getenv("GEMINI_API_KEY"))
model = genai.GenerativeModel(
'gemini-2.5-flash',
system_instruction=system_instruction_text
)
def convert_markdown_to_html(text):
html = markdown2.markdown(text, extras=["fenced-code-blocks", "tables"])
html = re.sub(r'<pre><code(.*?)>', r'<pre class="code-block"><code\1>', html)
html = re.sub(r'\*\*(.*?)\*\*', r'<strong>\1</strong>', html)
html = re.sub(r'\*(.*?)\*', r'<em>\1</em>', html)
return html
def detect_audio_request(text):
"""Detect if user is requesting audio"""
audio_keywords = ['audio', 'speak', 'say it', 'read aloud', 'hear', 'listen']
return any(keyword in text.lower() for keyword in audio_keywords)
def generate_audio_file(text):
"""Generate audio file from text and return filename"""
cleaned_text = re.sub(r'[\*_`#]', '', text)
cleaned_text = re.sub(r'\s+', ' ', cleaned_text).strip()
if not cleaned_text:
return None
filename = f"{uuid.uuid4()}.mp3"
filepath = os.path.join(AUDIO_FOLDER, filename)
tts = gTTS(text=cleaned_text, lang='en', slow=False)
tts.save(filepath)
return filename
@app.route('/chat', methods=['POST'])
def chat():
try:
data = request.json
user_message = data.get('message')
if not user_message:
return jsonify({"error": "No message provided"}), 400
# Detect if user is requesting audio
audio_requested = detect_audio_request(user_message)
response = model.generate_content(user_message)
plain_text_response = response.text
# Generate audio if requested
audio_url = None
if audio_requested:
# Add audio indicator if not already present
if not plain_text_response.startswith("π"):
plain_text_response = "π " + plain_text_response
# Generate audio file
audio_filename = generate_audio_file(plain_text_response)
if audio_filename:
audio_url = f"/static/audio/{audio_filename}"
html_response = convert_markdown_to_html(plain_text_response)
return jsonify({
"response_html": html_response,
"response_text": plain_text_response,
"audio_url": audio_url
})
except Exception as e:
app.logger.error(f"Chat Error: {e}")
return jsonify({"error": str(e)}), 500
@app.route('/generate-audio', methods=['POST'])
def generate_audio():
try:
data = request.json
text_to_speak = data.get('text')
if not text_to_speak:
return jsonify({"error": "No text provided"}), 400
cleaned_text = re.sub(r'[\*_`#]', '', text_to_speak)
cleaned_text = re.sub(r'\s+', ' ', cleaned_text).strip()
if not cleaned_text:
return jsonify({"error": "Text became empty after cleaning"}), 400
filename = f"{uuid.uuid4()}.mp3"
filepath = os.path.join(AUDIO_FOLDER, filename)
tts = gTTS(text=cleaned_text, lang='en', slow=False)
tts.save(filepath)
audio_url = f"/static/audio/{filename}"
return jsonify({"audio_url": audio_url})
except Exception as e:
app.logger.error(f"Audio Generation Error: {e}")
return jsonify({"error": str(e)}), 500
@app.route('/static/audio/<filename>')
def serve_audio(filename):
return send_from_directory(AUDIO_FOLDER, filename)
@app.route('/')
def serve_index():
return send_from_directory('static', 'index.html')
@app.route('/<path:path>')
def serve_static(path):
return send_from_directory('static', path)
if __name__ == '__main__':
app.run(host="0.0.0.0", port=7860) |