🕊️

思い立ったが吉日!!Swallow8B→Ollama→Mattermost

に公開

Swallow8BをJupyter Notebookで動かす。

まずは、Swallowとは。

Swallowとは東京科学大学と産業技術総合研究所が生成したLLM(大規模言語モデル)です。
8Bとは8Billion(80億)パラメータで学習したものだそうです。

https://swallow-llm.github.io/llama3.1-swallow.ja.html

下準備

今回はDockerCompose等を使います。準備しましょう。また、Nvidia製GPUを使いますので、

https://zenn.dev/evakichi/articles/bc47039f1d5234

を参考にしてみてください。

Jupyter NotebookでSwallow8Bを動かす(Docker使って)。

Docker composeを使ってやってみましょう。まずは、Dockerfileを使います。Swallow8Bの指定しているバージョンを指定します。

Dockerfile
FROM nvidia/cuda:12.1.0-cudnn8-devel-ubuntu22.04

RUN apt-get update && apt-get -y upgrade && apt-get install -y python3-pip python3-venv git vim

RUN mkdir -p /home/swallow && \
    groupadd -g 1000 swallow && \
    useradd -d /home/swallow -g 1000 -u 1000 swallow && \
    chmod 755 /home/swallow && \
    chown 1000:1000 /home/swallow

WORKDIR /home/swallow

RUN pip3 install jupyter notebook && \
    pip3 install torch==2.2.2 torchvision==0.17.2 torchaudio==2.2.2 --index-url https://download.pytorch.org/whl/cu121 && \
    pip3 install transformers==4.41.2 accelerate bitsandbytes

CMD ["jupyter","notebook","--ip=0.0.0.0","--port=8888","--NotebookApp.token=''","--allow-root"]

んでもってDocker composeの設定ファイルは次のようになります。

compose.yml
services:
  swallow:
    build: .
    container_name: swallow
    hostname: swallow
    runtime: nvidia
    ports:
      - 8888:8888
    tty: true
    volumes:
      - ./py:/home/swallow/py
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: 1
              capabilities: [gpu]

で、動かします。

$ COMPOSE_BAKE=true docker compose up -d --build

http://localhost:8888 に繋げるとうまくJuyter Notebookが見えれば成功です。

そのあと次のようなコードを新規作成したipynbファイルに書き込みましょう。

Untitled.ipynb
import torch
import transformers
from transformers import AutoModelForCausalLM, AutoTokenizer,BitsAndBytesConfig

で実行しましょう。一回エラーが出るかもしれませんが、二度目には出なくなります。(なぜかは調べていません。)

次に、以下のコードを実行してみましょう。

Untitled.ipynb
DEFAULT_SYSTEM_PROMPT = "あなたは日本語で回答するアシスタントです。"
text = "莫山先生の莫山発言。"

messages = [
    {"role": "system", "content": DEFAULT_SYSTEM_PROMPT},
    {"role": "user", "content": text},
]

prompt = tokenizer.apply_chat_template(
    messages,
    tokenize=False,
    add_generation_prompt=True
)

token_ids = tokenizer.encode(
    prompt, add_special_tokens=False,
    return_tensors="pt"
)

with torch.no_grad():
    output_ids = model.generate(
        token_ids.to(model.device),
        max_new_tokens=512,
        do_sample=True,
        temperature=0.6,
        top_p=0.9,
    )

output = tokenizer.decode(
    output_ids.tolist()[0][token_ids.size(1):], 
    skip_special_tokens=True
)
print(output)

結果は・・・、よくわからないものでした。

しかも時間かかりまくり。

Ollamaを使ってSwallow8Bを動かす(Docker使って)。

次に、Ollamaを使ってSwallow8Bを使って見ましょう。

OllamaのついでにAnythingLLMを使えるようにします。これでWeb上でチャットっぽいことができます。

ちなみにOllamaでSwallow8Bはちょっと一手間必要で以下を使います。

https://zenn.dev/hellorusk/books/e56548029b391f/viewer/ollama2

では、Composeファイルから。

