JA ▾

主要フレームワークでの API 中継設定:SDK から Dify まで

API 中継の接続に必要な値はエンドポイント、API キー、モデル名の 3 つだけです。難しいのは、フレームワークによってこれら 3 つの値に異なる名前が付けられている点です。base_url と呼ぶものもあれば、api_base と呼ぶもの、Dify のようにフォームになっているものもあります。本稿ではこれらを対照的に一覧化し、コードはそのまま実行可能です。最後にエラー解決の手順を記載します。

更新日

主要ポイント

  1. アドレスと API キーを環境変数 API_BASE と API_KEY に統一して格納し、コード内に平文で表示しないようにします。
  2. エンドポイントには /v1 サフィックスを付け、モデル名は uncensored と固定します。
  3. LangChain は base_url を使用し、LlamaIndex の OpenAILike は api_base を使用します。名前が異なりますが意味は同じです。
  4. Dify では「OpenAI-API-compatible」プロバイダを選択し、モデル名、アドレス、コンテキストウィンドウを手動で入力します。

まず 3 つの値を準備する

どのフレームワークを使用する場合でも、まずこれら 3 つの値を入手してください。その後の設定はこれらを入力するだけです。

  • エンドポイント:https://api.llmzhongzhuan.com/v1。末尾の /v1 は残してください。ただし、SDK が自動的に付加するため、/chat/completions を追加しないでください。
  • API キー:API キー取得ページ でメールアドレスとパスワードで登録するとすぐに表示されます。アカウントごとに 1 つずつ発行され、再設定可能です。再設定すると旧キーは直ちに無効になります。
  • モデル名:1 つだけです。uncensored です。GET /v1/models で自身で確認することもできます。

また、以下の制限事項も覚えておいてください。コンテキストの総長は 100,000 トークン、単一の max_tokens はデフォルト 2048、最大 32,000 です。各 API キーは 1 分間に 300 リクエストまでです。これらの数値は後のパラメータ設定で頻繁に使用されます。

環境変数の記述方法

API キーをコードにハードコードすることは最も一般的な事故の原因です。推奨される方法は、環境変数のみを参照し、デプロイ時にコンテナやシークレット管理システムから注入することです。以下では API_KEY と API_BASE の 2 つの変数を使用し、各フレームワークの例でもこの名前を統一して使用します。

# 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 を読み取ります。これらの変数名を引き継ぐか、以下のようにコンストラクタで明示的にパラメータを渡すことができます。明示的に渡す利点は、マシン上に残存する古い変数の影響を受けないため、デバッグ時に考慮すべき変数が 1 つ減ります。

OpenAI Python SDK と Node SDK

Python には v1 以上の openai パッケージ、Node には v4 以上が必要です。両者の違いは構文だけで、アドレスと API キーを渡してクライアントを構築します。まずは 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)

2 つの注意点があります。第一に、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 がコンテキストを分割する際に、デフォルトの数千トークンでドキュメントを誤って切り捨てなくなります。

Dify:OpenAI互換サプライヤー

Dify などのビジュアルプラットフォームではコードはなく、フォームで設定します。バージョンによって UI の文言が若干異なる場合がありますが、手順はほぼ同じです。

  1. 「設定」に移動し、「モデルプロバイダ」ページを見つけ、リストから「OpenAI-API-compatible」を選択して「モデルを追加」をクリックします。
  2. モデルタイプは「LLM」を選択し、モデル名に uncensored を入力します。
  3. API Key に API キーを入力し、API endpoint URL に https://api.llmzhongzhuan.com/v1 を入力します。
  4. モデルのコンテキストウィンドウ長に 100000、最大トークン上限に 32000 を入力します。
  5. ワークフローでツール呼び出しを使用する場合は、関数呼び出しサポートオプションを有効にし、ストリーミング出力を有効にしてください。
  6. 保存後、シンプルなチャットアプリを新規作成し、追加したモデルを選択してメッセージを送信し、正常に返答されるか確認します。

プラットフォームは保存時にヘルスチェックリクエストを送信することがあります。このステップで失敗する場合は、通常、アドレスにパスが重複して記載されているか、API キーの前後にスペースが含まれているためです。Dify がコンテナ内でデプロイされている場合は、コンテナが外部ドメインにアクセスできることを確認してください。

公開前に確認すべきパラメータとデプロイ方法

