diff --git a/docs/ja/agents.md b/docs/ja/agents.md index 389cbecd3..6cec065aa 100644 --- a/docs/ja/agents.md +++ b/docs/ja/agents.md @@ -4,16 +4,16 @@ search: --- # エージェント -エージェントは、アプリの中核となる構成要素です。エージェントは、instructions とツールで構成された大規模言語モデル(LLM)です。 +エージェントはアプリの中核となる基本コンポーネントです。エージェントは instructions とツールで構成された大規模言語モデル ( LLM ) です。 -## 基本構成 +## 基本設定 エージェントで最も一般的に設定するプロパティは次のとおりです。 -- `name`: エージェントを識別する必須の文字列です。 -- `instructions`: developer メッセージ、または system prompt とも呼ばれます。 -- `model`: 使用する LLM と、temperature、top_p などのモデル調整パラメーターを設定する任意の `model_settings`。 -- `tools`: エージェントがタスク達成のために使用できるツールです。 +- `name`: エージェントを識別する必須の文字列。 +- `instructions`: developer message または system prompt とも呼ばれます。 +- `model`: 使用する LLM と、`model_settings` による temperature、top_p などのモデル調整パラメーターの任意設定。 +- `tools`: エージェントがタスク達成のために使用できるツール。 ```python from agents import Agent, ModelSettings, function_tool @@ -33,7 +33,7 @@ agent = Agent( ## コンテキスト -エージェントは `context` 型に対して汎用的です。コンテキストは依存性注入のためのツールで、あなたが作成して `Runner.run()` に渡すオブジェクトです。これはすべてのエージェント、ツール、ハンドオフなどに渡され、エージェント実行のための依存関係と状態のまとめとして機能します。コンテキストには任意の Python オブジェクトを指定できます。 +エージェントは `context` 型に対してジェネリックです。コンテキストは依存性注入のためのツールで、あなたが作成して `Runner.run()` に渡すオブジェクトです。これはすべてのエージェント、ツール、ハンドオフなどに渡され、エージェント実行のための依存関係と状態の詰め合わせとして機能します。コンテキストには任意の Python オブジェクトを指定できます。 ```python @dataclass @@ -52,7 +52,7 @@ agent = Agent[UserContext]( ## 出力タイプ -デフォルトでは、エージェントはプレーンテキスト(つまり `str`)を出力します。特定のタイプの出力を生成したい場合は、`output_type` パラメーターを使用できます。一般的な選択肢は [Pydantic](https://docs.pydantic.dev/) オブジェクトを用いることですが、Pydantic の [TypeAdapter](https://docs.pydantic.dev/latest/api/type_adapter/) でラップ可能なあらゆる型(dataclasses、lists、TypedDict など)をサポートします。 +デフォルトでは、エージェントはプレーンテキスト (すなわち `str`) を出力します。特定のタイプの出力を生成させたい場合は、`output_type` パラメーターを使用できます。一般的には [Pydantic](https://docs.pydantic.dev/) オブジェクトを使用しますが、Pydantic の [TypeAdapter](https://docs.pydantic.dev/latest/api/type_adapter/) でラップできる任意の型 (dataclasses、lists、TypedDict など) をサポートします。 ```python from pydantic import BaseModel @@ -73,20 +73,20 @@ agent = Agent( !!! note - `output_type` を渡すと、モデルに通常のプレーンテキスト応答ではなく [structured outputs](https://platform.openai.com/docs/guides/structured-outputs) を使用するよう指示します。 + `output_type` を渡すと、モデルは通常のプレーンテキスト応答ではなく [structured outputs](https://platform.openai.com/docs/guides/structured-outputs) を使用するよう指示されます。 -## マルチエージェントのシステム設計パターン +## マルチエージェントの設計パターン -マルチエージェントシステムの設計方法は多数ありますが、広く適用できる 2 つのパターンをよく見かけます。 +マルチエージェント システムの設計にはさまざまな方法がありますが、広く適用できるパターンとして次の 2 つがよく見られます。 -1. マネージャー(エージェントをツールとして): 中央のマネージャー/オーケストレーターが、ツールとして公開された専門のサブエージェントを呼び出し、会話の制御を保持します。 -2. ハンドオフ: ピアのエージェントが制御を専門のエージェントに引き渡し、そのエージェントが会話を引き継ぎます。これは分散型です。 +1. マネージャー (エージェントをツールとして使用): 中央のマネージャー/オーケストレーターが、専門のサブエージェントをツールとして呼び出し、会話の制御を保持します。 +2. ハンドオフ: ピアエージェントが制御を専門のエージェントに引き渡し、そのエージェントが会話を引き継ぎます。これは分散型です。 -詳細は、[実践的なエージェント構築ガイド](https://cdn.openai.com/business-guides-and-resources/a-practical-guide-to-building-agents.pdf)をご覧ください。 +詳細は [エージェント構築の実践ガイド](https://cdn.openai.com/business-guides-and-resources/a-practical-guide-to-building-agents.pdf) をご覧ください。 -### マネージャー(エージェントをツールとして) +### マネージャー (エージェントをツールとして使用) -`customer_facing_agent` はすべてのユーザーやり取りを処理し、ツールとして公開された専門のサブエージェントを呼び出します。詳細は [ツール](tools.md#agents-as-tools) ドキュメントを参照してください。 +`customer_facing_agent` はすべてのユーザー対応を処理し、ツールとして公開された専門のサブエージェントを呼び出します。詳細は [ツール](tools.md#agents-as-tools) ドキュメントをご覧ください。 ```python from agents import Agent @@ -115,7 +115,7 @@ customer_facing_agent = Agent( ### ハンドオフ -ハンドオフは、エージェントが委任できるサブエージェントです。ハンドオフが発生すると、委任先のエージェントは会話履歴を受け取り、会話を引き継ぎます。このパターンにより、単一のタスクに特化して優れた能力を発揮する、モジュール式の専門エージェントが可能になります。詳細は [ハンドオフ](handoffs.md) ドキュメントを参照してください。 +ハンドオフは、エージェントが委任できるサブエージェントです。ハンドオフが発生すると、委任先のエージェントが会話履歴を受け取り、会話を引き継ぎます。このパターンにより、単一タスクに特化したモジュール型のエージェントを実現できます。詳細は [ハンドオフ](handoffs.md) ドキュメントをご覧ください。 ```python from agents import Agent @@ -136,7 +136,7 @@ triage_agent = Agent( ## 動的 instructions -多くの場合、エージェントの作成時に instructions を指定できますが、関数を介して動的に instructions を提供することもできます。その関数はエージェントとコンテキストを受け取り、プロンプトを返す必要があります。通常の関数と `async` 関数の両方が使用できます。 +多くの場合、エージェント作成時に instructions を指定できますが、関数経由で動的に指定することもできます。この関数はエージェントとコンテキストを受け取り、プロンプトを返す必要があります。通常の関数と `async` 関数の両方が利用できます。 ```python def dynamic_instructions( @@ -151,13 +151,13 @@ agent = Agent[UserContext]( ) ``` -## ライフサイクルイベント(フック) +## ライフサイクルイベント (フック) -エージェントのライフサイクルを観察したい場合があります。たとえば、イベントをログに記録したり、特定のイベントが発生したときにデータを事前取得したりできます。`hooks` プロパティを使ってエージェントのライフサイクルにフックできます。[`AgentHooks`][agents.lifecycle.AgentHooks] クラスをサブクラス化し、関心のあるメソッドをオーバーライドしてください。 +エージェントのライフサイクルを観測したい場合があります。たとえば、イベントのログ記録や、特定のイベント発生時にデータを事前取得したい場合です。`hooks` プロパティでエージェントのライフサイクルにフックできます。[`AgentHooks`][agents.lifecycle.AgentHooks] クラスをサブクラス化し、関心のあるメソッドをオーバーライドしてください。 ## ガードレール -ガードレールにより、エージェントの実行と並行してユーザー入力に対するチェック/バリデーションを実行し、エージェントの出力生成後にはその出力に対するチェック/バリデーションを実行できます。たとえば、ユーザー入力とエージェント出力の関連性をスクリーニングできます。詳細は [ガードレール](guardrails.md) ドキュメントを参照してください。 +ガードレールにより、エージェントの実行と並行してユーザー入力のチェック/バリデーションや、生成後のエージェント出力のチェック/バリデーションを実行できます。たとえば、ユーザー入力とエージェント出力の関連性をスクリーニングできます。詳細は [ガードレール](guardrails.md) ドキュメントをご覧ください。 ## エージェントのクローン/コピー @@ -178,12 +178,12 @@ robot_agent = pirate_agent.clone( ## ツール使用の強制 -ツールのリストを指定しても、LLM が必ずしもツールを使用するとは限りません。[`ModelSettings.tool_choice`][agents.model_settings.ModelSettings.tool_choice] を設定することで、ツール使用を強制できます。有効な値は次のとおりです。 +ツールのリストを提供しても、LLM が必ずツールを使用するとは限りません。[`ModelSettings.tool_choice`][agents.model_settings.ModelSettings.tool_choice] を設定することでツール使用を強制できます。有効な値は次のとおりです。 -1. `auto`: ツールを使用するかどうかを LLM に委ねます。 -2. `required`: LLM にツールの使用を要求します(どのツールを使うかは賢く判断できます)。 -3. `none`: LLM にツールを使用しないことを要求します。 -4. 具体的な文字列(例: `my_tool`)を設定し、その特定のツールを使用することを LLM に要求します。 +1. `auto`: LLM がツールを使用するかどうかを判断します。 +2. `required`: LLM にツールの使用を要求します (どのツールを使うかは賢く判断します)。 +3. `none`: LLM にツールを _使用しない_ ことを要求します。 +4. 特定の文字列 (例: `my_tool`) を設定: LLM にその特定のツールの使用を要求します。 ```python from agents import Agent, Runner, function_tool, ModelSettings @@ -201,11 +201,11 @@ agent = Agent( ) ``` -## ツール使用の挙動 +## ツール使用の動作 -`Agent` 構成の `tool_use_behavior` パラメーターは、ツールの出力の扱い方を制御します。 +`Agent` の設定にある `tool_use_behavior` パラメーターは、ツール出力の扱い方を制御します。 -- `"run_llm_again"`: デフォルト。ツールを実行し、LLM がその結果を処理して最終応答を生成します。 +- `"run_llm_again"`: デフォルト。ツールを実行し、その結果を LLM が処理して最終応答を生成します。 - `"stop_on_first_tool"`: 最初のツール呼び出しの出力を、その後の LLM 処理なしに最終応答として使用します。 ```python @@ -224,7 +224,7 @@ agent = Agent( ) ``` -- `StopAtTools(stop_at_tool_names=[...])`: 指定したいずれかのツールが呼び出された場合に停止し、その出力を最終応答として使用します。 +- `StopAtTools(stop_at_tool_names=[...])`: 指定したいずれかのツールが呼び出された時点で停止し、その出力を最終応答として使用します。 ```python from agents import Agent, Runner, function_tool @@ -248,7 +248,7 @@ agent = Agent( ) ``` -- `ToolsToFinalOutputFunction`: ツール結果を処理し、停止するか LLM を継続するかを判断するカスタム関数です。 +- `ToolsToFinalOutputFunction`: ツール結果を処理し、停止するか LLM を続行するかを判断するカスタム関数です。 ```python from agents import Agent, Runner, function_tool, FunctionToolResult, RunContextWrapper @@ -286,4 +286,4 @@ agent = Agent( !!! note - 無限ループを防ぐため、フレームワークはツール呼び出し後に `tool_choice` を自動で "auto" にリセットします。この動作は [`agent.reset_tool_choice`][agents.agent.Agent.reset_tool_choice] で構成可能です。無限ループは、ツール結果が LLM に送られ、`tool_choice` のために LLM が再びツール呼び出しを生成し続けることが原因です。 \ No newline at end of file + 無限ループを防ぐため、フレームワークはツール呼び出し後に `tool_choice` を自動的に "auto" にリセットします。この動作は [`agent.reset_tool_choice`][agents.agent.Agent.reset_tool_choice] で設定できます。無限ループは、ツール結果が LLM に送られ、`tool_choice` により LLM がさらに別のツール呼び出しを生成し続けることが原因です。 \ No newline at end of file diff --git a/docs/ja/config.md b/docs/ja/config.md index 5e0e93850..5efcd8b7e 100644 --- a/docs/ja/config.md +++ b/docs/ja/config.md @@ -6,7 +6,7 @@ search: ## API キーとクライアント -デフォルトでは、この SDK はインポートされるとすぐに、LLM リクエストと トレーシング 用に `OPENAI_API_KEY` 環境変数を探します。アプリ起動前にその環境変数を設定できない場合は、[set_default_openai_key()][agents.set_default_openai_key] 関数でキーを設定できます。 +デフォルトでは、 SDK はインポートされた時点で、 LLM リクエストとトレーシングのために `OPENAI_API_KEY` 環境変数を探します。アプリの起動前にその環境変数を設定できない場合は、 [set_default_openai_key()][agents.set_default_openai_key] 関数を使ってキーを設定できます。 ```python from agents import set_default_openai_key @@ -14,7 +14,7 @@ from agents import set_default_openai_key set_default_openai_key("sk-...") ``` -また、使用する OpenAI クライアントを設定することもできます。デフォルトでは、この SDK は環境変数の API キー、または上記で設定したデフォルトキーを使って `AsyncOpenAI` インスタンスを作成します。これを変更するには、[set_default_openai_client()][agents.set_default_openai_client] 関数を使用します。 +また、使用する OpenAI クライアントを構成することもできます。デフォルトでは、 SDK は `AsyncOpenAI` インスタンスを作成し、環境変数または上記で設定したデフォルトキーの API キーを使用します。これを変更するには、 [set_default_openai_client()][agents.set_default_openai_client] 関数を使用します。 ```python from openai import AsyncOpenAI @@ -24,7 +24,7 @@ custom_client = AsyncOpenAI(base_url="...", api_key="...") set_default_openai_client(custom_client) ``` -最後に、使用する OpenAI API をカスタマイズすることもできます。デフォルトでは OpenAI Responses API を使用します。これを上書きして Chat Completions API を使うには、[set_default_openai_api()][agents.set_default_openai_api] 関数を使用します。 +最後に、使用する OpenAI API をカスタマイズすることもできます。デフォルトでは、 OpenAI Responses API を使用します。 [set_default_openai_api()][agents.set_default_openai_api] 関数を使用して、 Chat Completions API を使うように上書きできます。 ```python from agents import set_default_openai_api @@ -34,7 +34,7 @@ set_default_openai_api("chat_completions") ## トレーシング -トレーシング はデフォルトで有効です。デフォルトでは、上記のセクションの OpenAI API キー(つまり、環境変数または設定したデフォルトキー)を使用します。トレーシング に使用する API キーを個別に設定するには、[`set_tracing_export_api_key`][agents.set_tracing_export_api_key] 関数を使用します。 +トレーシングはデフォルトで有効です。デフォルトでは、上記のセクションの OpenAI API キー(すなわち、環境変数または設定したデフォルトキー)を使用します。トレーシングに使用する API キーを個別に設定するには、 [`set_tracing_export_api_key`][agents.set_tracing_export_api_key] 関数を使用します。 ```python from agents import set_tracing_export_api_key @@ -42,7 +42,7 @@ from agents import set_tracing_export_api_key set_tracing_export_api_key("sk-...") ``` -[`set_tracing_disabled()`][agents.set_tracing_disabled] 関数を使用して、トレーシング を完全に無効化することもできます。 +[`set_tracing_disabled()`][agents.set_tracing_disabled] 関数を使用して、トレーシングを完全に無効化することもできます。 ```python from agents import set_tracing_disabled @@ -52,9 +52,9 @@ set_tracing_disabled(True) ## デバッグログ -この SDK には、ハンドラーが設定されていない 2 つの Python ロガーがあります。デフォルトでは、これは警告とエラーが `stdout` に送られ、それ以外のログは抑制されることを意味します。 +SDK には、ハンドラーが設定されていない 2 つの Python ロガーがあります。デフォルトでは、これは警告とエラーが `stdout` に送られ、それ以外のログは抑制されることを意味します。 -詳細なログを有効にするには、[`enable_verbose_stdout_logging()`][agents.enable_verbose_stdout_logging] 関数を使用します。 +詳細ログを有効にするには、 [`enable_verbose_stdout_logging()`][agents.enable_verbose_stdout_logging] 関数を使用します。 ```python from agents import enable_verbose_stdout_logging @@ -62,7 +62,7 @@ from agents import enable_verbose_stdout_logging enable_verbose_stdout_logging() ``` -または、ハンドラー、フィルター、フォーマッターなどを追加してログをカスタマイズできます。詳細は [Python logging guide](https://docs.python.org/3/howto/logging.html) を参照してください。 +また、ハンドラー、フィルター、フォーマッターなどを追加してログをカスタマイズすることもできます。詳しくは [Python logging ガイド](https://docs.python.org/3/howto/logging.html)をご覧ください。 ```python import logging @@ -83,7 +83,7 @@ logger.addHandler(logging.StreamHandler()) ### ログ内の機微なデータ -一部のログには機微なデータ(たとえば ユーザー データ)が含まれる場合があります。これらのデータがログ出力されないようにするには、次の環境変数を設定してください。 +一部のログには機微なデータ(例: ユーザーのデータ)が含まれる場合があります。これらのデータがログに出力されないようにするには、次の環境変数を設定します。 LLM の入力と出力のロギングを無効化するには: diff --git a/docs/ja/context.md b/docs/ja/context.md index 1b027dea5..46ca83fb2 100644 --- a/docs/ja/context.md +++ b/docs/ja/context.md @@ -4,30 +4,30 @@ search: --- # コンテキスト管理 -コンテキストは多義的な用語です。ここでは主に気にするべき 2 つのコンテキストがあります。 +コンテキストは多義的な用語です。気にすべきコンテキストには主に 2 つのクラスがあります。 -1. コードからローカルに利用可能なコンテキスト: これは、ツール関数の実行時、`on_handoff` のようなコールバック、ライフサイクルフックなどで必要になる可能性があるデータや依存関係です。 -2. LLM に利用可能なコンテキスト: これは、応答を生成する際に LLM が参照できるデータです。 +1. コードからローカルに参照できるコンテキスト: これは、ツール関数の実行時、`on_handoff` のようなコールバック中、ライフサイクルフックなどで必要になる可能性のあるデータや依存関係です。 +2. LLM に提供されるコンテキスト: これは、LLM が応答を生成するときに目にするデータです。 ## ローカルコンテキスト -これは [`RunContextWrapper`][agents.run_context.RunContextWrapper] クラスと、その中の [`context`][agents.run_context.RunContextWrapper.context] プロパティで表現されます。仕組みは以下のとおりです。 +これは [`RunContextWrapper`][agents.run_context.RunContextWrapper] クラスと、その中の [`context`][agents.run_context.RunContextWrapper.context] プロパティで表現されます。仕組みは次のとおりです。 -1. 任意の Python オブジェクトを作成します。一般的なパターンは dataclass や Pydantic オブジェクトの使用です。 +1. 任意の Python オブジェクトを作成します。一般的なパターンとしては、dataclass や Pydantic オブジェクトを使います。 2. そのオブジェクトを各種の実行メソッドに渡します(例: `Runner.run(..., **context=whatever**)`)。 -3. すべてのツール呼び出しやライフサイクルフックなどには、ラッパーオブジェクト `RunContextWrapper[T]` が渡されます。ここで `T` はコンテキストオブジェクトの型を表し、`wrapper.context` からアクセスできます。 +3. すべてのツール呼び出しやライフサイクルフックなどには、ラッパーオブジェクト `RunContextWrapper[T]` が渡されます。ここで `T` はコンテキストオブジェクトの型で、`wrapper.context` からアクセスできます。 -最も **重要** な点: 特定のエージェント実行におけるすべてのエージェント、ツール関数、ライフサイクルなどは、同じ種類(_type_)のコンテキストを使用しなければなりません。 +**最も重要** な注意点: 特定のエージェント実行において、すべてのエージェント、ツール関数、ライフサイクルなどは、同じ _型_ のコンテキストを使わなければなりません。 -コンテキストは次のような用途に使えます。 +コンテキストは次のような用途に使えます: -- 実行のための状況データ(例: ユーザー名 / uid など、ユーザーに関する情報) -- 依存関係(例: ロガーオブジェクト、データ取得クラスなど) -- 補助関数 +- 実行に関するコンテキストデータ(例: ユーザー名 / UID やその他のユーザー情報) +- 依存関係(例: ロガーオブジェクト、データフェッチャーなど) +- ヘルパー関数 !!! danger "注意" - コンテキストオブジェクトは LLM には送信されません。これは純粋にローカルなオブジェクトであり、読み書きやメソッド呼び出しが可能です。 + コンテキストオブジェクトは LLM に **送られません**。これは純粋にローカルなオブジェクトであり、読み取りや書き込み、メソッド呼び出しができます。 ```python import asyncio @@ -66,17 +66,17 @@ if __name__ == "__main__": asyncio.run(main()) ``` -1. これがコンテキストオブジェクトです。ここでは dataclass を使用していますが、任意の型を使用できます。 -2. これはツールです。`RunContextWrapper[UserInfo]` を受け取ることがわかります。ツール実装はコンテキストから読み取ります。 -3. 型チェッカーがエラーを検出できるよう、ジェネリックの `UserInfo` をエージェントに付与します(たとえば、異なるコンテキスト型を取るツールを渡そうとした場合など)。 +1. これがコンテキストオブジェクトです。ここでは dataclass を使っていますが、任意の型が使えます。 +2. これはツールです。`RunContextWrapper[UserInfo]` を受け取ることがわかります。ツールの実装はコンテキストから読み取ります。 +3. 型チェッカーがエラーを検出できるよう、エージェントにジェネリックの `UserInfo` を付与します(たとえば、異なるコンテキスト型を受け取るツールを渡した場合など)。 4. コンテキストは `run` 関数に渡されます。 5. エージェントはツールを正しく呼び出し、年齢を取得します。 --- -### 詳細: `ToolContext` +### 上級: `ToolContext` -場合によっては、実行中のツールに関する追加のメタデータ(名前、コール ID、raw の引数文字列など)にアクセスしたいことがあります。 +場合によっては、実行中のツールに関する追加メタデータ(名前、呼び出し ID、raw 引数文字列など)にアクセスしたいことがあります。 そのために、`RunContextWrapper` を拡張した [`ToolContext`][agents.tool_context.ToolContext] クラスを使用できます。 ```python @@ -105,23 +105,23 @@ agent = Agent( ) ``` -`ToolContext` は `RunContextWrapper` と同じ `.context` プロパティに加えて、 -現在のツール呼び出しに固有の追加フィールドを提供します: +`ToolContext` は `RunContextWrapper` と同じ `.context` プロパティに加え、 +現在のツール呼び出しに特化した追加フィールドを提供します: - `tool_name` – 呼び出されているツールの名前 -- `tool_call_id` – このツール呼び出しの一意な識別子 -- `tool_arguments` – ツールに渡された raw の引数文字列 +- `tool_call_id` – このツール呼び出しの一意の識別子 +- `tool_arguments` – ツールに渡された raw 引数文字列 実行中にツールレベルのメタデータが必要な場合は `ToolContext` を使用してください。 -エージェントとツール間での一般的なコンテキスト共有には、`RunContextWrapper` で十分です。 +エージェントとツール間で一般的にコンテキストを共有するだけなら、`RunContextWrapper` で十分です。 --- -## エージェント / LLM コンテキスト +## エージェント / LLM のコンテキスト -LLM が呼び出されるとき、LLM が参照できるデータは会話履歴のみです。つまり、LLM に新しいデータを利用可能にしたい場合は、そのデータを会話履歴で参照可能にする必要があります。方法はいくつかあります。 +LLM が呼び出されるとき、LLM が見られるデータは会話履歴にあるものだけです。したがって、新しいデータを LLM に利用可能にしたい場合は、その履歴で参照できる形で提供する必要があります。方法はいくつかあります。 -1. エージェントの `instructions` に追加します。これは「システムプロンプト」または「開発者メッセージ」とも呼ばれます。システムプロンプトは静的な文字列でも、コンテキストを受け取って文字列を出力する動的な関数でも構いません。これは常に有用な情報(例: ユーザー名や現在の日付)に適した一般的な手法です。 -2. `Runner.run` を呼び出す際に `input` に追加します。これは `instructions` の手法に似ていますが、[chain of command](https://cdn.openai.com/spec/model-spec-2024-05-08.html#follow-the-chain-of-command) の下位に位置するメッセージを持てます。 -3. 関数ツールで公開します。これはオンデマンドのコンテキストに有用です。LLM が必要なときにデータ取得のためにツールを呼び出せます。 -4. リトリーバルや Web 検索を使用します。これらは、ファイルやデータベース(リトリーバル)、または Web(Web 検索)から関連データを取得できる特別なツールです。これは、応答を関連するコンテキストデータで「グラウンディング」するのに役立ちます。 \ No newline at end of file +1. エージェントの `instructions` に追加します。これは "system prompt"(開発者メッセージ)とも呼ばれます。system prompt は静的な文字列でも、コンテキストを受け取って文字列を出力する動的な関数でもかまいません。これは常に有用な情報(例: ユーザー名や現在の日付)に適した一般的な手法です。 +2. `Runner.run` を呼び出すときに `input` に追加します。これは `instructions` の手法に似ていますが、[指揮系統](https://cdn.openai.com/spec/model-spec-2024-05-08.html#follow-the-chain-of-command) の下位にあるメッセージを持てます。 +3. 関数ツール経由で公開します。これはオンデマンドのコンテキストに有用です。LLM が必要なときにデータを取得するため、ツールを呼び出せます。 +4. リトリーバル(retrieval)や Web 検索を使用します。これらは、ファイルやデータベースから関連データを取得(リトリーバル)したり、Web から取得(Web 検索)したりできる特別なツールです。これは、応答を関連するコンテキストデータに「根拠付け」するのに有用です。 \ No newline at end of file diff --git a/docs/ja/examples.md b/docs/ja/examples.md index e5d3d59e6..d0a7f5b27 100644 --- a/docs/ja/examples.md +++ b/docs/ja/examples.md @@ -4,90 +4,90 @@ search: --- # コード例 -[repo](https://github.com/openai/openai-agents-python/tree/main/examples) のコード例セクションにある SDK のさまざまなサンプル実装をご覧ください。これらのコード例は、異なるパターンや機能を示すいくつかのカテゴリーに整理されています。 +[リポジトリ](https://github.com/openai/openai-agents-python/tree/main/examples) の examples セクションで、SDK の多様なサンプル実装を参照できます。これらの コード例 は、異なるパターンや機能を示す複数の カテゴリー に整理されています。 ## カテゴリー -- **[agent_patterns](https://github.com/openai/openai-agents-python/tree/main/examples/agent_patterns):** - このカテゴリーのコード例は、次のような一般的なエージェント設計パターンを示します。 - - - 決定的なワークフロー - - ツールとしてのエージェント - - エージェントの並列実行 - - 条件付きのツール使用 - - 入出力のガードレール - - 判定者としての LLM - - ルーティング - - ストリーミング ガードレール - -- **[basic](https://github.com/openai/openai-agents-python/tree/main/examples/basic):** - このカテゴリーのコード例は、次のような SDK の基礎的な機能を紹介します。 - - - Hello World のコード例(既定のモデル、GPT-5、オープンウェイトのモデル) - - エージェントのライフサイクル管理 - - 動的な システムプロンプト - - ストリーミング 出力(テキスト、アイテム、関数呼び出し引数) - - プロンプトテンプレート - - ファイル処理(ローカルとリモート、画像と PDF) - - 利用状況の追跡 - - 非厳密な出力型 - - 以前のレスポンス ID の使用 - -- **[customer_service](https://github.com/openai/openai-agents-python/tree/main/examples/customer_service):** - 航空会社向けのカスタマーサービス システムの例。 - -- **[financial_research_agent](https://github.com/openai/openai-agents-python/tree/main/examples/financial_research_agent):** - エージェント と ツール を用いた金融データ分析のための構造化されたリサーチ ワークフローを示す金融リサーチ エージェント。 - -- **[handoffs](https://github.com/openai/openai-agents-python/tree/main/examples/handoffs):** - メッセージフィルタリング付きのエージェントのハンドオフの実例をご覧ください。 - -- **[hosted_mcp](https://github.com/openai/openai-agents-python/tree/main/examples/hosted_mcp):** - ホスト型の MCP (Model Context Protocol) コネクタと承認の使い方を示すコード例。 - -- **[mcp](https://github.com/openai/openai-agents-python/tree/main/examples/mcp):** - MCP (Model Context Protocol) でエージェントを構築する方法を学べます。次を含みます: - - - ファイルシステムのコード例 - - Git のコード例 - - MCP プロンプト サーバーのコード例 - - SSE (Server-Sent Events) のコード例 - - ストリーミング可能な HTTP のコード例 - -- **[memory](https://github.com/openai/openai-agents-python/tree/main/examples/memory):** - エージェント向けのさまざまなメモリ実装のコード例。次を含みます: - - - SQLite セッションストレージ - - 高度な SQLite セッションストレージ - - Redis セッションストレージ - - SQLAlchemy セッションストレージ - - 暗号化セッションストレージ - - OpenAI セッションストレージ - -- **[model_providers](https://github.com/openai/openai-agents-python/tree/main/examples/model_providers):** - カスタムプロバイダーや LiteLLM 連携を含む、OpenAI 以外のモデルを SDK で使う方法を紹介します。 - -- **[realtime](https://github.com/openai/openai-agents-python/tree/main/examples/realtime):** - SDK を使ってリアルタイム体験を構築する方法を示すコード例。次を含みます: - - - Web アプリケーション - - コマンドライン インターフェイス - - Twilio 連携 - -- **[reasoning_content](https://github.com/openai/openai-agents-python/tree/main/examples/reasoning_content):** - 推論コンテンツと structured outputs の扱い方を示すコード例。 - -- **[research_bot](https://github.com/openai/openai-agents-python/tree/main/examples/research_bot):** - 複雑な複数のエージェント によるリサーチ ワークフローを示す、シンプルな ディープリサーチ クローン。 - -- **[tools](https://github.com/openai/openai-agents-python/tree/main/examples/tools):** - 次のような OpenAI がホストするツール の実装方法を学べます。 - - - Web 検索 および フィルター付き Web 検索 - - ファイル検索 - - Code Interpreter - - コンピュータ操作 - - 画像生成 - -- **[voice](https://github.com/openai/openai-agents-python/tree/main/examples/voice):** - TTS と STT モデルを用いた音声 エージェントのコード例。音声のストリーミング のコード例も含みます。 \ No newline at end of file +- **[agent_patterns](https://github.com/openai/openai-agents-python/tree/main/examples/agent_patterns):** + この カテゴリー の コード例 は、次のような一般的な エージェント の設計パターンを示します。 + + - 決定的なワークフロー + - ツールとしての エージェント + - エージェントの並列実行 + - 条件付きツール使用 + - 入力/出力のガードレール + - 審査員としての LLM + - ルーティング + - ストリーミングのガードレール + +- **[basic](https://github.com/openai/openai-agents-python/tree/main/examples/basic):** + これらの コード例 は、次のような SDK の基礎的な機能を紹介します。 + + - Hello World の コード例(デフォルトモデル、GPT-5、オープンウェイトモデル) + - エージェントのライフサイクル管理 + - 動的な システムプロンプト + - ストリーミング出力(テキスト、アイテム、関数呼び出しの引数) + - プロンプトテンプレート + - ファイル処理(ローカルとリモート、画像と PDF) + - 使用状況の追跡 + - 厳密でない出力タイプ + - 以前のレスポンス ID の使用 + +- **[customer_service](https://github.com/openai/openai-agents-python/tree/main/examples/customer_service):** + 航空会社向けのカスタマーサービス システムの例。 + +- **[financial_research_agent](https://github.com/openai/openai-agents-python/tree/main/examples/financial_research_agent):** + 金融データ分析のための エージェント とツールを用いた構造化されたリサーチ ワークフローを示す金融リサーチ エージェント。 + +- **[handoffs](https://github.com/openai/openai-agents-python/tree/main/examples/handoffs):** + メッセージフィルタリングを伴うエージェントのハンドオフの実用的な コード例。 + +- **[hosted_mcp](https://github.com/openai/openai-agents-python/tree/main/examples/hosted_mcp):** + ホスト型 MCP (Model Context Protocol) のコネクタと承認の使い方を示す コード例。 + +- **[mcp](https://github.com/openai/openai-agents-python/tree/main/examples/mcp):** + MCP (Model Context Protocol) で エージェント を構築する方法を学べます。内容例: + + - ファイルシステムの コード例 + - Git の コード例 + - MCP プロンプト サーバーの コード例 + - SSE (Server-Sent Events) の コード例 + - ストリーム可能な HTTP の コード例 + +- **[memory](https://github.com/openai/openai-agents-python/tree/main/examples/memory):** + エージェント 向けのさまざまなメモリ実装の コード例。内容: + + - SQLite セッションストレージ + - 高度な SQLite セッションストレージ + - Redis セッションストレージ + - SQLAlchemy セッションストレージ + - 暗号化セッションストレージ + - OpenAI セッションストレージ + +- **[model_providers](https://github.com/openai/openai-agents-python/tree/main/examples/model_providers):** + カスタムプロバイダーや LiteLLM 連携を含む、非 OpenAI モデルを SDK で使う方法を紹介。 + +- **[realtime](https://github.com/openai/openai-agents-python/tree/main/examples/realtime):** + SDK を用いてリアルタイムの体験を構築する コード例。内容: + + - Web アプリケーション + - コマンドライン インターフェイス + - Twilio 連携 + +- **[reasoning_content](https://github.com/openai/openai-agents-python/tree/main/examples/reasoning_content):** + 推論コンテンツと structured outputs の扱い方を示す コード例。 + +- **[research_bot](https://github.com/openai/openai-agents-python/tree/main/examples/research_bot):** + 複雑なマルチ エージェントのリサーチ ワークフローを示す、シンプルな deep research クローン。 + +- **[tools](https://github.com/openai/openai-agents-python/tree/main/examples/tools):** + 次のような OpenAI がホストするツール の実装方法を学べます。 + + - Web 検索 と、フィルタ付きの Web 検索 + - ファイル検索 + - Code Interpreter + - コンピュータ操作 + - 画像生成 + +- **[voice](https://github.com/openai/openai-agents-python/tree/main/examples/voice):** + 音声 エージェント の コード例。TTS と STT モデルを使用し、ストリーミング音声の コード例 も含みます。 \ No newline at end of file diff --git a/docs/ja/guardrails.md b/docs/ja/guardrails.md index d01fa81b8..ec6e9c4bf 100644 --- a/docs/ja/guardrails.md +++ b/docs/ja/guardrails.md @@ -4,44 +4,44 @@ search: --- # ガードレール -ガードレール は _並行して_ エージェント を実行し、 ユーザー の入力に対するチェックや検証を可能にします。たとえば、顧客からのリクエスト対応に非常に高性能(そのため遅く/高価)なモデルを使う エージェント があるとします。悪意のある ユーザー がそのモデルに数学の宿題の手伝いをさせるのは避けたいはずです。そこで、速く/安価なモデルで ガードレール を走らせます。ガードレール が不正な利用を検知した場合は、即座にエラーを送出して高価なモデルの実行を停止し、時間やコストを節約できます。 +ガードレールはエージェントと _並行して_ 実行され、ユーザー入力のチェックや検証を行います。たとえば、顧客からのリクエストに対応するために非常に高性能(ゆえに遅く/高価)なモデルを使うエージェントがあるとします。悪意のあるユーザーがモデルに数学の宿題を手伝わせようとするのは避けたいはずです。そこで、迅速/低コストなモデルでガードレールを実行できます。ガードレールが悪意のある利用を検出した場合、即座にエラーを送出し、高価なモデルの実行を停止して時間とコストを節約できます。 -ガードレール には 2 種類あります: +ガードレールには 2 種類あります: -1. 入力ガードレール は初期の ユーザー 入力に対して実行されます -2. 出力ガードレール は最終的な エージェント の出力に対して実行されます +1. 入力ガードレールは最初のユーザー入力に対して実行されます +2. 出力ガードレールは最終的なエージェント出力に対して実行されます ## 入力ガードレール -入力ガードレール は 3 ステップで動作します: +入力ガードレールは 3 つの手順で実行されます: -1. まず、エージェント に渡されたものと同じ入力を ガードレール が受け取ります。 -2. 次に、ガードレール 関数が実行され、[`GuardrailFunctionOutput`][agents.guardrail.GuardrailFunctionOutput] を生成し、これを [`InputGuardrailResult`][agents.guardrail.InputGuardrailResult] にラップします -3. 最後に、[`.tripwire_triggered`][agents.guardrail.GuardrailFunctionOutput.tripwire_triggered] が true かどうかを確認します。true の場合、[`InputGuardrailTripwireTriggered`][agents.exceptions.InputGuardrailTripwireTriggered] 例外が送出され、 ユーザー への適切な応答や例外処理が可能になります。 +1. まず、ガードレールはエージェントに渡されたのと同じ入力を受け取ります。 +2. 次に、ガードレール関数が実行され、[`GuardrailFunctionOutput`][agents.guardrail.GuardrailFunctionOutput] を生成し、それが [`InputGuardrailResult`][agents.guardrail.InputGuardrailResult] にラップされます。 +3. 最後に、[`.tripwire_triggered`][agents.guardrail.GuardrailFunctionOutput.tripwire_triggered] が true かどうかを確認します。true の場合、[`InputGuardrailTripwireTriggered`][agents.exceptions.InputGuardrailTripwireTriggered] 例外が送出されるため、ユーザーへの適切な対応や例外処理ができます。 !!! Note - 入力ガードレール は ユーザー 入力での実行を想定しているため、エージェント の ガードレール は、その エージェント が最初のエージェントである場合にのみ実行されます。なぜ `guardrails` プロパティが エージェント 側にあり、`Runner.run` に渡さないのかと疑問に思うかもしれません。これは、ガードレール は実際のエージェントに密接に関係する傾向があるためです。エージェント ごとに異なる ガードレール を実行することが多いため、コードを同じ場所に置くことで可読性が向上します。 + 入力ガードレールはユーザー入力に対して実行されることを意図しているため、エージェントのガードレールはそのエージェントが最初のエージェントである場合にのみ実行されます。なぜ `guardrails` プロパティがエージェント側にあり、`Runner.run` に渡さないのかと疑問に思うかもしれません。これは、ガードレールが実際のエージェントに密接に関連する傾向があるためです。エージェントごとに異なるガードレールを実行することになるので、コードを同じ場所に置くことで可読性が向上します。 ## 出力ガードレール -出力ガードレール は 3 ステップで動作します: +出力ガードレールは 3 つの手順で実行されます: -1. まず、エージェント が生成した出力を ガードレール が受け取ります。 -2. 次に、ガードレール 関数が実行され、[`GuardrailFunctionOutput`][agents.guardrail.GuardrailFunctionOutput] を生成し、これを [`OutputGuardrailResult`][agents.guardrail.OutputGuardrailResult] にラップします -3. 最後に、[`.tripwire_triggered`][agents.guardrail.GuardrailFunctionOutput.tripwire_triggered] が true かどうかを確認します。true の場合、[`OutputGuardrailTripwireTriggered`][agents.exceptions.OutputGuardrailTripwireTriggered] 例外が送出され、 ユーザー への適切な応答や例外処理が可能になります。 +1. まず、ガードレールはエージェントによって生成された出力を受け取ります。 +2. 次に、ガードレール関数が実行され、[`GuardrailFunctionOutput`][agents.guardrail.GuardrailFunctionOutput] を生成し、それが [`OutputGuardrailResult`][agents.guardrail.OutputGuardrailResult] にラップされます。 +3. 最後に、[`.tripwire_triggered`][agents.guardrail.GuardrailFunctionOutput.tripwire_triggered] が true かどうかを確認します。true の場合、[`OutputGuardrailTripwireTriggered`][agents.exceptions.OutputGuardrailTripwireTriggered] 例外が送出されるため、ユーザーへの適切な対応や例外処理ができます。 !!! Note - 出力ガードレール は最終的な エージェント の出力での実行を想定しているため、エージェント の ガードレール は、その エージェント が最後のエージェントである場合にのみ実行されます。入力ガードレール と同様に、ガードレール は実際のエージェントに密接に関係する傾向があるため、コードを同じ場所に置くことで可読性が向上します。 + 出力ガードレールは最終的なエージェント出力に対して実行されることを意図しているため、エージェントのガードレールはそのエージェントが最後のエージェントである場合にのみ実行されます。入力ガードレールと同様に、ガードレールは実際のエージェントに密接に関連する傾向があるため、コードを同じ場所に置くことで可読性が向上します。 -## トリップワイヤ +## トリップワイヤー -入力または出力が ガードレール に通らなかった場合、ガードレール はトリップワイヤでそれを通知できます。トリップワイヤが発動した ガードレール を検知するとすぐに、`{Input,Output}GuardrailTripwireTriggered` 例外を送出し、エージェント の実行を停止します。 +入力または出力がガードレールを通過できなかった場合、ガードレールはトリップワイヤーでそれを示せます。トリップワイヤーが作動したガードレールを検出するとすぐに、`{Input,Output}GuardrailTripwireTriggered` 例外を送出し、エージェントの実行を停止します。 ## ガードレールの実装 -入力を受け取り、[`GuardrailFunctionOutput`][agents.guardrail.GuardrailFunctionOutput] を返す関数を用意する必要があります。次の例では、内部で エージェント を実行することでこれを行います。 +入力を受け取り、[`GuardrailFunctionOutput`][agents.guardrail.GuardrailFunctionOutput] を返す関数を提供する必要があります。次の例では、内部でエージェントを実行してこれを行います。 ```python from pydantic import BaseModel @@ -94,12 +94,12 @@ async def main(): print("Math homework guardrail tripped") ``` -1. この エージェント を ガードレール 関数内で使用します。 -2. これは エージェント の入力/コンテキストを受け取り、結果を返す ガードレール 関数です。 -3. ガードレール の結果に追加情報を含めることができます。 -4. これはワークフローを定義する実際の エージェント です。 +1. このエージェントをガードレール関数内で使用します。 +2. これはエージェントの入力/コンテキストを受け取り、結果を返すガードレール関数です。 +3. ガードレール結果に追加情報を含めることができます。 +4. これはワークフローを定義する実際のエージェントです。 -出力ガードレール も同様です。 +出力ガードレールも同様です。 ```python from pydantic import BaseModel @@ -152,7 +152,7 @@ async def main(): print("Math output guardrail tripped") ``` -1. これは実際の エージェント の出力型です。 -2. これは ガードレール の出力型です。 -3. これは エージェント の出力を受け取り、結果を返す ガードレール 関数です。 -4. これはワークフローを定義する実際の エージェント です。 \ No newline at end of file +1. これは実際のエージェントの出力型です。 +2. これはガードレールの出力型です。 +3. これはエージェントの出力を受け取り、結果を返すガードレール関数です。 +4. これはワークフローを定義する実際のエージェントです。 \ No newline at end of file diff --git a/docs/ja/handoffs.md b/docs/ja/handoffs.md index 323bc8507..7bacede3b 100644 --- a/docs/ja/handoffs.md +++ b/docs/ja/handoffs.md @@ -4,17 +4,17 @@ search: --- # ハンドオフ -ハンドオフは、ある エージェント が別の エージェント にタスクを委譲できるようにするものです。これは、異なる エージェント がそれぞれ異なる分野を専門としている状況で特に有用です。例えば、カスタマーサポートアプリでは、注文状況、返金、FAQ などのタスクを個別に担当する エージェント が存在するかもしれません。 +ハンドオフは、あるエージェントが別のエージェントにタスクを委任できるようにします。これは、異なるエージェントがそれぞれ異なる分野に特化しているシナリオで特に有用です。たとえば、カスタマーサポートアプリでは、注文状況、返金、FAQ などのタスクをそれぞれ専門に扱うエージェントが存在する場合があります。 -ハンドオフは LLM にはツールとして表現されます。たとえば `Refund Agent` へのハンドオフがある場合、ツール名は `transfer_to_refund_agent` のようになります。 +ハンドオフは LLM にとってツールとして表現されます。たとえば、`Refund Agent` というエージェントへのハンドオフがある場合、ツール名は `transfer_to_refund_agent` になります。 ## ハンドオフの作成 -すべての エージェント は [`handoffs`][agents.agent.Agent.handoffs] パラメーターを持ち、これは `Agent` を直接渡すことも、ハンドオフをカスタマイズする `Handoff` オブジェクトを渡すこともできます。 +すべてのエージェントには [`handoffs`][agents.agent.Agent.handoffs] パラメーターがあり、これは `Agent` を直接受け取るか、ハンドオフをカスタマイズする `Handoff` オブジェクトを受け取ります。 -Agents SDK が提供する [`handoff()`][agents.handoffs.handoff] 関数を使ってハンドオフを作成できます。この関数では、ハンドオフ先の エージェント の指定に加え、任意のオーバーライドや入力フィルターを指定できます。 +Agents SDK が提供する [`handoff()`][agents.handoffs.handoff] 関数を使ってハンドオフを作成できます。この関数では、引き渡し先のエージェントに加えて、任意のオーバーライドや入力フィルターを指定できます。 -### 基本的な使用方法 +### 基本的な使い方 シンプルなハンドオフの作り方は次のとおりです。 @@ -28,19 +28,19 @@ refund_agent = Agent(name="Refund agent") triage_agent = Agent(name="Triage agent", handoffs=[billing_agent, handoff(refund_agent)]) ``` -1. `billing_agent` のように エージェント を直接使うことも、`handoff()` 関数を使うこともできます。 +1. エージェントを直接使用(`billing_agent` のように)することも、`handoff()` 関数を使用することもできます。 ### `handoff()` 関数によるハンドオフのカスタマイズ [`handoff()`][agents.handoffs.handoff] 関数では、さまざまなカスタマイズが可能です。 -- `agent`: ハンドオフ先の エージェント です。 -- `tool_name_override`: 既定では `Handoff.default_tool_name()` が使われ、`transfer_to_` に解決されます。これを上書きできます。 -- `tool_description_override`: `Handoff.default_tool_description()` による既定のツール説明を上書きします。 -- `on_handoff`: ハンドオフが呼び出されたときに実行されるコールバック関数。ハンドオフが呼ばれたタイミングでデータ取得を開始するなどに便利です。この関数はエージェントのコンテキストを受け取り、オプションで LLM が生成した入力も受け取れます。入力データは `input_type` パラメーターで制御します。 -- `input_type`: ハンドオフが受け取る入力の型(任意)。 -- `input_filter`: 次の エージェント が受け取る入力をフィルタリングできます。詳細は後述します。 -- `is_enabled`: ハンドオフを有効にするかどうか。ブール値、またはブール値を返す関数を指定でき、実行時に動的に有効/無効を切り替えられます。 +- `agent`: これは引き渡し先のエージェントです。 +- `tool_name_override`: 既定では `Handoff.default_tool_name()` 関数が使われ、`transfer_to_` に解決されます。これを上書きできます。 +- `tool_description_override`: `Handoff.default_tool_description()` の既定のツール説明を上書きします。 +- `on_handoff`: ハンドオフが呼び出されたときに実行されるコールバック関数です。ハンドオフが呼び出されることが分かった時点でのデータ取得の開始などに役立ちます。この関数はエージェントのコンテキストを受け取り、任意で LLM が生成した入力も受け取れます。入力データは `input_type` パラメーターで制御されます。 +- `input_type`: ハンドオフが想定する入力の型(任意)。 +- `input_filter`: 次のエージェントが受け取る入力をフィルタリングできます。詳細は以下をご覧ください。 +- `is_enabled`: ハンドオフが有効かどうか。これは boolean または boolean を返す関数にでき、実行時に動的にハンドオフを有効/無効にできます。 ```python from agents import Agent, handoff, RunContextWrapper @@ -58,9 +58,9 @@ handoff_obj = handoff( ) ``` -## ハンドオフの入力 +## ハンドオフ入力 -状況によっては、ハンドオフを呼び出す際に LLM に一部のデータを提供してほしい場合があります。例えば「エスカレーション エージェント」へのハンドオフを想定してください。ログのために理由を渡したい、ということがあるでしょう。 +状況によっては、ハンドオフを呼び出す際に LLM にいくらかのデータを提供してほしいことがあります。たとえば「エスカレーションエージェント」へのハンドオフを想像してください。ログのために理由を提供したいかもしれません。 ```python from pydantic import BaseModel @@ -84,9 +84,9 @@ handoff_obj = handoff( ## 入力フィルター -ハンドオフが起きると、新しい エージェント が会話を引き継ぎ、これまでの会話履歴全体を参照できるのが通常です。これを変更したい場合は、[`input_filter`][agents.handoffs.Handoff.input_filter] を設定できます。入力フィルターは、既存の入力を [`HandoffInputData`][agents.handoffs.HandoffInputData] 経由で受け取り、新しい `HandoffInputData` を返す関数です。 +ハンドオフが発生すると、新しいエージェントが会話を引き継ぎ、これまでの会話履歴全体を参照できるかのように振る舞います。これを変更したい場合は、[`input_filter`][agents.handoffs.Handoff.input_filter] を設定できます。入力フィルターは、[`HandoffInputData`][agents.handoffs.HandoffInputData] を介して既存の入力を受け取り、新しい `HandoffInputData` を返す関数です。 -一般的なパターン(例えば履歴からすべてのツール呼び出しを削除するなど)は、[`agents.extensions.handoff_filters`][] に用意されています。 +いくつかの一般的なパターン(たとえば履歴からすべてのツール呼び出しを削除するなど)は、[`agents.extensions.handoff_filters`][] に実装済みです。 ```python from agents import Agent, handoff @@ -100,11 +100,11 @@ handoff_obj = handoff( ) ``` -1. これは `FAQ agent` が呼び出される際、履歴からツールを自動的にすべて削除します。 +1. これは、`FAQ agent` が呼び出されたときに履歴からすべてのツールを自動的に削除します。 ## 推奨プロンプト -LLM がハンドオフを正しく理解できるようにするため、エージェント にハンドオフに関する情報を含めることを推奨します。[`agents.extensions.handoff_prompt.RECOMMENDED_PROMPT_PREFIX`][] に推奨のプレフィックスがあり、または [`agents.extensions.handoff_prompt.prompt_with_handoff_instructions`][] を呼び出して、推奨情報をプロンプトに自動追加できます。 +LLM がハンドオフを正しく理解できるようにするため、エージェントにハンドオフに関する情報を含めることをおすすめします。[`agents.extensions.handoff_prompt.RECOMMENDED_PROMPT_PREFIX`][] に推奨のプレフィックスを用意しています。あるいは、[`agents.extensions.handoff_prompt.prompt_with_handoff_instructions`][] を呼び出して、推奨データをプロンプトに自動的に追加することもできます。 ```python from agents import Agent diff --git a/docs/ja/index.md b/docs/ja/index.md index 9db90bd3c..c7905435a 100644 --- a/docs/ja/index.md +++ b/docs/ja/index.md @@ -4,31 +4,31 @@ search: --- # OpenAI Agents SDK -[OpenAI Agents SDK](https://github.com/openai/openai-agents-python) は、抽象化を最小限に抑えた軽量で使いやすいパッケージで、エージェント型の AI アプリを構築できるようにします。これは、私たちの以前のエージェント向け実験である [Swarm](https://github.com/openai/swarm/tree/main) の本番運用に対応したアップグレード版です。Agents SDK はごく少数の基本コンポーネントで構成されています: +[OpenAI Agents SDK](https://github.com/openai/openai-agents-python) は、最小限の抽象化で軽量かつ使いやすいパッケージとして、エージェント型 AI アプリを構築できるようにするものです。これは、以前のエージェント向け実験的プロジェクトである [Swarm](https://github.com/openai/swarm/tree/main) のプロダクション対応アップグレードです。Agents SDK には非常に小さな基本コンポーネントの集合があります。 -- **エージェント**: instructions と tools を備えた LLM -- **ハンドオフ**: 特定のタスクを他の エージェント に委任できる仕組み -- **ガードレール**: エージェントの入力と出力の検証を可能にする仕組み -- **セッション**: エージェントの実行間で会話履歴を自動的に維持 +- **エージェント** 、`instructions` とツールを備えた LLM +- **ハンドオフ** 、エージェントが特定のタスクを他のエージェントに委任できる仕組み +- **ガードレール** 、エージェントの入力と出力の検証を可能にする仕組み +- **セッション** 、エージェントの実行間で会話履歴を自動的に維持 -Python と組み合わせることで、これらの基本コンポーネントはツールと エージェント の複雑な関係を表現でき、急な学習コストなしに実運用アプリケーションを構築できます。さらに、この SDK には組み込みの **トレーシング** があり、エージェントのフローを可視化・デバッグできるほか、評価や、アプリケーション向けのモデルの微調整まで行えます。 +Python と組み合わせることで、これらの基本コンポーネントはツールとエージェント間の複雑な関係を表現でき、急な学習曲線なしに実運用のアプリケーションを構築できます。加えて、SDK には組み込みの **トレーシング** があり、エージェントのフローを可視化・デバッグし、評価したり、アプリケーション向けにモデルをファインチューニングすることもできます。 ## Agents SDK を使う理由 -この SDK は次の 2 つの設計原則に基づいています: +この SDK には、次の 2 つの設計原則があります。 -1. 使う価値がある十分な機能を備えつつ、学習を素早くするために基本コンポーネントは少数に保つ。 -2. すぐに高品質に動作し、必要に応じて挙動を細かくカスタマイズできる。 +1. 使う価値があるだけの十分な機能を備えつつ、学習が速く済むよう基本コンポーネントは少なく。 +2. すぐに高品質に動作しつつ、発生する処理を正確にカスタマイズ可能に。 -SDK の主な機能は次のとおりです: +SDK の主な機能は以下のとおりです。 -- エージェントループ: ツールの呼び出し、結果を LLM に渡す処理、LLM が完了するまでのループを内蔵。 -- Python ファースト: 新しい抽象化を学ぶのではなく、言語の組み込み機能で エージェント をオーケストレーション・連鎖。 -- ハンドオフ: 複数の エージェント 間での調整と委任を可能にする強力な機能。 -- ガードレール: エージェント と並行して入力の検証やチェックを実行し、失敗時は早期に中断。 -- セッション: エージェントの実行間で会話履歴を自動管理し、手動の状態管理を不要に。 -- 関数ツール: 任意の Python 関数をツール化し、自動スキーマ生成と Pydantic ベースの検証を提供。 -- トレーシング: ワークフローの可視化・デバッグ・監視を可能にし、OpenAI の評価・微調整・蒸留ツール群も活用可能。 +- エージェント ループ: ツールの呼び出し、実行結果を LLM に送信、LLM の完了までのループを処理する組み込みループ。 +- Python ファースト: 新しい抽象を学ぶことなく、言語の機能を用いてエージェントをオーケストレーション・連結。 +- ハンドオフ: 複数のエージェント間での調整と委任を可能にする強力な機能。 +- ガードレール: エージェントと並行して入力の検証やチェックを実行し、チェックが失敗した場合は早期終了。 +- セッション: エージェントの実行間で会話履歴を自動管理し、手動での状態管理を不要化。 +- 関数ツール: 任意の Python 関数をツール化し、自動スキーマ生成と Pydantic ベースの検証を提供。 +- トレーシング: ワークフローの可視化・デバッグ・監視ができ、OpenAI の評価、微調整、蒸留ツール群も活用可能。 ## インストール diff --git a/docs/ja/mcp.md b/docs/ja/mcp.md index 7d3247943..4e45ad728 100644 --- a/docs/ja/mcp.md +++ b/docs/ja/mcp.md @@ -4,32 +4,34 @@ search: --- # Model context protocol (MCP) -[Model context protocol](https://modelcontextprotocol.io/introduction)(MCP)は、アプリケーションがツールやコンテキストを言語モデルに公開する方法を標準化します。公式ドキュメントより: +[Model context protocol](https://modelcontextprotocol.io/introduction) (MCP) は、アプリケーションがツールとコンテキストを言語モデルに公開する方法を標準化します。公式ドキュメントより: -> MCP は、アプリケーションが LLMs にコンテキストを提供する方法を標準化するオープンなプロトコルです。MCP を AI アプリケーションのための USB-C ポートのようなものだと考えてください。USB-C がデバイスをさまざまな周辺機器やアクセサリーに接続する標準化された方法を提供するように、MCP は AI モデルをさまざまなデータソースやツールに接続する標準化された方法を提供します。 +> MCP is an open protocol that standardizes how applications provide context to LLMs. Think of MCP like a USB-C port for AI +> applications. Just as USB-C provides a standardized way to connect your devices to various peripherals and accessories, MCP +> provides a standardized way to connect AI models to different data sources and tools. -Agents Python SDK は複数の MCP トランスポートに対応しています。これにより、既存の MCP サーバーを再利用したり、独自に構築して、ファイルシステム、HTTP、またはコネクタに裏付けられたツールを エージェント に公開できます。 +Agents Python SDK は複数の MCP トランスポートに対応します。これにより、既存の MCP サーバーを再利用したり、独自に構築してファイルシステム、HTTP、またはコネクタに裏付けられたツールをエージェントに公開したりできます。 -## MCP 統合の選択 +## Choosing an MCP integration -MCP サーバーを エージェント に接続する前に、ツール呼び出しをどこで実行するか、また到達可能なトランスポートは何かを決めてください。以下のマトリクスは、Python SDK がサポートするオプションをまとめたものです。 +エージェントに MCP サーバーを接続する前に、ツール呼び出しをどこで実行するか、どのトランスポートに到達できるかを決めます。以下のマトリクスは、Python SDK がサポートするオプションをまとめたものです。 -| 必要なこと | 推奨オプション | -| ------------------------------------------------------------------------------------ | -------------------------------------------------------- | -| OpenAI の Responses API が、モデルの代理で公開到達可能な MCP サーバーを呼び出せるようにする | **Hosted MCP server tools** 経由で [`HostedMCPTool`][agents.tool.HostedMCPTool] | -| ローカルまたはリモートで自分が運用する Streamable HTTP サーバーに接続する | **Streamable HTTP MCP servers** 経由で [`MCPServerStreamableHttp`][agents.mcp.server.MCPServerStreamableHttp] | -| Server-Sent Events を伴う HTTP を実装するサーバーと通信する | **HTTP with SSE MCP servers** 経由で [`MCPServerSse`][agents.mcp.server.MCPServerSse] | -| ローカルプロセスを起動し、stdin/stdout で通信する | **stdio MCP servers** 経由で [`MCPServerStdio`][agents.mcp.server.MCPServerStdio] | +| What you need | Recommended option | +| ------------------------------------------------------------------------------------ | ----------------------------------------------------- | +| OpenAI の Responses API がモデルの代わりに公開到達可能な MCP サーバーを呼び出せるようにする | **Hosted MCP server tools** via [`HostedMCPTool`][agents.tool.HostedMCPTool] | +| ローカルまたはリモートで実行している Streamable HTTP サーバーに接続する | **Streamable HTTP MCP servers** via [`MCPServerStreamableHttp`][agents.mcp.server.MCPServerStreamableHttp] | +| Server-Sent Events を伴う HTTP を実装したサーバーと対話する | **HTTP with SSE MCP servers** via [`MCPServerSse`][agents.mcp.server.MCPServerSse] | +| ローカルプロセスを起動し、stdin/stdout 経由で通信する | **stdio MCP servers** via [`MCPServerStdio`][agents.mcp.server.MCPServerStdio] | -以下のセクションでは、それぞれのオプションの使用方法、設定方法、どのトランスポートを選ぶべきかを解説します。 +以下のセクションでは、それぞれのオプションの使い方、設定方法、どのトランスポートを選ぶべきかを説明します。 ## 1. Hosted MCP server tools -Hosted ツールでは、ツールの往復処理全体を OpenAI のインフラストラクチャに任せます。あなたのコードがツールを列挙・呼び出す代わりに、[`HostedMCPTool`][agents.tool.HostedMCPTool] が サーバーラベル(およびオプションのコネクタ メタデータ)を Responses API に転送します。モデルはリモートサーバーのツールを列挙して呼び出し、あなたの Python プロセスへの追加のコールバックは不要です。Hosted ツールは現在、Responses API の hosted MCP 統合をサポートする OpenAI モデルで動作します。 +ホスト型ツールは、ツールのラウンドトリップ全体を OpenAI のインフラに委ねます。あなたのコードがツールを列挙・呼び出す代わりに、[`HostedMCPTool`][agents.tool.HostedMCPTool] がサーバーのラベル (および任意のコネクタメタデータ) を Responses API に転送します。モデルはリモートサーバーのツールを列挙し、あなたの Python プロセスへの追加コールバックなしにそれらを呼び出します。ホスト型ツールは現在、Responses API のホスト型 MCP 連携をサポートする OpenAI モデルで動作します。 -### 基本的な hosted MCP ツール +### Basic hosted MCP tool -エージェント の `tools` リストに [`HostedMCPTool`][agents.tool.HostedMCPTool] を追加して hosted ツールを作成します。`tool_config` の dict は、REST API に送信する JSON と同じ構造です: +エージェントの `tools` リストに [`HostedMCPTool`][agents.tool.HostedMCPTool] を追加してホスト型ツールを作成します。`tool_config` の dict は、REST API に送る JSON をそのまま反映します: ```python import asyncio @@ -57,11 +59,11 @@ async def main() -> None: asyncio.run(main()) ``` -hosted サーバーはツールを自動的に公開します。`mcp_servers` に追加する必要はありません。 +ホスト型サーバーはツールを自動的に公開します。`mcp_servers` に追加する必要はありません。 -### ストリーミングする hosted MCP 結果 +### Streaming hosted MCP results -Hosted ツールは 関数ツール とまったく同じ方法で ストリーミング をサポートします。`Runner.run_streamed` に `stream=True` を渡すと、モデルが処理中でも増分の MCP 出力を消費できます: +ホスト型ツールは、関数ツールとまったく同じ方法で結果のストリーミングに対応します。`Runner.run_streamed` に `stream=True` を渡すと、モデルが処理中でも増分的な MCP 出力を消費できます: ```python result = Runner.run_streamed(agent, "Summarise this repository's top languages") @@ -71,9 +73,9 @@ async for event in result.stream_events(): print(result.final_output) ``` -### 任意の承認フロー +### Optional approval flows -サーバーが機微な操作を実行できる場合は、各ツール実行の前に、人またはプログラムによる承認を必須にできます。`tool_config` の `require_approval` を、単一のポリシー(`"always"`、`"never"`)またはツール名をポリシーにマッピングした dict で設定します。判断を Python 内で行うには、`on_approval_request` コールバックを指定します。 +サーバーが機微な操作を実行できる場合、各ツール実行前に人間またはプログラムによる承認を必須にできます。`tool_config` の `require_approval` を、単一のポリシー (`"always"`、`"never"`) またはツール名からポリシーへの dict で設定します。判断を Python 内で行うには、`on_approval_request` コールバックを指定します。 ```python from agents import MCPToolApprovalFunctionResult, MCPToolApprovalRequest @@ -101,11 +103,11 @@ agent = Agent( ) ``` -コールバックは同期・非同期のいずれでもよく、モデルが実行を継続するために承認データを必要とするたびに呼び出されます。 +コールバックは同期または非同期のいずれでもよく、モデルが実行を続けるために承認データを必要とするたびに呼び出されます。 -### コネクタ対応の hosted サーバー +### Connector-backed hosted servers -Hosted MCP は OpenAI コネクタにも対応しています。`server_url` を指定する代わりに、`connector_id` とアクセストークンを指定します。Responses API が認証を処理し、hosted サーバーがコネクタのツールを公開します。 +ホスト型 MCP は OpenAI コネクタにも対応しています。`server_url` を指定する代わりに、`connector_id` とアクセストークンを指定します。Responses API が認証を処理し、ホスト型サーバーがコネクタのツールを公開します。 ```python import os @@ -121,13 +123,12 @@ HostedMCPTool( ) ``` -ストリーミング、承認、コネクタを含む完全な hosted ツールのサンプルは +ストリーミング、承認、コネクタを含む完全なホスト型ツールのサンプルは、 [`examples/hosted_mcp`](https://github.com/openai/openai-agents-python/tree/main/examples/hosted_mcp) にあります。 ## 2. Streamable HTTP MCP servers -ネットワーク接続を自分で管理したい場合は、 -[`MCPServerStreamableHttp`][agents.mcp.server.MCPServerStreamableHttp] を使用します。Streamable HTTP サーバーは、トランスポートを自分で制御したい場合や、サーバーを自社インフラ内で運用しつつレイテンシーを抑えたい場合に最適です。 +ネットワーク接続を自分で管理したい場合は、[`MCPServerStreamableHttp`][agents.mcp.server.MCPServerStreamableHttp] を使います。Streamable HTTP サーバーは、トランスポートを自分で制御したい場合や、レイテンシを抑えつつ自前のインフラ内でサーバーを実行したい場合に最適です。 ```python import asyncio @@ -162,17 +163,16 @@ async def main() -> None: asyncio.run(main()) ``` -コンストラクタは、以下の追加オプションを受け付けます: +コンストラクターは追加オプションを受け付けます: - `client_session_timeout_seconds` は HTTP の読み取りタイムアウトを制御します。 - `use_structured_content` は、テキスト出力よりも `tool_result.structured_content` を優先するかどうかを切り替えます。 -- `max_retry_attempts` と `retry_backoff_seconds_base` は、`list_tools()` と `call_tool()` に自動リトライを追加します。 -- `tool_filter` により、一部のツールのみを公開できます([ツールのフィルタリング](#tool-filtering) を参照)。 +- `max_retry_attempts` と `retry_backoff_seconds_base` は、`list_tools()` と `call_tool()` の自動リトライを追加します。 +- `tool_filter` は公開するツールのサブセットを制限できます ([Tool filtering](#tool-filtering) を参照)。 ## 3. HTTP with SSE MCP servers -MCP サーバーが HTTP with SSE トランスポートを実装している場合は、 -[`MCPServerSse`][agents.mcp.server.MCPServerSse] をインスタンス化します。トランスポート以外は、API は Streamable HTTP サーバーと同一です。 +MCP サーバーが HTTP with SSE トランスポートを実装している場合は、[`MCPServerSse`][agents.mcp.server.MCPServerSse] をインスタンス化します。トランスポート以外は、API は Streamable HTTP サーバーと同一です。 ```python @@ -201,7 +201,7 @@ async with MCPServerSse( ## 4. stdio MCP servers -ローカルのサブプロセスとして動作する MCP サーバーには、[`MCPServerStdio`][agents.mcp.server.MCPServerStdio] を使用します。SDK はプロセスを起動し、パイプを開いたままにし、コンテキストマネージャーの終了時に自動的にクローズします。このオプションは、迅速なプロトタイプや、サーバーがコマンドラインのエントリーポイントのみを公開している場合に便利です。 +ローカルのサブプロセスとして実行される MCP サーバーには、[`MCPServerStdio`][agents.mcp.server.MCPServerStdio] を使用します。SDK はプロセスを起動し、パイプを開いたままにし、コンテキストマネージャが終了すると自動的に閉じます。このオプションは、迅速なプロトタイプ作成や、サーバーがコマンドラインのエントリーポイントのみを公開している場合に有用です。 ```python from pathlib import Path @@ -227,13 +227,13 @@ async with MCPServerStdio( print(result.final_output) ``` -## ツールのフィルタリング +## Tool filtering -各 MCP サーバーはツールフィルターをサポートしており、エージェント に必要な関数のみを公開できます。フィルタリングは、構築時または実行ごとに動的に行えます。 +各 MCP サーバーはツールのフィルタリングをサポートしており、エージェントに必要な関数のみを公開できます。フィルタリングは構築時にも、実行ごとに動的にも行えます。 -### 静的なツールフィルタリング +### Static tool filtering -[`create_static_tool_filter`][agents.mcp.create_static_tool_filter] を使用して、簡単な allow/block リストを設定します: +[`create_static_tool_filter`][agents.mcp.create_static_tool_filter] を使用して、簡単な許可/ブロックリストを設定します: ```python from pathlib import Path @@ -251,11 +251,11 @@ filesystem_server = MCPServerStdio( ) ``` -`allowed_tool_names` と `blocked_tool_names` の両方が指定された場合、SDK はまず allow リストを適用し、その後、残りの集合からブロック対象のツールを除外します。 +`allowed_tool_names` と `blocked_tool_names` の両方が指定された場合、SDK はまず許可リストを適用し、その後残りの集合からブロック対象のツールを削除します。 -### 動的なツールフィルタリング +### Dynamic tool filtering -より複雑なロジックが必要な場合は、[`ToolFilterContext`][agents.mcp.ToolFilterContext] を受け取る呼び出し可能オブジェクトを渡します。呼び出し可能オブジェクトは同期・非同期のいずれでもよく、ツールを公開すべきときに `True` を返します。 +より複雑なロジックには、[`ToolFilterContext`][agents.mcp.ToolFilterContext] を受け取る呼び出し可能オブジェクトを渡します。呼び出し可能オブジェクトは同期/非同期のいずれでもよく、ツールを公開すべき場合に `True` を返します。 ```python from pathlib import Path @@ -279,14 +279,14 @@ async with MCPServerStdio( ... ``` -フィルターのコンテキストは、アクティブな `run_context`、ツールを要求している `agent`、および `server_name` を公開します。 +フィルタコンテキストは、アクティブな `run_context`、ツールを要求している `agent`、および `server_name` を公開します。 -## プロンプト +## Prompts -MCP サーバーは、エージェントの instructions を動的に生成するプロンプトも提供できます。プロンプトをサポートするサーバーは、次の 2 つのメソッドを公開します: +MCP サーバーは、エージェントの instructions を動的に生成するプロンプトも提供できます。プロンプトに対応するサーバーは、次の 2 つのメソッドを公開します: -- `list_prompts()` は、利用可能なプロンプトテンプレートを列挙します。 -- `get_prompt(name, arguments)` は、必要に応じて パラメーター 付きの具体的なプロンプトを取得します。 +- `list_prompts()` は使用可能なプロンプトテンプレートを列挙します。 +- `get_prompt(name, arguments)` は、必要に応じてパラメーター付きで具体的なプロンプトを取得します。 ```python from agents import Agent @@ -304,21 +304,21 @@ agent = Agent( ) ``` -## キャッシュ +## Caching -各 エージェント 実行は、各 MCP サーバーに対して `list_tools()` を呼び出します。リモートサーバーは顕著なレイテンシーをもたらす可能性があるため、すべての MCP サーバークラスは `cache_tools_list` オプションを公開しています。ツール定義が頻繁に変化しないと確信できる場合にのみ `True` に設定してください。後で新しいリストを強制するには、サーバーインスタンスで `invalidate_tools_cache()` を呼び出します。 +各エージェント実行は、各 MCP サーバーに対して `list_tools()` を呼び出します。リモートサーバーは目立つレイテンシをもたらす可能性があるため、すべての MCP サーバークラスは `cache_tools_list` オプションを公開しています。ツール定義が頻繁に変わらないと確信できる場合にのみ、これを `True` に設定してください。あとで新しいリストを強制するには、サーバーインスタンスで `invalidate_tools_cache()` を呼び出します。 -## トレーシング +## Tracing -[Tracing](./tracing.md) は MCP のアクティビティを自動的に捕捉します。以下を含みます: +[Tracing](./tracing.md) は MCP のアクティビティを自動的に捕捉します。内容には次が含まれます: 1. ツールを列挙するための MCP サーバーへの呼び出し。 -2. ツール呼び出しに関する MCP 関連の情報。 +2. ツール呼び出しに関する MCP 関連情報。 ![MCP Tracing Screenshot](../assets/images/mcp-tracing.jpg) -## 参考資料 +## Further reading - [Model Context Protocol](https://modelcontextprotocol.io/) – 仕様および設計ガイド。 - [examples/mcp](https://github.com/openai/openai-agents-python/tree/main/examples/mcp) – 実行可能な stdio、SSE、Streamable HTTP のサンプル。 -- [examples/hosted_mcp](https://github.com/openai/openai-agents-python/tree/main/examples/hosted_mcp) – 承認やコネクタを含む完全な hosted MCP のデモ。 \ No newline at end of file +- [examples/hosted_mcp](https://github.com/openai/openai-agents-python/tree/main/examples/hosted_mcp) – 承認やコネクタを含む、完全なホスト型 MCP デモ。 \ No newline at end of file diff --git a/docs/ja/models/index.md b/docs/ja/models/index.md index 3ca290e65..1c88fd07c 100644 --- a/docs/ja/models/index.md +++ b/docs/ja/models/index.md @@ -4,20 +4,20 @@ search: --- # モデル -Agents SDK には、OpenAI モデルのサポートが 2 つの形であらかじめ用意されています。 +Agents SDK には、2 種類の OpenAI モデルのサポートがあらかじめ組み込まれています。 -- **推奨**: 新しい [Responses API](https://platform.openai.com/docs/api-reference/responses) を使って OpenAI API を呼び出す [`OpenAIResponsesModel`][agents.models.openai_responses.OpenAIResponsesModel] -- [Chat Completions API](https://platform.openai.com/docs/api-reference/chat) を使って OpenAI API を呼び出す [`OpenAIChatCompletionsModel`][agents.models.openai_chatcompletions.OpenAIChatCompletionsModel] +- **推奨**: [`OpenAIResponsesModel`][agents.models.openai_responses.OpenAIResponsesModel]。新しい [Responses API](https://platform.openai.com/docs/api-reference/responses) を使って OpenAI API を呼び出します。 +- [`OpenAIChatCompletionsModel`][agents.models.openai_chatcompletions.OpenAIChatCompletionsModel]。 [Chat Completions API](https://platform.openai.com/docs/api-reference/chat) を使って OpenAI API を呼び出します。 ## OpenAI モデル -`Agent` を初期化する際にモデルを指定しない場合は、デフォルトのモデルが使用されます。現在のデフォルトは [`gpt-4.1`](https://platform.openai.com/docs/models/gpt-4.1) で、エージェント的ワークフローの予測可能性と低レイテンシのバランスが優れています。 +`Agent` を初期化するときにモデルを指定しない場合は、デフォルトのモデルが使用されます。現在のデフォルトは [`gpt-4.1`](https://platform.openai.com/docs/models/gpt-4.1) で、エージェント型ワークフローにおける予測可能性と低レイテンシのバランスに優れています。 -[`gpt-5`](https://platform.openai.com/docs/models/gpt-5) などの他のモデルに切り替えたい場合は、次のセクションの手順に従ってください。 +[`gpt-5`](https://platform.openai.com/docs/models/gpt-5) など別のモデルに切り替えたい場合は、次のセクションの手順に従ってください。 -### 既定の OpenAI モデル +### デフォルトの OpenAI モデル -カスタムモデルを設定していないすべてのエージェントで一貫して特定のモデルを使用したい場合は、エージェントを実行する前に `OPENAI_DEFAULT_MODEL` 環境変数を設定してください。 +カスタムモデルを設定していないすべてのエージェントで特定のモデルを一貫して使用したい場合は、エージェントを実行する前に `OPENAI_DEFAULT_MODEL` 環境変数を設定してください。 ```bash export OPENAI_DEFAULT_MODEL=gpt-5 @@ -26,9 +26,9 @@ python3 my_awesome_agent.py #### GPT-5 モデル -[`gpt-5`](https://platform.openai.com/docs/models/gpt-5)、[`gpt-5-mini`](https://platform.openai.com/docs/models/gpt-5-mini)、または [`gpt-5-nano`](https://platform.openai.com/docs/models/gpt-5-nano) といった GPT-5 の推論モデルをこの方法で使用する場合、SDK はデフォルトで適切な `ModelSettings` を適用します。具体的には、`reasoning.effort` と `verbosity` をいずれも `"low"` に設定します。これらの設定を自分で構築したい場合は、`agents.models.get_default_model_settings("gpt-5")` を呼び出してください。 +この方法で GPT-5 のいずれかの推論モデル([`gpt-5`](https://platform.openai.com/docs/models/gpt-5)、[`gpt-5-mini`](https://platform.openai.com/docs/models/gpt-5-mini)、または [`gpt-5-nano`](https://platform.openai.com/docs/models/gpt-5-nano))を使用すると、SDK はデフォルトで適切な `ModelSettings` を適用します。具体的には、`reasoning.effort` と `verbosity` の両方を `"low"` に設定します。これらの設定を自分で構成したい場合は、`agents.models.get_default_model_settings("gpt-5")` を呼び出してください。 -さらに低レイテンシや特定の要件がある場合は、別のモデルや設定を選択できます。デフォルトモデルの推論負荷を調整するには、独自の `ModelSettings` を渡してください。 +レイテンシを下げたい場合や特定の要件がある場合は、別のモデルや設定を選べます。デフォルトモデルの推論負荷を調整するには、独自の `ModelSettings` を渡します。 ```python from openai.types.shared import Reasoning @@ -44,21 +44,21 @@ my_agent = Agent( ) ``` -特に低レイテンシを重視する場合、[`gpt-5-mini`](https://platform.openai.com/docs/models/gpt-5-mini) または [`gpt-5-nano`](https://platform.openai.com/docs/models/gpt-5-nano) に `reasoning.effort="minimal"` を指定して使うと、デフォルト設定よりも高速に応答が返ることがよくあります。ただし、Responses API の一部の組み込みツール(ファイル検索 や 画像生成 など)は `"minimal"` の推論負荷をサポートしていないため、本 Agents SDK の既定は `"low"` になっています。 +特に低レイテンシが必要な場合、[`gpt-5-mini`](https://platform.openai.com/docs/models/gpt-5-mini) または [`gpt-5-nano`](https://platform.openai.com/docs/models/gpt-5-nano) モデルで `reasoning.effort="minimal"` を使用すると、デフォルト設定よりも高速に応答が返ってくることがよくあります。ただし、Responses API の一部の組み込みツール(ファイル検索や画像生成など)は `"minimal"` の推論負荷をサポートしていないため、この Agents SDK ではデフォルトを `"low"` にしています。 #### 非 GPT-5 モデル -カスタムの `model_settings` なしで GPT-5 以外のモデル名を渡した場合、SDK はあらゆるモデルと互換性のある汎用的な `ModelSettings` にフォールバックします。 +カスタムの `model_settings` を指定せずに GPT-5 以外のモデル名を渡した場合、SDK はあらゆるモデルと互換性のある一般的な `ModelSettings` にフォールバックします。 ## 非 OpenAI モデル -[LiteLLM 連携](./litellm.md)を通じて、ほとんどの非 OpenAI モデルを使用できます。まず、litellm の依存関係グループをインストールします。 +[LiteLLM 連携](./litellm.md) を通じて、ほとんどの非 OpenAI モデルを使用できます。まず、litellm の依存関係グループをインストールします。 ```bash pip install "openai-agents[litellm]" ``` -次に、`litellm/` プレフィックスを付けて、[サポートされているモデル](https://docs.litellm.ai/docs/providers) を使用します。 +次に、`litellm/` プレフィックスを付けて [サポートされているモデル](https://docs.litellm.ai/docs/providers) を使用します。 ```python claude_agent = Agent(model="litellm/anthropic/claude-3-5-sonnet-20240620", ...) @@ -67,29 +67,29 @@ gemini_agent = Agent(model="litellm/gemini/gemini-2.5-flash-preview-04-17", ...) ### 非 OpenAI モデルを使うその他の方法 -他の LLM プロバイダを統合する方法はさらに 3 つあります(code examples は[こちら](https://github.com/openai/openai-agents-python/tree/main/examples/model_providers/))。 +他の LLM プロバイダを連携する方法はさらに 3 つあります(code examples は[こちら](https://github.com/openai/openai-agents-python/tree/main/examples/model_providers/))。 -1. [`set_default_openai_client`][agents.set_default_openai_client] は、LLM クライアントとして `AsyncOpenAI` のインスタンスをグローバルに使用したい場合に便利です。これは、LLM プロバイダが OpenAI 互換の API エンドポイントを持ち、`base_url` と `api_key` を設定できる場合の方法です。設定可能な例は [examples/model_providers/custom_example_global.py](https://github.com/openai/openai-agents-python/tree/main/examples/model_providers/custom_example_global.py) を参照してください。 -2. [`ModelProvider`][agents.models.interface.ModelProvider] は `Runner.run` レベルで指定します。これにより、「この実行のすべてのエージェントにカスタムモデルプロバイダを使う」と宣言できます。設定可能な例は [examples/model_providers/custom_example_provider.py](https://github.com/openai/openai-agents-python/tree/main/examples/model_providers/custom_example_provider.py) を参照してください。 -3. [`Agent.model`][agents.agent.Agent.model] を使うと、特定の Agent インスタンスでモデルを指定できます。これにより、異なるエージェントに異なるプロバイダを組み合わせて使用できます。簡単に多数のモデルを使う方法としては、[LiteLLM 連携](./litellm.md)の利用が便利です。 +1. [`set_default_openai_client`][agents.set_default_openai_client] は、LLM クライアントとして `AsyncOpenAI` のインスタンスをグローバルに使用したい場合に便利です。これは LLM プロバイダが OpenAI 互換の API エンドポイントを持ち、`base_url` と `api_key` を設定できるケース向けです。設定可能なサンプルは [examples/model_providers/custom_example_global.py](https://github.com/openai/openai-agents-python/tree/main/examples/model_providers/custom_example_global.py) を参照してください。 +2. [`ModelProvider`][agents.models.interface.ModelProvider] は `Runner.run` レベルにあります。これにより、「この実行の全エージェントでカスタムモデルプロバイダを使う」と指定できます。設定可能なサンプルは [examples/model_providers/custom_example_provider.py](https://github.com/openai/openai-agents-python/tree/main/examples/model_providers/custom_example_provider.py) を参照してください。 +3. [`Agent.model`][agents.agent.Agent.model] では、特定の Agent インスタンスに対してモデルを指定できます。これにより、異なるエージェントごとに異なるプロバイダを組み合わせて使用できます。設定可能なサンプルは [examples/model_providers/custom_example_agent.py](https://github.com/openai/openai-agents-python/tree/main/examples/model_providers/custom_example_agent.py) を参照してください。利用可能なモデルの多くを簡単に使う方法として [LiteLLM 連携](./litellm.md) があります。 -`platform.openai.com` の API キーがない場合は、`set_tracing_disabled()` でトレーシングを無効化するか、[別のトレーシング プロセッサー](../tracing.md) を設定することをおすすめします。 +`platform.openai.com` の API キーを持っていない場合は、`set_tracing_disabled()` でトレーシングを無効化するか、[別のトレーシング プロセッサー](../tracing.md) を設定することをおすすめします。 !!! note - これらの例では、Responses API をまだサポートしていない LLM プロバイダがほとんどであるため、Chat Completions API/モデルを使用しています。もしお使いの LLM プロバイダが対応している場合は、Responses の使用をおすすめします。 + これらの code examples では、Responses API をまだサポートしていないプロバイダが多いため、Chat Completions API/モデルを使用しています。お使いの LLM プロバイダが Responses をサポートしている場合は、Responses の使用を推奨します。 ## モデルの組み合わせ -1 つのワークフロー内で、エージェントごとに異なるモデルを使いたい場合があります。たとえば、振り分けには小型で高速なモデルを、複雑なタスクにはより大きく高機能なモデルを使うといった使い分けです。[`Agent`][agents.Agent] を設定する際、以下のいずれかで特定のモデルを選べます。 +単一のワークフロー内で、エージェントごとに異なるモデルを使いたい場合があります。例えば、振り分けには小型で高速なモデルを、複雑なタスクには大型で高機能なモデルを使う、といった使い分けです。[`Agent`][agents.Agent] を構成する際、次のいずれかで特定のモデルを選べます。 -1. モデル名を指定する。 -2. 任意のモデル名と、それを Model インスタンスに解決できる [`ModelProvider`][agents.models.interface.ModelProvider] を渡す。 +1. モデル名を渡す。 +2. 任意のモデル名 + その名前を Model インスタンスへマッピングできる [`ModelProvider`][agents.models.interface.ModelProvider] を渡す。 3. [`Model`][agents.models.interface.Model] 実装を直接渡す。 !!!note - SDK は [`OpenAIResponsesModel`][agents.models.openai_responses.OpenAIResponsesModel] と [`OpenAIChatCompletionsModel`][agents.models.openai_chatcompletions.OpenAIChatCompletionsModel] の両方の形をサポートしますが、両者はサポートする機能やツールのセットが異なるため、各ワークフローには 1 つのモデル形に統一することをおすすめします。ワークフローでモデル形を混在させる必要がある場合は、使用するすべての機能が両方で利用可能であることを確認してください。 + SDK は [`OpenAIResponsesModel`][agents.models.openai_responses.OpenAIResponsesModel] と [`OpenAIChatCompletionsModel`][agents.models.openai_chatcompletions.OpenAIChatCompletionsModel] の両方の形をサポートしますが、両者はサポートする機能やツールのセットが異なるため、各ワークフローでは単一のモデル形に統一することを推奨します。ワークフロー上どうしても混在させる必要がある場合は、使用するすべての機能が両方で利用可能であることを確認してください。 ```python from agents import Agent, Runner, AsyncOpenAI, OpenAIChatCompletionsModel @@ -125,7 +125,7 @@ async def main(): 1. OpenAI のモデル名を直接設定します。 2. [`Model`][agents.models.interface.Model] 実装を提供します。 -エージェントに使用するモデルをさらに詳細に設定したい場合は、温度などのオプションのモデル設定パラメーターを提供する [`ModelSettings`][agents.models.interface.ModelSettings] を渡せます。 +エージェントで使用するモデルをさらに構成したい場合は、`temperature` などの任意のモデル構成パラメーターを提供する [`ModelSettings`][agents.models.interface.ModelSettings] を渡せます。 ```python from agents import Agent, ModelSettings @@ -138,7 +138,7 @@ english_agent = Agent( ) ``` -また、OpenAI の Responses API を使う場合、[他にもいくつかの任意パラメーター](https://platform.openai.com/docs/api-reference/responses/create)(例: `user`、`service_tier` など)があります。トップレベルで指定できない場合は、`extra_args` を使って渡せます。 +また、OpenAI の Responses API を使用する場合、[他にもいくつかの任意パラメーター](https://platform.openai.com/docs/api-reference/responses/create)(例: `user`、`service_tier` など)があります。トップレベルに該当項目がない場合は、`extra_args` を使って渡せます。 ```python from agents import Agent, ModelSettings @@ -154,26 +154,26 @@ english_agent = Agent( ) ``` -## 他社 LLM プロバイダ利用時の一般的な問題 +## 他の LLM プロバイダを使用する際の一般的な問題 -### トレーシング クライアントの 401 エラー +### トレーシング クライアントのエラー 401 -トレーシング関連のエラーが発生する場合、トレースは OpenAI のサーバーにアップロードされる仕様で、OpenAI の API キーを持っていないことが原因です。解決策は次の 3 つです。 +トレーシングに関連するエラーが発生する場合、トレースは OpenAI サーバーにアップロードされ、OpenAI の API キーがないことが原因です。次の 3 つの方法で解決できます。 1. トレーシングを完全に無効化する: [`set_tracing_disabled(True)`][agents.set_tracing_disabled] -2. トレーシング用に OpenAI のキーを設定する: [`set_tracing_export_api_key(...)`][agents.set_tracing_export_api_key]。この API キーはトレースのアップロードにのみ使用され、[platform.openai.com](https://platform.openai.com/) のものが必要です。 -3. 非 OpenAI のトレース プロセッサーを使用する。[tracing のドキュメント](../tracing.md#custom-tracing-processors) を参照してください。 +2. トレーシング用に OpenAI キーを設定する: [`set_tracing_export_api_key(...)`][agents.set_tracing_export_api_key]。この API キーはトレースのアップロードのみに使用され、[platform.openai.com](https://platform.openai.com/) のものが必要です。 +3. 非 OpenAI のトレース プロセッサーを使用する。[tracing ドキュメント](../tracing.md#custom-tracing-processors) を参照してください。 ### Responses API のサポート -SDK はデフォルトで Responses API を使用しますが、他の多くの LLM プロバイダはまだ未対応です。その結果、404 などの問題が発生することがあります。解決するには次の 2 つの方法があります。 +SDK はデフォルトで Responses API を使用しますが、他の多くの LLM プロバイダはまだサポートしていません。その結果、404 などの問題が発生する場合があります。解決方法は 2 つあります。 1. [`set_default_openai_api("chat_completions")`][agents.set_default_openai_api] を呼び出します。これは、環境変数で `OPENAI_API_KEY` と `OPENAI_BASE_URL` を設定している場合に機能します。 -2. [`OpenAIChatCompletionsModel`][agents.models.openai_chatcompletions.OpenAIChatCompletionsModel] を使用します。code examples は[こちら](https://github.com/openai/openai-agents-python/tree/main/examples/model_providers/)。 +2. [`OpenAIChatCompletionsModel`][agents.models.openai_chatcompletions.OpenAIChatCompletionsModel] を使用します。code examples は[こちら](https://github.com/openai/openai-agents-python/tree/main/examples/model_providers/)にあります。 -### Structured outputs のサポート +### Structured outputs support -一部のモデルプロバイダは [structured outputs](https://platform.openai.com/docs/guides/structured-outputs) をサポートしていません。これにより、次のようなエラーが発生する場合があります。 +一部のモデルプロバイダは [structured outputs](https://platform.openai.com/docs/guides/structured-outputs) をサポートしていません。これにより、次のようなエラーが発生することがあります。 ``` @@ -181,12 +181,12 @@ BadRequestError: Error code: 400 - {'error': {'message': "'response_format.type' ``` -これは一部のモデルプロバイダ側の制約で、JSON 出力はサポートしていても、出力に使用する `json_schema` を指定できないというものです。こちらについては対応中ですが、JSON スキーマ出力をサポートしているプロバイダに依存することをおすすめします。さもないと、不正な JSON によってアプリが頻繁に壊れてしまう可能性があります。 +これは一部のモデルプロバイダの制約で、JSON 出力はサポートしていても、出力に使用する `json_schema` を指定できません。現在この問題の修正に取り組んでいますが、JSON schema 出力をサポートしているプロバイダに依存することをおすすめします。そうでない場合、不正な形式の JSON によりアプリが頻繁に壊れる可能性があります。 ## プロバイダをまたいだモデルの混在 -モデルプロバイダ間の機能差に注意しないと、エラーに直面する可能性があります。たとえば、OpenAI は structured outputs、マルチモーダル入力、ホスト型の ファイル検索 と Web 検索 をサポートしていますが、他の多くのプロバイダはこれらの機能をサポートしていません。以下の制約に注意してください。 +モデルプロバイダ間の機能差に注意しないと、エラーに遭遇する可能性があります。例えば、OpenAI は structured outputs、マルチモーダル入力、ホスト型のファイル検索および Web 検索をサポートしますが、他の多くのプロバイダはこれらの機能をサポートしていません。次の制限に注意してください。 -- サポートしていない `tools` を理解できないプロバイダに送らない -- テキスト専用モデルを呼び出す前にマルチモーダル入力を取り除く -- structured JSON 出力をサポートしないプロバイダでは、不正な JSON が生成されることがある点に留意する \ No newline at end of file +- サポートしていない `tools` を理解しないプロバイダに送らないでください +- テキスト専用モデルを呼び出す前に、マルチモーダル入力をフィルタリングしてください +- structured な JSON 出力をサポートしていないプロバイダは、無効な JSON を出力することがあります \ No newline at end of file diff --git a/docs/ja/models/litellm.md b/docs/ja/models/litellm.md index cb551aa49..e1e18231b 100644 --- a/docs/ja/models/litellm.md +++ b/docs/ja/models/litellm.md @@ -2,13 +2,13 @@ search: exclude: true --- -# LiteLLM を使った任意のモデルの利用 +# LiteLLM 経由で任意のモデルを利用 !!! note - LiteLLM 連携はベータ版です。特に小規模なモデルプロバイダーでは問題が発生する可能性があります。問題があれば [GitHub Issues](https://github.com/openai/openai-agents-python/issues) からご報告ください。迅速に修正します。 + LiteLLM の統合はベータ版です。特に小規模なモデルプロバイダーでは問題が発生する場合があります。問題があれば [GitHub の issues](https://github.com/openai/openai-agents-python/issues) にご報告ください。迅速に修正します。 -[LiteLLM](https://docs.litellm.ai/docs/) は、単一のインターフェースで 100+ のモデルを利用できるライブラリです。Agents SDK に LiteLLM 連携を追加し、任意の AI モデルを使用できるようにしました。 +[LiteLLM](https://docs.litellm.ai/docs/) は、単一のインターフェースで 100+ のモデルを利用できるライブラリです。Agents SDK では LiteLLM との統合により、任意の AI モデルを利用できます。 ## セットアップ @@ -22,13 +22,13 @@ pip install "openai-agents[litellm]" ## 例 -これは完全に動作する例です。実行すると、モデル名と API キーの入力を求められます。例えば、次を入力できます。 +これは実行可能なサンプルです。実行すると、モデル名と API キーの入力を求められます。例えば次のように入力できます。 -- `openai/gpt-4.1`(モデル)と、あなたの OpenAI API キー -- `anthropic/claude-3-5-sonnet-20240620`(モデル)と、あなたの Anthropic API キー -- など +- モデルに `openai/gpt-4.1`、API キーに OpenAI のキー +- モデルに `anthropic/claude-3-5-sonnet-20240620`、API キーに Anthropic のキー +- など -LiteLLM でサポートされているモデルの一覧は、[LiteLLM のプロバイダー ドキュメント](https://docs.litellm.ai/docs/providers) を参照してください。 +LiteLLM でサポートされているモデルの一覧は、[litellm のプロバイダードキュメント](https://docs.litellm.ai/docs/providers)をご覧ください。 ```python from __future__ import annotations @@ -78,7 +78,7 @@ if __name__ == "__main__": ## 使用状況データの追跡 -LiteLLM の応答を Agents SDK の使用状況メトリクスに反映させたい場合は、エージェント作成時に `ModelSettings(include_usage=True)` を渡してください。 +LiteLLM の応答で Agents SDK の使用状況メトリクスを記録したい場合は、エージェント作成時に `ModelSettings(include_usage=True)` を渡してください。 ```python from agents import Agent, ModelSettings @@ -91,4 +91,4 @@ agent = Agent( ) ``` -`include_usage=True` の場合、LiteLLM のリクエストは、組み込みの OpenAI モデルと同様に、`result.context_wrapper.usage` を通じてトークン数とリクエスト数を報告します。 \ No newline at end of file +`include_usage=True` を指定すると、LiteLLM のリクエストは、組み込みの OpenAI モデルと同様に、`result.context_wrapper.usage` を通じてトークン数とリクエスト数を報告します。 \ No newline at end of file diff --git a/docs/ja/multi_agent.md b/docs/ja/multi_agent.md index 935de152d..e57b4e323 100644 --- a/docs/ja/multi_agent.md +++ b/docs/ja/multi_agent.md @@ -4,38 +4,38 @@ search: --- # 複数のエージェントのオーケストレーション -オーケストレーションとは、アプリ内でのエージェントの流れのことです。どのエージェントが、どの順序で実行され、次に何をするかをどのように決めるのか。エージェントをオーケストレーションする主な方法は 2 つあります。 +オーケストレーションとは、アプリ内での エージェント の流れを指します。どの エージェント をどの順序で実行し、その後どう判断するかということです。エージェント をオーケストレーションする主な方法は 2 つあります。 -1. LLM に意思決定を任せる: これは LLM の知能を活用して、計画・推論し、その上で次に取るべきステップを決定します。 -2. コードでオーケストレーションする: コードでエージェントの流れを決定します。 +1. LLM に意思決定させる: LLM の知性を用いて計画・推論し、それに基づいて取るべき手順を決めます。 +2. コードによるオーケストレーション: コードで エージェント のフローを決定します。 -これらのパターンは組み合わせて使えます。それぞれにトレードオフがあり、以下で説明します。 +これらのパターンは組み合わせて使えます。各パターンには以下のようなトレードオフがあります。 ## LLM によるオーケストレーション -エージェントとは、instructions、tools、ハンドオフを備えた LLM です。つまり、オープンエンドなタスクが与えられたとき、LLM はツールを使ってアクションを実行・データを取得し、ハンドオフでサブエージェントにタスクを委譲しながら、タスクへの取り組み方を自律的に計画できます。例えば、リサーチ用のエージェントは次のようなツールを備えられます。 +エージェント は、instructions、tools、そして ハンドオフ を備えた LLM です。つまり、オープンエンドなタスクが与えられたとき、LLM はタスクに取り組む計画を自律的に立て、ツールを使って行動しデータを取得し、ハンドオフ を使ってサブエージェントにタスクを委譲できます。例えば、リサーチ用の エージェント は次のようなツールを備えられます。 -- Web 検索でオンライン情報を探す -- ファイル検索と取得でプロプライエタリなデータや接続を横断して検索する -- コンピュータ操作でコンピュータ上のアクションを実行する -- コード実行でデータ分析を行う -- 計画、レポート作成などに長けた特化エージェントへのハンドオフ +- Web 検索でオンライン情報を見つける +- ファイル検索 と取得で社内データやコネクションを横断的に検索する +- コンピュータ操作 によりコンピュータ上で行動を取る +- データ分析のためのコード実行 +- 計画立案やレポート作成などに長けた特化 エージェント への ハンドオフ -このパターンは、タスクがオープンエンドで LLM の知能に依拠したい場合に適しています。重要な戦術は次のとおりです。 +このパターンはタスクがオープンエンドで、LLM の知性に依拠したい場合に適しています。ここで重要な戦術は次のとおりです。 -1. 良いプロンプトに投資する。利用可能なツール、その使い方、遵守すべきパラメーターを明確にします。 -2. アプリを監視して反復する。問題が起きる箇所を観察し、プロンプトを改善します。 -3. エージェントに内省と改善を許可する。例えばループで実行して自己批評させる、あるいはエラーメッセージを与えて改善させます。 -4. 何でもこなす汎用エージェントではなく、1 つのタスクに秀でた特化エージェントを用意します。 -5. [evals](https://platform.openai.com/docs/guides/evals) に投資する。これによりエージェントを訓練し、タスク遂行能力を高められます。 +1. 良いプロンプトに投資してください。利用可能なツール、その使い方、遵守すべき パラメーター を明確に伝えます。 +2. アプリを監視し、反復改善してください。どこで問題が起きるかを把握し、プロンプトを改善します。 +3. エージェント が内省し改善できるようにします。例えばループで実行して自己批評させる、あるいはエラーメッセージを与えて改善させます。 +4. 何でもこなす汎用 エージェント よりも、1 つのタスクに特化して卓越する エージェント を用意します。 +5. [evals](https://platform.openai.com/docs/guides/evals) に投資してください。これにより エージェント を訓練し、タスク遂行能力を向上させられます。 ## コードによるオーケストレーション -LLM によるオーケストレーションは強力ですが、コードによるオーケストレーションは、速度・コスト・性能の面でより決定的かつ予測可能にできます。一般的なパターンは次のとおりです。 +LLM によるオーケストレーションは強力ですが、コードによるオーケストレーションは速度・コスト・性能の観点でより決定的かつ予測可能にできます。一般的なパターンは次のとおりです。 -- [structured outputs](https://platform.openai.com/docs/guides/structured-outputs) を使って、コードで検査可能な 適切な形式のデータ を生成する。例えば、エージェントにタスクをいくつかのカテゴリーに分類させ、そのカテゴリーに基づいて次のエージェントを選ぶことができます。 -- 複数のエージェントをチェーンして、前の出力を次の入力に変換する。ブログ記事の作成などのタスクを、調査→アウトライン作成→本文執筆→批評→改善という一連のステップに分解できます。 -- 実行担当のエージェントを `while` ループで回し、評価とフィードバックを行うエージェントと組み合わせて、評価者が所定の基準を満たしたと判断するまで繰り返す。 -- 複数のエージェントを並行実行する(例: Python の基本コンポーネントである `asyncio.gather` などによる)。相互に依存しない複数のタスクがある場合、速度向上に有用です。 +- [structured outputs](https://platform.openai.com/docs/guides/structured-outputs) を使って、コードで検査できる 適切な形式のデータ を生成します。例えば、タスクをいくつかの カテゴリー に分類するよう エージェント に依頼し、その カテゴリー に基づいて次の エージェント を選ぶ、といったことができます。 +- ある エージェント の出力を次の エージェント の入力に変換して、複数の エージェント を連鎖させます。ブログ記事執筆のようなタスクを一連の手順(調査、アウトライン作成、本文執筆、批評、改善)に分解できます。 +- 実行役の エージェント を `while` ループで回し、評価とフィードバックを行う エージェント と組み合わせ、評価者が基準を満たしたと判断するまで繰り返します。 +- 複数の エージェント を並列実行します(例: Python の基本コンポーネントである `asyncio.gather` など)。相互依存しない複数タスクがある場合、速度向上に有用です。 -[`examples/agent_patterns`](https://github.com/openai/openai-agents-python/tree/main/examples/agent_patterns) に多数の code examples があります。 \ No newline at end of file +[`examples/agent_patterns`](https://github.com/openai/openai-agents-python/tree/main/examples/agent_patterns) には多数の コード例 があります。 \ No newline at end of file diff --git a/docs/ja/quickstart.md b/docs/ja/quickstart.md index bd7e165a5..0f6e80146 100644 --- a/docs/ja/quickstart.md +++ b/docs/ja/quickstart.md @@ -6,7 +6,7 @@ search: ## プロジェクトと仮想環境の作成 -この作業は一度だけで大丈夫です。 +これは 1 回だけ実行すれば十分です。 ```bash mkdir my_project @@ -22,7 +22,7 @@ python -m venv .venv source .venv/bin/activate ``` -### Agents SDK のインストール +### Agents SDK をインストール ```bash pip install openai-agents # or `uv add openai-agents`, etc @@ -30,15 +30,15 @@ pip install openai-agents # or `uv add openai-agents`, etc ### OpenAI API キーの設定 -まだお持ちでない場合は、OpenAI API キーを作成するために[これらの手順](https://platform.openai.com/docs/quickstart#create-and-export-an-api-key)に従ってください。 +お持ちでない場合は、OpenAI API キーを作成するために [こちらの手順](https://platform.openai.com/docs/quickstart#create-and-export-an-api-key) に従ってください。 ```bash export OPENAI_API_KEY=sk-... ``` -## 最初の エージェント の作成 +## 最初のエージェントの作成 -エージェント は instructions、名前、オプションの config(`model_config` など)で定義します。 +エージェントは instructions、名前、およびオプションの設定(`model_config` など)で定義します。 ```python from agents import Agent @@ -49,9 +49,9 @@ agent = Agent( ) ``` -## いくつかの エージェント の追加 +## さらにいくつかのエージェントを追加 -追加の エージェント も同様に定義できます。`handoff_descriptions` は、ハンドオフ のルーティングを判断するための追加コンテキストを提供します。 +追加のエージェントも同様に定義できます。`handoff_descriptions` は、ハンドオフのルーティングを判断するための追加コンテキストを提供します。 ```python from agents import Agent @@ -69,9 +69,9 @@ math_tutor_agent = Agent( ) ``` -## ハンドオフ の定義 +## ハンドオフの定義 -各 エージェント で、タスクを進める方法を決定するために選択できる、発信側のハンドオフ オプションの一覧を定義できます。 +各エージェントで、タスクを前進させる方法を判断するために選択できる送信側のハンドオフ オプションの在庫(インベントリ)を定義できます。 ```python triage_agent = Agent( @@ -83,7 +83,7 @@ triage_agent = Agent( ## エージェント オーケストレーションの実行 -ワークフローが動作し、トリアージ エージェント が 2 つの専門 エージェント 間を正しくルーティングすることを確認しましょう。 +ワークフローが実行され、トリアージ エージェントが 2 つの専門エージェント間で正しくルーティングするか確認しましょう。 ```python from agents import Runner @@ -95,7 +95,7 @@ async def main(): ## ガードレールの追加 -入力または出力に対して実行するカスタム ガードレールを定義できます。 +入力または出力で実行するカスタム ガードレールを定義できます。 ```python from agents import GuardrailFunctionOutput, Agent, Runner @@ -121,9 +121,9 @@ async def homework_guardrail(ctx, agent, input_data): ) ``` -## まとめて実行 +## すべてをまとめる -すべてをまとめて、ハンドオフ と入力 ガードレール を使ってワークフロー全体を実行しましょう。 +すべてをまとめて、ハンドオフ と入力ガードレールを使用してワークフロー全体を実行しましょう。 ```python from agents import Agent, InputGuardrail, GuardrailFunctionOutput, Runner @@ -192,12 +192,12 @@ if __name__ == "__main__": ## トレースの表示 -エージェント 実行中に何が起きたかを確認するには、[OpenAI Dashboard の Trace viewer](https://platform.openai.com/traces) に移動して、エージェント 実行のトレースを表示してください。 +エージェント実行中に起きたことを確認するには、[OpenAI ダッシュボードの Trace viewer](https://platform.openai.com/traces) に移動してエージェント実行のトレースを表示します。 ## 次のステップ -より複雑なエージェント フローの構築方法を学びましょう: +より複雑なエージェント フローの構築方法を学びましょう。 -- [エージェント](agents.md) の設定方法について学ぶ。 -- [エージェントの実行](running_agents.md) について学ぶ。 -- [ツール](tools.md)、[ガードレール](guardrails.md)、[モデル](models/index.md) について学ぶ。 \ No newline at end of file +- [エージェント](agents.md) の設定方法を学ぶ。 +- [エージェントの実行](running_agents.md) について学ぶ。 +- [ツール](tools.md)、[ガードレール](guardrails.md)、[モデル](models/index.md) について学ぶ。 \ No newline at end of file diff --git a/docs/ja/realtime/guide.md b/docs/ja/realtime/guide.md index 7686efe30..5fd03f0a5 100644 --- a/docs/ja/realtime/guide.md +++ b/docs/ja/realtime/guide.md @@ -4,65 +4,65 @@ search: --- # ガイド -このガイドでは、 OpenAI Agents SDK の realtime 機能を用いて音声対応の AI エージェント を構築する方法を詳しく説明します。 +このガイドでは、OpenAI Agents SDK の realtime 機能を用いて音声対応の AI エージェントを構築する方法を詳しく説明します。 !!! warning "ベータ機能" -Realtime エージェント はベータ版です。実装の改善に伴い、重大な変更が入る可能性があります。 +Realtime エージェントはベータ版です。実装の改善に伴い、破壊的変更が入る可能性があります。 ## 概要 -Realtime エージェント は、リアルタイムで音声とテキスト入力を処理し、リアルタイム音声で応答する会話フローを可能にします。OpenAI の Realtime API との永続的な接続を維持し、低レイテンシで自然な音声対話と、割り込みへのスムーズな対応を実現します。 +Realtime エージェントは、音声およびテキスト入力をリアルタイムに処理し、リアルタイム音声で応答する会話フローを可能にします。OpenAI の Realtime API との永続接続を維持し、低レイテンシで自然な音声会話や割り込みへのスムーズな対応を実現します。 ## アーキテクチャ ### 中核コンポーネント -realtime システムは、いくつかの重要なコンポーネントで構成されます。 +realtime システムは、次の主要コンポーネントで構成されます。 -- **RealtimeAgent** : instructions、tools、handoffs で構成された エージェント。 -- **RealtimeRunner** : 設定を管理します。`runner.run()` を呼び出してセッションを取得できます。 -- **RealtimeSession** : 単一の対話セッション。通常、 ユーザー が会話を開始するたびに作成し、会話が終了するまで維持します。 -- **RealtimeModel** : 基盤となるモデルのインターフェース(通常は OpenAI の WebSocket 実装) +- **RealtimeAgent**: instructions、tools、ハンドオフで構成されたエージェントです。 +- **RealtimeRunner**: 構成を管理します。`runner.run()` を呼び出してセッションを取得できます。 +- **RealtimeSession**: 単一の対話セッションです。通常は ユーザー が会話を開始するたびに作成し、会話が終了するまで保持します。 +- **RealtimeModel**: 基盤となるモデルのインターフェース(通常は OpenAI の WebSocket 実装) ### セッションフロー 典型的な realtime セッションは次のフローに従います。 -1. **RealtimeAgent を作成** し、instructions、tools、handoffs を設定します。 -2. **RealtimeRunner をセットアップ** し、エージェントと構成オプションを指定します。 -3. `await runner.run()` を使って **セッションを開始** します。RealtimeSession が返ります。 -4. `send_audio()` または `send_message()` を使って **音声またはテキストメッセージを送信** します。 -5. セッションを反復処理して **イベントをリッスン** します。イベントには音声出力、文字起こし、ツール呼び出し、ハンドオフ、エラーが含まれます。 -6. ユーザー がエージェントにかぶせて話す **割り込みに対応** します。これにより、現在の音声生成は自動的に停止します。 +1. instructions、tools、ハンドオフを用いて **RealtimeAgent を作成** します。 +2. エージェントと構成オプションで **RealtimeRunner をセットアップ** します。 +3. `await runner.run()` を使って **セッションを開始** し、RealtimeSession を取得します。 +4. `send_audio()` または `send_message()` で **音声またはテキストメッセージを送信** します。 +5. セッションを反復処理して **イベントをリッスン** します。イベントには、音声出力、トランスクリプト、ツール呼び出し、ハンドオフ、エラーが含まれます。 +6. ユーザー がエージェントの発話に被せて話した際の **割り込み処理** を行います。これにより現在の音声生成は自動的に停止します。 -セッションは会話履歴を保持し、realtime モデルとの永続的な接続を管理します。 +セッションは会話履歴を保持し、realtime モデルとの永続接続を管理します。 -## エージェント設定 +## エージェント構成 -RealtimeAgent は通常の Agent クラスと同様に動作しますが、いくつか重要な違いがあります。API の詳細は [`RealtimeAgent`][agents.realtime.agent.RealtimeAgent] の API リファレンスをご覧ください。 +RealtimeAgent は通常の Agent クラスとほぼ同様に動作しますが、いくつか重要な違いがあります。API の詳細は [`RealtimeAgent`][agents.realtime.agent.RealtimeAgent] の API リファレンスをご覧ください。 通常のエージェントとの主な違い: -- モデルの選択はエージェントではなくセッションレベルで設定します。 -- structured outputs はサポートされません(`outputType` は未対応)。 -- 音声はエージェントごとに設定できますが、最初のエージェントが話し始めた後は変更できません。 -- それ以外の機能(tools、handoffs、instructions)は同様に動作します。 +- モデルの選択はエージェント レベルではなくセッション レベルで構成します。 +- structured outputs のサポートはありません(`outputType` は未対応です)。 +- 音声はエージェントごとに設定できますが、最初のエージェントが発話した後は変更できません。 +- それ以外の機能(tools、ハンドオフ、instructions)は同様に動作します。 -## セッション設定 +## セッション構成 ### モデル設定 -セッション設定では、基盤となる realtime モデルの動作を制御できます。モデル名(`gpt-realtime` など)、音声の選択(alloy、echo、fable、onyx、nova、shimmer)、対応モダリティ(テキスト / 音声)を設定できます。音声フォーマットは入力と出力の両方で設定でき、デフォルトは PCM16 です。 +セッション構成では、基盤となる realtime モデルの動作を制御できます。モデル名(例:`gpt-realtime`)、音声の選択( alloy、echo、fable、onyx、nova、shimmer )、およびサポートするモダリティ(テキストおよび/または音声)を設定できます。音声フォーマットは入力・出力の両方で設定でき、デフォルトは PCM16 です。 -### 音声設定 +### オーディオ設定 -音声設定では、セッションが音声入力と出力をどのように処理するかを制御します。Whisper などのモデルを用いた入力音声の文字起こし、言語設定、専門用語の精度を高めるための文字起こしプロンプトを設定できます。ターン検出設定では、エージェントが応答を開始・停止するタイミングを制御でき、音声活動検出のしきい値、無音時間、検出された発話の前後パディングなどのオプションがあります。 +オーディオ設定は、セッションが音声入出力をどのように扱うかを制御します。Whisper のようなモデルを使った入力音声の文字起こし、言語設定、専門用語の精度を高めるためのトランスクリプションプロンプトの指定が可能です。ターン検出設定では、エージェントがいつ応答を開始・終了すべきかを制御し、音声活動検出のしきい値、無音時間、検出音声の前後パディングなどを調整できます。 ## ツールと関数 ### ツールの追加 -通常のエージェントと同様に、realtime エージェント は会話中に実行される 関数ツール をサポートします。 +通常のエージェントと同様に、realtime エージェントは会話中に実行される 関数ツール をサポートします。 ```python from agents import function_tool @@ -90,7 +90,7 @@ agent = RealtimeAgent( ### ハンドオフの作成 -ハンドオフ は、専門の エージェント 間で会話を移譲できるようにします。 +ハンドオフにより、専門化されたエージェント間で会話を移譲できます。 ```python from agents.realtime import realtime_handoff @@ -119,22 +119,22 @@ main_agent = RealtimeAgent( ## イベント処理 -セッションはイベントをストリーミングし、セッションオブジェクトを反復処理することでリッスンできます。イベントには、音声出力チャンク、文字起こし結果、ツール実行の開始と終了、エージェントのハンドオフ、エラーなどが含まれます。特に次のイベントの処理が重要です。 +セッションはイベントを ストリーミング し、セッションオブジェクトを反復処理することでリッスンできます。イベントには、音声出力チャンク、文字起こし結果、ツール実行の開始と終了、エージェントのハンドオフ、エラーなどが含まれます。重要なイベントは次のとおりです。 -- **audio**: エージェントの応答からの Raw 音声データ -- **audio_end**: エージェントの発話が完了 -- **audio_interrupted**: ユーザー がエージェントを割り込み -- **tool_start/tool_end**: ツール実行のライフサイクル -- **handoff**: エージェントのハンドオフが発生 -- **error**: 処理中にエラーが発生 +- **audio**: エージェントの応答からの raw 音声データ +- **audio_end**: エージェントの発話が終了 +- **audio_interrupted**: ユーザー によるエージェントの割り込み +- **tool_start/tool_end**: ツール実行のライフサイクル +- **handoff**: エージェントのハンドオフが発生 +- **error**: 処理中にエラーが発生 -イベントの詳細は [`RealtimeSessionEvent`][agents.realtime.events.RealtimeSessionEvent] を参照してください。 +イベントの完全な詳細は [`RealtimeSessionEvent`][agents.realtime.events.RealtimeSessionEvent] を参照してください。 ## ガードレール -realtime エージェント では出力 ガードレール のみがサポートされています。リアルタイム生成中のパフォーマンス問題を避けるため、これらのガードレールはデバウンスされ、(毎語ではなく)定期的に実行されます。デフォルトのデバウンス長は 100 文字ですが、設定可能です。 +Realtime エージェントでは出力ガードレールのみがサポートされています。パフォーマンス問題を避けるため、これらのガードレールはデバウンスされ、(毎語ではなく)定期的に実行されます。デフォルトのデバウンス長は 100 文字ですが、変更可能です。 -ガードレールは `RealtimeAgent` に直接アタッチするか、セッションの `run_config` で提供できます。両方のソースからのガードレールは併用されます。 +ガードレールは `RealtimeAgent` に直接アタッチするか、セッションの `run_config` を通じて提供できます。両方のソースのガードレールは併用されます。 ```python from agents.guardrail import GuardrailFunctionOutput, OutputGuardrail @@ -152,25 +152,25 @@ agent = RealtimeAgent( ) ``` -ガードレールがトリガーされると、`guardrail_tripped` イベントが生成され、エージェントの現在の応答を中断することがあります。デバウンス動作は、安全性とリアルタイム性能要件のバランスを取るのに役立ちます。テキスト エージェント と異なり、realtime エージェント はガードレール発火時に Exception を送出しません。 +ガードレールがトリガーされると、`guardrail_tripped` イベントを生成し、エージェントの現在の応答を中断できます。デバウンス動作は、安全性とリアルタイムのパフォーマンス要件のバランスを取るのに役立ちます。テキスト エージェントと異なり、realtime エージェントはガードレールが作動しても **Exception**(例外) をスローしません。 -## 音声処理 +## オーディオ処理 -[`session.send_audio(audio_bytes)`][agents.realtime.session.RealtimeSession.send_audio] を使って音声をセッションに送信するか、[`session.send_message()`][agents.realtime.session.RealtimeSession.send_message] を使ってテキストを送信します。 +[`session.send_audio(audio_bytes)`][agents.realtime.session.RealtimeSession.send_audio] を使ってセッションに音声を送信するか、[`session.send_message()`][agents.realtime.session.RealtimeSession.send_message] を使ってテキストを送信します。 -音声出力については、`audio` イベントをリッスンし、任意の音声ライブラリで音声データを再生してください。ユーザー がエージェントを割り込んだ際に即時に再生を停止し、キューにある音声をクリアできるよう、`audio_interrupted` イベントを必ずリッスンしてください。 +音声出力については、`audio` イベントをリッスンし、好みのオーディオライブラリで音声データを再生してください。ユーザー がエージェントを割り込んだ際に即座に再生を停止し、キュー済みの音声をクリアするため、`audio_interrupted` イベントも必ずリッスンしてください。 -## 直接的なモデルアクセス +## モデルへの直接アクセス -基盤となるモデルにアクセスして、カスタムリスナーを追加したり高度な操作を実行できます。 +基盤となるモデルにアクセスして、カスタムリスナーを追加したり高度な操作を実行したりできます。 ```python # Add a custom listener to the model session.model.add_listener(my_custom_listener) ``` -これにより、接続を低レベルで制御する必要がある高度なユースケースに向けて、[`RealtimeModel`][agents.realtime.model.RealtimeModel] インターフェースへ直接アクセスできます。 +これは、接続を低レベルで制御する必要がある高度なユースケース向けに、[`RealtimeModel`][agents.realtime.model.RealtimeModel] インターフェースへ直接アクセスする手段を提供します。 -## 例 +## コード例 -完全な動作する code examples は、[examples/realtime ディレクトリ](https://github.com/openai/openai-agents-python/tree/main/examples/realtime) を参照してください。UI コンポーネントの有無それぞれのデモが含まれています。 \ No newline at end of file +完全な動作コードは、UI コンポーネントあり/なしのデモを含む [examples/realtime ディレクトリ](https://github.com/openai/openai-agents-python/tree/main/examples/realtime) を参照してください。 \ No newline at end of file diff --git a/docs/ja/realtime/quickstart.md b/docs/ja/realtime/quickstart.md index f84fc9a19..ac8efc8f8 100644 --- a/docs/ja/realtime/quickstart.md +++ b/docs/ja/realtime/quickstart.md @@ -4,10 +4,10 @@ search: --- # クイックスタート -リアルタイム エージェントは、OpenAI の Realtime API を使って AI エージェントとの音声会話を可能にします。本ガイドでは、最初のリアルタイム音声エージェントの作成手順を説明します。 +Realtime エージェントは、OpenAI の Realtime API を使用して AI エージェントとの音声会話を可能にします。このガイドでは、最初のリアルタイム音声エージェントの作成手順を説明します。 !!! warning "ベータ機能" -リアルタイム エージェントはベータ版です。実装の改善に伴い、破壊的な変更が入る可能性があります。 +Realtime エージェントはベータ版です。実装の改善に伴い、非互換な変更が入る可能性があります。 ## 前提条件 @@ -17,13 +17,13 @@ search: ## インストール -まだの場合は、OpenAI Agents SDK をインストールします: +まだの場合は、OpenAI Agents SDK をインストールしてください: ```bash pip install openai-agents ``` -## 最初のリアルタイム エージェントの作成 +## 最初の Realtime エージェントの作成 ### 1. 必要なコンポーネントのインポート @@ -32,7 +32,7 @@ import asyncio from agents.realtime import RealtimeAgent, RealtimeRunner ``` -### 2. リアルタイム エージェントの作成 +### 2. Realtime エージェントの作成 ```python agent = RealtimeAgent( @@ -41,7 +41,7 @@ agent = RealtimeAgent( ) ``` -### 3. runner の設定 +### 3. Runner のセットアップ ```python runner = RealtimeRunner( @@ -109,9 +109,9 @@ def _truncate_str(s: str, max_length: int) -> str: return s ``` -## 完全なコード例 +## 完全なサンプル -以下は動作する完全な例です: +以下は動作する完全なサンプルです: ```python import asyncio @@ -192,40 +192,40 @@ if __name__ == "__main__": ### モデル設定 -- `model_name`: 利用可能なリアルタイム モデルから選択 (例: `gpt-realtime`) +- `model_name`: 利用可能な Realtime モデルから選択 (例: `gpt-realtime`) - `voice`: 音声の選択 (`alloy`, `echo`, `fable`, `onyx`, `nova`, `shimmer`) - `modalities`: テキストまたは音声を有効化 (`["text"]` または `["audio"]`) -### オーディオ設定 +### 音声設定 -- `input_audio_format`: 入力音声のフォーマット (`pcm16`, `g711_ulaw`, `g711_alaw`) -- `output_audio_format`: 出力音声のフォーマット +- `input_audio_format`: 入力音声の形式 (`pcm16`, `g711_ulaw`, `g711_alaw`) +- `output_audio_format`: 出力音声の形式 - `input_audio_transcription`: 文字起こしの設定 ### ターン検出 - `type`: 検出方法 (`server_vad`, `semantic_vad`) -- `threshold`: 音声活動のしきい値 (0.0–1.0) +- `threshold`: 音声活動のしきい値 (0.0-1.0) - `silence_duration_ms`: ターン終了を検出する無音時間 - `prefix_padding_ms`: 発話前の音声パディング ## 次のステップ -- [リアルタイム エージェントの詳細を見る](guide.md) -- 動作するサンプルは [examples/realtime](https://github.com/openai/openai-agents-python/tree/main/examples/realtime) フォルダを参照 +- [Realtime エージェントの詳細はこちら](guide.md) +- 動作する code examples は [examples/realtime](https://github.com/openai/openai-agents-python/tree/main/examples/realtime) フォルダーを確認してください - エージェントにツールを追加 - エージェント間のハンドオフを実装 -- 安全のためにガードレールを設定 +- 安全のためのガードレールを設定 ## 認証 -環境に OpenAI API キーが設定されていることを確認します: +OpenAI API キーが環境に設定されていることを確認してください: ```bash export OPENAI_API_KEY="your-api-key-here" ``` -またはセッション作成時に直接渡します: +または、セッション作成時に直接渡します: ```python session = await runner.run(model_config={"api_key": "your-api-key"}) diff --git a/docs/ja/release.md b/docs/ja/release.md index 0dd13ef22..888b7c24a 100644 --- a/docs/ja/release.md +++ b/docs/ja/release.md @@ -2,31 +2,31 @@ search: exclude: true --- -# リリースプロセス/変更履歴 +# リリースプロセス/変更履歴 -本プロジェクトは、`0.Y.Z` 形式のやや調整したセマンティックバージョニングに従います。先頭の `0` は、この SDK が依然として急速に進化していることを示します。各コンポーネントの増分ルールは次のとおりです。 +このプロジェクトは、形式 `0.Y.Z` を用いた semantic versioning をやや変更したバージョンに従います。先頭の `0` は、SDK がまだ急速に進化していることを示します。各コンポーネントの増分は以下のとおりです。 ## マイナー(`Y`)バージョン -ベータでないすべての公開インターフェースに対する **後方互換性のない変更** がある場合に、マイナー バージョン `Y` を上げます。例えば、`0.0.x` から `0.1.x` への移行には互換性のない変更が含まれる場合があります。 +ベータとしてマークされていないパブリックインターフェースに対する **破壊的変更** の際に、マイナーバージョン `Y` を増やします。たとえば、`0.0.x` から `0.1.x` への変更には、破壊的変更が含まれる場合があります。 -互換性のない変更を避けたい場合は、プロジェクトで `0.0.x` に固定することを推奨します。 +破壊的変更を避けたい場合は、プロジェクトで `0.0.x` バージョンにピン留めすることをおすすめします。 ## パッチ(`Z`)バージョン -互換性を壊さない変更では `Z` を増やします: +破壊的でない変更では `Z` を増やします: - バグ修正 - 新機能 -- 非公開インターフェースの変更 +- プライベートインターフェースの変更 - ベータ機能の更新 -## 互換性のない変更の変更履歴 +## 破壊的変更の変更履歴 ### 0.2.0 -このバージョンでは、これまで `Agent` を引数に取っていたいくつかの箇所が、代わりに `AgentBase` を引数に取るようになりました。例えば、MCP サーバーにおける `list_tools()` 呼び出しです。これは純粋に型付け上の変更で、引き続き `Agent` オブジェクトを受け取ります。更新するには、`Agent` を `AgentBase` に置き換えて型エラーを解消するだけです。 +このバージョンでは、以前は引数として `Agent` を受け取っていた箇所のいくつかが、代わりに `AgentBase` を引数として受け取るようになりました。たとえば、MCP サーバーでの `list_tools()` 呼び出しです。これは型に関する変更のみであり、引き続き `Agent` オブジェクトを受け取ります。更新するには、`Agent` を `AgentBase` に置き換えて型エラーを修正してください。 ### 0.1.0 -このバージョンでは、[`MCPServer.list_tools()`][agents.mcp.server.MCPServer] に 2 つの新しいパラメーター `run_context` と `agent` が追加されました。`MCPServer` を継承するすべてのクラスにこれらのパラメーターを追加する必要があります。 \ No newline at end of file +このバージョンでは、[`MCPServer.list_tools()`][agents.mcp.server.MCPServer] に新しいパラメーター `run_context` と `agent` が追加されました。`MCPServer` を継承するすべてのクラスにこれらのパラメーターを追加する必要があります。 \ No newline at end of file diff --git a/docs/ja/repl.md b/docs/ja/repl.md index 6b8a3a958..a4f4967c4 100644 --- a/docs/ja/repl.md +++ b/docs/ja/repl.md @@ -4,7 +4,7 @@ search: --- # REPL ユーティリティ -この SDK は、ターミナル上でエージェントの挙動を手早く対話的にテストできる `run_demo_loop` を提供します。 +SDK は、ターミナルでエージェントの挙動を迅速に対話的にテストするための `run_demo_loop` を提供します。 ```python import asyncio @@ -18,6 +18,6 @@ if __name__ == "__main__": asyncio.run(main()) ``` -`run_demo_loop` はループでユーザー入力を促し、ターン間の会話履歴を保持します。デフォルトでは、生成され次第モデルの出力をストリーミングします。上の例を実行すると、run_demo_loop は対話的なチャットセッションを開始します。継続的に入力を求め、ターン間で会話全体の履歴を記憶し(そのためエージェントは何が話されたかを把握します)、生成と同時にエージェントの応答をリアルタイムで自動的にストリーミングします。 +`run_demo_loop` はループでユーザー入力を促し、ターン間で会話履歴を保持します。既定では、生成と同時にモデルの出力をストリーミングします。上の例を実行すると、 run_demo_loop が対話型のチャットセッションを開始します。あなたの入力を継続的に求め、ターン間で会話全体の履歴を記憶し(そのためエージェントは何が話されたかを把握できます)、生成と同時にエージェントの応答をリアルタイムで自動的にストリーミングします。 このチャットセッションを終了するには、`quit` または `exit` と入力して Enter を押すか、`Ctrl-D` キーボードショートカットを使用します。 \ No newline at end of file diff --git a/docs/ja/results.md b/docs/ja/results.md index 162c68dd4..f35c85031 100644 --- a/docs/ja/results.md +++ b/docs/ja/results.md @@ -2,55 +2,55 @@ search: exclude: true --- -# 実行結果 +# 結果 `Runner.run` メソッドを呼び出すと、次のいずれかが返ります。 - [`RunResult`][agents.result.RunResult](`run` または `run_sync` を呼び出した場合) - [`RunResultStreaming`][agents.result.RunResultStreaming](`run_streamed` を呼び出した場合) -これらはいずれも [`RunResultBase`][agents.result.RunResultBase] を継承しており、ほとんどの有用な情報はここに含まれます。 +どちらも [`RunResultBase`][agents.result.RunResultBase] を継承しており、有用な情報の多くはそこに含まれます。 ## 最終出力 [`final_output`][agents.result.RunResultBase.final_output] プロパティには、最後に実行されたエージェントの最終出力が含まれます。これは次のいずれかです。 - 最後のエージェントに `output_type` が定義されていない場合は `str` -- エージェントに出力タイプが定義されている場合は `last_agent.output_type` 型のオブジェクト +- エージェントに出力タイプが定義されている場合は、`last_agent.output_type` 型のオブジェクト !!! note - `final_output` は型 `Any` です。ハンドオフの可能性があるため、静的型付けはできません。ハンドオフが発生すると、どのエージェントが最後になるか分からないため、可能な出力タイプの集合を静的には特定できません。 + `final_output` の型は Any です。ハンドオフの可能性があるため、静的な型付けはできません。ハンドオフが発生すると、どのエージェントが最後になるか分からないため、取りうる出力タイプの集合を静的に特定できません。 -## 次ターンの入力 +## 次のターンへの入力 -[`result.to_input_list()`][agents.result.RunResultBase.to_input_list] を使うと、エージェント実行中に生成されたアイテムを、あなたが提供した元の入力に連結した入力リストへと変換できます。これにより、あるエージェント実行の出力を別の実行に渡したり、ループで実行して毎回新しい ユーザー 入力を追加したりするのが容易になります。 +[`result.to_input_list()`][agents.result.RunResultBase.to_input_list] を使うと、あなたが提供した元の入力に、エージェントの実行中に生成された項目を連結した入力リストに変換できます。これにより、あるエージェント実行の出力を別の実行へ渡したり、ループで実行して毎回新しい ユーザー 入力を追加したりするのが便利になります。 ## 最後のエージェント -[`last_agent`][agents.result.RunResultBase.last_agent] プロパティには、最後に実行されたエージェントが含まれます。これは ユーザー が次回入力する際に有用なことが多いです。たとえば、一次トリアージのエージェントから言語別のエージェントへハンドオフする設計の場合、最後のエージェントを保存しておき、次回 ユーザー がメッセージを送るときに再利用できます。 +[`last_agent`][agents.result.RunResultBase.last_agent] プロパティには、最後に実行されたエージェントが含まれます。アプリケーションによっては、次回 ユーザー が何か入力する際にこれが有用なことが多いです。例えば、フロントラインのトリアージ用エージェントが言語別のエージェントにハンドオフする構成の場合、最後のエージェントを保存しておき、次回 ユーザー がメッセージを送ったときに再利用できます。 ## 新規アイテム -[`new_items`][agents.result.RunResultBase.new_items] プロパティには、実行中に生成された新規アイテムが含まれます。アイテムは [`RunItem`][agents.items.RunItem] です。実行アイテムは、LLM が生成した raw アイテムをラップします。 +[`new_items`][agents.result.RunResultBase.new_items] プロパティには、実行中に生成された新しい項目が含まれます。各項目は [`RunItem`][agents.items.RunItem] です。RunItem は LLM が生成した raw アイテムをラップします。 - [`MessageOutputItem`][agents.items.MessageOutputItem]: LLM からのメッセージを示します。raw アイテムは生成されたメッセージです。 -- [`HandoffCallItem`][agents.items.HandoffCallItem]: LLM がハンドオフ ツールを呼び出したことを示します。raw アイテムは LLM からのツール呼び出しアイテムです。 -- [`HandoffOutputItem`][agents.items.HandoffOutputItem]: ハンドオフが発生したことを示します。raw アイテムはハンドオフ ツール呼び出しへのツール応答です。アイテムから送信元/送信先のエージェントにもアクセスできます。 +- [`HandoffCallItem`][agents.items.HandoffCallItem]: LLM がハンドオフ ツールを呼び出したことを示します。raw アイテムは LLM のツール呼び出し項目です。 +- [`HandoffOutputItem`][agents.items.HandoffOutputItem]: ハンドオフが発生したことを示します。raw アイテムはハンドオフ ツール呼び出しへのツール応答です。項目から送信元/宛先のエージェントにもアクセスできます。 - [`ToolCallItem`][agents.items.ToolCallItem]: LLM がツールを呼び出したことを示します。 -- [`ToolCallOutputItem`][agents.items.ToolCallOutputItem]: ツールが呼び出されたことを示します。raw アイテムはツール応答です。アイテムからツール出力にもアクセスできます。 -- [`ReasoningItem`][agents.items.ReasoningItem]: LLM からの推論アイテムを示します。raw アイテムは生成された推論です。 +- [`ToolCallOutputItem`][agents.items.ToolCallOutputItem]: ツールが呼び出されたことを示します。raw アイテムはツールの応答です。項目からツール出力にもアクセスできます。 +- [`ReasoningItem`][agents.items.ReasoningItem]: LLM からの推論項目を示します。raw アイテムは生成された推論です。 ## その他の情報 -### ガードレール結果 +### ガードレールの結果 -[`input_guardrail_results`][agents.result.RunResultBase.input_guardrail_results] と [`output_guardrail_results`][agents.result.RunResultBase.output_guardrail_results] プロパティには、(存在する場合)ガードレールの実行結果が含まれます。ガードレール結果には、記録や保存に有用な情報が含まれることがあるため、これらを参照できるようにしています。 +[`input_guardrail_results`][agents.result.RunResultBase.input_guardrail_results] および [`output_guardrail_results`][agents.result.RunResultBase.output_guardrail_results] プロパティには、存在する場合、ガードレールの結果が含まれます。ガードレールの結果には、記録や保存をしたい有用な情報が含まれることがあるため、参照できるようにしています。 -### Raw 応答 +### raw レスポンス [`raw_responses`][agents.result.RunResultBase.raw_responses] プロパティには、LLM によって生成された [`ModelResponse`][agents.items.ModelResponse] が含まれます。 ### 元の入力 -[`input`][agents.result.RunResultBase.input] プロパティには、`run` メソッドに渡した元の入力が含まれます。多くの場合これは不要ですが、必要な場合に備えて参照できます。 \ No newline at end of file +[`input`][agents.result.RunResultBase.input] プロパティには、`run` メソッドに渡した元の入力が含まれます。ほとんどの場合は不要ですが、必要な場合のために利用可能になっています。 \ No newline at end of file diff --git a/docs/ja/running_agents.md b/docs/ja/running_agents.md index a3a6c44fe..d2eab6af3 100644 --- a/docs/ja/running_agents.md +++ b/docs/ja/running_agents.md @@ -4,11 +4,11 @@ search: --- # エージェントの実行 -エージェントは [`Runner`][agents.run.Runner] クラスで実行できます。選択肢は 3 つあります。 +エージェントは [`Runner`][agents.run.Runner] クラスで実行できます。オプションは 3 つあります: -1. [`Runner.run()`][agents.run.Runner.run]: 非同期で実行し、[`RunResult`][agents.result.RunResult] を返します。 +1. [`Runner.run()`][agents.run.Runner.run]: 非同期に実行し、[`RunResult`][agents.result.RunResult] を返します。 2. [`Runner.run_sync()`][agents.run.Runner.run_sync]: 同期メソッドで、内部的には `.run()` を実行します。 -3. [`Runner.run_streamed()`][agents.run.Runner.run_streamed]: 非同期で実行し、[`RunResultStreaming`][agents.result.RunResultStreaming] を返します。LLM をストリーミングモードで呼び出し、受信したイベントをそのままストリーミングします。 +3. [`Runner.run_streamed()`][agents.run.Runner.run_streamed]: 非同期に実行し、[`RunResultStreaming`][agents.result.RunResultStreaming] を返します。LLM をストリーミングモードで呼び出し、受信したイベントをそのままストリーミングします。 ```python from agents import Agent, Runner @@ -23,55 +23,55 @@ async def main(): # Infinite loop's dance ``` -詳しくは [結果ガイド](results.md) を参照してください。 +詳細は [結果ガイド](results.md) をご覧ください。 ## エージェントループ -`Runner` の run メソッドを使うとき、開始エージェントと入力を渡します。入力は文字列( ユーザー メッセージと見なされます)または入力アイテムのリスト(OpenAI Responses API のアイテム)を指定できます。 +`Runner` の run メソッドを使うときは、開始するエージェントと入力を渡します。入力は文字列(ユーザーからのメッセージとして扱われます)か、OpenAI Responses API のアイテムのリストのいずれかです。 -Runner は次のループを実行します。 +ランナーは次のループを実行します: 1. 現在のエージェントに対して、現在の入力で LLM を呼び出します。 2. LLM が出力を生成します。 - 1. LLM が `final_output` を返した場合、ループは終了し、結果を返します。 - 2. LLM が ハンドオフ を行う場合、現在のエージェントと入力を更新してループを再実行します。 - 3. LLM が ツール呼び出し を生成した場合、それらを実行して結果を追記し、ループを再実行します。 + 1. LLM が `final_output` を返した場合、ループを終了し結果を返します。 + 2. LLM が ハンドオフ を行った場合、現在のエージェントと入力を更新してループを再実行します。 + 3. LLM が ツール呼び出し を生成した場合、それらを実行して結果を追加し、ループを再実行します。 3. 渡された `max_turns` を超えた場合、[`MaxTurnsExceeded`][agents.exceptions.MaxTurnsExceeded] 例外を送出します。 !!! note - LLM の出力が「最終出力」と見なされるルールは、目的の型のテキスト出力が生成され、かつツール呼び出しがないことです。 + LLM の出力が「最終出力」と見なされるルールは、望ましい型のテキスト出力を生成し、ツール呼び出しが存在しないことです。 ## ストリーミング -ストリーミングを使うと、LLM の実行中にストリーミングイベントも受け取れます。ストリーム完了時には、[`RunResultStreaming`][agents.result.RunResultStreaming] に、生成されたすべての新しい出力を含む実行の完全な情報が入ります。ストリーミングイベントは `.stream_events()` を呼び出してください。詳しくは [ストリーミングガイド](streaming.md) を参照してください。 +ストリーミングにより、LLM の実行中にストリーミングイベントを追加で受け取れます。ストリームが完了すると、[`RunResultStreaming`][agents.result.RunResultStreaming] に実行に関する完全な情報(生成されたすべての新しい出力を含む)が含まれます。ストリーミングイベントは `.stream_events()` を呼び出して取得できます。詳細は [ストリーミングガイド](streaming.md) をご覧ください。 ## 実行設定 -`run_config` パラメーターでは、エージェント実行のグローバル設定をいくつか構成できます。 +`run_config` パラメーターを使うと、エージェント実行のグローバル設定を構成できます: - [`model`][agents.run.RunConfig.model]: 各 Agent の `model` 設定に関わらず、使用するグローバルな LLM モデルを設定します。 -- [`model_provider`][agents.run.RunConfig.model_provider]: モデル名を解決するためのモデルプロバイダー。既定は OpenAI です。 -- [`model_settings`][agents.run.RunConfig.model_settings]: エージェント固有の設定を上書きします。例えば、グローバルな `temperature` や `top_p` を設定できます。 -- [`input_guardrails`][agents.run.RunConfig.input_guardrails], [`output_guardrails`][agents.run.RunConfig.output_guardrails]: すべての実行に含める入力または出力の ガードレール のリスト。 -- [`handoff_input_filter`][agents.run.RunConfig.handoff_input_filter]: ハンドオフに対して適用するグローバルな入力フィルター(すでにフィルターが設定されていない場合)。入力フィルターにより、新しいエージェントに送る入力を編集できます。詳細は [`Handoff.input_filter`][agents.handoffs.Handoff.input_filter] のドキュメントを参照してください。 -- [`tracing_disabled`][agents.run.RunConfig.tracing_disabled]: 実行全体の [トレーシング](tracing.md) を無効化します。 -- [`trace_include_sensitive_data`][agents.run.RunConfig.trace_include_sensitive_data]: LLM やツール呼び出しの入出力など、潜在的に機微なデータをトレースに含めるかどうかを設定します。 -- [`workflow_name`][agents.run.RunConfig.workflow_name], [`trace_id`][agents.run.RunConfig.trace_id], [`group_id`][agents.run.RunConfig.group_id]: 実行のトレーシングにおけるワークフロー名、トレース ID、トレースグループ ID を設定します。少なくとも `workflow_name` の設定を推奨します。グループ ID は任意で、複数の実行にまたがるトレースをリンクできます。 -- [`trace_metadata`][agents.run.RunConfig.trace_metadata]: すべてのトレースに含めるメタデータ。 +- [`model_provider`][agents.run.RunConfig.model_provider]: モデル名を解決するためのモデルプロバイダーで、デフォルトは OpenAI です。 +- [`model_settings`][agents.run.RunConfig.model_settings]: エージェント固有の設定を上書きします。たとえば、グローバルな `temperature` や `top_p` を設定できます。 +- [`input_guardrails`][agents.run.RunConfig.input_guardrails], [`output_guardrails`][agents.run.RunConfig.output_guardrails]: すべての実行に含める入力/出力の ガードレール のリストです。 +- [`handoff_input_filter`][agents.run.RunConfig.handoff_input_filter]: すべての ハンドオフ に適用するグローバルな入力フィルター(ハンドオフに既定のものがない場合)。入力フィルターにより、新しいエージェントに送る入力を編集できます。詳細は [`Handoff.input_filter`][agents.handoffs.Handoff.input_filter] のドキュメントをご覧ください。 +- [`tracing_disabled`][agents.run.RunConfig.tracing_disabled]: 実行全体の [トレーシング](tracing.md) を無効にできます。 +- [`trace_include_sensitive_data`][agents.run.RunConfig.trace_include_sensitive_data]: トレースに LLM やツール呼び出しの入出力などの機微なデータを含めるかどうかを設定します。 +- [`workflow_name`][agents.run.RunConfig.workflow_name], [`trace_id`][agents.run.RunConfig.trace_id], [`group_id`][agents.run.RunConfig.group_id]: 実行のトレーシング用 workflow 名、trace ID、trace group ID を設定します。少なくとも `workflow_name` の設定を推奨します。group ID はオプションで、複数の実行にわたるトレースの関連付けに使えます。 +- [`trace_metadata`][agents.run.RunConfig.trace_metadata]: すべてのトレースに含めるメタデータです。 ## 会話/チャットスレッド -いずれかの run メソッドを呼ぶと、1 つ以上のエージェント(ひいては 1 回以上の LLM 呼び出し)が実行される可能性がありますが、これはチャット会話における 1 つの論理的なターンを表します。例: +いずれの run メソッドを呼び出しても、1 つ以上のエージェント(つまり 1 回以上の LLM 呼び出し)が実行される可能性がありますが、チャット会話の単一の論理的ターンを表します。例: -1. ユーザー のターン: ユーザー がテキストを入力 -2. Runner の実行: 最初のエージェントが LLM を呼び出し、ツールを実行し、2 つ目のエージェントへハンドオフ、2 つ目のエージェントがさらにツールを実行し、最終的に出力を生成 +1. ユーザーのターン: ユーザーがテキストを入力 +2. Runner の実行: 最初のエージェントが LLM を呼び出し、ツールを実行し、2 番目のエージェントに ハンドオフ、2 番目のエージェントがさらにツールを実行し、その後に出力を生成。 -エージェントの実行終了時に、ユーザー に何を見せるかを選べます。例えば、エージェントが生成したすべての新しいアイテムを見せる、または最終出力だけを見せる、などです。いずれにせよ、ユーザー が追質問をするかもしれません。その場合は再度 run メソッドを呼び出します。 +エージェントの実行終了時に、ユーザーに何を表示するかを選択できます。たとえば、エージェントが生成したすべての新しいアイテムを表示するか、最終出力のみを表示するかです。いずれの場合でも、ユーザーがフォローアップの質問をする可能性があり、その場合は再び run メソッドを呼び出します。 ### 手動の会話管理 -次のターンの入力を取得するために、[`RunResultBase.to_input_list()`][agents.result.RunResultBase.to_input_list] メソッドを使って会話履歴を手動管理できます。 +次のターンの入力を取得するために、[`RunResultBase.to_input_list()`][agents.result.RunResultBase.to_input_list] メソッドを使って、会話履歴を手動で管理できます: ```python async def main(): @@ -93,7 +93,7 @@ async def main(): ### Sessions による自動会話管理 -より簡単な方法として、[Sessions](sessions.md) を使うと、`.to_input_list()` を手動で呼ばずに会話履歴を自動管理できます。 +より簡単な方法として、[Sessions](sessions/index.md) を使って `.to_input_list()` を手動で呼び出すことなく会話履歴を自動的に処理できます: ```python from agents import Agent, Runner, SQLiteSession @@ -117,24 +117,24 @@ async def main(): # California ``` -Sessions は自動で次を行います。 +Sessions は自動で次を行います: -- 各実行前に会話履歴を取得 -- 各実行後に新しいメッセージを保存 -- セッション ID ごとに別々の会話を維持 +- 各実行の前に会話履歴を取得 +- 各実行の後に新しいメッセージを保存 +- 異なるセッション ID ごとに別々の会話を維持 -詳細は [Sessions のドキュメント](sessions.md) を参照してください。 +詳細は [Sessions のドキュメント](sessions/index.md) をご覧ください。 ### サーバー管理の会話 -`to_input_list()` や `Sessions` でローカル管理する代わりに、OpenAI の conversation state 機能に サーバー 側での会話状態管理を任せることもできます。これにより、過去のすべてのメッセージを手動で再送しなくても会話履歴を保持できます。詳しくは [OpenAI Conversation state ガイド](https://platform.openai.com/docs/guides/conversation-state?api-mode=responses) を参照してください。 +`to_input_list()` や `Sessions` でローカルに扱う代わりに、OpenAI の conversation state 機能にサーバー側で会話状態を管理させることもできます。これにより、過去のメッセージをすべて手動で再送信せずに会話履歴を保持できます。詳細は [OpenAI Conversation state ガイド](https://platform.openai.com/docs/guides/conversation-state?api-mode=responses) をご覧ください。 -OpenAI はターン間の状態を追跡する方法を 2 つ提供しています。 +OpenAI はターン間で状態を追跡する方法を 2 つ提供しています: -#### 1. `conversation_id` を使用 +#### 1. `conversation_id` の使用 -まず OpenAI Conversations API で会話を作成し、その ID を後続のすべての呼び出しで再利用します。 +最初に OpenAI Conversations API で会話を作成し、その ID を以後のすべての呼び出しで再利用します: ```python from agents import Agent, Runner @@ -164,9 +164,9 @@ async def main(): # California ``` -#### 2. `previous_response_id` を使用 +#### 2. `previous_response_id` の使用 -もう 1 つの選択肢は、各ターンが前のターンのレスポンス ID に明示的にリンクする **response chaining** です。 +もう 1 つの方法は **response chaining** で、各ターンを前のターンの response ID に明示的にリンクします。 ```python from agents import Agent, Runner @@ -190,18 +190,18 @@ async def main(): ``` -## 長時間実行エージェントと human-in-the-loop +## 長時間実行エージェントとヒューマン・イン・ザ・ループ -Agents SDK の [Temporal](https://temporal.io/) 連携を使用して、human-in-the-loop のタスクを含む永続的な長時間実行ワークフローを動かせます。Temporal と Agents SDK が連携して長時間タスクを完了するデモは [この動画](https://www.youtube.com/watch?v=fFBZqzT4DD8) を、ドキュメントは [こちら](https://github.com/temporalio/sdk-python/tree/main/temporalio/contrib/openai_agents) を参照してください。 +Agents SDK の [Temporal](https://temporal.io/) 連携を使うと、ヒューマン・イン・ザ・ループのタスクを含む、永続的で長時間実行のワークフローを動かせます。Temporal と Agents SDK が連携して長時間実行タスクを完了するデモは[この動画](https://www.youtube.com/watch?v=fFBZqzT4DD8)で、ドキュメントは[こちら](https://github.com/temporalio/sdk-python/tree/main/temporalio/contrib/openai_agents)をご覧ください。 ## 例外 -SDK は特定の状況で例外を送出します。完全な一覧は [`agents.exceptions`][] にあります。概要は次のとおりです。 +SDK は特定の場合に例外を送出します。完全な一覧は [`agents.exceptions`][] にあります。概要: -- [`AgentsException`][agents.exceptions.AgentsException]: SDK 内で送出されるすべての例外の基底クラスです。他の特定の例外はすべてこの型から派生します。 -- [`MaxTurnsExceeded`][agents.exceptions.MaxTurnsExceeded]: エージェントの実行が `Runner.run`、`Runner.run_sync`、`Runner.run_streamed` に渡した `max_turns` 制限を超えた場合に送出されます。指定したインタラクション回数内にタスクを完了できなかったことを示します。 -- [`ModelBehaviorError`][agents.exceptions.ModelBehaviorError]: 基盤のモデル( LLM )が予期しない、または無効な出力を生成した場合に発生します。例: - - 不正な JSON: 特定の `output_type` が定義されている場合に、ツール呼び出しや直接出力で不正な JSON 構造を返した場合。 - - 予期しないツール関連の失敗: モデルが想定どおりにツールを使用できなかった場合 -- [`UserError`][agents.exceptions.UserError]: SDK を使用するあなた(この SDK を使ってコードを書く人)が誤った使い方をしたときに送出されます。これは通常、実装ミス、無効な設定、または SDK の API の誤用が原因です。 -- [`InputGuardrailTripwireTriggered`][agents.exceptions.InputGuardrailTripwireTriggered], [`OutputGuardrailTripwireTriggered`][agents.exceptions.OutputGuardrailTripwireTriggered]: それぞれ、入力 ガードレール または出力 ガードレール の条件が満たされたときに送出されます。入力 ガードレール は処理前に受信メッセージをチェックし、出力 ガードレール はエージェントの最終応答を配信前にチェックします。 \ No newline at end of file +- [`AgentsException`][agents.exceptions.AgentsException]: SDK 内で送出されるすべての例外の基底クラスです。ほかの特定の例外はすべてこの型から派生します。 +- [`MaxTurnsExceeded`][agents.exceptions.MaxTurnsExceeded]: エージェントの実行が `Runner.run`、`Runner.run_sync`、`Runner.run_streamed` メソッドに渡した `max_turns` 制限を超えた場合に送出されます。指定した対話ターン数内にタスクを完了できなかったことを示します。 +- [`ModelBehaviorError`][agents.exceptions.ModelBehaviorError]: 基盤となるモデル(LLM)が予期しない、または無効な出力を生成した場合に発生します。これには次が含まれます: + - 不正な JSON: 特定の `output_type` が定義されている場合に、ツール呼び出しや直接の出力で不正な JSON 構造を返す場合。 + - 予期しないツール関連の失敗: モデルが期待どおりにツールを使用できなかった場合 +- [`UserError`][agents.exceptions.UserError]: SDK を使用する(コードを書く)あなたが、SDK の使用中にエラーを起こした場合に送出されます。これは通常、不正なコード実装、無効な設定、SDK の API の誤用に起因します。 +- [`InputGuardrailTripwireTriggered`][agents.exceptions.InputGuardrailTripwireTriggered], [`OutputGuardrailTripwireTriggered`][agents.exceptions.OutputGuardrailTripwireTriggered]: それぞれ、入力 ガードレール または出力 ガードレール の条件を満たした場合に送出されます。入力 ガードレール は処理前に受信メッセージをチェックし、出力 ガードレール は配信前にエージェントの最終応答をチェックします。 \ No newline at end of file diff --git a/docs/ja/sessions.md b/docs/ja/sessions.md index 357641461..b722a867d 100644 --- a/docs/ja/sessions.md +++ b/docs/ja/sessions.md @@ -4,9 +4,9 @@ search: --- # セッション -Agents SDK には、複数のエージェント実行にわたって会話履歴を自動的に保持する組み込みのセッションメモリがあり、ターン間で手動で `.to_input_list()` を扱う必要がなくなります。 +Agents SDK は、複数のエージェント実行にわたって会話履歴を自動で維持する組み込みのセッションメモリを提供し、ターン間で手動で `.to_input_list()` を扱う必要をなくします。 -セッションは特定のセッションの会話履歴を保存し、明示的な手動メモリ管理を行わずにエージェントがコンテキストを維持できるようにします。これは、エージェントに過去のやり取りを記憶させたいチャットアプリケーションやマルチターンの会話を構築する際に特に有用です。 +セッションは特定のセッションに対する会話履歴を保存し、明示的な手動メモリ管理なしでエージェントがコンテキストを維持できるようにします。これは、エージェントに過去のやり取りを記憶させたいチャットアプリケーションやマルチターンの会話を構築する際に特に有用です。 ## クイックスタート @@ -49,19 +49,19 @@ print(result.final_output) # "Approximately 39 million" ## 仕組み -セッションメモリを有効にすると: +セッションメモリが有効な場合: -1. **各実行の前** : ランナーはセッションの会話履歴を自動的に取得し、入力アイテムの先頭に追加します。 -2. **各実行の後** : 実行中に生成されたすべての新しいアイテム(ユーザー入力、アシスタントの応答、ツール呼び出しなど)が自動的にセッションに保存されます。 -3. **コンテキストの保持** : 同じセッションでの後続の実行には完全な会話履歴が含まれ、エージェントはコンテキストを維持できます。 +1. **各実行の前**: ランナーはセッションの会話履歴を自動的に取得し、入力アイテムの前に付加します。 +2. **各実行の後**: 実行中に生成されたすべての新しいアイテム (ユーザー入力、アシスタントの応答、ツール呼び出しなど) は自動的にセッションに保存されます。 +3. **コンテキスト保持**: 同一セッションでの後続の実行には完全な会話履歴が含まれ、エージェントはコンテキストを維持できます。 -これにより、手動で `.to_input_list()` を呼び出したり、実行間で会話状態を管理したりする必要がなくなります。 +これにより、ターン間で `.to_input_list()` を手動で呼び出して会話状態を管理する必要がなくなります。 ## メモリ操作 ### 基本操作 -セッションは会話履歴を管理するためのいくつかの操作をサポートします: +セッションは会話履歴を管理するためにいくつかの操作をサポートします: ```python from agents import SQLiteSession @@ -88,7 +88,7 @@ await session.clear_session() ### 修正のための pop_item の使用 -`pop_item` メソッドは、会話の最後のアイテムを取り消したり変更したりしたい場合に特に便利です: +会話内の最後のアイテムを取り消したり修正したい場合、`pop_item` メソッドが特に便利です: ```python from agents import Agent, Runner, SQLiteSession @@ -119,7 +119,7 @@ print(f"Agent: {result.final_output}") ## メモリオプション -### メモリなし(デフォルト) +### メモリなし (デフォルト) ```python # Default behavior - no session memory @@ -128,8 +128,7 @@ result = await Runner.run(agent, "Hello") ### OpenAI Conversations API メモリ -[OpenAI Conversations API](https://platform.openai.com/docs/api-reference/conversations/create) を使用して、 -[conversation state](https://platform.openai.com/docs/guides/conversation-state?api-mode=responses#using-the-conversations-api) を自前のデータベースを管理せずに永続化します。これは、会話履歴の保存に OpenAI がホストするインフラにすでに依存している場合に役立ちます。 +自前のデータベースを管理せずに [会話状態](https://platform.openai.com/docs/guides/conversation-state?api-mode=responses#using-the-conversations-api) を永続化するには、[OpenAI Conversations API](https://platform.openai.com/docs/api-reference/conversations/create) を使用します。これは、会話履歴の保存に OpenAI がホストするインフラストラクチャに既に依存している場合に役立ちます。 ```python from agents import OpenAIConversationsSession @@ -190,9 +189,9 @@ result2 = await Runner.run( ### SQLAlchemy ベースのセッション -より高度なユースケースでは、SQLAlchemy ベースのセッションバックエンドを使用できます。これにより、セッションストレージに SQLAlchemy がサポートする任意のデータベース(PostgreSQL、MySQL、SQLite など)を使用できます。 +より高度なユースケースでは、SQLAlchemy ベースのセッションバックエンドを使用できます。これにより、セッションストレージに SQLAlchemy がサポートする任意のデータベース (PostgreSQL、MySQL、SQLite など) を使用できます。 -**例 1: `from_url` とインメモリ SQLite の使用** +**例 1: `from_url` を使ったインメモリ SQLite** これは最も簡単な開始方法で、開発やテストに最適です。 @@ -215,9 +214,9 @@ if __name__ == "__main__": asyncio.run(main()) ``` -**例 2: 既存の SQLAlchemy エンジンの使用** +**例 2: 既存の SQLAlchemy エンジンを使用** -本番アプリケーションでは、すでに SQLAlchemy の `AsyncEngine` インスタンスを持っている可能性が高いです。これをセッションに直接渡せます。 +本番アプリケーションでは、すでに SQLAlchemy の `AsyncEngine` インスタンスを持っている可能性が高いです。これをそのままセッションに渡せます。 ```python import asyncio @@ -247,9 +246,9 @@ if __name__ == "__main__": ### 暗号化セッション -保存時に会話データの暗号化が必要なアプリケーションでは、`EncryptedSession` を使用して任意のセッションバックエンドを透過的な暗号化と自動 TTL ベースの有効期限付きでラップできます。これには `encrypt` エクストラが必要です: `pip install openai-agents[encrypt]`。 +保存時に会話データの暗号化が必要なアプリケーションでは、`EncryptedSession` を使用して任意のセッションバックエンドを透過的な暗号化と自動 TTL ベースの有効期限でラップできます。これには `encrypt` エクストラが必要です: `pip install openai-agents[encrypt]`。 -`EncryptedSession` は、セッションごとの鍵導出(HKDF)を用いた Fernet 暗号化を使用し、古いメッセージの自動有効期限切れをサポートします。アイテムが TTL を超えた場合、取得時に黙ってスキップされます。 +`EncryptedSession` は、セッションごとのキー導出 (HKDF) を用いた Fernet 暗号化を使用し、古いメッセージの自動期限切れをサポートします。アイテムが TTL を超えると、取得時に静かにスキップされます。 **例: SQLAlchemy セッションデータの暗号化** @@ -282,19 +281,19 @@ if __name__ == "__main__": asyncio.run(main()) ``` -**主な特徴:** +**主な特長:** -- **透過的な暗号化** : 保存前にすべてのセッションアイテムを自動的に暗号化し、取得時に復号します -- **セッションごとの鍵導出** : セッション ID をソルトとして HKDF を使用し、一意の暗号鍵を導出します -- **TTL ベースの有効期限** : 設定可能な time-to-live(デフォルト: 10 分)に基づいて古いメッセージを自動的に期限切れにします -- **柔軟な鍵入力** : 暗号鍵として Fernet キーまたは生の文字列のいずれかを受け付けます -- **任意のセッションをラップ** : SQLite、SQLAlchemy、またはカスタムセッション実装で機能します +- **透過的な暗号化**: 保存前にすべてのセッションアイテムを自動的に暗号化し、取得時に復号化します +- **セッションごとのキー導出**: セッション ID をソルトとした HKDF で一意の暗号鍵を導出します +- **TTL ベースの有効期限**: 設定可能な有効期間に基づいて古いメッセージを自動的に期限切れにします (デフォルト: 10 分) +- **柔軟な鍵入力**: Fernet キーまたは生の文字列のいずれも暗号鍵として受け付けます +- **任意のセッションをラップ**: SQLite、SQLAlchemy、またはカスタムセッション実装で動作します !!! warning "重要なセキュリティに関する注意" - - 暗号鍵は安全に保存してください(例: 環境変数、シークレットマネージャー) - - 期限切れのトークンはアプリケーションサーバーのシステムクロックに基づいて拒否されます。クロックのずれにより有効なトークンが拒否されるのを避けるため、すべてのサーバーが NTP で時刻同期されていることを確認してください - - 基盤となるセッションは引き続き暗号化済みデータを保存するため、データベースインフラの管理はあなたのコントロール下にあります + - 暗号鍵は安全に保管してください (例: 環境変数、シークレットマネージャー) + - 期限切れトークンの拒否はアプリケーション サーバーのシステムクロックに基づきます。正当なトークンがクロックずれにより拒否されないよう、すべてのサーバーが NTP で時刻同期されていることを確認してください + - 基盤となるセッションは暗号化済みデータを保存し続けるため、データベース インフラストラクチャの管理権限は保持されます ## カスタムメモリ実装 @@ -346,20 +345,20 @@ result = await Runner.run( ### セッション ID の命名 -会話を整理しやすくする意味のあるセッション ID を使用します: +会話の整理に役立つわかりやすいセッション ID を使用します: -- ユーザー基準: `"user_12345"` -- スレッド基準: `"thread_abc123"` -- コンテキスト基準: `"support_ticket_456"` +- ユーザー基準: `"user_12345"` +- スレッド基準: `"thread_abc123"` +- コンテキスト基準: `"support_ticket_456"` ### メモリ永続化 -- 一時的な会話にはインメモリ SQLite(`SQLiteSession("session_id")`)を使用 -- 永続的な会話にはファイルベースの SQLite(`SQLiteSession("session_id", "path/to/db.sqlite")`)を使用 -- 既存のデータベース(SQLAlchemy がサポート)を持つ本番システムには SQLAlchemy ベースのセッション(`SQLAlchemySession("session_id", engine=engine, create_tables=True)`)を使用 -- 履歴を OpenAI Conversations API に保存したい場合は OpenAI がホストするストレージ(`OpenAIConversationsSession()`)を使用 -- 暗号化と TTL ベースの有効期限を透過的に付与するには暗号化セッション(`EncryptedSession(session_id, underlying_session, encryption_key)`)で任意のセッションをラップ -- より高度なユースケース向けに、他の本番システム(Redis、Django など)用のカスタムセッションバックエンドの実装を検討 +- 一時的な会話にはインメモリ SQLite (`SQLiteSession("session_id")`) を使用 +- 永続的な会話にはファイルベース SQLite (`SQLiteSession("session_id", "path/to/db.sqlite")`) を使用 +- 既存のデータベースを持つ本番システムには SQLAlchemy ベースのセッション (`SQLAlchemySession("session_id", engine=engine, create_tables=True)`) を使用 +- 履歴を OpenAI Conversations API に保存したい場合は OpenAI がホストするストレージ (`OpenAIConversationsSession()`) を使用 +- 透過的な暗号化と TTL ベースの有効期限で任意のセッションをラップするには暗号化セッション (`EncryptedSession(session_id, underlying_session, encryption_key)`) を使用 +- さらに高度なユースケース向けに、他の本番システム (Redis、Django など) 用のカスタムセッションバックエンドの実装を検討 ### セッション管理 @@ -385,9 +384,9 @@ result2 = await Runner.run( ) ``` -## 完全なコード例 +## 完全な例 -以下は、セッションメモリの動作を示す完全な例です: +セッションメモリの動作を示す完全な例です: ```python import asyncio @@ -451,10 +450,10 @@ if __name__ == "__main__": ## API リファレンス -詳細な API ドキュメントは次を参照してください: +詳細な API ドキュメントは以下をご覧ください: -- [`Session`][agents.memory.Session] - プロトコルインターフェース -- [`SQLiteSession`][agents.memory.SQLiteSession] - SQLite 実装 -- [`OpenAIConversationsSession`](ref/memory/openai_conversations_session.md) - OpenAI Conversations API 実装 -- [`SQLAlchemySession`][agents.extensions.memory.sqlalchemy_session.SQLAlchemySession] - SQLAlchemy ベースの実装 -- [`EncryptedSession`][agents.extensions.memory.encrypt_session.EncryptedSession] - TTL 対応の暗号化セッションラッパー \ No newline at end of file +- [`Session`][agents.memory.Session] - プロトコルインターフェース +- [`SQLiteSession`][agents.memory.SQLiteSession] - SQLite 実装 +- [`OpenAIConversationsSession`](ref/memory/openai_conversations_session.md) - OpenAI Conversations API 実装 +- [`SQLAlchemySession`][agents.extensions.memory.sqlalchemy_session.SQLAlchemySession] - SQLAlchemy ベースの実装 +- [`EncryptedSession`][agents.extensions.memory.encrypt_session.EncryptedSession] - TTL 付き暗号化セッションラッパー \ No newline at end of file diff --git a/docs/ja/sessions/advanced_sqlite_session.md b/docs/ja/sessions/advanced_sqlite_session.md new file mode 100644 index 000000000..2f7aaa18a --- /dev/null +++ b/docs/ja/sessions/advanced_sqlite_session.md @@ -0,0 +1,306 @@ +--- +search: + exclude: true +--- +# 高度な SQLite セッション + +`AdvancedSQLiteSession` は、基本の `SQLiteSession` を拡張した強化版で、会話の分岐、詳細な使用状況分析、構造化された会話クエリなど、高度な会話管理機能を提供します。 + +## 機能 + +- **会話の分岐**: 任意の ユーザー メッセージから代替の会話パスを作成 +- **使用状況の追跡**: 各ターンごとの詳細なトークン使用分析と完全な JSON 内訳 +- **構造化クエリ**: ターン単位の会話取得、ツール使用統計など +- **ブランチ管理**: 独立したブランチの切り替えと管理 +- **メッセージ構造のメタデータ**: メッセージ種別、ツール使用、会話フローを追跡 + +## クイックスタート + +```python +from agents import Agent, Runner +from agents.extensions.memory import AdvancedSQLiteSession + +# Create agent +agent = Agent( + name="Assistant", + instructions="Reply very concisely.", +) + +# Create an advanced session +session = AdvancedSQLiteSession( + session_id="conversation_123", + db_path="conversations.db", + create_tables=True +) + +# First conversation turn +result = await Runner.run( + agent, + "What city is the Golden Gate Bridge in?", + session=session +) +print(result.final_output) # "San Francisco" + +# IMPORTANT: Store usage data +await session.store_run_usage(result) + +# Continue conversation +result = await Runner.run( + agent, + "What state is it in?", + session=session +) +print(result.final_output) # "California" +await session.store_run_usage(result) +``` + +## 初期化 + +```python +from agents.extensions.memory import AdvancedSQLiteSession + +# Basic initialization +session = AdvancedSQLiteSession( + session_id="my_conversation", + create_tables=True # Auto-create advanced tables +) + +# With persistent storage +session = AdvancedSQLiteSession( + session_id="user_123", + db_path="path/to/conversations.db", + create_tables=True +) + +# With custom logger +import logging +logger = logging.getLogger("my_app") +session = AdvancedSQLiteSession( + session_id="session_456", + create_tables=True, + logger=logger +) +``` + +### パラメーター + +- `session_id` (str): 会話セッションの一意の識別子 +- `db_path` (str | Path): SQLite データベース ファイルへのパス。メモリ内ストレージの場合は `:memory:` がデフォルト +- `create_tables` (bool): 高度なテーブルを自動作成するかどうか。デフォルトは `False` +- `logger` (logging.Logger | None): セッション用のカスタムロガー。デフォルトはモジュールのロガー + +## 使用状況の追跡 + +AdvancedSQLiteSession は、会話の各ターンごとにトークン使用データを保存することで、詳細な使用状況分析を提供します。**これは各 エージェント 実行後に `store_run_usage` メソッドが呼び出されることに完全に依存します。** + +### 使用データの保存 + +```python +# After each agent run, store the usage data +result = await Runner.run(agent, "Hello", session=session) +await session.store_run_usage(result) + +# This stores: +# - Total tokens used +# - Input/output token breakdown +# - Request count +# - Detailed JSON token information (if available) +``` + +### 使用統計の取得 + +```python +# Get session-level usage (all branches) +session_usage = await session.get_session_usage() +if session_usage: + print(f"Total requests: {session_usage['requests']}") + print(f"Total tokens: {session_usage['total_tokens']}") + print(f"Input tokens: {session_usage['input_tokens']}") + print(f"Output tokens: {session_usage['output_tokens']}") + print(f"Total turns: {session_usage['total_turns']}") + +# Get usage for specific branch +branch_usage = await session.get_session_usage(branch_id="main") + +# Get usage by turn +turn_usage = await session.get_turn_usage() +for turn_data in turn_usage: + print(f"Turn {turn_data['user_turn_number']}: {turn_data['total_tokens']} tokens") + if turn_data['input_tokens_details']: + print(f" Input details: {turn_data['input_tokens_details']}") + if turn_data['output_tokens_details']: + print(f" Output details: {turn_data['output_tokens_details']}") + +# Get usage for specific turn +turn_2_usage = await session.get_turn_usage(user_turn_number=2) +``` + +## 会話の分岐 + +AdvancedSQLiteSession の主要機能の 1 つは、任意の ユーザー メッセージから会話ブランチを作成し、代替の会話パスを探索できることです。 + +### ブランチの作成 + +```python +# Get available turns for branching +turns = await session.get_conversation_turns() +for turn in turns: + print(f"Turn {turn['turn']}: {turn['content']}") + print(f"Can branch: {turn['can_branch']}") + +# Create a branch from turn 2 +branch_id = await session.create_branch_from_turn(2) +print(f"Created branch: {branch_id}") + +# Create a branch with custom name +branch_id = await session.create_branch_from_turn( + 2, + branch_name="alternative_path" +) + +# Create branch by searching for content +branch_id = await session.create_branch_from_content( + "weather", + branch_name="weather_focus" +) +``` + +### ブランチ管理 + +```python +# List all branches +branches = await session.list_branches() +for branch in branches: + current = " (current)" if branch["is_current"] else "" + print(f"{branch['branch_id']}: {branch['user_turns']} turns, {branch['message_count']} messages{current}") + +# Switch between branches +await session.switch_to_branch("main") +await session.switch_to_branch(branch_id) + +# Delete a branch +await session.delete_branch(branch_id, force=True) # force=True allows deleting current branch +``` + +### ブランチのワークフロー例 + +```python +# Original conversation +result = await Runner.run(agent, "What's the capital of France?", session=session) +await session.store_run_usage(result) + +result = await Runner.run(agent, "What's the weather like there?", session=session) +await session.store_run_usage(result) + +# Create branch from turn 2 (weather question) +branch_id = await session.create_branch_from_turn(2, "weather_focus") + +# Continue in new branch with different question +result = await Runner.run( + agent, + "What are the main tourist attractions in Paris?", + session=session +) +await session.store_run_usage(result) + +# Switch back to main branch +await session.switch_to_branch("main") + +# Continue original conversation +result = await Runner.run( + agent, + "How expensive is it to visit?", + session=session +) +await session.store_run_usage(result) +``` + +## 構造化クエリ + +AdvancedSQLiteSession は、会話の構造と内容を分析するための複数のメソッドを提供します。 + +### 会話分析 + +```python +# Get conversation organized by turns +conversation_by_turns = await session.get_conversation_by_turns() +for turn_num, items in conversation_by_turns.items(): + print(f"Turn {turn_num}: {len(items)} items") + for item in items: + if item["tool_name"]: + print(f" - {item['type']} (tool: {item['tool_name']})") + else: + print(f" - {item['type']}") + +# Get tool usage statistics +tool_usage = await session.get_tool_usage() +for tool_name, count, turn in tool_usage: + print(f"{tool_name}: used {count} times in turn {turn}") + +# Find turns by content +matching_turns = await session.find_turns_by_content("weather") +for turn in matching_turns: + print(f"Turn {turn['turn']}: {turn['content']}") +``` + +### メッセージ構造 + +セッションは、以下を含むメッセージ構造を自動的に追跡します。 + +- メッセージ種別(user、assistant、tool_call など) +- ツール呼び出しのツール名 +- ターン番号とシーケンス番号 +- ブランチの関連付け +- タイムスタンプ + +## データベース スキーマ + +AdvancedSQLiteSession は、基本の SQLite スキーマを拡張し、次の 2 つの追加テーブルを提供します。 + +### message_structure テーブル + +```sql +CREATE TABLE message_structure ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + session_id TEXT NOT NULL, + message_id INTEGER NOT NULL, + branch_id TEXT NOT NULL DEFAULT 'main', + message_type TEXT NOT NULL, + sequence_number INTEGER NOT NULL, + user_turn_number INTEGER, + branch_turn_number INTEGER, + tool_name TEXT, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (session_id) REFERENCES agent_sessions(session_id) ON DELETE CASCADE, + FOREIGN KEY (message_id) REFERENCES agent_messages(id) ON DELETE CASCADE +); +``` + +### turn_usage テーブル + +```sql +CREATE TABLE turn_usage ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + session_id TEXT NOT NULL, + branch_id TEXT NOT NULL DEFAULT 'main', + user_turn_number INTEGER NOT NULL, + requests INTEGER DEFAULT 0, + input_tokens INTEGER DEFAULT 0, + output_tokens INTEGER DEFAULT 0, + total_tokens INTEGER DEFAULT 0, + input_tokens_details JSON, + output_tokens_details JSON, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (session_id) REFERENCES agent_sessions(session_id) ON DELETE CASCADE, + UNIQUE(session_id, branch_id, user_turn_number) +); +``` + +## 完全な例 + +すべての機能を包括的に示す [complete example](https://github.com/openai/openai-agents-python/tree/main/examples/memory/advanced_sqlite_session_example.py) をご覧ください。 + +## API リファレンス + +- [`AdvancedSQLiteSession`][agents.extensions.memory.advanced_sqlite_session.AdvancedSQLiteSession] - メインクラス +- [`Session`][agents.memory.session.Session] - ベースセッションプロトコル \ No newline at end of file diff --git a/docs/ja/sessions/encrypted_session.md b/docs/ja/sessions/encrypted_session.md new file mode 100644 index 000000000..162e3dded --- /dev/null +++ b/docs/ja/sessions/encrypted_session.md @@ -0,0 +1,179 @@ +--- +search: + exclude: true +--- +# 暗号化セッション + +`EncryptedSession` は任意のセッション実装に透過的な暗号化を提供し、会話データを保護するとともに古い項目を自動的に期限切れにします。 + +## 特長 + +- **透過的な暗号化**: 任意のセッションを Fernet 暗号化でラップします +- **セッションごとのキー**: 一意の暗号化のために HKDF キー導出を使用します +- **自動期限切れ**: TTL が切れた古い項目は静かにスキップされます +- **ドロップイン代替**: 既存のどのセッション実装でも動作します + +## インストール + +暗号化セッションには `encrypt` 追加オプションが必要です: + +```bash +pip install openai-agents[encrypt] +``` + +## クイックスタート + +```python +import asyncio +from agents import Agent, Runner +from agents.extensions.memory import EncryptedSession, SQLAlchemySession + +async def main(): + agent = Agent("Assistant") + + # Create underlying session + underlying_session = SQLAlchemySession.from_url( + "user-123", + url="sqlite+aiosqlite:///:memory:", + create_tables=True + ) + + # Wrap with encryption + session = EncryptedSession( + session_id="user-123", + underlying_session=underlying_session, + encryption_key="your-secret-key-here", + ttl=600 # 10 minutes + ) + + result = await Runner.run(agent, "Hello", session=session) + print(result.final_output) + +if __name__ == "__main__": + asyncio.run(main()) +``` + +## 設定 + +### 暗号化キー + +暗号化キーは Fernet キーまたは任意の文字列にできます: + +```python +from agents.extensions.memory import EncryptedSession + +# Using a Fernet key (base64-encoded) +session = EncryptedSession( + session_id="user-123", + underlying_session=underlying_session, + encryption_key="your-fernet-key-here", + ttl=600 +) + +# Using a raw string (will be derived to a key) +session = EncryptedSession( + session_id="user-123", + underlying_session=underlying_session, + encryption_key="my-secret-password", + ttl=600 +) +``` + +### TTL(有効期間) + +暗号化された項目を有効にしておく期間を設定します: + +```python +# Items expire after 1 hour +session = EncryptedSession( + session_id="user-123", + underlying_session=underlying_session, + encryption_key="secret", + ttl=3600 # 1 hour in seconds +) + +# Items expire after 1 day +session = EncryptedSession( + session_id="user-123", + underlying_session=underlying_session, + encryption_key="secret", + ttl=86400 # 24 hours in seconds +) +``` + +## さまざまなセッションタイプでの使用 + +### SQLite セッションでの使用 + +```python +from agents import SQLiteSession +from agents.extensions.memory import EncryptedSession + +# Create encrypted SQLite session +underlying = SQLiteSession("user-123", "conversations.db") + +session = EncryptedSession( + session_id="user-123", + underlying_session=underlying, + encryption_key="secret-key" +) +``` + +### SQLAlchemy セッションでの使用 + +```python +from agents.extensions.memory import EncryptedSession, SQLAlchemySession + +# Create encrypted SQLAlchemy session +underlying = SQLAlchemySession.from_url( + "user-123", + url="postgresql+asyncpg://user:pass@localhost/db", + create_tables=True +) + +session = EncryptedSession( + session_id="user-123", + underlying_session=underlying, + encryption_key="secret-key" +) +``` + +!!! warning "高度なセッション機能" + + `EncryptedSession` を `AdvancedSQLiteSession` のような高度なセッション実装と併用する場合、次に注意してください。 + + - メッセージ内容が暗号化されるため、`find_turns_by_content()` のようなメソッドは有効に機能しません + - 内容に基づく検索は暗号化データ上で実行されるため、その有効性は制限されます + + + +## キー導出 + +EncryptedSession は HKDF(HMAC ベースの Key Derivation Function)を使用して、セッションごとに一意の暗号化キーを導出します。 + +- **マスターキー**: 提供された暗号化キー +- **セッションソルト**: セッション ID +- **Info 文字列**: `"agents.session-store.hkdf.v1"` +- **出力**: 32-byte の Fernet キー + +これにより、次のことが保証されます。 +- 各セッションは一意の暗号化キーを持ちます +- マスターキーなしにキーを導出することはできません +- 異なるセッション間でセッションデータを復号できません + +## 自動期限切れ + +項目が TTL を超えた場合、取得時に自動的にスキップされます。 + +```python +# Items older than TTL are silently ignored +items = await session.get_items() # Only returns non-expired items + +# Expired items don't affect session behavior +result = await Runner.run(agent, "Continue conversation", session=session) +``` + +## API リファレンス + +- [`EncryptedSession`][agents.extensions.memory.encrypt_session.EncryptedSession] - メインクラス +- [`Session`][agents.memory.session.Session] - ベースセッションプロトコル \ No newline at end of file diff --git a/docs/ja/sessions/index.md b/docs/ja/sessions/index.md new file mode 100644 index 000000000..4c124c755 --- /dev/null +++ b/docs/ja/sessions/index.md @@ -0,0 +1,435 @@ +--- +search: + exclude: true +--- +# セッション + +Agents SDK は、複数のエージェント実行にわたって会話履歴を自動的に保持する組み込みのセッションメモリを提供し、ターン間で手動で `.to_input_list()` を扱う必要をなくします。 + +セッションは特定のセッションの会話履歴を保存し、明示的な手動メモリ管理なしにエージェントがコンテキストを維持できるようにします。これは、エージェントに過去のやり取りを記憶させたいチャットアプリケーションやマルチターンの会話を構築する際に特に有用です。 + +## クイックスタート + +```python +from agents import Agent, Runner, SQLiteSession + +# Create agent +agent = Agent( + name="Assistant", + instructions="Reply very concisely.", +) + +# Create a session instance with a session ID +session = SQLiteSession("conversation_123") + +# First turn +result = await Runner.run( + agent, + "What city is the Golden Gate Bridge in?", + session=session +) +print(result.final_output) # "San Francisco" + +# Second turn - agent automatically remembers previous context +result = await Runner.run( + agent, + "What state is it in?", + session=session +) +print(result.final_output) # "California" + +# Also works with synchronous runner +result = Runner.run_sync( + agent, + "What's the population?", + session=session +) +print(result.final_output) # "Approximately 39 million" +``` + +## 仕組み + +セッションメモリが有効な場合: + +1. **各実行の前**: ランナーはセッションの会話履歴を自動的に取得し、入力アイテムの先頭に追加します。 +2. **各実行の後**: 実行中に生成されたすべての新しいアイテム(ユーザー入力、アシスタント応答、ツール呼び出しなど)が自動的にセッションに保存されます。 +3. **コンテキストの保持**: 同じセッションでの後続の実行には完全な会話履歴が含まれ、エージェントはコンテキストを維持できます。 + +これにより、ターン間で `.to_input_list()` を手動で呼び出したり、会話状態を管理したりする必要がなくなります。 + +## メモリ操作 + +### 基本操作 + +セッションは、会話履歴を管理するためのいくつかの操作をサポートします: + +```python +from agents import SQLiteSession + +session = SQLiteSession("user_123", "conversations.db") + +# Get all items in a session +items = await session.get_items() + +# Add new items to a session +new_items = [ + {"role": "user", "content": "Hello"}, + {"role": "assistant", "content": "Hi there!"} +] +await session.add_items(new_items) + +# Remove and return the most recent item +last_item = await session.pop_item() +print(last_item) # {"role": "assistant", "content": "Hi there!"} + +# Clear all items from a session +await session.clear_session() +``` + +### 修正のための pop_item の使用 + +`pop_item` メソッドは、会話の最後のアイテムを元に戻したり修正したい場合に特に便利です: + +```python +from agents import Agent, Runner, SQLiteSession + +agent = Agent(name="Assistant") +session = SQLiteSession("correction_example") + +# Initial conversation +result = await Runner.run( + agent, + "What's 2 + 2?", + session=session +) +print(f"Agent: {result.final_output}") + +# User wants to correct their question +assistant_item = await session.pop_item() # Remove agent's response +user_item = await session.pop_item() # Remove user's question + +# Ask a corrected question +result = await Runner.run( + agent, + "What's 2 + 3?", + session=session +) +print(f"Agent: {result.final_output}") +``` + +## セッションの種類 + +SDK は用途に応じていくつかのセッション実装を提供します: + +### OpenAI Conversations API セッション + +`OpenAIConversationsSession` を通じて [OpenAI の Conversations API](https://platform.openai.com/docs/api-reference/conversations) を使用します。 + +```python +from agents import Agent, Runner, OpenAIConversationsSession + +# Create agent +agent = Agent( + name="Assistant", + instructions="Reply very concisely.", +) + +# Create a new conversation +session = OpenAIConversationsSession() + +# Optionally resume a previous conversation by passing a conversation ID +# session = OpenAIConversationsSession(conversation_id="conv_123") + +# Start conversation +result = await Runner.run( + agent, + "What city is the Golden Gate Bridge in?", + session=session +) +print(result.final_output) # "San Francisco" + +# Continue the conversation +result = await Runner.run( + agent, + "What state is it in?", + session=session +) +print(result.final_output) # "California" +``` + +### SQLite セッション + +デフォルトの軽量な SQLite を使ったセッション実装です: + +```python +from agents import SQLiteSession + +# In-memory database (lost when process ends) +session = SQLiteSession("user_123") + +# Persistent file-based database +session = SQLiteSession("user_123", "conversations.db") + +# Use the session +result = await Runner.run( + agent, + "Hello", + session=session +) +``` + +### SQLAlchemy セッション + +あらゆる SQLAlchemy 対応データベースを使用できる本番環境向けのセッションです: + +```python +from agents.extensions.memory import SQLAlchemySession + +# Using database URL +session = SQLAlchemySession.from_url( + "user_123", + url="postgresql+asyncpg://user:pass@localhost/db", + create_tables=True +) + +# Using existing engine +from sqlalchemy.ext.asyncio import create_async_engine +engine = create_async_engine("postgresql+asyncpg://user:pass@localhost/db") +session = SQLAlchemySession("user_123", engine=engine, create_tables=True) +``` + +詳細なドキュメントは [SQLAlchemy セッション](sqlalchemy_session.md) を参照してください。 + +### 高度な SQLite セッション + +会話の分岐、使用状況分析、構造化クエリを備えた強化版 SQLite セッションです: + +```python +from agents.extensions.memory import AdvancedSQLiteSession + +# Create with advanced features +session = AdvancedSQLiteSession( + session_id="user_123", + db_path="conversations.db", + create_tables=True +) + +# Automatic usage tracking +result = await Runner.run(agent, "Hello", session=session) +await session.store_run_usage(result) # Track token usage + +# Conversation branching +await session.create_branch_from_turn(2) # Branch from turn 2 +``` + +詳細なドキュメントは [高度な SQLite セッション](advanced_sqlite_session.md) を参照してください。 + +### 暗号化セッション + +あらゆるセッション実装に対する透過的な暗号化ラッパーです: + +```python +from agents.extensions.memory import EncryptedSession, SQLAlchemySession + +# Create underlying session +underlying_session = SQLAlchemySession.from_url( + "user_123", + url="sqlite+aiosqlite:///conversations.db", + create_tables=True +) + +# Wrap with encryption and TTL +session = EncryptedSession( + session_id="user_123", + underlying_session=underlying_session, + encryption_key="your-secret-key", + ttl=600 # 10 minutes +) + +result = await Runner.run(agent, "Hello", session=session) +``` + +詳細なドキュメントは [暗号化セッション](encrypted_session.md) を参照してください。 + +## セッション管理 + +### セッション ID の命名 + +会話の整理に役立つ意味のあるセッション ID を使用します: + +- ユーザー単位: `"user_12345"` +- スレッド単位: `"thread_abc123"` +- コンテキスト単位: `"support_ticket_456"` + +### メモリの永続化 + +- 一時的な会話にはインメモリ SQLite(`SQLiteSession("session_id")`)を使用します +- 永続的な会話にはファイルベースの SQLite(`SQLiteSession("session_id", "path/to/db.sqlite")`)を使用します +- 既存の SQLAlchemy 対応データベースを利用する本番システムには SQLAlchemy ベースのセッション(`SQLAlchemySession("session_id", engine=engine, create_tables=True)`)を使用します +- 履歴を OpenAI Conversations API に保存したい場合は OpenAI ホスト型ストレージ(`OpenAIConversationsSession()`)を使用します +- 透過的な暗号化と TTL ベースの有効期限を追加したい場合は暗号化セッション(`EncryptedSession(session_id, underlying_session, encryption_key)`)で任意のセッションをラップします +- さらに高度なユースケースのために、他の本番システム(Redis、Django など)向けのカスタムセッションバックエンドの実装も検討してください + +### 複数セッション + +```python +from agents import Agent, Runner, SQLiteSession + +agent = Agent(name="Assistant") + +# Different sessions maintain separate conversation histories +session_1 = SQLiteSession("user_123", "conversations.db") +session_2 = SQLiteSession("user_456", "conversations.db") + +result1 = await Runner.run( + agent, + "Help me with my account", + session=session_1 +) +result2 = await Runner.run( + agent, + "What are my charges?", + session=session_2 +) +``` + +### セッション共有 + +```python +# Different agents can share the same session +support_agent = Agent(name="Support") +billing_agent = Agent(name="Billing") +session = SQLiteSession("user_123") + +# Both agents will see the same conversation history +result1 = await Runner.run( + support_agent, + "Help me with my account", + session=session +) +result2 = await Runner.run( + billing_agent, + "What are my charges?", + session=session +) +``` + +## 完全な例 + +セッションメモリが動作する完全な例を次に示します: + +```python +import asyncio +from agents import Agent, Runner, SQLiteSession + + +async def main(): + # Create an agent + agent = Agent( + name="Assistant", + instructions="Reply very concisely.", + ) + + # Create a session instance that will persist across runs + session = SQLiteSession("conversation_123", "conversation_history.db") + + print("=== Sessions Example ===") + print("The agent will remember previous messages automatically.\n") + + # First turn + print("First turn:") + print("User: What city is the Golden Gate Bridge in?") + result = await Runner.run( + agent, + "What city is the Golden Gate Bridge in?", + session=session + ) + print(f"Assistant: {result.final_output}") + print() + + # Second turn - the agent will remember the previous conversation + print("Second turn:") + print("User: What state is it in?") + result = await Runner.run( + agent, + "What state is it in?", + session=session + ) + print(f"Assistant: {result.final_output}") + print() + + # Third turn - continuing the conversation + print("Third turn:") + print("User: What's the population of that state?") + result = await Runner.run( + agent, + "What's the population of that state?", + session=session + ) + print(f"Assistant: {result.final_output}") + print() + + print("=== Conversation Complete ===") + print("Notice how the agent remembered the context from previous turns!") + print("Sessions automatically handles conversation history.") + + +if __name__ == "__main__": + asyncio.run(main()) +``` + +## カスタムセッション実装 + +[`Session`][agents.memory.session.Session] プロトコルに従うクラスを作成することで、独自のセッションメモリを実装できます: + +```python +from agents.memory.session import SessionABC +from agents.items import TResponseInputItem +from typing import List + +class MyCustomSession(SessionABC): + """Custom session implementation following the Session protocol.""" + + def __init__(self, session_id: str): + self.session_id = session_id + # Your initialization here + + async def get_items(self, limit: int | None = None) -> List[TResponseInputItem]: + """Retrieve conversation history for this session.""" + # Your implementation here + pass + + async def add_items(self, items: List[TResponseInputItem]) -> None: + """Store new items for this session.""" + # Your implementation here + pass + + async def pop_item(self) -> TResponseInputItem | None: + """Remove and return the most recent item from this session.""" + # Your implementation here + pass + + async def clear_session(self) -> None: + """Clear all items for this session.""" + # Your implementation here + pass + +# Use your custom session +agent = Agent(name="Assistant") +result = await Runner.run( + agent, + "Hello", + session=MyCustomSession("my_session") +) +``` + +## API リファレンス + +詳細な API ドキュメントは次を参照してください: + +- [`Session`][agents.memory.session.Session] - プロトコルインターフェース +- [`OpenAIConversationsSession`][agents.memory.OpenAIConversationsSession] - OpenAI Conversations API 実装 +- [`SQLiteSession`][agents.memory.sqlite_session.SQLiteSession] - 基本的な SQLite 実装 +- [`SQLAlchemySession`][agents.extensions.memory.sqlalchemy_session.SQLAlchemySession] - SQLAlchemy ベースの実装 +- [`AdvancedSQLiteSession`][agents.extensions.memory.advanced_sqlite_session.AdvancedSQLiteSession] - 分岐と分析を備えた強化版 SQLite +- [`EncryptedSession`][agents.extensions.memory.encrypt_session.EncryptedSession] - 任意のセッション用の暗号化ラッパー \ No newline at end of file diff --git a/docs/ja/sessions/sqlalchemy_session.md b/docs/ja/sessions/sqlalchemy_session.md new file mode 100644 index 000000000..5e9c3c52f --- /dev/null +++ b/docs/ja/sessions/sqlalchemy_session.md @@ -0,0 +1,80 @@ +--- +search: + exclude: true +--- +# SQLAlchemy セッション + +`SQLAlchemySession` は SQLAlchemy を使用して本番運用可能なセッション実装を提供し、SQLAlchemy がサポートする任意のデータベース (PostgreSQL、MySQL、SQLite など) をセッションストレージとして使用できます。 + +## インストール + +SQLAlchemy セッションには `sqlalchemy` エクストラが必要です: + +```bash +pip install openai-agents[sqlalchemy] +``` + +## クイックスタート + +### データベース URL の使用 + +最も簡単な開始方法: + +```python +import asyncio +from agents import Agent, Runner +from agents.extensions.memory import SQLAlchemySession + +async def main(): + agent = Agent("Assistant") + + # Create session using database URL + session = SQLAlchemySession.from_url( + "user-123", + url="sqlite+aiosqlite:///:memory:", + create_tables=True + ) + + result = await Runner.run(agent, "Hello", session=session) + print(result.final_output) + +if __name__ == "__main__": + asyncio.run(main()) +``` + +### 既存の SQLAlchemy エンジンの使用 + +既存の SQLAlchemy エンジンを持つアプリケーション向け: + +```python +import asyncio +from agents import Agent, Runner +from agents.extensions.memory import SQLAlchemySession +from sqlalchemy.ext.asyncio import create_async_engine + +async def main(): + # Create your database engine + engine = create_async_engine("postgresql+asyncpg://user:pass@localhost/db") + + agent = Agent("Assistant") + session = SQLAlchemySession( + "user-456", + engine=engine, + create_tables=True + ) + + result = await Runner.run(agent, "Hello", session=session) + print(result.final_output) + + # Clean up + await engine.dispose() + +if __name__ == "__main__": + asyncio.run(main()) +``` + + +## API リファレンス + +- [`SQLAlchemySession`][agents.extensions.memory.sqlalchemy_session.SQLAlchemySession] - メインクラス +- [`Session`][agents.memory.session.Session] - セッションのベースプロトコル \ No newline at end of file diff --git a/docs/ja/streaming.md b/docs/ja/streaming.md index 8aa0f12de..7ef4c1b64 100644 --- a/docs/ja/streaming.md +++ b/docs/ja/streaming.md @@ -4,15 +4,15 @@ search: --- # ストリーミング -ストリーミングを使うと、進行中のエージェントの実行に関する更新を購読できます。これはエンドユーザーへの進捗表示や部分的な応答の提示に役立ちます。 +ストリーミング を使用すると、エージェント の実行の進行に合わせて更新を購読できます。これは、エンドユーザー に進捗更新や部分的なレスポンスを表示するのに役立ちます。 -ストリーミングするには、[`Runner.run_streamed()`][agents.run.Runner.run_streamed] を呼び出します。これは [`RunResultStreaming`][agents.result.RunResultStreaming] を返します。`result.stream_events()` を呼ぶと、以下で説明する [`StreamEvent`][agents.stream_events.StreamEvent] オブジェクトの非同期ストリームが得られます。 +ストリーミング を行うには、[`Runner.run_streamed()`][agents.run.Runner.run_streamed] を呼び出します。これにより、[`RunResultStreaming`][agents.result.RunResultStreaming] が得られます。`result.stream_events()` を呼び出すと、[`StreamEvent`][agents.stream_events.StreamEvent] オブジェクトの非同期ストリームが得られます。詳細は以下で説明します。 ## raw レスポンスイベント -[`RawResponsesStreamEvent`][agents.stream_events.RawResponsesStreamEvent] は LLM から直接渡される raw なイベントです。OpenAI Responses API 形式であり、各イベントにはタイプ(`response.created`、`response.output_text.delta` など)とデータがあります。これらのイベントは、生成され次第、ユーザーに応答メッセージをストリーミングしたい場合に役立ちます。 +[`RawResponsesStreamEvent`][agents.stream_events.RawResponsesStreamEvent] は、LLM から直接渡される raw イベントです。これらは OpenAI Responses API 形式であり、各イベントには種類(`response.created`、`response.output_text.delta` など)とデータがあります。これらのイベントは、生成され次第すぐにユーザー にレスポンスメッセージをストリーミングしたい場合に有用です。 -例えば、次のコードは LLM が生成したテキストをトークンごとに出力します。 +例えば、これは LLM が生成したテキストをトークン単位で出力します。 ```python import asyncio @@ -35,11 +35,11 @@ if __name__ == "__main__": asyncio.run(main()) ``` -## 実行アイテムイベントとエージェントイベント +## Run item イベントと エージェント イベント -[`RunItemStreamEvent`][agents.stream_events.RunItemStreamEvent] は、より高レベルのイベントです。アイテムが完全に生成されたタイミングを通知します。これにより、トークン単位ではなく「メッセージが生成された」「ツールが実行された」などの粒度で進捗更新を行えます。同様に、[`AgentUpdatedStreamEvent`][agents.stream_events.AgentUpdatedStreamEvent] は現在のエージェントが変更された(例: handoff の結果として)際の更新を通知します。 +[`RunItemStreamEvent`][agents.stream_events.RunItemStreamEvent] は、より高レベルのイベントです。アイテムが完全に生成されたタイミングを通知します。これにより、各トークンごとではなく、「メッセージの生成完了」「ツールの実行完了」などのレベルで進捗更新をプッシュできます。同様に、[`AgentUpdatedStreamEvent`][agents.stream_events.AgentUpdatedStreamEvent] は、現在のエージェント が変更されたとき(例えば ハンドオフ の結果として)に更新を提供します。 -例えば、次のコードは raw イベントを無視し、ユーザーに更新をストリーミングします。 +例えば、これは raw イベントを無視し、ユーザー へ更新をストリーミングします。 ```python import asyncio diff --git a/docs/ja/tools.md b/docs/ja/tools.md index 349ad95fa..48f472fab 100644 --- a/docs/ja/tools.md +++ b/docs/ja/tools.md @@ -4,21 +4,21 @@ search: --- # ツール -ツールは エージェント がアクションを実行するためのものです。例えば、データの取得、コードの実行、外部 API の呼び出し、さらにはコンピュータの使用などです。Agents SDK には 3 つのツールのクラスがあります: +ツールは エージェント にアクションを実行させます。たとえばデータの取得、コードの実行、外部 API の呼び出し、さらにはコンピュータの使用などです。Agent SDK には 3 つのツールのクラスがあります: -- Hosted tools: これらは LLM サーバー上で AI モデルと並行して実行されます。OpenAI は retrieval、Web 検索、コンピュータ操作 を hosted tools として提供します。 +- Hosted ツール: これらは LLM サーバー 上で AI モデルと並行して動作します。OpenAI は retrieval、Web 検索、コンピュータ操作 を Hosted ツールとして提供しています。 - Function calling: 任意の Python 関数をツールとして使えます。 -- Agents as tools: エージェント をツールとして使えるため、ハンドオフ せずに他の エージェント を呼び出せます。 +- ツールとしての エージェント: エージェント をツールとして使えるため、ハンドオフ せずに他の エージェント を呼び出せます。 -## Hosted tools +## Hosted ツール -OpenAI は [`OpenAIResponsesModel`][agents.models.openai_responses.OpenAIResponsesModel] を使用する際に、いくつかの組み込みツールを提供します: +OpenAI は [`OpenAIResponsesModel`][agents.models.openai_responses.OpenAIResponsesModel] を使用する際に、いくつかの組み込みツールを提供しています: -- [`WebSearchTool`][agents.tool.WebSearchTool]: エージェント が Web を検索できます。 -- [`FileSearchTool`][agents.tool.FileSearchTool]: OpenAI の ベクトルストア から情報を取得できます。 -- [`ComputerTool`][agents.tool.ComputerTool]: コンピュータ操作 の自動化ができます。 +- [`WebSearchTool`][agents.tool.WebSearchTool]: エージェント に Web を検索させます。 +- [`FileSearchTool`][agents.tool.FileSearchTool]: OpenAI ベクトルストア から情報を取得できます。 +- [`ComputerTool`][agents.tool.ComputerTool]: コンピュータ操作 タスクを自動化できます。 - [`CodeInterpreterTool`][agents.tool.CodeInterpreterTool]: LLM がサンドボックス環境でコードを実行できます。 -- [`HostedMCPTool`][agents.tool.HostedMCPTool]: リモートの MCP サーバーのツールをモデルに公開します。 +- [`HostedMCPTool`][agents.tool.HostedMCPTool]: リモートの MCP サーバー のツールをモデルに公開します。 - [`ImageGenerationTool`][agents.tool.ImageGenerationTool]: プロンプトから画像を生成します。 - [`LocalShellTool`][agents.tool.LocalShellTool]: マシン上でシェルコマンドを実行します。 @@ -43,11 +43,11 @@ async def main(): ## 関数ツール -任意の Python 関数をツールとして使用できます。Agents SDK がツールのセットアップを自動で行います: +任意の Python 関数をツールとして使用できます。Agents SDK がツールを自動的にセットアップします: - ツール名は Python 関数名になります(または名前を指定できます) -- ツールの説明は関数の docstring から取得します(または説明を指定できます) -- 関数入力のスキーマは関数の引数から自動的に作成されます +- ツールの説明は関数の docstring から取得されます(または説明を指定できます) +- 関数入力のスキーマは関数の引数から自動生成されます - 各入力の説明は、無効化しない限り、関数の docstring から取得されます Python の `inspect` モジュールで関数シグネチャを抽出し、[`griffe`](https://mkdocstrings.github.io/griffe/) で docstring を解析し、スキーマ作成には `pydantic` を使用します。 @@ -102,12 +102,12 @@ for tool in agent.tools: ``` -1. 関数の引数には任意の Python 型を使用でき、関数は同期/非同期のどちらでも構いません。 -2. docstring があれば、説明や引数の説明の取得に使用します。 -3. 関数は任意で `context` を受け取れます(最初の引数である必要があります)。ツール名、説明、docstring スタイルなどの上書きも設定できます。 +1. 任意の Python 型を関数の引数に使え、関数は sync/async どちらでも構いません。 +2. docstring があれば、説明および引数の説明に使用します。 +3. 関数は任意で `context` を受け取れます(最初の引数である必要があります)。また、ツール名や説明、docstring スタイルなどのオーバーライドも設定できます。 4. デコレートした関数をツールのリストに渡せます。 -??? note "出力を表示" +??? note "Expand to see output" ``` fetch_weather @@ -177,14 +177,22 @@ for tool in agent.tools: } ``` +### 関数ツールから画像やファイルを返す + +テキスト出力に加えて、関数ツールの出力として 1 つまたは複数の画像やファイルを返すこともできます。そのためには次のいずれかを返します: + +- 画像: [`ToolOutputImage`][agents.tool.ToolOutputImage](または TypedDict 版の [`ToolOutputImageDict`][agents.tool.ToolOutputImageDict]) +- ファイル: [`ToolOutputFileContent`][agents.tool.ToolOutputFileContent](または TypedDict 版の [`ToolOutputFileContentDict`][agents.tool.ToolOutputFileContentDict]) +- テキスト: 文字列または文字列化可能オブジェクト、あるいは [`ToolOutputText`][agents.tool.ToolOutputText](または TypedDict 版の [`ToolOutputTextDict`][agents.tool.ToolOutputTextDict]) + ### カスタム関数ツール -Python 関数をツールとして使いたくない場合もあります。その場合は、直接 [`FunctionTool`][agents.tool.FunctionTool] を作成できます。次の提供が必要です: +Python 関数をツールとして使いたくない場合もあります。必要に応じて直接 [`FunctionTool`][agents.tool.FunctionTool] を作成できます。その場合、次を提供する必要があります: - `name` - `description` -- 引数の JSON スキーマである `params_json_schema` -- [`ToolContext`][agents.tool_context.ToolContext] と引数(JSON 文字列)を受け取り、ツールの出力を文字列で返す非同期関数 `on_invoke_tool` +- `params_json_schema`(引数の JSON スキーマ) +- `on_invoke_tool`([`ToolContext`][agents.tool_context.ToolContext] と引数の JSON 文字列を受け取り、ツールの出力を文字列で返す async 関数) ```python from typing import Any @@ -219,16 +227,16 @@ tool = FunctionTool( ### 引数と docstring の自動解析 -前述のとおり、関数シグネチャを自動解析してツールのスキーマを抽出し、docstring を解析してツールおよび個々の引数の説明を抽出します。補足事項: +前述のとおり、ツールのスキーマを抽出するために関数シグネチャを自動解析し、ツール全体および各引数の説明を抽出するために docstring を解析します。注意点は次のとおりです: -1. シグネチャ解析は `inspect` モジュール経由で行います。型アノテーションを用いて引数の型を理解し、全体スキーマを表す Pydantic モデルを動的に構築します。Python の基本型、Pydantic モデル、TypedDicts など、ほとんどの型をサポートします。 -2. docstring の解析には `griffe` を使用します。サポートする docstring 形式は `google`、`sphinx`、`numpy` です。docstring 形式は自動検出を試みますがベストエフォートのため、`function_tool` 呼び出し時に明示的に設定できます。`use_docstring_info` を `False` に設定して docstring 解析を無効化することもできます。 +1. シグネチャの解析は `inspect` モジュールで行います。型アノテーションから引数の型を把握し、全体のスキーマを表す Pydantic モデルを動的に構築します。Python の基本型、Pydantic モデル、TypedDict など、ほとんどの型をサポートします。 +2. docstring の解析には `griffe` を使用します。サポートする docstring 形式は `google`、`sphinx`、`numpy` です。docstring 形式の自動検出を試みますが、ベストエフォートのため、`function_tool` 呼び出し時に明示的に指定できます。`use_docstring_info` を `False` に設定して docstring 解析を無効にすることもできます。 スキーマ抽出のコードは [`agents.function_schema`][] にあります。 -## ツールとしてのエージェント +## ツールとしての エージェント -一部のワークフローでは、ハンドオフ せずに、中央の エージェント が専門 エージェント のネットワークをオーケストレーションしたい場合があります。これは エージェント をツールとしてモデル化することで実現できます。 +一部のワークフローでは、制御をハンドオフ するのではなく、中央の エージェント が専門 エージェント のネットワークをオーケストレーションしたい場合があります。エージェント をツールとしてモデル化することで実現できます。 ```python from agents import Agent, Runner @@ -267,9 +275,9 @@ async def main(): print(result.final_output) ``` -### ツール化エージェントのカスタマイズ +### ツール化したエージェントのカスタマイズ -`agent.as_tool` 関数は、エージェント をツールに変換しやすくするための簡便メソッドです。ただしすべての設定をサポートするわけではありません。例えば、`max_turns` は設定できません。高度なユースケースでは、ツール実装内で直接 `Runner.run` を使用してください: +`agent.as_tool` 関数は、エージェント を簡単にツールへ変換するためのユーティリティです。ただし、すべての設定をサポートしているわけではありません。たとえば `max_turns` は設定できません。高度なユースケースでは、ツール実装内で直接 `Runner.run` を使用してください: ```python @function_tool @@ -290,13 +298,13 @@ async def run_my_agent() -> str: ### カスタム出力抽出 -場合によっては、中央の エージェント に返す前にツール化した エージェント の出力を変更したいことがあります。例えば次のような場合に有用です: +場合によっては、中央の エージェント に返す前に、ツール化した エージェント の出力を加工したいことがあります。これは次のような場合に有用です: -- サブ エージェント のチャット履歴から特定の情報(例: JSON ペイロード)を抽出する。 -- エージェント の最終回答を変換または再フォーマットする(例: Markdown をプレーンテキストや CSV に変換)。 -- 出力を検証したり、エージェント の応答が欠落または不正な場合にフォールバック値を提供する。 +- サブエージェント のチャット履歴から特定の情報(例: JSON ペイロード)を抽出する。 +- エージェント の最終回答を変換・再フォーマットする(例: Markdown をプレーンテキストや CSV に変換)。 +- エージェント の応答が欠落・不正な場合に検証したりフォールバック値を提供する。 -これは `as_tool` メソッドに `custom_output_extractor` 引数を渡すことで実現できます: +これは `as_tool` メソッドに `custom_output_extractor` 引数を渡すことで行えます: ```python async def extract_json_payload(run_result: RunResult) -> str: @@ -317,7 +325,7 @@ json_tool = data_agent.as_tool( ### 条件付きツール有効化 -実行時に `is_enabled` パラメーターを使って エージェント ツールを条件付きで有効/無効にできます。これにより、コンテキスト、ユーザー の設定、実行時の条件に基づいて、LLM に提供するツールを動的にフィルタリングできます。 +実行時に `is_enabled` パラメーター を使って エージェント ツールを条件付きで有効化/無効化できます。これにより、コンテキスト、ユーザー の嗜好、実行時条件に基づいて、LLM に利用可能なツールを動的にフィルタリングできます。 ```python import asyncio @@ -372,11 +380,11 @@ async def main(): asyncio.run(main()) ``` -`is_enabled` パラメーターは次を受け付けます: +`is_enabled` パラメーター は次を受け付けます: - **Boolean 値**: `True`(常に有効)または `False`(常に無効) - **Callable 関数**: `(context, agent)` を受け取り boolean を返す関数 -- **Async 関数**: 複雑な条件ロジック向けの非同期関数 +- **Async 関数**: 複雑な条件ロジック用の async 関数 無効化されたツールは実行時に LLM から完全に隠されるため、次の用途に有用です: @@ -389,9 +397,9 @@ asyncio.run(main()) `@function_tool` で関数ツールを作成する際、`failure_error_function` を渡せます。これは、ツール呼び出しがクラッシュした場合に LLM へエラーレスポンスを提供する関数です。 -- 既定(何も渡さない場合)では、エラーが発生したことを LLM に伝える `default_tool_error_function` が実行されます。 -- 独自のエラー関数を渡した場合はそれが実行され、そのレスポンスが LLM に送信されます。 -- 明示的に `None` を渡した場合、ツール呼び出しエラーは再スローされ、あなたが処理する必要があります。モデルが不正な JSON を生成した場合は `ModelBehaviorError`、コードがクラッシュした場合は `UserError` などになり得ます。 +- 既定(何も渡さない場合)では、エラーが発生したことを LLM に知らせる `default_tool_error_function` を実行します。 +- 独自のエラー関数を渡した場合はそれが実行され、そのレスポンスが LLM に送られます。 +- 明示的に `None` を渡した場合、ツール呼び出しのエラーは再スローされ、呼び出し側で処理する必要があります。たとえば、モデルが不正な JSON を生成した場合は `ModelBehaviorError`、コードがクラッシュした場合は `UserError` などになり得ます。 ```python from agents import function_tool, RunContextWrapper @@ -414,4 +422,4 @@ def get_user_profile(user_id: str) -> str: ``` -`FunctionTool` オブジェクトを手動で作成する場合は、`on_invoke_tool` 関数内でエラーを処理する必要があります。 \ No newline at end of file +`FunctionTool` オブジェクトを手動で作成している場合は、`on_invoke_tool` 関数内でエラーを処理する必要があります。 \ No newline at end of file diff --git a/docs/ja/tracing.md b/docs/ja/tracing.md index 1f7f3bfec..71cd3a8eb 100644 --- a/docs/ja/tracing.md +++ b/docs/ja/tracing.md @@ -4,52 +4,52 @@ search: --- # トレーシング -Agents SDK には組み込みのトレーシングがあり、エージェントの実行中に発生するイベントの包括的な記録を収集します。たとえば LLM 生成、ツール呼び出し、ハンドオフ、ガードレール、さらにカスタムイベントなどです。[トレース ダッシュボード](https://platform.openai.com/traces)を使用すると、開発時や本番環境でワークフローのデバッグ、可視化、監視ができます。 +Agents SDK には組み込みのトレーシングが含まれます。エージェントの実行中に発生するイベントの包括的な記録( LLM 生成、ツール呼び出し、ハンドオフ、ガードレール、さらにカスタム イベント)を収集します。[Traces ダッシュボード](https://platform.openai.com/traces)を使用して、開発中および本番環境でワークフローをデバッグ、可視化、監視できます。 !!!note トレーシングはデフォルトで有効です。トレーシングを無効にする方法は 2 つあります。 1. 環境変数 `OPENAI_AGENTS_DISABLE_TRACING=1` を設定して、トレーシングをグローバルに無効化できます - 2. 1 回の実行のみ無効化するには、[`agents.run.RunConfig.tracing_disabled`][] を `True` に設定します + 2. [`agents.run.RunConfig.tracing_disabled`][] を `True` に設定して、単一の実行でトレーシングを無効化できます -***OpenAI の API を使用する Zero Data Retention (ZDR) ポリシー下で運用する組織では、トレーシングは利用できません。*** +***OpenAI の API を使用し Zero Data Retention (ZDR) ポリシーで運用している組織は、トレーシングを利用できません。*** ## トレースとスパン -- **トレース** は「ワークフロー」の単一のエンドツーエンド処理を表します。スパンで構成されます。トレースには次のプロパティがあります。 +- **トレース** は「ワークフロー」の単一のエンドツーエンド操作を表します。スパンで構成されます。トレースには次のプロパティがあります。 - `workflow_name`: 論理的なワークフローまたはアプリです。例: "Code generation" や "Customer service"。 - - `trace_id`: トレースの一意の ID。指定しない場合は自動生成されます。形式は `trace_<32_alphanumeric>` である必要があります。 - - `group_id`: 省略可能なグループ ID。同一の会話からの複数のトレースをリンクするために使用します。たとえばチャットスレッド ID を使用できます。 - - `disabled`: True の場合、このトレースは記録されません。 - - `metadata`: トレースのための任意のメタデータ。 -- **スパン** は開始時刻と終了時刻を持つ処理を表します。スパンには次の情報があります。 - - `started_at` および `ended_at` タイムスタンプ。 - - `trace_id`: 所属するトレースを表します - - `parent_id`: このスパンの親スパン (存在する場合) を指します - - `span_data`: スパンに関する情報。たとえば、`AgentSpanData` はエージェントに関する情報、`GenerationSpanData` は LLM 生成に関する情報などです。 + - `trace_id`: トレースの一意の ID。渡さない場合は自動生成されます。形式は `trace_<32_alphanumeric>` である必要があります。 + - `group_id`: 同一の会話からの複数のトレースをリンクするための任意のグループ ID。たとえばチャットスレッド ID を使用できます。 + - `disabled`: True の場合、トレースは記録されません。 + - `metadata`: トレースの任意のメタデータ。 +- **スパン** は開始時刻と終了時刻のある操作を表します。スパンには次があります。 + - `started_at` と `ended_at` のタイムスタンプ + - それが属するトレースを表す `trace_id` + - このスパンの親スパン(ある場合)を指す `parent_id` + - スパンに関する情報である `span_data`。たとえば、`AgentSpanData` はエージェントに関する情報を、`GenerationSpanData` は LLM 生成に関する情報などを含みます。 -## デフォルトのトレーシング +## 既定のトレーシング -デフォルトでは、SDK は次をトレースします。 +デフォルトで、 SDK は次をトレースします。 -- 全体の `Runner.{run, run_sync, run_streamed}()` が `trace()` でラップされます。 +- 全体の `Runner.{run, run_sync, run_streamed}()` は `trace()` でラップされます。 - エージェントが実行されるたびに、`agent_span()` でラップされます - LLM 生成は `generation_span()` でラップされます - 関数ツールの呼び出しはそれぞれ `function_span()` でラップされます - ガードレールは `guardrail_span()` でラップされます - ハンドオフは `handoff_span()` でラップされます -- 音声入力 (音声→テキスト) は `transcription_span()` でラップされます -- 音声出力 (テキスト→音声) は `speech_span()` でラップされます -- 関連する音声スパンは `speech_group_span()` の下に親子関係で配置される場合があります +- 音声入力(speech-to-text)は `transcription_span()` でラップされます +- 音声出力(text-to-speech)は `speech_span()` でラップされます +- 関連する音声スパンは `speech_group_span()` の下に親付けされる場合があります デフォルトでは、トレース名は "Agent workflow" です。`trace` を使用する場合はこの名前を設定できますし、[`RunConfig`][agents.run.RunConfig] で名前やその他のプロパティを構成することもできます。 -さらに、[カスタム トレース プロセッサー](#custom-tracing-processors) を設定して、トレースを別の宛先に送信できます (置き換え、または第 2 の宛先として)。 +さらに、[カスタム トレース プロセッサー](#custom-tracing-processors)を設定して、トレースを他の宛先に送信できます(置き換え、またはセカンダリ宛先として)。 -## 高レベルのトレース +## 上位レベルのトレース -`run()` を複数回呼び出す場合、それらを 1 つのトレースにまとめたいことがあります。その場合は、コード全体を `trace()` でラップします。 +`run()` への複数回の呼び出しを 1 つのトレースにまとめたい場合があります。その場合は、コード全体を `trace()` でラップします。 ```python from agents import Agent, Runner, trace @@ -70,40 +70,41 @@ async def main(): [`trace()`][agents.tracing.trace] 関数を使用してトレースを作成できます。トレースは開始と終了が必要です。方法は 2 つあります。 -1. 【推奨】トレースをコンテキストマネージャとして使用します。すなわち `with trace(...) as my_trace`。これにより適切なタイミングでトレースが自動的に開始・終了します。 +1. 【推奨】コンテキストマネージャーとして使用します。つまり `with trace(...) as my_trace`。これにより、適切なタイミングでトレースが自動的に開始・終了します。 2. [`trace.start()`][agents.tracing.Trace.start] と [`trace.finish()`][agents.tracing.Trace.finish] を手動で呼び出すこともできます。 -現在のトレースは Python の [`contextvar`](https://docs.python.org/3/library/contextvars.html) を通じて追跡されます。これは自動的に並行処理で機能することを意味します。トレースを手動で開始/終了する場合は、現在のトレースを更新するために `start()`/`finish()` に `mark_as_current` と `reset_current` を渡す必要があります。 +現在のトレースは Python の [`contextvar`](https://docs.python.org/3/library/contextvars.html) によって追跡されます。つまり、自動的に並行処理で機能します。トレースを手動で開始/終了する場合、現在のトレースを更新するために `start()`/`finish()` に `mark_as_current` と `reset_current` を渡す必要があります。 ## スパンの作成 -さまざまな [`*_span()`][agents.tracing.create] メソッドを使用してスパンを作成できます。一般には、スパンを手動で作成する必要はありません。カスタムのスパン情報を追跡するために [`custom_span()`][agents.tracing.custom_span] 関数を利用できます。 +さまざまな [`*_span()`][agents.tracing.create] メソッドを使用してスパンを作成できます。一般的に、スパンを手動で作成する必要はありません。カスタム スパン情報を追跡するための [`custom_span()`][agents.tracing.custom_span] 関数が利用できます。 -スパンは自動的に現在のトレースの一部になり、Python の [`contextvar`](https://docs.python.org/3/library/contextvars.html) で追跡される最も近い現在のスパンの下にネストされます。 +スパンは自動的に現在のトレースの一部となり、Python の [`contextvar`](https://docs.python.org/3/library/contextvars.html) によって追跡される、最も近い現在のスパンの下にネストされます。 -## 機微なデータ +## 機微データ 一部のスパンは機微なデータを取得する可能性があります。 -`generation_span()` は LLM 生成の入力/出力を保存し、`function_span()` は関数呼び出しの入力/出力を保存します。これらには機微なデータが含まれる可能性があるため、[`RunConfig.trace_include_sensitive_data`][agents.run.RunConfig.trace_include_sensitive_data] によってそのデータの取得を無効化できます。 +`generation_span()` は LLM 生成の入力/出力を、`function_span()` は関数呼び出しの入力/出力を保存します。機微なデータが含まれる可能性があるため、[`RunConfig.trace_include_sensitive_data`][agents.run.RunConfig.trace_include_sensitive_data] によってそのデータの取得を無効化できます。 -同様に、音声スパンにはデフォルトで入力および出力音声の base64 エンコード PCM データが含まれます。この音声データの取得は、[`VoicePipelineConfig.trace_include_sensitive_audio_data`][agents.voice.pipeline_config.VoicePipelineConfig.trace_include_sensitive_audio_data] を設定することで無効化できます。 +同様に、音声スパンにはデフォルトで入力および出力音声の base64 エンコードの PCM データが含まれます。[`VoicePipelineConfig.trace_include_sensitive_audio_data`][agents.voice.pipeline_config.VoicePipelineConfig.trace_include_sensitive_audio_data] を構成して、この音声データの取得を無効化できます。 ## カスタム トレーシング プロセッサー -トレーシングのハイレベルなアーキテクチャは次のとおりです。 +トレーシングの高レベルのアーキテクチャは次のとおりです。 -- 初期化時に、トレースの作成を担当するグローバルな [`TraceProvider`][agents.tracing.setup.TraceProvider] を作成します。 -- `TraceProvider` に [`BatchTraceProcessor`][agents.tracing.processors.BatchTraceProcessor] を構成し、これがトレース/スパンをバッチで [`BackendSpanExporter`][agents.tracing.processors.BackendSpanExporter] に送信します。エクスポーターはスパンとトレースを OpenAI のバックエンドへバッチでエクスポートします。 +- 初期化時に、トレースを作成する責任を持つグローバルな [`TraceProvider`][agents.tracing.setup.TraceProvider] を作成します。 +- `TraceProvider` を [`BatchTraceProcessor`][agents.tracing.processors.BatchTraceProcessor] で構成します。これはトレース/スパンをバッチで [`BackendSpanExporter`][agents.tracing.processors.BackendSpanExporter] に送信し、スパンとトレースを OpenAI バックエンドにバッチでエクスポートします。 -このデフォルト構成をカスタマイズし、別のバックエンドへの送信や追加のバックエンドへの送信、エクスポーターの動作変更を行うには、次の 2 つの方法があります。 +このデフォルト設定をカスタマイズして、別のバックエンドに送信したり、追加のバックエンドに送信したり、エクスポーターの動作を変更するには、次の 2 つの方法があります。 -1. [`add_trace_processor()`][agents.tracing.add_trace_processor] を使用すると、トレースやスパンが準備でき次第受け取る、**追加の** トレース プロセッサーを追加できます。これにより、OpenAI のバックエンドへの送信に加えて独自の処理を行えます。 -2. [`set_trace_processors()`][agents.tracing.set_trace_processors] を使用すると、デフォルトのプロセッサーを独自のトレース プロセッサーに**置き換え**られます。つまり、OpenAI のバックエンドに送信する `TracingProcessor` を含めない限り、トレースは OpenAI のバックエンドに送信されません。 +1. [`add_trace_processor()`][agents.tracing.add_trace_processor] は、トレースやスパンが準備できたときに受け取る「追加の」トレース プロセッサーを追加できます。これにより、トレースを OpenAI のバックエンドに送信するのに加えて、独自の処理を行えます。 +2. [`set_trace_processors()`][agents.tracing.set_trace_processors] は、デフォルトのプロセッサーを独自のトレース プロセッサーに「置き換える」ことができます。つまり、OpenAI バックエンドにトレースを送信する `TracingProcessor` を含めない限り、トレースは OpenAI バックエンドに送信されません。 -## OpenAI 以外のモデルでのトレーシング -OpenAI の API キーを OpenAI 以外のモデルと併用して、トレーシングを無効化することなく OpenAI Traces ダッシュボードで無料のトレーシングを有効にできます。 +## 非 OpenAI モデルでのトレーシング + +OpenAI の API キーを非 OpenAI モデルで使用して、トレーシングを無効にすることなく、OpenAI Traces ダッシュボードで無料のトレーシングを有効にできます。 ```python import os @@ -124,8 +125,9 @@ agent = Agent( ) ``` -## 注意 -- OpenAI Traces ダッシュボードで無料のトレースを表示できます。 +## 注意事項 +- 無料のトレースは OpenAI Traces ダッシュボードで確認できます。 + ## 外部トレーシング プロセッサー一覧 diff --git a/docs/ja/usage.md b/docs/ja/usage.md index ba53f6dcc..3f5860be3 100644 --- a/docs/ja/usage.md +++ b/docs/ja/usage.md @@ -4,21 +4,21 @@ search: --- # 使用状況 -Agents SDK は、各実行ごとにトークン使用状況を自動で追跡します。実行コンテキストから参照でき、コストの監視、制限の適用、分析の記録に利用できます。 +Agents SDK は、各ランでのトークン使用状況を自動的に追跡します。ランのコンテキストからアクセスでき、コストの監視、制限の適用、分析の記録に利用できます。 ## 追跡対象 -- **requests**: 生成系 LLM API 呼び出し回数 -- **input_tokens**: 送信した入力トークンの合計 +- **requests**: 実行された LLM API 呼び出し数 +- **input_tokens**: 送信された入力トークンの合計 - **output_tokens**: 受信した出力トークンの合計 - **total_tokens**: input + output - **details**: - `input_tokens_details.cached_tokens` - `output_tokens_details.reasoning_tokens` -## 実行からの使用状況の取得 +## ランからの使用状況へのアクセス -`Runner.run(...)` の後は、`result.context_wrapper.usage` から使用状況にアクセスします。 +`Runner.run(...)` の後、`result.context_wrapper.usage` から使用状況にアクセスします。 ```python result = await Runner.run(agent, "What's the weather in Tokyo?") @@ -30,11 +30,11 @@ print("Output tokens:", usage.output_tokens) print("Total tokens:", usage.total_tokens) ``` -使用状況は、実行中のすべてのモデル呼び出し(ツール呼び出しや ハンドオフ を含む)にわたって集計されます。 +使用状況はラン中のすべてのモデル呼び出し(ツール呼び出しやハンドオフを含む)で集計されます。 ### LiteLLM モデルでの使用状況の有効化 -LiteLLM プロバイダーは、デフォルトでは使用状況メトリクスを報告しません。[`LitellmModel`](models/litellm.md) を使用する場合は、エージェントに `ModelSettings(include_usage=True)` を渡して、LiteLLM のレスポンスが `result.context_wrapper.usage` に反映されるようにします。 +LiteLLM プロバイダーは、デフォルトでは使用状況メトリクスを報告しません。[`LitellmModel`](models/litellm.md) を使用する場合は、エージェントに `ModelSettings(include_usage=True)` を渡すことで、LiteLLM のレスポンスが `result.context_wrapper.usage` に反映されます。 ```python from agents import Agent, ModelSettings, Runner @@ -50,9 +50,9 @@ result = await Runner.run(agent, "What's the weather in Tokyo?") print(result.context_wrapper.usage.total_tokens) ``` -## セッションでの使用状況の取得 +## セッションでの使用状況へのアクセス -`Session`(例: `SQLiteSession`)を使用する場合、`Runner.run(...)` の各呼び出しは、その実行に固有の使用状況を返します。セッションはコンテキスト用の会話履歴を保持しますが、各実行の使用状況は独立しています。 +`Session`(例: `SQLiteSession`)を使用する場合、`Runner.run(...)` の各呼び出しは、その特定のランの使用状況を返します。セッションはコンテキスト用に会話履歴を保持しますが、各ランの使用状況は独立しています。 ```python session = SQLiteSession("my_conversation") @@ -64,11 +64,11 @@ second = await Runner.run(agent, "Can you elaborate?", session=session) print(second.context_wrapper.usage.total_tokens) # Usage for second run ``` -セッションは実行間で会話コンテキストを保持しますが、各 `Runner.run()` 呼び出しで返される使用状況メトリクスは、その実行のみを表します。セッションでは、以前のメッセージが各実行の入力として再投入されることがあり、その結果、以降のターンで入力トークン数に影響します。 +セッションはラン間で会話コンテキストを保持しますが、各 `Runner.run()` 呼び出しで返される使用状況メトリクスは、その実行に限られます。セッションでは、前のメッセージが各ランの入力として再投入されることがあり、その場合は後続ターンの入力トークン数に影響します。 ## フックでの使用状況の利用 -`RunHooks` を使用している場合、各フックに渡される `context` オブジェクトには `usage` が含まれます。これにより、重要なライフサイクル時点で使用状況を記録できます。 +`RunHooks` を使用している場合、各フックに渡される `context` オブジェクトには `usage` が含まれます。これにより、重要なライフサイクルのタイミングで使用状況を記録できます。 ```python class MyHooks(RunHooks): @@ -79,8 +79,8 @@ class MyHooks(RunHooks): ## API リファレンス -詳細な API ドキュメントは以下を参照してください。 +詳細な API ドキュメントは次を参照してください: - [`Usage`][agents.usage.Usage] - 使用状況の追跡データ構造 -- [`RunContextWrapper`][agents.run.RunContextWrapper] - 実行コンテキストから使用状況にアクセス -- [`RunHooks`][agents.run.RunHooks] - 使用状況トラッキングのライフサイクルにフック \ No newline at end of file +- [`RunContextWrapper`][agents.run.RunContextWrapper] - ランのコンテキストから使用状況にアクセス +- [`RunHooks`][agents.run.RunHooks] - 使用状況トラッキングのライフサイクルにフックする \ No newline at end of file diff --git a/docs/ja/visualization.md b/docs/ja/visualization.md index 1b4fb1197..dde5d9255 100644 --- a/docs/ja/visualization.md +++ b/docs/ja/visualization.md @@ -4,11 +4,11 @@ search: --- # エージェントの可視化 -エージェントの可視化では、 **Graphviz** を使用して、エージェントとその関係を構造化されたグラフィカル表現として生成できます。これは、アプリケーション内でエージェント、ツール、ハンドオフがどのように相互作用するかを理解するのに役立ちます。 +エージェントの可視化では、 **Graphviz** を用いてエージェントとその関係を表す構造化されたグラフィカル表現を生成できます。これは、アプリケーション内でエージェント、ツール、ハンドオフがどのように相互作用するかを理解するのに役立ちます。 ## インストール -オプションの `viz` 依存関係グループをインストールします: +オプションの `viz` 依存グループをインストールします: ```bash pip install "openai-agents[viz]" @@ -67,38 +67,39 @@ triage_agent = Agent( draw_graph(triage_agent) ``` -![Agent Graph](../assets/images/graph.png) +![エージェント グラフ](../assets/images/graph.png) -これは、 **トリアージ エージェント** と、そのサブエージェントやツールへの接続の構造を視覚的に表すグラフを生成します。 +これは、 **トリアージ エージェント** と、そのサブエージェントやツールとの接続を視覚的に表すグラフを生成します。 ## 可視化の理解 生成されるグラフには次が含まれます: -- エントリーポイントを示す **開始ノード**(`__start__`)。 -- 黄色で塗りつぶされた **長方形** で表されるエージェント。 -- 緑色で塗りつぶされた **楕円** で表されるツール。 -- 灰色で塗りつぶされた **長方形** で表される MCP サーバー。 +- エントリーポイントを示す **開始ノード** (`__start__`)。 +- 黄色で塗りつぶされた長方形で表されるエージェント。 +- 緑で塗りつぶされた楕円で表されるツール。 +- 灰色で塗りつぶされた長方形で表される MCP サーバー。 - 相互作用を示す有向エッジ: - - エージェント間のハンドオフは **実線の矢印**。 - - ツール呼び出しは **点線の矢印**。 - - MCP サーバー呼び出しは **破線の矢印**。 -- 実行が終了する場所を示す **終了ノード**(`__end__`)。 + - エージェント間のハンドオフには **実線の矢印**。 + - ツール呼び出しには **点線の矢印**。 + - MCP サーバー呼び出しには **破線の矢印**。 +- 実行の終了地点を示す **終了ノード** (`__end__`)。 - **注意:** MCP サーバーは最近の `agents` パッケージのバージョンで描画されます( **v0.2.8** で確認済み)。可視化に MCP ボックスが表示されない場合は、最新リリースにアップグレードしてください。 +**注意:** MCP サーバーは、最近のバージョンの +`agents` パッケージ( **v0.2.8** で確認済み)でレンダリングされます。可視化に MCP のボックスが表示されない場合は、最新リリースにアップグレードしてください。 ## グラフのカスタマイズ ### グラフの表示 -デフォルトでは、`draw_graph` はグラフをインライン表示します。グラフを別ウィンドウで表示するには、次のように記述します: +既定では、`draw_graph` はグラフをインラインで表示します。別ウィンドウで表示するには、次のようにします: ```python draw_graph(triage_agent).view() ``` ### グラフの保存 -デフォルトでは、`draw_graph` はグラフをインライン表示します。ファイルとして保存するには、ファイル名を指定します: +既定では、`draw_graph` はグラフをインラインで表示します。ファイルとして保存するには、ファイル名を指定します: ```python draw_graph(triage_agent, filename="agent_graph") diff --git a/docs/ja/voice/pipeline.md b/docs/ja/voice/pipeline.md index d80d7b61d..463e72618 100644 --- a/docs/ja/voice/pipeline.md +++ b/docs/ja/voice/pipeline.md @@ -4,7 +4,7 @@ search: --- # パイプラインとワークフロー -[`agents.voice.pipeline.VoicePipeline`](agents.voice.pipeline.VoicePipeline) は、エージェント型のワークフローを音声アプリに変換しやすくするクラスです。実行するワークフローを渡すと、パイプラインが入力音声の文字起こし、音声の終了検出、適切なタイミングでのワークフロー呼び出し、そしてワークフロー出力を音声に戻す処理までを引き受けます。 +[`VoicePipeline`][agents.voice.pipeline.VoicePipeline] は、エージェント のワークフローを音声アプリに簡単に変換できるクラスです。実行したいワークフローを渡すと、パイプラインが入力音声の文字起こし、音声の終了検出、適切なタイミングでのワークフロー呼び出し、そしてワークフロー出力の音声への変換までを処理します。 ```mermaid graph LR @@ -32,31 +32,31 @@ graph LR ``` -## パイプラインの設定 +## パイプラインの構成 -パイプラインを作成するとき、次の項目を設定できます。 +パイプラインを作成するとき、次の設定ができます。 -1. [`agents.voice.workflow.VoiceWorkflowBase`](agents.voice.workflow.VoiceWorkflowBase) の `workflow`。新しい音声が文字起こしされるたびに実行されるコードです。 -2. 使用する [`agents.voice.model.STTModel`](agents.voice.model.STTModel)(speech-to-text)と [`agents.voice.model.TTSModel`](agents.voice.model.TTSModel)(text-to-speech)のモデル -3. [`agents.voice.pipeline_config.VoicePipelineConfig`](agents.voice.pipeline_config.VoicePipelineConfig) の `config`。次のような設定ができます: - - モデルプロバイダー(モデル名をモデルへマッピングできます) - - トレーシング(無効化の可否、音声ファイルのアップロード可否、ワークフロー名、トレース ID など) - - TTS と STT のモデル設定(プロンプト、言語、使用するデータ型など) +1. 毎回新しい音声が文字起こしされるたびに実行されるコードである [`workflow`][agents.voice.workflow.VoiceWorkflowBase] +2. 使用する [`speech-to-text`][agents.voice.model.STTModel] および [`text-to-speech`][agents.voice.model.TTSModel] のモデル +3. 次のような項目を構成できる [`config`][agents.voice.pipeline_config.VoicePipelineConfig] + - モデル名をモデルに対応付けできるモデルプロバイダー + - トレーシング(トレーシングの無効化、音声ファイルのアップロード可否、ワークフロー名、トレース ID など) + - プロンプト、言語、使用するデータ型など TTS と STT モデルの設定 ## パイプラインの実行 -パイプラインは [`agents.voice.pipeline.VoicePipeline.run`](agents.voice.pipeline.VoicePipeline.run) の `run()` メソッドで実行できます。音声入力は次の 2 つの形式で渡せます。 +パイプラインは [`run()`][agents.voice.pipeline.VoicePipeline.run] メソッドで実行でき、音声入力を次の 2 つの形式で渡せます。 -1. [`agents.voice.input.AudioInput`](agents.voice.input.AudioInput) は、完全な音声を書き起こしたテキストがあり、その結果だけを生成したい場合に使います。話者が話し終えるタイミングを検出する必要がないケース、例えばあらかじめ録音された音声や、ユーザーが話し終えるタイミングが明確なプッシュ・トゥ・トークのアプリで有用です。 -2. [`agents.voice.input.StreamedAudioInput`](agents.voice.input.StreamedAudioInput) は、ユーザーが話し終えたタイミングを検出する必要がある場合に使います。検出された音声チャンクをプッシュでき、音声パイプラインは「アクティビティ検出」によって適切なタイミングで自動的にエージェントのワークフローを実行します。 +1. [`AudioInput`][agents.voice.input.AudioInput] は完全な音声トランスクリプトがある場合に使用し、その結果を生成するだけでよいときに使います。これは、話者の発話終了を検出する必要がないケース、たとえば録音済み音声や、 ユーザー の発話終了が明確なプッシュ・トゥ・トークのアプリで有用です。 +2. [`StreamedAudioInput`][agents.voice.input.StreamedAudioInput] は、 ユーザー の発話終了を検出する必要がある場合に使用します。検出された音声チャンクを順次プッシュでき、ボイスパイプラインは「activity detection(アクティビティ検出)」と呼ばれるプロセスを通じて適切なタイミングでエージェント のワークフローを自動実行します。 -## 実行結果 +## 結果 -音声パイプライン実行の結果は [`agents.voice.result.StreamedAudioResult`](agents.voice.result.StreamedAudioResult) です。これは、発生するイベントを逐次ストリーミングできるオブジェクトです。いくつかの種類の [`agents.voice.events.VoiceStreamEvent`](agents.voice.events.VoiceStreamEvent) があります。 +ボイスパイプライン実行の結果は [`StreamedAudioResult`][agents.voice.result.StreamedAudioResult] です。これは、発生するイベントを逐次 ストリーミング できるオブジェクトです。いくつかの種類の [`VoiceStreamEvent`][agents.voice.events.VoiceStreamEvent] があり、次が含まれます。 -1. [`agents.voice.events.VoiceStreamEventAudio`](agents.voice.events.VoiceStreamEventAudio): 音声チャンクを含みます。 -2. [`agents.voice.events.VoiceStreamEventLifecycle`](agents.voice.events.VoiceStreamEventLifecycle): ターンの開始・終了などのライフサイクルイベントを通知します。 -3. [`agents.voice.events.VoiceStreamEventError`](agents.voice.events.VoiceStreamEventError): エラーイベントです。 +1. 音声チャンクを含む [`VoiceStreamEventAudio`][agents.voice.events.VoiceStreamEventAudio] +2. ターンの開始・終了などのライフサイクルイベントを知らせる [`VoiceStreamEventLifecycle`][agents.voice.events.VoiceStreamEventLifecycle] +3. エラーイベントである [`VoiceStreamEventError`][agents.voice.events.VoiceStreamEventError] ```python @@ -76,4 +76,4 @@ async for event in result.stream(): ### 割り込み -Agents SDK は現在、[`agents.voice.input.StreamedAudioInput`](agents.voice.input.StreamedAudioInput) に対する割り込みの組み込みサポートを提供していません。代わりに、検出された各ターンごとに、ワークフローの個別の実行がトリガーされます。アプリケーション内で割り込みを扱いたい場合は、[`agents.voice.events.VoiceStreamEventLifecycle`](agents.voice.events.VoiceStreamEventLifecycle) のイベントを監視してください。`turn_started` は新しいターンが文字起こしされ処理が開始されたことを示し、`turn_ended` は該当ターンのすべての音声が配信された後に発火します。これらのイベントを利用して、モデルがターンを開始したときに話者のマイクをミュートし、そのターンに関連する音声をすべてフラッシュした後にアンミュートすることができます。 \ No newline at end of file +Agents SDK は現時点では [`StreamedAudioInput`][agents.voice.input.StreamedAudioInput] に対する組み込みの割り込みサポートを提供していません。代わりに、検出された各ターンごとにワークフローの個別の実行をトリガーします。アプリケーション内で割り込みを扱いたい場合は、[`VoiceStreamEventLifecycle`][agents.voice.events.VoiceStreamEventLifecycle] イベントを購読してください。`turn_started` は新しいターンが文字起こしされ処理が始まったことを示します。`turn_ended` は該当ターンのすべての音声が送出された後に発火します。これらのイベントを使って、モデルがターンを開始したときに話者のマイクをミュートし、ターンに関連する音声をすべてフラッシュした後にミュートを解除するといった制御ができます。 \ No newline at end of file diff --git a/docs/ja/voice/quickstart.md b/docs/ja/voice/quickstart.md index ea9860373..a670c231b 100644 --- a/docs/ja/voice/quickstart.md +++ b/docs/ja/voice/quickstart.md @@ -6,7 +6,7 @@ search: ## 前提条件 -Agents SDK の基本的な[クイックスタート手順](../quickstart.md)に従い、仮想環境をセットアップしてください。次に、SDK から音声関連のオプション依存関係をインストールします: +Agents SDK の基本的な[クイックスタート手順](../quickstart.md)に従い、仮想環境をセットアップしてください。次に、SDK から音声用のオプション依存関係をインストールします。 ```bash pip install 'openai-agents[voice]' @@ -14,11 +14,11 @@ pip install 'openai-agents[voice]' ## 概念 -理解すべき主な概念は [`VoicePipeline`][agents.voice.pipeline.VoicePipeline] で、3 段階のプロセスです: +主な概念は [`VoicePipeline`][agents.voice.pipeline.VoicePipeline] です。これは 3 段階のプロセスです。 -1. 音声をテキストに変換する音声認識モデルを実行します。 -2. 通常はエージェント的なワークフローであるコードを実行して、結果を生成します。 -3. 結果のテキストを音声に戻す音声合成モデルを実行します。 +1. 音声認識モデルを実行して、音声をテキストに変換します。 +2. 通常はエージェントのワークフローであるあなたのコードを実行して、結果を生成します。 +3. 音声合成モデルを実行して、結果のテキストを音声に戻します。 ```mermaid graph LR @@ -48,7 +48,7 @@ graph LR ## エージェント -まず、いくつかのエージェントを設定します。これは、この SDK でエージェントを作成したことがあれば馴染みがあるはずです。ここでは 2 つのエージェント、ハンドオフ、そしてツールを用意します。 +まず、いくつかの エージェント をセットアップします。これは、この SDK で エージェント を作成したことがあれば馴染みがあるはずです。ここでは、2 つの エージェント、ハンドオフ、ツール を用意します。 ```python import asyncio @@ -92,7 +92,7 @@ agent = Agent( ## 音声パイプライン -ワークフローとして [`SingleAgentVoiceWorkflow`][agents.voice.workflow.SingleAgentVoiceWorkflow] を使い、シンプルな音声パイプラインを設定します。 +ワークフローとして [`SingleAgentVoiceWorkflow`][agents.voice.workflow.SingleAgentVoiceWorkflow] を使い、シンプルな音声パイプラインを構築します。 ```python from agents.voice import SingleAgentVoiceWorkflow, VoicePipeline @@ -124,7 +124,7 @@ async for event in result.stream(): ``` -## まとめて実行 +## すべてを組み合わせる ```python import asyncio @@ -195,4 +195,4 @@ if __name__ == "__main__": asyncio.run(main()) ``` -このサンプルを実行すると、エージェントがあなたに話しかけます!自分でエージェントに話しかけられるデモは、[examples/voice/static](https://github.com/openai/openai-agents-python/tree/main/examples/voice/static) の例をチェックしてください。 \ No newline at end of file +このサンプルを実行すると、エージェントがあなたに話しかけます。自分でエージェントに話しかけられるデモは、[examples/voice/static](https://github.com/openai/openai-agents-python/tree/main/examples/voice/static) のサンプルをご覧ください。 \ No newline at end of file diff --git a/docs/ja/voice/tracing.md b/docs/ja/voice/tracing.md index bf9c419be..e287c5ede 100644 --- a/docs/ja/voice/tracing.md +++ b/docs/ja/voice/tracing.md @@ -4,15 +4,15 @@ search: --- # トレーシング -[エージェントのトレーシング](../tracing.md) と同様に、音声パイプラインも自動的にトレースされます。 +[エージェントのトレーシング](../tracing.md)と同様に、音声パイプラインも自動的にトレーシングされます。 -基本的なトレーシング情報は上記ドキュメントをご参照ください。さらに、[`VoicePipelineConfig`][agents.voice.pipeline_config.VoicePipelineConfig] を使ってパイプラインのトレーシングを設定できます。 +基本的なトレーシング情報については上記ドキュメントを参照してください。さらに、[`VoicePipelineConfig`][agents.voice.pipeline_config.VoicePipelineConfig] を使用してパイプラインのトレーシングを構成できます。 -トレーシング関連の主なフィールドは次のとおりです。 +主要なトレーシング関連フィールドは次のとおりです。 -- [`tracing_disabled`][agents.voice.pipeline_config.VoicePipelineConfig.tracing_disabled]: トレーシングを無効にするかどうかを制御します。既定ではトレーシングは有効です。 -- [`trace_include_sensitive_data`][agents.voice.pipeline_config.VoicePipelineConfig.trace_include_sensitive_data]: 音声書き起こしなど、機微なデータをトレースに含めるかどうかを制御します。これは音声パイプライン専用で、あなたの Workflow 内部で行われる処理には適用されません。 +- [`tracing_disabled`][agents.voice.pipeline_config.VoicePipelineConfig.tracing_disabled]: トレーシングを無効にするかどうかを制御します。デフォルトではトレーシングは有効です。 +- [`trace_include_sensitive_data`][agents.voice.pipeline_config.VoicePipelineConfig.trace_include_sensitive_data]: 音声書き起こしなど、機微なデータをトレースに含めるかどうかを制御します。これは音声パイプラインに特有であり、ワークフロー内で行われる処理には適用されません。 - [`trace_include_sensitive_audio_data`][agents.voice.pipeline_config.VoicePipelineConfig.trace_include_sensitive_audio_data]: 音声データをトレースに含めるかどうかを制御します。 -- [`workflow_name`][agents.voice.pipeline_config.VoicePipelineConfig.workflow_name]: トレースのワークフロー名です。 -- [`group_id`][agents.voice.pipeline_config.VoicePipelineConfig.group_id]: 複数のトレースを関連付けられる `group_id` です。 -- [`trace_metadata`][agents.voice.pipeline_config.VoicePipelineConfig.tracing_disabled]: トレースに含める追加のメタデータです。 \ No newline at end of file +- [`workflow_name`][agents.voice.pipeline_config.VoicePipelineConfig.workflow_name]: トレースのワークフロー名。 +- [`group_id`][agents.voice.pipeline_config.VoicePipelineConfig.group_id]: トレースの `group_id`。複数のトレースを関連付けることができます。 +- [`trace_metadata`][agents.voice.pipeline_config.VoicePipelineConfig.tracing_disabled]: トレースに含める追加のメタデータ。 \ No newline at end of file diff --git a/docs/ko/agents.md b/docs/ko/agents.md index f570f4fa8..22d32c034 100644 --- a/docs/ko/agents.md +++ b/docs/ko/agents.md @@ -4,16 +4,16 @@ search: --- # 에이전트 -에이전트는 앱의 핵심 빌딩 블록입니다. 에이전트는 instructions와 tools로 구성된 대규모 언어 모델(LLM)입니다. +에이전트는 앱의 핵심 기본 구성 요소입니다. 에이전트는 instructions 및 tools 로 구성된 대규모 언어 모델(LLM)입니다. ## 기본 구성 -에이전트에서 가장 일반적으로 구성하는 속성은 다음과 같습니다: +에이전트에서 가장 자주 구성하는 속성은 다음과 같습니다: - `name`: 에이전트를 식별하는 필수 문자열 -- `instructions`: developer message 또는 시스템 프롬프트라고도 함 -- `model`: 사용할 LLM과, temperature, top_p 등 모델 튜닝 매개변수를 설정하는 선택적 `model_settings` -- `tools`: 에이전트가 작업을 수행하는 데 사용할 수 있는 도구 +- `instructions`: 개발자 메시지 또는 시스템 프롬프트라고도 함 +- `model`: 사용할 LLM 과 temperature, top_p 등 모델 튜닝 매개변수를 설정하는 선택적 `model_settings` +- `tools`: 에이전트가 작업을 수행하기 위해 사용할 수 있는 도구 ```python from agents import Agent, ModelSettings, function_tool @@ -33,7 +33,7 @@ agent = Agent( ## 컨텍스트 -에이전트는 `context` 타입에 대해 제네릭합니다. 컨텍스트는 의존성 주입 도구로, 여러분이 생성해 `Runner.run()`에 전달하는 객체이며, 모든 에이전트, 도구, 핸드오프 등에게 전달되어 해당 실행에서 필요한 의존성과 상태를 담는 잡동사니 역할을 합니다. 어떤 Python 객체든 컨텍스트로 제공할 수 있습니다. +에이전트는 `context` 타입에 대해 제네릭합니다. 컨텍스트는 의존성 주입 도구로, `Runner.run()` 에 전달하는 객체이며, 모든 에이전트, 도구, 핸드오프 등에 전달되어 에이전트 실행을 위한 의존성과 상태 모음으로 사용됩니다. 컨텍스트로는 어떤 Python 객체든 제공할 수 있습니다. ```python @dataclass @@ -52,7 +52,7 @@ agent = Agent[UserContext]( ## 출력 타입 -기본적으로 에이전트는 일반 텍스트(즉, `str`) 출력을 생성합니다. 특정 타입의 출력을 에이전트가 생성하도록 하려면 `output_type` 매개변수를 사용할 수 있습니다. 일반적인 선택지는 [Pydantic](https://docs.pydantic.dev/) 객체이지만, Pydantic [TypeAdapter](https://docs.pydantic.dev/latest/api/type_adapter/)로 감쌀 수 있는 모든 타입(데이터클래스, 리스트, TypedDict 등)을 지원합니다. +기본적으로 에이전트는 일반 텍스트(즉, `str`) 출력을 생성합니다. 특정 타입의 출력을 원한다면 `output_type` 매개변수를 사용할 수 있습니다. 일반적인 선택은 [Pydantic](https://docs.pydantic.dev/) 객체를 사용하는 것이지만, Pydantic [TypeAdapter](https://docs.pydantic.dev/latest/api/type_adapter/) 로 래핑될 수 있는 모든 타입(데이터클래스, 리스트, TypedDict 등)을 지원합니다. ```python from pydantic import BaseModel @@ -73,20 +73,20 @@ agent = Agent( !!! note - `output_type`을 전달하면, 모델은 일반 텍스트 응답 대신 [structured outputs](https://platform.openai.com/docs/guides/structured-outputs)을 사용하도록 지시됩니다. + `output_type` 을 전달하면, 모델은 일반 텍스트 응답 대신 [structured outputs](https://platform.openai.com/docs/guides/structured-outputs) 을 사용하도록 지시받습니다. ## 멀티 에이전트 시스템 설계 패턴 -멀티 에이전트 시스템을 설계하는 방법은 다양하지만, 일반적으로 폭넓게 적용 가능한 두 가지 패턴이 있습니다: +멀티‑에이전트 시스템을 설계하는 방법은 다양하지만, 일반적으로 두 가지 널리 적용 가능한 패턴이 있습니다: -1. 매니저(도구로서의 에이전트): 중앙 매니저/오케스트레이터가 특화된 하위 에이전트를 도구처럼 호출하고 대화를 계속 통제함 -2. 핸드오프: 동등한 에이전트 간에 통제를 특화된 에이전트에게 넘기며, 그 에이전트가 대화를 인수함. 분산형 방식임 +1. 매니저(에이전트를 도구로): 중앙 매니저/오케스트레이터가 특화된 하위 에이전트를 도구처럼 호출하고 대화의 제어권을 유지 +2. 핸드오프: 동등한 에이전트들이 제어권을 특화된 에이전트에게 넘기고 그 에이전트가 대화를 이어받는 분산형 방식 -자세한 내용은 [에이전트 구축을 위한 실용 가이드](https://cdn.openai.com/business-guides-and-resources/a-practical-guide-to-building-agents.pdf)를 참고하세요. +자세한 내용은 [에이전트 구축 실용 가이드](https://cdn.openai.com/business-guides-and-resources/a-practical-guide-to-building-agents.pdf) 를 참고하세요. -### 매니저(도구로서의 에이전트) +### 매니저(에이전트를 도구로) -`customer_facing_agent`는 모든 사용자 상호작용을 처리하고, 도구로 노출된 특화된 하위 에이전트를 호출합니다. 자세한 내용은 [tools](tools.md#agents-as-tools) 문서를 참고하세요. +`customer_facing_agent` 가 모든 사용자 상호작용을 처리하고, 도구로 노출된 특화 하위 에이전트를 호출합니다. 자세한 내용은 [도구](tools.md#agents-as-tools) 문서를 참고하세요. ```python from agents import Agent @@ -115,7 +115,7 @@ customer_facing_agent = Agent( ### 핸드오프 -핸드오프는 에이전트가 위임할 수 있는 하위 에이전트입니다. 핸드오프가 발생하면, 위임받은 에이전트가 대화 내역을 전달받아 대화를 인수합니다. 이 패턴은 단일 작업에 뛰어난 모듈식, 특화형 에이전트를 가능하게 합니다. 자세한 내용은 [handoffs](handoffs.md) 문서를 참고하세요. +핸드오프는 에이전트가 위임할 수 있는 하위 에이전트입니다. 핸드오프가 발생하면 위임된 에이전트가 대화 기록을 받아 대화를 이어받습니다. 이 패턴은 단일 작업에 뛰어난 모듈식 특화 에이전트를 가능하게 합니다. 자세한 내용은 [핸드오프](handoffs.md) 문서를 참고하세요. ```python from agents import Agent @@ -136,7 +136,7 @@ triage_agent = Agent( ## 동적 instructions -대부분의 경우, 에이전트를 생성할 때 instructions를 제공하면 됩니다. 하지만 함수로 동적 instructions를 제공할 수도 있습니다. 이 함수는 에이전트와 컨텍스트를 입력으로 받아 프롬프트를 반환해야 합니다. 일반 함수와 `async` 함수 모두 허용됩니다. +대부분의 경우 에이전트를 생성할 때 instructions 를 제공할 수 있습니다. 하지만 함수로 동적 instructions 를 제공할 수도 있습니다. 이 함수는 에이전트와 컨텍스트를 입력받아 프롬프트를 반환해야 합니다. 일반 함수와 `async` 함수 모두 허용됩니다. ```python def dynamic_instructions( @@ -153,15 +153,15 @@ agent = Agent[UserContext]( ## 라이프사이클 이벤트(hooks) -때로는 에이전트의 라이프사이클을 관찰하고 싶을 수 있습니다. 예를 들어, 이벤트를 로깅하거나 특정 이벤트가 발생할 때 데이터를 미리 가져오고자 할 수 있습니다. `hooks` 속성으로 에이전트 라이프사이클에 훅을 걸 수 있습니다. [`AgentHooks`][agents.lifecycle.AgentHooks] 클래스를 상속하고 관심 있는 메서드를 오버라이드하세요. +가끔은 에이전트의 라이프사이클을 관찰하고 싶을 수 있습니다. 예를 들어, 이벤트를 로그로 남기거나 특정 이벤트 발생 시 데이터를 미리 가져오고 싶을 수 있습니다. `hooks` 속성으로 에이전트 라이프사이클에 훅을 추가할 수 있습니다. [`AgentHooks`][agents.lifecycle.AgentHooks] 클래스를 서브클래싱하고, 관심 있는 메서드를 오버라이드하세요. ## 가드레일 -가드레일은 에이전트 실행과 병렬로 사용자 입력에 대한 검사/검증을 수행하고, 에이전트 출력이 생성된 후에도 검사를 수행할 수 있게 합니다. 예를 들어, 사용자 입력과 에이전트 출력을 관련성 기준으로 스크리닝할 수 있습니다. 자세한 내용은 [guardrails](guardrails.md) 문서를 참고하세요. +가드레일은 에이전트 실행과 병렬로 사용자 입력에 대한 검사/검증을 수행하고, 에이전트 출력이 생성된 후에도 검사를 수행할 수 있도록 해줍니다. 예를 들어, 사용자 입력과 에이전트 출력을 관련성 기준으로 필터링할 수 있습니다. 자세한 내용은 [가드레일](guardrails.md) 문서를 참고하세요. ## 에이전트 복제/복사 -에이전트에서 `clone()` 메서드를 사용하면 에이전트를 복제하고, 원하는 속성을 선택적으로 변경할 수 있습니다. +에이전트의 `clone()` 메서드를 사용하면 에이전트를 복제하고, 원하는 속성을 선택적으로 변경할 수 있습니다. ```python pirate_agent = Agent( @@ -178,12 +178,12 @@ robot_agent = pirate_agent.clone( ## 도구 사용 강제 -도구 목록을 제공해도 LLM이 항상 도구를 사용하는 것은 아닙니다. [`ModelSettings.tool_choice`][agents.model_settings.ModelSettings.tool_choice]를 설정해 도구 사용을 강제할 수 있습니다. 유효한 값은 다음과 같습니다: +도구 목록을 제공해도 LLM 이 항상 도구를 사용하는 것은 아닙니다. [`ModelSettings.tool_choice`][agents.model_settings.ModelSettings.tool_choice] 를 설정하여 도구 사용을 강제할 수 있습니다. 유효한 값은 다음과 같습니다: -1. `auto`: LLM이 도구 사용 여부를 스스로 결정함 -2. `required`: LLM이 반드시 도구를 사용하도록 요구함(어떤 도구를 사용할지는 지능적으로 선택 가능) -3. `none`: LLM이 도구를 사용하지 않도록 요구함 -4. 특정 문자열 예: `my_tool`을 설정하면, LLM이 그 특정 도구를 사용하도록 요구함 +1. `auto`: LLM 이 도구 사용 여부를 결정 +2. `required`: LLM 이 도구를 사용해야 함(단, 어떤 도구를 사용할지는 지능적으로 결정) +3. `none`: LLM 이 도구를 _사용하지 않도록_ 요구 +4. 특정 문자열 설정(예: `my_tool`): 해당 특정 도구를 사용하도록 LLM 에 요구 ```python from agents import Agent, Runner, function_tool, ModelSettings @@ -203,10 +203,10 @@ agent = Agent( ## 도구 사용 동작 -`Agent` 구성의 `tool_use_behavior` 매개변수는 도구 출력이 처리되는 방식을 제어합니다: +`Agent` 구성의 `tool_use_behavior` 매개변수는 도구 출력 처리 방식을 제어합니다: -- `"run_llm_again"`: 기본값. 도구를 실행하고, LLM이 결과를 처리해 최종 응답을 생성함 -- `"stop_on_first_tool"`: 첫 번째 도구 호출의 출력을 추가 LLM 처리 없이 최종 응답으로 사용함 +- `"run_llm_again"`: 기본값. 도구를 실행한 뒤, LLM 이 결과를 처리하여 최종 응답을 생성 +- `"stop_on_first_tool"`: 첫 번째 도구 호출의 출력을 추가적인 LLM 처리 없이 최종 응답으로 사용 ```python from agents import Agent, Runner, function_tool, ModelSettings @@ -224,7 +224,7 @@ agent = Agent( ) ``` -- `StopAtTools(stop_at_tool_names=[...])`: 지정한 도구 중 하나가 호출되면 중지하고, 해당 도구 출력을 최종 응답으로 사용함 +- `StopAtTools(stop_at_tool_names=[...])`: 지정된 도구 중 하나가 호출되면 중지하고 해당 출력 을 최종 응답으로 사용 ```python from agents import Agent, Runner, function_tool @@ -248,7 +248,7 @@ agent = Agent( ) ``` -- `ToolsToFinalOutputFunction`: 도구 결과를 처리하고 중지할지 LLM을 계속 사용할지 결정하는 커스텀 함수 +- `ToolsToFinalOutputFunction`: 도구 결과를 처리하고 중지할지 LLM 을 계속 사용할지 결정하는 커스텀 함수 ```python from agents import Agent, Runner, function_tool, FunctionToolResult, RunContextWrapper @@ -286,4 +286,4 @@ agent = Agent( !!! note - 무한 루프를 방지하기 위해, 프레임워크는 도구 호출 후 `tool_choice`를 자동으로 "auto"로 재설정합니다. 이 동작은 [`agent.reset_tool_choice`][agents.agent.Agent.reset_tool_choice]를 통해 구성할 수 있습니다. 무한 루프는 도구 결과가 LLM으로 전달되고, `tool_choice` 때문에 LLM이 또 다른 도구 호출을 생성하는 과정이 반복되기 때문에 발생합니다. \ No newline at end of file + 무한 루프를 방지하기 위해, 프레임워크는 도구 호출 후 `tool_choice` 를 자동으로 "auto" 로 리셋합니다. 이 동작은 [`agent.reset_tool_choice`][agents.agent.Agent.reset_tool_choice] 로 구성할 수 있습니다. 무한 루프는 도구 결과가 LLM 에 전달되고, 그 결과 `tool_choice` 때문에 LLM 이 또 다른 도구 호출을 생성하는 과정을 반복하기 때문에 발생합니다. \ No newline at end of file diff --git a/docs/ko/config.md b/docs/ko/config.md index 791fff7bf..6a639fb00 100644 --- a/docs/ko/config.md +++ b/docs/ko/config.md @@ -6,7 +6,7 @@ search: ## API 키와 클라이언트 -기본적으로 SDK는 가져오자마자 LLM 요청과 트레이싱을 위해 `OPENAI_API_KEY` 환경 변수를 찾습니다. 앱이 시작되기 전에 해당 환경 변수를 설정할 수 없다면 [기본 OpenAI 키 설정][agents.set_default_openai_key] 함수를 사용해 키를 설정할 수 있습니다. +기본적으로 SDK 는 가져오자마자 LLM 요청과 트레이싱을 위해 `OPENAI_API_KEY` 환경 변수를 찾습니다. 앱이 시작되기 전에 해당 환경 변수를 설정할 수 없다면 [set_default_openai_key()][agents.set_default_openai_key] 함수를 사용해 키를 설정할 수 있습니다. ```python from agents import set_default_openai_key @@ -14,7 +14,7 @@ from agents import set_default_openai_key set_default_openai_key("sk-...") ``` -또는 사용할 OpenAI 클라이언트를 구성할 수도 있습니다. 기본적으로 SDK는 환경 변수의 API 키 또는 위에서 설정한 기본 키를 사용하여 `AsyncOpenAI` 인스턴스를 생성합니다. 이는 [기본 OpenAI 클라이언트 설정][agents.set_default_openai_client] 함수를 사용해 변경할 수 있습니다. +또는 사용할 OpenAI 클라이언트를 구성할 수도 있습니다. 기본적으로 SDK 는 환경 변수의 API 키 또는 위에서 설정한 기본 키를 사용하여 `AsyncOpenAI` 인스턴스를 생성합니다. [set_default_openai_client()][agents.set_default_openai_client] 함수를 사용해 이를 변경할 수 있습니다. ```python from openai import AsyncOpenAI @@ -24,7 +24,7 @@ custom_client = AsyncOpenAI(base_url="...", api_key="...") set_default_openai_client(custom_client) ``` -마지막으로 사용되는 OpenAI API를 커스터마이즈할 수도 있습니다. 기본적으로 우리는 OpenAI Responses API를 사용합니다. [기본 OpenAI API 설정][agents.set_default_openai_api] 함수를 사용해 Chat Completions API를 사용하도록 재정의할 수 있습니다. +마지막으로, 사용되는 OpenAI API 를 커스터마이즈할 수도 있습니다. 기본적으로 OpenAI Responses API 를 사용합니다. [set_default_openai_api()][agents.set_default_openai_api] 함수를 사용해 Chat Completions API 를 사용하도록 재정의할 수 있습니다. ```python from agents import set_default_openai_api @@ -34,7 +34,7 @@ set_default_openai_api("chat_completions") ## 트레이싱 -트레이싱은 기본적으로 활성화되어 있습니다. 기본적으로 위 섹션의 OpenAI API 키(즉, 환경 변수 또는 설정한 기본 키)를 사용합니다. 트레이싱에 사용할 API 키를 별도로 설정하려면 [`set_tracing_export_api_key`][agents.set_tracing_export_api_key] 함수를 사용하세요. +트레이싱은 기본적으로 활성화되어 있습니다. 기본적으로 위 섹션의 OpenAI API 키(즉, 환경 변수 또는 설정한 기본 키)를 사용합니다. [`set_tracing_export_api_key`][agents.set_tracing_export_api_key] 함수를 사용해 트레이싱에 사용할 API 키를 별도로 설정할 수 있습니다. ```python from agents import set_tracing_export_api_key @@ -52,7 +52,7 @@ set_tracing_disabled(True) ## 디버그 로깅 -SDK에는 핸들러가 설정되지 않은 두 개의 Python 로거가 있습니다. 기본적으로 이는 경고와 오류가 `stdout`으로 전송되고, 다른 로그는 억제됨을 의미합니다. +SDK 에는 핸들러가 설정되지 않은 두 개의 Python 로거가 있습니다. 기본적으로 이는 경고와 오류가 `stdout` 로 전송되고, 다른 로그는 억제됨을 의미합니다. 자세한 로깅을 활성화하려면 [`enable_verbose_stdout_logging()`][agents.enable_verbose_stdout_logging] 함수를 사용하세요. @@ -83,15 +83,15 @@ logger.addHandler(logging.StreamHandler()) ### 로그의 민감한 데이터 -일부 로그에는 민감한 데이터(예: 사용자 데이터)가 포함될 수 있습니다. 이러한 데이터의 로깅을 비활성화하려면 다음 환경 변수를 설정하세요. +일부 로그에는 민감한 데이터(예: 사용자 데이터)가 포함될 수 있습니다. 이러한 데이터가 로그에 포함되지 않도록 하려면 다음 환경 변수를 설정하세요. -LLM 입력과 출력을 로깅하지 않으려면: +LLM 입력과 출력을 로깅하지 않도록 비활성화하려면: ```bash export OPENAI_AGENTS_DONT_LOG_MODEL_DATA=1 ``` -도구 입력과 출력을 로깅하지 않으려면: +도구 입력과 출력을 로깅하지 않도록 비활성화하려면: ```bash export OPENAI_AGENTS_DONT_LOG_TOOL_DATA=1 diff --git a/docs/ko/context.md b/docs/ko/context.md index d9bd4e0c7..cb1c6d892 100644 --- a/docs/ko/context.md +++ b/docs/ko/context.md @@ -4,30 +4,30 @@ search: --- # 컨텍스트 관리 -컨텍스트는 과부하된 용어입니다. 고려해야 할 컨텍스트에는 두 가지 주요 범주가 있습니다: +컨텍스트는 다의어입니다. 다음 두 가지 주요 컨텍스트 범주가 있습니다: -1. 코드에서 로컬로 사용할 수 있는 컨텍스트: 이는 도구 함수 실행 시, `on_handoff` 같은 콜백 동안, 라이프사이클 훅 등에서 필요할 수 있는 데이터와 의존성입니다 -2. LLMs 에서 사용할 수 있는 컨텍스트: 이는 응답을 생성할 때 LLM 이 볼 수 있는 데이터입니다 +1. 코드에서 로컬로 사용할 수 있는 컨텍스트: 도구 함수 실행 시, `on_handoff` 같은 콜백, 라이프사이클 훅 등에서 필요한 데이터와 의존성 +2. LLM이 사용할 수 있는 컨텍스트: LLM이 응답을 생성할 때 볼 수 있는 데이터 ## 로컬 컨텍스트 -이는 [`RunContextWrapper`][agents.run_context.RunContextWrapper] 클래스와 그 안의 [`context`][agents.run_context.RunContextWrapper.context] 속성을 통해 표현됩니다. 동작 방식은 다음과 같습니다: +이는 [`RunContextWrapper`][agents.run_context.RunContextWrapper] 클래스와 그 안의 [`context`][agents.run_context.RunContextWrapper.context] 프로퍼티로 표현됩니다. 동작 방식은 다음과 같습니다: -1. 원하는 어떤 Python 객체든 생성합니다. 일반적으로 dataclass 또는 Pydantic 객체를 사용합니다 +1. 원하는 어떤 Python 객체든 만듭니다. 일반적으로 dataclass나 Pydantic 객체를 사용합니다 2. 해당 객체를 다양한 실행 메서드에 전달합니다(예: `Runner.run(..., **context=whatever**)`) -3. 모든 도구 호출, 라이프사이클 훅 등에는 `RunContextWrapper[T]` 래퍼 객체가 전달되며, 여기서 `T` 는 컨텍스트 객체 타입을 나타내고 `wrapper.context` 를 통해 접근할 수 있습니다 +3. 모든 도구 호출, 라이프사이클 훅 등은 `RunContextWrapper[T]` 래퍼 객체를 전달받습니다. 여기서 `T`는 컨텍스트 객체 타입을 나타내며 `wrapper.context`를 통해 접근할 수 있습니다 -가장 중요한 점: 특정 에이전트 실행에 대해 모든 에이전트, 도구 함수, 라이프사이클 등은 동일한 컨텍스트의 _타입_ 을 사용해야 합니다. +**가장 중요**한 점: 특정 에이전트 실행에서 모든 에이전트, 도구 함수, 라이프사이클 등은 동일한 _타입_의 컨텍스트를 사용해야 합니다. 컨텍스트는 다음과 같은 용도로 사용할 수 있습니다: -- 실행을 위한 컨텍스트 데이터(예: 사용자 이름/uid 또는 사용자에 대한 기타 정보) -- 의존성(예: 로거 객체, 데이터 페처 등) -- 헬퍼 함수 +- 실행에 대한 컨텍스트 데이터(예: 사용자 이름/uid 같은 정보 또는 그 외 사용자 정보) +- 의존성(예: 로거 객체, 데이터 페처 등) +- 헬퍼 함수 !!! danger "주의" - 컨텍스트 객체는 LLM 에게 **전송되지 않습니다**. 순수하게 로컬 객체로, 읽고 쓰고 메서드를 호출할 수 있습니다. + 컨텍스트 객체는 LLM으로 **전송되지 않습니다**. 이는 순수하게 로컬 객체이며 읽고 쓰고 메서드를 호출할 수 있습니다. ```python import asyncio @@ -66,18 +66,18 @@ if __name__ == "__main__": asyncio.run(main()) ``` -1. 이것이 컨텍스트 객체입니다. 여기서는 dataclass 를 사용했지만, 어떤 타입이든 사용할 수 있습니다. -2. 이것은 도구입니다. `RunContextWrapper[UserInfo]` 를 받는 것을 볼 수 있습니다. 도구 구현은 컨텍스트에서 읽습니다. -3. 에이전트를 제네릭 `UserInfo` 로 표시하여, 타입 체커가 오류를 잡을 수 있게 합니다(예: 다른 컨텍스트 타입을 받는 도구를 전달하려고 할 때). -4. 컨텍스트는 `run` 함수로 전달됩니다. -5. 에이전트는 도구를 올바르게 호출하고 나이를 가져옵니다. +1. 이 객체가 컨텍스트 객체입니다. 여기서는 dataclass를 사용했지만 어떤 타입이든 사용할 수 있습니다 +2. 이것은 도구입니다. `RunContextWrapper[UserInfo]`를 받는 것을 볼 수 있습니다. 도구 구현은 컨텍스트에서 읽습니다 +3. 에이전트를 제네릭 `UserInfo`로 표시하여, 타입 체커가 오류를 잡을 수 있게 합니다(예: 다른 컨텍스트 타입을 받는 도구를 전달하려고 했을 때) +4. 컨텍스트는 `run` 함수에 전달됩니다 +5. 에이전트는 도구를 올바르게 호출하고 나이를 가져옵니다 --- ### 고급: `ToolContext` -일부 경우 실행 중인 도구에 대한 추가 메타데이터(이름, 호출 ID, 원문 인자 문자열 등)에 접근하고 싶을 수 있습니다. -이를 위해 `RunContextWrapper` 를 확장한 [`ToolContext`][agents.tool_context.ToolContext] 클래스를 사용할 수 있습니다. +어떤 경우에는 실행 중인 도구에 대한 추가 메타데이터(이름, 호출 ID, 원문 인자 문자열 등)에 접근하고 싶을 수 있습니다. +이때 `RunContextWrapper`를 확장한 [`ToolContext`][agents.tool_context.ToolContext] 클래스를 사용할 수 있습니다. ```python from typing import Annotated @@ -105,23 +105,23 @@ agent = Agent( ) ``` -`ToolContext` 는 `RunContextWrapper` 와 동일한 `.context` 속성을 제공하며, -현재 도구 호출에 특화된 추가 필드를 포함합니다: +`ToolContext`는 `RunContextWrapper`와 동일한 `.context` 프로퍼티를 제공하며, +현재 도구 호출에 특화된 추가 필드를 제공합니다: -- `tool_name` – 호출되는 도구의 이름 +- `tool_name` – 호출 중인 도구의 이름 - `tool_call_id` – 이 도구 호출의 고유 식별자 - `tool_arguments` – 도구에 전달된 원문 인자 문자열 -실행 중 도구 수준 메타데이터가 필요할 때 `ToolContext` 를 사용하세요. -에이전트와 도구 간 일반적인 컨텍스트 공유에는 `RunContextWrapper` 만으로 충분합니다. +실행 중 도구 수준의 메타데이터가 필요할 때 `ToolContext`를 사용하세요. +에이전트와 도구 간 일반적인 컨텍스트 공유에는 `RunContextWrapper`만으로 충분합니다. --- ## 에이전트/LLM 컨텍스트 -LLM 이 호출될 때, LLM 이 볼 수 있는 **유일한** 데이터는 대화 이력뿐입니다. 따라서 LLM 에게 새로운 데이터를 제공하려면 해당 이력에 포함되도록 해야 합니다. 이를 수행하는 몇 가지 방법은 다음과 같습니다: +LLM이 호출될 때, LLM이 볼 수 있는 **유일한** 데이터는 대화 기록뿐입니다. 따라서 LLM에 새로운 데이터를 제공하려면, 그 데이터가 대화 기록에 포함되도록 해야 합니다. 방법은 몇 가지가 있습니다: -1. 에이전트 `instructions` 에 추가합니다. 이는 "시스템 프롬프트" 또는 "developer message" 라고도 합니다. 시스템 프롬프트는 정적인 문자열일 수도 있고, 컨텍스트를 받아 문자열을 출력하는 동적 함수일 수도 있습니다. 이는 항상 유용한 정보(예: 사용자 이름이나 현재 날짜)에 일반적으로 사용되는 방식입니다 -2. `Runner.run` 함수를 호출할 때 `input` 에 추가합니다. 이는 `instructions` 방식과 유사하지만, [지휘 계통(chain of command)](https://cdn.openai.com/spec/model-spec-2024-05-08.html#follow-the-chain-of-command)에서 더 낮은 위치의 메시지를 사용할 수 있습니다 -3. 함수 도구를 통해 노출합니다. 이는 _온디맨드_ 컨텍스트에 유용합니다. LLM 이 언제 데이터가 필요한지 결정하고, 해당 데이터를 가져오기 위해 도구를 호출할 수 있습니다 -4. 검색(retrieval) 또는 웹 검색을 사용합니다. 이는 파일이나 데이터베이스에서 관련 데이터를 가져오거나(retrieval), 웹에서 가져올 수 있는(웹 검색) 특수 도구입니다. 이는 관련 컨텍스트 데이터에 기반해 응답을 "그라운딩"하는 데 유용합니다 \ No newline at end of file +1. 에이전트 `instructions`에 추가합니다. 이는 "system prompt" 또는 "개발자 메시지"라고도 합니다. system prompt는 정적 문자열일 수도 있고, 컨텍스트를 받아 문자열을 출력하는 동적 함수일 수도 있습니다. 이는 항상 유용한 정보(예: 사용자 이름이나 현재 날짜)에 일반적으로 사용하는 방법입니다 +2. `Runner.run` 함수를 호출할 때 `input`에 추가합니다. 이는 `instructions`와 유사한 방법이지만, [명령 체계](https://cdn.openai.com/spec/model-spec-2024-05-08.html#follow-the-chain-of-command)에서 더 낮은 위치의 메시지를 사용할 수 있습니다 +3. 함수 도구로 노출합니다. 이는 _온디맨드_ 컨텍스트에 유용합니다. LLM이 데이터가 필요할 때를 스스로 결정하고, 해당 데이터를 가져오기 위해 도구를 호출할 수 있습니다 +4. 리트리벌(retrieval) 또는 웹 검색을 사용합니다. 이는 파일이나 데이터베이스에서 관련 데이터를 가져오거나(리트리벌), 웹에서 가져올 수 있는(웹 검색) 특수 도구입니다. 이는 응답을 관련 컨텍스트 데이터에 "그라운딩"하는 데 유용합니다 \ No newline at end of file diff --git a/docs/ko/examples.md b/docs/ko/examples.md index 8c778fa34..16138bd51 100644 --- a/docs/ko/examples.md +++ b/docs/ko/examples.md @@ -4,90 +4,90 @@ search: --- # 코드 예제 -[리포지토리](https://github.com/openai/openai-agents-python/tree/main/examples)의 examples 섹션에서 SDK의 다양한 샘플 구현을 확인하세요. code examples 는 서로 다른 패턴과 기능을 보여주는 여러 카테고리로 구성되어 있습니다. +[repo](https://github.com/openai/openai-agents-python/tree/main/examples)의 examples 섹션에서 SDK의 다양한 샘플 구현을 확인하세요. 예제는 다양한 패턴과 기능을 보여주는 여러 카테고리로 구성되어 있습니다. ## 카테고리 -- **[agent_patterns](https://github.com/openai/openai-agents-python/tree/main/examples/agent_patterns):** - 이 카테고리의 code examples 는 다음과 같은 일반적인 에이전트 설계 패턴을 보여줍니다 - - - 결정적 워크플로 - - 도구로서의 에이전트 - - 에이전트 병렬 실행 - - 조건부 도구 사용 - - 입력/출력 가드레일 - - 심판으로서의 LLM - - 라우팅 - - 스트리밍 가드레일 - -- **[basic](https://github.com/openai/openai-agents-python/tree/main/examples/basic):** - 이 code examples 는 SDK의 기본 기능을 보여줍니다 - - - Hello World code examples (기본 모델, GPT-5, 오픈 웨이트 모델) - - 에이전트 라이프사이클 관리 - - 동적 시스템 프롬프트 - - 스트리밍 출력(텍스트, 아이템, 함수 호출 인자) - - 프롬프트 템플릿 - - 파일 처리(로컬 및 원격, 이미지 및 PDF) - - 사용량 추적 - - 비엄격한 출력 타입 - - 이전 응답 ID 사용 - -- **[customer_service](https://github.com/openai/openai-agents-python/tree/main/examples/customer_service):** - 항공사를 위한 고객 서비스 시스템 예제 - -- **[financial_research_agent](https://github.com/openai/openai-agents-python/tree/main/examples/financial_research_agent):** - 금융 데이터 분석을 위한 에이전트와 도구로 구조화된 리서치 워크플로를 보여주는 금융 리서치 에이전트 - -- **[handoffs](https://github.com/openai/openai-agents-python/tree/main/examples/handoffs):** - 메시지 필터링을 활용한 에이전트 핸드오프의 실용적인 code examples - -- **[hosted_mcp](https://github.com/openai/openai-agents-python/tree/main/examples/hosted_mcp):** - 호스티드 MCP (Model Context Protocol) 커넥터와 승인 흐름을 사용하는 방법을 보여주는 code examples - -- **[mcp](https://github.com/openai/openai-agents-python/tree/main/examples/mcp):** - MCP (Model Context Protocol)로 에이전트를 만드는 방법을 학습하세요. 다음을 포함합니다 - - - 파일시스템 code examples - - Git code examples - - MCP 프롬프트 서버 code examples - - SSE (Server-Sent Events) code examples - - 스트리밍 가능한 HTTP code examples - -- **[memory](https://github.com/openai/openai-agents-python/tree/main/examples/memory):** - 에이전트를 위한 다양한 메모리 구현 code examples - - - SQLite 세션 스토리지 - - 고급 SQLite 세션 스토리지 - - Redis 세션 스토리지 - - SQLAlchemy 세션 스토리지 - - 암호화된 세션 스토리지 - - OpenAI 세션 스토리지 - -- **[model_providers](https://github.com/openai/openai-agents-python/tree/main/examples/model_providers):** - 커스텀 프로바이더와 LiteLLM 통합을 포함해, OpenAI 가 아닌 모델을 SDK와 함께 사용하는 방법을 알아보세요 - -- **[realtime](https://github.com/openai/openai-agents-python/tree/main/examples/realtime):** - SDK를 사용해 실시간 경험을 구축하는 방법을 보여주는 code examples - - - 웹 애플리케이션 - - 커맨드 라인 인터페이스 - - Twilio 통합 - -- **[reasoning_content](https://github.com/openai/openai-agents-python/tree/main/examples/reasoning_content):** - 추론 콘텐츠와 structured outputs 를 다루는 방법을 보여주는 code examples - -- **[research_bot](https://github.com/openai/openai-agents-python/tree/main/examples/research_bot):** - 복잡한 멀티 에이전트 리서치 워크플로를 보여주는 간단한 딥 리서치 클론 - -- **[tools](https://github.com/openai/openai-agents-python/tree/main/examples/tools):** - 다음과 같은 OpenAI 호스트하는 도구를 구현하는 방법을 학습하세요 - - - 웹 검색 및 필터를 적용한 웹 검색 - - 파일 검색 - - Code Interpreter - - 컴퓨터 사용 - - 이미지 생성 - -- **[voice](https://github.com/openai/openai-agents-python/tree/main/examples/voice):** - TTS 및 STT 모델을 활용한 음성 에이전트 code examples, 스트리밍 음성 code examples 를 포함합니다 \ No newline at end of file +- **[agent_patterns](https://github.com/openai/openai-agents-python/tree/main/examples/agent_patterns):** + 이 카테고리의 예제는 다음과 같은 일반적인 에이전트 설계 패턴을 보여줍니다 + + - 결정적 워크플로 + - 도구로서의 에이전트 + - 에이전트 병렬 실행 + - 조건부 도구 사용 + - 입력/출력 가드레일 + - 심사관으로서의 LLM + - 라우팅 + - 스트리밍 가드레일 + +- **[basic](https://github.com/openai/openai-agents-python/tree/main/examples/basic):** + 이 예제들은 다음과 같은 SDK의 기본 기능을 보여줍니다 + + - Hello World 예제 (기본 모델, GPT-5, 오픈 웨이트 모델) + - 에이전트 라이프사이클 관리 + - 동적 시스템 프롬프트 + - 스트리밍 출력 (텍스트, 아이템, 함수 호출 인자) + - 프롬프트 템플릿 + - 파일 처리 (로컬/원격, 이미지/PDF) + - 사용량 추적 + - 비엄격 출력 타입 + - 이전 응답 ID 사용 + +- **[customer_service](https://github.com/openai/openai-agents-python/tree/main/examples/customer_service):** + 항공사를 위한 고객 서비스 시스템 예제 + +- **[financial_research_agent](https://github.com/openai/openai-agents-python/tree/main/examples/financial_research_agent):** + 금융 데이터 분석을 위해 에이전트와 도구로 구조화된 리서치 워크플로를 시연하는 금융 리서치 에이전트 + +- **[handoffs](https://github.com/openai/openai-agents-python/tree/main/examples/handoffs):** + 메시지 필터링을 통한 에이전트 핸드오프의 실용적인 예제를 확인하세요 + +- **[hosted_mcp](https://github.com/openai/openai-agents-python/tree/main/examples/hosted_mcp):** + 호스티드 MCP (Model Context Protocol) 커넥터와 승인을 사용하는 방법을 보여주는 예제 + +- **[mcp](https://github.com/openai/openai-agents-python/tree/main/examples/mcp):** + MCP (Model Context Protocol)로 에이전트를 만드는 방법을 학습하세요. 예: + + - 파일시스템 예제 + - Git 예제 + - MCP 프롬프트 서버 예제 + - SSE (Server-Sent Events) 예제 + - 스트리밍 가능한 HTTP 예제 + +- **[memory](https://github.com/openai/openai-agents-python/tree/main/examples/memory):** + 에이전트를 위한 다양한 메모리 구현 예제 + + - SQLite 세션 스토리지 + - 고급 SQLite 세션 스토리지 + - Redis 세션 스토리지 + - SQLAlchemy 세션 스토리지 + - 암호화된 세션 스토리지 + - OpenAI 세션 스토리지 + +- **[model_providers](https://github.com/openai/openai-agents-python/tree/main/examples/model_providers):** + 사용자 지정 프로바이더와 LiteLLM 통합을 포함하여 OpenAI 이외 모델을 SDK로 사용하는 방법을 살펴보세요 + +- **[realtime](https://github.com/openai/openai-agents-python/tree/main/examples/realtime):** + SDK를 사용해 실시간 경험을 구축하는 방법을 보여주는 예제 + + - 웹 애플리케이션 + - 커맨드라인 인터페이스 + - Twilio 통합 + +- **[reasoning_content](https://github.com/openai/openai-agents-python/tree/main/examples/reasoning_content):** + 추론 콘텐츠와 structured outputs를 다루는 방법을 보여주는 예제 + +- **[research_bot](https://github.com/openai/openai-agents-python/tree/main/examples/research_bot):** + 복잡한 멀티 에이전트 연구 워크플로를 시연하는 간단한 딥 리서치 클론 + +- **[tools](https://github.com/openai/openai-agents-python/tree/main/examples/tools):** + 다음과 같은 OpenAI 호스트하는 도구를 구현하는 방법을 학습하세요 + + - 웹 검색 및 필터가 적용된 웹 검색 + - 파일 검색 + - Code interpreter + - 컴퓨터 사용 + - 이미지 생성 + +- **[voice](https://github.com/openai/openai-agents-python/tree/main/examples/voice):** + TTS와 STT 모델을 사용하는 보이스 에이전트 예제를 확인하세요. 스트리밍 보이스 예제 포함 \ No newline at end of file diff --git a/docs/ko/guardrails.md b/docs/ko/guardrails.md index 24d6db7fa..23fc5bfee 100644 --- a/docs/ko/guardrails.md +++ b/docs/ko/guardrails.md @@ -4,7 +4,7 @@ search: --- # 가드레일 -가드레일은 에이전트와 _병렬로_ 실행되어 사용자 입력에 대한 점검과 검증을 수행합니다. 예를 들어, 고객 요청을 돕기 위해 매우 스마트한(따라서 느리고/비용이 큰) 모델을 사용하는 에이전트를 상상해 보세요. 악의적인 사용자가 모델에게 수학 숙제를 도와 달라고 요청하는 것을 원치 않을 것입니다. 이때 빠르고/저렴한 모델로 가드레일을 실행할 수 있습니다. 가드레일이 악의적 사용을 감지하면 즉시 오류를 발생시켜 비용이 큰 모델의 실행을 중단하고 시간/비용을 절약할 수 있습니다. +가드레일은 에이전트와 _병렬로_ 실행되어 사용자 입력에 대한 점검과 검증을 수행할 수 있게 합니다. 예를 들어, 고객 요청을 돕기 위해 매우 똑똑한(따라서 느리고/비용이 큰) 모델을 사용하는 에이전트가 있다고 가정해 보겠습니다. 악의적인 사용자가 모델에게 수학 숙제를 도와 달라고 요청하는 것을 원치 않을 것입니다. 이때 빠르고/저렴한 모델로 가드레일을 실행할 수 있습니다. 가드레일이 악의적인 사용을 감지하면 즉시 오류를 발생시켜 비용이 큰 모델의 실행을 중단하고 시간/비용을 절약할 수 있습니다. 가드레일에는 두 가지 종류가 있습니다: @@ -13,35 +13,35 @@ search: ## 입력 가드레일 -입력 가드레일은 3단계로 실행됩니다: +입력 가드레일은 다음 3단계로 실행됩니다: -1. 먼저, 가드레일은 에이전트에 전달된 것과 동일한 입력을 수신합니다 -2. 다음으로, 가드레일 함수가 실행되어 [`GuardrailFunctionOutput`][agents.guardrail.GuardrailFunctionOutput]을 생성하고, 이는 [`InputGuardrailResult`][agents.guardrail.InputGuardrailResult]로 래핑됩니다 -3. 마지막으로 [`.tripwire_triggered`][agents.guardrail.GuardrailFunctionOutput.tripwire_triggered]가 true인지 확인합니다. true이면 [`InputGuardrailTripwireTriggered`][agents.exceptions.InputGuardrailTripwireTriggered] 예외가 발생하며, 이에 따라 사용자에게 적절히 응답하거나 예외를 처리할 수 있습니다 +1. 먼저, 가드레일은 에이전트에 전달된 것과 동일한 입력을 받습니다. +2. 다음으로, 가드레일 함수가 실행되어 [`GuardrailFunctionOutput`][agents.guardrail.GuardrailFunctionOutput]을 생성하고, 이를 [`InputGuardrailResult`][agents.guardrail.InputGuardrailResult]로 래핑합니다 +3. 마지막으로 [`.tripwire_triggered`][agents.guardrail.GuardrailFunctionOutput.tripwire_triggered]가 true인지 확인합니다. true이면 [`InputGuardrailTripwireTriggered`][agents.exceptions.InputGuardrailTripwireTriggered] 예외가 발생하여, 사용자에게 적절히 응답하거나 예외를 처리할 수 있습니다. !!! Note - 입력 가드레일은 사용자 입력에서 실행되도록 설계되었으므로, 에이전트의 가드레일은 해당 에이전트가 *첫 번째* 에이전트인 경우에만 실행됩니다. 왜 `guardrails` 속성이 `Runner.run`에 전달되는 대신 에이전트에 있냐고 궁금할 수 있습니다. 이는 가드레일이 실제 에이전트와 연관되는 경향이 있기 때문입니다. 서로 다른 에이전트에 대해 서로 다른 가드레일을 실행하므로, 코드를 같은 위치에 두는 것이 가독성에 유리합니다. + 입력 가드레일은 사용자 입력에서 실행되도록 설계되었으므로, 에이전트의 가드레일은 해당 에이전트가 *첫 번째* 에이전트일 때만 실행됩니다. 왜 `guardrails` 속성을 `Runner.run`으로 전달하지 않고 에이전트에 두는지 궁금할 수 있습니다. 가드레일은 실제 에이전트에 밀접하게 관련되는 경우가 많기 때문입니다. 에이전트마다 다른 가드레일을 실행하게 되므로 코드를 같은 위치에 두는 것이 가독성에 도움이 됩니다. ## 출력 가드레일 -출력 가드레일은 3단계로 실행됩니다: +출력 가드레일은 다음 3단계로 실행됩니다: -1. 먼저, 가드레일은 에이전트가 생성한 출력을 수신합니다 -2. 다음으로, 가드레일 함수가 실행되어 [`GuardrailFunctionOutput`][agents.guardrail.GuardrailFunctionOutput]을 생성하고, 이는 [`OutputGuardrailResult`][agents.guardrail.OutputGuardrailResult]로 래핑됩니다 -3. 마지막으로 [`.tripwire_triggered`][agents.guardrail.GuardrailFunctionOutput.tripwire_triggered]가 true인지 확인합니다. true이면 [`OutputGuardrailTripwireTriggered`][agents.exceptions.OutputGuardrailTripwireTriggered] 예외가 발생하며, 이에 따라 사용자에게 적절히 응답하거나 예외를 처리할 수 있습니다 +1. 먼저, 가드레일은 에이전트가 생성한 출력을 받습니다. +2. 다음으로, 가드레일 함수가 실행되어 [`GuardrailFunctionOutput`][agents.guardrail.GuardrailFunctionOutput]을 생성하고, 이를 [`OutputGuardrailResult`][agents.guardrail.OutputGuardrailResult]로 래핑합니다 +3. 마지막으로 [`.tripwire_triggered`][agents.guardrail.GuardrailFunctionOutput.tripwire_triggered]가 true인지 확인합니다. true이면 [`OutputGuardrailTripwireTriggered`][agents.exceptions.OutputGuardrailTripwireTriggered] 예외가 발생하여, 사용자에게 적절히 응답하거나 예외를 처리할 수 있습니다. !!! Note - 출력 가드레일은 최종 에이전트 출력에서 실행되도록 설계되었으므로, 에이전트의 가드레일은 해당 에이전트가 *마지막* 에이전트인 경우에만 실행됩니다. 입력 가드레일과 유사하게, 가드레일은 실제 에이전트와 연관되는 경향이 있으므로 서로 다른 에이전트에 대해 서로 다른 가드레일을 실행하며, 코드를 같은 위치에 두는 것이 가독성에 유리합니다. + 출력 가드레일은 최종 에이전트 출력에서 실행되도록 설계되었으므로, 에이전트의 가드레일은 해당 에이전트가 *마지막* 에이전트일 때만 실행됩니다. 입력 가드레일과 마찬가지로, 가드레일은 실제 에이전트와 밀접하게 관련되기 때문에 에이전트마다 다른 가드레일을 실행하게 되며, 코드를 같은 위치에 두는 것이 가독성에 도움이 됩니다. ## 트립와이어 -입력 또는 출력이 가드레일을 통과하지 못하면, 가드레일은 트립와이어로 이를 신호할 수 있습니다. 트립와이어가 트리거된 가드레일을 발견하는 즉시 `{Input,Output}GuardrailTripwireTriggered` 예외를 발생시키고 에이전트 실행을 중단합니다. +입력 또는 출력이 가드레일을 통과하지 못하면, 가드레일은 트립와이어(tripwire)로 이를 신호할 수 있습니다. 트립와이어가 발동된 가드레일을 확인하는 즉시 `{Input,Output}GuardrailTripwireTriggered` 예외를 발생시키고 에이전트 실행을 중단합니다. ## 가드레일 구현 -입력을 받고 [`GuardrailFunctionOutput`][agents.guardrail.GuardrailFunctionOutput]을 반환하는 함수를 제공해야 합니다. 이 예시에서는 내부적으로 에이전트를 실행하여 이를 수행합니다. +입력을 받아 [`GuardrailFunctionOutput`][agents.guardrail.GuardrailFunctionOutput]을 반환하는 함수를 제공해야 합니다. 이 예시에서는 내부적으로 에이전트를 실행하여 이를 수행합니다. ```python from pydantic import BaseModel @@ -94,10 +94,10 @@ async def main(): print("Math homework guardrail tripped") ``` -1. 이 에이전트를 가드레일 함수에서 사용합니다 -2. 이는 에이전트의 입력/컨텍스트를 받아 결과를 반환하는 가드레일 함수입니다 -3. 가드레일 결과에 추가 정보를 포함할 수 있습니다 -4. 이는 워크플로를 정의하는 실제 에이전트입니다 +1. 이 에이전트를 가드레일 함수에서 사용합니다. +2. 이는 에이전트의 입력/컨텍스트를 받아 결과를 반환하는 가드레일 함수입니다. +3. 가드레일 결과에 추가 정보를 포함할 수 있습니다. +4. 이는 워크플로를 정의하는 실제 에이전트입니다. 출력 가드레일도 유사합니다. @@ -152,7 +152,7 @@ async def main(): print("Math output guardrail tripped") ``` -1. 이는 실제 에이전트의 출력 타입입니다 -2. 이는 가드레일의 출력 타입입니다 -3. 이는 에이전트의 출력을 받아 결과를 반환하는 가드레일 함수입니다 -4. 이는 워크플로를 정의하는 실제 에이전트입니다 \ No newline at end of file +1. 이는 실제 에이전트의 출력 타입입니다. +2. 이는 가드레일의 출력 타입입니다. +3. 이는 에이전트의 출력을 받아 결과를 반환하는 가드레일 함수입니다. +4. 이는 워크플로를 정의하는 실제 에이전트입니다. \ No newline at end of file diff --git a/docs/ko/handoffs.md b/docs/ko/handoffs.md index 0a5482ea7..e89f9cdd2 100644 --- a/docs/ko/handoffs.md +++ b/docs/ko/handoffs.md @@ -4,15 +4,15 @@ search: --- # 핸드오프 -핸드오프는 한 에이전트가 다른 에이전트에게 작업을 위임하도록 합니다. 이는 서로 다른 분야에 특화된 에이전트들이 있는 시나리오에서 특히 유용합니다. 예를 들어, 고객 지원 앱에서는 주문 상태, 환불, FAQ 등 각각의 작업을 전담하는 에이전트가 있을 수 있습니다. +핸드오프를 사용하면 한 에이전트가 다른 에이전트에게 작업을 위임할 수 있습니다. 이는 서로 다른 분야에 특화된 에이전트들이 있는 시나리오에서 특히 유용합니다. 예를 들어, 고객 지원 앱에는 주문 상태, 환불, FAQ 등의 작업을 각각 전담하는 에이전트가 있을 수 있습니다. -핸드오프는 LLM 에게 도구로 표시됩니다. 따라서 `Refund Agent`라는 에이전트로의 핸드오프가 있다면, 도구 이름은 `transfer_to_refund_agent`가 됩니다. +핸드오프는 LLM 에게 도구로 표시됩니다. 예를 들어 `Refund Agent` 라는 에이전트로의 핸드오프가 있다면, 도구 이름은 `transfer_to_refund_agent` 가 됩니다. ## 핸드오프 생성 -모든 에이전트에는 [`handoffs`][agents.agent.Agent.handoffs] 매개변수가 있으며, 이는 `Agent`를 직접 받거나, 핸드오프를 커스터마이즈하는 `Handoff` 객체를 받을 수 있습니다. +모든 에이전트에는 [`handoffs`][agents.agent.Agent.handoffs] 매개변수가 있으며, `Agent` 를 직접 전달하거나 핸드오프를 커스터마이즈하는 `Handoff` 객체를 전달할 수 있습니다. -Agents SDK 에서 제공하는 [`handoff()`][agents.handoffs.handoff] 함수를 사용해 핸드오프를 생성할 수 있습니다. 이 함수는 넘겨줄 에이전트와 선택적 override 및 입력 필터를 지정할 수 있게 해줍니다. +Agents SDK 에서 제공하는 [`handoff()`][agents.handoffs.handoff] 함수를 사용해 핸드오프를 생성할 수 있습니다. 이 함수는 핸드오프 대상 에이전트와 함께 선택적 오버라이드 및 입력 필터를 지정할 수 있습니다. ### 기본 사용법 @@ -28,19 +28,19 @@ refund_agent = Agent(name="Refund agent") triage_agent = Agent(name="Triage agent", handoffs=[billing_agent, handoff(refund_agent)]) ``` -1. 에이전트를 직접 사용할 수도 있고(예: `billing_agent`), `handoff()` 함수를 사용할 수도 있습니다. +1. 에이전트를 직접 사용할 수 있습니다(예: `billing_agent`), 또는 `handoff()` 함수를 사용할 수 있습니다 -### `handoff()` 함수로 핸드오프 커스터마이즈 +### `handoff()` 함수를 통한 핸드오프 커스터마이징 -[`handoff()`][agents.handoffs.handoff] 함수로 다양한 설정을 커스터마이즈할 수 있습니다. +[`handoff()`][agents.handoffs.handoff] 함수로 다양한 항목을 커스터마이징할 수 있습니다. -- `agent`: 핸드오프가 이루어질 대상 에이전트 -- `tool_name_override`: 기본적으로 `Handoff.default_tool_name()` 함수가 사용되며, 이는 `transfer_to_`으로 결정됩니다. 이를 재정의할 수 있습니다 -- `tool_description_override`: `Handoff.default_tool_description()`의 기본 도구 설명을 재정의 -- `on_handoff`: 핸드오프가 호출될 때 실행되는 콜백 함수입니다. 핸드오프가 호출되는 순간 일부 데이터 페칭을 시작하는 등 작업에 유용합니다. 이 함수는 에이전트 컨텍스트를 받고, 선택적으로 LLM 이 생성한 입력도 받을 수 있습니다. 입력 데이터는 `input_type` 매개변수로 제어됩니다 -- `input_type`: 핸드오프에서 기대하는 입력의 타입(선택 사항) -- `input_filter`: 다음 에이전트가 받는 입력을 필터링합니다. 아래 내용을 참고하세요 -- `is_enabled`: 핸드오프 활성화 여부입니다. 불리언 또는 불리언을 반환하는 함수가 될 수 있으며, 런타임에 동적으로 핸드오프를 활성화/비활성화할 수 있습니다 +- `agent`: 작업을 넘길 대상 에이전트 +- `tool_name_override`: 기본적으로 `Handoff.default_tool_name()` 함수가 사용되며, 이는 `transfer_to_` 으로 결정됩니다. 이를 오버라이드할 수 있습니다 +- `tool_description_override`: `Handoff.default_tool_description()` 의 기본 도구 설명을 오버라이드 +- `on_handoff`: 핸드오프가 호출될 때 실행되는 콜백 함수. 핸드오프가 호출되는 즉시 데이터 페치 등을 시작하는 데 유용합니다. 이 함수는 에이전트 컨텍스트를 인자로 받고, 선택적으로 LLM 이 생성한 입력도 받을 수 있습니다. 입력 데이터는 `input_type` 매개변수로 제어됩니다 +- `input_type`: 핸드오프에서 기대하는 입력 타입(선택 사항) +- `input_filter`: 다음 에이전트가 받는 입력을 필터링할 수 있습니다. 아래를 참조하세요 +- `is_enabled`: 핸드오프 활성화 여부. 불리언이거나 불리언을 반환하는 함수가 될 수 있어, 런타임에 동적으로 활성/비활성화할 수 있습니다 ```python from agents import Agent, handoff, RunContextWrapper @@ -60,7 +60,7 @@ handoff_obj = handoff( ## 핸드오프 입력 -특정 상황에서는 LLM 이 핸드오프를 호출할 때 일부 데이터를 제공하길 원할 수 있습니다. 예를 들어, "에스컬레이션 에이전트"로의 핸드오프를 상상해 보세요. 로깅을 위해 사유(reason)를 제공받고 싶을 수 있습니다. +특정 상황에서는 LLM 이 핸드오프를 호출할 때 일부 데이터를 제공하길 원할 수 있습니다. 예를 들어, "에스컬레이션 에이전트"로의 핸드오프를 상상해 보세요. 기록을 위해 사유를 제공받고 싶을 수 있습니다. ```python from pydantic import BaseModel @@ -84,9 +84,9 @@ handoff_obj = handoff( ## 입력 필터 -핸드오프가 발생하면, 새로운 에이전트가 대화를 넘겨받아 이전의 전체 대화 기록을 볼 수 있게 됩니다. 이를 변경하고 싶다면 [`input_filter`][agents.handoffs.Handoff.input_filter]를 설정할 수 있습니다. 입력 필터는 [`HandoffInputData`][agents.handoffs.HandoffInputData]를 통해 기존 입력을 받아서, 새로운 `HandoffInputData`를 반환해야 하는 함수입니다. +핸드오프가 발생하면, 마치 새 에이전트가 대화를 인계받아 이전의 전체 대화 기록을 볼 수 있는 것과 같습니다. 이를 변경하려면 [`input_filter`][agents.handoffs.Handoff.input_filter] 를 설정할 수 있습니다. 입력 필터는 [`HandoffInputData`][agents.handoffs.HandoffInputData] 를 통해 기존 입력을 받고, 새로운 `HandoffInputData` 를 반환해야 하는 함수입니다. -일반적인 패턴들(예: 기록에서 모든 도구 호출 제거)이 있으며, 이는 [`agents.extensions.handoff_filters`][]에 구현되어 있습니다 +몇 가지 일반적인 패턴(예: 기록에서 모든 도구 호출 제거)이 있으며, 이는 [`agents.extensions.handoff_filters`][] 에 미리 구현되어 있습니다 ```python from agents import Agent, handoff @@ -100,11 +100,11 @@ handoff_obj = handoff( ) ``` -1. 이것은 `FAQ agent`가 호출될 때 기록에서 모든 도구를 자동으로 제거합니다. +1. 이는 `FAQ agent` 가 호출될 때 기록에서 모든 도구가 자동으로 제거됩니다 ## 권장 프롬프트 -LLM 이 핸드오프를 올바르게 이해하도록 하려면, 에이전트에 핸드오프 관련 정보를 포함하는 것을 권장합니다. [`agents.extensions.handoff_prompt.RECOMMENDED_PROMPT_PREFIX`][]의 권장 접두문을 사용하거나, [`agents.extensions.handoff_prompt.prompt_with_handoff_instructions`][]를 호출해 권장 데이터를 프롬프트에 자동으로 추가할 수 있습니다. +LLM 이 핸드오프를 올바르게 이해하도록 하려면, 에이전트에 핸드오프 관련 정보를 포함하는 것이 좋습니다. [`agents.extensions.handoff_prompt.RECOMMENDED_PROMPT_PREFIX`][] 에 권장 프리픽스가 있으며, 또는 [`agents.extensions.handoff_prompt.prompt_with_handoff_instructions`][] 를 호출해 프롬프트에 권장 데이터를 자동으로 추가할 수 있습니다. ```python from agents import Agent diff --git a/docs/ko/index.md b/docs/ko/index.md index 87bd3558c..f0cd0663e 100644 --- a/docs/ko/index.md +++ b/docs/ko/index.md @@ -4,31 +4,31 @@ search: --- # OpenAI Agents SDK -[OpenAI Agents SDK](https://github.com/openai/openai-agents-python)는 적은 추상화로 가볍고 사용하기 쉬운 패키지에서 에이전트형 AI 앱을 만들 수 있게 해줍니다. 이는 이전의 에이전트 실험인 [Swarm](https://github.com/openai/swarm/tree/main)의 프로덕션 준비 업그레이드입니다. Agents SDK 는 매우 작은 기본 구성요소 세트를 제공합니다: +[OpenAI Agents SDK](https://github.com/openai/openai-agents-python)는 매우 적은 추상화로 가볍고 사용하기 쉬운 패키지에서 에이전트형 AI 앱을 빌드할 수 있게 해줍니다. 이는 이전 에이전트 실험인 [Swarm](https://github.com/openai/swarm/tree/main)의 프로덕션 준비된 업그레이드입니다. Agents SDK에는 매우 작은 기본 구성 요소 집합이 있습니다: -- **에이전트**: instructions 와 tools 를 갖춘 LLM -- **핸드오프**: 에이전트가 특정 작업을 다른 에이전트에 위임할 수 있게 함 -- **가드레일**: 에이전트 입력과 출력을 검증할 수 있게 함 -- **세션**: 에이전트 실행 전반에 걸친 대화 기록을 자동으로 유지 관리 +- **에이전트**, instructions와 도구를 갖춘 LLM +- **핸드오프**, 에이전트가 특정 작업을 다른 에이전트에 위임할 수 있게 함 +- **가드레일**, 에이전트 입력과 출력을 검증할 수 있게 함 +- **세션**, 에이전트 실행 간 대화 기록을 자동으로 유지 관리함 -Python 과 결합하면, 이 기본 구성요소만으로도 도구와 에이전트 간의 복잡한 관계를 표현하고 가파른 학습 곡선 없이 실사용 애플리케이션을 구축할 수 있습니다. 또한 SDK 는 내장된 **트레이싱**을 제공하여 에이전트 플로를 시각화하고 디버그하며, 평가하고 심지어 애플리케이션에 맞게 모델을 파인튜닝할 수 있습니다. +Python과 결합하면, 이러한 기본 구성 요소만으로도 도구와 에이전트 간 복잡한 관계를 표현할 수 있으며, 가파른 학습 곡선 없이 실제 애플리케이션을 구축할 수 있습니다. 또한 SDK에는 기본 제공 **트레이싱**이 포함되어 있어 에이전트 플로우를 시각화하고 디버깅할 수 있으며, 이를 평가하고 심지어 애플리케이션에 맞게 모델을 파인튜닝할 수도 있습니다. -## Agents SDK 사용 이유 +## Agents SDK를 사용하는 이유 -SDK 의 설계 원칙은 두 가지입니다: +SDK의 핵심 설계 원칙은 두 가지입니다: -1. 쓸 만큼 충분한 기능을 제공하되, 빠르게 익힐 수 있도록 기본 구성요소는 최소화 -2. 기본 설정으로도 훌륭히 동작하지만, 동작 방식을 세밀하게 커스터마이즈 가능 +1. 사용할 가치가 있을 만큼 충분한 기능을 제공하되, 학습을 빠르게 할 수 있도록 기본 구성 요소는 최소화합니다 +2. 기본 설정으로도 훌륭하게 작동하지만, 동작을 정확히 원하는 대로 커스터마이즈할 수 있습니다 -주요 기능은 다음과 같습니다: +SDK의 주요 기능은 다음과 같습니다: -- 에이전트 루프: 도구 호출, 결과를 LLM 에 전달, LLM 이 완료될 때까지 루프를 처리하는 내장 에이전트 루프 -- 파이썬 우선: 새로운 추상화를 배울 필요 없이, 내장 언어 기능으로 에이전트를 오케스트레이션하고 연결 -- 핸드오프: 여러 에이전트 간 조정과 위임을 위한 강력한 기능 -- 가드레일: 에이전트와 병렬로 입력 검증과 체크를 실행하고, 실패 시 조기 중단 -- 세션: 에이전트 실행 전반의 대화 이력을 자동 관리하여 수동 상태 관리를 제거 -- 함수 도구: 어떤 Python 함수든 도구로 전환하고, 스키마 자동 생성과 Pydantic 기반 검증 제공 -- 트레이싱: 워크플로를 시각화, 디버그, 모니터링할 수 있는 내장 트레이싱과 OpenAI 의 평가, 파인튜닝, 증류 도구 제품군 활용 +- Agent loop: 도구 호출, 결과를 LLM에 전달, LLM이 완료될 때까지 루프를 수행하는 내장 에이전트 루프 +- 파이썬 우선: 새로운 추상화를 배우지 않고도, 언어의 기본 기능을 사용해 에이전트를 오케스트레이션하고 체이닝 +- 핸드오프: 여러 에이전트 간 조율 및 위임을 가능하게 하는 강력한 기능 +- 가드레일: 에이전트와 병렬로 입력 검증과 점검을 수행하며, 실패 시 조기에 중단 +- 세션: 에이전트 실행 전반에 걸친 대화 기록 자동 관리로 수동 상태 처리 불필요 +- 함수 도구: 모든 Python 함수를 도구로 변환, 스키마 자동 생성 및 Pydantic 기반 검증 제공 +- 트레이싱: 기본 제공 트레이싱으로 워크플로를 시각화, 디버그, 모니터링하고 OpenAI의 평가, 파인튜닝 및 디스틸레이션 도구 제품군을 활용할 수 있음 ## 설치 @@ -36,7 +36,7 @@ SDK 의 설계 원칙은 두 가지입니다: pip install openai-agents ``` -## Hello world 예제 +## Hello World 예제 ```python from agents import Agent, Runner @@ -51,7 +51,7 @@ print(result.final_output) # Infinite loop's dance. ``` -(_이 코드를 실행할 경우, `OPENAI_API_KEY` 환경 변수를 설정했는지 확인하세요_) +(_이를 실행하는 경우, `OPENAI_API_KEY` 환경 변수를 설정했는지 확인하세요_) ```bash export OPENAI_API_KEY=sk-... diff --git a/docs/ko/mcp.md b/docs/ko/mcp.md index 58d9eae6e..735e2021e 100644 --- a/docs/ko/mcp.md +++ b/docs/ko/mcp.md @@ -4,36 +4,34 @@ search: --- # Model context protocol (MCP) -[Model context protocol](https://modelcontextprotocol.io/introduction) (MCP)는 애플리케이션이 도구와 컨텍스트를 언어 모델에 노출하는 방식을 표준화합니다. 공식 문서에서 발췌: +[Model context protocol](https://modelcontextprotocol.io/introduction) (MCP)은 애플리케이션이 도구와 컨텍스트를 언어 모델에 노출하는 방법을 표준화합니다. 공식 문서에서: -> MCP는 애플리케이션이 LLM에 컨텍스트를 제공하는 방식을 표준화하는 오픈 프로토콜입니다. MCP를 AI 애플리케이션을 위한 USB‑C 포트로 생각해 보세요. -> USB‑C가 다양한 주변기기와 액세서리에 기기를 연결하는 표준화된 방식을 제공하듯, MCP는 AI 모델을 다양한 데이터 소스와 도구에 연결하는 표준화된 방식을 제공합니다. +> MCP는 애플리케이션이 LLM에 컨텍스트를 제공하는 방법을 표준화하는 오픈 프로토콜입니다. MCP를 AI 애플리케이션을 위한 USB‑C 포트라고 생각해 보세요. USB‑C가 다양한 주변기기와 액세서리에 기기를 연결하는 표준화된 방법을 제공하듯, MCP는 AI 모델을 다양한 데이터 소스와 도구에 연결하는 표준화된 방법을 제공합니다. Agents Python SDK는 여러 MCP 전송 방식을 이해합니다. 이를 통해 기존 MCP 서버를 재사용하거나 직접 구축하여 파일 시스템, HTTP, 또는 커넥터 기반 도구를 에이전트에 노출할 수 있습니다. ## MCP 통합 선택 -MCP 서버를 에이전트에 연결하기 전에 도구 호출을 어디에서 실행할지, 그리고 어떤 전송 방식을 사용할 수 있는지 결정하세요. 아래 매트릭스는 Python SDK가 지원하는 옵션을 요약합니다. +MCP 서버를 에이전트에 연결하기 전에 도구 호출이 어디에서 실행되어야 하는지와 접근 가능한 전송 방식을 결정하세요. 아래 매트릭스는 Python SDK가 지원하는 옵션을 요약합니다. -| 필요한 사항 | 권장 옵션 | +| 필요한 것 | 권장 옵션 | | ------------------------------------------------------------------------------------ | ----------------------------------------------------- | -| OpenAI의 Responses API가 모델을 대신해 공용으로 도달 가능한 MCP 서버를 호출하도록 함 | **호스티드 MCP 서버 도구** via [`HostedMCPTool`][agents.tool.HostedMCPTool] | -| 로컬 또는 원격에서 실행하는 Streamable HTTP 서버에 연결 | **Streamable HTTP MCP 서버** via [`MCPServerStreamableHttp`][agents.mcp.server.MCPServerStreamableHttp] | -| Server-Sent Events 를 구현한 HTTP 서버와 통신 | **HTTP with SSE MCP 서버** via [`MCPServerSse`][agents.mcp.server.MCPServerSse] | -| 로컬 프로세스를 실행하고 stdin/stdout 으로 통신 | **stdio MCP 서버** via [`MCPServerStdio`][agents.mcp.server.MCPServerStdio] | +| OpenAI의 Responses API가 모델을 대신해 공개적으로 접근 가능한 MCP 서버를 호출하도록 함 | [`HostedMCPTool`][agents.tool.HostedMCPTool]을 통한 **호스티드 MCP 서버 도구** | +| 로컬 또는 원격에서 실행하는 Streamable HTTP 서버에 연결 | [`MCPServerStreamableHttp`][agents.mcp.server.MCPServerStreamableHttp]을 통한 **Streamable HTTP MCP 서버** | +| Server-Sent Events 를 구현한 HTTP 서버와 통신 | [`MCPServerSse`][agents.mcp.server.MCPServerSse]을 통한 **HTTP with SSE MCP 서버** | +| 로컬 프로세스를 실행하고 stdin/stdout 로 통신 | [`MCPServerStdio`][agents.mcp.server.MCPServerStdio]을 통한 **stdio MCP 서버** | -아래 섹션에서는 각 옵션을 설정하는 방법과 언제 어떤 전송 방식을 선택할지 설명합니다. +아래 섹션에서는 각 옵션의 구성 방법과 언제 어떤 전송 방식을 선호해야 하는지 설명합니다. -## 1. 호스티드 MCP 서버 도구 +## 1. Hosted MCP server tools -호스티드 툴은 전체 도구 왕복을 OpenAI 인프라로 이동합니다. 코드에서 도구를 나열하고 호출하는 대신, -[`HostedMCPTool`][agents.tool.HostedMCPTool]이 서버 레이블(및 선택적 커넥터 메타데이터)을 Responses API로 전달합니다. -모델은 원격 서버의 도구를 나열하고, Python 프로세스로의 추가 콜백 없이 이를 호출합니다. 호스티드 툴은 현재 Responses API의 호스티드 MCP 통합을 지원하는 OpenAI 모델과 함께 작동합니다. +호스티드 툴은 도구 왕복 과정을 OpenAI 인프라로 전부 이전합니다. 코드에서 도구를 나열하고 호출하는 대신, +[`HostedMCPTool`][agents.tool.HostedMCPTool]이 서버 레이블(및 선택적 커넥터 메타데이터)을 Responses API로 전달합니다. 모델은 원격 서버의 도구를 나열하고 Python 프로세스로의 추가 콜백 없이 이를 호출합니다. 호스티드 툴은 현재 Responses API의 호스티드 MCP 통합을 지원하는 OpenAI 모델에서 작동합니다. ### 기본 호스티드 MCP 툴 -에이전트의 `tools` 목록에 [`HostedMCPTool`][agents.tool.HostedMCPTool]을 추가하여 호스티드 툴을 생성합니다. `tool_config` -딕셔너리는 REST API로 전송하는 JSON과 동일합니다: +에이전트의 `tools` 리스트에 [`HostedMCPTool`][agents.tool.HostedMCPTool]을 추가하여 호스티드 툴을 생성합니다. `tool_config` +딕셔너리는 REST API에 보낼 JSON을 그대로 반영합니다: ```python import asyncio @@ -61,12 +59,12 @@ async def main() -> None: asyncio.run(main()) ``` -호스티드 서버는 도구를 자동으로 노출하므로 `mcp_servers`에 추가할 필요가 없습니다. +호스티드 서버는 도구를 자동으로 노출합니다. `mcp_servers`에 추가할 필요가 없습니다. -### 호스티드 MCP 결과 스트리밍 +### 스트리밍 호스티드 MCP 결과 -호스티드 툴은 함수 도구와 정확히 같은 방식으로 스트리밍을 지원합니다. `Runner.run_streamed`에 `stream=True`를 전달하여 -모델이 실행 중일 때도 MCP의 증분 출력을 소비하세요: +호스티드 툴은 함수 도구와 완전히 동일한 방식으로 스트리밍 결과를 지원합니다. `Runner.run_streamed`에 `stream=True`를 +전달하면 모델이 계속 실행되는 동안 점진적인 MCP 출력을 소비할 수 있습니다: ```python result = Runner.run_streamed(agent, "Summarise this repository's top languages") @@ -78,8 +76,8 @@ print(result.final_output) ### 선택적 승인 플로우 -서버가 민감한 작업을 수행할 수 있는 경우, 각 도구 실행 전에 사람 또는 프로그램의 승인을 요구할 수 있습니다. `tool_config`의 -`require_approval`을 단일 정책(`"always"`, `"never"`) 또는 도구 이름별 정책 매핑 딕셔너리로 설정하세요. Python 내부에서 결정을 내리려면 `on_approval_request` 콜백을 제공합니다. +서버가 민감한 작업을 수행할 수 있는 경우 각 도구 실행 전에 사람 또는 프로그램적 승인을 요구할 수 있습니다. `tool_config`의 +`require_approval`을 단일 정책(`"always"`, `"never"`) 또는 도구 이름별 정책 매핑 딕셔너리로 구성하세요. Python 내부에서 결정을 내리려면 `on_approval_request` 콜백을 제공하세요. ```python from agents import MCPToolApprovalFunctionResult, MCPToolApprovalRequest @@ -107,12 +105,12 @@ agent = Agent( ) ``` -콜백은 동기 또는 비동기 모두 가능하며, 모델이 실행을 계속하기 위해 승인 데이터가 필요할 때마다 호출됩니다. +콜백은 동기 또는 비동기일 수 있으며, 모델이 실행을 계속하기 위해 승인 데이터가 필요할 때마다 호출됩니다. ### 커넥터 기반 호스티드 서버 호스티드 MCP는 OpenAI 커넥터도 지원합니다. `server_url`을 지정하는 대신 `connector_id`와 액세스 토큰을 제공하세요. -Responses API가 인증을 처리하며, 호스티드 서버는 커넥터의 도구를 노출합니다. +Responses API가 인증을 처리하고 호스티드 서버가 커넥터의 도구를 노출합니다. ```python import os @@ -174,11 +172,11 @@ asyncio.run(main()) - `client_session_timeout_seconds`는 HTTP 읽기 타임아웃을 제어합니다 - `use_structured_content`는 텍스트 출력보다 `tool_result.structured_content`를 선호할지 여부를 전환합니다 - `max_retry_attempts` 및 `retry_backoff_seconds_base`는 `list_tools()` 및 `call_tool()`에 자동 재시도를 추가합니다 -- `tool_filter`를 사용하면 노출할 도구의 하위 집합만 선택할 수 있습니다([도구 필터링](#tool-filtering) 참조) +- `tool_filter`는 노출할 도구의 하위 집합만 선택할 수 있게 합니다([Tool filtering](#tool-filtering) 참조) ## 3. HTTP with SSE MCP 서버 -MCP 서버가 HTTP with SSE 전송을 구현한다면, +MCP 서버가 HTTP with SSE 전송을 구현하는 경우, [`MCPServerSse`][agents.mcp.server.MCPServerSse]를 인스턴스화하세요. 전송 방식을 제외하면 API는 Streamable HTTP 서버와 동일합니다. ```python @@ -208,8 +206,8 @@ async with MCPServerSse( ## 4. stdio MCP 서버 -로컬 하위 프로세스로 실행되는 MCP 서버에는 [`MCPServerStdio`][agents.mcp.server.MCPServerStdio]를 사용하세요. SDK는 -프로세스를 시작하고 파이프를 열어두며, 컨텍스트 매니저 종료 시 자동으로 닫습니다. 이 옵션은 빠른 개념 증명이나 서버가 커맨드라인 엔트리 포인트만 노출하는 경우에 유용합니다. +로컬 하위 프로세스로 실행되는 MCP 서버에는 [`MCPServerStdio`][agents.mcp.server.MCPServerStdio]를 사용하세요. SDK가 +프로세스를 생성하고 파이프를 열어 유지하며, 컨텍스트 매니저가 종료될 때 자동으로 닫습니다. 이 옵션은 빠른 개념 증명이나 서버가 커맨드 라인 엔트리 포인트만 노출하는 경우에 유용합니다. ```python from pathlib import Path @@ -241,7 +239,7 @@ async with MCPServerStdio( ### 정적 도구 필터링 -[`create_static_tool_filter`][agents.mcp.create_static_tool_filter]를 사용해 간단한 허용/차단 목록을 구성하세요: +[`create_static_tool_filter`][agents.mcp.create_static_tool_filter]를 사용하여 간단한 허용/차단 리스트를 구성하세요: ```python from pathlib import Path @@ -259,12 +257,11 @@ filesystem_server = MCPServerStdio( ) ``` -`allowed_tool_names`와 `blocked_tool_names`가 모두 제공되면 SDK는 허용 목록을 먼저 적용한 뒤, 남은 집합에서 차단된 도구를 제거합니다. +`allowed_tool_names`와 `blocked_tool_names`가 모두 제공되는 경우 SDK는 먼저 허용 리스트를 적용한 다음 남은 집합에서 차단된 도구를 제거합니다. ### 동적 도구 필터링 -더 정교한 로직이 필요하면 [`ToolFilterContext`][agents.mcp.ToolFilterContext]를 받는 호출 가능 객체를 전달하세요. 이 호출체는 -동기 또는 비동기일 수 있으며, 도구를 노출해야 할 때 `True`를 반환합니다. +더 정교한 로직이 필요하면 [`ToolFilterContext`][agents.mcp.ToolFilterContext]를 입력으로 받는 호출 가능 객체를 전달하세요. 이 호출 가능 객체는 동기 또는 비동기일 수 있으며, 도구를 노출해야 하면 `True`를 반환합니다. ```python from pathlib import Path @@ -295,8 +292,8 @@ async with MCPServerStdio( MCP 서버는 에이전트 instructions 를 동적으로 생성하는 프롬프트도 제공할 수 있습니다. 프롬프트를 지원하는 서버는 두 가지 메서드를 노출합니다: -- `list_prompts()`는 사용 가능한 프롬프트 템플릿을 나열합니다 -- `get_prompt(name, arguments)`는 매개변수(옵션)를 포함해 구체적인 프롬프트를 가져옵니다 +- `list_prompts()`는 사용 가능한 프롬프트 템플릿을 열거합니다 +- `get_prompt(name, arguments)`는 필요 시 매개변수와 함께 구체적인 프롬프트를 가져옵니다 ```python from agents import Agent @@ -317,19 +314,19 @@ agent = Agent( ## 캐싱 모든 에이전트 실행은 각 MCP 서버에서 `list_tools()`를 호출합니다. 원격 서버는 눈에 띄는 지연을 유발할 수 있으므로, 모든 MCP -서버 클래스는 `cache_tools_list` 옵션을 제공합니다. 도구 정의가 자주 변경되지 않는다고 확신할 때만 `True`로 설정하세요. 이후 새 목록을 강제로 가져오려면 서버 인스턴스에서 `invalidate_tools_cache()`를 호출하세요. +서버 클래스는 `cache_tools_list` 옵션을 노출합니다. 도구 정의가 자주 변경되지 않는 것이 확실한 경우에만 `True`로 설정하세요. 이후 최신 목록을 강제로 가져오려면 서버 인스턴스에서 `invalidate_tools_cache()`를 호출하세요. ## 트레이싱 -[트레이싱](./tracing.md)은 다음을 포함해 MCP 활동을 자동으로 캡처합니다: +[트레이싱](./tracing.md)은 다음을 포함하여 MCP 활동을 자동으로 캡처합니다: -1. 도구를 나열하기 위한 MCP 서버 호출 -2. 도구 호출에 관한 MCP 관련 정보 +1. 도구 목록을 가져오기 위한 MCP 서버 호출 +2. 도구 호출의 MCP 관련 정보 ![MCP Tracing Screenshot](../assets/images/mcp-tracing.jpg) -## 추가 자료 +## 참고 자료 - [Model Context Protocol](https://modelcontextprotocol.io/) – 사양 및 설계 가이드 -- [examples/mcp](https://github.com/openai/openai-agents-python/tree/main/examples/mcp) – 실행 가능한 stdio, SSE, Streamable HTTP 샘플 -- [examples/hosted_mcp](https://github.com/openai/openai-agents-python/tree/main/examples/hosted_mcp) – 승인 및 커넥터를 포함한 완전한 호스티드 MCP 데모 \ No newline at end of file +- [examples/mcp](https://github.com/openai/openai-agents-python/tree/main/examples/mcp) – 실행 가능한 stdio, SSE, 및 Streamable HTTP 샘플 +- [examples/hosted_mcp](https://github.com/openai/openai-agents-python/tree/main/examples/hosted_mcp) – 승인과 커넥터를 포함한 완전한 호스티드 MCP 데모 \ No newline at end of file diff --git a/docs/ko/models/index.md b/docs/ko/models/index.md index d48a22d2f..0b4ca58dd 100644 --- a/docs/ko/models/index.md +++ b/docs/ko/models/index.md @@ -4,20 +4,20 @@ search: --- # 모델 -Agents SDK는 두 가지 방식으로 OpenAI 모델을 바로 사용할 수 있도록 지원합니다: +Agents SDK 는 다음 두 가지 방식으로 OpenAI 모델을 즉시 사용할 수 있도록 지원합니다: -- **권장**: 새로운 [Responses API](https://platform.openai.com/docs/api-reference/responses)를 사용해 OpenAI API를 호출하는 [`OpenAIResponsesModel`][agents.models.openai_responses.OpenAIResponsesModel] -- [Chat Completions API](https://platform.openai.com/docs/api-reference/chat)를 사용해 OpenAI API를 호출하는 [`OpenAIChatCompletionsModel`][agents.models.openai_chatcompletions.OpenAIChatCompletionsModel] +- **권장**: 새로운 [Responses API](https://platform.openai.com/docs/api-reference/responses)를 사용해 OpenAI API 를 호출하는 [`OpenAIResponsesModel`][agents.models.openai_responses.OpenAIResponsesModel] +- [Chat Completions API](https://platform.openai.com/docs/api-reference/chat)를 사용해 OpenAI API 를 호출하는 [`OpenAIChatCompletionsModel`][agents.models.openai_chatcompletions.OpenAIChatCompletionsModel] ## OpenAI 모델 -`Agent`를 초기화할 때 모델을 지정하지 않으면 기본 모델이 사용됩니다. 현재 기본값은 [`gpt-4.1`](https://platform.openai.com/docs/models/gpt-4.1)이며, 에이전트형 워크플로의 예측 가능성과 낮은 지연 시간 사이에 좋은 균형을 제공합니다. +`Agent` 를 초기화할 때 모델을 지정하지 않으면 기본 모델이 사용됩니다. 현재 기본값은 [`gpt-4.1`](https://platform.openai.com/docs/models/gpt-4.1)이며, 에이전트 워크플로에서 예측 가능성과 낮은 지연 시간 사이의 균형이 뛰어납니다. [`gpt-5`](https://platform.openai.com/docs/models/gpt-5) 같은 다른 모델로 전환하려면 다음 섹션의 단계를 따르세요. ### 기본 OpenAI 모델 -사용자 지정 모델을 설정하지 않은 모든 에이전트에 대해 일관되게 특정 모델을 사용하려면, 에이전트를 실행하기 전에 `OPENAI_DEFAULT_MODEL` 환경 변수를 설정하세요. +사용자 지정 모델을 설정하지 않은 모든 에이전트에서 일관되게 특정 모델을 사용하려면, 에이전트를 실행하기 전에 `OPENAI_DEFAULT_MODEL` 환경 변수를 설정하세요. ```bash export OPENAI_DEFAULT_MODEL=gpt-5 @@ -26,9 +26,9 @@ python3 my_awesome_agent.py #### GPT-5 모델 -이 방식으로 GPT-5 추론 모델들([`gpt-5`](https://platform.openai.com/docs/models/gpt-5), [`gpt-5-mini`](https://platform.openai.com/docs/models/gpt-5-mini), [`gpt-5-nano`](https://platform.openai.com/docs/models/gpt-5-nano))을 사용할 때, SDK는 기본적으로 합리적인 `ModelSettings`를 적용합니다. 구체적으로 `reasoning.effort`와 `verbosity`를 모두 `"low"`로 설정합니다. 이러한 설정을 직접 구성하려면 `agents.models.get_default_model_settings("gpt-5")`를 호출하세요. +GPT-5 의 reasoning 모델들([`gpt-5`](https://platform.openai.com/docs/models/gpt-5), [`gpt-5-mini`](https://platform.openai.com/docs/models/gpt-5-mini), [`gpt-5-nano`](https://platform.openai.com/docs/models/gpt-5-nano))을 이렇게 사용할 때, SDK 는 기본적으로 합리적인 `ModelSettings` 를 적용합니다. 구체적으로 `reasoning.effort` 와 `verbosity` 를 모두 `"low"` 로 설정합니다. 이러한 설정을 직접 구성하려면 `agents.models.get_default_model_settings("gpt-5")` 를 호출하세요. -지연 시간을 더 낮추거나 특정 요구 사항이 있는 경우, 다른 모델과 설정을 선택할 수 있습니다. 기본 모델의 추론 강도를 조정하려면 사용자 정의 `ModelSettings`를 전달하세요: +더 낮은 지연 시간 또는 특정 요구 사항이 있는 경우, 다른 모델과 설정을 선택할 수 있습니다. 기본 모델의 reasoning effort 를 조정하려면, 사용자 정의 `ModelSettings` 를 전달하세요: ```python from openai.types.shared import Reasoning @@ -44,52 +44,52 @@ my_agent = Agent( ) ``` -특히 지연 시간을 낮추려면 [`gpt-5-mini`](https://platform.openai.com/docs/models/gpt-5-mini) 또는 [`gpt-5-nano`](https://platform.openai.com/docs/models/gpt-5-nano) 모델에 `reasoning.effort="minimal"`을 사용하면 기본 설정보다 더 빠르게 응답하는 경우가 많습니다. 다만 Responses API의 일부 내장 도구(예: 파일 검색과 이미지 생성)는 `"minimal"` 추론 강도를 지원하지 않으므로, 이 Agents SDK의 기본값은 `"low"`입니다. +특히 지연 시간을 낮추려면, [`gpt-5-mini`](https://platform.openai.com/docs/models/gpt-5-mini) 또는 [`gpt-5-nano`](https://platform.openai.com/docs/models/gpt-5-nano) 모델을 `reasoning.effort="minimal"` 과 함께 사용하는 것이 기본 설정보다 더 빠르게 응답을 반환하는 경우가 많습니다. 다만 Responses API 의 일부 내장 도구(예: 파일 검색과 이미지 생성)는 `"minimal"` reasoning effort 를 지원하지 않으므로, 이 Agents SDK 는 기본값으로 `"low"` 를 사용합니다. -#### 비 GPT-5 모델 +#### Non-GPT-5 모델 -사용자 정의 `model_settings` 없이 비 GPT-5 모델 이름을 전달하는 경우, SDK는 모든 모델과 호환되는 일반 `ModelSettings`로 되돌립니다. +사용자 지정 `model_settings` 없이 Non–GPT-5 모델 이름을 전달하면, SDK 는 모든 모델과 호환되는 일반적인 `ModelSettings` 로 되돌립니다. -## 비 OpenAI 모델 +## Non-OpenAI 모델 -[LiteLLM 통합](../litellm.md)을 통해 대부분의 다른 비 OpenAI 모델을 사용할 수 있습니다. 먼저 litellm 의존성 그룹을 설치하세요: +대부분의 다른 Non-OpenAI 모델은 [LiteLLM 통합](./litellm.md)을 통해 사용할 수 있습니다. 먼저, litellm 종속성 그룹을 설치하세요: ```bash pip install "openai-agents[litellm]" ``` -그다음 `litellm/` 접두사를 붙여 [지원되는 모델](https://docs.litellm.ai/docs/providers)을 사용하세요: +그런 다음, `litellm/` 접두사를 사용해 [지원되는 모델](https://docs.litellm.ai/docs/providers) 중 아무거나 사용하세요: ```python claude_agent = Agent(model="litellm/anthropic/claude-3-5-sonnet-20240620", ...) gemini_agent = Agent(model="litellm/gemini/gemini-2.5-flash-preview-04-17", ...) ``` -### 비 OpenAI 모델을 사용하는 다른 방법 +### Non-OpenAI 모델을 사용하는 다른 방법 -다른 LLM 제공자를 통합하는 방법은 추가로 3가지가 있습니다(코드 예제는 [여기](https://github.com/openai/openai-agents-python/tree/main/examples/model_providers/) 참고): +다른 LLM 제공자를 통합하는 방법은 추가로 3가지가 있습니다(예시는 [여기](https://github.com/openai/openai-agents-python/tree/main/examples/model_providers/) 참조): -1. [`set_default_openai_client`][agents.set_default_openai_client]는 전역적으로 `AsyncOpenAI` 인스턴스를 LLM 클라이언트로 사용하고 싶은 경우에 유용합니다. 이는 LLM 제공자가 OpenAI 호환 API 엔드포인트를 제공하고, `base_url`과 `api_key`를 설정할 수 있는 경우에 해당합니다. 구성 가능한 코드 예제는 [examples/model_providers/custom_example_global.py](https://github.com/openai/openai-agents-python/tree/main/examples/model_providers/custom_example_global.py)를 참고하세요. -2. [`ModelProvider`][agents.models.interface.ModelProvider]는 `Runner.run` 수준에서 사용합니다. 이를 통해 "이번 실행의 모든 에이전트에 대해 사용자 지정 모델 제공자를 사용"하도록 지정할 수 있습니다. 구성 가능한 코드 예제는 [examples/model_providers/custom_example_provider.py](https://github.com/openai/openai-agents-python/tree/main/examples/model_providers/custom_example_provider.py)를 참고하세요. -3. [`Agent.model`][agents.agent.Agent.model]을 사용하면 특정 Agent 인스턴스에 모델을 지정할 수 있습니다. 이를 통해 에이전트마다 서로 다른 제공자를 혼합하여 사용할 수 있습니다. 손쉽게 대부분의 사용 가능한 모델을 쓰는 방법은 [LiteLLM 통합](../litellm.md)을 활용하는 것입니다. +1. [`set_default_openai_client`][agents.set_default_openai_client] 는 전역적으로 `AsyncOpenAI` 인스턴스를 LLM 클라이언트로 사용하고 싶을 때 유용합니다. LLM 제공자가 OpenAI 호환 API 엔드포인트를 제공하고, `base_url` 과 `api_key` 를 설정할 수 있는 경우에 해당합니다. 설정 가능한 예시는 [examples/model_providers/custom_example_global.py](https://github.com/openai/openai-agents-python/tree/main/examples/model_providers/custom_example_global.py) 를 참고하세요. +2. [`ModelProvider`][agents.models.interface.ModelProvider] 는 `Runner.run` 수준입니다. 이를 통해 "이 실행의 모든 에이전트에 대해 사용자 지정 모델 제공자를 사용"하도록 지정할 수 있습니다. 설정 가능한 예시는 [examples/model_providers/custom_example_provider.py](https://github.com/openai/openai-agents-python/tree/main/examples/model_providers/custom_example_provider.py) 를 참고하세요. +3. [`Agent.model`][agents.agent.Agent.model] 은 특정 Agent 인스턴스에서 모델을 지정할 수 있게 합니다. 이를 통해 에이전트마다 다른 제공자를 혼합하여 사용할 수 있습니다. 설정 가능한 예시는 [examples/model_providers/custom_example_agent.py](https://github.com/openai/openai-agents-python/tree/main/examples/model_providers/custom_example_agent.py) 를 참고하세요. 대부분의 사용 가능한 모델을 쉽게 사용하는 방법은 [LiteLLM 통합](./litellm.md)입니다. -`platform.openai.com`의 API 키가 없는 경우, `set_tracing_disabled()`로 트레이싱을 비활성화하거나, [다른 트레이싱 프로세서](../tracing.md)를 설정하는 것을 권장합니다. +`platform.openai.com` 의 API 키가 없는 경우, `set_tracing_disabled()` 를 통해 트레이싱을 비활성화하거나, [다른 트레이싱 프로세서](../tracing.md) 설정을 권장합니다. !!! note - 이 코드 예제에서는 대부분의 LLM 제공자가 아직 Responses API를 지원하지 않기 때문에 Chat Completions API/모델을 사용합니다. 사용 중인 LLM 제공자가 이를 지원한다면 Responses 사용을 권장합니다. + 이 예시에서는 대부분의 LLM 제공자가 아직 Responses API 를 지원하지 않기 때문에 Chat Completions API/모델을 사용합니다. LLM 제공자가 이를 지원한다면 Responses 사용을 권장합니다. -## 모델 혼합 및 조합 +## 모델 혼합 사용 -단일 워크플로 내에서 에이전트마다 다른 모델을 사용하고 싶을 수 있습니다. 예를 들어 분류(트리아지)에는 더 작고 빠른 모델을, 복잡한 작업에는 더 크고 성능이 높은 모델을 사용할 수 있습니다. [`Agent`][agents.Agent]를 구성할 때 다음 중 하나로 특정 모델을 선택할 수 있습니다: +단일 워크플로 내에서 에이전트마다 서로 다른 모델을 사용하고 싶을 수 있습니다. 예를 들어, 분류(트리아지)에는 더 작고 빠른 모델을, 복잡한 작업에는 더 크고 강력한 모델을 사용할 수 있습니다. [`Agent`][agents.Agent] 를 구성할 때 다음 중 하나로 특정 모델을 선택할 수 있습니다: -1. 모델 이름을 직접 전달 -2. 임의의 모델 이름 + 해당 이름을 Model 인스턴스로 매핑할 수 있는 [`ModelProvider`][agents.models.interface.ModelProvider] 전달 +1. 모델의 이름을 전달 +2. 임의의 모델 이름 + 그 이름을 Model 인스턴스로 매핑할 수 있는 [`ModelProvider`][agents.models.interface.ModelProvider] 를 전달 3. [`Model`][agents.models.interface.Model] 구현을 직접 제공 !!!note - SDK는 [`OpenAIResponsesModel`][agents.models.openai_responses.OpenAIResponsesModel]과 [`OpenAIChatCompletionsModel`][agents.models.openai_chatcompletions.OpenAIChatCompletionsModel] 두 형태 모두를 지원하지만, 두 형태가 지원하는 기능과 도구 세트가 다르므로 각 워크플로에는 단일 모델 형태를 사용하는 것을 권장합니다. 워크플로에 서로 다른 모델 형태가 필요한 경우, 사용하는 모든 기능이 두 형태에서 모두 제공되는지 확인하세요. + 우리 SDK 는 [`OpenAIResponsesModel`][agents.models.openai_responses.OpenAIResponsesModel] 과 [`OpenAIChatCompletionsModel`][agents.models.openai_chatcompletions.OpenAIChatCompletionsModel] 두 형태를 모두 지원하지만, 두 형태가 지원하는 기능과 도구가 다르기 때문에 각 워크플로에는 단일 모델 형태를 사용할 것을 권장합니다. 워크플로에서 모델 형태를 혼합해야 한다면, 사용하는 모든 기능이 두 형태 모두에서 제공되는지 확인하세요. ```python from agents import Agent, Runner, AsyncOpenAI, OpenAIChatCompletionsModel @@ -122,10 +122,10 @@ async def main(): print(result.final_output) ``` -1. OpenAI 모델 이름을 직접 설정 -2. [`Model`][agents.models.interface.Model] 구현을 제공 +1. OpenAI 모델의 이름을 직접 설정합니다 +2. [`Model`][agents.models.interface.Model] 구현을 제공합니다 -에이전트에 사용할 모델을 더 세부적으로 구성하려면 `temperature` 같은 선택적 모델 구성 매개변수를 제공하는 [`ModelSettings`][agents.models.interface.ModelSettings]를 전달할 수 있습니다. +에이전트에 사용되는 모델을 더 세밀하게 구성하려면, 온도(temperature)와 같은 선택적 모델 구성 매개변수를 제공하는 [`ModelSettings`][agents.models.interface.ModelSettings] 를 전달할 수 있습니다. ```python from agents import Agent, ModelSettings @@ -138,7 +138,7 @@ english_agent = Agent( ) ``` -또한 OpenAI의 Responses API를 사용할 때 [몇 가지 다른 선택적 매개변수](https://platform.openai.com/docs/api-reference/responses/create)(예: `user`, `service_tier` 등)가 있습니다. 이들이 최상위 수준에서 제공되지 않는 경우, `extra_args`를 사용하여 함께 전달할 수 있습니다. +또한 OpenAI 의 Responses API 를 사용할 때, [다른 몇 가지 선택적 매개변수](https://platform.openai.com/docs/api-reference/responses/create)(예: `user`, `service_tier` 등)가 있습니다. 이들이 최상위 수준에서 제공되지 않는 경우, `extra_args` 를 사용해 함께 전달할 수 있습니다. ```python from agents import Agent, ModelSettings @@ -154,26 +154,26 @@ english_agent = Agent( ) ``` -## 다른 LLM 제공자 사용 시 일반적인 문제 +## 다른 LLM 제공자 사용 시 흔한 문제 -### 트레이싱 클라이언트 오류 401 +### Tracing 클라이언트 오류 401 -트레이싱 관련 오류가 발생하는 경우, 트레이스가 OpenAI 서버로 업로드되는데 OpenAI API 키가 없기 때문입니다. 해결 방법은 세 가지입니다: +트레이싱 관련 오류가 발생하는 경우, 이는 트레이스가 OpenAI 서버로 업로드되는데 OpenAI API 키가 없기 때문입니다. 해결 방법은 세 가지입니다: -1. 트레이싱 완전 비활성화: [`set_tracing_disabled(True)`][agents.set_tracing_disabled] -2. 트레이싱용 OpenAI 키 설정: [`set_tracing_export_api_key(...)`][agents.set_tracing_export_api_key]. 이 API 키는 트레이스 업로드에만 사용되며, [platform.openai.com](https://platform.openai.com/)에서 발급된 키여야 합니다 -3. OpenAI가 아닌 트레이스 프로세서 사용. [트레이싱 문서](../tracing.md#custom-tracing-processors)를 참고하세요 +1. 트레이싱을 완전히 비활성화: [`set_tracing_disabled(True)`][agents.set_tracing_disabled] +2. 트레이싱을 위한 OpenAI 키 설정: [`set_tracing_export_api_key(...)`][agents.set_tracing_export_api_key]. 이 API 키는 트레이스 업로드에만 사용되며, 반드시 [platform.openai.com](https://platform.openai.com/) 의 키여야 합니다 +3. Non-OpenAI 트레이스 프로세서를 사용. [트레이싱 문서](../tracing.md#custom-tracing-processors) 참고 ### Responses API 지원 -SDK는 기본적으로 Responses API를 사용하지만, 대부분의 다른 LLM 제공자는 아직 이를 지원하지 않습니다. 이로 인해 404 등의 문제가 발생할 수 있습니다. 해결 방법은 다음 두 가지입니다: +SDK 는 기본적으로 Responses API 를 사용하지만, 대부분의 다른 LLM 제공자는 아직 이를 지원하지 않습니다. 이로 인해 404 등의 문제가 발생할 수 있습니다. 해결 방법은 두 가지입니다: -1. [`set_default_openai_api("chat_completions")`][agents.set_default_openai_api]를 호출하세요. 환경 변수로 `OPENAI_API_KEY`와 `OPENAI_BASE_URL`을 설정하는 경우 동작합니다 -2. [`OpenAIChatCompletionsModel`][agents.models.openai_chatcompletions.OpenAIChatCompletionsModel]을 사용하세요. 코드 예제는 [여기](https://github.com/openai/openai-agents-python/tree/main/examples/model_providers/)에 있습니다 +1. [`set_default_openai_api("chat_completions")`][agents.set_default_openai_api] 를 호출하세요. 이는 환경 변수로 `OPENAI_API_KEY` 와 `OPENAI_BASE_URL` 을 설정한 경우에 동작합니다 +2. [`OpenAIChatCompletionsModel`][agents.models.openai_chatcompletions.OpenAIChatCompletionsModel] 을 사용하세요. 예시는 [여기](https://github.com/openai/openai-agents-python/tree/main/examples/model_providers/) 에 있습니다 ### Structured outputs 지원 -일부 모델 제공자는 [structured outputs](https://platform.openai.com/docs/guides/structured-outputs)을 지원하지 않습니다. 이로 인해 다음과 유사한 오류가 발생할 수 있습니다: +일부 모델 제공자는 [structured outputs](https://platform.openai.com/docs/guides/structured-outputs) 를 지원하지 않습니다. 이는 때때로 다음과 같은 오류로 나타납니다: ``` @@ -181,12 +181,12 @@ BadRequestError: Error code: 400 - {'error': {'message': "'response_format.type' ``` -이는 일부 모델 제공자의 한계로, JSON 출력을 지원하더라도 출력에 사용할 `json_schema`를 지정할 수 없습니다. 이에 대한 해결책을 마련 중이지만, JSON 스키마 출력을 지원하는 제공자를 사용하는 것을 권장합니다. 그렇지 않으면 형식이 잘못된 JSON 때문에 앱이 자주 실패할 수 있습니다. +이는 일부 모델 제공자의 한계로, JSON 출력을 지원하지만 출력에 사용할 `json_schema` 를 지정할 수 없습니다. 이에 대한 해결을 진행 중이지만, JSON schema 출력을 지원하는 제공자에 의존할 것을 권장합니다. 그렇지 않으면 잘못된 JSON 으로 인해 앱이 자주 깨질 수 있습니다. ## 제공자 간 모델 혼합 -모델 제공자별 기능 차이를 인지하지 못하면 오류가 발생할 수 있습니다. 예를 들어 OpenAI는 structured outputs, 멀티모달 입력, 호스팅되는 파일 검색과 웹 검색을 지원하지만, 많은 다른 제공자는 이러한 기능을 지원하지 않습니다. 다음과 같은 제한 사항에 유의하세요: +모델 제공자 간 기능 차이를 인지하지 못하면 오류가 발생할 수 있습니다. 예를 들어, OpenAI 는 structured outputs, 멀티모달 입력, 호스티드 파일 검색 및 웹 검색을 지원하지만, 다른 많은 제공자는 이러한 기능을 지원하지 않습니다. 다음 제한 사항에 유의하세요: -- 지원하지 않는 `tools`를 이해하지 못하는 제공자에게 보내지 않기 +- 지원하지 않는 `tools` 를 이해하지 못하는 제공자에게 보내지 않기 - 텍스트 전용 모델을 호출하기 전에 멀티모달 입력을 필터링하기 -- structured JSON 출력을 지원하지 않는 제공자는 때때로 유효하지 않은 JSON을 생성할 수 있음을 인지하기 \ No newline at end of file +- structured JSON 출력을 지원하지 않는 제공자는 때때로 잘못된 JSON 을 생성할 수 있음을 인지하기 \ No newline at end of file diff --git a/docs/ko/models/litellm.md b/docs/ko/models/litellm.md index 529a48356..b89139e4c 100644 --- a/docs/ko/models/litellm.md +++ b/docs/ko/models/litellm.md @@ -2,33 +2,33 @@ search: exclude: true --- -# LiteLLM 를 통한 임의 모델 사용 +# LiteLLM 를 통한 임의의 모델 사용 !!! note - LiteLLM 통합은 베타 단계입니다. 특히 소규모 모델 제공자에서는 문제가 발생할 수 있습니다. 문제가 있으면 [GitHub 이슈](https://github.com/openai/openai-agents-python/issues)로 보고해 주세요. 신속히 수정하겠습니다. + LiteLLM 통합은 베타 단계입니다. 특히 소규모 모델 제공자에서 문제가 발생할 수 있습니다. 문제가 있으면 [GitHub 이슈](https://github.com/openai/openai-agents-python/issues)로 보고해 주시면 신속히 해결하겠습니다. -[LiteLLM](https://docs.litellm.ai/docs/)은 단일 인터페이스로 100개 이상의 모델을 사용할 수 있게 해주는 라이브러리입니다. Agents SDK에서 어떤 AI 모델이든 사용할 수 있도록 LiteLLM 통합을 추가했습니다. +[LiteLLM](https://docs.litellm.ai/docs/) 은 하나의 인터페이스로 100개 이상의 모델을 사용할 수 있게 해주는 라이브러리입니다. 우리는 Agents SDK 에서 임의의 AI 모델을 사용할 수 있도록 LiteLLM 통합을 추가했습니다. ## 설정 -`litellm`이 사용 가능해야 합니다. 선택적 `litellm` 의존성 그룹을 설치하면 됩니다: +`litellm` 이 사용 가능한지 확인해야 합니다. 선택적 `litellm` 종속성 그룹을 설치하여 사용할 수 있습니다: ```bash pip install "openai-agents[litellm]" ``` -완료되면, 모든 에이전트에서 [`LitellmModel`][agents.extensions.models.litellm_model.LitellmModel]을 사용할 수 있습니다. +완료되면, 어떤 에이전트에서도 [`LitellmModel`][agents.extensions.models.litellm_model.LitellmModel] 을 사용할 수 있습니다. ## 예제 -다음은 완전히 동작하는 예제입니다. 실행하면 모델 이름과 API 키를 입력하라는 메시지가 표시됩니다. 예를 들어 다음과 같이 입력할 수 있습니다: +다음은 완전한 동작 예제입니다. 실행하면 모델 이름과 API 키를 입력하라는 메시지가 표시됩니다. 예를 들어 다음과 같이 입력할 수 있습니다: -- `openai/gpt-4.1` 모델과 OpenAI API 키 -- `anthropic/claude-3-5-sonnet-20240620` 모델과 Anthropic API 키 +- `openai/gpt-4.1` 를 모델로, OpenAI API 키 +- `anthropic/claude-3-5-sonnet-20240620` 를 모델로, Anthropic API 키 - 등 -LiteLLM 에서 지원하는 전체 모델 목록은 [litellm 제공자 문서](https://docs.litellm.ai/docs/providers)를 참조하세요. +LiteLLM 이 지원하는 전체 모델 목록은 [litellm providers docs](https://docs.litellm.ai/docs/providers) 를 참고하세요. ```python from __future__ import annotations @@ -76,9 +76,9 @@ if __name__ == "__main__": asyncio.run(main(model, api_key)) ``` -## 사용량 데이터 추적 +## 사용 데이터 추적 -LiteLLM 응답을 Agents SDK 사용량 지표에 채우려면 에이전트를 생성할 때 `ModelSettings(include_usage=True)`를 전달하세요. +LiteLLM 응답이 Agents SDK 사용량 지표에 반영되길 원한다면, 에이전트를 생성할 때 `ModelSettings(include_usage=True)` 를 전달하세요. ```python from agents import Agent, ModelSettings @@ -91,4 +91,4 @@ agent = Agent( ) ``` -`include_usage=True`를 사용하면, LiteLLM 요청은 기본 제공 OpenAI 모델과 마찬가지로 `result.context_wrapper.usage`를 통해 토큰 및 요청 수를 보고합니다. \ No newline at end of file +`include_usage=True` 를 사용하면, LiteLLM 요청은 기본 OpenAI 모델과 마찬가지로 `result.context_wrapper.usage` 를 통해 토큰 및 요청 수를 보고합니다. \ No newline at end of file diff --git a/docs/ko/multi_agent.md b/docs/ko/multi_agent.md index 1500e628c..9e225075f 100644 --- a/docs/ko/multi_agent.md +++ b/docs/ko/multi_agent.md @@ -4,38 +4,38 @@ search: --- # 멀티 에이전트 오케스트레이션 -오케스트레이션은 앱 내 에이전트의 흐름을 의미합니다. 어떤 에이전트를 어떤 순서로 실행할지, 그리고 다음에 무엇을 할지 어떻게 결정할지에 관한 것입니다. 에이전트를 오케스트레이션하는 주요 방법은 두 가지입니다: +오케스트레이션은 앱에서 에이전트가 흐르는 방식을 의미합니다. 어떤 에이전트를 어떤 순서로 실행할지, 그리고 다음에 무엇을 할지 어떻게 결정할지에 대한 것입니다. 에이전트를 오케스트레이션하는 주요 방법은 두 가지입니다: -1. LLM 에게 결정을 맡기기: LLM 의 지능을 활용해 계획하고 추론하며 이에 따라 다음 단계를 결정하는 방식 +1. LLM에 의사결정을 맡기기: LLM의 지능을 활용해 계획하고 추론하며 다음에 취할 단계를 결정하는 방식 2. 코드로 오케스트레이션하기: 코드로 에이전트의 흐름을 결정하는 방식 -이 패턴들은 혼합하여 사용할 수 있습니다. 각각의 절충점은 아래에 설명되어 있습니다. +이 패턴들은 혼합하여 사용할 수 있습니다. 각 방법에는 아래에 설명된 트레이드오프가 있습니다. -## LLM 기반 오케스트레이션 +## LLM을 통한 오케스트레이션 -에이전트는 instructions, tools 및 핸드오프를 갖춘 LLM 입니다. 이는 개방형 작업이 주어졌을 때, LLM 이 도구를 사용해 행동하고 데이터를 수집하며, 핸드오프를 통해 하위 에이전트에 작업을 위임하는 방식으로 작업을 자율적으로 계획할 수 있음을 의미합니다. 예를 들어, 리서치 에이전트는 다음과 같은 도구를 갖출 수 있습니다: +에이전트는 instructions, tools 및 핸드오프로 구성된 LLM입니다. 이는 개방형 과제가 주어졌을 때 LLM이 스스로 도구를 사용해 행동하고 데이터를 수집하며, 핸드오프를 통해 하위 에이전트에 작업을 위임하는 계획을 세울 수 있음을 의미합니다. 예를 들어, 연구 에이전트는 다음과 같은 도구를 갖출 수 있습니다: -- 웹 검색을 통해 온라인에서 정보 찾기 -- 파일 검색 및 검색을 통해 독점 데이터와 연결에서 탐색하기 -- 컴퓨터 사용을 통해 컴퓨터에서 작업 수행하기 -- 코드 실행으로 데이터 분석 수행하기 +- 웹 검색을 통한 온라인 정보 탐색 +- 파일 검색 및 검색을 통한 사내 데이터와 연결 탐색 +- 컴퓨터 사용을 통한 컴퓨터 상의 액션 수행 +- 코드 실행을 통한 데이터 분석 - 기획, 보고서 작성 등에 특화된 에이전트로의 핸드오프 -이 패턴은 작업이 개방형이며 LLM 의 지능에 의존하고자 할 때 유용합니다. 여기서 가장 중요한 전술은 다음과 같습니다: +이 패턴은 과제가 개방형이고 LLM의 지능에 의존하고자 할 때 적합합니다. 여기서 중요한 전술은 다음과 같습니다: -1. 좋은 프롬프트에 투자하세요. 사용 가능한 도구와 사용 방법, 그리고 운영해야 하는 매개변수를 명확히 하세요. -2. 앱을 모니터링하고 반복 개선하세요. 문제가 생기는 지점을 파악하고 프롬프트를 개선하세요. -3. 에이전트가 내성하고 개선하도록 하세요. 예를 들어 루프에서 실행하여 스스로 비판하게 하거나 오류 메시지를 제공해 개선하도록 하세요. -4. 모든 것을 잘하는 범용 에이전트보다는 하나의 작업에 특화된 에이전트를 두세요. -5. [평가(evals)](https://platform.openai.com/docs/guides/evals)에 투자하세요. 에이전트를 훈련해 작업 능력을 향상시킬 수 있습니다. +1. 좋은 프롬프트에 투자하세요. 사용 가능한 도구, 사용 방법, 그리고 작동해야 하는 매개변수를 명확히 하세요 +2. 앱을 모니터링하고 반복 개선하세요. 문제가 생기는 지점을 확인하고 프롬프트를 개선하세요 +3. 에이전트가 자기 성찰하고 개선하도록 허용하세요. 예를 들어 루프에서 실행하고 자체 비평을 하게 하거나, 오류 메시지를 제공해 개선하도록 하세요 +4. 모든 것을 잘하는 범용 에이전트보다 한 가지 작업에 특화된 에이전트를 두세요 +5. [평가(evals)](https://platform.openai.com/docs/guides/evals)에 투자하세요. 이를 통해 에이전트를 훈련하여 과제 수행 능력을 향상시킬 수 있습니다 -## 코드 기반 오케스트레이션 +## 코드를 통한 오케스트레이션 -LLM 기반 오케스트레이션이 강력하긴 하지만, 코드 기반 오케스트레이션은 속도, 비용, 성능 측면에서 작업을 더 결정적이고 예측 가능하게 만듭니다. 일반적인 패턴은 다음과 같습니다: +LLM을 통한 오케스트레이션이 강력하지만, 코드를 통한 오케스트레이션은 속도, 비용, 성능 측면에서 작업을 더 결정론적이고 예측 가능하게 만듭니다. 일반적인 패턴은 다음과 같습니다: -- [structured outputs](https://platform.openai.com/docs/guides/structured-outputs)를 사용해 코드로 검사할 수 있는 적절한 형식의 데이터를 생성하기. 예를 들어, 에이전트에게 작업을 몇 가지 카테고리로 분류하게 한 뒤, 그 카테고리에 따라 다음 에이전트를 선택할 수 있습니다. -- 한 에이전트의 출력을 다음 에이전트의 입력으로 변환해 여러 에이전트를 체이닝하기. 예를 들어 블로그 글쓰기를 리서치, 개요 작성, 본문 작성, 비판, 개선의 일련의 단계로 분해할 수 있습니다. -- 작업을 수행하는 에이전트를 평가 및 피드백을 제공하는 에이전트와 함께 `while` 루프에서 실행하고, 평가자가 출력이 특정 기준을 통과했다고 판단할 때까지 반복하기 -- `asyncio.gather` 같은 파이썬의 기본 구성 요소를 통해 여러 에이전트를 병렬로 실행하기. 서로 의존하지 않는 여러 작업이 있을 때 속도에 유리합니다 +- [structured outputs](https://platform.openai.com/docs/guides/structured-outputs)를 사용해 코드로 검사할 수 있는 적절한 형식의 데이터를 생성하기. 예를 들어, 에이전트에게 작업을 몇 가지 카테고리로 분류하도록 요청한 다음, 해당 카테고리에 따라 다음 에이전트를 선택할 수 있습니다 +- 한 에이전트의 출력을 다음 에이전트의 입력으로 변환하여 여러 에이전트를 체이닝하기. 블로그 글 작성과 같은 작업을 리서치, 개요 작성, 본문 작성, 비평, 개선의 일련의 단계로 분해할 수 있습니다 +- 평가 및 피드백을 제공하는 에이전트와 실제 작업을 수행하는 에이전트를 `while` 루프로 함께 실행하고, 평가자가 출력이 특정 기준을 통과했다고 판단할 때까지 반복하기 +- `asyncio.gather`와 같은 파이썬 기본 구성 요소를 통해 여러 에이전트를 병렬로 실행하기. 상호 의존하지 않는 여러 작업이 있을 때 속도 향상에 유용합니다 -[`examples/agent_patterns`](https://github.com/openai/openai-agents-python/tree/main/examples/agent_patterns) 디렉토리에 여러 코드 예제가 있습니다. \ No newline at end of file +[`examples/agent_patterns`](https://github.com/openai/openai-agents-python/tree/main/examples/agent_patterns) 에 다양한 code examples가 있습니다. \ No newline at end of file diff --git a/docs/ko/quickstart.md b/docs/ko/quickstart.md index d925e6c77..28a171a97 100644 --- a/docs/ko/quickstart.md +++ b/docs/ko/quickstart.md @@ -30,7 +30,7 @@ pip install openai-agents # or `uv add openai-agents`, etc ### OpenAI API 키 설정 -없다면 OpenAI API 키를 만들기 위해 [이 안내](https://platform.openai.com/docs/quickstart#create-and-export-an-api-key)를 따르세요. +없다면 [이 안내](https://platform.openai.com/docs/quickstart#create-and-export-an-api-key)를 따라 OpenAI API 키를 생성하세요. ```bash export OPENAI_API_KEY=sk-... @@ -38,7 +38,7 @@ export OPENAI_API_KEY=sk-... ## 첫 에이전트 생성 -에이전트는 instructions, 이름, 그리고 선택적 구성(예: `model_config`)으로 정의합니다 +에이전트는 instructions, 이름, 그리고 선택적 구성(예: `model_config`)으로 정의됩니다. ```python from agents import Agent @@ -49,9 +49,9 @@ agent = Agent( ) ``` -## 추가 에이전트 +## 에이전트 추가 -추가 에이전트도 같은 방식으로 정의할 수 있습니다. `handoff_descriptions`는 핸드오프 라우팅을 결정하는 데 추가 컨텍스트를 제공합니다 +추가 에이전트도 동일한 방식으로 정의할 수 있습니다. `handoff_descriptions` 는 핸드오프 라우팅을 결정하는 데 도움이 되는 추가 컨텍스트를 제공합니다. ```python from agents import Agent @@ -71,7 +71,7 @@ math_tutor_agent = Agent( ## 핸드오프 정의 -각 에이전트에서 작업을 진행하는 방법을 결정하기 위해 선택할 수 있는 발신 핸드오프 옵션의 인벤토리를 정의할 수 있습니다. +각 에이전트에서, 작업을 진행하는 방법을 결정하기 위해 에이전트가 선택할 수 있는 아웃바운드 핸드오프 옵션의 목록을 정의할 수 있습니다. ```python triage_agent = Agent( @@ -83,7 +83,7 @@ triage_agent = Agent( ## 에이전트 오케스트레이션 실행 -워크플로가 실행되고 분류 에이전트가 두 전문 에이전트 사이를 올바르게 라우팅하는지 확인해 봅시다. +워크플로가 실행되고 분류 에이전트가 두 전문 에이전트 간에 올바르게 라우팅하는지 확인해 봅시다. ```python from agents import Runner @@ -95,7 +95,7 @@ async def main(): ## 가드레일 추가 -입력 또는 출력에 대해 실행될 사용자 지정 가드레일을 정의할 수 있습니다. +입력 또는 출력에 대해 실행할 사용자 정의 가드레일을 정의할 수 있습니다. ```python from agents import GuardrailFunctionOutput, Agent, Runner @@ -121,9 +121,9 @@ async def homework_guardrail(ctx, agent, input_data): ) ``` -## 전체 워크플로 통합 +## 전체 통합 -모두 통합하여 핸드오프와 입력 가드레일을 사용해 전체 워크플로를 실행해 봅시다. +이제 모두 합쳐서 핸드오프와 입력 가드레일을 사용해 전체 워크플로를 실행해 봅시다. ```python from agents import Agent, InputGuardrail, GuardrailFunctionOutput, Runner @@ -192,12 +192,12 @@ if __name__ == "__main__": ## 트레이스 보기 -에이전트 실행 중에 무슨 일이 있었는지 검토하려면 [OpenAI Dashboard의 Trace viewer](https://platform.openai.com/traces)로 이동해 실행 트레이스를 확인하세요. +에이전트 실행 중에 어떤 일이 있었는지 검토하려면 [OpenAI 대시보드의 Trace viewer](https://platform.openai.com/traces)에서 실행 트레이스를 확인하세요. ## 다음 단계 -더 복잡한 에이전트 플로우를 만드는 방법을 알아보세요: +더 복잡한 에이전트 플로를 구성하는 방법을 알아보세요: -- Learn about how to configure [에이전트](agents.md). -- Learn about [에이전트 실행](running_agents.md). -- Learn about [도구](tools.md), [가드레일](guardrails.md) 및 [모델](models/index.md). \ No newline at end of file +- Learn about how to configure [Agents](agents.md). +- Learn about [running agents](running_agents.md). +- Learn about [tools](tools.md), [guardrails](guardrails.md) and [models](models/index.md). \ No newline at end of file diff --git a/docs/ko/realtime/guide.md b/docs/ko/realtime/guide.md index 593b0e3f6..343d315a1 100644 --- a/docs/ko/realtime/guide.md +++ b/docs/ko/realtime/guide.md @@ -4,65 +4,65 @@ search: --- # 가이드 -이 가이드는 OpenAI Agents SDK의 실시간 기능을 사용하여 음성 지원 AI 에이전트를 구축하는 방법을 심층적으로 안내합니다. +이 가이드는 OpenAI Agents SDK의 실시간 기능을 사용해 음성 지원 AI 에이전트를 구축하는 방법을 자세히 설명합니다. !!! warning "베타 기능" -실시간 에이전트는 베타 단계입니다. 구현 개선 과정에서 호환성 깨짐이 발생할 수 있습니다. +실시간 에이전트는 베타 단계입니다. 구현을 개선하는 동안 하위 호환성이 깨질 수 있습니다. ## 개요 -실시간 에이전트는 대화형 흐름을 가능하게 하며, 오디오와 텍스트 입력을 실시간으로 처리하고 실시간 오디오로 응답합니다. OpenAI의 Realtime API와 지속적인 연결을 유지하여 낮은 지연의 자연스러운 음성 대화를 지원하고 인터럽션(중단 처리)을 우아하게 처리할 수 있습니다. +실시간 에이전트는 실시간으로 오디오와 텍스트 입력을 처리하고 실시간 오디오로 응답하는 대화 흐름을 제공합니다. OpenAI의 Realtime API와 지속적인 연결을 유지하여 지연이 낮은 자연스러운 음성 대화를 가능하게 하며, 사용자 인터럽션(중단 처리)을 우아하게 처리할 수 있습니다. ## 아키텍처 ### 핵심 구성 요소 -실시간 시스템은 다음의 주요 구성 요소로 이루어집니다: +실시간 시스템은 다음과 같은 주요 구성 요소로 이루어집니다. - **RealtimeAgent**: instructions, tools 및 핸드오프로 구성된 에이전트 -- **RealtimeRunner**: 구성 관리. `runner.run()` 을 호출하여 세션을 얻을 수 있습니다 -- **RealtimeSession**: 단일 상호작용 세션. 일반적으로 사용자가 대화를 시작할 때마다 하나를 만들고 대화가 끝날 때까지 유지합니다 +- **RealtimeRunner**: 구성을 관리합니다. `runner.run()`을 호출해 세션을 가져올 수 있습니다. +- **RealtimeSession**: 단일 상호작용 세션입니다. 일반적으로 사용자가 대화를 시작할 때마다 하나를 생성하고 대화가 끝날 때까지 유지합니다. - **RealtimeModel**: 기본 모델 인터페이스(일반적으로 OpenAI의 WebSocket 구현) -### 세션 플로우 +### 세션 흐름 -일반적인 실시간 세션은 다음 흐름을 따릅니다: +일반적인 실시간 세션 흐름은 다음과 같습니다. -1. instructions, tools 및 핸드오프로 **RealtimeAgent(들)를 생성**합니다 -2. 에이전트와 구성 옵션으로 **RealtimeRunner를 설정**합니다 -3. `await runner.run()` 을 사용해 **세션을 시작**하고 RealtimeSession을 반환받습니다 -4. `send_audio()` 또는 `send_message()` 로 **오디오나 텍스트 메시지를 전송**합니다 -5. 세션을 순회(iterate)하며 **이벤트를 수신**합니다 - 오디오 출력, 전사, 도구 호출, 핸드오프, 오류 등의 이벤트가 포함됩니다 -6. 사용자가 에이전트 말 위로 말할 때 **인터럽션(중단 처리)** 을 처리합니다. 현재 오디오 생성이 자동으로 중지됩니다 +1. instructions, tools 및 핸드오프로 **RealtimeAgent(들)** 을 생성합니다. +2. 에이전트와 구성 옵션으로 **RealtimeRunner를 설정** 합니다 +3. `await runner.run()`으로 **세션을 시작** 하며, RealtimeSession을 반환합니다. +4. `send_audio()` 또는 `send_message()`를 사용해 **오디오 또는 텍스트 메시지 전송** 합니다 +5. 세션을 반복(iterate)하여 **이벤트를 수신** 합니다 - 이벤트에는 오디오 출력, 전사, 도구 호출, 핸드오프, 오류가 포함됩니다 +6. 사용자가 에이전트의 발화를 가로챌 때 **인터럽션(중단 처리)** 을 처리하며, 현재 오디오 생성이 자동으로 중지됩니다 -세션은 대화 내역을 유지하며 실시간 모델과의 지속적인 연결을 관리합니다. +세션은 대화 이력을 유지하고 실시간 모델과의 지속 연결을 관리합니다. ## 에이전트 구성 -RealtimeAgent는 일반 Agent 클래스와 유사하게 동작하지만 몇 가지 중요한 차이점이 있습니다. 전체 API 세부 정보는 [`RealtimeAgent`][agents.realtime.agent.RealtimeAgent] API 레퍼런스를 참조하세요. +RealtimeAgent는 일반 Agent 클래스와 유사하지만 몇 가지 중요한 차이점이 있습니다. 전체 API 세부정보는 [`RealtimeAgent`][agents.realtime.agent.RealtimeAgent] API 레퍼런스를 참조하세요. 일반 에이전트와의 주요 차이점: -- 모델 선택은 에이전트 수준이 아닌 세션 수준에서 구성합니다 -- structured outputs 미지원(`outputType` 은 지원되지 않음) -- 음성(voice)은 에이전트별로 구성할 수 있지만 첫 에이전트가 말한 후에는 변경할 수 없습니다 -- 도구, 핸드오프, instructions 같은 다른 기능은 동일하게 작동합니다 +- 모델 선택은 에이전트 레벨이 아닌 세션 레벨에서 구성합니다. +- structured output 지원 없음(`outputType` 미지원) +- 음성(voice)은 에이전트별로 구성할 수 있으나, 첫 번째 에이전트가 말하기 시작한 후에는 변경할 수 없습니다. +- 그 외 tools, 핸드오프, instructions 등은 동일하게 동작합니다. ## 세션 구성 ### 모델 설정 -세션 구성으로 기본 실시간 모델 동작을 제어할 수 있습니다. 모델 이름(예: `gpt-realtime`), 음성 선택(alloy, echo, fable, onyx, nova, shimmer), 지원 모달리티(텍스트 및/또는 오디오)를 설정할 수 있습니다. 오디오 포맷은 입력과 출력 모두에 대해 설정 가능하며 기본값은 PCM16입니다. +세션 구성으로 기본 실시간 모델의 동작을 제어할 수 있습니다. 모델 이름(예: `gpt-realtime`), 음성 선택(alloy, echo, fable, onyx, nova, shimmer), 지원 모달리티(텍스트 및/또는 오디오)를 구성할 수 있습니다. 오디오 형식은 입력과 출력 모두에 대해 설정할 수 있으며 기본값은 PCM16입니다. ### 오디오 구성 -오디오 설정은 세션이 음성 입력과 출력을 처리하는 방식을 제어합니다. Whisper 같은 모델을 사용한 입력 오디오 전사 설정, 언어 선호도 설정, 도메인 특화 용어의 정확도를 높이기 위한 전사 프롬프트 제공이 가능합니다. 턴 감지 설정으로 에이전트가 언제 응답을 시작하고 끝낼지 제어할 수 있으며, 음성 활동 감지 임계값, 무음 지속 시간, 감지된 음성 주변 패딩 같은 옵션을 제공합니다. +오디오 설정은 세션의 음성 입력 및 출력을 처리하는 방식을 제어합니다. Whisper 등의 모델을 사용해 입력 오디오 전사를 구성하고, 언어 선호도를 설정하며, 도메인 특화 용어의 정확도를 높이기 위한 전사 프롬프트를 제공할 수 있습니다. 턴 감지 설정은 에이전트가 언제 응답을 시작하고 멈출지 제어하며, 음성 활동 감지 임계값, 무음 지속 시간, 감지된 음성 주변 패딩 등의 옵션을 제공합니다. ## 도구와 함수 ### 도구 추가 -일반 에이전트와 마찬가지로, 실시간 에이전트는 대화 중에 실행되는 함수 도구를 지원합니다: +일반 에이전트와 마찬가지로 실시간 에이전트는 대화 중 실행되는 함수 도구를 지원합니다: ```python from agents import function_tool @@ -90,7 +90,7 @@ agent = RealtimeAgent( ### 핸드오프 생성 -핸드오프를 통해 특화된 에이전트 간에 대화를 전환할 수 있습니다. +핸드오프를 사용하면 특화된 에이전트 간에 대화를 전환할 수 있습니다. ```python from agents.realtime import realtime_handoff @@ -119,22 +119,22 @@ main_agent = RealtimeAgent( ## 이벤트 처리 -세션은 세션 객체를 순회하여 수신할 수 있는 이벤트를 스트리밍합니다. 이벤트에는 오디오 출력 청크, 전사 결과, 도구 실행 시작과 종료, 에이전트 핸드오프, 오류가 포함됩니다. 처리해야 할 주요 이벤트는 다음과 같습니다: +세션은 세션 객체를 반복(iterate)하여 수신할 수 있는 이벤트를 스트리밍합니다. 이벤트에는 오디오 출력 청크, 전사 결과, 도구 실행 시작/종료, 에이전트 핸드오프, 오류 등이 포함됩니다. 처리해야 할 주요 이벤트는 다음과 같습니다. - **audio**: 에이전트 응답의 원문 오디오 데이터 -- **audio_end**: 에이전트가 말하기를 끝냄 -- **audio_interrupted**: 사용자가 에이전트를 중단함 +- **audio_end**: 에이전트 발화 종료 +- **audio_interrupted**: 사용자가 에이전트를 가로채어 중단 - **tool_start/tool_end**: 도구 실행 라이프사이클 - **handoff**: 에이전트 핸드오프 발생 - **error**: 처리 중 오류 발생 -전체 이벤트 세부 정보는 [`RealtimeSessionEvent`][agents.realtime.events.RealtimeSessionEvent]를 참조하세요. +전체 이벤트 세부정보는 [`RealtimeSessionEvent`][agents.realtime.events.RealtimeSessionEvent]를 참조하세요. ## 가드레일 -실시간 에이전트에는 출력 가드레일만 지원됩니다. 성능 문제를 피하기 위해 이 가드레일은 디바운스되어 주기적으로 실행되며(모든 단어마다 실행되지 않음), 기본 디바운스 길이는 100자이며 구성 가능합니다. +실시간 에이전트는 출력 가드레일만 지원합니다. 성능 문제를 방지하기 위해 실시간 생성 중 매 단어마다가 아니라 디바운스되어 주기적으로 실행됩니다. 기본 디바운스 길이는 100자이며, 구성 가능합니다. -가드레일은 `RealtimeAgent` 에 직접 연결하거나 세션의 `run_config` 를 통해 제공할 수 있습니다. 두 소스의 가드레일은 함께 실행됩니다. +가드레일은 `RealtimeAgent`에 직접 연결하거나 세션의 `run_config`를 통해 제공할 수 있습니다. 두 위치에서 제공된 가드레일은 함께 실행됩니다. ```python from agents.guardrail import GuardrailFunctionOutput, OutputGuardrail @@ -152,25 +152,25 @@ agent = RealtimeAgent( ) ``` -가드레일이 트리거되면 `guardrail_tripped` 이벤트를 생성하고 에이전트의 현재 응답을 인터럽트할 수 있습니다. 디바운스 동작은 안전성과 실시간 성능 요구 사이의 균형을 돕습니다. 텍스트 에이전트와 달리, 실시간 에이전트는 가드레일이 트리거되어도 Exception을 발생시키지 **않습니다**. +가드레일이 트리거되면 `guardrail_tripped` 이벤트를 생성하고 에이전트의 현재 응답을 인터럽트할 수 있습니다. 디바운스 동작은 안전성과 실시간 성능 요구 사이의 균형을 맞춥니다. 텍스트 에이전트와 달리, 실시간 에이전트는 가드레일이 트리거되어도 예외(Exception)를 발생시키지 **않습니다**. ## 오디오 처리 -[`session.send_audio(audio_bytes)`][agents.realtime.session.RealtimeSession.send_audio] 를 사용해 오디오를 세션에 전송하거나, [`session.send_message()`][agents.realtime.session.RealtimeSession.send_message] 를 사용해 텍스트를 전송하세요. +[`session.send_audio(audio_bytes)`][agents.realtime.session.RealtimeSession.send_audio]로 세션에 오디오를 전송하거나 [`session.send_message()`][agents.realtime.session.RealtimeSession.send_message]로 텍스트를 전송하세요. -오디오 출력의 경우 `audio` 이벤트를 수신하고 선호하는 오디오 라이브러리로 오디오 데이터를 재생하세요. 사용자가 에이전트를 중단할 때 즉시 재생을 중지하고 대기 중인 오디오를 지우기 위해 `audio_interrupted` 이벤트를 반드시 수신하세요. +오디오 출력을 위해서는 `audio` 이벤트를 수신하고 선호하는 오디오 라이브러리로 오디오 데이터를 재생하세요. 사용자가 에이전트를 중단할 때 즉시 재생을 멈추고 대기 중인 오디오를 모두 비우기 위해 `audio_interrupted` 이벤트를 반드시 수신하세요. -## 모델 직접 접근 +## 모델 직접 액세스 -기본 모델에 접근하여 사용자 지정 리스너를 추가하거나 고급 작업을 수행할 수 있습니다: +기본 모델에 접근하여 커스텀 리스너를 추가하거나 고급 작업을 수행할 수 있습니다: ```python # Add a custom listener to the model session.model.add_listener(my_custom_listener) ``` -이를 통해 연결에 대한 더 낮은 수준의 제어가 필요한 고급 사용 사례를 위해 [`RealtimeModel`][agents.realtime.model.RealtimeModel] 인터페이스에 직접 접근할 수 있습니다. +이렇게 하면 저수준 연결 제어가 필요한 고급 사용 사례를 위해 [`RealtimeModel`][agents.realtime.model.RealtimeModel] 인터페이스에 직접 접근할 수 있습니다. ## 코드 예제 -완전한 동작 code examples 는 UI 구성 요소가 있는 경우와 없는 경우의 데모를 포함하며, [examples/realtime 디렉터리](https://github.com/openai/openai-agents-python/tree/main/examples/realtime)에서 확인할 수 있습니다. \ No newline at end of file +완전한 동작 예시는 UI 구성 요소가 있는 경우와 없는 경우를 모두 포함하는 [examples/realtime 디렉터리](https://github.com/openai/openai-agents-python/tree/main/examples/realtime)를 확인하세요. \ No newline at end of file diff --git a/docs/ko/realtime/quickstart.md b/docs/ko/realtime/quickstart.md index da32ce59e..a8d5e5662 100644 --- a/docs/ko/realtime/quickstart.md +++ b/docs/ko/realtime/quickstart.md @@ -4,12 +4,12 @@ search: --- # 빠른 시작 -실시간 에이전트는 OpenAI의 Realtime API를 사용해 AI 에이전트와 음성 대화를 가능하게 합니다. 이 가이드는 첫 실시간 음성 에이전트를 만드는 과정을 안내합니다. +실시간 에이전트는 OpenAI의 Realtime API를 사용하여 AI 에이전트와의 음성 대화를 가능하게 합니다. 이 가이드는 첫 번째 실시간 음성 에이전트를 만드는 과정을 안내합니다. !!! warning "베타 기능" -실시간 에이전트는 베타 단계입니다. 구현을 개선하는 동안 호환성에 영향을 줄 수 있는 변경이 있을 수 있습니다. +실시간 에이전트는 베타 단계입니다. 구현을 개선하는 동안 호환성 변경이 발생할 수 있습니다. -## 사전 준비 +## 준비 사항 - Python 3.9 이상 - OpenAI API 키 @@ -25,7 +25,7 @@ pip install openai-agents ## 첫 실시간 에이전트 만들기 -### 1. 필요한 구성요소 가져오기 +### 1. 필요한 구성 요소 가져오기 ```python import asyncio @@ -111,7 +111,7 @@ def _truncate_str(s: str, max_length: int) -> str: ## 전체 예제 -다음은 완전한 동작 예제입니다: +다음은 완전한 작동 예제입니다: ```python import asyncio @@ -192,7 +192,7 @@ if __name__ == "__main__": ### 모델 설정 -- `model_name`: 사용 가능한 실시간 모델 중 선택 (예: `gpt-realtime`) +- `model_name`: 사용 가능한 실시간 모델에서 선택 (예: `gpt-realtime`) - `voice`: 음성 선택 (`alloy`, `echo`, `fable`, `onyx`, `nova`, `shimmer`) - `modalities`: 텍스트 또는 오디오 활성화 (`["text"]` 또는 `["audio"]`) @@ -204,9 +204,9 @@ if __name__ == "__main__": ### 턴 감지 -- `type`: 감지 방식 (`server_vad`, `semantic_vad`) +- `type`: 감지 방법 (`server_vad`, `semantic_vad`) - `threshold`: 음성 활동 임계값 (0.0-1.0) -- `silence_duration_ms`: 턴 종료를 감지할 무음 지속 시간 +- `silence_duration_ms`: 턴 종료를 감지할 침묵 지속 시간 - `prefix_padding_ms`: 발화 전 오디오 패딩 ## 다음 단계 @@ -219,13 +219,13 @@ if __name__ == "__main__": ## 인증 -환경 변수에 OpenAI API 키가 설정되어 있는지 확인하세요: +환경에 OpenAI API 키가 설정되어 있는지 확인하세요: ```bash export OPENAI_API_KEY="your-api-key-here" ``` -또는 세션을 생성할 때 직접 전달하세요: +또는 세션을 생성할 때 직접 전달할 수 있습니다: ```python session = await runner.run(model_config={"api_key": "your-api-key"}) diff --git a/docs/ko/release.md b/docs/ko/release.md index 19447134e..befd1c757 100644 --- a/docs/ko/release.md +++ b/docs/ko/release.md @@ -4,29 +4,29 @@ search: --- # 릴리스 프로세스/변경 로그 -이 프로젝트는 `0.Y.Z` 형식의 약간 수정된 시맨틱 버전 관리 방식을 따릅니다. 선행 `0`은 SDK가 여전히 빠르게 발전 중임을 의미합니다. 각 구성 요소는 다음과 같이 증가시킵니다: +이 프로젝트는 `0.Y.Z` 형태의 약간 수정된 시맨틱 버전 관리를 따릅니다. 앞의 `0`은 SDK가 아직 빠르게 발전 중임을 의미합니다. 각 구성 요소는 다음과 같이 증가합니다: ## 마이너(`Y`) 버전 -베타로 표시되지 않은 모든 공개 인터페이스에 **호환성 파괴 변경**이 있을 경우 마이너 버전 `Y`를 올립니다. 예를 들어 `0.0.x`에서 `0.1.x`로 올라갈 때 호환성 파괴 변경이 포함될 수 있습니다. +베타로 표시되지 않은 공개 인터페이스에 **브레이킹 체인지**가 있을 경우 마이너 버전 `Y`를 증가시킵니다. 예를 들어, `0.0.x`에서 `0.1.x`로 올라갈 때 브레이킹 체인지가 포함될 수 있습니다. -호환성 파괴 변경을 원하지 않으시면, 프로젝트에서 `0.0.x` 버전으로 고정하는 것을 권장합니다. +브레이킹 체인지를 원하지 않는 경우, 프로젝트에서 `0.0.x` 버전으로 고정할 것을 권장합니다. ## 패치(`Z`) 버전 -다음과 같은 호환성에 영향을 주지 않는 변경에 대해 `Z`를 증가시킵니다: +하위 호환을 깨지 않는 변경의 경우 `Z`를 증가시킵니다: -- Bug 수정 +- 버그 수정 - 새로운 기능 - 비공개 인터페이스 변경 - 베타 기능 업데이트 -## 호환성 파괴 변경 로그 +## 브레이킹 체인지 변경 로그 ### 0.2.0 -이 버전에서는 이전에 `Agent`를 인수로 받던 일부 위치가 이제 `AgentBase`를 인수로 받도록 변경되었습니다. 예: MCP 서버의 `list_tools()` 호출. 이는 순전히 타입 관련 변경이며, 여전히 `Agent` 객체를 받게 됩니다. 업데이트하려면 `Agent`를 `AgentBase`로 바꿔 타입 오류만 수정하면 됩니다. +이 버전에서는 기존에 `Agent`를 매개변수로 받던 일부 위치가 `AgentBase`를 매개변수로 받도록 변경되었습니다. 예: MCP 서버의 `list_tools()` 호출. 이는 순수하게 타입 관련 변경이며, 여전히 `Agent` 객체를 받게 됩니다. 업데이트하려면 타입 오류를 `Agent`를 `AgentBase`로 바꿔 해결하면 됩니다. ### 0.1.0 -이 버전에서는 [`MCPServer.list_tools()`][agents.mcp.server.MCPServer]에 `run_context`와 `agent`라는 두 개의 새로운 매개변수가 추가되었습니다. `MCPServer`를 서브클래싱하는 모든 클래스에 이 매개변수를 추가해야 합니다. \ No newline at end of file +이 버전에서 [`MCPServer.list_tools()`][agents.mcp.server.MCPServer]에 `run_context`와 `agent`라는 두 개의 새로운 매개변수가 추가되었습니다. `MCPServer`를 서브클래싱한 모든 클래스에 이 매개변수를 추가해야 합니다. \ No newline at end of file diff --git a/docs/ko/repl.md b/docs/ko/repl.md index 0cc5a4965..cdead249b 100644 --- a/docs/ko/repl.md +++ b/docs/ko/repl.md @@ -4,7 +4,7 @@ search: --- # REPL 유틸리티 -SDK는 터미널에서 에이전트의 동작을 빠르고 상호작용적으로 테스트할 수 있도록 `run_demo_loop`를 제공합니다. +SDK는 터미널에서 에이전트의 동작을 빠르고 인터랙티브하게 테스트할 수 있는 `run_demo_loop`를 제공합니다. ```python import asyncio @@ -18,6 +18,6 @@ if __name__ == "__main__": asyncio.run(main()) ``` -`run_demo_loop`는 반복 루프에서 사용자 입력을 요청하며, 턴 사이의 대화 기록을 유지합니다. 기본적으로 생성되는 대로 모델 출력을 스트리밍합니다. 위의 예제를 실행하면, run_demo_loop가 대화형 채팅 세션을 시작합니다. 사용자 입력을 계속 요청하고, 턴 사이의 전체 대화 기록을 기억하여(에이전트가 어떤 내용이 논의되었는지 알 수 있도록) 응답이 생성되는 즉시 실시간으로 자동 스트리밍합니다. +`run_demo_loop`는 루프에서 사용자 입력을 요청하고, 턴 사이의 대화 기록을 유지합니다. 기본적으로 생성되는 대로 모델 출력을 스트리밍합니다. 위 예제를 실행하면, run_demo_loop가 인터랙티브 채팅 세션을 시작합니다. 이 세션은 계속해서 입력을 요청하고, 턴 사이의 전체 대화 기록을 기억하며(에이전트가 어떤 내용이 오갔는지 알 수 있도록), 생성되는 즉시 에이전트의 응답을 실시간으로 자동 스트리밍합니다. -이 채팅 세션을 종료하려면 `quit` 또는 `exit`을(를) 입력하고 Enter를 누르거나 `Ctrl-D` 키보드 단축키를 사용하세요. \ No newline at end of file +이 채팅 세션을 종료하려면 `quit` 또는 `exit`를 입력(Enter 키)하거나 `Ctrl-D` 키보드 단축키를 사용하세요. \ No newline at end of file diff --git a/docs/ko/results.md b/docs/ko/results.md index 80d1c0da3..a6ab3dc49 100644 --- a/docs/ko/results.md +++ b/docs/ko/results.md @@ -6,51 +6,51 @@ search: `Runner.run` 메서드를 호출하면 다음 중 하나를 받습니다: -- `run` 또는 `run_sync` 호출 시 [`RunResult`][agents.result.RunResult] -- `run_streamed` 호출 시 [`RunResultStreaming`][agents.result.RunResultStreaming] +- `run` 또는 `run_sync` 를 호출한 경우 [`RunResult`][agents.result.RunResult] +- `run_streamed` 를 호출한 경우 [`RunResultStreaming`][agents.result.RunResultStreaming] -이 둘 모두 대부분의 유용한 정보가 담겨 있는 [`RunResultBase`][agents.result.RunResultBase]를 상속합니다. +둘 다 [`RunResultBase`][agents.result.RunResultBase] 를 상속하며, 대부분의 유용한 정보가 여기에 있습니다. ## 최종 출력 -[`final_output`][agents.result.RunResultBase.final_output] 속성에는 마지막으로 실행된 에이전트의 최종 출력이 담깁니다. 이는 다음 중 하나입니다: +[`final_output`][agents.result.RunResultBase.final_output] 속성에는 마지막으로 실행된 에이전트의 최종 출력이 포함됩니다. 다음 중 하나입니다: -- 마지막 에이전트에 `output_type`이 정의되지 않은 경우 `str` +- 마지막 에이전트에 `output_type` 이 정의되지 않은 경우 `str` - 에이전트에 출력 타입이 정의된 경우 `last_agent.output_type` 타입의 객체 !!! note - `final_output`의 타입은 `Any`입니다. 핸드오프 때문에 정적 타이핑을 할 수 없습니다. 핸드오프가 발생하면 어떤 에이전트든 마지막 에이전트가 될 수 있으므로, 가능한 출력 타입의 집합을 정적으로 알 수 없습니다. + `final_output` 의 타입은 `Any` 입니다. 핸드오프 때문에 정적으로 타입을 지정할 수 없습니다. 핸드오프가 발생하면 어떤 에이전트든 마지막 에이전트가 될 수 있으므로, 가능한 출력 타입 집합을 정적으로 알 수 없습니다. -## 다음 턴을 위한 입력 +## 다음 턴 입력 -[`result.to_input_list()`][agents.result.RunResultBase.to_input_list]를 사용하면 결과를, 제공한 원본 입력과 에이전트 실행 중 생성된 항목을 이어붙인 입력 리스트로 변환할 수 있습니다. 이를 통해 한 번의 에이전트 실행 출력을 다른 실행에 전달하거나, 루프에서 실행하면서 매번 새로운 사용자 입력을 덧붙이기에 편리합니다. +[`result.to_input_list()`][agents.result.RunResultBase.to_input_list] 를 사용하여 결과를 입력 리스트로 변환할 수 있습니다. 이는 사용자가 제공한 원본 입력과 에이전트 실행 중 생성된 항목들을 연결합니다. 이를 통해 한 에이전트 실행의 출력을 다른 실행에 전달하거나, 루프에서 실행하며 매번 새로운 사용자 입력을 추가하기에 편리합니다. ## 마지막 에이전트 -[`last_agent`][agents.result.RunResultBase.last_agent] 속성에는 마지막으로 실행된 에이전트가 담깁니다. 애플리케이션에 따라, 이는 사용자가 다음에 무언가를 입력할 때 유용한 경우가 많습니다. 예를 들어, 1차 분류 에이전트가 언어별 에이전트로 핸드오프하는 구조라면, 마지막 에이전트를 저장해 두었다가 사용자가 다음에 에이전트에 메시지를 보낼 때 재사용할 수 있습니다. +[`last_agent`][agents.result.RunResultBase.last_agent] 속성에는 마지막으로 실행된 에이전트가 포함됩니다. 애플리케이션에 따라, 이는 사용자가 다음에 무언가를 입력할 때 유용한 경우가 많습니다. 예를 들어, 프런트라인 트리아지 에이전트가 언어별 에이전트로 핸드오프하는 경우, 마지막 에이전트를 저장해 두었다가 사용자가 다음에 에이전트에 메시지를 보낼 때 재사용할 수 있습니다. -## 신규 항목 +## 새 항목 -[`new_items`][agents.result.RunResultBase.new_items] 속성에는 실행 중 생성된 신규 항목이 담깁니다. 항목은 [`RunItem`][agents.items.RunItem]입니다. 실행 항목은 LLM이 생성한 원문 항목을 래핑합니다. +[`new_items`][agents.result.RunResultBase.new_items] 속성에는 실행 중 생성된 새 항목이 포함됩니다. 항목은 [`RunItem`][agents.items.RunItem] 입니다. 실행 항목은 LLM 이 생성한 원문 항목을 래핑합니다. -- [`MessageOutputItem`][agents.items.MessageOutputItem]: LLM의 메시지를 나타냅니다. 원문 항목은 생성된 메시지입니다 -- [`HandoffCallItem`][agents.items.HandoffCallItem]: LLM이 핸드오프 도구를 호출했음을 나타냅니다. 원문 항목은 LLM의 도구 호출 항목입니다 -- [`HandoffOutputItem`][agents.items.HandoffOutputItem]: 핸드오프가 발생했음을 나타냅니다. 원문 항목은 핸드오프 도구 호출에 대한 도구 응답입니다. 항목에서 소스/타깃 에이전트에도 접근할 수 있습니다 -- [`ToolCallItem`][agents.items.ToolCallItem]: LLM이 도구를 호출했음을 나타냅니다 -- [`ToolCallOutputItem`][agents.items.ToolCallOutputItem]: 도구가 호출되었음을 나타냅니다. 원문 항목은 도구 응답입니다. 항목에서 도구 출력에도 접근할 수 있습니다 -- [`ReasoningItem`][agents.items.ReasoningItem]: LLM의 추론 항목을 나타냅니다. 원문 항목은 생성된 추론입니다 +- [`MessageOutputItem`][agents.items.MessageOutputItem] 은 LLM 의 메시지를 나타냅니다. 원문 항목은 생성된 메시지입니다 +- [`HandoffCallItem`][agents.items.HandoffCallItem] 은 LLM 이 핸드오프 도구를 호출했음을 나타냅니다. 원문 항목은 LLM 의 도구 호출 항목입니다 +- [`HandoffOutputItem`][agents.items.HandoffOutputItem] 은 핸드오프가 발생했음을 나타냅니다. 원문 항목은 핸드오프 도구 호출에 대한 도구 응답입니다. 항목에서 소스/타겟 에이전트에도 접근할 수 있습니다 +- [`ToolCallItem`][agents.items.ToolCallItem] 은 LLM 이 도구를 호출했음을 나타냅니다 +- [`ToolCallOutputItem`][agents.items.ToolCallOutputItem] 은 도구가 호출되었음을 나타냅니다. 원문 항목은 도구 응답입니다. 항목에서 도구 출력에도 접근할 수 있습니다 +- [`ReasoningItem`][agents.items.ReasoningItem] 은 LLM 의 추론 항목을 나타냅니다. 원문 항목은 생성된 추론입니다 ## 기타 정보 ### 가드레일 결과 -[`input_guardrail_results`][agents.result.RunResultBase.input_guardrail_results] 및 [`output_guardrail_results`][agents.result.RunResultBase.output_guardrail_results] 속성에는 (있는 경우) 가드레일의 결과가 담깁니다. 가드레일 결과에는 로깅하거나 저장하고 싶은 유용한 정보가 포함되는 경우가 있어, 이를 제공해 드립니다. +[`input_guardrail_results`][agents.result.RunResultBase.input_guardrail_results] 및 [`output_guardrail_results`][agents.result.RunResultBase.output_guardrail_results] 속성에는 (있는 경우) 가드레일 결과가 포함됩니다. 가드레일 결과에는 로깅하거나 저장하고 싶은 유용한 정보가 포함될 수 있으므로, 이를 제공해 드립니다. ### 원문 응답 -[`raw_responses`][agents.result.RunResultBase.raw_responses] 속성에는 LLM이 생성한 [`ModelResponse`][agents.items.ModelResponse] 목록이 담깁니다. +[`raw_responses`][agents.result.RunResultBase.raw_responses] 속성에는 LLM 이 생성한 [`ModelResponse`][agents.items.ModelResponse] 객체들이 포함됩니다. ### 원본 입력 -[`input`][agents.result.RunResultBase.input] 속성에는 `run` 메서드에 제공한 원본 입력이 담깁니다. 대부분의 경우 필요하지 않지만, 필요한 경우를 대비해 제공됩니다. \ No newline at end of file +[`input`][agents.result.RunResultBase.input] 속성에는 `run` 메서드에 제공한 원본 입력이 포함됩니다. 대부분의 경우 필요하지 않지만, 필요한 경우를 대비해 제공됩니다. \ No newline at end of file diff --git a/docs/ko/running_agents.md b/docs/ko/running_agents.md index 4160a4e03..132b51af8 100644 --- a/docs/ko/running_agents.md +++ b/docs/ko/running_agents.md @@ -4,11 +4,11 @@ search: --- # 에이전트 실행 -에이전트는 [`Runner`][agents.run.Runner] 클래스를 통해 실행할 수 있습니다. 선택지는 3가지입니다: +[`Runner`][agents.run.Runner] 클래스를 통해 에이전트를 실행할 수 있습니다. 선택지는 3가지입니다: 1. [`Runner.run()`][agents.run.Runner.run]: 비동기로 실행되며 [`RunResult`][agents.result.RunResult] 를 반환합니다. 2. [`Runner.run_sync()`][agents.run.Runner.run_sync]: 동기 메서드로, 내부적으로 `.run()` 을 실행합니다. -3. [`Runner.run_streamed()`][agents.run.Runner.run_streamed]: 비동기로 실행되며 [`RunResultStreaming`][agents.result.RunResultStreaming] 을 반환합니다. LLM 을 스트리밍 모드로 호출하고, 수신되는 대로 해당 이벤트를 스트림으로 제공합니다. +3. [`Runner.run_streamed()`][agents.run.Runner.run_streamed]: 비동기로 실행되며 [`RunResultStreaming`][agents.result.RunResultStreaming] 을 반환합니다. LLM 을 스트리밍 모드로 호출하며, 수신되는 대로 이벤트를 스트리밍합니다. ```python from agents import Agent, Runner @@ -23,51 +23,51 @@ async def main(): # Infinite loop's dance ``` -자세한 내용은 [결과 가이드](results.md)에서 확인하세요. +자세한 내용은 [결과 가이드](results.md)를 참고하세요. ## 에이전트 루프 -`Runner` 의 run 메서드를 사용할 때 시작 에이전트와 입력을 전달합니다. 입력은 문자열(사용자 메시지로 간주) 또는 OpenAI Responses API 의 입력 아이템 리스트가 될 수 있습니다. +`Runner` 의 run 메서드를 사용할 때 시작 에이전트와 입력을 전달합니다. 입력은 문자열(사용자 메시지로 간주됨) 또는 OpenAI Responses API 의 입력 항목 목록일 수 있습니다. 런너는 다음과 같은 루프를 실행합니다: -1. 현재 입력으로 현재 에이전트에 대해 LLM 을 호출합니다. +1. 현재 에이전트와 현재 입력으로 LLM 을 호출합니다. 2. LLM 이 출력을 생성합니다. - 1. LLM 이 `final_output` 을 반환하면 루프를 종료하고 결과를 반환합니다. - 2. LLM 이 핸드오프를 수행하면 현재 에이전트와 입력을 갱신하고 루프를 다시 실행합니다. - 3. LLM 이 도구 호출을 생성하면 해당 도구 호출을 실행하고 결과를 추가한 뒤 루프를 다시 실행합니다. + 1. LLM 이 `final_output` 을 반환하면 루프가 종료되고 결과를 반환합니다. + 2. LLM 이 핸드오프를 수행하면 현재 에이전트와 입력을 갱신하고 루프를 재실행합니다. + 3. LLM 이 도구 호출을 생성하면 해당 도구 호출을 실행하고 결과를 추가한 뒤 루프를 재실행합니다. 3. 전달된 `max_turns` 를 초과하면 [`MaxTurnsExceeded`][agents.exceptions.MaxTurnsExceeded] 예외를 발생시킵니다. !!! note - LLM 출력이 "최종 출력" 으로 간주되는 규칙은, 원하는 타입의 텍스트 출력을 생성하고 도구 호출이 없을 때입니다. + LLM 출력이 "최종 출력" 으로 간주되는 규칙은, 원하는 타입의 텍스트 출력을 생성하고 도구 호출이 없는 경우입니다. ## 스트리밍 -스트리밍을 사용하면 LLM 이 실행되는 동안 스트리밍 이벤트를 추가로 수신할 수 있습니다. 스트림이 끝나면 [`RunResultStreaming`][agents.result.RunResultStreaming] 에는 실행에 대한 완전한 정보와 새로 생성된 모든 출력이 포함됩니다. 스트리밍 이벤트는 `.stream_events()` 로 호출할 수 있습니다. 자세한 내용은 [스트리밍 가이드](streaming.md)를 참고하세요. +스트리밍을 사용하면 LLM 이 실행되는 동안 스트리밍 이벤트를 추가로 수신할 수 있습니다. 스트림이 완료되면 [`RunResultStreaming`][agents.result.RunResultStreaming] 에는 실행에 대한 모든 새로운 출력들을 포함한 전체 정보가 담깁니다. 스트리밍 이벤트는 `.stream_events()` 를 호출해 받을 수 있습니다. 자세한 내용은 [스트리밍 가이드](streaming.md)를 참고하세요. ## 실행 구성 -`run_config` 매개변수로 에이전트 실행에 대한 전역 설정을 구성할 수 있습니다: +`run_config` 매개변수는 에이전트 실행에 대한 전역 설정을 구성합니다: - [`model`][agents.run.RunConfig.model]: 각 Agent 의 `model` 설정과 무관하게 사용할 전역 LLM 모델을 설정합니다. -- [`model_provider`][agents.run.RunConfig.model_provider]: 모델 이름 조회를 위한 모델 공급자이며 기본값은 OpenAI 입니다. +- [`model_provider`][agents.run.RunConfig.model_provider]: 모델 이름을 조회할 모델 제공자이며 기본값은 OpenAI 입니다. - [`model_settings`][agents.run.RunConfig.model_settings]: 에이전트별 설정을 재정의합니다. 예를 들어 전역 `temperature` 또는 `top_p` 를 설정할 수 있습니다. -- [`input_guardrails`][agents.run.RunConfig.input_guardrails], [`output_guardrails`][agents.run.RunConfig.output_guardrails]: 모든 실행에 포함할 입력 또는 출력 가드레일의 리스트입니다. -- [`handoff_input_filter`][agents.run.RunConfig.handoff_input_filter]: 핸드오프에 이미 입력 필터가 없을 경우 모든 핸드오프에 적용할 전역 입력 필터입니다. 입력 필터는 새 에이전트로 전송되는 입력을 편집할 수 있게 합니다. 자세한 내용은 [`Handoff.input_filter`][agents.handoffs.Handoff.input_filter] 문서를 참고하세요. +- [`input_guardrails`][agents.run.RunConfig.input_guardrails], [`output_guardrails`][agents.run.RunConfig.output_guardrails]: 모든 실행에 포함할 입력 또는 출력 가드레일 목록입니다. +- [`handoff_input_filter`][agents.run.RunConfig.handoff_input_filter]: 핸드오프에 이미 지정된 필터가 없는 경우 모든 핸드오프에 적용할 전역 입력 필터입니다. 입력 필터를 사용하면 새 에이전트로 전송되는 입력을 수정할 수 있습니다. 자세한 내용은 [`Handoff.input_filter`][agents.handoffs.Handoff.input_filter] 문서를 참고하세요. - [`tracing_disabled`][agents.run.RunConfig.tracing_disabled]: 전체 실행에 대해 [트레이싱](tracing.md) 을 비활성화할 수 있습니다. -- [`trace_include_sensitive_data`][agents.run.RunConfig.trace_include_sensitive_data]: LLM 및 도구 호출의 입력/출력과 같은 민감할 수 있는 데이터를 트레이스에 포함할지 구성합니다. -- [`workflow_name`][agents.run.RunConfig.workflow_name], [`trace_id`][agents.run.RunConfig.trace_id], [`group_id`][agents.run.RunConfig.group_id]: 실행에 대한 트레이싱 워크플로 이름, 트레이스 ID, 트레이스 그룹 ID 를 설정합니다. 최소한 `workflow_name` 설정을 권장합니다. 그룹 ID 는 선택 필드로 여러 실행에 걸쳐 트레이스를 연결할 수 있습니다. +- [`trace_include_sensitive_data`][agents.run.RunConfig.trace_include_sensitive_data]: LLM 및 도구 호출 입출력과 같은 잠재적으로 민감한 데이터가 트레이스에 포함될지 여부를 설정합니다. +- [`workflow_name`][agents.run.RunConfig.workflow_name], [`trace_id`][agents.run.RunConfig.trace_id], [`group_id`][agents.run.RunConfig.group_id]: 실행에 대한 트레이싱 워크플로 이름, 트레이스 ID, 트레이스 그룹 ID 를 설정합니다. 최소한 `workflow_name` 설정을 권장합니다. 그룹 ID 는 선택 사항으로 여러 실행 간 트레이스를 연결할 수 있습니다. - [`trace_metadata`][agents.run.RunConfig.trace_metadata]: 모든 트레이스에 포함할 메타데이터입니다. ## 대화/채팅 스레드 -어떤 run 메서드를 호출하든 하나 이상의 에이전트가 실행될 수 있습니다(즉, 하나 이상의 LLM 호출). 하지만 이는 채팅 대화에서 하나의 논리적 턴을 의미합니다. 예: +어떤 run 메서드를 호출하더라도 하나 이상의 에이전트 실행(즉, 하나 이상의 LLM 호출)로 이어질 수 있지만, 이는 채팅 대화에서 단일 논리적 턴을 의미합니다. 예: 1. 사용자 턴: 사용자가 텍스트 입력 -2. Runner 실행: 첫 번째 에이전트가 LLM 을 호출하고 도구를 실행하며 두 번째 에이전트로 핸드오프, 두 번째 에이전트가 더 많은 도구를 실행한 뒤 출력을 생성 +2. Runner 실행: 첫 번째 에이전트가 LLM 을 호출하고 도구를 실행하며 두 번째 에이전트로 핸드오프, 두 번째 에이전트가 더 많은 도구를 실행한 후 출력을 생성 -에이전트 실행이 끝나면 사용자에게 무엇을 보여줄지 선택할 수 있습니다. 예를 들어 에이전트가 생성한 모든 새 아이템을 보여주거나 최종 출력만 보여줄 수 있습니다. 어느 쪽이든, 사용자가 후속 질문을 할 수 있으며, 이 경우 run 메서드를 다시 호출하면 됩니다. +에이전트 실행이 끝나면 사용자에게 무엇을 보여줄지 선택할 수 있습니다. 예를 들어 에이전트가 생성한 모든 새 항목을 보여주거나 최종 출력만 보여줄 수 있습니다. 어느 쪽이든 사용자가 후속 질문을 할 수 있고, 그 경우 run 메서드를 다시 호출하면 됩니다. ### 수동 대화 관리 @@ -93,7 +93,7 @@ async def main(): ### Sessions 를 통한 자동 대화 관리 -더 간단한 방법으로, [Sessions](sessions.md) 를 사용하면 `.to_input_list()` 를 수동으로 호출하지 않고도 대화 기록을 자동으로 처리할 수 있습니다: +더 간단한 방법으로, [Sessions](sessions/index.md) 를 사용하여 `.to_input_list()` 를 수동으로 호출하지 않고도 대화 기록을 자동으로 처리할 수 있습니다: ```python from agents import Agent, Runner, SQLiteSession @@ -117,24 +117,24 @@ async def main(): # California ``` -Sessions 는 자동으로 다음을 수행합니다: +Sessions 는 다음을 자동으로 수행합니다: -- 매 실행 전 대화 기록을 조회 -- 매 실행 후 새 메시지를 저장 -- 서로 다른 세션 ID 별로 분리된 대화를 유지 +- 각 실행 전에 대화 기록을 가져옴 +- 각 실행 후 새 메시지를 저장함 +- 서로 다른 세션 ID 에 대해 분리된 대화를 유지함 -자세한 내용은 [Sessions 문서](sessions.md)를 참고하세요. +자세한 내용은 [Sessions 문서](sessions/index.md)를 참고하세요. ### 서버 관리 대화 -`to_input_list()` 또는 `Sessions` 로 로컬에서 관리하는 대신, OpenAI 대화 상태 기능에 서버 측 대화 상태 관리를 맡길 수도 있습니다. 이렇게 하면 과거 메시지를 모두 수동으로 다시 보내지 않고도 대화 기록을 보존할 수 있습니다. 자세한 내용은 [OpenAI Conversation state 가이드](https://platform.openai.com/docs/guides/conversation-state?api-mode=responses)를 참고하세요. +`to_input_list()` 또는 `Sessions` 로 로컬에서 처리하는 대신 OpenAI 대화 상태 기능에 대화 상태 관리를 서버 측에서 맡길 수도 있습니다. 이를 통해 모든 과거 메시지를 수동으로 다시 전송하지 않고도 대화 기록을 보존할 수 있습니다. 자세한 내용은 [OpenAI Conversation state 가이드](https://platform.openai.com/docs/guides/conversation-state?api-mode=responses)를 참고하세요. -OpenAI 는 여러 턴에 걸친 상태 추적을 두 가지 방식으로 제공합니다: +OpenAI 는 턴을 넘나드는 상태를 추적하는 두 가지 방법을 제공합니다: #### 1. `conversation_id` 사용 -먼저 OpenAI Conversations API 를 사용해 대화를 생성한 뒤, 이후 모든 호출에서 해당 ID 를 재사용합니다: +먼저 OpenAI Conversations API 를 사용해 대화를 생성한 다음 이후 모든 호출에 해당 ID 를 재사용합니다: ```python from agents import Agent, Runner @@ -190,18 +190,18 @@ async def main(): ``` -## 장기 실행 에이전트 및 휴먼인더루프 +## 장기 실행 에이전트 및 휴먼인더루프 (HITL) -Agents SDK 의 [Temporal](https://temporal.io/) 통합을 사용하면 휴먼인더루프 (HITL) 작업을 포함한 내구성 있는 장기 실행 워크플로를 운영할 수 있습니다. Temporal 과 Agents SDK 가 함께 장기 실행 작업을 완료하는 데모는 [이 영상](https://www.youtube.com/watch?v=fFBZqzT4DD8)에서 확인하고, [여기 문서](https://github.com/temporalio/sdk-python/tree/main/temporalio/contrib/openai_agents)도 참고하세요. +Agents SDK 의 [Temporal](https://temporal.io/) 통합을 사용하면 휴먼인더루프 작업을 포함한 내구성 있는 장기 실행 워크플로를 실행할 수 있습니다. 장기 실행 작업을 완료하기 위해 Temporal 과 Agents SDK 가 함께 동작하는 데모는 [이 영상](https://www.youtube.com/watch?v=fFBZqzT4DD8)에서 볼 수 있으며, [문서는 여기](https://github.com/temporalio/sdk-python/tree/main/temporalio/contrib/openai_agents)에서 확인하세요. ## 예외 SDK 는 특정 경우에 예외를 발생시킵니다. 전체 목록은 [`agents.exceptions`][] 에 있습니다. 개요는 다음과 같습니다: -- [`AgentsException`][agents.exceptions.AgentsException]: SDK 내에서 발생하는 모든 예외의 기본 클래스입니다. 다른 모든 구체적 예외가 파생되는 일반적 타입입니다. -- [`MaxTurnsExceeded`][agents.exceptions.MaxTurnsExceeded]: 에이전트 실행이 `max_turns` 한도를 초과하여 `Runner.run`, `Runner.run_sync`, `Runner.run_streamed` 메서드에서 발생합니다. 지정된 상호작용 횟수 내에 에이전트가 작업을 완료하지 못했음을 나타냅니다. -- [`ModelBehaviorError`][agents.exceptions.ModelBehaviorError]: 기본 모델(LLM) 이 예기치 않거나 잘못된 출력을 생성할 때 발생합니다. 예를 들면 다음을 포함할 수 있습니다: - - 잘못된 JSON: 특히 특정 `output_type` 이 정의된 경우, 도구 호출용 또는 직접 출력으로 잘못된 JSON 구조를 제공하는 경우 - - 예기치 않은 도구 관련 실패: 모델이 예상 방식으로 도구를 사용하지 못한 경우 -- [`UserError`][agents.exceptions.UserError]: SDK 를 사용하는 코드 작성자인 귀하가 SDK 사용 중 오류를 범했을 때 발생합니다. 일반적으로 잘못된 코드 구현, 유효하지 않은 구성, SDK API 오사용에서 비롯됩니다. -- [`InputGuardrailTripwireTriggered`][agents.exceptions.InputGuardrailTripwireTriggered], [`OutputGuardrailTripwireTriggered`][agents.exceptions.OutputGuardrailTripwireTriggered]: 각각 입력 가드레일 또는 출력 가드레일 조건이 충족될 때 발생합니다. 입력 가드레일은 처리 전에 들어오는 메시지를 확인하고, 출력 가드레일은 전달 전에 에이전트의 최종 응답을 확인합니다. \ No newline at end of file +- [`AgentsException`][agents.exceptions.AgentsException]: SDK 내에서 발생하는 모든 예외의 기본 클래스입니다. 다른 모든 구체적인 예외가 파생되는 일반 타입의 역할을 합니다. +- [`MaxTurnsExceeded`][agents.exceptions.MaxTurnsExceeded]: 에이전트의 실행이 `max_turns` 제한을 초과하여 `Runner.run`, `Runner.run_sync`, 또는 `Runner.run_streamed` 메서드에서 발생하는 예외입니다. 이는 에이전트가 지정된 상호작용 횟수 내에 작업을 완료하지 못했음을 나타냅니다. +- [`ModelBehaviorError`][agents.exceptions.ModelBehaviorError]: 기반 모델(LLM) 이 예상치 못한 또는 유효하지 않은 출력을 생성할 때 발생하는 예외입니다. 다음을 포함할 수 있습니다: + - 잘못된 JSON: 특히 특정 `output_type` 이 정의된 경우, 도구 호출 또는 직접 출력에서 모델이 잘못된 JSON 구조를 제공하는 경우 + - 예상치 못한 도구 관련 실패: 모델이 도구를 예상한 방식으로 사용하지 못하는 경우 +- [`UserError`][agents.exceptions.UserError]: SDK 를 사용하는 코드 작성자(당신) 가 SDK 사용 중 오류를 저질렀을 때 발생하는 예외입니다. 일반적으로 잘못된 코드 구현, 잘못된 구성, SDK API 오용에서 비롯됩니다. +- [`InputGuardrailTripwireTriggered`][agents.exceptions.InputGuardrailTripwireTriggered], [`OutputGuardrailTripwireTriggered`][agents.exceptions.OutputGuardrailTripwireTriggered]: 각각 입력 가드레일 또는 출력 가드레일의 조건이 충족될 때 발생하는 예외입니다. 입력 가드레일은 처리 전에 들어오는 메시지를 검사하고, 출력 가드레일은 전달 전에 에이전트의 최종 응답을 검사합니다. \ No newline at end of file diff --git a/docs/ko/sessions.md b/docs/ko/sessions.md index e669acf85..ddc452633 100644 --- a/docs/ko/sessions.md +++ b/docs/ko/sessions.md @@ -4,9 +4,9 @@ search: --- # 세션 -Agents SDK 는 여러 에이전트 실행(run) 간에 대화 기록을 자동으로 유지하는 내장 세션 메모리를 제공합니다. 이를 통해 턴 사이에 `.to_input_list()` 를 수동으로 처리할 필요가 없습니다. +Agents SDK는 여러 에이전트 실행(run) 간 대화 기록을 자동으로 유지하는 내장 세션 메모리를 제공합니다. 이를 통해 턴 사이에 `.to_input_list()`를 수동으로 처리할 필요가 없습니다. -세션은 특정 세션의 대화 기록을 저장하여, 에이전트가 명시적인 수동 메모리 관리 없이도 컨텍스트를 유지할 수 있게 합니다. 이는 에이전트가 이전 상호작용을 기억해야 하는 채팅 애플리케이션이나 멀티턴 대화를 구축할 때 특히 유용합니다. +세션은 특정 세션의 대화 기록을 저장하여, 에이전트가 명시적인 수동 메모리 관리 없이도 컨텍스트를 유지할 수 있도록 합니다. 이는 이전 상호작용을 기억해야 하는 채팅 애플리케이션 또는 멀티 턴 대화를 구축할 때 특히 유용합니다. ## 빠른 시작 @@ -52,16 +52,16 @@ print(result.final_output) # "Approximately 39 million" 세션 메모리가 활성화되면: 1. **각 실행 전**: 러너가 세션의 대화 기록을 자동으로 가져와 입력 항목 앞에 추가합니다 -2. **각 실행 후**: 실행 중에 생성된 모든 새 항목(사용자 입력, 어시스턴트 응답, 도구 호출 등)이 자동으로 세션에 저장됩니다 -3. **컨텍스트 유지**: 동일한 세션으로 이후 실행 시 전체 대화 기록이 포함되어 에이전트가 컨텍스트를 유지할 수 있습니다 +2. **각 실행 후**: 실행 중 생성된 모든 새 항목(사용자 입력, 어시스턴트 응답, 도구 호출 등)이 자동으로 세션에 저장됩니다 +3. **컨텍스트 보존**: 동일한 세션으로 이어지는 이후 실행에는 전체 대화 기록이 포함되어 에이전트가 컨텍스트를 유지할 수 있습니다 -이로써 `.to_input_list()` 를 수동으로 호출하고 실행 간 상태를 관리할 필요가 없어집니다. +이를 통해 `.to_input_list()`를 수동으로 호출하고 실행 간 대화 상태를 관리할 필요가 없어집니다. ## 메모리 작업 ### 기본 작업 -세션은 대화 기록을 관리하기 위한 여러 작업을 지원합니다: +세션은 대화 기록 관리를 위한 여러 작업을 지원합니다: ```python from agents import SQLiteSession @@ -86,9 +86,9 @@ print(last_item) # {"role": "assistant", "content": "Hi there!"} await session.clear_session() ``` -### 수정에 pop_item 사용 +### 수정 시 pop_item 사용 -`pop_item` 메서드는 대화에서 마지막 항목을 되돌리거나 수정하고자 할 때 특히 유용합니다: +`pop_item` 메서드는 대화에서 마지막 항목을 취소하거나 수정하고 싶을 때 특히 유용합니다: ```python from agents import Agent, Runner, SQLiteSession @@ -129,7 +129,7 @@ result = await Runner.run(agent, "Hello") ### OpenAI Conversations API 메모리 자체 데이터베이스를 관리하지 않고 -[대화 상태](https://platform.openai.com/docs/guides/conversation-state?api-mode=responses#using-the-conversations-api)를 지속하려면 [OpenAI Conversations API](https://platform.openai.com/docs/api-reference/conversations/create)를 사용하세요. 이는 대화 기록 저장을 위해 OpenAI 가 호스팅하는 인프라에 이미 의존하고 있을 때 유용합니다. +[대화 상태](https://platform.openai.com/docs/guides/conversation-state?api-mode=responses#using-the-conversations-api)를 지속하려면 [OpenAI Conversations API](https://platform.openai.com/docs/api-reference/conversations/create)를 사용하세요. 이는 대화 기록 저장을 위해 OpenAI 호스트하는 인프라에 이미 의존하는 경우에 유용합니다. ```python from agents import OpenAIConversationsSession @@ -190,9 +190,9 @@ result2 = await Runner.run( ### SQLAlchemy 기반 세션 -더 고급 사용 사례의 경우, SQLAlchemy 기반 세션 백엔드를 사용할 수 있습니다. 이를 통해 SQLAlchemy 가 지원하는 모든 데이터베이스(PostgreSQL, MySQL, SQLite 등)를 세션 저장소로 사용할 수 있습니다. +더 고급 사용 사례의 경우, SQLAlchemy 기반 세션 백엔드를 사용할 수 있습니다. 이를 통해 SQLAlchemy가 지원하는 모든 데이터베이스(PostgreSQL, MySQL, SQLite 등)를 세션 저장소로 사용할 수 있습니다. -**예제 1: `from_url` 을 사용한 인메모리 SQLite** +**예시 1: 메모리 내 SQLite와 `from_url` 사용** 개발 및 테스트에 적합한 가장 간단한 시작 방법입니다. @@ -215,9 +215,9 @@ if __name__ == "__main__": asyncio.run(main()) ``` -**예제 2: 기존 SQLAlchemy 엔진 사용** +**예시 2: 기존 SQLAlchemy 엔진 사용** -프로덕션 애플리케이션에서는 이미 SQLAlchemy `AsyncEngine` 인스턴스를 보유하고 있을 가능성이 큽니다. 이를 세션에 직접 전달할 수 있습니다. +프로덕션 애플리케이션에서는 이미 SQLAlchemy `AsyncEngine` 인스턴스를 가지고 있을 수 있습니다. 이를 세션에 직접 전달할 수 있습니다. ```python import asyncio @@ -247,11 +247,11 @@ if __name__ == "__main__": ### 암호화된 세션 -보관 중인 대화 데이터의 암호화가 필요한 애플리케이션의 경우, `EncryptedSession` 을 사용해 어떤 세션 백엔드든 투명한 암호화와 자동 TTL 기반 만료로 래핑할 수 있습니다. 이를 위해 `encrypt` extra 가 필요합니다: `pip install openai-agents[encrypt]`. +보관 중인 대화 데이터를 암호화해야 하는 애플리케이션의 경우, `EncryptedSession`을 사용해 투명한 암호화와 자동 TTL 기반 만료로 어떤 세션 백엔드든 래핑할 수 있습니다. `encrypt` extra가 필요합니다: `pip install openai-agents[encrypt]`. -`EncryptedSession` 은 세션별 키 유도(HKDF)를 사용하는 Fernet 암호화를 적용하며, 오래된 메시지의 자동 만료를 지원합니다. 항목이 TTL 을 초과하면 조회 시 조용히 건너뜁니다. +`EncryptedSession`은 세션별 키 유도(HKDF)를 사용하는 Fernet 암호화를 사용하며, 오래된 메시지의 자동 만료를 지원합니다. 항목이 TTL을 초과하면 검색 시 조용히 건너뜁니다. -**예제: SQLAlchemy 세션 데이터 암호화** +**예시: SQLAlchemy 세션 데이터 암호화** ```python import asyncio @@ -284,20 +284,20 @@ if __name__ == "__main__": **주요 기능:** -- **투명한 암호화**: 저장 전 모든 세션 항목을 자동으로 암호화하고 조회 시 복호화 -- **세션별 키 유도**: 세션 ID 를 소금값(salt)으로 하는 HKDF 로 고유한 암호화 키 생성 -- **TTL 기반 만료**: 구성 가능한 time-to-live(기본: 10분)를 기준으로 오래된 메시지를 자동 만료 +- **투명한 암호화**: 저장 전 모든 세션 항목을 자동으로 암호화하고, 검색 시 복호화 +- **세션별 키 유도**: 세션 ID를 솔트로 사용하는 HKDF로 고유한 암호화 키 생성 +- **TTL 기반 만료**: 구성 가능한 TTL(기본값: 10분)에 따라 오래된 메시지를 자동 만료 - **유연한 키 입력**: Fernet 키 또는 원문 문자열을 암호화 키로 허용 -- **任의 세션 래핑**: SQLite, SQLAlchemy 또는 커스텀 세션 구현과 함께 사용 가능 +- **어떤 세션이든 래핑**: SQLite, SQLAlchemy 또는 커스텀 세션 구현과 호환 -!!! warning "중요한 보안 참고 사항" +!!! warning "중요한 보안 참고" - - 암호화 키를 안전하게 보관하세요(예: 환경 변수, 시크릿 매니저) - - 만료된 토큰은 애플리케이션 서버의 시스템 시계를 기준으로 거부됩니다 - 유효한 토큰이 시계 드리프트로 인해 거부되지 않도록 모든 서버가 NTP 로 시간 동기화되어 있는지 확인하세요 - - 기본 세션에는 여전히 암호화된 데이터가 저장되므로 데이터베이스 인프라에 대한 통제권을 유지할 수 있습니다 + - 암호화 키를 안전하게 저장하세요(예: 환경 변수, 시크릿 매니저) + - 만료된 토큰은 애플리케이션 서버의 시스템 시계를 기준으로 거부됩니다 - 유효한 토큰이 시계 드리프트로 인해 거부되지 않도록 모든 서버가 NTP로 시간 동기화되어 있는지 확인하세요 + - 기본 세션은 여전히 암호화된 데이터를 저장하므로 데이터베이스 인프라에 대한 제어권을 유지합니다 -## 사용자 정의 메모리 구현 +## 커스텀 메모리 구현 [`Session`][agents.memory.session.Session] 프로토콜을 따르는 클래스를 생성하여 자체 세션 메모리를 구현할 수 있습니다: @@ -344,9 +344,9 @@ result = await Runner.run( ## 세션 관리 -### 세션 ID 명명 +### 세션 ID 네이밍 -대화 정리에 도움이 되는 의미 있는 세션 ID 를 사용하세요: +대화를 체계적으로 구성할 수 있는 의미 있는 세션 ID를 사용하세요: - 사용자 기반: `"user_12345"` - 스레드 기반: `"thread_abc123"` @@ -354,11 +354,11 @@ result = await Runner.run( ### 메모리 지속성 -- 임시 대화에는 인메모리 SQLite(`SQLiteSession("session_id")`) 사용 -- 영구 대화에는 파일 기반 SQLite(`SQLiteSession("session_id", "path/to/db.sqlite")`) 사용 -- SQLAlchemy 가 지원하는 기존 데이터베이스가 있는 프로덕션 시스템에는 SQLAlchemy 기반 세션(`SQLAlchemySession("session_id", engine=engine, create_tables=True)`) 사용 -- OpenAI Conversations API 에 기록을 저장하기를 원할 때는 OpenAI 가 호스팅하는 저장소(`OpenAIConversationsSession()`) 사용 -- 투명한 암호화와 TTL 기반 만료가 필요한 경우 암호화된 세션(`EncryptedSession(session_id, underlying_session, encryption_key)`)으로 어떤 세션이든 래핑 +- 임시 대화에는 메모리 내 SQLite(`SQLiteSession("session_id")`) 사용 +- 지속형 대화에는 파일 기반 SQLite(`SQLiteSession("session_id", "path/to/db.sqlite")`) 사용 +- SQLAlchemy가 지원하는 기존 데이터베이스가 있는 프로덕션 시스템에는 SQLAlchemy 기반 세션(`SQLAlchemySession("session_id", engine=engine, create_tables=True)`) 사용 +- 기록을 OpenAI Conversations API에 저장하기를 원하면 OpenAI 호스트하는 스토리지(`OpenAIConversationsSession()`) 사용 +- 투명한 암호화와 TTL 기반 만료를 위해 어떤 세션이든 래핑하려면 암호화된 세션(`EncryptedSession(session_id, underlying_session, encryption_key)`) 사용 - 더 고급 사용 사례를 위해 다른 프로덕션 시스템(Redis, Django 등)에 대한 커스텀 세션 백엔드 구현 고려 ### 세션 관리 @@ -385,9 +385,9 @@ result2 = await Runner.run( ) ``` -## 전체 예제 +## 전체 예시 -다음은 세션 메모리가 실제로 동작하는 전체 예제입니다: +다음은 세션 메모리가 작동하는 방식을 보여주는 전체 예시입니다: ```python import asyncio @@ -449,12 +449,12 @@ if __name__ == "__main__": asyncio.run(main()) ``` -## API 참조 +## API 레퍼런스 -자세한 API 문서는 다음을 참조하세요: +자세한 API 문서는 다음을 참고하세요: - [`Session`][agents.memory.Session] - 프로토콜 인터페이스 - [`SQLiteSession`][agents.memory.SQLiteSession] - SQLite 구현 - [`OpenAIConversationsSession`](ref/memory/openai_conversations_session.md) - OpenAI Conversations API 구현 - [`SQLAlchemySession`][agents.extensions.memory.sqlalchemy_session.SQLAlchemySession] - SQLAlchemy 기반 구현 -- [`EncryptedSession`][agents.extensions.memory.encrypt_session.EncryptedSession] - TTL 이 포함된 암호화 세션 래퍼 \ No newline at end of file +- [`EncryptedSession`][agents.extensions.memory.encrypt_session.EncryptedSession] - TTL이 포함된 암호화 세션 래퍼 \ No newline at end of file diff --git a/docs/ko/sessions/advanced_sqlite_session.md b/docs/ko/sessions/advanced_sqlite_session.md new file mode 100644 index 000000000..76263f8c0 --- /dev/null +++ b/docs/ko/sessions/advanced_sqlite_session.md @@ -0,0 +1,307 @@ +--- +search: + exclude: true +--- +# 고급 SQLite 세션 + +`AdvancedSQLiteSession`은 기본 `SQLiteSession`을 확장한 버전으로, 대화 분기, 상세 사용량 분석, 구조화된 대화 쿼리 등 고급 대화 관리 기능을 제공합니다. + +## 기능 + +- **대화 분기**: 임의의 사용자 메시지에서 대체 대화 경로 생성 +- **사용량 추적**: 각 턴별 토큰 사용량을 JSON 상세 내역과 함께 제공 +- **구조화된 쿼리**: 턴별 대화 조회, 도구 사용 통계 등 +- **분기 관리**: 독립적인 분기 전환 및 관리 +- **메시지 구조 메타데이터**: 메시지 유형, 도구 사용, 대화 흐름 추적 + +## 빠른 시작 + +```python +from agents import Agent, Runner +from agents.extensions.memory import AdvancedSQLiteSession + +# Create agent +agent = Agent( + name="Assistant", + instructions="Reply very concisely.", +) + +# Create an advanced session +session = AdvancedSQLiteSession( + session_id="conversation_123", + db_path="conversations.db", + create_tables=True +) + +# First conversation turn +result = await Runner.run( + agent, + "What city is the Golden Gate Bridge in?", + session=session +) +print(result.final_output) # "San Francisco" + +# IMPORTANT: Store usage data +await session.store_run_usage(result) + +# Continue conversation +result = await Runner.run( + agent, + "What state is it in?", + session=session +) +print(result.final_output) # "California" +await session.store_run_usage(result) +``` + +## 초기화 + +```python +from agents.extensions.memory import AdvancedSQLiteSession + +# Basic initialization +session = AdvancedSQLiteSession( + session_id="my_conversation", + create_tables=True # Auto-create advanced tables +) + +# With persistent storage +session = AdvancedSQLiteSession( + session_id="user_123", + db_path="path/to/conversations.db", + create_tables=True +) + +# With custom logger +import logging +logger = logging.getLogger("my_app") +session = AdvancedSQLiteSession( + session_id="session_456", + create_tables=True, + logger=logger +) +``` + +### 매개변수 + +- `session_id` (str): 대화 세션의 고유 식별자 +- `db_path` (str | Path): SQLite 데이터베이스 파일 경로. 인메모리 저장소의 경우 기본값은 `:memory:` +- `create_tables` (bool): 고급 테이블을 자동으로 생성할지 여부. 기본값은 `False` +- `logger` (logging.Logger | None): 세션에 사용할 사용자 정의 로거. 기본값은 모듈 로거 + +## 사용량 추적 + +AdvancedSQLiteSession은 대화의 각 턴마다 토큰 사용량 데이터를 저장하여 상세 사용량 분석을 제공합니다. **이는 각 에이전트 실행 후 `store_run_usage` 메서드를 호출하는 것에 전적으로 의존합니다.** + +### 사용량 데이터 저장 + +```python +# After each agent run, store the usage data +result = await Runner.run(agent, "Hello", session=session) +await session.store_run_usage(result) + +# This stores: +# - Total tokens used +# - Input/output token breakdown +# - Request count +# - Detailed JSON token information (if available) +``` + +### 사용량 통계 조회 + +```python +# Get session-level usage (all branches) +session_usage = await session.get_session_usage() +if session_usage: + print(f"Total requests: {session_usage['requests']}") + print(f"Total tokens: {session_usage['total_tokens']}") + print(f"Input tokens: {session_usage['input_tokens']}") + print(f"Output tokens: {session_usage['output_tokens']}") + print(f"Total turns: {session_usage['total_turns']}") + +# Get usage for specific branch +branch_usage = await session.get_session_usage(branch_id="main") + +# Get usage by turn +turn_usage = await session.get_turn_usage() +for turn_data in turn_usage: + print(f"Turn {turn_data['user_turn_number']}: {turn_data['total_tokens']} tokens") + if turn_data['input_tokens_details']: + print(f" Input details: {turn_data['input_tokens_details']}") + if turn_data['output_tokens_details']: + print(f" Output details: {turn_data['output_tokens_details']}") + +# Get usage for specific turn +turn_2_usage = await session.get_turn_usage(user_turn_number=2) +``` + +## 대화 분기 + +AdvancedSQLiteSession의 핵심 기능 중 하나는 임의의 사용자 메시지로부터 대화 분기를 생성하여 대체 대화 경로를 탐색할 수 있는 능력입니다. + +### 분기 생성 + +```python +# Get available turns for branching +turns = await session.get_conversation_turns() +for turn in turns: + print(f"Turn {turn['turn']}: {turn['content']}") + print(f"Can branch: {turn['can_branch']}") + +# Create a branch from turn 2 +branch_id = await session.create_branch_from_turn(2) +print(f"Created branch: {branch_id}") + +# Create a branch with custom name +branch_id = await session.create_branch_from_turn( + 2, + branch_name="alternative_path" +) + +# Create branch by searching for content +branch_id = await session.create_branch_from_content( + "weather", + branch_name="weather_focus" +) +``` + +### 분기 관리 + +```python +# List all branches +branches = await session.list_branches() +for branch in branches: + current = " (current)" if branch["is_current"] else "" + print(f"{branch['branch_id']}: {branch['user_turns']} turns, {branch['message_count']} messages{current}") + +# Switch between branches +await session.switch_to_branch("main") +await session.switch_to_branch(branch_id) + +# Delete a branch +await session.delete_branch(branch_id, force=True) # force=True allows deleting current branch +``` + +### 분기 워크플로 예시 + +```python +# Original conversation +result = await Runner.run(agent, "What's the capital of France?", session=session) +await session.store_run_usage(result) + +result = await Runner.run(agent, "What's the weather like there?", session=session) +await session.store_run_usage(result) + +# Create branch from turn 2 (weather question) +branch_id = await session.create_branch_from_turn(2, "weather_focus") + +# Continue in new branch with different question +result = await Runner.run( + agent, + "What are the main tourist attractions in Paris?", + session=session +) +await session.store_run_usage(result) + +# Switch back to main branch +await session.switch_to_branch("main") + +# Continue original conversation +result = await Runner.run( + agent, + "How expensive is it to visit?", + session=session +) +await session.store_run_usage(result) +``` + +## 구조화된 쿼리 + +AdvancedSQLiteSession은 대화의 구조와 내용을 분석하기 위한 여러 메서드를 제공합니다. + +### 대화 분석 + +```python +# Get conversation organized by turns +conversation_by_turns = await session.get_conversation_by_turns() +for turn_num, items in conversation_by_turns.items(): + print(f"Turn {turn_num}: {len(items)} items") + for item in items: + if item["tool_name"]: + print(f" - {item['type']} (tool: {item['tool_name']})") + else: + print(f" - {item['type']}") + +# Get tool usage statistics +tool_usage = await session.get_tool_usage() +for tool_name, count, turn in tool_usage: + print(f"{tool_name}: used {count} times in turn {turn}") + +# Find turns by content +matching_turns = await session.find_turns_by_content("weather") +for turn in matching_turns: + print(f"Turn {turn['turn']}: {turn['content']}") +``` + +### 메시지 구조 + +세션은 다음을 포함하여 메시지 구조를 자동으로 추적합니다: + +- 메시지 유형 (user, assistant, tool_call 등) +- 도구 호출의 도구 이름 +- 턴 번호와 시퀀스 번호 +- 분기 연관 +- 타임스탬프 + +## 데이터베이스 스키마 + +AdvancedSQLiteSession은 기본 SQLite 스키마를 확장하여 두 개의 추가 테이블을 제공합니다: + +### message_structure 테이블 + +```sql +CREATE TABLE message_structure ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + session_id TEXT NOT NULL, + message_id INTEGER NOT NULL, + branch_id TEXT NOT NULL DEFAULT 'main', + message_type TEXT NOT NULL, + sequence_number INTEGER NOT NULL, + user_turn_number INTEGER, + branch_turn_number INTEGER, + tool_name TEXT, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (session_id) REFERENCES agent_sessions(session_id) ON DELETE CASCADE, + FOREIGN KEY (message_id) REFERENCES agent_messages(id) ON DELETE CASCADE +); +``` + +### turn_usage 테이블 + +```sql +CREATE TABLE turn_usage ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + session_id TEXT NOT NULL, + branch_id TEXT NOT NULL DEFAULT 'main', + user_turn_number INTEGER NOT NULL, + requests INTEGER DEFAULT 0, + input_tokens INTEGER DEFAULT 0, + output_tokens INTEGER DEFAULT 0, + total_tokens INTEGER DEFAULT 0, + input_tokens_details JSON, + output_tokens_details JSON, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (session_id) REFERENCES agent_sessions(session_id) ON DELETE CASCADE, + UNIQUE(session_id, branch_id, user_turn_number) +); +``` + +## 전체 예제 + +모든 기능을 종합적으로 보여주는 [완전한 예제](https://github.com/openai/openai-agents-python/tree/main/examples/memory/advanced_sqlite_session_example.py)를 확인하세요. + + +## API 레퍼런스 + +- [`AdvancedSQLiteSession`][agents.extensions.memory.advanced_sqlite_session.AdvancedSQLiteSession] - 메인 클래스 +- [`Session`][agents.memory.session.Session] - 기본 세션 프로토콜 \ No newline at end of file diff --git a/docs/ko/sessions/encrypted_session.md b/docs/ko/sessions/encrypted_session.md new file mode 100644 index 000000000..1e9fcdab2 --- /dev/null +++ b/docs/ko/sessions/encrypted_session.md @@ -0,0 +1,179 @@ +--- +search: + exclude: true +--- +# 암호화된 세션 + +`EncryptedSession`은 모든 세션 구현에 대해 투명한 암호화를 제공하며, 대화 데이터를 보호하고 오래된 항목을 자동으로 만료합니다. + +## 기능 + +- **투명한 암호화**: 모든 세션을 Fernet 암호화로 래핑 +- **세션별 키**: 세션마다 고유한 암호화를 위해 HKDF 키 파생 사용 +- **자동 만료**: TTL이 만료되면 오래된 항목을 조용히 건너뜀 +- **대체 가능**: 기존 세션 구현과 함께 작동 + +## 설치 + +암호화된 세션을 사용하려면 `encrypt` extra가 필요합니다: + +```bash +pip install openai-agents[encrypt] +``` + +## 빠른 시작 + +```python +import asyncio +from agents import Agent, Runner +from agents.extensions.memory import EncryptedSession, SQLAlchemySession + +async def main(): + agent = Agent("Assistant") + + # Create underlying session + underlying_session = SQLAlchemySession.from_url( + "user-123", + url="sqlite+aiosqlite:///:memory:", + create_tables=True + ) + + # Wrap with encryption + session = EncryptedSession( + session_id="user-123", + underlying_session=underlying_session, + encryption_key="your-secret-key-here", + ttl=600 # 10 minutes + ) + + result = await Runner.run(agent, "Hello", session=session) + print(result.final_output) + +if __name__ == "__main__": + asyncio.run(main()) +``` + +## 구성 + +### 암호화 키 + +암호화 키는 Fernet 키 또는 임의의 문자열일 수 있습니다: + +```python +from agents.extensions.memory import EncryptedSession + +# Using a Fernet key (base64-encoded) +session = EncryptedSession( + session_id="user-123", + underlying_session=underlying_session, + encryption_key="your-fernet-key-here", + ttl=600 +) + +# Using a raw string (will be derived to a key) +session = EncryptedSession( + session_id="user-123", + underlying_session=underlying_session, + encryption_key="my-secret-password", + ttl=600 +) +``` + +### TTL (Time To Live) + +암호화된 항목이 유효한 기간을 설정합니다: + +```python +# Items expire after 1 hour +session = EncryptedSession( + session_id="user-123", + underlying_session=underlying_session, + encryption_key="secret", + ttl=3600 # 1 hour in seconds +) + +# Items expire after 1 day +session = EncryptedSession( + session_id="user-123", + underlying_session=underlying_session, + encryption_key="secret", + ttl=86400 # 24 hours in seconds +) +``` + +## 다양한 세션 유형과의 사용 + +### SQLite 세션 사용 + +```python +from agents import SQLiteSession +from agents.extensions.memory import EncryptedSession + +# Create encrypted SQLite session +underlying = SQLiteSession("user-123", "conversations.db") + +session = EncryptedSession( + session_id="user-123", + underlying_session=underlying, + encryption_key="secret-key" +) +``` + +### SQLAlchemy 세션 사용 + +```python +from agents.extensions.memory import EncryptedSession, SQLAlchemySession + +# Create encrypted SQLAlchemy session +underlying = SQLAlchemySession.from_url( + "user-123", + url="postgresql+asyncpg://user:pass@localhost/db", + create_tables=True +) + +session = EncryptedSession( + session_id="user-123", + underlying_session=underlying, + encryption_key="secret-key" +) +``` + +!!! warning "고급 세션 기능" + + `EncryptedSession`을 `AdvancedSQLiteSession` 같은 고급 세션 구현과 함께 사용할 때는 다음을 유의하세요: + + - 메시지 콘텐츠가 암호화되므로 `find_turns_by_content()` 같은 메서드는 효과적으로 동작하지 않음 + - 콘텐츠 기반 검색은 암호화된 데이터에서 수행되므로 효율이 제한됨 + + + +## 키 파생 + +EncryptedSession은 세션마다 고유한 암호화 키를 파생하기 위해 HKDF (HMAC 기반 키 파생 함수)를 사용합니다: + +- **마스터 키**: 사용자가 제공한 암호화 키 +- **세션 솔트**: 세션 ID +- **정보 문자열**: `"agents.session-store.hkdf.v1"` +- **출력**: 32바이트 Fernet 키 + +이는 다음을 보장합니다: +- 각 세션은 고유한 암호화 키를 가짐 +- 마스터 키 없이는 키를 파생할 수 없음 +- 서로 다른 세션 간에는 세션 데이터를 복호화할 수 없음 + +## 자동 만료 + +항목이 TTL을 초과하면 검색 중 자동으로 건너뜁니다: + +```python +# Items older than TTL are silently ignored +items = await session.get_items() # Only returns non-expired items + +# Expired items don't affect session behavior +result = await Runner.run(agent, "Continue conversation", session=session) +``` + +## API 참조 + +- [`EncryptedSession`][agents.extensions.memory.encrypt_session.EncryptedSession] - 기본 클래스 +- [`Session`][agents.memory.session.Session] - 기본 세션 프로토콜 \ No newline at end of file diff --git a/docs/ko/sessions/index.md b/docs/ko/sessions/index.md new file mode 100644 index 000000000..8e44c50b7 --- /dev/null +++ b/docs/ko/sessions/index.md @@ -0,0 +1,435 @@ +--- +search: + exclude: true +--- +# 세션 + +Agents SDK 는 여러 에이전트 실행(run) 간에 대화 기록을 자동으로 유지하는 내장 세션 메모리를 제공하여, 턴 사이에 수동으로 `.to_input_list()` 를 처리할 필요를 없애 줍니다. + +세션은 특정 세션의 대화 기록을 저장하여, 에이전트가 명시적인 수동 메모리 관리 없이도 컨텍스트를 유지할 수 있게 합니다. 이는 에이전트가 이전 상호작용을 기억해야 하는 채팅 애플리케이션이나 멀티 턴 대화 구축에 특히 유용합니다. + +## 빠른 시작 + +```python +from agents import Agent, Runner, SQLiteSession + +# Create agent +agent = Agent( + name="Assistant", + instructions="Reply very concisely.", +) + +# Create a session instance with a session ID +session = SQLiteSession("conversation_123") + +# First turn +result = await Runner.run( + agent, + "What city is the Golden Gate Bridge in?", + session=session +) +print(result.final_output) # "San Francisco" + +# Second turn - agent automatically remembers previous context +result = await Runner.run( + agent, + "What state is it in?", + session=session +) +print(result.final_output) # "California" + +# Also works with synchronous runner +result = Runner.run_sync( + agent, + "What's the population?", + session=session +) +print(result.final_output) # "Approximately 39 million" +``` + +## 동작 방식 + +세션 메모리가 활성화되면: + +1. **각 실행 전**: 러너가 세션의 대화 기록을 자동으로 가져와 입력 아이템 앞에 추가합니다 +2. **각 실행 후**: 실행 중에 생성된 모든 새 아이템(사용자 입력, 어시스턴트 응답, 도구 호출 등)이 세션에 자동으로 저장됩니다 +3. **컨텍스트 보존**: 동일한 세션으로 이어지는 각 실행에는 전체 대화 기록이 포함되어 에이전트가 컨텍스트를 유지할 수 있습니다 + +이로써 `.to_input_list()` 를 수동으로 호출하고 실행 사이의 대화 상태를 관리할 필요가 없어집니다. + +## 메모리 작업 + +### 기본 작업 + +세션은 대화 기록을 관리하기 위한 여러 작업을 지원합니다: + +```python +from agents import SQLiteSession + +session = SQLiteSession("user_123", "conversations.db") + +# Get all items in a session +items = await session.get_items() + +# Add new items to a session +new_items = [ + {"role": "user", "content": "Hello"}, + {"role": "assistant", "content": "Hi there!"} +] +await session.add_items(new_items) + +# Remove and return the most recent item +last_item = await session.pop_item() +print(last_item) # {"role": "assistant", "content": "Hi there!"} + +# Clear all items from a session +await session.clear_session() +``` + +### 수정에 pop_item 사용 + +`pop_item` 메서드는 대화에서 마지막 아이템을 취소하거나 수정하고 싶을 때 특히 유용합니다: + +```python +from agents import Agent, Runner, SQLiteSession + +agent = Agent(name="Assistant") +session = SQLiteSession("correction_example") + +# Initial conversation +result = await Runner.run( + agent, + "What's 2 + 2?", + session=session +) +print(f"Agent: {result.final_output}") + +# User wants to correct their question +assistant_item = await session.pop_item() # Remove agent's response +user_item = await session.pop_item() # Remove user's question + +# Ask a corrected question +result = await Runner.run( + agent, + "What's 2 + 3?", + session=session +) +print(f"Agent: {result.final_output}") +``` + +## 세션 유형 + +SDK 는 다양한 사용 사례에 맞춘 여러 세션 구현을 제공합니다: + +### OpenAI Conversations API 세션 + +`OpenAIConversationsSession` 을 통해 [OpenAI's Conversations API](https://platform.openai.com/docs/api-reference/conversations)를 사용하세요. + +```python +from agents import Agent, Runner, OpenAIConversationsSession + +# Create agent +agent = Agent( + name="Assistant", + instructions="Reply very concisely.", +) + +# Create a new conversation +session = OpenAIConversationsSession() + +# Optionally resume a previous conversation by passing a conversation ID +# session = OpenAIConversationsSession(conversation_id="conv_123") + +# Start conversation +result = await Runner.run( + agent, + "What city is the Golden Gate Bridge in?", + session=session +) +print(result.final_output) # "San Francisco" + +# Continue the conversation +result = await Runner.run( + agent, + "What state is it in?", + session=session +) +print(result.final_output) # "California" +``` + +### SQLite 세션 + +기본 제공되는 가벼운 SQLite 기반 세션 구현: + +```python +from agents import SQLiteSession + +# In-memory database (lost when process ends) +session = SQLiteSession("user_123") + +# Persistent file-based database +session = SQLiteSession("user_123", "conversations.db") + +# Use the session +result = await Runner.run( + agent, + "Hello", + session=session +) +``` + +### SQLAlchemy 세션 + +SQLAlchemy 가 지원하는 모든 데이터베이스를 사용할 수 있는 프로덕션급 세션: + +```python +from agents.extensions.memory import SQLAlchemySession + +# Using database URL +session = SQLAlchemySession.from_url( + "user_123", + url="postgresql+asyncpg://user:pass@localhost/db", + create_tables=True +) + +# Using existing engine +from sqlalchemy.ext.asyncio import create_async_engine +engine = create_async_engine("postgresql+asyncpg://user:pass@localhost/db") +session = SQLAlchemySession("user_123", engine=engine, create_tables=True) +``` + +자세한 문서는 [SQLAlchemy 세션](sqlalchemy_session.md)을 참고하세요. + +### 고급 SQLite 세션 + +대화 분기, 사용량 분석, 구조화된 쿼리를 지원하는 향상된 SQLite 세션: + +```python +from agents.extensions.memory import AdvancedSQLiteSession + +# Create with advanced features +session = AdvancedSQLiteSession( + session_id="user_123", + db_path="conversations.db", + create_tables=True +) + +# Automatic usage tracking +result = await Runner.run(agent, "Hello", session=session) +await session.store_run_usage(result) # Track token usage + +# Conversation branching +await session.create_branch_from_turn(2) # Branch from turn 2 +``` + +자세한 문서는 [고급 SQLite 세션](advanced_sqlite_session.md)을 참고하세요. + +### 암호화된 세션 + +어떤 세션 구현에도 사용할 수 있는 투명한 암호화 래퍼: + +```python +from agents.extensions.memory import EncryptedSession, SQLAlchemySession + +# Create underlying session +underlying_session = SQLAlchemySession.from_url( + "user_123", + url="sqlite+aiosqlite:///conversations.db", + create_tables=True +) + +# Wrap with encryption and TTL +session = EncryptedSession( + session_id="user_123", + underlying_session=underlying_session, + encryption_key="your-secret-key", + ttl=600 # 10 minutes +) + +result = await Runner.run(agent, "Hello", session=session) +``` + +자세한 문서는 [암호화된 세션](encrypted_session.md)을 참고하세요. + +## 세션 관리 + +### 세션 ID 네이밍 + +대화를 체계적으로 정리할 수 있도록 의미 있는 세션 ID 를 사용하세요: + +- User 기반: `"user_12345"` +- 스레드 기반: `"thread_abc123"` +- 컨텍스트 기반: `"support_ticket_456"` + +### 메모리 지속성 + +- 임시 대화에는 인메모리 SQLite (`SQLiteSession("session_id")`) 사용 +- 지속형 대화에는 파일 기반 SQLite (`SQLiteSession("session_id", "path/to/db.sqlite")`) 사용 +- SQLAlchemy 가 지원하는 기존 데이터베이스를 사용하는 프로덕션 시스템에는 SQLAlchemy 기반 세션 (`SQLAlchemySession("session_id", engine=engine, create_tables=True)`) 사용 +- 기록을 OpenAI Conversations API 에 저장하기를 원한다면 OpenAI 가 호스팅하는 스토리지 (`OpenAIConversationsSession()`) 사용 +- 어떤 세션에도 투명한 암호화와 TTL 기반 만료를 적용하려면 암호화된 세션 (`EncryptedSession(session_id, underlying_session, encryption_key)`) 사용 +- 고급 사용 사례를 위해 다른 프로덕션 시스템(Redis, Django 등)에 맞춘 커스텀 세션 백엔드 구현 고려 + +### 다중 세션 + +```python +from agents import Agent, Runner, SQLiteSession + +agent = Agent(name="Assistant") + +# Different sessions maintain separate conversation histories +session_1 = SQLiteSession("user_123", "conversations.db") +session_2 = SQLiteSession("user_456", "conversations.db") + +result1 = await Runner.run( + agent, + "Help me with my account", + session=session_1 +) +result2 = await Runner.run( + agent, + "What are my charges?", + session=session_2 +) +``` + +### 세션 공유 + +```python +# Different agents can share the same session +support_agent = Agent(name="Support") +billing_agent = Agent(name="Billing") +session = SQLiteSession("user_123") + +# Both agents will see the same conversation history +result1 = await Runner.run( + support_agent, + "Help me with my account", + session=session +) +result2 = await Runner.run( + billing_agent, + "What are my charges?", + session=session +) +``` + +## 완전한 예제 + +세션 메모리가 실제로 동작하는 전체 예제는 다음과 같습니다: + +```python +import asyncio +from agents import Agent, Runner, SQLiteSession + + +async def main(): + # Create an agent + agent = Agent( + name="Assistant", + instructions="Reply very concisely.", + ) + + # Create a session instance that will persist across runs + session = SQLiteSession("conversation_123", "conversation_history.db") + + print("=== Sessions Example ===") + print("The agent will remember previous messages automatically.\n") + + # First turn + print("First turn:") + print("User: What city is the Golden Gate Bridge in?") + result = await Runner.run( + agent, + "What city is the Golden Gate Bridge in?", + session=session + ) + print(f"Assistant: {result.final_output}") + print() + + # Second turn - the agent will remember the previous conversation + print("Second turn:") + print("User: What state is it in?") + result = await Runner.run( + agent, + "What state is it in?", + session=session + ) + print(f"Assistant: {result.final_output}") + print() + + # Third turn - continuing the conversation + print("Third turn:") + print("User: What's the population of that state?") + result = await Runner.run( + agent, + "What's the population of that state?", + session=session + ) + print(f"Assistant: {result.final_output}") + print() + + print("=== Conversation Complete ===") + print("Notice how the agent remembered the context from previous turns!") + print("Sessions automatically handles conversation history.") + + +if __name__ == "__main__": + asyncio.run(main()) +``` + +## 사용자 정의 세션 구현 + +[`Session`][agents.memory.session.Session] 프로토콜을 따르는 클래스를 만들어 자체 세션 메모리를 구현할 수 있습니다: + +```python +from agents.memory.session import SessionABC +from agents.items import TResponseInputItem +from typing import List + +class MyCustomSession(SessionABC): + """Custom session implementation following the Session protocol.""" + + def __init__(self, session_id: str): + self.session_id = session_id + # Your initialization here + + async def get_items(self, limit: int | None = None) -> List[TResponseInputItem]: + """Retrieve conversation history for this session.""" + # Your implementation here + pass + + async def add_items(self, items: List[TResponseInputItem]) -> None: + """Store new items for this session.""" + # Your implementation here + pass + + async def pop_item(self) -> TResponseInputItem | None: + """Remove and return the most recent item from this session.""" + # Your implementation here + pass + + async def clear_session(self) -> None: + """Clear all items for this session.""" + # Your implementation here + pass + +# Use your custom session +agent = Agent(name="Assistant") +result = await Runner.run( + agent, + "Hello", + session=MyCustomSession("my_session") +) +``` + +## API 참고 + +자세한 API 문서는 다음을 참고하세요: + +- [`Session`][agents.memory.session.Session] - 프로토콜 인터페이스 +- [`OpenAIConversationsSession`][agents.memory.OpenAIConversationsSession] - OpenAI Conversations API 구현 +- [`SQLiteSession`][agents.memory.sqlite_session.SQLiteSession] - 기본 SQLite 구현 +- [`SQLAlchemySession`][agents.extensions.memory.sqlalchemy_session.SQLAlchemySession] - SQLAlchemy 기반 구현 +- [`AdvancedSQLiteSession`][agents.extensions.memory.advanced_sqlite_session.AdvancedSQLiteSession] - 분기 및 분석을 포함한 향상된 SQLite +- [`EncryptedSession`][agents.extensions.memory.encrypt_session.EncryptedSession] - 어떤 세션에도 적용 가능한 암호화 래퍼 \ No newline at end of file diff --git a/docs/ko/sessions/sqlalchemy_session.md b/docs/ko/sessions/sqlalchemy_session.md new file mode 100644 index 000000000..01d0f0d72 --- /dev/null +++ b/docs/ko/sessions/sqlalchemy_session.md @@ -0,0 +1,80 @@ +--- +search: + exclude: true +--- +# SQLAlchemy 세션 + +`SQLAlchemySession`은 SQLAlchemy를 사용해 프로덕션 준비가 된 세션 구현을 제공하며, 세션 저장을 위해 SQLAlchemy가 지원하는 모든 데이터베이스(PostgreSQL, MySQL, SQLite 등)를 사용할 수 있습니다. + +## 설치 + +SQLAlchemy 세션에는 `sqlalchemy` extra가 필요합니다: + +```bash +pip install openai-agents[sqlalchemy] +``` + +## 빠른 시작 + +### 데이터베이스 URL 사용 + +가장 간단한 시작 방법: + +```python +import asyncio +from agents import Agent, Runner +from agents.extensions.memory import SQLAlchemySession + +async def main(): + agent = Agent("Assistant") + + # Create session using database URL + session = SQLAlchemySession.from_url( + "user-123", + url="sqlite+aiosqlite:///:memory:", + create_tables=True + ) + + result = await Runner.run(agent, "Hello", session=session) + print(result.final_output) + +if __name__ == "__main__": + asyncio.run(main()) +``` + +### 기존 엔진 사용 + +기존 SQLAlchemy 엔진을 사용하는 애플리케이션의 경우: + +```python +import asyncio +from agents import Agent, Runner +from agents.extensions.memory import SQLAlchemySession +from sqlalchemy.ext.asyncio import create_async_engine + +async def main(): + # Create your database engine + engine = create_async_engine("postgresql+asyncpg://user:pass@localhost/db") + + agent = Agent("Assistant") + session = SQLAlchemySession( + "user-456", + engine=engine, + create_tables=True + ) + + result = await Runner.run(agent, "Hello", session=session) + print(result.final_output) + + # Clean up + await engine.dispose() + +if __name__ == "__main__": + asyncio.run(main()) +``` + + +## API 레퍼런스 + +- [`SQLAlchemySession`][agents.extensions.memory.sqlalchemy_session.SQLAlchemySession] - 기본 클래스 +- [`Session`][agents.memory.session.Session] - 기본 세션 프로토콜 \ No newline at end of file diff --git a/docs/ko/streaming.md b/docs/ko/streaming.md index 5a1edaf5b..4e43575d9 100644 --- a/docs/ko/streaming.md +++ b/docs/ko/streaming.md @@ -4,13 +4,13 @@ search: --- # 스트리밍 -스트리밍을 사용하면 에이전트 실행이 진행되는 동안 업데이트를 구독할 수 있습니다. 이는 최종 사용자에게 진행 상태와 부분 응답을 보여줄 때 유용합니다. +스트리밍을 사용하면 에이전트 실행이 진행되는 동안 업데이트를 구독할 수 있습니다. 이는 최종 사용자에게 진행 상황 업데이트와 부분 응답을 표시하는 데 유용합니다. -스트리밍을 사용하려면 [`Runner.run_streamed()`][agents.run.Runner.run_streamed]를 호출하면 되며, 이는 [`RunResultStreaming`][agents.result.RunResultStreaming]을 반환합니다. `result.stream_events()`를 호출하면 아래에 설명된 [`StreamEvent`][agents.stream_events.StreamEvent] 객체의 비동기 스트림을 받습니다. +스트리밍하려면 [`Runner.run_streamed()`][agents.run.Runner.run_streamed]를 호출하면 되고, 그러면 [`RunResultStreaming`][agents.result.RunResultStreaming]을 받습니다. `result.stream_events()`를 호출하면 아래에 설명된 [`StreamEvent`][agents.stream_events.StreamEvent] 객체의 비동기 스트림을 얻을 수 있습니다. ## 원문 응답 이벤트 -[`RawResponsesStreamEvent`][agents.stream_events.RawResponsesStreamEvent]는 LLM에서 직접 전달되는 원문 이벤트입니다. 이들은 OpenAI Responses API 형식을 따르며, 각 이벤트는 타입(예: `response.created`, `response.output_text.delta` 등)과 데이터를 가집니다. 생성되는 즉시 사용자에게 응답 메시지를 스트리밍하고 싶다면 이러한 이벤트가 유용합니다. +[`RawResponsesStreamEvent`][agents.stream_events.RawResponsesStreamEvent]는 LLM에서 직접 전달되는 원문 이벤트입니다. 이들은 OpenAI Responses API 형식이며, 각 이벤트에는 타입(예: `response.created`, `response.output_text.delta` 등)과 데이터가 있습니다. 이러한 이벤트는 생성과 동시에 사용자에게 응답 메시지를 스트리밍하려는 경우에 유용합니다. 예를 들어, 아래 코드는 LLM이 생성한 텍스트를 토큰 단위로 출력합니다. @@ -35,9 +35,9 @@ if __name__ == "__main__": asyncio.run(main()) ``` -## 실행 항목 이벤트와 에이전트 이벤트 +## 실행 항목 이벤트 및 에이전트 이벤트 -[`RunItemStreamEvent`][agents.stream_events.RunItemStreamEvent]는 상위 수준의 이벤트입니다. 항목이 완전히 생성되었을 때 알려줍니다. 이를 통해 각 토큰이 아니라 "메시지 생성됨", "도구 실행됨" 등과 같은 수준에서 진행 상태를 전달할 수 있습니다. 비슷하게, [`AgentUpdatedStreamEvent`][agents.stream_events.AgentUpdatedStreamEvent]는 현재 에이전트가 변경될 때(예: 핸드오프의 결과로) 업데이트를 제공합니다. +[`RunItemStreamEvent`][agents.stream_events.RunItemStreamEvent]는 더 높은 수준의 이벤트로, 항목이 완전히 생성되었을 때 알려줍니다. 이를 통해 각 토큰 단위가 아니라 "메시지 생성됨", "도구 실행됨" 등 수준에서 진행 상황을 전달할 수 있습니다. 유사하게, [`AgentUpdatedStreamEvent`][agents.stream_events.AgentUpdatedStreamEvent]는 현재 에이전트가 변경될 때(예: 핸드오프 결과로) 업데이트를 제공합니다. 예를 들어, 아래 코드는 원문 이벤트를 무시하고 사용자에게 업데이트를 스트리밍합니다. diff --git a/docs/ko/tools.md b/docs/ko/tools.md index 80038d81d..072a2f32b 100644 --- a/docs/ko/tools.md +++ b/docs/ko/tools.md @@ -4,23 +4,23 @@ search: --- # 도구 -도구는 에이전트가 데이터를 가져오고, 코드를 실행하고, 외부 API 를 호출하고, 심지어 컴퓨터를 사용하는 등의 행동을 할 수 있게 합니다. Agents SDK 에는 세 가지 클래스의 도구가 있습니다: +도구는 에이전트가 동작을 수행하도록 합니다. 예: 데이터 가져오기, 코드 실행, 외부 API 호출, 컴퓨터 사용 등. Agents SDK 에는 세 가지 종류의 도구가 있습니다: -- Hosted tools: 이는 AI 모델과 함께 LLM 서버에서 실행됩니다. OpenAI 는 리트리벌 (retrieval), 웹 검색 및 컴퓨터 사용을 호스티드 툴로 제공합니다 -- 함수 호출: 임의의 Python 함수를 도구로 사용할 수 있게 해줍니다 -- 도구로서의 에이전트: 에이전트를 도구로 사용하여 핸드오프 없이 에이전트가 다른 에이전트를 호출할 수 있게 합니다 +- 호스티드 툴: 이는 AI 모델과 함께 LLM 서버에서 실행됩니다. OpenAI 는 retrieval, 웹 검색 및 컴퓨터 사용을 호스티드 툴로 제공합니다 +- Function calling: 이를 통해 임의의 Python 함수를 도구로 사용할 수 있습니다 +- 도구로서의 에이전트: 에이전트를 도구로 사용할 수 있어, 핸드오프 없이 에이전트가 다른 에이전트를 호출할 수 있습니다 ## 호스티드 툴 -OpenAI 는 [`OpenAIResponsesModel`][agents.models.openai_responses.OpenAIResponsesModel] 사용 시 몇 가지 내장 도구를 제공합니다: +OpenAI 는 [`OpenAIResponsesModel`][agents.models.openai_responses.OpenAIResponsesModel] 사용 시 몇 가지 기본 제공 도구를 제공합니다: -- [`WebSearchTool`][agents.tool.WebSearchTool] 은 에이전트가 웹을 검색할 수 있게 합니다 -- [`FileSearchTool`][agents.tool.FileSearchTool] 은 OpenAI 벡터 스토어에서 정보를 검색할 수 있게 합니다 -- [`ComputerTool`][agents.tool.ComputerTool] 은 컴퓨터 사용 작업을 자동화할 수 있게 합니다 -- [`CodeInterpreterTool`][agents.tool.CodeInterpreterTool] 은 LLM 이 샌드박스 환경에서 코드를 실행할 수 있게 합니다 -- [`HostedMCPTool`][agents.tool.HostedMCPTool] 은 원격 MCP 서버의 도구를 모델에 노출합니다 -- [`ImageGenerationTool`][agents.tool.ImageGenerationTool] 은 프롬프트로부터 이미지를 생성합니다 -- [`LocalShellTool`][agents.tool.LocalShellTool] 은 로컬 머신에서 셸 명령을 실행합니다 +- [`WebSearchTool`][agents.tool.WebSearchTool]: 에이전트가 웹을 검색할 수 있습니다 +- [`FileSearchTool`][agents.tool.FileSearchTool]: OpenAI 벡터 스토어에서 정보를 검색할 수 있습니다 +- [`ComputerTool`][agents.tool.ComputerTool]: 컴퓨터 사용 작업을 자동화할 수 있습니다 +- [`CodeInterpreterTool`][agents.tool.CodeInterpreterTool]: LLM 이 샌드박스 환경에서 코드를 실행할 수 있습니다 +- [`HostedMCPTool`][agents.tool.HostedMCPTool]: 원격 MCP 서버의 도구를 모델에 노출합니다 +- [`ImageGenerationTool`][agents.tool.ImageGenerationTool]: 프롬프트로부터 이미지를 생성합니다 +- [`LocalShellTool`][agents.tool.LocalShellTool]: 로컬 머신에서 셸 명령을 실행합니다 ```python from agents import Agent, FileSearchTool, Runner, WebSearchTool @@ -45,12 +45,12 @@ async def main(): 임의의 Python 함수를 도구로 사용할 수 있습니다. Agents SDK 가 도구를 자동으로 설정합니다: -- 도구 이름은 Python 함수 이름이 됩니다(또는 이름을 제공할 수 있음) -- 도구 설명은 함수의 독스트링에서 가져옵니다(또는 설명을 제공할 수 있음) -- 함수 입력에 대한 스키마는 함수의 인자에서 자동으로 생성됩니다 -- 각 입력에 대한 설명은 비활성화하지 않는 한 함수의 독스트링에서 가져옵니다 +- 도구 이름은 Python 함수 이름이 됩니다(또는 직접 이름을 지정할 수 있음) +- 도구 설명은 함수의 docstring 에서 가져옵니다(또는 직접 설명을 지정할 수 있음) +- 함수 입력을 위한 스키마는 함수의 인자에서 자동 생성됩니다 +- 각 입력에 대한 설명은 비활성화하지 않는 한 함수의 docstring 에서 가져옵니다 -우리는 Python의 `inspect` 모듈을 사용해 함수 시그니처를 추출하고, [`griffe`](https://mkdocstrings.github.io/griffe/) 로 독스트링을 파싱하며 스키마 생성을 위해 `pydantic` 을 사용합니다. +Python 의 `inspect` 모듈로 함수 시그니처를 추출하고, [`griffe`](https://mkdocstrings.github.io/griffe/) 로 docstring 을 파싱하며 스키마 생성을 위해 `pydantic` 을 사용합니다. ```python import json @@ -102,10 +102,10 @@ for tool in agent.tools: ``` -1. 함수의 인자로 임의의 Python 타입을 사용할 수 있으며, 함수는 동기 또는 비동기일 수 있습니다 -2. 독스트링이 있으면, 설명과 인자 설명을 추출하는 데 사용됩니다 -3. 함수는 선택적으로 `context` 를 받을 수 있습니다(첫 번째 인자여야 함). 도구 이름, 설명, 사용할 독스트링 스타일 등과 같은 재정의도 설정할 수 있습니다 -4. 데코레이터가 적용된 함수를 도구 목록에 전달하면 됩니다 +1. 함수 인자로 어떤 Python 타입이든 사용할 수 있으며, 함수는 sync 또는 async 일 수 있습니다 +2. docstring 이 있으면, 설명과 인자 설명을 추출하는 데 사용됩니다 +3. 선택적으로 `context` 를 받을 수 있습니다(첫 번째 인자여야 함). 도구 이름, 설명, 사용할 docstring 스타일 등 오버라이드를 설정할 수도 있습니다 +4. 데코레이터가 적용된 함수를 도구 목록에 전달할 수 있습니다 ??? note "출력을 보려면 펼치기" @@ -177,14 +177,22 @@ for tool in agent.tools: } ``` +### 함수 도구에서 이미지나 파일 반환 + +텍스트 출력 외에도, 함수 도구의 출력으로 하나 이상의 이미지나 파일을 반환할 수 있습니다. 이를 위해 다음 중 하나를 반환할 수 있습니다: + +- 이미지: [`ToolOutputImage`][agents.tool.ToolOutputImage] (또는 TypedDict 버전인 [`ToolOutputImageDict`][agents.tool.ToolOutputImageDict]) +- 파일: [`ToolOutputFileContent`][agents.tool.ToolOutputFileContent] (또는 TypedDict 버전인 [`ToolOutputFileContentDict`][agents.tool.ToolOutputFileContentDict]) +- 텍스트: 문자열 또는 문자열로 변환 가능한 객체, 또는 [`ToolOutputText`][agents.tool.ToolOutputText] (또는 TypedDict 버전인 [`ToolOutputTextDict`][agents.tool.ToolOutputTextDict]) + ### 커스텀 함수 도구 -때로는 Python 함수를 도구로 사용하고 싶지 않을 수 있습니다. 이 경우 직접 [`FunctionTool`][agents.tool.FunctionTool] 을 생성할 수 있습니다. 제공해야 하는 것은 다음과 같습니다: +때로는 Python 함수를 도구로 사용하지 않기를 원할 수 있습니다. 이 경우 직접 [`FunctionTool`][agents.tool.FunctionTool] 을 생성할 수 있습니다. 다음을 제공해야 합니다: -- `name` -- `description` -- 인자에 대한 JSON 스키마인 `params_json_schema` -- [`ToolContext`][agents.tool_context.ToolContext] 와 JSON 문자열 형태의 인자를 받아 도구 출력을 문자열로 반환해야 하는 비동기 함수 `on_invoke_tool` +- `name` +- `description` +- `params_json_schema` — 인자에 대한 JSON 스키마 +- `on_invoke_tool` — [`ToolContext`][agents.tool_context.ToolContext] 와 JSON 문자열 형태의 인자를 받아 문자열로 도구 출력을 반환하는 async 함수 ```python from typing import Any @@ -217,18 +225,18 @@ tool = FunctionTool( ) ``` -### 자동 인자 및 독스트링 파싱 +### 자동 인자 및 docstring 파싱 -앞서 언급했듯이, 우리는 도구의 스키마를 추출하기 위해 함수 시그니처를 자동으로 파싱하고, 도구와 개별 인자에 대한 설명을 추출하기 위해 독스트링을 파싱합니다. 다음을 참고하세요: +앞서 언급했듯이, 도구의 스키마를 추출하기 위해 함수 시그니처를 자동으로 파싱하고, 도구 및 개별 인자에 대한 설명을 추출하기 위해 docstring 을 파싱합니다. 이에 대한 참고 사항: -1. 시그니처 파싱은 `inspect` 모듈을 통해 수행됩니다. 우리는 타입 어노테이션을 사용해 인자 타입을 파악하고, 전체 스키마를 표현하는 Pydantic 모델을 동적으로 빌드합니다. Python 기본 타입, Pydantic 모델, TypedDict 등 대부분의 타입을 지원합니다 -2. 독스트링 파싱에는 `griffe` 를 사용합니다. 지원되는 독스트링 형식은 `google`, `sphinx`, `numpy` 입니다. 독스트링 형식을 자동 감지하려고 시도하지만 최선의 노력 기준이며, `function_tool` 호출 시 명시적으로 설정할 수 있습니다. `use_docstring_info` 를 `False` 로 설정하여 독스트링 파싱을 비활성화할 수도 있습니다 +1. 시그니처 파싱은 `inspect` 모듈로 수행합니다. 타입 힌트를 사용해 인자 타입을 파악하고, 전체 스키마를 표현하는 Pydantic 모델을 동적으로 빌드합니다. Python 기본 타입, Pydantic 모델, TypedDict 등 대부분의 타입을 지원합니다 +2. docstring 파싱에는 `griffe` 를 사용합니다. 지원되는 docstring 형식은 `google`, `sphinx`, `numpy` 입니다. docstring 형식을 자동 감지하려 시도하지만, 최선의 노력 수준이므로 `function_tool` 호출 시 명시적으로 설정할 수 있습니다. `use_docstring_info` 를 `False` 로 설정하여 docstring 파싱을 비활성화할 수도 있습니다 스키마 추출을 위한 코드는 [`agents.function_schema`][] 에 있습니다. ## 도구로서의 에이전트 -일부 워크플로에서는 제어를 넘기는 대신 중앙 에이전트가 특화된 에이전트 네트워크를 오케스트레이션하기를 원할 수 있습니다. 에이전트를 도구로 모델링하여 이 작업을 수행할 수 있습니다. +일부 워크플로에서는 제어를 핸드오프하는 대신, 중앙 에이전트가 특화된 에이전트들의 네트워크를 오케스트레이션하도록 하고 싶을 수 있습니다. 에이전트를 도구로 모델링하여 이를 구현할 수 있습니다. ```python from agents import Agent, Runner @@ -267,9 +275,9 @@ async def main(): print(result.final_output) ``` -### 툴-에이전트 커스터마이징 +### 도구-에이전트 커스터마이즈 -`agent.as_tool` 함수는 에이전트를 도구로 손쉽게 전환하기 위한 편의 메서드입니다. 다만 모든 구성을 지원하지는 않습니다. 예를 들어 `max_turns` 를 설정할 수 없습니다. 고급 사용 사례의 경우, 도구 구현에서 `Runner.run` 을 직접 사용하세요: +`agent.as_tool` 함수는 에이전트를 도구로 손쉽게 전환하기 위한 편의 메서드입니다. 다만 모든 구성을 지원하지는 않습니다. 예를 들어 `max_turns` 는 설정할 수 없습니다. 고급 사용 사례의 경우 도구 구현에서 `Runner.run` 을 직접 사용하세요: ```python @function_tool @@ -290,13 +298,13 @@ async def run_my_agent() -> str: ### 커스텀 출력 추출 -특정 상황에서는 중앙 에이전트에 반환하기 전에 툴-에이전트의 출력을 수정하고 싶을 수 있습니다. 다음과 같은 경우에 유용합니다: +특정 상황에서는 중앙 에이전트에 반환하기 전에 도구-에이전트의 출력을 수정하고 싶을 수 있습니다. 다음과 같은 경우 유용합니다: -- 하위 에이전트의 대화 기록에서 특정 정보(예: JSON 페이로드)를 추출 -- 에이전트의 최종 답변을 변환 또는 재포맷(예: Markdown 을 일반 텍스트 또는 CSV 로 변환) -- 에이전트의 응답이 없거나 잘못된 경우 출력을 검증하거나 폴백 값을 제공 +- 하위 에이전트의 대화 기록에서 특정 정보(예: JSON 페이로드)를 추출 +- 에이전트의 최종 답변을 변환 또는 재포맷(예: Markdown 을 일반 텍스트 또는 CSV 로 변환) +- 출력 검증 또는 에이전트 응답이 없거나 잘못된 경우 대체값 제공 -이는 `as_tool` 메서드에 `custom_output_extractor` 인자를 제공하여 수행할 수 있습니다: +이는 `as_tool` 메서드에 `custom_output_extractor` 매개변수를 전달하여 구현할 수 있습니다: ```python async def extract_json_payload(run_result: RunResult) -> str: @@ -317,7 +325,7 @@ json_tool = data_agent.as_tool( ### 조건부 도구 활성화 -런타임에 `is_enabled` 매개변수를 사용하여 에이전트 도구를 조건부로 활성화하거나 비활성화할 수 있습니다. 이를 통해 컨텍스트, 사용자 선호도 또는 런타임 조건에 따라 LLM 에서 사용 가능한 도구를 동적으로 필터링할 수 있습니다. +런타임에 `is_enabled` 매개변수를 사용해 에이전트 도구를 조건부로 활성화 또는 비활성화할 수 있습니다. 이를 통해 컨텍스트, 사용자 선호도, 런타임 조건에 따라 LLM 에 제공할 도구를 동적으로 필터링할 수 있습니다. ```python import asyncio @@ -372,26 +380,26 @@ async def main(): asyncio.run(main()) ``` -`is_enabled` 매개변수는 다음을 허용합니다: +`is_enabled` 매개변수는 다음을 받을 수 있습니다: -- **불리언 값**: `True`(항상 활성) 또는 `False`(항상 비활성) -- **호출 가능 함수**: `(context, agent)` 를 받아 불리언을 반환하는 함수 -- **비동기 함수**: 복잡한 조건부 로직을 위한 비동기 함수 +- **불리언 값**: `True`(항상 활성) 또는 `False`(항상 비활성) +- **호출 가능한 함수**: `(context, agent)` 를 받아 불리언을 반환하는 함수 +- **Async 함수**: 복잡한 조건부 로직을 위한 async 함수 -비활성화된 도구는 런타임에 LLM 에 완전히 숨겨지므로 다음에 유용합니다: +비활성화된 도구는 런타임에 LLM 에서 완전히 숨겨지므로 다음에 유용합니다: -- 사용자 권한에 따른 기능 게이팅 -- 환경별 도구 가용성(dev vs prod) -- 서로 다른 도구 구성을 A/B 테스트 -- 런타임 상태에 따른 동적 도구 필터링 +- 사용자 권한 기반 기능 게이팅 +- 환경별 도구 가용성(dev vs prod) +- 다양한 도구 구성을 A/B 테스트 +- 런타임 상태에 따른 동적 도구 필터링 -## 함수 도구에서의 오류 처리 +## 함수 도구에서의 에러 처리 -`@function_tool` 로 함수 도구를 생성할 때 `failure_error_function` 을 전달할 수 있습니다. 이는 도구 호출이 실패할 경우 LLM 에 에러 응답을 제공하는 함수입니다. +`@function_tool` 로 함수 도구를 생성할 때 `failure_error_function` 을 전달할 수 있습니다. 이는 도구 호출이 크래시하는 경우 LLM 에 오류 응답을 제공하는 함수입니다. -- 기본적으로(즉, 아무것도 전달하지 않으면) 오류가 발생했음을 LLM 에 알리는 `default_tool_error_function` 이 실행됩니다 -- 자체 에러 함수를 전달하면 해당 함수가 대신 실행되며, 그 응답이 LLM 에 전송됩니다 -- 명시적으로 `None` 을 전달하면, 도구 호출 오류가 다시 발생하여 직접 처리해야 합니다. 모델이 잘못된 JSON 을 생성한 경우 `ModelBehaviorError`, 코드가 크래시한 경우 `UserError` 등이 될 수 있습니다 +- 기본적으로(아무 것도 전달하지 않으면) 오류가 발생했음을 LLM 에 알리는 `default_tool_error_function` 이 실행됩니다 +- 사용자 정의 오류 함수를 전달하면, 그 함수가 대신 실행되어 해당 응답이 LLM 에 전송됩니다 +- `None` 을 명시적으로 전달하면, 도구 호출 오류가 다시 발생하여 사용자가 처리할 수 있게 됩니다. 이는 모델이 잘못된 JSON 을 생성한 경우 `ModelBehaviorError`, 사용자 코드가 크래시한 경우 `UserError` 등이 될 수 있습니다 ```python from agents import function_tool, RunContextWrapper diff --git a/docs/ko/tracing.md b/docs/ko/tracing.md index 301965562..37e3e9bc9 100644 --- a/docs/ko/tracing.md +++ b/docs/ko/tracing.md @@ -4,52 +4,52 @@ search: --- # 트레이싱 -Agents SDK에는 기본 제공 트레이싱이 포함되어 있어 에이전트 실행 중 발생하는 이벤트의 종합적인 기록을 수집합니다: LLM 생성, 도구 호출, 핸드오프, 가드레일, 그리고 커스텀 이벤트까지 포함됩니다. [Traces 대시보드](https://platform.openai.com/traces)를 사용하면 개발 및 운영 환경에서 워크플로를 디버그하고, 시각화하며, 모니터링할 수 있습니다. +Agents SDK에는 내장 트레이싱이 포함되어 있어 에이전트 실행 중 발생하는 이벤트의 포괄적인 기록을 수집합니다: LLM 생성, 도구 호출, 핸드오프, 가드레일, 그리고 발생하는 사용자 정의 이벤트까지 모두 포함합니다. [Traces 대시보드](https://platform.openai.com/traces)를 사용해 개발 중과 프로덕션에서 워크플로를 디버그하고, 시각화하며, 모니터링할 수 있습니다. !!!note 트레이싱은 기본적으로 활성화되어 있습니다. 트레이싱을 비활성화하는 방법은 두 가지입니다: - 1. 환경 변수 `OPENAI_AGENTS_DISABLE_TRACING=1` 를 설정하여 전체적으로 트레이싱을 비활성화할 수 있습니다 - 2. 단일 실행에 대해서는 [`agents.run.RunConfig.tracing_disabled`][] 를 `True` 로 설정하여 트레이싱을 비활성화할 수 있습니다 + 1. 환경 변수 `OPENAI_AGENTS_DISABLE_TRACING=1` 를 설정하여 전역으로 비활성화 + 2. 단일 실행에 대해 [`agents.run.RunConfig.tracing_disabled`][] 를 `True` 로 설정하여 비활성화 -***OpenAI의 API를 사용하는 Zero Data Retention (ZDR) 정책 적용 조직의 경우, 트레이싱을 사용할 수 없습니다.*** +***OpenAI의 API를 사용하는 Zero Data Retention (ZDR) 정책 하에서 운영되는 조직의 경우, 트레이싱은 사용할 수 없습니다.*** ## 트레이스와 스팬 -- **트레이스(Traces)** 는 "워크플로"의 단일 엔드 투 엔드 작업을 나타냅니다. 스팬으로 구성됩니다. 트레이스에는 다음 속성이 있습니다: - - `workflow_name`: 논리적 워크플로 또는 앱의 이름입니다. 예: "Code generation" 또는 "Customer service" - - `trace_id`: 트레이스의 고유 ID입니다. 전달하지 않으면 자동으로 생성됩니다. 형식은 `trace_<32_alphanumeric>` 이어야 합니다 +- **Traces** 는 "워크플로"의 단일 엔드 투 엔드 작업을 나타냅니다. 스팬으로 구성됩니다. 트레이스에는 다음 속성이 있습니다: + - `workflow_name`: 논리적 워크플로 또는 앱입니다. 예: "Code generation" 또는 "Customer service" + - `trace_id`: 트레이스의 고유 ID입니다. 전달하지 않으면 자동 생성됩니다. 형식은 `trace_<32_alphanumeric>` 이어야 합니다 - `group_id`: 선택적 그룹 ID로, 동일한 대화에서 나온 여러 트레이스를 연결합니다. 예를 들어 채팅 스레드 ID를 사용할 수 있습니다 - `disabled`: True이면 트레이스가 기록되지 않습니다 - `metadata`: 트레이스에 대한 선택적 메타데이터 -- **스팬(Spans)** 은 시작 및 종료 시간이 있는 작업을 나타냅니다. 스팬에는 다음이 있습니다: +- **Spans** 는 시작 시간과 종료 시간이 있는 작업을 나타냅니다. 스팬에는 다음이 있습니다: - `started_at` 및 `ended_at` 타임스탬프 - - 소속 트레이스를 나타내는 `trace_id` - - 해당 스팬의 상위 스팬을 가리키는 `parent_id` (있는 경우) - - 스팬에 대한 정보를 담는 `span_data`. 예: `AgentSpanData` 는 에이전트 정보를, `GenerationSpanData` 는 LLM 생성 정보를 포함합니다 + - 속한 트레이스를 나타내는 `trace_id` + - 이 스팬의 상위 스팬(있을 경우)을 가리키는 `parent_id` + - 스팬에 대한 정보인 `span_data`. 예를 들어 `AgentSpanData`는 에이전트에 대한 정보를, `GenerationSpanData`는 LLM 생성에 대한 정보를 포함합니다 ## 기본 트레이싱 -기본적으로 SDK는 다음을 트레이싱합니다: +기본적으로, SDK는 다음을 트레이싱합니다: -- 전체 `Runner.{run, run_sync, run_streamed}()` 가 `trace()` 로 감싸집니다 -- 에이전트가 실행될 때마다 `agent_span()` 으로 감쌉니다 -- LLM 생성은 `generation_span()` 으로 감쌉니다 -- 함수 도구 호출은 각각 `function_span()` 으로 감쌉니다 -- 가드레일은 `guardrail_span()` 으로 감쌉니다 -- 핸드오프는 `handoff_span()` 으로 감쌉니다 -- 오디오 입력(음성-텍스트)은 `transcription_span()` 으로 감쌉니다 -- 오디오 출력(텍스트-음성)은 `speech_span()` 으로 감쌉니다 -- 관련 오디오 스팬은 `speech_group_span()` 아래에 상위로 연결될 수 있습니다 +- 전체 `Runner.{run, run_sync, run_streamed}()` 가 `trace()` 로 래핑됩니다 +- 에이전트가 실행될 때마다 `agent_span()` 으로 래핑됩니다 +- LLM 생성은 `generation_span()` 으로 래핑됩니다 +- 함수 도구 호출은 각각 `function_span()` 으로 래핑됩니다 +- 가드레일은 `guardrail_span()` 으로 래핑됩니다 +- 핸드오프는 `handoff_span()` 으로 래핑됩니다 +- 오디오 입력(음성-텍스트)은 `transcription_span()` 으로 래핑됩니다 +- 오디오 출력(텍스트-음성)은 `speech_span()` 으로 래핑됩니다 +- 관련 오디오 스팬은 `speech_group_span()` 하위로 배치될 수 있습니다 -기본적으로 트레이스 이름은 "Agent workflow" 입니다. `trace` 를 사용하면 이 이름을 설정할 수 있으며, 또는 [`RunConfig`][agents.run.RunConfig] 를 통해 이름과 기타 속성을 구성할 수 있습니다. +기본적으로 트레이스 이름은 "Agent workflow"입니다. `trace` 를 사용하면 이 이름을 설정할 수 있으며, 또는 [`RunConfig`][agents.run.RunConfig] 로 이름과 기타 속성을 구성할 수 있습니다. -또한, [사용자 지정 트레이싱 프로세서](#custom-tracing-processors)를 설정하여 트레이스를 다른 대상지로 전송할 수 있습니다(대체 또는 보조 대상지). +또한 [custom trace processors](#custom-tracing-processors) 를 설정하여 트레이스를 다른 대상으로 전송(대체 또는 보조 대상으로)할 수 있습니다. ## 상위 수준 트레이스 -때로는 여러 번의 `run()` 호출을 단일 트레이스의 일부로 묶고 싶을 수 있습니다. 이 경우 전체 코드를 `trace()` 로 감싸면 됩니다. +때로는 여러 번의 `run()` 호출을 하나의 트레이스에 포함하고 싶을 수 있습니다. 전체 코드를 `trace()` 로 래핑하면 됩니다. ```python from agents import Agent, Runner, trace @@ -64,46 +64,46 @@ async def main(): print(f"Rating: {second_result.final_output}") ``` -1. `Runner.run` 에 대한 두 번의 호출이 `with trace()` 로 감싸져 있으므로, 각 실행은 두 개의 트레이스를 생성하는 대신 전체 트레이스의 일부가 됩니다. +1. `Runner.run` 의 두 호출이 `with trace()` 로 래핑되어 있기 때문에, 개별 실행은 두 개의 트레이스를 생성하는 대신 전체 트레이스의 일부가 됩니다. ## 트레이스 생성 -[`trace()`][agents.tracing.trace] 함수를 사용해 트레이스를 생성할 수 있습니다. 트레이스는 시작과 종료가 필요합니다. 방법은 두 가지입니다: +[`trace()`][agents.tracing.trace] 함수를 사용해 트레이스를 생성할 수 있습니다. 트레이스는 시작과 종료가 필요합니다. 다음 두 가지 방법이 있습니다: 1. **권장**: 컨텍스트 매니저로 사용합니다. 예: `with trace(...) as my_trace`. 적절한 시점에 트레이스를 자동으로 시작하고 종료합니다 -2. 직접 [`trace.start()`][agents.tracing.Trace.start] 와 [`trace.finish()`][agents.tracing.Trace.finish] 를 호출할 수도 있습니다 +2. 수동으로 [`trace.start()`][agents.tracing.Trace.start] 와 [`trace.finish()`][agents.tracing.Trace.finish] 를 호출할 수도 있습니다 -현재 트레이스는 Python의 [`contextvar`](https://docs.python.org/3/library/contextvars.html) 를 통해 추적됩니다. 이는 동시성 환경에서도 자동으로 동작함을 의미합니다. 트레이스를 수동으로 시작/종료하는 경우, 현재 트레이스를 업데이트하기 위해 `start()`/`finish()` 에 `mark_as_current` 와 `reset_current` 를 전달해야 합니다. +현재 트레이스는 Python [`contextvar`](https://docs.python.org/3/library/contextvars.html) 를 통해 추적됩니다. 즉, 자동으로 동시성을 지원합니다. 트레이스를 수동으로 시작/종료하는 경우, 현재 트레이스를 업데이트하려면 `start()`/`finish()` 에 `mark_as_current` 및 `reset_current` 를 전달해야 합니다. ## 스팬 생성 -여러 [`*_span()`][agents.tracing.create] 메서드를 사용하여 스팬을 생성할 수 있습니다. 일반적으로 스팬을 수동으로 생성할 필요는 없습니다. 커스텀 스팬 정보를 추적하기 위해 [`custom_span()`][agents.tracing.custom_span] 함수를 사용할 수 있습니다. +여러 [`*_span()`][agents.tracing.create] 메서드를 사용해 스팬을 생성할 수 있습니다. 일반적으로 스팬을 수동으로 생성할 필요는 없습니다. 사용자 정의 스팬 정보를 추적하기 위한 [`custom_span()`][agents.tracing.custom_span] 함수가 제공됩니다. -스팬은 자동으로 현재 트레이스의 일부가 되며, Python의 [`contextvar`](https://docs.python.org/3/library/contextvars.html) 로 추적되는 가장 가까운 현재 스팬 아래에 중첩됩니다. +스팬은 자동으로 현재 트레이스의 일부가 되며, Python [`contextvar`](https://docs.python.org/3/library/contextvars.html) 를 통해 추적되는 가장 가까운 현재 스팬 하위로 중첩됩니다. -## 민감한 데이터 +## 민감 데이터 -특정 스팬은 잠재적으로 민감한 데이터를 캡처할 수 있습니다. +일부 스팬은 잠재적으로 민감한 데이터를 캡처할 수 있습니다. -`generation_span()` 은 LLM 생성의 입력/출력을 저장하고, `function_span()` 은 함수 호출의 입력/출력을 저장합니다. 이는 민감한 데이터를 포함할 수 있으므로, [`RunConfig.trace_include_sensitive_data`][agents.run.RunConfig.trace_include_sensitive_data] 를 통해 해당 데이터 캡처를 비활성화할 수 있습니다. +`generation_span()` 은 LLM 생성의 입력/출력을 저장하고, `function_span()` 은 함수 호출의 입력/출력을 저장합니다. 민감한 데이터를 포함할 수 있으므로 [`RunConfig.trace_include_sensitive_data`][agents.run.RunConfig.trace_include_sensitive_data] 를 통해 해당 데이터 캡처를 비활성화할 수 있습니다. -마찬가지로, 오디오 스팬은 기본적으로 입력 및 출력 오디오에 대해 base64 인코딩된 PCM 데이터를 포함합니다. [`VoicePipelineConfig.trace_include_sensitive_audio_data`][agents.voice.pipeline_config.VoicePipelineConfig.trace_include_sensitive_audio_data] 를 구성하여 이 오디오 데이터 캡처를 비활성화할 수 있습니다. +마찬가지로, 오디오 스팬은 기본적으로 입력 및 출력 오디오에 대해 base64로 인코딩된 PCM 데이터를 포함합니다. [`VoicePipelineConfig.trace_include_sensitive_audio_data`][agents.voice.pipeline_config.VoicePipelineConfig.trace_include_sensitive_audio_data] 를 구성하여 이 오디오 데이터 캡처를 비활성화할 수 있습니다. -## 사용자 지정 트레이싱 프로세서 +## 맞춤 트레이싱 프로세서 트레이싱의 상위 수준 아키텍처는 다음과 같습니다: -- 초기화 시 트레이스를 생성하는 역할의 전역 [`TraceProvider`][agents.tracing.setup.TraceProvider] 를 생성합니다 -- `TraceProvider` 를 [`BatchTraceProcessor`][agents.tracing.processors.BatchTraceProcessor] 로 구성하여 스팬과 트레이스를 배치로 [`BackendSpanExporter`][agents.tracing.processors.BackendSpanExporter] 에 전송하고, 이는 스팬과 트레이스를 OpenAI 백엔드로 배치 내보냅니다 +- 초기화 시, 트레이스를 생성하는 역할을 하는 전역 [`TraceProvider`][agents.tracing.setup.TraceProvider] 를 생성합니다 +- [`BatchTraceProcessor`][agents.tracing.processors.BatchTraceProcessor] 가 트레이스/스팬을 배치로 [`BackendSpanExporter`][agents.tracing.processors.BackendSpanExporter] 에 전달하도록 `TraceProvider` 를 구성합니다. Exporter 는 스팬과 트레이스를 OpenAI 백엔드로 배치 전송합니다 -기본 구성을 사용자 지정하여 다른 백엔드로 트레이스를 전송하거나 추가 백엔드로 전송하거나, 내보내기 동작을 수정하려면 두 가지 옵션이 있습니다: +기본 설정을 사용자 정의하여 다른 백엔드로 전송하거나 추가 백엔드로 전송하거나, exporter 동작을 수정하려면 다음 두 가지 옵션이 있습니다: -1. [`add_trace_processor()`][agents.tracing.add_trace_processor] 는 트레이스와 스팬이 준비되는 대로 수신하는 **추가** 트레이스 프로세서를 추가할 수 있게 합니다. 이를 통해 OpenAI 백엔드로 전송하는 것과 더불어 자체 처리를 수행할 수 있습니다 -2. [`set_trace_processors()`][agents.tracing.set_trace_processors] 는 기본 프로세서를 사용자 지정 트레이스 프로세서로 **교체** 할 수 있게 합니다. 이 경우 OpenAI 백엔드로 트레이스가 전송되지 않으며, 그렇게 하는 `TracingProcessor` 를 포함한 경우에만 전송됩니다 +1. [`add_trace_processor()`][agents.tracing.add_trace_processor] 는 트레이스와 스팬이 준비될 때 이를 수신하는 **추가** 트레이스 프로세서를 추가할 수 있게 해줍니다. 이를 통해 OpenAI 백엔드로 트레이스를 전송하는 것에 더해 자체 처리를 수행할 수 있습니다 +2. [`set_trace_processors()`][agents.tracing.set_trace_processors] 는 기본 프로세서를 사용자의 트레이스 프로세서로 **교체** 할 수 있게 해줍니다. 이 경우 OpenAI 백엔드로 트레이스가 전송되지 않으며, 이를 수행하는 `TracingProcessor` 를 포함한 경우에만 전송됩니다 -## 비 OpenAI 모델과의 트레이싱 +## 비 OpenAI 모델과 트레이싱 -OpenAI의 API 키를 비 OpenAI 모델과 함께 사용하여, 트레이싱을 비활성화할 필요 없이 OpenAI Traces 대시보드에서 무료 트레이싱을 활성화할 수 있습니다. +트레이싱을 비활성화할 필요 없이 OpenAI API 키를 비 OpenAI 모델과 함께 사용하여 OpenAI Traces 대시보드에서 무료 트레이싱을 활성화할 수 있습니다. ```python import os @@ -125,7 +125,7 @@ agent = Agent( ``` ## 참고 -- 무료 트레이스를 OpenAI Traces 대시보드에서 확인하세요 +- OpenAI Traces 대시보드에서 무료 트레이스를 확인하세요 ## 외부 트레이싱 프로세서 목록 diff --git a/docs/ko/usage.md b/docs/ko/usage.md index e51d8a568..e0e9a4adc 100644 --- a/docs/ko/usage.md +++ b/docs/ko/usage.md @@ -4,13 +4,13 @@ search: --- # 사용량 -Agents SDK 는 모든 실행에 대해 토큰 사용량을 자동으로 추적합니다. 실행 컨텍스트에서 접근하여 비용을 모니터링하고, 한도를 강제하거나, 분석을 기록할 수 있습니다. +Agents SDK는 모든 실행에 대해 토큰 사용량을 자동으로 추적합니다. 실행 컨텍스트에서 접근하여 비용 모니터링, 한도 적용, 분석 기록에 활용할 수 있습니다. ## 추적 항목 - **requests**: 수행된 LLM API 호출 수 -- **input_tokens**: 전송된 입력 토큰 총합 -- **output_tokens**: 수신된 출력 토큰 총합 +- **input_tokens**: 전송된 전체 입력 토큰 수 +- **output_tokens**: 수신된 전체 출력 토큰 수 - **total_tokens**: 입력 + 출력 - **details**: - `input_tokens_details.cached_tokens` @@ -18,7 +18,7 @@ Agents SDK 는 모든 실행에 대해 토큰 사용량을 자동으로 추적 ## 실행에서 사용량 접근 -`Runner.run(...)` 이후, `result.context_wrapper.usage` 를 통해 사용량에 접근합니다. +`Runner.run(...)` 이후에는 `result.context_wrapper.usage`를 통해 사용량에 접근합니다. ```python result = await Runner.run(agent, "What's the weather in Tokyo?") @@ -30,11 +30,11 @@ print("Output tokens:", usage.output_tokens) print("Total tokens:", usage.total_tokens) ``` -사용량은 실행 중의 모든 모델 호출에 걸쳐 집계됩니다(도구 호출과 핸드오프 포함). +사용량은 실행 중 수행된 모든 모델 호출(도구 호출과 핸드오프 포함)을 기준으로 집계됩니다. ### LiteLLM 모델에서 사용량 활성화 -LiteLLM 제공자는 기본적으로 사용량 지표를 보고하지 않습니다. [`LitellmModel`](models/litellm.md) 을 사용할 때, 에이전트에 `ModelSettings(include_usage=True)` 를 전달하면 LiteLLM 응답이 `result.context_wrapper.usage` 에 채워집니다. +LiteLLM 공급자는 기본적으로 사용량 메트릭을 보고하지 않습니다. [`LitellmModel`](models/litellm.md)을 사용할 때, 에이전트에 `ModelSettings(include_usage=True)`를 전달하면 LiteLLM 응답이 `result.context_wrapper.usage`에 채워집니다. ```python from agents import Agent, ModelSettings, Runner @@ -52,7 +52,7 @@ print(result.context_wrapper.usage.total_tokens) ## 세션에서 사용량 접근 -`Session`(예: `SQLiteSession`) 을 사용할 때, 각 `Runner.run(...)` 호출은 해당 실행에 대한 사용량을 반환합니다. 세션은 컨텍스트 유지를 위해 대화 내역을 보관하지만, 각 실행의 사용량은 독립적입니다. +`Session`(예: `SQLiteSession`)을 사용할 때, `Runner.run(...)`의 각 호출은 해당 실행에 대한 사용량을 반환합니다. 세션은 컨텍스트 유지를 위해 대화 기록을 보관하지만, 각 실행의 사용량은 독립적입니다. ```python session = SQLiteSession("my_conversation") @@ -64,11 +64,11 @@ second = await Runner.run(agent, "Can you elaborate?", session=session) print(second.context_wrapper.usage.total_tokens) # Usage for second run ``` -세션은 실행 간 대화 컨텍스트를 보존하지만, 각 `Runner.run()` 호출이 반환하는 사용량 지표는 해당 실행만을 나타냅니다. 세션에서는 이전 메시지가 각 실행의 입력으로 다시 공급될 수 있으며, 이는 이후 턴의 입력 토큰 수에 영향을 미칩니다. +세션은 실행 간 대화 컨텍스트를 보존하지만, 각 `Runner.run()` 호출이 반환하는 사용량 메트릭은 해당 실행만을 나타냅니다. 세션에서는 이전 메시지가 각 실행의 입력으로 다시 제공될 수 있으며, 이는 이후 턴의 입력 토큰 수에 영향을 줍니다. -## 훅에서 사용량 활용 +## 훅에서의 사용량 활용 -`RunHooks` 를 사용하는 경우, 각 훅에 전달되는 `context` 객체는 `usage` 를 포함합니다. 이를 통해 수명주기의 핵심 시점에 사용량을 로깅할 수 있습니다. +`RunHooks`를 사용하는 경우, 각 훅에 전달되는 `context` 객체에는 `usage`가 포함됩니다. 이를 통해 수명 주기의 핵심 시점에서 사용량을 로깅할 수 있습니다. ```python class MyHooks(RunHooks): @@ -77,10 +77,10 @@ class MyHooks(RunHooks): print(f"{agent.name} → {u.requests} requests, {u.total_tokens} total tokens") ``` -## API 참조 +## API 레퍼런스 -자세한 API 문서는 다음을 참고하세요. +자세한 API 문서는 다음을 참조하세요: - [`Usage`][agents.usage.Usage] - 사용량 추적 데이터 구조 - [`RunContextWrapper`][agents.run.RunContextWrapper] - 실행 컨텍스트에서 사용량 접근 -- [`RunHooks`][agents.run.RunHooks] - 사용량 추적 수명주기에 훅 연결 \ No newline at end of file +- [`RunHooks`][agents.run.RunHooks] - 사용량 추적 수명 주기에 훅 연결 \ No newline at end of file diff --git a/docs/ko/visualization.md b/docs/ko/visualization.md index 4d88c2a89..07c0b2c02 100644 --- a/docs/ko/visualization.md +++ b/docs/ko/visualization.md @@ -4,7 +4,7 @@ search: --- # 에이전트 시각화 -에이전트 시각화는 **Graphviz**를 사용하여 에이전트와 그 관계를 구조적으로 표현한 그래프를 생성합니다. 이는 애플리케이션 내에서 에이전트, 도구, 핸드오프가 어떻게 상호작용하는지 이해하는 데 유용합니다. +에이전트 시각화는 **Graphviz**를 사용해 에이전트와 그 관계를 구조화된 그래픽으로 생성합니다. 이는 애플리케이션 내에서 에이전트, 도구, 핸드오프가 어떻게 상호작용하는지 이해하는 데 유용합니다. ## 설치 @@ -16,14 +16,14 @@ pip install "openai-agents[viz]" ## 그래프 생성 -`draw_graph` 함수를 사용해 에이전트 시각화를 생성할 수 있습니다. 이 함수는 다음과 같은 유향 그래프를 만듭니다: +`draw_graph` 함수를 사용해 에이전트 시각화를 생성할 수 있습니다. 이 함수는 다음과 같은 방향 그래프를 만듭니다: -- **에이전트**는 노란색 상자로 표시됨 -- **MCP 서버**는 회색 상자로 표시됨 -- **도구**는 초록색 타원으로 표시됨 -- **핸드오프**는 한 에이전트에서 다른 에이전트로 향하는 방향성 간선 +- **에이전트**는 노란색 상자로 표시됩니다. +- **MCP 서버**는 회색 상자로 표시됩니다. +- **도구**는 초록색 타원으로 표시됩니다. +- **핸드오프**는 한 에이전트에서 다른 에이전트로 향하는 방향 간선입니다. -### 사용 예 +### 사용 예시 ```python import os @@ -67,39 +67,39 @@ triage_agent = Agent( draw_graph(triage_agent) ``` -![에이전트 그래프](../assets/images/graph.png) +![Agent Graph](../assets/images/graph.png) -이는 **트리아지 에이전트**의 구조와 하위 에이전트 및 도구와의 연결을 시각적으로 표현한 그래프를 생성합니다. +이는 **triage 에이전트**의 구조와 하위 에이전트 및 도구와의 연결을 시각적으로 나타내는 그래프를 생성합니다. ## 시각화 이해 생성된 그래프에는 다음이 포함됩니다: -- 진입점을 나타내는 **시작 노드**(`__start__`) +- 진입 지점을 나타내는 **시작 노드** (`__start__`) - 노란색 채우기의 **직사각형**으로 표시된 에이전트 - 초록색 채우기의 **타원**으로 표시된 도구 - 회색 채우기의 **직사각형**으로 표시된 MCP 서버 -- 상호작용을 나타내는 방향성 간선: +- 상호작용을 나타내는 방향 간선: - 에이전트 간 핸드오프는 **실선 화살표** - 도구 호출은 **점선 화살표** - MCP 서버 호출은 **파선 화살표** -- 실행 종료 지점을 나타내는 **종료 노드**(`__end__`) +- 실행이 종료되는 위치를 나타내는 **종료 노드** (`__end__`) -**참고:** MCP 서버는 최근 버전의 -`agents` 패키지에서 렌더링됩니다(**v0.2.8**에서 확인됨). 시각화에 MCP 상자가 보이지 않는 경우 최신 릴리스로 업그레이드하세요. +**참고:** MCP 서버는 최신 버전의 +`agents` 패키지에서 렌더링됩니다 ( **v0.2.8** 에서 확인됨). 시각화에 MCP 상자가 보이지 않으면 최신 릴리스로 업그레이드하세요. -## 그래프 커스터마이징 +## 그래프 사용자 정의 ### 그래프 표시 -기본적으로 `draw_graph`는 그래프를 인라인으로 표시합니다. 그래프를 별도 창에서 보려면 다음을 작성하세요: +기본적으로 `draw_graph`는 그래프를 인라인으로 표시합니다. 그래프를 별도 창에 표시하려면 다음을 작성하세요: ```python draw_graph(triage_agent).view() ``` ### 그래프 저장 -기본적으로 `draw_graph`는 그래프를 인라인으로 표시합니다. 파일로 저장하려면 파일명을 지정하세요: +기본적으로 `draw_graph`는 그래프를 인라인으로 표시합니다. 파일로 저장하려면 파일 이름을 지정하세요: ```python draw_graph(triage_agent, filename="agent_graph") diff --git a/docs/ko/voice/pipeline.md b/docs/ko/voice/pipeline.md index af6ad74ca..ad688b536 100644 --- a/docs/ko/voice/pipeline.md +++ b/docs/ko/voice/pipeline.md @@ -4,7 +4,7 @@ search: --- # 파이프라인과 워크플로 -[`VoicePipeline`][agents.voice.pipeline.VoicePipeline] 클래스는 에이전트 워크플로를 음성 앱으로 쉽게 전환할 수 있게 해줍니다. 실행할 워크플로를 전달하면, 파이프라인이 입력 오디오를 전사하고, 오디오 종료 시점을 감지하고, 적절한 시점에 워크플로를 호출하고, 워크플로 출력 결과를 다시 오디오로 변환하는 작업을 처리합니다 +[`VoicePipeline`][agents.voice.pipeline.VoicePipeline]은 에이전트 기반 워크플로를 음성 앱으로 쉽게 전환할 수 있게 해주는 클래스입니다. 실행할 워크플로를 전달하면, 파이프라인이 입력 오디오의 음성 인식, 발화 종료 감지, 적절한 시점의 워크플로 호출, 그리고 워크플로 출력을 다시 오디오로 변환하는 작업을 처리합니다. ```mermaid graph LR @@ -36,26 +36,26 @@ graph LR 파이프라인을 생성할 때 다음을 설정할 수 있습니다: -1. 새 오디오가 전사될 때마다 실행되는 코드인 [`workflow`][agents.voice.workflow.VoiceWorkflowBase] -2. 사용하는 [`speech-to-text`][agents.voice.model.STTModel] 및 [`text-to-speech`][agents.voice.model.TTSModel] 모델 +1. 매번 새 오디오가 전사될 때 실행되는 코드인 [`workflow`][agents.voice.workflow.VoiceWorkflowBase] +2. 사용되는 [`speech-to-text`][agents.voice.model.STTModel] 및 [`text-to-speech`][agents.voice.model.TTSModel] 모델 3. 다음과 같은 항목을 구성할 수 있는 [`config`][agents.voice.pipeline_config.VoicePipelineConfig] - - 모델 이름을 실제 모델로 매핑할 수 있는 모델 제공자 + - 모델 제공자: 모델 이름을 실제 모델로 매핑 - 트레이싱: 트레이싱 비활성화 여부, 오디오 파일 업로드 여부, 워크플로 이름, 트레이스 ID 등 - - 프롬프트, 언어, 사용하는 데이터 타입 등 TTS 및 STT 모델의 설정 + - TTS 및 STT 모델의 설정: 프롬프트, 언어, 사용되는 데이터 타입 등 ## 파이프라인 실행 -파이프라인은 [`run()`][agents.voice.pipeline.VoicePipeline.run] 메서드를 통해 실행할 수 있으며, 두 가지 형태로 오디오 입력을 전달할 수 있습니다: +파이프라인은 [`run()`][agents.voice.pipeline.VoicePipeline.run] 메서드로 실행할 수 있으며, 오디오 입력을 두 가지 형태로 전달할 수 있습니다: -1. 전체 오디오 전사본이 있고 그 결과만 생성하고자 할 때는 [`AudioInput`][agents.voice.input.AudioInput] 을 사용합니다. 이는 화자가 발화를 마치는 시점을 감지할 필요가 없는 경우에 유용합니다. 예를 들어, 사전 녹음된 오디오가 있거나 사용자가 발화를 마치는 시점이 명확한 푸시-투-토크 앱에서 유용합니다 -2. 사용자가 발화를 마치는 시점을 감지해야 할 수 있는 경우에는 [`StreamedAudioInput`][agents.voice.input.StreamedAudioInput] 을 사용합니다. 이는 감지되는 대로 오디오 청크를 푸시할 수 있게 하며, 음성 파이프라인은 "활동 감지(activity detection)"라는 과정을 통해 적절한 시점에 에이전트 워크플로를 자동으로 실행합니다 +1. [`AudioInput`][agents.voice.input.AudioInput]은 전체 오디오 전사가 있을 때 이를 기반으로 결과만 생성하려는 경우에 사용합니다. 발화 종료 시점을 별도로 감지할 필요가 없는 경우에 유용합니다. 예를 들어, 사전 녹음된 오디오나 사용자가 말하기를 마치는 시점이 명확한 푸시투토크 앱에서 유용합니다. +2. [`StreamedAudioInput`][agents.voice.input.StreamedAudioInput]은 사용자가 말을 마치는 시점을 감지해야 할 수 있는 경우에 사용합니다. 감지되는 대로 오디오 청크를 푸시할 수 있으며, 음성 파이프라인은 "활동 감지(activity detection)"라는 프로세스를 통해 적절한 시점에 에이전트 워크플로를 자동으로 실행합니다. ## 결과 -음성 파이프라인 실행의 결과는 [`StreamedAudioResult`][agents.voice.result.StreamedAudioResult] 입니다. 이는 발생하는 이벤트를 스트리밍으로 수신할 수 있는 객체입니다. 다음과 같은 여러 종류의 [`VoiceStreamEvent`][agents.voice.events.VoiceStreamEvent] 가 있습니다: +음성 파이프라인 실행 결과는 [`StreamedAudioResult`][agents.voice.result.StreamedAudioResult]입니다. 이는 발생하는 이벤트를 스트리밍할 수 있는 객체입니다. 다음과 같은 여러 종류의 [`VoiceStreamEvent`][agents.voice.events.VoiceStreamEvent]가 있습니다: -1. 오디오 청크를 포함하는 [`VoiceStreamEventAudio`][agents.voice.events.VoiceStreamEventAudio] -2. 턴 시작 및 종료와 같은 라이프사이클 이벤트를 알려주는 [`VoiceStreamEventLifecycle`][agents.voice.events.VoiceStreamEventLifecycle] +1. 오디오 청크가 포함된 [`VoiceStreamEventAudio`][agents.voice.events.VoiceStreamEventAudio] +2. 턴 시작/종료와 같은 라이프사이클 이벤트를 알려주는 [`VoiceStreamEventLifecycle`][agents.voice.events.VoiceStreamEventLifecycle] 3. 오류 이벤트인 [`VoiceStreamEventError`][agents.voice.events.VoiceStreamEventError] ```python @@ -76,4 +76,4 @@ async for event in result.stream(): ### 인터럽션(중단 처리) -Agents SDK 는 현재 [`StreamedAudioInput`][agents.voice.input.StreamedAudioInput] 에 대해 기본 제공 인터럽션(중단 처리) 지원을 제공하지 않습니다. 대신 감지된 각 턴마다 워크플로의 별도 실행을 트리거합니다. 애플리케이션 내부에서 인터럽션을 처리하려면 [`VoiceStreamEventLifecycle`][agents.voice.events.VoiceStreamEventLifecycle] 이벤트를 수신하면 됩니다. `turn_started` 는 새 턴이 전사되어 처리가 시작되었음을 나타냅니다. `turn_ended` 는 해당 턴에 대한 모든 오디오가 디스패치된 후 트리거됩니다. 이러한 이벤트를 사용하여 모델이 턴을 시작할 때 화자의 마이크를 음소거하고, 해당 턴의 관련 오디오를 모두 전송한 뒤 음소거를 해제할 수 있습니다 \ No newline at end of file +Agents SDK는 현재 [`StreamedAudioInput`][agents.voice.input.StreamedAudioInput]에 대해 내장된 인터럽션(중단 처리) 기능을 지원하지 않습니다. 대신 감지된 각 턴마다 워크플로의 별도 실행을 트리거합니다. 애플리케이션 내부에서 인터럽션을 처리하려면 [`VoiceStreamEventLifecycle`][agents.voice.events.VoiceStreamEventLifecycle] 이벤트를 수신하면 됩니다. `turn_started`는 새 턴이 전사되어 처리가 시작되었음을 나타냅니다. `turn_ended`는 해당 턴의 모든 오디오가 디스패치된 후 트리거됩니다. 이러한 이벤트를 사용해 모델이 턴을 시작할 때 화자의 마이크를 음소거하고, 해당 턴과 관련된 오디오를 모두 플러시한 후 음소거를 해제할 수 있습니다. \ No newline at end of file diff --git a/docs/ko/voice/quickstart.md b/docs/ko/voice/quickstart.md index 5881f3e67..31a5aebd0 100644 --- a/docs/ko/voice/quickstart.md +++ b/docs/ko/voice/quickstart.md @@ -6,7 +6,7 @@ search: ## 사전 준비 -Agents SDK의 기본 [빠른 시작 가이드](../quickstart.md)를 따라 가상 환경을 설정했는지 확인하세요. 그런 다음, SDK에서 선택 사항인 음성 관련 의존성을 설치하세요: +Agents SDK의 기본 [빠른 시작 안내](../quickstart.md)를 따라 가상 환경을 설정했는지 확인하세요. 그런 다음 SDK에서 음성 관련 선택적 종속성을 설치합니다: ```bash pip install 'openai-agents[voice]' @@ -14,11 +14,11 @@ pip install 'openai-agents[voice]' ## 개념 -알아두어야 할 핵심 개념은 [`VoicePipeline`][agents.voice.pipeline.VoicePipeline]이며, 이는 3단계 프로세스입니다: +핵심 개념은 [`VoicePipeline`][agents.voice.pipeline.VoicePipeline]으로, 3단계 프로세스입니다: -1. 음성을 텍스트로 변환하기 위해 음성-텍스트 모델을 실행 -2. 결과를 생성하기 위해 코드를 실행하며, 보통 에이전트 워크플로를 사용 -3. 결과 텍스트를 다시 음성으로 변환하기 위해 텍스트-음성 모델을 실행 +1. 음성을 텍스트로 변환하기 위해 음성 인식 모델을 실행 +2. 보통 에이전트 워크플로우인 코드를 실행하여 결과 생성 +3. 결과 텍스트를 다시 음성으로 변환하기 위해 음성 합성 모델을 실행 ```mermaid graph LR @@ -48,7 +48,7 @@ graph LR ## 에이전트 -먼저 에이전트를 설정해 봅시다. 이 SDK로 에이전트를 만들어본 적이 있다면 익숙할 것입니다. 에이전트 두 개와 핸드오프, 그리고 도구 하나를 사용합니다. +먼저 에이전트를 설정해 보겠습니다. 이 SDK로 에이전트를 만들어 본 적이 있다면 익숙할 것입니다. 에이전트 두 개, 핸드오프, 그리고 도구 하나를 사용합니다. ```python import asyncio @@ -92,7 +92,7 @@ agent = Agent( ## 음성 파이프라인 -워크플로로 [`SingleAgentVoiceWorkflow`][agents.voice.workflow.SingleAgentVoiceWorkflow]를 사용하여 간단한 음성 파이프라인을 설정하겠습니다. +워크플로우로 [`SingleAgentVoiceWorkflow`][agents.voice.workflow.SingleAgentVoiceWorkflow]를 사용하여 간단한 음성 파이프라인을 설정하겠습니다. ```python from agents.voice import SingleAgentVoiceWorkflow, VoicePipeline @@ -195,4 +195,4 @@ if __name__ == "__main__": asyncio.run(main()) ``` -이 예제를 실행하면 에이전트가 여러분에게 말을 겁니다! 직접 에이전트와 대화할 수 있는 데모는 [examples/voice/static](https://github.com/openai/openai-agents-python/tree/main/examples/voice/static)에서 확인하세요. \ No newline at end of file +이 예제를 실행하면 에이전트가 직접 말합니다! 직접 말로 상호작용하는 데모는 [examples/voice/static](https://github.com/openai/openai-agents-python/tree/main/examples/voice/static)에서 확인하세요. \ No newline at end of file diff --git a/docs/ko/voice/tracing.md b/docs/ko/voice/tracing.md index 58550ec09..d708aeb16 100644 --- a/docs/ko/voice/tracing.md +++ b/docs/ko/voice/tracing.md @@ -6,13 +6,13 @@ search: [에이전트가 트레이싱되는 방식](../tracing.md)과 마찬가지로, 음성 파이프라인도 자동으로 트레이싱됩니다. -기본 트레이싱 정보는 위 문서를 참고하시고, 추가로 [`VoicePipelineConfig`][agents.voice.pipeline_config.VoicePipelineConfig]를 통해 파이프라인 트레이싱을 구성할 수 있습니다. +기본 트레이싱 정보는 위의 문서를 참고하시고, 추가로 [`VoicePipelineConfig`][agents.voice.pipeline_config.VoicePipelineConfig]를 통해 파이프라인의 트레이싱을 구성할 수 있습니다. 주요 트레이싱 관련 필드는 다음과 같습니다: -- [`tracing_disabled`][agents.voice.pipeline_config.VoicePipelineConfig.tracing_disabled]: 트레이싱 비활성화 여부를 제어합니다. 기본값은 트레이싱 활성화 -- [`trace_include_sensitive_data`][agents.voice.pipeline_config.VoicePipelineConfig.trace_include_sensitive_data]: 오디오 전사본과 같은 잠재적으로 민감한 데이터 포함 여부를 제어합니다. 이는 음성 파이프라인에만 적용되며, Workflow 내부에서 발생하는 작업에는 적용되지 않습니다 -- [`trace_include_sensitive_audio_data`][agents.voice.pipeline_config.VoicePipelineConfig.trace_include_sensitive_audio_data]: 트레이스에 오디오 데이터를 포함할지 여부를 제어합니다 -- [`workflow_name`][agents.voice.pipeline_config.VoicePipelineConfig.workflow_name]: 트레이스 워크플로 이름 -- [`group_id`][agents.voice.pipeline_config.VoicePipelineConfig.group_id]: 여러 트레이스를 연결할 수 있게 해주는 트레이스의 `group_id` -- [`trace_metadata`][agents.voice.pipeline_config.VoicePipelineConfig.tracing_disabled]: 트레이스에 포함할 추가 메타데이터 \ No newline at end of file +- [`tracing_disabled`][agents.voice.pipeline_config.VoicePipelineConfig.tracing_disabled]: 트레이싱 비활성화 여부를 제어합니다. 기본적으로 트레이싱은 활성화되어 있습니다. +- [`trace_include_sensitive_data`][agents.voice.pipeline_config.VoicePipelineConfig.trace_include_sensitive_data]: 오디오 전사본과 같은 잠재적으로 민감한 데이터를 트레이스에 포함할지 여부를 제어합니다. 이는 음성 파이프라인에만 해당하며, Workflow 내부에서 발생하는 작업에는 적용되지 않습니다. +- [`trace_include_sensitive_audio_data`][agents.voice.pipeline_config.VoicePipelineConfig.trace_include_sensitive_audio_data]: 트레이스에 오디오 데이터를 포함할지 여부를 제어합니다. +- [`workflow_name`][agents.voice.pipeline_config.VoicePipelineConfig.workflow_name]: 트레이스 워크플로의 이름입니다. +- [`group_id`][agents.voice.pipeline_config.VoicePipelineConfig.group_id]: 여러 트레이스를 연결할 수 있게 해주는 트레이스의 `group_id`입니다. +- [`trace_metadata`][agents.voice.pipeline_config.VoicePipelineConfig.tracing_disabled]: 트레이스에 포함할 추가 메타데이터입니다. \ No newline at end of file diff --git a/docs/ref/extensions/memory/advanced_sqlite_session.md b/docs/ref/extensions/memory/advanced_sqlite_session.md index d3528a54a..ee2c95434 100644 --- a/docs/ref/extensions/memory/advanced_sqlite_session.md +++ b/docs/ref/extensions/memory/advanced_sqlite_session.md @@ -1,3 +1,3 @@ -# `Advanced Sqlite Session` +# `AdvancedSQLiteSession` -::: agents.extensions.memory.advanced_sqlite_session +::: agents.extensions.memory.advanced_sqlite_session.AdvancedSQLiteSession \ No newline at end of file diff --git a/docs/ref/memory.md b/docs/ref/memory.md index 04a2258bf..eb78a51a5 100644 --- a/docs/ref/memory.md +++ b/docs/ref/memory.md @@ -6,3 +6,4 @@ members: - Session - SQLiteSession + - OpenAIConversationsSession diff --git a/docs/running_agents.md b/docs/running_agents.md index 5d7634999..ab69d8463 100644 --- a/docs/running_agents.md +++ b/docs/running_agents.md @@ -89,7 +89,7 @@ async def main(): ### Automatic conversation management with Sessions -For a simpler approach, you can use [Sessions](sessions.md) to automatically handle conversation history without manually calling `.to_input_list()`: +For a simpler approach, you can use [Sessions](sessions/index.md) to automatically handle conversation history without manually calling `.to_input_list()`: ```python from agents import Agent, Runner, SQLiteSession @@ -119,7 +119,7 @@ Sessions automatically: - Stores new messages after each run - Maintains separate conversations for different session IDs -See the [Sessions documentation](sessions.md) for more details. +See the [Sessions documentation](sessions/index.md) for more details. ### Server-managed conversations diff --git a/docs/sessions/advanced_sqlite_session.md b/docs/sessions/advanced_sqlite_session.md new file mode 100644 index 000000000..ab6bfa5d8 --- /dev/null +++ b/docs/sessions/advanced_sqlite_session.md @@ -0,0 +1,303 @@ +# Advanced SQLite Sessions + +`AdvancedSQLiteSession` is an enhanced version of the basic `SQLiteSession` that provides advanced conversation management capabilities including conversation branching, detailed usage analytics, and structured conversation queries. + +## Features + +- **Conversation branching**: Create alternative conversation paths from any user message +- **Usage tracking**: Detailed token usage analytics per turn with full JSON breakdowns +- **Structured queries**: Get conversations by turns, tool usage statistics, and more +- **Branch management**: Independent branch switching and management +- **Message structure metadata**: Track message types, tool usage, and conversation flow + +## Quick start + +```python +from agents import Agent, Runner +from agents.extensions.memory import AdvancedSQLiteSession + +# Create agent +agent = Agent( + name="Assistant", + instructions="Reply very concisely.", +) + +# Create an advanced session +session = AdvancedSQLiteSession( + session_id="conversation_123", + db_path="conversations.db", + create_tables=True +) + +# First conversation turn +result = await Runner.run( + agent, + "What city is the Golden Gate Bridge in?", + session=session +) +print(result.final_output) # "San Francisco" + +# IMPORTANT: Store usage data +await session.store_run_usage(result) + +# Continue conversation +result = await Runner.run( + agent, + "What state is it in?", + session=session +) +print(result.final_output) # "California" +await session.store_run_usage(result) +``` + +## Initialization + +```python +from agents.extensions.memory import AdvancedSQLiteSession + +# Basic initialization +session = AdvancedSQLiteSession( + session_id="my_conversation", + create_tables=True # Auto-create advanced tables +) + +# With persistent storage +session = AdvancedSQLiteSession( + session_id="user_123", + db_path="path/to/conversations.db", + create_tables=True +) + +# With custom logger +import logging +logger = logging.getLogger("my_app") +session = AdvancedSQLiteSession( + session_id="session_456", + create_tables=True, + logger=logger +) +``` + +### Parameters + +- `session_id` (str): Unique identifier for the conversation session +- `db_path` (str | Path): Path to SQLite database file. Defaults to `:memory:` for in-memory storage +- `create_tables` (bool): Whether to automatically create the advanced tables. Defaults to `False` +- `logger` (logging.Logger | None): Custom logger for the session. Defaults to module logger + +## Usage tracking + +AdvancedSQLiteSession provides detailed usage analytics by storing token usage data per conversation turn. **This is entirely dependent on the `store_run_usage` method being called after each agent run.** + +### Storing usage data + +```python +# After each agent run, store the usage data +result = await Runner.run(agent, "Hello", session=session) +await session.store_run_usage(result) + +# This stores: +# - Total tokens used +# - Input/output token breakdown +# - Request count +# - Detailed JSON token information (if available) +``` + +### Retrieving usage statistics + +```python +# Get session-level usage (all branches) +session_usage = await session.get_session_usage() +if session_usage: + print(f"Total requests: {session_usage['requests']}") + print(f"Total tokens: {session_usage['total_tokens']}") + print(f"Input tokens: {session_usage['input_tokens']}") + print(f"Output tokens: {session_usage['output_tokens']}") + print(f"Total turns: {session_usage['total_turns']}") + +# Get usage for specific branch +branch_usage = await session.get_session_usage(branch_id="main") + +# Get usage by turn +turn_usage = await session.get_turn_usage() +for turn_data in turn_usage: + print(f"Turn {turn_data['user_turn_number']}: {turn_data['total_tokens']} tokens") + if turn_data['input_tokens_details']: + print(f" Input details: {turn_data['input_tokens_details']}") + if turn_data['output_tokens_details']: + print(f" Output details: {turn_data['output_tokens_details']}") + +# Get usage for specific turn +turn_2_usage = await session.get_turn_usage(user_turn_number=2) +``` + +## Conversation branching + +One of the key features of AdvancedSQLiteSession is the ability to create conversation branches from any user message, allowing you to explore alternative conversation paths. + +### Creating branches + +```python +# Get available turns for branching +turns = await session.get_conversation_turns() +for turn in turns: + print(f"Turn {turn['turn']}: {turn['content']}") + print(f"Can branch: {turn['can_branch']}") + +# Create a branch from turn 2 +branch_id = await session.create_branch_from_turn(2) +print(f"Created branch: {branch_id}") + +# Create a branch with custom name +branch_id = await session.create_branch_from_turn( + 2, + branch_name="alternative_path" +) + +# Create branch by searching for content +branch_id = await session.create_branch_from_content( + "weather", + branch_name="weather_focus" +) +``` + +### Branch management + +```python +# List all branches +branches = await session.list_branches() +for branch in branches: + current = " (current)" if branch["is_current"] else "" + print(f"{branch['branch_id']}: {branch['user_turns']} turns, {branch['message_count']} messages{current}") + +# Switch between branches +await session.switch_to_branch("main") +await session.switch_to_branch(branch_id) + +# Delete a branch +await session.delete_branch(branch_id, force=True) # force=True allows deleting current branch +``` + +### Branch workflow example + +```python +# Original conversation +result = await Runner.run(agent, "What's the capital of France?", session=session) +await session.store_run_usage(result) + +result = await Runner.run(agent, "What's the weather like there?", session=session) +await session.store_run_usage(result) + +# Create branch from turn 2 (weather question) +branch_id = await session.create_branch_from_turn(2, "weather_focus") + +# Continue in new branch with different question +result = await Runner.run( + agent, + "What are the main tourist attractions in Paris?", + session=session +) +await session.store_run_usage(result) + +# Switch back to main branch +await session.switch_to_branch("main") + +# Continue original conversation +result = await Runner.run( + agent, + "How expensive is it to visit?", + session=session +) +await session.store_run_usage(result) +``` + +## Structured queries + +AdvancedSQLiteSession provides several methods for analyzing conversation structure and content. + +### Conversation analysis + +```python +# Get conversation organized by turns +conversation_by_turns = await session.get_conversation_by_turns() +for turn_num, items in conversation_by_turns.items(): + print(f"Turn {turn_num}: {len(items)} items") + for item in items: + if item["tool_name"]: + print(f" - {item['type']} (tool: {item['tool_name']})") + else: + print(f" - {item['type']}") + +# Get tool usage statistics +tool_usage = await session.get_tool_usage() +for tool_name, count, turn in tool_usage: + print(f"{tool_name}: used {count} times in turn {turn}") + +# Find turns by content +matching_turns = await session.find_turns_by_content("weather") +for turn in matching_turns: + print(f"Turn {turn['turn']}: {turn['content']}") +``` + +### Message structure + +The session automatically tracks message structure including: + +- Message types (user, assistant, tool_call, etc.) +- Tool names for tool calls +- Turn numbers and sequence numbers +- Branch associations +- Timestamps + +## Database schema + +AdvancedSQLiteSession extends the basic SQLite schema with two additional tables: + +### message_structure table + +```sql +CREATE TABLE message_structure ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + session_id TEXT NOT NULL, + message_id INTEGER NOT NULL, + branch_id TEXT NOT NULL DEFAULT 'main', + message_type TEXT NOT NULL, + sequence_number INTEGER NOT NULL, + user_turn_number INTEGER, + branch_turn_number INTEGER, + tool_name TEXT, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (session_id) REFERENCES agent_sessions(session_id) ON DELETE CASCADE, + FOREIGN KEY (message_id) REFERENCES agent_messages(id) ON DELETE CASCADE +); +``` + +### turn_usage table + +```sql +CREATE TABLE turn_usage ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + session_id TEXT NOT NULL, + branch_id TEXT NOT NULL DEFAULT 'main', + user_turn_number INTEGER NOT NULL, + requests INTEGER DEFAULT 0, + input_tokens INTEGER DEFAULT 0, + output_tokens INTEGER DEFAULT 0, + total_tokens INTEGER DEFAULT 0, + input_tokens_details JSON, + output_tokens_details JSON, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (session_id) REFERENCES agent_sessions(session_id) ON DELETE CASCADE, + UNIQUE(session_id, branch_id, user_turn_number) +); +``` + +## Complete example + +Check out the [complete example](https://github.com/openai/openai-agents-python/tree/main/examples/memory/advanced_sqlite_session_example.py) for a comprehensive demonstration of all features. + + +## API Reference + +- [`AdvancedSQLiteSession`][agents.extensions.memory.advanced_sqlite_session.AdvancedSQLiteSession] - Main class +- [`Session`][agents.memory.session.Session] - Base session protocol diff --git a/docs/sessions/encrypted_session.md b/docs/sessions/encrypted_session.md new file mode 100644 index 000000000..ba3755ae9 --- /dev/null +++ b/docs/sessions/encrypted_session.md @@ -0,0 +1,175 @@ +# Encrypted Sessions + +`EncryptedSession` provides transparent encryption for any session implementation, securing conversation data with automatic expiration of old items. + +## Features + +- **Transparent encryption**: Wraps any session with Fernet encryption +- **Per-session keys**: Uses HKDF key derivation for unique encryption per session +- **Automatic expiration**: Old items are silently skipped when TTL expires +- **Drop-in replacement**: Works with any existing session implementation + +## Installation + +Encrypted sessions require the `encrypt` extra: + +```bash +pip install openai-agents[encrypt] +``` + +## Quick start + +```python +import asyncio +from agents import Agent, Runner +from agents.extensions.memory import EncryptedSession, SQLAlchemySession + +async def main(): + agent = Agent("Assistant") + + # Create underlying session + underlying_session = SQLAlchemySession.from_url( + "user-123", + url="sqlite+aiosqlite:///:memory:", + create_tables=True + ) + + # Wrap with encryption + session = EncryptedSession( + session_id="user-123", + underlying_session=underlying_session, + encryption_key="your-secret-key-here", + ttl=600 # 10 minutes + ) + + result = await Runner.run(agent, "Hello", session=session) + print(result.final_output) + +if __name__ == "__main__": + asyncio.run(main()) +``` + +## Configuration + +### Encryption key + +The encryption key can be either a Fernet key or any string: + +```python +from agents.extensions.memory import EncryptedSession + +# Using a Fernet key (base64-encoded) +session = EncryptedSession( + session_id="user-123", + underlying_session=underlying_session, + encryption_key="your-fernet-key-here", + ttl=600 +) + +# Using a raw string (will be derived to a key) +session = EncryptedSession( + session_id="user-123", + underlying_session=underlying_session, + encryption_key="my-secret-password", + ttl=600 +) +``` + +### TTL (Time To Live) + +Set how long encrypted items remain valid: + +```python +# Items expire after 1 hour +session = EncryptedSession( + session_id="user-123", + underlying_session=underlying_session, + encryption_key="secret", + ttl=3600 # 1 hour in seconds +) + +# Items expire after 1 day +session = EncryptedSession( + session_id="user-123", + underlying_session=underlying_session, + encryption_key="secret", + ttl=86400 # 24 hours in seconds +) +``` + +## Usage with different session types + +### With SQLite sessions + +```python +from agents import SQLiteSession +from agents.extensions.memory import EncryptedSession + +# Create encrypted SQLite session +underlying = SQLiteSession("user-123", "conversations.db") + +session = EncryptedSession( + session_id="user-123", + underlying_session=underlying, + encryption_key="secret-key" +) +``` + +### With SQLAlchemy sessions + +```python +from agents.extensions.memory import EncryptedSession, SQLAlchemySession + +# Create encrypted SQLAlchemy session +underlying = SQLAlchemySession.from_url( + "user-123", + url="postgresql+asyncpg://user:pass@localhost/db", + create_tables=True +) + +session = EncryptedSession( + session_id="user-123", + underlying_session=underlying, + encryption_key="secret-key" +) +``` + +!!! warning "Advanced Session Features" + + When using `EncryptedSession` with advanced session implementations like `AdvancedSQLiteSession`, note that: + + - Methods like `find_turns_by_content()` won't work effectively since message content is encrypted + - Content-based searches operate on encrypted data, limiting their effectiveness + + + +## Key derivation + +EncryptedSession uses HKDF (HMAC-based Key Derivation Function) to derive unique encryption keys per session: + +- **Master key**: Your provided encryption key +- **Session salt**: The session ID +- **Info string**: `"agents.session-store.hkdf.v1"` +- **Output**: 32-byte Fernet key + +This ensures that: +- Each session has a unique encryption key +- Keys cannot be derived without the master key +- Session data cannot be decrypted across different sessions + +## Automatic expiration + +When items exceed the TTL, they are automatically skipped during retrieval: + +```python +# Items older than TTL are silently ignored +items = await session.get_items() # Only returns non-expired items + +# Expired items don't affect session behavior +result = await Runner.run(agent, "Continue conversation", session=session) +``` + +## API Reference + +- [`EncryptedSession`][agents.extensions.memory.encrypt_session.EncryptedSession] - Main class +- [`Session`][agents.memory.session.Session] - Base session protocol diff --git a/docs/sessions.md b/docs/sessions/index.md similarity index 64% rename from docs/sessions.md rename to docs/sessions/index.md index b9a094c20..30a0ad904 100644 --- a/docs/sessions.md +++ b/docs/sessions/index.md @@ -113,37 +113,49 @@ result = await Runner.run( print(f"Agent: {result.final_output}") ``` -## Memory options +## Session types -### No memory (default) +The SDK provides several session implementations for different use cases: -```python -# Default behavior - no session memory -result = await Runner.run(agent, "Hello") -``` - -### OpenAI Conversations API memory +### OpenAI Conversations API sessions -Use the [OpenAI Conversations API](https://platform.openai.com/docs/api-reference/conversations/create) to persist -[conversation state](https://platform.openai.com/docs/guides/conversation-state?api-mode=responses#using-the-conversations-api) without managing your own database. This is helpful when you already rely on OpenAI-hosted infrastructure -for storing conversation history. +Use [OpenAI's Conversations API](https://platform.openai.com/docs/api-reference/conversations) through `OpenAIConversationsSession`. ```python -from agents import OpenAIConversationsSession +from agents import Agent, Runner, OpenAIConversationsSession + +# Create agent +agent = Agent( + name="Assistant", + instructions="Reply very concisely.", +) +# Create a new conversation session = OpenAIConversationsSession() # Optionally resume a previous conversation by passing a conversation ID # session = OpenAIConversationsSession(conversation_id="conv_123") +# Start conversation result = await Runner.run( agent, - "Hello", - session=session, + "What city is the Golden Gate Bridge in?", + session=session ) +print(result.final_output) # "San Francisco" + +# Continue the conversation +result = await Runner.run( + agent, + "What state is it in?", + session=session +) +print(result.final_output) # "California" ``` -### SQLite memory +### SQLite sessions + +The default, lightweight session implementation using SQLite: ```python from agents import SQLiteSession @@ -162,182 +174,78 @@ result = await Runner.run( ) ``` -### Multiple sessions +### SQLAlchemy sessions -```python -from agents import Agent, Runner, SQLiteSession +Production-ready sessions using any SQLAlchemy-supported database: -agent = Agent(name="Assistant") - -# Different sessions maintain separate conversation histories -session_1 = SQLiteSession("user_123", "conversations.db") -session_2 = SQLiteSession("user_456", "conversations.db") +```python +from agents.extensions.memory import SQLAlchemySession -result1 = await Runner.run( - agent, - "Hello", - session=session_1 +# Using database URL +session = SQLAlchemySession.from_url( + "user_123", + url="postgresql+asyncpg://user:pass@localhost/db", + create_tables=True ) -result2 = await Runner.run( - agent, - "Hello", - session=session_2 -) -``` -### SQLAlchemy-powered sessions +# Using existing engine +from sqlalchemy.ext.asyncio import create_async_engine +engine = create_async_engine("postgresql+asyncpg://user:pass@localhost/db") +session = SQLAlchemySession("user_123", engine=engine, create_tables=True) +``` -For more advanced use cases, you can use a SQLAlchemy-powered session backend. This allows you to use any database supported by SQLAlchemy (PostgreSQL, MySQL, SQLite, etc.) for session storage. +See [SQLAlchemy Sessions](sqlalchemy_session.md) for detailed documentation. -**Example 1: Using `from_url` with in-memory SQLite** +### Advanced SQLite sessions -This is the simplest way to get started, ideal for development and testing. +Enhanced SQLite sessions with conversation branching, usage analytics, and structured queries: ```python -import asyncio -from agents import Agent, Runner -from agents.extensions.memory.sqlalchemy_session import SQLAlchemySession +from agents.extensions.memory import AdvancedSQLiteSession -async def main(): - agent = Agent("Assistant") - session = SQLAlchemySession.from_url( - "user-123", - url="sqlite+aiosqlite:///:memory:", - create_tables=True, # Auto-create tables for the demo - ) +# Create with advanced features +session = AdvancedSQLiteSession( + session_id="user_123", + db_path="conversations.db", + create_tables=True +) - result = await Runner.run(agent, "Hello", session=session) +# Automatic usage tracking +result = await Runner.run(agent, "Hello", session=session) +await session.store_run_usage(result) # Track token usage -if __name__ == "__main__": - asyncio.run(main()) +# Conversation branching +await session.create_branch_from_turn(2) # Branch from turn 2 ``` -**Example 2: Using an existing SQLAlchemy engine** - -In a production application, you likely already have a SQLAlchemy `AsyncEngine` instance. You can pass it directly to the session. - -```python -import asyncio -from agents import Agent, Runner -from agents.extensions.memory.sqlalchemy_session import SQLAlchemySession -from sqlalchemy.ext.asyncio import create_async_engine - -async def main(): - # In your application, you would use your existing engine - engine = create_async_engine("sqlite+aiosqlite:///conversations.db") - - agent = Agent("Assistant") - session = SQLAlchemySession( - "user-456", - engine=engine, - create_tables=True, # Auto-create tables for the demo - ) - - result = await Runner.run(agent, "Hello", session=session) - print(result.final_output) - - await engine.dispose() - -if __name__ == "__main__": - asyncio.run(main()) -``` +See [Advanced SQLite Sessions](advanced_sqlite_session.md) for detailed documentation. ### Encrypted sessions -For applications requiring encryption of conversation data at rest, you can use `EncryptedSession` to wrap any session backend with transparent encryption and automatic TTL-based expiration. This requires the `encrypt` extra: `pip install openai-agents[encrypt]`. - -The `EncryptedSession` uses Fernet encryption with per-session key derivation (HKDF) and supports automatic expiration of old messages. When items exceed the TTL, they are silently skipped during retrieval. - -**Example: Encrypting SQLAlchemy session data** +Transparent encryption wrapper for any session implementation: ```python -import asyncio -from agents import Agent, Runner from agents.extensions.memory import EncryptedSession, SQLAlchemySession -async def main(): - # Create underlying session (works with any SessionABC implementation) - underlying_session = SQLAlchemySession.from_url( - session_id="user-123", - url="postgresql+asyncpg://app:secret@db.example.com/agents", - create_tables=True, - ) - - # Wrap with encryption and TTL-based expiration - session = EncryptedSession( - session_id="user-123", - underlying_session=underlying_session, - encryption_key="your-encryption-key", # Use a secure key from your secrets management - ttl=600, # 10 minutes - items older than this are silently skipped - ) +# Create underlying session +underlying_session = SQLAlchemySession.from_url( + "user_123", + url="sqlite+aiosqlite:///conversations.db", + create_tables=True +) - agent = Agent("Assistant") - result = await Runner.run(agent, "Hello", session=session) - print(result.final_output) +# Wrap with encryption and TTL +session = EncryptedSession( + session_id="user_123", + underlying_session=underlying_session, + encryption_key="your-secret-key", + ttl=600 # 10 minutes +) -if __name__ == "__main__": - asyncio.run(main()) +result = await Runner.run(agent, "Hello", session=session) ``` -**Key features:** - -- **Transparent encryption**: Automatically encrypts all session items before storage and decrypts on retrieval -- **Per-session key derivation**: Uses HKDF with the session ID as salt to derive unique encryption keys -- **TTL-based expiration**: Automatically expires old messages based on configurable time-to-live (default: 10 minutes) -- **Flexible key input**: Accepts either Fernet keys or raw strings as encryption keys -- **Wraps any session**: Works with SQLite, SQLAlchemy, or custom session implementations - -!!! warning "Important security notes" - - - Store your encryption key securely (e.g., environment variables, secrets manager) - - Expired tokens are rejected based on the application server's system clock - ensure all servers are time-synchronized with NTP to avoid valid tokens being rejected due to clock drift - - The underlying session still stores encrypted data, so you maintain control over your database infrastructure - - -## Custom memory implementations - -You can implement your own session memory by creating a class that follows the [`Session`][agents.memory.session.Session] protocol: - -```python -from agents.memory.session import SessionABC -from agents.items import TResponseInputItem -from typing import List - -class MyCustomSession(SessionABC): - """Custom session implementation following the Session protocol.""" - - def __init__(self, session_id: str): - self.session_id = session_id - # Your initialization here - - async def get_items(self, limit: int | None = None) -> List[TResponseInputItem]: - """Retrieve conversation history for this session.""" - # Your implementation here - pass - - async def add_items(self, items: List[TResponseInputItem]) -> None: - """Store new items for this session.""" - # Your implementation here - pass - - async def pop_item(self) -> TResponseInputItem | None: - """Remove and return the most recent item from this session.""" - # Your implementation here - pass - - async def clear_session(self) -> None: - """Clear all items for this session.""" - # Your implementation here - pass - -# Use your custom session -agent = Agent(name="Assistant") -result = await Runner.run( - agent, - "Hello", - session=MyCustomSession("my_session") -) -``` +See [Encrypted Sessions](encrypted_session.md) for detailed documentation. ## Session management @@ -358,12 +266,32 @@ Use meaningful session IDs that help you organize conversations: - Use encrypted sessions (`EncryptedSession(session_id, underlying_session, encryption_key)`) to wrap any session with transparent encryption and TTL-based expiration - Consider implementing custom session backends for other production systems (Redis, Django, etc.) for more advanced use cases -### Session management +### Multiple sessions ```python -# Clear a session when conversation should start fresh -await session.clear_session() +from agents import Agent, Runner, SQLiteSession + +agent = Agent(name="Assistant") + +# Different sessions maintain separate conversation histories +session_1 = SQLiteSession("user_123", "conversations.db") +session_2 = SQLiteSession("user_456", "conversations.db") + +result1 = await Runner.run( + agent, + "Help me with my account", + session=session_1 +) +result2 = await Runner.run( + agent, + "What are my charges?", + session=session_2 +) +``` + +### Session sharing +```python # Different agents can share the same session support_agent = Agent(name="Support") billing_agent = Agent(name="Billing") @@ -446,12 +374,58 @@ if __name__ == "__main__": asyncio.run(main()) ``` +## Custom session implementations + +You can implement your own session memory by creating a class that follows the [`Session`][agents.memory.session.Session] protocol: + +```python +from agents.memory.session import SessionABC +from agents.items import TResponseInputItem +from typing import List + +class MyCustomSession(SessionABC): + """Custom session implementation following the Session protocol.""" + + def __init__(self, session_id: str): + self.session_id = session_id + # Your initialization here + + async def get_items(self, limit: int | None = None) -> List[TResponseInputItem]: + """Retrieve conversation history for this session.""" + # Your implementation here + pass + + async def add_items(self, items: List[TResponseInputItem]) -> None: + """Store new items for this session.""" + # Your implementation here + pass + + async def pop_item(self) -> TResponseInputItem | None: + """Remove and return the most recent item from this session.""" + # Your implementation here + pass + + async def clear_session(self) -> None: + """Clear all items for this session.""" + # Your implementation here + pass + +# Use your custom session +agent = Agent(name="Assistant") +result = await Runner.run( + agent, + "Hello", + session=MyCustomSession("my_session") +) +``` + ## API Reference For detailed API documentation, see: -- [`Session`][agents.memory.Session] - Protocol interface -- [`SQLiteSession`][agents.memory.SQLiteSession] - SQLite implementation -- [`OpenAIConversationsSession`](ref/memory/openai_conversations_session.md) - OpenAI Conversations API implementation +- [`Session`][agents.memory.session.Session] - Protocol interface +- [`OpenAIConversationsSession`][agents.memory.OpenAIConversationsSession] - OpenAI Conversations API implementation +- [`SQLiteSession`][agents.memory.sqlite_session.SQLiteSession] - Basic SQLite implementation - [`SQLAlchemySession`][agents.extensions.memory.sqlalchemy_session.SQLAlchemySession] - SQLAlchemy-powered implementation -- [`EncryptedSession`][agents.extensions.memory.encrypt_session.EncryptedSession] - Encrypted session wrapper with TTL +- [`AdvancedSQLiteSession`][agents.extensions.memory.advanced_sqlite_session.AdvancedSQLiteSession] - Enhanced SQLite with branching and analytics +- [`EncryptedSession`][agents.extensions.memory.encrypt_session.EncryptedSession] - Encrypted wrapper for any session diff --git a/docs/sessions/sqlalchemy_session.md b/docs/sessions/sqlalchemy_session.md new file mode 100644 index 000000000..c33cd6a34 --- /dev/null +++ b/docs/sessions/sqlalchemy_session.md @@ -0,0 +1,76 @@ +# SQLAlchemy Sessions + +`SQLAlchemySession` uses SQLAlchemy to provide a production-ready session implementation, allowing you to use any database supported by SQLAlchemy (PostgreSQL, MySQL, SQLite, etc.) for session storage. + +## Installation + +SQLAlchemy sessions require the `sqlalchemy` extra: + +```bash +pip install openai-agents[sqlalchemy] +``` + +## Quick start + +### Using database URL + +The simplest way to get started: + +```python +import asyncio +from agents import Agent, Runner +from agents.extensions.memory import SQLAlchemySession + +async def main(): + agent = Agent("Assistant") + + # Create session using database URL + session = SQLAlchemySession.from_url( + "user-123", + url="sqlite+aiosqlite:///:memory:", + create_tables=True + ) + + result = await Runner.run(agent, "Hello", session=session) + print(result.final_output) + +if __name__ == "__main__": + asyncio.run(main()) +``` + +### Using existing engine + +For applications with existing SQLAlchemy engines: + +```python +import asyncio +from agents import Agent, Runner +from agents.extensions.memory import SQLAlchemySession +from sqlalchemy.ext.asyncio import create_async_engine + +async def main(): + # Create your database engine + engine = create_async_engine("postgresql+asyncpg://user:pass@localhost/db") + + agent = Agent("Assistant") + session = SQLAlchemySession( + "user-456", + engine=engine, + create_tables=True + ) + + result = await Runner.run(agent, "Hello", session=session) + print(result.final_output) + + # Clean up + await engine.dispose() + +if __name__ == "__main__": + asyncio.run(main()) +``` + + +## API Reference + +- [`SQLAlchemySession`][agents.extensions.memory.sqlalchemy_session.SQLAlchemySession] - Main class +- [`Session`][agents.memory.session.Session] - Base session protocol diff --git a/docs/zh/agents.md b/docs/zh/agents.md index df58a0b80..a5690e8c5 100644 --- a/docs/zh/agents.md +++ b/docs/zh/agents.md @@ -4,16 +4,16 @@ search: --- # 智能体 -智能体是你应用中的核心构建模块。一个智能体是一个大型语言模型(LLM),并通过 instructions 和工具进行配置。 +智能体是你应用的核心构建块。一个智能体是经过配置的 LLM(大型语言模型),带有 instructions 和 tools。 ## 基本配置 -你最常为智能体配置的属性有: +你最常配置的智能体属性包括: -- `name`: 一个必需的字符串,用于标识你的智能体。 -- `instructions`: 也称为开发者消息或系统提示词(system prompt)。 -- `model`: 要使用的 LLM,以及可选的 `model_settings`,用于配置如 temperature、top_p 等模型调优参数。 -- `tools`: 智能体可用于完成任务的工具。 +- `name`: 用于标识智能体的必填字符串。 +- `instructions`: 也称为开发者消息或系统提示词。 +- `model`: 使用的 LLM,以及可选的 `model_settings` 用于配置温度(temperature)、top_p 等模型调参。 +- `tools`: 智能体可用来完成任务的工具。 ```python from agents import Agent, ModelSettings, function_tool @@ -33,7 +33,7 @@ agent = Agent( ## 上下文 -智能体在其 `context` 类型上是通用的。Context 是一种依赖注入工具:这是一个你创建并传给 `Runner.run()` 的对象,它会传递给每个智能体、工具、任务转移等,用作一次运行期间的依赖与状态集合。你可以提供任意 Python 对象作为 context。 +智能体对其 `context` 类型是泛化的。Context 是一种依赖注入工具:你创建一个对象并传递给 `Runner.run()`,它会传递给每个智能体、工具、任务转移等,作为本次运行的依赖与状态集合。你可以提供任意 Python 对象作为 context。 ```python @dataclass @@ -52,7 +52,7 @@ agent = Agent[UserContext]( ## 输出类型 -默认情况下,智能体生成纯文本(即 `str`)输出。若你希望智能体生成特定类型的输出,可以使用 `output_type` 参数。常见做法是使用 [Pydantic](https://docs.pydantic.dev/) 对象,但我们支持任何可由 Pydantic 的 [TypeAdapter](https://docs.pydantic.dev/latest/api/type_adapter/) 包装的类型——如 dataclasses、lists、TypedDict 等。 +默认情况下,智能体生成纯文本(即 `str`)输出。如果你希望智能体生成特定类型的输出,可以使用 `output_type` 参数。常见做法是使用 [Pydantic](https://docs.pydantic.dev/) 对象,但我们支持任何可被 Pydantic [TypeAdapter](https://docs.pydantic.dev/latest/api/type_adapter/) 包装的类型——如数据类(dataclasses)、列表(lists)、TypedDict 等。 ```python from pydantic import BaseModel @@ -73,20 +73,20 @@ agent = Agent( !!! note - 当你传入 `output_type` 时,这会指示模型使用 [structured outputs](https://platform.openai.com/docs/guides/structured-outputs) 而非常规纯文本回复。 + 当你传入 `output_type` 时,这会告知模型使用 [structured outputs](https://platform.openai.com/docs/guides/structured-outputs) 而不是常规的纯文本响应。 ## 多智能体系统设计模式 -设计多智能体系统的方法很多,但我们常见两种具有广泛适用性的模式: +设计多智能体系统的方法有很多,但我们常见到两种广泛适用的模式: -1. 管理器(智能体作为工具):一个中心管理器/编排器将专业的子智能体作为工具调用,并保持对话控制权。 -2. 任务转移:对等的智能体将控制权转移给一个专业的智能体,由其接管对话。这是去中心化的。 +1. 管理者(将智能体作为工具):一个中心管理者/编排器将专业化的子智能体作为工具调用,并保持对话控制权。 +2. 任务转移:对等智能体将控制权移交给接管对话的专业化智能体。这是去中心化的。 -更多细节见[构建智能体的实用指南](https://cdn.openai.com/business-guides-and-resources/a-practical-guide-to-building-agents.pdf)。 +更多细节参见[我们的智能体构建实用指南](https://cdn.openai.com/business-guides-and-resources/a-practical-guide-to-building-agents.pdf)。 -### 管理器(智能体作为工具) +### 管理者(将智能体作为工具) -`customer_facing_agent` 处理所有用户交互,并调用作为工具暴露的专业子智能体。详见[工具](tools.md#agents-as-tools)文档。 +`customer_facing_agent` 负责所有用户交互,并将专业化子智能体作为工具调用。更多内容参见 [tools](tools.md#agents-as-tools) 文档。 ```python from agents import Agent @@ -115,7 +115,7 @@ customer_facing_agent = Agent( ### 任务转移 -任务转移是智能体可以委托的子智能体。当发生任务转移时,被委托的智能体会接收对话历史并接管对话。该模式使得模块化、专业化的智能体能在单一任务上表现出色。详见[任务转移](handoffs.md)文档。 +任务转移是智能体可以委派的子智能体。当发生任务转移时,被委派的智能体会接收对话历史并接管对话。该模式支持模块化、专精于单一任务的智能体。更多内容参见[任务转移](handoffs.md)文档。 ```python from agents import Agent @@ -136,7 +136,7 @@ triage_agent = Agent( ## 动态 instructions -在大多数情况下,你可以在创建智能体时直接提供 instructions。但你也可以通过函数动态提供 instructions。该函数将接收智能体和 context,并且必须返回提示词。同步和 `async` 函数均可接受。 +在大多数情况下,你可以在创建智能体时提供 instructions。但你也可以通过函数提供动态 instructions。该函数将接收智能体和上下文,并且必须返回提示词。支持常规函数和 `async` 函数。 ```python def dynamic_instructions( @@ -153,15 +153,15 @@ agent = Agent[UserContext]( ## 生命周期事件(hooks) -有时你希望观测智能体的生命周期。例如,你可能希望记录事件,或在特定事件发生时预取数据。你可以通过 `hooks` 属性挂接到智能体生命周期。继承 [`AgentHooks`][agents.lifecycle.AgentHooks] 类,并重写你感兴趣的方法。 +有时你希望观察智能体的生命周期。例如,你可能希望记录事件,或在特定事件发生时预取数据。你可以通过 `hooks` 属性挂载到智能体生命周期。继承 [`AgentHooks`][agents.lifecycle.AgentHooks] 类,并重写你感兴趣的方法。 ## 安全防护措施 -安全防护措施允许你在智能体运行的同时对用户输入进行并行检查/验证,并在智能体产出后对其输出进行检查。例如,你可以筛查用户输入和智能体输出的相关性。详见[安全防护措施](guardrails.md)文档。 +安全防护措施允许你在智能体运行的同时对用户输入进行检查/验证,并在智能体产出结果后对其输出进行检查。例如,你可以筛查用户输入和智能体输出的相关性。更多内容参见[安全防护措施](guardrails.md)文档。 ## 克隆/复制智能体 -通过在智能体上使用 `clone()` 方法,你可以复制一个智能体,并可选地修改任意你需要的属性。 +通过在智能体上使用 `clone()` 方法,你可以复制一个智能体,并可选地更改任意你想要的属性。 ```python pirate_agent = Agent( @@ -178,12 +178,12 @@ robot_agent = pirate_agent.clone( ## 强制使用工具 -提供工具列表并不总能保证 LLM 会使用某个工具。你可以通过设置 [`ModelSettings.tool_choice`][agents.model_settings.ModelSettings.tool_choice] 来强制使用工具。可用取值为: +提供工具列表并不总能让 LLM 使用工具。你可以通过设置 [`ModelSettings.tool_choice`][agents.model_settings.ModelSettings.tool_choice] 来强制使用工具。可选值包括: -1. `auto`:允许 LLM 自行决定是否使用工具。 -2. `required`:要求 LLM 使用某个工具(但可智能选择具体哪个工具)。 -3. `none`:要求 LLM 不使用工具。 -4. 设置特定字符串,如 `my_tool`,要求 LLM 使用该特定工具。 +1. `auto`,允许 LLM 自行决定是否使用工具。 +2. `required`,要求 LLM 必须使用工具(但可智能地选择哪个工具)。 +3. `none`,要求 LLM 不使用工具。 +4. 设置特定字符串,例如 `my_tool`,要求 LLM 使用该特定工具。 ```python from agents import Agent, Runner, function_tool, ModelSettings @@ -205,8 +205,8 @@ agent = Agent( `Agent` 配置中的 `tool_use_behavior` 参数控制如何处理工具输出: -- `"run_llm_again"`:默认值。运行工具后,由 LLM 处理结果以生成最终回复。 -- `"stop_on_first_tool"`:第一次工具调用的输出将作为最终回复,不再进行后续 LLM 处理。 +- `"run_llm_again"`:默认值。运行工具后,由 LLM 处理结果以生成最终响应。 +- `"stop_on_first_tool"`:第一次工具调用的输出将作为最终响应,不再经过 LLM 进一步处理。 ```python from agents import Agent, Runner, function_tool, ModelSettings @@ -224,7 +224,7 @@ agent = Agent( ) ``` -- `StopAtTools(stop_at_tool_names=[...])`: 如果调用了任一指定工具则停止,并将其输出作为最终回复。 +- `StopAtTools(stop_at_tool_names=[...])`:当调用了任一指定工具时停止,使用其输出作为最终响应。 ```python from agents import Agent, Runner, function_tool @@ -248,7 +248,7 @@ agent = Agent( ) ``` -- `ToolsToFinalOutputFunction`: 一个自定义函数,用于处理工具结果并决定是停止还是继续让 LLM 处理。 +- `ToolsToFinalOutputFunction`:自定义函数,用于处理工具结果并决定是停止还是继续交由 LLM。 ```python from agents import Agent, Runner, function_tool, FunctionToolResult, RunContextWrapper @@ -286,4 +286,4 @@ agent = Agent( !!! note - 为防止无限循环,框架会在一次工具调用后自动将 `tool_choice` 重置为 "auto"。可通过 [`agent.reset_tool_choice`][agents.agent.Agent.reset_tool_choice] 配置此行为。出现无限循环的原因是工具结果会被发送回 LLM,而由于 `tool_choice` 设置,LLM 可能再次产生工具调用,如此反复。 \ No newline at end of file + 为防止无限循环,框架会在一次工具调用后自动将 `tool_choice` 重置为 "auto"。可通过 [`agent.reset_tool_choice`][agents.agent.Agent.reset_tool_choice] 配置该行为。出现无限循环的原因是工具结果会被发送给 LLM,而由于 `tool_choice` 的设置,LLM 又会生成新的工具调用,如此往复。 \ No newline at end of file diff --git a/docs/zh/config.md b/docs/zh/config.md index 3f8ba33c0..2d39a5da8 100644 --- a/docs/zh/config.md +++ b/docs/zh/config.md @@ -2,11 +2,11 @@ search: exclude: true --- -# 配置 SDK +# SDK 配置 -## API 密钥和客户端 +## API 密钥与客户端 -默认情况下,SDK 在导入后会立即查找用于 LLM 请求和追踪的 `OPENAI_API_KEY` 环境变量。如果你无法在应用启动前设置该环境变量,可以使用 [set_default_openai_key()][agents.set_default_openai_key] 函数来设置密钥。 +默认情况下,SDK 在被导入后会立即从环境变量 `OPENAI_API_KEY` 中读取用于 LLM 请求和追踪 的密钥。如果你无法在应用启动前设置该环境变量,可以使用 [set_default_openai_key()][agents.set_default_openai_key] 函数来设置密钥。 ```python from agents import set_default_openai_key @@ -14,7 +14,7 @@ from agents import set_default_openai_key set_default_openai_key("sk-...") ``` -或者,你也可以配置要使用的 OpenAI 客户端。默认情况下,SDK 会创建一个 `AsyncOpenAI` 实例,使用环境变量中的 API 密钥或上面设置的默认密钥。你可以通过使用 [set_default_openai_client()][agents.set_default_openai_client] 函数来更改这一点。 +或者,你也可以配置要使用的 OpenAI 客户端。默认情况下,SDK 会创建一个 `AsyncOpenAI` 实例,使用环境变量中的 API 密钥或上文设置的默认密钥。你可以通过 [set_default_openai_client()][agents.set_default_openai_client] 函数进行更改。 ```python from openai import AsyncOpenAI @@ -24,7 +24,7 @@ custom_client = AsyncOpenAI(base_url="...", api_key="...") set_default_openai_client(custom_client) ``` -最后,你还可以自定义所使用的 OpenAI API。默认情况下,我们使用 OpenAI Responses API。你可以通过使用 [set_default_openai_api()][agents.set_default_openai_api] 函数将其覆盖为使用 Chat Completions API。 +最后,你也可以自定义所使用的 OpenAI API。默认情况下,我们使用 OpenAI Responses API。你可以通过 [set_default_openai_api()][agents.set_default_openai_api] 函数改为使用 Chat Completions API。 ```python from agents import set_default_openai_api @@ -34,7 +34,7 @@ set_default_openai_api("chat_completions") ## 追踪 -追踪默认启用。它默认使用上文中的 OpenAI API 密钥(即环境变量或你设置的默认密钥)。你可以通过使用 [`set_tracing_export_api_key`][agents.set_tracing_export_api_key] 函数专门设置用于追踪的 API 密钥。 +追踪 默认启用。它默认使用上文提到的 OpenAI API 密钥(即环境变量或你设置的默认密钥)。你可以使用 [`set_tracing_export_api_key`][agents.set_tracing_export_api_key] 函数专门设置用于 追踪 的 API 密钥。 ```python from agents import set_tracing_export_api_key @@ -42,7 +42,7 @@ from agents import set_tracing_export_api_key set_tracing_export_api_key("sk-...") ``` -你也可以通过使用 [`set_tracing_disabled()`][agents.set_tracing_disabled] 函数完全禁用追踪。 +你也可以通过 [`set_tracing_disabled()`][agents.set_tracing_disabled] 函数完全禁用 追踪。 ```python from agents import set_tracing_disabled @@ -52,9 +52,9 @@ set_tracing_disabled(True) ## 调试日志 -SDK 有两个 Python 记录器,默认未设置任何处理器。默认情况下,这意味着警告和错误会发送到 `stdout`,而其他日志会被抑制。 +该 SDK 提供两个未设置任何处理器的 Python 日志记录器。默认情况下,这意味着警告和错误会发送到 `stdout`,但其他日志会被抑制。 -要启用详细日志记录,使用 [`enable_verbose_stdout_logging()`][agents.enable_verbose_stdout_logging] 函数。 +要启用详细日志,请使用 [`enable_verbose_stdout_logging()`][agents.enable_verbose_stdout_logging] 函数。 ```python from agents import enable_verbose_stdout_logging @@ -62,7 +62,7 @@ from agents import enable_verbose_stdout_logging enable_verbose_stdout_logging() ``` -或者,你可以通过添加处理器、过滤器、格式化器等自定义日志。更多信息参见 [Python 日志记录指南](https://docs.python.org/3/howto/logging.html)。 +或者,你可以通过添加处理器、过滤器、格式化器等自定义日志。更多内容请参阅 [Python 日志指南](https://docs.python.org/3/howto/logging.html)。 ```python import logging @@ -83,7 +83,7 @@ logger.addHandler(logging.StreamHandler()) ### 日志中的敏感数据 -某些日志可能包含敏感数据(例如,用户数据)。如果你想禁止记录这类数据,请设置以下环境变量。 +某些日志可能包含敏感数据(例如,用户数据)。如果你希望禁止记录这些数据,请设置以下环境变量。 要禁用记录 LLM 输入和输出: @@ -91,7 +91,7 @@ logger.addHandler(logging.StreamHandler()) export OPENAI_AGENTS_DONT_LOG_MODEL_DATA=1 ``` -要禁用记录工具输入和输出: +要禁用记录 工具调用 输入和输出: ```bash export OPENAI_AGENTS_DONT_LOG_TOOL_DATA=1 diff --git a/docs/zh/context.md b/docs/zh/context.md index da6f9f7e1..2ba1d1a95 100644 --- a/docs/zh/context.md +++ b/docs/zh/context.md @@ -4,30 +4,30 @@ search: --- # 上下文管理 -“上下文”一词含义广泛。通常你会关心两类上下文: +“上下文”一词含义宽泛。你可能会关注两大类上下文: -1. 代码本地可用的上下文:即在工具函数运行时、`on_handoff` 等回调中、生命周期钩子里可能需要的数据与依赖。 -2. LLM 可用的上下文:即 LLM 在生成响应时能够看到的数据。 +1. 代码本地可用的上下文:当工具函数运行、`on_handoff` 等回调、生命周期钩子等期间可能需要的数据和依赖。 +2. LLM 可用的上下文:LLM 在生成响应时能够看到的数据。 ## 本地上下文 -这通过 [`RunContextWrapper`][agents.run_context.RunContextWrapper] 类及其内部的 [`context`][agents.run_context.RunContextWrapper.context] 属性来表示。工作方式如下: +这通过 [`RunContextWrapper`][agents.run_context.RunContextWrapper] 类及其内部的 [`context`][agents.run_context.RunContextWrapper.context] 属性来表示。其工作方式如下: 1. 创建任意你想要的 Python 对象。常见做法是使用 dataclass 或 Pydantic 对象。 -2. 将该对象传给各种运行方法(例如:`Runner.run(..., **context=whatever**))`)。 -3. 所有工具调用、生命周期钩子等都会接收一个包装对象 `RunContextWrapper[T]`,其中 `T` 表示你的上下文对象类型,你可以通过 `wrapper.context` 访问它。 +2. 将该对象传给各种运行方法(例如 `Runner.run(..., **context=whatever**)`)。 +3. 所有工具调用、生命周期钩子等都会接收到一个包装对象 `RunContextWrapper[T]`,其中 `T` 表示你的上下文对象类型,你可以通过 `wrapper.context` 访问。 -**最重要**的是:给定一次智能体运行,其所有智能体、工具函数、生命周期等都必须使用相同_类型_的上下文。 +最重要的一点:给定一次智能体运行中的每个智能体、工具函数、生命周期等都必须使用相同类型的上下文。 你可以将上下文用于: -- 运行的情境数据(例如用户名/uid 或关于用户的其他信息) -- 依赖(例如日志记录器对象、数据获取器等) -- 辅助函数 +- 运行的情境化数据(例如用户名/uid 或关于用户的其他信息) +- 依赖(例如 logger 对象、数据获取器等) +- 帮助函数 !!! danger "Note" - 上下文对象**不会**发送给 LLM。它纯粹是一个本地对象,你可以读取、写入并在其上调用方法。 + 上下文对象不会发送给 LLM。它纯粹是一个本地对象,你可以读取、写入并在其上调用方法。 ```python import asyncio @@ -66,17 +66,17 @@ if __name__ == "__main__": asyncio.run(main()) ``` -1. 这是上下文对象。这里我们使用了 dataclass,但你可以使用任意类型。 -2. 这是一个工具。它接收 `RunContextWrapper[UserInfo]`。工具实现会从上下文中读取数据。 -3. 我们用泛型 `UserInfo` 标注智能体,以便类型检查器能捕获错误(例如,如果我们尝试传入一个接收不同上下文类型的工具)。 -4. 通过 `run` 函数传入上下文。 +1. 这是上下文对象。这里使用了 dataclass,但你可以使用任意类型。 +2. 这是一个工具。你可以看到它接收 `RunContextWrapper[UserInfo]`。工具实现会从上下文中读取。 +3. 我们用泛型 `UserInfo` 标记智能体,以便类型检查器能捕获错误(例如,如果我们尝试传入一个使用不同上下文类型的工具)。 +4. 将上下文传给 `run` 函数。 5. 智能体正确调用工具并获得年龄。 --- ### 进阶:`ToolContext` -在某些情况下,你可能希望访问正在执行的工具的额外元数据——例如工具名、调用 ID 或原始参数字符串。 +在某些情况下,你可能希望访问正在执行的工具的额外元数据——例如其名称、调用 ID 或原始参数字符串。 为此,你可以使用扩展自 `RunContextWrapper` 的 [`ToolContext`][agents.tool_context.ToolContext] 类。 ```python @@ -106,22 +106,22 @@ agent = Agent( ``` `ToolContext` 提供与 `RunContextWrapper` 相同的 `.context` 属性, -并额外包含当前工具调用的专用字段: +并额外包含当前工具调用特有的字段: - `tool_name` – 正在调用的工具名称 - `tool_call_id` – 此次工具调用的唯一标识符 - `tool_arguments` – 传给工具的原始参数字符串 -当你在执行期间需要工具级别的元数据时,使用 `ToolContext`。 +当你在执行期间需要工具级元数据时,请使用 `ToolContext`。 对于智能体与工具之间的一般上下文共享,`RunContextWrapper` 已经足够。 --- ## 智能体/LLM 上下文 -当调用 LLM 时,它能看到的**唯一**数据来自对话历史。因此,如果你希望让 LLM 获取某些新数据,必须以能使其进入该历史的方式提供。有几种方法: +当调用 LLM 时,它能看到的唯一数据来自对话历史。这意味着如果你想让 LLM 能够使用某些新数据,你必须以某种方式将其放入该历史中。常见方法包括: -1. 将其添加到智能体的 `instructions`。这也被称为“system prompt(系统提示词)”或“开发者消息”。System prompts 可以是静态字符串,也可以是接收上下文并输出字符串的动态函数。这对于总是有用的信息很常见(例如用户名或当前日期)。 -2. 在调用 `Runner.run` 函数时将其添加到 `input`。这与 `instructions` 的做法类似,但允许你使用处于[指挥链](https://cdn.openai.com/spec/model-spec-2024-05-08.html#follow-the-chain-of-command)较低位置的消息。 -3. 通过 工具调用 暴露它。这对_按需_上下文很有用——LLM 会决定何时需要某些数据,并可调用工具来获取该数据。 -4. 使用 文件检索 或 网络检索。它们是能够从文件或数据库(文件检索)或从网络(网络检索)提取相关数据的特殊工具。这有助于让回答基于相关的上下文数据。 \ No newline at end of file +1. 将其添加到智能体的 `instructions`。这也被称为“系统提示词”或“开发者消息”。系统提示词可以是静态字符串,也可以是接收上下文并输出字符串的动态函数。这对于始终有用的信息很常见(例如用户名或当前日期)。 +2. 在调用 `Runner.run` 函数时,将其添加到 `input`。这与 `instructions` 策略类似,但允许你添加在[指令链](https://cdn.openai.com/spec/model-spec-2024-05-08.html#follow-the-chain-of-command)中层级更低的消息。 +3. 通过 工具调用 暴露。这对按需上下文很有用——LLM 决定何时需要某些数据,并可以调用工具来获取这些数据。 +4. 使用检索或 网络检索。这些是能够从文件或数据库(检索)或从网络(网络检索)获取相关数据的特殊工具。这有助于将响应“落地”到相关的上下文数据中。 \ No newline at end of file diff --git a/docs/zh/examples.md b/docs/zh/examples.md index e2c5c76f0..c01ae5f92 100644 --- a/docs/zh/examples.md +++ b/docs/zh/examples.md @@ -2,92 +2,86 @@ search: exclude: true --- -# 代码示例 +# 示例 -在[仓库](https://github.com/openai/openai-agents-python/tree/main/examples)的 examples 部分查看该 SDK 的多种示例实现。这些代码示例被组织为若干目录,以展示不同的模式和能力。 +在[repo](https://github.com/openai/openai-agents-python/tree/main/examples)的 examples 部分查看该 SDK 的各类示例实现。这些示例按多个目录组织,展示不同的模式与能力。 ## 目录 -- **[agent_patterns](https://github.com/openai/openai-agents-python/tree/main/examples/agent_patterns):** - 此目录中的示例演示常见的智能体设计模式,例如 - - - 确定性工作流 - - 将智能体作为工具 - - 智能体并行执行 - - 条件性工具使用 - - 输入/输出安全防护措施 - - 以 LLM 作为评审 - - 路由 - - 流式传输安全防护措施 - -- **[basic](https://github.com/openai/openai-agents-python/tree/main/examples/basic):** - 这些示例展示了 SDK 的基础能力,例如 - - - Hello World 代码示例(默认模型、GPT-5、开源权重模型) - - 智能体生命周期管理 - - 动态系统提示词 - - 流式传输输出(文本、项、函数调用参数) - - 提示词模板 - - 文件处理(本地与远程、图像与 PDF) - - 用量追踪 - - 非严格输出类型 - - 先前响应 ID 的使用 - -- **[customer_service](https://github.com/openai/openai-agents-python/tree/main/examples/customer_service):** - 航空公司客服系统示例。 - -- **[financial_research_agent](https://github.com/openai/openai-agents-python/tree/main/examples/financial_research_agent):** - 一个金融研究智能体,演示用于金融数据分析的智能体与工具的结构化研究工作流。 - -- **[handoffs](https://github.com/openai/openai-agents-python/tree/main/examples/handoffs):** - 查看结合消息过滤的智能体任务转移的实用示例。 - -- **[hosted_mcp](https://github.com/openai/openai-agents-python/tree/main/examples/hosted_mcp):** - 演示如何使用托管 MCP (Model Context Protocol) 连接器和审批的示例。 - -- **[mcp](https://github.com/openai/openai-agents-python/tree/main/examples/mcp):** - 学习如何使用 MCP (Model Context Protocol) 构建智能体,包括: - - - 文件系统代码示例 - - Git 代码示例 - - MCP prompt server 代码示例 - - SSE (Server-Sent Events) 代码示例 - - 可流式传输的 HTTP 代码示例 - -- **[memory](https://github.com/openai/openai-agents-python/tree/main/examples/memory):** - 不同智能体内存实现的示例,包括: - - - SQLite 会话存储 - - 高级 SQLite 会话存储 - - Redis 会话存储 - - SQLAlchemy 会话存储 - - 加密会话存储 - - OpenAI 会话存储 - -- **[model_providers](https://github.com/openai/openai-agents-python/tree/main/examples/model_providers):** - 了解如何在 SDK 中使用非 OpenAI 模型,包括自定义提供方和 LiteLLM 集成。 - -- **[realtime](https://github.com/openai/openai-agents-python/tree/main/examples/realtime):** - 展示如何使用 SDK 构建实时体验的示例,包括: - - - Web 应用 - - 命令行界面 - - Twilio 集成 - -- **[reasoning_content](https://github.com/openai/openai-agents-python/tree/main/examples/reasoning_content):** - 演示如何处理推理内容与 structured outputs 的示例。 - -- **[research_bot](https://github.com/openai/openai-agents-python/tree/main/examples/research_bot):** - 简易的 deep research 克隆,演示复杂的多智能体研究工作流。 - -- **[tools](https://github.com/openai/openai-agents-python/tree/main/examples/tools):** - 了解如何实现由OpenAI托管的工具,例如: - - - 网络检索以及带筛选器的网络检索 - - 文件检索 - - Code interpreter - - 计算机操作 - - 图像生成 - -- **[voice](https://github.com/openai/openai-agents-python/tree/main/examples/voice):** - 查看语音智能体的示例,使用我们的 TTS 与 STT 模型,包括流式语音示例。 \ No newline at end of file +- **[agent_patterns](https://github.com/openai/openai-agents-python/tree/main/examples/agent_patterns):** + 本目录中的示例展示常见的智能体设计模式,例如: + - 确定性工作流 + - 将智能体作为工具 + - 并行智能体执行 + - 条件性工具使用 + - 输入/输出安全防护措施 + - LLM 作为裁判 + - 路由 + - 流式传输安全防护措施 + +- **[basic](https://github.com/openai/openai-agents-python/tree/main/examples/basic):** + 这些示例展示 SDK 的基础能力,例如: + - Hello World 代码示例(默认模型、GPT-5、open-weight 模型) + - 智能体生命周期管理 + - 动态系统提示词 + - 流式输出(文本、条目、函数调用参数) + - 提示模板 + - 文件处理(本地与远程、图像与 PDF) + - 使用情况追踪 + - 非严格输出类型 + - 先前响应 ID 的使用 + +- **[customer_service](https://github.com/openai/openai-agents-python/tree/main/examples/customer_service):** + 航空公司的客服系统示例。 + +- **[financial_research_agent](https://github.com/openai/openai-agents-python/tree/main/examples/financial_research_agent):** + 一个金融研究智能体,展示通过智能体与工具实现结构化的金融数据分析工作流。 + +- **[handoffs](https://github.com/openai/openai-agents-python/tree/main/examples/handoffs):** + 查看带消息过滤的智能体任务转移的实用示例。 + +- **[hosted_mcp](https://github.com/openai/openai-agents-python/tree/main/examples/hosted_mcp):** + 展示如何使用托管的 MCP (Model Context Protocol) 连接器和审批的示例。 + +- **[mcp](https://github.com/openai/openai-agents-python/tree/main/examples/mcp):** + 学习如何使用 MCP (Model Context Protocol) 构建智能体,包括: + - 文件系统示例 + - Git 示例 + - MCP 提示服务示例 + - SSE (Server-Sent Events) 示例 + - 可流式传输的 HTTP 示例 + +- **[memory](https://github.com/openai/openai-agents-python/tree/main/examples/memory):** + 展示不同的智能体记忆实现方式,包括: + - SQLite 会话存储 + - 高级 SQLite 会话存储 + - Redis 会话存储 + - SQLAlchemy 会话存储 + - 加密会话存储 + - OpenAI 会话存储 + +- **[model_providers](https://github.com/openai/openai-agents-python/tree/main/examples/model_providers):** + 了解如何在 SDK 中使用非 OpenAI 模型,包括自定义提供方与 LiteLLM 集成。 + +- **[realtime](https://github.com/openai/openai-agents-python/tree/main/examples/realtime):** + 展示如何使用 SDK 构建实时体验的示例,包括: + - Web 应用 + - 命令行界面 + - 与 Twilio 的集成 + +- **[reasoning_content](https://github.com/openai/openai-agents-python/tree/main/examples/reasoning_content):** + 演示如何处理推理内容与 structured outputs 的示例。 + +- **[research_bot](https://github.com/openai/openai-agents-python/tree/main/examples/research_bot):** + 简单的深度研究克隆,展示复杂的多智能体研究工作流。 + +- **[tools](https://github.com/openai/openai-agents-python/tree/main/examples/tools):** + 了解如何实现由OpenAI托管的工具,例如: + - 网络检索以及带筛选的网络检索 + - 文件检索 + - Code interpreter + - 计算机操作 + - 图像生成 + +- **[voice](https://github.com/openai/openai-agents-python/tree/main/examples/voice):** + 查看语音智能体示例,使用我们的 TTS 和 STT 模型,包括流式语音示例。 \ No newline at end of file diff --git a/docs/zh/guardrails.md b/docs/zh/guardrails.md index a5d6d5241..78d55ad37 100644 --- a/docs/zh/guardrails.md +++ b/docs/zh/guardrails.md @@ -4,44 +4,44 @@ search: --- # 安全防护措施 -安全防护措施与您的智能体_并行_运行,使您能够对用户输入进行检查和验证。比如,假设您有一个使用非常智能(因此也较慢/昂贵)的模型来处理客户请求的智能体。您不希望恶意用户让该模型帮他们做数学作业。因此,您可以用一个快速/廉价的模型运行一条安全防护措施。如果该安全防护措施检测到恶意使用,它可以立即抛出错误,从而阻止昂贵模型运行,为您节省时间/金钱。 +安全防护措施与您的智能体_并行_运行,使您能够对用户输入进行检查与校验。比如,假设您有一个使用非常智能(因此也较慢/昂贵)模型来处理客户请求的智能体。您并不希望恶意用户让该模型帮他们做数学作业。因此,您可以使用一个快速/廉价模型来运行安全防护措施。如果该安全防护措施检测到恶意使用,它可以立即抛出错误,从而阻止昂贵模型的运行,帮您节省时间/金钱。 -安全防护措施分为两种类型: +安全防护措施有两种类型: -1. 输入安全防护措施在初始用户输入上运行 -2. 输出安全防护措施在最终智能体输出上运行 +1. 输入安全防护措施运行在初始用户输入上 +2. 输出安全防护措施运行在最终智能体输出上 ## 输入安全防护措施 输入安全防护措施分三步运行: 1. 首先,安全防护措施接收与智能体相同的输入。 -2. 接着,运行安全防护措施函数以生成一个[`GuardrailFunctionOutput`][agents.guardrail.GuardrailFunctionOutput],随后将其包装为[`InputGuardrailResult`][agents.guardrail.InputGuardrailResult] -3. 最后,我们检查[`.tripwire_triggered`][agents.guardrail.GuardrailFunctionOutput.tripwire_triggered]是否为 true。若为 true,则会抛出[`InputGuardrailTripwireTriggered`][agents.exceptions.InputGuardrailTripwireTriggered]异常,您即可适当回复用户或处理该异常。 +2. 接着,安全防护函数运行并生成一个[`GuardrailFunctionOutput`][agents.guardrail.GuardrailFunctionOutput],随后被包装在[`InputGuardrailResult`][agents.guardrail.InputGuardrailResult]中 +3. 最后,我们检查[`.tripwire_triggered`][agents.guardrail.GuardrailFunctionOutput.tripwire_triggered]是否为 true。若为 true,则会抛出[`InputGuardrailTripwireTriggered`][agents.exceptions.InputGuardrailTripwireTriggered]异常,以便您适当响应用户或处理该异常。 !!! Note - 输入安全防护措施旨在对用户输入运行,因此智能体的安全防护措施只会在该智能体是*第一个*智能体时运行。您可能会疑惑,为什么 `guardrails` 属性在智能体上,而不是传给 `Runner.run`?这是因为安全防护措施往往与具体的智能体相关——您会为不同的智能体运行不同的安全防护措施,因此将代码就近放置有助于可读性。 + 输入安全防护措施旨在运行于用户输入之上,因此仅当该智能体是*第一个*智能体时,才会运行该智能体的安全防护措施。您可能会想,为什么把 `guardrails` 属性放在智能体上,而不是传给 `Runner.run`?这是因为安全防护措施通常与具体的 Agent 密切相关——您会为不同的智能体运行不同的安全防护措施,因此将代码就地放置有助于可读性。 ## 输出安全防护措施 输出安全防护措施分三步运行: -1. 首先,安全防护措施接收由智能体产出的输出。 -2. 接着,运行安全防护措施函数以生成一个[`GuardrailFunctionOutput`][agents.guardrail.GuardrailFunctionOutput],随后将其包装为[`OutputGuardrailResult`][agents.guardrail.OutputGuardrailResult] -3. 最后,我们检查[`.tripwire_triggered`][agents.guardrail.GuardrailFunctionOutput.tripwire_triggered]是否为 true。若为 true,则会抛出[`OutputGuardrailTripwireTriggered`][agents.exceptions.OutputGuardrailTripwireTriggered]异常,您即可适当回复用户或处理该异常。 +1. 首先,安全防护措施接收由智能体产生的输出。 +2. 接着,安全防护函数运行并生成一个[`GuardrailFunctionOutput`][agents.guardrail.GuardrailFunctionOutput],随后被包装在[`OutputGuardrailResult`][agents.guardrail.OutputGuardrailResult]中 +3. 最后,我们检查[`.tripwire_triggered`][agents.guardrail.GuardrailFunctionOutput.tripwire_triggered]是否为 true。若为 true,则会抛出[`OutputGuardrailTripwireTriggered`][agents.exceptions.OutputGuardrailTripwireTriggered]异常,以便您适当响应用户或处理该异常。 !!! Note - 输出安全防护措施旨在对最终的智能体输出运行,因此智能体的安全防护措施只会在该智能体是*最后一个*智能体时运行。与输入安全防护措施类似,我们这样做是因为安全防护措施往往与具体的智能体相关——您会为不同的智能体运行不同的安全防护措施,因此将代码就近放置有助于可读性。 + 输出安全防护措施旨在运行于最终的智能体输出之上,因此仅当该智能体是*最后一个*智能体时,才会运行该智能体的安全防护措施。与输入安全防护措施类似,我们这样做是因为安全防护措施通常与具体的 Agent 密切相关——您会为不同的智能体运行不同的安全防护措施,因此将代码就地放置有助于可读性。 -## 触发绊线 +## 触发线 -如果输入或输出未通过安全防护措施,安全防护措施可以通过触发绊线来发出信号。一旦我们发现某个安全防护措施触发了绊线,就会立即抛出`{Input,Output}GuardrailTripwireTriggered`异常并停止智能体执行。 +如果输入或输出未通过安全防护措施,安全防护措施可以通过触发线发出信号。一旦我们发现某个安全防护措施触发了触发线,就会立即抛出`{Input,Output}GuardrailTripwireTriggered`异常,并停止 Agent 执行。 ## 安全防护措施实现 -您需要提供一个接收输入并返回[`GuardrailFunctionOutput`][agents.guardrail.GuardrailFunctionOutput]的函数。在此示例中,我们将通过在底层运行一个智能体来实现。 +您需要提供一个接收输入并返回[`GuardrailFunctionOutput`][agents.guardrail.GuardrailFunctionOutput]的函数。在以下示例中,我们将通过在幕后运行一个 Agent 来实现这一点。 ```python from pydantic import BaseModel @@ -94,12 +94,12 @@ async def main(): print("Math homework guardrail tripped") ``` -1. 我们将在安全防护措施函数中使用此智能体。 -2. 这是接收智能体输入/上下文并返回结果的安全防护措施函数。 -3. 我们可以在安全防护措施结果中包含额外信息。 +1. 我们将在安全防护函数中使用此智能体。 +2. 这是接收智能体输入/上下文并返回结果的安全防护函数。 +3. 我们可以在安全防护结果中包含额外信息。 4. 这是定义工作流的实际智能体。 -输出安全防护措施类似。 +输出安全防护措施与之类似。 ```python from pydantic import BaseModel @@ -154,5 +154,5 @@ async def main(): 1. 这是实际智能体的输出类型。 2. 这是安全防护措施的输出类型。 -3. 这是接收智能体输出并返回结果的安全防护措施函数。 +3. 这是接收智能体输出并返回结果的安全防护函数。 4. 这是定义工作流的实际智能体。 \ No newline at end of file diff --git a/docs/zh/handoffs.md b/docs/zh/handoffs.md index 083573c2e..175e05bbf 100644 --- a/docs/zh/handoffs.md +++ b/docs/zh/handoffs.md @@ -4,19 +4,19 @@ search: --- # 任务转移 -任务转移允许一个智能体将任务委托给另一个智能体。这在不同智能体各自专长不同领域的场景中特别有用。例如,一个客服应用可能拥有分别处理订单状态、退款、常见问题等任务的智能体。 +任务转移允许一个智能体将任务委派给另一个智能体。这在不同智能体各自专长不同领域的场景中尤为有用。例如,一个客户支持应用可能有不同的智能体分别处理订单状态、退款、常见问题等任务。 -对 LLM 而言,任务转移会被表示为工具。因此,如果要转移给名为 `Refund Agent` 的智能体,该工具将被命名为 `transfer_to_refund_agent`。 +在 LLM 看来,任务转移被表示为工具。因此,如果要将任务转移给名为 `Refund Agent` 的智能体,该工具将被命名为 `transfer_to_refund_agent`。 ## 创建任务转移 -所有智能体都有一个 [`handoffs`][agents.agent.Agent.handoffs] 参数,它可以直接接收一个 `Agent`,或者接收一个用于自定义任务转移的 `Handoff` 对象。 +所有智能体都有一个 [`handoffs`][agents.agent.Agent.handoffs] 参数,它既可以直接接收一个 `Agent`,也可以接收一个用于自定义任务转移的 `Handoff` 对象。 -你可以使用 Agents SDK 提供的 [`handoff()`][agents.handoffs.handoff] 函数来创建任务转移。该函数允许你指定要转移到的智能体,并可选地提供覆盖项和输入过滤器。 +你可以使用 Agents SDK 提供的 [`handoff()`][agents.handoffs.handoff] 函数来创建任务转移。此函数允许你指定要转移到的智能体,并可选地提供覆盖项和输入过滤器。 ### 基本用法 -以下是创建一个简单任务转移的方法: +以下展示如何创建一个简单的任务转移: ```python from agents import Agent, handoff @@ -28,19 +28,19 @@ refund_agent = Agent(name="Refund agent") triage_agent = Agent(name="Triage agent", handoffs=[billing_agent, handoff(refund_agent)]) ``` -1. 你可以直接使用智能体(如 `billing_agent`),或者使用 `handoff()` 函数。 +1. 你可以直接使用智能体(如 `billing_agent`),也可以使用 `handoff()` 函数。 ### 通过 `handoff()` 函数自定义任务转移 -[`handoff()`][agents.handoffs.handoff] 函数允许你进行自定义。 +[`handoff()`][agents.handoffs.handoff] 函数可用于自定义行为。 - `agent`: 要将任务转移到的智能体。 -- `tool_name_override`: 默认使用 `Handoff.default_tool_name()` 函数,其结果为 `transfer_to_`。你可以覆盖该名称。 -- `tool_description_override`: 覆盖 `Handoff.default_tool_description()` 提供的默认工具描述。 -- `on_handoff`: 当任务转移被调用时执行的回调函数。这对于在确认任务转移被调用后立即启动数据获取等操作非常有用。该函数接收智能体上下文,并且可选地接收由 LLM 生成的输入。输入数据由 `input_type` 参数控制。 +- `tool_name_override`: 默认使用 `Handoff.default_tool_name()`,其结果为 `transfer_to_`。你可以覆盖此值。 +- `tool_description_override`: 覆盖来自 `Handoff.default_tool_description()` 的默认工具描述。 +- `on_handoff`: 任务转移被调用时执行的回调函数。可用于在确定将进行任务转移后立即启动数据获取等操作。该函数会接收智能体上下文,并可选地接收由 LLM 生成的输入。输入数据由 `input_type` 参数控制。 - `input_type`: 任务转移期望的输入类型(可选)。 -- `input_filter`: 允许你过滤下一个智能体接收到的输入。详见下文。 -- `is_enabled`: 是否启用该任务转移。可以是布尔值或返回布尔值的函数,从而允许你在运行时动态启用或禁用任务转移。 +- `input_filter`: 允许你过滤下一个智能体接收的输入。详见下文。 +- `is_enabled`: 是否启用此任务转移。可以是布尔值或返回布尔值的函数,允许你在运行时动态启用或禁用任务转移。 ```python from agents import Agent, handoff, RunContextWrapper @@ -60,7 +60,7 @@ handoff_obj = handoff( ## 任务转移输入 -在某些情况下,你希望 LLM 在调用任务转移时提供一些数据。例如,设想转移到一个“升级智能体”。你可能希望提供一个原因,以便进行日志记录。 +在某些情况下,你希望 LLM 在调用任务转移时提供一些数据。例如,设想转移到一个“升级处理智能体(Escalation agent)”。你可能希望提供一个原因,以便进行日志记录。 ```python from pydantic import BaseModel @@ -84,9 +84,9 @@ handoff_obj = handoff( ## 输入过滤器 -当发生任务转移时,新智能体会像接管对话一样,能够看到先前的整个对话历史。如果你想改变这一点,可以设置一个 [`input_filter`][agents.handoffs.Handoff.input_filter]。输入过滤器是一个函数,它通过 [`HandoffInputData`][agents.handoffs.HandoffInputData] 接收现有输入,并且必须返回一个新的 `HandoffInputData`。 +当发生任务转移时,就好像新的智能体接管了对话,并能看到之前的全部对话历史。如果你希望更改这一行为,可以设置一个 [`input_filter`][agents.handoffs.Handoff.input_filter]。输入过滤器是一个函数,它通过 [`HandoffInputData`][agents.handoffs.HandoffInputData] 接收现有输入,并且必须返回一个新的 `HandoffInputData`。 -有一些常见模式(例如从历史中移除所有工具调用),已经在 [`agents.extensions.handoff_filters`][] 中为你实现。 +有一些常见模式(例如从历史记录中移除所有工具调用),已在 [`agents.extensions.handoff_filters`][] 中为你实现。 ```python from agents import Agent, handoff @@ -104,7 +104,7 @@ handoff_obj = handoff( ## 推荐提示词 -为确保 LLM 正确理解任务转移,我们建议在你的智能体中包含有关任务转移的信息。我们在 [`agents.extensions.handoff_prompt.RECOMMENDED_PROMPT_PREFIX`][] 中提供了建议的前缀,或者你可以调用 [`agents.extensions.handoff_prompt.prompt_with_handoff_instructions`][] 将推荐的数据自动添加到你的提示词中。 +为确保 LLM 正确理解任务转移,我们建议在你的智能体中包含关于任务转移的信息。我们在 [`agents.extensions.handoff_prompt.RECOMMENDED_PROMPT_PREFIX`][] 中提供了一个推荐前缀,或者你可以调用 [`agents.extensions.handoff_prompt.prompt_with_handoff_instructions`][] 将推荐数据自动添加到你的提示词中。 ```python from agents import Agent diff --git a/docs/zh/index.md b/docs/zh/index.md index 5d100e0f2..b5473ed18 100644 --- a/docs/zh/index.md +++ b/docs/zh/index.md @@ -4,31 +4,31 @@ search: --- # OpenAI Agents SDK -[OpenAI Agents SDK](https://github.com/openai/openai-agents-python) 让你以轻量、易用、极少抽象的方式构建智能体式 AI 应用。它是我们此前智能体实验项目 [Swarm](https://github.com/openai/swarm/tree/main) 的可用于生产的升级版。Agents SDK 仅包含一小组基本组件: +[OpenAI Agents SDK](https://github.com/openai/openai-agents-python) 使你能够以轻量、易用、抽象极少的方式构建智能体 AI 应用。它是我们此前智能体实验项目 [Swarm](https://github.com/openai/swarm/tree/main) 的面向生产的升级版。Agents SDK 仅包含一小组基本组件: -- **智能体**:配备 instructions 和 tools 的 LLMs -- **任务转移**:允许智能体将特定任务委派给其他智能体 -- **安全防护措施**:用于对智能体输入和输出进行验证 -- **会话**:在多次智能体运行之间自动维护对话历史 +- **智能体**:配备指令和工具的 LLM +- **任务转移**:允许智能体将特定任务委派给其他智能体 +- **安全防护措施**:对智能体的输入与输出进行验证 +- **会话**:在多次运行中自动维护对话历史 -结合 Python,这些基本组件足以表达工具与智能体之间的复杂关系,让你无需陡峭学习曲线即可构建真实应用。此外,SDK 内置 **追踪**,可用于可视化与调试智能体流程,并支持评估,甚至为你的应用微调模型。 +结合 Python,这些基本组件足以表达工具与智能体之间的复杂关系,让你无需陡峭的学习曲线即可构建真实世界的应用。此外,SDK 内置了 **追踪**,可视化并调试你的智能体流程,对其进行评估,甚至为你的应用微调模型。 ## 为什么使用 Agents SDK 该 SDK 的两条核心设计原则: -1. 功能足够丰富以值得使用,但基本组件足够少以便快速上手。 -2. 开箱即用,同时允许你精细定制具体行为。 +1. 功能足够丰富以值得使用,但基本组件足够精简以便快速上手。 +2. 开箱即用效果出色,同时允许你精确自定义行为。 -主要特性包括: +SDK 的主要特性包括: -- 智能体循环:内置循环负责调用工具、将结果发送给 LLM,并持续循环直至 LLM 完成。 -- Python 优先:使用内置语言特性来编排与串联智能体,无需学习新的抽象。 -- 任务转移:强大的能力,用于在多个智能体之间协调与委派。 -- 安全防护措施:与智能体并行执行输入验证与检查,如检查失败则提前中断。 -- 会话:在多次智能体运行之间自动管理对话历史,免去手动状态处理。 -- 工具调用:将任意 Python 函数变为工具,自动生成模式并通过 Pydantic 驱动验证。 -- 追踪:内置追踪用于可视化、调试与监控工作流,并可使用 OpenAI 的评估、微调与蒸馏工具套件。 +- 智能体循环:内置循环来调用工具、将结果发送给 LLM,并循环直至 LLM 完成。 +- Python 优先:使用语言内置特性编排与串联智能体,无需学习新的抽象。 +- 任务转移:在多个智能体之间进行协调与委派的强大能力。 +- 安全防护措施:与智能体并行运行输入验证与检查,一旦失败即可提前终止。 +- 会话:跨多次运行自动管理对话历史,免去手动状态处理。 +- 工具调用:将任意 Python 函数转换为工具,自动生成模式并使用 Pydantic 进行验证。 +- 追踪:内置追踪以可视化、调试并监控工作流,同时可使用 OpenAI 的评估、微调与蒸馏工具套件。 ## 安装 @@ -51,7 +51,7 @@ print(result.final_output) # Infinite loop's dance. ``` -(_如果运行此示例,请确保设置 `OPENAI_API_KEY` 环境变量_) +(运行前请确保已设置 `OPENAI_API_KEY` 环境变量) ```bash export OPENAI_API_KEY=sk-... diff --git a/docs/zh/mcp.md b/docs/zh/mcp.md index 518ed1923..d7def1c2a 100644 --- a/docs/zh/mcp.md +++ b/docs/zh/mcp.md @@ -4,34 +4,32 @@ search: --- # Model context protocol (MCP) -[Model context protocol](https://modelcontextprotocol.io/introduction)(MCP)标准化了应用向语言模型暴露工具和上下文的方式。官方文档中写道: +[Model context protocol](https://modelcontextprotocol.io/introduction)(MCP)标准化了应用如何向语言模型暴露工具和上下文。摘自官方文档: -> MCP is an open protocol that standardizes how applications provide context to LLMs. Think of MCP like a USB-C port for AI -> applications. Just as USB-C provides a standardized way to connect your devices to various peripherals and accessories, MCP -> provides a standardized way to connect AI models to different data sources and tools. +> MCP 是一种开放协议,用于标准化应用向 LLM 提供上下文的方式。可以把 MCP 想象成 AI 应用的 USB-C 接口。就像 USB-C 提供了一种标准化方式,将你的设备连接到各种外设和配件,MCP 也提供了一种标准化方式,将 AI 模型连接到不同的数据源和工具。 -Agents Python SDK 支持多种 MCP 传输方式。这样你可以复用现有的 MCP 服务或自建服务,将文件系统、HTTP 或基于连接器的工具暴露给智能体。 +Agents Python SDK 支持多种 MCP 传输方式。这使你可以复用现有 MCP 服务或自行构建,以向智能体暴露文件系统、HTTP 或由连接器支持的工具。 ## 选择 MCP 集成方式 -在将 MCP 服务接入智能体之前,先确定工具调用应在何处执行,以及你能使用哪些传输方式。下表总结了 Python SDK 支持的选项。 +在将 MCP 服务接入智能体前,请先决定工具调用应在哪里执行,以及你可以使用哪些传输方式。下表总结了 Python SDK 支持的选项。 -| 你的需求 | 推荐选项 | -| ------------------------------------------------------------------------------------ | ----------------------------------------------------- | -| 让 OpenAI 的 Responses API 代表模型调用可公开访问的 MCP 服务 | **托管 MCP 服务工具**,通过 [`HostedMCPTool`][agents.tool.HostedMCPTool] | -| 连接你在本地或远程运行的可流式传输的 HTTP 服务 | **可流式 HTTP MCP 服务**,通过 [`MCPServerStreamableHttp`][agents.mcp.server.MCPServerStreamableHttp] | -| 与实现了基于 Server-Sent Events 的 HTTP 的服务通信 | **HTTP with SSE MCP 服务**,通过 [`MCPServerSse`][agents.mcp.server.MCPServerSse] | -| 启动本地进程并通过 stdin/stdout 通信 | **stdio MCP 服务**,通过 [`MCPServerStdio`][agents.mcp.server.MCPServerStdio] | +| 你的需求 | 推荐选项 | +| ---------------------------------------------------------------------------------------- | ------------------------------------------------------ | +| 让 OpenAI 的 Responses API 代表模型调用可公网访问的 MCP 服务 | **托管的 MCP 服务器工具**,通过 [`HostedMCPTool`][agents.tool.HostedMCPTool] | +| 连接你在本地或远程运行的 Streamable HTTP 服务 | **可流式 HTTP MCP 服务器**,通过 [`MCPServerStreamableHttp`][agents.mcp.server.MCPServerStreamableHttp] | +| 与实现了带 Server-Sent Events 的 HTTP 的服务器通信 | **HTTP + SSE MCP 服务器**,通过 [`MCPServerSse`][agents.mcp.server.MCPServerSse] | +| 启动本地进程并通过 stdin/stdout 通信 | **stdio MCP 服务器**,通过 [`MCPServerStdio`][agents.mcp.server.MCPServerStdio] | -下文将逐一介绍各选项的配置方法及何时优先选择某种传输方式。 +下文将逐一介绍每种选项、配置方法,以及何时优先选择某种传输方式。 -## 1. 托管 MCP 服务工具 +## 1. 托管的 MCP 服务器工具 -托管工具将整个工具调用往返过程放在 OpenAI 的基础设施中。你的代码无需列出和调用工具,[`HostedMCPTool`][agents.tool.HostedMCPTool] 会将服务标签(以及可选的连接器元数据)转发给 Responses API。模型会列出远程服务的工具并直接调用,而无需额外回调到你的 Python 进程。托管工具目前适用于支持 Responses API 托管 MCP 集成的 OpenAI 模型。 +托管工具将整个工具的往返调用交给 OpenAI 的基础设施处理。你的代码无需列出和调用工具,[`HostedMCPTool`][agents.tool.HostedMCPTool] 会将服务器标签(以及可选的连接器元数据)转发给 Responses API。模型会列出远程服务器的工具并直接调用,无需额外回调到你的 Python 进程。托管工具目前适用于支持 Responses API 托管 MCP 集成的 OpenAI 模型。 ### 基础托管 MCP 工具 -在智能体的 `tools` 列表中添加 [`HostedMCPTool`][agents.tool.HostedMCPTool] 以创建托管工具。`tool_config` 字典与发送到 REST API 的 JSON 相对应: +通过在智能体的 `tools` 列表中添加 [`HostedMCPTool`][agents.tool.HostedMCPTool] 来创建托管工具。`tool_config` 字典与您发送到 REST API 的 JSON 相同: ```python import asyncio @@ -59,11 +57,11 @@ async def main() -> None: asyncio.run(main()) ``` -托管服务会自动暴露其工具;你无需将其添加到 `mcp_servers`。 +托管服务器会自动暴露其工具;你无需将其添加到 `mcp_servers`。 -### 托管 MCP 结果流式传输 +### 托管 MCP 结果的流式传输 -托管工具以与工具调用完全相同的方式支持流式传输。将 `stream=True` 传给 `Runner.run_streamed`,即可在模型仍在运行时消费增量 MCP 输出: +托管工具以与工具调用相同的方式支持流式传输。向 `Runner.run_streamed` 传入 `stream=True`,以在模型运行期间消费增量的 MCP 输出: ```python result = Runner.run_streamed(agent, "Summarise this repository's top languages") @@ -73,9 +71,9 @@ async for event in result.stream_events(): print(result.final_output) ``` -### 可选审批流程 +### 可选的审批流程 -如果某个服务可执行敏感操作,你可以在每次工具执行前要求人工或程序化审批。在 `tool_config` 中配置 `require_approval`,可以是单一策略(`"always"`、`"never"`),也可以是将工具名称映射到策略的字典。若在 Python 中做决策,提供一个 `on_approval_request` 回调。 +如果服务器可以执行敏感操作,你可以在每次工具执行前要求人工或程序化审批。在 `tool_config` 中配置 `require_approval`,可以是单一策略(`"always"`、`"never"`)或一个将工具名映射到策略的字典。若要在 Python 内部做决定,提供一个 `on_approval_request` 回调。 ```python from agents import MCPToolApprovalFunctionResult, MCPToolApprovalRequest @@ -103,11 +101,11 @@ agent = Agent( ) ``` -该回调可为同步或异步,当模型需要审批数据以继续运行时会被调用。 +该回调可以是同步或异步的,当模型需要审批数据以继续运行时会被调用。 -### 基于连接器的托管服务 +### 由连接器支持的托管服务器 -托管 MCP 也支持 OpenAI 连接器。你无需指定 `server_url`,改为提供 `connector_id` 和访问令牌。Responses API 处理认证,托管服务将暴露连接器的工具。 +托管 MCP 也支持 OpenAI 连接器。你可以不指定 `server_url`,改为提供 `connector_id` 和访问令牌。Responses API 会处理认证,托管服务器将暴露该连接器的工具。 ```python import os @@ -123,12 +121,13 @@ HostedMCPTool( ) ``` -完整可运行的托管工具示例——包括流式传输、审批和连接器——见 +包含流式传输、审批和连接器的完整托管工具示例位于 [`examples/hosted_mcp`](https://github.com/openai/openai-agents-python/tree/main/examples/hosted_mcp)。 -## 2. 可流式 HTTP MCP 服务 +## 2. 可流式 HTTP MCP 服务器 -当你希望自行管理网络连接时,使用 [`MCPServerStreamableHttp`][agents.mcp.server.MCPServerStreamableHttp]。当你掌控传输或希望在自有基础设施中运行服务并保持较低延迟时,可流式 HTTP 服务非常合适。 +当你希望自行管理网络连接时,请使用 +[`MCPServerStreamableHttp`][agents.mcp.server.MCPServerStreamableHttp]。当你可控传输层,或想把服务器运行在自己的基础设施中以保持低延迟时,可流式 HTTP 服务器是理想选择。 ```python import asyncio @@ -163,16 +162,17 @@ async def main() -> None: asyncio.run(main()) ``` -构造函数支持以下额外选项: +构造函数接受以下附加选项: - `client_session_timeout_seconds` 控制 HTTP 读取超时。 - `use_structured_content` 切换是否优先使用 `tool_result.structured_content` 而非文本输出。 -- `max_retry_attempts` 和 `retry_backoff_seconds_base` 为 `list_tools()` 与 `call_tool()` 提供自动重试。 -- `tool_filter` 允许仅暴露工具的子集(见[工具过滤](#tool-filtering))。 +- `max_retry_attempts` 和 `retry_backoff_seconds_base` 为 `list_tools()` 和 `call_tool()` 添加自动重试。 +- `tool_filter` 允许仅暴露工具的子集(参见[工具过滤](#tool-filtering))。 -## 3. HTTP with SSE MCP 服务 +## 3. HTTP + SSE MCP 服务器 -如果 MCP 服务实现了基于 SSE 的 HTTP 传输,实例化 [`MCPServerSse`][agents.mcp.server.MCPServerSse]。除传输方式外,其 API 与可流式 HTTP 服务一致。 +如果 MCP 服务器实现了带 SSE 的 HTTP 传输,请实例化 +[`MCPServerSse`][agents.mcp.server.MCPServerSse]。除了传输层不同,其 API 与可流式 HTTP 服务器完全相同。 ```python @@ -199,9 +199,9 @@ async with MCPServerSse( print(result.final_output) ``` -## 4. stdio MCP 服务 +## 4. stdio MCP 服务器 -对于以本地子进程形式运行的 MCP 服务,使用 [`MCPServerStdio`][agents.mcp.server.MCPServerStdio]。SDK 会启动进程、保持管道打开,并在上下文管理器退出时自动关闭。该选项适用于快速原型或仅提供命令行入口的服务。 +对于以本地子进程方式运行的 MCP 服务器,请使用 [`MCPServerStdio`][agents.mcp.server.MCPServerStdio]。SDK 会启动进程、保持管道打开,并在上下文管理器退出时自动关闭。这一选项有助于快速原型验证,或当服务器仅以命令行入口形式暴露时使用。 ```python from pathlib import Path @@ -229,7 +229,7 @@ async with MCPServerStdio( ## 工具过滤 -每个 MCP 服务均支持工具过滤,你可以仅暴露智能体所需的功能。过滤可在构造时设置,也可在每次运行时动态决定。 +每个 MCP 服务器都支持工具过滤,以便你仅暴露智能体所需的功能。过滤可以在构造时进行,也可以在每次运行时动态设置。 ### 静态工具过滤 @@ -251,11 +251,11 @@ filesystem_server = MCPServerStdio( ) ``` -当同时提供 `allowed_tool_names` 和 `blocked_tool_names` 时,SDK 会先应用允许列表,再从剩余集合中移除被阻止的工具。 +当同时提供 `allowed_tool_names` 和 `blocked_tool_names` 时,SDK 会先应用允许列表,然后从剩余集合中移除任何被阻止的工具。 ### 动态工具过滤 -对于更复杂的逻辑,传入一个可调用对象,它会接收一个 [`ToolFilterContext`][agents.mcp.ToolFilterContext]。该可调用对象可为同步或异步,返回 `True` 表示应暴露该工具。 +对于更复杂的逻辑,传入一个可调用对象,该对象接收 [`ToolFilterContext`][agents.mcp.ToolFilterContext]。该可调用对象可以是同步或异步的,并在工具应被暴露时返回 `True`。 ```python from pathlib import Path @@ -283,10 +283,10 @@ async with MCPServerStdio( ## 提示词 -MCP 服务还可提供动态生成智能体 instructions 的提示词。支持提示词的服务会暴露两个方法: +MCP 服务器还可以提供提示词,以动态生成智能体指令。支持提示词的服务器会暴露两个方法: -- `list_prompts()` 枚举可用的提示模板。 -- `get_prompt(name, arguments)` 获取具体提示词,可选地带参数。 +- `list_prompts()` 枚举可用的提示词模板。 +- `get_prompt(name, arguments)` 获取具体提示词,可选带参数。 ```python from agents import Agent @@ -306,13 +306,13 @@ agent = Agent( ## 缓存 -每次智能体运行都会在每个 MCP 服务上调用 `list_tools()`。远程服务可能带来明显延迟,因此所有 MCP 服务类都提供 `cache_tools_list` 选项。仅当你确信工具定义不经常变动时才将其设为 `True`。如需后续强制刷新,调用服务实例的 `invalidate_tools_cache()`。 +每次智能体运行都会对每个 MCP 服务器调用 `list_tools()`。远程服务器可能引入明显的延迟,因此所有 MCP 服务器类都暴露了 `cache_tools_list` 选项。仅当你确信工具定义不经常变化时,才将其设为 `True`。如需之后强制刷新工具列表,请在服务器实例上调用 `invalidate_tools_cache()`。 ## 追踪 [Tracing](./tracing.md) 会自动捕获 MCP 活动,包括: -1. 对 MCP 服务的工具列表请求。 +1. 对 MCP 服务器的工具列表调用。 2. 工具调用中的 MCP 相关信息。 ![MCP Tracing Screenshot](../assets/images/mcp-tracing.jpg) @@ -320,5 +320,5 @@ agent = Agent( ## 延伸阅读 - [Model Context Protocol](https://modelcontextprotocol.io/) – 规范与设计指南。 -- [examples/mcp](https://github.com/openai/openai-agents-python/tree/main/examples/mcp) – 可运行的 stdio、SSE 与可流式 HTTP 示例。 -- [examples/hosted_mcp](https://github.com/openai/openai-agents-python/tree/main/examples/hosted_mcp) – 包含审批与连接器的完整托管 MCP 演示。 \ No newline at end of file +- [examples/mcp](https://github.com/openai/openai-agents-python/tree/main/examples/mcp) – 可运行的 stdio、SSE 与可流式 HTTP 样例。 +- [examples/hosted_mcp](https://github.com/openai/openai-agents-python/tree/main/examples/hosted_mcp) – 完整的托管 MCP 演示,包括审批和连接器。 \ No newline at end of file diff --git a/docs/zh/models/index.md b/docs/zh/models/index.md index 68868ef90..26288ec41 100644 --- a/docs/zh/models/index.md +++ b/docs/zh/models/index.md @@ -4,20 +4,20 @@ search: --- # 模型 -Agents SDK 提供两种对 OpenAI 模型的开箱即用支持: +Agents SDK 开箱即用地支持两类 OpenAI 模型: -- **推荐**:[`OpenAIResponsesModel`][agents.models.openai_responses.OpenAIResponsesModel],使用全新的 [Responses API](https://platform.openai.com/docs/api-reference/responses) 调用 OpenAI API。 -- [`OpenAIChatCompletionsModel`][agents.models.openai_chatcompletions.OpenAIChatCompletionsModel],使用 [Chat Completions API](https://platform.openai.com/docs/api-reference/chat) 调用 OpenAI API。 +- **推荐**:[`OpenAIResponsesModel`][agents.models.openai_responses.OpenAIResponsesModel],通过新的 [Responses API](https://platform.openai.com/docs/api-reference/responses) 调用 OpenAI API。 +- [`OpenAIChatCompletionsModel`][agents.models.openai_chatcompletions.OpenAIChatCompletionsModel],通过 [Chat Completions API](https://platform.openai.com/docs/api-reference/chat) 调用 OpenAI API。 ## OpenAI 模型 -当你在初始化 `Agent` 时未指定模型,将使用默认模型。目前默认是 [`gpt-4.1`](https://platform.openai.com/docs/models/gpt-4.1),在智能体工作流的可预测性与低延迟之间具有良好平衡。 +当你在初始化 `Agent` 时未指定模型,将使用默认模型。目前默认是 [`gpt-4.1`](https://platform.openai.com/docs/models/gpt-4.1),在智能体工作流的可预测性与低延迟之间有良好平衡。 如果你想切换到其他模型,如 [`gpt-5`](https://platform.openai.com/docs/models/gpt-5),请按照下一节的步骤进行。 ### 默认 OpenAI 模型 -如果你希望对所有未设置自定义模型的智能体一致地使用某个特定模型,请在运行你的智能体之前设置 `OPENAI_DEFAULT_MODEL` 环境变量。 +如果你想为所有未设置自定义模型的智能体一致地使用某个特定模型,请在运行智能体之前设置环境变量 `OPENAI_DEFAULT_MODEL`。 ```bash export OPENAI_DEFAULT_MODEL=gpt-5 @@ -26,9 +26,9 @@ python3 my_awesome_agent.py #### GPT-5 模型 -当你以这种方式使用任一 GPT-5 的推理模型([`gpt-5`](https://platform.openai.com/docs/models/gpt-5)、[`gpt-5-mini`](https://platform.openai.com/docs/models/gpt-5-mini) 或 [`gpt-5-nano`](https://platform.openai.com/docs/models/gpt-5-nano))时,SDK 会默认应用合理的 `ModelSettings`。具体来说,它会将 `reasoning.effort` 和 `verbosity` 都设置为 `"low"`。如果你想自行构建这些设置,可调用 `agents.models.get_default_model_settings("gpt-5")`。 +当你以这种方式使用任一 GPT-5 推理模型([`gpt-5`](https://platform.openai.com/docs/models/gpt-5)、[`gpt-5-mini`](https://platform.openai.com/docs/models/gpt-5-mini) 或 [`gpt-5-nano`](https://platform.openai.com/docs/models/gpt-5-nano))时,SDK 会默认应用合理的 `ModelSettings`。具体来说,它会将 `reasoning.effort` 和 `verbosity` 都设置为 `"low"`。如果你想自行构建这些设置,调用 `agents.models.get_default_model_settings("gpt-5")`。 -为获得更低的延迟或满足特定需求,你可以选择不同的模型和设置。若要为默认模型调整推理强度,请传入你自己的 `ModelSettings`: +为了更低的延迟或满足特定需求,你可以选择不同的模型和设置。要为默认模型调整推理强度,传入你自己的 `ModelSettings`: ```python from openai.types.shared import Reasoning @@ -44,11 +44,11 @@ my_agent = Agent( ) ``` -特别是为了降低延迟,将 [`gpt-5-mini`](https://platform.openai.com/docs/models/gpt-5-mini) 或 [`gpt-5-nano`](https://platform.openai.com/docs/models/gpt-5-nano) 与 `reasoning.effort="minimal"` 搭配使用,通常会比默认设置更快地返回结果。不过,Responses API 中的一些内置工具(如 文件检索 与 图像生成)不支持 `"minimal"` 推理强度,这也是本 Agents SDK 默认使用 `"low"` 的原因。 +特别是为了更低延迟,使用 [`gpt-5-mini`](https://platform.openai.com/docs/models/gpt-5-mini) 或 [`gpt-5-nano`](https://platform.openai.com/docs/models/gpt-5-nano) 并设置 `reasoning.effort="minimal"`,通常会比默认设置更快返回响应。不过,Responses API 中的一些内置工具(如 文件检索 和 图像生成)不支持 `"minimal"` 推理强度,这也是本 Agents SDK 默认为 `"low"` 的原因。 #### 非 GPT-5 模型 -如果你在未提供自定义 `model_settings` 的情况下传入非 GPT-5 模型名,SDK 会回退到与任意模型兼容的通用 `ModelSettings`。 +如果你传入的是非 GPT-5 的模型名称且未提供自定义 `model_settings`,SDK 会回退到适用于任意模型的通用 `ModelSettings`。 ## 非 OpenAI 模型 @@ -67,29 +67,29 @@ gemini_agent = Agent(model="litellm/gemini/gemini-2.5-flash-preview-04-17", ...) ### 使用非 OpenAI 模型的其他方式 -你还可以通过另外 3 种方式集成其他 LLM 提供商(示例见[此处](https://github.com/openai/openai-agents-python/tree/main/examples/model_providers/)): +你还可以通过另外 3 种方式集成其他 LLM 提供商(code examples [在此](https://github.com/openai/openai-agents-python/tree/main/examples/model_providers/)): -1. [`set_default_openai_client`][agents.set_default_openai_client] 适用于你希望全局使用一个 `AsyncOpenAI` 实例作为 LLM 客户端的情况。适合 LLM 提供商有与 OpenAI 兼容的 API 端点、并可设置 `base_url` 和 `api_key` 的情形。可参考 [examples/model_providers/custom_example_global.py](https://github.com/openai/openai-agents-python/tree/main/examples/model_providers/custom_example_global.py) 中可配置示例。 -2. [`ModelProvider`][agents.models.interface.ModelProvider] 作用于 `Runner.run` 级别。它允许你在一次运行中声明“为该次运行的所有智能体使用自定义模型提供商”。可参考 [examples/model_providers/custom_example_provider.py](https://github.com/openai/openai-agents-python/tree/main/examples/model_providers/custom_example_provider.py) 中可配置示例。 -3. [`Agent.model`][agents.agent.Agent.model] 允许你在某个特定的 Agent 实例上指定模型。这样你可以为不同智能体混合搭配不同的提供商。可参考 [examples/model_providers/custom_example_agent.py](https://github.com/openai/openai-agents-python/tree/main/examples/model_providers/custom_example_agent.py) 中可配置示例。使用大多数可用模型的简便方式是通过 [LiteLLM 集成](./litellm.md)。 +1. [`set_default_openai_client`][agents.set_default_openai_client] 适用于你想全局使用一个 `AsyncOpenAI` 实例作为 LLM 客户端的情况。用于 LLM 提供商具有 OpenAI 兼容 API 端点、且你可以设置 `base_url` 和 `api_key` 的场景。可参见可配置示例:[examples/model_providers/custom_example_global.py](https://github.com/openai/openai-agents-python/tree/main/examples/model_providers/custom_example_global.py)。 +2. [`ModelProvider`][agents.models.interface.ModelProvider] 作用于 `Runner.run` 层面。它允许你声明“在本次运行中为所有智能体使用自定义模型提供商”。可参见可配置示例:[examples/model_providers/custom_example_provider.py](https://github.com/openai/openai-agents-python/tree/main/examples/model_providers/custom_example_provider.py)。 +3. [`Agent.model`][agents.agent.Agent.model] 允许你在特定的 Agent 实例上指定模型。这样你可以为不同智能体混合搭配不同提供商。可参见可配置示例:[examples/model_providers/custom_example_agent.py](https://github.com/openai/openai-agents-python/tree/main/examples/model_providers/custom_example_agent.py)。使用大多数可用模型的简便方式是通过 [LiteLLM 集成](./litellm.md)。 -在你没有来自 `platform.openai.com` 的 API key 的情况下,建议通过 `set_tracing_disabled()` 禁用 追踪,或设置[不同的追踪进程](../tracing.md)。 +在你没有来自 `platform.openai.com` 的 API key 的情况下,我们建议通过 `set_tracing_disabled()` 禁用 追踪,或设置一个[不同的追踪进程](../tracing.md)。 !!! note - 在这些示例中,我们使用 Chat Completions API/模型,因为大多数 LLM 提供商尚不支持 Responses API。如果你的 LLM 提供商支持,建议使用 Responses。 + 在这些示例中,我们使用 Chat Completions API/模型,因为多数 LLM 提供商尚不支持 Responses API。如果你的 LLM 提供商支持,建议使用 Responses。 -## 模型混合与搭配 +## 模型混搭 -在单个工作流中,你可能希望为每个智能体使用不同的模型。例如,你可以为初步分流使用更小更快的模型,为复杂任务使用更大更强的模型。配置 [`Agent`][agents.Agent] 时,你可以通过以下方式选择特定模型: +在单一工作流中,你可能希望为每个智能体使用不同的模型。例如,你可以为分诊使用更小更快的模型,为复杂任务使用更大更强的模型。在配置 [`Agent`][agents.Agent] 时,你可以通过以下方式选择特定模型: 1. 传入模型名称。 -2. 传入任意模型名 + 一个可以将该名称映射到 Model 实例的 [`ModelProvider`][agents.models.interface.ModelProvider]。 -3. 直接提供一个 [`Model`][agents.models.interface.Model] 的实现。 +2. 传入任一模型名称 + 一个能够将该名称映射到 Model 实例的 [`ModelProvider`][agents.models.interface.ModelProvider]。 +3. 直接提供一个 [`Model`][agents.models.interface.Model] 实现。 !!!note - 尽管我们的 SDK 同时支持 [`OpenAIResponsesModel`][agents.models.openai_responses.OpenAIResponsesModel] 和 [`OpenAIChatCompletionsModel`][agents.models.openai_chatcompletions.OpenAIChatCompletionsModel] 两种形态,但我们建议在每个工作流中使用单一模型形态,因为两者支持的功能和工具集合不同。如果你的工作流需要混合使用不同的模型形态,请确保你使用的所有功能在两者上都可用。 + 虽然我们的 SDK 同时支持 [`OpenAIResponsesModel`][agents.models.openai_responses.OpenAIResponsesModel] 和 [`OpenAIChatCompletionsModel`][agents.models.openai_chatcompletions.OpenAIChatCompletionsModel] 两种形态,但我们建议每个工作流使用单一模型形态,因为这两种形态支持的特性和工具集不同。如果你的工作流需要混用不同形态,请确保你使用的所有特性在两种形态上都可用。 ```python from agents import Agent, Runner, AsyncOpenAI, OpenAIChatCompletionsModel @@ -122,10 +122,10 @@ async def main(): print(result.final_output) ``` -1. 直接设置一个 OpenAI 模型的名称。 -2. 提供一个 [`Model`][agents.models.interface.Model] 的实现。 +1. 直接设置 OpenAI 模型的名称。 +2. 提供一个 [`Model`][agents.models.interface.Model] 实现。 -当你希望进一步配置智能体所用模型时,可以传入 [`ModelSettings`][agents.models.interface.ModelSettings],用于提供诸如 temperature 等可选的模型配置参数。 +当你希望进一步配置智能体所用的模型时,可以传入 [`ModelSettings`][agents.models.interface.ModelSettings],用于提供诸如 temperature 等可选模型配置 参数。 ```python from agents import Agent, ModelSettings @@ -138,7 +138,7 @@ english_agent = Agent( ) ``` -此外,当你使用 OpenAI 的 Responses API 时,[还有一些其他可选参数](https://platform.openai.com/docs/api-reference/responses/create)(例如 `user`、`service_tier` 等)。如果它们不在顶层可用,你可以使用 `extra_args` 传入。 +此外,当你使用 OpenAI 的 Responses API 时,[还有其他一些可选 参数](https://platform.openai.com/docs/api-reference/responses/create)(例如 `user`、`service_tier` 等)。如果它们不在顶层可用,你可以使用 `extra_args` 传入。 ```python from agents import Agent, ModelSettings @@ -158,22 +158,22 @@ english_agent = Agent( ### 追踪客户端错误 401 -如果你遇到与 追踪 相关的错误,这是因为追踪数据会上传到 OpenAI 服务,而你没有 OpenAI API key。你可以通过以下三种方式解决: +如果你遇到与追踪相关的错误,这是因为追踪会上传到 OpenAI 服务,而你没有 OpenAI API key。你有三种解决方案: 1. 完全禁用追踪:[`set_tracing_disabled(True)`][agents.set_tracing_disabled]。 -2. 为追踪设置 OpenAI key:[`set_tracing_export_api_key(...)`][agents.set_tracing_export_api_key]。此 API key 仅用于上传追踪数据,且必须来自 [platform.openai.com](https://platform.openai.com/)。 +2. 为追踪设置一个 OpenAI key:[`set_tracing_export_api_key(...)`][agents.set_tracing_export_api_key]。此 API key 仅用于上传追踪,且必须来自 [platform.openai.com](https://platform.openai.com/)。 3. 使用非 OpenAI 的追踪进程。参见[追踪文档](../tracing.md#custom-tracing-processors)。 ### Responses API 支持 -SDK 默认使用 Responses API,但大多数其他 LLM 提供商尚不支持。这可能导致出现 404 或类似问题。解决方法有两种: +SDK 默认使用 Responses API,但大多数其他 LLM 提供商尚不支持。因此你可能会看到 404 或类似问题。解决方法有两种: -1. 调用 [`set_default_openai_api("chat_completions")`][agents.set_default_openai_api]。当你通过环境变量设置 `OPENAI_API_KEY` 和 `OPENAI_BASE_URL` 时可用。 -2. 使用 [`OpenAIChatCompletionsModel`][agents.models.openai_chatcompletions.OpenAIChatCompletionsModel]。示例见[此处](https://github.com/openai/openai-agents-python/tree/main/examples/model_providers/)。 +1. 调用 [`set_default_openai_api("chat_completions")`][agents.set_default_openai_api]。如果你通过环境变量设置了 `OPENAI_API_KEY` 和 `OPENAI_BASE_URL`,这将有效。 +2. 使用 [`OpenAIChatCompletionsModel`][agents.models.openai_chatcompletions.OpenAIChatCompletionsModel]。code examples 见[此处](https://github.com/openai/openai-agents-python/tree/main/examples/model_providers/)。 -### Structured outputs 支持 +### 结构化输出支持 -某些模型提供商不支持 [structured outputs](https://platform.openai.com/docs/guides/structured-outputs)。这有时会导致类似如下的错误: +一些模型提供商不支持[结构化输出](https://platform.openai.com/docs/guides/structured-outputs)。这有时会导致如下类似错误: ``` @@ -181,12 +181,12 @@ BadRequestError: Error code: 400 - {'error': {'message': "'response_format.type' ``` -这是某些模型提供商的不足——它们支持 JSON 输出,但不允许你为输出指定 `json_schema`。我们正在推进对此进行修复,但建议优先使用支持 JSON schema 输出的提供商,否则你的应用常会因为 JSON 不合法而出错。 +这是部分模型提供商的不足——它们支持 JSON 输出,但不允许你为输出指定要使用的 `json_schema`。我们正在努力修复,但我们建议依赖支持 JSON schema 输出的提供商,否则你的应用经常会因 JSON 格式不正确而出错。 -## 跨提供商混合使用模型 +## 跨提供商混用模型 -你需要注意不同模型提供商之间的功能差异,否则可能会遇到错误。例如,OpenAI 支持 structured outputs、多模态输入以及托管的 文件检索 与 网络检索,但许多其他提供商不支持这些功能。需要注意以下限制: +你需要了解不同模型提供商的功能差异,否则可能会遇到错误。例如,OpenAI 支持 结构化输出、多模态输入,以及托管的 文件检索 和 网络检索,但许多其他提供商并不支持这些特性。注意以下限制: -- 不要将不受支持的 `tools` 发送给不理解它们的提供商 -- 在调用仅支持文本的模型前,过滤掉多模态输入 -- 注意不支持结构化 JSON 输出的提供商偶尔会生成无效的 JSON。 \ No newline at end of file +- 不要向不支持的提供商发送不被理解的 `tools` +- 在调用仅支持文本的模型前,过滤掉多模态输入 +- 注意不支持结构化 JSON 输出的提供商偶尔会生成无效的 JSON。 \ No newline at end of file diff --git a/docs/zh/models/litellm.md b/docs/zh/models/litellm.md index cd1827480..3e6ff09ec 100644 --- a/docs/zh/models/litellm.md +++ b/docs/zh/models/litellm.md @@ -6,13 +6,13 @@ search: !!! note - LiteLLM 集成处于测试阶段。你在使用某些模型提供商(尤其是较小的提供商)时可能会遇到问题。请通过 [Github issues](https://github.com/openai/openai-agents-python/issues) 报告问题,我们会尽快修复。 + LiteLLM 集成处于测试版阶段。你可能会在某些模型提供商(尤其是较小的提供商)上遇到问题。请通过 [GitHub 问题](https://github.com/openai/openai-agents-python/issues)报告,我们会尽快修复。 -[LiteLLM](https://docs.litellm.ai/docs/) 是一个库,可通过统一接口使用 100+ 模型。我们在 Agents SDK 中集成了 LiteLLM,使你可以使用任意 AI 模型。 +[LiteLLM](https://docs.litellm.ai/docs/) 是一个库,允许你通过统一接口使用 100+ 个模型。我们在 Agents SDK 中加入了 LiteLLM 集成,使你可以使用任意 AI 模型。 ## 设置 -你需要确保可用 `litellm`。可以通过安装可选的 `litellm` 依赖组来完成: +你需要确保 `litellm` 可用。可以通过安装可选的 `litellm` 依赖组来完成: ```bash pip install "openai-agents[litellm]" @@ -22,13 +22,13 @@ pip install "openai-agents[litellm]" ## 示例 -这是一个可直接运行的示例。运行后会提示你输入模型名称和 API 密钥。例如,你可以输入: +这是一个可直接运行的示例。运行时会提示你输入模型名称和 API key。比如,你可以输入: -- `openai/gpt-4.1` 作为模型,以及你的 OpenAI API 密钥 -- `anthropic/claude-3-5-sonnet-20240620` 作为模型,以及你的 Anthropic API 密钥 -- 等等 +- 模型为 `openai/gpt-4.1`,并提供你的 OpenAI API key +- 模型为 `anthropic/claude-3-5-sonnet-20240620`,并提供你的 Anthropic API key +- 等等 -LiteLLM 支持的完整模型列表请参见 [litellm providers docs](https://docs.litellm.ai/docs/providers)。 +有关 LiteLLM 支持的完整模型列表,请参见 [litellm providers 文档](https://docs.litellm.ai/docs/providers)。 ```python from __future__ import annotations @@ -78,7 +78,7 @@ if __name__ == "__main__": ## 使用数据追踪 -如果希望 LiteLLM 的响应填充到 Agents SDK 的使用指标中,在创建智能体时传入 `ModelSettings(include_usage=True)`。 +如果你希望 LiteLLM 的响应填充 Agents SDK 的使用度量指标,在创建智能体时传入 `ModelSettings(include_usage=True)`。 ```python from agents import Agent, ModelSettings @@ -91,4 +91,4 @@ agent = Agent( ) ``` -设置 `include_usage=True` 后,LiteLLM 请求会通过 `result.context_wrapper.usage` 报告 token 和请求计数,方式与内置的 OpenAI 模型相同。 \ No newline at end of file +启用 `include_usage=True` 后,LiteLLM 请求会通过 `result.context_wrapper.usage` 报告 token 和请求计数,就像内置的 OpenAI 模型一样。 \ No newline at end of file diff --git a/docs/zh/multi_agent.md b/docs/zh/multi_agent.md index 966a2da47..82668676d 100644 --- a/docs/zh/multi_agent.md +++ b/docs/zh/multi_agent.md @@ -4,38 +4,38 @@ search: --- # 编排多个智能体 -编排指的是应用中智能体的运行流程:哪些智能体运行、以什么顺序运行、以及它们如何决定接下来发生什么。编排智能体主要有两种方式: +编排指的是你在应用中安排智能体的运行流程:哪些智能体运行、以何种顺序运行、以及它们如何决定下一步。编排智能体主要有两种方式: -1. 让 LLM 做决策:利用 LLM 的智能进行规划、推理,并据此决定采取哪些步骤。 -2. 通过代码编排:通过你的代码来确定智能体的流程。 +1. 让 LLM 做决策:利用 LLM 的智能来规划、推理,并据此决定应采取的步骤。 +2. 通过代码编排:用你的代码决定智能体的流程。 -你可以混合使用这些模式。每种方式都有权衡,见下文。 +你可以混合使用这些模式。每种方式都有取舍,详见下文。 ## 通过 LLM 编排 -一个智能体是配备了指令(instructions)、工具(tools)和任务转移(handoffs)的 LLM。这意味着面对一个开放式任务时,LLM 可以自主规划如何完成任务,使用工具执行操作和获取数据,并通过任务转移将任务委派给子智能体。例如,一个研究智能体可以配备如下工具: +一个智能体是配备了 instructions、tools 和 任务转移 的 LLM。这意味着,面对一个开放式任务时,LLM 可以自主规划如何完成任务,使用工具采取行动并获取数据,并通过任务转移将子任务委派给子智能体。比如,一个研究类智能体可以配备如下工具: -- 网络检索以在网上查找信息 -- 文件检索与提取以搜索专有数据和连接 -- 计算机操作以在计算机上执行操作 -- 代码执行以进行数据分析 -- 任务转移到擅长规划、写报告等的专业智能体 +- 网络检索,用于在线查找信息 +- 文件检索与读取,用于检索专有数据与连接 +- 计算机操作,用于在计算机上执行操作 +- 代码执行,用于数据分析 +- 向在规划、报告撰写等方面擅长的专用智能体进行任务转移 -当任务是开放式且你希望依赖 LLM 的智能时,这种模式非常适合。关键做法包括: +当任务是开放式且你希望依赖 LLM 的智能时,这种模式非常适用。关键做法包括: -1. 投入精力于优质提示词。明确可用的工具、如何使用它们,以及它必须遵循的参数范围。 -2. 监控你的应用并迭代改进。找出问题发生的位置,并迭代优化提示词。 -3. 允许智能体自省和改进。例如,将其置于循环中,让其自我批判;或者提供错误信息并让其改进。 -4. 使用在单一任务上表现出色的专业智能体,而不是期望一个通用智能体在所有方面都表现良好。 -5. 投入于[评测(evals)](https://platform.openai.com/docs/guides/evals)。这可以让你训练智能体以改进并更好地完成任务。 +1. 投入打磨高质量的提示词。明确可用的工具、如何使用它们,以及必须遵守的参数范围。 +2. 监控并迭代你的应用。观察问题发生的位置,并迭代你的提示词。 +3. 允许智能体自省与改进。例如,将其置于循环中,让它自我批判;或者提供错误信息并让它改进。 +4. 使用在单一任务上表现卓越的专用智能体,而不是期望一个通用智能体在任何方面都表现出色。 +5. 投入到[评测(evals)](https://platform.openai.com/docs/guides/evals)。这可以帮助你训练智能体不断改进,更好地完成任务。 ## 通过代码编排 -尽管通过 LLM 编排功能强大,但通过代码编排可以在速度、成本和性能方面让任务更具确定性和可预测性。常见模式包括: +尽管通过 LLM 编排很强大,但通过代码编排在速度、成本和性能方面更具确定性与可预测性。常见模式包括: -- 使用 [structured outputs](https://platform.openai.com/docs/guides/structured-outputs) 生成可由你的代码检查的格式良好的数据。例如,你可以让一个智能体将任务分类到几个目录中,然后根据该目录选择下一个智能体。 -- 将多个智能体串联,把一个智能体的输出转换为下一个的输入。你可以将写博客文章这样的任务分解为一系列步骤——进行研究、写大纲、写正文、批判性审阅,然后改进。 -- 让执行任务的智能体与负责评估并提供反馈的智能体在一个 `while` 循环中运行,直到评估者判定输出满足某些标准为止。 -- 并行运行多个智能体,例如通过 Python 基本组件如 `asyncio.gather`。当你有多个彼此不依赖的任务时,这有助于提升速度。 +- 使用[structured outputs](https://platform.openai.com/docs/guides/structured-outputs)生成可由你的代码检查的格式良好的数据。比如,你可以让智能体将任务分类为几个目录,然后根据该目录选择下一个智能体。 +- 通过将一个智能体的输出转换为下一个智能体的输入来串联多个智能体。你可以将写博客这样的任务分解为一系列步骤——做研究、写大纲、写正文、批判性审阅,然后改进。 +- 将执行任务的智能体与负责评估并提供反馈的智能体一起在 `while` 循环中运行,直到评估者认为输出满足某些标准。 +- 并行运行多个智能体,例如通过 Python 基本组件如 `asyncio.gather`。当你有多个彼此独立的任务时,这有助于提升速度。 -我们在 [`examples/agent_patterns`](https://github.com/openai/openai-agents-python/tree/main/examples/agent_patterns) 中提供了许多代码示例。 \ No newline at end of file +我们在[`examples/agent_patterns`](https://github.com/openai/openai-agents-python/tree/main/examples/agent_patterns)中提供了若干代码示例。 \ No newline at end of file diff --git a/docs/zh/quickstart.md b/docs/zh/quickstart.md index 6439bdab4..94ac3183e 100644 --- a/docs/zh/quickstart.md +++ b/docs/zh/quickstart.md @@ -2,11 +2,11 @@ search: exclude: true --- -# 快速入门 +# 快速开始 -## 项目与虚拟环境创建 +## 创建项目与虚拟环境 -你只需执行一次。 +这一步只需执行一次。 ```bash mkdir my_project @@ -14,31 +14,31 @@ cd my_project python -m venv .venv ``` -### 虚拟环境激活 +### 激活虚拟环境 -每次启动新的终端会话都需执行。 +每次启动新的终端会话都需要执行这一步。 ```bash source .venv/bin/activate ``` -### Agents SDK 安装 +### 安装 Agents SDK ```bash pip install openai-agents # or `uv add openai-agents`, etc ``` -### OpenAI API 密钥设置 +### 设置 OpenAI API 密钥 -如果还没有,请按照[这些说明](https://platform.openai.com/docs/quickstart#create-and-export-an-api-key)创建一个 OpenAI API 密钥。 +如果你还没有,请按照[这些说明](https://platform.openai.com/docs/quickstart#create-and-export-an-api-key)创建一个 OpenAI API 密钥。 ```bash export OPENAI_API_KEY=sk-... ``` -## 第一个智能体创建 +## 创建你的第一个智能体 -智能体由 instructions、名称以及可选配置(例如 `model_config`)定义。 +智能体由 instructions、名称和可选配置(如 `model_config`)定义。 ```python from agents import Agent @@ -49,9 +49,9 @@ agent = Agent( ) ``` -## 更多智能体添加 +## 添加更多智能体 -其他智能体可用相同方式定义。`handoff_descriptions` 提供用于确定任务转移路由的额外上下文。 +可以用相同方式定义其他智能体。`handoff_descriptions` 提供附加上下文,用于确定任务转移路由。 ```python from agents import Agent @@ -69,9 +69,9 @@ math_tutor_agent = Agent( ) ``` -## 任务转移定义 +## 定义任务转移 -在每个智能体上,你可以定义一组可用的外发任务转移选项,供其选择以决定如何推进任务。 +在每个智能体上,你可以定义一个外发任务转移选项清单,智能体可据此选择以推进其任务。 ```python triage_agent = Agent( @@ -81,9 +81,9 @@ triage_agent = Agent( ) ``` -## 智能体编排运行 +## 运行智能体编排 -我们来检查工作流是否运行,以及分诊智能体是否能在两个专家型智能体之间正确路由。 +让我们检查工作流是否运行,以及分诊智能体是否在两个专家智能体之间正确路由。 ```python from agents import Runner @@ -93,9 +93,9 @@ async def main(): print(result.final_output) ``` -## 安全防护措施添加 +## 添加安全防护措施 -你可以定义自定义安全防护措施,在输入或输出阶段运行。 +你可以定义自定义安全防护措施,对输入或输出生效。 ```python from agents import GuardrailFunctionOutput, Agent, Runner @@ -121,9 +121,9 @@ async def homework_guardrail(ctx, agent, input_data): ) ``` -## 综合运行 +## 汇总整合 -让我们将其整合起来,使用任务转移和输入安全防护措施运行整个工作流。 +让我们把以上整合起来,运行完整工作流,使用任务转移和输入安全防护措施。 ```python from agents import Agent, InputGuardrail, GuardrailFunctionOutput, Runner @@ -190,14 +190,14 @@ if __name__ == "__main__": asyncio.run(main()) ``` -## 追踪查看 +## 查看追踪 -若要查看智能体运行期间发生的情况,请前往 [OpenAI 控制台中的追踪查看器](https://platform.openai.com/traces) 查看运行追踪。 +若要回顾智能体运行期间发生的情况,请前往 [OpenAI Dashboard 中的 Trace viewer](https://platform.openai.com/traces) 查看智能体运行的追踪。 ## 后续步骤 了解如何构建更复杂的智能体流程: -- 了解如何配置[Agents](agents.md)。 +- 了解如何配置[智能体](agents.md)。 - 了解[运行智能体](running_agents.md)。 -- 了解[tools](tools.md)、[安全防护措施](guardrails.md)和[模型](models/index.md)。 \ No newline at end of file +- 了解[工具](tools.md)、[安全防护措施](guardrails.md)和[模型](models/index.md)。 \ No newline at end of file diff --git a/docs/zh/realtime/guide.md b/docs/zh/realtime/guide.md index cc42fbeae..815059922 100644 --- a/docs/zh/realtime/guide.md +++ b/docs/zh/realtime/guide.md @@ -4,65 +4,65 @@ search: --- # 指南 -本指南深入介绍如何使用 OpenAI Agents SDK 的实时能力来构建支持语音的 AI 智能体。 +本指南深入介绍如何使用 OpenAI Agents SDK 的实时能力来构建语音驱动的 AI 智能体。 -!!! warning "测试版功能" -Realtime 智能体处于测试阶段。随着实现的改进,可能会有不兼容的更改。 +!!! warning "Beta feature" +实时智能体处于测试阶段。随着实现的改进,可能会出现非兼容性变更。 -## 概览 +## 概述 -Realtime 智能体支持会话式流程,能够实时处理音频与文本输入,并以实时音频进行回应。它们与 OpenAI 的 Realtime API 保持持久连接,实现低延迟的自然语音对话,并可优雅地处理打断。 +实时智能体支持会话式流程,能够实时处理音频与文本输入,并以实时音频进行响应。它们与 OpenAI 的 Realtime API 保持持久连接,从而实现低延迟的自然语音对话,并优雅地处理打断。 ## 架构 ### 核心组件 -该实时系统包含以下关键组件: +实时系统由以下关键组件组成: -- **RealtimeAgent**: 一个智能体,由 instructions、tools 和 任务转移 配置组成。 -- **RealtimeRunner**: 管理配置。你可以调用 `runner.run()` 获取会话。 -- **RealtimeSession**: 单个交互会话。通常在每次用户开始对话时创建一个,并在对话结束前保持存活。 -- **RealtimeModel**: 底层模型接口(通常是 OpenAI 的 WebSocket 实现) +- **RealtimeAgent**: 一个智能体,使用 instructions、tools 和 任务转移 进行配置。 +- **RealtimeRunner**: 管理配置。您可以调用 `runner.run()` 获取一个会话。 +- **RealtimeSession**: 单次交互会话。通常在每次用户开始对话时创建一个,并保持其存活直至对话结束。 +- **RealtimeModel**: 底层模型接口(通常是 OpenAI 的 WebSocket 实现) ### 会话流程 -一个典型的实时会话遵循以下流程: +一个典型的实时会话流程如下: -1. **创建 RealtimeAgent**,并配置 instructions、tools 和 任务转移。 -2. **设置 RealtimeRunner**,指定智能体和配置项。 -3. **启动会话**,使用 `await runner.run()`,该函数返回一个 RealtimeSession。 -4. **发送音频或文本消息** 到会话,使用 `send_audio()` 或 `send_message()`。 -5. **监听事件**,通过迭代会话对象来接收事件——事件包括音频输出、转录文本、工具调用、任务转移和错误。 -6. **处理打断**,当用户打断智能体说话时,会自动停止当前音频生成。 +1. 使用 instructions、tools 和 任务转移 创建您的 **RealtimeAgent**。 +2. 使用智能体和配置选项 **设置 RealtimeRunner**。 +3. 使用 `await runner.run()` **启动会话**,它会返回一个 RealtimeSession。 +4. 使用 `send_audio()` 或 `send_message()` 向会话 **发送音频或文本消息**。 +5. **监听事件**,通过遍历会话对象接收事件——事件包括音频输出、转写、工具调用、任务转移以及错误 +6. 当用户打断智能体说话时 **处理打断**,这会自动停止当前音频生成 -会话负责维护对话历史并管理与实时模型的持久连接。 +会话会维护对话历史,并管理与实时模型的持久连接。 ## 智能体配置 -RealtimeAgent 的工作方式与常规 Agent 类似,但有一些关键差异。完整 API 详情参见 [`RealtimeAgent`][agents.realtime.agent.RealtimeAgent] API 参考。 +RealtimeAgent 的工作方式与常规 Agent 类类似,但存在一些关键差异。完整 API 详情参见 [`RealtimeAgent`][agents.realtime.agent.RealtimeAgent] API 参考。 -与常规智能体的主要差异: +与常规模型智能体的主要差异: -- 模型选择在会话级别配置,而非智能体级别。 -- 不支持 structured output(不支持 `outputType`)。 -- 语音可按智能体配置,但在第一个智能体开始说话后不可更改。 -- 其他功能如 tools、任务转移 和 instructions 的工作方式相同。 +- 模型选择在会话级别配置,而非智能体级别。 +- 不支持 structured output(不支持 `outputType`)。 +- 可为每个智能体配置语音,但在第一个智能体开口说话后不可更改。 +- 其他功能如 tools、任务转移 和 instructions 的工作方式相同。 ## 会话配置 ### 模型设置 -会话配置允许你控制底层实时模型行为。你可以配置模型名称(如 `gpt-realtime`)、语音选择(alloy、echo、fable、onyx、nova、shimmer),以及支持的模态(文本和/或音频)。可为输入与输出设置音频格式,默认是 PCM16。 +会话配置允许您控制底层实时模型的行为。您可以配置模型名称(如 `gpt-realtime`)、语音选择(alloy、echo、fable、onyx、nova、shimmer)以及支持的模态(文本和/或音频)。输入与输出的音频格式均可设置,默认是 PCM16。 ### 音频配置 -音频设置控制会话如何处理语音输入与输出。你可以使用如 Whisper 的模型配置输入语音转录,设置语言偏好,并提供转录提示以提升领域术语的准确性。轮次检测设置控制智能体何时开始与停止回应,选项包括语音活动检测阈值、静音时长以及检测语音前后的填充。 +音频设置控制会话如何处理语音输入与输出。您可以使用如 Whisper 等模型进行输入音频转写,设置语言偏好,并提供转写提示以提升领域术语的准确率。轮次检测(turn detection)设置用于控制智能体何时开始与停止响应,可配置语音活动检测阈值、静音时长以及检测到语音的前后填充。 ## 工具与函数 ### 添加工具 -与常规智能体类似,Realtime 智能体支持在会话中执行的 工具调用: +与常规智能体相同,实时智能体支持在对话中执行的 工具调用: ```python from agents import function_tool @@ -90,7 +90,7 @@ agent = RealtimeAgent( ### 创建任务转移 -任务转移允许在不同的专业化智能体间迁移对话。 +任务转移允许在不同的专业化智能体之间转移对话。 ```python from agents.realtime import realtime_handoff @@ -119,22 +119,22 @@ main_agent = RealtimeAgent( ## 事件处理 -会话会流式传递事件,你可以通过迭代会话对象进行监听。事件包括音频输出分片、转录结果、工具执行的开始与结束、智能体任务转移以及错误。需要重点处理的事件包括: +会话会流式发送事件,您可以通过遍历会话对象进行监听。事件包括音频输出分片、转写结果、工具执行的开始与结束、智能体任务转移以及错误。需要重点处理的事件包括: -- **audio**: 来自智能体响应的原始音频数据 -- **audio_end**: 智能体完成发言 -- **audio_interrupted**: 用户打断了智能体 -- **tool_start/tool_end**: 工具执行生命周期 -- **handoff**: 发生了智能体任务转移 -- **error**: 处理过程中发生错误 +- **audio**: 来自智能体响应的原始音频数据 +- **audio_end**: 智能体完成发声 +- **audio_interrupted**: 用户打断了智能体 +- **tool_start/tool_end**: 工具执行生命周期 +- **handoff**: 发生了智能体任务转移 +- **error**: 处理过程中发生错误 -完整事件详情参见 [`RealtimeSessionEvent`][agents.realtime.events.RealtimeSessionEvent]。 +完整的事件详情参见 [`RealtimeSessionEvent`][agents.realtime.events.RealtimeSessionEvent]。 ## 安全防护措施 -Realtime 智能体仅支持输出层面的安全防护措施。为避免实时生成过程中的性能问题,这些防护是防抖执行的(不会对每个词触发),会定期运行。默认防抖长度为 100 个字符,但可配置。 +实时智能体仅支持输出安全防护措施。这些安全防护措施会进行防抖处理,并周期性运行(不是每个词都运行),以避免实时生成中的性能问题。默认防抖长度为 100 个字符,但可配置。 -安全防护措施可以直接附加到 `RealtimeAgent`,或通过会话的 `run_config` 提供。两个来源的防护会共同生效。 +安全防护措施既可直接附加到 `RealtimeAgent` 上,也可通过会话的 `run_config` 提供。来自两处的安全防护措施会共同运行。 ```python from agents.guardrail import GuardrailFunctionOutput, OutputGuardrail @@ -152,25 +152,25 @@ agent = RealtimeAgent( ) ``` -当安全防护措施被触发时,会生成一个 `guardrail_tripped` 事件,并可中断智能体当前的回应。防抖行为有助于在安全性与实时性能需求之间取得平衡。与文本智能体不同,Realtime 智能体在防护触发时不会抛出 Exception。 +当安全防护措施被触发时,会生成 `guardrail_tripped` 事件,并可中断智能体当前的响应。防抖行为有助于在安全性与实时性能需求之间取得平衡。与文本智能体不同,实时智能体在触发安全防护措施时**不会**抛出 Exception。 ## 音频处理 -通过 [`session.send_audio(audio_bytes)`][agents.realtime.session.RealtimeSession.send_audio] 发送音频到会话,或通过 [`session.send_message()`][agents.realtime.session.RealtimeSession.send_message] 发送文本。 +使用 [`session.send_audio(audio_bytes)`][agents.realtime.session.RealtimeSession.send_audio] 发送音频到会话,或使用 [`session.send_message()`][agents.realtime.session.RealtimeSession.send_message] 发送文本。 -对于音频输出,监听 `audio` 事件,并使用你偏好的音频库播放音频数据。请确保监听 `audio_interrupted` 事件,以便在用户打断智能体时立即停止播放并清除任何已排队的音频。 +对于音频输出,监听 `audio` 事件并通过您偏好的音频库播放音频数据。确保监听 `audio_interrupted` 事件,以便在用户打断智能体时立即停止播放并清空任何已排队的音频。 ## 直接模型访问 -你可以访问底层模型以添加自定义监听器或执行高级操作: +您可以访问底层模型以添加自定义监听器或执行高级操作: ```python # Add a custom listener to the model session.model.add_listener(my_custom_listener) ``` -这使你可以直接访问 [`RealtimeModel`][agents.realtime.model.RealtimeModel] 接口,用于需要对连接进行更低层控制的高级用例。 +这会为您提供对 [`RealtimeModel`][agents.realtime.model.RealtimeModel] 接口的直接访问,适用于需要更低层级连接控制的高级用例。 ## 代码示例 -欲获取完整可运行的示例,请查看 [examples/realtime 目录](https://github.com/openai/openai-agents-python/tree/main/examples/realtime),其中包含带 UI 与不带 UI 的演示。 \ No newline at end of file +欲获取完整可运行的代码示例,请查看 [examples/realtime 目录](https://github.com/openai/openai-agents-python/tree/main/examples/realtime),其中包含带有和不带有 UI 组件的演示。 \ No newline at end of file diff --git a/docs/zh/realtime/quickstart.md b/docs/zh/realtime/quickstart.md index 33eb2d730..44711db5b 100644 --- a/docs/zh/realtime/quickstart.md +++ b/docs/zh/realtime/quickstart.md @@ -4,10 +4,10 @@ search: --- # 快速开始 -实时智能体通过 OpenAI 的 Realtime API 实现与 AI 智能体的语音对话。本指南将引导你创建第一个实时语音智能体。 +实时智能体通过 OpenAI 的 Realtime API 为你的 AI 智能体启用语音对话。本指南将带你创建第一个实时语音智能体。 -!!! warning "Beta 功能" -实时智能体当前处于 beta 阶段。随着实现的改进,可能会有不兼容的变更。 +!!! warning "测试版功能" +实时智能体处于测试阶段。随着我们改进实现,可能会出现不兼容的变更。 ## 先决条件 @@ -17,7 +17,7 @@ search: ## 安装 -如果尚未安装,请先安装 OpenAI Agents SDK: +如果尚未安装,请安装 OpenAI Agents SDK: ```bash pip install openai-agents @@ -111,7 +111,7 @@ def _truncate_str(s: str, max_length: int) -> str: ## 完整示例 -下面是一个可运行的完整示例: +下面是一个完整、可运行的示例: ```python import asyncio @@ -192,15 +192,15 @@ if __name__ == "__main__": ### 模型设置 -- `model_name`: 从可用的实时模型中选择(例如 `gpt-realtime`) +- `model_name`: 从可用的实时模型中选择(例如,`gpt-realtime`) - `voice`: 选择语音(`alloy`、`echo`、`fable`、`onyx`、`nova`、`shimmer`) - `modalities`: 启用文本或音频(`["text"]` 或 `["audio"]`) ### 音频设置 -- `input_audio_format`: 输入音频的格式(`pcm16`、`g711_ulaw`、`g711_alaw`) -- `output_audio_format`: 输出音频的格式 -- `input_audio_transcription`: 转写配置 +- `input_audio_format`: 输入音频格式(`pcm16`、`g711_ulaw`、`g711_alaw`) +- `output_audio_format`: 输出音频格式 +- `input_audio_transcription`: 转录配置 ### 轮次检测 @@ -212,14 +212,14 @@ if __name__ == "__main__": ## 后续步骤 - [进一步了解实时智能体](guide.md) -- 在 [examples/realtime](https://github.com/openai/openai-agents-python/tree/main/examples/realtime) 文件夹中查看可运行的 code examples +- 在[代码示例/realtime](https://github.com/openai/openai-agents-python/tree/main/examples/realtime)文件夹中查看可用示例 - 为你的智能体添加工具 -- 在智能体之间实现任务转移 -- 设置安全防护措施以确保安全 +- 实现智能体之间的任务转移 +- 配置安全防护措施 -## 认证 +## 身份验证 -确保在环境中设置了 OpenAI API 密钥: +确保在你的环境中设置了 OpenAI API 密钥: ```bash export OPENAI_API_KEY="your-api-key-here" diff --git a/docs/zh/release.md b/docs/zh/release.md index 24e424343..efb94ca6b 100644 --- a/docs/zh/release.md +++ b/docs/zh/release.md @@ -4,29 +4,29 @@ search: --- # 发布流程/更新日志 -本项目遵循稍作修改的语义化版本控制,版本格式为 `0.Y.Z`。前导的 `0` 表示该 SDK 仍在快速演进中。版本号的增量规则如下: +本项目采用稍作修改的语义化版本控制,版本号形式为 `0.Y.Z`。前导的 `0` 表示 SDK 仍在快速迭代中。各组件递增规则如下: -## 次版本(`Y`) +## 次要(`Y`)版本 -对于未标记为 beta 的任何公共接口出现**不兼容变更(breaking changes)**时,我们会提升次版本号 `Y`。例如,从 `0.0.x` 升级到 `0.1.x` 可能包含不兼容变更。 +对于未标记为 beta 的任何公共接口出现的**不兼容变更**,我们将增加次要版本号 `Y`。例如,从 `0.0.x` 到 `0.1.x` 可能包含不兼容变更。 -如果你不希望引入不兼容变更,建议在你的项目中锁定到 `0.0.x` 版本。 +如果你不希望引入不兼容变更,建议在项目中固定到 `0.0.x` 版本。 -## 修订版本(`Z`) +## 补丁(`Z`)版本 -对于非破坏性变更,我们会递增 `Z`: +对于不引入不兼容的变更,我们将增加 `Z`: - Bug 修复 - 新功能 -- 私有接口的变更 -- beta 特性的更新 +- 对私有接口的更改 +- 对 beta 功能的更新 ## 不兼容变更日志 ### 0.2.0 -在该版本中,若干原本接收 `Agent` 作为参数的地方,现在改为接收 `AgentBase` 作为参数。例如,MCP 服务中的 `list_tools()` 调用。这只是类型层面的变更,你仍将收到 `Agent` 对象。要更新的话,只需将类型注解中的 `Agent` 替换为 `AgentBase`,以修复类型错误。 +在此版本中,一些过去接受 `Agent` 作为参数的地方,现在改为接受 `AgentBase` 作为参数。例如,MCP 服务中的 `list_tools()` 调用。这只是类型层面的变更,你仍会接收到 `Agent` 对象。要更新,只需将类型错误中的 `Agent` 替换为 `AgentBase` 即可。 ### 0.1.0 -在该版本中,[`MCPServer.list_tools()`][agents.mcp.server.MCPServer] 新增了两个参数:`run_context` 和 `agent`。你需要在任何继承自 `MCPServer` 的类中添加这些参数。 \ No newline at end of file +在此版本中,[`MCPServer.list_tools()`][agents.mcp.server.MCPServer] 新增了两个参数:`run_context` 和 `agent`。对于任何继承 `MCPServer` 的类,你需要添加这些参数。 \ No newline at end of file diff --git a/docs/zh/repl.md b/docs/zh/repl.md index 2be511741..ee7740555 100644 --- a/docs/zh/repl.md +++ b/docs/zh/repl.md @@ -4,7 +4,7 @@ search: --- # REPL 工具 -该 SDK 提供 `run_demo_loop`,可在终端中快速、交互式地测试智能体的行为。 +SDK 提供了 `run_demo_loop`,可在终端中直接对智能体行为进行快速、交互式测试。 ```python import asyncio @@ -18,6 +18,6 @@ if __name__ == "__main__": asyncio.run(main()) ``` -`run_demo_loop` 在循环中提示用户输入,并在多轮之间保留对话历史。默认情况下,它会在模型生成输出时进行流式传输。运行上述示例时,run_demo_loop 会启动一个交互式聊天会话。它会持续请求你的输入,在多轮之间记住完整的对话历史(因此你的智能体知道已经讨论了什么),并在生成过程中将智能体的响应实时流式传输给你。 +`run_demo_loop` 在循环中提示输入用户内容,并在各轮次之间保留对话历史。默认情况下,它会在生成时以流式传输的方式输出模型结果。运行上述示例后,run_demo_loop 会启动一个交互式聊天会话。它会持续询问你的输入、在轮次之间记住整个对话历史(因此你的智能体知道已经讨论过什么),并在生成过程中实时自动将智能体的回复流式传输给你。 要结束此聊天会话,只需输入 `quit` 或 `exit`(然后按回车),或使用 `Ctrl-D` 键盘快捷键。 \ No newline at end of file diff --git a/docs/zh/results.md b/docs/zh/results.md index 4887dc7bf..ff6f88e32 100644 --- a/docs/zh/results.md +++ b/docs/zh/results.md @@ -6,51 +6,51 @@ search: 当你调用 `Runner.run` 方法时,你会得到: -- 如果调用 `run` 或 `run_sync`,则得到 [`RunResult`][agents.result.RunResult] -- 如果调用 `run_streamed`,则得到 [`RunResultStreaming`][agents.result.RunResultStreaming] +- [`RunResult`][agents.result.RunResult](如果你调用 `run` 或 `run_sync`) +- [`RunResultStreaming`][agents.result.RunResultStreaming](如果你调用 `run_streamed`) -两者都继承自 [`RunResultBase`][agents.result.RunResultBase],大多数有用信息都在其中。 +二者都继承自 [`RunResultBase`][agents.result.RunResultBase],大多数有用信息都在这里。 ## 最终输出 -[`final_output`][agents.result.RunResultBase.final_output] 属性包含最后一个运行的智能体的最终输出。可能是: +[`final_output`][agents.result.RunResultBase.final_output] 属性包含最后一个运行的智能体的最终输出。它可能是: -- `str`,如果最后一个智能体没有定义 `output_type` -- 类型为 `last_agent.output_type` 的对象,如果该智能体定义了输出类型。 +- `str`,如果最后一个智能体没有定义 `output_type` +- 类型为 `last_agent.output_type` 的对象,如果该智能体定义了输出类型。 !!! note - `final_output` 的类型为 `Any`。由于存在 任务转移,我们无法进行静态类型标注。如果发生 任务转移,意味着任意智能体都可能成为最后一个智能体,因此我们无法静态地知道可能的输出类型集合。 + `final_output` 的类型是 `Any`。我们无法为其静态指定类型,因为存在任务转移。如果发生任务转移,意味着任意智能体都可能是最后的智能体,因此我们无法静态地知道可能的输出类型集合。 ## 下一轮的输入 -你可以使用 [`result.to_input_list()`][agents.result.RunResultBase.to_input_list] 将结果转换为输入列表,它会把你提供的原始输入与智能体运行期间生成的条目连接起来。这样可以方便地将一次智能体运行的输出传递到另一次运行中,或者在循环中运行并每次追加新的 用户 输入。 +你可以使用 [`result.to_input_list()`][agents.result.RunResultBase.to_input_list] 将结果转换为一个输入列表,将你提供的原始输入与智能体运行期间生成的条目连接起来。这样便于将一次智能体运行的输出传递到另一次运行中,或在循环中运行并每次附加新的用户输入。 -## 最后一个智能体 +## 最后的智能体 -[`last_agent`][agents.result.RunResultBase.last_agent] 属性包含最后一个运行的智能体。根据你的应用场景,这对于用户下一次输入时通常很有用。例如,如果你有一个一线分诊智能体,会将任务转移给特定语言的智能体,那么你可以存储该最后的智能体,并在下次用户向智能体发送消息时复用它。 +[`last_agent`][agents.result.RunResultBase.last_agent] 属性包含最后一个运行的智能体。根据你的应用场景,这通常对用户下一次输入很有用。例如,如果你有一个前线分诊智能体会进行任务转移到特定语言的智能体,你可以存储最后的智能体,并在用户下次给智能体发送消息时复用它。 -## 新增条目 +## 新条目 -[`new_items`][agents.result.RunResultBase.new_items] 属性包含运行期间生成的新增条目。这些条目是 [`RunItem`][agents.items.RunItem]。运行条目会包装由 LLM 生成的原始条目。 +[`new_items`][agents.result.RunResultBase.new_items] 属性包含运行期间生成的新条目。条目是 [`RunItem`][agents.items.RunItem]。运行条目封装了 LLM 生成的原始条目。 -- [`MessageOutputItem`][agents.items.MessageOutputItem] 表示来自 LLM 的消息。原始条目是生成的消息。 -- [`HandoffCallItem`][agents.items.HandoffCallItem] 表示 LLM 调用了任务转移工具。原始条目是来自 LLM 的工具调用项。 -- [`HandoffOutputItem`][agents.items.HandoffOutputItem] 表示发生了任务转移。原始条目是对任务转移工具调用的工具响应。你也可以从该条目访问源/目标智能体。 -- [`ToolCallItem`][agents.items.ToolCallItem] 表示 LLM 调用了某个工具。 -- [`ToolCallOutputItem`][agents.items.ToolCallOutputItem] 表示某个工具被调用。原始条目是工具响应。你也可以从该条目访问工具输出。 -- [`ReasoningItem`][agents.items.ReasoningItem] 表示来自 LLM 的推理条目。原始条目是生成的推理内容。 +- [`MessageOutputItem`][agents.items.MessageOutputItem] 表示来自 LLM 的消息。原始条目是生成的消息。 +- [`HandoffCallItem`][agents.items.HandoffCallItem] 表示 LLM 调用了任务转移工具。原始条目是来自 LLM 的工具调用项。 +- [`HandoffOutputItem`][agents.items.HandoffOutputItem] 表示发生了任务转移。原始条目是对任务转移工具调用的工具响应。你也可以从该条目访问源/目标智能体。 +- [`ToolCallItem`][agents.items.ToolCallItem] 表示 LLM 调用了某个工具。 +- [`ToolCallOutputItem`][agents.items.ToolCallOutputItem] 表示一个工具被调用。原始条目是工具响应。你也可以从该条目访问工具输出。 +- [`ReasoningItem`][agents.items.ReasoningItem] 表示来自 LLM 的推理条目。原始条目是生成的推理。 ## 其他信息 ### 安全防护措施结果 -如果有的话,[`input_guardrail_results`][agents.result.RunResultBase.input_guardrail_results] 和 [`output_guardrail_results`][agents.result.RunResultBase.output_guardrail_results] 属性包含安全防护措施的结果。安全防护措施结果有时包含你可能想记录或存储的有用信息,因此我们将其提供给你。 +[`input_guardrail_results`][agents.result.RunResultBase.input_guardrail_results] 和 [`output_guardrail_results`][agents.result.RunResultBase.output_guardrail_results] 属性包含安全防护措施的结果(如果有)。安全防护措施的结果有时包含你可能想记录或存储的有用信息,因此我们将其提供给你。 ### 原始响应 -[`raw_responses`][agents.result.RunResultBase.raw_responses] 属性包含由 LLM 生成的 [`ModelResponse`] 列表。[agents.items.ModelResponse] +[`raw_responses`][agents.result.RunResultBase.raw_responses] 属性包含由 LLM 生成的 [`ModelResponse`][agents.items.ModelResponse]。 ### 原始输入 -[`input`][agents.result.RunResultBase.input] 属性包含你提供给 `run` 方法的原始输入。大多数情况下你可能不需要它,但在需要时可以使用。 \ No newline at end of file +[`input`][agents.result.RunResultBase.input] 属性包含你传递给 `run` 方法的原始输入。在大多数情况下你不需要它,但如果需要也可以使用。 \ No newline at end of file diff --git a/docs/zh/running_agents.md b/docs/zh/running_agents.md index 1ae518c2c..7cbb3f212 100644 --- a/docs/zh/running_agents.md +++ b/docs/zh/running_agents.md @@ -4,11 +4,11 @@ search: --- # 运行智能体 -你可以通过 [`Runner`][agents.run.Runner] 类来运行智能体。你有 3 种选择: +你可以通过 [`Runner`][agents.run.Runner] 类来运行智能体。你有 3 个选项: -1. [`Runner.run()`][agents.run.Runner.run],异步运行并返回一个 [`RunResult`][agents.result.RunResult]。 -2. [`Runner.run_sync()`][agents.run.Runner.run_sync],同步方法,本质上在内部调用 `.run()`。 -3. [`Runner.run_streamed()`][agents.run.Runner.run_streamed],异步运行并返回一个 [`RunResultStreaming`][agents.result.RunResultStreaming]。它以流式模式调用 LLM,并在接收到事件时将其流式传输给你。 +1. [`Runner.run()`][agents.run.Runner.run]:异步运行并返回 [`RunResult`][agents.result.RunResult]。 +2. [`Runner.run_sync()`][agents.run.Runner.run_sync]:同步方法,内部调用 `.run()`。 +3. [`Runner.run_streamed()`][agents.run.Runner.run_streamed]:异步运行并返回 [`RunResultStreaming`][agents.result.RunResultStreaming]。它以流式模式调用 LLM,并在接收时将这些事件流式传给你。 ```python from agents import Agent, Runner @@ -23,55 +23,55 @@ async def main(): # Infinite loop's dance ``` -在[结果指南](results.md)中阅读更多内容。 +在[结果指南](results.md)中了解更多。 ## 智能体循环 -当你在 `Runner` 中使用 run 方法时,你需要传入一个起始智能体和输入。输入可以是字符串(视为用户消息),也可以是一组输入项列表,即 OpenAI Responses API 中的项目。 +当你使用 `Runner` 的 run 方法时,你需要传入一个起始智能体和输入。输入可以是字符串(视为一条用户消息),也可以是输入项的列表,即 OpenAI Responses API 中的各项。 -runner 随后运行一个循环: +Runner 会运行一个循环: 1. 我们使用当前输入为当前智能体调用 LLM。 2. LLM 生成输出。 1. 如果 LLM 返回 `final_output`,循环结束并返回结果。 - 2. 如果 LLM 进行任务转移,我们会更新当前智能体和输入,并重新运行循环。 - 3. 如果 LLM 产生工具调用,我们会运行这些工具调用,附加结果,并重新运行循环。 -3. 如果超过传入的 `max_turns`,我们会抛出一个 [`MaxTurnsExceeded`][agents.exceptions.MaxTurnsExceeded] 异常。 + 2. 如果 LLM 进行一次 任务转移,我们会更新当前智能体和输入,并重新运行循环。 + 3. 如果 LLM 产生工具调用,我们会运行这些工具调用、附加结果,并重新运行循环。 +3. 如果超过传入的 `max_turns`,我们会抛出 [`MaxTurnsExceeded`][agents.exceptions.MaxTurnsExceeded] 异常。 !!! note - 判断 LLM 输出是否为“最终输出”的规则是:它生成了所需类型的文本输出,且没有工具调用。 + 判断 LLM 输出是否为“最终输出”的规则是:它产生了所需类型的文本输出,且没有工具调用。 ## 流式传输 -流式传输允许你在 LLM 运行时额外接收流式事件。流结束后,[`RunResultStreaming`][agents.result.RunResultStreaming] 将包含有关此次运行的完整信息,包括所有新产生的输出。你可以调用 `.stream_events()` 获取流式事件。更多信息请阅读[流式传输指南](streaming.md)。 +流式传输允许你在 LLM 运行时额外接收流式事件。流结束后,[`RunResultStreaming`][agents.result.RunResultStreaming] 将包含关于此次运行的完整信息,包括所有新产生的输出。你可以调用 `.stream_events()` 获取流式事件。更多信息见[流式传输指南](streaming.md)。 ## 运行配置 -`run_config` 参数允许你为智能体运行配置一些全局设置: +`run_config` 参数允许你为一次智能体运行配置一些全局设置: -- [`model`][agents.run.RunConfig.model]:允许设置一个全局使用的 LLM 模型,而不管每个 Agent 的 `model` 是什么。 -- [`model_provider`][agents.run.RunConfig.model_provider]:用于查找模型名称的模型提供方,默认为 OpenAI。 -- [`model_settings`][agents.run.RunConfig.model_settings]:覆盖智能体特定设置。例如你可以设置全局的 `temperature` 或 `top_p`。 -- [`input_guardrails`][agents.run.RunConfig.input_guardrails], [`output_guardrails`][agents.run.RunConfig.output_guardrails]:要在所有运行中包含的输入或输出安全防护措施列表。 -- [`handoff_input_filter`][agents.run.RunConfig.handoff_input_filter]:应用于所有任务转移的全局输入过滤器(如果该任务转移尚未设置)。输入过滤器允许你编辑发送给新智能体的输入。更多细节见 [`Handoff.input_filter`][agents.handoffs.Handoff.input_filter] 的文档。 -- [`tracing_disabled`][agents.run.RunConfig.tracing_disabled]:允许你为整个运行禁用[追踪](tracing.md)。 -- [`trace_include_sensitive_data`][agents.run.RunConfig.trace_include_sensitive_data]:配置追踪中是否包含潜在敏感数据,例如 LLM 与工具调用的输入/输出。 -- [`workflow_name`][agents.run.RunConfig.workflow_name], [`trace_id`][agents.run.RunConfig.trace_id], [`group_id`][agents.run.RunConfig.group_id]:为此次运行设置追踪工作流名称、追踪 ID 和追踪分组 ID。我们建议至少设置 `workflow_name`。分组 ID 是可选字段,可用于跨多个运行关联追踪。 +- [`model`][agents.run.RunConfig.model]:允许设置一个全局的 LLM 模型使用,而不受每个 Agent 自身的 `model` 限制。 +- [`model_provider`][agents.run.RunConfig.model_provider]:用于查找模型名称的模型提供方,默认是 OpenAI。 +- [`model_settings`][agents.run.RunConfig.model_settings]:覆盖智能体级别的设置。例如,你可以设置全局的 `temperature` 或 `top_p`。 +- [`input_guardrails`][agents.run.RunConfig.input_guardrails], [`output_guardrails`][agents.run.RunConfig.output_guardrails]:要在所有运行中包含的输入或输出 安全防护措施 列表。 +- [`handoff_input_filter`][agents.run.RunConfig.handoff_input_filter]:应用于所有 任务转移 的全局输入过滤器(如果该任务转移尚无过滤器)。输入过滤器允许你编辑发送给新智能体的输入。更多细节见 [`Handoff.input_filter`][agents.handoffs.Handoff.input_filter] 的文档。 +- [`tracing_disabled`][agents.run.RunConfig.tracing_disabled]:允许为整个运行禁用[追踪](tracing.md)。 +- [`trace_include_sensitive_data`][agents.run.RunConfig.trace_include_sensitive_data]:配置追踪中是否包含潜在的敏感数据,如 LLM 和工具调用的输入/输出。 +- [`workflow_name`][agents.run.RunConfig.workflow_name], [`trace_id`][agents.run.RunConfig.trace_id], [`group_id`][agents.run.RunConfig.group_id]:为此次运行设置追踪的工作流名称、追踪 ID 和追踪分组 ID。我们建议至少设置 `workflow_name`。分组 ID 是一个可选字段,用于将多个运行的追踪关联起来。 - [`trace_metadata`][agents.run.RunConfig.trace_metadata]:要包含在所有追踪上的元数据。 ## 会话/聊天线程 -调用任一运行方法都可能导致一个或多个智能体运行(因此一个或多个 LLM 调用),但它表示聊天会话中的单个逻辑轮次。例如: +调用任一运行方法可能会导致一个或多个智能体运行(因此会进行一次或多次 LLM 调用),但它表示聊天对话中的单个逻辑轮次。例如: -1. 用户轮次:用户输入文本 -2. Runner 运行:第一个智能体调用 LLM,运行工具,进行一次任务转移到第二个智能体,第二个智能体运行更多工具,然后生成输出。 +1. 用户回合:用户输入文本 +2. Runner 运行:第一个智能体调用 LLM,运行工具,执行一次 任务转移 到第二个智能体,第二个智能体再运行更多工具,然后产生输出。 -在智能体运行结束时,你可以选择向用户展示什么。例如,你可以向用户展示智能体生成的每个新条目,或仅展示最终输出。无论哪种方式,用户都可能继续追问,此时你可以再次调用 run 方法。 +在智能体运行结束时,你可以选择向用户展示什么。例如,你可以展示智能体生成的每一个新项,或只展示最终输出。无论哪种方式,用户都可能接着提出后续问题,此时你可以再次调用运行方法。 ### 手动会话管理 -你可以使用 [`RunResultBase.to_input_list()`][agents.result.RunResultBase.to_input_list] 手动管理会话历史,以获取下一轮的输入: +你可以使用 [`RunResultBase.to_input_list()`][agents.result.RunResultBase.to_input_list] 方法手动管理会话历史,以获取下一回合的输入: ```python async def main(): @@ -93,7 +93,7 @@ async def main(): ### 使用 Sessions 的自动会话管理 -更简单的方式是使用 [Sessions](sessions.md) 自动处理会话历史,而无需手动调用 `.to_input_list()`: +若需要更简单的方式,你可以使用 [Sessions](sessions/index.md) 自动处理会话历史,而无需手动调用 `.to_input_list()`: ```python from agents import Agent, Runner, SQLiteSession @@ -123,17 +123,17 @@ Sessions 会自动: - 在每次运行后存储新消息 - 为不同的 session ID 维护独立会话 -更多细节见[Sessions 文档](sessions.md)。 +更多详情见 [Sessions 文档](sessions/index.md)。 ### 服务管理的会话 -你也可以让 OpenAI 会话状态功能在服务端管理会话状态,而不是在本地通过 `to_input_list()` 或 `Sessions` 进行处理。这样可以在不手动重发所有历史消息的情况下保留会话历史。更多信息请参阅 [OpenAI Conversation state 指南](https://platform.openai.com/docs/guides/conversation-state?api-mode=responses)。 +你也可以让 OpenAI 的会话状态功能在服务端管理会话状态,而不是使用 `to_input_list()` 或 `Sessions` 在本地处理。这样可以在不手动重发所有历史消息的情况下保留会话历史。更多详情见 [OpenAI Conversation state 指南](https://platform.openai.com/docs/guides/conversation-state?api-mode=responses)。 -OpenAI 提供两种跨轮次追踪状态的方式: +OpenAI 提供两种跨回合跟踪状态的方式: #### 1. 使用 `conversation_id` -你首先使用 OpenAI Conversations API 创建一个会话,然后在后续每次调用中复用其 ID: +你首先使用 OpenAI Conversations API 创建一个会话,然后在每次后续调用中复用其 ID: ```python from agents import Agent, Runner @@ -165,7 +165,7 @@ async def main(): #### 2. 使用 `previous_response_id` -另一种选择是**响应链式(response chaining)**,每一轮显式地链接到上一轮的响应 ID。 +另一种方式是**响应链式关联(response chaining)**,每一回合都显式链接到上一回合的响应 ID。 ```python from agents import Agent, Runner @@ -189,18 +189,18 @@ async def main(): ``` -## 长时运行的智能体与人机协同 +## 长时运行智能体与人类在环 -你可以使用 Agents SDK 与 [Temporal](https://temporal.io/) 的集成来运行持久的、长时运行的工作流,包括人机协同任务。查看此[视频](https://www.youtube.com/watch?v=fFBZqzT4DD8)中 Temporal 与 Agents SDK 协同完成长时任务的演示,以及[此处的文档](https://github.com/temporalio/sdk-python/tree/main/temporalio/contrib/openai_agents)。 +你可以使用 Agents SDK 的 [Temporal](https://temporal.io/) 集成来运行持久的长时工作流,包括人类在环任务。观看此[视频](https://www.youtube.com/watch?v=fFBZqzT4DD8)中 Temporal 与 Agents SDK 协作完成长时任务的演示,并[查看此处的文档](https://github.com/temporalio/sdk-python/tree/main/temporalio/contrib/openai_agents)。 ## 异常 -SDK 在特定情况下会抛出异常。完整列表见 [`agents.exceptions`][]。概览如下: +SDK 在某些情况下会抛出异常。完整列表见 [`agents.exceptions`][]。概览如下: -- [`AgentsException`][agents.exceptions.AgentsException]:这是 SDK 内抛出的所有异常的基类。它作为通用类型,其他所有特定异常都从它派生。 -- [`MaxTurnsExceeded`][agents.exceptions.MaxTurnsExceeded]:当智能体的运行超过传给 `Runner.run`、`Runner.run_sync` 或 `Runner.run_streamed` 方法的 `max_turns` 限制时抛出。表示智能体无法在指定的交互轮次内完成任务。 -- [`ModelBehaviorError`][agents.exceptions.ModelBehaviorError]:当底层模型(LLM)产生出乎意料或无效的输出时发生。这可能包括: - - JSON 格式错误:当模型为工具调用或其直接输出提供了格式错误的 JSON,尤其是在指定了特定 `output_type` 的情况下。 - - 意外的工具相关失败:当模型未按预期方式使用工具 -- [`UserError`][agents.exceptions.UserError]:当你(使用 SDK 编写代码的人)在使用 SDK 时出错会抛出该异常。通常由不正确的代码实现、无效的配置或误用 SDK 的 API 引起。 -- [`InputGuardrailTripwireTriggered`][agents.exceptions.InputGuardrailTripwireTriggered], [`OutputGuardrailTripwireTriggered`][agents.exceptions.OutputGuardrailTripwireTriggered]:当输入安全防护措施或输出安全防护措施的条件分别被触发时抛出。输入安全防护措施在处理前检查传入消息,而输出安全防护措施在交付前检查智能体的最终响应。 \ No newline at end of file +- [`AgentsException`][agents.exceptions.AgentsException]:SDK 内抛出的所有异常的基类。它作为通用类型,其他特定异常均由其派生。 +- [`MaxTurnsExceeded`][agents.exceptions.MaxTurnsExceeded]:当智能体运行超过传递给 `Runner.run`、`Runner.run_sync` 或 `Runner.run_streamed` 的 `max_turns` 限制时抛出。表示智能体无法在指定的交互轮次内完成任务。 +- [`ModelBehaviorError`][agents.exceptions.ModelBehaviorError]:当底层模型(LLM)产生意外或无效输出时发生。这可能包括: + - JSON 格式错误:当模型为工具调用或其直接输出提供了格式错误的 JSON,尤其是在定义了特定的 `output_type` 时。 + - 与工具相关的意外失败:当模型未按预期方式使用工具时 +- [`UserError`][agents.exceptions.UserError]:当你(使用 SDK 编写代码的人)在使用 SDK 时发生错误时抛出。通常由不正确的代码实现、无效配置或错误使用 SDK 的 API 引起。 +- [`InputGuardrailTripwireTriggered`][agents.exceptions.InputGuardrailTripwireTriggered], [`OutputGuardrailTripwireTriggered`][agents.exceptions.OutputGuardrailTripwireTriggered]:当分别满足输入 安全防护措施 或输出 安全防护措施 的条件时抛出。输入 安全防护措施 在处理前检查传入消息,而输出 安全防护措施 在交付前检查智能体的最终响应。 \ No newline at end of file diff --git a/docs/zh/sessions.md b/docs/zh/sessions.md index 24fc6fa6a..7e43d8044 100644 --- a/docs/zh/sessions.md +++ b/docs/zh/sessions.md @@ -4,9 +4,9 @@ search: --- # 会话 -Agents SDK 提供了内置的会话记忆,用于在多个智能体运行之间自动维护对话历史,从而无需在轮次之间手动处理 `.to_input_list()`。 +Agents SDK 提供内置的会话内存,可在多个智能体运行之间自动维护对话历史,无需在回合之间手动处理 `.to_input_list()`。 -会话为特定会话存储对话历史,使智能体无需显式的手动内存管理即可保持上下文。这对于构建聊天应用或多轮对话(希望智能体记住先前交互)尤其有用。 +会话为特定会话存储对话历史,使智能体无需显式的手动内存管理即可保持上下文。这对于构建聊天应用或多轮对话尤为有用,你可以让智能体记住之前的交互。 ## 快速开始 @@ -49,17 +49,17 @@ print(result.final_output) # "Approximately 39 million" ## 工作原理 -当启用会话记忆时: +当启用会话内存时: -1. **每次运行前**:运行器会自动检索该会话的对话历史,并将其添加到输入项之前。 -2. **每次运行后**:运行期间生成的所有新项目(用户输入、助手响应、工具调用等)都会自动存储到会话中。 -3. **上下文保留**:后续使用相同会话的每次运行都会包含完整的对话历史,从而使智能体保持上下文。 +1. **每次运行前**:运行器会自动检索该会话的对话历史,并将其预置到输入项之前。 +2. **每次运行后**:在运行期间生成的所有新条目(用户输入、助手响应、工具调用等)都会自动存储到会话中。 +3. **上下文保留**:使用相同会话的后续运行将包含完整对话历史,使智能体能够保持上下文。 这消除了在运行之间手动调用 `.to_input_list()` 并管理对话状态的需要。 -## 记忆操作 +## 内存操作 -### 基本操作 +### 基础操作 会话支持多种用于管理对话历史的操作: @@ -88,7 +88,7 @@ await session.clear_session() ### 使用 pop_item 进行更正 -当你希望撤销或修改对话中的最后一项时,`pop_item` 方法尤其有用: +当你想要撤销或修改对话中的最后一个条目时,`pop_item` 方法特别有用: ```python from agents import Agent, Runner, SQLiteSession @@ -117,19 +117,19 @@ result = await Runner.run( print(f"Agent: {result.final_output}") ``` -## 记忆选项 +## 内存选项 -### 无记忆(默认) +### 无内存(默认) ```python # Default behavior - no session memory result = await Runner.run(agent, "Hello") ``` -### OpenAI Conversations API 记忆 +### OpenAI Conversations API 内存 -使用 [OpenAI Conversations API](https://platform.openai.com/docs/api-reference/conversations/create) 持久化 -[conversation state](https://platform.openai.com/docs/guides/conversation-state?api-mode=responses#using-the-conversations-api),而无需管理你自己的数据库。当你已经依赖由 OpenAI 托管的基础设施来存储对话历史时,这将非常有用。 +使用 [OpenAI Conversations API](https://platform.openai.com/docs/api-reference/conversations/create) 来持久化 +[conversation state](https://platform.openai.com/docs/guides/conversation-state?api-mode=responses#using-the-conversations-api),无需管理你自己的数据库。当你已经依赖由 OpenAI 托管的基础设施来存储对话历史时,这将很有帮助。 ```python from agents import OpenAIConversationsSession @@ -146,7 +146,7 @@ result = await Runner.run( ) ``` -### SQLite 记忆 +### SQLite 内存 ```python from agents import SQLiteSession @@ -165,7 +165,7 @@ result = await Runner.run( ) ``` -### 多个会话 +### 多会话 ```python from agents import Agent, Runner, SQLiteSession @@ -190,9 +190,9 @@ result2 = await Runner.run( ### 由 SQLAlchemy 驱动的会话 -对于更高级的用例,你可以使用由 SQLAlchemy 驱动的会话后端。这允许你使用 SQLAlchemy 支持的任意数据库(PostgreSQL、MySQL、SQLite 等)进行会话存储。 +对于更高级的用例,你可以使用由 SQLAlchemy 驱动的会话后端。这样就可以使用任何 SQLAlchemy 支持的数据库(PostgreSQL、MySQL、SQLite 等)来进行会话存储。 -**示例 1: 使用 `from_url` 配合内存型 SQLite** +**示例 1:使用 `from_url` 搭配内存型 SQLite** 这是最简单的入门方式,适合开发和测试。 @@ -215,9 +215,9 @@ if __name__ == "__main__": asyncio.run(main()) ``` -**示例 2: 使用现有的 SQLAlchemy 引擎** +**示例 2:使用现有的 SQLAlchemy 引擎** -在生产应用中,你很可能已经有一个 SQLAlchemy `AsyncEngine` 实例。你可以将其直接传入会话。 +在生产应用中,你很可能已经拥有一个 SQLAlchemy 的 `AsyncEngine` 实例。你可以将其直接传递给会话。 ```python import asyncio @@ -247,11 +247,11 @@ if __name__ == "__main__": ### 加密会话 -对于需要对静态对话数据进行加密的应用,你可以使用 `EncryptedSession` 来包装任意会话后端,实现透明加密与基于 TTL 的自动过期。这需要 `encrypt` 可选依赖:`pip install openai-agents[encrypt]`。 +对于需要对静态对话数据进行加密的应用,你可以使用 `EncryptedSession` 来包装任意会话后端,实现透明加密和基于 TTL 的自动过期。这需要 `encrypt` 可选依赖:`pip install openai-agents[encrypt]`。 -`EncryptedSession` 使用基于会话的密钥派生(HKDF)的 Fernet 加密,并支持旧消息的自动过期。当项目超过 TTL 时,在检索过程中会被静默跳过。 +`EncryptedSession` 使用基于每个会话的密钥派生(HKDF)的 Fernet 加密,并支持旧消息的自动过期。当条目超过 TTL 时,它们在检索期间会被静默跳过。 -**示例:加密 SQLAlchemy 会话数据** +**示例:为 SQLAlchemy 会话数据加密** ```python import asyncio @@ -284,22 +284,22 @@ if __name__ == "__main__": **关键特性:** -- **透明加密**:在存储前自动加密所有会话项目,并在检索时解密 -- **每会话密钥派生**:使用会话 ID 作为盐配合 HKDF 推导唯一加密密钥 -- **基于 TTL 的过期**:根据可配置的存活时间(默认:10 分钟)自动使旧消息过期 -- **灵活的密钥输入**:接受 Fernet 密钥或原始字符串作为加密密钥 -- **可包装任意会话**:适用于 SQLite、SQLAlchemy 或自定义会话实现 +- **透明加密**:在存储前自动加密所有会话条目,并在检索时解密 +- **按会话派生密钥**:使用会话 ID 作为盐的 HKDF 来派生唯一加密密钥 +- **基于 TTL 的过期**:根据可配置的生存时间(默认:10 分钟)自动使旧消息过期 +- **灵活的密钥输入**:接受 Fernet 密钥或原始字符串作为加密密钥 +- **可包装任意会话**:适用于 SQLite、SQLAlchemy 或自定义会话实现 !!! warning "重要的安全注意事项" - - 将加密密钥安全存储(例如,环境变量、密钥管理服务) - - 过期令牌基于应用服务的系统时钟进行校验——请确保所有服务通过 NTP 同步时间,以避免因时钟漂移导致的误拒 - - 底层会话仍存储加密数据,因此你仍可掌控你的数据库基础设施 + - 安全存储你的加密密钥(如环境变量、密钥管理服务) + - 过期令牌根据应用服务的系统时钟被拒绝——请确保所有服务均通过 NTP 同步时间,以避免因时钟漂移导致的误拒 + - 底层会话仍存储加密数据,因此你依然可以掌控你的数据库基础设施 -## 自定义记忆实现 +## 自定义内存实现 -你可以通过创建一个遵循 [`Session`][agents.memory.session.Session] 协议的类来实现你自己的会话记忆: +你可以通过创建遵循 [`Session`][agents.memory.session.Session] 协议的类来实现你自己的会话内存: ```python from agents.memory.session import SessionABC @@ -346,20 +346,20 @@ result = await Runner.run( ### 会话 ID 命名 -使用有意义的会话 ID,以帮助组织对话: +使用有意义的会话 ID 来帮助组织对话: -- 用户维度:"user_12345" -- 线程维度:"thread_abc123" -- 场景维度:"support_ticket_456" +- 基于用户:`"user_12345"` +- 基于线程:`"thread_abc123"` +- 基于上下文:`"support_ticket_456"` -### 记忆持久化 +### 内存持久化 -- 使用内存型 SQLite(`SQLiteSession("session_id")`)用于临时会话 -- 使用基于文件的 SQLite(`SQLiteSession("session_id", "path/to/db.sqlite")`)用于持久会话 -- 使用由 SQLAlchemy 驱动的会话(`SQLAlchemySession("session_id", engine=engine, create_tables=True")`)用于基于 SQLAlchemy 支持的现有数据库的生产系统 -- 当你倾向于将历史存储在 OpenAI Conversations API 中时,使用由 OpenAI 托管的存储(`OpenAIConversationsSession()`) -- 使用加密会话(`EncryptedSession(session_id, underlying_session, encryption_key)`)为任意会话添加透明加密与基于 TTL 的过期 -- 针对其他生产系统(Redis、Django 等)考虑实现自定义会话后端以满足更高级用例 +- 临时会话使用内存型 SQLite(`SQLiteSession("session_id")`) +- 持久化会话使用基于文件的 SQLite(`SQLiteSession("session_id", "path/to/db.sqlite")`) +- 生产系统且已有数据库时,使用由 SQLAlchemy 驱动的会话(`SQLAlchemySession("session_id", engine=engine, create_tables=True)`),支持 SQLAlchemy 支持的数据库 +- 当你希望将历史存储在 OpenAI Conversations API 中时,使用 OpenAI 托管的存储(`OpenAIConversationsSession()`) +- 使用加密会话(`EncryptedSession(session_id, underlying_session, encryption_key)`)为任意会话提供透明加密与基于 TTL 的过期 +- 针对其他生产系统(Redis、Django 等)考虑实现自定义会话后端,以满足更高级的用例 ### 会话管理 @@ -387,7 +387,7 @@ result2 = await Runner.run( ## 完整示例 -下面是一个展示会话记忆实际效果的完整示例: +以下是展示会话内存实际效果的完整示例: ```python import asyncio @@ -451,10 +451,10 @@ if __name__ == "__main__": ## API 参考 -有关详细的 API 文档,请参阅: +详细的 API 文档请参阅: -- [`Session`][agents.memory.Session] - 协议接口 -- [`SQLiteSession`][agents.memory.SQLiteSession] - SQLite 实现 -- [`OpenAIConversationsSession`](ref/memory/openai_conversations_session.md) - OpenAI Conversations API 实现 -- [`SQLAlchemySession`][agents.extensions.memory.sqlalchemy_session.SQLAlchemySession] - 由 SQLAlchemy 驱动的实现 -- [`EncryptedSession`][agents.extensions.memory.encrypt_session.EncryptedSession] - 带 TTL 的加密会话包装器 \ No newline at end of file +- [`Session`][agents.memory.Session] - 协议接口 +- [`SQLiteSession`][agents.memory.SQLiteSession] - SQLite 实现 +- [`OpenAIConversationsSession`](ref/memory/openai_conversations_session.md) - OpenAI Conversations API 实现 +- [`SQLAlchemySession`][agents.extensions.memory.sqlalchemy_session.SQLAlchemySession] - 由 SQLAlchemy 驱动的实现 +- [`EncryptedSession`][agents.extensions.memory.encrypt_session.EncryptedSession] - 具有 TTL 的加密会话封装器 \ No newline at end of file diff --git a/docs/zh/sessions/advanced_sqlite_session.md b/docs/zh/sessions/advanced_sqlite_session.md new file mode 100644 index 000000000..6048268e8 --- /dev/null +++ b/docs/zh/sessions/advanced_sqlite_session.md @@ -0,0 +1,307 @@ +--- +search: + exclude: true +--- +# 高级 SQLite 会话 + +`AdvancedSQLiteSession` 是基础 `SQLiteSession` 的增强版本,提供高级对话管理能力,包括对话分支、详细的使用分析以及结构化对话查询。 + +## 功能 + +- **对话分支**: 可从任意用户消息创建替代对话路径 +- **使用跟踪**: 每轮的详细 token 使用分析,并提供完整的 JSON 明细 +- **结构化查询**: 按轮次获取对话、工具使用统计等 +- **分支管理**: 独立的分支切换与管理 +- **消息结构元数据**: 跟踪消息类型、工具使用与对话流程 + +## 快速开始 + +```python +from agents import Agent, Runner +from agents.extensions.memory import AdvancedSQLiteSession + +# Create agent +agent = Agent( + name="Assistant", + instructions="Reply very concisely.", +) + +# Create an advanced session +session = AdvancedSQLiteSession( + session_id="conversation_123", + db_path="conversations.db", + create_tables=True +) + +# First conversation turn +result = await Runner.run( + agent, + "What city is the Golden Gate Bridge in?", + session=session +) +print(result.final_output) # "San Francisco" + +# IMPORTANT: Store usage data +await session.store_run_usage(result) + +# Continue conversation +result = await Runner.run( + agent, + "What state is it in?", + session=session +) +print(result.final_output) # "California" +await session.store_run_usage(result) +``` + +## 初始化 + +```python +from agents.extensions.memory import AdvancedSQLiteSession + +# Basic initialization +session = AdvancedSQLiteSession( + session_id="my_conversation", + create_tables=True # Auto-create advanced tables +) + +# With persistent storage +session = AdvancedSQLiteSession( + session_id="user_123", + db_path="path/to/conversations.db", + create_tables=True +) + +# With custom logger +import logging +logger = logging.getLogger("my_app") +session = AdvancedSQLiteSession( + session_id="session_456", + create_tables=True, + logger=logger +) +``` + +### 参数 + +- `session_id` (str): 会话的唯一标识符 +- `db_path` (str | Path): SQLite 数据库文件路径。内存存储默认使用 `:memory:` +- `create_tables` (bool): 是否自动创建高级表。默认为 `False` +- `logger` (logging.Logger | None): 会话的自定义日志记录器。默认为模块 logger + +## 使用跟踪 + +AdvancedSQLiteSession 通过按对话轮次存储 token 使用数据,提供详细的使用分析。**这完全取决于在每次智能体运行后调用 `store_run_usage` 方法。** + +### 存储使用数据 + +```python +# After each agent run, store the usage data +result = await Runner.run(agent, "Hello", session=session) +await session.store_run_usage(result) + +# This stores: +# - Total tokens used +# - Input/output token breakdown +# - Request count +# - Detailed JSON token information (if available) +``` + +### 获取使用统计 + +```python +# Get session-level usage (all branches) +session_usage = await session.get_session_usage() +if session_usage: + print(f"Total requests: {session_usage['requests']}") + print(f"Total tokens: {session_usage['total_tokens']}") + print(f"Input tokens: {session_usage['input_tokens']}") + print(f"Output tokens: {session_usage['output_tokens']}") + print(f"Total turns: {session_usage['total_turns']}") + +# Get usage for specific branch +branch_usage = await session.get_session_usage(branch_id="main") + +# Get usage by turn +turn_usage = await session.get_turn_usage() +for turn_data in turn_usage: + print(f"Turn {turn_data['user_turn_number']}: {turn_data['total_tokens']} tokens") + if turn_data['input_tokens_details']: + print(f" Input details: {turn_data['input_tokens_details']}") + if turn_data['output_tokens_details']: + print(f" Output details: {turn_data['output_tokens_details']}") + +# Get usage for specific turn +turn_2_usage = await session.get_turn_usage(user_turn_number=2) +``` + +## 对话分支 + +AdvancedSQLiteSession 的关键特性之一是能够从任意用户消息创建对话分支,从而探索替代的对话路径。 + +### 创建分支 + +```python +# Get available turns for branching +turns = await session.get_conversation_turns() +for turn in turns: + print(f"Turn {turn['turn']}: {turn['content']}") + print(f"Can branch: {turn['can_branch']}") + +# Create a branch from turn 2 +branch_id = await session.create_branch_from_turn(2) +print(f"Created branch: {branch_id}") + +# Create a branch with custom name +branch_id = await session.create_branch_from_turn( + 2, + branch_name="alternative_path" +) + +# Create branch by searching for content +branch_id = await session.create_branch_from_content( + "weather", + branch_name="weather_focus" +) +``` + +### 分支管理 + +```python +# List all branches +branches = await session.list_branches() +for branch in branches: + current = " (current)" if branch["is_current"] else "" + print(f"{branch['branch_id']}: {branch['user_turns']} turns, {branch['message_count']} messages{current}") + +# Switch between branches +await session.switch_to_branch("main") +await session.switch_to_branch(branch_id) + +# Delete a branch +await session.delete_branch(branch_id, force=True) # force=True allows deleting current branch +``` + +### 分支工作流示例 + +```python +# Original conversation +result = await Runner.run(agent, "What's the capital of France?", session=session) +await session.store_run_usage(result) + +result = await Runner.run(agent, "What's the weather like there?", session=session) +await session.store_run_usage(result) + +# Create branch from turn 2 (weather question) +branch_id = await session.create_branch_from_turn(2, "weather_focus") + +# Continue in new branch with different question +result = await Runner.run( + agent, + "What are the main tourist attractions in Paris?", + session=session +) +await session.store_run_usage(result) + +# Switch back to main branch +await session.switch_to_branch("main") + +# Continue original conversation +result = await Runner.run( + agent, + "How expensive is it to visit?", + session=session +) +await session.store_run_usage(result) +``` + +## 结构化查询 + +AdvancedSQLiteSession 提供多种方法来分析对话结构与内容。 + +### 对话分析 + +```python +# Get conversation organized by turns +conversation_by_turns = await session.get_conversation_by_turns() +for turn_num, items in conversation_by_turns.items(): + print(f"Turn {turn_num}: {len(items)} items") + for item in items: + if item["tool_name"]: + print(f" - {item['type']} (tool: {item['tool_name']})") + else: + print(f" - {item['type']}") + +# Get tool usage statistics +tool_usage = await session.get_tool_usage() +for tool_name, count, turn in tool_usage: + print(f"{tool_name}: used {count} times in turn {turn}") + +# Find turns by content +matching_turns = await session.find_turns_by_content("weather") +for turn in matching_turns: + print(f"Turn {turn['turn']}: {turn['content']}") +``` + +### 消息结构 + +会话会自动跟踪消息结构,包括: + +- 消息类型(user、assistant、tool_call 等) +- 工具调用的工具名称 +- 轮次编号与序号 +- 分支关联 +- 时间戳 + +## 数据库模式 + +AdvancedSQLiteSession 在基础 SQLite 模式之上扩展了两个附加表: + +### message_structure 表 + +```sql +CREATE TABLE message_structure ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + session_id TEXT NOT NULL, + message_id INTEGER NOT NULL, + branch_id TEXT NOT NULL DEFAULT 'main', + message_type TEXT NOT NULL, + sequence_number INTEGER NOT NULL, + user_turn_number INTEGER, + branch_turn_number INTEGER, + tool_name TEXT, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (session_id) REFERENCES agent_sessions(session_id) ON DELETE CASCADE, + FOREIGN KEY (message_id) REFERENCES agent_messages(id) ON DELETE CASCADE +); +``` + +### turn_usage 表 + +```sql +CREATE TABLE turn_usage ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + session_id TEXT NOT NULL, + branch_id TEXT NOT NULL DEFAULT 'main', + user_turn_number INTEGER NOT NULL, + requests INTEGER DEFAULT 0, + input_tokens INTEGER DEFAULT 0, + output_tokens INTEGER DEFAULT 0, + total_tokens INTEGER DEFAULT 0, + input_tokens_details JSON, + output_tokens_details JSON, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (session_id) REFERENCES agent_sessions(session_id) ON DELETE CASCADE, + UNIQUE(session_id, branch_id, user_turn_number) +); +``` + +## 完整示例 + +参见[完整示例](https://github.com/openai/openai-agents-python/tree/main/examples/memory/advanced_sqlite_session_example.py),了解所有功能的综合演示。 + + +## API 参考 + +- [`AdvancedSQLiteSession`][agents.extensions.memory.advanced_sqlite_session.AdvancedSQLiteSession] - 主类 +- [`Session`][agents.memory.session.Session] - 基础会话协议 \ No newline at end of file diff --git a/docs/zh/sessions/encrypted_session.md b/docs/zh/sessions/encrypted_session.md new file mode 100644 index 000000000..9085b2221 --- /dev/null +++ b/docs/zh/sessions/encrypted_session.md @@ -0,0 +1,179 @@ +--- +search: + exclude: true +--- +# 加密会话 + +`EncryptedSession` 为任意会话实现提供透明加密,通过自动过期机制保护会话数据并自动跳过过期项。 + +## 功能 + +- **透明加密**: 使用 Fernet 加密封装任意会话 +- **每会话独立密钥**: 使用 HKDF 进行密钥派生,为每个会话生成唯一密钥 +- **自动过期**: 当 TTL 到期时,旧条目会被静默跳过 +- **即插即用替换**: 可与任何现有会话实现配合使用 + +## 安装 + +加密会话需要安装 `encrypt` 扩展: + +```bash +pip install openai-agents[encrypt] +``` + +## 快速开始 + +```python +import asyncio +from agents import Agent, Runner +from agents.extensions.memory import EncryptedSession, SQLAlchemySession + +async def main(): + agent = Agent("Assistant") + + # Create underlying session + underlying_session = SQLAlchemySession.from_url( + "user-123", + url="sqlite+aiosqlite:///:memory:", + create_tables=True + ) + + # Wrap with encryption + session = EncryptedSession( + session_id="user-123", + underlying_session=underlying_session, + encryption_key="your-secret-key-here", + ttl=600 # 10 minutes + ) + + result = await Runner.run(agent, "Hello", session=session) + print(result.final_output) + +if __name__ == "__main__": + asyncio.run(main()) +``` + +## 配置 + +### 加密密钥 + +加密密钥可以是一个 Fernet 密钥或任意字符串: + +```python +from agents.extensions.memory import EncryptedSession + +# Using a Fernet key (base64-encoded) +session = EncryptedSession( + session_id="user-123", + underlying_session=underlying_session, + encryption_key="your-fernet-key-here", + ttl=600 +) + +# Using a raw string (will be derived to a key) +session = EncryptedSession( + session_id="user-123", + underlying_session=underlying_session, + encryption_key="my-secret-password", + ttl=600 +) +``` + +### TTL(存活时间) + +设置加密条目的有效期: + +```python +# Items expire after 1 hour +session = EncryptedSession( + session_id="user-123", + underlying_session=underlying_session, + encryption_key="secret", + ttl=3600 # 1 hour in seconds +) + +# Items expire after 1 day +session = EncryptedSession( + session_id="user-123", + underlying_session=underlying_session, + encryption_key="secret", + ttl=86400 # 24 hours in seconds +) +``` + +## 与不同会话类型的配合使用 + +### 搭配 SQLite 会话 + +```python +from agents import SQLiteSession +from agents.extensions.memory import EncryptedSession + +# Create encrypted SQLite session +underlying = SQLiteSession("user-123", "conversations.db") + +session = EncryptedSession( + session_id="user-123", + underlying_session=underlying, + encryption_key="secret-key" +) +``` + +### 搭配 SQLAlchemy 会话 + +```python +from agents.extensions.memory import EncryptedSession, SQLAlchemySession + +# Create encrypted SQLAlchemy session +underlying = SQLAlchemySession.from_url( + "user-123", + url="postgresql+asyncpg://user:pass@localhost/db", + create_tables=True +) + +session = EncryptedSession( + session_id="user-123", + underlying_session=underlying, + encryption_key="secret-key" +) +``` + +!!! warning "高级会话功能" + + 当在诸如 `AdvancedSQLiteSession` 等高级会话实现中使用 `EncryptedSession` 时,请注意: + + - 由于消息内容被加密,`find_turns_by_content()` 等方法将无法有效工作 + - 基于内容的搜索作用于加密数据,其效果将受限 + + + +## 密钥派生 + +EncryptedSession 使用 HKDF(基于 HMAC 的密钥派生函数)为每个会话派生唯一的加密密钥: + +- **主密钥**: 你提供的加密密钥 +- **会话盐值**: 会话 ID +- **信息字符串**: `"agents.session-store.hkdf.v1"` +- **输出**: 32 字节的 Fernet 密钥 + +这可确保: +- 每个会话都有唯一的加密密钥 +- 没有主密钥无法推导出会话密钥 +- 不同会话之间无法解密彼此的数据 + +## 自动过期 + +当条目超过 TTL 时,检索过程中会自动跳过: + +```python +# Items older than TTL are silently ignored +items = await session.get_items() # Only returns non-expired items + +# Expired items don't affect session behavior +result = await Runner.run(agent, "Continue conversation", session=session) +``` + +## API 参考 + +- [`EncryptedSession`][agents.extensions.memory.encrypt_session.EncryptedSession] - 主类 +- [`Session`][agents.memory.session.Session] - 基础会话协议 \ No newline at end of file diff --git a/docs/zh/sessions/index.md b/docs/zh/sessions/index.md new file mode 100644 index 000000000..4e7e76f47 --- /dev/null +++ b/docs/zh/sessions/index.md @@ -0,0 +1,435 @@ +--- +search: + exclude: true +--- +# 会话 + +Agents SDK 提供内置会话记忆功能,自动在多个智能体运行之间维护对话历史,无需在回合间手动处理 `.to_input_list()`。 + +会话为特定会话存储对话历史,使智能体无需显式的手动内存管理即可保持上下文。这对构建聊天应用或多轮对话尤为有用,让智能体记住先前的交互。 + +## 快速开始 + +```python +from agents import Agent, Runner, SQLiteSession + +# Create agent +agent = Agent( + name="Assistant", + instructions="Reply very concisely.", +) + +# Create a session instance with a session ID +session = SQLiteSession("conversation_123") + +# First turn +result = await Runner.run( + agent, + "What city is the Golden Gate Bridge in?", + session=session +) +print(result.final_output) # "San Francisco" + +# Second turn - agent automatically remembers previous context +result = await Runner.run( + agent, + "What state is it in?", + session=session +) +print(result.final_output) # "California" + +# Also works with synchronous runner +result = Runner.run_sync( + agent, + "What's the population?", + session=session +) +print(result.final_output) # "Approximately 39 million" +``` + +## 工作原理 + +当启用会话记忆时: + +1. **每次运行前**:运行器会自动获取该会话的对话历史,并将其预置到输入项之前。 +2. **每次运行后**:运行期间生成的所有新项目(用户输入、助手回复、工具调用等)都会自动存储到会话中。 +3. **上下文保留**:对同一会话的后续每次运行都会包含完整对话历史,使智能体能够保持上下文。 + +这消除了在运行之间手动调用 `.to_input_list()` 并管理对话状态的需要。 + +## 内存操作 + +### 基本操作 + +会话支持多种对话历史管理操作: + +```python +from agents import SQLiteSession + +session = SQLiteSession("user_123", "conversations.db") + +# Get all items in a session +items = await session.get_items() + +# Add new items to a session +new_items = [ + {"role": "user", "content": "Hello"}, + {"role": "assistant", "content": "Hi there!"} +] +await session.add_items(new_items) + +# Remove and return the most recent item +last_item = await session.pop_item() +print(last_item) # {"role": "assistant", "content": "Hi there!"} + +# Clear all items from a session +await session.clear_session() +``` + +### 使用 pop_item 进行更正 + +当你希望撤销或修改对话中的最后一项时,`pop_item` 方法特别有用: + +```python +from agents import Agent, Runner, SQLiteSession + +agent = Agent(name="Assistant") +session = SQLiteSession("correction_example") + +# Initial conversation +result = await Runner.run( + agent, + "What's 2 + 2?", + session=session +) +print(f"Agent: {result.final_output}") + +# User wants to correct their question +assistant_item = await session.pop_item() # Remove agent's response +user_item = await session.pop_item() # Remove user's question + +# Ask a corrected question +result = await Runner.run( + agent, + "What's 2 + 3?", + session=session +) +print(f"Agent: {result.final_output}") +``` + +## 会话类型 + +SDK 为不同用例提供了多种会话实现: + +### OpenAI Conversations API 会话 + +通过 `OpenAIConversationsSession` 使用 [OpenAI 的 Conversations API](https://platform.openai.com/docs/api-reference/conversations)。 + +```python +from agents import Agent, Runner, OpenAIConversationsSession + +# Create agent +agent = Agent( + name="Assistant", + instructions="Reply very concisely.", +) + +# Create a new conversation +session = OpenAIConversationsSession() + +# Optionally resume a previous conversation by passing a conversation ID +# session = OpenAIConversationsSession(conversation_id="conv_123") + +# Start conversation +result = await Runner.run( + agent, + "What city is the Golden Gate Bridge in?", + session=session +) +print(result.final_output) # "San Francisco" + +# Continue the conversation +result = await Runner.run( + agent, + "What state is it in?", + session=session +) +print(result.final_output) # "California" +``` + +### SQLite 会话 + +默认、轻量的 SQLite 会话实现: + +```python +from agents import SQLiteSession + +# In-memory database (lost when process ends) +session = SQLiteSession("user_123") + +# Persistent file-based database +session = SQLiteSession("user_123", "conversations.db") + +# Use the session +result = await Runner.run( + agent, + "Hello", + session=session +) +``` + +### SQLAlchemy 会话 + +面向生产的会话实现,支持任何由 SQLAlchemy 支持的数据库: + +```python +from agents.extensions.memory import SQLAlchemySession + +# Using database URL +session = SQLAlchemySession.from_url( + "user_123", + url="postgresql+asyncpg://user:pass@localhost/db", + create_tables=True +) + +# Using existing engine +from sqlalchemy.ext.asyncio import create_async_engine +engine = create_async_engine("postgresql+asyncpg://user:pass@localhost/db") +session = SQLAlchemySession("user_123", engine=engine, create_tables=True) +``` + +参见 [SQLAlchemy 会话](sqlalchemy_session.md) 获取详细文档。 + +### 高级 SQLite 会话 + +增强的 SQLite 会话,支持会话分支、使用分析与结构化查询: + +```python +from agents.extensions.memory import AdvancedSQLiteSession + +# Create with advanced features +session = AdvancedSQLiteSession( + session_id="user_123", + db_path="conversations.db", + create_tables=True +) + +# Automatic usage tracking +result = await Runner.run(agent, "Hello", session=session) +await session.store_run_usage(result) # Track token usage + +# Conversation branching +await session.create_branch_from_turn(2) # Branch from turn 2 +``` + +参见 [高级 SQLite 会话](advanced_sqlite_session.md) 获取详细文档。 + +### 加密会话 + +适用于任意会话实现的透明加密封装: + +```python +from agents.extensions.memory import EncryptedSession, SQLAlchemySession + +# Create underlying session +underlying_session = SQLAlchemySession.from_url( + "user_123", + url="sqlite+aiosqlite:///conversations.db", + create_tables=True +) + +# Wrap with encryption and TTL +session = EncryptedSession( + session_id="user_123", + underlying_session=underlying_session, + encryption_key="your-secret-key", + ttl=600 # 10 minutes +) + +result = await Runner.run(agent, "Hello", session=session) +``` + +参见 [加密会话](encrypted_session.md) 获取详细文档。 + +## 会话管理 + +### 会话 ID 命名 + +使用有意义的会话 ID,帮助你组织对话: + +- 用户维度:`"user_12345"` +- 线程维度:`"thread_abc123"` +- 场景维度:`"support_ticket_456"` + +### 内存持久化 + +- 使用内存型 SQLite(`SQLiteSession("session_id")`)用于临时对话 +- 使用文件型 SQLite(`SQLiteSession("session_id", "path/to/db.sqlite")`)用于持久化对话 +- 使用 SQLAlchemy 驱动的会话(`SQLAlchemySession("session_id", engine=engine, create_tables=True)`)用于基于 SQLAlchemy 支持的现有数据库的生产系统 +- 当你希望将历史存储在 OpenAI Conversations API 中时,使用 OpenAI 托管存储(`OpenAIConversationsSession()`) +- 使用加密会话(`EncryptedSession(session_id, underlying_session, encryption_key)`)为任意会话提供透明加密与基于 TTL 的过期 +- 可考虑为其他生产系统(Redis、Django 等)实现自定义会话后端,以支持更高级的用例 + +### 多会话 + +```python +from agents import Agent, Runner, SQLiteSession + +agent = Agent(name="Assistant") + +# Different sessions maintain separate conversation histories +session_1 = SQLiteSession("user_123", "conversations.db") +session_2 = SQLiteSession("user_456", "conversations.db") + +result1 = await Runner.run( + agent, + "Help me with my account", + session=session_1 +) +result2 = await Runner.run( + agent, + "What are my charges?", + session=session_2 +) +``` + +### 会话共享 + +```python +# Different agents can share the same session +support_agent = Agent(name="Support") +billing_agent = Agent(name="Billing") +session = SQLiteSession("user_123") + +# Both agents will see the same conversation history +result1 = await Runner.run( + support_agent, + "Help me with my account", + session=session +) +result2 = await Runner.run( + billing_agent, + "What are my charges?", + session=session +) +``` + +## 完整示例 + +以下是一个完整示例,展示会话记忆的实际效果: + +```python +import asyncio +from agents import Agent, Runner, SQLiteSession + + +async def main(): + # Create an agent + agent = Agent( + name="Assistant", + instructions="Reply very concisely.", + ) + + # Create a session instance that will persist across runs + session = SQLiteSession("conversation_123", "conversation_history.db") + + print("=== Sessions Example ===") + print("The agent will remember previous messages automatically.\n") + + # First turn + print("First turn:") + print("User: What city is the Golden Gate Bridge in?") + result = await Runner.run( + agent, + "What city is the Golden Gate Bridge in?", + session=session + ) + print(f"Assistant: {result.final_output}") + print() + + # Second turn - the agent will remember the previous conversation + print("Second turn:") + print("User: What state is it in?") + result = await Runner.run( + agent, + "What state is it in?", + session=session + ) + print(f"Assistant: {result.final_output}") + print() + + # Third turn - continuing the conversation + print("Third turn:") + print("User: What's the population of that state?") + result = await Runner.run( + agent, + "What's the population of that state?", + session=session + ) + print(f"Assistant: {result.final_output}") + print() + + print("=== Conversation Complete ===") + print("Notice how the agent remembered the context from previous turns!") + print("Sessions automatically handles conversation history.") + + +if __name__ == "__main__": + asyncio.run(main()) +``` + +## 自定义会话实现 + +你可以通过创建遵循 [`Session`][agents.memory.session.Session] 协议的类来实现自己的会话记忆: + +```python +from agents.memory.session import SessionABC +from agents.items import TResponseInputItem +from typing import List + +class MyCustomSession(SessionABC): + """Custom session implementation following the Session protocol.""" + + def __init__(self, session_id: str): + self.session_id = session_id + # Your initialization here + + async def get_items(self, limit: int | None = None) -> List[TResponseInputItem]: + """Retrieve conversation history for this session.""" + # Your implementation here + pass + + async def add_items(self, items: List[TResponseInputItem]) -> None: + """Store new items for this session.""" + # Your implementation here + pass + + async def pop_item(self) -> TResponseInputItem | None: + """Remove and return the most recent item from this session.""" + # Your implementation here + pass + + async def clear_session(self) -> None: + """Clear all items for this session.""" + # Your implementation here + pass + +# Use your custom session +agent = Agent(name="Assistant") +result = await Runner.run( + agent, + "Hello", + session=MyCustomSession("my_session") +) +``` + +## API 参考 + +欲了解详细 API 文档,请参见: + +- [`Session`][agents.memory.session.Session] - 协议接口 +- [`OpenAIConversationsSession`][agents.memory.OpenAIConversationsSession] - OpenAI Conversations API 实现 +- [`SQLiteSession`][agents.memory.sqlite_session.SQLiteSession] - 基础 SQLite 实现 +- [`SQLAlchemySession`][agents.extensions.memory.sqlalchemy_session.SQLAlchemySession] - 基于 SQLAlchemy 的实现 +- [`AdvancedSQLiteSession`][agents.extensions.memory.advanced_sqlite_session.AdvancedSQLiteSession] - 增强的 SQLite,支持分支与分析 +- [`EncryptedSession`][agents.extensions.memory.encrypt_session.EncryptedSession] - 适用于任意会话的加密封装 \ No newline at end of file diff --git a/docs/zh/sessions/sqlalchemy_session.md b/docs/zh/sessions/sqlalchemy_session.md new file mode 100644 index 000000000..e9e50cf48 --- /dev/null +++ b/docs/zh/sessions/sqlalchemy_session.md @@ -0,0 +1,80 @@ +--- +search: + exclude: true +--- +# SQLAlchemy 会话 + +`SQLAlchemySession` 使用 SQLAlchemy 提供可用于生产环境的会话实现,使您可以使用任何 SQLAlchemy 支持的数据库(PostgreSQL、MySQL、SQLite 等)进行会话存储。 + +## 安装 + +SQLAlchemy 会话需要 `sqlalchemy` 扩展: + +```bash +pip install openai-agents[sqlalchemy] +``` + +## 快速开始 + +### 数据库 URL 用法 + +最简单的入门方式: + +```python +import asyncio +from agents import Agent, Runner +from agents.extensions.memory import SQLAlchemySession + +async def main(): + agent = Agent("Assistant") + + # Create session using database URL + session = SQLAlchemySession.from_url( + "user-123", + url="sqlite+aiosqlite:///:memory:", + create_tables=True + ) + + result = await Runner.run(agent, "Hello", session=session) + print(result.final_output) + +if __name__ == "__main__": + asyncio.run(main()) +``` + +### 现有引擎用法 + +适用于已有 SQLAlchemy 引擎的应用: + +```python +import asyncio +from agents import Agent, Runner +from agents.extensions.memory import SQLAlchemySession +from sqlalchemy.ext.asyncio import create_async_engine + +async def main(): + # Create your database engine + engine = create_async_engine("postgresql+asyncpg://user:pass@localhost/db") + + agent = Agent("Assistant") + session = SQLAlchemySession( + "user-456", + engine=engine, + create_tables=True + ) + + result = await Runner.run(agent, "Hello", session=session) + print(result.final_output) + + # Clean up + await engine.dispose() + +if __name__ == "__main__": + asyncio.run(main()) +``` + + +## API 参考 + +- [`SQLAlchemySession`][agents.extensions.memory.sqlalchemy_session.SQLAlchemySession] - 主类 +- [`Session`][agents.memory.session.Session] - 基础会话协议 \ No newline at end of file diff --git a/docs/zh/streaming.md b/docs/zh/streaming.md index 9fc6e7f78..489942451 100644 --- a/docs/zh/streaming.md +++ b/docs/zh/streaming.md @@ -4,15 +4,15 @@ search: --- # 流式传输 -流式传输允许你在智能体运行过程中订阅其更新。这有助于向最终用户展示进度更新和部分响应。 +流式传输允许你在智能体运行过程中订阅其更新。这对于向最终用户展示进度更新和部分响应很有用。 -要进行流式传输,你可以调用 [`Runner.run_streamed()`][agents.run.Runner.run_streamed],它会返回一个 [`RunResultStreaming`][agents.result.RunResultStreaming]。调用 `result.stream_events()` 会得到一个由 [`StreamEvent`][agents.stream_events.StreamEvent] 对象组成的异步流,下面会进行说明。 +要进行流式传输,你可以调用 [`Runner.run_streamed()`][agents.run.Runner.run_streamed],它会返回一个 [`RunResultStreaming`][agents.result.RunResultStreaming]。调用 `result.stream_events()` 会给你一个由 [`StreamEvent`][agents.stream_events.StreamEvent] 对象组成的异步流,具体说明如下。 ## 原始响应事件 -[`RawResponsesStreamEvent`][agents.stream_events.RawResponsesStreamEvent] 是直接从 LLM 传递过来的原始事件。它们采用 OpenAI Responses API 格式,也就是说每个事件都有一个类型(如 `response.created`、`response.output_text.delta` 等)以及数据。如果你希望在生成的同时将响应消息流式传输给用户,这些事件会很有用。 +[`RawResponsesStreamEvent`][agents.stream_events.RawResponsesStreamEvent] 是直接从 LLM 传递的原始事件。它们采用 OpenAI Responses API 格式,这意味着每个事件都有一个类型(例如 `response.created`、`response.output_text.delta` 等)和数据。如果你希望在消息生成时立刻将响应流式传输给用户,这些事件就很有用。 -例如,以下代码将逐个 token 输出由 LLM 生成的文本。 +例如,下面的示例将按 token 逐个输出由 LLM 生成的文本。 ```python import asyncio @@ -37,9 +37,9 @@ if __name__ == "__main__": ## 运行项事件与智能体事件 -[`RunItemStreamEvent`][agents.stream_events.RunItemStreamEvent] 是更高层级的事件。它们会在某个项完全生成后通知你。这样你就可以在“消息已生成”“工具已运行”等层级推送进度更新,而不是按每个 token 推送。类似地,[`AgentUpdatedStreamEvent`][agents.stream_events.AgentUpdatedStreamEvent] 会在当前智能体发生变化时(例如由于一次任务转移)向你提供更新。 +[`RunItemStreamEvent`][agents.stream_events.RunItemStreamEvent] 属于更高层级的事件。它会在某个条目(item)完全生成时通知你。这样你可以在“消息已生成”“工具已运行”等层级推送进度更新,而不是在每个 token 级别。类似地,[`AgentUpdatedStreamEvent`][agents.stream_events.AgentUpdatedStreamEvent] 会在当前智能体发生变化时(例如由于任务转移)给出更新。 -例如,以下代码将忽略原始事件并向用户流式传输更新。 +例如,下面的示例将忽略原始事件,并将更新流式传输给用户。 ```python import asyncio diff --git a/docs/zh/tools.md b/docs/zh/tools.md index 70737cc6d..19e7cf4d2 100644 --- a/docs/zh/tools.md +++ b/docs/zh/tools.md @@ -4,22 +4,22 @@ search: --- # 工具 -工具让智能体能够执行操作:例如获取数据、运行代码、调用外部 API,甚至进行计算机操作。Agents SDK 中有三类工具: +工具让智能体能够执行操作:例如获取数据、运行代码、调用外部 API,甚至进行计算机操作。在 Agent SDK 中,工具分为三类: -- 托管工具:这些在与 AI 模型同一 LLM 服务上运行。OpenAI 提供检索、网络检索和计算机操作等托管工具。 -- 工具调用:这允许你将任意 Python 函数用作工具。 -- 作为工具的智能体:这允许你将智能体作为工具使用,使智能体无需进行任务转移也能调用其他智能体。 +- 托管工具:这些工具在 LLM 服务与 AI 模型同机运行。OpenAI 提供检索、网络检索和计算机操作等托管工具。 +- Function calling:这些工具允许你将任意 Python 函数用作工具。 +- 智能体作为工具:这允许你将智能体作为工具使用,使智能体之间可以相互调用而无需进行任务转移。 ## 托管工具 -使用 [`OpenAIResponsesModel`][agents.models.openai_responses.OpenAIResponsesModel] 时,OpenAI 提供了一些内置工具: +在使用 [`OpenAIResponsesModel`][agents.models.openai_responses.OpenAIResponsesModel] 时,OpenAI 提供一些内置工具: - [`WebSearchTool`][agents.tool.WebSearchTool] 让智能体进行网络检索。 - [`FileSearchTool`][agents.tool.FileSearchTool] 允许从你的 OpenAI 向量存储中检索信息。 - [`ComputerTool`][agents.tool.ComputerTool] 允许自动化计算机操作任务。 -- [`CodeInterpreterTool`][agents.tool.CodeInterpreterTool] 让 LLM 在沙箱环境中执行代码。 +- [`CodeInterpreterTool`][agents.tool.CodeInterpreterTool] 让 LLM 在沙盒环境中执行代码。 - [`HostedMCPTool`][agents.tool.HostedMCPTool] 将远程 MCP 服务的工具暴露给模型。 -- [`ImageGenerationTool`][agents.tool.ImageGenerationTool] 从提示生成图像。 +- [`ImageGenerationTool`][agents.tool.ImageGenerationTool] 根据提示生成图像。 - [`LocalShellTool`][agents.tool.LocalShellTool] 在你的机器上运行 shell 命令。 ```python @@ -41,16 +41,16 @@ async def main(): print(result.final_output) ``` -## 工具调用 +## 函数工具 -你可以将任意 Python 函数用作工具。Agents SDK 会自动设置该工具: +你可以将任意 Python 函数用作工具。Agents SDK 会自动完成工具设置: -- 工具名称将是 Python 函数名(或你可以提供一个名称) -- 工具描述将取自函数的 docstring(或你可以提供描述) -- 函数输入的模式会根据函数参数自动创建 -- 每个输入的描述将从函数的 docstring 获取,除非你禁用它 +- 工具名称将是 Python 函数名(或你可以自定义名称) +- 工具描述将取自函数的 docstring(或你可以自定义描述) +- 函数输入的模式会基于函数参数自动创建 +- 每个输入的描述将取自函数的 docstring,除非被禁用 -我们使用 Python 的 `inspect` 模块提取函数签名,使用 [`griffe`](https://mkdocstrings.github.io/griffe/) 解析 docstring,并使用 `pydantic` 创建模式。 +我们使用 Python 的 `inspect` 模块来提取函数签名,配合 [`griffe`](https://mkdocstrings.github.io/griffe/) 解析 docstring,并用 `pydantic` 创建模式。 ```python import json @@ -102,10 +102,10 @@ for tool in agent.tools: ``` -1. 你可以将任意 Python 类型作为函数参数,函数可以是同步或异步。 -2. 若存在 docstring,将用于提取描述和参数说明。 -3. 函数可选地接收 `context`(必须为第一个参数)。你也可以设置覆盖项,如工具名称、描述、docstring 风格等。 -4. 你可以将装饰后的函数传递到工具列表中。 +1. 你可以使用任意 Python 类型作为函数参数,函数可以是同步或异步。 +2. 如果存在 docstring,会被用于提取工具与参数的描述。 +3. 函数可以选择性地接收 `context`(必须是第一个参数)。你也可以设置覆盖项,如工具名称、描述、docstring 风格等。 +4. 你可以将装饰后的函数传入工具列表。 ??? note "展开以查看输出" @@ -177,14 +177,22 @@ for tool in agent.tools: } ``` +### 从函数工具返回图像或文件 + +除了返回文本输出,你还可以将一个或多个图像或文件作为函数工具的输出。为此,你可以返回以下任意类型: + +- 图像:[`ToolOutputImage`][agents.tool.ToolOutputImage](或其 TypedDict 版本 [`ToolOutputImageDict`][agents.tool.ToolOutputImageDict]) +- 文件:[`ToolOutputFileContent`][agents.tool.ToolOutputFileContent](或其 TypedDict 版本 [`ToolOutputFileContentDict`][agents.tool.ToolOutputFileContentDict]) +- 文本:字符串或可转为字符串的对象,或 [`ToolOutputText`][agents.tool.ToolOutputText](或其 TypedDict 版本 [`ToolOutputTextDict`][agents.tool.ToolOutputTextDict]) + ### 自定义函数工具 -有时你不想把 Python 函数用作工具。如果你愿意,可以直接创建一个 [`FunctionTool`][agents.tool.FunctionTool]。你需要提供: +有时你不想使用 Python 函数作为工具。你可以直接创建一个 [`FunctionTool`][agents.tool.FunctionTool]。你需要提供: - `name` - `description` - `params_json_schema`,即参数的 JSON 模式 -- `on_invoke_tool`,这是一个异步函数,接收 [`ToolContext`][agents.tool_context.ToolContext] 和作为 JSON 字符串的参数,并且必须返回字符串形式的工具输出。 +- `on_invoke_tool`,这是一个异步函数,接收 [`ToolContext`][agents.tool_context.ToolContext] 和 JSON 字符串形式的参数,并且必须返回字符串形式的工具输出。 ```python from typing import Any @@ -217,18 +225,18 @@ tool = FunctionTool( ) ``` -### 自动参数与 docstring 解析 +### 自动解析参数与 docstring -如前所述,我们会自动解析函数签名以提取工具的模式,并解析 docstring 以提取工具及各个参数的描述。注意事项如下: +如前所述,我们会自动解析函数签名以提取工具的模式,并解析 docstring 以提取工具与各参数的描述。注意事项: -1. 使用 `inspect` 模块进行签名解析。我们使用类型注解理解参数类型,并动态构建一个 Pydantic 模型来表示整体模式。它支持大多数类型,包括 Python 基本类型、Pydantic 模型、TypedDict 等。 -2. 我们使用 `griffe` 解析 docstring。支持的 docstring 格式为 `google`、`sphinx` 和 `numpy`。我们会尝试自动检测 docstring 格式,但这是尽力而为,你也可以在调用 `function_tool` 时显式设置。你还可以通过将 `use_docstring_info` 设为 `False` 来禁用 docstring 解析。 +1. 使用 `inspect` 模块进行签名解析。我们利用类型注解来理解参数类型,并动态构建 Pydantic 模型表示整体模式。它支持大多数类型,包括 Python 基本类型、Pydantic 模型、TypedDict 等。 +2. 我们使用 `griffe` 解析 docstring。支持的 docstring 格式包括 `google`、`sphinx` 和 `numpy`。我们会尝试自动检测 docstring 格式,但这只是尽力而为,你也可以在调用 `function_tool` 时显式设置。你也可以通过将 `use_docstring_info` 设为 `False` 来禁用 docstring 解析。 -用于模式提取的代码位于 [`agents.function_schema`][] 中。 +用于模式提取的代码位于 [`agents.function_schema`][]。 -## 作为工具的智能体 +## 智能体作为工具 -在某些工作流中,你可能希望由一个中心智能体来编排一组专门化的智能体,而不是移交控制。你可以通过将智能体建模为工具来实现。 +在某些工作流中,你可能希望由一个中心智能体来编排一组专门化的智能体,而不是进行任务转移。你可以通过将智能体建模为工具来实现。 ```python from agents import Agent, Runner @@ -267,9 +275,9 @@ async def main(): print(result.final_output) ``` -### 自定义工具型智能体 +### 自定义工具化智能体 -`agent.as_tool` 函数是一个便捷方法,便于将智能体转换为工具。它并不支持所有配置;例如,你无法设置 `max_turns`。对于高级用例,请在你的工具实现中直接使用 `Runner.run`: +`agent.as_tool` 函数是一个便捷方法,便于将智能体转换为工具。但它不支持全部配置;例如,你不能设置 `max_turns`。对于高级用例,请在你的工具实现中直接使用 `Runner.run`: ```python @function_tool @@ -290,13 +298,13 @@ async def run_my_agent() -> str: ### 自定义输出提取 -在某些情况下,你可能希望在将工具型智能体的输出返回给中心智能体之前对其进行修改。如果你希望: +在某些情况下,你可能希望在将工具化智能体的输出返回给中心智能体之前对其进行修改。如果你想要: -- 从子智能体的对话历史中提取特定信息(例如 JSON 载荷)。 +- 从子智能体的对话历史中提取某个特定信息(例如 JSON 负载)。 - 转换或重新格式化智能体的最终答案(例如将 Markdown 转为纯文本或 CSV)。 -- 验证输出,或在智能体的响应缺失或格式错误时提供后备值。 +- 验证输出或在智能体的响应缺失或格式错误时提供回退值。 -可以通过向 `as_tool` 方法提供 `custom_output_extractor` 参数来实现: +你可以通过向 `as_tool` 方法提供 `custom_output_extractor` 参数来实现: ```python async def extract_json_payload(run_result: RunResult) -> str: @@ -315,9 +323,9 @@ json_tool = data_agent.as_tool( ) ``` -### 条件启用工具 +### 条件性启用工具 -你可以使用 `is_enabled` 参数在运行时有条件地启用或禁用智能体工具。这样可以根据上下文、用户偏好或运行时条件动态筛选 LLM 可用的工具。 +你可以在运行时使用 `is_enabled` 参数有条件地启用或禁用智能体工具。这允许你基于上下文、用户偏好或运行时条件动态筛选 LLM 可用的工具。 ```python import asyncio @@ -378,20 +386,20 @@ asyncio.run(main()) - **可调用函数**:接收 `(context, agent)` 并返回布尔值的函数 - **异步函数**:用于复杂条件逻辑的异步函数 -被禁用的工具在运行时会对 LLM 完全隐藏,这对以下场景很有用: +被禁用的工具在运行时对 LLM 完全不可见,适用于: - 基于用户权限的功能开关 - 基于环境的工具可用性(开发 vs 生产) - 不同工具配置的 A/B 测试 -- 基于运行时状态的动态工具筛选 +- 基于运行时状态的动态工具过滤 -## 在函数工具中处理错误 +## 处理函数工具中的错误 -当你通过 `@function_tool` 创建函数工具时,你可以传入一个 `failure_error_function`。这是一个在工具调用崩溃时向 LLM 提供错误响应的函数。 +当你通过 `@function_tool` 创建函数工具时,可以传入 `failure_error_function`。此函数会在工具调用崩溃时向 LLM 提供错误响应。 -- 默认情况下(即如果你不传入),它会运行 `default_tool_error_function`,告知 LLM 发生了错误。 -- 如果你传入了自己的错误函数,则会运行该函数,并将其响应发送给 LLM。 -- 如果你显式传入 `None`,则任何工具调用错误都会被重新抛出,供你自行处理。这可能是当模型生成了无效 JSON 时的 `ModelBehaviorError`,或者你的代码崩溃时的 `UserError`,等等。 +- 默认情况下(即你未传入任何内容),会运行 `default_tool_error_function`,告知 LLM 发生了错误。 +- 如果你传入了自定义错误函数,将运行该函数,并把响应发送给 LLM。 +- 如果你显式传入 `None`,则任何工具调用错误都会被重新抛出以供你处理。若模型生成了无效 JSON,可能会是 `ModelBehaviorError`;如果你的代码崩溃,可能会是 `UserError`,等等。 ```python from agents import function_tool, RunContextWrapper @@ -414,4 +422,4 @@ def get_user_profile(user_id: str) -> str: ``` -如果你手动创建一个 `FunctionTool` 对象,那么你必须在 `on_invoke_tool` 函数中处理错误。 \ No newline at end of file +如果你是手动创建 `FunctionTool` 对象,那么你必须在 `on_invoke_tool` 函数内部处理错误。 \ No newline at end of file diff --git a/docs/zh/tracing.md b/docs/zh/tracing.md index c1f68229c..845f51e53 100644 --- a/docs/zh/tracing.md +++ b/docs/zh/tracing.md @@ -4,52 +4,52 @@ search: --- # 追踪 -Agents SDK 内置了追踪功能,会在一次智能体运行过程中收集全面的事件记录:LLM 生成、工具调用、任务转移、安全防护措施,以及发生的自定义事件。使用 [Traces 仪表板](https://platform.openai.com/traces),你可以在开发与生产环境中对工作流进行调试、可视化和监控。 +Agents SDK 内置了追踪功能,会在一次智能体运行期间收集全面的事件记录:LLM 生成、工具调用、任务转移、安全防护措施,以及发生的自定义事件。使用 [Traces 控制台](https://platform.openai.com/traces),你可以在开发和生产环境中调试、可视化并监控你的工作流。 !!!note - 追踪默认启用。禁用追踪有两种方式: + 追踪默认启用。可以通过两种方式禁用追踪: 1. 通过设置环境变量 `OPENAI_AGENTS_DISABLE_TRACING=1` 全局禁用追踪 - 2. 通过将 [`agents.run.RunConfig.tracing_disabled`][] 设为 `True`,为单次运行禁用追踪 + 2. 通过将 [`agents.run.RunConfig.tracing_disabled`][] 设置为 `True`,仅为单次运行禁用追踪 -***对于使用 OpenAI API 且遵循 Zero Data Retention (ZDR) 策略的组织,追踪不可用。*** +***对于在使用 OpenAI API 并执行 Zero Data Retention (ZDR) 政策的组织,追踪不可用。*** ## 追踪与 Span -- **Traces(追踪)** 表示一次“工作流”的端到端操作。它们由多个 Span 组成。Trace 具有以下属性: - - `workflow_name`:逻辑上的工作流或应用。例如 “Code generation” 或 “Customer service”。 - - `trace_id`:该追踪的唯一 ID。如果未传入,会自动生成。必须符合格式 `trace_<32_alphanumeric>`。 - - `group_id`:可选的分组 ID,用于将同一会话中的多个追踪关联起来。例如你可以使用聊天线程 ID。 - - `disabled`:若为 True,则不会记录该追踪。 +- **Traces(追踪)** 表示一次“工作流”的端到端操作。由多个 Span 组成。Trace 具有以下属性: + - `workflow_name`:逻辑工作流或应用。例如 “Code generation” 或 “Customer service”。 + - `trace_id`:追踪的唯一 ID。如果未传入会自动生成。必须符合 `trace_<32_alphanumeric>` 格式。 + - `group_id`:可选的分组 ID,用于关联同一次对话中的多个追踪。例如,可以使用聊天线程 ID。 + - `disabled`:若为 True,该追踪不会被记录。 - `metadata`:追踪的可选元数据。 -- **Spans(Span)** 表示具有开始和结束时间的操作。Span 具有: - - `started_at` 与 `ended_at` 时间戳。 +- **Spans(Span)** 表示具有开始和结束时间的操作。Span 包含: + - `started_at` 和 `ended_at` 时间戳。 - `trace_id`,表示其所属的追踪 - - `parent_id`,指向该 Span 的父 Span(如有) - - `span_data`,关于该 Span 的信息。例如,`AgentSpanData` 包含智能体的信息,`GenerationSpanData` 包含 LLM 生成的信息,等等。 + - `parent_id`,指向该 Span 的父 Span(若存在) + - `span_data`,即关于该 Span 的信息。例如,`AgentSpanData` 包含关于智能体的信息,`GenerationSpanData` 包含关于 LLM 生成的信息,等等。 ## 默认追踪 默认情况下,SDK 会追踪以下内容: -- 整个 `Runner.{run, run_sync, run_streamed}()` 会被 `trace()` 包裹。 -- 每次智能体运行会被 `agent_span()` 包裹 -- LLM 生成会被 `generation_span()` 包裹 -- 每次工具调用会被 `function_span()` 包裹 -- 安全防护措施会被 `guardrail_span()` 包裹 -- 任务转移会被 `handoff_span()` 包裹 -- 音频输入(语音转文本)会被 `transcription_span()` 包裹 -- 音频输出(文本转语音)会被 `speech_span()` 包裹 -- 相关的音频 Span 可能会归于 `speech_group_span()` 之下 +- 整个 `Runner.{run, run_sync, run_streamed}()` 会被包裹在 `trace()` 中。 +- 每次智能体运行都会被包裹在 `agent_span()` 中 +- LLM 生成会被包裹在 `generation_span()` 中 +- 每次 工具调用 都会被包裹在 `function_span()` 中 +- 安全防护措施 会被包裹在 `guardrail_span()` 中 +- 任务转移 会被包裹在 `handoff_span()` 中 +- 音频输入(语音转文本)会被包裹在 `transcription_span()` 中 +- 音频输出(文本转语音)会被包裹在 `speech_span()` 中 +- 相关的音频 Span 可能会归属于一个 `speech_group_span()` 之下 -默认情况下,追踪名称为 “Agent workflow”。如果你使用 `trace`,可以设置该名称;或者你也可以通过 [`RunConfig`][agents.run.RunConfig] 来配置名称和其他属性。 +默认情况下,trace 的名称为 “Agent workflow”。如果你使用 `trace`,可以直接设置该名称;或者你也可以通过 [`RunConfig`][agents.run.RunConfig] 配置名称及其他属性。 -此外,你可以设置[自定义追踪进程](#custom-tracing-processors),将追踪推送到其他目的地(作为替代或次要目的地)。 +此外,你可以设置[自定义追踪处理器](#custom-tracing-processors),将追踪推送到其他目标位置(作为替代或第二目标)。 ## 更高层级的追踪 -有时,你可能希望多次对 `run()` 的调用属于同一个追踪。可以通过将整段代码包裹在 `trace()` 中实现。 +有时,你可能希望多次调用 `run()` 属于同一个追踪。可以通过用 `trace()` 包裹整段代码来实现。 ```python from agents import Agent, Runner, trace @@ -64,46 +64,46 @@ async def main(): print(f"Rating: {second_result.final_output}") ``` -1. 因为两次对 `Runner.run` 的调用都包裹在 `with trace()` 中,这些单独的运行将成为总体追踪的一部分,而不是创建两个追踪。 +1. 因为两次对 `Runner.run` 的调用都被 `with trace()` 包裹,单次运行会成为整体追踪的一部分,而不是创建两个追踪。 ## 创建追踪 -你可以使用 [`trace()`][agents.tracing.trace] 函数来创建追踪。追踪需要被启动并结束。你有两种方式: +你可以使用 [`trace()`][agents.tracing.trace] 函数创建追踪。追踪需要被显式开始与结束。你有两种方式: -1. 推荐:将追踪作为上下文管理器使用,即 `with trace(...) as my_trace`。这会在合适的时间自动开始与结束追踪。 +1. 推荐:将 trace 用作上下文管理器,即 `with trace(...) as my_trace`。这会在合适的时机自动开始和结束追踪。 2. 你也可以手动调用 [`trace.start()`][agents.tracing.Trace.start] 和 [`trace.finish()`][agents.tracing.Trace.finish]。 -当前的追踪通过 Python 的 [`contextvar`](https://docs.python.org/3/library/contextvars.html) 进行跟踪。这意味着它可自动适配并发场景。如果你手动开始/结束追踪,需要在调用 `start()`/`finish()` 时传入 `mark_as_current` 与 `reset_current` 以更新当前追踪。 +当前追踪通过 Python 的 [`contextvar`](https://docs.python.org/3/library/contextvars.html) 进行跟踪。这意味着它能自动适配并发。如果你手动开始/结束追踪,需要在 `start()`/`finish()` 中传入 `mark_as_current` 和 `reset_current` 来更新当前追踪。 ## 创建 Span -你可以使用各种 [`*_span()`][agents.tracing.create] 方法创建 Span。一般情况下,你不需要手动创建 Span。可使用 [`custom_span()`][agents.tracing.custom_span] 来记录自定义 Span 信息。 +你可以使用各种 [`*_span()`][agents.tracing.create] 方法来创建 Span。一般来说,你无需手动创建 Span。提供了一个 [`custom_span()`][agents.tracing.custom_span] 函数用于跟踪自定义 Span 信息。 -Span 会自动归属到当前追踪,并嵌套在最近的当前 Span 之下,该状态通过 Python 的 [`contextvar`](https://docs.python.org/3/library/contextvars.html) 进行跟踪。 +Span 会自动归属于当前追踪,并会嵌套在最近的当前 Span 之下,当前 Span 同样通过 Python 的 [`contextvar`](https://docs.python.org/3/library/contextvars.html) 进行跟踪。 ## 敏感数据 某些 Span 可能会捕获潜在的敏感数据。 -`generation_span()` 会存储 LLM 生成的输入/输出,`function_span()` 会存储工具调用的输入/输出。这些可能包含敏感数据,因此你可以通过 [`RunConfig.trace_include_sensitive_data`][agents.run.RunConfig.trace_include_sensitive_data] 禁用这些数据的捕获。 +`generation_span()` 会存储 LLM 生成的输入/输出,而 `function_span()` 会存储函数调用的输入/输出。这些可能包含敏感数据,因此你可以通过 [`RunConfig.trace_include_sensitive_data`][agents.run.RunConfig.trace_include_sensitive_data] 来禁用此类数据的捕获。 -类似地,音频相关的 Span 默认会包含输入与输出音频的 base64 编码 PCM 数据。你可以通过配置 [`VoicePipelineConfig.trace_include_sensitive_audio_data`][agents.voice.pipeline_config.VoicePipelineConfig.trace_include_sensitive_audio_data] 禁用这些音频数据的捕获。 +类似地,音频相关的 Span 默认会包含输入与输出音频的 base64 编码 PCM 数据。你可以通过配置 [`VoicePipelineConfig.trace_include_sensitive_audio_data`][agents.voice.pipeline_config.VoicePipelineConfig.trace_include_sensitive_audio_data] 来禁用音频数据的捕获。 -## 自定义追踪进程 +## 自定义追踪处理器 追踪的高层架构如下: -- 在初始化时,我们会创建一个全局的 [`TraceProvider`][agents.tracing.setup.TraceProvider],负责创建追踪。 -- 我们为 `TraceProvider` 配置一个 [`BatchTraceProcessor`][agents.tracing.processors.BatchTraceProcessor],它会将追踪/Span 批量发送到 [`BackendSpanExporter`][agents.tracing.processors.BackendSpanExporter],由其将 Span 与追踪批量导出到 OpenAI 后端。 +- 初始化时,我们会创建一个全局的 [`TraceProvider`][agents.tracing.setup.TraceProvider],负责创建追踪。 +- 我们为 `TraceProvider` 配置一个 [`BatchTraceProcessor`][agents.tracing.processors.BatchTraceProcessor],它会将追踪/Span 批量发送给 [`BackendSpanExporter`][agents.tracing.processors.BackendSpanExporter],后者将这些 Span 与追踪批量导出到 OpenAI 后端。 -若要自定义这一默认设置,以便将追踪发送到其他或附加的后端,或修改导出器行为,你有两种选择: +要自定义此默认设置,以便将追踪发送到替代或附加后端,或修改导出器行为,你有两种选择: -1. [`add_trace_processor()`][agents.tracing.add_trace_processor] 允许添加一个额外的追踪进程,它将在追踪与 Span 就绪时接收它们。这使你可以在将追踪发送到 OpenAI 后端之外,执行你自己的处理。 -2. [`set_trace_processors()`][agents.tracing.set_trace_processors] 允许用你自己的追踪进程替换默认进程。这意味着除非你包含一个执行该功能的 `TracingProcessor`,否则追踪将不会发送到 OpenAI 后端。 +1. [`add_trace_processor()`][agents.tracing.add_trace_processor] 允许你添加一个额外的追踪处理器,用于在追踪与 Span 就绪时接收它们。这样你可以在将追踪发送到 OpenAI 后端之外,执行你自己的处理。 +2. [`set_trace_processors()`][agents.tracing.set_trace_processors] 允许你用你自己的追踪处理器替换默认处理器。这意味着除非你包含一个会向 OpenAI 后端发送数据的 `TracingProcessor`,否则追踪将不会被发送到 OpenAI 后端。 -## 与非 OpenAI 模型的追踪 +## 在非 OpenAI 模型上的追踪 -你可以将 OpenAI API key 用于非 OpenAI 模型,在无需禁用追踪的情况下,在 OpenAI Traces 仪表板中启用免费的追踪。 +你可以在非 OpenAI 模型中使用 OpenAI API key,在无需禁用追踪的情况下,在 OpenAI Traces 控制台启用免费的追踪。 ```python import os @@ -125,9 +125,9 @@ agent = Agent( ``` ## 说明 -- 在 OpenAI Traces 仪表板查看免费追踪。 +- 在 Openai Traces 控制台查看免费追踪。 -## 外部追踪进程列表 +## 外部追踪处理器列表 - [Weights & Biases](https://weave-docs.wandb.ai/guides/integrations/openai_agents) - [Arize-Phoenix](https://docs.arize.com/phoenix/tracing/integrations-tracing/openai-agents-sdk) diff --git a/docs/zh/usage.md b/docs/zh/usage.md index 5f80c0ce0..ef1778324 100644 --- a/docs/zh/usage.md +++ b/docs/zh/usage.md @@ -4,19 +4,19 @@ search: --- # 用量 -Agents SDK 会自动跟踪每次运行的 token 用量。你可以从运行上下文中访问它,以用于监控成本、强制执行限制或记录分析数据。 +Agents SDK 会自动为每次运行追踪令牌用量。你可以从运行上下文中访问它,用于监控成本、实施限制或记录分析数据。 -## 跟踪内容 +## 追踪内容 - **requests**: 发起的 LLM API 调用次数 -- **input_tokens**: 发送的输入 token 总数 -- **output_tokens**: 接收的输出 token 总数 +- **input_tokens**: 发送的输入令牌总数 +- **output_tokens**: 接收的输出令牌总数 - **total_tokens**: 输入 + 输出 - **details**: - `input_tokens_details.cached_tokens` - `output_tokens_details.reasoning_tokens` -## 从一次运行访问用量 +## 从运行访问用量 在执行 `Runner.run(...)` 之后,通过 `result.context_wrapper.usage` 访问用量。 @@ -30,7 +30,7 @@ print("Output tokens:", usage.output_tokens) print("Total tokens:", usage.total_tokens) ``` -用量会聚合该次运行期间所有的模型调用(包括工具调用和任务转移)。 +用量会在该次运行期间的所有模型调用中聚合(包括工具调用和任务转移)。 ### 在 LiteLLM 模型中启用用量 @@ -52,7 +52,7 @@ print(result.context_wrapper.usage.total_tokens) ## 在会话中访问用量 -当你使用 `Session`(例如 `SQLiteSession`)时,每次调用 `Runner.run(...)` 都会返回该次运行的用量。会话会为上下文维护对话历史,但每次运行的用量彼此独立。 +当你使用 `Session`(例如,`SQLiteSession`)时,每次调用 `Runner.run(...)` 都会返回该次运行的用量。会话会为上下文维护对话历史,但每次运行的用量彼此独立。 ```python session = SQLiteSession("my_conversation") @@ -64,7 +64,7 @@ second = await Runner.run(agent, "Can you elaborate?", session=session) print(second.context_wrapper.usage.total_tokens) # Usage for second run ``` -请注意,虽然会话会在运行之间保留对话上下文,但每次 `Runner.run()` 调用返回的用量指标仅代表那一次的执行。在会话中,之前的消息可能会作为输入重新提供给每次运行,这会影响后续轮次的输入 token 计数。 +请注意,虽然会话会在运行之间保留对话上下文,但每次 `Runner.run()` 调用返回的用量仅代表该次执行。在会话中,先前消息可能会在每次运行时重新作为输入提供,这会影响后续轮次的输入令牌计数。 ## 在钩子中使用用量 @@ -79,8 +79,8 @@ class MyHooks(RunHooks): ## API 参考 -有关详细的 API 文档,请参见: +详见 API 文档: -- [`Usage`][agents.usage.Usage] - 用量跟踪数据结构 +- [`Usage`][agents.usage.Usage] - 用量追踪数据结构 - [`RunContextWrapper`][agents.run.RunContextWrapper] - 从运行上下文访问用量 -- [`RunHooks`][agents.run.RunHooks] - 接入用量跟踪生命周期 \ No newline at end of file +- [`RunHooks`][agents.run.RunHooks] - 挂钩用量追踪生命周期 \ No newline at end of file diff --git a/docs/zh/visualization.md b/docs/zh/visualization.md index 71953d427..8675d4acb 100644 --- a/docs/zh/visualization.md +++ b/docs/zh/visualization.md @@ -4,7 +4,7 @@ search: --- # 智能体可视化 -智能体可视化允许你使用 **Graphviz** 生成智能体及其关系的结构化图形表示。这有助于理解在应用中智能体、工具和任务转移如何交互。 +智能体可视化允许你使用 **Graphviz** 生成智能体及其关系的结构化图形表示。这有助于理解智能体、工具和任务转移在应用中的交互方式。 ## 安装 @@ -14,16 +14,16 @@ search: pip install "openai-agents[viz]" ``` -## 生成图形 +## 生成图 你可以使用 `draw_graph` 函数生成智能体可视化。该函数会创建一个有向图,其中: -- **Agents(智能体)** 显示为黄色方框。 -- **MCP Servers** 显示为灰色方框。 -- **Tools(工具)** 显示为绿色椭圆。 -- **Handoffs(任务转移)** 为从一个智能体指向另一个智能体的有向边。 +- **智能体** 用黄色方框表示。 +- **MCP 服务** 用灰色方框表示。 +- **工具** 用绿色椭圆表示。 +- **任务转移** 用从一个智能体指向另一个智能体的有向边表示。 -### 使用示例 +### 示例用法 ```python import os @@ -69,38 +69,39 @@ draw_graph(triage_agent) ![Agent Graph](../assets/images/graph.png) -这会生成一个图,直观展示了**分诊智能体(triage agent)**的结构,以及它与子智能体和工具的连接关系。 +这会生成一个图,直观展示了**分诊智能体**的结构及其与子智能体和工具的连接。 -## 可视化解析 -生成的图包含: +## 可视化说明 -- 一个表示入口的**起始节点**(`__start__`)。 +生成的图包括: + +- 一个表示入口点的**起始节点**(`__start__`)。 - 用**矩形**且填充黄色表示的智能体。 - 用**椭圆**且填充绿色表示的工具。 -- 用**矩形**且填充灰色表示的 MCP Servers。 +- 用**矩形**且填充灰色表示的 MCP 服务。 - 表示交互的有向边: - - **实线箭头**:智能体到智能体的任务转移。 - - **点线箭头**:工具调用。 - - **虚线箭头**:MCP Server 调用。 + - **实线箭头** 表示智能体到智能体的任务转移。 + - **虚线点状箭头** 表示工具调用。 + - **虚线箭头** 表示 MCP 服务调用。 - 一个表示执行终止位置的**结束节点**(`__end__`)。 -**注意:**MCP servers 会在 `agents` 包的较新版本中渲染(已在 **v0.2.8** 验证)。如果在你的可视化中看不到 MCP 方框,请升级到最新版本。 +**注意:**MCP 服务在近期版本的 `agents` 包中已被渲染(在 **v0.2.8** 中验证)。如果你在可视化中未看到 MCP 方框,请升级到最新版本。 ## 图形自定义 ### 显示图形 -默认情况下,`draw_graph` 会内联显示图形。要在单独的窗口中显示,请编写: +默认情况下,`draw_graph` 会内联显示图形。若要在单独窗口中显示图形,请编写如下代码: ```python draw_graph(triage_agent).view() ``` ### 保存图形 -默认情况下,`draw_graph` 会内联显示图形。要将其保存为文件,请指定文件名: +默认情况下,`draw_graph` 会内联显示图形。若要将其保存为文件,请指定文件名: ```python draw_graph(triage_agent, filename="agent_graph") ``` -这将在工作目录中生成 `agent_graph.png`。 \ No newline at end of file +这将在工作目录下生成 `agent_graph.png`。 \ No newline at end of file diff --git a/docs/zh/voice/pipeline.md b/docs/zh/voice/pipeline.md index d579b11a4..9714673eb 100644 --- a/docs/zh/voice/pipeline.md +++ b/docs/zh/voice/pipeline.md @@ -2,9 +2,9 @@ search: exclude: true --- -# 流水线和工作流 +# 流水线与工作流 -[`VoicePipeline`][agents.voice.pipeline.VoicePipeline] 是一个类,可轻松将你的智能体工作流变成语音应用。你传入要运行的工作流,流水线会负责转写输入音频、检测音频结束的时机、在合适的时间调用你的工作流,并将工作流的输出转换回音频。 +[`VoicePipeline`][agents.voice.pipeline.VoicePipeline] 是一个类,可轻松将你的智能体工作流变成语音应用。你传入要运行的工作流,流水线会负责转录输入音频、检测音频结束时间、在合适的时机调用你的工作流,并将工作流输出再转换为音频。 ```mermaid graph LR @@ -36,27 +36,27 @@ graph LR 创建流水线时,你可以设置以下内容: -1. [`workflow`][agents.voice.workflow.VoiceWorkflowBase],即每次有新音频被转写时运行的代码。 -2. 使用的 [`speech-to-text`][agents.voice.model.STTModel] 和 [`text-to-speech`][agents.voice.model.TTSModel] 模型 -3. [`config`][agents.voice.pipeline_config.VoicePipelineConfig],用于配置如下内容: +1. [`workflow`][agents.voice.workflow.VoiceWorkflowBase]:每次有新音频被转录时运行的代码。 +2. 使用的 [`speech-to-text`][agents.voice.model.STTModel] 和 [`text-to-speech`][agents.voice.model.TTSModel] 模型。 +3. [`config`][agents.voice.pipeline_config.VoicePipelineConfig]:用于配置如下内容: - 模型提供方,可将模型名称映射到具体模型 - 追踪,包括是否禁用追踪、是否上传音频文件、工作流名称、追踪 ID 等 - - TTS 和 STT 模型的设置,如提示词、语言和使用的数据类型 + - TTS 与 STT 模型的设置,如提示词、语言和所用数据类型 ## 运行流水线 -可以通过 [`run()`][agents.voice.pipeline.VoicePipeline.run] 方法运行流水线,它允许你以两种形式传入音频输入: +你可以通过 [`run()`][agents.voice.pipeline.VoicePipeline.run] 方法运行流水线,并以两种形式传入音频输入: -1. [`AudioInput`][agents.voice.input.AudioInput] 适用于你已有完整音频转写、只需为其生成结果的场景。这在无需检测说话者何时结束的情况下很有用,例如已有预录音频,或在按键说话(push-to-talk)应用中能明确知道用户何时说完。 -2. [`StreamedAudioInput`][agents.voice.input.StreamedAudioInput] 适用于需要检测用户何时说完的场景。它允许你在检测到时不断推送音频片段,语音流水线会通过称为“activity detection(活动检测)”的过程,在合适的时机自动运行智能体工作流。 +1. 当你已有完整音频并只想基于它产出结果时,使用 [`AudioInput`][agents.voice.input.AudioInput]。这适用于无需检测说话人何时说完的场景;例如,已录制的音频,或在按键说话应用中用户结束说话的时机是明确的。 +2. 当你可能需要检测用户何时说完时,使用 [`StreamedAudioInput`][agents.voice.input.StreamedAudioInput]。它允许你在检测到音频片段时逐步推送,语音流水线会通过“活动检测”自动在正确的时机运行智能体工作流。 ## 结果 -一次语音流水线运行的结果是 [`StreamedAudioResult`][agents.voice.result.StreamedAudioResult]。这是一个对象,可让你在事件发生时进行流式消费。存在几种 [`VoiceStreamEvent`][agents.voice.events.VoiceStreamEvent],包括: +语音流水线运行的结果是一个 [`StreamedAudioResult`][agents.voice.result.StreamedAudioResult]。这是一个可让你在事件发生时进行流式接收的对象。[`VoiceStreamEvent`][agents.voice.events.VoiceStreamEvent] 的类型包括: -1. [`VoiceStreamEventAudio`][agents.voice.events.VoiceStreamEventAudio],包含一段音频片段。 -2. [`VoiceStreamEventLifecycle`][agents.voice.events.VoiceStreamEventLifecycle],告知你生命周期事件,如一次轮次的开始或结束。 -3. [`VoiceStreamEventError`][agents.voice.events.VoiceStreamEventError],错误事件。 +1. [`VoiceStreamEventAudio`][agents.voice.events.VoiceStreamEventAudio],包含一段音频数据。 +2. [`VoiceStreamEventLifecycle`][agents.voice.events.VoiceStreamEventLifecycle],告知诸如轮次开始或结束等生命周期事件。 +3. [`VoiceStreamEventError`][agents.voice.events.VoiceStreamEventError],表示错误事件。 ```python @@ -76,4 +76,4 @@ async for event in result.stream(): ### 中断 -Agents SDK 目前不对 [`StreamedAudioInput`][agents.voice.input.StreamedAudioInput] 提供任何内置的中断支持。相反,对于每个检测到的轮次,它都会单独触发一次你的工作流运行。如果你想在应用中处理中断,可以监听 [`VoiceStreamEventLifecycle`][agents.voice.events.VoiceStreamEventLifecycle] 事件。`turn_started` 表示新的轮次已被转写且处理开始;`turn_ended` 会在相应轮次的全部音频分发完成后触发。你可以利用这些事件在模型开始一个轮次时静音说话者的麦克风,并在你将该轮次的相关音频全部发送完毕后取消静音。 \ No newline at end of file +Agents SDK 目前未对 [`StreamedAudioInput`][agents.voice.input.StreamedAudioInput] 提供任何内置的中断支持。相反,对于检测到的每个轮次,它都会单独触发你的工作流运行。如果你希望在应用内处理中断,可以监听 [`VoiceStreamEventLifecycle`][agents.voice.events.VoiceStreamEventLifecycle] 事件。`turn_started` 表示新的一轮已被转录且处理开始;`turn_ended` 会在对应轮次的所有音频发送完成后触发。你可以利用这些事件在模型开启一轮时静音说话者的麦克风,并在你将该轮相关音频全部发送完毕后再取消静音。 \ No newline at end of file diff --git a/docs/zh/voice/quickstart.md b/docs/zh/voice/quickstart.md index 77c78b3d9..49777a0e9 100644 --- a/docs/zh/voice/quickstart.md +++ b/docs/zh/voice/quickstart.md @@ -6,7 +6,7 @@ search: ## 先决条件 -请确保你已经按照 Agents SDK 的基础[快速开始说明](../quickstart.md)完成设置,并创建了一个虚拟环境。然后,从 SDK 安装可选的语音依赖: +请确保你已按照 Agents SDK 的基础[快速开始指南](../quickstart.md)进行操作,并已设置虚拟环境。然后,从 SDK 安装可选的语音依赖项: ```bash pip install 'openai-agents[voice]' @@ -17,7 +17,7 @@ pip install 'openai-agents[voice]' 需要了解的主要概念是一个[`VoicePipeline`][agents.voice.pipeline.VoicePipeline],它是一个包含 3 个步骤的流程: 1. 运行语音转文本模型,将音频转换为文本。 -2. 运行你的代码(通常是一个智能体工作流)以生成结果。 +2. 运行你的代码(通常是一个智能体工作流)来产生结果。 3. 运行文本转语音模型,将结果文本转换回音频。 ```mermaid @@ -48,7 +48,7 @@ graph LR ## 智能体 -首先,我们来设置一些智能体。如果你已经用这个 SDK 构建过任何智能体,这应该会让你感到熟悉。我们将创建几个智能体、一个任务转移,以及一个工具。 +首先,我们来设置一些智能体。如果你使用此 SDK 构建过智能体,这应当很熟悉。我们将有几个智能体、一个任务转移,以及一个工具。 ```python import asyncio @@ -124,7 +124,7 @@ async for event in result.stream(): ``` -## 整合 +## 整合到一起 ```python import asyncio @@ -195,4 +195,4 @@ if __name__ == "__main__": asyncio.run(main()) ``` -如果你运行这个示例,智能体会和你对话!查看[examples/voice/static](https://github.com/openai/openai-agents-python/tree/main/examples/voice/static)中的示例,了解一个你可以亲自与智能体对话的演示。 \ No newline at end of file +如果你运行此示例,智能体会对你说话!查看[examples/voice/static](https://github.com/openai/openai-agents-python/tree/main/examples/voice/static)中的示例,观看你可以亲自与智能体对话的演示。 \ No newline at end of file diff --git a/docs/zh/voice/tracing.md b/docs/zh/voice/tracing.md index 1cf563a5f..0d94d2800 100644 --- a/docs/zh/voice/tracing.md +++ b/docs/zh/voice/tracing.md @@ -6,13 +6,13 @@ search: 与[智能体的追踪方式](../tracing.md)相同,语音流水线也会被自动追踪。 -你可以阅读上述追踪文档以获取基础信息,此外还可以通过[`VoicePipelineConfig`][agents.voice.pipeline_config.VoicePipelineConfig]对流水线的追踪进行配置。 +你可以参考上面的追踪文档了解基础信息,此外还可以通过[`VoicePipelineConfig`][agents.voice.pipeline_config.VoicePipelineConfig]对流水线的追踪进行配置。 与追踪相关的关键字段包括: -- [`tracing_disabled`][agents.voice.pipeline_config.VoicePipelineConfig.tracing_disabled]: 控制是否禁用追踪。默认启用追踪。 -- [`trace_include_sensitive_data`][agents.voice.pipeline_config.VoicePipelineConfig.trace_include_sensitive_data]: 控制追踪是否包含可能敏感的数据,如音频转写。此设置仅针对语音流水线,不适用于你的工作流内部发生的任何内容。 -- [`trace_include_sensitive_audio_data`][agents.voice.pipeline_config.VoicePipelineConfig.trace_include_sensitive_audio_data]: 控制追踪是否包含音频数据。 -- [`workflow_name`][agents.voice.pipeline_config.VoicePipelineConfig.workflow_name]: 追踪工作流的名称。 -- [`group_id`][agents.voice.pipeline_config.VoicePipelineConfig.group_id]: 追踪的`group_id`,用于关联多个追踪。 -- [`trace_metadata`][agents.voice.pipeline_config.VoicePipelineConfig.tracing_disabled]: 要随追踪一同包含的额外元数据。 \ No newline at end of file +- [`tracing_disabled`][agents.voice.pipeline_config.VoicePipelineConfig.tracing_disabled]:控制是否禁用追踪。默认启用追踪。 +- [`trace_include_sensitive_data`][agents.voice.pipeline_config.VoicePipelineConfig.trace_include_sensitive_data]:控制追踪中是否包含可能敏感的数据,例如音频转写。此设置仅适用于语音流水线,不影响你的工作流内部的内容。 +- [`trace_include_sensitive_audio_data`][agents.voice.pipeline_config.VoicePipelineConfig.trace_include_sensitive_audio_data]:控制追踪中是否包含音频数据。 +- [`workflow_name`][agents.voice.pipeline_config.VoicePipelineConfig.workflow_name]:追踪工作流的名称。 +- [`group_id`][agents.voice.pipeline_config.VoicePipelineConfig.group_id]:追踪的`group_id`,用于关联多个追踪。 +- [`trace_metadata`][agents.voice.pipeline_config.VoicePipelineConfig.tracing_disabled]:要随追踪一同包含的其他元数据。 \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index 6dae53417..63f03d463 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -57,7 +57,11 @@ plugins: - Documentation: - agents.md - running_agents.md - - sessions.md + - Sessions: + - sessions/index.md + - sessions/sqlalchemy_session.md + - sessions/advanced_sqlite_session.md + - sessions/encrypted_session.md - results.md - streaming.md - repl.md @@ -146,7 +150,7 @@ plugins: - ref/extensions/litellm.md - ref/extensions/memory/sqlalchemy_session.md - ref/extensions/memory/encrypt_session.md - + - ref/extensions/memory/advanced_sqlite_session.md - locale: ja name: 日本語 build: true @@ -157,7 +161,11 @@ plugins: - ドキュメント: - agents.md - running_agents.md - - sessions.md + - セッション: + - sessions/index.md + - sessions/sqlalchemy_session.md + - sessions/advanced_sqlite_session.md + - sessions/encrypted_session.md - results.md - streaming.md - repl.md @@ -192,7 +200,11 @@ plugins: - 문서: - agents.md - running_agents.md - - sessions.md + - 세션: + - sessions/index.md + - sessions/sqlalchemy_session.md + - sessions/advanced_sqlite_session.md + - sessions/encrypted_session.md - results.md - streaming.md - repl.md @@ -227,7 +239,11 @@ plugins: - 文档: - agents.md - running_agents.md - - sessions.md + - 会话: + - sessions/index.md + - sessions/sqlalchemy_session.md + - sessions/advanced_sqlite_session.md + - sessions/encrypted_session.md - results.md - streaming.md - repl.md diff --git a/src/agents/result.py b/src/agents/result.py index a76a98b29..3fe20cfa5 100644 --- a/src/agents/result.py +++ b/src/agents/result.py @@ -4,7 +4,7 @@ import asyncio from collections.abc import AsyncIterator from dataclasses import dataclass, field -from typing import TYPE_CHECKING, Any, cast +from typing import TYPE_CHECKING, Any, Literal, cast from typing_extensions import TypeVar @@ -164,6 +164,9 @@ class RunResultStreaming(RunResultBase): _output_guardrails_task: asyncio.Task[Any] | None = field(default=None, repr=False) _stored_exception: Exception | None = field(default=None, repr=False) + # Soft cancel state + _cancel_mode: Literal["none", "immediate", "after_turn"] = field(default="none", repr=False) + @property def last_agent(self) -> Agent[Any]: """The last agent that was run. Updates as the agent run progresses, so the true last agent @@ -171,17 +174,51 @@ def last_agent(self) -> Agent[Any]: """ return self.current_agent - def cancel(self) -> None: - """Cancels the streaming run, stopping all background tasks and marking the run as - complete.""" - self._cleanup_tasks() # Cancel all running tasks - self.is_complete = True # Mark the run as complete to stop event streaming + def cancel(self, mode: Literal["immediate", "after_turn"] = "immediate") -> None: + """Cancel the streaming run. - # Optionally, clear the event queue to prevent processing stale events - while not self._event_queue.empty(): - self._event_queue.get_nowait() - while not self._input_guardrail_queue.empty(): - self._input_guardrail_queue.get_nowait() + Args: + mode: Cancellation strategy: + - "immediate": Stop immediately, cancel all tasks, clear queues (default) + - "after_turn": Complete current turn gracefully before stopping + * Allows LLM response to finish + * Executes pending tool calls + * Saves session state properly + * Tracks usage accurately + * Stops before next turn begins + + Example: + ```python + result = Runner.run_streamed(agent, "Task", session=session) + + async for event in result.stream_events(): + if user_interrupted(): + result.cancel(mode="after_turn") # Graceful + # result.cancel() # Immediate (default) + ``` + + Note: After calling cancel(), you should continue consuming stream_events() + to allow the cancellation to complete properly. + """ + # Store the cancel mode for the background task to check + self._cancel_mode = mode + + if mode == "immediate": + # Existing behavior - immediate shutdown + self._cleanup_tasks() # Cancel all running tasks + self.is_complete = True # Mark the run as complete to stop event streaming + + # Optionally, clear the event queue to prevent processing stale events + while not self._event_queue.empty(): + self._event_queue.get_nowait() + while not self._input_guardrail_queue.empty(): + self._input_guardrail_queue.get_nowait() + + elif mode == "after_turn": + # Soft cancel - just set the flag + # The streaming loop will check this and stop gracefully + # Don't call _cleanup_tasks() or clear queues yet + pass async def stream_events(self) -> AsyncIterator[StreamEvent]: """Stream deltas for new items as they are generated. We're using the types from the diff --git a/src/agents/run.py b/src/agents/run.py index e91279ad6..85607e7dd 100644 --- a/src/agents/run.py +++ b/src/agents/run.py @@ -951,6 +951,12 @@ async def _start_streaming( await AgentRunner._save_result_to_session(session, starting_input, []) while True: + # Check for soft cancel before starting new turn + if streamed_result._cancel_mode == "after_turn": + streamed_result.is_complete = True + streamed_result._event_queue.put_nowait(QueueCompleteSentinel()) + break + if streamed_result.is_complete: break @@ -1026,6 +1032,20 @@ async def _start_streaming( server_conversation_tracker.track_server_items(turn_result.model_response) if isinstance(turn_result.next_step, NextStepHandoff): + # Save the conversation to session if enabled (before handoff) + # Note: Non-streaming path doesn't save handoff turns immediately, + # but streaming needs to for graceful cancellation support + if session is not None: + should_skip_session_save = ( + await AgentRunner._input_guardrail_tripwire_triggered_for_stream( + streamed_result + ) + ) + if should_skip_session_save is False: + await AgentRunner._save_result_to_session( + session, [], turn_result.new_step_items + ) + current_agent = turn_result.next_step.new_agent current_span.finish(reset_current=True) current_span = None @@ -1033,6 +1053,12 @@ async def _start_streaming( streamed_result._event_queue.put_nowait( AgentUpdatedStreamEvent(new_agent=current_agent) ) + + # Check for soft cancel after handoff + if streamed_result._cancel_mode == "after_turn": # type: ignore[comparison-overlap] + streamed_result.is_complete = True + streamed_result._event_queue.put_nowait(QueueCompleteSentinel()) + break elif isinstance(turn_result.next_step, NextStepFinalOutput): streamed_result._output_guardrails_task = asyncio.create_task( cls._run_output_guardrails( @@ -1078,6 +1104,12 @@ async def _start_streaming( await AgentRunner._save_result_to_session( session, [], turn_result.new_step_items ) + + # Check for soft cancel after turn completion + if streamed_result._cancel_mode == "after_turn": # type: ignore[comparison-overlap] + streamed_result.is_complete = True + streamed_result._event_queue.put_nowait(QueueCompleteSentinel()) + break except AgentsException as exc: streamed_result.is_complete = True streamed_result._event_queue.put_nowait(QueueCompleteSentinel()) diff --git a/tests/test_cancel_streaming.py b/tests/test_cancel_streaming.py index 3417a3c5d..ddf603f9f 100644 --- a/tests/test_cancel_streaming.py +++ b/tests/test_cancel_streaming.py @@ -114,3 +114,20 @@ async def test_cancel_cleans_up_resources(): assert result._input_guardrail_queue.empty(), ( "Input guardrail queue should be empty after cancel." ) + + +@pytest.mark.asyncio +async def test_cancel_immediate_mode_explicit(): + """Test explicit immediate mode behaves same as default.""" + model = FakeModel() + agent = Agent(name="Joker", model=model) + + result = Runner.run_streamed(agent, input="Please tell me 5 jokes.") + + async for _ in result.stream_events(): + result.cancel(mode="immediate") + break + + assert result.is_complete + assert result._event_queue.empty() + assert result._cancel_mode == "immediate" diff --git a/tests/test_soft_cancel.py b/tests/test_soft_cancel.py new file mode 100644 index 000000000..395f2fb6f --- /dev/null +++ b/tests/test_soft_cancel.py @@ -0,0 +1,478 @@ +"""Tests for soft cancel (after_turn mode) functionality.""" + +import json + +import pytest + +from agents import Agent, Runner, SQLiteSession + +from .fake_model import FakeModel +from .test_responses import get_function_tool, get_function_tool_call, get_text_message + + +@pytest.mark.asyncio +async def test_soft_cancel_completes_turn(): + """Verify soft cancel waits for turn to complete.""" + model = FakeModel() + agent = Agent(name="Assistant", model=model) + + result = Runner.run_streamed(agent, input="Hello") + + # Cancel immediately after first event + event_count = 0 + async for _ in result.stream_events(): + event_count += 1 + if event_count == 1: + result.cancel(mode="after_turn") + + # Should get more than 1 event (turn completes) + assert event_count > 1, "Soft cancel should allow turn to complete" + assert result.is_complete + + +@pytest.mark.asyncio +async def test_soft_cancel_vs_immediate(): + """Compare soft cancel vs immediate cancel behavior.""" + # Immediate cancel + model1 = FakeModel() + agent1 = Agent(name="A1", model=model1) + result1 = Runner.run_streamed(agent1, input="Hello") + immediate_events = [] + async for event in result1.stream_events(): + immediate_events.append(event) + if len(immediate_events) == 1: + result1.cancel(mode="immediate") + + # Soft cancel + model2 = FakeModel() + agent2 = Agent(name="A2", model=model2) + result2 = Runner.run_streamed(agent2, input="Hello") + soft_events = [] + async for event in result2.stream_events(): + soft_events.append(event) + if len(soft_events) == 1: + result2.cancel(mode="after_turn") + + # Soft cancel should get more events + assert len(soft_events) > len(immediate_events), ( + f"Soft cancel should get more events: soft={len(soft_events)}, immediate={len(immediate_events)}" # noqa: E501 + ) + + +@pytest.mark.asyncio +async def test_soft_cancel_with_tool_calls(): + """Verify tool calls execute before soft cancel stops.""" + model = FakeModel() + agent = Agent( + name="Assistant", + model=model, + tools=[get_function_tool("calc", "42")], + ) + + model.add_multiple_turn_outputs( + [ + [ + get_text_message("Let me calculate"), + get_function_tool_call("calc", json.dumps({})), + ], + [get_text_message("Result is 42")], + ] + ) + + result = Runner.run_streamed(agent, input="Calculate") + + tool_call_seen = False + tool_output_seen = False + async for event in result.stream_events(): + if event.type == "run_item_stream_event": + if event.name == "tool_called": + tool_call_seen = True + # Cancel right after seeing tool call + result.cancel(mode="after_turn") + elif event.name == "tool_output": + tool_output_seen = True + + assert tool_call_seen, "Tool call should be seen" + assert tool_output_seen, "Tool output should be seen (tool should execute before soft cancel)" + + +@pytest.mark.asyncio +async def test_soft_cancel_saves_session(): + """Verify session is saved properly with soft cancel.""" + model = FakeModel() + agent = Agent(name="Assistant", model=model) + + session = SQLiteSession("test_soft_cancel_session") + await session.clear_session() # Start fresh + + result = Runner.run_streamed(agent, input="Hello", session=session) + + async for event in result.stream_events(): + if event.type == "run_item_stream_event": + result.cancel(mode="after_turn") + + # Check session has the turn + items = await session.get_items() + assert len(items) > 0, "Session should have saved items from completed turn" + + # Verify we can resume + result2 = await Runner.run(agent, "Continue", session=session) + assert result2.final_output is not None + + # Cleanup + await session.clear_session() + + +@pytest.mark.asyncio +async def test_soft_cancel_tracks_usage(): + """Verify usage is tracked for completed turn.""" + model = FakeModel() + agent = Agent(name="Assistant", model=model) + + result = Runner.run_streamed(agent, input="Hello") + + async for event in result.stream_events(): + if event.type == "raw_response_event": + result.cancel(mode="after_turn") + + # Usage should be tracked (FakeModel tracks requests even if tokens are 0) + assert result.context_wrapper.usage.requests > 0 + + +@pytest.mark.asyncio +async def test_soft_cancel_stops_next_turn(): + """Verify soft cancel prevents next turn from starting.""" + model = FakeModel() + agent = Agent( + name="Assistant", + model=model, + tools=[get_function_tool("tool1", "result1")], + ) + + # Set up multi-turn scenario + model.add_multiple_turn_outputs( + [ + [get_function_tool_call("tool1", "{}")], + [get_text_message("Turn 2")], + [get_text_message("Turn 3")], + ] + ) + + result = Runner.run_streamed(agent, input="Hello") + + turns_completed = 0 + async for event in result.stream_events(): + if event.type == "run_item_stream_event" and event.name == "tool_output": + turns_completed += 1 + if turns_completed == 1: + result.cancel(mode="after_turn") + + assert turns_completed == 1, "Should complete exactly 1 turn" + + +@pytest.mark.asyncio +async def test_cancel_mode_backward_compatibility(): + """Verify default behavior unchanged.""" + model = FakeModel() + agent = Agent(name="Assistant", model=model) + + result = Runner.run_streamed(agent, input="Hello") + + events = [] + async for event in result.stream_events(): + events.append(event) + if len(events) == 1: + result.cancel() # No mode argument + + # Should behave like immediate cancel + assert len(events) == 1 + assert result.is_complete + assert result._event_queue.empty() + assert result._cancel_mode == "immediate", "Should default to immediate mode" + + +@pytest.mark.asyncio +async def test_soft_cancel_idempotent(): + """Verify calling cancel multiple times is safe.""" + model = FakeModel() + agent = Agent(name="Assistant", model=model) + + result = Runner.run_streamed(agent, input="Hello") + + called_twice = False + async for _ in result.stream_events(): + if not called_twice: + result.cancel(mode="after_turn") + result.cancel(mode="after_turn") # Second call + called_twice = True + + # Should not raise or cause issues + assert result.is_complete + + +@pytest.mark.asyncio +async def test_soft_cancel_before_streaming(): + """Verify soft cancel before streaming starts.""" + model = FakeModel() + agent = Agent(name="Assistant", model=model) + + result = Runner.run_streamed(agent, input="Hello") + result.cancel(mode="after_turn") + + events = [e async for e in result.stream_events()] + + # Should stop quickly (may get agent_updated event before stopping) + assert len(events) <= 1, "Should get at most 1 event (agent_updated)" + assert result.is_complete + + +@pytest.mark.asyncio +async def test_soft_cancel_mixed_modes(): + """Verify changing cancel mode behaves correctly.""" + model = FakeModel() + agent = Agent(name="Assistant", model=model) + + result = Runner.run_streamed(agent, input="Hello") + + # First call soft, then immediate + result.cancel(mode="after_turn") + result.cancel(mode="immediate") # Override to immediate + + _ = [e async for e in result.stream_events()] + + # Immediate should take precedence + assert result._cancel_mode == "immediate" + # Queues should be empty (immediate cancel behavior) + assert result._event_queue.empty() + + +@pytest.mark.asyncio +async def test_soft_cancel_explicit_immediate_mode(): + """Test explicit immediate mode behaves same as default.""" + model = FakeModel() + agent = Agent(name="Assistant", model=model) + + result = Runner.run_streamed(agent, input="Hello") + + events = [] + async for event in result.stream_events(): + events.append(event) + if len(events) == 1: + result.cancel(mode="immediate") + break + + assert result.is_complete + assert result._event_queue.empty() + assert result._cancel_mode == "immediate" + assert len(events) == 1 + + +@pytest.mark.asyncio +async def test_soft_cancel_with_multiple_tool_calls(): + """Verify soft cancel works with multiple tool calls in one turn.""" + model = FakeModel() + agent = Agent( + name="Assistant", + model=model, + tools=[ + get_function_tool("tool1", "result1"), + get_function_tool("tool2", "result2"), + ], + ) + + # Turn with multiple tool calls + model.add_multiple_turn_outputs( + [ + [ + get_function_tool_call("tool1", "{}"), + get_function_tool_call("tool2", "{}"), + ], + [get_text_message("Both tools executed")], + ] + ) + + result = Runner.run_streamed(agent, input="Execute tools") + + tool_outputs_seen = 0 + async for event in result.stream_events(): + if event.type == "run_item_stream_event": + if event.name == "tool_called": + # Cancel after seeing first tool call + if tool_outputs_seen == 0: + result.cancel(mode="after_turn") + elif event.name == "tool_output": + tool_outputs_seen += 1 + + # Both tools should execute + assert tool_outputs_seen == 2, "Both tools should execute before soft cancel" + + +@pytest.mark.asyncio +async def test_soft_cancel_preserves_state(): + """Verify soft cancel preserves all result state correctly.""" + model = FakeModel() + agent = Agent( + name="Assistant", + model=model, + tools=[get_function_tool("tool1", "result")], + ) + + model.add_multiple_turn_outputs( + [ + [get_function_tool_call("tool1", "{}")], + [get_text_message("Done")], + ] + ) + + result = Runner.run_streamed(agent, input="Hello") + + async for event in result.stream_events(): + if event.type == "run_item_stream_event" and event.name == "tool_output": + result.cancel(mode="after_turn") + + # Verify state is preserved + assert result.is_complete + assert len(result.new_items) > 0, "Should have items from completed turn" + assert len(result.raw_responses) > 0, "Should have raw responses" + assert result.context_wrapper.usage.requests > 0, "Should have usage data (requests tracked)" + + +@pytest.mark.asyncio +async def test_immediate_cancel_clears_queues(): + """Verify immediate cancel clears queues as expected.""" + model = FakeModel() + agent = Agent(name="Assistant", model=model) + + result = Runner.run_streamed(agent, input="Hello") + + async for _ in result.stream_events(): + result.cancel(mode="immediate") + break + + # Verify queues are cleared + assert result._event_queue.empty(), "Event queue should be empty after immediate cancel" + assert result._input_guardrail_queue.empty(), ( + "Input guardrail queue should be empty after immediate cancel" + ) + + +@pytest.mark.asyncio +async def test_soft_cancel_does_not_clear_queues_immediately(): + """Verify soft cancel does NOT clear queues immediately.""" + model = FakeModel() + agent = Agent(name="Assistant", model=model) + + result = Runner.run_streamed(agent, input="Hello") + + # Just call cancel, don't consume events yet + result.cancel(mode="after_turn") + + # The cancel mode should be set + assert result._cancel_mode == "after_turn" + + # Now consume events + events = [e async for e in result.stream_events()] + + # Should have received events (queue was not cleared immediately) + assert len(events) >= 0 # Events may or may not be present depending on timing + + +@pytest.mark.asyncio +async def test_soft_cancel_with_handoff(): + """Verify soft cancel after handoff saves the handoff turn.""" + from agents import Handoff + + model = FakeModel() + + # Create two agents with handoff + agent2 = Agent(name="Agent2", model=model) + + async def on_invoke_handoff(context, data): + return agent2 + + agent1 = Agent( + name="Agent1", + model=model, + handoffs=[ + Handoff( + tool_name=Handoff.default_tool_name(agent2), + tool_description=Handoff.default_tool_description(agent2), + input_json_schema={}, + on_invoke_handoff=on_invoke_handoff, + agent_name=agent2.name, + ) + ], + ) + + # Setup: Agent1 does handoff, Agent2 responds + model.add_multiple_turn_outputs( + [ + # Agent1's turn - triggers handoff + [get_function_tool_call(Handoff.default_tool_name(agent2), "{}")], + # Agent2's turn after handoff + [get_text_message("Agent2 response")], + ] + ) + + session = SQLiteSession("test_soft_cancel_handoff") + await session.clear_session() + + result = Runner.run_streamed(agent1, input="Hello", session=session) + + handoff_seen = False + async for event in result.stream_events(): + if event.type == "run_item_stream_event" and event.name == "handoff_occured": + handoff_seen = True + # Cancel right after handoff + result.cancel(mode="after_turn") + + assert handoff_seen, "Handoff should have occurred" + + # Verify session has items from the handoff turn + items = await session.get_items() + assert len(items) > 0, "Session should have saved the handoff turn" + + # Cleanup + await session.clear_session() + + +@pytest.mark.asyncio +async def test_soft_cancel_with_session_and_multiple_turns(): + """Verify soft cancel with session across multiple turns.""" + model = FakeModel() + agent = Agent( + name="Assistant", + model=model, + tools=[get_function_tool("tool1", "result1")], + ) + + session = SQLiteSession("test_soft_cancel_multi") + await session.clear_session() + + # Setup 3 turns + model.add_multiple_turn_outputs( + [ + [get_function_tool_call("tool1", "{}")], + [get_function_tool_call("tool1", "{}")], + [get_text_message("Final")], + ] + ) + + result = Runner.run_streamed(agent, input="Hello", session=session) + + turns_seen = 0 + async for event in result.stream_events(): + if event.type == "run_item_stream_event" and event.name == "tool_output": + turns_seen += 1 + if turns_seen == 2: + result.cancel(mode="after_turn") + + # Should have completed 2 turns + assert turns_seen == 2 + + # Check session has both turns + items = await session.get_items() + assert len(items) > 0 + + # Cleanup + await session.clear_session()