自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

通過檢索增強生成(RAG) 增強LLM的實戰(zhàn)演練 原創(chuàng)

發(fā)布于 2024-5-20 08:27
瀏覽
0收藏

本文主要介紹如何通過檢索增強生成(RAG)增強LLM,并使用LlamaIndex和LangChain作為數(shù)據(jù)場景,將應(yīng)用程序部署到Heroku。

擁有正確的數(shù)據(jù)來支持用例對于在任何業(yè)務(wù)中成功采用大型語言模型(LLM)都是至關(guān)重要的。雖然大多數(shù)現(xiàn)成的LLM在完成一般任務(wù)上表現(xiàn)出色,但它們在處理特定的業(yè)務(wù)問題時可能會遇到困難。它們沒有針對開發(fā)人員的業(yè)務(wù)問題進(jìn)行數(shù)據(jù)訓(xùn)練,因此沒有足夠的場景來解決問題。

企業(yè)通常擁有大量的內(nèi)部數(shù)據(jù)和文檔,可以滿足特定場景的需求。但是有一個問題:如何將所有這些有用的數(shù)據(jù)(場景)集成到LLM中,而不需要進(jìn)行資源密集型和耗時的再培訓(xùn)或微調(diào)LLM?

其答案是檢索增強生成(RAG),這是一種通過實時檢索緊密場景信息來增強LLM的技術(shù)。

本文將介紹如何使用LlamaIndex和LangChain來實現(xiàn)LLM場景數(shù)據(jù)的存儲和檢索。將通過使用LlamaIndex解決一個特定于場景的RAG問題,然后將解決方案輕松地部署到Heroku。

在開始編碼之前,首先簡要介紹一下核心概念。

RAG和LlamaIndex簡介

當(dāng)向LLM提出一個需要場景來回答的問題時,RAG會檢索場景數(shù)據(jù)幫助LLM給出更準(zhǔn)確、更具體的回答。這就像讓廚師迅速前往農(nóng)貿(mào)市場去采購儲藏室沒有的最新鮮的食材一樣,這樣廚師長就可以采用所有必要的食材烹制出完美的菜肴。

RAG工作流如何提供場景的一個關(guān)鍵是使用矢量數(shù)據(jù)庫和矢量搜索索引。以下了解一些核心概念以及實現(xiàn)這一切所包含的內(nèi)容。

  • 向量是一組編碼數(shù)字,表示一段文本(例如單詞、短語、句子,甚至整個文檔)的含義和場景。
  • 嵌入是向量中的實際數(shù)值,但大多數(shù)人傾向于交替使用 “向量”和“嵌入”這兩個術(shù)語。
  • 已經(jīng)在文檔上訓(xùn)練了嵌入模型,以便它可以將新輸入的文本轉(zhuǎn)換為向量。并非所有的文本都以相同的方式談?wù)撓嗤氖虑椤紤]學(xué)術(shù)研究論文與營銷材料的不同。因此,有不同的嵌入模型——每個模型都在特定的數(shù)據(jù)集上訓(xùn)練,并且考慮特定的目標(biāo)。
  • 使用嵌入模型,可以從文檔中創(chuàng)建嵌入,將這些文檔中的文本分解為編碼數(shù)字。創(chuàng)建嵌入可能涉及到文檔分塊這樣的策略,它將大文檔分成更小的、可管理的部分。從那里,每個塊被轉(zhuǎn)換成一個嵌入。
  • 當(dāng)查詢一個向量數(shù)據(jù)庫時,其問題被轉(zhuǎn)換成一個嵌入,并與存儲在矢量數(shù)據(jù)庫中的所有其他嵌入進(jìn)行比較。
  • 當(dāng)建立一個向量搜索索引,可以執(zhí)行非??焖俸蜏?zhǔn)確的向量搜索(也稱為相似性搜索)。使用矢量數(shù)據(jù)庫可以執(zhí)行快速而準(zhǔn)確的搜索——不僅僅是像在傳統(tǒng)數(shù)據(jù)庫中那樣匹配特定字符串的存在,而且還可以匹配與使用的單詞在意義上相似的文檔。

