← 返回文章列表

大模型应用开发者 Python 必修课(二):环境配置篇

2024-01-27·5 分钟阅读

大模型应用开发者 Python 必修课(二):环境配置篇

前言

在大模型应用开发中,良好的环境配置是项目成功的基础。不同的项目可能需要不同版本的依赖库,比如项目 A 使用 openai==1.0.0,而项目 B 需要 openai==1.20.0。如果没有合理的隔离机制,依赖冲突会让你焦头烂额。

本章将深入探讨 Python 环境管理的核心概念和最佳实践,帮助你建立专业级的开发环境。

虚拟环境:为什么需要它?

依赖隔离问题

假设你的系统中有两个项目:

系统 Python 环境:
├── openai 1.0.0 (全局安装)

项目 A 需要:
├── openai >= 1.0.0  ✓ 满足

项目 B 需要:
├── openai >= 1.20.0  ✗ 版本过低!

这就是典型的依赖冲突问题。虚拟环境通过为每个项目创建独立的 Python 环境来解决这个问题。

虚拟环境的原理

虚拟环境结构:

my-project/
├── .venv/                    # 虚拟环境目录
│   ├── bin/                  # Linux/macOS
│   │   ├── python -> /usr/bin/python3.10
│   │   ├── pip
│   │   └── activate
│   ├── Scripts/              # Windows
│   │   ├── python.exe
│   │   ├── pip.exe
│   │   └── activate.bat
│   ├── lib/
│   │   └── python3.10/
│   │       └── site-packages/  # 独立的包安装目录
│   └── pyvenv.cfg            # 环境配置文件
├── src/
├── tests/
└── pyproject.toml

虚拟环境的关键特性:

  1. 独立的 site-packages:每个环境有自己的包安装目录
  2. Python 解释器链接:指向创建时使用的 Python 版本
  3. 隔离的 PATH:激活后,优先使用环境内的命令

创建虚拟环境的三种方式

1. venv(Python 内置)

Python 3.3+ 内置的虚拟环境工具,轻量且无需额外安装:

# 创建虚拟环境
python -m venv .venv

# 激活虚拟环境
# Linux/macOS
source .venv/bin/activate

# Windows (PowerShell)
.venv\Scripts\Activate.ps1

# Windows (CMD)
.venv\Scripts\activate.bat

# 退出虚拟环境
deactivate

优点

  • 内置工具,无需额外安装
  • 轻量级,创建速度快
  • 标准化,兼容性好

缺点

  • 不支持直接指定 Python 版本(使用创建时的 Python)
  • 功能相对简单

2. virtualenv

功能更强大的第三方虚拟环境工具:

# 安装
pip install virtualenv

# 创建虚拟环境
virtualenv .venv

# 指定 Python 版本
virtualenv -p python3.10 .venv
virtualenv -p python3.11 .venv

优点

  • 支持指定任意 Python 版本
  • 创建速度更快(使用缓存)
  • 支持更多配置选项

缺点

  • 需要额外安装
  • 对于简单项目可能过度

3. conda

适合数据科学和机器学习项目:

# 创建环境
conda create -n llm-project python=3.10

# 激活环境
conda activate llm-project

# 退出环境
conda deactivate

# 列出所有环境
conda env list

# 删除环境
conda env remove -n llm-project

优点

  • 可以管理不同版本的 Python 本身
  • 支持非 Python 依赖(如 CUDA)
  • 适合数据科学和机器学习项目

缺点

  • 安装体积大
  • 与 pip 混用时可能产生问题

选择建议

场景推荐工具
纯 Python 项目venv
需要管理多个 Python 版本virtualenv 或 conda
数据科学/机器学习项目conda
大模型应用开发(API 调用)venv + poetry
需要安装 CUDA 等系统依赖conda

依赖管理工具对比

pip + requirements.txt

传统的依赖管理方式:

# 安装依赖
pip install openai anthropic

# 导出依赖
pip freeze > requirements.txt

# 从文件安装
pip install -r requirements.txt

requirements.txt 示例

openai==1.12.0
anthropic==0.18.0
httpx==0.27.0
pydantic==2.6.0
python-dotenv==1.0.0

问题

  • 无法区分开发依赖和生产依赖
  • 没有依赖锁定机制(间接依赖版本不确定)
  • 跨平台时可能有兼容性问题

pip-tools

