AI エンジン追加ガイド

Paprika に自前の LLM / VLM を追加して、page.agent()page.ask()・codegen-loop で利用する手順です。

概要

PaprikaEngine は OpenAI 互換 API (/v1/chat/completions) を話す任意の AI バックエンドを登録できる仕組みです。 Ollama / vLLM / LM Studio / OpenRouter / LiteLLM など、OpenAI 互換エンドポイントを持つサービスならすべて利用可能です。

Engine の種類 (kind)入力用途
chatテキスト → テキストpage.ask()、codegen-loop、翻訳
vision-chatテキスト + 画像 → テキストpage.agent()(eye)、画像解析、PerceptionResult 生成
reasoningテキスト → 長考 + テキストR1 judge / distiller / strategist(brain)。<think> ブロックを出す推論モデル

アーキテクチャ

┌─────────────┐     PUT /engines/slug     ┌──────────┐
│  管理画面     │ ──────────────────────→ │  Hub     │
│  or API      │                          │ :8000    │
└─────────────┘                          └────┬─────┘
                                              │ /v1/chat/completions
                                              ▼
                                    ┌──────────────────┐
                                    │  Ollama / vLLM    │
                                    │  :11434           │
                                    │  (GPU or CPU)     │
                                    └──────────────────┘

Hub はスクリプト実行時に /engines/{slug}/resolve でエンドポイント情報を取得し、 Worker が直接 AI サーバへリクエストします。 endpoint/chat/completions で終わっていなければ、 自動的に /v1/chat/completions が付加されます。

1. Ollama インストール

AI エンジン用のマシン (GPU マシンまたは CPU サーバ) で実行:

# Ollama をインストール (Linux)
curl -fsSL https://ollama.com/install.sh | sh

# 確認
ollama --version
GPU について: NVIDIA GPU があれば自動検出されます。GPU が無い場合は CPU モードで動作します (推論速度は遅くなりますが、8B クラスの量子化モデルなら実用可能)。

2. モデル取得

Qwen3-VL 8B (Vision-Language Model, 推奨)

# Qwen3-VL 8B をダウンロード (約 6.1GB, デフォルトで Q4_K_M 量子化)
ollama pull qwen3-vl:8b

# ダウンロード確認
ollama list
# NAME           ID              SIZE      MODIFIED
# qwen3-vl:8b    901cae732162    6.1 GB    Just now

テスト実行

# テキストクエリでテスト
curl -s http://localhost:11434/v1/chat/completions \
  -H 'Content-Type: application/json' \
  -d '{
    "model": "qwen3-vl:8b",
    "messages": [{"role":"user","content":"こんにちは。日本語で返答してください。"}],
    "max_tokens": 100
  }'
Qwen3 の thinking モード: Qwen3 はデフォルトで reasoning (思考) モードが有効です。 Ollama の OpenAI 互換 API では reasoning フィールドに思考内容、 content に最終回答が入ります。 PaprikaEngine はこの形式を自動的に処理します。

3. ネットワーク公開

Ollama はデフォルトで 127.0.0.1:11434 (localhost のみ) で listen します。 Hub や Worker からアクセスするには、全インターフェイスで listen するよう設定を変更します。

# systemd サービスに環境変数を追加
sudo vi /etc/systemd/system/ollama.service

[Service] セクションに以下を追加:

[Service]
ExecStart=/usr/local/bin/ollama serve
User=ollama
Group=ollama
Restart=always
RestartSec=3
Environment="OLLAMA_HOST=0.0.0.0"       ← この行を追加
Environment="PATH=..."
# 設定を反映して再起動
sudo systemctl daemon-reload
sudo systemctl restart ollama

# 確認: 0.0.0.0:11434 で listen していること
ss -tlnp | grep 11434
# LISTEN  0  4096  *:11434  *:*  users:(("ollama",...))    ← OK

Hub からの接続テスト

# Hub マシンから実行 (<ollama-host> は Ollama のホスト IP)
curl -s http://<ollama-host>:11434/v1/models
# {"object":"list","data":[{"id":"qwen3-vl:8b",...}]}
ファイアウォール: ポート 11434 が LAN 内で開放されていることを確認してください。 ufw を使っている場合: sudo ufw allow 11434/tcp

4. エンジン登録

Hub の API でエンジンを登録します。

API で登録 (推奨)

curl -X PUT http://<HUB_HOST>:8000/engines/qwen3-vl-8b \
  -H 'Content-Type: application/json' \
  -d '{
    "slug": "qwen3-vl-8b",
    "name": "Qwen3-VL 8B (Ollama)",
    "kind": "vision-chat",
    "protocol": "openai",
    "endpoint": "http://<OLLAMA_HOST>:11434",
    "model": "qwen3-vl:8b",
    "timeout_s": 120,
    "supports_tools": false,
    "use_for_codegen": true,
    "notes": "Qwen3-VL 8B on Ollama"
  }'

パラメータ解説

フィールド説明
slug一意な識別子。スクリプトで engine="qwen3-vl-8b" と指定する名前
name管理画面に表示される人間向け名称
kindchat / vision-chat / reasoning
protocolopenai (Ollama / vLLM / OpenAI 互換すべて)
endpointベース URL。/v1/chat/completions は自動付加される
modelAPI に渡す model 名 (Ollama のモデル名そのまま)
timeout_sリクエストタイムアウト (秒)。CPU 推論なら長めに設定
supports_toolsFunction calling 対応なら true
use_for_codegenSubmit 画面の「コード生成 LLM」セレクタに表示するか
api_key_envAPI キーの環境変数名 (Ollama では不要)

