Como defensor del desarrollador, es difícil mantenerse al día con los mensajes del foro de usuarios y comprender el panorama general de lo que los usuarios están diciendo. Hay mucho contenido valioso, pero ¿cómo puede detectar rápidamente las conversaciones clave? ¡En este tutorial, te mostraré un hack de IA para realizar la agrupación semántica simplemente al solicitar LLM!

TL; DR 🔄 Esta publicación de blog trata sobre cómo pasar de (Data Science + Code) → (AI Solts + LLMS) para los mismos resultados, ¡solo más rápido y con menos esfuerzo! 🤖⚡. Está organizado de la siguiente manera:

  • Fuentes de inspiración y datos
  • Explorando los datos con paneles
  • LLM solicitando producir grupos KNN
  • Experimentar con incrustaciones personalizadas
  • Agrupación en múltiples servidores de discordia

Fuentes de inspiración y datos

Primero, daré accesorios para el documento de diciembre de 2024 Clio (Claude ideas y observaciones)una plataforma de preservación de la privacidad que utiliza asistentes de IA para analizar y los patrones de uso agregados de superficie en millones de conversaciones. Leer este artículo me inspiró a probar esto.

Datos. Usé solo públicamente disponible Discordia Mensajes, específicamente «hilos de foro», donde los usuarios solicitan ayuda tecnológica. Además, agregué y anononizé contenido para este blog. Por hilo, formateé los datos en formato de giro de conversación, con roles de usuario identificados como «usuario», haciendo la pregunta o «asistente», cualquier persona que responda la pregunta inicial del usuario. También agregué un puntaje de sentimiento binario simple y codificado (0 para «no feliz» y 1 para «feliz») basado en si el usuario dijo gracias en cualquier momento en su hilo. Para los proveedores de vectordb usé Zilliz/Milvus, Chroma y Qdrant.

El primer paso fue convertir los datos en un marco de datos de Pandas. A continuación se muestra un extracto. Puede ver para Thread_id = 2, un usuario solo hizo 1 pregunta. Pero para Thread_id = 3, un usuario hizo 4 preguntas diferentes en el mismo hilo (otras 2 preguntas en las marcas de tiempo más abajo, no se muestran a continuación).

El primer paso fue convertir los datos anonimizados en un marco de datos de Pandas con columnas: puntaje, usuario, rol, mensaje, marca de tiempo, hilo, user_turns.

Agregué una función ingenua de puntuación del sentimiento 0 | 1.

def calc_score(df):
   # Define the target words
   target_words = ["thanks", "thank you", "thx", "🙂", "😉", "👍"]


   # Helper function to check if any target word is in the concatenated message content
   def contains_target_words(messages):
       concatenated_content = " ".join(messages).lower()
       return any(word in concatenated_content for word in target_words)


   # Group by 'thread_id' and calculate score for each group
   thread_scores = (
       df[df['role_name'] == 'user']
       .groupby('thread_id')['message_content']
       .apply(lambda messages: int(contains_target_words(messages)))
   )
   # Map the calculated scores back to the original DataFrame
   df['score'] = df['thread_id'].map(thread_scores)
   return df


...


if __name__ == "__main__":
  
   # Load parameters from YAML file
   config_path = "config.yaml"
   params = load_params(config_path)
   input_data_folder = params['input_data_folder']
   processed_data_dir = params['processed_data_dir']
   threads_data_file = os.path.join(processed_data_dir, "thread_summary.csv")
  
   # Read data from Discord Forum JSON files into a pandas df.
   clean_data_df = process_json_files(
       input_data_folder,
       processed_data_dir)
  
   # Calculate score based on specific words in message content
   clean_data_df = calc_score(clean_data_df)


   # Generate reports and plots
   plot_all_metrics(processed_data_dir)


   # Concat thread messages & save as CSV for prompting.
   thread_summary_df, avg_message_len, avg_message_len_user = \
   concat_thread_messages_df(clean_data_df, threads_data_file)
   assert thread_summary_df.shape[0] == clean_data_df.thread_id.nunique()

Explorando los datos con paneles

De los datos procesados ​​anteriores, construí paneles tradicionales:

  • Volúmenes de mensajes: Picos únicos en proveedores como Qdrant y Milvus (posiblemente debido a eventos de marketing).
  • Participación del usuario: Los principales gráficos de barras de los usuarios y diagramas de dispersión del tiempo de respuesta frente al número de giros de los usuarios muestran que, en general, más giros del usuario significan una mayor satisfacción. Pero, la satisfacción no se ve correlacionada con el tiempo de respuesta. Los puntos oscuros de dispersión parecen aleatorios con respecto al eje y (tiempo de respuesta). ¿Quizás los usuarios no están en producción, sus preguntas no son muy urgentes? Existen atípicos, como Qdrant y Chroma, que pueden tener anomalías impulsadas por BOT.
  • Tendencias de satisfacción: Alrededor del 70% de los usuarios parecen felices de tener alguna interacción. Nota de datos: asegúrese de verificar los emojis por proveedor, a veces los usuarios responden usando emojis en lugar de palabras. Ejemplo Qdrant y Chroma.
Imagen del autor de los datos anónimos agregados. Top Lefts: los gráficos muestran el volumen de mensajes más alto de Chroma, seguido de Qdrant, y luego Milvus. Derechos principales: los mejores usuarios de mensajería, Qdrant + Chroma Possible bots (ver la barra superior en la tabla de usuarios de mensajería superior). Derechos intermedios: los gráficos de dispersión del tiempo de respuesta frente al número de giros de los usuarios no muestran correlación con respecto a los puntos oscuros y el eje y (tiempo de respuesta). Por lo general, una mayor satisfacción WRT X-Eje (giros de usuario), excepto el croma. Lefts inferiores: gráficos de barras de niveles de satisfacción, asegúrese de detectar posibles comentarios basados ​​en emoji, ver Qdrant y Chroma.

LLM solicitando producir grupos KNN

Para solicitar, el siguiente paso fue agregar datos por Thread_id. Para LLMS, necesita los textos concatenados juntos. Separo mensajes de usuario de mensajes completos de subprocesos para ver si uno u otro produciría mejores grupos. Terminé usando solo mensajes de usuario.

Ejemplo de datos anonimizados para solicitar. Todos los textos de mensajes concatenados juntos.

Con un archivo CSV para solicitar, ¡está listo para comenzar a usar un LLM para hacer ciencia de datos!

!pip install -q google.generativeai
import os
import google.generativeai as genai


# Get API key from local system
api_key=os.environ.get("GOOGLE_API_KEY")


# Configure API key
genai.configure(api_key=api_key)


# List all the model names
for m in genai.list_models():
   if 'generateContent' in m.supported_generation_methods:
       print(m.name)


# Try different models and prompts
GEMINI_MODEL_FOR_SUMMARIES = "gemini-2.0-pro-exp-02-05"
model = genai.GenerativeModel(GEMINI_MODEL_FOR_SUMMARIES)
# Combine the prompt and CSV data.
full_input = prompt + "\n\nCSV Data:\n" + csv_data
# Inference call to Gemini LLM
response = model.generate_content(full_input)


# Save response.text as .json file...


# Check token counts and compare to model limit: 2 million tokens
print(response.usage_metadata)
Imagen del autor. Arriba: Ejemplo de nombres de modelos LLM. Abajo: Llama de inferencia de ejemplo a Gemini LLM Token Counts: apt_token_count = tokens de entrada; candidates_token_count = tokens de salida; Total_Token_Count = Sum tokens Total utilizados.

Lamentablemente, la API de Géminis siguió cortando el response.text. Tuve mejor suerte usando AI Studio directamente.

Imagen del autor: Captura de pantalla de salidas de ejemplo de Google AI Studio.

Mis 5 indicaciones para Géminis Flash & Pro (La temperatura establecida en 0) están debajo.

Aviso#1: Obtenga resúmenes de hilo:

Dado este archivo .csv, por fila, agregue 3 columnas:
– Thread_summary = 205 caracteres o menos resumen de la columna de la fila ‘Message_Content’
– user_thread_summary = 126 caracteres o menos resumen de la columna de la fila ‘Message_content_user’
-Thread_topic = 3–5 Word Categoría de Super Alto nivel
Asegúrese de que los resúmenes capturen el contenido principal sin perder demasiados detalles. Haga resúmenes de hilo de usuario directamente al punto, capture el contenido principal sin perder demasiados detalles, omita el texto de introducción. Si un resumen más corto es lo suficientemente bueno, prefiera el resumen más corto. Asegúrese de que el tema sea lo suficientemente general como para que haya menos de 20 temas de alto nivel para todos los datos. Prefiere menos temas. Salidas de salida JSON: Thread_id, Thread_summary, user_thread_summary, thread_topic.

