Bakalarska_praca/Backend/server.py

219 lines
9.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import time
import re
# Сохраняем оригинальную функцию time.time
_real_time = time.time
# Переопределяем time.time для смещения времени на 1 секунду назад
time.time = lambda: _real_time() - 1
from flask import Flask, request, jsonify
from flask_cors import CORS
from google.oauth2 import id_token
from google.auth.transport import requests
import logging
# Импортируем функцию обработки из model.py
from model import process_query_with_mistral
import psycopg2
from psycopg2.extras import RealDictCursor
# Параметры подключения к базе данных
DATABASE_CONFIG = {
"dbname": "postgres",
"user": "postgres",
"password": "healthai!",
"host": "health-ai-user-db.cxeum6cmct3r.eu-west-1.rds.amazonaws.com",
"port": 5432,
}
# Подключение к базе данных
try:
conn = psycopg2.connect(**DATABASE_CONFIG)
print("Подключение к базе данных успешно установлено")
except Exception as e:
print(f"Ошибка подключения к базе данных: {e}")
conn = None
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
# Создаем Flask приложение
app = Flask(__name__)
CORS(app, resources={r"/api/*": {"origins": "http://localhost:5173"}})
# Ваш Google Client ID
CLIENT_ID = "532143017111-4eqtlp0oejqaovj6rf5l1ergvhrp4vao.apps.googleusercontent.com"
def save_user_to_db(name, email, google_id=None, password=None):
try:
with conn.cursor(cursor_factory=RealDictCursor) as cur:
cur.execute(
"""
INSERT INTO users (name, email, google_id, password)
VALUES (%s, %s, %s, %s)
ON CONFLICT (email) DO NOTHING
""",
(name, email, google_id, password)
)
conn.commit()
print(f"User {name} ({email}) saved successfully!")
except Exception as e:
print(f"Error saving user to database: {e}")
# Эндпоинт для верификации токенов Google OAuth
@app.route('/api/verify', methods=['POST'])
def verify_token():
data = request.get_json()
token = data.get('token')
if not token:
return jsonify({'error': 'No token provided'}), 400
try:
id_info = id_token.verify_oauth2_token(token, requests.Request(), CLIENT_ID)
user_email = id_info.get('email')
user_name = id_info.get('name')
google_id = id_info.get('sub') # Уникальный идентификатор пользователя Google
save_user_to_db(name=user_name, email=user_email, google_id=google_id)
logger.info(f"User authenticated and saved: {user_name} ({user_email})")
return jsonify({'message': 'Authentication successful', 'user': {'email': user_email, 'name': user_name}}), 200
except ValueError as e:
logger.error(f"Token verification failed: {e}")
return jsonify({'error': 'Invalid token'}), 400
# Эндпоинт для регистрации пользователя с проверкой на дублирование
@app.route('/api/register', methods=['POST'])
def register():
data = request.get_json()
name = data.get('name')
email = data.get('email')
password = data.get('password') # Рекомендуется хэшировать пароль
if not all([name, email, password]):
return jsonify({'error': 'All fields are required'}), 400
try:
with conn.cursor(cursor_factory=RealDictCursor) as cur:
cur.execute("SELECT * FROM users WHERE email = %s", (email,))
existing_user = cur.fetchone()
if existing_user:
return jsonify({'error': 'User already exists'}), 409
save_user_to_db(name=name, email=email, password=password)
return jsonify({'message': 'User registered successfully'}), 201
except Exception as e:
return jsonify({'error': str(e)}), 500
# Эндпоинт для логина пользователя
@app.route('/api/login', methods=['POST'])
def login():
data = request.get_json()
email = data.get('email')
password = data.get('password')
if not all([email, password]):
return jsonify({'error': 'Email and password are required'}), 400
try:
with conn.cursor(cursor_factory=RealDictCursor) as cur:
cur.execute("SELECT * FROM users WHERE email = %s", (email,))
user = cur.fetchone()
if not user:
return jsonify({'error': 'Invalid credentials'}), 401
if user.get('password') != password:
return jsonify({'error': 'Invalid credentials'}), 401
return jsonify({'message': 'Login successful', 'user': {'name': user.get('name'), 'email': user.get('email')}}), 200
except Exception as e:
return jsonify({'error': str(e)}), 500
# Объединённый эндпоинт для обработки запроса чата
@app.route('/api/chat', methods=['POST'])
def chat():
data = request.get_json()
query = data.get('query', '')
user_email = data.get('email') # email пользователя (если передается)
chat_id = data.get('chatId') # параметр для обновления существующего чата
if not query:
return jsonify({'error': 'No query provided'}), 400
# Вызов функции для обработки запроса (например, чат-бота)
response_obj = process_query_with_mistral(query)
best_answer = ""
if isinstance(response_obj, dict):
best_answer = response_obj.get("best_answer", "")
else:
best_answer = str(response_obj)
# Форматирование ответа с использованием re.sub
best_answer = re.sub(r'[*#]', '', best_answer)
best_answer = re.sub(r'(\d\.\s)', r'\n\n\1', best_answer)
best_answer = re.sub(r':\s-', r':\n-', best_answer)
# Если chatId передан, обновляем существующий чат, иначе создаем новый чат
if chat_id:
try:
with conn.cursor(cursor_factory=RealDictCursor) as cur:
cur.execute("SELECT chat FROM chat_history WHERE id = %s", (chat_id,))
existing_chat = cur.fetchone()
if existing_chat:
updated_chat = existing_chat['chat'] + f"\nUser: {query}\nBot: {best_answer}"
cur.execute("UPDATE chat_history SET chat = %s WHERE id = %s", (updated_chat, chat_id))
conn.commit()
else:
with conn.cursor(cursor_factory=RealDictCursor) as cur2:
cur2.execute(
"INSERT INTO chat_history (user_email, chat) VALUES (%s, %s) RETURNING id",
(user_email, f"User: {query}\nBot: {best_answer}")
)
new_chat_id = cur2.fetchone()['id']
conn.commit()
chat_id = new_chat_id
except Exception as e:
return jsonify({'error': str(e)}), 500
else:
try:
with conn.cursor(cursor_factory=RealDictCursor) as cur:
cur.execute(
"INSERT INTO chat_history (user_email, chat) VALUES (%s, %s) RETURNING id",
(user_email, f"User: {query}\nBot: {best_answer}")
)
new_chat_id = cur.fetchone()['id']
conn.commit()
chat_id = new_chat_id
except Exception as e:
return jsonify({'error': str(e)}), 500
# Возвращаем текстовый ответ и новый chatId, если чат был создан
return jsonify({'response': {'best_answer': best_answer, 'model': 'Mistral Small Vector', 'chatId': chat_id}}), 200
# Эндпоинт для получения истории чатов конкретного пользователя
@app.route('/api/chat_history', methods=['GET'])
def get_chat_history():
user_email = request.args.get('email')
if not user_email:
return jsonify({'error': 'User email is required'}), 400
try:
with conn.cursor(cursor_factory=RealDictCursor) as cur:
cur.execute(
"SELECT id, chat, created_at FROM chat_history WHERE user_email = %s ORDER BY created_at DESC",
(user_email,)
)
history = cur.fetchall()
return jsonify({'history': history}), 200
except Exception as e:
return jsonify({'error': str(e)}), 500
# Эндпоинт для получения деталей чата по ID
@app.route('/api/chat_history_detail', methods=['GET'])
def chat_history_detail():
chat_id = request.args.get('id')
if not chat_id:
return jsonify({'error': 'Chat id is required'}), 400
try:
with conn.cursor(cursor_factory=RealDictCursor) as cur:
cur.execute("SELECT id, chat, created_at FROM chat_history WHERE id = %s", (chat_id,))
chat = cur.fetchone()
if not chat:
return jsonify({'error': 'Chat not found'}), 404
return jsonify({'chat': chat}), 200
except Exception as e:
return jsonify({'error': str(e)}), 500
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000, debug=True)