多少網站域名采用中文四川全網推網絡推廣
該
example
來源于官方,主要用于快速了解LG 的基本使用,本文并沒有對 LG 的詳細說明,如果想要對他有深入認識可參考文章
該example
構建可視化出來的結果圖如下:
從圖中可以發(fā)現除了特殊節(jié)點
Start
和End
,還有一個agent
和tools
節(jié)點,在該graph
中執(zhí)行流程如下:
- 用戶輸入
- 節(jié)點名為
agent
首先響應然后調用節(jié)點名tools
tools
節(jié)點返回給agent
agent
判斷tools
結果是否符合預期,不符合繼續(xù)調用tools
,符合則走向End
節(jié)點,End
節(jié)點則認為graph
結束上述流程在代碼中有詳細介紹,讓我們跟著這個流程清晰認識 LG 的構建流程
1. Graph
整體流程定義
- 圖配置
此處可以定義圖的參數信息,例如 LLM 等信息
# Define the config
class GraphConfig(TypedDict):model_name: Literal["anthropic", "openai"]
- 圖定義
# 定義一個圖,StateGraph是我們主要使用圖定義的類,此處參數傳入
# 整個圖的狀態(tài)以及圖配置信息
workflow = StateGraph(AgentState, config_schema=GraphConfig)# 在該圖中可以體現cycle為此處,即大模型與工具的交互
# 嚴謹一些講應該是大模型參與的角色就可能有交互,這也是LG的最大意義
# 為了可以實現更好的應用效果,我們需要通過大模型的加入,但是大模型的加入
# 又會存在一些不確定性(如果只是傳統(tǒng)的方法,程序輸入輸出是一種固定式的,那就不太需要 LG 的存在了,我們自己代碼就可以去實現)
# LLM 對問題的理解,構建調用工具的提示詞,對工具結果的判斷理解等等
# 因此 Agent十分依賴大模型的能力
workflow.add_node("agent", llm_node)
workflow.add_node("action", tool_node)# set_entry_point定義了首先響應的節(jié)點是agent
workflow.set_entry_point("agent")# 圖中除了節(jié)點,節(jié)點之間的邊也至關重要,這影響到節(jié)點之間的邏輯關系
# 邊我們已經講到過存在普通邊和條件邊,對于條件邊定義方法為add_conditional_edges
workflow.add_conditional_edges(# agent節(jié)點為該邊的起始節(jié)點,也說明該邊的執(zhí)行是在agent節(jié)點執(zhí)行后"agent",# 定義映射條件should_continue,# 定義映射關系,key為字符串(自己定義即可),value為其他節(jié)點# should_continue的輸出將匹配映射關系,從而控制了該邊的走向,即在agent之后執(zhí)行哪個節(jié)點{# 如果should_continue輸出是continue,則調用action節(jié)點"continue": "action",# 如果should_continue輸出是end,則調用END節(jié)點"end": END,},
)# 剛才我們定義了條件邊,控制了agent節(jié)點走向 action或者 end的邏輯關系
# 現在我們定義從action響應之后,將其直接返回給agent,這也意味著action響應之后會直接走向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定義內容在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í)行過程中必要地方可以調用該工具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 搜索相關的任務
# max_results限制了最大返回結果數量
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]
這次已經完成了一個
example
的學習