File size: 5,689 Bytes
09c17cd | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 | #!/usr/bin/env python3
"""
パス管理モジュール
PyInstaller対応とサーバー起動の両方に対応
"""
import os
import sys
from pathlib import Path
from typing import Optional
class PathManager:
"""パス管理クラス(シングルトン)"""
_instance: Optional["PathManager"] = None
def __new__(cls):
if cls._instance is None:
cls._instance = super().__new__(cls)
cls._instance._initialized = False
return cls._instance
def __init__(self):
if self._initialized:
return
self._initialized = True
self._setup_paths()
def _setup_paths(self):
"""パス設定を初期化"""
# 実行環境の判定
if getattr(sys, 'frozen', False):
# PyInstallerでビルドされた場合
self.is_pyinstaller = True
self.base_path = Path(sys._MEIPASS)
self.package_path = self.base_path / 'package'
self.python_executable = sys.executable
else:
# 開発環境の場合
self.is_pyinstaller = False
self.base_path = Path(__file__).parent.parent
self.package_path = self.base_path / 'package'
self.python_executable = sys.executable
# モデルパス設定
self.model_path = self._get_model_path()
# ログ出力
print(f"[PATH] PyInstaller: {self.is_pyinstaller}")
print(f"[PATH] Base path: {self.base_path}")
print(f"[PATH] Package path: {self.package_path}")
print(f"[PATH] Model path: {self.model_path}")
def _get_model_path(self) -> str:
"""モデルファイルのパスを取得"""
# 環境変数から取得
env_model_path = os.getenv('LLM_MODEL_PATH')
if env_model_path and os.path.exists(env_model_path):
return env_model_path
# 配布物からの相対位置(優先)
try:
# 実行ファイルのあるディレクトリ(PyInstaller実行時は dist/.../tauri_python_server の場所)
executable_dir = Path(os.path.dirname(sys.executable)) if getattr(sys, 'frozen', False) else Path(__file__).parent.parent
candidate_relative_paths = [
# 配布レイアウト: <root>/models/<file> (exe が <root>/python/ にある想定)
(executable_dir.parent / 'models' / 'llama-3.2-3b-instruct-q4_k_m.gguf'),
# exe と同階層に models/
(executable_dir / 'models' / 'llama-3.2-3b-instruct-q4_k_m.gguf'),
# MEIPASS(展開一時ディレクトリ)配下
(Path(getattr(sys, '_MEIPASS', str(self.base_path))) / 'models' / 'llama-3.2-3b-instruct-q4_k_m.gguf'),
]
for rel in candidate_relative_paths:
rel_str = str(rel)
if os.path.exists(rel_str):
return rel_str
except Exception:
pass
# デフォルトパス
default_paths = [
os.path.expanduser("~/Documents/GitHub/LLMV_app_frontend/src-tauri/python/models/llama-3.2-3b-instruct-q4_k_m.gguf"),
os.path.expanduser("~/Documents/models/llama-3.2-3b-instruct-q4_k_m.gguf"),
os.path.expanduser("~/models/llama-3.2-3b-instruct-q4_k_m.gguf"),
"/opt/models/llama-3.2-3b-instruct-q4_k_m.gguf"
]
for path in default_paths:
if os.path.exists(path):
return path
# 見つからない場合は最初のデフォルトパスを返す
return default_paths[0]
def get_package_path(self) -> str:
"""パッケージパスを取得"""
return str(self.package_path)
def get_model_path(self) -> str:
"""モデルパスを取得"""
return self.model_path
def get_python_executable(self) -> str:
"""Python実行ファイルのパスを取得"""
return self.python_executable
def setup_sys_path(self):
"""sys.pathを設定"""
package_path_str = self.get_package_path()
# パッケージパスを追加
if package_path_str not in sys.path:
sys.path.insert(0, package_path_str)
# conda環境のパッケージパスも追加(開発環境のみ)
if not self.is_pyinstaller:
conda_package_path = '/Users/wataru/Documents/AppProject/LLMView_Server/package'
if os.path.exists(conda_package_path) and conda_package_path not in sys.path:
sys.path.insert(0, conda_package_path)
print(f"[PATH] sys.path configured: {len(sys.path)} paths")
def get_server_config(self) -> dict:
"""サーバー設定を取得"""
return {
'host': '127.0.0.1',
'port': 5000,
'debug': False,
'use_reloader': False,
'threaded': True
}
def get_pyinstaller_spec_path(self) -> str:
"""PyInstaller specファイルのパスを取得"""
return str(self.base_path / 'tauri_python_server.spec')
def get_dist_path(self) -> str:
"""ビルド出力ディレクトリのパスを取得"""
return str(self.base_path / 'dist')
def get_executable_name(self) -> str:
"""実行ファイル名を取得"""
return 'tauri_python_server'
# グローバルインスタンス
path_manager = PathManager()
def get_path_manager() -> PathManager:
"""PathManagerインスタンスを取得"""
return path_manager
|