llm-gemini 0.20a2__tar.gz → 0.22__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.22
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,72 @@ 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-06-05": "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-pro-preview-06-05`: Latest paid Gemini 2.5 Pro preview
97
+ - `gemini/gemini-2.5-flash-preview-05-20`: Gemini 2.5 Flash preview
98
+ - `gemini/gemini-2.5-pro-preview-05-06`
99
+ - `gemini/gemini-2.5-flash-preview-04-17`: Earlier Gemini 2.5 Flash preview
100
+ - `gemini/gemini-2.5-pro-preview-03-25`
101
+ - `gemini/gemini-2.5-pro-exp-03-25`: Free experimental release of Gemini 2.5 Pro
102
+ - `gemini/gemini-2.0-flash-lite`
103
+ - `gemini/gemini-2.0-pro-exp-02-05`
104
+ - `gemini/gemini-2.0-flash`
105
+ - `gemini/gemini-2.0-flash-thinking-exp-01-21`: Experimental "thinking" model from January 2025
106
+ - `gemini/gemini-2.0-flash-thinking-exp-1219`
107
+ - `gemini/gemma-3n-e4b-it`
108
+ - `gemini/gemma-3-27b-it`
109
+ - `gemini/gemma-3-12b-it`
110
+ - `gemini/gemma-3-4b-it`
111
+ - `gemini/gemma-3-1b-it`
112
+ - `gemini/learnlm-1.5-pro-experimental`
113
+ - `gemini/gemini-2.0-flash-exp`
114
+ - `gemini/gemini-exp-1206`
115
+ - `gemini/gemini-exp-1121`
116
+ - `gemini/gemini-exp-1114`
117
+ - `gemini/gemini-1.5-flash-8b-001`
118
+ - `gemini/gemini-1.5-flash-8b-latest`: The least expensive model
119
+ - `gemini/gemini-1.5-flash-002`
120
+ - `gemini/gemini-1.5-pro-002`
121
+ - `gemini/gemini-1.5-flash-001`
122
+ - `gemini/gemini-1.5-pro-001`
123
+ - `gemini/gemini-1.5-flash-latest`
124
+ - `gemini/gemini-1.5-pro-latest`
125
+ - `gemini/gemini-pro`
126
+ <!-- [[[end]]] -->
127
+
128
+ All of these models have aliases that omit the `gemini/` prefix, for example:
129
+
130
+ ```bash
131
+ llm -m gemini-1.5-flash-8b-latest --schema 'name,age int,bio' 'invent a dog'
132
+ ```
86
133
 
87
134
  ### Images, audio and video
88
135
 
@@ -155,6 +202,31 @@ To chat interactively with the model, run `llm chat`:
155
202
  llm chat -m gemini-2.0-flash
156
203
  ```
157
204
 
205
+ ### Timeouts
206
+
207
+ By default there is no `timeout` against the Gemini API. You can use the `timeout` option to protect against API requests that hang indefinitely.
208
+
209
+ With the CLI tool that looks like this, to set a 1.5 second timeout:
210
+
211
+ ```bash
212
+ llm -m gemini-2.5-flash-preview-05-20 'epic saga about mice' -o timeout 1.5
213
+ ```
214
+ In the Python library timeouts are used like this:
215
+ ```python
216
+ import httpx, llm
217
+
218
+ model = llm.get_model("gemini/gemini-2.5-flash-preview-05-20")
219
+
220
+ try:
221
+ response = model.prompt(
222
+ "epic saga about mice", timeout=1.5
223
+ )
224
+ print(response.text())
225
+ except httpx.TimeoutException:
226
+ print("Timeout exceeded")
227
+ ```
228
+ An `httpx.TimeoutException` subclass will be raised if the timeout is exceeded.
229
+
158
230
  ## Embeddings
159
231
 
160
232
  The plugin also adds support for the `gemini-embedding-exp-03-07` and `text-embedding-004` embedding models.
@@ -187,6 +259,21 @@ llm similar readmes -c 'upload csvs to stuff' -d embed.db
187
259
 
