langchain-core 1.0.0rc3__py3-none-any.whl → 1.0.2__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 (76) hide show
  1. langchain_core/agents.py +2 -4
  2. langchain_core/caches.py +16 -7
  3. langchain_core/callbacks/base.py +0 -4
  4. langchain_core/callbacks/manager.py +0 -11
  5. langchain_core/chat_history.py +5 -5
  6. langchain_core/document_loaders/base.py +6 -4
  7. langchain_core/document_loaders/blob_loaders.py +1 -1
  8. langchain_core/document_loaders/langsmith.py +9 -13
  9. langchain_core/documents/__init__.py +24 -3
  10. langchain_core/documents/base.py +72 -61
  11. langchain_core/documents/compressor.py +6 -6
  12. langchain_core/documents/transformers.py +6 -6
  13. langchain_core/embeddings/fake.py +2 -2
  14. langchain_core/example_selectors/semantic_similarity.py +7 -7
  15. langchain_core/exceptions.py +2 -2
  16. langchain_core/indexing/__init__.py +1 -1
  17. langchain_core/indexing/api.py +62 -62
  18. langchain_core/indexing/base.py +20 -22
  19. langchain_core/indexing/in_memory.py +2 -4
  20. langchain_core/language_models/__init__.py +6 -5
  21. langchain_core/language_models/base.py +7 -8
  22. langchain_core/language_models/chat_models.py +84 -78
  23. langchain_core/language_models/fake_chat_models.py +1 -1
  24. langchain_core/language_models/llms.py +20 -18
  25. langchain_core/load/dump.py +6 -8
  26. langchain_core/load/serializable.py +4 -1
  27. langchain_core/messages/__init__.py +9 -0
  28. langchain_core/messages/ai.py +11 -7
  29. langchain_core/messages/base.py +4 -0
  30. langchain_core/messages/block_translators/google_genai.py +5 -3
  31. langchain_core/messages/content.py +4 -4
  32. langchain_core/messages/utils.py +17 -17
  33. langchain_core/output_parsers/__init__.py +17 -1
  34. langchain_core/output_parsers/base.py +3 -0
  35. langchain_core/output_parsers/format_instructions.py +9 -4
  36. langchain_core/output_parsers/json.py +5 -2
  37. langchain_core/output_parsers/list.py +16 -16
  38. langchain_core/output_parsers/openai_tools.py +2 -2
  39. langchain_core/output_parsers/pydantic.py +1 -1
  40. langchain_core/output_parsers/string.py +3 -3
  41. langchain_core/output_parsers/xml.py +28 -25
  42. langchain_core/outputs/generation.py +2 -3
  43. langchain_core/prompt_values.py +0 -6
  44. langchain_core/prompts/base.py +5 -3
  45. langchain_core/prompts/chat.py +60 -52
  46. langchain_core/prompts/string.py +5 -2
  47. langchain_core/prompts/structured.py +12 -8
  48. langchain_core/rate_limiters.py +1 -3
  49. langchain_core/retrievers.py +41 -37
  50. langchain_core/runnables/base.py +25 -29
  51. langchain_core/runnables/branch.py +9 -9
  52. langchain_core/runnables/config.py +2 -4
  53. langchain_core/runnables/configurable.py +3 -3
  54. langchain_core/runnables/fallbacks.py +1 -1
  55. langchain_core/runnables/graph.py +7 -3
  56. langchain_core/runnables/retry.py +1 -1
  57. langchain_core/runnables/schema.py +2 -5
  58. langchain_core/runnables/utils.py +3 -3
  59. langchain_core/stores.py +4 -6
  60. langchain_core/tools/base.py +68 -14
  61. langchain_core/tools/convert.py +8 -7
  62. langchain_core/tools/retriever.py +6 -5
  63. langchain_core/tools/structured.py +7 -5
  64. langchain_core/tracers/event_stream.py +4 -1
  65. langchain_core/tracers/log_stream.py +6 -3
  66. langchain_core/utils/function_calling.py +8 -0
  67. langchain_core/utils/json_schema.py +1 -1
  68. langchain_core/utils/strings.py +1 -4
  69. langchain_core/utils/utils.py +12 -5
  70. langchain_core/vectorstores/base.py +130 -130
  71. langchain_core/vectorstores/in_memory.py +4 -4
  72. langchain_core/vectorstores/utils.py +1 -1
  73. langchain_core/version.py +1 -1
  74. {langchain_core-1.0.0rc3.dist-info → langchain_core-1.0.2.dist-info}/METADATA +8 -7
  75. {langchain_core-1.0.0rc3.dist-info → langchain_core-1.0.2.dist-info}/RECORD +76 -76
  76. {langchain_core-1.0.0rc3.dist-info → langchain_core-1.0.2.dist-info}/WHEEL +0 -0
