langchain-core 0.4.0.dev0__py3-none-any.whl → 1.0.0a2__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 (74) hide show
  1. langchain_core/_api/beta_decorator.py +2 -2
  2. langchain_core/_api/deprecation.py +1 -1
  3. langchain_core/beta/runnables/context.py +1 -1
  4. langchain_core/callbacks/base.py +14 -23
  5. langchain_core/callbacks/file.py +13 -2
  6. langchain_core/callbacks/manager.py +74 -157
  7. langchain_core/callbacks/streaming_stdout.py +3 -4
  8. langchain_core/callbacks/usage.py +2 -12
  9. langchain_core/chat_history.py +6 -6
  10. langchain_core/documents/base.py +1 -1
  11. langchain_core/documents/compressor.py +9 -6
  12. langchain_core/indexing/base.py +2 -2
  13. langchain_core/language_models/_utils.py +232 -101
  14. langchain_core/language_models/base.py +35 -23
  15. langchain_core/language_models/chat_models.py +248 -54
  16. langchain_core/language_models/fake_chat_models.py +28 -81
  17. langchain_core/load/dump.py +3 -4
  18. langchain_core/messages/__init__.py +30 -24
  19. langchain_core/messages/ai.py +188 -30
  20. langchain_core/messages/base.py +164 -25
  21. langchain_core/messages/block_translators/__init__.py +89 -0
  22. langchain_core/messages/block_translators/anthropic.py +451 -0
  23. langchain_core/messages/block_translators/bedrock.py +45 -0
  24. langchain_core/messages/block_translators/bedrock_converse.py +47 -0
  25. langchain_core/messages/block_translators/google_genai.py +45 -0
  26. langchain_core/messages/block_translators/google_vertexai.py +47 -0
  27. langchain_core/messages/block_translators/groq.py +45 -0
  28. langchain_core/messages/block_translators/langchain_v0.py +164 -0
  29. langchain_core/messages/block_translators/ollama.py +45 -0
  30. langchain_core/messages/block_translators/openai.py +798 -0
  31. langchain_core/messages/{content_blocks.py → content.py} +303 -278
  32. langchain_core/messages/human.py +29 -9
  33. langchain_core/messages/system.py +29 -9
  34. langchain_core/messages/tool.py +94 -13
  35. langchain_core/messages/utils.py +34 -234
  36. langchain_core/output_parsers/base.py +14 -50
  37. langchain_core/output_parsers/json.py +2 -5
  38. langchain_core/output_parsers/list.py +2 -7
  39. langchain_core/output_parsers/openai_functions.py +5 -28
  40. langchain_core/output_parsers/openai_tools.py +49 -90
  41. langchain_core/output_parsers/pydantic.py +2 -3
  42. langchain_core/output_parsers/transform.py +12 -53
  43. langchain_core/output_parsers/xml.py +9 -17
  44. langchain_core/prompt_values.py +8 -112
  45. langchain_core/prompts/chat.py +1 -3
  46. langchain_core/runnables/base.py +500 -451
  47. langchain_core/runnables/branch.py +1 -1
  48. langchain_core/runnables/fallbacks.py +4 -4
  49. langchain_core/runnables/history.py +1 -1
  50. langchain_core/runnables/passthrough.py +3 -3
  51. langchain_core/runnables/retry.py +1 -1
  52. langchain_core/runnables/router.py +1 -1
  53. langchain_core/structured_query.py +3 -7
  54. langchain_core/tools/base.py +14 -41
  55. langchain_core/tools/convert.py +2 -22
  56. langchain_core/tools/retriever.py +1 -8
  57. langchain_core/tools/structured.py +2 -10
  58. langchain_core/tracers/_streaming.py +6 -7
  59. langchain_core/tracers/base.py +7 -14
  60. langchain_core/tracers/core.py +4 -27
  61. langchain_core/tracers/event_stream.py +4 -15
  62. langchain_core/tracers/langchain.py +3 -14
  63. langchain_core/tracers/log_stream.py +2 -3
  64. langchain_core/utils/_merge.py +45 -7
  65. langchain_core/utils/function_calling.py +22 -9
  66. langchain_core/utils/utils.py +29 -0
  67. langchain_core/version.py +1 -1
  68. {langchain_core-0.4.0.dev0.dist-info → langchain_core-1.0.0a2.dist-info}/METADATA +7 -9
  69. {langchain_core-0.4.0.dev0.dist-info → langchain_core-1.0.0a2.dist-info}/RECORD +71 -64
  70. langchain_core/v1/__init__.py +0 -1
  71. langchain_core/v1/chat_models.py +0 -1047
  72. langchain_core/v1/messages.py +0 -755
  73. {langchain_core-0.4.0.dev0.dist-info → langchain_core-1.0.0a2.dist-info}/WHEEL +0 -0
  74. {langchain_core-0.4.0.dev0.dist-info → langchain_core-1.0.0a2.dist-info}/entry_points.txt +0 -0
