diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
new file mode 100644
index 000000000..902632b35
--- /dev/null
+++ b/.github/workflows/docs.yml
@@ -0,0 +1,78 @@
+# Builds the API reference (https://googleapis.github.io/python-genai/) with the
+# pinned Sphinx in docs/requirements.txt and publishes it to GitHub Pages.
+#
+# Run by hand from the Actions tab for now, from main: the github-pages
+# environment only accepts deployments from main. Publishing also needs the
+# repository's Pages source set to "GitHub Actions"; until then, leave "deploy"
+# unchecked to build the site and download it as an artifact.
+name: Docs
+
+on:
+ workflow_dispatch:
+ inputs:
+ ref:
+ description: Tag or branch to build. Tags from before this workflow have no docs/source.
+ required: true
+ default: main
+ deploy:
+ description: Publish to GitHub Pages
+ type: boolean
+ default: false
+
+permissions:
+ contents: read
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+ with:
+ ref: ${{ inputs.ref }}
+
+ - name: Set up Python
+ uses: actions/setup-python@v5
+ with:
+ python-version: '3.12'
+
+ - name: Install dependencies
+ run: |
+ python -m pip install --upgrade pip
+ pip install -r requirements.txt -r docs/requirements.txt
+
+ - name: Build
+ # The docs import `genai` from the checkout, as build_and_copy_docs.sh
+ # does from its copy in docs/google. custom.css is copied in first, as
+ # that script does. The doctree cache goes outside the site, so it is
+ # not published.
+ env:
+ PYTHONPATH: ${{ github.workspace }}/google
+ run: |
+ mkdir -p _site/_static/css
+ cp docs/source/custom.css _site/_static/css/custom.css
+ sphinx-build -b html -d "$RUNNER_TEMP/doctrees" docs/source _site
+
+ - name: Upload the site
+ uses: actions/upload-pages-artifact@v3
+ with:
+ path: _site
+
+ deploy:
+ if: inputs.deploy
+ needs: build
+ runs-on: ubuntu-latest
+ # One deployment at a time; builds can run side by side.
+ concurrency:
+ group: pages
+ cancel-in-progress: false
+ permissions:
+ pages: write
+ id-token: write
+ environment:
+ name: github-pages
+ url: ${{ steps.deployment.outputs.page_url }}
+ steps:
+ - name: Publish to GitHub Pages
+ id: deployment
+ uses: actions/deploy-pages@v4
diff --git a/docs/requirements.txt b/docs/requirements.txt
new file mode 100644
index 000000000..82a50c1b6
--- /dev/null
+++ b/docs/requirements.txt
@@ -0,0 +1,6 @@
+absl-py==2.1.0
+autodoc_pydantic==2.2.0
+furo==2025.09.25
+myst-parser==4.0.1
+sphinx==8.2.3
+sphinx-autodoc-typehints==3.2.0
diff --git a/docs/source/conf.py b/docs/source/conf.py
new file mode 100644
index 000000000..0c48bfdff
--- /dev/null
+++ b/docs/source/conf.py
@@ -0,0 +1,69 @@
+# Configuration file for the Sphinx documentation builder.
+#
+# For the full list of built-in configuration values, see the documentation:
+# https://www.sphinx-doc.org/en/master/usage/configuration.html
+
+# -- Project information -----------------------------------------------------
+# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
+
+project = 'Google Gen AI SDK'
+copyright = '2024, Google'
+author = 'Google'
+
+# -- General configuration ---------------------------------------------------
+# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
+
+extensions = []
+
+templates_path = ['_templates']
+exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
+
+autoclass_content = 'both'
+
+# -- Options for HTML output -------------------------------------------------
+# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
+
+html_static_path = ['_static']
+
+import html
+import os
+import sys
+sys.path.insert(0, os.path.abspath('.')) # Add current directory to path
+sys.path.insert(0, os.path.abspath('../google'))
+
+extensions = ['sphinxcontrib.autodoc_pydantic', 'myst_parser', 'sphinx.ext.autodoc', 'sphinx_autodoc_typehints', 'sphinx.ext.napoleon']
+html_theme = 'furo'
+
+TEXT_FONTS = '"Google Sans Text", Roboto, "Helvetica Neue", Helvetica, Arial, sans-serif'
+CODE_FONTS = 'Roboto Mono, "Helvetica Neue Mono", monospace'
+FONT_COLOR_FOR_LIGHT_THEME = 'black'
+FONT_COLOR_FOR_DARK_THEME = 'white'
+
+html_theme_options = {
+ "light_css_variables": {
+ "font-stack": TEXT_FONTS,
+ "font-stack--monospace": CODE_FONTS,
+ "font-stack--headings": TEXT_FONTS,
+ "color-brand-primary": FONT_COLOR_FOR_LIGHT_THEME,
+ "color-brand-content": FONT_COLOR_FOR_LIGHT_THEME,
+ },
+ "dark_css_variables": {
+ "font-stack": TEXT_FONTS,
+ "font-stack--monospace": CODE_FONTS,
+ "font-stack--headings": TEXT_FONTS,
+ "color-brand-primary": FONT_COLOR_FOR_DARK_THEME,
+ "color-brand-content": FONT_COLOR_FOR_DARK_THEME,
+ },
+}
+
+# These folders are copied to the documentation's HTML output
+html_static_path = ['_static']
+
+# These paths are either relative to html_static_path
+# or fully qualified paths (eg. https://...)
+html_css_files = [
+ 'css/custom.css',
+]
+
+autodoc_pydantic_model_show_json = True
+autodoc_pydantic_model_show_config_summary = False
diff --git a/docs/source/custom.css b/docs/source/custom.css
new file mode 100644
index 000000000..90b794f25
--- /dev/null
+++ b/docs/source/custom.css
@@ -0,0 +1,33 @@
+@import url('https://fonts.googleapis.com/css?family=Google+Sans:400,500|Roboto:400,400italic,500,500italic,700,700italic|Roboto+Mono:400,500,700&display=swap');
+
+body {
+ font-weight: 400;
+}
+
+h1 {
+ font-size: 32px;
+ font-weight: 400;
+}
+
+h2 {
+ font-size: 24px;
+ font-weight: 400;
+}
+
+h3 {
+ font-size: 20px;
+ font-weight: 400;
+}
+
+h4 {
+ font-size: 16px;
+ font-weight: 400;
+}
+
+.sidebar-brand-text {
+ font-size: 14px;
+}
+
+.highlight {
+ box-shadow: 0 2px 2px 0 rgba(0,0,0,0.14), 0 3px 1px -2px rgba(0,0,0,0.12), 0 1px 5px 0 rgba(0,0,0,0.2);
+}
\ No newline at end of file
diff --git a/docs/source/genai.rst b/docs/source/genai.rst
new file mode 100644
index 000000000..41fa05a20
--- /dev/null
+++ b/docs/source/genai.rst
@@ -0,0 +1,108 @@
+Submodules
+----------
+
+genai.client module
+-------------------
+
+.. automodule:: genai.client
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+
+GAOS Client Resources
+^^^^^^^^^^^^^^^^^^^^^
+
+The following resource classes are returned by the client properties
+``client.interactions``, ``client.agents``, ``client.webhooks``,
+``client.triggers``, and ``client.environments``.
+
+.. autoclass:: genai._gaos.google_genai.GeminiNextGenInteractions
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+.. autoclass:: genai._gaos.google_genai.AsyncGeminiNextGenInteractions
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+.. autoclass:: genai._gaos.google_genai.GeminiNextGenAgents
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+.. autoclass:: genai._gaos.google_genai.AsyncGeminiNextGenAgents
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+.. autoclass:: genai._gaos.google_genai.GeminiNextGenWebhooks
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+.. autoclass:: genai._gaos.google_genai.AsyncGeminiNextGenWebhooks
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+.. autoclass:: genai._gaos.google_genai.GeminiNextGenTriggers
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+.. autoclass:: genai._gaos.google_genai.AsyncGeminiNextGenTriggers
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+.. autoclass:: genai._gaos.google_genai.GeminiNextGenEnvironments
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+.. autoclass:: genai._gaos.google_genai.AsyncGeminiNextGenEnvironments
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+genai.live module
+-----------------
+
+.. automodule:: genai.live
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+genai.models module
+-------------------
+
+.. automodule:: genai.models
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+genai.tokens module
+-------------------
+
+.. automodule:: genai.tokens
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+genai.tunings module
+--------------------
+
+.. automodule:: genai.tunings
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+genai.types module
+------------------
+
+.. automodule:: genai.types
+ :members:
+ :undoc-members:
+ :show-inheritance:
diff --git a/docs/source/index.rst b/docs/source/index.rst
new file mode 100644
index 000000000..a285fcf80
--- /dev/null
+++ b/docs/source/index.rst
@@ -0,0 +1,2126 @@
+Google Gen AI SDK
+=================
+
+|pypi| |pyversions| |pydownloads|
+
+**Documentation:** ``_
+
+``_
+
+.. |pypi| image:: https://img.shields.io/pypi/v/google-genai.svg
+ :target: https://pypi.org/project/google-genai/
+.. |pyversions| image:: https://img.shields.io/pypi/pyversions/google-genai
+ :target: https://pypi.org/project/google-genai/
+.. |pydownloads| image:: https://img.shields.io/pypi/dw/google-genai
+ :target: https://pypistats.org/packages/google-genai
+
+Google Gen AI Python SDK provides an interface for developers to integrate
+Google's generative models into their Python applications. It supports the
+`Gemini Developer API `_ and
+`Gemini Enterprise Agent Platform API `_
+APIs.
+
+Installation
+------------
+
+.. code:: shell
+
+ pip install google-genai
+
+With `uv`:
+
+.. code:: shell
+
+ uv pip install google-genai
+
+
+Imports
+-------
+
+.. code:: python
+
+ from google import genai
+ from google.genai import types
+
+Create a client
+---------------
+
+Please run one of the following code blocks to create a client for
+different services (`Gemini Developer API `_ or `Gemini Enterprise Agent Platform API `_).
+
+.. code:: python
+
+ from google import genai
+
+ # Only run this block for Gemini Developer API
+ client = genai.Client(api_key='GEMINI_API_KEY')
+
+.. code:: python
+
+ from google import genai
+
+ # Only run this block for Gemini Enterprise Agent Platform API
+ client = genai.Client(
+ enterprise=True, project='your-project-id', location='us-central1'
+ )
+
+
+**(Optional) Using environment variables:**
+
+You can create a client by configuring the necessary environment variables.
+Configuration setup instructions depends on whether you're using the Gemini
+Developer API or the Gemini API in Gemini Enterprise Agent Platform.
+
+**Gemini Developer API:** Set the `GEMINI_API_KEY` or `GOOGLE_API_KEY`.
+It will automatically be picked up by the client. It's recommended that you
+set only one of those variables, but if both are set, `GOOGLE_API_KEY` takes
+precedence.
+
+.. code:: bash
+
+ export GEMINI_API_KEY='your-api-key'
+
+
+**Gemini API on Gemini Enterprise Agent Platform:** Set `GOOGLE_GENAI_USE_ENTERPRISE`,
+`GOOGLE_CLOUD_PROJECT` and `GOOGLE_CLOUD_LOCATION`, as shown below:
+
+.. code:: bash
+
+ export GOOGLE_GENAI_USE_ENTERPRISE=true
+ export GOOGLE_CLOUD_PROJECT='your-project-id'
+ export GOOGLE_CLOUD_LOCATION='us-central1'
+
+
+.. code:: python
+
+ from google import genai
+
+ client = genai.Client()
+
+
+Close a client
+^^^^^^^^^^^^^^
+
+Explicitly close the sync client to ensure that resources, such as the
+underlying HTTP connections, are properly cleaned up and closed.
+
+.. code:: python
+
+ from google.genai import Client
+
+ client = Client()
+ response_1 = client.models.generate_content(
+ model=MODEL_ID,
+ contents='Hello',
+ )
+ response_2 = client.models.generate_content(
+ model=MODEL_ID,
+ contents='Ask a question',
+ )
+ # Close the sync client to release resources.
+ client.close()
+
+
+To explicitly close the async client:
+
+.. code:: python
+
+ from google.genai import Client
+
+ aclient = Client(
+ enterprise=True, project='my-project-id', location='us-central1'
+ ).aio
+ response_1 = await aclient.models.generate_content(
+ model=MODEL_ID,
+ contents='Hello',
+ )
+ response_2 = await aclient.models.generate_content(
+ model=MODEL_ID,
+ contents='Ask a question',
+ )
+ # Close the async client to release resources.
+ await aclient.aclose()
+
+
+Client context managers
+^^^^^^^^^^^^^^^^^^^^^^^
+
+By using the sync client context manager, it will close the underlying
+sync client when exiting the with block.
+
+.. code:: python
+
+ from google.genai import Client
+
+ with Client() as client:
+ response_1 = client.models.generate_content(
+ model=MODEL_ID,
+ contents='Hello',
+ )
+ response_2 = client.models.generate_content(
+ model=MODEL_ID,
+ contents='Ask a question',
+ )
+
+
+By using the async client context manager, it will close the underlying
+async client when exiting the with block.
+
+
+.. code:: python
+
+ from google.genai import Client
+
+ async with Client().aio as aclient:
+ response_1 = await aclient.models.generate_content(
+ model=MODEL_ID,
+ contents='Hello',
+ )
+ response_2 = await aclient.models.generate_content(
+ model=MODEL_ID,
+ contents='Ask a question',
+ )
+
+
+API Selection
+^^^^^^^^^^^^^
+
+By default, the SDK uses the beta API endpoints provided by Google to support preview features in the APIs. The stable API endpoints can be selected by setting the API version to `v1`.
+
+To set the API version use ``http_options``. For example, to set the API version to ``v1`` for Gemini Enterprise Agent Platform API:
+
+.. code:: python
+
+ from google import genai
+ from google.genai import types
+
+ client = genai.Client(
+ enterprise=True,
+ project='your-project-id',
+ location='us-central1',
+ http_options=types.HttpOptions(api_version='v1')
+ )
+
+To set the API version to `v1alpha` for the Gemini Developer API:
+
+.. code:: python
+
+ from google import genai
+ from google.genai import types
+
+ # Only run this block for Gemini Developer API
+ client = genai.Client(
+ api_key='GEMINI_API_KEY',
+ http_options=types.HttpOptions(api_version='v1alpha')
+ )
+
+
+Faster async client option: Aiohttp
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+By default we use httpx for both sync and async client implementations. In order
+to have faster performance, you may install `google-genai[aiohttp]`. In Gen AI
+SDK we configure `trust_env=True` to match with the default behavior of httpx.
+Additional args of `aiohttp.ClientSession.request()`
+(`see _RequestOptions args `_)
+can be passed through the following way:
+
+.. code:: python
+
+ http_options = types.HttpOptions(
+ async_client_args={'cookies': ..., 'ssl': ...},
+ )
+
+ client=Client(..., http_options=http_options)
+
+
+Proxy
+^^^^^^^
+
+Both httpx and aiohttp libraries use `urllib.request.getproxies` from
+environment variables. Before client initialization, you may set proxy (and
+optional SSL_CERT_FILE) by setting the environment variables:
+
+
+.. code:: bash
+
+ export HTTPS_PROXY='http://username:password@proxy_uri:port'
+ export SSL_CERT_FILE='client.pem'
+
+
+If you need `socks5` proxy, httpx `supports `_
+`socks5` proxy if you pass it via args to httpx.Client(). You may install
+`httpx[socks]` to use it. Then you can pass it through the following way:
+
+.. code:: python
+
+ http_options = types.HttpOptions(
+ client_args={'proxy': 'socks5://user:pass@host:port'},
+ async_client_args={'proxy': 'socks5://user:pass@host:port'},
+ )
+
+ client=Client(..., http_options=http_options)
+
+
+Custom base url
+^^^^^^^^^^^^^^^
+
+In some cases you might need a custom base url (for example, API gateway proxy
+server) and bypass some authentication checks for project, location, or API key.
+You may pass the custom base url like this:
+
+.. code:: python
+
+ base_url = 'https://test-api-gateway-proxy.com'
+ client = Client(
+ enterprise=True, # Currently only enterprise=True is supported.
+ http_options={
+ 'base_url': base_url,
+ 'headers': {'Authorization': 'Bearer test_token'},
+ },
+ )
+
+
+Types
+-----
+
+Parameter types can be specified as either dictionaries(``TypedDict``) or `Pydantic Models `_.
+Pydantic model types are available in the ``types`` module.
+
+Models
+======
+
+The ``client.models`` modules exposes model inferencing and model
+getters. See the 'Create a client' section above to initialize a client.
+
+Generate Content
+----------------
+
+with text content input (text output)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. code:: python
+
+ response = client.models.generate_content(
+ model='gemini-flash-latest', contents='Why is the sky blue?'
+ )
+ print(response.text)
+
+
+with text content input (image output)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. code:: python
+
+ from google.genai import types
+
+ response = client.models.generate_content(
+ model='gemini-3.1-flash-lite-image',
+ contents='A cartoon infographic for flying sneakers',
+ config=types.GenerateContentConfig(
+ response_modalities=["IMAGE"],
+ image_config=types.ImageConfig(
+ aspect_ratio="9:16",
+ ),
+ ),
+ )
+
+ for part in response.parts:
+ if part.inline_data:
+ generated_image = part.as_image()
+ generated_image.show()
+
+
+with text content input (audio / speech output)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. code:: python
+
+ from google.genai import types
+
+ response = client.models.generate_content(
+ model='gemini-3.8-flash-tts',
+ contents='Give me a cheerful greeting.',
+ config=types.GenerateContentConfig(
+ response_modalities=['AUDIO'],
+ speech_config=types.SpeechConfig(
+ voice_config=types.VoiceConfig(
+ prebuilt_voice_config=types.PrebuiltVoiceConfig(
+ voice_name='Aoede'
+ )
+ )
+ ),
+ ),
+ )
+
+ for part in response.parts:
+ if part.inline_data:
+ with open('greeting.wav', 'wb') as f:
+ f.write(part.inline_data.data)
+
+
+with uploaded file (Gemini Developer API only)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+download the file in console.
+
+.. code:: console
+
+ !wget -q https://storage.googleapis.com/generativeai-downloads/data/a11.txt
+
+python code.
+
+.. code:: python
+
+ file = client.files.upload(file='a11.txt')
+ response = client.models.generate_content(
+ model='gemini-flash-latest',
+ contents=['Could you summarize this file?', file]
+ )
+ print(response.text)
+
+
+How to structure `contents` argument for `generate_content`
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+The SDK always converts the inputs to the `contents` argument into
+`list[types.Content]`.
+The following shows some common ways to provide your inputs.
+
+Provide a `list[types.Content]`
+""""""""""""""""""""""""""""""
+This is the canonical way to provide contents, SDK will not do any conversion.
+
+Provide a `types.Content` instance
+""""""""""""""""""""""""""""""
+
+.. code:: python
+
+ from google.genai import types
+
+ contents = types.Content(
+ role='user',
+ parts=[types.Part.from_text(text='Why is the sky blue?')]
+ )
+
+SDK converts this to
+
+.. code:: python
+
+ [
+ types.Content(
+ role='user',
+ parts=[types.Part.from_text(text='Why is the sky blue?')]
+ )
+ ]
+
+Provide a string
+""""""""""""""""""
+
+.. code:: python
+
+ contents='Why is the sky blue?'
+
+The SDK will assume this is a text part, and it converts this into the following:
+
+.. code:: python
+
+ [
+ types.UserContent(
+ parts=[
+ types.Part.from_text(text='Why is the sky blue?')
+ ]
+ )
+ ]
+
+Where a `types.UserContent` is a subclass of `types.Content`, it sets the
+`role` field to be `user`.
+
+Provide a list of string
+""""""""""""""""""""""""
+
+.. code:: python
+
+ contents=['Why is the sky blue?', 'Why is the cloud white?']
+
+The SDK assumes these are 2 text parts, it converts this into a single content,
+like the following:
+
+.. code:: python
+
+ [
+ types.UserContent(
+ parts=[
+ types.Part.from_text(text='Why is the sky blue?'),
+ types.Part.from_text(text='Why is the cloud white?'),
+ ]
+ )
+ ]
+
+Where a `types.UserContent` is a subclass of `types.Content`, the
+`role` field in `types.UserContent` is fixed to be `user`.
+
+Provide a function call part
+""""""""""""""""""""""""""
+
+.. code:: python
+
+ from google.genai import types
+
+ contents = types.Part.from_function_call(
+ name='get_weather_by_location',
+ args={'location': 'Boston'}
+ )
+
+The SDK converts a function call part to a content with a `model` role:
+
+.. code:: python
+
+ [
+ types.ModelContent(
+ parts=[
+ types.Part.from_function_call(
+ name='get_weather_by_location',
+ args={'location': 'Boston'}
+ )
+ ]
+ )
+ ]
+
+Where a `types.ModelContent` is a subclass of `types.Content`, the
+`role` field in `types.ModelContent` is fixed to be `model`.
+
+Provide a list of function call parts
+""""""""""""""""""""""""""""""
+
+.. code:: python
+
+ from google.genai import types
+
+ contents = [
+ types.Part.from_function_call(
+ name='get_weather_by_location',
+ args={'location': 'Boston'}
+ ),
+ types.Part.from_function_call(
+ name='get_weather_by_location',
+ args={'location': 'New York'}
+ ),
+ ]
+
+The SDK converts a list of function call parts to the a content with a `model` role:
+
+.. code:: python
+
+ [
+ types.ModelContent(
+ parts=[
+ types.Part.from_function_call(
+ name='get_weather_by_location',
+ args={'location': 'Boston'}
+ ),
+ types.Part.from_function_call(
+ name='get_weather_by_location',
+ args={'location': 'New York'}
+ )
+ ]
+ )
+ ]
+
+Where a `types.ModelContent` is a subclass of `types.Content`, the
+`role` field in `types.ModelContent` is fixed to be `model`.
+
+Provide a non function call part
+""""""""""""""""""""""""
+
+.. code:: python
+
+ from google.genai import types
+
+ contents = types.Part.from_uri(
+ file_uri: 'gs://generativeai-downloads/images/scones.jpg',
+ mime_type: 'image/jpeg',
+ )
+
+The SDK converts all non function call parts into a content with a `user` role.
+
+.. code:: python
+
+ [
+ types.UserContent(parts=[
+ types.Part.from_uri(
+ file_uri: 'gs://generativeai-downloads/images/scones.jpg',
+ mime_type: 'image/jpeg',
+ )
+ ])
+ ]
+
+Provide a list of non function call parts
+""""""""""""""""""""
+
+.. code:: python
+
+ from google.genai import types
+
+ contents = [
+ types.Part.from_text('What is this image about?'),
+ types.Part.from_uri(
+ file_uri: 'gs://generativeai-downloads/images/scones.jpg',
+ mime_type: 'image/jpeg',
+ )
+ ]
+
+The SDK will convert the list of parts into a content with a `user` role
+
+.. code:: python
+
+ [
+ types.UserContent(
+ parts=[
+ types.Part.from_text('What is this image about?'),
+ types.Part.from_uri(
+ file_uri: 'gs://generativeai-downloads/images/scones.jpg',
+ mime_type: 'image/jpeg',
+ )
+ ]
+ )
+ ]
+
+Mix types in contents
+""""""""""""""""""""""""""
+You can also provide a list of `types.ContentUnion`. The SDK leaves items of
+`types.Content` as is, it groups consecutive non function call parts into a
+single `types.UserContent`, and it groups consecutive function call parts into
+a single `types.ModelContent`.
+
+If you put a list within a list, the inner list can only contain
+`types.PartUnion` items. The SDK will convert the inner list into a single
+`types.UserContent`.
+
+
+System Instructions and Other Configs
+-------------------------------------
+
+The output of the model can be influenced by several optional settings
+available in generate_content's config parameter. For example, increasing
+`max_output_tokens` is essential for longer model responses. To make a model more
+deterministic, lowering the `temperature` parameter reduces randomness, with
+values near 0 minimizing variability. Capabilities and parameter defaults for
+each model is shown in the
+`Gemini Enterprise Agent Platform docs `_
+and `Gemini API docs `_ respectively.
+
+.. code:: python
+
+ from google.genai import types
+
+ response = client.models.generate_content(
+ model='gemini-flash-latest',
+ contents='high',
+ config=types.GenerateContentConfig(
+ system_instruction='I say high, you say low',
+ max_output_tokens=3,
+ temperature=0.3,
+ ),
+ )
+ print(response.text)
+
+Typed Config
+------------
+
+All API methods support Pydantic types for parameters as well as
+dictionaries. You can get the type from ``google.genai.types``.
+
+.. code:: python
+
+ from google.genai import types
+
+ response = client.models.generate_content(
+ model='gemini-flash-latest',
+ contents=types.Part.from_text(text='Why is the sky blue?'),
+ config=types.GenerateContentConfig(
+ temperature=0,
+ top_p=0.95,
+ top_k=20,
+ candidate_count=1,
+ seed=5,
+ max_output_tokens=100,
+ stop_sequences=['STOP!'],
+ presence_penalty=0.0,
+ frequency_penalty=0.0,
+ ),
+ )
+
+ print(response.text)
+
+List Base Models
+----------------
+
+To retrieve tuned models, see: :ref:`List Tuned Models`
+
+.. code:: python
+
+ for model in client.models.list():
+ print(model)
+
+.. code:: python
+
+ pager = client.models.list(config={'page_size': 10})
+ print(pager.page_size)
+ print(pager[0])
+ pager.next_page()
+ print(pager[0])
+
+List Base Models (Asynchronous)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. code:: python
+
+ async for job in await client.aio.models.list():
+ print(job)
+
+.. code:: python
+
+ async_pager = await client.aio.models.list(config={'page_size': 10})
+ print(async_pager.page_size)
+ print(async_pager[0])
+ await async_pager.next_page()
+ print(async_pager[0])
+
+Safety Settings
+---------------
+
+.. code:: python
+
+ from google.genai import types
+
+ response = client.models.generate_content(
+ model='gemini-flash-latest',
+ contents='Say something bad.',
+ config=types.GenerateContentConfig(
+ safety_settings=[
+ types.SafetySetting(
+ category='HARM_CATEGORY_HATE_SPEECH',
+ threshold='BLOCK_ONLY_HIGH',
+ )
+ ]
+ ),
+ )
+ print(response.text)
+
+Function Calling
+----------------
+
+Automatic Python function Support:
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+You can pass a Python function directly and it will be automatically
+called and responded by default.
+
+.. code:: python
+
+ from google.genai import types
+
+ def get_current_weather(location: str) -> str:
+ """Returns the current weather.
+
+ Args:
+ location: The city and state, e.g. San Francisco, CA
+ """
+ return 'sunny'
+
+
+ response = client.models.generate_content(
+ model='gemini-flash-latest',
+ contents='What is the weather like in Boston?',
+ config=types.GenerateContentConfig(
+ tools=[get_current_weather],
+ ),
+ )
+
+ print(response.text)
+
+Disabling automatic function calling
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+If you pass in a python function as a tool directly, and do not want
+automatic function calling, you can disable automatic function calling
+as follows:
+
+.. code:: python
+
+ from google.genai import types
+
+ response = client.models.generate_content(
+ model='gemini-flash-latest',
+ contents='What is the weather like in Boston?',
+ config=types.GenerateContentConfig(
+ tools=[get_current_weather],
+ automatic_function_calling=types.AutomaticFunctionCallingConfig(
+ disable=True
+ ),
+ ),
+ )
+
+With automatic function calling disabled, you will get a list of function call
+parts in the response:
+
+.. code:: python
+
+ function_calls: Optional[List[types.FunctionCall]] = response.function_calls
+
+
+Manually declare and invoke a function for function calling
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+If you don't want to use the automatic function support, you can manually
+declare the function and invoke it.
+
+The following example shows how to declare a function and pass it as a tool.
+Then you will receive a function call part in the response.
+
+.. code:: python
+
+ from google.genai import types
+
+ function = types.FunctionDeclaration(
+ name='get_current_weather',
+ description='Get the current weather in a given location',
+ parameters_json_schema={
+ 'type': 'object',
+ 'properties': {
+ 'location': {
+ 'type': 'string',
+ 'description': 'The city and state, e.g. San Francisco, CA',
+ }
+ },
+ 'required': ['location'],
+ },
+ )
+
+ tool = types.Tool(function_declarations=[function])
+
+ response = client.models.generate_content(
+ model='gemini-flash-latest',
+ contents='What is the weather like in Boston?',
+ config=types.GenerateContentConfig(
+ tools=[tool],
+ ),
+ )
+ print(response.function_calls[0])
+
+After you receive the function call part from the model, you can invoke the function
+and get the function response. And then you can pass the function response to
+the model.
+The following example shows how to do it for a simple function invocation.
+
+.. code:: python
+
+ from google.genai import types
+
+ user_prompt_content = types.Content(
+ role='user',
+ parts=[types.Part.from_text(text='What is the weather like in Boston?')],
+ )
+ function_call_part = response.function_calls[0]
+ function_call_content = response.candidates[0].content
+
+
+ try:
+ function_result = get_current_weather(
+ **function_call_part.function_call.args
+ )
+ function_response = {'result': function_result}
+ except (
+ Exception
+ ) as e: # instead of raising the exception, you can let the model handle it
+ function_response = {'error': str(e)}
+
+
+ function_response_part = types.Part.from_function_response(
+ name=function_call_part.name,
+ response=function_response,
+ )
+ function_response_content = types.Content(
+ role='tool', parts=[function_response_part]
+ )
+
+ response = client.models.generate_content(
+ model='gemini-flash-latest',
+ contents=[
+ user_prompt_content,
+ function_call_content,
+ function_response_content,
+ ],
+ config=types.GenerateContentConfig(
+ tools=[tool],
+ ),
+ )
+
+ print(response.text)
+
+
+Function calling with ``ANY`` tools config mode
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+If you configure function calling mode to be `ANY`, then the model will always
+return function call parts. If you also pass a python function as a tool, by
+default the SDK will perform automatic function calling until the remote calls
+exceed the maximum remote call for automatic function calling (default to 10 times).
+
+If you'd like to disable automatic function calling in `ANY` mode:
+
+.. code-block:: python
+
+ from google.genai import types
+
+ def get_current_weather(location: str) -> str:
+ """Returns the current weather.
+
+ Args:
+ location: The city and state, e.g. San Francisco, CA
+ """
+ return "sunny"
+
+ response = client.models.generate_content(
+ model="gemini-flash-latest",
+ contents="What is the weather like in Boston?",
+ config=types.GenerateContentConfig(
+ tools=[get_current_weather],
+ automatic_function_calling=types.AutomaticFunctionCallingConfig(
+ disable=True
+ ),
+ tool_config=types.ToolConfig(
+ function_calling_config=types.FunctionCallingConfig(mode='ANY')
+ ),
+ ),
+ )
+
+If you'd like to set ``x`` number of automatic function call turns, you can
+configure the maximum remote calls to be ``x + 1``.
+Assuming you prefer ``1`` turn for automatic function calling:
+
+.. code-block:: python
+
+ from google.genai import types
+
+ def get_current_weather(location: str) -> str:
+ """Returns the current weather.
+
+ Args:
+ location: The city and state, e.g. San Francisco, CA
+ """
+ return "sunny"
+
+ response = client.models.generate_content(
+ model="gemini-flash-latest",
+ contents="What is the weather like in Boston?",
+ config=types.GenerateContentConfig(
+ tools=[get_current_weather],
+ automatic_function_calling=types.AutomaticFunctionCallingConfig(
+ maximum_remote_calls=2
+ ),
+ tool_config=types.ToolConfig(
+ function_calling_config=types.FunctionCallingConfig(mode='ANY')
+ ),
+ ),
+ )
+
+Model Context Protocol (MCP) support (experimental)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Built-in `MCP `_ support is an
+experimental feature. You can pass a local MCP server as a tool directly.
+
+.. code:: python
+
+ import os
+ import asyncio
+ from datetime import datetime
+ from mcp import ClientSession, StdioServerParameters
+ from mcp.client.stdio import stdio_client
+ from google import genai
+
+ client = genai.Client()
+
+ # Create server parameters for stdio connection
+ server_params = StdioServerParameters(
+ command="npx", # Executable
+ args=["-y", "@philschmid/weather-mcp"], # MCP Server
+ env=None, # Optional environment variables
+ )
+
+ async def run():
+ async with stdio_client(server_params) as (read, write):
+ async with ClientSession(read, write) as session:
+ # Prompt to get the weather for the current day in London.
+ prompt = f"What is the weather in London in {datetime.now().strftime('%Y-%m-%d')}?"
+
+ # Initialize the connection between client and server
+ await session.initialize()
+
+ # Send request to the model with MCP function declarations
+ response = await client.aio.models.generate_content(
+ model="gemini-flash-latest",
+ contents=prompt,
+ config=genai.types.GenerateContentConfig(
+ temperature=0,
+ tools=[session], # uses the session, will automatically call the tool using automatic function calling
+ ),
+ )
+ print(response.text)
+
+ # Start the asyncio event loop and run the main function
+ asyncio.run(run())
+
+
+JSON Response Schema
+--------------------
+
+However you define your schema, don't duplicate it in your input prompt,
+including by giving examples of expected JSON output. If you do, the generated
+output might be lower in quality.
+
+JSON Schema support
+^^^^^^^^^^^^^^^^^^^
+
+Schemas can be provided as standard JSON schema.
+
+.. code:: python
+
+ user_profile = {
+ 'properties': {
+ 'age': {
+ 'anyOf': [
+ {'maximum': 20, 'minimum': 0, 'type': 'integer'},
+ {'type': 'null'},
+ ],
+ 'title': 'Age',
+ },
+ 'username': {
+ 'description': "User's unique name",
+ 'title': 'Username',
+ 'type': 'string',
+ },
+ },
+ 'required': ['username', 'age'],
+ 'title': 'User Schema',
+ 'type': 'object',
+ }
+
+ response = client.models.generate_content(
+ model='gemini-flash-latest',
+ contents='Give me a random user profile.',
+ config={
+ 'response_mime_type': 'application/json',
+ 'response_json_schema': user_profile
+ },
+ )
+ print(response.parsed)
+
+
+Pydantic Model Schema support
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Schemas can be provided as Pydantic Models.
+
+.. code:: python
+
+ from pydantic import BaseModel
+ from google.genai import types
+
+
+ class CountryInfo(BaseModel):
+ name: str
+ population: int
+ capital: str
+ continent: str
+ gdp: int
+ official_language: str
+ total_area_sq_mi: int
+
+
+ response = client.models.generate_content(
+ model='gemini-flash-latest',
+ contents='Give me information for the United States.',
+ config=types.GenerateContentConfig(
+ response_mime_type='application/json',
+ response_schema=CountryInfo,
+ ),
+ )
+ print(response.text)
+
+.. code:: python
+
+ from google.genai import types
+
+ response = client.models.generate_content(
+ model='gemini-flash-latest',
+ contents='Give me information for the United States.',
+ config=types.GenerateContentConfig(
+ response_mime_type='application/json',
+ response_schema={
+ 'required': [
+ 'name',
+ 'population',
+ 'capital',
+ 'continent',
+ 'gdp',
+ 'official_language',
+ 'total_area_sq_mi',
+ ],
+ 'properties': {
+ 'name': {'type': 'STRING'},
+ 'population': {'type': 'INTEGER'},
+ 'capital': {'type': 'STRING'},
+ 'continent': {'type': 'STRING'},
+ 'gdp': {'type': 'INTEGER'},
+ 'official_language': {'type': 'STRING'},
+ 'total_area_sq_mi': {'type': 'INTEGER'},
+ },
+ 'type': 'OBJECT',
+ },
+ ),
+ )
+ print(response.text)
+
+Enum Response Schema
+--------------------
+
+Text Response
+^^^^^^^^^^^^^^
+
+You can set ``response_mime_type`` to ``'text/x.enum'`` to return one of those enum
+values as the response.
+
+.. code:: python
+
+ from enum import Enum
+
+ class InstrumentEnum(Enum):
+ PERCUSSION = 'Percussion'
+ STRING = 'String'
+ WOODWIND = 'Woodwind'
+ BRASS = 'Brass'
+ KEYBOARD = 'Keyboard'
+
+ response = client.models.generate_content(
+ model='gemini-flash-latest',
+ contents='What instrument plays multiple notes at once?',
+ config={
+ 'response_mime_type': 'text/x.enum',
+ 'response_schema': InstrumentEnum,
+ },
+ )
+ print(response.text)
+
+JSON Response
+^^^^^^^^^^^^^^
+
+You can also set ``response_mime_type`` to ``'application/json'``, the response will be
+identical but in quotes.
+
+.. code:: python
+
+ from enum import Enum
+
+ class InstrumentEnum(Enum):
+ PERCUSSION = 'Percussion'
+ STRING = 'String'
+ WOODWIND = 'Woodwind'
+ BRASS = 'Brass'
+ KEYBOARD = 'Keyboard'
+
+ response = client.models.generate_content(
+ model='gemini-flash-latest',
+ contents='What instrument plays multiple notes at once?',
+ config={
+ 'response_mime_type': 'application/json',
+ 'response_schema': InstrumentEnum,
+ },
+ )
+ print(response.text)
+
+Generate Content (Synchronous Streaming)
+----------------------------------------
+
+Generate content in a streaming format so that the model outputs streams back
+to you, rather than being returned as one chunk.
+
+Streaming for text content
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. code:: python
+
+ for chunk in client.models.generate_content_stream(
+ model='gemini-flash-latest', contents='Tell me a story in 300 words.'
+ ):
+ print(chunk.text, end='')
+
+Streaming for image content
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+If your image is stored in `Google Cloud Storage `_, you can use the ``from_uri`` class method to create a ``Part`` object.
+
+.. code:: python
+
+ from google.genai import types
+
+ for chunk in client.models.generate_content_stream(
+ model='gemini-flash-latest',
+ contents=[
+ 'What is this image about?',
+ types.Part.from_uri(
+ file_uri='gs://generativeai-downloads/images/scones.jpg',
+ mime_type='image/jpeg',
+ ),
+ ],
+ ):
+ print(chunk.text, end='')
+
+
+If your image is stored in your local file system, you can read it in as bytes
+data and use the ``from_bytes`` class method to create a ``Part`` object.
+
+.. code:: python
+
+ from google.genai import types
+
+ YOUR_IMAGE_PATH = 'your_image_path'
+ YOUR_IMAGE_MIME_TYPE = 'your_image_mime_type'
+ with open(YOUR_IMAGE_PATH, 'rb') as f:
+ image_bytes = f.read()
+
+ for chunk in client.models.generate_content_stream(
+ model='gemini-flash-latest',
+ contents=[
+ 'What is this image about?',
+ types.Part.from_bytes(data=image_bytes, mime_type=YOUR_IMAGE_MIME_TYPE),
+ ],
+ ):
+ print(chunk.text, end='')
+
+Generate Content (Asynchronous Non Streaming)
+---------------------------------------------
+
+``client.aio`` exposes all the analogous `async methods `_ that are available on ``client``.
+Note that it applies to all the modules.
+
+For example, ``client.aio.models.generate_content`` is the ``async`` version of ``client.models.generate_content``
+
+.. code:: python
+
+ response = await client.aio.models.generate_content(
+ model='gemini-flash-latest', contents='Tell me a story in 300 words.'
+ )
+
+ print(response.text)
+
+Generate Content (Asynchronous Streaming)
+-----------------------------------------
+
+.. code:: python
+
+ async for chunk in await client.aio.models.generate_content_stream(
+ model='gemini-flash-latest', contents='Tell me a story in 300 words.'
+ ):
+ print(chunk.text, end='')
+
+Count Tokens and Compute Tokens
+-------------------------------
+
+.. code:: python
+
+ response = client.models.count_tokens(
+ model='gemini-flash-latest',
+ contents='why is the sky blue?',
+ )
+ print(response)
+
+Compute Tokens
+^^^^^^^^^^^^^^
+
+Compute tokens is only supported in Gemini Enterprise Agent Platform.
+
+.. code:: python
+
+ response = client.models.compute_tokens(
+ model='gemini-flash-latest',
+ contents='why is the sky blue?',
+ )
+ print(response)
+
+Count Tokens (Asynchronous)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. code:: python
+
+ response = await client.aio.models.count_tokens(
+ model='gemini-flash-latest',
+ contents='why is the sky blue?',
+ )
+ print(response)
+
+Local Count Tokens
+^^^^^^^^^^^^^^^^^^
+
+.. code:: python
+ from google.genai import local_tokenizer
+
+ tokenizer = local_tokenizer.LocalTokenizer(model_name='gemini-2.5-flash')
+ result = tokenizer.count_tokens("What is your name?")
+
+
+Local Compute Tokens
+^^^^^^^^^^^^^^^^^^^^
+
+.. code:: python
+ from google.genai import local_tokenizer
+
+ tokenizer = local_tokenizer.LocalTokenizer(model_name='gemini-2.5-flash')
+ result = tokenizer.compute_tokens("What is your name?")
+
+
+Embed Content
+-------------
+
+.. code:: python
+
+ response = client.models.embed_content(
+ model='gemini-embedding-001',
+ contents='why is the sky blue?',
+ )
+ print(response)
+
+.. code:: python
+
+ from google.genai import types
+
+ # multiple contents with config
+ response = client.models.embed_content(
+ model='gemini-embedding-001',
+ contents=['why is the sky blue?', 'What is your age?'],
+ config=types.EmbedContentConfig(output_dimensionality=10),
+ )
+
+ print(response)
+
+Imagen
+------
+
+Generate Images
+^^^^^^^^^^^^^^^
+
+Support for generate images in Gemini Developer API is behind an allowlist
+
+.. code:: python
+
+ from google.genai import types
+
+ # Generate Image
+ response1 = client.models.generate_images(
+ model='imagen-4.0-generate-001',
+ prompt='An umbrella in the foreground, and a rainy night sky in the background',
+ config=types.GenerateImagesConfig(
+ number_of_images=1,
+ include_rai_reason=True,
+ output_mime_type='image/jpeg',
+ ),
+ )
+ response1.generated_images[0].image.show()
+
+Upscale Image
+^^^^^^^^^^^^^
+
+Upscale image is only supported in Gemini Enterprise Agent Platform.
+
+.. code:: python
+
+ from google.genai import types
+
+ # Upscale the generated image from above
+ response2 = client.models.upscale_image(
+ model='imagen-4.0-upscale-preview',
+ image=response1.generated_images[0].image,
+ upscale_factor='x2',
+ config=types.UpscaleImageConfig(
+ include_rai_reason=True,
+ output_mime_type='image/jpeg',
+ ),
+ )
+ response2.generated_images[0].image.show()
+
+Edit Image
+^^^^^^^^^^^
+
+Edit image uses a separate model from generate and upscale.
+
+Edit image is only supported in Gemini Enterprise Agent Platform.
+
+.. code:: python
+
+ # Edit the generated image from above
+ from google.genai import types
+ from google.genai.types import RawReferenceImage, MaskReferenceImage
+
+ raw_ref_image = RawReferenceImage(
+ reference_id=1,
+ reference_image=response1.generated_images[0].image,
+ )
+
+ # Model computes a mask of the background
+ mask_ref_image = MaskReferenceImage(
+ reference_id=2,
+ config=types.MaskReferenceConfig(
+ mask_mode='MASK_MODE_BACKGROUND',
+ mask_dilation=0,
+ ),
+ )
+
+ response3 = client.models.edit_image(
+ model='imagen-3.0-capability-001',
+ prompt='Sunlight and clear sky',
+ reference_images=[raw_ref_image, mask_ref_image],
+ config=types.EditImageConfig(
+ edit_mode='EDIT_MODE_INPAINT_INSERTION',
+ number_of_images=1,
+ include_rai_reason=True,
+ output_mime_type='image/jpeg',
+ ),
+ )
+ response3.generated_images[0].image.show()
+
+Veo
+------
+Support for generating videos is considered public preview
+
+Generate Videos (Text to Video)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. code:: python
+
+ from google.genai import types
+
+ # Create operation
+ operation = client.models.generate_videos(
+ model='veo-3.1-generate-preview',
+ source=types.GenerateVideosSource(
+ prompt='A neon hologram of a cat driving at top speed',
+ ),
+ config=types.GenerateVideosConfig(
+ number_of_videos=1,
+ duration_seconds=5,
+ enhance_prompt=True,
+ ),
+ )
+
+ # Poll operation
+ while not operation.done:
+ time.sleep(20)
+ operation = client.operations.get(operation)
+
+ video = operation.response.generated_videos[0].video
+ video.show()
+
+
+Generate Videos (Image to Video)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. code:: python
+
+ from google.genai import types
+
+ # Read local image (uses mimetypes.guess_type to infer mime type)
+ image = types.Image.from_file(location="local/path/file.png")
+
+ # Create operation
+ operation = client.models.generate_videos(
+ model='veo-3.1-generate-preview',
+ source=types.GenerateVideosSource(
+ # Prompt is optional if image is provided
+ prompt='Night sky',
+ image=image,
+ ),
+ config=types.GenerateVideosConfig(
+ number_of_videos=1,
+ duration_seconds=5,
+ enhance_prompt=True,
+ # Can also pass an Image into last_frame for frame interpolation
+ ),
+ )
+
+ # Poll operation
+ while not operation.done:
+ time.sleep(20)
+ operation = client.operations.get(operation)
+
+ video = operation.response.generated_videos[0].video
+ video.show()
+
+
+Generate Videos (Video to Video)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Currently, only Gemini Enterprise Agent Platform supports Video to Video generation (Video extension).
+
+
+.. code:: python
+
+ from google.genai import types
+
+ # Read local video (uses mimetypes.guess_type to infer mime type)
+ video = types.Video.from_file("local/path/video.mp4")
+
+ # Create operation
+ operation = client.models.generate_videos(
+ model='veo-3.1-generate-preview',
+ source=types.GenerateVideosSource(
+ # Prompt is optional if Video is provided
+ prompt='Night sky',
+ # Input video must be in GCS
+ video=types.Video(
+ uri="gs://bucket-name/inputs/videos/cat_driving.mp4",
+ ),
+ ),
+ config=types.GenerateVideosConfig(
+ number_of_videos=1,
+ duration_seconds=5,
+ enhance_prompt=True,
+ ),
+ )
+
+ # Poll operation
+ while not operation.done:
+ time.sleep(20)
+ operation = client.operations.get(operation)
+
+ video = operation.response.generated_videos[0].video
+ video.show()
+
+
+Chats
+=====
+
+Create a chat session to start a multi-turn conversations with the model. Then,
+use `chat.send_message` function multiple times within the same chat session so
+that it can reflect on its previous responses (i.e., engage in an ongoing
+conversation). See the 'Create a client' section above to initialize a client.
+
+Send Message (Synchronous Non-Streaming)
+----------------------------------------
+
+.. code:: python
+
+ chat = client.chats.create(model='gemini-flash-latest')
+ response = chat.send_message('tell me a story')
+ print(response.text)
+ response = chat.send_message('summarize the story you told me in 1 sentence')
+ print(response.text)
+
+Send Message (Synchronous Streaming)
+------------------------------------
+
+.. code:: python
+
+ chat = client.chats.create(model='gemini-flash-latest')
+ for chunk in chat.send_message_stream('tell me a story'):
+ print(chunk.text)
+
+Send Message (Asynchronous Non-Streaming)
+-----------------------------------------
+
+.. code:: python
+
+ chat = client.aio.chats.create(model='gemini-flash-latest')
+ response = await chat.send_message('tell me a story')
+ print(response.text)
+
+Send Message (Asynchronous Streaming)
+-------------------------------------
+
+.. code:: python
+
+ chat = client.aio.chats.create(model='gemini-flash-latest')
+ async for chunk in await chat.send_message_stream('tell me a story'):
+ print(chunk.text)
+
+Files
+======================
+
+Files are only supported in Gemini Developer API. See the 'Create a client'
+section above to initialize a client.
+
+.. code:: console
+
+ gcloud storage cp gs://cloud-samples-data/generative-ai/pdf/2312.11805v3.pdf .
+ gcloud storage cp gs://cloud-samples-data/generative-ai/pdf/2403.05530.pdf .
+
+Upload
+------
+
+.. code:: python
+
+ file1 = client.files.upload(file='2312.11805v3.pdf')
+ file2 = client.files.upload(file='2403.05530.pdf')
+
+ print(file1)
+ print(file2)
+
+Get
+---
+
+.. code:: python
+
+ file1 = client.files.upload(file='2312.11805v3.pdf')
+ file_info = client.files.get(name=file1.name)
+
+
+Delete
+------
+
+.. code:: python
+
+ file3 = client.files.upload(file='2312.11805v3.pdf')
+
+ client.files.delete(name=file3.name)
+
+Caches
+======
+
+``client.caches`` contains the control plane APIs for cached content.
+ See the 'Create a client' section above to initialize a client.
+
+Create
+------
+
+.. code:: python
+
+ from google.genai import types
+
+ if client.enterprise:
+ file_uris = [
+ 'gs://cloud-samples-data/generative-ai/pdf/2312.11805v3.pdf',
+ 'gs://cloud-samples-data/generative-ai/pdf/2403.05530.pdf',
+ ]
+ else:
+ file_uris = [file1.uri, file2.uri]
+
+ cached_content = client.caches.create(
+ model='gemini-flash-latest',
+ config=types.CreateCachedContentConfig(
+ contents=[
+ types.Content(
+ role='user',
+ parts=[
+ types.Part.from_uri(
+ file_uri=file_uris[0], mime_type='application/pdf'
+ ),
+ types.Part.from_uri(
+ file_uri=file_uris[1],
+ mime_type='application/pdf',
+ ),
+ ],
+ )
+ ],
+ system_instruction='What is the sum of the two pdfs?',
+ display_name='test cache',
+ ttl='3600s',
+ ),
+ )
+
+Get
+---
+
+.. code:: python
+
+ cached_content = client.caches.get(name=cached_content.name)
+
+Generate Content with Caches
+-----------------------------
+
+.. code:: python
+
+ from google.genai import types
+
+ response = client.models.generate_content(
+ model='gemini-flash-latest',
+ contents='Summarize the pdfs',
+ config=types.GenerateContentConfig(
+ cached_content=cached_content.name,
+ ),
+ )
+ print(response.text)
+
+Interactions
+============
+
+The Interactions API is a unified interface for interacting with Gemini models and agents. It simplifies state management, tool orchestration, and long-running tasks.
+See the `Interactions documentation `_ for more details.
+
+Basic Interaction
+-----------------
+
+.. code:: python
+
+ interaction = client.interactions.create(
+ model='gemini-flash-latest',
+ input='Tell me a short joke about programming.'
+ )
+ print(interaction.output_text)
+
+Stateful Conversation
+---------------------
+
+The Interactions API supports server-side state management. You can continue a conversation by referencing the ``previous_interaction_id``.
+
+.. code:: python
+
+ # 1. First turn
+ interaction1 = client.interactions.create(
+ model='gemini-flash-latest',
+ input='Hi, my name is Amir.'
+ )
+ print(f"Model: {interaction1.output_text}")
+
+ # 2. Second turn (passing previous_interaction_id)
+ interaction2 = client.interactions.create(
+ model='gemini-flash-latest',
+ input='What is my name?',
+ previous_interaction_id=interaction1.id,
+ )
+ print(f"Model: {interaction2.output_text}")
+
+Multimodal Output (Images and Audio)
+------------------------------------
+
+The Interactions API can generate multimodal outputs, such as images or audio, by specifying ``response_modalities``.
+
+.. code:: python
+
+ import base64
+
+ # Generate an image
+ interaction = client.interactions.create(
+ model='gemini-3.1-flash-lite-image',
+ input='Generate an image of a futuristic city.',
+ response_modalities=['IMAGE'],
+ )
+
+ if interaction.output_image:
+ print(f"Generated image with mime_type: {interaction.output_image.mime_type}")
+ with open("generated_city.png", "wb") as f:
+ f.write(base64.b64decode(interaction.output_image.data))
+
+.. code:: python
+
+ import base64
+
+ # Generate speech
+ interaction = client.interactions.create(
+ model='gemini-3.8-flash-tts',
+ input='Say hello and give a one sentence motivational quote.',
+ response_modalities=['AUDIO'],
+ )
+
+ if interaction.output_audio:
+ print(f"Generated audio with mime_type: {interaction.output_audio.mime_type}")
+ with open("greeting.wav", "wb") as f:
+ f.write(base64.b64decode(interaction.output_audio.data))
+
+Built-in Tools
+--------------
+
+You can use Google's built-in tools such as Google Search or Code Execution.
+
+.. code:: python
+
+ interaction = client.interactions.create(
+ model='gemini-flash-latest',
+ input='Who won the last Super Bowl?',
+ tools=[{'type': 'google_search'}],
+ )
+ print(interaction.output_text)
+
+Tunings
+=======
+
+``client.tunings`` contains tuning job APIs and supports supervised fine
+tuning through ``tune``. Only supported in Gemini Enterprise Agent Platform. See the 'Create a client'
+section above to initialize a client.
+
+Tune
+----
+
+- Gemini Enterprise Agent Platform supports tuning from GCS source or from a `Gemini Enterprise Agent Platform Multimodal Dataset `_
+
+.. code:: python
+
+ from google.genai import types
+
+ model = 'gemini-flash-latest'
+ training_dataset = types.TuningDataset(
+ # or gcs_uri=my_enterprise_multimodal_dataset
+ gcs_uri='gs://your-gcs-bucket/your-tuning-data.jsonl',
+ )
+
+
+.. code:: python
+
+ from google.genai import types
+
+ tuning_job = client.tunings.tune(
+ base_model=model,
+ training_dataset=training_dataset,
+ config=types.CreateTuningJobConfig(
+ epoch_count=1, tuned_model_display_name='test_dataset_examples model'
+ ),
+ )
+ print(tuning_job)
+
+Get Tuning Job
+--------------
+
+.. code:: python
+
+ tuning_job = client.tunings.get(name=tuning_job.name)
+ print(tuning_job)
+
+.. code:: python
+
+ import time
+
+ completed_states = set(
+ [
+ 'JOB_STATE_SUCCEEDED',
+ 'JOB_STATE_FAILED',
+ 'JOB_STATE_CANCELLED',
+ ]
+ )
+
+ while tuning_job.state not in completed_states:
+ print(tuning_job.state)
+ tuning_job = client.tunings.get(name=tuning_job.name)
+ time.sleep(10)
+
+Use Tuned Model
+---------------
+
+.. code:: python
+
+ response = client.models.generate_content(
+ model=tuning_job.tuned_model.endpoint,
+ contents='why is the sky blue?',
+ )
+
+ print(response.text)
+
+Get Tuned Model
+---------------
+
+.. code:: python
+
+ tuned_model = client.models.get(model=tuning_job.tuned_model.model)
+ print(tuned_model)
+
+Update Tuned Model
+------------------
+
+.. code:: python
+
+ from google.genai import types
+
+ tuned_model = client.models.update(
+ model=tuning_job.tuned_model.model,
+ config=types.UpdateModelConfig(
+ display_name='my tuned model', description='my tuned model description'
+ ),
+ )
+ print(tuned_model)
+
+.. _List Tuned Models:
+
+List Tuned Models
+-----------------
+
+To retrieve base models, see: :ref:`List Base Models`
+
+.. code:: python
+
+ for model in client.models.list(config={'page_size': 10, 'query_base': False}):
+ print(model)
+
+.. code:: python
+
+ pager = client.models.list(config={'page_size': 10, 'query_base': False})
+ print(pager.page_size)
+ print(pager[0])
+ pager.next_page()
+ print(pager[0])
+
+List Tuned Models (Asynchronous)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. code:: python
+
+ async for job in await client.aio.models.list(config={'page_size': 10, 'query_base': False}):
+ print(job)
+
+.. code:: python
+
+ async_pager = await client.aio.models.list(config={'page_size': 10, 'query_base': False})
+ print(async_pager.page_size)
+ print(async_pager[0])
+ await async_pager.next_page()
+ print(async_pager[0])
+
+Update Tuned Model
+------------------
+
+.. code:: python
+
+ from google.genai import types
+
+ model = pager[0]
+
+ model = client.models.update(
+ model=model.name,
+ config=types.UpdateModelConfig(
+ display_name='my tuned model', description='my tuned model description'
+ ),
+ )
+
+ print(model)
+
+
+List Tuning Jobs
+----------------
+
+.. code:: python
+
+ for job in client.tunings.list(config={'page_size': 10}):
+ print(job)
+
+.. code:: python
+
+ pager = client.tunings.list(config={'page_size': 10})
+ print(pager.page_size)
+ print(pager[0])
+ pager.next_page()
+ print(pager[0])
+
+List Tuning Jobs (Asynchronous):
+
+.. code:: python
+
+ async for job in await client.aio.tunings.list(config={'page_size': 10}):
+ print(job)
+
+.. code:: python
+
+ async_pager = await client.aio.tunings.list(config={'page_size': 10})
+ print(async_pager.page_size)
+ print(async_pager[0])
+ await async_pager.next_page()
+ print(async_pager[0])
+
+Batch Prediction
+================
+
+Create a batch job. See the 'Create a client' section above to
+initialize a client.
+
+Create
+------
+
+Vertex AI client support using a BigQuery table or a GCS file as the source.
+
+.. code:: python
+
+ # Specify model and source file only, destination and job display name will be auto-populated
+ job = client.batches.create(
+ model='gemini-flash-latest',
+ src='bq://my-project.my-dataset.my-table', # or "gs://path/to/input/data"
+ )
+
+ print(job)
+
+
+Gemini Developer API
+^^^^^^^^^^^^^^^^^^^^
+
+.. code:: python
+
+ # Create a batch job with inlined requests
+ batch_job = client.batches.create(
+ model="gemini-flash-latest",
+ src=[{
+ "contents": [{
+ "parts": [{
+ "text": "Hello!",
+ }],
+ "role": "user",
+ }],
+ "config": {"response_modalities": ["text"]},
+ }],
+ )
+
+ job
+
+
+In order to create a batch job with file name. Need to upload a json file.
+For example myrequests.json:
+
+.. code:: json
+
+ {"key":"request_1", "request": {"contents": [{"parts": [{"text":
+ "Explain how AI works in a few words"}]}], "generation_config": {"response_modalities": ["TEXT"]}}}
+ {"key":"request_2", "request": {"contents": [{"parts": [{"text": "Explain how Crypto works in a few words"}]}]}}
+
+
+Then upload the file.
+
+.. code:: python
+
+ # Upload a file to Gemini Developer API
+ file_name = client.files.upload(
+ file='myrequests.json',
+ config=types.UploadFileConfig(display_name='test-json'),
+ )
+ # Create a batch job with file name
+ batch_job = client.batches.create(
+ model="gemini-flash-latest",
+ src="files/test-json",
+ )
+
+
+.. code:: python
+
+ # Get a job by name
+ job = client.batches.get(name=job.name)
+
+ job.state
+
+.. code:: python
+
+ completed_states = set(
+ [
+ 'JOB_STATE_SUCCEEDED',
+ 'JOB_STATE_FAILED',
+ 'JOB_STATE_CANCELLED',
+ 'JOB_STATE_PAUSED',
+ ]
+ )
+
+ while job.state not in completed_states:
+ print(job.state)
+ job = client.batches.get(name=job.name)
+ time.sleep(30)
+
+ job
+
+List
+----
+
+.. code:: python
+
+ from google.genai import types
+
+ for job in client.batches.list(config=types.ListBatchJobsConfig(page_size=10)):
+ print(job)
+
+List Batch Jobs with Pager
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. code:: python
+
+ from google.genai import types
+
+ pager = client.batches.list(config=types.ListBatchJobsConfig(page_size=10))
+ print(pager.page_size)
+ print(pager[0])
+ pager.next_page()
+ print(pager[0])
+
+List Batch Jobs (Asynchronous)
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. code:: python
+
+ from google.genai import types
+
+ async for job in await client.aio.batches.list(
+ config=types.ListBatchJobsConfig(page_size=10)
+ ):
+ print(job)
+
+List Batch Jobs with Pager (Asynchronous)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. code:: python
+
+ from google.genai import types
+
+ async_pager = await client.aio.batches.list(
+ config=types.ListBatchJobsConfig(page_size=10)
+ )
+ print(async_pager.page_size)
+ print(async_pager[0])
+ await async_pager.next_page()
+ print(async_pager[0])
+
+Delete
+------
+
+.. code:: python
+
+ # Delete the job resource
+ delete_job = client.batches.delete(name=job.name)
+
+ delete_job
+
+Error Handling
+==============
+
+To handle errors raised by the model service, the SDK provides this `APIError `_ class.
+
+.. code:: python
+
+ from google.genai import errors
+
+ try:
+ client.models.generate_content(
+ model="invalid-model-name",
+ contents="What is your name?",
+ )
+ except errors.APIError as e:
+ print(e.code) # 404
+ print(e.message)
+
+Extra Request Body
+==================
+
+The ``extra_body`` field in ``HttpOptions`` accepts a dictionary of additional JSON
+properties to include in the request body. This can be used to access new or
+experimental backend features that are not yet formally supported in the SDK.
+The structure of the dictionary must match the backend API's request structure.
+
+- Gemini Enterprise Agent Platform backend API docs: https://docs.cloud.google.com/gemini-enterprise-agent-platform/reference/rest
+- GeminiAPI backend API docs: https://ai.google.dev/api/rest
+
+.. code:: python
+
+ response = client.models.generate_content(
+ model="gemini-flash-latest",
+ contents="What is the weather in Boston? and how about Sunnyvale?",
+ config=types.GenerateContentConfig(
+ tools=[get_current_weather],
+ http_options=types.HttpOptions(extra_body={'tool_config': {'function_calling_config': {'mode': 'COMPOSITIONAL'}}}),
+ ),
+ )
+
+
+Reference
+=========
+.. toctree::
+ :maxdepth: 4
+
+ genai
diff --git a/docs/source/modules.rst b/docs/source/modules.rst
new file mode 100644
index 000000000..ff03010d6
--- /dev/null
+++ b/docs/source/modules.rst
@@ -0,0 +1,7 @@
+google
+======
+
+.. toctree::
+ :maxdepth: 4
+
+ genai