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.
- {llm_gemini-0.20a2 → llm_gemini-0.22}/PKG-INFO +109 -22
- {llm_gemini-0.20a2 → llm_gemini-0.22}/README.md +106 -20
- {llm_gemini-0.20a2 → llm_gemini-0.22}/llm_gemini.egg-info/PKG-INFO +109 -22
- {llm_gemini-0.20a2 → llm_gemini-0.22}/llm_gemini.egg-info/requires.txt +2 -1
- {llm_gemini-0.20a2 → llm_gemini-0.22}/llm_gemini.py +107 -49
- {llm_gemini-0.20a2 → llm_gemini-0.22}/pyproject.toml +3 -3
- {llm_gemini-0.20a2 → llm_gemini-0.22}/tests/test_gemini.py +8 -0
- {llm_gemini-0.20a2 → llm_gemini-0.22}/LICENSE +0 -0
- {llm_gemini-0.20a2 → llm_gemini-0.22}/llm_gemini.egg-info/SOURCES.txt +0 -0
- {llm_gemini-0.20a2 → llm_gemini-0.22}/llm_gemini.egg-info/dependency_links.txt +0 -0
- {llm_gemini-0.20a2 → llm_gemini-0.22}/llm_gemini.egg-info/entry_points.txt +0 -0
- {llm_gemini-0.20a2 → llm_gemini-0.22}/llm_gemini.egg-info/top_level.txt +0 -0
- {llm_gemini-0.20a2 → llm_gemini-0.22}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: llm-gemini
|
3
|
-
Version: 0.
|
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.
|
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
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
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
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
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.
|
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.
|
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
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
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,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=
|
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=
|
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
|
-
|
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 =
|
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.
|
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=
|
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.
|
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=
|
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
|
-
|
592
|
-
"
|
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
|
-
|
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
|
-
|
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.
|
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.
|
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
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|