pip 的增强工具,支持依赖锁定:

# 安装
pip install pip-tools

# 创建 requirements.in(直接依赖)
# requirements.in
openai>=1.0.0
anthropic>=0.18.0
pydantic>=2.0.0

# 编译生成 requirements.txt(包含所有依赖)
pip-compile requirements.in

# 安装
pip-sync

生成的 requirements.txt:

# This file is autogenerated by pip-compile
# Using the following versions:
#   openai==1.12.0
#   anthropic==0.18.0
#   ...

openai==1.12.0
    # via -r requirements.in
anthropic==0.18.0
    # via -r requirements.in
httpx==0.27.0
    # via
    #   anthropic
    #   openai
pydantic==2.6.0
    # via
    #   anthropic
    #   openai

Poetry(推荐)

现代 Python 项目管理工具,集成了依赖管理、虚拟环境、打包发布:

# 安装
pip install poetry

# 创建新项目
poetry new llm-project

# 或在现有项目中初始化
poetry init

# 添加依赖
poetry add openai anthropic

# 添加开发依赖
poetry add --group dev pytest black ruff

# 安装所有依赖
poetry install

# 激活虚拟环境
poetry shell

pyproject.toml 示例

[tool.poetry]
name = "llm-project"
version = "0.1.0"
description = "大模型应用项目"
authors = ["Your Name <your@email.com>"]
readme = "README.md"
packages = [{include = "llm_project"}]

[tool.poetry.dependencies]
python = "^3.10"
openai = "^1.12.0"
anthropic = "^0.18.0"
pydantic = "^2.6.0"
python-dotenv = "^1.0.0"

[tool.poetry.group.dev.dependencies]
pytest = "^8.0.0"
black = "^24.0.0"
ruff = "^0.2.0"
mypy = "^1.8.0"

