📌

LiteLLMを使ったLLMの集約 & 簡易的なKey管理 + langfuse添え

に公開

プライベートなLLM API、会社利用でのAPI、LocalLLMなど、LLMを使うだけでもいろいろなエンドポイントがあり管理が煩雑になる、あると思います。
そういったことへの対策として、いろいろなところでLiteLLMに関する記事はありますが、Keyの管理についてはあまり触れられていないようなので簡単にまとめておきます。

LiteLLMとは

https://docs.litellm.ai/

LiteLLMは、LLMプロバイダーへのアクセスを統一的なインターフェースで提供するOSSです。LiteLLM Proxy Server (LLM Gateway) として起動することで、個々のLLMプロバイダーのAPI仕様の違いを意識することなく、OpenAI互換の形式でリクエストを送信し、様々なモデルを利用できるようになります。
加えてLiteLLM Proxyは、単なるAPIの抽象化に留まらず、認証、認可、使用状況の追跡、コスト管理、レート制限、キャッシュ、モデルルーティングといった、エンタープライズレベルの運用機能を提供しており、きちんと設定すればプライベート利用にとどまらない利用ができる気がします。

今回はあくまで個人利用の範囲で紹介します。

LiteLLMの起動 (コンテナ起動)

https://docs.litellm.ai/docs/proxy/deploy

ここを読もう!呼んで、設定して、docker-compose up -d、これでOKです。

…だけだと寂しいので、大雑把に実施した環境変数の設定とconfig.yamlを以下に書きます。なお、config.yamlを読み込むようにするにはdocker-compose.yamlでコメントアウトされているvolume設定を有効にする必要があります。

環境変数

https://docs.litellm.ai/docs/proxy/config_settings#environment-variables---reference

設定できる一覧は上記にリストアップされています。私は以下のように設定しました。

.env
LITELLM_MASTER_KEY="sk-1234"
LITELLM_SALT_KEY="sk-1234"
DATABASE_URL = "postgresql://llmproxy:dbpassword9090@db:5432/litellm"
STORE_MODEL_IN_DB = "True"

LANGFUSE_PUBLIC_KEY="pk-lf-XXXX"
LANGFUSE_SECRET_KEY="sk-lf-XXXX"
LANGFUSE_HOST="http://localhost:8000"

上4つは公式リポジトリの記載ママです。Master Keyを変更したい場合はここで設定します。SALT Keyは、LiteLLMがAPIキーを暗号化するために使用されます。これも適宜変更してください。公式では1passwordのパスワードジェネレータ使えという推奨があります。

今回追加で設定したのはしたの3つです。これを設定すると、LangfuseがLiteLLMと連携できるようになります。個別にトレース設定をしなくても、LiteLLMを経由したリクエストは自動的にLangfuseに記録されます。基本的にはリクエスト単位の記録になるのでアプリケーションレベルでのトレース構造にはなりませんが、個人利用の範囲では十分なので設定しています。

config.yaml

やるべきことは、集約するモデルの設定と、その他のグローバルなLiteLLM設定を行うことです。

config.yaml
model_list:
  - model_name: claude-3-haiku
    litellm_params:
      model: bedrock/anthropic.claude-3-haiku-20240307-v1:0
      aws_region_name: ap-northeast-1
  - model_name: gpt-4o
    litellm_params:
      model: azure/gpt-4o
      api_base: https://****.openai.azure.com/
      api_version: "2025-01-01-preview"
      api_key: XXXX
  - model_name: deepseek-R1
    litellm_params:
      model: openrouter/deepseek/deepseek-r1
      api_key: sk-or-XXXX
  - model_name: ollama_chat/qwen3:4b
    litellm_params:
      model: ollama_chat/qwen3:4b
      api_base: "http://host.docker.internal:11434"

litellm_settings:
  drop_params: True
  success_callback: ["langfuse"]
  redact_user_api_key_info: true

私は、Bedrock、Azure OpenAI、OpenRouter、Ollamaのモデルを集約しています。各モデルの設定は、litellm_paramsで指定します。
Bedrockはaws configureで設定したプロファイルを利用可能な状態にすれば (例えばホストの.awsをvolumeにマウントするなど)、モデル名とリージョンの設定のみで利用可能です。
Ollamaは別のコンテナで起動しているLangfuseに接続することにしたため、コンテナからホストにアクセスするように指定しています。この設定でOllamaが起動していれば、LiteLLM経由でOllamaのモデルを利用できました。

