2024年5月21日火曜日

LM Studioのローカル・サーバーをOracle APEXのアプリケーションから呼び出す

AppleのMシリーズのMacbookにLM Studioをインストールして、 ローカル・サーバー(Local Inference Server)を実行してみます。OpenAI互換のChat Completions APIを呼び出すOracle APEXアプリケーションから、このローカル・サーバーを呼び出しLLMとチャットを行います。

以下のようにAPEXアプリケーションよりChat Completions APIを発行し、LM Studioのローカル・サーバーで処理を行います。


私のMacbookはメモリに余裕があるので、実行するモデルとして
ELYZA-japanese-Llama-2-7b-fast-instruct-q8_0.ggufをロードしてみます。使用できるメモリが少ない場合は、低いビット数で量子化されたモデルを選ぶと良いでしょう。

LM Studioをインストールして起動した状態から、作業を始めます。

検索(Search)画面を開き、検索ボックスからELYZAを検索します。検索結果より
ELYZA-japanese-Llama-2-7b-fast-instruct-q8_0.ggufをダウンロードします。


ダウンロードされたら、モデル(My Models)の画面を開き、ダウンロードされたモデルがあることを確認します。


ローカル・サーバー(Local Server)の画面を開きます。


ローカル・サーバーの構成を指定します。

Server Port8080とします。すでにポートが使用中であれば違う番号にします。Cross-Origin-Resource-Sharing(CORS)OFFRequest QueuingVerbose Server LogsApply Prompt FormattingONとします。


画面上部のSelect a model to loadをクリックし、ダウンロード済みのモデルELYZA japanese Llama 2 fast instructを選択します。


モデルがロードされるとローカル・サーバーが起動します。

OpenAI互換のChat Completions APIは以下のURLより呼び出すことができます。

http://localhost:8080/v1/chat/completions


OpenAI互換のサーバーが起動したので、Oracle APEXの準備に移ります。

Apple MシリーズでOracle APEXを動かす手順は、いくつかの記事に分かれて公開されています。そのため、手順が間違いやすくなっています。今回は、Oracle Database 23ai Freeのコンテナ・イメージより環境を作る一連の手順を、簡単に紹介します。

Apple MシリーズでOracle APEX(より正確にはOracle Database Freeのコンテナ・イメージ)は、Colimaを使って動作させます。Colimaはインストール済みとします。

以下の例ではmemory10G、cpu8を割り当てています。

colima start --arch x86_64 --memory 10 --cpu 8

% colima start --arch x86_64 --memory 10 --cpu 8 

INFO[0000] starting colima                              

INFO[0000] runtime: docker                              

INFO[0001] starting ...                                  context=vm

INFO[0048] provisioning ...                              context=docker

INFO[0049] starting ...                                  context=docker

INFO[0055] done                                         

% 


稼働中のColimaのパラメータを確認します。

colima list

% colima list

PROFILE    STATUS     ARCH      CPUS    MEMORY    DISK     RUNTIME    ADDRESS

default    Running    x86_64    8       10GiB     60GiB    docker     

% 


ディレクトリsetupstartupを作成します。

mkdir setup startup

% mkdir setup startup

% 


Oracle Database Freeのコンテナ・イメージから、コンテナapexdbを作成します。

docker run -d --name apexdb -e ORACLE_PWD=<SYSパスワード> -p 1521:1521 -p 8181:8181 -v `pwd`/setup:/opt/oracle/scripts/setup -v `pwd`/startup:/opt/oracle/scripts/startup container-registry.oracle.com/database/free:latest

コンテナ・イメージが未ダウンロードであれば、最初にコンテナ・イメージのダウンロードが行われ(pull処理)、続けてコンテナの作成が行われます。

% docker run -d --name apexdb -e ORACLE_PWD=oracle -p 1521:1521 -p 8181:8181 -v `pwd`/setup:/opt/oracle/scripts/setup -v `pwd`/startup:/opt/oracle/scripts/startup container-registry.oracle.com/database/free:latest

ea83b07c417380c356c0f07cd64a82deca29c8c1f86246e3b66c298064ce494b

%


コンテナが作成され、Oracle Database 23ai Freeが実行されていることを、ログより確認します。

docker logs -f apexdb

