自主代理與大語言模型(LLM)的結合,為複雜任務的自動化處理提供了新的解決方案。LLM賦予代理理解和生成文字的能力,而代理則為LLM提供了與環境互動的途徑。本文重點介紹ReAct框架,它是一種增強LLM回應能力的代理框架,允許LLM在採取行動後觀察結果,並根據觀察結果調整後續步驟。此方法透過迭代式的思考迴圈,有效地解決了複雜問題,並提高了LLM在特定任務上的表現。此外,正規表示式在解析LLM輸出中扮演著關鍵角色,它能夠精確地提取關鍵資訊,例如動作和動作輸入,從而實作更精細的控制和流程自動化。

自主代理與大語言模型(LLM)的協同運作

在探討自主代理(Agents)與大語言模型(LLM)如GPT的整合應用時,我們需要了解自主代理的基本構成及其在LLM中的特殊表現形式。自主代理是一種能夠感知環境、做出決策並採取行動以達成預設目標的實體。在LLM的背景下,這些代理透過文字輸入進行互動,利用LLM的強大處理能力來執行複雜任務。

自主代理的核心組成要素

  1. 輸入(Inputs):代理接收來自環境的資料或訊號,這些輸入可以是多樣化的,包括文字、影像、音訊等。在LLM的場景中,輸入主要透過文字形式呈現,但可以透過適當的轉換(如影片的文字轉錄)來處理多模態資料。

  2. 目標或獎勵函式(Goal or Reward Function):這定義了代理的行為準則。在根據目標的框架中,代理旨在達到特定的終態;在根據獎勵的設定中,代理則試圖最大化累積獎勵。例如,無人駕駛汽車的主要目標是安全有效地從A點導航到B點,其獎勵函式可能與保持安全距離、遵守速度限制和遵循交通規則相關。

  3. 可用行動(Available Actions):這指的是代理在任何給定時刻可以採取的操作範圍。對於無人駕駛汽車來說,可用行動包括加速、減速、轉向、變換車道等。在LLM中,可用行動可以透過整合現成的工具或自定義開發的工具來擴充套件,例如API呼叫、資料函式庫互動或外部系統的協調。

LLM中的自主代理

在LLM的背景下,自主代理的概念被重新詮釋以適應文字驅動的互動模式。這包括:

  • 透過文字輸入進行互動:LLM主要透過文字提示來接收輸入和提供輸出。這要求將多樣化的資料轉換為適合LLM處理的文字表示形式。

  • 利用目標驅動的指令:透過精心設計的提示,LLM能夠解析複雜目標並將其分解為系統性的步驟,從而指導模型達到預期的結果。

  • 透過功能性工具實作行動:LLM不僅限於文字生成,還可以透過整合各種工具來執行多樣化的任務,從而擴充套件其行動空間。

ReAct框架:一種增強LLM回應的代理框架

ReAct框架是原始的CoT(Chain-of-Thought)方法的改進版本,允許LLM在採取行動後建立觀察結果,並根據這些觀察結果決定下一步驟。這個過程持續進行,直到達到最終答案或達到最大迭代次數為止。

ReAct框架的工作原理

  1. 初始提示:提供一個初始提示給LLM,定義任務目標。

  2. 行動與觀察:LLM根據提示採取行動(例如,呼叫工具),並觀察結果。

  3. 迭代過程:根據觀察結果,LLM決定下一步的行動,直到達成最終答案或達到停止條件。

ReAct框架展示瞭如何透過自主代理與LLM的結合來增強模型的回應能力和執行複雜任務的能力。這種方法不僅提高了LLM在特定任務上的表現,也為開發更為智慧和自主的系統提供了新的途徑。

技術深度探討

在實作自主代理與LLM的整合時,開發者需要考慮以下幾個技術層面的挑戰:

  1. 輸入資料的多樣性處理:如何有效地將不同型別的資料轉換為LLM可以理解的文字格式。

  2. 目標和獎勵函式的定義:如何設計有效的目標或獎勵機制,以引導LLM朝著預期的方向發展。

  3. 擴充套件LLM的行動空間:透過整合更多的工具和功能,來增強LLM執行多樣化任務的能力。

程式碼範例:ReAct框架的基本實作

