生活分享
統一 API 層:OpenRouter 與 LiteLLM 換模型不改程式
OpenAI 相容端點是供應商提供的 REST 介面,形狀和 OpenAI 的 Chat Completions 端點相同,程式只要換 base_url、金鑰與 model 字串就能連到別家模型,不必重寫呼叫邏輯。這篇示範同一段 Python 用 openai 套件連上 OpenRouter 與 Groq 兩個相容端點,再用 LiteLLM 的 completion() 換三個 model 字串連到三家供應商,並比較 OpenRouter 這個託管閘道,跟 LiteLLM 的 SDK 與自架 Proxy,在「相容」範圍上的限制。
閱讀時間約 10 分鐘

本篇目錄
「OpenAI 相容」指的是供應商把自己的推論服務包成和 OpenAI Chat Completions 端點同樣形狀的 REST 介面;只要程式呼叫的是這個形狀,換一家供應商通常只需要換 base_url、金鑰與 model 字串,其餘程式碼不用動。這篇說明 OpenAI 相容端點的意思與能相容到什麼程度,再用 openai 套件與 LiteLLM 兩種做法實際切換供應商。
讀完這篇,你會有一段 Python 程式碼,用 openai 套件的用戶端連上兩個不同的 OpenAI 相容端點;也會有另一段程式,用 LiteLLM 的 completion() 函式只換 model 字串就連到三家供應商,還會知道「相容」指請求與回應的形狀相同,不是每個參數都通用。動手前需要能執行 Python(openai 套件官方文件寫最低支援 3.10)、用 pip 或 uv 裝好 openai 與 litellm 兩個套件,以及要呼叫那幾家供應商各自的 API 金鑰,金鑰一律放進環境變數,不寫進程式碼。
什麼是 OpenAI 相容端點
OpenAI 在 Chat Completions 端點定義了一套請求與回應的 JSON 形狀:請求帶 model、messages 等欄位,回應在 choices 裡放 message.content。不少供應商把自己的推論服務包成同一種形狀,讓原本寫給 OpenAI 的程式改個設定就能連過去。openai 官方套件的說明也寫,用戶端的 base_url 可以直接被覆寫,或改讀 OPENAI_BASE_URL 這個環境變數,程式完全不用動。
「相容」指的是形狀,不是每一個參數。OpenRouter 的 API 參考寫得很直接:如果選到的模型不支援某個請求參數,例如非 OpenAI 模型不支援 logit_bias、OpenAI 模型不支援 top_k,那個參數會被忽略,其餘的參數照樣轉送到底層那家供應商的 API。Groq 官方文件把自己寫成「大致相容」,同時明講 logprobs、logit_bias、top_logprobs 與 messages[].name 這幾個欄位目前不支援,帶了會直接收到 400 錯誤,不是默默忽略。同一個「相容」,兩家處理方式並不一樣,實際能用哪些參數,還是得查供應商自己的文件。
換 base_url 與 model 字串:同一支 openai 用戶端打兩家
openai 這個 Python 套件本來是為 OpenAI 自己的 API 寫的,但它的用戶端建構式接受 base_url 這個參數,把網址換成任何一個 OpenAI 相容端點,用戶端就會去打那個網址而不是 api.openai.com。下面的程式先連 OpenRouter:官方 quickstart 寫 base_url 要填 https://openrouter.ai/api/v1,請求送到 /api/v1/chat/completions 這個端點,金鑰放進 Authorization 標頭當 Bearer token;文件另外列了 HTTP-Referer 與 X-OpenRouter-Title 兩個選用標頭,設了應用程式就能出現在 OpenRouter 的排行榜上,不設也能正常呼叫。
import os
from openai import OpenAI
question = [{"role": "user", "content": "用一句話說明 API 金鑰是什麼"}]
# 官方 quickstart:base_url 指到 openrouter.ai,金鑰放 Authorization 標頭
openrouter = OpenAI(
base_url="https://openrouter.ai/api/v1",
api_key=os.environ["OPENROUTER_API_KEY"],
timeout=30.0,
)
reply = openrouter.chat.completions.create(
extra_headers={
"HTTP-Referer": os.environ.get("SITE_URL", ""),
"X-OpenRouter-Title": os.environ.get("SITE_NAME", ""),
},
model="anthropic/claude-sonnet-5",
messages=question,
)
print("OpenRouter:", reply.choices[0].message.content)
# 官方文件:base_url 換成 api.groq.com,金鑰改讀 GROQ_API_KEY
groq_client = OpenAI(
base_url="https://api.groq.com/openai/v1",
api_key=os.environ["GROQ_API_KEY"],
timeout=30.0,
)
reply = groq_client.chat.completions.create(
model="openai/gpt-oss-120b",
messages=question,
)
print("Groq:", reply.choices[0].message.content)
同一支用戶端換第二次連線時,只有 base_url、金鑰讀的環境變數,以及 model 字串三個地方不一樣:Groq 官方文件寫,要用 OpenAI 相容的用戶端連 Groq,base URL 換成 https://api.groq.com/openai/v1、金鑰改讀 GROQ_API_KEY 就好;範例裡的 openai/gpt-oss-120b 是 Groq 模型頁 MODEL ID 欄位上的代號,那一頁把它寫成 OpenAI 的旗艦開放權重開放權重(Open Weights):能下載模型,還要確認什麼開放權重通常表示模型的已訓練參數可取得,讓使用者有機會自行部署或調整,但不等於訓練資料與程式都公開。本文用本機筆記摘要示範權重、架構、tokenizer 和推論程式的分工,區分下載、可修改、商業使用與完整開源,也解釋為什麼本機執行不自動保證隱私。讀完能檢查模型版本、授權文件、硬體需求和來源完整性。閱讀全文模型。兩段呼叫都設了 timeout,避免網路異常時程式卡住不動;這裡用到的 anthropic/claude-sonnet-5 是 OpenRouter 目錄裡的代號,如果想繞過 OpenRouter、直接向 Anthropic 申請金鑰,站上《第一次呼叫 Claude API:金鑰、費用與十行 Python》已經走過一遍,這裡不重複。
LiteLLM:把「換供應商」收進一個函式
OpenRouter 是別人已經架好的閘道,帳號、金鑰、儲值都在 openrouter.ai 那一端,站上《OpenRouter:一把金鑰用遍各家模型》整理過,這裡不重複。LiteLLM 走另一條路:它是一個 Python 套件,官方文件把它寫成「OpenAI 用戶端的直接替代品」,重點是 completion()、embedding() 這些函式,直接匯入自己的程序裡呼叫,不需要另外連到誰架的伺服器;安裝指令是 uv add litellm。
LiteLLM 的 model 字串自己帶著供應商:官方文件示範每一家供應商時,都把供應商名稱寫在最前面、用斜線隔開,例如 model="openai/gpt-5.6-terra",並在同一段範例裡設好對應的環境變數(OPENAI_API_KEY、ANTHROPIC_API_KEY);透過 OpenRouter 轉接時要多包一層,文件寫送 model=openrouter/ 加上你的 OpenRouter 模型,請求就會送到 OpenRouter,範例是 model="openrouter/google/palm-2-chat-bison",金鑰讀 OPENROUTER_API_KEY,OPENROUTER_API_BASE 是選用欄位,不設定時預設就是 https://openrouter.ai/api/v1。下面同一段迴圈換了三次 model 字串,其他呼叫方式完全沒變;google/gemini-3.8-flash 一樣是 OpenRouter 上的代號,要直接向 Google 申請金鑰、建立第一支呼叫,見《AI Studio 與第一個 Gemini API 呼叫》。
import os
from litellm import completion
question = [{"role": "user", "content": "用一句話說明 API 金鑰是什麼"}]
# 三個字串分屬三家供應商,completion() 的呼叫方式完全相同
model_ids = [
"openai/gpt-5.6-terra",
"anthropic/claude-sonnet-5",
"openrouter/google/gemini-3.8-flash",
]
# 金鑰不寫進程式:LiteLLM 從環境變數讀,先確認三把都設好了
for name in ("OPENAI_API_KEY", "ANTHROPIC_API_KEY", "OPENROUTER_API_KEY"):
if name not in os.environ:
raise SystemExit(f"請先設定環境變數 {name}")
for model_id in model_ids:
reply = completion(model=model_id, messages=question, timeout=30)
print(model_id, "->", reply.choices[0].message.content)
三次呼叫用的是同一個 completion() 函式、同一份 messages,差別只有 model 這一個字串;官方文件寫,LiteLLM 把各家的錯誤對應成 OpenAI 的例外型別,例如 litellm.AuthenticationError、litellm.RateLimitError。第二個字串和第一段程式裡的 anthropic/claude-sonnet-5 同形不同意:這裡是 LiteLLM 前綴加 Anthropic 自己的代號、讀 ANTHROPIC_API_KEY,那裡是 OpenRouter 目錄裡的代號。官方文件也寫,completion() 預設遇到不支援的 OpenAI 參數會直接丟出例外,要自己在呼叫時加 drop_params=True,或整體設定 litellm.drop_params = True 才會改成忽略,而且只會捨棄不支援的 OpenAI 參數;這點放進下面的提醒框。
託管閘道與自架 Proxy:OpenRouter 與 LiteLLM 的另一種模式
前面兩段程式都是「自己的程序直接連出去」:一段連到 OpenRouter 這個別人架好的閘道,一段是 LiteLLM 在自己的程序裡轉接。LiteLLM 其實還有第三種形態,官方文件把它稱為 Proxy Server,是一個要自己架設的閘道伺服器,架起來以後它自己就是一個 OpenAI 相容端點。官方文件把它寫成「給平台團隊用的自架閘道,用來管理整個組織的 LLM大型語言模型(Large Language Model)是什麼大型語言模型從大量資料學習語言與其他模式,依上下文處理文字、生成回答或提出工具請求。本文以失物招領紀錄為例,說明 token、參數、預訓練、提示詞與上下文如何配合,區分模型、聊天產品、搜尋與外部工具,並解釋為何流暢答案仍需查證。讀完能更精確描述任務,知道何時該補檔案、要求工具計算或保留無法確認的答案。閱讀全文 存取」,功能包含依金鑰設定花費上限、集中記錄與快取,還有管理介面能看用量。
架起來之後,呼叫方式反而回到最一開始那個樣子:官方文件的範例直接用 openai 套件的用戶端,把 base_url 指到自己架的位址,範例寫的是 http://0.0.0.0:4000,api_key 填的是 anything 這個字串,實際的存取控制由 Proxy 自己的虛擬金鑰管。這樣看下來,OpenRouter 與 LiteLLM 的 Proxy 是同一種角色的兩種做法:一種別人架好、一種自己架自己維護,換來的是能自己設定每把金鑰的預算與存取規則;怎麼選要看團隊有沒有人力顧那台伺服器。
相容解決什麼、不解決什麼
換 base_url 與 model 字串解決的是「程式不用為每家供應商重寫一份呼叫邏輯」,但解決不了其他幾件事。價格、免費額度、速率限制是供應商自己訂的,換一個相容端點不會讓它們變得一樣,這篇不比價,系列另一篇《成本、品質、延遲:多模型流程怎麼取捨》會專門整理怎麼在三者之間取捨。同樣地,相容層幫忙轉接的是單一次請求,請求裡帶了工具呼叫(tool calling)之類的功能,底層模型本身支不支援仍然是那個模型自己的事。
要確定某個模型、某個供應商實際支援哪些參數,LiteLLM 官方文件提供一個 get_supported_openai_params() 函式,帶入 model 與供應商名稱就能查到一份清單;OpenRouter 則是在 API 參考的註解裡示範,用 supported_parameters 篩出支援工具呼叫的模型。這篇只示範兩個直連的端點與一段 LiteLLM 程式,還沒有真的依價格或失敗與否切換供應商,那部分屬於系列另一篇《模型路由與級聯:便宜先試、貴的兜底》要講的內容,這裡不重複。
| 做法 | 你在程式裡呼叫的東西 | model 字串怎麼寫 | 「相容」範圍由誰的文件定義 |
|---|---|---|---|
| openai 套件直連 | openai 套件的 OpenAI(...) 用戶端,base_url 指到該供應商 | 供應商自己的原生代號,例如 openai/gpt-oss-120b | 那家供應商自己的 API 文件 |
| OpenRouter | 同一支 openai 用戶端,base_url 指到 openrouter.ai | 供應商名稱+斜線+模型,例如 anthropic/claude-sonnet-5 | OpenRouter 的 API 參考 |
| LiteLLM SDK | 從 litellm 匯入的 completion() 函式 | 供應商前綴+原生代號,例如 anthropic/claude-sonnet-5(與 OpenRouter 那一列同形不同意) | LiteLLM 的 Input Params 文件頁,它列出各供應商支援哪些 OpenAI 參數 |
| LiteLLM Proxy | openai 套件的用戶端,base_url 指到自己架的伺服器 | 自己在 config.yaml 裡取的 model_name | 架設者自己寫的 config.yaml |
常見問題
OpenAI 相容是不是代表所有參數都能直接搬過去用?
不是。相容指的是請求與回應的 JSON 形狀一樣,不是每一個參數都通用。官方文件寫,OpenRouter 遇到模型不支援的參數會直接忽略、其餘照送;LiteLLM 預設遇到不支援的 OpenAI 參數會丟出例外,要自己開啟才會改成忽略。實際能用哪些參數,還是要查那個模型自己的文件。
OpenRouter 和 LiteLLM 是同一種東西嗎?
不是。OpenRouter 是別人已經架好、直接連線就能用的託管端點,帳號、金鑰、儲值都在對方那一端。LiteLLM 是一個 Python 套件,completion() 這些函式是在你自己的程序裡執行;它另外還有一個 Proxy 模式,需要自己架一台伺服器,架起來之後同樣變成一個 OpenAI 相容端點。
換供應商時,程式碼真的只需要改 base_url 和 model 嗎?
以這篇示範的兩個呼叫來說是的:openai 套件的用戶端只換了 base_url、金鑰讀的環境變數,和 model 字串三個地方,其餘程式碼沒有變。要注意的是不同供應商的 model 字串寫法不一樣:OpenRouter 用的是「供應商/模型」這種格式,Groq 則是填它模型頁表格 MODEL ID 欄位上的代號,兩邊不一定長得一樣。
LiteLLM 的 model 字串為什麼要加供應商前綴?
官方文件示範每一家供應商時,都把供應商名稱寫在 model 字串最前面、用斜線隔開,例如 openai/gpt-5.6-terra、anthropic/claude-sonnet-5,並在同一段範例裡設好對應的環境變數;OpenRouter 那一頁還明講,送 openrouter/ 加上你的 OpenRouter 模型,請求就會送到 OpenRouter。這篇的範例都照這個寫法。要注意 anthropic/claude-sonnet-5 這種字串在 LiteLLM 與在 OpenRouter 同形不同意:前者是 LiteLLM 前綴加 Anthropic 自己的代號,後者是 OpenRouter 目錄裡的代號。
要自己架 LiteLLM 的 Proxy,還是直接用 OpenRouter 比較好?
這篇沒有幫你決定,兩者是不同的取捨。OpenRouter 不用自己維運伺服器,能設定的就是對方那一端提供的項目;LiteLLM 的 Proxy 需要自己架設與維運,換來的是官方文件列出的那些自架功能,例如每把虛擬金鑰各自的預算、集中記錄與快取。要哪一種看團隊有沒有人力顧到自架的那台伺服器。
多模型 AI 工作流教學:從拆任務到串接不同模型多模型 AI 工作流教學:從拆任務到串接不同模型這個系列教的是怎麼把一件工作拆開、交給合適的模型,再把結果接回同一條流程:判斷該不該拆、拆給誰,換供應商不改程式,設計便宜先試的路由與級聯,讓模型之間用結構化輸出交接資料,再到代理式工具怎麼分工、同一套工具怎麼給多個客戶端共用、Claude Code 與 Codex 怎麼搭本機模型,以及上線後怎麼追蹤與防護。一般使用者可以從判斷該不該拆的觀念讀起,已經會寫 Python 的人能直接進到換供應商、寫路由與交接資料的幾篇。閱讀全文
OpenRouter:一把金鑰用遍各家模型OpenRouter:一把金鑰用遍各家模型OpenRouter 用一個 OpenAI 相容端點接上各家模型,官網 FAQ 寫儲值收 5.5% 手續費、token 價格不加價。這篇照 openrouter.ai 當天的文件走完註冊與金鑰、儲值與退款規則、模型頁每百萬 token 價格怎麼讀、免費模型每天能跑幾次、provider 欄位怎麼指定路由與資料留存,附 Python 與 curl 最小範例,以及誰適合、誰不適合。閱讀全文
同主題延伸閱讀
生活分享
Claude Code、Codex 搭本機模型:兩種接法怎麼選
Claude Code 與 Codex 搭配本機模型有兩種接法:代理照常連雲端、把大量雜務交給腳本或 MCP 工具去問本機模型,或是把代理的模型整個換成本機模型。這篇用資料能不能出門、上下文開得夠不夠長、工作的類型三個問題幫你選,並對照 Ollama、LM Studio、Anthropic 與 OpenAI 的官方文件,分清楚本機權重、Ollama 的 cloud 標籤與供應商端點是三種不同的東西。
引用本文的文章
最新旅遊情報攻略

