# modules/chatbot/chat_process.py import os import anthropic import logging from typing import Generator logger = logging.getLogger(__name__) class ChatProcessor: def __init__(self): """Inicializa el procesador de chat con la API de Claude""" self.client = anthropic.Anthropic( api_key=os.environ.get("ANTHROPIC_API_KEY") ) self.conversation_history = [] self.semantic_context = None self.current_lang = 'en' def set_semantic_context(self, text, metrics, graph_data, lang_code='en'): """Configura el contexto semántico completo para el chat""" if not text or not metrics: logger.error("Faltan datos esenciales para el contexto semántico") raise ValueError("Texto y métricas son requeridos") self.semantic_context = { 'full_text': text, # Texto completo del documento 'key_concepts': metrics.get('key_concepts', []), 'concept_centrality': metrics.get('concept_centrality', {}), 'graph_available': graph_data is not None, 'language': lang_code } self.current_lang = lang_code self.conversation_history = [] logger.info("Contexto semántico configurado correctamente") def _get_system_prompt(self): """Genera el prompt del sistema con todo el contexto necesario""" if not self.semantic_context: return "You are a helpful assistant." concepts = self.semantic_context['key_concepts'] top_concepts = ", ".join([f"{c[0]} ({c[1]:.2f})" for c in concepts[:5]]) prompts = { 'en': f"""You are a semantic analysis expert. The user analyzed a research article. Full text available (abbreviated for context). Key concepts: {top_concepts} Graph available: {self.semantic_context['graph_available']} Your tasks: 1. Answer questions about concepts and their relationships 2. Explain the semantic network structure 3. Suggest text improvements 4. Provide insights based on concept centrality""", 'es': f"""Eres un experto en análisis semántico. El usuario analizó un artículo de investigación. Texto completo disponible (abreviado para contexto). Conceptos clave: {top_concepts} Gráfico disponible: {self.semantic_context['graph_available']} Tus tareas: 1. Responder preguntas sobre conceptos y sus relaciones 2. Explicar la estructura de la red semántica 3. Sugerir mejoras al texto 4. Proporcionar insights basados en centralidad de conceptos""", 'pt': f"""Você é um especialista em análise semântica. O usuário analisou um artigo de pesquisa. Texto completo disponível (abreviado para contexto). Conceitos-chave: {top_concepts} Gráfico disponível: {self.semantic_context['graph_available']} Suas tarefas: 1. Responder perguntas sobre conceitos e suas relações 2. Explicar a estrutura da rede semântica 3. Sugerir melhorias no texto 4. Fornecer insights com base na centralidade dos conceitos""" } return prompts.get(self.current_lang, prompts['en']) def process_chat_input(self, message: str, lang_code: str) -> Generator[str, None, None]: """Procesa el mensaje con todo el contexto disponible""" try: if not self.semantic_context: yield "Error: Contexto semántico no configurado. Recargue el análisis." return # Actualizar idioma si es diferente if lang_code != self.current_lang: self.current_lang = lang_code logger.info(f"Idioma cambiado a: {lang_code}") # Construir historial de mensajes messages = [ { "role": "user", "content": f"Documento analizado (extracto):\n{self.semantic_context['full_text'][:2000]}..." }, *self.conversation_history, {"role": "user", "content": message} ] # Llamar a Claude con streaming with self.client.messages.stream( model="claude-3-sonnet-20240229", max_tokens=4000, temperature=0.7, system=self._get_system_prompt(), messages=messages ) as stream: full_response = "" for chunk in stream.text_stream: full_response += chunk yield chunk + "▌" # Guardar respuesta en historial self.conversation_history.extend([ {"role": "user", "content": message}, {"role": "assistant", "content": full_response} ]) logger.info("Respuesta generada y guardada en historial") except Exception as e: logger.error(f"Error en process_chat_input: {str(e)}", exc_info=True) yield { 'en': "Error processing message. Please reload the analysis.", 'es': "Error al procesar mensaje. Recargue el análisis.", 'pt': "Erro ao processar mensagem. Recarregue a análise." }.get(self.current_lang, "Processing error")