1、文檔加載器

文檔加載器用來加載各種不同類型的文檔。LangChain提供了100 多種不同的文檔加載器,可以加載各種類型文檔,包括:CSV、HTML、JSON、Markdown、PDF、DOC、XLS、圖片、視頻、音頻等等。具體的文檔加載器參考:https://python.langchain.com/docs/integrations/document_loaders/

2、文本分割器

加載文檔后,對于長文檔,需要分割成更小的塊,以適合LLM的上下文窗口。LangChain 有許多內(nèi)置的文檔轉(zhuǎn)換器,可以輕松地拆分、組合、過濾和以其他方式操作文檔。

LangChain 提供了多種不同類型的文本分割器。下表列出了所有這些以及一些特征:

類型:文本分割器的類型

分割依據(jù):此文本拆分器如何拆分文本

添加元數(shù)據(jù):此文本拆分器是否添加有關(guān)每個塊來自何處的元數(shù)據(jù)。 

描述:分離器的描述,包括有關(guān)何時使用它的建議。

類型分割依據(jù)添加元數(shù)據(jù)描述
Recursive用戶定義的字符列表 遞歸地分割文本。遞歸地分割文本的目的是嘗試使相關(guān)的文本片段彼此相鄰。這是開始分割文本的推薦方法。
HTMLHTML 特定字符?根據(jù) HTML 特定字符分割文本。值得注意的是,這添加了有關(guān)該塊來自何處的相關(guān)信息(基于 HTML)
MarkdownMarkdown 特定字符?根據(jù) Markdown 特定字符分割文本。值得注意的是,這添加了有關(guān)該塊來自何處的相關(guān)信息(基于 Markdown)
Code代碼(Python、JS)特定字符 根據(jù)特定于編碼語言的字符分割文本。有 15 種不同的語言可供選擇。
TokenTokens 基于tokens分割文本。有幾種不同的方法來衡量tokens.
Character用戶定義的字符 根據(jù)用戶定義的字符分割文本。比較簡單的方法之一。
[Experimental] Semantic Chunker句子 首先對句子進行分割。然后,如果它們在語義上足夠相似,則將它們相鄰地組合起來。

3、嵌入模型

嵌入(Embedding)是一種將單詞、短語或整個文檔轉(zhuǎn)換為密集向量的技術(shù)。每個單詞或短語被轉(zhuǎn)換成一組數(shù)字,這組數(shù)字捕捉了該文本的某些語義特征。

嵌入模型通過將文本轉(zhuǎn)換為計算機可以處理的數(shù)值形式(即向量),使得計算機能夠理解和處理自然語言。通過嵌入捕獲文本的語義,可以快速有效地找到文本的其他相似部分。
LangChain提供了超過25種不同嵌入提供商和方法的集成,可以參考:https://python.langchain.com/docs/integrations/text_embedding 抱臉上有個中文、英文嵌入模型排行榜,可以作為參考,具體還要選適合自己的,比如開源的,對中文支持比較好的等等:https://huggingface.co/spaces/mteb/leaderboard

4、向量數(shù)據(jù)庫

有了嵌入模型對數(shù)據(jù)的向量化,就需要數(shù)據(jù)庫來支持這些嵌入數(shù)據(jù)的高效存儲和搜索。LangChain提供了50多種不同向量數(shù)據(jù)庫的集成,可以參考:https://python.langchain.com/docs/integrations/vectorstores 目前Milvus評分最高。

二、RAG開發(fā)案例

接下來我們實戰(zhàn)開發(fā)一個基于特定知識庫的智能問答應用。還是在Jupyter Notebook環(huán)境中執(zhí)行。

1、創(chuàng)建智譜GLM4大模型對象

首先定義LangChain里智譜大模型的包裝類,參考第一篇文章里有,或者從github上下載:https://github.com/taoxibj/docs/blob/main/zhipuai.py 創(chuàng)建大模型對象

# 填寫您自己的APIKey
ZHIPUAI_API_KEY = "..."
llm = ChatZhipuAI(
temperature=0.1,
api_key=ZHIPUAI_API_KEY,
model_name="glm-4",
)

2、加載文檔

這里特定領(lǐng)域用戶的數(shù)據(jù)來源于一個示例的ordersample.csv文件,這個文件可以從我的github上獲取:https://github.com/taoxibj/docs/blob/main/ordersample.csv

文件具體內(nèi)容如下:

