AI Agents-5 | AI工作流與代理的深度剖析:從原理到實(shí)戰(zhàn)應(yīng)用 原創(chuàng)
這個系列文章旨在為AI代理(AI Agent)提供全面的概述,深入研究其特征,組成部分和類型,同時(shí)探索其進(jìn)化,挑戰(zhàn)和潛在的未來方向。
在人工智能飛速發(fā)展的今天,我們常常聽到“AI工作流”和“AI代理”這兩個概念。但你知道它們之間有什么區(qū)別嗎?又該如何選擇適合自己的技術(shù)路徑呢?今天,我們就來深入探討一下。
一、工作流與代理:到底有什么區(qū)別?
(一)定義與區(qū)別
在AI的世界里,“代理”(Agent)和“工作流”(Workflow)是兩種截然不同的存在。有些人把代理定義為完全自主的系統(tǒng),它們可以獨(dú)立運(yùn)行很長時(shí)間,利用各種工具完成復(fù)雜的任務(wù)。而另一些人則用它來描述那些按照預(yù)定義流程執(zhí)行的系統(tǒng)。
Anthropic公司把這兩種情況都?xì)w類為“代理系統(tǒng)”,但他們明確區(qū)分了工作流和代理:
- 工作流:是一種通過預(yù)定義代碼路徑來協(xié)調(diào)LLM(大型語言模型)和工具的系統(tǒng)。
- 代理:則是LLM動態(tài)地指導(dǎo)自己的流程和工具使用,完全掌控任務(wù)的執(zhí)行方式。
用一個簡單的比喻來說,工作流就像是按照食譜一步步做飯,而代理則像是一個廚師,根據(jù)食材和口味現(xiàn)場決定怎么做菜。
(二)什么時(shí)候用代理,什么時(shí)候不用?
開發(fā)基于LLM的應(yīng)用時(shí),最好從最簡單的解決方案開始,只有在必要時(shí)才引入復(fù)雜性。有時(shí)候,完全避開代理系統(tǒng)可能是個更好的選擇。畢竟,這些系統(tǒng)雖然能提高任務(wù)性能,但往往伴隨著更高的延遲和成本。所以,我們需要權(quán)衡利弊。
如果任務(wù)結(jié)構(gòu)清晰、規(guī)則明確,工作流可以提供穩(wěn)定性和一致性。而代理則更適合那些需要靈活性和大規(guī)模模型驅(qū)動決策的場景。不過,對于很多應(yīng)用來說,優(yōu)化單個LLM調(diào)用,加上檢索和上下文示例,往往就足夠了。
(三)框架的使用:利與弊
現(xiàn)在有很多框架可以讓代理系統(tǒng)的實(shí)現(xiàn)變得更簡單,比如LangChain的LangGraph、亞馬遜Bedrock的AI代理框架、Rivet(一個拖拽式GUI的LLM工作流構(gòu)建器)和Vellum(用于構(gòu)建和測試復(fù)雜工作流的GUI工具)。這些框架簡化了調(diào)用LLM、定義和解析工具、串聯(lián)調(diào)用等標(biāo)準(zhǔn)低級任務(wù),讓你更容易上手。
但這些框架也有缺點(diǎn)。它們可能會增加額外的抽象層,讓你看不清底層的提示和響應(yīng),從而讓調(diào)試變得困難。而且,它們可能會讓你不自覺地增加復(fù)雜性,而實(shí)際上簡單的設(shè)置就足夠了。
所以,我們建議開發(fā)者先直接使用LLM的API,因?yàn)楹芏嗄J街恍枰獛仔写a就能實(shí)現(xiàn)。如果你決定使用框架,一定要徹底理解底層代碼,因?yàn)閷蚣軆?nèi)部工作原理的錯誤假設(shè)是錯誤的常見來源。
二、構(gòu)建模塊:從簡單到復(fù)雜
(一)基礎(chǔ)設(shè)置
在構(gòu)建代理系統(tǒng)時(shí),你可以使用任何支持結(jié)構(gòu)化輸出和工具調(diào)用的聊天模型。以下是一個簡單的設(shè)置過程,展示了如何安裝包、設(shè)置API密鑰,并測試Anthropic的結(jié)構(gòu)化輸出和工具調(diào)用。
import os
import getpass
from langchain_anthropic import ChatAnthropic
def _set_env(var: str):
if not os.environ.get(var):
os.environ[var] = getpass.getpass(f"{var}: ")
_set_env("ANTHROPIC_API_KEY")
llm = ChatAnthropic(model="claude-3-5-sonnet-latest")
(二)增強(qiáng)型LLM:核心構(gòu)建模塊
代理系統(tǒng)的基礎(chǔ)是一個增強(qiáng)型LLM,它通過檢索、工具和記憶等增強(qiáng)功能來實(shí)現(xiàn)更強(qiáng)大的能力。我們的模型可以主動利用這些能力——生成自己的搜索查詢、選擇合適的工具、決定保留哪些信息。
我們建議重點(diǎn)關(guān)注兩個方面:一是將這些能力定制化到你的具體用例中;二是確保它們?yōu)長LM提供一個易于使用且文檔齊全的接口。雖然實(shí)現(xiàn)這些增強(qiáng)功能有很多方法,但一種方法是通過我們最近發(fā)布的模型上下文協(xié)議(Model Context Protocol),它允許開發(fā)者通過簡單的客戶端實(shí)現(xiàn)與不斷增長的第三方工具生態(tài)系統(tǒng)集成。
從現(xiàn)在開始,我們假設(shè)每個LLM調(diào)用都能訪問這些增強(qiáng)功能。
(三)工作流的實(shí)現(xiàn)
1. 鏈?zhǔn)教崾荆≒rompt Chaining)
鏈?zhǔn)教崾臼且环N將任務(wù)分解為一系列步驟的工作流,每個LLM調(diào)用都處理前一個的輸出。你可以在這個過程中加入程序化檢查(見下圖中的“門”),以確保流程仍在正軌上。
這種工作流適用于那些可以輕松分解為固定子任務(wù)的場景。主要目標(biāo)是通過增加延遲來換取更高的準(zhǔn)確性,讓每個LLM調(diào)用的任務(wù)變得更簡單。
例如:
- 先生成營銷文案,然后將其翻譯成另一種語言。
- 先寫文檔大綱,檢查大綱是否符合某些標(biāo)準(zhǔn),再根據(jù)大綱撰寫文檔。
from typing_extensions import TypedDict
from langgraph.graph import StateGraph, START, END
from IPython.display import Image, display
# 圖狀態(tài)
class State(TypedDict):
topic: str
joke: str
improved_joke: str
final_joke: str
# 節(jié)點(diǎn)
def generate_joke(state: State):
"""第一次LLM調(diào)用,生成初始笑話"""
msg = llm.invoke(f"Write a short joke about {state['topic']}")
return {"joke": msg.content}
def check_punchline(state: State):
"""檢查笑話是否有笑點(diǎn)"""
if"?"in state["joke"] or"!"in state["joke"]:
return"Fail"
return"Pass"
def improve_joke(state: State):
"""第二次LLM調(diào)用,改進(jìn)笑話"""
msg = llm.invoke(f"Make this joke funnier by adding wordplay: {state['joke']}")
return {"improved_joke": msg.content}
def polish_joke(state: State):
"""第三次LLM調(diào)用,完善笑話"""
msg = llm.invoke(f"Add a surprising twist to this joke: {state['improved_joke']}")
return {"final_joke": msg.content}
# 構(gòu)建工作流
workflow = StateGraph(State)
# 添加節(jié)點(diǎn)
workflow.add_node("generate_joke", generate_joke)
workflow.add_node("improve_joke", improve_joke)
workflow.add_node("polish_joke", polish_joke)
# 添加邊連接節(jié)點(diǎn)
workflow.add_edge(START, "generate_joke")
workflow.add_conditional_edges(
"generate_joke", check_punchline, {"Fail": "improve_joke", "Pass": END}
)
workflow.add_edge("improve_joke", "polish_joke")
workflow.add_edge("polish_joke", END)
# 編譯
chain = workflow.compile()
# 顯示工作流
display(Image(chain.get_graph().draw_mermaid_png()))
# 調(diào)用
state = chain.invoke({"topic": "cats"})
print("初始笑話:")
print(state["joke"])
print("\n--- --- ---\n")
if"improved_joke"in state:
print("改進(jìn)后的笑話:")
print(state["improved_joke"])
print("\n--- --- ---\n")
print("最終笑話:")
print(state["final_joke"])
else:
print("笑話未通過質(zhì)量檢查——未檢測到笑點(diǎn)!")
2. 并行化(Parallelization)
并行化是一種讓LLM同時(shí)處理任務(wù)的工作流,其輸出可以通過程序化的方式聚合。這種工作流有兩種主要形式:分段(Sectioning)和投票(Voting)。
- 分段:將任務(wù)分解為獨(dú)立的子任務(wù)并并行運(yùn)行。
- 投票:多次運(yùn)行相同的任務(wù)以獲得多樣化的輸出。
這種工作流適用于以下場景:當(dāng)子任務(wù)可以并行化以提高速度時(shí),或者需要多種視角或嘗試以獲得更可靠的結(jié)果時(shí)。對于復(fù)雜的任務(wù),如果每個考慮因素都由單獨(dú)的LLM調(diào)用處理,LLM通常會表現(xiàn)得更好,因?yàn)檫@樣可以讓每個調(diào)用專注于特定的方面。
例如:
- 分段:實(shí)現(xiàn)防護(hù)欄,一個模型實(shí)例處理用戶查詢,另一個篩選不當(dāng)內(nèi)容或請求。這比讓同一個LLM調(diào)用處理防護(hù)欄和核心響應(yīng)表現(xiàn)得更好。
- 投票:審查代碼漏洞,多個不同的提示檢查并標(biāo)記問題;評估內(nèi)容是否不當(dāng),多個提示從不同角度評估,或需要不同的投票閾值以平衡誤報(bào)和漏報(bào)。
# 圖狀態(tài)
class State(TypedDict):
topic: str
joke: str
story: str
poem: str
combined_output: str
# 節(jié)點(diǎn)
def call_llm_1(state: State):
"""第一次LLM調(diào)用,生成笑話"""
msg = llm.invoke(f"Write a joke about {state['topic']}")
return {"joke": msg.content}
def call_llm_2(state: State):
"""第二次LLM調(diào)用,生成故事"""
msg = llm.invoke(f"Write a story about {state['topic']}")
return {"story": msg.content}
def call_llm_3(state: State):
"""第三次LLM調(diào)用,生成詩歌"""
msg = llm.invoke(f"Write a poem about {state['topic']}")
return {"poem": msg.content}
def aggregator(state: State):
"""將笑話、故事和詩歌合并為一個輸出"""
combined = f"Here's a story, joke, and poem about {state['topic']}!\n\n"
combined += f"STORY:\n{state['story']}\n\n"
combined += f"JOKE:\n{state['joke']}\n\n"
combined += f"POEM:\n{state['poem']}"
return {"combined_output": combined}
# 構(gòu)建工作流
parallel_builder = StateGraph(State)
# 添加節(jié)點(diǎn)
parallel_builder.add_node("call_llm_1", call_llm_1)
parallel_builder.add_node("call_llm_2", call_llm_2)
parallel_builder.add_node("call_llm_3", call_llm_3)
parallel_builder.add_node("aggregator", aggregator)
# 添加邊連接節(jié)點(diǎn)
parallel_builder.add_edge(START, "call_llm_1")
parallel_builder.add_edge(START, "call_llm_2")
parallel_builder.add_edge(START, "call_llm_3")
parallel_builder.add_edge("call_llm_1", "aggregator")
parallel_builder.add_edge("call_llm_2", "aggregator")
parallel_builder.add_edge("call_llm_3", "aggregator")
parallel_builder.add_edge("aggregator", END)
# 編譯工作流
parallel_workflow = parallel_builder.compile()
# 顯示工作流
display(Image(parallel_workflow.get_graph().draw_mermaid_png()))
# 調(diào)用
state = parallel_workflow.invoke({"topic": "cats"})
print(state["combined_output"])
3. 路由(Routing)
路由工作流可以根據(jù)輸入的分類將其導(dǎo)向后續(xù)任務(wù)。這種工作流允許分離關(guān)注點(diǎn),并構(gòu)建更專業(yè)的提示。如果沒有這種工作流,優(yōu)化一種輸入的性能可能會損害其他輸入的性能。
這種工作流適用于以下場景:當(dāng)任務(wù)復(fù)雜且有明確的類別,這些類別可以分別處理,并且分類可以準(zhǔn)確完成(無論是通過LLM還是更傳統(tǒng)的分類模型/算法)。
例如:
- 將不同類型的客戶服務(wù)查詢(一般問題、退款請求、技術(shù)支持)導(dǎo)向不同的下游流程、提示和工具。
- 將簡單/常見問題導(dǎo)向較小的模型(如Claude 3.5 Haiku),將復(fù)雜/罕見問題導(dǎo)向更強(qiáng)大的模型(如Claude 3.5 Sonnet),以優(yōu)化成本和速度。
from typing_extensions import Literal
from langchain_core.messages import HumanMessage, SystemMessage
# 結(jié)構(gòu)化輸出的模式,用于路由邏輯
class Route(BaseModel):
step: Literal["poem", "story", "joke"] = Field(
None, descriptinotallow="路由過程中的下一步"
)
# 為LLM添加結(jié)構(gòu)化輸出模式
router = llm.with_structured_output(Route)
# 狀態(tài)
class State(TypedDict):
input: str
decision: str
output: str
# 節(jié)點(diǎn)
def llm_call_1(state: State):
"""寫一個故事"""
result = llm.invoke(state["input"])
return {"output": result.content}
def llm_call_2(state: State):
"""寫一個笑話"""
result = llm.invoke(state["input"])
return {"output": result.content}
def llm_call_3(state: State):
"""寫一首詩"""
result = llm.invoke(state["input"])
return {"output": result.content}
def llm_call_router(state: State):
"""根據(jù)輸入將任務(wù)路由到相應(yīng)的節(jié)點(diǎn)"""
decision = router.invoke(
[
SystemMessage(
cnotallow="根據(jù)用戶請求將輸入路由到故事、笑話或詩歌。"
),
HumanMessage(cnotallow=state["input"]),
]
)
return {"decision": decision.step}
# 條件邊函數(shù),根據(jù)路由決策將任務(wù)導(dǎo)向相應(yīng)節(jié)點(diǎn)
def route_decision(state: State):
if state["decision"] == "story":
return"llm_call_1"
elif state["decision"] == "joke":
return"llm_call_2"
elif state["decision"] == "poem":
return"llm_call_3"
# 構(gòu)建工作流
router_builder = StateGraph(State)
# 添加節(jié)點(diǎn)
router_builder.add_node("llm_call_1", llm_call_1)
router_builder.add_node("llm_call_2", llm_call_2)
router_builder.add_node("llm_call_3", llm_call_3)
router_builder.add_node("llm_call_router", llm_call_router)
# 添加邊連接節(jié)點(diǎn)
router_builder.add_edge(START, "llm_call_router")
router_builder.add_conditional_edges(
"llm_call_router",
route_decision,
{
"llm_call_1": "llm_call_1",
"llm_call_2": "llm_call_2",
"llm_call_3": "llm_call_3",
},
)
router_builder.add_edge("llm_call_1", END)
router_builder.add_edge("llm_call_2", END)
router_builder.add_edge("llm_call_3", END)
# 編譯工作流
router_workflow = router_builder.compile()
# 顯示工作流
display(Image(router_workflow.get_graph().draw_mermaid_png()))
# 調(diào)用
state = router_workflow.invoke({"input": "Write me a joke about cats"})
print(state["output"])
4. 協(xié)調(diào)者-工作者(Orchestrator-Worker)
在協(xié)調(diào)者-工作者工作流中,一個中心LLM動態(tài)地分解任務(wù),將其分配給工作者LLM,并整合它們的結(jié)果。
這種工作流適用于以下場景:當(dāng)任務(wù)復(fù)雜且無法預(yù)測需要哪些子任務(wù)時(shí)(例如在編程中,需要更改的文件數(shù)量以及每個文件的更改性質(zhì)通常取決于具體任務(wù))。雖然它在拓?fù)浣Y(jié)構(gòu)上與并行化類似,但關(guān)鍵區(qū)別在于其靈活性——子任務(wù)不是預(yù)先定義的,而是由協(xié)調(diào)者根據(jù)具體輸入動態(tài)確定的。
舉個例子,這種工作流非常適合以下場景:
- 編程產(chǎn)品需要對多個文件進(jìn)行復(fù)雜更改,每次更改都可能涉及不同的任務(wù)。
- 搜索任務(wù)需要從多個來源收集和分析信息,以獲取可能相關(guān)的數(shù)據(jù)。
from typing import Annotated, List
import operator
# 用于規(guī)劃的結(jié)構(gòu)化輸出模式
class Section(BaseModel):
name: str = Field(descriptinotallow="報(bào)告部分的名稱")
description: str = Field(descriptinotallow="本節(jié)涵蓋的主要主題和概念的簡要概述")
class Sections(BaseModel):
sections: List[Section] = Field(descriptinotallow="報(bào)告的各個部分")
# 為LLM添加結(jié)構(gòu)化輸出模式
planner = llm.with_structured_output(Sections)
# 創(chuàng)建工作者節(jié)點(diǎn)
因?yàn)閰f(xié)調(diào)者-工作者工作流非常常見,LangGraph提供了Send API來支持這種模式。它允許你動態(tài)創(chuàng)建工作者節(jié)點(diǎn),并為每個節(jié)點(diǎn)分配特定的輸入。每個工作者都有自己的狀態(tài),并且所有工作者的輸出都會寫入一個共享的狀態(tài)鍵,協(xié)調(diào)者圖可以訪問這個鍵。這使得協(xié)調(diào)者能夠訪問所有工作者的輸出,并將它們整合成最終輸出。如下所示,我們遍歷一個部分列表,并將每個部分發(fā)送到一個工作者節(jié)點(diǎn)。
```python
from langgraph.constants import Send
# 圖狀態(tài)
class State(TypedDict):
topic: str # 報(bào)告主題
sections: list[Section] # 報(bào)告部分列表
completed_sections: Annotated[list, operator.add] # 所有工作者并行寫入此鍵
final_report: str # 最終報(bào)告
# 工作者狀態(tài)
class WorkerState(TypedDict):
section: Section
completed_sections: Annotated[list, operator.add]
# 節(jié)點(diǎn)
def orchestrator(state: State):
"""協(xié)調(diào)者生成報(bào)告計(jì)劃"""
report_sections = planner.invoke(
[
SystemMessage(cnotallow="生成報(bào)告計(jì)劃"),
HumanMessage(cnotallow=f"報(bào)告主題:{state['topic']}")
]
)
return {"sections": report_sections.sections}
def llm_call(state: WorkerState):
"""工作者撰寫報(bào)告的一部分"""
section = llm.invoke(
[
SystemMessage(cnotallow="根據(jù)提供的名稱和描述撰寫報(bào)告部分。每個部分不加前言,使用Markdown格式。"),
HumanMessage(cnotallow=f"部分名稱:{state['section'].name},描述:{state['section'].description}")
]
)
return {"completed_sections": [section.content]}
def synthesizer(state: State):
"""將各部分整合成完整報(bào)告"""
completed_report_sections = "\n\n---\n\n".join(state["completed_sections"])
return {"final_report": completed_report_sections}
# 條件邊函數(shù),為每個計(jì)劃部分分配工作者
def assign_workers(state: State):
"""為計(jì)劃中的每個部分分配工作者"""
return [Send("llm_call", {"section": s}) for s in state["sections"]]
# 構(gòu)建工作流
orchestrator_worker_builder = StateGraph(State)
# 添加節(jié)點(diǎn)
orchestrator_worker_builder.add_node("orchestrator", orchestrator)
orchestrator_worker_builder.add_node("llm_call", llm_call)
orchestrator_worker_builder.add_node("synthesizer", synthesizer)
# 添加邊連接節(jié)點(diǎn)
orchestrator_worker_builder.add_edge(START, "orchestrator")
orchestrator_worker_builder.add_conditional_edges(
"orchestrator", assign_workers, ["llm_call"]
)
orchestrator_worker_builder.add_edge("llm_call", "synthesizer")
orchestrator_worker_builder.add_edge("synthesizer", END)
# 編譯工作流
orchestrator_worker = orchestrator_worker_builder.compile()
# 顯示工作流
display(Image(orchestrator_worker.get_graph().draw_mermaid_png()))
# 調(diào)用
state = orchestrator_worker.invoke({"topic": "創(chuàng)建關(guān)于LLM擴(kuò)展規(guī)律的報(bào)告"})
# 顯示最終報(bào)告
from IPython.display import Markdown
Markdown(state["final_report"])
5. 評估器-優(yōu)化器(Evaluator-Optimizer)
在評估器-優(yōu)化器工作流中,一個LLM調(diào)用生成響應(yīng),另一個提供評估和反饋,并在循環(huán)中不斷優(yōu)化。
這種工作流特別適用于以下場景:當(dāng)我們有明確的評估標(biāo)準(zhǔn),并且迭代優(yōu)化能夠帶來顯著價(jià)值時(shí)。如果LLM的響應(yīng)可以在人類明確反饋后得到改進(jìn),并且LLM能夠提供這種反饋,那么這種工作流就非常適合。這類似于人類作家在撰寫一篇經(jīng)過精心打磨的文檔時(shí)所經(jīng)歷的迭代寫作過程。
例如:
- 文學(xué)翻譯中,翻譯LLM可能無法在一開始就捕捉到所有細(xì)微差別,但評估LLM可以提供有用的批評。
- 復(fù)雜的搜索任務(wù)需要多輪搜索和分析以收集全面信息,評估器決定是否需要進(jìn)一步搜索。
# 圖狀態(tài)
class State(TypedDict):
joke: str
topic: str
feedback: str
funny_or_not: str
# 用于評估的結(jié)構(gòu)化輸出模式
class Feedback(BaseModel):
grade: Literal["funny", "not funny"] = Field(descriptinotallow="判斷笑話是否有趣")
feedback: str = Field(descriptinotallow="如果笑話不好笑,提供改進(jìn)建議")
# 為LLM添加結(jié)構(gòu)化輸出模式
evaluator = llm.with_structured_output(Feedback)
# 節(jié)點(diǎn)
def llm_call_generator(state: State):
"""LLM生成笑話"""
if state.get("feedback"):
msg = llm.invoke(
f"根據(jù)反饋生成關(guān)于{state['topic']}的笑話:{state['feedback']}"
)
else:
msg = llm.invoke(f"生成關(guān)于{state['topic']}的笑話")
return {"joke": msg.content}
def llm_call_evaluator(state: State):
"""LLM評估笑話"""
grade = evaluator.invoke(f"評估笑話:{state['joke']}")
return {"funny_or_not": grade.grade, "feedback": grade.feedback}
# 條件邊函數(shù),根據(jù)評估器的反饋決定是否返回生成器或結(jié)束
def route_joke(state: State):
"""根據(jù)評估器的反饋決定是否返回生成器或結(jié)束"""
if state["funny_or_not"] == "funny":
return"Accepted"
elif state["funny_or_not"] == "not funny":
return"Rejected + Feedback"
# 構(gòu)建工作流
optimizer_builder = StateGraph(State)
# 添加節(jié)點(diǎn)
optimizer_builder.add_node("llm_call_generator", llm_call_generator)
optimizer_builder.add_node("llm_call_evaluator", llm_call_evaluator)
# 添加邊連接節(jié)點(diǎn)
optimizer_builder.add_edge(START, "llm_call_generator")
optimizer_builder.add_edge("llm_call_generator", "llm_call_evaluator")
optimizer_builder.add_conditional_edges(
"llm_call_evaluator",
route_joke,
{
"Accepted": END,
"Rejected + Feedback": "llm_call_generator"
}
)
# 編譯工作流
optimizer_workflow = optimizer_builder.compile()
# 顯示工作流
display(Image(optimizer_workflow.get_graph().draw_mermaid_png()))
# 調(diào)用
state = optimizer_workflow.invoke({"topic": "Cats"})
print(state["joke"])
三、代理(Agent):自主智能體的力量
代理通常被實(shí)現(xiàn)為LLM通過工具調(diào)用(基于環(huán)境反饋)在循環(huán)中執(zhí)行動作的系統(tǒng)。正如Anthropic博客所指出的,代理可以處理復(fù)雜的任務(wù),但其實(shí)現(xiàn)往往非常簡單。它們通常是LLM根據(jù)環(huán)境反饋使用工具的循環(huán)。因此,清晰且周到地設(shè)計(jì)工具集及其文檔至關(guān)重要。
什么時(shí)候使用代理?
代理適用于那些開放性問題,這些問題很難或無法預(yù)測所需的步驟數(shù)量,并且無法硬編碼固定路徑。LLM可能會運(yùn)行多個回合,因此你需要對其決策能力有一定的信任。代理的自主性使其非常適合在受信任的環(huán)境中擴(kuò)展任務(wù)。
然而,自主性也意味著更高的成本和可能出現(xiàn)的錯誤累積。因此,我們建議在沙盒環(huán)境中進(jìn)行廣泛的測試,并設(shè)置適當(dāng)?shù)姆雷o(hù)欄。
例如:
- 編程代理可以解決涉及對多個文件進(jìn)行編輯的任務(wù)。
- “計(jì)算機(jī)使用”參考實(shí)現(xiàn)中,Claude通過計(jì)算機(jī)完成任務(wù)。
from langchain_core.tools import tool
# 定義工具
@tool
def multiply(a: int, b: int) -> int:
"""乘法工具"""
return a * b
@tool
def add(a: int, b: int) -> int:
"""加法工具"""
return a + b
@tool
def divide(a: int, b: int) -> float:
"""除法工具"""
return a / b
# 為LLM綁定工具
tools = [add, multiply, divide]
tools_by_name = {tool.name: tool for tool in tools}
llm_with_tools = llm.bind_tools(tools)
四、結(jié)合與定制這些模式:實(shí)現(xiàn)最佳效果
AI代理和代理工作流是互補(bǔ)的,可以集成在一起以實(shí)現(xiàn)最佳效果,尤其是在復(fù)雜的現(xiàn)實(shí)世界應(yīng)用中。
(一)增強(qiáng)自動化
AI代理可以自主處理特定任務(wù),而代理工作流則將這些任務(wù)協(xié)調(diào)成一個連貫、高效的過程。
(二)可擴(kuò)展性
在結(jié)構(gòu)化工作流中結(jié)合多個AI代理,可以使組織高效擴(kuò)展運(yùn)營,減少人工工作量,提高生產(chǎn)力。
(三)彈性與適應(yīng)性
雖然單個代理可以應(yīng)對局部變化,但工作流可以動態(tài)調(diào)整整體流程,以與戰(zhàn)略目標(biāo)保持一致或適應(yīng)外部干擾。
(四)實(shí)際案例:制造業(yè)中的集成AI代理與工作流
在智能制造系統(tǒng)中:
- AI代理可以監(jiān)控設(shè)備性能、預(yù)測維護(hù)需求并優(yōu)化生產(chǎn)計(jì)劃。
- 代理工作流則負(fù)責(zé)原材料采購、生產(chǎn)排序、質(zhì)量保證和物流,確保從原材料到產(chǎn)品交付的無縫過渡。
五、總結(jié):選擇適合你的系統(tǒng)才是成功的關(guān)鍵
在LLM領(lǐng)域,成功并不是關(guān)于構(gòu)建最復(fù)雜的系統(tǒng),而是構(gòu)建最適合你需求的系統(tǒng)。從簡單的提示開始,通過全面評估進(jìn)行優(yōu)化,只有在簡單解決方案不足時(shí)才添加多步代理系統(tǒng)。
在實(shí)現(xiàn)代理時(shí),我們建議遵循以下三個核心原則:
- 保持代理設(shè)計(jì)的簡潔性:避免不必要的復(fù)雜性,專注于核心功能。
- 優(yōu)先考慮透明性:明確展示代理的規(guī)劃步驟,讓用戶清楚了解其決策過程。
- 精心設(shè)計(jì)代理-計(jì)算機(jī)接口(ACI):通過徹底的工具文檔和測試,確保代理與外部系統(tǒng)的無縫交互。
框架可以幫助你快速上手,但不要害怕在進(jìn)入生產(chǎn)階段時(shí)減少抽象層,直接使用基礎(chǔ)組件。遵循這些原則,你可以創(chuàng)建出不僅強(qiáng)大而且可靠、可維護(hù)且值得用戶信賴的代理系統(tǒng)。
在這個充滿可能性的AI時(shí)代,選擇合適的技術(shù)路徑并將其應(yīng)用于實(shí)際場景,才是實(shí)現(xiàn)智能化轉(zhuǎn)型的關(guān)鍵。希望這篇文章能幫助你在AI工作流與代理的世界中找到屬于你的方向,解鎖智能技術(shù)的無限可能。
本文轉(zhuǎn)載自公眾號Halo咯咯 作者:基咯咯
