PR

【低スペックPCでAIを動かす方法】第5回:コピペで完成!Google Colab×超高性能AI「Qwen2.5」で最高の専用チャットを作る方法

Google Colab
この記事は約16分で読めます。


はじめに

これまで全4回にわたり、Google Colaboratory(Google Colab)を使ったAI開発の基礎を学んできました。いよいよ今回が連載の最終回です。これまでの知識を総動員して、あなた専用の高性能なAIアシスタントを完成させましょう。プログラミングの難しい知識は一切不要です。今回ご紹介するプログラムのコードを「コピー&ペースト」するだけで、まるで完成されたサービスのように自然な日本語で対話ができる最新のオープンソースAIを、ご自身のブラウザ上で動かすことができます。

👇 本記事でわかる3つの重要ポイント 👇

  • 【テーマ1】高性能AIを低スペックPCで動かすための「データ圧縮技術」の秘密
  • 【テーマ2】文脈を記憶し、長文にも対応できる最新のAIチャットプログラムの構造
  • 【テーマ3】コピペだけで完成する、ストリーミング対応の専用AIアシスタント構築手順

この記事を最後まで読みながら手を動かしていただければ、無料で利用できるGoogleの強力なサーバー(T4 GPU)を最大限に活用し、驚くほど賢いAIとの対話を楽しむことができるようになります。それでは、最終ステップへ進みましょう!

今回使用する最新オープンソースAI「Qwen2.5-7B」とは?

今回、私たちが動かすAIの頭脳には、「Qwen2.5-7B-Instruct」という最新のオープンソースモデルを採用します。これまでもいくつかのAIモデルについて触れてきましたが、今回のモデルは特に日本語の処理能力が非常に高く、論理的な思考や複雑な文章の作成までこなしてしまう、極めて優秀なAIです。

70Bクラスに迫る7Bモデルの実力

AIの賢さや規模を表す際に「パラメータ数」という言葉がよく使われます。今回のモデル名にある「7B」とは、約70億のパラメータ(脳の神経細胞のようなもの)を持っていることを意味します。かつては70B(約700億)クラスの超巨大なAIでなければ、自然な日本語の対話や複雑な論理処理は難しいとされていました。しかし、AI技術は日々急速に進化しており、現在ではこの7Bという比較的小さなサイズのモデルであっても、一昔前の超巨大モデルに匹敵するほどの素晴らしい性能を発揮するようになっています。

無料の「T4 GPU」で快適に動かすための工夫

Google Colabの無料枠で貸し出される「T4 GPU」というコンピューターには、一度に広げられる作業机(メモリ容量)に限界があります。そのため、そのままの状態でこの高性能なAIを読み込もうとすると、作業机がパンクしてエラーになってしまいます。
そこで今回のプログラムには、「4ビット量子化」という高度なデータ圧縮技術を組み込んでいます。これは、AIの賢さをほとんど落とすことなく、AIの頭脳のデータをギュッと小さく圧縮して作業机に収める魔法のような技術です。これにより、高価なパソコンを買わなくても、手元の低スペックPCのまま、クラウド上でサクサクと最新AIを動かすことができるのです。

ステップ1:AIを動かすための「道具箱」をインストールしよう

それでは、早速実践に入りましょう。まずは、Google Colabの画面を開き、前回の第4回で学んだ通り、メニューの「ランタイム」から「ランタイムのタイプを変更」を選び、「T4 GPU」を選択して保存してください。右上の表示が下図のようになれば準備完了です。

最初の作業は、AIを動かすために必要な様々な「道具(ライブラリ)」をインターネットからダウンロードしてインストールすることです。以下の短いコードをコピーして、Google Colabの最初の入力枠(コードセル)に貼り付けてください。

!pip install -q -U transformers accelerate bitsandbytes gradio

コードを実行して道具箱を準備する

貼り付けたら、コードセルの左側にある「再生ボタン」をクリックします。数十秒ほど待つと、画面にインストール状況が表示されます。「transformers」や「gradio」といった、AIの頭脳とやり取りをしたり、チャットの操作画面を作ったりするために必須となる部品が自動的に組み込まれていきます。処理が完了し、緑色のチェックマークが表示されれば、このステップは無事に成功です。

ステップ2:コピペで完了!チャットシステム構築の完全版コード

道具箱の準備ができたら、次はいよいよAIの本体とチャット画面を立ち上げるための「完全版プログラム」を入力します。かなり長いコードになりますが、内容をすべて理解する必要はありません。まるごとコピーして、新しいコードセルに貼り付けてください。

import threading
import torch
import gradio as gr
from transformers import (
    AutoModelForCausalLM,
    AutoTokenizer,
    BitsAndBytesConfig,
    TextIteratorStreamer,
)

# ---------------------------------------------------------
# 1. モデル設定
# ---------------------------------------------------------
MODEL_ID = "Qwen/Qwen2.5-7B-Instruct"
SYSTEM_PROMPT = "あなたは知的で親切な日本語AIアシスタントです。ユーザーの質問に対して、論理的かつ自然な日本語で丁寧に答えてください。"
MAX_INPUT_TOKENS = 3072   # 入力(履歴込み)の上限。T4のメモリ節約用
MAX_NEW_TOKENS = 1024

