不用ftp做網(wǎng)站云seo關(guān)鍵詞排名優(yōu)化軟件
Tip: 如果你在進(jìn)行深度學(xué)習(xí)、自動(dòng)駕駛、模型推理、微調(diào)或AI繪畫出圖等任務(wù),并且需要GPU資源,可以考慮使用UCloud云計(jì)算旗下的Compshare的GPU算力云平臺(tái)。他們提供高性價(jià)比的4090 GPU,按時(shí)收費(fèi)每卡2.6元,月卡只需要1.7元每小時(shí),并附帶200G的免費(fèi)磁盤空間。通過鏈接注冊并聯(lián)系客服,可以獲得20元代金券(相當(dāng)于6-7H的免費(fèi)GPU資源)。歡迎大家體驗(yàn)一下~
0. 簡介
自從發(fā)現(xiàn)可以利用自有數(shù)據(jù)來增強(qiáng)大語言模型(LLM)的能力以來,如何將 LLM 的通用知識(shí)與個(gè)人數(shù)據(jù)有效結(jié)合一直是熱門話題。關(guān)于使用微調(diào)(fine-tuning)還是檢索增強(qiáng)生成(RAG)來實(shí)現(xiàn)這一目標(biāo)的討論持續(xù)不斷。檢索增強(qiáng)生成 (RAG) 是一種使用來自私有或?qū)S袛?shù)據(jù)源的信息來輔助文本生成的技術(shù)。它將檢索模型(設(shè)計(jì)用于搜索大型數(shù)據(jù)集或知識(shí)庫)和生成模型(例如大型語言模型 (LLM),此類模型會(huì)使用檢索到的信息生成可供閱讀的文本回復(fù))結(jié)合在一起。
用一個(gè)簡單的比喻來說, RAG 對(duì)大語言模型(Large Language Model,LLM)的作用,就像開卷考試對(duì)學(xué)生一樣。在開卷考試中,學(xué)生可以帶著參考資料進(jìn)場,比如教科書或筆記,用來查找解答問題所需的相關(guān)信息。開卷考試的核心在于考察學(xué)生的推理能力,而非對(duì)具體信息的記憶能力。同樣地,在 RAG 中,事實(shí)性知識(shí)與 LLM 的推理能力相分離,被存儲(chǔ)在容易訪問和及時(shí)更新的外部知識(shí)源中,具體分為兩種:
- 參數(shù)化知識(shí)(Parametric knowledge): 模型在訓(xùn)練過程中學(xué)習(xí)得到的,隱式地儲(chǔ)存在神經(jīng)網(wǎng)絡(luò)的權(quán)重中。
- 非參數(shù)化知識(shí)(Non-parametric knowledge): 存儲(chǔ)在外部知識(shí)源,例如向量數(shù)據(jù)庫中。
1. 了解LangChain
從上圖可以看到,LangChain 目前有四層框架:
- 最下層深色部分:LangChain的Python和JavaScript庫。包含無數(shù)組件的接口和集成,以及將這些組件組合到一起的鏈(chain)和代理(agent)封裝,還有鏈和代理的具體實(shí)現(xiàn)。
- Templates:一組易于部署的參考體系結(jié)構(gòu),用于各種各樣的任務(wù)。
- LangServe:用于將LangChain鏈部署為REST API的庫。
- LangSmith:一個(gè)開發(fā)人員平臺(tái),允許您調(diào)試、測試、評(píng)估和監(jiān)控基于任何LLM框架構(gòu)建的鏈,并與LangChain無縫集成。
2. RAG基礎(chǔ)使用
首先,你需要建立一個(gè)向量數(shù)據(jù)庫,這個(gè)數(shù)據(jù)庫作為一個(gè)外部知識(shí)源,包含了所有必要的額外信息。填充這個(gè)數(shù)據(jù)庫需要遵循以下步驟:
- 收集數(shù)據(jù)并將其加載進(jìn)系統(tǒng)
- 將你的文檔進(jìn)行分塊處理
- 對(duì)分塊內(nèi)容進(jìn)行嵌入,并存儲(chǔ)這些塊
首先,你需要收集并加載數(shù)據(jù)。為了加載數(shù)據(jù),你可以利用 LangChain 提供的眾多 DocumentLoader 之一。Document 是一個(gè)包含文本和元數(shù)據(jù)的字典。為了加載文本,你會(huì)使用 LangChain 的 TextLoader。
import requests
from langchain.document_loaders import TextLoaderurl = "https://raw.githubusercontent.com/langchain-ai/langchain/master/docs/docs/modules/state_of_the_union.txt"
res = requests.get(url)
with open("state_of_the_union.txt", "w") as f:f.write(res.text)loader = TextLoader('./state_of_the_union.txt')
documents = loader.load()
其次,需要對(duì)文檔進(jìn)行分塊 — 由于 Document 的原始大小超出了 LLM 處理窗口的限制,因此需要將其切割成更小的片段。LangChain 提供了許多文本分割工具,對(duì)于這個(gè)簡單的示例,你可以使用 CharacterTextSplitter,設(shè)置 chunk_size 大約為 500,并且設(shè)置 chunk_overlap 為 50,以確保文本塊之間的連貫性。
from langchain.text_splitter import CharacterTextSplitter
text_splitter = CharacterTextSplitter(chunk_size=500, chunk_overlap=50)
chunks = text_splitter.split_documents(documents)
最后一步是嵌入并存儲(chǔ)這些文本塊 — 為了實(shí)現(xiàn)對(duì)文本塊的語義搜索,你需要為每個(gè)塊生成向量嵌入,并將它們存儲(chǔ)起來。生成向量嵌入時(shí),你可以使用 OpenAI 的嵌入模型;而存儲(chǔ)它們,則可以使用 Weaviate 向量數(shù)據(jù)庫。通過執(zhí)行 .from_documents() 操作,就可以自動(dòng)將這些塊填充進(jìn)向量數(shù)據(jù)庫中。
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import Weaviate
import weaviate
from weaviate.embedded import EmbeddedOptionsclient = weaviate.Client(embedded_options = EmbeddedOptions()
)vectorstore = Weaviate.from_documents(client = client,documents = chunks,embedding = OpenAIEmbeddings(),by_text = False
)
一旦向量數(shù)據(jù)庫準(zhǔn)備好,你就可以將它設(shè)定為檢索組件,這個(gè)組件能夠根據(jù)用戶查詢與已嵌入的文本塊之間的語義相似度,來檢索出額外的上下文信息
retriever = vectorstore.as_retriever()
接下來,你需要準(zhǔn)備一個(gè)提示模板,以便用額外的上下文信息來增強(qiáng)原始的提示。你可以根據(jù)下面顯示的示例,輕松地定制這樣一個(gè)提示模板。
from langchain.prompts import ChatPromptTemplatetemplate = """You are an assistant for question-answering tasks.
Use the following pieces of retrieved context to answer the question.
If you don't know the answer, just say that you don't know.
Use three sentences maximum and keep the answer concise.
Question: {question}
Context: {context}
Answer:
"""
prompt = ChatPromptTemplate.from_template(template)print(prompt)
在 RAG (檢索增強(qiáng)生成) 管道的構(gòu)建過程中,可以通過將檢索器、提示模板與大語言模型 (LLM) 相結(jié)合來形成一個(gè)序列。定義好 RAG 序列之后,就可以開始執(zhí)行它。
from langchain.chat_models import ChatOpenAI
from langchain.schema.runnable import RunnablePassthrough
from langchain.schema.output_parser import StrOutputParserllm = ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0)rag_chain = ({"context": retriever, "question": RunnablePassthrough()}| prompt| llm| StrOutputParser()
)query = "What did the president say about Justice Breyer"
rag_chain.invoke(query)
3. ollama替換chatgpt完成聯(lián)網(wǎng)搜索拆分
此外可以通過ollama檢索完成Embedding,給他資料,讓他從這些資料從中找到答案來回答問題,就是構(gòu)建知識(shí)庫,回答問題
urls = ["https://ollama.com/","https://ollama.com/blog/windows-preview","https://ollama.com/blog/openai-compatibility",
]
docs = [WebBaseLoader(url).load() for url in urls]
docs_list = [ item for sublist in docs for item in sublist]
#text_splitter = CharacterTextSplitter.from_tiktoken_encoder(chunk_size=7500,chunk_overlap=100)
text_splitter = CharacterTextSplitter.from_tiktoken_encoder(chunk_size=7500, chunk_overlap=100)
docs_splits = text_splitter.split_documents(docs_list)# 2 convert documents to Embeddings and store themvectorstore = Chroma.from_documents(documents=docs_splits,collection_name="rag-chroma",embedding=embeddings.ollama.OllamaEmbeddings(model='nomic-embed-text'),
)retriever =vectorstore.as_retriever()# 4 after RAG
print("\n######\nAfter RAG\n")
after_rag_template ="""Answer the question based only the following context:
{context}
Question:{question}
"""
after_rag_prompt = ChatPromptTemplate.from_template(after_rag_template)
after_rag_chain = ({"context": retriever, "question": RunnablePassthrough()}| after_rag_prompt| model_local| StrOutputParser()
)
print(after_rag_chain.invoke("What is Ollama?"))
通過三個(gè)網(wǎng)址,獲取數(shù)據(jù),將其轉(zhuǎn)化為embedding,存儲(chǔ)在向量庫中,我們提問時(shí),就能得到我們想要的一個(gè)初步答案,比未給語料時(shí)效果要好。
使用nomic-embed-text進(jìn)行嵌入,nomic-embed-text具有更高的上下文長度8k,該模型在短文本和長文本任務(wù)上均優(yōu)于 OpenAI Ada-002 和text-embedding-3-small。
4. 多模態(tài)RAG
為了幫助模型識(shí)別出"貓"的圖像和"貓"這個(gè)詞是相似的,我們依賴于多模態(tài)嵌入。為了簡化一下,想象有一個(gè)魔盒,能夠處理各種輸入——圖像、音頻、文本等。現(xiàn)在,當(dāng)我們用一張"貓"的圖像和文本"貓"來喂養(yǎng)這個(gè)盒子時(shí),它施展魔法,生成兩個(gè)數(shù)值向量。當(dāng)這兩個(gè)向量被輸入機(jī)器時(shí),機(jī)器會(huì)想:"根據(jù)這些數(shù)值,看起來它們都與’貓’有關(guān)。"這正是我們的目標(biāo)!我們的目標(biāo)是幫助機(jī)器識(shí)別"貓"的圖像和文本"貓"之間的密切聯(lián)系。然而,為了驗(yàn)證這個(gè)概念,當(dāng)我們在向量空間中繪制這兩個(gè)數(shù)值向量時(shí),結(jié)果發(fā)現(xiàn)它們非常接近。這個(gè)結(jié)果與我們之前觀察到的兩個(gè)文本詞"貓"和"狗"在向量空間中的接近度完全一致。這就是多模態(tài)的本質(zhì)。
現(xiàn)在我們訓(xùn)練文本-圖像模型識(shí)別出正樣本提供了準(zhǔn)確的解釋,而負(fù)樣本具有誤導(dǎo)性,應(yīng)該在訓(xùn)練過程中被忽略。正式來說,這種技術(shù)被OpenAI引入的 CLIP[2] (對(duì)比語言-圖像預(yù)訓(xùn)練)所稱,作者在大約4億對(duì)從互聯(lián)網(wǎng)上獲取的圖像標(biāo)題對(duì)上訓(xùn)練了一個(gè)圖像-文本模型,每當(dāng)模型犯錯(cuò)誤時(shí),對(duì)比損失函數(shù)就會(huì)增加并懲罰它,以確保模型訓(xùn)練良好。同樣的原則也適用于其他模態(tài)組合,例如貓的聲音與貓這個(gè)詞是語音-文本模型的正樣本,一段貓的視頻與描述性文本"這是一只貓"是視頻-文本模型的正樣本。