
【實戰】Day 19:從 PostgreSQL 開發 REST API:為 Agent 打造 JSON 數據橋樑
延續鞋墊廠訂單專案,這篇文章我們將使用 FastAPI 為 PostgreSQL 建立一層 REST API,將關聯式資料庫的查詢結果轉換為標準的 JSON 格式,為 AI Agent 的串接做好萬全準備。
WRITTEN BY

- Name
- Harry Chang
在上一篇文章中,我們已經成功將鞋墊廠的原始訂單資料去識別化,並存入 PostgreSQL 中。
這時很多開發者會想:「那我是不是可以直接讓 AI Agent 去連這個資料庫,自己寫 SQL 來查資料?」雖然這被稱為 Text-to-SQL,但在企業實戰中,我們非常不建議這麼做。
最安全、最現代化的做法是:開發一層 REST API,讓 Agent 只能透過 API 來拿 JSON 資料(也就是 API-Driven Agent 架構)。
為什麼 Agent 需要 API 而不是直接下 SQL?
把 AI 直接連上資料庫,就像是讓一個實習生直接進到金庫自己拿錢,風險極高。相對地,API 就像是銀行的櫃檯窗口。
這樣做有三大好處:
- 嚴格的權限控管:Agent 只能呼叫你寫好的 API 端點(Endpoint),完全阻絕了它胡亂下達
DELETE或跑出無限迴圈拖垮資料庫的可能。 - 結構化輸出 (JSON):大語言模型天生非常擅長解析 JSON 格式。透過 API,我們能保證給 LLM 的資料格式永遠是標準且一致的。
- 邏輯解耦:如果未來鞋墊廠的資料庫從 PostgreSQL 換成了 MongoDB,你只需要修改 API 裡的邏輯,完全不用去動 AI Agent 的程式碼。
實作解析:使用 FastAPI 開發訂單 API
在 Python 生態系中,目前開發 API 首選的框架就是 FastAPI,它不僅效能極高,還內建了強大的型別檢查功能。
以下是一段概念程式碼,示範如何開出一個查詢「特定品牌訂單」的 API 接口:
from fastapi import FastAPI, HTTPException
import psycopg2 # PostgreSQL 連線套件
import json
app = FastAPI()
# 連接我們昨天建立的 PostgreSQL 中介庫
def get_db_connection():
return psycopg2.connect(
host="localhost",
database="ai_database",
user="ai_user",
password="password"
)
@app.get("/api/v1/orders/")
def get_orders(brand_name: str, start_date: str = None, end_date: str = None):
"""
讓 Agent 透過品牌名稱 (如 Nike) 來查詢訂單資料
"""
conn = get_db_connection()
cursor = conn.cursor()
# 防呆機制與基礎 SQL 組合
query = "SELECT order_id, order_date, brand_name, insole_type, unit_price, order_qty, total_amount FROM safe_orders WHERE brand_name = %s"
params = [brand_name]
if start_date and end_date:
query += " AND order_date BETWEEN %s AND %s"
params.extend([start_date, end_date])
cursor.execute(query, tuple(params))
rows = cursor.fetchall()
if not rows:
raise HTTPException(status_code=404, detail="找不到該品牌的訂單")
# 將關聯式資料轉換為 JSON 格式 (List of Dictionaries)
result = []
for row in rows:
result.append({
"order_id": row[0],
"order_date": str(row[1]),
"brand_name": row[2],
"insole_type": row[3],
"unit_price": float(row[4]),
"order_qty": int(row[5]),
"total_amount": float(row[6])
})
cursor.close()
conn.close()
return {"status": "success", "data": result}
API 回傳的 JSON 結構
當未來的 AI Agent 想要知道「Nike 最近的訂單狀況」,它就會去打 http://localhost:8000/api/v1/orders/?brand_name=Nike,並收到如下標準的 JSON 格式:
{
"status": "success",
"data": [
{
"order_id": "ORD-1001",
"order_date": "2024-01-15",
"brand_name": "Nike",
"insole_type": "PU 發泡鞋墊",
"unit_price": 1.2,
"order_qty": 50000,
"total_amount": 60000.0
},
{
"order_id": "ORD-1006",
"order_date": "2024-03-15",
"brand_name": "Nike",
"insole_type": "EVA 成型鞋墊",
"unit_price": 0.85,
"order_qty": 15000,
"total_amount": 12750.0
}
]
}
透過這種方式,AI 拿到的是最純粹的數據,它可以非常輕易地計算總金額、或是比較不同鞋墊類型的佔比。
實用建議:三個起步行動
如果你正準備為公司的 Agent 寫 API,請留意這三個原則:
步驟 1:定義清晰的 Endpoint 與參數
不要想寫一個「萬能」的 API。最好把查詢拆細,例如 /api/orders (查訂單)、/api/inventory (查庫存)、/api/customers (查客戶)。參數越明確,Agent 在呼叫時就越不容易出錯。
步驟 2:限制回傳的資料筆數 (Pagination)
AI 的 Context Window(上下文視窗)是有限且昂貴的。如果你一次回傳 10 萬筆訂單,不僅浪費 Token,還會導致模型當機。務必在 API 中加入 LIMIT 或分頁機制(例如預設最多回傳 100 筆)。
步驟 3:撰寫詳盡的 API 文件 (OpenAPI/Swagger)
FastAPI 會自動產生 OpenAPI 規格文件。這份文件不僅是給人類開發者看的,更是給 AI Agent 看的說明書。把每一個參數的定義寫清楚,Agent 才能精準判斷何時該呼叫這支 API。
我的反思
在建構企業級 AI 應用的過程中,「API」的角色往往被低估了。
很多人以為 AI 無所不能,應該讓它直接去面對資料庫。但在真實的商業環境中,系統的穩定性與可控性永遠是第一順位。API-Driven 的設計哲學,其實就是為 AI 設下一道「溫柔的邊界」。我們不限制 AI 的推理能力,但我們嚴格規範它取得知識的途徑。
現在,我們已經把 Oracle 轉成了安全的 PostgreSQL,也用 FastAPI 開發出了標準的 JSON 介面。萬事俱備,明天,我們終於可以把這些工具綁定到 AI Agent 的大腦上了!