LangChain+ChatGLM項(xiàng)目(https://github.com/chatchat-space/langchain-ChatGLM)實(shí)現(xiàn)原理如下圖所示 (與基于文檔的問答 大同小異,過程包括:1 加載文檔 -> 2 讀取文檔 -> 3/4文檔分割 -> 5/6 文本向量化 -> 8/9 問句向量化 -> 10 在文檔向量中匹配出與問句向量最相似的top k個(gè) -> 11/12/13 匹配出的文本作為上下文和問題一起添加到prompt中 -> 14/15提交給LLM生成回答 )
一.文件加載與分割
加載文件:這是讀取存儲(chǔ)在本地的知識(shí)庫文件的步驟
讀取文件:讀取加載的文件內(nèi)容,通常是將其轉(zhuǎn)化為文本格式
文本分割(Text splitter):按照一定的規(guī)則(例如段落、句子、詞語等)將文本分割
def _load_file(self, filename):
# 判斷文件類型
if filename.lower().endswith(".pdf"): # 如果文件是 PDF 格式
loader = UnstructuredFileLoader(filename) # 使用 UnstructuredFileLoader 加載器來加載 PDF 文件
text_splitor = CharacterTextSplitter() # 使用 CharacterTextSplitter 來分割文件中的文本
docs = loader.load_and_split(text_splitor) # 加載文件并進(jìn)行文本分割
else: # 如果文件不是 PDF 格式
loader = UnstructuredFileLoader(filename, mode="elements") # 使用 UnstructuredFileLoader 加載器以元素模式加載文件
text_splitor = CharacterTextSplitter() # 使用 CharacterTextSplitter 來分割文件中的文本
docs = loader.load_and_split(text_splitor) # 加載文件并進(jìn)行文本分割
return docs # 返回處理后的文件數(shù)據(jù)
二.文本向量化與存儲(chǔ)
1.文本向量化(embedding)
這通常涉及到NLP的特征抽取,可以通過諸如TF-IDF、word2vec、BERT等方法將分割好的文本轉(zhuǎn)化為數(shù)值向量。
# 初始化方法,接受一個(gè)可選的模型名稱參數(shù),默認(rèn)值為 None
def __init__(self, model_name=None) -> None:
if not model_name: # 如果沒有提供模型名稱
# 使用默認(rèn)的嵌入模型
# 創(chuàng)建一個(gè) HuggingFaceEmbeddings 對(duì)象,模型名稱為類的 model_name 屬性
self.embeddings = HuggingFaceEmbeddings(model_name=self.model_name)
2.存儲(chǔ)到向量數(shù)據(jù)庫
文本向量化之后存儲(chǔ)到數(shù)據(jù)庫vectorstore。
def init_vector_store(self):
persist_dir = os.path.join(VECTORE_PATH, ".vectordb") # 持久化向量數(shù)據(jù)庫的地址
print("向量數(shù)據(jù)庫持久化地址: ", persist_dir) # 打印持久化地址
# 如果持久化地址存在
if os.path.exists(persist_dir):
# 從本地持久化文件中加載
print("從本地向量加載數(shù)據(jù)...")
# 使用 Chroma 加載持久化的向量數(shù)據(jù)
vector_store = Chroma(persist_directory=persist_dir, embedding_function=self.embeddings)
# 如果持久化地址不存在
else:
# 加載知識(shí)庫
documents = self.load_knownlege()
# 使用 Chroma 從文檔中創(chuàng)建向量存儲(chǔ)
vector_store = Chroma.from_documents(documents=documents,
embedding=self.embeddings,
persist_directory=persist_dir)
vector_store.persist() # 持久化向量存儲(chǔ)
return vector_store # 返回向量存儲(chǔ)
def load_knownlege(self):
docments = [] # 初始化一個(gè)空列表來存儲(chǔ)文檔
# 遍歷 DATASETS_DIR 目錄下的所有文件
for root, _, files in os.walk(DATASETS_DIR, topdown=False):
for file in files:
filename = os.path.join(root, file) # 獲取文件的完整路徑
docs = self._load_file(filename) # 加載文件中的文檔
# 更新 metadata 數(shù)據(jù)
new_docs = [] # 初始化一個(gè)空列表來存儲(chǔ)新文檔
for doc in docs:
# 更新文檔的 metadata,將 "source" 字段的值替換為不包含 DATASETS_DIR 的相對(duì)路徑
doc.metadata = {"source": doc.metadata["source"].replace(DATASETS_DIR, "")}
print("文檔2向量初始化中, 請(qǐng)稍等...", doc.metadata) # 打印正在初始化的文檔的 metadata
new_docs.append(doc) # 將文檔添加到新文檔列表
docments += new_docs # 將新文檔列表添加到總文檔列表
return docments # 返回所有文檔的列表
三.問句向量化
這是將用戶的查詢或問題轉(zhuǎn)化為向量,應(yīng)使用與文本向量化相同的方法,以便在相同的空間中進(jìn)行比較 。
四.相似文檔檢索
在文本向量中匹配出與問句向量最相似的top k個(gè),這一步是信息檢索的核心,通過計(jì)算余弦相似度、歐氏距離等方式,找出與問句向量最接近的文本向量。
def query(self, q):
"""在向量數(shù)據(jù)庫中查找與問句向量相似的文本向量"""
vector_store = self.init_vector_store()
docs = vector_store.similarity_search_with_score(q, k=self.top_k)
for doc in docs:
dc, s = doc
yield s, dc
五.prompt構(gòu)建
匹配出的文本作為上下文和問題一起添加到prompt中,這是利用匹配出的文本來形成與問題相關(guān)的上下文,用于輸入給語言模型。
六.答案生成
最后,將這個(gè)問題和上下文一起構(gòu)成的prompt提交給在線(例如GPT-4/ChatGPT)或本地化部署大語言模型,讓它生成回答。文章來源:http://www.zghlxwxcb.cn/news/detail-638657.html
class KnownLedgeBaseQA:
# 初始化
def __init__(self) -> None:
k2v = KnownLedge2Vector() # 創(chuàng)建一個(gè)知識(shí)到向量的轉(zhuǎn)換器
self.vector_store = k2v.init_vector_store() # 初始化向量存儲(chǔ)
self.llm = VicunaLLM() # 創(chuàng)建一個(gè) VicunaLLM 對(duì)象
# 獲得與查詢相似的答案
def get_similar_answer(self, query):
# 創(chuàng)建一個(gè)提示模板
prompt = PromptTemplate(
template=conv_qa_prompt_template,
input_variables=["context", "question"] # 輸入變量包括 "context"(上下文) 和 "question"(問題)
)
# 使用向量存儲(chǔ)來檢索文檔
retriever = self.vector_store.as_retriever(search_kwargs={"k": VECTOR_SEARCH_TOP_K})
docs = retriever.get_relevant_documents(query=query) # 獲取與查詢相關(guān)的文本
context = [d.page_content for d in docs] # 從文本中提取出內(nèi)容
result = prompt.format(context="\n".join(context), question=query) # 格式化模板,并用從文本中提取出的內(nèi)容和問題填充
return result # 返回結(jié)果
這種通過組合langchain+LLM的方式,特別適合一些垂直領(lǐng)域或大型集團(tuán)企業(yè)搭建通過LLM的智能對(duì)話能力搭建企業(yè)內(nèi)部的私有問答系統(tǒng),也適合個(gè)人專門針對(duì)一些英文paper進(jìn)行問答,比如比較火的一個(gè)開源項(xiàng)目:ChatPDF,其從文檔處理角度來看,實(shí)現(xiàn)流程如下(圖源):文章來源地址http://www.zghlxwxcb.cn/news/detail-638657.html
到了這里,關(guān)于AIGC:【LLM(四)】——LangChain+ChatGLM:本地知識(shí)庫問答方案的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!