Importaciones y carga de datos
Comenzamos importando algunas bibliotecas y módulos útiles.
import json
from transformers import CLIPProcessor, CLIPTextModelWithProjection
from torch import load, matmul, argsort
from torch.nn.functional import softmax
A continuación, importaremos fragmentos de texto e imágenes de las publicaciones del blog Multimodal LLM y Multimodal Embeddings. Estos se guardan en archivos .json, que se pueden cargar en Python como una lista de diccionario.
# load text chunks
with open('data/text_content.json', 'r', encoding='utf-8') as f:
text_content_list = json.load(f)# load images
with open('data/image_content.json', 'r', encoding='utf-8') as f:
image_content_list = json.load(f)
Aunque no repasaré aquí el proceso de preparación de datos, el código que utilicé se puede encontrar en el repositorio de GitHub.
También cargaremos las incrustaciones multimodales (de CLIP) para cada elemento en lista_texto_contenido Y lista_contenido_imagen. Estos se guardan como tensores de pytorch.
# load embeddings
text_embeddings = load('data/text_embeddings.pt', weights_only=True)
image_embeddings = load('data/image_embeddings.pt', weights_only=True)print(text_embeddings.shape)
print(image_embeddings.shape)
# >> torch.Size([86, 512])
# >> torch.Size([17, 512])
Al imprimir la forma de estos tensores, vemos que están representados mediante incrustaciones de 512 dimensiones. Y tenemos 86 fragmentos de texto y 17 imágenes.
Búsqueda multimodal
Una vez cargada nuestra base de conocimientos, ahora podemos definir una consulta de búsqueda vectorial. Esto implicará traducir una consulta de entrada en una integración utilizando CLIP. Procedemos de la misma forma que en los ejemplos del post anterior.
# query
query = "What is CLIP's contrastive loss function?"# embed query (4 steps)
# 1) load model
model = CLIPTextModelWithProjection.from_pretrained("openai/clip-vit-base-patch16")
# 2) load data processor
processor = CLIPProcessor.from_pretrained("openai/clip-vit-base-patch16")
# 3) pre-process text
inputs = processor(text=[text], return_tensors="pt", padding=True)
# 4) compute embeddings with CLIP
outputs = model(**inputs)
# extract embedding
query_embed = outputs.text_embeds
print(query_embed.shape)
# >> torch.Size([1, 512])
Al imprimir la forma, vemos que tenemos un único vector que representa la consulta.
Para realizar una búsqueda vectorial en la base de conocimientos, debemos hacer lo siguiente.
- Calcule las similitudes entre la incrustación de consultas y todas las incrustaciones de texto e imágenes.
- Cambie el tamaño de las similitudes para que varíen de 0 a 1 mediante la función softmax.
- Ordene las similitudes escaladas y devuelva los k resultados principales.
- Finalmente, filtre los resultados para mantener solo los elementos que superen un umbral de similitud predefinido.
Así es como se ve en el código de fragmentos de texto.
# define k and simiarlity threshold
k = 5
threshold = 0.05# multimodal search over articles
text_similarities = matmul(query_embed, text_embeddings.T)
# rescale similarities via softmax
temp=0.25
text_scores = softmax(text_similarities/temp, dim=1)
# return top k filtered text results
isorted_scores = argsort(text_scores, descending=True)[0]
sorted_scores = text_scores[0][isorted_scores]
itop_k_filtered = [idx.item()
for idx, score in zip(isorted_scores, sorted_scores)
if score.item() >= threshold][:k]
top_k = [text_content_list[i] for i in itop_k_filtered]
print(top_k)
# top k results[{'article_title': 'Multimodal Embeddings: An Introduction',
'section': 'Contrastive Learning',
'text': 'Two key aspects of CL contribute to its effectiveness'}]
Arriba vemos los mejores resultados de texto. Observe que solo tenemos un elemento, aunque k=5. De hecho, los elementos 2º a 5º estaban por debajo del umbral de 0,1.
Es interesante observar que este elemento no parece útil para nuestra solicitud inicial de «¿Cuál es la función de pérdida contrastiva de CLIP?» » Esto destaca uno de los principales retos de la investigación vectorial: elementos similares a una consulta determinada no necesariamente la responden.
Una forma de aliviar este problema es imponer restricciones menos estrictas a nuestros resultados de búsqueda aumentando k y reducir la similitud límiteluego, esperar que el LLM pueda determinar qué es útil y qué no.
Para hacer esto, primero agruparé los pasos de búsqueda vectorial en una función de Python.
def similarity_search(query_embed, target_embeddings, content_list,
k=5, threshold=0.05, temperature=0.5):
"""
Perform similarity search over embeddings and return top k results.
"""
# Calculate similarities
similarities = torch.matmul(query_embed, target_embeddings.T)# Rescale similarities via softmax
scores = torch.nn.functional.softmax(similarities/temperature, dim=1)
# Get sorted indices and scores
sorted_indices = scores.argsort(descending=True)[0]
sorted_scores = scores[0][sorted_indices]
# Filter by threshold and get top k
filtered_indices = [
idx.item() for idx, score in zip(sorted_indices, sorted_scores)
if score.item() >= threshold
][:k]
# Get corresponding content items and scores
top_results = [content_list[i] for i in filtered_indices]
result_scores = [scores[0][i].item() for i in filtered_indices]
return top_results, result_scores
A continuación, establezca parámetros de búsqueda más inclusivos.
# search over text chunks
text_results, text_scores = similarity_search(query_embed, text_embeddings,
text_content_list, k=15, threshold=0.01, temperature=0.25)# search over images
image_results, image_scores = similarity_search(query_embed, image_embeddings,
image_content_list, k=5, threshold=0.25, temperature=0.5)
Esto da 15 resultados de texto y 1 resultado de imagen.
1 - Two key aspects of CL contribute to its effectiveness
2 - To make a class prediction, we must extract the image logits and evaluate
which class corresponds to the maximum.
3 - Next, we can import a version of the clip model and its associated data
processor. Note: the processor handles tokenizing input text and image
preparation.
4 - The basic idea behind using CLIP for 0-shot image classification is to
pass an image into the model along with a set of possible class labels. Then,
a classification can be made by evaluating which text input is most similar to
the input image.
5 - We can then match the best image to the input text by extracting the text
logits and evaluating the image corresponding to the maximum.
6 - The code for these examples is freely available on the GitHub repository.
7 - We see that (again) the model nailed this simple example. But let’s try
some trickier examples.
8 - Next, we’ll preprocess the image/text inputs and pass them into the model.
9 - Another practical application of models like CLIP is multimodal RAG, which
consists of the automated retrieval of multimodal context to an LLM. In the
next article of this series, we will see how this works under the hood and
review a concrete example.
10 - Another application of CLIP is essentially the inverse of Use Case 1.
Rather than identifying which text label matches an input image, we can
evaluate which image (in a set) best matches a text input (i.e. query)—in
other words, performing a search over images.
11 - This has sparked efforts toward expanding LLM functionality to include
multiple modalities.
12 - GPT-4o — Input: text, images, and audio. Output: text.FLUX — Input: text.
Output: images.Suno — Input: text. Output: audio.
13 - The standard approach to aligning disparate embedding spaces is
contrastive learning (CL). A key intuition of CL is to represent different
views of the same information similarly [5].
14 - While the model is less confident about this prediction with a 54.64%
probability, it correctly implies that the image is not a meme.
15 - [8] Mini-Omni2: Towards Open-source GPT-4o with Vision, Speech and Duplex
Capabilities
Invitar a MLLM
Aunque la mayoría de estos resultados de elementos de texto no parecen útiles para nuestra consulta, el resultado de la imagen es exactamente lo que estamos buscando. Sin embargo, dados estos resultados de búsqueda, veamos cómo LLaMA 3.2 Vision responde a esta consulta.
Primero estructuraremos los resultados de la búsqueda como cadenas bien formateadas.
text_context = ""
for text in text_results:
if text_results:
text_context = text_context + "**Article title:** "
+ text['article_title'] + "\n"
text_context = text_context + "**Section:** "
+ text['section'] + "\n"
text_context = text_context + "**Snippet:** "
+ text['text'] + "\n\n"
image_context = ""
for image in image_results:
if image_results:
image_context = image_context + "**Article title:** "
+ image['article_title'] + "\n"
image_context = image_context + "**Section:** "
+ image['section'] + "\n"
image_context = image_context + "**Image Path:** "
+ image['image_path'] + "\n"
image_context = image_context + "**Image Caption:** "
+ image['caption'] + "\n\n"
Tenga en cuenta los metadatos que acompañan a cada elemento de texto e imagen. Esto ayudará al LLaMA a comprender mejor el contexto del contenido.
Luego entrelazamos los resultados de texto e imagen en un mensaje.
# construct prompt template
prompt = f"""Given the query "{query}" and the following relevant snippets:{text_context}
{image_context}
Please provide a concise and accurate answer to the query, incorporating
relevant information from the provided snippets where possible.
"""
El mensaje final es bastante largo, por lo que no lo imprimiré aquí. Sin embargo, se muestra completamente en el ejemplo de cuaderno en GitHub.
Finalmente, podemos usar ollama para reenviar este mensaje a LLaMA 3.2 Vision.
ollama.pull('llama3.2-vision')response = ollama.chat(
model='llama3.2-vision',
messages=[{
'role': 'user',
'content': prompt,
'images': [image["image_path"] for image in image_results]
}]
)
print(response['message']['content'])
The image depicts a contrastive loss function for aligning text and image
representations in multimodal models. The function is designed to minimize the
difference between the similarity of positive pairs (text-image) and negative
pairs (text-text or image-image). This loss function is commonly used in CLIP,
which stands for Contrastive Language-Image Pre-training.**Key Components:**
* **Positive Pairs:** Text-image pairs where the text describes an image.
* **Negative Pairs:** Text-text or image-image pairs that do not belong to
the same class.
* **Contrastive Loss Function:** Calculates the difference between positive
and negative pairs' similarities.
**How it Works:**
1. **Text-Image Embeddings:** Generate embeddings for both text and images
using a multimodal encoder (e.g., CLIP).
2. **Positive Pair Similarity:** Calculate the similarity score between each
text-image pair.
3. **Negative Pair Similarity:** Calculate the similarity scores between all
negative pairs.
4. **Contrastive Loss Calculation:** Compute the contrastive loss by
minimizing the difference between positive and negative pairs' similarities.
**Benefits:**
* **Multimodal Alignment:** Aligns text and image representations for better
understanding of visual content from text descriptions.
* **Improved Performance:** Enhances performance in downstream tasks like
image classification, retrieval, and generation.
El modelo comprende correctamente que la imagen contiene la información que necesita y explica la intuición general de cómo funciona. Sin embargo, él No entiende el significado de los pares positivos y negativos.pensando que un par negativo corresponde a un par de la misma categoría.
A medida que repasábamos los detalles de implementación paso a paso, integré todo en una interfaz de usuario agradable usando Gradio en este computadora portátil en el repositorio de GitHub.
Los sistemas RAG multimodales pueden sintetizar el conocimiento almacenado en una variedad de formatos, ampliando las posibilidades de la IA. Aquí analizamos 3 estrategias simples para desarrollar dicho sistema y luego vimos un ejemplo de implementación de un asistente de control de calidad de blog multimodal.
Aunque el ejemplo funcionó bastante bien para esta demostración, el proceso de búsqueda tiene limitaciones obvias. Algunas técnicas que pueden mejorar esto incluyen el uso de un reclasificar para refinar la búsqueda de similitud resultados y mejorar la calidad de la investigación mediante integraciones multimodales refinadas.
Si desea ver publicaciones futuras sobre estos temas, hágamelo saber en los comentarios 🙂
Obtenga más información sobre los modelos multimodales 👇