FlueでOpenAI互換APIを使うときはmodel specifierを先に疑う
Flue 1.0 BetaでOpenAI互換APIを使う際に、実モデルIDとFlueのprovider-id/model-id形式を混同してUnknown model specifierで止まった検証メモ。
Flue 1.0 BetaでGitHub IssueトリアージAgentを作ったとき、最初に詰まったのはAgentの設計ではなく、モデル指定でした。
Flue 1.0 BetaでGitHub Issueトリアージエージェントを動かしてみた https://llm-lab.dev/posts/flue-1-0-beta-issue-triage-agent/
手元で利用できるOpenAI互換APIに向ければよいだろう、という見立て自体は間違っていませんでした。ただし、API側のモデルIDをそのままFLUE_MODELへ入れると、Flue側のモデル解決では別の意味になります。
ここで一度、Unknown model specifierで止まりました。
そこじゃなかった!!
期待していたのは「接続先APIへ投げて、モデル側のエラーが返る」ことでした。しかし実際には、リクエストを投げる前にFlueのmodel specifier解決で止まりました。つまり、APIキー、base URL、モデルのtool calling適性以前に、Flueがどのproviderを使うかを判断できていなかったわけです。
何を混同したか
混同していたのは、API側のモデルIDとFlue側のmodel specifierです。
OpenAI互換APIの設定では、接続先が受け付けるモデルIDがあります。仮にそれが次のような値だとします。
preview/Kimi-K2.6
一方で、FlueのAgent設定に渡すmodelは、単なるリモートモデルIDではなく、provider-id/model-id形式の指定です。OpenAI互換APIをFlueの組み込みopenai providerとして扱うなら、次のように書きます。
openai/preview/Kimi-K2.6
前者はAPI側のモデル名で、後者はFlue側の接続経路まで含めた指定です。この差を見落とすと、モデルの性能やtool calling以前の段階で失敗します。
providerは増やさずopenaiを差し替える
今回の検証では、独自provider IDを新しく作るのではなく、組み込みopenai providerの向き先をOpenAI互換APIへ差し替えました。記事の主題は特定providerの紹介ではなく、FlueでAgentを動かすことなので、provider名は抽象化しています。
import { registerProvider } from '@flue/runtime';
const openAiCompatibleApiKey = process.env.OPENAI_COMPAT_API_KEY;
const openAiCompatibleBaseUrl = process.env.OPENAI_COMPAT_BASE_URL;
if (openAiCompatibleApiKey && openAiCompatibleBaseUrl) {
registerProvider('openai', {
baseUrl: openAiCompatibleBaseUrl,
apiKey: openAiCompatibleApiKey,
models: {
'preview/Kimi-K2.6': {
contextWindow: 131_072,
maxTokens: 16_384,
},
},
});
}
この形にすると、Flue上のprovider IDはopenaiのままです。したがってAgentやWorkflowから指定するモデルは、openai/<リモートモデルID>になります。
OPENAI_COMPAT_API_KEY="your-api-key"
OPENAI_COMPAT_BASE_URL="https://your-openai-compatible-endpoint/v1"
FLUE_MODEL="openai/preview/Kimi-K2.6"
ここで重要なのは、OPENAI_COMPAT_BASE_URLがAPIの向き先を決め、FLUE_MODELのopenai/がFlue内のprovider解決を決める、という役割分担です。どちらも「モデル接続」の話なので混ざりやすいのですが、見ている層が違います。
呼ぶ前に形だけ確認する
この手の詰まりは、実際にLLMを呼ぶ前に検出できます。検証環境には、FLUE_MODELの形とOpenAI互換API用の環境変数が入っているかだけを見る小さな確認スクリプトを置きました。
これはFlue公式CLIではなく、記事用に用意した検証スクリプトです。入力は環境変数FLUE_MODEL、OPENAI_COMPAT_BASE_URL、OPENAI_COMPAT_API_KEYで、providerへリクエストは投げません。確認するのは、FLUE_MODELがprovider-id/model-id形式になっているか、OpenAI互換APIへ向けるための環境変数が設定されているかだけです。
npm run check:model-specifier
出力は、次のように秘密値を出さずに要点だけ表示します。
{
"model": "openai/preview/Kimi-K2.6",
"validSpecifierShape": true,
"providerId": "openai",
"modelId": "preview/Kimi-K2.6",
"openAiCompatibleBaseUrlConfigured": true,
"openAiCompatibleApiKeyConfigured": true
}
この確認は地味ですが、Agentフレームワークを触るときには効きます。モデル呼び出しの失敗は、provider解決、認証、base URL、モデルID、tool calling、structured outputなど、複数の層に分かれます。最初から全部を一つのflue runで見ると、どこで失敗しているのかが分かりにくくなります。
Agent検証で分けて見るべき層
今回の失敗から、OpenAI互換APIをAgentフレームワークにつなぐときは、少なくとも次の層を分けて見るべきだと感じました。
- Flueがmodel specifierを解決できるか
- provider設定が期待したbase URLへ向いているか
- APIキーが認証を通るか
- 指定したモデルIDを接続先APIが受け付けるか
- そのモデルがtool callingやstructured outputに追従できるか
Unknown model specifierは1番目の問題です。ここで止まっている段階では、モデルの賢さも、OpenAI互換APIの品質も、Agentのプロンプト設計もまだ評価していません。
逆に言うと、ここを切り分けるだけで、その後の検証がかなり楽になります。FLUE_MODELの形が合っていると分かってから、次に認証、次に実モデルID、次にtool callingという順に進められるからです。
まとめ
FlueでOpenAI互換APIを使う場合、API側のモデルIDをそのままAgentに渡すのではなく、Flue側のprovider IDを含めたmodel specifierとして指定します。
FLUE_MODEL="openai/<remote-model-id>"
この一点を外すと、LLMを呼ぶ前にFlueのモデル解決で止まります。Agentの挙動を検証したいときほど、最初に接続経路、次に認証、最後にAgentの品質という順番で切り分けたほうがよさそうです。
正直、Agentの設計に入る前の地味な設定です。ただ、ここを曖昧にしたまま進めると、「モデルが悪いのか」「providerが悪いのか」「Agentの作りが悪いのか」が全部混ざります。こういう地味な境界確認こそ、LLMOpsの記事として残しておく価値がありそうです。