langchain-core 1.0.0a8__py3-none-any.whl → 1.0.0rc1__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 (135) hide show
  1. langchain_core/__init__.py +1 -1
  2. langchain_core/_api/__init__.py +0 -1
  3. langchain_core/_api/beta_decorator.py +17 -20
  4. langchain_core/_api/deprecation.py +30 -35
  5. langchain_core/_import_utils.py +1 -1
  6. langchain_core/agents.py +7 -6
  7. langchain_core/caches.py +4 -10
  8. langchain_core/callbacks/__init__.py +1 -8
  9. langchain_core/callbacks/base.py +232 -243
  10. langchain_core/callbacks/file.py +33 -33
  11. langchain_core/callbacks/manager.py +353 -416
  12. langchain_core/callbacks/stdout.py +21 -22
  13. langchain_core/callbacks/streaming_stdout.py +32 -32
  14. langchain_core/callbacks/usage.py +54 -51
  15. langchain_core/chat_history.py +42 -57
  16. langchain_core/document_loaders/langsmith.py +21 -21
  17. langchain_core/documents/__init__.py +0 -1
  18. langchain_core/documents/base.py +37 -40
  19. langchain_core/documents/transformers.py +28 -29
  20. langchain_core/embeddings/fake.py +46 -52
  21. langchain_core/exceptions.py +5 -5
  22. langchain_core/indexing/api.py +11 -11
  23. langchain_core/indexing/base.py +24 -24
  24. langchain_core/language_models/__init__.py +0 -2
  25. langchain_core/language_models/_utils.py +51 -53
  26. langchain_core/language_models/base.py +23 -24
  27. langchain_core/language_models/chat_models.py +121 -144
  28. langchain_core/language_models/fake_chat_models.py +5 -5
  29. langchain_core/language_models/llms.py +10 -12
  30. langchain_core/load/dump.py +1 -1
  31. langchain_core/load/load.py +16 -16
  32. langchain_core/load/serializable.py +35 -34
  33. langchain_core/messages/__init__.py +1 -16
  34. langchain_core/messages/ai.py +105 -104
  35. langchain_core/messages/base.py +26 -26
  36. langchain_core/messages/block_translators/__init__.py +17 -17
  37. langchain_core/messages/block_translators/anthropic.py +2 -2
  38. langchain_core/messages/block_translators/bedrock_converse.py +2 -2
  39. langchain_core/messages/block_translators/google_genai.py +2 -2
  40. langchain_core/messages/block_translators/groq.py +117 -21
  41. langchain_core/messages/block_translators/langchain_v0.py +2 -2
  42. langchain_core/messages/block_translators/openai.py +4 -4
  43. langchain_core/messages/chat.py +1 -1
  44. langchain_core/messages/content.py +189 -193
  45. langchain_core/messages/function.py +5 -5
  46. langchain_core/messages/human.py +15 -17
  47. langchain_core/messages/modifier.py +1 -1
  48. langchain_core/messages/system.py +12 -14
  49. langchain_core/messages/tool.py +45 -49
  50. langchain_core/messages/utils.py +384 -396
  51. langchain_core/output_parsers/__init__.py +1 -14
  52. langchain_core/output_parsers/base.py +22 -23
  53. langchain_core/output_parsers/json.py +3 -3
  54. langchain_core/output_parsers/list.py +1 -1
  55. langchain_core/output_parsers/openai_functions.py +46 -44
  56. langchain_core/output_parsers/openai_tools.py +7 -7
  57. langchain_core/output_parsers/pydantic.py +10 -11
  58. langchain_core/output_parsers/string.py +1 -1
  59. langchain_core/output_parsers/transform.py +2 -2
  60. langchain_core/output_parsers/xml.py +1 -1
  61. langchain_core/outputs/__init__.py +1 -1
  62. langchain_core/outputs/chat_generation.py +14 -14
  63. langchain_core/outputs/generation.py +5 -5
  64. langchain_core/outputs/llm_result.py +5 -5
  65. langchain_core/prompt_values.py +5 -5
  66. langchain_core/prompts/__init__.py +3 -23
  67. langchain_core/prompts/base.py +32 -37
  68. langchain_core/prompts/chat.py +216 -222
  69. langchain_core/prompts/dict.py +2 -2
  70. langchain_core/prompts/few_shot.py +76 -83
  71. langchain_core/prompts/few_shot_with_templates.py +6 -8
  72. langchain_core/prompts/image.py +11 -13
  73. langchain_core/prompts/loading.py +1 -1
  74. langchain_core/prompts/message.py +2 -2
  75. langchain_core/prompts/prompt.py +14 -16
  76. langchain_core/prompts/string.py +19 -7
  77. langchain_core/prompts/structured.py +24 -25
  78. langchain_core/rate_limiters.py +36 -38
  79. langchain_core/retrievers.py +41 -182
  80. langchain_core/runnables/base.py +565 -590
  81. langchain_core/runnables/branch.py +7 -7
  82. langchain_core/runnables/config.py +37 -44
  83. langchain_core/runnables/configurable.py +8 -9
  84. langchain_core/runnables/fallbacks.py +8 -8
  85. langchain_core/runnables/graph.py +28 -27
  86. langchain_core/runnables/graph_ascii.py +19 -18
  87. langchain_core/runnables/graph_mermaid.py +20 -31
  88. langchain_core/runnables/graph_png.py +7 -7
  89. langchain_core/runnables/history.py +20 -20
  90. langchain_core/runnables/passthrough.py +8 -8
  91. langchain_core/runnables/retry.py +3 -3
  92. langchain_core/runnables/router.py +1 -1
  93. langchain_core/runnables/schema.py +33 -33
  94. langchain_core/runnables/utils.py +30 -34
  95. langchain_core/stores.py +72 -102
  96. langchain_core/sys_info.py +27 -29
  97. langchain_core/tools/__init__.py +1 -14
  98. langchain_core/tools/base.py +63 -63
  99. langchain_core/tools/convert.py +92 -92
  100. langchain_core/tools/render.py +9 -9
  101. langchain_core/tools/retriever.py +1 -1
  102. langchain_core/tools/simple.py +6 -7
  103. langchain_core/tools/structured.py +17 -18
  104. langchain_core/tracers/__init__.py +1 -9
  105. langchain_core/tracers/base.py +35 -35
  106. langchain_core/tracers/context.py +12 -17
  107. langchain_core/tracers/event_stream.py +3 -3
  108. langchain_core/tracers/langchain.py +8 -8
  109. langchain_core/tracers/log_stream.py +17 -18
  110. langchain_core/tracers/memory_stream.py +2 -2
  111. langchain_core/tracers/schemas.py +0 -129
  112. langchain_core/utils/aiter.py +31 -31
  113. langchain_core/utils/env.py +5 -5
  114. langchain_core/utils/function_calling.py +48 -120
  115. langchain_core/utils/html.py +4 -4
  116. langchain_core/utils/input.py +2 -2
  117. langchain_core/utils/interactive_env.py +1 -1
  118. langchain_core/utils/iter.py +19 -19
  119. langchain_core/utils/json.py +1 -1
  120. langchain_core/utils/json_schema.py +2 -2
  121. langchain_core/utils/mustache.py +5 -5
  122. langchain_core/utils/pydantic.py +17 -17
  123. langchain_core/utils/strings.py +4 -4
  124. langchain_core/utils/utils.py +25 -28
  125. langchain_core/vectorstores/base.py +43 -64
  126. langchain_core/vectorstores/in_memory.py +83 -85
  127. langchain_core/version.py +1 -1
  128. {langchain_core-1.0.0a8.dist-info → langchain_core-1.0.0rc1.dist-info}/METADATA +23 -11
  129. langchain_core-1.0.0rc1.dist-info/RECORD +172 -0
  130. langchain_core/memory.py +0 -120
  131. langchain_core/pydantic_v1/__init__.py +0 -30
  132. langchain_core/pydantic_v1/dataclasses.py +0 -23
  133. langchain_core/pydantic_v1/main.py +0 -23
  134. langchain_core-1.0.0a8.dist-info/RECORD +0 -176
  135. {langchain_core-1.0.0a8.dist-info → langchain_core-1.0.0rc1.dist-info}/WHEEL +0 -0
