llm-gemini 0.20a2__tar.gz → 0.21__tar.gz

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: llm-gemini
3
- Version: 0.20a2
3
+ Version: 0.21
4
4
  Summary: LLM plugin to access Google's Gemini family of models
5
5
  Author: Simon Willison
6
6
  License-Expression: Apache-2.0
@@ -10,7 +10,7 @@ Project-URL: Issues, https://github.com/simonw/llm-gemini/issues
10
10
  Project-URL: CI, https://github.com/simonw/llm-gemini/actions
11
11
  Description-Content-Type: text/markdown
12
12
  License-File: LICENSE
13
- Requires-Dist: llm>=0.26a0
13
+ Requires-Dist: llm>=0.26
14
14
  Requires-Dist: httpx
15
15
  Requires-Dist: ijson
16
16
  Provides-Extra: test
@@ -18,6 +18,7 @@ Requires-Dist: pytest; extra == "test"
18
18
  Requires-Dist: pytest-recording; extra == "test"
19
19
  Requires-Dist: pytest-asyncio; extra == "test"
20
20
  Requires-Dist: nest-asyncio; extra == "test"
21
+ Requires-Dist: cogapp; extra == "test"
21
22
  Dynamic: license-file
22
23
 
23
24
  # llm-gemini
@@ -63,26 +64,71 @@ llm models default gemini-2.0-flash
63
64
  llm "A joke about a pelican and a walrus"
64
65
  ```
65
66
 
66
- Other models are:
67
-
68
- - `gemini-2.5-pro-preview-05-06` - latest paid Gemini 2.5 Pro preview
69
- - `gemini-2.5-flash-preview-05-20` - Gemini 2.5 Flash preview
70
- - `gemini-2.5-flash-preview-04-17` - Earlier Gemini 2.5 Flash preview
71
- - `gemini-2.5-pro-exp-03-25` - free experimental release of Gemini 2.5 Pro
72
- - `gemini-2.5-pro-preview-03-25` - paid preview of Gemini 2.5 Pro
73
- - `gemma-3-27b-it` - [Gemma 3](https://blog.google/technology/developers/gemma-3/) 27B
74
- - `gemini-2.0-pro-exp-02-05` - experimental release of Gemini 2.0 Pro
75
- - `gemini-2.0-flash-lite` - Gemini 2.0 Flash-Lite
76
- - `gemini-2.0-flash` - Gemini 2.0 Flash
77
- - `gemini-2.0-flash-thinking-exp-01-21` - experimental "thinking" model from January 2025
78
- - `gemini-2.0-flash-thinking-exp-1219` - experimental "thinking" model from December 2024
79
- - `learnlm-1.5-pro-experimental` - "an experimental task-specific model that has been trained to align with learning science principles" - [more details here](https://ai.google.dev/gemini-api/docs/learnlm).
80
- - `gemini-2.0-flash-exp` - [Gemini 2.0 Flash](https://blog.google/technology/google-deepmind/google-gemini-ai-update-december-2024/#gemini-2-0-flash)
81
- - `gemini-exp-1206` - recent experimental #3
82
- - `gemini-exp-1121` - recent experimental #2
83
- - `gemini-exp-1114` - recent experimental #1
84
- - `gemini-1.5-flash-8b-latest` - the least expensive
85
- - `gemini-1.5-flash-latest`
67
+ ## Available models
68
+
69
+ <!-- [[[cog
70
+ import cog
71
+ from llm import cli
72
+ from click.testing import CliRunner
73
+ runner = CliRunner()
74
+ result = runner.invoke(cli.cli, ["models", "-q", "gemini/"])
75
+ lines = reversed(result.output.strip().split("\n"))
76
+ to_output = []
77
+ NOTES = {
78
+ "gemini/gemini-2.5-pro-preview-05-06": "Latest paid Gemini 2.5 Pro preview",
79
+ "gemini/gemini-2.5-flash-preview-05-20": "Gemini 2.5 Flash preview",
80
+ "gemini/gemini-2.5-flash-preview-04-17": "Earlier Gemini 2.5 Flash preview",
81
+ "gemini/gemini-2.5-pro-exp-03-25": "Free experimental release of Gemini 2.5 Pro",
82
+ "gemini/gemini-2.0-flash-thinking-exp-01-21": "Experimental \"thinking\" model from January 2025",
83
+ "gemini/gemini-1.5-flash-8b-latest": "The least expensive model",
84
+ }
85
+ for line in lines:
86
+ model_id, rest = line.split(None, 2)[1:]
87
+ note = NOTES.get(model_id, "")
88
+ to_output.append(
89
+ "- `{}`{}".format(
90
+ model_id,
91
+ ': {}'.format(note) if note else ""
92
+ )
93
+ )
94
+ cog.out("\n".join(to_output))
95
+ ]]] -->
96
+ - `gemini/gemini-2.5-flash-preview-05-20`: Gemini 2.5 Flash preview
97
+ - `gemini/gemini-2.5-pro-preview-05-06`: Latest paid Gemini 2.5 Pro preview
98
+ - `gemini/gemini-2.5-flash-preview-04-17`: Earlier Gemini 2.5 Flash preview
99
+ - `gemini/gemini-2.5-pro-preview-03-25`
100
+ - `gemini/gemini-2.5-pro-exp-03-25`: Free experimental release of Gemini 2.5 Pro
101
+ - `gemini/gemini-2.0-flash-lite`
102
+ - `gemini/gemini-2.0-pro-exp-02-05`
103
+ - `gemini/gemini-2.0-flash`
104
+ - `gemini/gemini-2.0-flash-thinking-exp-01-21`: Experimental "thinking" model from January 2025
105
+ - `gemini/gemini-2.0-flash-thinking-exp-1219`
106
+ - `gemini/gemma-3n-e4b-it`
107
+ - `gemini/gemma-3-27b-it`
108
+ - `gemini/gemma-3-12b-it`
109
+ - `gemini/gemma-3-4b-it`
110
+ - `gemini/gemma-3-1b-it`
111
+ - `gemini/learnlm-1.5-pro-experimental`
112
+ - `gemini/gemini-2.0-flash-exp`
113
+ - `gemini/gemini-exp-1206`
114
+ - `gemini/gemini-exp-1121`
115
+ - `gemini/gemini-exp-1114`
116
+ - `gemini/gemini-1.5-flash-8b-001`
117
+ - `gemini/gemini-1.5-flash-8b-latest`: The least expensive model
118
+ - `gemini/gemini-1.5-flash-002`
119
+ - `gemini/gemini-1.5-pro-002`
120
+ - `gemini/gemini-1.5-flash-001`
121
+ - `gemini/gemini-1.5-pro-001`
122
+ - `gemini/gemini-1.5-flash-latest`
123
+ - `gemini/gemini-1.5-pro-latest`
124
+ - `gemini/gemini-pro`
125
+ <!-- [[[end]]] -->
126
+
127
+ All of these models have aliases that omit the `gemini/` prefix, for example:
128
+
129
+ ```bash
130
+ llm -m gemini-1.5-flash-8b-latest --schema 'name,age int,bio' 'invent a dog'
131
+ ```
86
132
 
87
133
  ### Images, audio and video
88
134
 
@@ -155,6 +201,31 @@ To chat interactively with the model, run `llm chat`:
155
201
  llm chat -m gemini-2.0-flash
156
202
  ```
