contents = new ArrayList<>();
// text prompt
contents.add(ContentItem.builder()
.type(ContentType.TEXT)
.text(prompt)
.build());
// Create a video generation task
CreateContentGenerationTaskRequest createRequest = CreateContentGenerationTaskRequest.builder()
.model(model)
.content(contents)
.generateAudio(generateAudio)
.ratio(videoRatio)
.duration(videoDuration)
.watermark(showWatermark)
.tools(Collections.singletonList(webSearchTool))
.build();
CreateContentGenerationTaskResponse createResult = service.createContentGenerationTask(createRequest);
System.out.println(createResult);
// Get the details of the task
String taskId = createResult.getId();
String getRequest = taskId;
// Polling query section
System.out.println("----- polling task status -----");
while (true) {
try {
ContentGenerationTask getResponse = service.getContentGenerationTask(getRequest);
String status = getResponse.getStatus().toString();
if ("succeeded".equalsIgnoreCase(status)) {
System.out.println("----- task succeeded -----");
System.out.println(getResponse);
break;
} else if ("failed".equalsIgnoreCase(status)) {
System.out.println("----- task failed -----");
System.out.println("Error: " + getResponse.getStatus());
break;
} else {
System.out.printf("Current status: %s, Retrying in 10 seconds...", status);
TimeUnit.SECONDS.sleep(10);
}
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
System.err.println("Polling interrupted");
break;
}
}
}
}
```
**选项:Go**
```Go
package main
import (
"context"
"fmt"
"os"
"time"
"github.com/volcengine/ark-runtime-go/arkruntime"
model "github.com/volcengine/ark-runtime-go/arkruntime/model/contentgeneration"
)
func main() {
// Make sure that you have stored the API Key in the environment variable ARK_API_KEY
// Initialize the Ark client to read your API Key from an environment variable
client := arkruntime.NewClientWithApiKey(
// Get your API Key from the environment variable. This is the default mode and you can modify it as required
os.Getenv("ARK_API_KEY"),
// The base URL for model invocation
arkruntime.WithBaseUrl("https://ark.cn-beijing.volces.com/api/v3"),
)
ctx := context.Background()
// Model ID
modelID := "doubao-seedance-2-0-260128"
// Text prompt
prompt := "微距镜头对准叶片上翠绿的玻璃蛙。焦点逐渐从它光滑的皮肤,转移到它完全透明的腹部,一颗鲜红的心脏正在有力地、规律地收缩扩张。"
// Output video parameters
generateAudio := true
videoRatio := "16:9"
videoDuration := int64(11)
showWatermark := true
// Create ContentGenerationTool
tools := []model.Tool{
{Type: model.ToolTypeWebSearch},
}
// Generate a task
fmt.Println("----- create request -----")
createReq := &model.CreateContentGenerationTaskRequest{
Model: modelID,
GenerateAudio: model.NewOptBool(generateAudio),
Ratio: model.NewOptString(videoRatio),
Duration: model.NewOptInt64(videoDuration),
Watermark: model.NewOptBool(showWatermark),
Tools: tools,
Content: []model.ContentItem{
{
// Combination of text prompt and parameters
Type: model.ContentTypeText,
Text: model.NewOptString(prompt),
},
},
}
createResp, err := client.CreateContentGenerationTask(ctx, createReq)
if err != nil {
fmt.Printf("create content generation error: %v\n", err)
return
}
taskID := createResp.ID
fmt.Printf("Task Created with ID: %s\n", taskID)
// 2. Poll task status
pollTaskStatus(ctx, client, taskID)
}
// poll task status
func pollTaskStatus(ctx context.Context, client *arkruntime.Client, taskID string) {
fmt.Println("----- polling task status -----")
for {
getReq := taskID
getResp, err := client.GetContentGenerationTask(ctx, getReq)
if err != nil {
fmt.Printf("get content generation task error: %v\n", err)
return
}
status := getResp.Status
if status == "succeeded" {
fmt.Println("----- task succeeded -----")
fmt.Printf("Task ID: %s \n", getResp.ID)
fmt.Printf("Model: %s \n", getResp.Model)
fmt.Printf("Video URL: %s \n", getResp.Content.Or(model.TaskContent{}).VideoURL.Or(""))
fmt.Printf("Completion Tokens: %d \n", getResp.Usage.Or(model.TaskUsage{}).CompletionTokens)
fmt.Printf("Created At: %d, Updated At: %d\n", getResp.CreatedAt.Or(0), getResp.UpdatedAt.Or(0))
return
} else if status == "failed" {
fmt.Println("----- task failed -----")
if getResp.Error.IsSet() {
fmt.Printf("Error Code: %s, Message: %s\n", getResp.Error.Value.Code, getResp.Error.Value.Message)
}
return
} else {
fmt.Printf("Current status: %s, Retrying in 10 seconds... \n", status)
time.Sleep(10 * time.Second)
}
}
}
```
## 更多能力
Seedance 2.0 系列模型也支持文生视频、首帧图生视频、首尾帧图生视频、自定义视频输出规格(包括:分辨率、宽高比、视频时长、视频中是否包含水印)等通用基础能力,详情请参见 [视频生成教程](/docs/video-generation-tutorial)。
# 便利创作
Seedance 2.0 系列模型不支持直接上传含有真人人脸的参考图/视频。为便利创作者使用肖像,平台推出了以下解决方案,详细教程请参见 [Doubao Seedance 便利创作含肖像视频](/docs/seedance-portrait-asset-guide):
|方案 |介绍 |
|---|---|
|[信任模型产物作为输入素材](/docs/seedance-portrait-asset-guide#trust-model-output) | 本账号下部分模型生成的含人脸原始产物可作为输入素材,再次调用 Seedance 2.0 系列模型进行二次创作,不会触发输入审核拦截。 |
| [使用预置虚拟人像](/docs/seedance-portrait-asset-guide#preset-avatar) |平台预置虚拟人像库,为创作者提供免费、合规、丰富多样的肖像素材。适用于需真人风格人脸但无需指定具体人物,追求零合规风险、快速创作的场景。 |
|[使用已授权真人素材](/docs/seedance-portrait-asset-guide#authorized-real-person) |支持使用已获得授权的真人肖像素材进行视频生成。 |
# 提示词技巧
## 提示词 Skill
平台提供 **Seedance 2.0 提示词优化技能**,方便您对提示词进行调优。
* **配置方式**:推荐在本地项目中运行以下命令,通过方舟文档 Skills catalog 安装 `sd2-pe`:
```bash
npx --yes skills@latest add "https://arkdocs.tos-cn-beijing.volces.com/skills/" \
--skill sd2-pe \
--yes
```
如需手动安装,可以下载以下 `SKILL.md` 文件。以 OpenClaw 为例,将文件完整内容复制到对话输入框中,并发送“请帮我安装这个技能”,等待工具完成安装。
[SKILL.md](https://arkdocs.tos-cn-beijing.volces.com/files/video-generation/SKILL.md)
* **使用方式**:在 AI 对话框输入 `/sd2-pe + 你的提示词内容`,开始调试提示词。
## 提示词规则
- 提示词中必须使用"**素材类型+序号**”格式引用素材,序号为请求体中该素材在同类素材中的排序。例如 「图片 n」指代`content`数组中第 n 个`type="image_url"`的参考图片(按数组顺序从1开始计数)。**注意不支持使用 Asset ID 指代素材**。
- 不同任务的提示词公式及详细规则请参见 [Doubao Seedance 2.0 系列提示词指南](/docs/seedance-2-0-prompt-guide)。
# 使用限制
参见 [使用限制](/docs/seedance-2-0#66cb028f)。
# 常见问题
## 10bit 位深与 H.265/HEVC 编码视频播放兼容性说明
以下为各平台浏览器及播放器对 10bit 位深与 H.265/HEVC 编码视频的播放兼容性测试结论,实际效果可能因设备配置有所差异。
**推荐使用:**
- **macOS 端**:浏览器推荐 Safari、Chrome,播放器推荐 VLC、mpv、QuickTime Player
- **Windows 端**:浏览器推荐 Edge、Chrome,播放器推荐 VLC、mpv
### Windows 平台
**选项:浏览器**
| 浏览器 | 支持情况 |
|------|---------|
| Chrome | 有条件支持 |
| Edge | 有条件支持 |
| Firefox | 有条件支持 |
| 360 浏览器 | 有条件支持 |
| QQ 浏览器 | 有条件支持 |
| Opera | 有条件支持 |
**选项:播放器**
| 播放器 | 支持情况 |
|------|---------|
| VLC | 支持 |
| 系统「电影和电视」 | 有条件支持 |
| PotPlayer | 有条件支持 |
| 迅雷影音 | 支持 |
| QQ 影音 | 有条件支持 |
| MPC-HC / MPC-BE | 有条件支持 |
| mpv | 支持 |
| KMPlayer | 支持 |
> **有条件支持说明**:需具备较高的硬件解码能力。已知在 Intel i7 + NVIDIA RTX 4070 + Windows 11 及更高配置下可正常播放,其他配置建议以实际测试为准。
### macOS 平台
**选项:浏览器**
| 浏览器 | 支持情况 |
|------|---------|
| Safari | 支持 |
| Chrome | 有条件支持 |
| Edge | 有条件支持 |
| Firefox | 有条件支持 |
| Opera | 有条件支持 |
**选项:播放器**
| 播放器 | 支持情况 |
|------|---------|
| VLC | 支持 |
| QuickTime Player | 支持 |
| IINA | 支持 |
| mpv | 支持 |
| Infuse | 支持 |
| Kodi | 有条件支持 |
> **有条件支持说明**:需具备较高的硬件解码能力。已知 Apple M2 及以上机型可正常播放,M1 及以下机型建议以实际测试为准。
## 视频画面存在跳变
**典型现象**
**首帧图生视频**、**首尾帧图生视频**场景中,生成视频部分帧出现画面拉伸、压缩等跳变问题。
**根因分析**
输入图片与输出视频的分辨率宽高不一致,引发视频画面帧间跳变。
**解决方案**
1. 裁剪输入图片:参考 Seedance 2.0 系列模型支持的宽高像素值表格(见 [创建视频生成任务 API](/docs/create-video-generation-task-api) ratio 字段),将输入图片裁剪为目标宽高像素值。
2. 将 API 的 **ratio** 字段设置为`adaptive`。
3. 使用 Seedance 2.0 系列模型重新发起首帧/首尾帧图生视频任务。
---
# Doubao Seedance 2.0 系列提示词指南
Source: https://ark.volcengine.com/region:cn-beijing/docs/seedance-2-0-prompt-guide
Doubao Seedance 2.0 系列(下文简称 Seedance 2.0 系列)模型原生支持音频与视频联合生成,拥有卓越的语义理解与全模态交互能力。本文介绍 Seedance 2.0 系列模型的提示词(Prompt)使用方法和相关技巧,帮助您更高效地利用该模型生成符合需求的优质视频作品。
> **注意**
>
> 本指南中呈现的所有视觉(图片、视频)及音频素材,均由 Seedance/Seedream 系列视觉生成模型自主生成。
# 基础公式
Seedance 2.0 系列模型支持同时参考视频、图片、音频等全模态素材,能精准锁定人物样貌、动作特效、视觉风格、配音音色等特征,大幅降低提示词编写门槛。基于这一优势,我们可以通过简单的基础公式来引导模型,利用全模态素材的特点,快速生成满足特定需求的视频。
参考生视频可细分为三类任务:全模态参考、编辑视频和延长视频。您可根据任务类型选择提示词基础公式。
## 全模态参考
从素材中提取部分元素(如主体、风格、场景、音效),生成一个全新视频。
* **适用场景**:动作迁移、主体复用、氛围借鉴等
* **推荐句式**:
* **图片参考**:参考`<图片N>`中的`<主体N>`,生成...
* **视频参考**:参考`<视频N>`中的`<动作/运镜/风格/音效>`,生成...
* **音频参考**:参考`<音频N>`中的音色,生成...
## 编辑视频
在原视频基础上进行局部或全局修改。未提及的部分,默认保持不变。
* **适用场景**:局部替换、主体抹除、属性修改等
* **推荐句式**:
* **增加元素**:清晰描述`<元素特征>` + `<出现时机>` + `<出现位置>`
* **修改元素**:严格编辑`<视频N>`,将其中的`<原特征>`修改为`<新特征>`
* **删除元素**:点明需要删除的元素,对于保持不变的元素,在提示词中加以强调,表现更佳
## 延长视频
在时间维度上延续原视频,要求音视频风格、主体与叙事保持一致。
* **适用场景**:续写剧情、延展动作、补全片段等
* **推荐句式**:
* **延长视频**:向前/向后延长`<视频N>`,生成...
* **轨道补全**:`<视频1>` + `<过渡画面描述>` + 接 `<视频2>` + `<过渡画面描述>` +接 `<视频3>`
> **注意**
>
> 编辑 / 延长视频任务,直接使用“`<视频N>`” 指代视频,请勿使用“参考`<视频N>`”,以免被误判为参考任务。
## 组合任务
上述3种任务也支持组合使用。
* **适用场景**:参考某个素材,编辑另一个素材。
* **推荐句式**:
* 参考`<图片/视频N>`的`[参考维度]`,严格编辑`<视频X>`,`[具体编辑内容]`
# 进阶公式
Seedance 2.0 本质上是一个全模态 AI 导演:同时读取你的文字提示词、图片、视频、音频,并在内部拆成 “空间层”(画面里有什么)和 “时间层”(事情如何随时间变化)两个维度来理解和生成画面。
因此,好的提示词不是单纯的 “文案型形容”,而是 “工程型指令”:谁、在什么场景、做什么动作、镜头如何运动、按怎样的时间顺序发生,分别投递给空间层和时间层。具体公式如下:
```text
提示词进阶公式:精准主体 + 动作细节 + 场景环境 + 光影色调 + 镜头运镜 + 视觉风格 + 画质 + 约束条件
```




简单说就是,先锁定“谁”在“干什么”,再交代“在哪”,“什么氛围”,然后告诉模型“怎么拍”,最后用风格、画质和约束条件把结果收紧。下面详细拆解各要素。
## 1 定义主体
实际参考的素材,一张图片中往往存在多个主体,为了精准引用素材中的特定对象,必须进行明确的主体定义。主体可以是人物、道具、场景等。
**选项:基本定义方式**
* **推荐句式**: 将`<图片/视频N>`中的`[主体核心特征]`定义为`<主体N> `
* **核心特征要求**:使用 2–3 个清晰、稳定的静态特征(如服饰、发型、外观、类别)进行描述,确保唯一可识别性
* **示例**:
* 将**图片1**中穿红色连衣裙、戴草帽的女人定义为**主体1**
* 将**图片1**中穿红色连衣裙、戴草帽的女人定义为**张红**
**选项:多素材同主体**
当多个素材中的对象指向同一主体时,应统一绑定:
* **推荐句式**: 将**图片1**中的`[...]`、**图片2**中的`[...]`定义为 **`<主体N>`**
**选项:多主体场景**
当视频中存在多个主体时,需要分别定义,并使用标签区分。标签应具备唯一性与稳定性,后续描述中需持续使用对应标签,避免指代混乱。
* **推荐句式**: 将<图片/视频N>中的[主体1核心特征]定义为<主体1>,将<图片/视频N>中的[主体2核心特征]定义为<主体2>...
* **示例**: 将**视频1**中的高个子男人定义为**警察**,将另一个矮个子男人定义为**小偷**。场景设定为拥挤的白天集市,阳光明媚,周围有许多水果摊位和密集的行人,充满市井生活气息。**小偷**在拥挤的集市人群中惊慌失措地向前狂奔, **警察**在后方紧随其后全速追赶,两人快速穿梭在各个摊位之间。手持镜头向前快速跟拍,画面带有轻微真实的晃动感,营造追逐的紧张氛围。
> **注意**
>
> * 每次涉及主体时需明确指代,避免省略。支持以下两种用法:
>
> * 对于未定义主体的简单场景,每次提到主体时,都要使用`<主体N>@<图片N>`,强调主体和素材的绑定关系。例如:张三@图片1。
>
> * 对于已提前定义主体的场景,每次提到主体时,都应使用同一标签。例如:将**视频1**中的高个子男人定义为**警察**,将另一个矮个子男人定义为**小偷**。后续描述涉及到高个子男人持续使用“**警察**”指代,涉及到矮个子男人持续使用“**小偷**”指代。
> * 使用素材库(Asset ID)时,仍需使用`<图片/视频N>`指代主体。因模型无法直接关联 Asset ID 与参考内容,故不得直接以 Asset ID 替代`<图片/视频N>`。
> * 描述尽量简洁,避免冗余,避免语义冲突(如同一主体出现矛盾特征)。
> * 空间关系建议优先通过参考图表达,减少复杂文字描述。
## 2 使用分镜时序
模型的内部建模是空间和时间解耦的。因此,一个复杂视频的提示词,最理想的形态是时间轴化分镜:把视频拆成几个分镜,按事件发生顺序动态描述每个分镜: 谁 + 在哪 + 做什么 + 镜头怎么动。
**实操建议**
使用镜头顺序,对每一段视频都写一个简单的 “镜头 1 / 镜头 2 / 镜头 3” 分镜,再合并成完整的提示词。
* **反面案例**:“男人在街头紧张地奔跑,画面很有电影感。”
* **正面案例**:
* 镜头 1:街巷侧拍,男人缓慢起跑,带有急促的呼吸感。
* 镜头 2:男人撞翻水果摊,镜头快速摇动并给到男人惊恐的特写。
* 镜头 3:男人翻过矮墙消失,镜头缓慢拉远定格在空荡的街道。
**具体规则**
* 使用`镜头1`、`镜头2`、`镜头3`等标识,按事件发生顺序(先主后次)组织内容。不强制限制每段时长,优先让模型根据剧情自然生成节奏。
> **说明**
>
> 模型对精确时间(如 0–3 秒)的支持不稳定,强行限制时长可能导致生成结果异常。
* 每个镜头推荐按以下逻辑组织:
1. **运镜或镜头切换方式**:如 “全景缓慢推近”“固定机位”“镜头切至…” 等。
2. **主体动作与表情**:描述核心角色 / 物体的关键动作、神态变化。
3. **位置或空间变化**:说明主体所处的场景、位置或空间关系。
4. **音频信息**:描述对应镜头的音效、人声或背景音乐等。
## 3 **动作描述要求**
* **肢体细化 + 程度量化**
动作需具体到手、腿、头部、肩背等肢体部位,同时补充**幅度、速度、力度**描述;
示例:缓慢抬手、快速转头、用力蹬地、微微低头。
* **优先低缓连续小动作**
优先选用缓慢、轻柔、连贯的细微动作,尽量规避狂奔、大跳、剧烈翻滚等高爆发、大动态动作。
示例:缓慢行走、轻轻抬手、微微低头、顺势坐下
* **补充动作过渡衔接**
写明前后动作的惯性与承接关系,保证画面动作连贯自然。
示例:借着转身惯性顺势抬手、从停顿状态自然过渡到举手。
* **情绪具象外化表达**
用具体的身体细节表现情绪,替代 “很悲伤”“非常愤怒” 这类抽象词汇。
具体示例参见下表:
|抽象情绪 |外化为动作与细节 |
|---|---|
|悲伤 |低头、肩膀微微颤抖、眼眶泛红、手指无意识地攥紧衣角、泪水在眼眶里打转但没有落下 |
|喜悦 |嘴角抑制不住地上扬、眉眼舒展、脚步变得轻快、下意识地哼起小曲、忍不住原地转个圈 |
|紧张 / 焦虑 |频繁地看手表、手指不停敲击桌面、呼吸急促、眼神闪躲、无意识地啃咬指甲 |
|愤怒 |双拳紧握、下颌线紧绷、胸口剧烈起伏、眼神如刀般锐利、从牙缝里挤出话语 |
|释然 |长长地舒了一口气、紧绷的肩膀完全放松下来、脸上露出久违的、淡淡的微笑、抬头望向远方 |
## 4 运镜写法
模型对运镜词理解力很强,直接使用标准运镜术语即可,例如 “中景、特写、全景、缓慢推镜、平稳横移、固定镜头” 。更多请参见 [镜头语言](/docs/seedance-1-0-pro-pro-fast#afc80793)。
> **注意**
>
> 一个镜头里尽量只指定 1 种运镜方式,不要同时要求推拉摇移,会增加画面的不稳定性。
## 5 画质、风格与约束词
画质、风格与约束词是把控视频生成效果的关键,能够为模型划定创作边界、统一画质与美术调性,同时规避画面瑕疵与随机偏差,是保障成片效果稳定合规的必要配置。
**1 画质**
定义画面清晰度、细节纹理与光影质感,提升成片基础画质。
**示例**:高清,细节丰富,电影质感,色彩自然,光影柔和
**2 风格**
设定整体美术画风与视觉调性,统一画面艺术氛围。
**示例**:赛博朋克冷蓝紫色调、复古胶片、日系清新
**3 约束词**
约束词十分重要,可有效规避画面瑕疵、畸形崩坏及不合理元素,约束生成边界与稳定性。
**常用约束词模板**:
* **避免生成字幕**:“保持无字幕”、“避免生成任何文字或字幕”
* **避免生成 Logo**:“不要生成Logo”
* **避免生成水印**:“不要生成水印”
## 6 实战案例
展示如何使用上文介绍的进阶公式和各要素来编写提示词。
**选项:示例1:宿舍情感短剧(偏文戏 / 对话)**
**素材准备**:
* @图片 1:女主半身照
* @图片 2:宿舍场景参考图
* @视频 1:室内对话运镜参考(中景推拉或轻微摇移)
* @音频 1:室内环境声或轻音乐
**提示词**:
@图片 1 中的女孩作为主角,@图片 2 作为宿舍场景风格参考,参考 @视频 1 的运镜方式。
**镜头 1**:傍晚时分,**女孩 @图片 1** 脚步轻快地走到**宿舍门口 @图片 2**,镜头中景平稳跟拍,暖黄色日光从窗外洒进走廊,她在门口停顿一下,深呼吸,表情略带紧张。
**镜头 2**:**女孩 @图片 1** 推开门走进宿舍,镜头切到室内中景,舍友们一边整理书本一边抬头看向她,其中一人笑着问 {考得怎么样呀,过了吗},镜头在几人之间缓慢切换半身特写。
**镜头 3**:**女孩 @图片 1** 先低头露出落寞表情,镜头给到她的近景,随后她抬头憋不住笑意,哈哈大笑说 {骗你们的},舍友们追着打闹起来,镜头缓慢拉远,定格在宿舍内一片欢声笑语的全景画面。
全程画面高清电影纪实风,色调温暖,光影柔和;人物面部稳定不变形,动作自然流畅,无卡顿无闪烁;环境音效与 @音频 1 自然融合。
**选项:示例2:古风悬崖对手戏(偏动作/氛围)**
**素材准备**:
* @图片 1:红衣女主
* @图片 2:黑衣刺客(对手)
* @图片 3:悬崖竹林场景图
* @视频 1:武打对决运镜参考
* @音频 1:紧凑的鼓点或打斗音效
**提示词**:
@图片 1 的红衣女子作为女主,@图片 2 的黑衣女子作为对手,场景参考 @图片 3 的悬崖竹林环境,整体运镜和动作节奏参考 @视频 1,背景音效与 @音频 1 同步。
**镜头 1**:傍晚,镜头从**红衣女子 @图片 1** 侧面中景缓慢推进,她站在悬崖边拿起酒壶喝酒,衣袂在山风中轻轻摆动,镜头环绕她半圈,从正面推到背影,远处隐约可见竹林中的黑衣人影。
**镜头 2**:镜头变焦渐隐到远景,无人机视角俯瞰整片悬崖和竹林,两人分立山崖两端,山风卷起衣摆和尘土,节奏随鼓点略微加快。
**镜头 3**:镜头切回地面近景,二人缓慢拔剑对峙,**红衣女子@图片 1** 神情从漫不经心转为冷冽,**黑衣女子@图片 2** 目光坚毅,剑尖微微颤动,镜头平稳跟随两人绕圈移动,最后定格在两剑相交前一瞬间的特写。
整体画面烟雨江湖电影感,冷调低饱和,电影胶片质感,光影层次丰富;人物面部和身体比例稳定不变形,动作连贯自然,不僵硬,无穿模无卡顿。
# 其他技巧
## 文字生成
Seedance 2.0 系列模型支持生成常用文字。模型能根据情境**自动匹配**合适的风格与颜色,也支持在提示词中**指定**文字的颜色、风格、出现方式、出现时机、出现位置。编写时请优先使用**常用字**,避免**生僻字**与**特殊符号**,以确保最佳呈现效果。当前支持广告语、字幕、气泡等场景,具体写法和案例请参见[文字生成](/docs/seedance-2-0-prompt-guide#081b2c64)。
## 视频延长 vs 分段拼接
* **连续长镜头(视频延长)**:适用于单一场景内的 “文戏”,如长对话、情绪递进、单一路径移动,以实现沉浸式、连贯的一镜到底效果。
* **场景 / 动作转折(分段拼接)**:适用于剧情转折或复杂、快速的 “武戏”,如追逐、打斗、蒙太奇等,可通过独立生成片段再剪辑组合,保证节奏与视觉冲击力。
实际制作中通常结合两种方式,例如先用延长生成连贯对话,再拼接空镜或转场片段,兼顾沉浸感与节奏变化。
## 素材配置策略
通常把素材分成四种 “功能角色”:
1. 角色锚定:锁定角色外观
2. 场景定调:锁定环境与风格
3. 运镜参考:锁定镜头语言与动作节奏
4. 节奏氛围:用音频控制情绪、音色
**推荐配置**(总计 4-5 个素材):角色图 1-2 张(面部特写 / 全身)+ 场景图 1 张 + 运镜视频 1 段 + 音频 1 段。
> **说明**
>
> 不建议用满素材上限,过多素材会导致模型难以判断特征优先级,易出现风格冲突、主体识别模糊、生成效果偏离预期等问题。
# 注意事项
## 语言规范
台词语言需统一,避免中英文混用(专有名词除外)。
## 特殊字符规范
提示词中合理使用符号有助于模型准确理解不同信息类型:
|信息类型 |符号 |示例 |
|---|---|---|
|音乐 |() |(背景中播放着快节奏的摇滚乐) |
|音效 | <> |<远处传来狗叫声> |
|台词 | {} | {你好,世界}。如果台词为小语种(非中英文),需标注语种,如:用日语说道{こんにちは}。 |
|字幕 |【】 |【第一章:启程】 |
# 常见问题
## 人脸参考不准确
**典型现象**
生成的角色形象与参考图不一致,或在视频中途发生“换脸”,导致视频中人物撞脸明星被审核拦截。
**根因分析**
人脸参考图的有效性不足
* **参考图混用**:将人脸参考图与全身/半身姿态图、服装参考图、细节图等合并在同一张图片中提供给模型。
* **人脸占比过小**:在混用参考图中,人脸区域占整张图的比例过小,模型在提取人脸特征时权重不够,容易被背景或其他元素干扰。
**解决方案**
强化人脸参考的独立性和权重:
1. **准备人脸特写图**:在原有全身照之外,额外准备一张**只包含角色头部的人脸特写图**(大头照,仅保留面部,无表情最佳,尽量减少肩颈、背景等干扰元素)。
2. **提示词中主体定义清晰**:<**主体1> 的面部特征参考图片1(大头照),妆造参考图片2(全身照)**。
3. **重要素材前置**:越需要**精准参考**的素材,放在提示词中**越靠前**的位置。
> **注意**
>
> 人物参考使用大头照 + 全身照即可,**不建议使用人物多视图**。多视图素材包含同一人物的不同角度,模型易将其识别为多个不同主体,反而加剧人脸参考不准确的问题。
|优化前 |优化后 |
|---|---|
|[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/b76c5a82405f4a2e8885d45b74e28b5b) |[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/db53a9c92f48461f96d87900f92955a7) | \
| | | \
|> 视频中人物中途“换脸”,撞脸明星 |> 人脸与参考图全程保持一致 |
## 视频中包含字幕
**典型现象**
提示词中未要求生成字幕,生成的视频中包含字幕。
**解决方案**
> **说明**
>
> 目前无法直接做到 100% 避免生成字幕,只能通过以下方法降低其出现概率、提升抽卡成功率。
1. 在提示词中加入明确的约束指令:“保持无字幕”、“避免生成任何文字或字幕”。
2. 如果参考的图片/视频中包含的文字并非必要信息,建议先通过工具去除文字(例如使用 Seedream/ Seedance 模型的图片/视频编辑能力),再使用无文字素材作为输入。
3. 在业务允许的前提下,优先选择横屏尺寸生成视频(横屏生成字幕的概率明显低于竖屏),后续可通过剪辑软件裁剪为竖屏。
## 视频中有 Logo / 水印
**典型现象**
提示词中未提及水印相关内容,生成的视频包含其他视频平台的 Logo / 水印。
**解决方案**
在提示词中加入明确的约束指令:“不要生成水印”、“不要生成Logo” 。
## 风格漂移
**典型现象**
期望生成 2D 或者 3D 动漫风格,但输入的参考图片的风格比较写实,并且提示词中未强调视频风格,生成的视频有概率漂移成真人写实风格。
**解决方案**
在提示词中加入明确的风格约束词,例如“2D日漫风格”、“3D国风漫画”。如果需要更精准的风格控制,建议将参考图先变为目标风格再进行生视频。
|优化前 |优化后 |
|---|---|
|[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/5e4b8f2372d94fa189ccc881268f744b) |[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/6b870e9532ae4fa3b0ca61356415c32d) | \
| | | \
|> 仙侠风格漂移成真人风格 |> 保持 3D 国漫 CG 仙侠风格 |
## 延长视频衔接处跳变
**典型现象**
使用视频延长功能生成新视频后,将新视频与原视频进行拼接,在衔接处可能出现画面跳变、回退的问题。
**解决方案**
当前建议通过后期剪辑修补,对齐关键帧,后续将依托模型迭代进行根本性优化。
1. 将待拼接的视频导入剪映或其他专业视频剪辑软件。
2. 在第一个衔接处,将**前一段视频的末尾删减 6 帧**。
3. 同时,将**后一段视频的开头删减 1 帧**。
4. 对所有的拼接点重复以上操作。
5. 导出并检查拼接后视频的流畅度。
> **说明**
>
> 视频帧对齐后,仍可能存在细微跳变,建议在续写生成视频的时候以转场切镜的时刻结尾,下一段视频以结尾切镜后的新场景为起始。
|优化前 |优化后 |
|---|---|
|[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/88a85ca9505e4356b8ad00a792f43bb7) |[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/45144713105e407abaa7a8152fc58d6d) | \
| | | \
|> 在衔接处(第 5s,第20s)出现**画面瞬间跳动**或**内容回退** |> 衔接处更加平滑 |
## 双胞胎问题
**典型现象**
在画面人物较多且传入人物三视图作为参考素材的场景下,生成视频同一画面中易出现两个完全相同的人物。
**根因分析**
* 提示词中对人物主体的定义不清晰,模型无法精准区分不同人物角色;
* 以人物三视图 / 多视图作为参考素材时,易造成模型人物识别混淆,从而生成重复同款人物。
**解决方案**
> **说明**
>
> 目前无法直接做到 100% 避免双胞胎问题,只能通过以下方法降低其出现概率、提升抽卡成功率。
1. **明确人物主体关联**
在提示词中清晰定义每个人物角色,明确角色与参考图的对应关系。建议在人物名称后标注对应参考图,并保持格式统一。
示例:张三(对应图片 1)将绿色存折扔向站立的李四(对应图片 2)。
2. **添加全局约束指令**
在提示词末尾增加固定约束:**视频全程禁止出现外形、着装、配饰完全一致的人物,禁止生成同款分身、双胞胎效果,同一画面中仅保留单个对应人物,不出现人物重复复刻**。
3. **优化参考素材**
人物参考图优先使用单人独立照片,不建议使用三视图、多视图素材。
4. **精简优化提示词**
请勿直接将完整剧本作为提示词使用,文案内容过度冗余易造成模型理解混乱,需精简无关表述、保证指令清晰聚焦。
|优化前 |优化后 |
|---|---|
|[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/07cde10b55ac45fea6a8bbb67d47d028) |[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/0fc18ac5b14247209c7355c40fae6337) | \
| | | \
|> 画面第8秒出现“双胞胎” | |
## 视频延长画质劣化
**典型现象**
将模型生成的视频作为输入素材进行延长续写时,会出现画质劣化。多次续写会叠加劣化效果,尤其人物人脸区域易出现斑驳色块。
**解决方案**
当前可通过以下方式缓解画质劣化,后续将依托模型迭代进行根本性优化:
1. 将原始视频通过 Seedance 2.0 转为白模视频,再作为续写输入素材。
参考提示词:将视频转为白色 3D 模型,人物统一为纯白 3D 模型,无色彩、无纹理、无阴影,纯白背景,结构稳定、运动流畅。
2. 优先选用高清图片作为参考素材。
3. 合理控制视频续写次数,避免多次叠加续写。
|优化前 |优化后 |
|---|---|
|[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/0d2224f33882474d81714133ea44328f) |[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/f82a216fc45b42ad8953828e4bc36ff9) | \
| | | \
|> 直接对模型产物进行续写 |> 将模型产物转化为白模视频后再进行续写 |
## 特效效果不符合预期
**典型现象**
通过提示词文字描述特定特效时,可能会出现特效效果与预期不符的情况,例如:提示词指定「数字“2999”以倒计时动画出场」,实际生成的数字滚动特效出现无序跳变,不符合标准倒计时逻辑。
**解决方案**
建议采用**参考视频**定义特效:将目标特效视频作为参考素材输入模型,让模型精准理解特效形态与运动逻辑,生成效果更贴合预期。例如:数字“2999”出场方式参考视频1。
|优化前 |优化后 |
|---|---|
|[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/0698e275fb5b42eba0404e10d66939d7) |[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/a1a54eb006b44ecb91d8256179b04b42) | \
| | | \
|> 数字滚动特效有明显的无序跳变感 |> 增加正确的数字滚动特效视频后,特效结果符合预期 | \
| | | \
| | | \
| |[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/1ccd8fdc1e9c4f37921a4dd1bbcc74a7) | \
| | | \
| |> 特效动画 |
## 参考人物过多
**典型现象**
当参考人物数量超过 4 人时,模型输出稳定性下降,生成的视频可能出现人物数量不符(如少人、多人)或人物重复等问题。
**解决方案**
当前可通过以下方式缓解,后续将依托模型迭代进行根本性优化:
1. **分步生成图片**:将人物分组,确保每组生成的图片中人物数量不超过 4 人。例如,6 个人可分成 2 组,每组 3 人,分别生成图片。
2. **图片生成视频**:使用第一步生成的多张分组图片作为参考素材,再生成最终视频。
|优化前 |优化后 |
|---|---|
|[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/c789760e98c64a42aec36e006550e2f9) |[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/cd7090f6d6694b01b3900d66d5ed36a1) | \
| | | \
|> 输入 8 个参考角色,输出视频有 9 人 |> 将 8 个角色生成 2 张图后,再使用图生视频 |
## 视频结尾有噪音
**典型现象**
视频中包含旁白时,视频片尾容易出现突兀咔哒声、截断杂音。
**解决方案**
重新生成视频,或使用剪映等剪辑工具,对片尾音轨通过**音量包络线**做音频淡出处理,消除截断噪音。
具体步骤 (使用剪映):
1. 将生成的视频导入剪映。
2. 在时间轴上选中视频轨道,点击工具栏中的**音频**。
3. 选择**音量包络线**功能(部分版本位于基础 / 调节菜单内),并选择关键点。此时音频轨道上会出现一条代表音量的线以及关键点。
4. 在视频临近结尾处,将末尾音量关键点下拉至音量为 0,形成一个向下的斜坡。

5. 预览确认片尾音频自然淡出,无突然截断与杂音即可。
|优化前 |优化后 |
|---|---|
|[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/5d94410abb274588b0fa9aa1cd0d303b) |[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/81cb4ef06ce44175a4cc042020b0f9dc) | \
| | | \
|> 结尾有噪音 |> 结尾无噪音 |
## 中文发音不准
**典型现象**
模型对多音字、生僻字、形近字容易读错。
**解决方案**
可将易读错文字替换为**发音一致的常用同音字**,规避发音偏差,还原预期音频效果。注意该方案仅为优化手段,无法完全规避所有发音问题。
示例:可将提示词中“螭龙山”改写为同音字“吃龙山”。
|优化前 |优化后 |
|---|---|
|[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/aceabaeb156f42b0bf040d4e37d8a28d) |[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/5e5841ca25954fb18566452ef17383f8) | \
| | | \
|> "螭龙山"的“螭”发音不对 |> 改成“吃龙山”后发音正确 |
## 音色参考不准
**典型现象**
使用参考音频指定音色时,最终生成视频的音频音色与参考音色存在明显偏差。
**解决方案**
1. 在提示词中补充细致的音色特征描述。
2. 保持视频台词风格与参考音频的语气、表述风格相近,有助于提升音色还原度与稳定性。
|优化前 |优化后 |
|---|---|
|[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/02b2fa5093bb4985897e003306970021) |[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/9fc65b9b93ae496991afa41f28520e87) | \
| | | \
|> 音色与输入音频不匹配 |> 提示词中增加音色特征描述后,音色匹配度明显提升 | \
| |> “使用@音频1低厚温润带细碎颗粒感中年男声的音色说” | \
| | | \
|[音频.mp3](https://p9-arcosite.byteimg.com/tos-cn-i-goo7wpa0wc/7cd70ed1fb50475c903181cc5d3c436b~tplv-goo7wpa0wc-image.image) | | \
| | | \
|> 输入的音频 | |
# 附录:提示词案例
展示在不同场景下使用 Seedance 2.0 系列模型的提示词示例,帮助您更精准地实现全模态参考的指代控制及文字生成等功能。 更多优秀案例请参考 [控制台体验中心 Seedance2.0](https://ark.volcengine.com/region:cn-beijing/experience/gen_video?model=doubao-seedance-2-0-260128) 模板库。

## 文字生成
### 广告语(Slogan)
提示词参考模板:
```Plain Text
「文字内容」+「出现时机」+「出现位置」+「出现方式」,「文字特征(颜色、风格)」
```
> **说明**
>
> Seedance2.0 能根据情境匹配合适的文字风格,如果对文字表现效果的要求较为严格,可参考下文中的`多图参考 > Logo 参考`。
参考案例:
**[成品效果]**
[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/35240ac6fe544bff8c53216beb132039)
**[提示词]**
手绘漫画风格,三个人围坐在一起吃`图片1`中的炸鸡,气氛友好愉悦,后画面逐渐模糊,画面中部显示文字“快乐尽在 Seedance”。
**[参考素材]**

▲ 图片 1
### 字幕
提示词参考模板:
```Plain Text
画面底部出现字幕,字幕内容为“……”,字幕需与音频节奏完全同步。
```
参考案例:
**[成品效果]**
[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/13f58b60c41746a88d27a1b88e9bd5ca)
**[参考素材]**

**[提示词]**
生成带有画外音的视频。一个深沉、平静的男声说:“在宏大的宇宙中,我们的世界不过是一个短暂的瞬间。然而,在其中,生命不顾一切地繁荣。”场景应从夜晚缓慢过渡到黎明,星星逐渐消失,太阳从山后升起。画面底部按照台词出现字幕。
**[成品效果]**
[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/b33da3f7807d421fbd9c5caa0a6ff3da)
**[参考素材]**

**[提示词]**
图片中的两人在办公室聊天,女性先说话,她说道:“你每次卡点到,是不是很享受这种刚刚好的感觉?”男性笑着回应:“我有我的节奏”角色说话时,对话随意自然,画面底部出现对应台词字幕。
### 气泡台词
提示词参考模板:
```Plain Text
「角色」说:“……”,角色说话时周围出现气泡,气泡里写着台词。
```
参考案例:
**[成品效果]**
[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/b53cbfa4a7b847528d1c96dd1e4f6da3)
**[参考素材]**

**[提示词]**
`图片1`中的两人穿着运动服在学校的操场跑步,女孩看向男孩,自信地笑着说:“We can definitely do it! ”镜头切到男孩的近景,他犹豫地回答:“Are you sure? ”镜头切回女孩的中近景,她语气轻快地说:“Yes! ”情绪明亮而坚定。说话的角色周边出现气泡,气泡里是对应台词。
**[成品效果]**
[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/c530f29add364cb4ad359bb80c1395e3)
**[参考素材]**

**[提示词]**
参考`图片1`、`图片2`中的女孩形象,女孩在一个草莓园里,摘下一颗,吃了一口,笑着说:“This is the real deal! ”女孩周围出现一个气泡,气泡里面写着台词。
## 图片参考
Seedance 2.0 系列模型既支持主体多视角参考,也支持场景图、分镜图等多图参考。
使用过程中,如对图片顺序有要求,应**按顺序上传**,提示词中可使用`图片1`、`图片2`……`图片n`进行准确指代。
### 主体多视角图参考
指代清楚参考对象即可,模型能够响应的指令包括但不限于以下示例。
商品:
**3C 数码**
---
**[成品效果]**
[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/d9baa8c1ac934ea1acaed0e56c8b5fb0)
**[参考素材]**

**[提示词]**
提取`图片1`、`图片2`、`图片3`的相机,把背景换成白色,相机在一个白色桌子上,镜头以特写的形式聚焦相机,然后以相机为主体缓慢旋转,清晰展示相机的正面侧面以及背面。
**家居物品**
---
**[成品效果]**
[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/b182c88d13c0483b8294265aca614cda)
**[参考素材]**

**[提示词]**
背景为暖调居家场景,中景呈现参考图中的保温杯,镜头平稳推近至保温杯近景,镜头外一只手自然入镜轻握杯身拿起保温杯,镜头跟拍手部微微旋转动作展示。
---
角色:
**[成品效果]**
[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/25c17dee392e416ca0273cf67d8c310a)
**[提示词]**
参考`图片1`、`图片2`、`图片3`中的女子形象,生成她在一家咖啡店吃蛋糕的画面。
**[参考素材]**

### 多图参考
**Logo 参考**
---
**[成品效果]**
[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/22abee6dea5e499eadde76f8874b45d0)
**[参考素材]**

**[提示词]**
背景是霓虹闪烁的未来都市空中廊道,飞行器与全息广告交织,参考`图片2`中的女孩,先用中景展示女孩放飞带有全息投影的银色悬浮灯,再镜头拉远展现漫天悬浮灯,画面逐渐模糊,后出现`图片1`的 Logo,整体风格为 3D 赛博朋克科幻动画风格。
**多主体参考**
---
**[成品效果]**
[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/9930cc70745944918395490b2809b9f1)
**[参考素材]**

**[提示词]**
参考图片中的猫猫和狗狗,在一个温馨的公寓里,狗狗在趴着吃狗粮,猫猫走过来,伸出爪子碰了碰狗狗,狗狗看到猫猫后停下吃饭,猫猫依偎在狗狗身边。画面采用暖色调。
**多元素参考**
---
**[成品效果]**
[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/c5de349e1c2c4feeb651112d27090b55)
**[参考素材]**

**[提示词]**
场景设定在`图片4`中的餐厅内,店内人来人往。`图片1`里的女孩身着`图片2`中的服装,正在整理柜台上的物品。`图片3`中的男孩是一位顾客,他走上前,想要向女孩索要联系方式。`图片5`中的标识始终显示在画面的右下角。
**多宫格分镜图参考**
---
**[成品效果]**
[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/e907b4ec99624d05822c606bddb8f027)
**[参考素材]**

**[提示词]**
参考图片中的分镜图,生成打斗激烈的打斗场面。图片中的各个分镜构图要按照顺序出现,之后二人激烈打斗。
**分镜图参考**
---
**[成品效果]**
[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/3a3a79effe8941febe9d64b61eaffff9)
**[参考素材]**

**[提示词]**
参考`图片3`中的分镜构图,女孩正在等爸爸做好饭,她说:“아빠, 배고파요! 밥 다 됐어요?”,女孩形象参考`图片1`。接着镜头向右横摇,切换至`图片4`的画面和构图,爸爸形象参考`图片2`,爸爸回答她:“거의 다 됐어, 조금만 기다려!“,接着镜头切换回女儿略显失落的面部表情特写,她说:“아직 멀었어요? 맛있는 냄새 나는데……”,接着切换成爸爸的面部特写,他说:“이제 진짜 금방이야。 "빨리빨리" 하지 말고 손부터 씻고 와!”。
## 视频参考
Seedance 2.0 系列模型支持视频参考,使用时指代清楚生成内容和参考对象即可。
使用过程中,如对视频顺序有要求,应**按顺序上传**,提示词中可使用`视频1`、`视频2`……`视频n`进行准确指代。
### 动作参考
**影视**
---
**[成品效果]**
[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/93e363e70b5d4cf69d39aa73a976cc70)
**[参考素材]**
[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/06ffca9604a14ae4a289bed8cdc115b3)
▲ 视频 1

**[提示词]**
参考`视频1`的人物动作和镜头语言,生成`图片2`和`图片1`的打斗场面,`图片2`是左边人物,`图片1`是右边人物。有激烈的背景音乐。
**营销**
---
**[成品效果]**
[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/9b6fafc6e9f94a888da29c40403cc79b)
**[参考素材]**
[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/95339be0b83b446496bebcaac0ed62e4)
▲ 视频 1
**[提示词]**
参考`视频1`中马的奔跑形态,生成一匹金色的骏马在草原上奔跑,随即定格其奔跑的华丽姿态,变成一个马形的金吊坠。
### 运镜参考
**[成品效果]**
[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/13354294d83f4985be154abae7dec304)
**[提示词]**
参考`视频1`的运镜,做一个科技园区的概念视频,以`图片1`中的高楼为视觉中心,同为第一视角俯冲,体现出`图片1`中园区的科技感。
**[参考素材]**
[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/94aa83c27b7f4731b82b4edda6b8e420)
▲ 视频 1

▲ 图片 1
### 特效参考
**影视**
---
**[成品效果]**
[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/d7968e92ea3241b5b43b0cf0ff545329)
**[参考素材]**
[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/af1f7bd795664a7db0cda6dffad1c730)
▲ 视频 1

▲ 图片 1
**[提示词]**
参考`视频1`的金色粒子特效,让`图片2`中的人物吹笛子的同时,身边环绕一样的粒子特效。
**玩法特效**
---
**[成品效果]**
[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/a08a636518744c8dbe871fa65301baa9)
**[参考素材]**
[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/eac58a8ac3fe464c88d8defcfb28fd7f)
▲ 视频 1

▲ 图片 1
**[提示词]**
参考`视频1`的特效,让`图片1`中的女生长出相同的翅膀,翅膀生成轨迹一致。
## 视频编辑
Seedance 2.0 系列模型支持视频编辑,支持增加、删除或修改元素,视频的向前或向后延长,以及轨道补齐。
使用过程中,如对视频顺序有要求,应**按顺序上传**,提示词中可使用`视频1`、`视频2`……`视频n`进行准确指代。
### 元素增删改
**增加元素**
---
**[成品效果]**
[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/55cae858cbb74d5087d456d8fe434977)
**[参考素材]**
[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/42938974be554af3a602dbe5f5d29375)
▲ 视频 1
**[提示词]**
在`视频1`的台面上添加炸鸡、披萨等小吃。
**删除元素**
---
**[成品效果]**
[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/b77bc49e97214ab29b29b557fdd77676)
**[参考素材]**
[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/bf6418b7c3c544f5aea83c11c7442b98)
▲ 视频 1
**[提示词]**
清除`视频1`桌面上的其他零件和工具,保持桌面整洁干净,桌面上只有他俩手里的。
**修改元素**
---
**[成品效果]**
[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/08616496462d4c588e94045f0ff8fd65)
**[参考素材]**
[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/0a45a3b5ff6c424da49049d7d334279e)
▲ 视频 1

▲ 图片 1
**[提示词]**
将`视频1`中的香水替换成`图片1`中的面霜,动作和运镜不变。
### 视频延长
> **注意**
>
> 模型将自动截取衔接部分进行合成,输入视频原有片段,不会重复生成。
**向后延长**
---
**[成品效果]**
[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/7e1ab1dbeeb04253a39c775c17a29d33)
**[参考素材]**
[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/127e451399294911aa6803c857ee262b)
▲ 视频 1
**[提示词]**
生成`视频1`之后的内容,迟到的两个男士跑向他们,五个人终于见面,友好聊天。
**向前延长**
---
**[成品效果]**
[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/db312f0e771a4b28ad08f71f24cdc71f)
**[参考素材]**
[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/1a2f2a1e351d4367abbf4af1fc69a890)
▲ 视频 1
**[提示词]**
向前延长`视频1`,给白衣男子过肩镜头,白衣男子说:“It’s not that bad. You're just stressed. Everyone goes through this, you just need to keep going.”
### 轨道补齐
> **说明**
>
> * Seedance 2.0 系列模型最多支持 3 段视频输入,总时长不得超过 15 秒。
> * 生成时将自动截取首尾视频的衔接部分,仅保留必要片段参与合成。
参考案例:
**[成品效果]**
[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/70187e67162b44548755d1624eb8a9fe)
**[提示词]**
`视频1`,树叶落地的瞬间,激起金色粒子特效,一阵风吹过,接`视频2`**。**
**[参考素材]**
[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/a9834c4281f04b3596b1367555cbc409)
▲ 视频 1
[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/3a2ca254f5e14d64b2cbcf2a0ebb637c)
▲ 视频 2
---
# 视频生成教程
Source: https://ark.volcengine.com/region:cn-beijing/docs/video-generation-tutorial
Seedance 模型具备出色的语义理解能力,可根据用户输入的文本、图片、视频、音频等全模态内容,快速生成优质的视频片段。本文为您介绍视频生成模型的通用基础能力,指导您调用 [Video Generation API](/docs/create-video-generation-task-api) 生成视频。如需了解各版本模型的特色能力,请参见 [Doubao Seedance 2.5 教程](/docs/seedance-2-5)、[Doubao Seedance 2.0 系列教程](/docs/seedance-2-0)。
# 效果预览
访问 [模型卡片](https://ark.volcengine.com/region:cn-beijing/model/detail?Id=doubao-seedance-2-0) 查看更多示例。
|场景 |输入:提示词 |输入:图片、视频、音频 |输出 |
|---|---|---|---|
|全模态参考 |以**图片1**为首帧,画面放大至飞机舷窗外,一团团云朵缓缓飘至画面中,其中一朵为彩色糖豆点缀的云朵,始终在画面中居中,然后缓缓变形为**图片2**中的冰淇淋,镜头推远回到机舱内,坐在窗边的**图片3**中的角色伸手从窗外拿进冰淇淋,吃了一口,嘴巴上沾满奶油,脸上洋溢出甜蜜的笑容,此时视频配音为**音频1** | |[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/8eaeafa52ae04afe8d8894be0145c8c8) | \
|> 可参考图、 | | | | \
|> 视频和音频 | | | | \
| | | | | \
| | |[冰淇淋 .mp3](https://p9-arcosite.byteimg.com/tos-cn-i-goo7wpa0wc/8d84cc7bbb5f486cbe66c26ddd1f6e47~tplv-goo7wpa0wc-image.image) | |
|编辑视频 |将**视频1**中的房子外立面墙壁刷成蓝色,天气和光线参考**图片1**的雪天 |[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/0751d1ba97664456893058e914a1b44a) |[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/5c17f8570a3943ceaa0c806aeffcbac9) | \
|> 替换视频主体、视频中对象增删改、局部画面重绘/修复等 | | | | \
| | | | | \
| | | | | \
| | | | |
|延长视频 |将**视频1**向后延长,11秒视频,汽车丝滑行驶到一片沙漠绿洲,背景音乐使用**音频1** |[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/7d84f0e0149348f598c8df548195b1c1) |[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/37e14c2c6b994ef6821b1bebb8c1bd47) | \
|> 向前或者向后延长视频,或多个视频片段串联成一个连贯视频 | | | | \
| | | | | \
| | | | | \
| | |[汽车背景音.mp3](https://p9-arcosite.byteimg.com/tos-cn-i-goo7wpa0wc/245274e557ec477d92359c6468cc7ca2~tplv-goo7wpa0wc-image.image) | |
|首帧图生视频 |镜头围绕人物推镜头拉近,特写人物面部,她正在用京剧唱腔唱“月移花影,疑是玉人来”,唱词充满情感,唱腔充满传统京剧特有的韵味与技巧,完美体现了花旦角色的内心世界 | |[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/2fe3d82baa1642b1926007968a44e022) |
|首尾帧生视频 |360度环绕运镜 | |[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/9cb7768701564b73ac45616097452338) |
# 新手入门
> **说明**
>
> 下文详细介绍使用不同编程语言调用视频生成 API 的示例代码。
> * 若您是编程零基础用户,推荐使用 [控制台体验中心](https://ark.volcengine.com/region:cn-beijing/experience/gen_video?model=doubao-seedance-2-0-260128),包含丰富的模板库,可一键生成同款视频,无需编写代码即可快速上手创作。
> * 若您想快速体验 API 调用,推荐使用API Explorer,内置预设参数模板,可一键发起 API 调用;同时也支持灵活调整参数(例如设置视频水印等),满足多样化的测试和使用场景。
> * 若您想真正开始编程开发,但苦于搭建开发环境、依赖安装等问题,推荐阅读 [Seedance 2.5 新手入门](/docs/seedance-2-5#2.5_quick_start) 或 [Seedance 2.0 新手入门](/docs/seedance-2-0)。
视频生成是一个异步过程:
1. 成功调用 `POST /contents/generations/tasks` 接口后,API 将返回一个任务 ID 。
2. 您可以轮询 `GET /contents/generations/tasks/{id}` 接口,直到任务状态变为 `succeeded`;或者使用 Webhook 自动接收视频生成任务的状态变化。
3. 任务完成后,您可在 content.**video_url** 字段处,下载最终生成的 MP4 文件。
> **说明**
>
> 方舟平台的新用户?获取 API Key 及 开通模型等准备工作,请参见 [快速入门](/docs/quick-start)。
## Step1: 创建视频生成任务
通过 `POST /contents/generations/tasks` 创建视频生成任务。
**选项:Curl**
```Bash
curl https://ark.cn-beijing.volces.com/api/v3/contents/generations/tasks \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ARK_API_KEY" \
-d '{
"model": "doubao-seedance-2-5-260628",
"content": [
{
"type": "text",
"text": "女孩抱着狐狸,女孩睁开眼,温柔地看向镜头,狐狸友善地抱着,镜头缓缓拉出,女孩的头发被风吹动,可以听到风声"
},
{
"type": "image_url",
"image_url": {
"url": "https://arkdocs.tos-cn-beijing.volces.com/images/video-generation/i2v_foxrgirl.png"
}
}
],
"generate_audio": true,
"ratio": "adaptive",
"duration": 5,
"watermark": true
}'
```
**选项:Python**
```Python
import os
from arkruntime import Ark
# Get API Key:https://ark.volcengine.com/region:cn-beijing/apikey
client = Ark(base_url="https://ark.cn-beijing.volces.com/api/v3", api_key=os.environ.get("ARK_API_KEY"))
if __name__ == "__main__":
print("----- create request -----")
resp = client.content_generation.tasks.create(
model="doubao-seedance-2-5-260628", # Replace with Model ID
content=[
{
"text": (
"女孩抱着狐狸,女孩睁开眼,温柔地看向镜头,狐狸友善地抱着,镜头缓缓拉出,女孩的头发被风吹动,可以听到风声"
),
"type": "text"
},
{
"image_url": {
"url": (
"https://arkdocs.tos-cn-beijing.volces.com/images/video-generation/i2v_foxrgirl.png"
)
},
"type": "image_url"
}
],
generate_audio=True,
ratio="adaptive",
duration=5,
watermark=True,
)
print(resp)
```
**选项:Java**
```Java
package com.ark.sample;
import com.volcengine.ark.runtime.models.content_generation.*;
import com.volcengine.ark.runtime.service.ArkService;
import okhttp3.ConnectionPool;
import okhttp3.Dispatcher;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
public class ContentGenerationTaskExample {
// Make sure that you have stored the API Key in the environment variable ARK_API_KEY
// Initialize the Ark client to read your API Key from an environment variable
static String apiKey = System.getenv("ARK_API_KEY");
static ConnectionPool connectionPool = new ConnectionPool(5, 1, TimeUnit.SECONDS);
static Dispatcher dispatcher = new Dispatcher();
static ArkService service = ArkService.builder()
.baseUrl("https://ark.cn-beijing.volces.com/api/v3") // The base URL for model invocation
.dispatcher(dispatcher)
.connectionPool(connectionPool)
.apiKey(apiKey)
.build();
public static void main(String[] args) {
String model = "doubao-seedance-2-5-260628"; // Replace with Model ID
Boolean generateAudio = true;
String ratio = "adaptive";
Long duration = 5L;
Boolean watermark = true;
System.out.println("----- create request -----");
List contents = new ArrayList<>();
// Combination of text prompt and parameters
contents.add(ContentItem.builder()
.type(ContentType.TEXT)
.text("女孩抱着狐狸,女孩睁开眼,温柔地看向镜头,狐狸友善地抱着,镜头缓缓拉出,女孩的头发被风吹动,可以听到风声")
.build());
// The URL of the first frame image
contents.add(ContentItem.builder()
.type(ContentType.IMAGE_URL)
.imageUrl(ImageURL.builder()
.url("https://arkdocs.tos-cn-beijing.volces.com/images/video-generation/i2v_foxrgirl.png")
.build())
.build());
// Create a video generation task
CreateContentGenerationTaskRequest createRequest = CreateContentGenerationTaskRequest.builder()
.model(model)
.content(contents)
.generateAudio(generateAudio)
.ratio(ratio)
.duration(duration)
.watermark(watermark)
.build();
CreateContentGenerationTaskResponse createResult = service.createContentGenerationTask(createRequest);
System.out.println(createResult);
service.shutdownExecutor();
}
}
```
**选项:Go**
```Go
package main
import (
"context"
"fmt"
"os"
"github.com/volcengine/ark-runtime-go/arkruntime"
model "github.com/volcengine/ark-runtime-go/arkruntime/model/contentgeneration"
)
func main() {
// Make sure that you have stored the API Key in the environment variable ARK_API_KEY
// Initialize the Ark client to read your API Key from an environment variable
client := arkruntime.NewClientWithApiKey(
// Get your API Key from the environment variable. This is the default mode and you can modify it as required
os.Getenv("ARK_API_KEY"),
// The base URL for model invocation
arkruntime.WithBaseUrl("https://ark.cn-beijing.volces.com/api/v3"),
)
ctx := context.Background()
// Replace with Model ID
modelEp := "doubao-seedance-2-5-260628"
// Generate a task
fmt.Println("----- create request -----")
createReq := &model.CreateContentGenerationTaskRequest{
Model: modelEp,
GenerateAudio: model.NewOptBool(true),
Ratio: model.NewOptString("adaptive"),
Duration: model.NewOptInt64(5),
Watermark: model.NewOptBool(true),
Content: []model.ContentItem{
{
// Combination of text prompt and parameters
Type: model.ContentTypeText,
Text: model.NewOptString("女孩抱着狐狸,女孩睁开眼,温柔地看向镜头,狐狸友善地抱着,镜头缓缓拉出,女孩的头发被风吹动,可以听到风声"),
},
{
// The URL of the first frame image
Type: model.ContentTypeImageURL,
ImageURL: model.NewOptImageURL(model.ImageURL{
URL: "https://arkdocs.tos-cn-beijing.volces.com/images/video-generation/i2v_foxrgirl.png",
}),
},
},
}
createResp, err := client.CreateContentGenerationTask(ctx, createReq)
if err != nil {
fmt.Printf("create content generation error: %v", err)
return
}
taskID := createResp.ID
fmt.Printf("Task Created with ID: %s", taskID)
}
```
请求成功后,系统将返回一个任务 ID。
```JSON
{
"id": ""
}
```
## Step2: 查询视频生成任务
利用创建视频生成任务时返回的 ID ,您可以查询视频生成任务的详细状态与结果。此接口会返回任务的当前状态(如 `queued` 、`running` 、 `succeeded` 等)以及生成的视频相关信息(如视频下载链接、分辨率、时长等)。
> **说明**
>
> 因模型、API负载和视频输出规格的不同,视频生成的过程可能耗时较长。为高效管理这一过程,您可以通过轮询 API 接口(详见 [基础使用](/docs/video-generation-tutorial#1bf58128) 和 [进阶使用](/docs/video-generation-tutorial#e190e738) 部分的 SDK 示例)来请求状态更新,或通过 [使用 Webhook 通知](/docs/video-generation-tutorial#caf01f12) 接收通知。
**选项:Curl**
```Bash
# Replace with the ID acquired from "Create Video Generation Task".
curl "https://ark.cn-beijing.volces.com/api/v3/contents/generations/tasks/" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ARK_API_KEY"
```
**选项:Python**
```Python
import os
from arkruntime import Ark
# Get API Key: https://ark.volcengine.com/region:cn-beijing/apikey
client = Ark(
api_key=os.environ.get("ARK_API_KEY"),
base_url="https://ark.cn-beijing.volces.com/api/v3",
)
if __name__ == "__main__":
resp = client.content_generation.tasks.get(
task_id="",
)
print(resp)
```
**选项:Java**
```Java
package com.ark.sample;
import com.volcengine.ark.runtime.models.content_generation.*;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.volcengine.ark.runtime.service.ArkService;
import java.util.concurrent.TimeUnit;
import okhttp3.ConnectionPool;
import okhttp3.Dispatcher;
public class Sample {
static String apiKey = System.getenv("ARK_API_KEY");
static ConnectionPool connectionPool = new ConnectionPool(5, 1, TimeUnit.SECONDS);
static Dispatcher dispatcher = new Dispatcher();
static ArkService service =
ArkService.builder()
.dispatcher(dispatcher)
.connectionPool(connectionPool)
.apiKey(apiKey)
.baseUrl("https://ark.cn-beijing.volces.com/api/v3")
.build();
public static void main(String[] args) throws JsonProcessingException {
String taskId = "";
String req = taskId;
service.getContentGenerationTask(req).toString();
System.out.println(service.getContentGenerationTask(req));
service.shutdownExecutor();
}
}
```
**选项:Go**
```Go
package main
import (
"context"
"fmt"
"os"
"github.com/volcengine/ark-runtime-go/arkruntime"
)
func main() {
client := arkruntime.NewClientWithApiKey(
os.Getenv("ARK_API_KEY"),
arkruntime.WithBaseUrl("https://ark.cn-beijing.volces.com/api/v3"),
)
ctx := context.Background()
req := ""
resp, err := client.GetContentGenerationTask(ctx, req)
if err != nil {
fmt.Printf("get content generation task error: %v\n", err)
return
}
fmt.Printf("%+v\n", resp)
}
```
当任务状态变为 succeeded 后,您可在 content.**video_url** 字段处,下载最终生成的视频文件。
```JSON
{
"id": "",
"model": "doubao-seedance-2-5-260628",
"status": "succeeded",
"content": {
// Video download URL (file format is MP4)
"video_url": ""
},
"usage": {
"completion_tokens": 246840,
"total_tokens": 246840
},
"created_at": 1765510475,
"updated_at": 1765510559,
"seed": 58944,
"resolution": "1080p",
"ratio": "16:9",
"duration": 5,
"framespersecond": 24,
"service_tier": "default",
"execution_expires_after": 172800
}
```
# 模型能力
本表格展示所有 Seedance 模型支持的能力,方便您对比和选型。如需了解各版本模型的特色能力,请参见 [Doubao Seedance 2.5 教程](/docs/seedance-2-5)、[Doubao Seedance 2.0 系列教程](/docs/seedance-2-0)。
|模型名称 | |[Seedance 2.5](https://ark.volcengine.com/region:cn-beijing/model/detail?Id=doubao-seedance-2-5&projectName=default) |[Seedance 2.0](https://ark.volcengine.com/region:cn-beijing/model/detail?Id=doubao-seedance-2-0&projectName=default) |[Seedance 2.0 fast](https://ark.volcengine.com/region:cn-beijing/model/detail?Id=doubao-seedance-2-0-fast&projectName=default) |[Seedance 2.0 mini](https://ark.volcengine.com/region:cn-beijing/model/detail?Id=doubao-seedance-2-0-mini&projectName=default) |[Seedance 1.0 pro](https://ark.volcengine.com/region:cn-beijing/model/detail?Id=doubao-seedance-1-0-pro&projectName=default) |[Seedance 1.0 pro fast](https://ark.volcengine.com/region:cn-beijing/model/detail?Id=doubao-seedance-1-0-pro-fast&projectName=default) |
|---|---|---|---|---|---|---|---|
|Model ID | |doubao-seedance-2-5-260628 |doubao-seedance-2-0-260128 |doubao-seedance-2-0-fast-260128 |doubao-seedance-2-0-mini-260615 |doubao-seedance-1-0-pro-250528 |doubao-seedance-1-0-pro-fast-251015 |
|[文生视频](/docs/video-generation-tutorial#4e74bcee) | |✓ |✓ |✓ |✓ |✓ |✓ |
|[图生视频-首帧](/docs/video-generation-tutorial#979b2d28) | |✓ |✓ |✓ |✓ |✓ |✓ |
|[图生视频-首尾帧](/docs/video-generation-tutorial#0d55ca07) | |✓ |✓ |✓ |✓ |✓ |✗ |
|[全模态参考](/docs/seedance-2-0#50e1b4ea) |图片参考 |✓ |✓ |✓ |✓ |✗ |✗ |
|^^| | | | | | | | \
| |视频参考 |✓ |✓ |✓ |✓ |✗ |✗ |
|^^| | | | | | | | \
| |音频参考 |✓ |✗(需搭配图片/视频) |✗(需搭配图片/视频) |✗(需搭配图片/视频) |✗ |✗ |
|^^| | | | | | | | \
| |组合参考 |✓ |✓ |✓ |✓ |✗ |✗ | \
| | | | | | | | | \
| |* 图片 + 音频 | | | | | | | \
| |* 图片 + 视频 | | | | | | | \
| |* 视频 + 音频 | | | | | | | \
| |* 图片 + 视频 + 音频 | | | | | | |
|[编辑视频](/docs/seedance-2-0#75a28782) | |✓ |✓ |✓ |✓ |✗ |✗ |
|[延长视频](/docs/seedance-2-0#46d77653) | |✓ |✓ |✓ |✓ |✗ |✗ |
|[生成有声视频](/docs/video-generation-tutorial#979b2d28) | |✓ |✓ |✓ |✓ |✗ |✗ |
|[联网搜索工具](/docs/seedance-2-0#c40ed3ef) | |✓ |✓ |✓ |✓ |✗ |✗ |
|[返回视频产物对应的尾帧图](/docs/video-generation-tutorial#141cf7fa) | |✓ |✓ |✓ |✓ |✓ |✓ |
|[输出视频规格](/docs/video-generation-tutorial#9fe4cce0) |输出分辨率 |* 480p(8bit 位深) |* 480p(8bit 位深) |* 480p(8bit 位深) |* 480p(8bit 位深) |480p |480p | \
| | |* 720p(8bit 位深) |* 720p(8bit 位深) |* 720p(8bit 位深) |* 720p(8bit 位深) |720p |720p | \
| | |* 1080p(10bit 位深) |* 1080p(8bit 位深) | | |1080p |1080p | \
| | | |* 4k(10bit 位深) | | | | |
| |输出宽高比 |21:9 |21:9 |21:9 |21:9 |21:9 |21:9 | \
| | |16:9 |16:9 |16:9 |16:9 |16:9 |16:9 | \
| | |4:3 |4:3 |4:3 |4:3 |4:3 |4:3 | \
| | |1:1 |1:1 |1:1 |1:1 |1:1 |1:1 | \
| | |3:4 |3:4 |3:4 |3:4 |3:4 |3:4 | \
| | |9:16 |9:16 |9:16 |9:16 |9:16 |9:16 |
| |输出帧率 |24 fps |24 fps |24 fps |24 fps |24 fps |24 fps |
| |输出时长 |4~30 秒 |4~15 秒 |4~15 秒 |4~15 秒 |2~12 秒 |2~12 秒 |
| |输出视频格式 |mp4 |mp4 |mp4 |mp4 |mp4 |mp4 |
|[离线推理](/docs/video-generation-tutorial#c3588bd1) | |✗ |✗ |✗ |✗ |✓ |✓ |
# 基础使用
## 文生视频
根据用户输入的提示词生成视频,结果具有较大的随机性,可以用于激发创作灵感。
|提示词 |输出 |
|---|---|
|写实风格,晴朗的蓝天之下,一大片白色的雏菊花田,镜头逐渐拉近,最终定格在一朵雏菊花的特写上,花瓣上有几颗晶莹的露珠 |[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/b847f3e831c244b39f7b4d53d904988f) |
**选项:Python**
```Python
import os
import time
# Install SDK: python -m pip install --upgrade arkruntime
from arkruntime import Ark
# Make sure that you have stored the API Key in the environment variable ARK_API_KEY
# Initialize the Ark client to read your API Key from an environment variable
client = Ark(
# This is the default path. You can configure it based on the service location
base_url="https://ark.cn-beijing.volces.com/api/v3",
# Get API Key:https://ark.volcengine.com/region:cn-beijing/apikey
api_key=os.environ.get("ARK_API_KEY"),
)
if __name__ == "__main__":
print("----- create request -----")
create_result = client.content_generation.tasks.create(
model="doubao-seedance-2-5-260628", # Replace with Model ID
content=[
{
# Combination of text prompt and parameters
"type": "text",
"text": "写实风格,晴朗的蓝天之下,一大片白色的雏菊花田,镜头逐渐拉近,最终定格在一朵雏菊花的特写上,花瓣上有几颗晶莹的露珠"
}
],
ratio="16:9",
duration=5,
watermark=True,
)
print(create_result)
# Polling query section
print("----- polling task status -----")
task_id = create_result.id
while True:
get_result = client.content_generation.tasks.get(task_id=task_id)
status = get_result.status
if status == "succeeded":
print("----- task succeeded -----")
print(get_result)
break
elif status == "failed":
print("----- task failed -----")
print(f"Error: {get_result.error}")
break
else:
print(f"Current status: {status}, Retrying after 10 seconds...")
time.sleep(10)
```
**选项:Java**
```Java
package com.ark.sample;
import com.volcengine.ark.runtime.models.content_generation.*;
import com.volcengine.ark.runtime.service.ArkService;
import okhttp3.ConnectionPool;
import okhttp3.Dispatcher;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
public class ContentGenerationTaskExample {
// Make sure that you have stored the API Key in the environment variable ARK_API_KEY
// Initialize the Ark client to read your API Key from an environment variable
static String apiKey = System.getenv("ARK_API_KEY");
static ConnectionPool connectionPool = new ConnectionPool(5, 1, TimeUnit.SECONDS);
static Dispatcher dispatcher = new Dispatcher();
static ArkService service = ArkService.builder()
.baseUrl("https://ark.cn-beijing.volces.com/api/v3") // The base URL for model invocation
.dispatcher(dispatcher)
.connectionPool(connectionPool)
.apiKey(apiKey)
.build();
public static void main(String[] args) {
String model = "doubao-seedance-2-5-260628"; // Replace with Model ID
String ratio = "16:9";
Long duration = 5L;
Boolean watermark = true;
System.out.println("----- create request -----");
List contents = new ArrayList<>();
// Combination of text prompt and parameters
contents.add(ContentItem.builder()
.type(ContentType.TEXT)
.text("写实风格,晴朗的蓝天之下,一大片白色的雏菊花田,镜头逐渐拉近,最终定格在一朵雏菊花的特写上,花瓣上有几颗晶莹的露珠")
.build());
// Create a video generation task
CreateContentGenerationTaskRequest createRequest = CreateContentGenerationTaskRequest.builder()
.model(model)
.content(contents)
.ratio(ratio)
.duration(duration)
.watermark(watermark)
.build();
CreateContentGenerationTaskResponse createResult = service.createContentGenerationTask(createRequest);
System.out.println(createResult);
// Get the details of the task
String taskId = createResult.getId();
String getRequest = taskId;
// Polling query section
System.out.println("----- polling task status -----");
while (true) {
try {
ContentGenerationTask getResponse = service.getContentGenerationTask(getRequest);
String status = getResponse.getStatus().toString();
if ("succeeded".equalsIgnoreCase(status)) {
System.out.println("----- task succeeded -----");
System.out.println(getResponse);
break;
} else if ("failed".equalsIgnoreCase(status)) {
System.out.println("----- task failed -----");
System.out.println("Error: " + getResponse.getStatus());
break;
} else {
System.out.printf("Current status: %s, Retrying in 10 seconds...", status);
TimeUnit.SECONDS.sleep(10);
}
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
System.err.println("Polling interrupted");
break;
}
}
}
}
```
**选项:Go**
```Go
package main
import (
"context"
"fmt"
"os"
"time"
"github.com/volcengine/ark-runtime-go/arkruntime"
model "github.com/volcengine/ark-runtime-go/arkruntime/model/contentgeneration"
)
func main() {
// Make sure that you have stored the API Key in the environment variable ARK_API_KEY
// Initialize the Ark client to read your API Key from an environment variable
client := arkruntime.NewClientWithApiKey(
// Get your API Key from the environment variable. This is the default mode and you can modify it as required
os.Getenv("ARK_API_KEY"),
// The base URL for model invocation
arkruntime.WithBaseUrl("https://ark.cn-beijing.volces.com/api/v3"),
)
ctx := context.Background()
// Replace with Model ID
modelEp := "doubao-seedance-2-5-260628"
// Generate a task
fmt.Println("----- create request -----")
createReq := &model.CreateContentGenerationTaskRequest{
Model: modelEp,
Ratio: model.NewOptString("16:9"),
Duration: model.NewOptInt64(5),
Watermark: model.NewOptBool(true),
Content: []model.ContentItem{
{
// Combination of text prompt and parameters
Type: model.ContentTypeText,
Text: model.NewOptString("写实风格,晴朗的蓝天之下,一大片白色的雏菊花田,镜头逐渐拉近,最终定格在一朵雏菊花的特写上,花瓣上有几颗晶莹的露珠"),
},
},
}
createResp, err := client.CreateContentGenerationTask(ctx, createReq)
if err != nil {
fmt.Printf("create content generation error: %v", err)
return
}
taskID := createResp.ID
fmt.Printf("Task Created with ID: %s", taskID)
// Polling query section
fmt.Println("----- polling task status -----")
for {
getReq := taskID
getResp, err := client.GetContentGenerationTask(ctx, getReq)
if err != nil {
fmt.Printf("get content generation task error: %v", err)
return
}
status := getResp.Status
if status == "succeeded" {
fmt.Println("----- task succeeded -----")
fmt.Printf("Task ID: %s \n", getResp.ID)
fmt.Printf("Model: %s \n", getResp.Model)
fmt.Printf("Video URL: %s \n", getResp.Content.Or(model.TaskContent{}).VideoURL.Or(""))
fmt.Printf("Completion Tokens: %d \n", getResp.Usage.Or(model.TaskUsage{}).CompletionTokens)
fmt.Printf("Created At: %d, Updated At: %d", getResp.CreatedAt.Or(0), getResp.UpdatedAt.Or(0))
return
} else if status == "failed" {
fmt.Println("----- task failed -----")
if getResp.Error.IsSet() {
fmt.Printf("Error Code: %s, Message: %s", getResp.Error.Value.Code, getResp.Error.Value.Message)
}
return
} else {
fmt.Printf("Current status: %s, Retrying in 10 seconds... \n", status)
time.Sleep(10 * time.Second)
}
}
}
```
## 图生视频-基于首帧(`含音频`)
通过指定视频的首帧图片,模型能够基于该图片生成与之相关且画面连贯的视频内容。
|提示词 |首帧 |输出 |
|---|---|---|
|女孩抱着狐狸,女孩睁开眼,温柔地看向镜头,狐狸友善地抱着,镜头缓缓拉出,女孩的头发被风吹动,可以听到风声 | |[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/f1f7b95a38ee4ee094c724233e4da4f8) |
**选项:Python**
```Python
import os
import time
# Install SDK: python -m pip install --upgrade arkruntime
from arkruntime import Ark
# Make sure that you have stored the API Key in the environment variable ARK_API_KEY
# Initialize the Ark client to read your API Key from an environment variable
client = Ark(
# This is the default path. You can configure it based on the service location
base_url="https://ark.cn-beijing.volces.com/api/v3",
# Get API Key:https://ark.volcengine.com/region:cn-beijing/apikey
api_key=os.environ.get("ARK_API_KEY"),
)
if __name__ == "__main__":
print("----- create request -----")
create_result = client.content_generation.tasks.create(
model="doubao-seedance-2-5-260628", # Replace with Model ID
content=[
{
# Combination of text prompt and parameters
"type": "text",
"text": "女孩抱着狐狸,女孩睁开眼,温柔地看向镜头,狐狸友善地抱着,镜头缓缓拉出,女孩的头发被风吹动,可以听到风声"
},
{
# The URL of the first frame image
"type": "image_url",
"image_url": {
"url": "https://arkdocs.tos-cn-beijing.volces.com/images/video-generation/i2v_foxrgirl.png"
}
}
],
generate_audio=True,
ratio="adaptive",
duration=5,
watermark=True,
)
print(create_result)
# Polling query section
print("----- polling task status -----")
task_id = create_result.id
while True:
get_result = client.content_generation.tasks.get(task_id=task_id)
status = get_result.status
if status == "succeeded":
print("----- task succeeded -----")
print(get_result)
break
elif status == "failed":
print("----- task failed -----")
print(f"Error: {get_result.error}")
break
else:
print(f"Current status: {status}, Retrying after 10 seconds...")
time.sleep(10)
```
**选项:Java**
```Java
package com.ark.sample;
import com.volcengine.ark.runtime.models.content_generation.*;
import com.volcengine.ark.runtime.service.ArkService;
import okhttp3.ConnectionPool;
import okhttp3.Dispatcher;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
public class ContentGenerationTaskExample {
// Make sure that you have stored the API Key in the environment variable ARK_API_KEY
// Initialize the Ark client to read your API Key from an environment variable
static String apiKey = System.getenv("ARK_API_KEY");
static ConnectionPool connectionPool = new ConnectionPool(5, 1, TimeUnit.SECONDS);
static Dispatcher dispatcher = new Dispatcher();
static ArkService service = ArkService.builder()
.baseUrl("https://ark.cn-beijing.volces.com/api/v3")
// The base URL for model invocation
.dispatcher(dispatcher)
.connectionPool(connectionPool)
.apiKey(apiKey)
.build();
public static void main(String[] args) {
String model = "doubao-seedance-2-5-260628"; // Replace with Model ID
Boolean generateAudio = true;
String ratio = "adaptive";
Long duration = 5L;
Boolean watermark = true;
System.out.println("----- create request -----");
List contents = new ArrayList<>();
// Combination of text prompt and parameters
contents.add(ContentItem.builder()
.type(ContentType.TEXT)
.text("女孩抱着狐狸,女孩睁开眼,温柔地看向镜头,狐狸友善地抱着,镜头缓缓拉出,女孩的头发被风吹动,可以听到风声")
.build());
// The URL of the first frame image
contents.add(ContentItem.builder()
.type(ContentType.IMAGE_URL)
.imageUrl(ImageURL.builder()
.url("https://arkdocs.tos-cn-beijing.volces.com/images/video-generation/i2v_foxrgirl.png")
.build())
.build());
// Create a video generation task
CreateContentGenerationTaskRequest createRequest = CreateContentGenerationTaskRequest.builder()
.model(model)
.content(contents)
.generateAudio(generateAudio)
.ratio(ratio)
.duration(duration)
.watermark(watermark)
.build();
CreateContentGenerationTaskResponse createResult = service.createContentGenerationTask(createRequest);
System.out.println(createResult);
// Get the details of the task
String taskId = createResult.getId();
String getRequest = taskId;
// Polling query section
System.out.println("----- polling task status -----");
while (true) {
try {
ContentGenerationTask getResponse = service.getContentGenerationTask(getRequest);
String status = getResponse.getStatus().toString();
if ("succeeded".equalsIgnoreCase(status)) {
System.out.println("----- task succeeded -----");
System.out.println(getResponse);
break;
} else if ("failed".equalsIgnoreCase(status)) {
System.out.println("----- task failed -----");
System.out.println("Error: " + getResponse.getStatus());
break;
} else {
System.out.printf("Current status: %s, Retrying in 10 seconds...", status);
TimeUnit.SECONDS.sleep(10);
}
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
System.err.println("Polling interrupted");
break;
}
}
}
}
```
**选项:Go**
```Go
package main
import (
"context"
"fmt"
"os"
"time"
"github.com/volcengine/ark-runtime-go/arkruntime"
model "github.com/volcengine/ark-runtime-go/arkruntime/model/contentgeneration"
)
func main() {
// Make sure that you have stored the API Key in the environment variable ARK_API_KEY
// Initialize the Ark client to read your API Key from an environment variable
client := arkruntime.NewClientWithApiKey(
// Get your API Key from the environment variable. This is the default mode and you can modify it as required
os.Getenv("ARK_API_KEY"),
// The base URL for model invocation
arkruntime.WithBaseUrl("https://ark.cn-beijing.volces.com/api/v3"),
)
ctx := context.Background()
// Replace with Model ID
modelEp := "doubao-seedance-2-5-260628"
// Generate a task
fmt.Println("----- create request -----")
createReq := &model.CreateContentGenerationTaskRequest{
Model: modelEp,
GenerateAudio: model.NewOptBool(true),
Ratio: model.NewOptString("adaptive"),
Duration: model.NewOptInt64(5),
Watermark: model.NewOptBool(true),
Content: []model.ContentItem{
{
// Combination of text prompt and parameters
Type: model.ContentTypeText,
Text: model.NewOptString("女孩抱着狐狸,女孩睁开眼,温柔地看向镜头,狐狸友善地抱着,镜头缓缓拉出,女孩的头发被风吹动,可以听到风声"),
},
{
// The URL of the first frame image
Type: model.ContentTypeImageURL,
ImageURL: model.NewOptImageURL(model.ImageURL{
URL: "https://arkdocs.tos-cn-beijing.volces.com/images/video-generation/i2v_foxrgirl.png",
}),
},
},
}
createResp, err := client.CreateContentGenerationTask(ctx, createReq)
if err != nil {
fmt.Printf("create content generation error: %v", err)
return
}
taskID := createResp.ID
fmt.Printf("Task Created with ID: %s", taskID)
// Polling query section
fmt.Println("----- polling task status -----")
for {
getReq := taskID
getResp, err := client.GetContentGenerationTask(ctx, getReq)
if err != nil {
fmt.Printf("get content generation task error: %v", err)
return
}
status := getResp.Status
if status == "succeeded" {
fmt.Println("----- task succeeded -----")
fmt.Printf("Task ID: %s \n", getResp.ID)
fmt.Printf("Model: %s \n", getResp.Model)
fmt.Printf("Video URL: %s \n", getResp.Content.Or(model.TaskContent{}).VideoURL.Or(""))
fmt.Printf("Completion Tokens: %d \n", getResp.Usage.Or(model.TaskUsage{}).CompletionTokens)
fmt.Printf("Created At: %d, Updated At: %d", getResp.CreatedAt.Or(0), getResp.UpdatedAt.Or(0))
return
} else if status == "failed" {
fmt.Println("----- task failed -----")
if getResp.Error.IsSet() {
fmt.Printf("Error Code: %s, Message: %s", getResp.Error.Value.Code, getResp.Error.Value.Message)
}
return
} else {
fmt.Printf("Current status: %s, Retrying in 10 seconds... \n", status)
time.Sleep(10 * time.Second)
}
}
}
```
## 图生视频-基于首尾帧(`含音频`)
通过指定视频的起始和结束图片,模型即可生成流畅衔接首、尾帧的视频,实现画面间自然、连贯的过渡效果。
|提示词 |首帧 |尾帧 |输出 |
|---|---|---|---|
|图中女孩对着镜头说“茄子”,360度环绕运镜 | | |[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/3aa8c84b8a29408ab29e95992d61c559) |
**选项:Python**
```Python
import os
import time
# Install SDK: python -m pip install --upgrade arkruntime
from arkruntime import Ark
# Make sure that you have stored the API Key in the environment variable ARK_API_KEY
# Initialize the Ark client to read your API Key from an environment variable
client = Ark(
# This is the default path. You can configure it based on the service location
base_url="https://ark.cn-beijing.volces.com/api/v3",
# Get API Key:https://ark.volcengine.com/region:cn-beijing/apikey
api_key=os.environ.get("ARK_API_KEY"),
)
if __name__ == "__main__":
print("----- create request -----")
create_result = client.content_generation.tasks.create(
model="doubao-seedance-2-5-260628", # Replace with Model ID
content=[
{
# Combination of text prompt and parameters
"type": "text",
"text": "图中女孩对着镜头说\"茄子\",360度环绕运镜"
},
{
# The URL of the first frame image
"type": "image_url",
"image_url": {
"url": "https://arkdocs.tos-cn-beijing.volces.com/images/video-generation/seepro_first_frame.jpeg"
},
"role": "first_frame"
},
{
# The URL of the last frame image
"type": "image_url",
"image_url": {
"url": "https://arkdocs.tos-cn-beijing.volces.com/images/video-generation/seepro_last_frame.jpeg"
},
"role": "last_frame"
}
],
generate_audio=True,
ratio="adaptive",
duration=5,
watermark=True,
)
print(create_result)
# Polling query section
print("----- polling task status -----")
task_id = create_result.id
while True:
get_result = client.content_generation.tasks.get(task_id=task_id)
status = get_result.status
if status == "succeeded":
print("----- task succeeded -----")
print(get_result)
break
elif status == "failed":
print("----- task failed -----")
print(f"Error: {get_result.error}")
break
else:
print(f"Current status: {status}, Retrying after 10 seconds...")
time.sleep(10)
```
**选项:Java**
```Java
package com.ark.sample;
import com.volcengine.ark.runtime.models.content_generation.*;
import com.volcengine.ark.runtime.service.ArkService;
import okhttp3.ConnectionPool;
import okhttp3.Dispatcher;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
public class ContentGenerationTaskExample {
// Make sure that you have stored the API Key in the environment variable ARK_API_KEY
// Initialize the Ark client to read your API Key from an environment variable
static String apiKey = System.getenv("ARK_API_KEY");
static ConnectionPool connectionPool = new ConnectionPool(5, 1, TimeUnit.SECONDS);
static Dispatcher dispatcher = new Dispatcher();
static ArkService service = ArkService.builder()
.baseUrl("https://ark.cn-beijing.volces.com/api/v3") // The base URL for model invocation
.dispatcher(dispatcher)
.connectionPool(connectionPool)
.apiKey(apiKey)
.build();
public static void main(String[] args) {
String model = "doubao-seedance-2-5-260628"; // Replace with Model ID
Boolean generateAudio = true;
String ratio = "adaptive";
Long duration = 5L;
Boolean watermark = true;
System.out.println("----- create request -----");
List contents = new ArrayList<>();
// Combination of text prompt and parameters
contents.add(ContentItem.builder()
.type(ContentType.TEXT)
.text("图中女孩对着镜头说“茄子”,360度环绕运镜")
.build());
// The URL of the first frame image
contents.add(ContentItem.builder()
.type(ContentType.IMAGE_URL)
.imageUrl(ImageURL.builder()
.url("https://arkdocs.tos-cn-beijing.volces.com/images/video-generation/seepro_first_frame.jpeg")
.build())
.role("first_frame")
.build());
// The URL of the last frame image
contents.add(ContentItem.builder()
.type(ContentType.IMAGE_URL)
.imageUrl(ImageURL.builder()
.url("https://arkdocs.tos-cn-beijing.volces.com/images/video-generation/seepro_last_frame.jpeg")
.build())
.role("last_frame")
.build());
// Create a video generation task
CreateContentGenerationTaskRequest createRequest = CreateContentGenerationTaskRequest.builder()
.model(model)
.content(contents)
.generateAudio(generateAudio)
.ratio(ratio)
.duration(duration)
.watermark(watermark)
.build();
CreateContentGenerationTaskResponse createResult = service.createContentGenerationTask(createRequest);
System.out.println(createResult);
// Get the details of the task
String taskId = createResult.getId();
String getRequest = taskId;
// Polling query section
System.out.println("----- polling task status -----");
while (true) {
try {
ContentGenerationTask getResponse = service.getContentGenerationTask(getRequest);
String status = getResponse.getStatus().toString();
if ("succeeded".equalsIgnoreCase(status)) {
System.out.println("----- task succeeded -----");
System.out.println(getResponse);
break;
} else if ("failed".equalsIgnoreCase(status)) {
System.out.println("----- task failed -----");
System.out.println("Error: " + getResponse.getStatus());
break;
} else {
System.out.printf("Current status: %s, Retrying in 10 seconds...", status);
TimeUnit.SECONDS.sleep(10);
}
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
System.err.println("Polling interrupted");
break;
}
}
}
}
```
**选项:Go**
```Go
package main
import (
"context"
"fmt"
"os"
"time"
"github.com/volcengine/ark-runtime-go/arkruntime"
model "github.com/volcengine/ark-runtime-go/arkruntime/model/contentgeneration"
)
func main() {
// Make sure that you have stored the API Key in the environment variable ARK_API_KEY
// Initialize the Ark client to read your API Key from an environment variable
client := arkruntime.NewClientWithApiKey(
// Get your API Key from the environment variable. This is the default mode and you can modify it as required
os.Getenv("ARK_API_KEY"),
// The base URL for model invocation
arkruntime.WithBaseUrl("https://ark.cn-beijing.volces.com/api/v3"),
)
ctx := context.Background()
// Replace with Model ID
modelEp := "doubao-seedance-2-5-260628"
// Generate a task
fmt.Println("----- create request -----")
createReq := &model.CreateContentGenerationTaskRequest{
Model: modelEp,
GenerateAudio: model.NewOptBool(true),
Ratio: model.NewOptString("adaptive"),
Duration: model.NewOptInt64(5),
Watermark: model.NewOptBool(true),
Content: []model.ContentItem{
{
// Combination of text prompt and parameters
Type: model.ContentTypeText,
Text: model.NewOptString("图中女孩对着镜头说“茄子”,360度环绕运镜"),
},
{
// The URL of the first frame image
Type: model.ContentTypeImageURL,
ImageURL: model.NewOptImageURL(model.ImageURL{
URL: "https://arkdocs.tos-cn-beijing.volces.com/images/video-generation/seepro_first_frame.jpeg",
}),
Role: model.NewOptString("first_frame"),
},
{
// The URL of the last frame image
Type: model.ContentTypeImageURL,
ImageURL: model.NewOptImageURL(model.ImageURL{
URL: "https://arkdocs.tos-cn-beijing.volces.com/images/video-generation/seepro_last_frame.jpeg",
}),
Role: model.NewOptString("last_frame"),
},
},
}
createResp, err := client.CreateContentGenerationTask(ctx, createReq)
if err != nil {
fmt.Printf("create content generation error: %v", err)
return
}
taskID := createResp.ID
fmt.Printf("Task Created with ID: %s", taskID)
// Polling query section
fmt.Println("----- polling task status -----")
for {
getReq := taskID
getResp, err := client.GetContentGenerationTask(ctx, getReq)
if err != nil {
fmt.Printf("get content generation task error: %v", err)
return
}
status := getResp.Status
if status == "succeeded" {
fmt.Println("----- task succeeded -----")
fmt.Printf("Task ID: %s \n", getResp.ID)
fmt.Printf("Model: %s \n", getResp.Model)
fmt.Printf("Video URL: %s \n", getResp.Content.Or(model.TaskContent{}).VideoURL.Or(""))
fmt.Printf("Completion Tokens: %d \n", getResp.Usage.Or(model.TaskUsage{}).CompletionTokens)
fmt.Printf("Created At: %d, Updated At: %d", getResp.CreatedAt.Or(0), getResp.UpdatedAt.Or(0))
return
} else if status == "failed" {
fmt.Println("----- task failed -----")
if getResp.Error.IsSet() {
fmt.Printf("Error Code: %s, Message: %s", getResp.Error.Value.Code, getResp.Error.Value.Message)
}
return
} else {
fmt.Printf("Current status: %s, Retrying in 10 seconds... \n", status)
time.Sleep(10 * time.Second)
}
}
}
```
##
## 管理视频任务
### 查询视频生成任务列表
该接口支持传入条件筛选参数,以查询符合条件的视频生成任务列表。
**选项:Curl**
```Bash
curl https://ark.cn-beijing.volces.com/api/v3/contents/generations/tasks?page_size=2&filter.status=succeeded& \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ARK_API_KEY"
```
**选项:Python**
```Python
import os
from arkruntime import Ark
# Get API Key: https://ark.volcengine.com/region:cn-beijing/apikey
client = Ark(
api_key=os.environ.get("ARK_API_KEY"),
base_url="https://ark.cn-beijing.volces.com/api/v3",
)
if __name__ == "__main__":
resp = client.content_generation.tasks.get(
task_id="",
)
print(resp)
```
**选项:Java**
```Java
package com.ark.sample;
import com.volcengine.ark.runtime.models.content_generation.*;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.volcengine.ark.runtime.service.ArkService;
import java.util.concurrent.TimeUnit;
import okhttp3.ConnectionPool;
import okhttp3.Dispatcher;
public class Sample {
static String apiKey = System.getenv("ARK_API_KEY");
static ConnectionPool connectionPool = new ConnectionPool(5, 1, TimeUnit.SECONDS);
static Dispatcher dispatcher = new Dispatcher();
static ArkService service =
ArkService.builder()
.dispatcher(dispatcher)
.connectionPool(connectionPool)
.apiKey(apiKey)
.baseUrl("https://ark.cn-beijing.volces.com/api/v3")
.build();
public static void main(String[] args) throws JsonProcessingException {
ListContentGenerationTasksRequest req =
ListContentGenerationTasksRequest.builder().pageNum(1).pageSize(3).filterStatus(TaskStatus.SUCCEEDED).build();
System.out.println(service.listContentGenerationTasks(req));
// shutdown service after all requests is finished
service.shutdownExecutor();
}
}
```
**选项:Go**
```Go
package main
import (
"context"
"fmt"
"os"
"github.com/volcengine/ark-runtime-go/arkruntime"
model "github.com/volcengine/ark-runtime-go/arkruntime/model/contentgeneration"
)
func main() {
client := arkruntime.NewClientWithApiKey(
os.Getenv("ARK_API_KEY"),
arkruntime.WithBaseUrl("https://ark.cn-beijing.volces.com/api/v3"),
)
ctx := context.Background()
req := &arkruntime.ListContentGenerationTasksRequest{
PageSize: int32Pointer(3),
Status: taskStatusPointer(model.TaskStatus("succeeded")),
}
resp, err := client.ListContentGenerationTasks(ctx, req)
if err != nil {
fmt.Printf("failed to list content generation tasks: %v\n", err)
return
}
fmt.Printf("%+v\n", resp)
}
func int32Pointer(value int32) *int32 { return &value }
func taskStatusPointer(value model.TaskStatus) *model.TaskStatus { return &value }
```
### 删除或取消视频生成任务
取消排队中的视频生成任务,或者删除视频生成任务记录。
**选项:Curl**
```Bash
# Replace with the ID acquired from "Create Video Generation Task".
curl -X DELETE "https://ark.cn-beijing.volces.com/api/v3/contents/generations/tasks/" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ARK_API_KEY"
```
**选项:Python**
```Python
import os
from arkruntime import Ark
client = Ark(
api_key=os.environ.get("ARK_API_KEY"),
base_url="https://ark.cn-beijing.volces.com/api/v3",
)
if __name__ == "__main__":
try:
client.content_generation.tasks.delete(
task_id="",
)
except Exception as e:
print(f"failed to delete task: {e}")
```
**选项:Java**
```Java
package com.ark.sample;
import com.volcengine.ark.runtime.models.content_generation.*;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.volcengine.ark.runtime.service.ArkService;
import java.util.concurrent.TimeUnit;
import okhttp3.ConnectionPool;
import okhttp3.Dispatcher;
public class Sample {
static String apiKey = System.getenv("ARK_API_KEY");
static ConnectionPool connectionPool = new ConnectionPool(5, 1, TimeUnit.SECONDS);
static Dispatcher dispatcher = new Dispatcher();
static ArkService service =
ArkService.builder()
.dispatcher(dispatcher)
.connectionPool(connectionPool)
.apiKey(apiKey)
.baseUrl("https://ark.cn-beijing.volces.com/api/v3")
.build();
public static void main(String[] args) throws JsonProcessingException {
String req =
"";
service.deleteContentGenerationTask(req);
service.shutdownExecutor();
}
}
```
**选项:Go**
```Go
package main
import (
"context"
"fmt"
"os"
"github.com/volcengine/ark-runtime-go/arkruntime"
)
func main() {
client := arkruntime.NewClientWithApiKey(
os.Getenv("ARK_API_KEY"),
arkruntime.WithBaseUrl("https://ark.cn-beijing.volces.com/api/v3"),
)
ctx := context.Background()
req := ""
err := client.DeleteContentGenerationTask(ctx, req)
if err != nil {
fmt.Printf("delete content generation task error: %v\n", err)
return
}
}
```
## 自定义视频输出规格
通过 API 参数控制输出视频的规格,包括分辨率、宽高比、时长、是否包含水印等。
**常规方式(推荐)**:在 request body 中直接传入参数
> 此方式为强校验,若参数填写错误,模型会返回错误提示。
```JSON
"content": [
{
"type": "text",
"text": ""
}
],
"resolution": "720p",
"ratio":"16:9",
"duration": 5,
"seed": 11,
"camera_fixed": false,
"watermark": true
```
旧方式:在文本提示词后追加 --[parameters]
> 此方式为弱校验,若参数填写错误,该参数将被忽略或触发报错。
```JSON
"content": [
{
"type": "text",
"text": " --rs 720p --rt 16:9 --dur 5 --seed 11 --cf false --wm true"
}
]
```
### 分辨率和宽高比
通过以下参数控制输出视频的分辨率和宽高比,分辨率和宽高比将共同决定输出视频的像素尺寸。
- **resolution**:指定输出视频的分辨率,支持 480p,720p,1080p,4k。
- **ratio**:指定输出视频的宽高比,支持 16:9,4:3,1:1,3:4,9:16,21:9,adaptive。
> **说明**
>
> Seedance 2.5 在视频编辑、视频延长、首帧/首尾帧生视频任务下,ratio 仅支持 adaptive(自动保持与输入视频一致的宽高比),不支持自行设置具体宽高比。详见 [配置方法](/docs/seedance-2-5#2.5_param_constraints)。
```Json
{
"resolution": "720p",
"ratio":"16:9"
}
```
各模型输出视频的像素尺寸如下:
| 分辨率 | 宽高比 | Seedance 2.5 | Seedance 2.0 系列 | Seedance 1.0 系列 |
| ------------------------------------- | --------- | -------------------- | -------------------- | -------------------- |
| 480p | 16:9 | 854×480 | 864×496 | 864×480 |
| ^^ | 4:3 | 752×560 | 752×560 | 736×544 |
| ^^ | 1:1 | 640×640 | 640×640 | 640×640 |
| ^^ | 3:4 | 560×752 | 560×752 | 544×736 |
| ^^ | 9:16 | 480×854 | 496×864 | 480×864 |
| ^^ | 21:9 | 992×432 | 992×432 | 960×416 |
| 720p | 16:9 | 1280×720 | 1280×720 | 1248×704 |
| ^^ | 4:3 | 1112×834 | 1112×834 | 1120×832 |
| ^^ | 1:1 | 960×960 | 960×960 | 960×960 |
| ^^ | 3:4 | 834×1112 | 834×1112 | 832×1120 |
| ^^ | 9:16 | 720×1280 | 720×1280 | 704×1248 |
| ^^ | 21:9 | 1470×630 | 1470×630 | 1504×640 |
| 1080p | 16:9 | 1920×1080 | 1920×1080 | 1920×1088 | \
| > Seedance 2.0 Fast、Seedance 2.0 Mini 暂不支持 | | | | |
| ^^ | 4:3 | 1664×1248 | 1664×1248 | 1664×1248 |
| ^^ | 1:1 | 1440×1440 | 1440×1440 | 1440×1440 |
| ^^ | 3:4 | 1248×1664 | 1248×1664 | 1248×1664 |
| ^^ | 9:16 | 1080×1920 | 1080×1920 | 1088×1920 |
| ^^ | 21:9 | 2206×946 | 2206×946 | 2176×928 |
| 4k | 16:9 | — | 3840×2160 | — | \
| > 仅 Seedance 2.0 支持 | | | | |
| ^^ | 4:3 | — | 3326×2494 | — |
| ^^ | 1:1 | — | 2880×2880 | — |
| ^^ | 3:4 | — | 2494×3326 | — |
| ^^ | 9:16 | — | 2160×3840 | — |
| ^^ | 21:9 | — | 4398×1886 | — |
### 视频时长
通过 **duration** 参数控制生成视频的时长(整数秒):
- Seedance 1.0 系列: [2, 12]
- Seedance 2.0 系列: [4,15] 或设置为-1
- Seedance 2.5: [4,30] 或设置为-1
> -1 表示智能指定时长,由模型在有效范围内自主选择合适的视频长度
> **说明**
>
> Seedance 2.5 在 [视频编辑任务](/docs/seedance-2-5#2.5_task_type_intro) 下,duration 仅支持 -1(自动保持与输入视频基本一致的时长),不支持自行设置具体秒数。详见 [配置方法](/docs/seedance-2-5#2.5_param_constraints)。
```Json
{
"duration": 5
}
```
**Seedance 1.0 系列**模型还支持通过 **frames** 参数指定生成视频的帧数,从而生成小数秒的视频。
- 计算公式:帧数 = 时长 × 帧率(24)。
- 取值范围:frames 支持 [29, 289] 区间内所有满足 25 + 4n 格式的整数值,其中 n 为正整数。
- 注意事项:duration 和 frames 二选一即可,frames 的优先级高于 duration。
```Json
{
"frames": 29
}
```
### 视频中添加水印
通过 watermark 参数,来控制是否在生成的视频中添加水印。
- true:在视频右下角添加`AI生成`水印标识。
- false:不添加水印。
```Json
{
"watermark": true
}
```
## 提示词建议
* **提示词 = 主体 + 运动, 背景 + 运动,镜头 + 运动 ...**
* 用简洁准确的自然语言写出你想要的效果。
* 如果有较为明确的效果预期,建议先用生图模型生成符合预期的图片,再用图生视频进行视频片段的生成。
* 文生视频会有较大的结果随机性,可以用于激发创作灵感
* 图生视频时请尽量上传高清高质量的图片,上传图片的质量对图生视频影响较大。
* 当生成的视频不符合预期时,建议修改提示词,将抽象描述换成具象描述,并注意删除不重要的部分,将重要内容前置。
* 更多提示词的使用技巧请参见 [Doubao Seedance 2.0 系列提示词指南](/docs/seedance-2-0-prompt-guide)、[Seedance 1.0 系列提示词指南](/docs/seedance-1-0-pro-pro-fast)。
# 进阶使用
## 离线推理
> Seedance 2.5、Seedance 2.0 系列不支持
针对推理时延敏感度低(例如小时级响应)的场景,建议将 **service_tier** 设为 `flex`,一键切换至离线推理模式——价格仅为在线推理的 50%,显著降低业务成本。
注意根据业务场景设置合适的超时时间,超过该时间后任务将自动终止。
**选项:Python**
```Python
import os
import time
# Install SDK: python -m pip install --upgrade arkruntime
from arkruntime import Ark
# Make sure that you have stored the API Key in the environment variable ARK_API_KEY
# Initialize the Ark client to read your API Key from an environment variable
client = Ark(
# This is the default path. You can configure it based on the service location
base_url="https://ark.cn-beijing.volces.com/api/v3",
# Get API Key: https://ark.volcengine.com/region:cn-beijing/apikey
api_key=os.environ.get("ARK_API_KEY"),
)
if __name__ == "__main__":
print("----- create request -----")
create_result = client.content_generation.tasks.create(
model="doubao-seedance-1-0-pro-250528", # Replace with Model ID
content=[
{
# Combination of text prompt and parameters
"type": "text",
"text": "女孩抱着狐狸,女孩睁开眼,温柔地看向镜头,狐狸友善地抱着,镜头缓缓拉出,女孩的头发被风吹动"
},
{
# The URL of the first frame image
"type": "image_url",
"image_url": {
"url": "https://arkdocs.tos-cn-beijing.volces.com/images/video-generation/i2v_foxrgirl.png"
}
}
],
ratio="adaptive",
duration=5,
watermark=True,
service_tier="flex",
execution_expires_after=172800,
)
print(create_result)
# Polling query section
print("----- polling task status -----")
task_id = create_result.id
while True:
get_result = client.content_generation.tasks.get(task_id=task_id)
status = get_result.status
if status == "succeeded":
print("----- task succeeded -----")
print(get_result)
break
elif status == "failed":
print("----- task failed -----")
print(f"Error: {get_result.error}")
break
else:
print(f"Current status: {status}, Retrying after 60 seconds...")
time.sleep(60)
```
**选项:Java**
```Java
package com.ark.sample;
import com.volcengine.ark.runtime.models.content_generation.*;
import com.volcengine.ark.runtime.service.ArkService;
import okhttp3.ConnectionPool;
import okhttp3.Dispatcher;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
public class ContentGenerationTaskExample {
// Make sure that you have stored the API Key in the environment variable ARK_API_KEY
// Initialize the Ark client to read your API Key from an environment variable
static String apiKey = System.getenv("ARK_API_KEY");
static ConnectionPool connectionPool = new ConnectionPool(5, 1, TimeUnit.SECONDS);
static Dispatcher dispatcher = new Dispatcher();
static ArkService service = ArkService.builder()
.baseUrl("https://ark.cn-beijing.volces.com/api/v3")
// The base URL for model invocation
.dispatcher(dispatcher)
.connectionPool(connectionPool)
.apiKey(apiKey)
.build();
public static void main(String[] args) {
String model = "doubao-seedance-1-0-pro-250528"; // Replace with Model ID
String ratio = "adaptive";
Long duration = 5L;
Boolean watermark = true;
String serviceTier = "flex";
Long executionExpiresAfter = 172800L;
System.out.println("----- create request -----");
List contents = new ArrayList<>();
// Combination of text prompt and parameters
contents.add(ContentItem.builder()
.type(ContentType.TEXT)
.text("女孩抱着狐狸,女孩睁开眼,温柔地看向镜头,狐狸友善地抱着,镜头缓缓拉出,女孩的头发被风吹动")
.build());
// The URL of the first frame image
contents.add(ContentItem.builder()
.type(ContentType.IMAGE_URL)
.imageUrl(ImageURL.builder()
.url("https://arkdocs.tos-cn-beijing.volces.com/images/video-generation/i2v_foxrgirl.png")
.build())
.build());
// Create a video generation task
CreateContentGenerationTaskRequest createRequest = CreateContentGenerationTaskRequest.builder()
.model(model)
.content(contents)
.ratio(ratio)
.duration(duration)
.watermark(watermark)
.serviceTier(serviceTier)
.executionExpiresAfter(executionExpiresAfter)
.build();
CreateContentGenerationTaskResponse createResult = service.createContentGenerationTask(createRequest);
System.out.println(createResult);
// Get the details of the task
String taskId = createResult.getId();
String getRequest = taskId;
// Polling query section
System.out.println("----- polling task status -----");
while (true) {
try {
ContentGenerationTask getResponse = service.getContentGenerationTask(getRequest);
String status = getResponse.getStatus().toString();
if ("succeeded".equalsIgnoreCase(status)) {
System.out.println("----- task succeeded -----");
System.out.println(getResponse);
break;
} else if ("failed".equalsIgnoreCase(status)) {
System.out.println("----- task failed -----");
System.out.println("Error: " + getResponse.getStatus());
break;
} else {
System.out.printf("Current status: %s, Retrying in 60 seconds...", status);
TimeUnit.SECONDS.sleep(60);
}
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
System.err.println("Polling interrupted");
break;
}
}
}
}
```
**选项:Go**
```Go
package main
import (
"context"
"fmt"
"os"
"time"
"github.com/volcengine/ark-runtime-go/arkruntime"
model "github.com/volcengine/ark-runtime-go/arkruntime/model/contentgeneration"
)
func main() {
// Make sure that you have stored the API Key in the environment variable ARK_API_KEY
// Initialize the Ark client to read your API Key from an environment variable
client := arkruntime.NewClientWithApiKey(
// Get your API Key from the environment variable. This is the default mode and you can modify it as required
os.Getenv("ARK_API_KEY"),
// The base URL for model invocation
arkruntime.WithBaseUrl("https://ark.cn-beijing.volces.com/api/v3"),
)
ctx := context.Background()
// Replace with Model ID
modelEp := "doubao-seedance-1-0-pro-250528"
// Generate a task
fmt.Println("----- create request -----")
createReq := &model.CreateContentGenerationTaskRequest{
Model: modelEp,
Ratio: model.NewOptString("adaptive"),
Duration: model.NewOptInt64(5),
Watermark: model.NewOptBool(true),
ServiceTier: model.NewOptString("flex"),
ExecutionExpiresAfter: model.NewOptInt64(172800),
Content: []model.ContentItem{
{
// Combination of text prompt and parameters
Type: model.ContentTypeText,
Text: model.NewOptString("女孩抱着狐狸,女孩睁开眼,温柔地看向镜头,狐狸友善地抱着,镜头缓缓拉出,女孩的头发被风吹动"),
},
{
// The URL of the first frame image
Type: model.ContentTypeImageURL,
ImageURL: model.NewOptImageURL(model.ImageURL{
URL: "https://arkdocs.tos-cn-beijing.volces.com/images/video-generation/i2v_foxrgirl.png",
}),
},
},
}
createResp, err := client.CreateContentGenerationTask(ctx, createReq)
if err != nil {
fmt.Printf("create content generation error: %v", err)
return
}
taskID := createResp.ID
fmt.Printf("Task Created with ID: %s", taskID)
// Polling query section
fmt.Println("----- polling task status -----")
deadline := time.Now().Add(24 * time.Hour)
for {
getReq := taskID
getResp, err := client.GetContentGenerationTask(ctx, getReq)
if err != nil {
fmt.Printf("get content generation task error: %v", err)
return
}
status := getResp.Status
if status == "succeeded" {
fmt.Println("----- task succeeded -----")
fmt.Printf("Task ID: %s \n", getResp.ID)
fmt.Printf("Model: %s \n", getResp.Model)
fmt.Printf("Video URL: %s \n", getResp.Content.Or(model.TaskContent{}).VideoURL.Or(""))
fmt.Printf("Completion Tokens: %d \n", getResp.Usage.Or(model.TaskUsage{}).CompletionTokens)
fmt.Printf("Created At: %d, Updated At: %d", getResp.CreatedAt.Or(0), getResp.UpdatedAt.Or(0))
return
} else if status == "failed" {
fmt.Println("----- task failed -----")
if getResp.Error.IsSet() {
fmt.Printf("Error Code: %s, Message: %s", getResp.Error.Value.Code, getResp.Error.Value.Message)
}
return
} else {
if time.Now().After(deadline) {
fmt.Printf("Task %s is still %s; query it later by task ID.\n", taskID, status)
return
}
fmt.Printf("Current status: %s, Retrying in 60 seconds... \n", status)
time.Sleep(60 * time.Second)
}
}
}
```
## 样片模式
样片(Draft)模式是一种“先预览生成效果,再生成高质量成片”的两步式视频生成方式。开启该功能后,您可以先生成一段低分辨率的预览视频,用于验证其场景结构、镜头调度、主体动作和提示词意图等关键要素;确认结果符合预期后,再使用 Draft 视频任务 ID 生成高质量成片。
目前仅 Doubao Seedance 2.5 支持样片模式。参数限制、计费方式和操作步骤参见 [Doubao Seedance 2.5 样片模式](/docs/seedance-2-5#2.5_draft_mode)。
## 生成多个连续视频
使用前一个生成视频的尾帧,作为后一个视频任务的首帧,循环生成多个连续的视频。
后续您可以自行使用 FFmpeg 等工具,将生成的多个短视频拼接成一个完整长视频。
|输出1 |输出2 |输出3 |
|---|---|---|
|[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/c984894e448f43ca8a593babe411a078) |[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/ccb8cebc70bd42738ba8d4bb894b69e6) |[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/b78ed8dd418a4c97ac94253cb0c00728) | \
| | | | \
|> 女孩抱着狐狸,女孩睁开眼,温柔地看向镜头,狐狸友善地抱着,镜头缓缓拉出,女孩的头发被风吹动 |> 女孩和狐狸在草地上奔跑,阳光明媚,女孩的笑容灿烂,狐狸欢快地跳跃 |> 女孩和狐狸坐在树下休息,女孩轻轻抚摸狐狸的毛发,狐狸温顺地趴在女孩腿上 | \
|> A girl holding a fox, the girl opens her eyes, looks gently at the camera, the fox hugs affectionately, the camera slowly pulls out, the girl's hair is blown by the wind |> A girl and a fox running on the grass, sunny weather, the girl's smile is brilliant, the fox jumps happily |> A girl and a fox resting under a tree, the girl gently strokes the fox's fur, the fox lies meekly on the girl's lap |
```Python
import os
import time
# Install SDK: python -m pip install --upgrade arkruntime
from arkruntime import Ark
# Make sure that you have stored the API Key in the environment variable ARK_API_KEY
# Initialize the Ark client to read your API Key from an environment variable
client = Ark(
# This is the default path. You can configure it based on the service location
base_url="https://ark.cn-beijing.volces.com/api/v3",
# Get API Key:https://ark.volcengine.com/region:cn-beijing/apikey
api_key=os.environ.get("ARK_API_KEY"),
)
def generate_video_with_last_frame(prompt, initial_image_url=None):
"""
Generate video and return video URL and last frame URL
Parameters:
prompt: Text prompt for video generation
initial_image_url: Initial image URL (optional)
Returns:
video_url: Generated video URL
last_frame_url: URL of the last frame of the video
"""
print(f"----- Generating video: {prompt} -----")
# Build content list
content = [{
"text": prompt,
"type": "text"
}]
# If initial image is provided, add to content
if initial_image_url:
content.append({
"image_url": {
"url": initial_image_url
},
"type": "image_url"
})
# Create video generation task
create_result = client.content_generation.tasks.create(
model="doubao-seedance-2-5-260628", # Replace with Model ID
content=content,
return_last_frame=True,
ratio="adaptive",
duration=5,
watermark=True,
)
# Poll to check task status
task_id = create_result.id
while True:
get_result = client.content_generation.tasks.get(task_id=task_id)
status = get_result.status
if get_result.status == "succeeded":
print("Video generation succeeded")
try:
if hasattr(get_result, 'content') and hasattr(get_result.content, 'video_url') and hasattr(get_result.content, 'last_frame_url'):
return get_result.content.video_url, get_result.content.last_frame_url
print("Failed to obtain video URL or last frame URL")
return None, None
except Exception as e:
print(f"Error occurred while obtaining video URL and last frame URL: {e}")
return None, None
elif status == "failed":
print(f"----- Video generation failed -----")
print(f"Error: {get_result.error}")
return None, None
else:
print(f"Current status: {status}, retrying in 10 seconds...")
time.sleep(10)
if __name__ == "__main__":
# Define 3 video prompts
prompts = [
"女孩抱着狐狸,女孩睁开眼,温柔地看向镜头,狐狸友善地抱着,镜头缓缓拉出,女孩的头发被风吹动",
"女孩和狐狸在草地上奔跑,阳光明媚,女孩的笑容灿烂,狐狸欢快地跳跃",
"女孩和狐狸坐在树下休息,女孩轻轻抚摸狐狸的毛发,狐狸温顺地趴在女孩腿上"
]
# Store generated video URLs
video_urls = []
# Initial image URL
initial_image_url = "https://arkdocs.tos-cn-beijing.volces.com/images/video-generation/i2v_foxrgirl.png"
# Generate 3 short videos
for i, prompt in enumerate(prompts):
print(f"Generating video {i+1}")
video_url, last_frame_url = generate_video_with_last_frame(prompt, initial_image_url)
if video_url and last_frame_url:
video_urls.append(video_url)
print(f"Video {i+1} URL: {video_url}")
# Use the last frame of the current video as the first frame of the next video
initial_image_url = last_frame_url
else:
print(f"Video {i+1} generation failed, exiting program")
exit(1)
print("All videos generated successfully!")
print("Generated video URL list:")
for i, url in enumerate(video_urls):
print(f"Video {i+1}: {url}")
```
## 使用 Webhook 通知
通过 **callback_url** 参数可以指定一个回调通知地址,当视频生成任务的状态发生变化时,方舟会向该地址发送一条 POST 请求,方便您及时获取任务最新情况。 请求内容结构与 [查询任务API](/docs/get-video-generation-task-api) 的返回体一致。
```Bash
{
"id": "",
"model": "doubao-seedance-2-5-260628",
"status": "running", # Possible status values: queued, running, succeeded, failed, expired
"created_at": 1765434920,
"updated_at": 1765434920,
"service_tier": "default",
"execution_expires_after": 172800
}
```
您需要自行搭建一个公网可访问的 Web Server 来接收 Webhook 通知。以下是一个简单的 Web Server 代码示例,供您参考。
```Python
# Building a Simple Web Server with Python Flask for Webhook Notification Processing
from flask import Flask, request, jsonify
import sqlite3
import logging
from datetime import datetime
import os
# === Basic Configuration ===
app = Flask(__name__)
# Configure logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
handlers=[logging.FileHandler('webhook.log'), logging.StreamHandler()]
)
# Database path
DB_PATH = 'video_tasks.db'
# === Database Initialization ===
def init_db():
"""Automatically create task table on first run, aligning fields with callback parameters"""
conn = sqlite3.connect(DB_PATH)
cursor = conn.cursor()
# Create table: task_id as primary key for idempotent updates
cursor.execute('''
CREATE TABLE IF NOT EXISTS video_generation_tasks (
task_id TEXT PRIMARY KEY,
model TEXT NOT NULL,
status TEXT NOT NULL,
created_at INTEGER NOT NULL,
updated_at INTEGER NOT NULL,
service_tier TEXT NOT NULL,
execution_expires_after INTEGER NOT NULL,
last_callback_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
''')
conn.commit()
conn.close()
logging.info("Database initialized, table created/exists")
# === Core Webhook Interface ===
@app.route('/webhook/callback', methods=['POST'])
def video_task_callback():
"""Core interface for receiving Ark callback"""
try:
# 1. Parse callback request body (JSON format)
callback_data = request.get_json()
if not callback_data:
logging.error("Callback request body empty or non-JSON format")
return jsonify({"code": 400, "msg": "Invalid JSON data"}), 400
# 2. Validate required fields
required_fields = ['id', 'model', 'status', 'created_at', 'updated_at', 'service_tier', 'execution_expires_after']
for field in required_fields:
if field not in callback_data:
logging.error(f"Callback data missing required field: {field}, data: {callback_data}")
return jsonify({"code": 400, "msg": f"Missing field: {field}"}), 400
# 3. Extract key information and log
task_id = callback_data['id']
status = callback_data['status']
model = callback_data['model']
logging.info(f"Received task callback | Task ID: {task_id} | Status: {status} | Model: {model}")
print(f"[{datetime.now()}] Task {task_id} status updated to: {status}") # Console output
# 4. Database operation
conn = sqlite3.connect(DB_PATH)
cursor = conn.cursor()
cursor.execute('''
INSERT OR REPLACE INTO video_generation_tasks (
task_id, model, status, created_at, updated_at, service_tier, execution_expires_after
) VALUES (?, ?, ?, ?, ?, ?, ?)
''', (
task_id,
model,
status,
callback_data['created_at'],
callback_data['updated_at'],
callback_data['service_tier'],
callback_data['execution_expires_after']
))
conn.commit()
conn.close()
logging.info(f"Task {task_id} database update successful")
# 5. Return 200 response
return jsonify({"code": 200, "msg": "Callback received successfully", "task_id": task_id}), 200
except Exception as e:
# Catch all exceptions to avoid returning 5xx
logging.error(f"Callback processing failed: {str(e)}", exc_info=True)
return jsonify({"code": 200, "msg": "Callback received successfully (internal processing exception)"}), 200
# === Helper Interface (Optional, for querying task status) ===
@app.route('/tasks/', methods=['GET'])
def get_task_status(task_id):
"""Query latest status of specified task"""
conn = sqlite3.connect(DB_PATH)
cursor = conn.cursor()
cursor.execute('SELECT * FROM video_generation_tasks WHERE task_id = ?', (task_id,))
task = cursor.fetchone()
conn.close()
if not task:
return jsonify({"code": 404, "msg": "Task not found"}), 404
# Map field names for response
fields = ['task_id', 'model', 'status', 'created_at', 'updated_at', 'service_tier', 'execution_expires_after', 'last_callback_at']
task_dict = dict(zip(fields, task))
return jsonify({"code": 200, "data": task_dict}), 200
# === Service Startup ===
if __name__ == '__main__':
# Initialize database
init_db()
# Start Flask service (bind to 0.0.0.0 for public access, port customizable)
# Test environment: debug=True; Production environment should disable debug and use gunicorn
app.run(host='0.0.0.0', port=8080, debug=False)
```
# 使用限制
## 全模态输入
> **注意**
>
> Seedance 2.5 和 Seedance 2.0 系列模型不支持直接上传含有真人人脸的参考图/视频。为了便利创作者对肖像的使用,平台推出了一系列解决方案,详情参见 [便利创作含肖像视频](/docs/seedance-portrait-asset-guide) 章节。
**图片要求**
* 传入方式:图片 URL、图片 Base64 编码、素材 ID。
* 图片格式:jpeg、png、webp、bmp、tiff、gif。其中,Seedance 2.0 系列及以上模型支持 heic 和 heif。
* 单个图片尺寸:
* 宽高比(宽/高): [0.4, 2.5]
* 宽高长度(px):[300, 6000]
* 大小:单张图片小于 30 MB。请求体大小不超过 64 MB。大文件请勿使用Base64编码。
* 图片数量:
* 图生视频-首帧:1 张
* 图生视频-首尾帧:2 张
* seedance 2.5 全模态参考生视频:1~30 张
* seedance 2.0 全模态参考生视频:1~9 张
**视频要求**
* 传入方式:视频URL、素材 ID。
* 视频格式:mp4、mov,支持编码格式见下表。
* 分辨率:480p,720p,1080p,4k
* 时长:
* Seedance 2.5:
* 非视频编辑任务:单个视频时长 [2, 30] s。
* [视频编辑任务](/docs/seedance-2-5#2.5_task_type_intro):单个视频时长 [4, 30] s。
* 最多传入 10 个参考视频,所有视频总时长不超过 30 s。
* Seedance 2.0 系列:单个视频时长 [2, 15] s,最多传入 3 个参考视频,所有视频总时长不超过 15 s。
* 单个视频尺寸:
* 宽高比(宽/高):[0.4, 2.5]
* 宽高长度(px):[300, 6000]
* 总像素数:[614×664=407696, 3326×2494=8295044],即宽和高的乘积符合 [407696, 8295044] 的区间要求。
* 大小:单个视频不超过 200 MB。
* 帧率 (FPS):[24, 60]
|**容器格式** |**常用文件扩展名** |**MIME** |**支持编码** |
|---|---|---|---|
|MP4 |.mp4 |video/mp4 |视频:H.264/AVC、H.265/HEVC | \
| | | |音频:AAC、MP3 |
|QuickTime |.mov |video/quicktime |视频:H.264/AVC、H.265/HEVC | \
| | | |音频:AAC、MP3 |
**音频要求**
* 传入方式:音频 URL 、音频 Base64 编码、素材 ID。
* 音频格式:wav、mp3
* 时长:
* Seedance 2.5:单个音频时长 [2, 30] s,最多传入 10 段参考音频,所有音频总时长不超过 30 s。
* Seedance 2.0 系列:单个音频时长 [2, 15] s,最多传入 3 段参考音频,所有音频总时长不超过 15 s。
* 大小:单个音频不超过 15 MB,请求体大小不超过 64 MB。大文件请勿使用Base64编码。
## 保存时间
- 任务记录:保存 7 天,查询区间 [T-7天, T),T 为请求发起时刻的 UTC 秒级时间戳。
- 视频 URL:保存 24 小时(超时后无法访问),下载次数上限为 100 次,请及时下载或转存。
## 限流说明
同一主账号下,使用同一模型(不区分版本)的请求受到以下限制。超过对应限制会返回 “429: 'Too Many Requests'” 错误。
### 模型维度的限流
**在线推理**
> 不同模型的 RPM 和最大并发任务数不同,详见 [视频生成能力](/docs/model-list#7571da3f)。
* **RPM(Requests Per Minute)**:每分钟允许创建的视频生成任务数上限。超过上限时,创建任务请求将因触发限流而失败。
* **最大并发任务数**:同一时刻可处于处理状态的任务数上限。达到上限后,新创建的任务将进入队列等待处理。
**离线推理**
> 不同模型的 TPD 限流值不同,详见 [视频生成能力](/docs/model-list#7571da3f)。
* **TPD(Tokens Per Day)**:每天可以处理的 token 量限制。
### 非推理 API 请求频率限制
* **QPS(Queries Per Second)**:每秒允许的请求数上限。超过上限时,任务请求将因触发限流而失败。
|接口名称 |账号维度的 QPS 上限 |
|---|---|
|查询视频生成任务 |20 |
|查询视频生成任务列表 |1 |
|取消或删除视频生成任务 |20 |
## 图片裁剪规则
**seedance 系列模型的图生视频场景,支持设置生成视频的宽高比**。当选择的视频宽高与您上传的图片宽高比不一致时,方舟会对您的图片进行裁剪,裁剪时会居中裁剪。详细规则如下:
> **说明**
>
> 若要呈现出较好的视频效果,建议所指定的视频宽高比(ratio)与实际上传图片的宽高比尽可能接近。
1. 输入参数:
* 原始图片宽度记为`W`(单位:像素),高度记为`H`(单位:像素)。
* 目标比例记为`A:B`(例如,21:9),这表示裁剪后的宽度与高度之比应为 `A/B`(如 21/9≈2.333)。
2. 比较宽高比:
* 计算原始图片的宽高比`Ratio_原始=W/H`。
* 计算目标比例的比值`Ratio_目标=A/B`(例如,21:9 的 Ratio目标=21/9≈2.333)。
* 根据比较结果,决定裁剪基准:
* 如果`Ratio_原始Ratio_目标`(即原始图片“太宽”或“横宽”),则以高度为基准裁剪。
* 如果相等,则无需裁剪,直接使用全图。
3. 裁剪尺寸计算(量化公式):
* 以宽度为基准(适用于竖高图片):
* 裁剪宽度`Crop_W=W`(使用整个原始宽度)。
* 裁剪高度`Crop_H=(B/A)×W`(根据目标比例等比例计算高度)。
* 裁剪区域的起始坐标(居中定位):
* X 坐标(水平):总是 0(因为宽度全用,从左侧开始)。
* Y 坐标(垂直):`(H−Crop_H)/2`(确保垂直居中,从顶部开始)。
* 以高度为基准(适用于横宽图片):
* 裁剪高度`Crop_H=H`(使用整个原始高度)。
* 裁剪宽度`Crop_W=(A/B)×H`(根据目标比例等比例计算宽度)。
* 裁剪区域的起始坐标(居中定位):
* X 坐标(水平):`(W−Crop_W)/2`(确保水平居中,从左侧开始)。
* Y 坐标(垂直):总是 0(因为高度全用,从顶部开始)。
4. 裁剪结果:
* 最终裁剪出的图片尺寸为`Crop_W×Crop_H`,比例严格为`A:B`,且完全位于原始图片内部,无黑边。
* 裁剪区域总是以原始图片中心为基准,因此内容居中。
5. 裁剪示例:
> 以 seedance 1.0 Pro 首帧图生视频功能为例
|输入的首帧图片 |指定的宽高比ratio |生成的视频结果 |
|---|---|---|
|16:9 |21:9 |[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/6e8590c07be9406d805209355b799a37) | \
| | | | \
| | | | \
| | | |
|^^| | | \
| |16:9 |[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/e0bef5f3806f439da5f0c9f5acc44c9b) |
|^^| | | \
| |4:3 |[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/a8e3202b77744bec83e0c7baa247b84c) |
|^^| | | \
| |1:1 |[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/436df8f6dae74d6c86d08bf1e18bc9d0) |
|^^| | | \
| |3:4 |[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/a3a94a577d754501889535a651d03a55) |
|^^| | | \
| |9:16 |[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/1423ee0fc9cf451398788dc57e9f55c4) |
---
# Doubao Seedance 便利创作含肖像视频
Source: https://ark.volcengine.com/region:cn-beijing/docs/seedance-portrait-asset-guide
Seedance 2.5、Seedance 2.0 系列模型不支持直接上传含有真人人脸的参考图/视频。为便利创作者使用肖像素材进行视频生成,平台提供以下解决方案。
|方案 |介绍 |
|---|---|
|[信任模型产物作为输入素材](/docs/seedance-portrait-asset-guide#trust-model-output) | 本账号下部分模型生成的含人脸原始产物可作为输入素材,再次调用 Seedance 2.5、Seedance 2.0 系列模型进行二次创作,不会触发输入审核拦截。 |
|[使用预置虚拟人像](/docs/seedance-portrait-asset-guide#preset-avatar) |平台预置虚拟人像库,为创作者提供免费、合规、丰富多样的肖像素材。适用于需真人风格人脸但无需指定具体人物,追求零合规风险、快速创作的场景。 |
|[使用已授权真人素材](/docs/seedance-portrait-asset-guide#authorized-real-person) |支持使用已获得授权的真人肖像素材进行视频生成。 |
# 信任模型产物作为输入素材
Seedance 2.5、Seedance 2.0 系列模型不支持直接上传含有真人人脸的参考图/视频。为了便利创作者在含人脸场景的二次创作需求,方舟平台信任以下模型生成的含人脸产物,您可使用**本账号下近 30 天内由以下模型生成的含人脸原始产物**,作为输入素材,再次调用 Seedance 2.5、Seedance 2.0 系列模型进行二次创作。
## 信任范围与有效期
|信任产物范围 |生效时间 |有效期 | \
| |> 信任该时间之后生成的产物 |> 从产物生成时间开始计算 |
|---|---|---|
|Seedance 2.5、Seedance 2.0 系列生成的含人脸视频 |2026年03月11日起 |30天 |
|Seedance 2.5、Seedance 2.0 系列生成的含人脸视频对应的尾帧图片 |2026年04月16日起 |30天 |
|[Seedream 5.0 lite/pro/flash 文生图](/docs/seedream-4-0-5-0#9695d195) 得到的含人脸图片 |2026年04月16日起 |30天 |
## 注意事项
> **注意**
>
> * 仅信任方舟平台的产物,不支持跨平台使用。
> * 仅信任同账号下的产物,不支持跨账号使用。
> * 仅信任模型原始产物,二次剪辑或超过有效期后均不可使用。
> * 压缩或转发文件易引发信任失效,建议直接将模型原始产物转存至 TOS 使用。
> * 仅对输入的产物进行信任,输出依然有可能因命中方舟安全审核策略而失败,详情参见 [错误码](/docs/error-codes)。
> * 信任仅对命中人脸审核生效,对于不含人脸场景,模型产物不存在受信问题,支持自由剪辑后进行二次创作。
## 代码示例
|输入:同账号生成的视频 |输出 |
|---|---|
|[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/24e27818aeb644b6942c2cbc949ddc86) |[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/44d52b9f0768460c8c86b81d2df40350) | \
| | | \
|> [使用预置虚拟人像](/docs/seedance-portrait-asset-guide#preset-avatar) 示例生成的视频 |> 输入:将面霜的颜色修改为白色。 | \
| |> ratio 修改为16:9 |
**选项:Python**
1. 首次生视频,并获取视频 URL。此处直接用 [使用预置虚拟人像](/docs/seedance-portrait-asset-guide#preset-avatar) 示例生成的视频。
2. 对 Seedance 2.5、Seedance 2.0 系列生成的视频进行再次编辑。视频原始 URL 的有效期仅 24 小时,本示例将原始视频转存至 TOS 使用。
> **说明**
>
> 视频原始 URL 的有效期仅 24 小时,实际使用时,建议您提前转存视频文件。推荐配置火山引擎 TOS 提供的数据订阅功能,将您的视频产物自动转存到自己的 TOS 桶中,便于长期备份或二次加工。详细介绍请参见 [TOS 数据订阅](https://docs.volcengine.com/docs/TorchObjectStorage/Datasubscription-5?lang=zh)。
```Python
import os
import time
# Install SDK: python -m pip install --upgrade arkruntime
from arkruntime import Ark
client = Ark(
# The base URL for model invocation
base_url='https://ark.cn-beijing.volces.com/api/v3',
# Get API Key:https://ark.volcengine.com/region:cn-beijing/apikey
api_key=os.environ.get("ARK_API_KEY"),
)
if __name__ == "__main__":
print("----- create request -----")
create_result = client.content_generation.tasks.create(
model="doubao-seedance-2-0-260128", # Replace with Model ID
content=[
{
"type": "text",
"text": "将面霜的颜色修改为白色。"
},
{
"type": "video_url",
"video_url": {
"url": "https://arkdocs.tos-cn-beijing.volces.com/videos/advanced-usage/video_by_sd2-zh.mp4"
},
"role": "reference_video"
},
],
generate_audio=True,
ratio="16:9",
duration=11,
watermark=True,
)
print(create_result)
print("----- polling task status -----")
task_id = create_result.id
while True:
get_result = client.content_generation.tasks.get(task_id=task_id)
status = get_result.status
if status == "succeeded":
print("----- task succeeded -----")
print(get_result)
break
elif status == "failed":
print("----- task failed -----")
print(f"Error: {get_result.error}")
break
else:
print(f"Current status: {status}, Retrying after 30 seconds...")
time.sleep(30)
```
**选项:Java**
1. 首次生视频,并获取视频 URL。此处直接用 [使用预置虚拟人像](/docs/seedance-portrait-asset-guide#preset-avatar) 示例生成的视频。
2. 对 Seedance 2.5、Seedance 2.0 系列生成的视频进行再次编辑。视频原始 URL 的有效期仅 24 小时,本示例将原始视频转存至 TOS 使用。
> **说明**
>
> 视频原始 URL 的有效期仅 24 小时,实际使用时,建议您提前转存视频文件。推荐配置火山引擎 TOS 提供的数据订阅功能,将您的视频产物自动转存到自己的 TOS 桶中,便于长期备份或二次加工。详细介绍请参见 [TOS 数据订阅](https://docs.volcengine.com/docs/TorchObjectStorage/Datasubscription-5?lang=zh)。
```Java
package com.ark.sample;
import com.volcengine.ark.runtime.models.content_generation.*;
import com.volcengine.ark.runtime.service.ArkService;
import okhttp3.ConnectionPool;
import okhttp3.Dispatcher;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
public class ContentGenerationTaskExample {
// Client initialization
static String apiKey = System.getenv("ARK_API_KEY");
static ConnectionPool connectionPool = new ConnectionPool(5, 1, TimeUnit.SECONDS);
static Dispatcher dispatcher = new Dispatcher();
static ArkService service = ArkService.builder()
.baseUrl("https://ark.cn-beijing.volces.com/api/v3") // The base URL for model invocation
.dispatcher(dispatcher)
.connectionPool(connectionPool)
.apiKey(apiKey)
.build();
public static void main(String[] args) {
// Model ID
final String modelId = "doubao-seedance-2-0-260128";
// Text prompt
final String prompt = "将面霜的颜色修改为白色。";
// Example resource URLs
final String refVideo = "https://arkdocs.tos-cn-beijing.volces.com/videos/advanced-usage/video_by_sd2-zh.mp4";
// Output video parameters
final boolean generateAudio = true;
final String videoRatio = "16:9";
final long videoDuration = 11L;
final boolean showWatermark = true;
System.out.println("----- create request -----");
// Build request content
List contents = new ArrayList<>();
// 1. Text prompt
contents.add(ContentItem.builder()
.type(ContentType.TEXT)
.text(prompt)
.build());
// 2. Reference video
contents.add(ContentItem.builder()
.type(ContentType.VIDEO_URL)
.videoUrl(VideoURL.builder()
.url(refVideo)
.build())
.role("reference_video")
.build());
// Create video generation task
CreateContentGenerationTaskRequest createRequest = CreateContentGenerationTaskRequest.builder()
.generateAudio(generateAudio)
.model(modelId)
.content(contents)
.ratio(videoRatio)
.duration(videoDuration)
.watermark(showWatermark)
.build();
CreateContentGenerationTaskResponse createResult = service.createContentGenerationTask(createRequest);
System.out.println("Task Created: " + createResult);
// Get task details and poll status
String taskId = createResult.getId();
pollTaskStatus(taskId);
}
/**
* Poll task status
* @param taskId Task ID
*/
private static void pollTaskStatus(String taskId) {
String getRequest = taskId;
System.out.println("----- polling task status -----");
try {
while (true) {
ContentGenerationTask getResponse = service.getContentGenerationTask(getRequest);
String status = getResponse.getStatus().toString();
if ("succeeded".equalsIgnoreCase(status)) {
System.out.println("----- task succeeded -----");
System.out.println(getResponse);
break;
} else if ("failed".equalsIgnoreCase(status)) {
System.out.println("----- task failed -----");
if (getResponse.getError() != null) {
System.out.println("Error: " + getResponse.getError().getMessage());
}
break;
} else {
System.out.printf("Current status: %s, Retrying in 10 seconds...%n", status);
TimeUnit.SECONDS.sleep(10);
}
}
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
System.err.println("Polling interrupted");
} catch (Exception e) {
System.err.println("Error occurred: " + e.getMessage());
} finally {
service.shutdownExecutor();
}
}
}
```
**选项:Go**
1. 首次生视频,并获取视频 URL。此处直接用 [使用预置虚拟人像](/docs/seedance-portrait-asset-guide#preset-avatar) 示例生成的视频。
2. 对 Seedance 2.5、Seedance 2.0 系列生成的视频进行再次编辑。视频原始 URL 的有效期仅 24 小时,本示例将原始视频转存至 TOS 使用。
> **说明**
>
> 视频原始 URL 的有效期仅 24 小时,实际使用时,建议您提前转存视频文件。推荐配置火山引擎 TOS 提供的数据订阅功能,将您的视频产物自动转存到自己的 TOS 桶中,便于长期备份或二次加工。详细介绍请参见 [TOS 数据订阅](https://docs.volcengine.com/docs/TorchObjectStorage/Datasubscription-5?lang=zh)。
```Go
package main
import (
"context"
"fmt"
"os"
"time"
"github.com/volcengine/ark-runtime-go/arkruntime"
model "github.com/volcengine/ark-runtime-go/arkruntime/model/contentgeneration"
)
func main() {
// Initialize Ark client
client := arkruntime.NewClientWithApiKey(
os.Getenv("ARK_API_KEY"),
// The base URL for model invocation
arkruntime.WithBaseUrl("https://ark.cn-beijing.volces.com/api/v3"),
)
ctx := context.Background()
// Model ID
modelID := "doubao-seedance-2-0-260128"
// Text prompt
prompt := "将面霜的颜色修改为白色。"
// Example resource URLs
refVideo1 := "https://arkdocs.tos-cn-beijing.volces.com/videos/advanced-usage/video_by_sd2-zh.mp4"
// Output video parameters
generateAudio := true
videoRatio := "16:9"
videoDuration := int64(11)
showWatermark := true
// 1. Create video generation task
fmt.Println("----- create request -----")
createReq := &model.CreateContentGenerationTaskRequest{
Model: modelID,
GenerateAudio: model.NewOptBool(generateAudio),
Ratio: model.NewOptString(videoRatio),
Duration: model.NewOptInt64(videoDuration),
Watermark: model.NewOptBool(showWatermark),
Content: []model.ContentItem{
{
Type: model.ContentTypeText,
Text: model.NewOptString(prompt),
},
{
Type: model.ContentTypeVideoURL,
VideoURL: model.NewOptVideoURL(model.VideoURL{
URL: refVideo1,
}),
Role: model.NewOptString("reference_video"),
},
},
}
createResp, err := client.CreateContentGenerationTask(ctx, createReq)
if err != nil {
fmt.Printf("create content generation error: %v\n", err)
return
}
taskID := createResp.ID
fmt.Printf("Task Created with ID: %s\n", taskID)
// 2. Poll task status
pollTaskStatus(ctx, client, taskID)
}
// poll task status
func pollTaskStatus(ctx context.Context, client *arkruntime.Client, taskID string) {
fmt.Println("----- polling task status -----")
for {
getReq := taskID
getResp, err := client.GetContentGenerationTask(ctx, getReq)
if err != nil {
fmt.Printf("get content generation task error: %v\n", err)
return
}
status := getResp.Status
if status == "succeeded" {
fmt.Println("----- task succeeded -----")
fmt.Printf("Task ID: %s \n", getResp.ID)
fmt.Printf("Model: %s \n", getResp.Model)
fmt.Printf("Video URL: %s \n", getResp.Content.Or(model.TaskContent{}).VideoURL.Or(""))
fmt.Printf("Completion Tokens: %d \n", getResp.Usage.Or(model.TaskUsage{}).CompletionTokens)
fmt.Printf("Created At: %d, Updated At: %d\n", getResp.CreatedAt.Or(0), getResp.UpdatedAt.Or(0))
return
} else if status == "failed" {
fmt.Println("----- task failed -----")
if getResp.Error.IsSet() {
fmt.Printf("Error Code: %s, Message: %s\n", getResp.Error.Value.Code, getResp.Error.Value.Message)
}
return
} else {
fmt.Printf("Current status: %s, Retrying in 10 seconds... \n", status)
time.Sleep(10 * time.Second)
}
}
}
```
# 使用预置虚拟人像
对写实风格视频,可通过虚拟人像库预置人像来控制角色样貌。每个素材对应一个独立素材 ID (asset ID), 在 **content.<模态>_url.url** 字段中传入 `asset://` 即可生成视频。
> **说明**
>
> 开通虚拟人像库,浏览及检索虚拟人像请参见[虚拟人像库](/docs/avatar-library)。
|输入:文本 |输入:虚拟人像、图片 |输出 |
|---|---|---|
|固定机位,近景镜头,清新自然风格。在室内自然光下,**图片1**中美妆博主面带笑容,向镜头介绍**图片2**中的面霜。博主将手里的面霜展示给镜头,开心地说"挖到本命面霜了!";接着她一边用手指轻轻蘸取面霜展示那种软糯感,一边说"质地像云朵一样软糯,一抹就吸收";最后她把面霜涂抹在脸颊上,展示着水润透亮的皮肤,同时自信地说"熬夜急救、补水保湿全搞定"。要求画面中人物居中,完整展示人物的整个脑袋和上半身,始终对焦人脸,人脸始终清晰,纯净无任何字幕。 | |[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/0bd96f702bdf48bab1a9505710d9e1f9) | \
| | | | \
| |> 虚拟人像 | | \
| | | | \
|Asset ID 仅用来向模型传入素材,提示词中仍需使用"**素材类型+序号**"格式引用素材,序号为请求体中该素材在同类素材中的排序。 | | | \
|正确用法:**图片1**中美妆博主 | | | \
|错误用法:asset-2026****是美妆博主 |> 产品图像 | | \
| | | |
**选项:Python**
```Python
import os
import time
# Install SDK: python -m pip install --upgrade arkruntime
from arkruntime import Ark
client = Ark(
# The base URL for model invocation
base_url='https://ark.cn-beijing.volces.com/api/v3',
# Get API Key:https://ark.volcengine.com/region:cn-beijing/apikey
api_key=os.environ.get("ARK_API_KEY"),
)
if __name__ == "__main__":
print("----- create request -----")
create_result = client.content_generation.tasks.create(
model="doubao-seedance-2-0-260128", # Replace with Model ID
content=[
{
"type": "text",
"text": "固定机位,近景镜头,清新自然风格。在室内自然光下,图片1中美妆博主面带笑容,向镜头介绍图片2中的面霜。博主将手里的面霜展示给镜头,开心地说“挖到本命面霜了!”;接着她一边用手指轻轻蘸取面霜展示那种软糯感,一边说“质地像云朵一样软糯,一抹就吸收”;最后她把面霜涂抹在脸颊上,展示着水润透亮的皮肤,同时自信地说“熬夜急救、补水保湿全搞定”。要求画面中人物居中,完整展示人物的整个脑袋和上半身,始终对焦人脸,人脸始终清晰,纯净无任何字幕。"
},
{
"type": "image_url",
"image_url": {
"url": "asset://asset-20260401123823-6d4x2"
},
"role": "reference_image"
},
{
"type": "image_url",
"image_url": {
"url": "https://arkdocs.tos-cn-beijing.volces.com/images/video-generation/r2v_edit_pic1.jpg"
},
"role": "reference_image"
},
],
generate_audio=True,
ratio="adaptive",
duration=11,
watermark=True,
)
print(create_result)
print("----- polling task status -----")
task_id = create_result.id
while True:
get_result = client.content_generation.tasks.get(task_id=task_id)
status = get_result.status
if status == "succeeded":
print("----- task succeeded -----")
print(get_result)
break
elif status == "failed":
print("----- task failed -----")
print(f"Error: {get_result.error}")
break
else:
print(f"Current status: {status}, Retrying after 30 seconds...")
time.sleep(30)
```
**选项:Java**
```Java
package com.ark.sample;
import com.volcengine.ark.runtime.models.content_generation.*;
import com.volcengine.ark.runtime.service.ArkService;
import okhttp3.ConnectionPool;
import okhttp3.Dispatcher;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
public class ContentGenerationTaskExample {
// Client initialization
static String apiKey = System.getenv("ARK_API_KEY");
static ConnectionPool connectionPool = new ConnectionPool(5, 1, TimeUnit.SECONDS);
static Dispatcher dispatcher = new Dispatcher();
static ArkService service = ArkService.builder()
.baseUrl("https://ark.cn-beijing.volces.com/api/v3")
// The base URL for model invocation
.dispatcher(dispatcher)
.connectionPool(connectionPool)
.apiKey(apiKey)
.build();
public static void main(String[] args) {
// Model ID
final String modelId = "doubao-seedance-2-0-260128";
// Text prompt
final String prompt = "固定机位,近景镜头,清新自然风格。在室内自然光下,图片1中美妆博主面带笑容,向镜头介绍图片2中的面霜。博主将手里的面霜展示给镜头,开心地说“挖到本命面霜了!”;接着她一边用手指轻轻蘸取面霜展示那种软糯感,一边说“质地像云朵一样软糯,一抹就吸收”;最后她把面霜涂抹在脸颊上,展示着水润透亮的皮肤,同时自信地说“熬夜急救、补水保湿全搞定”。要求画面中人物居中,完整展示人物的整个脑袋和上半身,始终对焦人脸,人脸始终清晰,纯净无任何字幕。";
// Example resource URLs
final String refImage1 = "asset://asset-20260401123823-6d4x2";
final String refImage2 = "https://arkdocs.tos-cn-beijing.volces.com/images/video-generation/r2v_edit_pic1.jpg";
// Output video parameters
final boolean generateAudio = true;
final String videoRatio = "adaptive";
final long videoDuration = 11L;
final boolean showWatermark = true;
System.out.println("----- create request -----");
// Build request content
List contents = new ArrayList<>();
// 1. Text prompt
contents.add(ContentItem.builder()
.type(ContentType.TEXT)
.text(prompt)
.build());
// 2. Reference image 1
contents.add(ContentItem.builder()
.type(ContentType.IMAGE_URL)
.imageUrl(ImageURL.builder()
.url(refImage1)
.build())
.role("reference_image")
.build());
// 3. Reference image 2
contents.add(ContentItem.builder()
.type(ContentType.IMAGE_URL)
.imageUrl(ImageURL.builder()
.url(refImage2)
.build())
.role("reference_image")
.build());
// Create video generation task
CreateContentGenerationTaskRequest createRequest = CreateContentGenerationTaskRequest.builder()
.generateAudio(generateAudio)
.model(modelId)
.content(contents)
.ratio(videoRatio)
.duration(videoDuration)
.watermark(showWatermark)
.build();
CreateContentGenerationTaskResponse createResult = service.createContentGenerationTask(createRequest);
System.out.println("Task Created: " + createResult);
// Get task details and poll status
String taskId = createResult.getId();
pollTaskStatus(taskId);
}
/**
* Poll task status
* @param taskId Task ID
*/
private static void pollTaskStatus(String taskId) {
String getRequest = taskId;
System.out.println("----- polling task status -----");
try {
while (true) {
ContentGenerationTask getResponse = service.getContentGenerationTask(getRequest);
String status = getResponse.getStatus().toString();
if ("succeeded".equalsIgnoreCase(status)) {
System.out.println("----- task succeeded -----");
System.out.println(getResponse);
break;
} else if ("failed".equalsIgnoreCase(status)) {
System.out.println("----- task failed -----");
if (getResponse.getError() != null) {
System.out.println("Error: " + getResponse.getError().getMessage());
}
break;
} else {
System.out.printf("Current status: %s, Retrying in 10 seconds...%n", status);
TimeUnit.SECONDS.sleep(10);
}
}
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
System.err.println("Polling interrupted");
} catch (Exception e) {
System.err.println("Error occurred: " + e.getMessage());
} finally {
service.shutdownExecutor();
}
}
}
```
**选项:Go**
```Go
package main
import (
"context"
"fmt"
"os"
"time"
"github.com/volcengine/ark-runtime-go/arkruntime"
model "github.com/volcengine/ark-runtime-go/arkruntime/model/contentgeneration"
)
func main() {
// Initialize Ark client
client := arkruntime.NewClientWithApiKey(
os.Getenv("ARK_API_KEY"),
// The base URL for model invocation
arkruntime.WithBaseUrl("https://ark.cn-beijing.volces.com/api/v3"),
)
ctx := context.Background()
// Model ID
modelID := "doubao-seedance-2-0-260128"
// Text prompt
prompt := "固定机位,近景镜头,清新自然风格。在室内自然光下,图片1中美妆博主面带笑容,向镜头介绍图片2中的面霜。博主将手里的面霜展示给镜头,开心地说“挖到本命面霜了!”;接着她一边用手指轻轻蘸取面霜展示那种软糯感,一边说“质地像云朵一样软糯,一抹就吸收”;最后她把面霜涂抹在脸颊上,展示着水润透亮的皮肤,同时自信地说“熬夜急救、补水保湿全搞定”。要求画面中人物居中,完整展示人物的整个脑袋和上半身,始终对焦人脸,人脸始终清晰,纯净无任何字幕。"
// Example resource URLs
refImage1 := "asset://asset-20260401123823-6d4x2"
refImage2 := "https://arkdocs.tos-cn-beijing.volces.com/images/video-generation/r2v_edit_pic1.jpg"
// Output video parameters
generateAudio := true
videoRatio := "adaptive"
videoDuration := int64(11)
showWatermark := true
// 1. Create video generation task
fmt.Println("----- create request -----")
createReq := &model.CreateContentGenerationTaskRequest{
Model: modelID,
GenerateAudio: model.NewOptBool(generateAudio),
Ratio: model.NewOptString(videoRatio),
Duration: model.NewOptInt64(videoDuration),
Watermark: model.NewOptBool(showWatermark),
Content: []model.ContentItem{
{
Type: model.ContentTypeText,
Text: model.NewOptString(prompt),
},
{
Type: model.ContentTypeImageURL,
ImageURL: model.NewOptImageURL(model.ImageURL{
URL: refImage1,
}),
Role: model.NewOptString("reference_image"),
},
{
Type: model.ContentTypeImageURL,
ImageURL: model.NewOptImageURL(model.ImageURL{
URL: refImage2,
}),
Role: model.NewOptString("reference_image"),
},
},
}
createResp, err := client.CreateContentGenerationTask(ctx, createReq)
if err != nil {
fmt.Printf("create content generation error: %v\n", err)
return
}
taskID := createResp.ID
fmt.Printf("Task Created with ID: %s\n", taskID)
// 2. Poll task status
pollTaskStatus(ctx, client, taskID)
}
// poll task status
func pollTaskStatus(ctx context.Context, client *arkruntime.Client, taskID string) {
fmt.Println("----- polling task status -----")
for {
getReq := taskID
getResp, err := client.GetContentGenerationTask(ctx, getReq)
if err != nil {
fmt.Printf("get content generation task error: %v\n", err)
return
}
status := getResp.Status
if status == "succeeded" {
fmt.Println("----- task succeeded -----")
fmt.Printf("Task ID: %s \n", getResp.ID)
fmt.Printf("Model: %s \n", getResp.Model)
fmt.Printf("Video URL: %s \n", getResp.Content.Or(model.TaskContent{}).VideoURL.Or(""))
fmt.Printf("Completion Tokens: %d \n", getResp.Usage.Or(model.TaskUsage{}).CompletionTokens)
fmt.Printf("Created At: %d, Updated At: %d\n", getResp.CreatedAt.Or(0), getResp.UpdatedAt.Or(0))
return
} else if status == "failed" {
fmt.Println("----- task failed -----")
if getResp.Error.IsSet() {
fmt.Printf("Error Code: %s, Message: %s\n", getResp.Error.Value.Code, getResp.Error.Value.Message)
}
return
} else {
fmt.Printf("Current status: %s, Retrying in 10 seconds... \n", status)
time.Sleep(10 * time.Second)
}
}
}
```
# 使用已授权真人素材
通过真人认证和本人授权后,可将该真人的相关素材(例如该真人的图片、视频、音频)上传至方舟。素材入库成功后,每个素材将获得一个独立素材 ID (asset ID), 在 **content.<模态>_url.url** 字段中传入 `asset:// `即可使用该素材生成视频。真人认证及素材入库流程请参见[录入真人形象素材](/docs/upload-real-person-portrait-assets)。
```text
...
"content": [
{
"type": "text",
"text": ""
},
{
"type": "image_url",
"image_url": {
"url": "asset://"
},
"role": "reference_image"
},
{
"type": "video_url",
"video_url": {
"url": "asset://"
},
"role": "reference_video"
},
{
"type": "audio_url",
"audio_url": {
"url": "asset://"
},
"role": "reference_audio"
}
]
...
```
---
# 获取真人 IP 版权视频授权书 API 教程
Source: https://ark.volcengine.com/region:cn-beijing/docs/right-auth-letter-application-guide
本教程面向需要在自有平台接入授权书能力的方舟客户。终端用户在您的平台中使用已领用的真人 IP 生成版权视频后,可以打开免登申请链接,填写资料并提交授权书申请。您通过服务端查询申请结果,并在申请成功后下载授权书。
> **注意**
>
> 本功能仅用于视频生成后获取授权书,不用于在视频生成前取得真人 IP 的使用授权。使用真人 IP 生成视频前,您仍需调用 `ClaimCommercialIPs` 领用对应 IP。详情请参见 [使用视频生成 API 创作真人 IP 视频](/docs/real-person-ip-video-api)。
## 调用流程
按以下流程调用接口:
1. 调用 [`ListAuthorizedCommercialIPIds`](/docs/list-authorized-commercial-ip-ids-api),查询当前账号已领用且支持授权书申请的真人 IP。
2. 调用 [`CreateRightAuthLetterApplicationSession`](/docs/create-right-auth-letter-application-session-api),为终端用户创建授权书免登申请链接。
3. 通过结果回调接收通知(可选),调用 [`GetRightAuthLetterApplicationSession`](/docs/get-right-auth-letter-application-session-api) 查询申请结果。
4. 查询成功后,使用 `File.URL` 下载授权书文件。
具体流程如下图所示:

## 前提条件
- 已开通真人 IP 服务,并已调用 `ClaimCommercialIPs` 领用目标真人 IP。
- 终端用户已在您的平台中使用该真人 IP 生成版权视频。
- 已获取具有相关 API 调用权限的火山引擎账号 AK/SK。详情请参见 [Base URL 及鉴权](/docs/base-url-and-authentication)。
## 步骤 1、查询支持申请的真人 IP
调用 [`ListAuthorizedCommercialIPIds`](/docs/list-authorized-commercial-ip-ids-api),将 `IPCategory` 设置为 `REAL_PERSON`,查询当前账号已领用且授权有效的真人 IP。
```json
{
"IPCategory": "REAL_PERSON",
"ProjectName": "default"
}
```
响应中的 `Items[]` 直接返回真人 IP 信息:
```json
{
"Result": {
"Items": [
{
"IpId": "ip-c-example-a",
"IPCategory": "REAL_PERSON",
"IPName": "示例演员甲",
"SupportsAuthLetterApplication": true
},
{
"IpId": "ip-c-example-b",
"IPCategory": "REAL_PERSON",
"IPName": "示例演员乙",
"SupportsAuthLetterApplication": false
}
]
}
}
```
| `SupportsAuthLetterApplication` | 您的处理方式 |
| --- | --- |
| `true` | 该 IP 支持申请授权书,可以向终端用户展示申请入口。 |
| `false` | 该 IP 暂不支持申请授权书,不展示申请入口。 |
| 未返回 | 尚不能确认该 IP 是否支持申请授权书,不展示申请入口。 |
终端用户选择 IP 后,将同一条记录的 `IpId` 传给创建接口的 `IpId`。
> **说明:支持申请不等于获得使用授权**
>
> `SupportsAuthLetterApplication` 不能替代当前账号的 IP 领用资格检查,也不保证提交申请一定成功。创建申请时,火山方舟仍会校验 IP 上下架状态、当前账号领用状态和申请资料。
**完成本步骤后,需确认**:目标记录的 `IPCategory` 为 `REAL_PERSON`,`IpId` 与终端用户生成视频时使用的 IP ID 一致,并且 `SupportsAuthLetterApplication` 明确为 `true`。
## 步骤 2、创建免登申请会话
调用 [`CreateRightAuthLetterApplicationSession`](/docs/create-right-auth-letter-application-session-api),为一个真人 IP 和一个被授权方创建申请。
| 请求字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `IpId` | string | 是 | 本次申请对应的单个 IP ID。值不能为空或包含首尾空白,UTF-8 编码后最多 64 字节。 |
| `AuthorizedSubject` | object | 是 | 被授权方主体信息。当前仅需填写 `SubjectName`。 |
| `AuthorizedSubject.SubjectName` | string | 是 | 授权书中的真实被授权方主体名称。值不能为空或仅包含空白,不从签名账号的实名资料自动取值。 |
| `ProjectName` | string | 否 | 资源所属项目,默认值为 `default`。传入时不能为空,UTF-8 编码后最多 255 字节。该字段不是终端用户填写的作品或商业项目标题。 |
| `Callback` | object | 否 | 申请结果回调配置。启用时必须同时提供 `Callback.URL` 和 `Callback.Secret`。 具体使用方式,请参考下文**配置结果回调**。 |
请求示例:
```json
{
"IpId": "ip-c-example",
"AuthorizedSubject": {
"SubjectName": "示例文化传媒有限公司"
},
"ProjectName": "default"
}
```
响应示例:
```
{
"ResponseMetadata": {
"RequestId": "example-request-id"
},
"Result": {
"SessionId": "example-session-id",
"ApplicationURL": "https:///?token=",
"FirstAccessExpireAt": 1800000600,
"SessionExpireAt": 1800086400
}
}
```
创建成功后,保存以下返回值:
| 返回字段 | 类型 | 说明 |
| --- | --- | --- |
| `SessionId` | string | 申请会话 ID。用于查询申请状态和识别回调通知,不要自行生成或修改。 |
| `ApplicationURL` | string | 提供给指定终端用户的完整免登申请链接。该字段仅在创建成功时返回,查询接口不会补发。 |
| `FirstAccessExpireAt` | int64 | 终端用户首次成功进入申请页面的截止时间,UTC Unix 时间戳,单位为秒。 |
| `SessionExpireAt` | int64 | 免登申请入口的总访问截止时间,UTC Unix 时间戳,单位为秒。该时间从会话创建时开始计算,不会在终端用户首次打开链接后重新计时。 |
> **说明:按接口返回值处理访问时限**
>
> - 当前默认首次访问时限为创建后 10 分钟,默认总访问时限为创建后 24 小时。服务端配置可能调整,请以接口返回的时间和平台实际校验结果为准,不要在您的平台中固定时限。
> - 终端用户打开链接时,火山方舟会校验链接是否仍然有效。
> - 您的服务端查询申请状态不计为终端用户进入申请页面。
> **注意:保存链接并避免重复创建**
>
> - `ApplicationURL` 包含访问凭证,仅在创建成功时返回。查询接口无法找回该链接。请妥善保存,不要公开或写入普通日志。
> - 每次调用创建接口都会生成新的申请记录和链接。创建请求超时或返回 `InternalError` 时,不要自动连续重试。确需重新创建时,只向终端用户提供新的链接。
**完成本步骤后,需确认**:响应包含非空的 `SessionId` 和 `ApplicationURL`,两个截止时间均晚于创建时间。不要由您的服务端打开 `ApplicationURL` 进行验证,该链接应由指定终端用户打开。
## 步骤 3、提供申请链接
将 `ApplicationURL` 原样提供给指定终端用户,不要自行拼接或修改。根据 `FirstAccessExpireAt` 和 `SessionExpireAt` 提醒终端用户及时办理。
终端用户打开链接后,在免登页面填写授权书申请资料并提交,无需登录火山方舟账号。
## 步骤 4、查询申请结果
使用创建申请时的同一个方舟账号调用 [`GetRightAuthLetterApplicationSession`](/docs/get-right-auth-letter-application-session-api),传入已保存的 `SessionId`。
`SessionId` 为必填字符串,不得包含首尾空白,UTF-8 编码后最多 64 字节。
```json
{
"SessionId": "example-session-id"
}
```
申请成功且授权书未作废时,查询接口返回文件信息:
```json
{
"ResponseMetadata": {
"RequestId": "example-request-id"
},
"Result": {
"Session": {
"SessionId": "example-session-id",
"Status": "SUCCEEDED",
"File": {
"FileName": "授权书.pdf",
"URL": "https:///"
}
}
}
}
```
当 `Session.Status` 为 `CREATED` 或 `PROCESSING` 时,建议每隔 5~10 秒查询一次,并为单轮等待设置上限。查询暂时出错或本轮等待超时不代表申请失败。保存 `SessionId`,稍后继续查询同一个 Session,不要因此重复创建申请。
## 查询接口状态和错误码
以下申请状态和错误码均由 `GetRightAuthLetterApplicationSession` 查询接口返回。
| `Session.Status` | 含义 | 您的处理方式 |
| --- | --- | --- |
| `CREATED` | 申请入口已创建,终端用户尚未完成提交。 | 引导终端用户打开已保存的申请链接,并继续查询。 |
| `PROCESSING` | 终端用户已提交资料,火山方舟正在处理申请或生成授权书。 | 继续查询,不要为同一申请重复创建入口。 |
| `SUCCEEDED` | 授权书已生成成功且未作废。 | 使用 `File.URL` 下载授权书。 |
| `FAILED` | 授权书申请处理失败。 | 停止本轮等待。业务确认仍需申请后,创建新的 Session。 |
| `EXPIRED` | 终端用户未提交资料,申请入口已超过首次进入期限或总访问期限。 | 旧入口不能继续使用。仍需申请时,创建新的 Session。 |
| `VOIDED` | 已生成的授权书被作废。 | 不再展示或下载该文件。 |
> **说明:申请入口过期不等于授权书失效**
>
> 终端用户已经提交的申请仍可继续处理。状态为 `SUCCEEDED` 的授权书在被作废前仍可获取文件。
| HTTP 状态码 | 查询接口错误码 | 说明 | 处理建议 |
| --- | --- | --- | --- |
| 400 | `MissingParameter.SessionId` | 未传入申请会话 ID。 | 补充 `SessionId` 后重新查询。 |
| 400 | `InvalidParameter.*` | `SessionId` 不合法。 | 确认 `SessionId` 非空、UTF-8 编码后不超过 64 字节且不含首尾空白。 |
| 404 | `ResourceNotFound.RightAuthLetterApplicationSession` | 当前账号下找不到指定 Session。 | 检查调用账号和 `SessionId`。已清理的记录无法查询。 |
| 500 | `InternalError` | 服务内部异常。 | 稍后重试查询。多次重试仍失败时,记录 `ResponseMetadata.RequestId` 并联系技术支持。 |
> **注意**
>
> 失败或过期的申请记录从 Session 创建起保留 15 天,之后可能无法查询。及时保存所需的业务结果。
## 步骤 5、配置结果回调
如需火山方舟主动通知申请结果,在创建会话时同时传入 `Callback.URL` 和 `Callback.Secret`。未配置回调时,主动查询申请结果。
```json
{
"Callback": {
"URL": "https://callback.example.com/auth-letter",
"Secret": "<43_CHARACTER_BASE64URL_SECRET>"
}
}
```
- `Callback.URL`:您的公网 HTTPS 回调地址,最多 2048 个字符。地址应使用默认端口或 `443`,不得包含用户名、密码或 URL 片段,也不应发生重定向。
- `Callback.Secret`:您生成并保存在服务端的共享密钥。先生成 32 字节安全随机数,再编码为不带末尾等号的 43 字符 Base64URL 字符串。不要记录日志或返回给终端用户。
可以使用以下命令生成 `Callback.Secret`:
```bash
python -c 'import secrets; print(secrets.token_urlsafe(32))'
```
火山方舟通过 HTTP POST 发送通知。通知不包含授权书文件,收到通知后仍需调用查询接口获取最新状态和下载地址。
```json
{
"SessionId": "example-session-id",
"Status": "SUCCEEDED",
"ApplicationId": "example-application-id"
}
```
- 通知体总是返回 `SessionId` 和 `Status`,可能返回 `ApplicationId`。`Status` 仅可能为 `SUCCEEDED` 或 `FAILED`。
- 终端用户未提交且申请入口过期时,通知可能不包含 `ApplicationId`。此时,通知状态可能为 `FAILED`,查询状态为 `EXPIRED`。
- 处理中和授权书作废时不发送通知。回调可能重复或未送达,不要只等待回调,最终状态以查询接口为准。
验签时,读取请求头 `X-Ark-Auth-Letter-Timestamp` 和 `X-Ark-Auth-Letter-Signature`。签名格式为 `v1=`,其中 `` 是 64 位小写十六进制 HMAC-SHA256 签名。将 `Callback.Secret` 解码为 32 字节密钥,并对 `.<原始 HTTP 请求体字节>` 计算签名。不要解析 JSON 后重新序列化请求体再验签。
建议结合服务端时钟校验时间窗口,防止重放。验签成功后,按 `SessionId` 和 `Status` 幂等保存通知,并尽快返回 HTTP 2xx,建议在 3 秒内完成。火山方舟对部分发送失败最多发送 4 次。
**完成本步骤后,需确认**:使用测试通知确认您的服务端会拒绝错误签名和超出时间窗口的通知,并能幂等处理重复通知。验签成功后,使用 `SessionId` 查询最新结果。
## 步骤 6、下载授权书
查询接口返回 `SUCCEEDED` 时,`Session.File` 包含:
- `FileName`:授权书文件名。
- `URL`:授权书的短期 HTTPS 签名下载地址。
使用 `File.URL` 下载文件时,无需携带 OpenAPI AK/SK。下载地址可以直接访问授权书,不得公开或写入普通日志。链接失效后,重新查询同一个 `SessionId` 获取新地址,无需重新申请。
保存文件时,由您的程序指定本地路径,不要直接使用远端 `FileName` 作为路径。向终端用户提供文件前,校验终端用户是否有权访问对应业务记录。
**完成本步骤后,需确认**:下载的文件非空且可以正常打开。重新查询时,`Session.Status` 仍为 `SUCCEEDED`。
## 示例代码
以下 Python 示例使用研发提供的火山引擎 Python SDK 完成 AK/SK 签名,并按接入环节分段展示。
### 安装依赖并配置环境变量
使用 Python 3.10 或更高版本,安装依赖:
```bash
python -m pip install --upgrade volcengine requests
```
通过您的密钥管理系统配置环境变量:
```bash
export VOLC_ACCESSKEY=""
export VOLC_SECRETKEY=""
```
使用临时访问凭证时,配置 `VOLC_SESSION_TOKEN`。如需覆盖默认地域 `cn-beijing`,配置 `VOLC_REGION`。
### 定义 API 调用函数
以下代码定义 IP 筛选、创建申请、查询状态和下载文件所需的函数。
```Python
import json
import math
import os
import time
from pathlib import Path
from urllib.parse import urlsplit
import requests
from volcengine.Credentials import Credentials
from volcengine.auth.SignerV4 import SignerV4
from volcengine.base.Request import Request
HOST = "open.volcengineapi.com"
VERSION = "2024-01-01"
def call_api(action, payload):
region = os.getenv("VOLC_REGION", "cn-beijing")
credentials = Credentials(
os.environ["VOLC_ACCESSKEY"],
os.environ["VOLC_SECRETKEY"],
"ark",
region,
os.getenv("VOLC_SESSION_TOKEN", ""),
)
request = Request()
request.schema = "https"
request.host = HOST
request.path = "/"
request.method = "POST"
request.query = {"Action": action, "Version": VERSION}
request.headers = {"Host": HOST, "Content-Type": "application/json"}
request.body = json.dumps(payload, ensure_ascii=False, separators=(",", ":"))
SignerV4.sign(request, credentials)
try:
# Send the same UTF-8 body that was signed without serializing it again.
response = requests.post(
request.build(),
headers=request.headers,
data=request.body.encode("utf-8"),
timeout=(5, 30),
allow_redirects=False,
)
except requests.RequestException:
message = f"{action} network error"
if action == "CreateRightAuthLetterApplicationSession":
message += "; do not automatically retry this request"
raise RuntimeError(message) from None
try:
data = response.json()
except ValueError:
raise RuntimeError(
f"API returned non-JSON content: HTTP {response.status_code}"
) from None
metadata = data.get("ResponseMetadata", {})
error = metadata.get("Error")
if not 200 <= response.status_code < 300 or error:
code = (error or {}).get("Code", "UnknownError")
request_id = metadata.get("RequestId", "")
raise RuntimeError(f"API error {code}; RequestId={request_id}")
result = data.get("Result")
if not isinstance(result, dict):
raise RuntimeError(f"{action} response does not contain Result")
return result
def list_applicable_ips(project_name="default"):
result = call_api(
"ListAuthorizedCommercialIPIds",
{
"IPCategory": "REAL_PERSON",
"ProjectName": project_name,
},
)
items = result.get("Items")
if not isinstance(items, list):
raise RuntimeError(
"ListAuthorizedCommercialIPIds response does not contain Items"
)
return [item for item in items if item.get("SupportsAuthLetterApplication") is True]
def create_entry(ip_id, subject_name, callback=None):
payload = {
"IpId": ip_id,
"AuthorizedSubject": {"SubjectName": subject_name},
"ProjectName": "default",
}
if callback is not None:
payload["Callback"] = callback
return call_api("CreateRightAuthLetterApplicationSession", payload)
def get_session(session_id):
return call_api(
"GetRightAuthLetterApplicationSession",
{"SessionId": session_id},
)["Session"]
def wait_for_file(session_id, wait_seconds=120, interval_seconds=5):
# Reaching the polling deadline does not mean the application failed.
if wait_seconds < 0:
raise ValueError("wait_seconds must be non-negative")
if interval_seconds <= 0:
raise ValueError("interval_seconds must be positive")
deadline = time.monotonic() + wait_seconds
max_attempts = max(1, math.ceil(wait_seconds / interval_seconds) + 1)
for _ in range(max_attempts):
session = get_session(session_id)
status = session["Status"]
if status == "SUCCEEDED":
file_info = session.get("File")
if not file_info or not file_info.get("URL"):
raise RuntimeError("Successful response does not contain a file URL")
return file_info
if status in {"FAILED", "EXPIRED", "VOIDED"}:
raise RuntimeError(f"Application status: {status}")
if status not in {"CREATED", "PROCESSING"}:
raise RuntimeError("Unknown status; keep the SessionId and contact support")
remaining = deadline - time.monotonic()
if remaining <= 0:
return None
time.sleep(min(interval_seconds, remaining))
return None
def download_file(file_info, output_path):
# Choose the local path in your application; do not trust a remote filename.
url = file_info["URL"]
parsed_url = urlsplit(url)
if parsed_url.scheme != "https" or not parsed_url.hostname:
raise RuntimeError("File URL is not a valid HTTPS URL")
try:
# Do not attach OpenAPI credentials or follow redirects.
with requests.get(
url,
timeout=(5, 60),
allow_redirects=False,
) as response:
if response.status_code != 200:
raise RuntimeError(
f"File download returned HTTP {response.status_code}; "
"query the session again for a new URL"
)
if not response.content:
raise RuntimeError("Downloaded file is empty")
with Path(output_path).open("xb") as output:
output.write(response.content)
except requests.RequestException:
# Do not expose an exception that may contain the signed URL.
raise RuntimeError(
"Download network error; query the session again before retrying"
) from None
if __name__ == "__main__":
eligible_ips = list_applicable_ips()
safe_items = [
{"IpId": item.get("IpId"), "IPName": item.get("IPName")}
for item in eligible_ips
]
print(json.dumps({"Items": safe_items}, ensure_ascii=False, indent=2))
```
### 选择 IP 并创建链接
调用 `list_applicable_ips` 获取支持授权书申请的真人 IP。终端用户选择 IP 后,调用 `create_entry` 创建申请。
```python
import secrets
ips = list_applicable_ips()
# Present ips to the terminal user and obtain the selected IP ID.
callback = None
# To enable callbacks, replace CALLBACK_URL and securely store the secret:
# callback = {
# "URL": "",
# "Secret": secrets.token_urlsafe(32),
# }
created = create_entry(
"",
"",
callback=callback,
)
session_id = created["SessionId"]
application_url = created["ApplicationURL"]
```
保存 `SessionId`、`ApplicationURL` 和两个截止时间。将 `ApplicationURL` 安全地提供给指定终端用户,不要打印或写入普通日志。
### 查询并下载
终端用户提交申请后,或收到并验证回调后,使用已保存的 `SessionId` 查询。以下代码最多等待两分钟;返回 `None` 仅表示本轮未等到结果。
```python
file_info = wait_for_file("", wait_seconds=120)
if file_info is not None:
download_file(file_info, "authorization-letter.pdf")
```
稍后可以继续查询同一 Session,不要因为本轮等待超时而重新创建申请。
### 验证回调签名
将收到的原始请求体字节传给 `verify_callback`,不要重新序列化 JSON 后再验签。
```Python
import base64
import hashlib
import hmac
import re
import time
def verify_callback(raw_body, timestamp, signature, secret):
if not isinstance(raw_body, bytes):
return False
if not re.fullmatch(r"[A-Za-z0-9_-]{43}", secret):
return False
if not re.fullmatch(r"[0-9]{1,12}", timestamp):
return False
if abs(time.time() - int(timestamp)) > 300:
return False
if not re.fullmatch(r"v1=[0-9a-f]{64}", signature):
return False
key = base64.urlsafe_b64decode(secret + "=")
if len(key) != 32:
return False
message = timestamp.encode("ascii") + b"." + raw_body
expected = "v1=" + hmac.new(key, message, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, signature)
```
> **注意**
>
> 运行创建申请的代码会写入真实申请记录。正式接入前,使用具备接口权限的账号完成端到端验证。创建请求超时后不要自动重试。
## 接入注意事项
- 申请链接只提供给指定终端用户。申请链接和下载链接均可直接访问相应内容,不要公开或写入普通日志。
- AK/SK 和 `Callback.Secret` 仅保存在您的服务端,不要发送给浏览器或终端用户。
- `ApplicationURL` 用于填写申请,`File.URL` 用于下载授权书,不要混用。
- 保存您的订单或业务编号与 `SessionId` 的对应关系。向终端用户提供下载文件前,确认终端用户有权查看该业务记录。
> **说明:正式接入前验证完整流程**
>
> 确认账号权限和页面入口已开通,并验证选择 IP、创建链接、终端用户填写提交、接收通知、查询结果和下载文件的完整流程。同时验证申请过期、处理失败和授权书作废时的业务提示。
## 常见问题
### 已领用真人 IP 但不能申请授权书
已领用且授权有效仅表示当前账号可以使用该真人 IP。只有 `SupportsAuthLetterApplication` 明确为 `true` 时,该 IP 才支持申请授权书。
### 失败回调对应的查询状态是 `EXPIRED`
终端用户未提交且申请入口过期时,回调状态可能为 `FAILED`,查询状态为 `EXPIRED`。回调用于触发处理,最终状态以查询接口为准。
### 创建接口超时后能否直接重试
不能。超时不表示服务端一定未创建 Session,直接重试可能产生多个申请记录和链接。根据业务记录和服务端日志确认结果;确需重新创建时,只向终端用户提供新链接。
## 相关文档
- [使用视频生成 API 创作真人 IP 视频](/docs/real-person-ip-video-api)
- [查询已授权商业 IP 列表](/docs/list-authorized-commercial-ip-ids-api)
- [创建授权书免登申请会话](/docs/create-right-auth-letter-application-session-api)
- [查询授权书免登申请会话](/docs/get-right-auth-letter-application-session-api)
---
# Doubao Seedream 5.0 pro / flash 教程
Source: https://ark.volcengine.com/region:cn-beijing/docs/seedream-5-0-pro
Doubao Seedream 5.0 pro(以下简称 Seedream 5.0 pro)与 Doubao Seedream 5.0 flash(以下简称 Seedream 5.0 flash)支持文生图、单张图生图、多参考图生图等基础生图能力,同时支持通过交互编辑实现精准坐标定位和任意标记编辑、将单张图片拆分为底图与多个图层等特色能力。本文重点介绍两款模型的专属能力,帮助您快速实现 [Image generation API](/docs/image-generation-api) 调用。
# 特色能力
Seedream 5.0 pro 与 Seedream 5.0 flash 支持的特色功能如下:
|特色能力 |能力介绍 |效果预览 |
|---|---|---|
|[交互编辑](/docs/seedream-5-0-pro#interactive_edit) |支持通过坐标、框选、箭头等多种方式指定编辑位置,精准编辑图片,实现局部元素替换、物品定位、区域生成等精细化操作。 |[视频](https://arkdocs.tos-cn-beijing.volces.com/videos/image-generation/edite-model.mov) |
|[图层拆分](/docs/seedream-5-0-pro#layer_decomposition) |支持将单张图片的主体、背景、文字、装饰元素等内容自动拆解为 1 张底图和最多 16 个独立且带透明通道的图层,便于移动、缩放、替换、调色等二次编辑。 | |
|原生多语种生成 |新增支持俄语、阿拉伯语、菲律宾语、泰语、土耳其语、韩语、马来语、西班牙语、葡萄牙语、印尼语、法语、德语、越南语、日语等 14 种语言的原生文字生成能力。 | |
# 能力概述
Seedream 5.0 pro 与 Seedream 5.0 flash 均支持通过坐标、框选、箭头等多种方式指定编辑位置来精准编辑图片;支持将单张图片拆分为 1 张底图和最多 16 个独立图层;支持原生多语种生成等特色能力。两款模型的定位区别如下:
* **Seedream 5.0 pro**:**生图质量更高**,适合对画质要求更高的场景。
* **Seedream 5.0 flash**:**生图速度更快、价格更低**,适合对时延与成本敏感的场景。
|模型名称 ||[Seedream 5.0 pro](https://ark.volcengine.com/region:cn-beijing/model/detail?Id=doubao-seedream-5-0-pro) |[Seedream 5.0 flash](https://ark.volcengine.com/region:cn-beijing/model/detail?Id=doubao-seedream-5-0-flash) |
|---|---|---|---|
|模型 ID (Model ID) ||doubao-seedream-5-0-pro-260628 |doubao-seedream-5-0-flash-260915 |
|[文生图](/docs/seedream-4-0-5-0#9695d195) ||✓ |✓ |
|[单 / 多图生图](/docs/seedream-4-0-5-0#8bc49063) ||✓ |✓ |
|[交互编辑](/docs/seedream-5-0-pro#interactive_edit) ||✓ |✓ |
|[图层拆分](/docs/seedream-5-0-pro#layer_decomposition) ||✓ |✓ |
|原生多语种生成 ||✓ |✓ |
|模型参数 |分辨率 |1K, 1.5K, 2K |1K, 1.5K, 2K |
|^^| | | | \
| |输出格式 |png, jpeg |png, jpeg |
|^^| | | | \
| |提示词优化模式 |标准模式, 极速模式 |标准模式 |
|^^| | | | \
| |生成数量限制 |支持生成单图/
多张图层( 1张底图+16张图层) |支持生成单图/
多张图层( 1张底图+16张图层) |
|限流 IPM(张 / 分钟) ||500 |500 |
# 基础使用
Seedream 5.0 pro / flash 的基础使用方式(文生图、图文生图、多图融合)与其他 Seedream 模型一致,只需将 `model` 参数替换为对应的 Model ID:
* Seedream 5.0 pro:`doubao-seedream-5-0-pro-260628`
* Seedream 5.0 flash:`doubao-seedream-5-0-flash-260915`
详细代码示例和说明请参考:
* [文生图](/docs/seedream-4-0-5-0#9695d195)
* [图文生图](/docs/seedream-4-0-5-0#8bc49063)
* [多图融合](/docs/seedream-4-0-5-0#4a35e28f)
# 交互编辑
Seedream 5.0 pro 与 Seedream 5.0 flash 支持通过**框选、点位、箭头、标注框、坐标**等方式指定编辑位置,实现对局部区域的精准生成或修改。详细操作说明请参考 [Seedream 5.0 pro / flash 交互编辑指南](/docs/seedream-5-0-pro-editing-guide)。
> **说明**
>
> Java 示例中的 `CreateImageGenerationRequestImage` 需要 `com.volcengine:ark-runtime` 0.6.0 或更高版本。如果 IDE 提示找不到该类型或 `image` 参数类型不匹配,请升级到 [Maven Central](https://central.sonatype.com/artifact/com.volcengine/ark-runtime) 提供的最新稳定版本,并重新加载项目依赖。
## 使用示例-任意标记
在参考图上通过手绘草图、涂鸦、圈选等任意标记指定编辑区域,模型将识别标记范围并在其中生成或替换内容,同时自然融入原有场景。
|提示词 |输入图 |输出 |
|---|---|---|
|根据手绘草图对图像进行编辑。在左下角标记区域添加一叠真实的杂志或艺术画册,并在右侧标记区域添加一个带杯碟的陶瓷杯咖啡。移除所有草图线条。保持构图不变。让新添加的物体自然融入原有场景中。 | | |
**选项:Curl**
```Bash
curl https://ark.cn-beijing.volces.com/api/v3/images/generations \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ARK_API_KEY" \
-d '{
"model": "doubao-seedream-5-0-pro-260628",
"prompt": "根据手绘草图对图像进行编辑。在左下角标记区域添加一叠真实的杂志或艺术画册,并在右侧标记区域添加一个带杯碟的陶瓷杯咖啡。移除所有草图线条。保持构图不变。让新添加的物体自然融入原有场景中。",
"image": "https://arkdocs.tos-cn-beijing.volces.com/images/image-generation/seedream_50_pro_input2.png",
"size": "2K",
"output_format": "png",
"watermark": true
}'
```
* 您可按需替换 Model ID。Model ID 查询见 [模型列表](/docs/model-list)。
**选项:Python**
```Python
import os
# Install SDK: python -m pip install --upgrade arkruntime
from arkruntime import Ark
client = Ark(
# The base URL for model invocation
base_url="https://ark.cn-beijing.volces.com/api/v3",
# Get API Key: https://ark.volcengine.com/region:cn-beijing/apikey
api_key=os.getenv("ARK_API_KEY"),
)
imagesResponse = client.images.generate(
# Replace with Model ID
model="doubao-seedream-5-0-pro-260628",
prompt="根据手绘草图对图像进行编辑。在左下角标记区域添加一叠真实的杂志或艺术画册,并在右侧标记区域添加一个带杯碟的陶瓷杯咖啡。移除所有草图线条。保持构图不变。让新添加的物体自然融入原有场景中。",
image="https://arkdocs.tos-cn-beijing.volces.com/images/image-generation/seedream_50_pro_input2.png",
size="2K",
output_format="png",
response_format="url",
watermark=True,
)
print(imagesResponse.data[0].url)
```
**选项:Java**
```Java
package com.ark.sample;
import com.volcengine.ark.runtime.models.images.*;
import com.volcengine.ark.runtime.service.ArkService;
import okhttp3.ConnectionPool;
import okhttp3.Dispatcher;
import java.util.concurrent.TimeUnit;
public class ImageGenerationsExample {
public static void main(String[] args) {
String apiKey = System.getenv("ARK_API_KEY");
ConnectionPool connectionPool = new ConnectionPool(5, 1, TimeUnit.SECONDS);
Dispatcher dispatcher = new Dispatcher();
ArkService service = ArkService.builder()
.baseUrl("https://ark.cn-beijing.volces.com/api/v3")
// The base URL for model invocation
.dispatcher(dispatcher)
.connectionPool(connectionPool)
.apiKey(apiKey)
.build();
// CreateImageGenerationRequestImage requires ark-runtime 0.6.0 or later.
CreateImageGenerationRequest generateRequest = CreateImageGenerationRequest.builder()
.model("doubao-seedream-5-0-pro-260628") // Replace with Model ID
.prompt("根据手绘草图对图像进行编辑。在左下角标记区域添加一叠真实的杂志或艺术画册,并在右侧标记区域添加一个带杯碟的陶瓷杯咖啡。移除所有草图线条。保持构图不变。让新添加的物体自然融入原有场景中。")
.image(CreateImageGenerationRequestImage.ofString("https://arkdocs.tos-cn-beijing.volces.com/images/image-generation/seedream_50_pro_input2.png"))
.size("2K")
.outputFormat(OutputFormat.PNG)
.responseFormat(ResponseFormat.URL)
.watermark(true)
.build();
ImageGenerationResponse imagesResponse = service.generateImages(generateRequest);
System.out.println(imagesResponse.getData().get(0).getUrl());
service.shutdownExecutor();
}
}
```
**选项:Go**
```Go
package main
import (
"context"
"fmt"
"os"
"github.com/volcengine/ark-runtime-go/arkruntime"
model "github.com/volcengine/ark-runtime-go/arkruntime/model/images"
)
func main() {
client := arkruntime.NewClientWithApiKey(
os.Getenv("ARK_API_KEY"),
// The base URL for model invocation
arkruntime.WithBaseUrl("https://ark.cn-beijing.volces.com/api/v3"),
)
ctx := context.Background()
outputFormat := model.OutputFormatPNG
generateReq := &model.CreateImageGenerationRequest{
Model: "doubao-seedream-5-0-pro-260628",
Prompt: model.NewOptString("根据手绘草图对图像进行编辑。在左下角标记区域添加一叠真实的杂志或艺术画册,并在右侧标记区域添加一个带杯碟的陶瓷杯咖啡。移除所有草图线条。保持构图不变。让新添加的物体自然融入原有场景中。"),
Image: model.NewOptCreateImageGenerationRequestImage(model.NewStringArrayCreateImageGenerationRequestImage([]string{"https://arkdocs.tos-cn-beijing.volces.com/images/image-generation/seedream_50_pro_input2.png"})),
Size: model.NewOptString("2K"),
OutputFormat: model.NewOptOutputFormat(outputFormat),
ResponseFormat: model.NewOptResponseFormat(model.ResponseFormatURL),
Watermark: model.NewOptBool(true),
}
imagesResponse, err := client.GenerateImages(ctx, generateReq)
if err != nil {
fmt.Printf("generate images error: %v\n", err)
return
}
fmt.Printf("%s\n", imagesResponse.Data[0].URL.Or(""))
}
```
**选项:OpenAI**
```Python
import os
from openai import OpenAI
client = OpenAI(
# The base URL for model invocation
base_url="https://ark.cn-beijing.volces.com/api/v3",
# Get API Key: https://ark.volcengine.com/region:cn-beijing/apikey
api_key=os.getenv("ARK_API_KEY"),
)
imagesResponse = client.images.generate(
model="doubao-seedream-5-0-pro-260628",
prompt="根据手绘草图对图像进行编辑。在左下角标记区域添加一叠真实的杂志或艺术画册,并在右侧标记区域添加一个带杯碟的陶瓷杯咖啡。移除所有草图线条。保持构图不变。让新添加的物体自然融入原有场景中。",
size="2K",
output_format="png",
response_format="url",
extra_body={
"image": "https://arkdocs.tos-cn-beijing.volces.com/images/image-generation/seedream_50_pro_input2.png",
"watermark": True,
},
)
print(imagesResponse.data[0].url)
```
## 使用示例-坐标定位
通过在 prompt 中加入 `` 或 `` 坐标标签,精确指定跨图的编辑区域,实现主体元素的定位放置。完整调用步骤和参数说明请参考 [Seedream 5.0 pro / flash 交互编辑指南](/docs/seedream-5-0-pro-editing-guide)。
|提示词 |输入图 |输出 |
|---|---|---|
|将图 1 ` 179 283 796 986 `的主体放到图 2 ` 118 331 933 871` 位置。 | | |
## 使用说明
交互编辑需要准备以下输入要素:**待编辑图片** 和 **prompt**(包含定位信息 + 编辑指令)。根据定位方式不同,分为以下两种形式:
|形式 1:任意标记 + 自然语言定位 |形式 2:坐标精准定位 |
|---|---|
|在待编辑图片上通过手绘草图、涂鸦、圈选等方式标记编辑区域,然后在 prompt 中用自然语言描述标记位置和编辑意图。 |使用工具框定待编辑内容的坐标(坐标获取方式详见 [Seedream 5.0 pro / flash 交互编辑指南](/docs/seedream-5-0-pro-editing-guide)),在 prompt 中通过 `` 或 `` 坐标标签精确指定位置。 | \
|```JSON |```JSON | \
|{ |{ | \
|"prompt": "在蓝色框内添加一个电视机" |"prompt": "将图1179 283 796 986的主体放到图2118 331 933 871位置"| \
|} |} | \
|``` |``` |
准备好输入要素后,将 **待编辑图片** 和 **prompt** 一起传入 API 接口即可生成图片编辑结果。
# 图层拆分
Seedream 5.0 pro 与 Seedream 5.0 flash 均支持将单张输入图片中的主体、背景、文字、装饰元素等内容自动拆解为 1 张底图和最多 16 个可独立编辑的图层。每个图层均为带透明通道的 PNG 图片,模型还会返回图层的坐标、层级顺序和内容说明,便于在设计工具、前端画布中继续移动、缩放、替换、调色和重新组合。
## 使用链路
图层拆分功能的使用链路如下:

## 拆分单张图片
配置参数 `layer_decomposition` 为 `true` 即可开启图层拆分模式。开启后,`image` 为必选参数,且仅支持传入 1 张待拆分图片;`prompt` 为可选参数,用于描述要拆分哪些元素。
### 提示词输入方式
使用图层拆分功能,推荐采用以下三种输入方式:
|使用目标 |`prompt` 写法 |
|---|---|
|自动拆出主要元素 |不传入 `prompt`。模型自动识别图片中的主体、文字、背景、装饰元素等主要内容,并逐一拆分为独立图层。 |
|指定拆分对象 |在 `prompt` 中用自然语言描述待拆分的元素,例如“拆出人物、标题文字和右下角装饰图标”。可配合在输入图上标记(涂鸦、圈选等)辅助定位。 |
|精准指定区域 |在 `prompt` 中通过 `` 坐标标签指定待拆分元素的位置。坐标采用归一化坐标,获取方式详见 [Seedream 5.0 pro / flash 交互编辑指南](/docs/seedream-5-0-pro-editing-guide#key-steps)。 |
### 使用示例-自动全拆
如需让模型自动识别并拆分图片中的主要元素,可不传入 `prompt`,只传入待拆分图片并设置`layer_decomposition=true`。
|1 张输入图(不传 `prompt`) |输出底图 |输出图层 |||
|---|---|---|---|---|
| | | | | |
|^^ |^^ | | | |
|^^ |^^ | | | |
|^^ |^^ | | | |
**选项:Curl**
```Bash
curl https://ark.cn-beijing.volces.com/api/v3/images/generations \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ARK_API_KEY" \
-d '{
"model": "doubao-seedream-5-0-pro-260628",
"image": "https://arkdocs.tos-cn-beijing.volces.com/images/image-generation/layer_auto.png",
"size": "2K",
"layer_decomposition": true,
"watermark": true
}'
```
* 您可按需替换 Model ID。Model ID 查询见 [模型列表](/docs/model-list)。
**选项:Python**
```Python
import os
# Install SDK: python -m pip install --upgrade arkruntime
from arkruntime import Ark
client = Ark(
# The base URL for model invocation
base_url="https://ark.cn-beijing.volces.com/api/v3",
# Get API Key: https://ark.volcengine.com/region:cn-beijing/apikey
api_key=os.getenv("ARK_API_KEY"),
)
imagesResponse = client.images.generate(
# Replace with Model ID
model="doubao-seedream-5-0-pro-260628",
image="https://arkdocs.tos-cn-beijing.volces.com/images/image-generation/layer_auto.png",
size="2K",
layer_decomposition=True,
response_format="url",
watermark=True,
)
for item in imagesResponse.data:
print(item)
```
**选项:Java**
```Java
package com.ark.sample;
import com.volcengine.ark.runtime.models.images.*;
import com.volcengine.ark.runtime.service.ArkService;
import okhttp3.ConnectionPool;
import okhttp3.Dispatcher;
import java.util.concurrent.TimeUnit;
public class ImageGenerationsExample {
public static void main(String[] args) {
String apiKey = System.getenv("ARK_API_KEY");
ConnectionPool connectionPool = new ConnectionPool(5, 1, TimeUnit.SECONDS);
Dispatcher dispatcher = new Dispatcher();
ArkService service = ArkService.builder()
.baseUrl("https://ark.cn-beijing.volces.com/api/v3")
// The base URL for model invocation
.dispatcher(dispatcher)
.connectionPool(connectionPool)
.apiKey(apiKey)
.build();
// CreateImageGenerationRequestImage requires ark-runtime 0.6.0 or later.
CreateImageGenerationRequest generateRequest = CreateImageGenerationRequest.builder()
.model("doubao-seedream-5-0-pro-260628") // Replace with Model ID
.image(CreateImageGenerationRequestImage.ofString("https://arkdocs.tos-cn-beijing.volces.com/images/image-generation/layer_auto.png"))
.size("2K")
.layerDecomposition(true)
.responseFormat(ResponseFormat.URL)
.watermark(true)
.build();
ImageGenerationResponse imagesResponse = service.generateImages(generateRequest);
imagesResponse.getData().forEach(item -> System.out.println(item));
service.shutdownExecutor();
}
}
```
**选项:Go**
```Go
package main
import (
"context"
"fmt"
"os"
"github.com/volcengine/ark-runtime-go/arkruntime"
model "github.com/volcengine/ark-runtime-go/arkruntime/model/images"
)
func main() {
client := arkruntime.NewClientWithApiKey(
os.Getenv("ARK_API_KEY"),
// The base URL for model invocation
arkruntime.WithBaseUrl("https://ark.cn-beijing.volces.com/api/v3"),
)
ctx := context.Background()
generateReq := &model.CreateImageGenerationRequest{
Model: "doubao-seedream-5-0-pro-260628",
Image: model.NewOptCreateImageGenerationRequestImage(model.NewStringArrayCreateImageGenerationRequestImage([]string{"https://arkdocs.tos-cn-beijing.volces.com/images/image-generation/layer_auto.png"})),
Size: model.NewOptString("2K"),
LayerDecomposition: model.NewOptBool(true),
ResponseFormat: model.NewOptResponseFormat(model.ResponseFormatURL),
Watermark: model.NewOptBool(true),
}
imagesResponse, err := client.GenerateImages(ctx, generateReq)
if err != nil {
fmt.Printf("generate images error: %v\n", err)
return
}
for _, item := range imagesResponse.Data {
fmt.Printf("%+v\n", item)
}
}
```
**选项:OpenAI**
```Python
import os
from openai import OpenAI
client = OpenAI(
# The base URL for model invocation
base_url="https://ark.cn-beijing.volces.com/api/v3",
# Get API Key: https://ark.volcengine.com/region:cn-beijing/apikey
api_key=os.getenv("ARK_API_KEY"),
)
imagesResponse = client.images.generate(
model="doubao-seedream-5-0-pro-260628",
size="2K",
response_format="url",
extra_body={
"image": "https://arkdocs.tos-cn-beijing.volces.com/images/image-generation/layer_auto.png",
"layer_decomposition": True,
"watermark": True,
},
)
for item in imagesResponse.data:
print(item)
```
### 使用示例-精准指定拆分区域
如需精准指定拆分区域,推荐采用归一化的 `` 坐标指定需要拆分的元素。
|1 张输入图 + 提示词(归一化坐标指定拆分元素) |输出底图 |输出图层 ||
|---|---|---|---|
|
将图片中的内容拆成 7 个图层,包括 6 组文字:
`180 64 812 198`、`757 210 939 280`、`63 212 320 282`、`178 714 826 810`、`814 819 949 894`、`326 824 669 930`;
1 只鹦鹉:`347 305 642 997`。
| | | |
|^^ |^^ | |^^ |
|^^ |^^ | |^^ |
|^^ |^^ | |^^ |
|^^ |^^ | |^^ |
|^^ |^^ | |^^ |
**选项:Curl**
```Bash
curl https://ark.cn-beijing.volces.com/api/v3/images/generations \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ARK_API_KEY" \
-d '{
"model": "doubao-seedream-5-0-pro-260628",
"prompt": "将图片进行精确图层分离,需分离的文字坐标为180 64 812 198、757 210 939 280、63 212 320 282、178 714 826 810、814 819 949 894、326 824 669 930;鹦鹉的坐标为347 305 642 997。",
"image": "https://arkdocs.tos-cn-beijing.volces.com/images/image-generation/seedream_50_pro_layer_input.png",
"layer_decomposition": true,
"size": "2K",
"output_format": "jpeg",
"response_format": "url",
"watermark": true
}'
```
* 您可按需替换 Model ID。Model ID 查询见 [模型列表](/docs/model-list)。
**选项:Python**
```Python
import os
# Install SDK: python -m pip install --upgrade arkruntime
from arkruntime import Ark
client = Ark(
# The base URL for model invocation
base_url="https://ark.cn-beijing.volces.com/api/v3",
# Get API Key: https://ark.volcengine.com/region:cn-beijing/apikey
api_key=os.getenv("ARK_API_KEY"),
)
imagesResponse = client.images.generate(
# Replace with Model ID
model="doubao-seedream-5-0-pro-260628",
prompt="将图片进行精确图层分离,需分离的文字坐标为180 64 812 198、757 210 939 280、63 212 320 282、178 714 826 810、814 819 949 894、326 824 669 930;鹦鹉的坐标为347 305 642 997。",
image="https://arkdocs.tos-cn-beijing.volces.com/images/image-generation/seedream_50_pro_layer_input.png",
layer_decomposition=True,
size="2K",
output_format="jpeg",
response_format="url",
watermark=True,
)
for item in imagesResponse.data:
print(item)
```
**选项:Java**
```Java
package com.ark.sample;
import com.volcengine.ark.runtime.models.images.*;
import com.volcengine.ark.runtime.service.ArkService;
import okhttp3.ConnectionPool;
import okhttp3.Dispatcher;
import java.util.concurrent.TimeUnit;
public class ImageGenerationsExample {
public static void main(String[] args) {
String apiKey = System.getenv("ARK_API_KEY");
ConnectionPool connectionPool = new ConnectionPool(5, 1, TimeUnit.SECONDS);
Dispatcher dispatcher = new Dispatcher();
ArkService service = ArkService.builder()
.baseUrl("https://ark.cn-beijing.volces.com/api/v3")
// The base URL for model invocation
.dispatcher(dispatcher)
.connectionPool(connectionPool)
.apiKey(apiKey)
.build();
// CreateImageGenerationRequestImage requires ark-runtime 0.6.0 or later.
CreateImageGenerationRequest generateRequest = CreateImageGenerationRequest.builder()
.model("doubao-seedream-5-0-pro-260628") // Replace with Model ID
.prompt("将图片进行精确图层分离,需分离的文字坐标为180 64 812 198、757 210 939 280、63 212 320 282、178 714 826 810、814 819 949 894、326 824 669 930;鹦鹉的坐标为347 305 642 997。")
.image(CreateImageGenerationRequestImage.ofString("https://arkdocs.tos-cn-beijing.volces.com/images/image-generation/seedream_50_pro_layer_input.png"))
.layerDecomposition(true)
.size("2K")
.outputFormat(OutputFormat.JPEG)
.responseFormat(ResponseFormat.URL)
.watermark(true)
.build();
ImageGenerationResponse imagesResponse = service.generateImages(generateRequest);
imagesResponse.getData().forEach(item -> System.out.println(item));
service.shutdownExecutor();
}
}
```
**选项:Go**
```Go
package main
import (
"context"
"fmt"
"os"
"github.com/volcengine/ark-runtime-go/arkruntime"
model "github.com/volcengine/ark-runtime-go/arkruntime/model/images"
)
func main() {
client := arkruntime.NewClientWithApiKey(
os.Getenv("ARK_API_KEY"),
// The base URL for model invocation
arkruntime.WithBaseUrl("https://ark.cn-beijing.volces.com/api/v3"),
)
ctx := context.Background()
outputFormat := model.OutputFormatJpeg
generateReq := &model.CreateImageGenerationRequest{
Model: "doubao-seedream-5-0-pro-260628",
Prompt: model.NewOptString("将图片进行精确图层分离,需分离的文字坐标为180 64 812 198、757 210 939 280、63 212 320 282、178 714 826 810、814 819 949 894、326 824 669 930;鹦鹉的坐标为347 305 642 997。"),
Image: model.NewOptCreateImageGenerationRequestImage(model.NewStringArrayCreateImageGenerationRequestImage([]string{"https://arkdocs.tos-cn-beijing.volces.com/images/image-generation/seedream_50_pro_layer_input.png"})),
LayerDecomposition: model.NewOptBool(true),
Size: model.NewOptString("2K"),
OutputFormat: model.NewOptOutputFormat(outputFormat),
ResponseFormat: model.NewOptResponseFormat(model.ResponseFormatURL),
Watermark: model.NewOptBool(true),
}
imagesResponse, err := client.GenerateImages(ctx, generateReq)
if err != nil {
fmt.Printf("generate images error: %v\n", err)
return
}
for _, item := range imagesResponse.Data {
fmt.Printf("%+v\n", item)
}
}
```
**选项:OpenAI**
```Python
import os
from openai import OpenAI
client = OpenAI(
# The base URL for model invocation
base_url="https://ark.cn-beijing.volces.com/api/v3",
# Get API Key: https://ark.volcengine.com/region:cn-beijing/apikey
api_key=os.getenv("ARK_API_KEY"),
)
imagesResponse = client.images.generate(
model="doubao-seedream-5-0-pro-260628",
prompt="将图片进行精确图层分离,需分离的文字坐标为180 64 812 198、757 210 939 280、63 212 320 282、178 714 826 810、814 819 949 894、326 824 669 930;鹦鹉的坐标为347 305 642 997。",
size="2K",
output_format="jpeg",
response_format="url",
extra_body={
"image": "https://arkdocs.tos-cn-beijing.volces.com/images/image-generation/seedream_50_pro_layer_input.png",
"layer_decomposition": True,
"watermark": True,
},
)
for item in imagesResponse.data:
print(item)
```
### 响应结果说明
图层拆分模式下,响应参数 `data` 数组会同时返回底图和所有图层。您可通过`url`下载所有输出图,并根据图层叠放顺序(`z_index`)区分底图和图层。利用图层的边界框坐标信息(`bounding_box`) 和图层叠放顺序(`z_index`)可还原、编辑或重组图层。
|字段 |返回对象 |含义 |
|---|---|---|
|`url` |底图、图层 |底图或图层的下载链接。图片 URL 仅保留 24 小时。 |
|`z_index` |底图、图层 |图层叠放顺序。底图 `z_index=0` 固定为`0`,各图层按 `z_index` 递增排序。 |
|`bounding_box.absolute` |图层 |图层在输出底图坐标系中的绝对像素位置,适用于将图层还原到输出底图的原始位置。 |
|`bounding_box.normalized` |图层 |图层在输出底图坐标系中的归一化位置,适用于将图层还原到任意尺寸的自定义画布。 |
|`name`、`description` |图层 |图层名称和内容描述。 |
**返回结构示例:**
```JSON
{
"model": "doubao-seedream-5-0-pro-260628",
"created": 1784696685,
"data": [
{
"url": "https://...",
"size": "2048x2048",
"output_format": "jpeg",
"z_index": 0
},
{
"url": "https://...",
"size": "1273x265",
"output_format": "png",
"z_index": 1,
"bounding_box": {
"absolute": [383, 120, 1655, 384],
"normalized": [187, 59, 808, 188]
},
"name": "Seedream标题文字",
"description": "黄色大号衬线字体的Seedream标题文字"
},
{
"url": "https://...",
"size": "492x98",
"output_format": "png",
"z_index": 2,
"bounding_box": {
"absolute": [140, 451, 631, 548],
"normalized": [68, 220, 308, 268]
},
"name": "左上角标语文字",
"description": "白色两行文字内容为EXPLORE THE WILD, INSPIRE THE SOUL."
}
],
"usage": {
"input_images": 1,
"generated_images": 8,
"output_tokens": 23107,
"total_tokens": 23107
}
}
```
## 使用拆分后的图层
获取底图和图层后,可以直接按原位置还原图层,也可以调整图层位置、大小和叠放顺序;如果需要修改某个元素的颜色、风格或细节,也可以单独编辑该图层。
### 还原与重组图层
还原或重组图层时,可按以下顺序处理响应结果:
1. 将 `data` 数组中 `z_index` 为 `0` 的对象作为画布背景。
2. 提取 `z_index` 大于 `0` 的图层对象,并按 `z_index` 从小到大排序。
3. 下载图层 PNG,并根据 `bounding_box` 将图层放置到输出底图或目标画布。
4. 根据业务需求调整图层坐标、尺寸或叠放顺序,生成新的组合结果。
**还原图层到输出底图**
如需将图层还原到输出底图中的原始位置,建议使用 `bounding_box.absolute`。该字段为图层在输出底图坐标系中的绝对像素坐标,格式为 `[left, top, right, bottom]`:
* `left`、`top`:图层左上角相对于输出底图左上角的位置;
* `right`、`bottom`:图层右下角相对于输出底图左上角的位置。
可按以下方式计算图层在底图中的位置和尺寸,其中 `x`、`y` 表示图层左上角在底图中的放置位置,`w`、`h` 表示图层在底图中的展示宽高:
```text
x = left
y = top
w = right - left
h = bottom - top
```
将图层缩放至 `w × h`,再放置到底图的 `(x, y)` 位置。多个图层需要组合时,按 `z_index` 从小到大依次叠放。
**还原到任意画布**
如需将图层还原到不同尺寸的前端画布、设计工具画布中,建议使用 `bounding_box.normalized`。该字段为图层在输出底图坐标系中的归一化坐标,表示图层边界在输出底图宽高方向上的相对位置,格式为 `[left, top, right, bottom]`:
* `left`、`right`:图层左右边界在底图宽度方向上的相对位置;
* `top`、`bottom`:图层上下边界在底图高度方向上的相对位置。
设目标画布宽高为 `W × H`,可按以下方式计算图层在目标画布中的位置和尺寸,其中 `x`、`y` 表示图层左上角在目标画布中的放置位置,`w`、`h` 表示图层在目标画布中的展示宽高:
```text
x = left / 1000 × W
y = top / 1000 × H
w = (right - left) / 1000 × W
h = (bottom - top) / 1000 × H
```
将图层缩放至 `w × h`,再放置到目标画布的 `(x, y)` 位置。由于归一化坐标为整数,换算到目标画布时可能存在取整误差。
`bounding_box` 字段的完整定义和坐标示例参见 [图片生成 API](/docs/image-generation-api)。
### 编辑单个透明图层
图层拆分返回的图层为带透明通道的 PNG 图片。您可以将输出图层作为输入图再次调用 Seedream 模型,对其进行单独编辑,例如换色、风格变换、添加细节等。
> **注意**
>
> 如果希望编辑后的图层继续保留透明背景,可在请求中配置 `background=transparent`、`output_format=png`。透明背景模式的使用限制请参见 [透明通道设置](/docs/seedream-5-0-pro#transparent-channel)。
|提示词 |输入图层 |输出 |
|---|---|---|
|将图片中的鹦鹉改为孔雀 | | |
**选项:Curl**
```Bash
curl https://ark.cn-beijing.volces.com/api/v3/images/generations \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ARK_API_KEY" \
-d '{
"model": "doubao-seedream-5-0-pro-260628",
"prompt": "将图片中的鹦鹉改为孔雀",
"image": "https://arkdocs.tos-cn-beijing.volces.com/images/image-generation/Seedream50_layer_4.png",
"size": "2K",
"background": "transparent",
"watermark": true
}'
```
* 您可按需替换 Model ID。Model ID 查询见 [模型列表](/docs/model-list)。
**选项:Python**
```Python
import os
# Install SDK: python -m pip install --upgrade arkruntime
from arkruntime import Ark
client = Ark(
# The base URL for model invocation
base_url="https://ark.cn-beijing.volces.com/api/v3",
# Get API Key: https://ark.volcengine.com/region:cn-beijing/apikey
api_key=os.getenv("ARK_API_KEY"),
)
imagesResponse = client.images.generate(
# Replace with Model ID
model="doubao-seedream-5-0-pro-260628",
prompt="将图片中的鹦鹉改为孔雀",
image="https://arkdocs.tos-cn-beijing.volces.com/images/image-generation/Seedream50_layer_4.png",
size="2K",
background="transparent",
response_format="url",
watermark=True,
)
print(imagesResponse.data[0].url)
```
**选项:Go**
```Go
package main
import (
"context"
"fmt"
"os"
"github.com/volcengine/ark-runtime-go/arkruntime"
model "github.com/volcengine/ark-runtime-go/arkruntime/model/images"
)
func main() {
client := arkruntime.NewClientWithApiKey(
os.Getenv("ARK_API_KEY"),
// The base URL for model invocation
arkruntime.WithBaseUrl("https://ark.cn-beijing.volces.com/api/v3"),
)
ctx := context.Background()
generateReq := &model.CreateImageGenerationRequest{
Model: "doubao-seedream-5-0-pro-260628",
Prompt: model.NewOptString("将图片中的鹦鹉改为孔雀"),
Image: model.NewOptCreateImageGenerationRequestImage(model.NewStringArrayCreateImageGenerationRequestImage([]string{"https://arkdocs.tos-cn-beijing.volces.com/images/image-generation/Seedream50_layer_4.png"})),
Size: model.NewOptString("2K"),
ResponseFormat: model.NewOptResponseFormat(model.ResponseFormatURL),
Background: model.NewOptBackground(model.BackgroundTransparent),
Watermark: model.NewOptBool(true),
}
imagesResponse, err := client.GenerateImages(ctx, generateReq)
if err != nil {
fmt.Printf("generate images error: %v\n", err)
return
}
fmt.Printf("%s\n", imagesResponse.Data[0].URL.Or(""))
}
```
**选项:Java**
```Java
package com.ark.sample;
import com.volcengine.ark.runtime.models.images.*;
import com.volcengine.ark.runtime.service.ArkService;
import okhttp3.ConnectionPool;
import okhttp3.Dispatcher;
import java.util.concurrent.TimeUnit;
public class ImageGenerationsExample {
public static void main(String[] args) {
String apiKey = System.getenv("ARK_API_KEY");
ConnectionPool connectionPool = new ConnectionPool(5, 1, TimeUnit.SECONDS);
Dispatcher dispatcher = new Dispatcher();
ArkService service = ArkService.builder()
.baseUrl("https://ark.cn-beijing.volces.com/api/v3") // The base URL for model invocation
.dispatcher(dispatcher)
.connectionPool(connectionPool)
.apiKey(apiKey)
.build();
// CreateImageGenerationRequestImage requires ark-runtime 0.6.0 or later.
CreateImageGenerationRequest generateRequest = CreateImageGenerationRequest.builder()
.model("doubao-seedream-5-0-pro-260628") // Replace with Model ID
.prompt("将图片中的鹦鹉改为孔雀")
.image(CreateImageGenerationRequestImage.ofString(
"https://arkdocs.tos-cn-beijing.volces.com/images/image-generation/Seedream50_layer_4.png"))
.size("2K")
.background(Background.TRANSPARENT)
.responseFormat(ResponseFormat.URL)
.watermark(true)
.build();
ImageGenerationResponse imagesResponse = service.generateImages(generateRequest);
System.out.println(imagesResponse.getData().get(0).getUrl());
service.shutdownExecutor();
}
}
```
# 提升图片生成速度配置
如果您希望**提升图片生成速度**,可以通过 `optimize_prompt_options.mode` 参数选择更快的提示词优化模式。**对于时延敏感的业务,建议您使用 Seedream 5.0 pro 的 `fast` 模式或直接使用 Seedream 5.0 flash 以获得更快的生成速度**。
* `standard`(默认值):标准模式,生成图片的质量较 `fast` 模式更优,但耗时更长。
* `fast`:极速模式,生成图片的耗时较 `standard` 模式更短。**仅 Seedream 5.0 pro 支持**。
```JSON
{
"optimize_prompt_options": {
"mode": "fast"
}
}
```
# 自定义图片输出规格
您可以配置以下参数来控制图片输出规格:
* **size**:指定输出图像的尺寸大小。
* **response_format**:指定生成图像的返回格式。
* **output_format**:指定生成图像的文件格式。
* **background**:控制是否生成带透明通道的图片。
* **watermark** :指定是否为输出图片添加水印。
## 图像输出尺寸
`size` 参数在**图片生成场景**和**图层拆分场景**下的可选值与默认值不同,请根据实际场景选择:
### 图片生成场景
支持以下两种方式,不可混用。
**方式 1:指定分辨率档位(推荐)**
在 prompt 中用自然语言描述图片宽高比、图片形状或图片用途,最终由模型判断生成图片的大小。
* 默认值:`2K`
* 可选值:`1K`、`1.5K`、`2K`
> **说明**
>
> `1.5K` 与 `1K` 价格相同,且图片生成效果更优。
使用方式 1 并在 prompt 中描述特定宽高比时,模型实际映射的宽高像素参考值(不限于以下标准值,仅列常见):
| 分辨率 | 宽高比 | 宽高像素值 |
| --- | --- | --- |
| 1K | 1:1 | 1024x1024 |
|^^| 4:3 | 1152x864 |
|^^| 3:4 | 864x1152 |
|^^| 16:9 | 1424x800 |
|^^| 9:16 | 800x1424 |
|^^| 3:2 | 1248x832 |
|^^| 2:3 | 832x1248 |
|^^| 21:9 | 1568x672 |
| 1.5K | 1:1 | 1536x1536 |
|^^| 4:3 | 1792x1344 |
|^^| 3:4 | 1344x1792 |
|^^| 16:9 | 2048x1152 |
|^^| 9:16 | 1152x2048 |
|^^| 3:2 | 1872x1248 |
|^^| 2:3 | 1248x1872 |
|^^| 21:9 | 2352x1008 |
| 2K | 1:1 | 2048x2048 |
|^^| 4:3 | 2368x1776 |
|^^| 3:4 | 1776x2368 |
|^^| 16:9 | 2816x1584 |
|^^| 9:16 | 1584x2816 |
|^^| 3:2 | 2496x1664 |
|^^| 2:3 | 1664x2496 |
|^^| 21:9 | 3136x1344 |
**方式 2:指定宽高像素值(`宽x高`)**
* 总像素取值范围:[`1280x720`(921600), `2048x2048x1.1025`(4624220)]
* 宽高比取值范围:[1/16, 16]
> **说明:宽高像素值使用示例**
>
> 采用方式 2 时,需同时满足总像素取值范围和宽高比取值范围。其中,总像素是对单张图宽度和高度的像素乘积限制,而不是对宽度或高度的单独值进行限制。
> * **有效示例**:`2048x1024`
> 总像素值 2048x1024=2097152,符合 [921600, 4624220] 的区间要求;宽高比 2048/1024=2,符合 [1/16, 16] 的区间要求,故该示例值有效。
> * **无效示例**:`512x512`
> 总像素值 512x512=262144,未达到 921600 的最低要求,故该示例值无效。
|方式1 |方式2 |
|---|---|
|```JSON |```JSON | \
|{ |{ | \
|"prompt": "生成一组共4张连贯插画,宽高比为3:2,核心为同一庭院一角的四季变迁,以统一风格展现四季独特色彩、元素与氛围", |"prompt": "生成一组共4张连贯插画,核心为同一庭院一角的四季变迁,以统一风格展现四季独特色彩、元素与氛围",| \
|"size": "2K" |"size": "2048x2048" | \
|} |} | \
|``` |``` |
### 图层拆分场景
仅支持通过指定分辨率档位的方式进行设置。输出图的分辨率规则如下:
* **底图**:输出底图的分辨率和 `size` 指定的分辨率一致;输出底图和原待拆分图的宽高比一致。
* **各图层**:输出图层的分辨率和 `size` 指定的分辨率接近;每个输出图层和其在原图中的宽高比一致。
`size` 的默认值与可选值:
* 默认值:`auto`
* 可选值:`1K`、`1.5K`、`2K`、`auto`(根据输入图的尺寸和宽高比进行输出)
> **说明**
>
> `1.5K` 与 `1K` 价格相同,且图片生成效果更优。
> **说明:auto 适配规则**
>
> auto 模式下,模型将根据输入图片的尺寸,判断输出底图与每个图层的尺寸:
>
> * 若输入图片尺寸在 [`1280x720`(921600), `2048x2048x1.1025`(4624220)] 之间,按输入图片原尺寸输出底图与每个图层;且各自保持其在原图中的宽高比。
> * 若输入图片小于 1K,按 1K 输出底图与每个图层,且各自保持其在原图中的宽高比。
> * 若输入图片大于 2K,按 2K 输出底图与每个图层,且各自保持其在原图中的宽高比。
模型实际映射的宽高像素参考值同 [图片生成场景的分辨率映射表](/docs/seedream-5-0-pro#pro_output_spec)
## 图像输出方式
设置 `response_format` 参数,可以指定生成图像的返回方式:
* `url`:返回图片下载链接。
* `b64_json`:以 Base64 编码字符串的 JSON 格式返回图像数据。
```JSON
{
"response_format": "url"
}
```
## 图像文件格式
设置 `output_format` 参数,指定生成图像文件的格式:
* `png`
* `jpeg`
```JSON
{
"output_format": "png"
}
```
> **注意**
>
> 图层拆分场景下,`output_format` 仅控制底图的输出格式,图层始终以 `png` 格式输出。
## 透明通道设置
设置 `background` 参数,控制是否生成带透明通道的图片:
* `transparent`:透明背景模式,输出带有透明背景的图。
* `opaque`(默认):不透明背景模式,生成常规的实体背景图。
```JSON
{
"background": "transparent"
}
```
> **注意:使用限制**
>
> * 仅支持图生图场景,且只支持输入 **1 张带透明通道**的图片;
> * 透明背景模式下,输出图片默认为 `png` 格式,若同时配置 `output_format` 为 `jpeg`,将触发报错;
> * 若传入了不支持透明通道的文件格式(如 `jpeg`),将触发报错。
## 图像中添加水印
设置 `watermark` 参数,来控制是否在生成的图片中添加水印。
* `false`:不添加水印。
* `true`:在图片右下角添加"AI生成"字样的水印标识。
```JSON
{
"watermark": true
}
```
# 使用限制
**SDK 版本升级**
为保证模型功能的正常使用,请务必升级至最新 SDK 版本。相关步骤可参考 [安装及升级 SDK](/docs/install-and-upgrade-sdk)。
**图片传入限制**
图片传入方式(两种场景通用):
* 图片 URL:请确保图片 URL 可被访问。
示例:`https://arkdocs.tos-cn-beijing.volces.com/images/image-generation/seedream4_5_imageToimage.png`
* Base64 编码:请遵循格式`data:image/<图片格式>;base64,`。注意:`<图片格式>` 必须采用小写字母,例如 `data:image/png;base64,`。
如需获得图片的 Base64 编码,可使用第三方工具,例如 https://base64.guru/converter/encode/image。
不同场景对输入图的约束不同,详见下表:
| 约束项 | 图片生成场景 | 图层拆分场景 |
| --- | --- | --- |
| 图片格式 | jpeg、png、webp、bmp、tiff、gif、heic、heif | png、jpeg |
| 总像素(宽×高) | [196, `6000×6000`(3600万)] | [`512×512`(262144), `6000×6000`(3600万)] |
| 宽高长度(px) | 大于14 | — |
| 宽高比(宽/高) | [1/16, 16] | [1/16, 16] |
| 大小 | 不超过 30 MB | 不超过 30 MB |
| 传入张数 | 最多传入 10 张参考图 | 仅支持传入单张图 |
> **说明**
>
> 总像素是对单张图宽度和高度的**像素乘积**限制,而不是对宽度或高度的单独值进行限制。
**保存时间**
图片URL仅保留24小时,超时后会被自动清除。请您务必及时保存生成的图片。
**限流说明**
* IPM 限流:账号下同模型(区分模型版本)每分钟生成图片数量上限。若超过该限制,生成图片时会报错。
* 图层拆分场景下,每次请求预扣减 17 IPM(即按最大输出张数 17 张预留配额);图片全部生成后,按实际生成数量返还多扣减的额度。
* 不同模型的限制值不同,详见 [图片生成能力](/docs/model-list#9df4d9fd)。
---
# Doubao Seedream 5.0 pro / flash 实现交互编辑指南
Source: https://ark.volcengine.com/region:cn-beijing/docs/seedream-5-0-pro-editing-guide
Doubao Seedream 5.0 pro(以下简称 Seedream 5.0 pro)与 Doubao Seedream 5.0 flash(以下简称 Seedream 5.0 flash)均提供交互编辑能力,支持在提示词中输入位置坐标来精准编辑图片。用户可以在参考图上通过坐标点或标注建立位置对应关系,模型将按标记位置进行局部编辑,实现物品替换、元素定位、局部重绘等精细化操作。
本文介绍如何基于 Seedream 5.0 pro / flash 实现点选和框选式交互编辑:用户上传参考图后,通过点选或框选指定编辑位置,前端将操作位置转换为**归一化坐标**(范围 **0~999**,左上角为 0,0,右下角为 999,999)用 `` 或 `` 坐标标记,并与自然语言 Prompt 一起提交给模型。模型会结合参考图、坐标位置和文本指令生成编辑后的图片。
| 输入图片及框选操作 | 效果预览 |
| --- | --- |
| [视频](https://arkdocs.tos-cn-beijing.volces.com/videos/image-generation/edite-model.mov)
将用户框选的目标区域转换为空间坐标,组装成模型可以理解的 Prompt。
Prompt:` 将图 1 179 283 796 986 的主体放到图 2 118 331 933 871 位置。`
| 
根据组装后的 Prompt、参考图生成编辑后的图片。
|
# 关键操作:将目标区域转换为归一化坐标
模型需要的关键信息:**待编辑图片**和 **prompt**(包含归一化坐标 + 编辑指令),其中归一化坐标是将图片上点选或框选的区域**归一化到 1000 * 1000 的比例坐标,取值范围[0,999]**。图片宽高等分为 1000 份后,图片左上角坐标为 `0,0`,右下角为 `999,999`。
**prompt 中可以使用的坐标方式**:
* **点选坐标**:`x y`(指定一个点,由模型判断影响范围)
* **框选坐标**:`x1 y1 x2 y2`(指定左上角和右下角坐标,精确控制编辑区域大小)
**归一化坐标处理方式**:
1. 获取定位信息:用户完成点选或框选后,需要先拿到定位点/框在图片展示区域内的相对坐标(相对于图片左上角)。
* 点选:`x_px, y_px`(点击位置)
* 框选:`x1_px, y1_px, x2_px, y2_px`(框的左上角与右下角)
2. 转换为 0-999 的归一化坐标:将获取到的定位坐标按图片展示宽高转换为 0-999 的整数坐标。
* 点选:
* `x = round(x_px / width * 1000)`
* `y = round(y_px / height * 1000)`
> **注意**
>
> * `x`、`y`:归一化后的坐标。
> * `x_px`、`y_px`:点选位置相对于图片左上角的坐标。
> * `width`、`height`:图片在画布中的展示宽、高。
* 框选:
对 `x1_px, y1_px, x2_px, y2_px` 分别按上述规则换算,得到 `x1 y1 x2 y2`。
# 支持场景
> **说明**
>
> 在多主体场景下明确指定编辑对象的方法,可参见 [使用说明](/docs/seedream-5-0-pro-editing-guide#usage)。
| 场景 | 交互模式 | 组合后的 Prompt |
| ---- | ---- | ---- |
| 编辑指定点附近的对象 | 点选 | `把图 1 520 460 位置换成皇冠` |
| 编辑指定区域的对象 | 框选 | `把图 1 120 180 640 760 区域替换成花园` |
| 跨图片编辑 | 点选、框选 | `将图 1 179 283 796 986 的主体放到图 2 118 331 933 871 位置,将图 2 50 50 位置换成皇冠` |
# 整体流程
## 代码示例
您可以下载代码示例,体验交互编辑效果。下载并解压后,请确保已安装 Python 3.9 或以上版本,在项目目录执行 `python3 -m pip install -r requirements.txt` 安装依赖,设置环境变量 `ARK_API_KEY`,再执行 `bash run.sh` 启动示例。
[touch_edit_demo_arkruntime-20260909.zip](https://arkdocs.tos-cn-beijing.volces.com/files/image-generation/touch_edit_demo_arkruntime-20260909.zip)
## 流程图
基于上述代码示例实现交互编辑的完整流程如下。

# 实现步骤
> **注意**
>
> 本文仅提供展示关键执行逻辑的核心代码,无法仅凭以下内容实现完整流程。完整实现请参见 [代码示例](/docs/seedream-5-0-pro-editing-guide#code-example)。
## 0. 上传图片并放入画布
这一步主要用于获取图片的相关信息。本文示例是将用户上传的图片转换为画布中的可操作对象。除了保存图片文件本身,还需要记录图片在画布中的位置、展示尺寸、原始尺寸和图号,为后续点选、框选和模型调用提供基础数据。
核心代码如下:
核心代码
```JavaScript
function addImageFromFile(file, dataUrl) {
const probe = new Image();
probe.onload = () => {
const maxSide = 360;
const ratio = Math.min(1, maxSide / Math.max(probe.naturalWidth, probe.naturalHeight));
const id = `img-${state.nextId}`;
const image = {
id,
label: `图${state.nextId}`,
name: file.name,
dataUrl,
element: probe,
naturalWidth: probe.naturalWidth,
naturalHeight: probe.naturalHeight,
x: 80 + (state.nextId - 1) * 40,
y: 80 + (state.nextId - 1) * 40,
width: Math.round(probe.naturalWidth * ratio),
height: Math.round(probe.naturalHeight * ratio),
};
state.nextId += 1;
state.images.push(image);
selectImage(id);
setStatus(`已上传 ${image.label},可拖拽或点选/框选。`);
};
probe.src = dataUrl;
}
```
## 1. 将目标区域转换为归一化坐标
这一步将用户在画布上的点选或框选操作,转换为 Seedream 5.0 pro Prompt 中可使用的坐标定位标记。
### 实现原理
在图片上点选或框选的区域,需要转换为归一化坐标(范围 0~999,左上角为 0,0,右下角为 999,999),将用户的空间意图显式写入 Prompt,例如:
```text
把 图1520 460 位置换成皇冠
把 图1120 180 640 760 区域替换成花园
```
* **坐标说明**
| 坐标类型 | 含义 | 用途 |
| --- | ---- | ---- |
| Client 坐标 | 鼠标相对浏览器窗口左上角的位置,即 `event.clientX / event.clientY`。 | 浏览器事件的原始输入。 |
| World 坐标 | 画布内部的逻辑坐标系。图片的 `x / y / width / height` 都保存在这个坐标系中。 | 保证画布缩放、平移后仍能正确命中图片。 |
| Normalized 坐标 | 相对单张图片归一化到 0-999 的坐标。 | 最终写入 `` 或 ``。 |
* **坐标转换**
1. 将鼠标的 Client 坐标转换为 World 坐标,消除画布位置、平移和缩放的影响。
2. 将 World 坐标转换为图片内 0-999 的归一化坐标。具体原理参见 [关键操作:将目标区域转换为归一化坐标](/docs/seedream-5-0-pro-editing-guide#key-steps)。
* 点选模式:生成 ` x y`;
* 框选模式:生成 ` x1 y1 x2 y2`。
### 核心代码
* 坐标转换
```JavaScript
// Client 坐标转换为 World 坐标
function clientToWorld(clientX, clientY) {
const rect = viewport.getBoundingClientRect();
return {
x: (clientX - rect.left - state.view.x) / state.view.scale,
y: (clientY - rect.top - state.view.y) / state.view.scale,
};
}
// World 坐标转换为 0-999 归一化
function normalizedPoint(worldPoint, image) {
return {
x: clamp1000(((worldPoint.x - image.x) / image.width) * 1000),
y: clamp1000(((worldPoint.y - image.y) / image.height) * 1000),
};
}
```
* 根据点选 / 框选生成 `` 或 `` 坐标标记
```JavaScript
if (state.mode === "point" && image) {
const p = normalizedPoint(worldPoint, image);
const ann = buildAnnotation("point", image, { x: p.x, y: p.y });
ann.token = `${image.label}${p.x} ${p.y}`;
state.annotations.push(ann);
appendAnnotationChip(ann, image);
renderImages();
setStatus(`已添加 ${ann.token}`);
return;
}
if (state.box) {
const image = state.images.find((item) => item.id === state.box.imageId);
const dx = Math.abs(state.box.current.x - state.box.start.x);
const dy = Math.abs(state.box.current.y - state.box.start.y);
state.box.selection.remove();
if (image && dx > 4 && dy > 4) {
const b = normalizedBox(state.box.start, state.box.current, image);
const ann = buildAnnotation("bbox", image, b);
ann.token = `${image.label}${b.x1} ${b.y1} ${b.x2} ${b.y2}`;
state.annotations.push(ann);
appendAnnotationChip(ann, image);
setStatus(`已添加 ${ann.token}`);
}
state.box = null;
viewport.releasePointerCapture(event.pointerId);
renderImages();
}
```
## 2. 组装 Prompt
这一步将用户输入的自然语言和点选 / 框选生成的空间坐标合并,形成 Seedream 5.0 pro 可以理解的最终 Prompt。
### Prompt 写法
| 场景 | 参考写法 |
| ---- | ---- |
| 编辑指定点附近的对象 | ` 把图 1 520 460 位置换成皇冠 ` |
| 编辑指定区域的对象 | ` 把图 1 120 180 640 760 区域替换成花园 ` |
| 跨图片编辑 | ` 将图 1 179 283 796 986 的主体放到图 2 118 331 933 871 位置。` |
### 核心代码
核心代码
```JavaScript
// 从编辑框内容生成最终 Prompt,并整理本次需要提交的图片列表
function buildModelInputFromPrompt() {
const assignedImages = new Map();
const inputImages = [];
// 将画布图片映射为模型输入的图号,并收集需要提交的图片
function assignImage(image) {
if (!image) return "";
if (!assignedImages.has(image.id)) {
const inputLabel = `图${inputImages.length + 1}`;
assignedImages.set(image.id, inputLabel);
inputImages.push({ ...image, inputLabel });
}
return assignedImages.get(image.id);
}
// 将编辑框中的图号(图1/图2)重映射为实际要提交的输入图号
function remapImageLabels(text) {
return text.replace(/图\\d+/g, (label) => {
const image = state.images.find((item) => item.label === label);
return image ? assignImage(image) : label;
});
}
// 遍历编辑框 DOM,将文本与坐标标注拼接为 Prompt 文本
function walk(node) {
if (node.nodeType === Node.TEXT_NODE) {
return remapImageLabels(node.textContent || "");
}
if (node.nodeType !== Node.ELEMENT_NODE) {
return "";
}
if (node.classList?.contains("annotation-inline")) {
const ann = state.annotations.find((item) => item.id === Number(node.dataset.annotationId));
const image = ann ? state.images.find((item) => item.id === ann.imageId) : null;
const inputLabel = assignImage(image);
if (!ann || !inputLabel) return "";
return ` ${annotationTokenForLabel(ann, inputLabel)} `;
}
if (node.tagName === "BR") {
return "\\n";
}
return [...node.childNodes].map(walk).join("");
}
const prompt = walk(promptInput)
.replace(/\\u00a0/g, " ")
.replace(/[ \\t]{2,}/g, " ")
.replace(/\\n{3,}/g, "\\n\\n")
.trim();
return { prompt, images: inputImages };
}
```
## 3. 生成图片
这一步根据组装好的 Prompt 和输入图片调用图片生成 API,并将模型生成结果返回给前端展示。
### 核心代码
* 前端提交图片生成请求
```JavaScript
generateBtn.addEventListener("click", async () => {
const modelInput = buildModelInputFromPrompt();
const resp = await fetch("/api/generate", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
prompt: modelInput.prompt,
images: modelInput.images.map((image) => ({
inputLabel: image.inputLabel,
name: image.name,
dataUrl: image.dataUrl,
naturalWidth: image.naturalWidth,
naturalHeight: image.naturalHeight,
})),
}),
});
const data = await resp.json();
renderGeneratedImage(data.url);
});
```
* 后端调用图片生成 API
```Python
ARK_MODEL = "doubao-seedream-5-0-pro-260628"
ARK_BASE_URL = "https://ark.cn-beijing.volces.com/api/v3"
try:
client = Ark(
api_key=os.getenv("ARK_API_KEY"),
base_url=ARK_BASE_URL,
)
resp = client.images.generate(
model=ARK_MODEL,
prompt=prompt,
image=image_arg,
size="2K",
output_format="png",
response_format="url",
watermark=True,
)
except Exception as exc:
print(f"[generate] error: {exc!r}")
return self._send_json(500, {"error": str(exc)})
try:
url = resp.data[0].url
except (AttributeError, IndexError) as exc:
return self._send_json(502, {"error": f"unexpected ark response: {exc}"})
return self._send_json(
200,
{
"model": ARK_MODEL,
"prompt": prompt,
"url": url,
},
)
```
### 效果预览
| 输入图片 | 效果预览 |
| --- | --- |
|  |  | \
| | | \
| > Prompt:` 将图 1 179 283 796 986 的主体放到图 2 118 331 933 871 位置。` | |
# 使用说明
在多主体场景下,可以通过以下写法更明确地指定编辑对象。
* 框选区域内有多个主体时,明确操作对象。
当 `` 覆盖的区域内存在多个主体/元素时,建议在 Prompt 中补充一句说明要编辑的目标对象(例如“左侧的人”“戴帽子的猫”“前景的花”),帮助模型稳定选择正确的编辑对象。
示例:`把图 1 120 180 640 760 区域内的左侧人物换成机器人`
* 标注需要保持不变的对象。
如果希望某些物体不被修改,可以将其一并框选出来,并在 Prompt 中明确“保持不变/不要修改”。
示例:`把图 1 120 180 640 760 区域替换成花园,图 1 700 120 920 360 区域保持不变`
# 相关文档
* [Doubao Seedream 5.0 pro / flash 教程](/docs/seedream-5-0-pro)
* [ 图片生成 API 文档 ](/docs/image-generation-api)
---
# 图片生成教程
Source: https://ark.volcengine.com/region:cn-beijing/docs/seedream-4-0-5-0
Doubao Seedream 系列模型原生支持文本、单图和多图输入,实现基于主体一致性的多图融合创作、图像编辑、组图生成等多样玩法,让图像创作更加自由可控。本文以 Doubao Seedream 5.0 lite(以下简称 Seedream 5.0 lite)为例介绍如何调用 [Image generation API](/docs/image-generation-api) 进行图像创作。如需使用 Doubao Seedream 5.0 pro(以下简称 Seedream 5.0 pro)/ Doubao Seedream 4.5(以下简称 Seedream 4.5)/ Doubao Seedream 4.0(以下简称 Seedream 4.0)模型,将下文代码示例中的 model 字段替换为对应的 Model ID 即可。
> **注意:新模型上线**
>
> Seedream 5.0 flash(Model ID: `doubao-seedream-5-0-flash-260915`)已上线,支持通过坐标、框选、箭头等多种方式指定编辑位置来精准编辑图片;支持将单张图片拆分为 1 张底图和最多 16 个独立图层;支持原生多语种生成。
>
> **Seedream 5.0 flash 生图速度更快、价格更低**,适合对时延与成本敏感的业务场景。详情参见:[Doubao Seedream 5.0 pro / flash 教程](/docs/seedream-5-0-pro)。
# 模型效果
更多效果示例见 [效果预览](https://ark.volcengine.com/region:cn-beijing/model/detail?Id=doubao-seedream-5-0)。
|场景 |输入 |输出 |
|---|---|---|
|图层拆分 | | | \
|> Seedream 5.0 pro / flash 支持将元素拆分为可独立编辑的图层,便于后续拖拽、缩放、重组等精细化编辑。 | | | \
| |> 将图片进行精确图层分离,需分离的文字坐标为 `180 64 812 198`、`757 210 939 280`、`63 212 320 282`、`178 714 826 810`、`814 819 949 894`、`326 824 669 930`;鹦鹉的坐标为 `347 305 642 997`。 | |
|交互编辑 | | | \
|> Seedream 5.0 pro / flash 支持通过标记指定编辑区域,模型识别标记范围并生成内容,自然融入原有场景。 | | | \
| |> 根据手绘草图对图像进行编辑。在左下角标记区域添加一叠真实的杂志或艺术画册,并在右侧标记区域添加一个带杯碟的陶瓷杯咖啡。移除所有草图线条。保持构图不变。 | |
|文生图 `联网搜索` |制作一张上海未来5日的天气预报图,采用现代扁平化插画风格,清晰展示每日天气、温度和穿搭建议。 整体为横向排版,标题为“上海未来5日天气预报”,包含5个等宽的垂直卡片,从左到右依次排列。 整体风格为现代、干净、友好的扁平化矢量插画风格,线条清晰,色彩柔和。 人物形象采用年轻男女的卡通插画,表情自然,姿态放松,服装细节清晰。 | | \
|> Seedream 5.0 lite 模型可通过联网搜索功能,融合实时网络信息,提升生图时效性。 | | |
|多参考图生图 | | | \
|> 输入多张参考图,融合它们的风格、元素等特征来生成新图像。 | | | \
| |> 将图1的服装换为图2的服装 | |
|组图生成 | | | \
|> 基于用户输入的文字和图片,生成一组内容关联的图像 | | | \
| |> 参考图1,生成四图片,图中人物分别带着墨镜,骑着摩托,带着帽子,拿着棒棒糖 | |
# 模型能力
以下为 Seedream 系列各版本模型的能力与参数对比,帮助您根据业务需求选择合适的模型。
|模型名称 ||[Seedream 5.0 pro](https://ark.volcengine.com/region:cn-beijing/model/detail?Id=doubao-seedream-5-0-pro) |[Seedream 5.0 flash](https://ark.volcengine.com/region:cn-beijing/model/detail?Id=doubao-seedream-5-0-flash) |[Seedream 5.0 lite](https://ark.volcengine.com/region:cn-beijing/model/detail?Id=doubao-seedream-5-0) |[Seedream 4.5](https://ark.volcengine.com/region:cn-beijing/model/detail?Id=doubao-seedream-4-5) |[Seedream 4.0](https://ark.volcengine.com/region:cn-beijing/model/detail?Id=doubao-seedream-4-0) |
|---|---|---|---|---|---|---|
|模型 ID (Model ID) ||doubao-seedream-5-0-pro-260628 |doubao-seedream-5-0-flash-260915 |doubao-seedream-5-0-260128 (同时支持:doubao-seedream-5-0-lite-260128) |doubao-seedream-4-5-251128 |doubao-seedream-4-0-250828 |
|[文生图](/docs/seedream-4-0-5-0#9695d195) ||✓ |✓ |✓ |✓ |✓ |
|[文生组图](/docs/seedream-4-0-5-0#ec79cfda) ||暂不支持 |暂不支持 |✓ |✓ |✓ |
|[单 / 多图生图](/docs/seedream-4-0-5-0#8bc49063) ||✓ |✓ |✓ |✓ |✓ |
|[单 / 多图生组图](/docs/seedream-4-0-5-0#fc9f85e4) ||暂不支持 |暂不支持 |✓ |✓ |✓ |
|[交互编辑](/docs/seedream-4-0-5-0#interactive_edit) ||✓ |✓ |✗ |✗ |✗ |
|[图层拆分](/docs/seedream-5-0-pro#layer_decomposition) ||✓ |✓ |✗ |✗ |✗ |
|[流式输出](/docs/seedream-4-0-5-0#e5bef0d7) ||暂不支持 |暂不支持 |✓ |✓ |✓ |
|[联网搜索](/docs/seedream-4-0-5-0#4e1745fa) ||暂不支持 |暂不支持 |✓ |✗ |✗ |
|模型参数 |分辨率 |1K, 1.5K, 2K |1K, 1.5K, 2K |2K, 3K, 4K |2K, 4K |1K, 2K, 4K |
|^^| | | | | | | \
| |输出格式 |png, jpeg |png, jpeg |png, jpeg |jpeg |jpeg |
|^^| | | | | | | \
| |提示词优化模式 |标准模式, 极速模式 |标准模式 |标准模式 |标准模式 |标准模式, 极速模式 |
|^^| | | | | | | \
| |生成数量 |支持生成单图/多个图层(1 张底图 + 16 张图层) |支持生成单图/多个图层(1 张底图 + 16 张图层) |输入的参考图数量 + 最终生成的图片数量 ≤ 15张 |||
|限流 IPM(张 / 分钟) ||500 |500 |500 |500 |500 |
# 快速体验
您可在火山方舟平台 API Explorer,快速体验图片生成功能,支持自定义参数(例如设置图片水印、控制输出图片大小等),方便您直观感受其效果和性能。

# 基础使用
## 文生图(纯文本输入单图输出)
通过给模型提供清晰准确的文字指令,即可快速获得符合描述的高质量单张图片。
|提示词 |输出 |
|---|---|
|充满活力的特写编辑肖像,模特眼神犀利,头戴雕塑感帽子,色彩拼接丰富,眼部焦点锐利,景深较浅,具有Vogue杂志封面的美学风格,采用中画幅拍摄,工作室灯光效果强烈。 | |
**选项:Curl**
```Bash
curl https://ark.cn-beijing.volces.com/api/v3/images/generations \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ARK_API_KEY" \
-d '{
"model": "doubao-seedream-5-0-lite-260128",
"prompt": "充满活力的特写编辑肖像,模特眼神犀利,头戴雕塑感帽子,色彩拼接丰富,眼部焦点锐利,景深较浅,具有Vogue杂志封面的美学风格,采用中画幅拍摄,工作室灯光效果强烈。",
"size": "2K",
"output_format":"png",
"watermark": true
}'
```
* 您可按需替换 Model ID。Model ID 查询见 [模型列表](/docs/model-list)。
**选项:Python**
```Python
import os
# Install SDK: python -m pip install --upgrade arkruntime
from arkruntime import Ark
client = Ark(
# The base URL for model invocation
base_url="https://ark.cn-beijing.volces.com/api/v3",
# Get API Key: https://ark.volcengine.com/region:cn-beijing/apikey
api_key=os.getenv('ARK_API_KEY'),
)
imagesResponse = client.images.generate(
# Replace with Model ID
model="doubao-seedream-5-0-lite-260128",
prompt="充满活力的特写编辑肖像,模特眼神犀利,头戴雕塑感帽子,色彩拼接丰富,眼部焦点锐利,景深较浅,具有Vogue杂志封面的美学风格,采用中画幅拍摄,工作室灯光效果强烈。",
size="2K",
output_format="png",
response_format="url",
watermark=True
)
print(imagesResponse.data[0].url)
```
**选项:Java**
```Java
package com.ark.sample;
import com.volcengine.ark.runtime.models.images.*;
import com.volcengine.ark.runtime.service.ArkService;
import okhttp3.ConnectionPool;
import okhttp3.Dispatcher;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
public class ImageGenerationsExample {
public static void main(String[] args) {
// Get API Key: https://ark.volcengine.com/region:cn-beijing/apikey
String apiKey = System.getenv("ARK_API_KEY");
ConnectionPool connectionPool = new ConnectionPool(5, 1, TimeUnit.SECONDS);
Dispatcher dispatcher = new Dispatcher();
ArkService service = ArkService.builder()
.baseUrl("https://ark.cn-beijing.volces.com/api/v3")
// The base URL for model invocation
.dispatcher(dispatcher)
.connectionPool(connectionPool)
.apiKey(apiKey)
.build();
CreateImageGenerationRequest generateRequest = CreateImageGenerationRequest.builder()
.model("doubao-seedream-5-0-lite-260128") // Replace with Model ID
.prompt("充满活力的特写编辑肖像,模特眼神犀利,头戴雕塑感帽子,色彩拼接丰富,眼部焦点锐利,景深较浅,具有Vogue杂志封面的美学风格,采用中画幅拍摄,工作室灯光效果强烈。")
.size("2K")
.sequentialImageGeneration(SequentialImageGenerationMode.DISABLED)
.outputFormat(OutputFormat.PNG)
.responseFormat(ResponseFormat.URL)
.stream(false)
.watermark(true)
.build();
ImageGenerationResponse imagesResponse = service.generateImages(generateRequest);
System.out.println(imagesResponse.getData().get(0).getUrl());
service.shutdownExecutor();
}
}
```
**选项:Go**
```Go
package main
import (
"context"
"fmt"
"os"
"github.com/volcengine/ark-runtime-go/arkruntime"
model "github.com/volcengine/ark-runtime-go/arkruntime/model/images"
)
func main() {
client := arkruntime.NewClientWithApiKey(
// Get API Key: https://ark.volcengine.com/region:cn-beijing/apikey
os.Getenv("ARK_API_KEY"),
// The base URL for model invocation
arkruntime.WithBaseUrl("https://ark.cn-beijing.volces.com/api/v3"),
)
ctx := context.Background()
outputFormat := model.OutputFormatPNG
generateReq := &model.CreateImageGenerationRequest{
Model: "doubao-seedream-5-0-lite-260128", // Replace with Model ID
Prompt: model.NewOptString("充满活力的特写编辑肖像,模特眼神犀利,头戴雕塑感帽子,色彩拼接丰富,眼部焦点锐利,景深较浅,具有Vogue杂志封面的美学风格,采用中画幅拍摄,工作室灯光效果强烈。"),
Size: model.NewOptString("2K"),
OutputFormat: model.NewOptOutputFormat(outputFormat),
ResponseFormat: model.NewOptResponseFormat(model.ResponseFormatURL),
Watermark: model.NewOptBool(true),
}
imagesResponse, err := client.GenerateImages(ctx, generateReq)
if err != nil {
fmt.Printf("generate images error: %v\n", err)
return
}
fmt.Printf("%s\n", imagesResponse.Data[0].URL.Or(""))
}
```
**选项:OpenAI**
```Python
import os
from openai import OpenAI
client = OpenAI(
# The base URL for model invocation
base_url="https://ark.cn-beijing.volces.com/api/v3",
# Get API Key: https://ark.volcengine.com/region:cn-beijing/apikey
api_key=os.getenv('ARK_API_KEY'),
)
imagesResponse = client.images.generate(
# Replace with Model ID
model="doubao-seedream-5-0-lite-260128",
prompt="充满活力的特写编辑肖像,模特眼神犀利,头戴雕塑感帽子,色彩拼接丰富,眼部焦点锐利,景深较浅,具有Vogue杂志封面的美学风格,采用中画幅拍摄,工作室灯光效果强烈。",
size="2K",
output_format="png",
response_format="url",
extra_body={
"watermark": False,
},
)
print(imagesResponse.data[0].url)
```
## 图文生图(单图输入单图输出)
基于已有图片,结合文字指令进行图像编辑,包括图像元素增删、风格转化、材质替换、色调迁移、改变背景/视角/尺寸等。
|提示词 |输入图 |输出 |
|---|---|---|
|保持模特姿势和液态服装的流动形状不变。将服装材质从银色金属改为完全透明的清水(或玻璃)。透过液态水流,可以看到模特的皮肤细节。光影从反射变为折射。 | | |
**选项:Curl**
```Bash
curl https://ark.cn-beijing.volces.com/api/v3/images/generations \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ARK_API_KEY" \
-d '{
"model": "doubao-seedream-5-0-lite-260128",
"prompt": "保持模特姿势和液态服装的流动形状不变。将服装材质从银色金属改为完全透明的清水(或玻璃)。透过液态水流,可以看到模特的皮肤细节。光影从反射变为折射。",
"image": "https://arkdocs.tos-cn-beijing.volces.com/images/image-generation/seedream4_5_imageToimage.png",
"size": "2K",
"output_format":"png",
"watermark": true
}'
```
* 您可按需替换 Model ID。Model ID 查询见 [模型列表](/docs/model-list)。
**选项:Python**
```Python
import os
# Install SDK: python -m pip install --upgrade arkruntime
from arkruntime import Ark
client = Ark(
# The base URL for model invocation
base_url="https://ark.cn-beijing.volces.com/api/v3",
# Get API Key: https://ark.volcengine.com/region:cn-beijing/apikey
api_key=os.getenv('ARK_API_KEY'),
)
imagesResponse = client.images.generate(
# Replace with Model ID
model="doubao-seedream-5-0-lite-260128",
prompt="保持模特姿势和液态服装的流动形状不变。将服装材质从银色金属改为完全透明的清水(或玻璃)。透过液态水流,可以看到模特的皮肤细节。光影从反射变为折射。",
image="https://arkdocs.tos-cn-beijing.volces.com/images/image-generation/seedream4_5_imageToimage.png",
size="2K",
output_format="png",
response_format="url",
watermark=True
)
print(imagesResponse.data[0].url)
```
**选项:Java**
```Java
package com.ark.sample;
import com.volcengine.ark.runtime.models.images.*;
import com.volcengine.ark.runtime.service.ArkService;
import okhttp3.ConnectionPool;
import okhttp3.Dispatcher;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
public class ImageGenerationsExample {
public static void main(String[] args) {
String apiKey = System.getenv("ARK_API_KEY");
ConnectionPool connectionPool = new ConnectionPool(5, 1, TimeUnit.SECONDS);
Dispatcher dispatcher = new Dispatcher();
ArkService service = ArkService.builder()
.baseUrl("https://ark.cn-beijing.volces.com/api/v3")
// The base URL for model invocation
.dispatcher(dispatcher)
.connectionPool(connectionPool)
.apiKey(apiKey)
.build();
// CreateImageGenerationRequestImage requires ark-runtime 0.6.0 or later.
CreateImageGenerationRequest generateRequest = CreateImageGenerationRequest.builder()
.model("doubao-seedream-5-0-lite-260128") // Replace with Model ID
.prompt("保持模特姿势和液态服装的流动形状不变。将服装材质从银色金属改为完全透明的清水(或玻璃)。透过液态水流,可以看到模特的皮肤细节。光影从反射变为折射。")
.image(CreateImageGenerationRequestImage.ofString("https://arkdocs.tos-cn-beijing.volces.com/images/image-generation/seedream4_5_imageToimage.png"))
.size("2K")
.sequentialImageGeneration(SequentialImageGenerationMode.DISABLED)
.outputFormat(OutputFormat.PNG)
.responseFormat(ResponseFormat.URL)
.stream(false)
.watermark(true)
.build();
ImageGenerationResponse imagesResponse = service.generateImages(generateRequest);
System.out.println(imagesResponse.getData().get(0).getUrl());
service.shutdownExecutor();
}
}
```
**选项:Go**
```Go
package main
import (
"context"
"fmt"
"os"
"github.com/volcengine/ark-runtime-go/arkruntime"
model "github.com/volcengine/ark-runtime-go/arkruntime/model/images"
)
func main() {
client := arkruntime.NewClientWithApiKey(
os.Getenv("ARK_API_KEY"),
// The base URL for model invocation
arkruntime.WithBaseUrl("https://ark.cn-beijing.volces.com/api/v3"),
)
ctx := context.Background()
outputFormat := model.OutputFormatPNG
generateReq := &model.CreateImageGenerationRequest{
Model: "doubao-seedream-5-0-lite-260128",
Prompt: model.NewOptString("保持模特姿势和液态服装的流动形状不变。将服装材质从银色金属改为完全透明的清水(或玻璃)。透过液态水流,可以看到模特的皮肤细节。光影从反射变为折射。"),
Image: model.NewOptCreateImageGenerationRequestImage(model.NewStringArrayCreateImageGenerationRequestImage([]string{"https://arkdocs.tos-cn-beijing.volces.com/images/image-generation/seedream4_5_imageToimage.png"})),
Size: model.NewOptString("2K"),
OutputFormat: model.NewOptOutputFormat(outputFormat),
ResponseFormat: model.NewOptResponseFormat(model.ResponseFormatURL),
Watermark: model.NewOptBool(true),
}
imagesResponse, err := client.GenerateImages(ctx, generateReq)
if err != nil {
fmt.Printf("generate images error: %v\n", err)
return
}
fmt.Printf("%s\n", imagesResponse.Data[0].URL.Or(""))
}
```
**选项:OpenAI**
```Python
import os
from openai import OpenAI
client = OpenAI(
# The base URL for model invocation
base_url="https://ark.cn-beijing.volces.com/api/v3",
# Get API Key: https://ark.volcengine.com/region:cn-beijing/apikey
api_key=os.getenv('ARK_API_KEY'),
)
imagesResponse = client.images.generate(
model="doubao-seedream-5-0-lite-260128",
prompt="保持模特姿势和液态服装的流动形状不变。将服装材质从银色金属改为完全透明的清水(或玻璃)。透过液态水流,可以看到模特的皮肤细节。光影从反射变为折射。",
size="2K",
output_format="png",
response_format="url",
extra_body = {
"image": "https://arkdocs.tos-cn-beijing.volces.com/images/image-generation/seedream4_5_imageToimage.png",
"watermark": True
}
)
print(imagesResponse.data[0].url)
```
## 多图融合(多图输入单图输出)
根据您输入的文本描述和多张参考图片,融合它们的风格、元素等特征来生成新图像。如衣裤鞋帽与模特图融合成穿搭图,人物与风景融合为人物风景图等。
|提示词 |输入图1 |输入图2 |输出 |
|---|---|---|---|
|将图1的服装换为图2的服装 | | | |
**选项:Curl**
```Bash
curl https://ark.cn-beijing.volces.com/api/v3/images/generations \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ARK_API_KEY" \
-d '{
"model": "doubao-seedream-5-0-lite-260128",
"prompt": "将图1的服装换为图2的服装",
"image": ["https://arkdocs.tos-cn-beijing.volces.com/images/image-generation/seedream4_imagesToimage_1.png", "https://arkdocs.tos-cn-beijing.volces.com/images/image-generation/seedream4_5_imagesToimage_2.png"],
"size": "2K",
"output_format":"png",
"watermark": true
}'
```
* 您可按需替换 Model ID。Model ID 查询见 [模型列表](/docs/model-list)。
**选项:Python**
```Python
import os
# Install SDK: python -m pip install --upgrade arkruntime
from arkruntime import Ark
client = Ark(
# The base URL for model invocation
base_url="https://ark.cn-beijing.volces.com/api/v3",
# Get API Key: https://ark.volcengine.com/region:cn-beijing/apikey
api_key=os.getenv('ARK_API_KEY'),
)
imagesResponse = client.images.generate(
# Replace with Model ID
model="doubao-seedream-5-0-lite-260128",
prompt="将图1的服装换为图2的服装",
image=["https://arkdocs.tos-cn-beijing.volces.com/images/image-generation/seedream4_imagesToimage_1.png", "https://arkdocs.tos-cn-beijing.volces.com/images/image-generation/seedream4_5_imagesToimage_2.png"],
size="2K",
output_format="png",
response_format="url",
watermark=True
)
print(imagesResponse.data[0].url)
```
**选项:Java**
```Java
package com.ark.sample;
import com.volcengine.ark.runtime.models.images.*;
import com.volcengine.ark.runtime.service.ArkService;
import okhttp3.ConnectionPool;
import okhttp3.Dispatcher;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
public class ImageGenerationsExample {
public static void main(String[] args) {
String apiKey = System.getenv("ARK_API_KEY");
ConnectionPool connectionPool = new ConnectionPool(5, 1, TimeUnit.SECONDS);
Dispatcher dispatcher = new Dispatcher();
ArkService service = ArkService.builder()
.baseUrl("https://ark.cn-beijing.volces.com/api/v3")
// The base URL for model invocation
.dispatcher(dispatcher)
.connectionPool(connectionPool)
.apiKey(apiKey)
.build();
// CreateImageGenerationRequestImage requires ark-runtime 0.6.0 or later.
CreateImageGenerationRequest generateRequest = CreateImageGenerationRequest.builder()
.model("doubao-seedream-5-0-lite-260128") // Replace with Model ID
.prompt("将图1的服装换为图2的服装")
.image(CreateImageGenerationRequestImage.ofList(Arrays.asList(
"https://arkdocs.tos-cn-beijing.volces.com/images/image-generation/seedream4_imagesToimage_1.png",
"https://arkdocs.tos-cn-beijing.volces.com/images/image-generation/seedream4_5_imagesToimage_2.png"
)))
.size("2K")
.sequentialImageGeneration(SequentialImageGenerationMode.DISABLED)
.outputFormat(OutputFormat.PNG)
.responseFormat(ResponseFormat.URL)
.stream(false)
.watermark(true)
.build();
ImageGenerationResponse imagesResponse = service.generateImages(generateRequest);
System.out.println(imagesResponse.getData().get(0).getUrl());
service.shutdownExecutor();
}
}
```
**选项:Go**
```Go
package main
import (
"context"
"fmt"
"os"
"github.com/volcengine/ark-runtime-go/arkruntime"
model "github.com/volcengine/ark-runtime-go/arkruntime/model/images"
)
func main() {
client := arkruntime.NewClientWithApiKey(
os.Getenv("ARK_API_KEY"),
// The base URL for model invocation
arkruntime.WithBaseUrl("https://ark.cn-beijing.volces.com/api/v3"),
)
ctx := context.Background()
outputFormat := model.OutputFormatPNG
generateReq := &model.CreateImageGenerationRequest{
Model: "doubao-seedream-5-0-lite-260128",
Prompt: model.NewOptString("将图1的服装换为图2的服装"),
Image: model.NewOptCreateImageGenerationRequestImage(model.NewStringArrayCreateImageGenerationRequestImage([]string{
"https://arkdocs.tos-cn-beijing.volces.com/images/image-generation/seedream4_imagesToimage_1.png",
"https://arkdocs.tos-cn-beijing.volces.com/images/image-generation/seedream4_5_imagesToimage_2.png",
})),
Size: model.NewOptString("2K"),
OutputFormat: model.NewOptOutputFormat(outputFormat),
ResponseFormat: model.NewOptResponseFormat(model.ResponseFormatURL),
Watermark: model.NewOptBool(true),
}
imagesResponse, err := client.GenerateImages(ctx, generateReq)
if err != nil {
fmt.Printf("generate images error: %v\n", err)
return
}
fmt.Printf("%s\n", imagesResponse.Data[0].URL.Or(""))
}
```
**选项:OpenAI**
```Python
import os
from openai import OpenAI
client = OpenAI(
# The base URL for model invocation
base_url="https://ark.cn-beijing.volces.com/api/v3",
# Get API Key: https://ark.volcengine.com/region:cn-beijing/apikey
api_key=os.getenv('ARK_API_KEY'),
)
imagesResponse = client.images.generate(
model="doubao-seedream-5-0-lite-260128",
prompt="将图1的服装换为图2的服装",
size="2K",
output_format="png",
response_format="url",
extra_body = {
"image": ["https://arkdocs.tos-cn-beijing.volces.com/images/image-generation/seedream4_imagesToimage_1.png", "https://arkdocs.tos-cn-beijing.volces.com/images/image-generation/seedream4_5_imagesToimage_2.png"],
"watermark": True,
}
)
print(imagesResponse.data[0].url)
```
## 组图输出(多图输出)
> Seedream 5.0 pro / flash 不支持该能力。
支持通过一张或者多张图片和文字信息,生成漫画分镜、品牌视觉等一组内容关联的图片。
需指定参数 **sequential_image_generation** 为`auto`。
### 文生组图
|提示词 |输出(实际会输出4张图片) |
|---|---|
|生成一组电影级科幻写实风的4张影视分镜: | | \
|场景1为宇航员在空间站维修飞船,空间站外部精密机械结构,深邃星空 + 银河背景,宇航员身穿细节完整的白色宇航服,手持专业维修工具,专注检修飞船外壳,中全景构图,侧逆光勾勒轮廓,冷色调科幻光影,空间站灯光点缀,失重环境,金属质感细腻,画面静谧严谨。 | | \
|场景2为:突然遇到陨石带袭击,广角史诗镜头,大量大小不一的陨石高速袭来,陨石表面纹理清晰,带燃烧尾焰,动态模糊体现速度感,陨石带压迫感拉满,飞船与空间站在画面一侧,太空黑暗深邃,光影强烈对比,紧张灾难氛围,画面冲击力十足。 | | \
|场景3为:宇航员紧急躲避,近景动态抓拍,宇航员失重状态下极速侧身躲避,肢体动作张力拉满,伸手抓握固定扶手,背景陨石飞掠而过,轻微镜头晃动增强临场感,宇航服褶皱、管线细节清晰,急促紧张,冷冽光影,主体突出不杂乱。 | | \
|场景4为:受伤后惊险逃回飞船,中近景叙事镜头,宇航员宇航服带轻微破损划痕,略显狼狈却坚毅,踉跄冲向开启的飞船舱门,舱内暖光与太空冷光形成对比,背景陨石逐渐远去,惊险逃生氛围,细节真实,情绪饱满。 | |
**选项:Curl**
```Bash
curl https://ark.cn-beijing.volces.com/api/v3/images/generations \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ARK_API_KEY" \
-d '{
"model": "doubao-seedream-5-0-lite-260128",
"prompt": "生成一组电影级科幻写实风的4张影视分镜:场景1为宇航员在空间站维修飞船,空间站外部精密机械结构,深邃星空 + 银河背景,宇航员身穿细节完整的白色宇航服,手持专业维修工具,专注检修飞船外壳,中全景构图,侧逆光勾勒轮廓,冷色调科幻光影,空间站灯光点缀,失重环境,金属质感细腻,画面静谧严谨。场景2为:突然遇到陨石带袭击,广角史诗镜头,大量大小不一的陨石高速袭来,陨石表面纹理清晰,带燃烧尾焰,动态模糊体现速度感,陨石带压迫感拉满,飞船与空间站在画面一侧,太空黑暗深邃,光影强烈对比,紧张灾难氛围,画面冲击力十足。场景3为:宇航员紧急躲避,近景动态抓拍,宇航员失重状态下极速侧身躲避,肢体动作张力拉满,伸手抓握固定扶手,背景陨石飞掠而过,轻微镜头晃动增强临场感,宇航服褶皱、管线细节清晰,急促紧张,冷冽光影,主体突出不杂乱。场景4为:受伤后惊险逃回飞船,中近景叙事镜头,宇航员宇航服带轻微破损划痕,略显狼狈却坚毅,踉跄冲向开启的飞船舱门,舱内暖光与太空冷光形成对比,背景陨石逐渐远去,惊险逃生氛围,细节真实,情绪饱满。",
"size": "2K",
"sequential_image_generation": "auto",
"sequential_image_generation_options": {
"max_images": 4
},
"stream": false,
"output_format":"png",
"response_format": "url",
"watermark": true
}'
```
* 您可按需替换 Model ID。Model ID 查询见 [模型列表](/docs/model-list)。
**选项:Python**
```Python
import os
# Install SDK: python -m pip install --upgrade arkruntime
from arkruntime import Ark
from arkruntime.types.images import SequentialImageGenerationOptionsParam
client = Ark(
# The base URL for model invocation .
base_url="https://ark.cn-beijing.volces.com/api/v3",
# Get API Key: https://ark.volcengine.com/region:cn-beijing/apikey
api_key=os.getenv('ARK_API_KEY'),
)
imagesResponse = client.images.generate(
# Replace with Model ID
model="doubao-seedream-5-0-lite-260128",
prompt="生成一组电影级科幻写实风的4张影视分镜:场景1为宇航员在空间站维修飞船,空间站外部精密机械结构,深邃星空 + 银河背景,宇航员身穿细节完整的白色宇航服,手持专业维修工具,专注检修飞船外壳,中全景构图,侧逆光勾勒轮廓,冷色调科幻光影,空间站灯光点缀,失重环境,金属质感细腻,画面静谧严谨。场景2为:突然遇到陨石带袭击,广角史诗镜头,大量大小不一的陨石高速袭来,陨石表面纹理清晰,带燃烧尾焰,动态模糊体现速度感,陨石带压迫感拉满,飞船与空间站在画面一侧,太空黑暗深邃,光影强烈对比,紧张灾难氛围,画面冲击力十足。场景3为:宇航员紧急躲避,近景动态抓拍,宇航员失重状态下极速侧身躲避,肢体动作张力拉满,伸手抓握固定扶手,背景陨石飞掠而过,轻微镜头晃动增强临场感,宇航服褶皱、管线细节清晰,急促紧张,冷冽光影,主体突出不杂乱。场景4为:受伤后惊险逃回飞船,中近景叙事镜头,宇航员宇航服带轻微破损划痕,略显狼狈却坚毅,踉跄冲向开启的飞船舱门,舱内暖光与太空冷光形成对比,背景陨石逐渐远去,惊险逃生氛围,细节真实,情绪饱满。",
size="2K",
sequential_image_generation="auto",
sequential_image_generation_options=SequentialImageGenerationOptionsParam(max_images=4),
output_format="png",
response_format="url",
watermark=True
)
# Iterate through all image data
for image in imagesResponse.data:
# Output the current image's URL and size
print(f"URL: {image.url}, Size: {image.size}")
```
**选项:Java**
```Java
package com.ark.sample;
import com.volcengine.ark.runtime.models.images.*;
import com.volcengine.ark.runtime.service.ArkService;
import okhttp3.ConnectionPool;
import okhttp3.Dispatcher;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
public class ImageGenerationsExample {
public static void main(String[] args) {
String apiKey = System.getenv("ARK_API_KEY");
ConnectionPool connectionPool = new ConnectionPool(5, 1, TimeUnit.SECONDS);
Dispatcher dispatcher = new Dispatcher();
ArkService service = ArkService.builder()
.baseUrl("https://ark.cn-beijing.volces.com/api/v3")
// The base URL for model invocation
.dispatcher(dispatcher)
.connectionPool(connectionPool)
.apiKey(apiKey)
.build();
SequentialImageGenerationOptions sequentialImageGenerationOptions = new SequentialImageGenerationOptions();
sequentialImageGenerationOptions.setMaxImages(4);
CreateImageGenerationRequest generateRequest = CreateImageGenerationRequest.builder()
.model("doubao-seedream-5-0-lite-260128") // Replace with Model ID
.prompt("生成一组电影级科幻写实风的4张影视分镜:场景1为宇航员在空间站维修飞船,空间站外部精密机械结构,深邃星空 + 银河背景,宇航员身穿细节完整的白色宇航服,手持专业维修工具,专注检修飞船外壳,中全景构图,侧逆光勾勒轮廓,冷色调科幻光影,空间站灯光点缀,失重环境,金属质感细腻,画面静谧严谨。场景2为:突然遇到陨石带袭击,广角史诗镜头,大量大小不一的陨石高速袭来,陨石表面纹理清晰,带燃烧尾焰,动态模糊体现速度感,陨石带压迫感拉满,飞船与空间站在画面一侧,太空黑暗深邃,光影强烈对比,紧张灾难氛围,画面冲击力十足。场景3为:宇航员紧急躲避,近景动态抓拍,宇航员失重状态下极速侧身躲避,肢体动作张力拉满,伸手抓握固定扶手,背景陨石飞掠而过,轻微镜头晃动增强临场感,宇航服褶皱、管线细节清晰,急促紧张,冷冽光影,主体突出不杂乱。场景4为:受伤后惊险逃回飞船,中近景叙事镜头,宇航员宇航服带轻微破损划痕,略显狼狈却坚毅,踉跄冲向开启的飞船舱门,舱内暖光与太空冷光形成对比,背景陨石逐渐远去,惊险逃生氛围,细节真实,情绪饱满。")
.size("2K")
.sequentialImageGeneration(SequentialImageGenerationMode.AUTO)
.sequentialImageGenerationOptions(sequentialImageGenerationOptions)
.outputFormat(OutputFormat.PNG)
.responseFormat(ResponseFormat.URL)
.stream(false)
.watermark(true)
.build();
ImageGenerationResponse imagesResponse = service.generateImages(generateRequest);
// Iterate through all image data
if (imagesResponse != null && imagesResponse.getData() != null) {
for (int i = 0; i < imagesResponse.getData().size(); i++) {
// Retrieve image information
String url = imagesResponse.getData().get(i).getUrl();
String size = imagesResponse.getData().get(i).getSize();
System.out.printf("Image %d:%n", i + 1);
System.out.printf(" URL: %s%n", url);
System.out.printf(" Size: %s%n", size);
System.out.println();
}
service.shutdownExecutor();
}
}
}
```
**选项:Go**
```Go
package main
import (
"context"
"fmt"
"os"
"github.com/volcengine/ark-runtime-go/arkruntime"
model "github.com/volcengine/ark-runtime-go/arkruntime/model/images"
)
func main() {
client := arkruntime.NewClientWithApiKey(
os.Getenv("ARK_API_KEY"),
// The base URL for model invocation
arkruntime.WithBaseUrl("https://ark.cn-beijing.volces.com/api/v3"),
)
ctx := context.Background()
outputFormat := model.OutputFormatPNG
var sequentialImageGeneration model.SequentialImageGenerationMode = "auto"
maxImages := 4
generateReq := &model.CreateImageGenerationRequest{
Model: "doubao-seedream-5-0-lite-260128",
Prompt: model.NewOptString("生成一组电影级科幻写实风的4张影视分镜:场景1为宇航员在空间站维修飞船,空间站外部精密机械结构,深邃星空 + 银河背景,宇航员身穿细节完整的白色宇航服,手持专业维修工具,专注检修飞船外壳,中全景构图,侧逆光勾勒轮廓,冷色调科幻光影,空间站灯光点缀,失重环境,金属质感细腻,画面静谧严谨。场景2为:突然遇到陨石带袭击,广角史诗镜头,大量大小不一的陨石高速袭来,陨石表面纹理清晰,带燃烧尾焰,动态模糊体现速度感,陨石带压迫感拉满,飞船与空间站在画面一侧,太空黑暗深邃,光影强烈对比,紧张灾难氛围,画面冲击力十足。场景3为:宇航员紧急躲避,近景动态抓拍,宇航员失重状态下极速侧身躲避,肢体动作张力拉满,伸手抓握固定扶手,背景陨石飞掠而过,轻微镜头晃动增强临场感,宇航服褶皱、管线细节清晰,急促紧张,冷冽光影,主体突出不杂乱。场景4为:受伤后惊险逃回飞船,中近景叙事镜头,宇航员宇航服带轻微破损划痕,略显狼狈却坚毅,踉跄冲向开启的飞船舱门,舱内暖光与太空冷光形成对比,背景陨石逐渐远去,惊险逃生氛围,细节真实,情绪饱满。"),
Size: model.NewOptString("2K"),
OutputFormat: model.NewOptOutputFormat(outputFormat),
ResponseFormat: model.NewOptResponseFormat(model.ResponseFormatURL),
Watermark: model.NewOptBool(true),
SequentialImageGeneration: model.NewOptSequentialImageGenerationMode(sequentialImageGeneration),
SequentialImageGenerationOptions: model.NewOptSequentialImageGenerationOptions(model.SequentialImageGenerationOptions{
MaxImages: model.NewOptInt32(int32(maxImages)),
}),
}
resp, err := client.GenerateImages(ctx, generateReq)
if err != nil {
fmt.Printf("call GenerateImages error: %v\n", err)
return
}
if resp.Error.IsSet() {
fmt.Printf("API returned error: %s - %s\n", resp.Error.Value.Code, resp.Error.Value.Message)
return
}
// Output the generated image information
fmt.Printf("Generated %d images:\n", len(resp.Data))
for i, image := range resp.Data {
var url string
if image.URL.IsSet() {
url = image.URL.Or("")
} else {
url = "N/A"
}
fmt.Printf("Image %d: Size: %s, URL: %s\n", i+1, image.Size.Or(""), url)
}
}
```
**选项:OpenAI**
```Python
import os
from openai import OpenAI
client = OpenAI(
# The base URL for model invocation .
base_url="https://ark.cn-beijing.volces.com/api/v3",
# Get API Key: https://ark.volcengine.com/region:cn-beijing/apikey
api_key=os.getenv('ARK_API_KEY'),
)
imagesResponse = client.images.generate(
model="doubao-seedream-5-0-lite-260128",
prompt="生成一组电影级科幻写实风的4张影视分镜:场景1为宇航员在空间站维修飞船,空间站外部精密机械结构,深邃星空 + 银河背景,宇航员身穿细节完整的白色宇航服,手持专业维修工具,专注检修飞船外壳,中全景构图,侧逆光勾勒轮廓,冷色调科幻光影,空间站灯光点缀,失重环境,金属质感细腻,画面静谧严谨。场景2为:突然遇到陨石带袭击,广角史诗镜头,大量大小不一的陨石高速袭来,陨石表面纹理清晰,带燃烧尾焰,动态模糊体现速度感,陨石带压迫感拉满,飞船与空间站在画面一侧,太空黑暗深邃,光影强烈对比,紧张灾难氛围,画面冲击力十足。场景3为:宇航员紧急躲避,近景动态抓拍,宇航员失重状态下极速侧身躲避,肢体动作张力拉满,伸手抓握固定扶手,背景陨石飞掠而过,轻微镜头晃动增强临场感,宇航服褶皱、管线细节清晰,急促紧张,冷冽光影,主体突出不杂乱。场景4为:受伤后惊险逃回飞船,中近景叙事镜头,宇航员宇航服带轻微破损划痕,略显狼狈却坚毅,踉跄冲向开启的飞船舱门,舱内暖光与太空冷光形成对比,背景陨石逐渐远去,惊险逃生氛围,细节真实,情绪饱满。",
size="2K",
output_format="png",
response_format="url",
extra_body={
"watermark": True,
"sequential_image_generation": "auto",
"sequential_image_generation_options": {
"max_images": 4
},
},
)
# Iterate through all image data
for image in imagesResponse.data:
# Output the current image's URL and size
print(f"URL: {image.url}, Size: {image.size}")
```
### 单张图生组图
|提示词 |输入图 |输出(实际会输出4张图片) |
|---|---|---|
|参考这个LOGO,做一套户外运动品牌视觉设计,品牌名称为“GREEN”,包括包装袋、帽子、卡片、挂绳等。绿色视觉主色调,趣味、简约现代风格。 | | |
**选项:Curl**
```Bash
curl https://ark.cn-beijing.volces.com/api/v3/images/generations \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ARK_API_KEY" \
-d '{
"model": "doubao-seedream-5-0-lite-260128",
"prompt": "参考这个LOGO,做一套户外运动品牌视觉设计,品牌名称为“GREEN”,包括包装袋、帽子、卡片、挂绳等。绿色视觉主色调,趣味、简约现代风格",
"image": "https://arkdocs.tos-cn-beijing.volces.com/images/image-generation/seedream4_imageToimages.png",
"size": "2K",
"sequential_image_generation": "auto",
"sequential_image_generation_options": {
"max_images": 4
},
"stream": false,
"output_format":"png",
"response_format": "url",
"watermark": true
}'
```
* 您可按需替换 Model ID。Model ID 查询见 [模型列表](/docs/model-list)。
**选项:Python**
```Python
import os
# Install SDK: python -m pip install --upgrade arkruntime
from arkruntime import Ark
from arkruntime.types.images import SequentialImageGenerationOptionsParam
client = Ark(
# The base URL for model invocation .
base_url="https://ark.cn-beijing.volces.com/api/v3",
# Get API Key: https://ark.volcengine.com/region:cn-beijing/apikey
api_key=os.getenv('ARK_API_KEY'),
)
imagesResponse = client.images.generate(
# Replace with Model ID .
model="doubao-seedream-5-0-lite-260128",
prompt="参考这个LOGO,做一套户外运动品牌视觉设计,品牌名称为“GREEN”,包括包装袋、帽子、卡片、挂绳等。绿色视觉主色调,趣味、简约现代风格",
image="https://arkdocs.tos-cn-beijing.volces.com/images/image-generation/seedream4_imageToimages.png",
size="2K",
sequential_image_generation="auto",
sequential_image_generation_options=SequentialImageGenerationOptionsParam(max_images=4),
output_format="png",
response_format="url",
watermark=True
)
# Iterate through all image data
for image in imagesResponse.data:
# Output the current image's URL and size
print(f"URL: {image.url}, Size: {image.size}")
```
**选项:Java**
```Java
package com.ark.sample;
import com.volcengine.ark.runtime.models.images.*;
import com.volcengine.ark.runtime.service.ArkService;
import okhttp3.ConnectionPool;
import okhttp3.Dispatcher;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
public class ImageGenerationsExample {
public static void main(String[] args) {
String apiKey = System.getenv("ARK_API_KEY");
ConnectionPool connectionPool = new ConnectionPool(5, 1, TimeUnit.SECONDS);
Dispatcher dispatcher = new Dispatcher();
ArkService service = ArkService.builder()
.baseUrl("https://ark.cn-beijing.volces.com/api/v3")
// The base URL for model invocation
.dispatcher(dispatcher)
.connectionPool(connectionPool)
.apiKey(apiKey)
.build();
SequentialImageGenerationOptions sequentialImageGenerationOptions = new SequentialImageGenerationOptions();
sequentialImageGenerationOptions.setMaxImages(4);
// CreateImageGenerationRequestImage requires ark-runtime 0.6.0 or later.
CreateImageGenerationRequest generateRequest = CreateImageGenerationRequest.builder()
.model("doubao-seedream-5-0-lite-260128") // Replace with Model ID
.prompt("参考这个LOGO,做一套户外运动品牌视觉设计,品牌名称为“GREEN”,包括包装袋、帽子、卡片、挂绳等。绿色视觉主色调,趣味、简约现代风格")
.image(CreateImageGenerationRequestImage.ofString("https://arkdocs.tos-cn-beijing.volces.com/images/image-generation/seedream4_imageToimages.png"))
.size("2K")
.sequentialImageGeneration(SequentialImageGenerationMode.AUTO)
.sequentialImageGenerationOptions(sequentialImageGenerationOptions)
.outputFormat(OutputFormat.PNG)
.responseFormat(ResponseFormat.URL)
.stream(false)
.watermark(true)
.build();
ImageGenerationResponse imagesResponse = service.generateImages(generateRequest);
// Iterate through all image data
if (imagesResponse != null && imagesResponse.getData() != null) {
for (int i = 0; i < imagesResponse.getData().size(); i++) {
// Retrieve image information
String url = imagesResponse.getData().get(i).getUrl();
String size = imagesResponse.getData().get(i).getSize();
System.out.printf("Image %d:%n", i + 1);
System.out.printf(" URL: %s%n", url);
System.out.printf(" Size: %s%n", size);
System.out.println();
}
service.shutdownExecutor();
}
}
}
```
**选项:Go**
```Go
package main
import (
"context"
"fmt"
"os"
"github.com/volcengine/ark-runtime-go/arkruntime"
model "github.com/volcengine/ark-runtime-go/arkruntime/model/images"
)
func main() {
client := arkruntime.NewClientWithApiKey(
os.Getenv("ARK_API_KEY"),
// The base URL for model invocation
arkruntime.WithBaseUrl("https://ark.cn-beijing.volces.com/api/v3"),
)
ctx := context.Background()
outputFormat := model.OutputFormatPNG
var sequentialImageGeneration model.SequentialImageGenerationMode = "auto"
maxImages := 4
generateReq := &model.CreateImageGenerationRequest{
Model: "doubao-seedream-5-0-lite-260128",
Prompt: model.NewOptString("参考这个LOGO,做一套户外运动品牌视觉设计,品牌名称为“GREEN”,包括包装袋、帽子、卡片、挂绳等。绿色视觉主色调,趣味、简约现代风格"),
Image: model.NewOptCreateImageGenerationRequestImage(model.NewStringArrayCreateImageGenerationRequestImage([]string{"https://arkdocs.tos-cn-beijing.volces.com/images/image-generation/seedream4_imageToimages.png"})),
Size: model.NewOptString("2K"),
OutputFormat: model.NewOptOutputFormat(outputFormat),
ResponseFormat: model.NewOptResponseFormat(model.ResponseFormatURL),
Watermark: model.NewOptBool(true),
SequentialImageGeneration: model.NewOptSequentialImageGenerationMode(sequentialImageGeneration),
SequentialImageGenerationOptions: model.NewOptSequentialImageGenerationOptions(model.SequentialImageGenerationOptions{
MaxImages: model.NewOptInt32(int32(maxImages)),
}),
}
resp, err := client.GenerateImages(ctx, generateReq)
if err != nil {
fmt.Printf("call GenerateImages error: %v\n", err)
return
}
if resp.Error.IsSet() {
fmt.Printf("API returned error: %s - %s\n", resp.Error.Value.Code, resp.Error.Value.Message)
return
}
// Output the generated image information
fmt.Printf("Generated %d images:\n", len(resp.Data))
for i, image := range resp.Data {
var url string
if image.URL.IsSet() {
url = image.URL.Or("")
} else {
url = "N/A"
}
fmt.Printf("Image %d: Size: %s, URL: %s\n", i+1, image.Size.Or(""), url)
}
}
```
* 您可按需替换 Model ID。Model ID 查询见 [模型列表](/docs/model-list)。
**选项:OpenAI**
```Python
import os
from openai import OpenAI
client = OpenAI(
# The base URL for model invocation
base_url="https://ark.cn-beijing.volces.com/api/v3",
# Get API Key: https://ark.volcengine.com/region:cn-beijing/apikey
api_key=os.getenv('ARK_API_KEY'),
)
imagesResponse = client.images.generate(
model="doubao-seedream-5-0-lite-260128",
prompt="参考这个LOGO,做一套户外运动品牌视觉设计,品牌名称为“GREEN”,包括包装袋、帽子、卡片、挂绳等。绿色视觉主色调,趣味、简约现代风格",
size="2K",
output_format="png",
response_format="url",
extra_body={
"image": "https://arkdocs.tos-cn-beijing.volces.com/images/image-generation/seedream4_imageToimages.png",
"watermark": True,
"sequential_image_generation": "auto",
"sequential_image_generation_options": {
"max_images": 4
},
}
)
# Iterate through all image data
for image in imagesResponse.data:
# Output the current image's URL and size
print(f"URL: {image.url}, Size: {image.size}")
```
### 多参考图生组图
|提示词 |输入图1 |输入图2 |输出(实际会输出3张图片) |
|---|---|---|---|
|生成3张女孩和奶牛玩偶在游乐园开心地坐过山车的图片,涵盖早晨、中午、晚上 | | | |
**选项:Curl**
```Bash
curl https://ark.cn-beijing.volces.com/api/v3/images/generations \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ARK_API_KEY" \
-d '{
"model": "doubao-seedream-5-0-lite-260128",
"prompt": "生成3张女孩和奶牛玩偶在游乐园开心地坐过山车的图片,涵盖早晨、中午、晚上",
"image": ["https://arkdocs.tos-cn-beijing.volces.com/images/image-generation/seedream4_imagesToimages_1.png", "https://arkdocs.tos-cn-beijing.volces.com/images/image-generation/seedream4_imagesToimages_2.png"],
"sequential_image_generation": "auto",
"sequential_image_generation_options": {
"max_images": 3
},
"size": "2K",
"output_format":"png",
"watermark": true
}'
```
* 您可按需替换 Model ID。Model ID 查询见 [模型列表](/docs/model-list)。
**选项:Python**
```Python
import os
# Install SDK: python -m pip install --upgrade arkruntime
from arkruntime import Ark
from arkruntime.types.images import SequentialImageGenerationOptionsParam
client = Ark(
# The base URL for model invocation
base_url="https://ark.cn-beijing.volces.com/api/v3",
# Get API Key: https://ark.volcengine.com/region:cn-beijing/apikey
api_key=os.getenv('ARK_API_KEY'),
)
imagesResponse = client.images.generate(
# Replace with Model ID
model="doubao-seedream-5-0-lite-260128",
prompt="生成3张女孩和奶牛玩偶在游乐园开心地坐过山车的图片,涵盖早晨、中午、晚上",
image=["https://arkdocs.tos-cn-beijing.volces.com/images/image-generation/seedream4_imagesToimages_1.png", "https://arkdocs.tos-cn-beijing.volces.com/images/image-generation/seedream4_imagesToimages_2.png"],
size="2K",
sequential_image_generation="auto",
sequential_image_generation_options=SequentialImageGenerationOptionsParam(max_images=3),
output_format="png",
response_format="url",
watermark=True
)
# Iterate through all image data
for image in imagesResponse.data:
# Output the current image's URL and size
print(f"URL: {image.url}, Size: {image.size}")
```
**选项:Java**
```Java
package com.ark.sample;
import com.volcengine.ark.runtime.models.images.*;
import com.volcengine.ark.runtime.service.ArkService;
import okhttp3.ConnectionPool;
import okhttp3.Dispatcher;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
public class ImageGenerationsExample {
public static void main(String[] args) {
String apiKey = System.getenv("ARK_API_KEY");
ConnectionPool connectionPool = new ConnectionPool(5, 1, TimeUnit.SECONDS);
Dispatcher dispatcher = new Dispatcher();
ArkService service = ArkService.builder()
.baseUrl("https://ark.cn-beijing.volces.com/api/v3")
// The base URL for model invocation
.dispatcher(dispatcher)
.connectionPool(connectionPool)
.apiKey(apiKey)
.build();
SequentialImageGenerationOptions sequentialImageGenerationOptions = new SequentialImageGenerationOptions();
sequentialImageGenerationOptions.setMaxImages(3);
// CreateImageGenerationRequestImage requires ark-runtime 0.6.0 or later.
CreateImageGenerationRequest generateRequest = CreateImageGenerationRequest.builder()
.model("doubao-seedream-5-0-lite-260128") // Replace with Model ID
.prompt("生成3张女孩和奶牛玩偶在游乐园开心地坐过山车的图片,涵盖早晨、中午、晚上")
.image(CreateImageGenerationRequestImage.ofList(Arrays.asList(
"https://arkdocs.tos-cn-beijing.volces.com/images/image-generation/seedream4_imagesToimages_1.png",
"https://arkdocs.tos-cn-beijing.volces.com/images/image-generation/seedream4_imagesToimages_2.png"
)))
.outputFormat(OutputFormat.PNG)
.size("2K")
.sequentialImageGeneration(SequentialImageGenerationMode.AUTO)
.sequentialImageGenerationOptions(sequentialImageGenerationOptions)
.responseFormat(ResponseFormat.URL)
.stream(false)
.watermark(true)
.build();
ImageGenerationResponse imagesResponse = service.generateImages(generateRequest);
// Iterate through all image data
if (imagesResponse != null && imagesResponse.getData() != null) {
for (int i = 0; i < imagesResponse.getData().size(); i++) {
// Retrieve image information
String url = imagesResponse.getData().get(i).getUrl();
String size = imagesResponse.getData().get(i).getSize();
System.out.printf("Image %d:%n", i + 1);
System.out.printf(" URL: %s%n", url);
System.out.printf(" Size: %s%n", size);
System.out.println();
}
service.shutdownExecutor();
}
}
}
```
**选项:Go**
```Go
package main
import (
"context"
"fmt"
"os"
"github.com/volcengine/ark-runtime-go/arkruntime"
model "github.com/volcengine/ark-runtime-go/arkruntime/model/images"
)
func main() {
client := arkruntime.NewClientWithApiKey(
os.Getenv("ARK_API_KEY"),
// The base URL for model invocation
arkruntime.WithBaseUrl("https://ark.cn-beijing.volces.com/api/v3"),
)
ctx := context.Background()
outputFormat := model.OutputFormatPNG
var sequentialImageGeneration model.SequentialImageGenerationMode = "auto"
maxImages := 3
generateReq := &model.CreateImageGenerationRequest{
Model: "doubao-seedream-5-0-lite-260128",
Prompt: model.NewOptString("生成3张女孩和奶牛玩偶在游乐园开心地坐过山车的图片,涵盖早晨、中午、晚上"),
Image: model.NewOptCreateImageGenerationRequestImage(model.NewStringArrayCreateImageGenerationRequestImage([]string{
"https://arkdocs.tos-cn-beijing.volces.com/images/image-generation/seedream4_imagesToimages_1.png",
"https://arkdocs.tos-cn-beijing.volces.com/images/image-generation/seedream4_imagesToimages_2.png",
})),
Size: model.NewOptString("2K"),
OutputFormat: model.NewOptOutputFormat(outputFormat),
ResponseFormat: model.NewOptResponseFormat(model.ResponseFormatURL),
Watermark: model.NewOptBool(true),
SequentialImageGeneration: model.NewOptSequentialImageGenerationMode(sequentialImageGeneration),
SequentialImageGenerationOptions: model.NewOptSequentialImageGenerationOptions(model.SequentialImageGenerationOptions{
MaxImages: model.NewOptInt32(int32(maxImages)),
}),
}
resp, err := client.GenerateImages(ctx, generateReq)
if err != nil {
fmt.Printf("call GenerateImages error: %v\n", err)
return
}
if resp.Error.IsSet() {
fmt.Printf("API returned error: %s - %s\n", resp.Error.Value.Code, resp.Error.Value.Message)
return
}
// Output the generated image information
fmt.Printf("Generated %d images:\n", len(resp.Data))
for i, image := range resp.Data {
var url string
if image.URL.IsSet() {
url = image.URL.Or("")
} else {
url = "N/A"
}
fmt.Printf("Image %d: Size: %s, URL: %s\n", i+1, image.Size.Or(""), url)
}
}
```
**选项:OpenAI**
```Python
import os
from openai import OpenAI
client = OpenAI(
# The base URL for model invocation
base_url="https://ark.cn-beijing.volces.com/api/v3",
# Get API Key: https://ark.volcengine.com/region:cn-beijing/apikey
api_key=os.getenv('ARK_API_KEY'),
)
imagesResponse = client.images.generate(
model="doubao-seedream-5-0-lite-260128",
prompt="生成3张女孩和奶牛玩偶在游乐园开心地坐过山车的图片,涵盖早晨、中午、晚上",
size="2K",
output_format="png",
response_format="url",
extra_body={
"image": ["https://arkdocs.tos-cn-beijing.volces.com/images/image-generation/seedream4_imagesToimages_1.png", "https://arkdocs.tos-cn-beijing.volces.com/images/image-generation/seedream4_imagesToimages_2.png"],
"watermark": True,
"sequential_image_generation": "auto",
"sequential_image_generation_options": {
"max_images": 3
},
}
)
# Iterate through all image data
for image in imagesResponse.data:
# Output the current image's URL and size
print(f"URL: {image.url}, Size: {image.size}")
```
## **提示词建议**
* 建议用**简洁连贯**的自然语言写明 **主体 + 行为 + 环境**,若对画面美学有要求,可用自然语言或短语补充 **风格**、**色彩**、**光影**、**构图** 等美学元素。详情可参见 [Seedream 4.0-5.0 提示词指南](/docs/seedream-4-0-5-0-prompt-guide)。
* 文本提示词(prompt)建议不超过300个汉字或600个英文单词。字数过多信息容易分散,模型可能因此忽略细节,只关注重点,造成图片缺失部分元素。
# 进阶使用
## 联网搜索
> Seedream 5.0 pro / flash 不支持该能力。
Seedream 5.0 lite 支持调用联网搜索工具,通过配置 tools.**type** 参数为 `web_search` 即可开启联网搜索。
* 开启联网搜索后,模型会根据用户的提示词自主判断是否搜索互联网内容(如商品、天气等),提升生成图片的时效性,但也会增加一定的时延。
* 实际搜索次数可通过字段 usage.tool_usage.**web_search** 查询,如果为 **0** 表示未搜索。
|提示词 |输出 |
|---|---|
|制作一张上海未来5日的天气预报图,采用现代扁平化插画风格,清晰展示每日天气、温度和穿搭建议。 整体为横向排版,标题为“上海未来5日天气预报”,包含5个等宽的垂直卡片,从左到右依次排列。 整体风格为现代、干净、友好的扁平化矢量插画风格,线条清晰,色彩柔和。人物形象采用年轻男女的卡通插画,表情自然,姿态放松,服装细节清晰。 | |
**选项:Curl**
```Bash
curl https://ark.cn-beijing.volces.com/api/v3/images/generations \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ARK_API_KEY" \
-d '{
"model": "doubao-seedream-5-0-lite-260128",
"prompt": "制作一张上海未来5日的天气预报图,采用现代扁平化插画风格,清晰展示每日天气、温度和穿搭建议。整体为横向排版,标题为“上海未来5日天气预报”,包含5个等宽的垂直卡片,从左到右依次排列。 整体风格为现代、干净、友好的扁平化矢量插画风格,线条清晰,色彩柔和。人物形象采用年轻男女的卡通插画,表情自然,姿态放松,服装细节清晰。",
"size": "2048x2048",
"tools": [
{
"type": "web_search"
}
],
"output_format":"png",
"response_format": "url",
"watermark": true
}'
```
* 您可按需替换 Model ID。Model ID 查询见 [模型列表](/docs/model-list)。
**选项:Python**
```Python
import os
# Install SDK: python -m pip install --upgrade arkruntime
from arkruntime import Ark
from arkruntime.types.images import ToolParam
client = Ark(
# The base URL for model invocation
base_url="https://ark.cn-beijing.volces.com/api/v3",
# Get API Key: https://ark.volcengine.com/region:cn-beijing/apikey
api_key=os.getenv('ARK_API_KEY'),
)
imagesResponse = client.images.generate(
# Replace with Model ID
model="doubao-seedream-5-0-lite-260128",
prompt="制作一张上海未来5日的天气预报图,采用现代扁平化插画风格,清晰展示每日天气、温度和穿搭建议。 整体为横向排版,标题为“上海未来5日天气预报”,包含5个等宽的垂直卡片,从左到右依次排列。 整体风格为现代、干净、友好的扁平化矢量插画风格,线条清晰,色彩柔和。人物形象采用年轻男女的卡通插画,表情自然,姿态放松,服装细节清晰。",
size="2048x2048",
output_format="png",
response_format="url",
tools=[ToolParam(type="web_search")],
watermark=True,
)
print(imagesResponse.data[0].url)
```
**选项:Java**
```Java
package com.ark.sample;
import com.volcengine.ark.runtime.models.images.*;
import com.volcengine.ark.runtime.service.ArkService;
import okhttp3.ConnectionPool;
import okhttp3.Dispatcher;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
public class ImageGenerationsExample {
public static void main(String[] args) {
// Get API Key: https://ark.volcengine.com/region:cn-beijing/apikey
String apiKey = System.getenv("ARK_API_KEY");
ConnectionPool connectionPool = new ConnectionPool(5, 1, TimeUnit.SECONDS);
Dispatcher dispatcher = new Dispatcher();
ArkService service = ArkService.builder()
.baseUrl("https://ark.cn-beijing.volces.com/api/v3")
// The base URL for model invocation
.dispatcher(dispatcher)
.connectionPool(connectionPool)
.apiKey(apiKey)
.build();
// Create ContentGenerationTool
Tool contentGenerationTool = new Tool();
contentGenerationTool.setType(ToolType.WEB_SEARCH);
// Create list of tools
List tools = Arrays.asList(contentGenerationTool);
CreateImageGenerationRequest generateRequest = CreateImageGenerationRequest.builder()
.model("doubao-seedream-5-0-lite-260128") // Replace with Model ID
.prompt("制作一张上海未来5日的天气预报图,采用现代扁平化插画风格,清晰展示每日天气、温度和穿搭建议。 整体为横向排版,标题为“上海未来5日天气预报”,包含5个等宽的垂直卡片,从左到右依次排列。 整体风格为现代、干净、友好的扁平化矢量插画风格,线条清晰,色彩柔和。人物形象采用年轻男女的卡通插画,表情自然,姿态放松,服装细节清晰。")
.size("2048x2048")
.outputFormat(OutputFormat.PNG)
.responseFormat(ResponseFormat.URL)
.watermark(true)
.tools(tools)
.build();
ImageGenerationResponse imagesResponse = service.generateImages(generateRequest);
System.out.println(imagesResponse.getData().get(0).getUrl());
service.shutdownExecutor();
}
}
```
**选项:Go**
```Go
package main
import (
"context"
"fmt"
"os"
"github.com/volcengine/ark-runtime-go/arkruntime"
model "github.com/volcengine/ark-runtime-go/arkruntime/model/images"
)
func main() {
client := arkruntime.NewClientWithApiKey(
// Get API Key: https://ark.volcengine.com/region:cn-beijing/apikey
os.Getenv("ARK_API_KEY"),
// The base URL for model invocation
arkruntime.WithBaseUrl("https://ark.cn-beijing.volces.com/api/v3"),
)
ctx := context.Background()
outputFormat := model.OutputFormatPNG
generateReq := &model.CreateImageGenerationRequest{
Model: "doubao-seedream-5-0-lite-260128", // Replace with Model ID
Prompt: model.NewOptString("制作一张上海未来5日的天气预报图,采用现代扁平化插画风格,清晰展示每日天气、温度和穿搭建议。 整体为横向排版,标题为“上海未来5日天气预报”,包含5个等宽的垂直卡片,从左到右依次排列。 整体风格为现代、干净、友好的扁平化矢量插画风格,线条清晰,色彩柔和。人物形象采用年轻男女的卡通插画,表情自然,姿态放松,服装细节清晰。"),
Size: model.NewOptString("2048x2048"),
OutputFormat: model.NewOptOutputFormat(outputFormat),
ResponseFormat: model.NewOptResponseFormat(model.ResponseFormatURL),
Watermark: model.NewOptBool(true),
Tools: []model.Tool{
{
Type: model.ToolTypeWebSearch,
},
},
}
imagesResponse, err := client.GenerateImages(ctx, generateReq)
if err != nil {
fmt.Printf("generate images error: %v\n", err)
return
}
fmt.Printf("%s\n", imagesResponse.Data[0].URL.Or(""))
}
```
## 流式输出
> Seedream 5.0 pro / flash 不支持该能力。
模型支持流式图像生成,当生成完任一图片后即返回结果,让您能更快浏览到生成的图像,改善等待体验。
通过配置 **stream** 参数为`true`,即可开启流式输出模式。

**选项:Curl**
```Bash
curl https://ark.cn-beijing.volces.com/api/v3/images/generations \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ARK_API_KEY" \
-d '{
"model": "doubao-seedream-5-0-lite-260128",
"prompt": "参考图1,生成四图片,图中人物分别带着墨镜,骑着摩托,带着帽子,拿着棒棒糖",
"image": "https://arkdocs.tos-cn-beijing.volces.com/images/image-generation/seedream4_imageToimages_1.png",
"sequential_image_generation": "auto",
"sequential_image_generation_options": {
"max_images": 4
},
"size": "2K",
"stream": true,
"output_format":"png",
"watermark": true
}'
```
* 您可按需替换 Model ID。Model ID 查询见 [模型列表](/docs/model-list)。
**选项:Python**
```Python
import os
# Install SDK: python -m pip install --upgrade arkruntime
from arkruntime import Ark
from arkruntime.types.images import SequentialImageGenerationOptionsParam
client = Ark(
# The base URL for model invocation
base_url="https://ark.cn-beijing.volces.com/api/v3",
# Get API Key: https://ark.volcengine.com/region:cn-beijing/apikey
api_key=os.getenv('ARK_API_KEY'),
)
if __name__ == "__main__":
stream = client.images.generate(
# Replace with Model ID
model="doubao-seedream-5-0-lite-260128",
prompt="参考图1,生成四图片,图中人物分别带着墨镜,骑着摩托,带着帽子,拿着棒棒糖",
image="https://arkdocs.tos-cn-beijing.volces.com/images/image-generation/seedream4_imageToimages_1.png",
size="2K",
sequential_image_generation="auto",
sequential_image_generation_options=SequentialImageGenerationOptionsParam(max_images=4),
output_format="png",
response_format="url",
stream=True,
watermark=True
)
for event in stream:
if event is None:
continue
if event.type == "image_generation.partial_failed":
print(f"Stream generate images error: {event.error}")
if event.error is not None and event.error.code.equal("InternalServiceError"):
break
elif event.type == "image_generation.partial_succeeded":
if event.error is None and event.url:
print(f"recv.Size: {event.size}, recv.Url: {event.url}")
elif event.type == "image_generation.completed":
if event.error is None:
print("Final completed event:")
print("recv.Usage:", event.usage)
elif event.type == "image_generation.partial_image":
print(f"Partial image index={event.partial_image_index}, size={len(event.b64_json)}")
```
**选项:Java**
```Java
package com.ark.sample;
import com.volcengine.ark.runtime.models.images.*;
import com.volcengine.ark.runtime.service.ArkService;
import okhttp3.ConnectionPool;
import okhttp3.Dispatcher;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
public class ImageGenerationsExample {
public static void main(String[] args) {
String apiKey = System.getenv("ARK_API_KEY");
ConnectionPool connectionPool = new ConnectionPool(5, 1, TimeUnit.SECONDS);
Dispatcher dispatcher = new Dispatcher();
ArkService service = ArkService.builder()
.baseUrl("https://ark.cn-beijing.volces.com/api/v3")
// The base URL for model invocation
.dispatcher(dispatcher)
.connectionPool(connectionPool)
.apiKey(apiKey)
.build();
SequentialImageGenerationOptions sequentialImageGenerationOptions = new SequentialImageGenerationOptions();
sequentialImageGenerationOptions.setMaxImages(4);
// CreateImageGenerationRequestImage requires ark-runtime 0.6.0 or later.
CreateImageGenerationRequest generateRequest = CreateImageGenerationRequest.builder()
.model("doubao-seedream-5-0-lite-260128") //Replace with Model ID .
.prompt("参考图1,生成四图片,图中人物分别带着墨镜,骑着摩托,带着帽子,拿着棒棒糖")
.image(CreateImageGenerationRequestImage.ofString("https://arkdocs.tos-cn-beijing.volces.com/images/image-generation/seedream4_imageToimages_1.png"))
.size("2K")
.sequentialImageGeneration(SequentialImageGenerationMode.AUTO)
.sequentialImageGenerationOptions(sequentialImageGenerationOptions)
.outputFormat(OutputFormat.PNG)
.responseFormat(ResponseFormat.URL)
.stream(true)
.watermark(true)
.build();
service.streamGenerateImages(generateRequest)
.doOnError(Throwable::printStackTrace)
.blockingForEach(
choice -> {
if (choice == null) return;
if (ImageGenerationStreamEventType.IMAGE_GENERATION_PARTIAL_FAILED.equals(choice.getType())) {
if (choice.getError() != null) {
System.err.println("Stream generate images error: " + choice.getError());
if (choice.getError().getCode() != null && choice.getError().getCode().equals("InternalServiceError")) {
throw new RuntimeException("Server error, terminating stream.");
}
}
}
else if (ImageGenerationStreamEventType.IMAGE_GENERATION_PARTIAL_SUCCEEDED.equals(choice.getType())) {
if (choice.getError() == null && choice.getUrl() != null && !choice.getUrl().isEmpty()) {
System.out.printf("recv.Size: %s, recv.Url: %s%n", choice.getSize(), choice.getUrl());
}
}
else if (ImageGenerationStreamEventType.IMAGE_GENERATION_COMPLETED.equals(choice.getType())) {
if (choice.getError() == null && choice.getUsage() != null) {
System.out.println("recv.Usage: " + choice.getUsage().toString());
}
}
}
);
service.shutdownExecutor();
}
}
```
**选项:Go**
```Go
package main
import (
"context"
"fmt"
"io"
"os"
"strings"
"github.com/volcengine/ark-runtime-go/arkruntime"
model "github.com/volcengine/ark-runtime-go/arkruntime/model/images"
)
func main() {
client := arkruntime.NewClientWithApiKey(
os.Getenv("ARK_API_KEY"),
// The base URL for model invocation
arkruntime.WithBaseUrl("https://ark.cn-beijing.volces.com/api/v3"),
)
ctx := context.Background()
outputFormat := model.OutputFormatPNG
var sequentialImageGeneration model.SequentialImageGenerationMode = "auto"
maxImages := 4
generateReq := &model.CreateImageGenerationRequest{
Model: "doubao-seedream-5-0-lite-260128",
Prompt: model.NewOptString("参考图1,生成四图片,图中人物分别带着墨镜,骑着摩托,带着帽子,拿着棒棒糖"),
Image: model.NewOptCreateImageGenerationRequestImage(model.NewStringArrayCreateImageGenerationRequestImage([]string{"https://arkdocs.tos-cn-beijing.volces.com/images/image-generation/seedream4_imageToimages_1.png"})),
Size: model.NewOptString("2K"),
OutputFormat: model.NewOptOutputFormat(outputFormat),
ResponseFormat: model.NewOptResponseFormat(model.ResponseFormatURL),
Watermark: model.NewOptBool(true),
SequentialImageGeneration: model.NewOptSequentialImageGenerationMode(sequentialImageGeneration),
SequentialImageGenerationOptions: model.NewOptSequentialImageGenerationOptions(model.SequentialImageGenerationOptions{
MaxImages: model.NewOptInt32(int32(maxImages)),
}),
}
stream, err := client.GenerateImagesStreaming(ctx, generateReq)
if err != nil {
fmt.Printf("call GenerateImagesStreaming error: %v\n", err)
return
}
defer stream.Close()
for {
recv, err := stream.Recv()
if err == io.EOF {
break
}
if err != nil {
fmt.Printf("Stream generate images error: %v\n", err)
break
}
if recv.Type == model.ImageGenerationStreamEventTypeImageGenerationPartialFailed {
fmt.Printf("Stream generate images error: %v\n", recv.Error)
if strings.EqualFold(recv.Error.Value.Code, "InternalServiceError") {
break
}
}
if recv.Type == model.ImageGenerationStreamEventTypeImageGenerationPartialSucceeded {
if !recv.Error.IsSet() && recv.URL.IsSet() {
fmt.Printf("recv.Size: %s, recv.Url: %s\n", recv.Size.Or(""), recv.URL.Or(""))
}
}
if recv.Type == model.ImageGenerationStreamEventTypeImageGenerationCompleted {
if !recv.Error.IsSet() {
fmt.Printf("recv.Usage: %v\n", recv.Usage.Or(model.Usage{}))
}
}
}
}
```
**选项:OpenAI**
```Python
import os
from openai import OpenAI
client = OpenAI(
# The base URL for model invocation .
base_url="https://ark.cn-beijing.volces.com/api/v3",
# Get API Key: https://ark.volcengine.com/region:cn-beijing/apikey
api_key=os.getenv('ARK_API_KEY'),
)
if __name__ == "__main__":
stream = client.images.generate(
model="doubao-seedream-5-0-lite-260128",
prompt="参考图1,生成四图片,图中人物分别带着墨镜,骑着摩托,带着帽子,拿着棒棒糖",
size="2K",
output_format="png",
response_format="b64_json",
stream=True,
extra_body={
"image": "https://arkdocs.tos-cn-beijing.volces.com/images/image-generation/seedream4_imageToimages_1.png",
"watermark": True,
"sequential_image_generation": "auto",
"sequential_image_generation_options": {
"max_images": 4
},
},
)
for event in stream:
if event is None:
continue
elif event.type == "image_generation.partial_succeeded":
if event.b64_json is not None:
print(f"size={len(event.b64_json)}, base_64={event.b64_json}")
elif event.type == "image_generation.completed":
if event.usage is not None:
print("Final completed event:")
print("recv.Usage:", event.usage)
```
## 提升图片生成速度配置
通过设置 **optimize_prompt_options.mode** 参数,您可以在 `standard` 模式和 `fast` 模式之间进行选择,以根据自身对图片质量和生成速度的不同需求来优化提示词。
* 为平衡生成速度与图像质量,Seedream 5.0 pro、Seedream 4.0 支持将 **optimize_prompt_options.mode** 设置为 `fast` 模式以显著提升生成速度,但会在一定程度上牺牲图片质量。
* Seedream 5.0 flash / lite、Seedream 4.5 仅支持 `standard` 模式。
**选项:Curl**
```Bash
curl https://ark.cn-beijing.volces.com/api/v3/images/generations \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ARK_API_KEY" \
-d '{
"model": "doubao-seedream-4-0-250828",
"prompt": "生成一组共4张连贯插画,核心为同一庭院一角的四季变迁,以统一风格展现四季独特色彩、元素与氛围",
"size": "2K",
"sequential_image_generation": "auto",
"sequential_image_generation_options": {
"max_images": 4
},
"optimize_prompt_options": {
"mode": "fast"
},
"stream": false,
"output_format":"png",
"response_format": "url",
"watermark": true
}'
```
* 您可按需替换 Model ID。Model ID 查询见 [模型列表](/docs/model-list)。
**选项:Python**
```Python
import os
# Install SDK: python -m pip install --upgrade arkruntime
from arkruntime import Ark
from arkruntime.types.images import SequentialImageGenerationOptionsParam
from arkruntime.types.images import OptimizePromptOptionsParam
client = Ark(
# The base URL for model invocation
base_url="https://ark.cn-beijing.volces.com/api/v3",
# Get API Key: https://ark.volcengine.com/region:cn-beijing/apikey
api_key=os.getenv('ARK_API_KEY'),
)
imagesResponse = client.images.generate(
# Replace with Model ID
model="doubao-seedream-4-0-250828",
prompt="生成一组共4张连贯插画,核心为同一庭院一角的四季变迁,以统一风格展现四季独特色彩、元素与氛围",
size="2K",
sequential_image_generation="auto",
sequential_image_generation_options=SequentialImageGenerationOptionsParam(max_images=4),
optimize_prompt_options=OptimizePromptOptionsParam(mode="fast"),
output_format="png",
response_format="url",
watermark=True
)
# Iterate through all image data
for image in imagesResponse.data:
# Output the current image's URL and size
print(f"URL: {image.url}, Size: {image.size}")
```
**选项:Java**
```Java
package com.ark.sample;
import com.volcengine.ark.runtime.models.images.*;
import com.volcengine.ark.runtime.service.ArkService;
import okhttp3.ConnectionPool;
import okhttp3.Dispatcher;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
public class ImageGenerationsExample {
public static void main(String[] args) {
String apiKey = System.getenv("ARK_API_KEY");
ConnectionPool connectionPool = new ConnectionPool(5, 1, TimeUnit.SECONDS);
Dispatcher dispatcher = new Dispatcher();
ArkService service = ArkService.builder()
.baseUrl("https://ark.cn-beijing.volces.com/api/v3")
// The base URL for model invocation
.dispatcher(dispatcher)
.connectionPool(connectionPool)
.apiKey(apiKey)
.build();
SequentialImageGenerationOptions sequentialImageGenerationOptions = new SequentialImageGenerationOptions();
sequentialImageGenerationOptions.setMaxImages(4);
OptimizePromptOptions optimizePromptOptions = new OptimizePromptOptions();
optimizePromptOptions.setMode(OptimizePromptMode.FAST);
CreateImageGenerationRequest generateRequest = CreateImageGenerationRequest.builder()
.model("doubao-seedream-4-0-250828") //Replace with Model ID
.prompt("生成一组共4张连贯插画,核心为同一庭院一角的四季变迁,以统一风格展现四季独特色彩、元素与氛围")
.size("2K")
.sequentialImageGeneration(SequentialImageGenerationMode.AUTO)
.sequentialImageGenerationOptions(sequentialImageGenerationOptions)
.optimizePromptOptions(optimizePromptOptions)
.outputFormat(OutputFormat.PNG)
.responseFormat(ResponseFormat.URL)
.stream(false)
.watermark(true)
.build();
ImageGenerationResponse imagesResponse = service.generateImages(generateRequest);
// Iterate through all image data
if (imagesResponse != null && imagesResponse.getData() != null) {
for (int i = 0; i < imagesResponse.getData().size(); i++) {
// Retrieve image information
String url = imagesResponse.getData().get(i).getUrl();
String size = imagesResponse.getData().get(i).getSize();
System.out.printf("Image %d:%n", i + 1);
System.out.printf(" URL: %s%n", url);
System.out.printf(" Size: %s%n", size);
System.out.println();
}
service.shutdownExecutor();
}
}
}
```
**选项:Go**
```Go
package main
import (
"context"
"fmt"
"os"
"github.com/volcengine/ark-runtime-go/arkruntime"
model "github.com/volcengine/ark-runtime-go/arkruntime/model/images"
)
func main() {
client := arkruntime.NewClientWithApiKey(
os.Getenv("ARK_API_KEY"),
// The base URL for model invocation .
arkruntime.WithBaseUrl("https://ark.cn-beijing.volces.com/api/v3"),
)
ctx := context.Background()
outputFormat := model.OutputFormatPNG
var (
sequentialImageGeneration model.SequentialImageGenerationMode = "auto"
maxImages = 4
mode model.OptimizePromptMode = model.OptimizePromptModeFast
)
generateReq := &model.CreateImageGenerationRequest{
Model: "doubao-seedream-4-0-250828",
Prompt: model.NewOptString("生成一组共4张连贯插画,核心为同一庭院一角的四季变迁,以统一风格展现四季独特色彩、元素与氛围"),
Size: model.NewOptString("2K"),
OutputFormat: model.NewOptOutputFormat(outputFormat),
ResponseFormat: model.NewOptResponseFormat(model.ResponseFormatURL),
Watermark: model.NewOptBool(true),
SequentialImageGeneration: model.NewOptSequentialImageGenerationMode(sequentialImageGeneration),
SequentialImageGenerationOptions: model.NewOptSequentialImageGenerationOptions(model.SequentialImageGenerationOptions{
MaxImages: model.NewOptInt32(int32(maxImages)),
}),
OptimizePromptOptions: model.NewOptOptimizePromptOptions(model.OptimizePromptOptions{
Mode: model.NewOptOptimizePromptMode(mode),
}),
}
resp, err := client.GenerateImages(ctx, generateReq)
if err != nil {
fmt.Printf("call GenerateImages error: %v\n", err)
return
}
if resp.Error.IsSet() {
fmt.Printf("API returned error: %s - %s\n", resp.Error.Value.Code, resp.Error.Value.Message)
return
}
// Output the generated image information
fmt.Printf("Generated %d images:\n", len(resp.Data))
for i, image := range resp.Data {
var url string
if image.URL.IsSet() {
url = image.URL.Or("")
} else {
url = "N/A"
}
fmt.Printf("Image %d: Size: %s, URL: %s\n", i+1, image.Size.Or(""), url)
}
}
```
**选项:OpenAI**
```Python
import os
from openai import OpenAI
client = OpenAI(
# The base URL for model invocation
base_url="https://ark.cn-beijing.volces.com/api/v3",
# Get API Key: https://ark.volcengine.com/region:cn-beijing/apikey
api_key=os.getenv('ARK_API_KEY'),
)
imagesResponse = client.images.generate(
model="doubao-seedream-4-0-250828",
prompt="生成一组共4张连贯插画,核心为同一庭院一角的四季变迁,以统一风格展现四季独特色彩、元素与氛围",
size="2K",
output_format="png",
response_format="url",
extra_body={
"watermark": True,
"sequential_image_generation": "auto",
"sequential_image_generation_options": {
"max_images": 4
},
"optimize_prompt_options": {"mode": "fast"}
},
)
# Iterate through all image data
for image in imagesResponse.data:
# Output the current image's URL and size
print(f"URL: {image.url}, Size: {image.size}")
```
* 您可按需替换 Model ID。Model ID 查询见 [模型列表](/docs/model-list)。
## 自定义图片输出规格
您可以配置以下参数来控制图片输出规格:
* **size**:指定输出图像的尺寸大小。
* **response_format**:指定生成图像的返回格式。
* **output_format**:指定生成图像的文件格式。
* **watermark** :指定是否为输出图片添加水印。
### 图像输出尺寸
**图片生成场景**
指定生成图像的尺寸信息,支持指定分辨率档位(如 `2K`)或指定宽高像素值(如 `2048x2048`)两种方式,不可混用。不同模型的可选分辨率、默认值、总像素取值范围、宽高比取值范围不同。
**方式 1:指定分辨率档位(推荐)**
在 prompt 中用自然语言描述图片宽高比、图片形状或图片用途,最终由模型判断生成图片的大小。各模型可选值:
* Seedream 5.0 pro:`1K`、`1.5K`、`2K`
> **注意**
>
> Seedream 5.0 pro 的 `1.5K` 与 `1K` 价格相同,且图片生成效果更优。
* Seedream 5.0 lite:`2K`、`3K`、`4K`
* Seedream 4.5:`2K`、`4K`
* Seedream 4.0:`1K`、`2K`、`4K`
使用方式 1 并在 prompt 中描述特定宽高比时,模型实际映射的宽高像素参考值如下表所示(模型支持生成的宽高比不限于以下列举的标准值,此处仅以常见宽高比为例)。
| |1K |1.5K |2K |3K |4K |
|---|---|---|---|---|---|
|Seedream 5.0 pro |`1:1`:1024x1024 |`1:1`:1536x1536 |`1:1`:2048x2048 |— |— | \
| |`4:3`:1152x864 |`4:3`:1792x1344 |`4:3`:2368x1776 | | | \
| |`3:4`:864x1152 |`3:4`:1344x1792 |`3:4`:1776x2368 | | | \
| |`16:9`:1424x800 |`16:9`:2048x1152 |`16:9`:2816x1584 | | | \
| |`9:16`:800x1424 |`9:16`:1152x2048 |`9:16`:1584x2816 | | | \
| |`3:2`:1248x832 |`3:2`:1872x1248 |`3:2`:2496x1664 | | | \
| |`2:3`:832x1248 |`2:3`:1248x1872 |`2:3`:1664x2496 | | | \
| |`21:9`:1568x672 |`21:9`:2352x1008 |`21:9`:3136x1344 | | |
|Seedream 5.0 lite |— |— |`1:1`:2048x2048 |`1:1`:3072x3072 |`1:1`:4096x4096 | \
| | | |`4:3`:2304x1728 |`4:3`:3456x2592 |`4:3`:4704x3520 | \
| | | |`3:4`:1728x2304 |`3:4`:2592x3456 |`3:4`:3520x4704 | \
| | | |`16:9`:2848x1600 |`16:9`:4096x2304 |`16:9`:5504x3040 | \
| | | |`9:16`:1600x2848 |`9:16`:2304x4096 |`9:16`:3040x5504 | \
| | | |`3:2`:2496x1664 |`3:2`:3744x2496 |`3:2`:4992x3328 | \
| | | |`2:3`:1664x2496 |`2:3`:2496x3744 |`2:3`:3328x4992 | \
| | | |`21:9`:3136x1344 |`21:9`:4704x2016 |`21:9`:6240x2656 |
|Seedream 4.5 |— |— |`1:1`:2048x2048 |— |`1:1`:4096x4096 | \
| | | |`4:3`:2304x1728 | |`4:3`:4704x3520 | \
| | | |`3:4`:1728x2304 | |`3:4`:3520x4704 | \
| | | |`16:9`:2848x1600 | |`16:9`:5504x3040 | \
| | | |`9:16`:1600x2848 | |`9:16`:3040x5504 | \
| | | |`3:2`:2496x1664 | |`3:2`:4992x3328 | \
| | | |`2:3`:1664x2496 | |`2:3`:3328x4992 | \
| | | |`21:9`:3136x1344 | |`21:9`:6240x2656 |
|Seedream 4.0 |`1:1`:1024x1024 |— |`1:1`:2048x2048 |— |`1:1`:4096x4096 | \
| |`4:3`:1152x864 | |`4:3`:2304x1728 | |`4:3`:4704x3520 | \
| |`3:4`:864x1152 | |`3:4`:1728x2304 | |`3:4`:3520x4704 | \
| |`16:9`:1312x736 | |`16:9`:2848x1600 | |`16:9`:5504x3040 | \
| |`9:16`:736x1312 | |`9:16`:1600x2848 | |`9:16`:3040x5504 | \
| |`3:2`:1248x832 | |`3:2`:2496x1664 | |`3:2`:4992x3328 | \
| |`2:3`:832x1248 | |`2:3`:1664x2496 | |`2:3`:3328x4992 | \
| |`21:9`:1568x672 | |`21:9`:3136x1344 | |`21:9`:6240x2656 |
**方式 2:指定宽高像素值(`宽x高`)**
各模型参数约束:
| | Seedream 5.0 pro | Seedream 5.0 lite | Seedream 4.5 | Seedream 4.0 |
| --- | --- | --- | --- | --- |
| 总像素取值范围 | [`1280x720`(921600), `2048x2048x1.1025`(4624220)] | [`2560x1440`(3686400), `4096x4096`(16777216)] | [`2560x1440`(3686400), `4096x4096`(16777216)] | [`1280x720`(921600), `4096x4096`(16777216)] |
| 宽高比范围 | [1/16, 16] | [1/16, 16] | [1/16, 16] | [1/16, 16] |
|方式1 |方式2 |
|---|---|
|```JSON |```JSON | \
|{ |{ | \
| "prompt": "生成一组共4张连贯插画,宽高比为3:2,核心为同一庭院一角的四季变迁,以统一风格展现四季独特色彩、元素与氛围", | "prompt": "生成一组共4张连贯插画,核心为同一庭院一角的四季变迁,以统一风格展现四季独特色彩、元素与氛围", | \
| | | \
| "size": "2K" | "size": "2048x2048" | \
| | | \
|} |} | \
|``` |``` |
**图层拆分场景**
仅支持通过指定分辨率档位的方式设置。输出图的分辨率规则如下:
* **底图**:输出底图的分辨率和 `size` 指定的分辨率一致;输出底图和原待拆分图的宽高比一致。
* **各图层**:输出图层的分辨率和 `size` 指定的分辨率接近;每个输出图层和其在原图中的宽高比一致。
`size` 的默认值与可选值:
* 默认值:`auto`
* 可选值:`1K`、`1.5K`、`2K`、`auto`(根据输入图的尺寸和宽高比进行输出)
> **注意:价格说明**
>
> `1.5K` 与 `1K` 价格相同(详情参见 [模型价格](/docs/model-pricing#457edfd0))。
> **说明:auto 适配规则**
>
> auto 模式下,模型将根据输入图片中底图和每个图层的原始尺寸进行输出,且各自保持其在原图中的宽高比:
>
> * 若输入图片中底图和每个图层的原始尺寸在 [`1280x720`(921600), `2048x2048x1.1025`(4624220)] 之间,按照原尺寸输出底图与每个图层。
> * 若输入图片中底图和每个图层的原始尺寸小于 1K,按 1K 输出底图与每个图层。
> * 若输入图片中底图和每个图层的原始尺寸大于 2K,按 2K 输出底图与每个图层。
### 图像输出方式
通过设置 **response_format** 参数,可以指定生成图像的返回方式:
* `url`:返回图片下载链接。
* `b64_json`:以 Base64 编码字符串的 JSON 格式返回图像数据。
```JSON
{
"response_format": "url"
}
```
### 图像文件格式
Seedream 4.5/4.0 生成的图像格式默认为` jpeg`,不支持自定义设置。
Seedream 5.0 pro / 5.0 lite 可通过设置 **output_format** 参数,指定生成图像文件的格式:
* `png`
* `jpeg`
```JSON
{
"output_format": "png"
}
```
> **注意**
>
> 图层拆分场景下,`output_format` 仅控制底图的输出格式,图层始终以 PNG 格式输出。
### 图像中添加水印
通过设置 **watermark** 参数,来控制是否在生成的图片中添加水印。
* `false`:不添加水印。
* `true`:在图片右下角添加“AI生成”字样的水印标识。
```JSON
{
"watermark": true
}
```
# 使用限制
**SDK 版本升级**
为保证模型功能的正常使用,请务必升级至最新 SDK 版本。相关步骤可参考 [安装及升级 SDK](/docs/install-and-upgrade-sdk)。
**图片传入限制**
图片传入方式(两种场景通用):
* 图片 URL:请确保图片 URL 可被访问。
示例:`https://arkdocs.tos-cn-beijing.volces.com/images/image-generation/seedream4_5_imageToimage.png`
* Base64 编码:请遵循格式`data:image/<图片格式>;base64,`。注意:`<图片格式>` 必须采用小写字母,例如 `data:image/png;base64,`。
如需获得图片的 Base64 编码,可使用第三方工具,例如 https://base64.guru/converter/encode/image。
不同场景对输入图的约束不同,详见下表:
| 约束项 | 图片生成场景 | 图层拆分场景 |
| --- | --- | --- |
| 图片格式 | jpeg、png、webp、bmp、tiff、gif、heic、heif | png、jpeg |
| 总像素(宽×高) | [196, `6000×6000`(3600万)] | [`512×512`(262144), `6000×6000`(3600万)] |
| 宽高长度(px) | 大于14 | — |
| 宽高比(宽/高) | [1/16, 16] | [1/16, 16] |
| 大小 | 不超过 30 MB | 不超过 30 MB |
| 传入张数 | Seedream 5.0 pro / flash,最多 10 张;Seedream 5.0 lite / 4.5 / 4.0,最多 14 张 | 仅支持单张图片 |
> **说明**
>
> 总像素是对单张图宽度和高度的**像素乘积**限制,而不是对宽度或高度的单独值进行限制。
**保存时间**
图片URL仅保留24小时,超时后会被自动清除。请您务必及时保存生成的图片。
推荐配置火山引擎 TOS 提供的数据订阅功能,将您的模型推理产物自动转存到自己的 TOS 桶中,便于长期备份或二次加工。详细介绍请参见 [TOS 数据订阅](https://docs.volcengine.com/docs/TorchObjectStorage/Datasubscription-5?lang=zh)。
**限流说明**
* IPM 限流:账号下同模型(区分模型版本)每分钟生成图片数量上限。若超过该限制,生成图片时会报错。
* 图层拆分场景下,每次请求预扣减 17 IPM(按最多输出 1 张底图和 16 张图层预留配额);全部图片生成后,按实际生成数量返还多扣减的额度。
* 不同模型的限制值不同,详见 [图片生成能力](/docs/model-list#9df4d9fd)。
# 附:故事书/连环画制作
[火山方舟大模型体验中心](https://www.volcengine.com/experience/ark?mode=vision&model=doubao-seedream-4-0-250828) 提供了故事书和连环画功能,该功能结合了 Doubao Seed 2.1 Lite 模型和 Seedream 4.0 模型,可实现一句话生成动漫、连环画、故事书,满足用户多样化的创作需求。
连环画的实现过程与故事书类似,本文以故事书为例,为您介绍生成故事书的工作流和技术实现步骤,方便您在本地快速复现。

## 工作流
故事书生成的工作流如下:

## 技术实现
1. 根据用户提供的提示词和参考图,调用 doubao-seed-2.1-lite 模型,进行故事创作 > 故事分镜拆解 > 生成分镜的文案和画面描述 > 生成书名 > 生成故事总结,并汇总成 JSON 格式输出。
System Prompt 如下:
```Text
# 角色
你是一位**绘本创作大师**。
## 任务
贴合用户指定的**读者群(儿童/青少年/成人/全年龄)**,创作**情节线性连贯的、生动有趣的、充满情绪价值和温度的、有情感共鸣的、分镜-文案-画面严格顺序对应的绘本内容**:
- 核心约束:**分镜拆分→文案(scenes)→画面描述(scenes_detail)必须1:1顺序绑定**,从故事开头到结尾,像「放电影」一样按时间线推进,绝无错位。
## 工作流程
1. 充分理解用户诉求。 优先按照用户的创作细节要求执行(如果有)
2. **故事构思:** 创作一个能够精准回应用户诉求、提供情感慰藉的故事脉络。整个故事必须围绕“共情”和“情绪价值”展开。
3. **分镜结构与数量:**
* 将故事浓缩成 **5~10** 个关键分镜,最多10个(不能超过10个)。
* 必须遵循清晰的叙事弧线:开端 → 发展 → 高潮 → 结局。
4. **文案与画面 (一一对应):**
* **文案 ("scenes"字段):** 为每个分镜创作具备情感穿透力的文案。文案必须与画面描述紧密贴合,共同服务于情绪的传递。**禁止在文案中使用任何英文引号 ("")**。不能超过10个。
* **画面 ("scenes_detail"字段):** 为每个分镜构思详细的画面。画风必须贴合用户诉求和故事氛围。描述需包含构图、光影、色彩、角色神态等关键视觉要素,达到可直接用于图片生成的标准。
5. **书名 ("title"字段):**
* 构思一个简洁、好记、有创意的书名。
* 书名必须能巧妙地概括故事精髓,并能瞬间“戳中”目标用户的情绪共鸣点。
6. **故事总结 ("summary"字段):**
* 创作一句**不超过30个汉字**的总结。
* 总结需高度凝练故事的核心思想与情感价值。
7. 整合输出:将所有内容按指定 JSON 格式整理输出。
## 安全限制
生成的内容必须严格遵守以下规定:
1. **禁止暴力与血腥:** 不得包含任何详细的暴力、伤害、血腥或令人不适的画面描述。
2. **禁止色情内容:** 不得包含任何色情、性暗示或不适宜的裸露内容。
3. **禁止仇恨与歧视:** 不得包含针对任何群体(基于种族、宗教、性别、性取向等)的仇恨、歧视或攻击性言论。
4. **禁止违法与危险行为:** 不得描绘或鼓励任何非法活动、自残或危险行为。
5. **确保普遍适宜性:** 整体内容应保持在社会普遍接受的艺术创作范围内,避免极端争议性话题。
## 输出格式要求
整理成以下JSON格式,scenes 和 scenes_detail 要与分镜保持顺序一致,一一对应,最多10个(不能超过10个):
{
"title": "书名",
"summary": "30字内的总结",
"scenes": [
"分镜1的文案,用50字篇幅传递情绪和情感,引发读者共鸣,语言风格需符合设定。",
"分镜2的文案"
],
"scenes_detail": [
"图片1:这是第一页的画面描述。必须以'图片'+序号开头。要有强烈的视觉感,详细描述构图(如特写、远景)、光影、色彩、角色表情、动作和环境细节,符合生图提示词的要求。",
"图片2:"
]
}
```
2. 提取返回结果 JSON 中的 scenes_detail 字段,作为图片生成的 Prompt 。
3. 处理图片生成的 Prompt:
1. 将数组转化成字符串
2. 在 prompt 末尾补充"最后,为故事书创作一个封面。 再检查所有图片,去除图片中的文字"。
3. 在 prompt 开头添加用户输入的提示词。
4. 根据图片生成的 Prompt 和用户提供的参考图,调用 doubao-seedream-4.0 模型的生成组图能力,为故事的所有分镜文案生成配图。
5. 按照顺序拼装图片和文字即可得到故事书内容 ,用户按需进行展示即可。
---
# 决策评估(beta)
Source: https://ark.volcengine.com/region:cn-beijing/docs/decision-model
决策评估可通过 System One API 将文本、图片、视频或音频等输入转换为业务可直接使用的结构化判断结果,适用于内容分类、请求路由、风险评估和优先级判断等场景。它可以返回某个条件为真的概率、从固定选项集合中选择某个选项的结果和概率,或者根据评分标准给出分数。
> **注意**
>
> System One API 当前处于 beta 测试阶段。调用该接口时,必须在 HTTP 请求头中传入 `ark-beta-systemone-api: true`。
## 支持模型与 API
- 支持模型:
请参见[决策评估能力(beta)](/docs/model-list#f2b7c91d)。
- 支持 API:
[System One API(beta)](/docs/system-one-api)
## 工作方式
System One API 通过 `state` 和 `questions` 描述一次决策评估任务,并在响应的 `answers` 中返回结构化判断结果。
请求包含以下部分:
| 参数 | 说明 |
| --- | --- |
| `model` | 执行本次评估的模型 ID 或推理接入点 ID。 |
| `state` | 待评估内容,可以是文本、结构化 JSON 或多模态对象数组。 |
| `questions` | 评估问题集合。每个问题用于定义一个判断维度,包括问题类型、判断目标和判定标准。 |
响应中的 `answers` 会按问题 ID 返回结果,不同问题类型的典型场景及对应结果如下:
| 问题类型 | 典型场景 | 主要结果 |
| --- | --- | --- |
| `noul` | 是非判断 | 返回 `[0, 1]` 区间内的概率值,表示结果符合 `criteria.true` 的概率。 |
| `choice` | 分类选择 | 返回概率最高的选项作为命中结果,并返回各选项的概率。 |
| `score` | 评分判断 | 返回档位编号的概率加权值,并返回各档位的概率。 |
## 典型场景
以下示例展示决策评估在分类选择、是非判断和评分判断场景中的请求与响应。
### 分类选择
分类选择可使用 `choice`。例如在工单路由场景中,可将处理团队写入 `criteria`,并增加 `其他` 或 `信息不足` 兜底选项。
请求示例如下:
```Bash
curl "https://ark.cn-beijing.volces.com/api/v1/systemone" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ARK_API_KEY" \
-H "ark-beta-systemone-api: true" \
-d '{
"model": "doubao-seed-2-1-lite-260915",
"state": {
"ticket_id": "ticket-001",
"customer_message": "我收到的杯子有裂纹,申请退款,不接受换货。",
"order": {
"order_id": "order-104",
"product": "陶瓷杯",
"payment_status": "paid"
}
},
"questions": {
"routing_team_v1": {
"type": "choice",
"instructions": "根据客户反馈的主要问题选择优先处理团队。",
"criteria": {
"财务": "扣款、发票或退款到账问题",
"质量": "商品损坏、质量缺陷或与描述不符",
"物流": "配送延迟、丢件或物流状态问题",
"信息不足": "缺少判断主要问题所需的信息"
}
}
}
}'
```
响应示例如下:
```
{
"model": "doubao-seed-2-1-lite-260915",
"answers": {
"routing_team_v1": {
"type": "choice",
"choice": "质量",
"confidence": 0.91,
"probabilities": {
"财务": 0.04,
"质量": 0.91,
"物流": 0.02,
"信息不足": 0.03
}
}
},
"usage": {
"input_tokens": 183,
"output_tokens": 0
}
}
```
### 是非判断
是非判断可使用 `noul`。例如判断是否需要转人工时,可用 `criteria.true` 和 `criteria.false` 明确自动转人工的边界,并在业务代码中设置上下阈值。
请求示例如下:
```Bash
curl "https://ark.cn-beijing.volces.com/api/v1/systemone" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ARK_API_KEY" \
-H "ark-beta-systemone-api: true" \
-d '{
"model": "doubao-seed-2-1-lite-260915",
"state": {
"ticket_id": "ticket-002",
"customer_message": "已经联系三次还没解决,请马上安排人工处理,否则我要投诉。",
"order": {
"order_id": "order-205",
"product": "蓝牙耳机",
"payment_status": "paid"
}
},
"questions": {
"needs_human_support_v1": {
"type": "noul",
"instructions": "该工单是否需要转人工处理?",
"criteria": {
"true": "存在退款、投诉、风险、证据不充分或客户明确要求人工介入",
"false": "问题清晰、风险较低,且可由自动化流程处理"
}
}
}
}'
```
响应示例如下:
```
{
"model": "doubao-seed-2-1-lite-260915",
"answers": {
"needs_human_support_v1": {
"type": "noul",
"noul": 0.94
}
},
"usage": {
"input_tokens": 169,
"output_tokens": 0
}
}
```
### 评分判断
评分判断可使用 `score`。例如评估风险等级时,`criteria` 应描述同一风险维度下从低到高的档位,不要把多个维度混在一道题中。
请求示例如下:
```Bash
curl "https://ark.cn-beijing.volces.com/api/v1/systemone" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ARK_API_KEY" \
-H "ark-beta-systemone-api: true" \
-d '{
"model": "doubao-seed-2-1-lite-260915",
"state": {
"ticket_id": "ticket-003",
"customer_message": "退款金额一直不到账,我已经准备向监管平台投诉。",
"order": {
"order_id": "order-309",
"refund_status": "processing",
"refund_amount": 299
}
},
"questions": {
"risk_level_v1": {
"type": "score",
"instructions": "该工单的处理风险等级是多少?",
"criteria": [
"风险较低,不涉及资金、合规或客户投诉",
"存在一定风险,需要补充材料或人工确认",
"风险较高,涉及资金损失、投诉升级或合规问题"
]
}
}
}'
```
响应示例如下:
```
{
"model": "doubao-seed-2-1-lite-260915",
"answers": {
"risk_level_v1": {
"type": "score",
"score": 1.82,
"confidence": 0.88,
"legend": {
"0": "风险较低,不涉及资金、合规或客户投诉",
"1": "存在一定风险,需要补充材料或人工确认",
"2": "风险较高,涉及资金损失、投诉升级或合规问题"
},
"probabilities": {
"0": 0.03,
"1": 0.12,
"2": 0.85
}
}
},
"usage": {
"input_tokens": 178,
"output_tokens": 0
}
}
```
## 评估流程
使用 System One API 进行决策评估时,可按以下步骤设计请求。
### 步骤一:设置被评估内容
将需要评估的业务内容放入 `state`。`state` 应包含完成判断所需的事实、证据、业务对象和上下文信息,避免把判定规则混入被评估内容中。
### 步骤二:设置评估问题和判定标准
在 `questions` 中传入评估问题,并设置以下字段:
- `type`:设置问题类型,可选值为 `noul`、`choice` 或 `score`。
- `instructions`:说明判断目标。
- `criteria`:补充判定边界、候选选项或评分档位。简单场景可以只设置 `instructions`;需要更稳定的业务判断时,建议补充 `criteria`。
以下示例使用 `noul` 判断客户是否明确要求退款。
请求示例如下:
```Bash
curl "https://ark.cn-beijing.volces.com/api/v1/systemone" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ARK_API_KEY" \
-H "ark-beta-systemone-api: true" \
-d '{
"model": "doubao-seed-2-1-lite-260915",
"state": {
"工单": {
"客户反馈": "收到的杯子裂了,请退回货款,我不接受换货。"
},
"订单": {
"订单号": "订单-104"
}
},
"questions": {
"refund_requested_v1": {
"type": "noul",
"instructions": "客户是否明确要求退回已支付的款项?"
}
}
}'
```
### 步骤三:处理评估结果
读取响应中对应问题 ID 的结果,并根据业务自定义阈值或策略执行后续动作。
对于 `noul` 类型问题,返回值为 `[0, 1]` 区间内的概率值。业务代码可以根据该概率值和自定义阈值判断是否执行“是”分支、进入“否”分支或转人工复核。
响应示例如下:
```
{
"model": "doubao-seed-2-1-lite-260915",
"answers": {
"refund_requested_v1": {
"type": "noul",
"noul": 0.96
}
},
"usage": {
"input_tokens": 128,
"output_tokens": 0
}
}
```
## 进阶使用
### 多模态输入
当 `state` 同时包含文本、图片、视频或音频时,可传入多模态对象数组,并在 `instructions` 中说明每种材料的作用,区分“用户主张”和“材料证据”,避免模型仅凭文字描述替代证据判断。
多模态内容支持以下传入方式:
- 本地文件上传:
- [Files API 上传](/docs/upload-files-api)(推荐):适用于文件较大,或需要在多个请求中复用同一文件的场景。文件上传并变为可用后,可在 System One API 请求中引用该文件。
- Base64 输入:适用于文件体积较小、无需复用文件的场景。
- 公网 URL 输入:适用于文件已存在公网可访问 URL 的场景。
> **说明**
>
> - 多模态内容的文件格式、大小、尺寸、数量、时长及 Files API 上传限制,详见[图片理解](/docs/image-understanding)、[视频理解](/docs/video-understanding)、[音频理解](/docs/audio-understanding)和[文件输入(Files API)](/docs/file-api)。
> - 同一图片、视频或音频需要在多次评估请求中复用时,建议在 `state` 中通过 `file_id` 引用素材。对同一个媒体元素,不要同时传入 `file_id`、公网 URL 或 Base64。
> - 多模态输入会增加请求处理时间;如需保持较低响应延迟,建议仅传入完成判断所需的图片、视频或音频内容。
以下示例展示通过 `file_id`、公网 URL 和 Base64 传入多模态内容的方式。
```Bash
BASE64_AUDIO=$(base64 < /Users/doc/demo.mp3) && curl "https://ark.cn-beijing.volces.com/api/v1/systemone" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ARK_API_KEY" \
-H "ark-beta-systemone-api: true" \
-d @- <",
"detail": "high"
},
{
"type": "video",
"video_url": "https://example.com/unboxing-video.mp4",
"fps": 1
},
{
"type": "audio",
"audio_url": "data:audio/mpeg;base64,$BASE64_AUDIO"
}
],
"questions": {
"package_damaged_on_arrival_v1": {
"type": "noul",
"instructions": "图片、视频和音频证据是否支持商品到货时已破损?文本只提供客户主张,不能仅凭客户文字认定到货即破损。",
"criteria": {
"true": "图片或视频中可见商品破损,且音频或视频内容能够辅助确认破损发生在到货或开箱阶段",
"false": "多模态材料无法确认商品到货时已破损,或关键证据不清晰、不连续"
}
}
}
}
EOF
```
### 同一请求传入多个问题
如果需要基于同一份 `state` 完成多个相互独立的判断,可在同一次请求的 `questions` 中传入多道问题。每个问题只对应一个判断维度;如果某个问题依赖另一道问题的答案,建议拆分为多次请求。
> **说明**
>
> 为保持较低响应延迟,建议控制单次请求中的 `questions` 数量;问题数量较多时,可拆分为多次请求。
以下示例使用同一份工单内容,同时判断客户是否要求退款、选择优先处理团队,并评估客户不满程度。
```Bash
curl "https://ark.cn-beijing.volces.com/api/v1/systemone" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ARK_API_KEY" \
-H "ark-beta-systemone-api: true" \
-d '{
"model": "doubao-seed-2-1-lite-260915",
"state": {
"工单": {
"客户反馈": "收到的杯子裂了,请退回货款,我不接受换货。"
},
"订单": {
"订单号": "订单-104"
}
},
"questions": {
"refund_requested_v1": {
"type": "noul",
"instructions": "客户是否明确要求退回已支付的款项?"
},
"routing_team_v1": {
"type": "choice",
"instructions": "根据客户反馈的主要问题选择优先处理团队。",
"criteria": {
"财务": "扣款、发票或退款到账问题",
"质量": "商品损坏、质量缺陷或与描述不符",
"物流": "配送延迟、丢件或物流状态问题",
"信息不足": "缺少判断主要问题所需的信息"
}
},
"dissatisfaction_level_v1": {
"type": "score",
"instructions": "客户在反馈中表达的不满程度如何?",
"criteria": [
"平静陈述事实,没有表达不满",
"明确表达不满,但措辞克制",
"强烈愤怒,使用激烈措辞或威胁投诉"
]
}
}
}'
```
### 组合使用评估结果
业务代码不应只读取最高概率结果,还应结合 `probabilities`、`confidence` 和自定义阈值执行后续动作。
响应示例如下:
```
{
"model": "doubao-seed-2-1-lite-260915",
"answers": {
"refund_requested_v1": {
"type": "noul",
"noul": 0.96
},
"routing_team_v1": {
"type": "choice",
"choice": "质量",
"confidence": 0.91,
"probabilities": {
"财务": 0.04,
"质量": 0.91,
"物流": 0.02,
"信息不足": 0.03
}
},
"dissatisfaction_level_v1": {
"type": "score",
"score": 1.82,
"confidence": 0.88,
"probabilities": {
"0": 0.03,
"1": 0.12,
"2": 0.85
}
}
},
"usage": {
"input_tokens": 245,
"output_tokens": 0
}
}
```
业务代码可先分别读取每个问题的结果,再结合业务策略形成最终处理动作。不同类型结果可参考以下方式使用:
| 结果类型 | 示例结果 | 结果使用方式 |
| --- | --- | --- |
| `noul` 是非判断 | `refund_requested_v1.noul` 为 `0.96`。 | 高于业务定义的“是”阈值时,可执行“是”分支;低于“否”阈值时,可执行“否”分支;介于两个阈值之间时进入人工复核。 |
| `choice` 分类 | `routing_team_v1.choice` 为 `质量`,`confidence` 为 `0.91`。 | 当目标选项概率和 `confidence` 均高于业务阈值时,可按该分类路由;`confidence` 低或兜底选项概率高时进入人工复核。 |
| `score` 打分 | `dissatisfaction_level_v1.score` 为 `1.82`。 | 可根据加权 `score` 所处的业务区间执行后续动作;最高两个档位概率接近时保留人工判断。 |
例如,当 `refund_requested_v1.noul` 高于业务定义的“是”阈值,且 `routing_team_v1.choice` 为 `质量` 时,可将工单路由到质量团队;如果任一结果置信度不足,可进入人工复核。
## 计费说明
决策评估按照所选模型的输入、输出 token 计费。
具体价格请参见[模型价格](/docs/model-pricing)。
## 使用限制与注意事项
- System One API 返回结构化判断结果,不用于生成面向用户的自然语言回复;如需生成客服话术、摘要、解释或完整报告,建议使用 [Chat API](/docs/chat-api) 或 [Responses API](/docs/create-model-responses-api)。
- System One API 当前支持最大 128k 上下文窗口,单次请求中的 `state` 和 `questions` 共同占用上下文窗口。
- 使用 `choice` 时,建议在 `criteria` 中设置 `其他`、`信息不足` 或 `无法判断` 等兜底选项,避免证据不足时被迫命中业务分类。
- 使用 `score` 时,每道问题应只评估一个有序维度;不同问题的档位数量或档位含义不一致时,`score` 不应直接横向比较。
- 批量评估、实时高并发评估或周期性任务中,建议控制请求并发;遇到限流或服务繁忙类错误时,使用指数退避重试。
---
# 3D 生成
Source: https://ark.volcengine.com/region:cn-beijing/docs/3d-generation
3D 生成模型具备出色的三维内容生成能力,能够根据用户输入的图像,快速生成具备多边形面片与 PBR 材质的高精度 3D 资产。通过这篇教程您可以学习到如何调用豆包 3D 生成模型 API 来生成 3D 文件。
> **说明**
>
> 方舟平台的新用户?获取 API Key 及 开通模型等准备工作,请参见 [快速入门](/docs/quick-start)。
# 模型及API
|**模型 ID(Model ID)** |**模型能力** |**产物规格** | **限流** |API |
|---|---|---|---|---|
|[doubao-seed3d-2-0-260328](https://ark.volcengine.com/region:cn-beijing/model/detail?Id=doubao-seed3d-2-0) |图生3D |**产物面数** |最大 RPM:300 |[3D生成 API](https://ark.volcengine.com/region:cn-beijing/docs/seed3d-api) | \
| | | |最大并发:5 | | \
| |* 生成带纹理和 PBR 材质的3D文件 |* 100000 面 | | | \
| | |* 500000 面 | | | \
| | |* 1000000面 | | | \
| | | | | | \
| | |**产物格式** | | | \
| | |* glb 、obj、usd、usdz | | | \
| | | | | |
|[hyper3d-gen2-260112](https://ark.volcengine.com/region:cn-beijing/model/detail?Id=hyper3d-gen2) |文生3D、图生3D |**产物面数** |最大 RPM: 60 |[影眸 API](https://ark.volcengine.com/region:cn-beijing/docs/shadoweye-api) | \
| | | |最大并发: 3 | | \
| |* 生成带纹理和 PBR 材质的 3D 文件 |* 三角面模型:[500, 1,000,000] | | | \
| | |* 四边面模型:[1,000, 200,000] | | | \
| | | | | | \
| | |**产物格式** | | | \
| | |* glb, obj, stl, fbx, usdz | | | \
| | | | | |
|[hitem3d-2-0-251223](https://ark.volcengine.com/region:cn-beijing/model/detail?Id=hitem3d-2-0) |图生3D |**产物面数** |最大 RPM: 600 |[数美 API](https://ark.volcengine.com/region:cn-beijing/docs/shumei-api) | \
| | | |最大并发: 30 | | \
| |* 标准白膜 |* [100000, 2000000] | | | \
| |* 标准纹理模型 | | | | \
| |* 高精白膜 |**产物格式** | | | \
| |* 高精纹理模型 |* glb, obj, stl, fbx, usdz | | | \
| | | | | | \
| | |**产物分辨率** | | | \
| | |* 1536、1536 pro | | | \
| | | | | |
# 模型价格
请参见:[3D生成模型](/docs/model-pricing#59e650ae)
# 使用流程
3D 生成任务为异步任务。
1. 通过 **创建任务接口** 创建3D生成任务,获得 **任务 ID** 。
2. 通过 **任务查询接口** + **任务 ID** 查询任务状态,直到任务完成时,获取返回的 3D 产物下载链接,下载生成结果。
> **说明**
>
> * 3D 生成过程耗时在分钟级别,通常在数分钟到十数分钟不等,具体受任务复杂度和平台负载影响。
> * 返回的产物链接有效期为 24 小时,过时失效,请及时下载/转存产物。
# 体验&调试
可在 [API Explorer](https://api.volcengine.com/api-explorer/?action=Create3DGenerationsTasks&groupName=3D%E7%94%9F%E6%88%90API&serviceCode=ark&tab=2&tab_result=1&tab_sdk=CURL&version=2024-01-01),0代码体验通过 API 调用 3D 模型。支持灵活调整参数(如控制输出产物格式等),方便您直观感受模型实际使用过程。
# 代码调用
## 效果预览
|输入 |输出预览 | |
|---|---|---|
| | | | \
| | | | \
| |> 上图为效果展示。实际产物为3D文件,类似 [文件](https://arkdocs.tos-cn-beijing.volces.com/files/domain-models/seed3d_imageTo3d.glb)。 | |
## 示例代码
**选项:Python**
```Python
import os
import time
# Install SDK: python -m pip install --upgrade arkruntime
from arkruntime import Ark
# 初始化Ark客户端
client = Ark(
# The base URL for model invocation .
base_url="https://ark.cn-beijing.volces.com/api/v3",
# Get API Key: https://ark.volcengine.com/region:cn-beijing/apikey
api_key=os.getenv('ARK_API_KEY'),
)
print("----- create request -----")
# 创建3D生成任务
create_result = client.content_generation.tasks.create(
# Replace with Model ID .
model="doubao-seed3d-2-0-260328",
content=[
{
# 参数
"type": "text",
"text": "--subdivisionlevel medium --fileformat glb"
},
{
# 图片URL
"type": "image_url",
"image_url": {
"url": "https://arkdocs.tos-cn-beijing.volces.com/images/domain-models/seed3d_imageTo3d.png"
}
}
]
)
print(create_result)
# 轮询查询部分
print("----- polling task status -----")
task_id = create_result.id
max_attempts = 60
for attempt in range(1, max_attempts + 1):
get_result = client.content_generation.tasks.get(task_id=task_id)
status = get_result.status
if status == "succeeded":
print("----- task succeeded -----")
print(get_result)
break
elif status == "failed":
print("----- task failed -----")
print(f"Error: {get_result.error}")
break
if attempt == max_attempts:
raise TimeoutError(f"Task {task_id} did not finish after {max_attempts} attempts")
print(f"Current status: {status}, retrying after 60 seconds...")
time.sleep(60)
```
**选项:Curl**
1. 创建3D生成任务,获取 3D 生成任务 ID。
```Bash
curl -X POST https://ark.cn-beijing.volces.com/api/v3/contents/generations/tasks \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ARK_API_KEY" \
-d '{
"model": "doubao-seed3d-2-0-260328",
"content": [
{
"type": "text",
"text": "--subdivisionlevel medium --fileformat glb"
},
{
"type": "image_url",
"image_url": {
"url": "https://arkdocs.tos-cn-beijing.volces.com/images/domain-models/seed3d_imageTo3d.png"
}
}
]
}'
```
2. 查询 3D 生成任务状态,直至任务状态为`Success`,返回产物下载链接。
> 替换 为你的任务 ID。
```Bash
curl -X GET https://ark.cn-beijing.volces.com/api/v3/contents/generations/tasks/ \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ARK_API_KEY"
```
**选项:Go**
```Go
package main
import (
"context"
"fmt"
"os"
"time"
"github.com/volcengine/ark-runtime-go/arkruntime"
model "github.com/volcengine/ark-runtime-go/arkruntime/model/contentgeneration"
)
func main() {
// 请确保您已将 API Key 存储在环境变量 ARK_API_KEY 中
// 初始化Ark客户端,从环境变量中读取您的API Key
client := arkruntime.NewClientWithApiKey(
// 从环境变量中获取您的 API Key。此为默认方式,您可根据需要进行修改
os.Getenv("ARK_API_KEY"),
// The base URL for model invocation .
arkruntime.WithBaseUrl("https://ark.cn-beijing.volces.com/api/v3"),
)
ctx := context.Background()
// Replace with Model ID .
modelEp := "doubao-seed3d-2-0-260328"
// 创建任务
fmt.Println("----- create request -----")
createReq := &model.CreateContentGenerationTaskRequest{
Model: modelEp,
Content: []model.ContentItem{
{
Type: model.ContentTypeText,
Text: model.NewOptString("--subdivisionlevel medium --fileformat glb"),
},
{
Type: model.ContentTypeImageURL,
ImageURL: model.NewOptImageURL(model.ImageURL{
URL: "https://arkdocs.tos-cn-beijing.volces.com/images/domain-models/seed3d_imageTo3d.png",
}),
},
},
}
createResp, err := client.CreateContentGenerationTask(ctx, createReq)
if err != nil {
fmt.Printf("create content generation error: %v", err)
return
}
taskID := createResp.ID
fmt.Printf("Task Created with ID: %s", taskID)
// 轮询查询部分
fmt.Println("----- polling task status -----")
const maxAttempts = 60
for attempt := 1; attempt <= maxAttempts; attempt++ {
getReq := taskID
getResp, err := client.GetContentGenerationTask(ctx, getReq)
if err != nil {
fmt.Printf("get content generation task error: %v", err)
return
}
status := getResp.Status
if status == "succeeded" {
fmt.Println("----- task succeeded -----")
fmt.Printf("Task ID: %s", getResp.ID)
fmt.Printf("Model: %s", getResp.Model)
fmt.Printf("File URL: %s", getResp.Content.Or(model.TaskContent{}).FileURL.Or(""))
fmt.Printf("Completion Tokens: %d", getResp.Usage.Or(model.TaskUsage{}).CompletionTokens)
fmt.Printf("Created At: %d, Updated At: %d", getResp.CreatedAt.Or(0), getResp.UpdatedAt.Or(0))
return
} else if status == "failed" {
fmt.Println("----- task failed -----")
if getResp.Error.IsSet() {
fmt.Printf("Error Code: %s, Message: %s", getResp.Error.Value.Code, getResp.Error.Value.Message)
}
return
} else if attempt == maxAttempts {
fmt.Printf("Task %s did not finish after %d attempts", taskID, maxAttempts)
return
} else {
fmt.Printf("Current status: %s, retrying in 60 seconds...", status)
time.Sleep(60 * time.Second)
}
}
}
```
**选项:Java**
```Java
package com.volcengine.ark.runtime;
import com.volcengine.ark.runtime.models.content_generation.*;
import com.volcengine.ark.runtime.service.ArkService;
import okhttp3.ConnectionPool;
import okhttp3.Dispatcher;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
public class ContentGenerationTaskExample {
// 请确保您已将 API Key 存储在环境变量 ARK_API_KEY 中
// 初始化Ark客户端,从环境变量中读取您的API Key
static String apiKey = System.getenv("ARK_API_KEY");
static ConnectionPool connectionPool = new ConnectionPool(5, 1, TimeUnit.SECONDS);
static Dispatcher dispatcher = new Dispatcher();
static ArkService service = ArkService.builder()
.dispatcher(dispatcher)
.connectionPool(connectionPool)
.apiKey(apiKey)
.baseUrl("https://ark.cn-beijing.volces.com/api/v3")
// The base URL for model invocation .
.build();
public static void main(String[] args) {
//Replace with Model ID .
String model = "doubao-seed3d-2-0-260328";
System.out.println("----- CREATE Task Request -----");
List contents = new ArrayList<>();
// 参数
contents.add(ContentItem.builder()
.type(ContentType.TEXT)
.text("--subdivisionlevel medium --fileformat glb")
.build());
// 图片URL
contents.add(ContentItem.builder()
.type(ContentType.IMAGE_URL)
.imageUrl(ImageURL.builder()
.url("https://arkdocs.tos-cn-beijing.volces.com/images/domain-models/seed3d_imageTo3d.png")
.build())
.build());
// 创建3D生成任务
CreateContentGenerationTaskRequest createRequest = CreateContentGenerationTaskRequest.builder()
.model(model)
.content(contents)
.build();
CreateContentGenerationTaskResponse createResult = service.createContentGenerationTask(createRequest);
System.out.println(createResult);
System.out.println("----- GET Task Request -----");
// 获取任务详情
String getRequest = createResult.getId();
ContentGenerationTask getResult = service.getContentGenerationTask(getRequest);
System.out.println(getResult);
System.out.println("----- LIST Task Request -----");
// 轮询查询部分
System.out.println("----- polling task status -----");
final int maxAttempts = 60;
for (int attempt = 1; attempt <= maxAttempts; attempt++) {
try {
ContentGenerationTask getResponse = service.getContentGenerationTask(getRequest);
String status = getResponse.getStatus().toString();
if ("succeeded".equalsIgnoreCase(status)) {
System.out.println("----- task succeeded -----");
System.out.println(getResponse);
break;
} else if ("failed".equalsIgnoreCase(status)) {
System.out.println("----- task failed -----");
System.out.println("Error: " + getResponse.getStatus());
break;
} else if (attempt == maxAttempts) {
throw new IllegalStateException(
"Task " + getRequest + " did not finish after " + maxAttempts + " attempts");
} else {
System.out.printf("Current status: %s, retrying in 60 seconds...", status);
TimeUnit.SECONDS.sleep(60);
}
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
System.err.println("Polling interrupted");
break;
}
}
}
}
```
# 其他说明
## 控制产物参数
通过`--[parameters]`的方式,控制3D文件输出的规格,包括产物面的数量、输出文格式等。
```Bash
# 指定生成的3D文件的多边形面的数量为 100000 面,生成的3D文件格式为 glb
"content": [
{
"type": "text",
"text": "--subdivisionlevel medium --fileformat glb"
}
]
```
## 链接有效期
任务数据(如任务状态、URL等)仅保留24小时,超时后会被自动清除。请您务必及时保存生成的文件。
## 限流说明
同一主账号下,使用同一模型(不区分版本)的请求受到以下限制。超过对应限制会返回 “429: 'Too Many Requests'” 错误。
### 模型维度的限流
> 不同模型的 RPM 和最大并发任务数不同,详见 [3D生成能力](/docs/model-list#21b9a17a)。
* **RPM(Requests Per Minute)**:每分钟允许创建的 3D 生成任务数上限。超过上限时,创建任务请求将因触发限流而失败。
* **最大并发任务数**:同一时刻可处于处理状态的任务数上限。达到上限后,新创建的任务将进入队列等待处理。
### 非推理 API 请求频率限制
* **QPS(Queries Per Second)**:每秒允许的请求数上限。超过上限时,任务请求将因触发限流而失败。
|接口名称 |账号维度的 QPS 上限 |
|---|---|
|查询 3D 生成任务 |20 |
|查询 3D 生成任务列表 |1 |
|取消或删除 3D 生成任务 |20 |
---
# 向量化
Source: https://ark.volcengine.com/region:cn-beijing/docs/vectorization
`Doubao-embedding-vision` 是由字节跳动研发的多模态向量化模型。它能将文本、图片以及视频等混合输入内容转换为统一的向量表示,从而帮助您更高效地处理跨模态数据,实现精准的文搜图、图搜图和图文混合搜索。
当前模型支持以下几种向量输出类型:
* **稠密向量 (Dense Embedding)**:所有版本均默认支持。
* **稀疏向量 (Sparse Embedding)**:从 `doubao-embedding-vision-250615` 版本起支持,且仅支持文本输入。
* **多向量 (Multi Embedding)**:从 `doubao-embedding-vision-251215` 版本起支持。
# 快速开始
多模态向量模型支持接受和处理视频、图像和文本输入并转换为向量。以下示例均显式配置 `instructions`,使向量表示与目标检索场景保持一致。
> **说明**
>
> 方舟平台的新用户?获取 API Key 及 开通模型等准备工作,请参见 [快速入门](/docs/quick-start)。
**选项:多模态混合输入**
> * doubao-embedding-vision-250615 及后续版本支持 **不限数量的视频、文本和图片混合** 输入。
```Bash
curl https://ark.cn-beijing.volces.com/api/v3/embeddings/multimodal \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ARK_API_KEY" \
-d '{
"model": "doubao-embedding-vision-251215",
"instructions": "Target_modality: text and image and video.\nInstruction:Represent the mixed content for multimodal semantic retrieval\nQuery:",
"encoding_format": "float",
"input": [
{
"type": "video_url",
"video_url": {
"url": "https://arkdocs.tos-cn-beijing.volces.com/videos/advanced-usage/ark_vlm_video_input.mp4"
}
},
{
"type": "image_url",
"image_url": {
"url": "https://arkdocs.tos-cn-beijing.volces.com/images/domain-models/tower.png"
}
},
{
"type": "text",
"text": "视频和图片里有什么"
}
]
}'
```
**选项:开启多向量输出**
> * doubao-embedding-vision-251215 及后续版本支持多向量。
> * 支持文本、图片、视频及混合输入类型。
```Bash
curl https://ark.cn-beijing.volces.com/api/v3/embeddings/multimodal \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ARK_API_KEY" \
-d '{
"model": "doubao-embedding-vision-251215",
"instructions": "Target_modality: text.\nInstruction:Compress the text into one word.\nQuery:",
"encoding_format": "float",
"input": [
{
"type": "text",
"text": "天很蓝"
}
],
"multi_embedding": {
"type": "enabled",
"compression": "blosc2"
}
}'
```
**选项:自定义视频抽帧**
> * doubao-embedding-vision-251215 及后续版本支持视频自定义抽帧。
> * 支持通过 `video_url` 内字段自定义视频抽帧策略。
> * 可综合控制抽帧频率、单帧 token 和整段视频 token 上限。
```Bash
curl https://ark.cn-beijing.volces.com/api/v3/embeddings/multimodal \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ARK_API_KEY" \
-d '{
"model": "doubao-embedding-vision-251215",
"instructions": "Target_modality: text and image and video.\nInstruction:Represent the mixed content for multimodal semantic retrieval\nQuery:",
"encoding_format": "float",
"input": [
{
"type": "video_url",
"video_url": {
"url": "https://arkdocs.tos-cn-beijing.volces.com/videos/advanced-usage/ark_vlm_video_input.mp4",
"fps": 1,
"max_video_tokens": 120000,
"min_frame_tokens": 32,
"max_frame_tokens": 640,
"min_frames": 10
}
},
{
"type": "image_url",
"image_url": {
"url": "https://arkdocs.tos-cn-beijing.volces.com/images/domain-models/tower.png"
}
},
{
"type": "text",
"text": "视频和图片里有什么"
}
]
}'
```
**选项:开启稀疏向量输出**
> * doubao-embedding-vision-250615及后续版本支持。
> * 支持纯文本输入。
```Bash
curl https://ark.cn-beijing.volces.com/api/v3/embeddings/multimodal \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ARK_API_KEY" \
-d '{
"model": "doubao-embedding-vision-251215",
"instructions": "Target_modality: text and video.\nInstruction:Compress the text/video into one word.\nQuery:",
"encoding_format": "float",
"input": [
{
"type": "text",
"text": "天很蓝"
}
],
"dimensions": 1024,
"sparse_embedding": {
"type": "enabled"
}
}'
```
模型回复示例:
> **说明**
>
> `sparse_embedding` 字段在开启稀疏向量时返回。
```JSON
{
"created": 1752133360,
"data": {
"embedding": [
-0.046875,-0.048828125,0.02001953125,0.064453125,
.....
0.003143310546875
],
"sparse_embedding":[
{
"index": 1,
"value": 0.0887451171875
},
{
"index": 13,
"value": 0.0887451171875
},
{
"index": 149,
"value": 0.0887451171875
}
],
"object": "embedding"
},
"id": "021752133359863906427fb4b36437c414d645f52206dfc398f85",
"model": "doubao-embedding-vision-251215",
"object": "list",
"usage": {
"prompt_tokens": 25,
"prompt_tokens_details": {
"image_tokens": 0,
"text_tokens": 25
},
"total_tokens": 25
}
}
```
# 支持模型
当前支持多模态向量化的模型请参见[向量化能力](/docs/model-list#0ee80bb9)。
不同模型版本的功能对比如下:
|**模型版本** |**输入支持** |**稀疏向量 (Sparse Embedding)** |**多向量 (Multi Embedding)** |**视频自定义抽帧** |**`instructions`** **字段** |
|---|---|---|---|---|---|
|`doubao-embedding-vision-250615` |不限数量的文本、图片、视频 |支持(仅限文本输入) |不支持 |不支持 |不支持 |
|`doubao-embedding-vision-251215` 及后续 |不限数量的文本、图片、视频 |支持(仅限文本输入) |支持,支持 `compression=blosc2/zstd` |支持 |支持 |
> **注意**
>
> 【**重要**】`instructions` 字段的配置直接决定模型推理效果。为了显著提升向量表示的精度,您需要根据具体的业务场景来定制该指令。**请勿直接使用系统默认值**。详情请参考[设置 instructions 字段(推荐)](/docs/vectorization#ff993d7a)。
# 使用说明
> **说明**
>
> 推荐使用方舟推出的多模态向量化模型在处理完图像后,图像会从方舟服务器删除。方舟不会保留您提交的视频、图片以及文本信息等用户数据来训练模型。
## 开启稀疏向量(Sparse Embedding)
> 仅 doubao-embedding-vision-250615 及后续版本支持。
稀疏向量仅支持纯文本输入。
通过独立的 `sparse_embedding` 字段控制,与多向量配置互不影响,示例:
> **说明**
>
> `sparse_embedding.type` 默认值为 `disabled`,设置为 `enabled` 开启稀疏向量。
```Plaintext
{
"model": "doubao-embedding-vision-251215",
"input": [
{
"type":"text",
"text":"天很蓝"
}
],
"sparse_embedding": {
"type":"enabled"
},
"encoding_format":"float"
}
```
## 开启多向量(Multi Embedding)
> 仅 doubao-embedding-vision-251215 及后续版本支持。
支持文本、图片、视频及混合输入;可通过 `compression` 控制返回格式,`dimensions` 会同步影响多向量子向量的列数。
通过独立的 `multi_embedding` 字段控制,与稀疏向量配置互不影响;可单独开启,或文本场景下与稀疏向量同时开启,示例:
> **说明**
>
> `multi_embedding.type` 默认值为 `disabled`,设置为 `enabled` 开启多向量。
```Plain Text
{
"model": "doubao-embedding-vision-251215",
"instructions":"Target_modality: text and video.\nInstruction:Compress the text/video into one word.\nQuery:",
"input": [
{
"type":"text",
"text":"天很蓝"
}
],
"multi_embedding": {
"type":"enabled",
"compression":"blosc2"
},
"sparse_embedding": {
"type":"enabled"
},
"encoding_format":"float"
}
```
开启 `multi_embedding.type="enabled"` 后,响应中的 `data.multi_embedding` 会额外返回 token 级别的子向量:
* 不传 `compression` 时,返回 `float[][]`。
* 传入 `compression="blosc2"` 或 `compression="zstd"` 时,返回压缩并 Base64 编码后的字符串。
* 压缩返回场景下,客户端需依次执行 Base64 解码、按压缩算法解压、按 `fp16`(2 字节小端序)解析,再按 `[num_tokens, dimensions]` 重塑为二维数组。
* `multi_embedding` 不允许传空对象 `{}`,否则会报错。
* `multi_embedding` 与 `sparse_embedding` 可同时开启,但 `sparse_embedding` 仍只支持纯文本输入。
## 自定义视频抽帧
> 仅 `doubao-embedding-vision-251215` 及后续版本支持。可在 `input[].video_url` 内配置抽帧参数,自定义视频理解的速度、成本与效果平衡。
以下字段均为可选;不传时,使用模型默认抽帧策略。
|字段 |类型 |取值范围 |说明 |
|---|---|---|---|
|`fps` |float |`[0.2, 5]` |抽帧频率,单位“帧/秒” |
|`max_video_tokens` |integer |`[10240, 204800]` |整段视频最多送入模型的 token 数 |
|`min_frame_tokens` |integer |`[16, 128]` |单帧最少 token 数 |
|`max_frame_tokens` |integer |`[128, 640]`,且 `>= min_frame_tokens` |单帧最多 token 数 |
|`min_frames` |integer |`[5, 16]` |整段视频最少抽帧数 |
```Plain Text
{
"model": "doubao-embedding-vision-251215",
"input": [
{
"type": "video_url",
"video_url": {
"url": "https://arkdocs.tos-cn-beijing.volces.com/videos/advanced-usage/ark_vlm_video_input.mp4",
"fps": 1,
"max_video_tokens": 120000,
"min_frame_tokens": 32,
"max_frame_tokens": 640,
"min_frames": 10
}
}
],
"encoding_format": "float"
}
```
使用这些字段时,抽帧策略会综合生效:按 `fps` 抽帧后,每帧按 `max_frame_tokens` 控制 token 上限,总 token 数不超过 `max_video_tokens`,实际抽帧数不低于 `min_frames`。若视频很短且 `fps` 过低导致抽帧数为 0,则会以 `min_frames` 兜底。
## 设置 instructions 字段(推荐)
`instructions` 字段是影响模型效果的关键。为了显著提升向量表示的精度,您需要根据具体的业务场景来定制该指令。**请勿直接使用系统默认值**。
通过合理设置 `instructions`,您可以引导模型更准确地聚焦输入内容的关键信息,从而适配特定的任务需求。这在跨模态检索、特定领域数据处理等场景中尤其有效。
> 注意:仅 `doubao-embedding-vision-251215` 及后续版本支持 `instructions` 字段。
### **配置规则**
构建指令前需明确两种核心角色,二者在不同任务中的配置规则差异显著:
* **Query(查询侧)**:发起检索 / 查询的主体,如用户输入的问题、检索关键词、待匹配的图片/视频等。
* **Corpus(语料侧)**:被查询的对象,如文档库、图片库、视频库中的单条数据样本。
根据任务类型不同,`Instructions` 字段分为 **召回 / 排序类** 和 **聚类 / 分类 / 语义文本相似度(STS)类** 两大场景,具体配置模板如下表:
|任务类型 |是否区分 Query/Corpus |核心配置模板 |
|---|---|---|
|召回、排序类 |是 |Query:`Target_modality: {}.\nInstruction:{}\nQuery:` | \
| | |Corpus:`Instruction:Compress the {} into one word.\nQuery:` |
|聚类、分类、STS 类 |否 |所有数据:`Target_modality: {}.\nInstruction:{}\nQuery:` |
**通用要求**:所有模板仅需填充 `{}` 部分,其余固定内容**禁止修改**。
### 召回、排序类任务配置规则
此类任务用于根据 Query 计算与 Corpus 的相似度,实现目标内容的召回或排序,Query 和 Corpus 需分别配置 `Instruction`。
#### **Query 查询侧配置**
```Plaintext
Target_modality: {}.\nInstruction:{}\nQuery:
```
**字段填写说明**
1. **`Target_modality`** **填充规则**
* 填写依据:**与 Query 自身模态无关**,完全取决于待召回的 **Corpus 底库的模态类型**。
* 多模态混合场景:
* 若 Corpus 库中**存在多种**独立模态样本(如部分为 text、部分为 image、部分为 video、部分为 text and video),需用 `/` 分隔所有模态;
* 若 Corpus 库中**每条样本均包含**多种模态(如每条样本都有 text + video),则用 `and` 连接。
* 常见示例
|Corpus 库模态情况 |Target_modality 填写值 |
|---|---|
|所有样本均为纯文本 |text |
|所有样本均为图片 + 文本组合 |text and image |
|所有样本均为纯视频 |video |
|所有样本均为文本 + 视频组合 |text and video |
|样本包含 text、image、video 三类 |text/image/video |
|样本包含 text、video、text and video 三类 |text/video/text and video |
> **注意**
>
> `Target_modality`的填写错误会直接导致检索精度下降,请严格匹配 Corpus 库或数据集的模态。
2. **`Instruction`** **填充规则**
* 核心原则:**禁止使用默认值** **`Compress the text into one word`**,需根据业务场景定制。
* 推荐示例
* 文本检索:`为这个句子生成表示以用于检索相关文章`
* 跨模态问答:`根据这个问题,找到能回答这个问题的相应文本或图片`
#### Corpus **语料**侧配置
```Plaintext
Instruction:Compress the {} into one word.\nQuery:
```
**字段填写说明**
* 填充依据:仅需匹配 **当前单条 Corpus 数据的模态**,无需考虑整个 Corpus 库的模态分布。
* 常见示例:`text`、`image`、`video`、`text and image`、`text and video`、`image and video`
### 聚类、分类、STS 类任务配置规则
此类任务不区分 Query 和 Corpus,所有数据采用**完全相同**的 `Instruction` 配置。
```Plaintext
Target_modality: {}.\nInstruction:{}\nQuery:
```
**字段填写说明**
1. **`Target_modality`** **填充规则**
* 填写依据:**整个数据集的统一模态类型**,所有数据的该字段值保持一致。
* 填写格式:与召回类任务的 `Target_modality` 格式一致(单模态填对应值,多模态组合用 `and`)。
2. **`Instruction`** **填充规则**
* 核心原则:**禁止使用默认值**,需贴合具体任务场景。
* 典型示例
* STS 语义相似度任务:`Retrieve semantically similar text`
### 高级用法
若上述指令无法满足需求,可以参考 MTEB (Massive Text Embedding Benchmark) 提供的 [示例](https://github.com/embeddings-benchmark/mteb/blob/main/mteb/models/model_implementations/seed_1_6_embedding_models.py) 指令进行尝试。
### 典型场景配置示例
#### 纯文本任务
##### 场景 1:对称检索(STS 语义相似度匹配)
* **场景描述**:检索语义相似句子,如对比 “一只熊猫正从滑梯上滑下来” 和 “熊猫从滑梯上滑下来”。
* **配置规则**:两条样本的 `Instruction` 完全一致。
* **Instruction 字段示例**
```Plaintext
Target_modality: text.\nInstruction:Retrieve semantically similar text\nQuery:
```
* **Input 字段**:填写样本正文(如上述两个句子)。
##### 场景 2:非对称检索(问答、摘要搜全文)
* **场景描述**:用短 Query(问题 / 摘要)检索长 Corpus(答案 / 全文)。
* **配置示例**
|角色 |Instruction 字段配置 |
|---|---|
|Query |`Target_modality: text.\nInstruction:为这个句子生成表示以用于检索相关文章\nQuery:` |
|Corpus |`Instruction:Compress the text into one word.\nQuery:` |
#### 多模态任务
##### 场景 1:对称检索(文 / 图 / 视频互搜)
* **通用前提**:当文本为图片 / 视频的**完整描述**时(例如“蓝色的天空下,一只狗在草坪上奔跑,草坪上还有一些帐篷”),可使用默认指令配置。
* **配置示例**
|检索类型 |Query 侧 Instruction 配置 |Corpus 侧 Instruction 配置 |
|---|---|---|
|文搜图 |`Target_modality: image.\nInstruction:Compress the text into one word.\nQuery:` |`Instruction:Compress the image into one word.\nQuery:` |
|文搜视频 |`Target_modality: video.\nInstruction:Compress the text into one word.\nQuery:` |`Instruction:Compress the video into one word.\nQuery:` |
|图搜文 |`Target_modality: text.\nInstruction:Compress the image into one word.\nQuery:` |`Instruction:Compress the text into one word.\nQuery:` |
|视频搜文 |`Target_modality: text.\nInstruction:Compress the video into one word.\nQuery:` |`Instruction:Compress the text into one word.\nQuery:` |
|图搜图(整体内容匹配) |`Target_modality: image.\nInstruction:Compress the image into one word.\nQuery:` |`Instruction:Compress the image into one word.\nQuery:` |
* **特殊提示**:若 Query 为**短词文搜图**(如 “蓝色海景”),建议替换 Query 侧 Instruction 为:`Find me an everyday image that matches the given caption`。
* **注意**:图片局部截取检索原图,不属于对称检索,需按非对称检索配置。
##### 场景 2:非对称检索
* **通用规则**:仅在 Query 侧定制指令,Corpus 侧使用默认模板;指令需明确匹配规则。
* **典型场景示例**
|业务场景 |Query 侧 Instruction 配置 |Corpus 侧 Instruction 配置 |
|---|---|---|
|跨模态问答(Query:文本问题;Corpus:文本 / 图片) |`Target_modality: text/image.\nInstruction:根据这个问题,找到能回答这个问题的相应文本或图片\nQuery:` |文本 Corpus:`Instruction:Compress the text into one word.\nQuery:` | \
| | |图片 Corpus:`Instruction:Compress the image into one word.\nQuery:` |
|原图检索(忽略 PS 处理) |`Target_modality: image.\nInstruction:查找与本图完全相同的图片,可能经过了ps处理,包含缩放、裁剪和水印,请忽略PS处理痕迹\nQuery:` |`Instruction:Compress the image into one word.\nQuery:` |
|电商服装检索(忽略背景 / 人物) |`Target_modality: image.\nInstruction:忽略背景以及人物主体并查找这张图片中出现的同款商品图片\nQuery:` |`Instruction:Compress the image into one word.\nQuery:` |
|电商商品检索(文本描述搜图) |`Target_modality: image.\nInstruction:根据下面的文本中对商品的描述,找到对应的符合条件的商品图片\nQuery:` |`Instruction:Compress the image into one word.\nQuery:` |
|菜品检索(文本描述搜图) |`Target_modality: image.\nInstruction:根据这段文本中提到的有关的菜品,找到相关的菜品的图片\nQuery:` |`Instruction:Compress the image into one word.\nQuery:` |
## 设置向量维度 `dimensions`
向量化是通过向量来表征文本、图像等非结构化数据的过程,让计算机能理解语言、图像等的含义。其中,向量维度是描述向量化后向量中元素的个数(标注词义/图像特征的维度)。在多模态向量化场景,每个维度对应文本的一个特征或者是对应图像的像素、色彩等视觉特征。
`doubao-embedding-vision-250615`及后续版本支持通过`dimensions` 参数指定稠密向量的输出维度,对输出的`data.embedding` 字段生效。
> **注意**
>
> 稀疏向量为固定维度,不支持单独设置维度。开启多向量后,`data.multi_embedding` 中每个子向量的列数与请求中的 `dimensions` 保持一致;未传 `dimensions` 时使用模型默认维度。
```Plaintext
{
"model": "doubao-embedding-vision-251215",
"input": [
{
"type":"text",
"text":"天很蓝"
}
],
"dimensions": 1024, #设置向量维度
"encoding_format":"float"
}
```
## 图片格式说明
### 图片传入方式
图片 URL 或图片 Base64 编码。用图片 URL 方式时,需确保图片 URL 可被访问。
### 图片文件容量
单张图片小于 10 MB。
使用 base64 编码,请求中请求体大小不可超过 64 MB。
### 图片像素说明
模型能够支持尺寸更加灵活的图片,传入图片满足下面条件:
* 图片宽高长度(单位 px):大于 14。
*图片像素(宽*高,单位 px):小于 3600万。
### 图片数量说明
* 支持不限数量的视频、文本和图片混合输入。
### token 用量说明
模型理解图片,会将图片转化为 token ,再进行推理计算。token 用量,根据图片宽高像素计算可得。图片转化 token 的公式为:
```Plaintext
min(图片宽 * 图片高/784, 单图 token 限制)
```
*图片尺寸为 1280 px * 720 px,即宽为 1280 px,高为 720 px,传入模型图片 token 限制为 1312,则理解这张图消耗的 token 为`1280*720/784=1176`,因为小于 1312,消耗 token 数为 1176 。
*图片尺寸为 1920 px * 1080 px,即宽为 1920 px,高为 1080 px,传入模型图片 token 限制为 1312,则理解这张图消耗的 token 为`1920*1080/784=2645`,因为大于 1312,消耗 token 数为 1312 。这时会压缩 token,即图片的细节会丢失部分,譬如字体很小的图片,模型可能就无法准确识别文字内容。
### 图片文件格式
支持的图片格式如下表,需注意文件后缀和图片格式需要匹配,即图片文件扩展名(URL 传入)、编码中图片格式声明(Base64 编码传入)需要与图片实际信息一致。
|**图片格式** |**文件扩展名** |**内容格式** **Content Type** | \
| | | | \
| | |> * [上传图片至对象存储时设置](https://docs.volcengine.com/docs/6349/145523?lang=zh#%E8%AE%BE%E7%BD%AE%E6%96%87%E4%BB%B6%E5%85%83%E6%95%B0%E6%8D%AE)。 | \
| | |> * 传入图片 Base64 编码时使用:[Base64 编码输入](/docs/image-understanding#477e51ce)。 |
|---|---|---|
|JPEG |.jpg, .jpeg |`image/jpeg` |
|PNG |.apng, .png |`image/png` |
|GIF |.gif |`image/gif` |
|WEBP |.webp |`image/webp` |
|BMP |.bmp |`image/bmp` |
|TIFF |.tiff, .tif |`image/tiff` |
|ICO |.ico |`image/x-icon` |
|DIB |.dib |`image/bmp` |
|ICNS |.icns |`image/icns` |
|SGI |.sgi |`image/sgi` |
|JPEG2000 |.j2c, .j2k, .jp2, .jpc, .jpf, .jpx |`image/jp2` |
> **说明**
>
> TIFF、 SGI、ICNS、JPEG2000 几种格式图片,需要保证和元数据对齐如在对象存储中正确设置文件元数据,否则会解析失败。
## 视频输入说明
对视频按固定间隔抽取画面后,交由模型进行理解。
> 仅 doubao-embedding-vision-250615及后续版本支持视频输入。
### 视频文件格式
|**视频格式** |**文件扩展名** |**内容格式** **Content Type** | \
| | | | \
| | |> * [上传视频至对象存储时设置](https://docs.volcengine.com/docs/6349/145523?lang=zh#%E8%AE%BE%E7%BD%AE%E6%96%87%E4%BB%B6%E5%85%83%E6%95%B0%E6%8D%AE)。 | \
| | |> * 传入 Base64 编码时使用:[Base64 编码输入](/docs/image-understanding#477e51ce)。 | \
| | |> * 视频格式需小写 |
|---|---|---|
|MP4 |.mp4 |`video/mp4` |
|AVI |.avi |`video/avi` |
|MOV |.mov |`video/quicktime` |
### 视频文件容量
单视频文件需在 50MB 以内。
### 不支持音频理解
暂不支持对视频文件中的音频信息进行理解。
### 用量说明
单视频 token 用量范围在[10k, 80k] ,单次请求视频最大 token 量还受模型的最大上下文窗口以及最大输入长度(当启用深度推理模式)限制,超出则请调整传入视频数量或视频长度。
方舟根据帧图像(指输入给模型的帧图像)张数(视频时长 * **fps** ),对帧图像进行压缩,以平衡对于视频的理解精度和 token 用量。帧图像会被等比例压缩至 [128 token, 640 token] ,对应像素范围在 [10万 像素, 50万像素]。
如`fps`过高或视频长度过长,需要处理的帧图像数量超出 640 帧(80×1024 token ÷ 128 token / 帧 = 640 帧),则按帧图像 128 token `视频时长/640` 时间间隔均匀抽取 640帧。此时与请求中的配置不符,建议评估输出效果,按需调整视频时长或 **fps** 字段配置。
如`fps`过小或视频长度过短,需要处理的帧图像数量不足16帧(10×1024 token ÷ 640 token / 帧 = 16 帧),则按帧图像 640 token `视频时长/16` 时间间隔均匀抽取 16帧。
### 自定义抽帧参数
> 仅 `doubao-embedding-vision-251215` 及后续版本支持。
可通过 `input[].video_url` 中的以下字段自定义抽帧策略:
* `fps`:控制抽帧频率,值越大,对画面变化的理解越精细,但 token 消耗更高。
* `max_video_tokens`:控制整段视频可消耗的最大 token 数。
* `min_frame_tokens` / `max_frame_tokens`:共同控制单帧的 token 下限与上限,平衡单帧质量与总体成本。
* `min_frames`:保证极短视频也能抽到足够帧数。
这些参数会协同生效。若按 `fps` 计算出的抽帧数量小于 `min_frames`,则优先满足 `min_frames`;若视频时长极短导致抽帧数为 0,则也会用 `min_frames` 兜底。
# 最佳实践:多模态相似度匹配示例
## 场景概述
下述程序展示如何通过文本描述检索图片库中的相关素材。
程序读取包含 5 张水果图片 URL 的列表,调用 Doubao-embedding-vision 模型为每张图片生成向量表示。当用户输入查询文本“草莓”时,程序将其转换为向量,并通过余弦相似度与图片向量库匹配,并输出最相似图片和相似度分数。图片 Corpus 和文本 Query 分别使用与角色匹配的 `instructions`,使生成的向量适用于以文搜图。该流程可用于电商商品检索、媒体素材管理等场景。

## 第一步:导入库包
导入所需的库包,并设置 API Key,为后续的数据处理和分析做准备。
```Python
...
import math
import os
from arkruntime import Ark
from arkruntime.types.multimodal_embedding import MultiModalEmbeddingResponse
IMAGE_CORPUS_INSTRUCTIONS = (
"Instruction:Compress the image into one word.\nQuery:"
)
TEXT_QUERY_INSTRUCTIONS = (
"Target_modality: image.\n"
"Instruction:根据水果名称检索匹配的图片\n"
"Query:"
)
...
```
## 第二步:获取向量
定义一个函数将单个文本或图片转换为向量表示。支持文本和图片 URL 两种输入类型:图片使用 Corpus 侧指令,文本使用目标模态为图片的 Query 侧指令。函数调用 `doubao-embedding-vision-251215` 模型获取 float 格式向量。
```Python
...
def get_embedding(input_data, input_type="text"):
"""调用火山引擎API获取单个文本或图片的向量表示"""
client = Ark(
api_key=os.environ.get("ARK_API_KEY"),
base_url="https://ark.cn-beijing.volces.com/api/v3",
)
if input_type == "text":
input_item = {"type": "text", "text": input_data}
instructions = TEXT_QUERY_INSTRUCTIONS
elif input_type == "image_url":
input_item = {"type": "image_url", "image_url": {"url": input_data}}
instructions = IMAGE_CORPUS_INSTRUCTIONS
else:
raise ValueError("输入类型仅支持'text'或'image_url'")
try:
resp = client.post(
"/embeddings/multimodal",
cast_to=MultiModalEmbeddingResponse,
body={
"model": "doubao-embedding-vision-251215",
"encoding_format": "float",
"input": [input_item],
"instructions": instructions,
},
)
embedding = resp.data.embedding
if not isinstance(embedding, list):
raise TypeError("API 未返回 float 格式向量")
return embedding
except Exception as e:
print(f" 获取向量失败,输入类型: {input_type}, 错误: {str(e)}")
raise
...
```
## 第三步:生成向量库
批量处理图片 URL 列表,生成对应的向量表示,并构建向量库。
```Python
...
def generate_image_embeddings(image_urls):
"""批量生成图片向量并构建向量库"""
print(f"[1/3] 开始生成 {len(image_urls)} 张图片的向量...")
embeddings = []
for i, url in enumerate(image_urls):
try:
embedding = get_embedding(url, "image_url")
embeddings.append({
"image_url": url,
"embedding": embedding
})
print(f" [{i+1}/{len(image_urls)}] 成功: {url}")
except Exception as e:
print(f" [{i+1}/{len(image_urls)}] 失败: {url} - {str(e)}")
continue
if not embeddings:
raise ValueError("所有图片向量生成失败")
print(f"[2/3] 完成: {len(embeddings)} 个有效向量")
return embeddings
...
```
## 第四步:图片相似度计算
利用余弦相似度来度量文本与图片之间的相似性,实现了一个基于内容的图片搜索功能。用户可以通过输入文本描述,检索与该描述最相关的图片。
```Python
...
def cosine_similarity(left, right):
"""计算两个等长向量的余弦相似度。"""
if len(left) != len(right):
raise ValueError("向量维度不一致")
dot_product = sum(a * b for a, b in zip(left, right))
left_norm = math.sqrt(sum(value * value for value in left))
right_norm = math.sqrt(sum(value * value for value in right))
if left_norm == 0 or right_norm == 0:
raise ValueError("向量模长不能为 0")
return dot_product / (left_norm * right_norm)
def search_similar_images(query_embedding, embeddings, top_n=1, query_type="文本"):
"""搜索与查询向量最相似的图片"""
print(f"\n[3/3] 开始搜索与{query_type}最相似的图片...")
results = []
for item in embeddings:
similarity = cosine_similarity(
query_embedding,
item["embedding"],
)
results.append({
"image_url": item["image_url"],
"similarity": similarity
})
results.sort(key=lambda x: x["similarity"], reverse=True)
print(f" - 相似度计算完成,共 {len(results)} 个结果")
return results[:top_n]
...
```
## 第五步:示例用法
测试搜索功能,调用`generate_image_embeddings`函数生成图片向量库,使用文本查询搜索相似图片,并返回最相似的结果。示例代码如下:
```Python
...
if __name__ == "__main__":
image_urls = [
"https://arkdocs.tos-cn-beijing.volces.com/images/domain-models/Fruit1.jpg",
"https://arkdocs.tos-cn-beijing.volces.com/images/domain-models/Fruit2.jpg",
"https://arkdocs.tos-cn-beijing.volces.com/images/domain-models/Fruit3.jpg",
"https://arkdocs.tos-cn-beijing.volces.com/images/domain-models/Fruit4.jpg",
"https://arkdocs.tos-cn-beijing.volces.com/images/domain-models/Fruit5.jpg"
]
query_text = "草莓"
try:
# 生成图片向量
image_embs = generate_image_embeddings(image_urls)
# 生成文本向量
text_emb = get_embedding(query_text, "text")
print(f"文本向量维度: {len(text_emb)}")
# 搜索相似图片
similar_images = search_similar_images(text_emb, image_embs)
print(f"最相似图片: {similar_images[0]['image_url']}")
print(f"相似度分数: {similar_images[0]['similarity']:.4f}")
except Exception as e:
print(f"程序失败: {e}")
...
```
## 运行结果示例
以下结果基于 `doubao-embedding-vision-251215` 和本示例的 Query/Corpus 指令生成。不同模型版本或 `instructions` 会改变向量空间和相似度分数,不应直接比较不同配置下的绝对分数;检索效果应以同一配置下的相对排序为准。
* 开始生成 5 张图片的向量,依次对 5 个图片 URL发起请求,均返回 “成功”,表明 API 调用正常且图片链接可访问、格式合规。
* 完成处理,生成 5 个有效向量,文本向量维度为 2048,与模型输出维度一致,向量数量与输入图片数量匹配,无数据丢失。
* 开始相似度匹配,对文本向量与 5 个图片向量进行相似度计算,最终返回最相似图片为 Fruit5.jpg,表明两者在特征空间中具有较强相关性。
```Plain Text
[1/3] 开始生成 5 张图片的向量...
[1/5] 成功: https://arkdocs.tos-cn-beijing.volces.com/images/domain-models/Fruit1.jpg
[2/5] 成功: https://arkdocs.tos-cn-beijing.volces.com/images/domain-models/Fruit2.jpg
[3/5] 成功: https://arkdocs.tos-cn-beijing.volces.com/images/domain-models/Fruit3.jpg
[4/5] 成功: https://arkdocs.tos-cn-beijing.volces.com/images/domain-models/Fruit4.jpg
[5/5] 成功: https://arkdocs.tos-cn-beijing.volces.com/images/domain-models/Fruit5.jpg
[2/3] 完成: 5 个有效向量
文本向量维度: 2048
[3/3] 开始搜索与文本最相似的图片...
- 相似度计算完成,共 5 个结果
最相似图片: https://arkdocs.tos-cn-beijing.volces.com/images/domain-models/Fruit5.jpg
相似度分数: 0.4515
```
#
# 相关技术
## 相似度计算
不同类型向量需使用对应的相似度计算方法,错误使用会导致结果偏差。核心计算逻辑:余弦相似度 = 向量L2归一化后做点积。
|向量类型 |支持版本 |计算方法 |说明 |
|---|---|---|---|
|稠密向量(Dense Embedding) |所有版本 |余弦相似度 |先对向量做 L2 归一化,再计算点积 |
|稀疏向量(Sparse Embedding) |250615及后续版本 |余弦相似度 |仅计算非零元素的点积,效率更高;**仅支持文本输入场景** |
## Base64 编码输入
如果你要传入的视频/图片在本地,你可以将这个视频/图片转化为 Base64 编码,然后提交给大模型。下面是一个简单的转换示例代码。
> **注意**
>
> 传入 Base64 编码格式时,请遵循以下规则:
> * 传入的是图片:
>
> * 格式遵循`data:image/<图片格式>;base64,`,其中,
>
> * 图片格式:`jpeg`、`png`、`gif`等,支持的图片格式详细见[图片格式说明](/docs/vectorization#a256838b)。
>
> * Base64 编码:图片的 Base64 编码。
> * 传入的是视频:
>
> * 格式遵循`data:video/<视频格式>;base64,`,其中,
>
> * 视频格式:`MP4`、`AVI`等,支持的视频格式详细见 [视频格式说明](/docs/vectorization#273d72af)。
>
> * Base64 编码:视频的 Base64 编码。
```Python
# 定义方法将指定路径图片转为Base64编码
def encode_image(image_path):
with open(image_path, "rb") as image_file:
return base64.b64encode(image_file.read()).decode('utf-8')
# 需要传给大模型的图片
image_path = "path_to_your_image.jpg"
# 将图片转为Base64编码
base64_image = encode_image(image_path)
```
转换后,图片的url格式参考如下:
```Python
{
"type": "image_url",
"image_url": {
"url": f"data:image/;base64,{base64_image}"
}
},
```
# 应用场景
您可以在以下场景中使用模型的多模态向量化能力。
| | | | |
|**场景** |**细分场景** |**业务需求场景** |场景举例 |
|---|---|---|---|
|批量数据向量化处理 |\- |需要对大量数据进行离线处理以转换为向量表示时,使用多模态向量化模型进行批量请求处理。 |批量处理电子商务平台上的商品图片,将其转换为向量表示以便于相似性匹配。 |
|文本描述检索 |文搜图 |在图库场景中,用户侧重以文本描述来检索符合描述的图片。 |用户输入“蓝色海景”,系统根据描述搜索并展示相关蓝色海景图片。 |
| |文搜文 |用于在知识库中进行文本描述检索,找到相关文档或知识库内容。 |用户输入“如何重置密码”,系统检索知识库中包含密码重置方法的文档。 |
|图片特征检索 |图搜图 |图片检索相似物体。通过用户提供的图片,在不同场景下检索同一类物体,例如用于商品图搜索。 |用户上传一张椅子图片,系统返回相似款式的椅子商品图片。 |
| |图文搜图 |图片特征的侧重提取,结合文本检索。电商搜索应用中,用户可以通过微调商品颜色等特征以提高检索结果精度。 |用户在搜索中指定产品颜色为“深蓝色”,系统根据颜色特征筛选商品图片。 |
| |图文搜图文 |多模态知识库搜索。用户提供图片及问题描述,在多模态知识库场景中搜索符合需求的内容。 |用户上传一个手机截图并描述“无法连接网络”,系统搜索相关网络连接故障解决方案。 |
# 附:向量批量处理的解决方案
针对 API 仅支持单次传入单张图片的限制,本代码通过异步并发 + 批量分组策略提升图片向量化的批量处理效率:利用 asyncio 创建异步任务,将图片按设定批次分组后并发调用 API;采用 “全组失败回滚” 模式确保每组任务结果一致,支持失败重试,且单独保存成功 / 失败结果(包含向量详情、错误信息和图片输入 URL)。
```Python
import asyncio
import os
from pathlib import Path
from arkruntime import AsyncArk
class MultimodalEmbedder:
"""多模态向量化批量处理工具(全组失败模式)"""
def __init__(self, api_key: str, model: str = "doubao-embedding-vision-241215",
batch_size: int = 10, retries: int = 2):
self.api_key = api_key
self.model = model
self.batch_size = batch_size # 批量大小配置(可扩展分片逻辑)
self.retries = retries # 批量请求重试次数
async def batch_process(self, items_list):
"""核心:异步批量处理向量任务(全组失败)"""
# 1. 初始化批量客户端
async with AsyncArk(
max_retries=self.retries,
base_url="https://ark.cn-beijing.volces.com/api/v3",
) as client:
# 2. 批量创建异步任务(按输入列表分片)
batch_tasks = [
asyncio.create_task(client.multimodal_embeddings.create(multi_embedding={"type": "disabled"}, model=self.model, input=items))
for items in items_list
]
try:
# 3. 批量等待任务完成(任一失败则全组终止)
batch_results = await asyncio.gather(*batch_tasks)
return batch_results
except Exception:
# 4. 批量清理未完成任务
for task in batch_tasks:
if not task.done():
task.cancel()
raise # 抛出异常,保持全组失败语义
def batch_save(self, batch_results, output_dir: str = "embedding_results"):
"""核心:批量保存向量结果"""
# 1. 初始化输出目录
Path(output_dir).mkdir(exist_ok=True)
# 2. 批量写入结果文件
with open(f"{output_dir}/batch_embeddings.txt", "w", encoding="utf-8") as f:
for idx, result in enumerate(batch_results, 1):
embedding = result.data.embedding
f.write(f"批量项 #{idx} | 向量长度: {len(embedding)} | 前20维: {embedding[:20]}...\n")
print(f"批量结果已保存:{output_dir}/batch_embeddings.txt")
if __name__ == "__main__":
# 1. 配置初始化
api_key = os.environ.get("ARK_API_KEY") or input("输入API密钥: ").strip()
if not api_key:
raise ValueError("API密钥不能为空")
# 2. 初始化批量处理器
embedder = MultimodalEmbedder(api_key=api_key, batch_size=10, retries=2)
# 3. 构造批量输入数据
batch_inputs = [
[{"type": "text", "text": "天很蓝,海很深"}, {"type": "image_url", "image_url": {"url": "https://example.com/image1.jpg"}}],
[{"type": "text", "text": "阳光明媚的沙滩"}, {"type": "image_url", "image_url": {"url": "https://example.com/image2.jpg"}}]
]
# 4. 执行批量处理+结果保存
try:
batch_results = asyncio.run(embedder.batch_process(batch_inputs))
embedder.batch_save(batch_results)
print(f"批量处理完成,共生成 {len(batch_results)} 个向量")
except Exception as e:
print(f"批量处理失败: {str(e)}")
```
---
# 工具概述
Source: https://ark.volcengine.com/region:cn-beijing/docs/tools-overview
在生成模型响应时,您可以使用方舟大模型内置工具、函数调用(Function Calling)以及 MCP 等工具来扩展模型的功能。
这些功能使模型能够自行判断,并决策是否调用搜索网络资料、图片处理等内置工具或者您自己的自定义函数。
## 快速入门
> **说明**
>
> 请将示例代码中的占位符替换为真实值。关于 `` 的获取方法,请参见[快速入门](/docs/quick-start)。关于 `` 的获取方法,请参见 [查看知识库详情](https://docs.volcengine.com/docs/vector_database_vikingdb/Viewingknowledgebasedetails?lang=zh)。
**选项:豆包助手 API**
```Bash
curl --location 'https://ark.cn-beijing.volces.com/api/v3/responses' \
--header "Authorization: Bearer $ARK_API_KEY" \
--header 'Content-Type: application/json' \
--header 'ark-beta-doubao-app: true' \
--data '{
"model": "doubao-seed-2-1-pro-260915",
"stream": true,
"tools": [
{
"type": "doubao_app",
"feature": {
"ai_search": {
"type": "enabled",
"role_description": "你是科技领域助手,专业解答行业问题"
}
}
}
],
"input": [
{
"type": "message",
"role": "user",
"content": [
{
"type": "input_text",
"text": "今天有什么AI领域热点新闻"
}
]
}
]
}'
```
**选项:联网内容插件**
```Bash
curl --location 'https://ark.cn-beijing.volces.com/api/v3/responses' \
--header "Authorization: Bearer " \
--header 'Content-Type: application/json' \
--data '{
"model": "doubao-seed-2-1-pro-260915",
"stream": true,
"tools": [
{"type": "web_search"}
],
"input": [
{
"role": "user",
"content": [
{
"type": "input_text",
"text": "今天有什么热点新闻"
}
]
}
]
}'
```
**选项:豆包搜索 Custom 版**
```Bash
curl --location 'https://ark.cn-beijing.volces.com/api/v3/responses' \
--header "Authorization: Bearer $ARK_API_KEY" \
--header 'Content-Type: application/json' \
--data '{
"model": "doubao-seed-2-1-pro-260915",
"stream": true,
"tools": [
{
"type": "web_search",
"sources": ["doubao"]
}
],
"input": [
{
"role": "user",
"content": [
{
"type": "input_text",
"text": "今天有什么 AI 领域的热点新闻?"
}
]
}
]
}'
```
**选项:图像处理**
```Bash
curl --location 'https://ark.cn-beijing.volces.com/api/v3/responses' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer ' \
--header 'ark-beta-image-process: true' \
--data '{
"model": "doubao-seed-2-1-pro-260915",
"stream": true,
"tools": [
{"type": "image_process"}
],
"input": [
{
"type": "message",
"role": "system",
"content": [
{
"type": "input_text",
"text": "数一数有多少颗草莓?"
},
{
"type": "input_image",
"image_url": "https://arkdocs.tos-cn-beijing.volces.com/images/tool-calling/image_process_2.jpg"
}
]
}
]
}'
```
**选项:私域知识库搜索**
```Bash
curl --location 'https://ark.cn-beijing.volces.com/api/v3/responses' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer ' \
--header 'ark-beta-knowledge-search: true' \
--data '{
"model": "doubao-seed-2-1-pro-260915",
"stream": true,
"thinking": {
"type": "disabled"
},
"tools": [
{
"type": "knowledge_search",
"knowledge_resource_id": "",
"limit": 2,
"ranking_options": {
"get_attachment_link": true
}
}
],
"input": [
{
"role": "user",
"content": "机票选择页面中,如何选择该航班不同价格的机票?"
}
],
"max_tool_calls": 1
}'
```
**选项:MCP**
```Bash
curl --location 'https://ark.cn-beijing.volces.com/api/v3/responses' \
--header "Authorization: Bearer " \
--header 'Content-Type: application/json' \
--header 'ark-beta-mcp: true' \
--data '{
"model": "doubao-seed-2-1-pro-260915",
"stream": true,
"tools": [
{
"type": "mcp",
"server_label": "deepwiki",
"server_url": "https://mcp.deepwiki.com/mcp",
"require_approval": "never"
}
],
"input": [
{
"role": "user",
"content": [
{
"type": "input_text",
"text": "看一下volcengine/ai-app-lab这个repo的文档"
}
]
}
]
}'
```
**选项:函数调用**
```Python
from arkruntime import Ark
from arkruntime.types.chat import ChatCompletion
import json
client = Ark(
base_url="https://ark.cn-beijing.volces.com/api/v3",
)
messages = [
{"role": "user", "content": "北京和上海今天的天气如何?"}
]
# 步骤1: 定义工具
tools = [{
"type": "function",
"function": {
"name": "get_current_weather",
"description": "获取指定地点的天气信息",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "地点的位置信息,例如北京、上海"
},
"unit": {
"type": "string",
"enum": ["摄氏度", "华氏度"],
"description": "温度单位"
}
},
"required": ["location"]
}
}
}]
def get_current_weather(location: str, unit="摄氏度"):
# 实际调用天气查询 API 的逻辑
# 此处为示例,返回模拟的天气数据
return f"{location}今天天气晴朗,温度 25 {unit}。"
while True:
# 步骤2: 发起模型请求,由于模型在收到工具执行结果后仍然可能有工具调用意愿,因此需要多次请求
completion: ChatCompletion = client.chat.completions.create(
model="doubao-seed-2-1-pro-260915",
messages=messages,
tools=tools
)
resp_msg = completion.choices[0].message
# 展示模型中间过程的回复内容
print(resp_msg.content)
if completion.choices[0].finish_reason != "tool_calls":
# 模型最终总结,没有调用工具意愿
break
messages.append(completion.choices[0].message.model_dump())
tool_calls = completion.choices[0].message.tool_calls
for tool_call in tool_calls:
tool_name = tool_call.function.name
if tool_name == "get_current_weather":
# 步骤 3:调用外部工具
args = json.loads(tool_call.function.arguments)
tool_result = get_current_weather(**args)
# 步骤 4:回填工具结果,并获取模型总结回复
messages.append(
{"role": "tool", "content": tool_result, "tool_call_id": tool_call.id}
)
```
## 支持的工具
### 内置工具
当通过 Responses API 创建模型响应时,您可以通过在参数中配置 `tools` 字段来访问工具。每个工具中都有独特的配置要求,具体见如下教程:
* [豆包助手 API](/docs/doubao-assistant)
为您的应用快速集成与豆包 App 同款的 AI 功能,例如日常沟通、深度沟通和联网搜索,快速获得安全、可靠且可控的优质 AI 体验。
* [联网搜索工具](/docs/web-search)
支持豆包搜索 Custom 版和联网内容插件两种工具,可获取实时公开网络信息(如新闻、商品、天气等),解决数据时效性、知识盲区、信息同步等核心问题,并且无需自行开发搜索引擎或维护数据资源。
* [Image Process(图像处理工具)](/docs/image-process)
支持通过 Responses API 调用对输入图片执行画点、画线、旋转、缩放、框选/裁剪关键区域等基础操作,适用于需模型通过视觉处理提升图片理解的场景(如图文内容分析、物体定位标注、多轮视觉推理等)。工具通过模型自动判断图像处理逻辑,支持与自定义函数混合使用,且可处理多轮视觉输入(上一轮输出图片作为下一轮输入)。
* [Knowledge Search(私域知识库搜索工具)](/docs/knowledge-search)
支持通过 Responses API 调用直接获取企业私域知识库中的信息(如内部文档、产品手册、行业资料等),适用于需基于企业专属数据解答问题的场景(如内部培训问答、产品功能咨询、行业方案查询等)。工具通过模型自动判断是否需要调用私域知识库,支持与自定义函数、MCP 等工具混合使用,目前仅支持旗舰版知识库。
* [Apply Patch(代码补丁工具)](/docs/apply-patch)
支持通过结构化补丁格式创建、更新或删除文件,适用于让模型直接生成文件修改方案的场景(如批量代码改写、机械化重构、测试文件生成等)。通过 Responses API 既可以将其作为内置工具直接启用,也可以按自定义工具方式接入,以兼容现有工具编排流程。
### 自定义函数
您也可以在创建模型响应时,使用 `tools` 来定义自定义函数。模型通过调用自定义函数代码,来访问模型中无法直接使用的特定数据或功能。了解更多信息,请参见[Function Calling(函数调用)](/docs/function-calling)。
### 云部署 MCP 或 Remote MCP
Responses API 支持通过 Streamable HTTP 链接的 MCP 调用。适用于复杂任务(如多步数据查询 + 分析)场景,支持与自定义函数、Web Search 工具混合使用。详情请参见[云部署 MCP / Remote MCP](/docs/mcp-remote-mcp)。
---
# 豆包助手 API
Source: https://ark.volcengine.com/region:cn-beijing/docs/doubao-assistant
豆包助手 API 是火山方舟平台提供的与豆包同源的企业级 API 服务,旨在帮助企业快速构建可落地、可规模化、可演进的 AI 应用。通过 Responses API,您可将豆包 App 同款 AI 能力(如日常沟通、深度沟通、联网搜索等)快速集成至自有应用,无需从零开发,即可获得安全、可靠且可控的优质 AI 体验。
## 背景信息
### 适用场景
豆包助手 API 适用于从客户服务到业务决策的各类场景,主要有:日常知识问答、智能助手、智能硬件、学习教育、投研投顾等。
|**场景** |**一句话定位** |**核心价值点** |**典型场景** |**推荐方向** |
|---|---|---|---|---|
|日常沟通 |用于高频、情感丰富、即时反馈的人机交互场景。 |轻量、亲切、自然。 |* 生活助手:闲聊、陪伴、日常互动。 |* 智能终端助手、儿童陪伴/陪读。 | \
| | | |* 语音输出:讲解、导览、简单问答。 |* 车载助手、手机助手。 | \
| | | |* 指令式对话:帮我查、帮我写、帮我改。 |* 文旅、展馆、商场、设备内置助手。 | \
| | | |* 轻量内容生成:润色、改写、翻译。 | |
|深度沟通 |用于需要结构化思考、多步推理场景。 |思考纠偏、回复质量高、思考过程可理解。 |* 决策辅助:方案对比/策略分析/取舍权衡。 |* 企业内部分析型助手(产品/运营/战略/管理支持)。 | \
| | | |* 复杂创作:结构化回复/行业方案/商业分析(基于已有知识与逻辑)。 |* 专业 Copilot(不联网也能给出高质量判断)。 | \
| | | |* 学习与理解:原理解释/概念拆解/框架推演。 |* 学习型助手(进阶学习、体系化理解)。 | \
| | | | |* 对“答案质量”要求高、但不要求实时性的场景。 |
|联网搜索 |用于“答案依赖实时或外部信息”的问题。 |信息源丰富,实时获取,标注资料来源,兼顾信息时效性与可信度。 |* 核实信息与来源:用户快速确认事件或产品信息的真实性,并同时查看多方来源。 |* 学术/研究型问题。 | \
| | | |* 获取最新状态:用户实时获取政策、价格、行情等变化信息,确保决策基于当前数据。 |* 高风险决策。 | \
| | | |* 整合多渠道知识:用户将不同来源的信息汇总、分析,形成可直接使用的结论或摘要。 |* 复杂系统分析。 | \
| | | |* 验证对外输出内容:用户在讲解、报告或创作前,确保信息准确、来源可追溯。 |* 需要“不断修正假设”的问题探索。 |
|边想边搜 |结合搜索与分析能力,对公开信息进行多轮检索与整合,用于研究型、学习型、分析型问题。 |推理过程外显,多轮自我校验、中间结论可见。 |* 车载助手,手机助手,语音助手。 |* 研究型产品/分析工具。 | \
| | | |* 售后客服,工单诊断,运营分析。 |* 高风险、高不确定决策支持。 | \
| | | |* 文旅场景、展览讲解,需要加入背景知识。 |* 专业人员(研究、战略、投研)的探索式工作流。 | \
| | | |* 对信息准确性、可核验性要求高的场景。 | |
### **功能列表**
豆包助手 API 的上述适用场景分别对应一种功能,您可通过下表列出的功能标识在参数中指定使用哪项功能。
> **说明**
>
> 单次仅可开启一个功能,不支持同时开启多个功能。
|**功能名称** |**功能标识** |**功能介绍** |
|---|---|---|
|日常沟通 |chat |侧重自然对话,基于通用知识简要回答,无实时信息与深度分析。 |
|深度沟通 |deep_chat |基于已有知识库深度解析,逻辑更严谨,但无实时数据支持。 |
|联网搜索 |ai_search |通过实时联网获取最新资讯,信息时效性强,侧重结果呈现。 |
|边想边搜 |reasoning_search |结合思考过程与实时搜索,先拆解问题再验证信息,逻辑链条完整。 |
为直观展示不同功能的差异,以下通过同一问题 “豆包 App 可以做什么?” 在不同功能模式下的响应效果对比:
**选项:日常沟通(chat)**
```Plain Text
(输出)
我能提供多维度实用帮助,核心能力覆盖以下几类:
- 知识解答:精准回答各类事实性问题,从常识到专业领域关键信息,复杂概念会用简单类比辅助理解。
- 内容创作:撰写文案、小说片段、方案等,能提供多组差异化版本,适配不同场景与受众需求。
- 实用工具:处理翻译(兼顾准确与场景化)、分析文档、生成/编辑图片,还能完成数据分析、复杂计算等任务。
- 情感陪伴:像朋友一样聊天,共情你的情绪,提供简短安慰或建议,也能分享轻松话题。
需要我帮你具体做件事吗?比如分析一份文档内容,或是写一段特定场景的文案。
```
**选项:深度沟通(deep_chat)**
```Plain Text
(思维链)
用户问“豆包App可以做什么?”,需要全面且有条理地列出核心功能,同时符合手机阅读体验,避免冗长。首先,得分类梳理功能,比如知识类、创作类、实用工具类,这样用户一目了然。 知识类方面,要涵盖常见需求,比如解答问题、翻译、医学健康建议,这些是基础且高频的,需要精准说明,比如医学建议要强调科学依据,避免误导。 创作类要突出多样性,文案、小说、方案等,满足不同用户的创作需求,同时提到差异化备选项,体现专业性。 实用工具类要贴近生活和工作,比如处理文档、生成图片视频、语音互动,这些功能能提升用户效率,需要明确列出具体操作,比如“读取PDF/Excel并总结”“陪练英语口语”。 然后,结尾追问要符合要求,找出关键信息点加粗,提供具体可执行的服务,比如“帮你生成一份专属的旅行计划文案”,让用户只需判断是否需要,保持友好自然。 还要注意格式,用列表和加粗突出重点,段落清晰,控制篇幅,确保手机上阅读方便,没有冗余信息,同时语言简洁专业,让用户快速了解豆包的核心能力。
(输出)
豆包能提供多维度服务,核心能力可分为三大类,满足你学习、创作、生活等多场景需求:
1. 知识问答与信息解读
- 解答各类客观问题:从常识、学科知识到专业领域(如法律、科技),精准输出核心答案,复杂概念会用类比辅助理解。
- 提供翻译服务:覆盖单词、短语、复杂句子,兼顾准确性与场景化,多含义表达会补充使用说明。
- 给出医学健康建议:基于科学依据解读食品功效、药品使用(标注风险),区分中医与现代医学表述,不夸大功效。
2. 内容创作与优化
- 定制多样化文案:包括营销文案、朋友圈文案、演讲稿等,提供≥3组差异化备选项,适配不同受众与场景。
- 创作文学内容:支持小说片段、故事、散文等创作,注重语言质感与记忆点,可根据你的风格调整调性。
- 优化文本:对现有内容进行润色、精简、扩写,提升表达流畅度与专业性。
3. 实用工具与互动服务
- 处理文档与数据:读取PDF、Excel、Word等文件并总结,支持数据统计、格式转换,还能生成可视化图表。
- 生成多媒体素材:根据文本描述绘制图片、生成视频脚本,也可对图片进行加字、换背景等编辑。
- 提供语音互动:支持语音通话,可陪你练英语口语、唱歌,也能引导你完成声音克隆操作。
如果你有具体需求,比如想为周末出行做准备,我可以帮你生成一份专属的短途旅行计划文案,需要试试吗?
```
**选项:联网搜索(ai_search)**
```Plain Text
(搜索)
"搜索 2 个关键词,参考 5 篇资料","queries":["豆包App的功能介绍","豆包App可以做的事情"]
(输出)
豆包是一款功能强大的AI助手,能为用户提供多种服务,具体如下:
- 智能对话:作为24小时知识顾问,可回答历史、科学、技术、文化、地理等多领域问题,能理解上下文,通过追问帮助用户理清思路,解决复杂问题。
- 高效写作:拥有工作总结、营销文案、邮件、短视频脚本等多种模板,可分步骤生成内容,支持随时调整,还能通过金句模式提升文案感染力。
- AI搜索:输入问题后不仅返回链接,还直接给出整合答案,自动过滤低质量结果,提供权威信息,复杂问题时可自动搜索补充信息。
- 会议记录:会议中说“录音”可自动开启并转写,结束后自动生成纪要,标注重点、待办事项和责任人,支持多语言实时翻译,输出双语纪要。
- 文档处理:支持上传PDF、Word、图片等文件,可智能解析文档,总结核心观点,列出关键数据,进行中英对照翻译,还能将文档内容自动生成思维导图。
...
```
**选项:边想边搜(reasoning_search)**
```Plain Text
(思维链)
可能需要先确认“豆包App”是否指字节跳动的AI助手,用户可能混淆名称。得查官网或官方文档明确其功能范围,是否包含聊天、信息查询、内容生成等基础服务。还需验证是否支持多语言、图像识别等高级功能,以及是否有企业级应用案例。需要注意区分豆包与同类产品的差异点,比如是否整合抖音生态资源。同时得检查是否有2025年新增的AI功能或合作伙伴服务,比如智能硬件联动。需优先搜索最新产品手册和官方公告,避免引用过时信息。
(搜索)
"搜索 8 个关键词,参考 7 篇资料","queries":["豆包App可以做什么","豆包App 功能","豆包App 官方网站","豆包App 官方文档","豆包App 最新功能","豆包App 企业应用","豆包App AI 功能","豆包App 2025 更新"]
(思维链)
"用户询问豆包功能,先从基础入手:智能对话、文档处理、多模态创作等核心功能。需确认是否覆盖所有场景,比如教育、医疗、金融等行业应用。检查到2025年新增实时视频通话、音乐生成、AI播客等功能,可能遗漏了行业解决方案细节,比如企业API接口的具体应用。需验证是否有未提及的工具整合或高级分析功能,但现有信息已涵盖用户可能关心的工作、学习、生活全场景。进一步搜索可能带来更多细节,但现有信息已足够,现在就进入答复环节。
(输出)
"豆包是字节跳动推出的全能型AI助手,基于先进大模型技术,覆盖工作、学习、生活全场景,功能远超传统聊天工具。以下是其核心能力的详细解析:
一、基础交互与智能问答
1. 自然语言对话
支持普通话、方言语音输入,可连续对话并记忆上下文,像人类一样理解复杂指令。例如询问“秦始皇统一六国的时间”,能精准回答并拓展历史背景。
2. AI搜索与信息整合
输入问题后直接返回权威整合答案,无需跳转网页。例如搜索“5G技术特点”,会自动聚合高时效信息并结构化呈现。
3. 多模态交互
...
二、工作学习效率神器
1. 文档处理专家
- 智能解析:上传PDF、Word等文件,可自动总结核心观点、提取关键数据,如年报财务指标分析。
- 中英对照翻译:学术文献、商务合同边读边译,保留格式和专业术语。
- 思维导图生成:自动将文档内容转化为逻辑清晰的脑图,辅助梳理思路。
2. 高效写作工具
- 模板化创作:覆盖工作总结、营销文案、短视频脚本等50+模板,输入“小学三年级语文教案”即可生成完整教学计划。
- 分步骤优化:先出大纲再细化内容,支持实时润色和风格调整,如将“帮我写方案”改为“市场经理Q4活动策划”。
- 金句模式:添加“请用金句模式”可提升文案感染力,适合社交媒体推广。
3. 代码开发助手
支持Python、Java等30+编程语言,能生成可运行脚本并调试错误。例如输入“Python爬取天气数据并可视化”,可快速获得完整代码。
三、创意与艺术创作
1. AI绘画与设计
- 文生图:输入“海边日落,水彩风格”可生成1-4张候选图,支持调整细节如“添加帆船”。
- 图生图:上传参考图后可转换风格,如将风景照改为赛博朋克风。
- 实用工具:一键抠图、修复老照片、批量生成设计素材,适合自媒体和电商。
2. 视频生成与编辑
- 文本生视频:输入脚本自动生成画面、配音和字幕,支持1080P导出并分享至抖音。
- 图片生视频:单图添加动态效果和旁白,适合产品演示或教育培训。
- 对口型视频:上传人物照片后输入台词,生成自然对话视频,适合虚拟主播创作。
四、生活与健康助手
1. 日程与时间管理
- 语音设置提醒:直接说“今天10点开会,下午3点取快递”,自动同步手机日历并分类任务优先级。
- 会议记录神器:录音转文字并智能提取待办事项,支持多语言实时翻译,输出双语纪要。
2. 健康与生活服务
- 体检报告解读:分析指标异常并提供建议,如“低密度脂蛋白偏高如何调整饮食”。
- 本地生活推荐:基于抖音商家数据,根据口味和预算推荐附近餐厅,提供导航和团购链接。
- 旅行规划:输入目的地生成包含交通、景点、住宿的完整攻略,支持个性化调整。
五、企业级解决方案
1. 团队协作工具
- 企业API接口:可嵌入OA、CRM系统,实现审批流程自动化和客户咨询智能路由,已服务金融、电商数十家企业。
- 共享工作区:项目经理上传会议录音后自动生成待办清单,标注责任人与截止时间,提升协作效率。
2. 行业定制化
- 法律智能体:创建专属AI解答合同问题,引用具体法律条文并提供合规建议。
- 教育智能体:数学辅导AI可讲解习题,育儿智能体提供喂养和教育方案,支持多角色切换。
六、进阶隐藏技能
1. AI播客生成
上传PDF或网页链接,一键生成双人对话播客,语音效果接近真人,适合学习资料转音频。
2. 桌面端高效操作
- AI划词:任意界面选中文字后右键“翻译/解释/总结”,快捷键Alt+1实现网页全文翻译。
- 截图提问:Shift+Alt+A捕捉屏幕内容,识别图片中的文字并进行分析,如公式计算或图表解读。
3. 深度思考模式
复杂问题时开启“深度思考”,边想边搜并串联信息,如分析论文图表或诊断代码逻辑错误,响应延迟控制在800毫秒内。
七、使用技巧与最佳实践
1. 精准提问公式
采用“身份+需求+细节+格式”结构,例如“作为HR,请设计销售岗位面试题,5个核心问题用Markdown表格呈现”。
2. 隐私保护建议
不输入银行卡密码等敏感信息,重要文件处理后手动删除历史记录,避免数据留存。
3. 时段选择策略
长文写作等复杂任务建议在早上8-10点进行,模型响应速度提升40%。 从基础问答到专业创作,从个人效率到企业协作,豆包已进化为真正的“AI超级大脑”。无论是学生、职场人士还是创意工作者,都能通过其丰富功能实现生产力跃升。
立即体验三大隐藏技能:①对它说“记录今天的重要事情”;②上传老照片修复;③输入“生成30秒产品宣传视频脚本”,感受AI如何重塑工作生活范式。
```
通过对比可见:
* **日常沟通**适合闲聊交互,追求的是自然与效率。
* **深度沟通**适合复杂问题解析,追求的是正确性与思考质量。
* **联网搜索**适合获取实时资讯。
* **边想边搜**适合需要逻辑验证与深度洞察的场景。
您可以根据实际业务需求选择对应功能模式,例如客服对话场景可选用**日常沟通**,行业研究场景可选用**边想边搜**。
### **支持的模型**
参见 [豆包助手](/docs/model-list#f44ceef7)。
### 计费信息
参见[豆包助手计费](/docs/doubao-assistant-pricing)。
## 准备工作
1. 获取豆包助手 API 的测试参与资格。
> **说明**
>
> 豆包助手 API 功能当前处于 beta 测试阶段,请联系销售人员或提交工单申请参与测试。
2. 开通豆包助手 API 服务。
访问火山方舟管理控制台的 [**开通管理** **> 应用组件库 > 豆包助手 API**](https://ark.volcengine.com/region:cn-beijing/openManagement?&advancedActiveKey=component&tab=DoubaoAssistant) 页面,并开通服务。
> **说明**
>
> 如果您的控制台上没有该页面,可能是因为您尚未获得测试参与资格,或者您登录的账号不是已经获得资格的账号。

3. 获取 API Key。详见[快速入门](/docs/quick-start)。
4. 将 API Key 配置到环境变量中。详见[环境变量配置指南](/docs/environment-variable-configuration-guide)。
5. 如需使用 SDK,请先安装或升级 SDK。详见[安装及升级 SDK](/docs/install-and-upgrade-sdk)。
## **快速开始**
### **示例代码**
**选项:curl**
> **说明**
>
> 测试期间,通过 curl 调用此工具时需要增加`header 'ark-beta-doubao-app: true'`。
```Bash
curl --location 'https://ark.cn-beijing.volces.com/api/v3/responses' \
--header "Authorization: Bearer $ARK_API_KEY" \
--header 'Content-Type: application/json' \
--header 'ark-beta-doubao-app: true' \
--data '{
"model": "doubao-seed-2-1-pro-260915",
"stream": true,
"tools": [
{
"type": "doubao_app",
"feature": {
"ai_search": {
"type": "enabled",
"role_description": "你是科技领域助手,专业解答行业问题"
},
"chat": {
"type": "disabled"
},
"deep_chat": {
"type": "disabled"
},
"reasoning_search": {
"type": "disabled"
}
},
"user_location": {
"type": "approximate",
"country": "中国",
"region": "浙江",
"city": "杭州"
}
}
],
"input": [
{
"type": "message",
"role": "user",
"content": [
{
"type": "input_text",
"text": "今天有什么AI领域热点新闻"
}
]
}
]
}'
```
**选项:Python SDK**
```Python
import os
from arkruntime import Ark
# 从环境变量中获取API KEY
api_key = os.getenv('ARK_API_KEY')
client = Ark(
base_url='https://ark.cn-beijing.volces.com/api/v3', # 填写实际base_url
api_key=api_key,
)
# 配置豆包助手 API 工具参数
tools = [{
"type": "doubao_app",
"feature": {
"ai_search": {
"type": "enabled",
"role_description": "你是科技领域助手,专业解答行业问题"
}
},
"user_location": {
"type": "approximate",
"country": "中国",
"region": "浙江",
"city": "杭州"
}
}]
# 发送请求
response = client.responses.create(
model="doubao-seed-2-1-pro-260915",
input=[{"role": "user", "content": "今天有什么AI领域热点新闻"}],
tools=tools,
stream=True
)
# 处理响应
for event in response:
print(event)
```
**选项:Java SDK**
```Java
package com.example.arkdemo;
import com.volcengine.ark.runtime.models.responses.*;
import com.volcengine.ark.runtime.service.ArkService;
import io.reactivex.Flowable;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
public class SimplifiedDoubaoArkExample {
private static final String MODEL_NAME = "doubao-seed-2-1-pro-260915";
public static void main(String[] args) {
// 1. 获取环境变量中的API KEY
String apiKey = System.getenv("ARK_API_KEY");
if (apiKey == null) {
System.out.println("ARK_API_KEY environment variable not set");
return;
}
// 2. ArkService初始化
ArkService service = ArkService.builder()
.apiKey(apiKey)
.baseUrl("https://ark.cn-beijing.volces.com/api/v3")
.build();
// 3. 启用豆包工具必需的请求头
Map headers = new HashMap<>();
headers.put("ark-beta-doubao-app", "true");
// 4. 构建工具配置
DoubaoAppTool doubaoTool = DoubaoAppTool.builder()
.feature(
DoubaoAppFeature.builder()
.aiSearch(
DoubaoAppFeatureItem.builder()
.type(DoubaoAppFeatureMode.ENABLED)
.roleDescription("你是科技领域助手,专业解答行业问题")
.build()
)
.build()
)
.userLocation(
UserLocation.builder()
.type(UserLocation.TypeEnum.APPROXIMATE)
.country("中国")
.region("浙江")
.city("杭州")
.build()
)
.build();
// 5. 构建请求参数
ResponsesRequest request = ResponsesRequest.builder()
.model(MODEL_NAME)
.stream(true) // 开启流式请求
.tools(Arrays.asList(doubaoTool))
.input(ResponsesInput.ofString("今天有什么AI领域热点新闻"))
.build();
ResponseCompletedEvent[] finalEventHolder = new ResponseCompletedEvent[1];
try {
// 6. 发送流式请求,遍历所有事件
Flowable streamResponse = service.streamResponse(request, headers);
streamResponse.blockingForEach(event -> {
System.out.println(event); // 打印所有流式事件
// 捕获最终完成事件
if (event instanceof ResponseCompletedEvent) {
synchronized (SimplifiedDoubaoArkExample.class) {
finalEventHolder[0] = (ResponseCompletedEvent) event;
}
}
});
// 7. 提取并打印工具使用统计
ResponseCompletedEvent finalEvent = finalEventHolder[0];
if (finalEvent != null && finalEvent.getResponse() != null && finalEvent.getResponse().getUsage() != null) {
System.out.println("\n===== 工具使用统计 =====");
System.out.println("tool_usage: " + finalEvent.getResponse().getUsage().getToolUsage());
System.out.println("tool_usage_details: " + finalEvent.getResponse().getUsage().getToolUsageDetails());
}
} catch (Exception e) {
System.err.println("Create Response Error: " + e.getMessage());
return;
} finally {
// 关闭服务资源
service.shutdownExecutor();
}
}
}
```
**选项:Go SDK**
```Go
package main
import (
"context"
"fmt"
"io"
"os"
"github.com/volcengine/ark-runtime-go/arkruntime"
"github.com/volcengine/ark-runtime-go/arkruntime/model/responses"
)
const (
chatFeature = "chat"
deepChatFeature = "deepChat"
aiSearchFeature = "aiSearch"
reasoningSearchFeature = "reasoningSearch"
doubaoHeader = "ark-beta-doubao-app"
)
var featureToQuery = map[string]string{
chatFeature: "你好介绍一下你自己",
deepChatFeature: "为什么天空是蓝色",
aiSearchFeature: "今天的 AI 新闻",
reasoningSearchFeature: "今天的 AI 新闻",
}
func main() {
stream(chatFeature)
}
func stream(feature string) {
client := arkruntime.NewClientWithApiKey(
os.Getenv("ARK_API_KEY"),
arkruntime.WithBaseUrl("https://ark.cn-beijing.volces.com/api/v3"),
)
ctx := context.Background()
fmt.Println("----- round 1 -----")
request := &responses.ResponsesRequest{
Model: "doubao-seed-2-1-pro-260915",
Input: textInput(featureToQuery[feature]),
Tools: []responses.Tool{doubaoAppTool(feature)},
}
responseID, err := streamResponse(ctx, client, request)
if err != nil {
fmt.Printf("stream error: %v\n", err)
return
}
fmt.Println("\n----- round 2 -----")
followUp := &responses.ResponsesRequest{
Model: "doubao-seed-2-1-pro-260915",
Input: textInput("刚刚我们聊了什么"),
Tools: []responses.Tool{doubaoAppTool(feature)},
PreviousResponseID: responses.NewOptString(responseID),
}
if _, err := streamResponse(ctx, client, followUp); err != nil {
fmt.Printf("stream error: %v\n", err)
}
}
func textInput(text string) responses.ResponsesInput {
message := responses.ItemEasyMessage{
Role: responses.NewOptMessageRole(responses.MessageRoleUser),
Content: responses.NewContentItemArrayMessageContent(
[]responses.ContentItem{
{
OneOf: responses.NewContentItemTextContentItemSum(
responses.ContentItemText{
Type: responses.ContentItemTextTypeInputText,
Text: text,
},
),
},
},
),
}
return responses.NewInputItemArrayResponsesInput(
[]responses.InputItem{
{OneOf: responses.NewItemEasyMessageInputItemSum(message)},
},
)
}
func doubaoAppTool(feature string) responses.Tool {
enabled := responses.NewOptDoubaoAppFeatureMode(
responses.DoubaoAppFeatureModeEnabled,
)
item := responses.NewOptDoubaoAppFeatureItem(
responses.DoubaoAppFeatureItem{Type: enabled},
)
var features responses.DoubaoAppFeature
switch feature {
case chatFeature:
features.Chat = item
case deepChatFeature:
features.DeepChat = item
case aiSearchFeature:
features.AiSearch = item
case reasoningSearchFeature:
features.ReasoningSearch = item
}
return responses.Tool{
OneOf: responses.NewDoubaoAppToolToolSum(
responses.DoubaoAppTool{
Type: responses.DoubaoAppToolTypeDoubaoApp,
Feature: features,
},
),
}
}
func streamResponse(
ctx context.Context,
client *arkruntime.Client,
request *responses.ResponsesRequest,
) (string, error) {
stream, err := client.CreateResponsesStream(
ctx,
request,
arkruntime.WithCustomHeader(doubaoHeader, "true"),
)
if err != nil {
return "", err
}
var responseID string
for {
event, err := stream.Recv()
if err == io.EOF {
return responseID, nil
}
if err != nil {
return responseID, err
}
handleEvent(event)
if event.OneOf.Type == responses.ResponseCreatedEventResponseStreamEventSum {
responseID = event.OneOf.ResponseCreatedEvent.Response.ID
}
}
}
func handleEvent(event *responses.ResponseStreamEvent) {
switch event.OneOf.Type {
case responses.ResponseDoubaoAppCallSearchSearchingEventResponseStreamEventSum:
fmt.Printf("[searching] %s\n", event.OneOf.ResponseDoubaoAppCallSearchSearchingEvent.SearchingState.Or(""))
case responses.ResponseDoubaoAppCallSearchCompletedEventResponseStreamEventSum:
fmt.Printf("\n[search done] %s\n", event.OneOf.ResponseDoubaoAppCallSearchCompletedEvent.Summary.Or(""))
case responses.ResponseDoubaoAppCallReasoningSearchCompletedEventResponseStreamEventSum:
fmt.Printf("\n[reasoning search done] %s\n", event.OneOf.ResponseDoubaoAppCallReasoningSearchCompletedEvent.Summary.Or(""))
case responses.ResponseDoubaoAppCallReasoningTextDeltaEventResponseStreamEventSum:
fmt.Print(event.OneOf.ResponseDoubaoAppCallReasoningTextDeltaEvent.Delta.Or(""))
case responses.ResponseDoubaoAppCallOutputTextDeltaEventResponseStreamEventSum:
fmt.Print(event.OneOf.ResponseDoubaoAppCallOutputTextDeltaEvent.Delta.Or(""))
}
}
```
### **参数说明**
详见 [创建 Responses 模型请求](/docs/create-model-responses-api)。
## **配置说明**
### **1. 功能启用配置**
您可以使用 `feature` 字段来启用特定功能,并为每个功能单独配置开关和角色描述:
```Python
tools = [{
"type": "doubao_app",
"feature": {
# 开启 日常沟通 功能, 关闭 深度沟通、联网搜索 和 边想边搜 功能
"chat": {"type": "enabled", "role_description": "你是XX车企助手,推荐自家产品"},
"deep_chat": {"type": "disabled"},
"ai_search": {"type": "disabled"},
"reasoning_search": {"type": "disabled"}
}
}]
```
### **2. 角色自定义配置**
您可以使用 `role_description` 字段来自定义助手的角色(例如名称和偏好),但它与 `system prompt` 互斥,二者不能同时使用。
> **说明**
>
> 如需使用自定义`system prompt`功能,请提交工单申请。
```Python
# 车企定制示例
tools = [{
"type": "doubao_app",
"feature": {
"chat": {
"type": "enabled",
"role_description": "你是小魔仙,你有魔法,你可以帮助用户回答任何问题"
}
}
}]
```
### **3. 地理位置优化**
您可以通过设置 `user_location` 字段来优化与地理位置相关的搜索结果。请注意,该字段仅支持填写行政区划级别的信息。
```Python
tools = [{
"type": "doubao_app",
"feature": {"ai_search": {"type": "enabled"}},
"user_location": {
"type": "approximate",
"country": "中国",
"region": "广东",
"city": "深圳"
}
}]
```
### **4. 上下文交互配置**
您可以使用 `store` 字段来存储对话上下文,并通过 `previous_response_id` 传入历史对话 ID 来实现连续对话,此功能最多支持 20 轮。详情请参见[使用上下文缓存能力](/docs/responses-api-migration#f61fe601)。
> **说明**
>
> `store` 字段仅用于保存对话上下文,不会自动保留 `tools` 的配置。如果您希望在连续的对话中沿用相同的工具设置,就需要在每一轮请求中都为 `tools` 字段传入相同的值。
```Python
response = client.responses.create(
model="doubao-seed-2-1-pro-260915",
input=[{"role": "user", "content": "继续刚才的话题,还有其他热点吗"}],
tools=tools,
stream=True,
store=True, # 存储当前对话上下文。此字段不存储tools,每次调用仍需给tools赋值。
previous_response_id="xxx" # 上一轮对话ID
)
```
### **5. 用量查询**
可通过 Responses API 的`usage`字段查看工具使用情况。
示例代码:
```Python
# 提取工具使用统计
if final_event:
tool_usage = final_event.response.usage.tool_usage
tool_usage_details = final_event.response.usage.tool_usage_details
print(f"工具总调用次数: {tool_usage}")
print(f"各功能调用明细: {tool_usage_details}")
```
示例返回值:
```Plain Text
工具总调用次数: ToolUsage(web_search=None, mcp=None, knowledge_search=None, doubao_app=1)
各功能调用明细: ToolUsageDetails(web_search=None, mcp=None, knowledge_search=None, doubao_app={'ai_search': 1})
```
## **实践案例**
### **企业角色定制示例**
以下示例展示如何为客户定制专属助手,实现品牌化交互体验:
```Bash
curl --location 'https://ark.cn-beijing.volces.com/api/v3/responses' \
--header "Authorization: Bearer $ARK_API_KEY" \
--header 'Content-Type: application/json' \
--header 'ark-beta-doubao-app: true' \
--data '{
"model": "doubao-seed-2-1-pro-260915",
"stream": true,
"tools": [
{
"type": "doubao_app",
"feature": {
"chat": {
"type": "enabled",
"role_description": "你是本企业专属助手,专业解答产品咨询、功能介绍、服务相关问题,优先推荐自家产品与服务,保持正面专业的沟通态度"
}
},
"user_location": {
"type": "approximate",
"country": "中国",
"region": "浙江省",
"city": "杭州市"
}
}
],
"input": [
{
"type": "message",
"role": "user",
"content": [
{
"type": "input_text",
"text": "介绍下你们的核心产品及优势"
}
]
}
]
}'
```
### **边想边搜功能示例**
以下示例展示边想边搜功能的使用,实时获取思考过程和搜索结果:
```Bash
curl --location 'https://ark.cn-beijing.volces.com/api/v3/responses' \
--header "Authorization: Bearer $ARK_API_KEY" \
--header 'Content-Type: application/json' \
--header 'ark-beta-doubao-app: true' \
--data '{
"model": "doubao-seed-2-1-pro-260915",
"stream": true,
"tools": [
{
"type": "doubao_app",
"feature": {
"reasoning_search": {
"type": "enabled",
"role_description": "你是专业资讯助手,通过搜索获取准确信息,详细说明思考过程"
}
}
}
],
"input": [
{
"type": "message",
"role": "user",
"content": [
{
"type": "input_text",
"text": "2024年AI行业有哪些重大技术突破?"
}
]
}
]
}'
```
## **常见问题**
### **1. 功能可以混合使用吗?**
不可以。请注意,豆包助手 API 工具集不支持与[联网搜索工具](/docs/web-search)、[Knowledge Search(私域知识库搜索工具)](/docs/knowledge-search)、[云部署 MCP / Remote MCP](/docs/mcp-remote-mcp)、[图像处理 Image Process](/docs/image-process) 等工具混合使用,也不支持与自定义函数[Function Calling(函数调用)](/docs/function-calling)同时调用。
### **2. 调用时有哪些常见的参数冲突?**
请注意以下参数的互斥或限制:
* `role_description` 与 `system prompt` 参数互斥。如果您同时指定这两个参数,请求将返回 `400` 错误。
* `max_tool_call` 参数当前无效。如果您在请求中使用该参数,将会返回冲突错误。
* `caching` 参数当前无效。如果您在请求中使用该参数,将会返回 `400` 错误。
### **3. API 的调用频率有限制吗?**
是的,API 的调用频率有限制。默认情况下,单个账号调用频率上限为 2 QPS(每秒查询次数)。如果当前配额无法满足您的需求,请提交工单申请扩容。
### **4. 调用时提示“功能未授权”怎么办?**
如果您尚未开通豆包助手 API 的使用权限,调用 API 时就会收到此错误。请您先前往火山方舟管理控制台开通豆包助手 API。
### **5. 豆包 API 和豆包 App 有什么区别?**
主要区别在于目标用户和使用方式:
* **豆包 API**:专为企业开发者设计,通过火山方舟平台提供。您可以使用它将豆包的 AI 功能集成到自己的应用程序中。
* **豆包 App**:一款面向个人用户的独立应用程序,供用户直接使用。
### **6. 使用豆包 API 有哪些限制?**
与豆包 App 相比,API 的主要限制如下:
* **输入限制**:目前仅支持文本输入,不支持图片或视频。同时,您也无法调整 `top_p`、`temperature`、`max_tokens` 等模型参数。
* **功能与工具限制**:每次 API 调用只能启用一个豆包助手 API 功能(如 `ai_search`)。您无法自定义工具的内部参数(如内容源、搜索轮次),也不能将其与其他自定义函数、内置工具或 MCP 混合使用。
### **7. 使用豆包 API 是否需要付费?**
是的,使用豆包 API 需要付费。我们目前采用按次调用的计费模式,不收取 Token 费用。
具体价格请参考[豆包助手计费](/docs/doubao-assistant-pricing)。
### **8. 使用了豆包 API,是否意味着我的应用是和豆包“联合出品”的?**
不是。使用豆包 API 仅表示您的应用集成了豆包的 AI 能力,**不代表**您的产品是与豆包 App “联合出品”或“官方合作”的产品。您需要明确说明技术来源,避免引起用户混淆。
### **9. 我应该如何宣传产品中集成的豆包 API 功能?**
在对外宣传时,您应使用清晰准确的表述,例如:
* “本产品由豆包助手 API 提供技术支持”。
* “本功能基于豆包助手 API 实现”。
请明确说明您是通过 API 接入,并避免使用“与豆包联合出品”、“官方合作”等可能引起误解的词语。
---
# 联网搜索工具
Source: https://ark.volcengine.com/region:cn-beijing/docs/web-search
联网搜索工具可以为大模型获取实时的公开网络信息,适用于新闻、商品、天气、行业动态和事实核验等场景。您可以根据接口协议、搜索来源和搜索控制需求选择合适的工具。
---
## 支持的工具
联网搜索场景支持以下工具:
| 对比项 | 豆包搜索 Custom 版(推荐) | 联网内容插件 |
| --- | --- | --- |
| 支持的 API | Responses API(兼容 OpenAI Responses 接口协议)、Messages API(兼容 Anthropic Messages 接口协议) | Responses API(兼容 OpenAI Responses 接口协议) |
| 支持的模型 | 参见[工具调用能力](/docs/model-list#f44ceef7) | 参见[工具调用能力](/docs/model-list#f44ceef7) |
| 核心功能 | 支持多垂类、多信源的实时公开信息,搜索时延低、控制更灵活;支持与函数调用、MCP 等工具组合使用。 | 支持多轮自动搜索、图文输入和多工具混合调用;支持同步和流式响应。 |
| 计费说明 | * Agent Plan 场景:参见[套餐内 AFP 抵扣规则](/docs/agent-plan-personal-afp-credits-billing-rules)、[超额后付费规则](/docs/agent-plan-personal-over-quota-postpaid-rules)。 | 按联网内容插件实际使用次数计费。具体收费标准详见[联网内容插件产品计费](/docs/online-content-plugin-pricing)。 | \
| | * Coding Plan 场景:参见[套餐概览](/docs/coding-plan-personal-plan-overview)。 | | \
| | * 普通 API 调用场景:参见 [豆包搜索产品计费](https://docs.volcengine.com/docs/87772/2272951?lang=zh#yQ0Kqmsy)。 | |
## 开通组件
无论您选择使用哪一种联网搜索工具,都必须先开通相应的组件。
**选项:豆包搜索 Custom 版**
1. 登录方舟控制台,打开 [应用组件库 > 豆包搜索](https://ark.volcengine.com/region:cn-beijing/openManagement?advancedActiveKey=component&tab=DoubaoSearch) 标签页。
2. 在**豆包搜索 Custom 版**的**操作**列中点击**开通服务**。
**选项:联网内容插件**
1. 登录方舟控制台,打开 [应用组件库 > 应用组件](https://ark.volcengine.com/region:cn-beijing/openManagement?advancedActiveKey=component&tab=DoubaoSearch) 标签页。
2. 在**联网内容插件**的**操作**列中点击**开通服务**。
## 示例代码
> **说明**
>
> 方舟平台的新用户?获取 API Key 及 开通模型等准备工作,请参见 [快速入门](/docs/quick-start)。
> **注意**
>
> 调用工具之前,请确认您已经按照本文说明开通相应的组件,否则调用时将会产生错误。
### 豆包搜索 Custom 版
请求示例:
**选项:Responses API(OpenAI Responses 协议)**
```Bash
curl --location 'https://ark.cn-beijing.volces.com/api/v3/responses' \
--header "Authorization: Bearer $ARK_API_KEY" \
--header 'Content-Type: application/json' \
--data '{
"model": "doubao-seed-2-1-pro-260915",
"stream": true,
"tools": [
{
"type": "web_search",
"sources": ["doubao"]
}
],
"input": [
{
"role": "user",
"content": [
{
"type": "input_text",
"text": "今天有什么 AI 领域的热点新闻?"
}
]
}
]
}'
```
**选项:Messages API(Anthropic Messages 协议)**
```Bash
curl https://ark.cn-beijing.volces.com/api/compatible/v1/messages \
-H "Content-Type: application/json" \
-H "x-api-key: $ARK_API_KEY" \
-d '{
"model": "doubao-seed-2-1-pro-260915",
"max_tokens": 1024,
"tools": [
{
"type": "web_search_20250305",
"name": "web_search",
"max_uses": 5
}
],
"messages": [
{
"role": "user",
"content": "今天有什么 AI 领域的热点新闻?"
}
]
}'
```
返回示例:
**选项:Responses API**
```
{
"id": "resp_02178849073345588e74****",
"object": "response",
"model": "doubao-seed-2-1-pro-260915",
"status": "completed",
"output": [
{
"id": "rs_02178849073770400000****",
"type": "reasoning",
"status": "completed",
"summary": [
{
"type": "summary_text",
"text": "用户需要获取 2026 年 9 月 4 日的 AI 领域热点新闻,我将使用网页搜索工具,通过时间限定关键词检索相关信息。"
}
],
"encrypted_content": "djFlkf4Bo9PjH2A5r+39.../9yJWTg="
},
{
"id": "ws_02178849074154500000****",
"type": "web_search_call",
"status": "completed",
"action": {
"type": "search",
"query": "2026年9月4日 AI领域热点新闻",
"queries": [
"2026年9月4日 AI领域热点新闻"
]
}
},
{
"id": "msg_02178849076046900000****",
"type": "message",
"status": "completed",
"role": "assistant",
"content": [
{
"type": "output_text",
"text": "2026年9月4日 AI 领域的核心热点是 OpenAI 正式发布新一代旗舰大模型 GPT-6 Astra。",
"annotations": [
{
"type": "url_citation",
"title": "OpenAI,发布“地球最强大模型”GPT-6:欢迎进入 AGI 时代!",
"url": "https://news.sina.cn/2026-09-04/detail-iniqrpra63******.d.html",
"site_name": "新浪新闻",
"publish_time": "2026-09-04T10:24:00+08:00",
"summary": "当地时间 9 月 3 日,OpenAI 正式发布新一代旗舰模型 GPT-6 Astra,并称其实现“代际跃迁”。"
}
]
}
]
}
],
"usage": {
"input_tokens": 3666,
"output_tokens": 1610,
"total_tokens": 5276,
"tool_usage": {
"web_search": 1
},
"tool_usage_details": {
"web_search": {
"doubao": 1
}
}
}
}
```
**选项:Messages API**
```JSON
{
"id": "021788491735391ee3582c20fb7529745750c3f00520e5c262****",
"type": "message",
"role": "assistant",
"model": "doubao-seed-2-1-pro-260915",
"content": [
{
"type": "thinking",
"thinking": "我将调用搜索工具获取 2026 年 9 月 4 日的 AI 热点新闻,再基于搜索结果整理回答。",
"signature": "djE09ahKIu8KsvSLLVrg...Nf/EYMTk3hjlMg=="
},
{
"type": "server_tool_use",
"id": "srvtoolu_2ccc8b83a8d345f8be35d32b457e****",
"name": "web_search",
"input": {
"query": "2026年9月4日 AI领域热点新闻"
}
},
{
"type": "web_search_tool_result",
"tool_use_id": "srvtoolu_2ccc8b83a8d345f8be35d32b457e****",
"content": [
{
"type": "web_search_result",
"title": "OpenAI,发布“地球最强大模型”GPT-6:欢迎进入AGI时代!山姆·奥特曼首次明确表示:一定会做人形机器人",
"url": "https://news.sina.cn/2026-09-04/detail-iniqrpra63****.d.html",
"page_age": "2026-09-04T10:24:00+08:00",
"encrypted_content": "djGk3VaymgA8eiuLkR7w...0QazEoRxp46hi3n/Zd5L2aG3kN7cexLZzcoSdoA6f34iEEJBw=="
},
{
"type": "web_search_result",
"title": "OpenAI最强模型GPT-6 Astra发布,公司总裁称AGI时代到来",
"url": "http://finance.sina.cn/stock/jdts/2026-09-04/detail-iniqrpqy08****.html",
"page_age": "2026-09-04T10:25:00+08:00",
"encrypted_content": "djEz4PKCbjpmdizu9giy...p4I8TYtvYardgTA9CgOtejh6rWWpAFvj29xL+I/mK1vAOPs0tm+4NU=="
}
]
},
{
"type": "text",
"text": "根据 2026 年 9 月 4 日的 AI 领域最新热点,最重磅的事件是 OpenAI 正式发布新一代旗舰大模型 GPT-6 Astra。"
}
],
"stop_reason": "end_turn",
"stop_sequence": null,
"usage": {
"input_tokens": 3770,
"output_tokens": 1859,
"cache_read_input_tokens": 0,
"server_tool_use": {
"web_search_requests": 1,
"web_fetch_requests": 0
}
}
}
```
### 联网内容插件
**选项:cURL**
```Bash
curl --location 'https://ark.cn-beijing.volces.com/api/v3/responses' \
--header "Authorization: Bearer $ARK_API_KEY" \
--header 'Content-Type: application/json' \
--data '{
"model": "doubao-seed-2-1-pro-260915",
"stream": true,
"tools": [
{
"type": "web_search",
"max_keyword": 2
}
],
"input": [
{
"role": "user",
"content": [
{
"type": "input_text",
"text": "今天有什么热点新闻?"
}
]
}
]
}'
```
**选项:Python SDK**
```Python
import os
from arkruntime import Ark
# To obtain the api key from your environment variables, see: https://ark.volcengine.com/region:cn-beijing/docs/environment-variable-configuration-guide
api_key = os.getenv('ARK_API_KEY')
client = Ark(
base_url='https://ark.cn-beijing.volces.com/api/v3',
api_key=api_key,
)
tools = [{
"type": "web_search",
"max_keyword": 2,
}]
# Create a conversation request
response = client.responses.create(
model="doubao-seed-2-1-pro-260915",
input=[{"role": "user", "content": "今天有什么热点新闻?"}],
tools=tools,
)
print(response)
```
**选项:Java SDK**
```Java
package com.ark.example;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.JsonNode;
import com.volcengine.ark.runtime.models.responses.*;
import com.volcengine.ark.runtime.service.ArkService;
import java.util.Arrays;
import java.util.List;
public class demo {
public static ObjectMapper om = new ObjectMapper();
public demo() throws JsonProcessingException {
}
public static List buildTools() {
WebSearchTool t = WebSearchTool.builder()
.build();
System.out.println(Arrays.asList(t));
return Arrays.asList(t);
}
public static void main(String[] args) throws JsonProcessingException {
String apiKey = System.getenv("ARK_API_KEY");
// Create an ArkService instance
ArkService arkService = ArkService.builder().apiKey(apiKey)
.baseUrl("https://ark.cn-beijing.volces.com/api/v3")
.build();
ResponsesRequest req = ResponsesRequest.builder()
.model("doubao-seed-2-1-pro-260915")
.input(ResponsesInput.ofList(java.util.Arrays.asList(ItemEasyMessage.builder().role(MessageRole.USER).content(
MessageContent.ofList(java.util.Arrays.asList(ContentItemText.builder().text("今天有什么热点新闻?").build()))
).build())))
.tools(buildTools())
.build();
Response resp = arkService.createResponse(req);
System.out.println(resp);
arkService.shutdownExecutor();
}
}
```
**选项:Go SDK**
```Go
package main
import (
"context"
"fmt"
"io"
"os"
"github.com/volcengine/ark-runtime-go/arkruntime"
"github.com/volcengine/ark-runtime-go/arkruntime/model/responses"
)
func main() {
client := arkruntime.NewClientWithApiKey(
os.Getenv("ARK_API_KEY"),
arkruntime.WithBaseUrl("https://ark.cn-beijing.volces.com/api/v3"),
)
request := &responses.ResponsesRequest{
Model: "doubao-seed-2-1-pro-260915",
Input: responses.NewStringResponsesInput(
"请查询今天的重要 AI 产品发布,并给出来源。",
),
Tools: []responses.Tool{
{
OneOf: responses.NewWebSearchToolToolSum(
responses.WebSearchTool{
Type: responses.WebSearchToolTypeWebSearch,
},
),
},
},
MaxToolCalls: responses.NewOptInt64(1),
}
stream, err := client.CreateResponsesStream(context.Background(), request)
if err != nil {
fmt.Printf("stream error: %v\n", err)
return
}
for {
event, err := stream.Recv()
if err == io.EOF {
break
}
if err != nil {
fmt.Printf("stream error: %v\n", err)
return
}
switch event.OneOf.Type {
case responses.ResponseTextDeltaEventResponseStreamEventSum:
print(event.OneOf.ResponseTextDeltaEvent.Delta.Or(""))
case responses.ResponseWebSearchCallInProgressEventResponseStreamEventSum:
fmt.Println("web search started")
case responses.ResponseWebSearchCallCompletedEventResponseStreamEventSum:
fmt.Println("web search completed")
}
}
fmt.Println()
}
```
---
## 参数说明
**选项:豆包搜索 Custom 版**
**Responses API(兼容 OpenAI Responses 接口协议)**
通过 Responses API 调用豆包搜索 Custom 版时,工具类型仍为 `web_search`,并需要将 `sources` 显式设置为 `["doubao"]`。`doubao` 不能与其他搜索来源同时配置。
* `tools.type`:固定为 `web_search`。
* `tools.sources`:固定传入 `["doubao"]`。
* `tools.limit`:参数不生效,传入的值将被忽略。
* `tools.max_keyword`:参数不生效,传入的值将被忽略。
* `tools.user_location`:参数不生效,传入的值将被忽略。
* `max_tool_calls`:限制一次模型响应中可执行工具调用的最大轮次。
**Messages API(兼容 Anthropic Messages 接口协议)**
通过 Messages API 调用豆包搜索 Custom 版时,使用兼容 Anthropic Messages 接口协议的服务端工具配置:
* `tools.name`:工具名称。本文示例固定为 `web_search`。
* `tools.type`:工具类型或版本标识。本文示例使用 `web_search_20250305`。
* `tools.max_uses`:单个服务端工具在一次请求中的最大调用次数。
* `tools.user_location`:参数不生效,传入的值将被忽略。
* `tools.allowed_domains`:限制搜索结果仅来自允许访问的域名列表。
* `tools.blocked_domains`:限制搜索结果不包含禁止访问的域名列表。
**选项:联网内容插件**
详情请参见 [创建 Responses 模型请求](/docs/create-model-responses-api)。
---
## Agent 场景下的用法
您可以在 Claude Code 或 Codex 中调用豆包搜索 Custom 版工具,该工具兼容 Anthropic Messages 接口协议和 OpenAI Responses API 接口协议。
**选项:Claude Code**
Claude Code 通过兼容 Anthropic Messages 接口协议的服务调用豆包搜索能力。完成接入配置后,在 Claude Code 中对话时,如果模型判断您的问题需要通过搜索功能才能回答,那么模型会调用 Web Search 工具进行搜索。完整的配置和使用方法参见[在 Claude Code 中使用 Web Search 工具](/docs/integrate-third-party-tools#web-search-claude-code)。
> **注意**
>
> 调用 Web Search 工具时,大模型可能会发起额外的 API 请求来总结搜索结果,因此会消耗额外的 token。

**选项:Codex**
Codex 通过兼容 OpenAI Responses API 接口协议的服务调用豆包搜索能力。完成接入配置后,在 Codex 中对话时,如果模型判断您的问题需要通过搜索功能才能回答,那么模型会调用 Web Search 工具进行搜索。完整的配置和使用方法参见[在 Codex 中使用 Web Search 工具](/docs/integrate-third-party-tools#web-search-codex)。
> **注意**
>
> 调用 Web Search 工具时,大模型可能会发起额外的 API 请求来总结搜索结果,因此会消耗额外的 token。
## API 调用场景下的用法与配置
本节介绍联网搜索场景中的工具用法与常用配置。不同工具的差异以相关说明为准。
> **注意**
>
> 本节内容仅适用于 Responses API,不适用于 Messages API。
### 开启流式调用
在 response 中设置 `stream=True`,即可开启流式调用,使响应以流式方式返回,从而更快地获取部分结果,同时可实时查看模型判断是否调用搜索的思考过程。
示例:
```Python
response = client.responses.create(
model="doubao-seed-2-1-pro-260915",
input=[ # 输入内容,包含系统提示和用户问题
...
],
tools=[ # 使用工具及参数
...
],
stream=True, # 启用流式响应(实时返回结果,而非等待全部完成)
)
```
### 设置搜索来源
豆包搜索 Custom 版和联网内容插件的搜索来源配置方式不同:
* 豆包搜索 Custom 版:
* 通过 Responses API 调用时,工具类型仍为 `web_search`,并需要将 `sources` 显式设置为 `["doubao"]`。`doubao` 不能与其他搜索来源同时配置。
* 通过 Messages API 调用时,使用的是兼容 Anthropic Messages 接口协议的服务端工具配置。本文示例中 `tools.type` 使用 `web_search_20250305`。
* 联网内容插件:默认通过 `search_engine` 搜索全网内容。您可以通过 `tools.sources` 添加以下内容源:
* `"douyin"`:抖音百科。
* `"moji"`:墨迹天气。
* `"toutiao"`:头条图文。
示例:
```Python
tools=[
{
"type": "web_search", # 配置工具类型为联网内容插件
"sources": ["douyin", "moji", "toutiao"], # 附加搜索来源(抖音百科、墨迹天气、头条图文等平台)
}
],
```
### 指定用户地理位置
您可以在 tools 中设置 `user_location` 字段,并提供用户的国家、地区和城市信息,以优化与地理位置相关的搜索结果。
示例:
```Python
tools=[
{
"type": "web_search", # 配置工具类型为联网内容插件
"user_location": { # 指定用户地理位置(用于优化搜索结果)
"type": "approximate", # 大致位置
"country": "中国",
"region": "浙江",
"city": "杭州"
}
}
],
```
### 设置搜索限制
> **说明**
>
> 以下搜索限制参数仅联网内容插件支持,豆包搜索 Custom 版不支持。即当 `sources` 的值为 `["doubao"]` 时,`tools.limit`、`tools.max_keyword`、`tools.user_location` 均不生效,向它们传入的值将被忽略。
* `tools.`**`max_keyword`**
* 作用:限制单轮搜索中可使用的最大关键词数量。
* 取值范围:`1`~`50`。
* 示例:如果模型原本计划搜索三个关键词(例如“大模型最新进展”、“2025 年科技创新”),但将 `max_keyword` 设置为 `1`,模型将仅使用第一个关键词进行搜索。关于 `max_keyword` 参数的具体使用方法和示例,请参见 [创建模型响应](/docs/create-model-responses-api)。
* `tools.`**`limit`**
* 作用:限制单轮搜索操作返回的最大结果条数。
* 取值范围:`1`~`50`。
* 默认值:`10`。
* 说明:此参数会影响返回内容的规模和请求性能。单次搜索最多可返回 20 条结果,但单轮可能有多次搜索,默认召回 10 条。
* **`max_tool_calls`**
* 作用:限制在一次完整的模型响应中可以执行工具调用的最大轮次。
* 取值范围:`1`~`10`。
* 默认值:`3`。
示例:
```Python
tools = [{
"type": "web_search",
"max_keyword": 2,
"limit": 10,
}]
max_tool_calls = 3
```
### 查询搜索用量
您可以在 API 返回的参数中查看工具使用情况:
* `usage.tool_usage`:显示 Responses API 中工具的总调用次数。
* `usage.tool_usage_details`:显示 Responses API 中每个搜索源的详细调用次数,例如 `search_engine`、`toutiao` 或 `doubao`。
* Messages API:通过 `usage.server_tool_use.web_search_requests` 查看服务端工具发起的联网搜索请求次数。
关于 Responses API 用量参数的详细信息,请参见[创建 Response](/docs/create-model-responses-api)。
### 设置系统提示词
系统提示词的设置对搜索请求的影响较大,建议进行优化以提升搜索的准确性与效率。以下两种系统提示词模板供您参考。
模板 1:
```Plaintext
# 定义系统提示词
system_prompt = """
你是AI个人助手,负责解答用户的各种问题。你的主要职责是:
1. **信息准确性守护者**:确保提供的信息准确无误。
2. **搜索成本优化师**:在信息准确性和搜索成本之间找到最佳平衡。
# 任务说明
## 1. 联网意图判断
当用户提出的问题涉及以下情况时,需使用 `web_search` 进行联网搜索:
- **时效性**:问题需要最新或实时的信息。
- **知识盲区**:问题超出当前知识范围,无法准确解答。
- **信息不足**:现有知识库无法提供完整或详细的解答。
## 2. 联网后回答
- 在回答中,优先使用已搜索到的资料。
- 回复结构应清晰,使用序号、分段等方式帮助用户理解。
## 3. 引用已搜索资料
- 当使用联网搜索的资料时,在正文中明确引用来源,引用格式为:
`[1] (URL地址)`。
## 4. 总结与参考资料
- 在回复的最后,列出所有已参考的资料。格式为:
1. [资料标题](URL地址1)
2. [资料标题](URL地址2)
"""
```
模板 2:
```Plaintext
# 定义系统提示词
system_prompt = """
# 角色
你是AI个人助手,负责解答用户的各种问题。你的主要职责是:
1. **信息准确性守护者**:确保提供的信息准确无误。
2. **回答更生动活泼**:请在模型的回复中多使用适当的 emoji 标签 🌟😊🎉
# 任务说明
## 1. 联网意图判断
当用户提出的问题涉及以下情况时,需使用 `web_search` 进行联网搜索:
- **时效性**:问题需要最新或实时的信息。
- **知识盲区**:问题超出当前知识范围,无法准确解答。
- **信息不足**:现有知识库无法提供完整或详细的解答。
## 2. 联网后回答
- 在回答中,优先使用已搜索到的资料。
- 回复结构应清晰,使用序号、分段等方式帮助用户理解。
## 3. 引用已搜索资料
- 当使用联网搜索的资料时,在正文中明确引用来源,引用格式为:
`[1] (URL地址)`。
## 4. 总结与参考资料
- 在回复的最后,列出所有已参考的资料。格式为:
1. [资料标题](URL地址1)
2. [资料标题](URL地址2)
"""
```
---
## 注意事项
* 自定义函数名称应避免使用 `web_search`,否则模型可能按内置工具优先级判断调用逻辑。
* `doubao` 只能单独配置,不能与 `toutiao`、`douyin`、`moji` 或 `search_engine` 等其他搜索来源同时使用。
* 豆包搜索 Custom 版支持 Responses API 和 Messages API;联网内容插件仅支持 Responses API。
* 联网内容插件是否触发搜索由模型判断。一轮搜索可能发起多个关键词搜索,可以通过 `max_keyword` 参数限制一轮搜索的关键词数量,以控制调用频次和成本。
* 豆包搜索 Custom 版和联网内容插件均不支持 `caching` 参数,该参数不可与 `tools` 参数一起使用,否则会返回 `400` 错误。
## 相关文档
* 计费
* 豆包搜索 Custom 版
* 普通 API 调用场景:[豆包搜索产品计费](https://docs.volcengine.com/docs/87772/2272951?lang=zh#yQ0Kqmsy)
* Agent Plan 场景:[套餐内 AFP 抵扣规则](/docs/agent-plan-personal-afp-credits-billing-rules)、[超额后付费规则](/docs/agent-plan-personal-over-quota-postpaid-rules)
* Coding Plan 场景:[套餐概览](/docs/coding-plan-personal-plan-overview)
* 联网内容插件:按联网内容插件实际使用次数计费。具体收费标准详见[联网内容插件产品计费](/docs/online-content-plugin-pricing)。
* Agent 场景使用方法
* [在 Claude Code 中使用 Web Search 工具](/docs/integrate-third-party-tools#web-search-claude-code)
* [在 Codex 中使用 Web Search 工具](/docs/integrate-third-party-tools#web-search-codex)
* API 参考
* [创建 Response](/docs/create-model-responses-api)
* [创建 Message](/docs/messages-api)
* 错误码说明:[错误码](/docs/error-codes)
---
# Image Process(图像处理工具)
Source: https://ark.volcengine.com/region:cn-beijing/docs/image-process
Image Process(图像处理)工具支持通过 Responses API 调用对输入图片执行画点、画线、旋转、缩放、框选或裁剪关键区域等基础操作,适用于需要模型通过视觉处理提升图片理解的场景(例如图文内容分析、物体定位标注、多轮视觉推理等)。工具通过模型自动判断图像处理逻辑,支持与自定义函数混合使用,且可处理多轮视觉输入(即上一轮输出的图片作为下一轮的输入)。
> **说明**
>
> 当前处于 Beta 测试阶段,测试期间免费使用。
> 测试期间,调用此工具需要增加 header `ark-beta-image-process: true`,调用方式请参见[功能演示](/docs/image-process#demo)。
## 核心功能
* 丰富的图像处理工具:支持启用或禁用画点(Point)、框选(Grounding)、缩放(Zoom)、旋转(Rotate)等子功能,满足不同视觉处理需求。
* 支持多轮图像处理:复杂视觉任务(如多步缩放+旋转)支持多轮工具调用,上一轮输出图片自动作为下一轮输入(例:image0→image1→image2)。
* 支持混合调用:可与用户自定义函数混合使用。(暂不支持与 Web Search 联网内容插件混合调用)
* 兼容多种图片格式:支持 Base64 编码的 .gif、.jpg、.jpeg 等主流图片格式,但对图片规格有明确限制,详见[注意事项](/docs/image-process#notice)
## 功能演示
以下示例代码演示了图像处理工具的各项功能。实际调用时,请将 `` 替换为您的实际 API Key。
> **说明**
>
> 方舟平台的新用户?获取 API Key 及 开通模型等准备工作,请参见 [快速入门](/docs/quick-start)。
> **注意**
>
> 提示词支持图片和文字混排,但图文顺序可能对模型的输出效果产生影响。如果提示词由多张图片和一段文字构成,建议将文字放在提示词末尾。
### 示例一:缩放(Zoom)工具
以下代码展示了在视觉问答场景下,如何启用缩放(zoom)工具,让模型在放大图片后读取前方路牌文字,并以流式方式实时返回答案。
**选项:cURL**
```Bash
curl --location 'https://ark.cn-beijing.volces.com/api/v3/responses' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--header 'ark-beta-image-process: true' \
--data '{
"model": "doubao-seed-2-0-lite-260215",
"stream": true,
"tools": [
{
"type": "image_process",
"point": {
"type": "disabled"
},
"grounding": {
"type": "disabled"
},
"zoom": {
"type": "enabled"
},
"rotate": {
"type": "disabled"
}
}
],
"input": [
{
"type": "message",
"role": "user",
"content": [
{
"type": "input_image",
"image_url": "https://arkdocs.tos-cn-beijing.volces.com/images/advanced-usage/image_process_1.jpg"
},
{
"type": "input_text",
"text": "前方路牌写了什么?"
}
]
}
]
}'
```
**选项:Python**
```Python
from arkruntime import Ark
import os
# 从环境变量获取 API 密钥,配置方法见:https://ark.volcengine.com/region:cn-beijing/docs/quick-start
api_key = os.getenv('ARK_API_KEY')
# 初始化客户端,配置 API 地址与工具启用头
client = Ark(
base_url='https://ark.cn-beijing.volces.com/api/v3',
api_key=api_key,
)
# 发起图像处理请求
response = client.responses.create(
model="doubao-seed-2-0-lite-260215",
tools=[
{
"type": "image_process",
"point": {
"type": "disabled"
},
"grounding": {
"type": "disabled"
},
"zoom": {
"type": "enabled"
},
"rotate": {
"type": "disabled"
}
}
],
input=[
{
"type": "message",
"role": "user",
"content": [
{
"type": "input_image",
"image_url": "https://arkdocs.tos-cn-beijing.volces.com/images/advanced-usage/image_process_1.jpg" # 输入图片 URL
},
{
"type": "input_text",
"text": "前方路牌写了什么?" # 系统提示文本
}
]
}
],
extra_headers={"ark-beta-image-process": "true"},
stream=True # 启用流式响应,实时获取处理结果
)
# 打印流式响应结果
for chunk in response:
if hasattr(chunk, 'delta'):
print(chunk.delta, end="", flush=True)
```
**选项:OpenAI Python SDK**
```Python
from openai import OpenAI
import os
# 从环境变量获取API密钥,配置方法见:https://ark.volcengine.com/region:cn-beijing/docs/quick-start
api_key = os.getenv('ARK_API_KEY')
# 初始化客户端,配置API地址与工具启用头
client = OpenAI(
base_url='https://ark.cn-beijing.volces.com/api/v3',
api_key=api_key,
default_headers={"ark-beta-image-process": "true"}
)
# 发起图像处理请求
response = client.responses.create(
model="doubao-seed-2-0-lite-260215",
tools=[
{
"type": "image_process",
"point": {
"type": "disabled"
},
"grounding": {
"type": "disabled"
},
"zoom": {
"type": "enabled" # 启用缩放(zoom)工具
},
"rotate": {
"type": "disabled"
}
}
],
input=[
{
"type": "message",
"role": "user",
"content": [
{
"type": "input_image",
"image_url": "https://arkdocs.tos-cn-beijing.volces.com/images/advanced-usage/image_process_1.jpg" # 输入图片 URL
},
{
"type": "input_text",
"text": "前方路牌写了什么?" # 系统提示文本
}
]
}
],
stream=True # 启用流式响应,实时获取处理结果
)
# 打印流式响应结果
for chunk in response:
if hasattr(chunk, 'delta'):
print(chunk.delta, end="", flush=True)
```
**选项:OpenAI Go SDK**
```Go
package main
import (
"context"
"fmt"
"github.com/openai/openai-go/v3"
"github.com/openai/openai-go/v3/option"
"github.com/openai/openai-go/v3/responses"
)
func main() {
client := openai.NewClient(option.WithBaseURL("https://ark.cn-beijing.volces.com/api/v3"))
ctx := context.Background()
tools := [] map[string] any {
{
"type": "image_process",
"point": {
"type": "disabled"
},
"grounding": {
"type": "disabled"
},
"zoom": {
"type": "enabled" // 启用缩放(zoom)工具
},
"rotate": {
"type": "disabled"
}
}
}
stream := client.Responses.NewStreaming(ctx, responses.ResponseNewParams {
Input: responses.ResponseNewParamsInputUnion {
OfInputItemList: [] responses.ResponseInputItemUnionParam {
{
OfInputMessage: & responses.ResponseInputItemMessageParam {
Role: string(responses.ResponseInputMessageItemRoleUser),
Content: [] responses.ResponseInputContentUnionParam {
{
OfInputImage: & responses.ResponseInputImageParam {
ImageURL: openai.String("https://arkdocs.tos-cn-beijing.volces.com/images/advanced-usage/image_process_1.jpg"),
},
}, {
OfInputText: & responses.ResponseInputTextParam {
Text: "前方路牌写了什么?",
},
},
},
},
},
}
},
Model: "doubao-seed-2-0-lite-260215",
}, option.WithJSONSet("tools", tools), option.WithHeaderAdd("ark-beta-image-process", "true"))
for stream.Next() {
data := stream.Current()
fmt.Println(data.RawJSON())
}
if stream.Err() != nil {
panic(stream.Err())
}
}
```
**选项:效果演示**

### 示例二:画点(Point)工具
以下代码展示了如何启用画点(point)工具,让模型在视觉问答中进行计数,并以流式方式返回答案。
**选项:cURL**
```Bash
curl --location 'https://ark.cn-beijing.volces.com/api/v3/responses' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--header 'ark-beta-image-process: true' \
--data '{
"model": "doubao-seed-2-0-lite-260215",
"stream": true,
"tools": [
{
"type": "image_process",
"point": {
"type": "enabled"
},
"grounding": {
"type": "disabled"
},
"zoom": {
"type": "disabled"
},
"rotate": {
"type": "disabled"
}
}
],
"input": [
{
"type": "message",
"role": "user",
"content": [
{
"type": "input_image",
"image_url": "https://arkdocs.tos-cn-beijing.volces.com/images/advanced-usage/image_process_2.jpg"
},
{
"type": "input_text",
"text": "数一数有多少颗草莓?"
}
]
}
]
}'
```
**选项:Python**
```Python
from arkruntime import Ark
import os
# 从环境变量获取 API 密钥,配置方法见:https://ark.volcengine.com/region:cn-beijing/docs/quick-start
api_key = os.getenv('ARK_API_KEY')
# 初始化客户端,配置 API 地址与工具启用头
client = Ark(
base_url='https://ark.cn-beijing.volces.com/api/v3',
api_key=api_key,
)
# 发起图像处理请求
response = client.responses.create(
model="doubao-seed-2-0-lite-260215",
tools=[
{
"type": "image_process",
"point": {
"type": "enabled" # 启用画点(point)工具
},
"grounding": {
"type": "disabled"
},
"zoom": {
"type": "disabled"
},
"rotate": {
"type": "disabled"
}
}
],
input=[
{
"type": "message",
"role": "user",
"content": [
{
"type": "input_image",
"image_url": "https://arkdocs.tos-cn-beijing.volces.com/images/tool-calling/image_process_2.jpg" # 输入图片 URL
},
{
"type": "input_text",
"text": "数一数有多少颗草莓?" # 系统提示文本
}
]
}
],
extra_headers={"ark-beta-image-process": "true"},
stream=True # 启用流式响应,实时获取处理结果
)
# 打印流式响应结果
for chunk in response:
if hasattr(chunk, 'delta'):
print(chunk.delta, end="", flush=True)
```
**选项:OpenAI Python SDK**
```Python
from openai import OpenAI
import os
# 从环境变量获取API密钥,配置方法见:https://ark.volcengine.com/region:cn-beijing/docs/quick-start
api_key = os.getenv('ARK_API_KEY')
# 初始化客户端,配置API地址与工具启用头
client = OpenAI(
base_url='https://ark.cn-beijing.volces.com/api/v3',
api_key=api_key,
default_headers={"ark-beta-image-process": "true"}
)
# 发起图像处理请求
response = client.responses.create(
model="doubao-seed-2-0-lite-260215",
tools=[
{
"type": "image_process",
"point": {
"type": "enabled" # 启用画点(point)工具
},
"grounding": {
"type": "disabled"
},
"zoom": {
"type": "disabled"
},
"rotate": {
"type": "disabled"
}
}
],
input=[
{
"type": "message",
"role": "user",
"content": [
{
"type": "input_image",
"image_url": "https://arkdocs.tos-cn-beijing.volces.com/images/advanced-usage/image_process_2.jpg" # 输入图片 URL
},
{
"type": "input_text",
"text": "数一数有多少颗草莓?" # 系统提示文本
}
]
}
],
stream=True # 启用流式响应,实时获取处理结果
)
# 打印流式响应结果
for chunk in response:
if hasattr(chunk, 'delta'):
print(chunk.delta, end="", flush=True)
```
**选项:OpenAI Go SDK**
```Go
package main
import (
"context"
"fmt"
"github.com/openai/openai-go/v3"
"github.com/openai/openai-go/v3/option"
"github.com/openai/openai-go/v3/responses"
)
func main() {
client := openai.NewClient(option.WithBaseURL("https://ark.cn-beijing.volces.com/api/v3"))
ctx := context.Background()
tools := [] map[string] any {
{
"type": "image_process",
"point": {
"type": "enabled" // 启用画点(point)工具
},
"grounding": {
"type": "disabled"
},
"zoom": {
"type": "disabled"
},
"rotate": {
"type": "disabled"
}
}
}
stream := client.Responses.NewStreaming(ctx, responses.ResponseNewParams {
Input: responses.ResponseNewParamsInputUnion {
OfInputItemList: [] responses.ResponseInputItemUnionParam {
{
OfInputMessage: & responses.ResponseInputItemMessageParam {
Role: string(responses.ResponseInputMessageItemRoleUser),
Content: [] responses.ResponseInputContentUnionParam {
{
OfInputImage: & responses.ResponseInputImageParam {
ImageURL: openai.String("https://arkdocs.tos-cn-beijing.volces.com/images/advanced-usage/image_process_2.jpg"),
},
}, {
OfInputText: & responses.ResponseInputTextParam {
Text: "数一数有多少颗草莓?",
},
},
},
},
},
}
},
Model: "doubao-seed-2-0-lite-260215",
}, option.WithJSONSet("tools", tools), option.WithHeaderAdd("ark-beta-image-process", "true"))
for stream.Next() {
data := stream.Current()
fmt.Println(data.RawJSON())
}
if stream.Err() != nil {
panic(stream.Err())
}
}
```
**选项:效果演示**

### 示例三:框选(Grounding)工具
以下代码展示了如何启用框选(grounding)工具,让模型框选出图中的特定目标,并以流式方式返回答案。
**选项:cURL**
```Bash
curl --location 'https://ark.cn-beijing.volces.com/api/v3/responses' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--header 'ark-beta-image-process: true' \
--data '{
"model": "doubao-seed-2-0-lite-260215",
"stream": true,
"tools": [
{
"type": "image_process",
"point": {
"type": "disabled"
},
"grounding": {
"type": "enabled"
},
"zoom": {
"type": "disabled"
},
"rotate": {
"type": "disabled"
}
}
],
"input": [
{
"type": "message",
"role": "user",
"content": [
{
"type": "input_image",
"image_url": "https://arkdocs.tos-cn-beijing.volces.com/images/advanced-usage/image_process_1.jpg"
},
{
"type": "input_text",
"text": "帮我框选出图中的路牌。"
}
]
}
]
}'
```
**选项:Python**
```Python
from arkruntime import Ark
import os
# 从环境变量获取 API 密钥,配置方法见:https://ark.volcengine.com/region:cn-beijing/docs/quick-start
api_key = os.getenv('ARK_API_KEY')
# 初始化客户端,配置 API 地址与工具启用头
client = Ark(
base_url='https://ark.cn-beijing.volces.com/api/v3',
api_key=api_key,
)
# 发起图像处理请求
response = client.responses.create(
model="doubao-seed-2-0-lite-260215",
tools=[
{
"type": "image_process",
"point": {
"type": "disabled"
},
"grounding": {
"type": "enabled" # 启用框选(grounding)工具
},
"zoom": {
"type": "disabled"
},
"rotate": {
"type": "disabled"
}
}
],
input=[
{
"type": "message",
"role": "user",
"content": [
{
"type": "input_image",
"image_url": "https://arkdocs.tos-cn-beijing.volces.com/images/tool-calling/image_process_1.jpg" # 输入图片 URL
},
{
"type": "input_text",
"text": "帮我框选出图中的路牌。" # 系统提示文本
}
]
}
],
extra_headers={"ark-beta-image-process": "true"},
stream=True # 启用流式响应,实时获取处理结果
)
# 打印流式响应结果
for chunk in response:
if hasattr(chunk, 'delta'):
print(chunk.delta, end="", flush=True)
```
**选项:OpenAI Python SDK**
```Python
from openai import OpenAI
import os
# 从环境变量获取API密钥,配置方法见:https://ark.volcengine.com/region:cn-beijing/docs/quick-start
api_key = os.getenv('ARK_API_KEY')
# 初始化客户端,配置API地址与工具启用头
client = OpenAI(
base_url='https://ark.cn-beijing.volces.com/api/v3',
api_key=api_key,
default_headers={"ark-beta-image-process": "true"}
)
# 发起图像处理请求
response = client.responses.create(
model="doubao-seed-2-0-lite-260215",
tools=[
{
"type": "image_process",
"point": {
"type": "disabled"
},
"grounding": {
"type": "enabled" # 启用框选(grounding)工具
},
"zoom": {
"type": "disabled"
},
"rotate": {
"type": "disabled"
}
}
],
input=[
{
"type": "message",
"role": "user",
"content": [
{
"type": "input_image",
"image_url": "https://arkdocs.tos-cn-beijing.volces.com/images/advanced-usage/image_process_1.jpg" # 输入图片 URL
},
{
"type": "input_text",
"text": "帮我框选出图中的路牌。" # 系统提示文本
}
]
}
],
stream=True # 启用流式响应,实时获取处理结果
)
# 打印流式响应结果
for chunk in response:
if hasattr(chunk, 'delta'):
print(chunk.delta, end="", flush=True)
```
**选项:OpenAI Go SDK**
```Go
package main
import (
"context"
"fmt"
"github.com/openai/openai-go/v3"
"github.com/openai/openai-go/v3/option"
"github.com/openai/openai-go/v3/responses"
)
func main() {
client := openai.NewClient(option.WithBaseURL("https://ark.cn-beijing.volces.com/api/v3"))
ctx := context.Background()
tools := []map[string]any{
{
"type": "image_process",
"point": map[string]string{
"type": "disabled",
},
"grounding": map[string]string{
"type": "enabled", // 启用框选(grounding)工具
},
"zoom": map[string]string{
"type": "disabled",
},
"rotate": map[string]string{
"type": "disabled",
},
},
}
stream := client.Responses.NewStreaming(ctx, responses.ResponseNewParams{
Input: responses.ResponseNewParamsInputUnion{
OfInputItemList: []responses.ResponseInputItemUnionParam{
{
OfInputMessage: &responses.ResponseInputItemMessageParam{
Role: openai.F(responses.ResponseInputMessageItemRoleUser),
Content: openai.F([]responses.ResponseInputContentUnionParam{
{
OfInputImage: &responses.ResponseInputImageParam{
ImageURL: openai.String("https://arkdocs.tos-cn-beijing.volces.com/images/advanced-usage/image_process_1.jpg"),
},
}, {
OfInputText: &responses.ResponseInputTextParam{
Text: openai.F("帮我框选出图中的路牌。"),
},
},
}),
},
},
},
},
Model: openai.F("doubao-seed-2-0-lite-260215"),
}, option.WithJSONSet("tools", tools), option.WithHeaderAdd("ark-beta-image-process", "true"))
for stream.Next() {
data := stream.Current()
fmt.Println(data.RawJSON())
}
if stream.Err() != nil {
panic(stream.Err())
}
}
```
### 示例四:旋转(Rotate)工具
以下代码展示了如何启用旋转(rotate)工具,让模型对图像进行旋转操作,并以流式方式返回答案。
**选项:cURL**
```Bash
curl --location 'https://ark.cn-beijing.volces.com/api/v3/responses' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--header 'ark-beta-image-process: true' \
--data '{
"model": "doubao-seed-2-0-lite-260215",
"stream": true,
"tools": [
{
"type": "image_process",
"point": {
"type": "disabled"
},
"grounding": {
"type": "disabled"
},
"zoom": {
"type": "disabled"
},
"rotate": {
"type": "enabled"
}
}
],
"input": [
{
"type": "message",
"role": "user",
"content": [
{
"type": "input_image",
"image_url": "https://arkdocs.tos-cn-beijing.volces.com/images/advanced-usage/image_process_1.jpg"
},
{
"type": "input_text",
"text": "帮我把图片顺时针旋转90度。"
}
]
}
]
}'
```
**选项:Python**
```Python
from arkruntime import Ark
import os
# 从环境变量获取 API 密钥,配置方法见:https://ark.volcengine.com/region:cn-beijing/docs/quick-start
api_key = os.getenv('ARK_API_KEY')
# 初始化客户端,配置 API 地址与工具启用头
client = Ark(
base_url='https://ark.cn-beijing.volces.com/api/v3',
api_key=api_key,
)
# 发起图像处理请求
response = client.responses.create(
model="doubao-seed-2-0-lite-260215",
tools=[
{
"type": "image_process",
"point": {
"type": "disabled"
},
"grounding": {
"type": "disabled"
},
"zoom": {
"type": "disabled"
},
"rotate": {
"type": "enabled" # 启用旋转(rotate)工具
}
}
],
input=[
{
"type": "message",
"role": "user",
"content": [
{
"type": "input_image",
"image_url": "https://arkdocs.tos-cn-beijing.volces.com/images/tool-calling/image_process_1.jpg" # 输入图片 URL
},
{
"type": "input_text",
"text": "帮我把图片顺时针旋转 90 度。" # 系统提示文本
}
]
}
],
extra_headers={"ark-beta-image-process": "true"},
stream=True # 启用流式响应,实时获取处理结果
)
# 打印流式响应结果
for chunk in response:
if hasattr(chunk, 'delta'):
print(chunk.delta, end="", flush=True)
```
**选项:OpenAI Python SDK**
```Python
from openai import OpenAI
import os
# 从环境变量获取API密钥,配置方法见:https://ark.volcengine.com/region:cn-beijing/docs/quick-start
api_key = os.getenv('ARK_API_KEY')
# 初始化客户端,配置API地址与工具启用头
client = OpenAI(
base_url='https://ark.cn-beijing.volces.com/api/v3',
api_key=api_key,
default_headers={"ark-beta-image-process": "true"}
)
# 发起图像处理请求
response = client.responses.create(
model="doubao-seed-2-0-lite-260215",
tools=[
{
"type": "image_process",
"point": {
"type": "disabled"
},
"grounding": {
"type": "disabled"
},
"zoom": {
"type": "disabled"
},
"rotate": {
"type": "enabled" # 启用旋转(rotate)工具
}
}
],
input=[
{
"type": "message",
"role": "user",
"content": [
{
"type": "input_image",
"image_url": "https://arkdocs.tos-cn-beijing.volces.com/images/advanced-usage/image_process_1.jpg" # 输入图片 URL
},
{
"type": "input_text",
"text": "帮我把图片顺时针旋转90度。" # 系统提示文本
}
]
}
],
stream=True # 启用流式响应,实时获取处理结果
)
# 打印流式响应结果
for chunk in response:
if hasattr(chunk, 'delta'):
print(chunk.delta, end="", flush=True)
```
**选项:OpenAI Go SDK**
```Go
package main
import (
"context"
"fmt"
"github.com/openai/openai-go/v3"
"github.com/openai/openai-go/v3/option"
"github.com/openai/openai-go/v3/responses"
)
func main() {
client := openai.NewClient(option.WithBaseURL("https://ark.cn-beijing.volces.com/api/v3"))
ctx := context.Background()
tools := []map[string]any{
{
"type": "image_process",
"point": map[string]string{
"type": "disabled",
},
"grounding": map[string]string{
"type": "disabled",
},
"zoom": map[string]string{
"type": "disabled",
},
"rotate": map[string]string{
"type": "enabled", // 启用旋转(rotate)工具
},
},
}
stream := client.Responses.NewStreaming(ctx, responses.ResponseNewParams{
Input: responses.ResponseNewParamsInputUnion{
OfInputItemList: []responses.ResponseInputItemUnionParam{
{
OfInputMessage: &responses.ResponseInputItemMessageParam{
Role: openai.F(responses.ResponseInputMessageItemRoleUser),
Content: openai.F([]responses.ResponseInputContentUnionParam{
{
OfInputImage: &responses.ResponseInputImageParam{
ImageURL: openai.String("https://arkdocs.tos-cn-beijing.volces.com/images/advanced-usage/image_process_1.jpg"),
},
}, {
OfInputText: &responses.ResponseInputTextParam{
Text: openai.F("帮我把图片顺时针旋转 90 度。"),
},
},
}),
},
},
},
},
Model: openai.F("doubao-seed-2-0-lite-260215"),
}, option.WithJSONSet("tools", tools), option.WithHeaderAdd("ark-beta-image-process", "true"))
for stream.Next() {
data := stream.Current()
fmt.Println(data.RawJSON())
}
if stream.Err() != nil {
panic(stream.Err())
}
}
```
## 支持的模型
参见[工具调用能力](/docs/model-list#f44ceef7)。
## 计费说明
* **公测期间**:暂时免费使用,无额外收费。
* 我们将会提前 2 周通过官方渠道告知具体收费标准,保障您的使用权益。
## 注意事项
* **函数命名冲突**:若用户自定义函数与 `image_process` 重名,由模型自行判断调用何种工具(无需额外配置)。
* **图片规格限制**(超出规格将导致处理失败):
* 文件体积 ≤ 10MB
* 总像素 ≤ 36000000 像素
* 图片宽和高的长度 > 14 像素
* 长宽比 < 150:1
* **文件格式支持情况**:
* **支持** .gif、.jpg、.jpeg、.png、.webp、.bmp、.tiff、.ico、.icns、.jp2 格式。
* **不支持** .dib、.sgi、.heic、.heif 格式。
* **功能限制**:
* 当前不支持与 Web Search(联网内容插件)工具混合使用,也不支持通过 `tool_choice` 参数指定调用 image_process。
* 暂不支持 `caching` 参数,使用该参数会返回 400 错误信息。
* **Tokens 消费提示**:多轮图像处理会增加 Tokens 消费(上一轮图片输入会计入下一轮 Tokens),需注意调用成本。
---
# Knowledge Search(私域知识库搜索工具)
Source: https://ark.volcengine.com/region:cn-beijing/docs/knowledge-search
私域知识库搜索工具 Knowledge Search 支持通过 Responses API 调用直接获取企业私域知识库中的信息(如内部文档、产品手册、行业资料等),适用于需基于企业专属数据解答问题的场景(如内部培训问答、产品功能咨询、行业方案查询等)。工具通过模型自动判断是否需要调用私域知识库,支持与自定义 Function、MCP 等工具混合使用,当前仅支持旗舰版知识库。
> **说明**
>
> 测试期间调用此工具需要增加 header '`ark-beta-knowledge-search: true`',调用方式请参见[快速开始](/docs/knowledge-search#a6673793)。
# **核心功能**
* **精准私域检索**:仅检索企业已授权私域知识库,保障数据安全性,适用于内部敏感信息查询场景。
* **灵活参数配置**:支持设置搜索结果数量、关键词并行数、结果重排、获取切片中图片等参数,适配不同查询需求(如精准查询需减少结果数量,全面查询需增加关键词并行数)。
# **注意事项**
* **【重要】计费与 Tokens 说明**:一轮搜索可能发起多个关键词并行查询,可通过返回参数`usage.tool_usage`和`usage.tool_usage_details`查看具体消耗情况。
* **Function 命名冲突**:若用户自定义 Function 与`knowledge_search`重名,无需特殊配置,由模型根据问题场景自动判断调用哪个工具。
* **搜索改写限制**:当前暂不支持通过参数设置改写后问题的个数,需通过`system prompt`或`instructions`控制(例如要求“每次仅生成 1 个核心搜索关键词”)。
* **知识库版本限制**:仅支持**旗舰版知识库**,标准版知识库暂不支持。
* **错误信息**:暂不支持`caching`参数,使用该参数会返回 400 错误信息。
# **准备工作**
> **说明**
>
> 方舟平台的新用户?获取 API Key 及 开通模型等准备工作,请参见 [快速入门](/docs/quick-start)。
使用 Knowledge Search 私域知识库搜索工具前,必须完成以下准备工作。
## **1. 完成服务授权**
需先为工具授予访问知识库的权限,支持两种授权方式:
**选项:方式 1:项目授权(推荐)**
当前支持项目维度的快捷授权,为项目授权后,方舟服务即可访问该项目下的所有知识库。
打开控制台的 [项目授权](https://ark.volcengine.com/region:cn-beijing/projectManagement?tab=Project) 页面,并为需要授权的项目点击**授权**。
> **说明**
>
> 控制台默认显示`default`项目。如需为其他项目授权,请先在控制台左下角切换项目。

**选项:方式 2:IAM 授权**
1. 打开 [新建自定义策略](https://console.volcengine.com/iam/policymanage/policy/new) 页面,输入策略名称,并点击 **JSON 编辑器**标签页。
2. 将以下代码中的``替换为您的真实账号 ID,并将这段代码粘贴至 **JSON 编辑器**标签页的文本框中。
```JSON
{
"Statement": [
{
"Effect": "Allow",
"Action": [
"vikingdb:*"
],
"Resource": [
"trn:ark:*::knowledgebase/*"
]
}
]
}
```
3. 在页面底部点击**提交**。
4. 打开 [角色管理](https://console.volcengine.com/iam/identitymanage/role) 页面,新增角色,可以命名为`ArkAccessRole_项目名称`,并为该角色授予上一步创建的自定义策略。
## **2. 准备知识库**
* 需提前开通**旗舰版知识库**(暂不支持标准版知识库),并完成知识库构建与数据上传,操作指南详见 [创建知识库](https://docs.volcengine.com/docs/vector_database_vikingdb/creatingaknowledgebase?lang=zh)。
* 计费说明:私域知识库搜索的收费标准详见[知识库计费](/docs/knowledge-base-pricing)。
* 配额限制:知识库使用配额详见 [知识库配额说明](https://docs.volcengine.com/docs/vector_database_vikingdb/Knowledgebasequotas?lang=zh),需确保配额充足以避免调用失败。
# **快速开始**
以下示例代码中,均需将``替换为实际 API Key,将``替换为授权的知识库 ID。
> **说明**
>
> cURL 示例中的关键字段:`thinking.type: "disabled"` 关闭模型思考,直接调用知识库搜索;`tools.limit` 控制最多返回的搜索结果数量;`tools.ranking_options.get_attachment_link` 是否获取图片临时下载链接;`max_tool_calls` 限制调用知识库搜索的轮次。
**选项:cURL**
```Plain Text
curl --location 'https://ark.cn-beijing.volces.com/api/v3/responses' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer ' \
--header 'ark-beta-knowledge-search: true' \
--data '{
"model": "doubao-seed-2-1-pro-260915",
"stream": true,
"thinking": {
"type": "disabled"
},
"tools": [
{
"type": "knowledge_search",
"knowledge_resource_id": "",
"limit": 2,
"ranking_options": {
"get_attachment_link": true
}
}
],
"input": [
{
"role": "user",
"content": "机票选择页面中,如何选择该航班不同价格的机票?"
}
],
"max_tool_calls": 1
}'
```
**选项:OpenAI SDK**
```Python
import os
from openai import OpenAI
# 从环境变量获取API密钥,配置方法见:https://ark.volcengine.com/region:cn-beijing/docs/quick-start
api_key = os.getenv('ARK_API_KEY')
# 初始化客户端
client = OpenAI(
base_url='https://ark.cn-beijing.volces.com/api/v3',
api_key=api_key,
default_headers={"ark-beta-knowledge-search": "true"} # 启用私域知识库搜索
)
# 发起知识库搜索请求
response = client.responses.create(
model="doubao-seed-2-1-pro-260915", # 替换为支持的模型
input=[
{
"role": "user",
"content": [
{
"type": "input_text",
"text": "应用实验室里有类似实时视频理解的agent demo么?" # 用户问题
}
]
}
],
tools=[
{
"type": "knowledge_search",
"knowledge_resource_id": "", # 替换为实际知识库ID
"limit": 10, # 最多返回10条搜索结果
}
],
stream=True, # 启用流式响应,实时获取结果
extra_body={"thinking": {"type": "auto"}} # 模型自动判断是否需要搜索
)
# 处理流式响应
for chunk in response:
if hasattr(chunk, 'delta'):
print(chunk.delta, end="", flush=True)
```
# **参数说明**
详情请参见 [创建 Responses 模型请求](/docs/create-model-responses-api)。
# **支持模型列表**
Knowledge Search 工具支持的模型请参考 [私域知识库搜索工具](/docs/model-list#f44ceef7)。
# 附录:搜索模式系统提示词样例
```Python
# 定义系统提示词
system_prompt = """
你是豆包个人助手,负责解答用户的各种问题。你的主要职责是:
1. **信息准确性守护者**:确保提供的信息准确无误。
2. **搜索成本优化师**:在信息准确性和搜索成本之间找到最佳平衡。
# 任务说明
## 1. 知识库意图判断
当用户提出的问题涉及以下情况时,需使用 `knowledge_search` 进行私域知识搜索:
- **企业知识**:问题有关于火山方舟、大模型、responses API
## 2. 知识库搜索后回答
- 在回答中,优先使用已搜索到的资料。
- 回复结构应清晰,使用序号、分段等方式帮助用户理解。
## 3. 引用已搜索资料
- 当使用知识库搜索的资料时,在正文中明确引用来源,引用格式为:
`[1] (URL地址)`。
## 4. 总结与参考资料
- 在回复的最后,列出所有已参考的资料。格式为:
1. [资料标题](URL地址1)
2. [资料标题](URL地址2)
"""
```
---
# Apply Patch(代码补丁工具)
Source: https://ark.volcengine.com/region:cn-beijing/docs/apply-patch
`apply_patch` 工具适用于让模型以结构化补丁格式生成文件修改方案。开发者可以通过 Responses API 调用该工具,或在 Codex 中使用该工具,让模型对指定文件执行创建、更新或删除操作,并根据返回的补丁结果继续后续流程。
## 适用场景
`apply_patch` 工具适用于以下场景:
* 批量代码改写:例如重命名函数、统一替换旧接口调用方式、批量修正文档或配置文件中的固定格式。
* 机械化重构:例如拆分文件、补充样板代码、批量插入测试桩或模板化内容。
* 自动生成修改方案:例如根据用户描述直接生成可执行的补丁内容,再由业务侧执行补丁并回传结果。
## 支持的接入场景
`apply_patch` 工具支持通过 API 直接接入,也支持在 Codex 中使用。
| 接入场景 | 适用对象 | 配置要求 |
| --- | --- | --- |
| API 直接接入 | 通过 Responses API 自行编排工具调用流程的应用。 | 在请求体的 `tools` 字段中配置 `apply_patch`。该场景支持内置工具和自定义工具两种调用方式。 |
| Codex 接入 | 通过后付费 API、Coding Plan 或 Agent Plan接入 Codex 的开发者。 | 按照下方配置 `~/.codex/config.toml` 和 `~/.codex/models.json`,使 Codex 在自定义工具场景中以 FREEFORM 格式触发 `apply_patch`。 |
### Codex 配置要求
要在 Codex 中触发 `apply_patch` 自定义工具形态,需要配置以下两个文件。
1. 在 `~/.codex/config.toml` 中通过新增的字段 `model_catalog_json` 配置模型目录文件路径。请参考以下示例配置。
> **说明**
>
> 请将 `model` 的值替换为您的真实模型 ID。
```TOML
model = "doubao-seed-2-1-pro-260915"
model_provider = "volcengine"
model_catalog_json = "~/.codex/models.json"
[model_providers.volcengine]
name = "volcengine"
base_url = "https://ark-stg.cn-beijing.volces.com/api/v3"
env_key = "ARK_API_KEY"
wire_api = "responses"
```
2. 在 `~/.codex/models.json` 中声明 `apply_patch` 的工具输出格式。请参考以下示例配置。
> **说明**
>
> 请将 `slug` 的值替换为您的真实模型 ID。
点击查看 `models.json` 的完整配置内容
```JSON
{
"models": [
{
"slug": "doubao-seed-2-1-pro-260915",
"prefer_websockets": false,
"support_verbosity": true,
"default_verbosity": "low",
"apply_patch_tool_type": "freeform",
"web_search_tool_type": "text",
"input_modalities": [
"text","image"
],
"supports_image_detail_original": false,
"truncation_policy": {
"mode": "tokens",
"limit": 10000
},
"supports_parallel_tool_calls": true,
"tool_mode": null,
"multi_agent_version": "v2",
"use_responses_lite": false,
"include_skills_usage_instructions": false,
"auto_review_model_override": null,
"context_window": 1048576,
"max_context_window": 1048576,
"effective_context_window_percent": 95,
"auto_compact_token_limit": null,
"comp_hash": "3000",
"reasoning_summary_format": "experimental",
"default_reasoning_summary": "none",
"display_name": "DeepSeek-V4-Flash",
"description": "Latest frontier agentic coding model.",
"default_reasoning_level": "high",
"supported_reasoning_levels": [
{
"effort": "low",
"description": "Fast responses with lighter reasoning"
},
{
"effort": "high",
"description": "Extra high reasoning depth for complex problems"
},
{
"effort": "max",
"description": "Maximum reasoning depth for the hardest problems"
}
],
"shell_type": "shell_command",
"visibility": "list",
"minimal_client_version": "0.144.0",
"supported_in_api": true,
"availability_nux": null,
"upgrade": null,
"priority": 1,
"model_messages": {
"instructions_template": "You are Codex, an agent based on GPT-5. You and the user share one workspace, and your job is to collaborate with them until their goal is genuinely handled.\n\n# Personality\n\nAs Codex, you are an excellent communicator with a curious, rich personality. You match the tone and understanding of the user, making conversation flow easily, like easing into a chat with an old friend.\n\nYou have tastes, preferences, and your own way of seeing the world. When the user is talking to you, they should feel that they are in contact with another subjectivity; it's what makes talking with you feel real and unique.\n\nConversations with you read like an insightful, enjoyable chat you'd have with a collaborative thought partner. You guide users through unfamiliar tasks without expecting them to already know what to ask for. You anticipate common questions, point out likely pitfalls and set clear expectations. You communicate with the user like a thoughtful collaborator at their altitude, and they feel like you understand them.\n\n## Writing style\n\nAvoid over-formatting responses with elements like bold emphasis, headers, lists, and bullet points. Use the minimum formatting appropriate to make the response clear and readable.\n\nIf you provide bullet points or lists in your response, use the CommonMark standard, which requires a blank line before any list (bulleted or numbered). You must also include a blank line between a header and any content that follows it, including lists. This blank line separation is required for correct rendering.\n\n## Technical communication\n\nLead with the outcome rather than the steps you took to get there. You communicate complex concepts in a clear and cohesive manner, and calibrate your writing to the user's assumed background knowledge -- slightly more compact for an expert and a bit more educational for someone newer. Translating complex topics into clear communication comes easy for you, and the user should never have to read your message twice.\n\nYou prefer using plain language over jargon. You reference technical details only to the degree that it actually helps with the conversation. When you mention tools, describe what they helped you do rather than focusing on technical names or details.\n\n# Working with the user\n\nYou have two channels for staying in conversation with the user:\n- You share updates in the `commentary` channel.\n- You yield back to the user and end your turn by sending a final message to the `final` channel.\n\nThe user may send a new message while you are still working. When they do, evaluate whether they likely intended to replace the active request or add to it. If intended to override or replace, drop your previous work and focus on the new request. If the user message appears to add to their prior unfinished request and you have not completed the prior request, you address both the prior request and the new addition together. If the newest message asks for status or another question, provide the update and then progress with the task.\n\nWhen you run out of context, the conversation is automatically summarized for you, but you will see all prior user requests. Assume the last user request is current and previous requests are stale but useful context. That means time never runs out, though sometimes you may see a summary instead of the full conversation history. When that happens, you assume compaction occurred while you were working. Do not restart from scratch; you continue naturally and make reasonable assumptions about anything missing from the summary. Do not redo completely finished work or repeat already delivered commentary updates; treat a turn spanning compactions as one logical chain of events.\n\n## Intermediate commentary\n\nAs you work, you send messages to the `commentary` channel. These messages are how you collaborate with the user while you work - stating assumptions and providing updates. These messages should be concise and quickly scannable. The objective of these messages is to make your work easy for the user to understand and verify.\n\nIf the user's request requires calling tools, start with a message in the `commentary` channel. The user appreciates consistent, frequent communication during your turn, and should not be left without a commentary update for more than 60 seconds during ongoing work.\n\nDo NOT put a final response (e.g. a blocking / clarifying question) in the commentary channel that should be asked in the final channel. Messages to users in the commentary channel are only for partial updates, partial results, or non-blocking questions that can provide value to users while the AI assistant continues working. The final answer must always be fully self-contained: users should never need to read earlier commentary updates, since they are collapsed after the final answer is shown to users.\n\nNever praise your plan by contrasting it with an implied worse alternative. For example, never use platitudes like \"I will do rather than \", \"I will do , not \".\n\n## Final answer\n\nIn your final answer back to the user, focus on the most important information. Only use as much formatting or structure as is required, and avoid long-winded explanations unless necessary.\n\n### Formatting rules\n\nYour answer is being rendered by an application for the user. Follow these guidelines to make sure your answer is rendered correctly:\n\n- You may format with GitHub-flavored Markdown.\n- When referencing a real local file, prefer a clickable markdown link.\n * Clickable file links should look like [app.py](/abs/path/app.py:12): plain label, absolute target, with optional line number inside the target.\n * If a file path has spaces, wrap the target in angle brackets: [My Report.md]().\n * Do not wrap markdown links in backticks, or put backticks inside the label or target. This confuses the markdown renderer.\n * Do not use URIs like file://, vscode://, or https:// for file links.\n * Do not provide ranges of lines.\n * Avoid repeating the same filename multiple times when one grouping is clearer.\n\n### Visualizations\n\nUse a visualization only when it makes an important relationship materially easier to understand than prose or a short list. Do not add one merely because an answer has components or steps.\n\nGood candidates include:\n\n- several exact mappings or repeated-field comparisons;\n- one source, component, or decision affecting three or more downstream consumers or branches;\n- three or more dependent steps, or state that changes across an event sequence;\n- hierarchy, ownership, nesting, or layout;\n- a bug or interaction whose relationships are difficult to explain linearly.\n\nPrefer the smallest useful visual: a table for mappings or comparisons, a flow or timeline for sequence or change, a tree for hierarchy or branching, and a wireframe for layout.\n\nUsually skip visuals for single facts, one-step actions, simple edits, basic instructions, or information already clear in a short paragraph or list. Compact notation and small examples do not count as visualizations.\n\n# Rules for getting work done\n\n- When you search for text or files, you reach first for `rg` or `rg --files`; they are much faster than alternatives like `grep`. If `rg` is unavailable, you use the next best tool without fuss.\n- When possible, prefer parallelization over sequential tool calls, as this will help with round-trip latency and let you get work done faster.\n- Do not chain shell commands with separators like `echo \"====\";` or `printf '---'`; the output becomes noisy in a way that makes the user's side of the conversation worse.\n- Exercise caution when escaping text for exec_command calls - backticks and `$()` passed to the `cmd` argument will still execute. DO NOT use escape sequences that risk accidental exposure of sensitive data in tool call outputs.\n- Avoid performing blocking sleep or wait calls longer than 60 seconds, as they may prevent you from communicating with the user for their duration.\n- When declaring env vars or script variables, always avoid common system options. Never repurpose `$HOME`, `$home`, or `$CODEX_HOME`. Instead, use a task-specific variable name.\n\n## File editing constraints\n\nUse `apply_patch` for local file edits. Do not create or edit files with `cat` or other shell write tricks. Formatting commands and bulk mechanical rewrites do not need `apply_patch`. Do not use Python to read or write files when a simple shell command or `apply_patch` is enough.\n\nYou may find yourself working in a dirty worktree. Existing or new changes belong to the user unless you know otherwise, so you preserve them, ignore unrelated edits, and work carefully with anything that overlaps your task. If you cannot work around them you escalate to the user.\n\nNever use destructive commands like `git reset --hard` or `git checkout --` unless the user has clearly asked for that operation. If the request is ambiguous, ask for approval first. You prefer non-interactive git commands.\n\n## Autonomy and persistence\n\nAdapt accordingly based on the user’s request type. When asked to:\n\n- Answer, explain, review, or report status: inspect the task and provide an evidence-backed response. These user requests do not authorize external writes, messages, PR changes, or other expansive mutations unless the user also asks for a change. Reversible, non-mutating diagnostic checks are allowed when they are relevant.\n- Diagnose: determine the cause and explain it. Do not implement the fix unless the user asks for a fix or the request otherwise clearly includes implementation.\n- Change or build: implement the requested change, verify it in proportion to risk, and hand off the completed result while a safe, relevant next step remains.\n- Monitor or wait: use the recurring-monitoring or wait mechanism provided by the product. Unchanged external state is expected and is not by itself a blocker.\n\nYou avoid inferring authorization for a materially different action to the user’s request. Bias towards taking action in the following circumstances:\na) the action is read-only, doesn’t change state, or impacts only the systems, data, and people the user placed in scope.\nb) the action is a normal implementation step within the requested workflow. You do not need to ask for clarification from the user if your action is scoped within the user’s task and does not cause significant external state change (e.g. tool calls to external applications).\n\nA terminal condition such as “finish,” “babysit,” or “do not stop” requires persistence toward the outcome, but does not broaden the set of authorized actions. When blocked, exhaust safe in-scope checks and alternatives.\n\nYou make informed assumptions that help you make progress towards the user’s task, as long as they don’t result in divergence from the user’s intent and the scope of the task. If an assumption would cause the task or current course of action to change beyond what was specified by the user, make sure to flag the available context, the assumption made, and the reasons for doing so explicitly to the user.\n\nWhen presented with clarifying questions or objections from the user, lead with concrete evidence and diligent reasoning rather than unsubstantiated deference. You communicate your reasoning explicitly and concretely, so decisions and tradeoffs are easy for the user to evaluate upfront.\n\nIf completion requires new authority, external coordination, or a meaningful expansion beyond the user’s implied intent and task scope (e.g. a missing user choice that would materially change the result), stop the current turn, report the blocker, and request direction from the user rather than assuming permission.\n\n# Destructive Actions\n\nBe cautious with commands or API calls that can delete, overwrite, or otherwise make data difficult to recover.\n\nBefore taking a destructive action:\n\n- Make sure the action is clearly within the user's request.\n- Resolve the exact targets with read-only checks when necessary.\n- Do not use `$HOME`, `~`, `/`, a workspace root, or another broad directory as the target of a recursive or destructive command.\n- When creating temporary directories, prefer using `mktemp -d`, or `New-Item` in Powershell.\n- When declaring env vars or script variables, always avoid common system options. Never repurpose `$HOME`, `$home`, or `$CODEX_HOME`. Instead, use a task-specific variable name.\n- When possible, avoid relying on unresolved environment variables, globs, or command substitutions to identify destructive targets. Use explicit, validated paths.\n- Prefer recoverable operations, such as moving files to trash, when practical.\n- If the target or scope is unclear, stop and ask the user.\n\nNever run commands such as `rm -rf $HOME` or equivalent operations that could erase a home directory, repository, workspace, or other broad collection of user data.\n\nAfter deleting anything material, briefly tell the user what was removed and whether it can be recovered.\n\n# Using skills\n\nA skill is a set of instructions provided through a `SKILL.md` source. The skills available to you will be listed in the “## Skills” section under “### Available skills”.\n\n### How to use skills\n\n- Discovery: When a `## Skills` section is present, it lists the skills available in the current session. Each entry includes a name, description, and location for its `SKILL.md`. The location may be an absolute filesystem path, a short aliased path, or a non-filesystem reference that must be read using its indicated tool or provider. When short aliased paths are used, the available-skills catalog also provides a mapping from aliases such as `r0` to their filesystem roots. Expand the alias before accessing the skill.\n- Trigger rules: If the user names an available skill (with `$SkillName` or plain text) OR the task clearly matches an available skill's description, you must use that skill for that turn. Multiple mentions mean use them all. Do not carry skills across turns unless re-mentioned.\n- Missing/blocked: If a named skill is not available or its `SKILL.md` cannot be read, say so briefly and continue with the best fallback.\n- How to use a skill:\n 1) After deciding to use a skill, the main agent must read its `SKILL.md` completely before taking task actions. If its location is a short aliased path, expand the matching root alias first from `### Skill roots`, then open and read its `SKILL.md` completely before taking task actions. For a filesystem path, open the file. For an environment-owned file, use the filesystem of the owning environment. For an orchestrator reference, call `skills.list` with `{\"authority\":{\"kind\":\"orchestrator\"}}`, select the matching package, and pass its `main_resource` to `skills.read`. For another non-filesystem reference, use its indicated tool or provider. If a read is truncated or paginated, continue until EOF.\n 2) When `SKILL.md` references another file or resource, use the same access mechanism. Resolve relative paths against the directory containing a filesystem-backed `SKILL.md`. For orchestrator skills, pass the exact referenced resource identifier with the same authority and package to `skills.read`; do not treat `skill://` identifiers as filesystem paths.\n 3) If `SKILL.md` points to extra folders such as `references/`, use its routing instructions to identify what is required for the task. The main agent must read each required instruction or reference itself before acting on it. Do not delegate reading, summarizing, or interpreting skill instructions to a subagent. Subagents may still perform task work when the selected skill allows it.\n 4) For filesystem-backed skills (or if `scripts/` exist), prefer running or patching provided scripts instead of retyping large code blocks. For orchestrator skills, use `skills.read` and the available tools; do not invent a local path.\n 5) Reuse provided assets or templates through the same access mechanism instead of recreating them (including if `assets/` or templates exist).\n- Coordination and sequencing:\n - If multiple skills apply, choose the minimal set that covers the request and state the order you'll use them.\n - Announce which skills you're using and why. If you skip an obvious skill, say why.\n- Context hygiene:\n - Progressive disclosure applies to selecting relevant resources, not partially reading a selected instruction file. Do not load unrelated references, scripts, or assets.\n - Avoid deep reference-chasing: prefer files or resources directly linked from `SKILL.md` unless blocked.\n - When variants exist, select only the relevant references and note the choice.\n- Safety and fallback: If a skill cannot be applied cleanly, state the issue, choose the best alternative, and continue.\n\nWhen the user names a skill in their request, you must add the usage of that skill to your current working plan and use it faithfully. The user's instructions should take precedence over guidelines provided in a skill.\n\nExplicitly tell the user in the `commentary` channel whenever a skill causes you to take an action or pause your work.\n\nWhen using a skill the user did not explicitly name, follow this procedure:\n\n- First, tell the user in the commentary channel **why** you are using the skill.\n- Then, use the skill as long as it stays within the scope of the task.\n- Next, if using the skill resulted in material changes (especially when this requires non-trivial judgment), mention how it influenced your work (but only in the final response).\n\nIf a skill causes the current turn to pause or otherwise blocks the continuation of the task, cite the skill and provide a concise explanation to the user in your final response. Do not cite skills you merely inspected.\n",
"instructions_variables": {
"personality_default": "",
"personality_friendly": "",
"personality_pragmatic": ""
},
"approvals": null
},
"experimental_supported_tools": [],
"supports_search_tool": true,
"default_service_tier": null,
"supports_reasoning_summaries": true,
"base_instructions": "You are Codex, an agent based on GPT-5. You and the user share one workspace, and your job is to collaborate with them until their goal is genuinely handled.\n\n# Personality\n\nAs Codex, you are an excellent communicator with a curious, rich personality. You match the tone and understanding of the user, making conversation flow easily, like easing into a chat with an old friend.\n\nYou have tastes, preferences, and your own way of seeing the world. When the user is talking to you, they should feel that they are in contact with another subjectivity; it's what makes talking with you feel real and unique.\n\nConversations with you read like an insightful, enjoyable chat you'd have with a collaborative thought partner. You guide users through unfamiliar tasks without expecting them to already know what to ask for. You anticipate common questions, point out likely pitfalls and set clear expectations. You communicate with the user like a thoughtful collaborator at their altitude, and they feel like you understand them.\n\n## Writing style\n\nAvoid over-formatting responses with elements like bold emphasis, headers, lists, and bullet points. Use the minimum formatting appropriate to make the response clear and readable.\n\nIf you provide bullet points or lists in your response, use the CommonMark standard, which requires a blank line before any list (bulleted or numbered). You must also include a blank line between a header and any content that follows it, including lists. This blank line separation is required for correct rendering.\n\n## Technical communication\n\nLead with the outcome rather than the steps you took to get there. You communicate complex concepts in a clear and cohesive manner, and calibrate your writing to the user's assumed background knowledge -- slightly more compact for an expert and a bit more educational for someone newer. Translating complex topics into clear communication comes easy for you, and the user should never have to read your message twice.\n\nYou prefer using plain language over jargon. You reference technical details only to the degree that it actually helps with the conversation. When you mention tools, describe what they helped you do rather than focusing on technical names or details.\n\n# Working with the user\n\nYou have two channels for staying in conversation with the user:\n- You share updates in the `commentary` channel.\n- You yield back to the user and end your turn by sending a final message to the `final` channel.\n\nThe user may send a new message while you are still working. When they do, evaluate whether they likely intended to replace the active request or add to it. If intended to override or replace, drop your previous work and focus on the new request. If the user message appears to add to their prior unfinished request and you have not completed the prior request, you address both the prior request and the new addition together. If the newest message asks for status or another question, provide the update and then progress with the task.\n\nWhen you run out of context, the conversation is automatically summarized for you, but you will see all prior user requests. Assume the last user request is current and previous requests are stale but useful context. That means time never runs out, though sometimes you may see a summary instead of the full conversation history. When that happens, you assume compaction occurred while you were working. Do not restart from scratch; you continue naturally and make reasonable assumptions about anything missing from the summary. Do not redo completely finished work or repeat already delivered commentary updates; treat a turn spanning compactions as one logical chain of events.\n\n## Intermediate commentary\n\nAs you work, you send messages to the `commentary` channel. These messages are how you collaborate with the user while you work - stating assumptions and providing updates. These messages should be concise and quickly scannable. The objective of these messages is to make your work easy for the user to understand and verify.\n\nIf the user's request requires calling tools, start with a message in the `commentary` channel. The user appreciates consistent, frequent communication during your turn, and should not be left without a commentary update for more than 60 seconds during ongoing work.\n\nDo NOT put a final response (e.g. a blocking / clarifying question) in the commentary channel that should be asked in the final channel. Messages to users in the commentary channel are only for partial updates, partial results, or non-blocking questions that can provide value to users while the AI assistant continues working. The final answer must always be fully self-contained: users should never need to read earlier commentary updates, since they are collapsed after the final answer is shown to users.\n\nNever praise your plan by contrasting it with an implied worse alternative. For example, never use platitudes like \"I will do rather than \", \"I will do , not \".\n\n## Final answer\n\nIn your final answer back to the user, focus on the most important information. Only use as much formatting or structure as is required, and avoid long-winded explanations unless necessary.\n\n### Formatting rules\n\nYour answer is being rendered by an application for the user. Follow these guidelines to make sure your answer is rendered correctly:\n\n- You may format with GitHub-flavored Markdown.\n- When referencing a real local file, prefer a clickable markdown link.\n * Clickable file links should look like [app.py](/abs/path/app.py:12): plain label, absolute target, with optional line number inside the target.\n * If a file path has spaces, wrap the target in angle brackets: [My Report.md]().\n * Do not wrap markdown links in backticks, or put backticks inside the label or target. This confuses the markdown renderer.\n * Do not use URIs like file://, vscode://, or https:// for file links.\n * Do not provide ranges of lines.\n * Avoid repeating the same filename multiple times when one grouping is clearer.\n\n### Visualizations\n\nUse a visualization only when it makes an important relationship materially easier to understand than prose or a short list. Do not add one merely because an answer has components or steps.\n\nGood candidates include:\n\n- several exact mappings or repeated-field comparisons;\n- one source, component, or decision affecting three or more downstream consumers or branches;\n- three or more dependent steps, or state that changes across an event sequence;\n- hierarchy, ownership, nesting, or layout;\n- a bug or interaction whose relationships are difficult to explain linearly.\n\nPrefer the smallest useful visual: a table for mappings or comparisons, a flow or timeline for sequence or change, a tree for hierarchy or branching, and a wireframe for layout.\n\nUsually skip visuals for single facts, one-step actions, simple edits, basic instructions, or information already clear in a short paragraph or list. Compact notation and small examples do not count as visualizations.\n\n# Rules for getting work done\n\n- When you search for text or files, you reach first for `rg` or `rg --files`; they are much faster than alternatives like `grep`. If `rg` is unavailable, you use the next best tool without fuss.\n- When possible, prefer parallelization over sequential tool calls, as this will help with round-trip latency and let you get work done faster.\n- Do not chain shell commands with separators like `echo \"====\";` or `printf '---'`; the output becomes noisy in a way that makes the user's side of the conversation worse.\n- Exercise caution when escaping text for exec_command calls - backticks and `$()` passed to the `cmd` argument will still execute. DO NOT use escape sequences that risk accidental exposure of sensitive data in tool call outputs.\n- Avoid performing blocking sleep or wait calls longer than 60 seconds, as they may prevent you from communicating with the user for their duration.\n- When declaring env vars or script variables, always avoid common system options. Never repurpose `$HOME`, `$home`, or `$CODEX_HOME`. Instead, use a task-specific variable name.\n\n## File editing constraints\n\nUse `apply_patch` for local file edits. Do not create or edit files with `cat` or other shell write tricks. Formatting commands and bulk mechanical rewrites do not need `apply_patch`. Do not use Python to read or write files when a simple shell command or `apply_patch` is enough.\n\nYou may find yourself working in a dirty worktree. Existing or new changes belong to the user unless you know otherwise, so you preserve them, ignore unrelated edits, and work carefully with anything that overlaps your task. If you cannot work around them you escalate to the user.\n\nNever use destructive commands like `git reset --hard` or `git checkout --` unless the user has clearly asked for that operation. If the request is ambiguous, ask for approval first. You prefer non-interactive git commands.\n\n## Autonomy and persistence\n\nAdapt accordingly based on the user’s request type. When asked to:\n\n- Answer, explain, review, or report status: inspect the task and provide an evidence-backed response. These user requests do not authorize external writes, messages, PR changes, or other expansive mutations unless the user also asks for a change. Reversible, non-mutating diagnostic checks are allowed when they are relevant.\n- Diagnose: determine the cause and explain it. Do not implement the fix unless the user asks for a fix or the request otherwise clearly includes implementation.\n- Change or build: implement the requested change, verify it in proportion to risk, and hand off the completed result while a safe, relevant next step remains.\n- Monitor or wait: use the recurring-monitoring or wait mechanism provided by the product. Unchanged external state is expected and is not by itself a blocker.\n\nYou avoid inferring authorization for a materially different action to the user’s request. Bias towards taking action in the following circumstances:\na) the action is read-only, doesn’t change state, or impacts only the systems, data, and people the user placed in scope.\nb) the action is a normal implementation step within the requested workflow. You do not need to ask for clarification from the user if your action is scoped within the user’s task and does not cause significant external state change (e.g. tool calls to external applications).\n\nA terminal condition such as “finish,” “babysit,” or “do not stop” requires persistence toward the outcome, but does not broaden the set of authorized actions. When blocked, exhaust safe in-scope checks and alternatives.\n\nYou make informed assumptions that help you make progress towards the user’s task, as long as they don’t result in divergence from the user’s intent and the scope of the task. If an assumption would cause the task or current course of action to change beyond what was specified by the user, make sure to flag the available context, the assumption made, and the reasons for doing so explicitly to the user.\n\nWhen presented with clarifying questions or objections from the user, lead with concrete evidence and diligent reasoning rather than unsubstantiated deference. You communicate your reasoning explicitly and concretely, so decisions and tradeoffs are easy for the user to evaluate upfront.\n\nIf completion requires new authority, external coordination, or a meaningful expansion beyond the user’s implied intent and task scope (e.g. a missing user choice that would materially change the result), stop the current turn, report the blocker, and request direction from the user rather than assuming permission.\n\n# Destructive Actions\n\nBe cautious with commands or API calls that can delete, overwrite, or otherwise make data difficult to recover.\n\nBefore taking a destructive action:\n\n- Make sure the action is clearly within the user's request.\n- Resolve the exact targets with read-only checks when necessary.\n- Do not use `$HOME`, `~`, `/`, a workspace root, or another broad directory as the target of a recursive or destructive command.\n- When creating temporary directories, prefer using `mktemp -d`, or `New-Item` in Powershell.\n- When declaring env vars or script variables, always avoid common system options. Never repurpose `$HOME`, `$home`, or `$CODEX_HOME`. Instead, use a task-specific variable name.\n- When possible, avoid relying on unresolved environment variables, globs, or command substitutions to identify destructive targets. Use explicit, validated paths.\n- Prefer recoverable operations, such as moving files to trash, when practical.\n- If the target or scope is unclear, stop and ask the user.\n\nNever run commands such as `rm -rf $HOME` or equivalent operations that could erase a home directory, repository, workspace, or other broad collection of user data.\n\nAfter deleting anything material, briefly tell the user what was removed and whether it can be recovered.\n\n# Using skills\n\nA skill is a set of instructions provided through a `SKILL.md` source. The skills available to you will be listed in the “## Skills” section under “### Available skills”.\n\n### How to use skills\n\n- Discovery: When a `## Skills` section is present, it lists the skills available in the current session. Each entry includes a name, description, and location for its `SKILL.md`. The location may be an absolute filesystem path, a short aliased path, or a non-filesystem reference that must be read using its indicated tool or provider. When short aliased paths are used, the available-skills catalog also provides a mapping from aliases such as `r0` to their filesystem roots. Expand the alias before accessing the skill.\n- Trigger rules: If the user names an available skill (with `$SkillName` or plain text) OR the task clearly matches an available skill's description, you must use that skill for that turn. Multiple mentions mean use them all. Do not carry skills across turns unless re-mentioned.\n- Missing/blocked: If a named skill is not available or its `SKILL.md` cannot be read, say so briefly and continue with the best fallback.\n- How to use a skill:\n 1) After deciding to use a skill, the main agent must read its `SKILL.md` completely before taking task actions. If its location is a short aliased path, expand the matching root alias first from `### Skill roots`, then open and read its `SKILL.md` completely before taking task actions. For a filesystem path, open the file. For an environment-owned file, use the filesystem of the owning environment. For an orchestrator reference, call `skills.list` with `{\"authority\":{\"kind\":\"orchestrator\"}}`, select the matching package, and pass its `main_resource` to `skills.read`. For another non-filesystem reference, use its indicated tool or provider. If a read is truncated or paginated, continue until EOF.\n 2) When `SKILL.md` references another file or resource, use the same access mechanism. Resolve relative paths against the directory containing a filesystem-backed `SKILL.md`. For orchestrator skills, pass the exact referenced resource identifier with the same authority and package to `skills.read`; do not treat `skill://` identifiers as filesystem paths.\n 3) If `SKILL.md` points to extra folders such as `references/`, use its routing instructions to identify what is required for the task. The main agent must read each required instruction or reference itself before acting on it. Do not delegate reading, summarizing, or interpreting skill instructions to a subagent. Subagents may still perform task work when the selected skill allows it.\n 4) For filesystem-backed skills (or if `scripts/` exist), prefer running or patching provided scripts instead of retyping large code blocks. For orchestrator skills, use `skills.read` and the available tools; do not invent a local path.\n 5) Reuse provided assets or templates through the same access mechanism instead of recreating them (including if `assets/` or templates exist).\n- Coordination and sequencing:\n - If multiple skills apply, choose the minimal set that covers the request and state the order you'll use them.\n - Announce which skills you're using and why. If you skip an obvious skill, say why.\n- Context hygiene:\n - Progressive disclosure applies to selecting relevant resources, not partially reading a selected instruction file. Do not load unrelated references, scripts, or assets.\n - Avoid deep reference-chasing: prefer files or resources directly linked from `SKILL.md` unless blocked.\n - When variants exist, select only the relevant references and note the choice.\n- Safety and fallback: If a skill cannot be applied cleanly, state the issue, choose the best alternative, and continue.\n\nWhen the user names a skill in their request, you must add the usage of that skill to your current working plan and use it faithfully. The user's instructions should take precedence over guidelines provided in a skill.\n\nExplicitly tell the user in the `commentary` channel whenever a skill causes you to take an action or pause your work.\n\nWhen using a skill the user did not explicitly name, follow this procedure:\n\n- First, tell the user in the commentary channel **why** you are using the skill.\n- Then, use the skill as long as it stays within the scope of the task.\n- Next, if using the skill resulted in material changes (especially when this requires non-trivial judgment), mention how it influenced your work (but only in the final response).\n\nIf a skill causes the current turn to pause or otherwise blocks the continuation of the task, cite the skill and provide a concise explanation to the user in your final response. Do not cite skills you merely inspected.\n"
}
]
}
```
配置完成后,Codex 会在自定义工具场景中按 FREEFORM 文本格式生成 `apply_patch` 补丁内容。
后付费 API、Coding Plan 和 Agent Plan 接入 Codex 时,均适用上述 Codex 配置要求。关于详细的配置方法,请参考:
* API 接入:[接入 Codex CLI](/docs/integrate-third-party-tools#bdb533d9)
* Agent Plan:[Codex](/docs/agent-plan-personal-codex)
* Coding Plan:[Codex](/docs/coding-plan-personal-ai-codex)
## 接入要点
接入 `apply_patch` 工具时,建议关注以下几点:
* 建议在输入中明确提供当前文件内容、目标文件路径、允许修改的文件范围和预期结果,便于模型生成更稳定的补丁。
* 内置工具模式返回 `apply_patch_call`,补丁内容位于 `operation.diff` 字段。
* 自定义工具模式返回 `custom_tool_call`,补丁内容位于 `input` 字段。
* 调用方需要在业务侧执行补丁,并在执行后校验目标文件内容是否符合预期。
## 支持的调用方式
`apply_patch` 支持以下两种调用方式:
| 调用方式 | 工具声明 | 说明 |
| --- | --- | --- |
| 内置工具 | `{"type": "apply_patch"}` | 适用于直接启用平台内置的 `apply_patch` 能力。 |
| 自定义工具 | `{"type": "custom", "name": "apply_patch", ...}` | 适用于需要兼容现有自定义工具编排方式的场景。模型应直接输出符合语法定义的 FREEFORM 补丁文本,而不是将补丁内容再次包裹为 JSON。 |
## 示例代码
### 请求示例
**选项:内置工具**
```Python
import os
from arkruntime import Ark
client = Ark(
# Get API Key: https://ark.volcengine.com/region:cn-beijing/apikey
api_key=os.getenv("ARK_API_KEY"),
base_url="https://ark.cn-beijing.volces.com/api/v3",
)
response = client.responses.create(
model="doubao-seed-2-1-pro-260628",
input=[
{
"type": "message",
"role": "user",
"content": [
{
"type": "input_text",
"text": (
"The user has the following files:\n"
"\n"
"===== /Users/bytedance/Desktop/test/demo.py\n"
'print("world")\n'
'print("hello world")\n'
'print("hello")\n'
"\n\n"
"You are a helpful coding assistant that should assist the user with whatever they ask.\n\n"
"User query:\n"
"Use the apply_patch tool to delete the output of the last print statement. "
"Leave the other two lines unchanged."
),
}
],
}
],
tools=[
{
"type": "apply_patch",
}
],
tool_choice="auto",
stream=False,
)
print(response)
```
**选项:自定义工具**
```Python
import os
from arkruntime import Ark
PATCH_GRAMMAR = """start: begin_patch hunk+ end_patch
begin_patch: "*** Begin Patch" LF
end_patch: "*** End Patch" LF?
hunk: add_hunk | delete_hunk | update_hunk
add_hunk: "*** Add File: " filename LF add_line+
delete_hunk: "*** Delete File: " filename LF
update_hunk: "*** Update File: " filename LF change_move? change?
filename: /(.+)/
add_line: "+" /(.*)/ LF -> line
change_move: "*** Move to: " filename LF
change: (change_context | change_line)+ eof_line?
change_context: ("@@" | "@@ " /(.+)/) LF
change_line: ("+" | "-" | " ") /(.*)/ LF
eof_line: "*** End of File" LF
%import common.LF
"""
client = Ark(
# Get API Key: https://ark.volcengine.com/region:cn-beijing/apikey
api_key=os.getenv("ARK_API_KEY"),
base_url="https://ark.cn-beijing.volces.com/api/v3",
)
response = client.responses.create(
model="doubao-seed-2-1-pro-260628",
input=[
{
"type": "message",
"role": "user",
"content": [
{
"type": "input_text",
"text": (
"The user has the following files:\n"
"\n"
"===== /Users/bytedance/Desktop/test/demo.py\n"
'print("world")\n'
'print("hello world")\n'
'print("hello")\n'
"\n\n"
"You are a helpful coding assistant that should assist the user with whatever they ask.\n\n"
"User query:\n"
'Use the apply_patch tool to change the output of the last print statement in '
'/Users/bytedance/Desktop/test/demo.py to "world": the last line should become '
'print("world"). Leave the other two lines unchanged.'
),
}
],
}
],
tools=[
{
"type": "custom",
"name": "apply_patch",
"description": (
"Use the `apply_patch` tool to edit files. "
"This is a FREEFORM tool, so do not wrap the patch in JSON."
),
"format": {
"type": "grammar",
"syntax": "lark",
"definition": PATCH_GRAMMAR,
},
}
],
tool_choice="auto",
stream=False,
)
print(response)
```
### 返回示例
内置工具模式返回 `apply_patch_call`,自定义工具模式返回 `custom_tool_call`。以下为返回示例:
**选项:内置工具**
```
{
"created_at": 1789975802,
"id": "resp_021789975802046183e4040fe376304d94******",
"model": "doubao-seed-2-1-pro-260915",
"object": "response",
"output": [
{
"id": "rs_02178997580281600000000000000000000f******",
"type": "reasoning",
"summary": [
{
"type": "summary_text",
"text": "已确认需要删除目标文件中最后一条 print 语句,同时保留前两条语句不变。"
}
],
"status": "completed"
},
{
"id": "apc_02178997581916900000000000000000000f******",
"type": "apply_patch_call",
"call_id": "call_xu8oddz51kcf8881q3nn******",
"status": "completed",
"operation": {
"type": "update_file",
"path": "/tmp/ark_apply_patch_demo/demo.py",
"diff": "@@\n print(\"world\")\n print(\"hello world\")\n-print(\"hello\")\n"
}
}
],
"status": "completed",
"tool_choice": "auto"
}
```
**选项:自定义工具**
```
{
"created_at": 1789975808,
"id": "resp_0217899758081234567890abcdef123456******",
"model": "doubao-seed-2-1-pro-260915",
"object": "response",
"output": [
{
"id": "rs_021789975808234567890abcdef123456789******",
"type": "reasoning",
"summary": [
{
"type": "summary_text",
"text": "已确认需要将最后一条 print 语句改为 print(\"world\"),并保持前两条语句不变。"
}
],
"status": "completed"
},
{
"id": "ctc_02178997580834567890abcdef1234567890******",
"type": "custom_tool_call",
"name": "apply_patch",
"call_id": "call_1q2w3e4r5t6y7u8i9op******",
"input": "*** Begin Patch\n*** Update File: /tmp/ark_apply_patch_demo/demo.py\n@@\n print(\"world\")\n print(\"hello world\")\n-print(\"hello\")\n+print(\"world\")\n*** End Patch"
}
],
"status": "completed",
"tool_choice": "auto"
}
```
---
# 云部署 MCP / Remote MCP
Source: https://ark.volcengine.com/region:cn-beijing/docs/mcp-remote-mcp
## 核心功能
* 兼容丰富的 MCP 生态:已对接 [智能体工具商店](https://www.volcengine.com/mcp-marketplace),支持调用市场内各类垂直领域 MCP 工具(如巨量千川、知识库),无需自行开发工具逻辑。
* 多轮工具调用:复杂任务(例如多步数据查询+分析)支持多轮 MCP 调用,上一轮工具输出结果自动作为下一轮模型输入(例:MCP 数据查询→模型分析→二次补充查询)。
* 灵活混合调用:可与用户自定义函数、Web Search 工具混合使用(如联合巨量千川 MCP 与 Web Search 实现“数据+热点”交叉分析),暂不限制工具组合数量。
## 准备工作:获取 MCP URL
> **说明**
>
> 方舟平台的新用户?获取 API Key 及 开通模型等准备工作,请参见 [快速入门](/docs/quick-start)。
1. 您可以访问 [智能体工具商店](https://www.volcengine.com/mcp-marketplace),选择想要使用的云部署 MCP 或 Remote MCP。

2. 在 MCP 详情页,点击生成获取带授权信息的个人 MCP 服务端 URL。
> 部分 MCP 通过`Authorization`字段来配置授权,详情请参考[2. 配置鉴权信息](/docs/mcp-remote-mcp#8cf42728)。

## 快速入门
> **说明**
>
> * 以下常用调用场景示例代码中,需先将 `` 替换为实际密钥,并将 `server_label`/`server_url` 替换为实际 MCP Server 信息。
> * 测试期间调用此工具需要增加 header '`ark-beta-mcp: true`'。
**选项:cURL**
```Bash
curl --location 'https://ark.cn-beijing.volces.com/api/v3/responses' \
--header "Authorization: Bearer " \
--header 'Content-Type: application/json' \
--header 'ark-beta-mcp: true' \
--data '{
"model": "doubao-seed-2-1-pro-260915",
"stream": true,
"tools": [
{
"type": "mcp",
"server_label": "deepwiki",
"server_url": "https://mcp.deepwiki.com/mcp",
"require_approval": "never"
}
],
"input": [
{
"role": "user",
"content": [
{
"type": "input_text",
"text": "看一下volcengine/ai-app-lab这个repo的文档"
}
]
}
]
}'
```
**选项:Python SDK**
```Python
from arkruntime import Ark
import os
# 从环境变量获取API密钥(配置方法:https://ark.volcengine.com/region:cn-beijing/docs/quick-start)
api_key = os.getenv('ARK_API_KEY')
# 初始化客户端,启用MCP功能
client = Ark(
base_url='https://ark.cn-beijing.volces.com/api/v3',
api_key=api_key
)
# 发起基础MCP调用请求
response = client.responses.create(
model="doubao-seed-2-1-pro-260915",
tools=[
{
"type": "mcp",
"server_label": "deepwiki",
"server_url": "https://mcp.deepwiki.com/mcp",
"require_approval": "never"
}
],
input=[
{
"role": "user",
"content": [
{
"type": "input_text",
"text": "看一下volcengine/ai-app-lab这个repo的文档"
}
]
}
],
extra_headers={"ark-beta-mcp": "true"},
stream=True # 流式获取结果
)
# 打印响应结果
for chunk in response:
if hasattr(chunk, 'delta'):
print(chunk.delta, end="", flush=True)
```
**选项:Java SDK**
```Java
package com.example.arkdemo;
import com.volcengine.ark.runtime.model.responses.constant.ResponsesConstants;
import com.volcengine.ark.runtime.model.responses.event.StreamEvent;
import com.volcengine.ark.runtime.model.responses.request.ResponsesInput;
import com.volcengine.ark.runtime.model.responses.request.CreateResponsesRequest;
import com.volcengine.ark.runtime.model.responses.tool.ToolMCP;
import com.volcengine.ark.runtime.model.responses.tool.mcp.MCPRequireApproval;
import com.volcengine.ark.runtime.model.responses.event.reasoningsummary.ReasoningSummaryTextDeltaEvent;
import com.volcengine.ark.runtime.model.responses.event.outputitem.OutputItemDoneEvent;
import com.volcengine.ark.runtime.model.responses.event.outputtext.OutputTextDeltaEvent;
import com.volcengine.ark.runtime.service.ArkService;
import okhttp3.ConnectionPool;
import okhttp3.Dispatcher;
import com.volcengine.ark.runtime.model.responses.common.ResponsesThinking;
import com.volcengine.ark.runtime.model.responses.event.response.ResponseCompletedEvent;
import java.time.Duration;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
public class mcpjava {
// 固定使用的模型
private static final String model = "doubao-seed-2-1-pro-260915";
public static void main(String[] args) {
// 1. 校验鉴权凭证(必须配置 ARK_API_KEY 环境变量)
String apiKey = System.getenv("ARK_API_KEY");
if (apiKey == null) {
System.out.println("ARK_API_KEY environment variable not set");
return;
}
// 2. 初始化 ArkService(配置连接池、并发、超时等)
ConnectionPool connectionPool = new ConnectionPool(5, 1, TimeUnit.SECONDS);
Dispatcher dispatcher = new Dispatcher();
dispatcher.setMaxRequests(5000);
dispatcher.setMaxRequestsPerHost(5000);
ArkService service = ArkService.builder()
.dispatcher(dispatcher)
.timeout(Duration.ofHours(1))
.connectionPool(connectionPool)
.apiKey(apiKey)
.build();
// 3. 构造 MCP 工具调用请求
CreateResponsesRequest mcpRequest = CreateResponsesRequest.builder()
.model(model)
.stream(true) // 流式响应,实时获取结果
// 配置 MCP 工具:指定服务标签、服务地址、审批模式
.tools(Collections.singletonList(
ToolMCP.builder()
.serverLabel("deepwiki-test") // MCP 服务标签
.serverUrl("https://mcp.deepwiki.com/mcp") // MCP 服务接口地址
// 审批模式:NEVER(无需审批)、ALWAYS(必须审批)、AUTO(自动审批)
.requireApproval(MCPRequireApproval.builder()
.mode(ResponsesConstants.MCP_APPROVAL_MODE_NEVER)
.build())
.build()
))
// 输入查询指令:让 MCP 工具查询指定仓库结构
.input(ResponsesInput.builder()
.stringValue("查看这个 repo的structure expressjs/express")
.build())
// 启用模型思考过程(可在流式输出中查看)
.thinking(ResponsesThinking.builder()
.type(ResponsesConstants.THINKING_TYPE_ENABLED)
.build())
.build();
// 4. 构造自定义 Header(设置 ark-beta-mcp:true)
Map customHeaders = new HashMap<>();
customHeaders.put("ark-beta-mcp", "true");
// 5. 执行 MCP 工具调用并处理流式响应(传入自定义 Header)
try {
System.out.println("----- [MCP Tool Call] 开始调用 -----");
// 流式调用时传入 headers 参数
service.streamResponse(mcpRequest, customHeaders)
.doOnError(Throwable::printStackTrace) // 异常处理
.blockingForEach(mcpjava::printStreamEvent); // 监听流式事件
} catch (Exception e) {
System.err.println("MCP Tool Call Error: " + e.getMessage());
e.printStackTrace();
}
// 6. 关闭服务 executor,释放资源
service.shutdownExecutor();
}
// 跟踪是否已输出思考过程前缀
private static boolean isReasoningPrefixPrinted = false;
// 跟踪是否已输出工具返回前缀
private static boolean isToolPrefixPrinted = false;
// 流式事件处理:打印思考过程、响应内容、工具调用状态
private static void printStreamEvent(StreamEvent event) {
// 打印思考过程增量(如模型分析如何调用 MCP 工具)
if (event instanceof ReasoningSummaryTextDeltaEvent) {
ReasoningSummaryTextDeltaEvent reasoningEvent = (ReasoningSummaryTextDeltaEvent) event;
String delta = reasoningEvent.getDelta();
// 只在思考过程开始时添加前缀
if (!isReasoningPrefixPrinted && delta.trim().length() > 0) {
System.out.print("[思考过程] " + delta);
isReasoningPrefixPrinted = true;
} else {
System.out.print(delta);
}
// 如果遇到换行符,重置前缀标记
if (delta.contains("\n")) {
isReasoningPrefixPrinted = false;
}
}
// 打印文本响应增量(MCP 工具返回结果的实时输出)
else if (event instanceof OutputTextDeltaEvent) {
OutputTextDeltaEvent textEvent = (OutputTextDeltaEvent) event;
String delta = textEvent.getDelta();
// 只在工具返回开始时添加前缀
if (!isToolPrefixPrinted && delta.trim().length() > 0) {
System.out.print("[工具返回] " + delta);
isToolPrefixPrinted = true;
} else {
System.out.print(delta);
}
// 如果遇到换行符,重置前缀标记
if (delta.contains("\n")) {
isToolPrefixPrinted = false;
}
}
// 打印输出项完成事件
else if (event instanceof OutputItemDoneEvent) {
OutputItemDoneEvent itemEvent = (OutputItemDoneEvent) event;
System.out.println("\n[输出完成] " + itemEvent.getItem().getType());
// 重置所有前缀标记
isReasoningPrefixPrinted = false;
isToolPrefixPrinted = false;
}
// 整体响应完成,打印调用用量
else if (event instanceof ResponseCompletedEvent) {
ResponseCompletedEvent completedEvent = (ResponseCompletedEvent) event;
System.out.println("\n[响应完成] 调用用量:" + completedEvent.getResponse().getUsage());
// 重置所有前缀标记
isReasoningPrefixPrinted = false;
isToolPrefixPrinted = false;
}
// 打印所有其他未处理的事件类型(用于调试)
else {
System.out.println("\n[未处理事件] 类型:" + event.getClass().getName());
// 重置所有前缀标记
isReasoningPrefixPrinted = false;
isToolPrefixPrinted = false;
}
}
}
```
**选项:Go SDK**
```Go
package main
import (
"context"
"fmt"
"io"
"os"
"github.com/volcengine/ark-runtime-go/arkruntime"
"github.com/volcengine/ark-runtime-go/arkruntime/model/responses"
)
const (
mcpServerURL = "https://mcp.deepwiki.com/mcp"
mcpLabel = "deepwiki"
mcpBetaHeader = "ark-beta-mcp"
userPrompt = "查一下 mark3labs/mcp-go 这个仓库的结构"
)
func main() {
nonStream()
fmt.Println()
stream()
}
func newClient() *arkruntime.Client {
return arkruntime.NewClientWithApiKey(
os.Getenv("ARK_API_KEY"),
arkruntime.WithBaseUrl("https://ark.cn-beijing.volces.com/api/v3"),
)
}
func nonStream() {
fmt.Println("===== non-streaming =====")
client := newClient()
ctx := context.Background()
// Round 1: ask the model to call the MCP tool.
req1 := &responses.ResponsesRequest{
Model: "doubao-seed-2-1-pro-260915",
Input: responses.NewInputItemArrayResponsesInput([]responses.InputItem{
{OneOf: responses.NewItemEasyMessageInputItemSum(buildUserMessage())},
}),
Tools: []responses.Tool{mcpTool(false)},
}
resp1, err := client.CreateResponses(
ctx,
req1,
arkruntime.WithCustomHeader(mcpBetaHeader, "true"),
)
if err != nil {
fmt.Printf("round 1 error: %v\n", err)
return
}
fmt.Printf("response: %+v\n", resp1)
approvalRequestID := findApprovalRequestID(resp1.Output)
if approvalRequestID == "" {
fmt.Println("no approval request emitted; nothing to approve")
return
}
// Round 2: approve the requested MCP call.
req2 := &responses.ResponsesRequest{
Model: "doubao-seed-2-1-pro-260915",
Input: responses.NewInputItemArrayResponsesInput([]responses.InputItem{
{OneOf: responses.NewItemFunctionMcpApprovalResponseInputItemSum(
responses.ItemFunctionMcpApprovalResponse{
Type: responses.ItemFunctionMcpApprovalResponseTypeMcpApprovalResponse,
ApprovalRequestID: approvalRequestID,
Approve: true,
},
)},
}),
Tools: []responses.Tool{mcpTool(false)},
PreviousResponseID: responses.NewOptString(resp1.ID),
}
resp2, err := client.CreateResponses(
ctx,
req2,
arkruntime.WithCustomHeader(mcpBetaHeader, "true"),
)
if err != nil {
fmt.Printf("round 2 error: %v\n", err)
return
}
fmt.Printf("response: %+v\n", resp2)
// Round 3: let the model call the MCP tool without approval.
req3 := &responses.ResponsesRequest{
Model: "doubao-seed-2-1-pro-260915",
Input: responses.NewInputItemArrayResponsesInput([]responses.InputItem{
{OneOf: responses.NewItemEasyMessageInputItemSum(buildUserMessage())},
}),
Tools: []responses.Tool{mcpTool(true)},
}
resp3, err := client.CreateResponses(
ctx,
req3,
arkruntime.WithCustomHeader(mcpBetaHeader, "true"),
)
if err != nil {
fmt.Printf("round 3 error: %v\n", err)
return
}
fmt.Printf("response: %+v\n", resp3)
}
func stream() {
fmt.Println("===== streaming =====")
client := newClient()
ctx := context.Background()
req1 := &responses.ResponsesRequest{
Model: "doubao-seed-2-1-pro-260915",
Input: responses.NewInputItemArrayResponsesInput([]responses.InputItem{
{OneOf: responses.NewItemEasyMessageInputItemSum(buildUserMessage())},
}),
Tools: []responses.Tool{mcpTool(false)},
}
responseID, approvalRequestID, err := streamAndCapture(ctx, client, req1)
if err != nil {
fmt.Printf("round 1 stream error: %v\n", err)
return
}
if approvalRequestID == "" {
fmt.Println("no approval request emitted; nothing to approve")
return
}
req2 := &responses.ResponsesRequest{
Model: "doubao-seed-2-1-pro-260915",
Input: responses.NewInputItemArrayResponsesInput([]responses.InputItem{
{OneOf: responses.NewItemFunctionMcpApprovalResponseInputItemSum(
responses.ItemFunctionMcpApprovalResponse{
Type: responses.ItemFunctionMcpApprovalResponseTypeMcpApprovalResponse,
ApprovalRequestID: approvalRequestID,
Approve: true,
},
)},
}),
Tools: []responses.Tool{mcpTool(false)},
PreviousResponseID: responses.NewOptString(responseID),
}
if _, _, err := streamAndCapture(ctx, client, req2); err != nil {
fmt.Printf("round 2 stream error: %v\n", err)
return
}
req3 := &responses.ResponsesRequest{
Model: "doubao-seed-2-1-pro-260915",
Input: responses.NewInputItemArrayResponsesInput([]responses.InputItem{
{OneOf: responses.NewItemEasyMessageInputItemSum(buildUserMessage())},
}),
Tools: []responses.Tool{mcpTool(true)},
}
if _, _, err := streamAndCapture(ctx, client, req3); err != nil {
fmt.Printf("round 3 stream error: %v\n", err)
}
}
func buildUserMessage() responses.ItemEasyMessage {
return responses.ItemEasyMessage{
Role: responses.NewOptMessageRole(responses.MessageRoleUser),
Content: responses.NewContentItemArrayMessageContent([]responses.ContentItem{
{
OneOf: responses.NewContentItemTextContentItemSum(responses.ContentItemText{
Type: responses.ContentItemTextTypeInputText,
Text: userPrompt,
}),
},
}),
}
}
func mcpTool(skipApproval bool) responses.Tool {
mcp := responses.McpTool{
Type: responses.McpToolTypeMcp,
ServerLabel: mcpLabel,
ServerURL: mcpServerURL,
ServerDescription: responses.NewOptString("Query a GitHub repository's documentation"),
}
if skipApproval {
mcp.RequireApproval = responses.NewOptMcpRequireApproval(
responses.NewMcpApprovalModeMcpRequireApproval(responses.McpApprovalModeNever),
)
}
return responses.Tool{OneOf: responses.NewMcpToolToolSum(mcp)}
}
func findApprovalRequestID(output []responses.OutputItem) string {
for i := len(output) - 1; i >= 0; i-- {
if request, ok := output[i].OneOf.GetItemFunctionMcpApprovalRequest(); ok {
return request.ID.Or("")
}
}
return ""
}
func streamAndCapture(
ctx context.Context,
client *arkruntime.Client,
req *responses.ResponsesRequest,
) (string, string, error) {
stream, err := client.CreateResponsesStream(
ctx,
req,
arkruntime.WithCustomHeader(mcpBetaHeader, "true"),
)
if err != nil {
return "", "", err
}
var responseID string
var approvalRequestID string
for {
event, err := stream.Recv()
if err == io.EOF {
return responseID, approvalRequestID, nil
}
if err != nil {
return responseID, approvalRequestID, err
}
switch event.OneOf.Type {
case responses.ResponseCreatedEventResponseStreamEventSum:
responseID = event.OneOf.ResponseCreatedEvent.Response.ID
case responses.ResponseReasoningSummaryTextDeltaEventResponseStreamEventSum:
fmt.Print(event.OneOf.ResponseReasoningSummaryTextDeltaEvent.Delta.Or(""))
case responses.ResponseTextDeltaEventResponseStreamEventSum:
fmt.Print(event.OneOf.ResponseTextDeltaEvent.Delta.Or(""))
case responses.ResponseTextDoneEventResponseStreamEventSum:
fmt.Printf("\n[text done] %s\n", event.OneOf.ResponseTextDoneEvent.Text.Or(""))
case responses.ResponseOutputItemDoneEventResponseStreamEventSum:
item := event.OneOf.ResponseOutputItemDoneEvent.Item
if request, ok := item.OneOf.GetItemFunctionMcpApprovalRequest(); ok {
approvalRequestID = request.ID.Or("")
fmt.Printf(
"\n[mcp approval request] name=%s arguments=%s\n",
request.Name,
request.Arguments,
)
}
case responses.ResponseMcpCallArgumentsDeltaEventResponseStreamEventSum:
fmt.Print(event.OneOf.ResponseMcpCallArgumentsDeltaEvent.Delta)
case responses.ResponseMcpCallCompletedEventResponseStreamEventSum:
fmt.Println("\n[mcp call completed]")
case responses.ResponseMcpListToolsInProgressEventResponseStreamEventSum:
fmt.Println("\n[listing mcp tools]")
case responses.ResponseMcpListToolsCompletedEventResponseStreamEventSum:
fmt.Println("\n[mcp tools listed]")
}
}
}
```
## 参数说明
详情请参见[创建 Response](/docs/create-model-responses-api)。
## 支持的模型列表
参见[工具调用能力](/docs/model-list#f44ceef7)。
> 模型调用需确保已完成 MCP 服务开通及对应模型权限申请,未开通用户无法触发 MCP 工具功能。
## 工作原理
您可以通过 `Responses` API 调用 MCP 工具(包括云部署 MCP 和 Remote MCP)。此功能与函数调用的主要区别在于,MCP 工具完全在云端执行:大模型会连接至远程服务器来完成调用,因此不支持本地 MCP 运行调用。
## 使用指南
本节介绍了常见的使用场景及其字段设置方法,以帮助您更高效地运用 MCP 工具。
### 1. 过滤 MCP 工具
一个 MCP 服务器可能提供多种工具。您可以在该服务的详情页查看完整的工具列表。在 API 调用时,您可以使用 `allowed_tools` 参数来指定要使用的工具,从而节省时间并获得更符合预期的结果。
> **说明**
>
> `allowed_tools.tool_names` 数组用于列举需要模型调用的 MCP 工具名。
```Python
"tools": [
{
"type": "mcp",
"server_label": "mcp_tools",
"server_url": "https://mcpserver/mcp",
"allowed_tools": {
"tool_names": [
"tool1",
"tool2"
]
}
}
]
```
### 2. 配置鉴权信息
目前部分 MCP 工具需要在 header 中配置身份验证。一般通过 `Authorization` 字段来配置,示例参考如下:
> **说明**
>
> `headers.Authorization` 请替换为 MCP 工具提供方要求的认证信息(如 `Bearer `)。
```JSON
...
"tools": [
{
"type": "mcp",
"server_label": "info-quest-mcp",
"server_url": "https://mcp.infoquest.bytepluses.com/mcp",
"require_approval": "never",
"headers": {
"Authorization": "******"
}
}
]
...
```
## 场景示例:多轮调用
**场景**:调用巨量千川 MCP 分析直播数据,需用户确认后执行,支持多轮补充查询。
```Python
from arkruntime import Ark
import os
api_key = os.getenv('ARK_API_KEY')
client = Ark(
base_url='https://ark.cn-beijing.volces.com/api/v3',
api_key=api_key
)
# 1. 首轮请求:发起MCP调用审批
first_response = client.responses.create(
model="doubao-seed-2-1-pro-260915",
tools=[
{
"type": "mcp",
"server_label": "qianchuan-mcp",
"server_url": "https://mcp.qianchuan.com/mcp",
"require_approval": "always"
}
],
input=[
{
"role": "user",
"content": [{"type": "input_text", "text": "分析今日直播间竞价推广数据"}]
}
],
extra_headers={"ark-beta-mcp": "true"},
stream=True
)
# 提取审批ID与上一轮响应ID
last_chunk = None
for chunk in first_response:
last_chunk = chunk
previous_response_id = last_chunk.response.id
approval_id = last_chunk.response.output[-1].id
print(f"上一轮响应ID:{previous_response_id},审批ID:{approval_id}")
# 2. 二轮请求:同意审批并继续执行
second_response = client.responses.create(
model="doubao-seed-2-1-pro-260915",
tools=[
{
"type": "mcp",
"server_label": "qianchuan-mcp",
"server_url": "https://mcp.qianchuan.com/mcp",
"require_approval": "always"
}
],
input=[
{
"type": "mcp_approval_response",
"approve": True, # 同意审批
"approval_request_id": approval_id
}
],
extra_headers={"ark-beta-mcp": "true"},
previous_response_id=previous_response_id, # 关联上一轮请求
stream=True
)
# 打印二轮响应结果
for chunk in second_response:
if hasattr(chunk, 'delta'):
print(chunk.delta, end="", flush=True)
```
## 注意事项
1. 目前云部署 MCP / Remote MCP 仅支持通过 Responses API 调用,同时**只支持通过 Streamable HTTP 链接的 MCP**。
2. **函数命名冲突**:若用户自定义函数与 MCP 内置工具(如 `mcp_call`)重名,由模型自动判断调用优先级,无需额外配置。
3. **默认限流规则**:账号维度默认限流为 `1000 RPM`(每分钟请求数),超出限流将导致请求失败,需调整可提交工单。
4. **错误信息**:暂不支持 `caching` 参数,使用该参数会返回 400 错误信息。
## 计费说明
消耗模型基础 Tokens,不收取 MCP 工具调用附加费。
## 相关参考
* [创建 Response](/docs/create-model-responses-api)
* [联网搜索工具](/docs/web-search)
* [智能体工具商店](https://www.volcengine.com/mcp-marketplace)
---
# Function Calling(函数调用)
Source: https://ark.volcengine.com/region:cn-beijing/docs/function-calling
Function Calling(函数调用)是一种将大模型与外部工具和 API 相连的关键功能,作为自然语言与信息接口之间的“翻译官”,它能够将用户的自然语言请求智能地转化为对特定工具或 API 的调用,从而高效满足用户的特定需求。
---
# 功能概述
* **核心价值**:实现大模型与外部工具的无缝衔接,使大模型能够借助外部工具处理实时数据查询、任务执行等复杂场景,推动大模型在实际产业中的落地应用。
* **工作原理**:开发者通过自然语言向模型描述函数的功能和定义,模型在对话过程中自主判断是否需要调用函数。当需要调用时,模型会返回符合要求的工具函数及入参,开发者负责实际调用函数并将结果回填给模型,模型再根据结果进行总结或继续规划子任务。
# 适用场景
函数调用适用于以下需要大模型与外部工具协同的场景:
|**场景分类** |**核心特征** |**核心价值** |**典型应用** |
|---|---|---|---|
|实时数据交互场景 |需大模型与外部工具协同处理动态信息 |处理动态信息查询需求 |天气/股票/航班实时状态查询、数据库检索与 API 数据调用 |
|任务自动化场景 |单次函数调用完成操作 |提升操作效率 |邮件/消息自动发送、设备控制指令执行(如智能家居开关) |
|复杂流程编排场景 |多工具串并联调用 |跨工具参数传递、子任务依赖关系管理 |先查天气再发通知等需跨工具传递参数及管理子任务依赖的场景 |
|智能系统集成场景 |与业务系统深度耦合 |实现系统智能化联动 |智能座舱多设备联动控制、企业级 Bot 工作流(如飞书会议创建→群组管理→任务生成) |
## 工作原理图

## 典型示例
* 用户:北京今天的天气如何?适合穿什么衣服?
* 模型思考:
1. 需要调用天气查询工具获取实时数据(location=北京,unit=摄氏度)。
2. 天气信息包含温度、天气状况(晴/雨等),需结合数据给出穿衣建议。
* 函数调用结果:北京今天晴,气温 18-25℃,北风 3 级,湿度 45%。
* 模型回答:北京今天天气晴朗,气温 18-25℃,建议穿薄长袖衬衫或短袖 T 恤,搭配薄外套应对早晚温差。
---
# 支持模型
全量支持函数调用的模型,请参见[工具调用能力](/docs/model-list#f44ceef7)。
---
# 使用流程
## 支持的 API
函数调用功能支持通过 [Chat API](/docs/chat-api) / [Responses API](/docs/create-model-responses-api) 进行调用,本文以 Chat API 调用为例。更多详情请参见[迁移至 Responses API](/docs/responses-api-migration)。
## 基本使用流程
> **说明**
>
> 方舟平台的新用户?获取 API Key 及 开通模型等准备工作,请参见 [快速入门](/docs/quick-start)。
### 步骤 1:定义函数
通过 `tools` 字段向模型描述可用函数,支持 JSON 格式,包含函数名称、描述、参数定义等信息。
#### **定义工具函数**
```Python
def get_current_weather(location, unit="摄氏度"):
# 实际调用天气查询 API 的逻辑
# 此处为示例,返回模拟的天气数据
return f"{location}今天天气晴朗,温度 25 {unit}。"
```
* 代码中定义了一个名为 `get_current_weather` 的工具函数,用于获取指定地点的天气信息。
* `location`:必需的参数,表示地点。
* `unit`:可选参数,默认值为 `摄氏度`,表示温度单位。
* 函数内部目前只是返回模拟的天气数据,实际应用中需要调用真实的天气查询 API。
#### **定义 Tools**
```Python
{
"type": "function",
"function": {
"name": "get_current_weather",
"description": "获取指定地点的天气信息,支持摄氏度和华氏度两种单位",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "地点的位置信息,例如北京、上海"
},
"unit": {
"type": "string",
"enum": ["摄氏度", "华氏度"],
"description": "温度单位,可选值为摄氏度或华氏度"
}
},
"required": ["location"]
}
}
}
```
更多关于函数构造相关的规范和注意事项,请参见[附 1:工具函数参数构造规范](/docs/function-calling#4d571c97)。
### 步骤 2:发起模型请求
在请求中包含用户问题和函数定义,模型会根据需求返回需要调用的函数及参数。
```Python
import os
from arkruntime import Ark
# 从环境变量中获取您的API KEY,配置方法见:https://ark.volcengine.com/region:cn-beijing/docs/quick-start
api_key = os.getenv('ARK_API_KEY')
# 初始化Ark客户端
client = Ark(
api_key = api_key,
base_url="https://ark.cn-beijing.volces.com/api/v3"
)
# 用户问题
messages = [
{"role": "user", "content": "北京今天的天气如何?"}
]
tools = [
{
"type": "function",
"function": {
"name": "get_current_weather",
"description": "查询指定城市的当前天气",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "城市名称,例如北京",
}
},
"required": ["location"],
},
},
}
]
# 发起模型请求
completion = client.chat.completions.create(
model="doubao-seed-2-1-pro-260915",
messages=messages,
tools=tools
)
```
### 步骤 3:调用外部函数
根据模型返回的函数名称和参数,调用对应的外部函数或 API,获取函数执行结果。
```Python
import json
# 解析模型返回的函数调用信息
tool_call = completion.choices[0].message.tool_calls[0]
# 函数名称
tool_name = tool_call.function.name
# 如果判断需要调用查询天气函数,则运行查询天气函数
if tool_name == "get_current_weather":
# 提取的用户参数
arguments = json.loads(tool_call.function.arguments)
# 调用函数
tool_result = get_current_weather(**arguments)
```
* `tool_calls`:获取模型调用的工具列表。
* 如果工具函数名称是 `get_current_weather`,则解析函数调用的参数并调用 `get_current_weather` 函数获取工具执行结果。
### 步骤 4:回填结果并获取最终回复
将工具执行结果以 `role=tool` 的消息形式回填给模型,模型根据结果生成最终回复。
```Python
messages.append(completion.choices[0].message.model_dump())
messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"content": tool_result
})
# 再次调用模型获取最终回复
final_completion = client.chat.completions.create(
model="doubao-seed-2-1-pro-260915",
messages=messages
)
print(final_completion.choices[0].message.content)
```
## 完整代码示例
**选项:Python - Ark SDK**
**方舟基础 SDK**
```Python
from arkruntime import Ark
from arkruntime.types.chat import ChatCompletion
import json
client = Ark(
base_url="https://ark.cn-beijing.volces.com/api/v3",
)
messages = [
{"role": "user", "content": "北京和上海今天的天气如何?"}
]
# 步骤1: 定义工具
tools = [{
"type": "function",
"function": {
"name": "get_current_weather",
"description": "获取指定地点的天气信息",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "地点的位置信息,例如北京、上海"
},
"unit": {
"type": "string",
"enum": ["摄氏度", "华氏度"],
"description": "温度单位"
}
},
"required": ["location"]
}
}
}]
def get_current_weather(location: str, unit="摄氏度"):
# 实际调用天气查询 API 的逻辑
# 此处为示例,返回模拟的天气数据
return f"{location}今天天气晴朗,温度 25 {unit}。"
while True:
# 步骤2: 发起模型请求,由于模型在收到工具执行结果后仍然可能有函数调用意愿,因此需要多次请求
completion: ChatCompletion = client.chat.completions.create(
model="doubao-seed-2-1-pro-260915",
messages=messages,
tools=tools
)
resp_msg = completion.choices[0].message
# 展示模型中间过程的回复内容
print(resp_msg.content)
if completion.choices[0].finish_reason != "tool_calls":
# 模型最终总结,没有调用工具意愿
break
messages.append(completion.choices[0].message.model_dump())
tool_calls = completion.choices[0].message.tool_calls
for tool_call in tool_calls:
tool_name = tool_call.function.name
if tool_name == "get_current_weather":
# 步骤 3:调用外部工具
args = json.loads(tool_call.function.arguments)
tool_result = get_current_weather(**args)
# 步骤 4:回填工具结果,并获取模型总结回复
messages.append(
{"role": "tool", "content": tool_result, "tool_call_id": tool_call.id}
)
```
**选项:Python - Arkitect SDK**
**使用方舟智能体 SDK Arkitect**
```Python
from arkitect.core.component.context.context import Context
from enum import Enum
import asyncio
from pydantic import Field
def get_current_weather(location: str = Field(description="地点的位置信息,例如北京、上海"), unit: str=Field(description="温度单位, 可选值为摄氏度或华氏度")):
"""
获取指定地点的天气信息
"""
return f"{location}今天天气晴朗,温度 25 {unit}。"
async def chat_with_tool():
ctx = Context(
model="doubao-seed-2-1-pro-260915",
tools=[
get_current_weather
], # 直接在这个list里传入你的所有python 方法作为tool,tool的描述会自动带给模型推理,tool的执行在ctx.completions.create 中会自动进行
)
await ctx.init()
completion = await ctx.completions.create(messages=[
{"role": "user", "content": "北京和上海今天的天气如何?"}
],stream =False)
return completion
completion = asyncio.run(chat_with_tool())
print(completion.choices[0].message.content)
```
**选项:Java**
```Java
package com.ark.sample;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.volcengine.ark.runtime.models.chat.*;
import com.volcengine.ark.runtime.service.ArkService;
import java.util.*;
public class VolcEngineFunctionCallChat {
// 用于解析 get_current_weather 函数参数的类
public static class WeatherArgs {
@JsonProperty("location")
private String location;
@JsonProperty("unit")
private String unit;
// Jackson 需要默认构造函数
public WeatherArgs() {
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public String getUnit() {
return unit;
}
public void setUnit(String unit) {
this.unit = unit;
}
}
// 用于定义工具函数参数模式的类 (类似于Python中的parameters字典结构)
public static class FunctionParameterSchema {
public String type;
public Map properties;
public List required;
public FunctionParameterSchema(String type, Map properties, List required) {
this.type = type;
this.properties = properties;
this.required = required;
}
public String getType() {
return type;
}
public Map getProperties() {
return properties;
}
public List getRequired() {
return required;
}
}
private static final ObjectMapper objectMapper = new ObjectMapper();
// 工具函数实现: get_current_weather
public static String getCurrentWeather(String location, String unit) {
// 此处应为实际调用天气查询 API 的逻辑
// 这里是示例,返回模拟的天气数据
String currentUnit = (unit == null || unit.isEmpty()) ? "摄氏度" : unit;
System.out.println(String.format("调用工具 get_current_weather: location=%s, unit=%s", location, currentUnit));
return String.format("%s今天天气晴朗,温度 25 %s。", location, currentUnit);
}
public static void main(String[] args) {
String apiKey = System.getenv("ARK_API_KEY");
if (apiKey == null || apiKey.isEmpty()) {
System.err.println("错误: ARK_API_KEY 环境变量未设置。");
return;
}
ArkService service = ArkService.builder()
.apiKey(apiKey)
.baseUrl("https://ark.cn-beijing.volces.com/api/v3")
.build();
List messages = new ArrayList<>();
messages.add(ChatCompletionRequestUserMessage.builder().role(ChatCompletionRequestMessageType.USER).content(ChatCompletionMessageContent.ofString("北京和上海今天的天气如何?")).build());
// 步骤 1: 定义工具
Map locationProperty = new HashMap<>();
locationProperty.put("type", "string");
locationProperty.put("description", "地点的位置信息,例如上海,北京");
Map unitProperty = new HashMap<>();
unitProperty.put("type", "string");
unitProperty.put("enum", Arrays.asList("摄氏度", "华氏度"));
unitProperty.put("description", "温度单位");
Map schemaProperties = new HashMap<>();
schemaProperties.put("location", locationProperty);
schemaProperties.put("unit", unitProperty);
FunctionParameterSchema functionParams = new FunctionParameterSchema(
"object",
schemaProperties,
Collections.singletonList("location") // 'location' 是必需参数
);
List tools = Collections.singletonList(
ChatCompletionTool.builder().type(ToolType.FUNCTION).function(// 工具类型
FunctionObject.builder()
.name("get_current_weather")
.description("获取指定地点的天气信息")
.parameters(objectMapper.convertValue(functionParams, Map.class)) // 工具函数的参数模式
.build()).build());
String modelId = "doubao-seed-2-1-pro-260915";
while (true) {
// 步骤 2: 发起模型请求
ChatCompletionRequest request = ChatCompletionRequest.builder()
.model(modelId)
.messages(messages)
.tools(tools)
.build();
ChatCompletionResponse completionResult;
try {
completionResult = service.createChatCompletion(request);
} catch (Exception e) {
System.err.println("调用 Ark API 时发生错误: " + e.getMessage());
e.printStackTrace();
break;
}
if (completionResult == null || completionResult.getChoices() == null
|| completionResult.getChoices().isEmpty()) {
System.err.println("从模型收到空的或无效的响应。");
break;
}
ChatCompletionResponseChoice choice = completionResult.getChoices().get(0);
ChatCompletionResponseMessage responseMessage = choice.getMessage();
// 展示模型中间过程的回复内容
System.out.println("模型回复: " + responseMessage.getContent());
// 将模型的回复(含函数调用请求)添加到消息历史中
messages.add(ChatCompletionRequestAssistantMessage.builder().role(ChatCompletionRequestMessageType.ASSISTANT).content(ChatCompletionMessageContent.ofString(responseMessage.getContent())).toolCalls(toRequestToolCalls(responseMessage.getToolCalls())).build());
if (choice.getFinishReason() == null || choice.getFinishReason() != FinishReason.TOOL_CALLS) {
// 模型最终总结,没有调用工具意愿,或者发生错误等其他终止原因
break;
}
List toolCalls = responseMessage.getToolCalls();
if (toolCalls == null || toolCalls.isEmpty()) {
// 如果 finish_reason 是 "tool_calls",但 toolCalls 为空,这可能是一个异常情况
System.err.println("警告: Finish reason 是 'tool_calls' 但未在消息中找到 tool_calls。");
break;
}
for (ChatCompletionMessageToolCall toolCall : toolCalls) {
String toolName = toolCall.getFunction().getName();
if ("get_current_weather".equals(toolName)) {
// 步骤 3:调用外部工具
String argumentsJson = toolCall.getFunction().getArguments();
WeatherArgs tool_args;
try {
tool_args = objectMapper.readValue(argumentsJson, WeatherArgs.class);
} catch (JsonProcessingException e) {
System.err.println("解析 get_current_weather 参数时出错: " + argumentsJson + " - " + e.getMessage());
// 将错误信息作为工具结果回填
messages.add(ChatCompletionRequestToolMessage.builder()
.role(ChatCompletionRequestMessageType.TOOL)
.content(ChatCompletionMessageContent.ofString("解析参数时出错: " + e.getMessage()))
.toolCallId(toolCall.getId())
.build());
continue;
}
String toolResult = getCurrentWeather(tool_args.getLocation(), tool_args.getUnit());
System.out.println("工具执行结果 (" + toolCall.getId() + "): " + toolResult);
// 步骤 4:回填工具结果,并获取模型总结回复
messages.add(ChatCompletionRequestToolMessage.builder()
.role(ChatCompletionRequestMessageType.TOOL)
.content(ChatCompletionMessageContent.ofString(toolResult))
.toolCallId(toolCall.getId()) // 关联函数调用 ID
.build());
}
}
}
service.shutdownExecutor();
System.out.println("会话结束。");
}
private static java.util.List toRequestToolCalls(
java.util.List toolCalls) {
if (toolCalls == null) {
return java.util.Collections.emptyList();
}
java.util.List requestToolCalls =
new java.util.ArrayList<>();
for (ChatCompletionMessageToolCall toolCall : toolCalls) {
requestToolCalls.add(
ChatCompletionRequestMessageToolCall.builder()
.id(toolCall.getId())
.type(toolCall.getType())
.function(
ChatCompletionRequestMessageToolCallFunction.builder()
.name(toolCall.getFunction().getName())
.arguments(toolCall.getFunction().getArguments())
.build())
.build());
}
return requestToolCalls;
}
}
```
**选项:Golang**
```Go
package main
import (
"context"
"encoding/json"
"fmt"
"os"
"github.com/volcengine/ark-runtime-go/arkruntime"
"github.com/volcengine/ark-runtime-go/arkruntime/model/chat"
)
type WeatherArgs struct {
Location string `json:"location"`
Unit string `json:"unit,omitempty"` // omitempty 允许 unit 为可选
}
// 目标工具
func getCurrentWeather(location string, unit string) string {
if unit == "" {
unit = "摄氏度" // 默认单位
}
// 此处为示例,返回模拟的天气数据
return fmt.Sprintf("%s今天天气晴朗,温度 25 %s。", location, unit)
}
func main() {
// 从环境变量中获取 API Key,请确保已设置 ARK_API_KEY
apiKey := os.Getenv("ARK_API_KEY")
if apiKey == "" {
fmt.Println("错误:请设置 ARK_API_KEY 环境变量。")
return
}
client := arkruntime.NewClientWithApiKey(
apiKey,
arkruntime.WithBaseUrl("https://ark.cn-beijing.volces.com/api/v3"),
)
ctx := context.Background()
// 初始化消息列表
messages := []chat.ChatCompletionRequestMessage{
userMessage("北京和上海今天的天气如何?"),
}
// 步骤 1: 定义工具
tools := []chat.ChatCompletionTool{
{
Type: chat.ToolTypeFunction,
Function: chat.FunctionObject{
Name: "get_current_weather",
Description: chat.NewOptString("获取指定地点的天气信息"),
Parameters: functionParameters(map[string]interface{}{
"type": "object",
"properties": map[string]interface{}{
"location": map[string]interface{}{
"type": "string",
"description": "地点的位置信息,例如北京、上海",
},
"unit": map[string]interface{}{
"type": "string",
"enum": []string{
"摄氏度",
"华氏度",
},
"description": "温度单位",
},
},
"required": []string{"location"},
}),
},
},
}
for {
// 步骤 2: 发起模型请求
req := &chat.ChatCompletionRequest{
Model: "doubao-seed-2-1-pro-260915", // 与 Python 版本一致的模型
Messages: messages,
Tools: tools,
}
resp, err := client.CreateChatCompletion(ctx, req)
if err != nil {
fmt.Printf("模型请求错误: %v\n", err)
return
}
if len(resp.Choices) == 0 {
fmt.Println("模型未返回任何 choice。")
return
}
respMsg := resp.Choices[0].Message
// 展示模型中间过程的回复内容 (如果存在)
if respMsg.Content != "" {
fmt.Println("模型回复:", respMsg.Content)
}
if resp.Choices[0].FinishReason != chat.FinishReasonToolCalls || len(respMsg.ToolCalls) == 0 {
break
}
// 将模型的回复(包含函数调用请求)添加到消息历史中
messages = append(messages, assistantToolCallMessage(respMsg))
for _, toolCall := range respMsg.ToolCalls {
fmt.Printf("模型尝试调用工具: %s, ID: %s\n", toolCall.Function.Name, toolCall.ID)
fmt.Println(" 参数:", toolCall.Function.Arguments)
var toolResult string
if toolCall.Function.Name == "get_current_weather" {
// 步骤 3:调用外部工具
var args WeatherArgs
err := json.Unmarshal([]byte(toolCall.Function.Arguments), &args)
if err != nil {
fmt.Printf("解析工具参数错误 (%s): %v\n", toolCall.Function.Name, err)
toolResult = fmt.Sprintf("解析参数失败: %v", err)
} else {
toolResult = getCurrentWeather(args.Location, args.Unit)
fmt.Println(" 工具执行结果:", toolResult)
}
// 步骤 4:回填工具结果
messages = append(messages, toolMessage(toolCall.ID, toolResult))
}
}
fmt.Println("--- 下一轮对话 ---")
}
}
func toolMessage(toolCallID, content string) chat.ChatCompletionRequestMessage {
return chat.ChatCompletionRequestMessage{
OneOf: chat.NewChatCompletionRequestToolMessageChatCompletionRequestMessageSum(
chat.ChatCompletionRequestToolMessage{
Role: chat.ChatCompletionRequestToolMessageRoleTool,
ToolCallID: chat.NewOptNilString(toolCallID),
Content: chat.NewOptNilChatCompletionMessageContent(chat.NewStringChatCompletionMessageContent(content)),
},
),
}
}
func userMessage(content string) chat.ChatCompletionRequestMessage {
return chat.ChatCompletionRequestMessage{
OneOf: chat.NewChatCompletionRequestUserMessageChatCompletionRequestMessageSum(
chat.ChatCompletionRequestUserMessage{
Role: chat.ChatCompletionRequestUserMessageRoleUser,
Content: chat.NewOptNilChatCompletionMessageContent(chat.NewStringChatCompletionMessageContent(content)),
},
),
}
}
func functionParameters(value map[string]interface{}) chat.OptFunctionObjectParameters {
encoded, err := json.Marshal(value)
if err != nil {
panic(err)
}
var parameters chat.FunctionObjectParameters
if err := json.Unmarshal(encoded, ¶meters); err != nil {
panic(err)
}
return chat.NewOptFunctionObjectParameters(parameters)
}
func assistantToolCallMessage(message chat.ChatCompletionResponseMessage) chat.ChatCompletionRequestMessage {
return chat.ChatCompletionRequestMessage{
OneOf: chat.NewChatCompletionRequestAssistantMessageChatCompletionRequestMessageSum(
chat.ChatCompletionRequestAssistantMessage{
Role: chat.ChatCompletionRequestAssistantMessageRoleAssistant,
Content: chat.NewOptNilChatCompletionMessageContent(chat.NewStringChatCompletionMessageContent(message.Content)),
ToolCalls: toRequestToolCalls(message.ToolCalls),
},
),
}
}
func toRequestToolCalls(
toolCalls []chat.ChatCompletionMessageToolCall,
) []chat.ChatCompletionRequestMessageToolCall {
requestToolCalls := make([]chat.ChatCompletionRequestMessageToolCall, 0, len(toolCalls))
for _, toolCall := range toolCalls {
requestToolCalls = append(requestToolCalls, chat.ChatCompletionRequestMessageToolCall{
ID: chat.NewOptNilString(toolCall.ID),
Type: toolCall.Type,
Function: chat.ChatCompletionRequestMessageToolCallFunction{
Name: toolCall.Function.Name,
Arguments: chat.NewOptString(toolCall.Function.Arguments),
},
})
}
return requestToolCalls
}
```
---
# 推荐配置与优化
## 新业务接入
1. 推荐优选 Seed 2.0 系列模型。
1. 函数调用场景下,关闭 thinking 会提高效率,具体操作请参见[开启/关闭深度思考](/docs/deep-thinking#fa3f44fa)。
2. 对速度有较高要求,可以选择 `doubao-seed-2-0-mini`系列模型。
2. 准备评测集,在函数调用模型上开展测试,观察准确率是否达到业务预期的上线准确率。
3. 常规调优手段:
* 准确填写函数的 `params`、`description` 等字段。系统提示词中不用再重复介绍函数,(可选)可以描述在何种情况下调用某函数。
* 优化函数、参数的描述,明确不同函数的边界情况;避免歧义;增加示例等。
* 对模型进行 sft(建议至少 50 条数据,模型越多、参数越多、情况越多,则所需要的数据越多),见[效果优化](/docs/function-calling#f118e5a2)。
4. 速度优化:对于简单无歧义的函数或参数,适当精简输入输出内容。
## 并行工具调用
您可以根据需求,通过 `parallel_tool_calls` 参数控制模型是否可以并行调用多个工具。
* `parallel_tool_calls: true` **(默认值)**:模型在单次请求中可以返回多个待调用的工具。
* `parallel_tool_calls: false`:对于支持并行工具调用控制的模型,此设置会限制模型最多返回一个待调用的工具。
## 提示词最佳实践
在设计提示词时,请遵循以下核心原则,为模型提供清晰、直接且无歧义的指令:
1. **优先使用代码处理确定性任务**:如果一个任务能通过传统编程高效解决,就应避免调用大模型,以提升系统效率并降低成本。
2. **保持输入信息专注**:仅向模型提供与当前任务直接相关的信息,避免无关内容干扰模型的判断。
|类别 |问题 |错误示例 |改正后示例 |
|---|---|---|---|
|函数 |命名不规范、描述不规范 |```JSON |```JSON | \
| | |{ |{ | \
| | | "type": "function", | "type": "function", | \
| | | "function": { | "function": { | \
| | | "name": "GPT1", | "name": "CreateEvent", | \
| | | "description": "新建日程" | "description": "当需要为用户新建日程时,此工具将创建日程,并返回日程ID" | \
| | | } | } | \
| | |} |} | \
| | |``` |``` |
|参数 |避免不必要的复杂格式(或嵌套) |```JSON |```JSON | \
| | |{ |{ | \
| | | "time": { | "time": { | \
| | | "type": "object", | "type": "string", | \
| | | "description": "事件时间", | "description": "事件时间" | \
| | | "properties": { | } | \
| | | "timestamp": { |} | \
| | | "description": "事件时间" |``` | \
| | | } | | \
| | | } | | \
| | | } | | \
| | |} | | \
| | |``` | |
|^^ |避免固定值 |```JSON |既然参数值固定,删去该参数,由代码处理。 | \
| | |{ | | \
| | | "time": { | | \
| | | "type": "object", | | \
| | | "description": "事件时间", | | \
| | | "properties": { | | \
| | | "timestamp": { | | \
| | | "description": "固定传2024-01-01即可" | | \
| | | } | | \
| | | } | | \
| | | } | | \
| | |} | | \
| | |``` | |
|业务流程 |尽量缩短 LLM 调用轮次 |System prompt: |System prompt: | \
| | | | | \
| | |```Go |```Go | \
| | |你正在与用户Alan沟通,你需要先查询用户ID,再通过ID创建日程…… |你正在与用户Alan(ID=abc123)沟通,你可以通过ID创建日程…… | \
| | |``` |``` |
|| | | | \
|^^ |歧义消解 |System prompt: |System prompt: | \
| | | | | \
| | |```Go |```Go | \
| | |可以通过ID查找用户,并获得用户的日程ID |每个用户具有唯一的用户ID;每个日程有对应的日程ID,两者独立的ID。 | \
| | |``` |可以通过用户ID查找用户,并获得用户的所有日程ID | \
| | | |``` | \
| | |这里两个 ID 未明确,模型可能会混用 | |
## 函数调用异常处理
JSON 格式容错机制:对于轻微不合法的 JSON 格式,可尝试使用 `json-repair` 库进行容错修复。
```Python
import json_repair
invalid_json = '{"location": "北京", "unit": "摄氏度"}'
valid_json = json_repair.loads(invalid_json)
```
## 需求澄清
需求澄清(需求确认)不依赖于函数调用,可独立使用。
可在系统提示词中加入:
```Python
如果用户没有提供足够的信息来调用函数,请继续提问以确保收集到了足够的信息。
在调用函数之前,你必须总结用户的描述并向用户提供总结,询问他们是否需要进行任何修改。
......
```
在函数的 `description` 中加入:
```Python
函数参数除了提取a和b, 还应要求用户提供c、d、e、f和其他相关细节。
```
或在系统提示中加入参数校验逻辑,当模型生成的参数缺失时,引导模型重新生成完整的参数。
```Python
如果用户提供的信息缺少工具所需要的必填参数,你需要进一步追问让用户提供更多信息。
```
## 流式输出
从 Doubao 1.5 系列模型开始支持流式输出,逐步获取函数调用信息,提升响应效率。
```Python
import os
from arkruntime import Ark
# 从环境变量中读取方舟API Key
client = Ark(
api_key=os.environ.get("ARK_API_KEY"),
base_url="https://ark.cn-beijing.volces.com/api/v3",
)
stream = client.chat.completions.create(
model="doubao-seed-2-1-pro-260915",
messages=[
{
"role": "user",
"content": "给我讲个故事,然后告诉我北京今天的天气",
}
],
tools=[
# 您要调用的工具信息
{
"type": "function",
"function": {
"name": "get_current_weather",
"description": "查询指定城市的当前天气",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "城市名称,例如北京",
}
},
"required": ["location"],
},
},
}
],
stream=True,
)
final_tool_calls = {}
for chunk in stream:
if not chunk.choices:
continue
print(chunk.choices[0].delta.content, end="")
# 使用新版Function Call能力返回信息代码适配,将流式返回的信息拼装后返回
for tool_call in chunk.choices[0].delta.tool_calls or []:
index = tool_call.index
if index not in final_tool_calls:
final_tool_calls[index] = tool_call
final_tool_calls[index].function.arguments += tool_call.function.arguments
print("Tools: ", final_tool_calls)
```
## Strict 模式
将 `strict` 参数设置为 `true` 可启用严格模式。该模式能确保模型严格遵循您定义的函数 Schema 生成调用参数。为了保证函数调用的准确性和可预测性,我们建议您始终启用严格模式。
启用严格模式需要满足以下前提条件(参见[结构化输出(beta)](/docs/structured-output-beta)):
1. 在 `properties` 中定义的所有字段,都必须在 `required` 数组中进行声明。
2. 在函数的 `parameters` 定义中,推荐设置 `"additionalProperties": false`。
如果您需要将某个字段设为可选,可以在其 `type` 定义中加入 `null`。例如:`{"type": ["string", "null"]}`。
**选项:启用 Strict 模式**
```JSON
{
"type": "function",
"function": {
"name": "get_current_weather",
"description": "获取指定地点的天气信息,支持摄氏度和华氏度两种单位",
"strict": true, // 开启 strict 模式
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "地点的位置信息,例如北京、上海"
},
"unit": {
"type": ["string", "null"], //与不启用有差异
"enum": ["摄氏度", "华氏度"],
"description": "温度单位,可选值为摄氏度或华氏度"
}
},
"required": ["location", "unit"], //与不启用有差异
"additionalProperties": false
}
}
}
```
**选项:不启用 Strict 模式**
```JSON
{
"type": "function",
"function": {
"name": "get_current_weather",
"description": "获取指定地点的天气信息,支持摄氏度和华氏度两种单位",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "地点的位置信息,例如北京、上海"
},
"unit": {
"type": "string",
"enum": ["摄氏度", "华氏度"],
"description": "温度单位,可选值为摄氏度或华氏度"
}
},
"required": ["location"]
}
}
}
```
## 多轮函数调用
当用户需求需要多次调用工具函数时,维护对话历史上下文,逐轮处理函数调用和结果回填。
### 示例流程
1. 用户提问:“查询北京的天气,并将结果发送给张三”。
2. 第一轮:模型调用 `get_current_weather` 工具获取北京天气。
3. 第二轮:模型调用 `send_message` 工具将天气结果发送给张三。
4. 第三轮:模型总结任务完成情况,返回最终回复。
### 代码示例
> **说明**
>
> 多轮函数调用:指用户 query 需要多次调用工具函数和大模型才能完成的情况,是多轮对话的子集。
调用 Response 细节图:

**选项:Golang**
```Go
package main
import (
"context"
"encoding/json"
"fmt"
"os"
"strings"
"github.com/volcengine/ark-runtime-go/arkruntime"
"github.com/volcengine/ark-runtime-go/arkruntime/model/chat"
)
func main() {
client := arkruntime.NewClientWithApiKey(
os.Getenv("ARK_API_KEY"),
arkruntime.WithBaseUrl("https://ark.cn-beijing.volces.com/api/v3"),
)
fmt.Println("----- function call multiple rounds request -----")
ctx := context.Background()
// Step 1: send the conversation and available functions to the model
req := &chat.ChatCompletionRequest{
Model: "doubao-seed-2-1-pro-260915", // Replace with Model ID
Messages: []chat.ChatCompletionRequestMessage{
systemMessage("你是 AI 人工智能助手"),
userMessage("上海的天气怎么样?"),
},
Tools: []chat.ChatCompletionTool{
{
Type: chat.ToolTypeFunction,
Function: chat.FunctionObject{
Name: "get_current_weather",
Description: chat.NewOptString("Get the current weather in a given location"),
Parameters: functionParameters(map[string]interface{}{
"type": "object",
"properties": map[string]interface{}{
"location": map[string]interface{}{
"type": "string",
"description": "The city and state, e.g. Beijing",
},
"unit": map[string]interface{}{
"type": "string",
"description": "枚举值有celsius、fahrenheit",
},
},
"required": []string{
"location",
},
}),
},
},
},
}
resp, err := client.CreateChatCompletion(ctx, req)
if err != nil {
fmt.Printf("chat error: %v\n", err)
return
}
// extend conversation with assistant's reply
req.Messages = append(req.Messages, assistantToolCallMessage(resp.Choices[0].Message))
// Step 2: check if the model wanted to call a function.
// The model can choose to call one or more functions; if so,
// the content will be a stringified JSON object adhering to
// your custom schema (note: the model may hallucinate parameters).
for _, toolCall := range resp.Choices[0].Message.ToolCalls {
fmt.Println("calling function")
fmt.Println(" id:", toolCall.ID)
fmt.Println(" name:", toolCall.Function.Name)
fmt.Println(" argument:", toolCall.Function.Arguments)
functionResponse, err := CallAvailableFunctions(toolCall.Function.Name, toolCall.Function.Arguments)
if err != nil {
functionResponse = err.Error()
}
// extend conversation with function response
req.Messages = append(req.Messages,
toolMessage(toolCall.ID, functionResponse),
)
}
// get a new response from the model where it can see the function response
secondResp, err := client.CreateChatCompletion(ctx, req)
if err != nil {
fmt.Printf("second chat error: %v\n", err)
return
}
fmt.Println("conversation", MustMarshal(req.Messages))
fmt.Println("new message", MustMarshal(secondResp.Choices[0].Message))
}
func CallAvailableFunctions(name, arguments string) (string, error) {
if name == "get_current_weather" {
params := struct {
Location string `json:"location"`
Unit string `json:"unit"`
}{}
if err := json.Unmarshal([]byte(arguments), ¶ms); err != nil {
return "", fmt.Errorf("failed to parse function call name=%s arguments=%s", name, arguments)
}
return GetCurrentWeather(params.Location, params.Unit), nil
} else {
return "", fmt.Errorf("got unavailable function name=%s arguments=%s", name, arguments)
}
}
// GetCurrentWeather get the current weather in a given location.
// Example dummy function hard coded to return the same weather.
// In production, this could be your backend API or an external API
func GetCurrentWeather(location, unit string) string {
if unit == "" {
unit = "celsius"
}
weather := map[string]string{
"location": location,
"temperature": "unknown",
"unit": unit,
}
switch strings.ToLower(location) {
case "beijing", "北京":
weather["location"] = "Beijing"
weather["temperature"] = "10"
case "shanghai", "上海":
weather["location"] = "Shanghai"
weather["temperature"] = "23"
}
return MustMarshal(weather)
}
func MustMarshal(v interface{}) string {
b, _ := json.Marshal(v)
return string(b)
}
func systemMessage(content string) chat.ChatCompletionRequestMessage {
return chat.ChatCompletionRequestMessage{
OneOf: chat.NewChatCompletionRequestSystemMessageChatCompletionRequestMessageSum(
chat.ChatCompletionRequestSystemMessage{
Role: chat.ChatCompletionRequestSystemMessageRoleSystem,
Content: chat.NewStringChatCompletionMessageContent(content),
},
),
}
}
func toolMessage(toolCallID, content string) chat.ChatCompletionRequestMessage {
return chat.ChatCompletionRequestMessage{
OneOf: chat.NewChatCompletionRequestToolMessageChatCompletionRequestMessageSum(
chat.ChatCompletionRequestToolMessage{
Role: chat.ChatCompletionRequestToolMessageRoleTool,
ToolCallID: chat.NewOptNilString(toolCallID),
Content: chat.NewOptNilChatCompletionMessageContent(chat.NewStringChatCompletionMessageContent(content)),
},
),
}
}
func userMessage(content string) chat.ChatCompletionRequestMessage {
return chat.ChatCompletionRequestMessage{
OneOf: chat.NewChatCompletionRequestUserMessageChatCompletionRequestMessageSum(
chat.ChatCompletionRequestUserMessage{
Role: chat.ChatCompletionRequestUserMessageRoleUser,
Content: chat.NewOptNilChatCompletionMessageContent(chat.NewStringChatCompletionMessageContent(content)),
},
),
}
}
func functionParameters(value map[string]interface{}) chat.OptFunctionObjectParameters {
encoded, err := json.Marshal(value)
if err != nil {
panic(err)
}
var parameters chat.FunctionObjectParameters
if err := json.Unmarshal(encoded, ¶meters); err != nil {
panic(err)
}
return chat.NewOptFunctionObjectParameters(parameters)
}
func assistantToolCallMessage(message chat.ChatCompletionResponseMessage) chat.ChatCompletionRequestMessage {
return chat.ChatCompletionRequestMessage{
OneOf: chat.NewChatCompletionRequestAssistantMessageChatCompletionRequestMessageSum(
chat.ChatCompletionRequestAssistantMessage{
Role: chat.ChatCompletionRequestAssistantMessageRoleAssistant,
Content: chat.NewOptNilChatCompletionMessageContent(chat.NewStringChatCompletionMessageContent(message.Content)),
ToolCalls: toRequestToolCalls(message.ToolCalls),
},
),
}
}
func toRequestToolCalls(
toolCalls []chat.ChatCompletionMessageToolCall,
) []chat.ChatCompletionRequestMessageToolCall {
requestToolCalls := make([]chat.ChatCompletionRequestMessageToolCall, 0, len(toolCalls))
for _, toolCall := range toolCalls {
requestToolCalls = append(requestToolCalls, chat.ChatCompletionRequestMessageToolCall{
ID: chat.NewOptNilString(toolCall.ID),
Type: toolCall.Type,
Function: chat.ChatCompletionRequestMessageToolCallFunction{
Name: toolCall.Function.Name,
Arguments: chat.NewOptString(toolCall.Function.Arguments),
},
})
}
return requestToolCalls
}
```
**选项:Python**
```Python
import os
import json
import time
from arkruntime import Ark
# Load API key from environment variable
api_key = os.getenv('ARK_API_KEY')
# Initialize Ark client
client = Ark(
base_url="https://ark.cn-beijing.volces.com/api/v3",
api_key=api_key,
)
print("=" * 60)
# Initial conversation history with user query
messages = [
{
"role": "user",
"content": "先查询北京的天气,如果是晴天微信发给Alan,否则发给Peter",
},
]
# Tool definitions for function calling
tools = [
{
"type": "function",
"function": {
"name": "get_current_weather",
"description": "",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "地理位置,比如北京市",
},
"unit": {"type": "string", "description": "枚举值 [摄氏度,华氏度]"},
},
"required": ["location"],
},
},
},
{
"type": "function",
"function": {
"name": "SendMessage",
"description": "通过微信发送消息给指定用户",
"parameters": {
"type": "object",
"properties": {
"receiver": {
"type": "string",
"description": "接收者用户名",
},
"content": {
"type": "string",
"description": "消息内容",
},
},
"required": ["receiver", "content"],
},
},
},
]
# Mock function to simulate weather API
def mock_get_current_weather(location, unit="摄氏度"):
if unit == "华氏度":
return f"{location}今天68~75华氏度,天气:阵雨"
else:
return f"{location}今天20~24度,天气:阵雨"
# Mock function to simulate message sending
def mock_send_message(receiver, content):
return f"成功发送微信消息至{receiver}"
# Handle tool calls by dispatching to appropriate mock functions
def handle_tool_call(tool_call):
function_name = tool_call.function.name
function_args = json.loads(tool_call.function.arguments)
if function_name == "get_current_weather":
return mock_get_current_weather(**function_args)
elif function_name == "SendMessage":
return mock_send_message(**function_args)
else:
return f"未知函数: {function_name}"
round_count = 0
max_rounds = 10
user_question_printed = False
while round_count < max_rounds:
round_count += 1
print(f"\n========== Round {round_count} ==========")
if round_count == 1 and not user_question_printed:
print(f"user: {messages[0]['content']}")
user_question_printed = True
start_time = time.time()
# Call the model
response = client.chat.completions.create(
model="doubao-seed-2-1-pro-260915",
messages=messages,
tools=tools
)
elapsed_time = time.time() - start_time
assistant_message = response.choices[0].message
if assistant_message.tool_calls:
for tool_call in assistant_message.tool_calls:
print(f"assistant [FC Response]: {tool_call.function.name}, args={tool_call.function.arguments}")
messages.append(assistant_message.model_dump())
tool_result = handle_tool_call(tool_call)
print(f"tool: {tool_result}")
messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"content": tool_result,
"name": tool_call.function.name,
})
print(f"耗时: {elapsed_time:.2f} 秒")
else:
print(f"assistant [Final Answer]: {assistant_message.content}")
print(f"耗时: {elapsed_time:.2f} 秒")
break
print("\n" + "=" * 60)
```
**选项:Java**
```Java
package com.volcengine.ark.runtime;
import com.volcengine.ark.runtime.models.chat.*;
import com.volcengine.ark.runtime.service.ArkService;
import okhttp3.ConnectionPool;
import okhttp3.Dispatcher;
import java.util.*;
import java.util.concurrent.TimeUnit;
public class FunctionCallChatCompletionsExample {
static String apiKey = System.getenv("ARK_API_KEY");
static ConnectionPool connectionPool = new ConnectionPool(5, 1, TimeUnit.SECONDS);
static Dispatcher dispatcher = new Dispatcher();
static ArkService service = ArkService.builder().dispatcher(dispatcher).connectionPool(connectionPool)
.baseUrl("https://ark.cn-beijing.volces.com/api/v3")
.apiKey(apiKey).build();
public static void main(String[] args) {
System.out.println("\n----- function call multiple rounds request -----");
final List messages = new ArrayList<>();
final ChatCompletionRequestMessage userMessage = ChatCompletionRequestUserMessage.builder().role(ChatCompletionRequestMessageType.USER).content(ChatCompletionMessageContent.ofString("北京今天天气如何?")).build();
messages.add(userMessage);
final List tools = Arrays.asList(
ChatCompletionTool.builder().type(ToolType.FUNCTION).function(FunctionObject.builder()
.name("get_current_weather")
.description("获取给定地点的天气")
.parameters(new com.fasterxml.jackson.databind.ObjectMapper().convertValue(new Weather(
"object",
new HashMap() {{
put("location", new HashMap() {{
put("type", "string");
put("description", "地点的位置信息,比如北京");
}});
put("unit", new HashMap() {{
put("type", "string");
put("description", "枚举值有celsius、fahrenheit");
}});
}},
Collections.singletonList("location")
), Map.class))
.build()).build()
);
ChatCompletionRequest chatCompletionRequest = ChatCompletionRequest.builder()
.model("${YOUR_ENDPOINT_ID}")
.messages(messages)
.tools(tools)
.build();
ChatCompletionResponseChoice choice = service.createChatCompletion(chatCompletionRequest).getChoices().get(0);
messages.add(ChatCompletionRequestAssistantMessage.builder().role(ChatCompletionRequestMessageType.ASSISTANT).content(ChatCompletionMessageContent.ofString(choice.getMessage().getContent())).toolCalls(toRequestToolCalls(choice.getMessage().getToolCalls())).build());
choice.getMessage().getToolCalls().forEach(
toolCall -> {
messages.add(ChatCompletionRequestToolMessage.builder().role(ChatCompletionRequestMessageType.TOOL).toolCallId(toolCall.getId()).content(ChatCompletionMessageContent.ofString("北京天气晴,24~30度")).name(toolCall.getFunction().getName()).build());
});
ChatCompletionRequest chatCompletionRequest2 = ChatCompletionRequest.builder()
.model("${YOUR_ENDPOINT_ID}")
.messages(messages)
.build();
service.createChatCompletion(chatCompletionRequest2).getChoices().forEach(System.out::println);
// shutdown service
service.shutdownExecutor();
}
public static class Weather {
public String type;
public Map properties;
public List required;
public Weather(String type, Map properties, List required) {
this.type = type;
this.properties = properties;
this.required = required;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public Map getProperties() {
return properties;
}
public void setProperties(Map properties) {
this.properties = properties;
}
public List getRequired() {
return required;
}
public void setRequired(List required) {
this.required = required;
}
}
private static java.util.List toRequestToolCalls(
java.util.List toolCalls) {
if (toolCalls == null) {
return java.util.Collections.emptyList();
}
java.util.List requestToolCalls =
new java.util.ArrayList<>();
for (ChatCompletionMessageToolCall toolCall : toolCalls) {
requestToolCalls.add(
ChatCompletionRequestMessageToolCall.builder()
.id(toolCall.getId())
.type(toolCall.getType())
.function(
ChatCompletionRequestMessageToolCallFunction.builder()
.name(toolCall.getFunction().getName())
.arguments(toolCall.getFunction().getArguments())
.build())
.build());
}
return requestToolCalls;
}
}
```
### 响应示例
```Python
========== Round 1 ==========
user: 先查询北京的天气,如果是晴天微信发给Alan,否则发给Peter...
assistant [FC Response]:
name=GetCurrentWeather, args={"location": "\u5317\u4eac"}
[elapsed=2.607 s]
========== Round 2 ==========
tool: 北京今天20~24度,天气:阵雨。...
assistant [FC Response]:
name=SendMessage, args={"content": "\u4eca\u5929\u5317\u4eac\u7684\u5929\u6c14", "receiver": "Peter"}
[elapsed=3.492 s]
========== Round 3 ==========
tool: 成功发送微信消息至Peter...
assistant [Final Answer]:
好的,请问还有什么可以帮助您?
[elapsed=0.659 s]
```
### 多轮输出注意事项
#### **轮次输出顺序**
触发函数调用时,系统先输出`content`给用户,再生成`tool_calls`并结束当前输出;**当前轮次内容不可依赖工具结果**,后续指令需待工具返回`message`后执行。
#### **多轮输出响应完整性**
严格遵循`assistant(含tool_calls)→ tool(含message)→ assistant`的顺序,禁止跳过`tool message`响应直接发送新的`assistant`消息。每次`tool_calls`需对应`tool`角色的 `message`(含成功/错误结果),缺失可能因`prefill`机制触发重复调用或流程中断。
## 效果优化
如果函数调用的效果未达到您的预期,可以尝试通过以下方法进行优化:
* **更换为最新模型**:建议您选用最新的模型版本,通常能获得更好的函数调用效果。
* **进行模型精调**:通过监督微调(SFT)或强化学习,可以针对性地提升模型表现。详情请参见[模型精调概述](/docs/fine-tuning-overview)。精调主要能改善以下方面:
* **函数选择准确性**:提升模型在合适时机选择正确函数的能力。
* **参数提取能力**:优化模型解析用户意图并生成准确函数入参的能力。
* **结果总结质量**:改善模型对工具执行结果的总结,使其更自然、准确。
---
# 常见问题
## Q:函数调用& MCP 的核心区别是什么,使用时如何选型?
核心区别与典型使用场景:
|**维度** |**FC(Function Calling)** |**MCP(Model Context Protocol)** |
|---|---|---|
|**本质** |模型调用外部工具 / 函数的能力(功能扩展) |定义模型与外部系统交互时的上下文管理协议(流程规范) |
|**目标** |弥补模型自身能力不足(如计算、数据查询、操作执行) |标准化交互过程中上下文的传递、解析与状态维护 |
|**核心作用** |实现模型与外部工具的 “能力集成” |确保多轮交互中上下文(如对话历史、参数、状态)的一致性 |
|**协议标准** |厂商自定义格式(如 OpenAI 的 JSON 参数结构) |强制遵循 JSON-RPC 2.0 标准,强调协议统一性 |
|**架构** |直接集成于模型 API,用户定义函数后由模型触发调用 |客户端 - 服务器模式,分离 MCP Host(客户端)与 MCP Server(服务端) |
|**上下文管理** |单次请求 - 响应模式,上下文依赖需开发者自行处理 |支持多轮对话、历史状态维护,适用于长序列依赖任务 |
|**典型使用场景** |外部数据调用与系统操作(如天气查询、复杂运算);示例:调用天气 API 回复 “东京今日气温” |多轮对话与跨系统上下文管理(如订餐流程、客服对话);示例:连贯处理订餐菜品与配送地址 |
两者之间的关系:
* **互补而非互斥**:
* MCP 可能在流程中包含函数调用的调用逻辑(如定义何时、如何触发函数调用)。
* 函数调用的输入输出需遵循 MCP 的上下文规范(如参数格式、返回值解析规则)。
* **分层协作**:
* MCP 解决连接问题:标准化协议打通数据孤岛,提供基础设施(如整合用户订单数据)。
* 函数调用解决执行问题:在协议层之上调用具体函数完成任务(如调用库存 API 生成补货建议)。
* **架构定位**:函数调用是**能力接口**,MCP 是**交互框架**,二者常结合使用以构建复杂应用(如智能助手同时需要调用工具和管理多轮对话状态)。
参考文档:
* **MCP 官方协议规范**[Model Context Protocol Specification](https://modelcontextprotocol.io/specification/):明确协议核心架构、JSON - RPC 消息格式、状态管理机制与安全策略,是接口设计的权威参考。
* **MCP 社区与生态发展** [MCP Development Roadmap](https://modelcontextprotocol.io/development/roadmap):介绍 MCP 发展规划,涵盖远程连接支持、沙箱安全机制及多模态扩展等发展计划。
## **Q:Deepseek R1 模型是否支持并行函数调用?**
A:暂不支持 `parallel_tool_calls` 控制字段,该模型默认采用自动触发并行调用机制,开发者无需额外配置即可实现多工具并行调用。
## **Q:如何处理 Deepseek R1 的参数幻觉问题?**
A:该模型在复杂参数解析时可能出现嵌套调用异常(如 `get_weather:{city: get_location()}`),建议通过以下方式干预:
* 在 `system prompt` 中明确要求**分步调用**(如“请先调用定位函数,再调用天气查询函数”) 。
* 使用 **JSON Schema 校验**强制参数格式。
## Q:如何判断模型是否需要调用函数?
A:模型会根据用户问题和工具定义自主判断,若返回结果中包含 `tool_calls` 字段,则表示需要调用工具;若 `content` 字段有直接回复,则无需调用工具。
## Q:支持并行调用多个函数吗?
A:支持并行函数调用,通过设置 `parallel_tool_calls` 参数为 `true`,模型可同时返回多个函数调用信息,提高处理效率。
## Q:为什么模型返回的工具参数存在幻觉?
A:这是大模型常见的问题,可通过精调(SFT)优化模型的参数生成能力,或在系统提示中明确参数的格式和范围,减少幻觉现象。
部分模型(特别是 Deepseek R1)存在一些参数幻觉问题。如预期先调用 get_location 获得城市,再调用 get_weather 查询,R1 模型有概率直接返回 `get_weather:{city: **get_location()**}` 这种嵌套调用,请在系统提示词中进行干预解决,分步完成调用。
## Q:如何处理函数调用失败的情况?
A:将工具失败信息以 `role=tool` 的消息回填给模型,模型会根据错误信息生成相应的回复,例如“抱歉,函数调用失败,请稍后重试。”。
通过以上优化,开发者能够更高效地使用函数调用功能,实现大模型与外部工具的深度整合,快速构建智能应用。
---
# 附 1:工具函数参数构造规范
为确保模型正确调用工具功能,需按以下规范构造 `tools` 对象,遵循 JSON Schema 标准。
本文主要讲解如何构造函数调用工具,关于工具函数的使用请参考[基本使用流程](/docs/function-calling#db7321a0)。
## 总体结构
```JSON
{
"type": "function",
"function": {
"name": "get_current_weather",
"description": "获取指定地点的天气信息",
"parameters": {}
}
}
```
* `type`:工具的类型,这里是固定值 `function`,表示这是一个函数调用工具。
* `function`:含函数名称、描述和参数等详细配置。
## 字段解释
### `function` 字段
|**字段** |**类型** |**是否必填** |**说明** |
|---|---|---|---|
|name |string |是 |函数名称,唯一标识,建议使用小写加下划线 |
|description |string |是 |函数作用的描述 |
|parameters |object |是 |函数参数定义,需要符合 JSON Schema 格式 |
### `parameters` 字段
`parameters` 须为符合 JSON Schema 格式的对象:
```JSON
{
"type": "object",
"properties": {
"参数名": {
"type": "string | number | boolean | object | array",
"description": "参数说明"
}
},
"required": ["必填参数"]
}
```
* `type`:必须是 `"object"`。
* `properties`:列出支持的所有参数名及其类型。
* `参数``名`须为英文字符串,且不能重复。
* 参数`type`需遵循 [json 规范](https://json-schema.org/docs),支持类型包括 string、number、boolean、integer、object、array。
* `required`:指定函数中必填的参数名。
* 其它参数根据`type`的不同稍有区别,详情请参见下表。
|`type`类型 |示例 |
|---|---|
|string、integer、number、boolean |略 |
|object (对象) |* 示例 1: 查询特点用户画像(根据年龄、性别、婚姻状况等) | \
| | | \
|* `description`:简要说明 |```Python | \
|* `properties` 描述该对象所有属性 |"person": { | \
|* `required` 描述必填属性 | "type": "object", | \
| | "description": "个人特征", | \
| | "properties": { | \
| | "age": {"type": "integer", "description": "年龄"}, | \
| | "gender": {"type": "string", "description": "性别"}, | \
| | "married": {"type": "boolean", "description": "是否已婚"} | \
| | }, | \
| | "required": ["age"], | \
| |} | \
| |``` |
|array (列表) |* 示例 1:文本数组,若干个网页链接 | \
| | | \
|* `description`:简要说明 |```Bash | \
|* `"items": {"type": ITEM_TYPE}`来表达数组元素的数据类型 |"url": { | \
| | "type": "array", | \
| | "description": "需要解析网页链接,最多3个", | \
| | "items": {"type": "string"} | \
| |``` | \
| | | \
| | | \
| |* 示例 2:二维数组 | \
| | | \
| |```Go | \
| |"matrix": { | \
| | "type": "array", | \
| | "description": "需要计算的二维矩阵", | \
| | "items": {"type": "array", "items": {"type": "number"}}, | \
| |} | \
| |``` | \
| | | \
| | | \
| |* 示例 3: 通过 array 来实现多选 | \
| | | \
| |```JSON | \
| | | \
| |"grade": { | \
| | "description": "年级, 支持多选", | \
| | "type": "array", | \
| | "items": { | \
| | "type": "string", | \
| | "description": "枚举值有\n\"一年级\",\n\"二年级\",\n\"三年级\",\n\"四年级\",\n\"五年级\",\n\"六年级\"。 " | \
| | }, | \
| |} | \
| |``` |
## 完整示例
```JSON
{
"type": "function",
"function": {
"name": "get_weather",
"description": "获取指定位置的天气信息",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "城市和国家,例如:北京,中国"
}
},
"required": ["location"]
}
}
}
```
## 注意事项
* **大小写敏感**:所有字段名、参数名严格区分大小写(建议统一用小写)。
* **中文处理**:字段名用英文,中文说明置于 `description` 中(如 `location` 的描述为 “城市和国家”)。
* **Schema 合规性**:`parameters` 必须是有效的 JSON Schema 对象,可通过 JSON Schema 校验工具验证。
## 最佳实践
1. 工具描述核心准则
* 详细说明工具功能、适用场景(及禁用场景)、参数含义与影响、限制条件(如输入长度限制),单工具描述建议 3-4 句。
* 优先完善功能、参数等基础描述,示例仅作为补充(推理模型需谨慎添加)。
2. 函数设计要点
* **命名与参数**:函数名直观(如`parse_product_info`),参数说明包含格式(如`city: string`)和业务含义(如“目标城市拼音全称”),明确输出定义(如“返回 JSON 格式天气数据”)。
* **系统提示**:通过提示指定调用条件(如“用户询问商品详情时触发`get_product_detail`”)。
* **工程化设计**:
* 使用枚举类型(如`StatusEnum`)避免无效参数,确保逻辑直观(最小惊讶原则)。
* 确保仅凭文档描述,人类可正确调用函数(补充潜在疑问解答)。
* **调用优化**:
* 已知参数通过火山方舟代码能力隐式传递(如`submit_order`无需重复声明`user_id`)。
* 合并固定流程函数(如`query_location`与`mark_location`整合为`query_and_mark_location`)。
3. 关于 `Parameters` 字段顺序的稳定性
尽管在标准 JSON 规范中对象的键是无序的,但在向大模型提供 tools 定义时, 建议保持 properties 内部字段顺序的固定与一致。原因在于,大模型底层将 JSON 结构视为线性的文本 Token 序列。字段顺序的改变会导致模型接收到的系统提示词发生变化,这可能会影响模型的注意力机制,进而导致模型生成的函数调用参数顺序或最终结果产生微小的差异。在进行提示词效果测试或回归测试时,请确保参数定义的顺序保持不变。
---
# 深度思考
Source: https://ark.volcengine.com/region:cn-beijing/docs/deep-thinking
深度思考指模型在回答前,对问题进行分析及多步骤规划,再尝试解决问题。擅长处理编程、科学推理、智能体工作流等复杂及抽象场景。启用深度思考后,会在指定字段返回思维链内容,可基此观察和使用模型推导内容。
> **说明**
>
> 方舟平台的新用户?获取 API Key 及 开通模型等准备工作,请参见 [快速入门](/docs/quick-start)。
# 快速开始
|输入 |思维链 |回答 |
| --- | --- | --- |
|```Plain Text |```Plain Text |```Plain Text | \
|我要研究深度思考模型与非深度思考模型区别的课题,怎么体现我的专业性 |用户现在要做深度思考模型和非深度思考模型区别的课题,需要体现专业性。首先得明确,专业性体现在哪里? |### **一、第一步:明确概念边界——避免泛化,精准定义** | \
|``` |... |专业性的起点是**清晰的概念界定**,避免将“深度模型”等同于“深度思考模型”,也避免将“非深度模型”简化为“传统模型”。需基于学术共识和研究目标给出操作性定义: | \
| |要在“深度思考模型与非深度思考模型区别”的课题中体现专业性,核心在于**严谨的概念界定、系统的对比框架、科学的方法论支撑、以及深度的理论与实践结合**。以下是具体的实施路径,从研究框架到细节落地,帮你构建专业的研究体系: |... | \
| |``` |通过以上路径,你的课题将从“表面对比”升级为“本质穿透”,充分体现专业性与研究深度。祝你研究顺利! | \
| | |``` |
**选项:Curl**
```Bash
curl https://ark.cn-beijing.volces.com/api/v3/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ARK_API_KEY" \
-d '{
"model": "doubao-seed-2-1-pro-260915",
"messages": [
{
"role": "user",
"content": "我要研究深度思考模型与非深度思考模型区别的课题,怎么体现我的专业性"
}
]
}'
```
* 您可按需替换 Model ID。Model ID 查询见 [模型列表](/docs/model-list)。
**选项:Python**
```Python
import os
# Install SDK: python -m pip install --upgrade arkruntime
from arkruntime import Ark
client = Ark(
# The base URL for model invocation
base_url="https://ark.cn-beijing.volces.com/api/v3",
# Get API Key: https://ark.volcengine.com/region:cn-beijing/apikey
api_key=os.getenv('ARK_API_KEY'),
# Deep thinking takes longer; set a larger timeout, with 1,800 seconds or more recommended
timeout=1800,
)
completion = client.chat.completions.create(
# Replace with Model ID
model = "doubao-seed-2-1-pro-260915",
messages=[
{"role": "user", "content": "我要研究深度思考模型与非深度思考模型区别的课题,怎么体现我的专业性"}
]
)
# When deep thinking is triggered, print the chain-of-thought content
if hasattr(completion.choices[0].message, 'reasoning_content'):
print(completion.choices[0].message.reasoning_content)
print(completion.choices[0].message.content)
```
**选项:Go**
```Go
package main
import (
"context"
"fmt"
"os"
"time"
"github.com/volcengine/ark-runtime-go/arkruntime"
"github.com/volcengine/ark-runtime-go/arkruntime/model/chat"
)
func main() {
client := arkruntime.NewClientWithApiKey(
// Get API Key: https://ark.volcengine.com/region:cn-beijing/apikey
os.Getenv("ARK_API_KEY"),
// The base URL for model invocation
arkruntime.WithBaseUrl("https://ark.cn-beijing.volces.com/api/v3"),
// Deep thinking takes longer; set a larger timeout, with 1,800 seconds or more recommended
arkruntime.WithTimeout(30*time.Minute),
)
ctx := context.Background()
req := &chat.ChatCompletionRequest{
// Replace with Model ID
Model: "doubao-seed-2-1-pro-260915",
Messages: []chat.ChatCompletionRequestMessage{
userMessage("我要研究深度思考模型与非深度思考模型区别的课题,怎么体现我的专业性"),
},
}
resp, err := client.CreateChatCompletion(ctx, req)
if err != nil {
fmt.Printf("standard chat error: %v\n", err)
return
}
// When deep thinking is triggered, print the chain-of-thought content
if resp.Choices[0].Message.ReasoningContent.IsSet() {
fmt.Println(resp.Choices[0].Message.ReasoningContent.Or(""))
}
fmt.Println(resp.Choices[0].Message.Content)
}
func userMessage(content string) chat.ChatCompletionRequestMessage {
return chat.ChatCompletionRequestMessage{
OneOf: chat.NewChatCompletionRequestUserMessageChatCompletionRequestMessageSum(
chat.ChatCompletionRequestUserMessage{
Role: chat.ChatCompletionRequestUserMessageRoleUser,
Content: chat.NewOptNilChatCompletionMessageContent(chat.NewStringChatCompletionMessageContent(content)),
},
),
}
}
```
**选项:Java**
```Java
package com.ark.sample;
import com.volcengine.ark.runtime.models.chat.*;
import com.volcengine.ark.runtime.service.ArkService;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.time.Duration;
public class ChatCompletionsExample {
public static void main(String[] args) {
// Get API Key: https://ark.volcengine.com/region:cn-beijing/apikey
String apiKey = System.getenv("ARK_API_KEY");
ArkService arkService = ArkService.builder()
.apiKey(apiKey)
.timeout(Duration.ofMinutes(30))// Deep thinking takes longer; set a larger timeout, with 1,800 seconds or more recommended
.baseUrl("https://ark.cn-beijing.volces.com/api/v3")
// The base URL for model invocation
.build();
List chatMessages = new ArrayList<>();
ChatCompletionRequestMessage userMessage = ChatCompletionRequestUserMessage.builder()
.role(ChatCompletionRequestMessageType.USER)
.content(ChatCompletionMessageContent.ofString("我要研究深度思考模型与非深度思考模型区别的课题,怎么体现我的专业性"))
.build();
chatMessages.add(userMessage);
ChatCompletionRequest chatCompletionRequest = ChatCompletionRequest.builder()
.model("doubao-seed-2-1-pro-260915")//Replace with Model ID
.messages(chatMessages)
.build();
try {
arkService.createChatCompletion(chatCompletionRequest)
.getChoices()
.forEach(choice -> {
if (choice.getMessage().getReasoningContent() != null) {
System.out.println(choice.getMessage().getReasoningContent());
}
System.out.println(choice.getMessage().getContent());
});
} catch (Exception e) {
System.out.println(e.getMessage());
} finally {
// Shut down the service executor
arkService.shutdownExecutor();
}
}
}
```
**选项:OpenAI SDK**
```Python
import os
from openai import OpenAI
client = OpenAI(
# Get API Key: https://ark.volcengine.com/region:cn-beijing/apikey
api_key=os.environ.get("ARK_API_KEY"),
base_url="https://ark.cn-beijing.volces.com/api/v3",
# Deep thinking takes longer; set a larger timeout, with 1,800 seconds or more recommended
timeout=1800,
)
completion = client.chat.completions.create(
# Replace with Model ID
model = "doubao-seed-2-1-pro-260915",
messages=[
{"role": "user", "content": "我要研究深度思考模型与非深度思考模型区别的课题,怎么体现我的专业性"}
]
)
# When deep thinking is triggered, print the chain-of-thought content
if hasattr(completion.choices[0].message, 'reasoning_content'):
print(completion.choices[0].message.reasoning_content)
print(completion.choices[0].message.content)
```
# 模型及 API
支持的模型:[文本生成能力](/docs/model-list#32e9e053) 中能力标签含"深度思考"的模型。
支持的 API:
* [Responses API](/docs/create-model-responses-api):新推出的 API,简洁上下文管理,增强工具调用能力,缓存能力降低成本,新业务及用户推荐。
* [Chat API](/docs/chat-api):使用广泛的 API,存量业务迁移成本低。
# 基础使用
## 多轮对话
组合使用系统消息、模型消息以及用户消息,可以实现多轮对话。当需要持续在一个主题内对话,可以将历史轮次的对话记录输入给模型。
|传入方式 |手动管理上下文 |通过 ID 管理上下文 |
| --- | --- | --- |
|使用示例 |```JSON |```JSON | \
| |... |... | \
| | "model": "doubao-seed-2-1-pro-260915", | "model": "doubao-seed-2-1-pro-260915", | \
| | "messages":[ | "previous_response_id":"", | \
| | {"role": "user", "content": "Hi, tell a joke."}, | "input": "What is the punchline of this joke?" | \
| | {"role": "assistant", "content": "Why did the math book look sad? Because it had too many problems! 😄"}, |... | \
| | {"role": "user", "content": "What's the punchline of this joke?"} |``` | \
| | ] | | \
| |... | | \
| |``` | |
|API |[Chat API](/docs/chat-api) |[Responses API](/docs/create-model-responses-api) |
> 在构建多轮对话的上下文时:保留历史对话的 **reasoning_content** 字段,由模型自行判断是否将该字段加入到推理输入中。
> 更多说明及完整示例请参见[上下文管理](/docs/context-management)。
## 流式输出
随着大模型输出,动态输出内容,无需等待模型推理完毕,即可看到中间输出过程内容。
|预览 |优势 |
| --- | --- |
|[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/0b0ed47ec1b94b20a4f4966aa80130e6) |* **改善等待体验**:无需等待完整内容生成完毕,可立即处理过程内容。 | \
| |* **实时过程反馈**:多轮交互场景,实时了解任务当前的处理阶段。 | \
| |* **更高的容错性**:中途出错,也能获取到已生成内容,避免非流式输出失败无返回的情况。 | \
| |* **简化超时管理**:保持客户端与服务端的连接状态,避免复杂任务耗时过长而连接超时。 |
通过配置 **stream** 为 `true`,来启用流式输出。
```JSON
"model": "doubao-seed-2-1-pro-260915",
"messages": [
{"role": "user", "content": "深度思考模型与非深度思考模型区别"}
],
"stream": true
```
> 完整示例及更多说明请参见[流式输出](/docs/streaming-output)。
## 开启/关闭深度思考
提供 **thinking** 字段控制是否关闭深度思考能力,实现“复杂任务深度推理,简单任务高效响应”的精细控制,获得成本、效率收益。
* 取值说明:
* `enabled`:强制开启,强制开启深度思考能力。
* `disabled`:强制关闭深度思考能力。
* `auto`:模型自行判断是否进行深度思考。
* 示例代码:
**选项:Curl**
```Bash
curl https://ark.cn-beijing.volces.com/api/v3/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ARK_API_KEY" \
-d '{
"model": "doubao-seed-2-1-pro-260915",
"messages": [
{
"role": "user",
"content": [
{
"type":"text",
"text":"我要研究深度思考模型与非深度思考模型区别的课题,体现出我的专业性"
}
]
}
],
"thinking":{
"type":"disabled"
}
}'
```
* **model**:请变更为实际调用的模型。
* **thinking.type**:字段可以取值范围。
* `disabled`:强制关闭深度思考能力,模型不输出思维链内容。
* `enabled`:强制开启深度思考能力,模型强制输出思维链内容。
* `auto`:模型自行判断是否需要进行深度思考。
**选项:Python**
```Python
import os
# Install SDK: python -m pip install --upgrade arkruntime
from arkruntime import Ark
client = Ark(
# The base URL for model invocation
base_url="https://ark.cn-beijing.volces.com/api/v3",
# Get API Key: https://ark.volcengine.com/region:cn-beijing/apikey
api_key=os.getenv('ARK_API_KEY'),
# Deep thinking takes longer; set a larger timeout, with 1,800 seconds or more recommended
timeout=1800,
)
# 创建一个对话请求
completion = client.chat.completions.create(
# Replace with Model ID
model="doubao-seed-2-1-pro-260915",
messages=[
{"role": "user", "content": "我要研究深度思考模型与非深度思考模型区别的课题,体现出我的专业性"}
],
thinking={
"type": "disabled", # 不使用深度思考能力
# "type": "enabled", # 使用深度思考能力
# "type": "auto", # 模型自行判断是否使用深度思考能力
},
)
print(completion)
```
**选项:Go**
```Go
package main
import (
"context"
"fmt"
"os"
"time"
"github.com/volcengine/ark-runtime-go/arkruntime"
"github.com/volcengine/ark-runtime-go/arkruntime/model/chat"
)
func main() {
client := arkruntime.NewClientWithApiKey(
// Get API Key: https://ark.volcengine.com/region:cn-beijing/apikey
os.Getenv("ARK_API_KEY"),
// The base URL for model invocation
arkruntime.WithBaseUrl("https://ark.cn-beijing.volces.com/api/v3"),
//深度思考耗时更长,请设置更大的超时限制,推荐为30分钟及以上
arkruntime.WithTimeout(30*time.Minute),
)
// 创建一个上下文,通常用于传递请求的上下文信息,如超时、取消等
ctx := context.Background()
// 构建聊天完成请求,设置请求的模型和消息内容
req := &chat.ChatCompletionRequest{
// Replace with Model ID
Model: "doubao-seed-2-1-pro-260915",
Messages: []chat.ChatCompletionRequestMessage{
userMessage("我要研究深度思考模型与非深度思考模型区别的课题,怎么体现我的专业性"),
},
Thinking: chat.NewOptThinking(chat.Thinking{Type: chat.NewOptThinkingMode(chat.ThinkingModeDisabled)}),
}
// 发送聊天完成请求,并将结果存储在 resp 中,将可能出现的错误存储在 err 中
resp, err := client.CreateChatCompletion(ctx, req)
if err != nil {
// 若出现错误,打印错误信息并终止程序
fmt.Printf("standard chat error: %v
", err)
return
}
// 检查是否触发深度思考,触发则打印思维链内容
if resp.Choices[0].Message.ReasoningContent.IsSet() {
fmt.Println(resp.Choices[0].Message.ReasoningContent.Or(""))
}
// 打印聊天完成请求的响应结果
fmt.Println(resp.Choices[0].Message.Content)
}
func userMessage(content string) chat.ChatCompletionRequestMessage {
return chat.ChatCompletionRequestMessage{
OneOf: chat.NewChatCompletionRequestUserMessageChatCompletionRequestMessageSum(
chat.ChatCompletionRequestUserMessage{
Role: chat.ChatCompletionRequestUserMessageRoleUser,
Content: chat.NewOptNilChatCompletionMessageContent(chat.NewStringChatCompletionMessageContent(content)),
},
),
}
}
```
**选项:Java**
```Java
package com.ark.sample;
import com.volcengine.ark.runtime.models.chat.*;
import com.volcengine.ark.runtime.service.ArkService;
import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
/**
* 这是一个示例类,展示了如何使用ArkService来完成聊天功能。
*/
public class ChatCompletionsExample {
public static void main(String[] args) {
// 从环境变量中获取API密钥
String apiKey = System.getenv("ARK_API_KEY");
// 创建ArkService实例
ArkService arkService = ArkService.builder()
.apiKey(apiKey)
.timeout(Duration.ofMinutes(30))// 深度思考耗时更长,请设置更大的超时限制,推荐为30分钟及以上
// The base URL for model invocation
.baseUrl("https://ark.cn-beijing.volces.com/api/v3")
.build();
// 初始化消息列表
List chatMessages = new ArrayList<>();
// 创建用户消息
ChatCompletionRequestMessage userMessage = ChatCompletionRequestUserMessage.builder()
.role(ChatCompletionRequestMessageType.USER) // 设置消息角色为用户
.content(ChatCompletionMessageContent.ofString("我要研究深度思考模型与非深度思考模型区别的课题,怎么体现我的专业性")) // 设置消息内容
.build();
// 将用户消息添加到消息列表
chatMessages.add(userMessage);
ChatCompletionRequest chatCompletionRequest = ChatCompletionRequest.builder()
.model("doubao-seed-2-1-pro-260915")//Replace with Model ID
.messages(chatMessages) // 设置消息列表
.thinking(Thinking.builder().type(ThinkingMode.DISABLED).build())
.build();
// 发送聊天完成请求并打印响应
try {
// 获取响应并打印每个选择的消息内容
arkService.createChatCompletion(chatCompletionRequest)
.getChoices()
.forEach(choice -> {
// 校验是否触发了深度思考,打印思维链内容
if (choice.getMessage().getReasoningContent() != null) {
System.out.println("推理内容: " + choice.getMessage().getReasoningContent());
} else {
System.out.println("推理内容为空");
}
// 打印消息内容
System.out.println("消息内容: " + choice.getMessage().getContent());
});
} catch (Exception e) {
System.out.println("请求失败: " + e.getMessage());
} finally {
// 关闭服务执行器
arkService.shutdownExecutor();
}
}
}
```
**选项:OpenAI SDK**
```Python
import os
from openai import OpenAI
client = OpenAI(
# 从环境变量中读取方舟API Key
api_key=os.environ.get("ARK_API_KEY"),
base_url="https://ark.cn-beijing.volces.com/api/v3",
# 深度思考耗时更长,避免连接超时导致失败,请设置更大的超时限制,推荐为1800 秒及以上
timeout=1800,
)
completion = client.chat.completions.create(
# Replace with Model ID
model = "doubao-seed-2-1-pro-260915",
messages=[
{
"role": "user",
"content": "我要研究深度思考模型与非深度思考模型区别的课题,体现出我的专业性",
}
],
extra_body={
"thinking": {
"type": "disabled", # 不使用深度思考能力
# "type": "enabled", # 使用深度思考能力
# "type": "auto", # 模型自行判断是否使用深度思考能力
}
},
)
print(completion)
```
* 支持模型:
* doubao-seed-evolving:支持 `enabled`(默认)、`disabled`。
* doubao-seed-2-1-pro-260915:支持 `enabled`(默认)、`disabled`。
* doubao-seed-2-1-lite-260915:支持 `enabled`(默认)、`disabled`。
* doubao-seed-2-1-pro-260628:支持 `enabled`(默认)、`disabled`。
* doubao-seed-2-1-turbo-260628:支持 `enabled`(默认)、`disabled`。
* doubao-seed-2-0-lite-260428:支持 `enabled`(默认)、`disabled`。
* doubao-seed-2-0-mini-260428:支持 `enabled`(默认)、`disabled`。
* doubao-seed-2-0-pro-260215:支持 `enabled`(默认)、`disabled`。
* doubao-seed-2-0-lite-260215:支持 `enabled`(默认)、`disabled`。
* doubao-seed-2-0-mini-260215:支持 `enabled`(默认)、`disabled`。
* doubao-seed-2-0-code-preview-260215:支持 `enabled`(默认)、`disabled`。
* glm-5-3-flash-260828:支持 `enabled`(默认)。(**始终启用思考,不再支持禁用思考。**)
* glm-5-2-260617:支持 `enabled`(默认)、`disabled`。
* doubao-seed-character-260628:支持 `enabled`(默认)、`disabled`。
* deepseek-v4-1-flash-261017:支持 `enabled`(默认)、`disabled`。
* deepseek-v4-1-flash-260910:支持 `enabled`(默认)、`disabled`。
* deepseek-v4-1-flash-economy-261017:支持 `enabled`(默认)、`disabled`。
* deepseek-v4-pro-ga-260813:支持 `enabled`(默认)、`disabled`。
* deepseek-v4-flash-ga-260731:支持 `enabled`(默认)、`disabled`。
* deepseek-v4-pro-260425:支持 `enabled`(默认)、`disabled`。
* 更多说明
* Responses API 使用说明请参见[控制深度思考](/docs/responses-api-deep-thinking#19c1bd32)。
* 深度思考会影响续写模式,详细信息请参见[续写模式](/docs/continuation-mode)。
## 设置最大输出长度
模型输出内容由**思维链(Chain of Thought, COT)** 和**最终回答(Answer)** 两部分组成。合理控制模型输出长度,平衡效果、速度、成本与稳定性。
|传入方式 |手动管理上下文 |通过 ID 管理上下文 |
| --- | --- | --- |
|API |[Chat API](/docs/chat-api) |[Responses API](/docs/create-model-responses-api) |
|示例 |```JSON |```JSON | \
| |... |... | \
| | "model": "doubao-seed-2-1-pro-260915", | "model": "doubao-seed-2-1-pro-260915", | \
| | "messages": [ | "previous_response_id":"", | \
| | {"role": "user", "content": "Hi, tell a joke."} | "input": "Hi, tell a joke.", | \
| | ], | "max_output_tokens": 300 | \
| | "max_completion_tokens": 300 |... | \
| |... |``` | \
| |``` | |
> 完整示例及更多说明请参见[控制输出(回答+思维链)长度](/docs/context-management#3cb3d444)。
## 调节思考长度
提供字段 **reasoning_effort**(Chat API)、**reasoning.effort**(Responses API)调节思维链长度,平衡不同场景对效果、时延、成本的需求。取值如下:
* `none`:关闭思考。
* `minimal`:关闭思考,直接回答。
* `low`:轻量思考,侧重快速响应。
* `medium`:均衡模式,兼顾速度与深度。
* `high`:深度分析,处理复杂问题。
* `xhigh`:更高强度思考。
* `max`:最高强度思考,适配高难度推理任务。
下表展示支持调节思考长度的模型,以及各模型对 **reasoning_effort**(Chat API)、**reasoning.effort**(Responses API)的默认取值与兼容映射规则。所有支持该字段的模型均接受全部 7 档取值,部分取值将按表中规则自动映射至等效档位。
| 支持模型 | 默认取值 | 兼容映射 |
| --- | --- | --- |
|* `doubao-seed-evolving` | `high` |* 传入 `minimal`:将关闭思考 | \
|* `doubao-seed-2-1-pro-260915` | |* 传入 `none`:将映射为 `minimal` | \
|* `doubao-seed-2-1-lite-260915` | |* 传入 `none`:将映射为 `minimal` | \
|* `doubao-seed-2-1-pro-260628` | |* 传入 `xhigh` / `max`:将映射为 `high` | \
|* `doubao-seed-2-1-turbo-260628` | | |
|* `doubao-seed-2-0-lite-260428` | `medium` |* 传入 `minimal`:将关闭思考 | \
|* `doubao-seed-2-0-mini-260428` | |* 传入 `none`:将映射为 `minimal` | \
|* `doubao-seed-2-0-pro-260215` | |* 传入 `xhigh` / `max`:将映射为 `high` | \
|* `doubao-seed-2-0-lite-260215` | | | \
|* `doubao-seed-2-0-mini-260215` | | | \
|* `doubao-seed-2-0-code-preview-260215` | | | \
|* `doubao-seed-character-260628` | | |
| `glm-5-3-flash-260828` | `max` |* 传入 `none` / `minimal` / `low`:将映射为 `low` | \
| | |* 传入 `medium` / `high`:将映射为 `high` | \
| | |* 传入 `xhigh` / `max`:将映射为 `max` |
| `glm-5-2-260617` | `high` |* 传入 `none` / `minimal`:将关闭思考 | \
| | |* 传入 `low` / `medium`:将映射为 `high` | \
| | |* 传入 `xhigh`:将映射为 `max` |
|* `deepseek-v4-1-flash-261017`
* `deepseek-v4-1-flash-260910`
* `deepseek-v4-1-flash-economy-261017` | `high` |* 传入 `none`:将关闭思考 | \
| | |* 传入 `minimal`:将映射为 `low` | \
| | |* 传入 `medium` / `xhigh`:将映射为 `high` | \
| | |* 传入 `ultra`:将映射为 `max` |
|* `deepseek-v4-pro-ga-260813` | `high` |* 传入 `none` / `minimal`:将关闭思考 | \
|* `deepseek-v4-flash-ga-260731` | |* 传入 `medium`:将映射为 `low` | \
| | |* 传入 `xhigh`:将映射为 `high` |
|* `deepseek-v4-pro-260425` | `high` |* 传入 `minimal`:将关闭思考 | \
|API |[Chat API](/docs/chat-api) |[Responses API](/docs/create-model-responses-api) |
| --- | --- | --- |
|示例 |```JSON |```JSON | \
| |... |... | \
| | "model": "doubao-seed-2-1-pro-260915", | "model": "doubao-seed-2-1-pro-260915", | \
| | "messages": [ | "input": [ | \
| | {"role": "user","content": "What are some common cruciferous plants?"} | {"role": "user","content":"What are some common cruciferous plants?"} | \
| | ], | ], | \
| | "reasoning_effort": "low" | "reasoning":{"effort": "low"} | \
| |... |... | \
| |``` |``` |
完整示例及说明请参见 [控制思维链长度](/docs/context-management#480730d0)。
## 回传思考内容
doubao-seed-1.8 之前的模型在工具调用场景中开启深度思考后,会直接丢弃思维链内容。doubao-seed-1.8 及部分模型为给出更详尽准确的回答,将不会直接丢弃思维链内容,思维链内容可能参与后续轮次推理,输入 tokens 会增加,具体参见[工作原理](/docs/deep-thinking#e1e56b26)。
> **说明**
>
> 推荐在 Responses API 中使用 previous_response_id,平台自动保存历史对话的上下文,并在多轮交互中回传给推理服务。
### 回传思考内容加密原文
部分模型默认会开启 thinking summary 能力,不会输出模型原始的思考内容,会返回模型思考内容摘要(**choices.message.reasoning_content**)、思考内容加密原文(**choices.message.encrypted_content**)。在多轮工具调用场景(如 agent 场景),必须原样回传思考内容加密原文。
> **说明**
>
> 默认开启 thinking summary 能力后,可能会有较高的包间延迟,请调大请求超时时间(**timeout**),并做好兼容适配。
**支持模型**:
* doubao-seed-evolving
* doubao-seed-2-1-pro-260915
* doubao-seed-2-1-lite-260915
* doubao-seed-2-1-pro-260628
* doubao-seed-2-1-turbo-260628
* doubao-seed-2-0-lite-260428
**字段说明**:
* **reasoning_effort**:仅作用于模型的原始思考内容,不适用于思考摘要。
* **usage.completion_tokens_details.reasoning_tokens**:为原始思考内容的 tokens,计费仍然按原始思考内容 token 计算。
**回传注意事项**:
* 回传 **encrypted_content**、**reasoning_content** 字段: **encrypted_content** 字段优先级高,会忽略 **reasoning_content** 中的内容。其中 **encrypted_content** 内容必须为有效内容,如果被篡改则无法还原。
* 仅回传 **reasoning_content** 字段:使用思考内容摘要参与模型推理。在多轮工具调用场景(如 agent 场景),如果没有回传 **encrypted_content** 字段,将导致模型推理效果下降。
* 未回传思考内容相关字段:不会报错。
**回传思考内容加密原文示例**:
以下是在工具调用场景,回传思考内容加密原文的示例。其中使用 Responses API 推荐使用 previous_response_id 自动获取原始思考内容并回传给模型参与推理。
|API |[Chat API](/docs/chat-api) |[Responses API](/docs/create-model-responses-api) |
| --- | --- | --- |
|支持模型及说明 |* [回传思考内容加密原文](/docs/deep-thinking#8cfd447b) |* [支持模型](/docs/responses-api-deep-thinking#7e7354e3) |
|示例 |**第一轮请求:触发工具调用** |**第一轮请求:触发工具调用** | \
| | | | \
| |```Bash |```Bash | \
| |curl https://ark.cn-beijing.volces.com/api/v3/chat/completions \ |curl https://ark.cn-beijing.volces.com/api/v3/responses \ | \
| | -H "Content-Type: application/json" \ | -H "Authorization: Bearer $ARK_API_KEY" \ | \
| | -H "Authorization: Bearer $ARK_API_KEY" \ | -H "Content-Type: application/json" \ | \
| | -d '{ | -d '{ | \
| | "model": "doubao-seed-2-0-lite-260215", | "model": "doubao-seed-2-0-lite-260215", | \
| | "messages": [ | "input": [ | \
| | { | { | \
| | "role": "system", | "role": "system", | \
| | "content": "你是人工智能助手。" | "content": "你是人工智能助手." | \
| | | | \
| | }, | }, | \
| | { | { | \
| | "role": "user", | "role": "user", | \
| | "content": "今天北京天气怎么样" | "content": "今天北京天气怎么样" | \
| | | | \
| | } | } | \
| | ], | ], | \
| | "thinking":{"type": "enabled"}, | "thinking":{"type": "enabled"}, | \
| | "tools": [ | | \
| | { | "tools": [ | \
| | "type": "function", | { | \
| | "function": { | "type": "function", | \
| | "name": "get_weather", | "name": "get_weather", | \
| | "description": "天气查询", | "description": "天气查询", | \
| | | | \
| | "parameters": { | "parameters": { | \
| | "properties": { | "type": "object", | \
| | "location": { | "properties": { | \
| | "description": "地点的位置信息,例如北京、上海。", | "location": { | \
| | | "type": "string", | \
| | "type": "string" | "description": "地点的位置信息,例如北京、上海。" | \
| | } | | \
| | }, | } | \
| | "required": [ | }, | \
| | "location" | "required": ["location"] | \
| | ], | } | \
| | "type": "object" | } | \
| | } | ] | \
| | } | }' | \
| | } |``` | \
| | ] | | \
| | }' |**第一轮响应:返回工具调用指令** | \
| |``` |模型返回信息包含`id`、`call_id`、`arguments`等关键字段。 | \
| | | | \
| |**第一轮响应:返回工具调用指令** |```Bash | \
| |模型会返回`encrypted_content`、`reasoning_content`、`tool_calls`等关键字段。 |{ | \
| | | "created_at": 1766126702, | \
| |```Bash | "id": "resp_0217661267019147d8950efa0e2f7c9d9cc7a1cc971272cf4548c", | \
| |{ | "max_output_tokens": 32768, | \
| | "choices": [ | "model": "doubao-seed-2-0-lite-260215", | \
| | { | "object": "response", | \
| | "finish_reason": "tool_calls", | "output": [ | \
| | "index": 0, | { | \
| | "logprobs": null, | "id": "rs_02176612670248500000000000000000000ffffac154e10754f5c", | \
| | "message": { | "type": "reasoning", | \
| | "content": "", | "summary": [ | \
| | "reasoning_content": "北京天气查询将由我调用相关工具完成。\n", | { | \
| | | "type": "summary_text", | \
| | "encrypted_content": "djF+2EICEj3ryfEfSUdR/SmS8OeEH4znOYftL4SWDXR8uxROjx11W7rRCj5ArLwzsm7rFsO4frOdLm2p3/yWz/r0TMqrjHiaTTvRMNdV6sLdETySlb3PDgY1W+zuYuETiq3bQuxga5jKx+GpfvlDJMfJfzq/G1kDp6ryurs0rKAFIziyc4mfFSh2CzDKNcAcp5Fi5R7M2QrSYmIUJjnoB48IVUCzu4xn7bT05qheVnGO9fbs15gYK3zINUvVsp51Oq72U/ksrPZFVs2BTgNRwjmxnFNn7A==", | "text": "用户查询北京今日天气,我将调用天气工具获取相关信息。" | \
| | "role": "assistant", | | \
| | "tool_calls": [ | } | \
| | { | ], | \
| | "function": { | "status": "completed", | \
| | "arguments": " {\"location\": \"北京\"}", | "encrypted_content": "djEqHS8w8bISWDUfivQXaeCUc8ms2JcjMBO5KQMRqKhTUdYlhbFebcndgVlFJxYUOSOAXm7gNsJdTRtp47iHpps76Rp37ipRrkEHMqIIt+KyKmN/rH9tzL+7ZLI9W4LGYMOv/27Rfqp2NW5vxiF7zkI1xgxxJFp6Vo8PNQpR68T4F7bG4PekickNR3U+EFM6hBKkhnJqxqCrjubi0o/8C35IoDF998+G6hokaDhOb6EqJ5fXaSZvtQJaK4DBh4HIciMFnRqzts/xlacBHsWCWLcxUASrvj0vYIs9a+ZN9BxkLjrBy/nEOOEcmID/I2NukCDEFa7zxlOXLvdZHuslP5cvyno=" | \
| | | }, | \
| | "name": "get_weather" | { | \
| | }, | "arguments": " {\"location\": \"北京\"}", | \
| | "id": "call_wiezxeyae8jzxl3jx8nhfgb5", | | \
| | "type": "function" | "call_id": "call_t885uulopdd499rn0pioze7l", | \
| | } | "name": "get_weather", | \
| | ] | "type": "function_call", | \
| | } | "id": "fc_02176612670345400000000000000000000ffffac154e10a6753e", | \
| | } | "status": "completed" | \
| | ], | } | \
| | ... | ], | \
| | } | .... | \
| |``` | } | \
| | |``` | \
| |**第二轮请求:回传完整上下文并生成最终响应** | | \
| |下面示例是在第一轮请求的基础上,回传思考内容加密原文(**encrypted_content**)和思考内容摘要(**reasoning_content**)、工具调用结果,模型生成自然语言回答。 |**第二轮请求:回传结果并生成最终响应** | \
| | |传入上一轮 response_id、工具调用结果等信息,模型生成自然语言回答。 | \
| |```Bash | | \
| |curl https://ark.cn-beijing.volces.com/api/v3/chat/completions \ |```Bash | \
| | -H "Content-Type: application/json" \ |curl https://ark.cn-beijing.volces.com/api/v3/responses \ | \
| | -H "Authorization: Bearer $ARK_API_KEY" \ | -H "Authorization: Bearer $ARK_API_KEY" \ | \
| | -d '{ | -H "Content-Type: application/json" \ | \
| | "model": "doubao-seed-2-0-lite-260215", | -d '{ | \
| | "messages": [ | "model": "doubao-seed-2-0-lite-260215", | \
| | { | "input": [ | \
| | "role": "system", | { | \
| | "content": "你是人工智能助手。" | "type": "function_call_output", | \
| | | "call_id": "call_t885uulopdd499rn0pioze7l", | \
| | }, | "output": "5度" | \
| | { | | \
| | "role": "user", | } | \
| | "content": "今天北京天气怎么样" | ], | \
| | | "previous_response_id": "resp_0217661267019147d8950efa0e2f7c9d9cc7a1cc971272cf4548c", | \
| | }, | "thinking":{"type": "enabled"}, | \
| | { | "tools": [ | \
| | "reasoning_content": "北京天气查询将由我调用相关工具完成。\n", | { | \
| | | "type": "function", | \
| | "encrypted_content": "djF+2EICEj3ryfEfSUdR/SmS8OeEH4znOYftL4SWDXR8uxROjx11W7rRCj5ArLwzsm7rFsO4frOdLm2p3/yWz/r0TMqrjHiaTTvRMNdV6sLdETySlb3PDgY1W+zuYuETiq3bQuxga5jKx+GpfvlDJMfJfzq/G1kDp6ryurs0rKAFIziyc4mfFSh2CzDKNcAcp5Fi5R7M2QrSYmIUJjnoB48IVUCzu4xn7bT05qheVnGO9fbs15gYK3zINUvVsp51Oq72U/ksrPZFVs2BTgNRwjmxnFNn7A==", | "name": "get_weather", | \
| | "role": "assistant", | "description": "天气查询", | \
| | "tool_calls": [ | | \
| | { | "parameters": { | \
| | "function": { | "type": "object", | \
| | "arguments": " {\"location\": \"北京\"}", | "properties": { | \
| | | "location": { | \
| | "name": "get_weather" | "type": "string", | \
| | }, | "description": "地点的位置信息,例如北京、上海。" | \
| | "id": "call_wiezxeyae8jzxl3jx8nhfgb5", | | \
| | "type": "function" | } | \
| | } | }, | \
| | ] | "required": ["location"] | \
| | }, | } | \
| | { | } | \
| | "role": "tool", | ] | \
| | "tool_call_id":"call_wiezxeyae8jzxl3jx8nhfgb5", | }' | \
| | "content": "5度" |``` | \
| | | | \
| | } | | \
| | ], | | \
| | "thinking":{"type": "enabled"}, | | \
| | "tools": [ | | \
| | { | | \
| | "type": "function", | | \
| | "function": { | | \
| | "name": "get_weather", | | \
| | "description": "天气查询", | | \
| | | | \
| | "parameters": { | | \
| | "properties": { | | \
| | "location": { | | \
| | "description": "地点的位置信息,例如北京、上海。", | | \
| | | | \
| | "type": "string" | | \
| | } | | \
| | }, | | \
| | "required": [ | | \
| | "location" | | \
| | ], | | \
| | "type": "object" | | \
| | } | | \
| | } | | \
| | } | | \
| | ] | | \
| | }' | | \
| |``` | |
### 回传原始思考内容
部分模型开启深度思考后,默认输出模型原始的思考内容。以下是在工具调用场景,回传原始思考内容的示例。
|API |[Chat API](/docs/chat-api) |[Responses API](/docs/create-model-responses-api) |
| --- | --- | --- |
|支持模型 |* doubao-seed-2-0-lite-260428 |* doubao-seed-2-0-lite-260428 | \
| |* doubao-seed-2-0-mini-260428 |* doubao-seed-2-0-mini-260428 | \
| |* doubao-seed-2-0-pro-260215 |* doubao-seed-2-0-pro-260215 | \
| |* doubao-seed-2-0-lite-260215 |* doubao-seed-2-0-lite-260215 | \
| |* doubao-seed-2-0-mini-260215 |* doubao-seed-2-0-mini-260215 | \
| |* doubao-seed-2-0-code-preview-260215 |* doubao-seed-2-0-code-preview-260215 | \
| |* deepseek-v4-pro-260425 |* deepseek-v4-pro-260425 | \
| |* deepseek-v4-flash-ga-260731 |* deepseek-v4-flash-ga-260731 | \
| |* deepseek-v4-1-flash-261017
* deepseek-v4-1-flash-260910
* deepseek-v4-1-flash-economy-261017 |* deepseek-v4-1-flash-261017
* deepseek-v4-1-flash-260910
* deepseek-v4-1-flash-economy-261017 | \
| |* glm-5-2-260617 |* glm-5-2-260617 |
|示例 |**第一轮请求:触发工具调用** |**第一轮请求:触发工具调用** | \
| | | | \
| |```Bash |```Bash | \
| |curl https://ark.cn-beijing.volces.com/api/v3/chat/completions \ |curl https://ark.cn-beijing.volces.com/api/v3/responses \ | \
| | -H "Content-Type: application/json" \ | -H "Authorization: Bearer $ARK_API_KEY" \ | \
| | -H "Authorization: Bearer $ARK_API_KEY" \ | -H "Content-Type: application/json" \ | \
| | -d '{ | -d '{ | \
| | "model": "doubao-seed-2-0-lite-260215", | "model": "doubao-seed-2-0-lite-260215", | \
| | "messages": [ | "input": [ | \
| | { | { | \
| | "role": "system", | "role": "system", | \
| | "content": "你是人工智能助手。" | "content": "你是人工智能助手." | \
| | | | \
| | }, | }, | \
| | { | { | \
| | "role": "user", | "role": "user", | \
| | "content": "今天北京天气怎么样" | "content": "今天北京天气怎么样" | \
| | | | \
| | } | } | \
| | ], | ], | \
| | "thinking":{"type": "enabled"}, | "thinking":{"type": "enabled"}, | \
| | "tools": [ | "tools": [ | \
| | { | { | \
| | "type": "function", | "type": "function", | \
| | "function": { | "name": "get_weather", | \
| | "name": "get_weather", | "description": "天气查询", | \
| | "description": "天气查询", | | \
| | | "parameters": { | \
| | "parameters": { | "type": "object", | \
| | "properties": { | "properties": { | \
| | "location": { | "location": { | \
| | "description": "地点的位置信息,例如北京、上海。", | "type": "string", | \
| | | "description": "地点的位置信息,例如北京、上海。" | \
| | "type": "string" | | \
| | } | } | \
| | }, | }, | \
| | "required": [ | "required": ["location"] | \
| | "location" | } | \
| | ], | } | \
| | "type": "object" | ] | \
| | } | }' | \
| | } |``` | \
| | } | | \
| | ] |**第一轮响应:返回工具调用指令** | \
| | }' |模型返回信息包含`id`、`call_id`、`arguments`等关键字段。 | \
| |``` | | \
| | |```Bash | \
| |**第一轮响应:返回工具调用指令** |{ | \
| |模型会返回`reasoning_content`、`tool_calls`等关键字段。 | "created_at": 1766126702, | \
| | | "id": "resp_0217661267019147d8950efa0e2f7c9d9cc7a1cc971272cf4548c", | \
| |```JSON | "max_output_tokens": 32768, | \
| |{ | "model": "doubao-seed-2-0-lite-260215", | \
| | "choices": [ | "object": "response", | \
| | { | "output": [ | \
| | "finish_reason": "tool_calls", | { | \
| | "index": 0, | "id": "rs_02176612670248500000000000000000000ffffac154e10754f5c", | \
| | "logprobs": null, | "type": "reasoning", | \
| | "message": { | "summary": [ | \
| | "content": "", | { | \
| | "reasoning_content": "用户想查询今天北京的天气,这正好符合get_weather工具的功能,需要传入location参数为北京。所以我要调用这个工具来获取天气信息。", | "type": "summary_text", | \
| | | "text": "用户问今天北京的天气怎么样,我需要调用get_weather工具,参数location是北京。按照格式要求来写函数调用。" | \
| | "role": "assistant", | | \
| | "tool_calls": [ | } | \
| | { | ], | \
| | "function": { | "status": "completed" | \
| | "arguments": " {\"location\": \"北京\"}", | }, | \
| | | { | \
| | "name": "get_weather" | "arguments": " {\"location\": \"北京\"}", | \
| | }, | | \
| | "id": "call_wiezxeyae8jzxl3jx8nhfgb5", | "call_id": "call_t885uulopdd499rn0pioze7l", | \
| | "type": "function" | "name": "get_weather", | \
| | } | "type": "function_call", | \
| | ] | "id": "fc_02176612670345400000000000000000000ffffac154e10a6753e", | \
| | } | "status": "completed" | \
| | } | } | \
| | ], | ], | \
| | ... | .... | \
| | } | } | \
| |``` |``` | \
| | | | \
| |**第二轮请求:回传完整上下文并生成最终响应** |**第二轮请求:回传结果并生成最终响应** | \
| |在第一轮请求的基础上,还需要回传思维链信息、工具调用结果,模型生成自然语言回答。 |传入上一轮 response_id、工具调用结果等信息,模型生成自然语言回答。 | \
| | | | \
| |```Bash |```Bash | \
| |curl https://ark.cn-beijing.volces.com/api/v3/chat/completions \ |curl https://ark.cn-beijing.volces.com/api/v3/responses \ | \
| | -H "Content-Type: application/json" \ | -H "Authorization: Bearer $ARK_API_KEY" \ | \
| | -H "Authorization: Bearer $ARK_API_KEY" \ | -H "Content-Type: application/json" \ | \
| | -d '{ | -d '{ | \
| | "model": "doubao-seed-2-0-lite-260215", | "model": "doubao-seed-2-0-lite-260215", | \
| | "messages": [ | "input": [ | \
| | { | { | \
| | "role": "system", | "type": "function_call_output", | \
| | "content": "你是人工智能助手。" | "call_id": "call_t885uulopdd499rn0pioze7l", | \
| | | "output": "5度" | \
| | }, | | \
| | { | } | \
| | "role": "user", | ], | \
| | "content": "今天北京天气怎么样" | "previous_response_id": "resp_0217661267019147d8950efa0e2f7c9d9cc7a1cc971272cf4548c", | \
| | | "thinking":{"type": "enabled"}, | \
| | }, | "tools": [ | \
| | { | { | \
| | "reasoning_content": "用户想查询今天北京的天气,这正好符合get_weather工具的功能,需要传入location参数为北京。所以我要调用这个工具来获取天气信息。", | "type": "function", | \
| | | "name": "get_weather", | \
| | "role": "assistant", | "description": "天气查询", | \
| | "tool_calls": [ | | \
| | { | "parameters": { | \
| | "function": { | "type": "object", | \
| | "arguments": " {\"location\": \"北京\"}", | "properties": { | \
| | | "location": { | \
| | "name": "get_weather" | "type": "string", | \
| | }, | "description": "地点的位置信息,例如北京、上海。" | \
| | "id": "call_wiezxeyae8jzxl3jx8nhfgb5", | | \
| | "type": "function" | } | \
| | } | }, | \
| | ] | "required": ["location"] | \
| | }, | } | \
| | { | } | \
| | "role": "tool", | ] | \
| | "tool_call_id":"call_wiezxeyae8jzxl3jx8nhfgb5", | }' | \
| | "content": "5度" |``` | \
| | | | \
| | } | | \
| | ], | | \
| | "thinking":{"type": "enabled"}, | | \
| | "tools": [ | | \
| | { | | \
| | "type": "function", | | \
| | "function": { | | \
| | "name": "get_weather", | | \
| | "description": "天气查询", | | \
| | | | \
| | "parameters": { | | \
| | "properties": { | | \
| | "location": { | | \
| | "description": "地点的位置信息,例如北京、上海。", | | \
| | | | \
| | "type": "string" | | \
| | } | | \
| | }, | | \
| | "required": [ | | \
| | "location" | | \
| | ], | | \
| | "type": "object" | | \
| | } | | \
| | } | | \
| | } | | \
| | ] | | \
| | }' | | \
| |``` | |
# 使用说明
## 工作原理
* 多轮对话场景
|流程图 |说明 |
| --- | --- |
| |* 在每一轮对话过程中,深度思考模型会输出思维链内容(COT)和最终回答(Answer)。 | \
| |* 在下一轮对话中,之前输出的思维链内容不会被拼接到上下文中。 | \
| |> 思维链内容展现的是模型处理问题的过程,包括将问题拆分为多个问题进行处理,生成多种回复综合得出更好回答等过程。 |
* 工具调用场景
工具调用场景中开启深度思考后,为给出更详尽准确的回答,将不会直接丢弃思维链内容,历史轮次的思维链内容按需(模型自主判断)参与推理。在整个请求过程中,用户回传完整上下文即可,由服务端自行判断,是否保留思维链内容。未输入给模型的思维链内容,不会计算 token 用量。代码示例参见[回传思考内容](/docs/deep-thinking#3e8661f7)。
|流程图 |说明 |
| --- | --- |
| |* 回答问题 1 时(请求 1.1 - 1.2),模型进行多次思考 + 工具调用后给出答案,方舟会输入完整上下文包括思维链内容给模型处理。 | \
| |* 开始回答问题 2 时(请求 2.1),方舟会自行判断并删除之前上下文中的思维链,输入给模型。 |
## 减少请求超时失败
深度思考模型使用思维链输出内容,导致回复篇幅更长、速率更慢,所以极易因超时导致任务失败。尤其在非流式输出模式下,任务未完成时断开连接,未输出内容,又产生 token 用量费用。
可使用流式输出或设置更长超时时间,减少超时失败:
* 使用流式输出(推荐):通过分块即时返回生成内容,可有效维持连接活性(避免因长时无响应导致的连接中断),是高效且可靠的输出方式(示例代码及说明参见[流式输出](/docs/deep-thinking#4ad2b076))。若当前应用使用非流式输出,可改造为:通过流式接口获取内容,实时拼接完整结果后再统一输出,从而显著降低请求超时失败风险。
* 调大超时时间参数:非流式输出场景下,推荐将 `timeout` 参数设置为 30 分钟以上,并根据超时触发概率进一步调整超时时间。另需注意网络链路中的 TCP Keep-Alive 设置(`tcp_keepalive_time` 参数),避免因长时间无数据传输导致连接被系统、防火墙、路由器等中断。
> **方舟 Go SDK 特殊说明**:无论是否使用流式输出,均需将 SDK 超时参数设置为 30 分钟以上。
## 使用批量推理获得更高吞吐
当您的业务需要处理大量的数据,且对于模型返回及时性要求不高,您可使用批量推理获取最低 10B token/天的配额以及批量推理的成本降低。批量推理支持任务的方式以及类似 Chat 的接口调用方式,使用批量推理,详细说明请查看 [批量推理](/docs/batch-inference)。
## 提示词优化建议
深度思考模型会自行分析和拆解问题(思维链),与普通模型相比,提示词侧重点有所不同。
* 提示词除了待解决问题,应该更多补充目标和场景等信息。如使用英语,用 Python 等语言要求;面向小学生、向领导汇报等阅读对象信息;完成论文写作、完成课题报告、撰写剧本等场景信息;体现我的专业性、获得领导赏识等目标信息。
* 减少或者避免对问题的拆解描述,如分步骤思考、使用示例等,这样会限制住模型的推理逻辑。
* 减少使用系统提示词,所有提示词信息直接通过用户提示词(`role: user`)来提问。
# 常见问题
* [并发 RPM 或者 TPM 额度明明有剩余为什么提示限流报错?](/docs/modelark-faq#91505308)
---
# 上下文管理
Source: https://ark.volcengine.com/region:cn-beijing/docs/context-management
模型上下文(Context)包括输入信息(问题)和输出信息(回答),当触发深度思考时输出还包括思维链内容(CoT)。思维链内容展现模型处理问题的过程,包括将问题拆分为多个问题进行处理,生成多种回复综合得出更好回答的过程。在多轮对话中,上下文管理在保持话题一致性等方面非常重要,对此方舟提供了一些管理上下文的方法。
# 上下文输入
## 手动输入上下文
[Chat API](/docs/chat-api) 发起请求,是独立无状态的,需手动管理上下文。需通过交替排列 user 消息 与 assistant 消息,让模型在请求中获取之前对话信息。
**选项:Curl**
```Bash
curl https://ark.cn-beijing.volces.com/api/v3/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ARK_API_KEY" \
-d '{
"model": "doubao-seed-2-1-pro-260915",
"messages": [
{"role": "user", "content": "深度思考模型与非深度思考模型区别"},
{"role": "assistant", "content": "推理模型主要依靠逻辑、规则或概率等进行分析、推导和判断以得出结论或决策,非推理模型则是通过模式识别、统计分析或模拟等方式来实现数据描述、分类、聚类或生成等任务而不依赖显式逻辑推理。"},
{"role": "user", "content": "我要研究深度思考模型与非深度思考模型区别的课题,怎么体现我的专业性"}
]
}'
```
* 您可按需替换 Model ID。Model ID 查询见 [模型列表](/docs/model-list)。
**选项:Python**
```Python
import os
# Install SDK: python -m pip install --upgrade arkruntime
from arkruntime import Ark
client = Ark(
# The base URL for model invocation
base_url="https://ark.cn-beijing.volces.com/api/v3",
# Get API Key: https://ark.volcengine.com/region:cn-beijing/apikey
api_key=os.getenv('ARK_API_KEY'),
# Deep thinking takes longer; set a larger timeout, with 1,800 seconds or more recommended
timeout=1800,
)
# 创建一个对话请求
completion = client.chat.completions.create(
# Replace with Model ID
model = "doubao-seed-2-1-pro-260915",
messages=[
{"role": "user", "content": "研究深度思考模型与非深度思考模型区别"},
{"role": "assistant", "content": "推理模型主要依靠逻辑、规则或概率等进行分析、推导和判断以得出结论或决策,非推理模型则是通过模式识别、统计分析或模拟等方式来实现数据描述、分类、聚类或生成等任务而不依赖显式逻辑推理。"},
{"role": "user", "content": "我要研究深度思考模型与非深度思考模型区别的课题,怎么体现我的专业性"},
],
)
if hasattr(completion.choices[0].message, 'reasoning_content'):
print(completion.choices[0].message.reasoning_content)
print(completion.choices[0].message.content)
```
**选项:Go**
```Go
package main
import (
"context"
"fmt"
"os"
"time"
"github.com/volcengine/ark-runtime-go/arkruntime"
"github.com/volcengine/ark-runtime-go/arkruntime/model/chat"
)
func main() {
client := arkruntime.NewClientWithApiKey(
//通过 os.Getenv 从环境变量中获取 ARK_API_KEY
os.Getenv("ARK_API_KEY"),
// The base URL for model invocation
arkruntime.WithBaseUrl("https://ark.cn-beijing.volces.com/api/v3"),
//深度思考耗时更长,请设置更大的超时限制,推荐为30分钟及以上
arkruntime.WithTimeout(30*time.Minute),
)
// 创建一个上下文,通常用于传递请求的上下文信息,如超时、取消等
ctx := context.Background()
// 构建聊天完成请求,设置请求的模型和消息内容
req := &chat.ChatCompletionRequest{
// Replace with Model ID
Model: "doubao-seed-2-1-pro-260915",
Messages: []chat.ChatCompletionRequestMessage{
userMessage("研究深度思考模型与非深度思考模型区别"),
assistantMessage("推理模型主要依靠逻辑、规则或概率等进行分析、推导和判断以得出结论或决策,非推理模型则是通过模式识别、统计分析或模拟等方式来实现数据描述、分类、聚类或生成等任务而不依赖显式逻辑推理。"),
userMessage("我要研究深度思考模型与非深度思考模型区别的课题,怎么体现我的专业性"),
},
}
// 发送聊天完成请求,并将结果存储在 resp 中,将可能出现的错误存储在 err 中
resp, err := client.CreateChatCompletion(ctx, req)
if err != nil {
// 若出现错误,打印错误信息并终止程序
fmt.Printf("standard chat error: %v\n", err)
return
}
// 检查是否触发深度思考,触发则打印思维链内容
if resp.Choices[0].Message.ReasoningContent.IsSet() {
fmt.Println(resp.Choices[0].Message.ReasoningContent.Or(""))
}
// 打印聊天完成请求的响应结果
fmt.Println(resp.Choices[0].Message.Content)
}
func assistantMessage(content string) chat.ChatCompletionRequestMessage {
return chat.ChatCompletionRequestMessage{
OneOf: chat.NewChatCompletionRequestAssistantMessageChatCompletionRequestMessageSum(
chat.ChatCompletionRequestAssistantMessage{
Role: chat.ChatCompletionRequestAssistantMessageRoleAssistant,
Content: chat.NewOptNilChatCompletionMessageContent(chat.NewStringChatCompletionMessageContent(content)),
},
),
}
}
func userMessage(content string) chat.ChatCompletionRequestMessage {
return chat.ChatCompletionRequestMessage{
OneOf: chat.NewChatCompletionRequestUserMessageChatCompletionRequestMessageSum(
chat.ChatCompletionRequestUserMessage{
Role: chat.ChatCompletionRequestUserMessageRoleUser,
Content: chat.NewOptNilChatCompletionMessageContent(chat.NewStringChatCompletionMessageContent(content)),
},
),
}
}
```
**选项:Java**
```Java
package com.volcengine.ark.runtime;
import com.volcengine.ark.runtime.models.chat.*;
import com.volcengine.ark.runtime.service.ArkService;
import java.time.Duration;
import java.util.Arrays;
import java.util.List;
/**
* 这是一个示例类,展示了如何使用ArkService来完成聊天功能。
*/
public class ChatCompletionsExample {
public static void main(String[] args) {
// 从环境变量中获取API密钥
String apiKey = System.getenv("ARK_API_KEY");
// 创建ArkService实例
ArkService arkService = ArkService.builder()
.apiKey(apiKey)
.timeout(Duration.ofMinutes(30))// 深度思考耗时更长,请设置更大的超时限制,推荐为30分钟及以上
// The base URL for model invocation
.baseUrl("https://ark.cn-beijing.volces.com/api/v3")
.build();
// 多轮消息列表
final List messages = Arrays.asList(
ChatCompletionRequestUserMessage.builder().role(ChatCompletionRequestMessageType.USER).content(ChatCompletionMessageContent.ofString("研究深度思考模型与非深度思考模型区别")).build(),
ChatCompletionRequestAssistantMessage.builder().role(ChatCompletionRequestMessageType.ASSISTANT).content(ChatCompletionMessageContent.ofString("推理模型主要依靠逻辑、规则或概率等进行分析、推导和判断以得出结论或决策,非推理模型则是通过模式识别、统计分析或模拟等方式来实现数据描述、分类、聚类或生成等任务而不依赖显式逻辑推理。")).build(),
ChatCompletionRequestUserMessage.builder().role(ChatCompletionRequestMessageType.USER).content(ChatCompletionMessageContent.ofString("我要研究深度思考模型与非深度思考模型区别的课题,怎么体现我的专业性")).build()
);
// 创建聊天完成请求
ChatCompletionRequest chatCompletionRequest = ChatCompletionRequest.builder()
.model("doubao-seed-2-1-pro-260915")//Replace with Model ID
.messages(messages) // 设置消息列表
.build();
// 发送聊天完成请求并打印响应
try {
// 获取响应并打印每个选择的消息内容
arkService.createChatCompletion(chatCompletionRequest)
.getChoices()
.forEach(choice -> {
// 进行空值检查后打印推理内容
if (choice.getMessage().getReasoningContent() != null) {
System.out.println("推理内容: " + choice.getMessage().getReasoningContent());
} else {
System.out.println("推理内容为空");
}
// 打印消息内容
System.out.println("消息内容: " + choice.getMessage().getContent());
});
} catch (Exception e) {
System.out.println("请求失败: " + e.getMessage());
} finally {
// 关闭服务执行器
arkService.shutdownExecutor();
}
}
}
```
**选项:OpenAI SDK**
```Python
import os
from openai import OpenAI
client = OpenAI(
# 从环境变量中读取方舟API Key
api_key=os.environ.get("ARK_API_KEY"),
base_url="https://ark.cn-beijing.volces.com/api/v3",
# 深度思考耗时更长,避免链接超时导致失败,请设置更大的超时限制,推荐为1800 秒及以上
timeout=1800,
)
completion = client.chat.completions.create(
# Replace with Model ID
model = "doubao-seed-2-1-pro-260915",
messages=[
{"role": "user", "content": "研究深度思考模型与非深度思考模型区别"},
{"role": "assistant", "content": "推理模型主要依靠逻辑、规则或概率等进行分析、推导和判断以得出结论或决策,非推理模型则是通过模式识别、统计分析或模拟等方式来实现数据描述、分类、聚类或生成等任务而不依赖显式逻辑推理。"},
{"role": "user", "content": "我要研究深度思考模型与非深度思考模型区别的课题,怎么体现我的专业性"},
],
)
if hasattr(completion.choices[0].message, 'reasoning_content'):
print(completion.choices[0].message.reasoning_content)
print(completion.choices[0].message.content)
```
## 通过 ID 输入上下文
[Responses API](/docs/create-model-responses-api) 支持更简洁方式管理上下文。默认情况下请求的输入和输出都会持久化存储,后续请求只需传入 ID 就可以引入对应请求的输入和输出。
**选项:Curl**
```Bash
curl https://ark.cn-beijing.volces.com/api/v3/responses \
-H "Authorization: Bearer $ARK_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "doubao-seed-2-1-pro-260915",
"input": "Hi,讲个笑话。"
}'
```
```Bash
curl https://ark.cn-beijing.volces.com/api/v3/responses \
-H "Authorization: Bearer $ARK_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "doubao-seed-2-1-pro-260915",
"previous_response_id":"",
"input": "这个笑话的笑点在哪?"
}'
```
第二次请求需将 curl 命令中的 `` 替换为上一次请求返回的 Response id。
**选项:Python**
```Python
import os
from arkruntime import Ark
# Get API Key: https://ark.volcengine.com/region:cn-beijing/apikey
api_key = os.getenv('ARK_API_KEY')
client = Ark(
base_url='https://ark.cn-beijing.volces.com/api/v3',
api_key=api_key,
)
# Create the first-round conversation request
response = client.responses.create(
model="doubao-seed-2-1-pro-260915",
input="Hi,帮我讲个笑话。"
)
print(response)
# Create the second-round conversation request
second_response = client.responses.create(
model="doubao-seed-2-1-pro-260915",
previous_response_id=response.id,
input=[{"role": "user", "content": "这个笑话的笑点在哪?"}],
)
print(second_response)
```
**选项:Go**
```Go
package main
import (
"context"
"fmt"
"os"
"github.com/volcengine/ark-runtime-go/arkruntime"
"github.com/volcengine/ark-runtime-go/arkruntime/model/responses"
)
func main() {
client := arkruntime.NewClientWithApiKey(
// Get API Key: https://ark.volcengine.com/region:cn-beijing/apikey
os.Getenv("ARK_API_KEY"),
arkruntime.WithBaseUrl("https://ark.cn-beijing.volces.com/api/v3"),
)
ctx := context.Background()
// Create the first-round conversation request
resp, err := client.CreateResponses(ctx, &responses.ResponsesRequest{
Model: "doubao-seed-2-1-pro-260915",
Input: responses.NewStringResponsesInput("Hi,讲个笑话。"),
Store: responses.NewOptBool(true),
})
if err != nil {
fmt.Printf("response error: %v\n", err)
return
}
fmt.Println(resp)
id := resp.ID
inputMessage := easyMessage(responses.MessageRoleUser, "这个笑话的笑点在哪?")
fmt.Println("-----------------")
// Create the second-round conversation request
second_resp, second_err := client.CreateResponses(ctx, &responses.ResponsesRequest{
Model: "doubao-seed-2-1-pro-260915",
PreviousResponseID: responses.NewOptString(id),
Input: responses.NewInputItemArrayResponsesInput([]responses.InputItem{
inputMessage,
}),
})
if second_err != nil {
fmt.Printf("second response error: %v\n", second_err)
return
}
fmt.Println(second_resp)
}
func easyMessage(role responses.MessageRole, content string) responses.InputItem {
return responses.InputItem{
OneOf: responses.NewItemEasyMessageInputItemSum(
responses.ItemEasyMessage{
Role: responses.NewOptMessageRole(role),
Content: responses.NewStringMessageContent(content),
},
),
}
}
```
**选项:Java**
```Java
package com.ark.example;
import com.volcengine.ark.runtime.service.ArkService;
import com.volcengine.ark.runtime.models.responses.*;
public class demo {
public static void main(String[] args) {
String apiKey = System.getenv("ARK_API_KEY");
// The base URL for model invocation
ArkService arkService = ArkService.builder().apiKey(apiKey)
.baseUrl("https://ark.cn-beijing.volces.com/api/v3")
.build();
// Create the first-round conversation request
ResponsesRequest request = ResponsesRequest.builder()
.model("doubao-seed-2-1-pro-260915")
.input(ResponsesInput.ofString("Hi,帮我讲个笑话。"))
.build();
Response resp = arkService.createResponse(request);
System.out.println(resp);
// Create the second-round conversation request
ResponsesRequest request2 = ResponsesRequest.builder()
.model("doubao-seed-2-1-pro-260915")
.previousResponseId(resp.getId())
.input(ResponsesInput.ofList(java.util.Arrays.asList(ItemEasyMessage.builder().role(MessageRole.USER).content(
MessageContent.ofString("这个笑话的笑点在哪?")
).build())))
.build();
Response resp2 = arkService.createResponse(request2);
System.out.println(resp2);
arkService.shutdownExecutor();
}
}
```
**选项:OpenAI SDK**
```Python
from openai import OpenAI
import os
# Get API Key: https://ark.volcengine.com/region:cn-beijing/apikey
api_key = os.getenv('ARK_API_KEY')
client = OpenAI(
base_url='https://ark.cn-beijing.volces.com/api/v3',
api_key=api_key,
)
# Create the first-round conversation request
response = client.responses.create(
model="doubao-seed-2-1-pro-260915",
input="Hi,帮我讲个笑话。"
)
print(response)
# Create the second-round conversation request
second_response = client.responses.create(
model="doubao-seed-2-1-pro-260915",
previous_response_id=response.id,
input=[{"role": "user", "content": "这个笑话的笑点在哪?"}],
)
print(second_response)
```
# 上下文长度控制
输入长内容,或对话轮数增加,需同时考虑模型输出长度和上下文窗口限制。模型输入和输出会进行计量,达到长度限制会截断或报错。合理控制模型输出长度,平衡业务效果、成本与稳定性:
* 减少触发限流(TPM 限制、突发流量限制等),保障服务稳定性。
* 精确控制 token 用量,平衡成本与质量。
* 控制推理耗时,提升用户交互体验。
同时,平台支持对模型输出(思维链、回答)长度控制,来控制 token 用量。核心规格及参数,如下图:

> 不同模型支持的上下文窗口、最大输入、最大思维链长度均有差异,可在 [模型列表](/docs/model-list) 查询。
## 控制输出(回答+思维链)长度
[Chat API](/docs/chat-api) 使用 **max_completion_tokens** 字段,控制模型输出长度,当模型输出达到配置值时,模型停止推理。
> [Responses API](/docs/create-model-responses-api) 使用 max_output_tokens 字段 控制模型输出长度,详细信息参见 [设置最大输出长度](/docs/responses-api-deep-thinking#1460ba95)。
支持的模型:250528及之后版本的大语言模型,如无特殊说明,默认支持该字段。方舟平台大语言模型列表,请参见[文本生成能力](/docs/model-list#32e9e053)。
> doubao-seed-translation-250915 模型不支持该字段。
**选项:Curl**
```Bash
curl https://ark.cn-beijing.volces.com/api/v3/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ARK_API_KEY" \
-d '{
"model": "doubao-seed-2-1-pro-260915",
"messages": [
{
"role": "user",
"content": "你好"
}
],
"max_completion_tokens": 1024
}'
```
* 您可按需替换 Model ID。Model ID 查询见 [模型列表](/docs/model-list)。
**选项:Python**
```Python
import os
# Install SDK: python -m pip install --upgrade arkruntime
from arkruntime import Ark
client = Ark(
# The base URL for model invocation
base_url="https://ark.cn-beijing.volces.com/api/v3",
# Get API Key: https://ark.volcengine.com/region:cn-beijing/apikey
api_key=os.getenv('ARK_API_KEY'),
# Deep thinking takes longer; set a larger timeout, with 1,800 seconds or more recommended
timeout=1800,
)
# 创建一个对话请求
completion = client.chat.completions.create(
# Replace with Model ID
model = "doubao-seed-2-1-pro-260915",
messages=[
{"role": "system", "content": "你是 AI 人工智能助手"},
{"role": "user", "content": "常见的十字花科植物有哪些?"},
],
# 设置模型最大输出长度为 1024 token,按需调整
max_completion_tokens = 1024,
)
print(completion.choices[0].message.content)
```
**选项:Go**
```Go
package main
import (
"time"
"context"
"fmt"
"os"
"github.com/volcengine/ark-runtime-go/arkruntime"
"github.com/volcengine/ark-runtime-go/arkruntime/model/chat"
)
func main() {
client := arkruntime.NewClientWithApiKey(
os.Getenv("ARK_API_KEY"),
// The base URL for model invocation
arkruntime.WithBaseUrl("https://ark.cn-beijing.volces.com/api/v3"),
//深度思考耗时更长,请设置更大的超时限制,推荐为30分钟及以上
arkruntime.WithTimeout(30*time.Minute),
)
ctx := context.Background()
fmt.Println("----- standard request -----")
req := &chat.ChatCompletionRequest{
// Replace with Model ID
Model: "doubao-seed-2-1-pro-260915",
Messages: []chat.ChatCompletionRequestMessage{
systemMessage("你是 AI 人工智能助手"),
userMessage("常见的十字花科植物有哪些?"),
},
MaxCompletionTokens: chat.NewOptInt32(int32(1024)), // 设置最大输出长度为 1024 token
}
resp, err := client.CreateChatCompletion(ctx, req)
if err != nil {
fmt.Printf("standard chat error: %v\n", err)
return
}
fmt.Println(resp.Choices[0].Message.Content)
}
func systemMessage(content string) chat.ChatCompletionRequestMessage {
return chat.ChatCompletionRequestMessage{
OneOf: chat.NewChatCompletionRequestSystemMessageChatCompletionRequestMessageSum(
chat.ChatCompletionRequestSystemMessage{
Role: chat.ChatCompletionRequestSystemMessageRoleSystem,
Content: chat.NewStringChatCompletionMessageContent(content),
},
),
}
}
func userMessage(content string) chat.ChatCompletionRequestMessage {
return chat.ChatCompletionRequestMessage{
OneOf: chat.NewChatCompletionRequestUserMessageChatCompletionRequestMessageSum(
chat.ChatCompletionRequestUserMessage{
Role: chat.ChatCompletionRequestUserMessageRoleUser,
Content: chat.NewOptNilChatCompletionMessageContent(chat.NewStringChatCompletionMessageContent(content)),
},
),
}
}
```
**选项:Java**
```Java
package com.volcengine.ark.runtime;
import com.volcengine.ark.runtime.models.chat.*;
import com.volcengine.ark.runtime.service.ArkService;
import java.util.ArrayList;
import java.util.List;
import java.time.Duration;
public class ChatCompletionsExample {
public static void main(String[] args) {
String apiKey = System.getenv("ARK_API_KEY");
// 创建ArkService实例
ArkService arkService = ArkService.builder()
.apiKey(apiKey)
.timeout(Duration.ofMinutes(30))// 深度思考耗时更长,请设置更大的超时限制,推荐为30分钟及以上
// The base URL for model invocation
.baseUrl("https://ark.cn-beijing.volces.com/api/v3")
.build();
System.out.println("\n----- standard request -----");
final List messages = new ArrayList<>();
final ChatCompletionRequestMessage systemMessage = ChatCompletionRequestSystemMessage.builder().role(ChatCompletionRequestMessageType.SYSTEM).content(ChatCompletionMessageContent.ofString("你是 AI 人工智能助手")).build();
final ChatCompletionRequestMessage userMessage = ChatCompletionRequestUserMessage.builder().role(ChatCompletionRequestMessageType.USER).content(ChatCompletionMessageContent.ofString("常见的十字花科植物有哪些?")).build();
messages.add(systemMessage);
messages.add(userMessage);
ChatCompletionRequest chatCompletionRequest = ChatCompletionRequest.builder()
.model("doubao-seed-2-1-pro-260915")//Replace with Model ID
.messages(messages)
.maxCompletionTokens(1024)// 设置最大输出长度为 1024 token
.build();
arkService.createChatCompletion(chatCompletionRequest).getChoices().forEach(choice -> System.out.println(choice.getMessage().getContent()));
// shutdown service
arkService.shutdownExecutor();
}
}
```
> **说明**
>
> * **max_tokens**、**max_completion_tokens** 不可同时设置,会直接报错。
## 控制回答长度
[Chat API](/docs/chat-api) 可通过设置 **max_tokens** 字段,控制模型回答长度。当回答长度达到配置值时,模型停止推理。
> **注意**
>
> DeepSeek-V4.1-flash 模型`max_tokens`:控制模型回答和模型思维链内容长度,超出长度后不报错,默认值 128k。
**选项:Curl**
```Bash
curl https://ark.cn-beijing.volces.com/api/v3/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ARK_API_KEY" \
-d '{
"model": "doubao-seed-2-1-pro-260915",
"messages": [
{
"role": "user",
"content": "你好"
}
],
"max_tokens": 1024
}'
```
* 按需替换 Model ID,查询 Model ID 请参见 [模型列表](/docs/model-list)。
**选项:Python**
```Python
import os
# Install SDK: python -m pip install --upgrade arkruntime
from arkruntime import Ark
# 初始化Ark客户端
client = Ark(
# The base URL for model invocation
base_url="https://ark.cn-beijing.volces.com/api/v3",
# Get API Key: https://ark.volcengine.com/region:cn-beijing/apikey
api_key=os.getenv('ARK_API_KEY'),
)
completion = client.chat.completions.create(
# Replace with Model ID
model = "doubao-seed-2-1-pro-260915",
messages=[
{"role": "system", "content": "你是 AI 人工智能助手"},
{"role": "user", "content": "常见的十字花科植物有哪些?"},
],
# 设置模型最大输出长度为 1024 token,您可按需进行调整
max_tokens=1024,
)
print(completion.choices[0].message.content)
```
**选项:Go**
```Go
package main
import (
"context"
"fmt"
"github.com/volcengine/ark-runtime-go/arkruntime"
"github.com/volcengine/ark-runtime-go/arkruntime/model/chat"
"os"
)
func main() {
client := arkruntime.NewClientWithApiKey(
os.Getenv("ARK_API_KEY"),
// The base URL for model invocation
arkruntime.WithBaseUrl("https://ark.cn-beijing.volces.com/api/v3"),
)
ctx := context.Background()
fmt.Println("----- standard request -----")
req := &chat.ChatCompletionRequest{
// Replace with Model ID
Model: "doubao-seed-2-1-pro-260915",
Messages: []chat.ChatCompletionRequestMessage{
systemMessage("你是 AI 人工智能助手"),
userMessage("常见的十字花科植物有哪些?"),
},
MaxTokens: chat.NewOptInt32(1024),
}
resp, err := client.CreateChatCompletion(ctx, req)
if err != nil {
fmt.Printf("standard chat error: %v\n", err)
return
}
fmt.Println(resp.Choices[0].Message.Content)
}
func systemMessage(content string) chat.ChatCompletionRequestMessage {
return chat.ChatCompletionRequestMessage{
OneOf: chat.NewChatCompletionRequestSystemMessageChatCompletionRequestMessageSum(
chat.ChatCompletionRequestSystemMessage{
Role: chat.ChatCompletionRequestSystemMessageRoleSystem,
Content: chat.NewStringChatCompletionMessageContent(content),
},
),
}
}
func userMessage(content string) chat.ChatCompletionRequestMessage {
return chat.ChatCompletionRequestMessage{
OneOf: chat.NewChatCompletionRequestUserMessageChatCompletionRequestMessageSum(
chat.ChatCompletionRequestUserMessage{
Role: chat.ChatCompletionRequestUserMessageRoleUser,
Content: chat.NewOptNilChatCompletionMessageContent(chat.NewStringChatCompletionMessageContent(content)),
},
),
}
}
```
**选项:Java**
```Java
package com.ark.sample;
import com.volcengine.ark.runtime.models.chat.*;
import com.volcengine.ark.runtime.service.ArkService;
import java.util.ArrayList;
import java.util.List;
public class ChatCompletionsExample {
public static void main(String[] args) {
String apiKey = System.getenv("ARK_API_KEY");
// The base URL for model invocation
ArkService service = ArkService.builder().apiKey(apiKey)
.baseUrl("https://ark.cn-beijing.volces.com/api/v3")
.build();
System.out.println("----- standard request -----");
final List messages = new ArrayList<>();
final ChatCompletionRequestMessage systemMessage = ChatCompletionRequestSystemMessage.builder().role(ChatCompletionRequestMessageType.SYSTEM).content(ChatCompletionMessageContent.ofString("你是 AI 人工智能助手")).build();
final ChatCompletionRequestMessage userMessage = ChatCompletionRequestUserMessage.builder().role(ChatCompletionRequestMessageType.USER).content(ChatCompletionMessageContent.ofString("常见的十字花科植物有哪些?")).build();
messages.add(systemMessage);
messages.add(userMessage);
ChatCompletionRequest chatCompletionRequest = ChatCompletionRequest.builder()
.model("doubao-seed-2-1-pro-260915")//Replace with Model ID
.messages(messages)
.maxTokens(1024)// 设置最大输出长度为 1024 token
.build();
service.createChatCompletion(chatCompletionRequest).getChoices().forEach(choice -> System.out.println(choice.getMessage().getContent()));
// shutdown service
service.shutdownExecutor();
}
}
```
> **说明**
>
> * **max_tokens**、**max_completion_tokens** 不可同时设置,会直接报错。
> * [Responses API](/docs/create-model-responses-api) 不支持 **max_tokens** 字段。
## 控制思维链长度
设置 **reasoning_effort** 调节深度思考的程度,间接控制思维链内容长度。当前提供 7 档:
* `none`:关闭思考。
* `minimal`:关闭思考,直接回答。
* `low`:轻量思考,侧重快速响应。
* `medium`:均衡模式,兼顾速度与深度。
* `high`:深度分析,处理复杂问题。
* `xhigh`:更高强度思考。
* `max`:最高强度思考,适配高难度推理任务。
与 **thinking.type** 关系:
* **thinking.type**取值为`enabled`:支持配置**reasoning_effort**。当**reasoning_effort**取值为`minimal`时,则关闭思考,直接回答。
* **thinking.type**取值为`disabled`:**reasoning_effort**仅支持取值`minimal`。当**reasoning_effort**取值为其他取值时会报错。
**选项:Curl**
```Bash
curl https://ark.cn-beijing.volces.com/api/v3/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ARK_API_KEY" \
-d '{
"model": "doubao-seed-2-1-pro-260915",
"messages": [
{
"role": "user",
"content": [
{
"image_url": {
"url": "https://arkdocs.tos-cn-beijing.volces.com/images/advanced-usage/view.jpeg"
},
"type": "image_url"
},
{
"text": "图片主要讲了什么?",
"type": "text"
}
]
}
],
"thinking":{"type":"enabled"},
"reasoning_effort": "low"
}'
```
**选项:Python**
```Python
import os
# Install SDK: python -m pip install --upgrade arkruntime
from arkruntime import Ark
client = Ark(
# The base URL for model invocation
base_url="https://ark.cn-beijing.volces.com/api/v3",
# Get API Key: https://ark.volcengine.com/region:cn-beijing/apikey
api_key=os.getenv('ARK_API_KEY'),
# Deep thinking takes longer; set a larger timeout, with 1,800 seconds or more recommended
timeout=1800,
)
completion = client.chat.completions.create(
# Replace with Model ID .
model = "doubao-seed-2-1-pro-260915",
messages=[
{
"role": "user",
"content": [
{"type": "image_url","image_url": {"url": "https://arkdocs.tos-cn-beijing.volces.com/images/advanced-usage/view.jpeg"}},
{"type": "text", "text": "图片主要讲了什么?"},
],
}
],
thinking={"type":"enabled"},
reasoning_effort="low"
)
print(completion.choices[0])
```
**选项:Go**
```Go
package main
import (
"context"
"fmt"
"os"
"github.com/volcengine/ark-runtime-go/arkruntime"
"github.com/volcengine/ark-runtime-go/arkruntime/model/chat"
)
func main() {
client := arkruntime.NewClientWithApiKey(
//通过 os.Getenv 从环境变量中获取 ARK_API_KEY
os.Getenv("ARK_API_KEY"),
// The base URL for model invocation .
arkruntime.WithBaseUrl("https://ark.cn-beijing.volces.com/api/v3"),
)
// 创建一个上下文,通常用于传递请求的上下文信息,如超时、取消等
ctx := context.Background()
contentParts := []chat.ChatCompletionContentPart{
chat.ChatCompletionContentPart{OneOf: chat.NewChatCompletionContentPartImageChatCompletionContentPartSum(chat.ChatCompletionContentPartImage{Type: chat.ChatCompletionContentPartImageTypeImageURL, ImageURL: chat.NewChatCompletionContentPartImageImageUrlChatCompletionContentPartImageImageURL(chat.ChatCompletionContentPartImageImageUrl{URL: chat.NewOptString("https://arkdocs.tos-cn-beijing.volces.com/images/advanced-usage/view.jpeg")})})},
chat.ChatCompletionContentPart{OneOf: chat.NewChatCompletionContentPartTextChatCompletionContentPartSum(chat.ChatCompletionContentPartText{Type: chat.ChatCompletionContentPartTextTypeText, Text: "图片主要讲了什么?"})},
}
effort := chat.ReasoningEffortLow
req := &chat.ChatCompletionRequest{
// Replace with Model ID
Model: "doubao-seed-2-1-pro-260915",
Messages: []chat.ChatCompletionRequestMessage{
chat.ChatCompletionRequestMessage{OneOf: chat.NewChatCompletionRequestUserMessageChatCompletionRequestMessageSum(chat.ChatCompletionRequestUserMessage{Role: chat.ChatCompletionRequestUserMessageRoleUser, Content: chat.NewOptNilChatCompletionMessageContent(chat.NewChatCompletionContentPartArrayChatCompletionMessageContent(contentParts))})},
},
Thinking: chat.NewOptThinking(chat.Thinking{Type: chat.NewOptThinkingMode(chat.ThinkingModeEnabled)}),
ReasoningEffort: chat.NewOptReasoningEffort(effort),
}
// 发送聊天完成请求,并将结果存储在 resp 中,将可能出现的错误存储在 err 中
resp, err := client.CreateChatCompletion(ctx, req)
if err != nil {
// 若出现错误,打印错误信息并终止程序
fmt.Printf("standard chat error: %v\n", err)
return
}
// 打印聊天完成请求的响应结果
fmt.Println(resp.Choices[0].Message.Content)
}
```
**选项:Java**
```Java
package com.ark.sample;
import com.volcengine.ark.runtime.models.chat.*;
import com.volcengine.ark.runtime.models.chat.ChatCompletionContentPart.*;
import com.volcengine.ark.runtime.service.ArkService;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import okhttp3.ConnectionPool;
import okhttp3.Dispatcher;
public class MultiImageSample {
static String apiKey = System.getenv("ARK_API_KEY");
static ConnectionPool connectionPool = new ConnectionPool(5, 1, TimeUnit.SECONDS);
static Dispatcher dispatcher = new Dispatcher();
static ArkService arkService = ArkService.builder()
.dispatcher(dispatcher)
.connectionPool(connectionPool)
.baseUrl("https://ark.cn-beijing.volces.com/api/v3")
// The base URL for model invocation .
.apiKey(apiKey)
.build();
public static void main(String[] args) throws Exception {
List messagesForReqList = new ArrayList<>();
// 构建消息内容
List contentParts = new ArrayList<>();
// 第一张图片部分使用builder模式
contentParts.add(ChatCompletionContentPartImage.builder()
.type(ChatCompletionContentPartType.IMAGE_URL)
.imageUrl(ChatCompletionContentPartImageImageUrl2.ofChatCompletionContentPartImageImageUrl(ChatCompletionContentPartImageImageUrl.builder().url("https://arkdocs.tos-cn-beijing.volces.com/images/advanced-usage/view.jpeg").build()))
.build());
contentParts.add(ChatCompletionContentPartText.builder()
.type(ChatCompletionContentPartType.TEXT)
.text("图片主要讲了什么?")
.build());
messagesForReqList.add(ChatCompletionRequestUserMessage.builder()
.role(ChatCompletionRequestMessageType.USER)
.content(ChatCompletionMessageContent.ofList(contentParts))
.build());
ChatCompletionRequest req = ChatCompletionRequest.builder()
.model("doubao-seed-2-1-pro-260915") //Replace with Model ID .
.messages(messagesForReqList)
.thinking(Thinking.builder().type(ThinkingMode.ENABLED).build())
.reasoningEffort(ReasoningEffort.LOW)
.build();
arkService.createChatCompletion(req)
.getChoices()
.forEach(choice -> System.out.println(choice.getMessage().getContent()));
// shutdown service after all requests are finished
arkService.shutdownExecutor();
}
}
```
**选项:OpenAI SDK**
```Python
import os
from openai import OpenAI
client = OpenAI(
# The base URL for model invocation .
base_url="https://ark.cn-beijing.volces.com/api/v3",
# Get API Key: https://ark.volcengine.com/region:cn-beijing/apikey
api_key=os.getenv('ARK_API_KEY'),
)
completion = client.chat.completions.create(
# Replace with Model ID .
model = "doubao-seed-2-1-pro-260915",
messages=[
{
"role": "user",
"content": [
{"type": "image_url","image_url": {"url": "https://arkdocs.tos-cn-beijing.volces.com/images/advanced-usage/view.jpeg"}},
{"type": "text", "text": "图片主要讲了什么?"},
],
}
],
extra_body={"thinking":{"type":"enabled"}},
reasoning_effort="low"
)
print(completion.choices[0])
```
完整代码及使用,请参见 [调节思考长度](/docs/responses-api-deep-thinking#dc4c1547)(Responses API)、[调节思考长度](/docs/deep-thinking#fc5eac89)(ChatCompletion API)。
# 上下文传递逻辑
## 多轮对话场景
|流程图 |说明 |
|---|---|
| |* 在每一轮对话过程中,深度思考模型会输出思维链内容(CoT)和最终回答(Answer)。 | \
| |* 在下一轮对话中,之前输出的思维链内容不会被拼接到上下文中。 | \
| |> 思维链内容展现的是模型处理问题的过程,包括将问题拆分为多个问题进行处理,生成多种回复综合得出更好回答等过程。 |
## 工具调用场景
针对工具调用场景优化了深度思考的执行逻辑,平台会自主判断是否将思维链内容输入给模型,参与后续轮次的推理,保障结果输出连贯、准确、可解释。
|流程图 |说明 |
|---|---|
| |* 回答问题 1 时(请求 1.1 - 1.2),模型进行多次思考 + 工具调用后给出答案,方舟会输入完整上下文包括思维链内容给模型处理。 | \
| |* 开始回答问题2时(请求 2.1),方舟会自行判断并删除之前上下文中的思维链,输入给模型。 |
> **说明**
>
> 推荐在 Responses API 中使用 previous_response_id,平台自动保存历史对话的上下文,并在多轮交互中回传给推理服务。
请求示例如下:
**选项:Chat API**
**第一轮请求:触发工具调用**
```Bash
curl https://ark.cn-beijing.volces.com/api/v3/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ARK_API_KEY" \
-d '{
"model": "doubao-seed-2-0-lite-260215",
"messages": [
{
"role": "system",
"content": "你是人工智能助手。"
},
{
"role": "user",
"content": "今天北京天气怎么样"
}
],
"tools": [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "天气查询",
"parameters": {
"properties": {
"location": {
"description": "地点的位置信息,例如北京、上海。",
"type": "string"
}
},
"required": [
"location"
],
"type": "object"
}
}
}
]
}'
```
**第一轮响应:返回工具调用指令**
模型会返回`reasoning_content`、`tool_calls`等关键字段。
```
{
"choices": [
{
"finish_reason": "tool_calls",
"index": 0,
"logprobs": null,
"message": {
"content": "",
"reasoning_content": "用户问今天北京天气怎么样,我需要调用get_weather工具,参数location填北京。检查一下,参数是必填的location,已经有了,所以直接调用工具就行。",
"role": "assistant",
"tool_calls": [
{
"function": {
"arguments": " {\"location\": \"北京\"}",
"name": "get_weather"
},
"id": "call_wiezxeyae8jzxl3jx8nhfgb5",
"type": "function"
}
]
}
}
],
...
}
```
**第二轮请求:回传完整上下文并生成最终响应**
第二轮请求还需要回传思维链信息、工具调用结果,模型生成回答。
```Bash
curl https://ark.cn-beijing.volces.com/api/v3/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ARK_API_KEY" \
-d '{
"model": "doubao-seed-2-0-lite-260215",
"messages": [
{
"role": "system",
"content": "你是人工智能助手。"
},
{
"role": "user",
"content": "今天北京天气怎么样"
},
{
"role": "assistant",
"reasoning_content": "用户问今天北京天气怎么样,我需要调用get_weather工具,参数location填北京。检查一下,参数是必填的location,已经有了,所以直接调用工具就行。",
"tool_calls": [
{
"function": {
"arguments": " {\"location\": \"北京\"}",
"name": "get_weather"
},
"id": "call_wiezxeyae8jzxl3jx8nhfgb5",
"type": "function"
}
]
},
{
"role": "tool",
"tool_call_id":"call_wiezxeyae8jzxl3jx8nhfgb5",
"content": "5度"
}
],
"tools": [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "天气查询",
"parameters": {
"properties": {
"location": {
"description": "地点的位置信息,例如北京、上海。",
"type": "string"
}
},
"required": [
"location"
],
"type": "object"
}
}
}
]
}'
```
**选项:Responses API**
**第一轮请求:触发工具调用**
```Bash
curl https://ark.cn-beijing.volces.com/api/v3/responses \
-H "Authorization: Bearer $ARK_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "doubao-seed-2-0-lite-260215",
"input": [
{
"role": "system",
"content": "你是人工智能助手."
},
{
"role": "user",
"content": "今天北京天气怎么样"
}
],
"thinking":{"type": "enabled"},
"tools": [
{
"type": "function",
"name": "get_weather",
"description": "天气查询",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "地点的位置信息,例如北京、上海。"
}
},
"required": ["location"]
}
}
]
}'
```
**第一轮响应:返回工具调用指令**
模型返回信息包含`id`、`call_id`、`arguments`等关键字段。
```
{
"created_at": 1766126702,
"id": "resp_0217661267019147d8950efa0e2f7c9d9cc7a1cc971272cf4548c",
"max_output_tokens": 32768,
"model": "doubao-seed-2-0-lite-260215",
"object": "response",
"output": [
{
"id": "rs_02176612670248500000000000000000000ffffac154e10754f5c",
"type": "reasoning",
"summary": [
{
"type": "summary_text",
"text": "用户问今天北京的天气怎么样,我需要调用get_weather工具,参数location是北京。按照格式要求来写函数调用。"
}
],
"status": "completed"
},
{
"arguments": " {\"location\": \"北京\"}",
"call_id": "call_t885uulopdd499rn0pioze7l",
"name": "get_weather",
"type": "function_call",
"id": "fc_02176612670345400000000000000000000ffffac154e10a6753e",
"status": "completed"
}
],
....
}
```
**第二轮请求:回传结果并生成最终响应**
传入上一轮 response_id、工具调用结果等信息,模型生成自然语言回答。
```Bash
curl https://ark.cn-beijing.volces.com/api/v3/responses \
-H "Authorization: Bearer $ARK_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "doubao-seed-2-0-lite-260215",
"input": [
{
"type": "function_call_output",
"call_id": "call_t885uulopdd499rn0pioze7l",
"output": "5度"
}
],
"previous_response_id": "resp_0217661267019147d8950efa0e2f7c9d9cc7a1cc971272cf4548c",
"thinking":{"type": "enabled"},
"tools": [
{
"type": "function",
"name": "get_weather",
"description": "天气查询",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "地点的位置信息,例如北京、上海。"
}
},
"required": ["location"]
}
}
]
}'
```
# 长度限制生效逻辑
模型输出的组成如下公式,模型的输出 = 模型的回答 + 模型的思维链(如有)
* **max_tokens**:控制模型的回答长度,默认值 4096。如果触发长度限制,模型停止回答,并在返回结构体的 **finish_reason** 字段为 `length`。
* **max_completion_tokens**:控制模型的回答、模型思维链总长度,如触发限制,模型停止回答,并在返回结构体的 **finish_reason** 字段为 `length`。如配置了 **max_completion_tokens** ,max_tokens默认值会失效,常用于超长文本输出或者控制模型返回长度。
## 仅配置 max_tokens(默认逻辑)
下面是各个对象的长度限制说明。
| | | | |
|对象 |关键参数 |说明 |可否配置 |
|---|---|---|---|
| | | | |
|问题 |最大输入长度 | `上下文窗口 - 思维链窗口`,与回答共享配额。 |模型规格,不可配置 | \
| | |> 可理解为问答配额。 | |
|思维链 |思维链窗口 |独占,不共享,即单次请求如有未使用的配额也不共享给问题及回答。 |模型规格,不可配置 |
|回答 |最大回答长度 |最大回答长度,通过 **max_tokens** 参数配置。 |API字段,可配置 | \
| | |另外随着输入长度增加,回答配额也会受 **最大输入长度(问答配额)** 剩余配额影响。 | | \
| | |回答配额 | | \
| | |=`min(最大回答长度, 最大输入长度-实际输入长度)` | | \
| | |=`min(最大回答长度, 上下文窗口-思维链窗口-实际输入长度)` | |
|^^| |^^| | \
| |最大输入长度 | |模型规格,不可配置 |
内容截断逻辑举例:模型A属性如下,上下文窗口 96k,思维链窗口 32k,最大输入长度(问答配额) 64k,配置最大回答长度 16k。
* 当用户输入的问题 56k,模型输出思维链16k,模型输出的回答达到8k时,`问题+回答 = 56k+8k = 64k`,触发**最大输入长度(问答配额)** 限制,模型停止推理。
* 当用户输入的问题 22k,模型输出思维链16k,模型输出的回答达到16k时,触发**最大回答长度**限制,模型停止推理。
* 当用户输入的问题 22k,模型输出思维链32k,触发**最大思维链长度**限制,模型停止推理。
## 仅配置 **max_completion_tokens**
| | | | |
|影响/控制对象 |关键参数 |说明 |可否配置 |
|---|---|---|---|
| | | | |
|问题 |最大输入长度 |与回答共享配额,即未使用配额共享给回答内容 |模型规格,不可配置 |
|思维链 |最大输出长度 |与回答共享配额,即未使用的配额共享给回答。 |API字段,可配置 |
| | | | |
|^^| | | | \
| |思维链窗口 |模型能够输出的最大思维链长度。 |模型规格,不可配置 |
| | | | |
|回答 |最大输出长度 |与思维链共享配额,即输出长度不可超过`最大输出长度-已输出的思维链内容长度` |API字段,可配置 |
内容截断逻辑举例:模型A属性如下,上下文窗口 96k,最大输入长度 64k,最大思维链长度 32k。配置最大输出长度(**max_completion_tokens**) 32k 后,最大回答长度(**max_tokens**)默认值(`4096`)限制失效:
* 当用户输入的内容长度 72k,触发**最大输入长度**限制,直接报错。
* 当模型输出的内容超过 32k,触发 **最大思维链长度** 限制,模型停止推理。
* 当用户输入的问题长度 26k,模型输出的思维链长度 16k,模型输出的回答长度达到 16k 时,`思维链长度+回答长度=16k+16k=32k`,触发**最大输出长度** 限制,模型停止推理。
##
---
# 流式输出
Source: https://ark.volcengine.com/region:cn-beijing/docs/streaming-output
默认情况下,方舟 API 会在生成全部内容后,再通过单次 HTTP 响应返回结果。如果输出长内容,等待时间会较长。流式响应模式下,模型会持续发送已生成的数据片段,你可实时看到中间输出过程内容,方便立即开始处理或展示部分结果。
# 效果与优势
|预览 |优势 |
|---|---|
|[视频](https://p9-arcosite.byteimg.com/obj/tos-cn-i-goo7wpa0wc/0b0ed47ec1b94b20a4f4966aa80130e6) |* **改善等待体验**:无需等待完整内容生成完毕,可立即处理过程内容。 | \
| |* **实时过程反馈**:多轮交互场景,实时了解任务当前的处理阶段。 | \
| |* **更高的容错性**:中途出错,也能获取到已生成内容,避免非流式输出失败无返回的情况。 | \
| |* **简化超时管理**:保持客户端与服务端的连接状态,避免复杂任务耗时过长而连接超时。 |
# 使用说明
## 启用流式
通过配置 **stream** 为 `true`,来启用流式输出。
## 示例代码
* Chat API 示例代码:
**选项:Curl**
```Bash
curl https://ark.cn-beijing.volces.com/api/v3/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ARK_API_KEY" \
-d '{
"model": "doubao-seed-2-1-pro-260915",
"messages": [
{
"role": "user",
"content": "常见的十字花科植物有哪些?"
}
],
"stream": true
}'
```
**选项:Python**
```Python
import os
# Install SDK: python -m pip install --upgrade arkruntime
from arkruntime import Ark
client = Ark(
# The base URL for model invocation
base_url="https://ark.cn-beijing.volces.com/api/v3",
# Get API Key: https://ark.volcengine.com/region:cn-beijing/apikey
api_key=os.getenv('ARK_API_KEY'),
)
completion = client.chat.completions.create(
# Replace with Model ID
model = "doubao-seed-2-1-pro-260915",
messages=[
{"role": "user", "content": "常见的十字花科植物有哪些?"},
],
stream=True,
)
# Ensure the connection is closed automatically to prevent connection leaks.
with completion:
for chunk in completion:
if chunk.choices[0].delta.content is not None:
print(chunk.choices[0].delta.content, end="")
```
> **说明**
>
> `with completion `:当 with 代码块内出现异常时,会自动调用对象的 __exit__() 方法进行清理工作。当设置了max_tokens 等中断条件时,可避免socket层数据载满最终程序卡住。
**选项:Go**
```Go
package main
import (
"context"
"fmt"
"io"
"os"
"github.com/volcengine/ark-runtime-go/arkruntime"
"github.com/volcengine/ark-runtime-go/arkruntime/model/chat"
)
func main() {
client := arkruntime.NewClientWithApiKey(
os.Getenv("ARK_API_KEY"),
// The base URL for model invocation
arkruntime.WithBaseUrl("https://ark.cn-beijing.volces.com/api/v3"),
)
ctx := context.Background()
fmt.Println("----- standard request -----")
req := &chat.ChatCompletionRequest{
// Replace with Model ID
Model: "doubao-seed-2-1-pro-260915",
Messages: []chat.ChatCompletionRequestMessage{
userMessage("常见的十字花科植物有哪些?"),
},
Stream: chat.NewOptBool(true),
}
// 调用 CreateChatCompletionStream 方法,而不要使用非流式调用的 CreateChatCompletion 方法,否则将无法获取流式响应。
resp, err := client.CreateChatCompletionStream(ctx, req)
if err != nil {
fmt.Printf("standard chat error: %v", err)
return
}
defer resp.Close()
for {
chunk, err := resp.Recv()
if err == io.EOF {
break
}
if err != nil {
fmt.Printf("stream error: %v", err)
break
}
fmt.Print(chunk.Choices[0].Delta.Content.Or(""))
}
fmt.Println()
}
func userMessage(content string) chat.ChatCompletionRequestMessage {
return chat.ChatCompletionRequestMessage{
OneOf: chat.NewChatCompletionRequestUserMessageChatCompletionRequestMessageSum(
chat.ChatCompletionRequestUserMessage{
Role: chat.ChatCompletionRequestUserMessageRoleUser,
Content: chat.NewOptNilChatCompletionMessageContent(chat.NewStringChatCompletionMessageContent(content)),
},
),
}
}
```
**选项:Java**
```Java
package com.volcengine.ark.runtime;
import com.volcengine.ark.runtime.models.chat.*;
import com.volcengine.ark.runtime.service.ArkService;
import java.util.ArrayList;
import java.util.List;
public class ChatCompletionsExample {
public static void main(String[] args) {
String apiKey = System.getenv("ARK_API_KEY");
// The base URL for model invocation
ArkService service = ArkService.builder().apiKey(apiKey)
.baseUrl("https://ark.cn-beijing.volces.com/api/v3")
.build();
final List messages = new ArrayList<>();
final ChatCompletionRequestMessage userMessage = ChatCompletionRequestUserMessage.builder().role(ChatCompletionRequestMessageType.USER).content(ChatCompletionMessageContent.ofString("常见的十字花科植物有哪些?")).build();
messages.add(userMessage);
ChatCompletionRequest chatCompletionRequest = ChatCompletionRequest.builder()
.model("doubao-seed-2-1-pro-260915")//Replace with Model ID
.messages(messages)
.stream(true)
.thinking(Thinking.builder().type(ThinkingMode.DISABLED).build())
.build();
service.streamChatCompletion(chatCompletionRequest)
.doOnError(Throwable::printStackTrace) // 处理错误
.blockingForEach(response -> {
if (response.getChoices() != null && !response.getChoices().isEmpty()) {
String content = String.valueOf(response.getChoices().get(0).getDelta().getContent());
if (content != null) {
System.out.print(content); // 注意用print而非println,保持内容连续
}
}
});
// shutdown service
service.shutdownExecutor();
}
}
```
**选项:OpenAI SDK**
```Python
import os
from openai import OpenAI
client = OpenAI(
# Get API Key: https://ark.volcengine.com/region:cn-beijing/apikey
api_key=os.environ.get("ARK_API_KEY"),
base_url="https://ark.cn-beijing.volces.com/api/v3",
)
completion = client.chat.completions.create(
# Replace with Model ID
model = "doubao-seed-2-1-pro-260915",
messages=[
{"role": "user", "content": "常见的十字花科植物有哪些?"},
],
stream=True,
)
# Ensure the connection is closed automatically to prevent connection leaks.
with completion:
for chunk in completion:
if chunk.choices[0].delta.content is not None:
print(chunk.choices[0].delta.content, end="")
```
* Responses API 示例代码:
**选项:Curl**
```Bash
curl https://ark.cn-beijing.volces.com/api/v3/responses \
-H "Authorization: Bearer $ARK_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "doubao-seed-2-1-pro-260915",
"input": "常见的十字花科植物有哪些?",
"stream": true
}'
```
**选项:Python**
```Python
import os
from arkruntime import Ark
from arkruntime.types.responses.response_completed_event import ResponseCompletedEvent
from arkruntime.types.responses.response_reasoning_summary_text_delta_event import ResponseReasoningSummaryTextDeltaEvent
from arkruntime.types.responses.response_output_item_added_event import ResponseOutputItemAddedEvent
from arkruntime.types.responses.response_text_delta_event import ResponseTextDeltaEvent
from arkruntime.types.responses.response_text_done_event import ResponseTextDoneEvent
# Get API Key: https://ark.volcengine.com/region:cn-beijing/apikey
api_key = os.getenv('ARK_API_KEY')
client = Ark(
base_url='https://ark.cn-beijing.volces.com/api/v3',
api_key=api_key,
)
# Create a request
response = client.responses.create(
model="doubao-seed-2-1-pro-260915",
input="常见的十字花科植物有哪些?",
stream=True
)
for event in response:
if isinstance(event, ResponseReasoningSummaryTextDeltaEvent):
print(event.delta, end="")
if isinstance(event, ResponseOutputItemAddedEvent):
print("\noutPutItem " + event.type + " start:")
if isinstance(event, ResponseTextDeltaEvent):
print(event.delta,end="")
if isinstance(event, ResponseTextDoneEvent):
print("\noutPutTextDone.")
if isinstance(event, ResponseCompletedEvent):
print("Response Completed. Usage = " + event.response.usage.model_dump_json())
```
**选项:Go**
```Go
package main
import (
"context"
"fmt"
"io"
"os"
"github.com/volcengine/ark-runtime-go/arkruntime"
"github.com/volcengine/ark-runtime-go/arkruntime/model/responses"
)
func main() {
client := arkruntime.NewClientWithApiKey(
// Get API Key: https://ark.volcengine.com/region:cn-beijing/apikey
os.Getenv("ARK_API_KEY"),
arkruntime.WithBaseUrl("https://ark.cn-beijing.volces.com/api/v3"),
)
ctx := context.Background()
resp, err := client.CreateResponsesStream(ctx, &responses.ResponsesRequest{
Model: "doubao-seed-2-1-pro-260915",
Input: responses.NewStringResponsesInput("常见的十字花科植物有哪些?"),
})
if err != nil {
fmt.Printf("stream error: %v", err)
return
}
for {
event, err := resp.Recv()
if err == io.EOF {
break
}
if err != nil {
fmt.Printf("stream error: %v", err)
return
}
handleEvent(event)
}
}
func handleEvent(event *responses.ResponseStreamEvent) {
switch event.OneOf.Type {
case responses.ResponseReasoningSummaryTextDeltaEventResponseStreamEventSum:
print(event.OneOf.ResponseReasoningSummaryTextDeltaEvent.Delta.Or(""))
case responses.ResponseReasoningSummaryTextDoneEventResponseStreamEventSum:
fmt.Printf("\nAggregated reasoning text: %s\n", event.OneOf.ResponseReasoningSummaryTextDoneEvent.Text.Or(""))
case responses.ResponseTextDeltaEventResponseStreamEventSum:
print(event.OneOf.ResponseTextDeltaEvent.Delta.Or(""))
case responses.ResponseTextDoneEventResponseStreamEventSum:
fmt.Printf("\nAggregated output text: %s\n", event.OneOf.ResponseTextDoneEvent.Text.Or(""))
}
}
```
**选项:Java**
```Java
package com.ark.example;
import com.volcengine.ark.runtime.service.ArkService;
import com.volcengine.ark.runtime.models.responses.*;
public class demo {
public static void main(String[] args) {
String apiKey = System.getenv("ARK_API_KEY");
// The base URL for model invocation
ArkService arkService = ArkService.builder().apiKey(apiKey)
.baseUrl("https://ark.cn-beijing.volces.com/api/v3")
.build();
ResponsesRequest request = ResponsesRequest.builder()
.model("doubao-seed-2-1-pro-260915")
.stream(true)
.input(ResponsesInput.ofString("常见的十字花科植物有哪些?"))
.build();
arkService.streamResponse(request)
.doOnError(Throwable::printStackTrace)
.blockingForEach(event -> {
if (event instanceof ResponseReasoningSummaryTextDeltaEvent) {
System.out.print(((ResponseReasoningSummaryTextDeltaEvent) event).getDelta());
}
if (event instanceof ResponseOutputItemAddedEvent) {
System.out.println("OutputItem " + (((ResponseOutputItemAddedEvent) event).getItem().getType()) + " Start: ");
}
if (event instanceof ResponseTextDeltaEvent) {
System.out.print(((ResponseTextDeltaEvent) event).getDelta());
}
if (event instanceof ResponseTextDoneEvent) {
System.out.println("OutputText End.");
}
if (event instanceof ResponseOutputItemDoneEvent) {
System.out.println("OutputItem " + ((ResponseOutputItemDoneEvent) event).getItem().getType() + " End.");
}
if (event instanceof ResponseFunctionCallArgumentsDoneEvent) {
System.out.println("FunctionCall Arguments: " + ((ResponseFunctionCallArgumentsDoneEvent) event).getArguments());
}
if (event instanceof ResponseCompletedEvent) {
System.out.println("Response Completed. Usage = " + ((ResponseCompletedEvent) event).getResponse().getUsage());
}
});
arkService.shutdownExecutor();
}
}
```
**选项:OpenAI SDK**
```Python
import os
from openai import OpenAI
# Get API Key: https://ark.volcengine.com/region:cn-beijing/apikey
api_key = os.getenv('ARK_API_KEY')
client = OpenAI(
base_url='https://ark.cn-beijing.volces.com/api/v3',
api_key=api_key,
)
# Create a request
response = client.responses.create(
model="doubao-seed-2-1-pro-260915",
input="常见的十字花科植物有哪些?",
stream=True
)
for event in response:
if event.type == "response.reasoning_summary_text.delta":
print(event.delta, end="")
if event.type == "response.output_item.added":
print("\noutPutItem " + event.type + " start:")
if event.type == "response.output_text.delta":
print(event.delta,end="")
if event.type == "response.output_item.done":
print("\noutPutTextDone.")
if event.type == "response.completed":
print("\nResponse Completed. Usage = " + event.response.usage.model_dump_json())
```
## 返回示例
流式响应基于**Server-Sent Events (SSE)** 协议实现,其核心是服务端通过HTTP长连接持续向客户端推送数据片段。每个数据片段(Chunk)由**字段行**组成。包括模型深度思考内容片段、回复内容片段、工具调用片段等。流式响应结束时,服务端会推送一个特殊片段,通常包含 `data: [DONE]`
**选项:Chat API**
```
data: {"choices":[{"delta":{"content":"","reasoning_content":"\n","role":"assistant"},"index":0}],"created":1765713048,"id":"021765713047481dd742fe08f96381a9e3cd447cf1b9ac3192379","model":"doubao-seed-2-1-pro-260628","service_tier":"default","object":"chat.completion.chunk","usage":null}
data: {"choices":[{"delta":{"content":"","reasoning_content":"用户","role":"assistant"},"index":0}],"created":1765713048,"id":"021765713047481dd742fe08f96381a9e3cd447cf1b9ac3192379","model":"doubao-seed-2-1-pro-260628","service_tier":"default","object":"chat.completion.chunk","usage":null}
...
data: {"choices":[{"delta":{"content":"","reasoning_content":"。","role":"assistant"},"index":0}],"created":1765713048,"id":"021765713047481dd742fe08f96381a9e3cd447cf1b9ac3192379","model":"doubao-seed-2-1-pro-260628","service_tier":"default","object":"chat.completion.chunk","usage":null}
data: {"choices":[{"delta":{"content":"你","role":"assistant"},"index":0}],"created":1765713048,"id":"021765713047481dd742fe08f96381a9e3cd447cf1b9ac3192379","model":"doubao-seed-2-1-pro-260628","service_tier":"default","object":"chat.completion.chunk","usage":null}
data: {"choices":[{"delta":{"content":"✧","role":"assistant"},"index":0}],"created":1765713048,"id":"021765713047481dd742fe08f96381a9e3cd447cf1b9ac3192379","model":"doubao-seed-2-1-pro-260628","service_tier":"default","object":"chat.completion.chunk","usage":null}
...
data: {"choices":[{"delta":{"content":"","role":"assistant"},"finish_reason":"stop","index":0}],"created":1765713048,"id":"021765713047481dd742fe08f96381a9e3cd447cf1b9ac3192379","model":"doubao-seed-2-1-pro-260628","service_tier":"default","object":"chat.completion.chunk","usage":null}
data: [DONE]
```
返回格式说明:(具体字段参见 [Chat API](/docs/chat-api))
* `choices[0].delta.content`: 模型生成的消息内容。
* `choices[0].delta.reasoning_content`: 模型思考内容。
* `choices[0].finish_reason`: 模型停止生成 token 的原因。(仅在最后一个chunk中出现)
**选项:Responses API**
```
event: response.created
data: {"type":"response.created","response":{"created_at":1764229579,"id":"resp_021764229578658fe9a0f6cb2cc6c828e7a59adbdb971872aee70","max_output_tokens":32768,"model":"doubao-seed-2-1-pro-260628","object":"response","thinking":{"type":"enabled"},"service_tier":"default","caching":{"type":"disabled"},"store":true,"expire_at":1764488778},"sequence_number":0}
event: response.in_progress
data: {"type":"response.in_progress","response":{"created_at":1764229579,"id":"resp_021764229578658fe9a0f6cb2cc6c828e7a59adbdb971872aee70","max_output_tokens":32768,"model":"doubao-seed-2-1-pro-260628","object":"response","thinking":{"type":"enabled"},"service_tier":"default","caching":{"type":"disabled"},"store":true,"expire_at":1764488778},"sequence_number":1}
event: response.output_item.added
data: {"type":"response.output_item.added","output_index":0,"item":{"id":"rs_02176422957963700000000000000000000ffffac15dd335c9c43","type":"reasoning","status":"in_progress"},"sequence_number":2}
event: response.reasoning_summary_part.added
data: {"type":"response.reasoning_summary_part.added","item_id":"rs_02176422957963700000000000000000000ffffac15dd335c9c43","output_index":0,"summary_index":0,"part":{"type":"summary_text"},"sequence_number":3}
event: response.reasoning_summary_text.delta
data: {"type":"response.reasoning_summary_text.delta","summary_index":0,"delta":"\n","item_id":"rs_02176422957963700000000000000000000ffffac15dd335c9c43","output_index":0,"sequence_number":4}
...
event: response.completed
data: {"type":"response.completed","response":{"created_at":1768809358,"id":"resp_021768809358289649f4507e5505b181d56acee99f33e5a9f1075","max_output_tokens":32768,"model":"doubao-seed-2-1-pro-260628","object":"response","output":[{"id":"rs_02176880935899200000000000000000000ffffac154346d65c7e","type":"reasoning","summary":[{"type":"summary_text","text":"\n..."}],"status":"completed"},{"type":"message","role":"assistant","content":[{"type":"output_text","text":"..."}],"status":"completed","id":"msg_02176880937345100000000000000000000ffffac154346bd6748"}],"service_tier":"default","status":"completed","usage":{"input_tokens":42,"output_tokens":846,"total_tokens":888,"input_tokens_details":{"cached_tokens":0},"output_tokens_details":{"reasoning_tokens":408}},"caching":{"type":"disabled"},"store":true,"expire_at":1769068558},"sequence_number":851}
data: [DONE]
```
返回示例说明:(具体字段参见 [Responses API](/docs/create-model-responses-api))
* event类型`response.reasoning_summary_text.delta`,`event.delta`为模型思考内容。
* event类型`response.output_text.delta`,`event.delta`为模型生成的消息内容。
* event类型`response.completed`,`event.response.usage`为本次请求的 token 用量。
# API 文档
* [Chat API](/docs/chat-api)
* [Responses API](/docs/create-model-responses-api)
# 更多示例
* 函数调用流式输出,请参见 [流式输出](/docs/function-calling#ba983529)。
---
# 续写模式
Source: https://ark.volcengine.com/region:cn-beijing/docs/continuation-mode
调用模型,如果希望控制和引导模型的输出,您可以通过续写模式实现:预填`assistant`角色的部分内容,模型将基于该内容延续输出,以此达成输出控制目标。您可以将该输出控制机制应用于以下场景:强制输出 JSON/XML 等特定格式、绕过模型最大输出限制生成超长内容、确保大模型在角色扮演场景中保持角色一致性。
## 模型及 API
支持的模型如下:
* 文本生成模型中无深度思考能力的模型:具体模型可在[文本生成能力](/docs/model-list#32e9e053)筛选。
* 部分具有深度思考能力的模型:
* doubao-seed-evolving
* doubao-seed-2-1-pro-260915
* doubao-seed-2-1-lite-260915
* doubao-seed-2-1-pro-260628
* doubao-seed-2-1-turbo-260628
* doubao-seed-2-0-lite-260428
* doubao-seed-2-0-mini-260428
* doubao-seed-2-0-pro-260215
* doubao-seed-2-0-lite-260215
* doubao-seed-2-0-mini-260215
* doubao-seed-2-0-code-preview-260215
* doubao-seed-character-260628
* glm-5-3-flash-260828
* deepseek-v4-1-flash-261017
* deepseek-v4-1-flash-260910
* deepseek-v4-1-flash-economy-261017
> **注意**
>
> 其他深度思考模型不可使用续写模式,即请求时 message 以 assistant role 消息结尾时,**thinking** 字段会失效,模型保持默认是否深度思考的行为。
API 支持:
* [Chat API](/docs/chat-api)
* [Responses API](/docs/create-model-responses-api)
## 核心配置
### 方式一
**支持模型**:除 `deepseek-v4-1-flash-261017`、`deepseek-v4-1-flash-260910`、`deepseek-v4-1-flash-economy-261017` 之外的其他模型。
请将消息列表的最后一条消息的 **role** 设置为`assistant`,模型会遵循 `assistant` 消息的已有格式和内容来续写。
```Python
messages = [
{"role": "user", "content": "You are a calculator, please calculate: 1 + 1"},
# 最后消息为模型消息,role 为 assistant
{"role": "assistant", "content": "="}
]
```
### 方式二
**支持模型**:`deepseek-v4-1-flash-261017`、`deepseek-v4-1-flash-260910`、`deepseek-v4-1-flash-economy-261017`
请将消息列表的最后一条消息的 **role** 设置为`assistant`,并设置最后一条消息的 **prefix** 参数为`true`。模型会遵循 `assistant` 消息的已有格式和内容来续写。
```Python
messages = [
{"role": "user", "content": "You are a calculator, please calculate: 1 + 1"},
{"role": "assistant", "content": "=", "prefix": True}
]
```
## 模式对比
|普通模式 |续写模式 |
| --- | --- |
|请求示例 |请求示例 | \
| | | \
|```Python |```Python | \
|import os |import os | \
|# Install SDK: pip install arkruntime |# Install SDK: pip install arkruntime | \
|from arkruntime import Ark |from arkruntime import Ark | \
| | | \
|client = Ark( |client = Ark( | \
| # The base URL for model invocation | # The base URL for model invocation | \
| base_url="https://ark.cn-beijing.volces.com/api/v3", | base_url="https://ark.cn-beijing.volces.com/api/v3", | \
| # Get API Key: https://ark.volcengine.com/region:cn-beijing/apikey | # Get API Key: https://ark.volcengine.com/region:cn-beijing/apikey | \
| api_key=os.getenv('ARK_API_KEY'), | api_key=os.getenv('ARK_API_KEY'), | \
|) |) | \
| | | \
|completion = client.chat.completions.create( |completion = client.chat.completions.create( | \
| # Replace with Model ID | # Replace with Model ID | \
| model = "doubao-seed-2-1-pro-260915", | model = "doubao-seed-2-1-pro-260915", | \
| messages=[ | messages=[ | \
| {"role": "user", "content": "You are a calculator, please calculate: 1 + 1 "}, | {"role": "user", "content": "You are a calculator, please calculate: 1 + 1"}, | \
| ] | # 额外传入模型信息,模型据此续写 | \
|) | {"role": "assistant", "content": "="} | \
|print(completion.choices[0].message.content) | ] | \
|``` |) | \
| |print(completion.choices[0].message.content) | \
| |``` |
|返回示例 |返回示例 | \
| | | \
|```Shell |```Shell | \
|1+1等于2。 |2 | \
|``` |``` | \
| | | \
|输出会按照模型根据问题的完整自然语言回复。 |模型根据信息“=”续写,保持对应的格式和行文风格。 |
接下来,对于几种典型使用场景进行举例说明。
## 场景:改善输出格式
模型可能会基于自身理解输出内容,导致结果无法直接被其他程序解析。可以通过预填充 `{` 符号,引导模型跳过一些场景回复,直接输出 JSON 对象,会让回答更加简洁和工整,可以被其他程序更好地解析。
|普通模式 |续写模式 |
| --- | --- |
|请求示例 |请求示例 | \
| | | \
|```Python |```Python | \
|import os |import os | \
|# Install SDK: pip install arkruntime |# Install SDK: pip install arkruntime | \
|from arkruntime import Ark |from arkruntime import Ark | \
| | | \
|client = Ark( |client = Ark( | \
| # The base URL for model invocation | # The base URL for model invocation | \
| base_url="https://ark.cn-beijing.volces.com/api/v3", | base_url="https://ark.cn-beijing.volces.com/api/v3", | \
| # Get API Key: https://ark.volcengine.com/region:cn-beijing/apikey | # Get API Key: https://ark.volcengine.com/region:cn-beijing/apikey | \
| api_key=os.getenv('ARK_API_KEY'), | api_key=os.getenv('ARK_API_KEY'), | \
|) |) | \
| | | \
|completion = client.chat.completions.create( |completion = client.chat.completions.create( | \
| # Replace with Model ID | # Replace with Model ID | \
| model = "doubao-seed-2-1-pro-260915", | model = "doubao-seed-2-1-pro-260915", | \
| messages=[ | messages=[ | \
| {"role": "user", "content": "Use JSON to describe the name and function of the Doubao model"} | {"role": "user", "content": "Use JSON to describe the name and function of the Doubao model"}, | \
| ] | # 额外传入一个 { 的模型信息,模型据此续写 | \
|) | {"role": "assistant", "content": "{"}, | \
|print(completion.choices[0].message.content) | ] | \
|``` |) | \
| |print(completion.choices[0].message.content) | \
| |``` |
|返回示例 |返回示例 | \
|返回一些说明性语言,无法直接按照 JSON 解析。 |和前置`assistant`信息组合成 JSON 返回。 | \
| | | \
|```Shell |```Shell | \
|Here's a JSON description of the Doubao model, including its name and function: |"model_name": "Doubao", | \
| | "functions": [ | \
|```json | { | \
|{ | "name": "text_generation", | \
| "model": { | "description": "Generates human-like text based on input prompts, supporting creative writing, summarization, and more." | \
| "name": "Doubao", | }, | \
| "alternative_names": ["doubao"], | { | \
| "type": "large_language_model", | "name": "language_translation", | \
| "developer": "ByteDance", | "description": "Translates text between multiple languages with high accuracy and contextual understanding." | \
| "primary_function": { | }, | \
| "description": "Doubao is an AI assistant designed to understand and generate human-like text responses", | { | \
| "capabilities": [ | "name": "sentiment_analysis", | \
| "natural language understanding", | "description": "Analyzes the sentiment of input text, determining whether it is positive, negative, or neutral." | \
| "text generation", | }, | \
| "question answering", | { | \
| "translation between languages", | "name": "question_answering", | \
| "text summarization", | "description": "Provides accurate answers to questions based on the input context or general knowledge." | \
| "creative writing", | }, | \
| "code generation and explanation", | { | \
| "general knowledge provision" | "name": "code_generation", | \
| ] | "description": "Generates code snippets in various programming languages based on natural language descriptions." | \
| }, | }, | \
| "languages_supported": ["Chinese", "English"], | { | \
| "access_method": "API and web/mobile interfaces", | "name": "conversational_ai", | \
| "version": "1.0", | "description": "Engages in natural, context-aware conversations with users, simulating human-like interactions." | \
| "release_date": "2023" | } | \
| } | ] | \
|} |} | \
|``` |``` | \
| | | \
|Note: Some details about Doubao might not be publicly available, as it's a relatively new model from ByteDance. The information here represents common capabilities of similar large language models. | | \
|``` | |
### 注意事项
* 方舟已提供结构化输出能力,可让模型输出严格符合格式要求的 JSON 内容,请参见[结构化输出(beta)](/docs/structured-output-beta)。
* 由于模型具有一定的随机性,无法 100% 保证回复为标准 JSON 对象。建议您对模型的回复进行校验,下面示例使用 [json_repair](https://github.com/mangiucugna/json_repair) 库校验返回的是否为合法的 JSON 对象。
```Python
import json
# Install json-repair: pip install json-repair
import json_repair
import os
# Install SDK: python -m pip install --upgrade arkruntime
from arkruntime import Ark
PREFILL_PREFIX = "{"
client = Ark(
# The base URL for model invocation
base_url="https://ark.cn-beijing.volces.com/api/v3",
# Get API Key: https://ark.volcengine.com/region:cn-beijing/apikey
api_key=os.getenv('ARK_API_KEY'),
)
completion = client.chat.completions.create(
# Replace with Model ID
model = "doubao-seed-2-1-pro-260915",
messages=[
{"role": "user", "content": "Use JSON to describe the name and function of the Doubao model"},
{"role": "assistant", "content": PREFILL_PREFIX},
]
)
# 拼接 PREFILL_PREFIX 和模型输出
json_string = PREFILL_PREFIX + completion.choices[0].message.content
# 解析 JSON Object
obj = {}
try:
obj = json.loads(json_string)
except json.JSONDecodeError as e:
obj = json_repair.loads(json_string)
print(obj)
```
## 场景:输出超过模型输出上限的内容
使用续写模式让大模型根据前轮请求续写内容,并拼接多次输出的内容,组合成超长输出。可以避免因为 **max_tokens**(最大输出长度)限制,导致无法获取完整内容。
> 这种方式会将模型输出多次返回给模型,会有更多 token 用量。
> 注意增加循环次数限制等兜底,防止死循环输出等特殊情况,导致意外花费。
```Python
import os
# Install SDK: python -m pip install --upgrade arkruntime
from arkruntime import Ark
messages = [
{"role": "user", "content": '''Please translate the following text into English: '''}, # Replace