Spaces:
Sleeping
Sleeping
| """ | |
| ModelAdapter - マルチモデル対応アダプター | |
| 新しいAIインターフェース(BaseAI)に対応 | |
| """ | |
| from typing import Any, Dict, List, Optional | |
| from .word_processor import WordDeterminer, WordPiece | |
| from .ai.base import BaseAI | |
| class ModelAdapter: | |
| """ | |
| マルチモデル対応アダプター | |
| - 初期化コストの高いコンポーネント(WordDeterminer, AIモデル)を1回だけ生成して保持 | |
| - メソッドでビルド処理を提供 | |
| - 返却はシリアライズしやすい dict/list 形式 | |
| """ | |
| def __init__(self, ai_model: BaseAI): | |
| """ | |
| 初期化 | |
| Args: | |
| ai_model: BaseAIを実装したモデルインスタンス | |
| """ | |
| # WordDeterminer(内部で Sudachi C モードの WordCounter を使用) | |
| self.determiner = WordDeterminer() | |
| # AIモデルを保持 | |
| self.model = ai_model | |
| def _clean_text(self, text: str) -> 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 | |
| return result.strip() | |
| def build_word_tree( | |
| self, | |
| prompt_text: str, | |
| root_text: str = "", | |
| top_k: int = 5, | |
| max_depth: int = 10 | |
| ) -> List[Dict[str, Any]]: | |
| """ | |
| 単語ツリーを構築して、完成ピースを dict の配列で返す。 | |
| 各要素: { text: str, probability: float } | |
| """ | |
| pieces: List[WordPiece] = self.determiner.build_word_tree( | |
| prompt_text=prompt_text, | |
| root_text=root_text, | |
| model=self.model, | |
| top_k=top_k, | |
| max_depth=max_depth, | |
| ) | |
| return [ | |
| {"text": self._clean_text(p.get_full_word()), "probability": float(p.probability)} | |
| for p in pieces | |
| ] | |
| def build_chat_prompt( | |
| self, | |
| user_content: str, | |
| system_content: str = "あなたは親切で役に立つAIアシスタントです。" | |
| ) -> str: | |
| """チャットプロンプト文字列を返す。""" | |
| return self.model.build_chat_prompt(user_content, system_content) | |
| def count_words(self, text: str) -> int: | |
| """Sudachi(C) ベースでの語数カウント。""" | |
| return self.determiner._count_words(text) | |