[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

Poetry 优势

  1. 依赖锁定:poetry.lock 确保跨环境一致性
  2. 分组管理:区分生产依赖和开发依赖
  3. 版本约束:语义化版本控制
  4. 虚拟环境集成:自动创建和管理虚拟环境
  5. 打包发布:内置构建和发布功能

uv(新一代工具)

由 Astral(Ruff 的开发者)推出的超快 Python 包管理器:

# 安装
pip install uv

# 创建虚拟环境
uv venv

# 安装依赖(比 pip 快 10-100 倍)
uv pip install openai anthropic

# 从 requirements.txt 安装
uv pip install -r requirements.txt

# 从 pyproject.toml 安装
uv pip install -e .

优势

  • 极快的依赖解析和安装速度
  • 兼容 pip 命令
  • 内存占用低

适用场景

  • CI/CD 环境中加速依赖安装
  • 大型项目的快速环境搭建

工具对比总结

特性pip + requirementspip-toolsPoetryuv
依赖锁定
开发依赖分离
虚拟环境管理
安装速度中等极快
学习成本
生产推荐

生产级项目结构

推荐的目录结构

llm-project/
├── .venv/                     # 虚拟环境(不提交到 Git)
├── src/                       # 源代码目录
│   └── llm_project/
│       ├── __init__.py
│       ├── config.py          # 配置管理
│       ├── clients/           # API 客户端
│       │   ├── __init__.py
│       │   ├── openai_client.py
│       │   └── anthropic_client.py
│       ├── models/            # 数据模型
│       │   ├── __init__.py
│       │   └── schemas.py
│       ├── services/          # 业务逻辑
│       │   ├── __init__.py
│       │   └── chat_service.py
│       └── utils/             # 工具函数
│           ├── __init__.py
│           └── helpers.py
├── tests/                     # 测试目录
│   ├── __init__.py
│   ├── conftest.py            # pytest 配置
│   ├── test_clients/
│   └── test_services/
├── .env.example               # 环境变量模板
├── .env                       # 环境变量(不提交)
├── .gitignore
├── pyproject.toml             # 项目配置
├── poetry.lock                # 依赖锁定
└── README.md

pyproject.toml 完整配置

[tool.poetry]
name = "llm-project"
version = "0.1.0"
description = "大模型应用项目"
authors = ["Your Name <your@email.com>"]
readme = "README.md"
packages = [{include = "llm_project", from = "src"}]

[tool.poetry.dependencies]
python = "^3.10"
openai = "^1.12.0"
anthropic = "^0.18.0"
pydantic = "^2.6.0"
pydantic-settings = "^2.1.0"
python-dotenv = "^1.0.0"
httpx = "^0.27.0"
tenacity = "^8.2.0"  # 重试机制

[tool.poetry.group.dev.dependencies]
pytest = "^8.0.0"
pytest-asyncio = "^0.23.0"
pytest-cov = "^4.1.0"
black = "^24.0.0"
ruff = "^0.2.0"
mypy = "^1.8.0"
pre-commit = "^3.6.0"

[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

# Black 配置
[tool.black]
line-length = 88
target-version = ["py310"]
include = '\.pyi?$'

# Ruff 配置
[tool.ruff]
line-length = 88
target-version = "py310"
select = ["E", "F", "I", "N", "W", "UP"]
ignore = ["E501"]

[tool.ruff.per-file-ignores]
"__init__.py" = ["F401"]

# MyPy 配置
[tool.mypy]
python_version = "3.10"
strict = true
warn_return_any = true
warn_unused_configs = true

# Pytest 配置
[tool.pytest.ini_options]
testpaths = ["tests"]
asyncio_mode = "auto"
addopts = "-v --tb=short"

.gitignore 配置

# Python
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg

# Virtual environments
.venv/
venv/
ENV/
env/

# IDE
.idea/
.vscode/
*.swp
*.swo
*~

# Environment variables
.env
.env.local
.env.*.local

# Testing
.pytest_cache/
.coverage
htmlcov/
.tox/
.nox/

# MyPy
.mypy_cache/
.dmypy.json
dmypy.json

# Ruff
.ruff_cache/

# Jupyter
.ipynb_checkpoints/

环境变量管理

使用 python-dotenv

# .env 文件
OPENAI_API_KEY=sk-xxx
ANTHROPIC_API_KEY=sk-ant-xxx
MODEL_NAME=gpt-4
TEMPERATURE=0.7
MAX_TOKENS=4096

# config.py
from dotenv import load_dotenv
import os

# 加载 .env 文件
load_dotenv()

class Config:
    OPENAI_API_KEY: str = os.getenv("OPENAI_API_KEY", "")
    ANTHROPIC_API_KEY: str = os.getenv("ANTHROPIC_API_KEY", "")
    MODEL_NAME: str = os.getenv("MODEL_NAME", "gpt-4")
    TEMPERATURE: float = float(os.getenv("TEMPERATURE", "0.7"))
    MAX_TOKENS: int = int(os.getenv("MAX_TOKENS", "4096"))

使用 pydantic-settings(推荐)

# config.py
from pydantic_settings import BaseSettings, SettingsConfigDict
from functools import lru_cache

class Settings(BaseSettings):
    """应用配置"""
    model_config = SettingsConfigDict(
        env_file=".env",
        env_file_encoding="utf-8",
        case_sensitive=False,
    )

    # API 密钥
    openai_api_key: str = ""
    anthropic_api_key: str = ""

    # 模型配置
    model_name: str = "gpt-4"
    temperature: float = 0.7
    max_tokens: int = 4096

    # 应用配置
    debug: bool = False
    log_level: str = "INFO"

@lru_cache
def get_settings() -> Settings:
    """获取配置单例"""
    return Settings()

# 使用
settings = get_settings()
print(settings.model_name)  # "gpt-4"

pydantic-settings 优势

  1. 类型验证:自动转换和验证环境变量类型
  2. 嵌套配置:支持复杂的配置结构
  3. 环境变量前缀:避免命名冲突
  4. 默认值:支持必填项和默认值

环境变量最佳实践

# 生产环境配置示例
from pydantic_settings import BaseSettings
from pydantic import Field, validator

class Settings(BaseSettings):
    """生产级配置"""

    # API 密钥(必填)
    openai_api_key: str = Field(..., min_length=1)
    anthropic_api_key: str = Field(..., min_length=1)

    # 模型配置
    model_name: str = Field(default="gpt-4")
    temperature: float = Field(default=0.7, ge=0, le=2)
    max_tokens: int = Field(default=4096, ge=1, le=128000)

    # 并发配置
    max_concurrent_requests: int = Field(default=10, ge=1, le=100)
    request_timeout: float = Field(default=30.0, ge=1)

    # 重试配置
    max_retries: int = Field(default=3, ge=0)
    retry_delay: float = Field(default=1.0, ge=0)

    @validator("openai_api_key")
    def validate_openai_key(cls, v: str) -> str:
        if not v.startswith("sk-"):
            raise ValueError("OpenAI API key should start with 'sk-'")
        return v

    class Config:
        env_file = ".env"
        env_file_encoding = "utf-8"

# 使用
try:
    settings = Settings()
except Exception as e:
    raise ValueError(f"Configuration error: {e}")

多环境配置

config/
├── .env.development    # 开发环境
├── .env.staging        # 测试环境
├── .env.production     # 生产环境
└── .env.example        # 模板文件
import os
from pydantic_settings import BaseSettings

class Settings(BaseSettings):
    # ... 配置项

    class Config:
        # 根据 ENV 环境变量选择配置文件
        env = os.getenv("ENV", "development")
        env_file = f"config/.env.{env}"

settings = Settings()

快速启动模板

创建新项目

# 使用 Poetry 创建项目
poetry new llm-project
cd llm-project

# 初始化 git
git init

# 创建目录结构
mkdir -p src/llm_project/{clients,models,services,utils}
mkdir -p tests/{test_clients,test_services}

# 创建配置文件
touch .env.example
touch src/llm_project/__init__.py
touch src/llm_project/config.py
touch tests/conftest.py

# 安装依赖
poetry add openai anthropic pydantic pydantic-settings python-dotenv httpx tenacity
poetry add --group dev pytest pytest-asyncio pytest-cov black ruff mypy pre-commit

一键脚本

创建 setup.sh(Linux/macOS):

#!/bin/bash

PROJECT_NAME=${1:-"llm-project"}

# 创建项目
poetry new $PROJECT_NAME
cd $PROJECT_NAME

# 创建目录结构
mkdir -p src/$PROJECT_NAME/{clients,models,services,utils}
mkdir -p tests/{test_clients,test_services}

# 创建文件
touch .env.example
touch src/$PROJECT_NAME/__init__.py
touch src/$PROJECT_NAME/config.py
touch tests/conftest.py

# 初始化 git
git init

echo "Project $PROJECT_NAME created successfully!"
echo "Next steps:"
echo "  1. cd $PROJECT_NAME"
echo "  2. poetry add openai anthropic pydantic"
echo "  3. Edit .env with your API keys"

创建 setup.ps1(Windows PowerShell):

param(
    [string]$ProjectName = "llm-project"
)

# 创建项目
poetry new $ProjectName
Set-Location $ProjectName

# 创建目录结构
$Dirs = @(
    "src/$ProjectName/clients",
    "src/$ProjectName/models",
    "src/$ProjectName/services",
    "src/$ProjectName/utils",
    "tests/test_clients",
    "tests/test_services"
)

foreach ($Dir in $Dirs) {
    New-Item -ItemType Directory -Path $Dir -Force | Out-Null
}

# 创建文件
New-Item -ItemType File -Path ".env.example" -Force | Out-Null
New-Item -ItemType File -Path "src/$ProjectName/__init__.py" -Force | Out-Null
New-Item -ItemType File -Path "src/$ProjectName/config.py" -Force | Out-Null
New-Item -ItemType File -Path "tests/conftest.py" -Force | Out-Null

# 初始化 git
git init

Write-Host "Project $ProjectName created successfully!"
Write-Host "Next steps:"
Write-Host "  1. cd $ProjectName"
Write-Host "  2. poetry add openai anthropic pydantic"
Write-Host "  3. Edit .env with your API keys"

小结

本章我们学习了:

  1. 虚拟环境原理:理解为什么需要虚拟环境和它的工作机制
  2. 虚拟环境工具:venv、virtualenv、conda 的选择策略
  3. 依赖管理工具:pip、pip-tools、Poetry、uv 的对比和推荐
  4. 项目结构:生产级 Python 项目的目录组织
  5. 环境变量管理:使用 pydantic-settings 进行类型安全的配置管理

参考资料

  1. Python venv 文档
  2. Poetry 官方文档
  3. uv 官方文档
  4. pydantic-settings 文档
  5. Python 打包用户指南

下一章预告

在下一章《核心语法篇》中,我们将深入学习:

  • Python 数据结构的高级用法
  • 列表推导、字典推导、生成器表达式
  • 生成器与迭代器的原理
  • 装饰器的实现与应用
  • 上下文管理器与 with 语句

系列持续更新中,欢迎关注!

分享: