langchain-core 0.4.0.dev0__py3-none-any.whl → 1.0.0__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-core might be problematic. Click here for more details.

Files changed (172) hide show
  1. langchain_core/__init__.py +1 -1
  2. langchain_core/_api/__init__.py +3 -4
  3. langchain_core/_api/beta_decorator.py +45 -70
  4. langchain_core/_api/deprecation.py +80 -80
  5. langchain_core/_api/path.py +22 -8
  6. langchain_core/_import_utils.py +10 -4
  7. langchain_core/agents.py +25 -21
  8. langchain_core/caches.py +53 -63
  9. langchain_core/callbacks/__init__.py +1 -8
  10. langchain_core/callbacks/base.py +341 -348
  11. langchain_core/callbacks/file.py +55 -44
  12. langchain_core/callbacks/manager.py +546 -683
  13. langchain_core/callbacks/stdout.py +29 -30
  14. langchain_core/callbacks/streaming_stdout.py +35 -36
  15. langchain_core/callbacks/usage.py +65 -70
  16. langchain_core/chat_history.py +48 -55
  17. langchain_core/document_loaders/base.py +46 -21
  18. langchain_core/document_loaders/langsmith.py +39 -36
  19. langchain_core/documents/__init__.py +0 -1
  20. langchain_core/documents/base.py +96 -74
  21. langchain_core/documents/compressor.py +12 -9
  22. langchain_core/documents/transformers.py +29 -28
  23. langchain_core/embeddings/fake.py +56 -57
  24. langchain_core/env.py +2 -3
  25. langchain_core/example_selectors/base.py +12 -0
  26. langchain_core/example_selectors/length_based.py +1 -1
  27. langchain_core/example_selectors/semantic_similarity.py +21 -25
  28. langchain_core/exceptions.py +15 -9
  29. langchain_core/globals.py +4 -163
  30. langchain_core/indexing/api.py +132 -125
  31. langchain_core/indexing/base.py +64 -67
  32. langchain_core/indexing/in_memory.py +26 -6
  33. langchain_core/language_models/__init__.py +15 -27
  34. langchain_core/language_models/_utils.py +267 -117
  35. langchain_core/language_models/base.py +92 -177
  36. langchain_core/language_models/chat_models.py +547 -407
  37. langchain_core/language_models/fake.py +11 -11
  38. langchain_core/language_models/fake_chat_models.py +72 -118
  39. langchain_core/language_models/llms.py +168 -242
  40. langchain_core/load/dump.py +8 -11
  41. langchain_core/load/load.py +32 -28
  42. langchain_core/load/mapping.py +2 -4
  43. langchain_core/load/serializable.py +50 -56
  44. langchain_core/messages/__init__.py +36 -51
  45. langchain_core/messages/ai.py +377 -150
  46. langchain_core/messages/base.py +239 -47
  47. langchain_core/messages/block_translators/__init__.py +111 -0
  48. langchain_core/messages/block_translators/anthropic.py +470 -0
  49. langchain_core/messages/block_translators/bedrock.py +94 -0
  50. langchain_core/messages/block_translators/bedrock_converse.py +297 -0
  51. langchain_core/messages/block_translators/google_genai.py +530 -0
  52. langchain_core/messages/block_translators/google_vertexai.py +21 -0
  53. langchain_core/messages/block_translators/groq.py +143 -0
  54. langchain_core/messages/block_translators/langchain_v0.py +301 -0
  55. langchain_core/messages/block_translators/openai.py +1010 -0
  56. langchain_core/messages/chat.py +2 -3
  57. langchain_core/messages/content.py +1423 -0
  58. langchain_core/messages/function.py +7 -7
  59. langchain_core/messages/human.py +44 -38
  60. langchain_core/messages/modifier.py +3 -2
  61. langchain_core/messages/system.py +40 -27
  62. langchain_core/messages/tool.py +160 -58
  63. langchain_core/messages/utils.py +527 -638
  64. langchain_core/output_parsers/__init__.py +1 -14
  65. langchain_core/output_parsers/base.py +68 -104
  66. langchain_core/output_parsers/json.py +13 -17
  67. langchain_core/output_parsers/list.py +11 -33
  68. langchain_core/output_parsers/openai_functions.py +56 -74
  69. langchain_core/output_parsers/openai_tools.py +68 -109
  70. langchain_core/output_parsers/pydantic.py +15 -13
  71. langchain_core/output_parsers/string.py +6 -2
  72. langchain_core/output_parsers/transform.py +17 -60
  73. langchain_core/output_parsers/xml.py +34 -44
  74. langchain_core/outputs/__init__.py +1 -1
  75. langchain_core/outputs/chat_generation.py +26 -11
  76. langchain_core/outputs/chat_result.py +1 -3
  77. langchain_core/outputs/generation.py +17 -6
  78. langchain_core/outputs/llm_result.py +15 -8
  79. langchain_core/prompt_values.py +29 -123
  80. langchain_core/prompts/__init__.py +3 -27
  81. langchain_core/prompts/base.py +48 -63
  82. langchain_core/prompts/chat.py +259 -288
  83. langchain_core/prompts/dict.py +19 -11
  84. langchain_core/prompts/few_shot.py +84 -90
  85. langchain_core/prompts/few_shot_with_templates.py +14 -12
  86. langchain_core/prompts/image.py +19 -14
  87. langchain_core/prompts/loading.py +6 -8
  88. langchain_core/prompts/message.py +7 -8
  89. langchain_core/prompts/prompt.py +42 -43
  90. langchain_core/prompts/string.py +37 -16
  91. langchain_core/prompts/structured.py +43 -46
  92. langchain_core/rate_limiters.py +51 -60
  93. langchain_core/retrievers.py +52 -192
  94. langchain_core/runnables/base.py +1727 -1683
  95. langchain_core/runnables/branch.py +52 -73
  96. langchain_core/runnables/config.py +89 -103
  97. langchain_core/runnables/configurable.py +128 -130
  98. langchain_core/runnables/fallbacks.py +93 -82
  99. langchain_core/runnables/graph.py +127 -127
  100. langchain_core/runnables/graph_ascii.py +63 -41
  101. langchain_core/runnables/graph_mermaid.py +87 -70
  102. langchain_core/runnables/graph_png.py +31 -36
  103. langchain_core/runnables/history.py +145 -161
  104. langchain_core/runnables/passthrough.py +141 -144
  105. langchain_core/runnables/retry.py +84 -68
  106. langchain_core/runnables/router.py +33 -37
  107. langchain_core/runnables/schema.py +79 -72
  108. langchain_core/runnables/utils.py +95 -139
  109. langchain_core/stores.py +85 -131
  110. langchain_core/structured_query.py +11 -15
  111. langchain_core/sys_info.py +31 -32
  112. langchain_core/tools/__init__.py +1 -14
  113. langchain_core/tools/base.py +221 -247
  114. langchain_core/tools/convert.py +144 -161
  115. langchain_core/tools/render.py +10 -10
  116. langchain_core/tools/retriever.py +12 -19
  117. langchain_core/tools/simple.py +52 -29
  118. langchain_core/tools/structured.py +56 -60
  119. langchain_core/tracers/__init__.py +1 -9
  120. langchain_core/tracers/_streaming.py +6 -7
  121. langchain_core/tracers/base.py +103 -112
  122. langchain_core/tracers/context.py +29 -48
  123. langchain_core/tracers/core.py +142 -105
  124. langchain_core/tracers/evaluation.py +30 -34
  125. langchain_core/tracers/event_stream.py +162 -117
  126. langchain_core/tracers/langchain.py +34 -36
  127. langchain_core/tracers/log_stream.py +87 -49
  128. langchain_core/tracers/memory_stream.py +3 -3
  129. langchain_core/tracers/root_listeners.py +18 -34
  130. langchain_core/tracers/run_collector.py +8 -20
  131. langchain_core/tracers/schemas.py +0 -125
  132. langchain_core/tracers/stdout.py +3 -3
  133. langchain_core/utils/__init__.py +1 -4
  134. langchain_core/utils/_merge.py +47 -9
  135. langchain_core/utils/aiter.py +70 -66
  136. langchain_core/utils/env.py +12 -9
  137. langchain_core/utils/function_calling.py +139 -206
  138. langchain_core/utils/html.py +7 -8
  139. langchain_core/utils/input.py +6 -6
  140. langchain_core/utils/interactive_env.py +6 -2
  141. langchain_core/utils/iter.py +48 -45
  142. langchain_core/utils/json.py +14 -4
  143. langchain_core/utils/json_schema.py +159 -43
  144. langchain_core/utils/mustache.py +32 -25
  145. langchain_core/utils/pydantic.py +67 -40
  146. langchain_core/utils/strings.py +5 -5
  147. langchain_core/utils/usage.py +1 -1
  148. langchain_core/utils/utils.py +104 -62
  149. langchain_core/vectorstores/base.py +131 -179
  150. langchain_core/vectorstores/in_memory.py +113 -182
  151. langchain_core/vectorstores/utils.py +23 -17
  152. langchain_core/version.py +1 -1
  153. langchain_core-1.0.0.dist-info/METADATA +68 -0
  154. langchain_core-1.0.0.dist-info/RECORD +172 -0
  155. {langchain_core-0.4.0.dev0.dist-info → langchain_core-1.0.0.dist-info}/WHEEL +1 -1
  156. langchain_core/beta/__init__.py +0 -1
  157. langchain_core/beta/runnables/__init__.py +0 -1
  158. langchain_core/beta/runnables/context.py +0 -448
  159. langchain_core/memory.py +0 -116
  160. langchain_core/messages/content_blocks.py +0 -1435
  161. langchain_core/prompts/pipeline.py +0 -133
  162. langchain_core/pydantic_v1/__init__.py +0 -30
  163. langchain_core/pydantic_v1/dataclasses.py +0 -23
  164. langchain_core/pydantic_v1/main.py +0 -23
  165. langchain_core/tracers/langchain_v1.py +0 -23
  166. langchain_core/utils/loading.py +0 -31
  167. langchain_core/v1/__init__.py +0 -1
  168. langchain_core/v1/chat_models.py +0 -1047
  169. langchain_core/v1/messages.py +0 -755
  170. langchain_core-0.4.0.dev0.dist-info/METADATA +0 -108
  171. langchain_core-0.4.0.dev0.dist-info/RECORD +0 -177
  172. langchain_core-0.4.0.dev0.dist-info/entry_points.txt +0 -4
