| |
|
| | import os
|
| | import anthropic
|
| | import streamlit as st
|
| | import time
|
| | import json
|
| | import base64
|
| | import logging
|
| |
|
| | from datetime import datetime, timezone
|
| | from io import BytesIO
|
| |
|
| |
|
| | from ..utils.widget_utils import generate_unique_key
|
| | from ..database.chat_mongo_db import store_chat_history
|
| |
|
| | logger = logging.getLogger(__name__)
|
| |
|
| |
|
| | conversation_cache = {}
|
| |
|
| | def get_conversation_cache_key(text, metrics, graph_data, lang_code):
|
| | """
|
| | Generate a cache key for conversations based on analysis data.
|
| | """
|
| | text_hash = hash(text[:1000])
|
| | metrics_hash = hash(json.dumps(metrics, sort_keys=True))
|
| | graph_hash = hash(graph_data[:100]) if graph_data else 0
|
| | return f"{text_hash}_{metrics_hash}_{graph_hash}_{lang_code}"
|
| |
|
| | def format_semantic_context(text, metrics, graph_data, lang_code):
|
| | """
|
| | Format the semantic analysis data for Claude's context.
|
| | """
|
| | formatted_data = {
|
| | 'text_sample': text[:2000],
|
| | 'key_concepts': metrics.get('key_concepts', []),
|
| | 'concept_centrality': metrics.get('concept_centrality', {}),
|
| | 'graph_description': "Network graph available" if graph_data else "No graph available",
|
| | 'language': lang_code
|
| | }
|
| |
|
| | return json.dumps(formatted_data, indent=2, ensure_ascii=False)
|
| |
|
| | def initiate_semantic_conversation(text, metrics, graph_data, lang_code):
|
| | """
|
| | Start a conversation with Claude about semantic analysis results.
|
| | """
|
| | try:
|
| | api_key = os.environ.get("ANTHROPIC_API_KEY")
|
| | if not api_key:
|
| | logger.error("Claude API key not found in environment variables")
|
| | return get_fallback_response(lang_code)
|
| |
|
| |
|
| | cache_key = get_conversation_cache_key(text, metrics, graph_data, lang_code)
|
| | if cache_key in conversation_cache:
|
| | logger.info("Using cached conversation starter")
|
| | return conversation_cache[cache_key]
|
| |
|
| |
|
| | context = format_semantic_context(text, metrics, graph_data, lang_code)
|
| |
|
| |
|
| | if lang_code == 'es':
|
| | system_prompt = """Eres un asistente especializado en análisis semántico de textos.
|
| | El usuario ha analizado un texto y quiere discutir los resultados contigo.
|
| | Estos son los datos del análisis:
|
| | - Fragmento del texto analizado
|
| | - Lista de conceptos clave identificados
|
| | - Medidas de centralidad de los conceptos
|
| | - Un grafo de relaciones conceptuales (si está disponible)
|
| |
|
| | Tu rol es:
|
| | 1. Demostrar comprensión del análisis mostrado
|
| | 2. Hacer preguntas relevantes sobre los resultados
|
| | 3. Ayudar al usuario a interpretar los hallazgos
|
| | 4. Sugerir posibles direcciones para profundizar el análisis
|
| |
|
| | Usa un tono profesional pero accesible. Sé conciso pero claro.
|
| | """
|
| | user_prompt = f"""Aquí están los resultados del análisis semántico:
|
| |
|
| | {context}
|
| |
|
| | Por favor:
|
| | 1. Haz un breve resumen de lo que notas en los resultados
|
| | 2. Formula 2-3 preguntas interesantes que podríamos explorar sobre estos datos
|
| | 3. Sugiere un aspecto del análisis que podría profundizarse
|
| |
|
| | Mantén tu respuesta bajo 250 palabras."""
|
| |
|
| | elif lang_code == 'fr':
|
| | system_prompt = """Vous êtes un assistant spécialisé dans l'analyse sémantique de textes.
|
| | L'utilisateur a analysé un texte et souhaite discuter des résultats avec vous.
|
| | Voici les données d'analyse:
|
| | - Extrait du texte analysé
|
| | - Liste des concepts clés identifiés
|
| | - Mesures de centralité des concepts
|
| | - Un graphique des relations conceptuelles (si disponible)
|
| |
|
| | Votre rôle est:
|
| | 1. Démontrer une compréhension de l'analyse présentée
|
| | 2. Poser des questions pertinentes sur les résultats
|
| | 3. Aider l'utilisateur à interpréter les résultats
|
| | 4. Proposer des pistes pour approfondir l'analyse
|
| |
|
| | Utilisez un ton professionnel mais accessible. Soyez concis mais clair.
|
| | """
|
| | user_prompt = f"""Voici les résultats de l'analyse sémantique:
|
| |
|
| | {context}
|
| |
|
| | Veuillez:
|
| | 1. Faire un bref résumé de ce que vous remarquez dans les résultats
|
| | 2. Formuler 2-3 questions intéressantes que nous pourrions explorer
|
| | 3. Suggérer un aspect de l'analyse qui pourrait être approfondi
|
| |
|
| | Limitez votre réponse à 250 mots."""
|
| |
|
| | elif lang_code == 'pt':
|
| | system_prompt = """Você é um assistente especializado em análise semântica de textos.
|
| | O usuário analisou um texto e quer discutir os resultados com você.
|
| | Aqui estão os dados da análise:
|
| | - Trecho do texto analisado
|
| | - Lista de conceitos-chave identificados
|
| | - Medidas de centralidade dos conceitos
|
| | - Um grafo de relações conceituais (se disponível)
|
| |
|
| | Seu papel é:
|
| | 1. Demonstrar compreensão da análise apresentada
|
| | 2. Fazer perguntas relevantes sobre os resultados
|
| | 3. Ajudar o usuário a interpretar os achados
|
| | 4. Sugerir possíveis direções para aprofundar a análise
|
| |
|
| | Use um tom profissional mas acessível. Seja conciso mas claro.
|
| | """
|
| | user_prompt = f"""Aqui estão os resultados da análise semântica:
|
| |
|
| | {context}
|
| |
|
| | Por favor:
|
| | 1. Faça um breve resumo do que você nota nos resultados
|
| | 2. Formule 2-3 perguntas interessantes que poderíamos explorar
|
| | 3. Sugira um aspecto da análise que poderia ser aprofundado
|
| |
|
| | Mantenha sua resposta em até 250 palavras."""
|
| |
|
| | else:
|
| | system_prompt = """You are an assistant specialized in semantic text analysis.
|
| | The user has analyzed a text and wants to discuss the results with you.
|
| | Here is the analysis data:
|
| | - Sample of the analyzed text
|
| | - List of identified key concepts
|
| | - Concept centrality measures
|
| | - A concept relationship graph (if available)
|
| |
|
| | Your role is to:
|
| | 1. Demonstrate understanding of the shown analysis
|
| | 2. Ask relevant questions about the results
|
| | 3. Help the user interpret the findings
|
| | 4. Suggest possible directions to deepen the analysis
|
| |
|
| | Use a professional but accessible tone. Be concise but clear.
|
| | """
|
| | user_prompt = f"""Here are the semantic analysis results:
|
| |
|
| | {context}
|
| |
|
| | Please:
|
| | 1. Give a brief summary of what you notice in the results
|
| | 2. Formulate 2-3 interesting questions we could explore
|
| | 3. Suggest one aspect of the analysis that could be deepened
|
| |
|
| | Keep your response under 250 words."""
|
| |
|
| |
|
| | client = anthropic.Anthropic(api_key=api_key)
|
| |
|
| |
|
| | start_time = time.time()
|
| | response = client.messages.create(
|
| | model="claude-3-sonnet-20240229",
|
| | max_tokens=1024,
|
| | temperature=0.7,
|
| | system=system_prompt,
|
| | messages=[
|
| | {"role": "user", "content": user_prompt}
|
| | ]
|
| | )
|
| | logger.info(f"Claude API call completed in {time.time() - start_time:.2f} seconds")
|
| |
|
| |
|
| | initial_response = response.content[0].text
|
| |
|
| |
|
| | conversation_cache[cache_key] = initial_response
|
| |
|
| | return initial_response
|
| |
|
| | except Exception as e:
|
| | logger.error(f"Error initiating semantic conversation: {str(e)}")
|
| | return get_fallback_response(lang_code)
|
| |
|
| | def continue_conversation(conversation_history, new_message, lang_code):
|
| | """
|
| | Continue an existing conversation about semantic analysis.
|
| | """
|
| | try:
|
| | api_key = os.environ.get("ANTHROPIC_API_KEY")
|
| | if not api_key:
|
| | logger.error("Claude API key not found in environment variables")
|
| | return get_fallback_response(lang_code)
|
| |
|
| |
|
| | messages = []
|
| | for msg in conversation_history:
|
| | messages.append({
|
| | "role": "user" if msg["sender"] == "user" else "assistant",
|
| | "content": msg["message"]
|
| | })
|
| |
|
| |
|
| | messages.append({"role": "user", "content": new_message})
|
| |
|
| |
|
| | if lang_code == 'es':
|
| | system_prompt = """Continúa la conversación sobre el análisis semántico.
|
| | Sé conciso pero útil. Responde en español."""
|
| | elif lang_code == 'fr':
|
| | system_prompt = """Continuez la conversation sur l'analyse sémantique.
|
| | Soyez concis mais utile. Répondez en français."""
|
| | elif lang_code == 'pt':
|
| | system_prompt = """Continue a conversa sobre a análise semântica.
|
| | Seja conciso mas útil. Responda em português."""
|
| | else:
|
| | system_prompt = """Continue the conversation about semantic analysis.
|
| | Be concise but helpful. Respond in English."""
|
| |
|
| |
|
| | client = anthropic.Anthropic(api_key=api_key)
|
| |
|
| |
|
| | response = client.messages.create(
|
| | model="claude-3-sonnet-20240229",
|
| | max_tokens=1024,
|
| | temperature=0.7,
|
| | system=system_prompt,
|
| | messages=messages
|
| | )
|
| |
|
| | return response.content[0].text
|
| |
|
| | except Exception as e:
|
| | logger.error(f"Error continuing semantic conversation: {str(e)}")
|
| | return get_fallback_response(lang_code)
|
| |
|
| | def get_fallback_response(lang_code):
|
| | """
|
| | Return fallback response if Claude API fails.
|
| | """
|
| | if lang_code == 'es':
|
| | return """Parece que hay un problema técnico. Por favor intenta de nuevo más tarde.
|
| |
|
| | Mientras tanto, aquí hay algunas preguntas que podrías considerar sobre tu análisis:
|
| | 1. ¿Qué conceptos tienen la mayor centralidad y por qué podría ser?
|
| | 2. ¿Hay conexiones inesperadas entre conceptos en tu grafo?
|
| | 3. ¿Cómo podrías profundizar en las relaciones entre los conceptos clave?"""
|
| |
|
| | elif lang_code == 'fr':
|
| | return """Il semble y avoir un problème technique. Veuillez réessayer plus tard.
|
| |
|
| | En attendant, voici quelques questions que vous pourriez considérer:
|
| | 1. Quels concepts ont la plus grande centralité et pourquoi?
|
| | 2. Y a-t-il des connexions inattendues entre les concepts?
|
| | 3. Comment pourriez-vous approfondir les relations entre les concepts clés?"""
|
| |
|
| | elif lang_code == 'pt':
|
| | return """Parece haver um problema técnico. Por favor, tente novamente mais tarde.
|
| |
|
| | Enquanto isso, aqui estão algumas perguntas que você poderia considerar:
|
| | 1. Quais conceitos têm maior centralidade e por que isso pode ocorrer?
|
| | 2. Há conexões inesperadas entre conceitos no seu grafo?
|
| | 3. Como você poderia aprofundar as relações entre os conceitos-chave?"""
|
| |
|
| | else:
|
| | return """There seems to be a technical issue. Please try again later.
|
| |
|
| | Meanwhile, here are some questions you might consider about your analysis:
|
| | 1. Which concepts have the highest centrality and why might that be?
|
| | 2. Are there unexpected connections between concepts in your graph?
|
| | 3. How could you explore the relationships between key concepts further?"""
|
| |
|
| | def store_conversation(username, text, metrics, graph_data, conversation):
|
| | try:
|
| | result = store_chat_history(
|
| | username=username,
|
| | messages=conversation,
|
| | analysis_type='semantic_analysis',
|
| | metadata={
|
| | 'text_sample': text[:500],
|
| | 'key_concepts': metrics.get('key_concepts', []),
|
| | 'graph_available': bool(graph_data)
|
| | }
|
| | )
|
| | logger.info(f"Conversación semántica guardada: {result}")
|
| | return result
|
| | except Exception as e:
|
| | logger.error(f"Error almacenando conversación semántica: {str(e)}")
|
| | return False
|
| |
|
| | def display_semantic_chat(text, metrics, graph_data, lang_code, t):
|
| | """
|
| | Display the chat interface for semantic analysis discussion.
|
| | """
|
| | try:
|
| |
|
| | if 'semantic_chat' not in st.session_state:
|
| | st.session_state.semantic_chat = {
|
| | 'history': [],
|
| | 'initialized': False
|
| | }
|
| |
|
| |
|
| | chat_container = st.container()
|
| |
|
| |
|
| | if not st.session_state.semantic_chat['initialized']:
|
| | with st.spinner(t.get('initializing_chat', 'Initializing conversation...')):
|
| | initial_response = initiate_semantic_conversation(
|
| | text, metrics, graph_data, lang_code
|
| | )
|
| |
|
| | st.session_state.semantic_chat['history'].append({
|
| | "sender": "assistant",
|
| | "message": initial_response
|
| | })
|
| | st.session_state.semantic_chat['initialized'] = True
|
| |
|
| |
|
| | if 'username' in st.session_state:
|
| | store_conversation(
|
| | st.session_state.username,
|
| | text,
|
| | metrics,
|
| | graph_data,
|
| | st.session_state.semantic_chat['history']
|
| | )
|
| |
|
| |
|
| | with chat_container:
|
| | st.markdown("### 💬 " + t.get('semantic_discussion', 'Semantic Analysis Discussion'))
|
| |
|
| | for msg in st.session_state.semantic_chat['history']:
|
| | if msg["sender"] == "user":
|
| | st.chat_message("user").write(msg["message"])
|
| | else:
|
| | st.chat_message("assistant").write(msg["message"])
|
| |
|
| |
|
| | user_input = st.chat_input(
|
| | t.get('chat_input_placeholder', 'Ask about your semantic analysis...')
|
| | )
|
| |
|
| | if user_input:
|
| |
|
| | st.session_state.semantic_chat['history'].append({
|
| | "sender": "user",
|
| | "message": user_input
|
| | })
|
| |
|
| |
|
| | with chat_container:
|
| | st.chat_message("user").write(user_input)
|
| | with st.spinner(t.get('assistant_thinking', 'Assistant is thinking...')):
|
| |
|
| | assistant_response = continue_conversation(
|
| | st.session_state.semantic_chat['history'],
|
| | user_input,
|
| | lang_code
|
| | )
|
| |
|
| |
|
| | st.session_state.semantic_chat['history'].append({
|
| | "sender": "assistant",
|
| | "message": assistant_response
|
| | })
|
| |
|
| |
|
| | st.chat_message("assistant").write(assistant_response)
|
| |
|
| |
|
| | if 'username' in st.session_state:
|
| | store_conversation(
|
| | st.session_state.username,
|
| | text,
|
| | metrics,
|
| | graph_data,
|
| | st.session_state.semantic_chat['history']
|
| | )
|
| |
|
| | except Exception as e:
|
| | logger.error(f"Error displaying semantic chat: {str(e)}")
|
| | st.error(t.get('chat_error', 'Error in chat interface. Please try again.')) |