「リクエストをキューに積んで順番に処理させたいが、OllamaのAPIにはキュー管理機能がない」
そんな悩みを抱える情報システム担当者やサーバー管理者は多い。この記事では、PythonのタスクキューフレームワークCeleryとRedisブローカーを組み合わせて、OllamaへのLLMリクエストを非同期タスクキューで管理する仕組みを構築する。OllamaのAPIコールをCeleryタスクとして定義し、ワーカーが並列で処理することで、複数ユーザーからの同時リクエストをサーバー過負荷なしにさばけるようになる。systemdでCeleryワーカーをサービスとして登録し、再起動後も自動復旧する本番構成まで一気に進める。
この記事のポイント
・Celery+Redisでollamaリクエストを非同期タスクとしてキュー処理できる
・`worker_concurrency`でGPU/RAM容量に合わせた同時処理数を制御する
・systemdの`After=ollama.service`で起動順序を保証して本番運用に対応する
・バッチ処理とリアルタイム処理をキュー名で分離して優先度制御できる
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
なぜOllamaに非同期キューが必要なのか
OllamaのAPIは1リクエストずつ逐次処理するシンプルな設計だ。単一ユーザーが使う場面では問題ないが、チームサーバーとして運用すると典型的な問題が発生する。AさんとBさんが同時にAPIを叩いた場合、Ollamaは先着順に1件ずつ処理する。Bさんのリクエストはブロックされて待機するが、クライアントツールによってはタイムアウトエラーで弾かれてしまう。大きなモデル(`llama3.3:70b-instruct-q4_0`等)は1リクエストの処理に数十秒~数分かかるため、チームで共有するほど詰まりが深刻になる。
さらに深刻なのは、夜間バッチ処理(社内文書の一括要約等)とリアルタイムチャットが混在するケースだ。バッチが大量のリクエストを一気に送ると、対話用のリクエストがすべて待機に回される。リアルタイム応答性が失われ、ユーザーの体感品質が大幅に悪化する。
Celeryはこの問題を解決するPythonの非同期タスクキューフレームワークだ。リクエストをタスクとしてキューに積み、ワーカーが設定した並列度で処理する。バッチ処理を低優先キューに入れてリアルタイム用キューを分離するといった制御も、Celeryの設定数行で実現できる。
ローカルLLMをチームで活用する背景については、「社内でChatGPTが使えないときの代替手段|機密データを守るローカルLLMという選択肢」も参考にしてほしい。
前提環境と準備するもの
この手順を進める前に、以下の環境を用意しておく。1. 前提条件の確認
- Ubuntu Server 22.04 または 24.04 LTS - OllamaがsystemdサービスとしてLAN内で稼働中(`127.0.0.1:11434`でリッスン) - Python 3.10以上がインストール済み - Redisが使えること(次の手順でインストールする) Ollamaのsystemdサービスへの登録がまだの場合は、先に「Ubuntu ServerでローカルLLMを構築する方法|Ollamaで機密データを外に出さず業務AIを動かす完全ガイド」を参照してほしい。まず現在の環境を確認する。
# Python バージョン確認 $ python3 --version Python 3.12.3 # Ollamaが稼働中か確認 $ systemctl status ollama | grep Active Active: active (running) since 2026-10-15 10:00:00 JST # APIへの疎通確認 $ curl -s http://127.0.0.1:11434/api/tags | head -c 100 {"models":[{"name":"llama3.3:70b-instruct-q4_0","modified_at":"2026-10-01T12:00:00Z"...
2. プロジェクトディレクトリの作成
$ sudo mkdir -p /opt/ollama-queue $ sudo chown $USER:$USER /opt/ollama-queue $ cd /opt/ollama-queue # Python仮想環境を作成 $ python3 -m venv venv $ source venv/bin/activate (venv)$ pip install --upgrade pip
CeleryとRedisブローカーをインストールする
Celeryはメッセージブローカーを介してタスクをやり取りする。本記事ではRedisをブローカーとして使う。設定がシンプルで、1台のサーバーに同居させやすいためだ。RabbitMQと比べて運用コストが低く、小規模チームには最適な選択になる。1. Redisのインストールと起動
$ sudo apt update && sudo apt install -y redis-server $ sudo systemctl enable redis-server $ sudo systemctl start redis-server # Redisの疎通確認 $ redis-cli ping PONG # バージョン確認 $ redis-server --version Redis server v=7.0.15
2. CeleryとPythonライブラリのインストール
(venv)$ pip install celery[redis] requests # インストール確認 (venv)$ celery --version celery v5.3.6 (emerald-rush) (venv)$ python -c "import redis; print(redis.__version__)" 5.0.1
Celeryタスクとしてollamaリクエストを定義する
Celeryの中心はタスク定義ファイルだ。`@app.task`デコレータを付けたPython関数がそのままキューに積めるタスクになる。1. Celeryアプリケーションを定義する
`/opt/ollama-queue/tasks.py`を作成する。$ cat > /opt/ollama-queue/tasks.py << 'EOF' import requests from celery import Celery # Redisをブローカー兼バックエンドに指定 app = Celery("ollama_queue", broker="redis://127.0.0.1:6379/0", backend="redis://127.0.0.1:6379/1") app.conf.update( task_serializer="json", result_expires=3600, # 結果を1時間保持 worker_concurrency=2, # 同時処理数(GPU/RAMに合わせて調整) task_acks_late=True, # ワーカー死亡時のタスク再投入を有効化 ) @app.task(bind=True, max_retries=3) def generate(self, model: str, prompt: str, options: dict = None): payload = { "model": model, "prompt": prompt, "stream": False, "options": options or {}, } try: resp = requests.post( "http://127.0.0.1:11434/api/generate", json=payload, timeout=300, ) resp.raise_for_status() return resp.json().get("response", "") except requests.RequestException as exc: raise self.retry(exc=exc, countdown=10) EOF echo "tasks.py created"
使用するモデルの選び方については「ローカルLLMのモデルを比較する方法|Llama3.3・Mistral・Gemma・Phi-4をUbuntuで使い分けるポイント」で詳しく解説しているので参照してほしい。
2. タスクを送信する呼び出し側コードを確認する
同ディレクトリに動作確認用のクライアントスクリプトを作成しておく。$ cat > /opt/ollama-queue/submit_task.py << 'EOF' from tasks import generate # タスクを非同期で投入(即座にタスクIDを返す) result = generate.delay( model="llama3.3:70b-instruct-q4_0", prompt="LinuxのsystemdとSysVinitの違いを100字で説明してください", ) print(f"Task ID: {result.id}") # 結果を待機して取得(最大300秒) response = result.get(timeout=300) print(f"Response: {response}") EOF echo "submit_task.py created"
Celeryワーカーを起動してタスクを処理させる
設定ファイルが完成したら、まずフォアグラウンドでワーカーを起動して実際に動くことを確認する。1. ワーカーをフォアグラウンドで起動する
$ cd /opt/ollama-queue && source venv/bin/activate # ワーカーをフォアグラウンドで起動(Ctrl+Cで停止) (venv)$ celery -A tasks worker --loglevel=info --concurrency=2 [config] .> app: ollama_queue:0x7f1234567890 .> transport: redis://127.0.0.1:6379/0 .> results: redis://127.0.0.1:6379/1 .> concurrency: 2 (prefork) [tasks] . tasks.generate [2026-10-15 12:00:00,000: INFO/MainProcess] Connected to redis://127.0.0.1:6379/0 [2026-10-15 12:00:00,100: INFO/MainProcess] celery@hostname ready.
2. 別ターミナルからタスクを投入して確認する
# 別ターミナルで実行 $ cd /opt/ollama-queue && source venv/bin/activate (venv)$ python submit_task.py Task ID: a1b2c3d4-e5f6-7890-abcd-ef1234567890 Response: systemdはLinuxカーネル起動後に最初に実行されるPID1のシステム初期化デーモンで...
複数タスクを同時に投入する場合も`generate.delay()`を繰り返し呼ぶだけでよい。`worker_concurrency=2`なら最大2件が並列処理され、残りはキューで待機する。Ollamaのリクエスト処理能力についての詳細は「Ubuntu ServerでローカルLLMを構築する方法」のパフォーマンスセクションを参照してほしい。
systemdでCeleryワーカーをサービスとして登録する
コンソールでの動作確認が取れたら、systemdサービスとして登録する。サーバー再起動後も自動起動し、クラッシュ時も自動で再起動するようになる。1. systemdユニットファイルを作成する
$ sudo tee /etc/systemd/system/ollama-celery.service << 'EOF' [Unit] Description=Celery Worker for Ollama Queue After=network.target redis-server.service ollama.service Requires=redis-server.service [Service] Type=forking User=ubuntu Group=ubuntu WorkingDirectory=/opt/ollama-queue ExecStart=/opt/ollama-queue/venv/bin/celery \ -A tasks worker \ --loglevel=info \ --concurrency=2 \ --logfile=/var/log/ollama-celery.log \ --pidfile=/var/run/ollama-celery.pid \ --detach ExecStop=/bin/kill -TERM $MAINPID Restart=on-failure RestartSec=10s [Install] WantedBy=multi-user.target EOF echo "service file created"
2. ログファイルの権限設定とサービス有効化
$ sudo touch /var/log/ollama-celery.log $ sudo chown ubuntu:ubuntu /var/log/ollama-celery.log $ sudo systemctl daemon-reload $ sudo systemctl enable ollama-celery $ sudo systemctl start ollama-celery # ステータス確認 $ systemctl status ollama-celery | grep Active Active: active (running) since 2026-10-15 12:00:00 JST
3. タスクキューの動作を本番環境でテストする
# Celeryワーカーに実際にpingを送って確認 $ cd /opt/ollama-queue && source venv/bin/activate (venv)$ celery -A tasks inspect ping -> celery@hostname: OK pong # キューの状態を確認 (venv)$ celery -A tasks inspect active_queues -> celery@hostname: OK * exchange=celery(direct) key=celery
よくあるトラブルと対処法
本番環境でのよくある詰まりポイントをまとめる。ワーカーが起動するがタスクが処理されない
Redisへの接続失敗が多い。接続状態を確認する。# Redisの起動確認 $ systemctl status redis-server | grep Active Active: active (running) # ポートのリッスン確認 $ ss -tlnp | grep 6379 LISTEN 0 511 127.0.0.1:6379 0.0.0.0:* users:(("redis-server",...)) # Celeryから接続確認 $ cd /opt/ollama-queue && source venv/bin/activate (venv)$ celery -A tasks inspect ping -> celery@hostname: OK pong
generate.delay()実行時にImportErrorが出る
`PYTHONPATH`が設定されていないか、仮想環境が有効化されていない状態で実行しているケースが多い。# 仮想環境を有効化してから実行する $ cd /opt/ollama-queue && source venv/bin/activate (venv)$ python -c "import tasks; print(tasks)"
リクエストが途中で切れる(長文生成時)
`tasks.py`の`timeout=300`(5分)が短い場合は600に延ばす。`llama3.3:70b-instruct-q4_0`のような大型モデルのCPU推論では5分超えが発生することがある。# tasks.py の timeout を延長する # 変更前: timeout=300 # 変更後: timeout=600 $ sed -i 's/timeout=300/timeout=600/' /opt/ollama-queue/tasks.py $ sudo systemctl restart ollama-celery
複数タスクが1件ずつしか処理されない
`worker_concurrency`が1になっている。GPUメモリとの相談になるが、CPUのみの構成では`worker_concurrency=4`程度まで増やせる場合がある。Ollamaがメモリ不足でクラッシュする場合は逆に下げる。# tasks.py の worker_concurrency を確認・変更 $ grep worker_concurrency /opt/ollama-queue/tasks.py worker_concurrency=2, # 変更後はサービスを再起動する $ sudo systemctl restart ollama-celery
systemdサービスが起動に失敗する
ユーザー名の不一致やPIDファイルの権限エラーが典型的な原因だ。# エラーログを確認 $ sudo journalctl -u ollama-celery -n 30 --no-pager # 実行ユーザーを確認 $ whoami ubuntu # PIDファイルのディレクトリ権限を確認 $ ls -la /var/run/ | grep ollama
まとめ
| 手順 | コマンド・ファイル | ポイント |
|---|---|---|
| Redisインストール | sudo apt install -y redis-server | ブローカー本体・127.0.0.1バインドで安全 |
| Celeryインストール | pip install celery[redis] requests | 仮想環境内でインストール |
| タスク定義 | /opt/ollama-queue/tasks.py | @app.taskデコレータでollamaリクエストをキュー化 |
| ワーカー確認起動 | celery -A tasks worker --loglevel=info | フォアグラウンドで動作確認してから本番へ |
| systemd登録 | /etc/systemd/system/ollama-celery.service | After=ollama.serviceで起動順序を保証 |
| サービス有効化 | sudo systemctl enable ollama-celery | 再起動後も自動起動・クラッシュ時に自動復旧 |
ローカルLLMのチーム運用を2日間のハンズオンで体験する
Celeryによるキュー管理やsystemdの本番設定など、実機GPU環境でチームサーバー構成を手を動かしながら習得したい方向けに、「ローカルAIマスターセミナー」を開催しています。
少人数(最大8名)ZOOMハンズオン形式で実施しています。
・Ubuntu ServerでローカルLLMを構築する方法|Ollamaで機密データを外に出さず業務AIを動かす完全ガイド
・社内でChatGPTが使えないときの代替手段|機密データを守るローカルLLMという選択肢
・ローカルLLMのモデルを比較する方法|Llama3.3・Mistral・Gemma・Phi-4をUbuntuで使い分けるポイント
3,100名以上が実践した「型」を無料で公開中
プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら
- 前のページへ:OllamaとMinIOでローカルS3互換ストレージのRAGを構築する方法|オブジェクトストレージに蓄積した社内文書をローカルLLMで検索・質問応答する手順
- この記事の属するカテゴリ:ローカルLLMへ戻る

無料メルマガで学習を続ける
Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。
登録無料・いつでも解除できます