@@ -2,11 +2,14 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from typing import TYPE_CHECKING, Any, Optional, Union, cast
5
+ from typing import TYPE_CHECKING, Any, Optional, Union, cast, overload
6
6
 
7
7
  from pydantic import ConfigDict, Field
8
+ from typing_extensions import Self
8
9
 
10
+ from langchain_core._api.deprecation import warn_deprecated
9
11
  from langchain_core.load.serializable import Serializable
12
+ from langchain_core.messages import content as types
10
13
  from langchain_core.utils import get_bolded_text
11
14
  from langchain_core.utils._merge import merge_dicts, merge_lists
12
15
  from langchain_core.utils.interactive_env import is_interactive_env
@@ -17,6 +20,52 @@ if TYPE_CHECKING:
17
20
  from langchain_core.prompts.chat import ChatPromptTemplate
18
21
 
19
22
 
23
+ class TextAccessor(str):
24
+ """String-like object that supports both property and method access patterns.
25
+
26
+ Exists to maintain backward compatibility while transitioning from method-based to
27
+ property-based text access in message objects. In LangChain <v1.0, message text was
28
+ accessed via ``.text()`` method calls. In v1.0=<, the preferred pattern is property
29
+ access via ``.text``.
30
+
31
+ Rather than breaking existing code immediately, ``TextAccessor`` allows both
32
+ patterns:
33
+ - Modern property access: ``message.text`` (returns string directly)
34
+ - Legacy method access: ``message.text()`` (callable, emits deprecation warning)
35
+
36
+ """
37
+
38
+ __slots__ = ()
39
+
40
+ def __new__(cls, value: str) -> Self:
41
+ """Create new TextAccessor instance."""
42
+ return str.__new__(cls, value)
43
+
44
+ def __call__(self) -> str:
45
+ """Enable method-style text access for backward compatibility.
46
+
47
+ This method exists solely to support legacy code that calls ``.text()``
48
+ as a method. New code should use property access (``.text``) instead.
49
+
50
+ .. deprecated:: 1.0.0
51
+ Calling ``.text()`` as a method is deprecated. Use ``.text`` as a property
52
+ instead. This method will be removed in 2.0.0.
53
+
54
+ Returns:
55
+ The string content, identical to property access.
56
+
57
+ """
58
+ warn_deprecated(
59
+ since="1.0.0",
60
+ message=(
61
+ "Calling .text() as a method is deprecated. "
62
+ "Use .text as a property instead (e.g., message.text)."
63
+ ),
64
+ removal="2.0.0",
65
+ )
66
+ return str(self)
67
+
68
+
20
69
  class BaseMessage(Serializable):
21
70
  """Base abstract message class.
22
71
 
@@ -61,15 +110,32 @@ class BaseMessage(Serializable):
61
110
  extra="allow",
62
111
  )
63
112
 
113
+ @overload
64
114
  def __init__(
65
- self, content: Union[str, list[Union[str, dict]]], **kwargs: Any
66
- ) -> None:
67
- """Pass in content as positional arg.
115
+ self,
116
+ content: Union[str, list[Union[str, dict]]],
117
+ **kwargs: Any,
118
+ ) -> None: ...
68
119
 
69
- Args:
70
- content: The string contents of the message.
71
- """
72
- super().__init__(content=content, **kwargs)
120
+ @overload
121
+ def __init__(
122
+ self,
123
+ content: Optional[Union[str, list[Union[str, dict]]]] = None,
124
+ content_blocks: Optional[list[types.ContentBlock]] = None,
125
+ **kwargs: Any,
126
+ ) -> None: ...
127
+
128
+ def __init__(
129
+ self,
130
+ content: Optional[Union[str, list[Union[str, dict]]]] = None,
131
+ content_blocks: Optional[list[types.ContentBlock]] = None,
132
+ **kwargs: Any,
133
+ ) -> None:
134
+ """Specify ``content`` as positional arg or ``content_blocks`` for typing."""
135
+ if content_blocks is not None:
136
+ super().__init__(content=content_blocks, **kwargs)
137
+ else:
138
+ super().__init__(content=content, **kwargs)
73
139
 
74
140
  @classmethod
75
141
  def is_lc_serializable(cls) -> bool:
@@ -88,25 +154,96 @@ class BaseMessage(Serializable):
88
154
  """
