🍣

自分で答えて自分でツッコミ!リフレクションエージェントとは

2024/02/22に公開

エージェントに過去の行動を振り返りさせることでブラッシュアップする手法だそうです。
プログラム合成や多段階の推論まで、幅広く成果が見られるとのこと。

https://twitter.com/LangChainAI/status/1760327384098898412

最もシンプルなものから複雑なもので3パターンあります。

  • Simple Reflection
  • Reflexion(↑とつづりが違う)
  • Language Agents Tree Search

Simple Reflection

一番シンプルなリフレクションエージェント。
ジェネレーターとリフレクターという2つのLLMコールがある。

  • ジェネレーターは回答を生成する
  • リフレクターは教師として、その回答に建設的な批評をする
    一定回数それを繰り返し、最後の回答だけ出力する。


最もシンプルな例の図。ジェネレーター脳が生成した回答をリフレクター脳が批判・メリット・提案を並べて評価している

プロンプト

新しい情報を使って前回の解答を修正する。
    - 前回の講評を参考に、重要な情報を追加してください。
        - 修正した答案には、確実に検証できるように数値引用を含めなければなりません。
        - 解答の一番下に「参考文献」セクションを追加してください(制限字数にはカウントされません)。例:
            - 1] https://example.com
            - 2] https://example.com
    - 前回の講評を参考に、余計な情報を削除し、250語以内にまとめてください。

実装

from langgraph.graph import MessageGraph
builder = MessageGraph()
builder.add_node("generate", generation_node)
builder.add_node("reflect", reflection_node)
builder.set_entry_point("generate")
def should_continue(state: List[BaseMessage]):
    if len(state) > 6:
        return END
    return "reflect"
builder.add_conditional_edges("generate", should_continue)
builder.add_edge("reflect", "generate")
graph = builder.compile()

全コードはこちら
星の王子さまの感想文が最終的にやたらレベルの高い文章になってる。

Reflexion

今度は応答の生成と反省を一つのアクターが行う。
Toolsを使ってチャット履歴を持つのと、引用元を明確にするところがSimple Reflectionとの違い。

ツール/ツールの実行
初期応答者(Initial responder):初期応答(と自己反省)を生成する。
再検討者(Revisor):以前の反省に基づいて再反応(と反省)を行う

from langgraph.graph import END, MessageGraph

MAX_ITERATIONS = 5
builder = MessageGraph()
builder.add_node("draft", first_responder.respond)
builder.add_node("execute_tools", execute_tools)
builder.add_node("revise", revisor.respond)
# draft -> execute_tools
builder.add_edge("draft", "execute_tools")
# execute_tools -> revise
builder.add_edge("execute_tools", "revise")

# Define looping logic:
def event_loop(state: List[BaseMessage]) -> str:
    # in our case, we'll just stop after N plans
    num_iterations = _get_num_iterations(state)
    if num_iterations > MAX_ITERATIONS:
        return END
    return "execute_tools"


# revise -> execute_tools OR end
builder.add_conditional_edges("revise", event_loop)
builder.set_entry_point("draft")
graph = builder.compile()

こんなフィードバックが得られる

'reflection':
{'missing': '前回の回答には、AIにおけるリフレクションの利点を説明する具体例やケーススタディが欠けていた。そのような例を含めることで、概念とその応用についてより具体的な理解が得られるだろう
superfluous': '最初の回答は包括的であったが、具体的な事例のない大まかな概要ではなく、AIにおけるリフレクションの実用的な応用と利点を示す直接的な事例があったほうがよい}

全コードはこちら

Language Agents Tree Search

ごめんなさい、CSの知識が足りなくてこれはよくわからなかった…

from langgraph.graph import END, StateGraph

class Node:
    def __init__(
        self,
        messages: List[BaseMessage],
        reflection: Reflection,
        parent: Optional[Node] = None,
    ):
        self.messages = messages
        self.parent = parent
        self.children = []
        self.value = 0
        self.visits = 0
    # Additional methods are defined here. Check the code for more!

class TreeState(TypedDict):
    # The full tree
    root: Node
    # The original input
    input: str

def should_loop(state: TreeState):
    """Determine whether to continue the tree search."""
    root = state["root"]
    if root.is_solved:
        return END
    if root.height > 5:
        return END
    return "expand"


builder = StateGraph(TreeState)
builder.add_node("start", generate_initial_response)
builder.add_node("expand", expand)
builder.set_entry_point("start")


builder.add_conditional_edges(
    "start",
    # Either expand/rollout or finish
    should_loop,
)
builder.add_conditional_edges(
    "expand",
    # Either continue to rollout or finish
    should_loop,
)

graph = builder.compile()

Discussion