% docker logs -f apexdb

Starting Oracle Net Listener.

Oracle Net Listener started.

Starting Oracle Database instance FREE.

Oracle Database instance FREE started.


The Oracle base remains unchanged with value /opt/oracle


SQL*Plus: Release 23.0.0.0.0 - Production on Tue May 21 06:29:42 2024

Version 23.4.0.24.05


Copyright (c) 1982, 2024, Oracle.  All rights reserved.



Connected to:

Oracle Database 23ai Free Release 23.0.0.0.0 - Develop, Learn, and Run for Free

Version 23.4.0.24.05


SQL> 

User altered.


SQL> 

User altered.


SQL> 

Session altered.


SQL> 

User altered.


SQL> Disconnected from Oracle Database 23ai Free Release 23.0.0.0.0 - Develop, Learn, and Run for Free

Version 23.4.0.24.05

The Oracle base remains unchanged with value /opt/oracle

#########################

DATABASE IS READY TO USE!

#########################

The following output is now a tail of the alert.log:

===========================================================

No patches have been applied

===========================================================

2024-05-21T06:29:36.336370+00:00

FREEPDB1(3):Opening pdb with Resource Manager plan: DEFAULT_PLAN

2024-05-21T06:29:38.359742+00:00

Completed: Pluggable database FREEPDB1 opened read write 

Completed: ALTER DATABASE OPEN

2024-05-21T06:29:47.296396+00:00

FREEPDB1(3):TABLE AUDSYS.AUD$UNIFIED: ADDED INTERVAL PARTITION SYS_P304 (3613) VALUES LESS THAN (TIMESTAMP' 2024-05-22 00:00:00')

2024-05-21T06:30:43.705898+00:00

TABLE SYS.WRP$_REPORTS: ADDED AUTOLIST FRAGMENT SYS_P373 (3) VALUES (( 1439224760, TO_DATE(' 2024-05-20 00:00:00', 'syyyy-mm-dd hh24:mi:ss', 'nls_calendar=gregorian') ))

2024-05-21T06:30:44.859763+00:00

TABLE SYS.WRP$_REPORTS_DETAILS: ADDED AUTOLIST FRAGMENT SYS_P374 (3) VALUES (( 1439224760, TO_DATE(' 2024-05-20 00:00:00', 'syyyy-mm-dd hh24:mi:ss', 'nls_calendar=gregorian') ))

TABLE SYS.WRP$_REPORTS_TIME_BANDS: ADDED AUTOLIST FRAGMENT SYS_P377 (3) VALUES (( 1439224760, TO_DATE(' 2024-05-20 00:00:00', 'syyyy-mm-dd hh24:mi:ss', 'nls_calendar=gregorian') ))



DATABASE IS READY TO USE!と表示されていると、データベースは利用可能です。

稼働中のデータベースにOracle APEXをインストールします。

ディレクトリsetupの下に、以下のAPEXの自動インストール・スクリプトを配置します。ファイル名は01_install_apex.shとして、実行権限を与えます。

chmod 755 setup/01_install_apex.sh

Colimaの環境では、なぜかOpenJDKではORDSのインストール時にエラーが発生するため、Oracle JDK 17をインストールするようにします。

スクリプトを一部変更します。OpenJDK17をコメントアウトし、Oracle JDK 17のコメントを外します。
#################################################################################
# Install JDK
# Oracle JDK must be chosen for Colima on Apple M Servces Mac.
################################################################################
# Step 1: Install Oracle JDK17
##### OpenJDK 17
#echo "Install OpenJDK 17 for ORDS..." > ${LOGFILE}
#su -c "dnf -y install java-17-openjdk-headless"
##### Oracle JDK 17
echo "Install Oracle JDK 17 for ORDS..." > ${LOGFILE}
curl -OL https://download.oracle.com/java/17/latest/jdk-17_linux-x64_bin.rpm
su -c "dnf -y localinstall jdk-17_linux-x64_bin.rpm"
rm -f jdk-17_linux-x64_bin.rpm
##### GraalVM CE to support GraphQL in ORDS.
#echo "Install GraalVM22 for GraphQL ..." > ${LOGFILE}
#su -c "dnf -y --repofrompath ol8_graalvm,https://yum.oracle.com/repo/OracleLinux/OL8/graalvm/community/x86_64 install graalvm22-ce-17-jdk graalvm22-ce-17-javascript"
echo "Done." >> ${LOGFILE}
ディレクトリstartupの下にORDSを起動するスクリプトを配置します。ファイル名は01_ords.shとして、実行権限を与えます。