compose.yml
services:
  anythingllm:
    image: mintplexlabs/anythingllm
    container_name: anythingllm
    ports:
    - "3001:3001"
    cap_add:
      - SYS_ADMIN
    environment:
    # Adjust for your environment
      - STORAGE_DIR=/app/server/storage
      - JWT_SECRET='fGKjVGTeihU5k54As8CPp8sPjjYY9E'
      - LLM_PROVIDER=ollama
      - OLLAMA_BASE_PATH=http://ollama:11434
      - OLLAMA_MODEL_PREF=hf.co/mmnga/tokyotech-llm-Llama-3.1-Swallow-8B-Instruct-v0.3-gguf
      - OLLAMA_MODEL_TOKEN_LIMIT=4096
      - EMBEDDING_ENGINE=ollama
      - EMBEDDING_BASE_PATH=http://ollama:11434
      - EMBEDDING_MODEL_PREF=nomic-embed-text:latest
      - EMBEDDING_MODEL_MAX_CHUNK_LENGTH=8192
      - VECTOR_DB=lancedb
      - WHISPER_PROVIDER=local
      - TTS_PROVIDER=native
      - PASSWORDMINCHAR=8
    volumes:
      - anythingllm_storage:/app/server/storage
    restart: always
  ollama:
    image: ollama/ollama
    container_name: ollama
    hostname: ollama
    volumes:
      - ollama:/root/.ollama
    ports:
      - 11434:11434
    runtime: nvidia
    restart: always
    tty: true
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: 1
              capabilities: [gpu]
volumes:
  ollama:
  anythingllm_storage:

実行します。

$ docker compose up -d 

まずは、Ollamaから実行して見ましょう。

$ docker compose exec -it ollama run hf.co/mmnga/tokyotech-llm-Llama-3.1-Swallow-8B-Instruct-v0.3-gguf

プロンプトが出たら成功です。
次に、AnythingLLMを使います。
http://localhost:3001 に繋げてWebインターフェースが出れば成功です。
これでだいぶチャットができる様になりました。

MattermostでSwallow8Bを動かす(Docker使って)。

MattermostはSLACKライクなチャットツールです。

Mattermostを使うためにはMattermostのサイトに書いてある方法を使うと良いでしょう。

https://docs.mattermost.com/deploy/server/deploy-containers.html

ということでちょっと一手間加えます。最初は

$ git clone https://github.com/mattermost/docker Mattermost

にします。
でもって、私はバインドマウントは苦手なので、ボリュームを作ってマウントします。

docker-compose.yml
# https://docs.docker.com/compose/environment-variables/
services:
  postgres:
    image: postgres:${POSTGRES_IMAGE_TAG}
    restart: ${RESTART_POLICY}
    security_opt:
      - no-new-privileges:true
    pids_limit: 100
    read_only: true
    tmpfs:
      - /tmp
      - /var/run/postgresql
    volumes:
      - postgres-data:/var/lib/postgresql/data
    environment:
      # timezone inside container
      - TZ

      # necessary Postgres options/variables
      - POSTGRES_USER
      - POSTGRES_PASSWORD
      - POSTGRES_DB

  mattermost:
    depends_on:
      - postgres
    image: mattermost/${MATTERMOST_IMAGE}:${MATTERMOST_IMAGE_TAG}
    restart: ${RESTART_POLICY}
    security_opt:
      - no-new-privileges:true
    pids_limit: 200
    read_only: ${MATTERMOST_CONTAINER_READONLY}
    tmpfs:
      - /tmp
    volumes:
      - ${MATTERMOST_CONFIG_PATH}:/mattermost/config:rw
      - ${MATTERMOST_DATA_PATH}:/mattermost/data:rw
      - ${MATTERMOST_LOGS_PATH}:/mattermost/logs:rw
      - ${MATTERMOST_PLUGINS_PATH}:/mattermost/plugins:rw
      - ${MATTERMOST_CLIENT_PLUGINS_PATH}:/mattermost/client/plugins:rw
      - ${MATTERMOST_BLEVE_INDEXES_PATH}:/mattermost/bleve-indexes:rw
      # When you want to use SSO with GitLab, you have to add the cert pki chain of GitLab inside Alpine
      # to avoid Token request failed: certificate signed by unknown authority
      # (link: https://github.com/mattermost/mattermost-server/issues/13059 and https://github.com/mattermost/docker/issues/34)
      # - ${GITLAB_PKI_CHAIN_PATH}:/etc/ssl/certs/pki_chain.pem:ro
    environment:
      # timezone inside container
      - TZ

      # necessary Mattermost options/variables (see env.example)
      - MM_SQLSETTINGS_DRIVERNAME
      - MM_SQLSETTINGS_DATASOURCE

      # necessary for bleve
      - MM_BLEVESETTINGS_INDEXDIR

      # additional settings
      - MM_SERVICESETTINGS_SITEURL