litellm_settingsでは、LiteLLMの動作に関する設定を行います。drop_paramsはリクエストパラメータを削除するかどうか、success_callbackは成功したリクエストのコールバック先を指定します。ここではLangfuseを指定することで、リクエストのトレース情報をLangfuseに送信しています。redact_user_api_key_infoは、ユーザーのAPIキー情報をマスクするための設定です。

models
登録したモデルはこんな感じで一覧で見れる

Keyの管理

LiteLLMでは、APIキーの管理を簡単に行うことができます。

認証方法自体はOAuth2.0での認証やカスタム設定もできるようです。様々な認証方式をサポートするということは、LiteLLMが単なるAPIゲートウェイではなく認証・認可の機能も持っており、認証された主体がどのモデルにアクセスできるか、どれだけの量をどの程度の頻度で利用できるか、といったポリシーを適用できることを意味します。組織的なID管理やセキュリティポリシーと深く統合できるということですね。

一方で、個人利用の範囲ではそこまでの重量級の機能は必要なく、APIキーを直接管理するのが簡単でリーズナブルな気がしています。特にMaster KeyとVirtual Keyによる階層的なキー管理は、セキュリティと運用効率のバランスの取れた方法ではないでしょうか。

Master Key

Master Keyは、LiteLLMの管理者が持つキーで、全ての管理権限を持ちます。
これを指定すればあらゆるリクエストを実行できるため、よく注意して管理する必要があると思います。

設定方法

Master Keyは、主に以下の方法で設定できました。

  • config.yaml での設定

前述の通り、config.yamlに以下のように設定することでMaster Keyを指定。

config.yaml
general_settings:
  master_key: "sk-yourMasterKey12345"
  • 環境変数での設定

環境変数 LITELLM_MASTER_KEY を設定することでもMaster Keyを指定。

.env
LITELLM_MASTER_KEY="sk-yourMasterKey12345"

できること

基本的にはすべてのコントロール権を持つキーです。具体的には以下のような操作が可能です。

  • Virtual Keyの管理
    • 新規Virtual Keyの発行 (/key/generate エンドポイント)
    • 既存Virtual Keyの情報照会 (/key/info エンドポイント)
    • Virtual Keyの更新 (/key/update エンドポイント、例: 予算増額、ガードレール設定)
    • Virtual Keyの無効化/ブロック (/key/block エンドポイント)
    • Virtual Keyの削除
  • ユーザー管理
    • 新規ユーザーの作成 (/user/new エンドポイント)
    • ユーザー情報の照会 (/user/info エンドポイント)
    • ユーザーの削除 (/user/delete エンドポイント)
  • チーム管理
    • 新規チームの作成 (/team/new エンドポイント)
    • チーム情報の照会 (/team/info エンドポイント)
    • チームへのコールバック設定(ロギングなど) (/team/callback エンドポイント)
  • モデル管理
    • プロキシで利用可能なモデルの追加、更新、削除(CLI経由など)
  • 認証情報管理
    • LLMプロバイダーの認証情報(APIキーなど)の管理(CLI経由など)
  • 管理UIおよびCLIからの操作
    • LiteLLM Proxy UIを介した各種管理操作のバックエンド認証
    • litellm-proxy CLIを用いた管理コマンド実行時の認証
  • Master Key自体の管理
    • Master Keyのローテーション (/key/regenerate エンドポイント)

Master Keyのローテーション

ベストプラクティスとして、Master Keyは定期的にローテーションすることが推奨されているようです (私はそもそも外部公開していないし、面倒なのでやっていませんが)。
万が一の漏洩時にも被害を最小限に抑えることができるので良い設計ですね。こんな感じで利用できるようです。

curl -L -X POST 'http://localhost:4000/key/regenerate' \
-H 'Authorization: Bearer <current-master-key>' \
-H 'Content-Type: application/json' \
-d '{
    "key": "<current-master-key>",
    "new_master_key": "<new-master-key>"
}'

Virtual Key

Virtual Keyは、LiteLLM Proxyを利用するクライアントアプリケーションやエンドユーザーに発行されるAPIキーであり、実際のLLMリクエストの認証と認可を担います。
Master Keyがプロキシ全体の管理を司るのに対し、Virtual Keyはより限定的な権限を設定できます。こういったあたりを作り込まなくても、composeでぱぱっと起動して使い始められるのがLiteLLMの良いところですね。

