LLMView_multi_model / package /ai /google_ai.py
WatNeru's picture
first commit
0447f30
"""
GoogleAI - Google API(Gemini)用アダプター
"""
from typing import List, Tuple, Optional
import os
import math
from .base import BaseAI
class GoogleAI(BaseAI):
"""
Google API(Gemini)用アダプター
特徴:
- API経由でモデルにアクセス
- logprobsパラメータでトークン確率を取得可能
- user/assistantを分離しない方が良い場合もある(テキスト形式)
- systemとuserを結合したテキスト形式を推奨
"""
_instances = {} # モデルごとのインスタンスをキャッシュ
def __new__(cls, model_name: str = None, api_key: str = None):
"""シングルトンパターンでクライアントを常駐"""
model = model_name or os.getenv("GOOGLE_MODEL", "gemini-pro")
key = api_key or os.getenv("GOOGLE_API_KEY")
cache_key = f"{model}:{key}"
if cache_key not in cls._instances:
cls._instances[cache_key] = super().__new__(cls)
cls._instances[cache_key]._initialized = False
return cls._instances[cache_key]
def __init__(self, model_name: str = None, api_key: str = None):
"""
初期化
Args:
model_name: モデル名(例: "gemini-pro")
api_key: Google APIキー
"""
if hasattr(self, '_initialized') and self._initialized:
return
self.model_name = model_name or os.getenv("GOOGLE_MODEL", "gemini-pro")
self.api_key = api_key or os.getenv("GOOGLE_API_KEY")
self._initialized = True
if not self.api_key:
raise ValueError("GOOGLE_API_KEYが設定されていません")
# Google Generative AIクライアントを初期化
try:
import google.generativeai as genai
genai.configure(api_key=self.api_key)
self.model = genai.GenerativeModel(self.model_name)
print(f"[GoogleAI] 初期化完了: モデル={self.model_name}")
except ImportError:
raise ImportError("google-generativeaiパッケージがインストールされていません。pip install google-generativeai を実行してください")
except Exception as e:
raise ValueError(f"Google Generative AIクライアントの初期化に失敗しました: {e}")
@classmethod
def get_model(cls, model_name: str = None, api_key: str = None) -> 'GoogleAI':
"""モデルインスタンスを取得(常駐キャッシュから)"""
return cls(model_name, api_key)
@classmethod
def clear_cache(cls):
"""キャッシュをクリア(開発・テスト用)"""
cls._instances.clear()
def get_token_probabilities(self, text: str, k: int = 5) -> List[Tuple[str, float]]:
"""
文章とkを引数に、{token, 確率}のリストを返す
Args:
text: 入力文章(プロンプト)
k: 取得するトークン数
Returns:
List[Tuple[str, float]]: (トークン, 確率)のリスト
"""
try:
# Gemini APIでトークン確率を取得
# 注意: Gemini APIのlogprobs取得方法は他のAPIと異なる可能性があります
response = self.model.generate_content(
text,
generation_config={
"max_output_tokens": 1, # 次のトークン1つだけを取得
"temperature": 0.0, # 確定的な結果を得るため
}
)
# 注意: Gemini APIのlogprobs取得方法は公式ドキュメントを確認してください
# ここでは仮の実装です
items: List[Tuple[str, float]] = []
# 実際の実装では、responseからlogprobsを取得する必要があります
# 現在のGemini APIでは、logprobsの直接取得が難しい可能性があります
# 代替案: 複数回のサンプリングで確率を推定
print("[GoogleAI] 警告: Gemini APIのlogprobs取得は実装が不完全です")
return items
except Exception as e:
print(f"[GoogleAI] トークン確率取得エラー: {e}")
import traceback
traceback.print_exc()
return []
def build_chat_prompt(
self,
user_content: str,
system_content: str = "あなたは親切で役に立つAIアシスタントです。簡潔な回答をしてください",
assistant_content: Optional[str] = None
) -> str:
"""
チャットプロンプトを構築(Gemini形式)
注意: Geminiでは、user/assistantを分離しない方が良い場合もあります。
systemとuserを結合したテキスト形式を推奨します。
Args:
user_content: ユーザーのメッセージ
system_content: システムプロンプト
assistant_content: アシスタントの既存応答(会話履歴用、オプション)
Returns:
str: Gemini形式のプロンプト(テキスト)
"""
prompt_parts = []
# Systemメッセージ(最初に1回だけ)
if system_content:
prompt_parts.append(f"システム: {system_content}")
prompt_parts.append("")
# 会話履歴がある場合(assistant_contentが指定されている場合)
if assistant_content:
prompt_parts.append(f"ユーザー: {user_content}")
prompt_parts.append(f"アシスタント: {assistant_content}")
prompt_parts.append("")
# 現在のUserメッセージ
prompt_parts.append(f"ユーザー: {user_content}")
prompt_parts.append("アシスタント:")
prompt_text = "\n".join(prompt_parts)
return prompt_text