LLM API 调用
个人学习记录。上一篇把路线和环境整理完,这一篇先不碰 LangChain、LangGraph,也不急着上 Spring AI。先把一次请求怎么发、结果怎么取、Key 怎么放这些东西记录清楚。
什么是 LLM API
LLM = Large Language Model 大语言模型
API = Application Programming Interface 应用程序编程接口
LLM API 就是让你的程序通过 HTTP 请求去调用大语言模型的接口。
可以先当成一次普通的 HTTP 请求来看。
里面主要有几个东西:
HTTP
JSON
API Key
把 model、messages、temperature 这些参数发给模型服务,模型服务再返回一段文本、JSON,或者后面要用到的工具调用结果。
这里先不急着学框架,先把请求体和响应体看清楚。后面用 Spring AI、LangChain、LangGraph 的时候,也能知道框架底下大概做了什么。
这一步在整个路线里的位置
后面大概都会变成这种结构:
用户输入
-> Java / Python 服务
-> 组装 messages
-> 调用 LLM API
-> 解析响应
-> 返回给前端或进入下一步流程
普通聊天是这样。
RAG 也是这样,只是中间多了一步检索:
用户问题
-> 检索知识库
-> 拼接上下文
-> 调用 LLM API
-> 生成答案
Tool Calling 也差不多,只是模型中途可能会判断要不要调用工具:
用户问题
-> 调用 LLM API
-> 模型决定调用哪个工具
-> 后端执行工具
-> 再把工具结果交给模型
-> 生成最终回答
这里先把 API 调用当成入口来学。
这一步不是为了写一个多复杂的聊天机器人,而是先知道大模型请求大概长什么样、返回结果怎么取、错误时应该先查哪里。
Chat Completions 是什么
现在很多模型都支持 OpenAI 兼容格式。
常见路径是:
POST /chat/completions
请求体大概长这样:
{
"model": "模型名称",
"messages": [
{
"role": "system",
"content": "你是一个严谨的 Java 后端工程师,回答要简洁。"
},
{
"role": "user",
"content": "什么是 LLM API?用一句话解释。"
}
],
"temperature": 0.3,
"max_tokens": 512
}
这里先看 messages。
它不是一个普通字符串,而是一组对话消息。
messages 怎么理解
messages 里常见三个角色:
system:给模型定规则
user:用户实际问的问题
assistant:模型之前回复过的内容
system 可以理解成模型的“工作说明”。
比如:
{
"role": "system",
"content": "你是一个严谨的 Java 后端工程师,回答要简洁,尽量给代码示例。"
}
user 就是用户输入。
{
"role": "user",
"content": "用 Java 写一个调用大模型 API 的例子。"
}
assistant 一般用来放历史回复。
单轮测试可以先不传历史。
可以先按这个方式区分:
规则放 system
问题放 user
历史对话按顺序补 assistant / user
规则尽量放在 system 里,不要全部塞到 user。
API Key 先放到环境变量里
API Key 相当于:
账号身份
调用权限
计费凭证
限流凭证
代码里不直接写 Key:
String apiKey = "sk-xxxx";
学习阶段先用 .env 或环境变量就够。
.env:
DASHSCOPE_API_KEY=你的阿里云百炼APIKey
.gitignore:
.env
.venv/
target/
__pycache__/
*.log
先用 curl 调一下
学习 API 可以先用 curl。
因为 curl 能通,说明 Key、地址、模型名、网络至少大方向没问题。
如果 curl 都不通,先查 Key、地址、模型名和网络,再去看 Java、Python 代码。
通义千问
阿里云百炼的通义千问支持 OpenAI 兼容接口。
这里用 Qwen3.5-Flash,接口参数写:
qwen3.5-flash
国内常见是北京区域:
https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions
国际站文档里经常出现新加坡区域:
https://dashscope-intl.aliyuncs.com/compatible-mode/v1/chat/completions
这两个不要混着用。Key 和区域对不上时,可能会出现权限或访问错误。
curl https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $DASHSCOPE_API_KEY" \
-d '{
"model": "qwen3.5-flash",
"messages": [
{
"role": "system",
"content": "你是一个严谨的 Java 后端工程师,回答要简洁。"
},
{
"role": "user",
"content": "什么是 LLM API?用一句话解释。"
}
]
}'
结果如下

Python 调用
Python 这里先用 OpenAI SDK,通过阿里云百炼的 OpenAI 兼容接口调用通义千问。
安装依赖:
python -m pip install openai python-dotenv
如果下载慢:
python -m pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
python -m pip install openai python-dotenv
创建 qwen_chat.py:
import os
from dotenv import load_dotenv
from openai import OpenAI
load_dotenv()
client = OpenAI(
api_key=os.getenv("DASHSCOPE_API_KEY"),
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1"
)
response = client.chat.completions.create(
model="qwen3.5-flash",
messages=[
{
"role": "system",
"content": "你是一个严谨的 Java 后端工程师,回答要简洁。"
},
{
"role": "user",
"content": "什么是 LLM API?用一句话解释。"
}
],
temperature=0.3,
max_tokens=512
)
print(response.choices[0].message.content)
print(response.usage)
运行:
python qwen_chat.py
这里重点看两行:
response.choices[0].message.content
response.usage

