☰
从DeepSeek-R1到提示语工程:模型选型与结构化输出实践
2026/11/3 2:58:16 网站建设 项目流程

简介:这份PDF指南面向人工智能从业者、开发者及希望提升大模型使用效率的学习者,围绕国产开源推理模型DeepSeek展开,从背景与发展、核心能力到实际应用逐步讲解。内容覆盖智能对话、文本生成、语义理解、知识推理与代码生成等场景,并重点剖析DeepSeek-R1的特点,比较推理模型与通用模型在任务选择、提示语策略上的差异。文中结合链式思维、提示语设计原则与“从下达指令到表达需求”的转变,给出可操作的优化思路,帮助读者在智能对话、内容创作和编程辅助中更充分地发挥模型能力。资源包共1个PDF文件,大小约5.4MB,结构完整、便于检索阅读;已有3005人学习,适合作为入门到进阶的参考材料。

1. 从入门到精通到底精在哪:一份 PDF 里最该先读的那几页

大多数人拿到《DeepSeek 从入门到精通》这份资料,第一反应是翻到提示语示例那一章,抄几句“你是一位资深……”就走人,用两天发现效果忽好忽坏,然后把文件塞进某个角落再也不打开。我第一遍也是这么干的,翻车翻得很彻底。后来重读才发现,真正值钱的不是那些能直接复制的句子里,而是夹在中间的两张表:一张讲推理模型和通用模型的优势/劣势边界,一张讲五类需求该用什么公式表达。这两张表决定了你后面所有提示语是“碰运气”还是“可复现”。

这份资料由某高校一个做新媒体与人工智能交叉方向的团队整理,围绕 DeepSeek-R1 这个开源推理模型展开,覆盖它是什么、能做什么、怎么用,以及从“下达指令”到“表达需求”的思路转变。它不适合当小说通读,适合当手册查:先建立模型选型的判断力,再练需求表达的写法,最后才是具体场景的模板。做 AI 应用落地的开发者、要把大模型接进业务流程的工程师、以及天天写提示语但说不清为什么有效的从业者,是这份东西的主要受益人群。

2. 推理模型与通用模型:R1 该在什么任务上出场

选型的第一个坑,是把“新模型”当成“更强模型”。R1 这类推理模型在数学推导、逻辑分析、复杂问题拆解上确实压过通用模型一头,但你让它写一首有意境的诗,它给你的东西往往工整得像说明书。原因不玄学,是训练目标不同:一个被往“把逻辑链走完”的方向推,一个被往“把语言分布学好”的方向推。

2.1 两条技术路线的性能本质

资料里给了一张四维对照表,我把它整理成更便于查阅的版本:

维度推理模型(R1 这类)通用模型(GPT 系、BERT 这类)
优势领域数学推导、逻辑分析、代码生成、复杂问题拆解文本生成、创意写作、多轮对话、开放性问答
劣势领域发散性任务,比如诗歌创作、自由联想需要严格逻辑链的任务,比如数学证明、多步核算
性能本质专精于逻辑密度高的任务擅长多样性高的任务
强弱判断并非全面更强,仅在其训练目标领域显著优于通用模型通用场景更灵活,但专项任务需依赖提示语补偿能力

这张表最该被记住的是最后一行。很多团队的选型逻辑是“出了新模型就全量切过去”,结果客服对话变得生硬、营销文案变得像技术文档。正确做法是按任务类型分流:发票金额核对、合同条款比对、SQL 生成、单元测试补全走推理模型;品牌文案、多轮闲聊、开放式头脑风暴走通用模型。混合编排也不丢人,一个业务流程里两段调用分别用不同模型,比强行让一个模型全能要稳得多。

再说 BERT 这类模型为什么出现在同一张表里。它不是生成模型,是做语言理解与分类的,情感分析、意图识别、文本分类这类任务上,一个小尺寸的 BERT 微调模型往往比调用大模型更便宜也更快。资料把它归进“非推理大模型”,本质是提醒你:不是所有 NLP 任务都需要生成式模型来接盘。

2.2 快思慢想:概率预测与链式推理的算力账

资料用“快思慢想”这个说法切开了两类模型的运行方式,这个比喻我觉得比任何公式都好用。

