第2章:环境搭建与 DeepSeek API 入门

📌 本章目标

  • 配置好 Python 开发环境
  • 获取 DeepSeek API Key
  • 写出第一个 DeepSeek API 调用
  • 封装一个通用的 LLM 调用函数(后续章节会一直用)
  • 理解 Token 和计费方式
  • 若不想使用终端进行文件操作,可直接使用pycharm进行操作。私信我免费获取学习文件

2.1 Python 环境配置

检查 Python 版本

打开终端(Windows 下用 PowerShell 或 CMD,Mac/Linux 用 Terminal),输入:

python --version
# 或
python3 --version

确保版本号 >= 3.10。如果不是,去 python.org 下载最新版。

创建项目文件夹

# 创建课程项目目录
mkdir ai-agent-course
cd ai-agent-course

# (推荐)创建虚拟环境,避免依赖冲突
python -m venv venv

# 激活虚拟环境
# Windows:
venv\Scripts\activate
# Mac/Linux:
source venv/bin/activate

安装依赖

pip install openai python-dotenv

💡 为什么用 openai 库而不是 DeepSeek 专用库?
DeepSeek API 完全兼容 OpenAI 的接口格式,所以我们用最成熟的 openai Python 库,只需要把 base_url 改成 DeepSeek 的地址就行。这意味着你以后切换到其他兼容 OpenAI 接口的模型(通义千问、智谱GLM等),只需要改一行配置!


2.2 获取 DeepSeek API Key

步骤

  1. 打开 DeepSeek 开放平台
  2. 注册/登录账号
  3. 进入「API Keys」页面
  4. 点击「创建 API Key」,复制保存

⚠️ 重要:API Key 只会在创建时显示一次,请立即保存!丢失只能重新创建。

安全存储 API Key

❌ 绝对不要把 API Key 写在代码里:

# 千万别这样!万一上传到 GitHub,你的 Key 会被盗用
api_key = "sk-xxxxxxxxxxxxxxxxxxxxxxxx"

✅ 正确做法:用环境变量

在项目根目录创建 .env 文件:

# .env 文件内容
DEEPSEEK_API_KEY=sk-your-real-api-key-here

然后创建 .gitignore 文件,确保 .env 不会被提交到 Git:

# .gitignore 文件内容
.env
venv/
__pycache__/
*.pyc

2.3 第一个 DeepSeek API 调用

创建一个文件 01_hello_deepseek.py

"""
第一个 DeepSeek API 调用
"""
import os
from openai import OpenAI
from dotenv import load_dotenv

# 加载 .env 文件中的环境变量
load_dotenv()

# 创建 DeepSeek 客户端
client = OpenAI(
    api_key=os.getenv("DEEPSEEK_API_KEY"),
    base_url="https://api.deepseek.com/v1"  # 关键!指向 DeepSeek 服务器
)

# 发起一次最简单的对话
response = client.chat.completions.create(
    model="deepseek-chat",      # DeepSeek 的对话模型
    messages=[
        {"role": "system", "content": "你是一个友善的 Python 老师"},
        {"role": "user", "content": "用一句话告诉我什么是变量"}
    ],
    temperature=0.7,             # 控制随机性,0=确定,1=创意
    max_tokens=100               # 限制最大输出长度
)

# 打印回复
print(response.choices[0].message.content)

运行:

python 01_hello_deepseek.py

预期输出类似:

变量就像一个贴了标签的盒子,你可以把数字、文字等数据放进去,
需要的时候通过标签就能找到它。

🎉 恭喜!你已经成功调用了 DeepSeek 大模型!


2.4 深入理解 API 调用参数

response = client.chat.completions.create(
    model="deepseek-chat",           # ① 模型选择
    messages=[                        # ② 消息列表
        {"role": "system", "content": "系统提示词,定义AI的行为"},
        {"role": "user", "content": "用户的问题"},
        {"role": "assistant", "content": "AI之前的回答(多轮对话时用)"}
    ],
    temperature=0.7,                  # ③ 创意度 0-2
    max_tokens=500,                   # ④ 最大输出长度
    top_p=0.9,                        # ⑤ 核采样(一般不动)
    stream=False                      # ⑥ 是否流式输出
)

参数详解

参数说明建议值
modelDeepSeek 有两个:deepseek-chat(通用)和 deepseek-reasoner(深度推理)通用用 chat
messages消息数组,role 有三种:system(设定)、user(用户)、assistant(AI)
temperature0=每次都一样,1=更有创造性事实问答 0.3,创意写作 0.8
max_tokens限制输出长度,防止浪费钱根据需求设,日常 500-2000
streamTrue=逐字返回(像打字效果),False=一次性返回聊天用True,Agent用False

messages 中三种 role 的作用

# 一个完整的多轮对话示例
messages = [
    # system:设定 AI 的身份、语气、规则(不会被用户看到)
    {"role": "system", "content": "你是一个严谨的数学老师,回答要简洁精确"},

    # user:用户说的话
    {"role": "user", "content": "1+1等于几?"},

    # assistant:AI 之前的回答(多轮对话时把历史放进去)
    {"role": "assistant", "content": "1+1等于2。"},

    # user:用户又问
    {"role": "user", "content": "那2+2呢?"},
]

💡 为什么要把历史对话放进去? LLM 本身是无状态的,每次调用都是"全新"的。多轮对话之所以能"记住"上下文,是因为我们把历史消息一起发过去了。这就是最简单的「短期记忆」。


2.5 封装一个通用调用函数

