Try   HackMD

AI / ML領域相關學習筆記入口頁面

Deeplearning.ai GenAI/LLM系列課程筆記

GenAI
RAG
AI Agents

原理可參考這篇綜論: How Agents for LLM Perform Task Planning。大型語言模型的代理如何進行任務規劃


AI Agents in LangGraph


LanaGraph Components。 LanaGraph組件

回顧上一小節的流程

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

  • LangChain的PromptTemplate
    • hub/hwchase17/react
    • 使用方式
      ​​​​​​​​# set the LANGCHAIN_API_KEY environment variable (create key in settings) ​​​​​​​​from langchain import hub ​​​​​​​​prompt = hub.pull("hwchase17/react")
    • 提示模板
      • {tools}可動態帶入指定工具
        • [{tool_names}]
      ​​​​​​​​Answer the following questions as best you can. You have access to the following tools: ​​​​​​​​{tools} ​​​​​​​​Use the following format: ​​​​​​​​Question: the input question you must answer ​​​​​​​​Thought: you should always think about what to do ​​​​​​​​Action: the action to take, should be one of [{tool_names}] ​​​​​​​​Action Input: the input to the action ​​​​​​​​Observation: the result of the action ​​​​​​​​... (this Thought/Action/Action Input/Observation can repeat N times) ​​​​​​​​Thought: I now know the final answer ​​​​​​​​Final Answer: the final answer to the original input question ​​​​​​​​Begin! ​​​​​​​​Question: {input} ​​​​​​​​Thought:{agent_scratchpad}

LangChain: Tools

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

  • 從langchain_community中調用tools
# get a tool from the library from langchain_community.tools.tavily_search import \ TavilySearchResults tool = TavilySearchResults(max_results=2) self.tools = {t.name: t for t in tools} self.model = model.bind_tools([tool])

New in LangGraph

  • Cyclic Graphs
  • Persistence
  • Human-in-the-loop

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

  • LangGraph is an extension of LangChain that supports graphs.
  • Single and Multi-agent flows are described and represented as graphs.
  • Allows for extremely controlled “flows”
  • Built-in persistence allows for human-in-the-loop workflows

Graph 基本組件

  • Nodes。節點: 代理或功能
  • Edges。邊: 連接節點
  • Conditional edges。條件邊: 決定
    Image Not Showing Possible Reasons
    • The image was uploaded to a note which you don't have access to
    • The note which the image was originally uploaded to has been deleted
    Learn More →
  • 極簡範例
    Image Not Showing Possible Reasons
    • The image was uploaded to a note which you don't have access to
    • The note which the image was originally uploaded to has been deleted
    Learn More →

Data/State

  • 代理狀態可被圖的所有部分訪問
    Agent state Is accessible to all parts of the graph
  • 是圖的本地狀態
    it is local to the graph
  • 可存儲在持久層中
    Can be stored in a persistence layer

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

  • 範例

    ​​​​# Simple ​​​​class AgentState(TypedDict): ​​​​ messages: Annotated[Sequence[BaseMessage], operator.add] ​​​​# Complex ​​​​class AgentState(TypedDict): ​​​​ input: str ​​​​ chat_history: list[BaseMessage] ​​​​ agent_outcome: Union[AgentAction, AgentFinish, None] ​​​​ intermediate_steps: Annotatedf[list[tuple[AgentAction, str]], operator.add]
    • Simple 範例

      • messages 欄位被更新時,它不是覆蓋原來的值,而是將新的消息添加到已有的消息中。 通過 Annotatedoperator.add 來實現的。
    • Complex 範例

      • 更複雜的 AgentState 結構,包括 inputchat_historyagent_outcomeintermediate_steps
      • inputchat_historyagent_outcome 這三個欄位都沒有進行特別的註釋,這意味著當這些欄位被更新時,新值會覆蓋現有的值
      • 唯一例外的是 intermediate_steps 欄位,它被註釋了 operator.add,這意味著當更新這個欄位時,新的值會添加到現有的值中,而不是覆蓋它
      • 為什麼 intermediate_steps 要添加而不是覆蓋
        • intermediate_steps 欄位被設計為追蹤代理行動和觀察的過程
        • 這些步驟在代理執行過程中不斷累加,所以每次更新時需要將新步驟添加到現有步驟中,而不是覆蓋掉
        • 保留完整的執行記錄,幫助追蹤代理的行動和決策過程

      類似RL中記錄所有STATE

  • State

    Image Not Showing Possible Reasons
    • The image was uploaded to a note which you don't have access to
    • The note which the image was originally uploaded to has been deleted
    Learn More →

Lab 使用LangGraph進行Agent設計實作

這個範例Agent類別的主要功能是處理LLM與外部工具的互動。它使用狀態機(State)來管理調用流程,確保在發現錯誤(例如無效的工具名稱)時能夠適當處理並進行重試。整體流程是:

  1. 使用模型生成訊息。
  2. 檢查訊息中是否有工具調用。
  3. 執行工具調用或重新請求模型生成訊息
  4. 重複此流程直到結束。
