多少網(wǎng)站域名采用中文四川全網(wǎng)推網(wǎng)絡(luò)推廣
該
example
來源于官方,主要用于快速了解LG 的基本使用,本文并沒有對 LG 的詳細(xì)說明,如果想要對他有深入認(rèn)識可參考文章
該example
構(gòu)建可視化出來的結(jié)果圖如下:
從圖中可以發(fā)現(xiàn)除了特殊節(jié)點
Start
和End
,還有一個agent
和tools
節(jié)點,在該graph
中執(zhí)行流程如下:
- 用戶輸入
- 節(jié)點名為
agent
首先響應(yīng)然后調(diào)用節(jié)點名tools
tools
節(jié)點返回給agent
agent
判斷tools
結(jié)果是否符合預(yù)期,不符合繼續(xù)調(diào)用tools
,符合則走向End
節(jié)點,End
節(jié)點則認(rèn)為graph
結(jié)束上述流程在代碼中有詳細(xì)介紹,讓我們跟著這個流程清晰認(rèn)識 LG 的構(gòu)建流程
1. Graph
整體流程定義
- 圖配置
此處可以定義圖的參數(shù)信息,例如 LLM 等信息
# Define the config
class GraphConfig(TypedDict):model_name: Literal["anthropic", "openai"]
- 圖定義
# 定義一個圖,StateGraph是我們主要使用圖定義的類,此處參數(shù)傳入
# 整個圖的狀態(tài)以及圖配置信息
workflow = StateGraph(AgentState, config_schema=GraphConfig)# 在該圖中可以體現(xiàn)cycle為此處,即大模型與工具的交互
# 嚴(yán)謹(jǐn)一些講應(yīng)該是大模型參與的角色就可能有交互,這也是LG的最大意義
# 為了可以實現(xiàn)更好的應(yīng)用效果,我們需要通過大模型的加入,但是大模型的加入
# 又會存在一些不確定性(如果只是傳統(tǒng)的方法,程序輸入輸出是一種固定式的,那就不太需要 LG 的存在了,我們自己代碼就可以去實現(xiàn))
# LLM 對問題的理解,構(gòu)建調(diào)用工具的提示詞,對工具結(jié)果的判斷理解等等
# 因此 Agent十分依賴大模型的能力
workflow.add_node("agent", llm_node)
workflow.add_node("action", tool_node)# set_entry_point定義了首先響應(yīng)的節(jié)點是agent
workflow.set_entry_point("agent")# 圖中除了節(jié)點,節(jié)點之間的邊也至關(guān)重要,這影響到節(jié)點之間的邏輯關(guān)系
# 邊我們已經(jīng)講到過存在普通邊和條件邊,對于條件邊定義方法為add_conditional_edges
workflow.add_conditional_edges(# agent節(jié)點為該邊的起始節(jié)點,也說明該邊的執(zhí)行是在agent節(jié)點執(zhí)行后"agent",# 定義映射條件should_continue,# 定義映射關(guān)系,key為字符串(自己定義即可),value為其他節(jié)點# should_continue的輸出將匹配映射關(guān)系,從而控制了該邊的走向,即在agent之后執(zhí)行哪個節(jié)點{# 如果should_continue輸出是continue,則調(diào)用action節(jié)點"continue": "action",# 如果should_continue輸出是end,則調(diào)用END節(jié)點"end": END,},
)# 剛才我們定義了條件邊,控制了agent節(jié)點走向 action或者 end的邏輯關(guān)系
# 現(xiàn)在我們定義從action響應(yīng)之后,將其直接返回給agent,這也意味著action響應(yīng)之后會直接走向agent節(jié)點
workflow.add_edge("action", "agent")
- 圖編譯
# 編譯圖,意味著他會編譯成LangChain可運行程序
graph = workflow.compile()
- 條件邊
def should_continue(state):messages = state["messages"]last_message = messages[-1]# If there are no tool calls, then we finishif not last_message.tool_calls:return "end"# Otherwise if there is, we continueelse:return "continue"
2. 節(jié)點定義
agent
節(jié)點
@lru_cache(maxsize=4)
def _get_model(model_name: str):
# model_name定義內(nèi)容在GraphConfig有定義if model_name == "openai":model = ChatOpenAI(temperature=0, model_name="gpt-4o")elif model_name == "anthropic":model = ChatAnthropic(temperature=0, model_name="claude-3-sonnet-20240229")else:raise ValueError(f"Unsupported model type: {model_name}")# 表示模型在執(zhí)行過程中必要地方可以調(diào)用該工具model = model.bind_tools(tools)return modelsystem_prompt = """Be a helpful assistant"""# Define the function that calls the model
def llm_node(state, config):
# 獲取輸入信息messages = state["messages"]messages = [{"role": "system", "content": system_prompt}] + messagesmodel_name = config.get('configurable', {}).get("model_name", "anthropic")model = _get_model(model_name)response = model.invoke(messages)# We return a list, because this will get added to the existing listreturn {"messages": [response]}
- 工具節(jié)點
from langchain_community.tools.tavily_search import TavilySearchResults# 用于執(zhí)行與 Tavily 搜索相關(guān)的任務(wù)
# max_results限制了最大返回結(jié)果數(shù)量
tools = [TavilySearchResults(max_results=1)]# Define the function to execute tools
tool_node = ToolNode(tools)
- 狀態(tài)定義
from langgraph.graph import add_messages
from langchain_core.messages import BaseMessage
from typing import TypedDict, Annotated, Sequenceclass AgentState(TypedDict):
# 描述了一個包含 messages 字段的字典,其中 messages 是一個消息列表,
# 類型為 BaseMessage,并且有額外的注釋 add_messagesmessages: Annotated[Sequence[BaseMessage], add_messages]
這次已經(jīng)完成了一個
example
的學(xué)習(xí)