ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

DeepSeek API 实战:从密钥到多轮对话的 Python 调用指南

DeepSeek API 实战:从密钥到多轮对话的 Python 调用指南 简介这份资源面向具备一定编程基础、希望掌握AI模型API集成技术的开发者系统讲解调用DeepSeek API的完整流程。内容从API工作机制入手用通俗比喻帮助理解请求与响应的本质再逐步展开注册账号、获取API Key、查阅文档、配置请求参数等准备工作并以Python为例演示发送HTTP请求、解析服务器返回结果及处理常见错误的实操方法。文中还涉及批量处理、上下文管理、流式传输等提效技巧以及密钥保护、数据隐私与信息安全方面的最佳实践并给出实际项目的搭建思路。资源包为1个docx文档约217KB结构紧凑、便于通读。目前已有161人学习适合想独立完成AI服务调用、将理论转化为可运行代码的读者参考。1. 从外卖比喻到真实请求DeepSeek API 到底能解决什么很多人第一次接触 DeepSeek API是被“外卖小哥”这个比喻带进来的——你下单后台做披萨API 负责把结果送到你手里。比喻本身没问题但真正落到代码里新手最容易卡住的地方恰恰是不知道“下单”这个动作在 HTTP 层面到底长什么样。你打开官网、注册账号、拿到一串sk-开头的密钥然后呢请求发到哪个地址、Header 里放什么、Body 里messages数组的role有哪几种取值、返回的 JSON 里内容藏在第几层——这些才是决定你能不能跑通第一个请求的关键。这篇笔记面向的是有基础 Python 能力、想把 DeepSeek 的对话能力接进自己脚本或小工具里的开发者。我会按“拿到密钥 → 发出第一个请求 → 处理返回 → 避坑 → 进阶”的顺序把每一步的参数含义和失败排查讲清楚。你跟着走完至少能得到一个能稳定跑通的调用模板而不是停留在“知道有 API 这回事”。2. 准备工作与第一个可运行请求密钥、地址、Header 和 Body 怎么配2.1 注册、创建 API Key 与文档里真正要看的三个字段注册流程本身不复杂进官网、填邮箱或手机号、验证。真正要留意的是创建 API Key 这一步。在后台的 API 管理页面点“生成新密钥”你会得到一串类似sk-12ab34cd56ef78gh90ij12kl34mn56op的字符。这串东西只在生成时完整显示一次关掉页面就再也看不到全文了所以生成后立刻复制到安全的地方这是血泪经验。拿到密钥后别急着写代码先花五分钟把官方文档里这三个字段确认清楚字段作用常见取值/位置请求地址请求发往哪个 URLhttps://api.deepseek.com/v1/chat/completions认证方式证明你有权限Header 里的Authorization: Bearer 你的密钥模型名用哪个模型deepseek-chat等以文档当前说明为准文档里还会列出一堆参数但第一次调用你只需要关心四个model、messages、temperature、max_tokens。其余的top_p、frequency_penalty之类等跑通之后再回来调。提示请求地址和模型名会随平台更新变化写代码前以官方文档当前页面为准不要照抄网上半年前的教程。2.2 用 requests 发出第一个请求五步拆解Python 里最直接的调用方式就是用requests库。先装依赖pip install requests然后按下面五步走。我把每一步单独拆开方便你对照排查。第一步设置请求头。Header 负责告诉服务器“我是谁”和“我发的是什么格式”import requests headers { Authorization: Bearer YOUR_API_KEY, # 把 YOUR_API_KEY 换成真实密钥 Content-Type: application/json # 声明请求体是 JSON 格式 }Authorization的值必须是Bearer加一个空格再加密钥这个空格漏掉就是 401 错误的头号原因。Content-Type固定写application/json因为下面json参数会自动序列化并带上这个头但显式写出来更保险。第二步准备请求体。请求体是真正的“订单内容”data { model: deepseek-chat, # 模型名以文档为准 messages: [ # 对话消息列表 {role: user, content: 你好请用鲁迅的风格写一段关于秋天的散文} ], temperature: 0.7, # 0 偏保守1 偏发散 max_tokens: 500 # 限制回复最大长度 }messages是一个数组每个元素有role和content两个键。role常见取值是user你发的、assistant模型回的、system设定人设或规则。第一次调用只放一条user消息就够了。temperature控制随机性写代码、做抽取任务时调到 0.2 以下更稳写文案、头脑风暴可以放到 0.8 以上。max_tokens是回复长度的硬上限设太小会导致回答被截断。第三步发送 POST 请求。用requests.post把地址、头、体拼起来response requests.post( https://api.deepseek.com/v1/chat/completions, headersheaders, jsondata )注意这里用的是jsondata而不是datadata。json会自动把字典序列化成 JSON 字符串并设置正确的 Content-Type用data传字典则不会序列化服务器收到的是 Python 的字典字符串表示直接报 400。第四步判断状态码并取内容。服务器返回的 JSON 里模型输出藏在choices[0].message.contentif response.status_code 200: result response.json() print(result[choices][0][message][content]) else: print(f请求失败状态码{response.status_code}) print(response.text) # 打印完整错误信息方便定位response.json()把返回的 JSON 字符串转成 Python 字典。choices是一个数组通常只有一个元素取[0]即可。如果状态码不是 200response.text里往往有具体的错误描述比如Invalid API key或Model not found先看这个再改代码。第五步把密钥从代码里挪出去。上面代码里直接写密钥只是演示实际项目里必须用环境变量import os api_key os.environ.get(DEEPSEEK_API_KEY) headers { Authorization: fBearer {api_key}, Content-Type: application/json }在终端里用export DEEPSEEK_API_KEYsk-...设置Windows 用set代码里只读不写。这样即使代码被分享出去密钥也不会跟着泄露。2.3 返回结构长什么样一次请求的完整数据流跑通之后你拿到的response.json()大致是这样一个结构{ id: chatcmpl-xxxx, object: chat.completion, choices: [ { index: 0, message: { role: assistant, content: 秋天总是来得悄无声息…… }, finish_reason: stop } ], usage: { prompt_tokens: 28, completion_tokens: 156, total_tokens: 184 } }finish_reason值得关注值是stop表示正常结束是length表示被max_tokens截断了这时候你就该把max_tokens调大。usage里的 token 数直接关系到计费养成每次调用后看一眼的习惯能帮你估算成本。3. 多轮对话与流式输出让请求更像真实聊天3.1 用 messages 数组维护上下文单次问答很简单但真实场景往往需要多轮。DeepSeek 的 API 本身不保存会话状态上下文完全靠你在每次请求时把历史消息一起传进去。做法是维护一个列表每轮把用户消息和模型回复都追加进去conversation [ {role: system, content: 你是一个简洁的技术助手回答不超过三句话。}, {role: user, content: 什么是 API} ] # 第一次请求 response requests.post(url, headersheaders, json{ model: deepseek-chat, messages: conversation, temperature: 0.5 }) reply response.json()[choices][0][message][content] conversation.append({role: assistant, content: reply}) # 第二次请求带上完整历史 conversation.append({role: user, content: 能举个例子吗}) response requests.post(url, headersheaders, json{ model: deepseek-chat, messages: conversation, temperature: 0.5 }) print(response.json()[choices][0][message][content])这里的关键点是conversation列表在两次请求之间没有被清空第二次请求把第一轮的user和assistant消息都带上了模型才能“记得”之前聊了什么。system消息放在最前面用来设定行为边界比如限制回答长度、指定语气。注意上下文越长消耗的 token 越多费用也越高。长对话要定期裁剪比如只保留最近 10 轮或者把早期内容做摘要后再传入。3.2 流式输出让回复一个字一个字蹦出来默认情况下API 会等模型生成完整回复后一次性返回长回答可能要等好几秒。开启stream后服务器会分块推送你可以边收边打印data { model: deepseek-chat, messages: [{role: user, content: 写一段 200 字的科幻开头}], stream: True } response requests.post(url, headersheaders, jsondata, streamTrue) for line in response.iter_lines(): if line: decoded line.decode(utf-8) if decoded.startswith(data: ): payload decoded[6:] # 去掉 data: 前缀 if payload.strip() [DONE]: break import json chunk json.loads(payload) delta chunk[choices][0].get(delta, {}) if content in delta: print(delta[content], end, flushTrue)几个参数要留意streamTrue在requests.post里也要同步设置否则iter_lines不会逐行返回。返回的每一行以data:开头最后一行是data: [DONE]。delta里可能没有content键比如第一个 chunk 只带role所以用.get(content)做判断。流式模式下usage字段通常不会出现在每个 chunk 里需要额外处理。3.3 超时、重试与并发的基本处理网络请求不可能永远成功。生产环境里至少要加超时和重试from requests.adapters import HTTPAdapter from urllib3.util.retry import Retry session requests.Session() retry Retry(total3, backoff_factor1, status_forcelist[429, 500, 502, 503]) session.mount(https://, HTTPAdapter(max_retriesretry)) response session.post(url, headersheaders, jsondata, timeout30)timeout30表示 30 秒没响应就抛异常避免程序卡死。Retry配置了遇到 429限流和 5xx服务器错误时自动重试 3 次backoff_factor1让每次重试间隔递增。这套组合能挡掉大部分偶发网络抖动但 401 和 400 这类客户端错误不会重试因为重试也没用得改代码。4. 避坑与排查401、400、截断和超时的真实原因4.1 401 认证失败密钥和 Bearer 前缀现象返回{error: Invalid API key}或状态码 401。原因最常见的是三个——密钥复制不完整首尾漏字符、Bearer和密钥之间少了空格、密钥已被删除或过期。解决把 Header 里的Authorization值打印出来逐字符核对。正确格式是Bearer sk-xxxxBearer后面有且只有一个空格。如果确认格式没问题去后台重新生成一个密钥替换。4.2 400 请求格式错误json 和 data 的区别现象返回 400错误信息里提到invalid request body或expected JSON。原因用了datadata而不是jsondata导致字典没有被序列化成 JSON或者messages里缺少role/content键或者model名写错了。解决统一用json参数。检查messages数组里每个元素是否都有role和content。model的值从文档里复制不要手打。4.3 回复被截断max_tokens 和 finish_reason现象回答到一半突然停了句子不完整。原因max_tokens设得太小模型还没说完就触发了长度上限。返回的finish_reason会是length而不是stop。解决先看finish_reason如果是length把max_tokens调大。但要注意模型本身有上下文窗口上限输入加输出的总 token 数不能超过这个值超了会直接报错。4.4 响应慢或超时流式与超时参数现象请求发出后十几秒没反应最后抛ReadTimeout。原因长回答在非流式模式下需要等全部生成完才返回网络链路不稳定服务器端负载高。解决对长文本场景开启streamTrue边生成边接收体感快很多。同时设置合理的timeout比如(10, 60)表示连接超时 10 秒、读取超时 60 秒。如果频繁超时检查本地网络或者把请求放到异步任务里跑。4.5 密钥泄露与用量失控现象收到账单发现用量远超预期或者密钥出现在公开仓库里。原因密钥硬编码在代码里被提交到了 Git或者没有设置用量上限。解决密钥只从环境变量读取.env文件加入.gitignore。在后台设置每日或每月消费限额开启用量告警。定期轮换密钥旧密钥保留一周过渡后删除。5. 进阶用 Flask 搭一个带上下文管理的写作助手把前面所有东西串起来做一个最小可用的 Web 应用用户输入主题后端调用 DeepSeek 生成文章并且支持连续追问修改。技术栈是 Python Flask。先装依赖pip install flask requests核心代码import os import json import requests from flask import Flask, request, jsonify, render_template app Flask(__name__) API_URL https://api.deepseek.com/v1/chat/completions HEADERS { Authorization: fBearer {os.environ.get(DEEPSEEK_API_KEY)}, Content-Type: application/json } # 用字典按 session_id 保存每个用户的对话历史 sessions {} def call_deepseek(messages, temperature0.5, max_tokens1500): 封装一次 API 调用返回文本内容或错误信息 payload { model: deepseek-chat, messages: messages, temperature: temperature, max_tokens: max_tokens } try: resp requests.post(API_URL, headersHEADERS, jsonpayload, timeout(10, 60)) if resp.status_code 200: return resp.json()[choices][0][message][content], None return None, fAPI 错误 {resp.status_code}: {resp.text} except requests.exceptions.Timeout: return None, 请求超时请稍后重试 app.route(/) def index(): return render_template(index.html) app.route(/generate, methods[POST]) def generate(): data request.get_json() topic data.get(topic, ).strip() session_id data.get(session_id, default) if not topic: return jsonify({error: 主题不能为空}), 400 # 取出或初始化该会话的历史 history sessions.setdefault(session_id, [ {role: system, content: 你是一个专业写作助手输出结构清晰的中文文章。} ]) history.append({role: user, content: f请围绕「{topic}」写一篇 800 字左右的文章分三个小节。}) content, error call_deepseek(history) if error: return jsonify({error: error}), 500 history.append({role: assistant, content: content}) # 只保留最近 20 条消息防止上下文无限增长 sessions[session_id] history[-20:] return jsonify({article: content}) if __name__ __main__: app.run(debugTrue, port5000)这段代码有几个设计点值得说。sessions字典用session_id做键每个用户或每个浏览器标签页可以有独立的历史互不干扰。call_deepseek把请求逻辑封装成一个函数超时设成(10, 60)连接 10 秒、读取 60 秒兼顾响应速度和长文本生成。历史记录用history[-20:]裁剪只保留最近 20 条消息避免 token 无限累积导致费用失控或超出上下文窗口。前端index.html只需要一个输入框和一个展示区域用fetch调/generate即可。如果你想支持“继续修改”再加一个输入框把用户的新要求追加到history里再调一次call_deepseek模型就能基于上一版文章做修改。验证方法很简单启动 Flask 后在浏览器里输入一个主题看是否返回文章然后追问“把第二段改得更口语化”看返回的内容是否基于上一版修改。如果第二次请求报错检查history是否被正确追加和裁剪。从那以后我每次接一个新的 API都会先把密钥塞进环境变量、写一个最小请求脚本跑通、再打印一次完整返回结构确认字段位置最后才动业务代码。这套习惯帮我省掉了大量“明明代码一样却跑不通”的排查时间。希望帮到你。本文还有配套的精品资源点击获取
返回列表