自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

LangChain居然不香了?一線程序員現(xiàn)身說(shuō)法,硬核博文剖析LLM應(yīng)用開(kāi)發(fā)原則

人工智能 新聞
最近,Hacker News熱榜上出現(xiàn)了一篇「聲討」LangChain的技術(shù)文章,得到了評(píng)論區(qū)網(wǎng)友的一致呼應(yīng)。去年還火遍L(zhǎng)LM圈的LangChain,為什么口碑逆轉(zhuǎn)了?

 2023年是屬于LLM初創(chuàng)公司的一年,也是屬于LangChain的一年。

這個(gè)發(fā)布于2022年10月的開(kāi)源框架可以支持開(kāi)發(fā)者構(gòu)建由LLM驅(qū)動(dòng)的應(yīng)用程序,目前依舊是社區(qū)中一種不可忽視的開(kāi)發(fā)范式。

圖片

更具體地說(shuō),基于LLM構(gòu)建應(yīng)用程序的過(guò)程有點(diǎn)像在搭積木。即使模型本身的能力已經(jīng)很強(qiáng)大了,我們依舊需要其他的組件和工具才能更好發(fā)揮其潛力。

比如聊天模型、提示模板、文本嵌入模型、文本分割器、文檔加載器、檢索器、向量存儲(chǔ)等,這些工具的不同的搭配組合能夠構(gòu)建出各種的應(yīng)用鏈,滿足RAG、Agent、存儲(chǔ)&索引、信息提取等不同的應(yīng)用需求。

圖片

舉個(gè)例子,你想用GPT-4開(kāi)發(fā)一個(gè)旅行顧問(wèn)機(jī)器人,為用戶提供行程方面的規(guī)劃和建議。如果只依靠GPT-4在訓(xùn)練時(shí)學(xué)到的知識(shí),沒(méi)有實(shí)時(shí)查詢最新的航班、酒店、景區(qū)信息,提供的建議就不可能準(zhǔn)確實(shí)用。

借助LangChain框架,這個(gè)機(jī)器人就能鏈接到各種API和外部數(shù)據(jù)庫(kù),并記住用戶的旅行偏好,甚至能根據(jù)用戶的對(duì)話歷史提供個(gè)性化建議。

這樣聽(tīng)起來(lái),LangChain是一個(gè)非常強(qiáng)大的工具,流行起來(lái)也是理所應(yīng)當(dāng)。

然而,最近一個(gè)技術(shù)團(tuán)隊(duì)的博文登上了HN熱榜,描述了他們從「入坑」LangChain到「幡然醒悟」,最終決定拋棄這個(gè)熱門(mén)框架的過(guò)程。

圖片

「為什么我們不再使用LangChain構(gòu)建AI agents——當(dāng)抽象弊大于利時(shí):在生產(chǎn)中使用LangChain的教訓(xùn)以及我們應(yīng)該做什么」

底下的評(píng)論也紛紛附和,表示這個(gè)框架有種「代碼糟糕」的感覺(jué),而且把使用LangChain描述為一條「充滿雷區(qū)的道路」。

圖片

「LangChain的抽象就是死亡的定義?!?/span>

圖片

從大受追捧到「人人喊打」,LangChain到底有什么樣的問(wèn)題?

問(wèn)題浮現(xiàn)

這個(gè)技術(shù)團(tuán)隊(duì)在生產(chǎn)中使用LangChain已經(jīng)超過(guò)12個(gè)月,開(kāi)始于2023年初。

當(dāng)時(shí),LangChain似乎是最佳選擇,因?yàn)樗鼡碛幸幌盗辛钊擞∠笊羁痰慕M件和工具,并且承諾開(kāi)發(fā)者「用一個(gè)下午將想法轉(zhuǎn)變?yōu)榭蓤?zhí)行的代碼」,流行程度飆升。

然而,隨著需求逐漸變得復(fù)雜,LangChain的不靈活性開(kāi)始顯現(xiàn)出來(lái),開(kāi)始阻礙生產(chǎn)力、成為摩擦的源頭。

團(tuán)隊(duì)不得不深入研究框架的內(nèi)部結(jié)構(gòu),以改善系統(tǒng)的底層行為。但因?yàn)長(zhǎng)angChain有意通過(guò)抽象屏蔽細(xì)節(jié),編寫(xiě)底層代碼的嘗試通常也不可行,或至少是十分復(fù)雜。

