Spaces:
Running
Running
add backend files
Browse files- backend/__pycache__/app.cpython-313.pyc +0 -0
- backend/app.py +5 -1
- backend/hf_model_utils.py +63 -0
- backend/requirements.txt +40 -2
- frontend/vite.config.js +4 -1
backend/__pycache__/app.cpython-313.pyc
CHANGED
|
Binary files a/backend/__pycache__/app.cpython-313.pyc and b/backend/__pycache__/app.cpython-313.pyc differ
|
|
|
backend/app.py
CHANGED
|
@@ -22,4 +22,8 @@ def greet_json():
|
|
| 22 |
|
| 23 |
# Serve frontend build under / (but exclude /api)
|
| 24 |
frontend_path = Path(__file__).parent.parent / "frontend" / "dist"
|
| 25 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 22 |
|
| 23 |
# Serve frontend build under / (but exclude /api)
|
| 24 |
frontend_path = Path(__file__).parent.parent / "frontend" / "dist"
|
| 25 |
+
|
| 26 |
+
if frontend_path.exists():
|
| 27 |
+
app.mount("/", StaticFiles(directory=frontend_path, html=True), name="frontend")
|
| 28 |
+
else:
|
| 29 |
+
print("Frontend build not found. Skipping StaticFiles mount.")
|
backend/hf_model_utils.py
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import torch
|
| 2 |
+
import torch.nn as nn
|
| 3 |
+
import json
|
| 4 |
+
import hashlib
|
| 5 |
+
import torch
|
| 6 |
+
import gc
|
| 7 |
+
from transformers import AutoConfig, AutoModel
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
def module_hash(module):
|
| 11 |
+
"""
|
| 12 |
+
Generate a hash representing the structure of a module.
|
| 13 |
+
Uses class name + child hashes + param shapes to detect repeats.
|
| 14 |
+
"""
|
| 15 |
+
children = list(module.named_children())
|
| 16 |
+
child_hashes = []
|
| 17 |
+
for name, child in children:
|
| 18 |
+
child_hashes.append(module_hash(child))
|
| 19 |
+
|
| 20 |
+
# Include class name and param shapes
|
| 21 |
+
param_info = [(name, tuple(p.shape), p.requires_grad)
|
| 22 |
+
for name, p in module.named_parameters(recurse=False)]
|
| 23 |
+
|
| 24 |
+
rep = (module.__class__.__name__, tuple(child_hashes), tuple(param_info))
|
| 25 |
+
rep_bytes = str(rep).encode('utf-8')
|
| 26 |
+
return hashlib.md5(rep_bytes).hexdigest()
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
def hf_style_structural_dict(module):
|
| 30 |
+
"""
|
| 31 |
+
Recursively convert a PyTorch module into a dict mirroring
|
| 32 |
+
Hugging Face's print(model), only counting repeats when structure is identical.
|
| 33 |
+
"""
|
| 34 |
+
children = list(module.named_children())
|
| 35 |
+
result = {"class_name": module.__class__.__name__}
|
| 36 |
+
|
| 37 |
+
# Include params if present
|
| 38 |
+
params = {name: {"shape": list(p.shape), "requires_grad": p.requires_grad}
|
| 39 |
+
for name, p in module.named_parameters(recurse=False)}
|
| 40 |
+
if params:
|
| 41 |
+
result["params"] = params
|
| 42 |
+
|
| 43 |
+
if children:
|
| 44 |
+
child_dict = {}
|
| 45 |
+
i = 0
|
| 46 |
+
while i < len(children):
|
| 47 |
+
name, child = children[i]
|
| 48 |
+
current_hash = module_hash(child)
|
| 49 |
+
count = 1
|
| 50 |
+
j = i + 1
|
| 51 |
+
# Count consecutive children that are structurally identical
|
| 52 |
+
while j < len(children) and module_hash(children[j][1]) == current_hash:
|
| 53 |
+
count += 1
|
| 54 |
+
j += 1
|
| 55 |
+
|
| 56 |
+
child_entry = hf_style_structural_dict(child)
|
| 57 |
+
if count > 1:
|
| 58 |
+
child_entry["num_repeats"] = count
|
| 59 |
+
child_dict[name] = child_entry
|
| 60 |
+
i += count
|
| 61 |
+
result["children"] = child_dict
|
| 62 |
+
|
| 63 |
+
return result
|
backend/requirements.txt
CHANGED
|
@@ -1,2 +1,40 @@
|
|
| 1 |
-
|
| 2 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
annotated-types==0.7.0
|
| 2 |
+
anyio==4.10.0
|
| 3 |
+
certifi==2025.8.3
|
| 4 |
+
charset-normalizer==3.4.3
|
| 5 |
+
click==8.2.1
|
| 6 |
+
fastapi==0.116.1
|
| 7 |
+
filelock==3.19.1
|
| 8 |
+
fsspec==2025.9.0
|
| 9 |
+
h11==0.16.0
|
| 10 |
+
hf-xet==1.1.10
|
| 11 |
+
httptools==0.6.4
|
| 12 |
+
idna==3.10
|
| 13 |
+
Jinja2==3.1.6
|
| 14 |
+
MarkupSafe==3.0.2
|
| 15 |
+
mpmath==1.3.0
|
| 16 |
+
networkx==3.5
|
| 17 |
+
numpy==2.3.3
|
| 18 |
+
packaging==25.0
|
| 19 |
+
pydantic==2.11.9
|
| 20 |
+
pydantic_core==2.33.2
|
| 21 |
+
python-dotenv==1.1.1
|
| 22 |
+
PyYAML==6.0.2
|
| 23 |
+
regex==2025.9.1
|
| 24 |
+
requests==2.32.5
|
| 25 |
+
safetensors==0.6.2
|
| 26 |
+
setuptools==80.9.0
|
| 27 |
+
sniffio==1.3.1
|
| 28 |
+
starlette==0.47.3
|
| 29 |
+
sympy==1.14.0
|
| 30 |
+
tokenizers==0.22.0
|
| 31 |
+
torch==2.8.0
|
| 32 |
+
tqdm==4.67.1
|
| 33 |
+
transformers==4.56.1
|
| 34 |
+
typing-inspection==0.4.1
|
| 35 |
+
typing_extensions==4.15.0
|
| 36 |
+
urllib3==2.5.0
|
| 37 |
+
uvicorn==0.35.0
|
| 38 |
+
uvloop==0.21.0
|
| 39 |
+
watchfiles==1.1.0
|
| 40 |
+
websockets==15.0.1
|
frontend/vite.config.js
CHANGED
|
@@ -5,7 +5,10 @@ export default defineConfig({
|
|
| 5 |
plugins: [react()],
|
| 6 |
server: {
|
| 7 |
proxy: {
|
| 8 |
-
'/api':
|
|
|
|
|
|
|
|
|
|
| 9 |
}
|
| 10 |
}
|
| 11 |
})
|
|
|
|
| 5 |
plugins: [react()],
|
| 6 |
server: {
|
| 7 |
proxy: {
|
| 8 |
+
'/api': {
|
| 9 |
+
target: 'http://localhost:8000', // your FastAPI backend
|
| 10 |
+
changeOrigin: true,
|
| 11 |
+
},
|
| 12 |
}
|
| 13 |
}
|
| 14 |
})
|