趋近智
构建可靠的大型语言模型(LLM)应用需要谨慎处理输出,因为LLM并不总是能生成完全符合期望结构的内容。即使通过精心的提示词工程和使用输出解析器——这些都是引导LLM响应的常用技术——错误仍然可能出现。网络问题、模型暂时性故障,或者仅仅是生成过程的概率性质,都可能导致响应无法根据您定义的模式(如 JSON 或 Pydantic 模型)正确解析。优雅地处理这些解析错误对于构建可靠的应用非常重要。忽视它们可能导致应用崩溃、数据处理不当或用户体验不佳。
当LLM的输出不符合预期格式时,您的解析代码(无论是 json.loads()、框架的解析器,还是Pydantic模型的验证)很可能会抛出异常。您需要一个应对故障的策略,而不是任由它导致应用崩溃。
了解解析可能失败的原因有助于选择正确的恢复方法:
true。max_tokens)而被截断。当解析尝试失败时,请考虑以下方法:
重试请求(简单重试): 有时,失败是暂时的。简单地重试完全相同的API调用,第二次尝试可能就会得到正确的响应。这通常是第一步也是最简单的步骤。将此与短暂延迟(退避)相结合,以避免API过载,特别是当错误是由于速率限制引起时。这在“实现重试机制”一节中有更详细的讨论,但它在这里也是一种基本方法。
使用纠正性提示重试: 如果简单重试失败,问题可能出在LLM对格式指令的理解或遵循上。您可以修改重试时的提示词。策略包括:
{previous_llm_output} 解析失败,错误为:{error_message}。请再次提供响应,严格遵循请求的JSON格式:{schema description}。”备用机制: 如果重试(无论是否修改提示)持续失败,您需要一个备用方案:
我们来用Python的 try-except 块演示一个基本流程,假设您正在尝试解析 JSON 并可能使用 Pydantic 这样的验证库。
import json
from pydantic import BaseModel, ValidationError
import time
import random
# 假设 'llm_api_call' 是一个函数,接受提示词并返回 LLM 的文本响应
# 假设 'YourDataModel' 是一个定义预期结构的 Pydantic 模型
MAX_RETRIES = 3
INITIAL_BACKOFF = 1 # seconds
def process_llm_request_with_parsing(prompt: str):
"""尝试获取和解析 LLM 输出,包含重试和错误处理。"""
current_prompt = prompt
for attempt in range(MAX_RETRIES):
try:
raw_output = llm_api_call(current_prompt)
# 尝试 1:直接 JSON 解析
try:
parsed_data = json.loads(raw_output)
# 可选:使用 Pydantic 验证
# validated_data = YourDataModel(**parsed_data)
# print("Successfully parsed and validated.")
# return validated_data
print("成功解析 JSON。")
return parsed_data # 如果不需要验证,返回原始解析数据
except json.JSONDecodeError as e:
print(f"尝试 {attempt + 1}:JSON 解析失败:{e}")
error_message = str(e)
failed_output = raw_output # 保留以备纠正性提示
# except ValidationError as e: # 如果使用 Pydantic
# print(f"尝试 {attempt + 1}:Pydantic 验证失败:{e}")
# error_message = str(e)
# failed_output = raw_output
# 如果解析/验证失败,准备重试
if attempt < MAX_RETRIES - 1:
# 策略:使用纠正性提示重试(简化示例)
current_prompt = (
f"{prompt}\n\n"
f"Your previous response failed parsing: `{error_message}`.\n"
f"Previous response snippet: ```{failed_output[:200]}...```\n"
f"请严格以正确的 JSON 格式提供响应。"
)
# 添加带抖动的指数退避
backoff_time = INITIAL_BACKOFF * (2 ** attempt) + random.uniform(0, 1)
print(f"{backoff_time:.2f} 秒后重试...")
time.sleep(backoff_time)
else:
print("达到最大重试次数。解析失败。")
# 在此处实现备用机制
log_error(prompt, failed_output, error_message)
return None # 或者抛出自定义异常,返回默认值等。
except Exception as api_error: # 捕获潜在的 API 调用错误
print(f"第 {attempt + 1} 次尝试时 API 调用失败:{api_error}")
if attempt < MAX_RETRIES - 1:
backoff_time = INITIAL_BACKOFF * (2 ** attempt) + random.uniform(0, 1)
time.sleep(backoff_time)
else:
print("达到最大重试次数后 API 调用失败。")
log_error(prompt, None, str(api_error))
return None
return None # 如果逻辑正确,这里理论上不应被执行
def log_error(prompt, failed_output, error_message):
# 实际日志实现(例如,写入文件,发送到日志服务)的占位符
print(f"记录错误:\n提示词:{prompt}\n失败输出:{failed_output}\n错误:{error_message}")
# 示例用法:
my_prompt = "Extract the name and age from the text 'John Doe is 30 years old' as JSON."
# 从文本 'John Doe is 30 years old' 中提取姓名和年龄,以 JSON 格式。
result = process_llm_request_with_parsing(my_prompt)
if result:
print("最终结果:", result)
else:
print("未能获得有效结果。")
我们可以用图表表示这个决策过程:
流程图说明了处理潜在LLM输出解析错误的过程,包括重试尝试和备用操作。
选择重试、纠正性提示和备用方案的正确组合取决于具体的应用需求、对失败的容忍度以及预期LLM输出的性质。错误处理不是事后才考虑的事情;它是构建可靠LLM驱动应用的核心组成部分。
简洁的语法。内置调试功能。从第一天起就可投入生产。
为 ApX 背后的 AI 系统而构建
这部分内容有帮助吗?
© 2026 ApX Machine Learning用心打造