def react_framework(llm, initial_prompt, max_iterations=10):
    current_prompt = initial_prompt
    iteration = 0
    
    while iteration < max_iterations:
        action = llm.get_action(current_prompt)
        observation = execute_action(action)
        
        if is_final_answer(observation):
            return observation
        
        current_prompt = update_prompt(current_prompt, action, observation)
        iteration += 1
    
    return "Maximum iterations reached."

# #### 內容解密:
# 此程式碼範例展示了ReAct框架的基本實作邏輯。首先,它定義了一個函式`react_framework`,該函式接受一個LLM例項、初始提示和最大迭代次數作為引數。然後,它進入一個迴圈,在每次迭代中,LLM根據當前提示採取行動,並觀察結果。如果觀察結果是最終答案,則傳回;否則,更新提示並繼續下一次迭代,直到達到最大迭代次數。


## ReAct框架的深入解析與實作

ReAct框架結合任務分解思考迴圈及多工具運用來解決複雜問題本文將探討ReAct框架的核心概念及其Python實作

### ReAct的思考迴圈機制

ReAct的核心在於其思考迴圈thought loop),這個過程包括以下步驟

1. **觀察環境**接收並理解輸入的問題或環境資訊
2. **解釋環境**根據觀察結果進行思考和分析
3. **決定行動**選擇適當的工具或行動方案
4. **執行行動**使用選定的工具或方法來執行決定的行動
5. **重複迴圈**持續執行上述步驟直到找到解決方案或達到迭代次數上限

#### 實務應用中的思考迴圈範例

在實際應用中思考迴圈可能涉及多個不同的工具和複雜的決策過程以下是一個簡化的範例來說明這個過程

1. **觀察原始問題**理解輸入的問題內容
2. **產生觀察結果**根據對問題的理解產生初步的觀察結果
3. **形成思考**根據觀察結果進行深入的思考和分析
4. **選擇並執行行動**利用可用的工具來執行決定的行動
5. **評估結果並重複**根據執行動動後的結果進行評估並決定是否需要重複迴圈

### ReAct提示詞的設計

要實作ReAct框架需要精心設計提示詞prompt來引導大語言模型LLM按照預定的思考迴圈進行問題解決一個典型的ReAct提示詞包含以下元素

- **問題陳述**明確需要解決的問題
- **可用工具**列出可以使用的工具及其功能描述
- **思考迴圈指示**引導LLM按照觀察思考行動的步驟進行問題解決

#### ReAct提示詞範例

