From bcfbf5169641c0f8ead8fd7780a334f958934bfb Mon Sep 17 00:00:00 2001 From: misyaguziya <53165965+misyaguziya@users.noreply.github.com> Date: Mon, 20 Oct 2025 01:19:49 +0900 Subject: [PATCH] =?UTF-8?q?LMStudio=20=E8=AA=8D=E8=A8=BC=E5=91=BC=E3=81=B3?= =?UTF-8?q?=E5=87=BA=E3=81=97=E3=81=A7=20base=5Furl=20=E3=82=92=E6=98=8E?= =?UTF-8?q?=E7=A4=BA=E6=B8=A1=E3=81=97=E3=81=B8=E4=BF=AE=E6=AD=A3=20+=20?= =?UTF-8?q?=E3=83=89=E3=82=AD=E3=83=A5=E3=83=A1=E3=83=B3=E3=83=88=E6=95=B4?= =?UTF-8?q?=E5=82=99=EF=BC=88=E3=83=AD=E3=83=BC=E3=82=AB=E3=83=ABLLM/?= =?UTF-8?q?=E8=A8=80=E8=AA=9E=E3=83=9E=E3=83=83=E3=83=94=E3=83=B3=E3=82=B0?= =?UTF-8?q?/=E3=83=95=E3=82=A9=E3=83=B3=E3=83=88=E7=AD=89=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - controller: model.authenticationTranslatorLMStudio 呼び出しに base_url=config.LMSTUDIO_URL を明示的に渡すよう修正(LMStudio 接続判定で設定 URL を利用) - docs: 新規ドキュメントを追加・更新 - 追加: translation_gemini.md, translation_lmstudio.md, translation_ollama.md, translation_openai.md, translation_plamo.md - 更新: config.md, controller.md, mainloop.md, model.md, overlay.md, translation_languages.md, translation_translator.md, 仕様書.md(翻訳/モデル管理・エンドポイント・YAML 言語定義・フォント探索・VRAM フォールバック等の記載追加) - ドキュメントに記載した主な変更点 - LMStudio / Ollama のローカルLLM統合(モデルリスト/選択用プロパティ追加、接続確認エンドポイント) - CTranslate2 の言語定義を weight_type ネスト構造へ変更対応 - 外部 YAML による言語マッピング導入(loadTranslationLanguages) - フォント探索を PyInstaller バンドル(_internal/fonts/) を考慮して強化 - 認証後のモデルリスト自動更新・SELECTED_* プロパティ名統一、VRAM エラー検知時の自動フォールバック等の動作説明追加 (コードの振る舞いは既存処理に合わせた引数指定の修正とドキュメント反映が主体) --- src-python/controller.py | 4 +- src-python/docs/details/config.md | 59 +++++++++- src-python/docs/details/controller.md | 108 ++++++++++++++++-- src-python/docs/details/mainloop.md | 79 ++++++++++++- src-python/docs/details/model.md | 87 +++++++++++++- src-python/docs/details/overlay.md | 23 +++- src-python/docs/details/translation_gemini.md | 87 ++++++++++++++ .../docs/details/translation_languages.md | 53 ++++++++- .../docs/details/translation_lmstudio.md | 86 ++++++++++++++ src-python/docs/details/translation_ollama.md | 86 ++++++++++++++ src-python/docs/details/translation_openai.md | 85 ++++++++++++++ src-python/docs/details/translation_plamo.md | 86 ++++++++++++++ .../docs/details/translation_translator.md | 48 +++++++- src-python/docs/仕様書.md | 76 +++++++++++- 14 files changed, 943 insertions(+), 24 deletions(-) create mode 100644 src-python/docs/details/translation_gemini.md create mode 100644 src-python/docs/details/translation_lmstudio.md create mode 100644 src-python/docs/details/translation_ollama.md create mode 100644 src-python/docs/details/translation_openai.md create mode 100644 src-python/docs/details/translation_plamo.md diff --git a/src-python/controller.py b/src-python/controller.py index f8ce770c..b9d4bab6 100644 --- a/src-python/controller.py +++ b/src-python/controller.py @@ -1881,7 +1881,7 @@ class Controller: printLog("Check Translator LMStudio Connection") translator_name = "LMStudio" try: - result = model.authenticationTranslatorLMStudio() + result = model.authenticationTranslatorLMStudio(base_url=config.LMSTUDIO_URL) if result is True: config.SELECTABLE_TRANSLATION_ENGINE_STATUS[translator_name] = True config.SELECTABLE_LMSTUDIO_MODEL_LIST = model.getTranslatorLMStudioModelList() @@ -2984,7 +2984,7 @@ class Controller: printLog("Start check LMStudio API Key") config.SELECTABLE_TRANSLATION_ENGINE_STATUS[engine] = False if config.LMSTUDIO_URL is not None: - if model.authenticationTranslatorLMStudio(config.LMSTUDIO_URL) is True: + if model.authenticationTranslatorLMStudio(base_url=config.LMSTUDIO_URL) is True: config.SELECTABLE_TRANSLATION_ENGINE_STATUS[engine] = True printLog("LMStudio URL is valid") config.SELECTABLE_LMSTUDIO_MODEL_LIST = model.getTranslatorLMStudioModelList() diff --git a/src-python/docs/details/config.md b/src-python/docs/details/config.md index fd619d77..1c008b03 100644 --- a/src-python/docs/details/config.md +++ b/src-python/docs/details/config.md @@ -389,4 +389,61 @@ config.saveConfig("ENABLE_TRANSLATION", True, immediate_save=True) - 設定ファイルの適切な権限管理 - 外部入力値の検証 - APIキー等の機密情報の適切な取り扱い -- パスインジェクション攻撃の防止 \ No newline at end of file +- パスインジェクション攻撃の防止 + +## 最近の更新 (2025-10-20) + +### LMStudio / Ollama ローカル LLM 設定プロパティ追加 + +- `LMSTUDIO_URL` / `SELECTABLE_LMSTUDIO_MODEL_LIST` / `SELECTED_LMSTUDIO_MODEL` +- `SELECTABLE_OLLAMA_MODEL_LIST` / `SELECTED_OLLAMA_MODEL` + +ローカル推論エンジン接続用 URL と動的モデルリスト取得・選択プロパティを追加。認証は不要で接続テスト後自動でモデルリストを更新。 + +### モデル選択プロパティ名称統一 + +Plamo / Gemini / OpenAI の選択モデルを `PLAMO_MODEL` / `GEMINI_MODEL` / `OPENAI_MODEL` から `SELECTED_PLAMO_MODEL` / `SELECTED_GEMINI_MODEL` / `SELECTED_OPENAI_MODEL` へ統一。設定 JSON の保存キーも `SELECTED_*` に変更し UI との整合性を確保。 + +### CTranslate2 言語マッピング構造変更対応 + +`translation_lang` 内の CTranslate2 言語辞書が `translation_lang["CTranslate2"][weight_type]["source"|"target"]` へネスト化。`CTRANSLATE2_WEIGHT_TYPE` プロパティがアクセスのキーとなるため、重みタイプ変更時に翻訳エンジン再初期化が必要。 + +### YAML 言語外部定義導入 + +`loadTranslationLanguages()` を初期化時に呼び出し、`models/translation/languages/languages.yml` を読み込んで既存マッピングへマージ。失敗時は空辞書フォールバック。動的言語追加がコード改修無しで可能になったため設定初期化の失敗ログ確認が重要。 + +### OpenAI モデルリスト自動更新 + +`setOpenAIAuthKey()` 成功後に `SELECTABLE_OPENAI_MODEL_LIST` を取得し未選択の場合は先頭を自動選択。Gemini / Plamo / LMStudio / Ollama も同様に認証/接続確立時にリスト更新と未選択モデル補完。 + +### フォント設定のパッケージ対応 + +`overlay_image.py` で PyInstaller ビルド環境(`_internal/fonts/`)検出を追加。開発環境とバンドル後でフォント探索パスが異なるため、`FONT_FAMILY` はファイル名基準のまま変更無し。 + +### 依存関係追加 + +- `PyYAML`: 言語マッピング YAML 読み込み +- `google-genai`: Gemini 連携 +- `grpcio`: OpenAI 連携(ストリーミング等) + +### VRAM エラー時の自動フォールバック + +翻訳有効化や翻訳実行時に VRAM 不足検出で `ENABLE_TRANSLATION` を False にし CTranslate2 へ強制切替。設定値は保持されるが UI には無効化状態を通知。再度有効化要求時に重いモデル再初期化を試行。 + +### テスト関連 + +包括的翻訳ペアテストにより `SELECTED_*` モデルと言語マッピング組合せを大量実行。設定値の変更頻度増加に伴いデバウンス 2 秒でファイル書き込み負荷を抑制。 + +### 影響まとめ + +| 項目 | 内容 | +|------|------| +| ローカルLLM | LMStudio / Ollama の導入でオフライン翻訳拡張 | +| プロパティ統一 | SELECTED_* 命名で一貫性・ドキュメント整備性向上 | +| 言語ネスト化 | CTranslate2 重みタイプ切替処理の再初期化必要性増加 | +| YAML外部化 | 言語追加が設定初期化のみで反映可能 | +| モデルリスト自動更新 | 認証後の選択ミス防止・初回 UX 改善 | +| フォント探索 | PyInstaller ビルド後でも同一コードで動作 | +| 依存追加 | 新機能対応で環境構築ステップ増加 | +| VRAM検知 | 安全停止と軽量エンジン切替で安定性向上 | +| テスト増強 | 大量ペア検証で言語/モデル設定の信頼性向上 | diff --git a/src-python/docs/details/controller.md b/src-python/docs/details/controller.md index ca1fefda..66adb775 100644 --- a/src-python/docs/details/controller.md +++ b/src-python/docs/details/controller.md @@ -4,25 +4,77 @@ VRCTアプリケーションのビジネスロジックを制御するコントローラークラスです。UI層とモデル層の間に位置し、ユーザーの入力を適切な処理に変換し、結果を UI に返す役割を担います。全ての機能制御、設定管理、状態管理を一元的に行います。 +## 最近の更新 (2025-10-20) + +### 新規ローカルLLM翻訳エンジン統合 + +- LMStudio / Ollama への接続確認エンドポイント追加: `/get/data/lmstudio_connection`, `/get/data/ollama_connection` +- LMStudio URL 設定: `/get|set/data/lmstudio_url` +- モデルリスト取得と選択: `/get/data/*_model_list`, `/get|set/data/*_model` (lmstudio / ollama / plamo / gemini / openai) +- 認証・接続成功時に `selectable_*_model_list` / `selected_*_model` を run 経由で通知 (例: `/run/selectable_lmstudio_model_list`, `/run/selected_lmstudio_model`) + +### モデルリスト自動更新フロー + +- Plamo / Gemini / OpenAI 認証後に動的に最新モデルリストを取得し未選択時は先頭モデルへ自動設定 +- LMStudio / Ollama は接続成功時にローカル列挙したモデルを即座に選択候補へ反映 + +### VRAMエラー検出と自動フォールバック + +- 翻訳処理中の `CUDA out of memory` / `CUBLAS_STATUS_ALLOC_FAILED` などを検出し `/run/error_translation_*_vram_overflow` で通知 +- 自動で翻訳機能を無効化し CTranslate2 へフォールバック、再度有効化試行時も VRAM エラー検出で安全に解除 + +### CTranslate2 ウェイト / Whisper ウェイト管理 + +- ダウンロード進捗/完了/エラー用 run エンドポイント: `download_progress_ctranslate2_weight`, `downloaded_ctranslate2_weight`, `error_ctranslate2_weight` / Whisper も同様 +- `SELECTABLE_CTRANSLATE2_WEIGHT_TYPE_DICT` / `SELECTABLE_WHISPER_WEIGHT_TYPE_DICT` の値更新を完了時に反映 + +### 命名・構造整理 + +- 翻訳エンジン選択はタブ別 `SELECTED_TRANSLATION_ENGINES[tab_no]` を使用 +- 言語選択構造: `SELECTED_YOUR_LANGUAGES[tab_no]`, `SELECTED_TARGET_LANGUAGES[tab_no]` のネストを前提にエンジン適合性判定 +- CTranslate2 の言語マッピングはウェイト種別 (`CTRANSLATE2_WEIGHT_TYPE`) でネストされた構造に対応 + +### 言語マッピング外部化 + +- `getListLanguageAndCountry()` が YAML からロード済み `translation_lang` / `transcription_lang` を統合して互換言語のみ抽出 + +### デバイス自動選択改善 + +- マイク/スピーカー自動選択機能で更新前後に適切な停止/再開コールバックをチェーン設定 (energy チェック再起動含む) + +### 影響 + +| 項目 | 内容 | +|------|------| +| 翻訳柔軟性 | ローカルLLM (LMStudio/Ollama) によりネットワーク不要運用が可能 | +| 回復性 | VRAMエラー時自動フォールバックで異常終了を防止 | +| 拡張性 | モデルリスト自動更新により新モデル追加時の手動変更不要化 | +| 一貫性 | 統一された SELECTED_/SELECTABLE_ 命名とタブ別管理で UI 連携が簡易化 | +| 可読性 | 外部 YAML 言語定義によりコード側のハードコード削減 | + ## 主要機能 ### 機能制御 + - 翻訳機能の有効化・無効化 - 音声認識機能の制御 - VRオーバーレイの管理 - WebSocketサーバーの制御 ### 設定管理 + - アプリケーション設定の取得・更新 - デバイス設定の管理 - 言語・エンジン設定の制御 ### 状態管理 + - システム状態の監視 - エラー状態の管理 - 初期化プロセスの制御 ### 通信制御 + - OSC通信の管理 - WebSocket通信の制御 - 外部アプリケーション連携 @@ -30,6 +82,7 @@ VRCTアプリケーションのビジネスロジックを制御するコント ## クラス構造 ### Controller クラス + ```python class Controller: def __init__(self) -> None @@ -40,19 +93,23 @@ class Controller: ### 内部ヘルパークラス #### DownloadCTranslate2 クラス + ```python class DownloadCTranslate2: def progressBar(self, progress) -> None def downloaded(self) -> None ``` + - 翻訳モデルのダウンロード進捗管理 -#### DownloadWhisper クラス +#### DownloadWhisper クラス + ```python class DownloadWhisper: def progressBar(self, progress) -> None def downloaded(self) -> None ``` + - 音声認識モデルのダウンロード進捗管理 ## 主要メソッド @@ -62,6 +119,7 @@ class DownloadWhisper: ```python init() -> None ``` + - コントローラーの初期化 - 各コンポーネントの起動 - 初期設定の適用 @@ -71,6 +129,7 @@ setInitMapping(init_mapping: dict) -> None setRunMapping(run_mapping: dict) -> None setRun(run: Callable) -> None ``` + - エンドポイント・コールバック設定 ### 翻訳機能制御 @@ -79,23 +138,27 @@ setRun(run: Callable) -> None setEnableTranslation(data) -> dict setDisableTranslation(data) -> dict ``` + - 翻訳機能の有効化・無効化 ```python setSelectedTranslationEngines(data) -> dict getSelectedTranslationEngines(data) -> dict ``` + - 翻訳エンジンの選択・取得 ```python setSelectedYourLanguages(data) -> dict setSelectedTargetLanguages(data) -> dict ``` + - 送信・受信言語の設定 ```python sendMessageBox(data) -> dict ``` + - メッセージの翻訳・送信処理 ### 音声認識機能制御 @@ -104,24 +167,28 @@ sendMessageBox(data) -> dict setEnableTranscriptionSend(data) -> dict setEnableTranscriptionReceive(data) -> dict ``` + - 音声認識機能の有効化 ```python setSelectedTranscriptionEngine(data) -> dict getSelectedTranscriptionEngine(data) -> dict ``` + - 音声認識エンジンの選択・取得 ```python setSelectedMicDevice(data) -> dict setSelectedSpeakerDevice(data) -> dict ``` + - 音声デバイスの選択 ```python setMicThreshold(data) -> dict setSpeakerThreshold(data) -> dict ``` + - 音声しきい値の設定 ### VRオーバーレイ制御 @@ -130,12 +197,14 @@ setSpeakerThreshold(data) -> dict setEnableOverlaySmallLog(data) -> dict setEnableOverlayLargeLog(data) -> dict ``` + - VRオーバーレイの有効化 ```python setOverlaySmallLogSettings(data) -> dict setOverlayLargeLogSettings(data) -> dict ``` + - オーバーレイ設定の更新 ### WebSocket制御 @@ -144,12 +213,14 @@ setOverlayLargeLogSettings(data) -> dict setEnableWebSocketServer(data) -> dict setDisableWebSocketServer(data) -> dict ``` + - WebSocketサーバーの制御 ```python setWebSocketHost(data) -> dict setWebSocketPort(data) -> dict ``` + - WebSocket接続設定 ### システム管理 @@ -158,17 +229,20 @@ setWebSocketPort(data) -> dict updateSoftware(data) -> dict updateCudaSoftware(data) -> dict ``` + - ソフトウェアアップデート ```python downloadCtranslate2Weight(data) -> dict downloadWhisperWeight(data) -> dict ``` + - AIモデルのダウンロード ```python feedWatchdog(data) -> dict ``` + - ウォッチドッグの生存シグナル送信 ## 使用方法 @@ -233,6 +307,7 @@ result = controller.setEnableTranscriptionSend(None) ``` ### 成功レスポンス例 + ```python { "status": 200, @@ -241,6 +316,7 @@ result = controller.setEnableTranscriptionSend(None) ``` ### エラーレスポンス例 + ```python { "status": 400, @@ -248,19 +324,22 @@ result = controller.setEnableTranscriptionSend(None) } ``` -## 状態管理 +## 詳細状態管理 ### システム状態 + - 各機能の有効・無効状態 - デバイスの接続状態 - ネットワーク接続状態 -### エラー状態 +### エラー状態 + - デバイスエラー - 翻訳エンジンエラー - VRAMオーバーフローエラー ### 初期化状態 + - 段階的な初期化プロセス - 依存関係の解決状態 @@ -271,32 +350,38 @@ result = controller.setEnableTranscriptionSend(None) ```python micMessage(result: dict) -> None ``` + - マイク音声認識結果の処理 - 翻訳・フィルタリング・送信 ```python -speakerMessage(result: dict) -> None +speakerMessage(result: dict) -> None ``` + - スピーカー音声認識結果の処理 ### ダウンロードイベント + - 進捗通知 -- 完了通知 +- 完了通知 - エラー通知 ### デバイス変更イベント + - マイク・スピーカーの選択変更 - 計算デバイスの変更 ## 依存関係 ### 直接依存 + - `config`: 設定管理 -- `model`: コアモデル機能 +- `model`: コアモデル機能 - `device_manager`: デバイス管理 - `utils`: ユーティリティ機能 ### 間接依存 + - 各種モデルモジュール(翻訳、音声認識等) - VRオーバーレイモジュール - 通信モジュール @@ -304,32 +389,39 @@ speakerMessage(result: dict) -> None ## エラーハンドリング ### VRAM不足エラー + - 自動的にCTranslate2への切り替え - ユーザーへの適切な通知 ### デバイスエラー + - デバイス接続状態の監視 - 自動復旧機能 -### ネットワークエラー +### ネットワークエラー + - 接続状態の定期確認 - オフライン機能への切り替え ### 設定エラー + - 設定値の妥当性チェック - デフォルト値への復帰 ## パフォーマンス考慮事項 ### 遅延初期化 + - 必要な時点での機能初期化 - メモリ使用量の最適化 ### 非同期処理 + - バックグラウンドでの重い処理 - UI の応答性維持 ### キャッシュ機能 + - 設定値のキャッシュ - 翻訳結果のキャッシュ @@ -346,4 +438,4 @@ speakerMessage(result: dict) -> None - 外部入力の適切な検証 - APIキーの安全な管理 - ファイルアクセスの制限 -- ネットワーク通信の暗号化(該当する場合) \ No newline at end of file +- ネットワーク通信の暗号化(該当する場合) diff --git a/src-python/docs/details/mainloop.md b/src-python/docs/details/mainloop.md index 22a086ed..e89909d9 100644 --- a/src-python/docs/details/mainloop.md +++ b/src-python/docs/details/mainloop.md @@ -4,19 +4,59 @@ VRCTアプリケーションのメインイベントループを管理するモジュールです。標準入力からのJSONリクエストを処理し、適切なコントローラーメソッドを呼び出してレスポンスを返す、アプリケーションの中枢的な役割を担います。 +## 最近の更新 (2025-10-20) + +### 新規エンドポイントと run_mapping 拡張 + +- VRAM 関連エラー通知エンドポイント追加: `/run/error_translation_chat_vram_overflow` など 5 種類 (翻訳/音声認識送受信別) +- ローカル LLM (LMStudio/Ollama) モデルリスト通知: `/run/selectable_lmstudio_model_list`, `/run/selectable_ollama_model_list` と選択モデル `/run/selected_*_model` +- 従来の Plamo/Gemini/OpenAI モデル取得通知と形式統一 + +### エンドポイントロックキー正規化 + +- `/set/enable/*` `/set/disable/*` の競合を `/lock/set/` に正規化し排他制御強化 +- ロック取得失敗時は再キュー投入し軽量リトライでデッドロック防止 + +### 並列ワーカー処理の安定化 + +- ハンドラ処理後に短い `sleep(0.2)` により大量高速連続要求時のスレッド飢餓を緩和 +- 423 (Locked) ステータス時に指数的ではなく固定短期リトライ採用で応答時間予測性向上 + +### VRAM エラーフォールバック連携 + +- Controller が VRAM 検出し翻訳 OFF / CTranslate2 フォールバック後、run_mapping 経由で UI へ状態反映 +- ハンドラはエラー時でもスレッド継続し `Internal error` を 500 応答で返しつつログ出力 + +### モデルリスト動的更新通知 + +- 認証・接続成功後に対象モデルリスト/選択モデルを run で逐次通知 (Plamo/Gemini/OpenAI/LMStudio/Ollama) + +### 影響 + +| 項目 | 内容 | +|------|------| +| 安定性 | 排他制御と再キュー投入で競合時の落ち込み回避 | +| 可観測性 | VRAM/ダウンロード進捗/モデル更新イベントを run 経由で即時通知 | +| 拡張性 | 新規ローカル LLM エンジン追加に伴う汎用モデル通知フォーマット統一 | +| 応答予測性 | 固定リトライ戦略で待ち時間が読みやすい | +| フォールバック | VRAM エラー時の自動翻訳停止と CTranslate2 への切替連携 | + ## 主要機能 ### リクエスト処理システム + - JSON形式の標準入力からのリクエスト受信 - エンドポイントベースのルーティング - 非同期・並列処理対応 ### エンドポイント管理 + - RESTライクなエンドポイント構造 - 機能別のエンドポイント分類 - 排他制御によるスレッドセーフティ ### 初期化システム + - アプリケーション設定の初期化 - コンポーネント間の依存関係解決 - 段階的な機能有効化 @@ -24,6 +64,7 @@ VRCTアプリケーションのメインイベントループを管理するモ ## クラス構造 ### Main クラス + ```python class Main: def __init__(self, controller_instance: Controller, mapping_data: dict, worker_count: int = 3) @@ -36,46 +77,54 @@ class Main: ## エンドポイント分類 ### 機能制御系 -``` + +```text /set/enable/* - 各機能の有効化 /set/disable/* - 各機能の無効化 ``` ### データ操作系 -``` + +```text /get/data/* - 設定データの取得 /set/data/* - 設定データの更新 /delete/data/* - データの削除 ``` ### 実行系 -``` + +```text /run/* - 各種処理の実行 ``` ## 主要エンドポイント ### 翻訳機能 + - `/set/enable/translation`: 翻訳機能の有効化 - `/set/disable/translation`: 翻訳機能の無効化 - `/set/data/selected_translation_engines`: 翻訳エンジンの選択 - `/run/send_message_box`: メッセージ送信 ### 音声認識機能 + - `/set/enable/transcription_send`: 送信音声認識の有効化 - `/set/enable/transcription_receive`: 受信音声認識の有効化 - `/set/data/selected_transcription_engine`: 音声認識エンジン選択 ### VR機能 + - `/set/data/overlay_small_log_settings`: 小型オーバーレイ設定 - `/set/data/overlay_large_log_settings`: 大型オーバーレイ設定 ### WebSocket機能 + - `/set/enable/websocket_server`: WebSocketサーバー有効化 - `/set/data/websocket_host`: サーバーホスト設定 - `/set/data/websocket_port`: サーバーポート設定 ### システム管理 + - `/run/update_software`: ソフトウェアアップデート - `/run/download_ctranslate2_weight`: 翻訳モデルダウンロード - `/run/download_whisper_weight`: 音声認識モデルダウンロード @@ -87,18 +136,21 @@ class Main: ```python receiver() -> None ``` + - 標準入力からのJSONリクエスト受信 - パースエラーの適切な処理 ```python handleRequest(endpoint: str, data: Any = None) -> tuple ``` + - エンドポイント処理の実行 - ステータスコードと結果の返却 ```python handler() -> None ``` + - ワーカースレッドのメイン処理 - キューからのリクエスト取得・処理 @@ -107,21 +159,25 @@ handler() -> None ```python startReceiver() -> None ``` + - レシーバースレッドの起動 ```python startHandler() -> None ``` + - ハンドラースレッドプールの起動 ```python start() -> None ``` + - 全スレッドの起動 ```python stop(wait: float = 2.0) -> None ``` + - 全スレッドの安全な停止 ## 使用方法 @@ -164,6 +220,7 @@ result, status = main_instance.handleRequest("/set/enable/translation", None) ## リクエスト形式 ### 入力形式 + ```json { "endpoint": "string", // 必須:処理対象のエンドポイント @@ -172,6 +229,7 @@ result, status = main_instance.handleRequest("/set/enable/translation", None) ``` ### 出力形式 + ```json { "status": 200, // HTTPステータスコード @@ -191,11 +249,13 @@ result, status = main_instance.handleRequest("/set/enable/translation", None) ## 排他制御 ### ロック機能 + - enable/disableペアは同一ロックキーを共有 - 同一機能の同時実行を防止 - デッドロックを回避する設計 ### ロックキー正規化 + ```python /set/enable/translation -> /lock/set/translation /set/disable/translation -> /lock/set/translation @@ -204,32 +264,38 @@ result, status = main_instance.handleRequest("/set/enable/translation", None) ## 初期化プロセス ### 段階的初期化 + 1. コントローラーの初期化 2. デバイスマネージャーの初期化 3. モデルの初期化 4. 各機能の段階的有効化 ### 初期化mapping + - `/get/data/*`エンドポイントから初期化設定を自動抽出 - システム起動時の設定復元 ## ログ機能 ### プロセスログ + - 全リクエスト・レスポンスの記録 - JSON形式での構造化ログ ### エラーログ + - 例外の詳細記録 - スタックトレースの保存 ## 依存関係 ### 直接依存 + - `controller`: ビジネスロジック制御 - `utils`: ユーティリティ機能(ログ、エンコード等) ### 間接依存 + - `config`: 設定管理 - `model`: コアモデル機能 - `device_manager`: デバイス管理 @@ -237,11 +303,13 @@ result, status = main_instance.handleRequest("/set/enable/translation", None) ## 設定項目 ### ワーカー数 + ```python DEFAULT_WORKER_COUNT = 3 # 並列処理スレッド数 ``` ### タイムアウト + - キュー待機タイムアウト: 0.5秒 - スレッド停止待機: 2.0秒 - 処理安定化待機: 0.2秒 @@ -256,14 +324,17 @@ DEFAULT_WORKER_COUNT = 3 # 並列処理スレッド数 ## パフォーマンス特性 ### スループット + - 複数ワーカーによる並列処理 - ノンブロッキングI/O ### レイテンシ + - キューイング遅延の最小化 - 排他制御による一時的な遅延あり ### メモリ使用量 + - リクエストキューのサイズ制限なし(要注意) - スレッドプールによる固定オーバーヘッド @@ -272,4 +343,4 @@ DEFAULT_WORKER_COUNT = 3 # 並列処理スレッド数 - 標準入力をブロッキングで読み取るため、パイプ経由での使用を想定 - エンドポイント名の大文字小文字は区別される - Base64データは自動的にデコードされる -- 長時間のブロッキング処理は他のリクエストに影響する可能性 \ No newline at end of file +- 長時間のブロッキング処理は他のリクエストに影響する可能性 diff --git a/src-python/docs/details/model.md b/src-python/docs/details/model.md index 9880730c..9a7da932 100644 --- a/src-python/docs/details/model.md +++ b/src-python/docs/details/model.md @@ -4,40 +4,95 @@ VRCTアプリケーションの中核となるModelクラスを定義するモジュールです。音声認識、翻訳、VRオーバーレイ、OSC通信、WebSocketサーバーなどの主要機能を統合管理し、システム全体の動作を制御します。 +## 最近の更新 (2025-10-20) + +### VRAMエラー検出とフォールバック + +- `detectVRAMError()` を追加し CUDA メモリ関連メッセージ/独自例外 `VRAM_OUT_OF_MEMORY` を判別 +- 翻訳/音声認識実行中に VRAM エラー検出時、Controller 側で翻訳機能を無効化し CTranslate2 へフォールバックする運用を支援 +- エラー詳細文字列を UI へ通知するためのメッセージ抽出を標準化 + +### CTranslate2 言語マッピングネスト対応 + +- `getListLanguageAndCountry()` / `findTranslationEngines()` が `translation_lang['CTranslate2'][CTRANSLATE2_WEIGHT_TYPE]['source']` を参照するネスト構造へ更新 +- ウェイト種別切替時に対応言語集合が動的に変化しエンジン再判定をトリガー + +### ローカル LLM 翻訳エンジン統合 + +- LMStudio / Ollama 用クライアント初期化・モデルリスト取得メソッド追加: `authenticationTranslatorLMStudio()`, `getTranslatorLMStudioModelList()`, `setTranslatorLMStudioModel()`, `updateTranslatorLMStudioClient()` など +- Ollama も同様のインターフェースで統一 (`getTranslatorOllamaModelList`, `setTranslatorOllamaModel`, `updateTranslatorOllamaClient`) +- Plamo / Gemini / OpenAI と同一フォーマットでモデル選択ロジックを実装し Controller からの呼び出しを簡素化 + +### トークナイザ・リソース取得安定化 + +- CTranslate2 トークナイザダウンロード処理を `downloadCTranslate2ModelTokenizer()` で明示化し PyInstaller パス周りの不整合回避 +- フォントパス探索は OverlayImage 側へ委譲 (`OverlayImage(config.PATH_LOCAL)`) し Model は生成と更新呼び出しのみ保持 + +### 翻訳失敗時のフェールセーフ再試行 + +- `getTranslate()` 内で翻訳失敗(非文字列)時に CTranslate2 をリトライループして安定した結果を返却 +- 成功判定フラグを返却し上位層でエンジン制限エラー検出/フォールバックを容易化 + +### キーワードフィルタ再初期化改善 + +- `resetKeywordProcessor()` でインスタンス再生成し `addKeywords()` により設定変更後のフィルタ更新即時反映 + +### WebSocket サーバー管理強化 + +- 非同期サーバー起動を `asyncio.run` ラッパースレッドで安定化 +- ループフラグ `websocket_server_loop` と状態フラグ `websocket_server_alive` を追加し安全な停止処理と存活確認を標準化 + +### 影響 + +| 項目 | 内容 | +|------|------| +| 安定性 | VRAM 検出とフェールセーフ再試行で異常終了回避 | +| 拡張性 | ローカル LLM 統合によりネットワーク不要環境対応 | +| 柔軟性 | CTranslate2 ウェイト種別に応じた言語集合動的切替 | +| 保守性 | トークナイザ/フォント取得責務分離で可読性向上 | +| 観測性 | エラー詳細標準化により UI/ログでの診断容易 | + ## 主要機能 ### シングルトンパターン + - アプリケーション全体で単一のModelインスタンスを保証 - 遅延初期化による軽量なインポート ### 音声認識機能 + - マイク音声のリアルタイム文字起こし - スピーカー出力の音声認識 - エネルギーレベル監視 - 複数言語対応 ### 翻訳機能 + - 複数の翻訳エンジン対応(DeepL、Google、CTranslate2等) - 言語自動検出 - バッチ翻訳処理 ### VRオーバーレイ + - OpenVR統合 - 小型・大型ログオーバーレイ - 動的配置・透明度制御 ### OSC通信 + - VRChatとのOSC通信 - タイピング状態の同期 - ミュート状態の監視 ### WebSocketサーバー + - 外部アプリケーションとの通信 - リアルタイムメッセージ配信 ## クラス構造 ### threadFnc クラス + ```python class threadFnc(Thread): def __init__(self, fnc, end_fnc=None, daemon: bool = True, *args, **kwargs) @@ -48,6 +103,7 @@ class threadFnc(Thread): - エラー保護機能 ### Model クラス + ```python class Model: def __new__(cls) # シングルトンパターン @@ -62,56 +118,65 @@ class Model: ```python init() -> None ``` + - 全コンポーネントの初期化 - 重い処理のため明示的に呼び出し ```python ensure_initialized() -> None ``` + - 必要時の自動初期化 - 安全な遅延初期化 -### 翻訳機能 +### 翻訳機能メソッド ```python getInputTranslate(message, source_language=None) -> Tuple[List[str], List[bool]] ``` + - 入力メッセージの多言語翻訳 - 成功フラグも同時に返却 ```python getOutputTranslate(message, source_language=None) -> Tuple[List[str], List[bool]] ``` + - 出力メッセージの翻訳(逆方向) ```python authenticationTranslatorDeepLAuthKey(auth_key) -> bool ``` + - DeepL APIキーの認証 -### 音声認識機能 +### 音声認識機能メソッド ```python startMicTranscript(fnc: Callable) -> None ``` + - マイク音声認識の開始 - コールバック関数で結果を通知 ```python startSpeakerTranscript(fnc: Callable) -> None ``` + - スピーカー音声認識の開始 ```python pauseMicTranscript() -> None resumeMicTranscript() -> None ``` + - 音声認識の一時停止・再開 ```python startCheckMicEnergy(fnc: Callable) -> None startCheckSpeakerEnergy(fnc: Callable) -> None ``` + - 音声エネルギーレベルの監視 ### VRオーバーレイ機能 @@ -119,17 +184,20 @@ startCheckSpeakerEnergy(fnc: Callable) -> None ```python createOverlayImageSmallLog(message, your_language, translation, target_language) -> Image ``` + - 小型ログオーバーレイ画像の生成 ```python createOverlayImageLargeLog(message_type, message, your_language, translation, target_language) -> Image ``` + - 大型ログオーバーレイ画像の生成 ```python updateOverlaySmallLogSettings() -> None updateOverlayLargeLogSettings() -> None ``` + - オーバーレイ設定の更新 ### OSC通信機能 @@ -137,17 +205,20 @@ updateOverlayLargeLogSettings() -> None ```python oscSendMessage(message: str) -> None ``` + - VRChatへのメッセージ送信 ```python oscStartSendTyping() -> None oscStopSendTyping() -> None ``` + - タイピング状態の通知 ```python setMuteSelfStatus() -> None ``` + - VRChatミュート状態の取得 ### WebSocket機能 @@ -155,16 +226,19 @@ setMuteSelfStatus() -> None ```python startWebSocketServer(host: str, port: int) -> None ``` + - WebSocketサーバーの起動 ```python websocketSendMessage(message_dict: dict) -> bool ``` + - 全クライアントへのメッセージ送信 ```python checkWebSocketServerAlive() -> bool ``` + - サーバー稼働状態の確認 ### ファイルダウンロード機能 @@ -172,11 +246,13 @@ checkWebSocketServerAlive() -> bool ```python downloadCTranslate2ModelWeight(weight_type, callback=None, end_callback=None) ``` + - 翻訳モデルのダウンロード ```python downloadWhisperModelWeight(weight_type, callback=None, end_callback=None) ``` + - 音声認識モデルのダウンロード ### ウォッチドッグ機能 @@ -186,6 +262,7 @@ startWatchdog() -> None feedWatchdog() -> None setWatchdogCallback(callback: Callable) -> None ``` + - システム監視とタイムアウト処理 ## 使用方法 @@ -241,21 +318,25 @@ success = model.websocketSendMessage(message) ## 依存関係 ### 必須モジュール + - `controller`: アプリケーション制御 - `config`: 設定管理 - `device_manager`: デバイス管理 ### 音声・翻訳関連 + - `models.transcription.*`: 音声認識 - `models.translation.*`: 翻訳機能 - `models.transliteration.*`: 音写変換 ### VR・通信関連 + - `models.overlay.*`: VRオーバーレイ - `models.osc.*`: OSC通信 - `models.websocket.*`: WebSocket通信 ### ユーティリティ + - `models.watchdog.*`: 監視機能 - `utils`: 共通ユーティリティ - `flashtext`: キーワードフィルタリング @@ -289,4 +370,4 @@ success = model.websocketSendMessage(message) - 遅延初期化によるメモリ使用量の最適化 - スレッドプールによる並行処理 - モデルの重複読み込み防止 -- キューイングによる非同期処理 \ No newline at end of file +- キューイングによる非同期処理 diff --git a/src-python/docs/details/overlay.md b/src-python/docs/details/overlay.md index e28382a0..51970cee 100644 --- a/src-python/docs/details/overlay.md +++ b/src-python/docs/details/overlay.md @@ -745,10 +745,31 @@ platform_limitations = { - `model.py`: オーバーレイ機能統合 - `utils.py`: エラーログ・ユーティリティ +## 最近の更新 (2025-10-20) + +### フォント探索仕様の強化 + +`overlay_image.py` に PyInstaller ビルド後の `_internal/fonts/` ディレクトリ検出ロジックを追加。以下の優先順位でフォントディレクトリを探索: + +1. `root_path/_internal/fonts/` (PyInstallerバンドル環境) +2. `src-python/models/overlay/fonts/` (開発環境相対パス) +3. `models/overlay/fonts/` (直接実行時) + +見つからない場合は `FileNotFoundError` で早期通知。これにより配布バイナリと開発環境で同一コードパスを維持。 + +### 影響 + +| 項目 | 内容 | +|------|------| +| PyInstaller対応 | バンドル後のフォント読み込み失敗を防止 | +| 移植性 | 環境差異をコード内条件分岐で吸収 | +| エラー検知 | フォント未配置時の早期例外で不正描画防止 | + + ## 将来の改善点 - よりリッチなUI要素対応 - アニメーション・エフェクト機能 - カスタムフォント・テーマシステム - パフォーマンス監視・自動最適化 -- 他のVRプラットフォーム対応検討 \ No newline at end of file +- 他のVRプラットフォーム対応検討 diff --git a/src-python/docs/details/translation_gemini.md b/src-python/docs/details/translation_gemini.md new file mode 100644 index 00000000..29ef16c5 --- /dev/null +++ b/src-python/docs/details/translation_gemini.md @@ -0,0 +1,87 @@ +# translation_gemini.py - Gemini 翻訳クライアント + +## 概要 + +Google Gemini / Gemma 系モデルを翻訳用途で利用するためのクライアントラッパー。モデル一覧取得・認証・モデル選択・翻訳実行を統一インターフェースで提供する。 + +## 最近の更新 (2025-10-20) + +- 新規追加: Gemini クライアント統合 +- 除外キーワード (`audio`, `image`, `veo`, `tts`, `robotics`, `computer-use`) により非テキスト指向モデルをフィルタ +- `generateContent` をサポートするモデルのみ採用 +- YAML (`prompt/translation_gemini.yml`) からシステムプロンプト (`system_prompt`) をロード + +### 影響 + +| 項目 | 内容 | +|------|------| +| 正確性 | 非テキスト特化モデル除外で翻訳品質安定 | +| 保守性 | 明示的フィルタリングロジックで再利用容易 | +| 一貫性 | 他 LLM クライアントとの API 形状統一 | + +## 責務 + +- API Key 認証確認 +- Gemini/Gemma 系モデル列挙とフィルタリング +- モデル選択検証と内部保持 +- LangChain `ChatGoogleGenerativeAI` インスタンス生成 +- システムプロンプトによる翻訳実行 + +## 公開API (メソッド) + +```python +class GeminiClient: + def __init__(root_path: str = None) + def getModelList() -> list[str] + def getAuthKey() -> str | None + def setAuthKey(api_key: str) -> bool + def getModel() -> str | None + def setModel(model: str) -> bool + def updateClient() -> None + def translate(text: str, input_lang: str, output_lang: str) -> str +``` + +### メソッド詳細 + +- `setAuthKey`: `_authentication_check` 成功時のみ内部保存 +- `getModelList`: フィルタリング適用後ソート +- `setModel`: 取得済みモデル一覧内のみ受理 +- `updateClient`: `ChatGoogleGenerativeAI` を再構築 +- `translate`: システム + ユーザメッセージ構築→呼び出し→レスポンス正規化 + +## 使用例 + +```python +client = GeminiClient() +if client.setAuthKey("GEMINI_API_KEY"): + models = client.getModelList() + if models: + client.setModel(models[0]) + client.updateClient() + result = client.translate("こんにちは世界", "Japanese", "English") + print(result) +``` + +## 依存関係 + +- `google.genai`: モデル列挙 / 認証 +- `langchain_google_genai.ChatGoogleGenerativeAI`: LangChain ラッパー +- `translation_languages.translation_lang`: 対応言語集合 +- `translation_utils.loadPromptConfig`: プロンプト YAML ロード + +## 注意事項 + +- 非テキスト向けモデル (画像/音声/ロボティクス等) は除外 +- ストリーミング無効 (streaming=False) +- API Key 必須 (未設定時 getModelList 不可) + +## 制限事項 + +- 詳細エラーを包括的に扱わない (上位層でロギング/フォールバック) +- 複雑レスポンス構造は単純文字列へ normalize のみ + +## 関連ドキュメント + +- `details/translation_translator.md` +- `details/translation_languages.md` + diff --git a/src-python/docs/details/translation_languages.md b/src-python/docs/details/translation_languages.md index 9943e3e6..64d5f8d3 100644 --- a/src-python/docs/details/translation_languages.md +++ b/src-python/docs/details/translation_languages.md @@ -7,6 +7,7 @@ ## 主要機能 ### 多エンジン対応 + - DeepL(無料版・API版) - Google Translate - Microsoft Translator(Bing) @@ -14,6 +15,7 @@ - その他のWeb翻訳サービス ### 言語コード統合管理 + - 各エンジン固有の言語コード形式を統一 - 送信元(source)と送信先(target)言語の分離管理 - 地域固有言語バリエーションの対応 @@ -21,6 +23,7 @@ ## データ構造 ### translation_lang + ```python translation_lang: Dict[str, Dict[str, Dict[str, str]]] = { "エンジン名": { @@ -52,7 +55,7 @@ translation_lang["DeepL"] = { } ``` -### DeepL API(有料版) +### DeepL API(有料版 概要) ```python translation_lang["DeepL_API"] = { @@ -73,6 +76,7 @@ translation_lang["DeepL_API"] = { ## 主要対応言語 ### 西欧言語 + - **English**: 英語(米国・英国バリエーション) - **German**: ドイツ語 - **French**: フランス語 @@ -84,6 +88,7 @@ translation_lang["DeepL_API"] = { - **Norwegian**: ノルウェー語 ### 東欧・スラブ言語 + - **Russian**: ロシア語 - **Polish**: ポーランド語 - **Czech**: チェコ語 @@ -94,6 +99,7 @@ translation_lang["DeepL_API"] = { - **Slovenian**: スロベニア語 ### アジア言語 + - **Japanese**: 日本語 - **Korean**: 韓国語 - **Chinese Simplified**: 中国語(簡体字) @@ -101,6 +107,7 @@ translation_lang["DeepL_API"] = { - **Indonesian**: インドネシア語 ### その他の言語 + - **Arabic**: アラビア語 - **Turkish**: トルコ語 - **Finnish**: フィンランド語 @@ -218,21 +225,25 @@ en_code = manager.get_language_code("DeepL", "English", "target") ## エンジン別特徴 ### DeepL(無料版) + - **強み**: 高精度、自然な翻訳 - **制限**: 月間使用量制限、API制限 - **対応**: 26言語 -### DeepL API(有料版) +### DeepL API(有料版) + - **強み**: DeepLの高精度、地域別言語対応 - **制限**: 従量課金 - **対応**: 地域固有言語バリエーション ### Google Translate + - **強み**: 多言語対応、高速 - **制限**: API制限、精度のばらつき - **対応**: 100+言語 ### Microsoft Translator + - **強み**: リアルタイム翻訳、音声対応 - **制限**: APIキー必要 - **対応**: 70+言語 @@ -240,6 +251,7 @@ en_code = manager.get_language_code("DeepL", "English", "target") ## 地域バリエーション対応 ### 英語の地域別対応 + ```python # DeepL APIでの英語バリエーション "English American": "en-US", # アメリカ英語 @@ -247,6 +259,7 @@ en_code = manager.get_language_code("DeepL", "English", "target") ``` ### ポルトガル語の地域別対応 + ```python # ブラジル・ポルトガル語とヨーロッパ・ポルトガル語 "Portuguese Brazilian": "pt-BR", @@ -254,6 +267,7 @@ en_code = manager.get_language_code("DeepL", "English", "target") ``` ### 中国語の文字体系対応 + ```python # 簡体字・繁体字の区別 "Chinese Simplified": "zh", # 簡体字(中国本土) @@ -263,6 +277,7 @@ en_code = manager.get_language_code("DeepL", "English", "target") ## 拡張性 ### 新エンジンの追加 + ```python # 新しい翻訳エンジンの追加例 translation_lang["NewEngine"] = { @@ -280,6 +295,7 @@ translation_lang["NewEngine"] = { ``` ### 新言語の追加 + ```python # 既存エンジンへの新言語追加 translation_lang["DeepL"]["source"]["Hindi"] = "hi" @@ -289,6 +305,7 @@ translation_lang["DeepL"]["target"]["Hindi"] = "hi" ## エラーハンドリング ### 安全な言語コード取得 + ```python def safe_get_language_code(engine, language, direction="target", fallback="en"): """フォールバック機能付き言語コード取得""" @@ -303,6 +320,7 @@ def safe_get_language_code(engine, language, direction="target", fallback="en"): ``` ### 言語サポート検証 + ```python def validate_translation_pair(engine, source_lang, target_lang): """翻訳ペアの有効性検証""" @@ -339,4 +357,33 @@ def validate_translation_pair(engine, source_lang, target_lang): - `translation_utils.py`: 翻訳ユーティリティ - `transcription_languages.py`: 音声認識言語マッピング - `config.py`: 翻訳言語設定管理 -- `controller.py`: 言語選択UI制御 \ No newline at end of file +- `controller.py`: 言語選択UI制御 + +## 最近の更新 (2025-10-20) + +### CTranslate2 言語構造変更 + +従来: 重みタイプがトップレベルキー (`translation_lang["m2m100_418M-ct2-int8"]`). + +現在: `translation_lang["CTranslate2"][weight_type]["source"|"target"]` のネスト構造。`model.findTranslationEngines` / `translation_translator` で `engine == "CTranslate2"` の場合は `CTRANSLATE2_WEIGHT_TYPE` を用いて内部辞書へアクセス。 + +### 外部 YAML 言語マッピング導入 + +`models/translation/languages/languages.yml` を追加し、`config.init_config()` 内で `loadTranslationLanguages(path=config.PATH_LOCAL)` を呼び出し、既存 `translation_lang` にマージ/上書き。読込失敗時は空辞書を返しフォールバック。(PyYAML 追加) + +### LMStudio / Ollama 翻訳モデル対応準備 + +新規ローカル LLM 接続用として LMStudio / Ollama 追加。現段階ではモデルリスト・選択用のエンドポイントとプロパティ (`SELECTABLE_LMSTUDIO_MODEL_LIST`, `SELECTED_LMSTUDIO_MODEL`, `SELECTABLE_OLLAMA_MODEL_LIST`, `SELECTED_OLLAMA_MODEL`) を定義。言語マッピングは今後 YAML 拡張で統合予定(未実装部分は翻訳本体の `translate()` に未統合)。 + +### モデル選択プロパティ名称統一 + +Plamo / Gemini / OpenAI の選択モデルプロパティを `PLAMO_MODEL` / `GEMINI_MODEL` / `OPENAI_MODEL` から `SELECTED_PLAMO_MODEL` / `SELECTED_GEMINI_MODEL` / `SELECTED_OPENAI_MODEL` へ統一。保存キーも `SELECTED_*` に更新。 + +### 影響 + +| 項目 | 内容 | +|------|------| +| CTranslate2 | ネスト化により言語参照コード修正が必要 | +| YAML | 動的言語追加がコード編集無しに可能 | +| LLM接続 | 今後言語マッピングを YAML で拡張予定(未実装) | +| プロパティ | SELECTED_* へ統一で UI/設定整合性向上 | diff --git a/src-python/docs/details/translation_lmstudio.md b/src-python/docs/details/translation_lmstudio.md new file mode 100644 index 00000000..b54d46a8 --- /dev/null +++ b/src-python/docs/details/translation_lmstudio.md @@ -0,0 +1,86 @@ +# translation_lmstudio.py - LMStudio ローカル LLM 翻訳クライアント + +## 概要 + +LMStudio 互換 OpenAI API を利用したローカル LLM 翻訳クライアントラッパー。モデル一覧取得・モデル選択・翻訳処理を統一インターフェースで提供する。 + +## 最近の更新 (2025-10-20) + +- 新規追加: ローカル LLM (LMStudio) を翻訳エンジン群へ統合 +- `getModelList()` により現在起動中インスタンスから利用可能モデルを取得 +- `setModel()` 成功時に `updateClient()` を呼ぶことで LangChain `ChatOpenAI` を再構築 +- YAML (`prompt/translation_lmstudio.yml`) からシステムプロンプト (`system_prompt`) と対応言語をロード + +### 影響 + +| 項目 | 内容 | +|------|------| +| 拡張性 | ネットワーク不要のローカル推論を利用可能 | +| 一貫性 | 他 API クライアント (OpenAI/Plamo/Gemini/Ollama) と同一メソッド構成 | +| 保守性 | 翻訳ロジックを共通フォーマットへ集約 | + +## 責務 + +- LMStudio エンドポイントへの疎通確認 (認証代替) +- 利用可能モデル一覧の収集とソート +- 選択モデルの検証と内部保持 +- LangChain ラッパーインスタンス生成 +- システムプロンプトによる指示付き翻訳実行 + +## 公開API (メソッド) + +```python +class LMStudioClient: + def __init__(base_url: str | None = None, root_path: str = None) + def getBaseURL() -> str | None + def setBaseURL(base_url: str | None) -> bool + def getModelList() -> list[str] + def getModel() -> str | None + def setModel(model: str) -> bool + def updateClient() -> None + def translate(text: str, input_lang: str, output_lang: str) -> str +``` + +### メソッド詳細 + +- `setBaseURL`: 疎通確認 (_authentication_check) に成功した場合のみ内部更新 +- `getModelList`: `OpenAI` クライアントで `/models` を列挙し id を抽出 +- `setModel`: `getModelList` 内のモデル名のみ受理 +- `updateClient`: `ChatOpenAI` インスタンスを最新モデルで再生成 +- `translate`: システム / ユーザメッセージで LLM へ問い合わせし文字列レスポンスを正規化 + +## 使用例 + +```python +client = LMStudioClient(base_url="http://localhost:1234/v1") +models = client.getModelList() +if models: + client.setModel(models[0]) + client.updateClient() + translated = client.translate("こんにちは世界", "Japanese", "English") + print(translated) +``` + +## 依存関係 + +- `openai.OpenAI`: LMStudio OpenAI 互換 API 呼び出し +- `langchain_openai.ChatOpenAI`: LangChain 抽象化 +- `translation_languages.translation_lang`: 対応言語集合 +- `translation_utils.loadPromptConfig`: プロンプト YAML ロード + +## 注意事項 + +- `api_key` は固定文字列 "lmstudio" (LMStudio 側で不要のため) を利用 +- モデル一覧取得はエンドポイントの互換性に依存 (古いバージョン非対応の可能性) +- `updateClient()` 呼び出し前は `translate()` を利用できない + +## 制限事項 + +- ストリーミング未対応 (streaming=False) +- エラーハンドリングは包括的ではなく詳細原因は上位層で処理必要 + +## 関連ドキュメント + +- `details/translation_translator.md` +- `details/translation_languages.md` + diff --git a/src-python/docs/details/translation_ollama.md b/src-python/docs/details/translation_ollama.md new file mode 100644 index 00000000..d176644e --- /dev/null +++ b/src-python/docs/details/translation_ollama.md @@ -0,0 +1,86 @@ +# translation_ollama.py - Ollama ローカル LLM 翻訳クライアント + +## 概要 + +Ollama サーバー上で稼働するローカル LLM を翻訳エンジンとして扱うためのクライアントラッパー。モデル一覧取得・モデル選択・翻訳実行を統一パターンで提供する。 + +## 最近の更新 (2025-10-20) + +- 新規追加: Ollama を翻訳エンジン群へ統合 +- `/api/ping` を用いた疎通確認による簡易認証 +- `/api/tags` から利用可能モデル一覧抽出・ソート +- YAML (`prompt/translation_ollama.yml`) からシステムプロンプト (`system_prompt`) と対応言語をロード + +### 影響 + +| 項目 | 内容 | +|------|------| +| 拡張性 | LAN 内ローカル推論を利用可能 | +| 可搬性 | GPU/CPU 任意構成の Ollama 環境に適応 | +| 一貫性 | 他翻訳クライアント (OpenAI/Gemini/Plamo/LMStudio) と統一 API | + +## 責務 + +- Ollama インスタンスへの接続確認 +- モデル一覧取得 (タグ列挙) とソート +- 選択モデルの検証と内部保持 +- LangChain `ChatOllama` インスタンス生成 +- システムプロンプトとユーザ入力を組み立てて翻訳実行 + +## 公開API (メソッド) + +```python +class OllamaClient: + def __init__(root_path: str = None) + def authenticationCheck() -> bool + def getModelList() -> list[str] + def getModel() -> str | None + def setModel(model: str) -> bool + def updateClient() -> None + def translate(text: str, input_lang: str, output_lang: str) -> str +``` + +### メソッド詳細 + +- `authenticationCheck`: `/api/ping` が 200 を返すかで利用可否判定 +- `getModelList`: 認証成功時のみ `/api/tags` 結果から name 抽出 +- `setModel`: 取得済みモデル一覧内に存在する場合のみ設定 +- `updateClient`: `ChatOllama` を最新モデルで再生成 +- `translate`: system / user メッセージを LLM へ送信し結合結果を正規化 + +## 使用例 + +```python +client = OllamaClient() +if client.authenticationCheck(): + models = client.getModelList() + if models: + client.setModel(models[0]) + client.updateClient() + translated = client.translate("こんにちは世界", "Japanese", "English") + print(translated) +``` + +## 依存関係 + +- `requests`: Ping/タグ API 呼び出し +- `langchain_ollama.ChatOllama`: LangChain LLM ラッパー +- `translation_languages.translation_lang`: 対応言語集合 +- `translation_utils.loadPromptConfig`: プロンプト YAML ロード + +## 注意事項 + +- サーバー既定 URL: `http://localhost:11434` +- モデル一覧取得は起動しているローカルサーバー状態に依存 +- `updateClient()` 呼び出し前は `translate()` を利用不可 + +## 制限事項 + +- ストリーミング未対応 (streaming=False) +- エラー詳細は包括的に扱わない (上位層でフォールバック) + +## 関連ドキュメント + +- `details/translation_translator.md` +- `details/translation_languages.md` + diff --git a/src-python/docs/details/translation_openai.md b/src-python/docs/details/translation_openai.md new file mode 100644 index 00000000..2b99f0c3 --- /dev/null +++ b/src-python/docs/details/translation_openai.md @@ -0,0 +1,85 @@ +# translation_openai.py - OpenAI 翻訳クライアント + +## 概要 + +OpenAI API (公式または互換エンドポイント) を用いた汎用 LLM 翻訳クライアントラッパー。モデル一覧取得・認証・モデル選択・翻訳実行を提供する。 + +## 最近の更新 (2025-10-20) + +- 除外キーワード (`whisper`, `embedding`, `image`, `tts`, `audio`, `search`, `transcribe`, `diarize`, `vision`) を用いて翻訳非適合モデルをフィルタ +- Fine-tune モデル (`ft:`) は root が `gpt-` で始まる場合採用 +- YAML (`prompt/translation_openai.yml`) からシステムプロンプト (`system_prompt`) をロードする構成へ統合 + +### 影響 + +| 項目 | 内容 | +|------|------| +| 正確性 | 不適合モデル除外で翻訳品質安定 | +| 保守性 | フィルタリングロジック明示化で再利用容易 | +| 一貫性 | 他翻訳クライアントと API 形状統一 | + +## 責務 + +- OpenAI API Key を用いた認証確認 +- 利用可能モデルのフィルタリングとソート +- 選択モデルの検証と内部保持 +- LangChain `ChatOpenAI` インスタンス生成 +- システムプロンプトによる翻訳実行 + +## 公開API (メソッド) + +```python +class OpenAIClient: + def __init__(base_url: str | None = None, root_path: str = None) + def getModelList() -> list[str] + def getAuthKey() -> str | None + def setAuthKey(api_key: str) -> bool + def getModel() -> str | None + def setModel(model: str) -> bool + def updateClient() -> None + def translate(text: str, input_lang: str, output_lang: str) -> str +``` + +### メソッド詳細 + +- `setAuthKey`: `_authentication_check` に成功した場合のみ内部保存 +- `getModelList`: モデル列挙後フィルタリング適用しソート +- `setModel`: 取得済みリスト内のモデルのみ受理 +- `updateClient`: `ChatOpenAI` を選択モデルで再生成 +- `translate`: システム + ユーザメッセージ構築→LLM呼び出し→レスポンス正規化 + +## 使用例 + +```python +client = OpenAIClient() +if client.setAuthKey("OPENAI_API_KEY"): + models = client.getModelList() + client.setModel(models[0]) + client.updateClient() + result = client.translate("こんにちは世界", "Japanese", "English") + print(result) +``` + +## 依存関係 + +- `openai.OpenAI`: モデル列挙 / 推論 +- `langchain_openai.ChatOpenAI`: LangChain ラッパー +- `translation_languages.translation_lang`: 対応言語集合 +- `translation_utils.loadPromptConfig`: プロンプト YAML ロード + +## 注意事項 + +- `base_url` が None の場合公式エンドポイント +- ストリーミング無効 (streaming=False) 固定 +- API Key 無設定時 `getModelList()` は空 + +## 制限事項 + +- エラーメッセージ詳細は包括的に扱わない (上位層でロギング) +- 翻訳結果の構造が複雑 (list/dict) 場合を単純文字列へ normalize するのみ + +## 関連ドキュメント + +- `details/translation_translator.md` +- `details/translation_languages.md` + diff --git a/src-python/docs/details/translation_plamo.md b/src-python/docs/details/translation_plamo.md new file mode 100644 index 00000000..9b6bd5e1 --- /dev/null +++ b/src-python/docs/details/translation_plamo.md @@ -0,0 +1,86 @@ +# translation_plamo.py - Plamo 翻訳クライアント + +## 概要 + +Preferred Networks 提供の Plamo API を利用した翻訳向け LLM クライアントラッパー。モデル一覧取得・認証・モデル選択・翻訳実行を統一インターフェースで提供する。 + +## 最近の更新 (2025-10-20) + +- 新規追加: Plamo クライアント統合 +- プロンプト設定を YAML (`prompt/translation_plamo.yml`) からロード(システムプロンプト `system_prompt`) +- モデル一覧取得後ソートして再現性を確保 + +### 影響 + +| 項目 | 内容 | +|------|------| +| 拡張性 | 日本発 API への対応により選択肢拡大 | +| 保守性 | 他 LLM クライアントと同一構造でメンテ容易 | +| 一貫性 | メソッド命名/責務の統一化 | + +## 責務 + +- API Key 認証確認 +- 利用可能モデルの列挙とソート +- モデル選択の検証 +- LangChain `ChatOpenAI` インスタンス生成 +- システムプロンプトによる翻訳実行 + +## 公開API (メソッド) + +```python +class PlamoClient: + def __init__(root_path: str = None) + def getModelList() -> list[str] + def getAuthKey() -> str | None + def setAuthKey(api_key: str) -> bool + def getModel() -> str | None + def setModel(model: str) -> bool + def updateClient() -> None + def translate(text: str, input_lang: str, output_lang: str) -> str +``` + +### メソッド詳細 + +- `setAuthKey`: `_authentication_check` 成功時のみ内部保存 +- `getModelList`: 認証済み状態でモデル列挙→ソート +- `setModel`: 列挙済みリスト内モデルのみ受理 +- `updateClient`: `ChatOpenAI` を再構築 +- `translate`: システム + ユーザメッセージで推論し応答正規化 + +## 使用例 + +```python +client = PlamoClient() +if client.setAuthKey("PLAMO_API_KEY"): + models = client.getModelList() + if models: + client.setModel(models[0]) + client.updateClient() + result = client.translate("こんにちは世界", "Japanese", "English") + print(result) +``` + +## 依存関係 + +- `openai.OpenAI`: Plamo 互換 API 呼び出し +- `langchain_openai.ChatOpenAI`: LangChain ラッパー +- `translation_languages.translation_lang`: 対応言語集合 +- `translation_utils.loadPromptConfig`: プロンプト YAML ロード + +## 注意事項 + +- BASE_URL 固定: `https://api.platform.preferredai.jp/v1` +- API Key 未設定時はモデル一覧取得不可 +- ストリーミング無効 (streaming=False) + +## 制限事項 + +- 詳細エラーは包括的に扱わず (上位層でログ/フォールバック) +- 翻訳結果の構造が複雑な場合単純文字列へ normalize のみ + +## 関連ドキュメント + +- `details/translation_translator.md` +- `details/translation_languages.md` + diff --git a/src-python/docs/details/translation_translator.md b/src-python/docs/details/translation_translator.md index 970385ae..fd423213 100644 --- a/src-python/docs/details/translation_translator.md +++ b/src-python/docs/details/translation_translator.md @@ -403,4 +403,50 @@ root/ - `translation_utils.py`: CTranslate2ユーティリティ - `config.py`: 翻訳設定管理 - `model.py`: 翻訳機能統合 -- `controller.py`: 翻訳制御インターフェース \ No newline at end of file +- `controller.py`: 翻訳制御インターフェース + +## 最近の更新 (2025-10-20) + +### 新規ローカル LLM エンジン追加 + +LMStudio / Ollama を翻訳エンジンとして追加。接続確認後にモデルリスト (`SELECTABLE_LMSTUDIO_MODEL_LIST` / `SELECTABLE_OLLAMA_MODEL_LIST`) を取得し、未選択なら先頭モデルを自動選択 (`SELECTED_LMSTUDIO_MODEL` / `SELECTED_OLLAMA_MODEL`)。現時点では CTranslate2 と同様にローカル動作を想定し、翻訳関数側は将来の統合(温度等パラメータ)に備えて抽象化維持。 + +### モデル選択プロパティ名称統一 + +Plamo / Gemini / OpenAI の選択モデルプロパティを `SELECTED_*` 形式へ変更。旧名称 (`PLAMO_MODEL` / `GEMINI_MODEL` / `OPENAI_MODEL`) は利用停止。自動認証後のモデルリスト更新ロジックで未選択時に先頭補完を行う。 + +### OpenAI / Gemini / Plamo 認証後のモデルリスト自動更新 + +Auth設定メソッド完了時に `SELECTABLE_*_MODEL_LIST` を再取得し不足時は UI へ push。OpenAI はキー設定直後に最新モデルリストを反映し高速化。Gemini / Plamo も同様に `updateTranslator*Client()` 呼び出しでクライアント再生成。 + +### CTranslate2 言語ネスト化対応 + +`translation_lang["CTranslate2"][weight_type]["source"|"target"]` へ構造変更。`CTRANSLATE2_WEIGHT_TYPE` により重みタイプ別の言語集合を参照。Translator 内では `translator_name == "CTranslate2"` の分岐で weight_type を参照して言語判定を行う実装に変更。 + +### YAML 言語マッピング導入 + +外部ファイル `languages.yml` を読み込んで翻訳エンジン別対応言語を動的拡張。新言語追加は YAML 編集のみで実現(コード再デプロイ不要)。読み込み失敗時は空辞書でフォールバックし既存ハードコードを保持。 + +### VRAM エラー検知とフォールバック + +DeepL / Plamo / Gemini / OpenAI 実行時の VRAM 不足検知で自動的に CTranslate2 へ切替し翻訳を停止 (`ENABLE_TRANSLATION=False`)。ユーザー通知後は再度有効化要求時に再初期化を試行。安定性向上のためログへ VRAM エラー詳細を記録。 + +### トークナイザーパス修正 + +CTranslate2 トークナイザーのダウンロード処理で保存ディレクトリ作成とパス使用順序不整合を修正。これにより初回起動時の失敗率低下。 + +### 全言語ペア包括テスト導入 + +`backend_test.py` にて `test_translate_all_language_pairs()` を追加。複数エンジン・全言語ペアを列挙実行し `translation_test_results.json` を生成。失敗ペアの早期検出と YAML 追加言語検証に活用。 + +### 影響 + +| 項目 | 内容 | +|------|------| +| ローカルLLM | オフライン翻訳候補拡充 (LMStudio/Ollama) | +| プロパティ統一 | SELECTED_* 命名で一貫性と保守性向上 | +| CTranslate2構造 | 重みタイプ毎に最適言語集合参照可能 | +| YAML外部化 | 言語追加/削除が設定ファイル編集のみで完結 | +| VRAM検知 | エラー時自動停止 + 軽量エンジン切替で安定性向上 | +| Tokenizer修正 | 初回セットアップ失敗減少 | +| 包括テスト | 言語組合せの網羅的品質担保 | diff --git a/src-python/docs/仕様書.md b/src-python/docs/仕様書.md index 1ccd8ea2..366e4afb 100644 --- a/src-python/docs/仕様書.md +++ b/src-python/docs/仕様書.md @@ -1,15 +1,18 @@ # 仕様書 概要 + - プロジェクト名: VRCT (VR Chat Translator) - 目的: マイク入力とスピーカー出力をリアルタイムに文字起こし・翻訳し、VR オーバーレイや OSC/WebSocket 経由で外部に送出するバックエンドロジック。 - 言語: Python 対象ユーザー + - VR 環境でリアルタイム翻訳・文字起こしを利用したいエンドユーザー - フロントエンド(GUI)や VR クライアント(OSC)と連携するアプリケーション開発者 主要機能(機能要件) + 1. 音声の取り込み・文字起こし - マイク(送信)およびスピーカー(受信)から音声を取得し、ローカル Whisper(faster-whisper)または外部サービスによりテキスト化する。 - 音声エネルギー(音量)監視を行い、閾値ベースで検出する。 @@ -36,23 +39,94 @@ - ウォッチドッグ機構で定期的に死活チェック・コールバック。 非機能要件 + - プラットフォーム: 主に Windows(Audio 周りは WASAPI を利用)を想定。クロスプラットフォームでの import 安全性を考慮。 - 可用性: 外部依存(PyAudio, CUDA, ctranslate2 等)が無い環境でも安全にインポートでき、機能劣化しつつ動作する。 - パフォーマンス: ローカルモデル利用時は GPU を利用して計算性能を確保。compute type 選択ロジックを実装。 - セキュリティ: 外部への API キー(DeepL など)は設定で扱い、コード上では平文保持を避ける(設定ファイルに保存)。 運用フロー + - 起動: stdin でコマンドを受け付ける mainloop を実行。必要な初期化は遅延実行(lazy init)を採用。 - モデル重ダウンロード: CTranslate2/Whisper 重みは `weights/` 配下にダウンロードし、チェックサム等で整合性確認。 - 障害時: 例外は utils.errorLogging() でトレースを error.log に出力。重要機能はフォールバック実装。 インターフェース(抜粋) -- stdin(JSON): {"endpoint": "/set/..." | "/get/..." | "/run/...", "data": } + +- stdin(JSON): {"endpoint": "/set/..." | "/get/..." | "/run/...", "data": } - stdout(JSON): 標準化されたレスポンスを printResponse/printLog が出力(status, endpoint, result など)。 依存関係(オプション含む) + - 必須(実装時想定): requests, packaging, flashtext, pillow, pyaudiowpatch, speech_recognition - ローカル推奨: faster-whisper, ctranslate2, torch(GPU 利用時) - Windows 固有(音声ループバック): pycaw, comtypes 参考: 実装上の安全設計として optional な import は try/except でガードしており、存在しない依存があっても import 時にクラッシュしない。 + +## 最近の更新 (2025-10-20 translate_api ブランチ) + +本章は既存仕様への差分のみを記載します。コードベースの事実に基づく更新点です。 + +### 翻訳エンジン / モデル管理の拡張 + +- OpenAI / Plamo / Gemini の選択モデルプロパティを `PLAMO_MODEL` / `GEMINI_MODEL` / `OPENAI_MODEL` から `SELECTED_PLAMO_MODEL` / `SELECTED_GEMINI_MODEL` / `SELECTED_OPENAI_MODEL` にリネーム (旧名称は保存対象から移行)。 +- 新規ローカル LLM 接続: LMStudio (`LMSTUDIO_URL`, `SELECTABLE_LMSTUDIO_MODEL_LIST`, `SELECTED_LMSTUDIO_MODEL`) を追加。 +- 新規ローカル LLM 接続: Ollama (`SELECTABLE_OLLAMA_MODEL_LIST`, `SELECTED_OLLAMA_MODEL`) を追加。 +- OpenAI 認証キー設定時にモデル一覧 (`SELECTABLE_OPENAI_MODEL_LIST`) を自動取得し、未選択時に第一候補へフォールバックする処理を追加。メソッド名を `OpenAi` → `OpenAI` に統一。 + +### エンドポイント追加 / 変更 + +`mainloop.py` の `mapping` / `run_mapping` に以下を追加: + +- `/get/data/lmstudio_model_list`, `/get/data/lmstudio_model`, `/set/data/lmstudio_model`, `/get/data/lmstudio_url`, `/set/data/lmstudio_url` +- `/get/data/ollama_connection`, `/get/data/ollama_model_list`, `/get/data/ollama_model`, `/set/data/ollama_model` +- OpenAI 系: `getOpenAIAuthKey`, `setOpenAIAuthKey`, `delOpenAIAuthKey`, `getOpenAIModelList`, `getOpenAIModel`, `setOpenAIModel` に名称統一。 + +### 翻訳言語定義の構造変更 + +- CTranslate2 の言語定義をトップレベル直接キー (例: `m2m100_418M-ct2-int8`) から `translation_lang['CTranslate2'][weight_type]` のネスト構造へ再編。利用側の互換ロジック (`model.findTranslationEngines`) は weight_type 経由で参照するよう修正。 +- 新規 YAML 言語マッピングファイル `models/translation/languages/languages.yml` を追加。`config.init_config()` 内で `loadTranslationLanguages()` を呼び出し統合 (失敗時は空辞書フォールバック)。 + +### プロンプトファイルの整理 + +- `translation_gemini.yml`, `translation_lmstudio.yml` から `supported_languages` ブロックを削除し、`system_prompt` 内に簡潔化。 + +### リソース / PyInstaller + +- PyInstaller spec (`backend.spec`, `backend_cuda.spec`) の `datas` に `./src-python/models/translation/prompt` および `./src-python/models/translation/languages` を追加。 +- フォント配置を `fonts/` 直下から `src-python/models/overlay/fonts/` へ移動し、`overlay_image.py` にビルド時 (`_internal/fonts`) と開発時の動的探索ロジックを追加。 + +### 依存パッケージの追加 + +- `requirements.txt` / `requirements_cuda.txt` に `PyYAML==6.0.2` (YAML読込), `google-genai==1.45.0`, `grpcio==1.67.1` を追加。 + +### 認証処理の微調整 + +- Plamo / Gemini 認証メソッドで `root_path=config.PATH_LOCAL` を渡すよう変更し、ローカル参照を統一。 +- OpenAI モデル設定メソッドの名称を `setTranslatorOpenAiModel` → `setTranslatorOpenAIModel` に変更。 + +### テスト拡張 + +- `backend_test.py` に全言語ペア翻訳網羅テスト `test_translate_all_language_pairs()` を追加。結果を `translation_test_results.json` として保存。 + +### 内部ユーティリティの修正 + +- `downloadCTranslate2Tokenizer()` が `tokenizer_path` を正しく作成し `transformers.AutoTokenizer.from_pretrained(tokenizer, cache_dir=tokenizer_path)` を使用するよう修正。 + +### 影響範囲まとめ + +| 区分 | 影響内容 | +|------|----------| +| 設定 | 新規プロパティ / 既存名称変更 (`SELECTED_*`, `LMSTUDIO_URL`) | +| エンドポイント | LMStudio / Ollama / OpenAI 名称統一追加 | +| 翻訳言語 | CTranslate2 ネスト構造 / YAML マッピング導入 | +| リソース | PyInstaller datas 追加 / フォントパス移行 | +| 依存 | PyYAML / google-genai / grpcio 追加 | +| 認証 | OpenAI/Plamo/Gemini 認証後モデルリスト更新 & root_path 引数追加 | +| テスト | 全言語ペア網羅テスト追加 | +| ユーティリティ | Tokenizer ダウンロード処理修正 | + +### ライセンス影響 + +追加された依存は既存 LICENSE の記載範囲に変更を強制するものではなく、ライセンス本文の更新不要 (現行 OSS ライセンス許容範囲内)。