OpenAI互換のLLMプロキシの小さなRubyプロトタイプで、リフィル可能なトークンバケットを使用しています.
Rubyの標準ライブラリのみを使用:Gemは使用せず、Rackも使用せず、WEBrickも使用しません.
実行
BASE_API_URL=http://192.168.0.124:8888/v1 \ BASE_API_KEY=1mmer \ BASE_MODEL=gemma4 \ ruby llm_proxy.rb
プロキシはデフォルトで0.0.0.0:8899でリッスンします.
ローカルLLMの192.168.0.124:8888で、保存されたローカル設定を実行します.
./run_local_proxy.sh
それにより、Rubyプロキシが起動しますhttp://127.0.0.1:8899/v1 と http://192.168.0.124:8888/v1 に送信します。
保存されたローカルのcurlチェックは:
./curl_local_proxy.sh
手動相当:
curl -sS -i -m 60 http://127.0.0.1:8899/v1/chat/completions \ -H 'Authorization: Bearer user-a' \ -H 'Content-Type: application/json' \ -d '{ "model": "gemma4", "messages": [{"role": "user", "content": "Reply with exactly: proxy ok"}], "max_tokens": 16 }'
プロキシを通じて検証結果:アップストリームは proxy ok で返答し、プロキシはローカルテストバケットで X-RateLimit-Remaining: 0 を返しました。
スモークテストを実行します:
ruby test_llm_proxy.rb
トークンバケット設定
MAX_TOKENS=10 # max saved tokens per user REFILL_TOKENS=2 # tokens added each refill REFILL_INTERVAL_SECONDS=300 # 5 minutes REQUEST_TOKEN_COST=1 # cost per accepted completion request
各々のバリアントトークンは独自のバケットを取得します。バリアントトークンなしのリクエストはリモートIPでバケット化されます。プロキシが未知のクライアントキーを拒否する場合、PROXY_API_KEYS=key1,key2を設定してください。
バケットが空の場合、/v1/chat/completionsと/v1/completionsは通常のOpenAIスタイルのアシスタントレスポンスを返します:
limit reached, wait 5 min
テストリクエスト
curl http://localhost:8888/v1/chat/completions \ -H 'Authorization: Bearer user-a' \ -H 'Content-Type: application/json' \ -d '{ "model": "anything", "messages": [{"role": "user", "content": "hello"}] }'
オプションで推定トークンモード
デフォルトでは、1つの完了リクエストはREQUEST_TOKEN_COSTバケットトークンがかかります。プロンプトのサイズと予想される出力に応じて概算で料金を請求します:
TOKEN_COST_MODE=estimate RESPONSE_TOKEN_RESERVE=256 ruby llm_proxy.rb
これはプロトタイプのための近似値です。












