零基础入门 DeepSeek 大模型 API 开发全指南:max_tokens 停止序列 temperature 系统提示四大核心参数详解、调优实战与两种 Prompt 写法效果对比教程
-
调用 DeepSeek 大模型 API 的四大核心可控参数为:
max_tokens、stop(停止序列)、temperature、system(系统提示),分别控制输出长度、停止时机、随机程度、角色设定。 -
max_tokens是输出 token 数的上限,设太小会截断内容,设太大浪费算力;生成 token 越多,接口响应耗时越长。 -
stop停止序列可以让模型遇到指定字符串时立刻停止生成,适合控制结构化输出的边界,但停止符本身不会出现在返回结果中。 -
temperature控制输出随机性,0 最保守稳定、适合计算分析类任务,1 最自然多样、适合创意写作类任务。 -
system系统提示用于设定模型全局角色与规则,指令效果比写在用户消息中更稳定;全部指令堆在 user 消息里也能运行,但规范性和效果可控性更差。 -
生产环境推荐「system 放角色规则 + user 放具体任务」的拆分写法,是兼顾效果、规范与可维护性的最优方案。
一、课程学习目标
本文面向零基础接触大模型 API 开发的读者,完整覆盖 DeepSeek 接口四大核心参数的原理、用法与调优技巧,同时对比两种常见的 Prompt 消息写法。学完后你将掌握:
-
理解
max_tokens参数的作用与调优方法 -
使用
temperature参数精准控制模型输出的随机性 -
掌握
stop停止序列的用途与使用注意事项 -
理解系统提示(System prompt)的角色与最佳实践
-
分清两种消息结构写法的差异,能根据场景选择最优方案
二、开发环境初始化
DeepSeek 完全兼容 OpenAI 接口规范,使用官方 OpenAI Python SDK 即可完成调用,标准初始化代码如下:
from dotenv import load_dotenv
from openai import OpenAI
import os
加载环境变量
load_dotenv()
my_api = os.getenv("DEEPSEEK_API_KEY")
初始化 DeepSeek 客户端
client = OpenAI(
api_key=my_api,
base_url="https://api.deepseek.com"
)
三、核心参数一:max_tokens(最大令牌数)
3.1 什么是 Token
大语言模型不是以完整单词 / 汉字为单位处理文本,而是以 token(令牌) 为最小单位。你可以把 token 理解为"文本碎片":模型先把输入文本拆成 token,再逐 token 生成输出内容。
-
英文场景:1 个 token ≈ 3.5 个英文字符
-
中文场景:1 个 token ≈ 1~2 个汉字
3.2 参数作用
max_tokens 用来设置模型输出内容的最大 token 数量上限。
-
设得太小:模型生成到一半就被强制截断,内容不完整
-
设得太大:模型不会强行填满上限,只是获得了更大的生成空间,内容短的时候依然会提前自然结束
3.3 两种停止状态
通过响应对象的 finish_reason 可以判断模型停止的原因:
|
停止原因 |
含义 |
说明 |
|
|
自然停止 |
模型认为内容已经说完,主动结束生成 |
|
|
截断停止 |
输出 token 数达到了 |
3.4 为什么要调整 max_tokens
|
考量维度 |
具体说明 |
|
API 配额限制 |
token 用量会计入接口额度,合理设置可控制成本、避免超量 |
|
性能效率 |
生成 token 越多,耗时越长、算力消耗越大,合理设值可优化响应速度 |
|
输出质量 |
上限太低会截断内容导致信息缺失,上限太高会造成不必要的性能开销 |
3.5 性能规律
生成 token 数量与耗时基本呈正相关:生成的内容越长,接口响应时间越久。例如生成 100token 仅需 1 秒左右,生成 4000token 则需要近 30 秒。
3.6 参数汇总表
|
参数项 |
详细说明 |
|
参数名称 |
|
|
核心作用 |
限制模型输出的最大 token 数量 |
|
取值范围 |
1 ~ 接口允许的最大值(DeepSeek 上限为 393216) |
|
常见问题 |
取值过小导致输出截断、内容不完整 |
|
调优建议 |
简单问答设 200-500,长文本生成设 1000-4000,避免无意义设超大值 |
使用 max_tokens
max_tokens 参数用于设置模型生成 token 数量的上限。举个例子:如果我们让模型写一首诗,并将 max_tokens 设为 10,模型会开始生成内容,当生成的 token 数达到 10 时会立即停止,这通常会导致输出被截断、内容不完整。我们来试一下:
truncated_response = client.chat.completions.create(
model="deepseek-v4-flash",
max_tokens=10,
messages=[
{"role": "user", "content": "写一首诗"}
]
)
print(truncated_response.choices[0].message.content)
输出示例:
为你写一首小诗:
晨
实际运行结果会有随机波动,但一定会出现截断。模型刚开始写诗,生成 10 个 token 后就被迫停止。
我们还可以通过响应对象的 finish_reason 属性,查看模型停止生成的原因。在这个场景下,它的值为 length,代表模型因达到最大 token 限制而停止。
print(truncated_response.choices[0].finish_reason)
输出:
'length'
当然,如果我们把 max_tokens 设为更大的值,通常就能得到完整的诗作:
longer_poem_response = client.chat.completions.create(
model="deepseek-v4-flash",
max_tokens=500,
messages=[
{"role": "user", "content": "写一首诗"}
]
)
print(longer_poem_response.choices[0].message.content)
输出示例:
《心音》
在静谧的时分,
当世界渐渐沉寂,
我听见心底的低语——
温柔的字句轻轻摇曳。
...
这是 max_tokens 设为 500 时模型生成的完整内容。 如果查看这个响应的 finish_reason,会看到值为 stop,代表模型自然完成了生成,内容已经输出完毕,主动停止了续写。
print(longer_poem_response.choices[0].finish_reason)
输出:
'stop'
需要注意的是:模型在生成时并"不知道" max_tokens 的存在。调整 max_tokens 不会改变模型的生成逻辑,只是给了模型更大的生成空间(数值大时)或强制截断输出(数值小时)。
同样重要的是:增大 max_tokens 不代表模型一定会生成对应数量的 token。比如我们让模型讲一个笑话,哪怕把 max_tokens 设为 1000,输出也通常远少于 1000 个 token。
response = client.chat.completions.create(
model="deepseek-v4-flash",
max_tokens=1000,
messages=[{"role": "user", "content": "讲一个笑话"}]
)
print(response.choices[0].message.content)
输出示例:
分享一个经典冷笑话:
为什么科学家不信任原子?因为万物都是原子"凑"出来的!
print(response.usage.completion_tokens)
输出:
55
在上面的例子中,我们把 max_tokens 设为 1000,但最终生成的内容只有 55 个 token。设置上限只是划定了最大边界,不代表模型会填满这个上限。
性能演示
我们来直观感受一下生成 token 数量对性能的影响。下面的函数让模型生成一段长对话,分别使用 3 档不同的 max_tokens 各运行一次,打印实际生成的 token 数与耗时。
import time
def compare_num_tokens_speed():
token_counts = [100, 1000, 4096]
task = """
请生成一段至少 5000 字的长对话,两个角色讨论社交媒体对心理健康的影响。
两位角色观点不同,展开理性、深入的辩论。
"""
for num_tokens in token_counts:
start_time = time.time()
response = client.chat.completions.create(
model="deepseek-v4-flash",
max_tokens=num_tokens,
messages=[{"role": "user", "content": task}]
)
end_time = time.time()
execution_time = end_time - start_time
print(f"生成 token 数:{response.usage.completion_tokens}")
print(f"执行耗时:{execution_time:.2f} 秒\n")
compare_num_tokens_speed()
示例输出:
生成 token 数:100
执行耗时:1.51 秒
生成 token 数:1000
执行耗时:8.33 秒
生成 token 数:3433
执行耗时:28.80 秒
可以清晰看到:模型生成的 token 越多,所需的时间就越长。
停止序列(Stop sequences)
另一个实用的参数是 stop(停止序列),它允许我们传入一个或多个字符串作为停止标记。当模型生成的内容中出现这些字符串时,会立即停止继续生成。你可以把它理解为:"如果生成了这个标记,就立刻停下,不要再输出后续内容。"
下面是一个不使用停止序列的请求示例:
response = client.chat.completions.create(
model="deepseek-v4-flash",
max_tokens=500,
messages=[{"role": "user", "content": "生成一个表示人物的 JSON 对象,包含姓名、邮箱、手机号三个字段。"}]
)
print(response.choices[0].message.content)
输出示例:
这是一个表示人物信息的 JSON 对象示例:
{
"name": "张三",
"email": "zhangsan@example.com",
"phoneNumber": "123-456-7890"
}
在这个示例中,JSON 对象包含三个键值对,分别对应...
可以看到,模型确实生成了 JSON 对象,但后面还附带了额外的解释文字。如果我们希望模型输出完 JSON 的闭合符 } 后就立即停止,可以加入 stop 参数:
response = client.chat.completions.create(
model="deepseek-v4-flash",
max_tokens=500,
messages=[{"role": "user", "content": "生成一个表示人物的 JSON 对象,包含姓名、邮箱、手机号三个字段。"}],
stop=["}"]
)
print(response.choices[0].message.content)
输出示例:
这是一个表示人物信息的 JSON 对象示例:
{
"name": "张三",
"email": "zhangsan@example.com",
"phone": "555-1234"
重要提示:注意生成的输出中不包含作为停止序列的 } 本身。如果需要完整可用的 JSON,需要我们手动把结尾的 } 补回去。
我们同样可以通过 finish_reason 查看模型停止的原因,此时值为 stop,代表触发了停止序列。
print(response.choices[0].finish_reason)
输出:
'stop'
多个停止序列
stop 参数支持传入多个停止序列,模型只要遇到其中任意一个,就会立即停止生成。
下面的示例让模型写诗,当生成字母 b 或 c 时停止,共运行 3 次:
def generate_random_letters_3_times():
for i in range(3):
response = client.chat.completions.create(
model="deepseek-v4-flash",
max_tokens=500,
messages=[{"role": "user", "content": "写一首诗"}],
stop=["b", "c"]
)
print(f"第 {i+1} 次响应停止原因:{response.choices[0].finish_reason}")
generate_random_letters_3_times()
示例输出:
第 1 次响应停止原因:stop
第 2 次响应停止原因:stop
第 3 次响应停止原因:stop
三次生成都因为触发了停止序列而提前结束。实际业务中我们通常不会用单个字母作为停止序列,更多用于结构化输出、固定格式截断等场景。
温度(Temperature)
temperature 参数用于控制生成内容的"随机性"与"创造性"。在 DeepSeek 中,它的取值范围为 0~2,默认值为 1。数值越高,输出越多样化、越不可预测,措辞变化越丰富;数值越低,输出越偏向确定性,更倾向于选择概率最高的表述与答案。
模型生成文本时,会预测下一个 token 的概率分布。temperature 的作用就是在采样下一个 token 前,对这个概率分布进行缩放:
-
温度接近 0 时,概率分布会被"压尖",高概率的 token 权重被进一步放大,模型输出更稳定、更保守,优先选择最稳妥的答案。
-
温度接近 2 时,概率分布会被"拉平",低概率 token 的出现概率提升,模型输出更随机、更有探索性,内容更具创造力与多样性。
什么时候调整温度?
一个通用的选型原则:分析类任务使用接近 0 的温度,创意类任务使用接近 1 的温度。
温度效果演示
我们通过一个简单示例直观感受差异。分别使用温度 0 和温度 1,让模型 3 次生成外星行星的名字,要求只输出单个单词:
def demonstrate_temperature():
temperatures = [0, 1]
for temperature in temperatures:
print(f"使用 temperature = {temperature} 调用 3 次")
print("================")
for i in range(3):
response = client.chat.completions.create(
model="deepseek-v4-flash",
max_tokens=100,
temperature=temperature,
messages=[{"role": "user", "content": "想一个外星行星的名字,仅输出单个单词。"}]
)
print(f"第 {i+1} 次响应:{response.choices[0].message.content.strip()}")
demonstrate_temperature()
输出示例:
使用 temperature = 0 调用 3 次
================
第 1 次响应:Xendor
第 2 次响应:Xendor
第 3 次响应:Xendor
使用 temperature = 1 调用 3 次
================
第 1 次响应:Xyron
第 2 次响应:Xandar
第 3 次响应:Zyrcon
可以看到,温度为 0 时,三次输出几乎完全一致。需要注意:即使 temperature=0,也不代表 100% 完全确定,依然可能存在微小波动,但和温度为 1 的情况相比,差异非常明显。
系统提示(System prompt)
system 角色的提示词是对话中的可选配置,用于给模型设定高层指令、定义角色身份、补充背景信息,从而为整段对话定下基调与规则。
关于系统提示的核心要点:
-
它是可选参数,但对设定对话语气、上下文与角色定位非常有用。
-
它作用于整段对话,会影响该次对话中模型的所有回复。
-
借助系统提示可以统一约束模型行为,无需在每条用户消息中重复指令。
通常建议将语气设定、角色设定、全局规则放在系统提示中;而详细的任务指令、外部输入内容(如文档)、示例样本放在用户消息中,效果更佳。系统提示只需要在对话开头设置一次,不需要在每轮用户消息中重复。
我们来试一个例子:
message = client.chat.completions.create(
model="deepseek-v4-flash",
max_tokens=1000,
messages=[
{"role": "system", "content": "你是一位贴心的外语老师,所有回复都使用法语。"},
{"role": "user", "content": "你好,很高兴认识你!"}
]
)
print(message.choices[0].message.content)
输出示例:
Bonjour ! Je suis ravi de vous rencontrer. Comment allez-vous aujourd'hui ?
四、核心参数二:stop(停止序列)
4.1 参数作用
stop 参数允许传入一个或多个字符串作为"停止标记"。模型生成内容时,只要遇到这些字符串,就会立刻停止继续生成,相当于给输出划定了明确的结束边界。
4.2 核心特性
-
触发即停:只要生成内容中出现停止序列,立刻终止后续输出
-
符不返回:停止序列本身不会出现在最终返回的内容里,需要手动补回
-
支持多个:可以同时传入多个停止符,任意一个被触发都会停止
4.3 典型使用场景
-
生成 JSON 时,设置
stop=["}"],让模型输出完 JSON 结构就停止,避免后面附带多余解释 -
生成编号列表时,设置
stop=["4."],保证模型只输出前 3 条,不会多生成额外条目 -
结构化数据提取时,用固定分隔符作为停止标记,精准控制输出范围
4.4 参数汇总表
|
参数项 |
详细说明 |
|
参数名称 |
|
|
核心作用 |
遇到指定字符串时立即终止生成 |
|
传入格式 |
字符串列表,支持单个或多个停止序列 |
|
重要特性 |
停止符本身不会包含在返回结果中 |
|
常见用途 |
结构化输出截断、固定条数控制、格式边界限定 |
五、核心参数三:temperature(温度)
5.1 参数作用
temperature 控制模型输出的随机性与创造性,取值范围 0~2,默认值为 1。
-
数值越低:输出越保守、越确定,优先选概率最高的表述,重复度高
-
数值越高:输出越随机、越有创造力,冷门表述的出现概率提升,内容多样性强
5.2 底层原理
模型每次生成下一个 token 时,会给出所有候选词的概率分布。temperature 本质是对这个概率分布做缩放:
-
接近 0:概率分布被"压尖",高概率词权重进一步放大,输出高度稳定
-
接近 2:概率分布被"拉平",低概率词也有机会被选中,输出天马行空
5.3 取值与场景对应表
|
temperature 取值 |
输出特性 |
适用场景 |
|
0 ~ 0.3 |
高度确定、保守稳定、重复度高 |
数学计算、代码生成、数据提取、客观问答 |
|
0.7 ~ 1.0 |
自然流畅、均衡合理、有轻微变化 |
日常对话、通用文案、内容总结 |
|
1.2 ~ 2.0 |
随机性强、脑洞大、多样性高 |
创意写作、诗歌、头脑风暴、发散构思 |
通用原则:分析类任务用低温,创意类任务用常温 / 高温。
5.4 参数汇总表
|
参数项 |
详细说明 |
|
参数名称 |
|
|
核心作用 |
控制输出内容的随机性与创造性 |
|
取值范围 |
0 ~ 2,默认值为 1 |
|
极端表现 |
0 最稳定,2 最发散 |
|
选型建议 |
求准用低温,求新用高温 |
六、核心参数四:system(系统提示)
6.1 参数作用
system 角色的提示词用于给模型设定全局身份、基调和规则,相当于在对话开始前给模型"立人设",它会影响整段对话中模型的所有回复。
6.2 使用要点
-
适合放:角色身份、语气要求、全局规则、背景设定
-
不适合放:具体任务指令、外部文档内容、示例样本(这类内容放 user 消息效果更好)
-
只需设置一次:不需要在每一轮用户消息中重复
6.3 参数汇总表
|
参数项 |
详细说明 |
|
角色名称 |
|
|
核心作用 |
设定模型全局角色、语气与规则 |
|
作用范围 |
整段对话生效,影响所有轮次回复 |
|
推荐存放内容 |
角色设定、风格要求、全局约束 |
|
不推荐存放 |
具体任务指令、输入数据、示例样本 |
七、专题:两种 Prompt 消息写法深度对比
在实际开发中,很多新手会纠结:角色设定和任务指令,是分开写在 system 和 user 里,还是全部堆在 user 消息里?下面结合你的代码做完整对比。
7.1 两种写法代码示例
写法 A:拆分式(system + user 分工)
messages=[
{"role": "system", "content": f"你是{topic}领域的专家,请围绕该主题生成有深度的思考题,以编号列表形式输出。"},
{"role": "user", "content": f"生成 {num_questions} 个关于{topic}的问题,用编号列表呈现。"}
]
写法 B:合并式(全部写在 user 里)
messages=[
{"role": "user", "content": f"你是{topic}领域的专家,请围绕该主题生成有深度的思考题,以编号列表形式输出。生成 {num_questions} 个关于{topic}的问题,用编号列表呈现。"}
]
7.2 多维度对比表
|
对比维度 |
写法 A:system+user 拆分 |
写法 B:全部放 user |
|
指令遵循度 |
更高,角色设定全局生效,模型更稳定地遵循人设 |
一般,角色指令容易被后续任务内容稀释 |
|
输出稳定性 |
强,多次调用风格、格式一致性更好 |
弱,容易出现格式跑偏、人设弱化 |
|
代码可读性 |
好,角色与任务职责分明,便于维护修改 |
差,所有指令混在一起,长 prompt 时难以调试 |
|
运行兼容性 |
完全兼容,是官方推荐的标准写法 |
也能运行,属于非规范写法 |
|
多轮对话适配 |
优,system 只需要写一次,后续只传 user 消息 |
差,每一轮都要重复角色设定,浪费 token |
|
适合场景 |
生产项目、多轮对话、要求稳定输出 |
快速测试、单轮简单调用、临时调试 |
7.3 效果差异说明
从你实际运行的结果也能看出:两种写法都能成功生成问题,但拆分写法下模型的输出格式更规整、角色感更强,思考题的深度与结构一致性更好;合并写法虽然也能出结果,但格式波动更大,偶尔会出现多余的开场白、编号不规范等问题。
7.4 最终结论
-
快速调试、临时写小脚本:两种写法都能用,合并写法写起来更快
-
正式项目、追求稳定可控:强烈推荐 system + user 的拆分写法,这是行业通用的最佳实践,可维护性与效果都更优
八、实战练习与参考实现
练习要求
编写 generate_questions 函数:
-
接收
topic(主题)和num_questions(问题数量)两个参数 -
生成指定数量的深度思考题,编号列表形式输出
-
要求使用
max_tokens限制长度、system设定角色、stop控制条数边界
参考代码(标准规范写法)
def generate_questions(topic: str, num_questions: int = 3):
response = client.chat.completions.create(
model="deepseek-v4-flash",
max_tokens=1000,
messages=[
{"role": "system", "content": f"你是{topic}领域的专家,请围绕该主题生成有深度的思考题,以编号列表形式输出。"},
{"role": "user", "content": f"生成 {num_questions} 个关于{topic}的问题,用编号列表呈现。"}
],
stop=[f"{num_questions + 1}."]
)
print(response.choices[0].message.content)
调用示例
generate_questions(topic="自由意志", num_questions=3)
完整可运行代码(含初始化与两种写法对比)
from dotenv import load_dotenv
from openai import OpenAI
import os
加载环境变量
load_dotenv()
my_api = os.getenv("DEEPSEEK_API_KEY")
初始化 DeepSeek 客户端
client = OpenAI(
api_key=my_api,
base_url="https://api.deepseek.com"
)
def generate_questions(topic: str, num_questions: int):
# 写法 A:拆分式(system + user 分工)—— 推荐
# questions = client.chat.completions.create(
# model="deepseek-v4-flash",
# max_tokens=1000,
# messages=[
# {"role": "system", "content": f"你是{topic}领域的专家,请围绕该主题生成有深度的思考题,以编号列表形式输出。"},
# {"role": "user", "content": f"生成 {num_questions} 个关于{topic}的问题,用编号列表呈现。"}
# ]
# )
# 写法 B:合并式(全部写在 user 里)—— 当前使用
questions = client.chat.completions.create(
model="deepseek-v4-flash",
max_tokens=1000,
messages=[
{"role": "user", "content": f"你是{topic}领域的专家,请围绕该主题生成有深度的思考题,以编号列表形式输出。生成 {num_questions} 个关于{topic}的问题,用编号列表呈现。"}
]
)
print(questions.choices[0].message.content)
generate_questions('蔡徐坤', 4)

九、写在最后
四大核心参数是驾驭大模型 API 的基础,理解它们的原理与适用场景,就能精准控制输出的长度、风格、格式与角色。再配合规范的消息结构写法,就能写出既稳定又易维护的调用代码。 新手学习建议先从默认参数跑通基础调用,再逐个调整参数观察效果变化,动手调试是理解参数作用最快的方式。
更多推荐




所有评论(0)