Aviso#2: Obtener estadísticas de clúster:

Dado este archivo de mensajes CSV, use column = ‘user_thread_summary’ para realizar la agrupación semántica de todas las filas. Use técnica = Silhouette, con método de enlace = Ward y Distance_Metric = Cosine Simility. Solo dame las estadísticas para el análisis de silueta del método por ahora.

Aviso#3: Realizar la agrupación inicial:

Dado este archivo de mensajes CSV, use columna = ‘user_thread_summary’ para realizar la agrupación semántica de todas las filas en clústeres n = 6 utilizando el método Silhouette. Use columna = «Thread_topic» para resumir cada tema de clúster en 1–3 palabras. Salida JSON con columnas: thread_id, nivel0_cluster_id, nivel0_cluster_topic.

Puntaje de silueta mide cuán similar es un objeto a su propio grupo (cohesión) versus otros grupos (separación). Los puntajes varían de -1 a 1. Una puntuación de silueta promedio más alta generalmente indica grupos mejor definidos con buena separación. Para más detalles, consulte el documentación de puntaje de silueta de scikit-learn.

Aplicándolo a los datos de Chroma. A continuación, muestro resultados de la pronta#2, como una trama de puntajes de silueta. Elegí N = 6 clústeres como un compromiso entre la puntuación alta y menos grupos. La mayoría de las LLM en estos días para el análisis de datos toman la entrada como CSV y salida JSON.

Imagen del autor de los datos anónimos agregados. Izquierda: elegí n = 6 grupos como compromiso entre una puntuación más alta y menos grupos. Derecha: los clústeres reales usando n = 6. El sentimiento más alto (puntajes más altos) son para temas sobre la consulta. El sentimiento más bajo (puntajes más bajos) son para temas sobre «problemas del cliente».

De la trama anterior, ¡puedes ver que finalmente nos estamos metiendo en la carne de lo que dicen los usuarios!

Aviso#4: Obtener estadísticas jerárquicas del clúster:

Dado este archivo de mensajes CSV, use la columna = ‘Thread_summary_user’ para realizar la agrupación semántica de todas las filas en la agrupación jerárquica (aglomerativa) con 2 niveles. Use el puntaje de silueta. ¿Cuál es el número óptimo de los siguientes clústeres de nivel 0 y nivel1? ¿Cuántos hilos por clúster de nivel1? Solo dame las estadísticas por ahora, haremos la agrupación real más tarde.

Aviso#5: Realizar agrupación jerárquica:

Acepte esta agrupación con 2 niveles. Agregue temas de clúster que resuman la columna de texto «Thread_topic». Los temas de clúster deben ser lo más cortos posible sin perder demasiados detalles en el significado del clúster.
– Temas de clúster de nivel 0 ~ 1–3 palabras.
– Temas de clúster nivel1 ~ 2–5 palabras.
Salida JSON con columnas: thread_id, nivel0_cluster_id, nivel0_cluster_topic, nivel1_cluster_id, nivel1_cluster_topic.

También solicité que genere un código a paso a luz para visualizar los clústeres (ya que no soy un experto en JS 😄). Los resultados para los mismos datos de croma se muestran a continuación.

Imagen del autor de los datos anónimos agregados. Imagen izquierda: cada punto de diagrama de dispersión es un hilo con Hover-Info. Imagen correcta: agrupación jerárquica con capacidades de desglose de datos sin procesar. Los errores de API y paquetes se parecen al tema más urgente de Chroma para solucionar, porque el sentimiento es bajo y el volumen de mensajes es alto.

Encontré esto muy perspicaz. Para Chroma, la agrupación reveló que, si bien los usuarios estaban contentos con temas como la consulta, la distancia y el rendimiento, no estaban contentos con las áreas como datos, cliente e implementación.

Experimentar con incrustaciones personalizadas

Repetí las indicaciones de agrupación anteriores, utilizando solo la incrustación numérica («user_embedding») en el CSV en lugar de los resúmenes de texto sin procesar («user_text»). He explicado incrustaciones en detalle anteriormente blogs Antes, y los riesgos de los modelos de sobre fáctica en las tablas de clasificación. OpenAi tiene confiable incrustaciones que son extremadamente asequibles por API Call. A continuación se muestra un fragmento de código de ejemplo cómo crear incrustaciones.

