从0到跑通业务(应该能吧)
零基础可上手,代码复制即跑,2小时入门 AI 应用开发
学习路径
环境搭建 → 调用大模型 → SDK封装 → 记忆/流式/Prompt → 落地案例 → 报错兜底
第0章 前置环境
Node.js · Python · 环境变量 · 代理配置 · 一键安装脚本
1 Node.js 环境(前端项目用)
版本要求:18+,推荐 20 LTS。用 nvm 管理多版本。
# ========== Node.js 安装(任选一种)==========
# 方式A:nvm(推荐,版本切换方便)
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.0/install.sh | bash
nvm install 20
nvm use 20
node -v # 确认输出 v20.x.x
# 方式B:直接下载(Windows去 nodejs.org 下载 MSI)
# Linux 一键
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - && sudo apt-get install -y nodejs
node -v && npm -v
验证成功:输出了 v20.x.x 版本号
2 Python 环境(后端/AI脚本用)
版本要求:3.10 - 3.12。推荐 conda 管理虚拟环境。
# ========== Python 安装(任选一种)==========
# 方式A:Miniconda(推荐,隔离性好)
# 下载:https://docs.anaconda.com/miniconda/
# Linux:
wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh
bash Miniconda3-latest-Linux-x86_64.sh
# 安装时选"yes"自动加入 PATH
# 方式B:系统 Python + venv
sudo apt update && sudo apt install python3.11 python3.11-venv python3-pip
python3.11 -m venv ai-env
source ai-env/bin/activate
# 验证
python --version # 确认输出 Python 3.10+ 或 3.11+ 或 3.12+
pip --version
3 pip 镜像源配置(国内必做)
不配置镜像,pip install 慢到怀疑人生。
# ========== pip 镜像源配置 ==========
# 临时使用(每次命令后跟 -i)
pip install requests -i https://pypi.tuna.tsinghua.edu.cn/simple
# 永久配置
mkdir -p ~/.pip
cat > ~/.pip/pip.conf << 'EOF'
[global]
index-url = https://pypi.tuna.tsinghua.edu.cn/simple
[install]
trusted-host = pypi.tuna.tsinghua.edu.cn
EOF
# 验证
pip config list
4 npm / yarn 镜像源配置
# ========== npm 镜像源配置 ==========
# 查看当前源
npm config get registry
# 临时使用
npm install express -g --registry=https://registry.npmmirror.com
# 永久配置为淘宝镜像
npm config set registry https://registry.npmmirror.com
# 验证
npm config get registry # 应输出 https://registry.npmmirror.com
5 API 密钥环境变量配置
密钥绝对不能硬编码进代码,泄漏后立即重置。
# ========== 环境变量配置 ==========
# Linux/Mac:将以下写入 ~/.bashrc 或 ~/.zshrc
# Windows:用系统属性 -> 环境变量 GUI界面
# ==== 方式A:.env 文件(项目内,推荐) ====
# 项目根目录创建 .env 文件(加入 .gitignore!)
cat > .env << 'EOF'
# 大模型 API Keys(去对应平台申请)
OPENAI_API_KEY=sk-xxxxxxxxxxxxxxxx
DASHSCOPE_API_KEY=sk-xxxxxxxxxxxxxxxx
# 代理(如需要)
HTTP_PROXY=http://127.0.0.1:7890
HTTPS_PROXY=http://127.0.0.1:7890
EOF
# ==== 方式B:系统环境变量(全局) ====
# Linux/Mac 永久生效:
echo 'export OPENAI_API_KEY="sk-xxxxx"' >> ~/.bashrc
echo 'export DASHSCOPE_API_KEY="sk-xxxxx"' >> ~/.bashrc
source ~/.bashrc
# 验证环境变量是否生效
echo $OPENAI_API_KEY # 应输出 sk-xxxxx(不要泄露!)
python -c "import os; print(os.environ.get('OPENAI_API_KEY','未设置'))"
警告:不要把 .env 提交到 GitHub!确保 .gitignore 包含 .env
6 一键依赖安装脚本
Node 和 Python 项目的依赖一键装好。
# ========== 一键安装脚本 ==========
# --- Node.js 项目 ---
cat > install-node.sh << 'EOF'
#!/bin/bash
set -e
echo "安装 Node.js 依赖..."
npm install
echo "✅ Node.js 依赖安装完成"
npm --version
node --version
EOF
chmod +x install-node.sh
./install-node.sh
# --- Python 项目 ---
cat > install-python.sh << 'EOF'
#!/bin/bash
set -e
echo "安装 Python 依赖..."
pip install --upgrade pip
pip install requests openai python-dotenv tqdm
echo "✅ Python 依赖安装完成"
pip --version
python --version
EOF
chmod +x install-python.sh
./install-python.sh
7 本地开发服务器 + 跨域配置
前端开发时解决跨域问题的几种方案。
// ========== 方案A:Vite 代理(推荐) ==========
// vite.config.js
import { defineConfig } from 'vite'
export default defineConfig({
server: {
port: 3000, // 本地端口
proxy: {
// /api/proxy -> https://api.openai.com(不发OPTIONS预检)
'/api/proxy': {
target: 'https://api.openai.com',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api\/proxy/, ''),
},
// /api/proxy-dashscope -> https://dashscope.aliyuncs.com
'/api/proxy-dashscope': {
target: 'https://dashscope.aliyuncs.com',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api\/proxy-dashscope/, ''),
}
}
}
})
// 使用时:
// fetch('/api/proxy/v1/chat/completions', ...) // 浏览器只发一次请求到本服务器
# ========== 方案B:Python CORS 代理(最简) ==========
# 文件:cors_proxy.py
# 运行:python cors_proxy.py,然后前端请求 http://localhost:8888/...
import http.server
import urllib.request
import json
class CORSProxy(http.server.BaseHTTPRequestHandler):
def do_OPTIONS(self):
self.send_response(200)
self.send_header('Access-Control-Allow-Origin', '*')
self.send_header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS')
self.send_header('Access-Control-Allow-Headers', 'Content-Type, Authorization')
self.end_headers()
def do_POST(self):
# 读取请求体
content_length = int(self.headers.get('Content-Length', 0))
body = self.rfile.read(content_length)
# 转发到目标
# 例如 OpenAI:target = 'https://api.openai.com/v1/chat/completions'
target = 'https://api.openai.com/v1/chat/completions' # 改成你的目标地址
req = urllib.request.Request(target, data=body, headers={
'Content-Type': 'application/json',
'Authorization': self.headers.get('Authorization', '')
}, method='POST')
try:
with urllib.request.urlopen(req, timeout=30) as resp:
data = resp.read()
self.send_response(200)
self.send_header('Access-Control-Allow-Origin', '*')
self.send_header('Content-Type', 'application/json')
self.end_headers()
self.wfile.write(data)
except Exception as e:
self.send_response(502)
self.send_header('Access-Control-Allow-Origin', '*')
self.end_headers()
self.wfile.write(json.dumps({'error': str(e)}).encode())
if __name__ == '__main__':
server = http.server.HTTPServer(('0.0.0.0', 8888), CORSProxy)
print('CORS 代理运行在 http://localhost:8888')
server.serve_forever()
第1章 核心基础
LLM 架构原理 · 主流模型代际 · API Key · 关键参数 · 请求体结构
1 LLM 核心原理:Transformer + Attention
大模型本质是一个语言建模器:根据前文预测下一个词。所有现代 LLM 都基于 Transformer 架构。
一句话理解
Transformer = 注意力机制 + 前馈网络 + 残差连接。Attention 让每个词"看到"其他所有词的关系,决定谁更重要。
Attention 机制(图解)
输入序列: [我, 爱, 学, Python]
↓
Step 1: 计算 Q(Query 查询)、K(Key 键)、V(Value 值)
Q = 输入 × Wq(我要找什么)
K = 输入 × Wk(我有什么特征)
V = 输入 × Wv(我的实际内容)
Step 2: 计算注意力分数
Score = Q · Kᵀ / √dk
(点积后缩放,防止梯度消失)
Step 3: Softmax 归一化 → 得到注意力权重
Attention = softmax(Score) × V
"Python" 应该给 "学" 更高的注意力权重(学Python)
"爱" 应该给 "Python" 更高的注意力权重(爱学Python)
核心公式:
Attention(Q,K,V) = softmax(QKᵀ / √dk) · V
Multi-Head Attention(多头注意力)
多组 Q/K/V 并行学习不同类型的依赖关系(语法、语义、位置等)。
MultiHead(Q,K,V) = Concat(head₁,...,headₕ) · W⁰
其中 headᵢ = Attention(Q·WᵢQ, K·WᵢK, V·WᵢV)
GPT 系列使用:
- Decoder-Only 架构(只有 Masked Self-Attention)
- 单向注意力(只能看前面的词),适合生成任务
- BERT 使用双向 Attention,适合理解任务
FFN(前馈网络)+ 残差 + LayerNorm
每个 Transformer Block:
x → + → Norm → Attention → + → Norm → FFN → + → 输出
↑ ↑
残差连接 残差连接
FFN(x) = ReLU(x·W₁ + b₁) · W₂ + b₂
= max(0, xW₁+b₁)W₂+b₂ (两层线性变换,中间升维)
LayerNorm: 标准化每一层的输出,加速训练收敛
位置编码(Positional Encoding)
Attention 本身不感知位置,需要手动注入位置信息。
GPT 使用 Rotary Position Embedding(RoPE):
- 旋转位置编码,而非绝对位置编码
- 相对位置信息更自然,适合长序列
公式理解:
将位置信息编码为旋转矩阵
x_i 与 x_j 的注意力只依赖相对距离 (i-j)
GPT 模型的生成过程
输入:"今天天气真"
↓ tokenize → [今天, 天气, 真]
↓ embedding + 位置编码
↓ N 层 Transformer Block(Masked Self-Attention + FFN)
↓ 投影到词表维度( vocab_size 如 50000)
↓ softmax → 每个词的概率分布
↓ 采样/贪心 → 选"好"
目标:最大化 P(下一个词|前文) 的似然
Loss = -Σ log P(真实词ᵢ)
训练时:Teacher Forcing(用真实前文预测下一个)
推理时:自回归(用自己的输出作为下一步的输入)
2 当前主流模型代际(2026年4月)
了解当前模型格局,才能选对模型、评估能力、合理定价。
| 模型 | 发布方 | 上下文 | 定位 | 备注 |
|---|---|---|---|---|
| deepseek-v4 | DeepSeek | 1M | 开源旗舰 | 最新DeepSeek旗舰,MoE架构,推理能力大幅提升 |
| gpt-4.5 | OpenAI | 256k | 旗舰多模态 | 2026最新版,o3推理模型已上线 |
| claude-4-sonnet | Anthropic | 200k | 编程+分析 | 2026最新,编程能力最强 |
| gemini-2.5-pro | 2M | 超长上下文 | 200万上下文,多模态全面升级 | |
| gpt-4o-mini | OpenAI | 128k | 性价比 | 比4.5便宜85%,能力依然强 |
| qwen3-72b | 阿里 | 256k | 开源旗舰 | Qwen3旗舰,中文最强开源 |
| qwen3-coder-32b | 阿里 | 256k | 代码专用 | 代码能力最强开源模型 |
| llama-4-405b | Meta | 256k | 开源超大杯 | Llama4旗舰,超越GPT-4水平 |
| deepseek-v3 | DeepSeek | 64k | 开源性价比 | MoE架构,API价格极低 |
| mistral-large-3 | Mistral | 128k | 欧洲代表 | 欧洲最强开源,多语言优秀 |
选模型建议
通用对话 / 写作 → gpt-4.5 / claude-4-sonnet / qwen3-72b
编程 / 代码 → claude-4-sonnet / qwen3-coder-32b / gpt-4.5
超长文档分析 → gemini-2.5-pro / deepseek-v4
低成本商用 → deepseek-v4 / deepseek-v3 / qwen3-72b
3 API Key 申请与平台选择
OpenAI(全球最通用)
申请:https://platform.openai.com/api-keys
模型:gpt-4.5, gpt-4o-mini, o3, o4-mini
注意:国内需要代理,推荐用国内平台替代
阿里云百炼 DashScope(国内首选)
申请:https://bailian.console.aliyun.com
模型:qwen-plus, qwen-max, qwen-long, qwen3-72b-instruct
✓ 国内直连,稳定,API 兼容 OpenAI 格式
硅基流动 SiliconFlow(免费额度高)
申请:https://cloud.siliconflow.cn
模型:Qwen/Qwen3-72B-Instruct, deepseek-ai/DeepSeek-V4, 大量开源模型
✓ 免费额度充足,白嫖友好,兼容 OpenAI SDK
Google AI(Gemma / Gemini)
申请:https://aistudio.google.com
模型:gemini-2.5-pro, gemini-2.5-flash, gemma-3-27b
✓ 超大上下文(200万token),免费额度慷慨
4 关键参数详解(7个必须懂的)
model
模型名称。决定能力上限、速度和价格。
messages
对话历史列表。
system:系统指令(定义AI角色、能力边界)
user:用户输入
assistant:AI历史回复(用于多轮上下文)
tool:工具调用结果(Function Calling后)
max_tokens(最大生成长度)
AI回复的最大 token 数上限,不是精确长度。
简单问答:200-500
一般写作:500-1500
长文生成:1500-4000
设太小会截断,设太大会浪费 tokens 和钱
temperature(创造性,0-2)
控制输出的随机性,本质是调整 softmax 的 logits 分布。
0.0-0.3:确定性输出(代码、翻译、数学)
0.5-0.7:一般对话默认值
1.0-1.5:创意写作、头脑风暴
公式:P(wᵢ) = softmax(logitsᵢ / T)
top_p(核采样,0-1)
从概率最高的 top_p 比例的词中采样。temperature=0 时相当于贪心。
1.0:不使用 top_p(全部词参与)
0.9:从概率最高的90%词中采样
一般 top_p 和 temperature 只用调一个,不要同时调
frequency_penalty(频率惩罚,-2 到 2)
减少重复已生成过的词的概率。值越大越不重复。
= 0:不惩罚(正常生成)
= 0.5-1.0:轻度减少重复
= 1.5-2.0:强制多样化和换词(可能影响连贯性)
presence_penalty(存在惩罚,-2 到 2)
只要词在历史中出现过就惩罚,不管出现频率。鼓励引入新话题。
= 0:不惩罚
= 0.5-1.0:鼓励谈新话题
= 1.5+:强制转换话题(可能跑偏)
stop(停止序列)
AI生成到指定字符串时停止。最多4个序列。
stop: ["===", "\n\n"] → 生成到这些字符停止
用于控制输出格式,如限制不超过某个标记
5 请求体结构(OpenAI 兼容格式)
{
"model": "gpt-4o-mini", // 模型名称(必填)
"messages": [ // 对话历史(必填)
{"role": "system", "content": "你是一个专业的Python后端工程师"}, // 系统指令
{"role": "user", "content": "解释一下闭包"}, // 用户问题
{"role": "assistant", "content": "闭包是..."}, // AI历史(可选)
{"role": "user", "content": "那装饰器呢"} // 追问
],
"max_tokens": 1000, // 最大生成token
"temperature": 0.7, // 创造性(0-2)
"top_p": 1.0, // 核采样(通常不调)
"frequency_penalty": 0, // 重复惩罚(0-2)
"presence_penalty": 0, // 话题新鲜度(-2到2)
"stream": false, // 是否流式
"stop": null, // 停止序列
"seed": null // 随机种子(temperature=0时生效)
}
// ========== 响应结构 ==========
{
"id": "chatcmpl-xxx",
"object": "chat.completion",
"created": 1710000000,
"model": "gpt-4o-mini",
"choices": [{
"index": 0,
"message": {
"role": "assistant",
"content": "闭包是指..."
},
"finish_reason": "stop", // stop | length | content_filter
"logprobs": null
}],
"usage": {
"prompt_tokens": 50, // 输入消耗
"completion_tokens": 120, // 输出消耗
"total_tokens": 170 // 总消耗
}
}
// ========== 流式响应 chunks ==========
{"id":"xxx","choices":[{"delta":{"content":"闭"},"finish_reason":null}]}
{"id":"xxx","choices":[{"delta":{"content":"包"},"finish_reason":null}]}
{"id":"xxx","choices":[{"delta":{"content":"是"},"finish_reason":null}]}
...
{"id":"xxx","choices":[{"delta":{},"finish_reason":"stop"}]}
6 上下文窗口(Context Window)详解
上下文窗口 = 单次请求能处理的 Token 上限(输入 + 输出)。超出会自动截断旧消息。
| 模型 | 上下文 | 说明 |
|---|---|---|
| gemini-2.0-flash | 1M tokens | ≈ 75万汉字 |
| claude-3.5-sonnet | 200k | ≈ 15万汉字 |
| gpt-4o / 4o-mini | 128k | ≈ 8万汉字 |
| qwen2.5 / deepseek-v3 | 128k / 64k | 开源主力 |
| qwen2.5-7b-instruct | 32k | 小模型中算大 |
Token 计算
1 中文汉字 ≈ 1.5 - 2.0 tokens(取决于模型 tokenizer)
1 个英文单词 ≈ 1.3 tokens
1 token ≈ 0.75 个单词(英文粗略估算)
Python 计算 token 数:
# pip install tiktoken
import tiktoken
enc = tiktoken.get_encoding("cl100k_base") # GPT-4/3.5 的编码器
tokens = enc.encode("床前明月光,疑是地上霜")
print(len(tokens)) # 输出 token 数
第2章 基础调用
原生 HTTP 调用 · Node.js / Python 双版本 · 完整可运行
1 Node.js 调用 OpenAI
使用原生 fetch(Node 18+),无需任何依赖。
// ========== 文件:openai_basic.mjs ==========
// 运行:node openai_basic.mjs
// 注意:需要设置环境变量 OPENAI_API_KEY
const API_KEY = process.env.OPENAI_API_KEY;
const API_URL = 'https://api.openai.com/v1/chat/completions';
async function callOpenAI(userMessage) {
const response = await fetch(API_URL, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${API_KEY}`,
},
body: JSON.stringify({
model: 'gpt-4o-mini', // 模型名称
messages: [
{ role: 'user', content: userMessage }
],
max_tokens: 500,
temperature: 0.7,
}),
});
// 检查HTTP状态码
if (!response.ok) {
const error = await response.text();
throw new Error(`API错误 ${response.status}: ${error}`);
}
const data = await response.json();
return data.choices[0].message.content;
}
// 调用示例
(async () => {
try {
const reply = await callOpenAI('用一句话介绍Python');
console.log('AI回复:', reply);
} catch (e) {
console.error('调用失败:', e.message);
}
})();
运行:OPENAI_API_KEY=sk-xxx node openai_basic.mjs
2 Python 调用 OpenAI
使用 requests 库,兼容所有 Python 版本。
# ========== 文件:openai_basic.py ==========
# 运行:python openai_basic.py
# 依赖:pip install requests
# 环境变量:export OPENAI_API_KEY=sk-xxx
import os
import requests
API_KEY = os.environ.get('OPENAI_API_KEY')
API_URL = 'https://api.openai.com/v1/chat/completions'
def call_openai(user_message: str) -> str:
"""调用 OpenAI ChatGPT,返回 AI 回复文本"""
headers = {
'Content-Type': 'application/json',
'Authorization': f'Bearer {API_KEY}',
}
payload = {
'model': 'gpt-4o-mini',
'messages': [
{'role': 'user', 'content': user_message}
],
'max_tokens': 500,
'temperature': 0.7,
}
response = requests.post(API_URL, headers=headers, json=payload, timeout=30)
response.raise_for_status() # HTTP错误时抛出异常
data = response.json()
return data['choices'][0]['message']['content']
# 调用示例
if __name__ == '__main__':
try:
reply = call_openai('用一句话介绍Python')
print(f'AI回复: {reply}')
except Exception as e:
print(f'调用失败: {e}')
运行:python openai_basic.py
3 Python 调用阿里云 DashScope(国内无需代理)
# ========== 文件:dashscope_basic.py ==========
# 运行:python dashscope_basic.py
# 依赖:pip install requests
# 环境变量:export DASHSCOPE_API_KEY=sk-xxx
# 模型列表:https://help.aliyun.com/zh/model-studio/getting-started/models
import os
import requests
API_KEY = os.environ.get('DASHSCOPE_API_KEY')
# DashScope 使用与 OpenAI 兼容的接口格式
API_URL = 'https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions'
def call_dashscope(user_message: str, model: str = 'qwen-plus') -> str:
"""调用阿里云 DashScope 大模型"""
headers = {
'Content-Type': 'application/json',
'Authorization': f'Bearer {API_KEY}',
}
payload = {
'model': model, # 可选:qwen-plus, qwen-turbo, qwen-max, qwen-long
'messages': [
{'role': 'user', 'content': user_message}
],
'max_tokens': 500,
'temperature': 0.7,
}
response = requests.post(API_URL, headers=headers, json=payload, timeout=30)
response.raise_for_status()
data = response.json()
return data['choices'][0]['message']['content']
if __name__ == '__main__':
try:
reply = call_dashscope('用一句话介绍Python', model='qwen-plus')
print(f'AI回复: {reply}')
except Exception as e:
print(f'调用失败: {e}')
第3章 SDK 封装
官方 SDK 标准化写法 · 多模型切换 · 统一接口层
1 Python:OpenAI 官方 SDK
# ========== 文件:llm_client.py ==========
# 运行:python llm_client.py
# 依赖:pip install openai python-dotenv
from openai import OpenAI
from dotenv import load_dotenv
import os
load_dotenv() # 加载 .env 文件中的环境变量
class LLMClient:
"""统一的大模型调用封装"""
def __init__(self, provider='openai'):
self.provider = provider
if provider == 'openai':
self.client = OpenAI(api_key=os.environ.get('OPENAI_API_KEY'))
self.default_model = 'gpt-4o-mini'
elif provider == 'dashscope':
# DashScope 使用 OpenAI 兼容接口
self.client = OpenAI(
api_key=os.environ.get('DASHSCOPE_API_KEY'),
base_url='https://dashscope.aliyuncs.com/compatible-mode/v1'
)
self.default_model = 'qwen-plus'
else:
raise ValueError(f'未知的 provider: {provider}')
def chat(self, message: str, model: str = None, temperature: float = 0.7, max_tokens: int = 500) -> str:
"""发送对话请求,返回 AI 回复"""
model = model or self.default_model
response = self.client.chat.completions.create(
model=model,
messages=[{'role': 'user', 'content': message}],
temperature=temperature,
max_tokens=max_tokens,
)
return response.choices[0].message.content
def chat_with_context(self, messages: list, model: str = None, temperature: float = 0.7) -> str:
"""带上下文的对话(支持多轮)"""
model = model or self.default_model
response = self.client.chat.completions.create(
model=model,
messages=messages,
temperature=temperature,
)
return response.choices[0].message.content
# 使用示例
if __name__ == '__main__':
# OpenAI
client = LLMClient(provider='openai')
reply = client.chat('用一句话介绍Python')
print(f'OpenAI: {reply}')
# 阿里云 DashScope
ds_client = LLMClient(provider='dashscope')
reply = ds_client.chat('用一句话介绍JavaScript')
print(f'DashScope: {reply}')
2 Node.js:OpenAI 官方 SDK
// ========== 文件:llm_client.mjs ==========
// 运行:node llm_client.mjs
// 依赖:npm install openai
// 环境变量:export OPENAI_API_KEY=sk-xxx
import OpenAI from 'openai';
class LLMClient {
constructor(provider = 'openai') {
this.provider = provider;
if (provider === 'openai') {
this.client = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
this.defaultModel = 'gpt-4o-mini';
} else if (provider === 'dashscope') {
this.client = new OpenAI({
apiKey: process.env.DASHSCOPE_API_KEY,
baseURL: 'https://dashscope.aliyuncs.com/compatible-mode/v1'
});
this.defaultModel = 'qwen-plus';
}
}
async chat(message, { model, temperature = 0.7, maxTokens = 500 } = {}) {
const response = await this.client.chat.completions.create({
model: model || this.defaultModel,
messages: [{ role: 'user', content: message }],
temperature,
max_tokens: maxTokens,
});
return response.choices[0].message.content;
}
async chatWithContext(messages, { model, temperature = 0.7 } = {}) {
const response = await this.client.chat.completions.create({
model: model || this.defaultModel,
messages,
temperature,
});
return response.choices[0].message.content;
}
}
// 使用示例
const client = new LLMClient('openai');
const reply = await client.chat('用一句话介绍Python');
console.log('OpenAI:', reply);
3 多模型统一调用(生产级封装)
一个函数调用,根据配置自动选择模型,切换模型不改业务代码。
# ========== 文件:unified_llm.py ==========
# 运行:python unified_llm.py
# 依赖:pip install openai python-dotenv
import os
from dotenv import load_dotenv
from openai import OpenAI
load_dotenv()
class UnifiedLLM:
"""统一调用入口,一个函数适配所有模型"""
# 模型配置表:可按需添加新模型
PROVIDERS = {
'gpt4o': {
'client': OpenAI(api_key=os.environ.get('OPENAI_API_KEY')),
'model': 'gpt-4o',
'base_url': None,
},
'gpt4o-mini': {
'client': OpenAI(api_key=os.environ.get('OPENAI_API_KEY')),
'model': 'gpt-4o-mini',
'base_url': None,
},
'qwen-plus': {
'client': OpenAI(
api_key=os.environ.get('DASHSCOPE_API_KEY'),
base_url='https://dashscope.aliyuncs.com/compatible-mode/v1'
),
'model': 'qwen-plus',
'base_url': 'dashscope',
},
'siliconflow': {
'client': OpenAI(
api_key=os.environ.get('SILICONFLOW_API_KEY'),
base_url='https://api.siliconflow.cn/v1'
),
'model': 'Qwen/Qwen2.5-7B-Instruct',
'base_url': 'siliconflow',
},
}
def __init__(self, provider_key='gpt4o-mini'):
cfg = self.PROVIDERS.get(provider_key)
if not cfg:
raise ValueError(f'未知 provider: {provider_key},可用: {list(self.PROVIDERS.keys())}')
self.client = cfg['client']
self.model = cfg['model']
def ask(self, prompt: str, temperature: float = 0.7, max_tokens: int = 1000) -> str:
"""同步调用,返回字符串"""
response = self.client.chat.completions.create(
model=self.model,
messages=[{'role': 'user', 'content': prompt}],
temperature=temperature,
max_tokens=max_tokens,
)
return response.choices[0].message.content
def ask_stream(self, prompt: str, temperature: float = 0.7):
"""流式调用,返回生成器"""
stream = self.client.chat.completions.create(
model=self.model,
messages=[{'role': 'user', 'content': prompt}],
temperature=temperature,
stream=True,
)
for chunk in stream:
if chunk.choices[0].delta.content:
yield chunk.choices[0].delta.content
# 使用示例
if __name__ == '__main__':
# 切换模型只需改这一行
llm = UnifiedLLM('qwen-plus') # 试试 'gpt4o-mini' 或 'siliconflow'
# 同步调用
reply = llm.ask('Python和JavaScript的区别是什么?')
print(f'回复: {reply}')
# 流式调用
print('\n流式输出: ', end='')
for text in llm.ask_stream('用3句话介绍Go语言'):
print(text, end='', flush=True)
print()
第4章 进阶能力
上下文记忆 · 流式输出 · Prompt 工程 · Function Calling
1 上下文记忆(多轮对话)
将对话历史组成 messages 数组传给模型,实现多轮连贯对话。
# ========== 文件:chat_with_memory.py ==========
# 运行:python chat_with_memory.py
import os
from openai import OpenAI
from dotenv import load_dotenv
load_dotenv()
client = OpenAI(api_key=os.environ.get('OPENAI_API_KEY'))
def chat_with_memory(user_input: str, history: list[dict]) -> tuple[str, list[dict]]:
"""
带记忆的对话
返回: (AI回复, 更新后的历史)
"""
# 将用户新输入追加到历史
history.append({'role': 'user', 'content': user_input})
response = client.chat.completions.create(
model='gpt-4o-mini',
messages=history,
temperature=0.7,
)
assistant_msg = response.choices[0].message.content
history.append({'role': 'assistant', 'content': assistant_msg})
return assistant_msg, history
# 使用示例
if __name__ == '__main__':
# 初始化对话历史(可加系统指令)
messages = [
{'role': 'system', 'content': '你是一个专业Python讲师,用简洁有趣的方式教学。'}
]
# 第1轮
reply1, messages = chat_with_memory('Python适合初学者吗?', messages)
print(f'AI: {reply1}\n')
# 第2轮(带历史)
reply2, messages = chat_with_memory('那Java呢?', messages)
print(f'AI: {reply2}\n')
# 第3轮(模型知道前两轮内容)
reply3, messages = chat_with_memory('它们两个学哪个好?', messages)
print(f'AI: {reply3}')
# 打印对话历史长度,确认上下文在累积
print(f'\n当前对话历史:{len(messages)} 条消息')
2 流式输出(打字机效果)
一个字一个字输出,适合长回复,提升用户体验。
# ========== 文件:stream_chat.py ==========
# 运行:python stream_chat.py
import os
from openai import OpenAI
from dotenv import load_dotenv
load_dotenv()
client = OpenAI(api_key=os.environ.get('OPENAI_API_KEY'))
def stream_chat(prompt: str):
"""流式调用,实时打印 AI 输出"""
stream = client.chat.completions.create(
model='gpt-4o-mini',
messages=[{'role': 'user', 'content': prompt}],
stream=True, # 关键:stream=True
)
print('AI: ', end='', flush=True)
full_reply = ''
for chunk in stream:
if chunk.choices[0].delta.content:
text = chunk.choices[0].delta.content
print(text, end='', flush=True)
full_reply += text
print() # 换行
return full_reply
# Node.js 版本:
# ========== 文件:stream_chat.mjs ==========
# const stream = await client.chat.completions.create({
# model: 'gpt-4o-mini',
# messages: [{ role: 'user', content: prompt }],
# stream: true,
# });
# for await (const chunk of stream) {
# process.stdout.write(chunk.choices[0].delta.content || '');
# }
if __name__ == '__main__':
reply = stream_chat('写一首关于编程的小诗')
3 Prompt 工程(核心技巧)
同一模型,Prompt不同效果天差地别。以下是经过验证的模板。
模板A:角色 + 任务 + 格式
你是一个[角色]。
请帮我[完成任务]。
输出格式:[要求的格式,如JSON/列表/段落]
举例:
你是一个Python后端开发专家。
请帮我评审以下代码的性能问题,给出优化建议。
输出格式:问题列表,每条包含:行号、问题描述、优化方案。
模板B:Few-shot(示例学习)
任务:将中文翻译成英文
示例:
输入:我爱你 → 输出:I love you
输入:今天天气真好 → 输出:The weather is nice today
现在翻译:
输入:这本书很好读
模板C:思维链(CoT)
问题:[复杂问题]
请分步骤思考,给出推理过程,最后给出答案。
先...再...最后...
举例:
问题:一个商店进了50个苹果,卖了30个,又进了20个,现在有多少?
请分步骤计算。
模板D:分隔符 + 提取结构化数据
请从以下文本中提取信息,输出JSON格式。
---
文本:
张三,男,1990年出生,软件工程师,月薪30000元。
李四,女,1995年出生,产品经理,月薪25000元。
---
输出格式(严格JSON):
{
"people": [
{"name": "", "gender": "", "birth_year": "", "job": "", "salary": 0}
]
}
4 Function Calling(让AI调用工具)
让AI决定调用哪个函数,实现天气查询、数据库查询等真实业务能力。
# ========== 文件:function_calling.py ==========
# 运行:python function_calling.py
import os
import json
from openai import OpenAI
from dotenv import load_dotenv
load_dotenv()
client = OpenAI(api_key=os.environ.get('OPENAI_API_KEY'))
# 定义可用函数
functions = [
{
'type': 'function',
'function': {
'name': 'get_weather',
'description': '查询城市天气',
'parameters': {
'type': 'object',
'properties': {
'city': {'type': 'string', 'description': '城市名称'},
'unit': {'type': 'string', 'enum': ['celsius', 'fahrenheit'], 'description': '温度单位'}
},
'required': ['city']
}
}
}
]
def get_weather(city: str, unit: str = 'celsius') -> dict:
"""模拟天气查询(真实项目里调用天气API)"""
return {'city': city, 'temperature': 22, 'condition': '晴天', 'unit': unit}
# 用户提问
user_question = '北京今天多少度?'
response = client.chat.completions.create(
model='gpt-4o-mini',
messages=[{'role': 'user', 'content': user_question}],
tools=functions,
)
assistant_msg = response.choices[0].message
print(f'AI回复内容: {assistant_msg.content}')
print(f'AI决定调用的工具: {assistant_msg.tool_calls}')
# 如果AI决定调用工具,执行函数
if assistant_msg.tool_calls:
for tool_call in assistant_msg.tool_calls:
fn_name = tool_call.function.name
fn_args = json.loads(tool_call.function.arguments)
print(f'\n执行函数: {fn_name}({fn_args})')
if fn_name == 'get_weather':
result = get_weather(**fn_args)
print(f'函数返回: {result}')
# 将工具结果反馈给AI,生成最终回复
follow_up = client.chat.completions.create(
model='gpt-4o-mini',
messages=[
{'role': 'user', 'content': user_question},
assistant_msg,
{'role': 'tool', 'tool_call_id': tool_call.id, 'content': json.dumps(result)},
],
)
print(f'\n最终回复: {follow_up.choices[0].message.content}')
5 RAG 检索增强生成
RAG = 检索 + 生成。让 AI 基于你自己的文档回答问题,而非大模型内部知识。
什么时候用 RAG?
✓ 私有文档问答(公司内部知识库)
✓ 需要引用最新文档(模型训练数据没有的)
✓ 需要答案可溯源(必须引用原始文档)
✗ 通用知识问答(直接问大模型即可)
RAG 核心流程
RAG 关键参数调优
Chunk Size(块大小)
常用:256 / 512 / 1024 tokens。代码用小块(256),文章用大块(512-1024)。
Top-K(召回数量)
通常取 3-10 个相关块。太多引入噪声,太少可能遗漏关键信息。
Chunk Overlap(重叠)
相邻块之间重叠 10-20%,防止块边界切断语义。
Embedding 模型
BGE / M3E / text2vec(中文);text-embedding-3-small(英文/多语言)。
完整 RAG 代码(LangChain)
# ========== 文件:simple_rag.py ==========
# 运行:python simple_rag.py
# 依赖:pip install langchain langchain-community \
# chromadb langchain-openai python-dotenv
import os
from dotenv import load_dotenv
from langchain_community.document_loaders import TextLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.vectorstores import Chroma
from langchain_openai import OpenAIEmbeddings, ChatOpenAI
from langchain.chains import RetrievalQA
load_dotenv()
# ========== Step 1: 加载文档 ==========
loader = TextLoader("knowledge.txt", encoding="utf-8")
documents = loader.load()
# ========== Step 2: 切块 ==========
splitter = RecursiveCharacterTextSplitter(
chunk_size=500, # 每块500 tokens
chunk_overlap=50, # 重叠50 tokens
separators=["\n\n", "\n", "。", "!", "?", " "] # 按优先级分割
)
chunks = splitter.split_documents(documents)
print(f"切成 {len(chunks)} 个块")
# ========== Step 3: 向量化存储 ==========
embedding = OpenAIEmbeddings(model="text-embedding-3-small")
vectorstore = Chroma.from_documents(
documents=chunks,
embedding=embedding,
persist_directory="./chroma_db" # 持久化存储
)
# ========== Step 4: 构建 QA Chain ==========
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
qa_chain = RetrievalQA.from_chain_type(
llm=llm,
chain_type="stuff", # stuff:将所有块塞进一个prompt
retriever=vectorstore.as_retriever(search_kwargs={"k": 3}),
return_source_documents=True # 返回引用的源文档
)
# ========== Step 5: 问答 ==========
query = "这份文档讲了什么主要内容?"
result = qa_chain.invoke({"query": query})
print(f"答案: {result['result']}")
print(f"引用了 {len(result['source_documents'])} 个文档块")
向量数据库选型
| 数据库 | 特点 | 适用场景 |
|---|---|---|
| ChromaDB | 轻量、本地、API 简单 | 原型 / 小规模 |
| Milvus | 生产级、高并发、分布式 | 大规模生产环境 |
| Qdrant | Rust 实现、性能好、有云服务 | 中等规模 |
| FAISS | Facebook 开源、纯本地、速度快 | 离线 / 嵌入式 |
| Pinecone | 全托管、云原生、免运维 | 快速上线 |
6 AI Agent(智能体)概念
Agent = 大模型 + 工具 + 规划 + 记忆。让 AI 自主完成复杂任务,而非被动回答。
Agent vs 普通 LLM 调用
普通 LLM
你问 → LLM 答 → 结束
单步执行
Agent
目标 → 规划 → 执行 → 反思 → 循环
自主决策多步
Agent 核心循环
while not goal_achieved:
1. Think(思考) → 模型分析当前状态,决定下一步
2. Plan(规划) → 拆解为可执行的步骤
3. Act(执行) → 调用工具(搜索/计算/代码等)
4. Observe(观察) → 获取工具返回结果
5. Reflect(反思) → 评估结果是否达成目标,决定继续或结束
ReAct 模式(推理 + 行动)
目前最主流的 Agent 实现范式,让模型交替进行推理和行动。
Thought: 我需要先搜索相关信息...
Action: search[Python async]
Observation: 搜索结果显示 Python async 相关资料...
Thought: 我已经获取了信息,现在可以回答...
Final Answer: Python 的 async/await 是用于...
常用 Agent 框架
LangChain Agents
支持多种 Agent 类型(ReAct、MRKL、Conversational)和工具
AutoGen(微软)
多 Agent 协作框架,多个 Agent 对话协作完成复杂任务
CrewAI
角色扮演式多 Agent 框架,适合业务流程自动化
Dspy
声明式 Agent 编程框架,用 Prompt 签名替代硬编码 Prompt
第5章 落地场景
RAG 知识库问答 · Agent 自动化 · 翻译 · 摘要 · 文本处理
1 场景A:AI 问答助手(网页版)
完整可运行的网页版问答界面,复制即用。
AI 问答助手
🤖 AI 问答助手
2 场景B:批量文本处理(Python)
将 Excel/TXT 中的文本批量翻译、改写、分类。
# ========== 文件:batch_processor.py ==========
# 运行:python batch_processor.py
# 用途:批量将中文标题翻译成英文 / 提取摘要 / 分类
# 依赖:pip install openai python-dotenv tqdm
import os
from dotenv import load_dotenv
from openai import OpenAI
from tqdm import tqdm
load_dotenv()
client = OpenAI(api_key=os.environ.get('OPENAI_API_KEY'))
# ========== 示例任务 ==========
titles = [
'Python入门完全指南',
'JavaScript高级技巧分享',
'深度学习中的正则化技术',
'Web开发安全最佳实践',
'机器学习模型评估指标详解',
]
def translate_to_english(text: str) -> str:
"""翻译成英文"""
response = client.chat.completions.create(
model='gpt-4o-mini',
messages=[{
'role': 'user',
'content': f'将以下中文标题翻译成英文,保持简洁:{text}'
}],
temperature=0.3, # 翻译用低温度,保证一致性
max_tokens=50,
)
return response.choices[0].message.content.strip()
def summarize(text: str) -> str:
"""生成一句话摘要"""
response = client.chat.completions.create(
model='gpt-4o-mini',
messages=[{
'role': 'user',
'content': f'为以下文本生成一句话中文摘要(不超过20字):{text}'
}],
temperature=0.3,
max_tokens=30,
)
return response.choices[0].message.content.strip()
# ========== 批量执行 ==========
if __name__ == '__main__':
print('=== 批量翻译 ===')
for title in tqdm(titles, desc='翻译中'):
en_title = translate_to_english(title)
print(f'{title} → {en_title}')
print('\n=== 批量摘要 ===')
for title in tqdm(titles, desc='摘要中'):
summary = summarize(title)
print(f'{title} → {summary}')
3 场景C:Node.js 写一个 Slack/钉钉 Bot
// ========== 文件:slack_bot.mjs ==========
// 运行:node slack_bot.mjs
// 依赖:npm install @slack/bolt openai
// 需配置 SLACK_BOT_TOKEN, SLACK_APP_TOKEN, OPENAI_API_KEY 环境变量
import { App } from '@slack/bolt';
import OpenAI from 'openai';
const app = new App({
token: process.env.SLACK_BOT_TOKEN,
signingSecret: process.env.SLACK_APP_SIGNING_SECRET,
});
const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
// 监听 DM 消息
app.message(/.*/, async ({ message, say }) => {
if (message.subtype === 'bot_message') return; // 忽略机器人消息
const userMessage = message.text;
console.log(`收到消息 from ${message.user}: ${userMessage}`);
// 调用 OpenAI
const response = await openai.chat.completions.create({
model: 'gpt-4o-mini',
messages: [{ role: 'user', content: userMessage }],
max_tokens: 500,
});
const reply = response.choices[0].message.content;
await say(reply); // 回复用户
});
(async () => {
await app.start({ port: 3000 });
console.log('🤖 Slack Bot 运行在 http://localhost:3000');
})();
4 场景D:RAG 知识库问答系统
完整可运行的 RAG 问答系统,基于私有文档进行问答,支持引文来源。
项目结构
rag_qa/
├── knowledge.txt # 你的知识库文档(txt/md/pdf)
├── build_index.py # 构建向量索引
├── app.py # 启动 RAG 服务
└── requirements.txt
# ========== 文件:requirements.txt ==========
# langchain==0.1.0
# langchain-community==0.0.10
# chromadb==0.4.22
# openai==1.10.0
# python-dotenv==1.0.0
# uvicorn==0.27.0
# ========== 文件:build_index.py(构建索引,一次性)==========
from langchain_community.document_loaders import TextLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.vectorstores import Chroma
from langchain_openai import OpenAIEmbeddings
loader = TextLoader("knowledge.txt", encoding="utf-8")
docs = loader.load()
splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50)
chunks = splitter.split_documents(docs)
vectorstore = Chroma.from_documents(
chunks, OpenAIEmbeddings(model="text-embedding-3-small"), persist_directory="./chroma_db"
)
vectorstore.persist()
print(f"✅ 索引构建完成,共 {len(chunks)} 个块")
# ========== 文件:app.py(FastAPI 服务)==========
from fastapi import FastAPI
from pydantic import BaseModel
from langchain_openai import ChatOpenAI
from langchain.chains import RetrievalQA
from langchain_community.vectorstores import Chroma
from langchain_openai import OpenAIEmbeddings
app = FastAPI(title="RAG 知识库问答 API")
embedding = OpenAIEmbeddings(model="text-embedding-3-small")
vectorstore = Chroma(persist_directory="./chroma_db", embedding_function=embedding)
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
qa_chain = RetrievalQA.from_chain_type(llm=llm, retriever=vectorstore.as_retriever(search_kwargs={"k": 3}))
class Question(BaseModel):
query: str
@app.post("/ask")
def ask(question: Question):
result = qa_chain.invoke({"query": question.query})
return {"answer": result["result"], "sources": [doc.page_content[:100] for doc in result.get("source_documents", [])]}
# 运行:uvicorn app:app --reload --port 8000
# 测试:curl -X POST http://localhost:8000/ask -H "Content-Type: application/json" -d '{"query": "这份文档讲了什么?"}'
5 场景E:多步自动化 Agent
让 AI 自主规划并执行多步任务,每步调用不同工具。
Agent 工作流示例
用户:帮我分析这家公司有没有投资价值
Step 1 → 搜索公司财务数据
Step 2 → 搜索行业竞争对手
Step 3 → 对比关键指标
Step 4 → 生成投资分析报告
# ========== 文件:simple_agent.py ==========
# 运行:python simple_agent.py
# 依赖:pip install langchain langchain-openai duckduckgo-search
from langchain_agents import Agent
from langchain.tools import Tool
from langchain_community.utilities import DuckDuckGoSearchAPIWrapper
from langchain_openai import ChatOpenAI
from langchain.agents import initialize_agent, AgentType
# ========== 定义工具 ==========
search = DuckDuckGoSearchAPIWrapper()
def search_tool(query: str) -> str:
"""搜索工具"""
return search.run(query)
tools = [
Tool(name="搜索", func=search_tool, description="当需要查找实时信息时使用")
]
# ========== 初始化 Agent ==========
llm = ChatOpenAI(model="gpt-4o", temperature=0)
agent = initialize_agent(
tools=tools,
llm=llm,
agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, # ReAct 模式
verbose=True
)
# ========== 运行 ==========
task = "搜索苹果公司最新财报,分析其营收结构和增长趋势"
result = agent.run(task)
print(result)
第6章 问题兜底
高频报错解析 · 调试技巧 · 自检清单
1 高频报错合集
401 Authentication Error / 401 Invalid API Key
原因:API Key 错误、过期、未填、环境变量未生效。
排查:echo $OPENAI_API_KEY 确认有值;检查 Key 是否被撤销,去平台重新生成。
403 Forbidden / Rate Limit Error
原因:请求频率超限(免费账号通常 3 RPM),或账号欠费。
排查:降低请求频率,加 time.sleep(1);去平台检查账单。
429 Too Many Requests
原因:触发了平台并发限制。
解决:加请求间隔,或换用支持更高并发的模型/账号。
CORS Error / 跨域报错
原因:浏览器直接调用 API,大多数大模型 API 不支持浏览器跨域。
解决:前端 -> 后端代理 -> 大模型(见第0章的 CORS 代理方案)。
Connection Error / Timeout
原因:网络不通(国内访问 OpenAI 需要代理),或请求超时。
解决:配置代理 export HTTPS_PROXY=http://127.0.0.1:7890;requests 加 timeout=60。
400 Bad Request: Invalid URL parameter
原因:模型名称拼错,或参数值超出范围(如 temperature > 2)。
排查:核对 model 名称;检查 payload 参数。
Model XXX does not exist
原因:模型名称不对,或该模型对当前 API Key 不可用。
排查:去平台控制台确认可用的模型列表。
2 调试技巧
技巧1:用 curl 先测通
# 先用 curl 测试 API 是否可达,确认 key 和网络没问题
curl https://api.openai.com/v1/models \
-H "Authorization: Bearer $OPENAI_API_KEY"
# 测试 ChatGPT
curl https://api.openai.com/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-d '{"model":"gpt-4o-mini","messages":[{"role":"user","content":"hi"}],"max_tokens":10}'
# 如果网络不通(国内),加上代理
curl --proxy http://127.0.0.1:7890 https://api.openai.com/v1/models \
-H "Authorization: Bearer $OPENAI_API_KEY"
技巧2:打印完整请求/响应
import requests
import json
# 调试模式:打印请求和响应
response = requests.post(url, headers=headers, json=payload, timeout=30)
print('状态码:', response.status_code)
print('响应头:', dict(response.headers))
print('响应体:', response.text) # 打印原始JSON
# 用 postman/insomnia 先手动测接口
# 或用 curl:curl -v(显示完整请求/响应头)
技巧3:检查环境变量是否生效
# Python
python -c "import os; print('OPENAI_API_KEY:', os.environ.get('OPENAI_API_KEY', '未设置'))"
# Node.js
node -e "console.log('OPENAI_API_KEY:', process.env.OPENAI_API_KEY || '未设置')"
3 自检清单
□ API Key 已正确设置(echo $XXX 检查)
□ Key 有余额 / 未过期 / 未被撤销
□ 模型名称拼写正确
□ 网络可达(curl 测试)
□ 国内访问 OpenAI 已配置代理
□ 请求格式正确(JSON / Authorization header)
□ max_tokens 足够大(太小会截断回复)
□ requests timeout 设置(防止卡死)
□ .env 文件未被提交到 GitHub
□ 跨域问题已用后端代理解决
第7章 拓展方向
开源模型生态 · 多模态 · AI Safety · 前沿趋势
1 当前主流开源模型生态
2026年4月,开源模型能力大幅提升,以下是各梯队代表模型。
| 模型 | 参数量 | 特点 | 适合场景 |
|---|---|---|---|
| DeepSeek-V4 | MoE~236B | 最新旗舰,推理大幅提升,API价格低 | 最强开源推理 / Agent |
| Llama 4 405B | 405B | Meta最新旗舰,超越GPT-4水平 | 最强开源通用 |
| Qwen3 72B | 72B | 中文最强,开源生态最完善 | 中文场景 / 部署 |
| Mistral Large 3 | ~70B | 欧洲最强,多语言优秀 | 多语言 / 翻译 |
| Qwen3 32B | 32B | 性价比最高,单卡可跑 | 本地部署 |
| Llama 4 8B | 8B | 轻量级,CPU 可跑 | 边缘设备 / 快速原型 |
| Qwen3 7B | 7B | 入门级,Mac 可跑 int4 | 学习 / 原型 |
模型选择决策树
需要最强推理能力?
→ DeepSeek-V4 / Llama 4 405B / GPT-4.5(需要 API)
中文场景 + 本地部署?
→ Qwen3 72B > Qwen3 32B > Qwen3 7B
预算有限,需要高性价比?
→ DeepSeek-V4 / Qwen3 32B(单卡 80G 可跑 fp16)
快速原型 / 学习?
→ Qwen3 7B 或 Ollama 一键跑
追求多语言 / 欧洲市场?
→ Mistral Large 3
2 多模态模型(图生文 / 文生图 / 视频)
视觉理解
GPT-4o / Claude 3.5 / Gemini 1.5 Pro
图片问答、图表理解、OCR
文生图
Stable Diffusion 3 / DALL-E 3 / Midjourney v6
AI 绘画、设计素材生成
视频生成
Sora / Runway Gen-3 / 可灵
AI 视频创作
语音 / 音乐
GPT-4o Voice / MusicGen / Suno
语音对话 / AI 音乐生成
入门路径推荐
视觉:pip install openai → vision分析图片 | 图生文:pip install transformers + torch + diffusers
3 AI Safety 与模型对齐
随着模型能力增强,Safety 问题越来越重要。
RLHF / DPO 对齐训练
让模型输出更符合人类偏好,减少有害内容
Prompt Injection 攻击
恶意指令注入Prompt绕过安全限制 → 注意输入校验
模型越狱(Jailbreak)
通过特殊提示词绕过安全限制,了解即可,不要实践
内容过滤 / Safety Models
OpenAI Moderation API / NVIDIA NeMo Guardrails
4 前沿趋势与学习路径
长上下文窗口
Gemini 1.5: 10M tokens上下文,RAG需求降低
测试时推理(Test-Time Compute)
o1/o3 模型:推理时用更多算力换更准答案
MCP(Model Context Protocol)
Anthropic提出的Agent工具调用标准协议
混合专家(MoE)架构
GPT-4 / Mixtral:稀疏激活,参数量大但推理快
推荐学习路径
1. 掌握 LLM API 调用(本书第2-3章)
2. 深入 Prompt 工程 + RAG + Function Calling(第4章)
3. 落地项目实战(第5章)
4. 学习微调原理 + 私有化部署(第8-9章)
5. 跟进前沿:关注 arXiv / HuggingFace / vLLM 博客
第8章 模型微调
LoRA · QLoRA · PEFT · 训练流程 · 推理优化
1 为什么需要微调?
预训练大模型能力很强,但不一定符合你的业务场景。微调就是在已有大模型基础上,用特定数据训练,让模型适配你的任务。
通用大模型
训练数据广泛,但专精不足
如:GPT-4、Qwen2.5
微调后模型
特定任务能力大幅提升
如:医疗问答、法律咨询、代码审查
什么时候选微调,而不是 RAG?
✓ 需要模型"记住"某种模式/风格(而非查找文档)
✓ 需要模型输出格式稳定、符合特定规范
✓ 推理延迟要求高,不接受每次都检索
✓ 标注数据充足(通常 1000+ 条)
2 LoRA 原理(Low-Rank Adaptation)
全参数微调需要更新数十亿参数,成本极高。LoRA 的核心思想是:冻结原模型参数,只训练少量附加的低秩矩阵。
全参数微调(每层都更新):
W ∈ R^(d×k) 原始权重(冻结,不更新)
W' = W + ΔW 全部参数都要更新
LoRA(只更新低秩矩阵):
W ∈ R^(d×k) 原始权重(冻结,不更新)
ΔW = B·A,其中 B∈R^(d×r), A∈R^(r×k),r << min(d,k)
W' = W + B·A 只训练 B 和 A 两个小矩阵
参数减少比例:2dr / (2dr + dk) ≈ 2r/d
例如 d=4096, r=8 → 参数减少到原来的 0.4%
秩(r)的选择:
r=4~16:轻量微调,适合风格迁移
r=32~64:标准微调,适合任务适应
r=128~256:深度微调,适合复杂任务
为什么低秩有效?
预训练模型已经学到了丰富的知识,参数更新方向主要集中在低秩子空间。用低秩矩阵捕捉任务特定的"方向",足够了。
核心洞察(来自 LoRA 论文):
预训练大模型的finetune过程中,
权重更新矩阵 ΔW 的秩很低(low intrinsic rank)
→ 只需要少量参数就能表达有效更新
3 QLoRA 原理(量化 + LoRA)
QLoRA = 4-bit 量化 + LoRA。把大模型参数量化压缩,同时保持微调效果。
QLoRA 的核心组件:
1. NF4(4-bit NormalFloat)量化
- 针对神经网络权重分布优化
- 比标准 4-bit 整数量化质量更高
2. 双重量化(Double Quant)
- 对量化常数也做量化,进一步压缩
3. 分页优化器(Paged Optimizers)
- 处理 GPU 显存峰值,避免 OOM
典型配置:4-bit 基础模型 + LoRA(r=64)
7B 模型微调显存:24GB → ~6GB(减少 75%)
显存估算公式
推理显存 ≈ 模型参数量(GB) × 2(fp16)或 × 0.5(int8)或 × 0.25(int4)
训练显存 ≈ 推理显存 + 4 × batch_size × seq_length² × layers
LoRA 训练额外显存 ≈ r × (d + k) × 2 bytes(fp16)
4 LoRA 微调实战代码
# ========== 文件:lora_finetune.py ==========
# 运行:python lora_finetune.py
# 依赖:pip install torch transformers peft datasets trl python-dotenv accelerate
import os
import torch
from datasets import load_dataset
from transformers import (
AutoModelForCausalLM,
AutoTokenizer,
TrainingArguments,
DataCollatorForSeq2Seq,
)
from peft import LoraConfig, get_peft_model, TaskType
from trl import SFTTrainer
# ========== 配置 ==========
MODEL_NAME = "Qwen/Qwen2.5-0.5B-Instruct" # 7B 需要更多显存,0.5B 可在单卡跑
OUTPUT_DIR = "./lora_output"
# ========== 加载模型 ==========
model = AutoModelForCausalLM.from_pretrained(
MODEL_NAME,
torch_dtype=torch.bfloat16,
device_map="auto",
)
model.print_trainable_parameters()
# 预期输出:trainable params: XXXX || all params: XXXX || trainable%: 0.X%
# ========== 配置 LoRA ==========
lora_config = LoraConfig(
r=16, # 秩,越大越强但越慢
lora_alpha=32, # LoRA 缩放因子
target_modules=[ # 应用到哪些层
"q_proj", "k_proj", "v_proj", "o_proj",
"gate_proj", "up_proj", "down_proj",
],
lora_dropout=0.05,
bias="none",
task_type=TaskType.CAUSAL_LM,
)
model = get_peft_model(model, lora_config)
model.print_trainable_parameters()
# ========== 准备数据 ==========
# 格式:{"instruction": "...", "input": "...", "output": "..."}
def format_example(example):
prompt = f"指令:{example['instruction']}\n"
if example.get('input'):
prompt += f"输入:{example['input']}\n"
return {"text": prompt + f"回答:{example['output']}"}
dataset = load_dataset("json", data_files="train.jsonl", split="train")
dataset = dataset.map(format_example)
# ========== 训练 ==========
training_args = TrainingArguments(
output_dir=OUTPUT_DIR,
num_train_epochs=3,
per_device_train_batch_size=4,
gradient_accumulation_steps=4,
learning_rate=1e-4,
warmup_ratio=0.1,
lr_scheduler_type="cosine",
bf16=True,
logging_steps=10,
save_steps=500,
report_to="tensorboard",
)
trainer = SFTTrainer(
model=model,
args=training_args,
train_dataset=dataset,
data_collator=DataCollatorForSeq2Seq(tokenizer=tokenizer, model=model),
)
trainer.train()
# ========== 推理:合并 LoRA 到原模型 ==========
from peft import PeftModel
base_model = AutoModelForCausalLM.from_pretrained(MODEL_NAME, torch_dtype=torch.bfloat16)
merged_model = PeftModel.from_pretrained(base_model, OUTPUT_DIR).merge_and_unload()
merged_model.save_pretrained("./merged_model")
print("✅ 微调完成,模型已保存到 ./merged_model")
第9章 工业级部署
vLLM · Ollama · TensorRT-LLM · 性能调优 · 监控排错
1 vLLM 部署(高吞吐量推理引擎)
vLLM 是目前最流行的 LLM 推理框架,使用 PagedAttention 技术,吞吐量比 HuggingFace 高 10-24 倍。
核心优势
PagedAttention:显存管理优化
Continuous Batching:动态批处理
Tensor Parallelism:多卡并行
FlashAttention:高效注意力计算
# ========== 安装 vLLM ==========
pip install vllm
# ========== 启动 vLLM 服务 ==========
# 单卡
python -m vllm.entrypoints.openai.api_server \
--model Qwen/Qwen2.5-7B-Instruct \
--port 8000 \
--dtype half \
--gpu-memory-utilization 0.9
# 多卡(Tensor Parallelism)
python -m vllm.entrypoints.openai.api_server \
--model Qwen/Qwen2.5-7B-Instruct \
--port 8000 \
--tensor-parallel-size 2 \
--dtype half
# ========== API 调用(与 OpenAI 兼容)==========
curl http://localhost:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "Qwen/Qwen2.5-7B-Instruct",
"messages": [{"role": "user", "content": "用一句话介绍Python"}],
"max_tokens": 200,
"temperature": 0.7
}'
性能对比
Qwen2.5-7B on A100 80G:
HuggingFace transformers:~30 tokens/s
vLLM(PagedAttention):~300+ tokens/s(10x 提升)
2 Ollama 部署(最简单的本地运行)
# ========== 安装 Ollama ==========
# Linux
curl -fsSL https://ollama.com/install.sh | sh
# ========== 拉取并运行模型 ==========
ollama pull qwen2.5:7b # 下载模型(需要 4GB+ 磁盘)
ollama run qwen2.5:7b # 交互式对话
# ========== API 服务(REST API)==========
# Ollama 自动在 11434 端口提供 REST API
curl http://localhost:11434/api/chat -d '{
"model": "qwen2.5:7b",
"messages": [{"role": "user", "content": "用一句话介绍Python"}],
"stream": false
}'
# ========== Python 调用 ==========
# pip install ollama
import ollama
response = ollama.chat(
model='qwen2.5:7b',
messages=[{"role": "user", "content": "用一句话介绍Python"}]
)
print(response['message']['content'])
# ========== 模型管理 ==========
ollama list # 查看已下载模型
ollama rm qwen2.5:7b # 删除模型
ollama show qwen2.5:7b # 查看模型信息
3 性能优化技巧
显存优化
• --gpu-memory-utilization 0.9(vLLM,默认90%显存)
• 启用 KV Cache 量化(int8/int4)减少显存占用
• batch_size 不是越大越好,要平衡延迟和吞吐
• 启用 FlashAttention-2(减少显存+加速)
延迟优化
• 预填充(Prefill)阶段:首次token生成,慢
• 解码(Decode)阶段:后续token生成,快
• Prompt 越短越好,只传递必要信息
• 启用 speculative decoding(猜测解码)加速
• 使用更小的模型处理简单任务
吞吐量优化
• Continuous Batching(连续批处理):核心
• Tensor Parallelism:多卡分片
• 适当增加 max_num_seqs(vLLM 参数)
• 使用更长的预填充+解码比例平衡
vLLM 关键参数调优
| 参数 | 默认值 | 调大 | 说明 |
|---|---|---|---|
| gpu-memory-utilization | 0.9 | - | 显存利用率 |
| max-num-seqs | 32 | 吞吐↑ | 最大并发数 |
| max-num-batched-tokens | 8192 | 吞吐↑ | 单批最大token |
| tensor-parallel-size | 1 | 显存↓ | 多卡数 |
4 监控与排错
CUDA Out of Memory (OOM)
原因:模型太大 + batch_size 过大 + 上下文太长。
解决:减小 batch_size、开启量化、使用更小模型、减少 max_tokens。
模型加载慢 / 显存占用高
解决:用 vLLM 替代 HuggingFace;加 --dtype half;加 --gpu-memory-utilization 0.9。
监控指标
• Throughput:tokens/s,平均每秒处理多少 token
• TTFT:Time To First Token,首 token 延迟
• TPOT:Time Per Output Token,平均每 token 生成时间
• GPU 利用率:nvidia-smi,确认 GPU 在干活
• KV Cache 命中率:vLLM 提供的指标
# 查看 GPU 利用率和显存
watch -n 1 nvidia-smi
# vLLM 日志查看
# 启动时加 -vv 会输出详细日志
python -m vllm.entrypoints.openai.api_server \
--model Qwen/Qwen2.5-7B-Instruct \
-vv 2>&1 | tee vllm.log
生产环境推荐架构
负载均衡层(Nginx / HAProxy)
↓
多个 vLLM 实例(不同 GPU 卡)
↓
Redis(会话管理、限流)