0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Moodle 4.5 × ローカルLLM(Ollama)でAI機能を完全内製化する方法【第二弾】

0
Posted at

はじめに:第一弾のおさらいと本記事の位置づけ

前回の記事(第一弾) では、Moodle 4.5にOpenAI(ChatGPT)APIを連携してAI機能を使う方法を紹介しました。

クラウドAIとの連携は手軽で強力ですが、1つの課題が残ります。

学習者が入力したテキストは、OpenAIのサーバーに送信される。

成績情報・社内資料・個人情報を含むコンテンツをAIで処理したい場合、このデータの外部送信は無視できない問題です。

本記事ではその解決策として、AIをMoodleと同じサーバー内で動かす「ローカルLLM」構成を紹介します。データは外に出ず、APIコストもゼロです。

第一弾(OpenAI) 第二弾(Ollama)
データの送信先 OpenAIのサーバー 自分のサーバー内
APIコスト 従量課金あり 無料
品質 非常に高い モデルによる
セットアップの難易度 低い やや高い
オフライン動作 不可 可能

本記事が想定する環境について
本記事は、オンプレミスサーバーまたはクラウド上のVPS・専用サーバーでDockerを使って自己ホスティングしているMoodle環境を前提としています。
MoodleCloudなどのSaaS型Moodleをご利用の場合、サーバーへの直接アクセスができないため、本記事で紹介する構成(MoodleとOllamaを同一ネットワーク内に同居させる)はそのままではできません。
SaaS型をご利用の方は、まず第一弾で紹介しているOpenAI APIとの連携をご検討ください。

Cloudflare Tunnelやngrokなどのトンネリングツールを使ってOllamaのエンドポイントをHTTPSで公開すれば、SaaS型MoodleからでもOllamaに接続することは技術的に可能です。
SaaS Moodle → HTTPS → Cloudflare Tunnel → 自社サーバーのOllama
ただし、この構成ではデータがインターネットを経由するため、「完全なローカル完結」にはなりません。またOllamaをインターネットに公開する場合はアクセス制限の設定が必須です。
ローカルLLMを選ぶ主な動機がデータプライバシーであれば、この方法はその目的に完全には応えられません。自己ホスティング環境への移行を検討する価値があります。

1. ローカルLLMとは何か

クラウドLLM vs ローカルLLM

LLM(Large Language Model:大規模言語モデル)とは、ChatGPTやClaudeのように自然な文章を生成・理解できるAIの中核技術です。

通常、LLMは巨大なサーバー群(クラウド)で動いており、私たちはインターネット経由でそのAIに問い合わせています。

クラウドLLM vs ローカルLLM

Ollamaとは

Ollamaは、ローカル環境でLLMを簡単に管理・実行するためのオープンソースツールです。

難しい環境構築なしに、コマンド1つでLLMをダウンロードして動かせます。さらに、OpenAI互換のAPIエンドポイントを提供しているため、OpenAI対応のツール(Moodleを含む)がそのまま使えます。

# モデルをダウンロードして起動するだけ
ollama pull qwen2.5:7b
ollama run qwen2.5:7b

Dockerイメージも公式に提供されており、既存のDocker環境にサービスとして追加するだけで動きます。

2. この構成が刺さる人・ユースケース

個人情報を扱う教育機関

学習者の成績・受講履歴・内申情報などは、外部サービスに送信することへのハードルが高い情報です。ローカルLLMであれば、インターネットを経由せずにAI処理が完結します。

API課金なしで運用したい中小企業・研修担当者

クラウドAIは従量課金のため、学習者数が増えるほどコストが増大します。ローカルLLMは初期構築コストのみで、追加課金なしに何度でも利用できます

オフライン環境での研修

工場・医療施設・セキュリティポリシーが厳しい企業など、インターネット接続が制限された環境でも、ローカルLLMであれば問題なく動作します。

Moodleを自前サーバーで運用しているケース

クラウドホスティング(MoodleCloud等)ではなく、オンプレミスやVPS上でMoodleを運用している場合は、同じサーバーにOllamaを追加するだけで導入できます。

3. 今回の検証環境

ハードウェア:GEEKOM A8 (ミニPC)

今回の検証に使用したのは、GEEKOM A8というミニPCです。

