langchain 基于 0.0.109 版本
一個(gè)基于LLMs的應(yīng)用程序開發(fā)框架, 通過可組合性來使用LLM構(gòu)建應(yīng)用程序. 其重點(diǎn)在于"可組合性"
大型語言模型 (LLM) 正在作為一種變革性技術(shù)出現(xiàn),使開發(fā)人員能夠構(gòu)建他們以前無法構(gòu)建的應(yīng)用程序。但是單獨(dú)使用這些 LLM 通常不足以創(chuàng)建真正強(qiáng)大的應(yīng)用程序,當(dāng)可以將它們與其他計(jì)算或知識(shí)來源相結(jié)合時(shí),就有真的價(jià)值了。LangChain 旨在協(xié)助開發(fā)這些類型的應(yīng)用程序.
其主要包含六個(gè)部分:
- LLMs和prompt, 對(duì)所有大模型的通用交互接口, 以及prompt管理,優(yōu)化等等
- chains, 一系列的調(diào)用(LLMs或者其他, 如網(wǎng)絡(luò), 操作系統(tǒng)), chains提供了標(biāo)準(zhǔn)的接口和設(shè)置來組合這些調(diào)用.
- data augmented generation 基于特定數(shù)據(jù)的內(nèi)容生成, 一種特殊的chain, 提供了一種能力: 先從外部的源獲取信息, 然后喂給LLMs
- agents, 代理, 非常重要的一環(huán), 關(guān)于對(duì)LLMs做何種action, 如何做
- memory 標(biāo)準(zhǔn)的接口, 在chains/call之間保存狀態(tài)
- Evaluation 提供了一些prompts/chains來利用模型來評(píng)估自身
prompt templates
ChatGPT 提供了通過 prompts 來進(jìn)行提示的方法,也就是在發(fā)起請(qǐng)求時(shí),可以帶上一段信息。由于是一個(gè)聊天接口,因此可以包含多個(gè)聊天的內(nèi)容。其中包括來自系統(tǒng)的提示:例如用來描述一下 ChatGPT 現(xiàn)在是什么角色,應(yīng)該具有什么樣的語言風(fēng)格等。另外還可以包含一些用戶的歷史聊天記錄,就像背景知識(shí)一類的,都可以作為用戶的輸入帶進(jìn)去,這樣可以使得 ChatGPT 在本次聊天中具有了領(lǐng)域知識(shí)與上下文信息。通過這種 prompts 的方式,可以對(duì) ChatGPT 有一定的定制能力,并使用其大模型的自然語言能力來組織回答信息。
prompt template是簡(jiǎn)化和用戶的交互, 用戶提出核心問題, template 渲染問題, 增加上下文信息, 歷史聊天信息, 背景知識(shí)等等.
chains
簡(jiǎn)單應(yīng)用可能對(duì)LLM進(jìn)行一次調(diào)用即可, 而復(fù)雜應(yīng)用往往需要串聯(lián)LLMs(相互連接或者和其他的專家系統(tǒng)). langchain為此提供了一套標(biāo)準(zhǔn)的接口和通用的實(shí)現(xiàn).
chain還細(xì)分為兩類: 通用任務(wù)chain 和 專有工具chain ,前者更多用來組織任務(wù)順序, 后者則專注在對(duì)某個(gè)工具的調(diào)用上.
- LLMChain: 簡(jiǎn)單接受template和用戶輸入, 調(diào)用LLM, 返回輸出
- SequentialChain: 組合chains, 發(fā)起一系列且有順序的調(diào)用請(qǐng)求
SimpleSequentialChain(chains=[chain, chain_two], verbose=True) - BashChain: 使用LLMs 以及 調(diào)用bash命令
- LLMRequestsChain: 發(fā)起調(diào)用, 之后將結(jié)果輸送給后來的chain.
- .........
- 自定義chain:
- 繼承Chain
- 實(shí)現(xiàn)input_keys和output_keys (前者接收先前chains的輸出, 后者給到后來chains作為輸入)
- 補(bǔ)全調(diào)用實(shí)現(xiàn)_call ( _call是chain運(yùn)行會(huì)調(diào)用的方法)
chain可以很簡(jiǎn)單地理解為 過程的抽象, chains的可組合性, 就是過程的組合.
agents
use LLM to determine which actions to take and in what order. An action can either be using a tool and observing its output, or returning to the user.
搭配上能理解用戶輸入的大模型, agents接受大模型輸出的指令, 可以打造強(qiáng)大的個(gè)人助理程序.
concepts
Tool : A function that performs a specific duty. This can be things like: Google Search, Database lookup, Python REPL, other chains. The interface for a tool is currently a function that is expected to have a string as an input, with a string as an output.
工具, 可以執(zhí)行某種特定任務(wù). 當(dāng)下, 可以理解為一個(gè) string => string的函數(shù). 內(nèi)置的工具:
https://langchain.readthedocs.io/en/latest/modules/agents/tools.html
可以: 發(fā)起調(diào)用, http請(qǐng)求, 搜索內(nèi)容, 執(zhí)行代碼(python), etc.
LLM : The language model powering the agent.
Agent : The agent to use. This should be a string that references a support agent class. Because this notebook focuses on the simplest, highest level API, this only covers using the standard supported agents. If you want to implement a custom agent, see the documentation for custom agents (coming soon).
用來調(diào)用工具的代理, 如果標(biāo)準(zhǔn)庫里沒有合適的工具代理, 可以自定義.
內(nèi)置代理類型:
- zero-shot-react-description 根據(jù)工具的描述, 和請(qǐng)求的string 來決定使用哪個(gè)工具
- react-docstore 使用react框架, 和docstore交互, 使用
Search和Lookup工具, 前者用來搜, 后者尋找term, 舉例: Wipipedia工具 - self-ask-with-search 此代理只使用一個(gè)工具: Intermediate Answer, 它會(huì)為問題尋找事實(shí)答案(指的非gpt生成的答案, 而是在網(wǎng)絡(luò)中,文本中已存在的), 如
Google search API工具 - conversational-react-description 為會(huì)話設(shè)置而設(shè)計(jì)的代理, 它的prompt會(huì)被設(shè)計(jì)的具有會(huì)話性, 且還是會(huì)使用 ReAct框架來決定使用來個(gè)工具, 并且將過往的會(huì)話交互存入內(nèi)存.
https://langchain.readthedocs.io/en/latest/modules/agents/agents.html
舉例
與向量數(shù)據(jù)庫交互
希望應(yīng)用程序, 在使用LLM的過程中, 和向量數(shù)據(jù)庫交互(其實(shí), 不用langchain庫, 自己編寫很簡(jiǎn)單的代碼就可以做到) 只是langchain庫在多數(shù)向量庫之上, 包裝了一層統(tǒng)一的交互接口.
https://langchain.readthedocs.io/en/latest/modules/agents/examples/agent_vectorstore.html
如下代碼所示 , 兩個(gè)tool被創(chuàng)建, 組合成工具包, 兩個(gè)工具, 分別是"SOU的qa"和 "Ruff的qa", 他們會(huì)分別閱讀SOU和Ruff網(wǎng)站的內(nèi)容, 并且調(diào)用LLM的向量接口, 生成向量, 存于本地?cái)?shù)據(jù)庫. 然后使用特定種類的agent作為某種路由, 可以按工具描述使用他們.
tools = [
Tool(
name = "State of Union QA System",
func=state_of_union.run,
description="useful for when you need to answer questions about the most recent state of the union address. Input should be a fully formed question."
),
Tool(
name = "Ruff QA System",
func=ruff.run,
description="useful for when you need to answer questions about ruff (a python linter). Input should be a fully formed question."
),
]
agent = initialize_agent(tools, llm, agent="zero-shot-react-description", verbose=True)
agent.run("What did biden say about ketanji brown jackson is the state of the union address?")
先搜再問 - data agumented generation
對(duì)于某些大模型沒有的信息或者知識(shí), 如果要補(bǔ)充這些信息, 需要重新訓(xùn)練模型, 成本比較高, 但是可以通過prompt的方式給到它, langchain為了方便上層開發(fā)應(yīng)用, 設(shè)計(jì)了self-ask-with-search代理, 即先到某個(gè)知識(shí)庫去獲取相關(guān)的信息和知識(shí), 然后利用LLM來理解這些知識(shí)和信息,然后回答用戶的問題.
memory
chain和agent是無狀態(tài)的, LLM模型也是, 所以需要prompt來進(jìn)行歷史提示.
Chains and Agents are stateless, meaning that they treat each incoming query independently (as are the underlying LLMs and chat models).
memory模塊提供了兩種能力:
- 模塊化管理和操作先前的對(duì)話的工具
- 將這些工具集成到chain里的設(shè)施
示例
https://langchain.readthedocs.io/en/latest/modules/memory/types/buffer.html
從示例中可以看出, langchain將對(duì)話保存在模塊化的memory中, 并且在predict的時(shí)候, 自動(dòng)帶上歷史會(huì)話, 作為prompt.
總結(jié)
關(guān)于agent和chains的差異,尤其是utils chain
agent是關(guān)于對(duì)LLM做何種action, 怎么做action, 在于挑選工具. chain重點(diǎn)是對(duì)輸入做處理 , 并且組織各個(gè)過程的順序.
data augemented generation
LLMs是基于大量非結(jié)構(gòu)化的語料訓(xùn)練的, 所以對(duì)通用的nlp任務(wù)有很好的的效果, 然而很多時(shí)候, 我們需要的不是在利用通用數(shù)據(jù)來生成結(jié)果, 而是基于特定的數(shù)據(jù)來產(chǎn)生結(jié)果.
- Summarization of a specific piece of text (a website, a private document, etc.)
- Question answering over a specific piece of text (a website, a private document, etc.)
- Question answering over multiple pieces of text (multiple websites, multiple private documents, etc.)
- Using the results of some external call to an API (results from a SQL query, etc.)
即, 不希望模型僅僅通過其訓(xùn)練的數(shù)據(jù)來生成文本, 而要把某些外部的數(shù)據(jù)也結(jié)合進(jìn)去, 所以步驟可以拆解為兩步:
- fetching: 取回
- user provided
- document retrival
- api querying
- augmenting: 傳遞給LLM
fetching
在fetching過程中, 比較重要的是取回的文檔不能太大, 因?yàn)槟壳暗哪P投紝?duì)輸入的長度有限制, 所以 langchain提供了各種工具來split文檔成一片一片, 并且控制每片中的內(nèi)容重疊(保持上下文). 另外一個(gè)是, 不能取回太多的文檔, 最好只選取和問題相關(guān)的文檔, 即相關(guān)度要高, 有比較多的方式來做這件事, 當(dāng)下比較流行的是:
在語義搜索和Q&A系統(tǒng)中, 將語料的doc切分成chunk, 將chunk向量化, 然后存儲(chǔ), 之后用戶的輸入到來后, 首先進(jìn)行向量化的相關(guān)性搜索, 將搜索的結(jié)果以及用戶數(shù)據(jù)一起作為prompt作為輸入喂給LLM, 這是目前常見的做法, 但業(yè)界也在考慮轉(zhuǎn)為大模型設(shè)計(jì)的數(shù)據(jù)結(jié)構(gòu)和索引技術(shù), 詳見 LlamaIndex
幾個(gè)開源項(xiàng)目:
- https://github.com/arc53/docsgpt
-
https://github.com/GanymedeNil/document.ai
都是用的 data augement generation 來做的.
LlamaIndex -> 專注在數(shù)據(jù)層
對(duì)于私有數(shù)據(jù), 受限于LLM的無狀態(tài), 訓(xùn)練代價(jià)大, token個(gè)數(shù)限制, 甚至fine-tune的接口不開放等等, 對(duì)于私有數(shù)據(jù)上的內(nèi)容生成, 現(xiàn)在常見的做法是embedding文檔, 先搜后問, 也即上文提到的langchain的一個(gè)核心模塊: data augementing generation. 與此同時(shí), LlamaIndex在考慮為LLM設(shè)計(jì)的數(shù)據(jù)結(jié)構(gòu)和索引.
現(xiàn)在想要增強(qiáng)LLM在私有數(shù)據(jù)上的表現(xiàn)能力, 有兩種方式: fine-tune 和 in-context learning (即將上下文放入輸入的prompt中) .
為了更好地(高效,便宜)進(jìn)行data augmentation, 想要解決: 數(shù)據(jù)攝取和索引. LlamaIndex提供的工具:
- data connectors : 連接到數(shù)據(jù)源, 和不同的數(shù)據(jù)格式
- 利用LLM來給結(jié)構(gòu)化,非結(jié)構(gòu)化數(shù)據(jù)做索引. 簡(jiǎn)化了in-context learning過程中繁瑣的細(xì)節(jié): prompt長度, 文本拆分,etc
- 用戶優(yōu)化的索引query 接口 和 模型調(diào)用接口的結(jié)合
- 一個(gè)權(quán)衡成本和性能的全面的工具集
不同于langchain的全面開發(fā), 均衡發(fā)展策略, llama-index更像是專注在data augmentation generation, 圍繞它來開發(fā)周邊對(duì)應(yīng)的能力. 即豐富的數(shù)據(jù)源和數(shù)據(jù)格式的讀取器, 統(tǒng)一的index表示, 花式的index讀取, 寫入.
smart agents -> 專注在agents
Build natural language agents that connect to your data, talk to APIs, and solve complex problems.
和Llama-index類似, 不過專注在agents, 準(zhǔn)備構(gòu)建一個(gè)agents market, 在大模型之上構(gòu)建一個(gè)軟件系統(tǒng), 可以和其它系統(tǒng)交互, 完成復(fù)雜任務(wù).
目前資料較少
總結(jié)
GPT Index vs LangChain 的區(qū)別:
根本上是因?yàn)?大語言模型支持的context有限,比如ChatGPT的Davinci model只有 4096 tokens,對(duì)應(yīng)中文,可能只有2000
“A big limitation of LLMs is context size (e.g. Davinci's limit is 4096 tokens. Large, but not infinite).”
如果單純的跟GPT模型對(duì)接,那直接用 GPT 的 Davinci 模型直接對(duì)話就行;ChatGPT 只是 GPT 其中一個(gè) chat-model 而已
如果需要借助GPT語言模型+私有數(shù)據(jù),那就需要突破 4096 tokens 的限制,也就是 feed "knowledge" to LLMs,所以需要用上 GPT Index
與此同時(shí),在用 ChatGPT 時(shí),單次輸入的 prompt 也有限制,所以 GPT Index 可以簡(jiǎn)化這個(gè) feed 喂數(shù)據(jù)的過程。
- 如果 GPT 直接就滿足要求,可以用 GPT Index,就夠了。
那為什么還有用上 LangChain 呢?就是因?yàn)?LLMs 不止 OpenAI 的 GPT 模型,LangChain 可以對(duì)接多種模型,即 Lang
而 Chain 的意思就是把多個(gè) LLM 調(diào)用,而且是調(diào)用序列,標(biāo)準(zhǔn)化,集成等工作,最后串起來
- LangChain 還做了很多框架層面的工作:Prompt、Loader、Chain、Agent、Memory
比如 Loader 部分,它也推出了跟 https://llamahub.ai 類似的 https://github.com/hwchase17/langchain-hub,用來集成外部數(shù)據(jù)。區(qū)別就在于 GPT Index 能用的,LangChain 都能用,LangChain 的 Loader 能加載其他語言模型,是 GPT 的超集。
再比如 Memory 部分,就是用來持久化 內(nèi)存 狀態(tài),所以能實(shí)現(xiàn) ChatGPT 聊天機(jī)器人這樣的功能,記住以前的交互非常重要,無論是短期的還是長期的。
Agent 部分就更有趣了,可以根據(jù)用戶輸入,再來決定調(diào)用這些工具中的哪一個(gè),比如 LangChain 的 GPT+WolframAlpha 示例,甚至還可以根據(jù)輸入去調(diào)用 WolframAlpha,解答你的數(shù)學(xué)提問,彌補(bǔ)GPT 數(shù)學(xué)弱智的問題。
當(dāng)然,它也可以去做 Google 搜索、數(shù)據(jù)庫查找 等操作,通過需要跟 Document Loader 結(jié)合起來用,你可以找到類似 https://llamahub.ai/l/file-pdf 等不少例子。
應(yīng)用
- chatpdf : 和書籍對(duì)話, 也是類似llama index的做法, 將內(nèi)容embedding, 利用LLM進(jìn)行提煉總結(jié).
- chatexcel: https://chatexcel.com/convert, 上傳excel, 利用自然語言描述需求, 自動(dòng)改表, 總結(jié)內(nèi)容. (私人表格助手)