langchain-google-genai 2.0.3__py3-none-any.whl → 2.0.5__py3-none-any.whl
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/_image_utils.py +15 -21
- langchain_google_genai/chat_models.py +11 -86
- langchain_google_genai/llms.py +12 -1
- {langchain_google_genai-2.0.3.dist-info → langchain_google_genai-2.0.5.dist-info}/METADATA +2 -12
- {langchain_google_genai-2.0.3.dist-info → langchain_google_genai-2.0.5.dist-info}/RECORD +7 -7
- {langchain_google_genai-2.0.3.dist-info → langchain_google_genai-2.0.5.dist-info}/LICENSE +0 -0
- {langchain_google_genai-2.0.3.dist-info → langchain_google_genai-2.0.5.dist-info}/WHEEL +0 -0
|
@@ -25,7 +25,6 @@ class ImageBytesLoader:
|
|
|
25
25
|
|
|
26
26
|
Currently supported:
|
|
27
27
|
- B64 Encoded image string
|
|
28
|
-
- Local file path
|
|
29
28
|
- URL
|
|
30
29
|
"""
|
|
31
30
|
|
|
@@ -35,7 +34,6 @@ class ImageBytesLoader:
|
|
|
35
34
|
Args:
|
|
36
35
|
image_string: Can be either:
|
|
37
36
|
- B64 Encoded image string
|
|
38
|
-
- Local file path
|
|
39
37
|
- URL
|
|
40
38
|
|
|
41
39
|
Returns:
|
|
@@ -51,12 +49,17 @@ class ImageBytesLoader:
|
|
|
51
49
|
return self._bytes_from_url(image_string)
|
|
52
50
|
|
|
53
51
|
if route == Route.LOCAL_FILE:
|
|
52
|
+
raise ValueError(
|
|
53
|
+
"Loading from local files is no longer supported for security reasons. "
|
|
54
|
+
"Please pass in images as Google Cloud Storage URI, "
|
|
55
|
+
"b64 encoded image string (data:image/...), or valid image url."
|
|
56
|
+
)
|
|
54
57
|
return self._bytes_from_file(image_string)
|
|
55
58
|
|
|
56
59
|
raise ValueError(
|
|
57
60
|
"Image string must be one of: Google Cloud Storage URI, "
|
|
58
|
-
"b64 encoded image string (data:image/...), valid image url
|
|
59
|
-
f"
|
|
61
|
+
"b64 encoded image string (data:image/...), or valid image url."
|
|
62
|
+
f"Instead got '{image_string}'."
|
|
60
63
|
)
|
|
61
64
|
|
|
62
65
|
def load_part(self, image_string: str) -> Part:
|
|
@@ -65,7 +68,6 @@ class ImageBytesLoader:
|
|
|
65
68
|
Args:
|
|
66
69
|
image_string: Can be either:
|
|
67
70
|
- B64 Encoded image string
|
|
68
|
-
- Local file path
|
|
69
71
|
- URL
|
|
70
72
|
"""
|
|
71
73
|
route = self._route(image_string)
|
|
@@ -77,7 +79,12 @@ class ImageBytesLoader:
|
|
|
77
79
|
bytes_ = self._bytes_from_url(image_string)
|
|
78
80
|
|
|
79
81
|
if route == Route.LOCAL_FILE:
|
|
80
|
-
|
|
82
|
+
msg = (
|
|
83
|
+
"Loading from local files is no longer supported for security reasons. "
|
|
84
|
+
"Please specify images as Google Cloud Storage URI, "
|
|
85
|
+
"b64 encoded image string (data:image/...), or valid image url."
|
|
86
|
+
)
|
|
87
|
+
raise ValueError(msg)
|
|
81
88
|
|
|
82
89
|
inline_data: Dict[str, Any] = {"data": bytes_}
|
|
83
90
|
mime_type, _ = mimetypes.guess_type(image_string)
|
|
@@ -98,8 +105,8 @@ class ImageBytesLoader:
|
|
|
98
105
|
|
|
99
106
|
raise ValueError(
|
|
100
107
|
"Image string must be one of: "
|
|
101
|
-
"b64 encoded image string (data:image/...)
|
|
102
|
-
f"
|
|
108
|
+
"b64 encoded image string (data:image/...) or valid image url."
|
|
109
|
+
f" Instead got '{image_string}'."
|
|
103
110
|
)
|
|
104
111
|
|
|
105
112
|
def _bytes_from_b64(self, base64_image: str) -> bytes:
|
|
@@ -121,19 +128,6 @@ class ImageBytesLoader:
|
|
|
121
128
|
|
|
122
129
|
raise ValueError(f"Error in b64 encoded image. Must follow pattern: {pattern}")
|
|
123
130
|
|
|
124
|
-
def _bytes_from_file(self, file_path: str) -> bytes:
|
|
125
|
-
"""Gets image bytes from a local file path.
|
|
126
|
-
|
|
127
|
-
Args:
|
|
128
|
-
file_path: Existing file path.
|
|
129
|
-
|
|
130
|
-
Returns:
|
|
131
|
-
Image bytes
|
|
132
|
-
"""
|
|
133
|
-
with open(file_path, "rb") as image_file:
|
|
134
|
-
image_bytes = image_file.read()
|
|
135
|
-
return image_bytes
|
|
136
|
-
|
|
137
131
|
def _bytes_from_url(self, url: str) -> bytes:
|
|
138
132
|
"""Gets image bytes from a public url.
|
|
139
133
|
|
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import asyncio
|
|
4
|
-
import base64
|
|
5
4
|
import json
|
|
6
5
|
import logging
|
|
7
|
-
import os
|
|
8
6
|
import uuid
|
|
9
7
|
import warnings
|
|
10
|
-
from io import BytesIO
|
|
11
8
|
from operator import itemgetter
|
|
12
9
|
from typing import (
|
|
13
10
|
Any,
|
|
@@ -24,13 +21,11 @@ from typing import (
|
|
|
24
21
|
Union,
|
|
25
22
|
cast,
|
|
26
23
|
)
|
|
27
|
-
from urllib.parse import urlparse
|
|
28
24
|
|
|
29
25
|
import google.api_core
|
|
30
26
|
|
|
31
27
|
# TODO: remove ignore once the google package is published with types
|
|
32
28
|
import proto # type: ignore[import]
|
|
33
|
-
import requests
|
|
34
29
|
from google.ai.generativelanguage_v1beta import (
|
|
35
30
|
GenerativeServiceAsyncClient as v1betaGenerativeServiceAsyncClient,
|
|
36
31
|
)
|
|
@@ -117,16 +112,6 @@ from langchain_google_genai.llms import _BaseGoogleGenerativeAI
|
|
|
117
112
|
|
|
118
113
|
from . import _genai_extension as genaix
|
|
119
114
|
|
|
120
|
-
IMAGE_TYPES: Tuple = ()
|
|
121
|
-
try:
|
|
122
|
-
import PIL
|
|
123
|
-
from PIL.Image import Image
|
|
124
|
-
|
|
125
|
-
IMAGE_TYPES = IMAGE_TYPES + (Image,)
|
|
126
|
-
except ImportError:
|
|
127
|
-
PIL = None # type: ignore
|
|
128
|
-
Image = None # type: ignore
|
|
129
|
-
|
|
130
115
|
logger = logging.getLogger(__name__)
|
|
131
116
|
|
|
132
117
|
|
|
@@ -248,75 +233,6 @@ def _is_openai_parts_format(part: dict) -> bool:
|
|
|
248
233
|
return "type" in part
|
|
249
234
|
|
|
250
235
|
|
|
251
|
-
def _is_vision_model(model: str) -> bool:
|
|
252
|
-
return "vision" in model
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
def _is_url(s: str) -> bool:
|
|
256
|
-
try:
|
|
257
|
-
result = urlparse(s)
|
|
258
|
-
return all([result.scheme, result.netloc])
|
|
259
|
-
except Exception as e:
|
|
260
|
-
logger.debug(f"Unable to parse URL: {e}")
|
|
261
|
-
return False
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
def _is_b64(s: str) -> bool:
|
|
265
|
-
return s.startswith("data:image")
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
def _load_image_from_gcs(path: str, project: Optional[str] = None) -> Image:
|
|
269
|
-
try:
|
|
270
|
-
from google.cloud import storage # type: ignore[attr-defined]
|
|
271
|
-
except ImportError:
|
|
272
|
-
raise ImportError(
|
|
273
|
-
"google-cloud-storage is required to load images from GCS."
|
|
274
|
-
" Install it with `pip install google-cloud-storage`"
|
|
275
|
-
)
|
|
276
|
-
if PIL is None:
|
|
277
|
-
raise ImportError(
|
|
278
|
-
"PIL is required to load images. Please install it "
|
|
279
|
-
"with `pip install pillow`"
|
|
280
|
-
)
|
|
281
|
-
|
|
282
|
-
gcs_client = storage.Client(project=project)
|
|
283
|
-
pieces = path.split("/")
|
|
284
|
-
blobs = list(gcs_client.list_blobs(pieces[2], prefix="/".join(pieces[3:])))
|
|
285
|
-
if len(blobs) > 1:
|
|
286
|
-
raise ValueError(f"Found more than one candidate for {path}!")
|
|
287
|
-
img_bytes = blobs[0].download_as_bytes()
|
|
288
|
-
return PIL.Image.open(BytesIO(img_bytes))
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
def _url_to_pil(image_source: str) -> Image:
|
|
292
|
-
if PIL is None:
|
|
293
|
-
raise ImportError(
|
|
294
|
-
"PIL is required to load images. Please install it "
|
|
295
|
-
"with `pip install pillow`"
|
|
296
|
-
)
|
|
297
|
-
try:
|
|
298
|
-
if isinstance(image_source, IMAGE_TYPES):
|
|
299
|
-
return image_source # type: ignore[return-value]
|
|
300
|
-
elif _is_url(image_source):
|
|
301
|
-
if image_source.startswith("gs://"):
|
|
302
|
-
return _load_image_from_gcs(image_source)
|
|
303
|
-
response = requests.get(image_source)
|
|
304
|
-
response.raise_for_status()
|
|
305
|
-
return PIL.Image.open(BytesIO(response.content))
|
|
306
|
-
elif _is_b64(image_source):
|
|
307
|
-
_, encoded = image_source.split(",", 1)
|
|
308
|
-
data = base64.b64decode(encoded)
|
|
309
|
-
return PIL.Image.open(BytesIO(data))
|
|
310
|
-
elif os.path.exists(image_source):
|
|
311
|
-
return PIL.Image.open(image_source)
|
|
312
|
-
else:
|
|
313
|
-
raise ValueError(
|
|
314
|
-
"The provided string is not a valid URL, base64, or file path."
|
|
315
|
-
)
|
|
316
|
-
except Exception as e:
|
|
317
|
-
raise ValueError(f"Unable to process the provided image source: {e}")
|
|
318
|
-
|
|
319
|
-
|
|
320
236
|
def _convert_to_parts(
|
|
321
237
|
raw_content: Union[str, Sequence[Union[str, dict]]],
|
|
322
238
|
) -> List[Part]:
|
|
@@ -400,8 +316,17 @@ def _parse_chat_history(
|
|
|
400
316
|
continue
|
|
401
317
|
elif isinstance(message, AIMessage):
|
|
402
318
|
role = "model"
|
|
403
|
-
|
|
404
|
-
|
|
319
|
+
if message.tool_calls:
|
|
320
|
+
parts = []
|
|
321
|
+
for tool_call in message.tool_calls:
|
|
322
|
+
function_call = FunctionCall(
|
|
323
|
+
{
|
|
324
|
+
"name": tool_call["name"],
|
|
325
|
+
"args": tool_call["args"],
|
|
326
|
+
}
|
|
327
|
+
)
|
|
328
|
+
parts.append(Part(function_call=function_call))
|
|
329
|
+
elif raw_function_call := message.additional_kwargs.get("function_call"):
|
|
405
330
|
function_call = FunctionCall(
|
|
406
331
|
{
|
|
407
332
|
"name": raw_function_call["name"],
|
langchain_google_genai/llms.py
CHANGED
|
@@ -310,10 +310,21 @@ class GoogleGenerativeAI(_BaseGoogleGenerativeAI, BaseLLM):
|
|
|
310
310
|
generation_config=generation_config,
|
|
311
311
|
safety_settings=kwargs.pop("safety_settings", None),
|
|
312
312
|
)
|
|
313
|
+
generation_info = None
|
|
314
|
+
if res.usage_metadata is not None:
|
|
315
|
+
generation_info = {
|
|
316
|
+
"usage_metadata": res.to_dict().get("usage_metadata")
|
|
317
|
+
}
|
|
318
|
+
|
|
313
319
|
candidates = [
|
|
314
320
|
"".join([p.text for p in c.content.parts]) for c in res.candidates
|
|
315
321
|
]
|
|
316
|
-
generations.append(
|
|
322
|
+
generations.append(
|
|
323
|
+
[
|
|
324
|
+
Generation(text=c, generation_info=generation_info)
|
|
325
|
+
for c in candidates
|
|
326
|
+
]
|
|
327
|
+
)
|
|
317
328
|
else:
|
|
318
329
|
res = _completion_with_retry(
|
|
319
330
|
self,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: langchain-google-genai
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.5
|
|
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
|
|
@@ -11,10 +11,8 @@ Classifier: Programming Language :: Python :: 3.9
|
|
|
11
11
|
Classifier: Programming Language :: Python :: 3.10
|
|
12
12
|
Classifier: Programming Language :: Python :: 3.11
|
|
13
13
|
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
-
Provides-Extra: images
|
|
15
14
|
Requires-Dist: google-generativeai (>=0.8.0,<0.9.0)
|
|
16
|
-
Requires-Dist: langchain-core (>=0.3.
|
|
17
|
-
Requires-Dist: pillow (>=10.1.0,<11.0.0) ; extra == "images"
|
|
15
|
+
Requires-Dist: langchain-core (>=0.3.15,<0.4)
|
|
18
16
|
Requires-Dist: pydantic (>=2,<3)
|
|
19
17
|
Project-URL: Repository, https://github.com/langchain-ai/langchain-google
|
|
20
18
|
Project-URL: Source Code, https://github.com/langchain-ai/langchain-google/tree/main/libs/genai
|
|
@@ -30,12 +28,6 @@ This package contains the LangChain integrations for Gemini through their genera
|
|
|
30
28
|
pip install -U langchain-google-genai
|
|
31
29
|
```
|
|
32
30
|
|
|
33
|
-
### Image utilities
|
|
34
|
-
To use image utility methods, like loading images from GCS urls, install with extras group 'images':
|
|
35
|
-
|
|
36
|
-
```bash
|
|
37
|
-
pip install -e "langchain-google-genai[images]"
|
|
38
|
-
```
|
|
39
31
|
|
|
40
32
|
## Chat Models
|
|
41
33
|
|
|
@@ -82,9 +74,7 @@ The value of `image_url` can be any of the following:
|
|
|
82
74
|
|
|
83
75
|
- A public image URL
|
|
84
76
|
- An accessible gcs file (e.g., "gcs://path/to/file.png")
|
|
85
|
-
- A local file path
|
|
86
77
|
- A base64 encoded image (e.g., `data:image/png;base64,abcd124`)
|
|
87
|
-
- A PIL image
|
|
88
78
|
|
|
89
79
|
|
|
90
80
|
|
|
@@ -3,14 +3,14 @@ langchain_google_genai/_common.py,sha256=ASlwE8hEbvOm55BVF_D4rf2nl7RYsnpsi5xbM6D
|
|
|
3
3
|
langchain_google_genai/_enums.py,sha256=KLPmxS1K83K4HjBIXFaXoL_sFEOv8Hq-2B2PDMKyDgo,197
|
|
4
4
|
langchain_google_genai/_function_utils.py,sha256=ksKgLoKPhKzd3QLLgYojuq4tOegoEL-oHPncARPds3w,16891
|
|
5
5
|
langchain_google_genai/_genai_extension.py,sha256=81a4ly5ZHlqMf37uJfdB8K41qE6J5ujLnbUypIfFf2o,20775
|
|
6
|
-
langchain_google_genai/_image_utils.py,sha256
|
|
7
|
-
langchain_google_genai/chat_models.py,sha256=
|
|
6
|
+
langchain_google_genai/_image_utils.py,sha256=_3knaOcAlI8AxHO8NyqNIqGbtldWRBU5wm5trdyhTzY,5033
|
|
7
|
+
langchain_google_genai/chat_models.py,sha256=X5CHWmRQjoV1l6AN0VbVX5cSYyW5FAoyS9jWFBqhig8,54232
|
|
8
8
|
langchain_google_genai/embeddings.py,sha256=PBJlcRExfegD2V9hnKQHW99fJJGsbPbmMW1TfQtPmqU,10132
|
|
9
9
|
langchain_google_genai/genai_aqa.py,sha256=qB6h3-BSXqe0YLR3eeVllYzmNKK6ofI6xJLdBahUVZo,4300
|
|
10
10
|
langchain_google_genai/google_vector_store.py,sha256=4wvhIiOmc3Fo046FyafPmT9NBCLek-9bgluvuTfrbpQ,16148
|
|
11
|
-
langchain_google_genai/llms.py,sha256=
|
|
11
|
+
langchain_google_genai/llms.py,sha256=EPUgkz5aqKOyKbztT7br8w60Uo5D_X_bF5qP-zd6iLs,14593
|
|
12
12
|
langchain_google_genai/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
13
|
-
langchain_google_genai-2.0.
|
|
14
|
-
langchain_google_genai-2.0.
|
|
15
|
-
langchain_google_genai-2.0.
|
|
16
|
-
langchain_google_genai-2.0.
|
|
13
|
+
langchain_google_genai-2.0.5.dist-info/LICENSE,sha256=DppmdYJVSc1jd0aio6ptnMUn5tIHrdAhQ12SclEBfBg,1072
|
|
14
|
+
langchain_google_genai-2.0.5.dist-info/METADATA,sha256=mE8t2CijamvFdZk3CKWgZW5SNvaB2LU8rl9jO-7K_nU,3551
|
|
15
|
+
langchain_google_genai-2.0.5.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
|
|
16
|
+
langchain_google_genai-2.0.5.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|