188
260
  See the [LLM embeddings documentation](https://llm.datasette.io/en/stable/embeddings/cli.html) for further details.
189
261
 
262
+ ## Listing all Gemini API models
263
+
264
+ 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.
265
+
266
+ ```bash
267
+ llm gemini models
268
+ ```
269
+ You can add a `--key X` option to use a different API key.
270
+
271
+ To filter models by their supported generation methods use `--method` one or more times:
272
+ ```bash
273
+ llm gemini models --method embedContent
274
+ ```
275
+ If you provide multiple methods you will see models that support any of them.
276
+
190
277
  ## Development
191
278
 
192
279
  To set up this plugin locally, first checkout the code. Then create a new virtual environment:
@@ -41,26 +41,72 @@ 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-06-05": "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-pro-preview-06-05`: Latest paid Gemini 2.5 Pro preview
74
+ - `gemini/gemini-2.5-flash-preview-05-20`: Gemini 2.5 Flash preview
75
+ - `gemini/gemini-2.5-pro-preview-05-06`
76
+ - `gemini/gemini-2.5-flash-preview-04-17`: Earlier Gemini 2.5 Flash preview
77
+ - `gemini/gemini-2.5-pro-preview-03-25`
78
+ - `gemini/gemini-2.5-pro-exp-03-25`: Free experimental release of Gemini 2.5 Pro
79
+ - `gemini/gemini-2.0-flash-lite`
80
+ - `gemini/gemini-2.0-pro-exp-02-05`
81
+ - `gemini/gemini-2.0-flash`
82
+ - `gemini/gemini-2.0-flash-thinking-exp-01-21`: Experimental "thinking" model from January 2025
83
+ - `gemini/gemini-2.0-flash-thinking-exp-1219`
84
+ - `gemini/gemma-3n-e4b-it`
85
+ - `gemini/gemma-3-27b-it`
86
+ - `gemini/gemma-3-12b-it`
87
+ - `gemini/gemma-3-4b-it`
88
+ - `gemini/gemma-3-1b-it`
89
+ - `gemini/learnlm-1.5-pro-experimental`
90
+ - `gemini/gemini-2.0-flash-exp`
91
+ - `gemini/gemini-exp-1206`
92
+ - `gemini/gemini-exp-1121`
93
+ - `gemini/gemini-exp-1114`
94
+ - `gemini/gemini-1.5-flash-8b-001`
95
+ - `gemini/gemini-1.5-flash-8b-latest`: The least expensive model
96
+ - `gemini/gemini-1.5-flash-002`
97
+ - `gemini/gemini-1.5-pro-002`
98
+ - `gemini/gemini-1.5-flash-001`
99
+ - `gemini/gemini-1.5-pro-001`
100
+ - `gemini/gemini-1.5-flash-latest`
101
+ - `gemini/gemini-1.5-pro-latest`
102
+ - `gemini/gemini-pro`
103
+ <!-- [[[end]]] -->
104
+
105
+ All of these models have aliases that omit the `gemini/` prefix, for example:
106
+
107
+ ```bash
108
+ llm -m gemini-1.5-flash-8b-latest --schema 'name,age int,bio' 'invent a dog'
109
+ ```
64
110
 
65
111
  ### Images, audio and video
66
112
 
@@ -133,6 +179,31 @@ To chat interactively with the model, run `llm chat`:
133
179
  llm chat -m gemini-2.0-flash
134
180
  ```
135
181
 
182
+ ### Timeouts
183
+
184
+ By default there is no `timeout` against the Gemini API. You can use the `timeout` option to protect against API requests that hang indefinitely.
185
+
186
+ With the CLI tool that looks like this, to set a 1.5 second timeout:
187
+
188
+ ```bash
189
+ llm -m gemini-2.5-flash-preview-05-20 'epic saga about mice' -o timeout 1.5
190
+ ```
191
+ In the Python library timeouts are used like this:
192
+ ```python
193
+ import httpx, llm
194
+
195
+ model = llm.get_model("gemini/gemini-2.5-flash-preview-05-20")
196
+
197
+ try:
198
+ response = model.prompt(
199
+ "epic saga about mice", timeout=1.5
200
+ )
201
+ print(response.text())
202
+ except httpx.TimeoutException:
203
+ print("Timeout exceeded")
204
+ ```
205
+ An `httpx.TimeoutException` subclass will be raised if the timeout is exceeded.
206
+
136
207
  ## Embeddings
137
208
 
138
209
  The plugin also adds support for the `gemini-embedding-exp-03-07` and `text-embedding-004` embedding models.
@@ -165,6 +236,21 @@ llm similar readmes -c 'upload csvs to stuff' -d embed.db
165
236
 
166
237
  See the [LLM embeddings documentation](https://llm.datasette.io/en/stable/embeddings/cli.html) for further details.
167
238
 
239
+ ## Listing all Gemini API models
240
+
241
+ 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.
242
+
243
+ ```bash
244
+ llm gemini models
245
+ ```
246
+ You can add a `--key X` option to use a different API key.
247
+
248
+ To filter models by their supported generation methods use `--method` one or more times:
249
+ ```bash
250
+ llm gemini models --method embedContent
251
+ ```
252
+ If you provide multiple methods you will see models that support any of them.
253
+
168
254
  ## Development
169
255
 
170
256
  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.22
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,72 @@ 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-06-05": "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-pro-preview-06-05`: Latest paid Gemini 2.5 Pro preview
97
+ - `gemini/gemini-2.5-flash-preview-05-20`: Gemini 2.5 Flash preview
98
+ - `gemini/gemini-2.5-pro-preview-05-06`
99
+ - `gemini/gemini-2.5-flash-preview-04-17`: Earlier Gemini 2.5 Flash preview
100
+ - `gemini/gemini-2.5-pro-preview-03-25`
101
+ - `gemini/gemini-2.5-pro-exp-03-25`: Free experimental release of Gemini 2.5 Pro
102
+ - `gemini/gemini-2.0-flash-lite`
103
+ - `gemini/gemini-2.0-pro-exp-02-05`
104
+ - `gemini/gemini-2.0-flash`
105
+ - `gemini/gemini-2.0-flash-thinking-exp-01-21`: Experimental "thinking" model from January 2025
106
+ - `gemini/gemini-2.0-flash-thinking-exp-1219`
107
+ - `gemini/gemma-3n-e4b-it`
108
+ - `gemini/gemma-3-27b-it`
109
+ - `gemini/gemma-3-12b-it`
110
+ - `gemini/gemma-3-4b-it`
111
+ - `gemini/gemma-3-1b-it`
112
+ - `gemini/learnlm-1.5-pro-experimental`
113
+ - `gemini/gemini-2.0-flash-exp`
114
+ - `gemini/gemini-exp-1206`
115
+ - `gemini/gemini-exp-1121`
116
+ - `gemini/gemini-exp-1114`
117
+ - `gemini/gemini-1.5-flash-8b-001`
118
+ - `gemini/gemini-1.5-flash-8b-latest`: The least expensive model
119
+ - `gemini/gemini-1.5-flash-002`
120
+ - `gemini/gemini-1.5-pro-002`
121
+ - `gemini/gemini-1.5-flash-001`
122
+ - `gemini/gemini-1.5-pro-001`
123
+ - `gemini/gemini-1.5-flash-latest`
124
+ - `gemini/gemini-1.5-pro-latest`
125
+ - `gemini/gemini-pro`
126
+ <!-- [[[end]]] -->
127
+
128
+ All of these models have aliases that omit the `gemini/` prefix, for example:
129
+
130
+ ```bash
131
+ llm -m gemini-1.5-flash-8b-latest --schema 'name,age int,bio' 'invent a dog'
132
+ ```
86
133
 
87
134
  ### Images, audio and video
88
135
 
@@ -155,6 +202,31 @@ To chat interactively with the model, run `llm chat`:
155
202
  llm chat -m gemini-2.0-flash
156
203
  ```
157
204
 
205
+ ### Timeouts
206
+
207
+ By default there is no `timeout` against the Gemini API. You can use the `timeout` option to protect against API requests that hang indefinitely.
208
+
209
+ With the CLI tool that looks like this, to set a 1.5 second timeout:
210
+
211
+ ```bash
212
+ llm -m gemini-2.5-flash-preview-05-20 'epic saga about mice' -o timeout 1.5
213
+ ```
214
+ In the Python library timeouts are used like this:
215
+ ```python
216
+ import httpx, llm
217
+
218
+ model = llm.get_model("gemini/gemini-2.5-flash-preview-05-20")
219
+
220
+ try:
221
+ response = model.prompt(
222
+ "epic saga about mice", timeout=1.5
223
+ )
224
+ print(response.text())
225
+ except httpx.TimeoutException:
226
+ print("Timeout exceeded")
227
+ ```
228
+ An `httpx.TimeoutException` subclass will be raised if the timeout is exceeded.
229
+
158
230
  ## Embeddings
159
231
 
160
232
  The plugin also adds support for the `gemini-embedding-exp-03-07` and `text-embedding-004` embedding models.
@@ -187,6 +259,21 @@ llm similar readmes -c 'upload csvs to stuff' -d embed.db
187
259
 
188
260
  See the [LLM embeddings documentation](https://llm.datasette.io/en/stable/embeddings/cli.html) for further details.
189
261
 
262
+ ## Listing all Gemini API models
263
+
264
+ 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.
265
+
266
+ ```bash
267
+ llm gemini models
268
+ ```
269
+ You can add a `--key X` option to use a different API key.
270
+
271
+ To filter models by their supported generation methods use `--method` one or more times:
272
+ ```bash
273
+ llm gemini models --method embedContent
274
+ ```
275
+ If you provide multiple methods you will see models that support any of them.
276
+
190
277
  ## Development
191
278
 
192
279
  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
@@ -41,6 +41,7 @@ GOOGLE_SEARCH_MODELS = {
41
41
  "gemini-2.5-flash-preview-04-17",
42
42
  "gemini-2.5-pro-preview-05-06",
43
43
  "gemini-2.5-flash-preview-05-20",
44
+ "gemini-2.5-pro-preview-06-05",
44
45
  }
45
46
 
46
47
  # Older Google models used google_search_retrieval instead of google_search
@@ -55,15 +56,57 @@ GOOGLE_SEARCH_MODELS_USING_SEARCH_RETRIEVAL = {
55
56
  }
56
57
 
57
58
  THINKING_BUDGET_MODELS = {
59
+ "gemini-2.0-flash-thinking-exp-01-21",
60
+ "gemini-2.0-flash-thinking-exp-1219",
58
61
  "gemini-2.5-flash-preview-04-17",
62
+ "gemini-2.5-pro-exp-03-25",
63
+ "gemini-2.5-pro-preview-03-25",
64
+ "gemini-2.5-pro-preview-05-06",
59
65
  "gemini-2.5-flash-preview-05-20",
66
+ "gemini-2.5-pro-preview-06-05",
67
+ }
68
+
69
+ NO_VISION_MODELS = {"gemma-3-1b-it", "gemma-3n-e4b-it"}
70
+
71
+ ATTACHMENT_TYPES = {
72
+ # Text
73
+ "text/plain",
74
+ "text/csv",
75
+ # PDF
76
+ "application/pdf",
77
+ # Images
78
+ "image/png",
79
+ "image/jpeg",
80
+ "image/webp",
81
+ "image/heic",
82
+ "image/heif",
83
+ # Audio
84
+ "audio/wav",
85
+ "audio/mp3",
86
+ "audio/aiff",
87
+ "audio/aac",
88
+ "audio/ogg",
89
+ "application/ogg",
90
+ "audio/flac",
91
+ "audio/mpeg", # Treated as audio/mp3
92
+ # Video
93
+ "video/mp4",
94
+ "video/mpeg",
95
+ "video/mov",
96
+ "video/avi",
97
+ "video/x-flv",
98
+ "video/mpg",
99
+ "video/webm",
100
+ "video/wmv",
101
+ "video/3gpp",
102
+ "video/quicktime",
60
103
  }
61
104
 
62
105
 
63
106
  @llm.hookimpl
64
107
  def register_models(register):
65
108
  # Register both sync and async versions of each model
66
- for model_id in [
109
+ for model_id in (
67
110
  "gemini-pro",
68
111
  "gemini-1.5-pro-latest",
69
112
  "gemini-1.5-flash-latest",
@@ -78,6 +121,12 @@ def register_models(register):
78
121
  "gemini-exp-1206",
79
122
  "gemini-2.0-flash-exp",
80
123
  "learnlm-1.5-pro-experimental",
124
+ # Gemma 3 models:
125
+ "gemma-3-1b-it",
126
+ "gemma-3-4b-it",
127
+ "gemma-3-12b-it", # 12th March 2025
128
+ "gemma-3-27b-it",
129
+ "gemma-3n-e4b-it", # 20th May 2025
81
130
  "gemini-2.0-flash-thinking-exp-1219",
82
131
  "gemini-2.0-flash-thinking-exp-01-21",
83
132
  # Released 5th Feb 2025:
@@ -85,8 +134,6 @@ def register_models(register):
85
134
  "gemini-2.0-pro-exp-02-05",
86
135
  # Released 25th Feb 2025:
87
136
  "gemini-2.0-flash-lite",
88
- # Released 12th March 2025:
89
- "gemma-3-27b-it",
90
137
  # 25th March 2025:
91
138
  "gemini-2.5-pro-exp-03-25",
92
139
  # 4th April 2025 (paid):
@@ -97,22 +144,29 @@ def register_models(register):
97
144
  "gemini-2.5-pro-preview-05-06",
98
145
  # 20th May 2025:
99
146
  "gemini-2.5-flash-preview-05-20",
100
- ]:
147
+ # 5th June 2025:
148
+ "gemini-2.5-pro-preview-06-05",
149
+ ):
101
150
  can_google_search = model_id in GOOGLE_SEARCH_MODELS
102
151
  can_thinking_budget = model_id in THINKING_BUDGET_MODELS
152
+ can_vision = model_id not in NO_VISION_MODELS
153
+ can_schema = "flash-thinking" not in model_id and "gemma-3" not in model_id
103
154
  register(
104
155
  GeminiPro(
105
156
  model_id,
157
+ can_vision=can_vision,
106
158
  can_google_search=can_google_search,
107
159
  can_thinking_budget=can_thinking_budget,
108
- can_schema="flash-thinking" not in model_id,
160
+ can_schema=can_schema,
109
161
  ),
110
162
  AsyncGeminiPro(
111
163
  model_id,
164
+ can_vision=can_vision,
112
165
  can_google_search=can_google_search,
113
166
  can_thinking_budget=can_thinking_budget,
114
- can_schema="flash-thinking" not in model_id,
167
+ can_schema=can_schema,
115
168
  ),
169
+ aliases=(model_id,),
116
170
  )
117
171
 
118
172
 
@@ -154,39 +208,7 @@ class _SharedGemini:
154
208
  supports_schema = True
155
209
  supports_tools = True
156
210
 
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
- )
211
+ attachment_types = set()
190
212
 
191
213
  class Options(llm.Options):
192
214
  code_execution: Optional[bool] = Field(
@@ -232,6 +254,14 @@ class _SharedGemini:
232
254
  description="Output a valid JSON object {...}",
233
255
  default=None,
234
256
  )
257
+ timeout: Optional[float] = Field(
258
+ description=(
259
+ "The maximum time in seconds to wait for a response. "
260
+ "If the model does not respond within this time, "
261
+ "the request will be aborted."
262
+ ),
263
+ default=None,
264
+ )
235
265
 
236
266
  class OptionsWithGoogleSearch(Options):
237
267
  google_search: Optional[bool] = Field(
@@ -247,12 +277,14 @@ class _SharedGemini:
247
277
 
248
278
  def __init__(
249
279
  self,
250
- model_id,
280
+ gemini_model_id,
281
+ can_vision=True,
251
282
  can_google_search=False,
252
283
  can_thinking_budget=False,
253
284
  can_schema=False,
254
285
  ):
255
- self.model_id = model_id
286
+ self.model_id = "gemini/{}".format(gemini_model_id)
287
+ self.gemini_model_id = gemini_model_id
256
288
  self.can_google_search = can_google_search
257
289
  self.supports_schema = can_schema
258
290
  if can_google_search:
@@ -260,6 +292,8 @@ class _SharedGemini:
260
292
  self.can_thinking_budget = can_thinking_budget
261
293
  if can_thinking_budget:
262
294
  self.Options = self.OptionsWithThinkingBudget
295
+ if can_vision:
296
+ self.attachment_types = ATTACHMENT_TYPES
263
297
 
264
298
  def build_messages(self, prompt, conversation):
265
299
  messages = []
@@ -457,14 +491,14 @@ class _SharedGemini:
457
491
 
458
492
  class GeminiPro(_SharedGemini, llm.KeyModel):
459
493
  def execute(self, prompt, stream, response, conversation, key):
460
- url = f"https://generativelanguage.googleapis.com/v1beta/models/{self.model_id}:streamGenerateContent"
494
+ url = f"https://generativelanguage.googleapis.com/v1beta/models/{self.gemini_model_id}:streamGenerateContent"
461
495
  gathered = []
462
496
  body = self.build_request_body(prompt, conversation)
463
497
 
464
498
  with httpx.stream(
465
499
  "POST",
466
500
  url,
467
- timeout=None,
501
+ timeout=prompt.options.timeout,
468
502
  headers={"x-goog-api-key": self.get_key(key)},
469
503
  json=body,
470
504
  ) as http_response:
@@ -490,7 +524,7 @@ class GeminiPro(_SharedGemini, llm.KeyModel):
490
524
 
491
525
  class AsyncGeminiPro(_SharedGemini, llm.AsyncKeyModel):
492
526
  async def execute(self, prompt, stream, response, conversation, key):
493
- url = f"https://generativelanguage.googleapis.com/v1beta/models/{self.model_id}:streamGenerateContent"
527
+ url = f"https://generativelanguage.googleapis.com/v1beta/models/{self.gemini_model_id}:streamGenerateContent"
494
528
  gathered = []
495
529
  body = self.build_request_body(prompt, conversation)
496
530
 
@@ -498,7 +532,7 @@ class AsyncGeminiPro(_SharedGemini, llm.AsyncKeyModel):
498
532
  async with client.stream(
499
533
  "POST",
500
534
  url,
501
- timeout=None,
535
+ timeout=prompt.options.timeout,
502
536
  headers={"x-goog-api-key": self.get_key(key)},
503
537
  json=body,
504
538
  ) as http_response:
@@ -588,8 +622,20 @@ def register_commands(cli):
588
622
 
589
623
  @gemini.command()
590
624
  @click.option("--key", help="API key to use")
591
- def models(key):
592
- "List of Gemini models pulled from their API"
625
+ @click.option(
626
+ "methods",
627
+ "--method",
628
+ multiple=True,
629
+ help="Filter by supported generation methods",
630
+ )
631
+ def models(key, methods):
632
+ """
633
+ List of Gemini models pulled from their API
634
+
635
+ Use --method to filter by supported generation methods for example:
636
+
637
+ llm gemini models --method generateContent --method embedContent
638
+ """
593
639
  key = llm.get_key(key, "gemini", "LLM_GEMINI_KEY")
594
640
  if not key:
595
641
  raise click.ClickException(
@@ -598,7 +644,16 @@ def register_commands(cli):
598
644
  url = f"https://generativelanguage.googleapis.com/v1beta/models"
599
645
  response = httpx.get(url, headers={"x-goog-api-key": key})
600
646
  response.raise_for_status()
601
- click.echo(json.dumps(response.json()["models"], indent=2))
647
+ models = response.json()["models"]
648
+ if methods:
649
+ models = [
650
+ model
651
+ for model in models
652
+ if any(
653
+ method in model["supportedGenerationMethods"] for method in methods
654
+ )
655
+ ]
656
+ click.echo(json.dumps(models, indent=2))
602
657
 
603
658
  @gemini.command()
604
659
  @click.option("--key", help="API key to use")
@@ -609,4 +664,7 @@ def register_commands(cli):
609
664
  f"https://generativelanguage.googleapis.com/v1beta/files?key={key}",
610
665
  )
611
666
  response.raise_for_status()
612
- click.echo(json.dumps(response.json()["files"], indent=2))
667
+ if "files" in response.json():
668
+ click.echo(json.dumps(response.json()["files"], indent=2))
669
+ else:
670
+ click.echo("No files uploaded to the Gemini API.", err=True)
@@ -1,13 +1,13 @@
1
1
  [project]
2
2
  name = "llm-gemini"
3
- version = "0.20a2"
3
+ version = "0.22"
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