mirror of
https://github.com/hwchase17/langchain.git
synced 2025-06-23 07:09:31 +00:00
langchain[patch]: runnable agent streaming param (#18761)
Usage: ```python agent = RunnableAgent(runnable=runnable, .., stream_runnable=False) ``` or for convenience ```python agent_executor = AgentExecutor(agent=agent, ..., stream_runnable=False) ```
This commit is contained in:
parent
c8c592d3f1
commit
bc6249c889
@ -345,6 +345,14 @@ class RunnableAgent(BaseSingleActionAgent):
|
|||||||
"""Runnable to call to get agent action."""
|
"""Runnable to call to get agent action."""
|
||||||
input_keys_arg: List[str] = []
|
input_keys_arg: List[str] = []
|
||||||
return_keys_arg: List[str] = []
|
return_keys_arg: List[str] = []
|
||||||
|
stream_runnable: bool = True
|
||||||
|
"""Whether to stream from the runnable or not.
|
||||||
|
|
||||||
|
If True then underlying LLM is invoked in a streaming fashion to make it possible
|
||||||
|
to get access to the individual LLM tokens when using stream_log with the Agent
|
||||||
|
Executor. If False then LLM is invoked in a non-streaming fashion and
|
||||||
|
individual LLM tokens will not be available in stream_log.
|
||||||
|
"""
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
"""Configuration for this pydantic object."""
|
"""Configuration for this pydantic object."""
|
||||||
@ -378,17 +386,21 @@ class RunnableAgent(BaseSingleActionAgent):
|
|||||||
Action specifying what tool to use.
|
Action specifying what tool to use.
|
||||||
"""
|
"""
|
||||||
inputs = {**kwargs, **{"intermediate_steps": intermediate_steps}}
|
inputs = {**kwargs, **{"intermediate_steps": intermediate_steps}}
|
||||||
# Use streaming to make sure that the underlying LLM is invoked in a streaming
|
final_output: Any = None
|
||||||
|
if self.stream_runnable:
|
||||||
|
# Use streaming to make sure that the underlying LLM is invoked in a
|
||||||
|
# streaming
|
||||||
# fashion to make it possible to get access to the individual LLM tokens
|
# fashion to make it possible to get access to the individual LLM tokens
|
||||||
# when using stream_log with the Agent Executor.
|
# when using stream_log with the Agent Executor.
|
||||||
# Because the response from the plan is not a generator, we need to
|
# Because the response from the plan is not a generator, we need to
|
||||||
# accumulate the output into final output and return that.
|
# accumulate the output into final output and return that.
|
||||||
final_output: Any = None
|
|
||||||
for chunk in self.runnable.stream(inputs, config={"callbacks": callbacks}):
|
for chunk in self.runnable.stream(inputs, config={"callbacks": callbacks}):
|
||||||
if final_output is None:
|
if final_output is None:
|
||||||
final_output = chunk
|
final_output = chunk
|
||||||
else:
|
else:
|
||||||
final_output += chunk
|
final_output += chunk
|
||||||
|
else:
|
||||||
|
final_output = self.runnable.invoke(inputs, config={"callbacks": callbacks})
|
||||||
|
|
||||||
return final_output
|
return final_output
|
||||||
|
|
||||||
@ -414,7 +426,9 @@ class RunnableAgent(BaseSingleActionAgent):
|
|||||||
"""
|
"""
|
||||||
inputs = {**kwargs, **{"intermediate_steps": intermediate_steps}}
|
inputs = {**kwargs, **{"intermediate_steps": intermediate_steps}}
|
||||||
final_output: Any = None
|
final_output: Any = None
|
||||||
# Use streaming to make sure that the underlying LLM is invoked in a streaming
|
if self.stream_runnable:
|
||||||
|
# Use streaming to make sure that the underlying LLM is invoked in a
|
||||||
|
# streaming
|
||||||
# fashion to make it possible to get access to the individual LLM tokens
|
# fashion to make it possible to get access to the individual LLM tokens
|
||||||
# when using stream_log with the Agent Executor.
|
# when using stream_log with the Agent Executor.
|
||||||
# Because the response from the plan is not a generator, we need to
|
# Because the response from the plan is not a generator, we need to
|
||||||
@ -426,6 +440,10 @@ class RunnableAgent(BaseSingleActionAgent):
|
|||||||
final_output = chunk
|
final_output = chunk
|
||||||
else:
|
else:
|
||||||
final_output += chunk
|
final_output += chunk
|
||||||
|
else:
|
||||||
|
final_output = await self.runnable.ainvoke(
|
||||||
|
inputs, config={"callbacks": callbacks}
|
||||||
|
)
|
||||||
return final_output
|
return final_output
|
||||||
|
|
||||||
|
|
||||||
@ -436,6 +454,14 @@ class RunnableMultiActionAgent(BaseMultiActionAgent):
|
|||||||
"""Runnable to call to get agent actions."""
|
"""Runnable to call to get agent actions."""
|
||||||
input_keys_arg: List[str] = []
|
input_keys_arg: List[str] = []
|
||||||
return_keys_arg: List[str] = []
|
return_keys_arg: List[str] = []
|
||||||
|
stream_runnable: bool = True
|
||||||
|
"""Whether to stream from the runnable or not.
|
||||||
|
|
||||||
|
If True then underlying LLM is invoked in a streaming fashion to make it possible
|
||||||
|
to get access to the individual LLM tokens when using stream_log with the Agent
|
||||||
|
Executor. If False then LLM is invoked in a non-streaming fashion and
|
||||||
|
individual LLM tokens will not be available in stream_log.
|
||||||
|
"""
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
"""Configuration for this pydantic object."""
|
"""Configuration for this pydantic object."""
|
||||||
@ -477,17 +503,21 @@ class RunnableMultiActionAgent(BaseMultiActionAgent):
|
|||||||
Action specifying what tool to use.
|
Action specifying what tool to use.
|
||||||
"""
|
"""
|
||||||
inputs = {**kwargs, **{"intermediate_steps": intermediate_steps}}
|
inputs = {**kwargs, **{"intermediate_steps": intermediate_steps}}
|
||||||
# Use streaming to make sure that the underlying LLM is invoked in a streaming
|
final_output: Any = None
|
||||||
|
if self.stream_runnable:
|
||||||
|
# Use streaming to make sure that the underlying LLM is invoked in a
|
||||||
|
# streaming
|
||||||
# fashion to make it possible to get access to the individual LLM tokens
|
# fashion to make it possible to get access to the individual LLM tokens
|
||||||
# when using stream_log with the Agent Executor.
|
# when using stream_log with the Agent Executor.
|
||||||
# Because the response from the plan is not a generator, we need to
|
# Because the response from the plan is not a generator, we need to
|
||||||
# accumulate the output into final output and return that.
|
# accumulate the output into final output and return that.
|
||||||
final_output: Any = None
|
|
||||||
for chunk in self.runnable.stream(inputs, config={"callbacks": callbacks}):
|
for chunk in self.runnable.stream(inputs, config={"callbacks": callbacks}):
|
||||||
if final_output is None:
|
if final_output is None:
|
||||||
final_output = chunk
|
final_output = chunk
|
||||||
else:
|
else:
|
||||||
final_output += chunk
|
final_output += chunk
|
||||||
|
else:
|
||||||
|
final_output = self.runnable.invoke(inputs, config={"callbacks": callbacks})
|
||||||
|
|
||||||
return final_output
|
return final_output
|
||||||
|
|
||||||
@ -512,12 +542,14 @@ class RunnableMultiActionAgent(BaseMultiActionAgent):
|
|||||||
Action specifying what tool to use.
|
Action specifying what tool to use.
|
||||||
"""
|
"""
|
||||||
inputs = {**kwargs, **{"intermediate_steps": intermediate_steps}}
|
inputs = {**kwargs, **{"intermediate_steps": intermediate_steps}}
|
||||||
# Use streaming to make sure that the underlying LLM is invoked in a streaming
|
final_output: Any = None
|
||||||
|
if self.stream_runnable:
|
||||||
|
# Use streaming to make sure that the underlying LLM is invoked in a
|
||||||
|
# streaming
|
||||||
# fashion to make it possible to get access to the individual LLM tokens
|
# fashion to make it possible to get access to the individual LLM tokens
|
||||||
# when using stream_log with the Agent Executor.
|
# when using stream_log with the Agent Executor.
|
||||||
# Because the response from the plan is not a generator, we need to
|
# Because the response from the plan is not a generator, we need to
|
||||||
# accumulate the output into final output and return that.
|
# accumulate the output into final output and return that.
|
||||||
final_output: Any = None
|
|
||||||
async for chunk in self.runnable.astream(
|
async for chunk in self.runnable.astream(
|
||||||
inputs, config={"callbacks": callbacks}
|
inputs, config={"callbacks": callbacks}
|
||||||
):
|
):
|
||||||
@ -525,6 +557,10 @@ class RunnableMultiActionAgent(BaseMultiActionAgent):
|
|||||||
final_output = chunk
|
final_output = chunk
|
||||||
else:
|
else:
|
||||||
final_output += chunk
|
final_output += chunk
|
||||||
|
else:
|
||||||
|
final_output = await self.runnable.ainvoke(
|
||||||
|
inputs, config={"callbacks": callbacks}
|
||||||
|
)
|
||||||
|
|
||||||
return final_output
|
return final_output
|
||||||
|
|
||||||
@ -977,10 +1013,15 @@ class AgentExecutor(Chain):
|
|||||||
else:
|
else:
|
||||||
multi_action = output_type == Union[List[AgentAction], AgentFinish]
|
multi_action = output_type == Union[List[AgentAction], AgentFinish]
|
||||||
|
|
||||||
|
stream_runnable = values.pop("stream_runnable", True)
|
||||||
if multi_action:
|
if multi_action:
|
||||||
values["agent"] = RunnableMultiActionAgent(runnable=agent)
|
values["agent"] = RunnableMultiActionAgent(
|
||||||
|
runnable=agent, stream_runnable=stream_runnable
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
values["agent"] = RunnableAgent(runnable=agent)
|
values["agent"] = RunnableAgent(
|
||||||
|
runnable=agent, stream_runnable=stream_runnable
|
||||||
|
)
|
||||||
return values
|
return values
|
||||||
|
|
||||||
def save(self, file_path: Union[Path, str]) -> None:
|
def save(self, file_path: Union[Path, str]) -> None:
|
||||||
|
Loading…
Reference in New Issue
Block a user