本文為 Simon Willison 在 PyBay 上發表的演講視頻的文字改進版
原文鏈接:
https://simonwillison.net/2023/Oct/23/embeddings/
演講視頻鏈接:
https://youtu.be/ArnMdc-ICCM
Embedding 是一個非常巧妙的技術,但常常和一堆令人生畏的術語一起出現。如果你能理解這些術語,它們就會為你打開強大的技術的大門,這些技術可以應用于各種有趣的問題。
如果你還不熟悉 Embedding,希望這篇文章能夠為你提供將它們應用于實際問題所需的一切知識。
本文將圍繞以下問題展開:
- 什么是 Embedding?
- 使用 Embedding 的相關內容
- 探索這些工具如何與 Word2Vec 一起工作
- 使用 LLM 工具計算Embedding
- 基于 Vibes 的搜索
- 使用 Symbex Embedding 代碼
- 使用 CLIP 將文本和圖像 Embedding 在一起
- 水龍頭查找器:使用 CLIP 查找水龍頭
- 聚類 Embedding
- 通過主成分分析進行二維可視化
- 使用平均位置對句子進行評分
- 使用檢索增強生成回答問題
什么是Embedding
Embedding 是一項與更廣泛的大型語言模型領域相鄰的技術——ChatGPT 和 Bard and Claude 背后的技術。
Embedding 基于一個技巧:獲取一段內容并將該內容轉換為浮點數數組,如上圖。
該數組的關鍵在于,無論內容有多長,它的長度始終相同。長度由你使用的 Embedding 模型定義,數組的長度可能是 300、1000 或 1536 個數字。
理解這個數字數組的最好方法是將其想象為一個非常奇怪的多維空間中的坐標。
我們很難可視化 1536 維空間,但是我們可以用可視化的3維空間來理解,為什么要在這個空間放置內容?因為我們可以根據內容所處的位置(特別是附近的其他內容)了解該內容相關的信息。
根據 Embedding 模型對世界的抽象且大多難以理解的理解,空間內的位置代表了內容的語義含義。它可能會捕獲已 Embedding 內容的顏色、形狀、概念或各種其他特征。沒有人能夠完全理解這些單獨數字的含義,但我們知道它們的位置可用于查找有關內容的信息。
使用Embedding的相關內容
作者使用 Embedding 解決的第一個問題是為他的 TIL 博客構建“相關內容”功能。他希望能夠在每個頁面的底部顯示相關文章的列表。
作者使用 Embedding 來完成此操作:
本例中使用了 OpenAItext-embedding-ada-002模型,該模型可通過 OpenAI 官網的 API獲得。
目前作者的網站上有 472 篇文章,并計算了每篇文章的 1536 維 Embedding 向量(浮點數數組),并將這些向量存儲在他網站的 SQLite 數據庫中。
現在,如果想查找給定文章的相關文章,我可以計算該文章的 Embedding 向量與數據庫中所有其他文章之間的余弦相似度,然后按距離返回 10 個最接近的匹配項。
這是用來計算這些余弦相似距離的Python 函數:
def cosine_similarity ( a , b ):dot_product = sum ( x * y for x , y in zip ( a , b )) 模量_a = sum ( x * x for x in a ) ** 0.5模量_b = sum ( x * x for b中的x ) ** 0.5返回點積/ (幅度_a *幅度_b )
作者的 TIL 站點在他的 Datasette Python 框架上運行,該框架支持在 SQLite 數據庫之上構建站點。文末會附有關于它的文章。
我們可以瀏覽將計算的 embedding 存儲在 tils/embeddings 的 SQLite 表。
這些是二進制值。我們可以運行此 SQL 查詢以十六進制形式查看它們:
從 Embedding 中選擇 id、十六進制(Embedding)
但這仍然不太可讀。我們可以使用llm_embed_decode()自定義 SQL 函數將它們轉換為 JSON 數組:
從 Embedding 限制10中選擇 id、llm_embed_decode(embedding)
它顯示每篇文章都附有 1536 個浮點數的數組。
我們可以使用另一個自定義 SQL 函數llm_embed_cosine(vector1, vector2)來計算這些余弦距離并找到最相似的內容。該 SQL 函數在 datasette-llm-embed 插件中定義。
以下查詢返回與我的 SQLite TG 文章最相似的五篇文章:
執行該查詢將返回以下結果:
正如預期的那樣,該文章與其自身的相似度為 1.0。其他文章都與 SQLite 中的地理空間 SQL 查詢相關。
該查詢的執行時間大約為 400 毫秒。為了加快速度,作者預先計算了每篇文章的前 10 個相似之處,并將它們存儲在一個名為 tils/similarities 的單獨表中。
作者編寫了一個 Python 函數來從該表中查找相關文檔,并從用于呈現文章頁面的模板中調用它。
在這個項目中使用了 OpenAI Embedding API,Embedding 了大約 402500 個代幣,按 0.0001 美元/1,000 個代幣計算,相當于只需 4 美分!它使用起來真的很方便,將一些文本與 API 密鑰一起發布,就會返回浮點數的 JSON 數組。
但是,這是一個專有模型。幾個月前,OpenAI 關閉了一些舊的 Embedding 模型,如果你存儲了這些模型的大量Embedding,這將是一個問題,因為如果你希望能夠 Embedding,則需要根據支持的模型重新計算它們還有什么新的東西。
盡管 OpenAI 承諾會承擔用戶使用這些新模型重新 Embedding 內容的財務成本,但這仍然是對依賴專有模型持謹慎態度的一個理由。好消息是,有非常強大的開放許可模型,你可以在自己的硬件上運行它們,從而避免它們被關閉的任何風險。我們稍后會詳細討論這個問題。
探索這些工具如何與 Word2Vec 一起工作
Google Research 10 年前發表了一篇有影響力的論文,描述了他們創建的名為 Word2Vec 的早期 Embedding 模型。這篇論文是 Efficient Estimation of Word Representations in Vector Space,發表日期為 2013 年 1 月 16 日。這篇論文引發了人們對 Embedding 的廣泛興趣。
Word2Vec 是一個模型,它將單個單詞轉換為包含 300 個數字的列表。該數字列表捕獲了相關單詞的含義。
通過演示可以最好地說明這一點。
搜索單詞以根據與其 Word2Vec 表示形式的余弦距離查找相似單詞。例如,單詞“france”會返回以下相關結果:
這是與法國有關的事物和歐洲地理的混合體。
可以在這里做的一件非常有趣的事情是對這些向量執行算術運算。
獲取“德國”的向量,添加“巴黎”并減去“法國”。得到的向量最接近“berlin”!
這個模型的某些部分已經捕捉到了民族和地理的概念,以至于你可以使用算術來探索關于世界的更多事實。
Word2Vec 使用 16 億字的內容進行訓練。我們今天使用的 Embedding 模型是在更大的數據集上進行訓練的,并且可以更豐富地理解底層關系。
使用 LLM 工具計算Embedding
作者一直在構建一個名為 LLM 的命令行實用程序和 Python 庫。幾個月前,作者擴展了 LLM 以支持也可以運行 Embedding 模型的插件。
以下是如何使用 LLM運行名為 all-MiniLM-L6-v2 的模型:
首先,我們安裝llm并使用它來安裝 llm-sentence-transformers 插件 - SentenceTransformers庫的包裝器。
pip install llm
llm install llm-sentence-transformers
接下來我們需要注冊 all-MiniLM-L6-v2 模型。這會將模型從 Hugging Face 下載到你的計算機:
llm sentence-transformers register all-MiniLM-L6-v2
我們可以通過 Embedding 一個句子來測試它,如下所示:
llm embed -m sentence-transformers/all-MiniLM-L6-v2 \-c 'Hello world'
這會輸出一個 JSON 數組,其開頭如下:
[-0.03447725251317024,0.031023245304822922, 0.006734962109476328,0.026108916848897934, -0.03936201333999634, …
像這樣的 Embedding 本身并不是很有趣,我們需要存儲和比較它們才能開始獲得有用的結果。
LLM 可以將 Embedding 存儲在“集合”(SQLite 表)中。embed -multi 命令可用于一次 Embedding 多條內容并將它們存儲在一個集合中。
這就是下一個命令的作用:
在這里,我們正在填充一個名為“readmes”的集合。
該–files選項有兩個參數:要搜索的目錄和與文件名匹配的全局模式。本例正在遞歸搜索主目錄中任何名為README.md的文件。
該–store選項使 LLM 除了 Embedding 向量之外還將原始文本存儲在 SQLite 表中。
該命令在計算機上運行大約需要 30 分鐘。現在我們有了一個名叫readmes的 16796 行的集合,它代表README.md在我們的主目錄中找到的每個文件。
基于 Vibes 的搜索
現在我們有了 Embedding 集合,我們可以使用 llm 類似命令對其進行搜索:
llm similar readmes -c 'sqlite backup tools' | jq .id
我們要求readmes集合中的項目類似于短語“sqlite backup tools”的 Embedding 向量。
該命令默認輸出 JSON,其中包括 README 文件的全文,因為我們–store之前使用它們進行了存儲。
通過管道傳輸結果jq .id會導致命令僅輸出匹配行的 ID。
排名靠前的匹配結果是:
這些都是很好的結果!這些自述文件中的每一個都描述了用于處理 SQLite 備份的工具或以某種方式與備份相關的項目。
有趣的是,不能保證術語“備份”直接出現在這些自述文件的文本中。內容在語義上與該短語相似,但可能與文本不完全匹配。
我們可以稱之為語義搜索。作者喜歡將其視為基于振動的搜索。
根據單詞含義的這種奇怪的多維空間表示,這些自述文件的氛圍與我們的搜索詞相關。
這非常有用。如果你曾經為網站構建過搜索引擎,你就會知道精確匹配并不總能幫助人們找到他們正在尋找的內容。
我們可以使用這種語義搜索來為一大堆不同類型的內容構建更好的搜索引擎。
使用 Symbex Embedding代碼
作者一直在構建的另一個工具稱為 Symbex。它是一個用于探索 Python 代碼庫中符號的工具。
最初構建它是為了幫助快速找到 Python 函數和類,并將它們輸送到 LLM 中以幫助解釋和重寫它們。
然后意識到可以使用它來計算代碼庫中所有函數的 Embedding,并使用這些 Embedding 來構建代碼搜索引擎。
新添加的 llm embed-multi 功能可以使用可用作輸入的相同輸出格式輸出表示找到的符號的 JSON 或 CSV。
以下是如何使用新發布的名為 gte-tiny 的模型構建 Datasette 項目中所有函數的集合。
symbex '’ ':’ --nl 查找當前目錄中的所有函數 ( ) 和類方法(模式),并將它們輸出為換行符分隔的 JSON。:
該 llm embed-multi … --format nl 命令需要以換行符分隔的 JSON 作為輸入,因此我們可以將輸出 symbex 直接通過管道傳輸到其中。
默認情況下將 Embedding 存儲在默認的 LLM SQLite 數據庫中。你可以添加 --database /tmp/data.db 以指定替代位置。
現在,可以針對代碼庫運行基于振動的語義搜索!
我們可以使用 llm similar 該命令來執行此操作,但也可以使用 Datasette 本身來運行這些搜索。
這是一個 SQL 查詢,使用之前的 datasette-llm-embed 插件:
Datasette 會自動將參數:input轉換為表單字段。
當運行它時,我們會得到與列出插件概念相關的函數:
這里的關鍵思想是使用 SQLite 作為集成點,這是將多個工具組合在一起的基礎。
我們可以運行單獨的工具,從代碼庫中提取函數,通過 Embedding 模型運行它們,將這些 Embedding 寫入 SQLite,然后對結果運行查詢。
現在,任何可以通過管道傳輸到工具中的內容都可以由該生態系統的其他組件 Embedding 和處理。
使用 CLIP 將文本和圖像Embedding在一起
作者目前最喜歡的 Embedding 模型是 CLIP。
CLIP 是 OpenAI 于 2021 年 1 月發布的一個令人著迷的模型,當時他們仍在公開地做大多數事情,可以 Embedding 文本和圖像。
至關重要的是,它將文字和圖像 Embedding 到同一個向量空間中。
如果 Embedding 字符串“dog”,你將獲得 512 維空間中的位置(取決于你的 CLIP 配置)。
如果你 Embedding 狗的照片,你將在同一空間中獲得一個位置,并且它與字符串“dog”的位置的距離很接近!
這意味著我們可以使用文本搜索相關圖像,也可以使用圖像搜索相關文本。
下面構建了一個交互式演示來幫助解釋其工作原理。該演示是一個 Observable 筆記本,直接在瀏覽器中運行 CLIP 模型。
這是一個相當大型的頁面,它必須加載 158MB 的資源(CLIP 文本模型為 64.6MB,圖像模型為 87.6MB),但一旦加載,你可以使用它來 Embedding 圖像,然后 Embedding 文本字符串并計算兩者之間的距離。
可以給它這張海灘照片:
然后輸入不同的文本字符串來計算相似度得分,此處顯示為百分比:
令人驚奇的是,我們可以在瀏覽器中運行的 JavaScript 中完成所有這些工作!
有一個明顯的問題:能夠拍攝任意照片并說“這與‘城市’一詞有多相似?”實際上并沒有那么有用。
訣竅是在此基礎上構建額外的接口。我們再一次有能力構建基于振動的搜索引擎。
這是其中一個很好的例子。
水龍頭查找器:使用 CLIP 查找水龍頭
Drew Breunig 使用 LLM 和作者的 llm-clip 插件構建了一個水龍頭搜索引擎。
他正在裝修浴室,需要購買新水龍頭。因此,他從一家水龍頭供應公司收集了 20000 張水龍頭照片,并對所有這些照片運行 CLIP。
他利用該結果構建了 Faucet Finder——一個自定義工具(使用 Datasette 部署),用于查找與其他水龍頭相似的水龍頭。
除此之外,這意味著你可以找到你喜歡的昂貴水龍頭,然后尋找視覺上相似的更便宜的選擇!
Drew 在 Find Bathroom Faucets with Embeddings 中詳細介紹了他的項目。
Drew 的演示使用預先計算的 Embedding 來顯示類似的結果,而無需在服務器上運行 CLIP 模型。
受此啟發,作者花了一些時間研究如何部署由他自己的 Fly.io 帳戶托管的服務器端 CLIP 模型。
Drew 的 Datasette 實例包含的 Embedding 向量表通過 Datasette API 公開。
作者使用此 API 部署了自己的實例來 Embedding 文本字符串,然后構建了一個 Observable 筆記本演示,該演示可以訪問這兩個 API 并組合結果。
observablehq.com/@simonw/search-for-faucets-with-clip-api
現在可以搜索“金紫色”之類的內容并獲取相關的結果:
能夠在幾個小時內啟動這種超特定的搜索引擎正是 Embedding 較為實用的技巧。
聚類Embedding
相關內容和基于語義/振動的搜索是 Embedding 的兩個最常見的應用,但是你也可以用它們做很多其他巧妙的事情。
其中之一是聚類。
為此構建了一個名為 llm-cluster 的插件,它使用 scikit-learn 中的 sklearn.cluster 來實現此功能。
為了證明這一點,作者使用 paginate-json 工具和 GitHub issues API 將存儲庫中所有問題的標題收集 simonw/llm 到一個名為的集合中 llm-issues:
paginate-json 'https://api.github.com/repos/simonw/llm/issues?state=all&filter=all' \| jq '[.[] | {id: .id, title: .title}]' \ | llm embed-multi llm-issues - \ --store
現在可以創建 10 個問題集群,如下所示:
llm install llm-clusterllm cluster llm-issues 10
集群作為 JSON 數組輸出,輸出看起來像這樣(部分內容):
這些看起來確實相關,但我們可以做得更好。該llm cluster命令有一個–summary選項,使其通過 LLM 傳遞生成的簇文本,并使用它為每個簇生成描述性名稱:
llm cluster llm-issues 10 --summary
這會返回“日志管理和交互式提示跟蹤”和“持續對話機制和管理”等名稱。有關更多詳細信息,請參閱文末 GitHub 項目鏈接。
通過主成分分析進行二維可視化
大規模多維空間的問題在于它很難可視化。
我們可以使用一種稱為主成分分析的技術將數據的維度減少到更易于管理的大小,結果表明較低的維度可以繼續捕獲有關內容的有用語義。
Matt Webb 使用 OpenAI Embedding 模型生成 Embedding,用于描述 BBC 的 In Our Time 播客的每一集。他使用這些來查找相關劇集,同時還針對它們運行 PCA 以創建交互式 2D 可視化。
將 1,536 維減少到只有 2 維仍然可以產生一種有意義的數據探索方式!有關歷史戰爭的劇集彼此相鄰,其他地方則有一系列有關現代科學發現的劇集。
Matt 在瀏覽杜威十進制代碼的 BBC In Our Time 檔案中對此進行了更多介紹。
使用平均位置對句子進行評分
Embedding 的另一個技巧是使用它們進行分類。
首先計算以某種方式分類的一組 Embedding 的平均位置,然后將新內容的 Embedding 與這些位置進行比較,以將其分配到一個類別。
Amelia Wattenberger 在“利用Embedding發揮創意”中展示了一個很好的例子。
她希望通過鼓勵具體和抽象句子的混合來幫助人們提高寫作水平。但是如何判斷文本句子是具體的還是抽象的呢?
她的技巧是生成兩種類型句子的樣本,計算它們的平均位置,然后根據它們與新定義的頻譜兩端的接近程度對新句子進行評分。
該分數甚至可以轉換為松散地表示給定句子的抽象或具體程度的顏色!
這是一個非常簡潔的演示,展示了你可以在這項技術的基礎上開始構建的創意界面。
使用檢索增強生成回答問題
每個嘗試 ChatGPT 的人最終都會問同樣的問題:我如何使用這個版本來回答基于我自己的私人筆記或我公司擁有的內部文檔的問題?
人們認為答案是在該內容的基礎上訓練自定義模型,這可能會花費巨大的代價。
事實證明這實際上沒有必要。你可以使用現成的大型語言模型模型(托管模型或本地運行的模型)和一種稱為檢索增強生成(RAG)的技巧。
關鍵思想是:用戶提出問題。你在私人文檔中搜索與問題相關的內容,然后將該內容的摘錄與原始問題一起粘貼到 LLM 中(遵守其大小限制,通常在 3,000 到 6,000 個單詞之間)。
然后,LLM 可以根據你提供的附加內容回答問題。
這個廉價的技巧卻非常有效。獲得此功能的基本版本很簡單,挑戰在于考慮到用戶可能會問的無數問題,使其盡可能良好地工作。
RAG 的關鍵問題是找出最好的內容摘錄,以包含在 LLM 的提示中。
由 Embedding 提供支持的“基于振動”的語義搜索正是收集潛在相關內容以幫助回答用戶問題所需的東西。
我們可以使用名為 E5-large-v2 的模型。這是一個根據具體用例進行訓練的模型。
查找與問題相關的內容的一個挑戰是,用戶的問題“什么是 shot-scraper?”不能保證被認為在語義上與回答該問題的內容相似。問題和斷言具有不同的語法。
E5-large-v2 通過支持兩種類型的內容來解決這個問題。你可以在同一空間中 Embedding 短語(事實句子)和查詢(問題),類似于 CLIP 支持圖像和文本的方式。
作者從博客中 Embedding 了 19,000 個文本段落作為短語,現在可以 Embedding 一個問題作為查詢,并使用它來查找最有可能回答該問題的段落。
結果是 RAG 作為單行 Bash 腳本實現:
此示例使用了作者的筆記本電腦上運行的 Llama 2 Chat 7B(帶有 llm-mlc 插件),因此他能夠使用在他的筆記本電腦上運行的代碼完全離線回答問題。
運行這個:
./blog-answer.sh 'What is shot-scraper?'
輸出這個:
這是對這個鏡頭抓取工具的一個很好的描述,沒有一個輸出與之前在博客上發布的內容完全匹配。
如何學習大模型 AI ?
由于新崗位的生產效率,要優于被取代崗位的生產效率,所以實際上整個社會的生產效率是提升的。
但是具體到個人,只能說是:
“最先掌握AI的人,將會比較晚掌握AI的人有競爭優勢”。
這句話,放在計算機、互聯網、移動互聯網的開局時期,都是一樣的道理。
我在一線互聯網企業工作十余年里,指導過不少同行后輩。幫助很多人得到了學習和成長。
我意識到有很多經驗和知識值得分享給大家,也可以通過我們的能力和經驗解答大家在人工智能學習中的很多困惑,所以在工作繁忙的情況下還是堅持各種整理和分享。但苦于知識傳播途徑有限,很多互聯網行業朋友無法獲得正確的資料得到學習提升,故此將并將重要的AI大模型資料包括AI大模型入門學習思維導圖、精品AI大模型學習書籍手冊、視頻教程、實戰學習等錄播視頻免費分享出來。
第一階段(10天):初階應用
該階段讓大家對大模型 AI有一個最前沿的認識,對大模型 AI 的理解超過 95% 的人,可以在相關討論時發表高級、不跟風、又接地氣的見解,別人只會和 AI 聊天,而你能調教 AI,并能用代碼將大模型和業務銜接。
- 大模型 AI 能干什么?
- 大模型是怎樣獲得「智能」的?
- 用好 AI 的核心心法
- 大模型應用業務架構
- 大模型應用技術架構
- 代碼示例:向 GPT-3.5 灌入新知識
- 提示工程的意義和核心思想
- Prompt 典型構成
- 指令調優方法論
- 思維鏈和思維樹
- Prompt 攻擊和防范
- …
第二階段(30天):高階應用
該階段我們正式進入大模型 AI 進階實戰學習,學會構造私有知識庫,擴展 AI 的能力。快速開發一個完整的基于 agent 對話機器人。掌握功能最強的大模型開發框架,抓住最新的技術進展,適合 Python 和 JavaScript 程序員。
- 為什么要做 RAG
- 搭建一個簡單的 ChatPDF
- 檢索的基礎概念
- 什么是向量表示(Embeddings)
- 向量數據庫與向量檢索
- 基于向量檢索的 RAG
- 搭建 RAG 系統的擴展知識
- 混合檢索與 RAG-Fusion 簡介
- 向量模型本地部署
- …
第三階段(30天):模型訓練
恭喜你,如果學到這里,你基本可以找到一份大模型 AI相關的工作,自己也能訓練 GPT 了!通過微調,訓練自己的垂直大模型,能獨立訓練開源多模態大模型,掌握更多技術方案。
到此為止,大概2個月的時間。你已經成為了一名“AI小子”。那么你還想往下探索嗎?
- 為什么要做 RAG
- 什么是模型
- 什么是模型訓練
- 求解器 & 損失函數簡介
- 小實驗2:手寫一個簡單的神經網絡并訓練它
- 什么是訓練/預訓練/微調/輕量化微調
- Transformer結構簡介
- 輕量化微調
- 實驗數據集的構建
- …
第四階段(20天):商業閉環
對全球大模型從性能、吞吐量、成本等方面有一定的認知,可以在云端和本地等多種環境下部署大模型,找到適合自己的項目/創業方向,做一名被 AI 武裝的產品經理。
- 硬件選型
- 帶你了解全球大模型
- 使用國產大模型服務
- 搭建 OpenAI 代理
- 熱身:基于阿里云 PAI 部署 Stable Diffusion
- 在本地計算機運行大模型
- 大模型的私有化部署
- 基于 vLLM 部署大模型
- 案例:如何優雅地在阿里云私有部署開源大模型
- 部署一套開源 LLM 項目
- 內容安全
- 互聯網信息服務算法備案
- …
學習是一個過程,只要學習就會有挑戰。天道酬勤,你越努力,就會成為越優秀的自己。
如果你能在15天內完成所有的任務,那你堪稱天才。然而,如果你能完成 60-70% 的內容,你就已經開始具備成為一名大模型 AI 的正確特征了。
這份完整版的大模型 AI 學習資料已經上傳CSDN,朋友們如果需要可以微信掃描下方CSDN官方認證二維碼免費領取【保證100%免費
】