@@ -838,13 +838,13 @@ class BaseChatModel(BaseLanguageModel[AIMessage], ABC):
838
838
  1. Take advantage of batched calls,
839
839
  2. Need more output from the model than just the top generated value,
840
840
  3. Are building chains that are agnostic to the underlying language model
841
- type (e.g., pure text completion models vs chat models).
841
+ type (e.g., pure text completion models vs chat models).
842
842
 
843
843
  Args:
844
844
  messages: List of list of messages.
845
845
  stop: Stop words to use when generating. Model output is cut off at the
846
846
  first occurrence of any of these substrings.
847
- callbacks: Callbacks to pass through. Used for executing additional
847
+ callbacks: `Callbacks` to pass through. Used for executing additional
848
848
  functionality, such as logging or streaming, throughout generation.
849
849
  tags: The tags to apply.
850
850
  metadata: The metadata to apply.
@@ -854,8 +854,8 @@ class BaseChatModel(BaseLanguageModel[AIMessage], ABC):
854
854
  to the model provider API call.
855
855
 
856
856
  Returns:
857
- An LLMResult, which contains a list of candidate Generations for each input
858
- prompt and additional model provider-specific output.
857
+ An `LLMResult`, which contains a list of candidate `Generations` for each
858
+ input prompt and additional model provider-specific output.
859
859
 
860
860
  """
861
861
  ls_structured_output_format = kwargs.pop(
@@ -956,13 +956,13 @@ class BaseChatModel(BaseLanguageModel[AIMessage], ABC):
956
956
  1. Take advantage of batched calls,
957
957
  2. Need more output from the model than just the top generated value,
958
958
  3. Are building chains that are agnostic to the underlying language model
959
- type (e.g., pure text completion models vs chat models).
959
+ type (e.g., pure text completion models vs chat models).
960
960
 
961
961
  Args:
962
962
  messages: List of list of messages.
963
963
  stop: Stop words to use when generating. Model output is cut off at the
964
964
  first occurrence of any of these substrings.
965
- callbacks: Callbacks to pass through. Used for executing additional
965
+ callbacks: `Callbacks` to pass through. Used for executing additional
966
966
  functionality, such as logging or streaming, throughout generation.
967
967
  tags: The tags to apply.
968
968
  metadata: The metadata to apply.
@@ -972,8 +972,8 @@ class BaseChatModel(BaseLanguageModel[AIMessage], ABC):
972
972
  to the model provider API call.
973
973
 
974
974
  Returns:
975
- An LLMResult, which contains a list of candidate Generations for each input
976
- prompt and additional model provider-specific output.
975
+ An `LLMResult`, which contains a list of candidate `Generations` for each
976
+ input prompt and additional model provider-specific output.
977
977
 
978
978
  """