把orersample.csv下載到jupyter notebook當前ipynb文件目錄,使用CSV文檔加載器,加載文檔內(nèi)容:

from langchain_community.document_loaders.csv_loader import CSVLoader

loader = CSVLoader(file_path='ordersample.csv')
data = loader.load()

打印加載后的文檔內(nèi)容:

from pprint import pprint
pprint(data)

按一行一個文檔,分成了6個文檔。

[Document(page_content='\ufeff訂單ID: 123456\n訂單金額: 100.18\n收貨人姓名: 李四同\n收貨人電話: 1234567890\n收貨地址: 北京市海淀區(qū)\n圖片: https://qnssl.niaogebiji.com/152701334564123796dd0f43.47234870.png', metadata={'source': 'ordersample.csv', 'row': 0}),
Document(page_content='\ufeff訂單ID: 111222\n訂單金額: 367.58\n收貨人姓名: 王五一\n收貨人電話: 1314567890\n收貨地址: 北京市朝陽區(qū)\n圖片: ', metadata={'source': 'ordersample.csv', 'row': 1}),
Document(page_content='\ufeff訂單ID: 333444\n訂單金額: 1234.5\n收貨人姓名: 張三豐\n收貨人電話: 1331112390\n收貨地址: 北京市西城區(qū)\n圖片: ', metadata={'source': 'ordersample.csv', 'row': 2}),
Document(page_content='\ufeff訂單ID: 123458\n訂單金額: 120.18\n收貨人姓名: 李四同\n收貨人電話: 1234567890\n收貨地址: 北京市海淀區(qū)\n圖片: https://qnssl.niaogebiji.com/152701334564123796dd0f43.47234870.png', metadata={'source': 'ordersample.csv', 'row': 3}),
Document(page_content='\ufeff訂單ID: 119822\n訂單金額: 267.58\n收貨人姓名: 王五一\n收貨人電話: 1314567890\n收貨地址: 北京市朝陽區(qū)\n圖片: ', metadata={'source': 'ordersample.csv', 'row': 4}),
Document(page_content='\ufeff訂單ID: 329444\n訂單金額: 234.5\n收貨人姓名: 張三豐\n收貨人電話: 1331112390\n收貨地址: 北京市西城區(qū)\n圖片: ', metadata={'source': 'ordersample.csv', 'row': 5})]

3、文本分割

通常可以使用遞歸字符文本分割器對文檔對象進行分割,可以設(shè)置分割塊字符的大小,和重合字符大小。因為我的文檔對象比較小,所以每個文檔基本上沒有達到要切分的大小閾值,可以嘗試把文檔內(nèi)容變多,試下效果。

from langchain.text_splitter import RecursiveCharacterTextSplitter

text_splitter = RecursiveCharacterTextSplitter(
chunk_size=1000, chunk_overlap=200, add_start_index=True
)
all_splits = text_splitter.split_documents(data)

可以打印一下分割后塊的數(shù)量。

len(all_splits)

4、向量化存儲

接下來我們首先使用嵌入模型對分割后的文檔進行向量化,然后存儲到向量數(shù)據(jù)庫中。

嵌入模型使用的是bge-large-zh-v1.5,這是BAAI北京智源人工智能研究院開源的,支持中、英文的嵌入模型,在開源嵌入模型中算是效果比較好的一個。向量數(shù)據(jù)庫使用的是FAISS,是FAIR(Meta人工智能實驗室)開源的向量數(shù)據(jù)庫。可以在本地使用,相對輕量些,沒有Milvus那么強, 但在本地環(huán)境使用也夠用了。

from langchain_community.embeddings import HuggingFaceBgeEmbeddings

model_name = "BAAI/bge-large-zh-v1.5"
model_kwargs = {"device": "cpu"}
encode_kwargs = {"normalize_embeddings": True}
bgeEmbeddings = HuggingFaceBgeEmbeddings(
model_name=model_name, model_kwargs=model_kwargs, encode_kwargs=encode_kwargs
)
from langchain_community.vectorstores import FAISS
vector = FAISS.from_documents(all_splits, bgeEmbeddings)

5、向量庫檢索

接下來嘗試下使用向量庫進行檢索。

retriever = vector.as_retriever(search_type="similarity", search_kwargs={"k": 3})
retriever.invoke("收貨人姓名是張三豐的,有幾個訂單?金額分別是多少,總共是多少?")

檢索結(jié)果如下。

