Skip to content
This page has been auto-translated and may contain errors.View in English

エージェント

docs.scrimba.com

**エージェント**は、タスクが完了するまで次に呼び出すツールを選択しながらループで実行するモデルです。このチャプターの残りの部分では、これが意味すること、その価値、そして静かにコストをかける場所について説明します。

エージェントループ

ツール使用では、モデルが1つの関数を呼び出し、結果を返していました。しかし、複数のステップが必要なタスクがあり、事前にステップを知ることができません。「最も安いフライトを見つけて予約する」は、検索、比較、カレンダーの確認、予約を意味する可能性があり、モデルはこのシーケンスを進行中に解決する必要があります。

そのため、単一のツール呼び出しを処理する代わりに、タスクが完了するまで実行されるループに全体を配置します。この反復サイクルは**エージェントループ**であり、タスクが完了するまで繰り返される1つのターンです:

  1. 会話と利用可能なツールをモデルに送信します。
  2. モデルはツールを呼び出すか、最終的な回答を提供します。
  3. ツールを呼び出した場合は、実行して、結果を会話に追加し、ステップ1に戻ります。
  4. 最終的な回答を提供した場合は、停止します。

各ターンで、モデルはこれまでに発生したすべてのこと(以前のツール結果を含む)を見て、次の手を決定します。これがツール使用との全体的な違いです。モデルが満足するまでループを続けます。

本当の変化は誰がステアリングしているかです。これまでのすべてのチャプターでは、コードが制御フローを決定していました。モデルをいつ呼び出すか、ツールをいつ実行するか、次は何が来るかを選択していました。エージェントはその決定をモデルに渡します。ループは「次は何が起こるべきか?」と繰り返し尋ね、モデルの予測は毎回その回答です。制御と引き換えに柔軟性を得て、その取引が到達可能性とリスクの両方の源です。

その下では、新しいことは何も起きていません。これは成長するコンテキストに対する同じ予測であり、ツール使用の往復を繰り返しているだけです。モデルは計画を立てて実行するわけではありません。各ターンで現在見ることができるものから次の単一の最良のステップを予測し、ループが再び実行されます。

それが機能するとき、それは目標に向かって推論しているように見えます。そうでないとき、エージェントがループ内でループするか、行き止まりを彷徨う可能性があります。なぜなら、システムのどの部分も全体的な計画を保持していないからです。

Junoエージェントループ エージェントはツール使用ループを繰り返したものです:会話とツールを送信し、モデルがツールを呼び出すか最終的な回答を提供し、任意のツールを実行して結果を返し、また実行します。それが回答するまで繰り返します。各ターンで、モデルはすべての以前の結果を見て、次のステップを選択します。プレーンなツール使用を超えた唯一の新しいアイデアは、1回の呼び出しを処理する代わりにループすることです。

ツール使用では、1回の呼び出しを処理して結果を返していました。エージェントはその往復をループで囲んだもので、モデルが完了したと判断するか、ステップ制限に達するまで実行されます。そのループが**エージェントループ**です。ここがポイントです:ステップのシーケンスをハードコードするのをやめて、各ターンでモデルに次を選択させます。

サイクルは4つのステップです:

  1. 会話とツールリストをモデルに送信します。
  2. モデルはツール呼び出しまたは最終的なテキスト回答で応答します。
  3. ツールを要求した場合は、実行して各結果を会話に追加し、ループします。
  4. 回答した場合は停止して返します。

これを機能させるメカニズムは、モデルが毎ターン完全に成長する会話を見ることです:元の要求、それが行ったすべてのツール呼び出し、戻ってきたすべての結果。この蓄積されたコンテキストは、エージェントの唯一のメモリです。各予測は、これまでの履歴全体に条件付けされているため、以前の結果に依存するステップをチェーンできます。

早期に名付ける価値のある詳細:ステップ2は一度に複数のツール呼び出しを返すことができます。呼び出しが互いに依存していない場合(3つの都市の天気をチェックするなど)、モデルは1つのターンで3つすべてを要求でき、一緒に実行できます。呼び出しが前のものの結果が必要な場合、モデルはその結果を待ってから次を要求する必要があるため、それらは別のターンにわたって発生します。ループは両方を処理します:このターンで戻ってきた呼び出しを実行し、すべての結果を入力して再度予測します。

