CapÃtulo 3: Embeddings y Búsqueda Semántica
3.2 Cuándo Usar Embeddings
Los embeddings han revolucionado la forma en que procesamos y entendemos la información textual en las aplicaciones modernas de IA. Mientras que los métodos tradicionales de procesamiento de texto dependen de coincidencias exactas o búsquedas básicas por palabras clave, los embeddings proporcionan una forma sofisticada de capturar los significados matizados y las relaciones entre fragmentos de texto. Al convertir palabras y frases en vectores numéricos de alta dimensión, los embeddings permiten que las máquinas entiendan las relaciones semánticas y similitudes de manera que se asemejan más a la comprensión humana.
Exploremos los escenarios clave donde los embeddings resultan particularmente valiosos, mostrando cómo esta tecnología transforma varios aspectos del procesamiento y recuperación de información. Entender estos casos de uso es crucial para desarrolladores y organizaciones que buscan aprovechar todo el potencial de la tecnología de embeddings en sus aplicaciones.
3.2.1 Búsqueda semántica
Encontrar información relevante basada en el significado en lugar de solo palabras clave, permitiendo resultados de búsqueda más inteligentes. A diferencia de la búsqueda tradicional basada en palabras clave que coincide con palabras o frases exactas, la búsqueda semántica comprende la intención y el significado contextual de una consulta analizando las relaciones subyacentes entre palabras y conceptos. Este enfoque avanzado permite que el sistema comprenda variaciones en el lenguaje, contexto e incluso la intención del usuario.
Por ejemplo, una búsqueda de "procesamiento del lenguaje natural" también devolvería resultados relevantes sobre "PLN," "lingüística computacional" o "análisis de texto." Cuando un usuario busca "tratamiento de síntomas del resfriado común," el sistema entendería y devolvería resultados sobre "remedios para la gripe," "reducción de la fiebre" y "medicamentos para la tos" - incluso si estas frases exactas no se utilizan. Esta tecnología aprovecha los vectores de embedding para calcular puntajes de similitud entre consultas y documentos, transformando cada fragmento de texto en una representación numérica de alta dimensión que captura su significado semántico. Este enfoque matemático permite resultados de búsqueda más matizados y precisos que tienen en cuenta:
- Sinónimos y términos relacionados (como "coche" y "automóvil")
- Relaciones conceptuales (conectando "python" tanto con programación como con serpientes, dependiendo del contexto)
- Múltiples idiomas (encontrando contenido relevante incluso cuando está escrito en diferentes idiomas)
- Variaciones contextuales (entendiendo que "apple" puede referirse tanto a la fruta como a la empresa tecnológica)
- Coincidencia de intención (reconociendo que "cómo arreglar una llanta pinchada" e "instrucciones de reparación de neumáticos" buscan la misma información)
Ejemplo:
Aquí hay un ejemplo de código que demuestra la búsqueda semántica usando embeddings de OpenAI, basado en el contenido que proporcionaste.
Este script:
- Definirá un pequeño conjunto de documentos.
- Generará embeddings para estos documentos y una consulta de búsqueda.
- Calculará la similitud entre la consulta y cada documento.
- Clasificará los documentos por relevancia basándose en la similitud semántica.
import os
from openai import OpenAI, OpenAIError
from dotenv import load_dotenv
import numpy as np # For cosine similarity calculation
import datetime
# --- Configuration ---
load_dotenv()
# Get the current date and location context
current_timestamp = "2025-03-22 15:22:00 CDT"
current_location = "Grapevine, Texas, United States"
print(f"Running Semantic Search example at: {current_timestamp}")
print(f"Location Context: {current_location}")
# Initialize the OpenAI client
try:
api_key = os.getenv("OPENAI_API_KEY")
if not api_key:
raise ValueError("OPENAI_API_KEY not found in environment variables.")
client = OpenAI(api_key=api_key)
print("OpenAI client initialized.")
except ValueError as e:
print(f"Configuration Error: {e}")
exit()
except Exception as e:
print(f"Error initializing OpenAI client: {e}")
exit()
# Define the embedding model
EMBEDDING_MODEL = "text-embedding-3-small"
# --- Helper Function to Generate Embedding ---
# (Same as in previous embeddings example)
def get_embedding(client, text, model=EMBEDDING_MODEL):
"""Generates an embedding for the given text using the specified model."""
print(f"Generating embedding for: \"{text[:50]}...\"") # Print truncated text
try:
response = client.embeddings.create(
input=text,
model=model
)
embedding_vector = response.data[0].embedding
print("Embedding generation successful.")
return embedding_vector
except OpenAIError as e:
print(f"OpenAI API Error generating embedding for text '{text[:50]}...': {e}")
return None
except Exception as e:
print(f"An unexpected error occurred during embedding generation for text '{text[:50]}...': {e}")
return None
# --- Helper Function for Cosine Similarity ---
# (Same as in previous embeddings example)
def cosine_similarity(vec_a, vec_b):
"""Calculates the cosine similarity between two vectors."""
if vec_a is None or vec_b is None:
# print("Error: Cannot calculate similarity with None vectors.")
return 0.0 # Return 0 if any vector is missing
vec_a = np.array(vec_a)
vec_b = np.array(vec_b)
norm_a = np.linalg.norm(vec_a)
norm_b = np.linalg.norm(vec_b)
if norm_a == 0 or norm_b == 0:
# print("Warning: One or both vectors have zero magnitude.")
return 0.0
else:
similarity = np.dot(vec_a, vec_b) / (norm_a * norm_b)
return similarity
# --- Semantic Search Implementation ---
# 1. Define your document store (a list of text strings)
# In a real application, this could come from a database, files, etc.
document_store = [
"The Eiffel Tower is a wrought-iron lattice tower on the Champ de Mars in Paris, France.",
"Photosynthesis is a process used by plants and other organisms to convert light energy into chemical energy.",
"Artificial intelligence research focuses on creating systems capable of performing tasks that typically require human intelligence.",
"A recipe for classic French onion soup involves caramelizing onions and topping with bread and cheese.",
"Machine learning, a subset of AI, involves algorithms that allow systems to learn from data.",
"The Louvre Museum in Paris is the world's largest art museum and a historic monument.",
"Natural Language Processing (NLP) enables computers to understand and process human language.",
"Baking bread requires careful measurement of ingredients like flour, water, yeast, and salt."
]
print(f"\nDocument store contains {len(document_store)} documents.")
# 2. Generate embeddings for all documents in the store (pre-computation)
# In a real app, you'd store these embeddings alongside the documents.
print("\nGenerating embeddings for the document store...")
document_embeddings = []
for doc in document_store:
embedding = get_embedding(client, doc)
# Store the document text and its embedding together
if embedding: # Only store if embedding was successful
document_embeddings.append({"text": doc, "embedding": embedding})
else:
print(f"Skipping document due to embedding error: \"{doc[:50]}...\"")
print(f"\nSuccessfully generated embeddings for {len(document_embeddings)} documents.")
# 3. Define the user's search query
search_query = "What is AI?"
# search_query = "Things to see in Paris"
# search_query = "How does NLP work?"
# search_query = "Cooking instructions"
print(f"\nSearch Query: \"{search_query}\"")
# 4. Generate embedding for the search query
print("\nGenerating embedding for the search query...")
query_embedding = get_embedding(client, search_query)
# 5. Calculate similarity and rank documents
search_results = []
if query_embedding and document_embeddings:
print("\nCalculating similarities...")
for doc_data in document_embeddings:
similarity = cosine_similarity(query_embedding, doc_data["embedding"])
search_results.append({"text": doc_data["text"], "score": similarity})
# Sort results by similarity score in descending order
search_results.sort(key=lambda x: x["score"], reverse=True)
# 6. Display results
print("\n--- Semantic Search Results ---")
print(f"Top results for query: \"{search_query}\"\n")
if not search_results:
print("No results found (or error calculating similarities).")
else:
# Display top N results (e.g., top 3)
top_n = 3
for i, result in enumerate(search_results[:top_n]):
print(f"{i+1}. Score: {result['score']:.4f}")
print(f" Text: {result['text']}")
print("-" * 10)
if len(search_results) > top_n:
print(f"(Showing top {top_n} of {len(search_results)} results)")
else:
print("\nCould not perform search.")
if not query_embedding:
print("Reason: Failed to generate embedding for the search query.")
if not document_embeddings:
print("Reason: No document embeddings were successfully generated.")
Explicación del Desglose del Código:
- Configuración y Funciones Auxiliares: Incluye importaciones estándar (
openai
,os
,dotenv
,numpy
), inicialización del cliente, y las funciones auxiliaresget_embedding
ycosine_similarity
del ejemplo anterior. - Almacén de Documentos: Una lista simple de Python (
document_store
) contiene el texto de los documentos que queremos buscar. En una aplicación real, estos datos probablemente provendrían de una base de datos o sistema de archivos. - Generación de Embeddings de Documentos:
- El script itera a través de cada documento en el
document_store
. - Llama a
get_embedding
para cada documento para obtener su representación numérica. - Almacena el texto original del documento y su vector de embedding correspondiente juntos (por ejemplo, en una lista de diccionarios). Este paso de pre-computación es crucial para la eficiencia en sistemas reales – generas los embeddings de documentos una vez y los almacenas. El manejo de errores asegura que los documentos se omitan si falla la generación del embedding.
- El script itera a través de cada documento en el
- Consulta de Búsqueda: Se define una cadena de ejemplo
search_query
. - Generación del Embedding de Consulta: La función
get_embedding
se llama nuevamente, esta vez para elsearch_query
. - Cálculo de Similitud y Clasificación:
- Verifica si tanto el embedding de consulta como los embeddings de documentos se generaron exitosamente.
- Itera a través de los
document_embeddings
almacenados. - Para cada documento, calcula la
cosine_similarity
entre elquery_embedding
y el embedding del documento. - El texto del documento y su puntaje de similitud calculado se almacenan en una lista
search_results
. - Finalmente,
search_results.sort(...)
ordena la lista basándose en elscore
en orden descendente (mayor similitud primero).
- Mostrar Resultados: El script imprime los N (por ejemplo, 3) documentos más relevantes de la lista ordenada, mostrando su puntaje de similitud y contenido de texto.
Este ejemplo ilustra claramente el concepto central de la búsqueda semántica: convertir tanto los documentos como las consultas en embeddings y luego usar la similitud vectorial (como la similitud del coseno) para encontrar documentos que están semánticamente relacionados con la consulta, incluso si no comparten las palabras clave exactas.
3.2.2 Agrupamiento por temas
El agrupamiento por temas es una técnica sofisticada para organizar y analizar grandes colecciones de documentos mediante su agrupación automática basada en su contenido semántico. Esta aplicación avanzada de embeddings transforma la manera en que procesamos y entendemos colecciones de documentos a gran escala, ofreciendo una poderosa solución para la organización de contenido. El sistema funciona convirtiendo cada documento en un vector de embedding multidimensional que captura su significado, y luego utiliza algoritmos de agrupamiento para juntar vectores similares.
Esta poderosa aplicación de embeddings permite a los sistemas:
- Identificar patrones temáticos a través de miles de documentos sin etiquetado manual - el sistema puede detectar automáticamente temas y tendencias comunes a través de vastas colecciones de documentos, ahorrando incontables horas de trabajo de categorización manual
- Agrupar discusiones, artículos o piezas de contenido similares en categorías intuitivas - al comprender las relaciones semánticas entre documentos, el sistema puede crear agrupaciones significativas que reflejan divisiones naturales de temas, incluso cuando los documentos utilizan terminología diferente para discutir los mismos conceptos
- Descubrir temas y tendencias emergentes dentro de grandes colecciones de documentos - a medida que se agrega nuevo contenido, el sistema puede identificar nuevos grupos temáticos que se están formando, ayudando a las organizaciones a mantenerse al día con las tendencias en desarrollo en su campo
- Crear jerarquías de contenido dinámicas que se adaptan cuando se agregan nuevos documentos - a diferencia de los sistemas de categorización estática tradicionales, el agrupamiento basado en embeddings puede reorganizar y refinar automáticamente las estructuras de categorías a medida que la colección de contenido crece y evoluciona
Por ejemplo, una organización de noticias podría usar el agrupamiento por temas para agrupar automáticamente miles de artículos en categorías como "Tecnología", "Política" o "Deportes", incluso cuando estos temas no están etiquetados explícitamente. Los embeddings capturan las relaciones semánticas entre artículos analizando el significado real y el contexto del contenido, no solo palabras clave. Esto permite un agrupamiento mucho más sofisticado que puede entender distinciones sutiles - por ejemplo, reconociendo que un artículo sobre el impacto económico de los estadios deportivos pertenece tanto a las categorías "Deportes" como "Negocios", o que artículos sobre diferentes lenguajes de programación pertenecen todos a un grupo de "Tecnología" a pesar de usar terminología completamente diferente.
Ejemplo:
A continuación se muestra un ejemplo de código que demuestra el agrupamiento por temas usando embeddings de OpenAI y el algoritmo K-means de scikit-learn
.
Este código:
- Definirá una lista de documentos de ejemplo que cubren diferentes temas implícitos.
- Generará embeddings para cada documento usando la API de OpenAI.
- Aplicará el algoritmo de agrupamiento K-Means para agrupar los vectores de embedding.
- Mostrará los documentos pertenecientes a cada grupo identificado.
import os
from openai import OpenAI, OpenAIError
from dotenv import load_dotenv
import numpy as np
from sklearn.cluster import KMeans # For clustering algorithm
import datetime
# --- Configuration ---
load_dotenv()
# Get the current date and location context
current_timestamp = "2025-03-23 15:26:00 CDT"
current_location = "Dallas, Texas, United States"
print(f"Running Topic Clustering example at: {current_timestamp}")
print(f"Location Context: {current_location}")
# Initialize the OpenAI client
try:
api_key = os.getenv("OPENAI_API_KEY")
if not api_key:
raise ValueError("OPENAI_API_KEY not found in environment variables.")
client = OpenAI(api_key=api_key)
print("OpenAI client initialized.")
except ValueError as e:
print(f"Configuration Error: {e}")
exit()
except Exception as e:
print(f"Error initializing OpenAI client: {e}")
exit()
# Define the embedding model
EMBEDDING_MODEL = "text-embedding-3-small"
# --- Helper Function to Generate Embedding ---
# (Same as in previous embeddings examples)
def get_embedding(client, text, model=EMBEDDING_MODEL):
"""Generates an embedding for the given text using the specified model."""
# Truncate text for printing if it's too long
print_text = text[:70] + "..." if len(text) > 70 else text
print(f"Generating embedding for: \"{print_text}\"")
try:
response = client.embeddings.create(
input=text,
model=model
)
embedding_vector = response.data[0].embedding
# print("Embedding generation successful.") # Reduce verbosity
return embedding_vector
except OpenAIError as e:
print(f"OpenAI API Error generating embedding for text '{print_text}': {e}")
return None
except Exception as e:
print(f"An unexpected error occurred during embedding generation for text '{print_text}': {e}")
return None
# --- Topic Clustering Implementation ---
# 1. Define your collection of documents
# These documents cover roughly 3 topics: AI/Tech, Travel/Geography, Food/Cooking
documents = [
"Artificial intelligence research focuses on creating systems capable of performing tasks that typically require human intelligence.",
"The Eiffel Tower is a wrought-iron lattice tower on the Champ de Mars in Paris, France.",
"A recipe for classic French onion soup involves caramelizing onions and topping with bread and cheese.",
"Machine learning, a subset of AI, involves algorithms that allow systems to learn from data.",
"The Great Wall of China is a series of fortifications made of stone, brick, tamped earth, wood, and other materials.",
"Natural Language Processing (NLP) enables computers to understand and process human language.",
"Baking bread requires careful measurement of ingredients like flour, water, yeast, and salt.",
"The Colosseum in Rome, Italy, is an oval amphitheatre in the centre of the city.",
"Deep learning utilizes artificial neural networks with multiple layers to model complex patterns.",
"Sushi is a traditional Japanese dish of prepared vinegared rice, usually with some sugar and salt, accompanying a variety of ingredients, such as seafood, often raw, and vegetables."
]
print(f"\nDocument collection contains {len(documents)} documents.")
# 2. Generate embeddings for all documents
print("\nGenerating embeddings for the document collection...")
embeddings = []
valid_documents = [] # Keep track of documents for which embedding was successful
for doc in documents:
embedding = get_embedding(client, doc)
if embedding:
embeddings.append(embedding)
valid_documents.append(doc) # Add corresponding document text
else:
print(f"Skipping document due to embedding error: \"{doc[:70]}...\"")
if not embeddings:
print("\nError: No embeddings were generated. Cannot perform clustering.")
exit()
print(f"\nSuccessfully generated embeddings for {len(valid_documents)} documents.")
# Convert embeddings list to a NumPy array for scikit-learn
embedding_matrix = np.array(embeddings)
# 3. Apply Clustering Algorithm (K-Means)
# We need to choose the number of clusters (k). Let's assume we expect 3 topics.
# In real applications, determining the optimal 'k' often requires experimentation
# (e.g., using the elbow method or silhouette scores).
n_clusters = 3
print(f"\nApplying K-Means clustering with k={n_clusters}...")
try:
kmeans = KMeans(n_clusters=n_clusters, random_state=42, n_init=10) # n_init suppresses warning
kmeans.fit(embedding_matrix)
cluster_labels = kmeans.labels_
print("Clustering complete.")
except Exception as e:
print(f"An error occurred during clustering: {e}")
exit()
# 4. Display Documents by Cluster
print(f"\n--- Documents Grouped by Topic Cluster (k={n_clusters}) ---")
# Create a dictionary to hold documents for each cluster
clustered_documents = {i: [] for i in range(n_clusters)}
# Assign each document (that had a valid embedding) to its cluster
for i, label in enumerate(cluster_labels):
clustered_documents[label].append(valid_documents[i])
# Print the contents of each cluster
for cluster_id, docs_in_cluster in clustered_documents.items():
print(f"\nCluster {cluster_id + 1}:")
if not docs_in_cluster:
print(" (No documents in this cluster)")
else:
for doc_text in docs_in_cluster:
# Print truncated document text for readability
print_text = doc_text[:100] + "..." if len(doc_text) > 100 else doc_text
print(f" - {print_text}")
print("-" * 20)
print("\nNote: The quality of clustering depends on the data, the embedding model,")
print("and the chosen number of clusters (k). Cluster numbers are arbitrary.")
Explicación del Desglose del Código:
- Configuración y Funciones Auxiliares:
- Incluye importaciones estándar más
KMeans
desklearn.cluster
. - Inicializa el cliente de OpenAI.
- Incluye la función auxiliar
get_embedding
(igual que antes).
- Incluye importaciones estándar más
- Colección de Documentos: Una lista llamada
documents
contiene el contenido de texto. Los documentos de muestra están elegidos para representar algunos temas subyacentes distintos (IA/Tecnología, Viajes/Geografía, Comida/Cocina). - Generación de Embeddings:
- El script itera a través de los
documents
. - Llama a
get_embedding
para cada documento. - Almacena los embeddings exitosos en la lista
embeddings
y el texto del documento correspondiente envalid_documents
. Esto asegura que los índices coincidan posteriormente. - El manejo de errores omite documentos si falla la generación del embedding.
- La lista de vectores de embedding se convierte en un array de NumPy (
embedding_matrix
), que es el formato de entrada estándar para los algoritmos descikit-learn
.
- El script itera a través de los
- Agrupamiento (K-Means):
- Elección de
k
: El número de grupos (n_clusters
) se establece (aquí,k=3
, asumiendo que esperamos tres temas basados en los datos de muestra). Un comentario destaca que encontrar elk
óptimo es frecuentemente una tarea separada en escenarios del mundo real. - Inicialización: Se crea un objeto
KMeans
.n_clusters
especifica el número deseado de grupos.random_state
asegura la reproducibilidad.n_init=10
ejecuta el algoritmo múltiples veces con diferentes centroides iniciales y elige el mejor resultado (suprime una advertencia futura). - Ajuste:
kmeans.fit(embedding_matrix)
ejecuta el algoritmo de agrupamiento K-Means en los embeddings de documentos. Encuentra los centros de los grupos y asigna cada vector de embedding al centro más cercano. - Etiquetas:
kmeans.labels_
contiene un array donde cada elemento indica el ID del grupo (0, 1, 2, etc.) asignado al embedding del documento correspondiente.
- Elección de
- Mostrar Resultados:
- Se crea un diccionario (
clustered_documents
) para organizar los resultados, con claves que representan los IDs de los grupos. - El script itera a través de las
cluster_labels
asignadas por K-Means. Para cada índicei
de documento, encuentra sulabel
asignada y añade el texto correspondiente devalid_documents[i]
a la lista para ese ID de grupo en el diccionario. - Finalmente, recorre el diccionario
clustered_documents
e imprime el texto de los documentos pertenecientes a cada grupo, agrupándolos claramente por el grupo temático identificado por el algoritmo.
- Se crea un diccionario (
Este ejemplo demuestra el poder de los embeddings para el descubrimiento de temas no supervisado. Al convertir texto en vectores, podemos usar algoritmos matemáticos como K-Means para agrupar documentos semánticamente similares sin necesidad de etiquetas predefinidas.
3.2.3 Sistemas de Recomendación
Sugerir elementos relacionados mediante la comprensión de las conexiones más profundas entre diferentes piezas de contenido. Esta poderosa aplicación de los embeddings permite a los sistemas proporcionar recomendaciones personalizadas analizando las relaciones semánticas entre elementos. Los vectores de embedding capturan patrones sutiles y similitudes que podrían no ser inmediatamente obvios para los observadores humanos.
Así es como los sistemas de recomendación aprovechan los embeddings:
- Filtrado Basado en Contenido
- Los sistemas analizan las características reales del contenido (como descripciones de texto, características o atributos)
- Cada elemento se convierte en un vector de embedding que representa sus características principales
- Los elementos similares se encuentran midiendo la distancia entre estos vectores
- Mejora del Filtrado Colaborativo
- Los comportamientos y preferencias de los usuarios también se convierten en embeddings
- El sistema puede identificar patrones en las interacciones usuario-elemento
- Esto ayuda a predecir qué elementos podría gustarle a un usuario basándose en las preferencias de usuarios similares
Por ejemplo, un servicio de streaming de video puede recomendar programas no solo basándose en etiquetas de género, sino entendiendo elementos temáticos, estilos narrativos y patrones narrativos complejos. Los vectores de embedding pueden capturar características matizadas como:
- Ritmo y complejidad de la trama
- Estilos de desarrollo de personajes
- Tono emocional y atmósfera
- Técnicas visuales y de dirección
De manera similar, las plataformas de comercio electrónico pueden sugerir productos entendiendo las similitudes contextuales en las descripciones de productos, el comportamiento del usuario y las características de los artículos. Esto incluye analizar:
- Descripciones y características de productos
- Patrones de navegación y compra de usuarios
- Niveles de precio y calidad
- Relaciones entre marcas y posicionamiento en el mercado
Esta comprensión semántica lleva a recomendaciones más precisas y relevantes en comparación con los métodos tradicionales que dependen únicamente de categorías explícitas o calificaciones de usuarios. El sistema puede identificar conexiones sutiles y patrones que podrían pasarse por alto con enfoques convencionales de recomendación, resultando en experiencias de usuario más atractivas y personalizadas.
Ejemplo:
El siguiente ejemplo de código demuestra cómo los embeddings de OpenAI pueden utilizarse para construir un sistema de recomendación simple basado en contenido.
Este script:
- Definirá un pequeño catálogo de elementos (por ejemplo, descripciones de películas).
- Generará embeddings para estos elementos.
- Elegirá un elemento objetivo.
- Encontrará otros elementos en el catálogo que sean semánticamente similares al elemento objetivo basándose en sus embeddings.
- Presentará los elementos más similares como recomendaciones.
import os
from openai import OpenAI, OpenAIError
from dotenv import load_dotenv
import numpy as np # For cosine similarity calculation
import datetime
# --- Configuration ---
load_dotenv()
# Get the current date and location context
current_timestamp = "2025-03-24 15:29:00 CDT"
current_location = "Austin, Texas, United States"
print(f"Running Recommendation System example at: {current_timestamp}")
print(f"Location Context: {current_location}")
# Initialize the OpenAI client
try:
api_key = os.getenv("OPENAI_API_KEY")
if not api_key:
raise ValueError("OPENAI_API_KEY not found in environment variables.")
client = OpenAI(api_key=api_key)
print("OpenAI client initialized.")
except ValueError as e:
print(f"Configuration Error: {e}")
exit()
except Exception as e:
print(f"Error initializing OpenAI client: {e}")
exit()
# Define the embedding model
EMBEDDING_MODEL = "text-embedding-3-small"
# --- Helper Function to Generate Embedding ---
# (Same as in previous embeddings examples)
def get_embedding(client, text, model=EMBEDDING_MODEL):
"""Generates an embedding for the given text using the specified model."""
# Truncate text for printing if it's too long
print_text = text[:70] + "..." if len(text) > 70 else text
print(f"Generating embedding for: \"{print_text}\"")
try:
response = client.embeddings.create(
input=text,
model=model
)
embedding_vector = response.data[0].embedding
# print("Embedding generation successful.") # Reduce verbosity
return embedding_vector
except OpenAIError as e:
print(f"OpenAI API Error generating embedding for text '{print_text}': {e}")
return None
except Exception as e:
print(f"An unexpected error occurred during embedding generation for text '{print_text}': {e}")
return None
# --- Helper Function for Cosine Similarity ---
# (Same as in previous embeddings examples)
def cosine_similarity(vec_a, vec_b):
"""Calculates the cosine similarity between two vectors."""
if vec_a is None or vec_b is None:
return 0.0 # Return 0 if any vector is missing
vec_a = np.array(vec_a)
vec_b = np.array(vec_b)
norm_a = np.linalg.norm(vec_a)
norm_b = np.linalg.norm(vec_b)
if norm_a == 0 or norm_b == 0:
return 0.0
else:
similarity = np.dot(vec_a, vec_b) / (norm_a * norm_b)
return similarity
# --- Recommendation System Implementation ---
# 1. Define your item catalog (e.g., movie descriptions)
# In a real application, this would come from a database.
item_catalog = [
{"id": "mov001", "title": "Space Odyssey: The Final Frontier", "description": "A visually stunning sci-fi epic exploring humanity's place in the universe, featuring complex themes and groundbreaking special effects."},
{"id": "mov002", "title": "Galactic Wars: Attack of the Clones", "description": "An action-packed space opera with laser battles, alien creatures, and a classic good versus evil storyline."},
{"id": "com001", "title": "Laugh Riot", "description": "A slapstick comedy about mistaken identities and hilarious mishaps during a weekend getaway."},
{"id": "doc001", "title": "Wonders of the Deep", "description": "An awe-inspiring documentary showcasing the beauty and mystery of marine life in the world's oceans."},
{"id": "mov003", "title": "Cyber City 2077", "description": "A gritty cyberpunk thriller set in a dystopian future, exploring themes of technology, consciousness, and rebellion."},
{"id": "com002", "title": "The Office Party", "description": "A witty ensemble comedy centered around awkward interactions and office politics during an annual holiday celebration."},
{"id": "doc002", "title": "Cosmic Journeys", "description": "A documentary exploring the vastness of space, black holes, distant galaxies, and the search for extraterrestrial life."},
{"id": "mov004", "title": "Interstellar Echoes", "description": "A philosophical science fiction film about astronauts travelling through a wormhole in search of a new home for humanity."}
]
print(f"\nItem catalog contains {len(item_catalog)} items.")
# 2. Generate embeddings for all items in the catalog (pre-computation)
print("\nGenerating embeddings for the item catalog...")
item_embeddings_data = []
for item in item_catalog:
# Combine title and description for a richer embedding
text_to_embed = f"{item['title']}: {item['description']}"
embedding = get_embedding(client, text_to_embed)
if embedding:
# Store item ID and its embedding
item_embeddings_data.append({"id": item["id"], "embedding": embedding})
else:
print(f"Skipping item {item['id']} due to embedding error.")
if not item_embeddings_data:
print("\nError: No embeddings were generated. Cannot provide recommendations.")
exit()
print(f"\nSuccessfully generated embeddings for {len(item_embeddings_data)} items.")
# 3. Select a target item for which to find recommendations
target_item_id = "mov001" # Let's find movies similar to "Space Odyssey"
print(f"\nFinding recommendations similar to item ID: {target_item_id}")
# Find the embedding for the target item
target_embedding = None
for item_data in item_embeddings_data:
if item_data["id"] == target_item_id:
target_embedding = item_data["embedding"]
break
if target_embedding is None:
print(f"Error: Could not find the embedding for the target item ID '{target_item_id}'.")
exit()
# 4. Calculate similarity between the target item and all other items
recommendations = []
print("\nCalculating similarities...")
for item_data in item_embeddings_data:
# Don't compare the item with itself
if item_data["id"] == target_item_id:
continue
similarity = cosine_similarity(target_embedding, item_data["embedding"])
recommendations.append({"id": item_data["id"], "score": similarity})
# 5. Sort potential recommendations by similarity score
recommendations.sort(key=lambda x: x["score"], reverse=True)
# 6. Display top N recommendations
print("\n--- Top Recommendations ---")
# Find the original title/description for the target item for context
target_item_info = next((item for item in item_catalog if item["id"] == target_item_id), None)
if target_item_info:
print(f"Based on: \"{target_item_info['title']}\"\n")
if not recommendations:
print("No recommendations found (or error calculating similarities).")
else:
top_n = 3
print(f"Top {top_n} most similar items:")
for i, rec in enumerate(recommendations[:top_n]):
# Find the full item details from the original catalog
rec_details = next((item for item in item_catalog if item["id"] == rec["id"]), None)
if rec_details:
print(f"{i+1}. ID: {rec['id']}, Score: {rec['score']:.4f}")
print(f" Title: {rec_details['title']}")
print(f" Description: {rec_details['description'][:100]}...") # Truncate description
print("-" * 10)
else:
print(f"{i+1}. ID: {rec['id']}, Score: {rec['score']:.4f} (Details not found)")
print("-" * 10)
if len(recommendations) > top_n:
print(f"(Showing top {top_n} of {len(recommendations)} potential recommendations)")
Explicación del Desglose del Código
Este ejemplo demuestra cómo construir un sistema de recomendación basado en contenido de manera sencilla combinando los embeddings de OpenAI con cálculos de similitud del coseno.
- Configuración y Funciones Auxiliares:
- Incluye importaciones estándar (
openai
,os
,dotenv
,numpy
), inicialización del cliente, y las funciones auxiliaresget_embedding
ycosine_similarity
previamente definidas.
- Incluye importaciones estándar (
- Catálogo de Elementos:
- Una lista de diccionarios (
item_catalog
) representa los elementos disponibles para recomendación (por ejemplo, películas). Cada elemento tiene unid
,título
ydescripción
. En un sistema real, esto probablemente se cargaría desde una base de datos.
- Una lista de diccionarios (
- Generación de Embeddings de Elementos:
- El script itera a través de cada
item
en elitem_catalog
. - Combinación de Contenido: Combina el
título
y ladescripción
en una sola cadena (text_to_embed
). Esto proporciona un contexto más rico al modelo de embedding que usar solo el título o la descripción por separado. - Llama a
get_embedding
para este texto combinado. - Almacena el
item['id']
y su vector deembedding
correspondiente juntos en la listaitem_embeddings_data
. Este paso de pre-cómputo es una práctica estándar para sistemas de recomendación.
- El script itera a través de cada
- Selección del Elemento Objetivo:
- Una variable
target_item_id
se establece para especificar el elemento para el cual queremos recomendaciones (por ejemplo, encontrar elementos similares amov001
). - El script recupera el vector de embedding pre-calculado para este
target_item_id
de la listaitem_embeddings_data
.
- Una variable
- Cálculo de Similitud:
- Itera a través de todos los elementos con embeddings en
item_embeddings_data
. - Exclusión: Explícitamente omite la comparación si el ID del elemento actual coincide con el
target_item_id
(un elemento no debería recomendarse a sí mismo). - Para cada otro elemento, calcula la
similitud_coseno
entre eltarget_embedding
y el embedding del elemento actual. - Almacena el
id
del otro elemento y supuntuación
de similitud calculada en una lista derecommendations
.
- Itera a través de todos los elementos con embeddings en
- Clasificación de Recomendaciones:
- La lista
recommendations
se ordena usandorecommendations.sort(...)
basándose en el camposcore
en orden descendente, colocando los elementos más similares al principio de la lista.
- La lista
- Mostrar Resultados:
- El script imprime el título del elemento objetivo para contexto.
- Luego itera a través de los N principales (por ejemplo, 3) elementos en la lista ordenada de
recommendations
. - Para cada ID de elemento recomendado, busca los detalles completos (título, descripción) del
item_catalog
original. - Imprime el rango, ID, puntuación de similitud, título y una descripción truncada para cada elemento recomendado.
Este ejemplo muestra efectivamente cómo los embeddings capturan el significado semántico, permitiendo que el sistema recomiende elementos basándose en la similitud de contenido (por ejemplo, recomendando otras películas de ciencia ficción filosóficas similares a "Space Odyssey") en lugar de solo etiquetas explícitas o historial del usuario.
3.2.4 Recuperación de contexto para asistentes de IA
Ayudar a los chatbots y sistemas de IA a encontrar y utilizar información relevante de grandes bases de conocimiento mediante la conversión tanto de consultas como de conocimiento almacenado en embeddings. Este proceso involucra varios pasos clave:
Primero, el sistema convierte todos los documentos en su base de conocimiento en vectores de embedding - representaciones numéricas que capturan el significado semántico del texto. Estos embeddings se almacenan en una base de datos vectorial para una recuperación rápida.
Cuando un asistente de IA recibe una pregunta, convierte esa consulta en un vector de embedding usando el mismo proceso. Esto asegura que tanto el conocimiento almacenado como las preguntas entrantes estén representados en el mismo espacio matemático.
El sistema luego realiza una búsqueda de similitud para encontrar la información más relevante. Esta búsqueda compara el embedding de la consulta con todos los embeddings almacenados, típicamente usando técnicas como similitud del coseno o búsqueda del vecino más cercano. La belleza de este enfoque es que puede identificar contenido semánticamente similar incluso cuando la redacción exacta difiere significativamente.
Por ejemplo, una consulta sobre "el portátil no enciende" podría coincidir con documentación sobre "problemas de energía en computadoras" porque sus embeddings capturan el significado subyacente similar. Esta coincidencia semántica es mucho más potente que la búsqueda tradicional basada en palabras clave.
Una vez que se identifica la información relevante, puede utilizarse para generar respuestas más precisas e informadas. Esto es particularmente potente para aplicaciones específicas de dominio donde la IA necesita acceder a documentación técnica, información de productos o políticas empresariales. El sistema puede manejar consultas complejas combinando múltiples piezas de contexto relevante, asegurando que las respuestas sean tanto precisas como exhaustivas.
Ejemplo:
A continuación se muestra un ejemplo de código que demuestra cómo los asistentes de IA pueden recuperar contexto usando embeddings de OpenAI, implementando los conceptos discutidos en la sección 3.2.4.
El script ilustra el proceso esencial de búsqueda en una base de conocimiento para proporcionar contexto relevante para las respuestas del asistente de IA.
import os
from openai import OpenAI, OpenAIError
from dotenv import load_dotenv
import numpy as np # For cosine similarity calculation
import datetime
# --- Configuration ---
load_dotenv()
# Get the current date and location context
current_timestamp = "2025-02-10 15:35:00 CDT"
current_location = "Grapevine, Texas, United States"
print(f"Running Context Retrieval example at: {current_timestamp}")
print(f"Location Context: {current_location}")
# Initialize the OpenAI client
try:
api_key = os.getenv("OPENAI_API_KEY")
if not api_key:
raise ValueError("OPENAI_API_KEY not found in environment variables.")
client = OpenAI(api_key=api_key)
print("OpenAI client initialized.")
except ValueError as e:
print(f"Configuration Error: {e}")
exit()
except Exception as e:
print(f"Error initializing OpenAI client: {e}")
exit()
# Define the embedding model
EMBEDDING_MODEL = "text-embedding-3-small"
# --- Helper Function to Generate Embedding ---
# (Same as in previous embeddings examples)
def get_embedding(client, text, model=EMBEDDING_MODEL):
"""Generates an embedding for the given text using the specified model."""
print_text = text[:70] + "..." if len(text) > 70 else text
print(f"Generating embedding for: \"{print_text}\"")
try:
response = client.embeddings.create(
input=text,
model=model
)
embedding_vector = response.data[0].embedding
return embedding_vector
except OpenAIError as e:
print(f"OpenAI API Error generating embedding for text '{print_text}': {e}")
return None
except Exception as e:
print(f"An unexpected error occurred during embedding generation for text '{print_text}': {e}")
return None
# --- Helper Function for Cosine Similarity ---
# (Same as in previous embeddings examples)
def cosine_similarity(vec_a, vec_b):
"""Calculates the cosine similarity between two vectors."""
if vec_a is None or vec_b is None:
return 0.0
vec_a = np.array(vec_a)
vec_b = np.array(vec_b)
norm_a = np.linalg.norm(vec_a)
norm_b = np.linalg.norm(vec_b)
if norm_a == 0 or norm_b == 0:
return 0.0
else:
similarity = np.dot(vec_a, vec_b) / (norm_a * norm_b)
return similarity
# --- Context Retrieval Implementation ---
# 1. Define your Knowledge Base (list of text documents/chunks)
# This represents the information the AI assistant can draw upon.
knowledge_base = [
{"id": "doc001", "source": "troubleshooting_guide.txt", "content": "If your laptop fails to power on, first check the power adapter connection. Ensure the cable is securely plugged into both the laptop and the wall outlet. Try a different outlet if possible."},
{"id": "doc002", "source": "troubleshooting_guide.txt", "content": "A blinking power light often indicates a battery issue or a charging problem. Try removing the battery (if removable) and powering on with only the adapter connected."},
{"id": "doc003", "source": "faq.html", "content": "To reset your password, go to the login page and click the 'Forgot Password' link. Follow the instructions sent to your registered email address."},
{"id": "doc004", "source": "product_manual.pdf", "content": "The Model X laptop uses a USB-C port for charging. Ensure you are using the correct wattage power adapter (65W minimum recommended)."},
{"id": "doc005", "source": "troubleshooting_guide.txt", "content": "No display output? Check if the laptop is making any sounds (fan spinning, beeps). Try connecting an external monitor to rule out a screen issue."},
{"id": "doc006", "source": "support_articles/power_issues.md", "content": "Holding the power button down for 15-30 seconds can perform a hard reset, sometimes resolving power-on failures."},
{"id": "doc007", "source": "faq.html", "content": "Software updates can be found in the 'System Settings' under the 'Updates' section. Ensure you are connected to the internet."}
]
print(f"\nKnowledge base contains {len(knowledge_base)} documents/chunks.")
# 2. Generate embeddings for the knowledge base (pre-computation)
print("\nGenerating embeddings for the knowledge base...")
kb_embeddings_data = []
for doc in knowledge_base:
embedding = get_embedding(client, doc["content"])
if embedding:
# Store document ID and its embedding
kb_embeddings_data.append({"id": doc["id"], "embedding": embedding})
else:
print(f"Skipping document {doc['id']} due to embedding error.")
if not kb_embeddings_data:
print("\nError: No embeddings were generated for the knowledge base. Cannot retrieve context.")
exit()
print(f"\nSuccessfully generated embeddings for {len(kb_embeddings_data)} knowledge base documents.")
# 3. Define the user's query to the AI assistant
user_query = "My computer won't start up."
# user_query = "How do I update the system software?"
# user_query = "Screen is black when I press the power button."
print(f"\nUser Query: \"{user_query}\"")
# 4. Generate embedding for the user query
print("\nGenerating embedding for the user query...")
query_embedding = get_embedding(client, user_query)
# 5. Find relevant documents from the knowledge base using similarity search
retrieved_context = []
if query_embedding and kb_embeddings_data:
print("\nCalculating similarities to find relevant context...")
for doc_data in kb_embeddings_data:
similarity = cosine_similarity(query_embedding, doc_data["embedding"])
retrieved_context.append({"id": doc_data["id"], "score": similarity})
# Sort context documents by similarity score in descending order
retrieved_context.sort(key=lambda x: x["score"], reverse=True)
# 6. Select Top N relevant documents to use as context
top_n_context = 3
print(f"\n--- Top {top_n_context} Relevant Context Documents Found ---")
if not retrieved_context:
print("No relevant context found (or error calculating similarities).")
else:
final_context_docs = []
for i, context_item in enumerate(retrieved_context[:top_n_context]):
# Find the full document details from the original knowledge base
doc_details = next((doc for doc in knowledge_base if doc["id"] == context_item["id"]), None)
if doc_details:
print(f"{i+1}. ID: {context_item['id']}, Score: {context_item['score']:.4f}")
print(f" Source: {doc_details['source']}")
print(f" Content: {doc_details['content'][:150]}...") # Truncate content
print("-" * 10)
final_context_docs.append(doc_details['content']) # Store content for next step
else:
print(f"{i+1}. ID: {context_item['id']}, Score: {context_item['score']:.4f} (Details not found)")
print("-" * 10)
if len(retrieved_context) > top_n_context:
print(f"(Showing top {top_n_context} of {len(retrieved_context)} potential context documents)")
# --- Next Step (Conceptual - Not coded here) ---
print("\n--- Next Step: Generating AI Assistant Response ---")
print("The content from the relevant documents above would now be combined")
print("with the original user query and sent to a model like GPT-4o")
print("as context to generate an informed and accurate response.")
print("Example prompt structure for GPT-4o:")
print("```")
print(f"System: You are a helpful AI assistant. Answer the user's question based ONLY on the provided context documents.")
print(f"User: Context Documents:\n1. {final_context_docs[0][:50]}...\n2. {final_context_docs[1][:50]}...\n[...]\n\nQuestion: {user_query}\n\nAnswer:")
print("```")
else:
print("\nCould not retrieve context.")
if not query_embedding:
print("Reason: Failed to generate embedding for the user query.")
if not kb_embeddings_data:
print("Reason: No knowledge base embeddings were successfully generated.")
Explicación del Desglose del Código
Este ejemplo demuestra el mecanismo central detrás de la recuperación de contexto para asistentes de IA usando embeddings – encontrar información relevante de una base de conocimiento para responder a la consulta de un usuario.
- Configuración y Funciones Auxiliares:
- Incluye importaciones estándar (
openai
,os
,dotenv
,numpy
), inicialización del cliente, y las funciones auxiliaresget_embedding
ycosine_similarity
.
- Incluye importaciones estándar (
- Definición de la Base de Conocimiento:
- Una lista de diccionarios (
knowledge_base
) simula el almacén de información al que puede acceder el asistente de IA. Cada diccionario representa un documento o fragmento de información e incluye unid
,source
(metadatos opcionales), y elcontent
del texto actual.
- Una lista de diccionarios (
- Generación de Embeddings de la Base de Conocimiento:
- El script itera a través de cada
doc
en elknowledge_base
. - Llama a
get_embedding
en eldoc["content"]
para obtener su representación vectorial. - Almacena el
doc['id']
y su correspondiente vectorembedding
juntos enkb_embeddings_data
. Este es el paso crucial de pre-computación – los embeddings para la base de conocimiento típicamente se generan fuera de línea y se almacenan (a menudo en una base de datos vectorial especializada) para una recuperación rápida.
- El script itera a través de cada
- Consulta del Usuario:
- Una cadena de ejemplo
user_query
representa la pregunta realizada al asistente de IA.
- Una cadena de ejemplo
- Generación del Embedding de la Consulta:
- La función
get_embedding
se llama para eluser_query
para obtener su representación vectorial en el mismo espacio de embeddings que los documentos de la base de conocimiento.
- La función
- Búsqueda de Similitud (Recuperación de Contexto):
- Itera a través de todos los embeddings pre-computados en
kb_embeddings_data
. - Para cada documento de la base de conocimiento, calcula la
cosine_similarity
entre elquery_embedding
y el embedding del documento. - Almacena el
id
del documento y suscore
de similitud relativo a la consulta en una listaretrieved_context
.
- Itera a través de todos los embeddings pre-computados en
- Clasificación y Selección:
- La lista
retrieved_context
se ordena porscore
en orden descendente, trayendo los documentos semánticamente más relevantes al principio. - El script selecciona los N primeros (por ejemplo, 3) documentos de esta lista ordenada. Estos documentos representan el contexto más relevante encontrado en la base de conocimiento para la consulta del usuario.
- La lista
- Mostrar el Contexto Recuperado:
- El script imprime los detalles (ID, puntuación, fuente, vista previa del contenido) de los N primeros documentos de contexto encontrados.
- Siguiente Paso Conceptual (Explicación Crucial):
- Las declaraciones finales de impresión explican el propósito de este proceso de recuperación. El contenido de estos
final_context_docs
no sería la respuesta final. En su lugar, se combinarían con eluser_query
original y se pasarían como contexto a un modelo de lenguaje grande como GPT-4o en una llamada API subsiguiente. - Se muestra una estructura de prompt de ejemplo, ilustrando cómo el contexto recuperado fundamenta al asistente de IA, permitiéndole generar una respuesta informada basada en la información relevante encontrada en la base de conocimiento, en lugar de confiar únicamente en su conocimiento general.
- Las declaraciones finales de impresión explican el propósito de este proceso de recuperación. El contenido de estos
Este ejemplo demuestra efectivamente la parte de recuperación de la Generación Aumentada por Recuperación (RAG), mostrando cómo los embeddings tienden un puente entre la consulta de un usuario y la información relevante almacenada en una base de conocimiento, permitiendo asistentes de IA más precisos y conscientes del contexto.
3.2.5 Detección de anomalías y similitud
Identificar patrones inusuales o encontrar elementos similares en grandes conjuntos de datos mediante la comparación de sus representaciones semánticas es una aplicación fundamental de la tecnología de embeddings. Esta poderosa técnica transforma datos sin procesar en vectores matemáticos que capturan la esencia de su contenido, permitiendo análisis sofisticados a gran escala. Así es cómo funcionan estos sistemas y sus aplicaciones clave:
- Detectar Anomalías
- Marcar transacciones o comportamientos inusuales que se desvían de los patrones normales - Por ejemplo, detectar compras sospechosas con tarjeta de crédito comparándolas con patrones típicos de gasto
- Identificar posibles amenazas de seguridad o intentos de fraude - Como reconocer patrones de inicio de sesión inusuales o detectar cuentas falsas basadas en análisis de comportamiento
- Detectar problemas de calidad de datos o valores atípicos en conjuntos de datos - Incluyendo la identificación de entradas de datos incorrectas o mediciones inusuales que podrían indicar mal funcionamiento del equipo
- Encontrar Similitudes
- Agrupar documentos, imágenes o puntos de datos relacionados basados en significado semántico - Esto permite a los sistemas agrupar contenido similar incluso cuando la redacción exacta difiere, facilitando la organización de grandes colecciones de información
- Emparejar consultas o tickets de soporte similares - Ayudando a los equipos de servicio al cliente a identificar problemas comunes y estandarizar respuestas a problemas frecuentes
- Identificar contenido duplicado o casi duplicado - Útil para sistemas de gestión de contenido para mantener la calidad de datos y reducir la redundancia
Al convertir puntos de datos en vectores de embedding, los sistemas pueden medir qué tan "diferentes" o "similares" son los elementos entre sí usando cálculos de distancia matemática. Este proceso funciona mapeando cada elemento a un punto en un espacio de alta dimensión, donde los elementos similares se posicionan más cerca entre sí y los elementos diferentes están más separados. Esta representación matemática hace posible marcar automáticamente patrones inusuales o agrupar elementos relacionados a gran escala, permitiendo tanto la detección de anomalías como la coincidencia de similitud de formas que serían imposibles con sistemas tradicionales basados en reglas.
Ejemplo:
El siguiente ejemplo de código demuestra la detección de similitud y anomalías usando embeddings de OpenAI.
Este script:
- Definirá un conjunto de datos de elementos de texto (por ejemplo, descripciones de transacciones o eventos).
- Generará embeddings para estos elementos.
- Detección de Similitud: Encontrará elementos más similares a un elemento objetivo dado.
- Detección de Anomalías: Identificará elementos que son menos similares (más anómalos) comparados con el resto del conjunto de datos usando un enfoque simple de similitud promedio.
import os
from openai import OpenAI, OpenAIError
from dotenv import load_dotenv
import numpy as np # For cosine similarity calculation
import datetime
# --- Configuration ---
load_dotenv()
# Get the current date and location context
current_timestamp = "2025-01-13 15:40:00 CDT"
current_location = "Houston, Texas, United States"
print(f"Running Similarity & Anomaly Detection example at: {current_timestamp}")
print(f"Location Context: {current_location}")
# Initialize the OpenAI client
try:
api_key = os.getenv("OPENAI_API_KEY")
if not api_key:
raise ValueError("OPENAI_API_KEY not found in environment variables.")
client = OpenAI(api_key=api_key)
print("OpenAI client initialized.")
except ValueError as e:
print(f"Configuration Error: {e}")
exit()
except Exception as e:
print(f"Error initializing OpenAI client: {e}")
exit()
# Define the embedding model
EMBEDDING_MODEL = "text-embedding-3-small"
# --- Helper Function to Generate Embedding ---
# (Same as in previous embeddings examples)
def get_embedding(client, text, model=EMBEDDING_MODEL):
"""Generates an embedding for the given text using the specified model."""
print_text = text[:70] + "..." if len(text) > 70 else text
print(f"Generating embedding for: \"{print_text}\"")
try:
response = client.embeddings.create(
input=text,
model=model
)
embedding_vector = response.data[0].embedding
return embedding_vector
except OpenAIError as e:
print(f"OpenAI API Error generating embedding for text '{print_text}': {e}")
return None
except Exception as e:
print(f"An unexpected error occurred during embedding generation for text '{print_text}': {e}")
return None
# --- Helper Function for Cosine Similarity ---
# (Same as in previous embeddings examples)
def cosine_similarity(vec_a, vec_b):
"""Calculates the cosine similarity between two vectors."""
if vec_a is None or vec_b is None:
return 0.0
vec_a = np.array(vec_a)
vec_b = np.array(vec_b)
norm_a = np.linalg.norm(vec_a)
norm_b = np.linalg.norm(vec_b)
if norm_a == 0 or norm_b == 0:
return 0.0
else:
# Clamp the value to handle potential floating point inaccuracies slightly outside [-1, 1]
similarity = np.dot(vec_a, vec_b) / (norm_a * norm_b)
return np.clip(similarity, -1.0, 1.0)
# --- Similarity and Anomaly Detection Implementation ---
# 1. Define your dataset (e.g., transaction descriptions, log entries)
# Includes mostly normal items and a couple of potentially anomalous ones.
dataset = [
{"id": "txn001", "description": "Grocery purchase at Local Supermarket"},
{"id": "txn002", "description": "Monthly subscription fee for streaming service"},
{"id": "txn003", "description": "Dinner payment at Italian Restaurant"},
{"id": "txn004", "description": "Online order for electronics from TechStore"},
{"id": "txn005", "description": "Fuel purchase at Gas Station"},
{"id": "txn006", "description": "Purchase of fresh produce and bread"}, # Similar to txn001
{"id": "txn007", "description": "Payment for movie streaming subscription"}, # Similar to txn002
{"id": "txn008", "description": "Unusual large wire transfer to overseas account"}, # Potential Anomaly 1
{"id": "txn009", "description": "Purchase of rare antique collectible vase"}, # Potential Anomaly 2
{"id": "txn010", "description": "Coffee purchase at Cafe Central"}
]
print(f"\nDataset contains {len(dataset)} items.")
# 2. Generate embeddings for all items in the dataset (pre-computation)
print("\nGenerating embeddings for the dataset...")
dataset_embeddings_data = []
for item in dataset:
embedding = get_embedding(client, item["description"])
if embedding:
# Store item ID, description, and its embedding
dataset_embeddings_data.append({
"id": item["id"],
"description": item["description"],
"embedding": embedding
})
else:
print(f"Skipping item {item['id']} due to embedding error.")
if not dataset_embeddings_data:
print("\nError: No embeddings were generated. Cannot perform analysis.")
exit()
print(f"\nSuccessfully generated embeddings for {len(dataset_embeddings_data)} items.")
# --- Part A: Similarity Detection ---
print("\n--- Part A: Similarity Detection ---")
# Select a target item to find similar items for
target_item_id_similarity = "txn001" # Find items similar to "Grocery purchase..."
print(f"Finding items similar to item ID: {target_item_id_similarity}")
# Find the target item's data
target_item_data = next((item for item in dataset_embeddings_data if item["id"] == target_item_id_similarity), None)
if target_item_data:
target_embedding = target_item_data["embedding"]
similar_items = []
# Calculate similarity between the target and all other items
for item_data in dataset_embeddings_data:
if item_data["id"] == target_item_id_similarity:
continue # Skip self-comparison
similarity = cosine_similarity(target_embedding, item_data["embedding"])
similar_items.append({
"id": item_data["id"],
"description": item_data["description"],
"score": similarity
})
# Sort by similarity score
similar_items.sort(key=lambda x: x["score"], reverse=True)
# Display top N similar items
print(f"\nItems most similar to: \"{target_item_data['description']}\"")
top_n_similar = 2
for i, item in enumerate(similar_items[:top_n_similar]):
print(f"{i+1}. ID: {item['id']}, Score: {item['score']:.4f}")
print(f" Description: {item['description']}")
print("-" * 10)
else:
print(f"Error: Could not find data for target item ID '{target_item_id_similarity}'.")
# --- Part B: Anomaly Detection (Simple Approach) ---
print("\n--- Part B: Anomaly Detection (Low Average Similarity) ---")
# Calculate the average similarity of each item to all other items
item_avg_similarities = []
num_items = len(dataset_embeddings_data)
if num_items < 2:
print("Need at least 2 items with embeddings to calculate average similarities.")
else:
print("\nCalculating average similarities for anomaly detection...")
for i in range(num_items):
current_item = dataset_embeddings_data[i]
total_similarity = 0
# Compare current item to all others
for j in range(num_items):
if i == j: # Don't compare item to itself
continue
other_item = dataset_embeddings_data[j]
similarity = cosine_similarity(current_item["embedding"], other_item["embedding"])
total_similarity += similarity
# Calculate average similarity (avoid division by zero if only 1 item)
average_similarity = total_similarity / (num_items - 1) if num_items > 1 else 0
item_avg_similarities.append({
"id": current_item["id"],
"description": current_item["description"],
"avg_score": average_similarity
})
print(f"Item ID {current_item['id']} - Avg Similarity: {average_similarity:.4f}")
# Sort items by average similarity in ascending order (lowest first = most anomalous)
item_avg_similarities.sort(key=lambda x: x["avg_score"])
# Display top N potential anomalies (items least similar to others)
print("\nPotential Anomalies (Lowest Average Similarity):")
top_n_anomalies = 3
for i, item in enumerate(item_avg_similarities[:top_n_anomalies]):
print(f"{i+1}. ID: {item['id']}, Avg Score: {item['avg_score']:.4f}")
print(f" Description: {item['description']}")
print("-" * 10)
print("\nNote: Low average similarity suggests an item is semantically")
print("different from the majority of other items in this dataset.")
Explicación del Desglose del Código
Este ejemplo demuestra el uso de embeddings de OpenAI tanto para encontrar elementos similares como para detectar posibles anomalías dentro de un conjunto de datos basándose en el significado semántico.
- Configuración y Funciones Auxiliares:
- Incluye importaciones estándar (
openai
,os
,dotenv
,numpy
), inicialización del cliente, y las funciones auxiliaresget_embedding
ycosine_similarity
. La funcióncosine_similarity
ahora incluyenp.clip
para asegurar que la salida esté estrictamente dentro de [-1, 1].
- Incluye importaciones estándar (
- Definición del Conjunto de Datos:
- Una lista de diccionarios (
dataset
) simula los datos a analizar (por ejemplo, descripciones de transacciones). Cada elemento tiene unid
y unadescription
de texto. Los datos de muestra incluyen principalmente elementos comunes y algunos conceptualmente diferentes destinados a ser posibles anomalías.
- Una lista de diccionarios (
- Generación de Embeddings del Conjunto de Datos:
- El script itera a través de cada
item
en eldataset
. - Llama a
get_embedding
en elitem["description"]
. - Almacena el
item['id']
,item['description']
, y su correspondiente vectorembedding
juntos endataset_embeddings_data
. Esta pre-computación es esencial.
- El script itera a través de cada
- Parte A: Detección de Similitud:
- Selección del Objetivo: Se elige un ID de elemento (
target_item_id_similarity
) para encontrar elementos similares. - Recuperación del Embedding Objetivo: El script encuentra el embedding pre-computado para el elemento objetivo.
- Comparación: Itera a través de todos los otros elementos en
dataset_embeddings_data
, calcula lacosine_similarity
entre el embedding del elemento objetivo y el embedding de cada otro elemento. - Clasificación: Los resultados (ID del otro elemento, descripción, puntuación de similitud) se almacenan y luego se ordenan por puntuación en orden descendente.
- Visualización: Se muestran los N elementos más similares.
- Selección del Objetivo: Se elige un ID de elemento (
- Parte B: Detección de Anomalías (Enfoque de Similitud Promedio Simple):
- Concepto: Este método simple identifica anomalías como elementos que tienen la similitud promedio más baja con todos los otros elementos en el conjunto de datos. Un elemento que es conceptualmente muy diferente del resto probablemente tendrá puntuaciones de similitud bajas cuando se compare con la mayoría de los otros.
- Cálculo:
- El script itera a través de cada elemento (
current_item
) endataset_embeddings_data
. - Para cada
current_item
, itera a través de todos los otros elementos en el conjunto de datos. - Calcula la
cosine_similarity
entre elcurrent_item
y cadaother_item
. - Suma estas similitudes y calcula la similitud promedio para el
current_item
.
- El script itera a través de cada elemento (
- Clasificación: Los elementos se almacenan junto con su
avg_score
calculado y luego se ordenan por esta puntuación en orden ascendente (similitud promedio más baja primero). - Visualización: Se muestran los N elementos con las puntuaciones de similitud promedio más bajas como posibles anomalías. Una nota explica la interpretación.
Este ejemplo muestra dos aplicaciones poderosas: encontrar contenido relacionado (similitud) e identificar valores atípicos (detección de anomalías) aprovechando la comprensión semántica capturada dentro de los embeddings de OpenAI.
3.2.6 Agrupamiento y Etiquetado
Organizar y etiquetar contenido automáticamente basándose en la similitud semántica - una técnica poderosa que utiliza vectores de embedding para comprender el verdadero significado y las relaciones entre diferentes piezas de contenido. Este enfoque va mucho más allá del tradicional emparejamiento de palabras clave, permitiendo una organización de contenido mucho más matizada y precisa.
Cuando el contenido se agrupa, los elementos similares se agrupan naturalmente según su significado semántico, incluso si utilizan terminología diferente para expresar los mismos conceptos. Por ejemplo, los documentos sobre "mantenimiento automotriz" y "reparación de coches" se agruparían juntos a pesar de usar palabras diferentes.
Esta organización inteligente ayuda a crear sistemas de navegación intuitivos, mejora el descubrimiento de contenido y hace que las grandes colecciones de documentos sean más manejables al agrupar elementos relacionados. Algunos beneficios clave incluyen:
- Generación automática de etiquetas basada en temas de grupos
- Organización dinámica que se adapta a medida que se agrega nuevo contenido
- Mejora de la relevancia en las búsquedas mediante comprensión semántica
- Mejor descubrimiento de contenido a través de sugerencias de elementos relacionados
El proceso de agrupamiento puede ajustarse para crear categorías amplias o subcategorías más granulares, dependiendo de las necesidades específicas de su sistema de organización de contenido. Esta flexibilidad lo convierte en una herramienta valiosa para gestionar desde bibliotecas digitales hasta bases de conocimiento empresariales.
Ejemplo:
Examinemos un ejemplo de código que demuestra el agrupamiento y etiquetado usando embeddings de OpenAI y GPT-4o.
Este script:
- Definirá una colección de documentos.
- Generará embeddings para los documentos.
- Agrupará los documentos usando K-Means basándose en sus embeddings.
- Para cada grupo, usará GPT-4o para analizar los documentos dentro de él y generar una etiqueta o descriptor descriptivo.
- Mostrará los documentos agrupados por cluster junto con sus etiquetas generadas por IA.
import os
from openai import OpenAI, OpenAIError
from dotenv import load_dotenv
import numpy as np
from sklearn.cluster import KMeans # For clustering algorithm
import datetime
# --- Configuration ---
load_dotenv()
# Get the current date and location context
current_timestamp = "2024-12-31 15:48:00 CDT"
current_location = "San Antonio, Texas, United States"
print(f"Running Clustering & Tagging example at: {current_timestamp}")
print(f"Location Context: {current_location}")
# Initialize the OpenAI client
try:
api_key = os.getenv("OPENAI_API_KEY")
if not api_key:
raise ValueError("OPENAI_API_KEY not found in environment variables.")
client = OpenAI(api_key=api_key)
print("OpenAI client initialized.")
except ValueError as e:
print(f"Configuration Error: {e}")
exit()
except Exception as e:
print(f"Error initializing OpenAI client: {e}")
exit()
# Define the embedding model
EMBEDDING_MODEL = "text-embedding-3-small"
# --- Helper Function to Generate Embedding ---
# (Same as in previous embeddings examples)
def get_embedding(client, text, model=EMBEDDING_MODEL):
"""Generates an embedding for the given text using the specified model."""
print_text = text[:70] + "..." if len(text) > 70 else text
print(f"Generating embedding for: \"{print_text}\"")
try:
response = client.embeddings.create(
input=text,
model=model
)
embedding_vector = response.data[0].embedding
return embedding_vector
except OpenAIError as e:
print(f"OpenAI API Error generating embedding for text '{print_text}': {e}")
return None
except Exception as e:
print(f"An unexpected error occurred during embedding generation for text '{print_text}': {e}")
return None
# --- Helper Function to Generate Cluster Tag using GPT-4o ---
def generate_cluster_tag(client, documents_in_cluster):
"""Uses GPT-4o to suggest a tag/label for a cluster of documents."""
if not documents_in_cluster:
return "Empty Cluster"
# Combine content for context, limiting total length if necessary
# Using first few hundred chars of each doc might be enough
max_context_length = 3000 # Limit context to avoid excessive token usage
context = ""
for i, doc in enumerate(documents_in_cluster):
doc_preview = f"Document {i+1}: {doc[:300]}...\n"
if len(context) + len(doc_preview) > max_context_length:
break
context += doc_preview
if not context:
return "Error: Could not create context"
system_prompt = "You are an expert at identifying themes and creating concise labels."
user_prompt = f"""Based on the following document excerpts from a single cluster, suggest a short, descriptive tag or label (2-5 words) that captures the main theme or topic of this group.
Document Excerpts:
---
{context.strip()}
---
Suggested Tag/Label:
"""
print(f"\nGenerating tag for cluster with {len(documents_in_cluster)} documents...")
try:
response = client.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_prompt}
],
max_tokens=20, # Short response expected
temperature=0.3 # More deterministic label
)
tag = response.choices[0].message.content.strip().replace('"', '') # Clean up quotes
print(f"Generated tag: '{tag}'")
return tag
except OpenAIError as e:
print(f"OpenAI API Error generating tag: {e}")
return "Tagging Error"
except Exception as e:
print(f"An unexpected error occurred during tag generation: {e}")
return "Tagging Error"
# --- Clustering and Tagging Implementation ---
# 1. Define your collection of documents
# Covers topics: Space Exploration, Cooking/Food, Web Development
documents = [
"NASA launches new probe to study Jupiter's moons.",
"Recipe for authentic Italian pasta carbonara.",
"JavaScript frameworks like React and Vue dominate front-end development.",
"The James Webb Space Telescope captures stunning images of distant galaxies.",
"Tips for baking the perfect sourdough bread at home.",
"Understanding asynchronous programming in Node.js.",
"SpaceX successfully lands its reusable rocket booster after launch.",
"Exploring the different types of olive oil and their uses in cooking.",
"CSS Grid vs Flexbox: Choosing the right layout module.",
"The search for habitable exoplanets continues with new telescope data.",
"How to make delicious homemade pizza from scratch.",
"Building RESTful APIs using Express.js and MongoDB."
]
print(f"\nDocument collection contains {len(documents)} documents.")
# 2. Generate embeddings for all documents
print("\nGenerating embeddings for the document collection...")
embeddings = []
valid_documents = [] # Keep track of documents for which embedding was successful
for doc in documents:
embedding = get_embedding(client, doc)
if embedding:
embeddings.append(embedding)
valid_documents.append(doc) # Add corresponding document text
else:
print(f"Skipping document due to embedding error: \"{doc[:70]}...\"")
if not embeddings:
print("\nError: No embeddings were generated. Cannot perform clustering.")
exit()
print(f"\nSuccessfully generated embeddings for {len(valid_documents)} documents.")
# Convert embeddings list to a NumPy array for scikit-learn
embedding_matrix = np.array(embeddings)
# 3. Apply Clustering Algorithm (K-Means)
# Choose the number of clusters (k). We expect 3 topics here.
n_clusters = 3
print(f"\nApplying K-Means clustering with k={n_clusters}...")
try:
kmeans = KMeans(n_clusters=n_clusters, random_state=42, n_init=10)
kmeans.fit(embedding_matrix)
cluster_labels = kmeans.labels_
print("Clustering complete.")
except Exception as e:
print(f"An error occurred during clustering: {e}")
exit()
# 4. Group Documents by Cluster
print("\nGrouping documents by cluster...")
clustered_documents = {i: [] for i in range(n_clusters)}
for i, label in enumerate(cluster_labels):
clustered_documents[label].append(valid_documents[i])
# 5. Generate Tags for Each Cluster using GPT-4o
print("\nGenerating tags for each cluster...")
cluster_tags = {}
for cluster_id, docs_in_cluster in clustered_documents.items():
tag = generate_cluster_tag(client, docs_in_cluster)
cluster_tags[cluster_id] = tag
# 6. Display Documents by Cluster with Generated Tags
print(f"\n--- Documents Grouped by Cluster and Tag (k={n_clusters}) ---")
for cluster_id, docs_in_cluster in clustered_documents.items():
generated_tag = cluster_tags.get(cluster_id, "Unknown Tag")
print(f"\nCluster {cluster_id + 1} - Suggested Tag: '{generated_tag}'")
print("-" * (28 + len(generated_tag))) # Adjust underline length
if not docs_in_cluster:
print(" (No documents in this cluster)")
else:
for doc_text in docs_in_cluster:
print(f" - {doc_text}") # Print full document text here
print("\nClustering and Tagging process complete.")
Explicación del Desglose del Código
Este script demuestra cómo agrupar automáticamente documentos similares por su significado semántico usando embeddings, y luego utiliza GPT-4o para generar etiquetas descriptivas para cada grupo.
- Configuración y Funciones Auxiliares:
- Incluye importaciones estándar más
KMeans
desklearn.cluster
. - Inicializa el cliente de OpenAI.
- Incluye la función auxiliar
get_embedding
.
- Incluye importaciones estándar más
- Nueva Función Auxiliar:
generate_cluster_tag
:- Propósito: Toma una lista de documentos pertenecientes a un único clúster y utiliza GPT-4o para sugerir una etiqueta concisa que resuma su tema común.
- Entrada: El objeto
client
ydocuments_in_cluster
(una lista de cadenas de texto). - Creación de Contexto: Concatena partes de los documentos (por ejemplo, los primeros 300 caracteres) para crear una cadena de contexto para GPT-4o, respetando una longitud máxima para gestionar el uso de tokens.
- Ingeniería de Prompt: Construye un prompt pidiendo a GPT-4o que actúe como un experto en identificación de temas y sugiera una etiqueta corta (2-5 palabras) basada en los extractos de documentos proporcionados.
- Llamada a la API: Utiliza
client.chat.completions.create
conmodel="gpt-4o"
y el prompt especializado. Se usa una temperatura baja para una generación de etiquetas más enfocada. - Salida: Devuelve la etiqueta sugerida por GPT-4o depurada, o un mensaje de error.
- Colección de Documentos: Una lista llamada
documents
contiene contenido de texto de muestra que abarca varios temas distintos (Espacio, Cocina, Desarrollo Web). - Generación de Embeddings:
- El script itera a través de los
documents
, genera un embedding para cada uno usandoget_embedding
, y almacena los embeddings exitosos y el texto correspondiente enembeddings
yvalid_documents
. - Los embeddings se convierten a un array de NumPy (
embedding_matrix
).
- El script itera a través de los
- Agrupamiento (K-Means):
- El número de clústeres (
n_clusters
) se establece (por ejemplo,k=3
). KMeans
descikit-learn
se inicializa y se ajusta a laembedding_matrix
.kmeans.labels_
proporciona la asignación de clúster para cada documento.
- El número de clústeres (
- Agrupación de Documentos:
- Se crea un diccionario (
clustered_documents
) para almacenar el texto de los documentos pertenecientes a cada ID de clúster.
- Se crea un diccionario (
- Generación de Etiquetas de Clúster:
- El script itera a través del diccionario
clustered_documents
. - Para cada
cluster_id
y su lista dedocs_in_cluster
, llama a la función auxiliargenerate_cluster_tag
. - La etiqueta sugerida para cada clúster se almacena en el diccionario
cluster_tags
.
- El script itera a través del diccionario
- Visualización de Resultados:
- El script itera nuevamente a través de los clústeres.
- Para cada clúster, recupera la etiqueta generada de
cluster_tags
. - Imprime el número del clúster, la etiqueta sugerida, y luego lista el texto completo de todos los documentos pertenecientes a ese clúster.
Este ejemplo muestra un flujo de trabajo potente: usar embeddings para el agrupamiento no supervisado de contenido basado en significado (clustering) y luego aprovechar un LLM como GPT-4o para interpretar esos grupos y asignar etiquetas significativas (etiquetado), automatizando la organización del contenido.
3.2.7 Recomendaciones de Contenido
Los sistemas de recomendación de contenido impulsados por embeddings representan un avance significativo en la tecnología de personalización. Al analizar relaciones semánticas, estos sistemas pueden entender el significado matizado y el contexto del contenido de maneras que los sistemas tradicionales basados en palabras clave no pueden.
Aquí hay una mirada detallada a cómo funcionan las recomendaciones basadas en embeddings:
- Análisis de Contenido:
- El sistema genera vectores de embedding sofisticados para cada pieza de contenido en la base de datos
- Estos vectores capturan características matizadas como estilo de escritura, profundidad del tema y tono emocional
- Los algoritmos avanzados analizan patrones a través de múltiples dimensiones de características de contenido
- Modelado de Preferencias del Usuario:
- El sistema rastrea patrones detallados de interacción incluyendo tiempo dedicado, nivel de participación y comportamiento de compartir
- Las preferencias históricas se ponderan y combinan para crear perfiles de usuario multidimensionales
- Se consideran tanto la retroalimentación explícita (calificaciones, me gusta) como las señales implícitas (profundidad de desplazamiento, visitas repetidas)
- Comprensión Contextual:
- Los factores en tiempo real como el tipo de dispositivo y la ubicación se incorporan al algoritmo de recomendación
- El sistema identifica patrones en el consumo de contenido basados en la hora del día y el día de la semana
- El comportamiento de la sesión actual se analiza para entender los intereses inmediatos del usuario
- Adaptación Dinámica:
- Los modelos de aprendizaje automático refinan continuamente los perfiles de usuario basados en nuevas interacciones
- El sistema aprende tanto de la retroalimentación positiva como negativa para mejorar la precisión
- Las estrategias de recomendación se ajustan automáticamente según las métricas de rendimiento
Este enfoque sofisticado permite que los motores de recomendación entreguen experiencias altamente personalizadas a través de varias capacidades clave:
- Identificar similitudes de contenido que podrían no ser aparentes a través de metadatos tradicionales
- Puede detectar conexiones temáticas entre elementos incluso cuando utilizan terminología diferente
- Reconoce estilos de escritura similares, tono y niveles de complejidad en el contenido
- Entender la progresión de los intereses del usuario a lo largo del tiempo
- Rastrea cómo evolucionan las preferencias desde temas básicos hasta avanzados
- Identifica cambios en los intereses del usuario a través de diferentes categorías
- Hacer recomendaciones entre dominios (por ejemplo, sugerir artículos basados en videos vistos)
- Conecta contenido a través de diferentes tipos de medios basándose en relaciones semánticas
- Aprovecha el aprendizaje de un dominio para mejorar las recomendaciones en otro
- Tener en cuenta tendencias estacionales y relevancia temporal
- Ajusta las recomendaciones basándose en factores sensibles al tiempo como festividades o eventos
- Considera las tendencias actuales y su impacto en los intereses del usuario
El resultado es una experiencia altamente personalizada que puede sugerir videos, artículos o productos verdaderamente relevantes que coincidan con los intereses de los usuarios, tanto actuales como en evolución. Esto va mucho más allá de los simples algoritmos de "a los usuarios que les gustó X también les gustó Y", creando una experiencia de usuario más atractiva y valiosa.
Ejemplo:
Aquí hay un ejemplo de código que demuestra el concepto central de recomendaciones de contenido usando embeddings.
Este script se centra en encontrar elementos de contenido semánticamente similares basados en sus embeddings, que es la base para las características de recomendación más avanzadas que describiste.
import os
from openai import OpenAI, OpenAIError
from dotenv import load_dotenv
import numpy as np # For cosine similarity calculation
import datetime
# --- Configuration ---
load_dotenv()
# Get the current date and location context
current_timestamp = "2024-11-30 15:52:00 CDT"
current_location = "Orlando, Florida, United States"
print(f"Running Content Recommendation example at: {current_timestamp}")
print(f"Location Context: {current_location}")
# Initialize the OpenAI client
try:
api_key = os.getenv("OPENAI_API_KEY")
if not api_key:
raise ValueError("OPENAI_API_KEY not found in environment variables.")
client = OpenAI(api_key=api_key)
print("OpenAI client initialized.")
except ValueError as e:
print(f"Configuration Error: {e}")
exit()
except Exception as e:
print(f"Error initializing OpenAI client: {e}")
exit()
# Define the embedding model
EMBEDDING_MODEL = "text-embedding-3-small"
# --- Helper Function to Generate Embedding ---
# (Same as in previous embeddings examples)
def get_embedding(client, text, model=EMBEDDING_MODEL):
"""Generates an embedding for the given text using the specified model."""
print_text = text[:70] + "..." if len(text) > 70 else text
print(f"Generating embedding for: \"{print_text}\"")
try:
response = client.embeddings.create(
input=text,
model=model
)
embedding_vector = response.data[0].embedding
return embedding_vector
except OpenAIError as e:
print(f"OpenAI API Error generating embedding for text '{print_text}': {e}")
return None
except Exception as e:
print(f"An unexpected error occurred during embedding generation for text '{print_text}': {e}")
return None
# --- Helper Function for Cosine Similarity ---
# (Same as in previous embeddings examples)
def cosine_similarity(vec_a, vec_b):
"""Calculates the cosine similarity between two vectors."""
if vec_a is None or vec_b is None:
return 0.0
vec_a = np.array(vec_a)
vec_b = np.array(vec_b)
norm_a = np.linalg.norm(vec_a)
norm_b = np.linalg.norm(vec_b)
if norm_a == 0 or norm_b == 0:
return 0.0
else:
similarity = np.dot(vec_a, vec_b) / (norm_a * norm_b)
return np.clip(similarity, -1.0, 1.0) # Ensure value is within valid range
# --- Content Recommendation Implementation ---
# 1. Define your Content Catalog (e.g., articles, blog posts)
# In a real application, this would come from a database or CMS.
content_catalog = [
{"id": "art001", "title": "Introduction to Quantum Computing", "content": "Exploring the basics of qubits, superposition, and entanglement in quantum mechanics and their potential for computation."},
{"id": "art002", "title": "Healthy Mediterranean Diet Recipes", "content": "Delicious and easy recipes focusing on fresh vegetables, olive oil, fish, and whole grains for a heart-healthy lifestyle."},
{"id": "art003", "title": "The Future of Artificial Intelligence in Healthcare", "content": "How AI and machine learning are transforming diagnostics, drug discovery, and personalized medicine."},
{"id": "art004", "title": "Beginner's Guide to Python Programming", "content": "Learn the fundamentals of Python syntax, data types, control flow, and functions to start coding."},
{"id": "art005", "title": "Understanding Neural Networks and Deep Learning", "content": "An overview of artificial neural networks, backpropagation, and the concepts behind deep learning models."},
{"id": "art006", "title": "Travel Guide: Hiking the Swiss Alps", "content": "Tips for planning your trip, recommended trails, essential gear, and stunning viewpoints in the Swiss Alps."},
{"id": "art007", "title": "Mastering the Art of French Pastry", "content": "Techniques for creating classic French desserts like croissants, macarons, and éclairs."},
{"id": "art008", "title": "Ethical Considerations in AI Development", "content": "Discussing bias, fairness, transparency, and accountability in the development and deployment of artificial intelligence systems."}
]
print(f"\nContent catalog contains {len(content_catalog)} items.")
# 2. Generate embeddings for all content items (pre-computation)
print("\nGenerating embeddings for the content catalog...")
content_embeddings_data = []
for item in content_catalog:
# Use title and content for embedding
text_to_embed = f"Title: {item['title']}\nContent: {item['content']}"
embedding = get_embedding(client, text_to_embed)
if embedding:
# Store item ID and its embedding
content_embeddings_data.append({"id": item["id"], "embedding": embedding})
else:
print(f"Skipping item {item['id']} due to embedding error.")
if not content_embeddings_data:
print("\nError: No embeddings were generated. Cannot provide recommendations.")
exit()
print(f"\nSuccessfully generated embeddings for {len(content_embeddings_data)} content items.")
# 3. Select a target item (e.g., an article the user just read)
target_item_id = "art003" # User read "The Future of Artificial Intelligence in Healthcare"
print(f"\nFinding content similar to item ID: {target_item_id}")
# Find the embedding for the target item
target_embedding = None
for item_data in content_embeddings_data:
if item_data["id"] == target_item_id:
target_embedding = item_data["embedding"]
break
if target_embedding is None:
print(f"Error: Could not find the embedding for the target item ID '{target_item_id}'.")
exit()
# 4. Calculate similarity between the target item and all other items
recommendations = []
print("\nCalculating similarities...")
for item_data in content_embeddings_data:
# Don't recommend the item itself
if item_data["id"] == target_item_id:
continue
similarity = cosine_similarity(target_embedding, item_data["embedding"])
recommendations.append({"id": item_data["id"], "score": similarity})
# 5. Sort potential recommendations by similarity score
recommendations.sort(key=lambda x: x["score"], reverse=True)
# 6. Display top N recommendations
print("\n--- Top Content Recommendations ---")
# Find the original title for the target item for context
target_item_info = next((item for item in content_catalog if item["id"] == target_item_id), None)
if target_item_info:
print(f"Because you read: \"{target_item_info['title']}\"\n")
if not recommendations:
print("No recommendations found (or error calculating similarities).")
else:
top_n = 3
print(f"Top {top_n} recommended items:")
for i, rec in enumerate(recommendations[:top_n]):
# Find the full item details from the original catalog
rec_details = next((item for item in content_catalog if item["id"] == rec["id"]), None)
if rec_details:
print(f"{i+1}. ID: {rec['id']}, Similarity Score: {rec['score']:.4f}")
print(f" Title: {rec_details['title']}")
print(f" Content Snippet: {rec_details['content'][:100]}...") # Truncate content
print("-" * 10)
else:
print(f"{i+1}. ID: {rec['id']}, Score: {rec['score']:.4f} (Details not found)")
print("-" * 10)
if len(recommendations) > top_n:
print(f"(Showing top {top_n} of {len(recommendations)} potential recommendations)")
print("\nNote: This demonstrates basic content-to-content similarity.")
print("Advanced systems incorporate user profiles, interaction history, context, etc.")
Explicación del Desglose del Código
Este script demuestra un enfoque fundamental para la recomendación de contenido utilizando embeddings de OpenAI, centrándose en encontrar elementos semánticamente similares a un elemento objetivo.
- Configuración y Funciones Auxiliares:
- Incluye importaciones estándar (
openai
,os
,dotenv
,numpy
), inicialización del cliente, y las funciones auxiliaresget_embedding
ycosine_similarity
.
- Incluye importaciones estándar (
- Catálogo de Contenido:
- Una lista de diccionarios (
content_catalog
) simula el contenido disponible (por ejemplo, artículos). Cada elemento tiene unid
,title
ycontent
.
- Una lista de diccionarios (
- Generación de Embeddings de Contenido (Pre-computación):
- El script itera sobre cada
item
en elcontent_catalog
. - Texto Combinado: Crea una cadena de texto combinada del
title
ycontent
del elemento para generar un embedding más rico que capture más detalle semántico. - Llama a
get_embedding
para este texto combinado. - Almacena el
item['id']
y su vectorembedding
encontent_embeddings_data
. Esta pre-computación es vital para la eficiencia.
- El script itera sobre cada
- Selección del Elemento Objetivo:
- Se elige un
target_item_id
(por ejemplo,art003
), simulando un elemento con el que el usuario ha interactuado (por ejemplo, leído). - El script recupera el embedding pre-computado para este elemento objetivo.
- Se elige un
- Cálculo de Similitud:
- Itera a través de todos los otros elementos en
content_embeddings_data
. - Calcula la
cosine_similarity
entre eltarget_embedding
y el embedding de cada otro elemento. - Almacena el
id
del otro elemento y suscore
de similitud en la listarecommendations
.
- Itera a través de todos los otros elementos en
- Clasificación de Recomendaciones:
- La lista
recommendations
se ordena porscore
en orden descendente, colocando primero los elementos de contenido más similares semánticamente.
- La lista
- Visualización de Resultados:
- El script muestra el título del elemento objetivo para dar contexto ("Porque has leído...").
- Muestra los N principales elementos recomendados (por ejemplo, 3), mostrando su ID, puntuación de similitud, título y un fragmento de su contenido.
- Nota Contextual: Las declaraciones finales mencionan explícitamente que este ejemplo muestra una similitud básica de contenido a contenido. Los sistemas de recomendación avanzados, como se describe en el texto de la sección, integrarían perfiles de usuario (embeddings basados en el historial de interacciones), contexto en tiempo real (tiempo, ubicación), retroalimentación explícita y potencialmente algoritmos más complejos más allá de la simple similitud del coseno. Sin embargo, el principio fundamental de usar embeddings para medir la relación semántica sigue siendo fundamental.
Este ejemplo ilustra efectivamente cómo los embeddings permiten recomendaciones basadas en la comprensión del significado del contenido, permitiendo sugerencias que van más allá de la simple coincidencia de palabras clave o categorías.
3.2.8 Clasificación y Priorización de Correos Electrónicos
La tecnología de embeddings permite un análisis y categorización sofisticados de correos electrónicos mediante la comprensión del significado semántico de los mensajes. Este sistema avanzado emplea múltiples capas de análisis para optimizar la gestión del correo electrónico:
- Detección de Urgencia
- Identificar asuntos urgentes que requieren atención inmediata mediante procesamiento del lenguaje natural
- Reconocer patrones de lenguaje urgente y señales contextuales analizando la elección de palabras, estructura de oraciones y patrones históricos
- Marcar correos críticos basándose en la importancia del remitente, palabras clave y jerarquía organizacional
- Categorización Inteligente
- Agrupar hilos de correo y conversaciones relacionadas mediante coincidencia de similitud semántica
- Clasificar mensajes por proyecto, departamento o función empresarial mediante análisis de contenido
- Crear carpetas dinámicas basadas en temas y tendencias emergentes
- Aplicar aprendizaje automático para mejorar la precisión de categorización con el tiempo
- Clasificación de Intención
- Distinguir entre solicitudes, actualizaciones y mensajes informativos mediante comprensión avanzada del lenguaje natural
- Priorizar elementos de acción y delegar tareas automáticamente según contenido y contexto
- Identificar requisitos de seguimiento y establecer recordatorios automáticos
- Extraer plazos y compromisos clave del contenido del mensaje
Al aprovechar la comprensión semántica, el sistema crea un proceso inteligente de procesamiento de correos electrónicos que puede manejar cientos de mensajes simultáneamente. El análisis basado en embeddings examina no solo palabras clave, sino el significado y contexto real de cada mensaje, considerando factores como:
- Contexto del mensaje dentro de conversaciones en curso
- Patrones históricos de comunicación
- Relaciones y jerarquías organizacionales
- Cronogramas y prioridades de proyectos
Este enfoque integral reduce significativamente la carga cognitiva de la gestión del correo electrónico al manejar automáticamente las tareas rutinarias de clasificación y priorización. El sistema asegura que los mensajes importantes reciban atención inmediata mientras mantiene una estructura organizada para todas las comunicaciones. Como resultado, los profesionales pueden concentrarse en actividades de alto valor en lugar de pasar horas clasificando manualmente su bandeja de entrada, lo que lleva a una mejor productividad y tiempos de respuesta más rápidos para comunicaciones críticas.
Ejemplo:
Este script simula la categorización de correos electrónicos entrantes basándose en su similitud semántica con categorías predefinidas como "Solicitud Urgente", "Actualización de Proyecto",
import os
from openai import OpenAI, OpenAIError
from dotenv import load_dotenv
import numpy as np # For cosine similarity calculation
import datetime
# --- Configuration ---
load_dotenv()
# Get the current date and location context
current_timestamp = "2024-10-31 15:54:00 CDT"
current_location = "Plano, Texas, United States"
print(f"Running Email Triage/Prioritization example at: {current_timestamp}")
print(f"Location Context: {current_location}")
# Initialize the OpenAI client
try:
api_key = os.getenv("OPENAI_API_KEY")
if not api_key:
raise ValueError("OPENAI_API_KEY not found in environment variables.")
client = OpenAI(api_key=api_key)
print("OpenAI client initialized.")
except ValueError as e:
print(f"Configuration Error: {e}")
exit()
except Exception as e:
print(f"Error initializing OpenAI client: {e}")
exit()
# Define the embedding model
EMBEDDING_MODEL = "text-embedding-3-small"
# --- Helper Function to Generate Embedding ---
# (Same as in previous embeddings examples)
def get_embedding(client, text, model=EMBEDDING_MODEL):
"""Generates an embedding for the given text using the specified model."""
print_text = text[:70] + "..." if len(text) > 70 else text
print(f"Generating embedding for: \"{print_text}\"")
try:
response = client.embeddings.create(
input=text,
model=model
)
embedding_vector = response.data[0].embedding
return embedding_vector
except OpenAIError as e:
print(f"OpenAI API Error generating embedding for text '{print_text}': {e}")
return None
except Exception as e:
print(f"An unexpected error occurred during embedding generation for text '{print_text}': {e}")
return None
# --- Helper Function for Cosine Similarity ---
# (Same as in previous embeddings examples)
def cosine_similarity(vec_a, vec_b):
"""Calculates the cosine similarity between two vectors."""
if vec_a is None or vec_b is None:
return 0.0
vec_a = np.array(vec_a)
vec_b = np.array(vec_b)
norm_a = np.linalg.norm(vec_a)
norm_b = np.linalg.norm(vec_b)
if norm_a == 0 or norm_b == 0:
return 0.0
else:
similarity = np.dot(vec_a, vec_b) / (norm_a * norm_b)
return np.clip(similarity, -1.0, 1.0) # Ensure value is within valid range
# --- Email Triage/Prioritization Implementation ---
# 1. Define Sample Emails (Subject + Snippet)
emails = [
{"id": "email01", "subject": "Urgent: Server Down!", "body_snippet": "The main production server seems to be unresponsive. We need immediate assistance to investigate and bring it back online."},
{"id": "email02", "subject": "Meeting Minutes - Project Phoenix Sync", "body_snippet": "Attached are the minutes from today's sync call. Key decisions included finalizing the Q3 roadmap. Action items assigned."},
{"id": "email03", "subject": "Quick Question about Report", "body_snippet": "Hi team, just had a quick question regarding the methodology used in the latest market analysis report. Can someone clarify?"},
{"id": "email04", "subject": "Fwd: Company Newsletter - April Edition", "body_snippet": "Sharing the latest company newsletter for your information."},
{"id": "email05", "subject": "Action Required: Submit Timesheet by EOD", "body_snippet": "Friendly reminder to please submit your weekly timesheet by the end of the day today. This is mandatory."},
{"id": "email06", "subject": "Update on Q2 Marketing Campaign", "body_snippet": "Just wanted to provide a brief update on the campaign performance metrics we discussed last week. See attached summary."},
{"id": "email07", "subject": "Can you approve this request ASAP?", "body_snippet": "Need your approval on the attached budget request urgently to proceed with the vendor contract."}
]
print(f"\nProcessing {len(emails)} emails.")
# 2. Define Categories/Priorities and their Semantic Representations
# We represent each category with a descriptive phrase.
categories = {
"Urgent Action Required": "Requires immediate attention, critical issue, deadline, ASAP request, mandatory task.",
"Project Update / Status": "Information about ongoing projects, progress reports, meeting minutes, status updates.",
"Question / Request for Info": "Asking for clarification, seeking information, query about details.",
"General Info / FYI": "Newsletter, announcement, sharing information, non-actionable update."
}
print(f"\nDefined categories: {list(categories.keys())}")
# 3. Generate embeddings for Categories (pre-computation recommended)
print("\nGenerating embeddings for categories...")
category_embeddings = {}
for category_name, category_description in categories.items():
embedding = get_embedding(client, category_description)
if embedding:
category_embeddings[category_name] = embedding
else:
print(f"Skipping category '{category_name}' due to embedding error.")
if not category_embeddings:
print("\nError: No embeddings generated for categories. Cannot triage emails.")
exit()
# 4. Process Each Email: Generate Embedding and Find Best Category
print("\nTriaging emails...")
email_results = []
for email in emails:
# Combine subject and body for better context
email_content = f"Subject: {email['subject']}\nBody: {email['body_snippet']}"
email_embedding = get_embedding(client, email_content)
if not email_embedding:
print(f"Skipping email {email['id']} due to embedding error.")
continue
# Find the category with the highest similarity
best_category = None
max_similarity = -1 # Cosine similarity ranges from -1 to 1
for category_name, category_embedding in category_embeddings.items():
similarity = cosine_similarity(email_embedding, category_embedding)
print(f" Email {email['id']} vs Category '{category_name}': Score {similarity:.4f}")
if similarity > max_similarity:
max_similarity = similarity
best_category = category_name
email_results.append({
"id": email["id"],
"subject": email["subject"],
"assigned_category": best_category,
"score": max_similarity
})
print(f"-> Email {email['id']} assigned to: '{best_category}' (Score: {max_similarity:.4f})")
# 5. Display Triage Results
print("\n--- Email Triage Results ---")
if not email_results:
print("No emails were successfully triaged.")
else:
# Optional: Group by category for display
results_by_category = {cat: [] for cat in categories.keys()}
for result in email_results:
if result["assigned_category"]: # Check if category was assigned
results_by_category[result["assigned_category"]].append(result)
for category_name, items in results_by_category.items():
print(f"\nCategory: {category_name}")
print("-" * (10 + len(category_name)))
if not items:
print(" (No emails assigned)")
else:
# Sort items within category by score if desired
items.sort(key=lambda x: x['score'], reverse=True)
for item in items:
print(f" - ID: {item['id']}, Subject: \"{item['subject']}\" (Score: {item['score']:.3f})")
print("\nEmail triage process complete.")
Explicación del Desglose del Código
Este ejemplo muestra cómo los embeddings de OpenAI pueden clasificar y priorizar automáticamente los correos electrónicos mediante la comprensión de su significado, demostrando un sistema inteligente de gestión de correos.
- Configuración y Funciones Auxiliares:
- Incluye importaciones estándar (
openai
,os
,dotenv
,numpy
), inicialización del cliente, y las funciones auxiliaresget_embedding
ycosine_similarity
.
- Incluye importaciones estándar (
- Datos de Ejemplo de Correos:
- Una lista de diccionarios (
emails
) simula mensajes entrantes. Cada correo tiene unid
,subject
, y unbody_snippet
.
- Una lista de diccionarios (
- Definiciones de Categorías:
- Un diccionario (
categories
) define las categorías objetivo para la clasificación (por ejemplo, "Acción Urgente Requerida", "Actualización de Proyecto / Estado"). - Idea Clave: Cada categoría está representada por una frase descriptiva o lista de palabras clave que captura su esencia semántica. Esta descripción es lo que será convertido en embedding.
- Un diccionario (
- Generación de Embeddings de Categorías:
- El script itera a través de las
categories
definidas. - Llama a
get_embedding
sobre la descripción asociada con cada nombre de categoría. - El vector de embedding resultante para cada categoría se almacena en el diccionario
category_embeddings
. Este paso típicamente sería pre-calculado y almacenado.
- El script itera a través de las
- Bucle de Procesamiento de Correos:
- El script itera a través de cada
email
en los datos de ejemplo. - Combinación de Contenido: Combina el
subject
ybody_snippet
en una única cadenaemail_content
para proporcionar un contexto más rico para el embedding. - Embedding del Correo: Llama a
get_embedding
para obtener la representación vectorial del contenido del correo actual. - Cálculo de Similitud:
- Luego itera a través de los
category_embeddings
pre-calculados. - Para cada categoría, calcula la
cosine_similarity
entre elemail_embedding
y elcategory_embedding
. - Mantiene un registro de la
best_category
(la que tiene el puntaje de similitud más alto encontrado hasta ahora) y el correspondiente puntajemax_similarity
.
- Luego itera a través de los
- Asignación: Después de comparar el correo con todas las categorías, se le asigna la
best_category
encontrada. El resultado (ID del correo, asunto, categoría asignada, puntaje) se almacena.
- El script itera a través de cada
- Visualización de Resultados de Clasificación:
- El script imprime las asignaciones finales.
- Agrupación Opcional: Incluye lógica para agrupar los resultados por categoría asignada para una presentación más clara, mostrando qué correos cayeron en los grupos "Urgente", "Actualización", etc.
Este ejemplo demuestra efectivamente cómo los embeddings permiten una categorización inteligente basada en el significado. Un correo solicitando "aprobación ASAP" puede ser correctamente identificado como "Acción Urgente Requerida" incluso sin usar la palabra exacta "urgente", porque su embedding será semánticamente cercano al embedding de la descripción de la categoría "Acción Urgente Requerida". Esto es mucho más robusto que el simple filtrado por palabras clave.
3.2 Cuándo Usar Embeddings
Los embeddings han revolucionado la forma en que procesamos y entendemos la información textual en las aplicaciones modernas de IA. Mientras que los métodos tradicionales de procesamiento de texto dependen de coincidencias exactas o búsquedas básicas por palabras clave, los embeddings proporcionan una forma sofisticada de capturar los significados matizados y las relaciones entre fragmentos de texto. Al convertir palabras y frases en vectores numéricos de alta dimensión, los embeddings permiten que las máquinas entiendan las relaciones semánticas y similitudes de manera que se asemejan más a la comprensión humana.
Exploremos los escenarios clave donde los embeddings resultan particularmente valiosos, mostrando cómo esta tecnología transforma varios aspectos del procesamiento y recuperación de información. Entender estos casos de uso es crucial para desarrolladores y organizaciones que buscan aprovechar todo el potencial de la tecnología de embeddings en sus aplicaciones.
3.2.1 Búsqueda semántica
Encontrar información relevante basada en el significado en lugar de solo palabras clave, permitiendo resultados de búsqueda más inteligentes. A diferencia de la búsqueda tradicional basada en palabras clave que coincide con palabras o frases exactas, la búsqueda semántica comprende la intención y el significado contextual de una consulta analizando las relaciones subyacentes entre palabras y conceptos. Este enfoque avanzado permite que el sistema comprenda variaciones en el lenguaje, contexto e incluso la intención del usuario.
Por ejemplo, una búsqueda de "procesamiento del lenguaje natural" también devolvería resultados relevantes sobre "PLN," "lingüística computacional" o "análisis de texto." Cuando un usuario busca "tratamiento de síntomas del resfriado común," el sistema entendería y devolvería resultados sobre "remedios para la gripe," "reducción de la fiebre" y "medicamentos para la tos" - incluso si estas frases exactas no se utilizan. Esta tecnología aprovecha los vectores de embedding para calcular puntajes de similitud entre consultas y documentos, transformando cada fragmento de texto en una representación numérica de alta dimensión que captura su significado semántico. Este enfoque matemático permite resultados de búsqueda más matizados y precisos que tienen en cuenta:
- Sinónimos y términos relacionados (como "coche" y "automóvil")
- Relaciones conceptuales (conectando "python" tanto con programación como con serpientes, dependiendo del contexto)
- Múltiples idiomas (encontrando contenido relevante incluso cuando está escrito en diferentes idiomas)
- Variaciones contextuales (entendiendo que "apple" puede referirse tanto a la fruta como a la empresa tecnológica)
- Coincidencia de intención (reconociendo que "cómo arreglar una llanta pinchada" e "instrucciones de reparación de neumáticos" buscan la misma información)
Ejemplo:
Aquí hay un ejemplo de código que demuestra la búsqueda semántica usando embeddings de OpenAI, basado en el contenido que proporcionaste.
Este script:
- Definirá un pequeño conjunto de documentos.
- Generará embeddings para estos documentos y una consulta de búsqueda.
- Calculará la similitud entre la consulta y cada documento.
- Clasificará los documentos por relevancia basándose en la similitud semántica.
import os
from openai import OpenAI, OpenAIError
from dotenv import load_dotenv
import numpy as np # For cosine similarity calculation
import datetime
# --- Configuration ---
load_dotenv()
# Get the current date and location context
current_timestamp = "2025-03-22 15:22:00 CDT"
current_location = "Grapevine, Texas, United States"
print(f"Running Semantic Search example at: {current_timestamp}")
print(f"Location Context: {current_location}")
# Initialize the OpenAI client
try:
api_key = os.getenv("OPENAI_API_KEY")
if not api_key:
raise ValueError("OPENAI_API_KEY not found in environment variables.")
client = OpenAI(api_key=api_key)
print("OpenAI client initialized.")
except ValueError as e:
print(f"Configuration Error: {e}")
exit()
except Exception as e:
print(f"Error initializing OpenAI client: {e}")
exit()
# Define the embedding model
EMBEDDING_MODEL = "text-embedding-3-small"
# --- Helper Function to Generate Embedding ---
# (Same as in previous embeddings example)
def get_embedding(client, text, model=EMBEDDING_MODEL):
"""Generates an embedding for the given text using the specified model."""
print(f"Generating embedding for: \"{text[:50]}...\"") # Print truncated text
try:
response = client.embeddings.create(
input=text,
model=model
)
embedding_vector = response.data[0].embedding
print("Embedding generation successful.")
return embedding_vector
except OpenAIError as e:
print(f"OpenAI API Error generating embedding for text '{text[:50]}...': {e}")
return None
except Exception as e:
print(f"An unexpected error occurred during embedding generation for text '{text[:50]}...': {e}")
return None
# --- Helper Function for Cosine Similarity ---
# (Same as in previous embeddings example)
def cosine_similarity(vec_a, vec_b):
"""Calculates the cosine similarity between two vectors."""
if vec_a is None or vec_b is None:
# print("Error: Cannot calculate similarity with None vectors.")
return 0.0 # Return 0 if any vector is missing
vec_a = np.array(vec_a)
vec_b = np.array(vec_b)
norm_a = np.linalg.norm(vec_a)
norm_b = np.linalg.norm(vec_b)
if norm_a == 0 or norm_b == 0:
# print("Warning: One or both vectors have zero magnitude.")
return 0.0
else:
similarity = np.dot(vec_a, vec_b) / (norm_a * norm_b)
return similarity
# --- Semantic Search Implementation ---
# 1. Define your document store (a list of text strings)
# In a real application, this could come from a database, files, etc.
document_store = [
"The Eiffel Tower is a wrought-iron lattice tower on the Champ de Mars in Paris, France.",
"Photosynthesis is a process used by plants and other organisms to convert light energy into chemical energy.",
"Artificial intelligence research focuses on creating systems capable of performing tasks that typically require human intelligence.",
"A recipe for classic French onion soup involves caramelizing onions and topping with bread and cheese.",
"Machine learning, a subset of AI, involves algorithms that allow systems to learn from data.",
"The Louvre Museum in Paris is the world's largest art museum and a historic monument.",
"Natural Language Processing (NLP) enables computers to understand and process human language.",
"Baking bread requires careful measurement of ingredients like flour, water, yeast, and salt."
]
print(f"\nDocument store contains {len(document_store)} documents.")
# 2. Generate embeddings for all documents in the store (pre-computation)
# In a real app, you'd store these embeddings alongside the documents.
print("\nGenerating embeddings for the document store...")
document_embeddings = []
for doc in document_store:
embedding = get_embedding(client, doc)
# Store the document text and its embedding together
if embedding: # Only store if embedding was successful
document_embeddings.append({"text": doc, "embedding": embedding})
else:
print(f"Skipping document due to embedding error: \"{doc[:50]}...\"")
print(f"\nSuccessfully generated embeddings for {len(document_embeddings)} documents.")
# 3. Define the user's search query
search_query = "What is AI?"
# search_query = "Things to see in Paris"
# search_query = "How does NLP work?"
# search_query = "Cooking instructions"
print(f"\nSearch Query: \"{search_query}\"")
# 4. Generate embedding for the search query
print("\nGenerating embedding for the search query...")
query_embedding = get_embedding(client, search_query)
# 5. Calculate similarity and rank documents
search_results = []
if query_embedding and document_embeddings:
print("\nCalculating similarities...")
for doc_data in document_embeddings:
similarity = cosine_similarity(query_embedding, doc_data["embedding"])
search_results.append({"text": doc_data["text"], "score": similarity})
# Sort results by similarity score in descending order
search_results.sort(key=lambda x: x["score"], reverse=True)
# 6. Display results
print("\n--- Semantic Search Results ---")
print(f"Top results for query: \"{search_query}\"\n")
if not search_results:
print("No results found (or error calculating similarities).")
else:
# Display top N results (e.g., top 3)
top_n = 3
for i, result in enumerate(search_results[:top_n]):
print(f"{i+1}. Score: {result['score']:.4f}")
print(f" Text: {result['text']}")
print("-" * 10)
if len(search_results) > top_n:
print(f"(Showing top {top_n} of {len(search_results)} results)")
else:
print("\nCould not perform search.")
if not query_embedding:
print("Reason: Failed to generate embedding for the search query.")
if not document_embeddings:
print("Reason: No document embeddings were successfully generated.")
Explicación del Desglose del Código:
- Configuración y Funciones Auxiliares: Incluye importaciones estándar (
openai
,os
,dotenv
,numpy
), inicialización del cliente, y las funciones auxiliaresget_embedding
ycosine_similarity
del ejemplo anterior. - Almacén de Documentos: Una lista simple de Python (
document_store
) contiene el texto de los documentos que queremos buscar. En una aplicación real, estos datos probablemente provendrían de una base de datos o sistema de archivos. - Generación de Embeddings de Documentos:
- El script itera a través de cada documento en el
document_store
. - Llama a
get_embedding
para cada documento para obtener su representación numérica. - Almacena el texto original del documento y su vector de embedding correspondiente juntos (por ejemplo, en una lista de diccionarios). Este paso de pre-computación es crucial para la eficiencia en sistemas reales – generas los embeddings de documentos una vez y los almacenas. El manejo de errores asegura que los documentos se omitan si falla la generación del embedding.
- El script itera a través de cada documento en el
- Consulta de Búsqueda: Se define una cadena de ejemplo
search_query
. - Generación del Embedding de Consulta: La función
get_embedding
se llama nuevamente, esta vez para elsearch_query
. - Cálculo de Similitud y Clasificación:
- Verifica si tanto el embedding de consulta como los embeddings de documentos se generaron exitosamente.
- Itera a través de los
document_embeddings
almacenados. - Para cada documento, calcula la
cosine_similarity
entre elquery_embedding
y el embedding del documento. - El texto del documento y su puntaje de similitud calculado se almacenan en una lista
search_results
. - Finalmente,
search_results.sort(...)
ordena la lista basándose en elscore
en orden descendente (mayor similitud primero).
- Mostrar Resultados: El script imprime los N (por ejemplo, 3) documentos más relevantes de la lista ordenada, mostrando su puntaje de similitud y contenido de texto.
Este ejemplo ilustra claramente el concepto central de la búsqueda semántica: convertir tanto los documentos como las consultas en embeddings y luego usar la similitud vectorial (como la similitud del coseno) para encontrar documentos que están semánticamente relacionados con la consulta, incluso si no comparten las palabras clave exactas.
3.2.2 Agrupamiento por temas
El agrupamiento por temas es una técnica sofisticada para organizar y analizar grandes colecciones de documentos mediante su agrupación automática basada en su contenido semántico. Esta aplicación avanzada de embeddings transforma la manera en que procesamos y entendemos colecciones de documentos a gran escala, ofreciendo una poderosa solución para la organización de contenido. El sistema funciona convirtiendo cada documento en un vector de embedding multidimensional que captura su significado, y luego utiliza algoritmos de agrupamiento para juntar vectores similares.
Esta poderosa aplicación de embeddings permite a los sistemas:
- Identificar patrones temáticos a través de miles de documentos sin etiquetado manual - el sistema puede detectar automáticamente temas y tendencias comunes a través de vastas colecciones de documentos, ahorrando incontables horas de trabajo de categorización manual
- Agrupar discusiones, artículos o piezas de contenido similares en categorías intuitivas - al comprender las relaciones semánticas entre documentos, el sistema puede crear agrupaciones significativas que reflejan divisiones naturales de temas, incluso cuando los documentos utilizan terminología diferente para discutir los mismos conceptos
- Descubrir temas y tendencias emergentes dentro de grandes colecciones de documentos - a medida que se agrega nuevo contenido, el sistema puede identificar nuevos grupos temáticos que se están formando, ayudando a las organizaciones a mantenerse al día con las tendencias en desarrollo en su campo
- Crear jerarquías de contenido dinámicas que se adaptan cuando se agregan nuevos documentos - a diferencia de los sistemas de categorización estática tradicionales, el agrupamiento basado en embeddings puede reorganizar y refinar automáticamente las estructuras de categorías a medida que la colección de contenido crece y evoluciona
Por ejemplo, una organización de noticias podría usar el agrupamiento por temas para agrupar automáticamente miles de artículos en categorías como "Tecnología", "Política" o "Deportes", incluso cuando estos temas no están etiquetados explícitamente. Los embeddings capturan las relaciones semánticas entre artículos analizando el significado real y el contexto del contenido, no solo palabras clave. Esto permite un agrupamiento mucho más sofisticado que puede entender distinciones sutiles - por ejemplo, reconociendo que un artículo sobre el impacto económico de los estadios deportivos pertenece tanto a las categorías "Deportes" como "Negocios", o que artículos sobre diferentes lenguajes de programación pertenecen todos a un grupo de "Tecnología" a pesar de usar terminología completamente diferente.
Ejemplo:
A continuación se muestra un ejemplo de código que demuestra el agrupamiento por temas usando embeddings de OpenAI y el algoritmo K-means de scikit-learn
.
Este código:
- Definirá una lista de documentos de ejemplo que cubren diferentes temas implícitos.
- Generará embeddings para cada documento usando la API de OpenAI.
- Aplicará el algoritmo de agrupamiento K-Means para agrupar los vectores de embedding.
- Mostrará los documentos pertenecientes a cada grupo identificado.
import os
from openai import OpenAI, OpenAIError
from dotenv import load_dotenv
import numpy as np
from sklearn.cluster import KMeans # For clustering algorithm
import datetime
# --- Configuration ---
load_dotenv()
# Get the current date and location context
current_timestamp = "2025-03-23 15:26:00 CDT"
current_location = "Dallas, Texas, United States"
print(f"Running Topic Clustering example at: {current_timestamp}")
print(f"Location Context: {current_location}")
# Initialize the OpenAI client
try:
api_key = os.getenv("OPENAI_API_KEY")
if not api_key:
raise ValueError("OPENAI_API_KEY not found in environment variables.")
client = OpenAI(api_key=api_key)
print("OpenAI client initialized.")
except ValueError as e:
print(f"Configuration Error: {e}")
exit()
except Exception as e:
print(f"Error initializing OpenAI client: {e}")
exit()
# Define the embedding model
EMBEDDING_MODEL = "text-embedding-3-small"
# --- Helper Function to Generate Embedding ---
# (Same as in previous embeddings examples)
def get_embedding(client, text, model=EMBEDDING_MODEL):
"""Generates an embedding for the given text using the specified model."""
# Truncate text for printing if it's too long
print_text = text[:70] + "..." if len(text) > 70 else text
print(f"Generating embedding for: \"{print_text}\"")
try:
response = client.embeddings.create(
input=text,
model=model
)
embedding_vector = response.data[0].embedding
# print("Embedding generation successful.") # Reduce verbosity
return embedding_vector
except OpenAIError as e:
print(f"OpenAI API Error generating embedding for text '{print_text}': {e}")
return None
except Exception as e:
print(f"An unexpected error occurred during embedding generation for text '{print_text}': {e}")
return None
# --- Topic Clustering Implementation ---
# 1. Define your collection of documents
# These documents cover roughly 3 topics: AI/Tech, Travel/Geography, Food/Cooking
documents = [
"Artificial intelligence research focuses on creating systems capable of performing tasks that typically require human intelligence.",
"The Eiffel Tower is a wrought-iron lattice tower on the Champ de Mars in Paris, France.",
"A recipe for classic French onion soup involves caramelizing onions and topping with bread and cheese.",
"Machine learning, a subset of AI, involves algorithms that allow systems to learn from data.",
"The Great Wall of China is a series of fortifications made of stone, brick, tamped earth, wood, and other materials.",
"Natural Language Processing (NLP) enables computers to understand and process human language.",
"Baking bread requires careful measurement of ingredients like flour, water, yeast, and salt.",
"The Colosseum in Rome, Italy, is an oval amphitheatre in the centre of the city.",
"Deep learning utilizes artificial neural networks with multiple layers to model complex patterns.",
"Sushi is a traditional Japanese dish of prepared vinegared rice, usually with some sugar and salt, accompanying a variety of ingredients, such as seafood, often raw, and vegetables."
]
print(f"\nDocument collection contains {len(documents)} documents.")
# 2. Generate embeddings for all documents
print("\nGenerating embeddings for the document collection...")
embeddings = []
valid_documents = [] # Keep track of documents for which embedding was successful
for doc in documents:
embedding = get_embedding(client, doc)
if embedding:
embeddings.append(embedding)
valid_documents.append(doc) # Add corresponding document text
else:
print(f"Skipping document due to embedding error: \"{doc[:70]}...\"")
if not embeddings:
print("\nError: No embeddings were generated. Cannot perform clustering.")
exit()
print(f"\nSuccessfully generated embeddings for {len(valid_documents)} documents.")
# Convert embeddings list to a NumPy array for scikit-learn
embedding_matrix = np.array(embeddings)
# 3. Apply Clustering Algorithm (K-Means)
# We need to choose the number of clusters (k). Let's assume we expect 3 topics.
# In real applications, determining the optimal 'k' often requires experimentation
# (e.g., using the elbow method or silhouette scores).
n_clusters = 3
print(f"\nApplying K-Means clustering with k={n_clusters}...")
try:
kmeans = KMeans(n_clusters=n_clusters, random_state=42, n_init=10) # n_init suppresses warning
kmeans.fit(embedding_matrix)
cluster_labels = kmeans.labels_
print("Clustering complete.")
except Exception as e:
print(f"An error occurred during clustering: {e}")
exit()
# 4. Display Documents by Cluster
print(f"\n--- Documents Grouped by Topic Cluster (k={n_clusters}) ---")
# Create a dictionary to hold documents for each cluster
clustered_documents = {i: [] for i in range(n_clusters)}
# Assign each document (that had a valid embedding) to its cluster
for i, label in enumerate(cluster_labels):
clustered_documents[label].append(valid_documents[i])
# Print the contents of each cluster
for cluster_id, docs_in_cluster in clustered_documents.items():
print(f"\nCluster {cluster_id + 1}:")
if not docs_in_cluster:
print(" (No documents in this cluster)")
else:
for doc_text in docs_in_cluster:
# Print truncated document text for readability
print_text = doc_text[:100] + "..." if len(doc_text) > 100 else doc_text
print(f" - {print_text}")
print("-" * 20)
print("\nNote: The quality of clustering depends on the data, the embedding model,")
print("and the chosen number of clusters (k). Cluster numbers are arbitrary.")
Explicación del Desglose del Código:
- Configuración y Funciones Auxiliares:
- Incluye importaciones estándar más
KMeans
desklearn.cluster
. - Inicializa el cliente de OpenAI.
- Incluye la función auxiliar
get_embedding
(igual que antes).
- Incluye importaciones estándar más
- Colección de Documentos: Una lista llamada
documents
contiene el contenido de texto. Los documentos de muestra están elegidos para representar algunos temas subyacentes distintos (IA/Tecnología, Viajes/Geografía, Comida/Cocina). - Generación de Embeddings:
- El script itera a través de los
documents
. - Llama a
get_embedding
para cada documento. - Almacena los embeddings exitosos en la lista
embeddings
y el texto del documento correspondiente envalid_documents
. Esto asegura que los índices coincidan posteriormente. - El manejo de errores omite documentos si falla la generación del embedding.
- La lista de vectores de embedding se convierte en un array de NumPy (
embedding_matrix
), que es el formato de entrada estándar para los algoritmos descikit-learn
.
- El script itera a través de los
- Agrupamiento (K-Means):
- Elección de
k
: El número de grupos (n_clusters
) se establece (aquí,k=3
, asumiendo que esperamos tres temas basados en los datos de muestra). Un comentario destaca que encontrar elk
óptimo es frecuentemente una tarea separada en escenarios del mundo real. - Inicialización: Se crea un objeto
KMeans
.n_clusters
especifica el número deseado de grupos.random_state
asegura la reproducibilidad.n_init=10
ejecuta el algoritmo múltiples veces con diferentes centroides iniciales y elige el mejor resultado (suprime una advertencia futura). - Ajuste:
kmeans.fit(embedding_matrix)
ejecuta el algoritmo de agrupamiento K-Means en los embeddings de documentos. Encuentra los centros de los grupos y asigna cada vector de embedding al centro más cercano. - Etiquetas:
kmeans.labels_
contiene un array donde cada elemento indica el ID del grupo (0, 1, 2, etc.) asignado al embedding del documento correspondiente.
- Elección de
- Mostrar Resultados:
- Se crea un diccionario (
clustered_documents
) para organizar los resultados, con claves que representan los IDs de los grupos. - El script itera a través de las
cluster_labels
asignadas por K-Means. Para cada índicei
de documento, encuentra sulabel
asignada y añade el texto correspondiente devalid_documents[i]
a la lista para ese ID de grupo en el diccionario. - Finalmente, recorre el diccionario
clustered_documents
e imprime el texto de los documentos pertenecientes a cada grupo, agrupándolos claramente por el grupo temático identificado por el algoritmo.
- Se crea un diccionario (
Este ejemplo demuestra el poder de los embeddings para el descubrimiento de temas no supervisado. Al convertir texto en vectores, podemos usar algoritmos matemáticos como K-Means para agrupar documentos semánticamente similares sin necesidad de etiquetas predefinidas.
3.2.3 Sistemas de Recomendación
Sugerir elementos relacionados mediante la comprensión de las conexiones más profundas entre diferentes piezas de contenido. Esta poderosa aplicación de los embeddings permite a los sistemas proporcionar recomendaciones personalizadas analizando las relaciones semánticas entre elementos. Los vectores de embedding capturan patrones sutiles y similitudes que podrían no ser inmediatamente obvios para los observadores humanos.
Así es como los sistemas de recomendación aprovechan los embeddings:
- Filtrado Basado en Contenido
- Los sistemas analizan las características reales del contenido (como descripciones de texto, características o atributos)
- Cada elemento se convierte en un vector de embedding que representa sus características principales
- Los elementos similares se encuentran midiendo la distancia entre estos vectores
- Mejora del Filtrado Colaborativo
- Los comportamientos y preferencias de los usuarios también se convierten en embeddings
- El sistema puede identificar patrones en las interacciones usuario-elemento
- Esto ayuda a predecir qué elementos podría gustarle a un usuario basándose en las preferencias de usuarios similares
Por ejemplo, un servicio de streaming de video puede recomendar programas no solo basándose en etiquetas de género, sino entendiendo elementos temáticos, estilos narrativos y patrones narrativos complejos. Los vectores de embedding pueden capturar características matizadas como:
- Ritmo y complejidad de la trama
- Estilos de desarrollo de personajes
- Tono emocional y atmósfera
- Técnicas visuales y de dirección
De manera similar, las plataformas de comercio electrónico pueden sugerir productos entendiendo las similitudes contextuales en las descripciones de productos, el comportamiento del usuario y las características de los artículos. Esto incluye analizar:
- Descripciones y características de productos
- Patrones de navegación y compra de usuarios
- Niveles de precio y calidad
- Relaciones entre marcas y posicionamiento en el mercado
Esta comprensión semántica lleva a recomendaciones más precisas y relevantes en comparación con los métodos tradicionales que dependen únicamente de categorías explícitas o calificaciones de usuarios. El sistema puede identificar conexiones sutiles y patrones que podrían pasarse por alto con enfoques convencionales de recomendación, resultando en experiencias de usuario más atractivas y personalizadas.
Ejemplo:
El siguiente ejemplo de código demuestra cómo los embeddings de OpenAI pueden utilizarse para construir un sistema de recomendación simple basado en contenido.
Este script:
- Definirá un pequeño catálogo de elementos (por ejemplo, descripciones de películas).
- Generará embeddings para estos elementos.
- Elegirá un elemento objetivo.
- Encontrará otros elementos en el catálogo que sean semánticamente similares al elemento objetivo basándose en sus embeddings.
- Presentará los elementos más similares como recomendaciones.
import os
from openai import OpenAI, OpenAIError
from dotenv import load_dotenv
import numpy as np # For cosine similarity calculation
import datetime
# --- Configuration ---
load_dotenv()
# Get the current date and location context
current_timestamp = "2025-03-24 15:29:00 CDT"
current_location = "Austin, Texas, United States"
print(f"Running Recommendation System example at: {current_timestamp}")
print(f"Location Context: {current_location}")
# Initialize the OpenAI client
try:
api_key = os.getenv("OPENAI_API_KEY")
if not api_key:
raise ValueError("OPENAI_API_KEY not found in environment variables.")
client = OpenAI(api_key=api_key)
print("OpenAI client initialized.")
except ValueError as e:
print(f"Configuration Error: {e}")
exit()
except Exception as e:
print(f"Error initializing OpenAI client: {e}")
exit()
# Define the embedding model
EMBEDDING_MODEL = "text-embedding-3-small"
# --- Helper Function to Generate Embedding ---
# (Same as in previous embeddings examples)
def get_embedding(client, text, model=EMBEDDING_MODEL):
"""Generates an embedding for the given text using the specified model."""
# Truncate text for printing if it's too long
print_text = text[:70] + "..." if len(text) > 70 else text
print(f"Generating embedding for: \"{print_text}\"")
try:
response = client.embeddings.create(
input=text,
model=model
)
embedding_vector = response.data[0].embedding
# print("Embedding generation successful.") # Reduce verbosity
return embedding_vector
except OpenAIError as e:
print(f"OpenAI API Error generating embedding for text '{print_text}': {e}")
return None
except Exception as e:
print(f"An unexpected error occurred during embedding generation for text '{print_text}': {e}")
return None
# --- Helper Function for Cosine Similarity ---
# (Same as in previous embeddings examples)
def cosine_similarity(vec_a, vec_b):
"""Calculates the cosine similarity between two vectors."""
if vec_a is None or vec_b is None:
return 0.0 # Return 0 if any vector is missing
vec_a = np.array(vec_a)
vec_b = np.array(vec_b)
norm_a = np.linalg.norm(vec_a)
norm_b = np.linalg.norm(vec_b)
if norm_a == 0 or norm_b == 0:
return 0.0
else:
similarity = np.dot(vec_a, vec_b) / (norm_a * norm_b)
return similarity
# --- Recommendation System Implementation ---
# 1. Define your item catalog (e.g., movie descriptions)
# In a real application, this would come from a database.
item_catalog = [
{"id": "mov001", "title": "Space Odyssey: The Final Frontier", "description": "A visually stunning sci-fi epic exploring humanity's place in the universe, featuring complex themes and groundbreaking special effects."},
{"id": "mov002", "title": "Galactic Wars: Attack of the Clones", "description": "An action-packed space opera with laser battles, alien creatures, and a classic good versus evil storyline."},
{"id": "com001", "title": "Laugh Riot", "description": "A slapstick comedy about mistaken identities and hilarious mishaps during a weekend getaway."},
{"id": "doc001", "title": "Wonders of the Deep", "description": "An awe-inspiring documentary showcasing the beauty and mystery of marine life in the world's oceans."},
{"id": "mov003", "title": "Cyber City 2077", "description": "A gritty cyberpunk thriller set in a dystopian future, exploring themes of technology, consciousness, and rebellion."},
{"id": "com002", "title": "The Office Party", "description": "A witty ensemble comedy centered around awkward interactions and office politics during an annual holiday celebration."},
{"id": "doc002", "title": "Cosmic Journeys", "description": "A documentary exploring the vastness of space, black holes, distant galaxies, and the search for extraterrestrial life."},
{"id": "mov004", "title": "Interstellar Echoes", "description": "A philosophical science fiction film about astronauts travelling through a wormhole in search of a new home for humanity."}
]
print(f"\nItem catalog contains {len(item_catalog)} items.")
# 2. Generate embeddings for all items in the catalog (pre-computation)
print("\nGenerating embeddings for the item catalog...")
item_embeddings_data = []
for item in item_catalog:
# Combine title and description for a richer embedding
text_to_embed = f"{item['title']}: {item['description']}"
embedding = get_embedding(client, text_to_embed)
if embedding:
# Store item ID and its embedding
item_embeddings_data.append({"id": item["id"], "embedding": embedding})
else:
print(f"Skipping item {item['id']} due to embedding error.")
if not item_embeddings_data:
print("\nError: No embeddings were generated. Cannot provide recommendations.")
exit()
print(f"\nSuccessfully generated embeddings for {len(item_embeddings_data)} items.")
# 3. Select a target item for which to find recommendations
target_item_id = "mov001" # Let's find movies similar to "Space Odyssey"
print(f"\nFinding recommendations similar to item ID: {target_item_id}")
# Find the embedding for the target item
target_embedding = None
for item_data in item_embeddings_data:
if item_data["id"] == target_item_id:
target_embedding = item_data["embedding"]
break
if target_embedding is None:
print(f"Error: Could not find the embedding for the target item ID '{target_item_id}'.")
exit()
# 4. Calculate similarity between the target item and all other items
recommendations = []
print("\nCalculating similarities...")
for item_data in item_embeddings_data:
# Don't compare the item with itself
if item_data["id"] == target_item_id:
continue
similarity = cosine_similarity(target_embedding, item_data["embedding"])
recommendations.append({"id": item_data["id"], "score": similarity})
# 5. Sort potential recommendations by similarity score
recommendations.sort(key=lambda x: x["score"], reverse=True)
# 6. Display top N recommendations
print("\n--- Top Recommendations ---")
# Find the original title/description for the target item for context
target_item_info = next((item for item in item_catalog if item["id"] == target_item_id), None)
if target_item_info:
print(f"Based on: \"{target_item_info['title']}\"\n")
if not recommendations:
print("No recommendations found (or error calculating similarities).")
else:
top_n = 3
print(f"Top {top_n} most similar items:")
for i, rec in enumerate(recommendations[:top_n]):
# Find the full item details from the original catalog
rec_details = next((item for item in item_catalog if item["id"] == rec["id"]), None)
if rec_details:
print(f"{i+1}. ID: {rec['id']}, Score: {rec['score']:.4f}")
print(f" Title: {rec_details['title']}")
print(f" Description: {rec_details['description'][:100]}...") # Truncate description
print("-" * 10)
else:
print(f"{i+1}. ID: {rec['id']}, Score: {rec['score']:.4f} (Details not found)")
print("-" * 10)
if len(recommendations) > top_n:
print(f"(Showing top {top_n} of {len(recommendations)} potential recommendations)")
Explicación del Desglose del Código
Este ejemplo demuestra cómo construir un sistema de recomendación basado en contenido de manera sencilla combinando los embeddings de OpenAI con cálculos de similitud del coseno.
- Configuración y Funciones Auxiliares:
- Incluye importaciones estándar (
openai
,os
,dotenv
,numpy
), inicialización del cliente, y las funciones auxiliaresget_embedding
ycosine_similarity
previamente definidas.
- Incluye importaciones estándar (
- Catálogo de Elementos:
- Una lista de diccionarios (
item_catalog
) representa los elementos disponibles para recomendación (por ejemplo, películas). Cada elemento tiene unid
,título
ydescripción
. En un sistema real, esto probablemente se cargaría desde una base de datos.
- Una lista de diccionarios (
- Generación de Embeddings de Elementos:
- El script itera a través de cada
item
en elitem_catalog
. - Combinación de Contenido: Combina el
título
y ladescripción
en una sola cadena (text_to_embed
). Esto proporciona un contexto más rico al modelo de embedding que usar solo el título o la descripción por separado. - Llama a
get_embedding
para este texto combinado. - Almacena el
item['id']
y su vector deembedding
correspondiente juntos en la listaitem_embeddings_data
. Este paso de pre-cómputo es una práctica estándar para sistemas de recomendación.
- El script itera a través de cada
- Selección del Elemento Objetivo:
- Una variable
target_item_id
se establece para especificar el elemento para el cual queremos recomendaciones (por ejemplo, encontrar elementos similares amov001
). - El script recupera el vector de embedding pre-calculado para este
target_item_id
de la listaitem_embeddings_data
.
- Una variable
- Cálculo de Similitud:
- Itera a través de todos los elementos con embeddings en
item_embeddings_data
. - Exclusión: Explícitamente omite la comparación si el ID del elemento actual coincide con el
target_item_id
(un elemento no debería recomendarse a sí mismo). - Para cada otro elemento, calcula la
similitud_coseno
entre eltarget_embedding
y el embedding del elemento actual. - Almacena el
id
del otro elemento y supuntuación
de similitud calculada en una lista derecommendations
.
- Itera a través de todos los elementos con embeddings en
- Clasificación de Recomendaciones:
- La lista
recommendations
se ordena usandorecommendations.sort(...)
basándose en el camposcore
en orden descendente, colocando los elementos más similares al principio de la lista.
- La lista
- Mostrar Resultados:
- El script imprime el título del elemento objetivo para contexto.
- Luego itera a través de los N principales (por ejemplo, 3) elementos en la lista ordenada de
recommendations
. - Para cada ID de elemento recomendado, busca los detalles completos (título, descripción) del
item_catalog
original. - Imprime el rango, ID, puntuación de similitud, título y una descripción truncada para cada elemento recomendado.
Este ejemplo muestra efectivamente cómo los embeddings capturan el significado semántico, permitiendo que el sistema recomiende elementos basándose en la similitud de contenido (por ejemplo, recomendando otras películas de ciencia ficción filosóficas similares a "Space Odyssey") en lugar de solo etiquetas explícitas o historial del usuario.
3.2.4 Recuperación de contexto para asistentes de IA
Ayudar a los chatbots y sistemas de IA a encontrar y utilizar información relevante de grandes bases de conocimiento mediante la conversión tanto de consultas como de conocimiento almacenado en embeddings. Este proceso involucra varios pasos clave:
Primero, el sistema convierte todos los documentos en su base de conocimiento en vectores de embedding - representaciones numéricas que capturan el significado semántico del texto. Estos embeddings se almacenan en una base de datos vectorial para una recuperación rápida.
Cuando un asistente de IA recibe una pregunta, convierte esa consulta en un vector de embedding usando el mismo proceso. Esto asegura que tanto el conocimiento almacenado como las preguntas entrantes estén representados en el mismo espacio matemático.
El sistema luego realiza una búsqueda de similitud para encontrar la información más relevante. Esta búsqueda compara el embedding de la consulta con todos los embeddings almacenados, típicamente usando técnicas como similitud del coseno o búsqueda del vecino más cercano. La belleza de este enfoque es que puede identificar contenido semánticamente similar incluso cuando la redacción exacta difiere significativamente.
Por ejemplo, una consulta sobre "el portátil no enciende" podría coincidir con documentación sobre "problemas de energía en computadoras" porque sus embeddings capturan el significado subyacente similar. Esta coincidencia semántica es mucho más potente que la búsqueda tradicional basada en palabras clave.
Una vez que se identifica la información relevante, puede utilizarse para generar respuestas más precisas e informadas. Esto es particularmente potente para aplicaciones específicas de dominio donde la IA necesita acceder a documentación técnica, información de productos o políticas empresariales. El sistema puede manejar consultas complejas combinando múltiples piezas de contexto relevante, asegurando que las respuestas sean tanto precisas como exhaustivas.
Ejemplo:
A continuación se muestra un ejemplo de código que demuestra cómo los asistentes de IA pueden recuperar contexto usando embeddings de OpenAI, implementando los conceptos discutidos en la sección 3.2.4.
El script ilustra el proceso esencial de búsqueda en una base de conocimiento para proporcionar contexto relevante para las respuestas del asistente de IA.
import os
from openai import OpenAI, OpenAIError
from dotenv import load_dotenv
import numpy as np # For cosine similarity calculation
import datetime
# --- Configuration ---
load_dotenv()
# Get the current date and location context
current_timestamp = "2025-02-10 15:35:00 CDT"
current_location = "Grapevine, Texas, United States"
print(f"Running Context Retrieval example at: {current_timestamp}")
print(f"Location Context: {current_location}")
# Initialize the OpenAI client
try:
api_key = os.getenv("OPENAI_API_KEY")
if not api_key:
raise ValueError("OPENAI_API_KEY not found in environment variables.")
client = OpenAI(api_key=api_key)
print("OpenAI client initialized.")
except ValueError as e:
print(f"Configuration Error: {e}")
exit()
except Exception as e:
print(f"Error initializing OpenAI client: {e}")
exit()
# Define the embedding model
EMBEDDING_MODEL = "text-embedding-3-small"
# --- Helper Function to Generate Embedding ---
# (Same as in previous embeddings examples)
def get_embedding(client, text, model=EMBEDDING_MODEL):
"""Generates an embedding for the given text using the specified model."""
print_text = text[:70] + "..." if len(text) > 70 else text
print(f"Generating embedding for: \"{print_text}\"")
try:
response = client.embeddings.create(
input=text,
model=model
)
embedding_vector = response.data[0].embedding
return embedding_vector
except OpenAIError as e:
print(f"OpenAI API Error generating embedding for text '{print_text}': {e}")
return None
except Exception as e:
print(f"An unexpected error occurred during embedding generation for text '{print_text}': {e}")
return None
# --- Helper Function for Cosine Similarity ---
# (Same as in previous embeddings examples)
def cosine_similarity(vec_a, vec_b):
"""Calculates the cosine similarity between two vectors."""
if vec_a is None or vec_b is None:
return 0.0
vec_a = np.array(vec_a)
vec_b = np.array(vec_b)
norm_a = np.linalg.norm(vec_a)
norm_b = np.linalg.norm(vec_b)
if norm_a == 0 or norm_b == 0:
return 0.0
else:
similarity = np.dot(vec_a, vec_b) / (norm_a * norm_b)
return similarity
# --- Context Retrieval Implementation ---
# 1. Define your Knowledge Base (list of text documents/chunks)
# This represents the information the AI assistant can draw upon.
knowledge_base = [
{"id": "doc001", "source": "troubleshooting_guide.txt", "content": "If your laptop fails to power on, first check the power adapter connection. Ensure the cable is securely plugged into both the laptop and the wall outlet. Try a different outlet if possible."},
{"id": "doc002", "source": "troubleshooting_guide.txt", "content": "A blinking power light often indicates a battery issue or a charging problem. Try removing the battery (if removable) and powering on with only the adapter connected."},
{"id": "doc003", "source": "faq.html", "content": "To reset your password, go to the login page and click the 'Forgot Password' link. Follow the instructions sent to your registered email address."},
{"id": "doc004", "source": "product_manual.pdf", "content": "The Model X laptop uses a USB-C port for charging. Ensure you are using the correct wattage power adapter (65W minimum recommended)."},
{"id": "doc005", "source": "troubleshooting_guide.txt", "content": "No display output? Check if the laptop is making any sounds (fan spinning, beeps). Try connecting an external monitor to rule out a screen issue."},
{"id": "doc006", "source": "support_articles/power_issues.md", "content": "Holding the power button down for 15-30 seconds can perform a hard reset, sometimes resolving power-on failures."},
{"id": "doc007", "source": "faq.html", "content": "Software updates can be found in the 'System Settings' under the 'Updates' section. Ensure you are connected to the internet."}
]
print(f"\nKnowledge base contains {len(knowledge_base)} documents/chunks.")
# 2. Generate embeddings for the knowledge base (pre-computation)
print("\nGenerating embeddings for the knowledge base...")
kb_embeddings_data = []
for doc in knowledge_base:
embedding = get_embedding(client, doc["content"])
if embedding:
# Store document ID and its embedding
kb_embeddings_data.append({"id": doc["id"], "embedding": embedding})
else:
print(f"Skipping document {doc['id']} due to embedding error.")
if not kb_embeddings_data:
print("\nError: No embeddings were generated for the knowledge base. Cannot retrieve context.")
exit()
print(f"\nSuccessfully generated embeddings for {len(kb_embeddings_data)} knowledge base documents.")
# 3. Define the user's query to the AI assistant
user_query = "My computer won't start up."
# user_query = "How do I update the system software?"
# user_query = "Screen is black when I press the power button."
print(f"\nUser Query: \"{user_query}\"")
# 4. Generate embedding for the user query
print("\nGenerating embedding for the user query...")
query_embedding = get_embedding(client, user_query)
# 5. Find relevant documents from the knowledge base using similarity search
retrieved_context = []
if query_embedding and kb_embeddings_data:
print("\nCalculating similarities to find relevant context...")
for doc_data in kb_embeddings_data:
similarity = cosine_similarity(query_embedding, doc_data["embedding"])
retrieved_context.append({"id": doc_data["id"], "score": similarity})
# Sort context documents by similarity score in descending order
retrieved_context.sort(key=lambda x: x["score"], reverse=True)
# 6. Select Top N relevant documents to use as context
top_n_context = 3
print(f"\n--- Top {top_n_context} Relevant Context Documents Found ---")
if not retrieved_context:
print("No relevant context found (or error calculating similarities).")
else:
final_context_docs = []
for i, context_item in enumerate(retrieved_context[:top_n_context]):
# Find the full document details from the original knowledge base
doc_details = next((doc for doc in knowledge_base if doc["id"] == context_item["id"]), None)
if doc_details:
print(f"{i+1}. ID: {context_item['id']}, Score: {context_item['score']:.4f}")
print(f" Source: {doc_details['source']}")
print(f" Content: {doc_details['content'][:150]}...") # Truncate content
print("-" * 10)
final_context_docs.append(doc_details['content']) # Store content for next step
else:
print(f"{i+1}. ID: {context_item['id']}, Score: {context_item['score']:.4f} (Details not found)")
print("-" * 10)
if len(retrieved_context) > top_n_context:
print(f"(Showing top {top_n_context} of {len(retrieved_context)} potential context documents)")
# --- Next Step (Conceptual - Not coded here) ---
print("\n--- Next Step: Generating AI Assistant Response ---")
print("The content from the relevant documents above would now be combined")
print("with the original user query and sent to a model like GPT-4o")
print("as context to generate an informed and accurate response.")
print("Example prompt structure for GPT-4o:")
print("```")
print(f"System: You are a helpful AI assistant. Answer the user's question based ONLY on the provided context documents.")
print(f"User: Context Documents:\n1. {final_context_docs[0][:50]}...\n2. {final_context_docs[1][:50]}...\n[...]\n\nQuestion: {user_query}\n\nAnswer:")
print("```")
else:
print("\nCould not retrieve context.")
if not query_embedding:
print("Reason: Failed to generate embedding for the user query.")
if not kb_embeddings_data:
print("Reason: No knowledge base embeddings were successfully generated.")
Explicación del Desglose del Código
Este ejemplo demuestra el mecanismo central detrás de la recuperación de contexto para asistentes de IA usando embeddings – encontrar información relevante de una base de conocimiento para responder a la consulta de un usuario.
- Configuración y Funciones Auxiliares:
- Incluye importaciones estándar (
openai
,os
,dotenv
,numpy
), inicialización del cliente, y las funciones auxiliaresget_embedding
ycosine_similarity
.
- Incluye importaciones estándar (
- Definición de la Base de Conocimiento:
- Una lista de diccionarios (
knowledge_base
) simula el almacén de información al que puede acceder el asistente de IA. Cada diccionario representa un documento o fragmento de información e incluye unid
,source
(metadatos opcionales), y elcontent
del texto actual.
- Una lista de diccionarios (
- Generación de Embeddings de la Base de Conocimiento:
- El script itera a través de cada
doc
en elknowledge_base
. - Llama a
get_embedding
en eldoc["content"]
para obtener su representación vectorial. - Almacena el
doc['id']
y su correspondiente vectorembedding
juntos enkb_embeddings_data
. Este es el paso crucial de pre-computación – los embeddings para la base de conocimiento típicamente se generan fuera de línea y se almacenan (a menudo en una base de datos vectorial especializada) para una recuperación rápida.
- El script itera a través de cada
- Consulta del Usuario:
- Una cadena de ejemplo
user_query
representa la pregunta realizada al asistente de IA.
- Una cadena de ejemplo
- Generación del Embedding de la Consulta:
- La función
get_embedding
se llama para eluser_query
para obtener su representación vectorial en el mismo espacio de embeddings que los documentos de la base de conocimiento.
- La función
- Búsqueda de Similitud (Recuperación de Contexto):
- Itera a través de todos los embeddings pre-computados en
kb_embeddings_data
. - Para cada documento de la base de conocimiento, calcula la
cosine_similarity
entre elquery_embedding
y el embedding del documento. - Almacena el
id
del documento y suscore
de similitud relativo a la consulta en una listaretrieved_context
.
- Itera a través de todos los embeddings pre-computados en
- Clasificación y Selección:
- La lista
retrieved_context
se ordena porscore
en orden descendente, trayendo los documentos semánticamente más relevantes al principio. - El script selecciona los N primeros (por ejemplo, 3) documentos de esta lista ordenada. Estos documentos representan el contexto más relevante encontrado en la base de conocimiento para la consulta del usuario.
- La lista
- Mostrar el Contexto Recuperado:
- El script imprime los detalles (ID, puntuación, fuente, vista previa del contenido) de los N primeros documentos de contexto encontrados.
- Siguiente Paso Conceptual (Explicación Crucial):
- Las declaraciones finales de impresión explican el propósito de este proceso de recuperación. El contenido de estos
final_context_docs
no sería la respuesta final. En su lugar, se combinarían con eluser_query
original y se pasarían como contexto a un modelo de lenguaje grande como GPT-4o en una llamada API subsiguiente. - Se muestra una estructura de prompt de ejemplo, ilustrando cómo el contexto recuperado fundamenta al asistente de IA, permitiéndole generar una respuesta informada basada en la información relevante encontrada en la base de conocimiento, en lugar de confiar únicamente en su conocimiento general.
- Las declaraciones finales de impresión explican el propósito de este proceso de recuperación. El contenido de estos
Este ejemplo demuestra efectivamente la parte de recuperación de la Generación Aumentada por Recuperación (RAG), mostrando cómo los embeddings tienden un puente entre la consulta de un usuario y la información relevante almacenada en una base de conocimiento, permitiendo asistentes de IA más precisos y conscientes del contexto.
3.2.5 Detección de anomalías y similitud
Identificar patrones inusuales o encontrar elementos similares en grandes conjuntos de datos mediante la comparación de sus representaciones semánticas es una aplicación fundamental de la tecnología de embeddings. Esta poderosa técnica transforma datos sin procesar en vectores matemáticos que capturan la esencia de su contenido, permitiendo análisis sofisticados a gran escala. Así es cómo funcionan estos sistemas y sus aplicaciones clave:
- Detectar Anomalías
- Marcar transacciones o comportamientos inusuales que se desvían de los patrones normales - Por ejemplo, detectar compras sospechosas con tarjeta de crédito comparándolas con patrones típicos de gasto
- Identificar posibles amenazas de seguridad o intentos de fraude - Como reconocer patrones de inicio de sesión inusuales o detectar cuentas falsas basadas en análisis de comportamiento
- Detectar problemas de calidad de datos o valores atípicos en conjuntos de datos - Incluyendo la identificación de entradas de datos incorrectas o mediciones inusuales que podrían indicar mal funcionamiento del equipo
- Encontrar Similitudes
- Agrupar documentos, imágenes o puntos de datos relacionados basados en significado semántico - Esto permite a los sistemas agrupar contenido similar incluso cuando la redacción exacta difiere, facilitando la organización de grandes colecciones de información
- Emparejar consultas o tickets de soporte similares - Ayudando a los equipos de servicio al cliente a identificar problemas comunes y estandarizar respuestas a problemas frecuentes
- Identificar contenido duplicado o casi duplicado - Útil para sistemas de gestión de contenido para mantener la calidad de datos y reducir la redundancia
Al convertir puntos de datos en vectores de embedding, los sistemas pueden medir qué tan "diferentes" o "similares" son los elementos entre sí usando cálculos de distancia matemática. Este proceso funciona mapeando cada elemento a un punto en un espacio de alta dimensión, donde los elementos similares se posicionan más cerca entre sí y los elementos diferentes están más separados. Esta representación matemática hace posible marcar automáticamente patrones inusuales o agrupar elementos relacionados a gran escala, permitiendo tanto la detección de anomalías como la coincidencia de similitud de formas que serían imposibles con sistemas tradicionales basados en reglas.
Ejemplo:
El siguiente ejemplo de código demuestra la detección de similitud y anomalías usando embeddings de OpenAI.
Este script:
- Definirá un conjunto de datos de elementos de texto (por ejemplo, descripciones de transacciones o eventos).
- Generará embeddings para estos elementos.
- Detección de Similitud: Encontrará elementos más similares a un elemento objetivo dado.
- Detección de Anomalías: Identificará elementos que son menos similares (más anómalos) comparados con el resto del conjunto de datos usando un enfoque simple de similitud promedio.
import os
from openai import OpenAI, OpenAIError
from dotenv import load_dotenv
import numpy as np # For cosine similarity calculation
import datetime
# --- Configuration ---
load_dotenv()
# Get the current date and location context
current_timestamp = "2025-01-13 15:40:00 CDT"
current_location = "Houston, Texas, United States"
print(f"Running Similarity & Anomaly Detection example at: {current_timestamp}")
print(f"Location Context: {current_location}")
# Initialize the OpenAI client
try:
api_key = os.getenv("OPENAI_API_KEY")
if not api_key:
raise ValueError("OPENAI_API_KEY not found in environment variables.")
client = OpenAI(api_key=api_key)
print("OpenAI client initialized.")
except ValueError as e:
print(f"Configuration Error: {e}")
exit()
except Exception as e:
print(f"Error initializing OpenAI client: {e}")
exit()
# Define the embedding model
EMBEDDING_MODEL = "text-embedding-3-small"
# --- Helper Function to Generate Embedding ---
# (Same as in previous embeddings examples)
def get_embedding(client, text, model=EMBEDDING_MODEL):
"""Generates an embedding for the given text using the specified model."""
print_text = text[:70] + "..." if len(text) > 70 else text
print(f"Generating embedding for: \"{print_text}\"")
try:
response = client.embeddings.create(
input=text,
model=model
)
embedding_vector = response.data[0].embedding
return embedding_vector
except OpenAIError as e:
print(f"OpenAI API Error generating embedding for text '{print_text}': {e}")
return None
except Exception as e:
print(f"An unexpected error occurred during embedding generation for text '{print_text}': {e}")
return None
# --- Helper Function for Cosine Similarity ---
# (Same as in previous embeddings examples)
def cosine_similarity(vec_a, vec_b):
"""Calculates the cosine similarity between two vectors."""
if vec_a is None or vec_b is None:
return 0.0
vec_a = np.array(vec_a)
vec_b = np.array(vec_b)
norm_a = np.linalg.norm(vec_a)
norm_b = np.linalg.norm(vec_b)
if norm_a == 0 or norm_b == 0:
return 0.0
else:
# Clamp the value to handle potential floating point inaccuracies slightly outside [-1, 1]
similarity = np.dot(vec_a, vec_b) / (norm_a * norm_b)
return np.clip(similarity, -1.0, 1.0)
# --- Similarity and Anomaly Detection Implementation ---
# 1. Define your dataset (e.g., transaction descriptions, log entries)
# Includes mostly normal items and a couple of potentially anomalous ones.
dataset = [
{"id": "txn001", "description": "Grocery purchase at Local Supermarket"},
{"id": "txn002", "description": "Monthly subscription fee for streaming service"},
{"id": "txn003", "description": "Dinner payment at Italian Restaurant"},
{"id": "txn004", "description": "Online order for electronics from TechStore"},
{"id": "txn005", "description": "Fuel purchase at Gas Station"},
{"id": "txn006", "description": "Purchase of fresh produce and bread"}, # Similar to txn001
{"id": "txn007", "description": "Payment for movie streaming subscription"}, # Similar to txn002
{"id": "txn008", "description": "Unusual large wire transfer to overseas account"}, # Potential Anomaly 1
{"id": "txn009", "description": "Purchase of rare antique collectible vase"}, # Potential Anomaly 2
{"id": "txn010", "description": "Coffee purchase at Cafe Central"}
]
print(f"\nDataset contains {len(dataset)} items.")
# 2. Generate embeddings for all items in the dataset (pre-computation)
print("\nGenerating embeddings for the dataset...")
dataset_embeddings_data = []
for item in dataset:
embedding = get_embedding(client, item["description"])
if embedding:
# Store item ID, description, and its embedding
dataset_embeddings_data.append({
"id": item["id"],
"description": item["description"],
"embedding": embedding
})
else:
print(f"Skipping item {item['id']} due to embedding error.")
if not dataset_embeddings_data:
print("\nError: No embeddings were generated. Cannot perform analysis.")
exit()
print(f"\nSuccessfully generated embeddings for {len(dataset_embeddings_data)} items.")
# --- Part A: Similarity Detection ---
print("\n--- Part A: Similarity Detection ---")
# Select a target item to find similar items for
target_item_id_similarity = "txn001" # Find items similar to "Grocery purchase..."
print(f"Finding items similar to item ID: {target_item_id_similarity}")
# Find the target item's data
target_item_data = next((item for item in dataset_embeddings_data if item["id"] == target_item_id_similarity), None)
if target_item_data:
target_embedding = target_item_data["embedding"]
similar_items = []
# Calculate similarity between the target and all other items
for item_data in dataset_embeddings_data:
if item_data["id"] == target_item_id_similarity:
continue # Skip self-comparison
similarity = cosine_similarity(target_embedding, item_data["embedding"])
similar_items.append({
"id": item_data["id"],
"description": item_data["description"],
"score": similarity
})
# Sort by similarity score
similar_items.sort(key=lambda x: x["score"], reverse=True)
# Display top N similar items
print(f"\nItems most similar to: \"{target_item_data['description']}\"")
top_n_similar = 2
for i, item in enumerate(similar_items[:top_n_similar]):
print(f"{i+1}. ID: {item['id']}, Score: {item['score']:.4f}")
print(f" Description: {item['description']}")
print("-" * 10)
else:
print(f"Error: Could not find data for target item ID '{target_item_id_similarity}'.")
# --- Part B: Anomaly Detection (Simple Approach) ---
print("\n--- Part B: Anomaly Detection (Low Average Similarity) ---")
# Calculate the average similarity of each item to all other items
item_avg_similarities = []
num_items = len(dataset_embeddings_data)
if num_items < 2:
print("Need at least 2 items with embeddings to calculate average similarities.")
else:
print("\nCalculating average similarities for anomaly detection...")
for i in range(num_items):
current_item = dataset_embeddings_data[i]
total_similarity = 0
# Compare current item to all others
for j in range(num_items):
if i == j: # Don't compare item to itself
continue
other_item = dataset_embeddings_data[j]
similarity = cosine_similarity(current_item["embedding"], other_item["embedding"])
total_similarity += similarity
# Calculate average similarity (avoid division by zero if only 1 item)
average_similarity = total_similarity / (num_items - 1) if num_items > 1 else 0
item_avg_similarities.append({
"id": current_item["id"],
"description": current_item["description"],
"avg_score": average_similarity
})
print(f"Item ID {current_item['id']} - Avg Similarity: {average_similarity:.4f}")
# Sort items by average similarity in ascending order (lowest first = most anomalous)
item_avg_similarities.sort(key=lambda x: x["avg_score"])
# Display top N potential anomalies (items least similar to others)
print("\nPotential Anomalies (Lowest Average Similarity):")
top_n_anomalies = 3
for i, item in enumerate(item_avg_similarities[:top_n_anomalies]):
print(f"{i+1}. ID: {item['id']}, Avg Score: {item['avg_score']:.4f}")
print(f" Description: {item['description']}")
print("-" * 10)
print("\nNote: Low average similarity suggests an item is semantically")
print("different from the majority of other items in this dataset.")
Explicación del Desglose del Código
Este ejemplo demuestra el uso de embeddings de OpenAI tanto para encontrar elementos similares como para detectar posibles anomalías dentro de un conjunto de datos basándose en el significado semántico.
- Configuración y Funciones Auxiliares:
- Incluye importaciones estándar (
openai
,os
,dotenv
,numpy
), inicialización del cliente, y las funciones auxiliaresget_embedding
ycosine_similarity
. La funcióncosine_similarity
ahora incluyenp.clip
para asegurar que la salida esté estrictamente dentro de [-1, 1].
- Incluye importaciones estándar (
- Definición del Conjunto de Datos:
- Una lista de diccionarios (
dataset
) simula los datos a analizar (por ejemplo, descripciones de transacciones). Cada elemento tiene unid
y unadescription
de texto. Los datos de muestra incluyen principalmente elementos comunes y algunos conceptualmente diferentes destinados a ser posibles anomalías.
- Una lista de diccionarios (
- Generación de Embeddings del Conjunto de Datos:
- El script itera a través de cada
item
en eldataset
. - Llama a
get_embedding
en elitem["description"]
. - Almacena el
item['id']
,item['description']
, y su correspondiente vectorembedding
juntos endataset_embeddings_data
. Esta pre-computación es esencial.
- El script itera a través de cada
- Parte A: Detección de Similitud:
- Selección del Objetivo: Se elige un ID de elemento (
target_item_id_similarity
) para encontrar elementos similares. - Recuperación del Embedding Objetivo: El script encuentra el embedding pre-computado para el elemento objetivo.
- Comparación: Itera a través de todos los otros elementos en
dataset_embeddings_data
, calcula lacosine_similarity
entre el embedding del elemento objetivo y el embedding de cada otro elemento. - Clasificación: Los resultados (ID del otro elemento, descripción, puntuación de similitud) se almacenan y luego se ordenan por puntuación en orden descendente.
- Visualización: Se muestran los N elementos más similares.
- Selección del Objetivo: Se elige un ID de elemento (
- Parte B: Detección de Anomalías (Enfoque de Similitud Promedio Simple):
- Concepto: Este método simple identifica anomalías como elementos que tienen la similitud promedio más baja con todos los otros elementos en el conjunto de datos. Un elemento que es conceptualmente muy diferente del resto probablemente tendrá puntuaciones de similitud bajas cuando se compare con la mayoría de los otros.
- Cálculo:
- El script itera a través de cada elemento (
current_item
) endataset_embeddings_data
. - Para cada
current_item
, itera a través de todos los otros elementos en el conjunto de datos. - Calcula la
cosine_similarity
entre elcurrent_item
y cadaother_item
. - Suma estas similitudes y calcula la similitud promedio para el
current_item
.
- El script itera a través de cada elemento (
- Clasificación: Los elementos se almacenan junto con su
avg_score
calculado y luego se ordenan por esta puntuación en orden ascendente (similitud promedio más baja primero). - Visualización: Se muestran los N elementos con las puntuaciones de similitud promedio más bajas como posibles anomalías. Una nota explica la interpretación.
Este ejemplo muestra dos aplicaciones poderosas: encontrar contenido relacionado (similitud) e identificar valores atípicos (detección de anomalías) aprovechando la comprensión semántica capturada dentro de los embeddings de OpenAI.
3.2.6 Agrupamiento y Etiquetado
Organizar y etiquetar contenido automáticamente basándose en la similitud semántica - una técnica poderosa que utiliza vectores de embedding para comprender el verdadero significado y las relaciones entre diferentes piezas de contenido. Este enfoque va mucho más allá del tradicional emparejamiento de palabras clave, permitiendo una organización de contenido mucho más matizada y precisa.
Cuando el contenido se agrupa, los elementos similares se agrupan naturalmente según su significado semántico, incluso si utilizan terminología diferente para expresar los mismos conceptos. Por ejemplo, los documentos sobre "mantenimiento automotriz" y "reparación de coches" se agruparían juntos a pesar de usar palabras diferentes.
Esta organización inteligente ayuda a crear sistemas de navegación intuitivos, mejora el descubrimiento de contenido y hace que las grandes colecciones de documentos sean más manejables al agrupar elementos relacionados. Algunos beneficios clave incluyen:
- Generación automática de etiquetas basada en temas de grupos
- Organización dinámica que se adapta a medida que se agrega nuevo contenido
- Mejora de la relevancia en las búsquedas mediante comprensión semántica
- Mejor descubrimiento de contenido a través de sugerencias de elementos relacionados
El proceso de agrupamiento puede ajustarse para crear categorías amplias o subcategorías más granulares, dependiendo de las necesidades específicas de su sistema de organización de contenido. Esta flexibilidad lo convierte en una herramienta valiosa para gestionar desde bibliotecas digitales hasta bases de conocimiento empresariales.
Ejemplo:
Examinemos un ejemplo de código que demuestra el agrupamiento y etiquetado usando embeddings de OpenAI y GPT-4o.
Este script:
- Definirá una colección de documentos.
- Generará embeddings para los documentos.
- Agrupará los documentos usando K-Means basándose en sus embeddings.
- Para cada grupo, usará GPT-4o para analizar los documentos dentro de él y generar una etiqueta o descriptor descriptivo.
- Mostrará los documentos agrupados por cluster junto con sus etiquetas generadas por IA.
import os
from openai import OpenAI, OpenAIError
from dotenv import load_dotenv
import numpy as np
from sklearn.cluster import KMeans # For clustering algorithm
import datetime
# --- Configuration ---
load_dotenv()
# Get the current date and location context
current_timestamp = "2024-12-31 15:48:00 CDT"
current_location = "San Antonio, Texas, United States"
print(f"Running Clustering & Tagging example at: {current_timestamp}")
print(f"Location Context: {current_location}")
# Initialize the OpenAI client
try:
api_key = os.getenv("OPENAI_API_KEY")
if not api_key:
raise ValueError("OPENAI_API_KEY not found in environment variables.")
client = OpenAI(api_key=api_key)
print("OpenAI client initialized.")
except ValueError as e:
print(f"Configuration Error: {e}")
exit()
except Exception as e:
print(f"Error initializing OpenAI client: {e}")
exit()
# Define the embedding model
EMBEDDING_MODEL = "text-embedding-3-small"
# --- Helper Function to Generate Embedding ---
# (Same as in previous embeddings examples)
def get_embedding(client, text, model=EMBEDDING_MODEL):
"""Generates an embedding for the given text using the specified model."""
print_text = text[:70] + "..." if len(text) > 70 else text
print(f"Generating embedding for: \"{print_text}\"")
try:
response = client.embeddings.create(
input=text,
model=model
)
embedding_vector = response.data[0].embedding
return embedding_vector
except OpenAIError as e:
print(f"OpenAI API Error generating embedding for text '{print_text}': {e}")
return None
except Exception as e:
print(f"An unexpected error occurred during embedding generation for text '{print_text}': {e}")
return None
# --- Helper Function to Generate Cluster Tag using GPT-4o ---
def generate_cluster_tag(client, documents_in_cluster):
"""Uses GPT-4o to suggest a tag/label for a cluster of documents."""
if not documents_in_cluster:
return "Empty Cluster"
# Combine content for context, limiting total length if necessary
# Using first few hundred chars of each doc might be enough
max_context_length = 3000 # Limit context to avoid excessive token usage
context = ""
for i, doc in enumerate(documents_in_cluster):
doc_preview = f"Document {i+1}: {doc[:300]}...\n"
if len(context) + len(doc_preview) > max_context_length:
break
context += doc_preview
if not context:
return "Error: Could not create context"
system_prompt = "You are an expert at identifying themes and creating concise labels."
user_prompt = f"""Based on the following document excerpts from a single cluster, suggest a short, descriptive tag or label (2-5 words) that captures the main theme or topic of this group.
Document Excerpts:
---
{context.strip()}
---
Suggested Tag/Label:
"""
print(f"\nGenerating tag for cluster with {len(documents_in_cluster)} documents...")
try:
response = client.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_prompt}
],
max_tokens=20, # Short response expected
temperature=0.3 # More deterministic label
)
tag = response.choices[0].message.content.strip().replace('"', '') # Clean up quotes
print(f"Generated tag: '{tag}'")
return tag
except OpenAIError as e:
print(f"OpenAI API Error generating tag: {e}")
return "Tagging Error"
except Exception as e:
print(f"An unexpected error occurred during tag generation: {e}")
return "Tagging Error"
# --- Clustering and Tagging Implementation ---
# 1. Define your collection of documents
# Covers topics: Space Exploration, Cooking/Food, Web Development
documents = [
"NASA launches new probe to study Jupiter's moons.",
"Recipe for authentic Italian pasta carbonara.",
"JavaScript frameworks like React and Vue dominate front-end development.",
"The James Webb Space Telescope captures stunning images of distant galaxies.",
"Tips for baking the perfect sourdough bread at home.",
"Understanding asynchronous programming in Node.js.",
"SpaceX successfully lands its reusable rocket booster after launch.",
"Exploring the different types of olive oil and their uses in cooking.",
"CSS Grid vs Flexbox: Choosing the right layout module.",
"The search for habitable exoplanets continues with new telescope data.",
"How to make delicious homemade pizza from scratch.",
"Building RESTful APIs using Express.js and MongoDB."
]
print(f"\nDocument collection contains {len(documents)} documents.")
# 2. Generate embeddings for all documents
print("\nGenerating embeddings for the document collection...")
embeddings = []
valid_documents = [] # Keep track of documents for which embedding was successful
for doc in documents:
embedding = get_embedding(client, doc)
if embedding:
embeddings.append(embedding)
valid_documents.append(doc) # Add corresponding document text
else:
print(f"Skipping document due to embedding error: \"{doc[:70]}...\"")
if not embeddings:
print("\nError: No embeddings were generated. Cannot perform clustering.")
exit()
print(f"\nSuccessfully generated embeddings for {len(valid_documents)} documents.")
# Convert embeddings list to a NumPy array for scikit-learn
embedding_matrix = np.array(embeddings)
# 3. Apply Clustering Algorithm (K-Means)
# Choose the number of clusters (k). We expect 3 topics here.
n_clusters = 3
print(f"\nApplying K-Means clustering with k={n_clusters}...")
try:
kmeans = KMeans(n_clusters=n_clusters, random_state=42, n_init=10)
kmeans.fit(embedding_matrix)
cluster_labels = kmeans.labels_
print("Clustering complete.")
except Exception as e:
print(f"An error occurred during clustering: {e}")
exit()
# 4. Group Documents by Cluster
print("\nGrouping documents by cluster...")
clustered_documents = {i: [] for i in range(n_clusters)}
for i, label in enumerate(cluster_labels):
clustered_documents[label].append(valid_documents[i])
# 5. Generate Tags for Each Cluster using GPT-4o
print("\nGenerating tags for each cluster...")
cluster_tags = {}
for cluster_id, docs_in_cluster in clustered_documents.items():
tag = generate_cluster_tag(client, docs_in_cluster)
cluster_tags[cluster_id] = tag
# 6. Display Documents by Cluster with Generated Tags
print(f"\n--- Documents Grouped by Cluster and Tag (k={n_clusters}) ---")
for cluster_id, docs_in_cluster in clustered_documents.items():
generated_tag = cluster_tags.get(cluster_id, "Unknown Tag")
print(f"\nCluster {cluster_id + 1} - Suggested Tag: '{generated_tag}'")
print("-" * (28 + len(generated_tag))) # Adjust underline length
if not docs_in_cluster:
print(" (No documents in this cluster)")
else:
for doc_text in docs_in_cluster:
print(f" - {doc_text}") # Print full document text here
print("\nClustering and Tagging process complete.")
Explicación del Desglose del Código
Este script demuestra cómo agrupar automáticamente documentos similares por su significado semántico usando embeddings, y luego utiliza GPT-4o para generar etiquetas descriptivas para cada grupo.
- Configuración y Funciones Auxiliares:
- Incluye importaciones estándar más
KMeans
desklearn.cluster
. - Inicializa el cliente de OpenAI.
- Incluye la función auxiliar
get_embedding
.
- Incluye importaciones estándar más
- Nueva Función Auxiliar:
generate_cluster_tag
:- Propósito: Toma una lista de documentos pertenecientes a un único clúster y utiliza GPT-4o para sugerir una etiqueta concisa que resuma su tema común.
- Entrada: El objeto
client
ydocuments_in_cluster
(una lista de cadenas de texto). - Creación de Contexto: Concatena partes de los documentos (por ejemplo, los primeros 300 caracteres) para crear una cadena de contexto para GPT-4o, respetando una longitud máxima para gestionar el uso de tokens.
- Ingeniería de Prompt: Construye un prompt pidiendo a GPT-4o que actúe como un experto en identificación de temas y sugiera una etiqueta corta (2-5 palabras) basada en los extractos de documentos proporcionados.
- Llamada a la API: Utiliza
client.chat.completions.create
conmodel="gpt-4o"
y el prompt especializado. Se usa una temperatura baja para una generación de etiquetas más enfocada. - Salida: Devuelve la etiqueta sugerida por GPT-4o depurada, o un mensaje de error.
- Colección de Documentos: Una lista llamada
documents
contiene contenido de texto de muestra que abarca varios temas distintos (Espacio, Cocina, Desarrollo Web). - Generación de Embeddings:
- El script itera a través de los
documents
, genera un embedding para cada uno usandoget_embedding
, y almacena los embeddings exitosos y el texto correspondiente enembeddings
yvalid_documents
. - Los embeddings se convierten a un array de NumPy (
embedding_matrix
).
- El script itera a través de los
- Agrupamiento (K-Means):
- El número de clústeres (
n_clusters
) se establece (por ejemplo,k=3
). KMeans
descikit-learn
se inicializa y se ajusta a laembedding_matrix
.kmeans.labels_
proporciona la asignación de clúster para cada documento.
- El número de clústeres (
- Agrupación de Documentos:
- Se crea un diccionario (
clustered_documents
) para almacenar el texto de los documentos pertenecientes a cada ID de clúster.
- Se crea un diccionario (
- Generación de Etiquetas de Clúster:
- El script itera a través del diccionario
clustered_documents
. - Para cada
cluster_id
y su lista dedocs_in_cluster
, llama a la función auxiliargenerate_cluster_tag
. - La etiqueta sugerida para cada clúster se almacena en el diccionario
cluster_tags
.
- El script itera a través del diccionario
- Visualización de Resultados:
- El script itera nuevamente a través de los clústeres.
- Para cada clúster, recupera la etiqueta generada de
cluster_tags
. - Imprime el número del clúster, la etiqueta sugerida, y luego lista el texto completo de todos los documentos pertenecientes a ese clúster.
Este ejemplo muestra un flujo de trabajo potente: usar embeddings para el agrupamiento no supervisado de contenido basado en significado (clustering) y luego aprovechar un LLM como GPT-4o para interpretar esos grupos y asignar etiquetas significativas (etiquetado), automatizando la organización del contenido.
3.2.7 Recomendaciones de Contenido
Los sistemas de recomendación de contenido impulsados por embeddings representan un avance significativo en la tecnología de personalización. Al analizar relaciones semánticas, estos sistemas pueden entender el significado matizado y el contexto del contenido de maneras que los sistemas tradicionales basados en palabras clave no pueden.
Aquí hay una mirada detallada a cómo funcionan las recomendaciones basadas en embeddings:
- Análisis de Contenido:
- El sistema genera vectores de embedding sofisticados para cada pieza de contenido en la base de datos
- Estos vectores capturan características matizadas como estilo de escritura, profundidad del tema y tono emocional
- Los algoritmos avanzados analizan patrones a través de múltiples dimensiones de características de contenido
- Modelado de Preferencias del Usuario:
- El sistema rastrea patrones detallados de interacción incluyendo tiempo dedicado, nivel de participación y comportamiento de compartir
- Las preferencias históricas se ponderan y combinan para crear perfiles de usuario multidimensionales
- Se consideran tanto la retroalimentación explícita (calificaciones, me gusta) como las señales implícitas (profundidad de desplazamiento, visitas repetidas)
- Comprensión Contextual:
- Los factores en tiempo real como el tipo de dispositivo y la ubicación se incorporan al algoritmo de recomendación
- El sistema identifica patrones en el consumo de contenido basados en la hora del día y el día de la semana
- El comportamiento de la sesión actual se analiza para entender los intereses inmediatos del usuario
- Adaptación Dinámica:
- Los modelos de aprendizaje automático refinan continuamente los perfiles de usuario basados en nuevas interacciones
- El sistema aprende tanto de la retroalimentación positiva como negativa para mejorar la precisión
- Las estrategias de recomendación se ajustan automáticamente según las métricas de rendimiento
Este enfoque sofisticado permite que los motores de recomendación entreguen experiencias altamente personalizadas a través de varias capacidades clave:
- Identificar similitudes de contenido que podrían no ser aparentes a través de metadatos tradicionales
- Puede detectar conexiones temáticas entre elementos incluso cuando utilizan terminología diferente
- Reconoce estilos de escritura similares, tono y niveles de complejidad en el contenido
- Entender la progresión de los intereses del usuario a lo largo del tiempo
- Rastrea cómo evolucionan las preferencias desde temas básicos hasta avanzados
- Identifica cambios en los intereses del usuario a través de diferentes categorías
- Hacer recomendaciones entre dominios (por ejemplo, sugerir artículos basados en videos vistos)
- Conecta contenido a través de diferentes tipos de medios basándose en relaciones semánticas
- Aprovecha el aprendizaje de un dominio para mejorar las recomendaciones en otro
- Tener en cuenta tendencias estacionales y relevancia temporal
- Ajusta las recomendaciones basándose en factores sensibles al tiempo como festividades o eventos
- Considera las tendencias actuales y su impacto en los intereses del usuario
El resultado es una experiencia altamente personalizada que puede sugerir videos, artículos o productos verdaderamente relevantes que coincidan con los intereses de los usuarios, tanto actuales como en evolución. Esto va mucho más allá de los simples algoritmos de "a los usuarios que les gustó X también les gustó Y", creando una experiencia de usuario más atractiva y valiosa.
Ejemplo:
Aquí hay un ejemplo de código que demuestra el concepto central de recomendaciones de contenido usando embeddings.
Este script se centra en encontrar elementos de contenido semánticamente similares basados en sus embeddings, que es la base para las características de recomendación más avanzadas que describiste.
import os
from openai import OpenAI, OpenAIError
from dotenv import load_dotenv
import numpy as np # For cosine similarity calculation
import datetime
# --- Configuration ---
load_dotenv()
# Get the current date and location context
current_timestamp = "2024-11-30 15:52:00 CDT"
current_location = "Orlando, Florida, United States"
print(f"Running Content Recommendation example at: {current_timestamp}")
print(f"Location Context: {current_location}")
# Initialize the OpenAI client
try:
api_key = os.getenv("OPENAI_API_KEY")
if not api_key:
raise ValueError("OPENAI_API_KEY not found in environment variables.")
client = OpenAI(api_key=api_key)
print("OpenAI client initialized.")
except ValueError as e:
print(f"Configuration Error: {e}")
exit()
except Exception as e:
print(f"Error initializing OpenAI client: {e}")
exit()
# Define the embedding model
EMBEDDING_MODEL = "text-embedding-3-small"
# --- Helper Function to Generate Embedding ---
# (Same as in previous embeddings examples)
def get_embedding(client, text, model=EMBEDDING_MODEL):
"""Generates an embedding for the given text using the specified model."""
print_text = text[:70] + "..." if len(text) > 70 else text
print(f"Generating embedding for: \"{print_text}\"")
try:
response = client.embeddings.create(
input=text,
model=model
)
embedding_vector = response.data[0].embedding
return embedding_vector
except OpenAIError as e:
print(f"OpenAI API Error generating embedding for text '{print_text}': {e}")
return None
except Exception as e:
print(f"An unexpected error occurred during embedding generation for text '{print_text}': {e}")
return None
# --- Helper Function for Cosine Similarity ---
# (Same as in previous embeddings examples)
def cosine_similarity(vec_a, vec_b):
"""Calculates the cosine similarity between two vectors."""
if vec_a is None or vec_b is None:
return 0.0
vec_a = np.array(vec_a)
vec_b = np.array(vec_b)
norm_a = np.linalg.norm(vec_a)
norm_b = np.linalg.norm(vec_b)
if norm_a == 0 or norm_b == 0:
return 0.0
else:
similarity = np.dot(vec_a, vec_b) / (norm_a * norm_b)
return np.clip(similarity, -1.0, 1.0) # Ensure value is within valid range
# --- Content Recommendation Implementation ---
# 1. Define your Content Catalog (e.g., articles, blog posts)
# In a real application, this would come from a database or CMS.
content_catalog = [
{"id": "art001", "title": "Introduction to Quantum Computing", "content": "Exploring the basics of qubits, superposition, and entanglement in quantum mechanics and their potential for computation."},
{"id": "art002", "title": "Healthy Mediterranean Diet Recipes", "content": "Delicious and easy recipes focusing on fresh vegetables, olive oil, fish, and whole grains for a heart-healthy lifestyle."},
{"id": "art003", "title": "The Future of Artificial Intelligence in Healthcare", "content": "How AI and machine learning are transforming diagnostics, drug discovery, and personalized medicine."},
{"id": "art004", "title": "Beginner's Guide to Python Programming", "content": "Learn the fundamentals of Python syntax, data types, control flow, and functions to start coding."},
{"id": "art005", "title": "Understanding Neural Networks and Deep Learning", "content": "An overview of artificial neural networks, backpropagation, and the concepts behind deep learning models."},
{"id": "art006", "title": "Travel Guide: Hiking the Swiss Alps", "content": "Tips for planning your trip, recommended trails, essential gear, and stunning viewpoints in the Swiss Alps."},
{"id": "art007", "title": "Mastering the Art of French Pastry", "content": "Techniques for creating classic French desserts like croissants, macarons, and éclairs."},
{"id": "art008", "title": "Ethical Considerations in AI Development", "content": "Discussing bias, fairness, transparency, and accountability in the development and deployment of artificial intelligence systems."}
]
print(f"\nContent catalog contains {len(content_catalog)} items.")
# 2. Generate embeddings for all content items (pre-computation)
print("\nGenerating embeddings for the content catalog...")
content_embeddings_data = []
for item in content_catalog:
# Use title and content for embedding
text_to_embed = f"Title: {item['title']}\nContent: {item['content']}"
embedding = get_embedding(client, text_to_embed)
if embedding:
# Store item ID and its embedding
content_embeddings_data.append({"id": item["id"], "embedding": embedding})
else:
print(f"Skipping item {item['id']} due to embedding error.")
if not content_embeddings_data:
print("\nError: No embeddings were generated. Cannot provide recommendations.")
exit()
print(f"\nSuccessfully generated embeddings for {len(content_embeddings_data)} content items.")
# 3. Select a target item (e.g., an article the user just read)
target_item_id = "art003" # User read "The Future of Artificial Intelligence in Healthcare"
print(f"\nFinding content similar to item ID: {target_item_id}")
# Find the embedding for the target item
target_embedding = None
for item_data in content_embeddings_data:
if item_data["id"] == target_item_id:
target_embedding = item_data["embedding"]
break
if target_embedding is None:
print(f"Error: Could not find the embedding for the target item ID '{target_item_id}'.")
exit()
# 4. Calculate similarity between the target item and all other items
recommendations = []
print("\nCalculating similarities...")
for item_data in content_embeddings_data:
# Don't recommend the item itself
if item_data["id"] == target_item_id:
continue
similarity = cosine_similarity(target_embedding, item_data["embedding"])
recommendations.append({"id": item_data["id"], "score": similarity})
# 5. Sort potential recommendations by similarity score
recommendations.sort(key=lambda x: x["score"], reverse=True)
# 6. Display top N recommendations
print("\n--- Top Content Recommendations ---")
# Find the original title for the target item for context
target_item_info = next((item for item in content_catalog if item["id"] == target_item_id), None)
if target_item_info:
print(f"Because you read: \"{target_item_info['title']}\"\n")
if not recommendations:
print("No recommendations found (or error calculating similarities).")
else:
top_n = 3
print(f"Top {top_n} recommended items:")
for i, rec in enumerate(recommendations[:top_n]):
# Find the full item details from the original catalog
rec_details = next((item for item in content_catalog if item["id"] == rec["id"]), None)
if rec_details:
print(f"{i+1}. ID: {rec['id']}, Similarity Score: {rec['score']:.4f}")
print(f" Title: {rec_details['title']}")
print(f" Content Snippet: {rec_details['content'][:100]}...") # Truncate content
print("-" * 10)
else:
print(f"{i+1}. ID: {rec['id']}, Score: {rec['score']:.4f} (Details not found)")
print("-" * 10)
if len(recommendations) > top_n:
print(f"(Showing top {top_n} of {len(recommendations)} potential recommendations)")
print("\nNote: This demonstrates basic content-to-content similarity.")
print("Advanced systems incorporate user profiles, interaction history, context, etc.")
Explicación del Desglose del Código
Este script demuestra un enfoque fundamental para la recomendación de contenido utilizando embeddings de OpenAI, centrándose en encontrar elementos semánticamente similares a un elemento objetivo.
- Configuración y Funciones Auxiliares:
- Incluye importaciones estándar (
openai
,os
,dotenv
,numpy
), inicialización del cliente, y las funciones auxiliaresget_embedding
ycosine_similarity
.
- Incluye importaciones estándar (
- Catálogo de Contenido:
- Una lista de diccionarios (
content_catalog
) simula el contenido disponible (por ejemplo, artículos). Cada elemento tiene unid
,title
ycontent
.
- Una lista de diccionarios (
- Generación de Embeddings de Contenido (Pre-computación):
- El script itera sobre cada
item
en elcontent_catalog
. - Texto Combinado: Crea una cadena de texto combinada del
title
ycontent
del elemento para generar un embedding más rico que capture más detalle semántico. - Llama a
get_embedding
para este texto combinado. - Almacena el
item['id']
y su vectorembedding
encontent_embeddings_data
. Esta pre-computación es vital para la eficiencia.
- El script itera sobre cada
- Selección del Elemento Objetivo:
- Se elige un
target_item_id
(por ejemplo,art003
), simulando un elemento con el que el usuario ha interactuado (por ejemplo, leído). - El script recupera el embedding pre-computado para este elemento objetivo.
- Se elige un
- Cálculo de Similitud:
- Itera a través de todos los otros elementos en
content_embeddings_data
. - Calcula la
cosine_similarity
entre eltarget_embedding
y el embedding de cada otro elemento. - Almacena el
id
del otro elemento y suscore
de similitud en la listarecommendations
.
- Itera a través de todos los otros elementos en
- Clasificación de Recomendaciones:
- La lista
recommendations
se ordena porscore
en orden descendente, colocando primero los elementos de contenido más similares semánticamente.
- La lista
- Visualización de Resultados:
- El script muestra el título del elemento objetivo para dar contexto ("Porque has leído...").
- Muestra los N principales elementos recomendados (por ejemplo, 3), mostrando su ID, puntuación de similitud, título y un fragmento de su contenido.
- Nota Contextual: Las declaraciones finales mencionan explícitamente que este ejemplo muestra una similitud básica de contenido a contenido. Los sistemas de recomendación avanzados, como se describe en el texto de la sección, integrarían perfiles de usuario (embeddings basados en el historial de interacciones), contexto en tiempo real (tiempo, ubicación), retroalimentación explícita y potencialmente algoritmos más complejos más allá de la simple similitud del coseno. Sin embargo, el principio fundamental de usar embeddings para medir la relación semántica sigue siendo fundamental.
Este ejemplo ilustra efectivamente cómo los embeddings permiten recomendaciones basadas en la comprensión del significado del contenido, permitiendo sugerencias que van más allá de la simple coincidencia de palabras clave o categorías.
3.2.8 Clasificación y Priorización de Correos Electrónicos
La tecnología de embeddings permite un análisis y categorización sofisticados de correos electrónicos mediante la comprensión del significado semántico de los mensajes. Este sistema avanzado emplea múltiples capas de análisis para optimizar la gestión del correo electrónico:
- Detección de Urgencia
- Identificar asuntos urgentes que requieren atención inmediata mediante procesamiento del lenguaje natural
- Reconocer patrones de lenguaje urgente y señales contextuales analizando la elección de palabras, estructura de oraciones y patrones históricos
- Marcar correos críticos basándose en la importancia del remitente, palabras clave y jerarquía organizacional
- Categorización Inteligente
- Agrupar hilos de correo y conversaciones relacionadas mediante coincidencia de similitud semántica
- Clasificar mensajes por proyecto, departamento o función empresarial mediante análisis de contenido
- Crear carpetas dinámicas basadas en temas y tendencias emergentes
- Aplicar aprendizaje automático para mejorar la precisión de categorización con el tiempo
- Clasificación de Intención
- Distinguir entre solicitudes, actualizaciones y mensajes informativos mediante comprensión avanzada del lenguaje natural
- Priorizar elementos de acción y delegar tareas automáticamente según contenido y contexto
- Identificar requisitos de seguimiento y establecer recordatorios automáticos
- Extraer plazos y compromisos clave del contenido del mensaje
Al aprovechar la comprensión semántica, el sistema crea un proceso inteligente de procesamiento de correos electrónicos que puede manejar cientos de mensajes simultáneamente. El análisis basado en embeddings examina no solo palabras clave, sino el significado y contexto real de cada mensaje, considerando factores como:
- Contexto del mensaje dentro de conversaciones en curso
- Patrones históricos de comunicación
- Relaciones y jerarquías organizacionales
- Cronogramas y prioridades de proyectos
Este enfoque integral reduce significativamente la carga cognitiva de la gestión del correo electrónico al manejar automáticamente las tareas rutinarias de clasificación y priorización. El sistema asegura que los mensajes importantes reciban atención inmediata mientras mantiene una estructura organizada para todas las comunicaciones. Como resultado, los profesionales pueden concentrarse en actividades de alto valor en lugar de pasar horas clasificando manualmente su bandeja de entrada, lo que lleva a una mejor productividad y tiempos de respuesta más rápidos para comunicaciones críticas.
Ejemplo:
Este script simula la categorización de correos electrónicos entrantes basándose en su similitud semántica con categorías predefinidas como "Solicitud Urgente", "Actualización de Proyecto",
import os
from openai import OpenAI, OpenAIError
from dotenv import load_dotenv
import numpy as np # For cosine similarity calculation
import datetime
# --- Configuration ---
load_dotenv()
# Get the current date and location context
current_timestamp = "2024-10-31 15:54:00 CDT"
current_location = "Plano, Texas, United States"
print(f"Running Email Triage/Prioritization example at: {current_timestamp}")
print(f"Location Context: {current_location}")
# Initialize the OpenAI client
try:
api_key = os.getenv("OPENAI_API_KEY")
if not api_key:
raise ValueError("OPENAI_API_KEY not found in environment variables.")
client = OpenAI(api_key=api_key)
print("OpenAI client initialized.")
except ValueError as e:
print(f"Configuration Error: {e}")
exit()
except Exception as e:
print(f"Error initializing OpenAI client: {e}")
exit()
# Define the embedding model
EMBEDDING_MODEL = "text-embedding-3-small"
# --- Helper Function to Generate Embedding ---
# (Same as in previous embeddings examples)
def get_embedding(client, text, model=EMBEDDING_MODEL):
"""Generates an embedding for the given text using the specified model."""
print_text = text[:70] + "..." if len(text) > 70 else text
print(f"Generating embedding for: \"{print_text}\"")
try:
response = client.embeddings.create(
input=text,
model=model
)
embedding_vector = response.data[0].embedding
return embedding_vector
except OpenAIError as e:
print(f"OpenAI API Error generating embedding for text '{print_text}': {e}")
return None
except Exception as e:
print(f"An unexpected error occurred during embedding generation for text '{print_text}': {e}")
return None
# --- Helper Function for Cosine Similarity ---
# (Same as in previous embeddings examples)
def cosine_similarity(vec_a, vec_b):
"""Calculates the cosine similarity between two vectors."""
if vec_a is None or vec_b is None:
return 0.0
vec_a = np.array(vec_a)
vec_b = np.array(vec_b)
norm_a = np.linalg.norm(vec_a)
norm_b = np.linalg.norm(vec_b)
if norm_a == 0 or norm_b == 0:
return 0.0
else:
similarity = np.dot(vec_a, vec_b) / (norm_a * norm_b)
return np.clip(similarity, -1.0, 1.0) # Ensure value is within valid range
# --- Email Triage/Prioritization Implementation ---
# 1. Define Sample Emails (Subject + Snippet)
emails = [
{"id": "email01", "subject": "Urgent: Server Down!", "body_snippet": "The main production server seems to be unresponsive. We need immediate assistance to investigate and bring it back online."},
{"id": "email02", "subject": "Meeting Minutes - Project Phoenix Sync", "body_snippet": "Attached are the minutes from today's sync call. Key decisions included finalizing the Q3 roadmap. Action items assigned."},
{"id": "email03", "subject": "Quick Question about Report", "body_snippet": "Hi team, just had a quick question regarding the methodology used in the latest market analysis report. Can someone clarify?"},
{"id": "email04", "subject": "Fwd: Company Newsletter - April Edition", "body_snippet": "Sharing the latest company newsletter for your information."},
{"id": "email05", "subject": "Action Required: Submit Timesheet by EOD", "body_snippet": "Friendly reminder to please submit your weekly timesheet by the end of the day today. This is mandatory."},
{"id": "email06", "subject": "Update on Q2 Marketing Campaign", "body_snippet": "Just wanted to provide a brief update on the campaign performance metrics we discussed last week. See attached summary."},
{"id": "email07", "subject": "Can you approve this request ASAP?", "body_snippet": "Need your approval on the attached budget request urgently to proceed with the vendor contract."}
]
print(f"\nProcessing {len(emails)} emails.")
# 2. Define Categories/Priorities and their Semantic Representations
# We represent each category with a descriptive phrase.
categories = {
"Urgent Action Required": "Requires immediate attention, critical issue, deadline, ASAP request, mandatory task.",
"Project Update / Status": "Information about ongoing projects, progress reports, meeting minutes, status updates.",
"Question / Request for Info": "Asking for clarification, seeking information, query about details.",
"General Info / FYI": "Newsletter, announcement, sharing information, non-actionable update."
}
print(f"\nDefined categories: {list(categories.keys())}")
# 3. Generate embeddings for Categories (pre-computation recommended)
print("\nGenerating embeddings for categories...")
category_embeddings = {}
for category_name, category_description in categories.items():
embedding = get_embedding(client, category_description)
if embedding:
category_embeddings[category_name] = embedding
else:
print(f"Skipping category '{category_name}' due to embedding error.")
if not category_embeddings:
print("\nError: No embeddings generated for categories. Cannot triage emails.")
exit()
# 4. Process Each Email: Generate Embedding and Find Best Category
print("\nTriaging emails...")
email_results = []
for email in emails:
# Combine subject and body for better context
email_content = f"Subject: {email['subject']}\nBody: {email['body_snippet']}"
email_embedding = get_embedding(client, email_content)
if not email_embedding:
print(f"Skipping email {email['id']} due to embedding error.")
continue
# Find the category with the highest similarity
best_category = None
max_similarity = -1 # Cosine similarity ranges from -1 to 1
for category_name, category_embedding in category_embeddings.items():
similarity = cosine_similarity(email_embedding, category_embedding)
print(f" Email {email['id']} vs Category '{category_name}': Score {similarity:.4f}")
if similarity > max_similarity:
max_similarity = similarity
best_category = category_name
email_results.append({
"id": email["id"],
"subject": email["subject"],
"assigned_category": best_category,
"score": max_similarity
})
print(f"-> Email {email['id']} assigned to: '{best_category}' (Score: {max_similarity:.4f})")
# 5. Display Triage Results
print("\n--- Email Triage Results ---")
if not email_results:
print("No emails were successfully triaged.")
else:
# Optional: Group by category for display
results_by_category = {cat: [] for cat in categories.keys()}
for result in email_results:
if result["assigned_category"]: # Check if category was assigned
results_by_category[result["assigned_category"]].append(result)
for category_name, items in results_by_category.items():
print(f"\nCategory: {category_name}")
print("-" * (10 + len(category_name)))
if not items:
print(" (No emails assigned)")
else:
# Sort items within category by score if desired
items.sort(key=lambda x: x['score'], reverse=True)
for item in items:
print(f" - ID: {item['id']}, Subject: \"{item['subject']}\" (Score: {item['score']:.3f})")
print("\nEmail triage process complete.")
Explicación del Desglose del Código
Este ejemplo muestra cómo los embeddings de OpenAI pueden clasificar y priorizar automáticamente los correos electrónicos mediante la comprensión de su significado, demostrando un sistema inteligente de gestión de correos.
- Configuración y Funciones Auxiliares:
- Incluye importaciones estándar (
openai
,os
,dotenv
,numpy
), inicialización del cliente, y las funciones auxiliaresget_embedding
ycosine_similarity
.
- Incluye importaciones estándar (
- Datos de Ejemplo de Correos:
- Una lista de diccionarios (
emails
) simula mensajes entrantes. Cada correo tiene unid
,subject
, y unbody_snippet
.
- Una lista de diccionarios (
- Definiciones de Categorías:
- Un diccionario (
categories
) define las categorías objetivo para la clasificación (por ejemplo, "Acción Urgente Requerida", "Actualización de Proyecto / Estado"). - Idea Clave: Cada categoría está representada por una frase descriptiva o lista de palabras clave que captura su esencia semántica. Esta descripción es lo que será convertido en embedding.
- Un diccionario (
- Generación de Embeddings de Categorías:
- El script itera a través de las
categories
definidas. - Llama a
get_embedding
sobre la descripción asociada con cada nombre de categoría. - El vector de embedding resultante para cada categoría se almacena en el diccionario
category_embeddings
. Este paso típicamente sería pre-calculado y almacenado.
- El script itera a través de las
- Bucle de Procesamiento de Correos:
- El script itera a través de cada
email
en los datos de ejemplo. - Combinación de Contenido: Combina el
subject
ybody_snippet
en una única cadenaemail_content
para proporcionar un contexto más rico para el embedding. - Embedding del Correo: Llama a
get_embedding
para obtener la representación vectorial del contenido del correo actual. - Cálculo de Similitud:
- Luego itera a través de los
category_embeddings
pre-calculados. - Para cada categoría, calcula la
cosine_similarity
entre elemail_embedding
y elcategory_embedding
. - Mantiene un registro de la
best_category
(la que tiene el puntaje de similitud más alto encontrado hasta ahora) y el correspondiente puntajemax_similarity
.
- Luego itera a través de los
- Asignación: Después de comparar el correo con todas las categorías, se le asigna la
best_category
encontrada. El resultado (ID del correo, asunto, categoría asignada, puntaje) se almacena.
- El script itera a través de cada
- Visualización de Resultados de Clasificación:
- El script imprime las asignaciones finales.
- Agrupación Opcional: Incluye lógica para agrupar los resultados por categoría asignada para una presentación más clara, mostrando qué correos cayeron en los grupos "Urgente", "Actualización", etc.
Este ejemplo demuestra efectivamente cómo los embeddings permiten una categorización inteligente basada en el significado. Un correo solicitando "aprobación ASAP" puede ser correctamente identificado como "Acción Urgente Requerida" incluso sin usar la palabra exacta "urgente", porque su embedding será semánticamente cercano al embedding de la descripción de la categoría "Acción Urgente Requerida". Esto es mucho más robusto que el simple filtrado por palabras clave.
3.2 Cuándo Usar Embeddings
Los embeddings han revolucionado la forma en que procesamos y entendemos la información textual en las aplicaciones modernas de IA. Mientras que los métodos tradicionales de procesamiento de texto dependen de coincidencias exactas o búsquedas básicas por palabras clave, los embeddings proporcionan una forma sofisticada de capturar los significados matizados y las relaciones entre fragmentos de texto. Al convertir palabras y frases en vectores numéricos de alta dimensión, los embeddings permiten que las máquinas entiendan las relaciones semánticas y similitudes de manera que se asemejan más a la comprensión humana.
Exploremos los escenarios clave donde los embeddings resultan particularmente valiosos, mostrando cómo esta tecnología transforma varios aspectos del procesamiento y recuperación de información. Entender estos casos de uso es crucial para desarrolladores y organizaciones que buscan aprovechar todo el potencial de la tecnología de embeddings en sus aplicaciones.
3.2.1 Búsqueda semántica
Encontrar información relevante basada en el significado en lugar de solo palabras clave, permitiendo resultados de búsqueda más inteligentes. A diferencia de la búsqueda tradicional basada en palabras clave que coincide con palabras o frases exactas, la búsqueda semántica comprende la intención y el significado contextual de una consulta analizando las relaciones subyacentes entre palabras y conceptos. Este enfoque avanzado permite que el sistema comprenda variaciones en el lenguaje, contexto e incluso la intención del usuario.
Por ejemplo, una búsqueda de "procesamiento del lenguaje natural" también devolvería resultados relevantes sobre "PLN," "lingüística computacional" o "análisis de texto." Cuando un usuario busca "tratamiento de síntomas del resfriado común," el sistema entendería y devolvería resultados sobre "remedios para la gripe," "reducción de la fiebre" y "medicamentos para la tos" - incluso si estas frases exactas no se utilizan. Esta tecnología aprovecha los vectores de embedding para calcular puntajes de similitud entre consultas y documentos, transformando cada fragmento de texto en una representación numérica de alta dimensión que captura su significado semántico. Este enfoque matemático permite resultados de búsqueda más matizados y precisos que tienen en cuenta:
- Sinónimos y términos relacionados (como "coche" y "automóvil")
- Relaciones conceptuales (conectando "python" tanto con programación como con serpientes, dependiendo del contexto)
- Múltiples idiomas (encontrando contenido relevante incluso cuando está escrito en diferentes idiomas)
- Variaciones contextuales (entendiendo que "apple" puede referirse tanto a la fruta como a la empresa tecnológica)
- Coincidencia de intención (reconociendo que "cómo arreglar una llanta pinchada" e "instrucciones de reparación de neumáticos" buscan la misma información)
Ejemplo:
Aquí hay un ejemplo de código que demuestra la búsqueda semántica usando embeddings de OpenAI, basado en el contenido que proporcionaste.
Este script:
- Definirá un pequeño conjunto de documentos.
- Generará embeddings para estos documentos y una consulta de búsqueda.
- Calculará la similitud entre la consulta y cada documento.
- Clasificará los documentos por relevancia basándose en la similitud semántica.
import os
from openai import OpenAI, OpenAIError
from dotenv import load_dotenv
import numpy as np # For cosine similarity calculation
import datetime
# --- Configuration ---
load_dotenv()
# Get the current date and location context
current_timestamp = "2025-03-22 15:22:00 CDT"
current_location = "Grapevine, Texas, United States"
print(f"Running Semantic Search example at: {current_timestamp}")
print(f"Location Context: {current_location}")
# Initialize the OpenAI client
try:
api_key = os.getenv("OPENAI_API_KEY")
if not api_key:
raise ValueError("OPENAI_API_KEY not found in environment variables.")
client = OpenAI(api_key=api_key)
print("OpenAI client initialized.")
except ValueError as e:
print(f"Configuration Error: {e}")
exit()
except Exception as e:
print(f"Error initializing OpenAI client: {e}")
exit()
# Define the embedding model
EMBEDDING_MODEL = "text-embedding-3-small"
# --- Helper Function to Generate Embedding ---
# (Same as in previous embeddings example)
def get_embedding(client, text, model=EMBEDDING_MODEL):
"""Generates an embedding for the given text using the specified model."""
print(f"Generating embedding for: \"{text[:50]}...\"") # Print truncated text
try:
response = client.embeddings.create(
input=text,
model=model
)
embedding_vector = response.data[0].embedding
print("Embedding generation successful.")
return embedding_vector
except OpenAIError as e:
print(f"OpenAI API Error generating embedding for text '{text[:50]}...': {e}")
return None
except Exception as e:
print(f"An unexpected error occurred during embedding generation for text '{text[:50]}...': {e}")
return None
# --- Helper Function for Cosine Similarity ---
# (Same as in previous embeddings example)
def cosine_similarity(vec_a, vec_b):
"""Calculates the cosine similarity between two vectors."""
if vec_a is None or vec_b is None:
# print("Error: Cannot calculate similarity with None vectors.")
return 0.0 # Return 0 if any vector is missing
vec_a = np.array(vec_a)
vec_b = np.array(vec_b)
norm_a = np.linalg.norm(vec_a)
norm_b = np.linalg.norm(vec_b)
if norm_a == 0 or norm_b == 0:
# print("Warning: One or both vectors have zero magnitude.")
return 0.0
else:
similarity = np.dot(vec_a, vec_b) / (norm_a * norm_b)
return similarity
# --- Semantic Search Implementation ---
# 1. Define your document store (a list of text strings)
# In a real application, this could come from a database, files, etc.
document_store = [
"The Eiffel Tower is a wrought-iron lattice tower on the Champ de Mars in Paris, France.",
"Photosynthesis is a process used by plants and other organisms to convert light energy into chemical energy.",
"Artificial intelligence research focuses on creating systems capable of performing tasks that typically require human intelligence.",
"A recipe for classic French onion soup involves caramelizing onions and topping with bread and cheese.",
"Machine learning, a subset of AI, involves algorithms that allow systems to learn from data.",
"The Louvre Museum in Paris is the world's largest art museum and a historic monument.",
"Natural Language Processing (NLP) enables computers to understand and process human language.",
"Baking bread requires careful measurement of ingredients like flour, water, yeast, and salt."
]
print(f"\nDocument store contains {len(document_store)} documents.")
# 2. Generate embeddings for all documents in the store (pre-computation)
# In a real app, you'd store these embeddings alongside the documents.
print("\nGenerating embeddings for the document store...")
document_embeddings = []
for doc in document_store:
embedding = get_embedding(client, doc)
# Store the document text and its embedding together
if embedding: # Only store if embedding was successful
document_embeddings.append({"text": doc, "embedding": embedding})
else:
print(f"Skipping document due to embedding error: \"{doc[:50]}...\"")
print(f"\nSuccessfully generated embeddings for {len(document_embeddings)} documents.")
# 3. Define the user's search query
search_query = "What is AI?"
# search_query = "Things to see in Paris"
# search_query = "How does NLP work?"
# search_query = "Cooking instructions"
print(f"\nSearch Query: \"{search_query}\"")
# 4. Generate embedding for the search query
print("\nGenerating embedding for the search query...")
query_embedding = get_embedding(client, search_query)
# 5. Calculate similarity and rank documents
search_results = []
if query_embedding and document_embeddings:
print("\nCalculating similarities...")
for doc_data in document_embeddings:
similarity = cosine_similarity(query_embedding, doc_data["embedding"])
search_results.append({"text": doc_data["text"], "score": similarity})
# Sort results by similarity score in descending order
search_results.sort(key=lambda x: x["score"], reverse=True)
# 6. Display results
print("\n--- Semantic Search Results ---")
print(f"Top results for query: \"{search_query}\"\n")
if not search_results:
print("No results found (or error calculating similarities).")
else:
# Display top N results (e.g., top 3)
top_n = 3
for i, result in enumerate(search_results[:top_n]):
print(f"{i+1}. Score: {result['score']:.4f}")
print(f" Text: {result['text']}")
print("-" * 10)
if len(search_results) > top_n:
print(f"(Showing top {top_n} of {len(search_results)} results)")
else:
print("\nCould not perform search.")
if not query_embedding:
print("Reason: Failed to generate embedding for the search query.")
if not document_embeddings:
print("Reason: No document embeddings were successfully generated.")
Explicación del Desglose del Código:
- Configuración y Funciones Auxiliares: Incluye importaciones estándar (
openai
,os
,dotenv
,numpy
), inicialización del cliente, y las funciones auxiliaresget_embedding
ycosine_similarity
del ejemplo anterior. - Almacén de Documentos: Una lista simple de Python (
document_store
) contiene el texto de los documentos que queremos buscar. En una aplicación real, estos datos probablemente provendrían de una base de datos o sistema de archivos. - Generación de Embeddings de Documentos:
- El script itera a través de cada documento en el
document_store
. - Llama a
get_embedding
para cada documento para obtener su representación numérica. - Almacena el texto original del documento y su vector de embedding correspondiente juntos (por ejemplo, en una lista de diccionarios). Este paso de pre-computación es crucial para la eficiencia en sistemas reales – generas los embeddings de documentos una vez y los almacenas. El manejo de errores asegura que los documentos se omitan si falla la generación del embedding.
- El script itera a través de cada documento en el
- Consulta de Búsqueda: Se define una cadena de ejemplo
search_query
. - Generación del Embedding de Consulta: La función
get_embedding
se llama nuevamente, esta vez para elsearch_query
. - Cálculo de Similitud y Clasificación:
- Verifica si tanto el embedding de consulta como los embeddings de documentos se generaron exitosamente.
- Itera a través de los
document_embeddings
almacenados. - Para cada documento, calcula la
cosine_similarity
entre elquery_embedding
y el embedding del documento. - El texto del documento y su puntaje de similitud calculado se almacenan en una lista
search_results
. - Finalmente,
search_results.sort(...)
ordena la lista basándose en elscore
en orden descendente (mayor similitud primero).
- Mostrar Resultados: El script imprime los N (por ejemplo, 3) documentos más relevantes de la lista ordenada, mostrando su puntaje de similitud y contenido de texto.
Este ejemplo ilustra claramente el concepto central de la búsqueda semántica: convertir tanto los documentos como las consultas en embeddings y luego usar la similitud vectorial (como la similitud del coseno) para encontrar documentos que están semánticamente relacionados con la consulta, incluso si no comparten las palabras clave exactas.
3.2.2 Agrupamiento por temas
El agrupamiento por temas es una técnica sofisticada para organizar y analizar grandes colecciones de documentos mediante su agrupación automática basada en su contenido semántico. Esta aplicación avanzada de embeddings transforma la manera en que procesamos y entendemos colecciones de documentos a gran escala, ofreciendo una poderosa solución para la organización de contenido. El sistema funciona convirtiendo cada documento en un vector de embedding multidimensional que captura su significado, y luego utiliza algoritmos de agrupamiento para juntar vectores similares.
Esta poderosa aplicación de embeddings permite a los sistemas:
- Identificar patrones temáticos a través de miles de documentos sin etiquetado manual - el sistema puede detectar automáticamente temas y tendencias comunes a través de vastas colecciones de documentos, ahorrando incontables horas de trabajo de categorización manual
- Agrupar discusiones, artículos o piezas de contenido similares en categorías intuitivas - al comprender las relaciones semánticas entre documentos, el sistema puede crear agrupaciones significativas que reflejan divisiones naturales de temas, incluso cuando los documentos utilizan terminología diferente para discutir los mismos conceptos
- Descubrir temas y tendencias emergentes dentro de grandes colecciones de documentos - a medida que se agrega nuevo contenido, el sistema puede identificar nuevos grupos temáticos que se están formando, ayudando a las organizaciones a mantenerse al día con las tendencias en desarrollo en su campo
- Crear jerarquías de contenido dinámicas que se adaptan cuando se agregan nuevos documentos - a diferencia de los sistemas de categorización estática tradicionales, el agrupamiento basado en embeddings puede reorganizar y refinar automáticamente las estructuras de categorías a medida que la colección de contenido crece y evoluciona
Por ejemplo, una organización de noticias podría usar el agrupamiento por temas para agrupar automáticamente miles de artículos en categorías como "Tecnología", "Política" o "Deportes", incluso cuando estos temas no están etiquetados explícitamente. Los embeddings capturan las relaciones semánticas entre artículos analizando el significado real y el contexto del contenido, no solo palabras clave. Esto permite un agrupamiento mucho más sofisticado que puede entender distinciones sutiles - por ejemplo, reconociendo que un artículo sobre el impacto económico de los estadios deportivos pertenece tanto a las categorías "Deportes" como "Negocios", o que artículos sobre diferentes lenguajes de programación pertenecen todos a un grupo de "Tecnología" a pesar de usar terminología completamente diferente.
Ejemplo:
A continuación se muestra un ejemplo de código que demuestra el agrupamiento por temas usando embeddings de OpenAI y el algoritmo K-means de scikit-learn
.
Este código:
- Definirá una lista de documentos de ejemplo que cubren diferentes temas implícitos.
- Generará embeddings para cada documento usando la API de OpenAI.
- Aplicará el algoritmo de agrupamiento K-Means para agrupar los vectores de embedding.
- Mostrará los documentos pertenecientes a cada grupo identificado.
import os
from openai import OpenAI, OpenAIError
from dotenv import load_dotenv
import numpy as np
from sklearn.cluster import KMeans # For clustering algorithm
import datetime
# --- Configuration ---
load_dotenv()
# Get the current date and location context
current_timestamp = "2025-03-23 15:26:00 CDT"
current_location = "Dallas, Texas, United States"
print(f"Running Topic Clustering example at: {current_timestamp}")
print(f"Location Context: {current_location}")
# Initialize the OpenAI client
try:
api_key = os.getenv("OPENAI_API_KEY")
if not api_key:
raise ValueError("OPENAI_API_KEY not found in environment variables.")
client = OpenAI(api_key=api_key)
print("OpenAI client initialized.")
except ValueError as e:
print(f"Configuration Error: {e}")
exit()
except Exception as e:
print(f"Error initializing OpenAI client: {e}")
exit()
# Define the embedding model
EMBEDDING_MODEL = "text-embedding-3-small"
# --- Helper Function to Generate Embedding ---
# (Same as in previous embeddings examples)
def get_embedding(client, text, model=EMBEDDING_MODEL):
"""Generates an embedding for the given text using the specified model."""
# Truncate text for printing if it's too long
print_text = text[:70] + "..." if len(text) > 70 else text
print(f"Generating embedding for: \"{print_text}\"")
try:
response = client.embeddings.create(
input=text,
model=model
)
embedding_vector = response.data[0].embedding
# print("Embedding generation successful.") # Reduce verbosity
return embedding_vector
except OpenAIError as e:
print(f"OpenAI API Error generating embedding for text '{print_text}': {e}")
return None
except Exception as e:
print(f"An unexpected error occurred during embedding generation for text '{print_text}': {e}")
return None
# --- Topic Clustering Implementation ---
# 1. Define your collection of documents
# These documents cover roughly 3 topics: AI/Tech, Travel/Geography, Food/Cooking
documents = [
"Artificial intelligence research focuses on creating systems capable of performing tasks that typically require human intelligence.",
"The Eiffel Tower is a wrought-iron lattice tower on the Champ de Mars in Paris, France.",
"A recipe for classic French onion soup involves caramelizing onions and topping with bread and cheese.",
"Machine learning, a subset of AI, involves algorithms that allow systems to learn from data.",
"The Great Wall of China is a series of fortifications made of stone, brick, tamped earth, wood, and other materials.",
"Natural Language Processing (NLP) enables computers to understand and process human language.",
"Baking bread requires careful measurement of ingredients like flour, water, yeast, and salt.",
"The Colosseum in Rome, Italy, is an oval amphitheatre in the centre of the city.",
"Deep learning utilizes artificial neural networks with multiple layers to model complex patterns.",
"Sushi is a traditional Japanese dish of prepared vinegared rice, usually with some sugar and salt, accompanying a variety of ingredients, such as seafood, often raw, and vegetables."
]
print(f"\nDocument collection contains {len(documents)} documents.")
# 2. Generate embeddings for all documents
print("\nGenerating embeddings for the document collection...")
embeddings = []
valid_documents = [] # Keep track of documents for which embedding was successful
for doc in documents:
embedding = get_embedding(client, doc)
if embedding:
embeddings.append(embedding)
valid_documents.append(doc) # Add corresponding document text
else:
print(f"Skipping document due to embedding error: \"{doc[:70]}...\"")
if not embeddings:
print("\nError: No embeddings were generated. Cannot perform clustering.")
exit()
print(f"\nSuccessfully generated embeddings for {len(valid_documents)} documents.")
# Convert embeddings list to a NumPy array for scikit-learn
embedding_matrix = np.array(embeddings)
# 3. Apply Clustering Algorithm (K-Means)
# We need to choose the number of clusters (k). Let's assume we expect 3 topics.
# In real applications, determining the optimal 'k' often requires experimentation
# (e.g., using the elbow method or silhouette scores).
n_clusters = 3
print(f"\nApplying K-Means clustering with k={n_clusters}...")
try:
kmeans = KMeans(n_clusters=n_clusters, random_state=42, n_init=10) # n_init suppresses warning
kmeans.fit(embedding_matrix)
cluster_labels = kmeans.labels_
print("Clustering complete.")
except Exception as e:
print(f"An error occurred during clustering: {e}")
exit()
# 4. Display Documents by Cluster
print(f"\n--- Documents Grouped by Topic Cluster (k={n_clusters}) ---")
# Create a dictionary to hold documents for each cluster
clustered_documents = {i: [] for i in range(n_clusters)}
# Assign each document (that had a valid embedding) to its cluster
for i, label in enumerate(cluster_labels):
clustered_documents[label].append(valid_documents[i])
# Print the contents of each cluster
for cluster_id, docs_in_cluster in clustered_documents.items():
print(f"\nCluster {cluster_id + 1}:")
if not docs_in_cluster:
print(" (No documents in this cluster)")
else:
for doc_text in docs_in_cluster:
# Print truncated document text for readability
print_text = doc_text[:100] + "..." if len(doc_text) > 100 else doc_text
print(f" - {print_text}")
print("-" * 20)
print("\nNote: The quality of clustering depends on the data, the embedding model,")
print("and the chosen number of clusters (k). Cluster numbers are arbitrary.")
Explicación del Desglose del Código:
- Configuración y Funciones Auxiliares:
- Incluye importaciones estándar más
KMeans
desklearn.cluster
. - Inicializa el cliente de OpenAI.
- Incluye la función auxiliar
get_embedding
(igual que antes).
- Incluye importaciones estándar más
- Colección de Documentos: Una lista llamada
documents
contiene el contenido de texto. Los documentos de muestra están elegidos para representar algunos temas subyacentes distintos (IA/Tecnología, Viajes/Geografía, Comida/Cocina). - Generación de Embeddings:
- El script itera a través de los
documents
. - Llama a
get_embedding
para cada documento. - Almacena los embeddings exitosos en la lista
embeddings
y el texto del documento correspondiente envalid_documents
. Esto asegura que los índices coincidan posteriormente. - El manejo de errores omite documentos si falla la generación del embedding.
- La lista de vectores de embedding se convierte en un array de NumPy (
embedding_matrix
), que es el formato de entrada estándar para los algoritmos descikit-learn
.
- El script itera a través de los
- Agrupamiento (K-Means):
- Elección de
k
: El número de grupos (n_clusters
) se establece (aquí,k=3
, asumiendo que esperamos tres temas basados en los datos de muestra). Un comentario destaca que encontrar elk
óptimo es frecuentemente una tarea separada en escenarios del mundo real. - Inicialización: Se crea un objeto
KMeans
.n_clusters
especifica el número deseado de grupos.random_state
asegura la reproducibilidad.n_init=10
ejecuta el algoritmo múltiples veces con diferentes centroides iniciales y elige el mejor resultado (suprime una advertencia futura). - Ajuste:
kmeans.fit(embedding_matrix)
ejecuta el algoritmo de agrupamiento K-Means en los embeddings de documentos. Encuentra los centros de los grupos y asigna cada vector de embedding al centro más cercano. - Etiquetas:
kmeans.labels_
contiene un array donde cada elemento indica el ID del grupo (0, 1, 2, etc.) asignado al embedding del documento correspondiente.
- Elección de
- Mostrar Resultados:
- Se crea un diccionario (
clustered_documents
) para organizar los resultados, con claves que representan los IDs de los grupos. - El script itera a través de las
cluster_labels
asignadas por K-Means. Para cada índicei
de documento, encuentra sulabel
asignada y añade el texto correspondiente devalid_documents[i]
a la lista para ese ID de grupo en el diccionario. - Finalmente, recorre el diccionario
clustered_documents
e imprime el texto de los documentos pertenecientes a cada grupo, agrupándolos claramente por el grupo temático identificado por el algoritmo.
- Se crea un diccionario (
Este ejemplo demuestra el poder de los embeddings para el descubrimiento de temas no supervisado. Al convertir texto en vectores, podemos usar algoritmos matemáticos como K-Means para agrupar documentos semánticamente similares sin necesidad de etiquetas predefinidas.
3.2.3 Sistemas de Recomendación
Sugerir elementos relacionados mediante la comprensión de las conexiones más profundas entre diferentes piezas de contenido. Esta poderosa aplicación de los embeddings permite a los sistemas proporcionar recomendaciones personalizadas analizando las relaciones semánticas entre elementos. Los vectores de embedding capturan patrones sutiles y similitudes que podrían no ser inmediatamente obvios para los observadores humanos.
Así es como los sistemas de recomendación aprovechan los embeddings:
- Filtrado Basado en Contenido
- Los sistemas analizan las características reales del contenido (como descripciones de texto, características o atributos)
- Cada elemento se convierte en un vector de embedding que representa sus características principales
- Los elementos similares se encuentran midiendo la distancia entre estos vectores
- Mejora del Filtrado Colaborativo
- Los comportamientos y preferencias de los usuarios también se convierten en embeddings
- El sistema puede identificar patrones en las interacciones usuario-elemento
- Esto ayuda a predecir qué elementos podría gustarle a un usuario basándose en las preferencias de usuarios similares
Por ejemplo, un servicio de streaming de video puede recomendar programas no solo basándose en etiquetas de género, sino entendiendo elementos temáticos, estilos narrativos y patrones narrativos complejos. Los vectores de embedding pueden capturar características matizadas como:
- Ritmo y complejidad de la trama
- Estilos de desarrollo de personajes
- Tono emocional y atmósfera
- Técnicas visuales y de dirección
De manera similar, las plataformas de comercio electrónico pueden sugerir productos entendiendo las similitudes contextuales en las descripciones de productos, el comportamiento del usuario y las características de los artículos. Esto incluye analizar:
- Descripciones y características de productos
- Patrones de navegación y compra de usuarios
- Niveles de precio y calidad
- Relaciones entre marcas y posicionamiento en el mercado
Esta comprensión semántica lleva a recomendaciones más precisas y relevantes en comparación con los métodos tradicionales que dependen únicamente de categorías explícitas o calificaciones de usuarios. El sistema puede identificar conexiones sutiles y patrones que podrían pasarse por alto con enfoques convencionales de recomendación, resultando en experiencias de usuario más atractivas y personalizadas.
Ejemplo:
El siguiente ejemplo de código demuestra cómo los embeddings de OpenAI pueden utilizarse para construir un sistema de recomendación simple basado en contenido.
Este script:
- Definirá un pequeño catálogo de elementos (por ejemplo, descripciones de películas).
- Generará embeddings para estos elementos.
- Elegirá un elemento objetivo.
- Encontrará otros elementos en el catálogo que sean semánticamente similares al elemento objetivo basándose en sus embeddings.
- Presentará los elementos más similares como recomendaciones.
import os
from openai import OpenAI, OpenAIError
from dotenv import load_dotenv
import numpy as np # For cosine similarity calculation
import datetime
# --- Configuration ---
load_dotenv()
# Get the current date and location context
current_timestamp = "2025-03-24 15:29:00 CDT"
current_location = "Austin, Texas, United States"
print(f"Running Recommendation System example at: {current_timestamp}")
print(f"Location Context: {current_location}")
# Initialize the OpenAI client
try:
api_key = os.getenv("OPENAI_API_KEY")
if not api_key:
raise ValueError("OPENAI_API_KEY not found in environment variables.")
client = OpenAI(api_key=api_key)
print("OpenAI client initialized.")
except ValueError as e:
print(f"Configuration Error: {e}")
exit()
except Exception as e:
print(f"Error initializing OpenAI client: {e}")
exit()
# Define the embedding model
EMBEDDING_MODEL = "text-embedding-3-small"
# --- Helper Function to Generate Embedding ---
# (Same as in previous embeddings examples)
def get_embedding(client, text, model=EMBEDDING_MODEL):
"""Generates an embedding for the given text using the specified model."""
# Truncate text for printing if it's too long
print_text = text[:70] + "..." if len(text) > 70 else text
print(f"Generating embedding for: \"{print_text}\"")
try:
response = client.embeddings.create(
input=text,
model=model
)
embedding_vector = response.data[0].embedding
# print("Embedding generation successful.") # Reduce verbosity
return embedding_vector
except OpenAIError as e:
print(f"OpenAI API Error generating embedding for text '{print_text}': {e}")
return None
except Exception as e:
print(f"An unexpected error occurred during embedding generation for text '{print_text}': {e}")
return None
# --- Helper Function for Cosine Similarity ---
# (Same as in previous embeddings examples)
def cosine_similarity(vec_a, vec_b):
"""Calculates the cosine similarity between two vectors."""
if vec_a is None or vec_b is None:
return 0.0 # Return 0 if any vector is missing
vec_a = np.array(vec_a)
vec_b = np.array(vec_b)
norm_a = np.linalg.norm(vec_a)
norm_b = np.linalg.norm(vec_b)
if norm_a == 0 or norm_b == 0:
return 0.0
else:
similarity = np.dot(vec_a, vec_b) / (norm_a * norm_b)
return similarity
# --- Recommendation System Implementation ---
# 1. Define your item catalog (e.g., movie descriptions)
# In a real application, this would come from a database.
item_catalog = [
{"id": "mov001", "title": "Space Odyssey: The Final Frontier", "description": "A visually stunning sci-fi epic exploring humanity's place in the universe, featuring complex themes and groundbreaking special effects."},
{"id": "mov002", "title": "Galactic Wars: Attack of the Clones", "description": "An action-packed space opera with laser battles, alien creatures, and a classic good versus evil storyline."},
{"id": "com001", "title": "Laugh Riot", "description": "A slapstick comedy about mistaken identities and hilarious mishaps during a weekend getaway."},
{"id": "doc001", "title": "Wonders of the Deep", "description": "An awe-inspiring documentary showcasing the beauty and mystery of marine life in the world's oceans."},
{"id": "mov003", "title": "Cyber City 2077", "description": "A gritty cyberpunk thriller set in a dystopian future, exploring themes of technology, consciousness, and rebellion."},
{"id": "com002", "title": "The Office Party", "description": "A witty ensemble comedy centered around awkward interactions and office politics during an annual holiday celebration."},
{"id": "doc002", "title": "Cosmic Journeys", "description": "A documentary exploring the vastness of space, black holes, distant galaxies, and the search for extraterrestrial life."},
{"id": "mov004", "title": "Interstellar Echoes", "description": "A philosophical science fiction film about astronauts travelling through a wormhole in search of a new home for humanity."}
]
print(f"\nItem catalog contains {len(item_catalog)} items.")
# 2. Generate embeddings for all items in the catalog (pre-computation)
print("\nGenerating embeddings for the item catalog...")
item_embeddings_data = []
for item in item_catalog:
# Combine title and description for a richer embedding
text_to_embed = f"{item['title']}: {item['description']}"
embedding = get_embedding(client, text_to_embed)
if embedding:
# Store item ID and its embedding
item_embeddings_data.append({"id": item["id"], "embedding": embedding})
else:
print(f"Skipping item {item['id']} due to embedding error.")
if not item_embeddings_data:
print("\nError: No embeddings were generated. Cannot provide recommendations.")
exit()
print(f"\nSuccessfully generated embeddings for {len(item_embeddings_data)} items.")
# 3. Select a target item for which to find recommendations
target_item_id = "mov001" # Let's find movies similar to "Space Odyssey"
print(f"\nFinding recommendations similar to item ID: {target_item_id}")
# Find the embedding for the target item
target_embedding = None
for item_data in item_embeddings_data:
if item_data["id"] == target_item_id:
target_embedding = item_data["embedding"]
break
if target_embedding is None:
print(f"Error: Could not find the embedding for the target item ID '{target_item_id}'.")
exit()
# 4. Calculate similarity between the target item and all other items
recommendations = []
print("\nCalculating similarities...")
for item_data in item_embeddings_data:
# Don't compare the item with itself
if item_data["id"] == target_item_id:
continue
similarity = cosine_similarity(target_embedding, item_data["embedding"])
recommendations.append({"id": item_data["id"], "score": similarity})
# 5. Sort potential recommendations by similarity score
recommendations.sort(key=lambda x: x["score"], reverse=True)
# 6. Display top N recommendations
print("\n--- Top Recommendations ---")
# Find the original title/description for the target item for context
target_item_info = next((item for item in item_catalog if item["id"] == target_item_id), None)
if target_item_info:
print(f"Based on: \"{target_item_info['title']}\"\n")
if not recommendations:
print("No recommendations found (or error calculating similarities).")
else:
top_n = 3
print(f"Top {top_n} most similar items:")
for i, rec in enumerate(recommendations[:top_n]):
# Find the full item details from the original catalog
rec_details = next((item for item in item_catalog if item["id"] == rec["id"]), None)
if rec_details:
print(f"{i+1}. ID: {rec['id']}, Score: {rec['score']:.4f}")
print(f" Title: {rec_details['title']}")
print(f" Description: {rec_details['description'][:100]}...") # Truncate description
print("-" * 10)
else:
print(f"{i+1}. ID: {rec['id']}, Score: {rec['score']:.4f} (Details not found)")
print("-" * 10)
if len(recommendations) > top_n:
print(f"(Showing top {top_n} of {len(recommendations)} potential recommendations)")
Explicación del Desglose del Código
Este ejemplo demuestra cómo construir un sistema de recomendación basado en contenido de manera sencilla combinando los embeddings de OpenAI con cálculos de similitud del coseno.
- Configuración y Funciones Auxiliares:
- Incluye importaciones estándar (
openai
,os
,dotenv
,numpy
), inicialización del cliente, y las funciones auxiliaresget_embedding
ycosine_similarity
previamente definidas.
- Incluye importaciones estándar (
- Catálogo de Elementos:
- Una lista de diccionarios (
item_catalog
) representa los elementos disponibles para recomendación (por ejemplo, películas). Cada elemento tiene unid
,título
ydescripción
. En un sistema real, esto probablemente se cargaría desde una base de datos.
- Una lista de diccionarios (
- Generación de Embeddings de Elementos:
- El script itera a través de cada
item
en elitem_catalog
. - Combinación de Contenido: Combina el
título
y ladescripción
en una sola cadena (text_to_embed
). Esto proporciona un contexto más rico al modelo de embedding que usar solo el título o la descripción por separado. - Llama a
get_embedding
para este texto combinado. - Almacena el
item['id']
y su vector deembedding
correspondiente juntos en la listaitem_embeddings_data
. Este paso de pre-cómputo es una práctica estándar para sistemas de recomendación.
- El script itera a través de cada
- Selección del Elemento Objetivo:
- Una variable
target_item_id
se establece para especificar el elemento para el cual queremos recomendaciones (por ejemplo, encontrar elementos similares amov001
). - El script recupera el vector de embedding pre-calculado para este
target_item_id
de la listaitem_embeddings_data
.
- Una variable
- Cálculo de Similitud:
- Itera a través de todos los elementos con embeddings en
item_embeddings_data
. - Exclusión: Explícitamente omite la comparación si el ID del elemento actual coincide con el
target_item_id
(un elemento no debería recomendarse a sí mismo). - Para cada otro elemento, calcula la
similitud_coseno
entre eltarget_embedding
y el embedding del elemento actual. - Almacena el
id
del otro elemento y supuntuación
de similitud calculada en una lista derecommendations
.
- Itera a través de todos los elementos con embeddings en
- Clasificación de Recomendaciones:
- La lista
recommendations
se ordena usandorecommendations.sort(...)
basándose en el camposcore
en orden descendente, colocando los elementos más similares al principio de la lista.
- La lista
- Mostrar Resultados:
- El script imprime el título del elemento objetivo para contexto.
- Luego itera a través de los N principales (por ejemplo, 3) elementos en la lista ordenada de
recommendations
. - Para cada ID de elemento recomendado, busca los detalles completos (título, descripción) del
item_catalog
original. - Imprime el rango, ID, puntuación de similitud, título y una descripción truncada para cada elemento recomendado.
Este ejemplo muestra efectivamente cómo los embeddings capturan el significado semántico, permitiendo que el sistema recomiende elementos basándose en la similitud de contenido (por ejemplo, recomendando otras películas de ciencia ficción filosóficas similares a "Space Odyssey") en lugar de solo etiquetas explícitas o historial del usuario.
3.2.4 Recuperación de contexto para asistentes de IA
Ayudar a los chatbots y sistemas de IA a encontrar y utilizar información relevante de grandes bases de conocimiento mediante la conversión tanto de consultas como de conocimiento almacenado en embeddings. Este proceso involucra varios pasos clave:
Primero, el sistema convierte todos los documentos en su base de conocimiento en vectores de embedding - representaciones numéricas que capturan el significado semántico del texto. Estos embeddings se almacenan en una base de datos vectorial para una recuperación rápida.
Cuando un asistente de IA recibe una pregunta, convierte esa consulta en un vector de embedding usando el mismo proceso. Esto asegura que tanto el conocimiento almacenado como las preguntas entrantes estén representados en el mismo espacio matemático.
El sistema luego realiza una búsqueda de similitud para encontrar la información más relevante. Esta búsqueda compara el embedding de la consulta con todos los embeddings almacenados, típicamente usando técnicas como similitud del coseno o búsqueda del vecino más cercano. La belleza de este enfoque es que puede identificar contenido semánticamente similar incluso cuando la redacción exacta difiere significativamente.
Por ejemplo, una consulta sobre "el portátil no enciende" podría coincidir con documentación sobre "problemas de energía en computadoras" porque sus embeddings capturan el significado subyacente similar. Esta coincidencia semántica es mucho más potente que la búsqueda tradicional basada en palabras clave.
Una vez que se identifica la información relevante, puede utilizarse para generar respuestas más precisas e informadas. Esto es particularmente potente para aplicaciones específicas de dominio donde la IA necesita acceder a documentación técnica, información de productos o políticas empresariales. El sistema puede manejar consultas complejas combinando múltiples piezas de contexto relevante, asegurando que las respuestas sean tanto precisas como exhaustivas.
Ejemplo:
A continuación se muestra un ejemplo de código que demuestra cómo los asistentes de IA pueden recuperar contexto usando embeddings de OpenAI, implementando los conceptos discutidos en la sección 3.2.4.
El script ilustra el proceso esencial de búsqueda en una base de conocimiento para proporcionar contexto relevante para las respuestas del asistente de IA.
import os
from openai import OpenAI, OpenAIError
from dotenv import load_dotenv
import numpy as np # For cosine similarity calculation
import datetime
# --- Configuration ---
load_dotenv()
# Get the current date and location context
current_timestamp = "2025-02-10 15:35:00 CDT"
current_location = "Grapevine, Texas, United States"
print(f"Running Context Retrieval example at: {current_timestamp}")
print(f"Location Context: {current_location}")
# Initialize the OpenAI client
try:
api_key = os.getenv("OPENAI_API_KEY")
if not api_key:
raise ValueError("OPENAI_API_KEY not found in environment variables.")
client = OpenAI(api_key=api_key)
print("OpenAI client initialized.")
except ValueError as e:
print(f"Configuration Error: {e}")
exit()
except Exception as e:
print(f"Error initializing OpenAI client: {e}")
exit()
# Define the embedding model
EMBEDDING_MODEL = "text-embedding-3-small"
# --- Helper Function to Generate Embedding ---
# (Same as in previous embeddings examples)
def get_embedding(client, text, model=EMBEDDING_MODEL):
"""Generates an embedding for the given text using the specified model."""
print_text = text[:70] + "..." if len(text) > 70 else text
print(f"Generating embedding for: \"{print_text}\"")
try:
response = client.embeddings.create(
input=text,
model=model
)
embedding_vector = response.data[0].embedding
return embedding_vector
except OpenAIError as e:
print(f"OpenAI API Error generating embedding for text '{print_text}': {e}")
return None
except Exception as e:
print(f"An unexpected error occurred during embedding generation for text '{print_text}': {e}")
return None
# --- Helper Function for Cosine Similarity ---
# (Same as in previous embeddings examples)
def cosine_similarity(vec_a, vec_b):
"""Calculates the cosine similarity between two vectors."""
if vec_a is None or vec_b is None:
return 0.0
vec_a = np.array(vec_a)
vec_b = np.array(vec_b)
norm_a = np.linalg.norm(vec_a)
norm_b = np.linalg.norm(vec_b)
if norm_a == 0 or norm_b == 0:
return 0.0
else:
similarity = np.dot(vec_a, vec_b) / (norm_a * norm_b)
return similarity
# --- Context Retrieval Implementation ---
# 1. Define your Knowledge Base (list of text documents/chunks)
# This represents the information the AI assistant can draw upon.
knowledge_base = [
{"id": "doc001", "source": "troubleshooting_guide.txt", "content": "If your laptop fails to power on, first check the power adapter connection. Ensure the cable is securely plugged into both the laptop and the wall outlet. Try a different outlet if possible."},
{"id": "doc002", "source": "troubleshooting_guide.txt", "content": "A blinking power light often indicates a battery issue or a charging problem. Try removing the battery (if removable) and powering on with only the adapter connected."},
{"id": "doc003", "source": "faq.html", "content": "To reset your password, go to the login page and click the 'Forgot Password' link. Follow the instructions sent to your registered email address."},
{"id": "doc004", "source": "product_manual.pdf", "content": "The Model X laptop uses a USB-C port for charging. Ensure you are using the correct wattage power adapter (65W minimum recommended)."},
{"id": "doc005", "source": "troubleshooting_guide.txt", "content": "No display output? Check if the laptop is making any sounds (fan spinning, beeps). Try connecting an external monitor to rule out a screen issue."},
{"id": "doc006", "source": "support_articles/power_issues.md", "content": "Holding the power button down for 15-30 seconds can perform a hard reset, sometimes resolving power-on failures."},
{"id": "doc007", "source": "faq.html", "content": "Software updates can be found in the 'System Settings' under the 'Updates' section. Ensure you are connected to the internet."}
]
print(f"\nKnowledge base contains {len(knowledge_base)} documents/chunks.")
# 2. Generate embeddings for the knowledge base (pre-computation)
print("\nGenerating embeddings for the knowledge base...")
kb_embeddings_data = []
for doc in knowledge_base:
embedding = get_embedding(client, doc["content"])
if embedding:
# Store document ID and its embedding
kb_embeddings_data.append({"id": doc["id"], "embedding": embedding})
else:
print(f"Skipping document {doc['id']} due to embedding error.")
if not kb_embeddings_data:
print("\nError: No embeddings were generated for the knowledge base. Cannot retrieve context.")
exit()
print(f"\nSuccessfully generated embeddings for {len(kb_embeddings_data)} knowledge base documents.")
# 3. Define the user's query to the AI assistant
user_query = "My computer won't start up."
# user_query = "How do I update the system software?"
# user_query = "Screen is black when I press the power button."
print(f"\nUser Query: \"{user_query}\"")
# 4. Generate embedding for the user query
print("\nGenerating embedding for the user query...")
query_embedding = get_embedding(client, user_query)
# 5. Find relevant documents from the knowledge base using similarity search
retrieved_context = []
if query_embedding and kb_embeddings_data:
print("\nCalculating similarities to find relevant context...")
for doc_data in kb_embeddings_data:
similarity = cosine_similarity(query_embedding, doc_data["embedding"])
retrieved_context.append({"id": doc_data["id"], "score": similarity})
# Sort context documents by similarity score in descending order
retrieved_context.sort(key=lambda x: x["score"], reverse=True)
# 6. Select Top N relevant documents to use as context
top_n_context = 3
print(f"\n--- Top {top_n_context} Relevant Context Documents Found ---")
if not retrieved_context:
print("No relevant context found (or error calculating similarities).")
else:
final_context_docs = []
for i, context_item in enumerate(retrieved_context[:top_n_context]):
# Find the full document details from the original knowledge base
doc_details = next((doc for doc in knowledge_base if doc["id"] == context_item["id"]), None)
if doc_details:
print(f"{i+1}. ID: {context_item['id']}, Score: {context_item['score']:.4f}")
print(f" Source: {doc_details['source']}")
print(f" Content: {doc_details['content'][:150]}...") # Truncate content
print("-" * 10)
final_context_docs.append(doc_details['content']) # Store content for next step
else:
print(f"{i+1}. ID: {context_item['id']}, Score: {context_item['score']:.4f} (Details not found)")
print("-" * 10)
if len(retrieved_context) > top_n_context:
print(f"(Showing top {top_n_context} of {len(retrieved_context)} potential context documents)")
# --- Next Step (Conceptual - Not coded here) ---
print("\n--- Next Step: Generating AI Assistant Response ---")
print("The content from the relevant documents above would now be combined")
print("with the original user query and sent to a model like GPT-4o")
print("as context to generate an informed and accurate response.")
print("Example prompt structure for GPT-4o:")
print("```")
print(f"System: You are a helpful AI assistant. Answer the user's question based ONLY on the provided context documents.")
print(f"User: Context Documents:\n1. {final_context_docs[0][:50]}...\n2. {final_context_docs[1][:50]}...\n[...]\n\nQuestion: {user_query}\n\nAnswer:")
print("```")
else:
print("\nCould not retrieve context.")
if not query_embedding:
print("Reason: Failed to generate embedding for the user query.")
if not kb_embeddings_data:
print("Reason: No knowledge base embeddings were successfully generated.")
Explicación del Desglose del Código
Este ejemplo demuestra el mecanismo central detrás de la recuperación de contexto para asistentes de IA usando embeddings – encontrar información relevante de una base de conocimiento para responder a la consulta de un usuario.
- Configuración y Funciones Auxiliares:
- Incluye importaciones estándar (
openai
,os
,dotenv
,numpy
), inicialización del cliente, y las funciones auxiliaresget_embedding
ycosine_similarity
.
- Incluye importaciones estándar (
- Definición de la Base de Conocimiento:
- Una lista de diccionarios (
knowledge_base
) simula el almacén de información al que puede acceder el asistente de IA. Cada diccionario representa un documento o fragmento de información e incluye unid
,source
(metadatos opcionales), y elcontent
del texto actual.
- Una lista de diccionarios (
- Generación de Embeddings de la Base de Conocimiento:
- El script itera a través de cada
doc
en elknowledge_base
. - Llama a
get_embedding
en eldoc["content"]
para obtener su representación vectorial. - Almacena el
doc['id']
y su correspondiente vectorembedding
juntos enkb_embeddings_data
. Este es el paso crucial de pre-computación – los embeddings para la base de conocimiento típicamente se generan fuera de línea y se almacenan (a menudo en una base de datos vectorial especializada) para una recuperación rápida.
- El script itera a través de cada
- Consulta del Usuario:
- Una cadena de ejemplo
user_query
representa la pregunta realizada al asistente de IA.
- Una cadena de ejemplo
- Generación del Embedding de la Consulta:
- La función
get_embedding
se llama para eluser_query
para obtener su representación vectorial en el mismo espacio de embeddings que los documentos de la base de conocimiento.
- La función
- Búsqueda de Similitud (Recuperación de Contexto):
- Itera a través de todos los embeddings pre-computados en
kb_embeddings_data
. - Para cada documento de la base de conocimiento, calcula la
cosine_similarity
entre elquery_embedding
y el embedding del documento. - Almacena el
id
del documento y suscore
de similitud relativo a la consulta en una listaretrieved_context
.
- Itera a través de todos los embeddings pre-computados en
- Clasificación y Selección:
- La lista
retrieved_context
se ordena porscore
en orden descendente, trayendo los documentos semánticamente más relevantes al principio. - El script selecciona los N primeros (por ejemplo, 3) documentos de esta lista ordenada. Estos documentos representan el contexto más relevante encontrado en la base de conocimiento para la consulta del usuario.
- La lista
- Mostrar el Contexto Recuperado:
- El script imprime los detalles (ID, puntuación, fuente, vista previa del contenido) de los N primeros documentos de contexto encontrados.
- Siguiente Paso Conceptual (Explicación Crucial):
- Las declaraciones finales de impresión explican el propósito de este proceso de recuperación. El contenido de estos
final_context_docs
no sería la respuesta final. En su lugar, se combinarían con eluser_query
original y se pasarían como contexto a un modelo de lenguaje grande como GPT-4o en una llamada API subsiguiente. - Se muestra una estructura de prompt de ejemplo, ilustrando cómo el contexto recuperado fundamenta al asistente de IA, permitiéndole generar una respuesta informada basada en la información relevante encontrada en la base de conocimiento, en lugar de confiar únicamente en su conocimiento general.
- Las declaraciones finales de impresión explican el propósito de este proceso de recuperación. El contenido de estos
Este ejemplo demuestra efectivamente la parte de recuperación de la Generación Aumentada por Recuperación (RAG), mostrando cómo los embeddings tienden un puente entre la consulta de un usuario y la información relevante almacenada en una base de conocimiento, permitiendo asistentes de IA más precisos y conscientes del contexto.
3.2.5 Detección de anomalías y similitud
Identificar patrones inusuales o encontrar elementos similares en grandes conjuntos de datos mediante la comparación de sus representaciones semánticas es una aplicación fundamental de la tecnología de embeddings. Esta poderosa técnica transforma datos sin procesar en vectores matemáticos que capturan la esencia de su contenido, permitiendo análisis sofisticados a gran escala. Así es cómo funcionan estos sistemas y sus aplicaciones clave:
- Detectar Anomalías
- Marcar transacciones o comportamientos inusuales que se desvían de los patrones normales - Por ejemplo, detectar compras sospechosas con tarjeta de crédito comparándolas con patrones típicos de gasto
- Identificar posibles amenazas de seguridad o intentos de fraude - Como reconocer patrones de inicio de sesión inusuales o detectar cuentas falsas basadas en análisis de comportamiento
- Detectar problemas de calidad de datos o valores atípicos en conjuntos de datos - Incluyendo la identificación de entradas de datos incorrectas o mediciones inusuales que podrían indicar mal funcionamiento del equipo
- Encontrar Similitudes
- Agrupar documentos, imágenes o puntos de datos relacionados basados en significado semántico - Esto permite a los sistemas agrupar contenido similar incluso cuando la redacción exacta difiere, facilitando la organización de grandes colecciones de información
- Emparejar consultas o tickets de soporte similares - Ayudando a los equipos de servicio al cliente a identificar problemas comunes y estandarizar respuestas a problemas frecuentes
- Identificar contenido duplicado o casi duplicado - Útil para sistemas de gestión de contenido para mantener la calidad de datos y reducir la redundancia
Al convertir puntos de datos en vectores de embedding, los sistemas pueden medir qué tan "diferentes" o "similares" son los elementos entre sí usando cálculos de distancia matemática. Este proceso funciona mapeando cada elemento a un punto en un espacio de alta dimensión, donde los elementos similares se posicionan más cerca entre sí y los elementos diferentes están más separados. Esta representación matemática hace posible marcar automáticamente patrones inusuales o agrupar elementos relacionados a gran escala, permitiendo tanto la detección de anomalías como la coincidencia de similitud de formas que serían imposibles con sistemas tradicionales basados en reglas.
Ejemplo:
El siguiente ejemplo de código demuestra la detección de similitud y anomalías usando embeddings de OpenAI.
Este script:
- Definirá un conjunto de datos de elementos de texto (por ejemplo, descripciones de transacciones o eventos).
- Generará embeddings para estos elementos.
- Detección de Similitud: Encontrará elementos más similares a un elemento objetivo dado.
- Detección de Anomalías: Identificará elementos que son menos similares (más anómalos) comparados con el resto del conjunto de datos usando un enfoque simple de similitud promedio.
import os
from openai import OpenAI, OpenAIError
from dotenv import load_dotenv
import numpy as np # For cosine similarity calculation
import datetime
# --- Configuration ---
load_dotenv()
# Get the current date and location context
current_timestamp = "2025-01-13 15:40:00 CDT"
current_location = "Houston, Texas, United States"
print(f"Running Similarity & Anomaly Detection example at: {current_timestamp}")
print(f"Location Context: {current_location}")
# Initialize the OpenAI client
try:
api_key = os.getenv("OPENAI_API_KEY")
if not api_key:
raise ValueError("OPENAI_API_KEY not found in environment variables.")
client = OpenAI(api_key=api_key)
print("OpenAI client initialized.")
except ValueError as e:
print(f"Configuration Error: {e}")
exit()
except Exception as e:
print(f"Error initializing OpenAI client: {e}")
exit()
# Define the embedding model
EMBEDDING_MODEL = "text-embedding-3-small"
# --- Helper Function to Generate Embedding ---
# (Same as in previous embeddings examples)
def get_embedding(client, text, model=EMBEDDING_MODEL):
"""Generates an embedding for the given text using the specified model."""
print_text = text[:70] + "..." if len(text) > 70 else text
print(f"Generating embedding for: \"{print_text}\"")
try:
response = client.embeddings.create(
input=text,
model=model
)
embedding_vector = response.data[0].embedding
return embedding_vector
except OpenAIError as e:
print(f"OpenAI API Error generating embedding for text '{print_text}': {e}")
return None
except Exception as e:
print(f"An unexpected error occurred during embedding generation for text '{print_text}': {e}")
return None
# --- Helper Function for Cosine Similarity ---
# (Same as in previous embeddings examples)
def cosine_similarity(vec_a, vec_b):
"""Calculates the cosine similarity between two vectors."""
if vec_a is None or vec_b is None:
return 0.0
vec_a = np.array(vec_a)
vec_b = np.array(vec_b)
norm_a = np.linalg.norm(vec_a)
norm_b = np.linalg.norm(vec_b)
if norm_a == 0 or norm_b == 0:
return 0.0
else:
# Clamp the value to handle potential floating point inaccuracies slightly outside [-1, 1]
similarity = np.dot(vec_a, vec_b) / (norm_a * norm_b)
return np.clip(similarity, -1.0, 1.0)
# --- Similarity and Anomaly Detection Implementation ---
# 1. Define your dataset (e.g., transaction descriptions, log entries)
# Includes mostly normal items and a couple of potentially anomalous ones.
dataset = [
{"id": "txn001", "description": "Grocery purchase at Local Supermarket"},
{"id": "txn002", "description": "Monthly subscription fee for streaming service"},
{"id": "txn003", "description": "Dinner payment at Italian Restaurant"},
{"id": "txn004", "description": "Online order for electronics from TechStore"},
{"id": "txn005", "description": "Fuel purchase at Gas Station"},
{"id": "txn006", "description": "Purchase of fresh produce and bread"}, # Similar to txn001
{"id": "txn007", "description": "Payment for movie streaming subscription"}, # Similar to txn002
{"id": "txn008", "description": "Unusual large wire transfer to overseas account"}, # Potential Anomaly 1
{"id": "txn009", "description": "Purchase of rare antique collectible vase"}, # Potential Anomaly 2
{"id": "txn010", "description": "Coffee purchase at Cafe Central"}
]
print(f"\nDataset contains {len(dataset)} items.")
# 2. Generate embeddings for all items in the dataset (pre-computation)
print("\nGenerating embeddings for the dataset...")
dataset_embeddings_data = []
for item in dataset:
embedding = get_embedding(client, item["description"])
if embedding:
# Store item ID, description, and its embedding
dataset_embeddings_data.append({
"id": item["id"],
"description": item["description"],
"embedding": embedding
})
else:
print(f"Skipping item {item['id']} due to embedding error.")
if not dataset_embeddings_data:
print("\nError: No embeddings were generated. Cannot perform analysis.")
exit()
print(f"\nSuccessfully generated embeddings for {len(dataset_embeddings_data)} items.")
# --- Part A: Similarity Detection ---
print("\n--- Part A: Similarity Detection ---")
# Select a target item to find similar items for
target_item_id_similarity = "txn001" # Find items similar to "Grocery purchase..."
print(f"Finding items similar to item ID: {target_item_id_similarity}")
# Find the target item's data
target_item_data = next((item for item in dataset_embeddings_data if item["id"] == target_item_id_similarity), None)
if target_item_data:
target_embedding = target_item_data["embedding"]
similar_items = []
# Calculate similarity between the target and all other items
for item_data in dataset_embeddings_data:
if item_data["id"] == target_item_id_similarity:
continue # Skip self-comparison
similarity = cosine_similarity(target_embedding, item_data["embedding"])
similar_items.append({
"id": item_data["id"],
"description": item_data["description"],
"score": similarity
})
# Sort by similarity score
similar_items.sort(key=lambda x: x["score"], reverse=True)
# Display top N similar items
print(f"\nItems most similar to: \"{target_item_data['description']}\"")
top_n_similar = 2
for i, item in enumerate(similar_items[:top_n_similar]):
print(f"{i+1}. ID: {item['id']}, Score: {item['score']:.4f}")
print(f" Description: {item['description']}")
print("-" * 10)
else:
print(f"Error: Could not find data for target item ID '{target_item_id_similarity}'.")
# --- Part B: Anomaly Detection (Simple Approach) ---
print("\n--- Part B: Anomaly Detection (Low Average Similarity) ---")
# Calculate the average similarity of each item to all other items
item_avg_similarities = []
num_items = len(dataset_embeddings_data)
if num_items < 2:
print("Need at least 2 items with embeddings to calculate average similarities.")
else:
print("\nCalculating average similarities for anomaly detection...")
for i in range(num_items):
current_item = dataset_embeddings_data[i]
total_similarity = 0
# Compare current item to all others
for j in range(num_items):
if i == j: # Don't compare item to itself
continue
other_item = dataset_embeddings_data[j]
similarity = cosine_similarity(current_item["embedding"], other_item["embedding"])
total_similarity += similarity
# Calculate average similarity (avoid division by zero if only 1 item)
average_similarity = total_similarity / (num_items - 1) if num_items > 1 else 0
item_avg_similarities.append({
"id": current_item["id"],
"description": current_item["description"],
"avg_score": average_similarity
})
print(f"Item ID {current_item['id']} - Avg Similarity: {average_similarity:.4f}")
# Sort items by average similarity in ascending order (lowest first = most anomalous)
item_avg_similarities.sort(key=lambda x: x["avg_score"])
# Display top N potential anomalies (items least similar to others)
print("\nPotential Anomalies (Lowest Average Similarity):")
top_n_anomalies = 3
for i, item in enumerate(item_avg_similarities[:top_n_anomalies]):
print(f"{i+1}. ID: {item['id']}, Avg Score: {item['avg_score']:.4f}")
print(f" Description: {item['description']}")
print("-" * 10)
print("\nNote: Low average similarity suggests an item is semantically")
print("different from the majority of other items in this dataset.")
Explicación del Desglose del Código
Este ejemplo demuestra el uso de embeddings de OpenAI tanto para encontrar elementos similares como para detectar posibles anomalías dentro de un conjunto de datos basándose en el significado semántico.
- Configuración y Funciones Auxiliares:
- Incluye importaciones estándar (
openai
,os
,dotenv
,numpy
), inicialización del cliente, y las funciones auxiliaresget_embedding
ycosine_similarity
. La funcióncosine_similarity
ahora incluyenp.clip
para asegurar que la salida esté estrictamente dentro de [-1, 1].
- Incluye importaciones estándar (
- Definición del Conjunto de Datos:
- Una lista de diccionarios (
dataset
) simula los datos a analizar (por ejemplo, descripciones de transacciones). Cada elemento tiene unid
y unadescription
de texto. Los datos de muestra incluyen principalmente elementos comunes y algunos conceptualmente diferentes destinados a ser posibles anomalías.
- Una lista de diccionarios (
- Generación de Embeddings del Conjunto de Datos:
- El script itera a través de cada
item
en eldataset
. - Llama a
get_embedding
en elitem["description"]
. - Almacena el
item['id']
,item['description']
, y su correspondiente vectorembedding
juntos endataset_embeddings_data
. Esta pre-computación es esencial.
- El script itera a través de cada
- Parte A: Detección de Similitud:
- Selección del Objetivo: Se elige un ID de elemento (
target_item_id_similarity
) para encontrar elementos similares. - Recuperación del Embedding Objetivo: El script encuentra el embedding pre-computado para el elemento objetivo.
- Comparación: Itera a través de todos los otros elementos en
dataset_embeddings_data
, calcula lacosine_similarity
entre el embedding del elemento objetivo y el embedding de cada otro elemento. - Clasificación: Los resultados (ID del otro elemento, descripción, puntuación de similitud) se almacenan y luego se ordenan por puntuación en orden descendente.
- Visualización: Se muestran los N elementos más similares.
- Selección del Objetivo: Se elige un ID de elemento (
- Parte B: Detección de Anomalías (Enfoque de Similitud Promedio Simple):
- Concepto: Este método simple identifica anomalías como elementos que tienen la similitud promedio más baja con todos los otros elementos en el conjunto de datos. Un elemento que es conceptualmente muy diferente del resto probablemente tendrá puntuaciones de similitud bajas cuando se compare con la mayoría de los otros.
- Cálculo:
- El script itera a través de cada elemento (
current_item
) endataset_embeddings_data
. - Para cada
current_item
, itera a través de todos los otros elementos en el conjunto de datos. - Calcula la
cosine_similarity
entre elcurrent_item
y cadaother_item
. - Suma estas similitudes y calcula la similitud promedio para el
current_item
.
- El script itera a través de cada elemento (
- Clasificación: Los elementos se almacenan junto con su
avg_score
calculado y luego se ordenan por esta puntuación en orden ascendente (similitud promedio más baja primero). - Visualización: Se muestran los N elementos con las puntuaciones de similitud promedio más bajas como posibles anomalías. Una nota explica la interpretación.
Este ejemplo muestra dos aplicaciones poderosas: encontrar contenido relacionado (similitud) e identificar valores atípicos (detección de anomalías) aprovechando la comprensión semántica capturada dentro de los embeddings de OpenAI.
3.2.6 Agrupamiento y Etiquetado
Organizar y etiquetar contenido automáticamente basándose en la similitud semántica - una técnica poderosa que utiliza vectores de embedding para comprender el verdadero significado y las relaciones entre diferentes piezas de contenido. Este enfoque va mucho más allá del tradicional emparejamiento de palabras clave, permitiendo una organización de contenido mucho más matizada y precisa.
Cuando el contenido se agrupa, los elementos similares se agrupan naturalmente según su significado semántico, incluso si utilizan terminología diferente para expresar los mismos conceptos. Por ejemplo, los documentos sobre "mantenimiento automotriz" y "reparación de coches" se agruparían juntos a pesar de usar palabras diferentes.
Esta organización inteligente ayuda a crear sistemas de navegación intuitivos, mejora el descubrimiento de contenido y hace que las grandes colecciones de documentos sean más manejables al agrupar elementos relacionados. Algunos beneficios clave incluyen:
- Generación automática de etiquetas basada en temas de grupos
- Organización dinámica que se adapta a medida que se agrega nuevo contenido
- Mejora de la relevancia en las búsquedas mediante comprensión semántica
- Mejor descubrimiento de contenido a través de sugerencias de elementos relacionados
El proceso de agrupamiento puede ajustarse para crear categorías amplias o subcategorías más granulares, dependiendo de las necesidades específicas de su sistema de organización de contenido. Esta flexibilidad lo convierte en una herramienta valiosa para gestionar desde bibliotecas digitales hasta bases de conocimiento empresariales.
Ejemplo:
Examinemos un ejemplo de código que demuestra el agrupamiento y etiquetado usando embeddings de OpenAI y GPT-4o.
Este script:
- Definirá una colección de documentos.
- Generará embeddings para los documentos.
- Agrupará los documentos usando K-Means basándose en sus embeddings.
- Para cada grupo, usará GPT-4o para analizar los documentos dentro de él y generar una etiqueta o descriptor descriptivo.
- Mostrará los documentos agrupados por cluster junto con sus etiquetas generadas por IA.
import os
from openai import OpenAI, OpenAIError
from dotenv import load_dotenv
import numpy as np
from sklearn.cluster import KMeans # For clustering algorithm
import datetime
# --- Configuration ---
load_dotenv()
# Get the current date and location context
current_timestamp = "2024-12-31 15:48:00 CDT"
current_location = "San Antonio, Texas, United States"
print(f"Running Clustering & Tagging example at: {current_timestamp}")
print(f"Location Context: {current_location}")
# Initialize the OpenAI client
try:
api_key = os.getenv("OPENAI_API_KEY")
if not api_key:
raise ValueError("OPENAI_API_KEY not found in environment variables.")
client = OpenAI(api_key=api_key)
print("OpenAI client initialized.")
except ValueError as e:
print(f"Configuration Error: {e}")
exit()
except Exception as e:
print(f"Error initializing OpenAI client: {e}")
exit()
# Define the embedding model
EMBEDDING_MODEL = "text-embedding-3-small"
# --- Helper Function to Generate Embedding ---
# (Same as in previous embeddings examples)
def get_embedding(client, text, model=EMBEDDING_MODEL):
"""Generates an embedding for the given text using the specified model."""
print_text = text[:70] + "..." if len(text) > 70 else text
print(f"Generating embedding for: \"{print_text}\"")
try:
response = client.embeddings.create(
input=text,
model=model
)
embedding_vector = response.data[0].embedding
return embedding_vector
except OpenAIError as e:
print(f"OpenAI API Error generating embedding for text '{print_text}': {e}")
return None
except Exception as e:
print(f"An unexpected error occurred during embedding generation for text '{print_text}': {e}")
return None
# --- Helper Function to Generate Cluster Tag using GPT-4o ---
def generate_cluster_tag(client, documents_in_cluster):
"""Uses GPT-4o to suggest a tag/label for a cluster of documents."""
if not documents_in_cluster:
return "Empty Cluster"
# Combine content for context, limiting total length if necessary
# Using first few hundred chars of each doc might be enough
max_context_length = 3000 # Limit context to avoid excessive token usage
context = ""
for i, doc in enumerate(documents_in_cluster):
doc_preview = f"Document {i+1}: {doc[:300]}...\n"
if len(context) + len(doc_preview) > max_context_length:
break
context += doc_preview
if not context:
return "Error: Could not create context"
system_prompt = "You are an expert at identifying themes and creating concise labels."
user_prompt = f"""Based on the following document excerpts from a single cluster, suggest a short, descriptive tag or label (2-5 words) that captures the main theme or topic of this group.
Document Excerpts:
---
{context.strip()}
---
Suggested Tag/Label:
"""
print(f"\nGenerating tag for cluster with {len(documents_in_cluster)} documents...")
try:
response = client.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_prompt}
],
max_tokens=20, # Short response expected
temperature=0.3 # More deterministic label
)
tag = response.choices[0].message.content.strip().replace('"', '') # Clean up quotes
print(f"Generated tag: '{tag}'")
return tag
except OpenAIError as e:
print(f"OpenAI API Error generating tag: {e}")
return "Tagging Error"
except Exception as e:
print(f"An unexpected error occurred during tag generation: {e}")
return "Tagging Error"
# --- Clustering and Tagging Implementation ---
# 1. Define your collection of documents
# Covers topics: Space Exploration, Cooking/Food, Web Development
documents = [
"NASA launches new probe to study Jupiter's moons.",
"Recipe for authentic Italian pasta carbonara.",
"JavaScript frameworks like React and Vue dominate front-end development.",
"The James Webb Space Telescope captures stunning images of distant galaxies.",
"Tips for baking the perfect sourdough bread at home.",
"Understanding asynchronous programming in Node.js.",
"SpaceX successfully lands its reusable rocket booster after launch.",
"Exploring the different types of olive oil and their uses in cooking.",
"CSS Grid vs Flexbox: Choosing the right layout module.",
"The search for habitable exoplanets continues with new telescope data.",
"How to make delicious homemade pizza from scratch.",
"Building RESTful APIs using Express.js and MongoDB."
]
print(f"\nDocument collection contains {len(documents)} documents.")
# 2. Generate embeddings for all documents
print("\nGenerating embeddings for the document collection...")
embeddings = []
valid_documents = [] # Keep track of documents for which embedding was successful
for doc in documents:
embedding = get_embedding(client, doc)
if embedding:
embeddings.append(embedding)
valid_documents.append(doc) # Add corresponding document text
else:
print(f"Skipping document due to embedding error: \"{doc[:70]}...\"")
if not embeddings:
print("\nError: No embeddings were generated. Cannot perform clustering.")
exit()
print(f"\nSuccessfully generated embeddings for {len(valid_documents)} documents.")
# Convert embeddings list to a NumPy array for scikit-learn
embedding_matrix = np.array(embeddings)
# 3. Apply Clustering Algorithm (K-Means)
# Choose the number of clusters (k). We expect 3 topics here.
n_clusters = 3
print(f"\nApplying K-Means clustering with k={n_clusters}...")
try:
kmeans = KMeans(n_clusters=n_clusters, random_state=42, n_init=10)
kmeans.fit(embedding_matrix)
cluster_labels = kmeans.labels_
print("Clustering complete.")
except Exception as e:
print(f"An error occurred during clustering: {e}")
exit()
# 4. Group Documents by Cluster
print("\nGrouping documents by cluster...")
clustered_documents = {i: [] for i in range(n_clusters)}
for i, label in enumerate(cluster_labels):
clustered_documents[label].append(valid_documents[i])
# 5. Generate Tags for Each Cluster using GPT-4o
print("\nGenerating tags for each cluster...")
cluster_tags = {}
for cluster_id, docs_in_cluster in clustered_documents.items():
tag = generate_cluster_tag(client, docs_in_cluster)
cluster_tags[cluster_id] = tag
# 6. Display Documents by Cluster with Generated Tags
print(f"\n--- Documents Grouped by Cluster and Tag (k={n_clusters}) ---")
for cluster_id, docs_in_cluster in clustered_documents.items():
generated_tag = cluster_tags.get(cluster_id, "Unknown Tag")
print(f"\nCluster {cluster_id + 1} - Suggested Tag: '{generated_tag}'")
print("-" * (28 + len(generated_tag))) # Adjust underline length
if not docs_in_cluster:
print(" (No documents in this cluster)")
else:
for doc_text in docs_in_cluster:
print(f" - {doc_text}") # Print full document text here
print("\nClustering and Tagging process complete.")
Explicación del Desglose del Código
Este script demuestra cómo agrupar automáticamente documentos similares por su significado semántico usando embeddings, y luego utiliza GPT-4o para generar etiquetas descriptivas para cada grupo.
- Configuración y Funciones Auxiliares:
- Incluye importaciones estándar más
KMeans
desklearn.cluster
. - Inicializa el cliente de OpenAI.
- Incluye la función auxiliar
get_embedding
.
- Incluye importaciones estándar más
- Nueva Función Auxiliar:
generate_cluster_tag
:- Propósito: Toma una lista de documentos pertenecientes a un único clúster y utiliza GPT-4o para sugerir una etiqueta concisa que resuma su tema común.
- Entrada: El objeto
client
ydocuments_in_cluster
(una lista de cadenas de texto). - Creación de Contexto: Concatena partes de los documentos (por ejemplo, los primeros 300 caracteres) para crear una cadena de contexto para GPT-4o, respetando una longitud máxima para gestionar el uso de tokens.
- Ingeniería de Prompt: Construye un prompt pidiendo a GPT-4o que actúe como un experto en identificación de temas y sugiera una etiqueta corta (2-5 palabras) basada en los extractos de documentos proporcionados.
- Llamada a la API: Utiliza
client.chat.completions.create
conmodel="gpt-4o"
y el prompt especializado. Se usa una temperatura baja para una generación de etiquetas más enfocada. - Salida: Devuelve la etiqueta sugerida por GPT-4o depurada, o un mensaje de error.
- Colección de Documentos: Una lista llamada
documents
contiene contenido de texto de muestra que abarca varios temas distintos (Espacio, Cocina, Desarrollo Web). - Generación de Embeddings:
- El script itera a través de los
documents
, genera un embedding para cada uno usandoget_embedding
, y almacena los embeddings exitosos y el texto correspondiente enembeddings
yvalid_documents
. - Los embeddings se convierten a un array de NumPy (
embedding_matrix
).
- El script itera a través de los
- Agrupamiento (K-Means):
- El número de clústeres (
n_clusters
) se establece (por ejemplo,k=3
). KMeans
descikit-learn
se inicializa y se ajusta a laembedding_matrix
.kmeans.labels_
proporciona la asignación de clúster para cada documento.
- El número de clústeres (
- Agrupación de Documentos:
- Se crea un diccionario (
clustered_documents
) para almacenar el texto de los documentos pertenecientes a cada ID de clúster.
- Se crea un diccionario (
- Generación de Etiquetas de Clúster:
- El script itera a través del diccionario
clustered_documents
. - Para cada
cluster_id
y su lista dedocs_in_cluster
, llama a la función auxiliargenerate_cluster_tag
. - La etiqueta sugerida para cada clúster se almacena en el diccionario
cluster_tags
.
- El script itera a través del diccionario
- Visualización de Resultados:
- El script itera nuevamente a través de los clústeres.
- Para cada clúster, recupera la etiqueta generada de
cluster_tags
. - Imprime el número del clúster, la etiqueta sugerida, y luego lista el texto completo de todos los documentos pertenecientes a ese clúster.
Este ejemplo muestra un flujo de trabajo potente: usar embeddings para el agrupamiento no supervisado de contenido basado en significado (clustering) y luego aprovechar un LLM como GPT-4o para interpretar esos grupos y asignar etiquetas significativas (etiquetado), automatizando la organización del contenido.
3.2.7 Recomendaciones de Contenido
Los sistemas de recomendación de contenido impulsados por embeddings representan un avance significativo en la tecnología de personalización. Al analizar relaciones semánticas, estos sistemas pueden entender el significado matizado y el contexto del contenido de maneras que los sistemas tradicionales basados en palabras clave no pueden.
Aquí hay una mirada detallada a cómo funcionan las recomendaciones basadas en embeddings:
- Análisis de Contenido:
- El sistema genera vectores de embedding sofisticados para cada pieza de contenido en la base de datos
- Estos vectores capturan características matizadas como estilo de escritura, profundidad del tema y tono emocional
- Los algoritmos avanzados analizan patrones a través de múltiples dimensiones de características de contenido
- Modelado de Preferencias del Usuario:
- El sistema rastrea patrones detallados de interacción incluyendo tiempo dedicado, nivel de participación y comportamiento de compartir
- Las preferencias históricas se ponderan y combinan para crear perfiles de usuario multidimensionales
- Se consideran tanto la retroalimentación explícita (calificaciones, me gusta) como las señales implícitas (profundidad de desplazamiento, visitas repetidas)
- Comprensión Contextual:
- Los factores en tiempo real como el tipo de dispositivo y la ubicación se incorporan al algoritmo de recomendación
- El sistema identifica patrones en el consumo de contenido basados en la hora del día y el día de la semana
- El comportamiento de la sesión actual se analiza para entender los intereses inmediatos del usuario
- Adaptación Dinámica:
- Los modelos de aprendizaje automático refinan continuamente los perfiles de usuario basados en nuevas interacciones
- El sistema aprende tanto de la retroalimentación positiva como negativa para mejorar la precisión
- Las estrategias de recomendación se ajustan automáticamente según las métricas de rendimiento
Este enfoque sofisticado permite que los motores de recomendación entreguen experiencias altamente personalizadas a través de varias capacidades clave:
- Identificar similitudes de contenido que podrían no ser aparentes a través de metadatos tradicionales
- Puede detectar conexiones temáticas entre elementos incluso cuando utilizan terminología diferente
- Reconoce estilos de escritura similares, tono y niveles de complejidad en el contenido
- Entender la progresión de los intereses del usuario a lo largo del tiempo
- Rastrea cómo evolucionan las preferencias desde temas básicos hasta avanzados
- Identifica cambios en los intereses del usuario a través de diferentes categorías
- Hacer recomendaciones entre dominios (por ejemplo, sugerir artículos basados en videos vistos)
- Conecta contenido a través de diferentes tipos de medios basándose en relaciones semánticas
- Aprovecha el aprendizaje de un dominio para mejorar las recomendaciones en otro
- Tener en cuenta tendencias estacionales y relevancia temporal
- Ajusta las recomendaciones basándose en factores sensibles al tiempo como festividades o eventos
- Considera las tendencias actuales y su impacto en los intereses del usuario
El resultado es una experiencia altamente personalizada que puede sugerir videos, artículos o productos verdaderamente relevantes que coincidan con los intereses de los usuarios, tanto actuales como en evolución. Esto va mucho más allá de los simples algoritmos de "a los usuarios que les gustó X también les gustó Y", creando una experiencia de usuario más atractiva y valiosa.
Ejemplo:
Aquí hay un ejemplo de código que demuestra el concepto central de recomendaciones de contenido usando embeddings.
Este script se centra en encontrar elementos de contenido semánticamente similares basados en sus embeddings, que es la base para las características de recomendación más avanzadas que describiste.
import os
from openai import OpenAI, OpenAIError
from dotenv import load_dotenv
import numpy as np # For cosine similarity calculation
import datetime
# --- Configuration ---
load_dotenv()
# Get the current date and location context
current_timestamp = "2024-11-30 15:52:00 CDT"
current_location = "Orlando, Florida, United States"
print(f"Running Content Recommendation example at: {current_timestamp}")
print(f"Location Context: {current_location}")
# Initialize the OpenAI client
try:
api_key = os.getenv("OPENAI_API_KEY")
if not api_key:
raise ValueError("OPENAI_API_KEY not found in environment variables.")
client = OpenAI(api_key=api_key)
print("OpenAI client initialized.")
except ValueError as e:
print(f"Configuration Error: {e}")
exit()
except Exception as e:
print(f"Error initializing OpenAI client: {e}")
exit()
# Define the embedding model
EMBEDDING_MODEL = "text-embedding-3-small"
# --- Helper Function to Generate Embedding ---
# (Same as in previous embeddings examples)
def get_embedding(client, text, model=EMBEDDING_MODEL):
"""Generates an embedding for the given text using the specified model."""
print_text = text[:70] + "..." if len(text) > 70 else text
print(f"Generating embedding for: \"{print_text}\"")
try:
response = client.embeddings.create(
input=text,
model=model
)
embedding_vector = response.data[0].embedding
return embedding_vector
except OpenAIError as e:
print(f"OpenAI API Error generating embedding for text '{print_text}': {e}")
return None
except Exception as e:
print(f"An unexpected error occurred during embedding generation for text '{print_text}': {e}")
return None
# --- Helper Function for Cosine Similarity ---
# (Same as in previous embeddings examples)
def cosine_similarity(vec_a, vec_b):
"""Calculates the cosine similarity between two vectors."""
if vec_a is None or vec_b is None:
return 0.0
vec_a = np.array(vec_a)
vec_b = np.array(vec_b)
norm_a = np.linalg.norm(vec_a)
norm_b = np.linalg.norm(vec_b)
if norm_a == 0 or norm_b == 0:
return 0.0
else:
similarity = np.dot(vec_a, vec_b) / (norm_a * norm_b)
return np.clip(similarity, -1.0, 1.0) # Ensure value is within valid range
# --- Content Recommendation Implementation ---
# 1. Define your Content Catalog (e.g., articles, blog posts)
# In a real application, this would come from a database or CMS.
content_catalog = [
{"id": "art001", "title": "Introduction to Quantum Computing", "content": "Exploring the basics of qubits, superposition, and entanglement in quantum mechanics and their potential for computation."},
{"id": "art002", "title": "Healthy Mediterranean Diet Recipes", "content": "Delicious and easy recipes focusing on fresh vegetables, olive oil, fish, and whole grains for a heart-healthy lifestyle."},
{"id": "art003", "title": "The Future of Artificial Intelligence in Healthcare", "content": "How AI and machine learning are transforming diagnostics, drug discovery, and personalized medicine."},
{"id": "art004", "title": "Beginner's Guide to Python Programming", "content": "Learn the fundamentals of Python syntax, data types, control flow, and functions to start coding."},
{"id": "art005", "title": "Understanding Neural Networks and Deep Learning", "content": "An overview of artificial neural networks, backpropagation, and the concepts behind deep learning models."},
{"id": "art006", "title": "Travel Guide: Hiking the Swiss Alps", "content": "Tips for planning your trip, recommended trails, essential gear, and stunning viewpoints in the Swiss Alps."},
{"id": "art007", "title": "Mastering the Art of French Pastry", "content": "Techniques for creating classic French desserts like croissants, macarons, and éclairs."},
{"id": "art008", "title": "Ethical Considerations in AI Development", "content": "Discussing bias, fairness, transparency, and accountability in the development and deployment of artificial intelligence systems."}
]
print(f"\nContent catalog contains {len(content_catalog)} items.")
# 2. Generate embeddings for all content items (pre-computation)
print("\nGenerating embeddings for the content catalog...")
content_embeddings_data = []
for item in content_catalog:
# Use title and content for embedding
text_to_embed = f"Title: {item['title']}\nContent: {item['content']}"
embedding = get_embedding(client, text_to_embed)
if embedding:
# Store item ID and its embedding
content_embeddings_data.append({"id": item["id"], "embedding": embedding})
else:
print(f"Skipping item {item['id']} due to embedding error.")
if not content_embeddings_data:
print("\nError: No embeddings were generated. Cannot provide recommendations.")
exit()
print(f"\nSuccessfully generated embeddings for {len(content_embeddings_data)} content items.")
# 3. Select a target item (e.g., an article the user just read)
target_item_id = "art003" # User read "The Future of Artificial Intelligence in Healthcare"
print(f"\nFinding content similar to item ID: {target_item_id}")
# Find the embedding for the target item
target_embedding = None
for item_data in content_embeddings_data:
if item_data["id"] == target_item_id:
target_embedding = item_data["embedding"]
break
if target_embedding is None:
print(f"Error: Could not find the embedding for the target item ID '{target_item_id}'.")
exit()
# 4. Calculate similarity between the target item and all other items
recommendations = []
print("\nCalculating similarities...")
for item_data in content_embeddings_data:
# Don't recommend the item itself
if item_data["id"] == target_item_id:
continue
similarity = cosine_similarity(target_embedding, item_data["embedding"])
recommendations.append({"id": item_data["id"], "score": similarity})
# 5. Sort potential recommendations by similarity score
recommendations.sort(key=lambda x: x["score"], reverse=True)
# 6. Display top N recommendations
print("\n--- Top Content Recommendations ---")
# Find the original title for the target item for context
target_item_info = next((item for item in content_catalog if item["id"] == target_item_id), None)
if target_item_info:
print(f"Because you read: \"{target_item_info['title']}\"\n")
if not recommendations:
print("No recommendations found (or error calculating similarities).")
else:
top_n = 3
print(f"Top {top_n} recommended items:")
for i, rec in enumerate(recommendations[:top_n]):
# Find the full item details from the original catalog
rec_details = next((item for item in content_catalog if item["id"] == rec["id"]), None)
if rec_details:
print(f"{i+1}. ID: {rec['id']}, Similarity Score: {rec['score']:.4f}")
print(f" Title: {rec_details['title']}")
print(f" Content Snippet: {rec_details['content'][:100]}...") # Truncate content
print("-" * 10)
else:
print(f"{i+1}. ID: {rec['id']}, Score: {rec['score']:.4f} (Details not found)")
print("-" * 10)
if len(recommendations) > top_n:
print(f"(Showing top {top_n} of {len(recommendations)} potential recommendations)")
print("\nNote: This demonstrates basic content-to-content similarity.")
print("Advanced systems incorporate user profiles, interaction history, context, etc.")
Explicación del Desglose del Código
Este script demuestra un enfoque fundamental para la recomendación de contenido utilizando embeddings de OpenAI, centrándose en encontrar elementos semánticamente similares a un elemento objetivo.
- Configuración y Funciones Auxiliares:
- Incluye importaciones estándar (
openai
,os
,dotenv
,numpy
), inicialización del cliente, y las funciones auxiliaresget_embedding
ycosine_similarity
.
- Incluye importaciones estándar (
- Catálogo de Contenido:
- Una lista de diccionarios (
content_catalog
) simula el contenido disponible (por ejemplo, artículos). Cada elemento tiene unid
,title
ycontent
.
- Una lista de diccionarios (
- Generación de Embeddings de Contenido (Pre-computación):
- El script itera sobre cada
item
en elcontent_catalog
. - Texto Combinado: Crea una cadena de texto combinada del
title
ycontent
del elemento para generar un embedding más rico que capture más detalle semántico. - Llama a
get_embedding
para este texto combinado. - Almacena el
item['id']
y su vectorembedding
encontent_embeddings_data
. Esta pre-computación es vital para la eficiencia.
- El script itera sobre cada
- Selección del Elemento Objetivo:
- Se elige un
target_item_id
(por ejemplo,art003
), simulando un elemento con el que el usuario ha interactuado (por ejemplo, leído). - El script recupera el embedding pre-computado para este elemento objetivo.
- Se elige un
- Cálculo de Similitud:
- Itera a través de todos los otros elementos en
content_embeddings_data
. - Calcula la
cosine_similarity
entre eltarget_embedding
y el embedding de cada otro elemento. - Almacena el
id
del otro elemento y suscore
de similitud en la listarecommendations
.
- Itera a través de todos los otros elementos en
- Clasificación de Recomendaciones:
- La lista
recommendations
se ordena porscore
en orden descendente, colocando primero los elementos de contenido más similares semánticamente.
- La lista
- Visualización de Resultados:
- El script muestra el título del elemento objetivo para dar contexto ("Porque has leído...").
- Muestra los N principales elementos recomendados (por ejemplo, 3), mostrando su ID, puntuación de similitud, título y un fragmento de su contenido.
- Nota Contextual: Las declaraciones finales mencionan explícitamente que este ejemplo muestra una similitud básica de contenido a contenido. Los sistemas de recomendación avanzados, como se describe en el texto de la sección, integrarían perfiles de usuario (embeddings basados en el historial de interacciones), contexto en tiempo real (tiempo, ubicación), retroalimentación explícita y potencialmente algoritmos más complejos más allá de la simple similitud del coseno. Sin embargo, el principio fundamental de usar embeddings para medir la relación semántica sigue siendo fundamental.
Este ejemplo ilustra efectivamente cómo los embeddings permiten recomendaciones basadas en la comprensión del significado del contenido, permitiendo sugerencias que van más allá de la simple coincidencia de palabras clave o categorías.
3.2.8 Clasificación y Priorización de Correos Electrónicos
La tecnología de embeddings permite un análisis y categorización sofisticados de correos electrónicos mediante la comprensión del significado semántico de los mensajes. Este sistema avanzado emplea múltiples capas de análisis para optimizar la gestión del correo electrónico:
- Detección de Urgencia
- Identificar asuntos urgentes que requieren atención inmediata mediante procesamiento del lenguaje natural
- Reconocer patrones de lenguaje urgente y señales contextuales analizando la elección de palabras, estructura de oraciones y patrones históricos
- Marcar correos críticos basándose en la importancia del remitente, palabras clave y jerarquía organizacional
- Categorización Inteligente
- Agrupar hilos de correo y conversaciones relacionadas mediante coincidencia de similitud semántica
- Clasificar mensajes por proyecto, departamento o función empresarial mediante análisis de contenido
- Crear carpetas dinámicas basadas en temas y tendencias emergentes
- Aplicar aprendizaje automático para mejorar la precisión de categorización con el tiempo
- Clasificación de Intención
- Distinguir entre solicitudes, actualizaciones y mensajes informativos mediante comprensión avanzada del lenguaje natural
- Priorizar elementos de acción y delegar tareas automáticamente según contenido y contexto
- Identificar requisitos de seguimiento y establecer recordatorios automáticos
- Extraer plazos y compromisos clave del contenido del mensaje
Al aprovechar la comprensión semántica, el sistema crea un proceso inteligente de procesamiento de correos electrónicos que puede manejar cientos de mensajes simultáneamente. El análisis basado en embeddings examina no solo palabras clave, sino el significado y contexto real de cada mensaje, considerando factores como:
- Contexto del mensaje dentro de conversaciones en curso
- Patrones históricos de comunicación
- Relaciones y jerarquías organizacionales
- Cronogramas y prioridades de proyectos
Este enfoque integral reduce significativamente la carga cognitiva de la gestión del correo electrónico al manejar automáticamente las tareas rutinarias de clasificación y priorización. El sistema asegura que los mensajes importantes reciban atención inmediata mientras mantiene una estructura organizada para todas las comunicaciones. Como resultado, los profesionales pueden concentrarse en actividades de alto valor en lugar de pasar horas clasificando manualmente su bandeja de entrada, lo que lleva a una mejor productividad y tiempos de respuesta más rápidos para comunicaciones críticas.
Ejemplo:
Este script simula la categorización de correos electrónicos entrantes basándose en su similitud semántica con categorías predefinidas como "Solicitud Urgente", "Actualización de Proyecto",
import os
from openai import OpenAI, OpenAIError
from dotenv import load_dotenv
import numpy as np # For cosine similarity calculation
import datetime
# --- Configuration ---
load_dotenv()
# Get the current date and location context
current_timestamp = "2024-10-31 15:54:00 CDT"
current_location = "Plano, Texas, United States"
print(f"Running Email Triage/Prioritization example at: {current_timestamp}")
print(f"Location Context: {current_location}")
# Initialize the OpenAI client
try:
api_key = os.getenv("OPENAI_API_KEY")
if not api_key:
raise ValueError("OPENAI_API_KEY not found in environment variables.")
client = OpenAI(api_key=api_key)
print("OpenAI client initialized.")
except ValueError as e:
print(f"Configuration Error: {e}")
exit()
except Exception as e:
print(f"Error initializing OpenAI client: {e}")
exit()
# Define the embedding model
EMBEDDING_MODEL = "text-embedding-3-small"
# --- Helper Function to Generate Embedding ---
# (Same as in previous embeddings examples)
def get_embedding(client, text, model=EMBEDDING_MODEL):
"""Generates an embedding for the given text using the specified model."""
print_text = text[:70] + "..." if len(text) > 70 else text
print(f"Generating embedding for: \"{print_text}\"")
try:
response = client.embeddings.create(
input=text,
model=model
)
embedding_vector = response.data[0].embedding
return embedding_vector
except OpenAIError as e:
print(f"OpenAI API Error generating embedding for text '{print_text}': {e}")
return None
except Exception as e:
print(f"An unexpected error occurred during embedding generation for text '{print_text}': {e}")
return None
# --- Helper Function for Cosine Similarity ---
# (Same as in previous embeddings examples)
def cosine_similarity(vec_a, vec_b):
"""Calculates the cosine similarity between two vectors."""
if vec_a is None or vec_b is None:
return 0.0
vec_a = np.array(vec_a)
vec_b = np.array(vec_b)
norm_a = np.linalg.norm(vec_a)
norm_b = np.linalg.norm(vec_b)
if norm_a == 0 or norm_b == 0:
return 0.0
else:
similarity = np.dot(vec_a, vec_b) / (norm_a * norm_b)
return np.clip(similarity, -1.0, 1.0) # Ensure value is within valid range
# --- Email Triage/Prioritization Implementation ---
# 1. Define Sample Emails (Subject + Snippet)
emails = [
{"id": "email01", "subject": "Urgent: Server Down!", "body_snippet": "The main production server seems to be unresponsive. We need immediate assistance to investigate and bring it back online."},
{"id": "email02", "subject": "Meeting Minutes - Project Phoenix Sync", "body_snippet": "Attached are the minutes from today's sync call. Key decisions included finalizing the Q3 roadmap. Action items assigned."},
{"id": "email03", "subject": "Quick Question about Report", "body_snippet": "Hi team, just had a quick question regarding the methodology used in the latest market analysis report. Can someone clarify?"},
{"id": "email04", "subject": "Fwd: Company Newsletter - April Edition", "body_snippet": "Sharing the latest company newsletter for your information."},
{"id": "email05", "subject": "Action Required: Submit Timesheet by EOD", "body_snippet": "Friendly reminder to please submit your weekly timesheet by the end of the day today. This is mandatory."},
{"id": "email06", "subject": "Update on Q2 Marketing Campaign", "body_snippet": "Just wanted to provide a brief update on the campaign performance metrics we discussed last week. See attached summary."},
{"id": "email07", "subject": "Can you approve this request ASAP?", "body_snippet": "Need your approval on the attached budget request urgently to proceed with the vendor contract."}
]
print(f"\nProcessing {len(emails)} emails.")
# 2. Define Categories/Priorities and their Semantic Representations
# We represent each category with a descriptive phrase.
categories = {
"Urgent Action Required": "Requires immediate attention, critical issue, deadline, ASAP request, mandatory task.",
"Project Update / Status": "Information about ongoing projects, progress reports, meeting minutes, status updates.",
"Question / Request for Info": "Asking for clarification, seeking information, query about details.",
"General Info / FYI": "Newsletter, announcement, sharing information, non-actionable update."
}
print(f"\nDefined categories: {list(categories.keys())}")
# 3. Generate embeddings for Categories (pre-computation recommended)
print("\nGenerating embeddings for categories...")
category_embeddings = {}
for category_name, category_description in categories.items():
embedding = get_embedding(client, category_description)
if embedding:
category_embeddings[category_name] = embedding
else:
print(f"Skipping category '{category_name}' due to embedding error.")
if not category_embeddings:
print("\nError: No embeddings generated for categories. Cannot triage emails.")
exit()
# 4. Process Each Email: Generate Embedding and Find Best Category
print("\nTriaging emails...")
email_results = []
for email in emails:
# Combine subject and body for better context
email_content = f"Subject: {email['subject']}\nBody: {email['body_snippet']}"
email_embedding = get_embedding(client, email_content)
if not email_embedding:
print(f"Skipping email {email['id']} due to embedding error.")
continue
# Find the category with the highest similarity
best_category = None
max_similarity = -1 # Cosine similarity ranges from -1 to 1
for category_name, category_embedding in category_embeddings.items():
similarity = cosine_similarity(email_embedding, category_embedding)
print(f" Email {email['id']} vs Category '{category_name}': Score {similarity:.4f}")
if similarity > max_similarity:
max_similarity = similarity
best_category = category_name
email_results.append({
"id": email["id"],
"subject": email["subject"],
"assigned_category": best_category,
"score": max_similarity
})
print(f"-> Email {email['id']} assigned to: '{best_category}' (Score: {max_similarity:.4f})")
# 5. Display Triage Results
print("\n--- Email Triage Results ---")
if not email_results:
print("No emails were successfully triaged.")
else:
# Optional: Group by category for display
results_by_category = {cat: [] for cat in categories.keys()}
for result in email_results:
if result["assigned_category"]: # Check if category was assigned
results_by_category[result["assigned_category"]].append(result)
for category_name, items in results_by_category.items():
print(f"\nCategory: {category_name}")
print("-" * (10 + len(category_name)))
if not items:
print(" (No emails assigned)")
else:
# Sort items within category by score if desired
items.sort(key=lambda x: x['score'], reverse=True)
for item in items:
print(f" - ID: {item['id']}, Subject: \"{item['subject']}\" (Score: {item['score']:.3f})")
print("\nEmail triage process complete.")
Explicación del Desglose del Código
Este ejemplo muestra cómo los embeddings de OpenAI pueden clasificar y priorizar automáticamente los correos electrónicos mediante la comprensión de su significado, demostrando un sistema inteligente de gestión de correos.
- Configuración y Funciones Auxiliares:
- Incluye importaciones estándar (
openai
,os
,dotenv
,numpy
), inicialización del cliente, y las funciones auxiliaresget_embedding
ycosine_similarity
.
- Incluye importaciones estándar (
- Datos de Ejemplo de Correos:
- Una lista de diccionarios (
emails
) simula mensajes entrantes. Cada correo tiene unid
,subject
, y unbody_snippet
.
- Una lista de diccionarios (
- Definiciones de Categorías:
- Un diccionario (
categories
) define las categorías objetivo para la clasificación (por ejemplo, "Acción Urgente Requerida", "Actualización de Proyecto / Estado"). - Idea Clave: Cada categoría está representada por una frase descriptiva o lista de palabras clave que captura su esencia semántica. Esta descripción es lo que será convertido en embedding.
- Un diccionario (
- Generación de Embeddings de Categorías:
- El script itera a través de las
categories
definidas. - Llama a
get_embedding
sobre la descripción asociada con cada nombre de categoría. - El vector de embedding resultante para cada categoría se almacena en el diccionario
category_embeddings
. Este paso típicamente sería pre-calculado y almacenado.
- El script itera a través de las
- Bucle de Procesamiento de Correos:
- El script itera a través de cada
email
en los datos de ejemplo. - Combinación de Contenido: Combina el
subject
ybody_snippet
en una única cadenaemail_content
para proporcionar un contexto más rico para el embedding. - Embedding del Correo: Llama a
get_embedding
para obtener la representación vectorial del contenido del correo actual. - Cálculo de Similitud:
- Luego itera a través de los
category_embeddings
pre-calculados. - Para cada categoría, calcula la
cosine_similarity
entre elemail_embedding
y elcategory_embedding
. - Mantiene un registro de la
best_category
(la que tiene el puntaje de similitud más alto encontrado hasta ahora) y el correspondiente puntajemax_similarity
.
- Luego itera a través de los
- Asignación: Después de comparar el correo con todas las categorías, se le asigna la
best_category
encontrada. El resultado (ID del correo, asunto, categoría asignada, puntaje) se almacena.
- El script itera a través de cada
- Visualización de Resultados de Clasificación:
- El script imprime las asignaciones finales.
- Agrupación Opcional: Incluye lógica para agrupar los resultados por categoría asignada para una presentación más clara, mostrando qué correos cayeron en los grupos "Urgente", "Actualización", etc.
Este ejemplo demuestra efectivamente cómo los embeddings permiten una categorización inteligente basada en el significado. Un correo solicitando "aprobación ASAP" puede ser correctamente identificado como "Acción Urgente Requerida" incluso sin usar la palabra exacta "urgente", porque su embedding será semánticamente cercano al embedding de la descripción de la categoría "Acción Urgente Requerida". Esto es mucho más robusto que el simple filtrado por palabras clave.
3.2 Cuándo Usar Embeddings
Los embeddings han revolucionado la forma en que procesamos y entendemos la información textual en las aplicaciones modernas de IA. Mientras que los métodos tradicionales de procesamiento de texto dependen de coincidencias exactas o búsquedas básicas por palabras clave, los embeddings proporcionan una forma sofisticada de capturar los significados matizados y las relaciones entre fragmentos de texto. Al convertir palabras y frases en vectores numéricos de alta dimensión, los embeddings permiten que las máquinas entiendan las relaciones semánticas y similitudes de manera que se asemejan más a la comprensión humana.
Exploremos los escenarios clave donde los embeddings resultan particularmente valiosos, mostrando cómo esta tecnología transforma varios aspectos del procesamiento y recuperación de información. Entender estos casos de uso es crucial para desarrolladores y organizaciones que buscan aprovechar todo el potencial de la tecnología de embeddings en sus aplicaciones.
3.2.1 Búsqueda semántica
Encontrar información relevante basada en el significado en lugar de solo palabras clave, permitiendo resultados de búsqueda más inteligentes. A diferencia de la búsqueda tradicional basada en palabras clave que coincide con palabras o frases exactas, la búsqueda semántica comprende la intención y el significado contextual de una consulta analizando las relaciones subyacentes entre palabras y conceptos. Este enfoque avanzado permite que el sistema comprenda variaciones en el lenguaje, contexto e incluso la intención del usuario.
Por ejemplo, una búsqueda de "procesamiento del lenguaje natural" también devolvería resultados relevantes sobre "PLN," "lingüística computacional" o "análisis de texto." Cuando un usuario busca "tratamiento de síntomas del resfriado común," el sistema entendería y devolvería resultados sobre "remedios para la gripe," "reducción de la fiebre" y "medicamentos para la tos" - incluso si estas frases exactas no se utilizan. Esta tecnología aprovecha los vectores de embedding para calcular puntajes de similitud entre consultas y documentos, transformando cada fragmento de texto en una representación numérica de alta dimensión que captura su significado semántico. Este enfoque matemático permite resultados de búsqueda más matizados y precisos que tienen en cuenta:
- Sinónimos y términos relacionados (como "coche" y "automóvil")
- Relaciones conceptuales (conectando "python" tanto con programación como con serpientes, dependiendo del contexto)
- Múltiples idiomas (encontrando contenido relevante incluso cuando está escrito en diferentes idiomas)
- Variaciones contextuales (entendiendo que "apple" puede referirse tanto a la fruta como a la empresa tecnológica)
- Coincidencia de intención (reconociendo que "cómo arreglar una llanta pinchada" e "instrucciones de reparación de neumáticos" buscan la misma información)
Ejemplo:
Aquí hay un ejemplo de código que demuestra la búsqueda semántica usando embeddings de OpenAI, basado en el contenido que proporcionaste.
Este script:
- Definirá un pequeño conjunto de documentos.
- Generará embeddings para estos documentos y una consulta de búsqueda.
- Calculará la similitud entre la consulta y cada documento.
- Clasificará los documentos por relevancia basándose en la similitud semántica.
import os
from openai import OpenAI, OpenAIError
from dotenv import load_dotenv
import numpy as np # For cosine similarity calculation
import datetime
# --- Configuration ---
load_dotenv()
# Get the current date and location context
current_timestamp = "2025-03-22 15:22:00 CDT"
current_location = "Grapevine, Texas, United States"
print(f"Running Semantic Search example at: {current_timestamp}")
print(f"Location Context: {current_location}")
# Initialize the OpenAI client
try:
api_key = os.getenv("OPENAI_API_KEY")
if not api_key:
raise ValueError("OPENAI_API_KEY not found in environment variables.")
client = OpenAI(api_key=api_key)
print("OpenAI client initialized.")
except ValueError as e:
print(f"Configuration Error: {e}")
exit()
except Exception as e:
print(f"Error initializing OpenAI client: {e}")
exit()
# Define the embedding model
EMBEDDING_MODEL = "text-embedding-3-small"
# --- Helper Function to Generate Embedding ---
# (Same as in previous embeddings example)
def get_embedding(client, text, model=EMBEDDING_MODEL):
"""Generates an embedding for the given text using the specified model."""
print(f"Generating embedding for: \"{text[:50]}...\"") # Print truncated text
try:
response = client.embeddings.create(
input=text,
model=model
)
embedding_vector = response.data[0].embedding
print("Embedding generation successful.")
return embedding_vector
except OpenAIError as e:
print(f"OpenAI API Error generating embedding for text '{text[:50]}...': {e}")
return None
except Exception as e:
print(f"An unexpected error occurred during embedding generation for text '{text[:50]}...': {e}")
return None
# --- Helper Function for Cosine Similarity ---
# (Same as in previous embeddings example)
def cosine_similarity(vec_a, vec_b):
"""Calculates the cosine similarity between two vectors."""
if vec_a is None or vec_b is None:
# print("Error: Cannot calculate similarity with None vectors.")
return 0.0 # Return 0 if any vector is missing
vec_a = np.array(vec_a)
vec_b = np.array(vec_b)
norm_a = np.linalg.norm(vec_a)
norm_b = np.linalg.norm(vec_b)
if norm_a == 0 or norm_b == 0:
# print("Warning: One or both vectors have zero magnitude.")
return 0.0
else:
similarity = np.dot(vec_a, vec_b) / (norm_a * norm_b)
return similarity
# --- Semantic Search Implementation ---
# 1. Define your document store (a list of text strings)
# In a real application, this could come from a database, files, etc.
document_store = [
"The Eiffel Tower is a wrought-iron lattice tower on the Champ de Mars in Paris, France.",
"Photosynthesis is a process used by plants and other organisms to convert light energy into chemical energy.",
"Artificial intelligence research focuses on creating systems capable of performing tasks that typically require human intelligence.",
"A recipe for classic French onion soup involves caramelizing onions and topping with bread and cheese.",
"Machine learning, a subset of AI, involves algorithms that allow systems to learn from data.",
"The Louvre Museum in Paris is the world's largest art museum and a historic monument.",
"Natural Language Processing (NLP) enables computers to understand and process human language.",
"Baking bread requires careful measurement of ingredients like flour, water, yeast, and salt."
]
print(f"\nDocument store contains {len(document_store)} documents.")
# 2. Generate embeddings for all documents in the store (pre-computation)
# In a real app, you'd store these embeddings alongside the documents.
print("\nGenerating embeddings for the document store...")
document_embeddings = []
for doc in document_store:
embedding = get_embedding(client, doc)
# Store the document text and its embedding together
if embedding: # Only store if embedding was successful
document_embeddings.append({"text": doc, "embedding": embedding})
else:
print(f"Skipping document due to embedding error: \"{doc[:50]}...\"")
print(f"\nSuccessfully generated embeddings for {len(document_embeddings)} documents.")
# 3. Define the user's search query
search_query = "What is AI?"
# search_query = "Things to see in Paris"
# search_query = "How does NLP work?"
# search_query = "Cooking instructions"
print(f"\nSearch Query: \"{search_query}\"")
# 4. Generate embedding for the search query
print("\nGenerating embedding for the search query...")
query_embedding = get_embedding(client, search_query)
# 5. Calculate similarity and rank documents
search_results = []
if query_embedding and document_embeddings:
print("\nCalculating similarities...")
for doc_data in document_embeddings:
similarity = cosine_similarity(query_embedding, doc_data["embedding"])
search_results.append({"text": doc_data["text"], "score": similarity})
# Sort results by similarity score in descending order
search_results.sort(key=lambda x: x["score"], reverse=True)
# 6. Display results
print("\n--- Semantic Search Results ---")
print(f"Top results for query: \"{search_query}\"\n")
if not search_results:
print("No results found (or error calculating similarities).")
else:
# Display top N results (e.g., top 3)
top_n = 3
for i, result in enumerate(search_results[:top_n]):
print(f"{i+1}. Score: {result['score']:.4f}")
print(f" Text: {result['text']}")
print("-" * 10)
if len(search_results) > top_n:
print(f"(Showing top {top_n} of {len(search_results)} results)")
else:
print("\nCould not perform search.")
if not query_embedding:
print("Reason: Failed to generate embedding for the search query.")
if not document_embeddings:
print("Reason: No document embeddings were successfully generated.")
Explicación del Desglose del Código:
- Configuración y Funciones Auxiliares: Incluye importaciones estándar (
openai
,os
,dotenv
,numpy
), inicialización del cliente, y las funciones auxiliaresget_embedding
ycosine_similarity
del ejemplo anterior. - Almacén de Documentos: Una lista simple de Python (
document_store
) contiene el texto de los documentos que queremos buscar. En una aplicación real, estos datos probablemente provendrían de una base de datos o sistema de archivos. - Generación de Embeddings de Documentos:
- El script itera a través de cada documento en el
document_store
. - Llama a
get_embedding
para cada documento para obtener su representación numérica. - Almacena el texto original del documento y su vector de embedding correspondiente juntos (por ejemplo, en una lista de diccionarios). Este paso de pre-computación es crucial para la eficiencia en sistemas reales – generas los embeddings de documentos una vez y los almacenas. El manejo de errores asegura que los documentos se omitan si falla la generación del embedding.
- El script itera a través de cada documento en el
- Consulta de Búsqueda: Se define una cadena de ejemplo
search_query
. - Generación del Embedding de Consulta: La función
get_embedding
se llama nuevamente, esta vez para elsearch_query
. - Cálculo de Similitud y Clasificación:
- Verifica si tanto el embedding de consulta como los embeddings de documentos se generaron exitosamente.
- Itera a través de los
document_embeddings
almacenados. - Para cada documento, calcula la
cosine_similarity
entre elquery_embedding
y el embedding del documento. - El texto del documento y su puntaje de similitud calculado se almacenan en una lista
search_results
. - Finalmente,
search_results.sort(...)
ordena la lista basándose en elscore
en orden descendente (mayor similitud primero).
- Mostrar Resultados: El script imprime los N (por ejemplo, 3) documentos más relevantes de la lista ordenada, mostrando su puntaje de similitud y contenido de texto.
Este ejemplo ilustra claramente el concepto central de la búsqueda semántica: convertir tanto los documentos como las consultas en embeddings y luego usar la similitud vectorial (como la similitud del coseno) para encontrar documentos que están semánticamente relacionados con la consulta, incluso si no comparten las palabras clave exactas.
3.2.2 Agrupamiento por temas
El agrupamiento por temas es una técnica sofisticada para organizar y analizar grandes colecciones de documentos mediante su agrupación automática basada en su contenido semántico. Esta aplicación avanzada de embeddings transforma la manera en que procesamos y entendemos colecciones de documentos a gran escala, ofreciendo una poderosa solución para la organización de contenido. El sistema funciona convirtiendo cada documento en un vector de embedding multidimensional que captura su significado, y luego utiliza algoritmos de agrupamiento para juntar vectores similares.
Esta poderosa aplicación de embeddings permite a los sistemas:
- Identificar patrones temáticos a través de miles de documentos sin etiquetado manual - el sistema puede detectar automáticamente temas y tendencias comunes a través de vastas colecciones de documentos, ahorrando incontables horas de trabajo de categorización manual
- Agrupar discusiones, artículos o piezas de contenido similares en categorías intuitivas - al comprender las relaciones semánticas entre documentos, el sistema puede crear agrupaciones significativas que reflejan divisiones naturales de temas, incluso cuando los documentos utilizan terminología diferente para discutir los mismos conceptos
- Descubrir temas y tendencias emergentes dentro de grandes colecciones de documentos - a medida que se agrega nuevo contenido, el sistema puede identificar nuevos grupos temáticos que se están formando, ayudando a las organizaciones a mantenerse al día con las tendencias en desarrollo en su campo
- Crear jerarquías de contenido dinámicas que se adaptan cuando se agregan nuevos documentos - a diferencia de los sistemas de categorización estática tradicionales, el agrupamiento basado en embeddings puede reorganizar y refinar automáticamente las estructuras de categorías a medida que la colección de contenido crece y evoluciona
Por ejemplo, una organización de noticias podría usar el agrupamiento por temas para agrupar automáticamente miles de artículos en categorías como "Tecnología", "Política" o "Deportes", incluso cuando estos temas no están etiquetados explícitamente. Los embeddings capturan las relaciones semánticas entre artículos analizando el significado real y el contexto del contenido, no solo palabras clave. Esto permite un agrupamiento mucho más sofisticado que puede entender distinciones sutiles - por ejemplo, reconociendo que un artículo sobre el impacto económico de los estadios deportivos pertenece tanto a las categorías "Deportes" como "Negocios", o que artículos sobre diferentes lenguajes de programación pertenecen todos a un grupo de "Tecnología" a pesar de usar terminología completamente diferente.
Ejemplo:
A continuación se muestra un ejemplo de código que demuestra el agrupamiento por temas usando embeddings de OpenAI y el algoritmo K-means de scikit-learn
.
Este código:
- Definirá una lista de documentos de ejemplo que cubren diferentes temas implícitos.
- Generará embeddings para cada documento usando la API de OpenAI.
- Aplicará el algoritmo de agrupamiento K-Means para agrupar los vectores de embedding.
- Mostrará los documentos pertenecientes a cada grupo identificado.
import os
from openai import OpenAI, OpenAIError
from dotenv import load_dotenv
import numpy as np
from sklearn.cluster import KMeans # For clustering algorithm
import datetime
# --- Configuration ---
load_dotenv()
# Get the current date and location context
current_timestamp = "2025-03-23 15:26:00 CDT"
current_location = "Dallas, Texas, United States"
print(f"Running Topic Clustering example at: {current_timestamp}")
print(f"Location Context: {current_location}")
# Initialize the OpenAI client
try:
api_key = os.getenv("OPENAI_API_KEY")
if not api_key:
raise ValueError("OPENAI_API_KEY not found in environment variables.")
client = OpenAI(api_key=api_key)
print("OpenAI client initialized.")
except ValueError as e:
print(f"Configuration Error: {e}")
exit()
except Exception as e:
print(f"Error initializing OpenAI client: {e}")
exit()
# Define the embedding model
EMBEDDING_MODEL = "text-embedding-3-small"
# --- Helper Function to Generate Embedding ---
# (Same as in previous embeddings examples)
def get_embedding(client, text, model=EMBEDDING_MODEL):
"""Generates an embedding for the given text using the specified model."""
# Truncate text for printing if it's too long
print_text = text[:70] + "..." if len(text) > 70 else text
print(f"Generating embedding for: \"{print_text}\"")
try:
response = client.embeddings.create(
input=text,
model=model
)
embedding_vector = response.data[0].embedding
# print("Embedding generation successful.") # Reduce verbosity
return embedding_vector
except OpenAIError as e:
print(f"OpenAI API Error generating embedding for text '{print_text}': {e}")
return None
except Exception as e:
print(f"An unexpected error occurred during embedding generation for text '{print_text}': {e}")
return None
# --- Topic Clustering Implementation ---
# 1. Define your collection of documents
# These documents cover roughly 3 topics: AI/Tech, Travel/Geography, Food/Cooking
documents = [
"Artificial intelligence research focuses on creating systems capable of performing tasks that typically require human intelligence.",
"The Eiffel Tower is a wrought-iron lattice tower on the Champ de Mars in Paris, France.",
"A recipe for classic French onion soup involves caramelizing onions and topping with bread and cheese.",
"Machine learning, a subset of AI, involves algorithms that allow systems to learn from data.",
"The Great Wall of China is a series of fortifications made of stone, brick, tamped earth, wood, and other materials.",
"Natural Language Processing (NLP) enables computers to understand and process human language.",
"Baking bread requires careful measurement of ingredients like flour, water, yeast, and salt.",
"The Colosseum in Rome, Italy, is an oval amphitheatre in the centre of the city.",
"Deep learning utilizes artificial neural networks with multiple layers to model complex patterns.",
"Sushi is a traditional Japanese dish of prepared vinegared rice, usually with some sugar and salt, accompanying a variety of ingredients, such as seafood, often raw, and vegetables."
]
print(f"\nDocument collection contains {len(documents)} documents.")
# 2. Generate embeddings for all documents
print("\nGenerating embeddings for the document collection...")
embeddings = []
valid_documents = [] # Keep track of documents for which embedding was successful
for doc in documents:
embedding = get_embedding(client, doc)
if embedding:
embeddings.append(embedding)
valid_documents.append(doc) # Add corresponding document text
else:
print(f"Skipping document due to embedding error: \"{doc[:70]}...\"")
if not embeddings:
print("\nError: No embeddings were generated. Cannot perform clustering.")
exit()
print(f"\nSuccessfully generated embeddings for {len(valid_documents)} documents.")
# Convert embeddings list to a NumPy array for scikit-learn
embedding_matrix = np.array(embeddings)
# 3. Apply Clustering Algorithm (K-Means)
# We need to choose the number of clusters (k). Let's assume we expect 3 topics.
# In real applications, determining the optimal 'k' often requires experimentation
# (e.g., using the elbow method or silhouette scores).
n_clusters = 3
print(f"\nApplying K-Means clustering with k={n_clusters}...")
try:
kmeans = KMeans(n_clusters=n_clusters, random_state=42, n_init=10) # n_init suppresses warning
kmeans.fit(embedding_matrix)
cluster_labels = kmeans.labels_
print("Clustering complete.")
except Exception as e:
print(f"An error occurred during clustering: {e}")
exit()
# 4. Display Documents by Cluster
print(f"\n--- Documents Grouped by Topic Cluster (k={n_clusters}) ---")
# Create a dictionary to hold documents for each cluster
clustered_documents = {i: [] for i in range(n_clusters)}
# Assign each document (that had a valid embedding) to its cluster
for i, label in enumerate(cluster_labels):
clustered_documents[label].append(valid_documents[i])
# Print the contents of each cluster
for cluster_id, docs_in_cluster in clustered_documents.items():
print(f"\nCluster {cluster_id + 1}:")
if not docs_in_cluster:
print(" (No documents in this cluster)")
else:
for doc_text in docs_in_cluster:
# Print truncated document text for readability
print_text = doc_text[:100] + "..." if len(doc_text) > 100 else doc_text
print(f" - {print_text}")
print("-" * 20)
print("\nNote: The quality of clustering depends on the data, the embedding model,")
print("and the chosen number of clusters (k). Cluster numbers are arbitrary.")
Explicación del Desglose del Código:
- Configuración y Funciones Auxiliares:
- Incluye importaciones estándar más
KMeans
desklearn.cluster
. - Inicializa el cliente de OpenAI.
- Incluye la función auxiliar
get_embedding
(igual que antes).
- Incluye importaciones estándar más
- Colección de Documentos: Una lista llamada
documents
contiene el contenido de texto. Los documentos de muestra están elegidos para representar algunos temas subyacentes distintos (IA/Tecnología, Viajes/Geografía, Comida/Cocina). - Generación de Embeddings:
- El script itera a través de los
documents
. - Llama a
get_embedding
para cada documento. - Almacena los embeddings exitosos en la lista
embeddings
y el texto del documento correspondiente envalid_documents
. Esto asegura que los índices coincidan posteriormente. - El manejo de errores omite documentos si falla la generación del embedding.
- La lista de vectores de embedding se convierte en un array de NumPy (
embedding_matrix
), que es el formato de entrada estándar para los algoritmos descikit-learn
.
- El script itera a través de los
- Agrupamiento (K-Means):
- Elección de
k
: El número de grupos (n_clusters
) se establece (aquí,k=3
, asumiendo que esperamos tres temas basados en los datos de muestra). Un comentario destaca que encontrar elk
óptimo es frecuentemente una tarea separada en escenarios del mundo real. - Inicialización: Se crea un objeto
KMeans
.n_clusters
especifica el número deseado de grupos.random_state
asegura la reproducibilidad.n_init=10
ejecuta el algoritmo múltiples veces con diferentes centroides iniciales y elige el mejor resultado (suprime una advertencia futura). - Ajuste:
kmeans.fit(embedding_matrix)
ejecuta el algoritmo de agrupamiento K-Means en los embeddings de documentos. Encuentra los centros de los grupos y asigna cada vector de embedding al centro más cercano. - Etiquetas:
kmeans.labels_
contiene un array donde cada elemento indica el ID del grupo (0, 1, 2, etc.) asignado al embedding del documento correspondiente.
- Elección de
- Mostrar Resultados:
- Se crea un diccionario (
clustered_documents
) para organizar los resultados, con claves que representan los IDs de los grupos. - El script itera a través de las
cluster_labels
asignadas por K-Means. Para cada índicei
de documento, encuentra sulabel
asignada y añade el texto correspondiente devalid_documents[i]
a la lista para ese ID de grupo en el diccionario. - Finalmente, recorre el diccionario
clustered_documents
e imprime el texto de los documentos pertenecientes a cada grupo, agrupándolos claramente por el grupo temático identificado por el algoritmo.
- Se crea un diccionario (
Este ejemplo demuestra el poder de los embeddings para el descubrimiento de temas no supervisado. Al convertir texto en vectores, podemos usar algoritmos matemáticos como K-Means para agrupar documentos semánticamente similares sin necesidad de etiquetas predefinidas.
3.2.3 Sistemas de Recomendación
Sugerir elementos relacionados mediante la comprensión de las conexiones más profundas entre diferentes piezas de contenido. Esta poderosa aplicación de los embeddings permite a los sistemas proporcionar recomendaciones personalizadas analizando las relaciones semánticas entre elementos. Los vectores de embedding capturan patrones sutiles y similitudes que podrían no ser inmediatamente obvios para los observadores humanos.
Así es como los sistemas de recomendación aprovechan los embeddings:
- Filtrado Basado en Contenido
- Los sistemas analizan las características reales del contenido (como descripciones de texto, características o atributos)
- Cada elemento se convierte en un vector de embedding que representa sus características principales
- Los elementos similares se encuentran midiendo la distancia entre estos vectores
- Mejora del Filtrado Colaborativo
- Los comportamientos y preferencias de los usuarios también se convierten en embeddings
- El sistema puede identificar patrones en las interacciones usuario-elemento
- Esto ayuda a predecir qué elementos podría gustarle a un usuario basándose en las preferencias de usuarios similares
Por ejemplo, un servicio de streaming de video puede recomendar programas no solo basándose en etiquetas de género, sino entendiendo elementos temáticos, estilos narrativos y patrones narrativos complejos. Los vectores de embedding pueden capturar características matizadas como:
- Ritmo y complejidad de la trama
- Estilos de desarrollo de personajes
- Tono emocional y atmósfera
- Técnicas visuales y de dirección
De manera similar, las plataformas de comercio electrónico pueden sugerir productos entendiendo las similitudes contextuales en las descripciones de productos, el comportamiento del usuario y las características de los artículos. Esto incluye analizar:
- Descripciones y características de productos
- Patrones de navegación y compra de usuarios
- Niveles de precio y calidad
- Relaciones entre marcas y posicionamiento en el mercado
Esta comprensión semántica lleva a recomendaciones más precisas y relevantes en comparación con los métodos tradicionales que dependen únicamente de categorías explícitas o calificaciones de usuarios. El sistema puede identificar conexiones sutiles y patrones que podrían pasarse por alto con enfoques convencionales de recomendación, resultando en experiencias de usuario más atractivas y personalizadas.
Ejemplo:
El siguiente ejemplo de código demuestra cómo los embeddings de OpenAI pueden utilizarse para construir un sistema de recomendación simple basado en contenido.
Este script:
- Definirá un pequeño catálogo de elementos (por ejemplo, descripciones de películas).
- Generará embeddings para estos elementos.
- Elegirá un elemento objetivo.
- Encontrará otros elementos en el catálogo que sean semánticamente similares al elemento objetivo basándose en sus embeddings.
- Presentará los elementos más similares como recomendaciones.
import os
from openai import OpenAI, OpenAIError
from dotenv import load_dotenv
import numpy as np # For cosine similarity calculation
import datetime
# --- Configuration ---
load_dotenv()
# Get the current date and location context
current_timestamp = "2025-03-24 15:29:00 CDT"
current_location = "Austin, Texas, United States"
print(f"Running Recommendation System example at: {current_timestamp}")
print(f"Location Context: {current_location}")
# Initialize the OpenAI client
try:
api_key = os.getenv("OPENAI_API_KEY")
if not api_key:
raise ValueError("OPENAI_API_KEY not found in environment variables.")
client = OpenAI(api_key=api_key)
print("OpenAI client initialized.")
except ValueError as e:
print(f"Configuration Error: {e}")
exit()
except Exception as e:
print(f"Error initializing OpenAI client: {e}")
exit()
# Define the embedding model
EMBEDDING_MODEL = "text-embedding-3-small"
# --- Helper Function to Generate Embedding ---
# (Same as in previous embeddings examples)
def get_embedding(client, text, model=EMBEDDING_MODEL):
"""Generates an embedding for the given text using the specified model."""
# Truncate text for printing if it's too long
print_text = text[:70] + "..." if len(text) > 70 else text
print(f"Generating embedding for: \"{print_text}\"")
try:
response = client.embeddings.create(
input=text,
model=model
)
embedding_vector = response.data[0].embedding
# print("Embedding generation successful.") # Reduce verbosity
return embedding_vector
except OpenAIError as e:
print(f"OpenAI API Error generating embedding for text '{print_text}': {e}")
return None
except Exception as e:
print(f"An unexpected error occurred during embedding generation for text '{print_text}': {e}")
return None
# --- Helper Function for Cosine Similarity ---
# (Same as in previous embeddings examples)
def cosine_similarity(vec_a, vec_b):
"""Calculates the cosine similarity between two vectors."""
if vec_a is None or vec_b is None:
return 0.0 # Return 0 if any vector is missing
vec_a = np.array(vec_a)
vec_b = np.array(vec_b)
norm_a = np.linalg.norm(vec_a)
norm_b = np.linalg.norm(vec_b)
if norm_a == 0 or norm_b == 0:
return 0.0
else:
similarity = np.dot(vec_a, vec_b) / (norm_a * norm_b)
return similarity
# --- Recommendation System Implementation ---
# 1. Define your item catalog (e.g., movie descriptions)
# In a real application, this would come from a database.
item_catalog = [
{"id": "mov001", "title": "Space Odyssey: The Final Frontier", "description": "A visually stunning sci-fi epic exploring humanity's place in the universe, featuring complex themes and groundbreaking special effects."},
{"id": "mov002", "title": "Galactic Wars: Attack of the Clones", "description": "An action-packed space opera with laser battles, alien creatures, and a classic good versus evil storyline."},
{"id": "com001", "title": "Laugh Riot", "description": "A slapstick comedy about mistaken identities and hilarious mishaps during a weekend getaway."},
{"id": "doc001", "title": "Wonders of the Deep", "description": "An awe-inspiring documentary showcasing the beauty and mystery of marine life in the world's oceans."},
{"id": "mov003", "title": "Cyber City 2077", "description": "A gritty cyberpunk thriller set in a dystopian future, exploring themes of technology, consciousness, and rebellion."},
{"id": "com002", "title": "The Office Party", "description": "A witty ensemble comedy centered around awkward interactions and office politics during an annual holiday celebration."},
{"id": "doc002", "title": "Cosmic Journeys", "description": "A documentary exploring the vastness of space, black holes, distant galaxies, and the search for extraterrestrial life."},
{"id": "mov004", "title": "Interstellar Echoes", "description": "A philosophical science fiction film about astronauts travelling through a wormhole in search of a new home for humanity."}
]
print(f"\nItem catalog contains {len(item_catalog)} items.")
# 2. Generate embeddings for all items in the catalog (pre-computation)
print("\nGenerating embeddings for the item catalog...")
item_embeddings_data = []
for item in item_catalog:
# Combine title and description for a richer embedding
text_to_embed = f"{item['title']}: {item['description']}"
embedding = get_embedding(client, text_to_embed)
if embedding:
# Store item ID and its embedding
item_embeddings_data.append({"id": item["id"], "embedding": embedding})
else:
print(f"Skipping item {item['id']} due to embedding error.")
if not item_embeddings_data:
print("\nError: No embeddings were generated. Cannot provide recommendations.")
exit()
print(f"\nSuccessfully generated embeddings for {len(item_embeddings_data)} items.")
# 3. Select a target item for which to find recommendations
target_item_id = "mov001" # Let's find movies similar to "Space Odyssey"
print(f"\nFinding recommendations similar to item ID: {target_item_id}")
# Find the embedding for the target item
target_embedding = None
for item_data in item_embeddings_data:
if item_data["id"] == target_item_id:
target_embedding = item_data["embedding"]
break
if target_embedding is None:
print(f"Error: Could not find the embedding for the target item ID '{target_item_id}'.")
exit()
# 4. Calculate similarity between the target item and all other items
recommendations = []
print("\nCalculating similarities...")
for item_data in item_embeddings_data:
# Don't compare the item with itself
if item_data["id"] == target_item_id:
continue
similarity = cosine_similarity(target_embedding, item_data["embedding"])
recommendations.append({"id": item_data["id"], "score": similarity})
# 5. Sort potential recommendations by similarity score
recommendations.sort(key=lambda x: x["score"], reverse=True)
# 6. Display top N recommendations
print("\n--- Top Recommendations ---")
# Find the original title/description for the target item for context
target_item_info = next((item for item in item_catalog if item["id"] == target_item_id), None)
if target_item_info:
print(f"Based on: \"{target_item_info['title']}\"\n")
if not recommendations:
print("No recommendations found (or error calculating similarities).")
else:
top_n = 3
print(f"Top {top_n} most similar items:")
for i, rec in enumerate(recommendations[:top_n]):
# Find the full item details from the original catalog
rec_details = next((item for item in item_catalog if item["id"] == rec["id"]), None)
if rec_details:
print(f"{i+1}. ID: {rec['id']}, Score: {rec['score']:.4f}")
print(f" Title: {rec_details['title']}")
print(f" Description: {rec_details['description'][:100]}...") # Truncate description
print("-" * 10)
else:
print(f"{i+1}. ID: {rec['id']}, Score: {rec['score']:.4f} (Details not found)")
print("-" * 10)
if len(recommendations) > top_n:
print(f"(Showing top {top_n} of {len(recommendations)} potential recommendations)")
Explicación del Desglose del Código
Este ejemplo demuestra cómo construir un sistema de recomendación basado en contenido de manera sencilla combinando los embeddings de OpenAI con cálculos de similitud del coseno.
- Configuración y Funciones Auxiliares:
- Incluye importaciones estándar (
openai
,os
,dotenv
,numpy
), inicialización del cliente, y las funciones auxiliaresget_embedding
ycosine_similarity
previamente definidas.
- Incluye importaciones estándar (
- Catálogo de Elementos:
- Una lista de diccionarios (
item_catalog
) representa los elementos disponibles para recomendación (por ejemplo, películas). Cada elemento tiene unid
,título
ydescripción
. En un sistema real, esto probablemente se cargaría desde una base de datos.
- Una lista de diccionarios (
- Generación de Embeddings de Elementos:
- El script itera a través de cada
item
en elitem_catalog
. - Combinación de Contenido: Combina el
título
y ladescripción
en una sola cadena (text_to_embed
). Esto proporciona un contexto más rico al modelo de embedding que usar solo el título o la descripción por separado. - Llama a
get_embedding
para este texto combinado. - Almacena el
item['id']
y su vector deembedding
correspondiente juntos en la listaitem_embeddings_data
. Este paso de pre-cómputo es una práctica estándar para sistemas de recomendación.
- El script itera a través de cada
- Selección del Elemento Objetivo:
- Una variable
target_item_id
se establece para especificar el elemento para el cual queremos recomendaciones (por ejemplo, encontrar elementos similares amov001
). - El script recupera el vector de embedding pre-calculado para este
target_item_id
de la listaitem_embeddings_data
.
- Una variable
- Cálculo de Similitud:
- Itera a través de todos los elementos con embeddings en
item_embeddings_data
. - Exclusión: Explícitamente omite la comparación si el ID del elemento actual coincide con el
target_item_id
(un elemento no debería recomendarse a sí mismo). - Para cada otro elemento, calcula la
similitud_coseno
entre eltarget_embedding
y el embedding del elemento actual. - Almacena el
id
del otro elemento y supuntuación
de similitud calculada en una lista derecommendations
.
- Itera a través de todos los elementos con embeddings en
- Clasificación de Recomendaciones:
- La lista
recommendations
se ordena usandorecommendations.sort(...)
basándose en el camposcore
en orden descendente, colocando los elementos más similares al principio de la lista.
- La lista
- Mostrar Resultados:
- El script imprime el título del elemento objetivo para contexto.
- Luego itera a través de los N principales (por ejemplo, 3) elementos en la lista ordenada de
recommendations
. - Para cada ID de elemento recomendado, busca los detalles completos (título, descripción) del
item_catalog
original. - Imprime el rango, ID, puntuación de similitud, título y una descripción truncada para cada elemento recomendado.
Este ejemplo muestra efectivamente cómo los embeddings capturan el significado semántico, permitiendo que el sistema recomiende elementos basándose en la similitud de contenido (por ejemplo, recomendando otras películas de ciencia ficción filosóficas similares a "Space Odyssey") en lugar de solo etiquetas explícitas o historial del usuario.
3.2.4 Recuperación de contexto para asistentes de IA
Ayudar a los chatbots y sistemas de IA a encontrar y utilizar información relevante de grandes bases de conocimiento mediante la conversión tanto de consultas como de conocimiento almacenado en embeddings. Este proceso involucra varios pasos clave:
Primero, el sistema convierte todos los documentos en su base de conocimiento en vectores de embedding - representaciones numéricas que capturan el significado semántico del texto. Estos embeddings se almacenan en una base de datos vectorial para una recuperación rápida.
Cuando un asistente de IA recibe una pregunta, convierte esa consulta en un vector de embedding usando el mismo proceso. Esto asegura que tanto el conocimiento almacenado como las preguntas entrantes estén representados en el mismo espacio matemático.
El sistema luego realiza una búsqueda de similitud para encontrar la información más relevante. Esta búsqueda compara el embedding de la consulta con todos los embeddings almacenados, típicamente usando técnicas como similitud del coseno o búsqueda del vecino más cercano. La belleza de este enfoque es que puede identificar contenido semánticamente similar incluso cuando la redacción exacta difiere significativamente.
Por ejemplo, una consulta sobre "el portátil no enciende" podría coincidir con documentación sobre "problemas de energía en computadoras" porque sus embeddings capturan el significado subyacente similar. Esta coincidencia semántica es mucho más potente que la búsqueda tradicional basada en palabras clave.
Una vez que se identifica la información relevante, puede utilizarse para generar respuestas más precisas e informadas. Esto es particularmente potente para aplicaciones específicas de dominio donde la IA necesita acceder a documentación técnica, información de productos o políticas empresariales. El sistema puede manejar consultas complejas combinando múltiples piezas de contexto relevante, asegurando que las respuestas sean tanto precisas como exhaustivas.
Ejemplo:
A continuación se muestra un ejemplo de código que demuestra cómo los asistentes de IA pueden recuperar contexto usando embeddings de OpenAI, implementando los conceptos discutidos en la sección 3.2.4.
El script ilustra el proceso esencial de búsqueda en una base de conocimiento para proporcionar contexto relevante para las respuestas del asistente de IA.
import os
from openai import OpenAI, OpenAIError
from dotenv import load_dotenv
import numpy as np # For cosine similarity calculation
import datetime
# --- Configuration ---
load_dotenv()
# Get the current date and location context
current_timestamp = "2025-02-10 15:35:00 CDT"
current_location = "Grapevine, Texas, United States"
print(f"Running Context Retrieval example at: {current_timestamp}")
print(f"Location Context: {current_location}")
# Initialize the OpenAI client
try:
api_key = os.getenv("OPENAI_API_KEY")
if not api_key:
raise ValueError("OPENAI_API_KEY not found in environment variables.")
client = OpenAI(api_key=api_key)
print("OpenAI client initialized.")
except ValueError as e:
print(f"Configuration Error: {e}")
exit()
except Exception as e:
print(f"Error initializing OpenAI client: {e}")
exit()
# Define the embedding model
EMBEDDING_MODEL = "text-embedding-3-small"
# --- Helper Function to Generate Embedding ---
# (Same as in previous embeddings examples)
def get_embedding(client, text, model=EMBEDDING_MODEL):
"""Generates an embedding for the given text using the specified model."""
print_text = text[:70] + "..." if len(text) > 70 else text
print(f"Generating embedding for: \"{print_text}\"")
try:
response = client.embeddings.create(
input=text,
model=model
)
embedding_vector = response.data[0].embedding
return embedding_vector
except OpenAIError as e:
print(f"OpenAI API Error generating embedding for text '{print_text}': {e}")
return None
except Exception as e:
print(f"An unexpected error occurred during embedding generation for text '{print_text}': {e}")
return None
# --- Helper Function for Cosine Similarity ---
# (Same as in previous embeddings examples)
def cosine_similarity(vec_a, vec_b):
"""Calculates the cosine similarity between two vectors."""
if vec_a is None or vec_b is None:
return 0.0
vec_a = np.array(vec_a)
vec_b = np.array(vec_b)
norm_a = np.linalg.norm(vec_a)
norm_b = np.linalg.norm(vec_b)
if norm_a == 0 or norm_b == 0:
return 0.0
else:
similarity = np.dot(vec_a, vec_b) / (norm_a * norm_b)
return similarity
# --- Context Retrieval Implementation ---
# 1. Define your Knowledge Base (list of text documents/chunks)
# This represents the information the AI assistant can draw upon.
knowledge_base = [
{"id": "doc001", "source": "troubleshooting_guide.txt", "content": "If your laptop fails to power on, first check the power adapter connection. Ensure the cable is securely plugged into both the laptop and the wall outlet. Try a different outlet if possible."},
{"id": "doc002", "source": "troubleshooting_guide.txt", "content": "A blinking power light often indicates a battery issue or a charging problem. Try removing the battery (if removable) and powering on with only the adapter connected."},
{"id": "doc003", "source": "faq.html", "content": "To reset your password, go to the login page and click the 'Forgot Password' link. Follow the instructions sent to your registered email address."},
{"id": "doc004", "source": "product_manual.pdf", "content": "The Model X laptop uses a USB-C port for charging. Ensure you are using the correct wattage power adapter (65W minimum recommended)."},
{"id": "doc005", "source": "troubleshooting_guide.txt", "content": "No display output? Check if the laptop is making any sounds (fan spinning, beeps). Try connecting an external monitor to rule out a screen issue."},
{"id": "doc006", "source": "support_articles/power_issues.md", "content": "Holding the power button down for 15-30 seconds can perform a hard reset, sometimes resolving power-on failures."},
{"id": "doc007", "source": "faq.html", "content": "Software updates can be found in the 'System Settings' under the 'Updates' section. Ensure you are connected to the internet."}
]
print(f"\nKnowledge base contains {len(knowledge_base)} documents/chunks.")
# 2. Generate embeddings for the knowledge base (pre-computation)
print("\nGenerating embeddings for the knowledge base...")
kb_embeddings_data = []
for doc in knowledge_base:
embedding = get_embedding(client, doc["content"])
if embedding:
# Store document ID and its embedding
kb_embeddings_data.append({"id": doc["id"], "embedding": embedding})
else:
print(f"Skipping document {doc['id']} due to embedding error.")
if not kb_embeddings_data:
print("\nError: No embeddings were generated for the knowledge base. Cannot retrieve context.")
exit()
print(f"\nSuccessfully generated embeddings for {len(kb_embeddings_data)} knowledge base documents.")
# 3. Define the user's query to the AI assistant
user_query = "My computer won't start up."
# user_query = "How do I update the system software?"
# user_query = "Screen is black when I press the power button."
print(f"\nUser Query: \"{user_query}\"")
# 4. Generate embedding for the user query
print("\nGenerating embedding for the user query...")
query_embedding = get_embedding(client, user_query)
# 5. Find relevant documents from the knowledge base using similarity search
retrieved_context = []
if query_embedding and kb_embeddings_data:
print("\nCalculating similarities to find relevant context...")
for doc_data in kb_embeddings_data:
similarity = cosine_similarity(query_embedding, doc_data["embedding"])
retrieved_context.append({"id": doc_data["id"], "score": similarity})
# Sort context documents by similarity score in descending order
retrieved_context.sort(key=lambda x: x["score"], reverse=True)
# 6. Select Top N relevant documents to use as context
top_n_context = 3
print(f"\n--- Top {top_n_context} Relevant Context Documents Found ---")
if not retrieved_context:
print("No relevant context found (or error calculating similarities).")
else:
final_context_docs = []
for i, context_item in enumerate(retrieved_context[:top_n_context]):
# Find the full document details from the original knowledge base
doc_details = next((doc for doc in knowledge_base if doc["id"] == context_item["id"]), None)
if doc_details:
print(f"{i+1}. ID: {context_item['id']}, Score: {context_item['score']:.4f}")
print(f" Source: {doc_details['source']}")
print(f" Content: {doc_details['content'][:150]}...") # Truncate content
print("-" * 10)
final_context_docs.append(doc_details['content']) # Store content for next step
else:
print(f"{i+1}. ID: {context_item['id']}, Score: {context_item['score']:.4f} (Details not found)")
print("-" * 10)
if len(retrieved_context) > top_n_context:
print(f"(Showing top {top_n_context} of {len(retrieved_context)} potential context documents)")
# --- Next Step (Conceptual - Not coded here) ---
print("\n--- Next Step: Generating AI Assistant Response ---")
print("The content from the relevant documents above would now be combined")
print("with the original user query and sent to a model like GPT-4o")
print("as context to generate an informed and accurate response.")
print("Example prompt structure for GPT-4o:")
print("```")
print(f"System: You are a helpful AI assistant. Answer the user's question based ONLY on the provided context documents.")
print(f"User: Context Documents:\n1. {final_context_docs[0][:50]}...\n2. {final_context_docs[1][:50]}...\n[...]\n\nQuestion: {user_query}\n\nAnswer:")
print("```")
else:
print("\nCould not retrieve context.")
if not query_embedding:
print("Reason: Failed to generate embedding for the user query.")
if not kb_embeddings_data:
print("Reason: No knowledge base embeddings were successfully generated.")
Explicación del Desglose del Código
Este ejemplo demuestra el mecanismo central detrás de la recuperación de contexto para asistentes de IA usando embeddings – encontrar información relevante de una base de conocimiento para responder a la consulta de un usuario.
- Configuración y Funciones Auxiliares:
- Incluye importaciones estándar (
openai
,os
,dotenv
,numpy
), inicialización del cliente, y las funciones auxiliaresget_embedding
ycosine_similarity
.
- Incluye importaciones estándar (
- Definición de la Base de Conocimiento:
- Una lista de diccionarios (
knowledge_base
) simula el almacén de información al que puede acceder el asistente de IA. Cada diccionario representa un documento o fragmento de información e incluye unid
,source
(metadatos opcionales), y elcontent
del texto actual.
- Una lista de diccionarios (
- Generación de Embeddings de la Base de Conocimiento:
- El script itera a través de cada
doc
en elknowledge_base
. - Llama a
get_embedding
en eldoc["content"]
para obtener su representación vectorial. - Almacena el
doc['id']
y su correspondiente vectorembedding
juntos enkb_embeddings_data
. Este es el paso crucial de pre-computación – los embeddings para la base de conocimiento típicamente se generan fuera de línea y se almacenan (a menudo en una base de datos vectorial especializada) para una recuperación rápida.
- El script itera a través de cada
- Consulta del Usuario:
- Una cadena de ejemplo
user_query
representa la pregunta realizada al asistente de IA.
- Una cadena de ejemplo
- Generación del Embedding de la Consulta:
- La función
get_embedding
se llama para eluser_query
para obtener su representación vectorial en el mismo espacio de embeddings que los documentos de la base de conocimiento.
- La función
- Búsqueda de Similitud (Recuperación de Contexto):
- Itera a través de todos los embeddings pre-computados en
kb_embeddings_data
. - Para cada documento de la base de conocimiento, calcula la
cosine_similarity
entre elquery_embedding
y el embedding del documento. - Almacena el
id
del documento y suscore
de similitud relativo a la consulta en una listaretrieved_context
.
- Itera a través de todos los embeddings pre-computados en
- Clasificación y Selección:
- La lista
retrieved_context
se ordena porscore
en orden descendente, trayendo los documentos semánticamente más relevantes al principio. - El script selecciona los N primeros (por ejemplo, 3) documentos de esta lista ordenada. Estos documentos representan el contexto más relevante encontrado en la base de conocimiento para la consulta del usuario.
- La lista
- Mostrar el Contexto Recuperado:
- El script imprime los detalles (ID, puntuación, fuente, vista previa del contenido) de los N primeros documentos de contexto encontrados.
- Siguiente Paso Conceptual (Explicación Crucial):
- Las declaraciones finales de impresión explican el propósito de este proceso de recuperación. El contenido de estos
final_context_docs
no sería la respuesta final. En su lugar, se combinarían con eluser_query
original y se pasarían como contexto a un modelo de lenguaje grande como GPT-4o en una llamada API subsiguiente. - Se muestra una estructura de prompt de ejemplo, ilustrando cómo el contexto recuperado fundamenta al asistente de IA, permitiéndole generar una respuesta informada basada en la información relevante encontrada en la base de conocimiento, en lugar de confiar únicamente en su conocimiento general.
- Las declaraciones finales de impresión explican el propósito de este proceso de recuperación. El contenido de estos
Este ejemplo demuestra efectivamente la parte de recuperación de la Generación Aumentada por Recuperación (RAG), mostrando cómo los embeddings tienden un puente entre la consulta de un usuario y la información relevante almacenada en una base de conocimiento, permitiendo asistentes de IA más precisos y conscientes del contexto.
3.2.5 Detección de anomalías y similitud
Identificar patrones inusuales o encontrar elementos similares en grandes conjuntos de datos mediante la comparación de sus representaciones semánticas es una aplicación fundamental de la tecnología de embeddings. Esta poderosa técnica transforma datos sin procesar en vectores matemáticos que capturan la esencia de su contenido, permitiendo análisis sofisticados a gran escala. Así es cómo funcionan estos sistemas y sus aplicaciones clave:
- Detectar Anomalías
- Marcar transacciones o comportamientos inusuales que se desvían de los patrones normales - Por ejemplo, detectar compras sospechosas con tarjeta de crédito comparándolas con patrones típicos de gasto
- Identificar posibles amenazas de seguridad o intentos de fraude - Como reconocer patrones de inicio de sesión inusuales o detectar cuentas falsas basadas en análisis de comportamiento
- Detectar problemas de calidad de datos o valores atípicos en conjuntos de datos - Incluyendo la identificación de entradas de datos incorrectas o mediciones inusuales que podrían indicar mal funcionamiento del equipo
- Encontrar Similitudes
- Agrupar documentos, imágenes o puntos de datos relacionados basados en significado semántico - Esto permite a los sistemas agrupar contenido similar incluso cuando la redacción exacta difiere, facilitando la organización de grandes colecciones de información
- Emparejar consultas o tickets de soporte similares - Ayudando a los equipos de servicio al cliente a identificar problemas comunes y estandarizar respuestas a problemas frecuentes
- Identificar contenido duplicado o casi duplicado - Útil para sistemas de gestión de contenido para mantener la calidad de datos y reducir la redundancia
Al convertir puntos de datos en vectores de embedding, los sistemas pueden medir qué tan "diferentes" o "similares" son los elementos entre sí usando cálculos de distancia matemática. Este proceso funciona mapeando cada elemento a un punto en un espacio de alta dimensión, donde los elementos similares se posicionan más cerca entre sí y los elementos diferentes están más separados. Esta representación matemática hace posible marcar automáticamente patrones inusuales o agrupar elementos relacionados a gran escala, permitiendo tanto la detección de anomalías como la coincidencia de similitud de formas que serían imposibles con sistemas tradicionales basados en reglas.
Ejemplo:
El siguiente ejemplo de código demuestra la detección de similitud y anomalías usando embeddings de OpenAI.
Este script:
- Definirá un conjunto de datos de elementos de texto (por ejemplo, descripciones de transacciones o eventos).
- Generará embeddings para estos elementos.
- Detección de Similitud: Encontrará elementos más similares a un elemento objetivo dado.
- Detección de Anomalías: Identificará elementos que son menos similares (más anómalos) comparados con el resto del conjunto de datos usando un enfoque simple de similitud promedio.
import os
from openai import OpenAI, OpenAIError
from dotenv import load_dotenv
import numpy as np # For cosine similarity calculation
import datetime
# --- Configuration ---
load_dotenv()
# Get the current date and location context
current_timestamp = "2025-01-13 15:40:00 CDT"
current_location = "Houston, Texas, United States"
print(f"Running Similarity & Anomaly Detection example at: {current_timestamp}")
print(f"Location Context: {current_location}")
# Initialize the OpenAI client
try:
api_key = os.getenv("OPENAI_API_KEY")
if not api_key:
raise ValueError("OPENAI_API_KEY not found in environment variables.")
client = OpenAI(api_key=api_key)
print("OpenAI client initialized.")
except ValueError as e:
print(f"Configuration Error: {e}")
exit()
except Exception as e:
print(f"Error initializing OpenAI client: {e}")
exit()
# Define the embedding model
EMBEDDING_MODEL = "text-embedding-3-small"
# --- Helper Function to Generate Embedding ---
# (Same as in previous embeddings examples)
def get_embedding(client, text, model=EMBEDDING_MODEL):
"""Generates an embedding for the given text using the specified model."""
print_text = text[:70] + "..." if len(text) > 70 else text
print(f"Generating embedding for: \"{print_text}\"")
try:
response = client.embeddings.create(
input=text,
model=model
)
embedding_vector = response.data[0].embedding
return embedding_vector
except OpenAIError as e:
print(f"OpenAI API Error generating embedding for text '{print_text}': {e}")
return None
except Exception as e:
print(f"An unexpected error occurred during embedding generation for text '{print_text}': {e}")
return None
# --- Helper Function for Cosine Similarity ---
# (Same as in previous embeddings examples)
def cosine_similarity(vec_a, vec_b):
"""Calculates the cosine similarity between two vectors."""
if vec_a is None or vec_b is None:
return 0.0
vec_a = np.array(vec_a)
vec_b = np.array(vec_b)
norm_a = np.linalg.norm(vec_a)
norm_b = np.linalg.norm(vec_b)
if norm_a == 0 or norm_b == 0:
return 0.0
else:
# Clamp the value to handle potential floating point inaccuracies slightly outside [-1, 1]
similarity = np.dot(vec_a, vec_b) / (norm_a * norm_b)
return np.clip(similarity, -1.0, 1.0)
# --- Similarity and Anomaly Detection Implementation ---
# 1. Define your dataset (e.g., transaction descriptions, log entries)
# Includes mostly normal items and a couple of potentially anomalous ones.
dataset = [
{"id": "txn001", "description": "Grocery purchase at Local Supermarket"},
{"id": "txn002", "description": "Monthly subscription fee for streaming service"},
{"id": "txn003", "description": "Dinner payment at Italian Restaurant"},
{"id": "txn004", "description": "Online order for electronics from TechStore"},
{"id": "txn005", "description": "Fuel purchase at Gas Station"},
{"id": "txn006", "description": "Purchase of fresh produce and bread"}, # Similar to txn001
{"id": "txn007", "description": "Payment for movie streaming subscription"}, # Similar to txn002
{"id": "txn008", "description": "Unusual large wire transfer to overseas account"}, # Potential Anomaly 1
{"id": "txn009", "description": "Purchase of rare antique collectible vase"}, # Potential Anomaly 2
{"id": "txn010", "description": "Coffee purchase at Cafe Central"}
]
print(f"\nDataset contains {len(dataset)} items.")
# 2. Generate embeddings for all items in the dataset (pre-computation)
print("\nGenerating embeddings for the dataset...")
dataset_embeddings_data = []
for item in dataset:
embedding = get_embedding(client, item["description"])
if embedding:
# Store item ID, description, and its embedding
dataset_embeddings_data.append({
"id": item["id"],
"description": item["description"],
"embedding": embedding
})
else:
print(f"Skipping item {item['id']} due to embedding error.")
if not dataset_embeddings_data:
print("\nError: No embeddings were generated. Cannot perform analysis.")
exit()
print(f"\nSuccessfully generated embeddings for {len(dataset_embeddings_data)} items.")
# --- Part A: Similarity Detection ---
print("\n--- Part A: Similarity Detection ---")
# Select a target item to find similar items for
target_item_id_similarity = "txn001" # Find items similar to "Grocery purchase..."
print(f"Finding items similar to item ID: {target_item_id_similarity}")
# Find the target item's data
target_item_data = next((item for item in dataset_embeddings_data if item["id"] == target_item_id_similarity), None)
if target_item_data:
target_embedding = target_item_data["embedding"]
similar_items = []
# Calculate similarity between the target and all other items
for item_data in dataset_embeddings_data:
if item_data["id"] == target_item_id_similarity:
continue # Skip self-comparison
similarity = cosine_similarity(target_embedding, item_data["embedding"])
similar_items.append({
"id": item_data["id"],
"description": item_data["description"],
"score": similarity
})
# Sort by similarity score
similar_items.sort(key=lambda x: x["score"], reverse=True)
# Display top N similar items
print(f"\nItems most similar to: \"{target_item_data['description']}\"")
top_n_similar = 2
for i, item in enumerate(similar_items[:top_n_similar]):
print(f"{i+1}. ID: {item['id']}, Score: {item['score']:.4f}")
print(f" Description: {item['description']}")
print("-" * 10)
else:
print(f"Error: Could not find data for target item ID '{target_item_id_similarity}'.")
# --- Part B: Anomaly Detection (Simple Approach) ---
print("\n--- Part B: Anomaly Detection (Low Average Similarity) ---")
# Calculate the average similarity of each item to all other items
item_avg_similarities = []
num_items = len(dataset_embeddings_data)
if num_items < 2:
print("Need at least 2 items with embeddings to calculate average similarities.")
else:
print("\nCalculating average similarities for anomaly detection...")
for i in range(num_items):
current_item = dataset_embeddings_data[i]
total_similarity = 0
# Compare current item to all others
for j in range(num_items):
if i == j: # Don't compare item to itself
continue
other_item = dataset_embeddings_data[j]
similarity = cosine_similarity(current_item["embedding"], other_item["embedding"])
total_similarity += similarity
# Calculate average similarity (avoid division by zero if only 1 item)
average_similarity = total_similarity / (num_items - 1) if num_items > 1 else 0
item_avg_similarities.append({
"id": current_item["id"],
"description": current_item["description"],
"avg_score": average_similarity
})
print(f"Item ID {current_item['id']} - Avg Similarity: {average_similarity:.4f}")
# Sort items by average similarity in ascending order (lowest first = most anomalous)
item_avg_similarities.sort(key=lambda x: x["avg_score"])
# Display top N potential anomalies (items least similar to others)
print("\nPotential Anomalies (Lowest Average Similarity):")
top_n_anomalies = 3
for i, item in enumerate(item_avg_similarities[:top_n_anomalies]):
print(f"{i+1}. ID: {item['id']}, Avg Score: {item['avg_score']:.4f}")
print(f" Description: {item['description']}")
print("-" * 10)
print("\nNote: Low average similarity suggests an item is semantically")
print("different from the majority of other items in this dataset.")
Explicación del Desglose del Código
Este ejemplo demuestra el uso de embeddings de OpenAI tanto para encontrar elementos similares como para detectar posibles anomalías dentro de un conjunto de datos basándose en el significado semántico.
- Configuración y Funciones Auxiliares:
- Incluye importaciones estándar (
openai
,os
,dotenv
,numpy
), inicialización del cliente, y las funciones auxiliaresget_embedding
ycosine_similarity
. La funcióncosine_similarity
ahora incluyenp.clip
para asegurar que la salida esté estrictamente dentro de [-1, 1].
- Incluye importaciones estándar (
- Definición del Conjunto de Datos:
- Una lista de diccionarios (
dataset
) simula los datos a analizar (por ejemplo, descripciones de transacciones). Cada elemento tiene unid
y unadescription
de texto. Los datos de muestra incluyen principalmente elementos comunes y algunos conceptualmente diferentes destinados a ser posibles anomalías.
- Una lista de diccionarios (
- Generación de Embeddings del Conjunto de Datos:
- El script itera a través de cada
item
en eldataset
. - Llama a
get_embedding
en elitem["description"]
. - Almacena el
item['id']
,item['description']
, y su correspondiente vectorembedding
juntos endataset_embeddings_data
. Esta pre-computación es esencial.
- El script itera a través de cada
- Parte A: Detección de Similitud:
- Selección del Objetivo: Se elige un ID de elemento (
target_item_id_similarity
) para encontrar elementos similares. - Recuperación del Embedding Objetivo: El script encuentra el embedding pre-computado para el elemento objetivo.
- Comparación: Itera a través de todos los otros elementos en
dataset_embeddings_data
, calcula lacosine_similarity
entre el embedding del elemento objetivo y el embedding de cada otro elemento. - Clasificación: Los resultados (ID del otro elemento, descripción, puntuación de similitud) se almacenan y luego se ordenan por puntuación en orden descendente.
- Visualización: Se muestran los N elementos más similares.
- Selección del Objetivo: Se elige un ID de elemento (
- Parte B: Detección de Anomalías (Enfoque de Similitud Promedio Simple):
- Concepto: Este método simple identifica anomalías como elementos que tienen la similitud promedio más baja con todos los otros elementos en el conjunto de datos. Un elemento que es conceptualmente muy diferente del resto probablemente tendrá puntuaciones de similitud bajas cuando se compare con la mayoría de los otros.
- Cálculo:
- El script itera a través de cada elemento (
current_item
) endataset_embeddings_data
. - Para cada
current_item
, itera a través de todos los otros elementos en el conjunto de datos. - Calcula la
cosine_similarity
entre elcurrent_item
y cadaother_item
. - Suma estas similitudes y calcula la similitud promedio para el
current_item
.
- El script itera a través de cada elemento (
- Clasificación: Los elementos se almacenan junto con su
avg_score
calculado y luego se ordenan por esta puntuación en orden ascendente (similitud promedio más baja primero). - Visualización: Se muestran los N elementos con las puntuaciones de similitud promedio más bajas como posibles anomalías. Una nota explica la interpretación.
Este ejemplo muestra dos aplicaciones poderosas: encontrar contenido relacionado (similitud) e identificar valores atípicos (detección de anomalías) aprovechando la comprensión semántica capturada dentro de los embeddings de OpenAI.
3.2.6 Agrupamiento y Etiquetado
Organizar y etiquetar contenido automáticamente basándose en la similitud semántica - una técnica poderosa que utiliza vectores de embedding para comprender el verdadero significado y las relaciones entre diferentes piezas de contenido. Este enfoque va mucho más allá del tradicional emparejamiento de palabras clave, permitiendo una organización de contenido mucho más matizada y precisa.
Cuando el contenido se agrupa, los elementos similares se agrupan naturalmente según su significado semántico, incluso si utilizan terminología diferente para expresar los mismos conceptos. Por ejemplo, los documentos sobre "mantenimiento automotriz" y "reparación de coches" se agruparían juntos a pesar de usar palabras diferentes.
Esta organización inteligente ayuda a crear sistemas de navegación intuitivos, mejora el descubrimiento de contenido y hace que las grandes colecciones de documentos sean más manejables al agrupar elementos relacionados. Algunos beneficios clave incluyen:
- Generación automática de etiquetas basada en temas de grupos
- Organización dinámica que se adapta a medida que se agrega nuevo contenido
- Mejora de la relevancia en las búsquedas mediante comprensión semántica
- Mejor descubrimiento de contenido a través de sugerencias de elementos relacionados
El proceso de agrupamiento puede ajustarse para crear categorías amplias o subcategorías más granulares, dependiendo de las necesidades específicas de su sistema de organización de contenido. Esta flexibilidad lo convierte en una herramienta valiosa para gestionar desde bibliotecas digitales hasta bases de conocimiento empresariales.
Ejemplo:
Examinemos un ejemplo de código que demuestra el agrupamiento y etiquetado usando embeddings de OpenAI y GPT-4o.
Este script:
- Definirá una colección de documentos.
- Generará embeddings para los documentos.
- Agrupará los documentos usando K-Means basándose en sus embeddings.
- Para cada grupo, usará GPT-4o para analizar los documentos dentro de él y generar una etiqueta o descriptor descriptivo.
- Mostrará los documentos agrupados por cluster junto con sus etiquetas generadas por IA.
import os
from openai import OpenAI, OpenAIError
from dotenv import load_dotenv
import numpy as np
from sklearn.cluster import KMeans # For clustering algorithm
import datetime
# --- Configuration ---
load_dotenv()
# Get the current date and location context
current_timestamp = "2024-12-31 15:48:00 CDT"
current_location = "San Antonio, Texas, United States"
print(f"Running Clustering & Tagging example at: {current_timestamp}")
print(f"Location Context: {current_location}")
# Initialize the OpenAI client
try:
api_key = os.getenv("OPENAI_API_KEY")
if not api_key:
raise ValueError("OPENAI_API_KEY not found in environment variables.")
client = OpenAI(api_key=api_key)
print("OpenAI client initialized.")
except ValueError as e:
print(f"Configuration Error: {e}")
exit()
except Exception as e:
print(f"Error initializing OpenAI client: {e}")
exit()
# Define the embedding model
EMBEDDING_MODEL = "text-embedding-3-small"
# --- Helper Function to Generate Embedding ---
# (Same as in previous embeddings examples)
def get_embedding(client, text, model=EMBEDDING_MODEL):
"""Generates an embedding for the given text using the specified model."""
print_text = text[:70] + "..." if len(text) > 70 else text
print(f"Generating embedding for: \"{print_text}\"")
try:
response = client.embeddings.create(
input=text,
model=model
)
embedding_vector = response.data[0].embedding
return embedding_vector
except OpenAIError as e:
print(f"OpenAI API Error generating embedding for text '{print_text}': {e}")
return None
except Exception as e:
print(f"An unexpected error occurred during embedding generation for text '{print_text}': {e}")
return None
# --- Helper Function to Generate Cluster Tag using GPT-4o ---
def generate_cluster_tag(client, documents_in_cluster):
"""Uses GPT-4o to suggest a tag/label for a cluster of documents."""
if not documents_in_cluster:
return "Empty Cluster"
# Combine content for context, limiting total length if necessary
# Using first few hundred chars of each doc might be enough
max_context_length = 3000 # Limit context to avoid excessive token usage
context = ""
for i, doc in enumerate(documents_in_cluster):
doc_preview = f"Document {i+1}: {doc[:300]}...\n"
if len(context) + len(doc_preview) > max_context_length:
break
context += doc_preview
if not context:
return "Error: Could not create context"
system_prompt = "You are an expert at identifying themes and creating concise labels."
user_prompt = f"""Based on the following document excerpts from a single cluster, suggest a short, descriptive tag or label (2-5 words) that captures the main theme or topic of this group.
Document Excerpts:
---
{context.strip()}
---
Suggested Tag/Label:
"""
print(f"\nGenerating tag for cluster with {len(documents_in_cluster)} documents...")
try:
response = client.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_prompt}
],
max_tokens=20, # Short response expected
temperature=0.3 # More deterministic label
)
tag = response.choices[0].message.content.strip().replace('"', '') # Clean up quotes
print(f"Generated tag: '{tag}'")
return tag
except OpenAIError as e:
print(f"OpenAI API Error generating tag: {e}")
return "Tagging Error"
except Exception as e:
print(f"An unexpected error occurred during tag generation: {e}")
return "Tagging Error"
# --- Clustering and Tagging Implementation ---
# 1. Define your collection of documents
# Covers topics: Space Exploration, Cooking/Food, Web Development
documents = [
"NASA launches new probe to study Jupiter's moons.",
"Recipe for authentic Italian pasta carbonara.",
"JavaScript frameworks like React and Vue dominate front-end development.",
"The James Webb Space Telescope captures stunning images of distant galaxies.",
"Tips for baking the perfect sourdough bread at home.",
"Understanding asynchronous programming in Node.js.",
"SpaceX successfully lands its reusable rocket booster after launch.",
"Exploring the different types of olive oil and their uses in cooking.",
"CSS Grid vs Flexbox: Choosing the right layout module.",
"The search for habitable exoplanets continues with new telescope data.",
"How to make delicious homemade pizza from scratch.",
"Building RESTful APIs using Express.js and MongoDB."
]
print(f"\nDocument collection contains {len(documents)} documents.")
# 2. Generate embeddings for all documents
print("\nGenerating embeddings for the document collection...")
embeddings = []
valid_documents = [] # Keep track of documents for which embedding was successful
for doc in documents:
embedding = get_embedding(client, doc)
if embedding:
embeddings.append(embedding)
valid_documents.append(doc) # Add corresponding document text
else:
print(f"Skipping document due to embedding error: \"{doc[:70]}...\"")
if not embeddings:
print("\nError: No embeddings were generated. Cannot perform clustering.")
exit()
print(f"\nSuccessfully generated embeddings for {len(valid_documents)} documents.")
# Convert embeddings list to a NumPy array for scikit-learn
embedding_matrix = np.array(embeddings)
# 3. Apply Clustering Algorithm (K-Means)
# Choose the number of clusters (k). We expect 3 topics here.
n_clusters = 3
print(f"\nApplying K-Means clustering with k={n_clusters}...")
try:
kmeans = KMeans(n_clusters=n_clusters, random_state=42, n_init=10)
kmeans.fit(embedding_matrix)
cluster_labels = kmeans.labels_
print("Clustering complete.")
except Exception as e:
print(f"An error occurred during clustering: {e}")
exit()
# 4. Group Documents by Cluster
print("\nGrouping documents by cluster...")
clustered_documents = {i: [] for i in range(n_clusters)}
for i, label in enumerate(cluster_labels):
clustered_documents[label].append(valid_documents[i])
# 5. Generate Tags for Each Cluster using GPT-4o
print("\nGenerating tags for each cluster...")
cluster_tags = {}
for cluster_id, docs_in_cluster in clustered_documents.items():
tag = generate_cluster_tag(client, docs_in_cluster)
cluster_tags[cluster_id] = tag
# 6. Display Documents by Cluster with Generated Tags
print(f"\n--- Documents Grouped by Cluster and Tag (k={n_clusters}) ---")
for cluster_id, docs_in_cluster in clustered_documents.items():
generated_tag = cluster_tags.get(cluster_id, "Unknown Tag")
print(f"\nCluster {cluster_id + 1} - Suggested Tag: '{generated_tag}'")
print("-" * (28 + len(generated_tag))) # Adjust underline length
if not docs_in_cluster:
print(" (No documents in this cluster)")
else:
for doc_text in docs_in_cluster:
print(f" - {doc_text}") # Print full document text here
print("\nClustering and Tagging process complete.")
Explicación del Desglose del Código
Este script demuestra cómo agrupar automáticamente documentos similares por su significado semántico usando embeddings, y luego utiliza GPT-4o para generar etiquetas descriptivas para cada grupo.
- Configuración y Funciones Auxiliares:
- Incluye importaciones estándar más
KMeans
desklearn.cluster
. - Inicializa el cliente de OpenAI.
- Incluye la función auxiliar
get_embedding
.
- Incluye importaciones estándar más
- Nueva Función Auxiliar:
generate_cluster_tag
:- Propósito: Toma una lista de documentos pertenecientes a un único clúster y utiliza GPT-4o para sugerir una etiqueta concisa que resuma su tema común.
- Entrada: El objeto
client
ydocuments_in_cluster
(una lista de cadenas de texto). - Creación de Contexto: Concatena partes de los documentos (por ejemplo, los primeros 300 caracteres) para crear una cadena de contexto para GPT-4o, respetando una longitud máxima para gestionar el uso de tokens.
- Ingeniería de Prompt: Construye un prompt pidiendo a GPT-4o que actúe como un experto en identificación de temas y sugiera una etiqueta corta (2-5 palabras) basada en los extractos de documentos proporcionados.
- Llamada a la API: Utiliza
client.chat.completions.create
conmodel="gpt-4o"
y el prompt especializado. Se usa una temperatura baja para una generación de etiquetas más enfocada. - Salida: Devuelve la etiqueta sugerida por GPT-4o depurada, o un mensaje de error.
- Colección de Documentos: Una lista llamada
documents
contiene contenido de texto de muestra que abarca varios temas distintos (Espacio, Cocina, Desarrollo Web). - Generación de Embeddings:
- El script itera a través de los
documents
, genera un embedding para cada uno usandoget_embedding
, y almacena los embeddings exitosos y el texto correspondiente enembeddings
yvalid_documents
. - Los embeddings se convierten a un array de NumPy (
embedding_matrix
).
- El script itera a través de los
- Agrupamiento (K-Means):
- El número de clústeres (
n_clusters
) se establece (por ejemplo,k=3
). KMeans
descikit-learn
se inicializa y se ajusta a laembedding_matrix
.kmeans.labels_
proporciona la asignación de clúster para cada documento.
- El número de clústeres (
- Agrupación de Documentos:
- Se crea un diccionario (
clustered_documents
) para almacenar el texto de los documentos pertenecientes a cada ID de clúster.
- Se crea un diccionario (
- Generación de Etiquetas de Clúster:
- El script itera a través del diccionario
clustered_documents
. - Para cada
cluster_id
y su lista dedocs_in_cluster
, llama a la función auxiliargenerate_cluster_tag
. - La etiqueta sugerida para cada clúster se almacena en el diccionario
cluster_tags
.
- El script itera a través del diccionario
- Visualización de Resultados:
- El script itera nuevamente a través de los clústeres.
- Para cada clúster, recupera la etiqueta generada de
cluster_tags
. - Imprime el número del clúster, la etiqueta sugerida, y luego lista el texto completo de todos los documentos pertenecientes a ese clúster.
Este ejemplo muestra un flujo de trabajo potente: usar embeddings para el agrupamiento no supervisado de contenido basado en significado (clustering) y luego aprovechar un LLM como GPT-4o para interpretar esos grupos y asignar etiquetas significativas (etiquetado), automatizando la organización del contenido.
3.2.7 Recomendaciones de Contenido
Los sistemas de recomendación de contenido impulsados por embeddings representan un avance significativo en la tecnología de personalización. Al analizar relaciones semánticas, estos sistemas pueden entender el significado matizado y el contexto del contenido de maneras que los sistemas tradicionales basados en palabras clave no pueden.
Aquí hay una mirada detallada a cómo funcionan las recomendaciones basadas en embeddings:
- Análisis de Contenido:
- El sistema genera vectores de embedding sofisticados para cada pieza de contenido en la base de datos
- Estos vectores capturan características matizadas como estilo de escritura, profundidad del tema y tono emocional
- Los algoritmos avanzados analizan patrones a través de múltiples dimensiones de características de contenido
- Modelado de Preferencias del Usuario:
- El sistema rastrea patrones detallados de interacción incluyendo tiempo dedicado, nivel de participación y comportamiento de compartir
- Las preferencias históricas se ponderan y combinan para crear perfiles de usuario multidimensionales
- Se consideran tanto la retroalimentación explícita (calificaciones, me gusta) como las señales implícitas (profundidad de desplazamiento, visitas repetidas)
- Comprensión Contextual:
- Los factores en tiempo real como el tipo de dispositivo y la ubicación se incorporan al algoritmo de recomendación
- El sistema identifica patrones en el consumo de contenido basados en la hora del día y el día de la semana
- El comportamiento de la sesión actual se analiza para entender los intereses inmediatos del usuario
- Adaptación Dinámica:
- Los modelos de aprendizaje automático refinan continuamente los perfiles de usuario basados en nuevas interacciones
- El sistema aprende tanto de la retroalimentación positiva como negativa para mejorar la precisión
- Las estrategias de recomendación se ajustan automáticamente según las métricas de rendimiento
Este enfoque sofisticado permite que los motores de recomendación entreguen experiencias altamente personalizadas a través de varias capacidades clave:
- Identificar similitudes de contenido que podrían no ser aparentes a través de metadatos tradicionales
- Puede detectar conexiones temáticas entre elementos incluso cuando utilizan terminología diferente
- Reconoce estilos de escritura similares, tono y niveles de complejidad en el contenido
- Entender la progresión de los intereses del usuario a lo largo del tiempo
- Rastrea cómo evolucionan las preferencias desde temas básicos hasta avanzados
- Identifica cambios en los intereses del usuario a través de diferentes categorías
- Hacer recomendaciones entre dominios (por ejemplo, sugerir artículos basados en videos vistos)
- Conecta contenido a través de diferentes tipos de medios basándose en relaciones semánticas
- Aprovecha el aprendizaje de un dominio para mejorar las recomendaciones en otro
- Tener en cuenta tendencias estacionales y relevancia temporal
- Ajusta las recomendaciones basándose en factores sensibles al tiempo como festividades o eventos
- Considera las tendencias actuales y su impacto en los intereses del usuario
El resultado es una experiencia altamente personalizada que puede sugerir videos, artículos o productos verdaderamente relevantes que coincidan con los intereses de los usuarios, tanto actuales como en evolución. Esto va mucho más allá de los simples algoritmos de "a los usuarios que les gustó X también les gustó Y", creando una experiencia de usuario más atractiva y valiosa.
Ejemplo:
Aquí hay un ejemplo de código que demuestra el concepto central de recomendaciones de contenido usando embeddings.
Este script se centra en encontrar elementos de contenido semánticamente similares basados en sus embeddings, que es la base para las características de recomendación más avanzadas que describiste.
import os
from openai import OpenAI, OpenAIError
from dotenv import load_dotenv
import numpy as np # For cosine similarity calculation
import datetime
# --- Configuration ---
load_dotenv()
# Get the current date and location context
current_timestamp = "2024-11-30 15:52:00 CDT"
current_location = "Orlando, Florida, United States"
print(f"Running Content Recommendation example at: {current_timestamp}")
print(f"Location Context: {current_location}")
# Initialize the OpenAI client
try:
api_key = os.getenv("OPENAI_API_KEY")
if not api_key:
raise ValueError("OPENAI_API_KEY not found in environment variables.")
client = OpenAI(api_key=api_key)
print("OpenAI client initialized.")
except ValueError as e:
print(f"Configuration Error: {e}")
exit()
except Exception as e:
print(f"Error initializing OpenAI client: {e}")
exit()
# Define the embedding model
EMBEDDING_MODEL = "text-embedding-3-small"
# --- Helper Function to Generate Embedding ---
# (Same as in previous embeddings examples)
def get_embedding(client, text, model=EMBEDDING_MODEL):
"""Generates an embedding for the given text using the specified model."""
print_text = text[:70] + "..." if len(text) > 70 else text
print(f"Generating embedding for: \"{print_text}\"")
try:
response = client.embeddings.create(
input=text,
model=model
)
embedding_vector = response.data[0].embedding
return embedding_vector
except OpenAIError as e:
print(f"OpenAI API Error generating embedding for text '{print_text}': {e}")
return None
except Exception as e:
print(f"An unexpected error occurred during embedding generation for text '{print_text}': {e}")
return None
# --- Helper Function for Cosine Similarity ---
# (Same as in previous embeddings examples)
def cosine_similarity(vec_a, vec_b):
"""Calculates the cosine similarity between two vectors."""
if vec_a is None or vec_b is None:
return 0.0
vec_a = np.array(vec_a)
vec_b = np.array(vec_b)
norm_a = np.linalg.norm(vec_a)
norm_b = np.linalg.norm(vec_b)
if norm_a == 0 or norm_b == 0:
return 0.0
else:
similarity = np.dot(vec_a, vec_b) / (norm_a * norm_b)
return np.clip(similarity, -1.0, 1.0) # Ensure value is within valid range
# --- Content Recommendation Implementation ---
# 1. Define your Content Catalog (e.g., articles, blog posts)
# In a real application, this would come from a database or CMS.
content_catalog = [
{"id": "art001", "title": "Introduction to Quantum Computing", "content": "Exploring the basics of qubits, superposition, and entanglement in quantum mechanics and their potential for computation."},
{"id": "art002", "title": "Healthy Mediterranean Diet Recipes", "content": "Delicious and easy recipes focusing on fresh vegetables, olive oil, fish, and whole grains for a heart-healthy lifestyle."},
{"id": "art003", "title": "The Future of Artificial Intelligence in Healthcare", "content": "How AI and machine learning are transforming diagnostics, drug discovery, and personalized medicine."},
{"id": "art004", "title": "Beginner's Guide to Python Programming", "content": "Learn the fundamentals of Python syntax, data types, control flow, and functions to start coding."},
{"id": "art005", "title": "Understanding Neural Networks and Deep Learning", "content": "An overview of artificial neural networks, backpropagation, and the concepts behind deep learning models."},
{"id": "art006", "title": "Travel Guide: Hiking the Swiss Alps", "content": "Tips for planning your trip, recommended trails, essential gear, and stunning viewpoints in the Swiss Alps."},
{"id": "art007", "title": "Mastering the Art of French Pastry", "content": "Techniques for creating classic French desserts like croissants, macarons, and éclairs."},
{"id": "art008", "title": "Ethical Considerations in AI Development", "content": "Discussing bias, fairness, transparency, and accountability in the development and deployment of artificial intelligence systems."}
]
print(f"\nContent catalog contains {len(content_catalog)} items.")
# 2. Generate embeddings for all content items (pre-computation)
print("\nGenerating embeddings for the content catalog...")
content_embeddings_data = []
for item in content_catalog:
# Use title and content for embedding
text_to_embed = f"Title: {item['title']}\nContent: {item['content']}"
embedding = get_embedding(client, text_to_embed)
if embedding:
# Store item ID and its embedding
content_embeddings_data.append({"id": item["id"], "embedding": embedding})
else:
print(f"Skipping item {item['id']} due to embedding error.")
if not content_embeddings_data:
print("\nError: No embeddings were generated. Cannot provide recommendations.")
exit()
print(f"\nSuccessfully generated embeddings for {len(content_embeddings_data)} content items.")
# 3. Select a target item (e.g., an article the user just read)
target_item_id = "art003" # User read "The Future of Artificial Intelligence in Healthcare"
print(f"\nFinding content similar to item ID: {target_item_id}")
# Find the embedding for the target item
target_embedding = None
for item_data in content_embeddings_data:
if item_data["id"] == target_item_id:
target_embedding = item_data["embedding"]
break
if target_embedding is None:
print(f"Error: Could not find the embedding for the target item ID '{target_item_id}'.")
exit()
# 4. Calculate similarity between the target item and all other items
recommendations = []
print("\nCalculating similarities...")
for item_data in content_embeddings_data:
# Don't recommend the item itself
if item_data["id"] == target_item_id:
continue
similarity = cosine_similarity(target_embedding, item_data["embedding"])
recommendations.append({"id": item_data["id"], "score": similarity})
# 5. Sort potential recommendations by similarity score
recommendations.sort(key=lambda x: x["score"], reverse=True)
# 6. Display top N recommendations
print("\n--- Top Content Recommendations ---")
# Find the original title for the target item for context
target_item_info = next((item for item in content_catalog if item["id"] == target_item_id), None)
if target_item_info:
print(f"Because you read: \"{target_item_info['title']}\"\n")
if not recommendations:
print("No recommendations found (or error calculating similarities).")
else:
top_n = 3
print(f"Top {top_n} recommended items:")
for i, rec in enumerate(recommendations[:top_n]):
# Find the full item details from the original catalog
rec_details = next((item for item in content_catalog if item["id"] == rec["id"]), None)
if rec_details:
print(f"{i+1}. ID: {rec['id']}, Similarity Score: {rec['score']:.4f}")
print(f" Title: {rec_details['title']}")
print(f" Content Snippet: {rec_details['content'][:100]}...") # Truncate content
print("-" * 10)
else:
print(f"{i+1}. ID: {rec['id']}, Score: {rec['score']:.4f} (Details not found)")
print("-" * 10)
if len(recommendations) > top_n:
print(f"(Showing top {top_n} of {len(recommendations)} potential recommendations)")
print("\nNote: This demonstrates basic content-to-content similarity.")
print("Advanced systems incorporate user profiles, interaction history, context, etc.")
Explicación del Desglose del Código
Este script demuestra un enfoque fundamental para la recomendación de contenido utilizando embeddings de OpenAI, centrándose en encontrar elementos semánticamente similares a un elemento objetivo.
- Configuración y Funciones Auxiliares:
- Incluye importaciones estándar (
openai
,os
,dotenv
,numpy
), inicialización del cliente, y las funciones auxiliaresget_embedding
ycosine_similarity
.
- Incluye importaciones estándar (
- Catálogo de Contenido:
- Una lista de diccionarios (
content_catalog
) simula el contenido disponible (por ejemplo, artículos). Cada elemento tiene unid
,title
ycontent
.
- Una lista de diccionarios (
- Generación de Embeddings de Contenido (Pre-computación):
- El script itera sobre cada
item
en elcontent_catalog
. - Texto Combinado: Crea una cadena de texto combinada del
title
ycontent
del elemento para generar un embedding más rico que capture más detalle semántico. - Llama a
get_embedding
para este texto combinado. - Almacena el
item['id']
y su vectorembedding
encontent_embeddings_data
. Esta pre-computación es vital para la eficiencia.
- El script itera sobre cada
- Selección del Elemento Objetivo:
- Se elige un
target_item_id
(por ejemplo,art003
), simulando un elemento con el que el usuario ha interactuado (por ejemplo, leído). - El script recupera el embedding pre-computado para este elemento objetivo.
- Se elige un
- Cálculo de Similitud:
- Itera a través de todos los otros elementos en
content_embeddings_data
. - Calcula la
cosine_similarity
entre eltarget_embedding
y el embedding de cada otro elemento. - Almacena el
id
del otro elemento y suscore
de similitud en la listarecommendations
.
- Itera a través de todos los otros elementos en
- Clasificación de Recomendaciones:
- La lista
recommendations
se ordena porscore
en orden descendente, colocando primero los elementos de contenido más similares semánticamente.
- La lista
- Visualización de Resultados:
- El script muestra el título del elemento objetivo para dar contexto ("Porque has leído...").
- Muestra los N principales elementos recomendados (por ejemplo, 3), mostrando su ID, puntuación de similitud, título y un fragmento de su contenido.
- Nota Contextual: Las declaraciones finales mencionan explícitamente que este ejemplo muestra una similitud básica de contenido a contenido. Los sistemas de recomendación avanzados, como se describe en el texto de la sección, integrarían perfiles de usuario (embeddings basados en el historial de interacciones), contexto en tiempo real (tiempo, ubicación), retroalimentación explícita y potencialmente algoritmos más complejos más allá de la simple similitud del coseno. Sin embargo, el principio fundamental de usar embeddings para medir la relación semántica sigue siendo fundamental.
Este ejemplo ilustra efectivamente cómo los embeddings permiten recomendaciones basadas en la comprensión del significado del contenido, permitiendo sugerencias que van más allá de la simple coincidencia de palabras clave o categorías.
3.2.8 Clasificación y Priorización de Correos Electrónicos
La tecnología de embeddings permite un análisis y categorización sofisticados de correos electrónicos mediante la comprensión del significado semántico de los mensajes. Este sistema avanzado emplea múltiples capas de análisis para optimizar la gestión del correo electrónico:
- Detección de Urgencia
- Identificar asuntos urgentes que requieren atención inmediata mediante procesamiento del lenguaje natural
- Reconocer patrones de lenguaje urgente y señales contextuales analizando la elección de palabras, estructura de oraciones y patrones históricos
- Marcar correos críticos basándose en la importancia del remitente, palabras clave y jerarquía organizacional
- Categorización Inteligente
- Agrupar hilos de correo y conversaciones relacionadas mediante coincidencia de similitud semántica
- Clasificar mensajes por proyecto, departamento o función empresarial mediante análisis de contenido
- Crear carpetas dinámicas basadas en temas y tendencias emergentes
- Aplicar aprendizaje automático para mejorar la precisión de categorización con el tiempo
- Clasificación de Intención
- Distinguir entre solicitudes, actualizaciones y mensajes informativos mediante comprensión avanzada del lenguaje natural
- Priorizar elementos de acción y delegar tareas automáticamente según contenido y contexto
- Identificar requisitos de seguimiento y establecer recordatorios automáticos
- Extraer plazos y compromisos clave del contenido del mensaje
Al aprovechar la comprensión semántica, el sistema crea un proceso inteligente de procesamiento de correos electrónicos que puede manejar cientos de mensajes simultáneamente. El análisis basado en embeddings examina no solo palabras clave, sino el significado y contexto real de cada mensaje, considerando factores como:
- Contexto del mensaje dentro de conversaciones en curso
- Patrones históricos de comunicación
- Relaciones y jerarquías organizacionales
- Cronogramas y prioridades de proyectos
Este enfoque integral reduce significativamente la carga cognitiva de la gestión del correo electrónico al manejar automáticamente las tareas rutinarias de clasificación y priorización. El sistema asegura que los mensajes importantes reciban atención inmediata mientras mantiene una estructura organizada para todas las comunicaciones. Como resultado, los profesionales pueden concentrarse en actividades de alto valor en lugar de pasar horas clasificando manualmente su bandeja de entrada, lo que lleva a una mejor productividad y tiempos de respuesta más rápidos para comunicaciones críticas.
Ejemplo:
Este script simula la categorización de correos electrónicos entrantes basándose en su similitud semántica con categorías predefinidas como "Solicitud Urgente", "Actualización de Proyecto",
import os
from openai import OpenAI, OpenAIError
from dotenv import load_dotenv
import numpy as np # For cosine similarity calculation
import datetime
# --- Configuration ---
load_dotenv()
# Get the current date and location context
current_timestamp = "2024-10-31 15:54:00 CDT"
current_location = "Plano, Texas, United States"
print(f"Running Email Triage/Prioritization example at: {current_timestamp}")
print(f"Location Context: {current_location}")
# Initialize the OpenAI client
try:
api_key = os.getenv("OPENAI_API_KEY")
if not api_key:
raise ValueError("OPENAI_API_KEY not found in environment variables.")
client = OpenAI(api_key=api_key)
print("OpenAI client initialized.")
except ValueError as e:
print(f"Configuration Error: {e}")
exit()
except Exception as e:
print(f"Error initializing OpenAI client: {e}")
exit()
# Define the embedding model
EMBEDDING_MODEL = "text-embedding-3-small"
# --- Helper Function to Generate Embedding ---
# (Same as in previous embeddings examples)
def get_embedding(client, text, model=EMBEDDING_MODEL):
"""Generates an embedding for the given text using the specified model."""
print_text = text[:70] + "..." if len(text) > 70 else text
print(f"Generating embedding for: \"{print_text}\"")
try:
response = client.embeddings.create(
input=text,
model=model
)
embedding_vector = response.data[0].embedding
return embedding_vector
except OpenAIError as e:
print(f"OpenAI API Error generating embedding for text '{print_text}': {e}")
return None
except Exception as e:
print(f"An unexpected error occurred during embedding generation for text '{print_text}': {e}")
return None
# --- Helper Function for Cosine Similarity ---
# (Same as in previous embeddings examples)
def cosine_similarity(vec_a, vec_b):
"""Calculates the cosine similarity between two vectors."""
if vec_a is None or vec_b is None:
return 0.0
vec_a = np.array(vec_a)
vec_b = np.array(vec_b)
norm_a = np.linalg.norm(vec_a)
norm_b = np.linalg.norm(vec_b)
if norm_a == 0 or norm_b == 0:
return 0.0
else:
similarity = np.dot(vec_a, vec_b) / (norm_a * norm_b)
return np.clip(similarity, -1.0, 1.0) # Ensure value is within valid range
# --- Email Triage/Prioritization Implementation ---
# 1. Define Sample Emails (Subject + Snippet)
emails = [
{"id": "email01", "subject": "Urgent: Server Down!", "body_snippet": "The main production server seems to be unresponsive. We need immediate assistance to investigate and bring it back online."},
{"id": "email02", "subject": "Meeting Minutes - Project Phoenix Sync", "body_snippet": "Attached are the minutes from today's sync call. Key decisions included finalizing the Q3 roadmap. Action items assigned."},
{"id": "email03", "subject": "Quick Question about Report", "body_snippet": "Hi team, just had a quick question regarding the methodology used in the latest market analysis report. Can someone clarify?"},
{"id": "email04", "subject": "Fwd: Company Newsletter - April Edition", "body_snippet": "Sharing the latest company newsletter for your information."},
{"id": "email05", "subject": "Action Required: Submit Timesheet by EOD", "body_snippet": "Friendly reminder to please submit your weekly timesheet by the end of the day today. This is mandatory."},
{"id": "email06", "subject": "Update on Q2 Marketing Campaign", "body_snippet": "Just wanted to provide a brief update on the campaign performance metrics we discussed last week. See attached summary."},
{"id": "email07", "subject": "Can you approve this request ASAP?", "body_snippet": "Need your approval on the attached budget request urgently to proceed with the vendor contract."}
]
print(f"\nProcessing {len(emails)} emails.")
# 2. Define Categories/Priorities and their Semantic Representations
# We represent each category with a descriptive phrase.
categories = {
"Urgent Action Required": "Requires immediate attention, critical issue, deadline, ASAP request, mandatory task.",
"Project Update / Status": "Information about ongoing projects, progress reports, meeting minutes, status updates.",
"Question / Request for Info": "Asking for clarification, seeking information, query about details.",
"General Info / FYI": "Newsletter, announcement, sharing information, non-actionable update."
}
print(f"\nDefined categories: {list(categories.keys())}")
# 3. Generate embeddings for Categories (pre-computation recommended)
print("\nGenerating embeddings for categories...")
category_embeddings = {}
for category_name, category_description in categories.items():
embedding = get_embedding(client, category_description)
if embedding:
category_embeddings[category_name] = embedding
else:
print(f"Skipping category '{category_name}' due to embedding error.")
if not category_embeddings:
print("\nError: No embeddings generated for categories. Cannot triage emails.")
exit()
# 4. Process Each Email: Generate Embedding and Find Best Category
print("\nTriaging emails...")
email_results = []
for email in emails:
# Combine subject and body for better context
email_content = f"Subject: {email['subject']}\nBody: {email['body_snippet']}"
email_embedding = get_embedding(client, email_content)
if not email_embedding:
print(f"Skipping email {email['id']} due to embedding error.")
continue
# Find the category with the highest similarity
best_category = None
max_similarity = -1 # Cosine similarity ranges from -1 to 1
for category_name, category_embedding in category_embeddings.items():
similarity = cosine_similarity(email_embedding, category_embedding)
print(f" Email {email['id']} vs Category '{category_name}': Score {similarity:.4f}")
if similarity > max_similarity:
max_similarity = similarity
best_category = category_name
email_results.append({
"id": email["id"],
"subject": email["subject"],
"assigned_category": best_category,
"score": max_similarity
})
print(f"-> Email {email['id']} assigned to: '{best_category}' (Score: {max_similarity:.4f})")
# 5. Display Triage Results
print("\n--- Email Triage Results ---")
if not email_results:
print("No emails were successfully triaged.")
else:
# Optional: Group by category for display
results_by_category = {cat: [] for cat in categories.keys()}
for result in email_results:
if result["assigned_category"]: # Check if category was assigned
results_by_category[result["assigned_category"]].append(result)
for category_name, items in results_by_category.items():
print(f"\nCategory: {category_name}")
print("-" * (10 + len(category_name)))
if not items:
print(" (No emails assigned)")
else:
# Sort items within category by score if desired
items.sort(key=lambda x: x['score'], reverse=True)
for item in items:
print(f" - ID: {item['id']}, Subject: \"{item['subject']}\" (Score: {item['score']:.3f})")
print("\nEmail triage process complete.")
Explicación del Desglose del Código
Este ejemplo muestra cómo los embeddings de OpenAI pueden clasificar y priorizar automáticamente los correos electrónicos mediante la comprensión de su significado, demostrando un sistema inteligente de gestión de correos.
- Configuración y Funciones Auxiliares:
- Incluye importaciones estándar (
openai
,os
,dotenv
,numpy
), inicialización del cliente, y las funciones auxiliaresget_embedding
ycosine_similarity
.
- Incluye importaciones estándar (
- Datos de Ejemplo de Correos:
- Una lista de diccionarios (
emails
) simula mensajes entrantes. Cada correo tiene unid
,subject
, y unbody_snippet
.
- Una lista de diccionarios (
- Definiciones de Categorías:
- Un diccionario (
categories
) define las categorías objetivo para la clasificación (por ejemplo, "Acción Urgente Requerida", "Actualización de Proyecto / Estado"). - Idea Clave: Cada categoría está representada por una frase descriptiva o lista de palabras clave que captura su esencia semántica. Esta descripción es lo que será convertido en embedding.
- Un diccionario (
- Generación de Embeddings de Categorías:
- El script itera a través de las
categories
definidas. - Llama a
get_embedding
sobre la descripción asociada con cada nombre de categoría. - El vector de embedding resultante para cada categoría se almacena en el diccionario
category_embeddings
. Este paso típicamente sería pre-calculado y almacenado.
- El script itera a través de las
- Bucle de Procesamiento de Correos:
- El script itera a través de cada
email
en los datos de ejemplo. - Combinación de Contenido: Combina el
subject
ybody_snippet
en una única cadenaemail_content
para proporcionar un contexto más rico para el embedding. - Embedding del Correo: Llama a
get_embedding
para obtener la representación vectorial del contenido del correo actual. - Cálculo de Similitud:
- Luego itera a través de los
category_embeddings
pre-calculados. - Para cada categoría, calcula la
cosine_similarity
entre elemail_embedding
y elcategory_embedding
. - Mantiene un registro de la
best_category
(la que tiene el puntaje de similitud más alto encontrado hasta ahora) y el correspondiente puntajemax_similarity
.
- Luego itera a través de los
- Asignación: Después de comparar el correo con todas las categorías, se le asigna la
best_category
encontrada. El resultado (ID del correo, asunto, categoría asignada, puntaje) se almacena.
- El script itera a través de cada
- Visualización de Resultados de Clasificación:
- El script imprime las asignaciones finales.
- Agrupación Opcional: Incluye lógica para agrupar los resultados por categoría asignada para una presentación más clara, mostrando qué correos cayeron en los grupos "Urgente", "Actualización", etc.
Este ejemplo demuestra efectivamente cómo los embeddings permiten una categorización inteligente basada en el significado. Un correo solicitando "aprobación ASAP" puede ser correctamente identificado como "Acción Urgente Requerida" incluso sin usar la palabra exacta "urgente", porque su embedding será semánticamente cercano al embedding de la descripción de la categoría "Acción Urgente Requerida". Esto es mucho más robusto que el simple filtrado por palabras clave.