@@ -3,9 +3,7 @@
3
3
  from typing import (
4
4
  TYPE_CHECKING,
5
5
  Any,
6
- Optional,
7
6
  TypeVar,
8
- Union,
9
7
  cast,
10
8
  )
11
9
 
@@ -35,7 +33,7 @@ U = TypeVar("U")
35
33
 
36
34
 
37
35
  class ExponentialJitterParams(TypedDict, total=False):
38
- """Parameters for ``tenacity.wait_exponential_jitter``."""
36
+ """Parameters for `tenacity.wait_exponential_jitter`."""
39
37
 
40
38
  initial: float
41
39
  """Initial wait."""
@@ -47,7 +45,7 @@ class ExponentialJitterParams(TypedDict, total=False):
47
45
  """Random additional wait sampled from random.uniform(0, jitter)."""
48
46
 
49
47
 
50
- class RunnableRetry(RunnableBindingBase[Input, Output]):
48
+ class RunnableRetry(RunnableBindingBase[Input, Output]): # type: ignore[no-redef]
51
49
  """Retry a Runnable if it fails.
52
50
 
53
51
  RunnableRetry can be used to add retry logic to any object
@@ -62,32 +60,34 @@ class RunnableRetry(RunnableBindingBase[Input, Output]):
62
60
  Example:
63
61
  Here's an example that uses a RunnableLambda to raise an exception
64
62
 
65
- .. code-block:: python
63
+ ```python
64
+ import time
66
65
 
67
- import time
68
66
 
69
- def foo(input) -> None:
70
- '''Fake function that raises an exception.'''
71
- raise ValueError(f"Invoking foo failed. At time {time.time()}")
67
+ def foo(input) -> None:
68
+ '''Fake function that raises an exception.'''
69
+ raise ValueError(f"Invoking foo failed. At time {time.time()}")
72
70
 
73
- runnable = RunnableLambda(foo)
74
71
 
75
- runnable_with_retries = runnable.with_retry(
76
- retry_if_exception_type=(ValueError,), # Retry only on ValueError
77
- wait_exponential_jitter=True, # Add jitter to the exponential backoff
78
- stop_after_attempt=2, # Try twice
79
- exponential_jitter_params={"initial": 2}, # if desired, customize backoff
80
- )
72
+ runnable = RunnableLambda(foo)
81
73
 
82
- # The method invocation above is equivalent to the longer form below:
74
+ runnable_with_retries = runnable.with_retry(
75
+ retry_if_exception_type=(ValueError,), # Retry only on ValueError
76
+ wait_exponential_jitter=True, # Add jitter to the exponential backoff
77
+ stop_after_attempt=2, # Try twice
78
+ exponential_jitter_params={"initial": 2}, # if desired, customize backoff
79
+ )
83
80
 
84
- runnable_with_retries = RunnableRetry(
85
- bound=runnable,
86
- retry_exception_types=(ValueError,),
87
- max_attempt_number=2,
88
- wait_exponential_jitter=True,
89
- exponential_jitter_params={"initial": 2},
90
- )
81
+ # The method invocation above is equivalent to the longer form below:
82
+
83
+ runnable_with_retries = RunnableRetry(
84
+ bound=runnable,
85
+ retry_exception_types=(ValueError,),
86
+ max_attempt_number=2,
87
+ wait_exponential_jitter=True,
88
+ exponential_jitter_params={"initial": 2},
89
+ )
90
+ ```
91
91
 
92
92
  This logic can be used to retry any Runnable, including a chain of Runnables,
93
93
  but in general it's best practice to keep the scope of the retry as small as
@@ -95,23 +95,21 @@ class RunnableRetry(RunnableBindingBase[Input, Output]):
95
95
  the Runnable that is likely to fail, not the entire chain.
96
96
 
97
97
  Example:
98
+ ```python
99
+ from langchain_core.chat_models import ChatOpenAI
100
+ from langchain_core.prompts import PromptTemplate
98
101
 
99
- .. code-block:: python
100
-
101
- from langchain_core.chat_models import ChatOpenAI
102
- from langchain_core.prompts import PromptTemplate
102
+ template = PromptTemplate.from_template("tell me a joke about {topic}.")
103
+ model = ChatOpenAI(temperature=0.5)
103
104
 
104
- template = PromptTemplate.from_template("tell me a joke about {topic}.")
105
- model = ChatOpenAI(temperature=0.5)
105
+ # Good
106
+ chain = template | model.with_retry()
106
107
 
107
- # Good
108
- chain = template | model.with_retry()
109
-
110
- # Bad
111
- chain = template | model
112
- retryable_chain = chain.with_retry()
113
-
114
- """ # noqa: E501
108
+ # Bad
109
+ chain = template | model
110
+ retryable_chain = chain.with_retry()
111
+ ```
112
+ """
115
113
 
116
114
  retry_exception_types: tuple[type[BaseException], ...] = (Exception,)
117
115
  """The exception types to retry on. By default all exceptions are retried.
@@ -126,9 +124,9 @@ class RunnableRetry(RunnableBindingBase[Input, Output]):
126
124
  wait_exponential_jitter: bool = True
127
125
  """Whether to add jitter to the exponential backoff."""
128
126
 
129
- exponential_jitter_params: Optional[ExponentialJitterParams] = None
130
- """Parameters for ``tenacity.wait_exponential_jitter``. Namely: ``initial``,
131
- ``max``, ``exp_base``, and ``jitter`` (all float values).
127
+ exponential_jitter_params: ExponentialJitterParams | None = None
128
+ """Parameters for `tenacity.wait_exponential_jitter`. Namely: `initial`,
129
+ `max`, `exp_base`, and `jitter` (all `float` values).
132
130
  """
133
131
 
134
132
  max_attempt_number: int = 3
@@ -174,7 +172,8 @@ class RunnableRetry(RunnableBindingBase[Input, Output]):
174
172
  retry_state: RetryCallState,
175
173
  ) -> list[RunnableConfig]:
176
174
  return [
177
- self._patch_config(c, rm, retry_state) for c, rm in zip(config, run_manager)
175
+ self._patch_config(c, rm, retry_state)
176
+ for c, rm in zip(config, run_manager, strict=False)
178
177
  ]
179
178
 
180
179
  def _invoke(
@@ -197,7 +196,7 @@ class RunnableRetry(RunnableBindingBase[Input, Output]):
197
196
 
198
197
  @override
199
198
  def invoke(
200
- self, input: Input, config: Optional[RunnableConfig] = None, **kwargs: Any
199
+ self, input: Input, config: RunnableConfig | None = None, **kwargs: Any
201
200
  ) -> Output:
202
201
  return self._call_with_config(self._invoke, input, config, **kwargs)
203
202
 
@@ -221,7 +220,7 @@ class RunnableRetry(RunnableBindingBase[Input, Output]):
221
220
 
222
221
  @override
223
222
  async def ainvoke(
224
- self, input: Input, config: Optional[RunnableConfig] = None, **kwargs: Any
223
+ self, input: Input, config: RunnableConfig | None = None, **kwargs: Any
225
224
  ) -> Output:
226
225
  return await self._acall_with_config(self._ainvoke, input, config, **kwargs)
227
226
 
@@ -231,34 +230,43 @@ class RunnableRetry(RunnableBindingBase[Input, Output]):
231
230
  run_manager: list["CallbackManagerForChainRun"],
232
231
  config: list[RunnableConfig],
233
232
  **kwargs: Any,
234
- ) -> list[Union[Output, Exception]]:
233
+ ) -> list[Output | Exception]:
235
234
  results_map: dict[int, Output] = {}
236
235
 
237
- def pending(iterable: list[U]) -> list[U]:
238
- return [item for idx, item in enumerate(iterable) if idx not in results_map]
239
-
240
236
  not_set: list[Output] = []
241
237
  result = not_set
242
238
  try:
243
239
  for attempt in self._sync_retrying():
244
240
  with attempt:
245
- # Get the results of the inputs that have not succeeded yet.
241
+ # Retry for inputs that have not yet succeeded
242
+ # Determine which original indices remain.
243
+ remaining_indices = [
244
+ i for i in range(len(inputs)) if i not in results_map
245
+ ]
246
+ if not remaining_indices:
247
+ break
248
+ pending_inputs = [inputs[i] for i in remaining_indices]
249
+ pending_configs = [config[i] for i in remaining_indices]
250
+ pending_run_managers = [run_manager[i] for i in remaining_indices]
251
+ # Invoke underlying batch only on remaining elements.
246
252
  result = super().batch(
247
- pending(inputs),
253
+ pending_inputs,
248
254
  self._patch_config_list(
249
- pending(config), pending(run_manager), attempt.retry_state
255
+ pending_configs, pending_run_managers, attempt.retry_state
250
256
  ),
251
257
  return_exceptions=True,
252
258
  **kwargs,
253
259
  )
254
- # Register the results of the inputs that have succeeded.
260
+ # Register the results of the inputs that have succeeded, mapping
261
+ # back to their original indices.
255
262
  first_exception = None
256
- for i, r in enumerate(result):
263
+ for offset, r in enumerate(result):
257
264
  if isinstance(r, Exception):
258
265
  if not first_exception:
259
266
  first_exception = r
260
267
  continue
261
- results_map[i] = r
268
+ orig_idx = remaining_indices[offset]
269
+ results_map[orig_idx] = r
262
270
  # If any exception occurred, raise it, to retry the failed ones
263
271
  if first_exception:
264
272
  raise first_exception
@@ -271,7 +279,7 @@ class RunnableRetry(RunnableBindingBase[Input, Output]):
271
279
  if result is not_set:
272
280
  result = cast("list[Output]", [e] * len(inputs))
273
281
 
274
- outputs: list[Union[Output, Exception]] = []
282
+ outputs: list[Output | Exception] = []
275
283
  for idx in range(len(inputs)):
276
284
  if idx in results_map:
277
285
  outputs.append(results_map[idx])
@@ -283,7 +291,7 @@ class RunnableRetry(RunnableBindingBase[Input, Output]):
283
291
  def batch(
284
292
  self,
285
293
  inputs: list[Input],
286
- config: Optional[Union[RunnableConfig, list[RunnableConfig]]] = None,
294
+ config: RunnableConfig | list[RunnableConfig] | None = None,
287
295
  *,
288
296
  return_exceptions: bool = False,
289
297
  **kwargs: Any,
@@ -298,34 +306,42 @@ class RunnableRetry(RunnableBindingBase[Input, Output]):
298
306
  run_manager: list["AsyncCallbackManagerForChainRun"],
299
307
  config: list[RunnableConfig],
300
308
  **kwargs: Any,
301
- ) -> list[Union[Output, Exception]]:
309
+ ) -> list[Output | Exception]:
302
310
  results_map: dict[int, Output] = {}
303
311
 
304
- def pending(iterable: list[U]) -> list[U]:
305
- return [item for idx, item in enumerate(iterable) if idx not in results_map]
306
-
307
312
  not_set: list[Output] = []
308
313
  result = not_set
309
314
  try:
310
315
  async for attempt in self._async_retrying():
311
316
  with attempt:
312
- # Get the results of the inputs that have not succeeded yet.
317
+ # Retry for inputs that have not yet succeeded
318
+ # Determine which original indices remain.
319
+ remaining_indices = [
320
+ i for i in range(len(inputs)) if i not in results_map
321
+ ]
322
+ if not remaining_indices:
323
+ break
324
+ pending_inputs = [inputs[i] for i in remaining_indices]
325
+ pending_configs = [config[i] for i in remaining_indices]
326
+ pending_run_managers = [run_manager[i] for i in remaining_indices]
313
327
  result = await super().abatch(
314
- pending(inputs),
328
+ pending_inputs,
315
329
  self._patch_config_list(
316
- pending(config), pending(run_manager), attempt.retry_state
330
+ pending_configs, pending_run_managers, attempt.retry_state
317
331
  ),
318
332
  return_exceptions=True,
319
333
  **kwargs,
320
334
  )
321
- # Register the results of the inputs that have succeeded.
335
+ # Register the results of the inputs that have succeeded, mapping
336
+ # back to their original indices.
322
337
  first_exception = None
323
- for i, r in enumerate(result):
338
+ for offset, r in enumerate(result):
324
339
  if isinstance(r, Exception):
325
340
  if not first_exception:
326
341
  first_exception = r
327
342
  continue
328
- results_map[i] = r
343
+ orig_idx = remaining_indices[offset]
344
+ results_map[orig_idx] = r
329
345
  # If any exception occurred, raise it, to retry the failed ones
330
346
  if first_exception:
331
347
  raise first_exception
@@ -338,7 +354,7 @@ class RunnableRetry(RunnableBindingBase[Input, Output]):
338
354
  if result is not_set:
339
355
  result = cast("list[Output]", [e] * len(inputs))
340
356
 
341
- outputs: list[Union[Output, Exception]] = []
357
+ outputs: list[Output | Exception] = []
342
358
  for idx in range(len(inputs)):
343
359
  if idx in results_map:
344
360
  outputs.append(results_map[idx])
@@ -350,7 +366,7 @@ class RunnableRetry(RunnableBindingBase[Input, Output]):
350
366
  async def abatch(
351
367
  self,
352
368
  inputs: list[Input],
353
- config: Optional[Union[RunnableConfig, list[RunnableConfig]]] = None,
369
+ config: RunnableConfig | list[RunnableConfig] | None = None,
354
370
  *,
355
371
  return_exceptions: bool = False,
356
372
  **kwargs: Any,
@@ -2,13 +2,10 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from collections.abc import Mapping
5
+ from collections.abc import Callable, Mapping
6
6
  from typing import (
7
7
  TYPE_CHECKING,
8
8
  Any,
9
- Callable,
10
- Optional,
11
- Union,
12
9
  cast,
13
10
  )
14
11
 
@@ -38,15 +35,12 @@ if TYPE_CHECKING:
38
35
 
39
36
 
40
37
  class RouterInput(TypedDict):
41
- """Router input.
42
-
43
- Attributes:
44
- key: The key to route on.
45
- input: The input to pass to the selected Runnable.
46
- """
38
+ """Router input."""
47
39
 
48
40
  key: str
41
+ """The key to route on."""
49
42
  input: Any
43
+ """The input to pass to the selected Runnable."""
50
44
 
51
45
 
52
46
  class RouterRunnable(RunnableSerializable[RouterInput, Output]):
@@ -55,18 +49,16 @@ class RouterRunnable(RunnableSerializable[RouterInput, Output]):
55
49
  Returns the output of the selected Runnable.
56
50
 
57
51
  Example:
52
+ ```python
53
+ from langchain_core.runnables.router import RouterRunnable
54
+ from langchain_core.runnables import RunnableLambda
58
55
 