管理画面から登録

Admin UI (http://<HUB>:8000/) → Engines タブ → 「+ 追加」からも登録できます。

5. 動作確認

API で確認

# 登録済みエンジン一覧
curl -s http://<HUB_HOST>:8000/engines | python3 -m json.tool

# 特定エンジンの詳細
curl -s http://<HUB_HOST>:8000/engines/qwen3-vl-8b

スクリプトから確認

import asyncio
from paprika_client import async_paprika

async def main():
    async with async_paprika.connect() as cli:
        async with cli.session("https://example.com") as page:
            # テキスト質問
            answer = await page.ask(
                "このページのタイトルを教えて",
                engine="qwen3-vl-8b"
            )
            print(answer)

asyncio.run(main())

使い方

page.ask() — テキスト質問

answer = await page.ask("このページの要約を日本語で", engine="qwen3-vl-8b")

page.agent() — 画像 + テキストで判断

result = await page.agent(
    "ログインボタンをクリックして",
    engine="qwen3-vl-8b"
)

codegen-loop (AI 調査)

Admin UI の Submit 画面 → 「コード生成 LLM」で登録したエンジンを選択できます (use_for_codegen: true の場合)。

promoted (デフォルトエンジン)

# engine="auto" 時にこのエンジンを優先使用
curl -X POST http://<HUB>:8000/engines/qwen3-vl-8b/promote

推奨モデル一覧

モデルOllama タグサイズkind最低 RAM/VRAM用途
Qwen3-VL 8Bqwen3-vl:8b6.1 GBvision-chat8 GB汎用 VLM。画像理解 + テキスト生成
Qwen3 8Bqwen3:8b5.2 GBchat8 GBテキスト専用。codegen / 翻訳
Gemma 3 12Bgemma3:12b8.1 GBchat12 GB高品質テキスト生成
Gemma 4 31Bgemma4:31b19 GBchat24 GB大規模テキスト (GPU 推奨)

vLLM で構築する場合

GPU サーバで高スループットが必要な場合は vLLM を使います。

# vLLM インストール
pip install vllm

# Qwen3-VL 8B を起動
python -m vllm.entrypoints.openai.api_server \
  --model Qwen/Qwen3-VL-8B-Instruct \
  --port 8001 \
  --host 0.0.0.0 \
  --trust-remote-code
# PaprikaEngine に登録
curl -X PUT http://<HUB>:8000/engines/qwen3-vl-vllm \
  -H 'Content-Type: application/json' \
  -d '{
    "slug": "qwen3-vl-vllm",
    "name": "Qwen3-VL 8B (vLLM, GPU)",
    "kind": "vision-chat",
    "protocol": "openai",
    "endpoint": "http://<GPU_HOST>:8001",
    "model": "Qwen/Qwen3-VL-8B-Instruct",
    "timeout_s": 60
  }'

外部 API を登録 (OpenAI / Anthropic 等)

OpenAI GPT-4o

curl -X PUT http://<HUB>:8000/engines/gpt-4o \
  -H 'Content-Type: application/json' \
  -d '{
    "slug": "gpt-4o",
    "name": "GPT-4o (OpenAI)",
    "kind": "vision-chat",
    "protocol": "openai",
    "endpoint": "https://api.openai.com",
    "model": "gpt-4o",
    "api_key_env": "OPENAI_API_KEY",
    "timeout_s": 60,
    "supports_tools": true,
    "use_for_codegen": true
  }'

api_key_env には環境変数名を指定します (値ではない)。 Hub コンテナの .envOPENAI_API_KEY=sk-... を設定してください。

Anthropic Claude (LiteLLM 経由)

# LiteLLM プロキシを起動
litellm --model claude-sonnet-4-20250514 --port 4000

# 登録
curl -X PUT http://<HUB>:8000/engines/claude-sonnet \
  -H 'Content-Type: application/json' \
  -d '{
    "slug": "claude-sonnet",
    "name": "Claude Sonnet (LiteLLM)",
    "kind": "vision-chat",
    "protocol": "openai",
    "endpoint": "http://<LITELLM_HOST>:4000",
    "model": "claude-sonnet-4-20250514",
    "timeout_s": 60,
    "supports_tools": true,
    "use_for_codegen": true
  }'

トラブルシューティング

Connection refused

# Ollama が起動しているか確認
sudo systemctl status ollama

# listen アドレスの確認 (0.0.0.0 であること)
ss -tlnp | grep 11434

# OLLAMA_HOST が設定されているか
grep OLLAMA_HOST /etc/systemd/system/ollama.service

Hub からモデル一覧が見えない

# Hub マシンから直接テスト
curl http://<OLLAMA_HOST>:11434/v1/models

# ファイアウォール確認
sudo ufw status
sudo ufw allow 11434/tcp

推論が遅い

Qwen3 の回答が空 (content が空文字)

Qwen3 の thinking モードが有効だと、OpenAI 互換 API で content が空、 reasoning に全文が入ることがあります。 max_tokens を増やすか、Ollama native API (/api/chat) で確認してください。

エンジンの削除・更新

# 更新 (同じ slug で PUT)
curl -X PUT http://<HUB>:8000/engines/qwen3-vl-8b -d '{...}'

# 削除
curl -X DELETE http://<HUB>:8000/engines/qwen3-vl-8b