| | |
| | import logging |
| | import os |
| | from azure.cosmos import CosmosClient |
| | from azure.cosmos.exceptions import CosmosHttpResponseError |
| | from pymongo import MongoClient |
| | import certifi |
| | from datetime import datetime |
| | import io |
| | from io import BytesIO |
| | import base64 |
| | import matplotlib.pyplot as plt |
| | from matplotlib.figure import Figure |
| | import bcrypt |
| | print(f"Bcrypt version: {bcrypt.__version__}") |
| | import uuid |
| | import plotly.graph_objects as go |
| | import numpy as np |
| | logging.basicConfig(level=logging.DEBUG) |
| | logger = logging.getLogger(__name__) |
| |
|
| | |
| | application_requests_container = None |
| | cosmos_client = None |
| | user_database = None |
| | user_container = None |
| | user_feedback_container = None |
| |
|
| | |
| | mongo_client = None |
| | mongo_db = None |
| | analysis_collection = None |
| | chat_collection = None |
| |
|
| |
|
| | |
| | def initialize_database_connections(): |
| | try: |
| | print("Iniciando conexi贸n a MongoDB") |
| | mongodb_success = initialize_mongodb_connection() |
| | print(f"Conexi贸n a MongoDB: {'exitosa' if mongodb_success else 'fallida'}") |
| | except Exception as e: |
| | print(f"Error al conectar con MongoDB: {str(e)}") |
| | mongodb_success = False |
| |
|
| | try: |
| | print("Iniciando conexi贸n a Cosmos DB SQL API") |
| | sql_success = initialize_cosmos_sql_connection() |
| | print(f"Conexi贸n a Cosmos DB SQL API: {'exitosa' if sql_success else 'fallida'}") |
| | except Exception as e: |
| | print(f"Error al conectar con Cosmos DB SQL API: {str(e)}") |
| | sql_success = False |
| |
|
| | return { |
| | "mongodb": mongodb_success, |
| | "cosmos_sql": sql_success |
| | } |
| |
|
| | |
| | def initialize_cosmos_sql_connection(): |
| | global cosmos_client, user_database, user_container, application_requests_container, user_feedback_container |
| | logger.info("Initializing Cosmos DB SQL API connection") |
| | try: |
| | cosmos_endpoint = os.environ.get("COSMOS_ENDPOINT") |
| | cosmos_key = os.environ.get("COSMOS_KEY") |
| | logger.info(f"Cosmos Endpoint: {cosmos_endpoint}") |
| | logger.info(f"Cosmos Key: {'*' * len(cosmos_key) if cosmos_key else 'Not set'}") |
| | |
| | if not cosmos_endpoint or not cosmos_key: |
| | logger.error("COSMOS_ENDPOINT or COSMOS_KEY environment variables are not set") |
| | raise ValueError("Las variables de entorno COSMOS_ENDPOINT y COSMOS_KEY deben estar configuradas") |
| | |
| | cosmos_client = CosmosClient(cosmos_endpoint, cosmos_key) |
| | user_database = cosmos_client.get_database_client("user_database") |
| | user_container = user_database.get_container_client("users") |
| | application_requests_container = user_database.get_container_client("application_requests") |
| | user_feedback_container = user_database.get_container_client("user_feedback") |
| | |
| | logger.info(f"user_container initialized: {user_container is not None}") |
| | logger.info(f"application_requests_container initialized: {application_requests_container is not None}") |
| | logger.info(f"user_feedback_container initialized: {user_feedback_container is not None}") |
| | |
| | logger.info("Conexi贸n a Cosmos DB SQL API exitosa") |
| | return True |
| | except Exception as e: |
| | logger.error(f"Error al conectar con Cosmos DB SQL API: {str(e)}", exc_info=True) |
| | return False |
| |
|
| | |
| | def initialize_mongodb_connection(): |
| | global mongo_client, mongo_db, analysis_collection, chat_collection |
| | try: |
| | cosmos_mongodb_connection_string = os.getenv("MONGODB_CONNECTION_STRING") |
| | if not cosmos_mongodb_connection_string: |
| | logger.error("La variable de entorno MONGODB_CONNECTION_STRING no est谩 configurada") |
| | return False |
| |
|
| | mongo_client = MongoClient(cosmos_mongodb_connection_string, |
| | tls=True, |
| | tlsCAFile=certifi.where(), |
| | retryWrites=False, |
| | serverSelectionTimeoutMS=5000, |
| | connectTimeoutMS=10000, |
| | socketTimeoutMS=10000) |
| |
|
| | mongo_client.admin.command('ping') |
| | |
| | mongo_db = mongo_client['aideatext_db'] |
| | analysis_collection = mongo_db['text_analysis'] |
| | chat_collection = mongo_db['chat_history'] |
| |
|
| | |
| | mongo_client.admin.command('ping') |
| | |
| | logger.info("Conexi贸n a Cosmos DB MongoDB API exitosa") |
| | return True |
| | except Exception as e: |
| | logger.error(f"Error al conectar con Cosmos DB MongoDB API: {str(e)}", exc_info=True) |
| | return False |
| |
|
| | |
| | def create_user(username, password, role): |
| | global user_container |
| | try: |
| | print(f"Attempting to create user: {username} with role: {role}") |
| | if user_container is None: |
| | print("Error: user_container is None. Attempting to reinitialize connection.") |
| | if not initialize_cosmos_sql_connection(): |
| | raise Exception("Failed to initialize SQL connection") |
| | |
| | hashed_password = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt()).decode('utf-8') |
| | print(f"Password hashed successfully for user: {username}") |
| | user_data = { |
| | 'id': username, |
| | 'password': hashed_password, |
| | 'role': role, |
| | 'created_at': datetime.utcnow().isoformat() |
| | } |
| | user_container.create_item(body=user_data) |
| | print(f"Usuario {role} creado: {username}") |
| | return True |
| | except Exception as e: |
| | print(f"Detailed error in create_user: {str(e)}") |
| | return False |
| |
|
| | |
| | def create_admin_user(username, password): |
| | return create_user(username, password, 'Administrador') |
| | |
| | |
| | def create_student_user(username, password): |
| | return create_user(username, password, 'Estudiante') |
| | |
| | |
| | |
| | def get_user(username): |
| | try: |
| | query = f"SELECT * FROM c WHERE c.id = '{username}'" |
| | items = list(user_container.query_items(query=query, enable_cross_partition_query=True)) |
| | user = items[0] if items else None |
| | if user: |
| | print(f"Usuario encontrado: {username}, Rol: {user.get('role')}") |
| | else: |
| | print(f"Usuario no encontrado: {username}") |
| | return user |
| | except Exception as e: |
| | print(f"Error al obtener usuario {username}: {str(e)}") |
| | return None |
| |
|
| | |
| | def store_application_request(name, email, institution, role, reason): |
| | global application_requests_container |
| | logger.info("Entering store_application_request function") |
| | try: |
| | logger.info("Checking application_requests_container") |
| | if application_requests_container is None: |
| | logger.error("application_requests_container is not initialized") |
| | return False |
| |
|
| | logger.info("Creating application request document") |
| | application_request = { |
| | "id": str(uuid.uuid4()), |
| | "name": name, |
| | "email": email, |
| | "institution": institution, |
| | "role": role, |
| | "reason": reason, |
| | "requestDate": datetime.utcnow().isoformat() |
| | } |
| |
|
| | logger.info(f"Attempting to store document: {application_request}") |
| | application_requests_container.create_item(body=application_request) |
| | logger.info(f"Application request stored for email: {email}") |
| | return True |
| | except Exception as e: |
| | logger.error(f"Error storing application request: {str(e)}") |
| | return False |
| | |
| | |
| | def store_user_feedback(username, name, email, feedback): |
| | global user_feedback_container |
| | logger.info(f"Attempting to store user feedback for user: {username}") |
| | try: |
| | if user_feedback_container is None: |
| | logger.error("user_feedback_container is not initialized") |
| | return False |
| |
|
| | feedback_item = { |
| | "id": str(uuid.uuid4()), |
| | "username": username, |
| | "name": name, |
| | "email": email, |
| | "feedback": feedback, |
| | "timestamp": datetime.utcnow().isoformat() |
| | } |
| |
|
| | result = user_feedback_container.create_item(body=feedback_item) |
| | logger.info(f"User feedback stored with ID: {result['id']} for user: {username}") |
| | return True |
| | except Exception as e: |
| | logger.error(f"Error storing user feedback for user {username}: {str(e)}") |
| | return False |
| |
|
| |
|
| | |
| |
|
| | def store_morphosyntax_result(username, text, repeated_words, arc_diagrams, pos_analysis, morphological_analysis, sentence_structure): |
| | if analysis_collection is None: |
| | logger.error("La conexi贸n a MongoDB no est谩 inicializada") |
| | return False |
| |
|
| | try: |
| | word_count = {} |
| | for word, color in repeated_words.items(): |
| | category = color |
| | word_count[category] = word_count.get(category, 0) + 1 |
| |
|
| | analysis_document = { |
| | 'username': username, |
| | 'timestamp': datetime.utcnow(), |
| | 'text': text, |
| | 'word_count': word_count, |
| | 'arc_diagrams': arc_diagrams, |
| | 'pos_analysis': pos_analysis, |
| | 'morphological_analysis': morphological_analysis, |
| | 'sentence_structure': sentence_structure |
| | } |
| |
|
| | result = analysis_collection.insert_one(analysis_document) |
| | logger.info(f"An谩lisis guardado con ID: {result.inserted_id} para el usuario: {username}") |
| | return True |
| | except Exception as e: |
| | logger.error(f"Error al guardar el an谩lisis para el usuario {username}: {str(e)}") |
| | return False |
| |
|
| | |
| | def store_semantic_result(username, text, analysis_result): |
| | if analysis_collection is None: |
| | print("La conexi贸n a MongoDB no est谩 inicializada") |
| | return False |
| | try: |
| | |
| | key_concepts = [(concept, float(frequency)) for concept, frequency in analysis_result['key_concepts']] |
| | |
| | |
| | buf = BytesIO() |
| | analysis_result['relations_graph'].savefig(buf, format='png') |
| | buf.seek(0) |
| | img_str = base64.b64encode(buf.getvalue()).decode('utf-8') |
| | |
| | analysis_document = { |
| | 'username': username, |
| | 'timestamp': datetime.utcnow(), |
| | 'key_concepts': key_concepts, |
| | 'graph': img_str, |
| | 'analysis_type': 'semantic' |
| | } |
| | |
| | result = analysis_collection.insert_one(analysis_document) |
| | print(f"An谩lisis sem谩ntico guardado con ID: {result.inserted_id} para el usuario: {username}") |
| | return True |
| | except Exception as e: |
| | print(f"Error al guardar el an谩lisis sem谩ntico para el usuario {username}: {str(e)}") |
| | return False |
| |
|
| | |
| |
|
| | def store_discourse_analysis_result(username, text1, text2, analysis_result): |
| | if analysis_collection is None: |
| | print("La conexi贸n a MongoDB no est谩 inicializada") |
| | return False |
| | |
| | try: |
| | |
| | buf1 = BytesIO() |
| | analysis_result['graph1'].savefig(buf1, format='png') |
| | buf1.seek(0) |
| | img_str1 = base64.b64encode(buf1.getvalue()).decode('utf-8') |
| |
|
| | buf2 = BytesIO() |
| | analysis_result['graph2'].savefig(buf2, format='png') |
| | buf2.seek(0) |
| | img_str2 = base64.b64encode(buf2.getvalue()).decode('utf-8') |
| |
|
| | |
| | fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(20, 10)) |
| | ax1.imshow(plt.imread(BytesIO(base64.b64decode(img_str1)))) |
| | ax1.axis('off') |
| | ax1.set_title("Documento 1: Relaciones Conceptuales") |
| | ax2.imshow(plt.imread(BytesIO(base64.b64decode(img_str2)))) |
| | ax2.axis('off') |
| | ax2.set_title("Documento 2: Relaciones Conceptuales") |
| | |
| | buf_combined = BytesIO() |
| | fig.savefig(buf_combined, format='png') |
| | buf_combined.seek(0) |
| | img_str_combined = base64.b64encode(buf_combined.getvalue()).decode('utf-8') |
| | plt.close(fig) |
| |
|
| | |
| | key_concepts1 = [(concept, float(frequency)) for concept, frequency in analysis_result['key_concepts1']] |
| | key_concepts2 = [(concept, float(frequency)) for concept, frequency in analysis_result['key_concepts2']] |
| |
|
| | |
| | analysis_document = { |
| | 'username': username, |
| | 'timestamp': datetime.utcnow(), |
| | |
| | |
| | 'graph1': img_str1, |
| | 'graph2': img_str2, |
| | 'combined_graph': img_str_combined, |
| | 'key_concepts1': key_concepts1, |
| | 'key_concepts2': key_concepts2, |
| | 'analysis_type': 'discourse' |
| | } |
| |
|
| | |
| | result = analysis_collection.insert_one(analysis_document) |
| | print(f"An谩lisis discursivo guardado con ID: {result.inserted_id} para el usuario: {username}") |
| | return True |
| | except Exception as e: |
| | print(f"Error al guardar el an谩lisis discursivo para el usuario {username}: {str(e)}") |
| | print(f"Tipo de excepci贸n: {type(e).__name__}") |
| | print(f"Detalles de la excepci贸n: {e.args}") |
| | return False |
| |
|
| | |
| | def store_chat_history(username, messages): |
| | try: |
| | logger.info(f"Attempting to save chat history for user: {username}") |
| | logger.debug(f"Messages to save: {messages}") |
| | |
| | chat_document = { |
| | 'username': username, |
| | 'timestamp': datetime.utcnow(), |
| | 'messages': messages |
| | } |
| | result = chat_collection.insert_one(chat_document) |
| | logger.info(f"Chat history saved with ID: {result.inserted_id} for user: {username}") |
| | logger.debug(f"Chat content: {messages}") |
| | return True |
| | except Exception as e: |
| | logger.error(f"Error saving chat history for user {username}: {str(e)}") |
| | return False |
| |
|
| | |
| | def get_student_data(username): |
| | if analysis_collection is None or chat_collection is None: |
| | logger.error("La conexi贸n a MongoDB no est谩 inicializada") |
| | return None |
| | formatted_data = { |
| | "username": username, |
| | "entries": [], |
| | "entries_count": 0, |
| | "word_count": {}, |
| | "semantic_analyses": [], |
| | "discourse_analyses": [], |
| | "chat_history": [] |
| | } |
| | try: |
| | logger.info(f"Buscando datos de an谩lisis para el usuario: {username}") |
| | cursor = analysis_collection.find({"username": username}) |
| | |
| | for entry in cursor: |
| | formatted_entry = { |
| | "timestamp": entry.get("timestamp", datetime.utcnow()), |
| | "analysis_type": entry.get("analysis_type", "morphosyntax") |
| | } |
| | |
| | if formatted_entry["analysis_type"] == "morphosyntax": |
| | formatted_entry.update({ |
| | "text": entry.get("text", ""), |
| | "word_count": entry.get("word_count", {}), |
| | "arc_diagrams": entry.get("arc_diagrams", []) |
| | }) |
| | for category, count in formatted_entry["word_count"].items(): |
| | formatted_data["word_count"][category] = formatted_data["word_count"].get(category, 0) + count |
| | |
| | elif formatted_entry["analysis_type"] == "semantic": |
| | formatted_entry.update({ |
| | "key_concepts": entry.get("key_concepts", []), |
| | "graph": entry.get("graph", "") |
| | }) |
| | formatted_data["semantic_analyses"].append(formatted_entry) |
| | |
| | elif formatted_entry["analysis_type"] == "discourse": |
| | formatted_entry.update({ |
| | "text1": entry.get("text1", ""), |
| | "text2": entry.get("text2", ""), |
| | "key_concepts1": entry.get("key_concepts1", []), |
| | "key_concepts2": entry.get("key_concepts2", []), |
| | "graph1": entry.get("graph1", ""), |
| | "graph2": entry.get("graph2", ""), |
| | "combined_graph": entry.get("combined_graph", "") |
| | }) |
| | formatted_data["discourse_analyses"].append(formatted_entry) |
| | |
| | formatted_data["entries"].append(formatted_entry) |
| | |
| | formatted_data["entries_count"] = len(formatted_data["entries"]) |
| | formatted_data["entries"].sort(key=lambda x: x["timestamp"], reverse=True) |
| | |
| | for entry in formatted_data["entries"]: |
| | entry["timestamp"] = entry["timestamp"].isoformat() |
| | |
| | except Exception as e: |
| | logger.error(f"Error al obtener datos de an谩lisis del estudiante {username}: {str(e)}") |
| | |
| | try: |
| | logger.info(f"Buscando historial de chat para el usuario: {username}") |
| | chat_cursor = chat_collection.find({"username": username}) |
| | for chat in chat_cursor: |
| | formatted_chat = { |
| | "timestamp": chat["timestamp"].isoformat(), |
| | "messages": chat["messages"] |
| | } |
| | formatted_data["chat_history"].append(formatted_chat) |
| | |
| | formatted_data["chat_history"].sort(key=lambda x: x["timestamp"], reverse=True) |
| | |
| | except Exception as e: |
| | logger.error(f"Error al obtener historial de chat del estudiante {username}: {str(e)}") |
| | logger.info(f"Datos formateados para {username}: {formatted_data}") |
| | return formatted_data |