157
203
 
204
+ ### Timeouts
205
+
206
+ By default there is no `timeout` against the Gemini API. You can use the `timeout` option to protect against API requests that hang indefinitely.
207
+
208
+ With the CLI tool that looks like this, to set a 1.5 second timeout:
209
+
210
+ ```bash
211
+ llm -m gemini-2.5-flash-preview-05-20 'epic saga about mice' -o timeout 1.5
212
+ ```
213
+ In the Python library timeouts are used like this:
214
+ ```python
215
+ import httpx, llm
216
+
217
+ model = llm.get_model("gemini/gemini-2.5-flash-preview-05-20")
218
+
219
+ try:
220
+ response = model.prompt(
221
+ "epic saga about mice", timeout=1.5
222
+ )
223
+ print(response.text())
224
+ except httpx.TimeoutException:
225
+ print("Timeout exceeded")
226
+ ```
227
+ An `httpx.TimeoutException` subclass will be raised if the timeout is exceeded.
228
+
158
229
  ## Embeddings
159
230
 
160
231
  The plugin also adds support for the `gemini-embedding-exp-03-07` and `text-embedding-004` embedding models.
@@ -187,6 +258,21 @@ llm similar readmes -c 'upload csvs to stuff' -d embed.db
187
258
 
188
259
  See the [LLM embeddings documentation](https://llm.datasette.io/en/stable/embeddings/cli.html) for further details.
189
260
 
261
+ ## Listing all Gemini API models
262
+
263
+ The `llm gemini models` command lists all of the models that are exposed by the Gemini API, some of which may not be available through this plugin.
264
+
265
+ ```bash
266
+ llm gemini models
267
+ ```
268
+ You can add a `--key X` option to use a different API key.
269
+
270
+ To filter models by their supported generation methods use `--method` one or more times:
271
+ ```bash
272
+ llm gemini models --method embedContent
273
+ ```
274
+ If you provide multiple methods you will see models that support any of them.
275
+
190
276
  ## Development
191
277
 
192
278
  To set up this plugin locally, first checkout the code. Then create a new virtual environment:
@@ -41,26 +41,71 @@ llm models default gemini-2.0-flash
41
41
  llm "A joke about a pelican and a walrus"
42
42
  ```
43
43
 
44
- Other models are:
45
-
46
- - `gemini-2.5-pro-preview-05-06` - latest paid Gemini 2.5 Pro preview
47
- - `gemini-2.5-flash-preview-05-20` - Gemini 2.5 Flash preview
48
- - `gemini-2.5-flash-preview-04-17` - Earlier Gemini 2.5 Flash preview
49
- - `gemini-2.5-pro-exp-03-25` - free experimental release of Gemini 2.5 Pro
50
- - `gemini-2.5-pro-preview-03-25` - paid preview of Gemini 2.5 Pro
51
- - `gemma-3-27b-it` - [Gemma 3](https://blog.google/technology/developers/gemma-3/) 27B
52
- - `gemini-2.0-pro-exp-02-05` - experimental release of Gemini 2.0 Pro
53
- - `gemini-2.0-flash-lite` - Gemini 2.0 Flash-Lite
54
- - `gemini-2.0-flash` - Gemini 2.0 Flash
55
- - `gemini-2.0-flash-thinking-exp-01-21` - experimental "thinking" model from January 2025
56
- - `gemini-2.0-flash-thinking-exp-1219` - experimental "thinking" model from December 2024
57
- - `learnlm-1.5-pro-experimental` - "an experimental task-specific model that has been trained to align with learning science principles" - [more details here](https://ai.google.dev/gemini-api/docs/learnlm).
58
- - `gemini-2.0-flash-exp` - [Gemini 2.0 Flash](https://blog.google/technology/google-deepmind/google-gemini-ai-update-december-2024/#gemini-2-0-flash)
59
- - `gemini-exp-1206` - recent experimental #3
60
- - `gemini-exp-1121` - recent experimental #2
61
- - `gemini-exp-1114` - recent experimental #1
62
- - `gemini-1.5-flash-8b-latest` - the least expensive
63
- - `gemini-1.5-flash-latest`
44
+ ## Available models
45
+
46
+ <!-- [[[cog
47
+ import cog
48
+ from llm import cli
49
+ from click.testing import CliRunner
50
+ runner = CliRunner()
51
+ result = runner.invoke(cli.cli, ["models", "-q", "gemini/"])
52
+ lines = reversed(result.output.strip().split("\n"))
53
+ to_output = []
54
+ NOTES = {
55
+ "gemini/gemini-2.5-pro-preview-05-06": "Latest paid Gemini 2.5 Pro preview",
56
+ "gemini/gemini-2.5-flash-preview-05-20": "Gemini 2.5 Flash preview",
57
+ "gemini/gemini-2.5-flash-preview-04-17": "Earlier Gemini 2.5 Flash preview",
58
+ "gemini/gemini-2.5-pro-exp-03-25": "Free experimental release of Gemini 2.5 Pro",
59
+ "gemini/gemini-2.0-flash-thinking-exp-01-21": "Experimental \"thinking\" model from January 2025",
60
+ "gemini/gemini-1.5-flash-8b-latest": "The least expensive model",
61
+ }
62
+ for line in lines:
63
+ model_id, rest = line.split(None, 2)[1:]
64
+ note = NOTES.get(model_id, "")
65
+ to_output.append(
66
+ "- `{}`{}".format(
67
+ model_id,
68
+ ': {}'.format(note) if note else ""
69
+ )
70
+ )
71
+ cog.out("\n".join(to_output))
72
+ ]]] -->
73
+ - `gemini/gemini-2.5-flash-preview-05-20`: Gemini 2.5 Flash preview
74
+ - `gemini/gemini-2.5-pro-preview-05-06`: Latest paid Gemini 2.5 Pro preview
75
+ - `gemini/gemini-2.5-flash-preview-04-17`: Earlier Gemini 2.5 Flash preview
76
+ - `gemini/gemini-2.5-pro-preview-03-25`
77
+ - `gemini/gemini-2.5-pro-exp-03-25`: Free experimental release of Gemini 2.5 Pro
78
+ - `gemini/gemini-2.0-flash-lite`
79
+ - `gemini/gemini-2.0-pro-exp-02-05`
80
+ - `gemini/gemini-2.0-flash`
81
+ - `gemini/gemini-2.0-flash-thinking-exp-01-21`: Experimental "thinking" model from January 2025
82
+ - `gemini/gemini-2.0-flash-thinking-exp-1219`
83
+ - `gemini/gemma-3n-e4b-it`
84
+ - `gemini/gemma-3-27b-it`
85
+ - `gemini/gemma-3-12b-it`
86
+ - `gemini/gemma-3-4b-it`
87
+ - `gemini/gemma-3-1b-it`
88
+ - `gemini/learnlm-1.5-pro-experimental`
89
+ - `gemini/gemini-2.0-flash-exp`
90
+ - `gemini/gemini-exp-1206`
91
+ - `gemini/gemini-exp-1121`
92
+ - `gemini/gemini-exp-1114`
93
+ - `gemini/gemini-1.5-flash-8b-001`
94
+ - `gemini/gemini-1.5-flash-8b-latest`: The least expensive model
95
+ - `gemini/gemini-1.5-flash-002`
96
+ - `gemini/gemini-1.5-pro-002`
97
+ - `gemini/gemini-1.5-flash-001`
98
+ - `gemini/gemini-1.5-pro-001`
99
+ - `gemini/gemini-1.5-flash-latest`
100
+ - `gemini/gemini-1.5-pro-latest`
101
+ - `gemini/gemini-pro`
102
+ <!-- [[[end]]] -->
103
+
104
+ All of these models have aliases that omit the `gemini/` prefix, for example:
105
+
106
+ ```bash
107
+ llm -m gemini-1.5-flash-8b-latest --schema 'name,age int,bio' 'invent a dog'
108
+ ```
64
109
 
65
110
  ### Images, audio and video
66
111
 
@@ -133,6 +178,31 @@ To chat interactively with the model, run `llm chat`:
133
178
  llm chat -m gemini-2.0-flash
134
179
  ```
135
180
 
181
+ ### Timeouts
182
+
183
+ By default there is no `timeout` against the Gemini API. You can use the `timeout` option to protect against API requests that hang indefinitely.
184
+
185
+ With the CLI tool that looks like this, to set a 1.5 second timeout:
186
+
187
+ ```bash
188
+ llm -m gemini-2.5-flash-preview-05-20 'epic saga about mice' -o timeout 1.5
189
+ ```
190
+ In the Python library timeouts are used like this:
191
+ ```python
192
+ import httpx, llm
193
+
194
+ model = llm.get_model("gemini/gemini-2.5-flash-preview-05-20")
195
+
196
+ try:
197
+ response = model.prompt(
198
+ "epic saga about mice", timeout=1.5
199
+ )
200
+ print(response.text())
201
+ except httpx.TimeoutException:
202
+ print("Timeout exceeded")
203
+ ```
204
+ An `httpx.TimeoutException` subclass will be raised if the timeout is exceeded.
205
+
136
206
  ## Embeddings
137
207
 
138
208
  The plugin also adds support for the `gemini-embedding-exp-03-07` and `text-embedding-004` embedding models.
@@ -165,6 +235,21 @@ llm similar readmes -c 'upload csvs to stuff' -d embed.db
165
235
 
166
236
  See the [LLM embeddings documentation](https://llm.datasette.io/en/stable/embeddings/cli.html) for further details.
167
237
 
238
+ ## Listing all Gemini API models
239
+
240
+ The `llm gemini models` command lists all of the models that are exposed by the Gemini API, some of which may not be available through this plugin.
241
+
242
+ ```bash
243
+ llm gemini models
244
+ ```
245
+ You can add a `--key X` option to use a different API key.
246
+
247
+ To filter models by their supported generation methods use `--method` one or more times:
248
+ ```bash
249
+ llm gemini models --method embedContent
250
+ ```
251
+ If you provide multiple methods you will see models that support any of them.
252
+
168
253
  ## Development
169
254
 
170
255
  To set up this plugin locally, first checkout the code. Then create a new virtual environment:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: llm-gemini
3
- Version: 0.20a2
3
+ Version: 0.21
4
4
  Summary: LLM plugin to access Google's Gemini family of models
5
5
  Author: Simon Willison
6
6
  License-Expression: Apache-2.0
@@ -10,7 +10,7 @@ Project-URL: Issues, https://github.com/simonw/llm-gemini/issues
10
10
  Project-URL: CI, https://github.com/simonw/llm-gemini/actions
11
11
  Description-Content-Type: text/markdown
12
12
  License-File: LICENSE
13
- Requires-Dist: llm>=0.26a0
13
+ Requires-Dist: llm>=0.26
14
14
  Requires-Dist: httpx
15
15
  Requires-Dist: ijson
16
16
  Provides-Extra: test
@@ -18,6 +18,7 @@ Requires-Dist: pytest; extra == "test"
18
18
  Requires-Dist: pytest-recording; extra == "test"
19
19
  Requires-Dist: pytest-asyncio; extra == "test"
20
20
  Requires-Dist: nest-asyncio; extra == "test"
21
+ Requires-Dist: cogapp; extra == "test"
21
22
  Dynamic: license-file
22
23
 
23
24
  # llm-gemini
@@ -63,26 +64,71 @@ llm models default gemini-2.0-flash
63
64
  llm "A joke about a pelican and a walrus"
64
65
  ```
65
66
 
66
- Other models are:
67
-
68
- - `gemini-2.5-pro-preview-05-06` - latest paid Gemini 2.5 Pro preview
69
- - `gemini-2.5-flash-preview-05-20` - Gemini 2.5 Flash preview
70
- - `gemini-2.5-flash-preview-04-17` - Earlier Gemini 2.5 Flash preview
71
- - `gemini-2.5-pro-exp-03-25` - free experimental release of Gemini 2.5 Pro
72
- - `gemini-2.5-pro-preview-03-25` - paid preview of Gemini 2.5 Pro
73
- - `gemma-3-27b-it` - [Gemma 3](https://blog.google/technology/developers/gemma-3/) 27B
74
- - `gemini-2.0-pro-exp-02-05` - experimental release of Gemini 2.0 Pro
75
- - `gemini-2.0-flash-lite` - Gemini 2.0 Flash-Lite
76
- - `gemini-2.0-flash` - Gemini 2.0 Flash
77
- - `gemini-2.0-flash-thinking-exp-01-21` - experimental "thinking" model from January 2025
78
- - `gemini-2.0-flash-thinking-exp-1219` - experimental "thinking" model from December 2024
79
- - `learnlm-1.5-pro-experimental` - "an experimental task-specific model that has been trained to align with learning science principles" - [more details here](https://ai.google.dev/gemini-api/docs/learnlm).
80
- - `gemini-2.0-flash-exp` - [Gemini 2.0 Flash](https://blog.google/technology/google-deepmind/google-gemini-ai-update-december-2024/#gemini-2-0-flash)
81
- - `gemini-exp-1206` - recent experimental #3
82
- - `gemini-exp-1121` - recent experimental #2
83
- - `gemini-exp-1114` - recent experimental #1
84
- - `gemini-1.5-flash-8b-latest` - the least expensive
85
- - `gemini-1.5-flash-latest`
67
+ ## Available models
68
+
69
+ <!-- [[[cog
70
+ import cog
71
+ from llm import cli
72
+ from click.testing import CliRunner
73
+ runner = CliRunner()
74
+ result = runner.invoke(cli.cli, ["models", "-q", "gemini/"])
75
+ lines = reversed(result.output.strip().split("\n"))
76
+ to_output = []
77
+ NOTES = {
78
+ "gemini/gemini-2.5-pro-preview-05-06": "Latest paid Gemini 2.5 Pro preview",
79
+ "gemini/gemini-2.5-flash-preview-05-20": "Gemini 2.5 Flash preview",
80
+ "gemini/gemini-2.5-flash-preview-04-17": "Earlier Gemini 2.5 Flash preview",
81
+ "gemini/gemini-2.5-pro-exp-03-25": "Free experimental release of Gemini 2.5 Pro",
82
+ "gemini/gemini-2.0-flash-thinking-exp-01-21": "Experimental \"thinking\" model from January 2025",
83
+ "gemini/gemini-1.5-flash-8b-latest": "The least expensive model",
84
+ }
85
+ for line in lines:
86
+ model_id, rest = line.split(None, 2)[1:]
87
+ note = NOTES.get(model_id, "")
88
+ to_output.append(
89
+ "- `{}`{}".format(
90
+ model_id,
91
+ ': {}'.format(note) if note else ""
92
+ )
93
+ )
94
+ cog.out("\n".join(to_output))
95
+ ]]] -->
96
+ - `gemini/gemini-2.5-flash-preview-05-20`: Gemini 2.5 Flash preview
97
+ - `gemini/gemini-2.5-pro-preview-05-06`: Latest paid Gemini 2.5 Pro preview
98
+ - `gemini/gemini-2.5-flash-preview-04-17`: Earlier Gemini 2.5 Flash preview
99
+ - `gemini/gemini-2.5-pro-preview-03-25`
100
+ - `gemini/gemini-2.5-pro-exp-03-25`: Free experimental release of Gemini 2.5 Pro
101
+ - `gemini/gemini-2.0-flash-lite`
102
+ - `gemini/gemini-2.0-pro-exp-02-05`
103
+ - `gemini/gemini-2.0-flash`
104
+ - `gemini/gemini-2.0-flash-thinking-exp-01-21`: Experimental "thinking" model from January 2025
105
+ - `gemini/gemini-2.0-flash-thinking-exp-1219`
106
+ - `gemini/gemma-3n-e4b-it`
107
+ - `gemini/gemma-3-27b-it`
108
+ - `gemini/gemma-3-12b-it`
109
+ - `gemini/gemma-3-4b-it`
110
+ - `gemini/gemma-3-1b-it`
111
+ - `gemini/learnlm-1.5-pro-experimental`
112
+ - `gemini/gemini-2.0-flash-exp`
113
+ - `gemini/gemini-exp-1206`
114
+ - `gemini/gemini-exp-1121`
115
+ - `gemini/gemini-exp-1114`
116
+ - `gemini/gemini-1.5-flash-8b-001`
117
+ - `gemini/gemini-1.5-flash-8b-latest`: The least expensive model
118
+ - `gemini/gemini-1.5-flash-002`
119
+ - `gemini/gemini-1.5-pro-002`
120
+ - `gemini/gemini-1.5-flash-001`
121
+ - `gemini/gemini-1.5-pro-001`
122
+ - `gemini/gemini-1.5-flash-latest`
123
+ - `gemini/gemini-1.5-pro-latest`
124
+ - `gemini/gemini-pro`
125
+ <!-- [[[end]]] -->
126
+
127
+ All of these models have aliases that omit the `gemini/` prefix, for example:
128
+
129
+ ```bash
130
+ llm -m gemini-1.5-flash-8b-latest --schema 'name,age int,bio' 'invent a dog'
131
+ ```
86
132
 
87
133
  ### Images, audio and video
88
134
 
@@ -155,6 +201,31 @@ To chat interactively with the model, run `llm chat`:
155
201
  llm chat -m gemini-2.0-flash
156
202
  ```
157
203
 
204
+ ### Timeouts
205
+
206
+ By default there is no `timeout` against the Gemini API. You can use the `timeout` option to protect against API requests that hang indefinitely.
207
+
208
+ With the CLI tool that looks like this, to set a 1.5 second timeout:
209
+
210
+ ```bash
211
+ llm -m gemini-2.5-flash-preview-05-20 'epic saga about mice' -o timeout 1.5
212
+ ```
213
+ In the Python library timeouts are used like this:
214
+ ```python
215
+ import httpx, llm
216
+
217
+ model = llm.get_model("gemini/gemini-2.5-flash-preview-05-20")
218
+
219
+ try:
220
+ response = model.prompt(
221
+ "epic saga about mice", timeout=1.5
222
+ )
223
+ print(response.text())
224
+ except httpx.TimeoutException:
225
+ print("Timeout exceeded")
226
+ ```
227
+ An `httpx.TimeoutException` subclass will be raised if the timeout is exceeded.
228
+
158
229
  ## Embeddings
159
230
 
160
231
  The plugin also adds support for the `gemini-embedding-exp-03-07` and `text-embedding-004` embedding models.
@@ -187,6 +258,21 @@ llm similar readmes -c 'upload csvs to stuff' -d embed.db
187
258
 
188
259
  See the [LLM embeddings documentation](https://llm.datasette.io/en/stable/embeddings/cli.html) for further details.
189
260
 
261
+ ## Listing all Gemini API models
262
+
263
+ The `llm gemini models` command lists all of the models that are exposed by the Gemini API, some of which may not be available through this plugin.
264
+
265
+ ```bash
266
+ llm gemini models
267
+ ```
268
+ You can add a `--key X` option to use a different API key.
269
+
270
+ To filter models by their supported generation methods use `--method` one or more times:
271
+ ```bash
272
+ llm gemini models --method embedContent
273
+ ```
274
+ If you provide multiple methods you will see models that support any of them.
275
+
190
276
  ## Development
191
277
 
192
278
  To set up this plugin locally, first checkout the code. Then create a new virtual environment:
@@ -1,4 +1,4 @@
1
- llm>=0.26a0
1
+ llm>=0.26
2
2
  httpx
3
3
  ijson
4
4
 
@@ -7,3 +7,4 @@ pytest
7
7
  pytest-recording
8
8
  pytest-asyncio
9
9
  nest-asyncio
10
+ cogapp
@@ -55,15 +55,56 @@ GOOGLE_SEARCH_MODELS_USING_SEARCH_RETRIEVAL = {
55
55
  }
56
56
 
57
57
  THINKING_BUDGET_MODELS = {
58
+ "gemini-2.0-flash-thinking-exp-01-21",
59
+ "gemini-2.0-flash-thinking-exp-1219",
58
60
  "gemini-2.5-flash-preview-04-17",
61
+ "gemini-2.5-pro-exp-03-25",
62
+ "gemini-2.5-pro-preview-03-25",
63
+ "gemini-2.5-pro-preview-05-06",
59
64
  "gemini-2.5-flash-preview-05-20",
60
65
  }
61
66
 
67
+ NO_VISION_MODELS = {"gemma-3-1b-it", "gemma-3n-e4b-it"}
68
+
69
+ ATTACHMENT_TYPES = {
70
+ # Text
71
+ "text/plain",
72
+ "text/csv",
73
+ # PDF
74
+ "application/pdf",
75
+ # Images
76
+ "image/png",
77
+ "image/jpeg",
78
+ "image/webp",
79
+ "image/heic",
80
+ "image/heif",
81
+ # Audio
82
+ "audio/wav",
83
+ "audio/mp3",
84
+ "audio/aiff",
85
+ "audio/aac",
86
+ "audio/ogg",
87
+ "application/ogg",
88
+ "audio/flac",
89
+ "audio/mpeg", # Treated as audio/mp3
90
+ # Video
91
+ "video/mp4",
92
+ "video/mpeg",
93
+ "video/mov",
94
+ "video/avi",
95
+ "video/x-flv",
96
+ "video/mpg",
97
+ "video/webm",
98
+ "video/wmv",
99
+ "video/3gpp",
100
+ "video/quicktime",
101
+ }
102
+
62
103
 
63
104
  @llm.hookimpl
64
105
  def register_models(register):
65
106
  # Register both sync and async versions of each model
66
- for model_id in [
107
+ for model_id in (
67
108
  "gemini-pro",
68
109
  "gemini-1.5-pro-latest",
69
110
  "gemini-1.5-flash-latest",
@@ -78,6 +119,12 @@ def register_models(register):
78
119
  "gemini-exp-1206",
79
120
  "gemini-2.0-flash-exp",
80
121
  "learnlm-1.5-pro-experimental",
122
+ # Gemma 3 models:
123
+ "gemma-3-1b-it",
124
+ "gemma-3-4b-it",
125
+ "gemma-3-12b-it", # 12th March 2025
126
+ "gemma-3-27b-it",
127
+ "gemma-3n-e4b-it", # 20th May 2025
81
128
  "gemini-2.0-flash-thinking-exp-1219",
82
129
  "gemini-2.0-flash-thinking-exp-01-21",
83
130
  # Released 5th Feb 2025:
@@ -85,8 +132,6 @@ def register_models(register):
85
132
  "gemini-2.0-pro-exp-02-05",
86
133
  # Released 25th Feb 2025:
87
134
  "gemini-2.0-flash-lite",
88
- # Released 12th March 2025:
89
- "gemma-3-27b-it",
90
135
  # 25th March 2025:
91
136
  "gemini-2.5-pro-exp-03-25",
92
137
  # 4th April 2025 (paid):
@@ -97,22 +142,27 @@ def register_models(register):
97
142
  "gemini-2.5-pro-preview-05-06",
98
143
  # 20th May 2025:
99
144
  "gemini-2.5-flash-preview-05-20",
100
- ]:
145
+ ):
101
146
  can_google_search = model_id in GOOGLE_SEARCH_MODELS
102
147
  can_thinking_budget = model_id in THINKING_BUDGET_MODELS
148
+ can_vision = model_id not in NO_VISION_MODELS
149
+ can_schema = "flash-thinking" not in model_id and "gemma-3" not in model_id
103
150
  register(
104
151
  GeminiPro(
105
152
  model_id,
153
+ can_vision=can_vision,
106
154
  can_google_search=can_google_search,
107
155
  can_thinking_budget=can_thinking_budget,
108
- can_schema="flash-thinking" not in model_id,
156
+ can_schema=can_schema,
109
157
  ),
110
158
  AsyncGeminiPro(
111
159
  model_id,
160
+ can_vision=can_vision,
112
161
  can_google_search=can_google_search,
113
162
  can_thinking_budget=can_thinking_budget,
114
- can_schema="flash-thinking" not in model_id,
163
+ can_schema=can_schema,
115
164
  ),
165
+ aliases=(model_id,),
116
166
  )
117
167
 
118
168
 
@@ -154,39 +204,7 @@ class _SharedGemini:
154
204
  supports_schema = True
155
205
  supports_tools = True
156
206
 
157
- attachment_types = (
158
- # Text
159
- "text/plain",
160
- "text/csv",
161
- # PDF
162
- "application/pdf",
163
- # Images
164
- "image/png",
165
- "image/jpeg",
166
- "image/webp",
167
- "image/heic",
168
- "image/heif",
169
- # Audio
170
- "audio/wav",
171
- "audio/mp3",
172
- "audio/aiff",
173
- "audio/aac",
174
- "audio/ogg",
175
- "application/ogg",
176
- "audio/flac",
177
- "audio/mpeg", # Treated as audio/mp3
178
- # Video
179
- "video/mp4",
180
- "video/mpeg",
181
- "video/mov",
182
- "video/avi",
183
- "video/x-flv",
184
- "video/mpg",
185
- "video/webm",
186
- "video/wmv",
187
- "video/3gpp",
188
- "video/quicktime",
189
- )
207
+ attachment_types = set()
190
208
 
191
209
  class Options(llm.Options):
192
210
  code_execution: Optional[bool] = Field(
@@ -232,6 +250,14 @@ class _SharedGemini:
232
250
  description="Output a valid JSON object {...}",
233
251
  default=None,
234
252
  )
253
+ timeout: Optional[float] = Field(
254
+ description=(
255
+ "The maximum time in seconds to wait for a response. "
256
+ "If the model does not respond within this time, "
257
+ "the request will be aborted."
258
+ ),
259
+ default=None,
260
+ )
235
261
 
236
262
  class OptionsWithGoogleSearch(Options):
237
263
  google_search: Optional[bool] = Field(
@@ -247,12 +273,14 @@ class _SharedGemini:
247
273
 
248
274
  def __init__(
249
275
  self,
250
- model_id,
276
+ gemini_model_id,
277
+ can_vision=True,
251
278
  can_google_search=False,
252
279
  can_thinking_budget=False,
253
280
  can_schema=False,
254
281
  ):
255
- self.model_id = model_id
282
+ self.model_id = "gemini/{}".format(gemini_model_id)
283
+ self.gemini_model_id = gemini_model_id
256
284
  self.can_google_search = can_google_search
257
285
  self.supports_schema = can_schema
258
286
  if can_google_search:
@@ -260,6 +288,8 @@ class _SharedGemini:
260
288
  self.can_thinking_budget = can_thinking_budget
261
289
  if can_thinking_budget:
262
290
  self.Options = self.OptionsWithThinkingBudget
291
+ if can_vision:
292
+ self.attachment_types = ATTACHMENT_TYPES
263
293
 
264
294
  def build_messages(self, prompt, conversation):
265
295
  messages = []
@@ -457,14 +487,14 @@ class _SharedGemini:
457
487
 
458
488
  class GeminiPro(_SharedGemini, llm.KeyModel):
459
489
  def execute(self, prompt, stream, response, conversation, key):
460
- url = f"https://generativelanguage.googleapis.com/v1beta/models/{self.model_id}:streamGenerateContent"
490
+ url = f"https://generativelanguage.googleapis.com/v1beta/models/{self.gemini_model_id}:streamGenerateContent"
461
491
  gathered = []
462
492
  body = self.build_request_body(prompt, conversation)
463
493
 
464
494
  with httpx.stream(
465
495
  "POST",
466
496
  url,
467
- timeout=None,
497
+ timeout=prompt.options.timeout,
468
498
  headers={"x-goog-api-key": self.get_key(key)},
469
499
  json=body,
470
500
  ) as http_response:
@@ -490,7 +520,7 @@ class GeminiPro(_SharedGemini, llm.KeyModel):
490
520
 
491
521
  class AsyncGeminiPro(_SharedGemini, llm.AsyncKeyModel):
492
522
  async def execute(self, prompt, stream, response, conversation, key):
493
- url = f"https://generativelanguage.googleapis.com/v1beta/models/{self.model_id}:streamGenerateContent"
523
+ url = f"https://generativelanguage.googleapis.com/v1beta/models/{self.gemini_model_id}:streamGenerateContent"
494
524
  gathered = []
495
525
  body = self.build_request_body(prompt, conversation)
496
526
 
@@ -498,7 +528,7 @@ class AsyncGeminiPro(_SharedGemini, llm.AsyncKeyModel):
498
528
  async with client.stream(
499
529
  "POST",
500
530
  url,
501
- timeout=None,
531
+ timeout=prompt.options.timeout,
502
532
  headers={"x-goog-api-key": self.get_key(key)},
503
533
  json=body,
504
534
  ) as http_response:
@@ -588,8 +618,20 @@ def register_commands(cli):
588
618
 
589
619
  @gemini.command()
590
620
  @click.option("--key", help="API key to use")
591
- def models(key):
592
- "List of Gemini models pulled from their API"
621
+ @click.option(
622
+ "methods",
623
+ "--method",
624
+ multiple=True,
625
+ help="Filter by supported generation methods",
626
+ )
627
+ def models(key, methods):
628
+ """
629
+ List of Gemini models pulled from their API
630
+
631
+ Use --method to filter by supported generation methods for example:
632
+
633
+ llm gemini models --method generateContent --method embedContent
634
+ """
593
635
  key = llm.get_key(key, "gemini", "LLM_GEMINI_KEY")
594
636
  if not key:
595
637
  raise click.ClickException(
@@ -598,7 +640,16 @@ def register_commands(cli):
598
640
  url = f"https://generativelanguage.googleapis.com/v1beta/models"
599
641
  response = httpx.get(url, headers={"x-goog-api-key": key})
600
642
  response.raise_for_status()
601
- click.echo(json.dumps(response.json()["models"], indent=2))
643
+ models = response.json()["models"]
644
+ if methods:
645
+ models = [
646
+ model
647
+ for model in models
648
+ if any(
649
+ method in model["supportedGenerationMethods"] for method in methods
650
+ )
651
+ ]
652
+ click.echo(json.dumps(models, indent=2))
602
653
 
603
654
  @gemini.command()
604
655
  @click.option("--key", help="API key to use")
@@ -1,13 +1,13 @@
1
1
  [project]
2
2
  name = "llm-gemini"
3
- version = "0.20a2"
3
+ version = "0.21"
4
4
  description = "LLM plugin to access Google's Gemini family of models"
5
5
  readme = "README.md"
6
6
  authors = [{name = "Simon Willison"}]
7
7
  license = "Apache-2.0"
8
8
  classifiers = []
9
9
  dependencies = [
10
- "llm>=0.26a0",
10
+ "llm>=0.26",
11
11
  "httpx",
12
12
  "ijson"
13
13
  ]
@@ -22,7 +22,7 @@ CI = "https://github.com/simonw/llm-gemini/actions"
22
22
  gemini = "llm_gemini"
23
23
 
24
24
  [project.optional-dependencies]
25
- test = ["pytest", "pytest-recording", "pytest-asyncio", "nest-asyncio"]
25
+ test = ["pytest", "pytest-recording", "pytest-asyncio", "nest-asyncio", "cogapp"]
26
26
 
27
27
  [tool.pytest.ini_options]
28
28
  asyncio_mode = "strict"
@@ -232,6 +232,14 @@ def test_cli_gemini_models(tmpdir, monkeypatch):
232
232
  result2 = runner.invoke(cli, ["gemini", "models", "--key", GEMINI_API_KEY])
233
233
  assert result2.exit_code == 0
234
234
  assert "gemini-1.5-flash-latest" in result2.output
235
+ # And with --method
236
+ result3 = runner.invoke(
237
+ cli, ["gemini", "models", "--key", GEMINI_API_KEY, "--method", "embedContent"]
238
+ )
239
+ assert result3.exit_code == 0
240
+ models = json.loads(result3.output)
241
+ for model in models:
242
+ assert "embedContent" in model["supportedGenerationMethods"]
235
243
 
236
244
 
237
245
  @pytest.mark.vcr
File without changes
File without changes