volumes:
  mattermost-config:
  mattermost-data:
  mattermost-logs:
  mattermost-plugins:
  mattermost-client-plugins:
  mattermost-bleve-indexes:
  postgres-data:
.env
MATTERMOST_CONFIG_PATH=mattermost-config
MATTERMOST_DATA_PATH=mattermost-data
MATTERMOST_LOGS_PATH=mattermost-logs
MATTERMOST_PLUGINS_PATH=mattermost-plugins
MATTERMOST_CLIENT_PLUGINS_PATH=mattermost-client-plugins
MATTERMOST_BLEVE_INDEXES_PATH=mattermost-bleve-indexes
docker-compose.nginx.yml
services:
  nginx:
    depends_on:
      - mattermost
    container_name: nginx_mattermost
    image: nginx:${NGINX_IMAGE_TAG}
    restart: ${RESTART_POLICY}
    security_opt:
      - no-new-privileges:true
    pids_limit: 100
    read_only: true
    tmpfs:
      - /var/run
      - /var/cache
      - /var/log/nginx
    volumes:
      - ${NGINX_CONFIG_PATH}:/etc/nginx/conf.d:ro
      - ${NGINX_DHPARAMS_FILE}:/dhparams4096.pem
      - ${CERT_PATH}:/cert.pem:ro
      - ${KEY_PATH}:/key.pem:ro
      - shared-webroot:/usr/share/nginx/html
    environment:
      # timezone inside container
      - TZ
    ports:
      - ${HTTPS_PORT}:443
      - ${HTTP_PORT}:80
  mattermost:
    ports:
      - ${CALLS_PORT}:${CALLS_PORT}/udp
      - ${CALLS_PORT}:${CALLS_PORT}/tcp

# Shared volume for Let's Encrypt certificate renewal with a webroot
volumes:
  shared-webroot:
    name: shared-webroot

# This network name is being used for Let's Encrypt certificate renewal
networks:
  default:
    name: mattermost

.env
# Domain of service
DOMAIN=magnum.lan

CERT_PATH=./certs/magnum.lan.crt
KEY_PATH=./certs/magnum.lan.key

magnum.lanというのは私のローカルのドメイン名です。OpenWrtで名前を「magnum」と登録するとつけられる名前です。
鍵と証明書ファイルは、私のこれを参考にしてください。

https://zenn.dev/evakichi/articles/cfe0dea7029514

では動かします。動かす方法は

$ docker compose -f docker-compose.yml -f docker-compose.nginx.yml up -d

です。
これで、https://magnum.lan/ に繋げると、MatterMostに繋げます。

そこから、設定をしてMattermostを使います。
では、最後に、MattermostからSwallow8Bを使うことをします。

Mattermostの左肩からシステムコンソールを立ち上げます。(言語を日本語にしています。)

システムコンソールを立ち上げたらスクロールして、プラグイン→Copilotを選択します。

無料版ではCopilotは一個だけですのでこれしか使えません。

で一個を設定します。保存して実行してみましょう。

そうすると、@ai と入れて質問したりするときちんと回答が返って来てくればOKです。

では楽しいLLMライフを!!

Discussion