項目 スペック
CPU AMD Ryzen 7 8845HS(8コア16スレッド)
RAM 32GB
ストレージ NVMe SSD 1TB
サイズ 手のひらサイズ(約13cm角)

GPUなし・CPU推論のみの構成です。それでもqwen2.5:7b約10〜13トークン/秒で動作し、Moodle上のAI機能として十分実用的な速度が出ています。

専用サーバーや高価なGPUマシンは不要です。同等スペックのミニPCや既存のLinuxサーバーがあれば同じ構成を再現できます。

ソフトウェア構成

Ubuntu 24.04 LTS
└── Docker Compose
    ├── moodle45     (Moodle 4.5.11)
    ├── shared_db    (MariaDB 10.11)
    ├── ollama       (ollama/ollama:latest)  ← 今回追加
    └── traefik      (リバースプロキシ・SSL)

すべてのコンテナがshared_netという内部ネットワークで接続されており、Moodleからhttp://ollama:11434でOllamaにアクセスできます。

スクリーンショット: docker ps の出力結果(全コンテナが動いている状態)

モデル選定:なぜqwen2.5:7bなのか

今回の構成で利用可能なモデルを比較した結果、qwen2.5:7bを採用しました。

モデル パラメータ数 RAM使用量 日本語品質 速度(CPU)
llama3.2:3b 3B 約2GB ◎ 速い
qwen2.5:7b 7B 約5GB ○ 良好 ○ 実用的
gemma4:12b 12B 約8GB △ やや遅い
gemma4:26b 26B 約17GB ◎ 高品質 ✕ 遅すぎる

qwen2.5:7bを選んだ理由は3つです。

  1. 日本語対応が良好:Alibaba製のQwenシリーズは日本語を含むアジア言語の学習データが豊富で、日本語の要約・生成品質が安定しています
  2. CPU推論でも実用的な速度:7Bサイズであれば32GBのRAMで余裕を持って動作し、応答速度も許容範囲内です
  3. 検証済み:本記事の執筆にあたり、実際にMoodleとの連携を検証しました

より高品質な日本語生成が必要な場合はgemma4:26bも候補ですが、CPU推論では応答に数分かかる場合があり、Moodleのリクエストがタイムアウトするリスクがあります。GPU環境がある場合に試してみてください。

4. Ollamaのセットアップ

docker-compose.yml(最小構成)

既存のMoodle環境にOllamaを追加する最小構成のサンプルです。

services:
  moodle:
    image: your-moodle-image
    container_name: moodle45
    networks:
      - shared_net
    # (既存の設定)

  ollama:
    image: ollama/ollama:latest
    container_name: ollama
    restart: unless-stopped
    networks:
      - shared_net          # Moodleと同じネットワークに参加させる
    volumes:
      - ollama_data:/root/.ollama   # モデルデータの永続化

networks:
  shared_net:
    name: shared_net        # 既存のネットワーク名に合わせる

volumes:
  ollama_data:

GPU(NVIDIA)を使う場合deployセクションを追加します。CPU推論で十分な場合は上記のままでOKです。

コンテナの起動

docker compose up -d ollama

モデルのダウンロード

# qwen2.5:7b をダウンロード(約4.7GB)
docker exec -it ollama ollama pull qwen2.5:7b

# ダウンロード済みモデルの確認
docker exec -it ollama ollama list

スクリーンショット: ollama list の出力(qwen2.5:7bが表示されている)

疎通確認

MoodleコンテナからOllamaに到達できるかを確認します。

# Moodleコンテナ内からOllamaのモデル一覧を取得
docker exec -it moodle45 curl -s http://ollama:11434/api/tags

モデル名を含むJSONが返れば成功です。

続いて、OpenAI互換エンドポイントも確認します。

docker exec -it moodle45 curl -s \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer ollama" \
  -d '{"model":"qwen2.5:7b","messages":[{"role":"user","content":"こんにちは"}]}' \
  http://ollama:11434/v1/chat/completions

日本語で応答が返ってくれば、Moodleとの連携準備は完了です。

スクリーンショット: curlコマンドの実行結果(日本語の応答が返ってきた状態)

5. Moodle側の設定