在RAG場景中,使用原始提示符對矢量數(shù)據(jù)庫中的所有文檔執(zhí)行矢量搜索。然后,將這些匹配的文檔作為場景發(fā)送到LLM應(yīng)用程序。LLM現(xiàn)在有一組詳細(xì)的注釋,在對原始提示進(jìn)行回答時可以參考。

通過檢索增強生成(RAG) 增強LLM的實戰(zhàn)演練-AI.x社區(qū)

LlamaIndex是一個關(guān)鍵的框架,它簡化了集成、組織和檢索私有或?qū)S脭?shù)據(jù)的過程。它將幫助開發(fā)人員創(chuàng)建文檔嵌入和矢量搜索索引。然后,將依靠LangChain將其拼湊在一起,執(zhí)行相似性搜索并將結(jié)果發(fā)送到LLM以獲取響應(yīng)。LlamaIndex和LangChain共同為處理RAG工作流提供了一個安全可靠的解決方案。

準(zhǔn)備好做些什么了嗎?現(xiàn)在開始吧!

演示項目簡介

使用LlamaIndex和Heroku學(xué)習(xí)RAG的最好方法是構(gòu)建一個小型的示例應(yīng)用程序。出于開發(fā)人員的目的,假設(shè)正在與“古登堡計劃”(Project Gutenberg)合作,這是一個擁有70000多本免費電子書的圖書館。如果想要構(gòu)建一個基于LLM的聊天機器人,它可以回答關(guān)于項目中免費書籍的特定問題。

這是使用RAG的完美用例,可以使用LlamaIndex獲得的大量書籍文本。為了使項目簡單,將使用公元401年問世的《圣奧古斯丁的懺悔錄》書中的內(nèi)容。