[Document(page_content='\ufeff訂單ID: 329444\n訂單金額: 234.5\n收貨人姓名: 張三豐\n收貨人電話: 1331112390\n收貨地址: 北京市西城區(qū)\n圖片:', metadata={'source': 'ordersample.csv', 'row': 5, 'start_index': 0}),
Document(page_content='\ufeff訂單ID: 333444\n訂單金額: 1234.5\n收貨人姓名: 張三豐\n收貨人電話: 1331112390\n收貨地址: 北京市西城區(qū)\n圖片:', metadata={'source': 'ordersample.csv', 'row': 2, 'start_index': 0}),
Document(page_content='\ufeff訂單ID: 123456\n訂單金額: 100.18\n收貨人姓名: 李四同\n收貨人電話: 1234567890\n收貨地址: 北京市海淀區(qū)\n圖片: https://qnssl.niaogebiji.com/152701334564123796dd0f43.47234870.png', metadata={'source': 'ordersample.csv', 'row': 0, 'start_index': 0})]

6、生成問答結(jié)果

使用檢索鏈,串聯(lián)向量庫檢索和大模型,根據(jù)用戶的提問,生成問答結(jié)果。

from langchain_core.prompts import ChatPromptTemplate
prompt = ChatPromptTemplate.from_template("""僅根據(jù)所提供的上下文回答以下問題:

<context>
{context}
</context>

問題: {question}""")

from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough
retriever_chain = (
{"context": retriever , "question": RunnablePassthrough()}
| prompt
| llm
| StrOutputParser()
)

可以開始進行提問。提問一:

retriever_chain.invoke("訂單ID是123456的收貨人是誰,電話是多少?")

回答:

'根據(jù)所提供的上下文,訂單ID為123456的收貨人是李四同,電話是1234567890。'

提問二:

retriever_chain.invoke("收貨人張三豐有幾個訂單?金額分別是多少,總共是多少?")

回答:

'收貨人張三豐有兩個訂單。第一個訂單的訂單ID是329444,金額是234.5元;第二個訂單的訂單ID是333444,金額是1234.5元。這兩個訂單的總金額是1469元。'

提問三:

retriever_chain.invoke("收貨地址是朝陽區(qū)的有哪些訂單?")

回答:

'收貨地址是朝陽區(qū)的訂單有:\n\n1. 訂單ID: 119822,訂單金額: 267.58,收貨人姓名: 王五一,收貨人電話: 1314567890,收貨地址: 北京市朝陽區(qū)。\n2. 訂單ID: 111222,訂單金額: 367.58,收貨人姓名: 王五一,收貨人電話: 1314567890,收貨地址: 北京市朝陽區(qū)。\n\n以上兩個訂單的收貨地址均為北京市朝陽區(qū)。'

整體的回答結(jié)果還算準確。但是也有一些情況,回答的不對的,基本上是向量庫檢索出的答案有出入造成的問題,所以語料知識的向量化和結(jié)構(gòu)化,還是很重要的。

三、總結(jié)

這篇文章首先介紹了在LangChain中使用RAG的重要組成部分,包括文檔加載器、文本分割器、嵌入模型、向量數(shù)據(jù)庫,然后通過一個示例演示了LLM如何通過RAG檢索增強生成的方式,借助特定領(lǐng)域用戶數(shù)據(jù),更準確的回答用戶的提問。

對于RAG來說,語料的結(jié)構(gòu)化是很重要的,后面也會深入分析一些文檔材料如DOC、XLS、PDF的結(jié)構(gòu)化以及如何更好的進行切分來獲取更精準的答案。敬請期待。

文章轉(zhuǎn)自微信公眾號@頂尖程序員

上一篇:

最新LangChain+GLM4開發(fā)AI應用程序系列(二):Agent智能體篇

下一篇:

探索AI編程前沿:DeepSeek、CodeLlama、GLM與ChatGPT系列大模型Java編碼能力測評
#你可能也喜歡這些API文章!

我們有何不同?

API服務商零注冊

多API并行試用

數(shù)據(jù)驅(qū)動選型,提升決策效率

查看全部API→
??

熱門場景實測,選對API

#AI文本生成大模型API

對比大模型API的內(nèi)容創(chuàng)意新穎性、情感共鳴力、商業(yè)轉(zhuǎn)化潛力

25個渠道
一鍵對比試用API 限時免費

#AI深度推理大模型API

對比大模型API的邏輯推理準確性、分析深度、可視化建議合理性

10個渠道
一鍵對比試用API 限時免費