ローカルで完結する生成AIアプリを「日本語版 Gemma 2 2B」で実装
画像はDALL·E 3で生成しました
はじめに
生成AIが注目されて約2年となりますが、その活用はセキュリティやハルシネーションなどの懸念が常に付きまとってきました。特に、クライアントデータや個人情報に対して生成AIを使うことはかなりのハードルになっています。その要因の1つは、クラウド上にデータを送ることによるセキュリティリスクとなります。
例えば、この記事で取り上げる日英翻訳についても、業務情報をクラウド上にアップロードして翻訳してよいものかという議論があります。
一方で、生成AIの中でもSLM(Small Language Model)の進化はここ数か月で目覚ましいものになっている認識です。
GemmaやPhi、Llamaなど。
特に下記記事でとりあげたGemmaの日本語ファインチューニングは進んできていて、SLMでも日本語がだいぶ通用するようになってきています。
そうだ、ローカル(端末のみ)で完結する翻訳アプリを作ってみよう
ここで思いついたのが、SLMを活用したローカル上で完結するアプリを作ってみてはどうかということ。
具体的には、翻訳アプリは作ってみようと思いました。
アーキテクチャ - PythonからOllama経由でGemma2へアクセス
Pythonでチャット画面を実装して、SLM「gemma-2-2b-jpn-it」へアクセスします。
SLMをローカル上で動かすので、チャットにインプットした情報がインターネットへ流出する心配はありません。
構築手順
Ollamaのインストール
下記記事はGemma2の記事ですが、Ollamaのインストール手順も記載しています。この手順を参考にインストールします。
gemma-2-2b-jpn-itのデプロイ
schronekoさんがollamaで使えるようにしてくれています。本当に感謝です。 下記コマンドでデプロイできます。
ollama run schroneko/gemma-2-2b-jpn-it
こんなイメージで。2回目以降はデプロイではなく「gemma-2-2b-jpn-it」の実行のみとなります!
Pythonで実装
ollamaのライブラリをまずインストールしましょう。
pip install ollama
Claudeを使ってサッとコーディングしました。
import tkinter as tk
from tkinter import scrolledtext, ttk
import ollama
import threading
import re
class OllamaChatGUI:
def __init__(self, master):
self.master = master
master.title("Ollama Translator")
master.geometry("600x500")
self.chat_history = scrolledtext.ScrolledText(master, state='disabled', height=20)
self.chat_history.pack(padx=10, pady=10, fill=tk.BOTH, expand=True)
self.direction_var = tk.StringVar()
self.direction_var.set("English to Japanese")
self.direction_dropdown = ttk.Combobox(master, textvariable=self.direction_var,
values=["English to Japanese", "Japanese to English"],
state="readonly")
self.direction_dropdown.pack(padx=10, pady=5)
self.msg_entry = tk.Text(master, height=3, width=50)
self.msg_entry.pack(side=tk.LEFT, padx=10, pady=10)
self.msg_entry.bind("<Control-Return>", self.send_message)
self.send_button = tk.Button(master, text="Translate", command=self.send_message)
self.send_button.pack(side=tk.LEFT, padx=10, pady=10)
self.system_prompts = {
"Japanese to English": """
Translate the input message from Japanese to English.
# Output Format
- Provide only the translation result without any additional text or explanation.
""",
"English to Japanese": """
Translate the input message from English to Japanese.
# Output Format
- Provide only the translation result without any additional text or explanation.
"""
}
def send_message(self, event=None):
user_message = self.msg_entry.get("1.0", tk.END).strip()
if user_message:
direction = self.direction_var.get()
self.append_message(f"Original ({direction.split(' to ')[0]}): " + user_message)
self.msg_entry.delete("1.0", tk.END)
threading.Thread(target=self.get_ollama_response, args=(user_message, direction)).start()
def get_ollama_response(self, user_message, direction):
try:
system_prompt = self.system_prompts[direction]
messages = [
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_message}
]
response = ollama.chat(model='schroneko/gemma-2-2b-jpn-it', messages=messages)
assistant_message = response['message']['content']
cleaned_message = self.clean_response(assistant_message)
self.append_message(f"Translation ({direction.split(' to ')[1]}): " + cleaned_message)
except Exception as e:
self.append_message("Error: " + str(e))
def clean_response(self, message):
# 不要な文言を削除
cleaned = re.sub(r'</?(start_of_turn|end_of_turn)>', '', message)
# 前後の空白を削除
cleaned = cleaned.strip()
return cleaned
def append_message(self, message):
self.chat_history.configure(state='normal')
self.chat_history.insert(tk.END, message + "\n\n")
self.chat_history.configure(state='disabled')
self.chat_history.see(tk.END)
if __name__ == "__main__":
root = tk.Tk()
gui = OllamaChatGUI(root)
root.mainloop()
実行
先ほどのPythonをコマンドプロンプトで実行します。すると下記のようなウインドウが表示されます。
英語 → 日本語
下記英文の記事の冒頭を日本語に翻訳してみましょう。
具体的には下記英文です。We've developed a new series of AI models designed to spend more time thinking before they respond. They can reason through complex tasks and solve harder problems than previous models in science, coding, and math.
翻訳している様子はこんな感じ。
日本語 → 英語
今度は日本語から英語に翻訳してみます。
下記日本語の記事を英語に翻訳してみましょう。
具体的には下記日本語文です。
Felo Search は AI 駆動の検索エンジンで、世界中の知識を発見し理解するために最適化された多言語対応の人工知能検索エンジンです。情報源を検索して詳細な回答を迅速にまとめ、ユーザーがどのような質問をしてもインターネットを検索し、理解しやすく検証可能な回答を提供します。知識を広げ、個別の洞察と情報を提供することができます。
翻訳している様子はこんな感じ。
NPU等の活用が待たれる
今回はCPUを使ったSLM活用になっています。Copilot+PCに搭載されているNPUを活用できるようになるとさらに幅が広がるのではと考えています。
実際、実装したツールを使って翻訳するとCPUが跳ね上がっていてCPUが使われていることがわかります。
おわりに
今回のアプリを応用して、メールの概要を生成する端末アプリも作れたりします。また、端末上で音声の文字お越しがスムーズにできれば通話しながら端末だけでリアルタイム通訳できる日も夢ではなくなってきています!
急速に進化を遂げている生成AI界隈ですが、引き続き追っていけたらと考えています!
Discussion