1. 调用 DeepSeek 大模型 API 的四大核心可控参数为:max_tokensstop(停止序列)、temperaturesystem(系统提示),分别控制输出长度、停止时机、随机程度、角色设定。

  2. max_tokens 是输出 token 数的上限,设太小会截断内容,设太大浪费算力;生成 token 越多,接口响应耗时越长。

  3. stop 停止序列可以让模型遇到指定字符串时立刻停止生成,适合控制结构化输出的边界,但停止符本身不会出现在返回结果中。

  4. temperature 控制输出随机性,0 最保守稳定、适合计算分析类任务,1 最自然多样、适合创意写作类任务。

  5. system 系统提示用于设定模型全局角色与规则,指令效果比写在用户消息中更稳定;全部指令堆在 user 消息里也能运行,但规范性和效果可控性更差。

  6. 生产环境推荐「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 可以判断模型停止的原因:

停止原因

含义

说明

stop

自然停止

模型认为内容已经说完,主动结束生成

length

截断停止

输出 token 数达到了 max_tokens 上限,被强制截断

3.4 为什么要调整 max_tokens

考量维度

具体说明

API 配额限制

token 用量会计入接口额度,合理设置可控制成本、避免超量

性能效率

生成 token 越多,耗时越长、算力消耗越大,合理设值可优化响应速度

输出质量

上限太低会截断内容导致信息缺失,上限太高会造成不必要的性能开销

3.5 性能规律

生成 token 数量与耗时基本呈正相关:生成的内容越长,接口响应时间越久。例如生成 100token 仅需 1 秒左右,生成 4000token 则需要近 30 秒。

3.6 参数汇总表

参数项

详细说明

参数名称

max_tokens

核心作用

限制模型输出的最大 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 参数支持传入多个停止序列,模型只要遇到其中任意一个,就会立即停止生成。

下面的示例让模型写诗,当生成字母 bc 时停止,共运行 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 核心特性

  1. 触发即停:只要生成内容中出现停止序列,立刻终止后续输出

  2. 符不返回:停止序列本身不会出现在最终返回的内容里,需要手动补回

  3. 支持多个:可以同时传入多个停止符,任意一个被触发都会停止

4.3 典型使用场景

  • 生成 JSON 时,设置 stop=["}"],让模型输出完 JSON 结构就停止,避免后面附带多余解释

  • 生成编号列表时,设置 stop=["4."],保证模型只输出前 3 条,不会多生成额外条目

  • 结构化数据提取时,用固定分隔符作为停止标记,精准控制输出范围

4.4 参数汇总表

参数项

详细说明

参数名称

stop

核心作用

遇到指定字符串时立即终止生成

传入格式

字符串列表,支持单个或多个停止序列

重要特性

停止符本身不会包含在返回结果中

常见用途

结构化输出截断、固定条数控制、格式边界限定


五、核心参数三: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 参数汇总表

参数项

详细说明

参数名称

temperature

核心作用

控制输出内容的随机性与创造性

取值范围

0 ~ 2,默认值为 1

极端表现

0 最稳定,2 最发散

选型建议

求准用低温,求新用高温


六、核心参数四:system(系统提示)

6.1 参数作用

system 角色的提示词用于给模型设定全局身份、基调和规则,相当于在对话开始前给模型"立人设",它会影响整段对话中模型的所有回复。

6.2 使用要点

  • 适合放:角色身份、语气要求、全局规则、背景设定

  • 不适合放:具体任务指令、外部文档内容、示例样本(这类内容放 user 消息效果更好)

  • 只需设置一次:不需要在每一轮用户消息中重复

6.3 参数汇总表

参数项

详细说明

角色名称

system

核心作用

设定模型全局角色、语气与规则

作用范围

整段对话生效,影响所有轮次回复

推荐存放内容

角色设定、风格要求、全局约束

不推荐存放

具体任务指令、输入数据、示例样本


七、专题:两种 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 函数:

  1. 接收 topic(主题)和 num_questions(问题数量)两个参数

  2. 生成指定数量的深度思考题,编号列表形式输出

  3. 要求使用 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 的基础,理解它们的原理与适用场景,就能精准控制输出的长度、风格、格式与角色。再配合规范的消息结构写法,就能写出既稳定又易维护的调用代码。 新手学习建议先从默认参数跑通基础调用,再逐个调整参数观察效果变化,动手调试是理解参数作用最快的方式。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