Agent 智能體開(kāi)發(fā)框架選型指南 原創(chuàng) 精華
編者按: 本文通過(guò)作者的實(shí)踐對(duì)比發(fā)現(xiàn),框架的選擇應(yīng)基于項(xiàng)目具體需求和團(tuán)隊(duì)特點(diǎn),而不是簡(jiǎn)單追求某個(gè)特定框架。不同框架各有優(yōu)勢(shì):
- 無(wú)框架方案實(shí)施最為簡(jiǎn)單直接,代碼結(jié)構(gòu)清晰,適合理解智能體原理,但隨著項(xiàng)目復(fù)雜度增加可能變得難以維護(hù)。
- LangGraph提供完整的智能體結(jié)構(gòu)規(guī)范,特別適合團(tuán)隊(duì)協(xié)作和智能體結(jié)構(gòu)新手,但框架限制較多,如不認(rèn)同其理念可能面臨較大調(diào)試挑戰(zhàn)。
- LlamaIndex Workflows采用事件驅(qū)動(dòng)架構(gòu),在框架約束和開(kāi)發(fā)自由度之間取得平衡,對(duì)框架依賴(lài)較少,但其固有的異步特性可能增加某些場(chǎng)景的復(fù)雜度。
框架選擇需要考慮三個(gè)關(guān)鍵因素:項(xiàng)目是否已深度集成了特定框架、團(tuán)隊(duì)對(duì)智能體架構(gòu)的熟悉程度、是否有可供參考的相似項(xiàng)目案例。
作者 | Aparna Dhinakaran
編譯 | 岳揚(yáng)
Image by author
智能體(Agents)正迎來(lái)輝煌時(shí)刻。伴隨著眾多新框架的涌現(xiàn)和對(duì)該領(lǐng)域的持續(xù)投資[1],現(xiàn)代 AI 智能體正在跨越起初的不穩(wěn)定階段[2],迅速取代 RAG 成為開(kāi)發(fā)首選。那么,2024 年是否會(huì)成為 autonomous AI 系統(tǒng)全面接管撰寫(xiě)郵件、預(yù)訂航班、數(shù)據(jù)分析等任務(wù)的一年呢?
也許吧,但要實(shí)現(xiàn)這一點(diǎn)還有很多工作要做。開(kāi)發(fā)人員在構(gòu)建智能體時(shí),不僅要決定使用何種模型、應(yīng)用場(chǎng)景和技術(shù)架構(gòu),還要挑選合適的開(kāi)發(fā)框架。是堅(jiān)持較為早期的 LangGraph,還是轉(zhuǎn)向新興的 LlamaIndex Workflows?或者走傳統(tǒng)路線(xiàn),自己編寫(xiě)全部代碼呢?
這篇文章的目的就是讓您更輕松地做出選擇。在過(guò)去幾周里,我使用多個(gè)主流框架構(gòu)建了相同的智能體,并從技術(shù)角度分析了它們各自的優(yōu)缺點(diǎn)。每個(gè)智能體的所有代碼都可以在此代碼倉(cāng)庫(kù)[3]中找到。
本文測(cè)試用智能體的基本概述
本次測(cè)試所采用的智能體整合了多項(xiàng)功能,包括執(zhí)行函數(shù)調(diào)用(function calling)、使用多種工具或技能、與外部資源建立連接,以及實(shí)現(xiàn)狀態(tài)或記憶的共享。
該智能體具備以下幾項(xiàng)核心能力:
- 基于知識(shí)庫(kù)進(jìn)行問(wèn)題解答
- 數(shù)據(jù)交互:針對(duì) LLM 應(yīng)用程序的數(shù)據(jù)進(jìn)行問(wèn)題解答
- 數(shù)據(jù)洞察:對(duì)獲取的數(shù)據(jù)進(jìn)行更高層次的趨勢(shì)和模式分析
為了達(dá)成上述目標(biāo),智能體需要掌握三項(xiàng)基本技能:結(jié)合產(chǎn)品文檔的 RAG、在相關(guān)數(shù)據(jù)庫(kù)上生成 SQL 語(yǔ)句的能力,以及數(shù)據(jù)分析技巧。智能體的用戶(hù)界面使用 gradio 搭建,而智能體本身則以聊天機(jī)器人(chatbot)的形式構(gòu)建。
01 Code-Based Agent(不使用智能體框架)
在著手開(kāi)發(fā)智能體時(shí),您可以選擇不依賴(lài)任何框架,而是完全自主構(gòu)建。在啟動(dòng)這個(gè)項(xiàng)目之初,我首先采用了這種方法。
Image by author
1.1 純代碼架構(gòu)
下面是基于純代碼構(gòu)建的智能體,其核心是一個(gè)由 OpenAI 提供支持的技能路由器,它通過(guò)函數(shù)調(diào)用來(lái)確定使用哪項(xiàng)技能。技能執(zhí)行完畢后,控制權(quán)將返回給技能路由器,以便調(diào)用其他技能或直接向用戶(hù)作出回應(yīng)。
智能體會(huì)持續(xù)記錄用戶(hù)消息和智能體響應(yīng),并在每次調(diào)用時(shí)將這一完整列表傳遞給技能路由器,確保在整個(gè)交互過(guò)程中保留上下文。
各項(xiàng)技能均在獨(dú)立的類(lèi)中進(jìn)行定義(例如“GenerateSQLQuery”類(lèi)),這些類(lèi)都保存在 SkillMap 中。技能路由器僅與 SkillMap 進(jìn)行交互,通過(guò)它來(lái)加載技能的名稱(chēng)、描述以及可調(diào)用的函數(shù)。這種設(shè)計(jì)理念使得向智能體中添加新技能變得非常簡(jiǎn)單:只需將該技能編寫(xiě)為一個(gè)獨(dú)立的類(lèi),并將其加入到 SkillMap 的技能列表即可。這樣做的目的是為了在不影響技能路由器代碼的前提下,輕松實(shí)現(xiàn)新技能的添加。
總的來(lái)說(shuō),這種實(shí)現(xiàn)方式雖然簡(jiǎn)單易行,但仍然存在一些需要克服的難題。
1.2 使用純代碼智能體面臨的挑戰(zhàn)
第一個(gè)困難在于如何設(shè)計(jì)技能路由器的系統(tǒng)提示詞(system prompt)。 在上面的例子中,技能路由器往往傾向于自行生成 SQL 語(yǔ)句,而不是交給相應(yīng)的技能模塊去處理。如果你有過(guò)試圖讓大語(yǔ)言模型停止執(zhí)行某項(xiàng)任務(wù)的經(jīng)歷,那你可能深知這其中的挫敗感;為了找到合適的提示詞,我不得不進(jìn)行了多次調(diào)試。此外,處理每個(gè)步驟產(chǎn)生的不同輸出格式也是一項(xiàng)復(fù)雜的工作。 由于我選擇不使用結(jié)構(gòu)化輸出,因此必須為技能路由器和各項(xiàng)技能中大語(yǔ)言模型的調(diào)用準(zhǔn)備多種格式的應(yīng)對(duì)策略。
1.3 純代碼智能體的優(yōu)點(diǎn)
基于代碼的方法提供了一個(gè)扎實(shí)的基礎(chǔ)和出發(fā)點(diǎn),是一種絕佳的學(xué)習(xí)途徑,讓我們可以在不依賴(lài)現(xiàn)成框架提供的智能體教程的情況下,了解智能體的運(yùn)作原理。雖然引導(dǎo)大語(yǔ)言模型按既定行為模式運(yùn)作確實(shí)存在難度,但代碼結(jié)構(gòu)本身簡(jiǎn)潔明了,易于操作,對(duì)于某些使用場(chǎng)景而言,這種做法是完全合理的(具體分析將在下文展開(kāi))。
02 LangGraph
LangGraph 是眾多智能體框架中歷史最為悠久的之一,它于 2024 年 1 月首次發(fā)布。該框架的設(shè)計(jì)初衷是為了解決現(xiàn)有流程和鏈條的非循環(huán)性問(wèn)題,它通過(guò)采用 Pregel 圖結(jié)構(gòu)來(lái)解決這一問(wèn)題。 LangGraph 通過(guò)引入節(jié)點(diǎn)(nodes)、邊(edges)以及條件邊(conditional edges)的概念,簡(jiǎn)化了在智能體中創(chuàng)建循環(huán)流程的過(guò)程,使得圖的遍歷變得更加直觀。LangGraph 是基于 LangChain 構(gòu)建的,它繼承了后者的對(duì)象(objects)和類(lèi)型(types)。
Image by author
2.1 LangGraph 架構(gòu)
從表面上看,LangGraph 智能體與基于代碼的智能體有相似之處,但它們的底層代碼卻有大不相同。雖然 LangGraph 在技術(shù)上也使用了“路由器(router)”這一概念,即通過(guò)代碼函數(shù)調(diào)用 OpenAI 并利用其響應(yīng)來(lái)推進(jìn)到下一個(gè)步驟,但程序在不同技能之間的切換控制機(jī)制卻完全不同。
在此定義的圖(graph)中,包含了一個(gè)用于初始化 OpenAI 調(diào)用的節(jié)點(diǎn),即上文中提到的“agent”,以及一個(gè)用于工具處理步驟節(jié)點(diǎn),即“tools”。LangGraph 內(nèi)置了一個(gè)名為 ToolNode 的對(duì)象,它能夠接收一系列可調(diào)用的工具,并根據(jù) ChatMessage 的響應(yīng)來(lái)觸發(fā)這些工具,完成操作后再次回到“agent”節(jié)點(diǎn)。
每當(dāng)“agent”節(jié)點(diǎn)(也可以理解為基于代碼的智能體中的技能路由器(router))被調(diào)用之后,should_continue 這條邊將判斷是將響應(yīng)直接返回給用戶(hù),還是轉(zhuǎn)給 ToolNode 來(lái)處理工具調(diào)用。
在每個(gè)節(jié)點(diǎn)中,“state” 負(fù)責(zé)保存與 OpenAI 的交互消息和響應(yīng)列表,這一點(diǎn)與基于代碼的智能體保持上下文的方式相似。
2.2 使用 LangGraph 面臨的挑戰(zhàn)
在處理 LangGraph 構(gòu)建的智能體示例時(shí),遇到的主要難題在于必須借助 Langchain 對(duì)象才能確保流程的順暢。
挑戰(zhàn) 1:函數(shù)調(diào)用的 validation 錯(cuò)誤
為了能夠使用 ToolNode 對(duì)象,我不得不對(duì) Skill 代碼進(jìn)行大規(guī)模的重構(gòu)。ToolNode 需要一組可調(diào)用的函數(shù)列表,我本以為可以直接使用現(xiàn)成的函數(shù),但是函數(shù)參數(shù)配置出了問(wèn)題,導(dǎo)致流程受阻。
這些技能(skills)是以類(lèi)形式定義的,每個(gè)類(lèi)都有一個(gè)可調(diào)用的成員函數(shù),其中“self”是首個(gè)參數(shù)。GPT-4o 足夠智能,能夠在生成函數(shù)調(diào)用(function call)時(shí)自動(dòng)排除“self”參數(shù),但 LangGraph 卻因此認(rèn)為缺少了必要參數(shù),從而拋出了 validation 錯(cuò)誤。
這個(gè)問(wèn)題讓我摸索了好幾小時(shí)才搞清楚,因?yàn)殄e(cuò)誤信息把函數(shù)里的第三個(gè)參數(shù)(數(shù)據(jù)分析技能中的“args”)錯(cuò)誤地標(biāo)記為缺失參數(shù)(missing parameter):
需要指出的是,這個(gè)誤導(dǎo)性的錯(cuò)誤信息其實(shí)來(lái)自 Pydantic,而非 LangGraph。
最后,我下定決心,改用 Langchain 的 @tool 裝飾器將我的技能(skills)重新編寫(xiě)為基本方法,這樣程序就能正常運(yùn)行了。
挑戰(zhàn) 2:Debugging
正如前文所述,在框架中調(diào)試非常困難。主要是因?yàn)殄e(cuò)誤信息混亂不清,以及框架中的抽象概念,它們使得追蹤和查看變量變得非常復(fù)雜。
抽象概念主要體現(xiàn)在嘗試跟蹤智能體間傳遞的消息時(shí)。LangGraph 會(huì)將消息保存在 state[“messages”] 里。Graph 中的一些節(jié)點(diǎn)會(huì)自動(dòng)從這些消息(messages)中提取信息,這樣的自動(dòng)化過(guò)程可能會(huì)讓節(jié)點(diǎn)在訪(fǎng)問(wèn)消息(messages)時(shí),我們難以把握消息(messages)的具體內(nèi)容。
智能體行動(dòng)的順序視圖(圖片由作者提供)
2.3 LangGraph 的優(yōu)點(diǎn)
LangGraph 的最大優(yōu)勢(shì)在于其易用性。它的圖結(jié)構(gòu)代碼簡(jiǎn)潔且易于理解。對(duì)于那些擁有復(fù)雜節(jié)點(diǎn)邏輯的場(chǎng)景,LangGraph 能夠提供一個(gè)清晰的圖視圖,讓我們更輕松地把握智能體的連接方式。此外,LangGraph 還可以直接轉(zhuǎn)換以 LangChain 構(gòu)建的現(xiàn)有應(yīng)用程序。
2.4 經(jīng)驗(yàn)之談
當(dāng)我們只使用 LangGraph 框架的相關(guān)功能時(shí),一切都會(huì)運(yùn)行得非常流暢;但一旦我們嘗試跳出框架,就要準(zhǔn)備好進(jìn)行一些令人頭疼的調(diào)試了。
03 LlamaIndex Workflows
Workflows 是智能體框架領(lǐng)域的新晉成員,它于今年夏初首次亮相。與 LangGraph 類(lèi)似,它的設(shè)計(jì)宗旨是簡(jiǎn)化可循環(huán)智能體的構(gòu)建過(guò)程。此外,Workflows 特別強(qiáng)調(diào)其異步執(zhí)行的能力。
在 Workflows 中,某些設(shè)計(jì)元素似乎是為了直接對(duì)標(biāo) LangGraph,尤其是它采用事件(events)而非邊(edges)或條件邊(conditional edges)作為連接邏輯的方式。在 Workflows 中,智能體邏輯被封裝在“步驟(steps)”中(與 LangGraph 中的“節(jié)點(diǎn)(nodes)”相對(duì)應(yīng)),而事件(events)的發(fā)出和接收則負(fù)責(zé)在不同的步驟(steps)間傳遞信息。
Image by author
上述框架與 LangGraph 的結(jié)構(gòu)頗為相似,但有一點(diǎn)不同:我給 Workflow 增加了一個(gè)初始化步驟,用于準(zhǔn)備智能體的環(huán)境上下文,稍后我會(huì)詳細(xì)介紹這一點(diǎn)。盡管兩者的結(jié)構(gòu)相似,但它們所依賴(lài)的代碼實(shí)現(xiàn)卻截然不同。
3.1 Workflows 架構(gòu)
以下代碼段描繪了 Workflow 的架構(gòu)。與 LangGraph 相仿,在這一部分,我配置了狀態(tài)信息(state),并將各項(xiàng)技能(skills)綁定到了 LLM 對(duì)象上。
在這里,我還定義了一個(gè)額外的步驟——“prepare_agent”。該步驟負(fù)責(zé)將用戶(hù)輸入轉(zhuǎn)換成 ChatMessage,并將其存儲(chǔ)到工作流的記憶存儲(chǔ)中。將這一過(guò)程作為一個(gè)獨(dú)立的步驟分離出來(lái),意味著智能體在遍歷工作步驟(steps)時(shí)可以重復(fù)回到這一步,從而避免反復(fù)將用戶(hù)信息加入到記憶存儲(chǔ)中。
在 LangGraph 的實(shí)現(xiàn)案例中,我通過(guò)一個(gè)位于圖(graph)之外的 run_agent 方法實(shí)現(xiàn)了相同的功能。這一改變主要是出于風(fēng)格上的考慮,但我認(rèn)為,將這一邏輯整合到 Workflow 和圖(graph)中,會(huì)更加整潔和高效。
在 Workflow 配置完成后,我繼續(xù)編寫(xiě)了路由代碼:
以及工具調(diào)用處理代碼:
它們的實(shí)現(xiàn)方式似乎更接近于純代碼的智能體,而非 LangGraph 智能體。這主要是因?yàn)?Workflows 選擇在各步驟(steps)中維護(hù)條件路由(conditional routing)邏輯,而不是像 LangGraph 那樣使用條件邊(conditional edge)(第 18-24 行在 LangGraph 中是條件邊,而現(xiàn)在它們只是路由步驟的一部分)。另外,LangGraph 中的 ToolNode 對(duì)象能夠在 tool_call_handler 方法中自動(dòng)處理大部分任務(wù)。
在路由步驟之后,我們能夠?qū)?SkillMap 以及基于純代碼的智能體中已有的技能(skills)直接應(yīng)用于 Workflows。這些技能(skills)無(wú)需任何修改即可與 Workflows 配合使用,這大大簡(jiǎn)化了我的工作。
3.2 使用 Workflows 面臨的挑戰(zhàn)
挑戰(zhàn) 1:Sync vs Async
盡管對(duì)于在線(xiàn)運(yùn)行的智能體來(lái)說(shuō),異步執(zhí)行是更優(yōu)的選擇,但調(diào)試同步執(zhí)行的智能體通常更為簡(jiǎn)便。Workflows 本身是為了異步操作而設(shè)計(jì)的,因此嘗試將其改為同步執(zhí)行非常困難。
起初,我以為只需去掉“async”方法標(biāo)識(shí),并將函數(shù)名“achat_with_tools”改為“chat_with_tools”即可。但是,由于 Workflow 類(lèi)內(nèi)部的方法同樣采用了異步標(biāo)記,為了實(shí)現(xiàn)同步運(yùn)行,我不得不重新定義這些方法。盡管如此,我最終還是選擇了異步處理方式,幸運(yùn)的是,這并沒(méi)有增加調(diào)試的難度。
智能體行動(dòng)的順序視圖(圖片由作者提供)
挑戰(zhàn) 2:Pydantic Validation Errors
與 LangGraph 的問(wèn)題類(lèi)似,在智能體的技能(skills)處也出現(xiàn)了令人困惑的 Pydantic Validation Errors。幸運(yùn)的是,由于 Workflows 能夠很好地處理成員函數(shù),這些問(wèn)題這次比較容易解決。最終,我不得不更加規(guī)范地為智能體技能(skills)創(chuàng)建 LlamaIndex FunctionTool 對(duì)象:
從構(gòu)建 FunctionTools 的 AgentFlow.init 文件中摘錄
3.3 Workflows 的優(yōu)點(diǎn)
與 LangGraph 相比,我在使用 Workflows 構(gòu)建智能體時(shí)要輕松得多,主要原因是 Workflows 并未提供內(nèi)置功能,而是需要我自己編寫(xiě)路由邏輯和工具操作代碼。 這也使得我的 Workflow 智能體與基于純代碼的智能體看起來(lái)極為相似。
最大的區(qū)別在于事件(events)的使用上。我使用兩個(gè)自定義事件在智能體中的各個(gè)步驟之間移動(dòng):
這種基于事件的發(fā)射器-接收器架構(gòu)(emitter-receiver),取代了直接調(diào)用智能體中某些方法的做法,例如工具調(diào)用處理(tool call handler)。
對(duì)于那些步驟(steps)更為復(fù)雜、異步觸發(fā)且可能產(chǎn)生多個(gè)事件(events)的系統(tǒng)來(lái)說(shuō),這種架構(gòu)就非常有助于干凈利落地管理這些步驟。
Workflows 的其他優(yōu)點(diǎn)還包括其輕量級(jí)特性,不會(huì)施加過(guò)多的結(jié)構(gòu)限制(除了必須使用特定的 LlamaIndex 對(duì)象外),并且其基于事件(event-based)的架構(gòu)為直接函數(shù)調(diào)用提供了一種有效的替代方案,這對(duì)于處理復(fù)雜、異步的應(yīng)用場(chǎng)景尤為有益。
04 對(duì)這些方法進(jìn)行比較
對(duì)比這三種方法,各有其獨(dú)到之處。
無(wú)框架方法實(shí)施起來(lái)最簡(jiǎn)單。由于所有抽象層都是由開(kāi)發(fā)者自行定義(如前例中的 SkillMap 對(duì)象),因此管理不同類(lèi)型(types)和對(duì)象(objects)相對(duì)簡(jiǎn)單。但是,代碼的可讀性和易用性完全取決于開(kāi)發(fā)者個(gè)人,可以預(yù)見(jiàn),如果沒(méi)有一定的智能體結(jié)構(gòu)約束,智能體的復(fù)雜性增加后可能會(huì)變得難以駕馭。
LangGraph 提供了豐富的智能體結(jié)構(gòu)支持,使得智能體的定義非常清晰。對(duì)于多人協(xié)作開(kāi)發(fā)的智能體來(lái)說(shuō),這種智能體結(jié)構(gòu)設(shè)定有助于統(tǒng)一架構(gòu)規(guī)范。LangGraph 也為那些對(duì)智能體結(jié)構(gòu)不太熟悉的開(kāi)發(fā)者提供了幫助。不過(guò),這樣做也有代價(jià) —— 由于 LangGraph 為你做了許多工作,如果你不完全認(rèn)同這個(gè)框架,它可能會(huì)讓你頭疼不已;代碼可能會(huì)非常簡(jiǎn)潔,但你可能要為此進(jìn)行更多的調(diào)試工作。
Workflows 則處于兩者之間?;谑录╡vent-based)的架構(gòu)在某些項(xiàng)目中可能極具價(jià)值,而且因?yàn)樗鼘?duì) LlamaIndex 類(lèi)型的使用要求不高,對(duì)于那些沒(méi)有在應(yīng)用程序中完全使用該框架的開(kāi)發(fā)者來(lái)說(shuō),提供了更大的自由度。
Image created by author
歸根結(jié)底,關(guān)鍵問(wèn)題可能在于“你是否已經(jīng)在使用 LlamaIndex 或 LangChain 來(lái)組織應(yīng)用程序?” LangGraph 和 Workflows 都與它們所依賴(lài)的框架緊密集成,因此每個(gè)特定智能體框架的額外優(yōu)勢(shì)可能不足以成為轉(zhuǎn)換使用的理由。
純代碼方法可能永遠(yuǎn)是一個(gè)有吸引力的選擇。如果你能夠嚴(yán)格地記錄并執(zhí)行所創(chuàng)建的任何抽象概念,那么確保外部框架不會(huì)成為你的阻礙就很容易了。
05 在選擇智能體框架時(shí)需要考慮的關(guān)鍵問(wèn)題
當(dāng)然,單純一句“具體情況具體分析”這樣的回答總是讓人不太滿(mǎn)意。以下三個(gè)問(wèn)題或許能幫你選擇下一個(gè)智能體項(xiàng)目應(yīng)該采用哪個(gè)框架。
你的項(xiàng)目是否已經(jīng)深度集成了 LlamaIndex 或 LangChain?
如果是的話(huà),不妨優(yōu)先考慮這兩個(gè)選項(xiàng)。
你對(duì)智能體的常見(jiàn)架構(gòu)是否熟悉,還是更希望有人告訴你應(yīng)該如何構(gòu)建智能體結(jié)構(gòu)?
如果你傾向于后者,那么 Workflows 可能是個(gè)不錯(cuò)的選擇。如果你非常傾向于后者,那么 LangGraph 或許更適合你。
你要構(gòu)建的智能體是否有參考樣例?
框架的一個(gè)優(yōu)勢(shì)在于,每個(gè)框架都有大量的教程和實(shí)例供你參考。而純代碼構(gòu)建智能體的參考實(shí)例相對(duì)較少。
Image created by author
06 Conclusion
選擇一個(gè)智能體框架只是影響生成式人工智能系統(tǒng)在生產(chǎn)環(huán)境中表現(xiàn)眾多決策中的一項(xiàng),建立強(qiáng)大的安全保障和對(duì)大語(yǔ)言模型(LLM)的監(jiān)控[4]是必要的 —— 同時(shí),面對(duì)新智能體框架、研究成果和模型對(duì)傳統(tǒng)技術(shù)的顛覆,我們還需保持靈活應(yīng)對(duì)的態(tài)度。
Thanks for reading!
Hope you have enjoyed and learned new things from this blog!
About the authors
Aparna Dhinakaran
Co-Founder and CPO of Arize AI. Formerly Computer Vision PhD at Cornell, Uber Machine Learning, UC Berkeley AI Research.
END
本期互動(dòng)內(nèi)容 ??
?請(qǐng)分享一下你最常使用的智能體開(kāi)發(fā)方式?為什么?
??文中鏈接??
[1]??https://foundationcapital.com/goodbye-aiops-welcome-agentsres-the-next-100b-opportunity/??
[2]??https://arxiv.org/html/2405.13966v1??
[3]??https://github.com/Arize-ai/phoenix/tree/main/examples/agent_framework_comparison??
[4]??https://docs.arize.com/phoenix/tracing/llm-traces??
原文鏈接:
??https://towardsdatascience.com/choosing-between-llm-agent-frameworks-69019493b259??
