皆さんこんにちは!現在「100日チャレンジ」と題して、日々新しい技術習得に挑戦中の宮川です。
3日目の今日は、Metaの最新LLM「Llama 3」をベースにrinna社が日本語能力を高めたというrinna/llama-3-youko-8b
モデルに注目。まずは自分の手元、ローカルマシン(CPU: Intel Core i7 12世代, GPU: Intel Iris Xe 内蔵グラフィクス)でこの大規模言語モデルを動かし、簡単なチャットボットを構築することに挑戦しました!
※1日目、2日目はブログにはまだしていません。
今日の成果
rinna/llama-3-youko-8b
をローカル環境で動かす。- 基本的なテキスト生成を確認する。
- Webフレームワーク (Flask) でチャットボットを構築する。
- ブラウザで対話できるUI (Streamlit) を作る。
環境構築:まずは足元から
開発環境は RockyLinux + VSCode + Python 3.13 です。プロジェクトごとに依存関係をきれいに保つため、まずはPython標準のvenv
を使って仮想環境を構築しました。今日の作業はこの仮想環境 (.venv
) の中で行います。
# Python
# 作業ディレクトリ作成 & 移動
mkdir 003Llama3-8B-Youko && cd 003Llama3-8B-Youko
# 仮想環境作成 & アクティベート
python3.13 -m venv .venv
source .venv/bin/activate
# 必要なライブラリをインストール
pip install transformers torch accelerate sentencepiece flask streamlit
最初の関門:巨大モデルをローカルに召喚! (test_load.py
)
まずはHugging Faceのtransformers
ライブラリを使って、モデルとトークナイザーをロードするシンプルなスクリプト (test_load.py
) を作成。
# Python
# (test_load.py の抜粋)
from transformers import AutoTokenizer, AutoModelForCausalLM
model_name = "rinna/llama-3-youko-8b"
print(f"Loading model: {model_name}")
tokenizer = AutoTokenizer.from_pretrained(model_name)
# 初回実行時、ここで約16.5GBのダウンロードが発生!
model = AutoModelForCausalLM.from_pretrained(model_name)
print("Model loaded successfully.")
print(f"Model is on device: {model.device}") # -> cpu と表示
実行すると、予想通り初回はモデルのダウンロードが始まりました。我が家の100Mbps回線では数十分かかりましたね…。そして、ダウンロード後、モデルがメモリにロードされるのを待ちます。巨大モデルを動かす最初の洗礼を受けた気分です(笑)RAMの使用量もかなり気になるところ。無事にロードが完了し、Model is on device: cpu
と表示されたときはホッとしました。
挑戦1:FlaskでWebチャットボット構築 (flask_chatbot.py
)
モデルが動くことを確認できたので、次はWebアプリケーションフレームワークの Flask を使って、ブラウザから対話できるチャットボットを作成しました。簡単なHTMLフロントエンド (templates/index.html) も用意し、そこからの入力を受け付けて応答を返す仕組みです。
# Python
# (Flask アプリの抜粋)
from flask import Flask, request, jsonify, render_template
import torch
from transformers import AutoTokenizer, AutoModelForCausalLM
import logging
app = Flask(__name__)
logging.basicConfig(level=logging.INFO)
# モデルとトークナイザーのロード (メモリ効率化とGPU利用を試行)
model_name = "rinna/llama-3-youko-8b"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(
model_name,
torch_dtype=torch.bfloat16, # メモリ使用量削減のため半精度(bfloat16)を指定
device_map="auto" # GPUがあれば自動で割り当て (今回はCPUのはず)
)
@app.route("/", methods=["GET"])
def home():
return render_template("index.html") # HTMLを表示
@app.route("/chat", methods=["POST"])
def chat():
user_input = request.json.get("message", "")
logging.info(f"User input: {user_input}")
# モデルで応答を生成 (パラメータも設定)
inputs = tokenizer(user_input, return_tensors="pt").to(model.device)
outputs = model.generate(
**inputs,
max_new_tokens=50, # 最大生成トークン数
temperature=0.7, # ランダム性 (低いほど決定的)
top_p=0.9, # 上位p%からサンプリング
do_sample=True # サンプリングを有効化
)
response = tokenizer.decode(outputs[0], skip_special_tokens=True)
logging.info(f"Bot response: {response}")
return jsonify({"response": response})
if __name__ == "__main__":
app.run(debug=True, host='0.0.0.0', port=5000) # 例
このコードでは、モデルロード時に torch_dtype=torch.bfloat16 を指定してメモリ使用量を抑えようとしたり、device_map=”auto” でGPU利用(今回はCPUですが)を考慮しています。また、応答生成時には temperature や top_p などのパラメータを設定し、応答の多様性を調整しようと試みました。flask run でサーバーを起動し、ブラウザからアクセスして動作を確認。ちゃんと応答が返ってきましたが、やはりここでも応答速度が課題となりました。
挑戦2:StreamlitでインタラクティブUI (app.py)
Flaskで基本的なWebアプリは作れましたが、もっと手軽にインタラクティブなUIを作りたいと思い、次は Streamlit を試してみました。PythonコードだけでリッチなUIが作れるのが魅力です。
# Python
# (st_app.py Streamlit アプリの抜粋)
import streamlit as st
# ... (Flaskアプリと同様に model, tokenizer のロード処理) ...
st.title("🦙 Llama 3 Youko ローカルチャット (Streamlit版)")
# チャット履歴の初期化 (st.session_state を活用)
if "messages" not in st.session_state:
st.session_state.messages = []
# ユーザーからの入力 (st.chat_input を使用)
if prompt := st.chat_input("メッセージを入力してください"):
# ... (Flask同様にモデルに応答を生成させる処理) ...
# ... (ユーザー入力とモデル応答を st.session_state.messages に追加) ...
# チャット履歴の表示 (st.chat_message を使用)
for message in st.session_state.messages:
with st.chat_message(message["role"]):
st.markdown(message["content"])
st.chat_input や st.chat_message といった便利なコンポーネントのおかげで、Flaskの時よりも少ないコード量で、洗練されたチャットUIを実装できました。状態管理には st.session_state を利用。streamlit run st_app.py で起動し、こちらもブラウザで動作確認。やはり手軽さではStreamlitに軍配が上がりますね!
ローカル実行の現実:忍耐力が試される対話
さて、FlaskとStreamlit、2つの方法でチャットボットを動かしてみての感想です。どちらのアプリでも、ローカルマシン(GPUなし)での応答時間は、プロンプトにもよりますが8秒から、長いと25秒以上かかりました。これは、対話としてはかなり厳しい速度です…。原因はやはりCPUでの推論処理と、もしかしたらRAMのスワップなども影響しているかもしれません。
生成される応答も、時折「おっ」と思わせる自然な日本語が出てくる一方で、少し話が噛み合わなかったり、唐突な内容になったりすることも。Flask側で生成パラメータ(temperature
, top_p
など)を調整してみましたが、応答速度が遅いため、最適なパラメータを見つけるための試行錯誤に時間がかかりすぎてしまい、ローカル環境でのチューニングは現実的ではないと感じました。
3日目の学びと気づき
- ローカルLLMの壁: 高性能GPUなしで大規模モデルを快適に動かすのは難しい。理論と実体験で痛感。
- Flask vs Streamlit: しっかりしたWebアプリやAPIならFlask、手軽なUIプロトタイプやデモならStreamlitと、目的に応じた使い分けが有効。
- Webフレームワークの選択肢: 今回は試せませんでしたが、より高速なAPIサーバー構築にはFastAPI、UI構築の別候補としてGradioなども比較検討してみたい。
- モデルロードの工夫:
torch_dtype
指定によるメモリ削減効果は確認できた(かもしれない)。device_map
はGPUがないと意味がないが、コードの汎用性は上がる。
次なる挑戦:Colabでの高速化とRAGによる”教育”へ
今回のローカルでの挑戦を踏まえ、次はGoogle Colabの有料プラン(Pro/Pro+) を利用して、高性能GPU(例えば A100 や V100 など、強力なGPUがあります)で、どれだけ応答速度が改善されるか試してみたいと思います!ローカルであれだけ待たされた分、期待が高まります。
さらに将来的には、単に対話するだけでなく、RAG(Retrieval-Augmented Generation) 技術を使って、このチャットボットに特定の知識、例えば私自身のブログ記事の内容や技術メモなどを “教育” して、よりパーソナルで賢いAIアシスタントに育てていくことにも挑戦したいと考えています。
まとめとコード
100日チャレンジ3日目は、ローカル環境でのLLM実行の難しさと、Webアプリ化の手軽さの両方を体験する、非常に学びの多い一日となりました。FlaskとStreamlitという異なるアプローチでチャットボットを形にできたのは大きな収穫です。
今日作成したコードはGitHubにアップロードしています。まだまだ荒削りですが、興味のある方はぜひ覗いてみてください!
- Flaskアプリ:
app.py
とtemplates/index.html
- Streamlitアプリ:
st_app.py
- モデルロードテスト:
test_load.py
- GitHubリポジトリ: https://github.com/miyakawa2449/100day/tree/main/003Llama3-8B-Youko
皆さんのLLM活用術やローカルでの奮闘記なども、ぜひコメントで教えていただけると嬉しいです!
ピンバック: ローカルLLM 100日チャレンジ Day 4: Colab GPUで応答速度劇的改善! でもモデルのクセと環境構築の壁も… | MIYAKAWA AI