繁中 ▾

常見框架轉接 API 設定:從 SDK 到 Dify

接入轉接 API 的核心只有三個值:介面位址、金鑰、模型名。難的是每個框架給這三個值取的名字不同,有的叫 base_url,有的叫 api_base,Dify 裡乾脆是一個表單。這篇文章把它們對照列出,每段程式碼都能直接執行,最後附上依序排查的清單。

更新於

重點

  1. 統一將位址與金鑰放入環境變數 API_BASE 與 API_KEY,程式碼中不出現明文。
  2. 介面位址要帶 /v1 後綴,模型名固定寫 uncensored。
  3. LangChain 用 base_url,LlamaIndex 的 OpenAILike 用 api_base,名字不同含義相同。
  4. 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 這類視覺化平台沒有程式碼,而是透過表單設定。不同版本的介面文案略有出入,但步驟基本一致:

  1. 進入「設定」,找到「模型供應商」頁面,在列表裡選擇「OpenAI-API-compatible」,點擊新增模型。
  2. 模型類型選「LLM」,模型名稱填 uncensored。
  3. API Key 填你的金鑰,API endpoint URL 填 https://api.llmzhongzhuan.com/v1。
  4. 模型上下文長度填 100000,最大 token 上限填 32000。
  5. 如果要在工作流裡使用工具呼叫,把函式呼叫支援選項打開;串流輸出保持開啟。
  6. 儲存後新建一個簡單的聊天應用,選中剛新增的模型發一句話,確認能正常回傳。

平台有時會在儲存時發一次探測請求,如果這一步失敗,通常是位址多寫了路徑,或者金鑰前後多了空白。如果你的 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% 集中在幾處,按下面的順序查最快:

  1. 401:金鑰為空、複製時帶了空白字元,或者重置後仍在用舊金鑰。
  2. 404:路徑寫成了不帶 /v1 的根路徑,或者多拼了一次 /chat/completions。
  3. 402:錯誤碼為 no_credit,說明餘額用完或試用已過期,需要儲值預付額度。
  4. 400:常見原因是輸入加 max_tokens 超過了 100,000,或請求體超過 8 MB。
  5. 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。設定就是這麼簡單。

獲取 API 金鑰