import os import threading import gradio as gr from llama_cpp import Llama # 同時リクエスト時にCPU資源が衝突し、サーバーがフリーズするのを防ぐためのロック(排他制御) model_lock = threading.Lock() # 2 vCPUのCPU Basic環境に最適化 n_threads = 2 # モデルのロード # 複数スレッドからの安全なアクセスに耐えるよう初期化 llm = Llama.from_pretrained( repo_id="mmnga/RakutenAI-2.0-mini-instruct-gguf", filename="RakutenAI-2.0-mini-instruct-Q4_0.gguf", n_ctx=1536, # 長文コードに対応するための容量 n_threads=n_threads, n_threads_batch=n_threads, n_batch=128, verbose=False ) def respond(message, chat_history): # 他の同時リクエスト(別タブのユーザーなど)と同時に推論が走ってモデルがクラッシュするのを防ぎます。 # 順番待ち(キュー)が発生した際も、前の処理が終わり次第、次の処理がクリアな状態で動き出します。 with model_lock: # システムプロンプト messages = [ { "role": "system", "content": ( "あなたは優秀で誠実な日本人アシスタントです。質問に対して常に丁寧かつ分かりやすく回答してください。 " "プログラミングのソースコードを生成・修正する際は、途中で省略せず、最後まで完成された動作可能なコードを提示してください。" ) } ] # メモリの引き継ぎを防ぐため、履歴はクリーンに初期化し、直近の1往復(最新の1ターン)のみを安全に抽出 last_turns = chat_history[-1:] if chat_history else [] for turn in last_turns: if isinstance(turn, dict): role = turn.get("role") content = turn.get("content") if role in ["user", "assistant"] and content: messages.append({"role": role, "content": content}) elif isinstance(turn, (list, tuple)) and len(turn) == 2: user_msg, bot_msg = turn if user_msg: messages.append({"role": "user", "content": user_msg}) if bot_msg: messages.append({"role": "assistant", "content": bot_msg}) # 最新のメッセージを追加 messages.append({"role": "user", "content": message}) # 推論(ストリーミング出力) response_stream = llm.create_chat_completion( messages=messages, max_tokens=1024, temperature=0.2, stream=True ) partial_reply = "" for chunk in response_stream: delta = chunk["choices"][0]["delta"] if "content" in delta: partial_reply += delta["content"] yield partial_reply # チャットUIの定義 demo = gr.ChatInterface( fn=respond, concurrency_limit=3, # キューイング制限を3に設定し、CPU Basic環境でのリソース枯渇を防止 title="Meronly - Rakuten AI 2.0 Mini", description=""" 低速ですがサードパーティ製Rakuten AI利用可能サイト、唯一(おそらく)のページです。
※2 vCPU環境向けに処理を大幅に高速化・安定化させています。

ライセンス情報:
本アプリは、Apache License 2.0 に基づき提供されている楽天グループ株式会社のオープンモデル RakutenAI-2.0-mini-instruct をコミュニティ有志が軽量化したGGUF版を使用しています。 """ ) if __name__ == "__main__": demo.launch()