モチベーション
この投稿で、ナレッジグラフを構築できるLLMは、OpenAIとMistral(何もAPI経由)であると述べた。ネットでは、この記事のようにollamaを使ってGraphRAG環境を構築している事例を見かけるようになった。
自分もローカル環境でナレッジグラフを構築することにチャレンジしたい。今回の投稿では、ollamaをインストールするまでをまとめる。
情報源
- ollama/ollama - dockerhubの情報。
 - Ollama is now available as an official Docker image - ollamaのブログ記事でdockerコンテナとしてollamaをインストールする情報。
 - Ollamaで体験!Gemma2-2b-jpnが切り拓く日本語AI活用の新時代 - ollamaでgemma2日本語版インストールする情報。
 - Ollamaで Google の日本語版 Gemma 2 2B を動かす - 同じくollamaでgemma2日本語版をインストールする情報。
 - ローカル環境でLLMを選んでLangChainで実行する。 - ollama CLIコマンドの一覧が載っていて、助かった。また、この記事のコードで4つのLLMを確かめた。
 - OllamaLLM Connection refused… - JupyterLabでコードを確かめる際に、connection refusedのエラーが出たので、その際に参考にした。
 - インストールから日本語モデル導入まで - GGUFファイルをollamaに組み込む際に参考した。
 
ollamaをインストール
docker-compose.ymlを作成
情報源1.や2.のdockerコンテナ起動のコマンドラインを参考に、次のようなyamlを作成した。
services:
  ollama:
    image: ollama/ollama
    container_name: ollama
    ports:
      - "11434:11434"
    volumes:
      - ./ollama:/root/.ollama
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: 1
              capabilities: [gpu]
    restart: always
ホスト側の./ollamaディレクトリは、NFSマウント配下に置いた。そうすることで、別のGPUマシンと共有できると考えて。
$ pwd
/mnt/nfs2/workspace/ollama
$ ls -l
合計 8
-rw-rw-r-- 1 kenji kenji  325 11月 21 18:33 docker-compose.yml
drwxrwxr-x 3 kenji kenji 4096 11月 22 15:28 ollama
$ sudo docker compose up -d
上記の通り、ollamaコンテナを起動する。
LLMモデルを(ダウンロードし)実行
次のように、上記で起動したコンテナに入り、コンテナ内で、ollamaコマンドを使ってモデルを実行する。
$ sudo docker exec -it ollama /bin/bash
# ollama --version
ollama version is 0.4.2
# ollama run schroneko/gemma-2-2b-jpn-it
実行結果
情報源3.のサンプルをそのまま使って、実行した。
>>> 日本の四季について端的にわかりやすく教えて
日本の四季は、大きく分けて**春、夏、秋、冬**の4つの季節があります。
* **春:**  桜の花が咲き乱れる季節です。暖かくなり、植物が芽吹きます。
* **夏:**  暑く、日差しが強くなります。海や湖で泳ぎ、屋外で遊びます。
* **秋:**  紅葉が美しい季節です。気温が下がり、冷たい風が吹きます。
* **冬:**  寒く、雪が降ることがあります。冬スポーツを楽しんだり、暖房で体を温めたりし
ます。
JupyterLabからollamaモデルを使う
この投稿で紹介したDockerfileに、「pip innstall ollama, langchain-ollama」を追加して、JupyterLabのdockerコンテナを作成した。Dockerfileの整理については後述。
実行コード
情報源5.のコードを参考に、JupyterLabコンテナから実行した。
from langchain_core.prompts import ChatPromptTemplate
from langchain_ollama.llms import OllamaLLM
model = OllamaLLM(base_url = "http://192.168.11.4:11434", model="schroneko/gemma-2-2b-jpn-it")
# PROMPT
template = """Question: {question}
Answer: ステップバイステップで考えてみましょう。"""
prompt = ChatPromptTemplate.from_template(template)
# CHAIN
chain = prompt | model
result = chain.invoke({"question": "美味しいパスタの作り方は?"})
print(result)
OllamaLLM()の引数のbase_urlのところがポイント。これは、情報源6.を参考にした。base_urlを指定しないと、connection refusedのエラーが発生する。
ggufファイルをモデルとして組み込む
情報源7.を参考に、huggingfaceにあるこの一覧の「Q8-0」をダウンロードして、以下のようにModelfileを準備した。
$ wget https://huggingface.co/mradermacher/Llama-3-neoAI-8B-Chat-v0.1-GGUF/resolve/main\
/Llama-3-neoAI-8B-Chat-v0.1.Q8_0.gguf
$ cat Modelfile
FROM ./Llama-3-neoAI-8B-Chat-v0.1.Q8_0.gguf
上記の作業は、yamlファイル説明のところのollamaディレクトリ配下で行う。そうするとコンテナからもggufファイルとModelfileにアクセスできる。
ollamaコンテナに入り(既に説明済みのdocker execによって)、ollamaコマンドでモデルを作る。
#ollama create neoai-8b-chat -f Modelfile
気づいたこと
- ollamaコンテナでモデルをpullしておけば、JupyterLabのコードのモデル接続(OllamaLLM)時にrunしてくれるようで、アクセスできる。
 - JupyterLabでモデルを変更すると、ollama側でモデルのstopとrunを行なっているようだ。
 - コンテナに入って、「ollama stop モデル」するとGPUメモリを解放しているようだ。
 
