為什么我們勸你棄用LangChain? 原創(chuàng)
作者 | Fabian Both
編輯 | 伊風(fēng)
為什么我們不再使用LangChain來構(gòu)建我們的AI代理AI agents?
在Octomind,我們使用多個(gè)大型語言模型(LLM)的AI代理來自動(dòng)創(chuàng)建和修復(fù)Playwright中的端到端測試。直到幾個(gè)月前,我們還在使用LangChain框架。
在這篇文章中,我將分享我們使用LangChain時(shí)遇到的困難,并解釋為什么用模塊化的構(gòu)建塊替換其僵化的高級(jí)抽象后,我們的代碼庫變得更簡潔,使我們的團(tuán)隊(duì)更快樂、更高效。
1.背景故事
我們在生產(chǎn)中使用LangChain超過12個(gè)月,從2023年初開始,然后在2024年將其移除。
2023年,LangChain似乎是我們的最佳選擇。它有一個(gè)令人印象深刻的組件和工具列表,并且其受歡迎程度迅速上升。它承諾“讓開發(fā)人員可以在一個(gè)下午內(nèi)從想法變?yōu)榭蛇\(yùn)行的代碼?!钡S著我們的需求變得更加復(fù)雜,問題開始浮現(xiàn),LangChain變成了摩擦而不是生產(chǎn)力的來源。
隨著其不靈活性開始顯現(xiàn),我們很快發(fā)現(xiàn)自己在深入研究LangChain內(nèi)部,以改進(jìn)我們系統(tǒng)的底層行為。但由于LangChain故意抽象了許多細(xì)節(jié),因此通常不容易或不可能編寫我們所需的底層代碼。
2.早期框架的危險(xiǎn)
AI和LLM是快速變化的領(lǐng)域,每周都有新概念和想法涌現(xiàn)。因此,當(dāng)一個(gè)框架如LangChain圍繞多個(gè)新興技術(shù)創(chuàng)建時(shí),設(shè)計(jì)能經(jīng)受時(shí)間考驗(yàn)的抽象是非常困難的。
我相信,如果我在他們創(chuàng)建LangChain時(shí)嘗試構(gòu)建一個(gè)類似的框架,我也不會(huì)做得更好。事后看錯(cuò)誤是很容易的,這篇文章的目的是不公平地批評LangChain的核心開發(fā)人員或其貢獻(xiàn)者。每個(gè)人都在盡力而為。
設(shè)計(jì)良好的抽象很難,即使需求是明確的。但當(dāng)你在這樣一個(gè)變化多端的狀態(tài)下建模組件(如代理)時(shí),僅對低級(jí)構(gòu)建塊使用抽象是更安全的方式。
3.LangChain抽象帶來的問題
在我們簡單的需求與其使用假設(shè)一致時(shí),LangChain最初是好用的。但其高度的抽象很快使我們的代碼變得難以理解與維護(hù)。當(dāng)我們的團(tuán)隊(duì)開始花費(fèi)與構(gòu)建功能一樣多的時(shí)間來理解和調(diào)試LangChain時(shí),這不是一個(gè)好兆頭。
LangChain的抽象方法的問題可以通過這個(gè)將英文單詞翻譯成意大利語的簡單示例來展示。
這是一個(gè)僅使用OpenAI包的Python示例:
圖片
這是簡單且易于理解的代碼,包含一個(gè)類和一個(gè)函數(shù)調(diào)用。其余是標(biāo)準(zhǔn)的Python。
讓我們對比一下LangChain的版本:
圖片
代碼大致相同,但相似之處僅此而已。
我們現(xiàn)在有三個(gè)類和四個(gè)函數(shù)調(diào)用。但最令人擔(dān)憂的是引入了三個(gè)新的抽象:
- 提示模板:提供給LLM的提示
- 輸出解析器:處理LLM的輸出
- 鏈:LangChain的“LCEL語法”覆蓋Python的 `|` 運(yùn)算符
所有LangChain所做的就是增加了代碼的復(fù)雜性而沒有明顯的好處。
這段代碼可能適用于早期階段的原型。但對于生產(chǎn)使用,每個(gè)組件都必須合理理解,以確保在實(shí)際使用條件下不會(huì)意外爆炸。你必須遵守給定的數(shù)據(jù)結(jié)構(gòu),并圍繞這些抽象設(shè)計(jì)你的應(yīng)用程序。
讓我們再看看一個(gè)Python中的抽象對比,這次是從API獲取JSON。
使用內(nèi)置的http包:
圖片
使用requests包:
圖片
勝利者顯而易見。這就是一個(gè)好的抽象的感覺。
當(dāng)然,這些是簡單的例子。但我的觀點(diǎn)是,好的抽象簡化了你的代碼并減少了理解它所需的認(rèn)知負(fù)擔(dān)。
LangChain試圖通過隱藏細(xì)節(jié),用更少的代碼做更多的事情來讓你的生活更輕松。但當(dāng)這以犧牲簡單性和靈活性為代價(jià)時(shí),抽象就失去了價(jià)值。
LangChain還習(xí)慣于在其他抽象之上使用抽象,因此你常常被迫以嵌套抽象的方式思考如何正確使用API。這不可避免地導(dǎo)致理解巨大的堆棧跟蹤并調(diào)試你沒有編寫的內(nèi)部框架代碼,而不是實(shí)現(xiàn)新功能。
4.LangChain對我們開發(fā)團(tuán)隊(duì)的影響
我們的應(yīng)用程序大量使用AI代理來執(zhí)行不同類型的任務(wù),例如測試用例發(fā)現(xiàn)、Playwright測試生成和自動(dòng)修復(fù)。
當(dāng)我們想從單一的順序代理架構(gòu)轉(zhuǎn)向更復(fù)雜的架構(gòu)時(shí),LangChain成了限制因素。例如,生成子代理并讓它們與原始代理交互,或者多個(gè)專家代理相互交互。
在另一個(gè)實(shí)例中,我們需要根據(jù)業(yè)務(wù)邏輯和LLM的輸出動(dòng)態(tài)更改我們的代理可以訪問的工具的可用性。但LangChain并沒有提供一種方法來外部觀察代理的狀態(tài),導(dǎo)致我們不得不縮小實(shí)現(xiàn)的范圍以適應(yīng)LangChain代理的有限功能。
一旦我們移除它,我們就不再需要將我們的需求轉(zhuǎn)換為LangChain適當(dāng)?shù)慕鉀Q方案。我們只需編碼即可。
因此,如果不是LangChain,你應(yīng)該使用什么框架?也許你根本不需要框架。
5.你需要一個(gè)框架來構(gòu)建AI應(yīng)用程序嗎?
LangChain在早期幫助了我們,因?yàn)樗峁┝薒LM功能,使我們能夠?qū)W⒂跇?gòu)建應(yīng)用程序。但事后看來,從長遠(yuǎn)來看,我們會(huì)更好地不用框架。
LangChain的長組件列表給人的印象是,構(gòu)建一個(gè)LLM驅(qū)動(dòng)的應(yīng)用程序很復(fù)雜。但大多數(shù)應(yīng)用程序需要的核心組件通常是:
- 一個(gè)用于LLM通信的客戶端
- 用于函數(shù)調(diào)用的函數(shù)/工具
- 一個(gè)用于RAG的向量數(shù)據(jù)庫
- 一個(gè)用于跟蹤、評估等的可觀察性平臺(tái)
其余的是圍繞這些組件的幫助工具(例如,用于向量數(shù)據(jù)庫的分塊和嵌入),或者是常規(guī)的應(yīng)用程序任務(wù),例如通過數(shù)據(jù)持久性和緩存管理文件和應(yīng)用程序狀態(tài)。
如果你在沒有框架的情況下開始你的AI開發(fā)之旅,是的,組建你自己的工具箱會(huì)花費(fèi)更長的時(shí)間,并且需要更多的前期學(xué)習(xí)和研究。但這是值得的時(shí)間投資,因?yàn)槟阏趯W(xué)習(xí)你將要操作的領(lǐng)域的基本知識(shí)。
在大多數(shù)情況下,你對LLM的使用將是簡單而直接的。你主要會(huì)編寫順序代碼,迭代提示,并改進(jìn)輸出的質(zhì)量和可預(yù)測性。大多數(shù)任務(wù)可以通過簡單的代碼和相對較少的外部包來完成。
即使使用代理,也不太可能做超出簡單的代理到代理通信,在預(yù)定的順序流程中處理代理狀態(tài)和它們的響應(yīng)。你不需要框架來實(shí)現(xiàn)這一點(diǎn)。
雖然代理領(lǐng)域正在迅速發(fā)展,有許多令人興奮的可能性和有趣的用例,但我們建議在代理使用模式穩(wěn)定下來之前,保持簡單。
6.使用構(gòu)建塊保持快速和精簡
假設(shè)你沒有向生產(chǎn)發(fā)布垃圾代碼,那么團(tuán)隊(duì)創(chuàng)新和迭代的速度是成功的最重要指標(biāo)。AI領(lǐng)域的許多開發(fā)是由實(shí)驗(yàn)和原型驅(qū)動(dòng)的。
但框架通常是為基于已建立的使用模式強(qiáng)制結(jié)構(gòu)而設(shè)計(jì)的——LLM驅(qū)動(dòng)的應(yīng)用程序尚未有這些模式。將新想法轉(zhuǎn)換為框架特定的代碼,限制了你的迭代速度。
構(gòu)建塊方法更喜歡使用簡單的低級(jí)代碼和精心選擇的外部包,保持你的架構(gòu)精簡,使開發(fā)人員可以將注意力集中在他們試圖解決的問題上。
構(gòu)建塊是指你覺得已經(jīng)全面理解且不太可能改變的簡單組件。例如,一個(gè)向量數(shù)據(jù)庫。它是一種已知類型的模塊化組件,具有一組基礎(chǔ)功能,因此可以很容易地被替換掉。你的代碼庫需要保持精簡和適應(yīng)性,以最大化你的學(xué)習(xí)速度和每個(gè)迭代周期的價(jià)值。
. . .
我希望我能恰當(dāng)?shù)睾凸降孛枋鑫覀冊谑褂肔angChain時(shí)遇到的挑戰(zhàn),以及為什么完全放棄框架對我們團(tuán)隊(duì)是非常有益的。
我們目前使用模塊化構(gòu)建塊和最小化抽象的策略使我們現(xiàn)在能夠更快地開發(fā),并減少了摩擦。
本文轉(zhuǎn)載自??51CTO技術(shù)棧??,作者:伊風(fēng)
