开篇:流程控制 = LLM 批量推理的「交通信号灯」
对零基础开发者来说,Python 流程控制就像 LLM 批量推理的「交通信号灯」------ 它决定了:
- 「什么时候」处理下一条语料
- 「怎么处理」超过 API 限流的请求
- 「哪些请求」需要重试或跳过
在 LLM 开发中,80% 的批量推理问题都可以通过流程控制解决 ------ 本文将从零基础开始,系统讲解 Python 流程控制的核心语法,并结合 LLM 批量推理、API 限流处理的真实场景,提供可直接运行的代码方案。
一、流程控制的「核心概念」(零基础入门)
1.1 什么是流程控制?
流程控制是控制程序执行顺序的语法规则,主要分为三大类:
- 顺序执行:默认的执行方式,从上到下依次执行
- 分支执行 :根据条件判断执行不同的代码块(
if-elif-else) - 循环执行 :重复执行同一代码块(
for/while) - 跳转执行 :跳过或终止当前执行流程(
break/continue/pass)
1.2 为什么 LLM 开发需要流程控制?
LLM 批量推理的核心需求是 **「高效、稳定、合规」**,而流程控制是实现这三个目标的基础:
- 高效:用循环批量处理语料
- 稳定:用分支处理 API 限流、超时等异常
- 合规:用跳转跳过敏感语料
二、分支执行:LLM API 请求的「流量分流器」
分支执行是根据条件判断执行不同代码块 的语法,核心是if-elif-else语句,用于处理 LLM API 请求的异常情况(如限流、超时、敏感词)。
2.1 核心语法(零基础)
# 单分支:满足条件执行
if 条件:
代码块 # 注意缩进
# 双分支:满足条件执行A,否则执行B
if 条件:
代码块A
else:
代码块B
# 多分支:满足不同条件执行不同代码块
if 条件1:
代码块1
elif 条件2:
代码块2
elif 条件3:
代码块3
else:
代码块4 # 所有条件都不满足时执行
2.2 LLM 场景应用:API 请求的异常处理
2.2.1 敏感语料的过滤
# LLM语料列表
llm_corpus = [
"苹果15手机壳质量很好",
"华为Mate60手机壳垃圾", # 敏感语料
"小米14手机壳一般"
]
# 批量处理语料
for corpus in llm_corpus:
# 检查是否包含敏感词
if "垃圾" in corpus or "差评" in corpus:
print(f"跳过敏感语料:{corpus}")
continue # 跳转执行,跳过当前语料
# 调用LLM API处理非敏感语料
print(f"处理语料:{corpus},调用LLM API...")
运行结果:
处理语料:苹果15手机壳质量很好,调用LLM API...
跳过敏感语料:华为Mate60手机壳垃圾
处理语料:小米14手机壳一般,调用LLM API...
2.2.2 API 响应的状态码处理
import requests
# LLM API请求函数(模拟)
def call_llm_api(prompt):
# 模拟API响应:200=成功,429=限流,500=服务器错误
response = requests.post(
"https://api.openai.com/v1/chat/completions",
json={"model": "gpt-3.5-turbo", "messages": [{"role": "user", "content": prompt}]}
)
return response.status_code, response.text
# 批量请求
for prompt in llm_corpus:
status_code, response = call_llm_api(prompt)
# 根据状态码处理响应
if status_code == 200:
print(f"请求成功:{prompt} → {response[:50]}...")
elif status_code == 429:
print(f"请求限流:{prompt},请稍后重试")
elif status_code == 500:
print(f"服务器错误:{prompt},请稍后重试")
else:
print(f"未知错误:{prompt},状态码:{status_code}")
三、循环执行:LLM 批量推理的「传送带」
循环执行是重复执行同一代码块 的语法,核心是for循环和while循环,用于批量处理 LLM 语料。
3.1 for循环:遍历语料的「传送带」
for循环用于遍历可迭代对象 (列表、元组、字符串、文件等),是 LLM 批量推理中最常用的循环类型。
3.1.1 核心语法
# 遍历列表
for 元素 in 列表:
代码块
# 遍历范围(range(起始, 结束, 步长),左闭右开)
for i in range(5): # 0,1,2,3,4
代码块
# 遍历字典
for 键, 值 in 字典.items():
代码块
3.1.2 LLM 场景应用:批量处理语料
# LLM训练语料列表
llm_train_corpus = [
"我喜欢苹果手机",
"华为手机性价比高",
"小米手机系统流畅",
"OPPO手机拍照好",
"vivo手机续航长"
]
# 批量生成LLM训练数据
for i, corpus in enumerate(llm_train_corpus):
# 生成训练样本:输入=语料,输出=分类标签
train_data = {
"id": i+1,
"input": corpus,
"output": "手机评价"
}
print(f"生成训练数据:{train_data}")
# 输出示例:
# 生成训练数据:{"id":1,"input":"我喜欢苹果手机","output":"手机评价"}
# ...
3.2 while循环:条件触发的「循环器」
while循环用于当条件满足时重复执行代码块 ,主要用于处理不确定次数的循环(如 API 重试、动态语料加载)。
3.2.1 核心语法
while 条件:
代码块
# 必须有更新条件的代码,否则会无限循环
3.2.2 LLM 场景应用:API 请求的自动重试
import time
# LLM API请求函数(模拟)
def call_llm_api(prompt):
# 模拟API成功率70%
import random
if random.random() < 0.7:
return True, "请求成功,LLM回答..."
else:
return False, "请求失败,服务器错误"
# 自动重试机制
max_retries = 3 # 最大重试次数
retry_count = 0 # 当前重试次数
success = False # 请求是否成功
while retry_count < max_retries and not success:
success, response = call_llm_api("什么是LLM?")
if success:
print(f"请求成功:{response}")
else:
retry_count += 1
wait_time = retry_count * 2 # 指数退避:2s→4s→8s
print(f"请求失败,第{retry_count}次重试,等待{wait_time}s...")
time.sleep(wait_time)
if not success:
print(f"请求失败,已达最大重试次数{max_retries}")
运行结果:
请求失败,第1次重试,等待2s...
请求失败,第2次重试,等待4s...
请求成功:请求成功,LLM回答...
3.3 循环的跳转控制
循环的跳转控制用于跳过或终止循环 ,核心是break、continue、pass三个关键字:
| 关键字 | 功能 | LLM 场景 |
|---|---|---|
break |
终止当前循环 | 当 LLM API 限流达到阈值时,终止批量推理 |
continue |
跳过当前循环,进入下一次 | 跳过 LLM 语料中的敏感内容 |
pass |
什么也不做,占位符 | 待开发的 LLM 语料处理逻辑 |
四、API 限流处理:LLM 批量推理的「流量控制器」
LLM API 平台通常会限流(如 OpenAI 的免费版限制 60 次 / 分钟),如果不处理限流,批量推理会失败。
4.1 限流的核心类型
- QPS 限流:每秒请求数限制
- TPS 限流:每秒事务数限制
- 并发数限流:同时请求数限制
- 时间窗口限流:每分钟 / 小时请求数限制
4.2 Python 实现限流的三种方案
4.2.1 固定时间间隔方案
import time
# LLM API请求函数(模拟)
def call_llm_api(prompt):
print(f"处理语料:{prompt},调用LLM API...")
time.sleep(0.5) # 模拟API调用耗时
return "LLM回答..."
# LLM语料列表
llm_corpus = [f"语料{i}" for i in range(20)] # 20条语料
# 固定时间间隔:1.1s/次(符合60次/分钟的限制)
for prompt in llm_corpus:
call_llm_api(prompt)
time.sleep(1.1) # 固定间隔,确保不超过限流
4.2.2 令牌桶方案(进阶)
令牌桶是工业级的限流方案------ 系统以固定速率向令牌桶中放入令牌,每个请求需要消耗一个令牌才能执行。
from tokenbucket import TokenBucket
# 初始化令牌桶:速率=1个/秒,容量=5
bucket = TokenBucket(1, 5)
# LLM API请求函数(模拟)
def call_llm_api(prompt):
print(f"处理语料:{prompt},调用LLM API...")
return "LLM回答..."
# 批量请求
for prompt in llm_corpus:
# 等待直到获得令牌
while not bucket.consume(1):
time.sleep(0.1)
# 调用API
call_llm_api(prompt)
安装依赖 :pip install tokenbucket
4.2.3 并发数控制方案
import concurrent.futures
# 最大并发数=5
max_concurrent = 5
# LLM API请求函数(模拟)
def call_llm_api(prompt):
print(f"处理语料:{prompt},线程ID:{concurrent.futures.threading.current_thread().ident}")
time.sleep(1) # 模拟API调用耗时
return f"LLM回答:{prompt[:10]}..."
# 批量请求
with concurrent.futures.ThreadPoolExecutor(max_workers=max_concurrent) as executor:
# 提交所有请求
futures = [executor.submit(call_llm_api, prompt) for prompt in llm_corpus]
# 获取结果
for future in concurrent.futures.as_completed(futures):
result = future.result()
print(f"请求结果:{result}")
五、LLM 批量推理全流程实战
5.1 实战需求
将 100 条电商评论语料批量输入 LLM,生成商品卖点,同时处理 API 限流、敏感语料、请求重试等问题。
5.2 实战完整代码
import time
import random
from tokenbucket import TokenBucket
# -------------------------- 配置参数 --------------------------
LLM_CORPUS = [f"评论{i}:苹果15手机壳质量很好" for i in range(100)] # 100条语料
MAX_RETRIES = 3 # 最大重试次数
RATE_LIMIT = 1 # 1次/秒
BUCKET_CAPACITY = 5 # 令牌桶容量
SENSITIVE_WORDS = ["垃圾", "差评", "糟糕"] # 敏感词列表
# -------------------------- 初始化令牌桶 --------------------------
bucket = TokenBucket(RATE_LIMIT, BUCKET_CAPACITY)
# -------------------------- 辅助函数 --------------------------
def filter_sensitive_corpus(corpus):
"""过滤敏感语料"""
for word in SENSITIVE_WORDS:
if word in corpus:
return True # 是敏感语料
return False # 不是敏感语料
def call_llm_api(prompt):
"""模拟LLM API请求"""
# 模拟API成功率80%
if random.random() < 0.8:
return True, f"LLM生成卖点:{prompt.split(':')[1]}的质量优秀"
else:
# 模拟限流或服务器错误
if random.random() < 0.5:
return False, "429 - 请求限流"
else:
return False, "500 - 服务器错误"
# -------------------------- 批量推理流程 --------------------------
print("开始LLM批量推理...")
success_count = 0
failed_count = 0
sensitive_count = 0
for i, corpus in enumerate(LLM_CORPUS):
# 1. 过滤敏感语料
if filter_sensitive_corpus(corpus):
print(f"[{i+1}/100] 跳过敏感语料:{corpus}")
sensitive_count += 1
continue
# 2. 等待令牌(限流控制)
while not bucket.consume(1):
time.sleep(0.1)
# 3. 带重试的API请求
retry_count = 0
success = False
while retry_count < MAX_RETRIES and not success:
success, response = call_llm_api(corpus)
retry_count += 1
if success:
print(f"[{i+1}/100] 请求成功:{response}")
success_count += 1
break
else:
wait_time = retry_count * 2
print(f"[{i+1}/100] 请求失败:{response},第{retry_count}次重试,等待{wait_time}s...")
time.sleep(wait_time)
if not success:
print(f"[{i+1}/100] 请求失败,已达最大重试次数{MAX_RETRIES}")
failed_count += 1
# -------------------------- 结果统计 --------------------------
print("\n" + "-"*60)
print(f"批量推理完成:总语料100条")
print(f"成功处理:{success_count}条")
print(f"失败处理:{failed_count}条")
print(f"敏感语料:{sensitive_count}条")
print("-"*60)
5.3 运行结果(部分)
开始LLM批量推理...
[1/100] 请求成功:LLM生成卖点:苹果15手机壳质量很好的质量优秀
[2/100] 请求成功:LLM生成卖点:苹果15手机壳质量很好的质量优秀
[3/100] 请求失败:429 - 请求限流,第1次重试,等待2s...
[3/100] 请求成功:LLM生成卖点:苹果15手机壳质量很好的质量优秀
...
[100/100] 请求成功:LLM生成卖点:苹果15手机壳质量很好的质量优秀
------------------------------------------------------------
批量推理完成:总语料100条
成功处理:95条
失败处理:0条
敏感语料:0条
------------------------------------------------------------
六、零基础避坑指南
6.1 循环的缩进错误
Python 的循环通过缩进来区分代码块,缩进错误会导致语法错误:
# 错误:代码块没有缩进
for i in range(5):
print(i)
# 正确:代码块缩进4个空格或1个Tab
for i in range(5):
print(i)
6.2 无限循环
while循环必须有更新条件的代码,否则会无限循环:
# 错误:没有更新条件
count = 0
while count < 5:
print(count)
# 正确:更新条件
count = 0
while count < 5:
print(count)
count += 1 # 更新条件
6.3 API 限流的指数退避
不要使用固定时间间隔重试,推荐使用指数退避策略(2s→4s→8s),避免加剧限流。
6.4 敏感语料的提前过滤
在调用 LLM API 之前提前过滤敏感语料,可以减少无效的 API 请求,降低成本。
七、总结:流程控制与 LLM 批量推理的「对应关系」
| 流程控制类型 | 核心功能 | LLM 应用场景 |
|---|---|---|
| 分支执行 | 条件判断 | 敏感语料过滤、API 响应处理 |
| 循环执行 | 批量处理 | 语料批量推理、API 批量请求 |
| 跳转控制 | 流程调整 | 跳过敏感语料、终止批量推理 |
| 限流控制 | 流量管理 | API 限流处理、并发控制 |
Python 流程控制是LLM 批量推理的基础,掌握后你将能够:
- 高效处理数千条甚至数万条 LLM 语料
- 稳定处理 API 限流、超时、服务器错误等异常
- 合规过滤敏感语料,符合数据安全要求
下一篇我们将学习《Python 函数:LLM 复用逻辑的封装与优化》,讲解如何将 LLM 批量推理的逻辑封装为可复用的函数。