@haposoft/cafekit 0.13.4 → 0.14.1
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/README.md +1 -2
- package/bin/lib/i18n.js +2 -2
- package/bin/lib/manifest.js +15 -0
- package/bin/lib/opencode-install.js +0 -14
- package/bin/phases/claude-runtime.js +4 -1
- package/bin/phases/claude-settings.js +38 -7
- package/package.json +1 -1
- package/src/claude/agents/ui-ux-designer.md +4 -4
- package/src/claude/hooks/__tests__/privacy-block.test.js +79 -0
- package/src/claude/hooks/__tests__/session-writeenv.test.js +68 -0
- package/src/claude/hooks/__tests__/spec-gate.test.js +270 -0
- package/src/claude/hooks/privacy-block.cjs +22 -2
- package/src/claude/hooks/session.cjs +5 -1
- package/src/claude/hooks/spec-gate.cjs +173 -0
- package/src/claude/hooks/spec-state.cjs +10 -17
- package/src/claude/hooks/task-scaffold-guard.cjs +4 -2
- package/src/claude/migration-manifest.json +5 -4
- package/src/claude/rules/skill-domain-routing.md +2 -3
- package/src/claude/rules/skill-workflow-routing.md +2 -3
- package/src/claude/rules/state-sync.md +4 -0
- package/src/claude/runtime.json +4 -0
- package/src/claude/scripts/validate-docs.cjs +4 -7
- package/src/claude/scripts/validate-spec-output.cjs +29 -9
- package/src/claude/settings/settings.json +4 -0
- package/src/claude/skills/ai-multimodal/.env.example +11 -13
- package/src/claude/skills/ai-multimodal/SKILL.md +1 -1
- package/src/claude/skills/ai-multimodal/references/audio-processing.md +25 -27
- package/src/claude/skills/ai-multimodal/references/video-analysis.md +23 -27
- package/src/claude/skills/ai-multimodal/references/vision-understanding.md +26 -26
- package/src/claude/skills/ai-multimodal/scripts/check_setup.py +1 -1
- package/src/claude/skills/ai-multimodal/scripts/gemini_batch_process.py +7 -9
- package/src/claude/skills/brainstorm/SKILL.md +1 -2
- package/src/claude/skills/docx/SKILL.md +1 -1
- package/src/claude/skills/frontend-design/SKILL.md +1 -1
- package/src/claude/skills/frontend-design/references/ai-multimodal-overview.md +4 -4
- package/src/claude/skills/frontend-design/references/analysis-techniques.md +3 -3
- package/src/claude/skills/frontend-design/references/asset-generation.md +2 -2
- package/src/claude/skills/frontend-design/references/design-extraction-overview.md +4 -4
- package/src/claude/skills/frontend-design/references/extraction-best-practices.md +3 -3
- package/src/claude/skills/frontend-design/references/technical-accessibility.md +1 -1
- package/src/claude/skills/frontend-design/references/technical-optimization.md +1 -1
- package/src/claude/skills/frontend-design/references/technical-overview.md +2 -2
- package/src/claude/skills/frontend-design/references/technical-workflows.md +6 -6
- package/src/claude/skills/frontend-design/references/visual-analysis-overview.md +3 -3
- package/src/claude/skills/inspect/SKILL.md +3 -3
- package/src/claude/skills/inspect/references/external-gemini-inspection.md +9 -9
- package/src/claude/skills/pdf/SKILL.md +1 -1
- package/src/claude/skills/pptx/SKILL.md +1 -1
- package/src/claude/skills/specs/SKILL.md +1 -1
- package/src/claude/skills/xlsx/SKILL.md +1 -1
- package/src/opencode/AGENTS.md +1 -2
- package/src/opencode/plugins/session.ts +2 -2
- package/src/opencode/plugins/spec-state.ts +244 -0
- package/src/opencode/plugins/task-scaffold-guard.ts +161 -0
- package/src/claude/scripts/browser-tool.cjs +0 -138
- package/src/claude/skills/generate-graph/LICENSE +0 -21
- package/src/claude/skills/generate-graph/README.md +0 -523
- package/src/claude/skills/generate-graph/SKILL.md +0 -429
- package/src/claude/skills/generate-graph/agentloop-core.svg +0 -101
- package/src/claude/skills/generate-graph/agents/openai.yaml +0 -4
- package/src/claude/skills/generate-graph/assets/samples/sample-style1-flat.png +0 -0
- package/src/claude/skills/generate-graph/assets/samples/sample-style2-dark.png +0 -0
- package/src/claude/skills/generate-graph/assets/samples/sample-style3-blueprint.png +0 -0
- package/src/claude/skills/generate-graph/assets/samples/sample-style4-notion.png +0 -0
- package/src/claude/skills/generate-graph/assets/samples/sample-style5-glass.png +0 -0
- package/src/claude/skills/generate-graph/assets/samples/sample-style6-claude.png +0 -0
- package/src/claude/skills/generate-graph/assets/samples/sample-style7-openai.png +0 -0
- package/src/claude/skills/generate-graph/fixtures/agent-memory-types-style4.json +0 -181
- package/src/claude/skills/generate-graph/fixtures/api-flow-style7.json +0 -40
- package/src/claude/skills/generate-graph/fixtures/mem0-style1.json +0 -297
- package/src/claude/skills/generate-graph/fixtures/microservices-style3.json +0 -64
- package/src/claude/skills/generate-graph/fixtures/multi-agent-style5.json +0 -45
- package/src/claude/skills/generate-graph/fixtures/system-architecture-style6.json +0 -48
- package/src/claude/skills/generate-graph/fixtures/tool-call-style2.json +0 -182
- package/src/claude/skills/generate-graph/package.json +0 -42
- package/src/claude/skills/generate-graph/references/icons.md +0 -281
- package/src/claude/skills/generate-graph/references/style-1-flat-icon.md +0 -108
- package/src/claude/skills/generate-graph/references/style-2-dark-terminal.md +0 -107
- package/src/claude/skills/generate-graph/references/style-3-blueprint.md +0 -113
- package/src/claude/skills/generate-graph/references/style-4-notion-clean.md +0 -94
- package/src/claude/skills/generate-graph/references/style-5-glassmorphism.md +0 -125
- package/src/claude/skills/generate-graph/references/style-6-claude-official.md +0 -209
- package/src/claude/skills/generate-graph/references/style-7-openai.md +0 -215
- package/src/claude/skills/generate-graph/references/style-diagram-matrix.md +0 -135
- package/src/claude/skills/generate-graph/references/svg-layout-best-practices.md +0 -100
- package/src/claude/skills/generate-graph/scripts/generate-diagram.sh +0 -157
- package/src/claude/skills/generate-graph/scripts/generate-from-template.py +0 -1556
- package/src/claude/skills/generate-graph/scripts/test-all-styles.sh +0 -135
- package/src/claude/skills/generate-graph/scripts/validate-svg.sh +0 -292
- package/src/claude/skills/generate-graph/templates/agent-architecture.svg +0 -28
- package/src/claude/skills/generate-graph/templates/architecture.svg +0 -23
- package/src/claude/skills/generate-graph/templates/comparison-matrix.svg +0 -14
- package/src/claude/skills/generate-graph/templates/data-flow.svg +0 -28
- package/src/claude/skills/generate-graph/templates/er-diagram.svg +0 -21
- package/src/claude/skills/generate-graph/templates/flowchart.svg +0 -21
- package/src/claude/skills/generate-graph/templates/sequence.svg +0 -20
- package/src/claude/skills/generate-graph/templates/state-machine.svg +0 -20
- package/src/claude/skills/generate-graph/templates/timeline.svg +0 -19
- package/src/claude/skills/generate-graph/templates/use-case.svg +0 -21
- package/src/claude/skills/impact-analysis/SKILL.md +0 -276
- package/src/claude/skills/impact-analysis/references/change-detection.md +0 -270
- package/src/claude/skills/impact-analysis/references/dependency-scouting.md +0 -338
- package/src/claude/skills/impact-analysis/references/edge-case-identification.md +0 -439
- package/src/claude/skills/impact-analysis/references/industry-techniques.md +0 -695
- package/src/claude/skills/impact-analysis/references/practical-techniques-guide.md +0 -753
- package/src/claude/skills/impact-analysis/references/project-detection.md +0 -704
- package/src/claude/skills/impact-analysis/references/react-native-customization.md +0 -508
- package/src/claude/skills/impact-analysis/references/report-template.md +0 -604
- package/src/claude/skills/impact-analysis/references/test-scenario-generation.md +0 -459
- package/src/claude/skills/impact-analysis/scripts/README.md +0 -476
- package/src/claude/skills/impact-analysis/scripts/ast-analyze.js +0 -403
- package/src/claude/skills/impact-analysis/scripts/calculate-risk.js +0 -475
- package/src/claude/skills/impact-analysis/scripts/find-dependencies.sh +0 -202
- package/src/claude/skills/impact-analysis/scripts/run-analysis.sh +0 -312
|
@@ -42,7 +42,7 @@ myfile = client.files.upload(file='meeting.mp3')
|
|
|
42
42
|
|
|
43
43
|
# Transcribe
|
|
44
44
|
response = client.models.generate_content(
|
|
45
|
-
model='
|
|
45
|
+
model='gemma-4-31b-it',
|
|
46
46
|
contents=['Generate a transcript of the speech.', myfile]
|
|
47
47
|
)
|
|
48
48
|
print(response.text)
|
|
@@ -52,7 +52,7 @@ print(response.text)
|
|
|
52
52
|
|
|
53
53
|
```python
|
|
54
54
|
response = client.models.generate_content(
|
|
55
|
-
model='
|
|
55
|
+
model='gemma-4-31b-it',
|
|
56
56
|
contents=['Generate transcript with timestamps in MM:SS format.', myfile]
|
|
57
57
|
)
|
|
58
58
|
```
|
|
@@ -61,7 +61,7 @@ response = client.models.generate_content(
|
|
|
61
61
|
|
|
62
62
|
```python
|
|
63
63
|
response = client.models.generate_content(
|
|
64
|
-
model='
|
|
64
|
+
model='gemma-4-31b-it',
|
|
65
65
|
contents=['Transcribe with speaker labels. Format: [Speaker 1], [Speaker 2], etc.', myfile]
|
|
66
66
|
)
|
|
67
67
|
```
|
|
@@ -70,7 +70,7 @@ response = client.models.generate_content(
|
|
|
70
70
|
|
|
71
71
|
```python
|
|
72
72
|
response = client.models.generate_content(
|
|
73
|
-
model='
|
|
73
|
+
model='gemma-4-31b-it',
|
|
74
74
|
contents=['Transcribe only the segment from 02:30 to 05:15.', myfile]
|
|
75
75
|
)
|
|
76
76
|
```
|
|
@@ -81,7 +81,7 @@ response = client.models.generate_content(
|
|
|
81
81
|
|
|
82
82
|
```python
|
|
83
83
|
response = client.models.generate_content(
|
|
84
|
-
model='
|
|
84
|
+
model='gemma-4-31b-it',
|
|
85
85
|
contents=['Summarize key points in 5 bullets with timestamps.', myfile]
|
|
86
86
|
)
|
|
87
87
|
```
|
|
@@ -91,19 +91,19 @@ response = client.models.generate_content(
|
|
|
91
91
|
```python
|
|
92
92
|
# Music analysis
|
|
93
93
|
response = client.models.generate_content(
|
|
94
|
-
model='
|
|
94
|
+
model='gemma-4-31b-it',
|
|
95
95
|
contents=['Identify the musical instruments and genre.', myfile]
|
|
96
96
|
)
|
|
97
97
|
|
|
98
98
|
# Environmental sounds
|
|
99
99
|
response = client.models.generate_content(
|
|
100
|
-
model='
|
|
100
|
+
model='gemma-4-31b-it',
|
|
101
101
|
contents=['Identify all sounds: voices, music, ambient noise.', myfile]
|
|
102
102
|
)
|
|
103
103
|
|
|
104
104
|
# Birdsong identification
|
|
105
105
|
response = client.models.generate_content(
|
|
106
|
-
model='
|
|
106
|
+
model='gemma-4-31b-it',
|
|
107
107
|
contents=['Identify bird species based on their calls.', myfile]
|
|
108
108
|
)
|
|
109
109
|
```
|
|
@@ -112,7 +112,7 @@ response = client.models.generate_content(
|
|
|
112
112
|
|
|
113
113
|
```python
|
|
114
114
|
response = client.models.generate_content(
|
|
115
|
-
model='
|
|
115
|
+
model='gemma-4-31b-it',
|
|
116
116
|
contents=['What is discussed from 10:30 to 15:45? Provide key points.', myfile]
|
|
117
117
|
)
|
|
118
118
|
```
|
|
@@ -127,13 +127,13 @@ myfile = client.files.upload(file='large-audio.mp3')
|
|
|
127
127
|
|
|
128
128
|
# First query
|
|
129
129
|
response1 = client.models.generate_content(
|
|
130
|
-
model='
|
|
130
|
+
model='gemma-4-31b-it',
|
|
131
131
|
contents=['Transcribe this', myfile]
|
|
132
132
|
)
|
|
133
133
|
|
|
134
134
|
# Second query (reuses same file)
|
|
135
135
|
response2 = client.models.generate_content(
|
|
136
|
-
model='
|
|
136
|
+
model='gemma-4-31b-it',
|
|
137
137
|
contents=['Summarize this', myfile]
|
|
138
138
|
)
|
|
139
139
|
```
|
|
@@ -147,7 +147,7 @@ with open('small-audio.mp3', 'rb') as f:
|
|
|
147
147
|
audio_bytes = f.read()
|
|
148
148
|
|
|
149
149
|
response = client.models.generate_content(
|
|
150
|
-
model='
|
|
150
|
+
model='gemma-4-31b-it',
|
|
151
151
|
contents=[
|
|
152
152
|
'Describe this audio',
|
|
153
153
|
types.Part.from_bytes(data=audio_bytes, mime_type='audio/mp3')
|
|
@@ -161,14 +161,14 @@ response = client.models.generate_content(
|
|
|
161
161
|
|
|
162
162
|
| Model | Quality | Speed | Cost/1M tokens |
|
|
163
163
|
|-------|---------|-------|----------------|
|
|
164
|
-
| `
|
|
165
|
-
| `
|
|
164
|
+
| `gemma-4-31b-it-native-audio-preview-09-2025` | High | Fast | $10 |
|
|
165
|
+
| `gemma-4-31b-it` TTS mode | Premium | Slower | $20 |
|
|
166
166
|
|
|
167
167
|
### Basic TTS
|
|
168
168
|
|
|
169
169
|
```python
|
|
170
170
|
response = client.models.generate_content(
|
|
171
|
-
model='
|
|
171
|
+
model='gemma-4-31b-it-native-audio-preview-09-2025',
|
|
172
172
|
contents='Generate audio: Welcome to today\'s episode.'
|
|
173
173
|
)
|
|
174
174
|
|
|
@@ -182,19 +182,19 @@ with open('output.wav', 'wb') as f:
|
|
|
182
182
|
```python
|
|
183
183
|
# Professional tone
|
|
184
184
|
response = client.models.generate_content(
|
|
185
|
-
model='
|
|
185
|
+
model='gemma-4-31b-it-native-audio-preview-09-2025',
|
|
186
186
|
contents='Generate audio in a professional, clear tone: Welcome to our quarterly earnings call.'
|
|
187
187
|
)
|
|
188
188
|
|
|
189
189
|
# Casual and friendly
|
|
190
190
|
response = client.models.generate_content(
|
|
191
|
-
model='
|
|
191
|
+
model='gemma-4-31b-it-native-audio-preview-09-2025',
|
|
192
192
|
contents='Generate audio in a friendly, conversational tone: Hey there! Let\'s dive into today\'s topic.'
|
|
193
193
|
)
|
|
194
194
|
|
|
195
195
|
# Narrative style
|
|
196
196
|
response = client.models.generate_content(
|
|
197
|
-
model='
|
|
197
|
+
model='gemma-4-31b-it-native-audio-preview-09-2025',
|
|
198
198
|
contents='Generate audio in a narrative, storytelling tone: Once upon a time, in a land far away...'
|
|
199
199
|
)
|
|
200
200
|
```
|
|
@@ -244,9 +244,7 @@ response = client.models.generate_content(
|
|
|
244
244
|
- 9.5 hours = 1,094,400 tokens
|
|
245
245
|
|
|
246
246
|
**Model selection**:
|
|
247
|
-
- Use `
|
|
248
|
-
- Upgrade to `gemini-2.5-pro` ($3/1M tokens) for complex analysis
|
|
249
|
-
- For high-volume: `gemini-1.5-flash` ($0.70/1M tokens)
|
|
247
|
+
- Use `gemma-4-31b-it` for transcription and analysis (read model from `.claude/runtime.json`: `gemini.model`)
|
|
250
248
|
|
|
251
249
|
**Reduce costs**:
|
|
252
250
|
- Process only relevant segments using timestamps
|
|
@@ -265,7 +263,7 @@ def transcribe_with_retry(file_path, max_retries=3):
|
|
|
265
263
|
try:
|
|
266
264
|
myfile = client.files.upload(file=file_path)
|
|
267
265
|
response = client.models.generate_content(
|
|
268
|
-
model='
|
|
266
|
+
model='gemma-4-31b-it',
|
|
269
267
|
contents=['Transcribe with timestamps', myfile]
|
|
270
268
|
)
|
|
271
269
|
return response.text
|
|
@@ -283,7 +281,7 @@ def transcribe_with_retry(file_path, max_retries=3):
|
|
|
283
281
|
|
|
284
282
|
```python
|
|
285
283
|
response = client.models.generate_content(
|
|
286
|
-
model='
|
|
284
|
+
model='gemma-4-31b-it',
|
|
287
285
|
contents=[
|
|
288
286
|
'''Transcribe this meeting with:
|
|
289
287
|
1. Speaker labels
|
|
@@ -299,7 +297,7 @@ response = client.models.generate_content(
|
|
|
299
297
|
|
|
300
298
|
```python
|
|
301
299
|
response = client.models.generate_content(
|
|
302
|
-
model='
|
|
300
|
+
model='gemma-4-31b-it',
|
|
303
301
|
contents=[
|
|
304
302
|
'''Create podcast summary with:
|
|
305
303
|
1. Main topics with timestamps
|
|
@@ -315,7 +313,7 @@ response = client.models.generate_content(
|
|
|
315
313
|
|
|
316
314
|
```python
|
|
317
315
|
response = client.models.generate_content(
|
|
318
|
-
model='
|
|
316
|
+
model='gemma-4-31b-it',
|
|
319
317
|
contents=[
|
|
320
318
|
'''Analyze interview:
|
|
321
319
|
1. Questions asked with timestamps
|
|
@@ -331,7 +329,7 @@ response = client.models.generate_content(
|
|
|
331
329
|
|
|
332
330
|
```python
|
|
333
331
|
response = client.models.generate_content(
|
|
334
|
-
model='
|
|
332
|
+
model='gemma-4-31b-it',
|
|
335
333
|
contents=[
|
|
336
334
|
'''Verify audio content:
|
|
337
335
|
1. Check for specific keywords or phrases
|
|
@@ -348,7 +346,7 @@ response = client.models.generate_content(
|
|
|
348
346
|
```python
|
|
349
347
|
# Gemini auto-detects language
|
|
350
348
|
response = client.models.generate_content(
|
|
351
|
-
model='
|
|
349
|
+
model='gemma-4-31b-it',
|
|
352
350
|
contents=['Transcribe this audio and translate to English if needed.', myfile]
|
|
353
351
|
)
|
|
354
352
|
```
|
|
@@ -22,12 +22,8 @@ Comprehensive guide for video understanding, temporal analysis, and YouTube proc
|
|
|
22
22
|
|
|
23
23
|
## Model Selection
|
|
24
24
|
|
|
25
|
-
###
|
|
26
|
-
- **
|
|
27
|
-
|
|
28
|
-
### Gemini 2.5 Series (Recommended)
|
|
29
|
-
- **gemini-2.5-pro**: Best quality, 1M-2M context
|
|
30
|
-
- **gemini-2.5-flash**: Balanced, 1M-2M context (recommended)
|
|
25
|
+
### Recommended
|
|
26
|
+
- **gemma-4-31b-it**: 1M-2M context, balanced quality/speed (read model from `.claude/runtime.json`: `gemini.model`)
|
|
31
27
|
|
|
32
28
|
### Context Windows
|
|
33
29
|
- **2M token models**: ~2 hours (default) or ~6 hours (low-res)
|
|
@@ -57,7 +53,7 @@ if myfile.state.name == 'FAILED':
|
|
|
57
53
|
|
|
58
54
|
# Analyze
|
|
59
55
|
response = client.models.generate_content(
|
|
60
|
-
model='
|
|
56
|
+
model='gemma-4-31b-it',
|
|
61
57
|
contents=['Summarize this video in 3 key points', myfile]
|
|
62
58
|
)
|
|
63
59
|
print(response.text)
|
|
@@ -69,7 +65,7 @@ print(response.text)
|
|
|
69
65
|
from google.genai import types
|
|
70
66
|
|
|
71
67
|
response = client.models.generate_content(
|
|
72
|
-
model='
|
|
68
|
+
model='gemma-4-31b-it',
|
|
73
69
|
contents=[
|
|
74
70
|
'Summarize the main topics discussed',
|
|
75
71
|
types.Part.from_uri(
|
|
@@ -87,7 +83,7 @@ with open('short-clip.mp4', 'rb') as f:
|
|
|
87
83
|
video_bytes = f.read()
|
|
88
84
|
|
|
89
85
|
response = client.models.generate_content(
|
|
90
|
-
model='
|
|
86
|
+
model='gemma-4-31b-it',
|
|
91
87
|
contents=[
|
|
92
88
|
'What happens in this video?',
|
|
93
89
|
types.Part.from_bytes(data=video_bytes, mime_type='video/mp4')
|
|
@@ -102,7 +98,7 @@ response = client.models.generate_content(
|
|
|
102
98
|
```python
|
|
103
99
|
# Analyze specific time range
|
|
104
100
|
response = client.models.generate_content(
|
|
105
|
-
model='
|
|
101
|
+
model='gemma-4-31b-it',
|
|
106
102
|
contents=[
|
|
107
103
|
'Summarize this segment',
|
|
108
104
|
types.Part.from_video_metadata(
|
|
@@ -119,7 +115,7 @@ response = client.models.generate_content(
|
|
|
119
115
|
```python
|
|
120
116
|
# Lower FPS for static content (saves tokens)
|
|
121
117
|
response = client.models.generate_content(
|
|
122
|
-
model='
|
|
118
|
+
model='gemma-4-31b-it',
|
|
123
119
|
contents=[
|
|
124
120
|
'Analyze this presentation',
|
|
125
121
|
types.Part.from_video_metadata(
|
|
@@ -131,7 +127,7 @@ response = client.models.generate_content(
|
|
|
131
127
|
|
|
132
128
|
# Higher FPS for fast-moving content
|
|
133
129
|
response = client.models.generate_content(
|
|
134
|
-
model='
|
|
130
|
+
model='gemma-4-31b-it',
|
|
135
131
|
contents=[
|
|
136
132
|
'Analyze rapid movements in this sports video',
|
|
137
133
|
types.Part.from_video_metadata(
|
|
@@ -155,7 +151,7 @@ for video in [video1, video2]:
|
|
|
155
151
|
video = client.files.get(name=video.name)
|
|
156
152
|
|
|
157
153
|
response = client.models.generate_content(
|
|
158
|
-
model='
|
|
154
|
+
model='gemma-4-31b-it',
|
|
159
155
|
contents=[
|
|
160
156
|
'Compare these two product demos. Which explains features better?',
|
|
161
157
|
video1,
|
|
@@ -170,7 +166,7 @@ response = client.models.generate_content(
|
|
|
170
166
|
|
|
171
167
|
```python
|
|
172
168
|
response = client.models.generate_content(
|
|
173
|
-
model='
|
|
169
|
+
model='gemma-4-31b-it',
|
|
174
170
|
contents=[
|
|
175
171
|
'What happens at 01:15 and how does it relate to 02:30?',
|
|
176
172
|
myfile
|
|
@@ -182,7 +178,7 @@ response = client.models.generate_content(
|
|
|
182
178
|
|
|
183
179
|
```python
|
|
184
180
|
response = client.models.generate_content(
|
|
185
|
-
model='
|
|
181
|
+
model='gemma-4-31b-it',
|
|
186
182
|
contents=[
|
|
187
183
|
'''Create a timeline with timestamps:
|
|
188
184
|
- Key events
|
|
@@ -199,7 +195,7 @@ response = client.models.generate_content(
|
|
|
199
195
|
|
|
200
196
|
```python
|
|
201
197
|
response = client.models.generate_content(
|
|
202
|
-
model='
|
|
198
|
+
model='gemma-4-31b-it',
|
|
203
199
|
contents=[
|
|
204
200
|
'Identify all scene changes with timestamps and describe each scene',
|
|
205
201
|
myfile
|
|
@@ -213,7 +209,7 @@ response = client.models.generate_content(
|
|
|
213
209
|
|
|
214
210
|
```python
|
|
215
211
|
response = client.models.generate_content(
|
|
216
|
-
model='
|
|
212
|
+
model='gemma-4-31b-it',
|
|
217
213
|
contents=[
|
|
218
214
|
'Transcribe the audio from this video',
|
|
219
215
|
myfile
|
|
@@ -225,7 +221,7 @@ response = client.models.generate_content(
|
|
|
225
221
|
|
|
226
222
|
```python
|
|
227
223
|
response = client.models.generate_content(
|
|
228
|
-
model='
|
|
224
|
+
model='gemma-4-31b-it',
|
|
229
225
|
contents=[
|
|
230
226
|
'''Transcribe with visual context:
|
|
231
227
|
- Audio transcription
|
|
@@ -241,7 +237,7 @@ response = client.models.generate_content(
|
|
|
241
237
|
|
|
242
238
|
```python
|
|
243
239
|
response = client.models.generate_content(
|
|
244
|
-
model='
|
|
240
|
+
model='gemma-4-31b-it',
|
|
245
241
|
contents=[
|
|
246
242
|
'Transcribe with speaker labels and timestamps',
|
|
247
243
|
myfile
|
|
@@ -255,7 +251,7 @@ response = client.models.generate_content(
|
|
|
255
251
|
|
|
256
252
|
```python
|
|
257
253
|
response = client.models.generate_content(
|
|
258
|
-
model='
|
|
254
|
+
model='gemma-4-31b-it',
|
|
259
255
|
contents=[
|
|
260
256
|
'''Summarize this video:
|
|
261
257
|
1. Main topic and purpose
|
|
@@ -271,7 +267,7 @@ response = client.models.generate_content(
|
|
|
271
267
|
|
|
272
268
|
```python
|
|
273
269
|
response = client.models.generate_content(
|
|
274
|
-
model='
|
|
270
|
+
model='gemma-4-31b-it',
|
|
275
271
|
contents=[
|
|
276
272
|
'''Create educational materials:
|
|
277
273
|
1. List key concepts taught
|
|
@@ -287,7 +283,7 @@ response = client.models.generate_content(
|
|
|
287
283
|
|
|
288
284
|
```python
|
|
289
285
|
response = client.models.generate_content(
|
|
290
|
-
model='
|
|
286
|
+
model='gemma-4-31b-it',
|
|
291
287
|
contents=[
|
|
292
288
|
'List all actions performed in this tutorial with timestamps',
|
|
293
289
|
myfile
|
|
@@ -299,7 +295,7 @@ response = client.models.generate_content(
|
|
|
299
295
|
|
|
300
296
|
```python
|
|
301
297
|
response = client.models.generate_content(
|
|
302
|
-
model='
|
|
298
|
+
model='gemma-4-31b-it',
|
|
303
299
|
contents=[
|
|
304
300
|
'''Review video content:
|
|
305
301
|
1. Identify any problematic content
|
|
@@ -315,7 +311,7 @@ response = client.models.generate_content(
|
|
|
315
311
|
|
|
316
312
|
```python
|
|
317
313
|
response = client.models.generate_content(
|
|
318
|
-
model='
|
|
314
|
+
model='gemma-4-31b-it',
|
|
319
315
|
contents=[
|
|
320
316
|
'''Analyze interview:
|
|
321
317
|
1. Questions asked (timestamps)
|
|
@@ -332,7 +328,7 @@ response = client.models.generate_content(
|
|
|
332
328
|
|
|
333
329
|
```python
|
|
334
330
|
response = client.models.generate_content(
|
|
335
|
-
model='
|
|
331
|
+
model='gemma-4-31b-it',
|
|
336
332
|
contents=[
|
|
337
333
|
'''Analyze sports video:
|
|
338
334
|
1. Key plays with timestamps
|
|
@@ -362,7 +358,7 @@ response = client.models.generate_content(
|
|
|
362
358
|
youtube_uri = 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'
|
|
363
359
|
|
|
364
360
|
response = client.models.generate_content(
|
|
365
|
-
model='
|
|
361
|
+
model='gemma-4-31b-it',
|
|
366
362
|
contents=[
|
|
367
363
|
'Create chapter markers with timestamps',
|
|
368
364
|
types.Part.from_uri(uri=youtube_uri, mime_type='video/mp4')
|
|
@@ -444,7 +440,7 @@ class VideoAnalysis(BaseModel):
|
|
|
444
440
|
duration: str
|
|
445
441
|
|
|
446
442
|
response = client.models.generate_content(
|
|
447
|
-
model='
|
|
443
|
+
model='gemma-4-31b-it',
|
|
448
444
|
contents=['Analyze this video', myfile],
|
|
449
445
|
config=genai.types.GenerateContentConfig(
|
|
450
446
|
response_mime_type='application/json',
|
|
@@ -25,9 +25,9 @@ Comprehensive guide for image analysis, object detection, and visual understandi
|
|
|
25
25
|
## Model Selection
|
|
26
26
|
|
|
27
27
|
### Gemini 2.5 Series
|
|
28
|
-
- **
|
|
29
|
-
- **
|
|
30
|
-
- **
|
|
28
|
+
- **gemma-4-31b-it**: Best quality, segmentation + detection
|
|
29
|
+
- **gemma-4-31b-it**: Fast, efficient, all features
|
|
30
|
+
- **gemma-4-31b-it-lite**: Lightweight, all features
|
|
31
31
|
|
|
32
32
|
### Feature Requirements
|
|
33
33
|
- **Segmentation**: Requires 2.5+ models
|
|
@@ -49,7 +49,7 @@ with open('image.jpg', 'rb') as f:
|
|
|
49
49
|
img_bytes = f.read()
|
|
50
50
|
|
|
51
51
|
response = client.models.generate_content(
|
|
52
|
-
model='
|
|
52
|
+
model='gemma-4-31b-it',
|
|
53
53
|
contents=[
|
|
54
54
|
'Describe this image in detail',
|
|
55
55
|
genai.types.Part.from_bytes(data=img_bytes, mime_type='image/jpeg')
|
|
@@ -62,7 +62,7 @@ print(response.text)
|
|
|
62
62
|
|
|
63
63
|
```python
|
|
64
64
|
response = client.models.generate_content(
|
|
65
|
-
model='
|
|
65
|
+
model='gemma-4-31b-it',
|
|
66
66
|
contents=[
|
|
67
67
|
'Classify this image. Provide category and confidence level.',
|
|
68
68
|
img_part
|
|
@@ -74,7 +74,7 @@ response = client.models.generate_content(
|
|
|
74
74
|
|
|
75
75
|
```python
|
|
76
76
|
response = client.models.generate_content(
|
|
77
|
-
model='
|
|
77
|
+
model='gemma-4-31b-it',
|
|
78
78
|
contents=[
|
|
79
79
|
'How many people are in this image and what are they doing?',
|
|
80
80
|
img_part
|
|
@@ -88,7 +88,7 @@ response = client.models.generate_content(
|
|
|
88
88
|
|
|
89
89
|
```python
|
|
90
90
|
response = client.models.generate_content(
|
|
91
|
-
model='
|
|
91
|
+
model='gemma-4-31b-it',
|
|
92
92
|
contents=[
|
|
93
93
|
'Detect all objects in this image and provide bounding boxes',
|
|
94
94
|
img_part
|
|
@@ -103,7 +103,7 @@ response = client.models.generate_content(
|
|
|
103
103
|
|
|
104
104
|
```python
|
|
105
105
|
response = client.models.generate_content(
|
|
106
|
-
model='
|
|
106
|
+
model='gemma-4-31b-it',
|
|
107
107
|
contents=[
|
|
108
108
|
'Create a segmentation mask for all people in this image',
|
|
109
109
|
img_part
|
|
@@ -122,7 +122,7 @@ img1 = PIL.Image.open('photo1.jpg')
|
|
|
122
122
|
img2 = PIL.Image.open('photo2.jpg')
|
|
123
123
|
|
|
124
124
|
response = client.models.generate_content(
|
|
125
|
-
model='
|
|
125
|
+
model='gemma-4-31b-it',
|
|
126
126
|
contents=[
|
|
127
127
|
'Compare these two images. What are the differences?',
|
|
128
128
|
img1,
|
|
@@ -135,7 +135,7 @@ response = client.models.generate_content(
|
|
|
135
135
|
|
|
136
136
|
```python
|
|
137
137
|
response = client.models.generate_content(
|
|
138
|
-
model='
|
|
138
|
+
model='gemma-4-31b-it',
|
|
139
139
|
contents=[
|
|
140
140
|
'Extract all visible text from this image',
|
|
141
141
|
img_part
|
|
@@ -155,7 +155,7 @@ with open('image.jpg', 'rb') as f:
|
|
|
155
155
|
img_bytes = f.read()
|
|
156
156
|
|
|
157
157
|
response = client.models.generate_content(
|
|
158
|
-
model='
|
|
158
|
+
model='gemma-4-31b-it',
|
|
159
159
|
contents=[
|
|
160
160
|
'Analyze this image',
|
|
161
161
|
types.Part.from_bytes(data=img_bytes, mime_type='image/jpeg')
|
|
@@ -171,7 +171,7 @@ import PIL.Image
|
|
|
171
171
|
img = PIL.Image.open('photo.jpg')
|
|
172
172
|
|
|
173
173
|
response = client.models.generate_content(
|
|
174
|
-
model='
|
|
174
|
+
model='gemma-4-31b-it',
|
|
175
175
|
contents=['What is in this image?', img]
|
|
176
176
|
)
|
|
177
177
|
```
|
|
@@ -184,12 +184,12 @@ myfile = client.files.upload(file='large-image.jpg')
|
|
|
184
184
|
|
|
185
185
|
# Use multiple times
|
|
186
186
|
response1 = client.models.generate_content(
|
|
187
|
-
model='
|
|
187
|
+
model='gemma-4-31b-it',
|
|
188
188
|
contents=['Describe this image', myfile]
|
|
189
189
|
)
|
|
190
190
|
|
|
191
191
|
response2 = client.models.generate_content(
|
|
192
|
-
model='
|
|
192
|
+
model='gemma-4-31b-it',
|
|
193
193
|
contents=['What colors dominate this image?', myfile]
|
|
194
194
|
)
|
|
195
195
|
```
|
|
@@ -198,7 +198,7 @@ response2 = client.models.generate_content(
|
|
|
198
198
|
|
|
199
199
|
```python
|
|
200
200
|
response = client.models.generate_content(
|
|
201
|
-
model='
|
|
201
|
+
model='gemma-4-31b-it',
|
|
202
202
|
contents=[
|
|
203
203
|
'Analyze this image',
|
|
204
204
|
types.Part.from_uri(
|
|
@@ -250,7 +250,7 @@ class ImageAnalysis(BaseModel):
|
|
|
250
250
|
scene_type: str
|
|
251
251
|
|
|
252
252
|
response = client.models.generate_content(
|
|
253
|
-
model='
|
|
253
|
+
model='gemma-4-31b-it',
|
|
254
254
|
contents=['Analyze this image', img_part],
|
|
255
255
|
config=genai.types.GenerateContentConfig(
|
|
256
256
|
response_mime_type='application/json',
|
|
@@ -272,7 +272,7 @@ images = [
|
|
|
272
272
|
]
|
|
273
273
|
|
|
274
274
|
response = client.models.generate_content(
|
|
275
|
-
model='
|
|
275
|
+
model='gemma-4-31b-it',
|
|
276
276
|
contents=['Analyze these images and find common themes'] + images
|
|
277
277
|
)
|
|
278
278
|
```
|
|
@@ -284,7 +284,7 @@ before = PIL.Image.open('before.jpg')
|
|
|
284
284
|
after = PIL.Image.open('after.jpg')
|
|
285
285
|
|
|
286
286
|
response = client.models.generate_content(
|
|
287
|
-
model='
|
|
287
|
+
model='gemma-4-31b-it',
|
|
288
288
|
contents=[
|
|
289
289
|
'Compare before and after. List all visible changes.',
|
|
290
290
|
before,
|
|
@@ -300,7 +300,7 @@ reference = PIL.Image.open('target.jpg')
|
|
|
300
300
|
candidates = [PIL.Image.open(f'option{i}.jpg') for i in range(5)]
|
|
301
301
|
|
|
302
302
|
response = client.models.generate_content(
|
|
303
|
-
model='
|
|
303
|
+
model='gemma-4-31b-it',
|
|
304
304
|
contents=[
|
|
305
305
|
'Find which candidate images contain objects similar to the reference',
|
|
306
306
|
reference
|
|
@@ -333,7 +333,7 @@ response = client.models.generate_content(
|
|
|
333
333
|
**Few-shot examples**:
|
|
334
334
|
```python
|
|
335
335
|
response = client.models.generate_content(
|
|
336
|
-
model='
|
|
336
|
+
model='gemma-4-31b-it',
|
|
337
337
|
contents=[
|
|
338
338
|
'Example: For an image of a cat on a sofa, respond: "Object: cat, Location: sofa"',
|
|
339
339
|
'Now analyze this image:',
|
|
@@ -371,7 +371,7 @@ response = client.models.generate_content(
|
|
|
371
371
|
|
|
372
372
|
```python
|
|
373
373
|
response = client.models.generate_content(
|
|
374
|
-
model='
|
|
374
|
+
model='gemma-4-31b-it',
|
|
375
375
|
contents=[
|
|
376
376
|
'''Analyze this product image:
|
|
377
377
|
1. Identify the product
|
|
@@ -388,7 +388,7 @@ response = client.models.generate_content(
|
|
|
388
388
|
|
|
389
389
|
```python
|
|
390
390
|
response = client.models.generate_content(
|
|
391
|
-
model='
|
|
391
|
+
model='gemma-4-31b-it',
|
|
392
392
|
contents=[
|
|
393
393
|
'Extract all text and UI elements from this screenshot',
|
|
394
394
|
img_part
|
|
@@ -400,7 +400,7 @@ response = client.models.generate_content(
|
|
|
400
400
|
|
|
401
401
|
```python
|
|
402
402
|
response = client.models.generate_content(
|
|
403
|
-
model='
|
|
403
|
+
model='gemma-4-31b-it',
|
|
404
404
|
contents=[
|
|
405
405
|
'Describe visible features in this medical image. Note: This is for informational purposes only.',
|
|
406
406
|
img_part
|
|
@@ -412,7 +412,7 @@ response = client.models.generate_content(
|
|
|
412
412
|
|
|
413
413
|
```python
|
|
414
414
|
response = client.models.generate_content(
|
|
415
|
-
model='
|
|
415
|
+
model='gemma-4-31b-it',
|
|
416
416
|
contents=[
|
|
417
417
|
'Extract data from this chart and format as JSON',
|
|
418
418
|
img_part
|
|
@@ -424,7 +424,7 @@ response = client.models.generate_content(
|
|
|
424
424
|
|
|
425
425
|
```python
|
|
426
426
|
response = client.models.generate_content(
|
|
427
|
-
model='
|
|
427
|
+
model='gemma-4-31b-it',
|
|
428
428
|
contents=[
|
|
429
429
|
'''Analyze this scene:
|
|
430
430
|
1. Location type
|
|
@@ -451,7 +451,7 @@ def analyze_image_with_retry(image_path, prompt, max_retries=3):
|
|
|
451
451
|
img_bytes = f.read()
|
|
452
452
|
|
|
453
453
|
response = client.models.generate_content(
|
|
454
|
-
model='
|
|
454
|
+
model='gemma-4-31b-it',
|
|
455
455
|
contents=[
|
|
456
456
|
prompt,
|
|
457
457
|
genai.types.Part.from_bytes(
|
|
@@ -302,7 +302,7 @@ def main():
|
|
|
302
302
|
print("\nImage generation models:")
|
|
303
303
|
print(" • gemma-4-31b-it-image - Nano Banana Flash (DEFAULT - fast)")
|
|
304
304
|
print(" • imagen-4.0-generate-001 - Imagen 4 (alternative - production)")
|
|
305
|
-
print(" •
|
|
305
|
+
print(" • gemma-4-31b-it-image-preview - Nano Banana Pro (4K text, reasoning)")
|
|
306
306
|
print("\nExample (uses default model):")
|
|
307
307
|
print(" python scripts/gemini_batch_process.py --task generate \\")
|
|
308
308
|
print(" --prompt 'A sunset over mountains' --aspect-ratio 16:9 --size 2K")
|
|
@@ -8,8 +8,8 @@ Supports all Gemini modalities:
|
|
|
8
8
|
- Video: Summarization, Q&A, scene detection
|
|
9
9
|
- Document: PDF extraction, structured output
|
|
10
10
|
- Generation: Image creation via Imagen 4 or Nano Banana (Gemini native)
|
|
11
|
-
- Nano Banana 2 (
|
|
12
|
-
- Nano Banana Pro (
|
|
11
|
+
- Nano Banana 2 (gemma-4-31b-it-image): Fastest, 95% Pro quality (default)
|
|
12
|
+
- Nano Banana Pro (gemma-4-31b-it-image-preview): Quality/4K text/reasoning
|
|
13
13
|
- Imagen 4 (imagen-4.0-*): Production-grade generation
|
|
14
14
|
"""
|
|
15
15
|
|
|
@@ -60,10 +60,10 @@ except ImportError:
|
|
|
60
60
|
|
|
61
61
|
|
|
62
62
|
# Image generation model configuration
|
|
63
|
-
# Default:
|
|
63
|
+
# Default: gemma-4-31b-it-image (Nano Banana 2 - 3-5x faster, 95% Pro quality)
|
|
64
64
|
# Alternative: imagen-4.0-generate-001 (production quality)
|
|
65
65
|
# All image generation requires billing - no completely free option exists
|
|
66
|
-
IMAGE_MODEL_DEFAULT = '
|
|
66
|
+
IMAGE_MODEL_DEFAULT = 'gemma-4-31b-it-image' # Nano Banana 2 (fastest, near-Pro quality)
|
|
67
67
|
IMAGE_MODEL_FALLBACK = 'gemma-4-31b-it-image' # Fallback if Nano Banana 2 fails
|
|
68
68
|
IMAGEN_MODELS = {
|
|
69
69
|
'imagen-4.0-generate-001',
|
|
@@ -138,7 +138,7 @@ def get_default_model(task: str) -> str:
|
|
|
138
138
|
return model
|
|
139
139
|
# Default to Nano Banana 2 (fastest, near-Pro quality)
|
|
140
140
|
# Alternative: imagen-4.0-generate-001 for production quality
|
|
141
|
-
return '
|
|
141
|
+
return 'gemma-4-31b-it-image'
|
|
142
142
|
|
|
143
143
|
elif task == 'generate-video':
|
|
144
144
|
model = os.getenv('VIDEO_GEN_MODEL')
|
|
@@ -180,8 +180,6 @@ def validate_model_task_combination(model: str, task: str) -> None:
|
|
|
180
180
|
'imagen-4.0-generate-001',
|
|
181
181
|
'imagen-4.0-ultra-generate-001',
|
|
182
182
|
'imagen-4.0-fast-generate-001',
|
|
183
|
-
'gemini-3.1-flash-image-preview',
|
|
184
|
-
'gemini-3-pro-image-preview',
|
|
185
183
|
'gemma-4-31b-it-image',
|
|
186
184
|
'gemma-4-31b-it-image-preview',
|
|
187
185
|
]
|
|
@@ -1093,7 +1091,7 @@ Examples:
|
|
|
1093
1091
|
|
|
1094
1092
|
# Generate images with Nano Banana Pro (4K text, reasoning)
|
|
1095
1093
|
%(prog)s --task generate --prompt "Travel poster with text 'EXPLORE'" \\
|
|
1096
|
-
--model
|
|
1094
|
+
--model gemma-4-31b-it-image-preview --aspect-ratio 3:4 --size 4K
|
|
1097
1095
|
|
|
1098
1096
|
# Generate images with Imagen 4 (production quality)
|
|
1099
1097
|
%(prog)s --task generate --prompt "Product photo of coffee mug" \\
|
|
@@ -1119,7 +1117,7 @@ Examples:
|
|
|
1119
1117
|
help='Aspect ratio for image/video generation')
|
|
1120
1118
|
parser.add_argument('--num-images', type=int, default=1,
|
|
1121
1119
|
help='Number of images to generate (1-4, default: 1)')
|
|
1122
|
-
# 4K available for Nano Banana Pro (
|
|
1120
|
+
# 4K available for Nano Banana Pro (gemma-4-31b-it-image-preview)
|
|
1123
1121
|
# Note: Not all models support --size, only use when needed
|
|
1124
1122
|
parser.add_argument('--size', choices=['1K', '2K', '4K'], default=None,
|
|
1125
1123
|
help='Image size - 1K/2K for Imagen 4, 1K/2K/4K for Nano Banana (optional)')
|