メインコンテンツへスキップ
openai-serve は、OpenAI API の一部を実装する小さな HTTP ゲートウェイです。 受け取ったリクエストをローカルの lcpd-grpcd(Requester)へ gRPC で転送します。 Requester は Lightning 接続、見積もり(quote)/支払い、結果取得を担います。 これにより、既存の OpenAI 互換クライアント(SDK / LangChain / curl など)は、主に base_url を切り替えるだけで LCP 上の Provider にリクエストを投げられます。

アーキテクチャ

OpenAI SDK / curl
   |
   |  HTTP(OpenAI互換)
   v
openai-serve
   |
   |  gRPC(LCPDService)
   v
lcpd-grpcd(Requester)  --- Lightning --- Provider peer(lcpd-grpcd Provider)
ポイント:
  • openai-serve は意図的にステートレスで、Lightning へ直接接続しません。
  • sats を支払う権限を持つのは Requester(lcpd-grpcd)です。

ログとプライバシー

ログはセンシティブとして扱います。openai-serve は、生のユーザー入力を永続化しなくても診断できるように設計しています。
  • ログには、生のプロンプト(messages[].content)や生のモデル出力を残してはいけません。
  • ログは運用メタデータ(model/peer/job id、価格、時間、byte/token カウント)のみに寄せます。
  • OPENAI_SERVE_LOG_LEVEL=debug はリクエストログがより詳細になります。運用では(必要になるまで)デフォルトの info を推奨します。

対応エンドポイント

  • POST /v1/chat/completions(JSON または stream:true の SSE パススルー)
  • POST /v1/responses(JSON または stream:true の SSE パススルー)
  • GET /v1/models
  • GET /healthz

クイックスタート

前提: lcpd-grpcd は別プロセスで起動(Requester モード)し、Lightning node と LCP peers に到達できる状態にします。 ビルド:
cd apps/openai-serve
go install ./cmd/openai-serve
起動:
export OPENAI_SERVE_HTTP_ADDR="127.0.0.1:8080"
export OPENAI_SERVE_LCPD_GRPC_ADDR="127.0.0.1:50051"

# 任意: 認証(カンマ区切り)
export OPENAI_SERVE_API_KEYS="devkey1"

openai-serve
動作確認:
curl -sS http://127.0.0.1:8080/v1/chat/completions \
  -H 'content-type: application/json' \
  -H 'authorization: Bearer devkey1' \
  -d '{"model":"gpt-5.2","messages":[{"role":"user","content":"Say hello."}]}'
ストリーミング(Chat Completions):
curl -N http://127.0.0.1:8080/v1/chat/completions \
  -H 'content-type: application/json' \
  -H 'authorization: Bearer devkey1' \
  -d '{"model":"gpt-5.2","stream":true,"messages":[{"role":"user","content":"Say hello."}]}'
ストリーミング(Responses):
curl -N http://127.0.0.1:8080/v1/responses \
  -H 'content-type: application/json' \
  -H 'authorization: Bearer devkey1' \
  -d '{"model":"gpt-5.2","stream":true,"input":"Say hello."}'

CLI ツールから使う

openai-serve は OpenAI Chat Completions / Responses API(stream:true 含む)互換です。 多くの OpenAI 互換 CLI ツールは、base_url と API key を設定することで openai-serve を利用できます。

Codex CLI

Codex CLI を openai-serve に向けるには、カスタムの model provider を定義します(wire format は Chat Completions)。
  1. ~/.codex/config.toml に追記:
[model_providers.openai_serve]
name = "openai-serve"
base_url = "http://127.0.0.1:8080/v1"
env_key = "OPENAI_SERVE_API_KEY"
wire_api = "chat"

[profiles.lcp]
model = "gpt-5.2"
model_provider = "openai_serve"
  1. 実行(API key は openai-serve 側の設定と一致させてください):
export OPENAI_SERVE_API_KEY="devkey1"
codex --profile lcp "Say hello in Japanese."
ストリーミング(stream:true)は SSE としてそのままパススルーします。フィールドのサポート可否は選択された Provider に依存します。

LLM(llm

llm は OpenAI 互換 base URL に向けて実行できます。llm の user directory に extra-openai-models.yaml を作成し、 以下を追加してください:
- model_id: lcp-gpt-5.2
  model_name: gpt-5.2
  api_base: http://127.0.0.1:8080/v1
  can_stream: true
  api_key_name: openai-serve
その後:
llm keys set openai-serve
llm -m lcp-gpt-5.2 "Say hello in Japanese."

リクエスト/レスポンスの挙動

  • openai-serve は Chat Completions / Responses の request/response bytes をそのまま運ぶパススルーゲートウェイです。
  • ルーティング前に最小限の検証のみ行います:
    • body が JSON object であること
    • model が存在し、空でなく、前後に空白がないこと
    • messages(chat)または input(responses)が存在し、空でないこと
    • HTTP Content-Encoding は省略または identity(圧縮されたリクエストボディは拒否)
  • stream:true のとき、text/event-stream の bytes を順次パススルーします。stream なし/false のときは JSON body をまとめて返します。
  • リクエストボディは 1 MiB までです。
  • Provider の結果 bytes はそのまま返し、HTTP の Content-Type / Content-Encoding は LCP result metadata から取得します。
設定、ルーティング、Safety knobs(最大価格、タイムアウト、モデル allowlist)は 設定 を参照してください。

LCP メタデータヘッダ

POST /v1/chat/completionsPOST /v1/responses のレスポンスには以下が含まれます:
  • X-Lcp-Peer-Id: 選択された Provider の peer id
  • X-Lcp-Job-Id: job id(hex)
  • X-Lcp-Price-Msat: 受諾した quote の価格
  • X-Lcp-Terms-Hash: 受諾した quote の terms hash(hex)