89
155
  return ["langchain", "schema", "messages"]
90
156
 
91
- def text(self) -> str:
92
- """Get the text content of the message.
157
+ @property
158
+ def content_blocks(self) -> list[types.ContentBlock]:
159
+ r"""Return ``content`` as a list of standardized :class:`~langchain_core.messages.content.ContentBlock`\s.
160
+
161
+ .. important::
162
+
163
+ To use this property correctly, the corresponding ``ChatModel`` must support
164
+ ``message_version='v1'`` or higher (and it must be set):
165
+
166
+ .. code-block:: python
167
+
168
+ from langchain.chat_models import init_chat_model
169
+ llm = init_chat_model("...", message_version="v1")
170
+
171
+ # or
172
+
173
+ from langchain-openai import ChatOpenAI
174
+ llm = ChatOpenAI(model="gpt-4o", message_version="v1")
175
+
176
+ Otherwise, the property will perform best-effort parsing to standard types,
177
+ though some content may be misinterpreted.
178
+
179
+ .. versionadded:: 1.0.0
180
+
181
+ """ # noqa: E501
182
+ from langchain_core.messages import content as types
183
+ from langchain_core.messages.block_translators.anthropic import (
184
+ _convert_to_v1_from_anthropic_input,
185
+ )
186
+ from langchain_core.messages.block_translators.langchain_v0 import (
187
+ _convert_v0_multimodal_input_to_v1,
188
+ )
189
+ from langchain_core.messages.block_translators.openai import (
190
+ _convert_to_v1_from_chat_completions_input,
191
+ )
192
+
193
+ blocks: list[types.ContentBlock] = []
194
+
195
+ # First pass: convert to standard blocks
196
+ content = (
197
+ [self.content]
198
+ if isinstance(self.content, str) and self.content
199
+ else self.content
200
+ )
201
+ for item in content:
202
+ if isinstance(item, str):
203
+ blocks.append({"type": "text", "text": item})
204
+ elif isinstance(item, dict):
205
+ item_type = item.get("type")
206
+ if item_type not in types.KNOWN_BLOCK_TYPES:
207
+ blocks.append({"type": "non_standard", "value": item})
208
+ else:
209
+ blocks.append(cast("types.ContentBlock", item))
210
+
211
+ # Subsequent passes: attempt to unpack non-standard blocks
212
+ for parsing_step in [
213
+ _convert_v0_multimodal_input_to_v1,
214
+ _convert_to_v1_from_chat_completions_input,
215
+ _convert_to_v1_from_anthropic_input,
216
+ ]:
217
+ blocks = parsing_step(blocks)
218
+ return blocks
219
+
220
+ @property
221
+ def text(self) -> TextAccessor:
222
+ """Get the text content of the message as a string.
223
+
224
+ Can be used as both property (``message.text``) and method (``message.text()``).
225
+
226
+ .. deprecated:: 1.0.0
227
+ Calling ``.text()`` as a method is deprecated. Use ``.text`` as a property
228
+ instead. This method will be removed in 2.0.0.
93
229
 
94
230
  Returns:
95
231
  The text content of the message.
96
232
  """
97
233
  if isinstance(self.content, str):
98
- return self.content
99
-
100
- # must be a list
101
- blocks = [
102
- block
103
- for block in self.content
104
- if isinstance(block, str)
105
- or (block.get("type") == "text" and isinstance(block.get("text"), str))
106
- ]
107
- return "".join(
108
- block if isinstance(block, str) else block["text"] for block in blocks
109
- )
234
+ text_value = self.content
235
+ else:
236
+ # must be a list
237
+ blocks = [
238
+ block
239
+ for block in self.content
240
+ if isinstance(block, str)
241
+ or (block.get("type") == "text" and isinstance(block.get("text"), str))
242
+ ]
243
+ text_value = "".join(
244
+ block if isinstance(block, str) else block["text"] for block in blocks
245
+ )
246
+ return TextAccessor(text_value)
110
247
 
111
248
  def __add__(self, other: Any) -> ChatPromptTemplate:
112
249
  """Concatenate this message with another message."""
@@ -152,7 +289,9 @@ def merge_content(
152
289
  Returns:
153
290
  The merged content.
154
291
  """
