RAG環境を作るためにVector database(Chroma)をインストールする

# はじめに
この記事では、学習目的でRAG環境を作る際に必要と思われるVector database(Chroma)を導入した際の内容になります。公式サイトの[Getting Started](https://docs.trychroma.com/docs/overview/getting-started)を参考に簡単な動作確認を行いました。

## 導入環境
CentOS Stream9に導入してみました。作業はtestuserを用いました。
```bash
[testuser@localhost ~]$ uname -a
Linux localhost.localdomain 5.14.0-319.el9.x86_64 #1 SMP PREEMPT_DYNAMIC Thu May 25 19:53:58 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux
```

## chromadb導入用のvenvを作成する
```
[testuser@localhost ~]$ python -m venv chroma
[testuser@localhost ~]$ source chroma/bin/activate
(chroma) [testuser@localhost ~]$ 
```

## pipコマンドを用いchromadbをインストールする
```
(chroma) [testuser@localhost ~]$ pip install chromadb
Collecting chromadb
〜省略〜
Successfully installed PyYAML-6.0.2 annotated-types-0.7.0 anyio-4.8.0 asgiref-3.8.1 backoff-2.2.1 bcrypt-4.2.1 build-1.2.2.post1 cachetools-5.5.0 certifi-2024.12.14 charset-normalizer-3.4.1 chroma-hnswlib-0.7.6 chromadb-0.6.3 click-8.1.8 coloredlogs-15.0.1 deprecated-1.2.15 durationpy-0.9 exceptiongroup-1.2.2 fastapi-0.115.6 filelock-3.16.1 flatbuffers-24.12.23 fsspec-2024.12.0 google-auth-2.37.0 googleapis-common-protos-1.66.0 grpcio-1.69.0 h11-0.14.0 httpcore-1.0.7 httptools-0.6.4 httpx-0.28.1 huggingface-hub-0.27.1 humanfriendly-10.0 idna-3.10 importlib-metadata-8.5.0 importlib-resources-6.5.2 kubernetes-31.0.0 markdown-it-py-3.0.0 mdurl-0.1.2 mmh3-5.0.1 monotonic-1.6 mpmath-1.3.0 numpy-2.0.2 oauthlib-3.2.2 onnxruntime-1.19.2 opentelemetry-api-1.29.0 opentelemetry-exporter-otlp-proto-common-1.29.0 opentelemetry-exporter-otlp-proto-grpc-1.29.0 opentelemetry-instrumentation-0.50b0 opentelemetry-instrumentation-asgi-0.50b0 opentelemetry-instrumentation-fastapi-0.50b0 opentelemetry-proto-1.29.0 opentelemetry-sdk-1.29.0 opentelemetry-semantic-conventions-0.50b0 opentelemetry-util-http-0.50b0 orjson-3.10.15 overrides-7.7.0 packaging-24.2 posthog-3.8.3 protobuf-5.29.3 pyasn1-0.6.1 pyasn1-modules-0.4.1 pydantic-2.10.5 pydantic-core-2.27.2 pygments-2.19.1 pypika-0.48.9 pyproject-hooks-1.2.0 python-dateutil-2.9.0.post0 python-dotenv-1.0.1 requests-2.32.3 requests-oauthlib-2.0.0 rich-13.9.4 rsa-4.9 shellingham-1.5.4 six-1.17.0 sniffio-1.3.1 starlette-0.41.3 sympy-1.13.3 tenacity-9.0.0 tokenizers-0.21.0 tomli-2.2.1 tqdm-4.67.1 typer-0.15.1 typing-extensions-4.12.2 urllib3-2.3.0 uvicorn-0.34.0 uvloop-0.21.0 watchfiles-1.0.4 websocket-client-1.8.0 websockets-14.1 wrapt-1.17.2 zipp-3.21.0
WARNING: You are using pip version 21.2.3; however, version 24.3.1 is available.
You should consider upgrading via the '/home/testuser/chroma/bin/python -m pip install --upgrade pip' command.
(chroma) [testuser@localhost ~]$ 
```
pipのバージョンが古いと最後に出力されたので、ついでにアップグレードしておきます。
```bash
(chroma) [testuser@localhost ~]$ python -m pip install --upgrade pip
```
## サンプルコードの実行
公式サイトのGetting Startedに記載されているサンプルコード実行してみる。
```python:test.py
import chromadb
chroma_client = chromadb.Client()
```
```bash
(chroma) [testuser@localhost ~]$ python test.py 
Traceback (most recent call last):
  File "/home/testuser/test.py", line 1, in <module>
    import chromadb
  File "/home/testuser/chroma/lib64/python3.9/site-packages/chromadb/__init__.py", line 85, in <module>
    raise RuntimeError(
RuntimeError: Your system has an unsupported version of sqlite3. Chroma                     requires sqlite3 >= 3.35.0.
Please visit                     https://docs.trychroma.com/troubleshooting#sqlite to learn how                     to upgrade.
(chroma) [testuser@localhost ~]$ 
```

# エラー原因の確認(sqliteのバージョン)
インストール済みsqlite3のバージョンが要件を満たさないためエラーが発生しているみたいです。インストール済みsqlite3のバージョンを確認してみることにします。
```bash
(chroma) [testuser@localhost ~]$ python -c "import sqlite3; print(sqlite3.sqlite_version)"
3.34.1
(chroma) [testuser@localhost ~]$ dnf info sqlite.x86_64
Last metadata expiration check: 0:04:10 ago on Sun Jan 19 11:40:15 2025.
Available Packages
Name         : sqlite
Version      : 3.34.1
Release      : 7.el9
Architecture : x86_64
```
CentOS Stream9のパッケージに含まれているsqliteのバージョンは、3.34までみたいです。CentOS Stream10の場合、3.45や3.46がパッケージに含まれているみたいです。今回は、このままの環境を用いsqlite3.45以上をソースコードからビルドしてインストールしてみることにします。

## sqlite 3.48のビルドおよびインストール
sqliteは、[公式ダウンロードサイト](https://www.sqlite.org/download.html)から最新のautoconfをダウンロードすることにします。
```
(chroma) [testuser@localhost ~]$ curl -LO https://www.sqlite.org/2025/sqlite-autoconf-3480000.tar.gz
(chroma) [testuser@localhost ~]$ gzip -dc sqlite-autoconf-3480000.tar.gz | tar tf -
〜省略〜
(chroma) [testuser@localhost ~]$ cd sqlite-autoconf-3480000
(chroma) [testuser@localhost sqlite-autoconf-3480000]$ (chroma) [testuser@localhost sqlite-autoconf-3480000]$ ./configure
〜省略〜
(chroma) [testuser@localhost sqlite-autoconf-3480000]$ make -j 4
〜省略〜
(chroma) [testuser@localhost sqlite-autoconf-3480000]$ sudo make install
```
```bash
(chroma) [testuser@localhost sqlite-autoconf-3480000]$ cd ..
(chroma) [testuser@localhost ~]$ python -c "import sqlite3; print(sqlite3.sqlite_version)"
3.34.1
```
どうやらバージョンが古いままのものを認識してしまっている様です。おそらくLD_LIBRARY_PATHを設定する必要があるようです。make installした際の出力にもそれっぽい内容があった気がします。
```bash
(chroma) [testuser@localhost ~]$ export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH 
(chroma) [testuser@localhost ~]$ python -c "import sqlite3; print(sqlite3.sqlite_version)"
3.48.0
```
新しくインストールしたバージョンを認識してくれた様です。それではあらためてサンプルコードを実行してみましょう。
```bash
(chroma) [testuser@localhost ~]$ python test.py 
```
## データを登録するサンプルコードの実行
エラーなく正常終了した様です。では、次のサンプルコードを追記して動作確認を進めてみましょう。
```python:test.py
(chroma) [testuser@localhost ~]$ cat test.py 
import chromadb
chroma_client = chromadb.Client()

collection = chroma_client.create_collection(name="my_collection")

collection.add(
    documents=[
        "This is a document about pineapple",
        "This is a document about oranges"
    ],
    ids=["id1", "id2"]
)
```
サンプルコードを実行するとどうやらLMをインターネットからダウンロードしているみたいです。今回はエラーなく正常終了しました。
```
(chroma) [testuser@localhost ~]$ python test.py 
/home/testuser/.cache/chroma/onnx_models/all-MiniLM-L6-v2/onnx.tar.gz:  33%|██████████████████▉                                       | 25.9M/79.3M [01:32<02:46, 337kiB/s]
```
## 次のサンプルコードを用意し実行してみます。
```python:test.py
(chroma) [testuser@localhost ~]$ cat test.py 
import chromadb
chroma_client = chromadb.Client()

collection = chroma_client.create_collection(name="my_collection")

collection.add(
    documents=[
        "This is a document about pineapple",
        "This is a document about oranges"
    ],
    ids=["id1", "id2"]
)

results = collection.query(
    query_texts=["This is a query document about hawaii"],
    n_results=2
)
print(results)
```
## サンプルコードの出力結果の内容
実行すると以下出力が得られました。distancesの値が0に近いほど類似度が高いということなのでしょう。この場合は、id1のpineappleがhawaiiに近いという事なのでしょう。
```
(chroma) [testuser@localhost ~]$ python test.py 
{
    'ids': [['id1', 'id2']],
    'embeddings': None,
    'documents': [[
        'This is a document about pineapple',
        'This is a document about oranges']],
    'uris': None,
    'data': None,
    'metadatas': [[None, None]],
    'distances': [[1.0404009819030762, 1.2430799007415771]],
    'included': [
        <IncludeEnum.distances: 'distances'>,
        <IncludeEnum.documents: 'documents'>,
        <IncludeEnum.metadatas: 'metadatas'>
    ]
}
```
## 終わりに
導入環境依存により何度かつまづきましたが、無事にVector database(Chroma)を導入し、簡単なサンプルコードの動作確認を終えることができました。