究其根源,作者認(rèn)為是LangChain的抽象程度過(guò)高。在開(kāi)發(fā)的初期階段,較為簡(jiǎn)單的需求與框架的假設(shè)相一致,因此配合得很好。

但高級(jí)抽象很快使之后的代碼變得難以理解、維護(hù),團(tuán)隊(duì)花費(fèi)在理解和調(diào)試LangChain上的時(shí)間越來(lái)越多,幾乎趕上了真正構(gòu)建功能所用的時(shí)間。

舉個(gè)具體的例子,上代碼:用OpenAI的包,將英語(yǔ)單詞翻譯為意大利語(yǔ)(沒(méi)錯(cuò),就是GPT-4o發(fā)布會(huì)demo的功能)

from openai import OpenAI

client = OpenAI(api_key="<your_api_key>")
text = "hello!"
language = "Italian"

messages = [
    {"role": "system", "content": "You are an expert translator"},
    {"role": "user", "content": f"Translate the following from English into {language}"},
    {"role": "user", "content": f"{text}"},
]

response = client.chat.completions.create(model="gpt-4o", messages=messages)
result = response.choices[0].message.content

這段代碼很好理解,包含一個(gè)OpenAI類(lèi)的實(shí)例client以及一個(gè)函數(shù)調(diào)用,其余都是標(biāo)準(zhǔn)的python代碼。

那如果用LangChain寫(xiě)呢?

from langchain_openai import ChatOpenAI
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate

os.environ["OPENAI_API_KEY"] = "<your_api_key>"
text = "hello!"
language = "Italian"


prompt_template = ChatPromptTemplate.from_messages(
    [("system", "You are an expert translator"),
     ("user", "Translate the following from English into {language}"),
     ("user", "{text}")]
)

parser = StrOutputParser()
chain = prompt_template | model | parser
result = chain.invoke({"language": language, "text": text})

涉及到三個(gè)類(lèi)、四個(gè)函數(shù)調(diào)用。但最令人擔(dān)憂的是,一個(gè)如此簡(jiǎn)單的任務(wù)需要引入三個(gè)抽象概念——

  • 提示模板(prompt template):為L(zhǎng)LM提供提示
  • 輸出解析器(output parser):處理LLM的輸出
  • 鏈(chain):LangChain的「LCEL語(yǔ)法」覆蓋了Python的「|」運(yùn)算符

這似乎徒增代碼復(fù)雜性,卻沒(méi)有任何額外的好處。

LangChain似乎更適合早期原型,但不適合實(shí)際的生產(chǎn)使用。

對(duì)于后者而言,開(kāi)發(fā)人員必須理解每一個(gè)組件,才能保證代碼不會(huì)在真實(shí)的使用場(chǎng)景中意外崩潰,但LangChain限制他們必須遵守給定的數(shù)據(jù)結(jié)構(gòu)和抽象概念,這無(wú)疑是額外的負(fù)擔(dān)。

再舉一個(gè)例子,這次是從API獲取JSON。

要使用Python內(nèi)置的http包可以這樣寫(xiě):

import http.client
import json

conn = http.client.HTTPSConnection("api.example.com")
conn.request("GET", "/data")
response = conn.getresponse()
data = json.loads(response.read().decode())
conn.close()

用requests包的寫(xiě)法則更加簡(jiǎn)潔:

import requests

response = requests.get("/data")
data = response.json()

這感覺(jué)上就是好的抽象。雖然是微不足道的小例子,但足以說(shuō)明一個(gè)觀點(diǎn)——好的抽象可以簡(jiǎn)化代碼,并能讓人快速理解。

LangChain的初衷是好的,它希望隱藏細(xì)節(jié),讓開(kāi)發(fā)人員用更少的代碼完成更多的功能。但如果代價(jià)是失去開(kāi)發(fā)的簡(jiǎn)潔和靈活,這種抽象就失去了價(jià)值。

此外,LangChain還習(xí)慣于「嵌套抽象」,在一個(gè)抽象概念之上再使用抽象。

這不僅讓學(xué)習(xí)API的過(guò)程更加復(fù)雜,開(kāi)發(fā)人員還不得不面對(duì)大量的堆棧跟蹤信息,并調(diào)試那些自己不熟悉的內(nèi)部框架代碼。

