langchain-ai / langchain-google

MIT License
74 stars 78 forks source link

Support for handling multiple/parallel function call responses with create_tool_calling_agent #275

Closed yeesian closed 3 weeks ago

yeesian commented 4 weeks ago

Currently the following code

!pip3 install --upgrade --quiet \
    google-cloud-aiplatform==1.53.0 \
    langchain==0.2.2 \
    langchain-google-vertexai==1.0.4 \
    cloudpickle==3.0.0 \
    requests

from langchain.tools import tool

@tool
def call_product_details(product_id: str, store_id: str, store_zip:str):
    """Provide all information about a product except delivery"""
    return """{"data":{"product":"brandName":"brand_name",{"specName":"Product Depth (in.)","specValue":"3.8 in","__typename":"Specification"},{"specName":"Product Height (in.)","specValue":"12.2 in","__typename":"Specification"},{"specName":"Product Size","specValue":"1","__typename":"Specification"},{"specName":"Product Width (in.)","specValue":"7.4 in","__typename":"Specification"}]}}}"""

@tool
def call_fulfillment(product_id: str, store_zip: str, store_id: str):
    """Get Fulfillment information about a product including shipping or delivery."""
    return """{"data":{"product":{"deliveryTimeline":"today","deliveryDates":{"startDate":"2024-05-06","endDate":"2024-05-06","__typename":"DeliveryDate"},"inventory":{"isOutOfStock":false,"isInStock":true}}"""

from langchain import agents
from langchain_google_vertexai import ChatVertexAI
from langchain_core.prompts import ChatPromptTemplate

model = "gemini-1.5-pro-001"
llm = ChatVertexAI(
    model_name=model,
    project="model-extend-test",
    max_tokens=500,
    temperature=0.5,
)

tools = [call_product_details, call_fulfillment]

prompt = ChatPromptTemplate.from_messages(
    [
        ("human", "{input}"),
        ("placeholder", "{agent_scratchpad}"),])

agent = agents.create_tool_calling_agent(
    llm,
    tools,
    prompt
)
agent_executor = agents.AgentExecutor(agent=agent, tools=tools, verbose=True)
agent_executor.invoke({
    "input": 'use multiple tools. what is the brand and when can i get this delivered? {"product_id": "432890", "store_id": "0123", "store_zip": "1234"}'
})

has been failing with the following error message:

> Entering new AgentExecutor chain...
WARNING:langchain_google_vertexai.chat_models:This model can reply with multiple function calls in one response. Please don't rely on `additional_kwargs.function_call` as only the last one will be saved.Use `tool_calls` instead.
WARNING:langchain_core.language_models.llms:Retrying langchain_google_vertexai.chat_models._completion_with_retry.<locals>._completion_with_retry_inner in 4.0 seconds as it raised InvalidArgument: 400 Request contains an invalid argument..

Invoking: `call_product_details` with `{'store_zip': '1234', 'store_id': '0123', 'product_id': '432890'}`

{"data":{"product":"brandName":"brand_name",{"specName":"Product Depth (in.)","specValue":"3.8 in","__typename":"Specification"},{"specName":"Product Height (in.)","specValue":"12.2 in","__typename":"Specification"},{"specName":"Product Size","specValue":"1","__typename":"Specification"},{"specName":"Product Width (in.)","specValue":"7.4 in","__typename":"Specification"}]}}}
Invoking: `call_fulfillment` with `{'product_id': '432890', 'store_id': '0123', 'store_zip': '1234'}`