概率预测型(快速反应)靠大量数据训练出的分布,一步到位给出最可能的答案,响应快、算力成本低、依赖预设规则决策,创造力限于模式识别与优化。链式推理型(慢速思考)靠 Chain-of-Thought 把问题拆成步骤逐步推进,慢、贵,但能做自主分析、能处理多维度和非结构化问题。

这笔账要算清楚:同一个问题,走慢速思考的 token 消耗可能是快速反应的几倍到十几倍,延迟也成倍上升。所以“所有请求都上推理模型”在产品上是不成立的,尤其是需要秒回的交互场景。我的常见做法是分层:入口做意图识别,判断这问题是“查个信息”还是“要推一遍逻辑”,前者走通用模型,后者才路由到推理模型,并且给推理链路单独设超时和降级策略。

还有一个容易被忽略的点:链式推理模型会自己展开中间步骤,如果你在提示语里再手工塞一遍“第一步…第二步…”,等于给它套了两层脚手架,反而可能压缩它的推理空间。资料里那句“若强行拆解步骤,反而可能限制其能力”,是这一章里最实用的一句话。

2.3 三条选型硬规则

把上面的分析压成可执行的判断,我一般用这三条:

第一,按任务类型选,不按模型热度选。判断标准是任务对“逻辑链完整性”的要求有多高。要证明、要推导、要逐条核对,走推理模型;要发散、要风格、要多轮来回,走通用模型。

第二,推理模型给简洁指令,通用模型给结构化引导。推理模型已经内化了推理逻辑,你只需要说清目标和约束;通用模型缺什么补什么,需要显式要求分步、给示例、限定输出格式。

第三,别用角色扮演去“激活”推理模型。资料明确写了这条误区:对推理模型使用启发式提示(比如“你是一位资深架构师”)可能干扰它的逻辑主线。这句话我一开始不信,实测过几次之后信了——同一个算法题,加了角色设定之后答案反而更容易跑偏到“架构层面的建议”上去。

判断流程可以简化成一句话:先问这个任务有没有唯一正确答案和明确推导路径,有就上推理模型并给最短指令,没有就上通用模型并给足约束和示例。

3. 提示语的三件套拆解:从「下达指令」走到「表达需求」

资料里对提示语的定义很朴素:用户输入给 AI 系统的指令或信息,用来引导它生成特定输出。真正有价值的是它把提示语拆成了三个可分别打磨的部件,以及后面那套“需求类型 → 表达公式”的映射。这套东西让我从“改十遍提示语碰运气”变成了“定位是哪一件套没写对”。

3.1 指令、上下文、期望:三个部件各管什么

部件作用缺失时的典型症状
指令(Instruction)明确告诉模型要执行什么任务模型答非所问,或自作主张扩展任务范围
上下文(Context)提供背景信息,帮助模型准确理解输出泛泛而谈,像百科词条,不贴你的业务
期望(Expectation)明确输出形式、长度、粒度、风格每次格式都不一样,没法直接进下游系统

三件套里最容易被跳过的是“期望”。工程师写提示语常常只写任务不写格式,结果模型每次返回的结构都不同,解析代码里塞满 if-else,这是血泪经验。把“输出 JSON、字段名为 xxx、不要额外解释文字”写进期望,比在下游写十行容错代码划算。

资料里给了三个对照示例,能看出三件套的密度差异:“将以下内容翻译为法语:Hello, world” 是指令型,只有指令;“假设你是一位 19 世纪的历史学家,评论拿破仑的崛起”加了上下文;“为一篇关于气候变化的文章写一个引言,长度 200 字”加了期望。三句话的信息量递进,模型输出的可控性也递进。

3.2 六种提示语类型与它们各自的边界

资料把提示语分成六类,我在实际项目里给每一类补了一条“什么时候别用”:

指令型,直接下达任务,适合翻译、格式转换、抽取字段。别用在需要模型自己判断取舍的场景,它会把你的指令当唯一真理执行到底。

问答型,提问求答案,适合知识查询、概念解释。别用它做多步推理,问一句答一句,模型不会主动补链条。

角色扮演型,要求模型进入某个身份,适合风格模拟、视角切换、教学口吻改写。别用在推理模型上,也别用在需要严格事实性的任务上——角色会带来“表演性”,模型开始编。