以這個(gè)技術(shù)團(tuán)隊(duì)自己的開(kāi)發(fā)為例,他們的應(yīng)用程序使用大量AI agent執(zhí)行不同類(lèi)型的任務(wù),比如測(cè)試用例發(fā)現(xiàn)、Playwright測(cè)試生成和自動(dòng)修復(fù)。

當(dāng)他們想要從只有單個(gè)順序代理的架構(gòu)轉(zhuǎn)向更復(fù)雜架構(gòu)時(shí),例如,生成sub-agnet并與原始agent交互,或者多個(gè)專(zhuān)業(yè)agent彼此交互,LangChain就成為了限制因素。

另一個(gè)示例中,需要根據(jù)業(yè)務(wù)邏輯和LLM的輸出,動(dòng)態(tài)更改agent可訪問(wèn)工具的可用性。但LangChain沒(méi)有提供從外部觀察agent狀態(tài)的方法,導(dǎo)致他們不得不縮小實(shí)現(xiàn)范圍,以適應(yīng)LangChain對(duì)agent可用功能的限制。

下決心刪除LangChain之后,技術(shù)團(tuán)隊(duì)仿佛得到了真正的「解脫」。不僅工作高效了,內(nèi)耗也少了。


一旦刪除了它,我們就可以不用先將需求轉(zhuǎn)化為適合LangChain的解決方案。我們只寫(xiě)代碼就可以了。


拋棄LangChain,下一個(gè)框架用什么?

事后,團(tuán)隊(duì)仔細(xì)反思復(fù)盤(pán)了這個(gè)問(wèn)題。他們認(rèn)為,長(zhǎng)期來(lái)看,不使用框架是更好的選擇。

LangChain提供了一長(zhǎng)串組件,讓人感覺(jué)LLM驅(qū)動(dòng)的應(yīng)用程序很復(fù)雜,但其實(shí)并不是。核心組件只有幾樣——

  • 用于LLM通信的客戶端
  • 函數(shù)或調(diào)用函數(shù)的工具
  • 用于RAG的向量數(shù)據(jù)庫(kù)
  • 用于追蹤、評(píng)估等功能的可觀察平臺(tái)

其余的組件,要么是以上核心組件的輔助(比如向量數(shù)據(jù)庫(kù)的分塊和嵌入),要么只是完成常規(guī)應(yīng)用程序的任務(wù)(比如使用數(shù)據(jù)持久化和緩存,以管理文件和應(yīng)用程序狀態(tài))。

如果不使用任何框架,毫無(wú)疑問(wèn)會(huì)增加前期用于學(xué)習(xí)、調(diào)研的工作量,開(kāi)發(fā)者需要更長(zhǎng)時(shí)間來(lái)組建自己的工具箱。

但「磨刀不誤砍柴工」,這些時(shí)間是值得的。在即將進(jìn)入的領(lǐng)域打下基礎(chǔ),這對(duì)你本人和應(yīng)用程序的未來(lái)都是良好的投資。

而且,很多情況下,使用LLM的流程都是非常簡(jiǎn)單直接的。開(kāi)發(fā)人員主要編寫(xiě)順序代碼、迭代提示,并提高輸出的質(zhì)量和可預(yù)測(cè)性。絕大多數(shù)任務(wù)都可以通過(guò)簡(jiǎn)潔的代碼和較小的外部包集合來(lái)實(shí)現(xiàn)。

即使用到了agent,也不一定需要框架才能實(shí)現(xiàn)。在處理業(yè)務(wù)邏輯時(shí),一般只需要在預(yù)定順序流中進(jìn)行agent之間的通信,處理它們的狀態(tài)和響應(yīng),超出這個(gè)范圍的工作內(nèi)容并不多。

雖然agent領(lǐng)域正在迅速發(fā)展,并帶來(lái)許多令人興奮的用例和可能性,但在代理的使用模式逐漸固化的過(guò)程中,我們還是應(yīng)該遵循簡(jiǎn)潔原則。

構(gòu)建基本塊,「輕裝疾行」

