
掌握API建模:基本概念和實(shí)踐
用于衡量文本的相關(guān)性。這個(gè)也是 OpenAI API 能實(shí)現(xiàn)構(gòu)建自己知識(shí)庫(kù)的關(guān)鍵所在。
他相比 fine-tuning 最大的優(yōu)勢(shì)就是,不用進(jìn)行訓(xùn)練,并且可以實(shí)時(shí)添加新的內(nèi)容,而不用加一次新的內(nèi)容就訓(xùn)練一次,并且各方面成本要比 fine-tuning 低很多。
具體比較和選擇可以參考這個(gè)視頻:https://www.youtube.com/watch?v=9qq6HTr7Ocw
通過上面的必備概念大家應(yīng)該已經(jīng)可以對(duì) LangChain 有了一定的了解,但是可能還有有些懵。
這都是小問題,我相信看完后面的實(shí)戰(zhàn),你們就會(huì)徹底的理解上面的內(nèi)容,并且能感受到這個(gè)庫(kù)的真正強(qiáng)大之處。
因?yàn)槲覀?OpenAI API 進(jìn)階,所以我們后面的范例使用的 LLM 都是以O(shè)pen AI 為例,后面大家可以根據(jù)自己任務(wù)的需要換成自己需要的 LLM 模型即可。
當(dāng)然,在這篇文章的末尾,全部的全部代碼都會(huì)被保存為一個(gè) colab 的 ipynb 文件提供給大家來學(xué)習(xí)。
建議大家按順序去看每個(gè)例子,因?yàn)橄乱粋€(gè)例子會(huì)用到上一個(gè)例子里面的知識(shí)點(diǎn)。
當(dāng)然,如果有看不懂的也不用擔(dān)心,可以繼續(xù)往后看,第一次學(xué)習(xí)講究的是不求甚解。
第一個(gè)案例,我們就來個(gè)最簡(jiǎn)單的,用 LangChain 加載 OpenAI 的模型,并且完成一次問答。
在開始之前,我們需要先設(shè)置我們的 openai 的 key,這個(gè) key 可以在用戶管理里面創(chuàng)建,這里就不細(xì)說了。
import os
os.environ["OPENAI_API_KEY"] = '你的api key'
然后,我們進(jìn)行導(dǎo)入和執(zhí)行
from langchain.llms import OpenAI
llm = OpenAI(model_name="text-davinci-003",max_tokens=1024)
llm("怎么評(píng)價(jià)人工智能")
這時(shí),我們就可以看到他給我們的返回結(jié)果了,怎么樣,是不是很簡(jiǎn)單。
接下來,我們就來搞點(diǎn)有意思的。我們來讓我們的 OpenAI api 聯(lián)網(wǎng)搜索,并返回答案給我們。
這里我們需要借助 Serpapi 來進(jìn)行實(shí)現(xiàn),Serpapi 提供了 google 搜索的 api 接口。
首先需要我們到 Serpapi 官網(wǎng)上注冊(cè)一個(gè)用戶,https://serpapi.com/ 并復(fù)制他給我們生成 api key。
然后我們需要像上面的 openai api key 一樣設(shè)置到環(huán)境變量里面去。
import os
os.environ["OPENAI_API_KEY"] = '你的api key'
os.environ["SERPAPI_API_KEY"] = '你的api key'
然后,開始編寫我的代碼
from langchain.agents import load_tools
from langchain.agents import initialize_agent
from langchain.llms import OpenAI
from langchain.agents import AgentType
# 加載 OpenAI 模型
llm = OpenAI(temperature=0,max_tokens=2048)
# 加載 serpapi 工具
tools = load_tools(["serpapi"])
# 如果搜索完想在計(jì)算一下可以這么寫
# tools = load_tools(['serpapi', 'llm-math'])
# 如果搜索完想再讓他再用python的print做點(diǎn)簡(jiǎn)單的計(jì)算,可以這樣寫
# tools=load_tools(["serpapi","python_repl"])
# 工具加載后都需要初始化,verbose 參數(shù)為 True,會(huì)打印全部的執(zhí)行詳情
agent = initialize_agent(tools, llm, agent=AgentType.SELF_ASK_WITH_SEARCH, verbose=True)
# 運(yùn)行 agent
agent.run("What's the date today? What great events have taken place today in history?")
我們可以看到,他正確的返回了日期(有時(shí)差),并且返回了歷史上的今天。
在 chain 和 agent 對(duì)象上都會(huì)有 verbose
這個(gè)參數(shù),這個(gè)是個(gè)非常有用的參數(shù),開啟他后我們可以看到完整的 chain 執(zhí)行過程。
可以在上面返回的結(jié)果看到,他將我們的問題拆分成了幾個(gè)步驟,然后一步一步得到最終的答案。
關(guān)于agent type 幾個(gè)選項(xiàng)的含義(理解不了也不會(huì)影響下面的學(xué)習(xí),用多了自然理解了):
Search
和Lookup
工具, 前者用來搜, 后者尋找term, 舉例: Wipipedia
工具Google search API
工具reAct 介紹可以看這個(gè):https://arxiv.org/pdf/2210.03629.pdf
agent type 官方解釋:
https://python.langchain.com/en/latest/modules/agents/agents/agent_types.html?highlight=zero-shot-react-description
有一點(diǎn)要說明的是,這個(gè)
serpapi
貌似對(duì)中文不是很友好,所以提問的 prompt 建議使用英文。
當(dāng)然,官方已經(jīng)寫好了?ChatGPT Plugins
?的 agent,未來 chatgpt 能用啥插件,我們?cè)?api 里面也能用插件,想想都美滋滋。
不過目前只能使用不用授權(quán)的插件,期待未來官方解決這個(gè)。
感興趣的可以看這個(gè)文檔:https://python.langchain.com/en/latest/modules/agents/tools/examples/chatgpt_plugins.html
假如我們想要用 openai api 對(duì)一個(gè)段文本進(jìn)行總結(jié),我們通常的做法就是直接發(fā)給 api 讓他總結(jié)。但是如果文本超過了 api 最大的 token 限制就會(huì)報(bào)錯(cuò)。
這時(shí),我們一般會(huì)進(jìn)行對(duì)文章進(jìn)行分段,比如通過 tiktoken 計(jì)算并分割,然后將各段發(fā)送給 api 進(jìn)行總結(jié),最后將各段的總結(jié)再進(jìn)行一個(gè)全部的總結(jié)。
如果,你用是 LangChain,他很好的幫我們處理了這個(gè)過程,使得我們編寫代碼變的非常簡(jiǎn)單。
廢話不多說,直接上代碼。
from langchain.document_loaders import UnstructuredFileLoader
from langchain.chains.summarize import load_summarize_chain
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain import OpenAI
# 導(dǎo)入文本
loader = UnstructuredFileLoader("/content/sample_data/data/lg_test.txt")
# 將文本轉(zhuǎn)成 Document 對(duì)象
document = loader.load()
print(f'documents:{len(document)}')
# 初始化文本分割器
text_splitter = RecursiveCharacterTextSplitter(
chunk_size = 500,
chunk_overlap = 0
)
# 切分文本
split_documents = text_splitter.split_documents(document)
print(f'documents:{len(split_documents)}')
# 加載 llm 模型
llm = OpenAI(model_name="text-davinci-003", max_tokens=1500)
# 創(chuàng)建總結(jié)鏈
chain = load_summarize_chain(llm, chain_type="refine", verbose=True)
# 執(zhí)行總結(jié)鏈,(為了快速演示,只總結(jié)前5段)
chain.run(split_documents[:5])
首先我們對(duì)切割前和切割后的 document 個(gè)數(shù)進(jìn)行了打印,我們可以看到,切割前就是只有整篇的一個(gè) document,切割完成后,會(huì)把上面一個(gè) document 切成 317 個(gè) document。
最終輸出了對(duì)前 5 個(gè) document 的總結(jié)。
這里有幾個(gè)參數(shù)需要注意:
chunk_overlap
?參數(shù)這個(gè)是指切割后的每個(gè) document 里包含幾個(gè)上一個(gè) document 結(jié)尾的內(nèi)容,主要作用是為了增加每個(gè) document 的上下文關(guān)聯(lián)。比如,chunk_overlap=0
時(shí), 第一個(gè) document 為 aaaaaa,第二個(gè)為 bbbbbb;當(dāng) chunk_overlap=2
時(shí),第一個(gè) document 為 aaaaaa,第二個(gè)為 aabbbbbb。
不過,這個(gè)也不是絕對(duì)的,要看所使用的那個(gè)文本分割模型內(nèi)部的具體算法。
文本分割器可以參考這個(gè)文檔:https://python.langchain.com/en/latest/modules/indexes/text_splitters.html
chain_type
?參數(shù)這個(gè)參數(shù)主要控制了將 document 傳遞給 llm 模型的方式,一共有 4 種方式:
stuff
: 這種最簡(jiǎn)單粗暴,會(huì)把所有的 document 一次全部傳給 llm 模型進(jìn)行總結(jié)。如果document很多的話,勢(shì)必會(huì)報(bào)超出最大 token 限制的錯(cuò),所以總結(jié)文本的時(shí)候一般不會(huì)選中這個(gè)。
map_reduce
: 這個(gè)方式會(huì)先將每個(gè) document 進(jìn)行總結(jié),最后將所有 document 總結(jié)出的結(jié)果再進(jìn)行一次總結(jié)。
refine
: 這種方式會(huì)先總結(jié)第一個(gè) document,然后在將第一個(gè) document 總結(jié)出的內(nèi)容和第二個(gè) document 一起發(fā)給 llm 模型在進(jìn)行總結(jié),以此類推。這種方式的好處就是在總結(jié)后一個(gè) document 的時(shí)候,會(huì)帶著前一個(gè)的 document 進(jìn)行總結(jié),給需要總結(jié)的 document 添加了上下文,增加了總結(jié)內(nèi)容的連貫性。
map_rerank
: 這種一般不會(huì)用在總結(jié)的 chain 上,而是會(huì)用在問答的 chain 上,他其實(shí)是一種搜索答案的匹配方式。首先你要給出一個(gè)問題,他會(huì)根據(jù)問題給每個(gè) document 計(jì)算一個(gè)這個(gè) document 能回答這個(gè)問題的概率分?jǐn)?shù),然后找到分?jǐn)?shù)最高的那個(gè) document ,在通過把這個(gè) document 轉(zhuǎn)化為問題的 prompt 的一部分(問題+document)發(fā)送給 llm 模型,最后 llm 模型返回具體答案。
在這個(gè)例子中,我們會(huì)介紹如何從我們本地讀取多個(gè)文檔構(gòu)建知識(shí)庫(kù),并且使用 Openai API 在知識(shí)庫(kù)中進(jìn)行搜索并給出答案。
這個(gè)是個(gè)很有用的教程,比如可以很方便的做一個(gè)可以介紹公司業(yè)務(wù)的機(jī)器人,或是介紹一個(gè)產(chǎn)品的機(jī)器人。
from langchain.embeddings.openai import OpenAIEmbeddings
from langchain.vectorstores import Chroma
from langchain.text_splitter import CharacterTextSplitter
from langchain import OpenAI,VectorDBQA
from langchain.document_loaders import DirectoryLoader
from langchain.chains import RetrievalQA
# 加載文件夾中的所有txt類型的文件
loader = DirectoryLoader('/content/sample_data/data/', glob='**/*.txt')
# 將數(shù)據(jù)轉(zhuǎn)成 document 對(duì)象,每個(gè)文件會(huì)作為一個(gè) document
documents = loader.load()
# 初始化加載器
text_splitter = CharacterTextSplitter(chunk_size=100, chunk_overlap=0)
# 切割加載的 document
split_docs = text_splitter.split_documents(documents)
# 初始化 openai 的 embeddings 對(duì)象
embeddings = OpenAIEmbeddings()
# 將 document 通過 openai 的 embeddings 對(duì)象計(jì)算 embedding 向量信息并臨時(shí)存入 Chroma 向量數(shù)據(jù)庫(kù),用于后續(xù)匹配查詢
docsearch = Chroma.from_documents(split_docs, embeddings)
# 創(chuàng)建問答對(duì)象
qa = VectorDBQA.from_chain_type(llm=OpenAI(), chain_type="stuff", vectorstore=docsearch,return_source_documents=True)
# 進(jìn)行問答
result = qa({"query": "科大訊飛今年第一季度收入是多少?"})
print(result)
我們可以通過結(jié)果看到,他成功的從我們的給到的數(shù)據(jù)中獲取了正確的答案。
關(guān)于 Openai embeddings 詳細(xì)資料可以參看這個(gè)連接: https://platform.openai.com/docs/guides/embeddings
我們上個(gè)案例里面有一步是將 document 信息轉(zhuǎn)換成向量信息和embeddings的信息并臨時(shí)存入 Chroma 數(shù)據(jù)庫(kù)。
因?yàn)槭桥R時(shí)存入,所以當(dāng)我們上面的代碼執(zhí)行完成后,上面的向量化后的數(shù)據(jù)將會(huì)丟失。如果想下次使用,那么就還需要再計(jì)算一次embeddings,這肯定不是我們想要的。
那么,這個(gè)案例我們就來通過 Chroma 和 Pinecone 這兩個(gè)數(shù)據(jù)庫(kù)來講一下如何做向量數(shù)據(jù)持久化。
因?yàn)?LangChain 支持的數(shù)據(jù)庫(kù)有很多,所以這里就介紹兩個(gè)用的比較多的,更多的可以參看文檔:https://python.langchain.com/en/latest/modules/indexes/vectorstores/getting_started.html
chroma 是個(gè)本地的向量數(shù)據(jù)庫(kù),他提供的一個(gè)?persist_directory
?來設(shè)置持久化目錄進(jìn)行持久化。讀取時(shí),只需要調(diào)取?from_document
?方法加載即可。
from langchain.vectorstores import Chroma
# 持久化數(shù)據(jù)
docsearch = Chroma.from_documents(documents, embeddings, persist_directory="D:/vector_store")
docsearch.persist()
# 加載數(shù)據(jù)
docsearch = Chroma(persist_directory="D:/vector_store", embedding_function=embeddings)
Pinecone 是一個(gè)在線的向量數(shù)據(jù)庫(kù)。所以,我可以第一步依舊是注冊(cè),然后拿到對(duì)應(yīng)的 api key。https://app.pinecone.io/
免費(fèi)版如果索引14天不使用會(huì)被自動(dòng)清除。
然后創(chuàng)建我們的數(shù)據(jù)庫(kù):
Index Name:這個(gè)隨意
Dimensions:OpenAI 的 text-embedding-ada-002 模型為 OUTPUT DIMENSIONS 為 1536,所以我們這里填 1536
Metric:可以默認(rèn)為 cosine
Pod Type:想好就用 S1,想快就用 P1
持久化數(shù)據(jù)和加載數(shù)據(jù)代碼如下
# 持久化數(shù)據(jù)
docsearch = Pinecone.from_texts([t.page_content for t in split_docs], embeddings, index_name=index_name)
# 加載數(shù)據(jù)
docsearch = Pinecone.from_existing_index(index_name, embeddings)
一個(gè)簡(jiǎn)單從數(shù)據(jù)庫(kù)獲取 embeddings,并回答的代碼如下
from langchain.text_splitter import CharacterTextSplitter
from langchain.document_loaders import DirectoryLoader
from langchain.vectorstores import Chroma, Pinecone
from langchain.embeddings.openai import OpenAIEmbeddings
from langchain.llms import OpenAI
from langchain.chains.question_answering import load_qa_chain
import pinecone
# 初始化 pinecone
pinecone.init(
api_key="你的api key",
environment="你的Environment"
)
loader = DirectoryLoader('/content/sample_data/data/', glob='**/*.txt')
# 將數(shù)據(jù)轉(zhuǎn)成 document 對(duì)象,每個(gè)文件會(huì)作為一個(gè) document
documents = loader.load()
# 初始化加載器
text_splitter = CharacterTextSplitter(chunk_size=500, chunk_overlap=0)
# 切割加載的 document
split_docs = text_splitter.split_documents(documents)
index_name="liaokong-test"
# 持久化數(shù)據(jù)
# docsearch = Pinecone.from_texts([t.page_content for t in split_docs], embeddings, index_name=index_name)
# 加載數(shù)據(jù)
docsearch = Pinecone.from_existing_index(index_name,embeddings)
query = "科大訊飛今年第一季度收入是多少?"
docs = docsearch.similarity_search(query, include_metadata=True)
llm = OpenAI(temperature=0)
chain = load_qa_chain(llm, chain_type="stuff", verbose=True)
chain.run(input_documents=docs, question=query)
在 chatgpt api(也就是 GPT-3.5-Turbo)模型出來后,因錢少活好深受大家喜愛,所以 LangChain 也加入了專屬的鏈和模型,我們來跟著這個(gè)例子看下如何使用他。
import os
from langchain.document_loaders import YoutubeLoader
from langchain.embeddings.openai import OpenAIEmbeddings
from langchain.vectorstores import Chroma
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.chains import ChatVectorDBChain, ConversationalRetrievalChain
from langchain.chat_models import ChatOpenAI
from langchain.prompts.chat import (
ChatPromptTemplate,
SystemMessagePromptTemplate,
HumanMessagePromptTemplate
)
# 加載 youtube 頻道
loader = YoutubeLoader.from_youtube_channel('https://www.youtube.com/watch?v=Dj60HHy-Kqk')
# 將數(shù)據(jù)轉(zhuǎn)成 document
documents = loader.load()
# 初始化文本分割器
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=1000,
chunk_overlap=20
)
# 分割 youtube documents
documents = text_splitter.split_documents(documents)
# 初始化 openai embeddings
embeddings = OpenAIEmbeddings()
# 將數(shù)據(jù)存入向量存儲(chǔ)
vector_store = Chroma.from_documents(documents, embeddings)
# 通過向量存儲(chǔ)初始化檢索器
retriever = vector_store.as_retriever()
system_template = """
Use the following context to answer the user's question.
If you don't know the answer, say you don't, don't try to make it up. And answer in Chinese.
-----------
{context}
-----------
{chat_history}
"""
# 構(gòu)建初始 messages 列表,這里可以理解為是 openai 傳入的 messages 參數(shù)
messages = [
SystemMessagePromptTemplate.from_template(system_template),
HumanMessagePromptTemplate.from_template('{question}')
]
# 初始化 prompt 對(duì)象
prompt = ChatPromptTemplate.from_messages(messages)
# 初始化問答鏈
qa = ConversationalRetrievalChain.from_llm(ChatOpenAI(temperature=0.1,max_tokens=2048),retriever,qa_prompt=prompt)
chat_history = []
while True:
question = input('問題:')
# 開始發(fā)送問題 chat_history 為必須參數(shù),用于存儲(chǔ)對(duì)話歷史
result = qa({'question': question, 'chat_history': chat_history})
chat_history.append((question, result['answer']))
print(result['answer'])
我們可以看到他能很準(zhǔn)確的圍繞這個(gè)油管視頻進(jìn)行問答
使用流式回答也很方便
from langchain.callbacks.base import CallbackManager
from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler
chat = ChatOpenAI(streaming=True, callback_manager=CallbackManager([StreamingStdOutCallbackHandler()]), verbose=True, temperature=0)
resp = chat(chat_prompt_with_values.to_messages())
我們主要是結(jié)合使用 zapier
來實(shí)現(xiàn)將萬(wàn)種工具連接起來。
所以我們第一步依舊是需要申請(qǐng)賬號(hào)和他的自然語(yǔ)言 api key。https://zapier.com/l/natural-language-actions
他的 api key 雖然需要填寫信息申請(qǐng)。但是基本填入信息后,基本可以秒在郵箱里看到審核通過的郵件。
然后,我們通過右鍵里面的連接打開我們的api 配置頁(yè)面。我們點(diǎn)擊右側(cè)的?Manage Actions
?來配置我們要使用哪些應(yīng)用。
我在這里配置了 Gmail 讀取和發(fā)郵件的 action,并且所有字段都選的是通過 AI 猜。
配置好后,我們開始寫代碼
import os
os.environ["ZAPIER_NLA_API_KEY"] = ''
from langchain.llms import OpenAI
from langchain.agents import initialize_agent
from langchain.agents.agent_toolkits import ZapierToolkit
from langchain.utilities.zapier import ZapierNLAWrapper
llm = OpenAI(temperature=.3)
zapier = ZapierNLAWrapper()
toolkit = ZapierToolkit.from_zapier_nla_wrapper(zapier)
agent = initialize_agent(toolkit.get_tools(), llm, agent="zero-shot-react-description", verbose=True)
# 我們可以通過打印的方式看到我們都在 Zapier 里面配置了哪些可以用的工具
for tool in toolkit.get_tools():
print (tool.name)
print (tool.description)
print ("\n\n")
agent.run('請(qǐng)用中文總結(jié)最后一封"******@qq.com"發(fā)給我的郵件。并將總結(jié)發(fā)送給"******@qq.com"')
我們可以看到他成功讀取了******@qq.com
給他發(fā)送的最后一封郵件,并將總結(jié)的內(nèi)容又發(fā)送給了******@qq.com
這是我發(fā)送給 Gmail 的郵件。
這是他發(fā)送給 QQ 郵箱的郵件。
這只是個(gè)小例子,因?yàn)??zapier
?有數(shù)以千計(jì)的應(yīng)用,所以我們可以輕松結(jié)合 openai api 搭建自己的工作流。
因?yàn)樗擎準(zhǔn)降模运部梢园错樞蛞来稳?zhí)行多個(gè)
from langchain.llms import OpenAI
from langchain.chains import LLMChain
from langchain.prompts import PromptTemplate
from langchain.chains import SimpleSequentialChain
# location 鏈
llm = OpenAI(temperature=1)
template = """Your job is to come up with a classic dish from the area that the users suggests.
% USER LOCATION
{user_location}
YOUR RESPONSE:
"""
prompt_template = PromptTemplate(input_variables=["user_location"], template=template)
location_chain = LLMChain(llm=llm, prompt=prompt_template)
# meal 鏈
template = """Given a meal, give a short and simple recipe on how to make that dish at home.
% MEAL
{user_meal}
YOUR RESPONSE:
"""
prompt_template = PromptTemplate(input_variables=["user_meal"], template=template)
meal_chain = LLMChain(llm=llm, prompt=prompt_template)
# 通過 SimpleSequentialChain 串聯(lián)起來,第一個(gè)答案會(huì)被替換第二個(gè)中的user_meal,然后再進(jìn)行詢問
overall_chain = SimpleSequentialChain(chains=[location_chain, meal_chain], verbose=True)
review = overall_chain.run("Rome")
有時(shí)候我們希望輸出的內(nèi)容不是文本,而是像 json 那樣結(jié)構(gòu)化的數(shù)據(jù)。
from langchain.output_parsers import StructuredOutputParser, ResponseSchema
from langchain.prompts import PromptTemplate
from langchain.llms import OpenAI
llm = OpenAI(model_name="text-davinci-003")
# 告訴他我們生成的內(nèi)容需要哪些字段,每個(gè)字段類型式啥
response_schemas = [
ResponseSchema(name="bad_string", description="This a poorly formatted user input string"),
ResponseSchema(name="good_string", description="This is your response, a reformatted response")
]
# 初始化解析器
output_parser = StructuredOutputParser.from_response_schemas(response_schemas)
# 生成的格式提示符
# {
# "bad_string": string // This a poorly formatted user input string
# "good_string": string // This is your response, a reformatted response
#}
format_instructions = output_parser.get_format_instructions()
template = """
You will be given a poorly formatted string from a user.
Reformat it and make sure all the words are spelled correctly
{format_instructions}
% USER INPUT:
{user_input}
YOUR RESPONSE:
"""
# 講我們的格式描述嵌入到 prompt 中去,告訴 llm 我們需要他輸出什么樣格式的內(nèi)容
prompt = PromptTemplate(
input_variables=["user_input"],
partial_variables={"format_instructions": format_instructions},
template=template
)
promptValue = prompt.format(user_input="welcom to califonya!")
llm_output = llm(promptValue)
# 使用解析器進(jìn)行解析生成的內(nèi)容
output_parser.parse(llm_output)
from langchain.agents import initialize_agent, Tool
from langchain.agents import AgentType
from langchain.tools import BaseTool
from langchain.llms import OpenAI
from langchain import LLMMathChain, SerpAPIWrapper
llm = OpenAI(temperature=0)
# 初始化搜索鏈和計(jì)算鏈
search = SerpAPIWrapper()
llm_math_chain = LLMMathChain(llm=llm, verbose=True)
# 創(chuàng)建一個(gè)功能列表,指明這個(gè) agent 里面都有哪些可用工具,agent 執(zhí)行過程可以看必知概念里的 Agent 那張圖
tools = [
Tool(
name = "Search",
func=search.run,
description="useful for when you need to answer questions about current events"
),
Tool(
name="Calculator",
func=llm_math_chain.run,
description="useful for when you need to answer questions about math"
)
]
# 初始化 agent
agent = initialize_agent(tools, llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True)
# 執(zhí)行 agent
agent.run("Who is Leo DiCaprio's girlfriend? What is her current age raised to the 0.43 power?")
自定義工具里面有個(gè)比較有意思的地方,使用哪個(gè)工具的權(quán)重是靠 工具中描述內(nèi)容
來實(shí)現(xiàn)的,和我們之前編程靠數(shù)值來控制權(quán)重完全不同。
比如 Calculator 在描述里面寫到,如果你問關(guān)于數(shù)學(xué)的問題就用他這個(gè)工具。我們就可以在上面的執(zhí)行過程中看到,他在我們請(qǐng)求的 prompt 中數(shù)學(xué)的部分,就選用了Calculator 這個(gè)工具進(jìn)行計(jì)算。
上一個(gè)例子我們使用的是通過自定義一個(gè)列表來存儲(chǔ)對(duì)話的方式來保存歷史的。
當(dāng)然,你也可以使用自帶的 memory 對(duì)象來實(shí)現(xiàn)這一點(diǎn)。
from langchain.memory import ChatMessageHistory
from langchain.chat_models import ChatOpenAI
chat = ChatOpenAI(temperature=0)
# 初始化 MessageHistory 對(duì)象
history = ChatMessageHistory()
# 給 MessageHistory 對(duì)象添加對(duì)話內(nèi)容
history.add_ai_message("你好!")
history.add_user_message("中國(guó)的首都是哪里?")
# 執(zhí)行對(duì)話
ai_response = chat(history.messages)
print(ai_response)
使用 HuggingFace 模型之前,需要先設(shè)置環(huán)境變量
import os
os.environ['HUGGINGFACEHUB_API_TOKEN'] = ''
使用在線的 HuggingFace 模型
from langchain import PromptTemplate, HuggingFaceHub, LLMChain
template = """Question: {question}
Answer: Let's think step by step."""
prompt = PromptTemplate(template=template, input_variables=["question"])
llm = HuggingFaceHub(repo_id="google/flan-t5-xl", model_kwargs={"temperature":0, "max_length":64})
llm_chain = LLMChain(prompt=prompt, llm=llm)
question = "What NFL team won the Super Bowl in the year Justin Beiber was born?"
print(llm_chain.run(question))
將 HuggingFace 模型直接拉到本地使用
將模型拉到本地使用的好處:
所有的案例都基本已經(jīng)結(jié)束了,希望大家能通過這篇文章的學(xué)習(xí)有所收獲。這篇文章只是對(duì) LangChain 一個(gè)初級(jí)的講解,高級(jí)的功能希望大家繼續(xù)探索。
并且因?yàn)?LangChain 迭代極快,所以后面肯定會(huì)隨著AI繼續(xù)的發(fā)展,還會(huì)迭代出更好用的功能,所以我非??春眠@個(gè)開源庫(kù)。
希望大家能結(jié)合 LangChain 開發(fā)出更有創(chuàng)意的產(chǎn)品,而不僅僅只搞一堆各種一鍵搭建chatgpt聊天客戶端的那種產(chǎn)品。
這篇標(biāo)題后面加了個(gè) 01
是我希望這篇文章只是一個(gè)開始,后面如何出現(xiàn)了更好的技術(shù)我還是希望能繼續(xù)更新下去這個(gè)系列。
文章轉(zhuǎn)自微信公眾號(hào)@VFXinfo
掌握API建模:基本概念和實(shí)踐
程序員常用的API接口管理工具有哪些?
簡(jiǎn)化API縮寫:應(yīng)用程序編程接口終極指南
如何為你的項(xiàng)目挑選最佳API?完整選擇流程解讀
應(yīng)用程序開發(fā)蓬勃發(fā)展的必備開放API
.NET Core Web APi類庫(kù)如何內(nèi)嵌運(yùn)行和.NET Core Web API 中的異常處理
.NET Core Web API + Vue By Linux and Windows 部署方案知識(shí)點(diǎn)總結(jié)
優(yōu)化利潤(rùn):計(jì)算并報(bào)告OpenAI支持的API的COGS
用于集成大型語(yǔ)言模型的LLM API
對(duì)比大模型API的內(nèi)容創(chuàng)意新穎性、情感共鳴力、商業(yè)轉(zhuǎn)化潛力
一鍵對(duì)比試用API 限時(shí)免費(fèi)