做電子商務(wù)網(wǎng)站需要什么軟件seo標(biāo)題優(yōu)化褲子關(guān)鍵詞
LangChain的介紹和入門
1 什么是LangChain
LangChain由 Harrison Chase 創(chuàng)建于2022年10月,它是圍繞LLMs(大語言模型)建立的一個框架,LLMs使用機(jī)器學(xué)習(xí)算法和海量數(shù)據(jù)來分析和理解自然語言,GPT3.5、GPT4是LLMs最先進(jìn)的代表,國內(nèi)百度的文心一言、阿里的通義千問也屬于LLMs。LangChain自身并不開發(fā)LLMs,它的核心理念是為各種LLMs實(shí)現(xiàn)通用的接口,把LLMs相關(guān)的組件“鏈接”在一起,簡化LLMs應(yīng)用的開發(fā)難度,方便開發(fā)者快速地開發(fā)復(fù)雜的LLMs應(yīng)用。LangChain目前有兩個語言的實(shí)現(xiàn):Python和Node.js
我們從兩個方面全面介紹LangChain:一個是LangChain組件的基本概念和應(yīng)用;另一個是LangChain常見的使用場景。
2 LangChain主要組件
一個LangChain的應(yīng)用是需要多個組件共同實(shí)現(xiàn)的,LangChain主要支持6種組件:
- Models:模型,各種類型的模型和模型集成,比如GPT-4
- Prompts:提示,包括提示管理、提示優(yōu)化和提示序列化
- Memory:記憶,用來保存和模型交互時的上下文狀態(tài)
- Indexes:索引,用來結(jié)構(gòu)化文檔,以便和模型交互
- Chains:鏈,一系列對各種組件的調(diào)用
- Agents:代理,決定模型采取哪些行動,執(zhí)行并且觀察流程,直到完成為止
2.1 Models
現(xiàn)在市面上的模型多如牛毛,各種各樣的模型不斷出現(xiàn),LangChain模型組件提供了與各種模型的集成,并為所有模型提供一個精簡的統(tǒng)一接口。
LangChain目前支持三種類型的模型:LLMs、Chat Models(聊天模型)、Embeddings Models(嵌入模型).
-
LLMs: 大語言模型接收文本字符作為輸入,返回的也是文本字符.
-
聊天模型: 基于LLMs, 不同的是它接收聊天消(一種特定格式的數(shù)據(jù))作為輸入,返回的也是聊天消息.
-
文本嵌入模型: 文本嵌入模型接收文本作為輸入, 返回的是浮點(diǎn)數(shù)列表.
LangChain支持的三類模型,它們的使用場景不同,輸入和輸出不同,開發(fā)者需要根據(jù)項目需要選擇相應(yīng)。
2.1.1 LLMs (大語言模型)
LLMs使用場景最多,常用大模型的下載庫:https://huggingface.co/models:
接下來我們以GPT模型為例, 使用該類模型的組件:
- 第一步:安裝必備的工具包:langchain和openai
pip install openai==0.28
pip install langchain
注意,在使用openai模型之前,必須開通OpenAI API服務(wù),需要獲得API Token。
- 第二步:申請API Token
- 第三部:代碼實(shí)現(xiàn)
# 導(dǎo)入OpenAI模型
from langchain.llms import OpenAI
import os
os.environ["OPENAI_API_KEY"] = "你的OpenAI API token"
llm = OpenAI(model_name="text-davinci-003", n=2, temperature=0.3)
llm("給我講一個笑話")
# 答案:一個猴子去河里洗澡,洗完后他看見自己的影子,他覺得自己太瘦了,于是他又把頭放進(jìn)河里洗了一遍!# 使用generate方法可以同時接收多個輸入,并且返回token使用信息
llm.generate(["給我講一個故事", "給我講一個笑話"])
# 答案:# generations=[
# [Generation(text='\n\n一個叫瑪麗的小女孩,有一只叫毛毛的小貓。\n\n每天晚上,瑪麗都會和毛毛一起玩耍,一起跳舞,一起唱歌,一起玩游戲。\n\n有一天,瑪麗和毛毛一起去海邊玩,突然,毛毛被一只海鷗抓走了?,旣惙浅?#xff0c;她跑到海邊哭了起來,哭著喊著毛毛的',
# generation_info={'finish_reason': 'length', 'logprobs': None}),
# Generation(text='\n\n一個叫小明的男孩,他很喜歡探險。有一天,他和他的朋友們一起去森林里玩,突然,他發(fā)現(xiàn)一個洞穴,他非常好奇,于是他決定去看看洞穴里面到底有什么。\n\n他走進(jìn)洞穴,里面黑暗而又潮濕,他繼續(xù)前行,突然,他看到一只大老虎,它正在吃一只小兔子。',
# generation_info={'finish_reason': 'length', 'logprobs': None})],
# [Generation(text='\n\n兩個熊在森林里走,一個熊說:“嘿,你知道為什么樹林里沒有路嗎?”另一個熊回答:“不知道,為什么?”第一個熊說:“因?yàn)樗鼈兌荚诶@樹林跑!”', generation_info={'finish_reason': 'stop', 'logprobs': None}), Generation(text='\n\n兩個熊在森林里拔蘿卜,一個熊拔出一個蘿卜,另一個熊說:“你拔的太慢了,我拔的快一點(diǎn)!”',
# generation_info={'finish_reason': 'stop', 'logprobs': None})]
2.1.2 Chat Models (聊天模型)
聊天消息包含下面幾種類型,使用時需要按照約定傳入合適的值:
- AIMessage: 用來保存LLM的響應(yīng),以便在下次請求時把這些信息傳回給LLM.
- HumanMessage: 發(fā)送給LLMs的提示信息,比如“實(shí)現(xiàn)一個快速排序方法”.
- SystemMessage: 設(shè)置LLM模型的行為方式和目標(biāo)。你可以在這里給出具體的指示,比如“作為一個代碼專家”,或者“返回json格式”.
- ChatMessage: ChatMessage可以接收任意形式的值,但是在大多數(shù)時間,我們應(yīng)該使用上面的三種類型.
LangChain支持的常見聊天模型有:
模型 | 描述 |
---|---|
ChatOpenAI | OpenAI聊天模型 |
AzureChatOpenAI | Azure提供的OpenAI聊天模型 |
PromptLayerChatOpenAI | 基于OpenAI的提示模版平臺 |
舉例說明:
from langchain.chat_models import ChatOpenAI
from langchain.schema import (AIMessage,HumanMessage,SystemMessage
)
import os
os.environ["OPENAI_API_KEY"] = "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"chat = ChatOpenAI(temperature=0)messages = [SystemMessage(content="返回json object,不要純文本,按照每項參數(shù)拆分,不要說明和解釋信息"),HumanMessage(content="告訴我model Y汽車的尺寸參數(shù)")
]print(chat(messages))
# 答案:# content='{\n "車長": "4,750 mm",\n "車寬": "1,921 mm",\n "車高": "1,624 mm",\n "軸距": "2,890 mm",\n "最小離地間隙": "162 mm",\n "行李箱容積": "1,900 L"\n}' additional_kwargs={} example=False
2.1.3 提示模板
在上面的例子中,模型默認(rèn)是返回純文本結(jié)果的,如果需要返回json格式,需要不斷優(yōu)化SystemMessage。那么有什么簡單的方式快速讓模型返回想要的數(shù)據(jù)呢?就是提示模版。
提示模板就是把一些常見的提示整理成模板,用戶只需要修改模板中特定的詞語,就能快速準(zhǔn)確地告訴模型自己的需求。我們看個例子:
第一步:導(dǎo)入依賴
from langchain.chat_models import ChatOpenAI
from langchain.prompts import (ChatPromptTemplate,PromptTemplate,SystemMessagePromptTemplate,AIMessagePromptTemplate,HumanMessagePromptTemplate,
)
from langchain.schema import (AIMessage,HumanMessage,SystemMessage
)
第二步:實(shí)現(xiàn)提示模板:
system_template="你是一個把{input_language}翻譯成{output_language}的助手"
system_message_prompt = SystemMessagePromptTemplate.from_template(system_template)
human_template="{text}"
human_message_prompt = HumanMessagePromptTemplate.from_template(human_template)chat_prompt = ChatPromptTemplate.from_messages([system_message_prompt, human_message_prompt])
messages = chat_prompt.format_prompt(input_language="英語", output_language="漢語", text="I love programming.")print(messages)
#messages=[SystemMessage(content='你是一個把英語翻譯成漢語的助手', additional_kwargs={}), HumanMessage(content='I love programming.', additional_kwargs={}, example=False)]
chat = ChatOpenAI(temperature=0)print(chat(messages.to_messages()))# content='我喜歡編程。' additional_kwargs={} example=False
2.1.4 Embeddings Models(嵌入模型)
Embeddings Models特點(diǎn):將字符串作為輸入,返回一個浮動數(shù)的列表。在NLP中,Embedding的作用就是將數(shù)據(jù)進(jìn)行文本向量化。
Embeddings Models可以為文本創(chuàng)建向量映射,這樣就能在向量空間里去考慮文本,執(zhí)行諸如語義搜索之類的操作,比如說尋找相似的文本片段。
接下來我們以一個OpenAI文本嵌入模型的例子進(jìn)行說明:
from langchain.embeddings import OpenAIEmbeddings
open_embed = OpenAIEmbeddings()
text = "這是一個測試文檔。"query_result = open_embed.embed_query(text)
doc_result = open_embed.embed_documents([text])print(query_result)
# [-0.009422866627573967, 0.004315766040235758, 0.002380653750151396, ...]
上述代碼中,我們分別使用了兩種方法來進(jìn)行文本的向量表示,他們最大不同在于:embed_query()接收一個字符串的輸入,而embed_documents可以接收一組字符串。
LangChain集成的文本嵌入模型有:
- AzureOpenAI、Cohere、Hugging Face Hub、OpenAI、Llama-cpp、SentenceTransformers
2.2 Prompts
Prompt是指當(dāng)用戶輸入信息給模型時加入的提示,這個提示的形式可以是zero-shot或者few-shot等方式,目的是讓模型理解更為復(fù)雜的業(yè)務(wù)場景以便更好的解決問題。
提示模板:如果你有了一個起作用的提示,你可能想把它作為一個模板用于解決其他問題,LangChain就提供了PromptTemplates組件,它可以幫助你更方便的構(gòu)建提示。
zero-shot提示方式:
from langchain import PromptTemplate
from langchain.llms import OpenAItemplate = "我的鄰居姓{(diào)lastname},他生了個兒子,給他兒子起個名字"prompt = PromptTemplate(input_variables=["lastname"],template=template,
)prompt_text = prompt.format(lastname="王")
# result: 我的鄰居姓王,他生了個兒子,給他兒子起個名字# 調(diào)用OpenAI
llm = OpenAI(temperature=0.9)
print(llm(prompt_text))# 叫王愛慕。
few-shot提示方式:
from langchain import PromptTemplate, FewShotPromptTemplate
from langchain.llms import OpenAIexamples = [{"word": "開心", "antonym": "難過"},{"word": "高", "antonym": "矮"},
]example_template = """
單詞: {word}
反義詞: {antonym}\\n
"""example_prompt = PromptTemplate(input_variables=["word", "antonym"],template=example_template,
)few_shot_prompt = FewShotPromptTemplate(examples=examples,example_prompt=example_prompt,prefix="給出每個單詞的反義詞",suffix="單詞: {input}\\n反義詞:",input_variables=["input"],example_separator="\\n",
)prompt_text = few_shot_prompt.format(input="粗")
print(prompt_text)# 給出每個單詞的反義詞
# 單詞: 開心
# 反義詞: 難過# 單詞: 高
# 反義詞: 矮# 單詞: 粗
# 反義詞:# 調(diào)用OpenAI
llm = OpenAI(temperature=0.9)
print(llm(prompt_text))# 細(xì)
2.3 Chains(鏈)
在LangChain中,Chains描述了將LLM與其他組件結(jié)合起來完成一個應(yīng)用程序的過程.
針對上一小節(jié)的提示模版例子,zero-shot里面,我們可以用鏈來連接提示模版組件和模型,進(jìn)而可以實(shí)現(xiàn)代碼的更改:
from langchain import PromptTemplate
from langchain.llms import OpenAI
from langchain.chains import LLMChain
# 定義模板
template = "我的鄰居姓{(diào)lastname},他生了個兒子,給他兒子起個名字"prompt = PromptTemplate(input_variables=["lastname"],template=template,
)
llm = OpenAI(temperature=0.9)chain = LLMChain(llm = llm, prompt = prompt)
# 執(zhí)行鏈
print(chain.run("王"))
# 可以叫王子,也可以叫小王或者小王子等。。
如果你想將第一個模型輸出的結(jié)果,直接作為第二個模型的輸入,還可以使用LangChain的SimpleSequentialChain, 代碼如下:
from langchain import PromptTemplate
from langchain.llms import OpenAI
from langchain.chains import LLMChain, SimpleSequentialChain
# 創(chuàng)建第一條鏈
template = "我的鄰居姓{(diào)lastname},他生了個兒子,給他兒子起個名字"first_prompt = PromptTemplate(input_variables=["lastname"],template=template,
)
llm = OpenAI(temperature=0.9)first_chain = LLMChain(llm = llm, prompt = first_prompt)# 創(chuàng)建第二條鏈
second_prompt = PromptTemplate(input_variables=["child_name"],template="鄰居的兒子名字叫{child_name},給他起一個小名",
)second_chain = LLMChain(llm=llm, prompt=second_prompt)# 鏈接兩條鏈
overall_chain = SimpleSequentialChain(chains=[first_chain, second_chain], verbose=True)# 執(zhí)行鏈,只需要傳入第一個參數(shù)
catchphrase = overall_chain.run("王")
2.4 Agents (代理)
在 LangChain 中 Agents 的作用就是根據(jù)用戶的需求,來訪問一些第三方工具(比如:搜索引擎或者數(shù)據(jù)庫),進(jìn)而來解決相關(guān)需求問題。
為什么要借助第三方庫?
- 因?yàn)榇竽P碗m然非常強(qiáng)大,但是也具備一定的局限性,比如不能回答實(shí)時信息、處理數(shù)學(xué)邏輯問題仍然非常的初級等等。因此,可以借助第三方工具來輔助大模型的應(yīng)用。
幾個重要的概念:
-
代理:
- 負(fù)責(zé)控制整段代碼的邏輯和執(zhí)行,代理暴露了一個接口,用來接收用戶輸入,并返回AgentAction或AgentFinish。
- AgentAction決定使用哪個工具
- AgentFinish意味著代理的工作完成了,返回給用戶結(jié)果。
-
工具:
- 第三方服務(wù)的集成,比如谷歌、bing等等
-
工具包:
-
一些集成好了代理包,比如
create_csv_agent
可以使用模型解讀csv文件。 -
模型解決csv文件示例:
from langchain.agents import create_csv_agent from langchain.llms import OpenAI agent = create_csv_agent(OpenAI(temperature=0), 'data.csv', verbose=True) agent.run("一共有多少行數(shù)據(jù)?")
-
-
代理執(zhí)行器:
- 負(fù)責(zé)迭代運(yùn)行代理的循環(huán),直到滿足停止的標(biāo)準(zhǔn)。
現(xiàn)在我們實(shí)現(xiàn)一個使用代理的例子:假如我們在北京,想讓大語言模型告訴我們明天穿什么衣服,由于大語言模型不知道明天的天氣,我們借助于serpapi
來查詢天氣,并傳遞給模型,代碼如下:
from langchain.agents import load_tools
from langchain.agents import initialize_agent
from langchain.agents import AgentType
from langchain.llms import OpenAIllm = OpenAI(temperature=0)
tools = load_tools(["serpapi"], llm=llm)
agent = initialize_agent(tools, llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True)agent.run("明天在北京穿什么衣服合適?")
要注意的是,運(yùn)行這個示例需要申請
serpapi
token,并且設(shè)置到環(huán)境變量SERPAPI_API_KEY
,然后安裝依賴包google-search-results
LangChain支持的工具如下:
工具 | 描述 |
---|---|
Bing Search | Bing搜索 |
Google Search | Google搜索 |
Google Serper API | 一個從google搜索提取數(shù)據(jù)的API |
Python REPL | 執(zhí)行python代碼 |
Requests | 執(zhí)行python代碼 |
2.5 Memory
大模型本身不具備上下文的概念,它并不保存上次交互的內(nèi)容,ChatGPT之所以能夠和人正常溝通對話,因?yàn)樗M(jìn)行了一層封裝,將歷史記錄回傳給了模型。
因此 LangChain 也提供了Memory組件, Memory分為兩種類型:短期記憶和長期記憶。短期記憶一般指單一會話時傳遞數(shù)據(jù),長期記憶則是處理多個會話時獲取和更新信息。
目前的Memory組件只需要考慮ChatMessageHistory。舉例分析:
from langchain.memory import ChatMessageHistoryhistory = ChatMessageHistory()
history.add_user_message("在嗎?")
history.add_ai_message("有什么事?")print(history.messages)# [HumanMessage(content='在嗎?', additional_kwargs={}), AIMessage(content='有什么事?', additional_kwargs={})]
和OpenAI結(jié)合,直接使用ConversationChain
:
from langchain import ConversationChain
from langchain.llms import OpenAIllm = OpenAI(temperature=0)
conversation = ConversationChain(llm=llm, verbose=True)
conversation.predict(input="小明有1只貓")
conversation.predict(input="小剛有2只狗")
conversation.predict(input="小明和小剛一共有幾只寵物?")
如果要像chatGPT一樣,長期保存歷史消息,,可以使用messages_to_dict
方法
from langchain.memory import ChatMessageHistory
from langchain.schema import messages_from_dict, messages_to_dicthistory = ChatMessageHistory()
history.add_user_message("hi!")
history.add_ai_message("whats up?")dicts = messages_to_dict(history.messages)print(dicts)
# [{'type': 'human', 'data': {'content': 'hi!', 'additional_kwargs': {}}},
# {'type': 'ai', 'data': {'content': 'whats up?', 'additional_kwargs': {}}}]
# 讀取歷史消息
new_messages = messages_from_dict(dicts)print(new_messages)
#[HumanMessage(content='hi!', additional_kwargs={}),
# AIMessage(content='whats up?', additional_kwargs={})]
2.6 Indexes (索引)
Indexes組件的目的是讓LangChain具備處理文檔處理的能力,包括:文檔加載、檢索等。注意,這里的文檔不局限于txt、pdf等文本類內(nèi)容,還涵蓋email、區(qū)塊鏈、視頻等內(nèi)容。
Indexes組件主要包含類型:
- 文檔加載器
- 文本分割器
- VectorStores
- 檢索器
2.6.1 文檔加載器
文檔加載器主要基于Unstructured
包,Unstructured
是一個python包,可以把各種類型的文件轉(zhuǎn)換成文本。
文檔加載器使用起來很簡單,只需要引入相應(yīng)的loader工具:
from langchain.document_loaders import TextLoader
loader = TextLoader('../state_of_the_union.txt', encoding='utf8')
documents = loader.load()
LangChain支持的文檔加載器 (部分):
文檔加載器 | 描述 |
---|---|
CSV | CSV問價 |
JSON Files | 加載JSON文件 |
Jupyter Notebook | 加載notebook文件 |
Markdown | 加載markdown文件 |
Microsoft PowerPoint | 加載ppt文件 |
加載pdf文件 | |
Images | 加載圖片 |
File Directory | 加載目錄下所有文件 |
HTML | 網(wǎng)頁 |
2.6.2 文檔分割器
由于模型對輸入的字符長度有限制,我們在碰到很長的文本時,需要把文本分割成多個小的文本片段。
文本分割最簡單的方式是按照字符長度進(jìn)行分割,但是這會帶來很多問題,比如說如果文本是一段代碼,一個函數(shù)被分割到兩段之后就成了沒有意義的字符,所以整體的原則是把語義相關(guān)的文本片段放在一起。
LangChain中最基本的文本分割器是CharacterTextSplitter
,它按照指定的分隔符(默認(rèn)“\n\n”)進(jìn)行分割,并且考慮文本片段的最大長度。我們看個例子:
from langchain.text_splitter import CharacterTextSplitter# 初始字符串
state_of_the_union = "..."text_splitter = CharacterTextSplitter( separator = "\\n\\n",chunk_size = 1000,chunk_overlap = 200,length_function = len,
)texts = text_splitter.create_documents([state_of_the_union])
除了CharacterTextSplitter分割器,LangChain還支持其他文檔分割器 (部分):
文檔加載器 | 描述 |
---|---|
LatexTextSplitter | 沿著Latex標(biāo)題、標(biāo)題、枚舉等分割文本。 |
MarkdownTextSplitter | 沿著Markdown的標(biāo)題、代碼塊或水平規(guī)則來分割文本。 |
TokenTextSplitter | 根據(jù)openAI的token數(shù)進(jìn)行分割 |
PythonCodeTextSplitter | 沿著Python類和方法的定義分割文本。 |
2.6.3 VectorStores
VectorStores是一種特殊類型的數(shù)據(jù)庫,它的作用是存儲由嵌入創(chuàng)建的向量,提供相似查詢等功能。我們使用其中一個Chroma
組件作為例子:
from langchain.embeddings.openai import OpenAIEmbeddings
from langchain.text_splitter import CharacterTextSplitter
from langchain.vectorstores import Chroma# pku.txt內(nèi)容:<https://www.pku.edu.cn/about.html>
with open('./pku.txt') as f:state_of_the_union = f.read()
text_splitter = CharacterTextSplitter(chunk_size=100, chunk_overlap=0)
texts = text_splitter.split_text(state_of_the_union)embeddings = OpenAIEmbeddings()docsearch = Chroma.from_texts(texts, embeddings)query = "1937年北京大學(xué)發(fā)生了什么?"
docs = docsearch.similarity_search(query)
print(docs)
LangChain支持的VectorStore如下:
VectorStore | 描述 |
---|---|
Chroma | 一個開源嵌入式數(shù)據(jù)庫 |
ElasticSearch | ElasticSearch |
Milvus | 用于存儲、索引和管理由深度神經(jīng)網(wǎng)絡(luò)和其他機(jī)器學(xué)習(xí)(ML)模型產(chǎn)生的大量嵌入向量的數(shù)據(jù)庫 |
Redis | 基于redis的檢索器 |
FAISS | Facebook AI相似性搜索服務(wù) |
Pinecone | 一個具有廣泛功能的向量數(shù)據(jù)庫 |
2.6.4 檢索器
檢索器是一種便于模型查詢的存儲數(shù)據(jù)的方式,LangChain約定檢索器組件至少有一個方法get_relevant_texts
,這個方法接收查詢字符串,返回一組文檔。
from langchain.document_loaders import TextLoader
from langchain.text_splitter import CharacterTextSplitter
from langchain.vectorstores import FAISS
from langchain.embeddings import OpenAIEmbeddingsloader = TextLoader('../../../state_of_the_union.txt')
documents = loader.load()
text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
texts = text_splitter.split_documents(documents)
embeddings = OpenAIEmbeddings()db = FAISS.from_documents(texts, embeddings)
retriever = db.as_retriever()
docs = retriever.get_relevant_documents("what did he say about ketanji brown jackson")
LangChain支持的檢索器組件如下:
檢索器 | 介紹 |
---|---|
Azure Cognitive Search Retriever | Amazon ACS檢索服務(wù) |
ChatGPT Plugin Retriever | ChatGPT檢索插件 |
Databerry | Databerry檢索 |
ElasticSearch BM25 | ElasticSearch檢索器 |
Metal | Metal檢索器 |
Pinecone Hybrid Search | Pinecone檢索服務(wù) |
SVM Retriever | SVM檢索器 |
TF-IDF Retriever | TF-IDF檢索器 |
VectorStore Retriever | VectorStore檢索器 |
Vespa retriever | 一個支持結(jié)構(gòu)化文本和向量搜索的平臺 |
Weaviate Hybrid Search | 一個開源的向量搜索引擎 |
Wikipedia | 支持wikipedia內(nèi)容檢索 |
3 LangChain使用場景
- 個人助手
- 基于文檔的問答系統(tǒng)
- 聊天機(jī)器人
- Tabular數(shù)據(jù)查詢
- API交互
- 信息提取
- 文檔總結(jié)
小結(jié)
主要對LangChain框架基礎(chǔ)知識介紹,我們對LangChain有一個初步認(rèn)識,了解LangChain的使用場景。