langchain-core 1.0.3__py3-none-any.whl → 1.0.4__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.
Files changed (40) hide show
  1. langchain_core/agents.py +36 -27
  2. langchain_core/callbacks/manager.py +18 -1
  3. langchain_core/callbacks/usage.py +2 -2
  4. langchain_core/documents/base.py +6 -6
  5. langchain_core/example_selectors/length_based.py +1 -1
  6. langchain_core/indexing/api.py +6 -6
  7. langchain_core/language_models/_utils.py +1 -1
  8. langchain_core/language_models/base.py +37 -18
  9. langchain_core/language_models/chat_models.py +44 -28
  10. langchain_core/language_models/llms.py +66 -36
  11. langchain_core/messages/ai.py +3 -3
  12. langchain_core/messages/base.py +1 -1
  13. langchain_core/messages/content.py +2 -2
  14. langchain_core/messages/utils.py +12 -8
  15. langchain_core/output_parsers/openai_tools.py +14 -2
  16. langchain_core/outputs/generation.py +6 -5
  17. langchain_core/prompt_values.py +2 -2
  18. langchain_core/prompts/base.py +47 -44
  19. langchain_core/prompts/chat.py +35 -28
  20. langchain_core/prompts/dict.py +1 -1
  21. langchain_core/prompts/message.py +4 -4
  22. langchain_core/runnables/base.py +97 -52
  23. langchain_core/runnables/branch.py +22 -20
  24. langchain_core/runnables/configurable.py +30 -29
  25. langchain_core/runnables/fallbacks.py +22 -20
  26. langchain_core/runnables/graph_mermaid.py +4 -1
  27. langchain_core/runnables/graph_png.py +28 -0
  28. langchain_core/runnables/history.py +43 -32
  29. langchain_core/runnables/passthrough.py +35 -25
  30. langchain_core/runnables/router.py +5 -5
  31. langchain_core/runnables/schema.py +1 -1
  32. langchain_core/sys_info.py +4 -2
  33. langchain_core/tools/base.py +22 -16
  34. langchain_core/utils/function_calling.py +9 -6
  35. langchain_core/utils/input.py +3 -0
  36. langchain_core/utils/pydantic.py +2 -2
  37. langchain_core/version.py +1 -1
  38. {langchain_core-1.0.3.dist-info → langchain_core-1.0.4.dist-info}/METADATA +1 -1
  39. {langchain_core-1.0.3.dist-info → langchain_core-1.0.4.dist-info}/RECORD +40 -40
  40. {langchain_core-1.0.3.dist-info → langchain_core-1.0.4.dist-info}/WHEEL +0 -0
@@ -587,14 +587,15 @@ class _StringImageMessagePromptTemplate(BaseMessagePromptTemplate):
587
587
  for prompt in self.prompt:
588
588
  inputs = {var: kwargs[var] for var in prompt.input_variables}
589
589
  if isinstance(prompt, StringPromptTemplate):
590
- formatted: str | ImageURL | dict[str, Any] = prompt.format(**inputs)
591
- content.append({"type": "text", "text": formatted})
590
+ formatted_text: str = prompt.format(**inputs)
591
+ if formatted_text != "":
592
+ content.append({"type": "text", "text": formatted_text})
592
593
  elif isinstance(prompt, ImagePromptTemplate):
593
- formatted = prompt.format(**inputs)
594
- content.append({"type": "image_url", "image_url": formatted})
594
+ formatted_image: ImageURL = prompt.format(**inputs)
595
+ content.append({"type": "image_url", "image_url": formatted_image})
595
596
  elif isinstance(prompt, DictPromptTemplate):
596
- formatted = prompt.format(**inputs)
597
- content.append(formatted)
597
+ formatted_dict: dict[str, Any] = prompt.format(**inputs)
598
+ content.append(formatted_dict)
598
599
  return self._msg_class(
599
600
  content=content, additional_kwargs=self.additional_kwargs
600
601
  )
@@ -617,16 +618,15 @@ class _StringImageMessagePromptTemplate(BaseMessagePromptTemplate):
617
618
  for prompt in self.prompt:
618
619
  inputs = {var: kwargs[var] for var in prompt.input_variables}
619
620
  if isinstance(prompt, StringPromptTemplate):
620
- formatted: str | ImageURL | dict[str, Any] = await prompt.aformat(
621
- **inputs
622
- )
623
- content.append({"type": "text", "text": formatted})
621
+ formatted_text: str = await prompt.aformat(**inputs)
622
+ if formatted_text != "":
623
+ content.append({"type": "text", "text": formatted_text})
624
624
  elif isinstance(prompt, ImagePromptTemplate):
