File size: 17,274 Bytes
24060c9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
# modules/semantic/semantic_agent_interaction.py
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

# Local imports
from ..utils.widget_utils import generate_unique_key
from ..database.chat_mongo_db import store_chat_history

logger = logging.getLogger(__name__)

# Cache for conversation history to avoid redundant API calls
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])  # Only use first 1000 chars for hashing
    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],  # Limit text sample
        '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)
        
        # Check cache first
        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]
        
        # Format context for Claude
        context = format_semantic_context(text, metrics, graph_data, lang_code)
        
        # Determine language for prompt
        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:  # Default to English
            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."""
        
        # Initialize Claude client
        client = anthropic.Anthropic(api_key=api_key)
        
        # Call Claude API
        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")
        
        # Extract response
        initial_response = response.content[0].text
        
        # Cache the result
        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)
        
        # Prepare conversation history for Claude
        messages = []
        for msg in conversation_history:
            messages.append({
                "role": "user" if msg["sender"] == "user" else "assistant",
                "content": msg["message"]
            })
        
        # Add the new message
        messages.append({"role": "user", "content": new_message})
        
        # System prompt based on language
        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."""
        
        # Initialize Claude client
        client = anthropic.Anthropic(api_key=api_key)
        
        # Call Claude API
        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:
        # Initialize session state for conversation if not exists
        if 'semantic_chat' not in st.session_state:
            st.session_state.semantic_chat = {
                'history': [],
                'initialized': False
            }
        
        # Container for chat display
        chat_container = st.container()
        
        # Initialize conversation if not done yet
        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
                
                # Store initial conversation
                if 'username' in st.session_state:
                    store_conversation(
                        st.session_state.username,
                        text,
                        metrics,
                        graph_data,
                        st.session_state.semantic_chat['history']
                    )
        
        # Display 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"])
        
        # Input for new message
        user_input = st.chat_input(
            t.get('chat_input_placeholder', 'Ask about your semantic analysis...')
        )
        
        if user_input:
            # Add user message to history
            st.session_state.semantic_chat['history'].append({
                "sender": "user",
                "message": user_input
            })
            
            # Display user message immediately
            with chat_container:
                st.chat_message("user").write(user_input)
                with st.spinner(t.get('assistant_thinking', 'Assistant is thinking...')):
                    # Get assistant response
                    assistant_response = continue_conversation(
                        st.session_state.semantic_chat['history'],
                        user_input,
                        lang_code
                    )
                    
                    # Add assistant response to history
                    st.session_state.semantic_chat['history'].append({
                        "sender": "assistant",
                        "message": assistant_response
                    })
                    
                    # Display assistant response
                    st.chat_message("assistant").write(assistant_response)
            
            # Store updated conversation
            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.'))