print(f"[{MODEL_ID}] のロードを開始します。数分かかります...")

# ---------------------------------------------------------
# 2. 4ビット量子化(T4向け)
# ---------------------------------------------------------
quantization_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_quant_type="nf4",
    bnb_4bit_compute_dtype=torch.float16,
    bnb_4bit_use_double_quant=True,
)

tokenizer = AutoTokenizer.from_pretrained(MODEL_ID)
model = AutoModelForCausalLM.from_pretrained(
    MODEL_ID,
    quantization_config=quantization_config,
    device_map="auto",
    low_cpu_mem_usage=True,
)
model.eval()
print("モデルのロード完了。UIを起動します。")

# ---------------------------------------------------------
# 3. 履歴の正規化
# ---------------------------------------------------------
def to_text(content):
    """Gradioが渡す content(文字列/リスト/辞書)を必ず文字列にする"""
    if content is None:
        return ""
    if isinstance(content, str):
        return content
    if isinstance(content, dict):
        if "text" in content and content["text"]:
            return str(content["text"])
        return ""  # 画像・ファイルなどは無視
    if isinstance(content, (list, tuple)):
        return "".join(to_text(c) for c in content)
    return str(content)

def history_to_messages(history):
    """どの形式の history でも [{'role','content(str)'}] に変換する"""
    msgs = []
    for item in history or []:
        # 新形式: {"role": ..., "content": ...}
        if isinstance(item, dict):
            role = item.get("role")
            text = to_text(item.get("content"))
            if role in ("user", "assistant") and text.strip():
                msgs.append({"role": role, "content": text})
        # 旧形式: [user, assistant] のペア
        elif isinstance(item, (list, tuple)) and len(item) == 2:
            u, a = to_text(item[0]), to_text(item[1])
            if u.strip():
                msgs.append({"role": "user", "content": u})
            if a.strip():
                msgs.append({"role": "assistant", "content": a})
    return msgs

def build_inputs(history_msgs, user_text):
    """上限トークンを超える場合は古い履歴から削って入力を作る"""
    msgs = list(history_msgs)
    while True:
        full = [{"role": "system", "content": SYSTEM_PROMPT}] + msgs + \
               [{"role": "user", "content": user_text}]
        prompt = tokenizer.apply_chat_template(
            full, tokenize=False, add_generation_prompt=True
        )
        inputs = tokenizer(prompt, return_tensors="pt")
        if inputs["input_ids"].shape[1] <= MAX_INPUT_TOKENS or len(msgs) == 0:
            return inputs
        msgs = msgs[2:]  # 古い1往復(user+assistant)を削除

# ---------------------------------------------------------
# 4. ストリーミング推論
# ---------------------------------------------------------
def predict(message, history):
    user_text = to_text(message)  # multimodal時のdictにも対応
    history_msgs = history_to_messages(history)
    inputs = build_inputs(history_msgs, user_text).to(model.device)

    streamer = TextIteratorStreamer(
        tokenizer, skip_prompt=True, skip_special_tokens=True
    )
    generate_kwargs = dict(
        **inputs,
        streamer=streamer,
        max_new_tokens=MAX_NEW_TOKENS,
        do_sample=True,
        temperature=0.7,
        top_p=0.9,
        repetition_penalty=1.1,
        pad_token_id=tokenizer.eos_token_id,
    )

    errors = []

    def run_generate():
        try:
            with torch.no_grad():
                model.generate(**generate_kwargs)
        except Exception as e:
            errors.append(e)
            streamer.on_finalized_text("", stream_end=True)  # 画面が固まらないよう終了させる

    thread = threading.Thread(target=run_generate)
    thread.start()

    partial = ""
    for new_text in streamer:
        partial += new_text
        yield partial

    thread.join()
    if errors:
        yield partial + f"\n\n⚠️ 生成中にエラーが発生しました: {errors[0]}"

    # 次の質問のためにGPUの不要なキャッシュを解放
    torch.cuda.empty_cache()

# ---------------------------------------------------------
# 5. UI起動
# ---------------------------------------------------------
chat_ui = gr.ChatInterface(
    fn=predict,
    title="Qwen2.5-7B 日本語AIアシスタント (Colab T4)",
    description="何回でも続けて質問できます。",
    examples=[
        "量子コンピュータの仕組みを、小学生にもわかるように説明してください。",
        "Pythonで特定のディレクトリ内のCSVファイルを全て読み込み、結合するスクリプトを書いて。",
        "日本の歴史において、江戸幕府が260年以上も続いた理由は何だと考えられますか?",
    ],
)

chat_ui.queue().launch(share=True, debug=True)

このプログラムに組み込まれた4つの強力な機能

