AIdeaText commited on
Commit
5855e51
1 Parent(s): 6ca43ec

Update modules/text_analysis/semantic_analysis.py

Browse files
modules/text_analysis/semantic_analysis.py CHANGED
@@ -220,70 +220,132 @@ def fig_to_html(fig):
220
 
221
  def identify_key_concepts(doc, min_freq=2, min_length=3):
222
  """
223
- Identifica conceptos clave en el texto, excluyendo stopwords
224
- y aplicando criterios de frecuencia y longitud.
 
 
 
 
 
225
  """
226
- stopwords = get_stopwords(doc.lang_)
227
- word_freq = Counter()
228
-
229
- for token in doc:
230
- if (token.text.lower() not in stopwords and # No es stopword
231
- token.is_alpha and # Es alfabético
232
- len(token.text) >= min_length and # Longitud mínima
233
- not token.is_punct and # No es puntuación
234
- not token.like_num): # No es número
235
-
236
- # Usar el lema en lugar del token para unificar variantes
237
- word_freq[token.lemma_] += 1
238
-
239
- # Filtrar por frecuencia mínima y ordenar por frecuencia
240
- key_concepts = [(word, freq) for word, freq in word_freq.items()
 
 
 
241
  if freq >= min_freq]
242
- key_concepts.sort(key=lambda x: x[1], reverse=True)
243
-
244
- return key_concepts[:10] # Retornar los 10 conceptos más frecuentes
 
 
 
 
 
 
245
 
246
 
247
  def create_concept_graph(doc, key_concepts):
248
  """
249
  Crea un grafo de relaciones entre conceptos.
 
 
 
 
 
250
  """
251
- G = nx.Graph()
252
- concept_words = {concept[0] for concept in key_concepts}
253
-
254
- for sent in doc.sents:
255
- sentence_concepts = []
256
- for token in sent:
257
- if token.lemma_ in concept_words:
258
- sentence_concepts.append(token.lemma_)
259
 
260
- # Crear conexiones entre conceptos en la misma oración
261
- for i, concept1 in enumerate(sentence_concepts):
262
- for concept2 in sentence_concepts[i+1:]:
263
- if G.has_edge(concept1, concept2):
264
- G[concept1][concept2]['weight'] += 1
265
- else:
266
- G.add_edge(concept1, concept2, weight=1)
267
-
268
- return G
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
269
 
270
  def visualize_concept_graph(G, lang_code):
271
- fig, ax = plt.subplots(figsize=(12, 8))
272
- pos = nx.spring_layout(G, k=0.5, iterations=50)
273
- node_sizes = [G.nodes[node]['weight'] * 100 for node in G.nodes()]
274
- nx.draw_networkx_nodes(G, pos, node_size=node_sizes, node_color='lightblue', alpha=0.8, ax=ax)
275
- nx.draw_networkx_labels(G, pos, font_size=10, font_weight="bold", ax=ax)
276
- edge_weights = [G[u][v]['weight'] for u, v in G.edges()]
277
- nx.draw_networkx_edges(G, pos, width=edge_weights, alpha=0.5, ax=ax)
278
- title = {
279
- 'es': "Relaciones entre Conceptos Clave",
280
- 'en': "Key Concept Relations",
281
- 'fr': "Relations entre Concepts Clés"
282
- }
283
- ax.set_title(title[lang_code], fontsize=16)
284
- ax.axis('off')
285
- plt.tight_layout()
286
- return fig
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
287
 
288
  def create_entity_graph(entities):
289
  G = nx.Graph()
 
220
 
221
  def identify_key_concepts(doc, min_freq=2, min_length=3):
222
  """
223
+ Identifica conceptos clave en el texto.
224
+ Args:
225
+ doc: Documento procesado por spaCy
226
+ min_freq: Frecuencia mínima para considerar un concepto
227
+ min_length: Longitud mínima de palabra para considerar
228
+ Returns:
229
+ list: Lista de tuplas (concepto, frecuencia)
230
  """