この中にグローバルな計画はありません。モデルは右今見えるものから最良の次のステップを予測します。タスク全体のマップからではなく。これはエージェントと固定パイプラインを書いてきた固定パイプラインの違いであり、研究ステップをチェーンできるのと同じループが自分の尾を追うこともできます。

Junoエージェントループ エージェントはツール使用の往復をループで実行です:会話とツールを送信し、モデルがツールを呼び出すか回答し、ツールを実行して結果を返し、回答するまで繰り返します。成長する会話はエージェントの唯一のメモリなので、各ステップはそれ以前のすべての結果に条件付けされます。1つのターンは、複数の独立したツール呼び出しを一度に返すことも、各ステップが最後のステップに依存する場合は1つずつ返すこともできます。グローバルな計画は どこにもありません:すべてのステップは新しい次のステップの推測です。

エージェントはツール使用の往復をループに配置し、ハンドルを渡したもの、エージェントループ:モデルが各ターンで次のツールを選択し、実行し、結果を返し、最終的な回答を代わりに返すまで再度実行します。ループは4つのステップで、興味深い部分ではありません。興味深い部分はアーキテクチャが提供し、提供しないものです。

サイクル:

  1. 実行中の会話とツールスキーマを送信します。
  2. モデルはツール呼び出しまたは最終的な回答を返します。
  3. 呼び出しを実行し、結果を追加し、ループします。
  4. 最終的な回答で返します。

1つのターンは複数のツール呼び出しを返すことができます。モデルは、それらが独立していると判断したときに並列呼び出しを発行します(3つのルックアップで相互にデータ依存性がない場合)、1つが他方の出力を必要とする場合、連続した呼び出しはターン全体にわたります。外部からこれを強制することはできません:作業が並列化するかどうかは、モデルがタスクから推定したものに基づいているため、並列処理できると思うタスクはシリアル化されて遅くなる可能性があり、シリアル処理できると思うタスクは一度に実行する準備ができている必要があるバッチとして戻ってくる可能性があります。

ここが負荷を担う事実です。すべての失敗モードはこれをトレースしています。グローバルな計画はありません。モデルはタスクのマップを保持して実行するわけではありません。各ターンで現在の会話から次のステップを予測します。その会話は、システム全体の状態です。プロンプトと、これまでのすべての呼び出しと結果が蓄積されています。

すべてのステップは前のステップを信頼し、何も全体をチェックします。これが、目標に向かって推論しているように見えるエージェントが、実際には局所的にもっともらしい推測のシーケンスを取っている理由です。それは動作するとき、加算されます。

今内部化するための結果はその1つです。ガードレールセクションはそれを支払います:状態がコンテキストのみの成長する書き起こしなので、各ステップはそれに条件付けられているので、初期の間違ったツール結果は修正されません。それは構築されます。エラーは前方に伝播し、複合し、ループのどの部分も気付くのに配置されません。エージェントの信頼性の仕事は、その1つのプロパティと戦う大部分です。

Junoエージェントループ エージェントはツール使用の往復をループで実行し、モデルがステアリングしています:次のツールを選択し、実行し、結果を返し、回答するまで繰り返します。全体の状態は成長する書き起こしであり、グローバルな計画はどこにもなく、最後のものに条件付けられた次のステップの推測のチェーンのみです。モデルが独立していると判断したときは平行呼び出しを返すか、相互に依存するときはシリアル呼び出しを返すことができます。どちらかは制御できません。1つのことを保持してください:すべてのステップは前のステップを信頼するため、初期の間違った結果は全体をチェックするもの なしで前方に複合します。

最小限のエージェント

ここにコード内のループがあります。ツール使用からツール定義と実装を再利用し、モデルがツールの要求を停止するまで実行されるループで囲みます。

python
import json

