|
114 | 114 | from google.cloud.aiplatform_v1beta1.types import ( |
115 | 115 | Blob, |
116 | 116 | Candidate, |
| 117 | + CodeExecutionResult, |
117 | 118 | Part, |
118 | 119 | HarmCategory, |
119 | 120 | Content, |
| 121 | + ExecutableCode, |
120 | 122 | FileData, |
121 | 123 | FunctionCall, |
122 | 124 | FunctionResponse, |
@@ -242,6 +244,29 @@ def _convert_to_prompt(part: Union[str, Dict]) -> Optional[Part]: |
242 | 244 | return Part(text=part["text"]) |
243 | 245 | else: |
244 | 246 | return None |
| 247 | + if part["type"] == "executable_code": |
| 248 | + if "executable_code" not in part or "language" not in part: |
| 249 | + raise ValueError( |
| 250 | + "Executable code part must have 'code' and 'language' keys, got " |
| 251 | + f"{part}" |
| 252 | + ) |
| 253 | + return Part( |
| 254 | + executable_code=ExecutableCode( |
| 255 | + language=part["language"], code=part["executable_code"] |
| 256 | + ) |
| 257 | + ) |
| 258 | + if part["type"] == "code_execution_result": |
| 259 | + if "code_execution_result" not in part or "outcome" not in part: |
| 260 | + raise ValueError( |
| 261 | + "Code execution result part must have 'code_execution_result' and " |
| 262 | + f"'outcome' keys, got {part}" |
| 263 | + ) |
| 264 | + return Part( |
| 265 | + code_execution_result=CodeExecutionResult( |
| 266 | + output=part["code_execution_result"], outcome=part["outcome"] |
| 267 | + ) |
| 268 | + ) |
| 269 | + |
245 | 270 | if is_data_content_block(part): |
246 | 271 | # LangChain standard format |
247 | 272 | if part["type"] == "image" and part["source_type"] == "url": |
@@ -542,7 +567,7 @@ def _parse_response_candidate( |
542 | 567 | def _parse_response_candidate( |
543 | 568 | response_candidate: "Candidate", streaming: bool = False |
544 | 569 | ) -> AIMessage: |
545 | | - content: Union[None, str, List[str]] = None |
| 570 | + content: Union[None, str, List[Union[str, dict[str, Any]]]] = None |
546 | 571 | additional_kwargs = {} |
547 | 572 | tool_calls = [] |
548 | 573 | invalid_tool_calls = [] |
@@ -610,6 +635,44 @@ def _parse_response_candidate( |
610 | 635 | error=str(e), |
611 | 636 | ) |
612 | 637 | ) |
| 638 | + if hasattr(part, "executable_code") and part.executable_code is not None: |
| 639 | + if part.executable_code.code and part.executable_code.language: |
| 640 | + code_message = { |
| 641 | + "type": "executable_code", |
| 642 | + "executable_code": part.executable_code.code, |
| 643 | + "language": part.executable_code.language, |
| 644 | + } |
| 645 | + if not content: |
| 646 | + content = [code_message] |
| 647 | + elif isinstance(content, str): |
| 648 | + content = [content, code_message] |
| 649 | + elif isinstance(content, list): |
| 650 | + content.append(code_message) |
| 651 | + else: |
| 652 | + raise Exception("Unexpected content type") |
| 653 | + |
| 654 | + if ( |
| 655 | + hasattr(part, "code_execution_result") |
| 656 | + and part.code_execution_result is not None |
| 657 | + ): |
| 658 | + if part.code_execution_result.output and part.code_execution_result.outcome: |
| 659 | + execution_result = { |
| 660 | + "type": "code_execution_result", |
| 661 | + # Name output -> code_execution_result for consistency with |
| 662 | + # langchain-google-genai |
| 663 | + "code_execution_result": part.code_execution_result.output, |
| 664 | + "outcome": part.code_execution_result.outcome, |
| 665 | + } |
| 666 | + |
| 667 | + if not content: |
| 668 | + content = [execution_result] |
| 669 | + elif isinstance(content, str): |
| 670 | + content = [content, execution_result] |
| 671 | + elif isinstance(content, list): |
| 672 | + content.append(execution_result) |
| 673 | + else: |
| 674 | + raise Exception("Unexpected content type") |
| 675 | + |
613 | 676 | if content is None: |
614 | 677 | content = "" |
615 | 678 |
|
@@ -896,16 +959,30 @@ class GetPopulation(BaseModel): |
896 | 959 |
|
897 | 960 | See ``ChatVertexAI.bind_tools()`` method for more. |
898 | 961 |
|
899 | | - Use Search with Gemini 2: |
| 962 | + Built-in search: |
900 | 963 | .. code-block:: python |
901 | 964 |
|
902 | 965 | from google.cloud.aiplatform_v1beta1.types import Tool as VertexTool |
| 966 | + from langchain_google_vertexai import ChatVertexAI |
| 967 | +
|
903 | 968 | llm = ChatVertexAI(model="gemini-2.0-flash-exp") |
904 | 969 | resp = llm.invoke( |
905 | 970 | "When is the next total solar eclipse in US?", |
906 | 971 | tools=[VertexTool(google_search={})], |
907 | 972 | ) |
908 | 973 |
|
| 974 | + Built-in code execution: |
| 975 | + .. code-block:: python |
| 976 | +
|
| 977 | + from google.cloud.aiplatform_v1beta1.types import Tool as VertexTool |
| 978 | + from langchain_google_vertexai import ChatVertexAI |
| 979 | +
|
| 980 | + llm = ChatVertexAI(model="gemini-2.0-flash-exp") |
| 981 | + resp = llm.invoke( |
| 982 | + "What is 3^3?", |
| 983 | + tools=[VertexTool(code_execution={})], |
| 984 | + ) |
| 985 | +
|
909 | 986 | Structured output: |
910 | 987 | .. code-block:: python |
911 | 988 |
|
|
0 commit comments