llm-gemini 0.20a1__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.20a1
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,25 +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-04-17` - Gemini 2.5 Flash preview
70
- - `gemini-2.5-pro-exp-03-25` - free experimental release of Gemini 2.5 Pro
71
- - `gemini-2.5-pro-preview-03-25` - paid preview of Gemini 2.5 Pro
72
- - `gemma-3-27b-it` - [Gemma 3](https://blog.google/technology/developers/gemma-3/) 27B
73
- - `gemini-2.0-pro-exp-02-05` - experimental release of Gemini 2.0 Pro
74
- - `gemini-2.0-flash-lite` - Gemini 2.0 Flash-Lite
75
- - `gemini-2.0-flash` - Gemini 2.0 Flash
76
- - `gemini-2.0-flash-thinking-exp-01-21` - experimental "thinking" model from January 2025
77
- - `gemini-2.0-flash-thinking-exp-1219` - experimental "thinking" model from December 2024
78
- - `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).
79
- - `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)
80
- - `gemini-exp-1206` - recent experimental #3
81
- - `gemini-exp-1121` - recent experimental #2
82
- - `gemini-exp-1114` - recent experimental #1
83
- - `gemini-1.5-flash-8b-latest` - the least expensive
84
- - `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
+ ```
85
132
 
86
133
  ### Images, audio and video
87
134
 
@@ -154,6 +201,31 @@ To chat interactively with the model, run `llm chat`:
154
201
  llm chat -m gemini-2.0-flash
155
202
  ```
156
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
+
157
229
  ## Embeddings
158
230
 
159
231
  The plugin also adds support for the `gemini-embedding-exp-03-07` and `text-embedding-004` embedding models.
@@ -186,6 +258,21 @@ llm similar readmes -c 'upload csvs to stuff' -d embed.db
186
258
 
187
259
  See the [LLM embeddings documentation](https://llm.datasette.io/en/stable/embeddings/cli.html) for further details.
188
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
+
189
276
  ## Development
190
277
 
191
278
  To set up this plugin locally, first checkout the code. Then create a new virtual environment:
@@ -41,25 +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-04-17` - Gemini 2.5 Flash preview
48
- - `gemini-2.5-pro-exp-03-25` - free experimental release of Gemini 2.5 Pro
49
- - `gemini-2.5-pro-preview-03-25` - paid preview of Gemini 2.5 Pro
50
- - `gemma-3-27b-it` - [Gemma 3](https://blog.google/technology/developers/gemma-3/) 27B
51
- - `gemini-2.0-pro-exp-02-05` - experimental release of Gemini 2.0 Pro
52
- - `gemini-2.0-flash-lite` - Gemini 2.0 Flash-Lite
53
- - `gemini-2.0-flash` - Gemini 2.0 Flash
54
- - `gemini-2.0-flash-thinking-exp-01-21` - experimental "thinking" model from January 2025
55
- - `gemini-2.0-flash-thinking-exp-1219` - experimental "thinking" model from December 2024
56
- - `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).
57
- - `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)
58
- - `gemini-exp-1206` - recent experimental #3
59
- - `gemini-exp-1121` - recent experimental #2
60
- - `gemini-exp-1114` - recent experimental #1
61
- - `gemini-1.5-flash-8b-latest` - the least expensive
62
- - `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
+ ```
63
109
 
64
110
  ### Images, audio and video
65
111
 
@@ -132,6 +178,31 @@ To chat interactively with the model, run `llm chat`:
132
178
  llm chat -m gemini-2.0-flash
133
179
  ```
134
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
+
135
206
  ## Embeddings
136
207
 
137
208
  The plugin also adds support for the `gemini-embedding-exp-03-07` and `text-embedding-004` embedding models.
@@ -164,6 +235,21 @@ llm similar readmes -c 'upload csvs to stuff' -d embed.db
164
235
 
165
236
  See the [LLM embeddings documentation](https://llm.datasette.io/en/stable/embeddings/cli.html) for further details.
166
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
+
167
253
  ## Development
168
254
 
169
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.20a1
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,25 +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-04-17` - Gemini 2.5 Flash preview
70
- - `gemini-2.5-pro-exp-03-25` - free experimental release of Gemini 2.5 Pro
71
- - `gemini-2.5-pro-preview-03-25` - paid preview of Gemini 2.5 Pro
72
- - `gemma-3-27b-it` - [Gemma 3](https://blog.google/technology/developers/gemma-3/) 27B
73
- - `gemini-2.0-pro-exp-02-05` - experimental release of Gemini 2.0 Pro
74
- - `gemini-2.0-flash-lite` - Gemini 2.0 Flash-Lite
75
- - `gemini-2.0-flash` - Gemini 2.0 Flash
76
- - `gemini-2.0-flash-thinking-exp-01-21` - experimental "thinking" model from January 2025
77
- - `gemini-2.0-flash-thinking-exp-1219` - experimental "thinking" model from December 2024
78
- - `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).
79
- - `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)
80
- - `gemini-exp-1206` - recent experimental #3
81
- - `gemini-exp-1121` - recent experimental #2
82
- - `gemini-exp-1114` - recent experimental #1
83
- - `gemini-1.5-flash-8b-latest` - the least expensive
84
- - `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
+ ```
85
132
 
86
133
  ### Images, audio and video
87
134
 
@@ -154,6 +201,31 @@ To chat interactively with the model, run `llm chat`:
154
201
  llm chat -m gemini-2.0-flash
155
202
  ```
