WatNeru commited on
Commit
df1c720
·
1 Parent(s): dd1bc6c

Fix ZeroGPU support, improve model loading and error handling

Browse files
Files changed (1) hide show
  1. app.py +80 -27
app.py CHANGED
@@ -3,18 +3,9 @@
3
  FastAPI 版 LLMView Word Tree サーバー
4
  """
5
 
6
- # GPU要求(Hugging Face Space用)- インポート直後に実行
7
- try:
8
- import spaces
9
- spaces.GPU() # GPUを要求
10
- print("[SPACE] GPU要求を送信しました")
11
- except ImportError:
12
- print("[SPACE] spacesパッケージが見つかりません(ローカル環境の可能性)")
13
- except Exception as e:
14
- print(f"[SPACE] GPU要求エラー: {e}")
15
-
16
  import os
17
  import threading
 
18
  from pathlib import Path
19
  from typing import List, Dict, Any, Optional
20
 
@@ -22,6 +13,20 @@ from fastapi import FastAPI, HTTPException
22
  from huggingface_hub import snapshot_download
23
  from pydantic import BaseModel, Field
24
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
  try:
26
  from package.path_manager import get_path_manager
27
  except ImportError:
@@ -68,46 +73,93 @@ def _set_status(message: str) -> None:
68
 
69
  def ensure_model_available() -> str:
70
  """モデルファイルをローカルに用意(なければHFから取得)"""
 
71
  current_path = Path(path_manager.get_model_path())
 
 
72
  if current_path.exists():
 
73
  return str(current_path)
74
 
 
75
  HF_LOCAL_DIR.mkdir(parents=True, exist_ok=True)
 
76
  _set_status("Hugging Face からモデルをダウンロード中...")
77
 
78
- snapshot_download(
79
- repo_id=HF_MODEL_REPO,
80
- allow_patterns=HF_MODEL_FILENAME,
81
- local_dir=str(HF_LOCAL_DIR),
82
- local_dir_use_symlinks=False,
83
- token=HF_TOKEN,
84
- )
85
- downloaded = HF_LOCAL_DIR / HF_MODEL_FILENAME
86
- if not downloaded.exists():
87
- raise FileNotFoundError(
88
- f"モデル {HF_MODEL_FILENAME} が {downloaded} に見つかりません"
89
  )
90
-
91
- os.environ["LLM_MODEL_PATH"] = str(downloaded)
92
- path_manager.model_path = str(downloaded)
93
- return str(downloaded)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
 
95
 
96
  def initialize_model() -> None:
97
  """RustAdapter とモデルを初期化"""
98
  global adapter
99
  try:
 
100
  _set_status("モデルを読み込み中です...")
101
  from package.rust_adapter import RustAdapter
102
 
 
103
  model_path = ensure_model_available()
 
 
 
104
  adapter = RustAdapter.get_instance(model_path)
 
 
105
  _set_status("モデル準備完了")
 
106
  except Exception as exc: # pragma: no cover
107
- _set_status(f"モデル初期化に失敗しました: {exc}")
 
 
108
  import traceback
109
-
110
  traceback.print_exc()
 
 
111
 
112
 
113
  # Space 起動時にバックグラウンドで初期化
@@ -144,6 +196,7 @@ def health() -> Dict[str, Any]:
144
 
145
 
146
  @app.post("/build_word_tree", response_model=List[WordTreeResponse])
 
147
  def build_word_tree(payload: WordTreeRequest) -> List[WordTreeResponse]:
148
  """単語ツリーを構築"""
149
  if not payload.prompt_text.strip():
 
3
  FastAPI 版 LLMView Word Tree サーバー
4
  """
5
 
 
 
 
 
 
 
 
 
 
 
6
  import os
7
  import threading
8
+ import sys
9
  from pathlib import Path
10
  from typing import List, Dict, Any, Optional
11
 
 
13
  from huggingface_hub import snapshot_download
14
  from pydantic import BaseModel, Field
15
 
16
+ # ZeroGPU対応: spacesパッケージをインポート(デコレータ用)
17
+ try:
18
+ import spaces
19
+ SPACES_AVAILABLE = True
20
+ print("[SPACE] spacesパッケージをインポートしました")
21
+ except ImportError:
22
+ SPACES_AVAILABLE = False
23
+ print("[SPACE] spacesパッケージが見つかりません(ローカル環境の可能性)")
24
+ # ダミーデコレータを定義
25
+ class DummyGPU:
26
+ def __call__(self, func):
27
+ return func
28
+ spaces = type('spaces', (), {'GPU': DummyGPU()})()
29
+
30
  try:
31
  from package.path_manager import get_path_manager
32
  except ImportError:
 
73
 
74
  def ensure_model_available() -> str:
75
  """モデルファイルをローカルに用意(なければHFから取得)"""
76
+ print(f"[MODEL] ensure_model_available() 開始")
77
  current_path = Path(path_manager.get_model_path())
