记忆模型推理服务接入
duMemory 云数据库 Agent 记忆服务提供兼容 OpenAI 和 Anthropic 协议的模型推理 API。您可以根据现有应用或 Agent 使用的 SDK 选择对应协议,调用当前 API Key 有权访问的模型。
连接信息
| 信息 | 值 |
|---|---|
| API Base URL | https://cloud.memory.bj.baidubce.com/llm |
| API Key | 在控制台“API Key”页签下的“记忆模型推理“Tab中创建 |
| 传输协议 | HTTPS;流式响应使用 Server-Sent Events(SSE) |
接口总览
| 接口 | 协议 | 方法 | 用途 |
|---|---|---|---|
/v1/models |
OpenAI Models | GET | 列出当前 API Key 有权调用的模型 |
/v1/chat/completions |
OpenAI Chat Completions | POST | 通用对话推理,兼容 OpenAI SDK |
/v1/responses |
OpenAI Responses | POST | 使用输出项结构承载消息、推理和工具调用,适合 Agent 场景 |
/v1/messages |
Anthropic Messages | POST | 兼容 Anthropic SDK 与 Claude 生态工具链 |
三种推理协议使用相同的 API Key 权限和可用模型范围。选择协议时,主要考虑现有客户端使用的 SDK 和所需的响应结构:
| 接入需求 | 推荐协议 |
|---|---|
| 使用 OpenAI Chat Completions 接口或已有对话应用 | Chat Completions |
| 需要按输出项处理消息、推理或工具调用 | Responses |
| 使用 Anthropic SDK 或 Claude 生态工具链 | Messages |
认证方式
模型服务使用 API Key 进行身份认证。调用接口时,在请求头中携带以下信息:
1Authorization: Bearer <your-api-key>
2Content-Type: application/json
流式请求建议同时设置:
1Accept: text/event-stream
Anthropic 官方 SDK 默认通过 x-api-key 请求头传递 api_key,但模型服务的 /v1/messages 接口只接受 Authorization: Bearer。使用 Anthropic SDK 时,必须将 API Key 配置到 auth_token,不要配置到 api_key。
获取可用模型
建议在接入时先调用模型列表接口,确认当前 API Key 可使用的模型名称。该接口不需要请求体或查询参数。
1curl -sS \
2 -H "Authorization: Bearer $MEMORY_API_KEY" \
3 "https://cloud.memory.bj.baidubce.com/llm/v1/models"
响应示例:
1{
2 "object": "list",
3 "data": [
4 {
5 "id": "deepseek-v3.2",
6 "object": "model",
7 "created": 1677610602,
8 "owned_by": "openai",
9 "max_input_tokens": 131072,
10 "max_output_tokens": 8192
11 }
12 ]
13}
响应字段
| 字段 | 类型 | 说明 |
|---|---|---|
object |
string | 固定为 list |
data |
array | 当前 API Key 有权调用的模型列表;元素顺序不固定 |
data[].id |
string | 模型名称,即推理请求中 model 字段的取值 |
data[].object |
string | 固定为 model |
data[].created |
int | OpenAI 协议占位字段,固定为 1677610602,不代表模型上线时间 |
data[].owned_by |
string | 统一为 openai,表示使用 OpenAI 兼容协议,不代表模型的实际厂商 |
data[].max_input_tokens |
int | 最大输入 Token 数;可选字段,仅部分模型返回 |
data[].max_output_tokens |
int | 最大输出 Token 数;可选字段,仅部分模型返回 |
模型列表已经根据 API Key 的模型策略完成过滤。处理响应时,请根据 data[].id 查找目标模型,不要依赖数组下标;使用最大输入和输出 Token 数前,需要先判断对应字段是否存在。
使用用户 API Key 调用 GET /v1/models/{id} 获取单个模型详情时,将返回 HTTP 401。需要查询某个模型时,请从模型列表中按 data[].id 筛选。
Chat Completions 接入
Chat Completions 是通用对话推理接口,兼容 OpenAI Chat Completions 协议和 OpenAI 官方 SDK。
请求参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
model |
string | 是 | 模型名称,取自模型列表接口返回的 data[].id |
messages |
array | 是 | 对话消息数组,按时间正序排列 |
stream |
bool | 否 | 是否使用 SSE 流式返回,默认为 false |
stream_options |
object | 否 | 流式响应配置,仅在 stream=true 时生效 |
max_tokens |
int | 否 | 本次生成的最大 Token 数,不包含输入 |
temperature |
float | 否 | 采样温度,取值范围为 0~2,数值越大,输出随机性越高 |
top_p |
float | 否 | 核采样阈值;建议与 temperature 二选一调整 |
n |
int | 否 | 候选结果数量,默认为 1 |
stop |
string | 否 | 命中指定字符串时停止生成 |
presence_penalty |
float | 否 | 用于抑制已经出现过的话题 |
frequency_penalty |
float | 否 | 用于抑制高频 Token |
response_format |
object | 否 | 使用 json_object 或 json_schema 约束结构化输出 |
tools |
array | 否 | 可供模型调用的工具声明 |
tool_choice |
string/object | 否 | 可设为 auto、none,或指定一个函数 |
user |
string | 否 | 业务侧终端用户标识,将透传用于风控 |
messages 元素
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
role |
string | 是 | 消息角色:system、user、assistant 或 tool |
content |
string/array | 是 | 消息正文;多模态模型可使用内容块数组 |
tool_calls |
array | 否 | 模型上一轮发起的工具调用,仅用于 assistant 消息 |
tool_call_id |
string | 否 | 工具结果对应的调用 ID,role=tool 时必填 |
非流式调用
请求示例:
1curl -sS \
2 "https://cloud.memory.bj.baidubce.com/llm/v1/chat/completions" \
3 -H "Authorization: Bearer $MEMORY_API_KEY" \
4 -H "Content-Type: application/json" \
5 -d '{
6 "model": "deepseek-v3.2",
7 "messages": [
8 {"role": "user", "content": "用一句话解释什么是向量数据库"}
9 ],
10 "max_tokens": 128
11 }'
响应示例:
1{
2 "id": "chatcmpl-68628a65-4c8f-4b1e-9a2d-7f3e5c1b8d90",
3 "object": "chat.completion",
4 "created": 1785383012,
5 "model": "deepseek-v3.2",
6 "system_fingerprint": "vllm-0.22.1-tp4-dp8-ep-c9d0853f",
7 "choices": [
8 {
9 "index": 0,
10 "finish_reason": "stop",
11 "message": {
12 "role": "assistant",
13 "content": "向量数据库是专门存储和检索高维向量数据的数据库,通过相似度计算实现语义检索。"
14 }
15 }
16 ],
17 "usage": {
18 "prompt_tokens": 9,
19 "completion_tokens": 37,
20 "total_tokens": 46,
21 "prompt_tokens_details": {
22 "cached_tokens": 9
23 }
24 }
25}
响应字段
| 字段 | 类型 | 说明 |
|---|---|---|
id |
string | 本次请求 ID,前缀为 chatcmpl-;排查请求问题时可提供该值 |
object |
string | 非流式响应固定为 chat.completion |
created |
int | 秒级 Unix 时间戳 |
model |
string | 本次请求使用的模型名称 |
system_fingerprint |
string | 上游运行环境指纹,取值不稳定,业务不要依赖或展示 |
choices[].index |
int | 候选结果序号,从 0 开始 |
choices[].finish_reason |
string | 生成结束原因,见下表 |
choices[].message.role |
string | 固定为 assistant |
choices[].message.content |
string | 回复正文;发起工具调用时可能为空或只包含过渡内容 |
choices[].message.tool_calls |
array | 模型发起的工具调用 |
choices[].message.provider_specific_fields |
object | 上游透传的非标准字段,结构不稳定,业务不要依赖 |
usage.prompt_tokens |
int | 输入 Token 数,包含系统消息和全部历史消息 |
usage.completion_tokens |
int | 输出 Token 数 |
usage.total_tokens |
int | 输入与输出 Token 数之和 |
usage.prompt_tokens_details.cached_tokens |
int | 输入中命中 Prompt Cache 的 Token 数 |
usage.completion_tokens_details.reasoning_tokens |
int | 输出中属于推理过程的 Token 数;非推理模型通常为 0 |
结束原因
| 取值 | 说明 |
|---|---|
stop |
正常生成结束 |
length |
达到 max_tokens 上限,输出被截断 |
tool_calls |
模型请求调用工具 |
content_filter |
输出被内容安全策略拦截 |
当 finish_reason 为 length 时,输出可能是残缺 JSON 或不完整语句。业务侧需要判断结束原因,不要直接展示或解析被截断的内容。
流式调用
在请求中设置 "stream": true 后,模型服务通过 text/event-stream 返回增量内容。收到上游增量后,模型服务会立即下发,不额外缓冲。
如需在流结束前接收 usage,可同时设置:
1{
2 "stream": true,
3 "stream_options": {
4 "include_usage": true
5 }
6}
stream_options.include_usage 默认为 false。设为 true 时,流末尾会增加一个包含 usage 的响应帧。
首帧只包含角色信息,正文为空:
1data: {"id":"chatcmpl-f62199f3-...","object":"chat.completion.chunk","created":1785342989,"model":"deepseek-v3.2","choices":[{"index":0,"delta":{"role":"assistant","content":""}}]}
增量帧通过 delta.content 返回正文片段:
1data: {"id":"chatcmpl-f62199f3-...","object":"chat.completion.chunk","created":1785342989,"model":"deepseek-v3.2","choices":[{"index":0,"delta":{"content":"向量"}}]}
结束帧中的 delta 为空对象,同时返回 finish_reason:
1data: {"id":"chatcmpl-f62199f3-...","object":"chat.completion.chunk","created":1785342989,"model":"deepseek-v3.2","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}
用量帧仅在 stream_options.include_usage=true 时出现,此时 choices 为空数组:
1data: {"id":"chatcmpl-...","object":"chat.completion.chunk","created":1785342989,"model":"deepseek-v3.2","choices":[],"usage":{"prompt_tokens":7,"completion_tokens":17,"total_tokens":24,"completion_tokens_details":{"reasoning_tokens":0},"prompt_tokens_details":{"cached_tokens":7}}}
流式响应以以下标记结束:
1data: [DONE]
解析流式响应时需要注意:
data: [DONE]不是 JSON,不要交给 JSON 解析器处理。- 将各增量帧的
delta.content按顺序拼接,得到完整回复。 delta可能只包含role、只包含content或为空对象,读取字段前需要判空。- 包含
usage的响应帧不包含正文,应跳过内容拼接。
工具调用
在请求中通过 tools 声明可调用的函数:
1{
2 "model": "deepseek-v3.2",
3 "messages": [
4 {"role": "user", "content": "北京今天天气怎么样?"}
5 ],
6 "tools": [
7 {
8 "type": "function",
9 "function": {
10 "name": "get_weather",
11 "description": "查询城市天气",
12 "parameters": {
13 "type": "object",
14 "properties": {
15 "city": {"type": "string"}
16 },
17 "required": ["city"]
18 }
19 }
20 }
21 ],
22 "tool_choice": "auto"
23}
模型决定调用工具时,finish_reason 为 tool_calls:
1{
2 "choices": [
3 {
4 "index": 0,
5 "finish_reason": "tool_calls",
6 "message": {
7 "role": "assistant",
8 "content": "我来帮您查询北京今天的天气。",
9 "tool_calls": [
10 {
11 "id": "call_e5aa044d6b364c3ca1222c7f",
12 "type": "function",
13 "function": {
14 "name": "get_weather",
15 "arguments": "{\"city\": \"北京\"}"
16 }
17 }
18 ]
19 }
20 }
21 ]
22}
| 字段 | 类型 | 说明 |
|---|---|---|
tool_calls[].id |
string | 工具调用 ID,回填执行结果时作为 tool_call_id |
tool_calls[].type |
string | 固定为 function |
tool_calls[].function.name |
string | 模型选择的函数名称 |
tool_calls[].function.arguments |
string | 函数参数,是 JSON 字符串而不是 JSON 对象,需要再次解析 |
模型生成的函数参数可能不符合工具声明中的 Schema,业务侧需要进行校验并容错处理。执行工具后,将包含 tool_calls 的 assistant 消息和包含 tool_call_id 的 tool 消息追加到对话,再次调用接口。只要 finish_reason 仍为 tool_calls,就继续执行这一流程,直到返回 stop。
业务侧必须为工具调用设置最大轮数,避免模型反复请求工具造成无限循环。
Responses 接入
Responses 接口使用 OpenAI Responses 协议。与 Chat Completions 相比,请求使用 input,响应使用输出项数组 output[],可以在同一个数组中承载消息、推理和工具调用等不同类型的内容。
请求参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
model |
string | 是 | 模型名称 |
input |
string/array | 是 | 字符串表示一条用户消息;数组元素形如 {"role":"user","content":"..."} |
instructions |
string | 否 | 系统级指令,对应 Chat Completions 中的 system 消息 |
stream |
bool | 否 | 是否以命名事件的 SSE 流式返回,默认为 false |
max_output_tokens |
int | 否 | 输出 Token 上限,对应 Chat Completions 的 max_tokens |
temperature |
float | 否 | 采样温度 |
top_p |
float | 否 | 核采样阈值 |
tools |
array | 否 | 工具声明;name 和 parameters 位于工具对象顶层 |
tool_choice |
object | 否 | 工具选择配置 |
metadata |
object | 否 | 业务自定义键值,将在响应中原样返回 |
非流式调用
请求示例:
1curl -sS \
2 "https://cloud.memory.bj.baidubce.com/llm/v1/responses" \
3 -H "Authorization: Bearer $MEMORY_API_KEY" \
4 -H "Content-Type: application/json" \
5 -d '{
6 "model": "deepseek-v3.2",
7 "input": "用一句话解释什么是倒排索引",
8 "max_output_tokens": 128
9 }'
响应示例:
1{
2 "id": "resp_9f2c1d84a7b3...",
3 "object": "response",
4 "created_at": 1785383105,
5 "status": "completed",
6 "model": "deepseek-v3.2",
7 "output": [
8 {
9 "type": "message",
10 "id": "chatcmpl-8a41c0de-...",
11 "status": "completed",
12 "role": "assistant",
13 "content": [
14 {
15 "type": "output_text",
16 "text": "倒排索引是把词映射到包含它的文档列表的索引结构。",
17 "annotations": []
18 }
19 ]
20 }
21 ],
22 "usage": {
23 "input_tokens": 11,
24 "input_tokens_details": {
25 "cached_tokens": 11,
26 "audio_tokens": null,
27 "text_tokens": null
28 },
29 "output_tokens": 28,
30 "output_tokens_details": null,
31 "total_tokens": 39
32 }
33}
响应字段
| 字段 | 类型 | 说明 |
|---|---|---|
id |
string | 本次响应 ID,前缀为 resp_,与 output[].id 不同 |
object |
string | 固定为 response |
created_at |
int | 秒级 Unix 时间戳 |
status |
string | 响应状态:completed、incomplete 或 failed |
model |
string | 本次请求使用的模型名称 |
output |
array | 输出项数组,长度和元素类型不固定 |
output[].type |
string | 输出项类型,文本回复为 message |
output[].id |
string | 输出项 ID |
output[].status |
string | 输出项状态 |
output[].role |
string | message 输出项固定为 assistant |
output[].content[].type |
string | 内容块类型,文本内容为 output_text |
output[].content[].text |
string | 文本正文 |
output[].content[].annotations |
array | 引用标注,当前为空数组 |
usage.input_tokens |
int | 输入 Token 数 |
usage.input_tokens_details.cached_tokens |
int | 命中 Prompt Cache 的输入 Token 数 |
usage.output_tokens |
int | 输出 Token 数 |
usage.total_tokens |
int | 输入与输出 Token 数之和 |
读取正文时,需要遍历 output,筛选 type=message 的输出项,再遍历其 content,拼接所有 type=output_text 的 text。不要固定读取 output[0].content[0].text,推理类模型可能在文本消息之前插入其他类型的输出项。
响应中可能出现值为 null 的字段,例如 output_tokens_details 或 phase。反序列化时需要允许字段为空。
流式调用
在请求中设置 "stream": true 后,Responses 接口通过带事件名称的 SSE 返回结果。单轮纯文本回复的典型事件顺序如下:
1event: response.created
2event: response.in_progress
3event: response.output_item.added
4event: response.content_part.added
5event: response.output_text.delta
6event: response.output_text.done
7event: response.content_part.done
8event: response.output_item.done
9event: response.completed
| 事件 | 用途 |
|---|---|
response.created |
响应对象已创建,携带初始响应快照 |
response.in_progress |
开始生成 |
response.output_item.added |
新增输出项,item.type 表示输出项类型 |
response.content_part.added |
在当前输出项中新增内容块 |
response.output_text.delta |
文本增量,通过 delta 字段返回 |
response.output_text.done |
文本块生成结束,携带完整文本 |
response.content_part.done |
内容块结束 |
response.output_item.done |
输出项结束 |
response.completed |
全部生成结束,携带最终响应对象和完整 usage |
客户端应根据事件名称分派处理逻辑,而不是依赖事件的固定位置。对于无法识别的新增事件类型,建议默认忽略,避免协议扩展影响现有调用。正文只需拼接 response.output_text.delta 事件中的 delta 字段。
Anthropic Messages 接入
Messages 接口兼容 Anthropic Messages 协议,可通过 Anthropic 官方 SDK 和 Claude 生态工具链调用模型服务。请求中的 model 仍然使用模型列表接口返回的模型名称,不需要替换为 Claude 模型名称。
请求参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
model |
string | 是 | 模型名称,取自模型列表接口 |
messages |
array | 是 | 对话消息数组,元素包含 role 和 content |
max_tokens |
int | 是 | 本次生成的最大 Token 数;缺失时返回 HTTP 400 |
system |
array | 否 | 系统指令,是顶层参数,不放入 messages |
stream |
bool | 否 | 是否使用 SSE 流式返回,默认为 false |
temperature |
float | 否 | 采样温度 |
top_p |
float | 否 | 核采样阈值 |
stop_sequences |
array | 否 | 命中即停止生成的字符串数组 |
tools |
array | 否 | Anthropic 风格工具声明,使用 name、description 和 input_schema |
tool_choice |
object | 否 | 例如 {"type":"auto"} 或 {"type":"tool","name":"x"} |
metadata |
object | 否 | 业务自定义键值 |
system 是顶层参数。在 messages 中传入 role: "system" 不符合 Anthropic Messages 协议,可能被拒绝或忽略。
非流式调用
请求示例:
1curl -sS \
2 "https://cloud.memory.bj.baidubce.com/llm/v1/messages" \
3 -H "Authorization: Bearer $MEMORY_API_KEY" \
4 -H "Content-Type: application/json" \
5 -d '{
6 "model": "deepseek-v3.2",
7 "max_tokens": 128,
8 "messages": [
9 {"role": "user", "content": "用一句话解释什么是 B+ 树"}
10 ]
11 }'
响应示例:
1{
2 "id": "msg_01Xy8fK2...",
3 "type": "message",
4 "role": "assistant",
5 "model": "deepseek-v3.2",
6 "content": [
7 {
8 "type": "text",
9 "text": "B+树是一种平衡多路搜索树,所有数据都存在叶子节点并用链表相连,适合范围查询。"
10 }
11 ],
12 "stop_reason": "end_turn",
13 "stop_sequence": null,
14 "usage": {
15 "input_tokens": 0,
16 "output_tokens": 39,
17 "cache_read_input_tokens": 11
18 }
19}
响应字段
| 字段 | 类型 | 说明 |
|---|---|---|
id |
string | 消息 ID |
type |
string | 固定为 message |
role |
string | 固定为 assistant |
model |
string | 模型名称 |
content |
array | 内容块数组,长度和内容块类型不固定 |
content[].type |
string | 内容块类型,包括 text 和 tool_use |
content[].text |
string | type=text 时的回复正文 |
stop_reason |
string | 结束原因:end_turn、max_tokens、tool_use 或 stop_sequence |
stop_sequence |
string/null | 命中的停止字符串;未命中时为 null |
usage.input_tokens |
int | 未命中 Prompt Cache 的输入 Token 数 |
usage.output_tokens |
int | 输出 Token 数 |
usage.cache_read_input_tokens |
int | 命中 Prompt Cache 的输入 Token 数 |
usage.cache_creation_input_tokens |
int/null | 写入 Prompt Cache 的 Token 数;部分上游可能返回 0 或 null |
处理 content 时,需要遍历内容块并根据 type 分派,不能假定数组中只有一个文本块。当全部输入都命中 Prompt Cache 时,usage.input_tokens 可能为 0,相应数量会出现在 usage.cache_read_input_tokens 中。
流式调用
在请求中设置 "stream": true 后,Messages 接口通过带事件名称的 SSE 返回结果:
1event: message_start
2event: content_block_start
3event: content_block_delta
4event: content_block_stop
5event: message_delta
6event: message_stop
content_block_delta 会重复出现。正文增量位于 delta.type=text_delta 事件的 delta.text 字段中。
message_delta 示例:
1event: message_delta
2data: {"type":"message_delta","delta":{"stop_reason":"max_tokens"},"usage":{"input_tokens":0,"output_tokens":40,"cache_read_input_tokens":7}}
解析流式响应时需要注意:
message_start中的usage是占位值,可能全部为 0;最终usage位于message_delta中。message_start中的message.model可能使用与请求不同的大小写,不要用该字段进行模型判断;需要模型标识时,使用请求中传入的值。- 只拼接
content_block_delta中delta.type=text_delta的delta.text。 - Messages 协议没有
[DONE]标记,以message_stop作为流结束信号。
SDK 接入
OpenAI SDK
OpenAI SDK 可调用 Chat Completions 和 Responses 接口。base_url 需要配置到 /llm/v1:
1import os
2
3from openai import OpenAI
4
5client = OpenAI(
6 base_url="https://cloud.memory.bj.baidubce.com/llm/v1",
7 api_key=os.environ["MEMORY_API_KEY"],
8)
9
10# Chat Completions
11chat_response = client.chat.completions.create(
12 model="deepseek-v3.2",
13 messages=[{"role": "user", "content": "用一句话介绍你自己"}],
14)
15print(chat_response.choices[0].message.content)
16
17# Responses
18response = client.responses.create(
19 model="deepseek-v3.2",
20 input="用一句话介绍你自己",
21)
22print(response.output_text)
Anthropic SDK
Anthropic SDK 的 base_url 配置到 /llm,SDK 会自动拼接 /v1/messages。API Key 必须配置到 auth_token:
1import os
2
3from anthropic import Anthropic
4
5client = Anthropic(
6 base_url="https://cloud.memory.bj.baidubce.com/llm",
7 auth_token=os.environ["MEMORY_API_KEY"],
8)
9
10message = client.messages.create(
11 model="deepseek-v3.2",
12 max_tokens=128,
13 messages=[{"role": "user", "content": "用一句话介绍你自己"}],
14)
15text = "".join(block.text for block in message.content if block.type == "text")
16print(text)
使用建议
- 保护 API Key:通过环境变量或安全配置服务注入 API Key,不要将其写入源码、公开配置、截图或代码仓库。
- 动态获取模型名称:从模型列表接口读取
data[].id,不要依赖固定模型列表或数组顺序。 - 检查生成状态:处理 Chat Completions 的
finish_reason、Responses 的status和 Messages 的stop_reason,避免直接使用被截断或未完成的输出。 - 按类型解析响应:Responses 的输出项和 Messages 的内容块都可能包含多种类型,不要依赖固定数组下标。
- 兼容可选字段:对可选字段和
null值进行容错,避免上游字段缺失时反序列化失败。 - 按事件名称解析流:流式客户端应根据事件或增量类型分派处理逻辑,不要依赖固定帧序号。
- 限制工具调用轮数:为工具调用循环设置最大轮数,防止模型重复调用工具。
- 不依赖非标准字段:
system_fingerprint、provider_specific_fields和流式响应中的模型名称回显可能发生变化,不要用于稳定的业务判断或直接展示。
评价此篇文章