231
+ try:
232
+ # Obtener stopwords para el idioma
233
+ stopwords = get_stopwords(doc.lang_)
234
+
235
+ # Contar frecuencias de palabras
236
+ word_freq = Counter()
237
+
238
+ for token in doc:
239
+ if (token.lemma_.lower() not in stopwords and
240
+ len(token.lemma_) >= min_length and
241
+ token.is_alpha and
242
+ not token.is_punct and
243
+ not token.like_num):
244
+
245
+ word_freq[token.lemma_.lower()] += 1
246
+
247
+ # Filtrar por frecuencia mínima
248
+ concepts = [(word, freq) for word, freq in word_freq.items()
249
  if freq >= min_freq]
250
+
251
+ # Ordenar por frecuencia
252
+ concepts.sort(key=lambda x: x[1], reverse=True)
253
+
254
+ return concepts[:10] # Retornar los 10 conceptos más frecuentes
255
+
256
+ except Exception as e:
257
+ logger.error(f"Error en identify_key_concepts: {str(e)}")
258
+ return [] # Retornar lista vacía en caso de error
259
 
260
 
261
  def create_concept_graph(doc, key_concepts):
262
  """
263
  Crea un grafo de relaciones entre conceptos.
264
+ Args:
265
+ doc: Documento procesado por spaCy
266
+ key_concepts: Lista de tuplas (concepto, frecuencia)
267
+ Returns:
268
+ nx.Graph: Grafo de conceptos
269
  """
270
+ try:
271
+ G = nx.Graph()
 
 
 
 
 
 
272
 
273
+ # Crear un conjunto de conceptos clave para búsqueda rápida
274
+ concept_words = {concept[0].lower() for concept in key_concepts}
275
+
276
+ # Añadir nodos al grafo
277
+ for concept, freq in key_concepts:
278
+ G.add_node(concept.lower(), weight=freq)
279
+
280
+ # Analizar cada oración
281
+ for sent in doc.sents:
282
+ # Obtener conceptos en la oración actual
283
+ current_concepts = []
284
+ for token in sent:
285
+ if token.lemma_.lower() in concept_words:
286
+ current_concepts.append(token.lemma_.lower())
287
+
288
+ # Crear conexiones entre conceptos en la misma oración
289
+ for i, concept1 in enumerate(current_concepts):
290
+ for concept2 in current_concepts[i+1:]:
291
+ if concept1 != concept2:
292
+ # Si ya existe la arista, incrementar el peso
293
+ if G.has_edge(concept1, concept2):
294
+ G[concept1][concept2]['weight'] += 1
295
+ # Si no existe, crear nueva arista con peso 1
296
+ else:
297
+ G.add_edge(concept1, concept2, weight=1)
298
+
299
+ return G
300
+
301
+ except Exception as e:
302
+ logger.error(f"Error en create_concept_graph: {str(e)}")
303
+ # Retornar un grafo vacío en caso de error
304
+ return nx.Graph()
305
 
306
  def visualize_concept_graph(G, lang_code):
307
+ """
308
+ Visualiza el grafo de conceptos.
309
+ Args:
310
+ G: Grafo de networkx
311
+ lang_code: Código del idioma
312
+ Returns:
313
+ matplotlib.figure.Figure: Figura con el grafo visualizado
314
+ """
315
+ try:
316
+ plt.figure(figsize=(12, 8))
317
+
318
+ # Calcular el layout del grafo
319
+ pos = nx.spring_layout(G)
320
+
321
+ # Obtener pesos de nodos y aristas
322
+ node_weights = [G.nodes[node].get('weight', 1) * 500 for node in G.nodes()]
323
+ edge_weights = [G[u][v].get('weight', 1) for u, v in G.edges()]
324
+
325
+ # Dibujar el grafo
326
+ nx.draw_networkx_nodes(G, pos,
327
+ node_size=node_weights,
328
+ node_color='lightblue',
329
+ alpha=0.6)
330
+
331
+ nx.draw_networkx_edges(G, pos,
332
+ width=edge_weights,
333
+ alpha=0.5,
334
+ edge_color='gray')
335
+
336
+ nx.draw_networkx_labels(G, pos,
337
+ font_size=10,
338
+ font_weight='bold')
339
+
340
+ plt.title("Red de conceptos relacionados")
341
+ plt.axis('off')
342
+
343
+ return plt.gcf()
344
+
345
+ except Exception as e:
346
+ logger.error(f"Error en visualize_concept_graph: {str(e)}")
347
+ # Retornar una figura vacía en caso de error
348
+ return plt.figure()
349
 
350
  def create_entity_graph(entities):
351
  G = nx.Graph()