2024年2月14日水曜日

OllamaでCode Llamaを実行しAPEXアプリケーションからコードを生成させる

Oracle APEX界隈で著名なPlamen Muskovさんが、X(旧Twitter)にてOllamaを使ってLLaVAを呼び出すAPEXアプリケーションを作ったと投稿していました。


Ollamaであれば簡単にCode Llamaを動かすことができそうなので、以前に作成した環境で試してみました。Ollamallama_cpp.serverと同様に、APIサーバーとして動作します。

llama_cpp.serverをAmpere A1のインスタンス上で動かしてみる
https://apexugj.blogspot.com/2023/07/llamacppserver-on-ap.html

以下はその作業の記録です。

OllamaのGitHubのページに、Ollamaのインストール手順が記載されています。

Always FreeのAmpere A1のコンピュート・インスタンスが作成済みとします。OSはUbuntuです。接続ユーザーはubuntu(Oracle Linuxのインスタンスでのopcに当たります)になります。

ユーザーubuntuで接続し、Linux & WSL2のインストール手順として記載されている以下のコマンドを実行します。

ubuntu@mywhisper2:~$ curl -fsSL https://ollama.com/install.sh | sh

>>> Downloading ollama...

######################################################################## 100.0%######################################################################### 100.0%

>>> Installing ollama to /usr/local/bin...

>>> Creating ollama user...

>>> Adding ollama user to render group...

>>> Adding current user to ollama group...

>>> Creating ollama systemd service...

>>> Enabling and starting ollama service...

Created symlink /etc/systemd/system/default.target.wants/ollama.service → /etc/systemd/system/ollama.service.

>>> The Ollama API is now available at 0.0.0.0:11434.

>>> Install complete. Run "ollama" from the command line.

WARNING: No NVIDIA GPU detected. Ollama will run in CPU-only mode.

ubuntu@mywhisper2:~$


インストールを実行しているユーザーがroot権限を持っているか、sudoでroot権限を取れることが前提のようです。スクリプトの実行が完了すると、OSのサービスとしてollamaがインストールされます。また/usr/local/bin以下にollamaが作成されます。

インストール直後にollamaがサービスとして起動します。サービスの起動と終了にはsystemctlコマンドを使用します。

モデルcodellamaを呼び出せるように、ダウンロードします。

ubuntu@mywhisper2:~$ ollama run codellama

pulling manifest 

pulling 3a43f93b78ec... 100% ▕████████████████▏ 3.8 GB                         

pulling 8c17c2ebb0ea... 100% ▕████████████████▏ 7.0 KB                         

pulling 590d74a5569b... 100% ▕████████████████▏ 4.8 KB                         

pulling 2e0493f67d0c... 100% ▕████████████████▏   59 B                         

pulling 7f6a57943a88... 100% ▕████████████████▏  120 B                         

pulling 316526ac7323... 100% ▕████████████████▏  529 B                         

verifying sha256 digest 

writing manifest 

removing any unused layers 

success 

>>> /?

Available Commands:

  /set            Set session variables

  /show           Show model information

  /load <model>   Load a session or model

  /save <model>   Save your current session

  /bye            Exit

  /?, /help       Help for a command

  /? shortcuts    Help for keyboard shortcuts


Use """ to begin a multi-line message.


>>> /bye

ubuntu@mywhisper2:~$


以上でCode Llamaを呼び出す準備ができました。

OllamaはデフォルトでTCPポート11434を開けて、REST APIの要求を待ち受けます。

firewalldに対して、TCPポート11434への接続を許可します。

ubuntu@mywhisper2:~$ sudo firewall-cmd --add-port=11434/tcp

You're performing an operation over default zone ('public'),

but your connections/interfaces are in zone 'docker' (see --get-active-zones)

You most likely need to use --zone=docker option.


success

ubuntu@mywhisper2:~$ 


変更を永続化します。

ubuntu@mywhisper2:~$ sudo firewall-cmd --runtime-to-permanent

success

ubuntu@mywhisper2:~$ 


リクエストをHTTPSで受け付けてHTTPでllama_cpp.serverを呼び出していたNginxの設定を変更します。/etc/nginx/conf.d以下のserver.confに含まれるproxy_passの行のポート番号を8000から11434に変更します。

proxy_pass http://localhost:11434/;

以上の変更を行なった後にNginxを再起動すると、Ollamaを呼び出せる状態になります。

OllamaとCode Llamaを呼び出すAPEXアプリケーションについて、簡単に紹介します。

OllamaはOpenAIのchat completions互換APIをサポートしているとのことですが、今回はCode Llamaを呼び出すので、単純にGenerate a completionを呼び出すことにしました。

ページ・アイテムP1_MODELモデル名を設定します。今回はcodellamaの指定だけを想定していますが、一応変更できます。P1_MESSAGEプロンプトとなる文章を入力します。Generation APIの呼び出しに与える値は以上です。

ページ・アイテムP1_RESPONSEにCode Llamaの出力を表示します。マークダウンが返されるため、アイテム・タイプMarkdownエディタを選択しています。ページ・アイテムP1_STATSにAPI呼び出しに関する統計情報を表示します。

Ollama/Code Llamaの呼び出しは、ボタンSEND_MESSAGEに実装した動的アクションにより実行します。TRUEアクションサーバー側のコードを実行PL/SQLコードとして以下を記述します。Ollamaのレスポンスはデフォルトでストリーミングで、ストリーミング出力にしないとNginxがタイムアウトするため、APEX側でCode Llamaのレスポンスをつなげ合わせています。



アプリケーション定義置換に置換文字列G_ENDPOINTとして、OllamaのAPI呼び出しのエンドポイント(https://ホスト名/api/generate)、G_TRANSFER_TIMEOUTにAPEX側のAPEX_WEB_SERVICE.MAKE_REST_REQUESTのp_transfer_timeoutに与える秒数を指定します。

以下、プロンプトとして以下を与えた結果です。

「フィボナッチ数列の12番目の数を表示するJavaScriptのコードを教えてください。」

レスポンスが返されるまで2分はかかるので実用性はありませんが、Code Llamaが日本語を受け付けてレスポンスも日本語で返してきたのには、少し驚きました。


今回作成したAPEXアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/ollama-codellama-app.zip

Oracle APEXのアプリケーション作成の参考になれば幸いです。