フレームワークが動作することは第一歩です。以下のパラメータは公開前に逐一確認することをお勧めします。これらはコストと失敗率を決定します。

  • max_tokens:デフォルトは 2048 です。長文の出力が必要な場合は明示的に引き上げてください。上限は 32,000 です。入力と出力の合計が 100,000 を超えると、400 エラーが発生することに注意してください。
  • timeout:長文の出力ではリクエストの所要時間が長くなります。ストリーミングの場面では読み込みタイムアウトを 60 秒以上に設定することをお勧めします。非ストリーミングの場合は、最長の出力に基づいて推定してください。
  • temperature / top_p / stop:これらの標準的なサンプリングパラメータは透過的に渡され、フレームワークで設定した値がそのまま有効になります。追加のスイッチは不要です。
  • 同時リクエスト:各 API キーは毎分 300 リクエストまで。同一キーを複数サービスインスタンスで共有する場合、レート制限は合算されるため、各インスタンスを 300 リクエストで計画しないように。
  • リトライ:フレームワーク付属のリトライは通常ネットワークエラーのみを対象としており、429 と 503 にはバックオフ処理を自分で追加する必要があります。詳細は安定性ガイドを参照してください。

コンテナへのデプロイでも考え方は同じで、「イメージ内に API キーを格納しない」とし、オーケストレーションツールが起動時に注入します。以下は compose での最小限の記述です。

# docker-compose.yml 片段
services:
  app:
    image: your-app:latest
    environment:
      API_BASE: https://api.llmzhongzhuan.com/v1
      API_KEY: ${API_KEY}   # 从宿主机环境或 .env 读取,不写进镜像

Kubernetes ではシークレット参照に切り替えます。原則は変わりません。また、異なる環境用に異なるアカウントまたは API キーの準備をお勧めします。例えば、開発、ステージング、本番用にそれぞれ 1 セットずつ用意します。これにより、ある環境の API キーが漏洩したり残高が枯渇したりしても、本番環境に影響が及びません。各アカウントには API キーが 1 つだけ発行されるため、複数環境では複数のアカウントを用意し、それぞれに適切な残高を事前にチャージすることをお勧めします。

最後にログについてです。多くのフレームワークはデバッグモードで完全なリクエストヘッダーを出力します。そこには Authorization が含まれるため、本番環境ではこれらのデバッグ出力を必ず無効にするか、ログフィルターで API キーをマスクしてください。usage フィールドを記録することは良い習慣です。これにより請求書と照合でき、特定の機能のプロンプトが突然長くなったことを事前に発見できます。

エラー発生時のトラブルシューティング順序

接続フェーズの問題の 90% は以下の箇所に集中しています。以下の順序で調査すると最も早く解決できます。

  1. 401:API キーが空、コピー時にスペースが含まれていた、またはリセット後も古い API キーを使用している。
  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 にアクセスする。接続が成功すれば問題はアプリケーション層にあることを意味し、失敗すればプロキシとファイアウォールを確認する。トラブルシューティングの過程をチームのドキュメントに記録しておけば、次回新人が接続する際に無駄な手順を踏まなくて済む。

3つの値がすべて正しいのに失敗する場合、まず curl で直接リクエストを実行してフレームワーク自体の問題を除外してください。転送が実際に何をしているかを知りたい場合は、転送の原理の記事を参照してください。

よくある質問

base_url に /v1 を付ける必要があるのか?

付ける必要があります。https://api.llmzhongzhuan.com/v1 と設定すれば、SDK が自動的に /chat/completions を付加するため、重複して追加する必要はありません。

LlamaIndex で OpenAI ではなく OpenAILike を使用する必要があるのはなぜか?

OpenAI クラスはモデル名が公式リストに含まれているかチェックするため、カスタムモデル名ではエラーになります。OpenAILike は検証を行わないため、互換インターフェースとの接続により適しています。

Dify で入力するモデル名は自由に設定できるのか?

できません。リクエストにはこの id がそのまま含まれるため、モデル名は uncensored でなければなりません。表示名は別途設定できますが、モデルフィールドは一致させる必要があります。

環境変数を変更したのに反映されないのはなぜか?

大半はターミナルまたはプロセスの再起動が行われていないためです。コード内で base_url と api_key を明示的に渡すことを推奨し、実際に使用されるアドレスを出力して確認してください。

フォームに記入するだけで API キーを取得できます

アカウントの作成、API キーのコピー、Base URL の変更。設定はこれだけです。

API キーを取得する