第一行是模型回答。
第二行是 token 使用情况,后面做成本统计会用到。
Java 调用
Java 这边先不用 Spring AI。
这里直接用 JDK 自带的 HttpClient,先看清楚底层 HTTP 请求。
这样做的好处是:
不引入太多框架
请求头、请求体都能看清楚
出错时知道先查哪一层
后面再换 Spring AI 心里有底
通义千问示例
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class QwenChatDemo {
public static void main(String[] args) throws Exception {
String apiKey = System.getenv("DASHSCOPE_API_KEY");
if (apiKey == null || apiKey.isBlank()) {
throw new IllegalStateException("请先配置环境变量 DASHSCOPE_API_KEY");
}
String body = """
{
"model": "qwen3.5-flash",
"messages": [
{
"role": "system",
"content": "你是一个严谨的 Java 后端工程师,回答要简洁。"
},
{
"role": "user",
"content": "什么是 LLM API?用一句话解释。"
}
],
"temperature": 0.3,
"max_tokens": 512
}
""";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions"))
.header("Content-Type", "application/json")
.header("Authorization", "Bearer " + apiKey)
.POST(HttpRequest.BodyPublishers.ofString(body))
.build();
HttpClient client = HttpClient.newHttpClient();
HttpResponse<String> response = client.send(
request,
HttpResponse.BodyHandlers.ofString()
);
System.out.println(response.statusCode());
System.out.println(response.body());
}
}
先打印完整 JSON,不急着解析。
原因很简单:
先知道原始响应长什么样,再封装对象。否则对象字段写错了,还以为是模型没返回。
常见参数
model:用哪个模型。
学习阶段先不选最贵、最复杂的模型。先能跑通,再慢慢比较效果。
messages:对话上下文。
后面做多轮对话、RAG、Agent,很多时候都是在维护和加工这组消息。
temperature:随机性。
可以先按这个范围理解:
写代码:0.1 - 0.3
总结文档:0.3 - 0.5
创意写作:0.7 - 1.0
max_tokens:限制输出长度。
先给输出加个限制,避免 token 用得太随意。
stream:是否流式输出。
聊天框逐字显示会用到,但这篇先不展开。先把非流式跑通。
返回结果怎么看
CompletionUsage(completion_tokens=1131, prompt_tokens=36, total_tokens=1167, completion_tokens_details=CompletionTokensDetails(accepted_prediction_tokens=None, audio_tokens=None, reasoning_tokens=1091, rejected_prediction_tokens=None, text_tokens=1131), prompt_tokens_details=PromptTokensDetails(audio_tokens=None, cached_tokens=None, text_tokens=36))
典型响应里重点看这些:
choices[0].message.content:模型回复的内容
usage.prompt_tokens:输入用了多少 token
usage.completion_tokens:输出用了多少 token
usage.total_tokens:总 token
usage 后面会用到。
现在看起来只是一个数字,后面做平台时可能会变成:
成本统计
用户额度
接口限流
模型效果对比
调用链日志
这也是 Java 后端能发挥价值的地方。
模型调用不是只要“能问能答”就结束了,企业里还要知道谁调了、调了多少、花了多少钱、失败了几次。
简单封装
这一步先不在每个文件里复制 HTTP 代码。
可以先有一个最小封装。
Python:
class LlmClient:
def __init__(self, client, model: str):
self.client = client
self.model = model
def chat(self, user_input: str) -> str:
response = self.client.chat.completions.create(
model=self.model,
messages=[
{
"role": "system",
"content": "你是一个严谨的 Java 后端工程师,回答要简洁。"
},
{
"role": "user",
"content": user_input
}
],
temperature=0.3
)
return response.choices[0].message.content
Java 后面可以这样想:
LlmClient
├── chat(String prompt)
├── chat(List<Message> messages)
├── parseResponse(String responseBody)
└── recordUsage(...)
接 Spring Boot 以后,再变成:
@Service
public class LlmService {
public String chat(String message) {
// 这里封装模型调用
return "";
}
}
这时候就能自然接上:
Controller
Service
日志
限流
数据库
用户权限
常见问题
401
先查 API Key。
Key 是否复制完整
Authorization 是否写成 Bearer xxx
环境变量是否真的生效
账户是否欠费或没有权限
404
先查接口地址。
base_url 是否正确
/chat/completions 路径是否正确
通义千问的区域是否选对
model not found
先查模型名。
模型名会变,以控制台和官方文档为准。
请求超时
大模型响应慢是正常的。
工程里不能无限等,后面要加:
连接超时
读取超时
失败重试
熔断降级
这部分先记着,后面做 Spring Boot 服务时再补。
练习清单
这一篇我只要求自己完成几件事:
阿里云百炼 API Key 已准备
.env 已创建
.gitignore 已排除 .env
curl 能调通
Python 能调通
Java HttpClient 能调通
能看懂 messages
能从 choices[0].message.content 取出回复
能看懂 usage token
知道 temperature / max_tokens / stream 的作用
建议目录:
ai-agent-study
├── java
│ └── llm-api-demo
│ └── QwenChatDemo.java
├── python
│ └── llm-api-demo
│ ├── qwen_chat.py
│ ├── llm_client.py
│ └── .env
└── docs
└── llm-api.md
小结
这一篇先记住这句话:
LLM API 可以先按 HTTP + JSON + API Key 来理解。后面更需要慢慢补的,应该是怎么把它稳定、安全、可观测地接进业务系统。
对 Java 后端来说,这一步很适合从工程视角去理解。
先不急着堆框架,先做到:
请求能发出去
响应能看懂
错误能定位
Key 不泄露
token 能统计
这些先打牢,后面学 Spring AI、RAG、Tool Calling、Agent 工作流,心里会更有底一点。


Comments | 0 条评论