通过 Comfy Router 使用 Google Gemini
通过 Comfy Router 以 HTTP 方式调用 Google Gemini 文本模型的 Python、TypeScript 和 cURL 代码片段,以及请求字段和返回结果的结构
通过 Comfy Router 使用 Google Gemini
通过 Comfy Router 以 HTTP 方式调用 Google Gemini 文本模型的 Python、TypeScript 和 cURL 代码片段,以及请求字段和返回结果的结构
Google Gemini 的 API 参考。Google Gemini 是 Google 的多模态文本模型系列,在 Flash 和 Pro 各层级中覆盖从快速起草到深度推理的各类场景。
快速开始
在你的 Comfy 工作区中创建一个密钥,并将其导出为 COMFY_API_KEY。Python 和 TypeScript 代码片段使用 Comfy SDK(pip install comfy-sdk 和 npm install @comfyorg/sdk);cURL 代码片段则是通过原始 HTTP 发出的同一调用。
选择你要调用的模型。下面的全部内容,从代码片段到 Schema 和示例,都随你的选择而定。
[tab] Gemini 3.1 Pro 模型 ID:vertexai/gemini-3.1-pro-preview端点:POST https://api.comfy.org/v2/models/vertexai/gemini-3.1-pro-preview> [tab] 等待结果 > > ``python Python theme={null} > import asyncio > from comfy_sdk import AsyncComfy > > # Reads COMFY_API_KEY from the environment. > # The SDK automatically creates an idempotency key and reuses it for automatic retries. > async def main(): > async with AsyncComfy() as client: > result = await client.models.run( > "vertexai/gemini-3.1-pro-preview", > { > "contents": [ > { > "role": "user", > "parts": [ > { > "text": "Describe a single red maple leaf on a white background in one sentence.", > }, > ], > }, > ], > "generationConfig": { > "temperature": 0.7, > "maxOutputTokens": 256, > }, > }, > ) > > print("text:", result["candidates"][0]["content"]["parts"][0]["text"]) > > asyncio.run(main()) >`> >`typescript TypeScript theme={null} > import { comfy } from "@comfyorg/sdk"; > > // Reads COMFY_API_KEY from the environment. > // The SDK automatically creates an idempotency key and reuses it for automatic retries. > type Result = { candidates: { content: { parts: { text: string }[] } }[] }; > const result = await comfy.models.run<Result>("vertexai/gemini-3.1-pro-preview", { > contents: [ > { > role: "user", > parts: [ > { > text: "Describe a single red maple leaf on a white background in one sentence.", > }, > ], > }, > ], > generationConfig: { > temperature: 0.7, > maxOutputTokens: 256, > }, > }); > if (result.kind !== "json") throw new Error("expected a JSON result"); > > console.log("text:", result.data.candidates[0].content.parts[0].text); >`> >`bash cURL theme={null} > curl https://api.comfy.org/v2/models/vertexai/gemini-3.1-pro-preview \ > -H "X-API-Key: $COMFY_API_KEY" \ > -H "Idempotency-Key: $(uuidgen)" \ > -H "Content-Type: application/json" \ > -d "{\"contents\": [{\"role\":\"user\",\"parts\":[{\"text\":\"Describe a single red maple leaf on a white background in one sentence.\"}]}], \"generationConfig\": {\"temperature\":0.7,\"maxOutputTokens\":256}}" >`> [tab] 排队并稍后收集 > > 将相同的请求体发送到POST https://api.comfy.org/v2/models/vertexai/gemini-3.1-pro-preview/requests。Router 会在运行被受理后立即返回201和request_id,结果就绪后即可从本进程或其他进程收集。[队列投递](https://docs.comfy.org/zh/development/comfy-router/queue.md)详细介绍了状态查询、取消和结果收集。 > >`python Python theme={null} > import asyncio > from comfy_sdk import AsyncComfy > > # Reads COMFY_API_KEY from the environment. > # Each submit() call mints its own Idempotency-Key and reuses it for automatic retries. > async def main(): > async with AsyncComfy() as client: > handle = await client.models.submit( > "vertexai/gemini-3.1-pro-preview", > { > "contents": [ > { > "role": "user", > "parts": [ > { > "text": "Describe a single red maple leaf on a white background in one sentence.", > }, > ], > }, > ], > "generationConfig": { > "temperature": 0.7, > "maxOutputTokens": 256, > }, > }, > ) > print("request_id:", handle.request_id) # with the model ID, all another process needs > > # Poll until the request completes, waiting the Retry-After the server names. > async for update in handle.iter_events(): > print(update.status, update.queue_position) > > # The provider's own payload, the same value models.run() returns. > # A request that failed or was cancelled raises the typed Router error here. > result = await handle.get() > > print("text:", result["candidates"][0]["content"]["parts"][0]["text"]) > > asyncio.run(main()) >`> >`typescript TypeScript theme={null} > import { comfy } from "@comfyorg/sdk"; > > // Reads COMFY_API_KEY from the environment. > // Each submit() call mints its own Idempotency-Key and reuses it for automatic retries. > type Result = { candidates: { content: { parts: { text: string }[] } }[] }; > const handle = await comfy.models.submit<Result>("vertexai/gemini-3.1-pro-preview", { > contents: [ > { > role: "user", > parts: [ > { > text: "Describe a single red maple leaf on a white background in one sentence.", > }, > ], > }, > ], > generationConfig: { > temperature: 0.7, > maxOutputTokens: 256, > }, > }); > console.log("requestId:", handle.requestId); // with the model ID, all another process needs > > // Poll until the request completes, waiting the Retry-After the server names. > for await (const update of handle.events()) { > console.log(update.status, update.queuePosition); > } > > // The same result models.run() returns. A request that failed or was cancelled rejects here. > const result = await handle.get(); > if (result.kind !== "json") throw new Error("expected a JSON result"); > > console.log("text:", result.data.candidates[0].content.parts[0].text); >`> >`bash cURL theme={null} > # 1. Submit. Router answers 201 with request_id, status_url, response_url and cancel_url. > curl https://api.comfy.org/v2/models/vertexai/gemini-3.1-pro-preview/requests \ > -H "X-API-Key: $COMFY_API_KEY" \ > -H "Idempotency-Key: $(uuidgen)" \ > -H "Content-Type: application/json" \ > -d "{\"contents\": [{\"role\":\"user\",\"parts\":[{\"text\":\"Describe a single red maple leaf on a white background in one sentence.\"}]}], \"generationConfig\": {\"temperature\":0.7,\"maxOutputTokens\":256}}" > > # 2. Poll until status is COMPLETED, waiting the Retry-After seconds each response names. > REQUEST_ID="<request_id from the 201 body>" > curl -i https://api.comfy.org/v2/models/vertexai/gemini-3.1-pro-preview/requests/$REQUEST_ID/status \ > -H "X-API-Key: $COMFY_API_KEY" > > # 3. Collect. 200 with the model's native output, 202 with the status body while it is still running. > curl https://api.comfy.org/v2/models/vertexai/gemini-3.1-pro-preview/requests/$REQUEST_ID \ > -H "X-API-Key: $COMFY_API_KEY" >`## Schema ### 输入 **contents**object[]*required* 与模型当前对话的内容。对于单轮查询,这是一个单独的实例;对于多轮查询,这是一个重复字段,包含对话历史和最新请求。 **contents\[].parts**object[]*required* **contents\[].parts\[].fileData**object基于 URI 的数据。 **contents\[].parts\[].fileData.fileUri**stringURI **contents\[].parts\[].fileData.mimeType**stringdata 或 fileUri 字段中指定文件的媒体类型。可接受的值包括以下几种。对于 gemini-2.0-flash-lite 和 gemini-2.0-flash,音频文件的最大长度为 8.4 小时,视频文件(不含音频)的最大长度为 1 小时。有关更多信息,请参阅 Gemini 音频和视频要求。文本文件必须采用 UTF-8 编码。文本文件的内容会计入 token 限制。图像分辨率无限制。 可选值:application/pdf、audio/mpeg、audio/mp3、audio/wav、image/png、image/jpeg、image/webp、text/plain、video/mov、video/mpeg、video/mp4、video/mpg、video/avi、video/wmv、video/mpegps、video/flv、image/heic、image/heif、audio/flac、video/webm**contents\[].parts\[].inlineData**object以原始字节形式提供的内联数据。对于 gemini-2.0-flash-lite 和 gemini-2.0-flash,最多可以通过 inlineData 指定 3000 张图像。 **contents\[].parts\[].inlineData.data**string (byte)要在提示中以内联方式包含的图像、PDF 或视频的 base64 编码。以内联方式包含媒体时,还必须指定数据的媒体类型(mimeType)。大小限制:20MB 格式:byte**contents\[].parts\[].inlineData.mimeType**stringdata 或 fileUri 字段中指定文件的媒体类型。可接受的值包括以下几种。对于 gemini-2.0-flash-lite 和 gemini-2.0-flash,音频文件的最大长度为 8.4 小时,视频文件(不含音频)的最大长度为 1 小时。有关更多信息,请参阅 Gemini 音频和视频要求。文本文件必须采用 UTF-8 编码。文本文件的内容会计入 token 限制。图像分辨率无限制。 可选值:application/pdf、audio/mpeg、audio/mp3、audio/wav、image/png、image/jpeg、image/webp、text/plain、video/mov、video/mpeg、video/mp4、video/mpg、video/avi、video/wmv、video/mpegps、video/flv、image/heic、image/heif、audio/flac、video/webm**contents\[].parts\[].mediaProcessing**string模型读取此部分视频的方式。设置为 "AGENTIC" 可让模型自行决定要检查哪些片段,而不是按固定速率进行帧采样。省略则使用默认的固定速率采样。支持 gemini-3.7-flash 及更新的 Flash 模型。 **contents\[].parts\[].text**string文本提示或代码片段。 **contents\[].parts\[].thought**boolean表示此部分是模型的一个思考/推理步骤。 **contents\[].role**string可选值:user、model**generationConfig**object生成过程的采样、长度和输出设置。每个字段都是可选的:下面声明了default的字段在省略时会应用该默认值,其余字段则回退到模型自身的行为。 **generationConfig.imageConfig**object图像生成的配置 **generationConfig.imageConfig.aspectRatio**string已生成图像的宽高比 **generationConfig.imageConfig.imageOutputOptions**object可选。已生成图像的图像输出格式。 **generationConfig.imageConfig.imageOutputOptions.compressionQuality**integer可选。输出图像的压缩质量。 **generationConfig.imageConfig.imageOutputOptions.mimeType**string可选。在 Vertex AI 路径(即由 Comfy 自身凭证提供服务的请求,以及使用 GCP 服务账号进行身份验证的 BYOK 请求)上,输出应保存为的图像格式。这些路径上接受的值为image/png和image/jpeg,匹配时不区分大小写,并在请求被转发之前统一转为小写;任何其他值都会被拒绝,并返回 400 错误且指明该字段。省略时默认为image/png。使用 Google AI Studio API 密钥进行身份验证的 BYOK 请求是个例外:该上游没有此属性,一旦请求中包含它就会拒绝整个调用,因此该字段会从请求中移除,而不是被采用或被拒绝,输出格式由 AI Studio 自行决定。在所有路径上,都应从你收到的响应部分中读回媒体类型(inlineData.mimeType,或者当设置了uploadImagesToStorage时读取fileData.mimeType),而不要假设你发送的值就是最终结果。 **generationConfig.imageConfig.imageSize**string可选。指定已生成图像的尺寸。支持的值为 1K、2K、4K。如果未指定,模型将使用默认值 1K。 **generationConfig.maxOutputTokens**integer响应中可生成的 token 最大数量。一个 token 大约相当于 4 个字符。100 个 token 大致对应 60-80 个单词。 范围:16到65536**generationConfig.responseModalities** \\TEXT,IMAGE[]**generationConfig.seed**integer当 seed 固定为特定值时,模型会尽力对重复请求给出相同的响应。不保证输出具有确定性。此外,即使使用相同的 seed 值,更改模型或参数设置(例如 temperature)也可能导致响应发生变化。默认情况下,会使用随机 seed 值。适用于以下模型:gemini-2.5-flash、gemini-2.5-pro、gemini-2.5-flash-preview-04-1、gemini-2.5-pro-preview-05-0、gemini-2.0-flash-lite-00、gemini-2.0-flash-001 **generationConfig.stopSequences**string[]**generationConfig.temperature**number(default: 1) temperature 用于在生成响应期间进行采样,采样发生在应用 topP 和 topK 时。temperature 控制 token 选择过程中的随机程度。较低的温度适合需要较少开放性回答或创造性回答的提示,而较高的温度可以带来更多样或更有创造性的结果。温度为 0 表示始终选择概率最高的 token。在这种情况下,给定提示的响应大多是确定性的,但仍可能出现少量变化。如果模型返回的响应过于通用、过于简短,或者模型给出了回退响应,请尝试提高 temperature 范围:0到2格式:float**generationConfig.thinkingConfig**object可选。思考功能的配置。思考是模型将复杂任务分解为更小步骤,从而生成更高质量响应的过程。 **generationConfig.thinkingConfig.includeThoughts**boolean可选。如果为 true,模型将在响应中包含其思考内容。 **generationConfig.thinkingConfig.thinkingBudget**integer可选。模型思考过程的 token 预算。模型将尽力保持在此预算范围内。 **generationConfig.thinkingConfig.thinkingLevel**string可选。模型的思考级别。 可能的值:THINKING_LEVEL_UNSPECIFIED、LOW、MEDIUM、HIGH、MINIMAL**generationConfig.topK**integer(default: 40) Top-K 会改变模型选择输出 token 的方式。top-K 为 1 表示下一个被选中的 token 是模型词表中所有 token 里概率最高的那个。top-K 为 3 表示借助 temperature 从 3 个概率最高的 token 中选择下一个 token。 范围:1到…**generationConfig.topP**number(default: 0.95) 如果指定,则使用核采样。 Top-P 会改变模型选择输出 token 的方式。token 会从概率最高(参见 top-K)到最低依次选出,直到它们的概率之和等于 top-P 值。例如,如果 token A、B 和 C 的概率分别为 0.3、0.2 和 0.1,且 top-P 值为 0.5,那么模型会借助 temperature 选择 A 或 B 作为下一个 token,并排除 C 作为候选。 指定较低的值可获得随机性更低的响应,指定较高的值可获得随机性更高的响应。 范围:0到1格式:float**safetySettings**object[]用于阻止不安全内容的按请求设置。在 GenerateContentResponse.candidates 上强制执行。 **safetySettings\[].category**string*required* 可能的值:HARM_CATEGORY_SEXUALLY_EXPLICIT、HARM_CATEGORY_HATE_SPEECH、HARM_CATEGORY_HARASSMENT、HARM_CATEGORY_DANGEROUS_CONTENT**safetySettings\[].threshold**string*required* 可能的值:OFF、BLOCK_NONE、BLOCK_LOW_AND_ABOVE、BLOCK_MEDIUM_AND_ABOVE、BLOCK_ONLY_HIGH**systemInstruction**object用于引导模型获得更好表现的指令。例如,"尽可能简洁地回答"或"不要在回复中使用技术术语"。这些文本字符串会计入 token 限制。systemInstruction 的 role 字段会被忽略,不会影响模型的表现。注意:parts 中只应使用文本,且每个 part 中的内容应位于单独的段落。 **systemInstruction.parts**object[]*required* 构成单条消息的有序 part 列表。不同的 part 可以具有不同的 IANA MIME 类型。有关输入的限制(例如最大 token 数量或图像数量),请参阅 Google 模型页面上的模型规格。 **systemInstruction.parts\[].text**string文本提示或代码片段。 **systemInstruction.role**string创建消息的实体的身份。支持以下值:user:表示该消息由真实的人发送,通常是用户生成的消息。model:表示该消息由模型生成。在多轮对话中,model 值用于将来自模型的消息插入对话。对于非多轮对话,此字段可以留空或不设置。 可能的值:user、model**tools**object[]一段代码,使系统能够与外部系统交互,以执行超出模型知识和范围之外的一个操作或一组操作。请参阅函数调用。 **tools\[].functionDeclarations**object[]**tools\[].functionDeclarations\[].description**string**tools\[].functionDeclarations\[].name**string*required* **tools\[].functionDeclarations\[].parameters**object函数参数的 JSON schema **uploadImagesToStorage**boolean若为 true,已生成的图像将上传到云端存储,并以签名 URL 的形式返回,而不是内联 base64 数据。这些 URL 会在 24 小时后过期。 **videoMetadata**object对于视频输入,表示视频在 Duration 格式下的起始和结束偏移量。例如,要指定一段从 1:00 开始的 10 秒片段,请设置 "startOffset": \{ "seconds": 60 } 和 "endOffset": \{ "seconds": 70 }。只有当视频数据以 inlineData 或 fileData 形式呈现时,才应指定该元数据。 **videoMetadata.endOffset**object表示视频时间轴位置上的时长偏移量。 **videoMetadata.endOffset.nanos**integer以纳秒为精度的带符号秒的小数部分。带小数的负秒值,其 nanos 值仍必须为非负。 Range:0到999999999**videoMetadata.endOffset.seconds**integer时间跨度的带符号秒数。必须介于 -315,576,000,000 到 +315,576,000,000 之间(含两端)。 Range:-315576000000到315576000000**videoMetadata.startOffset**object表示视频时间轴位置上的时长偏移量。 **videoMetadata.startOffset.nanos**integer以纳秒为精度的带符号秒的小数部分。带小数的负秒值,其 nanos 值仍必须为非负。 Range:0到999999999**videoMetadata.startOffset.seconds**integer时间跨度的带符号秒数。必须介于 -315,576,000,000 到 +315,576,000,000 之间(含两端)。 Range:-315576000000到315576000000根据 Router 在GET /v2/models/vertexai/gemini-3.1-pro-preview/openapi.json提供的 schema 生成,该文档也是请求到达提供商之前用于校验调用的同一份文档。 ### 输出 **candidates**object[]**candidates\[].citationMetadata**object**candidates\[].citationMetadata.citations**object[]**candidates\[].citationMetadata.citations\[].authors**string[]**candidates\[].citationMetadata.citations\[].endIndex**integer**candidates\[].citationMetadata.citations\[].license**string**candidates\[].citationMetadata.citations\[].publicationDate**string (date)格式:date**candidates\[].citationMetadata.citations\[].startIndex**integer**candidates\[].citationMetadata.citations\[].title**string**candidates\[].citationMetadata.citations\[].uri**string**candidates\[].content**object与模型进行的当前对话的内容。对于单轮查询,这是一个单独的实例。对于多轮查询,这是一个重复字段,包含对话历史和最新的请求。 **candidates\[].content.parts**object[]*required* **candidates\[].content.parts\[].fileData**object基于 URI 的数据。 **candidates\[].content.parts\[].fileData.fileUri**stringURI **candidates\[].content.parts\[].fileData.mimeType**stringdata 或 fileUri 字段中所指定文件的媒体类型。可接受的值包括以下内容。对于 gemini-2.0-flash-lite 和 gemini-2.0-flash,音频文件的最大长度为 8.4 小时,视频文件(不含音频)的最大长度为一小时。有关更多信息,请参阅 Gemini 音频和视频要求。文本文件必须采用 UTF-8 编码。文本文件的内容计入 token 限制。图像分辨率无限制。 可能的值:application/pdf、audio/mpeg、audio/mp3、audio/wav、image/png、image/jpeg、image/webp、text/plain、video/mov、video/mpeg、video/mp4、video/mpg、video/avi、video/wmv、video/mpegps、video/flv、image/heic、image/heif、audio/flac、video/webm**candidates\[].content.parts\[].inlineData**object原始字节形式的内联数据。对于 gemini-2.0-flash-lite 和 gemini-2.0-flash,最多可以通过 inlineData 指定 3000 张图像。 **candidates\[].content.parts\[].inlineData.data**string (byte)以内联方式包含在提示中的图像、PDF 或视频的 base64 编码。以内联方式包含媒体时,还必须指定数据的媒体类型(mimeType)。大小限制:20MB 格式:byte**candidates\[].content.parts\[].inlineData.mimeType**stringdata 或 fileUri 字段中所指定文件的媒体类型。可接受的值包括以下内容。对于 gemini-2.0-flash-lite 和 gemini-2.0-flash,音频文件的最大长度为 8.4 小时,视频文件(不含音频)的最大长度为一小时。有关更多信息,请参阅 Gemini 音频和视频要求。文本文件必须采用 UTF-8 编码。文本文件的内容计入 token 限制。图像分辨率无限制。 可能的值:application/pdf、audio/mpeg、audio/mp3、audio/wav、image/png、image/jpeg、image/webp、text/plain、video/mov、video/mpeg、video/mp4、video/mpg、video/avi、video/wmv、video/mpegps、video/flv、image/heic、image/heif、audio/flac、video/webm**candidates\[].content.parts\[].mediaProcessing**string模型如何读取此部分的视频。设置为 "AGENTIC" 可让模型自行决定检查哪些片段,而不是采用固定速率的帧采样。省略则使用默认的固定速率采样。支持 gemini-3.7-flash 及更新的 Flash 模型。 **candidates\[].content.parts\[].text**string文本提示或代码片段。 **candidates\[].content.parts\[].thought**boolean表示此部分为模型的思考/推理步骤。 **candidates\[].content.role**string可能的值:user、model**candidates\[].finishReason**string**candidates\[].safetyRatings**object[]**candidates\[].safetyRatings\[].category**string可能的值:HARM_CATEGORY_SEXUALLY_EXPLICIT、HARM_CATEGORY_HATE_SPEECH、HARM_CATEGORY_HARASSMENT、HARM_CATEGORY_DANGEROUS_CONTENT**candidates\[].safetyRatings\[].probability**string内容违反指定安全类别的概率 可能的值:NEGLIGIBLE、LOW、MEDIUM、HIGH、UNKNOWN**createTime**string响应创建时的时间戳。 **modelVersion**string用于生成响应的模型版本。 **promptFeedback**object**promptFeedback.blockReason**string**promptFeedback.blockReasonMessage**string**promptFeedback.safetyRatings**object[]**promptFeedback.safetyRatings\[].category**string可能的值:HARM_CATEGORY_SEXUALLY_EXPLICIT、HARM_CATEGORY_HATE_SPEECH、HARM_CATEGORY_HARASSMENT、HARM_CATEGORY_DANGEROUS_CONTENT**promptFeedback.safetyRatings\[].probability**string内容违反指定安全类别的概率 可能的值:NEGLIGIBLE、LOW、MEDIUM、HIGH、UNKNOWN**responseId**string响应的唯一标识符。 **usageMetadata**object**usageMetadata.cachedContentTokenCount**integer仅限输出。输入中缓存部分(缓存内容)的 token 数量。 **usageMetadata.candidatesTokenCount**integer响应中的 token 数量。 **usageMetadata.candidatesTokensDetails**object[]按模态划分的候选 token 明细。 **usageMetadata.candidatesTokensDetails\[].modality**string输入或输出内容的模态类型。 可能的值:MODALITY_UNSPECIFIED、TEXT、IMAGE、VIDEO、AUDIO、DOCUMENT**usageMetadata.candidatesTokensDetails\[].tokenCount**integer给定模态的 token 数量。 **usageMetadata.promptTokenCount**integer请求中的 token 数量。设置 cachedContent 后,这仍是有效的提示总大小,也就是说其中包含缓存内容中的 token 数量。 **usageMetadata.promptTokensDetails**object[]按模态划分的提示 token 明细。 **usageMetadata.promptTokensDetails\[].modality**string输入或输出内容的模态类型。 可能的值:MODALITY_UNSPECIFIED、TEXT、IMAGE、VIDEO、AUDIO、DOCUMENT**usageMetadata.promptTokensDetails\[].tokenCount**integer给定模态的 token 数量。 **usageMetadata.thoughtsTokenCount**integerthoughts 输出中存在的 token 数量。 **usageMetadata.toolUsePromptTokenCount**integer工具使用提示中存在的 token 数量。 **usageMetadata.toolUsePromptTokensDetails**object[]按模态划分的工具使用提示 token 明细。 **usageMetadata.toolUsePromptTokensDetails\[].modality**string输入或输出内容的模态类型。 可能的值:MODALITY_UNSPECIFIED、TEXT、IMAGE、VIDEO、AUDIO、DOCUMENT**usageMetadata.toolUsePromptTokensDetails\[].tokenCount**integer给定模态的 token 数量。 **usageMetadata.totalTokenCount**integertoken 总数(提示 + 候选)。 **usageMetadata.trafficType**string请求使用的流量类型(例如 PROVISIONED\_THROUGHPUT)。 ## 示例 ### 输入`json theme={null} { "contents": [ { "role": "user", "parts": [ { "text": "Describe a single red maple leaf on a white background in one sentence." } ] } ], "generationConfig": { "temperature": 0.7, "maxOutputTokens": 256 } }`### 输出`json theme={null} { "candidates": [ { "content": { "role": "model", "parts": [ { "text": "A single red maple leaf rests on a plain white background, its edges sharp and its color deep." } ] }, "finishReason": "STOP" } ], "usageMetadata": { "promptTokenCount": 18, "candidatesTokenCount": 24 } }``
[tab] Gemini 3.5 Flash 模型 ID:vertexai/gemini-3.5-flash端点:POST https://api.comfy.org/v2/models/vertexai/gemini-3.5-flash> [tab] 等待结果 > > ``python Python theme={null} > import asyncio > from comfy_sdk import AsyncComfy > > # Reads COMFY_API_KEY from the environment. > # The SDK automatically creates an idempotency key and reuses it for automatic retries. > async def main(): > async with AsyncComfy() as client: > result = await client.models.run( > "vertexai/gemini-3.5-flash", > { > "contents": [ > { > "role": "user", > "parts": [ > { > "text": "Describe a single red maple leaf on a white background in one sentence.", > }, > ], > }, > ], > "generationConfig": { > "temperature": 0.7, > "maxOutputTokens": 256, > }, > }, > ) > > print("text:", result["candidates"][0]["content"]["parts"][0]["text"]) > > asyncio.run(main()) >`> >`typescript TypeScript theme={null} > import { comfy } from "@comfyorg/sdk"; > > // Reads COMFY_API_KEY from the environment. > // The SDK automatically creates an idempotency key and reuses it for automatic retries. > type Result = { candidates: { content: { parts: { text: string }[] } }[] }; > const result = await comfy.models.run<Result>("vertexai/gemini-3.5-flash", { > contents: [ > { > role: "user", > parts: [ > { > text: "Describe a single red maple leaf on a white background in one sentence.", > }, > ], > }, > ], > generationConfig: { > temperature: 0.7, > maxOutputTokens: 256, > }, > }); > if (result.kind !== "json") throw new Error("expected a JSON result"); > > console.log("text:", result.data.candidates[0].content.parts[0].text); >`> >`bash cURL theme={null} > curl https://api.comfy.org/v2/models/vertexai/gemini-3.5-flash \ > -H "X-API-Key: $COMFY_API_KEY" \ > -H "Idempotency-Key: $(uuidgen)" \ > -H "Content-Type: application/json" \ > -d "{\"contents\": [{\"role\":\"user\",\"parts\":[{\"text\":\"Describe a single red maple leaf on a white background in one sentence.\"}]}], \"generationConfig\": {\"temperature\":0.7,\"maxOutputTokens\":256}}" >`> [tab] 排队并稍后收集 > > 将相同的请求体发送到POST https://api.comfy.org/v2/models/vertexai/gemini-3.5-flash/requests。Router 会在运行被受理后立即返回201和request_id,结果就绪后即可从本进程或其他进程收集。[队列投递](https://docs.comfy.org/zh/development/comfy-router/queue.md)详细介绍了状态查询、取消和结果收集。 > >`python Python theme={null} > import asyncio > from comfy_sdk import AsyncComfy > > # Reads COMFY_API_KEY from the environment. > # Each submit() call mints its own Idempotency-Key and reuses it for automatic retries. > async def main(): > async with AsyncComfy() as client: > handle = await client.models.submit( > "vertexai/gemini-3.5-flash", > { > "contents": [ > { > "role": "user", > "parts": [ > { > "text": "Describe a single red maple leaf on a white background in one sentence.", > }, > ], > }, > ], > "generationConfig": { > "temperature": 0.7, > "maxOutputTokens": 256, > }, > }, > ) > print("request_id:", handle.request_id) # with the model ID, all another process needs > > # Poll until the request completes, waiting the Retry-After the server names. > async for update in handle.iter_events(): > print(update.status, update.queue_position) > > # The provider's own payload, the same value models.run() returns. > # A request that failed or was cancelled raises the typed Router error here. > result = await handle.get() > > print("text:", result["candidates"][0]["content"]["parts"][0]["text"]) > > asyncio.run(main()) >`> >`typescript TypeScript theme={null} > import { comfy } from "@comfyorg/sdk"; > > // Reads COMFY_API_KEY from the environment. > // Each submit() call mints its own Idempotency-Key and reuses it for automatic retries. > type Result = { candidates: { content: { parts: { text: string }[] } }[] }; > const handle = await comfy.models.submit<Result>("vertexai/gemini-3.5-flash", { > contents: [ > { > role: "user", > parts: [ > { > text: "Describe a single red maple leaf on a white background in one sentence.", > }, > ], > }, > ], > generationConfig: { > temperature: 0.7, > maxOutputTokens: 256, > }, > }); > console.log("requestId:", handle.requestId); // with the model ID, all another process needs > > // Poll until the request completes, waiting the Retry-After the server names. > for await (const update of handle.events()) { > console.log(update.status, update.queuePosition); > } > > // The same result models.run() returns. A request that failed or was cancelled rejects here. > const result = await handle.get(); > if (result.kind !== "json") throw new Error("expected a JSON result"); > > console.log("text:", result.data.candidates[0].content.parts[0].text); >`> >`bash cURL theme={null} > # 1. Submit. Router answers 201 with request_id, status_url, response_url and cancel_url. > curl https://api.comfy.org/v2/models/vertexai/gemini-3.5-flash/requests \ > -H "X-API-Key: $COMFY_API_KEY" \ > -H "Idempotency-Key: $(uuidgen)" \ > -H "Content-Type: application/json" \ > -d "{\"contents\": [{\"role\":\"user\",\"parts\":[{\"text\":\"Describe a single red maple leaf on a white background in one sentence.\"}]}], \"generationConfig\": {\"temperature\":0.7,\"maxOutputTokens\":256}}" > > # 2. Poll until status is COMPLETED, waiting the Retry-After seconds each response names. > REQUEST_ID="<request_id from the 201 body>" > curl -i https://api.comfy.org/v2/models/vertexai/gemini-3.5-flash/requests/$REQUEST_ID/status \ > -H "X-API-Key: $COMFY_API_KEY" > > # 3. Collect. 200 with the model's native output, 202 with the status body while it is still running. > curl https://api.comfy.org/v2/models/vertexai/gemini-3.5-flash/requests/$REQUEST_ID \ > -H "X-API-Key: $COMFY_API_KEY" >`## Schema ### 输入 **contents**object[]*required* 与模型当前对话的内容。对于单轮查询,这是一个单独的实例;对于多轮查询,这是一个重复字段,包含对话历史和最新请求。 **contents\[].parts**object[]*required* **contents\[].parts\[].fileData**object基于 URI 的数据。 **contents\[].parts\[].fileData.fileUri**stringURI **contents\[].parts\[].fileData.mimeType**stringdata 或 fileUri 字段中指定文件的媒体类型。可接受的值包括以下几种。对于 gemini-2.0-flash-lite 和 gemini-2.0-flash,音频文件的最大长度为 8.4 小时,视频文件(不含音频)的最大长度为 1 小时。有关更多信息,请参阅 Gemini 音频和视频要求。文本文件必须采用 UTF-8 编码。文本文件的内容会计入 token 限制。图像分辨率无限制。 可选值:application/pdf、audio/mpeg、audio/mp3、audio/wav、image/png、image/jpeg、image/webp、text/plain、video/mov、video/mpeg、video/mp4、video/mpg、video/avi、video/wmv、video/mpegps、video/flv、image/heic、image/heif、audio/flac、video/webm**contents\[].parts\[].inlineData**object以原始字节形式提供的内联数据。对于 gemini-2.0-flash-lite 和 gemini-2.0-flash,最多可以通过 inlineData 指定 3000 张图像。 **contents\[].parts\[].inlineData.data**string (byte)要在提示中以内联方式包含的图像、PDF 或视频的 base64 编码。以内联方式包含媒体时,还必须指定数据的媒体类型(mimeType)。大小限制:20MB 格式:byte**contents\[].parts\[].inlineData.mimeType**stringdata 或 fileUri 字段中指定文件的媒体类型。可接受的值包括以下几种。对于 gemini-2.0-flash-lite 和 gemini-2.0-flash,音频文件的最大长度为 8.4 小时,视频文件(不含音频)的最大长度为 1 小时。有关更多信息,请参阅 Gemini 音频和视频要求。文本文件必须采用 UTF-8 编码。文本文件的内容会计入 token 限制。图像分辨率无限制。 可选值:application/pdf、audio/mpeg、audio/mp3、audio/wav、image/png、image/jpeg、image/webp、text/plain、video/mov、video/mpeg、video/mp4、video/mpg、video/avi、video/wmv、video/mpegps、video/flv、image/heic、image/heif、audio/flac、video/webm**contents\[].parts\[].mediaProcessing**string模型读取此部分视频的方式。设置为 "AGENTIC" 可让模型自行决定要检查哪些片段,而不是按固定速率进行帧采样。省略则使用默认的固定速率采样。支持 gemini-3.7-flash 及更新的 Flash 模型。 **contents\[].parts\[].text**string文本提示或代码片段。 **contents\[].parts\[].thought**boolean表示此部分是模型的一个思考/推理步骤。 **contents\[].role**string可选值:user、model**generationConfig**object生成过程的采样、长度和输出设置。每个字段都是可选的:下面声明了default的字段在省略时会应用该默认值,其余字段则回退到模型自身的行为。 **generationConfig.imageConfig**object图像生成的配置 **generationConfig.imageConfig.aspectRatio**string已生成图像的宽高比 **generationConfig.imageConfig.imageOutputOptions**object可选。已生成图像的图像输出格式。 **generationConfig.imageConfig.imageOutputOptions.compressionQuality**integer可选。输出图像的压缩质量。 **generationConfig.imageConfig.imageOutputOptions.mimeType**string可选。在 Vertex AI 路径(即由 Comfy 自身凭证提供服务的请求,以及使用 GCP 服务账号进行身份验证的 BYOK 请求)上,输出应保存为的图像格式。这些路径上接受的值为image/png和image/jpeg,匹配时不区分大小写,并在请求被转发之前统一转为小写;任何其他值都会被拒绝,并返回 400 错误且指明该字段。省略时默认为image/png。使用 Google AI Studio API 密钥进行身份验证的 BYOK 请求是个例外:该上游没有此属性,一旦请求中包含它就会拒绝整个调用,因此该字段会从请求中移除,而不是被采用或被拒绝,输出格式由 AI Studio 自行决定。在所有路径上,都应从你收到的响应部分中读回媒体类型(inlineData.mimeType,或者当设置了uploadImagesToStorage时读取fileData.mimeType),而不要假设你发送的值就是最终结果。 **generationConfig.imageConfig.imageSize**string可选。指定已生成图像的尺寸。支持的值为 1K、2K、4K。如果未指定,模型将使用默认值 1K。 **generationConfig.maxOutputTokens**integer响应中可生成的 token 最大数量。一个 token 大约相当于 4 个字符。100 个 token 大致对应 60-80 个单词。 范围:16到65536**generationConfig.responseModalities** \\TEXT,IMAGE[]**generationConfig.seed**integer当 seed 固定为特定值时,模型会尽力对重复请求给出相同的响应。不保证输出具有确定性。此外,即使使用相同的 seed 值,更改模型或参数设置(例如 temperature)也可能导致响应发生变化。默认情况下,会使用随机 seed 值。适用于以下模型:gemini-2.5-flash、gemini-2.5-pro、gemini-2.5-flash-preview-04-1、gemini-2.5-pro-preview-05-0、gemini-2.0-flash-lite-00、gemini-2.0-flash-001 **generationConfig.stopSequences**string[]**generationConfig.temperature**number(default: 1) temperature 用于在生成响应期间进行采样,采样发生在应用 topP 和 topK 时。temperature 控制 token 选择过程中的随机程度。较低的温度适合需要较少开放性回答或创造性回答的提示,而较高的温度可以带来更多样或更有创造性的结果。温度为 0 表示始终选择概率最高的 token。在这种情况下,给定提示的响应大多是确定性的,但仍可能出现少量变化。如果模型返回的响应过于通用、过于简短,或者模型给出了回退响应,请尝试提高 temperature 范围:0到2格式:float**generationConfig.thinkingConfig**object可选。思考功能的配置。思考是模型将复杂任务分解为更小步骤,从而生成更高质量响应的过程。 **generationConfig.thinkingConfig.includeThoughts**boolean可选。如果为 true,模型将在响应中包含其思考内容。 **generationConfig.thinkingConfig.thinkingBudget**integer可选。模型思考过程的 token 预算。模型将尽力保持在此预算范围内。 **generationConfig.thinkingConfig.thinkingLevel**string可选。模型的思考级别。 可能的值:THINKING_LEVEL_UNSPECIFIED、LOW、MEDIUM、HIGH、MINIMAL**generationConfig.topK**integer(default: 40) Top-K 会改变模型选择输出 token 的方式。top-K 为 1 表示下一个被选中的 token 是模型词表中所有 token 里概率最高的那个。top-K 为 3 表示借助 temperature 从 3 个概率最高的 token 中选择下一个 token。 范围:1到…**generationConfig.topP**number(default: 0.95) 如果指定,则使用核采样。 Top-P 会改变模型选择输出 token 的方式。token 会从概率最高(参见 top-K)到最低依次选出,直到它们的概率之和等于 top-P 值。例如,如果 token A、B 和 C 的概率分别为 0.3、0.2 和 0.1,且 top-P 值为 0.5,那么模型会借助 temperature 选择 A 或 B 作为下一个 token,并排除 C 作为候选。 指定较低的值可获得随机性更低的响应,指定较高的值可获得随机性更高的响应。 范围:0到1格式:float**safetySettings**object[]用于阻止不安全内容的按请求设置。在 GenerateContentResponse.candidates 上强制执行。 **safetySettings\[].category**string*required* 可能的值:HARM_CATEGORY_SEXUALLY_EXPLICIT、HARM_CATEGORY_HATE_SPEECH、HARM_CATEGORY_HARASSMENT、HARM_CATEGORY_DANGEROUS_CONTENT**safetySettings\[].threshold**string*required* 可能的值:OFF、BLOCK_NONE、BLOCK_LOW_AND_ABOVE、BLOCK_MEDIUM_AND_ABOVE、BLOCK_ONLY_HIGH**systemInstruction**object用于引导模型获得更好表现的指令。例如,"尽可能简洁地回答"或"不要在回复中使用技术术语"。这些文本字符串会计入 token 限制。systemInstruction 的 role 字段会被忽略,不会影响模型的表现。注意:parts 中只应使用文本,且每个 part 中的内容应位于单独的段落。 **systemInstruction.parts**object[]*required* 构成单条消息的有序 part 列表。不同的 part 可以具有不同的 IANA MIME 类型。有关输入的限制(例如最大 token 数量或图像数量),请参阅 Google 模型页面上的模型规格。 **systemInstruction.parts\[].text**string文本提示或代码片段。 **systemInstruction.role**string创建消息的实体的身份。支持以下值:user:表示该消息由真实的人发送,通常是用户生成的消息。model:表示该消息由模型生成。在多轮对话中,model 值用于将来自模型的消息插入对话。对于非多轮对话,此字段可以留空或不设置。 可能的值:user、model**tools**object[]一段代码,使系统能够与外部系统交互,以执行超出模型知识和范围之外的一个操作或一组操作。请参阅函数调用。 **tools\[].functionDeclarations**object[]**tools\[].functionDeclarations\[].description**string**tools\[].functionDeclarations\[].name**string*required* **tools\[].functionDeclarations\[].parameters**object函数参数的 JSON schema **uploadImagesToStorage**boolean若为 true,已生成的图像将上传到云端存储,并以签名 URL 的形式返回,而不是内联 base64 数据。这些 URL 会在 24 小时后过期。 **videoMetadata**object对于视频输入,表示视频在 Duration 格式下的起始和结束偏移量。例如,要指定一段从 1:00 开始的 10 秒片段,请设置 "startOffset": \{ "seconds": 60 } 和 "endOffset": \{ "seconds": 70 }。只有当视频数据以 inlineData 或 fileData 形式呈现时,才应指定该元数据。 **videoMetadata.endOffset**object表示视频时间轴位置上的时长偏移量。 **videoMetadata.endOffset.nanos**integer以纳秒为精度的带符号秒的小数部分。带小数的负秒值,其 nanos 值仍必须为非负。 Range:0到999999999**videoMetadata.endOffset.seconds**integer时间跨度的带符号秒数。必须介于 -315,576,000,000 到 +315,576,000,000 之间(含两端)。 Range:-315576000000到315576000000**videoMetadata.startOffset**object表示视频时间轴位置上的时长偏移量。 **videoMetadata.startOffset.nanos**integer以纳秒为精度的带符号秒的小数部分。带小数的负秒值,其 nanos 值仍必须为非负。 Range:0到999999999**videoMetadata.startOffset.seconds**integer时间跨度的带符号秒数。必须介于 -315,576,000,000 到 +315,576,000,000 之间(含两端)。 Range:-315576000000到315576000000根据 Router 在GET /v2/models/vertexai/gemini-3.5-flash/openapi.json提供的 schema 生成,该文档也是请求到达提供商之前用于校验调用的同一份文档。 ### 输出 **candidates**object[]**candidates\[].citationMetadata**object**candidates\[].citationMetadata.citations**object[]**candidates\[].citationMetadata.citations\[].authors**string[]**candidates\[].citationMetadata.citations\[].endIndex**integer**candidates\[].citationMetadata.citations\[].license**string**candidates\[].citationMetadata.citations\[].publicationDate**string (date)格式:date**candidates\[].citationMetadata.citations\[].startIndex**integer**candidates\[].citationMetadata.citations\[].title**string**candidates\[].citationMetadata.citations\[].uri**string**candidates\[].content**object与模型进行的当前对话的内容。对于单轮查询,这是一个单独的实例。对于多轮查询,这是一个重复字段,包含对话历史和最新的请求。 **candidates\[].content.parts**object[]*required* **candidates\[].content.parts\[].fileData**object基于 URI 的数据。 **candidates\[].content.parts\[].fileData.fileUri**stringURI **candidates\[].content.parts\[].fileData.mimeType**stringdata 或 fileUri 字段中所指定文件的媒体类型。可接受的值包括以下内容。对于 gemini-2.0-flash-lite 和 gemini-2.0-flash,音频文件的最大长度为 8.4 小时,视频文件(不含音频)的最大长度为一小时。有关更多信息,请参阅 Gemini 音频和视频要求。文本文件必须采用 UTF-8 编码。文本文件的内容计入 token 限制。图像分辨率无限制。 可能的值:application/pdf、audio/mpeg、audio/mp3、audio/wav、image/png、image/jpeg、image/webp、text/plain、video/mov、video/mpeg、video/mp4、video/mpg、video/avi、video/wmv、video/mpegps、video/flv、image/heic、image/heif、audio/flac、video/webm**candidates\[].content.parts\[].inlineData**object原始字节形式的内联数据。对于 gemini-2.0-flash-lite 和 gemini-2.0-flash,最多可以通过 inlineData 指定 3000 张图像。 **candidates\[].content.parts\[].inlineData.data**string (byte)以内联方式包含在提示中的图像、PDF 或视频的 base64 编码。以内联方式包含媒体时,还必须指定数据的媒体类型(mimeType)。大小限制:20MB 格式:byte**candidates\[].content.parts\[].inlineData.mimeType**stringdata 或 fileUri 字段中所指定文件的媒体类型。可接受的值包括以下内容。对于 gemini-2.0-flash-lite 和 gemini-2.0-flash,音频文件的最大长度为 8.4 小时,视频文件(不含音频)的最大长度为一小时。有关更多信息,请参阅 Gemini 音频和视频要求。文本文件必须采用 UTF-8 编码。文本文件的内容计入 token 限制。图像分辨率无限制。 可能的值:application/pdf、audio/mpeg、audio/mp3、audio/wav、image/png、image/jpeg、image/webp、text/plain、video/mov、video/mpeg、video/mp4、video/mpg、video/avi、video/wmv、video/mpegps、video/flv、image/heic、image/heif、audio/flac、video/webm**candidates\[].content.parts\[].mediaProcessing**string模型如何读取此部分的视频。设置为 "AGENTIC" 可让模型自行决定检查哪些片段,而不是采用固定速率的帧采样。省略则使用默认的固定速率采样。支持 gemini-3.7-flash 及更新的 Flash 模型。 **candidates\[].content.parts\[].text**string文本提示或代码片段。 **candidates\[].content.parts\[].thought**boolean表示此部分为模型的思考/推理步骤。 **candidates\[].content.role**string可能的值:user、model**candidates\[].finishReason**string**candidates\[].safetyRatings**object[]**candidates\[].safetyRatings\[].category**string可能的值:HARM_CATEGORY_SEXUALLY_EXPLICIT、HARM_CATEGORY_HATE_SPEECH、HARM_CATEGORY_HARASSMENT、HARM_CATEGORY_DANGEROUS_CONTENT**candidates\[].safetyRatings\[].probability**string内容违反指定安全类别的概率 可能的值:NEGLIGIBLE、LOW、MEDIUM、HIGH、UNKNOWN**createTime**string响应创建时的时间戳。 **modelVersion**string用于生成响应的模型版本。 **promptFeedback**object**promptFeedback.blockReason**string**promptFeedback.blockReasonMessage**string**promptFeedback.safetyRatings**object[]**promptFeedback.safetyRatings\[].category**string可能的值:HARM_CATEGORY_SEXUALLY_EXPLICIT、HARM_CATEGORY_HATE_SPEECH、HARM_CATEGORY_HARASSMENT、HARM_CATEGORY_DANGEROUS_CONTENT**promptFeedback.safetyRatings\[].probability**string内容违反指定安全类别的概率 可能的值:NEGLIGIBLE、LOW、MEDIUM、HIGH、UNKNOWN**responseId**string响应的唯一标识符。 **usageMetadata**object**usageMetadata.cachedContentTokenCount**integer仅限输出。输入中缓存部分(缓存内容)的 token 数量。 **usageMetadata.candidatesTokenCount**integer响应中的 token 数量。 **usageMetadata.candidatesTokensDetails**object[]按模态划分的候选 token 明细。 **usageMetadata.candidatesTokensDetails\[].modality**string输入或输出内容的模态类型。 可能的值:MODALITY_UNSPECIFIED、TEXT、IMAGE、VIDEO、AUDIO、DOCUMENT**usageMetadata.candidatesTokensDetails\[].tokenCount**integer给定模态的 token 数量。 **usageMetadata.promptTokenCount**integer请求中的 token 数量。设置 cachedContent 后,这仍是有效的提示总大小,也就是说其中包含缓存内容中的 token 数量。 **usageMetadata.promptTokensDetails**object[]按模态划分的提示 token 明细。 **usageMetadata.promptTokensDetails\[].modality**string输入或输出内容的模态类型。 可能的值:MODALITY_UNSPECIFIED、TEXT、IMAGE、VIDEO、AUDIO、DOCUMENT**usageMetadata.promptTokensDetails\[].tokenCount**integer给定模态的 token 数量。 **usageMetadata.thoughtsTokenCount**integerthoughts 输出中存在的 token 数量。 **usageMetadata.toolUsePromptTokenCount**integer工具使用提示中存在的 token 数量。 **usageMetadata.toolUsePromptTokensDetails**object[]按模态划分的工具使用提示 token 明细。 **usageMetadata.toolUsePromptTokensDetails\[].modality**string输入或输出内容的模态类型。 可能的值:MODALITY_UNSPECIFIED、TEXT、IMAGE、VIDEO、AUDIO、DOCUMENT**usageMetadata.toolUsePromptTokensDetails\[].tokenCount**integer给定模态的 token 数量。 **usageMetadata.totalTokenCount**integertoken 总数(提示 + 候选)。 **usageMetadata.trafficType**string请求使用的流量类型(例如 PROVISIONED\_THROUGHPUT)。 ## 示例 ### 输入`json theme={null} { "contents": [ { "role": "user", "parts": [ { "text": "Describe a single red maple leaf on a white background in one sentence." } ] } ], "generationConfig": { "temperature": 0.7, "maxOutputTokens": 256 } }`### 输出`json theme={null} { "candidates": [ { "content": { "role": "model", "parts": [ { "text": "A single red maple leaf rests on a plain white background, its edges sharp and its color deep." } ] }, "finishReason": "STOP" } ], "usageMetadata": { "promptTokenCount": 18, "candidatesTokenCount": 24 } }``
[tab] Gemini 2.5 Pro 模型 ID:vertexai/gemini-2.5-pro端点:POST https://api.comfy.org/v2/models/vertexai/gemini-2.5-pro> [tab] 等待结果 > > ``python Python theme={null} > import asyncio > from comfy_sdk import AsyncComfy > > # Reads COMFY_API_KEY from the environment. > # The SDK automatically creates an idempotency key and reuses it for automatic retries. > async def main(): > async with AsyncComfy() as client: > result = await client.models.run( > "vertexai/gemini-2.5-pro", > { > "contents": [ > { > "role": "user", > "parts": [ > { > "text": "Describe a single red maple leaf on a white background in one sentence.", > }, > ], > }, > ], > "generationConfig": { > "temperature": 0.7, > "maxOutputTokens": 256, > }, > }, > ) > > print("text:", result["candidates"][0]["content"]["parts"][0]["text"]) > > asyncio.run(main()) >`> >`typescript TypeScript theme={null} > import { comfy } from "@comfyorg/sdk"; > > // Reads COMFY_API_KEY from the environment. > // The SDK automatically creates an idempotency key and reuses it for automatic retries. > type Result = { candidates: { content: { parts: { text: string }[] } }[] }; > const result = await comfy.models.run<Result>("vertexai/gemini-2.5-pro", { > contents: [ > { > role: "user", > parts: [ > { > text: "Describe a single red maple leaf on a white background in one sentence.", > }, > ], > }, > ], > generationConfig: { > temperature: 0.7, > maxOutputTokens: 256, > }, > }); > if (result.kind !== "json") throw new Error("expected a JSON result"); > > console.log("text:", result.data.candidates[0].content.parts[0].text); >`> >`bash cURL theme={null} > curl https://api.comfy.org/v2/models/vertexai/gemini-2.5-pro \ > -H "X-API-Key: $COMFY_API_KEY" \ > -H "Idempotency-Key: $(uuidgen)" \ > -H "Content-Type: application/json" \ > -d "{\"contents\": [{\"role\":\"user\",\"parts\":[{\"text\":\"Describe a single red maple leaf on a white background in one sentence.\"}]}], \"generationConfig\": {\"temperature\":0.7,\"maxOutputTokens\":256}}" >`> [tab] 排队并稍后收集 > > 将相同的请求体发送到POST https://api.comfy.org/v2/models/vertexai/gemini-2.5-pro/requests。Router 会在运行被受理后立即返回201和request_id,结果就绪后即可从本进程或其他进程收集。[队列投递](https://docs.comfy.org/zh/development/comfy-router/queue.md)详细介绍了状态查询、取消和结果收集。 > >`python Python theme={null} > import asyncio > from comfy_sdk import AsyncComfy > > # Reads COMFY_API_KEY from the environment. > # Each submit() call mints its own Idempotency-Key and reuses it for automatic retries. > async def main(): > async with AsyncComfy() as client: > handle = await client.models.submit( > "vertexai/gemini-2.5-pro", > { > "contents": [ > { > "role": "user", > "parts": [ > { > "text": "Describe a single red maple leaf on a white background in one sentence.", > }, > ], > }, > ], > "generationConfig": { > "temperature": 0.7, > "maxOutputTokens": 256, > }, > }, > ) > print("request_id:", handle.request_id) # with the model ID, all another process needs > > # Poll until the request completes, waiting the Retry-After the server names. > async for update in handle.iter_events(): > print(update.status, update.queue_position) > > # The provider's own payload, the same value models.run() returns. > # A request that failed or was cancelled raises the typed Router error here. > result = await handle.get() > > print("text:", result["candidates"][0]["content"]["parts"][0]["text"]) > > asyncio.run(main()) >`> >`typescript TypeScript theme={null} > import { comfy } from "@comfyorg/sdk"; > > // Reads COMFY_API_KEY from the environment. > // Each submit() call mints its own Idempotency-Key and reuses it for automatic retries. > type Result = { candidates: { content: { parts: { text: string }[] } }[] }; > const handle = await comfy.models.submit<Result>("vertexai/gemini-2.5-pro", { > contents: [ > { > role: "user", > parts: [ > { > text: "Describe a single red maple leaf on a white background in one sentence.", > }, > ], > }, > ], > generationConfig: { > temperature: 0.7, > maxOutputTokens: 256, > }, > }); > console.log("requestId:", handle.requestId); // with the model ID, all another process needs > > // Poll until the request completes, waiting the Retry-After the server names. > for await (const update of handle.events()) { > console.log(update.status, update.queuePosition); > } > > // The same result models.run() returns. A request that failed or was cancelled rejects here. > const result = await handle.get(); > if (result.kind !== "json") throw new Error("expected a JSON result"); > > console.log("text:", result.data.candidates[0].content.parts[0].text); >`> >`bash cURL theme={null} > # 1. Submit. Router answers 201 with request_id, status_url, response_url and cancel_url. > curl https://api.comfy.org/v2/models/vertexai/gemini-2.5-pro/requests \ > -H "X-API-Key: $COMFY_API_KEY" \ > -H "Idempotency-Key: $(uuidgen)" \ > -H "Content-Type: application/json" \ > -d "{\"contents\": [{\"role\":\"user\",\"parts\":[{\"text\":\"Describe a single red maple leaf on a white background in one sentence.\"}]}], \"generationConfig\": {\"temperature\":0.7,\"maxOutputTokens\":256}}" > > # 2. Poll until status is COMPLETED, waiting the Retry-After seconds each response names. > REQUEST_ID="<request_id from the 201 body>" > curl -i https://api.comfy.org/v2/models/vertexai/gemini-2.5-pro/requests/$REQUEST_ID/status \ > -H "X-API-Key: $COMFY_API_KEY" > > # 3. Collect. 200 with the model's native output, 202 with the status body while it is still running. > curl https://api.comfy.org/v2/models/vertexai/gemini-2.5-pro/requests/$REQUEST_ID \ > -H "X-API-Key: $COMFY_API_KEY" >`## Schema ### 输入 *这些字段遵循 Google 公布的 API 规范,并在 CI 中对照该规范进行校验。Router 针对此模型自身的 Schema 尚未发布,因此请求会未经校验直接转发给提供商。* **contents**object[]*required* 目前为止的对话内容,按从最旧到最新的顺序排列。part 可以是text,也可以是inlineData,用于在提示词之外一并发送图像、音频或视频。 **contents\[].role**string*required* 该轮对话的作者。 可选值:user、model**contents\[].parts**object[]*required* 该轮对话的内容部分。 **contents\[].parts\[].text**string文本部分。 **contents\[].parts\[].inlineData**object内联媒体部分。 **contents\[].parts\[].inlineData.mimeType**string媒体类型,例如image/png。 **contents\[].parts\[].inlineData.data**stringBase64 编码的媒体字节。 **systemInstruction**object应用于整个对话的系统提示词。 **systemInstruction.parts**object[]**systemInstruction.parts\[].text**string**generationConfig**object采样与长度设置。 **generationConfig.temperature**number采样的随机性。默认值因模型而异。 范围:0到2**generationConfig.topP**number核采样阈值。默认值因模型而异。 **generationConfig.topK**integerTop-k 采样截断值。默认值因模型而异。 **generationConfig.maxOutputTokens**integer已生成 token 数量的上限。 **generationConfig.seed**integer用于可复现采样的种子。 **generationConfig.stopSequences**string[]一旦生成就会终止生成的字符串。 **generationConfig.thinkingConfig**object在支持该功能的模型上控制推理投入。 **generationConfig.thinkingConfig.thinkingLevel**string可选值:MINIMAL、LOW、MEDIUM、HIGH**generationConfig.thinkingConfig.includeThoughts**boolean在返回答案的同时返回模型的推理过程。 **tools**object[]模型可以调用的函数声明。 **tools\[].functionDeclarations**object[]**tools\[].functionDeclarations\[].name**string**tools\[].functionDeclarations\[].description**string**tools\[].functionDeclarations\[].parameters**object该函数参数的 JSON Schema。 ### 输出 Router 会原样返回 Google 的原生响应。文本位于candidates[0].content.parts[0].text。 **candidates**object[]已生成的候选;除非你要求更多,否则只有一个。 **candidates\[].content**object**candidates\[].content.role**string可选值:model**candidates\[].content.parts**object[]**candidates\[].content.parts\[].text**string已生成的文本。 **candidates\[].content.parts\[].functionCall**object当模型选择调用你的某个tools时出现。 **candidates\[].content.parts\[].functionCall.name**string**candidates\[].content.parts\[].functionCall.args**object**candidates\[].finishReason**string生成停止的原因:STOP、MAX_TOKENS、SAFETY等。 **usageMetadata**object本次调用的 token 统计。 **usageMetadata.promptTokenCount**integer提示词中的 token 数量。 **usageMetadata.candidatesTokenCount**integer已生成候选中的 token 数量。 **promptFeedback**object当提示词本身被拦截时出现。在读取结果之前,请先检查candidates是否存在;被拦截的响应中也可能出现usageMetadata。 **promptFeedback.blockReason**string提示词被拦截的原因。此时不会返回任何候选;请重新表述提示词后重试。 可选值:SAFETY、OTHER、BLOCKLIST、PROHIBITED_CONTENT、IMAGE_SAFETY## 示例 ### 输入`json theme={null} { "contents": [ { "role": "user", "parts": [ { "text": "Describe a single red maple leaf on a white background in one sentence." } ] } ], "generationConfig": { "temperature": 0.7, "maxOutputTokens": 256 } }`### 输出`json theme={null} { "candidates": [ { "content": { "role": "model", "parts": [ { "text": "A single red maple leaf rests on a plain white background, its edges sharp and its color deep." } ] }, "finishReason": "STOP" } ], "usageMetadata": { "promptTokenCount": 18, "candidatesTokenCount": 24 } }``
[tab] Gemini 2.5 Flash 模型 ID:vertexai/gemini-2.5-flash端点:POST https://api.comfy.org/v2/models/vertexai/gemini-2.5-flash> [tab] 等待结果 > > ``python Python theme={null} > import asyncio > from comfy_sdk import AsyncComfy > > # Reads COMFY_API_KEY from the environment. > # The SDK automatically creates an idempotency key and reuses it for automatic retries. > async def main(): > async with AsyncComfy() as client: > result = await client.models.run( > "vertexai/gemini-2.5-flash", > { > "contents": [ > { > "role": "user", > "parts": [ > { > "text": "Describe a single red maple leaf on a white background in one sentence.", > }, > ], > }, > ], > "generationConfig": { > "temperature": 0.7, > "maxOutputTokens": 256, > }, > }, > ) > > print("text:", result["candidates"][0]["content"]["parts"][0]["text"]) > > asyncio.run(main()) >`> >`typescript TypeScript theme={null} > import { comfy } from "@comfyorg/sdk"; > > // Reads COMFY_API_KEY from the environment. > // The SDK automatically creates an idempotency key and reuses it for automatic retries. > type Result = { candidates: { content: { parts: { text: string }[] } }[] }; > const result = await comfy.models.run<Result>("vertexai/gemini-2.5-flash", { > contents: [ > { > role: "user", > parts: [ > { > text: "Describe a single red maple leaf on a white background in one sentence.", > }, > ], > }, > ], > generationConfig: { > temperature: 0.7, > maxOutputTokens: 256, > }, > }); > if (result.kind !== "json") throw new Error("expected a JSON result"); > > console.log("text:", result.data.candidates[0].content.parts[0].text); >`> >`bash cURL theme={null} > curl https://api.comfy.org/v2/models/vertexai/gemini-2.5-flash \ > -H "X-API-Key: $COMFY_API_KEY" \ > -H "Idempotency-Key: $(uuidgen)" \ > -H "Content-Type: application/json" \ > -d "{\"contents\": [{\"role\":\"user\",\"parts\":[{\"text\":\"Describe a single red maple leaf on a white background in one sentence.\"}]}], \"generationConfig\": {\"temperature\":0.7,\"maxOutputTokens\":256}}" >`> [tab] 排队并稍后收集 > > 将相同的请求体发送到POST https://api.comfy.org/v2/models/vertexai/gemini-2.5-flash/requests。Router 会在运行被受理后立即返回201和request_id,结果就绪后即可从本进程或其他进程收集。[队列投递](https://docs.comfy.org/zh/development/comfy-router/queue.md)详细介绍了状态查询、取消和结果收集。 > >`python Python theme={null} > import asyncio > from comfy_sdk import AsyncComfy > > # Reads COMFY_API_KEY from the environment. > # Each submit() call mints its own Idempotency-Key and reuses it for automatic retries. > async def main(): > async with AsyncComfy() as client: > handle = await client.models.submit( > "vertexai/gemini-2.5-flash", > { > "contents": [ > { > "role": "user", > "parts": [ > { > "text": "Describe a single red maple leaf on a white background in one sentence.", > }, > ], > }, > ], > "generationConfig": { > "temperature": 0.7, > "maxOutputTokens": 256, > }, > }, > ) > print("request_id:", handle.request_id) # with the model ID, all another process needs > > # Poll until the request completes, waiting the Retry-After the server names. > async for update in handle.iter_events(): > print(update.status, update.queue_position) > > # The provider's own payload, the same value models.run() returns. > # A request that failed or was cancelled raises the typed Router error here. > result = await handle.get() > > print("text:", result["candidates"][0]["content"]["parts"][0]["text"]) > > asyncio.run(main()) >`> >`typescript TypeScript theme={null} > import { comfy } from "@comfyorg/sdk"; > > // Reads COMFY_API_KEY from the environment. > // Each submit() call mints its own Idempotency-Key and reuses it for automatic retries. > type Result = { candidates: { content: { parts: { text: string }[] } }[] }; > const handle = await comfy.models.submit<Result>("vertexai/gemini-2.5-flash", { > contents: [ > { > role: "user", > parts: [ > { > text: "Describe a single red maple leaf on a white background in one sentence.", > }, > ], > }, > ], > generationConfig: { > temperature: 0.7, > maxOutputTokens: 256, > }, > }); > console.log("requestId:", handle.requestId); // with the model ID, all another process needs > > // Poll until the request completes, waiting the Retry-After the server names. > for await (const update of handle.events()) { > console.log(update.status, update.queuePosition); > } > > // The same result models.run() returns. A request that failed or was cancelled rejects here. > const result = await handle.get(); > if (result.kind !== "json") throw new Error("expected a JSON result"); > > console.log("text:", result.data.candidates[0].content.parts[0].text); >`> >`bash cURL theme={null} > # 1. Submit. Router answers 201 with request_id, status_url, response_url and cancel_url. > curl https://api.comfy.org/v2/models/vertexai/gemini-2.5-flash/requests \ > -H "X-API-Key: $COMFY_API_KEY" \ > -H "Idempotency-Key: $(uuidgen)" \ > -H "Content-Type: application/json" \ > -d "{\"contents\": [{\"role\":\"user\",\"parts\":[{\"text\":\"Describe a single red maple leaf on a white background in one sentence.\"}]}], \"generationConfig\": {\"temperature\":0.7,\"maxOutputTokens\":256}}" > > # 2. Poll until status is COMPLETED, waiting the Retry-After seconds each response names. > REQUEST_ID="<request_id from the 201 body>" > curl -i https://api.comfy.org/v2/models/vertexai/gemini-2.5-flash/requests/$REQUEST_ID/status \ > -H "X-API-Key: $COMFY_API_KEY" > > # 3. Collect. 200 with the model's native output, 202 with the status body while it is still running. > curl https://api.comfy.org/v2/models/vertexai/gemini-2.5-flash/requests/$REQUEST_ID \ > -H "X-API-Key: $COMFY_API_KEY" >`## Schema ### 输入 *这些字段遵循 Google 公布的 API 规范,并在 CI 中对照该规范进行校验。Router 针对此模型自身的 Schema 尚未发布,因此请求会未经校验直接转发给提供商。* **contents**object[]*required* 目前为止的对话内容,按从最旧到最新的顺序排列。part 可以是text,也可以是inlineData,用于在提示词之外一并发送图像、音频或视频。 **contents\[].role**string*required* 该轮对话的作者。 可选值:user、model**contents\[].parts**object[]*required* 该轮对话的内容部分。 **contents\[].parts\[].text**string文本部分。 **contents\[].parts\[].inlineData**object内联媒体部分。 **contents\[].parts\[].inlineData.mimeType**string媒体类型,例如image/png。 **contents\[].parts\[].inlineData.data**stringBase64 编码的媒体字节。 **systemInstruction**object应用于整个对话的系统提示词。 **systemInstruction.parts**object[]**systemInstruction.parts\[].text**string**generationConfig**object采样与长度设置。 **generationConfig.temperature**number采样的随机性。默认值因模型而异。 范围:0到2**generationConfig.topP**number核采样阈值。默认值因模型而异。 **generationConfig.topK**integerTop-k 采样截断值。默认值因模型而异。 **generationConfig.maxOutputTokens**integer已生成 token 数量的上限。 **generationConfig.seed**integer用于可复现采样的种子。 **generationConfig.stopSequences**string[]一旦生成就会终止生成的字符串。 **generationConfig.thinkingConfig**object在支持该功能的模型上控制推理投入。 **generationConfig.thinkingConfig.thinkingLevel**string可选值:MINIMAL、LOW、MEDIUM、HIGH**generationConfig.thinkingConfig.includeThoughts**boolean在返回答案的同时返回模型的推理过程。 **tools**object[]模型可以调用的函数声明。 **tools\[].functionDeclarations**object[]**tools\[].functionDeclarations\[].name**string**tools\[].functionDeclarations\[].description**string**tools\[].functionDeclarations\[].parameters**object该函数参数的 JSON Schema。 ### 输出 Router 会原样返回 Google 的原生响应。文本位于candidates[0].content.parts[0].text。 **candidates**object[]已生成的候选;除非你要求更多,否则只有一个。 **candidates\[].content**object**candidates\[].content.role**string可选值:model**candidates\[].content.parts**object[]**candidates\[].content.parts\[].text**string已生成的文本。 **candidates\[].content.parts\[].functionCall**object当模型选择调用你的某个tools时出现。 **candidates\[].content.parts\[].functionCall.name**string**candidates\[].content.parts\[].functionCall.args**object**candidates\[].finishReason**string生成停止的原因:STOP、MAX_TOKENS、SAFETY等。 **usageMetadata**object本次调用的 token 统计。 **usageMetadata.promptTokenCount**integer提示词中的 token 数量。 **usageMetadata.candidatesTokenCount**integer已生成候选中的 token 数量。 **promptFeedback**object当提示词本身被拦截时出现。在读取结果之前,请先检查candidates是否存在;被拦截的响应中也可能出现usageMetadata。 **promptFeedback.blockReason**string提示词被拦截的原因。此时不会返回任何候选;请重新表述提示词后重试。 可选值:SAFETY、OTHER、BLOCKLIST、PROHIBITED_CONTENT、IMAGE_SAFETY## 示例 ### 输入`json theme={null} { "contents": [ { "role": "user", "parts": [ { "text": "Describe a single red maple leaf on a white background in one sentence." } ] } ], "generationConfig": { "temperature": 0.7, "maxOutputTokens": 256 } }`### 输出`json theme={null} { "candidates": [ { "content": { "role": "model", "parts": [ { "text": "A single red maple leaf rests on a plain white background, its edges sharp and its color deep." } ] }, "finishReason": "STOP" } ], "usageMetadata": { "promptTokenCount": 18, "candidatesTokenCount": 24 } }``
发布前须知
SDK 会生成 Idempotency-Key 并在自动重试中复用它。手动重试时,请复用原始 key。Router 最长可保持连接 10 分钟。
请求失败时,Router 会发送 X-Comfy-Error-Type 响应头说明原因。422 表示 Router 在调用提供商之前就拒绝了输入,413 表示请求体超出了 Router 可接受的大小。已生成的资源请及时下载,因为结果 URL 会过期。
上文任何字段描述中提到的尺寸限制,都是提供商对该字段自身的限定,引自提供商的规范。Router 会对整个请求体另行设置上限,base64 编码的媒体内容也计入其中:参见请求体大小。
本页记录的是通过 Comfy Router 调用的某一个合作伙伴模型。同一个 comfy-sdk / @comfyorg/sdk 包还提供第二个客户端,用于在 Comfy Cloud 上运行完整的 ComfyUI 工作流图:Comfy(api_key=...) / new Comfy({ apiKey }),并带有 client.workflows、client.assets 和 client.jobs。请参阅 Comfy SDKs。
[card] 请求头 身份验证、幂等性、请求 ID、错误分类、重试节奏、消费限额。
[card] 使用 Router API 模型发现、验证错误、重试与计费。
[card] 限制 Router 目前不支持的功能,以及替代方案。