{"data":{"product":{"deliveryTimeline":"today","deliveryDates":{"startDate":"2024-05-06","endDate":"2024-05-06","__typename":"DeliveryDate"},"inventory":{"isOutOfStock":false,"isInStock":true}}WARNING:langchain_core.language_models.llms:Retrying langchain_google_vertexai.chat_models._completion_with_retry.<locals>._completion_with_retry_inner in 4.0 seconds as it raised InvalidArgument: 400 Request contains an invalid argument..
WARNING:langchain_core.language_models.llms:Retrying langchain_google_vertexai.chat_models._completion_with_retry.<locals>._completion_with_retry_inner in 4.0 seconds as it raised InvalidArgument: 400 Request contains an invalid argument..
WARNING:langchain_core.language_models.llms:Retrying langchain_google_vertexai.chat_models._completion_with_retry.<locals>._completion_with_retry_inner in 8.0 seconds as it raised InvalidArgument: 400 Request contains an invalid argument..
WARNING:langchain_core.language_models.llms:Retrying langchain_google_vertexai.chat_models._completion_with_retry.<locals>._completion_with_retry_inner in 10.0 seconds as it raised InvalidArgument: 400 Request contains an invalid argument..
---------------------------------------------------------------------------
_MultiThreadedRendezvous                  Traceback (most recent call last)
[/usr/local/lib/python3.10/dist-packages/google/api_core/grpc_helpers.py](https://localhost:8080/#) in error_remapped_callable(*args, **kwargs)
    161             prefetch_first = getattr(callable_, "_prefetch_first_result_", True)
--> 162             return _StreamingResponseIterator(
    163                 result, prefetch_first_result=prefetch_first

34 frames
[/usr/local/lib/python3.10/dist-packages/google/api_core/grpc_helpers.py](https://localhost:8080/#) in __init__(self, wrapped, prefetch_first_result)
     87             if prefetch_first_result:
---> 88                 self._stored_first_result = next(self._wrapped)
     89         except TypeError:

[/usr/local/lib/python3.10/dist-packages/grpc/_channel.py](https://localhost:8080/#) in __next__(self)
    542     def __next__(self):
--> 543         return self._next()
    544 

[/usr/local/lib/python3.10/dist-packages/grpc/_channel.py](https://localhost:8080/#) in _next(self)
    968                 elif self._state.code is not None:
--> 969                     raise self
    970 

_MultiThreadedRendezvous: <_MultiThreadedRendezvous of RPC that terminated with:
    status = StatusCode.INVALID_ARGUMENT
    details = "Request contains an invalid argument."
    debug_error_string = "UNKNOWN:Error received from peer ipv4:173.194.213.95:443 {grpc_message:"Request contains an invalid argument.", grpc_status:3, created_time:"2024-06-04T23:27:37.44187111+00:00"}"
>

The above exception was the direct cause of the following exception:

InvalidArgument                           Traceback (most recent call last)
[<ipython-input-5-715a9eadcc2e>](https://localhost:8080/#) in <cell line: 1>()
----> 1 agent_executor.invoke({
      2     "input": 'use multiple tools. what is the brand and when can i get this delivered? {"product_id": "432890", "store_id": "0123", "store_zip": "1234"}'
      3 })

[/usr/local/lib/python3.10/dist-packages/langchain/chains/base.py](https://localhost:8080/#) in invoke(self, input, config, **kwargs)
    164         except BaseException as e:
    165             run_manager.on_chain_error(e)
--> 166             raise e
    167         run_manager.on_chain_end(outputs)
    168 

[/usr/local/lib/python3.10/dist-packages/langchain/chains/base.py](https://localhost:8080/#) in invoke(self, input, config, **kwargs)
    154             self._validate_inputs(inputs)
    155             outputs = (
--> 156                 self._call(inputs, run_manager=run_manager)
    157                 if new_arg_supported
    158                 else self._call(inputs)

[/usr/local/lib/python3.10/dist-packages/langchain/agents/agent.py](https://localhost:8080/#) in _call(self, inputs, run_manager)
   1431         # We now enter the agent loop (until it returns something).
   1432         while self._should_continue(iterations, time_elapsed):
-> 1433             next_step_output = self._take_next_step(
   1434                 name_to_tool_map,
   1435                 color_mapping,

[/usr/local/lib/python3.10/dist-packages/langchain/agents/agent.py](https://localhost:8080/#) in _take_next_step(self, name_to_tool_map, color_mapping, inputs, intermediate_steps, run_manager)
   1137     ) -> Union[AgentFinish, List[Tuple[AgentAction, str]]]:
   1138         return self._consume_next_step(
-> 1139             [
   1140                 a
   1141                 for a in self._iter_next_step(

[/usr/local/lib/python3.10/dist-packages/langchain/agents/agent.py](https://localhost:8080/#) in <listcomp>(.0)
   1137     ) -> Union[AgentFinish, List[Tuple[AgentAction, str]]]:
   1138         return self._consume_next_step(
-> 1139             [
   1140                 a
   1141                 for a in self._iter_next_step(

[/usr/local/lib/python3.10/dist-packages/langchain/agents/agent.py](https://localhost:8080/#) in _iter_next_step(self, name_to_tool_map, color_mapping, inputs, intermediate_steps, run_manager)
   1165 
   1166             # Call the LLM to see what to do.
-> 1167             output = self.agent.plan(
   1168                 intermediate_steps,
   1169                 callbacks=run_manager.get_child() if run_manager else None,

[/usr/local/lib/python3.10/dist-packages/langchain/agents/agent.py](https://localhost:8080/#) in plan(self, intermediate_steps, callbacks, **kwargs)
    513             # Because the response from the plan is not a generator, we need to
    514             # accumulate the output into final output and return that.
--> 515             for chunk in self.runnable.stream(inputs, config={"callbacks": callbacks}):
    516                 if final_output is None:
    517                     final_output = chunk

[/usr/local/lib/python3.10/dist-packages/langchain_core/runnables/base.py](https://localhost:8080/#) in stream(self, input, config, **kwargs)
   2784         **kwargs: Optional[Any],
   2785     ) -> Iterator[Output]:
-> 2786         yield from self.transform(iter([input]), config, **kwargs)
   2787 
   2788     async def atransform(

[/usr/local/lib/python3.10/dist-packages/langchain_core/runnables/base.py](https://localhost:8080/#) in transform(self, input, config, **kwargs)
   2771         **kwargs: Optional[Any],
   2772     ) -> Iterator[Output]:
-> 2773         yield from self._transform_stream_with_config(
   2774             input,
   2775             self._transform,

[/usr/local/lib/python3.10/dist-packages/langchain_core/runnables/base.py](https://localhost:8080/#) in _transform_stream_with_config(self, input, transformer, config, run_type, **kwargs)
   1776             try:
   1777                 while True:
-> 1778                     chunk: Output = context.run(next, iterator)  # type: ignore
   1779                     yield chunk
   1780                     if final_output_supported:

[/usr/local/lib/python3.10/dist-packages/langchain_core/runnables/base.py](https://localhost:8080/#) in _transform(self, input, run_manager, config, **kwargs)
   2733                 final_pipeline = step.transform(final_pipeline, config)
   2734 
-> 2735         for output in final_pipeline:
   2736             yield output
   2737 

[/usr/local/lib/python3.10/dist-packages/langchain_core/runnables/base.py](https://localhost:8080/#) in transform(self, input, config, **kwargs)
   1152         got_first_val = False
   1153 
-> 1154         for ichunk in input:
   1155             # The default implementation of transform is to buffer input and
   1156             # then call stream.

[/usr/local/lib/python3.10/dist-packages/langchain_core/runnables/base.py](https://localhost:8080/#) in transform(self, input, config, **kwargs)
   4653         **kwargs: Any,
   4654     ) -> Iterator[Output]:
-> 4655         yield from self.bound.transform(
   4656             input,
   4657             self._merge_configs(config),

[/usr/local/lib/python3.10/dist-packages/langchain_core/runnables/base.py](https://localhost:8080/#) in transform(self, input, config, **kwargs)
   1170 
   1171         if got_first_val:
-> 1172             yield from self.stream(final, config, **kwargs)
   1173 
   1174     async def atransform(

[/usr/local/lib/python3.10/dist-packages/langchain_core/language_models/chat_models.py](https://localhost:8080/#) in stream(self, input, config, stop, **kwargs)
    263                     ),
    264                 )
--> 265                 raise e
    266             else:
    267                 run_manager.on_llm_end(LLMResult(generations=[[generation]]))

[/usr/local/lib/python3.10/dist-packages/langchain_core/language_models/chat_models.py](https://localhost:8080/#) in stream(self, input, config, stop, **kwargs)
    243             generation: Optional[ChatGenerationChunk] = None
    244             try:
--> 245                 for chunk in self._stream(messages, stop=stop, **kwargs):
    246                     if chunk.message.id is None:
    247                         chunk.message.id = f"run-{run_manager.run_id}"

[/usr/local/lib/python3.10/dist-packages/langchain_google_vertexai/chat_models.py](https://localhost:8080/#) in _stream(self, messages, stop, run_manager, **kwargs)
    919             )
    920             return
--> 921         yield from self._stream_gemini(
    922             messages=messages, stop=stop, run_manager=run_manager, **kwargs
    923         )

[/usr/local/lib/python3.10/dist-packages/langchain_google_vertexai/chat_models.py](https://localhost:8080/#) in _stream_gemini(self, messages, stop, run_manager, **kwargs)
    932     ) -> Iterator[ChatGenerationChunk]:
    933         request = self._prepare_request_gemini(messages=messages, stop=stop, **kwargs)
--> 934         response_iter = _completion_with_retry(
    935             self.prediction_client.stream_generate_content,
    936             max_retries=self.max_retries,

[/usr/local/lib/python3.10/dist-packages/langchain_google_vertexai/chat_models.py](https://localhost:8080/#) in _completion_with_retry(generation_method, max_retries, run_manager, **kwargs)
    494         else kwargs
    495     )
--> 496     return _completion_with_retry_inner(
    497         generation_method,
    498         **params,

[/usr/local/lib/python3.10/dist-packages/tenacity/__init__.py](https://localhost:8080/#) in wrapped_f(*args, **kw)
    328         )
    329         def wrapped_f(*args: t.Any, **kw: t.Any) -> t.Any:
--> 330             return self(f, *args, **kw)
    331 
    332         def retry_with(*args: t.Any, **kwargs: t.Any) -> WrappedFn:

[/usr/local/lib/python3.10/dist-packages/tenacity/__init__.py](https://localhost:8080/#) in __call__(self, fn, *args, **kwargs)
    465         retry_state = RetryCallState(retry_object=self, fn=fn, args=args, kwargs=kwargs)
    466         while True:
--> 467             do = self.iter(retry_state=retry_state)
    468             if isinstance(do, DoAttempt):
    469                 try:

[/usr/local/lib/python3.10/dist-packages/tenacity/__init__.py](https://localhost:8080/#) in iter(self, retry_state)
    366         result = None
    367         for action in self.iter_state.actions:
--> 368             result = action(retry_state)
    369         return result
    370 

[/usr/local/lib/python3.10/dist-packages/tenacity/__init__.py](https://localhost:8080/#) in exc_check(rs)
    408                 retry_exc = self.retry_error_cls(fut)
    409                 if self.reraise:
--> 410                     raise retry_exc.reraise()
    411                 raise retry_exc from fut.exception()
    412 

[/usr/local/lib/python3.10/dist-packages/tenacity/__init__.py](https://localhost:8080/#) in reraise(self)
    181     def reraise(self) -> t.NoReturn:
    182         if self.last_attempt.failed:
--> 183             raise self.last_attempt.result()
    184         raise self
    185 

[/usr/lib/python3.10/concurrent/futures/_base.py](https://localhost:8080/#) in result(self, timeout)
    449                     raise CancelledError()
    450                 elif self._state == FINISHED:
--> 451                     return self.__get_result()
    452 
    453                 self._condition.wait(timeout)

[/usr/lib/python3.10/concurrent/futures/_base.py](https://localhost:8080/#) in __get_result(self)
    401         if self._exception:
    402             try:
--> 403                 raise self._exception
    404             finally:
    405                 # Break a reference cycle with the exception in self._exception

[/usr/local/lib/python3.10/dist-packages/tenacity/__init__.py](https://localhost:8080/#) in __call__(self, fn, *args, **kwargs)
    468             if isinstance(do, DoAttempt):
    469                 try:
--> 470                     result = fn(*args, **kwargs)
    471                 except BaseException:  # noqa: B902
    472                     retry_state.set_exception(sys.exc_info())  # type: ignore[arg-type]

[/usr/local/lib/python3.10/dist-packages/langchain_google_vertexai/chat_models.py](https://localhost:8080/#) in _completion_with_retry_inner(generation_method, **kwargs)
    487     @retry_decorator
    488     def _completion_with_retry_inner(generation_method: Callable, **kwargs: Any) -> Any:
--> 489         return generation_method(**kwargs)
    490 
    491     params = (

[/usr/local/lib/python3.10/dist-packages/google/cloud/aiplatform_v1beta1/services/prediction_service/client.py](https://localhost:8080/#) in stream_generate_content(self, request, model, contents, retry, timeout, metadata)
   2248 
   2249         # Send the request.
-> 2250         response = rpc(
   2251             request,
   2252             retry=retry,

[/usr/local/lib/python3.10/dist-packages/google/api_core/gapic_v1/method.py](https://localhost:8080/#) in __call__(self, timeout, retry, *args, **kwargs)
    111             kwargs["metadata"] = metadata
    112 
--> 113         return wrapped_func(*args, **kwargs)
    114 
    115 

[/usr/local/lib/python3.10/dist-packages/google/api_core/grpc_helpers.py](https://localhost:8080/#) in error_remapped_callable(*args, **kwargs)
    164             )
    165         except grpc.RpcError as exc:
--> 166             raise exceptions.from_grpc_error(exc) from exc
    167 
    168     return error_remapped_callable

InvalidArgument: 400 Request contains an invalid argument.---------------------------------------------------------------------------
_MultiThreadedRendezvous                  Traceback (most recent call last)
[/usr/local/lib/python3.10/dist-packages/google/api_core/grpc_helpers.py](https://localhost:8080/#) in error_remapped_callable(*args, **kwargs)
    161             prefetch_first = getattr(callable_, "_prefetch_first_result_", True)
--> 162             return _StreamingResponseIterator(
    163                 result, prefetch_first_result=prefetch_first

34 frames
[/usr/local/lib/python3.10/dist-packages/google/api_core/grpc_helpers.py](https://localhost:8080/#) in __init__(self, wrapped, prefetch_first_result)
     87             if prefetch_first_result:
---> 88                 self._stored_first_result = next(self._wrapped)
     89         except TypeError:

[/usr/local/lib/python3.10/dist-packages/grpc/_channel.py](https://localhost:8080/#) in __next__(self)
    542     def __next__(self):
--> 543         return self._next()
    544 

[/usr/local/lib/python3.10/dist-packages/grpc/_channel.py](https://localhost:8080/#) in _next(self)
    968                 elif self._state.code is not None:
--> 969                     raise self
    970 

_MultiThreadedRendezvous: <_MultiThreadedRendezvous of RPC that terminated with:
    status = StatusCode.INVALID_ARGUMENT
    details = "Request contains an invalid argument."
    debug_error_string = "UNKNOWN:Error received from peer ipv4:173.194.213.95:443 {grpc_message:"Request contains an invalid argument.", grpc_status:3, created_time:"2024-06-04T23:27:37.44187111+00:00"}"
>

The above exception was the direct cause of the following exception:

InvalidArgument                           Traceback (most recent call last)
[<ipython-input-5-715a9eadcc2e>](https://localhost:8080/#) in <cell line: 1>()
----> 1 agent_executor.invoke({
      2     "input": 'use multiple tools. what is the brand and when can i get this delivered? {"product_id": "432890", "store_id": "0123", "store_zip": "1234"}'
      3 })

[/usr/local/lib/python3.10/dist-packages/langchain/chains/base.py](https://localhost:8080/#) in invoke(self, input, config, **kwargs)
    164         except BaseException as e:
    165             run_manager.on_chain_error(e)
--> 166             raise e
    167         run_manager.on_chain_end(outputs)
    168 

[/usr/local/lib/python3.10/dist-packages/langchain/chains/base.py](https://localhost:8080/#) in invoke(self, input, config, **kwargs)
    154             self._validate_inputs(inputs)
    155             outputs = (
--> 156                 self._call(inputs, run_manager=run_manager)
    157                 if new_arg_supported
    158                 else self._call(inputs)

[/usr/local/lib/python3.10/dist-packages/langchain/agents/agent.py](https://localhost:8080/#) in _call(self, inputs, run_manager)
   1431         # We now enter the agent loop (until it returns something).
   1432         while self._should_continue(iterations, time_elapsed):
-> 1433             next_step_output = self._take_next_step(
   1434                 name_to_tool_map,
   1435                 color_mapping,

[/usr/local/lib/python3.10/dist-packages/langchain/agents/agent.py](https://localhost:8080/#) in _take_next_step(self, name_to_tool_map, color_mapping, inputs, intermediate_steps, run_manager)
   1137     ) -> Union[AgentFinish, List[Tuple[AgentAction, str]]]:
   1138         return self._consume_next_step(
-> 1139             [
   1140                 a
   1141                 for a in self._iter_next_step(

[/usr/local/lib/python3.10/dist-packages/langchain/agents/agent.py](https://localhost:8080/#) in <listcomp>(.0)
   1137     ) -> Union[AgentFinish, List[Tuple[AgentAction, str]]]:
   1138         return self._consume_next_step(
-> 1139             [
   1140                 a
   1141                 for a in self._iter_next_step(

[/usr/local/lib/python3.10/dist-packages/langchain/agents/agent.py](https://localhost:8080/#) in _iter_next_step(self, name_to_tool_map, color_mapping, inputs, intermediate_steps, run_manager)
   1165 
   1166             # Call the LLM to see what to do.
-> 1167             output = self.agent.plan(
   1168                 intermediate_steps,
   1169                 callbacks=run_manager.get_child() if run_manager else None,

[/usr/local/lib/python3.10/dist-packages/langchain/agents/agent.py](https://localhost:8080/#) in plan(self, intermediate_steps, callbacks, **kwargs)
    513             # Because the response from the plan is not a generator, we need to
    514             # accumulate the output into final output and return that.
--> 515             for chunk in self.runnable.stream(inputs, config={"callbacks": callbacks}):
    516                 if final_output is None:
    517                     final_output = chunk

[/usr/local/lib/python3.10/dist-packages/langchain_core/runnables/base.py](https://localhost:8080/#) in stream(self, input, config, **kwargs)
   2784         **kwargs: Optional[Any],
   2785     ) -> Iterator[Output]:
-> 2786         yield from self.transform(iter([input]), config, **kwargs)
   2787 
   2788     async def atransform(

[/usr/local/lib/python3.10/dist-packages/langchain_core/runnables/base.py](https://localhost:8080/#) in transform(self, input, config, **kwargs)
   2771         **kwargs: Optional[Any],
   2772     ) -> Iterator[Output]:
-> 2773         yield from self._transform_stream_with_config(
   2774             input,
   2775             self._transform,

[/usr/local/lib/python3.10/dist-packages/langchain_core/runnables/base.py](https://localhost:8080/#) in _transform_stream_with_config(self, input, transformer, config, run_type, **kwargs)
   1776             try:
   1777                 while True:
-> 1778                     chunk: Output = context.run(next, iterator)  # type: ignore
   1779                     yield chunk
   1780                     if final_output_supported:

[/usr/local/lib/python3.10/dist-packages/langchain_core/runnables/base.py](https://localhost:8080/#) in _transform(self, input, run_manager, config, **kwargs)
   2733                 final_pipeline = step.transform(final_pipeline, config)
   2734 
-> 2735         for output in final_pipeline:
   2736             yield output
   2737 

[/usr/local/lib/python3.10/dist-packages/langchain_core/runnables/base.py](https://localhost:8080/#) in transform(self, input, config, **kwargs)
   1152         got_first_val = False
   1153 
-> 1154         for ichunk in input:
   1155             # The default implementation of transform is to buffer input and
   1156             # then call stream.

[/usr/local/lib/python3.10/dist-packages/langchain_core/runnables/base.py](https://localhost:8080/#) in transform(self, input, config, **kwargs)
   4653         **kwargs: Any,
   4654     ) -> Iterator[Output]:
-> 4655         yield from self.bound.transform(
   4656             input,
   4657             self._merge_configs(config),

[/usr/local/lib/python3.10/dist-packages/langchain_core/runnables/base.py](https://localhost:8080/#) in transform(self, input, config, **kwargs)
   1170 
   1171         if got_first_val:
-> 1172             yield from self.stream(final, config, **kwargs)
   1173 
   1174     async def atransform(

[/usr/local/lib/python3.10/dist-packages/langchain_core/language_models/chat_models.py](https://localhost:8080/#) in stream(self, input, config, stop, **kwargs)
    263                     ),
    264                 )
--> 265                 raise e
    266             else:
    267                 run_manager.on_llm_end(LLMResult(generations=[[generation]]))

[/usr/local/lib/python3.10/dist-packages/langchain_core/language_models/chat_models.py](https://localhost:8080/#) in stream(self, input, config, stop, **kwargs)
    243             generation: Optional[ChatGenerationChunk] = None
    244             try:
--> 245                 for chunk in self._stream(messages, stop=stop, **kwargs):
    246                     if chunk.message.id is None:
    247                         chunk.message.id = f"run-{run_manager.run_id}"

[/usr/local/lib/python3.10/dist-packages/langchain_google_vertexai/chat_models.py](https://localhost:8080/#) in _stream(self, messages, stop, run_manager, **kwargs)
    919             )
    920             return
--> 921         yield from self._stream_gemini(
    922             messages=messages, stop=stop, run_manager=run_manager, **kwargs
    923         )

[/usr/local/lib/python3.10/dist-packages/langchain_google_vertexai/chat_models.py](https://localhost:8080/#) in _stream_gemini(self, messages, stop, run_manager, **kwargs)
    932     ) -> Iterator[ChatGenerationChunk]:
    933         request = self._prepare_request_gemini(messages=messages, stop=stop, **kwargs)
--> 934         response_iter = _completion_with_retry(
    935             self.prediction_client.stream_generate_content,
    936             max_retries=self.max_retries,

[/usr/local/lib/python3.10/dist-packages/langchain_google_vertexai/chat_models.py](https://localhost:8080/#) in _completion_with_retry(generation_method, max_retries, run_manager, **kwargs)
    494         else kwargs
    495     )
--> 496     return _completion_with_retry_inner(
    497         generation_method,
    498         **params,

[/usr/local/lib/python3.10/dist-packages/tenacity/__init__.py](https://localhost:8080/#) in wrapped_f(*args, **kw)
    328         )
    329         def wrapped_f(*args: t.Any, **kw: t.Any) -> t.Any:
--> 330             return self(f, *args, **kw)
    331 
    332         def retry_with(*args: t.Any, **kwargs: t.Any) -> WrappedFn:

[/usr/local/lib/python3.10/dist-packages/tenacity/__init__.py](https://localhost:8080/#) in __call__(self, fn, *args, **kwargs)
    465         retry_state = RetryCallState(retry_object=self, fn=fn, args=args, kwargs=kwargs)
    466         while True:
--> 467             do = self.iter(retry_state=retry_state)
    468             if isinstance(do, DoAttempt):
    469                 try:

[/usr/local/lib/python3.10/dist-packages/tenacity/__init__.py](https://localhost:8080/#) in iter(self, retry_state)
    366         result = None
    367         for action in self.iter_state.actions:
--> 368             result = action(retry_state)
    369         return result
    370 

[/usr/local/lib/python3.10/dist-packages/tenacity/__init__.py](https://localhost:8080/#) in exc_check(rs)
    408                 retry_exc = self.retry_error_cls(fut)
    409                 if self.reraise:
--> 410                     raise retry_exc.reraise()
    411                 raise retry_exc from fut.exception()
    412 

[/usr/local/lib/python3.10/dist-packages/tenacity/__init__.py](https://localhost:8080/#) in reraise(self)
    181     def reraise(self) -> t.NoReturn:
    182         if self.last_attempt.failed:
--> 183             raise self.last_attempt.result()
    184         raise self
    185 

[/usr/lib/python3.10/concurrent/futures/_base.py](https://localhost:8080/#) in result(self, timeout)
    449                     raise CancelledError()
    450                 elif self._state == FINISHED:
--> 451                     return self.__get_result()
    452 
    453                 self._condition.wait(timeout)

[/usr/lib/python3.10/concurrent/futures/_base.py](https://localhost:8080/#) in __get_result(self)
    401         if self._exception:
    402             try:
--> 403                 raise self._exception
    404             finally:
    405                 # Break a reference cycle with the exception in self._exception

[/usr/local/lib/python3.10/dist-packages/tenacity/__init__.py](https://localhost:8080/#) in __call__(self, fn, *args, **kwargs)
    468             if isinstance(do, DoAttempt):
    469                 try:
--> 470                     result = fn(*args, **kwargs)
    471                 except BaseException:  # noqa: B902
    472                     retry_state.set_exception(sys.exc_info())  # type: ignore[arg-type]

[/usr/local/lib/python3.10/dist-packages/langchain_google_vertexai/chat_models.py](https://localhost:8080/#) in _completion_with_retry_inner(generation_method, **kwargs)
    487     @retry_decorator
    488     def _completion_with_retry_inner(generation_method: Callable, **kwargs: Any) -> Any:
--> 489         return generation_method(**kwargs)
    490 
    491     params = (

[/usr/local/lib/python3.10/dist-packages/google/cloud/aiplatform_v1beta1/services/prediction_service/client.py](https://localhost:8080/#) in stream_generate_content(self, request, model, contents, retry, timeout, metadata)
   2248 
   2249         # Send the request.
-> 2250         response = rpc(
   2251             request,
   2252             retry=retry,

[/usr/local/lib/python3.10/dist-packages/google/api_core/gapic_v1/method.py](https://localhost:8080/#) in __call__(self, timeout, retry, *args, **kwargs)
    111             kwargs["metadata"] = metadata
    112 
--> 113         return wrapped_func(*args, **kwargs)
    114 
    115 

[/usr/local/lib/python3.10/dist-packages/google/api_core/grpc_helpers.py](https://localhost:8080/#) in error_remapped_callable(*args, **kwargs)
    164             )
    165         except grpc.RpcError as exc:
--> 166             raise exceptions.from_grpc_error(exc) from exc
    167 
    168     return error_remapped_callable

InvalidArgument: 400 Request contains an invalid argument.---------------------------------------------------------------------------
_MultiThreadedRendezvous                  Traceback (most recent call last)
[/usr/local/lib/python3.10/dist-packages/google/api_core/grpc_helpers.py](https://localhost:8080/#) in error_remapped_callable(*args, **kwargs)
    161             prefetch_first = getattr(callable_, "_prefetch_first_result_", True)
--> 162             return _StreamingResponseIterator(
    163                 result, prefetch_first_result=prefetch_first

34 frames
[/usr/local/lib/python3.10/dist-packages/google/api_core/grpc_helpers.py](https://localhost:8080/#) in __init__(self, wrapped, prefetch_first_result)
     87             if prefetch_first_result:
---> 88                 self._stored_first_result = next(self._wrapped)
     89         except TypeError:

[/usr/local/lib/python3.10/dist-packages/grpc/_channel.py](https://localhost:8080/#) in __next__(self)
    542     def __next__(self):
--> 543         return self._next()
    544 

[/usr/local/lib/python3.10/dist-packages/grpc/_channel.py](https://localhost:8080/#) in _next(self)
    968                 elif self._state.code is not None:
--> 969                     raise self
    970 

_MultiThreadedRendezvous: <_MultiThreadedRendezvous of RPC that terminated with:
    status = StatusCode.INVALID_ARGUMENT
    details = "Request contains an invalid argument."
    debug_error_string = "UNKNOWN:Error received from peer ipv4:173.194.213.95:443 {grpc_message:"Request contains an invalid argument.", grpc_status:3, created_time:"2024-06-04T23:27:37.44187111+00:00"}"
>

The above exception was the direct cause of the following exception:

InvalidArgument                           Traceback (most recent call last)
[<ipython-input-5-715a9eadcc2e>](https://localhost:8080/#) in <cell line: 1>()
----> 1 agent_executor.invoke({
      2     "input": 'use multiple tools. what is the brand and when can i get this delivered? {"product_id": "432890", "store_id": "0123", "store_zip": "1234"}'
      3 })

[/usr/local/lib/python3.10/dist-packages/langchain/chains/base.py](https://localhost:8080/#) in invoke(self, input, config, **kwargs)
    164         except BaseException as e:
    165             run_manager.on_chain_error(e)
--> 166             raise e
    167         run_manager.on_chain_end(outputs)
    168 

[/usr/local/lib/python3.10/dist-packages/langchain/chains/base.py](https://localhost:8080/#) in invoke(self, input, config, **kwargs)
    154             self._validate_inputs(inputs)
    155             outputs = (
--> 156                 self._call(inputs, run_manager=run_manager)
    157                 if new_arg_supported
    158                 else self._call(inputs)

[/usr/local/lib/python3.10/dist-packages/langchain/agents/agent.py](https://localhost:8080/#) in _call(self, inputs, run_manager)
   1431         # We now enter the agent loop (until it returns something).
   1432         while self._should_continue(iterations, time_elapsed):
-> 1433             next_step_output = self._take_next_step(
   1434                 name_to_tool_map,
   1435                 color_mapping,

[/usr/local/lib/python3.10/dist-packages/langchain/agents/agent.py](https://localhost:8080/#) in _take_next_step(self, name_to_tool_map, color_mapping, inputs, intermediate_steps, run_manager)
   1137     ) -> Union[AgentFinish, List[Tuple[AgentAction, str]]]:
   1138         return self._consume_next_step(
-> 1139             [
   1140                 a
   1141                 for a in self._iter_next_step(

[/usr/local/lib/python3.10/dist-packages/langchain/agents/agent.py](https://localhost:8080/#) in <listcomp>(.0)
   1137     ) -> Union[AgentFinish, List[Tuple[AgentAction, str]]]:
   1138         return self._consume_next_step(
-> 1139             [
   1140                 a
   1141                 for a in self._iter_next_step(

[/usr/local/lib/python3.10/dist-packages/langchain/agents/agent.py](https://localhost:8080/#) in _iter_next_step(self, name_to_tool_map, color_mapping, inputs, intermediate_steps, run_manager)
   1165 
   1166             # Call the LLM to see what to do.
-> 1167             output = self.agent.plan(
   1168                 intermediate_steps,
   1169                 callbacks=run_manager.get_child() if run_manager else None,

[/usr/local/lib/python3.10/dist-packages/langchain/agents/agent.py](https://localhost:8080/#) in plan(self, intermediate_steps, callbacks, **kwargs)
    513             # Because the response from the plan is not a generator, we need to
    514             # accumulate the output into final output and return that.
--> 515             for chunk in self.runnable.stream(inputs, config={"callbacks": callbacks}):
    516                 if final_output is None:
    517                     final_output = chunk

[/usr/local/lib/python3.10/dist-packages/langchain_core/runnables/base.py](https://localhost:8080/#) in stream(self, input, config, **kwargs)
   2784         **kwargs: Optional[Any],
   2785     ) -> Iterator[Output]:
-> 2786         yield from self.transform(iter([input]), config, **kwargs)
   2787 
   2788     async def atransform(

[/usr/local/lib/python3.10/dist-packages/langchain_core/runnables/base.py](https://localhost:8080/#) in transform(self, input, config, **kwargs)
   2771         **kwargs: Optional[Any],
   2772     ) -> Iterator[Output]:
-> 2773         yield from self._transform_stream_with_config(
   2774             input,
   2775             self._transform,

[/usr/local/lib/python3.10/dist-packages/langchain_core/runnables/base.py](https://localhost:8080/#) in _transform_stream_with_config(self, input, transformer, config, run_type, **kwargs)
   1776             try:
   1777                 while True:
-> 1778                     chunk: Output = context.run(next, iterator)  # type: ignore
   1779                     yield chunk
   1780                     if final_output_supported:

[/usr/local/lib/python3.10/dist-packages/langchain_core/runnables/base.py](https://localhost:8080/#) in _transform(self, input, run_manager, config, **kwargs)
   2733                 final_pipeline = step.transform(final_pipeline, config)
   2734 
-> 2735         for output in final_pipeline:
   2736             yield output
   2737 

[/usr/local/lib/python3.10/dist-packages/langchain_core/runnables/base.py](https://localhost:8080/#) in transform(self, input, config, **kwargs)
   1152         got_first_val = False
   1153 
-> 1154         for ichunk in input:
   1155             # The default implementation of transform is to buffer input and
   1156             # then call stream.

[/usr/local/lib/python3.10/dist-packages/langchain_core/runnables/base.py](https://localhost:8080/#) in transform(self, input, config, **kwargs)
   4653         **kwargs: Any,
   4654     ) -> Iterator[Output]:
-> 4655         yield from self.bound.transform(
   4656             input,
   4657             self._merge_configs(config),

[/usr/local/lib/python3.10/dist-packages/langchain_core/runnables/base.py](https://localhost:8080/#) in transform(self, input, config, **kwargs)
   1170 
   1171         if got_first_val:
-> 1172             yield from self.stream(final, config, **kwargs)
   1173 
   1174     async def atransform(

[/usr/local/lib/python3.10/dist-packages/langchain_core/language_models/chat_models.py](https://localhost:8080/#) in stream(self, input, config, stop, **kwargs)
    263                     ),
    264                 )
--> 265                 raise e
    266             else:
    267                 run_manager.on_llm_end(LLMResult(generations=[[generation]]))

[/usr/local/lib/python3.10/dist-packages/langchain_core/language_models/chat_models.py](https://localhost:8080/#) in stream(self, input, config, stop, **kwargs)
    243             generation: Optional[ChatGenerationChunk] = None
    244             try:
--> 245                 for chunk in self._stream(messages, stop=stop, **kwargs):
    246                     if chunk.message.id is None:
    247                         chunk.message.id = f"run-{run_manager.run_id}"

[/usr/local/lib/python3.10/dist-packages/langchain_google_vertexai/chat_models.py](https://localhost:8080/#) in _stream(self, messages, stop, run_manager, **kwargs)
    919             )
    920             return
--> 921         yield from self._stream_gemini(
    922             messages=messages, stop=stop, run_manager=run_manager, **kwargs
    923         )

[/usr/local/lib/python3.10/dist-packages/langchain_google_vertexai/chat_models.py](https://localhost:8080/#) in _stream_gemini(self, messages, stop, run_manager, **kwargs)
    932     ) -> Iterator[ChatGenerationChunk]:
    933         request = self._prepare_request_gemini(messages=messages, stop=stop, **kwargs)
--> 934         response_iter = _completion_with_retry(
    935             self.prediction_client.stream_generate_content,
    936             max_retries=self.max_retries,

[/usr/local/lib/python3.10/dist-packages/langchain_google_vertexai/chat_models.py](https://localhost:8080/#) in _completion_with_retry(generation_method, max_retries, run_manager, **kwargs)
    494         else kwargs
    495     )
--> 496     return _completion_with_retry_inner(
    497         generation_method,
    498         **params,

[/usr/local/lib/python3.10/dist-packages/tenacity/__init__.py](https://localhost:8080/#) in wrapped_f(*args, **kw)
    328         )
    329         def wrapped_f(*args: t.Any, **kw: t.Any) -> t.Any:
--> 330             return self(f, *args, **kw)
    331 
    332         def retry_with(*args: t.Any, **kwargs: t.Any) -> WrappedFn:

[/usr/local/lib/python3.10/dist-packages/tenacity/__init__.py](https://localhost:8080/#) in __call__(self, fn, *args, **kwargs)
    465         retry_state = RetryCallState(retry_object=self, fn=fn, args=args, kwargs=kwargs)
    466         while True:
--> 467             do = self.iter(retry_state=retry_state)
    468             if isinstance(do, DoAttempt):
    469                 try:

[/usr/local/lib/python3.10/dist-packages/tenacity/__init__.py](https://localhost:8080/#) in iter(self, retry_state)
    366         result = None
    367         for action in self.iter_state.actions:
--> 368             result = action(retry_state)
    369         return result
    370 

[/usr/local/lib/python3.10/dist-packages/tenacity/__init__.py](https://localhost:8080/#) in exc_check(rs)
    408                 retry_exc = self.retry_error_cls(fut)
    409                 if self.reraise:
--> 410                     raise retry_exc.reraise()
    411                 raise retry_exc from fut.exception()
    412 

[/usr/local/lib/python3.10/dist-packages/tenacity/__init__.py](https://localhost:8080/#) in reraise(self)
    181     def reraise(self) -> t.NoReturn:
    182         if self.last_attempt.failed:
--> 183             raise self.last_attempt.result()
    184         raise self
    185 

[/usr/lib/python3.10/concurrent/futures/_base.py](https://localhost:8080/#) in result(self, timeout)
    449                     raise CancelledError()
    450                 elif self._state == FINISHED:
--> 451                     return self.__get_result()
    452 
    453                 self._condition.wait(timeout)

[/usr/lib/python3.10/concurrent/futures/_base.py](https://localhost:8080/#) in __get_result(self)
    401         if self._exception:
    402             try:
--> 403                 raise self._exception
    404             finally:
    405                 # Break a reference cycle with the exception in self._exception

[/usr/local/lib/python3.10/dist-packages/tenacity/__init__.py](https://localhost:8080/#) in __call__(self, fn, *args, **kwargs)
    468             if isinstance(do, DoAttempt):
    469                 try:
--> 470                     result = fn(*args, **kwargs)
    471                 except BaseException:  # noqa: B902
    472                     retry_state.set_exception(sys.exc_info())  # type: ignore[arg-type]

[/usr/local/lib/python3.10/dist-packages/langchain_google_vertexai/chat_models.py](https://localhost:8080/#) in _completion_with_retry_inner(generation_method, **kwargs)
    487     @retry_decorator
    488     def _completion_with_retry_inner(generation_method: Callable, **kwargs: Any) -> Any:
--> 489         return generation_method(**kwargs)
    490 
    491     params = (

[/usr/local/lib/python3.10/dist-packages/google/cloud/aiplatform_v1beta1/services/prediction_service/client.py](https://localhost:8080/#) in stream_generate_content(self, request, model, contents, retry, timeout, metadata)
   2248 
   2249         # Send the request.
-> 2250         response = rpc(
   2251             request,
   2252             retry=retry,

[/usr/local/lib/python3.10/dist-packages/google/api_core/gapic_v1/method.py](https://localhost:8080/#) in __call__(self, timeout, retry, *args, **kwargs)
    111             kwargs["metadata"] = metadata
    112 
--> 113         return wrapped_func(*args, **kwargs)
    114 
    115 

[/usr/local/lib/python3.10/dist-packages/google/api_core/grpc_helpers.py](https://localhost:8080/#) in error_remapped_callable(*args, **kwargs)
    164             )
    165         except grpc.RpcError as exc:
--> 166             raise exceptions.from_grpc_error(exc) from exc
    167 
    168     return error_remapped_callable

InvalidArgument: 400 Request contains an invalid argument.