File size: 3,571 Bytes
ec9b387 1deacc5 3ebc508 1deacc5 465bca7 3ebc508 ec9b387 14c0817 ec9b387 14c0817 3ebc508 1deacc5 ec9b387 14c0817 3ebc508 ec9b387 14c0817 ec9b387 14c0817 3ebc508 ec9b387 1deacc5 3ebc508 ec9b387 3ebc508 ec9b387 3ebc508 263ee79 ec9b387 3ebc508 263ee79 ec9b387 3ebc508 ec9b387 3ebc508 ec9b387 14c0817 ec9b387 14c0817 ec9b387 14c0817 ec9b387 14c0817 ec9b387 14c0817 465bca7 ec9b387 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 |
# 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.
"""
genai.configure(api_key=os.getenv("GEMINI_API_KEY"))
# Initialize the model with the system instruction
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
@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
response = model.generate_content(user_message)
plain_text_response = response.text
html_response = convert_markdown_to_html(plain_text_response)
return jsonify({
"response_html": html_response,
"response_text": plain_text_response
})
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, cannot generate audio."}), 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"/{filepath.replace(os.path.sep, '/')}"
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('/')
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) |