156
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
+
157
229
  ## Embeddings
158
230
 
159
231
  The plugin also adds support for the `gemini-embedding-exp-03-07` and `text-embedding-004` embedding models.
@@ -186,6 +258,21 @@ llm similar readmes -c 'upload csvs to stuff' -d embed.db
186
258
 
187
259
  See the [LLM embeddings documentation](https://llm.datasette.io/en/stable/embeddings/cli.html) for further details.
188
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
+
189
276
  ## Development
190
277
 
191
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
@@ -40,6 +40,7 @@ GOOGLE_SEARCH_MODELS = {
40
40
  "gemini-2.5-pro-exp-03-25",
41
41
  "gemini-2.5-flash-preview-04-17",
42
42
  "gemini-2.5-pro-preview-05-06",
43
+ "gemini-2.5-flash-preview-05-20",
43
44
  }
44
45
 
45
46
  # Older Google models used google_search_retrieval instead of google_search
@@ -54,14 +55,56 @@ GOOGLE_SEARCH_MODELS_USING_SEARCH_RETRIEVAL = {
54
55
  }
55
56
 
56
57
  THINKING_BUDGET_MODELS = {
58
+ "gemini-2.0-flash-thinking-exp-01-21",
59
+ "gemini-2.0-flash-thinking-exp-1219",
57
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",
64
+ "gemini-2.5-flash-preview-05-20",
65
+ }
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",
58
101
  }
59
102
 
60
103
 
61
104
  @llm.hookimpl
62
105
  def register_models(register):
63
106
  # Register both sync and async versions of each model
64
- for model_id in [
107
+ for model_id in (
65
108
  "gemini-pro",
66
109
  "gemini-1.5-pro-latest",
67
110
  "gemini-1.5-flash-latest",
@@ -76,6 +119,12 @@ def register_models(register):
76
119
  "gemini-exp-1206",
77
120
  "gemini-2.0-flash-exp",
78
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
79
128
  "gemini-2.0-flash-thinking-exp-1219",
80
129
  "gemini-2.0-flash-thinking-exp-01-21",
81
130
  # Released 5th Feb 2025:
@@ -83,8 +132,6 @@ def register_models(register):
83
132
  "gemini-2.0-pro-exp-02-05",
84
133
  # Released 25th Feb 2025:
85
134
  "gemini-2.0-flash-lite",
86
- # Released 12th March 2025:
87
- "gemma-3-27b-it",
88
135
  # 25th March 2025:
89
136
  "gemini-2.5-pro-exp-03-25",
90
137
  # 4th April 2025 (paid):
@@ -93,22 +140,29 @@ def register_models(register):
93
140
  "gemini-2.5-flash-preview-04-17",
94
141
  # 6th May 2025:
95
142
  "gemini-2.5-pro-preview-05-06",
96
- ]:
143
+ # 20th May 2025:
144
+ "gemini-2.5-flash-preview-05-20",
145
+ ):
97
146
  can_google_search = model_id in GOOGLE_SEARCH_MODELS
98
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
99
150
  register(
100
151
  GeminiPro(
101
152
  model_id,
153
+ can_vision=can_vision,
102
154
  can_google_search=can_google_search,
103
155
  can_thinking_budget=can_thinking_budget,
104
- can_schema="flash-thinking" not in model_id,
156
+ can_schema=can_schema,
105
157
  ),
106
158
  AsyncGeminiPro(
107
159
  model_id,
160
+ can_vision=can_vision,
108
161
  can_google_search=can_google_search,
109
162
  can_thinking_budget=can_thinking_budget,
110
- can_schema="flash-thinking" not in model_id,
163
+ can_schema=can_schema,
111
164
  ),
165
+ aliases=(model_id,),
112
166
  )
113
167
 
114
168
 
@@ -150,39 +204,7 @@ class _SharedGemini:
150
204
  supports_schema = True
151
205
  supports_tools = True
152
206
 
