@ -39,6 +39,8 @@ from langchain.load.serializable import Serializable
from langchain . pydantic_v1 import Field
from langchain . schema . runnable . config import (
RunnableConfig ,
acall_func_with_variable_args ,
call_func_with_variable_args ,
ensure_config ,
get_async_callback_manager_for_config ,
get_callback_manager_for_config ,
@ -47,16 +49,15 @@ from langchain.schema.runnable.config import (
patch_config ,
)
from langchain . schema . runnable . utils import (
Input ,
Output ,
accepts_config ,
accepts_run_manager ,
accepts_run_manager_and_config ,
gather_with_concurrency ,
)
from langchain . utils . aiter import atee , py_anext
from langchain . utils . iter import safetee
Input = TypeVar ( " Input " )
# Output type should implement __concat__, as eg str, list, dict do
Output = TypeVar ( " Output " )
Other = TypeVar ( " Other " )
@ -311,16 +312,7 @@ class Runnable(Generic[Input, Output], ABC):
name = config . get ( " run_name " ) ,
)
try :
if accepts_run_manager_and_config ( func ) :
output = func (
input ,
run_manager = run_manager ,
config = config ,
) # type: ignore[call-arg]
elif accepts_run_manager ( func ) :
output = func ( input , run_manager = run_manager ) # type: ignore[call-arg]
else :
output = func ( input ) # type: ignore[call-arg]
output = call_func_with_variable_args ( func , input , run_manager , config )
except Exception as e :
run_manager . on_chain_error ( e )
raise
@ -353,19 +345,9 @@ class Runnable(Generic[Input, Output], ABC):
name = config . get ( " run_name " ) ,
)
try :
if accepts_run_manager_and_config ( func ) :
output = await func (
input ,
run_manager = run_manager ,
config = config ,
) # type: ignore[call-arg]
elif accepts_run_manager ( func ) :
output = await func (
input ,
run_manager = run_manager ,
) # type: ignore[call-arg]
else :
output = await func ( input ) # type: ignore[call-arg]
output = await acall_func_with_variable_args (
func , input , run_manager , config
)
except Exception as e :
await run_manager . on_chain_error ( e )
raise
@ -408,16 +390,15 @@ class Runnable(Generic[Input, Output], ABC):
)
]
try :
if accepts_run_manager_and_config ( func ) :
output = func (
input ,
run_manager = run_managers ,
config = configs ,
) # type: ignore[call-arg]
elif accepts_run_manager ( func ) :
output = func ( input , run_manager = run_managers ) # type: ignore[call-arg]
else :
output = func ( input ) # type: ignore[call-arg]
kwargs : Dict [ str , Any ] = { }
if accepts_config ( func ) :
kwargs [ " config " ] = [
patch_config ( c , callbacks = rm . get_child ( ) )
for c , rm in zip ( configs , run_managers )
]
if accepts_run_manager ( func ) :
kwargs [ " run_manager " ] = run_managers
output = func ( input , * * kwargs ) # type: ignore[call-arg]
except Exception as e :
for run_manager in run_managers :
run_manager . on_chain_error ( e )
@ -479,16 +460,15 @@ class Runnable(Generic[Input, Output], ABC):
)
)
try :
if accepts_run_manager_and_config ( func ) :
output = await func (
input ,
run_manager = run_managers ,
config = configs ,
) # type: ignore[call-arg]
elif accepts_run_manager ( func ) :
output = await func ( input , run_manager = run_managers ) # type: ignore
else :
output = await func ( input ) # type: ignore[call-arg]
kwargs : Dict [ str , Any ] = { }
if accepts_config ( func ) :
kwargs [ " config " ] = [
patch_config ( c , callbacks = rm . get_child ( ) )
for c , rm in zip ( configs , run_managers )
]
if accepts_run_manager ( func ) :
kwargs [ " run_manager " ] = run_managers
output = await func ( input , * * kwargs ) # type: ignore[call-arg]
except Exception as e :
await asyncio . gather (
* ( run_manager . on_chain_error ( e ) for run_manager in run_managers )
@ -550,19 +530,14 @@ class Runnable(Generic[Input, Output], ABC):
name = config . get ( " run_name " ) ,
)
try :
if accepts_run_manager_and_config ( transformer ) :
iterator = transformer (
input_for_transform ,
run_manager = run_manager ,
config = config ,
) # type: ignore[call-arg]
elif accepts_run_manager ( transformer ) :
iterator = transformer (
input_for_transform ,
run_manager = run_manager ,
) # type: ignore[call-arg]
else :
iterator = transformer ( input_for_transform ) # type: ignore[call-arg]
kwargs : Dict [ str , Any ] = { }
if accepts_config ( transformer ) :
kwargs [ " config " ] = patch_config (
config , callbacks = run_manager . get_child ( )
)
if accepts_run_manager ( transformer ) :
kwargs [ " run_manager " ] = run_manager
iterator = transformer ( input_for_transform , * * kwargs ) # type: ignore[call-arg]
for chunk in iterator :
yield chunk
if final_output_supported :
@ -631,21 +606,14 @@ class Runnable(Generic[Input, Output], ABC):
name = config . get ( " run_name " ) ,
)
try :
# mypy can't quite work out thew type guard here, but this is safe,
# check implementations of the accepts_* functions
if accepts_run_manager_and_config ( transformer ) :
iterator = transformer (
input_for_transform ,
run_manager = run_manager ,
config = config ,
) # type: ignore[call-arg]
elif accepts_run_manager ( transformer ) :
iterator = transformer (
input_for_transform ,
run_manager = run_manager ,
) # type: ignore[call-arg]
else :
iterator = transformer ( input_for_transform ) # type: ignore[call-arg]
kwargs : Dict [ str , Any ] = { }
if accepts_config ( transformer ) :
kwargs [ " config " ] = patch_config (
config , callbacks = run_manager . get_child ( )
)
if accepts_run_manager ( transformer ) :
kwargs [ " run_manager " ] = run_manager
iterator = transformer ( input_for_transform , * * kwargs ) # type: ignore[call-arg]
async for chunk in iterator :
yield chunk
if final_output_supported :
@ -1756,7 +1724,7 @@ class RunnableLambda(Runnable[Input, Output]):
run_manager : CallbackManagerForChainRun ,
config : RunnableConfig ,
) - > Output :
output = self . func ( input )
output = call_func_with_variable_args ( self . func , input , run_manager , config )
# If the output is a runnable, invoke it
if isinstance ( output , Runnable ) :
recursion_limit = config [ " recursion_limit " ]
@ -1780,7 +1748,9 @@ class RunnableLambda(Runnable[Input, Output]):
run_manager : AsyncCallbackManagerForChainRun ,
config : RunnableConfig ,
) - > Output :
output = await self . afunc ( input )
output = await acall_func_with_variable_args (
self . afunc , input , run_manager , config
)
# If the output is a runnable, invoke it
if isinstance ( output , Runnable ) :
recursion_limit = config [ " recursion_limit " ]
@ -1798,6 +1768,21 @@ class RunnableLambda(Runnable[Input, Output]):
)
return output
def _config (
self , config : Optional [ RunnableConfig ] , callable : Callable [ . . . , Any ]
) - > RunnableConfig :
config = config or { }
if config . get ( " run_name " ) is None :
try :
run_name = callable . __name__
except AttributeError :
run_name = None
if run_name is not None :
return patch_config ( config , run_name = run_name )
return config
def invoke (
self ,
input : Input ,
@ -1805,7 +1790,11 @@ class RunnableLambda(Runnable[Input, Output]):
* * kwargs : Optional [ Any ] ,
) - > Output :
if hasattr ( self , " func " ) :
return self . _call_with_config ( self . _invoke , input , config )
return self . _call_with_config (
self . _invoke ,
input ,
self . _config ( config , self . func ) ,
)
else :
raise TypeError (
" Cannot invoke a coroutine function synchronously. "
@ -1819,7 +1808,11 @@ class RunnableLambda(Runnable[Input, Output]):
* * kwargs : Optional [ Any ] ,
) - > Output :
if hasattr ( self , " afunc " ) :
return await self . _acall_with_config ( self . _ainvoke , input , config )
return await self . _acall_with_config (
self . _ainvoke ,
input ,
self . _config ( config , self . afunc ) ,
)
else :
# Delegating to super implementation of ainvoke.
# Uses asyncio executor to run the sync version (invoke)