第一弾(OpenAI連携)を読んだ方へ
プロバイダーの作成・アクションの有効化・AI Placementsの有効化手順は第一弾と同じです。本章ではOllama固有の設定と、第一弾との差分を中心に説明します。

5-1. AIプロバイダーの設定

サイト管理 → 一般 → AI → AIプロバイダ
→「OpenAI APIプロバイダ」を選択
→「設定」を選択

スクリーンショット: OpenAIプロバイダの設定

プロバイダー設定画面では、APIキーに任意の文字列を入力します(Ollamaは認証不要ですが、空欄だとエラーになります)。

項目
OpenAI APIキー ollama(任意の文字列)

スクリーンショット: OpenAI APIプロバイダー設定画面(APIキーに「ollama」と入力)

5-2. アクション設定(ここがOpenAIとの最大の差分)

「テキストを生成する」行の「設定」 をクリックします。

項目
AIモデル qwen2.5:7b
APIエンドポイント http://ollama:11434/v1/chat/completions

スクリーンショット: テキストを生成するアクション設定画面(エンドポイントにOllamaのURLが入力された状態)

エンドポイントの設定が最重要ポイントです。

OpenAIのデフォルトURL(https://api.openai.com/v1/chat/completions)から、OllamaのURL(http://ollama:11434/v1/chat/completions)に変更してください。

/v1 だけでなく /v1/chat/completions までフルパスで入力する必要があります。省略すると404エラーになります。

「テキストを要約する」も同様に設定します。

項目
AIモデル qwen2.5:7b
APIエンドポイント http://ollama:11434/v1/chat/completions

5-3. セキュリティ設定(Ollama固有の重要な設定)

ここが第一弾(OpenAI)との最大の違いです。

Moodleには外部への不審なリクエストを防ぐSSRF(サーバーサイドリクエストフォージェリ)対策機能があります。この機能が、Docker内部ネットワークのプライベートIPへのアクセスもブロックしてしまいます

OllamaコンテナのIPは172.20.x.x(Dockerのデフォルトネットワーク)ですが、これはMoodleのデフォルトブロックリスト172.16.0.0/12の範囲に含まれているため、そのままではアクセスできません。

サイト管理 → Security → HTTP security

① cURLブロック済みホスト一覧から172.16.0.0/12を削除

スクリーンショット: cURLブロック済みホスト一覧(172.16.0.0/12 を削除した状態)

設定後の内容:

127.0.0.0/8
192.168.0.0/16
10.0.0.0/8
0.0.0.0
localhost
169.254.169.254
0000::1

② cURL許可済みポートに11434を追加

443
80
11434

スクリーンショット: 許可済みポート11434を追加した状態

この設定を忘れると、Moodle側でAI生成を実行したときに「何か問題が発生しました。後でもう一度」というエラーが表示され続けます。

5-4. AI Placementsの有効化

第一弾と同じ手順です。

サイト管理 → 一般 → AI → AI配置
→ テキストエディタ配置:ON
→ コースアシスタンす配置:ON → 設定 → コーステキストのコンテン  ツを要約します:有効

スクリーンショット: AI配置設定画面(両方オンの状態)

6. 動作確認

テキスト生成

  1. コース内で「テキストとメディア」などを編集モードで追加
  2. TinyMCEツールバーの ✨アイコン をクリック
  3. 「テキストを生成する」を選択
  4. プロンプトを入力して送信

スクリーンショット: TinyMCEのAIテキスト生成ダイアログ(プロンプト入力中)
「レスポンスを生成する」→「もう少し」と表示された後、生成されたテキストがエディタに挿入されます。

OpenAIに比べると応答に数秒〜十数秒かかりますが、CPU推論ではこれが標準的な速度です。

AI要約

Course Assistanceの要約ボタンは、アクティビティの閲覧画面全般に表示されます。ページ・課題・小テスト・フォーラムなど多くのアクティビティで利用できます。

アクティビティ 要約ボタン 備考
ページ(mod/page) 本文がそのまま要約される。最も効果的
課題(mod/assign) 課題の説明文が要約される
小テスト(mod/quiz) 小テストの説明文が要約される
テキストとメディア(label) コースページ直貼りのため対象外

アクティビティによって要約できるコンテンツの量が異なります。本文が充実している「ページ」アクティビティが最も効果的です。

「ページ」アクティビティでの確認手順:

  1. 「ページ」アクティビティにテキストを入力して保存
  2. 閲覧モード(編集モードOFF)でページを開く
  3. 画面右側に「AI要約」パネルが表示される
  4. 「要約」をクリック

スクリーンショット: ページアクティビティのAI要約パネル(日本語で要約された状態)

7. OpenAI vs Ollama まとめ比較

比較項目 OpenAI(第一弾) Ollama(本記事)
データの送信 OpenAIサーバーへ送信 サーバー内で完結
ランニングコスト 従量課金 無料
応答速度 速い(1〜2秒) やや遅い(5〜15秒)
日本語品質 非常に高い 良好(qwen2.5:7b)
セットアップ 簡単 やや手間がかかる
オフライン動作 不可 可能
モデルの選択肢 OpenAIのモデルのみ 100以上から選択可
向いている用途 手軽に高品質なAIを使いたい データを外に出せない

どちらが優れているというわけではなく、運用ポリシーと用途によって使い分けるのが現実的です。

8. 実際にハマったポイント(トラブルシューティング)

本記事の検証中に遭遇した問題を記録しておきます。他のブログではあまり見かけない情報です。

① cURLブロックリストの172.16.0.0/12問題

最も時間がかかった問題です。Moodle管理画面の「cURLブロック済みホスト」リストにollamaという文字列が自動登録されていたため、最初にそれを削除しました。しかし、それだけでは解決しませんでした。

OllamaのDockerコンテナIPが172.20.0.11であり、これが172.16.0.0/12のCIDR範囲(172.16.0.0172.31.255.255)に含まれていたため、ホスト名ではなくIPレベルでブロックされていたのです。

# ブロックされているか確認するコマンド
docker exec -it moodle45 php -r "
define('CLI_SCRIPT', true);
require('/var/www/html/config.php');
\$helper = new \core\files\curl_security_helper();
\$url = 'http://ollama:11434/v1/chat/completions';
echo 'blocked: ' . (\$helper->url_is_blocked(\$url) ? 'YES' : 'NO') . PHP_EOL;
"

blocked: YESが返る場合は、ブロックリストから172.16.0.0/12を削除してください。

② エンドポイントは/v1ではなく/v1/chat/completions

アクション設定でエンドポイントをhttp://ollama:11434/v1と入力した場合、/v1エンドポイントはOllamaに存在しないため404が返ります。必ず/v1/chat/completionsまでフルパスで入力してください。

③ ポート11434の許可を忘れずに

cURLのブロックリスト設定と同じ画面に「cURL許可済みポート」があります。デフォルトは44380のみです。11434を追加しないと、ブロックリストの解除とは別にポートレベルでブロックされます。

④ Course Assistanceはアクティビティの閲覧画面に表示される

「テキストとメディア(label)」ではAI要約ボタンが表示されません。「ページ」「課題」「小テスト」などのアクティビティを閲覧モードで開いてください。なお、小テストやフォーラムでは説明文のみが要約対象となるため、コンテンツが少ない場合は有用な要約が得られないことがあります。本文が充実した「ページ」アクティビティが最も効果的です。

⑤ Moodle 4.5にはOllama専用プロバイダーが存在しない

aiprovider_ollamaプラグインはMoodle 5.0以降でのみ利用できます。Moodle 4.5ではaiprovider_openaiプラグインのエンドポイントをOllamaのURLに書き換えることで対応します。

まとめ

Moodle 4.5 × OllamaのローカルLLM構成を実現するための要点です。

ステップ 内容
1 docker-compose.ymlにollamaサービスを追加
2 qwen2.5:7bをpull
3 OpenAI APIプロバイダーを作成し、APIキーにollamaを入力
4 アクション設定でエンドポイントをhttp://ollama:11434/v1/chat/completionsに変更
5 cURLブロックリストから172.16.0.0/12を削除、ポート11434を追加
6 AI Placementsを有効化

データを外部に送らず、APIコストもゼロで、Moodle 4.5のAI機能をフル活用できます。個人情報・機密情報を扱う教育機関・企業研修での導入に、ぜひ参考にしてください。

参考リンク


※ この記事は Zenn (rublix) にも投稿しています。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?