文章目录
-
- 前言
- 1 系统提示词:给模型写的岗位说明书
-
- 1.1 有没有提示词,效果天差地别
- 1.2 一套直接抄的实用模板
- 1.3 新手最容易踩的三个坑
- 2 核心参数详解:每个我都跑过实验
-
- 2.1 temperature:随机性旋钮
- 2.2 max_tokens:输出长度上限
- 2.3 model:模型该怎么选
- 2.4 stream:流式开关
- 3 封装成可复用的函数
- 4 长对话服从度测试
- 5 小结
- 6 动手练一练

P.S. 无意间发现了一个巨牛的人工智能教程,非常通俗易懂,对AI感兴趣的朋友强烈推荐去看看,
传送门https://blog.csdn.net/HHX_01
前言
做Agent开发的兄弟,我赌你肯定纠结过俩问题:
系统提示词怎么写,模型才乖乖听话?
API里那几个参数调来调去,到底在调个啥?
今天全是我自己踩过坑、跑过实验的干货,看完直接就能上手调旋钮。
1 系统提示词:给模型写的岗位说明书
1.1 有没有提示词,效果天差地别
先给你们看个最直观的对比。
就问一句代码有啥问题,不加系统提示词的时候,模型能给你从除法的定义讲起,再扯半篇异常处理体系,绕半天才说到重点。跟上课老教授似的,铺垫十分钟,知识点三十秒。
加了精准的系统提示词呢?直接说问题加解法,干净利落。
# 不用 system prompt
messages = [{"role": "user", "content": "帮我看看这段代码有什么问题:x = 5 / 0"}]
# 用 system prompt
messages = [
{"role": "system", "content": "你是一个代码审查员。只指出问题和修法,每条不超过两行,不讲背景知识。"},
{"role": "user", "content": "帮我看看这段代码有什么问题:x = 5 / 0"},
]
同样的问题,输出天差地别。说白了,系统提示词就是定模型的身份和说话方式,相当于给它发了份岗位说明书。
1.2 一套直接抄的实用模板
我自己写提示词,一直用四块结构,按需增减就行,基本不会出大错。
SYSTEM_PROMPT = """
# 角色
你是一个Python代码审查助手。
# 行为规则
1. 只指出问题,不重写整个文件
2. 每个问题格式:[严重程度] 位置 – 问题 – 建议修法
3. 不确定的地方明确说"不确定",禁止猜测
# 输出格式
用Markdown列表输出,最多5条,按严重程度排序。
# 边界
如果代码与Python无关,回复"仅支持Python代码"。
"""
四块分别是:角色(你是谁)→ 规则(怎么干活)→ 格式(输出长啥样)→ 边界(啥活不干)。
就跟公司招人的JD一样,说清楚岗责、要求、交付标准、禁区,比啥都强。
1.3 新手最容易踩的三个坑
第一个坑:玩命堆形容词。
“你是一个非常非常专业的顶级专家”——说真的,没用。模型不吃你这套彩虹屁。
就像你点外卖跟商家说“你是世界级大厨”,不如直接说“多放辣少放盐别放香菜”。要写可执行的规则,别整虚头巴脑的情绪价值。
第二个坑:规则互相打架。
一边说“回答要详尽全面”,一边又要求“不超过50字”,模型直接精神分裂,只能随机挑一个服从。
写完自己通读一遍,有冲突的直接删掉,别让模型做选择题。
第三个坑:全用否定句提要求。
“不要啰嗦”“不要废话”——效果远不如“每条不超过两行”。
模型对正向指令的服从度高多了,否定句只用来划红线的时候用,比如“禁止编造API名称”。
2 核心参数详解:每个我都跑过实验
光会写提示词还不够,API参数才是调节输出的关键旋钮。每个我都做过对照实验,给你们讲明白到底在控啥。
2.1 temperature:随机性旋钮
原理一句话:模型每生成一个词,都会给所有候选词算个概率分布,temperature就决定了抽样的时候敢不敢选冷门词。
设成0,就永远选概率最高的那个词,同样的输入,输出几乎一模一样,主打一个稳定。
数值越高,比如1.5,低概率的词也敢往外蹦,输出花样多、有创意,但也更容易胡说八道。
我写了段测试代码,同一个问题不同温度各跑3次,差别一目了然。
def ask(temp: float) –> str:
resp = client.chat.completions.create(
model="deepseek-chat",
temperature=temp,
messages=[{"role": "user", "content": "用一个比喻解释什么是递归,一个词的比喻也算"}],
)
return resp.choices[0].message.content[:30]
for t in (0, 0.7, 1.5):
print(f"— temperature={t} —")
for _ in range(3):
print(" ", ask(t))
跑出来的结果很明显:t=0的时候三次输出几乎没差,跟复读机似的;t=1.5的时候三次全不一样,偶尔还能给你整出个离谱到笑出声的比喻,像喝了假酒的创意总监。
给你们整理了场景推荐值,直接抄就行:
| 代码生成、数据抽取、分类 | 0 ~ 0.3 | 要稳定可复现 |
| 日常对话、总结改写 | 0.5 ~ 0.8 | 平衡灵活和稳定 |
| 创意写作、起名字 | 0.9 ~ 1.2 | 要发散脑洞 |
做Agent开发听我一句,全程0~0.3就完事了。你要的是个靠谱干活的执行者,不是天天给你整活的艺术家。
2.2 max_tokens:输出长度上限
这个参数好理解,就是模型最多输出多少个token,超了直接硬截断。
resp = client.chat.completions.create(
model="deepseek-chat",
messages=[...],
max_tokens=100, # 回答最多100个token,超过就硬截断
)
主要两个用处:一是当省钱护栏,防止模型失控输出长篇大论烧你token;二是强制造短回答,配合“一句话回答”这类提示词,效果翻倍。
提醒一个巨容易踩的坑:如果输出被截断了,resp.choices[0].finish_reason会是"length",而不是正常结束的"stop"。
print(resp.choices[0].finish_reason) # "stop"=正常结束 "length"=被截断
调试的时候发现回答莫名断在半句话,先查这个字段,别上来就骂模型傻。
2.3 model:模型该怎么选
同一家厂商一般都有好几个模型档位,比如普通对话款和推理款。
普通对话模型:快、便宜,应付Agent里的常规节点绰绰有余。
推理模型:贵、慢,但复杂问题正确率高,难活再上。
工程上的经验:别全程用最贵的模型,纯纯冤大头。
就像公司干活,打印整理、简单判断用实习生就行,核心决策才请总监。路由、格式化、简单分类用便宜模型,关键决策再上推理模型,这才是成本优化的基本操作。
2.4 stream:流式开关
这个参数就是控制逐字返回效果的,后面有一整篇专门讲它,这里先记个参数名就行。
3 封装成可复用的函数
从这篇开始,后面的内容会反复用到LLM调用。我建议你们把它封装成一个统一的函数,存成llm_utils.py,后面直接import就行,省得每次复制粘贴改参数。
# llm_utils.py
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["OPENAI_API_KEY"],
base_url="https://api.deepseek.com",
)
def chat(
messages: list[dict],
model: str = "deepseek-chat",
temperature: float = 0.3,
max_tokens: int = 1024,
) –> str:
"""统一封装的LLM调用。Agent开发默认低temperature。"""
resp = client.chat.completions.create(
model=model,
messages=messages,
temperature=temperature,
max_tokens=max_tokens,
)
if resp.choices[0].finish_reason == "length":
print("[警告] 输出被max_tokens截断")
return resp.choices[0].message.content
# 用法示例:
if __name__ == "__main__":
print(chat([
{"role": "system", "content": "你是简洁的编程助手。"},
{"role": "user", "content": "一句话解释什么是异步编程。"},
]))
封装的好处谁用谁知道:参数默认值统一,所有调用默认都是0.3的温度;输出截断自动打警告;换模型只改一处就行,维护起来巨省心。
4 长对话服从度测试
很多人不知道一个坑:系统提示词不是硬约束,是软引导。对话越长,模型越容易把它忘了。
我做过个实验,要求模型只能回答“是”或“否”,连着问几个问题,看看能坚持几轮。
system = "你回答任何问题都只能用'是'或'否'。"
history = [{"role": "system", "content": system}]
for q in ["Python是编程语言吗?", "天空是蓝的吗?", "详细介绍一下Python的历史",
"详细讲讲图灵的故事"]:
history.append({"role": "user", "content": q})
a = chat(history, temperature=0)
history.append({"role": "assistant", "content": a})
print(f"Q: {q}\\nA: {a[:50]}\\n")
典型现象:前两三轮还乖乖答“是”“否”,到后面直接“越狱”,开始长篇大论,把只能答两个字的规矩忘得一干二净。
结论很明确:别迷信系统提示词能管到底,上下文越长,服从度越低。
两个应对方案: 第一,重要的格式要求,在最后一轮用户消息里再强调一遍,越靠后的指令,模型越听话。 第二,如果输出必须严格结构化,别光靠提示词,用代码解析加失败重试兜底,比啥都靠谱。
5 小结
最后给你们划个重点,记不住的收藏这一段就行:
- 系统提示词按「角色→规则→格式→边界」四块写,要正向可执行,别整虚的
- Agent开发temperature就用0~0.3,稳定比啥都重要
- max_tokens是输出护栏,回答断了先查finish_reason
- 模型分档混用,便宜模型干杂活,推理模型干难活,控制成本
- 长对话系统提示词会失效,重要约束末尾重申+代码兜底
6 动手练一练
光看没用,动手跑一遍才记得住,留三个小作业:
- 用四块结构,给「外卖推荐助手」写一个系统提示词
- 跑一遍temperature实验,亲眼看看0和1.5的差别到底有多大
- 把max_tokens设成20,问一个长问题,观察finish_reason的值
下一篇咱们聊流式输出——AI一个字一个字蹦出来的效果,到底怎么用代码稳稳接住。
P.S. 无意间发现了一个巨牛的人工智能教程,非常通俗易懂,对AI感兴趣的朋友强烈推荐去看看,传送门https://blog.csdn.net/HHX_01



