何回か同じようなタイトルで書いていますが,今回はLLMを利用する上での採点補助サーバーです。
採点補助サーバーとは何を言っているかというと,具体的な採点のみを担当して,採点結果の記録などはとらないサーバーのことです。LMS から来たリクエストを最初に受けるのが kanaike というサーバーです。kanaike は採点の差配と記録と返事を担当します。以前に書いた絵ですが,下記のような連携です。
実際の採点処理,数式の正誤判定とかですが,それは kanaike とは別のサーバーで担当します。別に分けた理由は,将来的に AI 的な処理をする場合にビデオカードなどのハードを利用する必要があるだろうと予想したためです。kanaike は仮想で運用されてます。デフォルトの採点処理担当は仮想で用意しますが,これには最大公約数的な共通する採点機能を置く感じです。その上で別の採点処理担当のサーバーを用意することになるのではないかと考えました。こうしておけば,それぞれの教師の手近なところでカスタマイズされた採点処理が可能となります。手近なところになければ,カスタマイズは難しいですし,またデフォルトが別に稼働していますので,安定性を検証する必要もそれほどありません。他の人への迷惑を考える必要がありませんから。こういったことを考えて,具体的な採点処理を kanaike から外しました。
話が長くなりそうですが,このような外部に置く採点サーバーでは,最初は機械学習的なものの利用を考えていました。そうすると採点の機能ごとに個別の重み(パラメータ)などが必要です。それもあって,教師の手近に置いた方が良いと考えていたのですが,最近の言語モデルなら,プロンプトに書く内容で,その機能を変化させることが可能なようです。そうであればある程度汎用品が見えてくるのかもしれません。おそらく一台では難しいので下図のように複数台で構成されるサーバー群になりそうです。一台の仕切るサーバー(仮想)とその周りに ollama か何かが動く複数台のサーバー(物理サーバー)を想定しています。
一台の仕切るサーバーが仮想なのは,このサーバーは特殊なものなのでサンプルをこちらで用意しておいてコピーを配布するためです。ollama が動くサーバーは一般的な構成で考えています。普通に ollama がAPIを通じて利用できる様にしておく感じです。ともかく LLM を利用する採点補助サーバー群の構築のために,この仕切る仮想サーバーの構築作業をまとめます。と言ってもインストール手順のようなものだけで,そこで差配したり採点処理をするソフトの話は除きます。
さて,始めます。OS は ubuntu 24 です。最初に synaptic を入れました。それを使って git を入れました(必要だったかな?)。
apache のインストールです。
sudo apt install apache2
phpのインストールです。
sudo apt install php
phpinfoコマンドを試しました。これはゆくゆくは削除しとかないと。
<?php
phpinfo();
?>
upload ファイルサイズ等の変更をします。/etc/php/8.3/apache2/php.ini を書き換えます。apache の再起動をすれば反映されます。phpinfo の情報で確認します。
post_max_size = 大きな値
upload_max_filesize = 大きな値
max_execution_time = 大きな値
memory_limit = 大きな値
php-xml のインストール。synaptic から。simplexml_load_string を利用するため。
synaptic から php-mbstring を追加する。この辺を有効にしたいときには apache の再起動が必要です。
Python 関連。もともと入っている Python のバージョンは下記。
$ python3 --version
Python 3.12.3
Python の準備。ライブラリーなどを用意する。synaptic から pandas、numpy(すでに入っていた)、sympy(すでに入っていた)、pip をインストール。この仮想マシンでは cupy などは必要ない。wsgi も利用しない。これらのライブラリーはグローバルにインストールします。このサーバーでやることは特殊な環境を用意しなくてもすむ範囲内にとどめたいと思います。
build-essential をインストールしようとしたら、すでに入っていた。これは maxima のインストールに必要です。
maxima のインストール。たぶんまだ数式自動採点の結果は必要だと思うので maxima をインストールします。synaptic から gnuplot, texinfo, sbcl 2.2.9 をインストールします。maxima は 5.36.0 を sbcl オプションをつけて以下の様にコンパイルします。ソースはここからダウンロードします。 それをホームディレクトリー等で展開して,そのフォルダーに移動します(後は下記のコード参照)。
cd ./maxima-5.36.0
./configure –enable-sbcl
make
sudo make install
maxima のコンパイルにエラーはありませんでした。古い maxima を利用しているので、ここは心配なところです。古い maxima をなぜ使っているかというと、古い STUCK のパーツを利用しているからです。それに合わせてその頃の maxima のバージョンを使い続けています。
/var/www の内容を準備。コピーして配置。temporary の所有権を www-data に変更します。採点用のプログラムに関しても今回は修正が必要なものがあります。
maxima-optimised の再構築をします。maximalocal.mac のあるフォルダーのところに移動しておいて、maxima を起動します。それから下記のコマンドを打ちます。
(%i1) load("maximalocal.mac");
上記の出力は下記です。失敗に気づくように出力も記録しておきます。
; compiling file "/usr/local/share/maxima/5.36.0/share/draw/grcommon.lisp" (written 04 SEP 2026 12:36:27 PM):
; wrote /home/friend/.maxima/binary/5_36_0/sbcl/2_2_9_debian/share/draw/grcommon.fasl
; compilation finished in 0:00:00.532
;; loading #P"/home/friend/.maxima/binary/5_36_0/sbcl/2_2_9_debian/share/draw/grcommon.fasl"
; compiling file "/usr/local/share/maxima/5.36.0/share/draw/gnuplot.lisp" (written 04 SEP 2026 12:36:27 PM):
; file: /usr/local/share/maxima/5.36.0/share/draw/gnuplot.lisp
; in: DEFUN REGION
; (MAKE-ARRAY (LIST (1+ MAXIMA::NX) (1+ MAXIMA::NY)) :ELEMENT-TYPE 'BOOLEAN)
;
; caught STYLE-WARNING:
; The default initial element 0 is not a BOOLEAN.
; See also:
; The ANSI Standard, Function MAKE-ARRAY
; The ANSI Standard, Function UPGRADED-ARRAY-ELEMENT-TYPE
; wrote /home/friend/.maxima/binary/5_36_0/sbcl/2_2_9_debian/share/draw/gnuplot.fasl
; compilation finished in 0:00:01.263
;; loading #P"/home/friend/.maxima/binary/5_36_0/sbcl/2_2_9_debian/share/draw/gnuplot.fasl"
; compiling file "/usr/local/share/maxima/5.36.0/share/draw/vtk.lisp" (written 04 SEP 2026 12:36:27 PM):
; wrote /home/friend/.maxima/binary/5_36_0/sbcl/2_2_9_debian/share/draw/vtk.fasl
; compilation finished in 0:00:00.941
;; loading #P"/home/friend/.maxima/binary/5_36_0/sbcl/2_2_9_debian/share/draw/vtk.fasl"
; compiling file "/usr/local/share/maxima/5.36.0/share/draw/picture.lisp" (written 04 SEP 2026 12:36:27 PM):
; wrote /home/friend/.maxima/binary/5_36_0/sbcl/2_2_9_debian/share/draw/picture.fasl
; compilation finished in 0:00:00.101
;; loading #P"/home/friend/.maxima/binary/5_36_0/sbcl/2_2_9_debian/share/draw/picture.fasl"
;
; compilation unit finished
; caught 1 STYLE-WARNING condition
WARNING: redefining MAXIMA::TEX-MQUOTIENT in DEFUN
WARNING: redefining MAXIMA::TEX-PREFIX in DEFUN
WARNING: redefining MAXIMA::TEX-STRING in DEFUN
WARNING: redefining MAXIMA::TEX-DERIVATIVE in DEFUN
WARNING: redefining MAXIMA::TEX-D in DEFUN
WARNING: redefining MAXIMA::TEX-DABBREV in DEFUN
WARNING: redefining MAXIMA::TEX-INT in DEFUN
[ STACK-Maxima started, library version 2015060800 ]
(%o0) "maximalocal.mac"
うまくいったのだと思います。続いて下記のコマンドを打ちます。
:lisp (sb-ext:save-lisp-and-die "maxima-optimised" :toplevel #'run :executable t);
今度は出力は無くて、maxima も終了します。フォルダーを見ると maxima-optimised という 70MB あたりの大きさのファイルが作られていました。ここで採点プログラムを試した方がいいと思って、採点プログラムの中身を調べて見ました。
とりあえず、数式の自動採点は動いているようでした。
プログラムを見ていてvideo の処理もあるかもと思って、ffmpeg を synaptic からインストールしました。
apache のエラーログを見ていたら tex が無いとか言われていたので、インストールしました。
sudo apt install texlive-full
このあと、他の採点機能も試してみました。採点の際に maxima や Python が動きますが、Python に関して今回は wsgi を使いません。直接 Python を実行します。つまり exec にコードを渡します。LLM を動かすとなると採点にかかる時間はいずれにせよ長くなるので、複雑な wsgi を使うのを止めました。そうすると回答がバイナリーデータを含んでいるときに、exec に渡すには文字列が大きくなりすぎてエラーとなりました。それでバイナリーデータは、といっても base64 変換されたテキストデータなのですが、いったん PHP からテキストファイルとして書き出して、Python からそれを読み込むようにしました。色々ありますね。
採点プログラムの検討はこれぐらいにして、設定の仕上げです。
apache の言語の設定をします。 php での日本語の取り扱いに関するものです(参考サイト)。作業内容を下記に引用します。
/etc/apache2/envvars を修正。export LANG=C の行をコメントアウトして、export LANG=ja_JP.UTF-8 を追加。下記のような感じです。
# export LANG=C
export LANG=ja_JP.UTF-8
apache のバージョンを返さないように設定を変更する。/etc/apache2/conf-available/security.conf において
ServerTokens Prod
ServerSignature Off
emporary フォルダーの中身を定期的に削除する設定(参考サイト)をする。直接設定を記述します。
/etc/crontab を /etc/cron.d/ へ、適当な名前をつけてコピーする。拡張子無しのファイル名を付ける。
sudo cp ./crontab ./cron.d/newName
もともとファイルに記述されていた命令のリストを削除して(多分削除しないと二重になると思います)、実行したいファイル(ここでは php ファイル)を指定する。参考サイトに注意点が多々ある。/bin/bash となっていることの確認や、スペースとタブの使い方が厳密であることなどである。下記は毎日12時ちょうどに実行する指定である。
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
# Example of job definition:
# .---------------- minute (0 - 59)
# | .------------- hour (0 - 23)
# | | .---------- day of month (1 - 31)
# | | | .------- month (1 - 12) OR jan,feb,mar,apr ...
# | | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# | | | | |
# * * * * * user-name command to be executed
0 0 * * * root php /var/www/html/xxx/xxxxx.php
だいたいこのようなところかと思います。あとは採点プログラムを修正することが残っています。外部の ollama サーバーにいかににつなぐかを考えないと。
追加 20260917
curl のインストール。ollama サーバーとの通信をなるべく curl のみでやりたいです。Python を www-data で実行することを考えたら, curl のみの方が良い。
追加 20260927
方針を変えました。結局 ollama の Python ライブラリーを使うことになりました。利用方法は グローバルに ollama を使用できるようにするのとは少し違うやり方です。特定の環境でライブラリーをインストールした後,そのファイルを www-data がアクセス可能なフォルダーにコピーします。それを下記のように読みこめるようにパスを登録します。
import sys
sys.path.insert(0, '/どこか/lib/python3.12/site-packages/')
import ollama
こんな感じでライブラリーを利用することにしました。
複数台の ollama サーバー群を作る話には,進展がありました。NVIDIA が先日公表した PAIR を利用しようと思います。
参考記事…西川和久の不定期コラム:家庭にあるPCのLLMリソースを束ねるNVIDIA「PAIR」、早速試してみた!
ollama をインストールしてあるパソコンに,PAIR をインストールします。そうすると ollama のポート番号とは別に,PAIR 用のポート番号が割り振られます。
上図のように URL はローカルのみなのですが,このローカルのポートにアクセスして利用します。ローカルのみなので使用するには以下の様にしようと思います。この仮想で運用する採点サーバーに ollama と PAIR をインストールして,LLM のモデルは何も入れないようにします。その状態なら ローカルの PAIR にリクエストをすれば,すべてのリクエストが PAIR のクラスターを組む他のパソコンに流れます。
上図はクラスターを組む二つのパソコンのパフォーマンスメーター?が表示されています。左端に現在のジョブ(リクエスト)が表示されていて,それが2台目のパソコンで処理されている状況を示しています。処理しているパソコンと線で結ばれています。PAIR は設定も簡単なので,当面これを試してみようと思います。
この PAIR のクラスターで下図のようなことをやります。下図は e-Learning の教材です。受講者の回答に対して批評させてみました。問題の内容は画像情報として与えています。LLM は gemma4:12b です。プロンプトは下記。
「画像は穴埋め問題です。回答者は問いの1番の答えとして タヌキ と答えてきています。正解は 猫型ロボット と設定されています。回答者の回答が適切かどうか判断してください。」
この通信は返事に1分から長い時には3分ほどかかります。