def run_agent(user_text, tools, tool_impls, max_steps=6):
    messages = [{"role": "user", "content": user_text}]
    step = 0

    while step < max_steps:
        response = client.chat.completions.create(model=MODEL, messages=messages, tools=tools)
        message = response.choices[0].message
        messages.append(message)

        calls = message.tool_calls
        if not calls:
            return message.content  # ツール不要:これが最終的な回答です

        # すべての要求されたツールを実行し、結果をフィードバックします
        for call in calls:
            args = json.loads(call.function.arguments)
            result = tool_impls[call.function.name](args)
            messages.append({"role": "tool", "tool_call_id": call.id, "content": json.dumps(result)})

        step += 1

    return "Stopped: the agent reached its step limit."  # セーフティネット

上から下に読みます:モデルを呼び出し、そのメッセージを会話に押し、ツールを要求した場合は、それらすべてを実行して結果を追加し、再度ループします。モデルがツール呼び出しの代わりにテキストを返すとき、そのテキストが最終的な回答で、それを返します。

max_steps値は**ステップ制限**を設定します。これは、ループが逃げてしまうのを防ぐセーフティネットであり、次のセクションはこれについて説明しています。ここの形状は1つのプロバイダーのSDKと一致します;フィールド名はプロバイダー全体で異なりますが、ループはどこでも同じです。

Juno最小限のエージェント 最小限のエージェントはモデル呼び出し周辺のループです:モデルを実行し、それが要求するツールを実行し、結果をフィードバックし、繰り返します。モデルがツール呼び出しの代わりにテキストを返すとき、そのテキストが最終的な回答です。ステップ制限は、後で追加するエキストラではなく、必要なセーフティネットです。

ここにコード内のループがあります。ツール使用からツール定義と実装を再利用します。モデルがツール要求を停止するか、ステップキャップに到達するまで実行されます。

python
import json

def run_agent(user_text, tools, tool_impls, max_steps=6):
    messages = [{"role": "user", "content": user_text}]
    step = 0

    while step < max_steps:
        response = client.chat.completions.create(model=MODEL, messages=messages, tools=tools)
        message = response.choices[0].message
        messages.append(message)

        calls = message.tool_calls
        if not calls:
            return message.content  # 最終的な回答

        for call in calls:
            args = json.loads(call.function.arguments)
            try:
                result = tool_impls[call.function.name](args)
            except Exception as err:
                result = {"error": str(err)}  # 失敗を表示し、クラッシュしません
            messages.append({"role": "tool", "tool_call_id": call.id, "content": json.dumps(result)})

        step += 1

    return "Stopped: the agent reached its step limit."

形状は1つのプロバイダーのSDKで、フィールド名は異なりますが、すべてのループには次のパーツがあります:モデルのメッセージを追加し、ツールを要求したかどうかで分岐し、要求されたものを実行し、各結果をそのコール id にキー付けされたtoolメッセージとして返します。

ベアバージョンのみで作成する価値のある1つの変更は、ツール周辺のtry/exceptです。ツールが失敗した場合、例外がループを殺さないでください。それをキャッチしてエラーをツール結果としてモデルに返します。次のターンでモデルは「そのルックアップが失敗した」を読み、適応できます:異なる引数で再試行、別のツールを試す、またはユーザーにタスクを完了できなかったことを伝えます。クラッシュはモデルに回復の機会を与えません;この**エラーアズリザルト**パターンは行動する情報と共にループに留まります。

この実行中に2つのことを追跡します。まず、会話のみが成長します。各ターンでモデルのメッセージとすべてのツール結果を追加するため、ステップ5までに、モデルはステップ1から4からすべてを再度読んでいます。これはエージェントのメモリであり、またその請求書でもあります:各ステップは全体の蓄積されたコンテキストを再送信するため、ステップごとのトークンコストはタスク実行中に上昇します。10ステップのエージェントは10の安い呼び出しではなく、より大きなトランスクリプトの上の10の呼び出しです。

次に、その成長がmax_stepsが無限ループの停止を超えて重要な理由です。タスクに対するキャップを選択します。天気の質問には2~3ステップが必要です;研究タスクは10を望む可能性があります。健全な実行がかかるものより少し上にキャップを設定して、正当に長いタスクは完了できますが、スタックしたものはまだ予算をドレインする前に遮断されます。