コードを貼り付けて実行する前に、この長いプログラムの中でどのような「すごい技術」が使われているのか、簡単にご紹介します。これらを知っておくと、AIの仕組みへの理解がより一層深まります。

1. 会話の「文脈」を忘れない記憶システム

通常のシンプルなプログラムでは、AIは「一つ前の質問」のことしか覚えていません。しかし、このプログラムの「3. 履歴の正規化」という部分には、過去のあなたとの会話(チャットの履歴)をしっかりと整理して、AIに一緒に届ける機能が組み込まれています。これにより、「さっきの話の続きなんだけど…」といった、人間同士のような自然な文脈を踏まえた対話が可能になっています。会話が長くなりすぎた場合は、自動的に古い記憶から削っていくため、メモリがパンクする心配もありません。

2. 待ち時間をゼロにする「ストリーミング機能」

「4. ストリーミング推論」という部分は、AIの回答を劇的に快適にするための仕組みです。本来、AIはすべての回答を考え終わってから一気に画面に表示します。しかし、この機能を使うと、AIが言葉を一つ思いつくたびに、まるで誰かがキーボードを叩いているかのように、1文字ずつカタカタとリアルタイムで画面に表示してくれます。これにより、「回答が長くて画面が固まっているように見える」というストレスを完全に無くしています。

3. ランダム性と安定性を両立する細かな設定

AIの性格を決める設定として、「temperature=0.7」や「top_p=0.9」という数字が書き込まれています。これは、真面目すぎる回答だけでなく、適度に人間らしい柔軟な表現をしてくれるようにする調整です。さらに、「repetition_penalty=1.1」という設定を加えることで、AIが同じ言葉を何度もループして繰り返してしまうエラーを未然に防いでいます。

4. 通信トラブルを防ぐ「公開リンク」の自動生成

一番最後の「chat_ui.queue().launch(share=True, debug=True)」という一文は、非常に重要な役割を果たしています。Google Colabの画面の中に直接チャットを表示しようとすると、通信の渋滞が起きてエラーになりやすい問題があります。しかし、この「share=True」という設定のおかげで、あなた専用の一時的なWebサイト(URL)が自動的に作成され、別の画面でエラーなく快適にチャットを楽しむことができるようになっています。

いよいよ対話スタート!AIアシスタントを使ってみよう

それでは、先ほど貼り付けたコードの「再生ボタン」をクリックしてください。

数分待って専用のURLを開く

最初の準備には少し時間がかかります。「Qwen2.5-7B-Instruct のロードを開始します。数分かかります…」というメッセージが表示され、AIの頭脳データが順番にダウンロードされていきます。データが大きいので、焦らずに3分から5分ほどゆっくりお待ちください。

「モデルのロード完了。UIを起動します。」と表示された後、画面の一番下に青い文字で「Running on public URL: https://○○○.gradio.live」というリンクが現れます。この青いリンクをクリックすると、ブラウザの新しいタブが開きます。

自由に質問を投げかけてみましょう

新しいタブに「Qwen2.5-7B 日本語AIアシスタント (Colab T4)」というタイトルの、洗練されたチャット画面が表示されれば大成功です。画面の下には、すぐに試せるように3つの例文(量子コンピュータの仕組み、Pythonのスクリプト作成、歴史の考察など)も用意されています。
まずは例文をクリックして、AIがどれほどのスピードと高い知性で回答を導き出してくれるか、ストリーミング(文字が流れるように表示される様子)を体験してみてください。その後は、知的好奇心を満たす深い考察や、日々の生活に関する疑問、あるいは文章作成の相談など、気になることを何でも自由に質問してみましょう。きっと、その圧倒的な性能に驚かれるはずです。

使い終わった後のお片付けルール

最後に、一つだけ重要なお約束があります。AIとの対話を十分に楽しんで終了する際は、必ず「お片付け」をしてください。Googleのサーバーは共有の資源です。
チャット画面のタブを閉じたら、必ずGoogle Colabの元の画面に戻り、画面上部の「ランタイム」メニューから「ランタイムを接続解除して削除」をクリックして、借りていたコンピューターを返却してください。これを習慣づけることで、次回もエラーのない綺麗な状態からスムーズに始めることができます。

まとめ

全5回にわたってお届けしてきた「低スペックPCでもオープンソースAIを動かせる!」の連載は、これにて完結となります。

最初は難しそうに感じたかもしれませんが、ブラウザとGoogleアカウントさえあれば、プログラミングの深い知識がなくても、世界最高峰の技術に触れることができる時代になりました。今回構築したシステムは、個人で利用するには十分すぎるほどの性能と安定性を誇っています。
この仕組みを活用すれば、日常の調べ物や趣味の探求など、知的生活がさらに豊かで刺激的なものになることは間違いありません。

これからは、このAIアシスタントを良きパートナーとして、新しいテクノロジーがもたらすワクワクするような未来を存分に楽しんでください。最後まで連載にお付き合いいただき、本当にありがとうございました。これからも、素晴らしい体験を続けていきましょう!

参考リスト


タイトルとURLをコピーしました