78
+ print(f"[MODEL] 現在のモデルパス: {current_path}")
79
+
80
  if current_path.exists():
81
+ print(f"[MODEL] 既存のモデルファイルを使用: {current_path}")
82
  return str(current_path)
83
 
84
+ print(f"[MODEL] モデルファイルが見つからないため、ダウンロードを開始")
85
  HF_LOCAL_DIR.mkdir(parents=True, exist_ok=True)
86
+ print(f"[MODEL] ダウンロード先ディレクトリ: {HF_LOCAL_DIR}")
87
  _set_status("Hugging Face からモデルをダウンロード中...")
88
 
89
+ # snapshot_downloadの戻り値(ダウンロード先ディレクトリ)を使用
90
+ try:
91
+ downloaded_dir = snapshot_download(
92
+ repo_id=HF_MODEL_REPO,
93
+ allow_patterns=HF_MODEL_FILENAME,
94
+ local_dir=str(HF_LOCAL_DIR),
95
+ local_dir_use_symlinks=False,
96
+ token=HF_TOKEN,
 
 
 
97
  )
98
+ print(f"[MODEL] snapshot_download完了: {downloaded_dir}")
99
+ except Exception as e:
100
+ print(f"[MODEL] snapshot_downloadエラー: {e}")
101
+ import traceback
102
+ traceback.print_exc()
103
+ raise
104
+
105
+ # ダウンロードされたディレクトリからファイルを検索
106
+ downloaded_dir_path = Path(downloaded_dir)
107
+ print(f"[MODEL] ダウンロード先パス: {downloaded_dir_path}")
108
+
109
+ # まず直接パスを試す
110
+ downloaded = downloaded_dir_path / HF_MODEL_FILENAME
111
+ print(f"[MODEL] 直接パスを確認: {downloaded}")
112
+
113
+ if not downloaded.exists():
114
+ # リポジトリ構造を保持している可能性があるので、再帰的に検索
115
+ print(f"[MODEL] 直接パスに存在しないため、再帰的に検索中...")
116
+ found_files = list(downloaded_dir_path.rglob(HF_MODEL_FILENAME))
117
+ print(f"[MODEL] 見つかったファイル数: {len(found_files)}")
118
+ if found_files:
119
+ downloaded = found_files[0]
120
+ print(f"[MODEL] ファイルを発見: {downloaded}")
121
+ else:
122
+ # ディレクトリ内の全ファイルをリストアップしてデバッグ情報を出力
123
+ all_files = list(downloaded_dir_path.rglob("*"))
124
+ print(f"[MODEL] ディレクトリ内の全ファイル: {[str(f) for f in all_files[:20]]}")
125
+ raise FileNotFoundError(
126
+ f"モデル {HF_MODEL_FILENAME} が {downloaded_dir} に見つかりません。"
127
+ f"見つかったファイル: {[str(f) for f in all_files[:10]]}"
128
+ )
129
+
130
+ model_path_str = str(downloaded.resolve())
131
+ print(f"[MODEL] モデルパスを設定: {model_path_str}")
132
+ os.environ["LLM_MODEL_PATH"] = model_path_str
133
+ path_manager.model_path = model_path_str
134
+ return model_path_str
135
 
136
 
137
  def initialize_model() -> None:
138
  """RustAdapter とモデルを初期化"""
139
  global adapter
140
  try:
141
+ print("[INIT] モデル初期化スレッド開��")
142
  _set_status("モデルを読み込み中です...")
143
  from package.rust_adapter import RustAdapter
144
 
145
+ print("[INIT] ensure_model_available() を呼び出し")
146
  model_path = ensure_model_available()
147
+ print(f"[INIT] モデルパス取得: {model_path}")
148
+
149
+ print("[INIT] RustAdapter.get_instance() を呼び出し")
150
  adapter = RustAdapter.get_instance(model_path)
151
+ print("[INIT] RustAdapter初期化完了")
152
+
153
  _set_status("モデル準備完了")
154
+ print("[INIT] モデル初期化完了")
155
  except Exception as exc: # pragma: no cover
156
+ error_msg = f"モデル初期化に失敗しました: {exc}"
157
+ print(f"[INIT] エラー: {error_msg}")
158
+ _set_status(error_msg)
159
  import traceback
 
160
  traceback.print_exc()
161
+ # プロセスを終了させないように、エラーをログに記録するだけ
162
+ sys.stderr.write(f"[INIT] モデル初期化エラー(プロセスは継続): {exc}\n")
163
 
164
 
165
  # Space 起動時にバックグラウンドで初期化
 
196
 
197
 
198
  @app.post("/build_word_tree", response_model=List[WordTreeResponse])
199
+ @spaces.GPU # ZeroGPU対応: このエンドポイントでGPUを要求
200
  def build_word_tree(payload: WordTreeRequest) -> List[WordTreeResponse]:
201
  """単語ツリーを構築"""
202
  if not payload.prompt_text.strip():