假設(shè)技術(shù)團(tuán)隊(duì)沒(méi)有在生產(chǎn)中混入垃圾代碼,那么創(chuàng)新和迭代的速度是衡量成功的最重要指標(biāo),因?yàn)锳I領(lǐng)域的許多發(fā)展都是由實(shí)驗(yàn)和原型設(shè)計(jì)驅(qū)動(dòng)的。

這意味著,代碼庫(kù)需要盡可能精簡(jiǎn)且適應(yīng)性強(qiáng),才能最大限度提升開(kāi)發(fā)人員的學(xué)習(xí)速度,每個(gè)迭代周期才能產(chǎn)生更多價(jià)值。

然而,「框架」的概念與此并不相容,它通常是人為設(shè)計(jì)出一種代碼結(jié)構(gòu),為了匹配根據(jù)既有的使用模式。

但LLM驅(qū)動(dòng)的應(yīng)用還在發(fā)展階段,沒(méi)有固定的使用模式。當(dāng)你不得不將創(chuàng)新的想法「翻譯」為特定于某個(gè)框架的代碼時(shí),就限制了迭代速度。

因此,相比于使用框架,更好的辦法是構(gòu)建基本塊(builing blocks),通過(guò)簡(jiǎn)潔的底層代碼和精心挑選的外部依賴包,保持架構(gòu)的精簡(jiǎn),從而讓開(kāi)發(fā)人員專(zhuān)注于真正需要解決的問(wèn)題。

「構(gòu)建基本塊」意味著簡(jiǎn)潔、可被完全理解,且不易變動(dòng)。最典型的例子就是矢量數(shù)據(jù)庫(kù),它屬于已知類(lèi)型的模塊化組件,只有基本功能,因此可以輕松被更換或取代。

因此,作者所在團(tuán)隊(duì)目前的策略是,完全不使用任何框架,用盡可能少的抽象進(jìn)行模塊化構(gòu)建,從而讓開(kāi)發(fā)過(guò)程更快、更流暢。

雖然LangChain的槽點(diǎn)如此之多,但作者還是選擇不過(guò)分苛責(zé)。某種程度上,這些缺陷都是無(wú)法避免的。

在AI和LLM這樣快速變化的領(lǐng)域,每周都會(huì)涌現(xiàn)新的概念和想法。因此,想要在如此多新型技術(shù)中間創(chuàng)建LangChain這樣的框架,并設(shè)計(jì)出經(jīng)得起時(shí)間考驗(yàn)的抽象,是非常困難的。

作者非常坦誠(chéng)地承認(rèn),如果當(dāng)初是自己去構(gòu)建LangChain,也不會(huì)做得比現(xiàn)在更好。當(dāng)一個(gè)「事后諸葛」指出錯(cuò)誤總是容易的,這篇博文的目的并不是批評(píng)任何LangChain的開(kāi)發(fā)人員或貢獻(xiàn)者,因?yàn)槊總€(gè)人都在盡力而為。

即使能很好地理解需求,構(gòu)建精心設(shè)計(jì)的抽象也是很困難的。因此在不斷變動(dòng)的條件下對(duì)組件(比如agent)進(jìn)行建模時(shí),更安全的選擇是僅對(duì)底層模塊使用抽象。

責(zé)任編輯:張燕妮 來(lái)源: 新智元
相關(guān)推薦

2019-01-03 11:26:07

碼農(nóng)大齡程序員工作

2020-03-04 15:56:16

碼農(nóng)程序員開(kāi)發(fā)

2011-05-26 09:01:32

2013-11-06 10:15:01

微軟Windows廣告

2024-03-07 09:15:57

2010-11-18 17:04:14

2017-12-07 14:38:06

2020-05-11 10:00:04

程序員技術(shù)管理

2011-12-19 14:26:46

云計(jì)算

2010-02-24 14:16:56

Visual Stud

2010-04-01 14:35:58

數(shù)據(jù)中心

2018-08-08 08:51:17

微軟谷歌面試

2018-07-17 14:05:49

2020-09-01 14:21:27

程序員薪水開(kāi)發(fā)

2009-05-27 09:31:41

2021-09-30 11:09:53

亞馬遜云科技ISV

2022-03-22 09:20:57

應(yīng)用線程池技術(shù)

2021-06-21 08:19:26

碼農(nóng)工作工程師

2023-09-19 12:41:51

LangChainLLM模型

2014-07-11 10:05:31

程序員開(kāi)發(fā)原則
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)