Juno最小限のエージェント ループは:モデルのメッセージを追加し、ツールを要求したかどうかで分岐し、実行し、各結果をtoolメッセージとして返します。ツール呼び出しをtry/exceptで囲み、クラッシュする代わりにエラーを返して、モデルが再試行または回復できます。会話のみが成長することを監視します:すべてのステップが全体のトランスクリプトを再送信するため、ステップごとのトークンコストはタスク実行中に上昇します。max_stepsをタスクに対して設定し、健全な実行より少し上です。

ループ、ツール使用からのツールレイヤーを再利用します。1つのプロバイダーのSDK形状、フィールド名は異なり、構造は異なりません。

python
import json

def run_agent(user_text, tools, tool_impls, max_steps=6):
    messages = [{"role": "user", "content": user_text}]
    step = 0

    while step < max_steps:
        response = client.chat.completions.create(model=MODEL, messages=messages, tools=tools)
        message = response.choices[0].message
        messages.append(message)

        calls = message.tool_calls
        if not calls:
            return message.content

        for call in calls:
            args = json.loads(call.function.arguments)
            try:
                result = tool_impls[call.function.name](args)
            except Exception as err:
                result = {"error": str(err)}  # モデルはこれを読んで次のターンで適応できます
            messages.append({"role": "tool", "tool_call_id": call.id, "content": json.dumps(result)})

        step += 1

    return "Stopped: the agent reached its step limit."

ベアループは正しく、出荷不可能で、この2つの間のギャップはこのセクションが存在する場所です。このコードの3つのプロパティが本番環境で噛みます。

エラーを表示し、決してクラッシュしないでください。try/exceptは失敗したツールをモデルがそれを読むことができるモデルに結果として返します。それは正しいですが、何をしているのか理解してください:エラー文字列をモデルに渡し、それが合理的に回復することを信頼しています。同じ不良呼び出しを再試行、別のアプローチを考案、または謝罪して停止する可能性があります。

エラーをフィードバックするとエージェントは存続します;回復の信頼性は向上しません。負荷軸受けに対して、ツールごとの再試行をキャップし、繰り返される失敗をモデルが感じで解決させるようにループするターミナル状態として扱います。

トランスクリプトのみが成長し、それは2つの複合コストです。完全な蓄積されたヒストリーを再送信するため、毎ステップのトークンコストが上昇するため、長い実行は1つあたりフラットなものではなく、各ターンに昇給する請求書を支払います。トランスクリプトが長いほど、モデルが次の手を決定するため古いツール出力を読んでいます。それはまさにコンテキストウィンドウチャプターの**lost-in-the-middle**効果が噛み始める場所です。モデルは長いコンテキストの中央に埋もれている情報にはあまり出席しません:制約すべき初期の指示はエージェントの蓄積された結果の下に沈み、あまり出席されません。長いエージェントは大声で失敗しません、それらは漂流します。

max_stepsは予算であり、バグガードではありません。それはモデルが停止するタイミングを決定し、間違って決定できるため存在します:ステップ上のループ、2つのツール間でピンポン、行き止まりを追いかけます。

その数は本当のコスト上限です。最悪のケースの支出は、大体max_stepsに、実行の終わりの近くの完全なコンテキスト呼び出しのコストを掛けたものであるため、コンテキストヘビータスク上の気前の良いキャップは気前の良い請求書です。最長の正当な実行とマージンからそれを設定し、実行がそれに定期的にヒットするときアラームに設定し(それはエージェントがスタックしている信号です。キャップが低すぎません)、完了できないエージェントを紙張りするのに上げるのに抵抗します。

Juno最小限のエージェント ベアループは正しく、出荷不可能です。ツールエラーを返して、モデルが適応できるようにしますが、再試行をキャップし、繰り返される失敗をターミナルとして扱います。表面化されたエラーは回復の信頼性を向上させません。トランスクリプトのみが成長するため、ステップごとのトークンコストが上昇し、古い結果の下に初期の指示が埋もれます。エージェントは漂流します。max_stepsはコスト上限です。バグガードではなく:最長の実行プラスマージンに対して設定し、実行がそれに継続的にヒットする場合、エージェントはスタックしているため、数値を反射的に上げないでください。

