Spaces:
Sleeping
Sleeping
| """ | |
| BaseAI - すべてのAIモデルアダプターの基底クラス | |
| """ | |
| from abc import ABC, abstractmethod | |
| from typing import List, Tuple, Optional | |
| class BaseAI(ABC): | |
| """ | |
| すべてのAIモデルアダプターが実装すべき基底クラス | |
| 各モデルは以下のメソッドを実装する必要があります: | |
| - get_token_probabilities: トークン確率の取得 | |
| - build_chat_prompt: モデル固有のプロンプト形式への変換 | |
| """ | |
| def get_token_probabilities(self, text: str, k: int = 5) -> List[Tuple[str, float]]: | |
| """ | |
| テキストから次のトークン候補と確率を取得 | |
| Args: | |
| text: 入力テキスト(プロンプト) | |
| k: 取得するトークン候補数 | |
| Returns: | |
| List[Tuple[str, float]]: (トークン, 確率)のリスト(確率順) | |
| """ | |
| raise NotImplementedError | |
| def build_chat_prompt( | |
| self, | |
| user_content: str, | |
| system_content: str = "", | |
| assistant_content: Optional[str] = None | |
| ) -> str: | |
| """ | |
| モデル固有のチャットプロンプト形式に変換 | |
| 注意: モデルによってuser/assistantの分離方法が異なります | |
| - OpenAI, Claude: user/assistantを明確に分離することを推奨 | |
| - Gemini: user/assistantを分離しない方が良い場合もある | |
| - Transformers: モデルによって異なる(Llamaは分離推奨) | |
| Args: | |
| user_content: ユーザーのメッセージ | |
| system_content: システムプロンプト(オプション) | |
| assistant_content: アシスタントの既存応答(会話履歴用、オプション) | |
| Returns: | |
| str: モデル固有のプロンプト形式 | |
| """ | |
| raise NotImplementedError | |
| def _clean_text(self, text: str) -> str: | |
| """ | |
| 制御文字・不可視文字・置換文字を厳密に取り除く(共通処理) | |
| Args: | |
| text: クリーンアップするテキスト | |
| Returns: | |
| str: クリーンアップされたテキスト | |
| """ | |
| if not text: | |
| return "" | |
| # 制御文字(0x00-0x1F、0x7F-0x9F)を除去 | |
| # ただし、改行・タブ・復帰は許可 | |
| cleaned = [] | |
| for ch in text: | |
| code = ord(ch) | |
| # 許可する制御文字: 改行(0x0A), タブ(0x09), 復帰(0x0D) | |
| if code in [0x09, 0x0A, 0x0D]: | |
| cleaned.append(ch) | |
| # 通常の印刷可能文字 | |
| elif ch.isprintable(): | |
| # 置換文字(U+FFFD)を除去 | |
| if ch != "\uFFFD": | |
| cleaned.append(ch) | |
| # その他の制御文字や不可視文字は除去 | |
| result = "".join(cleaned) | |
| # ゼロ幅文字を除去 | |
| result = result.replace("\u200B", "") # Zero-width space | |
| result = result.replace("\u200C", "") # Zero-width non-joiner | |
| result = result.replace("\u200D", "") # Zero-width joiner | |
| result = result.replace("\uFEFF", "") # Zero-width no-break space | |
| # その他の不可視文字(結合文字など)を除去 | |
| result = result.replace("\u200E", "") # Left-to-right mark | |
| result = result.replace("\u200F", "") # Right-to-left mark | |
| result = result.replace("\u202A", "") # Left-to-right embedding | |
| result = result.replace("\u202B", "") # Right-to-left embedding | |
| result = result.replace("\u202C", "") # Pop directional formatting | |
| result = result.replace("\u202D", "") # Left-to-right override | |
| result = result.replace("\u202E", "") # Right-to-left override | |
| return result.strip() | |