作成方法

API (/key/generate)、CLI、Web UIのいずれかからVirtual Keyを作成できます。Web UIからの作成は、LiteLLM Proxyの管理UIにアクセスしVirtual Keys → Create New Keyを選択します。

Virtual Key作成
Virtual Keyの作成画面

この画面を見るとわかるように、以下のような内容を個別に設定できます。社内でLLMのAPI基盤を作ったり、部署ごとにバジェットコントロール、クォータコントロールをしたりする場合には変にスクラッチで作るよりLiteLLMを使ったほうが多分セキュアで楽ですね。

設定値 設定例 説明
Models ["gpt-3.5-turbo", "gpt-4"] アクセスを許可するモデルのリスト
Aliases {"gpt-4-alias": "gpt-4"} モデル名のエイリアス
Duration 30d 有効期間
Max Budget 100.0 最大利用予算 (USD)
TPM Limit 10000 1分あたりの最大トークン数
RPM Limit 100 1分あたりの最大リクエスト数
User ID user-123 関連付けるユーザーID
Team ID team-abc 関連付けるチームID
Metadata {"project": "alpha"} カスタムメタデータ
Key Alias my-project-key キーのエイリアス(管理用の表示名)
Guardrails ["pii-masking"] 適用するガードレールのリスト

利用方法

OpenAI API互換の形式でリクエストを送信することで、LiteLLM ProxyはVirtual Keyを使用するだけです。

認証が通ってかつ、許可されたモデルに対してはリクエストが通ります。

認証が通るとき
$ curl -X POST http://localhost:8000/chat/completions \
  -H "Authorization: Bearer sk-****" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-4o",
    "messages": [
      {
        "role": "user",
        "content": "こんにちは、調子はどうですか?"
      }
    ]
  }'

{
  "id": "chatcmpl-BhYvissWugcPiamCNtaVTVdEAbkrY",
  (...中略...)
  "choices": [
    {
      "finish_reason": "stop",
      "index": 0,
      "message": {
        "content": "こんにちは!私はAIなので体調の概念はありませんが、きちんと動作しています。何かお手伝いできることはありますか?",
        "role": "assistant",
        "tool_calls": null,
        "function_call": null,
        "annotations": []
      }
    }
  ],
  (...中略...)
}

一方で、Virtual Keyで許可されていないモデルに対してリクエストを送信すると、認証は通ってもリクエストは拒否されます。

認証が失敗したとき
$ curl -X POST http://localhost:8000/chat/completions \
  -H "Authorization: Bearer sk-****" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-3-7-sonnet",
    "messages": [
      {
        "role": "user",
        "content": "こんにちは、調子はどうですか?"
      }
    ]
  }'

{
  "error": {
    "message": "key not allowed to access model. This key can only access models=['gpt-4o']. Tried to access claude-3-7-sonnet",
    "type": "key_model_access_denied",
    "param": "model",
    "code": "401"
  }
}

ちなみに、ここでAuthorizationヘッダにMaster Keyを指定すると全部通ります。

Langfuseとの連携

LiteLLMとLangfuseを連携させると、LiteLLMを経由したリクエストのトレース情報をLangfuseに自動的に記録されます。こんな感じ。

Langfuseとの連携
Langfuseのトレース画面

前述の通り、アプリケーション単位のトレースではなく、LiteLLMを経由したリクエスト単位のトレースになりますが、個人利用の範囲では十分な情報が得られます。

具体的にどんなリクエストが発生したんだっけ?、トークン数どのくらいだっけ?、なんか挙動おかしいけどちゃんとリクエスト通ってるの?、といった、見たいけどぱっと取るのがいまいち面倒な情報が確認できるので、雑にLLM使いたいだけ勢としてはちょうどいい塩梅だと思ってます。

もうちょっと設定したらいい感じでトレースの仕方も変えられたりするのかもしれないですが、個人的な需要がないので今回はここまで。

…まぁ、LangGraphとか使うときはそれはそれでトレース設定したりするんですが😛。

まとめ

LiteLLMを使うことで、複数のLLMプロバイダーへのアクセスを統一的に管理できるだけでなく、APIキーの管理も簡単に行えるようになります。ついでにLangfuseも連携させられます。

というお話でした。

とある通信会社の有志

Discussion