简介:这份《2025年DeepSeek:15天指导手册——从入门到精通》是一份面向AI工具新手、职场办公人群及学术科研用户的系统化学习资料,旨在帮助读者用15天从零上手到熟练运用DeepSeek完成日常任务。内容覆盖三分钟创建AI伙伴、认识AI控制台、有效提问的五个黄金法则、新手必学的10个魔法指令,以及文档分析、代码编写、学术论文开题/写作/答辩辅助等真实场景,并配有避坑指南,例如验证码不显示、扫描版PDF处理等实用提醒。资源包共1个文件,为PDF格式,大小仅1.12MB,便于下载与移动端阅读;以“保姆级教学+多场景覆盖”模式展开,适合按章节循序学习或按需查阅。目前已有3111人学习,对于希望提升与AI协作效率、快速上手DeepSeek的读者,这份手册能提供清晰的操作路径和可直接套用的指令模板。
1. 这份 15 天 DeepSeek 手册解决什么问题:从“能调用 API”到“能上线交付”
第一次在业务里真正用 DeepSeek 时,我以为跑通 API 后就结束了:填提示词、拿回结果、收工。直到接手一个 PDF 资料整理需求,才发现从“能调用”到“能交付”之间隔着一条深沟——文档切分不合理时模型答非所问,上下文窗口塞满后输出丢字段,JSON 输出又总在引号或换行符上中断。手里这份“2025年DeepSeek:15天指导手册-从入门到精通.pdf”之所以值得照着执行,是因为它把 DeepSeek 接入、提示词工程、工具调用和本地部署拆成了 15 天可跟进的路线,顺序基本等价于从注册账号到把模型接入业务系统的完整项目周期。适合刚拿到 API Key、想做第一个跑得通项目的开发者,也适合已经调通 demo、却在结构化输出和上下文管理上反复翻车的工程师。接下来我按这条 15 天路线,把能直接复现的命令、参数和避坑经验都铺开讲清楚。
2. 前 5 天怎么走:API 接入、模型选型与第一个能跑的最小脚本
这份手册最有价值的地方在于前 5 天没有让人先背一轮概念,而是直接动手调接口。很多人在这一步就分岔了:有人把时间花在搭一个遥不可及的“大模型平台”上,实际上用一个 OpenAI 兼容的 Python SDK 就够了。先把这 5 天的节奏固定下来:前三天跑通一次完整调用,中间一天做稳定性测试,第五天把模型选型和费用记录逻辑写进代码。
2.1 前三天必须跑通的三件事
第一天,注册账号并拿到 API Key,确认 DeepSeek 的 base_url 和 SDK 兼容情况。常见做法是直接用 openai 库,把 base_url 指到官方地址,密钥从环境变量读取。不要反复折腾网络代理和中间层,先确保能在一个干净环境里返回结果。
第二天,写一个最小调用并观察三个输出:content、finish_reason、usage。很多新手只看 content,一旦结果不对就换提示词,完全没意识到响应其实是被截断了。finish_reason 为 stop 才是正常结束,为 length 说明输出被 max_tokens 卡住,需要调大生成上限或压缩提示词。
第三天,把同一个提示词连续调用三次,观测输出的稳定性。temperature 设成 0 时大部分任务可以稳定下来,但长文本生成仍可能漂移。这种漂移不是玄学,而是采样路径不同导致的,解决方式是给任务增加确定的输出约束,而不是反复改措辞。
2.2 用 Python 完成第一次 DeepSeek API 调用:最小脚本与参数拆解
把前两天合并成一个可以反复用的最小脚本,我一般是这么写的:
import os from openai import OpenAI client = OpenAI( api_key=os.getenv("DEEPSEEK_API_KEY"), base_url="https://api.deepseek.com" ) resp = client.chat.completions.create( model="deepseek-chat", messages=[ {"role": "system", "content": "你是只输出简洁中文的助手。"}, {"role": "user", "content": "把这段商品描述压缩成 20 字以内的卖点:\n材料是食品级不锈钢,容量 1.5L,可以炖汤也可以煮面。"} ], temperature=0.3, max_tokens=256, top_p=0.9 ) print(resp.choices[0].message.content) print("finish_reason:", resp.choices[0].finish_reason) print("prompt_tokens:", resp.usage.prompt_tokens, "completion_tokens:", resp.usage.completion_tokens)逻辑说明:整个调用只依赖一个 chat.completions 接口,messages 列表里带一条 system 和一条 user。DeepSeek 的 API 与 OpenAI 协议兼容,所以后续想换回其他平台模型时,这套代码基本不用动,只需要调整模型名和 base_url。
参数说明:temperature=0.3 是我对“压缩、抽取、结构化”类任务的默认值;创意类任务才会放到 0.7 以上,但格式稳定性会明显变差。max_tokens=256 是为了防止生成失控,正式项目建议至少 512。top_p 建议保持默认 0.9,不要和 temperature 同时大幅调整,否则两个采样参数相互叠加,输出波动会翻倍。print 里打印 usage 和 finish_reason,是为了把“模型有没有按预期完成”和“内容好不好”分开看。
执行时如果出现连接超时或 SSL 错误,先检查 base_url 是否写对,再检查终端里是否残留了系统级代理环境变量。这一步排查顺序能省掉大多数网络类报错。
2.3 deepseek-chat 和 deepseek-reasoner 怎么选:判断有没有多步推理
到了第四天,你会在手册 API 页看到两个常见模型名:deepseek-chat 和 deepseek-reasoner。选型的核心逻辑不是“贵的更好”,而是任务里有没有多步推理。deepseek-chat 是通用对话模型,适合绝大多数文本生成、抽取、分类任务,速度快、消耗低。deepseek-reasoner 会在给出答案前先走一段推理链,适合数学题、条件判断、多步骤规划,代价是延迟和 token 消耗明显更高。
我的习惯是用一个问题自测:业务逻辑里是否藏着超过两个条件的判断?比如“判断一个售后申请该不该通过,并列出理由”,需要同时考虑订单状态、时间、用户等级,我会切到 reasoner。如果只是“从日志里抽 error 行并转成表格”,chat 就够,不需要让模型反复“思考”。
另外一个容易犯的错是全局无脑用 reasoner。曾经有个项目把所有调用都切到 reasoner,响应时间从 1 秒涨到 8 秒,用户等不住,最后退回 chat 后问题依旧能解决。推理链路只用在真正需要的地方。
第五天记一笔费用账:按任务记录输入 token 和输出 token,拆到业务模块。DeepSeek 的价格相比很多模型并不贵,但失控的调用次数、无限制的重试和过长的输出,会让账单以倍数增长。用一个字段在请求时标记业务来源,月底就能看出哪个模块在烧钱。
2.4 调用前的最后一道防线:重试、超时与费用日志
调用 DeepSeek API 不会永远一次成功,我在生产环境里一定会做三段式防御:区分错误类型、只对可重试的错误重试、记录每次请求耗时和费用。下面这段代码用了 tenacity 库,只对连接类错误做指数退避重试,遇到 4xx 校验错误直接抛出,不浪费重试:
from tenacity import retry, stop_after_attempt, wait_exponential, retry_if_exception_type import httpx class InvalidRequestError(Exception): pass @retry(retry=retry_if_exception_type((httpx.ConnectError, httpx.TimeoutException)), stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, max=8)) def chat_once(client, messages, model="deepseek-chat"): resp = client.chat.completions.create( model=model, messages=messages, temperature=0, max_tokens=512 ) return resp.choices[0].message.content这段代码背后的逻辑是“不要把服务端错误和客户端错误混在一起重试”:4xx 类错误,比如 API Key 无效、messages 格式不对,重试一千次结果也一样;网络中断、服务端 5xx 才值得重试。stop_after_attempt(3) 和 wait_exponential(max=8) 的组合足够应对短时抖动,又不至于让用户等待过久。费用日志我会连同 uuid 一起写进结构化日志,字段包括 model、prompt_tokens、completion_tokens、latency_ms 和业务标识,之后做成本分析时不用再翻聊天记录。
3. 中间 5 天做厚:提示词模板、上下文窗口与 PDF 文档处理
前 5 天把 API 跑通后,真正决定项目能不能用的是后面 5 天。这一章对应手册的第六到十天:系统提示词结构、多轮对话窗口控制、以及 PDF 这样的长文档该怎么喂给模型。这三件事都属于“不做项目发现不了”的功夫,而它们决定了一个 demo 能否变成可维护的系统。
3.1 系统提示词不写长,写结构:角色、约束、格式、示例
我见过很多 prompt 翻车现场:要么只有一句话,模型自由发挥;要么写成三千字说明书,模型反而抓不到重点。把 system prompt 拆成四段,短路率会明显下降:角色定位、行为约束、输出格式、完整示例。示例是最容易被省略但最不能省的一块,尤其是要求输出 JSON 的时候。
system_prompt = """ 你是售后工单整理助手。 任务:把原始描述整理成结构化 JSON。 约束: - 不推断原始文本里不存在的信息; - 日期统一为 YYYY-MM-DD; - 缺失字段输出 null。 输出格式(严格 JSON,不要用 markdown 代码块包裹): {"order_id": string, "problem_type": string, "priority": "high|medium|low", "deadline": string|null} 示例输入: 单号 S20250101 的屏幕裂了,客户想 3 天内换新。 示例输出: {"order_id": "S20250101", "problem_type": "屏幕损坏", "priority": "medium", "deadline": null} """这段提示词的关键不在字多,而在“示例”和“不要 markdown 代码块”这两处。很多模型默认会把 JSON 包在 ```json 块里,后端 json.loads 如果没做兼容,就直接报错;在提示词里先声明不让它包,能省掉一个解析层。“缺失字段输出 null”也是在示例里教会模型的行为,比用一百个字解释继承和空值的区别更有效。
另外一个习惯是:不要把用户输入直接拼进 system prompt。system 只放固定的规则和示例,用户内容单独放 user 消息。这样模型不会把业务里的脏数据带进规则层,后续排查、复现问题也方便很多。
3.2 多轮对话窗口不够怎么办:滑动窗口截断的实用函数
DeepSeek 的上下文窗口虽然不小,但多轮对话里历史消息会持续增长。把整段对话一直追加进 messages,总有一天会撞上窗口上限,到时候模型要么忽略最早的消息,要么直接报错。我一般用滑动窗口法:系统消息永远保留,历史消息只保留离当前问题最近的若干轮,更早的直接丢掉。
def trim_messages(messages, max_budget_tokens=60000, reserve_output=4000): system_msg = [m for m in messages if m["role"] == "system"] history = [m for m in messages if m["role"] != "system"] # 中文场景下,一个字符约等于 1 ~ 1.5 token,这里按 1.2 估算 budget = max_budget_tokens - reserve_output kept = [] used = 0 for msg in reversed(history): size = len(msg["content"]) * 1.2 if used + size > budget: break kept.insert(0, msg) used += size return system_msg + kept逻辑说明:先把 system 消息单独拿出来,保证角色和格式约定永远不会被截掉;然后从最后一条历史开始倒序扫描,估算每条占用的 token 数,累计接近预算就停止。budget 是总窗口减去 reserve_output,后者是给模型生成答案预留的空间,避免输出还没写完就把窗口耗尽。
参数说明:max_budget_tokens=60000 是按 DeepSeek 常见上下文窗口扣去安全余量设置的,如果你的任务经常处理超长文档,可以再往下调;reserve_output=4000 适合一般问答,如果要生成上千行的代码或长文,把它调到 8000。这个函数不能替代真正的检索,但足以让多轮会话手写程序保持稳定,也不急着为一个早期项目引入向量数据库。
3.3 把 PDF 手册变成模型能消费的数据:抽取、清洗、切块
这一章的重点是手册本身可能也是一份 PDF:你需要抽取文本、去除页眉页脚、切块再喂给模型。直接把 PDF 塞给模型这条路走不通,因为模型不直接读二进制 PDF;要先解析文本层。
import pdfplumber # 1. 按页抽取文本,跳过空页 with pdfplumber.open("2025年DeepSeek:15天指导手册-从入门到精通.pdf") as pdf: pages = [page.extract_text() or "" for page in pdf.pages] full_text = "\n".join(page for page in pages if page.strip()) # 2. 按 800 字切块,块与块之间重叠 100 字 chunk_size = 800 overlap = 100 chunks = [] current = "" for para in full_text.split("\n"): if len(current) + len(para) > chunk_size: if current: chunks.append(current) current = current[-overlap:] + para else: current += "\n" + para if current: chunks.append(current)逻辑说明:pdfplumber 负责抽取文本层,解析后过滤空页,再把全文按段落拼接成一块。切块用的是简单窗口:每块 800 个中文字符,块与块之间保留 100 字重叠,避免句子在边界被砍断。
参数说明:chunk_size=800 对应约 1000~1200 token,适合大多数单段落语义任务;如果后续要做向量检索,建议按“章节标题”切块而不是纯字符切块,但那份工作要再加一层标题识别。overlap=100 会让同一句话在两块里重复出现,检索阶段会因此多一次命中,性价比很高。清洗阶段可以再处理两类噪声:页眉页脚里的“第 x 页 共 y 页”,以及页码和日期行;扫描版 PDF 需要 OCR,工程量会明显放大,15 天计划里不建议自己造轮子。
3.4 别急着把 PDF 转成 Word:保留结构比转换格式更重要
看到“pdf转word”这个常见路径,我多半会提醒一句:如果你的最终目标是让模型看懂手册内容,转成 Word 再喂给模型通常是个弯路,因为转换过程会引入表格错位、分页符和乱码,这些噪声会直接污染语义。更稳妥的做法是走上一节的抽取、清洗、切块链路。只有当需要人工阅读、批注或二次编辑时,我才会用转换工具,且转换后还要人工核对页数和表格。结构化数据优先,格式转换是备选方案,这个顺序别搞反。
4. 后 5 天冲刺:工具调用、本地部署与真正接入业务
第 11 到 15 天,路线图的重心会从“训练”转向“工程”。这三件事可以并行练:把模型接入内部工具、把模型在本地或边缘设备上跑起来、把 API 接进 IDE 和业务系统。这里我按实际踩过坑后的优先级排列,先讲最常用的 tool calling。
4.1 用 tool calling 让模型主动查库存:参数与回传机制
tool calling 最核心的概念是:模型不直接执行函数,它只负责告诉你“该调用哪个函数、参数是什么”,真正执行数据库查询、发邮件、调用第三方接口的是你的程序。执行完之后,再把结果回传给模型,让它组织成用户能读的答复。新手最容易漏掉“回传”这一步,结果模型拿到函数结果后接不上原来的对话。
from openai import OpenAI import os, json client = OpenAI(api_key=os.getenv("DEEPSEEK_API_KEY"), base_url="https://api.deepseek.com") tools = [ { "type": "function", "function": { "name": "query_stock", "description": "查询商品 SKU 的当前库存", "parameters": { "type": "object", "properties": { "sku": {"type": "string", "description": "商品编码,例如 A100-23"} }, "required": ["sku"] } } } ] resp = client.chat.completions.create( model="deepseek-chat", messages=[{"role": "user", "content": "帮我查一下 A100-23 还有多少库存"}], tools=tools, tool_choice="auto" ) msg = resp.choices[0].message if msg.tool_calls: tc = msg.tool_calls[0] print("函数:", tc.function.name) print("参数:", tc.function.arguments) sku = json.loads(tc.function.arguments)["sku"] stock = {"A100-23": 42} final = client.chat.completions.create( model="deepseek-chat", messages=[ {"role": "user", "content": "帮我查一下 A100-23 还有多少库存"}, msg, {"role": "tool", "tool_call_id": tc.id, "content": json.dumps({"sku": sku, "stock": stock.get(sku, 0)})} ], tools=tools ) print(final.choices[0].message.content)逻辑说明:第一轮请求返回的 assistant 消息里带着 tool_calls 数组,你需要在第二次请求里把这条 msg 原样放回 messages。紧接着追加一条 role=tool 的消息,里面必须带 tool_call_id=tc.id,否则模型不知道这个结果对应哪一次调用。tool_choice 保持 "auto",让模型根据输入自由决定是否要查库存;如果设成 "required",即使问题是“你好”,模型也会强行调用一次工具,除了浪费一次来回还要处理空参数。
4.2 本地部署 DeepSeek 之前,先看这张硬件方案表
手册后半段常安排一个“本地部署”的章节,但网上不少说法把“本地部署”讲成了玄学。先澄清一个事实:想在自己的笔记本上跑完整版 DeepSeek-V3/R1 不现实,那是一个超大参数的模型。通常说的本地部署跑的是量化后的蒸馏小模型,典型的是 R1 的 7B 或 32B 蒸馏版本,两者完全是两码事。
| 方案 | 显存需求 | 生成速度预期 | 适合场景 | | 官方 API | 无需本地 GPU | 快、延迟稳定 | 生产首选 | | 7B 蒸馏模型,4bit 量化 | 8GB 左右 | 每秒几个到十几个 token | 离线演示、数据不出内网 | | 32B 蒸馏模型,4bit 量化 | 20GB 左右 | 速度明显下降 | 单机自用、实验验证 |
我一般建议本地部署只做两件事:一是学习量化和推理框架的原理,二是处理不能出内网的数据。如果只是为了省 API 费用,建议先算总账:自己买显卡、租机器、维护推理服务的成本和电费,往往比按量付费更贵。工具上,常用来跑 GGUF 模型的是以 llama.cpp 为代表的开源推理框架;参数层面,先 context_length=4096 跑通链路,再根据内存慢慢上调;threads 别直接卡满 CPU 核数,留两个给系统,否则推理时整机卡成 PPT。量化文件优先选模型作者或社区正式发布的版本,混用不同量化器和底座会导致中文乱码,这在第五章还会单独展开。
4.3 把 DeepSeek 接进现有系统与 IDE:灰度切换与配置注意事项
接入现有业务系统时,最安全的方式是预留一个开关:先在内部环境把部分流量切到模型,观察请求成功率、延迟和响应质量,再逐步扩大比例。不要一次性替换掉全部规则逻辑。常见做法是在配置中心加一个功能开关,比如“模型处理比例”,灰度期间保持人工复核通道。
IDE 接入是另一个高频场景。在 VSCode 这类编辑器里的 AI 插件安装时,几乎所有主流辅助工具都支持 OpenAI 兼容接口。配置项通常长这样:
{ "provider": "openai-compatible", "base_url": "https://api.deepseek.com", "api_key": "env:DEEPSEEK_API_KEY", "model": "deepseek-chat" }这段配置的含义是告诉插件“我用 OpenAI 协议,但服务器地址指向 DeepSeek”。api_key 用 env:DEEPSEEK_API_KEY 而不是明文,是为了避免密钥被写进同步到云端的配置或截图里。每次换工具,只需要确认插件支持自定义 base_url,否则就用平台的网关做一层转发。接入后的第一次验证,建议用一个简单的“翻译或解释代码”请求测试,这比一张空白的聊天框更快发现问题。生产系统接入时,上传的 PDF 文件还要先做安全清洗,第五章最后一个坑会专门讲这个被忽略的细节。
5. 执行 15 天计划最容易踩的 5 个坑:现象、原因与解决
这一章是血泪经验。每条我都按“现象→原因→解决”的顺序写,你按顺序排查,大多数“模型突然不行了”的问题都能收敛到这几个地方。
5.1 上下文塞满后模型开始答非所问
现象:把一本很长的 PDF 或整段系统日志直接塞进 messages,前几轮回答还正常,越到后面输出越离谱,要么开始复读,要么回答和问题完全没有关系。
原因:请求的 token 数超过了模型最大上下文,被服务端静默截断或丢弃中间内容。模型看不到完整输入,只能靠残存的记忆“脑补”,自然答非所问。另一个诱因是没做检索,把大量与提问无关的资料全部塞进 prompt,白白挤占窗口。
解决:先用第 3 章的 trim_messages 把历史裁剪成滑动窗口;长文档必须先检索再拼接,只把命中的 3~5 个块传进去。如果任务确实需要长上下文,就把 max_tokens 调低,给输入留出更多空间。上线前用一份“偏长输入”的测试用例专门验证这个场景,别只用短 prompt 测。
5.2 工作流报 “tool calls need immediate results” 卡死
现象:用某个调度框架串模型和业务服务时,第一次 tool call 生成正常,但执行完函数后第二次调用或结果回传时直接报错,提示工具调用需要立即返回结果,整个工作流停住。
原因:这通常不是模型本身的问题,而是编排框架的设计约束。这类框架要求 tool call 生成后立刻同步执行并回传结果,如果你把执行丢给异步队列、慢查询或人工审批,框架会在超时后判定会话无效。问题出在消息往返的时间设计里,忽略了实时性约束。
解决:把工具调用收敛成同步短链路,函数执行控制在秒级;需要人工审批或长时间处理的任务,不要放进同一个实时会话,而是拆成两个独立任务:第一步生成参数,第二步后台执行,再单独把结果通知用户。如果在自己的代码里手动实现 tool calling,同样注意:每轮只处理一个 tool call,执行完立即回传,再把结果追加进 messages,不要让对话悬在半空。
5.3 JSON 输出偶尔解析失败:原因多半在示例和 temperature
现象:同一套提示词和同一份数据,大多数时候 json.loads 能成功,偶尔却失败。失败点要么是字符串里有反斜杠,要么是模型输出里夹了一行解释性文字。
原因:模型是在按概率生成文本,不是在执行 JSON 序列化器。一旦 temperature 偏高,输出格式就容易漂移;另一个常见诱因是示例不规范,比如示例里有中文冒号或注释。用户输入里包含特殊字符时,也能把格式带偏。
解决:temperature 调低到 0,并在提示词里明确写“不要输出解释,只输出 JSON”。解析层做兜底:用正则提取文本里第一个{到最后一个}之间的部分再 json.loads。更稳的方案是让模型只输出值,字段名由程序端拼接,这样就算模型漏掉一个字段也只是值缺失,不会整段报废。遇到极端情况,返回上一次成功的缓存结果,也比给用户报错强。
5.4 本地部署中文乱码、速度慢到没法用
现象:下载量化模型用本地推理框架加载后,输入中文或输出中文变成乱码,或者生成速度仅有每秒两三个 token,等得怀疑人生。
原因:乱码大多是 tokenizer 与模型文件版本不匹配,或者量化参数和底座模型混用了。速度慢有两层原因,一是内存带宽不足,生成 token 时读取整个模型参数量太大;二是上下文长度设太高,显存被占满后开始频繁换入换出。
解决:优先使用模型官方或社区置顶验证过的量化文件,不要自己混搭底模和量化器。推理参数先短上下文 4096 跑通,再根据内存缓慢上调;threads 不要拉满,给系统留余地。如果速度仍然无法接受,直接回归官方 API 是最理性的止损方案——本地部署的目标是学习和合规,不是省钱。
5.5 用户上传的 PDF 带了脚本,触发 XSS 注入
现象:上线一个支持上传 PDF 的服务后,安全测试发现用户上传的 PDF 文本里包含 HTML 脚本标签,解析文本被前端页面渲染时直接执行了,触发脚本注入。
原因:PDF 解析后得到的文本被当作可信内容存储并回显,没有做转义和标签剥离。这在 Spring Boot 这类后端常见,凡是“上传文件→解析→回显”的链路都可能踩到。
解决:在全局过滤器或入口处,对所有上传文件的文本内容做清洗,去掉脚本标签和事件属性,再进入 PDF 解析;文本入库时按纯文本处理,前端回显时再做一次转义。这个安全动作要前置,不要等下游页面去处理。附带一提:如果服务面向外部用户,还建议对上传文件大小、页面数量和解析超时做限流,防止有人用超大 PDF 拖垮解析服务。这个坑不算模型的问题,但凡是做模型产品的工程师几乎都会遇到一次。
6. 从 15 天计划毕业后:用回归测试集固化你的提示词
15 天计划的最后,不是把能找到的 demo 都跑一遍,而是应该回头审视:我下一次改提示词,怎么知道自己没把旧功能改坏?肉眼判断是最不可靠的,因为模型输出有随机性,你觉得新版本变强,可能只是运气。我现在的做法是为每个业务场景建一个小回归集,规模 80~100 条,每条记输入、期望行为和必须出现的字段,然后跑一个脚本自动比对。
import json, os from openai import OpenAI client = OpenAI(api_key=os.getenv("DEEPSEEK_API_KEY"), base_url="https://api.deepseek.com") with open("regression_cases.json") as f: cases = json.load(f) failed = [] for c in cases: resp = client.chat.completions.create( model="deepseek-chat", messages=[{"role": "system", "content": c["system"]}, {"role": "user", "content": c["user"]}], temperature=0 ) got = resp.choices[0].message.content if c["expect"] not in got: failed.append({"case": c["name"], "got": got}) print("通过率:%.1f%% 失败数:%d" % ( (len(cases) - len(failed)) / len(cases) * 100, len(failed)))逻辑说明:脚本逐个读入测试用例,用 temperature=0 固定采样,让同一输入尽量复现同一输出。然后检查期望字段是否出现在结果里;对严格格式要求,可以改成 JSON 字段级别的比较。失败数超过阈值,就说明这次改动有回归,直接回滚或调整再测。
两个让测试集长期生效的习惯值得保留。第一,把测试样例的输入和期望输出都写成文本文件放入代码库,每次提示词改动一起提交,评审时能直观看到改动对哪些场景有影响。第二,定期补充“线上真实失败”的样例,模型答错过的输入都应该进回归集,下次改 prompt 前先验证它是否恢复。
因为 DeepSeek 兼容 OpenAI 协议,这套回归脚本在未来把供应商换成其他模型时基本不用重写。我也靠着它把“上线后因为提示词而翻车”的次数降到接近零。希望帮到你。
本文还有配套的精品资源,点击获取