class Agent: def __init__(self, model, tools, system=""): self.system = system graph = StateGraph(AgentState) graph.add_node("llm", self.call_openai) graph.add_node("action", self.take_action) graph.add_conditional_edges( "llm", self.exists_action, {True: "action", False: END} ) graph.add_edge("action", "llm") graph.set_entry_point("llm") self.graph = graph.compile() self.tools = {t.name: t for t in tools} self.model = model.bind_tools(tools) def exists_action(self, state: AgentState): result = state['messages'][-1] return len(result.tool_calls) > 0 def call_openai(self, state: AgentState): messages = state['messages'] if self.system: messages = [SystemMessage(content=self.system)] + messages message = self.model.invoke(messages) return {'messages': [message]} def take_action(self, state: AgentState): tool_calls = state['messages'][-1].tool_calls results = [] for t in tool_calls: print(f"Calling: {t}") if not t['name'] in self.tools: # check for bad tool name from LLM print("\n ....bad tool name....") result = "bad tool name, retry" # instruct LLM to retry if bad else: result = self.tools[t['name']].invoke(t['args']) results.append(ToolMessage(tool_call_id=t['id'], name=t['name'], content=str(result))) print("Back to the model!") return {'messages': results}
  1. 類別初始化 (__init__ 方法)
  • 參數

    • model: LLM模型,用於生成回應。
    • tools: 一個工具列表,這些工具可以被LLM調用。
    • system: (可選)系統訊息,作為對話的一部分提供給模型。
  • 初始化

    • 設定system參數為類別屬性。
    • 建立StateGraph對象來管理代理的狀態和行為。這是一個狀態機,用於控制代理的流程。
    • 向狀態圖中添加節點和邊:
      • 節點 "llm":調用OpenAI模型的函數call_openai
      • 節點 "action":執行工具調用的函數take_action
      • 條件邊:從"llm"節點到"action"節點,當exists_action返回True時,進行此轉換;如果返回False,則結束(END)。
      • 邊:從"action"節點回到"llm"節點。
    • 設定進入點為"llm"
    • 將狀態圖編譯為可執行形式並儲存至self.graph
    • 將工具轉換為字典格式,儲存在self.tools中。
    • 將模型與工具綁定,儲存在self.model中。
  1. 方法 exists_action
  • 用途:檢查模型生成的最後一個訊息中是否存在工具調用。
  • 邏輯
    • 取得最後一條訊息result
    • 如果result中包含工具調用,返回True,否則返回False
  1. 方法 call_openai
  • 用途:調用OpenAI模型並返回其輸出。
  • 邏輯
    • 構建訊息列表,將system訊息(如果存在)添加到訊息序列的最前面。
    • 調用模型,傳入這些訊息,並取得模型回應。
    • 返回字典,包含模型生成的新訊息。
  1. 方法 take_action
  • 用途:執行LLM請求的工具調用,並返回結果。
  • 邏輯
    • 取得最後一條訊息中的所有工具調用。
    • 初始化results列表來儲存每個工具調用的結果。
    • 對每個工具調用進行迭代:
      • 檢查工具名稱是否存在於self.tools中。
      • 如果名稱無效,回傳"bad tool name, retry",並要求LLM重試。
      • 如果名稱有效,調用相應的工具並傳入參數。
      • 將每個工具調用的結果儲存為ToolMessage對象,並添加到results列表中。
    • 返回包含這些結果訊息的字典。
prompt = """You are a smart research assistant. Use the search engine to look up information. \ You are allowed to make multiple calls (either together or in sequence). \ Only look up information when you are sure of what you want. \ If you need to look up some information before asking a follow up question, you are allowed to do that! """ model = ChatOpenAI(model="gpt-3.5-turbo") #reduce inference cost abot = Agent(model, [tool], system=prompt) messages = [HumanMessage(content="What is the weather in sf?")] result = abot.graph.invoke({"messages": messages})
# Note, the query was modified to produce more consistent results. # Results may vary per run and over time as search information and models change. query = "Who won the super bowl in 2024? In what state is the winning team headquarters located? \ What is the GDP of that state? Answer each question." messages = [HumanMessage(content=query)] model = ChatOpenAI(model="gpt-4o") # requires more advanced model abot = Agent(model, [tool], system=prompt) result = abot.graph.invoke({"messages": messages})
  • 繪製graph流程簡圖
from IPython.display import Image Image(abot.graph.get_graph().draw_png())

image

class Agent的mermaid詳細邏輯流程圖

Model Response
True
False
Valid
Invalid
Return to LLM
llm: call_openai
exists_action
action: take_action
END
Check Tool Name
Invoke Tool
Return 'bad tool name, retry'
ToolMessage: ToolCallResult