使用GPT文本嵌入和CLIP图像嵌入实现维基百科文章的多模态检索
在本笔记本中,我们将展示如何使用LlamaIndex构建一个多模态检索系统。
维基百科文本嵌入索引:使用OpenAI为文本生成GPT文本嵌入
维基百科图像嵌入索引:来自OpenAI的CLIP嵌入用于图像
查询编码器:
- 使用GPT嵌入对文本索引进行编码器查询文本
- 使用CLIP嵌入对图像索引进行编码器查询文本
框架:LlamaIndex
步骤:
- 下载维基百科文章的文本和图像原始文件
- 使用GPT嵌入为向量存储构建文本索引
- 使用CLIP嵌入为向量存储构建图像索引
- 使用不同的查询编码嵌入和向量存储同时检索相关文本和图像
%pip install llama-index-vector-stores-qdrant%pip install llama_index ftfy regex tqdm%pip install git+https://github.com/openai/CLIP.git%pip install torch torchvision%pip install matplotlib scikit-image%pip install -U qdrant_client从维基百科加载和下载包含文本和图像的多模态数据集
Section titled “Load and Download Multi-Modal datasets including texts and images from Wikipedia”解析维基百科文章并保存到本地文件夹
from pathlib import Pathimport requests
wiki_titles = [ "batman", "Vincent van Gogh", "San Francisco", "iPhone", "Tesla Model S", "BTS",]
data_path = Path("data_wiki")
for title in wiki_titles: response = requests.get( "https://en.wikipedia.org/w/api.php", params={ "action": "query", "format": "json", "titles": title, "prop": "extracts", "explaintext": True, }, ).json() page = next(iter(response["query"]["pages"].values())) wiki_text = page["extract"]
if not data_path.exists(): Path.mkdir(data_path)
with open(data_path / f"{title}.txt", "w") as fp: fp.write(wiki_text)解析维基百科图片与文本。加载至本地文件夹
Section titled “Parse Wikipedia Images and texts. Load into local folder”import wikipediaimport urllib.request
image_path = Path("data_wiki")image_uuid = 0# image_metadata_dict stores images metadata including image uuid, filename and pathimage_metadata_dict = {}MAX_IMAGES_PER_WIKI = 30
wiki_titles = [ "San Francisco", "Batman", "Vincent van Gogh", "iPhone", "Tesla Model S", "BTS band",]
# create folder for images onlyif not image_path.exists(): Path.mkdir(image_path)
# Download images for wiki pages# Assing UUID for each imagefor title in wiki_titles: images_per_wiki = 0 print(title) try: page_py = wikipedia.page(title) list_img_urls = page_py.images for url in list_img_urls: if url.endswith(".jpg") or url.endswith(".png"): image_uuid += 1 image_file_name = title + "_" + url.split("/")[-1]
# img_path could be s3 path pointing to the raw image file in the future image_metadata_dict[image_uuid] = { "filename": image_file_name, "img_path": "./" + str(image_path / f"{image_uuid}.jpg"), } urllib.request.urlretrieve( url, image_path / f"{image_uuid}.jpg" ) images_per_wiki += 1 # Limit the number of images downloaded per wiki page to 15 if images_per_wiki > MAX_IMAGES_PER_WIKI: break except: print(str(Exception("No images found for Wikipedia page: ")) + title) continueimport os
os.environ["OPENAI_API_KEY"] = "YOUR_API_KEY"使用不同集合下的文本和图像嵌入构建多模态向量存储
Section titled “Build Multi Modal Vector Store using Text and Image embeddings under different collections”import qdrant_clientfrom llama_index.core import SimpleDirectoryReaderfrom llama_index.vector_stores.qdrant import QdrantVectorStorefrom llama_index.core import VectorStoreIndex, StorageContextfrom llama_index.core.indices import MultiModalVectorStoreIndex
# Create a local Qdrant vector storeclient = qdrant_client.QdrantClient(path="qdrant_db")
text_store = QdrantVectorStore( client=client, collection_name="text_collection")image_store = QdrantVectorStore( client=client, collection_name="image_collection")storage_context = StorageContext.from_defaults( vector_store=text_store, image_store=image_store)
# Create the MultiModal indexdocuments = SimpleDirectoryReader("./data_wiki/").load_data()index = MultiModalVectorStoreIndex.from_documents( documents, storage_context=storage_context,)/Users/haotianzhang/llama_index/venv/lib/python3.11/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html from .autonotebook import tqdm as notebook_tqdmfrom PIL import Imageimport matplotlib.pyplot as pltimport os
def plot_images(image_metadata_dict): original_images_urls = [] images_shown = 0 for image_id in image_metadata_dict: img_path = image_metadata_dict[image_id]["img_path"] if os.path.isfile(img_path): filename = image_metadata_dict[image_id]["filename"] image = Image.open(img_path).convert("RGB")
plt.subplot(8, 8, len(original_images_urls) + 1) plt.imshow(image) plt.xticks([]) plt.yticks([])
original_images_urls.append(filename) images_shown += 1 if images_shown >= 64: break
plt.tight_layout()
plot_images(image_metadata_dict)
在不同集合下构建独立的CLIP图像嵌入索引 wikipedia_img
Section titled “Build a separate CLIP image embedding index under a differnt collection wikipedia_img”def plot_images(image_paths): images_shown = 0 plt.figure(figsize=(16, 9)) for img_path in image_paths: if os.path.isfile(img_path): image = Image.open(img_path)
plt.subplot(2, 3, images_shown + 1) plt.imshow(image) plt.xticks([]) plt.yticks([])
images_shown += 1 if images_shown >= 9: breaktest_query = "who are BTS team members"# generate retrieval resultsretriever = index.as_retriever(similarity_top_k=3, image_similarity_top_k=5)retrieval_results = retriever.retrieve(test_query)from llama_index.core.response.notebook_utils import display_source_nodefrom llama_index.core.schema import ImageNode
retrieved_image = []for res_node in retrieval_results: if isinstance(res_node.node, ImageNode): retrieved_image.append(res_node.node.metadata["file_path"]) else: display_source_node(res_node, source_length=200)
plot_images(retrieved_image)节点ID: e30e1817-4e31-4047-be5d-37502560920c
相似度: 0.808149809808292
文本: BTS(韩语:방탄소년단;罗马化:Bangtan Sonyeondan;字面意思:防弹少年团),亦被称为Bangtan Boys,是于2010年成立的韩国男子音乐组合。该组合成员包括Jin、Suga、J-Hope、RM、Jimi…
节点ID: 024f3296-37c8-46d5-a184-2f78c621a99f
相似度: 0.7987048642063129
文本: === 粉丝圈 ===
根据金亨均的说法,BTS的崛起得益于YouTube音乐视频节目和消费的大幅增长,以及偶像帝国的到来,包括周边商品…
节点ID: c564ccf4-a94f-408f-8b21-224538dc2e94
相似度: 0.7838098925118134
文本: == 历史 ==
=== 2010–2014年:组建与早期岁月 ===
防弹少年团于2010年组建,当时Big Hit娱乐公司首席执行官房时赫希望围绕RM(金南俊)组建一个嘻哈团体,当时他还是一名大学生…

test_query = "what are Vincent van Gogh's famous paintings"# generate retrieval resultsretriever = index.as_retriever(similarity_top_k=3, image_similarity_top_k=5)retrieval_results = retriever.retrieve(test_query)
retrieved_image = []for res_node in retrieval_results: if isinstance(res_node.node, ImageNode): retrieved_image.append(res_node.node.metadata["file_path"]) else: display_source_node(res_node, source_length=200)
plot_images(retrieved_image)节点ID: e002927c-0bf5-482b-a0a1-0ee2f3cd48f9
相似度: 0.8675476190545354
文本: 文森特·威廉·梵高(荷兰语:[ˈvɪnsɛnt ˈʋɪləɱ vɑŋ ˈɣɔx];1853年3月30日-1890年7月29日)是一位荷兰后印象派画家,他是艺术史上最著名和最具影响力的人物之一…
节点ID: 69ef1c64-a5b4-468c-a58c-7d36151961a7
相似度: 0.8661792475490765
文本: ==== 花卉 ====
梵高绘制了多幅带有花卉的风景画,包括玫瑰、丁香、鸢尾花和向日葵。部分作品反映了他对色彩语言的兴趣,同时也展现了日本浮世绘…
节点ID: f971a611-a8b9-48b4-a81b-d3856438aab8
相似度: 0.8616832203971132
文本: ==== 肖像 ====
梵高曾说肖像画是他最大的兴趣。"在我的职业中,最令我着迷的,远超过其他一切的",他在1890年写道,"是肖像画,那…

test_query = "what is the popular tourist attraction in San Francisco"# generate retrieval resultsretriever = index.as_retriever(similarity_top_k=3, image_similarity_top_k=5)retrieval_results = retriever.retrieve(test_query)
retrieved_image = []for res_node in retrieval_results: if isinstance(res_node.node, ImageNode): retrieved_image.append(res_node.node.metadata["file_path"]) else: display_source_node(res_node, source_length=200)
plot_images(retrieved_image)节点ID: 8c14be3e-345a-4764-9b64-dacff771bc04
相似度: 0.8689195893277072
文本内容: === 旅游与会展 ===
旅游业是旧金山最重要的私营产业之一,占该市就业岗位的七分之一以上。这座城市频繁被描绘…
节点ID: 22aa7d86-017f-433d-98dc-4007d9f67c17
相似度: 0.8452524742723133
文本: === LGBT ===
旧金山长期以来一直有着对LGBT友好的历史。它是美国第一个女同性恋权利组织"比利提斯之女"的所在地;也是首位公开同性恋身份竞选公职的人……
节点ID: 3846a17a-79d8-415e-9bcf-76c818b27203
相似度: 0.8329496262980858
文本: == 公园与休闲 ==
旧金山的多个公园及几乎所有海滩构成了金门国家休闲区的一部分,这是美国国家公园系统中访问量最大的区域之一…

test_query = "which company makes Tesla"# generate retrieval resultsretriever = index.as_retriever(similarity_top_k=3, image_similarity_top_k=5)retrieval_results = retriever.retrieve(test_query)
retrieved_image = []for res_node in retrieval_results: if isinstance(res_node.node, ImageNode): retrieved_image.append(res_node.node.metadata["file_path"]) else: display_source_node(res_node, source_length=200)
plot_images(retrieved_image)节点ID: 214c61be-dad6-403c-b301-bc2320b87e7a
相似度: 0.7808396168295813
文本: 特斯拉Model S是由特斯拉公司自2012年起生产的电池电动全尺寸豪华轿车,采用掀背式车身设计。Model S采用电池供电的双电机全轮驱动布局,…
节点ID: 15b737b4-90e3-443a-87aa-13a7d7e80b87
相似度: 0.7807424063856144
文本: === P100D ===
P100D在测功机上的输出功率为439千瓦(589马力),扭矩为1,248牛·米(920磅力·英尺)。截至2017年3月,P100D是全球加速最快的量产车,NHRA滚动起步加速至6…
节点ID: e134452b-3031-47b0-a20c-df4fe32f1bcf
相似度: 0.7754107325086438
文本: === 召回记录 ===
截至2021年12月,特斯拉已对Model S车型进行过七次召回:
2013年6月14日,特斯拉召回了2013年5月10日至2013年6月8日期间生产的Model S车辆,原因是存在不规范的制造工艺…

test_query = "what is the main character in Batman"# generate retrieval resultsretriever = index.as_retriever(similarity_top_k=3, image_similarity_top_k=5)retrieval_results = retriever.retrieve(test_query)
retrieved_image = []for res_node in retrieval_results: if isinstance(res_node.node, ImageNode): retrieved_image.append(res_node.node.metadata["file_path"]) else: display_source_node(res_node, source_length=200)
plot_images(retrieved_image)节点ID: ff85b136-08c8-465d-96f5-a554c65067d8
相似度: 0.8461934674061043
文本: ==== 人物性格 ====
蝙蝠侠的主要性格特征可概括为“财富;体能优势;推理能力与执念”。蝙蝠侠漫画的细节与基调随时间推移不断演变…
节点ID: 55f5b842-6fd0-4e45-aef2-27f74f670e82
相似度: 0.8229623965891602
文本: 蝙蝠侠是出现在DC漫画公司出版的美国漫画书中的超级英雄。该角色由艺术家鲍勃·凯恩和作家比尔·芬格创作,首次亮相于漫画书第27期…
节点ID: cb4755db-088e-46af-92b2-3a4a3649d9fe
相似度: 0.8218281955244808
文本: === 敌人 ===
蝙蝠侠面对各种各样的敌人,从普通罪犯到古怪的超级反派。其中许多反派映射了蝙蝠侠角色特质与发展历程的某些方面,往往带有悲剧性…
