> ## Documentation Index
> Fetch the complete documentation index at: https://candy-208aed2d-85.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# openai-serve（OpenAI互換ゲートウェイ）

> OpenAI互換のHTTPサーバ。lcpd-grpcd（Requester）へgRPCで転送します。

`openai-serve` は、OpenAI API の一部を実装する小さな HTTP ゲートウェイです。
受け取ったリクエストをローカルの `lcpd-grpcd`（Requester）へ gRPC で転送します。
Requester は Lightning 接続、見積もり（quote）/支払い、結果取得を担います。

これにより、既存の OpenAI 互換クライアント（SDK / LangChain / curl など）は、主に `base_url` を切り替えるだけで
LCP 上の Provider にリクエストを投げられます。

## アーキテクチャ

```text theme={null}
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 に到達できる状態にします。

ビルド:

```sh theme={null}
cd apps/openai-serve
go install ./cmd/openai-serve
```

起動:

```sh theme={null}
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
```

動作確認:

```sh theme={null}
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）:

```sh theme={null}
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）:

```sh theme={null}
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` に追記:

```toml theme={null}
[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"
```

2. 実行（API key は `openai-serve` 側の設定と一致させてください）:

```sh theme={null}
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` を作成し、
以下を追加してください:

```yaml theme={null}
- 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
```

その後:

```sh theme={null}
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）は
[設定](/openai-serve/configuration-ja) を参照してください。

## LCP メタデータヘッダ

`POST /v1/chat/completions` と `POST /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）