chmod 755 startup/01_ords.sh


インストール・スクリプト01_install_apex.shを、コンテナの中で実行します。

docker exec -it apexdb /opt/oracle/scripts/setup/01_install_apex.sh

先ほどのCPU数が8、メモリが10GBのColimaの環境で1時間半程度の時間がかかりました。

% docker exec -it apexdb /opt/oracle/scripts/setup/01_install_apex.sh

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current

                                 Dload  Upload   Total   Spent    Left  Speed

100  174M  100  174M    0     0  7739k      0  0:00:23  0:00:23 --:--:-- 6342k

Oracle Linux 8 BaseOS Latest (x86_64)                            4.0 MB/s |  74 MB     00:18    

Oracle Linux 8 Application Stream (x86_64)                       5.8 MB/s |  56 MB     00:09    

Oracle Linux 8 Development Packages (x86_64)                     6.1 MB/s | 137 MB     00:22    

Last metadata expiration check: 0:01:16 ago on Tue May 21 06:54:46 2024.

Dependencies resolved.

=================================================================================================

 Package            Architecture       Version                    Repository                Size

=================================================================================================

Installing:

 jdk-17             x86_64             2000:17.0.11-7             @commandline             174 M


Transaction Summary

=================================================================================================

Install  1 Package


Total size: 174 M

Installed size: 304 M

Downloading Packages:


[中略]


Configuration:

  /etc/ords/config


The global setting named: standalone.static.context.path was set to: /i


ORDS: Release 24.1 Production on Tue May 21 08:14:28 2024


Copyright (c) 2010, 2024, Oracle.


Configuration:

  /etc/ords/config


The global setting named: standalone.static.path was set to: /opt/oracle/apex/23.2.0/images

% 


コンテナapexdbを再起動します。

docker restart apexdb

% docker restart apexdb

apexdb

%


コンテナの起動状況を確認します。qemuによるx86_64のエミュレーションが行われているため、ステータスがhealtyになるまで、少々時間がかかります。

% docker ps

CONTAINER ID   IMAGE                                                COMMAND                   CREATED       STATUS                        PORTS                                                                                  NAMES

ea83b07c4173   container-registry.oracle.com/database/free:latest   "/bin/bash -c $ORACL…"   2 hours ago   Up About a minute (healthy)   0.0.0.0:1521->1521/tcp, :::1521->1521/tcp, 0.0.0.0:8181->8181/tcp, :::8181->8181/tcp   apexdb

% 


ステータスがhealthyになったところで、ローカルのブラウザよりAPEXの管理サービスへ接続します。


管理サービスにサインインします。管理ユーザーはadmin、初期パスワードはWelcome_1です。


APEXのインストール直後は、開発に使用するワークスペースはありません。そのため、ワークスペースの作成を勧められます。

ワークスペースを作成します。


新規に作成するワークスペース名はapexdevとします。

へ進みます。


ワークスペースに紐づくスキーマを新規作成します。

既存のスキーマの再利用いいえスキーマ名はAutonomous Databaseの命名規則に合わせてwksp_apexdevとします。スキーマのパスワードを設定します。

領域割当て制限(MB)は最大の10000を選択します。

へ進みます。


ワークスペースの管理者を設定します。

管理者のユーザー名adminとします。管理者のパスワード(これは初期パスワードなので、初回サインイン時に変更を求められます)と、電子メールを設定します。電子メールを送信するには、メールの送信を行なう電子メール・サーバーを設定する必要があります。

へ進みます。


以上の設定で、ワークスペースを作成します。


ワークスペースが作成されます。


Oracle APEXのワークスペースからOpenAI互換のAPIを呼び出せるように、APEXがインストールされたスキーマAPEX_230200にネットワークACLを追加します。

作成したコンテナに接続します。

docker exec -it apexdb /bin/bash

% docker exec -it apexdb /bin/bash

bash-4.4$ 


