Remove local model and add auto-download
Browse files- .gitignore +5 -0
- app.py +43 -1
- package/__pycache__/ai.cpython-310.pyc +0 -0
- package/__pycache__/config.cpython-310.pyc +0 -0
- package/__pycache__/path_manager.cpython-310.pyc +0 -0
- package/__pycache__/rust_adapter.cpython-310.pyc +0 -0
- package/__pycache__/word_counter.cpython-310.pyc +0 -0
- package/__pycache__/word_processor.cpython-310.pyc +0 -0
- requirements.txt +3 -0
.gitignore
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# モデルキャッシュ
|
| 2 |
+
model/
|
| 3 |
+
model_cache/
|
| 4 |
+
|
| 5 |
+
|
app.py
CHANGED
|
@@ -3,10 +3,13 @@
|
|
| 3 |
FastAPI 版 LLMView Word Tree サーバー
|
| 4 |
"""
|
| 5 |
|
|
|
|
| 6 |
import threading
|
|
|
|
| 7 |
from typing import List, Dict, Any, Optional
|
| 8 |
|
| 9 |
from fastapi import FastAPI, HTTPException
|
|
|
|
| 10 |
from pydantic import BaseModel, Field
|
| 11 |
|
| 12 |
try:
|
|
@@ -22,6 +25,18 @@ adapter = None
|
|
| 22 |
status_message = "モデル初期化中..."
|
| 23 |
status_lock = threading.Lock()
|
| 24 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 25 |
|
| 26 |
class WordTreeRequest(BaseModel):
|
| 27 |
prompt_text: str = Field(..., description="生成に使用するプロンプト")
|
|
@@ -41,6 +56,33 @@ def _set_status(message: str) -> None:
|
|
| 41 |
status_message = message
|
| 42 |
|
| 43 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 44 |
def initialize_model() -> None:
|
| 45 |
"""RustAdapter とモデルを初期化"""
|
| 46 |
global adapter
|
|
@@ -48,7 +90,7 @@ def initialize_model() -> None:
|
|
| 48 |
_set_status("モデルを読み込み中です...")
|
| 49 |
from package.rust_adapter import RustAdapter
|
| 50 |
|
| 51 |
-
model_path =
|
| 52 |
adapter = RustAdapter.get_instance(model_path)
|
| 53 |
_set_status("モデル準備完了")
|
| 54 |
except Exception as exc: # pragma: no cover
|
|
|
|
| 3 |
FastAPI 版 LLMView Word Tree サーバー
|
| 4 |
"""
|
| 5 |
|
| 6 |
+
import os
|
| 7 |
import threading
|
| 8 |
+
from pathlib import Path
|
| 9 |
from typing import List, Dict, Any, Optional
|
| 10 |
|
| 11 |
from fastapi import FastAPI, HTTPException
|
| 12 |
+
from huggingface_hub import snapshot_download
|
| 13 |
from pydantic import BaseModel, Field
|
| 14 |
|
| 15 |
try:
|
|
|
|
| 25 |
status_message = "モデル初期化中..."
|
| 26 |
status_lock = threading.Lock()
|
| 27 |
|
| 28 |
+
HF_MODEL_REPO = os.getenv("HF_MODEL_REPO", "WatNeru/LLMView-model")
|
| 29 |
+
HF_MODEL_FILENAME = os.getenv(
|
| 30 |
+
"HF_MODEL_FILENAME", "llama-3.2-3b-instruct-q4_k_m.gguf"
|
| 31 |
+
)
|
| 32 |
+
HF_LOCAL_DIR = Path(
|
| 33 |
+
os.getenv(
|
| 34 |
+
"HF_MODEL_LOCAL_DIR",
|
| 35 |
+
path_manager.base_path / "model_cache",
|
| 36 |
+
)
|
| 37 |
+
)
|
| 38 |
+
HF_TOKEN = os.getenv("HF_TOKEN")
|
| 39 |
+
|
| 40 |
|
| 41 |
class WordTreeRequest(BaseModel):
|
| 42 |
prompt_text: str = Field(..., description="生成に使用するプロンプト")
|
|
|
|
| 56 |
status_message = message
|
| 57 |
|
| 58 |
|
| 59 |
+
def ensure_model_available() -> str:
|
| 60 |
+
"""モデルファイルをローカルに用意(なければHFから取得)"""
|
| 61 |
+
current_path = Path(path_manager.get_model_path())
|
| 62 |
+
if current_path.exists():
|
| 63 |
+
return str(current_path)
|
| 64 |
+
|
| 65 |
+
HF_LOCAL_DIR.mkdir(parents=True, exist_ok=True)
|
| 66 |
+
_set_status("Hugging Face からモデルをダウンロード中...")
|
| 67 |
+
|
| 68 |
+
snapshot_download(
|
| 69 |
+
repo_id=HF_MODEL_REPO,
|
| 70 |
+
allow_patterns=HF_MODEL_FILENAME,
|
| 71 |
+
local_dir=str(HF_LOCAL_DIR),
|
| 72 |
+
local_dir_use_symlinks=False,
|
| 73 |
+
token=HF_TOKEN,
|
| 74 |
+
)
|
| 75 |
+
downloaded = HF_LOCAL_DIR / HF_MODEL_FILENAME
|
| 76 |
+
if not downloaded.exists():
|
| 77 |
+
raise FileNotFoundError(
|
| 78 |
+
f"モデル {HF_MODEL_FILENAME} が {downloaded} に見つかりません"
|
| 79 |
+
)
|
| 80 |
+
|
| 81 |
+
os.environ["LLM_MODEL_PATH"] = str(downloaded)
|
| 82 |
+
path_manager.model_path = str(downloaded)
|
| 83 |
+
return str(downloaded)
|
| 84 |
+
|
| 85 |
+
|
| 86 |
def initialize_model() -> None:
|
| 87 |
"""RustAdapter とモデルを初期化"""
|
| 88 |
global adapter
|
|
|
|
| 90 |
_set_status("モデルを読み込み中です...")
|
| 91 |
from package.rust_adapter import RustAdapter
|
| 92 |
|
| 93 |
+
model_path = ensure_model_available()
|
| 94 |
adapter = RustAdapter.get_instance(model_path)
|
| 95 |
_set_status("モデル準備完了")
|
| 96 |
except Exception as exc: # pragma: no cover
|
package/__pycache__/ai.cpython-310.pyc
DELETED
|
Binary file (5.28 kB)
|
|
|
package/__pycache__/config.cpython-310.pyc
DELETED
|
Binary file (4.93 kB)
|
|
|
package/__pycache__/path_manager.cpython-310.pyc
DELETED
|
Binary file (4.76 kB)
|
|
|
package/__pycache__/rust_adapter.cpython-310.pyc
DELETED
|
Binary file (3.2 kB)
|
|
|
package/__pycache__/word_counter.cpython-310.pyc
DELETED
|
Binary file (5.42 kB)
|
|
|
package/__pycache__/word_processor.cpython-310.pyc
DELETED
|
Binary file (15.2 kB)
|
|
|
requirements.txt
CHANGED
|
@@ -19,5 +19,8 @@ gradio>=4.38.0
|
|
| 19 |
fastapi>=0.111.0
|
| 20 |
uvicorn>=0.30.0
|
| 21 |
|
|
|
|
|
|
|
|
|
|
| 22 |
# その他
|
| 23 |
typing-extensions>=4.0.0
|
|
|
|
| 19 |
fastapi>=0.111.0
|
| 20 |
uvicorn>=0.30.0
|
| 21 |
|
| 22 |
+
# Model management
|
| 23 |
+
huggingface-hub>=0.24.0
|
| 24 |
+
|
| 25 |
# その他
|
| 26 |
typing-extensions>=4.0.0
|