@yeongjaeyou/claude-code-config 0.17.1 → 0.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/guidelines/work-guidelines.md +29 -0
- package/.claude/skills/gradio-cv-app/SKILL.md +170 -0
- package/.claude/skills/gradio-cv-app/references/github-references.md +134 -0
- package/.claude/skills/gradio-cv-app/references/i18n-patterns.md +416 -0
- package/.claude/skills/gradio-cv-app/references/refined-theme.md +403 -0
- package/.claude/skills/gradio-cv-app/references/task-templates.md +433 -0
- package/package.json +1 -1
|
@@ -0,0 +1,433 @@
|
|
|
1
|
+
# Task Templates
|
|
2
|
+
|
|
3
|
+
Implementation templates for each CV task type.
|
|
4
|
+
|
|
5
|
+
## Common Patterns
|
|
6
|
+
|
|
7
|
+
### Device Configuration
|
|
8
|
+
|
|
9
|
+
```python
|
|
10
|
+
import torch
|
|
11
|
+
|
|
12
|
+
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
|
13
|
+
print(f"Using device: {device}")
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
### GPU Decorator (Local/HF Spaces Compatible)
|
|
17
|
+
|
|
18
|
+
```python
|
|
19
|
+
try:
|
|
20
|
+
import spaces
|
|
21
|
+
SPACES_AVAILABLE = True
|
|
22
|
+
except ImportError:
|
|
23
|
+
SPACES_AVAILABLE = False
|
|
24
|
+
|
|
25
|
+
def gpu_decorator(func):
|
|
26
|
+
"""Runs directly on local, allocates GPU on Spaces"""
|
|
27
|
+
if SPACES_AVAILABLE:
|
|
28
|
+
return spaces.GPU(func)
|
|
29
|
+
return func
|
|
30
|
+
|
|
31
|
+
@gpu_decorator
|
|
32
|
+
def inference_function(image, model_name="default"):
|
|
33
|
+
# Your inference logic here
|
|
34
|
+
pass
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### App Launch Pattern
|
|
38
|
+
|
|
39
|
+
```python
|
|
40
|
+
if __name__ == "__main__":
|
|
41
|
+
demo.queue(max_size=30).launch(mcp_server=True, ssr_mode=False, show_error=True)
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Dark Mode Toggle
|
|
45
|
+
|
|
46
|
+
Add a theme toggle button with system preference detection. See [refined-theme.md](refined-theme.md) for full theme code.
|
|
47
|
+
|
|
48
|
+
```python
|
|
49
|
+
# Lucide icons (CSS controls visibility based on theme)
|
|
50
|
+
THEME_ICONS = '''
|
|
51
|
+
<span class="icon-moon"><svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"/></svg></span>
|
|
52
|
+
<span class="icon-sun"><svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="4"/><path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41"/></svg></span>
|
|
53
|
+
'''
|
|
54
|
+
|
|
55
|
+
# Toggle and init JavaScript
|
|
56
|
+
TOGGLE_JS = """() => {
|
|
57
|
+
document.documentElement.classList.toggle('dark');
|
|
58
|
+
localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light');
|
|
59
|
+
}"""
|
|
60
|
+
|
|
61
|
+
INIT_JS = """() => {
|
|
62
|
+
const saved = localStorage.getItem('theme');
|
|
63
|
+
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
64
|
+
if (saved === 'dark' || (!saved && prefersDark)) {
|
|
65
|
+
document.documentElement.classList.add('dark');
|
|
66
|
+
}
|
|
67
|
+
}"""
|
|
68
|
+
|
|
69
|
+
# Add to CSS
|
|
70
|
+
theme_toggle_css = """
|
|
71
|
+
#theme-toggle button { min-width: 40px !important; padding: 8px !important; }
|
|
72
|
+
#theme-toggle .icon-moon { display: inline-block; }
|
|
73
|
+
#theme-toggle .icon-sun { display: none; }
|
|
74
|
+
.dark #theme-toggle .icon-moon { display: none; }
|
|
75
|
+
.dark #theme-toggle .icon-sun { display: inline-block; }
|
|
76
|
+
"""
|
|
77
|
+
|
|
78
|
+
# Usage in Blocks
|
|
79
|
+
with gr.Blocks(theme=refined_theme, css=css + theme_toggle_css) as demo:
|
|
80
|
+
with gr.Row():
|
|
81
|
+
gr.Markdown("# App Title", elem_id="main-title")
|
|
82
|
+
theme_btn = gr.Button(THEME_ICONS, elem_id="theme-toggle", size="sm")
|
|
83
|
+
|
|
84
|
+
# ... UI components ...
|
|
85
|
+
|
|
86
|
+
theme_btn.click(fn=None, js=TOGGLE_JS)
|
|
87
|
+
demo.load(fn=None, js=INIT_JS)
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## OCR/VLM App (`ocr`)
|
|
93
|
+
|
|
94
|
+
Multimodal OCR app - Extract text from images/videos/PDFs
|
|
95
|
+
|
|
96
|
+
### Key Components
|
|
97
|
+
- `gr.Tabs`: Image/Video/PDF tab structure
|
|
98
|
+
- `gr.Accordion`: Advanced Options (max_tokens, temperature)
|
|
99
|
+
- `TextIteratorStreamer`: Streaming output
|
|
100
|
+
|
|
101
|
+
### Structure
|
|
102
|
+
|
|
103
|
+
```python
|
|
104
|
+
import gradio as gr
|
|
105
|
+
from transformers import AutoProcessor, AutoModelForVision2Seq, TextIteratorStreamer
|
|
106
|
+
import threading
|
|
107
|
+
|
|
108
|
+
# Model loading
|
|
109
|
+
processor = AutoProcessor.from_pretrained("model-name")
|
|
110
|
+
model = AutoModelForVision2Seq.from_pretrained("model-name").to(device)
|
|
111
|
+
model.train(False) # Inference mode
|
|
112
|
+
|
|
113
|
+
@gpu_decorator
|
|
114
|
+
def process_image(image, prompt, max_tokens, temperature):
|
|
115
|
+
streamer = TextIteratorStreamer(processor.tokenizer, skip_special_tokens=True)
|
|
116
|
+
# Inference logic
|
|
117
|
+
...
|
|
118
|
+
|
|
119
|
+
with gr.Blocks(theme=refined_theme, css=css) as demo:
|
|
120
|
+
with gr.Column(elem_id="col-container"):
|
|
121
|
+
gr.Markdown("# OCR App", elem_id="main-title")
|
|
122
|
+
|
|
123
|
+
with gr.Tabs():
|
|
124
|
+
with gr.TabItem("Image"):
|
|
125
|
+
image_input = gr.Image(label="Image", type="pil")
|
|
126
|
+
|
|
127
|
+
with gr.TabItem("Video"):
|
|
128
|
+
video_input = gr.Video(label="Video")
|
|
129
|
+
|
|
130
|
+
with gr.TabItem("PDF"):
|
|
131
|
+
pdf_input = gr.File(label="PDF", file_types=[".pdf"])
|
|
132
|
+
|
|
133
|
+
prompt_input = gr.Textbox(label="Prompt", placeholder="Extract text from the image")
|
|
134
|
+
|
|
135
|
+
with gr.Accordion("Advanced Options", open=False):
|
|
136
|
+
max_tokens = gr.Slider(100, 2000, value=500, label="Max Tokens")
|
|
137
|
+
temperature = gr.Slider(0.1, 1.0, value=0.7, label="Temperature")
|
|
138
|
+
|
|
139
|
+
output = gr.Textbox(label="Result", lines=10, show_copy_button=True)
|
|
140
|
+
submit_btn = gr.Button("Run", variant="primary")
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## Image Classification App (`classify`)
|
|
146
|
+
|
|
147
|
+
Binary or multi-class image classification
|
|
148
|
+
|
|
149
|
+
### Key Components
|
|
150
|
+
- `gr.Interface`: Simple structure
|
|
151
|
+
- `gr.Label`: Probability display
|
|
152
|
+
|
|
153
|
+
### Structure
|
|
154
|
+
|
|
155
|
+
```python
|
|
156
|
+
import gradio as gr
|
|
157
|
+
from transformers import AutoImageProcessor, AutoModelForImageClassification
|
|
158
|
+
import torch
|
|
159
|
+
|
|
160
|
+
# Model loading
|
|
161
|
+
processor = AutoImageProcessor.from_pretrained("model-name")
|
|
162
|
+
model = AutoModelForImageClassification.from_pretrained("model-name").to(device)
|
|
163
|
+
model.train(False)
|
|
164
|
+
|
|
165
|
+
def classify_image(image):
|
|
166
|
+
inputs = processor(images=image, return_tensors="pt").to(device)
|
|
167
|
+
|
|
168
|
+
with torch.no_grad():
|
|
169
|
+
outputs = model(**inputs)
|
|
170
|
+
probs = torch.nn.functional.softmax(outputs.logits, dim=-1)[0]
|
|
171
|
+
|
|
172
|
+
labels = model.config.id2label
|
|
173
|
+
return {labels[i]: float(probs[i]) for i in range(len(labels))}
|
|
174
|
+
|
|
175
|
+
demo = gr.Interface(
|
|
176
|
+
fn=classify_image,
|
|
177
|
+
inputs=gr.Image(type="pil", label="Image"),
|
|
178
|
+
outputs=gr.Label(num_top_classes=5, label="Classification Result"),
|
|
179
|
+
title="Image Classification",
|
|
180
|
+
theme=refined_theme,
|
|
181
|
+
css=css,
|
|
182
|
+
)
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## Image Generation App (`generate`)
|
|
188
|
+
|
|
189
|
+
Diffusion model-based image generation (with LoRA support)
|
|
190
|
+
|
|
191
|
+
### Key Components
|
|
192
|
+
- Style dictionary
|
|
193
|
+
- LoRA loading pattern
|
|
194
|
+
- Grid generation options
|
|
195
|
+
|
|
196
|
+
### Structure
|
|
197
|
+
|
|
198
|
+
```python
|
|
199
|
+
import gradio as gr
|
|
200
|
+
from diffusers import DiffusionPipeline
|
|
201
|
+
import torch
|
|
202
|
+
|
|
203
|
+
# Style presets
|
|
204
|
+
STYLES = {
|
|
205
|
+
"Default": "",
|
|
206
|
+
"Cinematic": "cinematic lighting, dramatic shadows, film grain",
|
|
207
|
+
"Minimal": "minimal, clean, simple composition",
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
# Pipeline loading
|
|
211
|
+
pipe = DiffusionPipeline.from_pretrained(
|
|
212
|
+
"model-name",
|
|
213
|
+
torch_dtype=torch.float16,
|
|
214
|
+
).to(device)
|
|
215
|
+
|
|
216
|
+
# LoRA loading (optional)
|
|
217
|
+
# pipe.load_lora_weights("lora-path")
|
|
218
|
+
|
|
219
|
+
@gpu_decorator
|
|
220
|
+
def generate_image(prompt, style, seed, steps, guidance):
|
|
221
|
+
if seed == -1:
|
|
222
|
+
seed = torch.randint(0, 2**32, (1,)).item()
|
|
223
|
+
|
|
224
|
+
generator = torch.Generator(device=device).manual_seed(seed)
|
|
225
|
+
|
|
226
|
+
full_prompt = f"{prompt}, {STYLES[style]}" if STYLES[style] else prompt
|
|
227
|
+
|
|
228
|
+
image = pipe(
|
|
229
|
+
prompt=full_prompt,
|
|
230
|
+
num_inference_steps=steps,
|
|
231
|
+
guidance_scale=guidance,
|
|
232
|
+
generator=generator,
|
|
233
|
+
).images[0]
|
|
234
|
+
|
|
235
|
+
return image, seed
|
|
236
|
+
|
|
237
|
+
with gr.Blocks(theme=refined_theme, css=css) as demo:
|
|
238
|
+
with gr.Column(elem_id="col-container"):
|
|
239
|
+
gr.Markdown("# Image Generation", elem_id="main-title")
|
|
240
|
+
|
|
241
|
+
prompt = gr.Textbox(label="Prompt", lines=3)
|
|
242
|
+
style = gr.Radio(list(STYLES.keys()), value="Default", label="Style")
|
|
243
|
+
|
|
244
|
+
with gr.Row():
|
|
245
|
+
seed = gr.Number(value=-1, label="Seed (-1 = Random)")
|
|
246
|
+
steps = gr.Slider(10, 50, value=25, step=1, label="Steps")
|
|
247
|
+
guidance = gr.Slider(1, 15, value=7.5, step=0.5, label="Guidance Scale")
|
|
248
|
+
|
|
249
|
+
output = gr.Image(label="Result")
|
|
250
|
+
used_seed = gr.Number(label="Used Seed", interactive=False)
|
|
251
|
+
|
|
252
|
+
submit_btn = gr.Button("Generate", variant="primary")
|
|
253
|
+
submit_btn.click(generate_image, [prompt, style, seed, steps, guidance], [output, used_seed])
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
---
|
|
257
|
+
|
|
258
|
+
## Segmentation App (`segment`)
|
|
259
|
+
|
|
260
|
+
Text prompt-based image segmentation
|
|
261
|
+
|
|
262
|
+
### Key Components
|
|
263
|
+
- `gr.AnnotatedImage`: Segmentation result visualization
|
|
264
|
+
- Confidence Threshold slider
|
|
265
|
+
|
|
266
|
+
### Structure
|
|
267
|
+
|
|
268
|
+
```python
|
|
269
|
+
import gradio as gr
|
|
270
|
+
from transformers import AutoProcessor, AutoModelForMaskGeneration
|
|
271
|
+
|
|
272
|
+
processor = AutoProcessor.from_pretrained("model-name")
|
|
273
|
+
model = AutoModelForMaskGeneration.from_pretrained("model-name").to(device)
|
|
274
|
+
model.train(False)
|
|
275
|
+
|
|
276
|
+
@gpu_decorator
|
|
277
|
+
def segment_image(image, text_prompt, threshold):
|
|
278
|
+
inputs = processor(images=image, text=text_prompt, return_tensors="pt").to(device)
|
|
279
|
+
|
|
280
|
+
with torch.no_grad():
|
|
281
|
+
outputs = model(**inputs)
|
|
282
|
+
|
|
283
|
+
# Mask processing logic
|
|
284
|
+
masks = outputs.pred_masks[0]
|
|
285
|
+
# ...
|
|
286
|
+
|
|
287
|
+
return (image, annotations)
|
|
288
|
+
|
|
289
|
+
with gr.Blocks(theme=refined_theme, css=css) as demo:
|
|
290
|
+
with gr.Column(elem_id="col-container"):
|
|
291
|
+
gr.Markdown("# Image Segmentation", elem_id="main-title")
|
|
292
|
+
|
|
293
|
+
with gr.Row():
|
|
294
|
+
input_image = gr.Image(label="Input Image", type="pil")
|
|
295
|
+
output_image = gr.AnnotatedImage(label="Segmentation Result")
|
|
296
|
+
|
|
297
|
+
text_prompt = gr.Textbox(label="Segmentation Target", placeholder="e.g., person, car, dog")
|
|
298
|
+
threshold = gr.Slider(0.1, 0.9, value=0.5, label="Confidence Threshold")
|
|
299
|
+
|
|
300
|
+
submit_btn = gr.Button("Segment", variant="primary")
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
---
|
|
304
|
+
|
|
305
|
+
## Image Editing App (`edit`)
|
|
306
|
+
|
|
307
|
+
Prompt-based image editing
|
|
308
|
+
|
|
309
|
+
### Key Components
|
|
310
|
+
- Side-by-side input/output image layout
|
|
311
|
+
- LoRA adapter selection Dropdown
|
|
312
|
+
|
|
313
|
+
### Structure
|
|
314
|
+
|
|
315
|
+
```python
|
|
316
|
+
import gradio as gr
|
|
317
|
+
|
|
318
|
+
ADAPTERS = {
|
|
319
|
+
"Default": None,
|
|
320
|
+
"Style A": "adapter-a",
|
|
321
|
+
"Style B": "adapter-b",
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
@gpu_decorator
|
|
325
|
+
def edit_image(image, prompt, adapter_name, strength):
|
|
326
|
+
# Adapter loading
|
|
327
|
+
if ADAPTERS[adapter_name]:
|
|
328
|
+
pipe.load_lora_weights(ADAPTERS[adapter_name])
|
|
329
|
+
|
|
330
|
+
# Editing logic
|
|
331
|
+
result = pipe(
|
|
332
|
+
image=image,
|
|
333
|
+
prompt=prompt,
|
|
334
|
+
strength=strength,
|
|
335
|
+
).images[0]
|
|
336
|
+
|
|
337
|
+
return result
|
|
338
|
+
|
|
339
|
+
with gr.Blocks(theme=refined_theme, css=css) as demo:
|
|
340
|
+
with gr.Column(elem_id="col-container"):
|
|
341
|
+
gr.Markdown("# Image Editing", elem_id="main-title")
|
|
342
|
+
|
|
343
|
+
with gr.Row():
|
|
344
|
+
input_image = gr.Image(label="Original Image", type="pil")
|
|
345
|
+
output_image = gr.Image(label="Edited Result")
|
|
346
|
+
|
|
347
|
+
prompt = gr.Textbox(label="Editing Prompt")
|
|
348
|
+
adapter = gr.Dropdown(list(ADAPTERS.keys()), value="Default", label="Style Adapter")
|
|
349
|
+
strength = gr.Slider(0.1, 1.0, value=0.75, label="Edit Strength")
|
|
350
|
+
|
|
351
|
+
submit_btn = gr.Button("Edit", variant="primary")
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
---
|
|
355
|
+
|
|
356
|
+
## Image Captioning App (`caption`)
|
|
357
|
+
|
|
358
|
+
Image description generation
|
|
359
|
+
|
|
360
|
+
### Key Components
|
|
361
|
+
- Model selection Radio
|
|
362
|
+
- `show_copy_button=True`
|
|
363
|
+
|
|
364
|
+
### Structure
|
|
365
|
+
|
|
366
|
+
```python
|
|
367
|
+
import gradio as gr
|
|
368
|
+
from transformers import AutoProcessor, AutoModelForCausalLM
|
|
369
|
+
|
|
370
|
+
MODELS = {
|
|
371
|
+
"Default": "model-a",
|
|
372
|
+
"Detailed": "model-b",
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
def caption_image(image, model_choice):
|
|
376
|
+
model_name = MODELS[model_choice]
|
|
377
|
+
# Captioning logic
|
|
378
|
+
...
|
|
379
|
+
return caption
|
|
380
|
+
|
|
381
|
+
with gr.Blocks(theme=refined_theme, css=css) as demo:
|
|
382
|
+
with gr.Column(elem_id="col-container"):
|
|
383
|
+
gr.Markdown("# Image Captioning", elem_id="main-title")
|
|
384
|
+
|
|
385
|
+
input_image = gr.Image(label="Image", type="pil")
|
|
386
|
+
model_choice = gr.Radio(list(MODELS.keys()), value="Default", label="Model")
|
|
387
|
+
|
|
388
|
+
output = gr.Textbox(label="Caption", lines=5, show_copy_button=True)
|
|
389
|
+
|
|
390
|
+
submit_btn = gr.Button("Generate Caption", variant="primary")
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
---
|
|
394
|
+
|
|
395
|
+
## Detection App (`detect`)
|
|
396
|
+
|
|
397
|
+
Deepfake, AI-generated image detection, etc.
|
|
398
|
+
|
|
399
|
+
### Key Components
|
|
400
|
+
- Binary classification (Real/Fake)
|
|
401
|
+
- `gr.Label` for probability output
|
|
402
|
+
|
|
403
|
+
### Structure
|
|
404
|
+
|
|
405
|
+
```python
|
|
406
|
+
import gradio as gr
|
|
407
|
+
from transformers import AutoImageProcessor, AutoModelForImageClassification
|
|
408
|
+
|
|
409
|
+
processor = AutoImageProcessor.from_pretrained("model-name")
|
|
410
|
+
model = AutoModelForImageClassification.from_pretrained("model-name").to(device)
|
|
411
|
+
model.train(False)
|
|
412
|
+
|
|
413
|
+
def detect(image):
|
|
414
|
+
inputs = processor(images=image, return_tensors="pt").to(device)
|
|
415
|
+
|
|
416
|
+
with torch.no_grad():
|
|
417
|
+
outputs = model(**inputs)
|
|
418
|
+
probs = torch.nn.functional.softmax(outputs.logits, dim=-1)[0]
|
|
419
|
+
|
|
420
|
+
return {
|
|
421
|
+
"Real": float(probs[0]),
|
|
422
|
+
"Fake": float(probs[1]),
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
demo = gr.Interface(
|
|
426
|
+
fn=detect,
|
|
427
|
+
inputs=gr.Image(type="pil", label="Image"),
|
|
428
|
+
outputs=gr.Label(label="Detection Result"),
|
|
429
|
+
title="Deepfake Detection",
|
|
430
|
+
theme=refined_theme,
|
|
431
|
+
css=css,
|
|
432
|
+
)
|
|
433
|
+
```
|