155
- merged = first_content
292
+ merged: Union[str, list[Union[str, dict]]]
293
+ merged = "" if first_content is None else first_content
294
+
156
295
  for content in contents:
157
296
  # If current is a string
158
297
  if isinstance(merged, str):
@@ -173,8 +312,8 @@ def merge_content(
173
312
  # If second content is an empty string, treat as a no-op
174
313
  elif content == "":
175
314
  pass
176
- else:
177
- # Otherwise, add the second content as a new element of the list
315
+ # Otherwise, add the second content as a new element of the list
316
+ elif merged:
178
317
  merged.append(content)
179
318
  return merged
180
319
 
@@ -0,0 +1,89 @@
1
+ """Derivations of standard content blocks from provider content."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import TYPE_CHECKING, Callable
6
+
7
+ if TYPE_CHECKING:
8
+ from langchain_core.messages import AIMessage, AIMessageChunk
9
+ from langchain_core.messages import content as types
10
+
11
+ # Provider to translator mapping
12
+ PROVIDER_TRANSLATORS: dict[str, dict[str, Callable[..., list[types.ContentBlock]]]] = {}
13
+
14
+
15
+ def register_translator(
16
+ provider: str,
17
+ translate_content: Callable[[AIMessage], list[types.ContentBlock]],
18
+ translate_content_chunk: Callable[[AIMessageChunk], list[types.ContentBlock]],
19
+ ) -> None:
20
+ """Register content translators for a provider.
21
+
22
+ Args:
23
+ provider: The model provider name (e.g. ``'openai'``, ``'anthropic'``).
24
+ translate_content: Function to translate ``AIMessage`` content.
25
+ translate_content_chunk: Function to translate ``AIMessageChunk`` content.
26
+ """
27
+ PROVIDER_TRANSLATORS[provider] = {
28
+ "translate_content": translate_content,
29
+ "translate_content_chunk": translate_content_chunk,
30
+ }
31
+
32
+
33
+ def get_translator(
34
+ provider: str,
35
+ ) -> dict[str, Callable[..., list[types.ContentBlock]]] | None:
36
+ """Get the translator functions for a provider.
37
+
38
+ Args:
39
+ provider: The model provider name.
40
+
41
+ Returns:
42
+ Dictionary with ``'translate_content'`` and ``'translate_content_chunk'``
43
+ functions, or None if no translator is registered for the provider.
44
+ """
45
+ return PROVIDER_TRANSLATORS.get(provider)
46
+
47
+
48
+ def _register_translators() -> None:
49
+ """Register all translators in langchain-core.
50
+
51
+ A unit test ensures all modules in ``block_translators`` are represented here.
52
+
53
+ For translators implemented outside langchain-core, they can be registered by
54
+ calling ``register_translator`` from within the integration package.
55
+ """
56
+ from langchain_core.messages.block_translators.anthropic import (
57
+ _register_anthropic_translator,
58
+ )
59
+ from langchain_core.messages.block_translators.bedrock import (
60
+ _register_bedrock_translator,
61
+ )
62
+ from langchain_core.messages.block_translators.bedrock_converse import (
63
+ _register_bedrock_converse_translator,
64
+ )
65
+ from langchain_core.messages.block_translators.google_genai import (
66
+ _register_google_genai_translator,
67
+ )
68
+ from langchain_core.messages.block_translators.google_vertexai import (
69
+ _register_google_vertexai_translator,
70
+ )
71
+ from langchain_core.messages.block_translators.groq import _register_groq_translator
72
+ from langchain_core.messages.block_translators.ollama import (
73
+ _register_ollama_translator,
74
+ )
75
+ from langchain_core.messages.block_translators.openai import (
76
+ _register_openai_translator,
77
+ )
78
+
79
+ _register_bedrock_translator()
80
+ _register_bedrock_converse_translator()
81
+ _register_anthropic_translator()
82
+ _register_google_genai_translator()
83
+ _register_google_vertexai_translator()
84
+ _register_groq_translator()
85
+ _register_ollama_translator()
86
+ _register_openai_translator()
87
+
88
+
89
+ _register_translators()