后续章节会频繁调用 LLM,我们先封装好,避免重复代码。

创建 llm_utils.py(这是本章练习用,后续每章代码都是自包含的,不需要此文件):

"""
LLM 通用工具函数
本章练习用 —— 演示如何封装 API 调用
"""
import os
from openai import OpenAI
from dotenv import load_dotenv

load_dotenv()

# ============================================
# 全局客户端(整个项目共用这一个)
# ============================================
client = OpenAI(
    api_key=os.getenv("DEEPSEEK_API_KEY"),
    base_url="https://api.deepseek.com/v1"
)

# ============================================
# 基础调用:发消息,拿回复
# ============================================
def chat(
    messages: list[dict],
    model: str = "deepseek-chat",
    temperature: float = 0.7,
    max_tokens: int = 2000,
) -> str:
    """
    最简单的 LLM 调用:传入消息列表,返回文本回复

    参数:
        messages: 消息列表 [{"role":"user","content":"..."}]
        model: 模型名称
        temperature: 创意度 0-2
        max_tokens: 最大输出长度

    返回:
        模型回复的文本
    """
    response = client.chat.completions.create(
        model=model,
        messages=messages,
        temperature=temperature,
        max_tokens=max_tokens,
    )
    return response.choices[0].message.content


# ============================================
# 带工具调用:发消息,模型可能要求调用工具
# ============================================
def chat_with_tools(
    messages: list[dict],
    tools: list[dict],
    model: str = "deepseek-chat",
) -> dict:
    """
    带 tool calling 的 LLM 调用

    返回的字典包含:
    - has_tool_calls: bool, 模型是否想调用工具
    - content: str | None, 文本回复(如果不调用工具)
    - tool_calls: list, 工具调用列表(如果要调用工具)
    """
    response = client.chat.completions.create(
        model=model,
        messages=messages,
        tools=tools,
    )

    msg = response.choices[0].message

    if msg.tool_calls:
        return {
            "has_tool_calls": True,
            "content": None,
            "tool_calls": [
                {
                    "id": tc.id,
                    "name": tc.function.name,
                    "arguments": tc.function.arguments,  # JSON 字符串
                }
                for tc in msg.tool_calls
            ],
            "raw_message": msg,  # 需要放回 messages 中
        }
    else:
        return {
            "has_tool_calls": False,
            "content": msg.content,
            "tool_calls": [],
            "raw_message": msg,
        }


# ============================================
# 流式调用:逐字输出(做聊天界面时用)
# ============================================
def chat_stream(messages: list[dict], model: str = "deepseek-chat"):
    """
    流式调用 LLM,生成器函数,逐块返回文本

    用法:
        for chunk in chat_stream(messages):
            print(chunk, end="", flush=True)
    """
    response = client.chat.completions.create(
        model=model,
        messages=messages,
        stream=True,
    )

    for chunk in response:
        if chunk.choices[0].delta.content:
            yield chunk.choices[0].delta.content


# ============================================
# 测试代码
# ============================================
if __name__ == "__main__":
    # 测试基础调用
    print("=== 测试基础调用 ===")
    result = chat([
        {"role": "user", "content": "用一句话解释什么是 API"}
    ])
    print(result)

    print("\n=== 测试流式调用 ===")
    for chunk in chat_stream([
        {"role": "user", "content": "数到10"}
    ]):
        print(chunk, end="", flush=True)
    print()

2.6 理解 Token 和计费

什么是 Token?

LLM 不直接处理"字",而是处理 Token(词元)。一个 Token 大约等于:

  • 英文:1 个 Token ≈ 0.75 个单词
  • 中文:1 个 Token ≈ 0.5 个汉字(中文更"贵"一些)

举例:

"你好世界"       → 大约 4-6 个 token
"Hello World"   → 大约 2-3 个 token

DeepSeek 的价格(非常便宜!)

模型输入价格输出价格100万token≈
deepseek-chat¥1/百万token¥2/百万token约70万汉字
deepseek-reasoner¥4/百万token¥16/百万token约70万汉字

📊 直观感受:发100条消息,每条1000字,总花费约 ¥0.2

计算 Token 数量(可选)

# 安装 tiktoken
# pip install tiktoken

import tiktoken

def count_tokens(text: str) -> int:
    """估算一段文本的 token 数"""
    # DeepSeek 兼容 OpenAI 的 tokenizer
    encoding = tiktoken.get_encoding("cl100k_base")
    return len(encoding.encode(text))

print(count_tokens("你好世界"))       # 输出大约 4-6
print(count_tokens("Hello World"))    # 输出大约 2-3

📝 本章小结

已完成内容
Python 环境配置 + 虚拟环境
获取 DeepSeek API Key + 安全存储
第一个 API 调用成功
封装了 chat() / chat_with_tools() / chat_stream()
理解了 Token 概念和计费方式

✏️ 练习题

  1. 动手做:修改 temperature 参数(0.1、0.7、1.5),对同一个问题"讲个笑话",看看输出有什么不同。

  2. 动手做:给 system 消息设置不同的角色(“你是一个诗人”、“你是一个程序员”、“你是一个5岁小孩”),问同一个问题,观察回答风格的差异。

  3. 挑战题:用 chat_stream() 函数做一个简单的命令行对话程序,用户输入一句,AI 逐字输出回复,可以持续对话直到用户输入 quit


下一章预告第3章:Tool Calling — 让 Agent 拥有"手" —— 这章是 Agent 最核心的技术,学会它你就掌握了 Agent 的"灵魂"!

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