@@ -1,13 +1,13 @@
1
1
  """Derivations of standard content blocks from provider content.
2
2
 
3
- ``AIMessage`` will first attempt to use a provider-specific translator if
4
- ``model_provider`` is set in ``response_metadata`` on the message. Consequently, each
3
+ `AIMessage` will first attempt to use a provider-specific translator if
4
+ `model_provider` is set in `response_metadata` on the message. Consequently, each
5
5
  provider translator must handle all possible content response types from the provider,
6
6
  including text.
7
7
 
8
8
  If no provider is set, or if the provider does not have a registered translator,
9
- ``AIMessage`` will fall back to best-effort parsing of the content into blocks using
10
- the implementation in ``BaseMessage``.
9
+ `AIMessage` will fall back to best-effort parsing of the content into blocks using
10
+ the implementation in `BaseMessage`.
11
11
  """
12
12
 
13
13
  from __future__ import annotations
@@ -23,15 +23,15 @@ if TYPE_CHECKING:
23
23
  PROVIDER_TRANSLATORS: dict[str, dict[str, Callable[..., list[types.ContentBlock]]]] = {}
24
24
  """Map model provider names to translator functions.
25
25
 
26
- The dictionary maps provider names (e.g. ``'openai'``, ``'anthropic'``) to another
26
+ The dictionary maps provider names (e.g. `'openai'`, `'anthropic'`) to another
27
27
  dictionary with two keys:
28
- - ``'translate_content'``: Function to translate ``AIMessage`` content.
29
- - ``'translate_content_chunk'``: Function to translate ``AIMessageChunk`` content.
28
+ - `'translate_content'`: Function to translate `AIMessage` content.
29
+ - `'translate_content_chunk'`: Function to translate `AIMessageChunk` content.
30
30
 
31
- When calling `.content_blocks` on an ``AIMessage`` or ``AIMessageChunk``, if
32
- ``model_provider`` is set in ``response_metadata``, the corresponding translator
31
+ When calling `.content_blocks` on an `AIMessage` or `AIMessageChunk`, if
32
+ `model_provider` is set in `response_metadata`, the corresponding translator
33
33
  functions will be used to parse the content into blocks. Otherwise, best-effort parsing
34
- in ``BaseMessage`` will be used.
34
+ in `BaseMessage` will be used.
35
35
  """
