langchain-google-genai 2.1.1__py3-none-any.whl → 2.1.2__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/_function_utils.py +54 -20
- langchain_google_genai/chat_models.py +123 -8
- {langchain_google_genai-2.1.1.dist-info → langchain_google_genai-2.1.2.dist-info}/METADATA +4 -4
- {langchain_google_genai-2.1.1.dist-info → langchain_google_genai-2.1.2.dist-info}/RECORD +6 -6
- {langchain_google_genai-2.1.1.dist-info → langchain_google_genai-2.1.2.dist-info}/LICENSE +0 -0
- {langchain_google_genai-2.1.1.dist-info → langchain_google_genai-2.1.2.dist-info}/WHEEL +0 -0
|
@@ -61,18 +61,22 @@ _ALLOWED_SCHEMA_FIELDS_SET = set(_ALLOWED_SCHEMA_FIELDS)
|
|
|
61
61
|
_FunctionDeclarationLike = Union[
|
|
62
62
|
BaseTool, Type[BaseModel], gapic.FunctionDeclaration, Callable, Dict[str, Any]
|
|
63
63
|
]
|
|
64
|
+
_GoogleSearchRetrievalLike = Union[
|
|
65
|
+
gapic.GoogleSearchRetrieval,
|
|
66
|
+
Dict[str, Any],
|
|
67
|
+
]
|
|
64
68
|
|
|
65
69
|
|
|
66
70
|
class _ToolDict(TypedDict):
|
|
67
71
|
function_declarations: Sequence[_FunctionDeclarationLike]
|
|
72
|
+
google_search_retrieval: Optional[_GoogleSearchRetrievalLike]
|
|
68
73
|
|
|
69
74
|
|
|
70
75
|
# Info: This means one tool=Sequence of FunctionDeclaration
|
|
71
76
|
# The dict should be gapic.Tool like. {"function_declarations": [ { "name": ...}.
|
|
72
77
|
# OpenAI like dict is not be accepted. {{'type': 'function', 'function': {'name': ...}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
]
|
|
78
|
+
_ToolType = Union[gapic.Tool, _ToolDict, _FunctionDeclarationLike]
|
|
79
|
+
_ToolsType = Sequence[_ToolType]
|
|
76
80
|
|
|
77
81
|
|
|
78
82
|
def _format_json_schema_to_gapic(schema: Dict[str, Any]) -> Dict[str, Any]:
|
|
@@ -122,7 +126,7 @@ def _format_dict_to_function_declaration(
|
|
|
122
126
|
|
|
123
127
|
# Info: gapic.Tool means function_declarations and proto.Message.
|
|
124
128
|
def convert_to_genai_function_declarations(
|
|
125
|
-
tools:
|
|
129
|
+
tools: _ToolsType,
|
|
126
130
|
) -> gapic.Tool:
|
|
127
131
|
if not isinstance(tools, collections.abc.Sequence):
|
|
128
132
|
logger.warning(
|
|
@@ -132,24 +136,54 @@ def convert_to_genai_function_declarations(
|
|
|
132
136
|
tools = [tools]
|
|
133
137
|
gapic_tool = gapic.Tool()
|
|
134
138
|
for tool in tools:
|
|
135
|
-
if
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
139
|
+
if any(f in gapic_tool for f in ["google_search_retrieval"]):
|
|
140
|
+
raise ValueError(
|
|
141
|
+
"Providing multiple google_search_retrieval"
|
|
142
|
+
" or mixing with function_declarations is not supported"
|
|
143
|
+
)
|
|
144
|
+
if isinstance(tool, (gapic.Tool)):
|
|
145
|
+
rt: gapic.Tool = (
|
|
146
|
+
tool if isinstance(tool, gapic.Tool) else tool._raw_tool # type: ignore
|
|
147
|
+
)
|
|
148
|
+
if "google_search_retrieval" in rt:
|
|
149
|
+
gapic_tool.google_search_retrieval = rt.google_search_retrieval
|
|
150
|
+
if "function_declarations" in rt:
|
|
151
|
+
gapic_tool.function_declarations.extend(rt.function_declarations)
|
|
152
|
+
if "google_search" in rt:
|
|
153
|
+
gapic_tool.google_search = rt.google_search
|
|
140
154
|
elif isinstance(tool, dict):
|
|
141
|
-
|
|
142
|
-
if not
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
if function_declarations:
|
|
148
|
-
fds = [
|
|
149
|
-
_format_to_gapic_function_declaration(fd)
|
|
150
|
-
for fd in function_declarations
|
|
155
|
+
# not _ToolDictLike
|
|
156
|
+
if not any(
|
|
157
|
+
f in tool
|
|
158
|
+
for f in [
|
|
159
|
+
"function_declarations",
|
|
160
|
+
"google_search_retrieval",
|
|
151
161
|
]
|
|
152
|
-
|
|
162
|
+
):
|
|
163
|
+
fd = _format_to_gapic_function_declaration(tool) # type: ignore[arg-type]
|
|
164
|
+
gapic_tool.function_declarations.append(fd)
|
|
165
|
+
continue
|
|
166
|
+
# _ToolDictLike
|
|
167
|
+
tool = cast(_ToolDict, tool)
|
|
168
|
+
if "function_declarations" in tool:
|
|
169
|
+
function_declarations = tool["function_declarations"]
|
|
170
|
+
if not isinstance(
|
|
171
|
+
tool["function_declarations"], collections.abc.Sequence
|
|
172
|
+
):
|
|
173
|
+
raise ValueError(
|
|
174
|
+
"function_declarations should be a list"
|
|
175
|
+
f"got '{type(function_declarations)}'"
|
|
176
|
+
)
|
|
177
|
+
if function_declarations:
|
|
178
|
+
fds = [
|
|
179
|
+
_format_to_gapic_function_declaration(fd)
|
|
180
|
+
for fd in function_declarations
|
|
181
|
+
]
|
|
182
|
+
gapic_tool.function_declarations.extend(fds)
|
|
183
|
+
if "google_search_retrieval" in tool:
|
|
184
|
+
gapic_tool.google_search_retrieval = gapic.GoogleSearchRetrieval(
|
|
185
|
+
tool["google_search_retrieval"]
|
|
186
|
+
)
|
|
153
187
|
else:
|
|
154
188
|
fd = _format_to_gapic_function_declaration(tool) # type: ignore[arg-type]
|
|
155
189
|
gapic_tool.function_declarations.append(fd)
|
|
@@ -32,6 +32,7 @@ from google.ai.generativelanguage_v1beta import (
|
|
|
32
32
|
from google.ai.generativelanguage_v1beta.types import (
|
|
33
33
|
Blob,
|
|
34
34
|
Candidate,
|
|
35
|
+
CodeExecution,
|
|
35
36
|
Content,
|
|
36
37
|
FileData,
|
|
37
38
|
FunctionCall,
|
|
@@ -45,9 +46,7 @@ from google.ai.generativelanguage_v1beta.types import (
|
|
|
45
46
|
ToolConfig,
|
|
46
47
|
VideoMetadata,
|
|
47
48
|
)
|
|
48
|
-
from google.ai.generativelanguage_v1beta.types import
|
|
49
|
-
Tool as GoogleTool,
|
|
50
|
-
)
|
|
49
|
+
from google.ai.generativelanguage_v1beta.types import Tool as GoogleTool
|
|
51
50
|
from langchain_core.callbacks.manager import (
|
|
52
51
|
AsyncCallbackManagerForLLMRun,
|
|
53
52
|
CallbackManagerForLLMRun,
|
|
@@ -72,7 +71,7 @@ from langchain_core.output_parsers.openai_tools import (
|
|
|
72
71
|
parse_tool_calls,
|
|
73
72
|
)
|
|
74
73
|
from langchain_core.outputs import ChatGeneration, ChatGenerationChunk, ChatResult
|
|
75
|
-
from langchain_core.runnables import Runnable, RunnablePassthrough
|
|
74
|
+
from langchain_core.runnables import Runnable, RunnableConfig, RunnablePassthrough
|
|
76
75
|
from langchain_core.tools import BaseTool
|
|
77
76
|
from langchain_core.utils.function_calling import convert_to_openai_tool
|
|
78
77
|
from pydantic import (
|
|
@@ -458,6 +457,41 @@ def _parse_response_candidate(
|
|
|
458
457
|
elif text:
|
|
459
458
|
raise Exception("Unexpected content type")
|
|
460
459
|
|
|
460
|
+
if hasattr(part, "executable_code") and part.executable_code is not None:
|
|
461
|
+
if part.executable_code.code and part.executable_code.language:
|
|
462
|
+
code_message = {
|
|
463
|
+
"type": "executable_code",
|
|
464
|
+
"executable_code": part.executable_code.code,
|
|
465
|
+
"language": part.executable_code.language,
|
|
466
|
+
}
|
|
467
|
+
if not content:
|
|
468
|
+
content = [code_message]
|
|
469
|
+
elif isinstance(content, str):
|
|
470
|
+
content = [content, code_message]
|
|
471
|
+
elif isinstance(content, list):
|
|
472
|
+
content.append(code_message)
|
|
473
|
+
else:
|
|
474
|
+
raise Exception("Unexpected content type")
|
|
475
|
+
|
|
476
|
+
if (
|
|
477
|
+
hasattr(part, "code_execution_result")
|
|
478
|
+
and part.code_execution_result is not None
|
|
479
|
+
):
|
|
480
|
+
if part.code_execution_result.output:
|
|
481
|
+
execution_result = {
|
|
482
|
+
"type": "code_execution_result",
|
|
483
|
+
"code_execution_result": part.code_execution_result.output,
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
if not content:
|
|
487
|
+
content = [execution_result]
|
|
488
|
+
elif isinstance(content, str):
|
|
489
|
+
content = [content, execution_result]
|
|
490
|
+
elif isinstance(content, list):
|
|
491
|
+
content.append(execution_result)
|
|
492
|
+
else:
|
|
493
|
+
raise Exception("Unexpected content type")
|
|
494
|
+
|
|
461
495
|
if part.inline_data.mime_type.startswith("image/"):
|
|
462
496
|
image_format = part.inline_data.mime_type[6:]
|
|
463
497
|
message = {
|
|
@@ -521,6 +555,16 @@ def _parse_response_candidate(
|
|
|
521
555
|
)
|
|
522
556
|
if content is None:
|
|
523
557
|
content = ""
|
|
558
|
+
if any(isinstance(item, dict) and "executable_code" in item for item in content):
|
|
559
|
+
warnings.warn(
|
|
560
|
+
"""
|
|
561
|
+
⚠️ Warning: Output may vary each run.
|
|
562
|
+
- 'executable_code': Always present.
|
|
563
|
+
- 'execution_result' & 'image_url': May be absent for some queries.
|
|
564
|
+
|
|
565
|
+
Validate before using in production.
|
|
566
|
+
"""
|
|
567
|
+
)
|
|
524
568
|
|
|
525
569
|
if streaming:
|
|
526
570
|
return AIMessageChunk(
|
|
@@ -575,6 +619,8 @@ def _response_to_result(
|
|
|
575
619
|
generation_info = {}
|
|
576
620
|
if candidate.finish_reason:
|
|
577
621
|
generation_info["finish_reason"] = candidate.finish_reason.name
|
|
622
|
+
# Add model_name in last chunk
|
|
623
|
+
generation_info["model_name"] = response.model_version
|
|
578
624
|
generation_info["safety_ratings"] = [
|
|
579
625
|
proto.Message.to_dict(safety_rating, use_integers_for_enums=False)
|
|
580
626
|
for safety_rating in candidate.safety_ratings
|
|
@@ -736,6 +782,16 @@ class ChatGoogleGenerativeAI(_BaseGoogleGenerativeAI, BaseChatModel):
|
|
|
736
782
|
'args': {'location': 'New York City, NY'},
|
|
737
783
|
'id': '634582de-5186-4e4b-968b-f192f0a93678'}]
|
|
738
784
|
|
|
785
|
+
Use Search with Gemini 2:
|
|
786
|
+
.. code-block:: python
|
|
787
|
+
|
|
788
|
+
from google.ai.generativelanguage_v1beta.types import Tool as GenAITool
|
|
789
|
+
llm = ChatGoogleGenerativeAI(model="gemini-2.0-flash-exp")
|
|
790
|
+
resp = llm.invoke(
|
|
791
|
+
"When is the next total solar eclipse in US?",
|
|
792
|
+
tools=[GenAITool(google_search={})],
|
|
793
|
+
)
|
|
794
|
+
|
|
739
795
|
Structured output:
|
|
740
796
|
.. code-block:: python
|
|
741
797
|
|
|
@@ -847,6 +903,14 @@ class ChatGoogleGenerativeAI(_BaseGoogleGenerativeAI, BaseChatModel):
|
|
|
847
903
|
def _llm_type(self) -> str:
|
|
848
904
|
return "chat-google-generative-ai"
|
|
849
905
|
|
|
906
|
+
@property
|
|
907
|
+
def _supports_code_execution(self) -> bool:
|
|
908
|
+
return (
|
|
909
|
+
"gemini-1.5-pro" in self.model
|
|
910
|
+
or "gemini-1.5-flash" in self.model
|
|
911
|
+
or "gemini-2" in self.model
|
|
912
|
+
)
|
|
913
|
+
|
|
850
914
|
@classmethod
|
|
851
915
|
def is_lc_serializable(self) -> bool:
|
|
852
916
|
return True
|
|
@@ -921,6 +985,42 @@ class ChatGoogleGenerativeAI(_BaseGoogleGenerativeAI, BaseChatModel):
|
|
|
921
985
|
"response_modalities": self.response_modalities,
|
|
922
986
|
}
|
|
923
987
|
|
|
988
|
+
def invoke(
|
|
989
|
+
self,
|
|
990
|
+
input: LanguageModelInput,
|
|
991
|
+
config: Optional[RunnableConfig] = None,
|
|
992
|
+
*,
|
|
993
|
+
code_execution: Optional[bool] = None,
|
|
994
|
+
stop: Optional[list[str]] = None,
|
|
995
|
+
**kwargs: Any,
|
|
996
|
+
) -> BaseMessage:
|
|
997
|
+
"""
|
|
998
|
+
Enable code execution. Supported on: gemini-1.5-pro, gemini-1.5-flash,
|
|
999
|
+
gemini-2.0-flash, and gemini-2.0-pro. When enabled, the model can execute
|
|
1000
|
+
code to solve problems.
|
|
1001
|
+
"""
|
|
1002
|
+
|
|
1003
|
+
"""Override invoke to add code_execution parameter."""
|
|
1004
|
+
|
|
1005
|
+
if code_execution is not None:
|
|
1006
|
+
if not self._supports_code_execution:
|
|
1007
|
+
raise ValueError(
|
|
1008
|
+
f"Code execution is only supported on Gemini 1.5 Pro, \
|
|
1009
|
+
Gemini 1.5 Flash, "
|
|
1010
|
+
f"Gemini 2.0 Flash, and Gemini 2.0 Pro models. \
|
|
1011
|
+
Current model: {self.model}"
|
|
1012
|
+
)
|
|
1013
|
+
if "tools" not in kwargs:
|
|
1014
|
+
code_execution_tool = GoogleTool(code_execution=CodeExecution())
|
|
1015
|
+
kwargs["tools"] = [code_execution_tool]
|
|
1016
|
+
|
|
1017
|
+
else:
|
|
1018
|
+
raise ValueError(
|
|
1019
|
+
"Tools are already defined." "code_execution tool can't be defined"
|
|
1020
|
+
)
|
|
1021
|
+
|
|
1022
|
+
return super().invoke(input, config, stop=stop, **kwargs)
|
|
1023
|
+
|
|
924
1024
|
def _get_ls_params(
|
|
925
1025
|
self, stop: Optional[List[str]] = None, **kwargs: Any
|
|
926
1026
|
) -> LangSmithParams:
|
|
@@ -1199,8 +1299,12 @@ class ChatGoogleGenerativeAI(_BaseGoogleGenerativeAI, BaseChatModel):
|
|
|
1199
1299
|
"Must specify at most one of tool_choice and tool_config, received "
|
|
1200
1300
|
f"both:\n\n{tool_choice=}\n\n{tool_config=}"
|
|
1201
1301
|
)
|
|
1302
|
+
|
|
1202
1303
|
formatted_tools = None
|
|
1203
|
-
|
|
1304
|
+
code_execution_tool = GoogleTool(code_execution=CodeExecution())
|
|
1305
|
+
if tools == [code_execution_tool]:
|
|
1306
|
+
formatted_tools = tools
|
|
1307
|
+
elif tools:
|
|
1204
1308
|
formatted_tools = [convert_to_genai_function_declarations(tools)]
|
|
1205
1309
|
elif functions:
|
|
1206
1310
|
formatted_tools = [convert_to_genai_function_declarations(functions)]
|
|
@@ -1226,9 +1330,20 @@ class ChatGoogleGenerativeAI(_BaseGoogleGenerativeAI, BaseChatModel):
|
|
|
1226
1330
|
f"be specified if 'tools' is specified."
|
|
1227
1331
|
)
|
|
1228
1332
|
raise ValueError(msg)
|
|
1229
|
-
all_names = [
|
|
1230
|
-
|
|
1231
|
-
|
|
1333
|
+
all_names: List[str] = []
|
|
1334
|
+
for t in formatted_tools:
|
|
1335
|
+
if hasattr(t, "function_declarations"):
|
|
1336
|
+
t_with_declarations = cast(Any, t)
|
|
1337
|
+
all_names.extend(
|
|
1338
|
+
f.name for f in t_with_declarations.function_declarations
|
|
1339
|
+
)
|
|
1340
|
+
elif isinstance(t, GoogleTool) and hasattr(t, "code_execution"):
|
|
1341
|
+
continue
|
|
1342
|
+
else:
|
|
1343
|
+
raise TypeError(
|
|
1344
|
+
f"Tool {t} doesn't have function_declarations attribute"
|
|
1345
|
+
)
|
|
1346
|
+
|
|
1232
1347
|
tool_config = _tool_choice_to_tool_config(tool_choice, all_names)
|
|
1233
1348
|
|
|
1234
1349
|
formatted_tool_config = None
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: langchain-google-genai
|
|
3
|
-
Version: 2.1.
|
|
3
|
+
Version: 2.1.2
|
|
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
|
|
@@ -13,7 +13,7 @@ Classifier: Programming Language :: Python :: 3.11
|
|
|
13
13
|
Classifier: Programming Language :: Python :: 3.12
|
|
14
14
|
Requires-Dist: filetype (>=1.2.0,<2.0.0)
|
|
15
15
|
Requires-Dist: google-ai-generativelanguage (>=0.6.16,<0.7.0)
|
|
16
|
-
Requires-Dist: langchain-core (>=0.3.
|
|
16
|
+
Requires-Dist: langchain-core (>=0.3.49,<0.4.0)
|
|
17
17
|
Requires-Dist: pydantic (>=2,<3)
|
|
18
18
|
Project-URL: Repository, https://github.com/langchain-ai/langchain-google
|
|
19
19
|
Project-URL: Source Code, https://github.com/langchain-ai/langchain-google/tree/main/libs/genai
|
|
@@ -98,7 +98,7 @@ meow_str = response.content[1]
|
|
|
98
98
|
|
|
99
99
|
#### Multimodal Outputs in Chains
|
|
100
100
|
|
|
101
|
-
|
|
101
|
+
```
|
|
102
102
|
from langchain_core.runnables import RunnablePassthrough
|
|
103
103
|
from langchain_core.prompts import ChatPromptTemplate
|
|
104
104
|
|
|
@@ -114,7 +114,7 @@ prompt = ChatPromptTemplate(
|
|
|
114
114
|
)
|
|
115
115
|
chain = {"animal": RunnablePassthrough()} | prompt | llm
|
|
116
116
|
res = chain.invoke("cat")
|
|
117
|
-
|
|
117
|
+
```
|
|
118
118
|
|
|
119
119
|
## Embeddings
|
|
120
120
|
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
langchain_google_genai/__init__.py,sha256=IsTvA3UcECLDckt3zWxK6u-n3MEa5KeEQpqsS-Z8shM,2784
|
|
2
2
|
langchain_google_genai/_common.py,sha256=RS_FN1k9BeeSRz8HuPyjh_lfDQPZKY6KdvK5EfVuxDw,5431
|
|
3
3
|
langchain_google_genai/_enums.py,sha256=Zj3BXXLlkm_UybegCi6fLsfFhriJCt_LAJvgatgPWQ0,252
|
|
4
|
-
langchain_google_genai/_function_utils.py,sha256=
|
|
4
|
+
langchain_google_genai/_function_utils.py,sha256=lvHunWWsSU0RmAal4rVpgm2JucCnKUq21Uc0eqFY49c,19115
|
|
5
5
|
langchain_google_genai/_genai_extension.py,sha256=81a4ly5ZHlqMf37uJfdB8K41qE6J5ujLnbUypIfFf2o,20775
|
|
6
6
|
langchain_google_genai/_image_utils.py,sha256=tPrQyMvVmO8xkuow1SvA91omxUEv9ZUy1EMHNGjMAKY,5202
|
|
7
|
-
langchain_google_genai/chat_models.py,sha256=
|
|
7
|
+
langchain_google_genai/chat_models.py,sha256=PTWraSNiYBQJ-ev9R2OoWcu7cruBeS8JfRdUl2ydXZU,57944
|
|
8
8
|
langchain_google_genai/embeddings.py,sha256=jQRWPXD9twXoVBlXJQG7Duz0fb8UC0kgRzzwAmW3Dic,10146
|
|
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
11
|
langchain_google_genai/llms.py,sha256=QNPitkORf86w8WQpTbjuPFCQFkB-qKRMW2phhRBwAEA,4318
|
|
12
12
|
langchain_google_genai/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
13
|
-
langchain_google_genai-2.1.
|
|
14
|
-
langchain_google_genai-2.1.
|
|
15
|
-
langchain_google_genai-2.1.
|
|
16
|
-
langchain_google_genai-2.1.
|
|
13
|
+
langchain_google_genai-2.1.2.dist-info/LICENSE,sha256=DppmdYJVSc1jd0aio6ptnMUn5tIHrdAhQ12SclEBfBg,1072
|
|
14
|
+
langchain_google_genai-2.1.2.dist-info/METADATA,sha256=go98GAJH_sz8QSo18j1vrEw8guoNw_xOF_-iPCutwd4,4728
|
|
15
|
+
langchain_google_genai-2.1.2.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
|
|
16
|
+
langchain_google_genai-2.1.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|