local-ai-app-integration について
local-ai-app-integrationは、既存アプリにLemonadeをプライベートなサブプロセスとして組み込み、ローカルAIモードを追加する手順を案内します。クラウドAIのHTTP APIを利用中で、推論エンジンをアプリに同梱したい開発者向けです。
主な機能
- 01既存のAI API呼び出しの調査
- 02モダリティに応じたモデルとバックエンドの選択
- 03アプリ内へのLemonadeパッケージ配置
- 04lemondサブプロセスの起動と監視
- 05クライアントの接続先変更とエラー処理
活用シーン
- 01既存アプリへのローカルAIモード追加
- 02アプリのチャットクライアントとローカルlemondの接続
- 03モデルとバックエンドのアプリへの同梱
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ amd/ skills --skill local-ai-app-integrationインストール後、Claude Code で/local-ai-app-integrationを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
.federated.jsonreference.mdskill-card.mdevals/evals.jsonevals/files/apikey-guard/main.pyevals/files/openai-stub/main.py詳細
ローカル AI アプリの統合(埋め込み型 Lemonade)
クラウド AI API(OpenAI、Anthropic、または Ollama 互換)をすでに利用しているアプリに、ローカル AI モードを追加します。アプリは Embeddable Lemonade バイナリである lemond を専用のサブプロセスとして起動し、既存のクライアントは http://localhost:PORT/api/v1 に接続します。ユーザーは別途インストールすることなく、ローカルでプライベートな、ハードウェアに最適化された推論(CPU、AMD iGPU/dGPU、XDNA2 NPU)を利用できます。
最終的に追加・変更するもの: 新しいランチャーモジュール(約 30 行)、既存の HTTP クライアントへの必須変更 3 つ(base_url、api_key、120 秒の HTTP タイムアウト)、vendor/lemonade/ に格納するベンダーバイナリ 1 つ。
このスキルが適しているケース
次の条件をすべて満たす場合に、このスキルを使用してください。
- アプリがすでに OpenAI Chat Completions、Anthropic Messages、または Ollama などのクラウド AI サービスを HTTP 経由で呼び出している。
- ユーザーは、その AI エンジンをアプリにバンドルし、別途インストールすることなく、エンドユーザーの PC で実行したい。
- 対象プラットフォームが Windows x64 または Linux x64 である(macOS 版の埋め込み機能はベータ版です)。
ユーザーがシステム全体で使う Lemonade Server(1 回インストールし、複数のアプリで共有)を希望する場合は、このスキルを使用せず、https://lemonade-server.ai/install_options.html と標準の OpenAI ベース URL http://localhost:13305/api/v1 を案内してください。
推奨する手順
このスキルでは、手順が 1 つに定められています。理由を明示せずに変更しないでください。
[ ] 1. Survey the app's current AI integration
[ ] 2. Pick a model + backend profile
[ ] 3. Place Embeddable Lemonade in the app's tree (full package, not just the binary)
[ ] 4. Add a `lemond` launcher (subprocess + API key + port + per-stage logging)
[ ] 5. Re-point the existing client at lemond (base_url, api_key, 120s timeout — all three required)
[ ] 6. Wait for /api/v1/health, install backend, then PULL the model before first use
[ ] 7. Wire shutdown and error recovery
次のチェックリストで進捗を確認してください。各手順の検証が済んでから、次に進んでください。
すべての段階をログに記録してください。 ローカル統合には、プロセス起動、ヘルスチェック、バックエンドのインストール、モデルのダウンロード、初回推論など、気づきにくい失敗箇所が数多くあります。各遷移でログを出さなければ、「何も起きなかった」のか「手順 3 で失敗した」のか区別できません。実装中は段階ごとに明確なログを 1 行出してください(手順 4 を参照)。この統合で最もよくある行き詰まりは、エラーが出ずに結果が空になることです。ログがなければ原因を特定できません。
手順 1:アプリを調査する
アプリが現在クラウド AI API を呼び出している箇所をすべて探します。リポジトリ内を次のキーワードで検索してください。
openai、OpenAI(、chat.completions、responses.createanthropic、Anthropic(、messages.createapi.openai.com、api.anthropic.com、localhost:11434(Ollama)OPENAI_API_KEY、ANTHROPIC_API_KEY
続行する前に、次の 4 点を記録してください。
- クライアントライブラリと言語(例:
openai-python、openai-node、@anthropic-ai/sdk、go-openai、生のfetch)。 - 使用するモダリティ: テキストチャット、ツール呼び出し、埋め込み、画像生成、文字起こし、TTS。これをもとに、手順 2 でモデルとバックエンドを選びます。
- ベース URL と API キーを構築する単一の場所。そのような場所がなければ、先に 1 か所にまとめてください。ローカルモードへの切り替えは、設定オブジェクト 1 つだけを変更する必要があります。
- キーの入力前にアプリをブロックするAPI キーの必須チェック(初回設定画面、空のキーを拒否するバリデーター、キーが存在するまで AI を無効にする起動時チェックなど)。それぞれ記録してください。手順 5 でローカルモード時に回避します。
ステップ 2:モデルとバックエンドプロファイルを選択する
アプリの主なモダリティに基づいて、デフォルトプロファイルを1つ選択します。選択肢を並べ立てないでください。適切なデフォルトを1つ用意し、ユーザーが変更する方法を説明してください。
| アプリの主なニーズ | デフォルトモデル | レシピ | 理由 |
|---|---|---|---|
| 一般的なチャット/アシスタント | Qwen3-4B-GGUF | llamacpp | 小型で高速、ツール呼び出しに優れ、8GB システムで動作 |
| コーディングアシスタント | Qwen2.5-Coder-7B-Instruct-GGUF | llamacpp | 高いコーディング性能、iGPU で動作 |
| ビジョン/マルチモーダルチャット | Gemma-4-E2B-it-GGUF | llamacpp | 小型のマルチモーダルなデフォルト |
| Ryzen AI で NPU を優先 | Llama-3.2-3B-Instruct-Hybrid | ryzenai-llm | Windows の XDNA2 NPU |
| 音声テキスト変換(Windows) | Whisper-Large-v3-Turbo | whispercpp | モデルは1つ。プローブが NPU → iGPU/dGPU → CPU を自動選択 |
| 音声テキスト変換(Linux NPU) | whisper-v3-turbo-FLM | flm | Linux の NPU 経路。NPU を使わない場合は whispercpp の iGPU/CPU にフォールバック |
| テキスト音声変換 | kokoro-v1 | kokoro | CPU のみ、低レイテンシ |
| 画像生成 | SDXL-Turbo | sd-cpp | 1ステップで生成 |
LLM バックエンドは llamacpp をデフォルトとし、llamacpp_backend を未設定にすることで、lemond が rocm → vulkan → cpu を自動的に選択するようにします。アプリに厳密なハードウェア要件がある場合にのみ上書きしてください。
対象範囲:このスキルは、開発者のマシンで統合時に一度だけバックエンドを選択します。 エンドユーザーのハードウェアに基づく実行時のフォールバックは対象外です。どのマシンでもアプリが動作するよう、汎用フォールバックとして vulkan をバンドルしてください。開発者のマシンに NPU があり、選択したレシピが対応している場合、スキルは NPU バックエンドを使用します。それ以外の場合は vulkan にフォールバックします。
注: NPU があっても、すべてのレシピが NPU に対応しているわけではありません。採用を決める前に、
GET /api/v1/system-infoでレシピとバックエンドの組み合わせがinstalledまたはinstallableであることを確認してください。レシピごとの判断基準については、reference.md を参照してください。
その他の選択肢やトレードオフについては、reference.md を参照してください。
ステップ 3:Embeddable Lemonade をアプリのディレクトリツリーに配置し、バックエンドをインストールする
最新の Lemonade リリースから埋め込み用アーティファクトを取得します。
https://github.com/lemonade-sdk/lemonade/releases/latest
対象 OS に合ったファイルをダウンロードします。
- Windows:
lemonade-embeddable-{VERSION}-windows-x64.zip - Linux:
lemonade-embeddable-{VERSION}-ubuntu-x64.tar.gz
タグからダウンロード URL を手作業で組み立てないでください。 Git タグには先頭に
vが付きます(例:v10.8.0)が、アセットのファイル名では省かれます(lemonade-embeddable-10.8.0-...)。そのため、タグをそのまま使うと 404 になります。以下のように、GitHub API に安定した名前パターンでアセットを問い合わせ、返された URL を使ってください。これならバージョンや命名が変わっても正しく動作します。
まず、配置先のディレクトリを作成します。新規リポジトリにはまだ存在しません。
# Windows
New-Item -ItemType Directory -Force vendor\lemonade
# Linux
mkdir -p vendor/lemonade
続いて、Windows ではダウンロードして展開します(PowerShell)。
$rel = Invoke-RestMethod https://api.github.com/repos/lemonade-sdk/lemonade/releases/latest
$asset = $rel.assets | Where-Object { $_.name -like "lemonade-embeddable-*-windows-x64.zip" } | Select-Object -First 1
Invoke-WebRequest $asset.browser_download_url -OutFile lemond.zip
Expand-Archive lemond.zip -DestinationPath "$env:TEMP\lemond-unpack"
$folder = $asset.name -replace '\.zip$','' # unpacked dir = asset name without .zip
Copy-Item -Recurse "$env:TEMP\lemond-unpack\$folder\*" vendor\lemonade\
# Sanity check: resources/ must be nested under vendor\lemonade\ (not flattened)
if (-not (Test-Path vendor\lemonade\resources\*.json)) { throw "resources/ missing — re-extract and copy again" }
Linux では次のようにします(bash)。
URL=$(curl -s https://api.github.com/repos/lemonade-sdk/lemonade/releases/latest \
| grep browser_download_url | grep ubuntu-x64.tar.gz | cut -d'"' -f4)
curl -L "$URL" | tar -xz --strip-components=1 -C vendor/lemonade
バイナリだけでなく、パッケージ全体をコピーしてください。 アーカイブには
lemond[.exe]、lemonade[.exe]、LICENSE、resources/が含まれています。resources/ディレクトリは必須です。これがないと、lemond は起動してヘルスチェックに合格するものの、すべてのモデルおよびバックエンドリクエストに失敗します。バイナリだけをコピーすると、正常に見えても機能しないサーバーになります。lemondとlemonadeCLI の違い:lemondはアプリに同梱される組み込みサーバーのバイナリです。lemonadeCLI は別個のパッケージングツールで、開発時またはビルド時にバックエンドをインストールするためだけに使用します。上記で展開した同じ組み込み可能なアーカイブには、lemond[.exe]の隣に対応するlemonade[.exe]も含まれているため、バージョンは同梱のlemondと一致します。入手するためにpip install lemonade-sdkを実行しないでください。PyPI パッケージは別の古いリリース系列で、ポート、モデル名、インストール API がここに同梱されるlemondと一致せず、両者を混在させると、バージョンの不一致が気付かれないまま発生することが確認されています。この手順でダウンロードした同じリリースのlemonadeCLI、lemond、バックエンドをすべて使用し、バージョンを一致させてください。
セットアップ後(初回起動+バックエンドのインストール)の想定レイアウトです。展開したばかりのパッケージに含まれるのは lemond[.exe]、lemonade[.exe]、LICENSE、resources/ のみです。以下の項目は、コメントにあるとおり、後から作成されます。
vendor/lemonade/
lemond[.exe] # the only binary the app ships
LICENSE
config.json # generated on first run; commit a seed copy
resources/
server_models.json # do not edit; use GET /api/v1/models at runtime
backend_versions.json
bin/ # backends bundled at packaging time
llamacpp/vulkan/llama-server[.exe]
models/ # pre-bundled model weights (optional)
models--unsloth--Qwen3-4B-GGUF/
server_models.json: このファイルを編集したり、参照したりしないでください。内容が古い可能性があります。唯一の信頼できるモデル一覧は、バックエンドをインストール済みの実行中のlemondインスタンスに対するGET /api/v1/modelsの結果です。
バンドル内容の決定:慎重に選択してください
- バックエンド: パッケージング時に
llamacpp:vulkanをバンドルします(すべての GPU で動作します)。AMD 対応システムでは、初回起動時にGET /api/v1/system-infoで確認してから、POST /api/v1/installを使用してllamacpp:rocmをインストールします。すべてのバックエンドを同梱すると、成果物が肥大化するため避けてください。 - モデル:
models/の下にデフォルトモデルをバンドルする(オフラインインストールが可能ですが、インストーラーが大きくなります)か、初回起動時にPOST /api/v1/pullで取得する(インストーラーは小さくなりますが、ネットワークが必要です)かを選択します。どちらかを選び、ドキュメントに記載してください。 models_dir: 重みをアプリ内に保持するには、config.jsonで./modelsに設定します。他のアプリと重みを共有したいとユーザーが明示的に希望する場合に限り、autoのままにしてください。
バックエンドのインストール時期 — 2 つの異なる方法:
パッケージング時(開発者のマシン、バンドル前)。同梱する
lemondとバージョンを一致させるため、vendor/lemonade/内にある同梱の lemonade CLI を使用します(./またはフルパスを先頭に付けます)。vendor/lemonade/lemonade backends install llamacpp:vulkan vendor/lemonade/lemonade backends install flm:npu # Windows NPU の場合のみこれにより、アプリの出荷前にバックエンドのバイナリが
vendor/lemonade/bin/に組み込まれます。lemondを実行しておく必要はありません。同梱のlemondとバージョンが一致する最新のlemonadeCLI を使用してください(展開したアーカイブ内のコピーが使えます)。pip install lemonade-sdkは使用しないでください。初回起動時/実行時(ユーザーのマシン、
lemondの起動後):POST /api/v1/install {"recipe": "llamacpp", "backend": "rocm"}これを、どの環境にも一律にバンドルできないハードウェア固有のバックエンド(例:
llamacpp:rocm)に使用します。lemondがすでに起動している必要があります(ステップ 4 の完了後)。
ステップ 4:lemond ランチャーを追加する
新しいモジュール lemond_launcher.py(またはアプリの言語に合わせて
lemond_launcher.<ext>)としてランチャーを作成します。これは薄いプロセス
スーパーバイザーです。役割は次のとおりです。
- 新しいランダムな API キーを生成します:
key = secrets.token_urlsafe(32) - 使用可能な localhost ポートを選びます:
socketをポート 0 にバインドし、割り当てられたポートを読み取ってから、ソケットを閉じます。 - lemond を
subprocessとして起動します:subprocess.Popen([LEMOND_BIN, LEMOND_DIR, "--port", str(port)], env={**os.environ, "LEMONADE_API_KEY": key}) Authorization: Bearer {key}を付けてGET /api/v1/healthをポーリングし、HTTP 200 が返るまでループします。これが唯一の正しい準備完了チェックです。- 選択した
portとkeyをアプリのほかの部分から使えるようにします。
ライフサイクルの各段階で 1 行ずつログを出力してください。 最初からロギングを組み込み、 問題が発生してから付け足すのではなく、各段階で記録されるようにします。目標とする出力は次のとおりです。
[lemond] Starting on port <port> [lemond] Healthy on port <port> [lemond] <recipe>:<backend> installed (or: already installed / install failed) [lemond] Pulling model <name>... then: Model <name> ready (or: pull returned <status>) [local] <modality> result: <value> (first inference output — empty string here = unpulled model)最初の推論結果をそのまま記録することで、ステップ 6 の無出力の失敗が、 何時間も原因が分からない状態ではなく、1 行で診断できるようになります。これらのログは アプリの通常のロギング経由で出力し、リリース時には抑制できるようにしてください。
開発モードのファイルウォッチャー: アプリがソースツリーを監視する ファイルウォッチャー(Tauri、Electron、Next.js、Vite など)を使う場合は、 監視対象のパスから
vendor/lemonade/を除外してください。Lemond は実行時に設定ファイルと キャッシュファイルを書き込みます。これらを検出したウォッチャーはアプリを再起動し、 lemond サブプロセスを終了して、新しいポートで再び起動します。その結果、実行中の文字起こしが 気づかれないまま中断されます。テストの前に、ウォッチャーの除外リストへvendor/(または同等のパス)を追加してください。
reference.md § Reference launchers のリファレンス実装をそのまま使用してください。内容を変更せずにコピーし、LEMOND_DIR のパスだけを調整します。ランチャーを一から作成しないでください。リファレンスの Python ランチャーは API キーに secrets、空きポートの確認に socket、lemond の起動に subprocess を使用します。Node.js ランチャーは標準ライブラリの同等のモジュールを使用します。どちらもポート競合時の再試行とヘルスチェックのポーリングを正しく処理します。
準備完了の判定は、常に正確なエンドポイント
GET http://127.0.0.1:<port>/api/v1/health をポーリングし、HTTP 200 が返るかどうかで行います。lemond の標準出力や標準エラー出力を読んで判定してはいけません。作成するヘルスチェック用ヘルパーは、必ず /api/v1/health パスにアクセスしてください。
Step 5: 既存のクライアントの接続先を lemond に変更する
アプリの既存のクライアント構築に3つの変更を加えます。いずれも必須であり、省略できません。
base_urlをhttp://127.0.0.1:{port}/api/v1に設定しますapi_keyをランチャーキーに設定します- HTTP タイムアウトを120秒に設定します — これは必須であり、省略できません
120秒のタイムアウトは、調整の目安ではありません。多くの HTTP クライアントのデフォルト値は30秒ですが、実機では lemond の初回モデル読み込みにかかる時間より短い値です。設定しないとリクエストが気づかないうちにタイムアウトし、UI に何も表示されません。そのため、連携が壊れている場合と区別がつきません。
Python(openai)— 変更内容:
import httpx
from openai import OpenAI
proc, key, port = start_lemond()
client = OpenAI(
base_url=f"http://127.0.0.1:{port}/api/v1",
api_key=key,
http_client=httpx.Client(timeout=120), # required: 120s for first-run model load
)
その他のクライアントの場合:
| 既存のクライアント | 新しい base_url | 新しい認証方法 | タイムアウト |
|---|---|---|---|
openai-python | http://127.0.0.1:{port}/api/v1 | api_key=key | httpx.Client(timeout=120) |
openai-node | http://127.0.0.1:{port}/api/v1 | apiKey: key | timeout: 120000 |
@anthropic-ai/sdk | http://127.0.0.1:{port}/api/v1 | apiKey: key | timeout: 120000 |
fetch / requests の直接呼び出し | 同じ | Authorization: Bearer {key} | リクエストごとに設定 |
| Ollama 互換コード | http://127.0.0.1:{port}/api/v0 | キーも渡す | 120秒 |
リクエストのモデル識別子には、クラウドのモデル名ではなく、Lemonade のモデル名(例:Qwen3-4B-GGUF)を引き続き使用します。
ローカルモードでは、クラウド API キーは一切必要ありません。 これは例外的なケースではなく、ローカルモードの基本的な特性です。認証先となるクラウドサービスがないため、ユーザーにキーを求めることは決してありません。キーを要求するオンボーディング画面、バリデーター、起動時チェックは、ローカルモードのユーザーをブロックしてはなりません。具体的には、次のとおりです。
- ローカルモードでは、キー入力画面をスキップするか、自動的に完了させます。
- すべての検証処理でローカルモードを認証済みとして扱います。空のキーのチェックでは、アクティブなモードがローカルの場合は「有効」として処理を終了し、「API key not configured」を決してスローしないようにします。
- ゲートを再び有効にするのは、クラウドモードの場合に限ります。
Step 4 の lemond キーはランチャーによって内部的に生成され、ローカルのループバック接続にのみ使用されるため、ユーザーに表示されたり入力を求められたりすることはありません。そのため、UI のプレースホルダー(例:"local")は何でもかまいません。ローカルモードに切り替えたとき、ユーザーがキー入力画面で行き詰まることがあってはなりません。
Step 6: 初回推論の前に、ヘルスチェック、バックエンド、モデルのダウンロードを済ませる
GET /api/v1/health が200を返すということは、サーバーが起動していることを示します。推論が機能することを意味するわけではありません。最初の実際のリクエストが成功する前に、さらに3つの条件を満たす必要があります。使用するモダリティのバックエンドがインストールされていること、モデルの重みがディスクにダウンロードされていること、そして(初回の呼び出し時に)モデルがメモリに読み込まれることです。ヘルスチェックが200なら「準備完了」とみなすことが、連携が壊れているように見える最大の原因です。
起動時に POST /api/v1/load を呼び出さないでください。 Lemond は最初の推論リクエスト時にモデルを遅延読み込みし、その処理を自動で行います。事前読み込みは lemond のバージョンによって動作が安定しません(/load リクエストのボディ形式はリリース間で変更されています)。また、不正な呼び出しにより、ユーザーが何も操作する前にサーバーがクラッシュしたり、不安定になったりすることがあります。lemond に遅延実行させるのは読み込みの手順だけです。ダウンロードは遅延させないでください。
モデルをダウンロードしてディスク上に配置する
レイジーロードでは、すでにダウンロード済みの重みのみがロードされます。モデルを一度もプルしていない場合、最初の推論でエラーにはならず、lemond は HTTP 200 とともに空の/未入力の結果を返します。そのため、ヘルスチェックに成功し、バックエンドをインストールしたら、あらかじめモデルをプルしてください。
POST /api/v1/pull
{"model": "Whisper-Large-v3-Turbo"}
これは冪等です。重みがすでに存在する場合は何もせず、存在しない場合はダウンロードします。セットアップ中(バックエンドのインストール後、ユーザーが最初の推論を実行する前)に一度実行し、結果をログに記録してください。
- デフォルトモデル(ステップ 2 で選んだモデル):上記のように名前を指定してプルします。
- **カスタムモデル/ユーザーが上書きしたモデル:**存在すると思い込まないでください。まず
GET /api/v1/modelsを使って、実在する Lemonade モデルであることを確認してから(唯一信頼できるカタログです。reference.md を参照)、同じ方法でプルします。カタログにモデルが表示されても、重みがダウンロード済みである証拠にはなりません。プルに成功して初めて確認できます。
**何も表示されない場合、ほとんどはモデルがプルされていません。**推論が HTTP エラーなしで空文字列/空の出力を返す場合、モデルはダウンロードされていません。ほかのことをデバッグする前に、プルの手順を確認してください。これは最も多くの時間を浪費する失敗モードです。プルの結果と最初の推論結果(ステップ 4 を参照)をログに記録し、推測に頼らずコンソールから原因を特定できるようにしてください。
モデルのロードだけでなく、セットアップの全体を表示する
初回のコールドスタートで必要なのは、モデルのロードだけではありません。全体の手順は次のとおりです。
server spawn → health 200 → backend install → model download → model load → first result
新しいマシンでは、バックエンドのインストールとモデルのダウンロードにそれぞれ数十秒から数分かかることがあります(ネットワーク経由で数 GB の重みをダウンロードするためです)。モデルのロードだけでも 10~30 秒かかります。この間に何も表示しないアプリは、フリーズしたように見えてしまいます。
最低限、セットアップ開始から最初の応答が届くまで、ローディングインジケーターまたはステータスメッセージ(「ローカル AI をセットアップしています…」)を表示し、最後のロードだけでなく、上記の手順の全体をカバーしてください。最も簡単な実装は、セットアップ/最初のリクエストの開始時にフラグを設定し、最初の応答が届いたら解除する方法です。モデルを一度プルしてロードすれば、その後の実行は高速になります。長い待ち時間が発生するのは初回のみです。
ステップ 7:ライフサイクルと復旧
対応する価値のある失敗モードは、以下のみです。過剰に複雑な実装は避けてください。
| 症状 | 原因 | 復旧方法 |
|---|---|---|
| 推論が HTTP 200 とともに空/未入力を返し、エラーがない | モデルがプルされていません。バックエンドはインストール済みですが、重みがないため、レイジーロードでロードするものがありません | {"model":"..."} を指定して POST /api/v1/pull を実行し、成功を待ってから再試行します。プルの結果と最初の推論結果をログに記録してください。これは最もよくあるサイレントな失敗です。ステップ 6 を参照してください |
POST /api/v1/load が 404/モデルが見つからないというエラーを返す | モデルがまだプルされていません(上記の空の結果と同じ根本原因です) | {"model": "..."} を指定して POST /api/v1/pull を実行してから、/api/v1/load を再試行します |
POST /api/v1/load がバックエンドエラーとともに 500 を返す | このハードウェア用のバックエンドがインストールされていません | GET /api/v1/system-info を実行して、対応するバックエンドを選び、{"recipe": "...", "backend": "..."} を指定して POST /api/v1/install を実行してから再試行します |
| サブプロセスがすぐに終了する | ポート競合:freePort() の実行後、lemond がポートにバインドする前に、別のプロセスがそのポートを取得しました | リファレンスランチャーは、新しいポートで自動的に再試行します(3 回まで) |
/api/v1/health が 200 を返さない | ディスクが低速な場合、初回のバックエンド展開に時間がかかります | 初回起動時はタイムアウトを 90 秒、その後は 30 秒に設定します |
| すべてのリクエストで HTTP 401 が発生する | Authorization: Bearer ヘッダーを付け忘れています | LEMONADE_API_KEY が設定されている場合、Lemonade は認証されていない呼び出しを拒否するため、クライアントの設定を確認してください |
**シャットダウン:**アプリ終了時に proc.terminate()(Unix)または proc.kill()(Windows)を実行します。lemond は設定を書き込み、数秒以内に正常終了します。必ずプロセスの終了を待ち、孤立させないでください。
lemond の標準出力を解析して準備完了を検出しないでください。HTTP の /api/v1/health プローブを使用してください。標準出力の形式は、安定した仕様として保証されていません。
検証チェックリスト
以下のすべてを満たした時点で、統合は完了です。
-
vendor/lemonade/にlemond[.exe]、lemonade[.exe]、LICENSE、resources/を含む完全なパッケージが格納されています。バイナリだけではありません。 -
lemondは、起動ごとに新しい API キーを使ってサブプロセスとして起動します。 -
GET /api/v1/healthはタイムアウト以内に 200 を返します。 - 最初の推論の前に、デフォルトモデルが取得済み(またはバンドル済み)です。カスタムモデル/上書きされたモデルは
GET /api/v1/modelsで確認してから取得します。エラーなしで空の結果が返る場合、この手順はスキップされています。 - 各ライフサイクル段階で明確なログ行(起動、ヘルスチェック、バックエンドのインストール、モデルの取得、最初の結果)が出力されるため、コンソールから障害を診断できます。
- 既存クライアントのチャット/画像/音声呼び出しは、ベース URL とキーを差し替えるだけで、有効な応答を返します。他のコードは変更しません。
- 初回実行時のレイテンシーが表示されます。最初の推論リクエストを送信した時点から応答が届くまで、インターフェースに読み込み状態が表示されます。
- HTTP クライアントのタイムアウトは 120 秒に設定されています。
- ローカルモードでは、アプリにクラウド API キーは不要です。オンボーディング画面、バリデーター、起動時チェックによってユーザーの利用がブロックされず、アクティブなモードがローカルの場合に、どのコードパスでも「API key not configured」がスローされません。
- アプリで開発モードのファイルウォッチャーを使用している場合、ウォッチ対象のパスから
vendor/lemonade/が除外されているため、lemond による実行時の書き込みで再起動が発生しません。 - 親プロセスを終了しても、
lemondのサブプロセスが残りません。 - 最適なバックエンドがない新しいマシンでも、
bin/にバンドルされた Vulkan フォールバックによってアプリが動作します。
未チェックの項目が1つでもある場合、タスクを完了と宣言しないでください。
リファレンス
モデルカタログの詳細、バックエンド選択マトリックス、全エンドポイントのリファレンス、設定キー、モデルごとの recipe_options.json の調整については、
reference.md を参照してください。