停止とガードレール

モデルが停止するタイミングを決定できるループは、停止に失敗する可能性があります。ツールを永遠に呼び出したり、自分自身を繰り返したり、行き止まりを追いかけたりする可能性があります。すべてのステップはトークンで請求されるモデル呼び出しであるため、逃げてしまうエージェントは素早くお金と時間を消費します。

だから**ガードレール**、ループの周りに配置される制限は、ポーランドステップを追加するのではなく、設計の一部です:

  • ステップ制限。 ループ数を制限し、max_stepsがしているように制限します。ヒットした場合は停止して返します。
  • ツール入力を検証します。 モデルは引数を選択するため、実際の結果を持つ任意のものを実行する前に確認してください。
  • ツールができることを制限します。 エージェントに必要な最小電力を与えます。削除するツールより安全な読み取りツール。
  • コストを監視します。 タスクごとに複数のモデル呼び出しはすぐに乗算するため、トークンを追跡し、予算を設定します。

これらを結ぶスレッド:モデルはパスを即興しているため、それが行わない制限を配置します。エージェントが少なくとも1回は間違ったことをするものと仮定し、その生存可能です。

Juno停止とガードレール エージェントは独自の停止点を決定するため、永遠にループでき、すべてのループがトークンをコストします。常にステップ制限を設定し、モデルが選択する引数を検証し、ツールに必要な最小パワーを付与します。タスク追跡は複数のモデル呼び出しをすぐに追加するため、コストをトラッキングします。

モデルが停止するタイミングを決定できるループは失敗して停止する可能性があり、各ステップはトークン請求されるモデル呼び出しであるため、スタックしたエージェントは予算を素早く消費します。ガードレールは設計の一部です。ワイヤーに4つ:

  • ステップ制限。 max_stepsでループを制限し、ヒット時にクリーンに返します。これはランアウェイループに対する厳しい停止です。
  • ツール入力を検証します。 モデルは引数を選択し、誤って選択する可能性があります。削除はIDなし、送金は負の金額、パス許可されたディレクトリの外で、実際の結果を伴うツールを実行する前に確認します。
  • 最小パワー。 各ツールに、タスクが必要とする最小限の機能を付与します。読み取り専用は読み取り専用勝利をシングアウト、スコープされたクエリは生のデータベースアクセスを打つ、固定受信者のリストは任意の送信をしはいします。
  • コスト上限。 呼び出しごとではなく実行全体にわたってトークンを追跡し、実行が予算を超える場合は停止します。

これらを結ぶポイントは、ツールへの引数がモデルから来るため、間接的にはモデルが読んだテキストから来るということです。ツールがWebページをフェッチし、そのページに命令が含まれていた場合、それらの命令はモデルのコンテキストに含まれ、次のツール呼び出しを操ります。これは**プロンプトインジェクション**:エージェントが何をするかに影響を与える可能性のあるコンテキスト内の信頼できないテキスト。防御はプロンプトにはありません。すべてのツール入力を検証し、すべてのツールのパワーをスコープすることで、完全にハイジャックされた引数でさえ実際のダメージを行うことはできません。

Juno停止とガードレール 4つのガードレール、ポーランドではなく設計別:max_steps厳しい停止、すべての結果あるツールの入力検証、最小パワーツールスコープ、実行全体のトークン予算。入力検証が重要な理由:ツール引数はモデルから来て、それが読んだテキストから来るため、フェッチされたページを使用して命令が含まれているのはプロンプト注入です。次の呼び出しを操ることができます。入力を検証し、パワーをスコープして、ハイジャックされた引数がそれでもダメージを行うことはできません。

モデルが停止するタイミングを決定できるループは失敗して停止する可能性があり、すべてのステップはトークン請求されるコールであるため、失敗モードは状態でコストがかかります。4つのガードレール(ステップ制限、入力検証、最小パワー、コスト上限)は賭けです。注目に値する部分は、入力検証が衛生チェックではなく、セキュリティ制御である理由です。

