DeepSeek实用指南:从API调用到提示词工程与参数调优 简介清华大学新闻与传播学院新媒体研究中心发布的104页《DeepSeek从入门到精通》PDF是一份面向AI学习者、科研人员及内容创作者的实用指南旨在帮助读者从零理解DeepSeek大模型并掌握高效使用方法。内容从DeepSeek公司背景与开源推理模型DeepSeek-R1讲起系统介绍其在智能对话、文本生成、语义理解、代码生成、联网搜索等场景中的能力边界并着重区分推理模型与通用模型、快速反应与链式思考等核心概念。文中配有大量对比表格、任务场景示例与提示语设计案例清晰展示数学证明、创意写作、代码调试等不同任务的模型选型与提示策略可有效规避角色扮演干扰、步骤过度拆分、缺少逻辑引导等常见误区。资源为1个PDF文件大小5.36MB便携易读。已有14275人学习下载。全书共104页图文并茂既可通读搭建知识体系也可作为日常使用时的随手参考手册。1. 一份 104 页的《DeepSeek从入门到精通》真正的价值在哪《DeepSeek从入门到精通》这份 104 页 PDF最近在不少技术群里被反复转发。有人把它当资料收藏有人读完一遍后还是只会发一句“你好”。我的判断是这份文档真正的价值不在于那 104 页能带来多少新知识而在于它把一条从“会聊天”到“会用模型”的升级路线摆在了桌面上。下面我不复述文档原文只按这条路线走一遍先选使用方式再做提示词设计再配参数、管上下文最后接进一个真实小工具。新手能照做熟手能直接看到边界和坑。2. 先把地基打牢DeepSeek 能做什么以及两种主流使用方式2.1 从对话到代码生成先认清能力边界DeepSeek 这一类大模型最擅长的是生成类任务对话、代码补全、文本改写、摘要、分类、抽取、头脑风暴。它能在你给出清晰指令后把一段半结构化需求翻译成可读的代码或方案这是不少团队愿意把它接进内部工具的原因。但它不是搜索引擎也不是数据库。对于“某库的最新版本是多少”“今天下午的股价是多少”这类时效性问题它可能给出一个看起来合理、实际已经过时的答案。它也不是执行器你说“帮我删除服务器上某个临时文件”它只能给你清空指令不会直接操作你的系统。认清这条边界比学会更多提示词技巧更重要能帮你避免把“看起来很聪明”误当成“真的可靠”。我一般会把任务分成两类。一类是生成与转换写脚本、改文案、清洗文本、做会议纪要这类可以大胆交给模型。另一类是事实校验与最终决策版本号、金额、合规判断这类必须有人工审查或外部数据兜底。入门阶段只要先分清这两类后面就不会太离谱。2.2 选 API 还是选本地部署一张对比表帮你定方向拿到模型能力之后第一个要定的事情是用哪种方式接入。常见做法有两种一种是使用别人提供的 API 服务把数据发到远端拿结果回来另一种是在自己的机器或内网里跑模型权重。选型不能只看“哪个火”要看数据敏感度、硬件预算和并发要求。对比维度API 方式本地部署方式数据是否离开本机通常会上传到服务端数据基本不出内网硬件要求几乎为零只要能调接口需要显卡和显存至少要足够的 RAM并发与响应调用方负责限流整体延迟较低并发能力受本地算力限制落地成本按调用量付费启动速度快一次性硬件投入长期边际成本低可控性依赖服务方更新与状态模型版本、参数、数据流向都可控适用场景原型、轻量工具、低频任务数据敏感、高频内部服务、离线场景我给你的建议是如果只想在三天内做出一个自己能用的工具或者团队还没有统一算力先走 API。它把交付周期从“装环境两周”压缩成“一下午”。如果数据涉及内部代码、客户资料或者你会长时间高频调用本地部署更稳妥。不要把这两条路对立起来很多团队的做法是敏感任务走本地粗糙草稿走 API两套入口共用同一套下游逻辑。2.3 最小可用的 API 调用Python 示例与参数说明先跑通一个最小示例比研究任何高级特性都重要。下面这段代码不依赖重型的第三方包只用了 Python 原生的requests方便你复制到任何环境里验证接入链路。import os import requests # 这些值不要硬编码统一从环境变量或配置中心读取 api_base os.environ.get(LLM_API_BASE, https://example.com/v1) api_key os.environ.get(LLM_API_KEY, replace-me) model os.environ.get(LLM_MODEL, deepseek-chat) payload { model: model, messages: [ {role: system, content: 你是一名熟悉代码审查的工程师。}, {role: user, content: 请用三句话指出这段代码里的性能问题。}, ], temperature: 0.7, # 越大越随机越小越保守 max_tokens: 1024, # 限制生成内容的长度 } resp requests.post( f{api_base}/chat/completions, headers{Authorization: fBearer {api_key}}, jsonpayload, timeout60, ) resp.raise_for_status() # 非 2xx 直接抛出异常方便排查 data resp.json() print(data[choices][0][message][content])这段代码做的事情很简单把一个角色设定和一条用户问题组装成messages列表发给大模型接口再取出第一份回复打印出来。api_base、api_key、model三个值都来自你实际拿到的接入信息通常不需要你也别写在代码里。temperature控制随机程度做代码生成、信息抽取时我习惯调到 0.2 左右做创意文案时再调到 0.8 以上。max_tokens不是越大越好它只约束模型输出长度不扩大你输入内容的上限。第一次跑的时候常见错误是401鉴权失败别急着排查模型先确认 key 是否正确、有没有多余空格再就是接口路径拼错chat/completions这种路径少一个斜杠都会报 404。把resp.text打出来绝大多数问题一眼就能定位。3. 提示词设计才是分水岭从会问到会“榨”出结果3.1 提示词四要素角色、任务、上下文、输出格式同样一个模型有人只能拿到泛泛而谈有人能拿到可直接落地的代码差别往往在提示词。我不太爱讲花哨的“咒语”更愿意把提示词拆成四个固定要素角色、任务、上下文、输出格式。角色告诉模型“站在什么立场说话”。你让它“你是后端工程师正在做 code review”它给出的意见会更贴近工程实际。任务必须是一个可执行的动作“分析这段代码”太模糊“列出这段代码里可能引发并发问题的三个位置”才是任务。上下文负责补充限制条件比如语言风格、禁止操作的依赖、已有环境约束。输出格式则直接决定你能不能把结果接进程序常见的是 JSON、Markdown 表格或纯列表。我一般会在写任何提示词前先按这四个要素在草稿里各写一句然后再拼成一段话。这样做的好处是当模型输出不对时你能快速判断是任务没写清还是格式没约束住而不是靠“再试一次”碰运气。3.2 用“思维链引导”压榨长文本推理能力对于逻辑判断、代码排错、方案评估这类任务直接让模型给结论它容易跳步。更可靠的做法是给它一个推理脚手架让它先分步骤思考再汇总结论。这样得到的结果可复查性更强出问题时也能看到它到底在哪一步跑偏了。prompt 背景我们需要从用户反馈里判断一条产品建议是否值得做。 请按以下步骤推理 1. 列出这条建议的核心诉求 2. 判断该诉求是否已被现有功能覆盖 3. 如果未覆盖评估目标用户规模和实现成本 4. 最终输出值得做 / 不值得做 / 需要更多信息。 用户反馈内容 “希望导出报表时能同时生成图表不然每次都要手动再做一遍。” 这份提示词的关键在于我把“怎么思考”拆成了显式步骤而不是简单说“请好好分析”。模型会沿着第 1、2、3 步生成中间内容最后再给结论。对于需要人工复核的场景这种设计能省下大量时间因为你不用重新推演它的全部分析过程。需要提醒的是“思维链引导”不等于每一步都要很冗长。步骤过多会让输出变长、变慢也会消耗更多 token。我的经验是普通判断给三步到四步就够只有复杂任务才需要更多中间环节。如果发现模型在某个步骤上反复绕圈先检查那一步的描述是否包含了一个可判定的条件。3.3 一个可抄作业的提示词模板从模糊需求到结构化输出如果你要把 DeepSeek 的结果接进程序那结构化输出就是刚需。最省心的方式是在提示词里明确指定 JSON 结构并告知“只输出 JSON不要额外解释”。system_prompt 你是信息抽取助手。只输出 JSON不要输出任何额外解释。 user_prompt 从下面的合同文本中抽取 甲方名称、乙方名称、合同金额、签约日期。 输出格式 {甲方: , 乙方: , 合同金额: , 签约日期: } 合同文本 “甲方某科技有限公司与乙方某软件工作室于 2025 年 3 月签订协议 合同金额为人民币 20 万元整。” 即使提示词约束得再严格模型偶尔还是会在 JSON 前后加一段解释或者把内容包进 Markdown 代码块。为了不让下游解析直接翻车我会在解析时加一层容错import json def parse_json_loose(text: str) - dict: try: return json.loads(text) except json.JSONDecodeError: start, end text.find({), text.rfind(}) if end start: return json.loads(text[start : end 1]) raise ValueError(无法从响应中提取 JSON)这段容错逻辑先尝试直接解析失败后就截取第一个左花括号到最后一个右花括号之间的内容再解析。它能救回一部分因为多余解释导致的失败但解决不了字段缺失的问题。所以更重要的还是在上游把输出格式写死并在提示词里加一句“字段缺失时填空字符串不要自己编造”。我遇到过不少次模型把金额写成“贰拾万元整”看上去合理但程序很难直接用遇到这种情况你需要在提示词里规定金额格式必须为阿拉伯数字。4. 调参和上下文管理让“从入门到精通”真正拉开差距4.1 temperature、top_p 与 max_tokens 的配合逻辑很多人拿到接口后只改一个temperature其他参数都不动这其实浪费了模型的表达能力。先看一张常用参数建议表任务类型temperature 区间max_tokens 建议备注数据抽取 / 分类 / 代码生成0.1 到 0.3按输出长度估够用即可追求高确定性文档总结 / 改写0.3 到 0.6一般是输入长度的 20% 左右保留一定变化创意文案 / 头脑风暴0.7 到 1.0根据需要的篇幅定允许发散temperature控制的是采样随机程度越低越贴近概率最高的那条路径越高越容易出现意外表达。top_p控制的是候选词集合大小思路是只从累计概率达到某个阈值的词里采样。这两个参数本质都在调节“随机性”所以我不建议同时大幅调整否则很难判断是哪一项导致了输出漂移。我的习惯是固定top_p1.0只调temperature或者反过来固定temperature0.7只调top_p。max_tokens也要注意它只约束生成部分的长度不约束输入提示词的长度。很多新手发现回复被截断第一反应是“上下文窗口太小”但看返回里的finish_reason才发现是因为max_tokens设成了 512。另外不同服务对长文本的计费方式不同有人把提示词也算进输出配额导致设置很大的max_tokens直接报超限。所以遇到截断先看错误信息再动参数。4.2 长文本放不下的三种应对分块、摘要、外挂检索当你要处理的文本超过模型的上下文承受能力时不能硬塞。常见做法有三种分块、摘要、外挂检索。先看一个最基础的分块函数。它按固定长度切文本并保留一定重叠区域避免语义在切缝处断裂。def chunk_text(text: str, chunk_size: int 1500, overlap: int 200): chunks [] start 0 while start len(text): end min(start chunk_size, len(text)) chunks.append(text[start:end]) if end len(text): break start end - overlap return chunkschunk_size决定每段文本长度我一般会根据模型的实际输入上限留出约 20% 余量因为后面还要拼提示词和输出空间。overlap让相邻切片有部分重叠能减少“一句话被从中间切开导致信息缺失”的问题。但 overlap 也不能太大否则等于重复消费 token成本会翻倍。摘要法适合“整篇文本的结论比细节更重要”的场景做法是先让模型分块总结再把总结继续总结最后把压缩后的摘要作为上下文。外挂检索则更进一步先用关键词或向量召回最相关的片段只把相关片段拼进提示词。向量召回听起来高大上本质就是找出“最像这段问题”的候选文本。我的建议是先试试分块加关键词过滤多数需求用不到向量库等文本量大到关键词过滤扛不住时再上向量方案。4.3 用一套评估问题做回归测试别让调参变成玄学调参最怕凭感觉。今天调低 temperature试了一个问题觉得“好多了”明天换个任务又被直接打脸。我现在的做法是维护一小组固定测试用例每次只改一个变量跑一遍对比通过率。cases [ { name: 抽取合同日期, prompt: 从“合同签订日期为 2025 年 3 月 8 日”中抽取日期。, contains: [2025-03-08], }, { name: 生成函数声明, prompt: 写一个 Python 函数输入列表返回去重后的列表。, contains: [def], }, ] def evaluate(model_caller, cases, temperature0.2): passed 0 for case in cases: output model_caller(case[prompt], temperaturetemperature) ok all(keyword in output for keyword in case[contains]) passed int(ok) print(case[name], 通过 if ok else 失败) print(f通过率 {passed}/{len(cases)})这段脚本的判断标准很简单输出里是否包含关键子串。对于分类和抽取任务我还会额外加一个“能被解析为 JSON”的校验。关键在于它逼迫你先把验收标准写明白而不是笼统地感觉“输出还挺顺眼”。每次改参数后跑一遍通过率上升就保留下降就回滚调参就不再是玄学。5. 避坑指南从 API 报错到答非所问的 5 个真实翻车现场5.1 同一个提示词换个时间跑结果完全不一样某开发者跟我说过他上午让模型生成一段正则结果是对的下午用同样的提示词再跑结果完全没法用。他第一反应是工具坏了其实是采样随机性在作怪。原因有两层temperature大于 0 时模型每次从候选词里抽样结果天然有波动另外服务端如果调整了模型版本或负载策略同样的输入也会得到不同输出。解决方法是对关键任务把temperature调到 0 或接近 0如果接口支持固定随机种子就固定种子还不放心就跑三次取多数结果或对输出做差异对比。不要用一个样本的“好”来断言某套参数一定好。5.2 长文本被截断代码只生成了一半生成一个完整脚本结果代码在函数中间戛然而止这是非常典型的截断问题。第一件事不是重写提示词而是检查返回里的finish_reason。如果它的值是length说明已经达到了长度上限。finish_reason data[choices][0].get(finish_reason) if finish_reason length: print(达到 max_tokens 上限请增大 max_tokens 或采用分段生成)如果是这个原因解决办法很简单调大max_tokens。但如果你的提示词本身已经很长接近上下文上限那即使max_tokens设得很大也可能在请求阶段就报错。这时候要反过来做减法删掉冗余示例压缩历史对话或者把要生成的代码拆成多个函数分段生成。别让模型一口气写一个 2000 行的模块先写骨架再逐段补全。5.3 本地推理特别慢以为模型坏了有人把模型部署到本地后发现生成一段话要等几十秒立刻怀疑是硬件坏了。其实在多数情况下不是故障而是模型尺寸与硬件不匹配。原因主要是模型参数量太大超过了本机显存或内存带宽的承受范围甚至已经开始使用 CPU 计算。解决思路是换更小参数的模型版本或者使用量化后的权重同尺寸模型的显存占用可以降到接近一半推理时不要同时开太多请求每次只跑一个任务第一次使用前先跑一小段提示词预热避免冷启动带来的高延迟。如果你只是写个轻量脚本本地推理未必比 API 更快别为了“本地”而本地。5.4 提示词越长效果反而越差另一类常见踩坑是“越详细越好”的执念。有人把一整本文档塞进提示词让模型总结重点结果总结得丢三落四还夹带了不少无关内容。原因在于超长上下文中模型对中间位置信息的注意力会衰减无关示例还会把它的输出风格带偏。解决办法是把提示词做瘦身最关键的指令放在开头最需要遵守的约束放在结尾中间只保留必要上下文示例控制在两三个以内并且要和你的目标输出高度相关。比如你只想要 JSON 输出就放一个“正确 JSON 示例”不要同时再放一段 Markdown 和普通文本示例。发现有无关信息直接删掉再试别怕提示词太短。5.5 把模型的“搜索式回答”当成事实让模型回答“某个开源组件最新版本是多少”它给了一个看起来合理但已经过时的版本号。这不是模型故意骗你而是它擅长生成“像答案”的文本但知识存在截止时间。解决方法是把事实性任务和生成性任务分开。对于时效性强的信息要么明确告诉模型“只用我提供的资料回答”要么把外部检索结果注入上下文并要求它在回答中标注“根据资料”。尤其是版本号、价格、法律条款、具体日期这类内容最后一步必须人工或程序校验。别让模型替你做“最终确认”它更适合做“初稿和参考”。6. 把 DeepSeek 接进一个小工具验证你的“精通”程度6.1 用 FastAPI 包一层最小服务替换默认请求入口跑通单次调用之后下一步是把调用包成一个内部服务让团队成员和脚本都通过这一个入口走。这样密钥、日志、限流都能统一管理不用在每个脚本里重复塞 API 信息。import os import requests from fastapi import FastAPI from pydantic import BaseModel app FastAPI() API_BASE os.environ[LLM_API_BASE] API_KEY os.environ[LLM_API_KEY] class AskRequest(BaseModel): prompt: str temperature: float 0.3 app.post(/ask) def ask(req: AskRequest): payload { model: deepseek-chat, messages: [{role: user, content: req.prompt}], temperature: req.temperature, max_tokens: 1024, } resp requests.post( f{API_BASE}/chat/completions, headers{Authorization: fBearer {API_KEY}}, jsonpayload, timeout60, ) resp.raise_for_status() return resp.json()[choices][0][message][content]这个接口把模型调用封装成了/ask入参只有prompt和可选的temperature。这样做的好处是下游脚本不再关心模型名和鉴权方式你甚至可以随时把底层模型换成同接口的另一个版本而不需要通知所有调用方。密钥从环境变量读取避免泄露在代码仓库里。6.2 加一条自动重试 返回缓存的进阶链路接口封装好后下一步是解决两个实际问题接口偶发超时、重复请求浪费资源。我一般会加一个带退避的重试函数再给确定性请求加一层本地缓存。import time import functools def retry_on_exception(func, max_retries3, base_wait2): for i in range(max_retries): try: return func() except Exception: if i max_retries - 1: raise time.sleep(base_wait * (i 1)) def call_service(prompt: str, temperature: float) - str: # 这里放上面封装好的请求代码返回最终文本 ... functools.lru_cache(maxsize256) def ask_cached(prompt: str, temperature: float) - str: if temperature 0.0: return retry_on_exception(lambda: call_service(prompt, temperature)) return call_service(prompt, temperature)retry_on_exception会在请求失败时等 2 秒、4 秒、6 秒再重试最多试三遍。注意重试只适合幂等请求也就是“无论执行多少次结果都一样”的任务如果你的任务是让模型生成一段随机创意重试会造成额外成本。缓存只对temperature0.0的请求生效因为结果可复现缓存命中后直接返回历史结果不再消耗调用预算。对于高并发场景临时性错开请求往往比重试更快。6.3 通过一次半小时的回归脚本形成自己的使用基线有了接口、缓存和回归用例你其实已经具备了一套“越用越稳”的工作方式。我现在的习惯是每次调整模型或参数后先跑一遍第 4 章里的评估脚本半小时后看通过率再决定是否替换上线。下面是一个简单的基线模板任务类型推荐 temperaturemax_tokens重试策略信息抽取0.15121 次重试代码补全0.210241 次重试文案改写0.62048不重试头脑风暴0.92048不重试以前我总凭感觉调参吃过不少亏。有一次要批量生成商品描述我把temperature调到了 0.9结果一半输出里出现了夸大其词的形容审核成本比省下的 token 还贵。后来我养成了固定基线的习惯每类任务都有一组标准参数和验收关键词改任何一个变量都不再靠运气。希望帮到你。本文还有配套的精品资源点击获取