979
979
  ls_structured_output_format = kwargs.pop(
@@ -1510,17 +1510,21 @@ class BaseChatModel(BaseLanguageModel[AIMessage], ABC):
1510
1510
  If `schema` is a Pydantic class then the model output will be a
1511
1511
  Pydantic instance of that class, and the model-generated fields will be
1512
1512
  validated by the Pydantic class. Otherwise the model output will be a
1513
- dict and will not be validated. See `langchain_core.utils.function_calling.convert_to_openai_tool`
1514
- for more on how to properly specify types and descriptions of
1515
- schema fields when specifying a Pydantic or `TypedDict` class.
1513
+ dict and will not be validated.
1514
+
1515
+ See `langchain_core.utils.function_calling.convert_to_openai_tool` for
1516
+ more on how to properly specify types and descriptions of schema fields
1517
+ when specifying a Pydantic or `TypedDict` class.
1516
1518
 
1517
1519
  include_raw:
1518
1520
  If `False` then only the parsed structured output is returned. If
1519
1521
  an error occurs during model output parsing it will be raised. If `True`
1520
1522
  then both the raw model response (a `BaseMessage`) and the parsed model
1521
1523
  response will be returned. If an error occurs during output parsing it
1522
- will be caught and returned as well. The final output is always a dict
1523
- with keys `'raw'`, `'parsed'`, and `'parsing_error'`.
1524
+ will be caught and returned as well.
1525
+
1526
+ The final output is always a `dict` with keys `'raw'`, `'parsed'`, and
1527
+ `'parsing_error'`.
1524
1528
 
1525
1529
  Raises:
1526
1530
  ValueError: If there are any unsupported `kwargs`.
@@ -1528,97 +1532,99 @@ class BaseChatModel(BaseLanguageModel[AIMessage], ABC):
1528
1532
  `with_structured_output()`.
1529
1533
 
1530
1534
  Returns:
1531
- A Runnable that takes same inputs as a `langchain_core.language_models.chat.BaseChatModel`.
1535
+ A `Runnable` that takes same inputs as a
1536
+ `langchain_core.language_models.chat.BaseChatModel`. If `include_raw` is
1537
+ `False` and `schema` is a Pydantic class, `Runnable` outputs an instance
1538
+ of `schema` (i.e., a Pydantic object). Otherwise, if `include_raw` is
1539
+ `False` then `Runnable` outputs a `dict`.
1532
1540
 
1533
- If `include_raw` is False and `schema` is a Pydantic class, Runnable outputs
1534
- an instance of `schema` (i.e., a Pydantic object).
1541
+ If `include_raw` is `True`, then `Runnable` outputs a `dict` with keys:
1535
1542
 
1536
- Otherwise, if `include_raw` is False then Runnable outputs a dict.
1543
+ - `'raw'`: `BaseMessage`
1544
+ - `'parsed'`: `None` if there was a parsing error, otherwise the type
1545
+ depends on the `schema` as described above.
1546
+ - `'parsing_error'`: `BaseException | None`
1537
1547
 
1538
- If `include_raw` is True, then Runnable outputs a dict with keys:
1548
+ Example: Pydantic schema (`include_raw=False`):
1539
1549
 
1540
- - `'raw'`: BaseMessage
1541
- - `'parsed'`: None if there was a parsing error, otherwise the type
1542
- depends on the `schema` as described above.
1543
- - `'parsing_error'`: BaseException | None
1550
+ ```python
1551
+ from pydantic import BaseModel
1544
1552
 
1545
- Example: Pydantic schema (include_raw=False):
1546
- ```python
1547
- from pydantic import BaseModel
1548
1553
 
1554
+ class AnswerWithJustification(BaseModel):
1555
+ '''An answer to the user question along with justification for the answer.'''
1549
1556
 
1550
- class AnswerWithJustification(BaseModel):
1551
- '''An answer to the user question along with justification for the answer.'''
1557
+ answer: str
1558
+ justification: str
1552
1559
 
1553
- answer: str
1554
- justification: str
1555
1560
 
1561
+ model = ChatModel(model="model-name", temperature=0)
1562
+ structured_model = model.with_structured_output(AnswerWithJustification)
1556
1563
 
1557
- model = ChatModel(model="model-name", temperature=0)
1558
- structured_model = model.with_structured_output(AnswerWithJustification)
1564
+ structured_model.invoke(
1565
+ "What weighs more a pound of bricks or a pound of feathers"
1566
+ )
1559
1567
 
1560
- structured_model.invoke(
1561
- "What weighs more a pound of bricks or a pound of feathers"
1562
- )
1568
+ # -> AnswerWithJustification(
1569
+ # answer='They weigh the same',
1570
+ # justification='Both a pound of bricks and a pound of feathers weigh one pound. The weight is the same, but the volume or density of the objects may differ.'
1571
+ # )
1572
+ ```
1563
1573
 
1564
- # -> AnswerWithJustification(
1565
- # answer='They weigh the same',
1566
- # justification='Both a pound of bricks and a pound of feathers weigh one pound. The weight is the same, but the volume or density of the objects may differ.'
1567
- # )
1568
- ```
1574
+ Example: Pydantic schema (`include_raw=True`):
1569
1575
 
1570
- Example: Pydantic schema (include_raw=True):
1571
- ```python
1572
- from pydantic import BaseModel
1576
+ ```python
1577
+ from pydantic import BaseModel
1573
1578
 
1574
1579
 
1575
- class AnswerWithJustification(BaseModel):
1576
- '''An answer to the user question along with justification for the answer.'''
1580
+ class AnswerWithJustification(BaseModel):
1581
+ '''An answer to the user question along with justification for the answer.'''
1577
1582
 
1578
- answer: str
1579
- justification: str
1583
+ answer: str
1584
+ justification: str
1580
1585
 
1581
1586
 
1582
- model = ChatModel(model="model-name", temperature=0)
1583
- structured_model = model.with_structured_output(
1584
- AnswerWithJustification, include_raw=True
1585
- )
1587
+ model = ChatModel(model="model-name", temperature=0)
1588
+ structured_model = model.with_structured_output(
1589
+ AnswerWithJustification, include_raw=True
1590
+ )
1586
1591
 
1587
- structured_model.invoke(
1588
- "What weighs more a pound of bricks or a pound of feathers"
1589
- )
1590
- # -> {
1591
- # 'raw': AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_Ao02pnFYXD6GN1yzc0uXPsvF', 'function': {'arguments': '{"answer":"They weigh the same.","justification":"Both a pound of bricks and a pound of feathers weigh one pound. The weight is the same, but the volume or density of the objects may differ."}', 'name': 'AnswerWithJustification'}, 'type': 'function'}]}),
1592
- # 'parsed': AnswerWithJustification(answer='They weigh the same.', justification='Both a pound of bricks and a pound of feathers weigh one pound. The weight is the same, but the volume or density of the objects may differ.'),
1593
- # 'parsing_error': None
1594
- # }
1595
- ```
1592
+ structured_model.invoke(
1593
+ "What weighs more a pound of bricks or a pound of feathers"
1594
+ )
1595
+ # -> {
1596
+ # 'raw': AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_Ao02pnFYXD6GN1yzc0uXPsvF', 'function': {'arguments': '{"answer":"They weigh the same.","justification":"Both a pound of bricks and a pound of feathers weigh one pound. The weight is the same, but the volume or density of the objects may differ."}', 'name': 'AnswerWithJustification'}, 'type': 'function'}]}),
1597
+ # 'parsed': AnswerWithJustification(answer='They weigh the same.', justification='Both a pound of bricks and a pound of feathers weigh one pound. The weight is the same, but the volume or density of the objects may differ.'),
1598
+ # 'parsing_error': None
1599
+ # }
1600
+ ```
1596
1601
 
1597
- Example: Dict schema (include_raw=False):
1598
- ```python
1599
- from pydantic import BaseModel
1600
- from langchain_core.utils.function_calling import convert_to_openai_tool
1602
+ Example: `dict` schema (`include_raw=False`):
1601
1603
 
1604
+ ```python
1605
+ from pydantic import BaseModel
1606
+ from langchain_core.utils.function_calling import convert_to_openai_tool
1602
1607
 
1603
- class AnswerWithJustification(BaseModel):
1604
- '''An answer to the user question along with justification for the answer.'''
1605
1608
 
1606
- answer: str
1607
- justification: str
1609
+ class AnswerWithJustification(BaseModel):
1610
+ '''An answer to the user question along with justification for the answer.'''
1608
1611
 
1612
+ answer: str
1613
+ justification: str
1609
1614
 
1610
- dict_schema = convert_to_openai_tool(AnswerWithJustification)
1611
- model = ChatModel(model="model-name", temperature=0)
1612
- structured_model = model.with_structured_output(dict_schema)
1613
1615
 
1614
- structured_model.invoke(
1615
- "What weighs more a pound of bricks or a pound of feathers"
1616
- )
1617
- # -> {
1618
- # 'answer': 'They weigh the same',
1619
- # 'justification': 'Both a pound of bricks and a pound of feathers weigh one pound. The weight is the same, but the volume and density of the two substances differ.'
1620
- # }
1621
- ```
1616
+ dict_schema = convert_to_openai_tool(AnswerWithJustification)
1617
+ model = ChatModel(model="model-name", temperature=0)
1618
+ structured_model = model.with_structured_output(dict_schema)
1619
+
1620
+ structured_model.invoke(
1621
+ "What weighs more a pound of bricks or a pound of feathers"
1622
+ )
1623
+ # -> {
1624
+ # 'answer': 'They weigh the same',
1625
+ # 'justification': 'Both a pound of bricks and a pound of feathers weigh one pound. The weight is the same, but the volume and density of the two substances differ.'
1626
+ # }
1627
+ ```
1622
1628
 
1623
1629
  !!! warning "Behavior changed in 0.2.26"
1624
1630
  Added support for TypedDict class.
@@ -1,4 +1,4 @@
1
- """Fake chat model for testing purposes."""
1
+ """Fake chat models for testing purposes."""
2
2
 
3
3
  import asyncio
4
4
  import re
@@ -1,4 +1,7 @@
1
- """Base interface for large language models to expose."""
1
+ """Base interface for traditional large language models (LLMs) to expose.
2
+
3
+ These are traditionally older models (newer models generally are chat models).
4
+ """
2
5
 
3
6
  from __future__ import annotations
4
7
 
@@ -91,13 +94,17 @@ def create_base_retry_decorator(
91
94
  if isinstance(run_manager, AsyncCallbackManagerForLLMRun):
92
95
  coro = run_manager.on_retry(retry_state)
93
96
  try:
94
- loop = asyncio.get_event_loop()
95
- if loop.is_running():
96
- # TODO: Fix RUF006 - this task should have a reference
97
- # and be awaited somewhere
98
- loop.create_task(coro) # noqa: RUF006
99
- else:
97
+ try:
98
+ loop = asyncio.get_event_loop()
99
+ except RuntimeError:
100
100
  asyncio.run(coro)
101
+ else:
102
+ if loop.is_running():
103
+ # TODO: Fix RUF006 - this task should have a reference
104
+ # and be awaited somewhere
105
+ loop.create_task(coro) # noqa: RUF006
106
+ else:
107
+ asyncio.run(coro)
101
108
  except Exception as e:
102
109
  _log_error_once(f"Error in on_retry: {e}")
103
110
  else:
@@ -841,7 +848,7 @@ class BaseLLM(BaseLanguageModel[str], ABC):
841
848
  prompts: List of string prompts.
842
849
  stop: Stop words to use when generating. Model output is cut off at the
843
850
  first occurrence of any of these substrings.
844
- callbacks: Callbacks to pass through. Used for executing additional
851
+ callbacks: `Callbacks` to pass through. Used for executing additional
845
852
  functionality, such as logging or streaming, throughout generation.
846
853
  tags: List of tags to associate with each prompt. If provided, the length
847
854
  of the list must match the length of the prompts list.
@@ -861,8 +868,8 @@ class BaseLLM(BaseLanguageModel[str], ABC):
861
868
  `run_name` (if provided) does not match the length of prompts.
862
869
 
863
870
  Returns:
864
- An LLMResult, which contains a list of candidate Generations for each input
865
- prompt and additional model provider-specific output.
871
+ An `LLMResult`, which contains a list of candidate `Generations` for each
872
+ input prompt and additional model provider-specific output.
866
873
  """
867
874
  if not isinstance(prompts, list):
868
875
  msg = (
@@ -1111,7 +1118,7 @@ class BaseLLM(BaseLanguageModel[str], ABC):
1111
1118
  prompts: List of string prompts.
1112
1119
  stop: Stop words to use when generating. Model output is cut off at the
1113
1120
  first occurrence of any of these substrings.
1114
- callbacks: Callbacks to pass through. Used for executing additional
1121
+ callbacks: `Callbacks` to pass through. Used for executing additional
1115
1122
  functionality, such as logging or streaming, throughout generation.
1116
1123
  tags: List of tags to associate with each prompt. If provided, the length
1117
1124
  of the list must match the length of the prompts list.
@@ -1130,8 +1137,8 @@ class BaseLLM(BaseLanguageModel[str], ABC):
1130
1137
  `run_name` (if provided) does not match the length of prompts.
1131
1138
 
1132
1139
  Returns:
1133
- An LLMResult, which contains a list of candidate Generations for each input
1134
- prompt and additional model provider-specific output.
1140
+ An `LLMResult`, which contains a list of candidate `Generations` for each
1141
+ input prompt and additional model provider-specific output.
1135
1142
  """
1136
1143
  if isinstance(metadata, list):
1137
1144
  metadata = [
@@ -1387,11 +1394,6 @@ class LLM(BaseLLM):
1387
1394
  `astream` will use `_astream` if provided, otherwise it will implement
1388
1395
  a fallback behavior that will use `_stream` if `_stream` is implemented,
1389
1396
  and use `_acall` if `_stream` is not implemented.
1390
-
1391
- Please see the following guide for more information on how to
1392
- implement a custom LLM:
1393
-
1394
- https://python.langchain.com/docs/how_to/custom_llm/
1395
1397
  """
1396
1398
 
1397
1399
  @abstractmethod
@@ -17,7 +17,7 @@ def default(obj: Any) -> Any:
17
17
  obj: The object to serialize to json if it is a Serializable object.
18
18
 
19
19
  Returns:
20
- A json serializable object or a SerializedNotImplemented object.
20
+ A JSON serializable object or a SerializedNotImplemented object.
21
21
  """
22
22
  if isinstance(obj, Serializable):
23
23
  return obj.to_json()
@@ -38,7 +38,7 @@ def _dump_pydantic_models(obj: Any) -> Any:
38
38
 
39
39
 
40
40
  def dumps(obj: Any, *, pretty: bool = False, **kwargs: Any) -> str:
41
- """Return a json string representation of an object.
41
+ """Return a JSON string representation of an object.
42
42
 
43
43
  Args:
44
44
  obj: The object to dump.
@@ -47,7 +47,7 @@ def dumps(obj: Any, *, pretty: bool = False, **kwargs: Any) -> str:
47
47
  **kwargs: Additional arguments to pass to `json.dumps`
48
48
 
49
49
  Returns:
50
- A json string representation of the object.
50
+ A JSON string representation of the object.
51
51
 
52
52
  Raises:
53
53
  ValueError: If `default` is passed as a kwarg.
@@ -71,14 +71,12 @@ def dumps(obj: Any, *, pretty: bool = False, **kwargs: Any) -> str:
71
71
  def dumpd(obj: Any) -> Any:
72
72
  """Return a dict representation of an object.
73
73
 
74
- !!! note
75
- Unfortunately this function is not as efficient as it could be because it first
76
- dumps the object to a json string and then loads it back into a dictionary.
77
-
78
74
  Args:
79
75
  obj: The object to dump.
80
76
 
81
77
  Returns:
82
- dictionary that can be serialized to json using json.dumps
78
+ Dictionary that can be serialized to json using `json.dumps`.
83
79
  """
80
+ # Unfortunately this function is not as efficient as it could be because it first
81
+ # dumps the object to a json string and then loads it back into a dictionary.
84
82
  return json.loads(dumps(obj))
@@ -97,11 +97,14 @@ class Serializable(BaseModel, ABC):
97
97
  by default. This is to prevent accidental serialization of objects that should
98
98
  not be serialized.
99
99
  - `get_lc_namespace`: Get the namespace of the LangChain object.
100
+
100
101
  During deserialization, this namespace is used to identify
101
102
  the correct class to instantiate.
103
+
102
104
  Please see the `Reviver` class in `langchain_core.load.load` for more details.
103
105
  During deserialization an additional mapping is handle classes that have moved
104
106
  or been renamed across package versions.
107
+
105
108
  - `lc_secrets`: A map of constructor argument names to secret ids.
106
109
  - `lc_attributes`: List of additional attribute names that should be included
107
110
  as part of the serialized representation.
@@ -194,7 +197,7 @@ class Serializable(BaseModel, ABC):
194
197
  ValueError: If the class has deprecated attributes.
195
198
 
196
199
  Returns:
197
- A json serializable object or a `SerializedNotImplemented` object.
200
+ A JSON serializable object or a `SerializedNotImplemented` object.
198
201
  """
199
202
  if not self.is_lc_serializable():
200
203
  return self.to_json_not_implemented()
@@ -9,6 +9,9 @@ if TYPE_CHECKING:
9
9
  from langchain_core.messages.ai import (
10
10
  AIMessage,
11
11
  AIMessageChunk,
12
+ InputTokenDetails,
13
+ OutputTokenDetails,
14
+ UsageMetadata,
12
15
  )
13
16
  from langchain_core.messages.base import (
14
17
  BaseMessage,
@@ -87,10 +90,12 @@ __all__ = (
87
90
  "HumanMessage",
88
91
  "HumanMessageChunk",
89
92
  "ImageContentBlock",
93
+ "InputTokenDetails",
90
94
  "InvalidToolCall",
91
95
  "MessageLikeRepresentation",
92
96
  "NonStandardAnnotation",
93
97
  "NonStandardContentBlock",
98
+ "OutputTokenDetails",
94
99
  "PlainTextContentBlock",
95
100
  "ReasoningContentBlock",
96
101
  "RemoveMessage",
@@ -104,6 +109,7 @@ __all__ = (
104
109
  "ToolCallChunk",
105
110
  "ToolMessage",
106
111
  "ToolMessageChunk",
112
+ "UsageMetadata",
107
113
  "VideoContentBlock",
108
114
  "_message_from_dict",
109
115
  "convert_to_messages",
@@ -145,6 +151,7 @@ _dynamic_imports = {
145
151
  "HumanMessageChunk": "human",
146
152
  "NonStandardAnnotation": "content",
147
153
  "NonStandardContentBlock": "content",
154
+ "OutputTokenDetails": "ai",
148
155
  "PlainTextContentBlock": "content",
149
156
  "ReasoningContentBlock": "content",
150
157
  "RemoveMessage": "modifier",
@@ -154,12 +161,14 @@ _dynamic_imports = {
154
161
  "SystemMessage": "system",
155
162
  "SystemMessageChunk": "system",
156
163
  "ImageContentBlock": "content",
164
+ "InputTokenDetails": "ai",
157
165
  "InvalidToolCall": "tool",
158
166
  "TextContentBlock": "content",
159
167
  "ToolCall": "tool",
160
168
  "ToolCallChunk": "tool",
161
169
  "ToolMessage": "tool",
162
170
  "ToolMessageChunk": "tool",
171
+ "UsageMetadata": "ai",
163
172
  "VideoContentBlock": "content",
164
173
  "AnyMessage": "utils",
165
174
  "MessageLikeRepresentation": "utils",
@@ -48,10 +48,10 @@ class InputTokenDetails(TypedDict, total=False):
48
48
  }
49
49
  ```
50
50
 
51
- !!! version-added "Added in version 0.3.9"
52
-
53
51
  May also hold extra provider-specific keys.
54
52
 
53
+ !!! version-added "Added in version 0.3.9"
54
+
55
55
  """
56
56
 
57
57
  audio: int
@@ -83,6 +83,8 @@ class OutputTokenDetails(TypedDict, total=False):
83
83
  }
84
84
  ```
85
85
 
86
+ May also hold extra provider-specific keys.
87
+
86
88
  !!! version-added "Added in version 0.3.9"
87
89
 
88
90
  """
@@ -124,6 +126,10 @@ class UsageMetadata(TypedDict):
124
126
  !!! warning "Behavior changed in 0.3.9"
125
127
  Added `input_token_details` and `output_token_details`.
126
128
 
129
+ !!! note "LangSmith SDK"
130
+ The LangSmith SDK also has a `UsageMetadata` class. While the two share fields,
131
+ LangSmith's `UsageMetadata` has additional fields to capture cost information
132
+ used by the LangSmith platform.
127
133
  """
128
134
 
129
135
  input_tokens: int
@@ -131,7 +137,7 @@ class UsageMetadata(TypedDict):
131
137
  output_tokens: int
132
138
  """Count of output (or completion) tokens. Sum of all output token types."""
133
139
  total_tokens: int
134
- """Total token count. Sum of input_tokens + output_tokens."""
140
+ """Total token count. Sum of `input_tokens` + `output_tokens`."""
135
141
  input_token_details: NotRequired[InputTokenDetails]
136
142
  """Breakdown of input token counts.
137
143
 
@@ -141,7 +147,6 @@ class UsageMetadata(TypedDict):
141
147
  """Breakdown of output token counts.
142
148
 
143
149
  Does *not* need to sum to full output token count. Does *not* need to have all keys.
144
-
145
150
  """
146
151
 
147
152
 
@@ -153,7 +158,6 @@ class AIMessage(BaseMessage):
153
158
  This message represents the output of the model and consists of both
154
159
  the raw output as returned by the model and standardized fields
155
160
  (e.g., tool calls, usage metadata) added by the LangChain framework.
156
-
157
161
  """
158
162
 
159
163
  tool_calls: list[ToolCall] = []
@@ -651,13 +655,13 @@ def add_ai_message_chunks(
651
655
  chunk_id = id_
652
656
  break
653
657
  else:
654
- # second pass: prefer lc_run-* ids over lc_* ids
658
+ # second pass: prefer lc_run-* IDs over lc_* IDs
655
659
  for id_ in candidates:
656
660
  if id_ and id_.startswith(LC_ID_PREFIX):
657
661
  chunk_id = id_
658
662
  break
659
663
  else:
660
- # third pass: take any remaining id (auto-generated lc_* ids)
664
+ # third pass: take any remaining ID (auto-generated lc_* IDs)
661
665
  for id_ in candidates:
662
666
  if id_:
663
667
  chunk_id = id_
@@ -93,6 +93,10 @@ class BaseMessage(Serializable):
93
93
  """Base abstract message class.
94
94
 
95
95
  Messages are the inputs and outputs of a chat model.
96
+
97
+ Examples include [`HumanMessage`][langchain.messages.HumanMessage],
98
+ [`AIMessage`][langchain.messages.AIMessage], and
99
+ [`SystemMessage`][langchain.messages.SystemMessage].
96
100
  """
97
101
 
98
102
  content: str | list[str | dict]
@@ -282,7 +282,7 @@ def _convert_to_v1_from_genai(message: AIMessage) -> list[types.ContentBlock]:
282
282
  standard content blocks for returning.
283
283
 
284
284
  Args:
285
- message: The AIMessage or AIMessageChunk to convert.
285
+ message: The `AIMessage` or `AIMessageChunk` to convert.
286
286
 
287
287
  Returns:
288
288
  List of standard content blocks derived from the message content.
@@ -368,7 +368,7 @@ def _convert_to_v1_from_genai(message: AIMessage) -> list[types.ContentBlock]:
368
368
  else:
369
369
  # Assume it's raw base64 without data URI
370
370
  try:
371
- # Validate base64 and decode for mime type detection
371
+ # Validate base64 and decode for MIME type detection
372
372
  decoded_bytes = base64.b64decode(url, validate=True)
373
373
 
374
374
  image_url_b64_block = {
@@ -379,7 +379,7 @@ def _convert_to_v1_from_genai(message: AIMessage) -> list[types.ContentBlock]:
379
379
  try:
380
380
  import filetype # type: ignore[import-not-found] # noqa: PLC0415
381
381
 
382
- # Guess mime type based on file bytes
382
+ # Guess MIME type based on file bytes
383
383
  mime_type = None
384
384
  kind = filetype.guess(decoded_bytes)
385
385
  if kind:
@@ -458,6 +458,8 @@ def _convert_to_v1_from_genai(message: AIMessage) -> list[types.ContentBlock]:
458
458
  if outcome is not None:
459
459
  server_tool_result_block["extras"]["outcome"] = outcome
460
460
  converted_blocks.append(server_tool_result_block)
461
+ elif item_type == "text":
462
+ converted_blocks.append(cast("types.TextContentBlock", item))
461
463
  else:
462
464
  # Unknown type, preserve as non-standard
463
465
  converted_blocks.append({"type": "non_standard", "value": item})
@@ -644,7 +644,7 @@ class AudioContentBlock(TypedDict):
644
644
 
645
645
 
646
646
  class PlainTextContentBlock(TypedDict):
647
- """Plaintext data (e.g., from a document).
647
+ """Plaintext data (e.g., from a `.txt` or `.md` document).
648
648
 
649
649
  !!! note
650
650
  A `PlainTextContentBlock` existed in `langchain-core<1.0.0`. Although the
@@ -767,7 +767,7 @@ class FileContentBlock(TypedDict):
767
767
 
768
768
 
769
769
  class NonStandardContentBlock(TypedDict):
770
- """Provider-specific data.
770
+ """Provider-specific content data.
771
771
 
772
772
  This block contains data for which there is not yet a standard type.
773
773
 
@@ -802,7 +802,7 @@ class NonStandardContentBlock(TypedDict):
802
802
  """
803
803
 
804
804
  value: dict[str, Any]
805
- """Provider-specific data."""
805
+ """Provider-specific content data."""
806
806
 
807
807
  index: NotRequired[int | str]
808
808
  """Index of block in aggregate response. Used during streaming."""
@@ -1399,7 +1399,7 @@ def create_non_standard_block(
1399
1399
  """Create a `NonStandardContentBlock`.
1400
1400
 
1401
1401
  Args:
1402
- value: Provider-specific data.
1402
+ value: Provider-specific content data.
1403
1403
  id: Content block identifier. Generated automatically if not provided.
1404
1404
  index: Index of block in aggregate response. Used during streaming.
1405
1405