diff --git a/docs/astro.config.mjs b/docs/astro.config.mjs index 6c68662f..2d463549 100644 --- a/docs/astro.config.mjs +++ b/docs/astro.config.mjs @@ -87,7 +87,7 @@ const plugins = [ paths: ['api/**'], }, ], - exclude: ['ja/**'], + exclude: ['ja/**', 'zh/**'], }), ]; @@ -97,6 +97,7 @@ const sidebar = [ link: '/', translations: { ja: '概要', + zh: '概述', }, }, { @@ -104,12 +105,14 @@ const sidebar = [ link: '/guides/quickstart', translations: { ja: 'クイックスタート', + zh: '快速开始', }, }, { label: 'Guides', translations: { ja: 'ガイド', + zh: '指南', }, items: [ { @@ -117,6 +120,7 @@ const sidebar = [ link: '/guides/agents', translations: { ja: 'エージェント', + zh: '智能体', }, }, { @@ -124,6 +128,7 @@ const sidebar = [ link: '/guides/running-agents', translations: { ja: 'エージェントの実行', + zh: '运行智能体', }, }, { @@ -131,6 +136,7 @@ const sidebar = [ link: '/guides/results', translations: { ja: 'エージェントの実行結果', + zh: '执行结果', }, }, { @@ -138,6 +144,7 @@ const sidebar = [ link: '/guides/tools', translations: { ja: 'ツール', + zh: '工具', }, }, { @@ -145,6 +152,7 @@ const sidebar = [ link: '/guides/multi-agent', translations: { ja: 'マルチエージェント', + zh: '多智能体编排', }, }, { @@ -152,6 +160,7 @@ const sidebar = [ link: '/guides/handoffs', translations: { ja: 'ハンドオフ', + zh: '交接', }, }, { @@ -159,6 +168,7 @@ const sidebar = [ link: '/guides/context', translations: { ja: 'コンテキスト管理', + zh: '上下文管理', }, }, { @@ -166,6 +176,7 @@ const sidebar = [ link: '/guides/models', translations: { ja: 'モデル', + zh: '模型', }, }, { @@ -173,6 +184,7 @@ const sidebar = [ link: '/guides/guardrails', translations: { ja: 'ガードレール', + zh: '护栏', }, }, { @@ -180,6 +192,7 @@ const sidebar = [ link: '/guides/streaming', translations: { ja: 'ストリーミング', + zh: '流式传输', }, }, { @@ -187,6 +200,7 @@ const sidebar = [ link: '/guides/human-in-the-loop', translations: { ja: '人間の介入(HITL)', + zh: '人机协作', }, }, { @@ -194,6 +208,7 @@ const sidebar = [ link: '/guides/mcp', translations: { ja: 'MCP 連携', + zh: 'MCP 集成', }, }, { @@ -201,6 +216,7 @@ const sidebar = [ link: '/guides/tracing', translations: { ja: 'トレーシング', + zh: '追踪', }, }, { @@ -208,6 +224,7 @@ const sidebar = [ link: '/guides/config', translations: { ja: 'SDK の設定', + zh: 'SDK 配置', }, }, { @@ -215,6 +232,7 @@ const sidebar = [ link: '/guides/troubleshooting', translations: { ja: 'トラブルシューティング', + zh: '故障排除', }, }, { @@ -222,6 +240,7 @@ const sidebar = [ link: '/guides/release', translations: { ja: 'リリースプロセス', + zh: '发布流程', }, }, ], @@ -230,6 +249,7 @@ const sidebar = [ label: 'Voice Agents', translations: { ja: '音声エージェント', + zh: '语音智能体', }, items: [ { @@ -237,6 +257,7 @@ const sidebar = [ link: '/guides/voice-agents', translations: { ja: '音声エージェントの概要', + zh: '语音智能体概述', }, }, { @@ -244,6 +265,7 @@ const sidebar = [ link: '/guides/voice-agents/quickstart', translations: { ja: 'クイックスタート', + zh: '快速开始', }, }, { @@ -251,6 +273,7 @@ const sidebar = [ link: '/guides/voice-agents/build', translations: { ja: '音声エージェントの構築', + zh: '构建语音智能体', }, }, { @@ -258,6 +281,7 @@ const sidebar = [ link: '/guides/voice-agents/transport', translations: { ja: 'リアルタイムトランスポート', + zh: '传输机制', }, }, ], @@ -266,6 +290,7 @@ const sidebar = [ label: 'Extensions', translations: { ja: '拡張機能', + zh: '扩展', }, items: [ { @@ -273,6 +298,7 @@ const sidebar = [ link: '/extensions/ai-sdk', translations: { ja: 'AI SDK で任意モデルを指定', + zh: '使用 AI SDK 指定任意模型', }, }, { @@ -280,6 +306,7 @@ const sidebar = [ link: '/extensions/twilio', translations: { ja: 'Realtime Agent を Twilio に接続', + zh: '将实时智能体连接到 Twilio', }, }, ], @@ -288,6 +315,7 @@ const sidebar = [ label: 'API Reference', translations: { ja: 'APIリファレンス', + zh: 'API 参考', }, collapsed: false, items: [ @@ -350,6 +378,10 @@ export default defineConfig({ label: '日本語', lang: 'ja', }, + zh: { + label: '中文', + lang: 'zh', + }, }, social: [ { diff --git a/docs/src/content/docs/zh/extensions/ai-sdk.mdx b/docs/src/content/docs/zh/extensions/ai-sdk.mdx new file mode 100644 index 00000000..59e222c4 --- /dev/null +++ b/docs/src/content/docs/zh/extensions/ai-sdk.mdx @@ -0,0 +1,85 @@ +--- +title: 使用任何模型与 Vercel 的 AI SDK +description: Connect your Agents SDK agents to any model through the Vercel's AI SDK +--- + +import { Aside, Steps, Code } from '@astrojs/starlight/components'; +import aiSdkSetupExample from '../../../../../../examples/docs/extensions/ai-sdk-setup.ts?raw'; + + + +开箱即用,Agents SDK 可通过 Responses API 或 Chat Completions API 与 OpenAI 模型配合使用。不过,如果您希望使用其他模型,[Vercel 的 AI SDK](https://sdk.vercel.ai/) 提供了多种受支持的模型,可通过此适配器接入 Agents SDK。 + +## 设置 + + + +1. 通过安装扩展包来安装 AI SDK 适配器: + + ```bash + npm install @openai/agents-extensions + ``` + +2. 从 [Vercel 的 AI SDK](https://ai-sdk.dev/docs/foundations/providers-and-models) 选择所需的模型包并进行安装: + + ```bash + npm install @ai-sdk/openai + ``` + +3. 导入适配器和模型以连接到您的智能体: + + ```typescript + import { openai } from '@ai-sdk/openai'; + import { aisdk } from '@openai/agents-extensions'; + ``` + +4. 初始化模型实例,供该智能体使用: + + ```typescript + const model = aisdk(openai('o4-mini')); + ``` + + + + + +## 示例 + + + +## 提供方元数据传递 + +如果您需要随消息发送提供方特定的选项,请通过 `providerMetadata` 传递。这些值会直接转发给底层的 AI SDK 模型。例如,在 Agents SDK 中如下的 `providerData` + +```ts +providerData: { + anthropic: { + cacheControl: { + type: 'ephemeral'; + } + } +} +``` + +将会变为 + +```ts +providerMetadata: { + anthropic: { + cacheControl: { + type: 'ephemeral'; + } + } +} +``` + +在使用 AI SDK 集成时。 diff --git a/docs/src/content/docs/zh/extensions/twilio.mdx b/docs/src/content/docs/zh/extensions/twilio.mdx new file mode 100644 index 00000000..55d819f0 --- /dev/null +++ b/docs/src/content/docs/zh/extensions/twilio.mdx @@ -0,0 +1,85 @@ +--- +title: 使用实时智能体与 Twilio +description: Connect your Agents SDK agents to Twilio to use voice agents +--- + +import { Aside, Steps, Code } from '@astrojs/starlight/components'; +import twilioBasicExample from '../../../../../../examples/docs/extensions/twilio-basic.ts?raw'; +import twilioServerExample from '../../../../../../examples/realtime-twilio/index.ts?raw'; + +Twilio 提供一个 [Media Streams API](https://www.twilio.com/docs/voice/media-streams),可将电话通话中的原始音频发送到 WebSocket 服务器。此设置可用于将您的 [Overview](/openai-agents-js/zh/guides/voice-agents) 连接到 Twilio。您可以使用 `websocket` 模式下的默认 Realtime Session 传输,将来自 Twilio 的事件连接到您的 Realtime Session。不过,这需要您设置正确的音频格式,并调整自己的打断时机,因为与基于 Web 的对话相比,电话通话自然会引入更高的延迟。 + +为提升搭建体验,我们创建了专用的传输层,替您处理与 Twilio 的连接,包括处理打断和音频转发。 + + + +## 设置 + + + +1. **请确保您拥有 Twilio 账号和一个 Twilio 电话号码。** + +2. **设置一个可以接收来自 Twilio 事件的 WebSocket 服务器。** + + 如果您在本地开发,这将需要您配置一个本地隧道,比如 + 这将需要您配置一个本地隧道,比如 [`ngrok`](https://ngrok.io/) 或 + [Cloudflare Tunnel](https://developers.cloudflare.com/pages/how-to/preview-with-cloudflare-tunnel/) + 以便让 Twilio 访问您的本地服务器。您可以使用 `TwilioRealtimeTransportLayer` + 来连接到 Twilio。 + +3. **通过安装扩展包来安装 Twilio 适配器:** + + ```bash + npm install @openai/agents-extensions + ``` + +4. **导入适配器和模型以连接到您的 `RealtimeSession`:** + + + +5. **将您的 `RealtimeSession` 连接到 Twilio:** + + ```typescript + session.connect({ apiKey: 'your-openai-api-key' }); + ``` + + + +任何您期望从 `RealtimeSession` 获得的事件和行为都会按预期工作,包括工具调用、护栏等。阅读 [Overview](/openai-agents-js/zh/guides/voice-agents) 以了解如何将 `RealtimeSession` 与语音智能体一起使用的更多信息。 + +## 提示与注意事项 + +1. **速度是关键。** + + 为了接收来自 Twilio 的所有必要事件和音频,一旦您拿到 WebSocket 连接的引用,就应尽快创建 + `TwilioRealtimeTransportLayer` 实例,并立即调用 `session.connect()`。 + +2. **访问 Twilio 的原始事件。** + + 如果您想访问 Twilio 发送的原始事件,可以在 `RealtimeSession` 实例上监听 + `transport_event` 事件。来自 Twilio 的每个事件的 `type` 都是 `twilio_message`,并包含一个 `message` 属性,其中包含原始事件数据。 + +3. **查看调试日志。** + + 有时您可能会遇到需要更多信息才能定位的问题。使用 `DEBUG=openai-agents*` 环境变量将显示来自 Agents SDK 的所有调试日志。或者,您也可以仅为 Twilio 适配器启用调试日志: + `DEBUG=openai-agents:extensions:twilio*`。 + +## 完整示例服务器 + +下面是一个端到端的 WebSocket 服务器示例,它接收来自 Twilio 的请求并将其转发到 `RealtimeSession`。 + + diff --git a/docs/src/content/docs/zh/guides/agents.mdx b/docs/src/content/docs/zh/guides/agents.mdx new file mode 100644 index 00000000..569df4a3 --- /dev/null +++ b/docs/src/content/docs/zh/guides/agents.mdx @@ -0,0 +1,169 @@ +--- +title: 智能体 +description: Learn more about how to define agents in the OpenAI Agents SDK for JavaScript / TypeScript +--- + +import { Code } from '@astrojs/starlight/components'; +import simpleAgent from '../../../../../../examples/docs/agents/simpleAgent.ts?raw'; +import agentWithTools from '../../../../../../examples/docs/agents/agentWithTools.ts?raw'; +import agentWithContext from '../../../../../../examples/docs/agents/agentWithContext.ts?raw'; +import agentWithAodOutputType from '../../../../../../examples/docs/agents/agentWithAodOutputType.ts?raw'; +import agentsAsTools from '../../../../../../examples/docs/agents/agentsAsTools.ts?raw'; +import agentWithHandoffs from '../../../../../../examples/docs/agents/agentWithHandoffs.ts?raw'; +import agentWithDynamicInstructions from '../../../../../../examples/docs/agents/agentWithDynamicInstructions.ts?raw'; +import agentWithLifecycleHooks from '../../../../../../examples/docs/agents/agentWithLifecycleHooks.ts?raw'; +import agentCloning from '../../../../../../examples/docs/agents/agentCloning.ts?raw'; +import agentForcingToolUse from '../../../../../../examples/docs/agents/agentForcingToolUse.ts?raw'; + +智能体是 OpenAI Agents SDK 的主要构建模块。**智能体** 是一个大型语言模型(LLM),它被配置了: + +- **Instructions** —— 告诉模型*它是谁*以及*应如何响应*的系统提示。 +- **Model** —— 要调用的 OpenAI 模型,以及可选的模型调优参数。 +- **Tools** —— LLM 为完成任务可调用的一组函数或 API。 + + + +本页其余部分将更详细地介绍每个智能体特性。 + +--- + +## 基础配置 + +`Agent` 构造函数接收一个配置对象。最常用的属性如下所示。 + +| 属性 | 必填 | 描述 | +| --------------- | ---- | ------------------------------------------------------------------------------------------ | +| `name` | 是 | 简短、易读的标识符。 | +| `instructions` | 是 | 系统提示(字符串**或**函数——参见[动态 instructions](#dynamic-instructions))。 | +| `model` | 否 | 模型名称**或**自定义的 [`Model`](/openai-agents-js/openai/agents/interfaces/model/) 实现。 | +| `modelSettings` | 否 | 调优参数(temperature、top_p 等)。 | +| `tools` | 否 | 模型可调用的 [`Tool`](/openai-agents-js/openai/agents/type-aliases/tool/) 实例数组。 | + + + +--- + +## 上下文 + +智能体在其上下文类型上是**泛型化**的——即 `Agent`。_上下文_ 是一个依赖注入对象,由您创建并传递给 `Runner.run()`。它会被转发到每个工具、护栏、交接等组件,对于存储状态或提供共享服务(数据库连接、用户元数据、功能开关等)很有用。 + + + +--- + +## 输出类型 + +默认情况下,智能体返回**纯文本**(`string`)。如果希望模型返回结构化对象,可以指定 `outputType` 属性。SDK 接受: + +1. [Zod](https://github.com/colinhacks/zod) 模式(`z.object({...})`)。 +2. 任意兼容 JSON Schema 的对象。 + + + +当提供了 `outputType` 时,SDK 会自动使用 +[structured outputs](https://platform.openai.com/docs/guides/structured-outputs) 而非纯文本。 + +--- + +## 多智能体系统设计模式 + +组合智能体有很多方式。我们在生产应用中经常看到两种模式: + +1. **管理器(智能体作为工具)**——一个中心智能体掌控对话,并调用以工具形式暴露的专业智能体。 +2. **交接**——初始智能体在识别出用户的请求后,将整个对话委托给某个专家智能体。 + +这两种方法是互补的。管理器为您提供一个集中位置来实施护栏或速率限制,而交接让每个智能体专注于单一任务,而不必保留对对话的控制权。 + +### 管理器(智能体作为工具) + +在这种模式下,管理器从不移交控制权——LLM 使用工具,且由管理器汇总最终答案。详见 [Tools](/openai-agents-js/zh/guides/tools#agents-as-tools)。 + + + +### 交接 + +使用交接时,分流智能体负责路由请求,但一旦发生交接,专家智能体就拥有对话的控制权,直到产生最终输出。这使提示更短,并让您可以独立地推理每个智能体。了解更多请参阅 [Handoffs](/openai-agents-js/zh/guides/handoffs)。 + + + +--- + +## 动态 instructions + +`instructions` 可以是**函数**而非字符串。该函数接收当前的 `RunContext` 和 Agent 实例,并且可以返回字符串 _或_ `Promise`。 + + + +同时支持同步和 `async` 函数。 + +--- + +## 生命周期钩子 + +对于高级用例,您可以通过监听事件来观察智能体的生命周期 + + + +--- + +## 护栏 + +护栏允许您验证或转换用户输入与智能体输出。通过 `inputGuardrails` 和 `outputGuardrails` 数组进行配置。详见 [Guardrails](/openai-agents-js/zh/guides/guardrails)。 + +--- + +## 智能体的克隆 / 复制 + +需要在现有智能体基础上做些小修改?使用 `clone()` 方法,它会返回一个全新的 `Agent` 实例。 + + + +--- + +## 强制工具使用 + +提供工具并不保证 LLM 会调用它。您可以通过 `modelSettings.tool_choice` **强制**使用工具: + +1. `'auto'`(默认)——LLM 决定是否使用工具。 +2. `'required'`——LLM _必须_ 调用某个工具(可自行选择哪个)。 +3. `'none'`——LLM **不得** 调用任何工具。 +4. 指定工具名,例如 `'calculator'` ——LLM 必须调用该特定工具。 + + + +### 防止无限循环 + +在一次工具调用后,SDK 会自动将 `tool_choice` 重置为 `'auto'`。这可防止模型进入反复尝试调用工具的无限循环。您可以通过 `resetToolChoice` 标志或配置 +`toolUseBehavior` 来覆盖该行为: + +- `'run_llm_again'`(默认)——使用工具结果再次运行 LLM。 +- `'stop_on_first_tool'` ——将第一个工具结果视为最终答案。 +- `{ stopAtToolNames: ['my_tool'] }` ——当任一列出的工具被调用时停止。 +- `(context, toolResults) => ...` ——返回运行是否应结束的自定义函数。 + +```typescript +const agent = new Agent({ + ..., + toolUseBehavior: 'stop_on_first_tool', +}); +``` + +--- + +## 后续步骤 + +- 了解如何 [Running Agents](/openai-agents-js/zh/guides/running-agents)。 +- 深入了解 [Tools](/openai-agents-js/zh/guides/tools)、[Guardrails](/openai-agents-js/zh/guides/guardrails) 和 [Models](/openai-agents-js/zh/guides/models)。 +- 在侧边栏的 **@openai/agents** 下查阅完整的 TypeDoc 参考。 diff --git a/docs/src/content/docs/zh/guides/config.mdx b/docs/src/content/docs/zh/guides/config.mdx new file mode 100644 index 00000000..1b3abcb3 --- /dev/null +++ b/docs/src/content/docs/zh/guides/config.mdx @@ -0,0 +1,76 @@ +--- +title: 配置 SDK +description: Customize API keys, tracing and logging behavior +--- + +import { Code } from '@astrojs/starlight/components'; +import setDefaultOpenAIKeyExample from '../../../../../../examples/docs/config/setDefaultOpenAIKey.ts?raw'; +import setDefaultOpenAIClientExample from '../../../../../../examples/docs/config/setDefaultOpenAIClient.ts?raw'; +import setOpenAIAPIExample from '../../../../../../examples/docs/config/setOpenAIAPI.ts?raw'; +import setTracingExportApiKeyExample from '../../../../../../examples/docs/config/setTracingExportApiKey.ts?raw'; +import setTracingDisabledExample from '../../../../../../examples/docs/config/setTracingDisabled.ts?raw'; +import getLoggerExample from '../../../../../../examples/docs/config/getLogger.ts?raw'; + +## API 密钥与客户端 + +默认情况下,SDK 在首次导入时会读取环境变量 `OPENAI_API_KEY`。如果无法设置该变量,您可以手动调用 `setDefaultOpenAIKey()`。 + + + +您也可以传入自己的 `OpenAI` 客户端实例。否则 SDK 将使用默认密钥自动创建一个。 + + + +最后,您可以在 Responses API 和 Chat Completions API 之间切换。 + + + +## 追踪 + +追踪默认启用,并使用上文的 OpenAI 密钥。可以通过 `setTracingExportApiKey()` 设置单独的密钥。 + + + +也可以完全禁用追踪。 + + + +## 调试日志 + +SDK 使用 [`debug`](https://www.npmjs.com/package/debug) 包进行调试日志记录。将环境变量 `DEBUG` 设为 `openai-agents*` 以查看详细日志。 + +```bash +export DEBUG=openai-agents* +``` + +您可以使用 `@openai/agents` 中的 `getLogger(namespace)` 为自己的模块获取一个带命名空间的日志记录器。 + + + +### 日志中的敏感数据 + +某些日志可能包含用户数据。可通过设置以下环境变量来禁用。 + +要禁用记录 LLM 的输入和输出: + +```bash +export OPENAI_AGENTS_DONT_LOG_MODEL_DATA=1 +``` + +要禁用记录工具的输入和输出: + +```bash +export OPENAI_AGENTS_DONT_LOG_TOOL_DATA=1 +``` diff --git a/docs/src/content/docs/zh/guides/context.mdx b/docs/src/content/docs/zh/guides/context.mdx new file mode 100644 index 00000000..f55ec030 --- /dev/null +++ b/docs/src/content/docs/zh/guides/context.mdx @@ -0,0 +1,43 @@ +--- +title: 上下文管理 +description: Learn how to provide local data via RunContext and expose context to the LLM +--- + +import { Aside, Code } from '@astrojs/starlight/components'; +import localContextExample from '../../../../../../examples/docs/context/localContext.ts?raw'; + +“上下文”是一个被广泛使用的术语。你可能关心两大类上下文: + +1. 你的代码在一次运行期间可访问的**本地上下文**:工具所需的依赖或数据、像 `onHandoff` 这样的回调,以及生命周期钩子。 +2. 语言模型在生成响应时可见的**智能体/LLM 上下文**。 + +## 本地上下文 + +本地上下文由 `RunContext` 类型表示。你可以创建任意对象来保存状态或依赖,并将其传给 `Runner.run()`。所有工具调用和钩子都会接收一个 `RunContext` 包装器,以便它们读取或修改该对象。 + + + +参与同一次运行的每个智能体、工具和钩子必须使用相同的**类型**的上下文。 + +将本地上下文用于如下场景: + +- 关于本次运行的数据(用户名、ID 等) +- 诸如日志记录器或数据获取器等依赖项 +- 辅助函数 + + + +## 智能体/LLM 上下文 + +当调用 LLM 时,它能看到的数据仅来自会话历史。若要提供更多信息,你有几种选择: + +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. 使用检索或 Web 搜索工具,将回答建立在来自文件、数据库或 Web 的相关数据之上。 diff --git a/docs/src/content/docs/zh/guides/guardrails.mdx b/docs/src/content/docs/zh/guides/guardrails.mdx new file mode 100644 index 00000000..350191e5 --- /dev/null +++ b/docs/src/content/docs/zh/guides/guardrails.mdx @@ -0,0 +1,56 @@ +--- +title: 护栏 +description: Validate or transform agent input and output +--- + +import { Code } from '@astrojs/starlight/components'; +import inputGuardrailExample from '../../../../../../examples/docs/guardrails/guardrails-input.ts?raw'; +import outputGuardrailExample from '../../../../../../examples/docs/guardrails/guardrails-output.ts?raw'; + +护栏与您的智能体*并行*运行,允许您对用户输入或智能体输出执行检查与验证。比如,您可以在调用昂贵模型之前,先运行一个轻量模型作为护栏。如果护栏检测到恶意使用,它可以触发错误并阻止高成本模型的运行。 + +护栏有两种类型: + +1. **输入护栏** 运行于初始的用户输入。 +2. **输出护栏** 运行于智能体的最终输出。 + +## 输入护栏 + +输入护栏分三步执行: + +1. 护栏接收与传递给智能体相同的输入。 +2. 护栏函数执行并返回一个 [`GuardrailFunctionOutput`](/openai-agents-js/openai/agents/interfaces/guardrailfunctionoutput),并封装在 [`InputGuardrailResult`](/openai-agents-js/openai/agents/interfaces/inputguardrailresult) 中。 +3. 如果 `tripwireTriggered` 为 `true`,将抛出 [`InputGuardrailTripwireTriggered`](/openai-agents-js/openai/agents/classes/inputguardrailtripwiretriggered) 错误。 + +> **注意** +> 输入护栏面向用户输入,因此仅当该智能体是工作流中的*第一个*智能体时才会运行。护栏在智能体本身上进行配置,因为不同的智能体通常需要不同的护栏。 + +## 输出护栏 + +输出护栏遵循相同模式: + +1. 护栏接收与传递给智能体相同的输入。 +2. 护栏函数执行并返回一个 [`GuardrailFunctionOutput`](/openai-agents-js/openai/agents/interfaces/guardrailfunctionoutput),并封装在 [`OutputGuardrailResult`](/openai-agents-js/openai/agents/interfaces/outputguardrailresult) 中。 +3. 如果 `tripwireTriggered` 为 `true`,将抛出 [`OutputGuardrailTripwireTriggered`](/openai-agents-js/openai/agents/classes/outputguardrailtripwiretriggered) 错误。 + +> **注意** +> 仅当该智能体是工作流中的*最后*智能体时才会运行输出护栏。关于实时语音交互,请参见 [Building Voice Agents](/openai-agents-js/zh/guides/voice-agents/build#guardrails)。 + +## 绊线 + +当护栏失败时,它会通过绊线发出信号。一旦绊线被触发,运行器(runner)会抛出相应错误并停止执行。 + +## 护栏的实现 + +护栏本质上是一个返回 `GuardrailFunctionOutput` 的函数。下面是一个最小示例:它在底层运行另一个智能体,以检查用户是否在请求数学作业方面的帮助。 + + + +输出护栏的工作方式相同。 + + + +1. 在护栏函数内部使用 `guardrailAgent`。 +2. 护栏函数接收智能体的输入或输出并返回结果。 +3. 可以在护栏结果中包含额外信息。 +4. `agent` 定义应用护栏的实际工作流。 diff --git a/docs/src/content/docs/zh/guides/handoffs.mdx b/docs/src/content/docs/zh/guides/handoffs.mdx new file mode 100644 index 00000000..1776a2cc --- /dev/null +++ b/docs/src/content/docs/zh/guides/handoffs.mdx @@ -0,0 +1,55 @@ +--- +title: 交接 +description: Delegate tasks from one agent to another +--- + +import { Code } from '@astrojs/starlight/components'; +import basicUsageExample from '../../../../../../examples/docs/handoffs/basicUsage.ts?raw'; +import customizeHandoffExample from '../../../../../../examples/docs/handoffs/customizeHandoff.ts?raw'; +import handoffInputExample from '../../../../../../examples/docs/handoffs/handoffInput.ts?raw'; +import inputFilterExample from '../../../../../../examples/docs/handoffs/inputFilter.ts?raw'; +import recommendedPromptExample from '../../../../../../examples/docs/handoffs/recommendedPrompt.ts?raw'; + +交接允许一个智能体将对话的一部分委托给另一个智能体。这在不同智能体专注于特定领域时很有用。比如在客服应用中,您可能会有处理预订、退款或常见问题的智能体。 + +对于 LLM,交接会被表示为工具。如果您将对话交接给名为 `Refund Agent` 的智能体,对应的工具名称将是 `transfer_to_refund_agent`。 + +## 交接的创建 + +每个智能体都接受一个 `handoffs` 选项。它可以包含其他 `Agent` 实例,或由 `handoff()` 辅助函数返回的 `Handoff` 对象。 + +### 基础用法 + + + +### 通过 `handoff()` 的交接自定义 + +`handoff()` 函数允许您调整生成的工具。 + +- `agent` — 交接目标智能体。 +- `toolNameOverride` — 覆盖默认的 `transfer_to_` 工具名称。 +- `toolDescriptionOverride` — 覆盖默认的工具描述。 +- `onHandoff` — 交接发生时的回调。接收一个 `RunContext`,以及可选的已解析输入。 +- `inputType` — 交接期望的输入 schema。 +- `inputFilter` — 过滤传递给下一个智能体的历史记录。 + + + +## 交接输入 + +有时您希望在调用交接时由 LLM 提供数据。定义一个输入 schema,并在 `handoff()` 中使用它。 + + + +## 输入过滤器 + +默认情况下,交接会接收整个对话历史。若要修改传递给下一个智能体的内容,请提供一个 `inputFilter`。 +常用辅助函数位于 `@openai/agents-core/extensions`。 + + + +## 推荐提示词 + +当您的提示词提及交接时,LLM 的响应会更稳定。SDK 通过 `RECOMMENDED_PROMPT_PREFIX` 提供了一个推荐前缀。 + + diff --git a/docs/src/content/docs/zh/guides/human-in-the-loop.mdx b/docs/src/content/docs/zh/guides/human-in-the-loop.mdx new file mode 100644 index 00000000..df9b4dff --- /dev/null +++ b/docs/src/content/docs/zh/guides/human-in-the-loop.mdx @@ -0,0 +1,61 @@ +--- +title: 人工干预 +description: Add a human in the loop check for your agent executions +--- + +import { Aside, Code } from '@astrojs/starlight/components'; +import humanInTheLoopExample from '../../../../../../examples/docs/human-in-the-loop/index.ts?raw'; +import toolApprovalDefinition from '../../../../../../examples/docs/human-in-the-loop/toolApprovalDefinition.ts?raw'; + +本指南演示如何使用 SDK 内置的人工干预支持,根据人工介入暂停和恢复智能体的运行。 + +当前的主要用例是:在执行敏感的工具调用前请求批准。 + +## 批准请求 + +您可以通过将 `needsApproval` 选项设置为 `true`,或设置为返回布尔值的异步函数,来定义需要批准的工具。 + + + +### 流程 + +1. 如果智能体决定调用一个(或多个)工具,它会通过评估 `needsApproval` 来检查该工具是否需要批准。 +2. 如果需要批准,智能体将检查是否已批准或已拒绝。 + - 如果既未批准也未拒绝,工具会向智能体返回一条静态消息,说明该工具调用无法执行。 + - 如果缺少批准/拒绝,它将触发一个工具批准请求。 +3. 智能体将收集所有工具批准请求并中断执行。 +4. 如果存在中断,[Results](/openai-agents-js/zh/guides/results) 将包含一个 `interruptions` 数组,用于描述待处理步骤。当某个工具调用需要确认时,会出现一个 `type: "tool_approval_item"` 的 `ToolApprovalItem`。 +5. 您可以调用 `result.state.approve(interruption)` 或 `result.state.reject(interruption)` 来批准或拒绝该工具调用。 +6. 在处理完所有中断后,您可以将 `result.state` 传回 `runner.run(agent, state)` 以恢复执行,其中 `agent` 是触发此次整体运行的原始智能体。 +7. 流程将从第 1 步重新开始。 + +## 示例 + +下面是一个更完整的人工干预流程示例,它会在终端中提示进行批准,并临时将状态存储到文件中。 + + + +有关可运行的端到端版本,请参阅[完整示例脚本](https://github.com/openai/openai-agents-js/tree/main/examples/agent-patterns/human-in-the-loop.ts)。 + +## 更长批准时长的处理 + +人工干预流程被设计为可在较长时间内中断,而无需让您的服务器持续运行。如果您需要中止请求并稍后继续,可以序列化状态,之后再恢复。 + +您可以使用 `JSON.stringify(result.state)` 序列化状态,并在之后将序列化的状态传入 `RunState.fromString(agent, serializedState)` 以恢复,其中 `agent` 是触发此次整体运行的智能体实例。 + +这样,您可以将序列化后的状态存储在数据库中,或与请求一起保存。 + +### 待处理任务的版本控制 + + + +如果您的批准请求需要较长时间,并且您打算以有意义的方式对智能体定义进行版本化,或升级您的 Agents SDK 版本,我们目前建议您通过使用包别名并行安装两个版本的 Agents SDK,来实现自定义的分支逻辑。 + +在实践中,这意味着:为您的代码指定一个版本号,并将其与序列化状态一同存储,同时在反序列化时引导其使用正确版本的代码。 diff --git a/docs/src/content/docs/zh/guides/mcp.mdx b/docs/src/content/docs/zh/guides/mcp.mdx new file mode 100644 index 00000000..55aeb8ef --- /dev/null +++ b/docs/src/content/docs/zh/guides/mcp.mdx @@ -0,0 +1,120 @@ +--- +title: 模型上下文协议 (MCP) +description: Learn how to utilize MCP servers as tools +--- + +import { Code } from '@astrojs/starlight/components'; +import hostedAgentExample from '../../../../../../examples/docs/mcp/hostedAgent.ts?raw'; +import hostedExample from '../../../../../../examples/docs/mcp/hosted.ts?raw'; +import hostedStreamExample from '../../../../../../examples/docs/mcp/hostedStream.ts?raw'; +import hostedHITLExample from '../../../../../../examples/docs/mcp/hostedHITL.ts?raw'; +import hostedConnectorExample from '../../../../../../examples/docs/mcp/hostedConnector.ts?raw'; +import streamableHttpExample from '../../../../../../examples/docs/mcp/streamableHttp.ts?raw'; +import stdioExample from '../../../../../../examples/docs/mcp/stdio.ts?raw'; +import toolFilterExample from '../../../../../../examples/docs/mcp/tool-filter.ts?raw'; + +[**Model Context Protocol (MCP)**](https://modelcontextprotocol.io) 是一个开放协议,用于规范应用如何向 LLM 提供工具和上下文。摘自 MCP 文档: + +> MCP 是一个开放协议,用于规范应用如何向 LLM 提供上下文。可以把 MCP 想象成 AI 应用的 USB‑C 接口。正如 USB‑C 为设备连接各类外设与配件提供了统一方式,MCP 为连接 AI 模型与不同数据源和工具提供了统一方式。 + +该 SDK 支持三种类型的 MCP 服务器: + +1. **远程 MCP 服务器工具** – 由 [OpenAI Responses API](https://platform.openai.com/docs/guides/tools-remote-mcp) 作为工具调用的远程 MCP 服务器 +2. **Streamable HTTP MCP 服务器** – 实现了 [Streamable HTTP 传输](https://modelcontextprotocol.io/docs/concepts/transports#streamable-http) 的本地或远程服务器 +3. **Stdio MCP 服务器** – 通过标准输入/输出访问的服务器(最简单的选项) + +请根据你的用例选择服务器类型: + +| 你的需求 | 推荐选项 | +| --------------------------------------------------------------- | -------------------------- | +| 使用默认的 OpenAI Responses 模型调用公共可访问的远程服务器 | **1. 远程 MCP 服务器工具** | +| 使用公共可访问的远程服务器,但在本地触发工具调用 | **2. Streamable HTTP** | +| 使用本地运行的 Streamable HTTP 服务器 | **2. Streamable HTTP** | +| 将非 OpenAI Responses 模型与任意 Streamable HTTP 服务器配合使用 | **2. Streamable HTTP** | +| 使用只支持标准 I/O 协议的本地 MCP 服务器 | **3. Stdio** | + +## 1. 远程 MCP 服务器工具 + +托管工具会将整个往返交互推送到模型中。不是你的代码调用 MCP 服务器,而是由 OpenAI Responses API 调用远程工具端点,并将结果流式传回模型。 + +下面是使用托管 MCP 工具的最简单示例。你可以将远程 MCP 服务器的标签和 URL 传给 `hostedMcpTool` 实用函数,便于创建托管 MCP 服务器工具。 + + + +然后,你可以使用 `run` 函数(或你自定义的 `Runner` 实例的 `run` 方法)来运行智能体: + + + +若要流式获取增量 MCP 结果,在运行 `Agent` 时传入 `stream: true`: + + + +#### 可选审批流程 + +对于敏感操作,你可以要求对每次工具调用进行人工审批。传入 `requireApproval: 'always'`,或传入一个细粒度对象,将工具名称映射为 `'never'`/`'always'`。 + +如果你能以编程方式判断工具调用是否安全,可以使用 [`onApproval` 回调](https://github.com/openai/openai-agents-js/blob/main/examples/mcp/hosted-mcp-on-approval.ts) 来批准或拒绝工具调用。如果需要人工审批,你可以使用与本地函数工具相同的、基于 `interruptions` 的 [Human-in-the-loop](/openai-agents-js/zh/guides/human-in-the-loop/) 方法。 + + + +### 由连接器支持的托管服务器 + +托管 MCP 也支持 OpenAI 连接器。你无需提供 `serverUrl`,而是传入连接器的 `connectorId` 和 `authorization` 令牌。Responses API 将处理身份验证,并通过托管 MCP 接口暴露连接器的工具。 + + + +在此示例中,环境变量 `GOOGLE_CALENDAR_AUTHORIZATION` 存放了从 Google OAuth Playground 获取的 OAuth 令牌,它授权由连接器支持的服务器调用 Calendar API。包含可运行示例并演示流式传输的样例见 [`examples/connectors`](https://github.com/openai/openai-agents-js/tree/main/examples/connectors)。 + +在我们的 GitHub 仓库中可以找到完整可运行的示例(托管工具/Streamable HTTP/stdio + 流式传输、HITL、onApproval):[examples/mcp](https://github.com/openai/openai-agents-js/tree/main/examples/mcp)。 + +## 2. Streamable HTTP MCP 服务器 + +当你的智能体直接与本地或远程的 Streamable HTTP MCP 服务器通信时,可用服务器的 `url`、`name` 和可选设置实例化 `MCPServerStreamableHttp`: + + + +该构造函数还接受其他 MCP TypeScript SDK 选项,如 `authProvider`、`requestInit`、`fetch`、`reconnectionOptions` 和 `sessionId`。详见 [MCP TypeScript SDK 仓库](https://github.com/modelcontextprotocol/typescript-sdk)及其文档。 + +## 3. Stdio MCP 服务器 + +对于仅通过标准 I/O 暴露的服务器,使用 `fullCommand` 实例化 `MCPServerStdio`: + + + +## 其他注意事项 + +对于 **Streamable HTTP** 和 **Stdio** 服务器,每次运行 `Agent` 时,它都可能调用 `list_tools()` 来发现可用工具。由于这次往返会带来延迟(尤其是访问远程服务器时),你可以通过向 `MCPServerStdio` 或 `MCPServerStreamableHttp` 传入 `cacheToolsList: true` 来在内存中缓存结果。 + +只有在你确信工具列表不会变化时才启用此功能。若需稍后使缓存失效,可在服务器实例上调用 `invalidateToolsCache()`。 + +### 工具筛选 + +你可以通过传入静态筛选器(`createMCPToolStaticFilter`)或自定义函数,限制每个服务器对外暴露的工具。下面是一个组合示例,展示了两种方式: + + + +## 延伸阅读 + +- [Model Context Protocol](https://modelcontextprotocol.io/) – 官方规范。 +- [examples/mcp](https://github.com/openai/openai-agents-js/tree/main/examples/mcp) – 可运行的 + 演示(上文引用)。 diff --git a/docs/src/content/docs/zh/guides/models.mdx b/docs/src/content/docs/zh/guides/models.mdx new file mode 100644 index 00000000..8c500efd --- /dev/null +++ b/docs/src/content/docs/zh/guides/models.mdx @@ -0,0 +1,171 @@ +--- +title: 模型 +description: Choose and configure language models for your agents +--- + +import { Code } from '@astrojs/starlight/components'; +import modelCustomProviderExample from '../../../../../../examples/docs/models/customProviders.ts?raw'; +import setDefaultOpenAIKeyExample from '../../../../../../examples/docs/config/setDefaultOpenAIKey.ts?raw'; +import modelSettingsExample from '../../../../../../examples/docs/models/modelSettings.ts?raw'; +import promptIdExample from '../../../../../../examples/basic/prompt-id.ts?raw'; +import agentWithModelExample from '../../../../../../examples/docs/models/agentWithModel.ts?raw'; +import runnerWithModelExample from '../../../../../../examples/docs/models/runnerWithModel.ts?raw'; +import setTracingExportApiKeyExample from '../../../../../../examples/docs/config/setTracingExportApiKey.ts?raw'; + +每个智能体最终都会调用一个 LLM。SDK 在两个轻量级接口之后抽象了模型: + +- [`Model`](/openai-agents-js/openai/agents/interfaces/model) – 知道如何针对特定 API 发起一次请求。 +- [`ModelProvider`](/openai-agents-js/openai/agents/interfaces/modelprovider) – 将人类可读的模型**名称**(例如 `'gpt‑4o'`)解析为 `Model` 实例。 + +在日常工作中,你通常只需要与模型**名称**交互,偶尔会用到 `ModelSettings`。 + + + +## 默认模型 + +在初始化 `Agent` 时如果未指定模型,将使用默认模型。目前默认是 [`gpt-4.1`](https://platform.openai.com/docs/models/gpt-4.1),它在智能体工作流的可预测性与低延迟之间提供了良好的平衡。 + +如果你想切换到其他模型(如 [`gpt-5`](https://platform.openai.com/docs/models/gpt-5)),有两种方式可以为你的智能体进行配置。 + +首先,如果你希望对所有未设置自定义模型的智能体始终使用某个特定模型,请在运行智能体之前设置环境变量 `OPENAI_DEFAULT_MODEL`。 + +```bash +export OPENAI_DEFAULT_MODEL=gpt-5 +node my-awesome-agent.js +``` + +其次,你可以为某个 `Runner` 实例设置默认模型。如果没有为某个智能体设置模型,将使用该 `Runner` 的默认模型。 + + + +### 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"`。若要为默认模型调整推理强度,请传入你自己的 `modelSettings`: + +```ts +import { Agent } from '@openai/agents'; + +const myAgent = new Agent({ + name: 'My Agent', + instructions: "You're a helpful agent.", + modelSettings: { + providerData: { + reasoning: { effort: 'minimal' }, + text: { verbosity: 'low' }, + }, + // If OPENAI_DEFAULT_MODEL=gpt-5 is set, passing only modelSettings works. + // It's also fine to pass a GPT-5 model name explicitly: + // model: '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) 并将 `reasoning.effort="minimal"`,通常会比默认设置更快地返回响应。然而,Responses API 中的一些内置工具(如文件搜索和图像生成)不支持 `"minimal"` 的推理强度,这也是本 Agents SDK 默认设为 `"low"` 的原因。 + +### 非 GPT-5 模型 + +如果你传入的是非 GPT‑5 的模型名称且未提供自定义 `modelSettings`,SDK 会回退到与任意模型兼容的通用 `modelSettings`。 + +--- + +## OpenAI 提供方 + +默认的 `ModelProvider` 使用 OpenAI API 来解析名称。它支持两个不同的端点: + +| API | 用途 | 调用 `setOpenAIAPI()` | +| ---------------- | ------------------------------------------------------ | ------------------------------------ | +| Chat Completions | 标准聊天与函数调用 | `setOpenAIAPI('chat_completions')` | +| Responses | 全新的以流式传输为先的生成式 API(工具调用、灵活输出) | `setOpenAIAPI('responses')` _(默认)_ | + +### 身份验证 + + + +如果你需要自定义网络设置,也可以通过 `setDefaultOpenAIClient(client)` 插入你自己的 `OpenAI` 客户端。 + +--- + +## 模型设置 + +`ModelSettings` 与 OpenAI 的参数一一对应,但不依赖特定提供方。 + +| 字段 | 类型 | 说明 | +| ------------------- | ------------------------------------------ | ------------------------------------------------------------------------- | +| `temperature` | `number` | 创造性与确定性的权衡。 | +| `topP` | `number` | 核采样。 | +| `frequencyPenalty` | `number` | 惩罚重复的 token。 | +| `presencePenalty` | `number` | 鼓励生成新的 token。 | +| `toolChoice` | `'auto' \| 'required' \| 'none' \| string` | 参见[强制使用工具](/openai-agents-js/zh/guides/agents#forcing-tool-use)。 | +| `parallelToolCalls` | `boolean` | 在支持的情况下允许并行函数调用。 | +| `truncation` | `'auto' \| 'disabled'` | token 截断策略。 | +| `maxTokens` | `number` | 响应中的最大 token 数。 | +| `store` | `boolean` | 持久化响应以用于检索/RAG 工作流。 | +| `reasoning.effort` | `'minimal' \| 'low' \| 'medium' \| 'high'` | gpt-5 等模型的推理强度。 | +| `text.verbosity` | `'low' \| 'medium' \| 'high'` | gpt-5 等模型的文本冗长度。 | + +可在任一层级附加设置: + + + +`Runner` 级别的设置会覆盖与按智能体设置冲突的任何配置。 + +--- + +## 提示 + +可以通过 `prompt` 参数为智能体进行配置,指示应使用某个存储在服务器上的提示配置来控制智能体的行为。目前,只有在使用 OpenAI [Responses API](https://platform.openai.com/docs/api-reference/responses) 时才支持该选项。 + +| 字段 | 类型 | 说明 | +| ----------- | -------- | --------------------------------------------------------------------------- | +| `promptId` | `string` | 提示的唯一标识符。 | +| `version` | `string` | 你希望使用的提示版本。 | +| `variables` | `object` | 要替换进提示中的键/值对。值可以是字符串,或文本、图像、文件等内容输入类型。 | + + + +任何额外的智能体配置(如 tools 或 instructions)都会覆盖你在存储的提示中可能已配置的值。 + +--- + +## 自定义模型提供方 + +实现你自己的提供方很简单——实现 `ModelProvider` 和 `Model`,并将该提供方传给 `Runner` 构造函数: + + + +--- + +## 追踪导出器 + +使用 OpenAI 提供方时,你可以通过提供 API 密钥来选择启用自动追踪导出: + + + +这会将追踪发送到 [OpenAI 控制台](https://platform.openai.com/traces),你可以在其中检查工作流的完整执行图。 + +--- + +## 后续步骤 + +- 探索 [Running Agents](/openai-agents-js/zh/guides/running-agents)。 +- 使用[Tools](/openai-agents-js/zh/guides/tools)为你的模型赋能。 +- 按需添加[Guardrails](/openai-agents-js/zh/guides/guardrails)或[Tracing](/openai-agents-js/zh/guides/tracing)。 diff --git a/docs/src/content/docs/zh/guides/multi-agent.md b/docs/src/content/docs/zh/guides/multi-agent.md new file mode 100644 index 00000000..625ba34c --- /dev/null +++ b/docs/src/content/docs/zh/guides/multi-agent.md @@ -0,0 +1,40 @@ +--- +title: 协调多个智能体 +description: Coordinate the flow between several agents +--- + +编排指的是您应用中智能体的流程。哪些智能体运行、以什么顺序运行,以及它们如何决定接下来发生什么?有两种主要方式来编排智能体: + +1. 让 LLM 做决策:利用 LLM 的智能进行规划、推理,并据此决定采取哪些步骤。 +2. 通过代码进行编排:用您的代码来决定智能体的流程。 + +您可以混合搭配这些模式。它们各有取舍,详见下文。 + +## 基于 LLM 的编排 + +智能体是配备了 instructions、tools 和交接 的 LLM。这意味着面对一个开放式任务时,LLM 可以自主规划如何完成任务,使用 tools 来采取行动和获取数据,并通过交接将任务委派给子智能体。比如,一个研究智能体可以配备如下工具: + +- Web 搜索,用于在网上查找信息 +- 文件搜索与检索,用于在专有数据和连接中查询 +- 计算机操作,用于在计算机上执行动作 +- 代码执行,用于进行数据分析 +- 交接到专门的智能体,这些智能体擅长规划、报告撰写等 + +当任务是开放式且您希望依赖 LLM 的智能时,这种模式非常适合。这里最重要的策略是: + +1. 打磨高质量的提示。明确哪些 tools 可用、如何使用它们,以及必须遵循哪些参数范围。 +2. 监控您的应用并持续迭代。观察问题出现在哪里,并迭代优化提示。 +3. 允许智能体自省和改进。例如,将其置于循环中,让它自我批判;或者提供错误信息,让它改进。 +4. 让专门化的智能体在单一任务上做到出色,而不是依赖一个通用智能体去胜任一切。 +5. 投入到[评测](https://platform.openai.com/docs/guides/evals)。这可以帮助您训练智能体,使其在任务上不断提升。 + +## 基于代码的编排 + +尽管基于 LLM 的编排很强大,基于代码的编排在速度、成本和性能方面更具确定性和可预测性。常见模式包括: + +- 使用[structured outputs](https://platform.openai.com/docs/guides/structured-outputs)生成您可以用代码检查的格式良好的数据。例如,您可以让一个智能体将任务归类为几个类别,然后根据该类别选择下一个智能体。 +- 通过将一个智能体的输出转换为下一个智能体的输入来串联多个智能体。您可以把写一篇博客文章这样的任务分解为一系列步骤:调研、写大纲、撰写正文、批判性审阅,然后改进。 +- 让执行任务的智能体与负责评估并提供反馈的智能体在 `while` 循环中协同运行,直到评估者认为输出满足某些标准为止。 +- 并行运行多个智能体,例如通过 JavaScript 基本组件如 `Promise.all`。当多个任务彼此独立时,这有助于提升速度。 + +我们在[`examples/agent-patterns`](https://github.com/openai/openai-agents-js/tree/main/examples/agent-patterns)中提供了许多代码示例。 diff --git a/docs/src/content/docs/zh/guides/quickstart.mdx b/docs/src/content/docs/zh/guides/quickstart.mdx new file mode 100644 index 00000000..ca9911ca --- /dev/null +++ b/docs/src/content/docs/zh/guides/quickstart.mdx @@ -0,0 +1,159 @@ +--- +title: 快速上手 +description: Create your first AI Agent from scratch +--- + +import { Steps } from '@astrojs/starlight/components'; +import { Code } from '@astrojs/starlight/components'; +import quickstartExample from '../../../../../../examples/docs/quickstart/index.ts?raw'; + +## 项目设置 + + + +1. 创建项目并初始化 npm。这一步只需执行一次。 + + ```bash + mkdir my_project + cd my_project + npm init -y + ``` + +2. 安装 Agents SDK。 + + ```bash + npm install @openai/agents zod@3 + ``` + +3. 设置 OpenAI API 密钥。如果还没有,请按照[这些说明](https://platform.openai.com/docs/quickstart#create-and-export-an-api-key)创建一个 OpenAI API key。 + + ```bash + export OPENAI_API_KEY=sk-... + ``` + + 或者,你也可以调用 `setDefaultOpenAIKey('')` 以编程方式设置密钥,并使用 `setTracingExportApiKey('')` 进行追踪。 + 参见 [Configuring the SDK](/openai-agents-js/zh/guides/config) 了解更多详情。 + + + +## 第一个智能体创建 + +智能体由 instructions 和名称定义。 + +```typescript +import { Agent } from '@openai/agents'; + +const agent = new Agent({ + name: 'History Tutor', + instructions: + 'You provide assistance with historical queries. Explain important events and context clearly.', +}); +``` + +## 第一个智能体运行 + +可以使用 `run` 方法来运行智能体。通过同时传入要启动的智能体以及要传递的输入来触发一次运行。 + +这将返回一个运行结果,其中包含最终输出以及该次运行期间执行的任何操作。 + +```typescript +import { Agent, run } from '@openai/agents'; + +const agent = new Agent({ + name: 'History Tutor', + instructions: + 'You provide assistance with historical queries. Explain important events and context clearly.', +}); + +const result = await run(agent, 'When did sharks first appear?'); + +console.log(result.finalOutput); +``` + +## 智能体工具配置 + +你可以为智能体提供工具,用于查找信息或执行操作。 + +```typescript +import { Agent, tool } from '@openai/agents'; + +const historyFunFact = tool({ + // The name of the tool will be used by the agent to tell what tool to use. + name: 'history_fun_fact', + // The description is used to describe **when** to use the tool by telling it **what** it does. + description: 'Give a fun fact about a historical event', + // This tool takes no parameters, so we provide an empty Zod Object. + parameters: z.object({}), + execute: async () => { + // The output will be returned back to the Agent to use + return 'Sharks are older than trees.'; + }, +}); + +const agent = new Agent({ + name: 'History Tutor', + instructions: + 'You provide assistance with historical queries. Explain important events and context clearly.', + // Adding the tool to the agent + tools: [historyFunFact], +}); +``` + +## 更多智能体添加 + +可以以类似方式定义更多智能体,将问题拆解为更小的部分,使智能体更专注于当前任务。同时,你也可以在智能体上指定所用模型,从而针对不同问题使用不同的模型。 + +```typescript +const historyTutorAgent = new Agent({ + name: 'History Tutor', + instructions: + 'You provide assistance with historical queries. Explain important events and context clearly.', +}); + +const mathTutorAgent = new Agent({ + name: 'Math Tutor', + instructions: + 'You provide help with math problems. Explain your reasoning at each step and include examples', +}); +``` + +## 交接定义 + +为了在多个智能体之间进行编排,你可以为某个智能体定义 `handoffs`。这样,该智能体就可以将对话传递给下一个智能体。这将在一次运行过程中自动发生。 + +运行结束后,你可以通过查看运行结果中的 `finalAgent` 属性来了解是哪一个智能体生成了最终响应。 + +## 智能体编排运行 + +Runner 用于处理各个智能体的执行、可能发生的交接以及工具的执行。 + +```typescript +import { run } from '@openai/agents'; + +async function main() { + const result = await run(triageAgent, 'What is the capital of France?'); + console.log(result.finalOutput); +} + +main().catch((err) => console.error(err)); +``` + +## 综合示例 + +把以上内容整合成一个完整示例。将其放入 `index.js` 文件并运行。 + + + +## 追踪查看 + +Agents SDK 会为你自动生成追踪。这使你能够审阅智能体的运行情况、它们调用了哪些工具、以及它们将对话交接给了哪个智能体。 + +要查看一次智能体运行期间发生的情况,请前往 [OpenAI Dashboard 中的 Trace viewer](https://platform.openai.com/traces)。 + +## 后续步骤 + +了解如何构建更复杂的智能体流程: + +- 了解如何配置 [Agents](/openai-agents-js/zh/guides/agents)。 +- 了解 [Running Agents](/openai-agents-js/zh/guides/running-agents)。 +- 了解 [Tools](/openai-agents-js/zh/guides/tools)、[Guardrails](/openai-agents-js/zh/guides/guardrails) 和 [Models](/openai-agents-js/zh/guides/models)。 diff --git a/docs/src/content/docs/zh/guides/release.mdx b/docs/src/content/docs/zh/guides/release.mdx new file mode 100644 index 00000000..2e16e7ea --- /dev/null +++ b/docs/src/content/docs/zh/guides/release.mdx @@ -0,0 +1,37 @@ +--- +title: 发布流程 +description: Learn how we version and release the SDK and recent changes. +--- + +## 版本管理 + +本项目采用稍作修改的语义化版本形式 `0.Y.Z`。开头的 `0` 表示 SDK 仍在快速演进中。各部分的递增规则如下: + +## 次要(`Y`)版本 + +对于未标记为 beta 的任何公共接口的**破坏性变更**,我们将提升次要版本 `Y`。例如,从 `0.0.x` 升到 `0.1.x` 可能包含破坏性变更。 + +如果不希望出现破坏性变更,建议在项目中固定到 `0.0.x` 版本。 + +## 补丁(`Z`) 版本 + +对于非破坏性变更,我们会递增 `Z`: + +- Bug 修复 +- 新功能 +- 私有接口的变更 +- 对 beta 功能的更新 + +## 子包的版本管理 + +主包 `@openai/agents` 由多个可独立使用的子包组成。目前,各包的版本是联动的,这意味着如果一个包提升了版本,其他包也会随之提升。随着我们推进到 `1.0.0`,这一策略可能会改变。 + +## 更新日志 + +我们为每个子包生成更新日志,帮助理解发生了哪些变更。由于变更可能发生在某个子包中,您可能需要查阅对应的更新日志以获取变更的详细信息。 + +- [`@openai/agents`](https://github.com/openai/openai-agents-js/blob/main/packages/agents/CHANGELOG.md) +- [`@openai/agents-core`](https://github.com/openai/openai-agents-js/blob/main/packages/agents-core/CHANGELOG.md) +- [`@openai/agents-extensions`](https://github.com/openai/openai-agents-js/blob/main/packages/agents-extensions/CHANGELOG.md) +- [`@openai/agents-openai`](https://github.com/openai/openai-agents-js/blob/main/packages/agents-openai/CHANGELOG.md) +- [`@openai/agents-realtime`](https://github.com/openai/openai-agents-js/blob/main/packages/agents-realtime/CHANGELOG.md) diff --git a/docs/src/content/docs/zh/guides/results.mdx b/docs/src/content/docs/zh/guides/results.mdx new file mode 100644 index 00000000..0d570e3e --- /dev/null +++ b/docs/src/content/docs/zh/guides/results.mdx @@ -0,0 +1,89 @@ +--- +title: 结果 +description: Learn how to access the results and output from your agent run +--- + +import { Code } from '@astrojs/starlight/components'; +import handoffFinalOutputTypes from '../../../../../../examples/docs/results/handoffFinalOutputTypes.ts?raw'; +import historyLoop from '../../../../../../examples/docs/results/historyLoop.ts?raw'; + +当您在[Running Agents](/openai-agents-js/zh/guides/running-agents)中运行智能体时,您将会收到: + +- [`RunResult`](/openai-agents-js/openai/agents/classes/runresult):如果在调用 `run` 时未设置 `stream: true` +- [`StreamedRunResult`](/openai-agents-js/openai/agents/classes/streamedrunresult):如果在调用 `run` 时设置了 `stream: true`。有关流式传输的详细信息,请参阅[Streaming](/openai-agents-js/zh/guides/streaming)。 + +## 最终输出 + +`finalOutput` 属性包含最后一个运行的智能体的最终输出。该结果可以是: + +- `string` — 对于未定义 `outputType` 的任何智能体的默认类型 +- `unknown` — 如果智能体将 JSON 模式定义为输出类型。在这种情况下,JSON 已解析,但您仍需手动验证其类型。 +- `z.infer` — 如果智能体将 Zod 模式定义为输出类型。输出会自动根据该模式进行解析。 +- `undefined` — 如果智能体未产生输出(例如在产生输出之前就停止) + +如果您在使用具有不同输出类型的交接,应该使用 `Agent.create()` 方法而不是 `new Agent()` 构造函数来创建智能体。 + +这将使 SDK 能够在所有可能的交接之间推断输出类型,并为 `finalOutput` 属性提供联合类型。 + +例如: + + + +## 下一轮的输入 + +您有两种方式可以获取下一轮的输入: + +- `result.history` — 包含您的输入和智能体输出的副本。 +- `result.output` — 包含整个智能体运行的输出。 + +在类似聊天的用例中,`history` 是维护完整历史记录的一种便捷方式: + + + +## 最后一个智能体 + +`lastAgent` 属性包含最后一个运行的智能体。根据您的应用程序,这通常对下一次用户输入很有用。例如,如果您有一个前线分诊智能体会把任务交接给特定语言的智能体,您可以存储最后一个智能体,并在下次用户向智能体发送消息时重用它。 + +在流式传输模式下,访问 `currentAgent` 属性也很有用,它映射到当前正在运行的智能体。 + +## 新增项 + +`newItems` 属性包含运行期间生成的新项。这些项是 [`RunItem`](/openai-agents-js/openai/agents/type-aliases/runitem)s。运行项会封装由 LLM 生成的原始项。除了获取 LLM 的输出外,还可据此了解这些事件关联的是哪个智能体。 + +- [`RunMessageOutputItem`](/openai-agents-js/openai/agents/classes/runmessageoutputitem) 表示来自 LLM 的消息。原始项是生成的消息。 +- [`RunHandoffCallItem`](/openai-agents-js/openai/agents/classes/runhandoffcallitem) 表示 LLM 调用了交接工具。原始项是来自 LLM 的工具调用项。 +- [`RunHandoffOutputItem`](/openai-agents-js/openai/agents/classes/runhandoffoutputitem) 表示发生了交接。原始项是对交接工具调用的工具响应。您还可以从该项访问源/目标智能体。 +- [`RunToolCallItem`](/openai-agents-js/openai/agents/classes/runtoolcallitem) 表示 LLM 调用了某个工具。 +- [`RunToolCallOutputItem`](/openai-agents-js/openai/agents/classes/runtoolcalloutputitem) 表示某个工具被调用。原始项是工具响应。您也可以从该项访问工具输出。 +- [`RunReasoningItem`](/openai-agents-js/openai/agents/classes/runreasoningitem) 表示来自 LLM 的推理项。原始项是生成的推理内容。 +- [`RunToolApprovalItem`](/openai-agents-js/openai/agents/classes/runtoolapprovalitem) 表示 LLM 请求对某个工具调用进行批准。原始项是来自 LLM 的工具调用项。 + +## 状态 + +`state` 属性包含本次运行的状态。大多数附加到 `result` 的信息都源自 `state`,但 `state` 可序列化/反序列化,并且在需要[从错误中恢复](/openai-agents-js/zh/guides/running-agents#exceptions)或处理[`interruption`](#interruptions)时,也可作为后续调用 `run` 的输入。 + +## 中断 + +如果您在智能体中使用了 `needsApproval`,则 `run` 可能会触发一些需要您在继续之前处理的 `interruptions`。在这种情况下,`interruptions` 将是导致中断的 `ToolApprovalItem`s 数组。请查看[Human-in-the-loop](/openai-agents-js/zh/guides/human-in-the-loop)了解如何处理中断的更多信息。 + +## 其他信息 + +### 原始响应 + +`rawResponses` 属性包含智能体运行期间由模型生成的原始 LLM 响应。 + +### 最后一个响应 ID + +`lastResponseId` 属性包含智能体运行期间模型生成的最后一个响应的 ID。 + +### 护栏结果 + +如果存在,`inputGuardrailResults` 和 `outputGuardrailResults` 属性包含护栏的结果。护栏结果有时包含您希望记录或存储的有用信息,因此我们将其提供给您。 + +### 原始输入 + +`input` 属性包含您传递给 run 方法的原始输入。在大多数情况下您不需要它,但在需要时可以使用。 diff --git a/docs/src/content/docs/zh/guides/running-agents.mdx b/docs/src/content/docs/zh/guides/running-agents.mdx new file mode 100644 index 00000000..df9c869a --- /dev/null +++ b/docs/src/content/docs/zh/guides/running-agents.mdx @@ -0,0 +1,125 @@ +--- +title: 运行智能体 +description: Configure and execute agent workflows with the Runner class +--- + +import { Aside, Code } from '@astrojs/starlight/components'; +import helloWorldWithRunnerExample from '../../../../../../examples/docs/hello-world-with-runner.ts?raw'; +import helloWorldExample from '../../../../../../examples/docs/hello-world.ts?raw'; +import runningAgentsExceptionExample from '../../../../../../examples/docs/running-agents/exceptions1.ts?raw'; +import chatLoopExample from '../../../../../../examples/docs/running-agents/chatLoop.ts?raw'; + +智能体本身不会做任何事——您需要使用 `Runner` 类或 `run()` 工具来**运行**它们。 + + + +当您不需要自定义 runner 时,也可以使用 `run()` 工具,它会运行一个单例的默认 `Runner` 实例。 + +或者,您可以创建自己的 `Runner` 实例: + + + +在运行完您的智能体后,您将收到一个 [Results](/openai-agents-js/zh/guides/results) 对象,其中包含最终输出和完整的运行历史。 + +## 智能体循环 + +当您在 Runner 中使用 run 方法时,您需要传入一个起始智能体和输入。输入可以是字符串(视为用户消息),也可以是输入项列表,这些输入项与 OpenAI Responses API 中的项目一致。 + +随后 Runner 会执行一个循环: + +1. 使用当前输入调用当前智能体的模型。 +2. 检查 LLM 响应。 + - **最终输出** → 返回。 + - **交接** → 切换到新智能体,保留累积的会话历史,回到 1。 + - **工具调用** → 执行工具,将其结果追加到会话中,回到 1。 +3. 一旦达到 `maxTurns`,抛出 [`MaxTurnsExceededError`](/openai-agents-js/openai/agents-core/classes/maxturnsexceedederror)。 + + + +### Runner 生命周期 + +在应用启动时创建一个 `Runner` 并在请求之间复用。该实例会存储全局配置,例如模型提供方和追踪选项。只有在需要完全不同的设置时才创建另一个 `Runner`。对于简单脚本,您也可以直接调用 `run()`,它会在内部使用默认 runner。 + +## 运行参数 + +`run()` 方法的输入包括用于启动运行的初始智能体、此次运行的输入,以及一组选项。 + +输入可以是字符串(视为用户消息)、[input items](/openai-agents-js/openai/agents-core/type-aliases/agentinputitem) 列表,或者在构建[Human-in-the-loop](/openai-agents-js/zh/guides/human-in-the-loop) 智能体时使用的 [`RunState`](/openai-agents-js/openai/agents-core/classes/runstate) 对象。 + +附加选项包括: + +| 选项 | 默认值 | 描述 | +| ---------- | ------- | ---------------------------------------------------------------------------------------------------------------------- | +| `stream` | `false` | 若为 `true`,调用将返回 `StreamedRunResult`,并在模型产生事件时逐步发出。 | +| `context` | – | 转发到每个工具 / 护栏 / 交接的上下文对象。详见[Context management](/openai-agents-js/zh/guides/context)。 | +| `maxTurns` | `10` | 安全上限——达到后会抛出 [`MaxTurnsExceededError`](/openai-agents-js/openai/agents-core/classes/maxturnsexceedederror)。 | +| `signal` | – | 用于取消的 `AbortSignal`。 | + +## 流式传输 + +流式传输允许您在 LLM 运行时额外接收流事件。一旦流开始,`StreamedRunResult` 将包含关于此次运行的完整信息,包括所有新产生的输出。您可以使用 `for await` 循环迭代这些流事件。更多内容请参阅[Streaming](/openai-agents-js/zh/guides/streaming)。 + +## 运行配置 + +如果您要创建自己的 `Runner` 实例,可以传入一个 `RunConfig` 对象来配置该 runner。 + +| 字段 | 类型 | 用途 | +| --------------------------- | --------------------- | -------------------------------------------------------- | +| `model` | `string \| Model` | 为运行中的**所有**智能体强制指定某个模型。 | +| `modelProvider` | `ModelProvider` | 解析模型名称——默认使用 OpenAI 提供方。 | +| `modelSettings` | `ModelSettings` | 全局调参参数,会覆盖每个智能体的设置。 | +| `handoffInputFilter` | `HandoffInputFilter` | 在执行交接时修改输入项(如果交接本身尚未定义的话)。 | +| `inputGuardrails` | `InputGuardrail[]` | 应用于*初始*用户输入的护栏。 | +| `outputGuardrails` | `OutputGuardrail[]` | 应用于*最终*输出的护栏。 | +| `tracingDisabled` | `boolean` | 完全禁用 OpenAI 追踪。 | +| `traceIncludeSensitiveData` | `boolean` | 将 LLM/工具的输入与输出从追踪中排除,同时仍然生成 span。 | +| `workflowName` | `string` | 显示在 Traces 仪表盘中——用于帮助对相关运行分组。 | +| `traceId` / `groupId` | `string` | 手动指定 trace 或 group ID,而不是让 SDK 自动生成。 | +| `traceMetadata` | `Record` | 附加到每个 span 的任意元数据。 | + +## 会话 / 聊天线程 + +每次调用 `runner.run()`(或 `run()` 工具)代表应用层会话中的一个**轮次**。您可以自行决定向终端用户展示多少 `RunResult` 内容——有时只展示 `finalOutput`,有时展示每一个生成的项目。 + + + +参见[聊天示例](https://github.com/openai/openai-agents-js/tree/main/examples/basic/chat.ts)获取一个交互式版本。 + +## 异常 + +SDK 会抛出一小组可供捕获的错误: + +- [`MaxTurnsExceededError`](/openai-agents-js/openai/agents-core/classes/maxturnsexceedederror) – 达到 `maxTurns`。 +- [`ModelBehaviorError`](/openai-agents-js/openai/agents-core/classes/modelbehaviorerror) – 模型产生了无效输出(例如格式错误的 JSON、未知工具)。 +- [`InputGuardrailTripwireTriggered`](/openai-agents-js/openai/agents-core/classes/inputguardrailtripwiretriggered) / [`OutputGuardrailTripwireTriggered`](/openai-agents-js/openai/agents-core/classes/outputguardrailtripwiretriggered) – 违反护栏。 +- [`GuardrailExecutionError`](/openai-agents-js/openai/agents-core/classes/guardrailexecutionerror) – 护栏执行失败。 +- [`ToolCallError`](/openai-agents-js/openai/agents-core/classes/toolcallerror) – 任一函数工具调用失败。 +- [`UserError`](/openai-agents-js/openai/agents-core/classes/usererror) – 基于配置或用户输入抛出的任意错误。 + +以上错误均继承自基础的 `AgentsError` 类,该类可能提供 `state` 属性用于访问当前运行状态。 + +下面是一个处理 `GuardrailExecutionError` 的代码示例: + + + +运行上述示例时,您将看到如下输出: + +``` +Guardrail execution failed: Error: Input guardrail failed to complete: Error: Something is wrong! +Math homework guardrail tripped +``` + +--- + +## 后续步骤 + +- 了解如何[Models](/openai-agents-js/zh/guides/models)。 +- 为您的智能体提供[Tools](/openai-agents-js/zh/guides/tools)。 +- 添加用于生产的[Guardrails](/openai-agents-js/zh/guides/guardrails)或[Tracing](/openai-agents-js/zh/guides/tracing)。 diff --git a/docs/src/content/docs/zh/guides/streaming.mdx b/docs/src/content/docs/zh/guides/streaming.mdx new file mode 100644 index 00000000..0112765e --- /dev/null +++ b/docs/src/content/docs/zh/guides/streaming.mdx @@ -0,0 +1,132 @@ +--- +title: 流式传输 +description: Stream agent output in real time using the Runner +--- + +import { Code } from '@astrojs/starlight/components'; +import basicStreamingExample from '../../../../../../examples/docs/streaming/basicStreaming.ts?raw'; +import nodeTextStreamExample from '../../../../../../examples/docs/streaming/nodeTextStream.ts?raw'; +import handleAllEventsExample from '../../../../../../examples/docs/streaming/handleAllEvents.ts?raw'; +import streamedHITLExample from '../../../../../../examples/docs/streaming/streamedHITL.ts?raw'; + +Agents SDK 可以逐步输出来自模型和其他执行步骤的结果。流式传输可保持 UI 响应,避免在更新用户之前等待整个最终结果。 + +## 启用流式传输 + +向 `Runner.run()` 传入 `{ stream: true }` 选项,可获得一个流式对象,而不是完整结果: + + + +启用流式传输后,返回的 `stream` 实现了 `AsyncIterable` 接口。每个产出的事件都是一个对象,用于描述运行期间发生的情况。该流会产出三种事件类型之一,每种类型描述智能体执行的不同部分。大多数应用只需要模型的文本,因此流也提供了辅助方法。 + +### 获取文本输出 + +调用 `stream.toTextStream()` 获取已发出的文本流。当 `compatibleWithNodeStreams` 为 `true` 时,返回值是常规的 Node.js `Readable`。我们可以将其直接管道到 `process.stdout` 或其他目标位置。 + + + +当运行以及所有待处理的回调完成后,`stream.completed` Promise 会被 resolve。如果你想确保不会再有输出,请务必等待它完成。 + +### 监听所有事件 + +你可以使用 `for await` 循环在事件到达时逐个检查。可用信息包括底层模型事件、任何智能体切换,以及 SDK 特定的运行信息: + + + +参见[流式示例](https://github.com/openai/openai-agents-js/tree/main/examples/agent-patterns/streamed.ts),该脚本完整演示了同时打印纯文本流和原始事件流。 + +## 事件类型 + +该流会产出三种不同的事件类型: + +### raw_model_stream_event + +```ts +type RunRawModelStreamEvent = { + type: 'raw_model_stream_event'; + data: ResponseStreamEvent; +}; +``` + +示例: + +```json +{ + "type": "raw_model_stream_event", + "data": { + "type": "output_text_delta", + "delta": "Hello" + } +} +``` + +### run_item_stream_event + +```ts +type RunItemStreamEvent = { + type: 'run_item_stream_event'; + name: RunItemStreamEventName; + item: RunItem; +}; +``` + +交接示例负载: + +```json +{ + "type": "run_item_stream_event", + "name": "handoff_occurred", + "item": { + "type": "handoff_call", + "id": "h1", + "status": "completed", + "name": "transfer_to_refund_agent" + } +} +``` + +### agent_updated_stream_event + +```ts +type RunAgentUpdatedStreamEvent = { + type: 'agent_updated_stream_event'; + agent: Agent; +}; +``` + +示例: + +```json +{ + "type": "agent_updated_stream_event", + "agent": { + "name": "Refund Agent" + } +} +``` + +## 流式传输中的人工干预 + +流式传输与会暂停执行的交接兼容(例如当某个工具需要批准时)。流对象上的 `interruption` 字段会暴露这些中断,你可以针对每个中断调用 `state.approve()` 或 `state.reject()` 继续执行。再次以 `{ stream: true }` 执行可恢复流式输出。 + + + +一个与用户交互的更完整示例见 +[`human-in-the-loop-stream.ts`](https://github.com/openai/openai-agents-js/tree/main/examples/agent-patterns/human-in-the-loop-stream.ts)。 + +## 提示 + +- 退出前请记得等待 `stream.completed`,以确保所有输出都已刷新。 +- 初始的 `{ stream: true }` 选项仅适用于提供该选项的那次调用。如果你使用 `RunState` 重新运行,必须再次指定该选项。 +- 如果你的应用只关心文本结果,优先使用 `toTextStream()`,以避免处理单独的事件对象。 + +借助流式传输和事件系统,你可以将智能体集成到聊天界面、终端应用,或任何用户能从增量更新中获益的场景中。 diff --git a/docs/src/content/docs/zh/guides/tools.mdx b/docs/src/content/docs/zh/guides/tools.mdx new file mode 100644 index 00000000..924daffd --- /dev/null +++ b/docs/src/content/docs/zh/guides/tools.mdx @@ -0,0 +1,116 @@ +--- +title: 工具 +description: Provide your agents with capabilities via hosted tools or custom function tools +--- + +import { Code } from '@astrojs/starlight/components'; +import toolsFunctionExample from '../../../../../../examples/docs/tools/functionTools.ts?raw'; +import toolsHostedToolsExample from '../../../../../../examples/docs/tools/hostedTools.ts?raw'; +import nonStrictSchemaTools from '../../../../../../examples/docs/tools/nonStrictSchemaTools.ts?raw'; +import agentsAsToolsExample from '../../../../../../examples/docs/tools/agentsAsTools.ts?raw'; +import mcpLocalServer from '../../../../../../examples/docs/tools/mcpLocalServer.ts?raw'; + +工具让智能体**采取行动**——获取数据、调用外部 API、执行代码,甚至使用计算机。JavaScript/TypeScript SDK 支持四种类别: + +1. **托管工具**——在 OpenAI 服务器上与模型并行运行。_(Web 搜索、文件搜索、计算机操作、Code Interpreter、图像生成)_ +2. **函数工具**——使用 JSON 模式包装任意本地函数,使 LLM 可调用。 +3. **作为工具的智能体**——将整个智能体暴露为可调用的工具。 +4. **本地 MCP 服务器**——附加一个在您机器上运行的 Model Context Protocol 服务器。 + +--- + +## 1. 托管工具 + +使用 `OpenAIResponsesModel` 时,您可以添加以下内置工具: + +| 工具 | 类型字符串 | 用途 | +| ----------------------- | -------------------- | -------------------------------- | +| Web search | `'web_search'` | 互联网搜索。 | +| File / retrieval search | `'file_search'` | 查询托管在 OpenAI 上的向量存储。 | +| 计算机操作 | `'computer'` | 自动化 GUI 交互。 | +| Code Interpreter | `'code_interpreter'` | 在沙箱环境中运行代码。 | +| 图像生成 | `'image_generation'` | 根据文本生成图像。 | + + + +确切的参数集合与 OpenAI Responses API 保持一致——高级选项如 `rankingOptions` 或语义过滤器,请参阅官方文档。 + +--- + +## 2. 函数工具 + +借助 `tool()` 辅助函数,您可以将**任意**函数变成工具。 + + + +### 选项参考 + +| 字段 | 是否必需 | 说明 | +| --------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `name` | 否 | 默认为函数名(例如,`get_weather`)。 | +| `description` | 是 | 展示给 LLM 的清晰、可读的人类描述。 | +| `parameters` | 是 | 可以是 Zod 模式,或原始 JSON 模式对象。使用 Zod 参数会自动启用**严格**模式。 | +| `strict` | 否 | 当 `true`(默认)时,如果参数未通过校验,SDK 会返回模型错误。将其设为 `false` 可进行模糊匹配。 | +| `execute` | 是 | `(args, context) => string \| Promise`– 您的业务逻辑。可选的第二个参数为`RunContext`。 | +| `errorFunction` | 否 | 自定义处理器 `(context, error) => string`,用于将内部错误转换为用户可见的字符串。 | + +### 非严格 JSON 模式工具 + +如果您需要模型对无效或部分输入进行“猜测”,在使用原始 JSON 模式时可以禁用严格模式: + + + +--- + +## 3. 作为工具的智能体 + +有时您希望某个智能体在不完全进行对话交接的情况下帮助另一个智能体。使用 `agent.asTool()`: + + + +在底层,SDK 会: + +- 创建一个仅含 `input` 参数的函数工具。 +- 在调用该工具时,使用该输入运行子智能体。 +- 返回最后一条消息,或由 `customOutputExtractor` 提取的输出。 + +--- + +## 4. 本地 MCP 服务器 + +您可以通过本地 [Model Context Protocol](https://modelcontextprotocol.io/) 服务器暴露工具,并将其附加到智能体。使用 `MCPServerStdio` 来启动并连接到该服务器: + + + +完整示例参见 [`filesystem-example.ts`](https://github.com/openai/openai-agents-js/tree/main/examples/mcp/filesystem-example.ts)。 + +--- + +## 工具使用行为 + +有关控制模型何时以及如何必须使用工具(`tool_choice`、`toolUseBehavior` 等),请参见[Agents](/openai-agents-js/zh/guides/agents#forcing-tool-use)。 + +--- + +## 最佳实践 + +- **简短且明确的描述**——说明工具做什么以及何时使用。 +- **验证输入**——尽可能使用 Zod 模式进行严格的 JSON 校验。 +- **避免在错误处理器中产生副作用**——`errorFunction` 应返回有用的字符串,而不是抛出异常。 +- **单一职责的工具**——小而可组合的工具有助于模型更好地推理。 + +--- + +## 后续步骤 + +- 了解 [Agents](/openai-agents-js/zh/guides/agents#forcing-tool-use) 中的强制使用工具。 +- 添加 [Guardrails](/openai-agents-js/zh/guides/guardrails) 以验证工具的输入或输出。 +- 深入查阅 [`tool()`](/openai-agents-js/openai/agents/functions/tool) 以及各种托管工具类型的 TypeDoc 参考。 diff --git a/docs/src/content/docs/zh/guides/tracing.mdx b/docs/src/content/docs/zh/guides/tracing.mdx new file mode 100644 index 00000000..487c8a2e --- /dev/null +++ b/docs/src/content/docs/zh/guides/tracing.mdx @@ -0,0 +1,112 @@ +--- +title: 追踪 +description: Learn how to trace your agent runs +--- + +import { Aside, Code } from '@astrojs/starlight/components'; +import customTraceExample from '../../../../../../examples/docs/custom-trace.ts?raw'; +import cloudflareWorkers from '../../../../../../examples/docs/tracing/cloudflareWorkers.ts?raw'; + +Agents SDK 内置了追踪功能,可在智能体运行期间收集全面的事件记录:LLM 生成、工具调用、交接、护栏,甚至自定义事件。通过 [Traces 仪表板](https://platform.openai.com/traces),您可以在开发与生产环境中调试、可视化并监控工作流。 + + + +## 导出循环生命周期 + +在大多数环境中,追踪会按固定间隔自动导出。在浏览器或 Cloudflare Workers 中,此功能默认禁用。当排队的追踪过多时仍会触发导出,但不会按固定间隔导出。相应地,您应使用 `getGlobalTraceProvider().forceFlush()` 将导出作为代码生命周期的一部分手动执行。 + +例如,在 Cloudflare Worker 中,应将代码包装在 `try/catch/finally` 块里,并结合 `waitUntil` 调用强制刷新,以确保在 worker 退出前导出追踪。 + + + +## 追踪与跨度 + +- **追踪(Traces)** 表示一次“工作流”的端到端操作。它由多个跨度(Spans)组成。追踪具有以下属性: + - `workflow_name`:逻辑上的工作流或应用名称。例如 “代码生成” 或 “客户服务”。 + - `trace_id`:追踪的唯一 ID。如果未传入会自动生成。必须匹配格式 `trace_<32_alphanumeric>`。 + - `group_id`:可选的分组 ID,用于关联来自同一会话的多个追踪。例如可使用聊天线程 ID。 + - `disabled`:若为 True,则不会记录该追踪。 + - `metadata`:追踪的可选元数据。 +- **跨度(Spans)** 表示具有开始与结束时间的操作。跨度包含: + - `started_at` 与 `ended_at` 时间戳 + - `trace_id`,表示其所属的追踪 + - `parent_id`,指向其父跨度(如有) + - `span_data`,即关于该跨度的信息。例如,`AgentSpanData` 包含关于智能体的信息,`GenerationSpanData` 包含关于 LLM 生成的信息,等等。 + +## 默认追踪 + +默认情况下,SDK 会追踪以下内容: + +- 整个 `run()` 或 `Runner.run()` 被封装在一个 `Trace` 中 +- 每次智能体运行,都会被封装在 `AgentSpan` 中 +- LLM 的生成被封装在 `GenerationSpan` 中 +- 每次函数工具调用都会被封装在 `FunctionSpan` 中 +- 护栏被封装在 `GuardrailSpan` 中 +- 交接被封装在 `HandoffSpan` 中 + +默认情况下,trace 被命名为 "Agent workflow"。如果使用 `withTrace`,您可以设置该名称;或者通过 [`RunConfig.workflowName`](/openai-agents-js/openai/agents-core/type-aliases/runconfig/#workflowname) 配置名称及其他属性。 + +此外,您可以设置[自定义追踪处理器](#custom-tracing-processors),将追踪推送到其他目标(作为替代或附加目的地)。 + +### 语音智能体追踪 + +如果您在默认的 OpenAI Realtime API 下使用 `RealtimeAgent` 与 `RealtimeSession`,追踪将自动在 Realtime API 侧进行,除非您在 `RealtimeSession` 上通过 `tracingDisabled: true` 禁用,或通过 `OPENAI_AGENTS_DISABLE_TRACING` 环境变量禁用。 + +请参阅 [Overview](/openai-agents-js/zh/guides/voice-agents) 了解更多详情。 + +## 更高层级的追踪 + +有时,您可能希望多次调用 `run()` 属于同一个追踪。可将整段代码包裹在 `withTrace()` 中来实现。 + + + +1. 由于两次 `run` 调用都包裹在 `withTrace()` 中,这两次独立运行会属于同一个整体追踪,而不是创建两个追踪。 + +## 创建追踪 + +您可以使用 [`withTrace()`](/openai-agents-js/openai/agents-core/functions/withtrace/) 函数来创建追踪。或者,您也可以使用 `getGlobalTraceProvider().createTrace()` 手动创建一个新追踪,并将其传入 `withTrace()`。 + +当前追踪通过 [Node.js `AsyncLocalStorage`](https://nodejs.org/api/async_context.html#class-asynclocalstorage) 或相应环境的 polyfill 来追踪。这意味着它可自动适配并发场景。 + +## 创建跨度 + +您可以使用各类 `create*Span()` 方法(如 `createGenerationSpan()`、`createFunctionSpan()` 等)来创建跨度。一般来说,无需手动创建跨度。可使用 [`createCustomSpan()`](/openai-agents-js/openai/agents-core/functions/createcustomspan/) 记录自定义跨度信息。 + +跨度会自动归属到当前追踪,并嵌套在最近的当前跨度之下;当前跨度通过 [Node.js `AsyncLocalStorage`](https://nodejs.org/api/async_context.html#class-asynclocalstorage) 或相应环境的 polyfill 来追踪。 + +## 敏感数据 + +某些跨度可能会捕获潜在的敏感数据。 + +`createGenerationSpan()` 会存储 LLM 生成的输入/输出,`createFunctionSpan()` 会存储函数调用的输入/输出。这些可能包含敏感数据,因此您可以通过 [`RunConfig.traceIncludeSensitiveData +`](/openai-agents-js/openai/agents-core/type-aliases/runconfig/#traceincludesensitivedata) 禁用对这些数据的捕获。 + +## 自定义追踪处理器 + +追踪的高层架构如下: + +- 在初始化时,我们会创建全局 [`TraceProvider`](/openai-agents-js/openai/agents-core/classes/traceprovider),负责创建追踪,并可通过 [`getGlobalTraceProvider()`](/openai-agents-js/openai/agents-core/functions/getglobaltraceprovider/) 访问。 +- 我们为 `TraceProvider` 配置一个 [`BatchTraceProcessor`](/openai-agents-js/openai/agents-core/classes/batchtraceprocessor/),它会将追踪/跨度成批发送给 [`OpenAITracingExporter`](/openai-agents-js/openai/agents-openai/classes/openaitracingexporter/),由其将跨度与追踪成批导出到 OpenAI 后端。 + +若要自定义该默认配置,将追踪发送到替代或附加的后端,或修改导出器行为,您有两种选择: + +1. [`addTraceProcessor()`](/openai-agents-js/openai/agents-core/functions/addtraceprocessor) 允许添加**额外**的追踪处理器,该处理器会在追踪与跨度就绪时接收它们。这样除了将追踪发送至 OpenAI 后端外,您还可执行自定义处理。 +2. [`setTraceProcessors()`](/openai-agents-js/openai/agents-core/functions/settraceprocessors) 允许**替换**默认处理器为您自己的追踪处理器。这意味着除非包含一个会将数据发送到 OpenAI 后端的 `TracingProcessor`,否则追踪将不会发送到 OpenAI 后端。 + +## 外部追踪处理器列表 + +- [AgentOps](https://docs.agentops.ai/v2/usage/typescript-sdk#openai-agents-integration) +- [Keywords AI](https://docs.keywordsai.co/integration/development-frameworks/openai-agents-sdk-js) diff --git a/docs/src/content/docs/zh/guides/troubleshooting.mdx b/docs/src/content/docs/zh/guides/troubleshooting.mdx new file mode 100644 index 00000000..3f1bf99c --- /dev/null +++ b/docs/src/content/docs/zh/guides/troubleshooting.mdx @@ -0,0 +1,40 @@ +--- +title: 故障排除 +description: Learn how to troubleshoot issues with the OpenAI Agents SDK. +--- + +## 支持的环境 + +OpenAI Agents SDK 在以下服务器环境中受支持: + +- Node.js 22+ +- Deno 2.35+ +- Bun 1.2.5+ + +### 有限支持 + +- **Cloudflare Workers**:可以在 Cloudflare Workers 中使用 Agents SDK,但目前存在一些限制: + - SDK 当前需要启用 `nodejs_compat` + - 在请求结束时需要手动刷新追踪数据。有关更多详细信息,请参见 [Tracing](/openai-agents-js/zh/guides/tracing#export-loop-lifecycle)。 + - 由于 Cloudflare Workers 对 `AsyncLocalStorage` 的支持有限,部分追踪可能不够准确 +- **浏览器**: + - 目前在浏览器中不支持追踪 +- **v8 isolates**: + - 如果使用带有合适浏览器 polyfill 的打包工具,应该可以为 v8 isolates 打包该 SDK,但追踪将无法工作 + - v8 isolates 尚未经过广泛测试 + +## 调试日志 + +如果在使用 SDK 时遇到问题,可以启用调试日志以获取更多运行信息。 + +通过将 `DEBUG` 环境变量设置为 `openai-agents:*` 来启用调试日志。 + +```bash +DEBUG=openai-agents:* +``` + +或者,您可以将调试限定到 SDK 的特定部分: + +- `openai-agents:core` — 对 SDK 的主要执行逻辑 +- `openai-agents:openai` — 针对 OpenAI API 调用 +- `openai-agents:realtime` — 针对实时智能体组件 diff --git a/docs/src/content/docs/zh/guides/voice-agents.mdx b/docs/src/content/docs/zh/guides/voice-agents.mdx new file mode 100644 index 00000000..1959a98d --- /dev/null +++ b/docs/src/content/docs/zh/guides/voice-agents.mdx @@ -0,0 +1,51 @@ +--- +title: 语音智能体 +description: Build realtime voice assistants using RealtimeAgent and RealtimeSession +--- + +import { Aside, Code, LinkCard } from '@astrojs/starlight/components'; +import createAgentExample from '../../../../../../examples/docs/voice-agents/createAgent.ts?raw'; +import multiAgentsExample from '../../../../../../examples/docs/voice-agents/multiAgents.ts?raw'; +import createSessionExample from '../../../../../../examples/docs/voice-agents/createSession.ts?raw'; +import configureSessionExample from '../../../../../../examples/docs/voice-agents/configureSession.ts?raw'; +import handleAudioExample from '../../../../../../examples/docs/voice-agents/handleAudio.ts?raw'; +import defineToolExample from '../../../../../../examples/docs/voice-agents/defineTool.ts?raw'; +import toolApprovalEventExample from '../../../../../../examples/docs/voice-agents/toolApprovalEvent.ts?raw'; +import guardrailsExample from '../../../../../../examples/docs/voice-agents/guardrails.ts?raw'; +import guardrailSettingsExample from '../../../../../../examples/docs/voice-agents/guardrailSettings.ts?raw'; +import audioInterruptedExample from '../../../../../../examples/docs/voice-agents/audioInterrupted.ts?raw'; +import sessionInterruptExample from '../../../../../../examples/docs/voice-agents/sessionInterrupt.ts?raw'; +import sessionHistoryExample from '../../../../../../examples/docs/voice-agents/sessionHistory.ts?raw'; +import historyUpdatedExample from '../../../../../../examples/docs/voice-agents/historyUpdated.ts?raw'; +import updateHistoryExample from '../../../../../../examples/docs/voice-agents/updateHistory.ts?raw'; +import customWebRTCTransportExample from '../../../../../../examples/docs/voice-agents/customWebRTCTransport.ts?raw'; +import websocketSessionExample from '../../../../../../examples/docs/voice-agents/websocketSession.ts?raw'; +import transportEventsExample from '../../../../../../examples/docs/voice-agents/transportEvents.ts?raw'; +import thinClientExample from '../../../../../../examples/docs/voice-agents/thinClient.ts?raw'; + +![Realtime Agents](https://cdn.openai.com/API/docs/images/diagram-speech-to-speech.png) + +语音智能体使用 OpenAI 的语音到语音模型,提供实时语音聊天。这些模型支持音频、文本与工具调用的流式传输,适用于语音/电话客服、移动应用体验以及语音聊天等场景。 + +Voice Agents SDK 为 [OpenAI Realtime API](https://platform.openai.com/docs/guides/realtime) 提供 TypeScript 客户端。 + + + +### 关键特性 + +- 通过 WebSocket 或 WebRTC 连接 +- 可在浏览器端和后端连接中使用 +- 音频与打断处理 +- 通过交接进行多智能体编排 +- 工具定义与调用 +- 自定义护栏用于监控模型输出 +- 流式传输事件回调 +- 文本与语音智能体复用同一套组件 + +通过使用语音到语音模型,我们可以利用模型实时处理音频的能力,无需在模型执行后将语音转录为文本并再转换回音频。 + +![语音到语音模型](https://cdn.openai.com/API/docs/images/diagram-chained-agent.png) diff --git a/docs/src/content/docs/zh/guides/voice-agents/build.mdx b/docs/src/content/docs/zh/guides/voice-agents/build.mdx new file mode 100644 index 00000000..beb96493 --- /dev/null +++ b/docs/src/content/docs/zh/guides/voice-agents/build.mdx @@ -0,0 +1,163 @@ +--- +title: 构建语音智能体 +description: Learn how to build voice agents using the OpenAI Agents SDK, what features are available, how to architecture your application, and more. +--- + +import { Steps, Aside, Code } from '@astrojs/starlight/components'; +import createAgentExample from '../../../../../../../examples/docs/voice-agents/createAgent.ts?raw'; +import multiAgentsExample from '../../../../../../../examples/docs/voice-agents/multiAgents.ts?raw'; +import createSessionExample from '../../../../../../../examples/docs/voice-agents/createSession.ts?raw'; +import configureSessionExample from '../../../../../../../examples/docs/voice-agents/configureSession.ts?raw'; +import handleAudioExample from '../../../../../../../examples/docs/voice-agents/handleAudio.ts?raw'; +import defineToolExample from '../../../../../../../examples/docs/voice-agents/defineTool.ts?raw'; +import toolApprovalEventExample from '../../../../../../../examples/docs/voice-agents/toolApprovalEvent.ts?raw'; +import guardrailsExample from '../../../../../../../examples/docs/voice-agents/guardrails.ts?raw'; +import guardrailSettingsExample from '../../../../../../../examples/docs/voice-agents/guardrailSettings.ts?raw'; +import audioInterruptedExample from '../../../../../../../examples/docs/voice-agents/audioInterrupted.ts?raw'; +import sessionInterruptExample from '../../../../../../../examples/docs/voice-agents/sessionInterrupt.ts?raw'; +import sessionHistoryExample from '../../../../../../../examples/docs/voice-agents/sessionHistory.ts?raw'; +import historyUpdatedExample from '../../../../../../../examples/docs/voice-agents/historyUpdated.ts?raw'; +import updateHistoryExample from '../../../../../../../examples/docs/voice-agents/updateHistory.ts?raw'; +import customWebRTCTransportExample from '../../../../../../../examples/docs/voice-agents/customWebRTCTransport.ts?raw'; +import websocketSessionExample from '../../../../../../../examples/docs/voice-agents/websocketSession.ts?raw'; +import transportEventsExample from '../../../../../../../examples/docs/voice-agents/transportEvents.ts?raw'; +import thinClientExample from '../../../../../../../examples/docs/voice-agents/thinClient.ts?raw'; +import toolHistoryExample from '../../../../../../../examples/docs/voice-agents/toolHistory.ts?raw'; +import sendMessageExample from '../../../../../../../examples/docs/voice-agents/sendMessage.ts?raw'; +import serverAgentExample from '../../../../../../../examples/docs/voice-agents/serverAgent.ts?raw'; +import delegationAgentExample from '../../../../../../../examples/docs/voice-agents/delegationAgent.ts?raw'; +import turnDetectionExample from '../../../../../../../examples/docs/voice-agents/turnDetection.ts?raw'; + +## 音频处理 + +某些传输层(例如默认的 `OpenAIRealtimeWebRTC`)会自动为您处理音频输入和输出。对于其他传输机制(例如 `OpenAIRealtimeWebSocket`),您需要自行处理会话音频: + + + +## 会话配置 + +您可以在构造期间向 [`RealtimeSession`](/openai-agents-js/openai/agents-realtime/classes/realtimesession/) 传递其他选项,或在调用 `connect(...)` 时进行配置。 + + + +这些传输层允许您传入任何与[会话](https://platform.openai.com/docs/api-reference/realtime-client-events/session/update)匹配的参数。 + +对于尚无对应项的新增参数(在 [RealtimeSessionConfig](/openai-agents-js/openai/agents-realtime/type-aliases/realtimesessionconfig/) 中没有匹配的参数),您可以使用 `providerData`。传入 `providerData` 的任何内容都会直接作为 `session` 对象的一部分传递。 + +## 交接 + +与常规智能体类似,您可以使用交接将智能体拆分为多个智能体并在它们之间编排,从而提升智能体的性能并更好地限定问题范围。 + + + +与常规智能体不同,交接在 Realtime Agents 中的行为略有差异。执行交接时,正在进行的会话会被更新为新的智能体配置。因此,智能体会自动访问正在进行的对话历史,并且当前不会应用输入过滤器。 + +此外,这意味着在交接中无法更改 `voice` 或 `model`。您也只能连接到其他 Realtime Agents。如果您需要使用不同的模型,例如像 `o4-mini` 这样的推理模型,可以使用[通过工具进行委派](#delegation-through-tools)。 + +## 工具 + +与常规智能体相同,Realtime Agents 可以调用工具来执行操作。您可以使用与常规智能体相同的 `tool()` 函数来定义工具。 + + + +Realtime Agents 只能使用函数工具,并且这些工具会在与您的 Realtime 会话相同的位置执行。这意味着如果您在浏览器中运行 Realtime 会话,您的工具也会在浏览器中执行。如果需要执行更敏感的操作,您可以在工具内向后端服务器发起 HTTP 请求。 + +在工具执行期间,智能体将无法处理来自用户的新请求。改善体验的一种方式是,让智能体在即将执行工具时进行提示,或使用特定短语为执行工具争取一些时间。 + +### 访问对话历史 + +除了智能体调用特定工具时传入的参数之外,您还可以访问由 Realtime 会话跟踪的当前对话历史的快照。如果您需要基于当前对话状态执行更复杂的操作,或计划[使用工具进行委派](#delegation-through-tools),这将非常有用。 + + + + + +### 工具执行前的审批 + +如果您将工具定义为 `needsApproval: true`,智能体会在执行工具之前发出 `tool_approval_requested` 事件。 + +通过监听此事件,您可以向用户展示一个 UI 以批准或拒绝工具调用。 + + + + + +## 护栏 + +护栏提供了一种方式,用于监测智能体的输出是否违反了一组规则,并可立即切断响应。这些护栏检查会基于智能体响应的转录文本执行,因此要求启用模型的文本输出(默认已启用)。 + +当模型响应返回时,您提供的护栏会异步运行,使您可以基于预定义的分类触发条件(例如“提到某个特定禁用词”)来切断响应。 + +当护栏被触发时,会话会发出 `guardrail_tripped` 事件。该事件还会提供一个包含触发护栏的 `itemId` 的 `details` 对象。 + + + +默认情况下,护栏每 100 个字符运行一次,或在响应文本生成结束时运行一次。由于朗读文本通常更耗时,这意味着在大多数情况下,护栏应能在用户听到之前捕获违规内容。 + +如果您想修改此行为,可以向会话传入一个 `outputGuardrailSettings` 对象。 + + + +## 回合检测 / 语音活动检测 + +Realtime 会话将使用 Realtime API 内置的[语音活动检测模式](https://platform.openai.com/docs/guides/realtime-vad),自动检测用户何时在说话并触发新的回合。 + +您可以通过向会话传入 `turnDetection` 对象来更改语音活动检测模式。 + + + +调整回合检测设置可以帮助校准不必要的打断并处理静默。请查阅[Realtime API 文档以了解不同设置的更多细节](https://platform.openai.com/docs/guides/realtime-vad)。 + +## 中断 + +使用内置的语音活动检测时,打断智能体说话会自动触发智能体基于所听到的内容进行检测并更新其上下文。同时会发出一个 `audio_interrupted` 事件。这可用于立即停止所有音频播放(仅适用于 WebSocket 连接)。 + + + +如果您想执行手动中断,例如在 UI 中提供一个“停止”按钮,可以手动调用 `interrupt()`: + + + +无论采用哪种方式,Realtime 会话都会处理对智能体生成的中断,截断其对已对用户所述内容的认知,并更新历史。 + +如果您使用 WebRTC 连接到智能体,还会清空音频输出。如果您使用 WebSocket,则需要自行通过停止已排队待播放的音频的播放来处理这一点。 + +## 文本输入 + +如果您想向智能体发送文本输入,可以使用 `RealtimeSession` 的 `sendMessage` 方法。 + +这对于让用户以两种模态与智能体交互,或为对话提供额外上下文非常有用。 + + + +## 对话历史管理 + +`RealtimeSession` 会在 `history` 属性中自动管理对话历史: + +您可以使用它向用户渲染历史或对其执行其他操作。由于该历史会在对话过程中持续变化,您可以监听 `history_updated` 事件。 + +如果您想修改历史,例如完全删除一条消息或更新其转录文本,可以使用 `updateHistory` 方法。 + + + +### 限制 + +1. 目前无法在事后更新/更改函数工具调用 +2. 历史中的文本输出需要启用转录与文本模态 +3. 由于中断而被截断的响应没有转录文本 + +## 通过工具委派 + +![通过工具委派](https://cdn.openai.com/API/docs/diagram-speech-to-speech-agent-tools.png) + +通过将对话历史与一次工具调用相结合,您可以将对话委派给另一个后端智能体以执行更复杂的操作,然后将其结果返回给用户。 + + + +下面的代码将会在服务器上执行。本示例通过 Next.js 的 Server Actions 实现。 + + diff --git a/docs/src/content/docs/zh/guides/voice-agents/quickstart.mdx b/docs/src/content/docs/zh/guides/voice-agents/quickstart.mdx new file mode 100644 index 00000000..348fba37 --- /dev/null +++ b/docs/src/content/docs/zh/guides/voice-agents/quickstart.mdx @@ -0,0 +1,129 @@ +--- +title: 语音智能体快速上手 +description: Build your first realtime voice assistant using the OpenAI Agents SDK in minutes. +--- + +import { Steps, Aside, Code } from '@astrojs/starlight/components'; +import helloWorldExample from '../../../../../../../examples/docs/voice-agents/helloWorld.ts?raw'; +import createAgentExample from '../../../../../../../examples/docs/voice-agents/createAgent.ts?raw'; +import multiAgentsExample from '../../../../../../../examples/docs/voice-agents/multiAgents.ts?raw'; +import createSessionExample from '../../../../../../../examples/docs/voice-agents/createSession.ts?raw'; +import configureSessionExample from '../../../../../../../examples/docs/voice-agents/configureSession.ts?raw'; +import handleAudioExample from '../../../../../../../examples/docs/voice-agents/handleAudio.ts?raw'; +import defineToolExample from '../../../../../../../examples/docs/voice-agents/defineTool.ts?raw'; +import toolApprovalEventExample from '../../../../../../../examples/docs/voice-agents/toolApprovalEvent.ts?raw'; +import guardrailsExample from '../../../../../../../examples/docs/voice-agents/guardrails.ts?raw'; +import guardrailSettingsExample from '../../../../../../../examples/docs/voice-agents/guardrailSettings.ts?raw'; +import audioInterruptedExample from '../../../../../../../examples/docs/voice-agents/audioInterrupted.ts?raw'; +import sessionInterruptExample from '../../../../../../../examples/docs/voice-agents/sessionInterrupt.ts?raw'; +import sessionHistoryExample from '../../../../../../../examples/docs/voice-agents/sessionHistory.ts?raw'; +import historyUpdatedExample from '../../../../../../../examples/docs/voice-agents/historyUpdated.ts?raw'; +import updateHistoryExample from '../../../../../../../examples/docs/voice-agents/updateHistory.ts?raw'; +import customWebRTCTransportExample from '../../../../../../../examples/docs/voice-agents/customWebRTCTransport.ts?raw'; +import websocketSessionExample from '../../../../../../../examples/docs/voice-agents/websocketSession.ts?raw'; +import transportEventsExample from '../../../../../../../examples/docs/voice-agents/transportEvents.ts?raw'; +import thinClientExample from '../../../../../../../examples/docs/voice-agents/thinClient.ts?raw'; + + + +0. **创建项目** + + 在本 Quickstart 中,我们将创建一个可在浏览器中使用的语音智能体。如果您想要从一个新项目开始,可以尝试 [`Next.js`](https://nextjs.org/docs/getting-started/installation) 或 [`Vite`](https://vite.dev/guide/installation.html)。 + + ```bash + npm create vite@latest my-project -- --template vanilla-ts + ``` + +1. **安装 Agents SDK** + + ```bash + npm install @openai/agents zod@3 + ``` + + 或者,您也可以安装 `@openai/agents-realtime`,以获取独立的浏览器包。 + +2. **生成客户端临时令牌** + + 由于此应用将运行在用户的浏览器中,我们需要一种安全的方式通过 Realtime API 连接到模型。为此可以使用一种[临时客户端密钥](https://platform.openai.com/docs/guides/realtime#creating-an-ephemeral-token),并应在您的后端服务器上生成。用于测试时,您也可以使用 `curl` 和常规 OpenAI API 密钥生成一个密钥。 + + ```bash + export OPENAI_API_KEY="sk-proj-...(your own key here)" + curl -X POST https://api.openai.com/v1/realtime/client_secrets \ + -H "Authorization: Bearer $OPENAI_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "session": { + "type": "realtime", + "model": "gpt-realtime" + } + }' + ``` + + 响应会在顶层包含一个名为“value”的字符串,并以“ek\_”前缀开头。您可以使用此临时密钥在稍后建立 WebRTC 连接。请注意,此密钥仅在短时间内有效,需要重新生成。 + +3. **创建第一个智能体** + + 创建新的 [`RealtimeAgent`](/openai-agents-js/openai/agents-realtime/classes/realtimeagent/) 与创建常规的 [`Agent`](/openai-agents-js/zh/guides/agents) 非常相似。 + + ```typescript + import { RealtimeAgent } from '@openai/agents-realtime'; + + const agent = new RealtimeAgent({ + name: 'Assistant', + instructions: 'You are a helpful assistant.', + }); + ``` + +4. **创建会话** + + 与常规智能体不同,语音智能体会在一个持续运行并监听的 `RealtimeSession` 中,该会话会随时间处理与模型的对话与连接。该会话还会处理音频处理、打断以及我们稍后会介绍的许多其他生命周期功能。 + + ```typescript + import { RealtimeSession } from '@openai/agents-realtime'; + + const session = new RealtimeSession(agent, { + model: 'gpt-realtime', + }); + ``` + + `RealtimeSession` 构造函数将 `agent` 作为第一个参数。此智能体将是您的用户最先可以与之交互的对象。 + +5. **连接到会话** + + 要连接到会话,您需要传入之前生成的客户端临时令牌。 + + ```typescript + await session.connect({ apiKey: 'ek_...(put your own key here)' }); + ``` + + 这将在浏览器中通过 WebRTC 连接到 Realtime API,并自动为音频输入和输出配置您的麦克风和扬声器。如果您在后端服务器(如 Node.js)上运行 `RealtimeSession`,SDK 将自动使用 WebSocket 作为连接。您可以在[Transport Mechanisms](/openai-agents-js/zh/guides/voice-agents/transport) 指南中了解更多不同的传输层。 + +6. **整合所有内容** + + + +7. **启动并开始对话** + + 启动您的 Web 服务器,访问包含新实时智能体代码的页面。您会看到麦克风访问请求。授权后,您即可开始与智能体对话。 + + ```bash + npm run dev + ``` + + + +## 后续步骤 + +从这里开始,您可以设计并构建自己的语音智能体。语音智能体包含与常规智能体相同的许多功能,同时也有一些独特功能。 + +- 了解如何为语音智能体添加: + - [工具](/openai-agents-js/zh/guides/voice-agents/build#tools) + - [交接](/openai-agents-js/zh/guides/voice-agents/build#handoffs) + - [护栏](/openai-agents-js/zh/guides/voice-agents/build#guardrails) + - [处理音频中断](/openai-agents-js/zh/guides/voice-agents/build#audio-interruptions) + - [管理会话历史](/openai-agents-js/zh/guides/voice-agents/build#session-history) + +- 进一步了解不同的传输层。 + - [WebRTC](/openai-agents-js/zh/guides/voice-agents/transport#connecting-over-webrtc) + - [WebSocket](/openai-agents-js/zh/guides/voice-agents/transport#connecting-over-websocket) + - [构建你自己的传输机制](/openai-agents-js/zh/guides/voice-agents/transport#building-your-own-transport-mechanism) diff --git a/docs/src/content/docs/zh/guides/voice-agents/transport.mdx b/docs/src/content/docs/zh/guides/voice-agents/transport.mdx new file mode 100644 index 00000000..5fd58830 --- /dev/null +++ b/docs/src/content/docs/zh/guides/voice-agents/transport.mdx @@ -0,0 +1,66 @@ +--- +title: 实时传输层 +description: Learn about the different transport layers that can be used with Realtime Agents. +--- + +import { Steps } from '@astrojs/starlight/components'; +import { Code } from '@astrojs/starlight/components'; + +import createAgentExample from '../../../../../../../examples/docs/voice-agents/createAgent.ts?raw'; +import multiAgentsExample from '../../../../../../../examples/docs/voice-agents/multiAgents.ts?raw'; +import createSessionExample from '../../../../../../../examples/docs/voice-agents/createSession.ts?raw'; +import configureSessionExample from '../../../../../../../examples/docs/voice-agents/configureSession.ts?raw'; +import handleAudioExample from '../../../../../../../examples/docs/voice-agents/handleAudio.ts?raw'; +import defineToolExample from '../../../../../../../examples/docs/voice-agents/defineTool.ts?raw'; +import toolApprovalEventExample from '../../../../../../../examples/docs/voice-agents/toolApprovalEvent.ts?raw'; +import guardrailsExample from '../../../../../../../examples/docs/voice-agents/guardrails.ts?raw'; +import guardrailSettingsExample from '../../../../../../../examples/docs/voice-agents/guardrailSettings.ts?raw'; +import audioInterruptedExample from '../../../../../../../examples/docs/voice-agents/audioInterrupted.ts?raw'; +import sessionInterruptExample from '../../../../../../../examples/docs/voice-agents/sessionInterrupt.ts?raw'; +import sessionHistoryExample from '../../../../../../../examples/docs/voice-agents/sessionHistory.ts?raw'; +import historyUpdatedExample from '../../../../../../../examples/docs/voice-agents/historyUpdated.ts?raw'; +import updateHistoryExample from '../../../../../../../examples/docs/voice-agents/updateHistory.ts?raw'; +import customWebRTCTransportExample from '../../../../../../../examples/docs/voice-agents/customWebRTCTransport.ts?raw'; +import websocketSessionExample from '../../../../../../../examples/docs/voice-agents/websocketSession.ts?raw'; +import transportEventsExample from '../../../../../../../examples/docs/voice-agents/transportEvents.ts?raw'; +import thinClientExample from '../../../../../../../examples/docs/voice-agents/thinClient.ts?raw'; + +## 默认传输层 + +### WebRTC 连接 + +默认传输层使用 WebRTC。音频会从麦克风进行录制并自动回放。 + +如果要使用你自己的媒体流或音频元素,请在创建会话时提供一个 `OpenAIRealtimeWebRTC` 实例。 + + + +### WebSocket 连接 + +在创建会话时传入 `transport: 'websocket'` 或提供 `OpenAIRealtimeWebSocket` 的实例,以使用 WebSocket 连接替代 WebRTC。这非常适合服务器端用例,例如使用 Twilio 构建电话智能体。 + + + +使用任意录制/播放库处理原始 PCM16 音频字节。 + +### 自定义传输机制 + +如果你想使用不同的语音到语音 API,或有自己的自定义传输机制,你可以通过实现 `RealtimeTransportLayer` 接口并触发 `RealtimeTransportEventTypes` 事件来创建你自己的实现。 + +## 更直接的 Realtime API 交互 + +如果你想使用 OpenAI Realtime API,但需要更直接地访问 Realtime API,有两种选项: + +### 选项 1 - 访问传输层 + +如果你仍希望受益于 `RealtimeSession` 的全部能力,可以通过 `session.transport` 访问你的传输层。 + +传输层会将其接收到的每个事件以 `*` 事件的形式发出,你也可以使用 `sendEvent()` 方法发送原始事件。 + + + +### 选项 2 — 仅使用传输层 + +如果你不需要自动工具执行、护栏等,也可以将传输层用作仅管理连接和中断的轻量客户端。 + + diff --git a/docs/src/content/docs/zh/index.mdx b/docs/src/content/docs/zh/index.mdx new file mode 100644 index 00000000..4bdddd29 --- /dev/null +++ b/docs/src/content/docs/zh/index.mdx @@ -0,0 +1,61 @@ +--- +title: OpenAI Agents SDK TypeScript +description: The OpenAI Agents SDK for TypeScript enables you to build agentic AI apps in a lightweight, easy-to-use package with very few abstractions. +--- + +import { LinkCard } from '@astrojs/starlight/components'; +import { Code } from '@astrojs/starlight/components'; +import Hero from '../../../components/Hero.astro'; + +import helloWorldExample from '../../../../../examples/docs/hello-world.ts?raw'; + + + 快速上手 + 几分钟内构建您的第一个智能体。 + 开始构建 + + +## 概述 + +[适用于 TypeScript 的 OpenAI Agents SDK](https://github.com/openai/openai-agents-js) +让您能够在一个轻量、易用且抽象极少的包中构建以智能体为核心的 AI 应用。它是我们此前面向智能体的实验项目 +[Swarm](https://github.com/openai/swarm/tree/main) 的面向生产的升级版本,同时[提供 Python 版本](https://github.com/openai/openai-agents-python)。Agents SDK 仅包含一小组基础组件: + +- **Agents**,即配备 instructions 和 tools 的 LLM +- **Handoffs**,允许智能体将特定任务委派给其他智能体 +- **Guardrails**,允许对传入智能体的输入进行验证 + +结合 TypeScript,这些基础组件足以表达 tools 与智能体之间的复杂关系,让您无需陡峭的学习曲线即可构建真实世界的应用。此外,SDK 内置了**追踪**,便于可视化和调试您的智能体流程,并对其进行评估,甚至为您的应用微调模型。 + +## 使用 Agents SDK 的理由 + +该 SDK 的两条核心设计原则: + +1. 功能足够多,值得使用;但基础组件足够少,易于上手。 +2. 开箱即用效果极佳,同时您可以精确自定义执行行为。 + +该 SDK 的主要功能包括: + +- **Agent loop**:内置的智能体循环,负责调用 tools、将结果发送给 LLM,并循环直至 LLM 完成。 +- **TypeScript-first**:利用语言内建特性来编排与串联智能体,而无需学习新的抽象。 +- **Handoffs**:在多个智能体之间进行协调与委派的强大能力。 +- **Guardrails**:与您的智能体并行执行输入验证与检查,若检查失败将提前中止。 +- **Function tools**:将任意 TypeScript 函数转换为工具,自动生成 schema,并基于 Zod 进行验证。 +- **Tracing**:内置追踪,便于可视化、调试和监控您的工作流,并可使用 OpenAI 的评估、微调与蒸馏工具套件。 +- **Realtime Agents**:构建强大的语音智能体,包括自动打断检测、上下文管理、护栏等。 + +## 安装 + +```bash +npm install @openai/agents zod@3 +``` + +## Hello World 示例 + + + +(_如果要运行,请确保设置 `OPENAI_API_KEY` 环境变量_) + +```bash +export OPENAI_API_KEY=sk-... +``` diff --git a/docs/src/scripts/translate.ts b/docs/src/scripts/translate.ts index 6cdc9f07..b44f42b5 100644 --- a/docs/src/scripts/translate.ts +++ b/docs/src/scripts/translate.ts @@ -123,6 +123,7 @@ export async function extractSidebarTranslations( const sourceDir = path.resolve(__dirname, '../../src/content/docs'); const languages: Record = { ja: 'Japanese', + zh: 'Chinese', // Add more languages here }; const OPENAI_MODEL = process.env.OPENAI_MODEL || 'gpt-5'; @@ -180,6 +181,38 @@ const engToNonEngMapping: Record> = { 'ほんの数分ではじめてのエージェントをつくることができます。', "Let's build": 'はじめる', }, + zh: { + agents: '智能体', + 'computer use': '计算机操作', + 'OAI hosted tools': 'OpenAI 托管工具', + 'well formed data': '格式良好的数据', + guardrail: '护栏', + handoffs: '交接', + 'function tools': '函数工具', + tracing: '追踪', + 'code examples': '代码示例', + 'vector store': '向量存储', + 'deep research': '深度研究', + category: '类别', + user: '用户', + parameter: '参数', + processor: '处理器', + server: '服务器', + 'web search': 'Web 搜索', + 'file search': '文件搜索', + streaming: '流式传输', + 'system prompt': '系统提示', + 'TypeScript-first': 'TypeScript 优先', + 'Human in the loop': '人工干预', + 'Hosted tool': '托管工具', + 'Hosted MCP server tools': '远程 MCP 服务器工具', + raw: '原始', + 'Realtime Agents': '实时智能体', + 'Build your first agent in minutes.': '几分钟内构建您的第一个智能体。', + "Let's build": '开始构建', + Overview: '概述', + Quickstart: '快速上手', + }, }; const engToNonEngInstructions: Record = { @@ -194,6 +227,13 @@ const engToNonEngInstructions: Record = { '* You must consistently use polite wording such as です/ます rather than である/なのだ.', "* Don't put 。 at the end for non-sentence bullet points", ], + zh: [ + "* The term 'result' in the Runner guide context must be translated as '运行结果' or '执行结果'", + '* Use clear and concise Chinese expressions, avoiding overly formal or archaic language', + '* For technical terms, prefer commonly accepted Chinese translations over literal translations', + '* Use Chinese punctuation marks appropriately (。,;:""\'\'())', + '* When translating code-related content, maintain consistency with established Chinese programming terminology', + ], }; async function ensureDir(dir: string) { @@ -259,6 +299,12 @@ You must return **only** the translated markdown. Do not include any commentary, - Insert a half‑width space before and after all alphanumeric terms. - Add a half‑width space just outside markdown emphasis markers: \` **bold** \` (good) vs \`** bold **\` (bad). +*(applies only when ${targetLanguage} = Chinese)* +- Use proper Chinese punctuation marks (。,;:""''()) instead of English ones +- For technical terms mixed with Chinese text, add appropriate spacing for readability +- Use simplified Chinese characters consistently +- Follow Chinese grammar and sentence structure patterns + ######################### ## DO NOT TRANSLATE ## ######################### @@ -385,7 +431,13 @@ You must return **only** the translated markdown. Do not include any commentary, ######################### *(applies only when ${targetLanguage} = Japanese)* - Insert a half‑width space before and after all alphanumeric terms. -- Add a half‑width space just outside markdown emphasis markers: \` **bold** \` (good) vs \`** bold **\` (bad). Review this rule again before returning the translated text. +- Add a half‑width space just outside markdown emphasis markers: \` **bold** \` (good) vs \`** bold **\` (bad). + +*(applies only when ${targetLanguage} = Chinese)* +- Use proper Chinese punctuation marks (。,;:""''()) instead of English ones +- For technical terms mixed with Chinese text, add appropriate spacing for readability +- Use simplified Chinese characters consistently +- Follow Chinese grammar and sentence structure patterns Review this rule again before returning the translated text. ######################### ## DO NOT TRANSLATE ##