创意型,引导内容生成,适合文案、故事、命名。别指望它一次到位,创意类任务的关键是给约束(字数、风格参照、必须包含的元素),约束越具体越可用。

分析型,要求对给定信息做推理,适合评论情感判断、报告要点归纳、异常原因推测。别把原始数据整段丢进去就完事,得告诉它分析方法和输出结构。

多模态型,文本加图像混合输入,适合读图取字、界面理解、图表解读。别指望它对低分辨率截图做精确数值识别,涉及金额、编号这类关键字段必须人工复核。

这六类不是互斥的,一个成熟提示语往往是指令型打底、分析型做主体、期望部分约束输出格式。分类的意义在于:效果不对时,你能快速定位是“类型选错了”还是“部件没写全”。

3.3 五类需求的表达公式

这是资料里我认为最该背下来的一张表。它把日常需求归成五类,每类给一个公式和两种模型的适配策略:

需求类型特点表达公式推理模型适配通用模型适配
决策需求需权衡选项、评估风险、选最优解目标 + 选项 + 评估标准要求逻辑推演和量化分析直接建议,依赖经验归纳
分析需求需理解数据、发现模式或因果问题 + 数据/信息 + 分析方法触发因果链推导与假设验证表层总结或分类
创造性需求需生成新颖内容主题 + 风格/约束 + 创新方向结合逻辑框架生成结构化创意自由发散,依赖示例引导
验证需求需检查逻辑自洽、数据可靠结论/方案 + 验证方法 + 风险点自主设计验证路径并排查矛盾简单确认,缺乏深度推演
执行需求需完成具体操作任务 + 步骤约束 + 输出格式自主优化步骤,兼顾效率与正确性严格按指令执行,无自主优化

公式看着抽象,落到句子上就很具体。决策需求可以写成“为降低物流成本,现有两种方案:一是自建区域仓库(初期投入高、长期成本低),二是与第三方合作(按需付费、灵活性高)。请按 ROI 模型对比五年总成本并给出推荐”。分析需求写成“分析近三年的销量数据(附 CSV),说明增长趋势与政策关联性,预测下一年的市占率,需说明所用模型及参数依据”。验证需求写成“以下是某结论:模型 A 优于传统方法 B。请验证实验数据是否支持该结论、对照组设置是否存在偏差、重新计算显著性”。

对比一下就知道差别在哪:模糊的提示语给的是“帮我分析一下这个数据”,模型只能给你一段正确但没用的废话;套上公式之后,输出直接能进汇报材料。

3.4 策略差异与三个反复出现的误区

资料按任务类型列了一张策略对照表,我挑几个最常踩的:

数学证明这类任务,推理模型直接抛问题就行,写“证明勾股定理”;给它加“先画图、再列公式、最后推导”的分步指导,反而可能打断它自己的路径。通用模型则必须显式要求分步并给参考框架,否则它倾向于跳过关键步骤直接给结论。

创意写作反过来,推理模型要给风格和边界,比如“以海明威的风格写一个冒险故事,不超过 800 字”,不给约束它容易写成逻辑清晰的流水账;通用模型要给明确的目标和示例,纯开放式指令会让它自由发挥到无法收敛。

代码生成上,推理模型给一句“用 Python 实现快速排序,输出需包含注释”就够;通用模型则要细化到“先解释原理,再写代码,再给一个测试用例,输入输出格式如下”。

三个误区总结成一句话:不要对推理模型用启发式提示,不要对通用模型过度信任。前者会干扰逻辑主线,后者会让你拿到一个看起来很像对的错误答案,这比明显错误更危险。

4. 把文档里的场景跑成代码:文本生成、语义分析与代码补全

文档里的场景讲得比较概念化,真正落到工程上,是把“文本生成、语义理解、代码生成”这三类能力包成可调用、可解析、可回归的函数。这一章按我实际接线时的顺序写:先跑通一次调用,再做结构化输出,最后做批量语义分析和代码验收。

4.1 环境准备与第一次调用

接口层用 OpenAI 兼容的写法最省事,换模型只改 model 字段。先装依赖、配密钥:

pip install openai python-dotenv # 把密钥写进 .env,不要硬编码进代码,也不要提交到仓库 echo 'DEEPSEEK_API_KEY=your_key_here' >> .env

然后是第一次调用,重点是三件套怎么落到 messages 里:

import os from dotenv import load_dotenv from openai import OpenAI load_dotenv() client = OpenAI( api_key=os.environ["DEEPSEEK_API_KEY"], base_url="https://api.deepseek.com", # 兼容层地址,具体以官方文档为准 ) resp = client.chat.completions.create( model="deepseek-chat", # 通用对话线;推理线换成对应的 reasoner 模型名 messages=[ # 上下文:把业务背景交代清楚,别让模型猜 {"role": "system", "content": "你是电商客服质检助手,只依据给定的对话内容判断,不补充外部信息。"}, # 指令 + 期望:一句话说清任务和输出形式 {"role": "user", "content": "判断下面这段客服对话中,客服是否主动告知了退换货时限。只输出 是 或 否。\n\n对话:<粘贴对话>"}, ], temperature=0.2, # 分类判定类任务压低随机性 max_tokens=16, # 只要一个词,限制长度能省钱也能防跑偏 ) print(resp.choices[0].message.content)

逻辑说明:system 承载上下文和角色边界,user 承载指令和期望,这是三件套最省事的落法。temperature 设 0.2 是因为判定类任务不需要发散,越确定越好;max_tokens 设成 16 是为了强制模型别写解释,一旦它开始“首先……其次……”,说明提示语的期望部分没写死。

参数说明:base_url 和模型名以官方文档当前说明为准,不同接入方式的模型标识不一样;推理线模型在采样参数上有限制,常见做法是干脆不传 temperature 和 top_p,让它按自己的策略走,传了也可能被忽略,别把调参精力浪费在这上面。

4.2 结构化输出:让模型直接吐 JSON

文本生成最容易翻车的地方不是内容质量,是格式不稳定。下面这个写法把“期望”写死到极致:

import json PROMPT = """从下面的招聘启事中抽取字段,输出严格的 JSON,不要 Markdown 代码块,不要任何解释文字。 字段定义: - title: 岗位名称,字符串 - city: 工作城市,字符串,多个城市用顿号分隔 - years: 经验要求,整数,不限填 0 - skills: 技能关键词数组,最多 6 个 招聘启事: {jd} """ def extract(jd: str, retry: int = 2) -> dict: for i in range(retry + 1): resp = client.chat.completions.create( model="deepseek-chat", messages=[{"role": "user", "content": PROMPT.format(jd=jd)}], temperature=0, # 抽取任务要绝对稳定 response_format={"type": "json_object"}, # 支持时优先用这个 ) raw = resp.choices[0].message.content.strip() try: return json.loads(raw) except json.JSONDecodeError: # 兜底:去掉可能包裹的代码块标记再试一次 raw = raw.removeprefix("```json").removeprefix("```").removesuffix("```").strip() try: return json.loads(raw) except json.JSONDecodeError: if i == retry: raise return {}

逻辑说明:字段定义写在提示语里而不是写在代码注释里,是因为模型看不到你的注释。重试逻辑不是为了掩盖问题,是为了兜住偶发的格式抖动;如果重试三次还失败,说明提示语的字段定义有歧义,该改提示语而不是加重试次数。

参数说明:temperature 设 0 是抽取类任务的标配;response_format 在支持结构化输出的接口上优先开启,能显著降低解析失败率;skill 数组限 6 个是为了控制输出长度,不设上限时模型容易把“责任心强、抗压能力好”这类软性描述也塞进去,污染下游检索。

提示:JSON 解析失败先看原始返回里有没有中文全角引号或多余换行,这两个是最高频的元凶,不是模型“不听话”。

4.3 批量语义分析:情感与意图的跑法

批量任务的核心不是单次调用写得多漂亮,是限速、重试、结果落盘这三件事。下面是我常用的骨架:

import time from concurrent.futures import ThreadPoolExecutor LABELS = ["咨询价格", "催发货", "申请退款", "投诉质量", "其他"] def classify(text: str) -> str: prompt = ( "把下面的用户留言归到唯一一个类别,只输出类别名,不要解释。\n" f"可选类别:{'、'.join(LABELS)}\n" f"留言:{text}" ) for attempt in range(3): try: r = client.chat.completions.create( model="deepseek-chat", messages=[{"role": "user", "content": prompt}], temperature=0, max_tokens=8, ) label = r.choices[0].message.content.strip() return label if label in LABELS else "其他" # 白名单校验,防自创类别 except Exception: time.sleep(2 ** attempt) # 指数退避 return "其他" with ThreadPoolExecutor(max_workers=4) as pool: results = list(pool.map(classify, texts))

逻辑说明:白名单校验这一步必须加。模型有概率返回“退款申请”这种近义但不在列表里的词,直接入库会导致统计口径漂移。max_tokens 压到 8 是硬约束,逼它不要输出理由。并发数控制在 4 以内,再高容易触发限流,反而整体变慢。

参数说明:如果分类体系超过 20 类,别硬塞进一个提示语,改成两阶段——先粗分大类,再在类内细分,准确率会明显好于一次性给 30 个选项。另外意图识别这种任务,小样本示例比长篇规则有效,给每类两三个典型例子,比写十行判定标准管用。

4.4 代码生成与调试:把模糊需求变成可验收的指令

“写个排序代码”这种指令,模型一定给你东西,但你要花五轮才拿到能用的。改成可验收的写法:

task = """把下面这段 C 实现改写为 Python,要求: 1. 时间复杂度保持 O(n log n),不要退化成 O(n^2); 2. 用 numpy 做数组操作,避免 Python 层循环; 3. 输出完整可运行代码,包含一个 main 里的测试用例,用 time.perf_counter 打印耗时; 4. 代码里对关键步骤加中文注释。 C 代码: <粘贴原始实现>""" resp = client.chat.completions.create( model="deepseek-reasoner", # 逻辑密度高的改写任务走推理线 messages=[{"role": "user", "content": task}], ) print(resp.choices[0].message.content)

逻辑说明:这段提示语把“期望”拆成了四条可检查的约束——复杂度、实现方式、可运行性、可读性。验收标准写进提示语,比事后人工改要省事得多。推理线模型在这里的优势是它会自己核对复杂度是否退化,通用模型则经常直接给你一个双重循环的实现。

参数说明:推理线模型不要传 temperature 之类的采样参数,常见做法是只传 messages;如果返回内容里包含推理过程字段,注意把它和最终答案分开处理,别把思考过程直接打进前端。代码生成的输出务必跑一遍再入库,模型给的“可运行代码”有相当比例缺少 import 或缺边界处理。

5. 避坑与排查:五个翻车现场和它们的解法

这一章是我自己踩过的,按“现象 → 原因 → 解决”写,每条都能对上前面某一节的原理。新手照着排一遍,能省掉不少来回。

5.1 提示语层面的三个坑

坑一:给推理模型加角色设定,输出反而变差。

现象:同一道算法题,直接问能拿满分,加上“你是一位二十年经验的算法专家”之后,答案开始变成“建议从架构层面考虑”,具体代码反而没了。

原因:推理模型的内化推理路径被角色扮演的表演性带偏,它开始“演专家”而不是“解题”。

解决:推理线只写任务目标和约束,把角色设定全部删掉。要约束输出形式就直接写格式要求,别用身份暗示。

坑二:长文档整段塞进去做摘要,细节全丢。

现象:一份四十页的报告丢进去让它总结,返回的摘要通顺但没有任何数字,而报告里全是关键指标。

原因:单向长上下文里,模型对中段的注意力明显衰减,加上“总结”这个词本身会引导它做抽象概括,主动丢掉具体数值。

解决:分段处理再聚合——先按小节切块,每块抽“结论 + 数字 + 出处”,最后只对这些结构化结果做二次归纳。提示语里明确写“保留所有百分比和金额,不得改写数字”。

坑三:用通用模型直接问复杂推理,拿到看着对的错误答案。

现象:让它核算一个多步的分账逻辑,答案格式漂亮、步骤齐全,但第三步的基数用错了,整体结果偏差百分之十几。

原因:通用模型没有强逻辑链约束,它会“顺着最可能的写法”把步骤补完,中途不会停下来校验前提。

解决:要么换推理线,要么把问题拆成多轮,每轮只问一步并要求它给出计算依据,再人工或用代码核对每一步的中间值。关键业务上,我一般要求模型输出中间变量,然后自己在代码里复算一遍。

5.2 调用与工程层面的两个坑

坑四:把 temperature 当成“聪明度”旋钮。

现象:为了让回答“更有深度”,把 temperature 从 0.2 调到 0.9,结果 JSON 解析失败率从 1% 涨到 20%,字段名还开始自创。

原因:temperature 调的是采样随机性,不是能力。抽取、分类、结构化输出这类任务,随机性就是敌人。

解决:按任务定档——抽取与判定用 0 到 0.2,文案创作用 0.7 到 0.9,代码生成用 0.2 到 0.4。别在不同任务之间复用同一套默认参数。

坑五:本地跑得好,上线就超时。

现象:测试时单条请求一秒多返回,接入生产后偶发几十秒超时,用户投诉。

原因:推理线模型在复杂问题上会展开很长的中间步骤,延迟方差极大;再加上没设超时和重试,一次慢请求就拖住了整个队列。

解决:推理线单独设更长的超时并配降级策略(超时就退回通用线给一个快速回答),入口按问题复杂度做路由。同时记录每次调用的 token 消耗和耗时,按周看分布,异常长的请求单独捞出来分析是哪类提示语触发的。

注意:排查这类问题时先看是不是提示语里混进了整段文档,上下文长度暴涨会同时拉高延迟和费用,这是最常见也最容易忽略的原因。

6. 把提示语当代码管:版本、评测集与回归

前五章讲的是怎么写对一条提示语,这一章讲怎么让一百条提示语不互相打架、改一条不弄坏另一条。我吃过最大的亏是:产品上线三个月,运营在后台改了七版提示语,没人记录改了什么,某天分类准确率突然掉到及格线以下,翻遍聊天记录也找不回上一版。

从那以后我的做法是给提示语上版本控制:每条提示语一个文件,文件名带场景标识,文件头写清适用模型、参数、责任人,正文就是提示语本身,变量用占位符。改动走提交记录,回滚就是一次 checkout。这件事不复杂,但它把“玄学调参”变成了可追溯的工程活动。

第二步是建一个小评测集。不用多,每个场景三十到五十条真实样本,覆盖典型输入和已知的边界情况,人工标好标准答案。每次改提示语或换模型,跑一遍这个集子,看准确率和解析失败率两个数。我一般用下面这种最笨的方式跑:

import json def evaluate(cases_path: str, predict) -> dict: cases = [json.loads(line) for line in open(cases_path, encoding="utf-8")] hit = 0 bad_format = 0 misses = [] for c in cases: try: pred = predict(c["input"]) except Exception: bad_format += 1 continue if pred == c["label"]: hit += 1 else: misses.append({"input": c["input"], "gold": c["label"], "pred": pred}) n = len(cases) return { "accuracy": round(hit / n, 4), "format_error_rate": round(bad_format / n, 4), "top_misses": misses[:10], # 只留前十条,方便人工看错在哪 }

这段代码没什么技术含量,价值全在“每次改动都跑一遍”这个纪律上。返回里的 format_error_rate 比 accuracy 更值得盯:准确率掉两三个点可能是样本波动,格式错误率涨上去说明模型行为发生了结构性变化,通常是接口或模型版本变了。

检查项触发时机判断标准处理动作
准确率下降超过 5 个百分点每次提示语改动后对比上一版基线回滚到上一版再逐步改
格式错误率超过 3%每次模型切换后对比上一版基线检查输出约束是否失效
平均 token 消耗上涨超过 30%每周对比上周均值排查上下文是否塞多了
单次延迟 P95 翻倍持续监控对比历史分位检查是否误路由到推理线

第三步是记录模型切换的影响。同一个提示语在通用线和推理线上的表现可能完全不同,切模型必须重跑评测集,不能靠“新模型应该更好”的直觉。我现在的习惯是:任何提示语改动,先在评测集上跑,再看十条典型样本的人工抽检,两者都过才允许合并。这套流程写下来不到一页纸,但它把反复翻车的概率压到了很低。

希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询