gemini-webapi 1.6.1__tar.gz → 1.17.0__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.
- {gemini_webapi-1.6.1 → gemini_webapi-1.17.0}/.github/workflows/github-release.yml +1 -1
- {gemini_webapi-1.6.1 → gemini_webapi-1.17.0}/.github/workflows/pypi-publish.yml +5 -5
- {gemini_webapi-1.6.1 → gemini_webapi-1.17.0}/.gitignore +1 -1
- {gemini_webapi-1.6.1 → gemini_webapi-1.17.0}/PKG-INFO +213 -56
- {gemini_webapi-1.6.1 → gemini_webapi-1.17.0}/README.md +206 -51
- gemini_webapi-1.17.0/assets/sample.pdf +0 -0
- {gemini_webapi-1.6.1 → gemini_webapi-1.17.0}/pyproject.toml +4 -3
- gemini_webapi-1.17.0/src/gemini_webapi/__init__.py +6 -0
- {gemini_webapi-1.6.1 → gemini_webapi-1.17.0}/src/gemini_webapi/client.py +331 -154
- gemini_webapi-1.17.0/src/gemini_webapi/components/__init__.py +3 -0
- gemini_webapi-1.17.0/src/gemini_webapi/components/gem_mixin.py +288 -0
- gemini_webapi-1.17.0/src/gemini_webapi/constants.py +85 -0
- {gemini_webapi-1.6.1 → gemini_webapi-1.17.0}/src/gemini_webapi/exceptions.py +32 -0
- gemini_webapi-1.17.0/src/gemini_webapi/types/__init__.py +7 -0
- {gemini_webapi-1.6.1 → gemini_webapi-1.17.0}/src/gemini_webapi/types/candidate.py +16 -1
- gemini_webapi-1.17.0/src/gemini_webapi/types/gem.py +132 -0
- gemini_webapi-1.17.0/src/gemini_webapi/types/grpc.py +34 -0
- {gemini_webapi-1.6.1 → gemini_webapi-1.17.0}/src/gemini_webapi/types/image.py +14 -9
- {gemini_webapi-1.6.1 → gemini_webapi-1.17.0}/src/gemini_webapi/types/modeloutput.py +4 -0
- gemini_webapi-1.17.0/src/gemini_webapi/utils/__init__.py +14 -0
- gemini_webapi-1.17.0/src/gemini_webapi/utils/decorators.py +52 -0
- {gemini_webapi-1.6.1 → gemini_webapi-1.17.0}/src/gemini_webapi/utils/get_access_token.py +80 -24
- {gemini_webapi-1.6.1 → gemini_webapi-1.17.0}/src/gemini_webapi/utils/load_browser_cookies.py +10 -4
- gemini_webapi-1.17.0/src/gemini_webapi/utils/logger.py +37 -0
- gemini_webapi-1.17.0/src/gemini_webapi/utils/parsing.py +79 -0
- {gemini_webapi-1.6.1 → gemini_webapi-1.17.0}/src/gemini_webapi/utils/rotate_1psidts.py +9 -5
- {gemini_webapi-1.6.1 → gemini_webapi-1.17.0}/src/gemini_webapi/utils/upload_file.py +30 -9
- {gemini_webapi-1.6.1 → gemini_webapi-1.17.0}/src/gemini_webapi.egg-info/PKG-INFO +213 -56
- {gemini_webapi-1.6.1 → gemini_webapi-1.17.0}/src/gemini_webapi.egg-info/SOURCES.txt +8 -1
- gemini_webapi-1.17.0/src/gemini_webapi.egg-info/requires.txt +4 -0
- {gemini_webapi-1.6.1 → gemini_webapi-1.17.0}/tests/test_client_features.py +86 -34
- gemini_webapi-1.17.0/tests/test_gem_mixin.py +88 -0
- {gemini_webapi-1.6.1 → gemini_webapi-1.17.0}/tests/test_save_image.py +15 -9
- gemini_webapi-1.6.1/src/gemini_webapi/__init__.py +0 -4
- gemini_webapi-1.6.1/src/gemini_webapi/constants.py +0 -23
- gemini_webapi-1.6.1/src/gemini_webapi/types/__init__.py +0 -3
- gemini_webapi-1.6.1/src/gemini_webapi/utils/__init__.py +0 -10
- gemini_webapi-1.6.1/src/gemini_webapi/utils/logger.py +0 -39
- gemini_webapi-1.6.1/src/gemini_webapi.egg-info/requires.txt +0 -3
- gemini_webapi-1.6.1/tests/test_rotate_cookies.py +0 -26
- {gemini_webapi-1.6.1 → gemini_webapi-1.17.0}/.github/dependabot.yml +0 -0
- {gemini_webapi-1.6.1 → gemini_webapi-1.17.0}/.vscode/launch.json +0 -0
- {gemini_webapi-1.6.1 → gemini_webapi-1.17.0}/.vscode/settings.json +0 -0
- {gemini_webapi-1.6.1 → gemini_webapi-1.17.0}/LICENSE +0 -0
- {gemini_webapi-1.6.1 → gemini_webapi-1.17.0}/assets/banner.png +0 -0
- {gemini_webapi-1.6.1 → gemini_webapi-1.17.0}/assets/favicon.png +0 -0
- {gemini_webapi-1.6.1 → gemini_webapi-1.17.0}/assets/logo.svg +0 -0
- {gemini_webapi-1.6.1 → gemini_webapi-1.17.0}/setup.cfg +0 -0
- {gemini_webapi-1.6.1 → gemini_webapi-1.17.0}/src/gemini_webapi.egg-info/dependency_links.txt +0 -0
- {gemini_webapi-1.6.1 → gemini_webapi-1.17.0}/src/gemini_webapi.egg-info/top_level.txt +0 -0
|
@@ -24,9 +24,9 @@ jobs:
|
|
|
24
24
|
name: Build package
|
|
25
25
|
runs-on: ubuntu-latest
|
|
26
26
|
steps:
|
|
27
|
-
- uses: actions/checkout@
|
|
27
|
+
- uses: actions/checkout@v5
|
|
28
28
|
- name: Set up Python
|
|
29
|
-
uses: actions/setup-python@
|
|
29
|
+
uses: actions/setup-python@v6
|
|
30
30
|
with:
|
|
31
31
|
python-version: '3.x'
|
|
32
32
|
- name: Install dependencies
|
|
@@ -36,7 +36,7 @@ jobs:
|
|
|
36
36
|
- name: Build package
|
|
37
37
|
run: python -m build
|
|
38
38
|
- name: Archive production artifacts
|
|
39
|
-
uses: actions/upload-artifact@v4.
|
|
39
|
+
uses: actions/upload-artifact@v4.6.2
|
|
40
40
|
with:
|
|
41
41
|
name: dist
|
|
42
42
|
path: dist
|
|
@@ -52,9 +52,9 @@ jobs:
|
|
|
52
52
|
id-token: write # IMPORTANT: this permission is mandatory for trusted publishing
|
|
53
53
|
steps:
|
|
54
54
|
- name: Retrieve built artifacts
|
|
55
|
-
uses: actions/download-artifact@
|
|
55
|
+
uses: actions/download-artifact@v5.0.0
|
|
56
56
|
with:
|
|
57
57
|
name: dist
|
|
58
58
|
path: dist
|
|
59
59
|
- name: Publish package distributions to PyPI
|
|
60
|
-
uses: pypa/gh-action-pypi-publish@v1.
|
|
60
|
+
uses: pypa/gh-action-pypi-publish@v1.13.0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: gemini-webapi
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.17.0
|
|
4
4
|
Summary: ✨ An elegant async Python wrapper for Google Gemini web app
|
|
5
5
|
Author: UZQueen
|
|
6
6
|
License: GNU AFFERO GENERAL PUBLIC LICENSE
|
|
@@ -676,9 +676,11 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
676
676
|
Requires-Python: >=3.10
|
|
677
677
|
Description-Content-Type: text/markdown
|
|
678
678
|
License-File: LICENSE
|
|
679
|
-
Requires-Dist: httpx
|
|
680
|
-
Requires-Dist:
|
|
681
|
-
Requires-Dist:
|
|
679
|
+
Requires-Dist: httpx[http2]~=0.28.1
|
|
680
|
+
Requires-Dist: loguru~=0.7.3
|
|
681
|
+
Requires-Dist: orjson~=3.11.1
|
|
682
|
+
Requires-Dist: pydantic~=2.12.2
|
|
683
|
+
Dynamic: license-file
|
|
682
684
|
|
|
683
685
|
<p align="center">
|
|
684
686
|
<img src="https://raw.githubusercontent.com/HanaokaYuzu/Gemini-API/master/assets/banner.png" width="55%" alt="Gemini Banner" align="center">
|
|
@@ -711,9 +713,10 @@ A reverse-engineered asynchronous python wrapper for [Google Gemini](https://gem
|
|
|
711
713
|
## Features
|
|
712
714
|
|
|
713
715
|
- **Persistent Cookies** - Automatically refreshes cookies in background. Optimized for always-on services.
|
|
714
|
-
- **
|
|
716
|
+
- **Image Generation** - Natively supports generating and editing images with natural language.
|
|
717
|
+
- **System Prompt** - Supports customizing model's system prompt with [Gemini Gems](https://gemini.google.com/gems/view).
|
|
715
718
|
- **Extension Support** - Supports generating contents with [Gemini extensions](https://gemini.google.com/extensions) on, like YouTube and Gmail.
|
|
716
|
-
- **Classified Outputs** -
|
|
719
|
+
- **Classified Outputs** - Categorizes texts, thoughts, web images and AI generated images in the response.
|
|
717
720
|
- **Official Flavor** - Provides a simple and elegant interface inspired by [Google Generative AI](https://ai.google.dev/tutorials/python_quickstart)'s official API.
|
|
718
721
|
- **Asynchronous** - Utilizes `asyncio` to run generating tasks and return outputs efficiently.
|
|
719
722
|
|
|
@@ -725,16 +728,22 @@ A reverse-engineered asynchronous python wrapper for [Google Gemini](https://gem
|
|
|
725
728
|
- [Authentication](#authentication)
|
|
726
729
|
- [Usage](#usage)
|
|
727
730
|
- [Initialization](#initialization)
|
|
728
|
-
- [Generate contents
|
|
729
|
-
- [Generate contents
|
|
731
|
+
- [Generate contents](#generate-contents)
|
|
732
|
+
- [Generate contents with files](#generate-contents-with-files)
|
|
730
733
|
- [Conversations across multiple turns](#conversations-across-multiple-turns)
|
|
731
734
|
- [Continue previous conversations](#continue-previous-conversations)
|
|
735
|
+
- [Select language model](#select-language-model)
|
|
736
|
+
- [Apply system prompt with Gemini Gems](#apply-system-prompt-with-gemini-gems)
|
|
737
|
+
- [Manage Custom Gems](#manage-custom-gems)
|
|
738
|
+
- [Create a custom gem](#create-a-custom-gem)
|
|
739
|
+
- [Update an existing gem](#update-an-existing-gem)
|
|
740
|
+
- [Delete a custom gem](#delete-a-custom-gem)
|
|
741
|
+
- [Retrieve model's thought process](#retrieve-models-thought-process)
|
|
732
742
|
- [Retrieve images in response](#retrieve-images-in-response)
|
|
733
|
-
- [Generate
|
|
734
|
-
- [Save images to local files](#save-images-to-local-files)
|
|
743
|
+
- [Generate and edit images](#generate-and-edit-images)
|
|
735
744
|
- [Generate contents with Gemini extensions](#generate-contents-with-gemini-extensions)
|
|
736
745
|
- [Check and switch to other reply candidates](#check-and-switch-to-other-reply-candidates)
|
|
737
|
-
- [
|
|
746
|
+
- [Logging Configuration](#logging-configuration)
|
|
738
747
|
- [References](#references)
|
|
739
748
|
- [Stargazers](#stargazers)
|
|
740
749
|
|
|
@@ -746,13 +755,13 @@ A reverse-engineered asynchronous python wrapper for [Google Gemini](https://gem
|
|
|
746
755
|
|
|
747
756
|
Install/update the package with pip.
|
|
748
757
|
|
|
749
|
-
```
|
|
758
|
+
```sh
|
|
750
759
|
pip install -U gemini_webapi
|
|
751
760
|
```
|
|
752
761
|
|
|
753
762
|
Optionally, package offers a way to automatically import cookies from your local browser. To enable this feature, install `browser-cookie3` as well. Supported platforms and browsers can be found [here](https://github.com/borisbabic/browser_cookie3?tab=readme-ov-file#contribute).
|
|
754
763
|
|
|
755
|
-
```
|
|
764
|
+
```sh
|
|
756
765
|
pip install -U browser-cookie3
|
|
757
766
|
```
|
|
758
767
|
|
|
@@ -768,15 +777,17 @@ pip install -U browser-cookie3
|
|
|
768
777
|
|
|
769
778
|
> [!NOTE]
|
|
770
779
|
>
|
|
771
|
-
> If your application is deployed in a containerized environment (e.g. Docker), you may want to persist the cookies with a volume to avoid re-authentication every time the container rebuilds.
|
|
780
|
+
> If your application is deployed in a containerized environment (e.g. Docker), you may want to persist the cookies with a volume to avoid re-authentication every time the container rebuilds. You can set `GEMINI_COOKIE_PATH` environment variable to specify the path where auto-refreshed cookies are stored. Make sure the path is writable by the application.
|
|
772
781
|
>
|
|
773
782
|
> Here's part of a sample `docker-compose.yml` file:
|
|
774
783
|
|
|
775
784
|
```yaml
|
|
776
785
|
services:
|
|
777
786
|
main:
|
|
787
|
+
environment:
|
|
788
|
+
GEMINI_COOKIE_PATH: /tmp/gemini_webapi
|
|
778
789
|
volumes:
|
|
779
|
-
- ./gemini_cookies:/
|
|
790
|
+
- ./gemini_cookies:/tmp/gemini_webapi
|
|
780
791
|
```
|
|
781
792
|
|
|
782
793
|
> [!NOTE]
|
|
@@ -804,7 +815,7 @@ Secure_1PSIDTS = "COOKIE VALUE HERE"
|
|
|
804
815
|
|
|
805
816
|
async def main():
|
|
806
817
|
# If browser-cookie3 is installed, simply use `client = GeminiClient()`
|
|
807
|
-
client = GeminiClient(Secure_1PSID, Secure_1PSIDTS,
|
|
818
|
+
client = GeminiClient(Secure_1PSID, Secure_1PSIDTS, proxy=None)
|
|
808
819
|
await client.init(timeout=30, auto_close=False, close_delay=300, auto_refresh=True)
|
|
809
820
|
|
|
810
821
|
asyncio.run(main())
|
|
@@ -814,9 +825,9 @@ asyncio.run(main())
|
|
|
814
825
|
>
|
|
815
826
|
> `auto_close` and `close_delay` are optional arguments for automatically closing the client after a certain period of inactivity. This feature is disabled by default. In an always-on service like chatbot, it's recommended to set `auto_close` to `True` combined with reasonable seconds of `close_delay` for better resource management.
|
|
816
827
|
|
|
817
|
-
### Generate contents
|
|
828
|
+
### Generate contents
|
|
818
829
|
|
|
819
|
-
Ask a
|
|
830
|
+
Ask a single-turn question by calling `GeminiClient.generate_content`, which returns a `gemini_webapi.ModelOutput` object containing the generated text, images, thoughts, and conversation metadata.
|
|
820
831
|
|
|
821
832
|
```python
|
|
822
833
|
async def main():
|
|
@@ -830,15 +841,15 @@ asyncio.run(main())
|
|
|
830
841
|
>
|
|
831
842
|
> Simply use `print(response)` to get the same output if you just want to see the response text
|
|
832
843
|
|
|
833
|
-
### Generate contents
|
|
844
|
+
### Generate contents with files
|
|
834
845
|
|
|
835
|
-
Gemini supports
|
|
846
|
+
Gemini supports file input, including images and documents. Optionally, you can pass files as a list of paths in `str` or `pathlib.Path` to `GeminiClient.generate_content` together with text prompt.
|
|
836
847
|
|
|
837
848
|
```python
|
|
838
849
|
async def main():
|
|
839
850
|
response = await client.generate_content(
|
|
840
|
-
"
|
|
841
|
-
|
|
851
|
+
"Introduce the contents of these two files. Is there any connection between them?",
|
|
852
|
+
files=["assets/sample.pdf", Path("assets/banner.png")],
|
|
842
853
|
)
|
|
843
854
|
print(response.text)
|
|
844
855
|
|
|
@@ -847,14 +858,20 @@ asyncio.run(main())
|
|
|
847
858
|
|
|
848
859
|
### Conversations across multiple turns
|
|
849
860
|
|
|
850
|
-
If you want to keep conversation continuous, please use `GeminiClient.start_chat` to create a `ChatSession` object and send messages through it. The conversation history will be automatically handled and get updated after each turn.
|
|
861
|
+
If you want to keep conversation continuous, please use `GeminiClient.start_chat` to create a `gemini_webapi.ChatSession` object and send messages through it. The conversation history will be automatically handled and get updated after each turn.
|
|
851
862
|
|
|
852
863
|
```python
|
|
853
864
|
async def main():
|
|
854
865
|
chat = client.start_chat()
|
|
855
|
-
response1 = await chat.send_message(
|
|
856
|
-
|
|
857
|
-
|
|
866
|
+
response1 = await chat.send_message(
|
|
867
|
+
"Introduce the contents of these two files. Is there any connection between them?",
|
|
868
|
+
files=["assets/sample.pdf", Path("assets/banner.png")],
|
|
869
|
+
)
|
|
870
|
+
print(response1.text)
|
|
871
|
+
response2 = await chat.send_message(
|
|
872
|
+
"Use image generation tool to modify the banner with another font and design."
|
|
873
|
+
)
|
|
874
|
+
print(response2.text, response2.images, sep="\n\n----------------------------------\n\n")
|
|
858
875
|
|
|
859
876
|
asyncio.run(main())
|
|
860
877
|
```
|
|
@@ -884,72 +901,208 @@ async def main():
|
|
|
884
901
|
asyncio.run(main())
|
|
885
902
|
```
|
|
886
903
|
|
|
887
|
-
###
|
|
904
|
+
### Select language model
|
|
905
|
+
|
|
906
|
+
You can specify which language model to use by passing `model` argument to `GeminiClient.generate_content` or `GeminiClient.start_chat`. The default value is `unspecified`.
|
|
907
|
+
|
|
908
|
+
Currently available models (as of November 20, 2025):
|
|
888
909
|
|
|
889
|
-
|
|
910
|
+
- `unspecified` - Default model
|
|
911
|
+
- `gemini-3.0-pro` - Gemini 3.0 Pro
|
|
912
|
+
- `gemini-2.5-pro` - Gemini 2.5 Pro
|
|
913
|
+
- `gemini-2.5-flash` - Gemini 2.5 Flash
|
|
890
914
|
|
|
891
915
|
```python
|
|
916
|
+
from gemini_webapi.constants import Model
|
|
917
|
+
|
|
892
918
|
async def main():
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
919
|
+
response1 = await client.generate_content(
|
|
920
|
+
"What's you language model version? Reply version number only.",
|
|
921
|
+
model=Model.G_2_5_FLASH,
|
|
922
|
+
)
|
|
923
|
+
print(f"Model version ({Model.G_2_5_FLASH.model_name}): {response1.text}")
|
|
924
|
+
|
|
925
|
+
chat = client.start_chat(model="gemini-2.5-pro")
|
|
926
|
+
response2 = await chat.send_message("What's you language model version? Reply version number only.")
|
|
927
|
+
print(f"Model version (gemini-2.5-pro): {response2.text}")
|
|
896
928
|
|
|
897
929
|
asyncio.run(main())
|
|
898
930
|
```
|
|
899
931
|
|
|
900
|
-
###
|
|
932
|
+
### Apply system prompt with Gemini Gems
|
|
901
933
|
|
|
902
|
-
|
|
934
|
+
System prompt can be applied to conversations via [Gemini Gems](https://gemini.google.com/gems/view). To use a gem, you can pass `gem` argument to `GeminiClient.generate_content` or `GeminiClient.start_chat`. `gem` can be either a string of gem id or a `gemini_webapi.Gem` object. Only one gem can be applied to a single conversation.
|
|
903
935
|
|
|
904
|
-
> [!
|
|
936
|
+
> [!TIP]
|
|
905
937
|
>
|
|
906
|
-
>
|
|
938
|
+
> There are some system predefined gems that by default are not shown to users (and therefore may not work properly). Use `client.fetch_gems(include_hidden=True)` to include them in the fetch result.
|
|
939
|
+
|
|
940
|
+
```python
|
|
941
|
+
async def main():
|
|
942
|
+
# Fetch all gems for the current account, including both predefined and user-created ones
|
|
943
|
+
await client.fetch_gems(include_hidden=False)
|
|
944
|
+
|
|
945
|
+
# Once fetched, gems will be cached in `GeminiClient.gems`
|
|
946
|
+
gems = client.gems
|
|
947
|
+
|
|
948
|
+
# Get the gem you want to use
|
|
949
|
+
system_gems = gems.filter(predefined=True)
|
|
950
|
+
coding_partner = system_gems.get(id="coding-partner")
|
|
951
|
+
|
|
952
|
+
response1 = await client.generate_content(
|
|
953
|
+
"what's your system prompt?",
|
|
954
|
+
model=Model.G_2_5_FLASH,
|
|
955
|
+
gem=coding_partner,
|
|
956
|
+
)
|
|
957
|
+
print(response1.text)
|
|
958
|
+
|
|
959
|
+
# Another example with a user-created custom gem
|
|
960
|
+
# Gem ids are consistent strings. Store them somewhere to avoid fetching gems every time
|
|
961
|
+
your_gem = gems.get(name="Your Gem Name")
|
|
962
|
+
your_gem_id = your_gem.id
|
|
963
|
+
chat = client.start_chat(gem=your_gem_id)
|
|
964
|
+
response2 = await chat.send_message("what's your system prompt?")
|
|
965
|
+
print(response2)
|
|
966
|
+
```
|
|
967
|
+
|
|
968
|
+
### Manage Custom Gems
|
|
969
|
+
|
|
970
|
+
You can create, update, and delete your custom gems programmatically with the API. Note that predefined system gems cannot be modified or deleted.
|
|
971
|
+
|
|
972
|
+
#### Create a custom gem
|
|
973
|
+
|
|
974
|
+
Create a new custom gem with a name, system prompt (instructions), and optional description:
|
|
975
|
+
|
|
976
|
+
```python
|
|
977
|
+
async def main():
|
|
978
|
+
# Create a new custom gem
|
|
979
|
+
new_gem = await client.create_gem(
|
|
980
|
+
name="Python Tutor",
|
|
981
|
+
prompt="You are a helpful Python programming tutor.",
|
|
982
|
+
description="A specialized gem for Python programming"
|
|
983
|
+
)
|
|
984
|
+
|
|
985
|
+
print(f"Custom gem created: {new_gem}")
|
|
986
|
+
|
|
987
|
+
# Use the newly created gem in a conversation
|
|
988
|
+
response = await client.generate_content(
|
|
989
|
+
"Explain how list comprehensions work in Python",
|
|
990
|
+
gem=new_gem
|
|
991
|
+
)
|
|
992
|
+
print(response.text)
|
|
993
|
+
|
|
994
|
+
asyncio.run(main())
|
|
995
|
+
```
|
|
996
|
+
|
|
997
|
+
#### Update an existing gem
|
|
998
|
+
|
|
999
|
+
> [!NOTE]
|
|
907
1000
|
>
|
|
908
|
-
>
|
|
909
|
-
> >
|
|
910
|
-
> > This feature’s availability in any specific Gemini app is also limited to the supported languages and countries of that app.
|
|
911
|
-
> >
|
|
912
|
-
> > For now, this feature isn’t available to users under 18.
|
|
1001
|
+
> When updating a gem, you must provide all parameters (name, prompt, description) even if you only want to change one of them.
|
|
913
1002
|
|
|
914
1003
|
```python
|
|
915
1004
|
async def main():
|
|
916
|
-
|
|
1005
|
+
# Get a custom gem (assuming you have one named "Python Tutor")
|
|
1006
|
+
await client.fetch_gems()
|
|
1007
|
+
python_tutor = client.gems.get(name="Python Tutor")
|
|
1008
|
+
|
|
1009
|
+
# Update the gem with new instructions
|
|
1010
|
+
updated_gem = await client.update_gem(
|
|
1011
|
+
gem=python_tutor, # Can also pass gem ID string
|
|
1012
|
+
name="Advanced Python Tutor",
|
|
1013
|
+
prompt="You are an expert Python programming tutor.",
|
|
1014
|
+
description="An advanced Python programming assistant"
|
|
1015
|
+
)
|
|
1016
|
+
|
|
1017
|
+
print(f"Custom gem updated: {updated_gem}")
|
|
1018
|
+
|
|
1019
|
+
asyncio.run(main())
|
|
1020
|
+
```
|
|
1021
|
+
|
|
1022
|
+
#### Delete a custom gem
|
|
1023
|
+
|
|
1024
|
+
```python
|
|
1025
|
+
async def main():
|
|
1026
|
+
# Get the gem to delete
|
|
1027
|
+
await client.fetch_gems()
|
|
1028
|
+
gem_to_delete = client.gems.get(name="Advanced Python Tutor")
|
|
1029
|
+
|
|
1030
|
+
# Delete the gem
|
|
1031
|
+
await client.delete_gem(gem_to_delete) # Can also pass gem ID string
|
|
1032
|
+
print(f"Custom gem deleted: {gem_to_delete.name}")
|
|
1033
|
+
|
|
1034
|
+
asyncio.run(main())
|
|
1035
|
+
```
|
|
1036
|
+
|
|
1037
|
+
### Retrieve model's thought process
|
|
1038
|
+
|
|
1039
|
+
When using models with thinking capabilities, the model's thought process will be populated in `ModelOutput.thoughts`.
|
|
1040
|
+
|
|
1041
|
+
```python
|
|
1042
|
+
async def main():
|
|
1043
|
+
response = await client.generate_content(
|
|
1044
|
+
"What's 1+1?", model="gemini-2.5-pro"
|
|
1045
|
+
)
|
|
1046
|
+
print(response.thoughts)
|
|
1047
|
+
print(response.text)
|
|
1048
|
+
|
|
1049
|
+
asyncio.run(main())
|
|
1050
|
+
```
|
|
1051
|
+
|
|
1052
|
+
### Retrieve images in response
|
|
1053
|
+
|
|
1054
|
+
Images in the API's output are stored as a list of `gemini_webapi.Image` objects. You can access the image title, URL, and description by calling `Image.title`, `Image.url` and `Image.alt` respectively.
|
|
1055
|
+
|
|
1056
|
+
```python
|
|
1057
|
+
async def main():
|
|
1058
|
+
response = await client.generate_content("Send me some pictures of cats")
|
|
917
1059
|
for image in response.images:
|
|
918
1060
|
print(image, "\n\n----------------------------------\n")
|
|
919
1061
|
|
|
920
1062
|
asyncio.run(main())
|
|
921
1063
|
```
|
|
922
1064
|
|
|
923
|
-
|
|
924
|
-
>
|
|
925
|
-
> by default, when asked to send images (like the previous example), Gemini will send images fetched from web instead of generating images with AI model, unless you specifically require to "generate" images in your prompt. In this package, web images and generated images are treated differently as `WebImage` and `GeneratedImage`, and will be automatically categorized in the output.
|
|
1065
|
+
### Generate and edit images
|
|
926
1066
|
|
|
927
|
-
|
|
1067
|
+
You can ask Gemini to generate and edit images with Nano Banana, Google's latest image model, simply by natural language.
|
|
928
1068
|
|
|
929
|
-
|
|
1069
|
+
> [!IMPORTANT]
|
|
1070
|
+
>
|
|
1071
|
+
> Google has some limitations on the image generation feature in Gemini, so its availability could be different per region/account. Here's a summary copied from [official documentation](https://support.google.com/gemini/answer/14286560) (as of Sep 10, 2025):
|
|
1072
|
+
>
|
|
1073
|
+
> > This feature’s availability in any specific Gemini app is also limited to the supported languages and countries of that app.
|
|
1074
|
+
> >
|
|
1075
|
+
> > For now, this feature isn’t available to users under 18.
|
|
1076
|
+
> >
|
|
1077
|
+
> > To use this feature, you must be signed in to Gemini Apps.
|
|
1078
|
+
|
|
1079
|
+
You can save images returned from Gemini to local by calling `Image.save()`. Optionally, you can specify the file path and file name by passing `path` and `filename` arguments to the function and skip images with invalid file names by passing `skip_invalid_filename=True`. Works for both `WebImage` and `GeneratedImage`.
|
|
930
1080
|
|
|
931
1081
|
```python
|
|
932
1082
|
async def main():
|
|
933
1083
|
response = await client.generate_content("Generate some pictures of cats")
|
|
934
1084
|
for i, image in enumerate(response.images):
|
|
935
1085
|
await image.save(path="temp/", filename=f"cat_{i}.png", verbose=True)
|
|
1086
|
+
print(image, "\n\n----------------------------------\n")
|
|
936
1087
|
|
|
937
1088
|
asyncio.run(main())
|
|
938
1089
|
```
|
|
939
1090
|
|
|
1091
|
+
> [!NOTE]
|
|
1092
|
+
>
|
|
1093
|
+
> by default, when asked to send images (like the previous example), Gemini will send images fetched from web instead of generating images with AI model, unless you specifically require to "generate" images in your prompt. In this package, web images and generated images are treated differently as `WebImage` and `GeneratedImage`, and will be automatically categorized in the output.
|
|
1094
|
+
|
|
940
1095
|
### Generate contents with Gemini extensions
|
|
941
1096
|
|
|
942
1097
|
> [!IMPORTANT]
|
|
943
1098
|
>
|
|
944
|
-
> To access Gemini extensions in API, you must activate them on the [Gemini website](https://gemini.google.com/extensions) first. Same as image generation, Google also has limitations on the availability of Gemini extensions. Here's a summary copied from [official documentation](https://support.google.com/gemini/answer/13695044) (as of
|
|
1099
|
+
> To access Gemini extensions in API, you must activate them on the [Gemini website](https://gemini.google.com/extensions) first. Same as image generation, Google also has limitations on the availability of Gemini extensions. Here's a summary copied from [official documentation](https://support.google.com/gemini/answer/13695044) (as of March 19th, 2025):
|
|
945
1100
|
>
|
|
946
|
-
> > To
|
|
947
|
-
> >
|
|
948
|
-
> > Sign in with your personal Google Account that you manage on your own. Extensions, including the Google Workspace extension, are currently not available to Google Workspace accounts for school, business, or other organizations.
|
|
1101
|
+
> > To connect apps to Gemini, you must have Gemini Apps Activity on.
|
|
949
1102
|
> >
|
|
950
|
-
> >
|
|
1103
|
+
> > To use this feature, you must be signed in to Gemini Apps.
|
|
951
1104
|
> >
|
|
952
|
-
> > Important:
|
|
1105
|
+
> > Important: If you’re under 18, Google Workspace and Maps apps currently only work with English prompts in Gemini.
|
|
953
1106
|
|
|
954
1107
|
After activating extensions for your account, you can access them in your prompts either by natural language or by starting your prompt with "@" followed by the extension keyword.
|
|
955
1108
|
|
|
@@ -970,7 +1123,7 @@ asyncio.run(main())
|
|
|
970
1123
|
|
|
971
1124
|
### Check and switch to other reply candidates
|
|
972
1125
|
|
|
973
|
-
A response from Gemini
|
|
1126
|
+
A response from Gemini sometimes contains multiple reply candidates with different generated contents. You can check all candidates and choose one to continue the conversation. By default, the first candidate will be chosen.
|
|
974
1127
|
|
|
975
1128
|
```python
|
|
976
1129
|
async def main():
|
|
@@ -991,9 +1144,9 @@ async def main():
|
|
|
991
1144
|
asyncio.run(main())
|
|
992
1145
|
```
|
|
993
1146
|
|
|
994
|
-
###
|
|
1147
|
+
### Logging Configuration
|
|
995
1148
|
|
|
996
|
-
|
|
1149
|
+
This package uses [loguru](https://loguru.readthedocs.io/en/stable/) for logging, and exposes a function `set_log_level` to control log level. You can set log level to one of the following values: `DEBUG`, `INFO`, `WARNING`, `ERROR` and `CRITICAL`. The default value is `INFO`.
|
|
997
1150
|
|
|
998
1151
|
```python
|
|
999
1152
|
from gemini_webapi import set_log_level
|
|
@@ -1001,6 +1154,10 @@ from gemini_webapi import set_log_level
|
|
|
1001
1154
|
set_log_level("DEBUG")
|
|
1002
1155
|
```
|
|
1003
1156
|
|
|
1157
|
+
> [!NOTE]
|
|
1158
|
+
>
|
|
1159
|
+
> Calling `set_log_level` for the first time will **globally** remove all existing loguru handlers. You may want to configure logging directly with loguru to avoid this issue and have more advanced control over logging behaviors.
|
|
1160
|
+
|
|
1004
1161
|
## References
|
|
1005
1162
|
|
|
1006
1163
|
[Google AI Studio](https://ai.google.dev/tutorials/ai-studio_quickstart)
|