[Oracle Database 23ai]ローカルRESTプロバイダOllamaで表データをEmbeddingしてみた。(2024/12/10)

こちらの記事は[Oracle Cloud Infrastructure Advent Calendar 2024](https://qiita.com/advent-calendar/2024/oci) Day 10 の記事として書かれています。Day 09の記事は @seigen_chan さんの記事「[CloudWorld2024の旅記録残しつつCloudWorld2025への目標立ててみた](https://qiita.com/seigen_chan/items/b0e592e7ea44c139b424)」でした。


# はじめに
Oracle Database 23ai の2024年10月のアップデートでローカル・ホストのRESTエンドポイント・プロバイダOllamaがサポートされました。Ollamaで利用可能なLLM (Llama 3、Phi 3、Mistral、Gemma 2など)を使用してEMBEDDINGやサマリーの生成、テキストの生成ができます。
今回はOCI Base Database上のOracle Database 23aiを使用し、表データのEmbeddingを試してみました。


# 作業ステップ

- 事前作業
- Ollamaをインストール
- 表データのEmbedding

# 事前作業
- 作業用データベースユーザの作成
PDBにSYSDBA権限で接続し、データベースユーザを作成し、「DB_DEVELOPER_ROLE」、「create credential」権限を付与します。

```sql
$ export NLS_LANG=American_America.AL32UTF8
$ sqlplus / as sysdba

alter session set container=pdb1;
CREATE USER docuser identified by <password> DEFAULT TABLESPACE USERS quota unlimited on USERS;
GRANT DB_DEVELOPER_ROLE, create credential to docuser;
```

- サンプル表、データの作成
作成したデータベースユーザで表を作成し、データを格納します。

```sql
create table documentation_tab (id number,info varchar2(512));
insert into documentation_tab (id,info) values(	1,'San Francisco is in California.');
-- 省略
commit;
```

# Ollamaをインストール

[https://ollama.com/download](https://ollama.com/download)にアクセスし、Linux用の「Install with one command:」を確認
Base Databaseのノードにssh ログインし、rootユーザでコマンドを実行します。

```
# curl -fsSL https://ollama.com/install.sh | sh
```

コマンドの結果

```
>>> Installing ollama to /usr/local
>>> Downloading Linux amd64 bundle
######################################################################## 100.0%
>>> Creating ollama user...
>>> Adding ollama user to render group...
>>> Adding ollama user to video 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 127.0.0.1:11434.
>>> Install complete. Run "ollama" from the command line.
WARNING: No NVIDIA/AMD GPU detected. Ollama will run in CPU-only mode.
```

### ollama run <model_name>コマンドを使用してモデルを実行

Llama 3モデルをコール

```
$ ollama run llama3
pulling manifest
pulling 6a0746a1ec1a... 100% ▕████████████████▏ 4.7 GB
<略>
verifying sha256 digest
writing manifest
success
>>> /bye
```

:::note warn
注意： デフォルトのインストール領域に空きがない場合、モデルを格納する領域を確保します。
:::

エラーメッセージを確認し、書き込み途中のファイルを削除
```
Error: write /usr/share/ollama/.ollama/models/blobs/sha256-6a0746a1ec1aef3e7ec53                                                                                                                                                             868f220ff6e389f6f8ef87a01d77c96807de94ca2aa-partial: no space left on device
```

```
# rm /usr/share/ollama/.ollama/models/blobs/sha256-6a0746a1ec1aef3e7ec53868f220ff6e389f6f8ef87a01d77c96807de94ca2aa-partial
```

領域に空きがあるディレクトリにシンボリックリンクを作成

```
# mkdir /u01/ollama/
# mkdir /u01/ollama/models
# chown ollama:ollama /u01/ollama/models
# ln -s /u01/ollama/models/ /usr/share/ollama/.ollama/models
```


### cURLコマンドを使用して、Ollamaがローカルで実行されていることを確認

```
$ curl http://localhost:11434/api/embeddings -d '{
  "model" : "llama3", 
  "prompt": "Here is an article about llamas" 
}

{"embedding":[-1.6629716157913208,-
< 略 >
,-0.4060233533382416]
$
```

# 表データのEmbedding

DBMS_VECTORまたはDBMS_VECTOR_CHAINパッケージの関数UTL_TO_EMBEDDINGをコールすることでOllamaを使用してEmbeddingできます。


### ホストへの接続を許可するための接続権限をdocuserに付与

```sql
BEGIN
  DBMS_NETWORK_ACL_ADMIN.APPEND_HOST_ACE(
    host => '*',
    ace => xs$ace_type(privilege_list => xs$name_list('connect'),
                       principal_name => 'docuser',
                       principal_type => xs_acl.ptype_db));
END;
/
```

### UTL_TO_EMBEDDINGをコール

- テキストをEmbeddingして確認

「hello」という文字列のEmbedding

```sql
SQL> var embed_ollama_params clob;
SQL> exec :embed_ollama_params := '{ -
     "provider": "ollama", -
     "host"    : "local", -
     "url"     : "http://localhost:11434/api/embeddings", -
     "model"   : "llama3" -
}';

PL/SQL procedure successfully completed.

SQL> select dbms_vector.utl_to_embedding('hello', json(:embed_ollama_params)) ollama_output from dual;

OLLAMA_OUTPUT
--------------------------------------------------------------------------------
[-2.31221581E+000,-3.26045007E-001,2.48111725E-001,-1.65610778E+000,

```

### 表データのEmbedding


```
SQL> var embed_ollama_params clob;
SQL> exec :embed_ollama_params := '{ -
      "provider": "ollama", -
      "host"    : "local", -
      "url"     : "http://localhost:11434/api/embeddings", -
      "model"   : "llama3" -
}';

PL/SQL procedure successfully completed.
```
     
Vector列を持つ表(documentation_table)を作成し、サンプル表(documentation_tab)のデータEmbeddingします。

```sql
create table documentation_table (id number, text clob,v vector);
insert into documentation_Table select id,info,dbms_vector.utl_to_embedding(info, json(:embed_ollama_params)) vector from documentation_tab;
commit;
```



# セマンティック検索の実行
Embeddingされたデータを使ってセマンティック検索を実施してみます。

```sql
select text from documentation_table
order by vector_distance(v, dbms_vector.utl_to_embedding('Cars', json(:embed_ollama_params)), EUCLIDEAN)
fetch first 5 rows only;


TEXT
--------------------------------------------------------------------------------
Apples can be green, yellow or red.
Limes are green.
Toyotas are reliable.
Ripe strawberries are red.
Queens is in New York.

5 rows selected.

```

# おわりに

Oracle Database 23ai の AI Vestor Search機能でローカルRESTプロバイダOllamaを使用し表データのEmveddingを実施してみました。Embeddingされたデータに対してセマンティック検索をすることができました。

## 参考情報
- [ローカルRESTプロバイダOllamaを使用したテキスト文字列から埋込みへの変換](https://docs.oracle.com/cd/G11854_01/vecse/convert-text-string-embedding-locally-ollama.html)