153
- attachment_types = (
154
- # Text
155
- "text/plain",
156
- "text/csv",
157
- # PDF
158
- "application/pdf",
159
- # Images
160
- "image/png",
161
- "image/jpeg",
162
- "image/webp",
163
- "image/heic",
164
- "image/heif",
165
- # Audio
166
- "audio/wav",
167
- "audio/mp3",
168
- "audio/aiff",
169
- "audio/aac",
170
- "audio/ogg",
171
- "application/ogg",
172
- "audio/flac",
173
- "audio/mpeg", # Treated as audio/mp3
174
- # Video
175
- "video/mp4",
176
- "video/mpeg",
177
- "video/mov",
178
- "video/avi",
179
- "video/x-flv",
180
- "video/mpg",
181
- "video/webm",
182
- "video/wmv",
183
- "video/3gpp",
184
- "video/quicktime",
185
- )
207
+ attachment_types = set()
186
208
 
187
209
  class Options(llm.Options):
188
210
  code_execution: Optional[bool] = Field(
@@ -228,6 +250,14 @@ class _SharedGemini:
228
250
  description="Output a valid JSON object {...}",
229
251
  default=None,
230
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
+ )
231
261
 
232
262
  class OptionsWithGoogleSearch(Options):
233
263
  google_search: Optional[bool] = Field(
@@ -243,12 +273,14 @@ class _SharedGemini:
243
273
 
244
274
  def __init__(
245
275
  self,
246
- model_id,
276
+ gemini_model_id,
277
+ can_vision=True,
247
278
  can_google_search=False,
248
279
  can_thinking_budget=False,
249
280
  can_schema=False,
250
281
  ):
251
- self.model_id = model_id
282
+ self.model_id = "gemini/{}".format(gemini_model_id)
283
+ self.gemini_model_id = gemini_model_id
252
284
  self.can_google_search = can_google_search
253
285
  self.supports_schema = can_schema
254
286
  if can_google_search:
@@ -256,6 +288,8 @@ class _SharedGemini:
256
288
  self.can_thinking_budget = can_thinking_budget
257
289
  if can_thinking_budget:
258
290
  self.Options = self.OptionsWithThinkingBudget
291
+ if can_vision:
292
+ self.attachment_types = ATTACHMENT_TYPES
259
293
 
260
294
  def build_messages(self, prompt, conversation):
261
295
  messages = []
@@ -453,14 +487,14 @@ class _SharedGemini:
453
487
 
454
488
  class GeminiPro(_SharedGemini, llm.KeyModel):
455
489
  def execute(self, prompt, stream, response, conversation, key):
456
- 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"
457
491
  gathered = []
458
492
  body = self.build_request_body(prompt, conversation)
459
493
 
460
494
  with httpx.stream(
461
495
  "POST",
462
496
  url,
463
- timeout=None,
497
+ timeout=prompt.options.timeout,
464
498
  headers={"x-goog-api-key": self.get_key(key)},
465
499
  json=body,
466
500
  ) as http_response:
@@ -486,7 +520,7 @@ class GeminiPro(_SharedGemini, llm.KeyModel):
486
520
 
487
521
  class AsyncGeminiPro(_SharedGemini, llm.AsyncKeyModel):
488
522
  async def execute(self, prompt, stream, response, conversation, key):
489
- 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"
490
524
  gathered = []
491
525
  body = self.build_request_body(prompt, conversation)
492
526
 
@@ -494,7 +528,7 @@ class AsyncGeminiPro(_SharedGemini, llm.AsyncKeyModel):
494
528
  async with client.stream(
495
529
  "POST",
496
530
  url,
497
- timeout=None,
531
+ timeout=prompt.options.timeout,
498
532
  headers={"x-goog-api-key": self.get_key(key)},
499
533
  json=body,
500
534
  ) as http_response:
@@ -584,8 +618,20 @@ def register_commands(cli):
584
618
 
585
619
  @gemini.command()
586
620
  @click.option("--key", help="API key to use")
587
- def models(key):
588
- "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
+ """
589
635
  key = llm.get_key(key, "gemini", "LLM_GEMINI_KEY")
590
636
  if not key:
591
637
  raise click.ClickException(
@@ -594,7 +640,16 @@ def register_commands(cli):
594
640
  url = f"https://generativelanguage.googleapis.com/v1beta/models"
595
641
  response = httpx.get(url, headers={"x-goog-api-key": key})
596
642
  response.raise_for_status()
597
- 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))
598
653
 
599
654
  @gemini.command()
600
655
  @click.option("--key", help="API key to use")
@@ -1,13 +1,13 @@
1
1
  [project]
2
2
  name = "llm-gemini"
3
- version = "0.20a1"
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