本文為 AI 描述優化 api 設計 系列文,第 7 篇:
- 如何設計一個商品描述優化 API?—— 完整指南
- 設計 AI 優化商品描述的 Prompt
- FastAPI:高效且易用的 Python Web 框架
- 介紹 Uvicorn:高效能 ASGI 伺服器
- Uvicorn 監聽 0.0.0.0,但為何 API 只能用 127.0.0.1 訪問?
- Tenacity:強大的 Python 重試機制庫
- FastAPI 建立商品描述優化 API 👈進度
- 介紹 pytest:Python 測試框架的強大選擇
- Python httpx 完整指南:高效的 HTTP 客戶端
- Pytest-Benchmark:高效能測試的基準分析工具
- 深入解析 monkeypatch:Python 測試中的強大工具
- API 自動化測試與效能優化
建議閱讀本文前,先具備 聊天機器人-建議回復 相關系列文的概念。
在現代電商環境中,優質的商品描述能夠提高轉換率,增強搜尋引擎優化(SEO),並提升消費者的購物體驗。
然而,撰寫高品質的商品描述往往需要大量時間與精力。
因此,我們可以運用 AI 來自動優化商品描述,確保內容簡潔、精準,並符合品牌風格。
本篇文章將帶領你使用 FastAPI,搭建一個 AI 驅動的商品描述優化 API,透過 OpenAI GPT-4o 自動優化商品描述,並確保輸出符合 JSON 結構。
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
import openai
import os
from tenacity import retry, stop_after_attempt, wait_fixed
from dotenv import load_dotenv
import json
import logging
load_dotenv()
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
# 初始化 FastAPI
app = FastAPI(title="商品描述優化 API")
# 定義請求 Body
class DescriptionRequest(BaseModel):
description: str
# 讀取 Prompt 文件
def load_prompt():
with open("optimize_description_prompt.txt", "r", encoding="utf-8") as file:
return file.read()
# Retry 機制(API 失敗時最多重試 3 次,每次間隔 2 秒)
@retry(stop=stop_after_attempt(3), wait=wait_fixed(2))
def optimize_description(text: str) -> str:
prompt = load_prompt().replace("{商品描述}", text)
try:
client = openai.OpenAI(api_key=OPENAI_API_KEY)
response = client.chat.completions.create(
model="gpt-4o",
response_format={"type": "json_object"},
messages=[{"role": "system", "content": prompt}],
max_tokens=500
)
logging.info(f"OpenAI API 回應: {response}")
print(f"🔍 OpenAI API 回應: {response}")
if not response.choices or not response.choices[0].message.content:
raise HTTPException(status_code=500, detail="❌ OpenAI API 回應為空")
optimized_text =response.choices[0].message.content.strip() if response.choices else ""
if not optimized_text:
raise HTTPException(status_code=500, detail="❌ OpenAI API 回應為空")
try:
return json.loads(optimized_text)
except json.JSONDecodeError as e:
logging.error(f"❌ JSON 解析錯誤: {e}")
raise HTTPException(status_code=500, detail=f"OpenAI API 回應格式錯誤: {str(e)}")
except Exception as e:
logging.error(f"❌ OpenAI API 失敗: {e}")
raise HTTPException(status_code=500, detail=f"OpenAI API 失敗: {str(e)}")
@app.post("/summarized-description")
async def summarize_description(request: DescriptionRequest):
if not request.description.strip():
raise HTTPException(status_code=400, detail="❌ 商品描述不可為空")
optimized_text = optimize_description(request.description)
return optimized_text
# 啟動方式(開發模式)
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)
環境設定與安裝 FastAPI
在開始之前,請確保你的系統已安裝 Python 3.8 以上版本,並準備好虛擬環境(建議使用 venv)。
接下來,我們需要安裝 FastAPI 及相關依賴:
安裝必要套件
在終端機執行以下指令,安裝 FastAPI 及 OpenAI 相關套件:
pip install fastapi uvicorn openai pydantic tenacity python-dotenvfastapi:FastAPI 框架uvicorn:ASGI 伺服器(用來啟動 FastAPI 應用)openai:與 OpenAI API 互動pydantic:數據驗證與模型處理tenacity:實現 API 重試機制python-dotenv:載入環境變數(儲存 API 金鑰)
初始化 FastAPI 專案
在專案目錄下,建立一個 Python 檔案 optimize_description.py,並加入以下基本架構:
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
import openai
import os
from tenacity import retry, stop_after_attempt, wait_fixed
from dotenv import load_dotenv
import json
import logging
載入環境變數
為了保護 OpenAI API 金鑰,我們將其存放於 .env 檔案:
load_dotenv()
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")並在 .env 檔案中新增:
OPENAI_API_KEY=你的API金鑰定義 FastAPI 服務與請求格式
初始化 FastAPI 應用
app = FastAPI(title="商品描述優化 API")我們將使用 Pydantic 定義請求結構:
class DescriptionRequest(BaseModel):
description: str
這樣 API 就能接收一個 description 參數,並確保它是 str 類型。
建立 OpenAI API 呼叫邏輯
我們需要讀取 prompt 文件,並將用戶輸入的商品描述嵌入到 prompt 中:
def load_prompt():
with open("optimize_description_prompt.txt", "r", encoding="utf-8") as file:
return file.read()
接著,使用 tenacity 增強 API 呼叫的穩定性:
@retry(stop=stop_after_attempt(3), wait=wait_fixed(2))
def optimize_description(text: str) -> str:
prompt = load_prompt().replace("{商品描述}", text)
try:
client = openai.OpenAI(api_key=OPENAI_API_KEY)
response = client.chat.completions.create(
model="gpt-4o",
response_format={"type": "json_object"},
messages=[{"role": "system", "content": prompt}],
max_tokens=500
)
logging.info(f"OpenAI API 回應: {response}")
if not response.choices or not response.choices[0].message.content:
raise HTTPException(status_code=500, detail="❌ OpenAI API 回應為空")
optimized_text = response.choices[0].message.content.strip() if response.choices else ""
if not optimized_text:
raise HTTPException(status_code=500, detail="❌ OpenAI API 回應為空")
try:
return json.loads(optimized_text)
except json.JSONDecodeError as e:
logging.error(f"❌ JSON 解析錯誤: {e}")
raise HTTPException(status_code=500, detail=f"OpenAI API 回應格式錯誤: {str(e)}")
except Exception as e:
logging.error(f"❌ OpenAI API 失敗: {e}")
raise HTTPException(status_code=500, detail=f"OpenAI API 失敗: {str(e)}")
自動重試機制(@retry 裝飾器)
@retry(stop=stop_after_attempt(3), wait=wait_fixed(2))這行使用了 tenacity 套件提供的 @retry 裝飾器,確保 API 請求發生錯誤時:
- 最多重試 3 次(
stop_after_attempt(3)) - 每次重試間隔 2 秒(
wait_fixed(2))
這樣可以增加 API 呼叫的穩定性,避免因網路問題或 OpenAI 服務臨時不可用而導致請求失敗。
讀取 Prompt 並替換商品描述
prompt = load_prompt().replace("{商品描述}", text)這行程式碼:
- 調用
load_prompt()讀取optimize_description_prompt.txt檔案內容 - 使用
.replace("{商品描述}", text),將{商品描述}替換為用戶提供的text
這樣就可以確保發送給 OpenAI 的 prompt 內容是完整的。
呼叫 OpenAI API
client = openai.OpenAI(api_key=OPENAI_API_KEY)
response = client.chat.completions.create(
model="gpt-4o",
response_format={"type": "json_object"},
messages=[{"role": "system", "content": prompt}],
max_tokens=500
)
這段程式碼:
- 初始化 OpenAI 客戶端,使用
OPENAI_API_KEY進行身份驗證。 - 呼叫 OpenAI API 來生成優化後的商品描述:
- 使用的模型是
gpt-4o(最新的 OpenAI 生成模型)。 - 設定回應格式為 JSON(
response_format={"type": "json_object"}),確保回傳的結果是結構化數據。 - 將 Prompt 發送給 OpenAI,作為
messages參數中的system消息。 - 限制最大 Token 數量為 500,避免輸出過長。
- 使用的模型是
檢查 OpenAI API 回應
logging.inf(f"OpenAI API 回應: {response}")這行程式碼將 OpenAI API 的回應記錄在日誌中,方便偵錯。
if not response.choices or not response.choices[0].message.content:
raise HTTPException(status_code=500, detail="❌ OpenAI API 回應為空")這行程式碼:
- 檢查
response.choices是否存在,確保 API 有返回結果。 - 檢查
response.choices[0].message.content是否有內容,確保 AI 確實產生了文字。 - 如果沒有回應內容,就 拋出 HTTP 500 錯誤,通知用戶發生錯誤。
處理 OpenAI 回傳的內容
optimized_text = response.choices[0].message.content.strip() if response.choices else ""這行程式碼:
- 從 API 回應中取得內容。
- 使用
.strip()去除前後空白,確保輸出格式乾淨。 - 如果內容為空,則拋出錯誤:
if not optimized_text:
raise HTTPException(status_code=500, detail="❌ OpenAI API 回應為空")嘗試解析 JSON
try:
return json.loads(optimized_text)
except json.JSONDecodeError as e:
logging.error(f"❌ JSON 解析錯誤: {e}")
raise HTTPException(status_code=500, detail=f"OpenAI API 回應格式錯誤: {str(e)}")
這段程式碼:
- 使用
json.loads()解析 API 回應內容,確保回傳結果是有效的 JSON。 - 如果 JSON 解析失敗(格式錯誤),則記錄錯誤並拋出 HTTP 500 錯誤。
全域錯誤處理
except Exception as e:
logging.error(f"❌ OpenAI API 失敗: {e}")
raise HTTPException(status_code=500, detail=f"OpenAI API 失敗: {str(e)}")
這段程式碼:
- 捕捉所有異常(
Exception),避免未處理的錯誤導致 API 崩潰。 - 記錄錯誤訊息,方便日誌追蹤。
- 返回 HTTP 500 錯誤,告知請求失敗。
定義 FastAPI 端點
接下來,我們建立一個 POST API 端點,接收商品描述並返回優化結果:
@app.post("/summarized-description")
async def summarize_description(request: DescriptionRequest):
if not request.description.strip():
raise HTTPException(status_code=400, detail="❌ 商品描述不可為空")
optimized_text = optimize_description(request.description)
return optimized_text這個 API 端點:
- 檢查請求內容,確保
description不是空白 - 呼叫
optimize_description(),透過 OpenAI 進行優化 - 返回優化結果(JSON 格式)
啟動 API 服務
在終端機執行以下指令,啟動 FastAPI 伺服器:
uvicorn optimize_description:app --host 0.0.0.0 --port 8000 --reload
或者在 Python 代碼中加入:
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)
當服務成功啟動,會顯示類似:
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
你可以透過瀏覽器或 curl 測試:
curl -X 'POST' 'http://127.0.0.1:8000/summarized-description' \
-H 'Content-Type: application/json' \
-d '{"description": "這是一款高品質的無線藍牙耳機,具備降噪功能"}'
API 測試與錯誤處理
我們可以透過 pytest 測試 API 是否正常運行,並確保 JSON 格式正確:
def test_api():
import requests
url = "http://127.0.0.1:8000/summarized-description"
data = {"description": "高效能筆記型電腦,適合遊戲與商務使用"}
response = requests.post(url, json=data)
assert response.status_code == 200
print(response.json())
常見錯誤處理:
- API 金鑰無效 → 確保
.env設定正確 - 輸入內容為空 → 返回
400 Bad Request - OpenAI API 失敗 → 自動重試(最多 3 次)
結論
本篇文章介紹了如何使用 FastAPI 搭建 商品描述優化 API,透過 OpenAI GPT-4o 自動優化內容,並確保 API 穩定運行。