v5Dev / src /modules /chatbot /chat_process.py
AIdeaText's picture
Upload 281 files
24060c9 verified
raw
history blame
5.76 kB
# 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")