59
- .. code-block:: python
60
-
61
- from langchain_core.runnables.router import RouterRunnable
62
- from langchain_core.runnables import RunnableLambda
63
-
64
- add = RunnableLambda(func=lambda x: x + 1)
65
- square = RunnableLambda(func=lambda x: x**2)
66
-
67
- router = RouterRunnable(runnables={"add": add, "square": square})
68
- router.invoke({"key": "square", "input": 3})
56
+ add = RunnableLambda(func=lambda x: x + 1)
57
+ square = RunnableLambda(func=lambda x: x**2)
69
58
 
59
+ router = RouterRunnable(runnables={"add": add, "square": square})
60
+ router.invoke({"key": "square", "input": 3})
61
+ ```
70
62
  """
71
63
 
72
64
  runnables: Mapping[str, Runnable[Any, Output]]
@@ -80,14 +72,14 @@ class RouterRunnable(RunnableSerializable[RouterInput, Output]):
80
72
 
81
73
  def __init__(
82
74
  self,
83
- runnables: Mapping[str, Union[Runnable[Any, Output], Callable[[Any], Output]]],
75
+ runnables: Mapping[str, Runnable[Any, Output] | Callable[[Any], Output]],
84
76
  ) -> None:
85
77
  """Create a RouterRunnable.
86
78
 
87
79
  Args:
88
80
  runnables: A mapping of keys to Runnables.
89
81
  """
90
- super().__init__( # type: ignore[call-arg]
82
+ super().__init__(
91
83
  runnables={key: coerce_to_runnable(r) for key, r in runnables.items()}
92
84
  )
93
85
 
@@ -98,18 +90,22 @@ class RouterRunnable(RunnableSerializable[RouterInput, Output]):
98
90
  @classmethod
99
91
  @override
100
92
  def is_lc_serializable(cls) -> bool:
101
- """Return whether this class is serializable."""
93
+ """Return True as this class is serializable."""
102
94
  return True
103
95
 
104
96
  @classmethod
105
97
  @override
106
98
  def get_lc_namespace(cls) -> list[str]:
107
- """Get the namespace of the langchain object."""
99
+ """Get the namespace of the LangChain object.
100
+
101
+ Returns:
102
+ `["langchain", "schema", "runnable"]`
103
+ """
108
104
  return ["langchain", "schema", "runnable"]
109
105
 
110
106
  @override
111
107
  def invoke(
112
- self, input: RouterInput, config: Optional[RunnableConfig] = None, **kwargs: Any
108
+ self, input: RouterInput, config: RunnableConfig | None = None, **kwargs: Any
113
109
  ) -> Output:
114
110
  key = input["key"]
115
111
  actual_input = input["input"]
@@ -124,8 +120,8 @@ class RouterRunnable(RunnableSerializable[RouterInput, Output]):
124
120
  async def ainvoke(
125
121
  self,
126
122
  input: RouterInput,
127
- config: Optional[RunnableConfig] = None,
128
- **kwargs: Optional[Any],
123
+ config: RunnableConfig | None = None,
124
+ **kwargs: Any | None,
129
125
  ) -> Output:
130
126
  key = input["key"]
131
127
  actual_input = input["input"]
@@ -140,10 +136,10 @@ class RouterRunnable(RunnableSerializable[RouterInput, Output]):
140
136
  def batch(
141
137
  self,
142
138
  inputs: list[RouterInput],
143
- config: Optional[Union[RunnableConfig, list[RunnableConfig]]] = None,
139
+ config: RunnableConfig | list[RunnableConfig] | None = None,
144
140
  *,
145
141
  return_exceptions: bool = False,
146
- **kwargs: Optional[Any],
142
+ **kwargs: Any | None,
147
143
  ) -> list[Output]:
148
144
  if not inputs:
149
145
  return []
@@ -156,7 +152,7 @@ class RouterRunnable(RunnableSerializable[RouterInput, Output]):
156
152
 
157
153
  def invoke(
158
154
  runnable: Runnable, input_: Input, config: RunnableConfig
159
- ) -> Union[Output, Exception]:
155
+ ) -> Output | Exception:
160
156
  if return_exceptions:
161
157
  try:
162
158
  return runnable.invoke(input_, config, **kwargs)
@@ -177,10 +173,10 @@ class RouterRunnable(RunnableSerializable[RouterInput, Output]):
177
173
  async def abatch(
178
174
  self,
179
175
  inputs: list[RouterInput],
180
- config: Optional[Union[RunnableConfig, list[RunnableConfig]]] = None,
176
+ config: RunnableConfig | list[RunnableConfig] | None = None,
181
177
  *,
182
178
  return_exceptions: bool = False,
183
- **kwargs: Optional[Any],
179
+ **kwargs: Any | None,
184
180
  ) -> list[Output]:
185
181
  if not inputs:
186
182
  return []
@@ -193,7 +189,7 @@ class RouterRunnable(RunnableSerializable[RouterInput, Output]):
193
189
 
194
190
  async def ainvoke(
195
191
  runnable: Runnable, input_: Input, config: RunnableConfig
196
- ) -> Union[Output, Exception]:
192
+ ) -> Output | Exception:
197
193
  if return_exceptions:
198
194
  try:
199
195
  return await runnable.ainvoke(input_, config, **kwargs)
@@ -213,8 +209,8 @@ class RouterRunnable(RunnableSerializable[RouterInput, Output]):
213
209
  def stream(
214
210
  self,
215
211
  input: RouterInput,
216
- config: Optional[RunnableConfig] = None,
217
- **kwargs: Optional[Any],
212
+ config: RunnableConfig | None = None,
213
+ **kwargs: Any | None,
218
214
  ) -> Iterator[Output]:
219
215
  key = input["key"]
220
216
  actual_input = input["input"]
@@ -229,8 +225,8 @@ class RouterRunnable(RunnableSerializable[RouterInput, Output]):
229
225
  async def astream(
230
226
  self,
231
227
  input: RouterInput,
232
- config: Optional[RunnableConfig] = None,
233
- **kwargs: Optional[Any],
228
+ config: RunnableConfig | None = None,
229
+ **kwargs: Any | None,
234
230
  ) -> AsyncIterator[Output]:
235
231
  key = input["key"]
236
232
  actual_input = input["input"]