如何调用大模型
作者:程序员马丁
Ragent AI —— 从 0 到 1 纯手工打造企业级 Agentic RAG,拒绝 Demo 玩具!AI 时代,助你拿个offer。
上一篇咱们搞清楚了大模型是什么——参数量、Token、上下文窗口、Temperature 这些核心概念,以及 Chat 模型和基座模型的区别。最后留了一个悬念:开发者需要通过 API 调用大模型,才能把它集成到自己的系统里。
这一篇,咱们动手。
这篇结束后,你会用自己写的 Java 程序和大模型对话——发一个问题过去,拿到一个回答回来,就像调用一个普通的 HTTP 接口一样。而且你会掌握两种调用方式:非流式(一次性拿到完整回答)和流式(像 ChatGPT 那样逐字输出)。
在写代码之前,有一件事必须先搞清楚:你要发什么格式的请求,会收到什么格式的响应。这就是 OpenAI 接口协议。
OpenAI 接口 协议:大模型 API 的“普通话”
1. 为什么要先讲 OpenAI 协议
你可能会问:我们后面用的是 SiliconFlow 平台上的 Qwen 模型,为什么要讲 OpenAI 的协议?
原因很简单:OpenAI 的 Chat Completions API 已经成了大模型 API 的事实标准。就像 HTTP 是 Web 世界的通用协议一样,OpenAI 的接口格式是大模型 API 世界的“普通话”。
国内的 DeepSeek、通义千问、智谱 GLM、SiliconFlow,国外的 Anthropic(Claude)、Google(Gemini)——几乎所有主流厂商都提供了兼容 OpenAI 协议的 API 接口(截止 2025 年 2 月,Anthropic 和 Google 都已经有了自己的原生 API 协议,但同时也提供了 OpenAI 兼容层)。这意味着什么?你只需要学一套协议,就能调用市面上几乎所有的大模型。换模型的时候,改一下 baseURL 和 API Key 就行,代码逻辑一行不用动。
所以这套协议值得你花时间搞清楚,后续系列中所有的 API 调用(Chat API、Embedding API、Reranker API)都建立在这个基础上。
2. 请求格式详解
调用大模型 API,本质上就是发一个 HTTP POST 请求。请求体是一个 JSON,长这样:
{
"model": "Qwen/Qwen3-32B",
"messages": [
{
"role": "system",
"content": "你是一个专业的电商客服助手,只回答和退货、换货、物流相关的问题。"
},
{
"role": "user",
"content": "买了一周的东西还能退吗?"
}
],
"temperature": 0.1,
"max_tokens": 512,
"stream": false
}
下面逐个字段讲清楚。
2.1 model:指定要调用的模型
model 字段告诉平台你要用哪个模型来处理这次请求。不同平台的模型 ID 格式可能不同:
| 平台 | 模型 ID 示例 | 说明 |
|---|---|---|
| SiliconFlow | Qwen/Qwen3-32B | 厂商/模型名 格式 |
| OpenAI | gpt-4o | 直接用模型名 |
| DeepSeek | deepseek-chat | 直接用模型名 |
本系列统一使用 SiliconFlow 平台上的 Qwen/Qwen3-32B,中文效果好,适合学习和实验。该模型为付费模型,但价格很低,充值几块钱就够实验很久。
2.2 messages:对话消息数组
messages 是整个请求中最核心的字段。它是一个数组,里面的每条消息都有两个属性:role(角色)和 content(内容)。
模型不是只看你当前这一句话,而是看整个 messages 数组。你可以把它理解为一段对话记录——模型会根据这段完整的对话记录来生成回答。
2.3 messages 中的角色机制
messages 数组中的每条消息都有一个 role,一共有三种角色:
system(系统角色)
系统消息用来定义模型的行为规则,相当于给模型一份工作手册。模型会始终遵守系统消息中的指令。
比如你设置了 "role": "system", "content": "你是一个专业的电商客服助手,只回答和退货、换货、物流相关的问题",那么当用户问“今天天气怎么样”时,模型会拒绝回答,因为这不在它的“工作范围”内。
system 消息在 RAG 系统中非常重要——后续我们会通过 system 消息告诉模型"根据以下参考资料回答用户的问题,如果资料中没有相关信息,请如实告知"。
user(用户角色)
用户消息就是用户的输入,也就是用户问的问题。
assistant(助手角色)
助手消息是模型之前的回答。它的作用是构建多轮对话的上下文。
举个例子,一段多轮对话的 messages 数组长这样:
{
"messages": [
{"role": "system", "content": "你是一个电商客服助手"},
{"role": "user", "content": "你们支持七天无理由退货吗?"},
{"role": "assistant", "content": "支持的。自签收之日起7天内,商品未使用且不影响二次销售的,可以申请七天无理由退货。"},
{"role": "user", "content": "那运费谁出?"}
]
}
模型看到这个数组,就知道之前聊过退货的话题,所以能理解“那运费谁出”问的是退货运费,而不是发货运费。如果你只发最后一句“那运费谁出”,模型根本不知道你在说什么。
大模型本身是没有记忆的。每次 API 调用都是独立的,模型不会记住上一次调用的内容。所谓的多轮对话,其实是你在每次请求中把之前的对话历史都带上,让模型看到完整的上下文。这也是为什么对话越长,消耗的 Token 越多——因为每次请求都要把历史消息重新发一遍。
来看 一个更直观的例子——同一个问题,不同的 system 消息会导致完全不同的回答风格:
| system 消息 | 用户问题 | 模型回答风格 |
|---|---|---|
| 你是一个专业的技术顾问 | Java 和 Python 哪个好? | 客观分析两种语言的优劣势和适用场景 |
| 你是一个 Java 狂热粉丝 | Java 和 Python 哪个好? | 疯狂吹 Java,贬低 Python |
| 你是一个五岁小孩 | Java 和 Python 哪个好? | 用幼稚的语气回答,可能说"我不知道这是什么" |
这就是 system 消息的威力——它能从根本上改变模型的行为模式。
关于 OpenAI 的 developer 角色:OpenAI 在新版 API 中引入了
developer角色来替代system角色(参考 OpenAI 官方文档)。两者的功能类似,都是用来定义模型的行为规则。不过目前大多数兼容 OpenAI 协议的平台(包括 SiliconFlow、DeepSeek 等)仍然使用system角色,所以本系列统一使用system。如果你直接调用 OpenAI 官方 API,可以用developer替换system,效果是一样的。
2.4 temperature、max_tokens、top_p 等参数
除了 model 和 messages,还有几个常用的可选参数:
| 参数 | 类型 | 说明 | RAG 场景推荐值 |
|---|---|---|---|
temperature | float | 控制回答的随机性,0~2 之间。上一篇详细讲过 | 0~0.3 |
max_tokens | int | 模型最多生成多少个 Token。超过这个数就会被截断 | 512~2048(根据预期回答长度设置) |
top_p | float | 另一种控制随机性的方式,0~1 之间。和 temperature 二选一即可 | 0.7~0.9 |
stream | boolean | 是否启用流式返回。true 为流式,false 为非流式 | 根据场景选择 |
temperature和top_p都是控制随机性的参数,一般只调其中一个就行。本系列统一用temperature,更直观。
2.5 stream:流式开关
stream 参数决定了模型的回答是一次性返回还是逐块推送:
stream: false(默认):模型生成完所有内容后,一次性返回完整的 JSON 响应。适合后台处理场景stream: true:模型每生成一小段内容就立刻推送给客户端,客户端可以实时展示。适合面向用户的对话场景
这两种方式的区别和实现,后面会用完整的代码示例来演示。
3. 响应格式详解
发出请求后,模型会返回一个 JSON 响应(这里先看非流式的响应格式):
{
"id": "chatcmpl-abc123",
"object": "chat.completion",
"created": 1700000000,
"model": "Qwen/Qwen3-32B",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "支持的。根据我们的退货政策,自签收之日起7天内,商品未经使用且不影响二次销售的,您可以申请七天无理由退货。请在订单详情页点击\"申请退货\"按钮,按照提示操作即可。"
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 42,
"completion_tokens": 68,
"total_tokens": 110
}
}
关键字段说明:
id:这次请求的唯一标识,用于日志追踪choices:模型的回答数组。通常只有一个元素(除非你设置了n参数要求生成多个回答)choices[0].message:模型的回答,格式和请求中的 message 一样,role是assistant,content是回答内容choices[0].finish_reason:模型停止生成的原因usage:Token 用量统计
3.1 usage:Token 用量统计
usage 字段告诉你这次调用消耗了多少 Token:
| 字段 | 含义 |
|---|---|
prompt_tokens | 你发送的内容(system + user + assistant 历史消息)消耗的 Token 数 |
completion_tokens | 模型生成的回答消耗的 Token 数 |
total_tokens | 总 Token 数 = prompt_tokens + completion_tokens |
API 按 Token 计费,所以这个字段帮你监控成本。上面的例子中,输入 42 个 Token,输出 68 个 Token,总共 110 个 Token。
3.2 finish_reason:模型为什么停下来了
finish_reason 有两个常见的值:
| 值 | 含义 | 说明 |
|---|---|---|
stop | 正常结束 | 模型认为回答已经完整,主动停止 |
length | 达到长度上限 | 回答被 max_tokens 截断了,内容可能不完整 |
如果你经常看到 finish_reason: "length",说明你的 max_tokens 设小了,模型的回答被截断了。把 max_tokens 调大一些就行。
4. 为什么国内厂商都 兼容这个协议
OpenAI 是最早定义这套 Chat Completions API 协议的,围绕它已经形成了庞大的生态:
- 各种 SDK 和框架(LangChain、Spring AI、LlamaIndex)都默认支持 OpenAI 协议
- 开发者社区的教程、示例代码大多基于这个协议
- 各种工具(Postman 模板、VS Code 插件、命令行工具)都兼容这个格式
国内厂商兼容这个协议,开发者就能零成本迁移。你用 SiliconFlow 写的代码,想切换到 DeepSeek 官方 API,只需要改两个东西:
// SiliconFlow
baseURL = "https://api.siliconflow.cn/v1/chat/completions"
apiKey = "你的 SiliconFlow API Key"
// 切换到 DeepSeek
baseURL = "https://api.deepseek.com/v1/chat/completions"
apiKey = "你的 DeepSeek API Key"
代码逻辑一行不用改。这就是兼容协议的好处。
SiliconFlow 平台:注册与获取 API Key
1. 为什么选择 SiliconFlow
上一篇已经提过技术选型的理由,这里再简单汇总一下:
- 国内平台,网络访问没有障碍,不需要特殊网络环境
- 注册简单,手机号即可注册,新用户有免费额度
- 支持多种主流开源模型(Qwen、DeepSeek、GLM、Llama 等),一个平台就能用多种模型
- API 完全兼容 OpenAI 协议,学会了这一套,切换到其他平台零成本
- 部分模型可免费调用,足够学习和实验使用