FREEPDB1のPDBで、以下のスクリプトを実行します。
begin
  DBMS_NETWORK_ACL_ADMIN.APPEND_HOST_ACE(
    host => '*',
    ace => xs$ace_type(
        privilege_list => xs$name_list('connect'),
        principal_name => 'APEX_230200',
        principal_type => xs_acl.ptype_db));
  commit; 
end;
/

bash-4.4$ sqlplus / as sysdba


SQL*Plus: Release 23.0.0.0.0 - Production on Tue May 21 08:43:38 2024

Version 23.4.0.24.05


Copyright (c) 1982, 2024, Oracle.  All rights reserved.



Connected to:

Oracle Database 23ai Free Release 23.0.0.0.0 - Develop, Learn, and Run for Free

Version 23.4.0.24.05


SQL> alter session set container = freepdb1;


Session altered.


SQL> begin

  DBMS_NETWORK_ACL_ADMIN.APPEND_HOST_ACE(

    host => '*',

    ace => xs$ace_type(

        privilege_list => xs$name_list('connect'),

        principal_name => 'APEX_230200',

        principal_type => xs_acl.ptype_db));

  commit; 

end;

/  2    3    4    5    6    7    8    9   10  


PL/SQL procedure successfully completed.


SQL> exit

Disconnected from Oracle Database 23ai Free Release 23.0.0.0.0 - Develop, Learn, and Run for Free

Version 23.4.0.24.05

bash-4.4$


Oracle APEXの開発ツールにサインインします。

http://localhost:8181/ords/apex

ワークスペースapexdev、サインインするユーザーadminパスワードにワークスペース作成時に指定した初期パスワードを入力します。

サインインします。


初期パスワードを変更します。


Oracle APEXの開発画面が開きます。


これからは、以下の記事で作成しているAPEXアプリケーションをインストールします。

OpenAIのChat Completions APIを呼び出すAPEXアプリを作成する
https://apexugj.blogspot.com/2024/04/chat-with-generative-ai-sample-app-0.html

OpenAIのChat Completions APIを呼び出すパッケージUTL_OPENAI_CHAT_APIは、表OPENAI_TOOLSを参照するため、あらかじめ表OPENAI_TOOLSを作成します。


SQLワークショップSQLスクリプトより、作成を実行します。


実行するスクリプトを貼り付け、スクリプト名を入力して実行します。


スクリプトは即時実行します。


表OPENAI_TOOLSが作成されます。


同様の手順にて、パッケージUTL_OPENAI_CHAT_APIのパッケージ定義部と本体を作成します。

パッケージ定義
パッケージ本体

エクスポートされたAPEXアプリケーションをダウンロードし、ワークスペースにインポートします。
https://github.com/ujnak/apexapps/blob/master/exports/chat-with-generative-ai-0.zip

アプリケーション・ビルダーからインポートを実行します。


インポートするファイルとしてchat-with-generative-ai-0.zipを選択します。

へ進みます。


アプリケーションのインストールを実行します。


アプリケーションがインポートされました。

接続先となるLLMを設定するため、アプリケーションの編集を実行します。


アプリケーションの編集画面が開きます。

アプリケーション定義の編集を開きます。


アプリケーション定義置換タブを開きます。

置換文字列のG_API_ENDPOINTの置換値は以下です。
http://host.docker.internal:8080/v1/chat/completions

置換文字列G_CREDENTIALの置換値は空白にします。G_MODEL_NAMEとして何を指定してもLM Studio側でロードしたモデルが使われるため、gpt-3.5-turboから変更はしません。


変更を適用し、アプリケーションを実行します。


ワークスペースに作成されている唯一のユーザーadminにて、アプリケーションにサインインします。


Promptに「あなたは日本語を話す親切なアシスタントです。」と入力し、Set Promptをクリックします。


User Messageに「東京から大阪まで一番早く着く方法と、その時間を教えてください。」と入力し、Send Messageをクリックします。


内容はさておき、日本語としては正確な回答が得られます。


LM StudioのトップページにMade possible thanks to the llama.cpp project.との記載があるため、LLMの処理にはllama.cppの実装が使われている模様です。

LM Studioを使うとllama.cppをそのまま使用するより、はるかに簡単にローカル・サーバーを立てることができます。

今回の記事は以上になります。