JupyterLabコンテナを見直す
ここまででollamaコンテナがバックエンドでLLMの処理を行えるようになった。これまでJupyterLabのコンテナにllama-cpp-pythonを組み込んでいた。今後はJupyterLabコンテナにllama-cpp-pythonが必要でなくなり、JupyterLabコンテナがシンプルになる。
JupyterLabコンテナのDockerfile
シンプルになったDockerfileは次の通り。
# JupyterLabが使えるDockerイメージ
# 自分がこれまで作成したNoteBookに必要なパッケージをインストールしたもの。
FROM nvidia/cuda:12.1.1-cudnn8-devel-ubuntu22.04
# Set bash as the default shell
ENV SHELL=/bin/bash
# Build with some basic utilities
RUN apt update \
        && apt install -y \
        wget \
        bzip2 \
        git \
        git-lfs \
        curl \
        unzip \
        file \
        xz-utils \
        sudo \
        python3 \
        python3-pip && \
        apt-get autoremove -y && \
        apt-get clean && \
        rm -rf /usr/local/src/*
# alias python='python3'
RUN ln -s /usr/bin/python3 /usr/bin/python
RUN pip install --upgrade pip setuptools \
        && pip install torch torchvision torchaudio \
         --index-url https://download.pytorch.org/whl/cu121 \
        && pip install jupyterlab matplotlib pandas scikit-learn ipywidgets \
        && pip install transformers accelerate sentencepiece einops \
        && pip install auto-gptq optimum \
        && pip install langchain bitsandbytes protobuf \
        && pip install langchain-community langchain_openai wikipedia \
        && pip install langchain-huggingface unstructured html2text rank-bm25 janome \
        && pip install langchain-chroma sudachipy sudachidict_full \
        && pip install langchain-experimental neo4j \
        && pip install json-repair langchain-mistralai \
        && pip install mysql-connector-python \
        && pip install ragas datasets neo4j-graphrag \
        && pip install pypdf tiktoken sentence_transformers faiss-gpu trafilatura \
        && pip install ollama langchain-ollama
# Create a working directory
WORKDIR /workdir
# Port number in container side
EXPOSE 8888
ENTRYPOINT ["jupyter-lab", "--ip=0.0.0.0", "--port=8888", "--no-browser", "--allow-root", "--NotebookApp.token=''"]
CMD ["--notebook-dir=/workdir"]
まとめ
JupyterLabコンテナとollamaコンテナに分離し、コーディングを行う部分(フロントエンド)とLLMモデルを扱う部分(バックエンド)に分離でき構造的にすっきりした。これによって、今後LLMモデルを使うアプリを作成する場合にも良い結果をなると思う。