```plaintext
你將嘗試解決找到問題答案的任務使用鏈式思考推理來解決問題遵循以下模式
1. 觀察原始問題original_question: 原始問題文字
2. 建立觀察結果observation: 觀察結果文字
3. 根據觀察結果建立思考thought: 思考文字
4. 使用工具對思考採取行動action: 工具名稱action_input: 工具輸入

不要猜測或假設工具的結果相反提供一個結構化的輸出包括action和action_input
你有權存取以下工具{tools}
原始問題{question}

根據提供的工具結果
要麼提供下一個觀察結果actionaction_input要麼提供最終答案如果可用)。
如果您提供最終答案則必須傳回以下模式
"我已找到答案:最終答案"

ReAct的Python實作

為了更好地理解ReAct框架的工作原理,我們可以建立一個簡化的Python實作。這個實作將重點放在提取LLM回應中的action和action_input。

程式碼實作

import re

def extract_action_and_input(text):
    # 編譯正規表示式模式
    action_pattern = re.compile(r"(?i)action\s*:\s*([^\n]+)", re.MULTILINE)
    action_input_pattern = re.compile(r"(?i)action\s*_*input\s*:\s*([^\n]+)", re.MULTILINE)

    # 查詢所有action和action_input的出現
    actions = action_pattern.findall(text)
    action_inputs = action_input_pattern.findall(text)

    # 提取最後一次出現的action和action_input
    last_action = actions[-1] if actions else None
    last_action_input = action_inputs[-1] if action_inputs else None

    return last_action, last_action_input

# 範例文字
text = """
Action: search_on_google
Action_Input: Tom Hanks's current wife
action: search_on_wikipedia
action_input: How old is Rita Wilson in 2023
action : search_on_google
action input: some other query
"""

last_action, last_action_input = extract_action_and_input(text)
print("Last Action:", last_action)
print("Last Action Input:", last_action_input)

#### 內容解密:

此段程式碼主要功能是從給定的文字中提取最後一次出現的actionaction_input。首先,我們使用正規表示式來匹配文字中的actionaction_input模式。然後,透過findall方法查詢所有匹配的結果。最後,提取最後一次匹配的actionaction_input並傳回。

  1. import re:匯入Python的正規表示式模組,用於模式匹配。
  2. extract_action_and_input函式:定義了一個函式來提取actionaction_input
    • 使用re.compile編譯兩個正規表示式模式,分別用於匹配actionaction_input
    • 使用findall方法在給定文字中查詢所有匹配的結果。
    • 傳回最後一次匹配的actionaction_input
  3. 範例文字:提供了一個包含多個actionaction_input的示例文字,用於測試函式功能。

Mermaid圖表示例

  graph LR
    A[開始] --> B[觀察原始問題]
    B --> C[建立觀察結果]
    C --> D[根據觀察結果建立思考]
    D --> E[使用工具對思考採取行動]
    E --> F[評估結果]
    F -->|需要重複| B
    F -->|已找到答案| G[提供最終答案]
    G --> H[結束]

圖表翻譯:

此圖表呈現了ReAct框架的思考迴圈流程。首先,從觀察原始問題開始,然後建立觀察結果。接著,根據觀察結果進行深入思考,並使用適當的工具採取行動。完成行動後,評估結果以決定是否需要重複迴圈或已找到最終答案。如果需要重複,則回到觀察階段;如果已找到答案,則提供最終答案並結束流程。

正規表示式在大語言模型(LLM)輸出解析中的應用

在處理大語言模型(LLM)的輸出時,經常需要解析複雜的文字結構以提取關鍵資訊。正規表示式(Regular Expression, Regex)是實作此目標的有效工具。本文將探討正規表示式在LLM輸出解析中的具體應用,特別是在提取動作(action)和動作輸入(action_input)等資訊方面的實踐。

正規表示式基礎

在探討具體應用之前,我們先簡要回顧正規表示式的基礎知識。正規表示式是一種強大的文書處理工具,能夠對字串進行搜尋、匹配和提取操作。其基本構成包括:

  1. 文字匹配:直接匹配指定的文字。
  2. 特殊字元:如 .^$[]()|?*+{} 等,具有特殊含義。
  3. 字元類別:如 \s(空白字元)、\w(單詞字元)、\d(數字字元)等,用於匹配特定類別的字元。
  4. 重複符號:如 *(零次或多次)、+(一次或多次)、?(零次或一次)等,用於指定匹配的重複次數。

解析LLM輸出的正規表示式模式

在LLM輸出的解析中,我們經常需要提取特定的資訊,如動作(action)和動作輸入(action_input)。以下是一個典型的正規表示式模式,用於匹配這類別資訊:

action_pattern = re.compile(r"(?i)action\s*:\s*([^\n]+)", re.MULTILINE)
action_input_pattern = re.compile(r"(?i)action\s*_*input\s*:\s*([^\n]+)", re.MULTILINE)

模式解析

  1. (?i):這是一個內嵌標誌,表示後續的模式匹配是大小寫不敏感的。

    • 作用:確保能夠匹配不同大小寫形式的「action」或「action_input」。
  2. actionaction\s*_*input:這兩個部分分別匹配文字「action」和「action_input」。

    • \s*_*:匹配零個或多個空白字元和下劃線,確保能夠處理格式上的變化。
  3. \s*:\s*:匹配冒號前後的零個或多個空白字元。

    • 作用:容忍冒號周圍可能出現的空白字元。
  4. ([^\n]+):捕捉組,用於提取冒號後直到行尾的內容。

    • [^\n]:匹配任何非換行符的字元。
    • +:表示至少匹配一個字元。
  5. re.MULTILINE:使 ^$ 匹配每一行的開始和結束,而不僅僅是整個字串的開始和結束。

實作範例

下面是一個完整的Python函式,利用上述正規表示式模式來提取LLM輸出中的最後一個動作和動作輸入:

import re

def extract_last_action_and_input(text):
    # 編譯正規表示式模式
    action_pattern = re.compile(r"(?i)action\s*:\s*([^\n]+)", re.MULTILINE)
    action_input_pattern = re.compile(r"(?i)action\s*_*input\s*:\s*([^\n]+)", re.MULTILINE)
    
    # 查詢所有符合的動作和動作輸入
    actions = action_pattern.findall(text)
    action_inputs = action_input_pattern.findall(text)
    
    # 提取最後一個符合的動作和動作輸入
    last_action = actions[-1] if actions else None
    last_action_input = action_inputs[-1] if action_inputs else None
    
    return {"action": last_action, "action_input": last_action_input}

# 示例文字
text = """
action: search_on_google
action_input: some query
...
action: search_on_google
action_input: some other query
"""

# 提取資訊
result = extract_last_action_and_input(text)
print(result)  # {'action': 'search_on_google', 'action_input': 'some other query'}

程式碼解說

  1. extract_last_action_and_input 函式

    • 接收一個文字字串 text 作為輸入。
    • 使用 re.compile 編譯兩個正規表示式模式,分別用於匹配「action」和「action_input」。
  2. findall 方法

    • 對輸入的 text 使用編譯好的模式進行全部匹配,傳回所有符合條件的字串列表。
  3. 提取最後一個匹配結果

    • actionsaction_inputs 列表中提取最後一個元素,若列表為空則傳回 None
  4. 傳回結果

    • 以字典形式傳回最後一個「action」和「action_input」。

處理正規表示式解析錯誤

由於LLM的輸出可能不完全符合預期,正規表示式解析可能會遇到錯誤。常見的處理方法包括:

  1. 使用LLM修正前一次的輸出:將解析錯誤的輸出回饋給LLM,讓其進行修正。
  2. 發起新的LLM請求:根據前一次的狀態,重新生成輸出。

這些方法能夠提高系統的穩健性,確保在面對不確定性輸出時仍能有效運作。

結合其他元件實作完整功能

在實際應用中,我們通常需要結合多個元件來實作完整的功能。例如,利用 ChatOpenAI 進行模型互動,並定義可用的工具集:

from langchain_openai.chat_models import ChatOpenAI
from langchain.prompts.chat import SystemMessagePromptTemplate

# 初始化 ChatOpenAI 例項
chat = ChatOpenAI(model_kwargs={"stop": ["tool_result:"]})

# 定義可用工具
tools = {
    "search_on_google": {
        "function": lambda query: f"Jason Derulo doesn't have a wife or partner.",
        "description": "Searches on google for a query",
    }
}

# 設定基礎提示範本
base_prompt = """
You will attempt to solve the problem of finding the answer to a question.
...
"""

# 生成模型輸出
output = chat.invoke(SystemMessagePromptTemplate.from_template(template=base_prompt).format_messages(tools=tools, question="Is Jason Derulo with a partner?"))
print(output)

#### 內容解密:

此段程式碼展示瞭如何結合 ChatOpenAI 和正規表示式解析來實作完整的LLM輸出處理流程。首先,定義了一個 ChatOpenAI 例項,並設定停止序列以避免無謂的生成。接著,定義了可用的工具集及其描述。然後,利用 SystemMessagePromptTemplate 設定提示範本,並將工具集和問題傳入模型進行生成。最終輸出模型的回應結果。透過這種方式,可以有效地引導LLM生成結構化的輸出,便於後續的正規表示式解析。

正規表示式在LLM輸出解析中的流程圖示
  graph LR;
    A[接收LLM輸出] --> B[編譯正規表示式模式];
    B --> C[執行正規表示式匹配];
    C --> D[提取關鍵資訊];
    D --> E[處理解析錯誤];
    E --> F[傳回解析結果];

圖表翻譯: 此圖示展示了使用正規表示式解析LLM輸出的流程。首先接收LLM生成的文字輸出,然後編譯適當的正規表示式模式,接著執行匹配操作以提取所需的結構化資訊。若遇到解析錯誤,則進行相應的錯誤處理。最終,將解析得到的資訊以結構化的形式傳回,供後續應用使用。透過這個流程,能夠有效地從LLM的非結構化輸出中抽取出有價值的資料。