625
- formatted = await prompt.aformat(**inputs)
626
- content.append({"type": "image_url", "image_url": formatted})
625
+ formatted_image: ImageURL = await prompt.aformat(**inputs)
626
+ content.append({"type": "image_url", "image_url": formatted_image})
627
627
  elif isinstance(prompt, DictPromptTemplate):
628
- formatted = prompt.format(**inputs)
629
- content.append(formatted)
628
+ formatted_dict: dict[str, Any] = prompt.format(**inputs)
629
+ content.append(formatted_dict)
630
630
  return self._msg_class(
631
631
  content=content, additional_kwargs=self.additional_kwargs
632
632
  )
@@ -1343,11 +1343,25 @@ def _create_template_from_message_type(
1343
1343
  raise ValueError(msg)
1344
1344
  var_name = template[1:-1]
1345
1345
  message = MessagesPlaceholder(variable_name=var_name, optional=True)
1346
- elif len(template) == 2 and isinstance(template[1], bool):
1347
- var_name_wrapped, is_optional = template
1346
+ else:
1347
+ try:
1348
+ var_name_wrapped, is_optional = template
1349
+ except ValueError as e:
1350
+ msg = (
1351
+ "Unexpected arguments for placeholder message type."
1352
+ " Expected either a single string variable name"
1353
+ " or a list of [variable_name: str, is_optional: bool]."
1354
+ f" Got: {template}"
1355
+ )
1356
+ raise ValueError(msg) from e
1357
+
1358
+ if not isinstance(is_optional, bool):
1359
+ msg = f"Expected is_optional to be a boolean. Got: {is_optional}"
1360
+ raise ValueError(msg) # noqa: TRY004
1361
+
1348
1362
  if not isinstance(var_name_wrapped, str):
1349
1363
  msg = f"Expected variable name to be a string. Got: {var_name_wrapped}"
1350
- raise ValueError(msg) # noqa:TRY004
1364
+ raise ValueError(msg) # noqa: TRY004
1351
1365
  if var_name_wrapped[0] != "{" or var_name_wrapped[-1] != "}":
1352
1366
  msg = (
1353
1367
  f"Invalid placeholder template: {var_name_wrapped}."
@@ -1357,14 +1371,6 @@ def _create_template_from_message_type(
1357
1371
  var_name = var_name_wrapped[1:-1]
1358
1372
 
1359
1373
  message = MessagesPlaceholder(variable_name=var_name, optional=is_optional)
1360
- else:
1361
- msg = (
1362
- "Unexpected arguments for placeholder message type."
1363
- " Expected either a single string variable name"
1364
- " or a list of [variable_name: str, is_optional: bool]."
1365
- f" Got: {template}"
1366
- )
1367
- raise ValueError(msg)
1368
1374
  else:
1369
1375
  msg = (
1370
1376
  f"Unexpected message type: {message_type}. Use one of 'human',"
@@ -1418,10 +1424,11 @@ def _convert_to_message_template(
1418
1424
  )
1419
1425
  raise ValueError(msg)
1420
1426
  message = (message["role"], message["content"])
1421
- if len(message) != 2:
1427
+ try:
1428
+ message_type_str, template = message
1429
+ except ValueError as e:
1422
1430
  msg = f"Expected 2-tuple of (role, template), got {message}"
1423
- raise ValueError(msg)
1424
- message_type_str, template = message
1431
+ raise ValueError(msg) from e
1425
1432
  if isinstance(message_type_str, str):
1426
1433
  message_ = _create_template_from_message_type(
1427
1434
  message_type_str, template, template_format=template_format
@@ -69,7 +69,7 @@ class DictPromptTemplate(RunnableSerializable[dict, dict]):
69
69
 
70
70
  @classmethod
71
71
  def is_lc_serializable(cls) -> bool:
72
- """Return True as this class is serializable."""
72
+ """Return `True` as this class is serializable."""
73
73
  return True
74
74
 
75
75
  @classmethod
@@ -18,7 +18,7 @@ class BaseMessagePromptTemplate(Serializable, ABC):
18
18
 
19
19
  @classmethod
20
20
  def is_lc_serializable(cls) -> bool:
21
- """Return True as this class is serializable."""
21
+ """Return `True` as this class is serializable."""
22
22
  return True
23
23
 
24
24
  @classmethod
@@ -32,13 +32,13 @@ class BaseMessagePromptTemplate(Serializable, ABC):
32
32
 
33
33
  @abstractmethod
34
34
  def format_messages(self, **kwargs: Any) -> list[BaseMessage]:
35
- """Format messages from kwargs. Should return a list of BaseMessages.
35
+ """Format messages from kwargs. Should return a list of `BaseMessage` objects.
36
36
 
37
37
  Args:
38
38
  **kwargs: Keyword arguments to use for formatting.
39
39
 
40
40
  Returns:
41
- List of BaseMessages.
41
+ List of `BaseMessage` objects.
42
42
  """
43
43
 
44
44
  async def aformat_messages(self, **kwargs: Any) -> list[BaseMessage]:
@@ -48,7 +48,7 @@ class BaseMessagePromptTemplate(Serializable, ABC):
48
48
  **kwargs: Keyword arguments to use for formatting.
49
49
 
50
50
  Returns:
51
- List of BaseMessages.
51
+ List of `BaseMessage` objects.
52
52
  """
53
53
  return self.format_messages(**kwargs)
54
54
 
@@ -118,6 +118,8 @@ if TYPE_CHECKING:
118
118
 
119
119
  Other = TypeVar("Other")
120
120
 
121
+ _RUNNABLE_GENERIC_NUM_ARGS = 2 # Input and Output
122
+
121
123
 
122
124
  class Runnable(ABC, Generic[Input, Output]):
123
125
  """A unit of work that can be invoked, batched, streamed, transformed and composed.
@@ -309,7 +311,10 @@ class Runnable(ABC, Generic[Input, Output]):
309
311
  for base in self.__class__.mro():
310
312
  if hasattr(base, "__pydantic_generic_metadata__"):
311
313
  metadata = base.__pydantic_generic_metadata__
312
- if "args" in metadata and len(metadata["args"]) == 2:
314
+ if (
315
+ "args" in metadata
316
+ and len(metadata["args"]) == _RUNNABLE_GENERIC_NUM_ARGS
317
+ ):
313
318
  return metadata["args"][0]
314
319
 
315
320
  # If we didn't find a Pydantic model in the parent classes,
@@ -317,7 +322,7 @@ class Runnable(ABC, Generic[Input, Output]):
317
322
  # Runnables that are not pydantic models.
318
323
  for cls in self.__class__.__orig_bases__: # type: ignore[attr-defined]
319
324
  type_args = get_args(cls)
320
- if type_args and len(type_args) == 2:
325
+ if type_args and len(type_args) == _RUNNABLE_GENERIC_NUM_ARGS:
321
326
  return type_args[0]
322
327
 
323
328
  msg = (
@@ -340,12 +345,15 @@ class Runnable(ABC, Generic[Input, Output]):
340
345
  for base in self.__class__.mro():
341
346
  if hasattr(base, "__pydantic_generic_metadata__"):
342
347
  metadata = base.__pydantic_generic_metadata__
343
- if "args" in metadata and len(metadata["args"]) == 2:
348
+ if (
349
+ "args" in metadata
350
+ and len(metadata["args"]) == _RUNNABLE_GENERIC_NUM_ARGS
351
+ ):
344
352
  return metadata["args"][1]
345
353
 
346
354
  for cls in self.__class__.__orig_bases__: # type: ignore[attr-defined]
347
355
  type_args = get_args(cls)
348
- if type_args and len(type_args) == 2:
356
+ if type_args and len(type_args) == _RUNNABLE_GENERIC_NUM_ARGS:
349
357
  return type_args[1]
350
358
 
351
359
  msg = (
@@ -424,7 +432,7 @@ class Runnable(ABC, Generic[Input, Output]):
424
432
  print(runnable.get_input_jsonschema())
425
433
  ```
426
434
 
427
- !!! version-added "Added in version 0.3.0"
435
+ !!! version-added "Added in `langchain-core` 0.3.0"
428
436
 
429
437
  """
430
438
  return self.get_input_schema(config).model_json_schema()
@@ -502,7 +510,7 @@ class Runnable(ABC, Generic[Input, Output]):
502
510
  print(runnable.get_output_jsonschema())
503
511
  ```
504
512
 
505
- !!! version-added "Added in version 0.3.0"
513
+ !!! version-added "Added in `langchain-core` 0.3.0"
506
514
 
507
515
  """
508
516
  return self.get_output_schema(config).model_json_schema()
@@ -566,7 +574,7 @@ class Runnable(ABC, Generic[Input, Output]):
566
574
  Returns:
567
575
  A JSON schema that represents the config of the `Runnable`.
568
576
 
569
- !!! version-added "Added in version 0.3.0"
577
+ !!! version-added "Added in `langchain-core` 0.3.0"
570
578
 
571
579
  """
572
580
  return self.config_schema(include=include).model_json_schema()
@@ -766,7 +774,7 @@ class Runnable(ABC, Generic[Input, Output]):
766
774
  """Assigns new fields to the `dict` output of this `Runnable`.
767
775
 
768
776
  ```python
769
- from langchain_community.llms.fake import FakeStreamingListLLM
777
+ from langchain_core.language_models.fake import FakeStreamingListLLM
770
778
  from langchain_core.output_parsers import StrOutputParser
771
779
  from langchain_core.prompts import SystemMessagePromptTemplate
772
780
  from langchain_core.runnables import Runnable
@@ -818,10 +826,12 @@ class Runnable(ABC, Generic[Input, Output]):
818
826
  Args:
819
827
  input: The input to the `Runnable`.
820
828
  config: A config to use when invoking the `Runnable`.
829
+
821
830
  The config supports standard keys like `'tags'`, `'metadata'` for
822
831
  tracing purposes, `'max_concurrency'` for controlling how much work to
823
- do in parallel, and other keys. Please refer to the `RunnableConfig`
824
- for more details.
832
+ do in parallel, and other keys.
833
+
834
+ Please refer to `RunnableConfig` for more details.
825
835
 
826
836
  Returns:
827
837
  The output of the `Runnable`.
@@ -838,10 +848,12 @@ class Runnable(ABC, Generic[Input, Output]):
838
848
  Args:
839
849
  input: The input to the `Runnable`.
840
850
  config: A config to use when invoking the `Runnable`.
851
+
841
852
  The config supports standard keys like `'tags'`, `'metadata'` for
842
853
  tracing purposes, `'max_concurrency'` for controlling how much work to
843
- do in parallel, and other keys. Please refer to the `RunnableConfig`
844
- for more details.
854
+ do in parallel, and other keys.
855
+
856
+ Please refer to `RunnableConfig` for more details.
845
857
 
846
858
  Returns:
847
859
  The output of the `Runnable`.
@@ -868,8 +880,9 @@ class Runnable(ABC, Generic[Input, Output]):
868
880
  config: A config to use when invoking the `Runnable`. The config supports
869
881
  standard keys like `'tags'`, `'metadata'` for
870
882
  tracing purposes, `'max_concurrency'` for controlling how much work
871
- to do in parallel, and other keys. Please refer to the
872
- `RunnableConfig` for more details.
883
+ to do in parallel, and other keys.
884
+
885
+ Please refer to `RunnableConfig` for more details.
873
886
  return_exceptions: Whether to return exceptions instead of raising them.
874
887
  **kwargs: Additional keyword arguments to pass to the `Runnable`.
875
888
 
@@ -932,10 +945,12 @@ class Runnable(ABC, Generic[Input, Output]):
932
945
  Args:
933
946
  inputs: A list of inputs to the `Runnable`.
934
947
  config: A config to use when invoking the `Runnable`.
948
+
935
949
  The config supports standard keys like `'tags'`, `'metadata'` for
936
950
  tracing purposes, `'max_concurrency'` for controlling how much work to
937
- do in parallel, and other keys. Please refer to the `RunnableConfig`
938
- for more details.
951
+ do in parallel, and other keys.
952
+
953
+ Please refer to `RunnableConfig` for more details.
939
954
  return_exceptions: Whether to return exceptions instead of raising them.
940
955
  **kwargs: Additional keyword arguments to pass to the `Runnable`.
941
956
 
@@ -998,10 +1013,12 @@ class Runnable(ABC, Generic[Input, Output]):
998
1013
  Args:
999
1014
  inputs: A list of inputs to the `Runnable`.
1000
1015
  config: A config to use when invoking the `Runnable`.
1016
+
1001
1017
  The config supports standard keys like `'tags'`, `'metadata'` for
1002
1018
  tracing purposes, `'max_concurrency'` for controlling how much work to
1003
- do in parallel, and other keys. Please refer to the `RunnableConfig`
1004
- for more details.
1019
+ do in parallel, and other keys.
1020
+
1021
+ Please refer to `RunnableConfig` for more details.
1005
1022
  return_exceptions: Whether to return exceptions instead of raising them.
1006
1023
  **kwargs: Additional keyword arguments to pass to the `Runnable`.
1007
1024
 
@@ -1061,10 +1078,12 @@ class Runnable(ABC, Generic[Input, Output]):
1061
1078
  Args:
1062
1079
  inputs: A list of inputs to the `Runnable`.
1063
1080
  config: A config to use when invoking the `Runnable`.
1081
+
1064
1082
  The config supports standard keys like `'tags'`, `'metadata'` for
1065
1083
  tracing purposes, `'max_concurrency'` for controlling how much work to
1066
- do in parallel, and other keys. Please refer to the `RunnableConfig`
1067
- for more details.
1084
+ do in parallel, and other keys.
1085
+
1086
+ Please refer to `RunnableConfig` for more details.
1068
1087
  return_exceptions: Whether to return exceptions instead of raising them.
1069
1088
  **kwargs: Additional keyword arguments to pass to the `Runnable`.
1070
1089
 
@@ -1742,46 +1761,52 @@ class Runnable(ABC, Generic[Input, Output]):
1742
1761
  import time
1743
1762
  import asyncio
1744
1763
 
1764
+
1745
1765
  def format_t(timestamp: float) -> str:
1746
1766
  return datetime.fromtimestamp(timestamp, tz=timezone.utc).isoformat()
1747
1767
 
1768
+
1748
1769
  async def test_runnable(time_to_sleep: int):
1749
1770
  print(f"Runnable[{time_to_sleep}s]: starts at {format_t(time.time())}")
1750
1771
  await asyncio.sleep(time_to_sleep)
1751
1772
  print(f"Runnable[{time_to_sleep}s]: ends at {format_t(time.time())}")
1752
1773
 
1774
+
1753
1775
  async def fn_start(run_obj: Runnable):
1754
1776
  print(f"on start callback starts at {format_t(time.time())}")
1755
1777
  await asyncio.sleep(3)
1756
1778
  print(f"on start callback ends at {format_t(time.time())}")
1757
1779
 
1780
+
1758
1781
  async def fn_end(run_obj: Runnable):
1759
1782
  print(f"on end callback starts at {format_t(time.time())}")
1760
1783
  await asyncio.sleep(2)
1761
1784
  print(f"on end callback ends at {format_t(time.time())}")
1762
1785
 
1786
+
1763
1787
  runnable = RunnableLambda(test_runnable).with_alisteners(
1764
- on_start=fn_start,
1765
- on_end=fn_end
1788
+ on_start=fn_start, on_end=fn_end
1766
1789
  )
1790
+
1791
+
1767
1792
  async def concurrent_runs():
1768
1793
  await asyncio.gather(runnable.ainvoke(2), runnable.ainvoke(3))
1769
1794
 
1770
- asyncio.run(concurrent_runs())
1771
- Result:
1772
- on start callback starts at 2025-03-01T07:05:22.875378+00:00
1773
- on start callback starts at 2025-03-01T07:05:22.875495+00:00
1774
- on start callback ends at 2025-03-01T07:05:25.878862+00:00
1775
- on start callback ends at 2025-03-01T07:05:25.878947+00:00
1776
- Runnable[2s]: starts at 2025-03-01T07:05:25.879392+00:00
1777
- Runnable[3s]: starts at 2025-03-01T07:05:25.879804+00:00
1778
- Runnable[2s]: ends at 2025-03-01T07:05:27.881998+00:00
1779
- on end callback starts at 2025-03-01T07:05:27.882360+00:00
1780
- Runnable[3s]: ends at 2025-03-01T07:05:28.881737+00:00
1781
- on end callback starts at 2025-03-01T07:05:28.882428+00:00
1782
- on end callback ends at 2025-03-01T07:05:29.883893+00:00
1783
- on end callback ends at 2025-03-01T07:05:30.884831+00:00
1784
1795
 
1796
+ asyncio.run(concurrent_runs())
1797
+ # Result:
1798
+ # on start callback starts at 2025-03-01T07:05:22.875378+00:00
1799
+ # on start callback starts at 2025-03-01T07:05:22.875495+00:00
1800
+ # on start callback ends at 2025-03-01T07:05:25.878862+00:00
1801
+ # on start callback ends at 2025-03-01T07:05:25.878947+00:00
1802
+ # Runnable[2s]: starts at 2025-03-01T07:05:25.879392+00:00
1803
+ # Runnable[3s]: starts at 2025-03-01T07:05:25.879804+00:00
1804
+ # Runnable[2s]: ends at 2025-03-01T07:05:27.881998+00:00
1805
+ # on end callback starts at 2025-03-01T07:05:27.882360+00:00
1806
+ # Runnable[3s]: ends at 2025-03-01T07:05:28.881737+00:00
1807
+ # on end callback starts at 2025-03-01T07:05:28.882428+00:00
1808
+ # on end callback ends at 2025-03-01T07:05:29.883893+00:00
1809
+ # on end callback ends at 2025-03-01T07:05:30.884831+00:00
1785
1810
  ```
1786
1811
  """
1787
1812
  return RunnableBinding(
@@ -1843,7 +1868,7 @@ class Runnable(ABC, Generic[Input, Output]):
1843
1868
  `exp_base`, and `jitter` (all `float` values).
1844
1869
 
1845
1870
  Returns:
1846
- A new Runnable that retries the original Runnable on exceptions.
1871
+ A new `Runnable` that retries the original `Runnable` on exceptions.
1847
1872
 
1848
1873
  Example:
1849
1874
  ```python
@@ -1927,7 +1952,9 @@ class Runnable(ABC, Generic[Input, Output]):
1927
1952
  exceptions_to_handle: A tuple of exception types to handle.
1928
1953
  exception_key: If `string` is specified then handled exceptions will be
1929
1954
  passed to fallbacks as part of the input under the specified key.
1955
+
1930
1956
  If `None`, exceptions will not be passed to fallbacks.
1957
+
1931
1958
  If used, the base `Runnable` and its fallbacks must accept a
1932
1959
  dictionary as input.
1933
1960
 
@@ -1963,7 +1990,9 @@ class Runnable(ABC, Generic[Input, Output]):
1963
1990
  exceptions_to_handle: A tuple of exception types to handle.
1964
1991
  exception_key: If `string` is specified then handled exceptions will be
1965
1992
  passed to fallbacks as part of the input under the specified key.
1993
+
1966
1994
  If `None`, exceptions will not be passed to fallbacks.
1995
+
1967
1996
  If used, the base `Runnable` and its fallbacks must accept a
1968
1997
  dictionary as input.
1969
1998
 
@@ -2429,10 +2458,14 @@ class Runnable(ABC, Generic[Input, Output]):
2429
2458
 
2430
2459
  `as_tool` will instantiate a `BaseTool` with a name, description, and
2431
2460
  `args_schema` from a `Runnable`. Where possible, schemas are inferred
2432
- from `runnable.get_input_schema`. Alternatively (e.g., if the
2433
- `Runnable` takes a dict as input and the specific dict keys are not typed),
2434
- the schema can be specified directly with `args_schema`. You can also
2435
- pass `arg_types` to just specify the required arguments and their types.
2461
+ from `runnable.get_input_schema`.
2462
+
2463
+ Alternatively (e.g., if the `Runnable` takes a dict as input and the specific
2464
+ `dict` keys are not typed), the schema can be specified directly with
2465
+ `args_schema`.
2466
+
2467
+ You can also pass `arg_types` to just specify the required arguments and their
2468
+ types.
2436
2469
 
2437
2470
  Args:
2438
2471
  args_schema: The schema for the tool.
@@ -2501,7 +2534,7 @@ class Runnable(ABC, Generic[Input, Output]):
2501
2534
  as_tool.invoke({"a": 3, "b": [1, 2]})
2502
2535
  ```
2503
2536
 
2504
- String input:
2537
+ `str` input:
2505
2538
 
2506
2539
  ```python
2507
2540
  from langchain_core.runnables import RunnableLambda
@@ -2750,6 +2783,9 @@ def _seq_output_schema(
2750
2783
  return last.get_output_schema(config)
2751
2784
 
2752
2785
 
2786
+ _RUNNABLE_SEQUENCE_MIN_STEPS = 2
2787
+
2788
+
2753
2789
  class RunnableSequence(RunnableSerializable[Input, Output]):
2754
2790
  """Sequence of `Runnable` objects, where the output of one is the input of the next.
2755
2791
 
@@ -2859,7 +2895,7 @@ class RunnableSequence(RunnableSerializable[Input, Output]):
2859
2895
  name: The name of the `Runnable`.
2860
2896
  first: The first `Runnable` in the sequence.
2861
2897
  middle: The middle `Runnable` objects in the sequence.
2862
- last: The last Runnable in the sequence.
2898
+ last: The last `Runnable` in the sequence.
2863
2899
 
2864
2900
  Raises:
2865
2901
  ValueError: If the sequence has less than 2 steps.
@@ -2872,8 +2908,11 @@ class RunnableSequence(RunnableSerializable[Input, Output]):
2872
2908
  steps_flat.extend(step.steps)
2873
2909
  else:
2874
2910
  steps_flat.append(coerce_to_runnable(step))
2875
- if len(steps_flat) < 2:
2876
- msg = f"RunnableSequence must have at least 2 steps, got {len(steps_flat)}"
2911
+ if len(steps_flat) < _RUNNABLE_SEQUENCE_MIN_STEPS:
2912
+ msg = (
2913
+ f"RunnableSequence must have at least {_RUNNABLE_SEQUENCE_MIN_STEPS} "
2914
+ f"steps, got {len(steps_flat)}"
2915
+ )
2877
2916
  raise ValueError(msg)
2878
2917
  super().__init__(
2879
2918
  first=steps_flat[0],
@@ -2904,7 +2943,7 @@ class RunnableSequence(RunnableSerializable[Input, Output]):
2904
2943
  @classmethod
2905
2944
  @override
2906
2945
  def is_lc_serializable(cls) -> bool:
2907
- """Return True as this class is serializable."""
2946
+ """Return `True` as this class is serializable."""
2908
2947
  return True
2909
2948
 
2910
2949
  model_config = ConfigDict(
@@ -3610,7 +3649,7 @@ class RunnableParallel(RunnableSerializable[Input, dict[str, Any]]):
3610
3649
  @classmethod
3611
3650
  @override
3612
3651
  def is_lc_serializable(cls) -> bool:
3613
- """Return True as this class is serializable."""
3652
+ """Return `True` as this class is serializable."""
3614
3653
  return True
3615
3654
 
3616
3655
  @classmethod
@@ -3668,6 +3707,12 @@ class RunnableParallel(RunnableSerializable[Input, dict[str, Any]]):
3668
3707
  == "object"
3669
3708
  for s in self.steps__.values()
3670
3709
  ):
3710
+ for step in self.steps__.values():
3711
+ fields = step.get_input_schema(config).model_fields
3712
+ root_field = fields.get("root")
3713
+ if root_field is not None and root_field.annotation != Any:
3714
+ return super().get_input_schema(config)
3715
+
3671
3716
  # This is correct, but pydantic typings/mypy don't think so.
3672
3717
  return create_model_v2(
3673
3718
  self.get_name("Input"),
@@ -4477,7 +4522,7 @@ class RunnableLambda(Runnable[Input, Output]):
4477
4522
  # on itemgetter objects, so we have to parse the repr
4478
4523
  items = str(func).replace("operator.itemgetter(", "")[:-1].split(", ")
4479
4524
  if all(
4480
- item[0] == "'" and item[-1] == "'" and len(item) > 2 for item in items
4525
+ item[0] == "'" and item[-1] == "'" and item != "''" for item in items
4481
4526
  ):
4482
4527
  fields = {item[1:-1]: (Any, ...) for item in items}
4483
4528
  # It's a dict, lol
@@ -5139,7 +5184,7 @@ class RunnableEachBase(RunnableSerializable[list[Input], list[Output]]):
5139
5184
  @classmethod
5140
5185
  @override
5141
5186
  def is_lc_serializable(cls) -> bool:
5142
- """Return True as this class is serializable."""
5187
+ """Return `True` as this class is serializable."""
5143
5188
  return True
5144
5189
 
5145
5190
  @classmethod
@@ -5322,7 +5367,7 @@ class RunnableEach(RunnableEachBase[Input, Output]):
5322
5367
 
5323
5368
 
5324
5369
  class RunnableBindingBase(RunnableSerializable[Input, Output]): # type: ignore[no-redef]
5325
- """`Runnable` that delegates calls to another `Runnable` with a set of kwargs.
5370
+ """`Runnable` that delegates calls to another `Runnable` with a set of `**kwargs`.
5326
5371
 
5327
5372
  Use only if creating a new `RunnableBinding` subclass with different `__init__`
5328
5373
  args.
@@ -5462,7 +5507,7 @@ class RunnableBindingBase(RunnableSerializable[Input, Output]): # type: ignore[
5462
5507
  @classmethod
5463
5508
  @override
5464
5509
  def is_lc_serializable(cls) -> bool:
5465
- """Return True as this class is serializable."""
5510
+ """Return `True` as this class is serializable."""
5466
5511
  return True
5467
5512
 
5468
5513
  @classmethod
@@ -5752,7 +5797,7 @@ class RunnableBinding(RunnableBindingBase[Input, Output]): # type: ignore[no-re
5752
5797
  ```python
5753
5798
  # Create a Runnable binding that invokes the chat model with the
5754
5799
  # additional kwarg `stop=['-']` when running it.
5755
- from langchain_community.chat_models import ChatOpenAI
5800
+ from langchain_openai import ChatOpenAI
5756
5801
 
5757
5802
  model = ChatOpenAI()
5758
5803
  model.invoke('Say "Parrot-MAGIC"', stop=["-"]) # Should return `Parrot`
@@ -36,11 +36,13 @@ from langchain_core.runnables.utils import (
36
36
  get_unique_config_specs,
37
37
  )
38
38
 
39
+ _MIN_BRANCHES = 2
40
+
39
41
 
40
42
  class RunnableBranch(RunnableSerializable[Input, Output]):
41
- """Runnable that selects which branch to run based on a condition.
43
+ """`Runnable` that selects which branch to run based on a condition.
42
44
 
43
- The Runnable is initialized with a list of `(condition, Runnable)` pairs and
45
+ The `Runnable` is initialized with a list of `(condition, Runnable)` pairs and
44
46
  a default branch.
45
47
 
46
48
  When operating on an input, the first condition that evaluates to True is
@@ -86,12 +88,12 @@ class RunnableBranch(RunnableSerializable[Input, Output]):
86
88
  Defaults a `Runnable` to run if no condition is met.
87
89
 
88
90
  Raises:
89
- ValueError: If the number of branches is less than 2.
91
+ ValueError: If the number of branches is less than `2`.
90
92
  TypeError: If the default branch is not `Runnable`, `Callable` or `Mapping`.
91
- TypeError: If a branch is not a tuple or list.
92
- ValueError: If a branch is not of length 2.
93
+ TypeError: If a branch is not a `tuple` or `list`.
94
+ ValueError: If a branch is not of length `2`.
93
95
  """
94
- if len(branches) < 2:
96
+ if len(branches) < _MIN_BRANCHES:
95
97
  msg = "RunnableBranch requires at least two branches"
96
98
  raise ValueError(msg)
97
99
 
@@ -118,7 +120,7 @@ class RunnableBranch(RunnableSerializable[Input, Output]):
118
120
  )
119
121
  raise TypeError(msg)
120
122
 
121
- if len(branch) != 2:
123
+ if len(branch) != _MIN_BRANCHES:
122
124
  msg = (
123
125
  f"RunnableBranch branches must be "
124
126
  f"tuples or lists of length 2, not {len(branch)}"
@@ -140,7 +142,7 @@ class RunnableBranch(RunnableSerializable[Input, Output]):
140
142
 
141
143
  @classmethod
142
144
  def is_lc_serializable(cls) -> bool:
143
- """Return True as this class is serializable."""
145
+ """Return `True` as this class is serializable."""
144
146
  return True
145
147
 
146
148
  @classmethod
@@ -187,12 +189,12 @@ class RunnableBranch(RunnableSerializable[Input, Output]):
187
189
  def invoke(
188
190
  self, input: Input, config: RunnableConfig | None = None, **kwargs: Any
189
191
  ) -> Output:
190
- """First evaluates the condition, then delegate to true or false branch.
192
+ """First evaluates the condition, then delegate to `True` or `False` branch.
191
193
 
192
194
  Args:
193
- input: The input to the Runnable.
194
- config: The configuration for the Runnable.
195
- **kwargs: Additional keyword arguments to pass to the Runnable.
195
+ input: The input to the `Runnable`.
196
+ config: The configuration for the `Runnable`.
197
+ **kwargs: Additional keyword arguments to pass to the `Runnable`.
196
198
 
197
199
  Returns:
198
200
  The output of the branch that was run.
@@ -297,12 +299,12 @@ class RunnableBranch(RunnableSerializable[Input, Output]):
297
299
  config: RunnableConfig | None = None,
298
300
  **kwargs: Any | None,
299
301
  ) -> Iterator[Output]:
300
- """First evaluates the condition, then delegate to true or false branch.
302
+ """First evaluates the condition, then delegate to `True` or `False` branch.
301
303
 
302
304
  Args:
303
- input: The input to the Runnable.
304
- config: The configuration for the Runnable.
305
- **kwargs: Additional keyword arguments to pass to the Runnable.
305
+ input: The input to the `Runnable`.
306
+ config: The configuration for the Runna`ble.
307
+ **kwargs: Additional keyword arguments to pass to the `Runnable`.
306
308
 
307
309
  Yields:
308
310
  The output of the branch that was run.
@@ -381,12 +383,12 @@ class RunnableBranch(RunnableSerializable[Input, Output]):
381
383
  config: RunnableConfig | None = None,
382
384
  **kwargs: Any | None,
383
385
  ) -> AsyncIterator[Output]:
384
- """First evaluates the condition, then delegate to true or false branch.
386
+ """First evaluates the condition, then delegate to `True` or `False` branch.
385
387
 
386
388
  Args:
387
- input: The input to the Runnable.
388
- config: The configuration for the Runnable.
389
- **kwargs: Additional keyword arguments to pass to the Runnable.
389
+ input: The input to the `Runnable`.
390
+ config: The configuration for the `Runnable`.
391
+ **kwargs: Additional keyword arguments to pass to the `Runnable`.
390
392
 
391
393
  Yields:
392
394
  The output of the branch that was run.