36
36
 
37
37
 
@@ -43,9 +43,9 @@ def register_translator(
43
43
  """Register content translators for a provider in `PROVIDER_TRANSLATORS`.
44
44
 
45
45
  Args:
46
- provider: The model provider name (e.g. ``'openai'``, ``'anthropic'``).
47
- translate_content: Function to translate ``AIMessage`` content.
48
- translate_content_chunk: Function to translate ``AIMessageChunk`` content.
46
+ provider: The model provider name (e.g. `'openai'`, `'anthropic'`).
47
+ translate_content: Function to translate `AIMessage` content.
48
+ translate_content_chunk: Function to translate `AIMessageChunk` content.
49
49
  """
50
50
  PROVIDER_TRANSLATORS[provider] = {
51
51
  "translate_content": translate_content,
@@ -62,9 +62,9 @@ def get_translator(
62
62
  provider: The model provider name.
63
63
 
64
64
  Returns:
65
- Dictionary with ``'translate_content'`` and ``'translate_content_chunk'``
65
+ Dictionary with `'translate_content'` and `'translate_content_chunk'`
66
66
  functions, or None if no translator is registered for the provider. In such
67
- case, best-effort parsing in ``BaseMessage`` will be used.
67
+ case, best-effort parsing in `BaseMessage` will be used.
68
68
  """
69
69
  return PROVIDER_TRANSLATORS.get(provider)
70
70
 
@@ -72,10 +72,10 @@ def get_translator(
72
72
  def _register_translators() -> None:
73
73
  """Register all translators in langchain-core.
74
74
 
75
- A unit test ensures all modules in ``block_translators`` are represented here.
75
+ A unit test ensures all modules in `block_translators` are represented here.
76
76
 
77
77
  For translators implemented outside langchain-core, they can be registered by
78
- calling ``register_translator`` from within the integration package.
78
+ calling `register_translator` from within the integration package.
79
79
  """
80
80
  from langchain_core.messages.block_translators.anthropic import ( # noqa: PLC0415
81
81
  _register_anthropic_translator,
@@ -32,11 +32,11 @@ def _convert_to_v1_from_anthropic_input(
32
32
  """Convert Anthropic format blocks to v1 format.
33
33
 
34
34
  During the `.content_blocks` parsing process, we wrap blocks not recognized as a v1
35
- block as a ``'non_standard'`` block with the original block stored in the ``value``
35
+ block as a `'non_standard'` block with the original block stored in the `value`
36
36
  field. This function attempts to unpack those blocks and convert any blocks that
37
37
  might be Anthropic format to v1 ContentBlocks.
38
38
 
39
- If conversion fails, the block is left as a ``'non_standard'`` block.
39
+ If conversion fails, the block is left as a `'non_standard'` block.
40
40
 
41
41
  Args:
42
42
  content: List of content blocks to process.
@@ -36,11 +36,11 @@ def _convert_to_v1_from_converse_input(
36
36
  """Convert Bedrock Converse format blocks to v1 format.
37
37
 
38
38
  During the `.content_blocks` parsing process, we wrap blocks not recognized as a v1
39
- block as a ``'non_standard'`` block with the original block stored in the ``value``
39
+ block as a `'non_standard'` block with the original block stored in the `value`
40
40
  field. This function attempts to unpack those blocks and convert any blocks that
41
41
  might be Converse format to v1 ContentBlocks.
42
42
 
43
- If conversion fails, the block is left as a ``'non_standard'`` block.
43
+ If conversion fails, the block is left as a `'non_standard'` block.
44
44
 
45
45
  Args:
46
46
  content: List of content blocks to process.
@@ -106,11 +106,11 @@ def _convert_to_v1_from_genai_input(
106
106
  `response_metadata`.
107
107
 
108
108
  During the `.content_blocks` parsing process, we wrap blocks not recognized as a v1
109
- block as a ``'non_standard'`` block with the original block stored in the ``value``
109
+ block as a `'non_standard'` block with the original block stored in the `value`
110
110
  field. This function attempts to unpack those blocks and convert any blocks that
111
111
  might be GenAI format to v1 ContentBlocks.
112
112
 
113
- If conversion fails, the block is left as a ``'non_standard'`` block.
113
+ If conversion fails, the block is left as a `'non_standard'` block.
114
114
 
115
115
  Args:
116
116
  content: List of content blocks to process.
@@ -1,39 +1,135 @@
1
1
  """Derivations of standard content blocks from Groq content."""
2
2
 
3
- import warnings
3
+ import json
4
+ import re
5
+ from typing import Any
4
6
 
5
7
  from langchain_core.messages import AIMessage, AIMessageChunk
6
8
  from langchain_core.messages import content as types
9
+ from langchain_core.messages.base import _extract_reasoning_from_additional_kwargs
7
10
 
8
- WARNED = False
9
11
 
12
+ def _populate_extras(
13
+ standard_block: types.ContentBlock, block: dict[str, Any], known_fields: set[str]
14
+ ) -> types.ContentBlock:
15
+ """Mutate a block, populating extras."""
16
+ if standard_block.get("type") == "non_standard":
17
+ return standard_block
10
18
 
11
- def translate_content(message: AIMessage) -> list[types.ContentBlock]: # noqa: ARG001
12
- """Derive standard content blocks from a message with Groq content."""
13
- global WARNED # noqa: PLW0603
14
- if not WARNED:
15
- warning_message = (
16
- "Content block standardization is not yet fully supported for Groq."
19
+ for key, value in block.items():
20
+ if key not in known_fields:
21
+ if "extras" not in standard_block:
22
+ # Below type-ignores are because mypy thinks a non-standard block can
23
+ # get here, although we exclude them above.
24
+ standard_block["extras"] = {} # type: ignore[typeddict-unknown-key]
25
+ standard_block["extras"][key] = value # type: ignore[typeddict-item]
26
+
27
+ return standard_block
28
+
29
+
30
+ def _parse_code_json(s: str) -> dict:
31
+ """Extract Python code from Groq built-in tool content.
32
+
33
+ Extracts the value of the 'code' field from a string of the form:
34
+ {"code": some_arbitrary_text_with_unescaped_quotes}
35
+
36
+ As Groq may not escape quotes in the executed tools, e.g.:
37
+ ```
38
+ '{"code": "import math; print("The square root of 101 is: "); print(math.sqrt(101))"}'
39
+ ```
40
+ """ # noqa: E501
41
+ m = re.fullmatch(r'\s*\{\s*"code"\s*:\s*"(.*)"\s*\}\s*', s, flags=re.DOTALL)
42
+ if not m:
43
+ msg = (
44
+ "Could not extract Python code from Groq tool arguments. "
45
+ "Expected a JSON object with a 'code' field."
17
46
  )
18
- warnings.warn(warning_message, stacklevel=2)
19
- WARNED = True
20
- raise NotImplementedError
47
+ raise ValueError(msg)
48
+ return {"code": m.group(1)}
49
+
50
+
51
+ def _convert_to_v1_from_groq(message: AIMessage) -> list[types.ContentBlock]:
52
+ """Convert groq message content to v1 format."""
53
+ content_blocks: list[types.ContentBlock] = []
21
54
 
55
+ if reasoning_block := _extract_reasoning_from_additional_kwargs(message):
56
+ content_blocks.append(reasoning_block)
22
57
 
23
- def translate_content_chunk(message: AIMessageChunk) -> list[types.ContentBlock]: # noqa: ARG001
24
- """Derive standard content blocks from a message chunk with Groq content."""
25
- global WARNED # noqa: PLW0603
26
- if not WARNED:
27
- warning_message = (
28
- "Content block standardization is not yet fully supported for Groq."
58
+ if executed_tools := message.additional_kwargs.get("executed_tools"):
59
+ for idx, executed_tool in enumerate(executed_tools):
60
+ args: dict[str, Any] | None = None
61
+ if arguments := executed_tool.get("arguments"):
62
+ try:
63
+ args = json.loads(arguments)
64
+ except json.JSONDecodeError:
65
+ if executed_tool.get("type") == "python":
66
+ try:
67
+ args = _parse_code_json(arguments)
68
+ except ValueError:
69
+ continue
70
+ elif (
71
+ executed_tool.get("type") == "function"
72
+ and executed_tool.get("name") == "python"
73
+ ):
74
+ # GPT-OSS
75
+ args = {"code": arguments}
76
+ else:
77
+ continue
78
+ if isinstance(args, dict):
79
+ name = ""
80
+ if executed_tool.get("type") == "search":
81
+ name = "web_search"
82
+ elif executed_tool.get("type") == "python" or (
83
+ executed_tool.get("type") == "function"
84
+ and executed_tool.get("name") == "python"
85
+ ):
86
+ name = "code_interpreter"
87
+ server_tool_call: types.ServerToolCall = {
88
+ "type": "server_tool_call",
89
+ "name": name,
90
+ "id": str(idx),
91
+ "args": args,
92
+ }
93
+ content_blocks.append(server_tool_call)
94
+ if tool_output := executed_tool.get("output"):
95
+ tool_result: types.ServerToolResult = {
96
+ "type": "server_tool_result",
97
+ "tool_call_id": str(idx),
98
+ "output": tool_output,
99
+ "status": "success",
100
+ }
101
+ known_fields = {"type", "arguments", "index", "output"}
102
+ _populate_extras(tool_result, executed_tool, known_fields)
103
+ content_blocks.append(tool_result)
104
+
105
+ if isinstance(message.content, str) and message.content:
106
+ content_blocks.append({"type": "text", "text": message.content})
107
+
108
+ for tool_call in message.tool_calls:
109
+ content_blocks.append( # noqa: PERF401
110
+ {
111
+ "type": "tool_call",
112
+ "name": tool_call["name"],
113
+ "args": tool_call["args"],
114
+ "id": tool_call.get("id"),
115
+ }
29
116
  )
30
- warnings.warn(warning_message, stacklevel=2)
31
- WARNED = True
32
- raise NotImplementedError
117
+
118
+ return content_blocks
119
+
120
+
121
+ def translate_content(message: AIMessage) -> list[types.ContentBlock]:
122
+ """Derive standard content blocks from a message with groq content."""
123
+ return _convert_to_v1_from_groq(message)
124
+
125
+
126
+ def translate_content_chunk(message: AIMessageChunk) -> list[types.ContentBlock]:
127
+ """Derive standard content blocks from a message chunk with groq content."""
128
+ return _convert_to_v1_from_groq(message)
33
129
 
34
130
 
35
131
  def _register_groq_translator() -> None:
36
- """Register the Groq translator with the central registry.
132
+ """Register the groq translator with the central registry.
37
133
 
38
134
  Run automatically when the module is imported.
39
135
  """
@@ -11,11 +11,11 @@ def _convert_v0_multimodal_input_to_v1(
11
11
  """Convert v0 multimodal blocks to v1 format.
12
12
 
13
13
  During the `.content_blocks` parsing process, we wrap blocks not recognized as a v1
14
- block as a ``'non_standard'`` block with the original block stored in the ``value``
14
+ block as a `'non_standard'` block with the original block stored in the `value`
15
15
  field. This function attempts to unpack those blocks and convert any v0 format
16
16
  blocks to v1 format.
17
17
 
18
- If conversion fails, the block is left as a ``'non_standard'`` block.
18
+ If conversion fails, the block is left as a `'non_standard'` block.
19
19
 
20
20
  Args:
21
21
  content: List of content blocks to process.
@@ -18,7 +18,7 @@ if TYPE_CHECKING:
18
18
 
19
19
 
20
20
  def convert_to_openai_image_block(block: dict[str, Any]) -> dict:
21
- """Convert ``ImageContentBlock`` to format expected by OpenAI Chat Completions."""
21
+ """Convert `ImageContentBlock` to format expected by OpenAI Chat Completions."""
22
22
  if "url" in block:
23
23
  return {
24
24
  "type": "image_url",
@@ -156,11 +156,11 @@ def _convert_to_v1_from_chat_completions_input(
156
156
  """Convert OpenAI Chat Completions format blocks to v1 format.
157
157
 
158
158
  During the `.content_blocks` parsing process, we wrap blocks not recognized as a v1
159
- block as a ``'non_standard'`` block with the original block stored in the ``value``
159
+ block as a `'non_standard'` block with the original block stored in the `value`
160
160
  field. This function attempts to unpack those blocks and convert any blocks that
161
161
  might be OpenAI format to v1 ContentBlocks.
162
162
 
163
- If conversion fails, the block is left as a ``'non_standard'`` block.
163
+ If conversion fails, the block is left as a `'non_standard'` block.
164
164
 
165
165
  Args:
166
166
  content: List of content blocks to process.
@@ -263,7 +263,7 @@ _FUNCTION_CALL_IDS_MAP_KEY = "__openai_function_call_ids__"
263
263
 
264
264
 
265
265
  def _convert_from_v03_ai_message(message: AIMessage) -> AIMessage:
266
- """Convert v0 AIMessage into ``output_version="responses/v1"`` format."""
266
+ """Convert v0 AIMessage into `output_version="responses/v1"` format."""
267
267
  from langchain_core.messages import AIMessageChunk # noqa: PLC0415
268
268
 
269
269
  # Only update ChatOpenAI v0.3 AIMessages
@@ -31,7 +31,7 @@ class ChatMessageChunk(ChatMessage, BaseMessageChunk):
31
31
  type: Literal["ChatMessageChunk"] = "ChatMessageChunk" # type: ignore[assignment]
32
32
  """The type of the message (used during serialization).
33
33
 
34
- Defaults to ``'ChatMessageChunk'``.
34
+ Defaults to `'ChatMessageChunk'`.
35
35
 
36
36
  """
37
37