常見框架轉接 API 設定:從 SDK 到 Dify
接入轉接 API 的核心只有三個值:介面位址、金鑰、模型名。難的是每個框架給這三個值取的名字不同,有的叫 base_url,有的叫 api_base,Dify 裡乾脆是一個表單。這篇文章把它們對照列出,每段程式碼都能直接執行,最後附上依序排查的清單。
重點
- 統一將位址與金鑰放入環境變數 API_BASE 與 API_KEY,程式碼中不出現明文。
- 介面位址要帶 /v1 後綴,模型名固定寫 uncensored。
- LangChain 用 base_url,LlamaIndex 的 OpenAILike 用 api_base,名字不同含義相同。
- Dify 裡選「OpenAI-API-compatible」供應商,手動填寫模型名、位址與上下文長度即可。
先備齊三個值
不管用哪個框架,先確認手裡有這三樣東西,後續設定都是填空。
- 介面位址:
https://api.llmzhongzhuan.com/v1。注意末尾的/v1要保留,但不要再加/chat/completions,SDK 會自己拼接。 - 金鑰:在 取得金鑰頁 用信箱與密碼註冊後立即顯示,每個帳號一把,可以重設,重設後舊的立即作廢。
- 模型名:只有一個,
uncensored。你可以用GET /v1/models自己確認。
另外請記住幾個限制:上下文總長 100,000 token,單次 max_tokens 預設 2048、最大 32,000,每個金鑰每分鐘 300 次請求。這些數字在後續參數設定中會反覆出現。
環境變數的寫法
把金鑰寫死在程式碼裡是最常見的事故源頭。推薦的做法是只讀環境變數,部署時由容器或金鑰管理系統注入。下面用 API_KEY 與 API_BASE 兩個變數,各個框架的範例都沿用這兩個名字。
# Linux / macOS:写进 ~/.zshrc 或 .env 加载脚本
export API_KEY="替换为你的密钥"
export API_BASE="https://api.llmzhongzhuan.com/v1"
# Windows PowerShell(仅当前会话)
$env:API_KEY = "替换为你的密钥"
$env:API_BASE = "https://api.llmzhongzhuan.com/v1"
如果你用 .env 檔案,別忘了把它加進 .gitignore。另外,官方 Python SDK 預設會讀取 OPENAI_API_KEY 與 OPENAI_BASE_URL,你既可以沿用這兩個變數名,也可以像下面那樣在建構子裡明確傳參。明確傳參的好處是不會被機器上殘留的舊變數干擾,除錯時少一個變數。
OpenAI Python SDK 與 Node SDK
Python 需要 v1 以上的 openai 套件,Node 需要 v4 以上。兩者的差異僅在於語法,建立客戶端時傳入端點與金鑰即可。先查看 Python 的非串流請求,同時列印 usage 以便核對扣費:
import os
from openai import OpenAI
client = OpenAI(
base_url=os.environ.get("API_BASE", "https://api.llmzhongzhuan.com/v1"),
api_key=os.environ["API_KEY"],
)
resp = client.chat.completions.create(
model="uncensored",
messages=[{"role": "user", "content": "写一条 20 字以内的发布公告标题。"}],
max_tokens=100,
)
print(resp.choices[0].message.content)
print(resp.usage)
Node 範例改用串流輸出,這是前端打字機效果最常用的寫法。串流請求結束時伺服器會自動補一個帶 usage 的分片,不需要額外參數:
import OpenAI from "openai";
const client = new OpenAI({
baseURL: process.env.API_BASE ?? "https://api.llmzhongzhuan.com/v1",
apiKey: process.env.API_KEY,
});
const stream = await client.chat.completions.create({
model: "uncensored",
messages: [{ role: "user", content: "列出三个命名服务端日志字段的好习惯。" }],
stream: true,
max_tokens: 300,
});
for await (const chunk of stream) {
process.stdout.write(chunk.choices[0]?.delta?.content ?? "");
}
process.stdout.write("\n");
Node 範例使用頂層 await,需要 .mjs 檔案或在 package.json 裡設定 "type": "module"。如果你的執行環境不支援,把它包進 async 函式即可。
LangChain:ChatOpenAI 的 base_url
LangChain 裡不需要任何專門的適配器,直接用 langchain_openai 套件裡的 ChatOpenAI,把 base_url 指過去就行。
import os
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(
model="uncensored",
base_url=os.environ.get("API_BASE", "https://api.llmzhongzhuan.com/v1"),
api_key=os.environ["API_KEY"],
temperature=0.7,
max_tokens=500,
timeout=60,
)
print(llm.invoke("把“服务已降级”改写成对用户友好的一句话。").content)
兩個小提醒。第一,max_tokens 與 timeout 最好明確設定,預設值未必符合你的業務。第二,如果你在鏈裡用工具呼叫,本站支援 OpenAI 格式的 tools,LangChain 的 bind_tools 可以正常使用;串流時在 stream() 裡按區塊消費即可。
LlamaIndex:OpenAILike
LlamaIndex 內建的 OpenAI 類別會校驗模型名是否在官方清單內,遇到自訂模型名會報錯。這時應該改用 llama-index-llms-openai-like 裡的 OpenAILike,它不做這種校驗,參數名也不同,位址叫 api_base。
import os
from llama_index.llms.openai_like import OpenAILike
llm = OpenAILike(
model="uncensored",
api_base=os.environ.get("API_BASE", "https://api.llmzhongzhuan.com/v1"),
api_key=os.environ["API_KEY"],
is_chat_model=True,
context_window=100000,
max_tokens=500,
)
print(llm.complete("用一句话解释什么是幂等请求。"))
此處的 is_chat_model=True 很關鍵,它讓 LlamaIndex 使用對話端點而非舊的補全端點。context_window 設為 100000,LlamaIndex 在分割上下文時就不會誤按預設的數千 token 截斷你的文件。
Dify:OpenAI-API-compatible 供應商
Dify 這類視覺化平台沒有程式碼,而是透過表單設定。不同版本的介面文案略有出入,但步驟基本一致:
- 進入「設定」,找到「模型供應商」頁面,在列表裡選擇「OpenAI-API-compatible」,點擊新增模型。
- 模型類型選「LLM」,模型名稱填
uncensored。 - API Key 填你的金鑰,API endpoint URL 填
https://api.llmzhongzhuan.com/v1。 - 模型上下文長度填 100000,最大 token 上限填 32000。
- 如果要在工作流裡使用工具呼叫,把函式呼叫支援選項打開;串流輸出保持開啟。
- 儲存後新建一個簡單的聊天應用,選中剛新增的模型發一句話,確認能正常回傳。
平台有時會在儲存時發一次探測請求,如果這一步失敗,通常是位址多寫了路徑,或者金鑰前後多了空白。如果你的 Dify 部署在容器裡,還要確認容器能存取外部網域名稱。
上線前要核對的參數與部署寫法
框架能跑通只是第一步,下面幾個參數在上線前最好逐一核對,它們決定了成本與失敗率。
- max_tokens:預設 2048,需要長文輸出就明確調大,上限 32,000。注意輸入與輸出加起來不能超過 100,000,否則會收到 400。
- timeout:長輸出的請求耗時更久,串流場景建議把讀取逾時設到 60 秒以上,非串流則按最長輸出估算。
- temperature / top_p / stop:這些標準採樣參數會被透傳,框架裡設定的值會直接生效,不需要額外開關。
- 並行請求:每個金鑰每分鐘 300 次請求,多個服務實例共用同一把金鑰時,限流是合併計算的,別讓每個實例都按 300 次來規劃。
- 重試:框架內建的重試往往只針對網路錯誤,對 429 與 503 要自己加退避,寫法見穩定性那一篇。
部署到容器時,思路同樣是「映像檔裡不放金鑰」,由編排工具在啟動時注入。下面是 compose 裡的最小寫法:
# docker-compose.yml 片段
services:
app:
image: your-app:latest
environment:
API_BASE: https://api.llmzhongzhuan.com/v1
API_KEY: ${API_KEY} # 从宿主机环境或 .env 读取,不写进镜像
在 Kubernetes 裡就換成 Secret 引用,原則不變。另外建議給不同環境準備不同的帳號或金鑰,例如開發、預發與生產各一套,這樣某個環境的金鑰洩露或餘額耗盡,不會連帶影響線上。因為每個帳號只有一把金鑰,所以多環境最好對應多個帳號,並分別預儲值適量餘額。
最後是日誌。很多框架在除錯模式下會列印完整的請求標頭,裡面就包含 Authorization,務必在生產環境關閉這類除錯輸出,或者在日誌過濾器裡把金鑰脫敏。把 usage 欄位記錄下來則是好習慣,它能幫你對照帳單,也能提前發現某個功能的提示詞突然變長。
報錯時的排查順序
接入階段的問題 90% 集中在幾處,按下面的順序查最快:
- 401:金鑰為空、複製時帶了空白字元,或者重置後仍在用舊金鑰。
- 404:路徑寫成了不帶
/v1的根路徑,或者多拼了一次/chat/completions。 - 402:錯誤碼為 no_credit,說明餘額用完或試用已過期,需要儲值預付額度。
- 400:常見原因是輸入加
max_tokens超過了 100,000,或請求體超過 8 MB。 - 429 / 503:前者是每分鐘 300 次的速率限制,後者是 upstream_busy,稍等幾秒重試,具體做法見 穩定性實踐。
還有一類容易被忽略的問題是網路環境。公司內網、代理軟體或者安全組規則,可能讓域名解析成功卻無法建立 HTTPS 連線,表現為長時間卡住後超時,而不是明確的錯誤碼。遇到這種情況,先在同一台機器上用 curl 訪問 /v1/models;能通就說明問題在應用層,不通則去查代理和防火牆。把排查過程記在團隊文件裡,下次新同事接入時就能少走一遍彎路。
三個值都正確卻仍然失敗時,先用 curl 直接請求一次,排除框架自身的問題。如果想先了解中轉到底做了什麼,可以回看 中轉原理 這一篇。
常見問題
base_url 到底要不要帶 /v1?
要帶。写成 https://api.llmzhongzhuan.com/v1 即可,SDK 會在後面自動拼上 /chat/completions,不要重複添加。
LlamaIndex 為什麼要用 OpenAILike 而不是 OpenAI?
OpenAI 類會檢查模型名是否屬於官方清單,自訂模型名會報錯。OpenAILike 不做校驗,更適合接入相容介面。
Dify 裡填的模型名可以隨便起嗎?
不可以,模型名必須是 uncensored,因為請求會原樣帶上這個 id。顯示名稱可以另外起,但模型欄位要對。
環境變數改了為什麼沒生效?
多數是終端或程序沒有重啟。建議在程式碼裡顯式傳 base_url 和 api_key,並列印一次實際使用的位址來確認。
只需填寫表單即可獲取金鑰
建立帳戶,複製金鑰,修改 Base URL。設定就是這麼簡單。