教學課程:使用 Azure Cache for Redis 對 Azure OpenAI 內嵌進行向量相似性搜尋
在本教學課程中,您將逐步解說基本的向量相似度搜尋使用案例。 您將使用 Azure OpenAI 服務所產生的內嵌和 Azure Cache for Redis 企業層的內建向量搜尋功能來查詢電影數據集,以尋找最相關的相符專案。
本教學課程使用 維琪百科電影繪圖數據集 ,其中包含 1901 至 2017 年維琪百科超過 35,000 部電影的繪圖描述。 數據集包含每個電影的繪圖摘要,加上電影發行年份、導演(s)、主演和內容類型等元數據。 您將遵循本教學課程的步驟,根據繪圖摘要產生內嵌,並使用其他元數據來執行混合式查詢。
在本教學課程中,您會了解如何:
- 建立針對向量搜尋設定的 Azure Cache for Redis 實例
- 安裝 Azure OpenAI 和其他必要的 Python 連結庫。
- 下載影片數據集並準備進行分析。
- 使用 text-embedding-ada-002(第 2 版)模型來產生內嵌。
- 在 Azure Cache for Redis 中建立向量索引
- 使用 餘弦相似度 來排名搜尋結果。
- 透過 RediSearch 使用混合式查詢功能來預先篩選數據,並讓向量搜尋更加強大。
重要
本教學課程將逐步引導您建置 Jupyter Notebook。 您可以遵循本教學課程搭配 Python 程式代碼檔案(.py),並取得 類似的 結果,但您必須將本教學課程中的所有程式碼區塊新增至檔案, .py
並執行一次以查看結果。 換句話說,Jupyter Notebook 會在您執行數據格時提供中繼結果,但這不是您在 Python 程式代碼檔案中工作時應該預期的行為。
重要
如果您想要改為遵循已完成的 Jupyter Notebook, 請下載名為 tutorial.ipynb 的 Jupyter Notebook 檔案,並將它儲存到新的 redis-vector 資料夾中。
必要條件
- Azure 訂用帳戶 - 免費建立一個訂用帳戶
- 在所需的 Azure 訂用帳戶中授與 Azure OpenAI 的存取權目前,您必須申請 Azure OpenAI 的存取權。 您可以填妥 https://aka.ms/oai/access 的表單,以申請 Azure OpenAI 的存取權。
- Python 3.7.1 或更新版本
- Jupyter Notebooks (選擇性)
- 已部署 text-embedding-ada-002 (第 2 版) 模型的 Azure OpenAI 資源。 此模型目前僅適用於 特定區域。 如需如何部署模型的指示,請參閱資源部署指南。
建立 Azure Cache for Redis 實例
遵循快速入門:建立 Redis 企業快取指南。 在 [ 進階 ] 頁面上,確定您已新增 RediSearch 模組,並已選擇 企業 叢集原則。 所有其他設定都可以符合快速入門中所述的預設值。
快取需要幾分鐘的時間才能建立。 您可以同時移至下一個步驟。
設定開發環境
在通常儲存專案的位置中,於本機計算機上建立名為 redis-vector 的資料夾。
在資料夾中建立新的 Python 檔案 (tutorial.py) 或 Jupyter Notebook (tutorial.ipynb)。
安裝必要的 Python 套件:
pip install "openai==1.6.1" num2words matplotlib plotly scipy scikit-learn pandas tiktoken redis langchain
下載資料集
在網頁瀏覽器中,巡覽至 https://www.kaggle.com/datasets/jrobischon/wikipedia-movie-plots。
使用 Kaggle 登入或註冊。 需要註冊才能下載檔案。
選取 Kaggle 上的 [ 下載 ] 鏈接以下載 archive.zip 檔案。
擷取archive.zip檔案,並將wiki_movie_plots_deduped.csv移至 redis-vector 資料夾。
匯入連結庫並設定連線資訊
若要成功對 Azure OpenAI 進行呼叫,您需要 端點 和 密鑰。 您也需要 端點 和 金鑰 ,才能連線到 Azure Cache for Redis。
移至 Azure 入口網站 中的 Azure OpenAI 資源。
在 [資源管理] 區段中找出端點和金鑰。 複製您的端點和存取密鑰,因為您需要這兩者來驗證 API 呼叫。 範例端點是:
https://docs-test-001.openai.azure.com
。 您可以使用KEY1
或KEY2
。在 Azure 入口網站 中,移至 Azure Cache for Redis 資源的 [概觀] 頁面。 複製您的端點。
在 [設定] 區段中找出 [存取密鑰]。 複製您的存取金鑰。 您可以使用
Primary
或Secondary
。將下列程式代碼新增至新的程式代碼資料格:
# Code cell 2 import re from num2words import num2words import os import pandas as pd import tiktoken from typing import List from langchain.embeddings import AzureOpenAIEmbeddings from langchain.vectorstores.redis import Redis as RedisVectorStore from langchain.document_loaders import DataFrameLoader API_KEY = "<your-azure-openai-key>" RESOURCE_ENDPOINT = "<your-azure-openai-endpoint>" DEPLOYMENT_NAME = "<name-of-your-model-deployment>" MODEL_NAME = "text-embedding-ada-002" REDIS_ENDPOINT = "<your-azure-redis-endpoint>" REDIS_PASSWORD = "<your-azure-redis-password>"
使用
API_KEY
Azure OpenAI 部署中的金鑰和端點值來更新 和RESOURCE_ENDPOINT
的值。DEPLOYMENT_NAME
應該使用text-embedding-ada-002 (Version 2)
內嵌模型設定為部署的名稱,而且MODEL_NAME
應該是使用的特定內嵌模型。使用來自 Azure Cache for Redis 實體的端點與金鑰值來更新
REDIS_ENDPOINT
與REDIS_PASSWORD
。重要
強烈建議使用環境變數或 Azure 金鑰保存庫 之類的秘密管理員來傳入 API 金鑰、端點和部署名稱資訊。 為了簡單起見,這些變數會以純文本在這裡設定。
執行程式代碼儲存格 2。
將數據集匯入 pandas 並處理數據
接下來,您將將 csv 檔案讀入 pandas DataFrame。
將下列程式代碼新增至新的程式代碼資料格:
# Code cell 3 df=pd.read_csv(os.path.join(os.getcwd(),'wiki_movie_plots_deduped.csv')) df
執行程式代碼儲存格 3。 您應該會看見下列輸出:
接下來,藉由新增
id
索引、從數據行標題移除空格,以及篩選電影,只取得 1970 年之後和來自英文國家/地區的電影,以處理數據。 此篩選步驟可減少數據集中的電影數目,進而降低產生內嵌所需的成本和時間。 您可以根據喜好設定變更或移除篩選參數。若要篩選資料,請將下列程式代碼新增至新的程式代碼資料格:
# Code cell 4 df.insert(0, 'id', range(0, len(df))) df['year'] = df['Release Year'].astype(int) df['origin'] = df['Origin/Ethnicity'].astype(str) del df['Release Year'] del df['Origin/Ethnicity'] df = df[df.year > 1970] # only movies made after 1970 df = df[df.origin.isin(['American','British','Canadian'])] # only movies from English-speaking cinema df
執行程式代碼儲存格 4。 您應該會看見下列結果:
藉由移除空格符和標點符號來建立函式來清除數據,然後將它用於包含繪圖的數據框架。
將下列程式代碼新增至新的程式代碼資料格並加以執行:
# Code cell 5 pd.options.mode.chained_assignment = None # s is input text def normalize_text(s, sep_token = " \n "): s = re.sub(r'\s+', ' ', s).strip() s = re.sub(r". ,","",s) # remove all instances of multiple spaces s = s.replace("..",".") s = s.replace(". .",".") s = s.replace("\n", "") s = s.strip() return s df['Plot']= df['Plot'].apply(lambda x : normalize_text(x))
最後,移除包含內嵌模型太長之繪圖描述的任何專案。 (換句話說,它們需要超過8192個令牌限制的令牌。然後計算產生內嵌所需的令牌數目。 這也會影響內嵌產生的價格。
將下列程式代碼新增至新的程式代碼資料格:
# Code cell 6 tokenizer = tiktoken.get_encoding("cl100k_base") df['n_tokens'] = df["Plot"].apply(lambda x: len(tokenizer.encode(x))) df = df[df.n_tokens<8192] print('Number of movies: ' + str(len(df))) print('Number of tokens required:' + str(df['n_tokens'].sum()))
執行程式代碼儲存格 6。 您應該會看見下列輸出:
Number of movies: 11125 Number of tokens required:7044844
重要
請參閱 Azure OpenAI 服務定價,以根據所需的令牌數目來產生內嵌的成本。
將數據框架載入 LangChain
使用 DataFrameLoader
類別將 DataFrame 載入 LangChain。 一旦數據位於 LangChain 檔中,使用 LangChain 連結庫來產生內嵌並執行相似度搜尋會比較容易。 將 [繪圖] 設定為 page_content_column
,以便在此數據行上產生內嵌。
將下列程式代碼新增至新的程式代碼資料格並加以執行:
# Code cell 7 loader = DataFrameLoader(df, page_content_column="Plot" ) movie_list = loader.load()
產生內嵌,並將其載入 Redis
既然數據已篩選並載入至 LangChain,您將建立內嵌專案,以便查詢每個電影的繪圖。 下列程式代碼會設定 Azure OpenAI、產生內嵌,並將內嵌向量載入 Azure Cache for Redis。
將下列程式代碼新增至新的程式代碼資料格:
# Code cell 8 embedding = AzureOpenAIEmbeddings( deployment=DEPLOYMENT_NAME, model=MODEL_NAME, azure_endpoint=RESOURCE_ENDPOINT, openai_api_type="azure", openai_api_key=API_KEY, openai_api_version="2023-05-15", show_progress_bar=True, chunk_size=16 # current limit with Azure OpenAI service. This will likely increase in the future. ) # name of the Redis search index to create index_name = "movieindex" # create a connection string for the Redis Vector Store. Uses Redis-py format: https://redis-py.readthedocs.io/en/stable/connections.html#redis.Redis.from_url # This example assumes TLS is enabled. If not, use "redis://" instead of "rediss:// redis_url = "rediss://:" + REDIS_PASSWORD + "@"+ REDIS_ENDPOINT # create and load redis with documents vectorstore = RedisVectorStore.from_documents( documents=movie_list, embedding=embedding, index_name=index_name, redis_url=redis_url ) # save index schema so you can reload in the future without re-generating embeddings vectorstore.write_schema("redis_schema.yaml")
執行程式代碼數據格 8。 這可能需要超過 30 分鐘才能完成。
redis_schema.yaml
也會產生檔案。 如果您想要連線到 Azure Cache for Redis 實例中的索引,而不需重新產生內嵌,此檔案就很有用。
重要
產生內嵌的速度取決於 Azure OpenAI 模型可用的 配額。 使用每分鐘 24 萬個令牌的配額,大約需要 30 分鐘的時間來處理數據集中的 700 萬個令牌。
執行向量搜尋查詢
現在您已設定數據集、Azure OpenAI 服務 API 和 Redis 實例,您可以使用向量進行搜尋。 在此範例中,會傳回指定查詢的前 10 個結果。
將下列程式代碼新增至 Python 程式代碼檔案:
# Code cell 9 query = "Spaceships, aliens, and heroes saving America" results = vectorstore.similarity_search_with_score(query, k=10) for i, j in enumerate(results): movie_title = str(results[i][0].metadata['Title']) similarity_score = str(round((1 - results[i][1]),4)) print(movie_title + ' (Score: ' + similarity_score + ')')
執行程式代碼儲存格 9。 您應該會看見下列輸出:
Independence Day (Score: 0.8348) The Flying Machine (Score: 0.8332) Remote Control (Score: 0.8301) Bravestarr: The Legend (Score: 0.83) Xenogenesis (Score: 0.8291) Invaders from Mars (Score: 0.8291) Apocalypse Earth (Score: 0.8287) Invasion from Inner Earth (Score: 0.8287) Thru the Moebius Strip (Score: 0.8283) Solar Crisis (Score: 0.828)
相似度分數會隨著電影的序數排名以相似性傳回。 請注意,更特定的查詢的相似度分數會降低得更快。
混合式搜尋
由於 RediSearch 在向量搜尋之上也具有豐富的搜尋功能,因此可以依數據集中的元數據來篩選結果,例如電影內容類型、轉型、發行年份或導演。 在此情況下,根據內容類型
comedy
進行篩選。將下列程式代碼新增至新的程式代碼資料格:
# Code cell 10 from langchain.vectorstores.redis import RedisText query = "Spaceships, aliens, and heroes saving America" genre_filter = RedisText("Genre") == "comedy" results = vectorstore.similarity_search_with_score(query, filter=genre_filter, k=10) for i, j in enumerate(results): movie_title = str(results[i][0].metadata['Title']) similarity_score = str(round((1 - results[i][1]),4)) print(movie_title + ' (Score: ' + similarity_score + ')')
執行程式代碼數據格 10。 您應該會看見下列輸出:
Remote Control (Score: 0.8301) Meet Dave (Score: 0.8236) Elf-Man (Score: 0.8208) Fifty/Fifty (Score: 0.8167) Mars Attacks! (Score: 0.8165) Strange Invaders (Score: 0.8143) Amanda and the Alien (Score: 0.8136) Suburban Commando (Score: 0.8129) Coneheads (Score: 0.8129) Morons from Outer Space (Score: 0.8121)
透過 Azure Cache for Redis 和 Azure OpenAI 服務,您可以使用內嵌和向量搜尋,將強大的搜尋功能新增至您的應用程式。
清除資源
如果您想要繼續使用在本文中建立的資源,請保留資源群組。
否則,如果您已完成資源,您可以刪除您建立的 Azure 資源群組,以避免產生費用。
重要
刪除資源群組是無法復原的。 當您刪除資源群組時,會永久刪除其中的所有資源。 請確定您不會不小心刪除錯誤的資源群組或資源。 如果您在包含您想要保留之資源的現有資源群組內建立資源,您可以個別刪除每個資源,而不是刪除資源群組。
若要刪除資源群組
登入 Azure 入口網站,然後選取 [資源群組]。
選取您要刪除的資源群組。
如果有許多資源群組,請使用 [ 篩選任何字段... ] 方塊,輸入您為此文章建立的資源群組名稱。 選取結果清單中的資源群組。
選取 [刪除資源群組]。
系統會要求您確認刪除資源群組。 輸入要確認的資源群組名稱,然後選取 [ 刪除]。
幾分鐘后,資源群組及其所有資源都會遭到刪除。
相關內容
- 深入了解 Azure Cache for Redis
- 深入瞭解 Azure Cache for Redis 向量搜尋功能
- 深入瞭解 Azure OpenAI 服務所產生的內嵌
- 深入瞭解 餘弦相似性
- 瞭解如何使用 OpenAI 和 Redis 建置 AI 支援的應用程式
- 建置具有語意答案的問答應用程式