AIdeaText commited on
Commit
e54f9b8
·
verified ·
1 Parent(s): 1d15d08

Create semantic_agent_interaction.py

Browse files
modules/semantic/semantic_agent_interaction.py ADDED
@@ -0,0 +1,404 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # modules/semantic/semantic_agent_interaction.py
2
+ import os
3
+ import anthropic
4
+ import streamlit as st
5
+ import logging
6
+ import time
7
+ import json
8
+ from datetime import datetime, timezone
9
+ from io import BytesIO
10
+ import base64
11
+
12
+ # Local imports
13
+ from ..utils.widget_utils import generate_unique_key
14
+ from ..database.semantic_mongo_db import store_semantic_interaction
15
+
16
+ logger = logging.getLogger(__name__)
17
+
18
+ # Cache for conversation history to avoid redundant API calls
19
+ conversation_cache = {}
20
+
21
+ def get_conversation_cache_key(text, metrics, graph_data, lang_code):
22
+ """
23
+ Generate a cache key for conversations based on analysis data.
24
+ """
25
+ text_hash = hash(text[:1000]) # Only use first 1000 chars for hashing
26
+ metrics_hash = hash(json.dumps(metrics, sort_keys=True))
27
+ graph_hash = hash(graph_data[:100]) if graph_data else 0
28
+ return f"{text_hash}_{metrics_hash}_{graph_hash}_{lang_code}"
29
+
30
+ def format_semantic_context(text, metrics, graph_data, lang_code):
31
+ """
32
+ Format the semantic analysis data for Claude's context.
33
+ """
34
+ formatted_data = {
35
+ 'text_sample': text[:2000], # Limit text sample
36
+ 'key_concepts': metrics.get('key_concepts', []),
37
+ 'concept_centrality': metrics.get('concept_centrality', {}),
38
+ 'graph_description': "Network graph available" if graph_data else "No graph available",
39
+ 'language': lang_code
40
+ }
41
+
42
+ return json.dumps(formatted_data, indent=2, ensure_ascii=False)
43
+
44
+ def initiate_semantic_conversation(text, metrics, graph_data, lang_code):
45
+ """
46
+ Start a conversation with Claude about semantic analysis results.
47
+ """
48
+ try:
49
+ api_key = os.environ.get("ANTHROPIC_API_KEY")
50
+ if not api_key:
51
+ logger.error("Claude API key not found in environment variables")
52
+ return get_fallback_response(lang_code)
53
+
54
+ # Check cache first
55
+ cache_key = get_conversation_cache_key(text, metrics, graph_data, lang_code)
56
+ if cache_key in conversation_cache:
57
+ logger.info("Using cached conversation starter")
58
+ return conversation_cache[cache_key]
59
+
60
+ # Format context for Claude
61
+ context = format_semantic_context(text, metrics, graph_data, lang_code)
62
+
63
+ # Determine language for prompt
64
+ if lang_code == 'es':
65
+ system_prompt = """Eres un asistente especializado en análisis semántico de textos.
66
+ El usuario ha analizado un texto y quiere discutir los resultados contigo.
67
+ Estos son los datos del análisis:
68
+ - Fragmento del texto analizado
69
+ - Lista de conceptos clave identificados
70
+ - Medidas de centralidad de los conceptos
71
+ - Un grafo de relaciones conceptuales (si está disponible)
72
+
73
+ Tu rol es:
74
+ 1. Demostrar comprensión del análisis mostrado
75
+ 2. Hacer preguntas relevantes sobre los resultados
76
+ 3. Ayudar al usuario a interpretar los hallazgos
77
+ 4. Sugerir posibles direcciones para profundizar el análisis
78
+
79
+ Usa un tono profesional pero accesible. Sé conciso pero claro.
80
+ """
81
+ user_prompt = f"""Aquí están los resultados del análisis semántico:
82
+
83
+ {context}
84
+
85
+ Por favor:
86
+ 1. Haz un breve resumen de lo que notas en los resultados
87
+ 2. Formula 2-3 preguntas interesantes que podríamos explorar sobre estos datos
88
+ 3. Sugiere un aspecto del análisis que podría profundizarse
89
+
90
+ Mantén tu respuesta bajo 250 palabras."""
91
+
92
+ elif lang_code == 'fr':
93
+ system_prompt = """Vous êtes un assistant spécialisé dans l'analyse sémantique de textes.
94
+ L'utilisateur a analysé un texte et souhaite discuter des résultats avec vous.
95
+ Voici les données d'analyse:
96
+ - Extrait du texte analysé
97
+ - Liste des concepts clés identifiés
98
+ - Mesures de centralité des concepts
99
+ - Un graphique des relations conceptuelles (si disponible)
100
+
101
+ Votre rôle est:
102
+ 1. Démontrer une compréhension de l'analyse présentée
103
+ 2. Poser des questions pertinentes sur les résultats
104
+ 3. Aider l'utilisateur à interpréter les résultats
105
+ 4. Proposer des pistes pour approfondir l'analyse
106
+
107
+ Utilisez un ton professionnel mais accessible. Soyez concis mais clair.
108
+ """
109
+ user_prompt = f"""Voici les résultats de l'analyse sémantique:
110
+
111
+ {context}
112
+
113
+ Veuillez:
114
+ 1. Faire un bref résumé de ce que vous remarquez dans les résultats
115
+ 2. Formuler 2-3 questions intéressantes que nous pourrions explorer
116
+ 3. Suggérer un aspect de l'analyse qui pourrait être approfondi
117
+
118
+ Limitez votre réponse à 250 mots."""
119
+
120
+ elif lang_code == 'pt':
121
+ system_prompt = """Você é um assistente especializado em análise semântica de textos.
122
+ O usuário analisou um texto e quer discutir os resultados com você.
123
+ Aqui estão os dados da análise:
124
+ - Trecho do texto analisado
125
+ - Lista de conceitos-chave identificados
126
+ - Medidas de centralidade dos conceitos
127
+ - Um grafo de relações conceituais (se disponível)
128
+
129
+ Seu papel é:
130
+ 1. Demonstrar compreensão da análise apresentada
131
+ 2. Fazer perguntas relevantes sobre os resultados
132
+ 3. Ajudar o usuário a interpretar os achados
133
+ 4. Sugerir possíveis direções para aprofundar a análise
134
+
135
+ Use um tom profissional mas acessível. Seja conciso mas claro.
136
+ """
137
+ user_prompt = f"""Aqui estão os resultados da análise semântica:
138
+
139
+ {context}
140
+
141
+ Por favor:
142
+ 1. Faça um breve resumo do que você nota nos resultados
143
+ 2. Formule 2-3 perguntas interessantes que poderíamos explorar
144
+ 3. Sugira um aspecto da análise que poderia ser aprofundado
145
+
146
+ Mantenha sua resposta em até 250 palavras."""
147
+
148
+ else: # Default to English
149
+ system_prompt = """You are an assistant specialized in semantic text analysis.
150
+ The user has analyzed a text and wants to discuss the results with you.
151
+ Here is the analysis data:
152
+ - Sample of the analyzed text
153
+ - List of identified key concepts
154
+ - Concept centrality measures
155
+ - A concept relationship graph (if available)
156
+
157
+ Your role is to:
158
+ 1. Demonstrate understanding of the shown analysis
159
+ 2. Ask relevant questions about the results
160
+ 3. Help the user interpret the findings
161
+ 4. Suggest possible directions to deepen the analysis
162
+
163
+ Use a professional but accessible tone. Be concise but clear.
164
+ """
165
+ user_prompt = f"""Here are the semantic analysis results:
166
+
167
+ {context}
168
+
169
+ Please:
170
+ 1. Give a brief summary of what you notice in the results
171
+ 2. Formulate 2-3 interesting questions we could explore
172
+ 3. Suggest one aspect of the analysis that could be deepened
173
+
174
+ Keep your response under 250 words."""
175
+
176
+ # Initialize Claude client
177
+ client = anthropic.Anthropic(api_key=api_key)
178
+
179
+ # Call Claude API
180
+ start_time = time.time()
181
+ response = client.messages.create(
182
+ model="claude-3-sonnet-20240229",
183
+ max_tokens=1024,
184
+ temperature=0.7,
185
+ system=system_prompt,
186
+ messages=[
187
+ {"role": "user", "content": user_prompt}
188
+ ]
189
+ )
190
+ logger.info(f"Claude API call completed in {time.time() - start_time:.2f} seconds")
191
+
192
+ # Extract response
193
+ initial_response = response.content[0].text
194
+
195
+ # Cache the result
196
+ conversation_cache[cache_key] = initial_response
197
+
198
+ return initial_response
199
+
200
+ except Exception as e:
201
+ logger.error(f"Error initiating semantic conversation: {str(e)}")
202
+ return get_fallback_response(lang_code)
203
+
204
+ def continue_conversation(conversation_history, new_message, lang_code):
205
+ """
206
+ Continue an existing conversation about semantic analysis.
207
+ """
208
+ try:
209
+ api_key = os.environ.get("ANTHROPIC_API_KEY")
210
+ if not api_key:
211
+ logger.error("Claude API key not found in environment variables")
212
+ return get_fallback_response(lang_code)
213
+
214
+ # Prepare conversation history for Claude
215
+ messages = []
216
+ for msg in conversation_history:
217
+ messages.append({
218
+ "role": "user" if msg["sender"] == "user" else "assistant",
219
+ "content": msg["message"]
220
+ })
221
+
222
+ # Add the new message
223
+ messages.append({"role": "user", "content": new_message})
224
+
225
+ # System prompt based on language
226
+ if lang_code == 'es':
227
+ system_prompt = """Continúa la conversación sobre el análisis semántico.
228
+ Sé conciso pero útil. Responde en español."""
229
+ elif lang_code == 'fr':
230
+ system_prompt = """Continuez la conversation sur l'analyse sémantique.
231
+ Soyez concis mais utile. Répondez en français."""
232
+ elif lang_code == 'pt':
233
+ system_prompt = """Continue a conversa sobre a análise semântica.
234
+ Seja conciso mas útil. Responda em português."""
235
+ else:
236
+ system_prompt = """Continue the conversation about semantic analysis.
237
+ Be concise but helpful. Respond in English."""
238
+
239
+ # Initialize Claude client
240
+ client = anthropic.Anthropic(api_key=api_key)
241
+
242
+ # Call Claude API
243
+ response = client.messages.create(
244
+ model="claude-3-sonnet-20240229",
245
+ max_tokens=1024,
246
+ temperature=0.7,
247
+ system=system_prompt,
248
+ messages=messages
249
+ )
250
+
251
+ return response.content[0].text
252
+
253
+ except Exception as e:
254
+ logger.error(f"Error continuing semantic conversation: {str(e)}")
255
+ return get_fallback_response(lang_code)
256
+
257
+ def get_fallback_response(lang_code):
258
+ """
259
+ Return fallback response if Claude API fails.
260
+ """
261
+ if lang_code == 'es':
262
+ return """Parece que hay un problema técnico. Por favor intenta de nuevo más tarde.
263
+
264
+ Mientras tanto, aquí hay algunas preguntas que podrías considerar sobre tu análisis:
265
+ 1. ¿Qué conceptos tienen la mayor centralidad y por qué podría ser?
266
+ 2. ¿Hay conexiones inesperadas entre conceptos en tu grafo?
267
+ 3. ¿Cómo podrías profundizar en las relaciones entre los conceptos clave?"""
268
+
269
+ elif lang_code == 'fr':
270
+ return """Il semble y avoir un problème technique. Veuillez réessayer plus tard.
271
+
272
+ En attendant, voici quelques questions que vous pourriez considérer:
273
+ 1. Quels concepts ont la plus grande centralité et pourquoi?
274
+ 2. Y a-t-il des connexions inattendues entre les concepts?
275
+ 3. Comment pourriez-vous approfondir les relations entre les concepts clés?"""
276
+
277
+ elif lang_code == 'pt':
278
+ return """Parece haver um problema técnico. Por favor, tente novamente mais tarde.
279
+
280
+ Enquanto isso, aqui estão algumas perguntas que você poderia considerar:
281
+ 1. Quais conceitos têm maior centralidade e por que isso pode ocorrer?
282
+ 2. Há conexões inesperadas entre conceitos no seu grafo?
283
+ 3. Como você poderia aprofundar as relações entre os conceitos-chave?"""
284
+
285
+ else:
286
+ return """There seems to be a technical issue. Please try again later.
287
+
288
+ Meanwhile, here are some questions you might consider about your analysis:
289
+ 1. Which concepts have the highest centrality and why might that be?
290
+ 2. Are there unexpected connections between concepts in your graph?
291
+ 3. How could you explore the relationships between key concepts further?"""
292
+
293
+ def store_conversation(username, text, metrics, graph_data, conversation):
294
+ """
295
+ Store the conversation in the database.
296
+ """
297
+ try:
298
+ result = store_semantic_interaction(
299
+ username=username,
300
+ text=text,
301
+ metrics=metrics,
302
+ graph_data=graph_data,
303
+ conversation=conversation
304
+ )
305
+
306
+ logger.info(f"Conversation stored successfully: {result}")
307
+ return result
308
+ except Exception as e:
309
+ logger.error(f"Error storing conversation: {str(e)}")
310
+ return False
311
+
312
+ def display_semantic_chat(text, metrics, graph_data, lang_code, t):
313
+ """
314
+ Display the chat interface for semantic analysis discussion.
315
+ """
316
+ try:
317
+ # Initialize session state for conversation if not exists
318
+ if 'semantic_chat' not in st.session_state:
319
+ st.session_state.semantic_chat = {
320
+ 'history': [],
321
+ 'initialized': False
322
+ }
323
+
324
+ # Container for chat display
325
+ chat_container = st.container()
326
+
327
+ # Initialize conversation if not done yet
328
+ if not st.session_state.semantic_chat['initialized']:
329
+ with st.spinner(t.get('initializing_chat', 'Initializing conversation...')):
330
+ initial_response = initiate_semantic_conversation(
331
+ text, metrics, graph_data, lang_code
332
+ )
333
+
334
+ st.session_state.semantic_chat['history'].append({
335
+ "sender": "assistant",
336
+ "message": initial_response
337
+ })
338
+ st.session_state.semantic_chat['initialized'] = True
339
+
340
+ # Store initial conversation
341
+ if 'username' in st.session_state:
342
+ store_conversation(
343
+ st.session_state.username,
344
+ text,
345
+ metrics,
346
+ graph_data,
347
+ st.session_state.semantic_chat['history']
348
+ )
349
+
350
+ # Display chat history
351
+ with chat_container:
352
+ st.markdown("### 💬 " + t.get('semantic_discussion', 'Semantic Analysis Discussion'))
353
+
354
+ for msg in st.session_state.semantic_chat['history']:
355
+ if msg["sender"] == "user":
356
+ st.chat_message("user").write(msg["message"])
357
+ else:
358
+ st.chat_message("assistant").write(msg["message"])
359
+
360
+ # Input for new message
361
+ user_input = st.chat_input(
362
+ t.get('chat_input_placeholder', 'Ask about your semantic analysis...')
363
+ )
364
+
365
+ if user_input:
366
+ # Add user message to history
367
+ st.session_state.semantic_chat['history'].append({
368
+ "sender": "user",
369
+ "message": user_input
370
+ })
371
+
372
+ # Display user message immediately
373
+ with chat_container:
374
+ st.chat_message("user").write(user_input)
375
+ with st.spinner(t.get('assistant_thinking', 'Assistant is thinking...')):
376
+ # Get assistant response
377
+ assistant_response = continue_conversation(
378
+ st.session_state.semantic_chat['history'],
379
+ user_input,
380
+ lang_code
381
+ )
382
+
383
+ # Add assistant response to history
384
+ st.session_state.semantic_chat['history'].append({
385
+ "sender": "assistant",
386
+ "message": assistant_response
387
+ })
388
+
389
+ # Display assistant response
390
+ st.chat_message("assistant").write(assistant_response)
391
+
392
+ # Store updated conversation
393
+ if 'username' in st.session_state:
394
+ store_conversation(
395
+ st.session_state.username,
396
+ text,
397
+ metrics,
398
+ graph_data,
399
+ st.session_state.semantic_chat['history']
400
+ )
401
+
402
+ except Exception as e:
403
+ logger.error(f"Error displaying semantic chat: {str(e)}")
404
+ st.error(t.get('chat_error', 'Error in chat interface. Please try again.'))