完成的項目代碼庫可以在這個GitHub存儲庫(https://github.com/alvinslee/llamaindex-gutenberg-demo)中找到。如果愿意的話,可以克隆repo并將應(yīng)用程序部署到Heroku。或者,可以逐步了解如何獲得代碼。

構(gòu)建這個演示項目將遵循以下一些步驟:

  • 設(shè)置項目。
  • 加載數(shù)據(jù)。
  • 構(gòu)建索引。
  • 存儲索引。
  • 集成LangChain。
  • 部署到Heroku。

步驟1:設(shè)置項目

為Python項目創(chuàng)建一個新文件夾,然后激活venv并安裝需要的初始依賴項。

Shell 
1 (venv) ~/project$ pip install llama-index langchain langchain-openai

接下來,將加載要索引的數(shù)據(jù)。

步驟2:加載數(shù)據(jù)

在構(gòu)建用于RAG的內(nèi)部數(shù)據(jù)索引時,必須將所有數(shù)據(jù)(文本)收集到一個地方。在這個例子中,該項目采用了《圣奧古斯丁的懺悔錄》的文本。將使用LlamaIndex將這個場景轉(zhuǎn)換為嵌入的矢量索引。

在典型的用例中,其場景數(shù)據(jù)將是適合試圖解決的業(yè)務(wù)問題的大型文本語料庫。

對于這個小型演示項目,將創(chuàng)建一個名為data的子文件夾,然后將該書作為單個文件下載到該文件夾中。

Shell 
1(venv) ~/project$ mkdir data
2
3 (venv) ~/project$ curl \
4           https://www.gutenberg.org/cache/epub/3296/pg3296.txt \
5              -o data/confessions.txt
6
7
8 (venv) ~/project$ ls data
9  confessions.txt

步驟3:構(gòu)建索引

在一個目錄中收集了所有數(shù)據(jù)之后,就可以構(gòu)建索引了。將編寫一個簡單的Python應(yīng)用程序,它將使用LlamaIndex為數(shù)據(jù)建立索引,然后查詢索引。

為此,需要一個OpenAI帳戶和API密鑰。這是因為LlamaIndex使用OpenAI的text-embedding-3-small作為默認(rèn)嵌入模型 (更改這些默認(rèn)值超出了本文的討論范圍) 。

在這個項目的根文件夾中,創(chuàng)建了一個名為index.py的文件。初始內(nèi)容如下所示:
Python 
1 # index.py
2
3 from llama_index.core import VectorStoreIndex, SimpleDirectoryReader
4 import os
5
6 if os.environ.get('OPENAI_API_KEY') is None:
7  exit('You must provide an OPENAI_API_KEY env var.')
8
9 documents = SimpleDirectoryReader("data").load_data()
10 index = VectorStoreIndex.from_documents(documents)
11
12 query_engine = index.as_query_engine()
13 response = query_engine.query("In which city is Saint Augustine the Bishop?")
14 print(response)

運行文件并收到預(yù)期的響應(yīng):

Shell 
1 (venv) ~/project$ OPENAI_API_KEY=sk-******** python index.py
2 Hippo

當(dāng)然,可以再次檢查數(shù)據(jù)??纯催@本書的前幾行,可以看到:

Shell 
1 THE CONFESSIONS OF SAINT AUGUSTINE
2
3 By Saint Augustine
4
5 Bishop of Hippo

正如人們所看到的,LlamaIndex完成了它的工作。Python應(yīng)用程序完全按照開發(fā)人員對向量索引數(shù)據(jù)的期望回答了問題。

步驟4:存儲索引

需要注意的是,在上面的示例中,只將索引數(shù)據(jù)存儲在內(nèi)存中,而不是磁盤上。索引(現(xiàn)在是內(nèi)存中的一系列向量嵌入)將在調(diào)用OpenAI模型并完成工作流后完全丟失。

為文本創(chuàng)建向量索引(嵌入)不是免費的,所以不想每次調(diào)用模型時都重新計算這些結(jié)果。最好有一個單獨的工作流將索引持久化到磁盤。然后,可以在任何時候引用它。

一種常見的方法是將嵌入存儲在PostgreSQL數(shù)據(jù)庫中,并使用pgvector執(zhí)行相似性搜索。為了使演示簡單,只將索引數(shù)據(jù)存儲為平面文件。

因此,將這個簡單的步驟添加到index.py文件中:

Python 
1 PERSIST_DIR='./my_vector_indexes/gutenberg/'
2 index.storage_context.persist(persist_dir=PERSIST_DIR)

現(xiàn)在,在運行文件之后,可以檢查存儲的索引。

Shell 
1 (venv) ~/project$ OPENAI_API_KEY=sk-******** python index.py
2 Hippo
3
4 (venv) ~/project$ tree
5 .
6├── data
7│   └── confessions.txt
8├── index.py
9└── my_vector_indexes
10    └── gutenberg
11        ├── default__vector_store.json
12        ├── docstore.json
13        ├── graph_store.json
14        ├── image__vector_store.json
15        └── index_store.json
16
17 3 directories, 7 files

步驟5:整合LangChain

已經(jīng)了解矢量索引存儲的基礎(chǔ)知識,以及構(gòu)建一個矢量索引存儲是多么容易。但是,為了真正構(gòu)建一個將所有內(nèi)容鏈接在一起的端到端應(yīng)用程序,可以使用LangChain。這樣,就可以將解決方案部署為API。可以重寫index.py代碼,使其更適合生產(chǎn)環(huán)境。

以下將展示代碼,然后解釋接下來要做的事情。它可能看起來像很多代碼,但只添加了一些新步驟。

Python 
1 # index.py
2
3 import os
4 from langchain_openai import ChatOpenAI
5 from langchain.chains import ConversationalRetrievalChain
6 from langchain.memory import ConversationBufferWindowMemory
7 from llama_index.core import VectorStoreIndex, SimpleDirectoryReader
8 from langchain_community.retrievers import LlamaIndexRetriever
9 from fastapi import FastAPI
10 from pydantic import BaseModel
11
?12 if os.environ.get('OPENAI_API_KEY') is None:
13  exit('You must provide an OPENAI_API_KEY env var.')
14
15 documents = SimpleDirectoryReader("data").load_data()
16 index = VectorStoreIndex.from_documents(documents)
17
18 # For this demo, we will not persist the index.
19
20
21 retriever = LlamaIndexRetriever(index=index.as_query_engine())
22
23 llm = ChatOpenAI(model_name="gpt-3.5-turbo", max_tokens=2048)
24
25 memory = ConversationBufferWindowMemory(
26  memory_key='chat_history',
27  return_messages=True,
28  k=3
29 )
30
?31 conversation = ConversationalRetrievalChain.from_llm(
32  llm=llm, 
33  retriever=retriever,
34  memory=memory,
35  max_tokens_limit=1536  
36 )
37
38 class Prompt(BaseModel):
39  question: str
40
41 app = FastAPI()
42
43 @app.post("/prompt")
44 async def query_chatbot(prompt: Prompt):
45  response = conversation.invoke({'question': prompt.question})
46  return response['answer']
47
48 if __name__=='__main__':
49  import uvicorn
50  uvicorn.run(app, host="localhost", port=8000)

首先,要注意的是,現(xiàn)在直接使用了LangChain和OpenAI。將LLM與一些內(nèi)存一起設(shè)置,以便在后續(xù)查詢中“記住”對話?,F(xiàn)在有一個真正的聊天機器人,可以與之互動。

從這里,使用FastAPI創(chuàng)建一個API服務(wù)器,該服務(wù)器監(jiān)聽/prompt端點上的POST請求。對該端點的請求預(yù)計具有帶有問題的請求體,然后將其(連同來自向量索引的場景)傳遞給LLM。

使用uvicorn在端口8000上啟動服務(wù)器。

在啟動服務(wù)器之前,添加這些新的Python依賴項:

Shell 
1(venv) ~/project$ pip install fastapi pydantic uvicorn

現(xiàn)在是測試的時候了。首先啟動服務(wù)器。

Shell 
1 (venv) ~/project$ OPENAI_API_KEY=sk-******** python index.py
2INFO:     Started server process [1101807]
3 INFO:     Waiting for application startup.
4 INFO:     Application startup complete.
5 INFO:     Uvicorn running on http://localhost:8000 (Press CTRL+C to quit)

在另一個終端中,向端點發(fā)送一個curl請求。

Shell 
1 $ curl -X POST \
2       --header "Content-type:application/json" \
3       --data '{"question":"Who is Ambrose?"}' \
4       http://localhost:8000/prompt
5
6
7 "Ambrose is a person mentioned in the text provided. He is described as a respected
8 and celibate man who was esteemed by the author. Ambrose is depicted as a figure of
9 great honor and excellence, particularly known for his dedication to reading and
10 studying."
11

獲得成功!向量索引似乎已經(jīng)啟動并運行,這個聊天機器人功能齊全,是部署的時候了。

步驟6:部署到Heroku

在完成了主要的工作之后,只需要采取幾個簡單的步驟將應(yīng)用程序部署到Heroku。

(1)用Python依賴項創(chuàng)建requirements.txt文件

Heroku需要知道在構(gòu)建項目時要安裝哪些Python依賴項。它在一個名為requirements.txt的文件中查找這個列表。可以用下面的命令輕松地生成:

Shell 
1(venv) ~/project$ pip freeze > requirements.txt

(2)創(chuàng)建Procfile

還需要告訴Heroku如何啟動Python應(yīng)用程序。在一個名為Procfile的文件中執(zhí)行這一操作。

Shell 
1 (venv) ~/project$ echo \
2                 'web: uvicorn index:app --host=0.0.0.0 --port=${PORT}' > Procfile

(3)創(chuàng)建runtime.txt文件

最后,runtime.txt將告訴Heroku希望使用哪種Python運行時版本。

Shell 
1 (venv) ~/project$ echo 'python-3.11.8' > runtime.txt

這些都是需要的文件。這時項目文件夾結(jié)構(gòu)應(yīng)該看起來像(已經(jīng)刪除了持久化的矢量索引):

Shell 
1 ~/project$ tree
2 .
3├── data
4│   └── confessions.txt
5├── index.py
6├── Procfile
7├── requirements.txt
8└── runtime.txt
9
10 1 directory, 5 files

如果開發(fā)人員是從頭開始工作,并且沒有為這個演示項目克隆GitHub倉庫,那么將這些文件提交到自己的Git存儲庫。

(4)創(chuàng)建Heroku應(yīng)用程序

下載并安裝Heroku CLI后,執(zhí)行如下命令。開發(fā)人員可以為其應(yīng)用程序選擇任何名字,需要提供唯一的OpenAI API密鑰。

Shell 
1 ~/project$ heroku login
2
3 ~/project$ heroku apps:create my-llamaindex-app
4
5 ~/project$ heroku git:remote -a my-llamaindex-app
6
7 ~/project$ heroku config:add OPENAI_API_KEY=replaceme -a my-llamaindex-app
8
9 ~/project$ git push heroku main
10 …
11 remote: -----> Building on the Heroku-22 stack
12 remote: -----> Determining which buildpack to use for this app
13 remote: -----> Python app detected
14 remote: -----> Using Python version specified in runtime.txt
15 …
16 remote: -----> Launching...
17 remote:        Released v4
18 remote:        https://my-llamaindex-app-6b48faa3ee6a.herokuapp.com/ deployed to Heroku
19

部署應(yīng)用程序后,通過向API服務(wù)器發(fā)送curl請求進(jìn)行測試:

Shell 
1 $ curl -X POST \
2       --header "Content-type:application/json" \
3       --data '{"question":"Who is Ambrose?"}' \
4       https://my-llamaindex-app-6b48faa3ee6a.herokuapp.com/prompt
5
6 "Ambrose is a significant figure in the text provided. He is being described as a
7 respected and happy man, known for his celibacy and his dedication to reading and
8 studying. He is referred to as a holy oracle and a person of great influence and
9 wisdom."
10

需要記住的是,上面的curl調(diào)用在部署中使用了唯一的Heroku應(yīng)用URL。

現(xiàn)在已經(jīng)在Heroku上運行了!

結(jié)論

現(xiàn)在已經(jīng)清楚地了解了LlamaIndex的強大功能,以及它在構(gòu)建RAG應(yīng)用程序與LLM交互時所扮演的重要角色。當(dāng)可以很容易地添加特定的數(shù)據(jù)源作為LLM的場景,而不需采用成本昂貴的模型再訓(xùn)練時,這是一個巨大的勝利。而對于希望進(jìn)一步推進(jìn)LLM工作流程的公司和開發(fā)人員來說,這也是一個勝利。

將LlamaIndex與其他LangChain工具集結(jié)合起來也是無縫且直接的,構(gòu)建聊天機器人只需要幾行額外的代碼。最后,能夠快速輕松地將解決方案部署到Heroku,使應(yīng)用程序可以立即訪問,而不會有任何麻煩。像這樣的簡單部署使開發(fā)人員能夠?qū)W⒂跇?gòu)建基于LLM的解決方案這一更復(fù)雜、更重要的任務(wù)。

原文標(biāo)題:How To Implement RAG: A Simple Walkthrough,作者:Alvin Lee

鏈接:https://dzone.com/articles/how-to-implement-rag-a-simple-walkthrough。

?著作權(quán)歸作者所有,如需轉(zhuǎn)載,請注明出處,否則將追究法律責(zé)任
收藏
回復(fù)
舉報
回復(fù)
相關(guān)推薦