豆包大模型是字节跳动在火山引擎上开放的大语言模型服务,其核心对话接口兼容 OpenAI Chat Completions 规范。对于已经熟悉 Python 或 Node.js 的开发者来说,不用重新学一套 API 设计,替换 base_url 和 model 就能把原有代码迁移过来。本文先讲开通和基础对话,再把流式输出、多轮记忆、函数调用这几个高频能力串成一条可落地的调用链路。

一、开通服务与接入准备
调用豆包大模型前,需要到火山方舟控制台完成账号开通并创建推理接入点。控制台会给每个接入点分配一个模型 ID,常见的是 doubao-pro-32k 这类预置模型,也可能是 ep- 开头的独立接入点。正式项目建议使用独立接入点,后续做限流、版本回退、上下文长度调整时会方便很多。
开通后进入 API Key 管理页面生成密钥。这个密钥只在创建时完整显示一次,务必提前写入环境变量。Python 侧安装 OpenAI 官方 SDK 即可,不必额外安装火山专用包。初始化客户端时重点改两个地方:api_key 和 base_url。下面是一个最小化的基础对话示例。
import os
from openai import OpenAI
client = OpenAI(
api_key=os.getenv("ARK_API_KEY"),
base_url="https://ark.cn-beijing.volces.com/api/v3",
)
response = client.chat.completions.create(
model="doubao-pro-32k",
messages=[
{"role": "system", "content": "你是一个简洁的编程助手。"},
{"role": "user", "content": "用一句话解释什么是闭包。"},
],
temperature=0.7,
max_tokens=512,
)
print(response.choices[0].message.content)
这段代码跑通后,说明密钥、模型 ID 和网络连通性都没问题。messages 里的 system 角色用来约束助手行为,user 角色是用户输入,assistant 角色是模型历史回复。基础对话的核心就是维护好这个列表。
二、基础对话参数解析与多轮记忆
基础对话并不只是发送一句话、收到一句话。temperature 控制随机性,低值适合事实问答和代码生成,高值适合创意文案。top_p 是核采样参数,max_tokens 限制最大输出长度。豆包模型在低温度下输出通常更稳定,接口调试阶段可以先设为 0.3 左右,等业务逻辑稳定后再按场景调整。
真正让对话连续的,是把每一轮消息都回传给模型。很多失败案例是因为只保留了最后一句用户输入,导致模型完全不知道前面说过什么。正确做法是维护一个完整的消息历史列表,用户每次发言都追加一条 user 消息,模型回复后再追加一条 assistant 消息。下面是一个简单的多轮封装。
messages = [
{"role": "system", "content": "你是一个熟悉云原生技术的助手。"},
]
def chat(user_text):
messages.append({"role": "user", "content": user_text})
resp = client.chat.completions.create(
model="doubao-pro-32k",
messages=messages,
temperature=0.6,
)
answer = resp.choices[0].message.content
messages.append({"role": "assistant", "content": answer})
return answer
print(chat("什么是 Kubernetes?"))
print(chat("它和虚拟机有什么区别?"))
第二个问题没有重复 Kubernetes,但模型仍然知道它指代什么,因为历史消息里已经包含了上一轮回答。多轮记忆的主要成本是 token,对话越长,费用和延迟越高。如果上下文接近上限,可以删除较早的历史消息,或者用模型先生成一个摘要再继续。
三、流式输出:从一次性返回到逐字显示
普通请求必须等模型生成完整结果后才返回,这在长回答场景下会明显拉长等待时间。聊天机器人、代码补全和实时翻译通常采用流式输出,让模型每生成一小段文本就返回一段,前端可以像打字机一样展示。豆包大模型把 stream 参数设为 True 即可开启。
流式请求的写法和普通请求类似,只是返回值变成了一个可迭代的事件流。每个事件对象中,choices[0].delta 表示本次增量,delta.content 就是新增文本。需要注意最后一个事件可能只包含结束标记,不包含内容,因此要判断 delta.content 是否存在。
stream = client.chat.completions.create(
model="doubao-pro-32k",
messages=[{"role": "user", "content": "写一首关于秋天的短诗"}],
stream=True,
)
for chunk in stream:
delta = chunk.choices[0].delta
if delta and delta.content:
print(delta.content, end="", flush=True)
print()
上线流式功能时还要关注首 token 延迟和断线重连。首 token 延迟反映模型从收到请求到开始输出第一个字的时间,影响因素包括模型排队、prompt 长度和采样参数。网络断开时,SDK 不会自动恢复已经连接的流,需要在调用侧增加有限次重试,并记录已经生成的内容,避免重复输出。
四、函数调用:让模型学会调用工具
基础对话只能生成自然语言,如果让它查询天气、搜索订单或操作数据库,就需要函数调用。它的机制不是模型替你执行函数,而是模型根据用户输入返回一个结构化的调用意图,包含函数名和参数。真正执行 HTTP 请求、数据库查询的代码,仍然由开发者编写。
以天气查询为例,先定义工具描述。参数使用 JSON Schema,type、properties、required 要写清楚,这些信息直接影响模型判断该提取哪些字段。下面代码把工具传给模型,并观察返回的 tool_calls。
tools = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "查询指定城市的天气",
"parameters": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "城市名称,例如北京"
}
},
"required": ["city"]
}
}
}
]
response = client.chat.completions.create(
model="doubao-pro-32k",
messages=[{"role": "user", "content": "北京今天天气怎么样?"}],
tools=tools,
tool_choice="auto",
)
message = response.choices[0].message
print(message.tool_calls)
拿到 tool_calls 后,先用 json.loads 解析参数,再调用真实天气服务。执行结果不能直接打印给用户,而要封装成一条 tool 消息回传给模型,让模型基于结果生成自然语言回答。tool_call_id 必须与上一条调用记录一致,否则接口会报参数错误。
import json
args = json.loads(message.tool_calls[0].function.arguments)
city = args["city"]
weather_result = f"{city}晴,气温 26 摄氏度"
messages = [
{"role": "user", "content": "北京今天天气怎么样?"},
message,
{
"role": "tool",
"tool_call_id": message.tool_calls[0].id,
"content": weather_result,
},
]
final_resp = client.chat.completions.create(
model="doubao-pro-32k",
messages=messages,
tools=tools,
)
print(final_resp.choices[0].message.content)
函数调用最容易出问题的地方是 schema 写得含糊,比如缺少 required 字段、描述只有函数名没有用途。另一个高频错误是回传结果时漏掉 tool_call_id,或者把多条工具结果编成一条。建议在开发阶段先打印完整 tool_calls,确认模型返回的参数符合预期后再接入真实业务。
五、多模态输入与常见问题排查
部分豆包视觉模型支持图片输入,可以在 content 列表里同时放入文本和图片。图片可以用公网 URL,也可以使用 base64 编码。对于文档识别、商品分类、截图分析等场景,比仅靠文本描述要准确得多。下面是一个图片理解示例,模型 ID 需使用控制台里支持视觉的接入点。
response = client.chat.completions.create(
model="doubao-1-5-vision-pro-32k",
messages=[
{
"role": "user",
"content": [
{"type": "text", "text": "请描述这张图片的内容"},
{
"type": "image_url",
"image_url": {
"url": "https://picsum.photos/200"
}
}
]
}
],
)
print(response.choices[0].message.content)
实际接入时常见错误包括 401 鉴权失败、模型 ID 不存在、请求过于频繁触发限流、上下文超过模型上限等。401 通常是 API Key 错误或已删除;模型 ID 报错可以回控制台确认接入点名称;限流则要检查接入点的 QPS 设置,必要时加入重试和退避;上下文超长需要压缩历史消息或换用更长上下文的模型。把这些基础故障排查清楚,豆包大模型就能稳定进入业务代码。