from openai import OpenAI


EMBEDDING_MODEL = "text-embedding-3-small"
EMBEDDING_DIM = 512 # 512 or 1536 possible


# Initialize client with API key
openai_client = OpenAI(
   api_key=os.environ.get("OPENAI_API_KEY"),
)


# Function to create embeddings
def get_embedding(text, embedding_model=EMBEDDING_MODEL,
                 embedding_dim=EMBEDDING_DIM):
   response = openai_client.embeddings.create(
       input=text,
       model=embedding_model,
       dimensions=embedding_dim
   )
   return response.data[0].embedding


# Function to call per pandas df row in .apply()
def generate_row_embeddings(row):
   return {
       'user_embedding': get_embedding(row['user_thread_summary']),
   }


# Generate embeddings using pandas apply
embeddings_data = df.apply(generate_row_embeddings, axis=1)
# Add embeddings back into df as separate columns
df['user_embedding'] = embeddings_data.apply(lambda x: x['user_embedding'])
display(df.head())


# Save as CSV ...
Datos de ejemplo para solicitar. La columna «User_embedding» es una longitud de matriz = 512 de números de punto flotante.

Curiosamente, tanto Perplexity Pro como Gemini 2.0 Pro a veces temas de clúster alucinados (por ejemplo, clasificar erróneamente una pregunta sobre consultas lentas como «materia personal»).

Conclusión: al realizar NLP con indicaciones, deje que el LLM genere sus propias incrustaciones: los incrustaciones generadas externamente parecen confundir el modelo.

Imagen del autor de los datos anónimos agregados. Temas de clúster alucinados Gemini 1.5 Pro de Google Pro y Google cuando se les dio una columna de incrustación generada externamente. Conclusión: al realizar PNL con indicaciones, solo mantenga el texto en bruto y deje que el LLM cree sus propias embedidas detrás de escena. ¡La alimentación en incrustaciones generadas externamente parece confundir el LLM!

Agrupación en múltiples servidores de discordia

Finalmente, amplié el análisis para incluir mensajes de discordia de tres proveedores de VectordB diferentes. La visualización resultante destacó problemas comunes, como Milvus y Chroma que enfrentan problemas de autenticación.

Imagen del autor de los datos agregados y anonimizados: un panel de VectordB VectordB Muestra los principales problemas en muchas empresas. Una cosa que se destaca es que tanto Milvus como el croma están teniendo problemas con la autenticación.

Resumen

Aquí hay un resumen de los pasos que seguí para realizar la agrupación semántica usando las indicaciones de LLM:

  1. Extraer hilos de discordia.
  2. Los datos de formateo en conversación giran con roles («usuario», «asistente»).
  3. Sentimiento de puntaje y ahorre como CSV.
  4. Solicite Google Gemini 2.0 Flash para resúmenes de hilos.
  5. PROMEDIA PERPEXITY Pro o Gemini 2.0 Pro para la agrupación basada en resúmenes de hilos utilizando el mismo CSV.
  6. PROMEDIA PERPLEXITY Pro o Gemini 2.0 Pro para escribir Racionalizar Código para visualizar clústeres (porque no soy un experto en JS 😆).

Siguiendo estos pasos, puede transformar rápidamente los datos del foro sin procesar en ideas procesables: ¡lo que solía tomar días de codificación ahora se puede hacer en solo una tarde!

Referencias

  1. CLIO: Perspectivas de preservación de la privacidad sobre el uso de IA del mundo real, https://arxiv.org/abs/2412.13678
  2. Blog antrópico sobre clio, https://www.anthropic.com/research/clio
  3. Servidor Milvus Discordúltimo acceso el 7 de febrero de 2025
    Servidor de discordia de Chromaúltimo acceso el 7 de febrero de 2025
    Servidor Qdrant Discordúltimo acceso el 7 de febrero de 2025
  4. Modelos Géminis, https://ai.google.dev/gemini-api/docs/models/gemini
  5. Blog sobre modelos Gemini 2.0, https://blog.google/technology/google-deepmind/gemini-model-updates-february-2025/
  6. SCIKIT-Learn Silhouette Puntuación
  7. Incrustaciones de Operai Matryoshka
  8. Racionalizar

Por automata