API リファレンス

LLM AI Server with llama.cpp が端末内で公開する HTTP API の仕様と使用例です。Ollama 互換エンドポイント(/api/*)、OpenAI 互換エンドポイント(/v1/chat/completions, /v1/completions ほか)、Anthropic Messages API 互換エンドポイント(/v1/messages, /v1/messages/count_tokens)、llama.cpp WebUI 互換エンドポイント(/props, /slots ほか)、およびモデル制御用の独自エンドポイント(/models/load, /models/unload)を、現行の OllamaApiServer 実装をもとに整理しています。

関連文書: 操作マニュアル | 技術仕様 | プライバシーポリシー

Ollama 互換 OpenAI 互換 Anthropic 互換 SSE / NDJSON streaming Embeddings Structured Output Multimodal Tools / Function Calling Reasoning

目次

1. 基本情報

2. 互換性サマリ

チャット / 生成 / 埋め込みの主要な用途では Ollama・OpenAI の両仕様と互換です。トークン統計(Ollama の eval_count 系、OpenAI の usage)も返すため、Open WebUI や LangChain のような統計を参照するクライアントでもそのまま動作します。一方、本アプリは「端末内 1 モデル・1 推論」を前提とした実装のため、リポジトリ管理系のエンドポイントは提供しません。

区分内容
Ollama 互換POST /api/generatePOST /api/chatGET/POST /api/tagsPOST /api/embedPOST /api/embeddings(旧仕様)、POST /api/tokenize。応答形は {model, created_at, response|message, done} 系で互換。完了時の chunk には total_duration / load_duration / prompt_eval_count / prompt_eval_duration / eval_count / eval_duration(ナノ秒)を付与。ツール利用時は done_reasontool_callsreasoning_content を追加。
OpenAI 互換POST /v1/chat/completions(streaming は SSE、終端 data: [DONE])、POST /v1/completions(レガシー Completions、object: "text_completion")、GET /v1/modelsPOST /v1/embeddingsPOST /v1/responses/input_tokens。応答には idchatcmpl-… / cmpl-…)・createdobjectchoices[].message/delta/textfinish_reason、非ストリーミング時は usage を含みます。
Anthropic 互換POST /v1/messages(Messages API。streaming は名前付き SSE イベント message_start / content_block_* / message_delta / message_stop)、POST /v1/messages/count_tokenssystem・マルチターン・思考(thinking ブロック)・画像 / 音声入力・基本的な tool_use / tool_result に対応。応答は content[] ブロック配列(text / thinking / tool_use)+ stop_reasonusageinput_tokens / output_tokens)。
llama.cpp WebUI 互換GET /propsGET /slotsGET /health/v1/health)、GET /models、Bundled WebUI 配信。
拡張(独自)POST /models/load / POST /models/unload(明示的なモデル制御)、マルチモーダル入力(image_url / input_audio、Anthropic は image / audio ブロック)、共有 MCP / Function Definitions 設定、reasoning_contentsamplers によるサンプラー順序指定、パフォーマンス指標を本文末尾に付記するオプション。
未実装(注意点)モデルリポジトリ管理(/api/show, /api/pull, /api/push, /api/create, /api/copy, /api/delete, /api/ps, /api/version)、/v1/responses 本体、logprobsn > 1 の複数候補生成には対応していません。ストリーミング応答(SSE)には usage を含めません(stream_options.include_usage は無視されます)。/v1/embeddingsusage は形だけの 0 です。stop / stop_sequences は受理しますが強制はしません。

「パフォーマンス指標を表示」を有効にすると、上記の統計フィールドとは別に、トークン数・処理時間・速度・端末温度が生成本文の末尾(OpenAI は追加 delta、Ollama は追加 chunk)にテキストとして付記されます。

3. 共通仕様

3-1. 同時実行と待機キュー

3-2. エラー応答

/api/* 系と独自エンドポイントは {"error": "..."} 形式、/v1/* 系は OpenAI 形式のエラーオブジェクトを返します。

// /api/* のエラー形式
{ "error": "'input' is required" }

// /v1/* のエラー形式
{
  "error": {
    "message": "No messages provided",
    "type": "invalid_request_error",
    "code": 400
  }
}
ステータス意味
400JSON 不正、必須項目欠落、非対応の content[].type、未対応モダリティ、非対応の画像形式 など
404未定義の経路
405非対応の HTTP メソッド
413リクエストボディが 64 MB を超過
500設定ロード失敗、生成・埋め込み失敗 など
503ビジー(キュー満杯 / 待機タイムアウト / リセット進行中 / アンロード時にモデル使用中)

ストリーミング中にエラーが発生した場合は、/api/* では error を含む chunk、/v1/* ではエラーオブジェクトの SSE イベントに続けて data: [DONE] を送出してストリームを閉じます。クライアント側が切断した場合はネイティブ生成もキャンセルされます。

4. POST/api/generate

単一プロンプトからの生成(Ollama generate 互換)。既定で streaming(NDJSON)。

リクエスト

フィールド説明
modelstringプロファイル名。未指定時は "default"
promptstringユーザープロンプト。
systemstring?任意。システムプロンプト(設定側より優先)。
streambool既定 truefalse で一括応答。
optionsobject?Ollama 慣習のサンプリング / コンテキスト設定。num_ctx, num_predict, temperature, top_k, top_p, min_p, repeat_penalty, repeat_last_n, mirostat* を解釈します(13 章)。
format / grammarstring|object任意。構造化出力の制約(14 章)。
thinkbool|string?任意。思考(reasoning)の有効 / 無効(15 章)。
toolsarray?任意。指定すると内部ツール実行ループに切り替わります(17 章)。配列以外を渡すと 400

非ストリーミング応答

curl http://localhost:11434/api/generate -d '{
  "model": "my-profile",
  "prompt": "日本の首都は?",
  "stream": false
}'
{
  "model": "my-profile",
  "created_at": "2026-08-13T03:10:00.000Z",
  "response": "日本の首都は東京です。",
  "done": true,
  "total_duration": 1843000000,
  "load_duration": 12000000,
  "prompt_eval_count": 18,
  "prompt_eval_duration": 231000000,
  "eval_count": 12,
  "eval_duration": 1600000000
}

ストリーミング応答(NDJSON)

1 行 1 JSON。各 chunk は "done": falseresponse に部分文字列。最後に "done": true と統計フィールドを含む chunk を送出します。

{"model":"my-profile","created_at":"...","response":"日本","done":false}
{"model":"my-profile","created_at":"...","response":"の首都は","done":false}
{"model":"my-profile","created_at":"...","response":"","done":true,"total_duration":1843000000,"prompt_eval_count":18,"eval_count":12,...}

統計フィールドはナノ秒単位で、Ollama の定義に合わせています(total_duration = load_duration + prompt_eval_duration + eval_duration)。tok/s を計算するクライアントはそのまま利用できます。

5. POST/api/chat

messages 配列による会話生成(Ollama chat 互換)。既定で streaming(NDJSON)。

リクエスト

フィールド説明
modelstringプロファイル名。未指定時は "default"
messagesarray必須。{role, content} の配列。rolesystem / user / assistant / toolcontent は文字列、またはマルチモーダル用の配列(16 章)。
streambool既定 true
optionsobject?4 章と同じ(num_ctx / num_predict ほか)。
format / grammarstring|object任意(14 章)。
thinkbool|string?任意(15 章)。
toolsarray?任意(17 章)。

非ストリーミング応答

curl http://localhost:11434/api/chat -d '{
  "model": "my-profile",
  "stream": false,
  "options": { "num_ctx": 8192, "temperature": 0.7 },
  "messages": [
    {"role": "system", "content": "あなたは簡潔に答えるアシスタントです。"},
    {"role": "user", "content": "富士山の標高は?"}
  ]
}'
{
  "model": "my-profile",
  "created_at": "2026-08-13T03:10:00.000Z",
  "message": { "role": "assistant", "content": "3,776 m です。" },
  "done": true,
  "total_duration": 980000000,
  "load_duration": 8000000,
  "prompt_eval_count": 34,
  "prompt_eval_duration": 180000000,
  "eval_count": 9,
  "eval_duration": 792000000
}

ストリーミング応答(NDJSON)

{"model":"my-profile","created_at":"...","message":{"role":"assistant","content":"3,776"},"done":false}
{"model":"my-profile","created_at":"...","message":{"role":"assistant","content":" m です。"},"done":false}
{"model":"my-profile","created_at":"...","message":{"role":"assistant","content":""},"done":true,"eval_count":9,...}

思考を有効にしたモデルでは、思考部分は本文ではなく message.reasoning_content として送出されます(15 章)。

6. GETPOST/api/tags

利用可能なモデル(プロファイル)一覧。Ollama tags 互換。

curl http://localhost:11434/api/tags
{
  "models": [
    {
      "name": "my-profile",
      "model": "my-profile",
      "modified_at": "2026-08-13T03:10:00.000Z",
      "size": 0,
      "details": {
        "format": "gguf",
        "family": "llama",
        "parameter_size": "unknown",
        "quantization_level": "unknown"
      }
    }
  ]
}

sizeparameter_size 等は端末側で確定できないため固定値(0 / "unknown")です。ファイルサイズ・ロード状態・モダリティ(vision / audio)まで必要な場合は /v1/models8 章)を使ってください。

7. POST/v1/chat/completions

OpenAI Chat Completions 互換。既定で streaming(SSE)。OpenAI 公式 SDK の base_url をこのサーバーに向けるだけで利用できます。

リクエスト

フィールド説明
modelstringプロファイル名。空 / 未指定時は現在ロード中のモデル、なければ既定プロファイルに解決されます。
messagesarray必須。OpenAI 形式。content は文字列または {type, ...} パーツ配列(16 章)。
streambool既定 true
max_tokens / n_predictint生成トークン上限。n_predict: 0 は pre-encode のみ(13 章)。
response_formatobject?json_object / json_schema / text14 章)。
reasoning_format / chat_template_kwargsstring / object思考制御(15 章)。
tools / tool_choice / parallel_tool_callsarray / any / bool任意(17 章)。
サンプリング各種number 等temperature, top_p, top_k, min_p, presence_penalty, frequency_penalty, samplers ほか(13 章)。リクエスト単位で設定を上書きします。

非ストリーミング応答

curl http://localhost:11434/v1/chat/completions -d '{
  "model": "my-profile",
  "stream": false,
  "messages": [
    {"role": "user", "content": "Say hello in Japanese."}
  ]
}'
{
  "id": "chatcmpl-4f0a1c2e5b7d4a9f8c3e1b6d2a7f0e5c",
  "object": "chat.completion",
  "created": 1786000000,
  "model": "my-profile",
  "choices": [
    {
      "index": 0,
      "message": { "role": "assistant", "content": "こんにちは!" },
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_tokens": 14,
    "completion_tokens": 5,
    "total_tokens": 19
  }
}

ストリーミング応答(SSE)

先頭に delta.role="assistant" の chunk、続いて delta.content を持つ chunk 群、最後に finish_reason:"stop" の chunk と data: [DONE] を送出します。全 chunk が同じ id / created を共有します。

data: {"id":"chatcmpl-4f0a…","object":"chat.completion.chunk","created":1786000000,"model":"my-profile","choices":[{"index":0,"delta":{"role":"assistant"},"finish_reason":null}]}

data: {"id":"chatcmpl-4f0a…","object":"chat.completion.chunk","created":1786000000,"model":"my-profile","choices":[{"index":0,"delta":{"content":"こん"},"finish_reason":null}]}

data: {"id":"chatcmpl-4f0a…","object":"chat.completion.chunk","created":1786000000,"model":"my-profile","choices":[{"index":0,"delta":{"content":"にちは!"},"finish_reason":null}]}

data: {"id":"chatcmpl-4f0a…","object":"chat.completion.chunk","created":1786000000,"model":"my-profile","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}

data: [DONE]

注意: ストリーミング応答の chunk には usage を含めません(stream_options.include_usage は未対応)。トークン統計が必要な場合は stream: false を使うか、Ollama 側の /api/chat(完了 chunk に eval_count 等を含む)を利用してください。

7-2. POST/v1/completions

OpenAI レガシー Completions 互換。チャットテンプレートを通さず、prompt をそのままモデルへ入力する素の補完用途です。応答は object: "text_completion" で、テキストは choices[].text に入ります。プロトコル上マルチモーダルは扱いません(画像・音声はチャット / Messages を利用してください)。

リクエスト

フィールド説明
modelstringプロファイル名。空 / 未指定時は現在ロード中のモデル、なければ既定プロファイルに解決されます。
promptstring | string[]必須。文字列、または文字列配列(改行で連結)。空 / 欠落時は 400
streambool既定 falsetrue で SSE。
max_tokens / n_predictint生成トークン上限(13 章)。
サンプリング各種 / grammarnumber 等temperature, top_p, top_k, samplers ほか(13 章)、GBNF grammar14 章)を受け付けます。

非ストリーミング応答

curl http://localhost:11434/v1/completions -d '{
  "model": "my-profile",
  "prompt": "東京を3行で紹介して",
  "max_tokens": 128,
  "stream": false
}'
{
  "id": "cmpl-2b7d4a9f8c3e1b6d2a7f0e5c4f0a1c2e",
  "object": "text_completion",
  "created": 1786000000,
  "model": "my-profile",
  "choices": [
    { "index": 0, "text": "東京は日本の首都です。…", "finish_reason": "stop", "logprobs": null }
  ],
  "usage": { "prompt_tokens": 12, "completion_tokens": 40, "total_tokens": 52 }
}

ストリーミング応答(SSE)

各 chunk は object: "text_completion" で、部分テキストが choices[].text に入ります。最後に finish_reason: "stop" の chunk と data: [DONE] を送出します。

data: {"id":"cmpl-…","object":"text_completion","created":1786000000,"model":"my-profile","choices":[{"index":0,"text":"東京は","finish_reason":null,"logprobs":null}]}

data: {"id":"cmpl-…","object":"text_completion","created":1786000000,"model":"my-profile","choices":[{"index":0,"text":"","finish_reason":"stop","logprobs":null}]}

data: [DONE]

7-3. POST/v1/messages(Anthropic Messages API)

Anthropic Messages API 互換。Anthropic 公式 SDK / クライアントの base URL をこのサーバーに向けて利用できます(x-api-key / anthropic-version ヘッダーは受理しますが無視されます)。system・マルチターン・思考(thinking ブロック)・画像 / 音声入力・基本的な tool_use / tool_result の往復に対応します。既定は非ストリーミング(stream:false)で、max_tokens は必須です。

リクエスト

フィールド説明
modelstringプロファイル名。実在の Claude モデル名(例 claude-3-5-sonnet)を送っても、ローカルの現行モデルに解決されます。
max_tokensint必須。欠落時は 400
messagesarray必須。{role, content} の配列。roleuser / assistantcontent は文字列、または text / image / audio / tool_use / tool_result ブロック配列(16 章)。
systemstring | array?任意。システムプロンプト(文字列またはテキストブロック配列)。
streambool既定 falsetrue で名前付き SSE イベント。
thinkingobject?{"type":"enabled"|"disabled"}15 章)。
tools / tool_choicearray / object?任意。Anthropic 形式(name / description / input_schema)。tool_choiceauto / any / tool17 章)。
temperature / top_p / top_knumber任意。サンプリング上書き(13 章)。

非ストリーミング応答

curl http://localhost:11434/v1/messages -d '{
  "model": "my-profile",
  "max_tokens": 256,
  "messages": [
    {"role": "user", "content": "富士山の標高は?"}
  ]
}'
{
  "id": "msg_988412deab264f1abf8904b938f389a7",
  "type": "message",
  "role": "assistant",
  "model": "my-profile",
  "content": [
    { "type": "text", "text": "3,776 m です。" }
  ],
  "stop_reason": "end_turn",
  "stop_sequence": null,
  "usage": { "input_tokens": 15, "output_tokens": 8 }
}

思考を有効にすると、content の先頭に {"type":"thinking","thinking":"…"} ブロックが入り、続けて {"type":"text","text":"…"} が入ります。ツール呼び出し時は {"type":"tool_use","id":…,"name":…,"input":{…}} ブロックと stop_reason:"tool_use" を返します。

ストリーミング応答(名前付き SSE イベント)

Anthropic 準拠のイベント列を送出します。テキストは text_delta、思考は thinking_delta、ツール引数は input_json_delta として流れます。

event: message_start
data: {"type":"message_start","message":{"id":"msg_…","type":"message","role":"assistant","model":"my-profile","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":15,"output_tokens":0}}}

event: content_block_start
data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}}

event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"3,776 m です。"}}

event: content_block_stop
data: {"type":"content_block_stop","index":0}

event: message_delta
data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"output_tokens":8}}

event: message_stop
data: {"type":"message_stop"}

トークン数の見積り: POST /v1/messages/count_tokens

生成を行わず、プロンプトの入力トークン数だけを返します。

curl http://localhost:11434/v1/messages/count_tokens -d '{
  "model": "my-profile",
  "messages": [{"role": "user", "content": "hello world"}]
}'
{ "input_tokens": 4 }

エラーは Anthropic 形式({"type":"error","error":{"type":…,"message":…}})で返します。max_tokens 欠落は invalid_request_error400)です。

8. GET/v1/models・/models

OpenAI 互換のモデル一覧に加え、llama.cpp WebUI 向けの models 配列(状態・モダリティ)も同時に返します。

curl http://localhost:11434/v1/models
{
  "object": "list",
  "data": [
    {
      "id": "my-profile",
      "name": "my-profile",
      "object": "model",
      "owned_by": "llamacpp",
      "created": 1786000000,
      "in_cache": true,
      "path": "/data/.../my-model.gguf",
      "status": { "value": "loaded" },
      "tags": []
    }
  ],
  "models": [
    {
      "name": "my-profile",
      "model": "my-profile",
      "modified_at": "2026-08-13T03:10:00.000Z",
      "size": 4100000000,
      "capabilities": ["multimodal"],
      "modalities": { "vision": true, "audio": false },
      "details": { "format": "gguf", "family": "llama", "parameter_size": "unknown", "quantization_level": "unknown" }
    }
  ]
}

data[] が OpenAI 互換、models[] が llama.cpp WebUI 互換です。status.valueloaded / unloadedin_cache は GGUF ファイルが端末内に存在するかどうか。modalities はロード済みモデルなら実際の対応状況、未ロードならファイルからの推定値を返します。details.family はモデルファイル名から推定したモデルファミリです。

9. POST埋め込み(Embeddings)

埋め込み用 GGUF(BERT 系 / *-embedding など)をプロファイルに設定しておくと、Ollama 形式と OpenAI 形式の両方でベクトルを取得できます。3 つのエンドポイントは同じネイティブ実装を共有し、入出力の形だけが異なります。

エンドポイント入力出力
POST /api/embed(Ollama 現行){model, input}input は文字列または文字列配列。{model, embeddings: [[...], ...], total_duration, load_duration, prompt_eval_count}
POST /api/embeddings(Ollama 旧仕様){model, prompt}(単一文字列){embedding: [...]}
POST /v1/embeddings(OpenAI){model, input}input は文字列または文字列配列。{object:"list", data:[{object:"embedding", index, embedding:[...]}], model, usage}

使用例(Ollama 形式・複数入力)

curl http://localhost:11434/api/embed -d '{
  "model": "my-embedding-profile",
  "input": ["東京の天気", "大阪の天気"]
}'
{
  "model": "my-embedding-profile",
  "embeddings": [[0.0123, -0.0456, ...], [0.0210, -0.0388, ...]],
  "total_duration": 84000000,
  "load_duration": 3000000,
  "prompt_eval_count": 12
}

使用例(OpenAI 形式)

curl http://localhost:11434/v1/embeddings -d '{
  "model": "my-embedding-profile",
  "input": "検索クエリのテキスト"
}'
{
  "object": "list",
  "data": [
    { "object": "embedding", "index": 0, "embedding": [0.0123, -0.0456, ...] }
  ],
  "model": "my-embedding-profile",
  "usage": { "prompt_tokens": 0, "total_tokens": 0 }
}

入力が空("" や空配列)の場合は 400、埋め込み生成に失敗した場合は 500 を返します。長い入力はモデルの n_batch に合わせて内部で切り詰められます。/v1/embeddingsusage は互換性のためのプレースホルダで、常に 0 です。

10. POSTトークン数カウント

ロード中モデルのトークナイザで、テキストのトークン列 / トークン数を取得します。コンテキスト長の見積もりやチャンク分割に利用できます。

Ollama 形式: POST /api/tokenize

curl http://localhost:11434/api/tokenize -d '{
  "model": "my-profile",
  "content": "こんにちは、世界"
}'
{ "tokens": [123, 4567, 89, 1011] }

OpenAI 形式: POST /v1/responses/input_tokens

curl http://localhost:11434/v1/responses/input_tokens -d '{
  "model": "my-profile",
  "input": "こんにちは、世界"
}'
{ "input_tokens": 4, "object": "response.input_tokens" }

/api/tokenizecontent/v1/responses/input_tokensinput が必須です(空文字は 400)。/v1/responses/input_tokensmodel を省略した場合は、ロード中のモデル → 既定プロファイルの順に解決されます。

11. POST/models/load・/models/unload

推論を伴わずにモデルの常駐状態を制御する独自エンドポイントです。ベンチマーク前のウォームアップや、メモリ解放に使えます。

// 指定プロファイルをロード(既にロード済みなら即座に成功)
curl http://localhost:11434/models/load -d '{"model": "my-profile"}'
{ "success": true }

// アンロード(メモリ解放)
curl http://localhost:11434/models/unload -d '{"model": "my-profile"}'
{ "success": true }

12. GET/props・/slots・/health

主に同梱 WebUI(llama.cpp 風)の初期化に使われるエンドポイントです。?model=<プロファイル名> で対象を指定できます。

curl "http://localhost:11434/props?model=my-profile"
curl http://localhost:11434/health

13. 生成・サンプリングパラメータ

13-1. コンテキストサイズ(num_ctx

options.num_ctx(またはトップレベルの num_ctx)を指定すると、次回ロード時のコンテキスト長として反映されます。現在ロード中の値と異なる場合はモデルが自動的に再ロードされるため、初回リクエストの応答時間が伸びる点に注意してください。

{ "model": "my-profile", "options": { "num_ctx": 16384 }, "messages": [...] }

13-2. 生成トークン数

num_predict / n_predict / max_tokens のいずれでも指定できます(options 内・トップレベルの両方を参照。優先順位は num_predictn_predictmax_tokens)。n_predict: 0 を指定すると pre-encode のみを行い、空応答で早期復帰します(プロンプト評価のウォームアップ用)。

13-3. サンプリングパラメータ

次のキーをリクエスト本文(/api/*options 内でも可)に含めると、そのリクエストのあいだプロファイル設定を上書きします(指定しなかった項目はプロファイルの値を使用)。

キー対応する設定
temperaturenumber温度
top_kintTop-k
top_pnumberTop-p
min_pnumberMin-p
typ_pnumberTypical-p
dynatemp_range / dynatemp_exponentnumberDynamic temperature
xtc_probability / xtc_thresholdnumberXTC サンプラー
repeat_last_nintPenalty 対象トークン数
repeat_penaltynumberRepeat penalty
presence_penalty / frequency_penaltynumberPresence / Frequency penalty
dry_multiplier / dry_base / dry_allowed_length / dry_penalty_last_nnumber / intDRY サンプラー
mirostat / mirostat_tau / mirostat_etaint / numberMirostat
samplersstring[]サンプラーチェーンの適用順(例 ["top_k","typ_p","top_p","min_p","temperature"])。空配列 / 未指定でプロファイルの既定順に戻ります。

options 経由で解釈されるのは num_ctx, num_predict, n_predict, temperature, top_k, top_p, min_p, repeat_penalty, repeat_last_n, mirostat, mirostat_tau, mirostat_eta です。その他のサンプラー(DRY / XTC / dynatemp / typ_p など)はトップレベルに置いてください。

14. 構造化出力(JSON / GBNF)

生成をスキーマや文法で制約できます。Ollama 形式と OpenAI 形式の両方を受け付け、指定はリクエスト単位で適用され、次のリクエストには引き継がれません。

フィールド形式説明
formatOllama"json" で任意の JSON を強制。JSON Schema オブジェクトを渡すとそのスキーマに従います。
grammarOllama / llama.cppGBNF 文法を直接指定。
response_formatOpenAI{"type":"json_object"}{"type":"json_schema","json_schema":{"name":...,"schema":{...}}}{"type":"text"}(制約なし)。
// Ollama: JSON Schema による構造化出力
curl http://localhost:11434/api/chat -d '{
  "model": "my-profile",
  "stream": false,
  "format": {
    "type": "object",
    "properties": {
      "city": { "type": "string" },
      "temperature_c": { "type": "number" }
    },
    "required": ["city", "temperature_c"]
  },
  "messages": [{"role": "user", "content": "東京の気温を JSON で"}]
}'
// OpenAI: response_format
curl http://localhost:11434/v1/chat/completions -d '{
  "model": "my-profile",
  "stream": false,
  "response_format": {
    "type": "json_schema",
    "json_schema": {
      "name": "weather",
      "schema": {
        "type": "object",
        "properties": { "city": {"type":"string"}, "temperature_c": {"type":"number"} },
        "required": ["city", "temperature_c"]
      }
    }
  },
  "messages": [{"role": "user", "content": "Tokyo weather as JSON"}]
}'
// GBNF を直接指定(yes / no のみを出力させる)
{
  "model": "my-profile",
  "prompt": "富士山は日本で一番高い山ですか?",
  "grammar": "root ::= \"yes\" | \"no\""
}

15. 思考(Reasoning)制御

思考プロセスを持つモデル(DeepSeek-R1、Qwen3 系など)では、思考部分を本文と分離して reasoning_content として返します。有効 / 無効は次の優先順位で決まります。

  1. think(Ollama 標準): true / false、または文字列("false" 以外は有効)。
  2. reasoning_format: "none" で無効、"auto" で有効。
  3. chat_template_kwargs: enable_thinking / enable_reasoning(bool)、reasoning"off" で無効)。
  4. プロファイル設定の「Enable Think」。
// 思考を明示的に無効化(Ollama 形式)
{ "model": "my-profile", "think": false, "messages": [...] }

// OpenAI 形式で思考出力を抑制
{ "model": "my-profile", "reasoning_format": "none", "messages": [...] }
// 応答例(OpenAI / 非ストリーミング)
{
  "id": "chatcmpl-…",
  "object": "chat.completion",
  "choices": [{
    "index": 0,
    "message": {
      "role": "assistant",
      "reasoning_content": "ユーザーは標高を尋ねている。富士山は 3,776 m。",
      "content": "3,776 m です。"
    },
    "finish_reason": "stop"
  }]
}

ストリーミング時は delta.reasoning_content を持つ chunk が本文 chunk より先に流れます。思考を無効にした場合、モデルが出力した <think> 等のタグは本文から除去されます。

16. マルチモーダル入力

/api/chat/v1/chat/completions では、content をパーツ配列にすることで画像・音声を渡せます。Anthropic の /v1/messages でも同様に、content ブロック配列に画像 / 音声を含められます(下表)。いずれもロード中のモデルが vision / audio に対応している必要があり、非対応の場合は 400 を返します(対応状況は /v1/modelsmodalities で確認できます)。mmproj / projector を伴うモデルをロードしてください。

type説明
text / input_textテキスト(text フィールド)。
image_urlimage_url.urldata:image/...;base64, 形式の data URL、または HTTP/HTTPS の画像 URL。リモート取得は 10 MB 上限・接続 / 読み取り各 10 秒でタイムアウトします。
input_audioinput_audio.data(base64)と input_audio.format"wav" または "mp3")。

Anthropic /v1/messages のブロック: 画像は {"type":"image","source":{"type":"base64","media_type":"image/jpeg","data":"…"}}source.type:"url" も可)。音声はローカル拡張として {"type":"audio","source":{"data":"<base64>","format":"wav"}} を受け付けます。内部では OpenAI 形式の image_url / input_audio に変換して同じ mmproj 経路で処理します。

対応画像形式: JPEG / PNG / BMP / GIF など、ネイティブ側デコーダ(stb_image)が読める形式のみです。Android の標準保存形式である HEIC / HEIF・WebP・AVIF は非対応で、送信すると 400 とその旨のメッセージを返します。事前に JPEG / PNG へ変換してください。

curl http://localhost:11434/v1/chat/completions -d '{
  "model": "my-vision-profile",
  "stream": false,
  "messages": [
    {
      "role": "user",
      "content": [
        {"type": "text", "text": "この画像を説明して"},
        {"type": "image_url", "image_url": {"url": "data:image/jpeg;base64,/9j/4AAQ..."}}
      ]
    }
  ]
}'
// 音声入力(wav / mp3)
{
  "role": "user",
  "content": [
    {"type": "text", "text": "この音声を文字起こしして"},
    {"type": "input_audio", "input_audio": {"data": "UklGR...", "format": "wav"}}
  ]
}

17. ツール / Function Calling

リクエストに tools を渡すか、アプリの「MCP 設定」で共有 MCP / Function Definitions を有効にすると、内部ツール実行ループに切り替わります。/api/generate/api/chat/v1/chat/completions/v1/messages のいずれでも利用できます。

Anthropic /v1/messages: ツールは Anthropic 形式(name / description / input_schema)で渡し、tool_choiceauto / any / tool を受け付けます。応答はアシスタントの tool_use ブロック(stop_reason:"tool_use")で返り、次ターンでユーザーの tool_result ブロックを送ることで往復します。共有 MCP を有効にした場合は MCP ツールがサーバー側で自動実行されます(リクエストで渡した tools はクライアント実行型です)。

// リクエスト(OpenAI 互換のツール定義)
{
  "model": "my-profile",
  "stream": false,
  "tools": [
    {
      "type": "function",
      "function": {
        "name": "get_weather",
        "description": "指定都市の現在の天気を返す",
        "parameters": {
          "type": "object",
          "properties": { "city": { "type": "string" } },
          "required": ["city"]
        }
      }
    }
  ],
  "messages": [{"role": "user", "content": "東京の天気は?"}]
}
// 応答(非ストリーミング)
{
  "id": "chatcmpl-…",
  "object": "chat.completion",
  "created": 1786000000,
  "model": "my-profile",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": "",
        "tool_calls": [
          {
            "id": "call_1",
            "type": "function",
            "function": { "name": "get_weather", "arguments": "{\"city\":\"Tokyo\"}" }
          }
        ]
      },
      "finish_reason": "tool_calls"
    }
  ],
  "usage": { "prompt_tokens": 96, "completion_tokens": 21, "total_tokens": 117 }
}

18. クライアント例

OpenAI Python SDK

from openai import OpenAI

client = OpenAI(
    base_url="http://localhost:11434/v1",
    api_key="not-needed",  # 認証は不要(任意の文字列で可)
)

resp = client.chat.completions.create(
    model="my-profile",
    messages=[{"role": "user", "content": "こんにちは"}],
    stream=False,
)
print(resp.choices[0].message.content)
print(resp.usage)  # prompt_tokens / completion_tokens / total_tokens

OpenAI 互換ストリーミング(Python)

stream = client.chat.completions.create(
    model="my-profile",
    messages=[{"role": "user", "content": "俳句を1つ"}],
    stream=True,
)
for chunk in stream:
    delta = chunk.choices[0].delta
    if delta.content:
        print(delta.content, end="", flush=True)

構造化出力(Python)

resp = client.chat.completions.create(
    model="my-profile",
    messages=[{"role": "user", "content": "東京の気温を JSON で"}],
    response_format={
        "type": "json_schema",
        "json_schema": {
            "name": "weather",
            "schema": {
                "type": "object",
                "properties": {"city": {"type": "string"}, "temperature_c": {"type": "number"}},
                "required": ["city", "temperature_c"],
            },
        },
    },
    stream=False,
)
import json; print(json.loads(resp.choices[0].message.content))

埋め込み(Python)

vec = client.embeddings.create(
    model="my-embedding-profile",
    input=["東京の天気", "大阪の天気"],
)
print(len(vec.data), len(vec.data[0].embedding))

Anthropic Python SDK

from anthropic import Anthropic

client = Anthropic(
    base_url="http://localhost:11434",  # /v1/messages を提供
    api_key="not-needed",               # 認証は不要(無視されます)
)

msg = client.messages.create(
    model="my-profile",
    max_tokens=256,                     # 必須
    messages=[{"role": "user", "content": "こんにちは"}],
)
print(msg.content[0].text)
print(msg.usage.input_tokens, msg.usage.output_tokens)

Anthropic Messages(curl / SSE)

curl -N http://localhost:11434/v1/messages -d '{
  "model": "my-profile",
  "max_tokens": 256,
  "stream": true,
  "messages": [{"role": "user", "content": "俳句を1つ"}]
}'

Ollama 公式 Python クライアント

from ollama import Client

client = Client(host="http://localhost:11434")

res = client.chat(
    model="my-profile",
    messages=[{"role": "user", "content": "自己紹介して"}],
    options={"num_ctx": 8192, "temperature": 0.7},
)
print(res["message"]["content"])
print(res["eval_count"], res["eval_duration"])  # tok/s の計算に利用可能

emb = client.embed(model="my-embedding-profile", input="検索クエリ")
print(len(emb["embeddings"][0]))

Ollama 互換(curl / NDJSON)

curl -N http://localhost:11434/api/chat -d '{
  "model": "my-profile",
  "messages": [{"role": "user", "content": "自己紹介して"}]
}'

JavaScript(fetch / SSE)

const res = await fetch("http://localhost:11434/v1/chat/completions", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    model: "my-profile",
    messages: [{ role: "user", content: "Hello" }],
    stream: true,
  }),
});

const reader = res.body.getReader();
const decoder = new TextDecoder();
while (true) {
  const { value, done } = await reader.read();
  if (done) break;
  for (const line of decoder.decode(value).split("\n")) {
    if (!line.startsWith("data: ")) continue;
    const data = line.slice(6);
    if (data === "[DONE]") break;
    const json = JSON.parse(data);
    process.stdout.write(json.choices[0].delta.content ?? "");
  }
}

ウォームアップ → 生成 → 解放(curl)

# 1. モデルを常駐させる(推論なし)
curl http://localhost:11434/models/load -d '{"model":"my-profile"}'

# 2. プロンプトのトークン数を確認
curl http://localhost:11434/api/tokenize -d '{"model":"my-profile","content":"長い入力テキスト…"}'

# 3. 生成
curl http://localhost:11434/api/chat -d '{"model":"my-profile","stream":false,"messages":[{"role":"user","content":"要約して"}]}'

# 4. メモリを解放
curl http://localhost:11434/models/unload -d '{"model":"my-profile"}'

本ページは現行の Android 実装(OllamaApiServer)に基づきます。応答例は説明のため整形しています。実際のフィールド構成・既定値はアプリのバージョンにより変わることがあります。