Spaces:
Running
on
Zero
Running
on
Zero
Add files
Browse files- .gitattributes +4 -0
- .pre-commit-config.yaml +33 -0
- .python-version +1 -0
- .vscode/extensions.json +8 -0
- .vscode/settings.json +17 -0
- README.md +3 -3
- app.py +260 -0
- assets/cat.jpeg +3 -0
- assets/speech.wav +3 -0
- assets/speech2.wav +3 -0
- pyproject.toml +67 -0
- requirements.txt +288 -0
- style.css +4 -0
- uv.lock +0 -0
- wheels/timm-1.0.16.dev0-py3-none-any.whl +3 -0
- wheels/transformers-4.53.0.dev0-py3-none-any.whl +3 -0
.gitattributes
CHANGED
@@ -33,3 +33,7 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
36 |
+
*.jpeg filter=lfs diff=lfs merge=lfs -text
|
37 |
+
*.whl filter=lfs diff=lfs merge=lfs -text
|
38 |
+
*.wav filter=lfs diff=lfs merge=lfs -text
|
39 |
+
*.jpg filter=lfs diff=lfs merge=lfs -text
|
.pre-commit-config.yaml
ADDED
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
repos:
|
2 |
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
3 |
+
rev: v5.0.0
|
4 |
+
hooks:
|
5 |
+
- id: check-executables-have-shebangs
|
6 |
+
- id: check-json
|
7 |
+
- id: check-merge-conflict
|
8 |
+
- id: check-shebang-scripts-are-executable
|
9 |
+
- id: check-toml
|
10 |
+
- id: check-yaml
|
11 |
+
- id: end-of-file-fixer
|
12 |
+
- id: mixed-line-ending
|
13 |
+
args: ["--fix=lf"]
|
14 |
+
- id: requirements-txt-fixer
|
15 |
+
- id: trailing-whitespace
|
16 |
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
17 |
+
rev: v0.12.0
|
18 |
+
hooks:
|
19 |
+
- id: ruff-check
|
20 |
+
args: ["--fix"]
|
21 |
+
- id: ruff-format
|
22 |
+
- repo: https://github.com/pre-commit/mirrors-mypy
|
23 |
+
rev: v1.16.1
|
24 |
+
hooks:
|
25 |
+
- id: mypy
|
26 |
+
args: ["--ignore-missing-imports"]
|
27 |
+
additional_dependencies:
|
28 |
+
[
|
29 |
+
"types-python-slugify",
|
30 |
+
"types-pytz",
|
31 |
+
"types-PyYAML",
|
32 |
+
"types-requests",
|
33 |
+
]
|
.python-version
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
3.10
|
.vscode/extensions.json
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"recommendations": [
|
3 |
+
"ms-python.python",
|
4 |
+
"charliermarsh.ruff",
|
5 |
+
"streetsidesoftware.code-spell-checker",
|
6 |
+
"tamasfe.even-better-toml"
|
7 |
+
]
|
8 |
+
}
|
.vscode/settings.json
ADDED
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"editor.formatOnSave": true,
|
3 |
+
"files.insertFinalNewline": false,
|
4 |
+
"[python]": {
|
5 |
+
"editor.defaultFormatter": "charliermarsh.ruff",
|
6 |
+
"editor.formatOnType": true,
|
7 |
+
"editor.codeActionsOnSave": {
|
8 |
+
"source.fixAll.ruff": "explicit",
|
9 |
+
"source.organizeImports": "explicit"
|
10 |
+
}
|
11 |
+
},
|
12 |
+
"[jupyter]": {
|
13 |
+
"files.insertFinalNewline": false
|
14 |
+
},
|
15 |
+
"notebook.output.scrolling": true,
|
16 |
+
"notebook.formatOnSave.enabled": true
|
17 |
+
}
|
README.md
CHANGED
@@ -1,8 +1,8 @@
|
|
1 |
---
|
2 |
title: Gemma 3n E4B It
|
3 |
-
emoji:
|
4 |
-
colorFrom:
|
5 |
-
colorTo:
|
6 |
sdk: gradio
|
7 |
sdk_version: 5.34.2
|
8 |
app_file: app.py
|
|
|
1 |
---
|
2 |
title: Gemma 3n E4B It
|
3 |
+
emoji: ⚡
|
4 |
+
colorFrom: red
|
5 |
+
colorTo: purple
|
6 |
sdk: gradio
|
7 |
sdk_version: 5.34.2
|
8 |
app_file: app.py
|
app.py
ADDED
@@ -0,0 +1,260 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import pathlib
|
3 |
+
import shlex
|
4 |
+
import subprocess
|
5 |
+
import tempfile
|
6 |
+
from collections.abc import Iterator
|
7 |
+
from threading import Thread
|
8 |
+
|
9 |
+
# TODO: remove this once the transformers implementation is published # noqa: FIX002, TD002, TD003
|
10 |
+
if os.getenv("SPACE_ID"):
|
11 |
+
subprocess.run(shlex.split("pip install wheels/timm-1.0.16.dev0-py3-none-any.whl"), check=True) # noqa: S603
|
12 |
+
subprocess.run(shlex.split("pip install wheels/transformers-4.53.0.dev0-py3-none-any.whl"), check=True) # noqa: S603
|
13 |
+
|
14 |
+
import av
|
15 |
+
import gradio as gr
|
16 |
+
import spaces
|
17 |
+
import torch
|
18 |
+
from gradio.utils import get_upload_folder
|
19 |
+
from transformers import AutoModelForImageTextToText, AutoProcessor
|
20 |
+
from transformers.generation.streamers import TextIteratorStreamer
|
21 |
+
|
22 |
+
# TODO: update model_id # noqa: FIX002, TD002, TD003
|
23 |
+
model_id = "gg-hf-gm/gemma-3n-E4B-it"
|
24 |
+
|
25 |
+
processor = AutoProcessor.from_pretrained(model_id)
|
26 |
+
model = AutoModelForImageTextToText.from_pretrained(model_id, device_map="auto", torch_dtype=torch.bfloat16)
|
27 |
+
|
28 |
+
IMAGE_FILE_TYPES = (".jpg", ".jpeg", ".png", ".webp")
|
29 |
+
VIDEO_FILE_TYPES = (".mp4", ".mov", ".webm")
|
30 |
+
AUDIO_FILE_TYPES = (".mp3", ".wav")
|
31 |
+
|
32 |
+
GRADIO_TEMP_DIR = get_upload_folder()
|
33 |
+
|
34 |
+
TARGET_FPS = int(os.getenv("TARGET_FPS", "3"))
|
35 |
+
MAX_FRAMES = int(os.getenv("MAX_FRAMES", "30"))
|
36 |
+
MAX_INPUT_TOKENS = int(os.getenv("MAX_INPUT_TOKENS", "10_000"))
|
37 |
+
|
38 |
+
|
39 |
+
def get_file_type(path: str) -> str:
|
40 |
+
if path.endswith(IMAGE_FILE_TYPES):
|
41 |
+
return "image"
|
42 |
+
if path.endswith(VIDEO_FILE_TYPES):
|
43 |
+
return "video"
|
44 |
+
if path.endswith(AUDIO_FILE_TYPES):
|
45 |
+
return "audio"
|
46 |
+
error_message = f"Unsupported file type: {path}"
|
47 |
+
raise ValueError(error_message)
|
48 |
+
|
49 |
+
|
50 |
+
def count_files_in_new_message(paths: list[str]) -> tuple[int, int]:
|
51 |
+
video_count = 0
|
52 |
+
non_video_count = 0
|
53 |
+
for path in paths:
|
54 |
+
if path.endswith(VIDEO_FILE_TYPES):
|
55 |
+
video_count += 1
|
56 |
+
else:
|
57 |
+
non_video_count += 1
|
58 |
+
return video_count, non_video_count
|
59 |
+
|
60 |
+
|
61 |
+
def validate_media_constraints(message: dict) -> bool:
|
62 |
+
video_count, non_video_count = count_files_in_new_message(message["files"])
|
63 |
+
if video_count > 1:
|
64 |
+
gr.Warning("Only one video is supported.")
|
65 |
+
return False
|
66 |
+
if video_count == 1 and non_video_count > 0:
|
67 |
+
gr.Warning("Mixing images and videos is not allowed.")
|
68 |
+
return False
|
69 |
+
return True
|
70 |
+
|
71 |
+
|
72 |
+
def extract_frames_to_tempdir(
|
73 |
+
video_path: str,
|
74 |
+
target_fps: float,
|
75 |
+
max_frames: int | None = None,
|
76 |
+
parent_dir: str | None = None,
|
77 |
+
prefix: str = "frames_",
|
78 |
+
) -> str:
|
79 |
+
temp_dir = tempfile.mkdtemp(prefix=prefix, dir=parent_dir)
|
80 |
+
|
81 |
+
container = av.open(video_path)
|
82 |
+
video_stream = container.streams.video[0]
|
83 |
+
|
84 |
+
if video_stream.duration is None or video_stream.time_base is None:
|
85 |
+
raise ValueError("video_stream is missing duration or time_base")
|
86 |
+
|
87 |
+
time_base = video_stream.time_base
|
88 |
+
duration = float(video_stream.duration * time_base)
|
89 |
+
interval = 1.0 / target_fps
|
90 |
+
|
91 |
+
total_frames = int(duration * target_fps)
|
92 |
+
if max_frames is not None:
|
93 |
+
total_frames = min(total_frames, max_frames)
|
94 |
+
|
95 |
+
target_times = [i * interval for i in range(total_frames)]
|
96 |
+
target_index = 0
|
97 |
+
|
98 |
+
for frame in container.decode(video=0):
|
99 |
+
if frame.pts is None:
|
100 |
+
continue
|
101 |
+
|
102 |
+
timestamp = float(frame.pts * time_base)
|
103 |
+
|
104 |
+
if target_index < len(target_times) and abs(timestamp - target_times[target_index]) < (interval / 2):
|
105 |
+
frame_path = pathlib.Path(temp_dir) / f"frame_{target_index:04d}.jpg"
|
106 |
+
frame.to_image().save(frame_path)
|
107 |
+
target_index += 1
|
108 |
+
|
109 |
+
if max_frames is not None and target_index >= max_frames:
|
110 |
+
break
|
111 |
+
|
112 |
+
container.close()
|
113 |
+
return temp_dir
|
114 |
+
|
115 |
+
|
116 |
+
def process_new_user_message(message: dict) -> list[dict]:
|
117 |
+
if not message["files"]:
|
118 |
+
return [{"type": "text", "text": message["text"]}]
|
119 |
+
|
120 |
+
file_types = [get_file_type(path) for path in message["files"]]
|
121 |
+
|
122 |
+
if len(file_types) == 1 and file_types[0] == "video":
|
123 |
+
gr.Info(f"Video will be processed at {TARGET_FPS} FPS, max {MAX_FRAMES} frames in this Space.")
|
124 |
+
|
125 |
+
temp_dir = extract_frames_to_tempdir(
|
126 |
+
message["files"][0],
|
127 |
+
target_fps=TARGET_FPS,
|
128 |
+
max_frames=MAX_FRAMES,
|
129 |
+
parent_dir=GRADIO_TEMP_DIR,
|
130 |
+
)
|
131 |
+
paths = sorted(pathlib.Path(temp_dir).glob("*.jpg"))
|
132 |
+
return [
|
133 |
+
{"type": "text", "text": message["text"]},
|
134 |
+
*[{"type": "image", "image": path.as_posix()} for path in paths],
|
135 |
+
]
|
136 |
+
|
137 |
+
return [
|
138 |
+
{"type": "text", "text": message["text"]},
|
139 |
+
*[{"type": file_type, file_type: path} for path, file_type in zip(message["files"], file_types, strict=True)],
|
140 |
+
]
|
141 |
+
|
142 |
+
|
143 |
+
def process_history(history: list[dict]) -> list[dict]:
|
144 |
+
messages = []
|
145 |
+
current_user_content: list[dict] = []
|
146 |
+
for item in history:
|
147 |
+
if item["role"] == "assistant":
|
148 |
+
if current_user_content:
|
149 |
+
messages.append({"role": "user", "content": current_user_content})
|
150 |
+
current_user_content = []
|
151 |
+
messages.append({"role": "assistant", "content": [{"type": "text", "text": item["content"]}]})
|
152 |
+
else:
|
153 |
+
content = item["content"]
|
154 |
+
if isinstance(content, str):
|
155 |
+
current_user_content.append({"type": "text", "text": content})
|
156 |
+
else:
|
157 |
+
filepath = content[0]
|
158 |
+
file_type = get_file_type(filepath)
|
159 |
+
current_user_content.append({"type": file_type, file_type: filepath})
|
160 |
+
return messages
|
161 |
+
|
162 |
+
|
163 |
+
@spaces.GPU(duration=120)
|
164 |
+
@torch.inference_mode()
|
165 |
+
def generate(message: dict, history: list[dict], system_prompt: str = "", max_new_tokens: int = 512) -> Iterator[str]:
|
166 |
+
if not validate_media_constraints(message):
|
167 |
+
yield ""
|
168 |
+
return
|
169 |
+
|
170 |
+
messages = []
|
171 |
+
if system_prompt:
|
172 |
+
messages.append({"role": "system", "content": [{"type": "text", "text": system_prompt}]})
|
173 |
+
messages.extend(process_history(history))
|
174 |
+
messages.append({"role": "user", "content": process_new_user_message(message)})
|
175 |
+
|
176 |
+
inputs = processor.apply_chat_template(
|
177 |
+
messages,
|
178 |
+
add_generation_prompt=True,
|
179 |
+
tokenize=True,
|
180 |
+
return_dict=True,
|
181 |
+
return_tensors="pt",
|
182 |
+
)
|
183 |
+
n_tokens = inputs["input_ids"].shape[1]
|
184 |
+
if n_tokens > MAX_INPUT_TOKENS:
|
185 |
+
gr.Warning(
|
186 |
+
f"Input too long. Max {MAX_INPUT_TOKENS} tokens. Got {n_tokens} tokens. This limit is set to avoid CUDA out-of-memory errors in this Space."
|
187 |
+
)
|
188 |
+
yield ""
|
189 |
+
return
|
190 |
+
|
191 |
+
inputs = inputs.to(device=model.device, dtype=torch.bfloat16)
|
192 |
+
|
193 |
+
streamer = TextIteratorStreamer(processor, timeout=30.0, skip_prompt=True, skip_special_tokens=True)
|
194 |
+
generate_kwargs = dict(
|
195 |
+
inputs,
|
196 |
+
streamer=streamer,
|
197 |
+
max_new_tokens=max_new_tokens,
|
198 |
+
do_sample=False,
|
199 |
+
disable_compile=True,
|
200 |
+
)
|
201 |
+
t = Thread(target=model.generate, kwargs=generate_kwargs)
|
202 |
+
t.start()
|
203 |
+
|
204 |
+
output = ""
|
205 |
+
for delta in streamer:
|
206 |
+
output += delta
|
207 |
+
yield output
|
208 |
+
|
209 |
+
|
210 |
+
examples = [
|
211 |
+
[
|
212 |
+
{
|
213 |
+
"text": "What is the capital of France?",
|
214 |
+
"files": [],
|
215 |
+
}
|
216 |
+
],
|
217 |
+
[
|
218 |
+
{
|
219 |
+
"text": "Describe this image in detail.",
|
220 |
+
"files": ["assets/cat.jpeg"],
|
221 |
+
}
|
222 |
+
],
|
223 |
+
[
|
224 |
+
{
|
225 |
+
"text": "Transcribe the following speech segment in English.",
|
226 |
+
"files": ["assets/speech.wav"],
|
227 |
+
}
|
228 |
+
],
|
229 |
+
[
|
230 |
+
{
|
231 |
+
"text": "Transcribe the following speech segment in English.",
|
232 |
+
"files": ["assets/speech2.wav"],
|
233 |
+
}
|
234 |
+
],
|
235 |
+
]
|
236 |
+
|
237 |
+
demo = gr.ChatInterface(
|
238 |
+
fn=generate,
|
239 |
+
type="messages",
|
240 |
+
textbox=gr.MultimodalTextbox(
|
241 |
+
file_types=list(IMAGE_FILE_TYPES + VIDEO_FILE_TYPES + AUDIO_FILE_TYPES),
|
242 |
+
file_count="multiple",
|
243 |
+
autofocus=True,
|
244 |
+
),
|
245 |
+
multimodal=True,
|
246 |
+
additional_inputs=[
|
247 |
+
gr.Textbox(label="System Prompt", value="You are a helpful assistant."),
|
248 |
+
gr.Slider(label="Max New Tokens", minimum=100, maximum=2000, step=10, value=700),
|
249 |
+
],
|
250 |
+
stop_btn=False,
|
251 |
+
title="Gemma 3n E4B it",
|
252 |
+
examples=examples,
|
253 |
+
run_examples_on_click=False,
|
254 |
+
cache_examples=False,
|
255 |
+
css_paths="style.css",
|
256 |
+
delete_cache=(1800, 1800),
|
257 |
+
)
|
258 |
+
|
259 |
+
if __name__ == "__main__":
|
260 |
+
demo.launch()
|
assets/cat.jpeg
ADDED
![]() |
Git LFS Details
|
assets/speech.wav
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:219f55927c62af71fa7dc29581b647ade375286498dd0e342cc07c72cc8edc04
|
3 |
+
size 136764
|
assets/speech2.wav
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:f03711ca239a7b6f3cd13f3942f4f64b32173f4f1d01abf55fa91608a178efac
|
3 |
+
size 545644
|
pyproject.toml
ADDED
@@ -0,0 +1,67 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
[project]
|
2 |
+
name = "gemma-3n-e4b-it"
|
3 |
+
version = "0.1.0"
|
4 |
+
description = ""
|
5 |
+
readme = "README.md"
|
6 |
+
requires-python = ">=3.10"
|
7 |
+
dependencies = [
|
8 |
+
"accelerate>=1.8.1",
|
9 |
+
"av>=14.4.0",
|
10 |
+
"gradio>=5.34.2",
|
11 |
+
"hf-transfer>=0.1.9",
|
12 |
+
"librosa>=0.11.0",
|
13 |
+
"spaces>=0.37.1",
|
14 |
+
"torch==2.5.1",
|
15 |
+
"torchvision>=0.20.1",
|
16 |
+
]
|
17 |
+
|
18 |
+
[tool.ruff]
|
19 |
+
line-length = 119
|
20 |
+
|
21 |
+
[tool.ruff.lint]
|
22 |
+
select = ["ALL"]
|
23 |
+
ignore = [
|
24 |
+
"COM812", # missing-trailing-comma
|
25 |
+
"D203", # one-blank-line-before-class
|
26 |
+
"D213", # multi-line-summary-second-line
|
27 |
+
"E501", # line-too-long
|
28 |
+
"SIM117", # multiple-with-statements
|
29 |
+
#
|
30 |
+
"D100", # undocumented-public-module
|
31 |
+
"D101", # undocumented-public-class
|
32 |
+
"D102", # undocumented-public-method
|
33 |
+
"D103", # undocumented-public-function
|
34 |
+
"D104", # undocumented-public-package
|
35 |
+
"D105", # undocumented-magic-method
|
36 |
+
"D107", # undocumented-public-init
|
37 |
+
"EM101", # raw-string-in-exception
|
38 |
+
"FBT001", # boolean-type-hint-positional-argument
|
39 |
+
"FBT002", # boolean-default-value-positional-argument
|
40 |
+
"PD901", # pandas-df-variable-name
|
41 |
+
"PGH003", # blanket-type-ignore
|
42 |
+
"PLR0913", # too-many-arguments
|
43 |
+
"PLR0915", # too-many-statements
|
44 |
+
"TRY003", # raise-vanilla-args
|
45 |
+
]
|
46 |
+
unfixable = [
|
47 |
+
"F401", # unused-import
|
48 |
+
]
|
49 |
+
|
50 |
+
[tool.ruff.lint.pydocstyle]
|
51 |
+
convention = "google"
|
52 |
+
|
53 |
+
[tool.ruff.lint.per-file-ignores]
|
54 |
+
"*.ipynb" = ["T201", "T203"]
|
55 |
+
|
56 |
+
[tool.ruff.format]
|
57 |
+
docstring-code-format = true
|
58 |
+
|
59 |
+
[tool.uv.sources]
|
60 |
+
timm = { path = "wheels/timm-1.0.16.dev0-py3-none-any.whl" }
|
61 |
+
transformers = { path = "wheels/transformers-4.53.0.dev0-py3-none-any.whl" }
|
62 |
+
|
63 |
+
[dependency-groups]
|
64 |
+
dev = [
|
65 |
+
"timm",
|
66 |
+
"transformers",
|
67 |
+
]
|
requirements.txt
ADDED
@@ -0,0 +1,288 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# This file was autogenerated by uv via the following command:
|
2 |
+
# uv pip compile pyproject.toml -o requirements.txt
|
3 |
+
accelerate==1.8.1
|
4 |
+
# via gemma-3n-e4b-it (pyproject.toml)
|
5 |
+
aiofiles==24.1.0
|
6 |
+
# via gradio
|
7 |
+
annotated-types==0.7.0
|
8 |
+
# via pydantic
|
9 |
+
anyio==4.9.0
|
10 |
+
# via
|
11 |
+
# gradio
|
12 |
+
# httpx
|
13 |
+
# starlette
|
14 |
+
audioread==3.0.1
|
15 |
+
# via librosa
|
16 |
+
av==14.4.0
|
17 |
+
# via gemma-3n-e4b-it (pyproject.toml)
|
18 |
+
certifi==2025.6.15
|
19 |
+
# via
|
20 |
+
# httpcore
|
21 |
+
# httpx
|
22 |
+
# requests
|
23 |
+
cffi==1.17.1
|
24 |
+
# via soundfile
|
25 |
+
charset-normalizer==3.4.2
|
26 |
+
# via requests
|
27 |
+
click==8.2.1
|
28 |
+
# via
|
29 |
+
# typer
|
30 |
+
# uvicorn
|
31 |
+
decorator==5.2.1
|
32 |
+
# via librosa
|
33 |
+
exceptiongroup==1.3.0
|
34 |
+
# via anyio
|
35 |
+
fastapi==0.115.13
|
36 |
+
# via gradio
|
37 |
+
ffmpy==0.6.0
|
38 |
+
# via gradio
|
39 |
+
filelock==3.18.0
|
40 |
+
# via
|
41 |
+
# huggingface-hub
|
42 |
+
# torch
|
43 |
+
# triton
|
44 |
+
fsspec==2025.5.1
|
45 |
+
# via
|
46 |
+
# gradio-client
|
47 |
+
# huggingface-hub
|
48 |
+
# torch
|
49 |
+
gradio==5.34.2
|
50 |
+
# via
|
51 |
+
# gemma-3n-e4b-it (pyproject.toml)
|
52 |
+
# spaces
|
53 |
+
gradio-client==1.10.3
|
54 |
+
# via gradio
|
55 |
+
groovy==0.1.2
|
56 |
+
# via gradio
|
57 |
+
h11==0.16.0
|
58 |
+
# via
|
59 |
+
# httpcore
|
60 |
+
# uvicorn
|
61 |
+
hf-transfer==0.1.9
|
62 |
+
# via gemma-3n-e4b-it (pyproject.toml)
|
63 |
+
hf-xet==1.1.5
|
64 |
+
# via huggingface-hub
|
65 |
+
httpcore==1.0.9
|
66 |
+
# via httpx
|
67 |
+
httpx==0.28.1
|
68 |
+
# via
|
69 |
+
# gradio
|
70 |
+
# gradio-client
|
71 |
+
# safehttpx
|
72 |
+
# spaces
|
73 |
+
huggingface-hub==0.33.0
|
74 |
+
# via
|
75 |
+
# accelerate
|
76 |
+
# gradio
|
77 |
+
# gradio-client
|
78 |
+
idna==3.10
|
79 |
+
# via
|
80 |
+
# anyio
|
81 |
+
# httpx
|
82 |
+
# requests
|
83 |
+
jinja2==3.1.6
|
84 |
+
# via
|
85 |
+
# gradio
|
86 |
+
# torch
|
87 |
+
joblib==1.5.1
|
88 |
+
# via
|
89 |
+
# librosa
|
90 |
+
# scikit-learn
|
91 |
+
lazy-loader==0.4
|
92 |
+
# via librosa
|
93 |
+
librosa==0.11.0
|
94 |
+
# via gemma-3n-e4b-it (pyproject.toml)
|
95 |
+
llvmlite==0.44.0
|
96 |
+
# via numba
|
97 |
+
markdown-it-py==3.0.0
|
98 |
+
# via rich
|
99 |
+
markupsafe==3.0.2
|
100 |
+
# via
|
101 |
+
# gradio
|
102 |
+
# jinja2
|
103 |
+
mdurl==0.1.2
|
104 |
+
# via markdown-it-py
|
105 |
+
mpmath==1.3.0
|
106 |
+
# via sympy
|
107 |
+
msgpack==1.1.1
|
108 |
+
# via librosa
|
109 |
+
networkx==3.4.2
|
110 |
+
# via torch
|
111 |
+
numba==0.61.2
|
112 |
+
# via librosa
|
113 |
+
numpy==2.2.6
|
114 |
+
# via
|
115 |
+
# accelerate
|
116 |
+
# gradio
|
117 |
+
# librosa
|
118 |
+
# numba
|
119 |
+
# pandas
|
120 |
+
# scikit-learn
|
121 |
+
# scipy
|
122 |
+
# soundfile
|
123 |
+
# soxr
|
124 |
+
# torchvision
|
125 |
+
nvidia-cublas-cu12==12.4.5.8
|
126 |
+
# via
|
127 |
+
# nvidia-cudnn-cu12
|
128 |
+
# nvidia-cusolver-cu12
|
129 |
+
# torch
|
130 |
+
nvidia-cuda-cupti-cu12==12.4.127
|
131 |
+
# via torch
|
132 |
+
nvidia-cuda-nvrtc-cu12==12.4.127
|
133 |
+
# via torch
|
134 |
+
nvidia-cuda-runtime-cu12==12.4.127
|
135 |
+
# via torch
|
136 |
+
nvidia-cudnn-cu12==9.1.0.70
|
137 |
+
# via torch
|
138 |
+
nvidia-cufft-cu12==11.2.1.3
|
139 |
+
# via torch
|
140 |
+
nvidia-curand-cu12==10.3.5.147
|
141 |
+
# via torch
|
142 |
+
nvidia-cusolver-cu12==11.6.1.9
|
143 |
+
# via torch
|
144 |
+
nvidia-cusparse-cu12==12.3.1.170
|
145 |
+
# via
|
146 |
+
# nvidia-cusolver-cu12
|
147 |
+
# torch
|
148 |
+
nvidia-nccl-cu12==2.21.5
|
149 |
+
# via torch
|
150 |
+
nvidia-nvjitlink-cu12==12.4.127
|
151 |
+
# via
|
152 |
+
# nvidia-cusolver-cu12
|
153 |
+
# nvidia-cusparse-cu12
|
154 |
+
# torch
|
155 |
+
nvidia-nvtx-cu12==12.4.127
|
156 |
+
# via torch
|
157 |
+
orjson==3.10.18
|
158 |
+
# via gradio
|
159 |
+
packaging==25.0
|
160 |
+
# via
|
161 |
+
# accelerate
|
162 |
+
# gradio
|
163 |
+
# gradio-client
|
164 |
+
# huggingface-hub
|
165 |
+
# lazy-loader
|
166 |
+
# pooch
|
167 |
+
# spaces
|
168 |
+
pandas==2.3.0
|
169 |
+
# via gradio
|
170 |
+
pillow==11.2.1
|
171 |
+
# via
|
172 |
+
# gradio
|
173 |
+
# torchvision
|
174 |
+
platformdirs==4.3.8
|
175 |
+
# via pooch
|
176 |
+
pooch==1.8.2
|
177 |
+
# via librosa
|
178 |
+
psutil==5.9.8
|
179 |
+
# via
|
180 |
+
# accelerate
|
181 |
+
# spaces
|
182 |
+
pycparser==2.22
|
183 |
+
# via cffi
|
184 |
+
pydantic==2.11.7
|
185 |
+
# via
|
186 |
+
# fastapi
|
187 |
+
# gradio
|
188 |
+
# spaces
|
189 |
+
pydantic-core==2.33.2
|
190 |
+
# via pydantic
|
191 |
+
pydub==0.25.1
|
192 |
+
# via gradio
|
193 |
+
pygments==2.19.2
|
194 |
+
# via rich
|
195 |
+
python-dateutil==2.9.0.post0
|
196 |
+
# via pandas
|
197 |
+
python-multipart==0.0.20
|
198 |
+
# via gradio
|
199 |
+
pytz==2025.2
|
200 |
+
# via pandas
|
201 |
+
pyyaml==6.0.2
|
202 |
+
# via
|
203 |
+
# accelerate
|
204 |
+
# gradio
|
205 |
+
# huggingface-hub
|
206 |
+
requests==2.32.4
|
207 |
+
# via
|
208 |
+
# huggingface-hub
|
209 |
+
# pooch
|
210 |
+
# spaces
|
211 |
+
rich==14.0.0
|
212 |
+
# via typer
|
213 |
+
ruff==0.12.0
|
214 |
+
# via gradio
|
215 |
+
safehttpx==0.1.6
|
216 |
+
# via gradio
|
217 |
+
safetensors==0.5.3
|
218 |
+
# via accelerate
|
219 |
+
scikit-learn==1.7.0
|
220 |
+
# via librosa
|
221 |
+
scipy==1.15.3
|
222 |
+
# via
|
223 |
+
# librosa
|
224 |
+
# scikit-learn
|
225 |
+
semantic-version==2.10.0
|
226 |
+
# via gradio
|
227 |
+
shellingham==1.5.4
|
228 |
+
# via typer
|
229 |
+
six==1.17.0
|
230 |
+
# via python-dateutil
|
231 |
+
sniffio==1.3.1
|
232 |
+
# via anyio
|
233 |
+
soundfile==0.13.1
|
234 |
+
# via librosa
|
235 |
+
soxr==0.5.0.post1
|
236 |
+
# via librosa
|
237 |
+
spaces==0.37.1
|
238 |
+
# via gemma-3n-e4b-it (pyproject.toml)
|
239 |
+
starlette==0.46.2
|
240 |
+
# via
|
241 |
+
# fastapi
|
242 |
+
# gradio
|
243 |
+
sympy==1.13.1
|
244 |
+
# via torch
|
245 |
+
threadpoolctl==3.6.0
|
246 |
+
# via scikit-learn
|
247 |
+
tomlkit==0.13.3
|
248 |
+
# via gradio
|
249 |
+
torch==2.5.1
|
250 |
+
# via
|
251 |
+
# gemma-3n-e4b-it (pyproject.toml)
|
252 |
+
# accelerate
|
253 |
+
# torchvision
|
254 |
+
torchvision==0.20.1
|
255 |
+
# via gemma-3n-e4b-it (pyproject.toml)
|
256 |
+
tqdm==4.67.1
|
257 |
+
# via huggingface-hub
|
258 |
+
triton==3.1.0
|
259 |
+
# via torch
|
260 |
+
typer==0.16.0
|
261 |
+
# via gradio
|
262 |
+
typing-extensions==4.14.0
|
263 |
+
# via
|
264 |
+
# anyio
|
265 |
+
# exceptiongroup
|
266 |
+
# fastapi
|
267 |
+
# gradio
|
268 |
+
# gradio-client
|
269 |
+
# huggingface-hub
|
270 |
+
# librosa
|
271 |
+
# pydantic
|
272 |
+
# pydantic-core
|
273 |
+
# rich
|
274 |
+
# spaces
|
275 |
+
# torch
|
276 |
+
# typer
|
277 |
+
# typing-inspection
|
278 |
+
# uvicorn
|
279 |
+
typing-inspection==0.4.1
|
280 |
+
# via pydantic
|
281 |
+
tzdata==2025.2
|
282 |
+
# via pandas
|
283 |
+
urllib3==2.5.0
|
284 |
+
# via requests
|
285 |
+
uvicorn==0.34.3
|
286 |
+
# via gradio
|
287 |
+
websockets==15.0.1
|
288 |
+
# via gradio-client
|
style.css
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
1 |
+
h1 {
|
2 |
+
text-align: center;
|
3 |
+
display: block;
|
4 |
+
}
|
uv.lock
ADDED
The diff for this file is too large to render.
See raw diff
|
|
wheels/timm-1.0.16.dev0-py3-none-any.whl
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:bc9686fd88dfc74611ac0eb9c6a8598ea33f9cfc8cb1a7477cd9c765c659bae9
|
3 |
+
size 2485728
|
wheels/transformers-4.53.0.dev0-py3-none-any.whl
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:6f2c9040adc3ac4574b20aaf04883ba8a5f0ef6fc62b1d1ca24744369205fdd5
|
3 |
+
size 11532544
|