在開發 AI 應用的過程中,你一定遇過這些狀況:API 突然超時、模型回應格式錯誤、Token 限制爆掉、服務暫時不可用...今天我們要深入探討如何優雅地處理這些錯誤,讓你的 AI 應用更加穩定可靠。
AI 應用與傳統應用最大的差異在於其不確定性:
import openai
from openai import OpenAI
client = OpenAI()
try:
response = [client.chat](http://client.chat).completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "Hello"}]
)
except openai.APIConnectionError as e:
print(f"網路連線失敗:{e.__cause__}")
# 實作重連邏輯
except openai.APITimeoutError as e:
print(f"請求超時:{e}")
# 考慮增加 timeout 或簡化請求
import time
from tenacity import retry, wait_exponential, stop_after_attempt
@retry(
wait=wait_exponential(multiplier=1, min=4, max=60),
stop=stop_after_attempt(5)
)
def call_api_with_retry():
try:
response = [client.chat](http://client.chat).completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "分析這段文字..."}]
)
return response
except openai.RateLimitError as e:
print(f"達到速率限制:{e.status_code}")
# 從 response header 取得 retry-after
retry_after = e.response.headers.get("retry-after")
if retry_after:
time.sleep(int(retry_after))
raise # 重新拋出異常讓 retry 裝飾器處理
import json
from typing import Dict, Any
class OutputParser:
def __init__(self, max_retries=3):
self.max_retries = max_retries
def parse_json_response(self, text: str, llm_client) -> Dict[str, Any]:
"""嘗試解析 JSON,失敗時要求 LLM 修正"""
for attempt in range(self.max_retries):
try:
# 嘗試解析 JSON
return json.loads(text)
except json.JSONDecodeError as e:
if attempt == self.max_retries - 1:
# 最後一次嘗試失敗,返回錯誤
raise ValueError(f"無法解析 JSON: {e}")
# 要求 LLM 修正格式
repair_prompt = f"""
以下 JSON 格式有誤,請修正並只回傳正確的 JSON:
錯誤訊息:{str(e)}
原始內容:{text}
請只回傳修正後的 JSON,不要加任何說明。
"""
response = llm_[client.chat](http://client.chat).completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": repair_prompt}],
temperature=0
)
text = response.choices[0].message.content
print(f"嘗試修復 JSON (第 {attempt + 1} 次)")
return {}
import httpx
from openai import OpenAI
# 細緻的超時控制
client = OpenAI(
timeout=httpx.Timeout(
connect=5.0, # 連線超時
read=30.0, # 讀取超時
write=10.0, # 寫入超時
pool=2.0 # 連線池超時
),
max_retries=3 # 自動重試次數
)
# 針對特定請求調整設定
response = client.with_options(
timeout=60.0, # 長文本處理需要更多時間
max_retries=5
).chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "處理這份長文件..."}]
)
from typing import Optional, List
from dataclasses import dataclass
@dataclass
class ModelConfig:
name: str
max_tokens: int
cost_per_1k: float
class AIServiceWithFallback:
def __init__(self):
# 設定模型優先順序
self.models = [
ModelConfig("gpt-4o", 128000, 0.005),
ModelConfig("gpt-4o-mini", 128000, 0.00015),
ModelConfig("gpt-3.5-turbo", 16385, 0.0005)
]
self.client = OpenAI()
def complete(self, prompt: str, max_retries: int = 2) -> Optional[str]:
"""嘗試使用不同模型完成請求"""
errors = []
for model in self.models:
for attempt in range(max_retries):
try:
response = [self.client.chat](http://self.client.chat).completions.create(
model=[model.name](http://model.name),
messages=[{"role": "user", "content": prompt}],
max_tokens=min(1000, model.max_tokens)
)
print(f"成功使用 {[model.name](http://model.name)}")
return response.choices[0].message.content
except openai.APIStatusError as e:
error_msg = f"{[model.name](http://model.name)} 失敗 (嘗試 {attempt + 1}): {e}"
errors.append(error_msg)
print(error_msg)
# 如果是 token 限制錯誤,直接換模型
if e.status_code == 400 and "token" in str(e).lower():
break
# 其他錯誤等待後重試
if attempt < max_retries - 1:
time.sleep(2 ** attempt) # 指數退避
# 所有嘗試都失敗
raise Exception(f"所有模型都失敗:\n" + "\n".join(errors))
import logging
from datetime import datetime
from typing import Any, Dict
import json
class AIErrorMonitor:
def __init__(self, log_file="ai_errors.log"):
# 設定日誌
logging.basicConfig(
filename=log_file,
level=[logging.INFO](http://logging.INFO),
format='%(asctime)s - %(levelname)s - %(message)s'
)
self.logger = logging.getLogger(__name__)
# 錯誤統計
self.error_stats = {
"total_requests": 0,
"successful_requests": 0,
"errors_by_type": {},
"errors_by_model": {}
}
錯誤處理是 AI 應用成熟度的重要指標。一個優秀的錯誤處理系統不僅能提升使用者體驗,還能節省開發時間和營運成本。記住,錯誤不可避免,但我們可以優雅地處理它們。