ツール引数はモデル出力であり、モデル出力は、エージェントがフェッチしたテキストを含むコンテキスト内のすべてのものに条件付けられます。エージェントがWebページ、ドキュメント、電子メール、制御しないツール結果を読む瞬間、信頼できないテキストはそのコンテキストにあり、命令を運ぶことができます。これは**プロンプトインジェクション**:入力内の敵対的なコンテンツがモデルを意図しない行動に操作します。シングルショットプロンプトでは迷惑です。エージェントでは、モデルの次の手段はツール呼び出しであり実際の結果があり、注入されたテキストはその呼び出しに影響を与えることができるため、生きているエクスプロイトです。

敵対的なものとして設計してください。3つのルール は保ちます:

  • アロリスト、ブロックリストではなく、すべてのツール引数に対して検証します。 有効な引数がどのように見えるか(このID形式、この受信者セット、このディレクトリ)を定義し、他のすべてを拒否します。攻撃者が作製するすべてのインプット入力を列挙することはできません;良いものを列挙できます。
  • ツールパワーをスコープして、完全にハイジャックされた呼び出しが生存可能です。 引数は攻撃者が制御されていると仮定し、ツールが何をできるかを尋ねます。本当の答えが「誰でもメール」または「任意の行を削除」の場合、プロンプトがどれだけ慎重であっても、ツールは広すぎます。最小パワーは、モデルが危険にさらされ、プロンプトは実際に制御されないとき、保持される制御です。
  • 不可逆的な行動に人間をループに入れます。 お金を送信する、データを削除する、顧客にメールを送信する:これらを確認に対してゲートします。エージェントは提案し、人またはより厳しいチェックが処分します。

これがプロンプトに住んでいない、より深い理由:システムプロンプトの命令とフェッチされたコンテンツの注入された命令は、同じ種類のもの、コンテキスト内のテキストとして到着し、モデルは一方を他方より信頼できる方法で見分ける信頼できる方法を持っていません。だからあなたはプロンプトで安全に向かうことはできません。保持する境界は、モデルの外側にあります:検証された入力とスコープされたツール。これは安全性と制限のより広い治療に接続します。

Juno停止とガードレール 4つのガードレールは賭けです;得点を稼ぐものは入力検証です。なぜなら、それはセキュリティ制御だからです。ツール引数はモデル出力であり、それが読んだすべてのものに条件付けられているため、任意のフェッチされたページまたはメールが注入された命令を伝えることができ、エージェント内、その呼び出しは実際の結果があります。アロリストに対して検証し、すべてのツールをスコープして、ハイジャックされた引数が生存可能であることを確認し、不可逆的な行動で人間をゲートします。プロンプトで安全に向かうことはできません:注入されたシステム命令は同じ種類のテキストをモデルに送信するため、境界はモデルの外に住む必要があります。

ワークフローがエージェントを打つとき

エージェントは興味深いですが、それは1つが必要がないときにリーチするための誘惑を作ります。明確なルール:ステップを既に知っている場合は、エージェントを使用しないでください。それらを単純なコード、**ワークフロー**として書き出します。各ステップは固定順序で実行されます。

ワークフローは、より信頼性が高く、安く、デバッグがはるかに簡単です。モデルがパスを見つけることを願うのではなく、パスを制御するため。オープンエンドなタスクでステップは発見された内容に依存する場合にエージェントを保存します。

構造化出力呼び出しまたはRAGルックアップが手で配線されているように見える多くの機能。ステップを事前に書き下ろせない場合にのみ、エージェントに到達します。

Junoワークフローがエージェントを打つとき ステップを既に知っている場合は、エージェントを使用する代わりに、ワークフローとしてハードコードします:それはより安く、信頼性が高く、デバッグがより簡単です。オープンエンドなタスク向けエージェントを保存します。多くの「エージェント」機能は本当に、構造化出力またはRAGの呼び出しです。

エージェントは興味深いツールであり、正確にはそれが間違っているとき到達するものです。決定ルールは1つの質問です:ステップを事前に書き下ろせますか?はい、あなたはを**ワークフロー**が欲しい場合、ステップとして明確なコード、固定順序、エージェント。

ワークフローはエージェントが苦労するすべての人に勝ちます。これは安いです。1つまたは2つのモデル呼び出しを行うため、ループ作り替えるのではなく。より信頼性があります。パスは固定されているため、再決定されるのではなく。そしてもっと簡単にデバッグします。失敗は、モデル選択の移動のチェーンのどこかではなく、検査できる既知のステップで発生するため。

ここはテスト実践です。「このサポートチケットを要約し、緊急度を分類し、キューにルーティングする」には既知ステップが既知順序であるため、ワークフローです:1つの構造化出力呼び出して概要、カテゴリ、緊急度を取得してからプレーンコードルート結果。「このお客様の最後の3つの注文が失敗した理由を調査する」は既知ステップを持たず、パスは各ルックアップが表示する内容に依存するため、エージェントです。

トラップは多くの機能がオープンエンドに見え、そうではないことです。ドキュメントからフィールドを抜く、ドキュメントから回答、受信メールをソート:これらはエージェント作業のように読みますが、構造化出力呼び出しまたはRAGルックアップに解決し、コードの周り。デフォルトはワークフローとタスクがエージェントを得て、予測不可能な方法で。

Junoワークフローがエージェントを打つとき 決定は1つの質問です:ステップを事前に書き下ろせますか?はい、ワークフロー、明確なコード、ステップを構築します。安いです、より信頼性があります、既知の点でデバッグ可能です。「概要、分類、ルート票」はワークフロー:1つの構造化出力呼び出しプラスルーティングコード。「これらの注文が失敗した理由を調査」はエージェントです。パスは各ステップが見つけるものに依存するため。ワークフローにデフォルトを設定し、タスクがエージェントを得るようにします。

エージェントはツールが使いたいですが、適切でない場所で使用されるツールです。決定ルールは短いです:ステップを事前に書き下ろせるなら、書き下ろしてください。それは**ワークフロー**、明確なコードのステップ、固定順序、エージェントを打つコストに対して、任意の誰のかたち信頼性、デバッグ可能性タスク。

理由はアーキテクチャまでトレースします。エージェントには全体的な計画がなく、エラーを前方に複合するため、その信頼性はすべてのステップが何も全体をチェックしない権利の製品です。書いたワークフローには計画があります。定義により、各ステップを分離して検査、テスト、検証できます。ワークフローで何かが壊れたら、それはラインで壊れます。エージェント内で何かが壊れたら、それはモデル選択の移動のトランスクリプトのどこかで壊れます。トレースからそれが考えていたことを再構成します。

さて、より難しいケース、なぜなら「ステップを知っているか」は直接的な半分だからです。エージェントは誤ったツール、タスクがオープンエンドの場合でも、間違ったステップの費用が高すぎて、次のステップの推測にかかります。エージェント、移動お金、またはデータを予約旅行は、オープンエンドと、また計画されていない、注射可能なものの場所。正しい設計はしばしばハイブリッドです:モデル計画または提案しますが、固定ワークフローと人間のゲート実行するため、予測不可能な部分は不可逆的な部分を直接タッチすることはありません。

だから質問は2つの質問です。ステップを知っているのですか、間違ったステップの費用は何ですか?

既知のステップはワークフローに移動します。未知の安い、可逆的なアクション、エージェントが存続する場所。未知のステップで高い不可逆的なアクション制約設計が必要です。フリーランニングループではなく。

エージェントは、安い可逆的なステップのオープンエンドな作業に適合し、それ以外はありません。予想される「エージェント」機能の共有の予想外のシェアは、構造化出力呼び出しまたはRAGルックアップであり、その方法が良好に保たれます。

Junoワークフローがエージェントを打つとき 2つの質問、1つではなく:ステップを知っているのですか、間違ったステップの費用は何ですか?既知のステップはワークフロー、全体的な計画を持つため、エージェントを打つことが信頼性とデバッグしているため移動します。安い可逆的な行動による未知のステップは、エージェントが搭乗する場所。高い不可逆的な行動による未知のステップ、ハイブリッド:モデル提案が、固定ワークフローと人間のゲート実行するため、エラー複合ループはそれらで直接触れません。

実際には

上記のrun_agent関数は、全体です。質問、ツールセット、実装、ループするまで完了。小さなタスクはループが実行される場所を示しています:

python
answer = run_agent(
    "東京の天気はどうですか。傘を持って行く必要がありますか?",
    tools,        # ツール使用チャプターからの get_weather を含める
    tool_impls,   # {"get_weather": ...}
)
# エージェントはget_weatherを呼び出し、「曇り」を読み、1つの最終的なターンで回答します:
# 「東京は18度で曇りなので、傘を持ち運ぶことは賢明です。」

1つのツール、1つのループ、1つの回答。同じ構造は複数のツールとステップにスケール、形状を変えずにします。これほど有能なものを構築できたら、次の質問は、実際に機能するかどうかです。これは評価についてです。

Juno実際にはrun_agentループは全体パターンです:質問、ツール、実装を与えて、モデルがツール要求を停止するか、ステップ制限にヒットするまでループします。1つのツールと1つのループは形状を変えずに多数にスケールします。次の質問は実際に機能するかどうか、評価です。

run_agent関数は全体パターンです。質問、ツール、実装を与えて、モデルが要求を停止するか、キャップにヒットするまでループします。

python
answer = run_agent(
    "東京の天気はどうですか。傘を持って行く必要がありますか?",
    tools,        # ツール使用チャプターからの get_weather を含める
    tool_impls,   # {"get_weather": ...}
)
# エージェントはget_weatherを呼び出し、1つの最終的なターンで回答します。

1つのツール、1つのループ、1つの回答。同じ形状は複数のツールとステップにスケールします。無料でスケールしません。エージェントは異なる入力で異なるパスを取るため、1つの好調な実行は、今日失敗する実行についてほとんど何も教えてくれません。

それは、エージェントの横でビルドする次のことが、それを測定する方法である理由です:代表的なタスクセット全体で実行し、次の1つの成功を信頼するのではなく、結果をチェックします。「試したときに動作した」を追跡できる数に変えることは、正確に評価がカバーするものです。

Juno実際にはrun_agentループは全体パターンで、1つのツールと1つのループは形状を変えずに多くにスケールします。キャッチは信頼:エージェントはインプット入力あたり異なるパスを取るため、良いデモは、次の実行についてほとんど何も証明しません。代表的なタスク全体で測定する方法を構築してください。ループ、評価です。

run_agent関数は全体パターンであり、下記の例はむき出しの最小です:1つのツール、1つのループ、1つの回答。

python
answer = run_agent(
    "東京の天気はどうですか。傘を持って行く必要がありますか?",
    tools,        # ツール使用チャプターからの get_weather を含める
    tool_impls,   # {"get_weather": ...}
)
# get_weatherは「曇り」を返し、モデルは1つの最終的なターンで回答します。

形状は多くのツールと多くのステップにスケールしコードは静止したままですが、それがトラップです。失敗モードは、スケールするコード上のパス依存です。異なる入力は、モデル選択の異なるシーケンスを駆動するため、インプット入力テストは、見ていないインプット入力についてほとんど何も教えてくれません。サンプリングからの非決定論は、同じインプット入力でも異なるパスを2回取ることができることを意味します。

だからあなたがエージェント次にビルドすることは、測定で、ワークフローが必要とする異なる種類の測定です。1つの予想される出力をアサートしていません;多くの代表的なタスクをサンプリングして、結果の分布を読んでいます:予算内でどのくらい頻繁に完了するのか、正しい回答に到達する頻度、どこでループするか、それはテール費用です。それはエージェント形のバージョン評価であり、上記のセクションからの信頼性とコストの懸念が、デモを得た数値に変わるようになる唯一の方法です。

Juno実際にはrun_agentは全体パターンであり、形状でスケールするほか、失敗モードは一緒にスケールします。エージェントはパス依存され、サンプリングは非決定論を追加するため、インプット入力テストはテストを伝え、デモは好ましい証明を少なく使用します。測定:サンプル多数の代表的なタスク、結果の分布を読んで、どのくらい頻繁に完了するか、予算でループの場所、テール費用は何です。それは評価のためのものであり、信頼性とコストの懸念が、デモを得た数値に変わります。