情報
2026 韓國楓葉預測:雪嶽山 10 月 20 日、首爾近郊 10 月底、內藏山與漢拏山 11 月上旬
韓國山林廳 2026 年 9 月 22 日公布的楓紅高峰預測:雪嶽山 10 月 20 日,春川、國立樹木園到首爾植物園落在 10 月 28 日到 11 月 2 日,內藏山 11 月 4 日、漢拏山 11 月 6 日,整體比最近 5 年晚約 0.8 天。整理各地楓樹與銀杏的預測日、首爾出發怎麼排,以及出發前去哪裡看即時楓況。2026 年 10 月查證。
- 季節活動
- 自然
- 觀景

攻略胡志明市
胡志明市到頭頓一日遊:白藤碼頭搭高速船、船票與班次,下船就是胡梅纜車與耶穌基督像
人在胡志明市挪一天去頭頓看海:市中心的白藤高速船碼頭搭船,航程 120 分鐘到頭頓的胡梅碼頭,平日成人 320,000 越南盾、週末 350,000,回程末班平日 15:00。下船就是胡梅纜車站,同一條路上有白宮,小山頂上是耶穌基督像。平日一天只有兩班船,整天要從末班船倒推著排。
- 交通
- 行程範例
- 海灘

攻略沖繩
沖繩不開車攻略:單軌只到浦添,美麗海水族館要坐兩個多小時的巴士,回那霸的最後一班直達車 17:22 就開走
不租車的沖繩怎麼移動:那霸市區靠沖繩都市單軌電車(ゆいレール),那霸機場站到終點てだこ浦西 19 站、17 公里、37 分鐘,一日券 1,000 日圓;美麗海水族館有那霸機場直達的高速巴士,單程 2,000 日圓起、官方時刻表上 2 小時上下,下車後還要走 10 分鐘;古宇利島要在今帰仁村役場轉車,當天來回光坐車就六個半小時;回程的最後一班直達車 17:22 就從記念公園前開走(2026 年 9 月查證)。
- 交通
- 行程範例
- 預算
資料來源
- OpenRouter Quickstart(base_url、Authorization Bearer、選用排行榜標頭、OpenAI SDK 範例) · 查證日期:
- OpenRouter API Reference: Overview(/api/v1/chat/completions 端點、與 OpenAI 格式的差異、不支援參數被忽略) · 查證日期:
- LiteLLM Docs(Python SDK 與 Proxy 兩種形態、uv add litellm、completion() 範例、例外類別) · 查證日期:
- LiteLLM Docs: Input Params(completion() 函式簽名、get_supported_openai_params()、drop_params) · 查證日期:
- LiteLLM Docs: OpenRouter(model 字串要加 openrouter/ 前綴、OPENROUTER_API_KEY 與 OPENROUTER_API_BASE) · 查證日期:
- openai-python README(base_url 建構參數、OPENAI_BASE_URL 環境變數、Python 3.10+、timeout 預設 10 分鐘) · 查證日期:
- Groq Docs: OpenAI Compatibility(大致相容的宣告、base_url 與 GROQ_API_KEY、不支援欄位收到 400 錯誤) · 查證日期:
- Groq Docs: Models(MODEL ID 欄位上的 openai/gpt-oss-120b、GPT-OSS 120B 的模型說明) · 查證日期: