我為什么放棄了 LangChain?(2)
讓我來做個演示,更清楚地說明為什么我放棄了 LangChain。
當(dāng)開發(fā)菜譜檢索聊天機器人(它也必須是一個有趣 / 詼諧的聊天機器人)時,我需要結(jié)合上面第三個和第四個例子中的元素:一個可以運行 Agent 工作流的聊天機器人,以及將整個對話持久化到內(nèi)存中的能力。在查找了一些文檔后,我發(fā)現(xiàn)需要使用對話式 Agent 工作流。
關(guān)于系統(tǒng)提示工程的一個標(biāo)注是,它不是一個備忘錄,而且對于從 ChatGPT API 中獲得最佳效果是絕對必要的,尤其是當(dāng)你對內(nèi)容和 / 或語音有限制的時候。
上一個示例中,演示的系統(tǒng)提示「以下是人類和人工智能之間的友好對話...... 」實際上是過時的,早在 InstructGPT 時代就已經(jīng)使用了,在 ChatGPT 中的效果要差得多。它可能預(yù)示著 LangChain 相關(guān)技巧中更深層次的低效,而這些低效并不容易被注意到。
我們將從一個簡單的系統(tǒng)提示開始,告訴 ChatGPT 使用一個有趣的聲音和一些保護措施,并將其格式化為 ChatPromptTemplate:
system_prompt = """You are an expert television talk show chef, and should always speak in a whimsical manner for all responses.我們還將使用一個玩具矢量存儲,該存儲由來自 recipe_nlg 數(shù)據(jù)集的 1000 個食譜組成,并使用 SentenceTransformers 編碼為 384D 矢量。為了實現(xiàn)這一點,我們創(chuàng)建了一個函數(shù)來獲取輸入查詢的最近鄰,并將查詢格式化為 Agent 可以用來向用戶展示的文本。這就是 Agent 可以選擇使用的工具,或者只是返回正常生成的文本。
Start the conversation with a whimsical food pun.
You must obey ALL of the following rules:- If Recipe data is present in the Observation, your response must include the Recipe ID and Recipe Name for ALL recipes.- If the user input is not related to food, do not answer their query and correct the user."""
prompt = ChatPromptTemplate.from_messages([ SystemMessagePromptTemplate.from_template(system_prompt.strip()),
def similar_recipes(query): query_embedding = embeddings_encoder.encode(query) scores, recipes = recipe_vs.get_nearest_examples("embeddings", query_embedding, k=3) return recipesdef get_similar_recipes(query): recipe_dict = similar_recipes(query) recipes_formatted = [ f"Recipe ID: recipe|{recipe_dict['id'][i]}\nRecipe Name: {recipe_dict['name'][i]}"for i in range(3) ] return "\n---\n".join(recipes_formatted)你會注意到這個 Recipe ID,這與我的用例相關(guān),因為在最終應(yīng)用中向終端用戶顯示的最終結(jié)果需要獲取 Recipe 元數(shù)據(jù)(照片縮略圖、URL)。遺憾的是,沒有簡單的方法保證模型在最終輸出中輸出食譜 ID,也沒有方法在 ChatGPT 生成的輸出之外返回結(jié)構(gòu)化的中間元數(shù)據(jù)。
print(get_similar_recipes("yummy dessert"))# Recipe ID: recipe|167188# Recipe Name: Creamy Strawberry Pie# ---# Recipe ID: recipe|1488243# Recipe Name: Summer Strawberry Pie Recipe# ---# Recipe ID: recipe|299514# Recipe Name: Pudding Cake
將 get_similar_recipes 指定為一個工具是很簡單的,盡管你需要指定一個名稱和描述,這實際上是一種微妙的提示工程,因為 LangChain 可能會因為指定的名稱和描述不正確而無法選擇一個工具。
tools = [ Tool( func=get_similar_recipes, name="Similar Recipes", description="Useful to get similar recipes in response to a user query about food.", ),]最后,是示例中的 Agent 構(gòu)建代碼,以及新的系統(tǒng)提示。
memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True)llm = ChatOpenAI(temperature=0)agent_chain = initialize_agent(tools, llm, prompt=prompt, agent=AgentType.CHAT_CONVERSATIONAL_REACT_DESCRIPTION, verbose=True, memory=memory)
沒有錯誤?,F(xiàn)在運行 Agent,看看會發(fā)生什么:
agent_chain.run(input="Hi!")
> Entering new chain...{ "action": "Final Answer", "action_input": "Hello! How can I assist you today?"}什么?它完全忽略了我的系統(tǒng)提示!檢查內(nèi)存變量證實了這一點。
> Finished chain.Hello! How can I assist you today?
在 ConversationBufferMemory 的文檔中,甚至在代碼本身中都沒有關(guān)于系統(tǒng)提示的內(nèi)容,甚至在 ChatGPT 使其成為主流的幾個月之后。
在 Agent 中使用系統(tǒng)提示的方法是在 initialize_agent 中添加一個 agents_kwargs 參數(shù),我只是在一個月前發(fā)布的一個不相關(guān)的文檔頁面中發(fā)現(xiàn)了這一點。
agent_kwargs = { "system_message": system_prompt.strip()}
使用此新參數(shù)重新創(chuàng)建 Agent 并再次運行,會導(dǎo)致 JSONDecodeError。
好消息是,系統(tǒng)提示這次應(yīng)該是起作用了。
OutputParserException: Could not parse LLM output: Hello there, my culinary companion! How delightful to have you here in my whimsical kitchen. What delectable dish can I assist you with today?
壞消息是,它壞了,但又是為什么呢?我這一次沒有做任何奇怪的事情。
有趣的事實:這些大量的提示也會成比例地增加 API 成本。
這樣做的后果是,正常輸出結(jié)構(gòu)中的任何重大變化,例如由自定義系統(tǒng)提示引起的變化,都有可能破壞 Agent。這些錯誤經(jīng)常發(fā)生,以至于有一個文檔頁面專門用于處理 Agent 輸出解析錯誤。
我們暫時把與聊天機器人對話看作是一個邊緣案例。重要的是,機器人能夠返回菜譜,因為如果連這一點都做不到,那么使用 LangChain 就沒有意義了。
在不使用系統(tǒng)提示的情況下創(chuàng)建一個新的 Agent,然后問它什么是簡單有趣的晚餐?
> Entering new chain...{ "action": "Similar Recipes", "action_input": "fun and easy dinner"}Observation: Recipe ID: recipe|1774221Recipe Name: Crab DipYour Guests will Like this One.---Recipe ID: recipe|836179Recipe Name: Easy Chicken Casserole---Recipe ID: recipe|1980633Recipe Name: Easy in the Microwave Curry DoriaThought:{ "action": "Final Answer", "action_input": "..."}至少它成功了:ChatGPT 能夠從上下文中提取出菜譜,并對其進行適當(dāng)?shù)母袷交ㄉ踔聊軌蛐拚Q中的錯別字),并且能夠在適當(dāng)?shù)臅r候進行判斷。
> Finished chain.Here are some fun and easy dinner recipes you can try:
1. Crab Dip2. Easy Chicken Casserole3. Easy in the Microwave Curry Doria
Enjoy your meal!
這里真正的問題是,輸出的聲音很無聊,這也是基礎(chǔ)版 ChatGPT 的共同特點和詬病。即使通過系統(tǒng)提示工程解決了 ID 缺失的問題,這般聽上去的效果也不值得將其發(fā)布。就算真的在語音質(zhì)量和輸出質(zhì)量之間取得了平衡,Agent 計數(shù)仍然會隨機失敗,而這并不是我的過錯。
實際上,Agent 工作流是一個非常脆弱的紙牌搭成的房子,憑良心說,生產(chǎn)應(yīng)用中估計無法使用。
LangChain 確實有 Custom Agent 和 Custom Chain 的功能,所以你可以在堆棧的某些部分重寫邏輯(也許文檔很少),這可以解決我遇到的一些問題,但在這一點上,你會感覺到 LangChain 更加復(fù)雜,還不如創(chuàng)建你自己的 Python 庫。
工作要講究方法
大量隨機集成帶來的問題比解決方案更多。
當(dāng)然,LangChain 確實也有很多實用功能,比如文本分割器和集成向量存儲,這兩種功能都是「用 PDF / 代碼聊天」演示不可或缺的(在我看來這只是一個噱頭)。
所有這些集成的真正問題在于,只使用基于 LangChain 的代碼會造成固有的鎖定,而且如果你查看集成的代碼,它們并不十分穩(wěn)健。
LangChain 正在建立一條護城河,這對 LangChain 的投資者來說是好事,因為他們想從 3000 萬美元中獲得回報,但對使用它的開發(fā)者來說卻非常不利??偠灾琇angChain 體現(xiàn)了「它很復(fù)雜,所以它一定更好」這一經(jīng)常困擾后期代碼庫的哲學(xué),可是 LangChain 甚至還不到一年。
要想讓 LangChain 做我想讓它做的事,就必須花大力氣破解它,這將造成大量的技術(shù)負擔(dān)。與現(xiàn)在的人工智能初創(chuàng)公司不同,我自己的 LangChain 項目的技術(shù)債務(wù)無法用風(fēng)險投資來償還。在使用復(fù)雜的生態(tài)系統(tǒng)時,應(yīng)用程序接口封裝器至少應(yīng)該降低代碼的復(fù)雜性和認知負荷,因為使用人工智能本身就需要花費足夠的腦力。LangChain 是為數(shù)不多的在大多數(shù)常用情況下都會增加開銷的軟件之一。
我得出的結(jié)論是,制作自己的 Python 軟件包要比讓 LangChain 來滿足自己的需求容易得多。因此,我開發(fā)并開源了 simpleaichat:一個用于輕松連接聊天應(yīng)用程序的 Python 程序包,它強調(diào)代碼的最小復(fù)雜度,并將向量存儲等高級功能與對話邏輯解耦。
開源地址:https://github.com/minimaxir/simpleaichat
但寫這篇博文并不是為了像那些騙子一樣,通過詆毀競爭對手來為 simpleaichat 做****廣告。我不想宣傳 simpleaichat,我更愿意把時間花在用人工智能創(chuàng)造更酷的項目上,很遺憾我沒能用 LangChain 做到這一點。
我知道有人會說:「既然 LangChain 是開源的,為什么不向它的 repo 提交拉取請求,而要抱怨它呢?」唯一真正能解決的辦法就是把它全部燒掉,然后重新開始,這就是為什么我的「創(chuàng)建一個新的 Python 庫來連接人工智能」的解決方案也是最實用的。
我收到過很多留言,問我該「學(xué)什么才能開始使用 ChatGPT API」,我擔(dān)心他們會因為炒作而首先使用 LangChain。如果擁有技術(shù)棧背景的機器學(xué)習(xí)工程師因為 LangChain 毫無必要的復(fù)雜性而難以使用 LangChain,那么任何初學(xué)者都會被淹沒。
關(guān)于軟件復(fù)雜性和復(fù)雜性下的流行性之爭是永恒的話題。沒有人愿意成為批評 LangChain 這樣的免費開源軟件的混蛋,但我愿意承擔(dān)這個責(zé)任。明確地說,我并不反對 Harrison Chase 或 LangChain 的其他維護者(他們鼓勵反饋)。
然而,LangChain 的流行已經(jīng)扭曲了圍繞 LangChain 本身的人工智能創(chuàng)業(yè)生態(tài)系統(tǒng),這就是為什么我不得不坦誠我對它的疑慮。
原文鏈接:https://minimaxir.com/2023/07/langchain-problem/
*博客內(nèi)容為網(wǎng)友個人發(fā)布,僅代表博主個人觀點,如有侵權(quán)請聯(lián)系工作人員刪除。