langchain-google-genai 2.1.7__tar.gz → 2.1.9__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.
Potentially problematic release.
This version of langchain-google-genai might be problematic. Click here for more details.
- {langchain_google_genai-2.1.7 → langchain_google_genai-2.1.9}/PKG-INFO +22 -21
- {langchain_google_genai-2.1.7 → langchain_google_genai-2.1.9}/README.md +21 -20
- {langchain_google_genai-2.1.7 → langchain_google_genai-2.1.9}/langchain_google_genai/__init__.py +26 -24
- {langchain_google_genai-2.1.7 → langchain_google_genai-2.1.9}/langchain_google_genai/_common.py +10 -10
- {langchain_google_genai-2.1.7 → langchain_google_genai-2.1.9}/langchain_google_genai/_function_utils.py +9 -2
- {langchain_google_genai-2.1.7 → langchain_google_genai-2.1.9}/langchain_google_genai/_genai_extension.py +5 -5
- {langchain_google_genai-2.1.7 → langchain_google_genai-2.1.9}/langchain_google_genai/_image_utils.py +3 -3
- {langchain_google_genai-2.1.7 → langchain_google_genai-2.1.9}/langchain_google_genai/chat_models.py +186 -31
- {langchain_google_genai-2.1.7 → langchain_google_genai-2.1.9}/langchain_google_genai/embeddings.py +125 -21
- {langchain_google_genai-2.1.7 → langchain_google_genai-2.1.9}/langchain_google_genai/llms.py +13 -1
- {langchain_google_genai-2.1.7 → langchain_google_genai-2.1.9}/pyproject.toml +1 -1
- {langchain_google_genai-2.1.7 → langchain_google_genai-2.1.9}/LICENSE +0 -0
- {langchain_google_genai-2.1.7 → langchain_google_genai-2.1.9}/langchain_google_genai/_enums.py +0 -0
- {langchain_google_genai-2.1.7 → langchain_google_genai-2.1.9}/langchain_google_genai/genai_aqa.py +0 -0
- {langchain_google_genai-2.1.7 → langchain_google_genai-2.1.9}/langchain_google_genai/google_vector_store.py +0 -0
- {langchain_google_genai-2.1.7 → langchain_google_genai-2.1.9}/langchain_google_genai/py.typed +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: langchain-google-genai
|
|
3
|
-
Version: 2.1.
|
|
3
|
+
Version: 2.1.9
|
|
4
4
|
Summary: An integration package connecting Google's genai package and LangChain
|
|
5
5
|
Home-page: https://github.com/langchain-ai/langchain-google
|
|
6
6
|
License: MIT
|
|
@@ -29,16 +29,20 @@ This package enables seamless access to Google Gemini's chat, vision, embeddings
|
|
|
29
29
|
|
|
30
30
|
## Table of Contents
|
|
31
31
|
|
|
32
|
-
- [
|
|
33
|
-
- [
|
|
34
|
-
- [
|
|
35
|
-
- [
|
|
36
|
-
- [
|
|
37
|
-
- [
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
- [
|
|
41
|
-
- [
|
|
32
|
+
- [langchain-google-genai](#langchain-google-genai)
|
|
33
|
+
- [Table of Contents](#table-of-contents)
|
|
34
|
+
- [Overview](#overview)
|
|
35
|
+
- [Installation](#installation)
|
|
36
|
+
- [Quickstart](#quickstart)
|
|
37
|
+
- [Chat Models](#chat-models)
|
|
38
|
+
- [Multimodal Inputs](#multimodal-inputs)
|
|
39
|
+
- [Multimodal Outputs](#multimodal-outputs)
|
|
40
|
+
- [Audio Output](#audio-output)
|
|
41
|
+
- [Multimodal Outputs in Chains](#multimodal-outputs-in-chains)
|
|
42
|
+
- [Thinking Support](#thinking-support)
|
|
43
|
+
- [Embeddings](#embeddings)
|
|
44
|
+
- [Semantic Retrieval (RAG)](#semantic-retrieval-rag)
|
|
45
|
+
- [Resources](#resources)
|
|
42
46
|
|
|
43
47
|
---
|
|
44
48
|
|
|
@@ -109,9 +113,9 @@ print(response.content)
|
|
|
109
113
|
|
|
110
114
|
✅ `image_url` can be:
|
|
111
115
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
116
|
+
- A public image URL
|
|
117
|
+
- A Google Cloud Storage path (`gcs://...`)
|
|
118
|
+
- A base64-encoded image (e.g., `data:image/png;base64,...`)
|
|
115
119
|
|
|
116
120
|
---
|
|
117
121
|
|
|
@@ -208,7 +212,7 @@ You can use Gemini embeddings in LangChain:
|
|
|
208
212
|
```python
|
|
209
213
|
from langchain_google_genai import GoogleGenerativeAIEmbeddings
|
|
210
214
|
|
|
211
|
-
embeddings = GoogleGenerativeAIEmbeddings(model="models/embedding-001")
|
|
215
|
+
embeddings = GoogleGenerativeAIEmbeddings(model="models/gemini-embedding-001")
|
|
212
216
|
vector = embeddings.embed_query("hello, world!")
|
|
213
217
|
print(vector)
|
|
214
218
|
```
|
|
@@ -249,12 +253,9 @@ print("Answerable probability:", response.answerable_probability)
|
|
|
249
253
|
|
|
250
254
|
---
|
|
251
255
|
|
|
252
|
-
|
|
253
256
|
## Resources
|
|
254
257
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
258
|
+
- [LangChain Documentation](https://docs.langchain.com/)
|
|
259
|
+
- [Google Generative AI SDK](https://googleapis.github.io/python-genai/)
|
|
260
|
+
- [Gemini Model Documentation](https://ai.google.dev/)
|
|
260
261
|
|
|
@@ -8,16 +8,20 @@ This package enables seamless access to Google Gemini's chat, vision, embeddings
|
|
|
8
8
|
|
|
9
9
|
## Table of Contents
|
|
10
10
|
|
|
11
|
-
- [
|
|
12
|
-
- [
|
|
13
|
-
- [
|
|
14
|
-
- [
|
|
15
|
-
- [
|
|
16
|
-
- [
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
- [
|
|
20
|
-
- [
|
|
11
|
+
- [langchain-google-genai](#langchain-google-genai)
|
|
12
|
+
- [Table of Contents](#table-of-contents)
|
|
13
|
+
- [Overview](#overview)
|
|
14
|
+
- [Installation](#installation)
|
|
15
|
+
- [Quickstart](#quickstart)
|
|
16
|
+
- [Chat Models](#chat-models)
|
|
17
|
+
- [Multimodal Inputs](#multimodal-inputs)
|
|
18
|
+
- [Multimodal Outputs](#multimodal-outputs)
|
|
19
|
+
- [Audio Output](#audio-output)
|
|
20
|
+
- [Multimodal Outputs in Chains](#multimodal-outputs-in-chains)
|
|
21
|
+
- [Thinking Support](#thinking-support)
|
|
22
|
+
- [Embeddings](#embeddings)
|
|
23
|
+
- [Semantic Retrieval (RAG)](#semantic-retrieval-rag)
|
|
24
|
+
- [Resources](#resources)
|
|
21
25
|
|
|
22
26
|
---
|
|
23
27
|
|
|
@@ -88,9 +92,9 @@ print(response.content)
|
|
|
88
92
|
|
|
89
93
|
✅ `image_url` can be:
|
|
90
94
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
95
|
+
- A public image URL
|
|
96
|
+
- A Google Cloud Storage path (`gcs://...`)
|
|
97
|
+
- A base64-encoded image (e.g., `data:image/png;base64,...`)
|
|
94
98
|
|
|
95
99
|
---
|
|
96
100
|
|
|
@@ -187,7 +191,7 @@ You can use Gemini embeddings in LangChain:
|
|
|
187
191
|
```python
|
|
188
192
|
from langchain_google_genai import GoogleGenerativeAIEmbeddings
|
|
189
193
|
|
|
190
|
-
embeddings = GoogleGenerativeAIEmbeddings(model="models/embedding-001")
|
|
194
|
+
embeddings = GoogleGenerativeAIEmbeddings(model="models/gemini-embedding-001")
|
|
191
195
|
vector = embeddings.embed_query("hello, world!")
|
|
192
196
|
print(vector)
|
|
193
197
|
```
|
|
@@ -228,11 +232,8 @@ print("Answerable probability:", response.answerable_probability)
|
|
|
228
232
|
|
|
229
233
|
---
|
|
230
234
|
|
|
231
|
-
|
|
232
235
|
## Resources
|
|
233
236
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
237
|
+
- [LangChain Documentation](https://docs.langchain.com/)
|
|
238
|
+
- [Google Generative AI SDK](https://googleapis.github.io/python-genai/)
|
|
239
|
+
- [Gemini Model Documentation](https://ai.google.dev/)
|
{langchain_google_genai-2.1.7 → langchain_google_genai-2.1.9}/langchain_google_genai/__init__.py
RENAMED
|
@@ -4,55 +4,57 @@ This module integrates Google's Generative AI models, specifically the Gemini se
|
|
|
4
4
|
|
|
5
5
|
**Chat Models**
|
|
6
6
|
|
|
7
|
-
The
|
|
7
|
+
The ``ChatGoogleGenerativeAI`` class is the primary interface for interacting with Google's Gemini chat models. It allows users to send and receive messages using a specified Gemini model, suitable for various conversational AI applications.
|
|
8
8
|
|
|
9
9
|
**LLMs**
|
|
10
10
|
|
|
11
|
-
The
|
|
11
|
+
The ``GoogleGenerativeAI`` class is the primary interface for interacting with Google's Gemini LLMs. It allows users to generate text using a specified Gemini model.
|
|
12
12
|
|
|
13
13
|
**Embeddings**
|
|
14
14
|
|
|
15
|
-
The
|
|
15
|
+
The ``GoogleGenerativeAIEmbeddings`` class provides functionalities to generate embeddings using Google's models.
|
|
16
16
|
These embeddings can be used for a range of NLP tasks, including semantic analysis, similarity comparisons, and more.
|
|
17
|
+
|
|
17
18
|
**Installation**
|
|
18
19
|
|
|
19
20
|
To install the package, use pip:
|
|
20
21
|
|
|
21
|
-
|
|
22
|
-
pip install -U langchain-google-genai
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
.. code-block:: python
|
|
23
|
+
pip install -U langchain-google-genai
|
|
24
|
+
|
|
25
|
+
**Using Chat Models**
|
|
25
26
|
|
|
26
27
|
After setting up your environment with the required API key, you can interact with the Google Gemini models.
|
|
27
28
|
|
|
28
|
-
|
|
29
|
-
|
|
29
|
+
.. code-block:: python
|
|
30
|
+
|
|
31
|
+
from langchain_google_genai import ChatGoogleGenerativeAI
|
|
30
32
|
|
|
31
|
-
llm = ChatGoogleGenerativeAI(model="gemini-pro")
|
|
32
|
-
llm.invoke("Sing a ballad of LangChain.")
|
|
33
|
-
```
|
|
33
|
+
llm = ChatGoogleGenerativeAI(model="gemini-2.5-pro")
|
|
34
|
+
llm.invoke("Sing a ballad of LangChain.")
|
|
34
35
|
|
|
35
|
-
|
|
36
|
+
**Using LLMs**
|
|
36
37
|
|
|
37
38
|
The package also supports generating text with Google's models.
|
|
38
39
|
|
|
39
|
-
|
|
40
|
-
from langchain_google_genai import GoogleGenerativeAI
|
|
40
|
+
.. code-block:: python
|
|
41
41
|
|
|
42
|
-
|
|
43
|
-
llm.invoke("Once upon a time, a library called LangChain")
|
|
44
|
-
```
|
|
42
|
+
from langchain_google_genai import GoogleGenerativeAI
|
|
45
43
|
|
|
46
|
-
|
|
44
|
+
llm = GoogleGenerativeAI(model="gemini-2.5-pro")
|
|
45
|
+
llm.invoke("Once upon a time, a library called LangChain")
|
|
46
|
+
|
|
47
|
+
**Embedding Generation**
|
|
47
48
|
|
|
48
49
|
The package also supports creating embeddings with Google's models, useful for textual similarity and other NLP applications.
|
|
49
50
|
|
|
50
|
-
|
|
51
|
-
|
|
51
|
+
.. code-block:: python
|
|
52
|
+
|
|
53
|
+
from langchain_google_genai import GoogleGenerativeAIEmbeddings
|
|
54
|
+
|
|
55
|
+
embeddings = GoogleGenerativeAIEmbeddings(model="models/gemini-embedding-001")
|
|
56
|
+
embeddings.embed_query("hello, world!")
|
|
52
57
|
|
|
53
|
-
embeddings = GoogleGenerativeAIEmbeddings(model="models/embedding-001")
|
|
54
|
-
embeddings.embed_query("hello, world!")
|
|
55
|
-
```
|
|
56
58
|
""" # noqa: E501
|
|
57
59
|
|
|
58
60
|
from langchain_google_genai._enums import HarmBlockThreshold, HarmCategory, Modality
|
{langchain_google_genai-2.1.7 → langchain_google_genai-2.1.9}/langchain_google_genai/_common.py
RENAMED
|
@@ -24,8 +24,8 @@ class _BaseGoogleGenerativeAI(BaseModel):
|
|
|
24
24
|
model: str = Field(
|
|
25
25
|
...,
|
|
26
26
|
description="""The name of the model to use.
|
|
27
|
-
|
|
28
|
-
- gemini-pro
|
|
27
|
+
Examples:
|
|
28
|
+
- gemini-2.5-pro
|
|
29
29
|
- models/text-bison-001""",
|
|
30
30
|
)
|
|
31
31
|
"""Model name to use."""
|
|
@@ -39,20 +39,19 @@ Supported examples:
|
|
|
39
39
|
"when making API calls. If not provided, credentials will be ascertained from "
|
|
40
40
|
"the GOOGLE_API_KEY envvar"
|
|
41
41
|
temperature: float = 0.7
|
|
42
|
-
"""Run inference with this temperature. Must
|
|
43
|
-
[0.0, 2.0]."""
|
|
42
|
+
"""Run inference with this temperature. Must be within ``[0.0, 2.0]``."""
|
|
44
43
|
top_p: Optional[float] = None
|
|
45
44
|
"""Decode using nucleus sampling: consider the smallest set of tokens whose
|
|
46
|
-
probability sum is at least top_p
|
|
45
|
+
probability sum is at least ``top_p``. Must be within ``[0.0, 1.0]``."""
|
|
47
46
|
top_k: Optional[int] = None
|
|
48
|
-
"""Decode using top-k sampling: consider the set of top_k most probable tokens.
|
|
47
|
+
"""Decode using top-k sampling: consider the set of ``top_k`` most probable tokens.
|
|
49
48
|
Must be positive."""
|
|
50
49
|
max_output_tokens: Optional[int] = Field(default=None, alias="max_tokens")
|
|
51
50
|
"""Maximum number of tokens to include in a candidate. Must be greater than zero.
|
|
52
|
-
If unset, will default to 64
|
|
51
|
+
If unset, will default to ``64``."""
|
|
53
52
|
n: int = 1
|
|
54
53
|
"""Number of chat completions to generate for each prompt. Note that the API may
|
|
55
|
-
not return the full n completions if duplicates are generated."""
|
|
54
|
+
not return the full ``n`` completions if duplicates are generated."""
|
|
56
55
|
max_retries: int = 6
|
|
57
56
|
"""The maximum number of retries to make when generating."""
|
|
58
57
|
|
|
@@ -94,6 +93,7 @@ Supported examples:
|
|
|
94
93
|
|
|
95
94
|
For example:
|
|
96
95
|
|
|
96
|
+
.. code-block:: python
|
|
97
97
|
from google.generativeai.types.safety_types import HarmBlockThreshold, HarmCategory
|
|
98
98
|
|
|
99
99
|
safety_settings = {
|
|
@@ -102,7 +102,7 @@ Supported examples:
|
|
|
102
102
|
HarmCategory.HARM_CATEGORY_HARASSMENT: HarmBlockThreshold.BLOCK_LOW_AND_ABOVE,
|
|
103
103
|
HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT: HarmBlockThreshold.BLOCK_NONE,
|
|
104
104
|
}
|
|
105
|
-
|
|
105
|
+
""" # noqa: E501
|
|
106
106
|
|
|
107
107
|
@property
|
|
108
108
|
def lc_secrets(self) -> Dict[str, str]:
|
|
@@ -149,7 +149,7 @@ def get_client_info(module: Optional[str] = None) -> "ClientInfo":
|
|
|
149
149
|
module (Optional[str]):
|
|
150
150
|
Optional. The module for a custom user agent header.
|
|
151
151
|
Returns:
|
|
152
|
-
google.api_core.gapic_v1.client_info.ClientInfo
|
|
152
|
+
``google.api_core.gapic_v1.client_info.ClientInfo``
|
|
153
153
|
"""
|
|
154
154
|
client_library_version, user_agent = get_user_agent(module)
|
|
155
155
|
return ClientInfo(
|
|
@@ -322,7 +322,7 @@ def _get_properties_from_schema_any(schema: Any) -> Dict[str, Any]:
|
|
|
322
322
|
|
|
323
323
|
|
|
324
324
|
def _get_properties_from_schema(schema: Dict) -> Dict[str, Any]:
|
|
325
|
-
properties = {}
|
|
325
|
+
properties: Dict[str, Dict[str, Union[str, int, Dict, List]]] = {}
|
|
326
326
|
for k, v in schema.items():
|
|
327
327
|
if not isinstance(k, str):
|
|
328
328
|
logger.warning(f"Key '{k}' is not supported in schema, type={type(k)}")
|
|
@@ -331,7 +331,14 @@ def _get_properties_from_schema(schema: Dict) -> Dict[str, Any]:
|
|
|
331
331
|
logger.warning(f"Value '{v}' is not supported in schema, ignoring v={v}")
|
|
332
332
|
continue
|
|
333
333
|
properties_item: Dict[str, Union[str, int, Dict, List]] = {}
|
|
334
|
-
if v.get("
|
|
334
|
+
if v.get("anyOf") and all(
|
|
335
|
+
anyOf_type.get("type") != "null" for anyOf_type in v.get("anyOf", [])
|
|
336
|
+
):
|
|
337
|
+
properties_item["anyOf"] = [
|
|
338
|
+
_format_json_schema_to_gapic(anyOf_type)
|
|
339
|
+
for anyOf_type in v.get("anyOf", [])
|
|
340
|
+
]
|
|
341
|
+
elif v.get("type") or v.get("anyOf") or v.get("type_"):
|
|
335
342
|
item_type_ = _get_type_from_schema(v)
|
|
336
343
|
properties_item["type_"] = item_type_
|
|
337
344
|
if _is_nullable_schema(v):
|
|
@@ -174,12 +174,12 @@ class TestCredentials(credentials.Credentials):
|
|
|
174
174
|
|
|
175
175
|
@property
|
|
176
176
|
def expired(self) -> bool:
|
|
177
|
-
"""Returns
|
|
177
|
+
"""Returns ``False``, test credentials never expire."""
|
|
178
178
|
return False
|
|
179
179
|
|
|
180
180
|
@property
|
|
181
181
|
def valid(self) -> bool:
|
|
182
|
-
"""Returns
|
|
182
|
+
"""Returns ``True``, test credentials are always valid."""
|
|
183
183
|
return True
|
|
184
184
|
|
|
185
185
|
def refresh(self, request: Any) -> None:
|
|
@@ -206,11 +206,11 @@ class TestCredentials(credentials.Credentials):
|
|
|
206
206
|
def _get_credentials() -> Optional[credentials.Credentials]:
|
|
207
207
|
"""Returns credential from config if set or fake credentials for unit testing.
|
|
208
208
|
|
|
209
|
-
If _config.testing is True
|
|
209
|
+
If ``_config.testing`` is ``True``, a fake credential is returned.
|
|
210
210
|
Otherwise, we are in a real environment and will use credentials if provided
|
|
211
|
-
or None is returned.
|
|
211
|
+
or ``None`` is returned.
|
|
212
212
|
|
|
213
|
-
If None is passed to the clients later on, the actual credentials will be
|
|
213
|
+
If ``None`` is passed to the clients later on, the actual credentials will be
|
|
214
214
|
inferred by the rules specified in google.auth package.
|
|
215
215
|
"""
|
|
216
216
|
if _config.testing:
|
{langchain_google_genai-2.1.7 → langchain_google_genai-2.1.9}/langchain_google_genai/_image_utils.py
RENAMED
|
@@ -30,7 +30,7 @@ class ImageBytesLoader:
|
|
|
30
30
|
"""
|
|
31
31
|
|
|
32
32
|
def load_bytes(self, image_string: str) -> bytes:
|
|
33
|
-
"""Routes to the correct loader based on the image_string
|
|
33
|
+
"""Routes to the correct loader based on the ``'image_string'``.
|
|
34
34
|
|
|
35
35
|
Args:
|
|
36
36
|
image_string: Can be either:
|
|
@@ -178,8 +178,8 @@ def image_bytes_to_b64_string(
|
|
|
178
178
|
|
|
179
179
|
Args:
|
|
180
180
|
image_bytes: Bytes of the image.
|
|
181
|
-
encoding: Type of encoding in the string. 'ascii' by default.
|
|
182
|
-
image_format: Format of the image. 'png' by default.
|
|
181
|
+
encoding: Type of encoding in the string. ``'ascii'`` by default.
|
|
182
|
+
image_format: Format of the image. ``'png'`` by default.
|
|
183
183
|
|
|
184
184
|
Returns:
|
|
185
185
|
B64 image encoded string.
|
{langchain_google_genai-2.1.7 → langchain_google_genai-2.1.9}/langchain_google_genai/chat_models.py
RENAMED
|
@@ -6,6 +6,7 @@ import io
|
|
|
6
6
|
import json
|
|
7
7
|
import logging
|
|
8
8
|
import mimetypes
|
|
9
|
+
import time
|
|
9
10
|
import uuid
|
|
10
11
|
import warnings
|
|
11
12
|
import wave
|
|
@@ -31,7 +32,7 @@ from typing import (
|
|
|
31
32
|
import filetype # type: ignore[import]
|
|
32
33
|
import google.api_core
|
|
33
34
|
|
|
34
|
-
# TODO: remove ignore once the
|
|
35
|
+
# TODO: remove ignore once the Google package is published with types
|
|
35
36
|
import proto # type: ignore[import]
|
|
36
37
|
from google.ai.generativelanguage_v1beta import (
|
|
37
38
|
GenerativeServiceAsyncClient as v1betaGenerativeServiceAsyncClient,
|
|
@@ -153,7 +154,12 @@ class ChatGoogleGenerativeAIError(GoogleGenerativeAIError):
|
|
|
153
154
|
"""
|
|
154
155
|
|
|
155
156
|
|
|
156
|
-
def _create_retry_decorator(
|
|
157
|
+
def _create_retry_decorator(
|
|
158
|
+
max_retries: int = 6,
|
|
159
|
+
wait_exponential_multiplier: float = 2.0,
|
|
160
|
+
wait_exponential_min: float = 1.0,
|
|
161
|
+
wait_exponential_max: float = 60.0,
|
|
162
|
+
) -> Callable[[Any], Any]:
|
|
157
163
|
"""
|
|
158
164
|
Creates and returns a preconfigured tenacity retry decorator.
|
|
159
165
|
|
|
@@ -165,15 +171,14 @@ def _create_retry_decorator() -> Callable[[Any], Any]:
|
|
|
165
171
|
Callable[[Any], Any]: A retry decorator configured for handling specific
|
|
166
172
|
Google API exceptions.
|
|
167
173
|
"""
|
|
168
|
-
multiplier = 2
|
|
169
|
-
min_seconds = 1
|
|
170
|
-
max_seconds = 60
|
|
171
|
-
max_retries = 2
|
|
172
|
-
|
|
173
174
|
return retry(
|
|
174
175
|
reraise=True,
|
|
175
176
|
stop=stop_after_attempt(max_retries),
|
|
176
|
-
wait=wait_exponential(
|
|
177
|
+
wait=wait_exponential(
|
|
178
|
+
multiplier=wait_exponential_multiplier,
|
|
179
|
+
min=wait_exponential_min,
|
|
180
|
+
max=wait_exponential_max,
|
|
181
|
+
),
|
|
177
182
|
retry=(
|
|
178
183
|
retry_if_exception_type(google.api_core.exceptions.ResourceExhausted)
|
|
179
184
|
| retry_if_exception_type(google.api_core.exceptions.ServiceUnavailable)
|
|
@@ -198,13 +203,17 @@ def _chat_with_retry(generation_method: Callable, **kwargs: Any) -> Any:
|
|
|
198
203
|
Returns:
|
|
199
204
|
Any: The result from the chat generation method.
|
|
200
205
|
"""
|
|
201
|
-
retry_decorator = _create_retry_decorator(
|
|
206
|
+
retry_decorator = _create_retry_decorator(
|
|
207
|
+
max_retries=kwargs.get("max_retries", 6),
|
|
208
|
+
wait_exponential_multiplier=kwargs.get("wait_exponential_multiplier", 2.0),
|
|
209
|
+
wait_exponential_min=kwargs.get("wait_exponential_min", 1.0),
|
|
210
|
+
wait_exponential_max=kwargs.get("wait_exponential_max", 60.0),
|
|
211
|
+
)
|
|
202
212
|
|
|
203
213
|
@retry_decorator
|
|
204
214
|
def _chat_with_retry(**kwargs: Any) -> Any:
|
|
205
215
|
try:
|
|
206
216
|
return generation_method(**kwargs)
|
|
207
|
-
# Do not retry for these errors.
|
|
208
217
|
except google.api_core.exceptions.FailedPrecondition as exc:
|
|
209
218
|
if "location is not supported" in exc.message:
|
|
210
219
|
error_msg = (
|
|
@@ -218,6 +227,13 @@ def _chat_with_retry(generation_method: Callable, **kwargs: Any) -> Any:
|
|
|
218
227
|
raise ChatGoogleGenerativeAIError(
|
|
219
228
|
f"Invalid argument provided to Gemini: {e}"
|
|
220
229
|
) from e
|
|
230
|
+
except google.api_core.exceptions.ResourceExhausted as e:
|
|
231
|
+
# Handle quota-exceeded error with recommended retry delay
|
|
232
|
+
if hasattr(e, "retry_after") and e.retry_after < kwargs.get(
|
|
233
|
+
"wait_exponential_max", 60.0
|
|
234
|
+
):
|
|
235
|
+
time.sleep(e.retry_after)
|
|
236
|
+
raise e
|
|
221
237
|
except Exception as e:
|
|
222
238
|
raise e
|
|
223
239
|
|
|
@@ -295,7 +311,7 @@ def _is_openai_image_block(block: dict) -> bool:
|
|
|
295
311
|
def _convert_to_parts(
|
|
296
312
|
raw_content: Union[str, Sequence[Union[str, dict]]],
|
|
297
313
|
) -> List[Part]:
|
|
298
|
-
"""Converts a list of LangChain messages into a
|
|
314
|
+
"""Converts a list of LangChain messages into a Google parts."""
|
|
299
315
|
parts = []
|
|
300
316
|
content = [raw_content] if isinstance(raw_content, str) else raw_content
|
|
301
317
|
image_loader = ImageBytesLoader()
|
|
@@ -413,7 +429,7 @@ def _convert_to_parts(
|
|
|
413
429
|
def _convert_tool_message_to_parts(
|
|
414
430
|
message: ToolMessage | FunctionMessage, name: Optional[str] = None
|
|
415
431
|
) -> list[Part]:
|
|
416
|
-
"""Converts a tool or function message to a
|
|
432
|
+
"""Converts a tool or function message to a Google part."""
|
|
417
433
|
# Legacy agent stores tool name in message.additional_kwargs instead of message.name
|
|
418
434
|
name = message.name or name or message.additional_kwargs.get("name")
|
|
419
435
|
response: Any
|
|
@@ -824,14 +840,13 @@ class ChatGoogleGenerativeAI(_BaseGoogleGenerativeAI, BaseChatModel):
|
|
|
824
840
|
To use, you must have either:
|
|
825
841
|
|
|
826
842
|
1. The ``GOOGLE_API_KEY`` environment variable set with your API key, or
|
|
827
|
-
2. Pass your API key using the google_api_key kwarg
|
|
828
|
-
to the ChatGoogleGenerativeAI constructor.
|
|
843
|
+
2. Pass your API key using the ``google_api_key`` kwarg to the ChatGoogleGenerativeAI constructor.
|
|
829
844
|
|
|
830
845
|
.. code-block:: python
|
|
831
846
|
|
|
832
847
|
from langchain_google_genai import ChatGoogleGenerativeAI
|
|
833
848
|
|
|
834
|
-
llm = ChatGoogleGenerativeAI(model="gemini-2.
|
|
849
|
+
llm = ChatGoogleGenerativeAI(model="gemini-2.5-flash")
|
|
835
850
|
llm.invoke("Write me a ballad about LangChain")
|
|
836
851
|
|
|
837
852
|
Invoke:
|
|
@@ -893,8 +908,8 @@ class ChatGoogleGenerativeAI(_BaseGoogleGenerativeAI, BaseChatModel):
|
|
|
893
908
|
|
|
894
909
|
Context Caching:
|
|
895
910
|
Context caching allows you to store and reuse content (e.g., PDFs, images) for faster processing.
|
|
896
|
-
The
|
|
897
|
-
Below are two examples: caching a single file directly and caching multiple files using
|
|
911
|
+
The ``cached_content`` parameter accepts a cache name created via the Google Generative AI API.
|
|
912
|
+
Below are two examples: caching a single file directly and caching multiple files using ``Part``.
|
|
898
913
|
|
|
899
914
|
Single File Example:
|
|
900
915
|
This caches a single file and queries it.
|
|
@@ -1041,7 +1056,7 @@ class ChatGoogleGenerativeAI(_BaseGoogleGenerativeAI, BaseChatModel):
|
|
|
1041
1056
|
.. code-block:: python
|
|
1042
1057
|
|
|
1043
1058
|
from google.ai.generativelanguage_v1beta.types import Tool as GenAITool
|
|
1044
|
-
llm = ChatGoogleGenerativeAI(model="gemini-2.
|
|
1059
|
+
llm = ChatGoogleGenerativeAI(model="gemini-2.5-flash")
|
|
1045
1060
|
resp = llm.invoke(
|
|
1046
1061
|
"When is the next total solar eclipse in US?",
|
|
1047
1062
|
tools=[GenAITool(google_search={})],
|
|
@@ -1099,6 +1114,144 @@ class ChatGoogleGenerativeAI(_BaseGoogleGenerativeAI, BaseChatModel):
|
|
|
1099
1114
|
|
|
1100
1115
|
'The weather in this image appears to be sunny and pleasant. The sky is a bright blue with scattered white clouds, suggesting fair weather. The lush green grass and trees indicate a warm and possibly slightly breezy day. There are no signs of rain or storms.'
|
|
1101
1116
|
|
|
1117
|
+
PDF input:
|
|
1118
|
+
.. code-block:: python
|
|
1119
|
+
|
|
1120
|
+
import base64
|
|
1121
|
+
from langchain_core.messages import HumanMessage
|
|
1122
|
+
|
|
1123
|
+
pdf_bytes = open("/path/to/your/test.pdf", 'rb').read()
|
|
1124
|
+
pdf_base64 = base64.b64encode(pdf_bytes).decode('utf-8')
|
|
1125
|
+
|
|
1126
|
+
message = HumanMessage(
|
|
1127
|
+
content=[
|
|
1128
|
+
{"type": "text", "text": "describe the document in a sentence"},
|
|
1129
|
+
{
|
|
1130
|
+
"type": "file",
|
|
1131
|
+
"source_type": "base64",
|
|
1132
|
+
"mime_type":"application/pdf",
|
|
1133
|
+
"data": pdf_base64
|
|
1134
|
+
}
|
|
1135
|
+
]
|
|
1136
|
+
)
|
|
1137
|
+
ai_msg = llm.invoke([message])
|
|
1138
|
+
ai_msg.content
|
|
1139
|
+
|
|
1140
|
+
.. code-block:: python
|
|
1141
|
+
|
|
1142
|
+
'This research paper describes a system developed for SemEval-2025 Task 9, which aims to automate the detection of food hazards from recall reports, addressing the class imbalance problem by leveraging LLM-based data augmentation techniques and transformer-based models to improve performance.'
|
|
1143
|
+
|
|
1144
|
+
Video input:
|
|
1145
|
+
.. code-block:: python
|
|
1146
|
+
|
|
1147
|
+
import base64
|
|
1148
|
+
from langchain_core.messages import HumanMessage
|
|
1149
|
+
|
|
1150
|
+
video_bytes = open("/path/to/your/video.mp4", 'rb').read()
|
|
1151
|
+
video_base64 = base64.b64encode(video_bytes).decode('utf-8')
|
|
1152
|
+
|
|
1153
|
+
message = HumanMessage(
|
|
1154
|
+
content=[
|
|
1155
|
+
{"type": "text", "text": "describe what's in this video in a sentence"},
|
|
1156
|
+
{
|
|
1157
|
+
"type": "file",
|
|
1158
|
+
"source_type": "base64",
|
|
1159
|
+
"mime_type": "video/mp4",
|
|
1160
|
+
"data": video_base64
|
|
1161
|
+
}
|
|
1162
|
+
]
|
|
1163
|
+
)
|
|
1164
|
+
ai_msg = llm.invoke([message])
|
|
1165
|
+
ai_msg.content
|
|
1166
|
+
|
|
1167
|
+
.. code-block:: python
|
|
1168
|
+
|
|
1169
|
+
'Tom and Jerry, along with a turkey, engage in a chaotic Thanksgiving-themed adventure involving a corn-on-the-cob chase, maze antics, and a disastrous attempt to prepare a turkey dinner.'
|
|
1170
|
+
|
|
1171
|
+
You can also pass YouTube URLs directly:
|
|
1172
|
+
|
|
1173
|
+
.. code-block:: python
|
|
1174
|
+
|
|
1175
|
+
from langchain_core.messages import HumanMessage
|
|
1176
|
+
|
|
1177
|
+
message = HumanMessage(
|
|
1178
|
+
content=[
|
|
1179
|
+
{"type": "text", "text": "summarize the video in 3 sentences."},
|
|
1180
|
+
{
|
|
1181
|
+
"type": "media",
|
|
1182
|
+
"file_uri": "https://www.youtube.com/watch?v=9hE5-98ZeCg",
|
|
1183
|
+
"mime_type": "video/mp4",
|
|
1184
|
+
}
|
|
1185
|
+
]
|
|
1186
|
+
)
|
|
1187
|
+
ai_msg = llm.invoke([message])
|
|
1188
|
+
ai_msg.content
|
|
1189
|
+
|
|
1190
|
+
.. code-block:: python
|
|
1191
|
+
|
|
1192
|
+
'The video is a demo of multimodal live streaming in Gemini 2.0. The narrator is sharing his screen in AI Studio and asks if the AI can see it. The AI then reads text that is highlighted on the screen, defines the word “multimodal,” and summarizes everything that was seen and heard.'
|
|
1193
|
+
|
|
1194
|
+
Audio input:
|
|
1195
|
+
.. code-block:: python
|
|
1196
|
+
|
|
1197
|
+
import base64
|
|
1198
|
+
from langchain_core.messages import HumanMessage
|
|
1199
|
+
|
|
1200
|
+
audio_bytes = open("/path/to/your/audio.mp3", 'rb').read()
|
|
1201
|
+
audio_base64 = base64.b64encode(audio_bytes).decode('utf-8')
|
|
1202
|
+
|
|
1203
|
+
message = HumanMessage(
|
|
1204
|
+
content=[
|
|
1205
|
+
{"type": "text", "text": "summarize this audio in a sentence"},
|
|
1206
|
+
{
|
|
1207
|
+
"type": "file",
|
|
1208
|
+
"source_type": "base64",
|
|
1209
|
+
"mime_type":"audio/mp3",
|
|
1210
|
+
"data": audio_base64
|
|
1211
|
+
}
|
|
1212
|
+
]
|
|
1213
|
+
)
|
|
1214
|
+
ai_msg = llm.invoke([message])
|
|
1215
|
+
ai_msg.content
|
|
1216
|
+
|
|
1217
|
+
.. code-block:: python
|
|
1218
|
+
|
|
1219
|
+
"In this episode of the Made by Google podcast, Stephen Johnson and Simon Tokumine discuss NotebookLM, a tool designed to help users understand complex material in various modalities, with a focus on its unexpected uses, the development of audio overviews, and the implementation of new features like mind maps and source discovery."
|
|
1220
|
+
|
|
1221
|
+
File upload (URI-based):
|
|
1222
|
+
You can also upload files to Google's servers and reference them by URI.
|
|
1223
|
+
This works for PDFs, images, videos, and audio files.
|
|
1224
|
+
|
|
1225
|
+
.. code-block:: python
|
|
1226
|
+
|
|
1227
|
+
import time
|
|
1228
|
+
from google import genai
|
|
1229
|
+
from langchain_core.messages import HumanMessage
|
|
1230
|
+
|
|
1231
|
+
client = genai.Client()
|
|
1232
|
+
|
|
1233
|
+
myfile = client.files.upload(file="/path/to/your/sample.pdf")
|
|
1234
|
+
while myfile.state.name == "PROCESSING":
|
|
1235
|
+
time.sleep(2)
|
|
1236
|
+
myfile = client.files.get(name=myfile.name)
|
|
1237
|
+
|
|
1238
|
+
message = HumanMessage(
|
|
1239
|
+
content=[
|
|
1240
|
+
{"type": "text", "text": "What is in the document?"},
|
|
1241
|
+
{
|
|
1242
|
+
"type": "media",
|
|
1243
|
+
"file_uri": myfile.uri,
|
|
1244
|
+
"mime_type": "application/pdf",
|
|
1245
|
+
},
|
|
1246
|
+
]
|
|
1247
|
+
)
|
|
1248
|
+
ai_msg = llm.invoke([message])
|
|
1249
|
+
ai_msg.content
|
|
1250
|
+
|
|
1251
|
+
.. code-block:: python
|
|
1252
|
+
|
|
1253
|
+
"This research paper assesses and mitigates multi-turn jailbreak vulnerabilities in large language models using the Crescendo attack study, evaluating attack success rates and mitigation strategies like prompt hardening and LLM-as-guardrail."
|
|
1254
|
+
|
|
1102
1255
|
Token usage:
|
|
1103
1256
|
.. code-block:: python
|
|
1104
1257
|
|
|
@@ -1140,12 +1293,15 @@ class ChatGoogleGenerativeAI(_BaseGoogleGenerativeAI, BaseChatModel):
|
|
|
1140
1293
|
|
|
1141
1294
|
response_mime_type: Optional[str] = None
|
|
1142
1295
|
"""Optional. Output response mimetype of the generated candidate text. Only
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1296
|
+
supported in Gemini 1.5 and later models.
|
|
1297
|
+
|
|
1298
|
+
Supported mimetype:
|
|
1299
|
+
* ``'text/plain'``: (default) Text output.
|
|
1300
|
+
* ``'application/json'``: JSON response in the candidates.
|
|
1301
|
+
* ``'text/x.enum'``: Enum in plain text.
|
|
1302
|
+
|
|
1303
|
+
The model also needs to be prompted to output the appropriate response
|
|
1304
|
+
type, otherwise the behavior is undefined. This is a preview feature.
|
|
1149
1305
|
"""
|
|
1150
1306
|
|
|
1151
1307
|
response_schema: Optional[Dict[str, Any]] = None
|
|
@@ -1230,9 +1386,7 @@ class ChatGoogleGenerativeAI(_BaseGoogleGenerativeAI, BaseChatModel):
|
|
|
1230
1386
|
if self.top_k is not None and self.top_k <= 0:
|
|
1231
1387
|
raise ValueError("top_k must be positive")
|
|
1232
1388
|
|
|
1233
|
-
if not any(
|
|
1234
|
-
self.model.startswith(prefix) for prefix in ("models/", "tunedModels/")
|
|
1235
|
-
):
|
|
1389
|
+
if not any(self.model.startswith(prefix) for prefix in ("models/",)):
|
|
1236
1390
|
self.model = f"models/{self.model}"
|
|
1237
1391
|
|
|
1238
1392
|
additional_headers = self.additional_headers or {}
|
|
@@ -1328,7 +1482,7 @@ class ChatGoogleGenerativeAI(_BaseGoogleGenerativeAI, BaseChatModel):
|
|
|
1328
1482
|
|
|
1329
1483
|
else:
|
|
1330
1484
|
raise ValueError(
|
|
1331
|
-
"Tools are already defined.
|
|
1485
|
+
"Tools are already defined.code_execution tool can't be defined"
|
|
1332
1486
|
)
|
|
1333
1487
|
|
|
1334
1488
|
return super().invoke(input, config, stop=stop, **kwargs)
|
|
@@ -1545,7 +1699,7 @@ class ChatGoogleGenerativeAI(_BaseGoogleGenerativeAI, BaseChatModel):
|
|
|
1545
1699
|
)
|
|
1546
1700
|
|
|
1547
1701
|
if run_manager:
|
|
1548
|
-
run_manager.on_llm_new_token(gen.text)
|
|
1702
|
+
run_manager.on_llm_new_token(gen.text, chunk=gen)
|
|
1549
1703
|
yield gen
|
|
1550
1704
|
|
|
1551
1705
|
async def _astream(
|
|
@@ -1611,7 +1765,7 @@ class ChatGoogleGenerativeAI(_BaseGoogleGenerativeAI, BaseChatModel):
|
|
|
1611
1765
|
)
|
|
1612
1766
|
|
|
1613
1767
|
if run_manager:
|
|
1614
|
-
await run_manager.on_llm_new_token(gen.text)
|
|
1768
|
+
await run_manager.on_llm_new_token(gen.text, chunk=gen)
|
|
1615
1769
|
yield gen
|
|
1616
1770
|
|
|
1617
1771
|
def _prepare_request(
|
|
@@ -1816,7 +1970,8 @@ class ChatGoogleGenerativeAI(_BaseGoogleGenerativeAI, BaseChatModel):
|
|
|
1816
1970
|
tools: A list of tool definitions to bind to this chat model.
|
|
1817
1971
|
Can be a pydantic model, callable, or BaseTool. Pydantic
|
|
1818
1972
|
models, callables, and BaseTools will be automatically converted to
|
|
1819
|
-
their schema dictionary representation.
|
|
1973
|
+
their schema dictionary representation. Tools with Union types in
|
|
1974
|
+
their arguments are now supported and converted to `anyOf` schemas.
|
|
1820
1975
|
**kwargs: Any additional parameters to pass to the
|
|
1821
1976
|
:class:`~langchain.runnable.Runnable` constructor.
|
|
1822
1977
|
"""
|
{langchain_google_genai-2.1.7 → langchain_google_genai-2.1.9}/langchain_google_genai/embeddings.py
RENAMED
|
@@ -17,7 +17,10 @@ from langchain_google_genai._common import (
|
|
|
17
17
|
GoogleGenerativeAIError,
|
|
18
18
|
get_client_info,
|
|
19
19
|
)
|
|
20
|
-
from langchain_google_genai._genai_extension import
|
|
20
|
+
from langchain_google_genai._genai_extension import (
|
|
21
|
+
build_generative_async_service,
|
|
22
|
+
build_generative_service,
|
|
23
|
+
)
|
|
21
24
|
|
|
22
25
|
_MAX_TOKENS_PER_BATCH = 20000
|
|
23
26
|
_DEFAULT_BATCH_SIZE = 100
|
|
@@ -29,29 +32,30 @@ class GoogleGenerativeAIEmbeddings(BaseModel, Embeddings):
|
|
|
29
32
|
To use, you must have either:
|
|
30
33
|
|
|
31
34
|
1. The ``GOOGLE_API_KEY`` environment variable set with your API key, or
|
|
32
|
-
2. Pass your API key using the google_api_key kwarg
|
|
33
|
-
|
|
35
|
+
2. Pass your API key using the google_api_key kwarg to the
|
|
36
|
+
GoogleGenerativeAIEmbeddings constructor.
|
|
34
37
|
|
|
35
38
|
Example:
|
|
36
39
|
.. code-block:: python
|
|
37
40
|
|
|
38
41
|
from langchain_google_genai import GoogleGenerativeAIEmbeddings
|
|
39
42
|
|
|
40
|
-
embeddings = GoogleGenerativeAIEmbeddings(model="
|
|
43
|
+
embeddings = GoogleGenerativeAIEmbeddings(model="gemini-embedding-001")
|
|
41
44
|
embeddings.embed_query("What's our Q1 revenue?")
|
|
42
45
|
"""
|
|
43
46
|
|
|
44
47
|
client: Any = None #: :meta private:
|
|
48
|
+
async_client: Any = None #: :meta private:
|
|
45
49
|
model: str = Field(
|
|
46
50
|
...,
|
|
47
51
|
description="The name of the embedding model to use. "
|
|
48
|
-
"Example: models/embedding-001",
|
|
52
|
+
"Example: ``'models/gemini-embedding-001'``",
|
|
49
53
|
)
|
|
50
54
|
task_type: Optional[str] = Field(
|
|
51
55
|
default=None,
|
|
52
56
|
description="The task type. Valid options include: "
|
|
53
|
-
"task_type_unspecified
|
|
54
|
-
"semantic_similarity
|
|
57
|
+
"``'task_type_unspecified'``, ``'retrieval_query'``, ``'retrieval_document'``, "
|
|
58
|
+
"``'semantic_similarity'``, ``'classification'``, and ``'clustering'``",
|
|
55
59
|
)
|
|
56
60
|
google_api_key: Optional[SecretStr] = Field(
|
|
57
61
|
default_factory=secret_from_env("GOOGLE_API_KEY", default=None),
|
|
@@ -76,7 +80,7 @@ class GoogleGenerativeAIEmbeddings(BaseModel, Embeddings):
|
|
|
76
80
|
)
|
|
77
81
|
transport: Optional[str] = Field(
|
|
78
82
|
default=None,
|
|
79
|
-
description="A string, one of: [
|
|
83
|
+
description="A string, one of: [``'rest'``, ``'grpc'``, ``'grpc_asyncio'``].",
|
|
80
84
|
)
|
|
81
85
|
request_options: Optional[Dict] = Field(
|
|
82
86
|
default=None,
|
|
@@ -93,6 +97,9 @@ class GoogleGenerativeAIEmbeddings(BaseModel, Embeddings):
|
|
|
93
97
|
google_api_key = self.google_api_key
|
|
94
98
|
client_info = get_client_info("GoogleGenerativeAIEmbeddings")
|
|
95
99
|
|
|
100
|
+
if not any(self.model.startswith(prefix) for prefix in ("models/",)):
|
|
101
|
+
self.model = f"models/{self.model}"
|
|
102
|
+
|
|
96
103
|
self.client = build_generative_service(
|
|
97
104
|
credentials=self.credentials,
|
|
98
105
|
api_key=google_api_key,
|
|
@@ -100,6 +107,13 @@ class GoogleGenerativeAIEmbeddings(BaseModel, Embeddings):
|
|
|
100
107
|
client_options=self.client_options,
|
|
101
108
|
transport=self.transport,
|
|
102
109
|
)
|
|
110
|
+
self.async_client = build_generative_async_service(
|
|
111
|
+
credentials=self.credentials,
|
|
112
|
+
api_key=google_api_key,
|
|
113
|
+
client_info=client_info,
|
|
114
|
+
client_options=self.client_options,
|
|
115
|
+
transport=self.transport,
|
|
116
|
+
)
|
|
103
117
|
return self
|
|
104
118
|
|
|
105
119
|
@staticmethod
|
|
@@ -166,12 +180,12 @@ class GoogleGenerativeAIEmbeddings(BaseModel, Embeddings):
|
|
|
166
180
|
def _prepare_request(
|
|
167
181
|
self,
|
|
168
182
|
text: str,
|
|
183
|
+
*,
|
|
169
184
|
task_type: Optional[str] = None,
|
|
170
185
|
title: Optional[str] = None,
|
|
171
186
|
output_dimensionality: Optional[int] = None,
|
|
172
187
|
) -> EmbedContentRequest:
|
|
173
188
|
task_type = self.task_type or task_type or "RETRIEVAL_DOCUMENT"
|
|
174
|
-
# https://ai.google.dev/api/rest/v1/models/batchEmbedContents#EmbedContentRequest
|
|
175
189
|
request = EmbedContentRequest(
|
|
176
190
|
content={"parts": [{"text": text}]},
|
|
177
191
|
model=self.model,
|
|
@@ -190,17 +204,17 @@ class GoogleGenerativeAIEmbeddings(BaseModel, Embeddings):
|
|
|
190
204
|
titles: Optional[List[str]] = None,
|
|
191
205
|
output_dimensionality: Optional[int] = None,
|
|
192
206
|
) -> List[List[float]]:
|
|
193
|
-
"""Embed a list of strings
|
|
194
|
-
|
|
207
|
+
"""Embed a list of strings using the `batch endpoint <https://ai.google.dev/api/embeddings#method:-models.batchembedcontents>`__.
|
|
208
|
+
|
|
209
|
+
Google Generative AI currently sets a max batch size of 100 strings.
|
|
195
210
|
|
|
196
211
|
Args:
|
|
197
212
|
texts: List[str] The list of strings to embed.
|
|
198
213
|
batch_size: [int] The batch size of embeddings to send to the model
|
|
199
|
-
task_type: task_type
|
|
214
|
+
task_type: `task_type <https://ai.google.dev/api/embeddings#tasktype>`__
|
|
200
215
|
titles: An optional list of titles for texts provided.
|
|
201
|
-
|
|
202
|
-
output_dimensionality: Optional reduced dimension for the output embedding.
|
|
203
|
-
https://ai.google.dev/api/rest/v1/models/batchEmbedContents#EmbedContentRequest
|
|
216
|
+
Only applicable when TaskType is ``'RETRIEVAL_DOCUMENT'``.
|
|
217
|
+
output_dimensionality: Optional `reduced dimension for the output embedding <https://ai.google.dev/api/embeddings#EmbedContentRequest>`__.
|
|
204
218
|
Returns:
|
|
205
219
|
List of embeddings, one for each text.
|
|
206
220
|
"""
|
|
@@ -237,26 +251,26 @@ class GoogleGenerativeAIEmbeddings(BaseModel, Embeddings):
|
|
|
237
251
|
def embed_query(
|
|
238
252
|
self,
|
|
239
253
|
text: str,
|
|
254
|
+
*,
|
|
240
255
|
task_type: Optional[str] = None,
|
|
241
256
|
title: Optional[str] = None,
|
|
242
257
|
output_dimensionality: Optional[int] = None,
|
|
243
258
|
) -> List[float]:
|
|
244
|
-
"""Embed a text, using the non-batch endpoint
|
|
245
|
-
https://ai.google.dev/api/rest/v1/models/embedContent#EmbedContentRequest
|
|
259
|
+
"""Embed a text, using the `non-batch endpoint <https://ai.google.dev/api/embeddings#method:-models.embedcontent>`__.
|
|
246
260
|
|
|
247
261
|
Args:
|
|
248
262
|
text: The text to embed.
|
|
249
|
-
task_type: task_type
|
|
263
|
+
task_type: `task_type <https://ai.google.dev/api/embeddings#tasktype>`__
|
|
250
264
|
title: An optional title for the text.
|
|
251
|
-
|
|
252
|
-
output_dimensionality: Optional reduced dimension for the output embedding.
|
|
265
|
+
Only applicable when TaskType is ``'RETRIEVAL_DOCUMENT'``.
|
|
266
|
+
output_dimensionality: Optional `reduced dimension for the output embedding <https://ai.google.dev/api/embeddings#EmbedContentRequest>`__.
|
|
253
267
|
|
|
254
268
|
Returns:
|
|
255
269
|
Embedding for the text.
|
|
256
270
|
"""
|
|
257
271
|
task_type_to_use = task_type if task_type else self.task_type
|
|
258
272
|
if task_type_to_use is None:
|
|
259
|
-
task_type_to_use = "RETRIEVAL_QUERY"
|
|
273
|
+
task_type_to_use = "RETRIEVAL_QUERY"
|
|
260
274
|
try:
|
|
261
275
|
request: EmbedContentRequest = self._prepare_request(
|
|
262
276
|
text=text,
|
|
@@ -268,3 +282,93 @@ class GoogleGenerativeAIEmbeddings(BaseModel, Embeddings):
|
|
|
268
282
|
except Exception as e:
|
|
269
283
|
raise GoogleGenerativeAIError(f"Error embedding content: {e}") from e
|
|
270
284
|
return list(result.embedding.values)
|
|
285
|
+
|
|
286
|
+
async def aembed_documents(
|
|
287
|
+
self,
|
|
288
|
+
texts: List[str],
|
|
289
|
+
*,
|
|
290
|
+
batch_size: int = _DEFAULT_BATCH_SIZE,
|
|
291
|
+
task_type: Optional[str] = None,
|
|
292
|
+
titles: Optional[List[str]] = None,
|
|
293
|
+
output_dimensionality: Optional[int] = None,
|
|
294
|
+
) -> List[List[float]]:
|
|
295
|
+
"""Embed a list of strings using the `batch endpoint <https://ai.google.dev/api/embeddings#method:-models.batchembedcontents>`__.
|
|
296
|
+
|
|
297
|
+
Google Generative AI currently sets a max batch size of 100 strings.
|
|
298
|
+
|
|
299
|
+
Args:
|
|
300
|
+
texts: List[str] The list of strings to embed.
|
|
301
|
+
batch_size: [int] The batch size of embeddings to send to the model
|
|
302
|
+
task_type: `task_type <https://ai.google.dev/api/embeddings#tasktype>`__
|
|
303
|
+
titles: An optional list of titles for texts provided.
|
|
304
|
+
Only applicable when TaskType is ``'RETRIEVAL_DOCUMENT'``.
|
|
305
|
+
output_dimensionality: Optional `reduced dimension for the output embedding <https://ai.google.dev/api/embeddings#EmbedContentRequest>`__.
|
|
306
|
+
Returns:
|
|
307
|
+
List of embeddings, one for each text.
|
|
308
|
+
"""
|
|
309
|
+
embeddings: List[List[float]] = []
|
|
310
|
+
batch_start_index = 0
|
|
311
|
+
for batch in GoogleGenerativeAIEmbeddings._prepare_batches(texts, batch_size):
|
|
312
|
+
if titles:
|
|
313
|
+
titles_batch = titles[
|
|
314
|
+
batch_start_index : batch_start_index + len(batch)
|
|
315
|
+
]
|
|
316
|
+
batch_start_index += len(batch)
|
|
317
|
+
else:
|
|
318
|
+
titles_batch = [None] * len(batch) # type: ignore[list-item]
|
|
319
|
+
|
|
320
|
+
requests = [
|
|
321
|
+
self._prepare_request(
|
|
322
|
+
text=text,
|
|
323
|
+
task_type=task_type,
|
|
324
|
+
title=title,
|
|
325
|
+
output_dimensionality=output_dimensionality,
|
|
326
|
+
)
|
|
327
|
+
for text, title in zip(batch, titles_batch)
|
|
328
|
+
]
|
|
329
|
+
|
|
330
|
+
try:
|
|
331
|
+
result = await self.async_client.batch_embed_contents(
|
|
332
|
+
BatchEmbedContentsRequest(requests=requests, model=self.model)
|
|
333
|
+
)
|
|
334
|
+
except Exception as e:
|
|
335
|
+
raise GoogleGenerativeAIError(f"Error embedding content: {e}") from e
|
|
336
|
+
embeddings.extend([list(e.values) for e in result.embeddings])
|
|
337
|
+
return embeddings
|
|
338
|
+
|
|
339
|
+
async def aembed_query(
|
|
340
|
+
self,
|
|
341
|
+
text: str,
|
|
342
|
+
*,
|
|
343
|
+
task_type: Optional[str] = None,
|
|
344
|
+
title: Optional[str] = None,
|
|
345
|
+
output_dimensionality: Optional[int] = None,
|
|
346
|
+
) -> List[float]:
|
|
347
|
+
"""Embed a text, using the `non-batch endpoint <https://ai.google.dev/api/embeddings#method:-models.embedcontent>`__.
|
|
348
|
+
|
|
349
|
+
Args:
|
|
350
|
+
text: The text to embed.
|
|
351
|
+
task_type: `task_type <https://ai.google.dev/api/embeddings#tasktype>`__
|
|
352
|
+
title: An optional title for the text.
|
|
353
|
+
Only applicable when TaskType is ``'RETRIEVAL_DOCUMENT'``.
|
|
354
|
+
output_dimensionality: Optional `reduced dimension for the output embedding <https://ai.google.dev/api/embeddings#EmbedContentRequest>`__.
|
|
355
|
+
|
|
356
|
+
Returns:
|
|
357
|
+
Embedding for the text.
|
|
358
|
+
"""
|
|
359
|
+
task_type_to_use = task_type if task_type else self.task_type
|
|
360
|
+
if task_type_to_use is None:
|
|
361
|
+
task_type_to_use = "RETRIEVAL_QUERY"
|
|
362
|
+
try:
|
|
363
|
+
request: EmbedContentRequest = self._prepare_request(
|
|
364
|
+
text=text,
|
|
365
|
+
task_type=task_type,
|
|
366
|
+
title=title,
|
|
367
|
+
output_dimensionality=output_dimensionality,
|
|
368
|
+
)
|
|
369
|
+
result: EmbedContentResponse = await self.async_client.embed_content(
|
|
370
|
+
request
|
|
371
|
+
)
|
|
372
|
+
except Exception as e:
|
|
373
|
+
raise GoogleGenerativeAIError(f"Error embedding content: {e}") from e
|
|
374
|
+
return list(result.embedding.values)
|
{langchain_google_genai-2.1.7 → langchain_google_genai-2.1.9}/langchain_google_genai/llms.py
RENAMED
|
@@ -29,7 +29,7 @@ class GoogleGenerativeAI(_BaseGoogleGenerativeAI, BaseLLM):
|
|
|
29
29
|
.. code-block:: python
|
|
30
30
|
|
|
31
31
|
from langchain_google_genai import GoogleGenerativeAI
|
|
32
|
-
llm = GoogleGenerativeAI(model="gemini-pro")
|
|
32
|
+
llm = GoogleGenerativeAI(model="gemini-2.5-pro")
|
|
33
33
|
"""
|
|
34
34
|
|
|
35
35
|
client: Any = None #: :meta private:
|
|
@@ -63,6 +63,9 @@ class GoogleGenerativeAI(_BaseGoogleGenerativeAI, BaseLLM):
|
|
|
63
63
|
def validate_environment(self) -> Self:
|
|
64
64
|
"""Validates params and passes them to google-generativeai package."""
|
|
65
65
|
|
|
66
|
+
if not any(self.model.startswith(prefix) for prefix in ("models/",)):
|
|
67
|
+
self.model = f"models/{self.model}"
|
|
68
|
+
|
|
66
69
|
self.client = ChatGoogleGenerativeAI(
|
|
67
70
|
api_key=self.google_api_key,
|
|
68
71
|
credentials=self.credentials,
|
|
@@ -86,6 +89,15 @@ class GoogleGenerativeAI(_BaseGoogleGenerativeAI, BaseLLM):
|
|
|
86
89
|
"""Get standard params for tracing."""
|
|
87
90
|
ls_params = super()._get_ls_params(stop=stop, **kwargs)
|
|
88
91
|
ls_params["ls_provider"] = "google_genai"
|
|
92
|
+
|
|
93
|
+
models_prefix = "models/"
|
|
94
|
+
ls_model_name = (
|
|
95
|
+
self.model[len(models_prefix) :]
|
|
96
|
+
if self.model and self.model.startswith(models_prefix)
|
|
97
|
+
else self.model
|
|
98
|
+
)
|
|
99
|
+
ls_params["ls_model_name"] = ls_model_name
|
|
100
|
+
|
|
89
101
|
if ls_max_tokens := kwargs.get("max_output_tokens", self.max_output_tokens):
|
|
90
102
|
ls_params["ls_max_tokens"] = ls_max_tokens
|
|
91
103
|
return ls_params
|
|
File without changes
|
{langchain_google_genai-2.1.7 → langchain_google_genai-2.1.9}/langchain_google_genai/_enums.py
RENAMED
|
File without changes
|
{langchain_google_genai-2.1.7 → langchain_google_genai-2.1.9}/langchain_google_genai/genai_aqa.py
RENAMED
|
File without changes
|
|
File without changes
|
{langchain_google_genai-2.1.7 → langchain_google_genai-2.1.9}/langchain_google_genai/py.typed
RENAMED
|
File without changes
|