langchain-core 0.3.68__py3-none-any.whl → 0.3.70__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.
- langchain_core/_api/deprecation.py +3 -3
- langchain_core/_import_utils.py +2 -2
- langchain_core/caches.py +1 -1
- langchain_core/callbacks/manager.py +2 -2
- langchain_core/chat_history.py +20 -16
- langchain_core/document_loaders/base.py +3 -3
- langchain_core/documents/base.py +3 -3
- langchain_core/indexing/api.py +6 -6
- langchain_core/language_models/_utils.py +1 -1
- langchain_core/language_models/base.py +1 -1
- langchain_core/language_models/chat_models.py +8 -8
- langchain_core/language_models/fake_chat_models.py +6 -2
- langchain_core/language_models/llms.py +23 -26
- langchain_core/load/load.py +23 -2
- langchain_core/load/serializable.py +4 -4
- langchain_core/messages/tool.py +1 -3
- langchain_core/messages/utils.py +29 -32
- langchain_core/output_parsers/base.py +1 -1
- langchain_core/output_parsers/openai_functions.py +7 -7
- langchain_core/output_parsers/openai_tools.py +38 -8
- langchain_core/output_parsers/xml.py +7 -7
- langchain_core/outputs/__init__.py +8 -9
- langchain_core/outputs/chat_generation.py +5 -3
- langchain_core/outputs/generation.py +2 -1
- langchain_core/outputs/llm_result.py +14 -14
- langchain_core/prompts/base.py +5 -5
- langchain_core/prompts/chat.py +22 -21
- langchain_core/prompts/dict.py +0 -2
- langchain_core/prompts/pipeline.py +13 -15
- langchain_core/prompts/prompt.py +4 -4
- langchain_core/prompts/string.py +4 -4
- langchain_core/rate_limiters.py +2 -3
- langchain_core/retrievers.py +6 -6
- langchain_core/runnables/base.py +21 -18
- langchain_core/runnables/branch.py +3 -3
- langchain_core/runnables/graph.py +1 -1
- langchain_core/runnables/history.py +3 -3
- langchain_core/runnables/router.py +1 -2
- langchain_core/runnables/utils.py +1 -1
- langchain_core/stores.py +1 -1
- langchain_core/sys_info.py +2 -2
- langchain_core/tools/base.py +7 -7
- langchain_core/tools/structured.py +8 -1
- langchain_core/tracers/core.py +4 -4
- langchain_core/tracers/event_stream.py +5 -5
- langchain_core/tracers/log_stream.py +5 -1
- langchain_core/utils/_merge.py +2 -0
- langchain_core/utils/env.py +2 -2
- langchain_core/utils/function_calling.py +4 -6
- langchain_core/utils/image.py +1 -1
- langchain_core/utils/json_schema.py +64 -59
- langchain_core/utils/mustache.py +9 -4
- langchain_core/vectorstores/base.py +10 -10
- langchain_core/vectorstores/in_memory.py +5 -5
- langchain_core/vectorstores/utils.py +21 -0
- langchain_core/version.py +1 -1
- {langchain_core-0.3.68.dist-info → langchain_core-0.3.70.dist-info}/METADATA +2 -2
- {langchain_core-0.3.68.dist-info → langchain_core-0.3.70.dist-info}/RECORD +60 -60
- {langchain_core-0.3.68.dist-info → langchain_core-0.3.70.dist-info}/WHEEL +0 -0
- {langchain_core-0.3.68.dist-info → langchain_core-0.3.70.dist-info}/entry_points.txt +0 -0
|
@@ -18,16 +18,14 @@ def _get_inputs(inputs: dict, input_variables: list[str]) -> dict:
|
|
|
18
18
|
since="0.3.22",
|
|
19
19
|
removal="1.0",
|
|
20
20
|
message=(
|
|
21
|
-
"This class is deprecated
|
|
22
|
-
" for a replacement option: "
|
|
23
|
-
"https://python.langchain.com/api_reference/core/prompts/langchain_core.prompts.pipeline.PipelinePromptTemplate.html"
|
|
21
|
+
"This class is deprecated in favor of chaining individual prompts together."
|
|
24
22
|
),
|
|
25
23
|
)
|
|
26
24
|
class PipelinePromptTemplate(BasePromptTemplate):
|
|
27
|
-
"""
|
|
25
|
+
"""Pipeline prompt template.
|
|
28
26
|
|
|
29
27
|
This has been deprecated in favor of chaining individual prompts together in your
|
|
30
|
-
code
|
|
28
|
+
code; e.g. using a for loop, you could do:
|
|
31
29
|
|
|
32
30
|
.. code-block:: python
|
|
33
31
|
|
|
@@ -81,13 +79,13 @@ class PipelinePromptTemplate(BasePromptTemplate):
|
|
|
81
79
|
A formatted string.
|
|
82
80
|
"""
|
|
83
81
|
for k, prompt in self.pipeline_prompts:
|
|
84
|
-
|
|
82
|
+
inputs = _get_inputs(kwargs, prompt.input_variables)
|
|
85
83
|
if isinstance(prompt, BaseChatPromptTemplate):
|
|
86
|
-
kwargs[k] = prompt.format_messages(**
|
|
84
|
+
kwargs[k] = prompt.format_messages(**inputs)
|
|
87
85
|
else:
|
|
88
|
-
kwargs[k] = prompt.format(**
|
|
89
|
-
|
|
90
|
-
return self.final_prompt.format_prompt(**
|
|
86
|
+
kwargs[k] = prompt.format(**inputs)
|
|
87
|
+
inputs = _get_inputs(kwargs, self.final_prompt.input_variables)
|
|
88
|
+
return self.final_prompt.format_prompt(**inputs)
|
|
91
89
|
|
|
92
90
|
async def aformat_prompt(self, **kwargs: Any) -> PromptValue:
|
|
93
91
|
"""Async format the prompt with the inputs.
|
|
@@ -99,13 +97,13 @@ class PipelinePromptTemplate(BasePromptTemplate):
|
|
|
99
97
|
A formatted string.
|
|
100
98
|
"""
|
|
101
99
|
for k, prompt in self.pipeline_prompts:
|
|
102
|
-
|
|
100
|
+
inputs = _get_inputs(kwargs, prompt.input_variables)
|
|
103
101
|
if isinstance(prompt, BaseChatPromptTemplate):
|
|
104
|
-
kwargs[k] = await prompt.aformat_messages(**
|
|
102
|
+
kwargs[k] = await prompt.aformat_messages(**inputs)
|
|
105
103
|
else:
|
|
106
|
-
kwargs[k] = await prompt.aformat(**
|
|
107
|
-
|
|
108
|
-
return await self.final_prompt.aformat_prompt(**
|
|
104
|
+
kwargs[k] = await prompt.aformat(**inputs)
|
|
105
|
+
inputs = _get_inputs(kwargs, self.final_prompt.input_variables)
|
|
106
|
+
return await self.final_prompt.aformat_prompt(**inputs)
|
|
109
107
|
|
|
110
108
|
def format(self, **kwargs: Any) -> str:
|
|
111
109
|
"""Format the prompt with the inputs.
|
langchain_core/prompts/prompt.py
CHANGED
|
@@ -287,17 +287,17 @@ class PromptTemplate(StringPromptTemplate):
|
|
|
287
287
|
The prompt template loaded from the template.
|
|
288
288
|
"""
|
|
289
289
|
input_variables = get_template_variables(template, template_format)
|
|
290
|
-
|
|
290
|
+
partial_variables_ = partial_variables or {}
|
|
291
291
|
|
|
292
|
-
if
|
|
292
|
+
if partial_variables_:
|
|
293
293
|
input_variables = [
|
|
294
|
-
var for var in input_variables if var not in
|
|
294
|
+
var for var in input_variables if var not in partial_variables_
|
|
295
295
|
]
|
|
296
296
|
|
|
297
297
|
return cls(
|
|
298
298
|
input_variables=input_variables,
|
|
299
299
|
template=template,
|
|
300
300
|
template_format=template_format,
|
|
301
|
-
partial_variables=
|
|
301
|
+
partial_variables=partial_variables_,
|
|
302
302
|
**kwargs,
|
|
303
303
|
)
|
langchain_core/prompts/string.py
CHANGED
|
@@ -131,12 +131,12 @@ def mustache_template_vars(
|
|
|
131
131
|
if type_ == "end":
|
|
132
132
|
section_depth -= 1
|
|
133
133
|
elif (
|
|
134
|
-
type_ in
|
|
134
|
+
type_ in {"variable", "section", "inverted section", "no escape"}
|
|
135
135
|
and key != "."
|
|
136
136
|
and section_depth == 0
|
|
137
137
|
):
|
|
138
138
|
variables.add(key.split(".")[0])
|
|
139
|
-
if type_ in
|
|
139
|
+
if type_ in {"section", "inverted section"}:
|
|
140
140
|
section_depth += 1
|
|
141
141
|
return variables
|
|
142
142
|
|
|
@@ -164,11 +164,11 @@ def mustache_schema(
|
|
|
164
164
|
if type_ == "end":
|
|
165
165
|
if section_stack:
|
|
166
166
|
prefix = section_stack.pop()
|
|
167
|
-
elif type_ in
|
|
167
|
+
elif type_ in {"section", "inverted section"}:
|
|
168
168
|
section_stack.append(prefix)
|
|
169
169
|
prefix = prefix + tuple(key.split("."))
|
|
170
170
|
fields[prefix] = False
|
|
171
|
-
elif type_ in
|
|
171
|
+
elif type_ in {"variable", "no escape"}:
|
|
172
172
|
fields[prefix + tuple(key.split("."))] = True
|
|
173
173
|
defs: Defs = {} # None means leaf node
|
|
174
174
|
while fields:
|
langchain_core/rate_limiters.py
CHANGED
|
@@ -146,13 +146,12 @@ class InMemoryRateLimiter(BaseRateLimiter):
|
|
|
146
146
|
|
|
147
147
|
Args:
|
|
148
148
|
requests_per_second: The number of tokens to add per second to the bucket.
|
|
149
|
-
|
|
150
|
-
to make requests.
|
|
149
|
+
The tokens represent "credit" that can be used to make requests.
|
|
151
150
|
check_every_n_seconds: check whether the tokens are available
|
|
152
151
|
every this many seconds. Can be a float to represent
|
|
153
152
|
fractions of a second.
|
|
154
153
|
max_bucket_size: The maximum number of tokens that can be in the bucket.
|
|
155
|
-
|
|
154
|
+
Must be at least 1. Used to prevent bursts of requests.
|
|
156
155
|
"""
|
|
157
156
|
# Number of requests that we can make per second.
|
|
158
157
|
self.requests_per_second = requests_per_second
|
langchain_core/retrievers.py
CHANGED
|
@@ -254,13 +254,13 @@ class BaseRetriever(RunnableSerializable[RetrieverInput, RetrieverOutput], ABC):
|
|
|
254
254
|
run_id=kwargs.pop("run_id", None),
|
|
255
255
|
)
|
|
256
256
|
try:
|
|
257
|
-
|
|
257
|
+
kwargs_ = kwargs if self._expects_other_args else {}
|
|
258
258
|
if self._new_arg_supported:
|
|
259
259
|
result = self._get_relevant_documents(
|
|
260
|
-
input, run_manager=run_manager, **
|
|
260
|
+
input, run_manager=run_manager, **kwargs_
|
|
261
261
|
)
|
|
262
262
|
else:
|
|
263
|
-
result = self._get_relevant_documents(input, **
|
|
263
|
+
result = self._get_relevant_documents(input, **kwargs_)
|
|
264
264
|
except Exception as e:
|
|
265
265
|
run_manager.on_retriever_error(e)
|
|
266
266
|
raise
|
|
@@ -318,13 +318,13 @@ class BaseRetriever(RunnableSerializable[RetrieverInput, RetrieverOutput], ABC):
|
|
|
318
318
|
run_id=kwargs.pop("run_id", None),
|
|
319
319
|
)
|
|
320
320
|
try:
|
|
321
|
-
|
|
321
|
+
kwargs_ = kwargs if self._expects_other_args else {}
|
|
322
322
|
if self._new_arg_supported:
|
|
323
323
|
result = await self._aget_relevant_documents(
|
|
324
|
-
input, run_manager=run_manager, **
|
|
324
|
+
input, run_manager=run_manager, **kwargs_
|
|
325
325
|
)
|
|
326
326
|
else:
|
|
327
|
-
result = await self._aget_relevant_documents(input, **
|
|
327
|
+
result = await self._aget_relevant_documents(input, **kwargs_)
|
|
328
328
|
except Exception as e:
|
|
329
329
|
await run_manager.on_retriever_error(e)
|
|
330
330
|
raise
|
langchain_core/runnables/base.py
CHANGED
|
@@ -108,7 +108,7 @@ if TYPE_CHECKING:
|
|
|
108
108
|
Other = TypeVar("Other")
|
|
109
109
|
|
|
110
110
|
|
|
111
|
-
class Runnable(Generic[Input, Output]
|
|
111
|
+
class Runnable(ABC, Generic[Input, Output]):
|
|
112
112
|
"""A unit of work that can be invoked, batched, streamed, transformed and composed.
|
|
113
113
|
|
|
114
114
|
Key Methods
|
|
@@ -1160,22 +1160,21 @@ class Runnable(Generic[Input, Output], ABC):
|
|
|
1160
1160
|
|
|
1161
1161
|
A StreamEvent is a dictionary with the following schema:
|
|
1162
1162
|
|
|
1163
|
-
- ``event``: **str** - Event names are of the
|
|
1164
|
-
|
|
1163
|
+
- ``event``: **str** - Event names are of the format:
|
|
1164
|
+
on_[runnable_type]_(start|stream|end).
|
|
1165
1165
|
- ``name``: **str** - The name of the Runnable that generated the event.
|
|
1166
|
-
- ``run_id``: **str** - randomly generated ID associated with the given
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
- ``parent_ids``: **list[str]** - The IDs of the parent runnables that
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
will return an empty list.
|
|
1166
|
+
- ``run_id``: **str** - randomly generated ID associated with the given
|
|
1167
|
+
execution of the Runnable that emitted the event. A child Runnable that gets
|
|
1168
|
+
invoked as part of the execution of a parent Runnable is assigned its own
|
|
1169
|
+
unique ID.
|
|
1170
|
+
- ``parent_ids``: **list[str]** - The IDs of the parent runnables that generated
|
|
1171
|
+
the event. The root Runnable will have an empty list. The order of the parent
|
|
1172
|
+
IDs is from the root to the immediate parent. Only available for v2 version of
|
|
1173
|
+
the API. The v1 version of the API will return an empty list.
|
|
1175
1174
|
- ``tags``: **Optional[list[str]]** - The tags of the Runnable that generated
|
|
1176
|
-
|
|
1177
|
-
- ``metadata``: **Optional[dict[str, Any]]** - The metadata of the Runnable
|
|
1178
|
-
|
|
1175
|
+
the event.
|
|
1176
|
+
- ``metadata``: **Optional[dict[str, Any]]** - The metadata of the Runnable that
|
|
1177
|
+
generated the event.
|
|
1179
1178
|
- ``data``: **dict[str, Any]**
|
|
1180
1179
|
|
|
1181
1180
|
|
|
@@ -1183,7 +1182,7 @@ class Runnable(Generic[Input, Output], ABC):
|
|
|
1183
1182
|
chains. Metadata fields have been omitted from the table for brevity.
|
|
1184
1183
|
Chain definitions have been included after the table.
|
|
1185
1184
|
|
|
1186
|
-
|
|
1185
|
+
.. NOTE:: This reference table is for the V2 version of the schema.
|
|
1187
1186
|
|
|
1188
1187
|
+----------------------+------------------+---------------------------------+-----------------------------------------------+-------------------------------------------------+
|
|
1189
1188
|
| event | name | chunk | input | output |
|
|
@@ -4205,6 +4204,8 @@ class RunnableGenerator(Runnable[Input, Output]):
|
|
|
4205
4204
|
return False
|
|
4206
4205
|
return False
|
|
4207
4206
|
|
|
4207
|
+
__hash__ = None # type: ignore[assignment]
|
|
4208
|
+
|
|
4208
4209
|
@override
|
|
4209
4210
|
def __repr__(self) -> str:
|
|
4210
4211
|
return f"RunnableGenerator({self.name})"
|
|
@@ -4484,10 +4485,10 @@ class RunnableLambda(Runnable[Input, Output]):
|
|
|
4484
4485
|
sig = inspect.signature(func)
|
|
4485
4486
|
if sig.return_annotation != inspect.Signature.empty:
|
|
4486
4487
|
# unwrap iterator types
|
|
4487
|
-
if getattr(sig.return_annotation, "__origin__", None) in
|
|
4488
|
+
if getattr(sig.return_annotation, "__origin__", None) in {
|
|
4488
4489
|
collections.abc.Iterator,
|
|
4489
4490
|
collections.abc.AsyncIterator,
|
|
4490
|
-
|
|
4491
|
+
}:
|
|
4491
4492
|
return getattr(sig.return_annotation, "__args__", (Any,))[0]
|
|
4492
4493
|
return sig.return_annotation
|
|
4493
4494
|
except ValueError:
|
|
@@ -4588,6 +4589,8 @@ class RunnableLambda(Runnable[Input, Output]):
|
|
|
4588
4589
|
return False
|
|
4589
4590
|
return False
|
|
4590
4591
|
|
|
4592
|
+
__hash__ = None # type: ignore[assignment]
|
|
4593
|
+
|
|
4591
4594
|
def __repr__(self) -> str:
|
|
4592
4595
|
"""A string representation of this Runnable."""
|
|
4593
4596
|
if self._repr is None:
|
|
@@ -111,7 +111,7 @@ class RunnableBranch(RunnableSerializable[Input, Output]):
|
|
|
111
111
|
"Runnable[Input, Output]", coerce_to_runnable(cast("RunnableLike", default))
|
|
112
112
|
)
|
|
113
113
|
|
|
114
|
-
|
|
114
|
+
branches_ = []
|
|
115
115
|
|
|
116
116
|
for branch in branches[:-1]:
|
|
117
117
|
if not isinstance(branch, (tuple, list)):
|
|
@@ -130,10 +130,10 @@ class RunnableBranch(RunnableSerializable[Input, Output]):
|
|
|
130
130
|
condition, runnable = branch
|
|
131
131
|
condition = cast("Runnable[Input, bool]", coerce_to_runnable(condition))
|
|
132
132
|
runnable = coerce_to_runnable(runnable)
|
|
133
|
-
|
|
133
|
+
branches_.append((condition, runnable))
|
|
134
134
|
|
|
135
135
|
super().__init__(
|
|
136
|
-
branches=
|
|
136
|
+
branches=branches_,
|
|
137
137
|
default=default_,
|
|
138
138
|
) # type: ignore[call-arg]
|
|
139
139
|
|
|
@@ -339,10 +339,10 @@ class RunnableWithMessageHistory(RunnableBindingBase):
|
|
|
339
339
|
).with_config(run_name="RunnableWithMessageHistory")
|
|
340
340
|
|
|
341
341
|
if history_factory_config:
|
|
342
|
-
|
|
342
|
+
config_specs = history_factory_config
|
|
343
343
|
else:
|
|
344
344
|
# If not provided, then we'll use the default session_id field
|
|
345
|
-
|
|
345
|
+
config_specs = [
|
|
346
346
|
ConfigurableFieldSpec(
|
|
347
347
|
id="session_id",
|
|
348
348
|
annotation=str,
|
|
@@ -359,7 +359,7 @@ class RunnableWithMessageHistory(RunnableBindingBase):
|
|
|
359
359
|
output_messages_key=output_messages_key,
|
|
360
360
|
bound=bound,
|
|
361
361
|
history_messages_key=history_messages_key,
|
|
362
|
-
history_factory_config=
|
|
362
|
+
history_factory_config=config_specs,
|
|
363
363
|
**kwargs,
|
|
364
364
|
)
|
|
365
365
|
self._history_chain = history_chain
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
from collections.abc import Mapping
|
|
6
|
-
from itertools import starmap
|
|
7
6
|
from typing import (
|
|
8
7
|
TYPE_CHECKING,
|
|
9
8
|
Any,
|
|
@@ -206,7 +205,7 @@ class RouterRunnable(RunnableSerializable[RouterInput, Output]):
|
|
|
206
205
|
configs = get_config_list(config, len(inputs))
|
|
207
206
|
return await gather_with_concurrency(
|
|
208
207
|
configs[0].get("max_concurrency"),
|
|
209
|
-
*
|
|
208
|
+
*map(ainvoke, runnables, actual_inputs, configs),
|
|
210
209
|
)
|
|
211
210
|
|
|
212
211
|
@override
|
|
@@ -194,7 +194,7 @@ class IsLocalDict(ast.NodeVisitor):
|
|
|
194
194
|
and isinstance(node.func.value, ast.Name)
|
|
195
195
|
and node.func.value.id == self.name
|
|
196
196
|
and node.func.attr == "get"
|
|
197
|
-
and len(node.args) in
|
|
197
|
+
and len(node.args) in {1, 2}
|
|
198
198
|
and isinstance(node.args[0], ast.Constant)
|
|
199
199
|
and isinstance(node.args[0].value, str)
|
|
200
200
|
):
|
langchain_core/stores.py
CHANGED
langchain_core/sys_info.py
CHANGED
|
@@ -8,7 +8,7 @@ def _get_sub_deps(packages: Sequence[str]) -> list[str]:
|
|
|
8
8
|
from importlib import metadata
|
|
9
9
|
|
|
10
10
|
sub_deps = set()
|
|
11
|
-
|
|
11
|
+
underscored_packages = {pkg.replace("-", "_") for pkg in packages}
|
|
12
12
|
|
|
13
13
|
for pkg in packages:
|
|
14
14
|
try:
|
|
@@ -21,7 +21,7 @@ def _get_sub_deps(packages: Sequence[str]) -> list[str]:
|
|
|
21
21
|
|
|
22
22
|
for req in required:
|
|
23
23
|
cleaned_req = req.split(" ")[0]
|
|
24
|
-
if cleaned_req.replace("-", "_") not in
|
|
24
|
+
if cleaned_req.replace("-", "_") not in underscored_packages:
|
|
25
25
|
sub_deps.add(cleaned_req)
|
|
26
26
|
|
|
27
27
|
return sorted(sub_deps, key=lambda x: x.lower())
|
langchain_core/tools/base.py
CHANGED
|
@@ -134,7 +134,7 @@ def _get_filtered_args(
|
|
|
134
134
|
k: schema[k]
|
|
135
135
|
for i, (k, param) in enumerate(valid_keys.items())
|
|
136
136
|
if k not in filter_args
|
|
137
|
-
and (i > 0 or param.name not in
|
|
137
|
+
and (i > 0 or param.name not in {"self", "cls"})
|
|
138
138
|
and (include_injected or not _is_injected_arg_type(param.annotation))
|
|
139
139
|
}
|
|
140
140
|
|
|
@@ -336,7 +336,7 @@ def create_schema_from_function(
|
|
|
336
336
|
else:
|
|
337
337
|
# Handle classmethods and instance methods
|
|
338
338
|
existing_params: list[str] = list(sig.parameters.keys())
|
|
339
|
-
if existing_params and existing_params[0] in
|
|
339
|
+
if existing_params and existing_params[0] in {"self", "cls"} and in_class:
|
|
340
340
|
filter_args_ = [existing_params[0], *list(FILTERED_ARGS)]
|
|
341
341
|
else:
|
|
342
342
|
filter_args_ = list(FILTERED_ARGS)
|
|
@@ -776,7 +776,7 @@ class ChildTool(BaseTool):
|
|
|
776
776
|
def run(
|
|
777
777
|
self,
|
|
778
778
|
tool_input: Union[str, dict[str, Any]],
|
|
779
|
-
verbose: Optional[bool] = None,
|
|
779
|
+
verbose: Optional[bool] = None, # noqa: FBT001
|
|
780
780
|
start_color: Optional[str] = "green",
|
|
781
781
|
color: Optional[str] = "green",
|
|
782
782
|
callbacks: Callbacks = None,
|
|
@@ -803,7 +803,7 @@ class ChildTool(BaseTool):
|
|
|
803
803
|
run_id: The id of the run. Defaults to None.
|
|
804
804
|
config: The configuration for the tool. Defaults to None.
|
|
805
805
|
tool_call_id: The id of the tool call. Defaults to None.
|
|
806
|
-
kwargs: Keyword arguments to be passed to tool callbacks
|
|
806
|
+
kwargs: Keyword arguments to be passed to tool callbacks (event handler)
|
|
807
807
|
|
|
808
808
|
Returns:
|
|
809
809
|
The output of the tool.
|
|
@@ -846,9 +846,9 @@ class ChildTool(BaseTool):
|
|
|
846
846
|
tool_input, tool_call_id
|
|
847
847
|
)
|
|
848
848
|
if signature(self._run).parameters.get("run_manager"):
|
|
849
|
-
tool_kwargs
|
|
849
|
+
tool_kwargs |= {"run_manager": run_manager}
|
|
850
850
|
if config_param := _get_runnable_config_param(self._run):
|
|
851
|
-
tool_kwargs
|
|
851
|
+
tool_kwargs |= {config_param: config}
|
|
852
852
|
response = context.run(self._run, *tool_args, **tool_kwargs)
|
|
853
853
|
if self.response_format == "content_and_artifact":
|
|
854
854
|
if not isinstance(response, tuple) or len(response) != 2:
|
|
@@ -888,7 +888,7 @@ class ChildTool(BaseTool):
|
|
|
888
888
|
async def arun(
|
|
889
889
|
self,
|
|
890
890
|
tool_input: Union[str, dict],
|
|
891
|
-
verbose: Optional[bool] = None,
|
|
891
|
+
verbose: Optional[bool] = None, # noqa: FBT001
|
|
892
892
|
start_color: Optional[str] = "green",
|
|
893
893
|
color: Optional[str] = "green",
|
|
894
894
|
callbacks: Callbacks = None,
|
|
@@ -197,7 +197,14 @@ class StructuredTool(BaseTool):
|
|
|
197
197
|
description_ = source_function.__doc__ or None
|
|
198
198
|
if description_ is None and args_schema:
|
|
199
199
|
if isinstance(args_schema, type) and is_basemodel_subclass(args_schema):
|
|
200
|
-
description_ = args_schema.__doc__
|
|
200
|
+
description_ = args_schema.__doc__
|
|
201
|
+
if (
|
|
202
|
+
description_
|
|
203
|
+
and "A base class for creating Pydantic models" in description_
|
|
204
|
+
):
|
|
205
|
+
description_ = ""
|
|
206
|
+
elif not description_:
|
|
207
|
+
description_ = None
|
|
201
208
|
elif isinstance(args_schema, dict):
|
|
202
209
|
description_ = args_schema.get("description")
|
|
203
210
|
else:
|
langchain_core/tracers/core.py
CHANGED
|
@@ -165,7 +165,7 @@ class _TracerCore(ABC):
|
|
|
165
165
|
**kwargs: Any,
|
|
166
166
|
) -> Run:
|
|
167
167
|
"""Create a chat model run."""
|
|
168
|
-
if self._schema_format not in
|
|
168
|
+
if self._schema_format not in {"streaming_events", "original+chat"}:
|
|
169
169
|
# Please keep this un-implemented for backwards compatibility.
|
|
170
170
|
# When it's unimplemented old tracers that use the "original" format
|
|
171
171
|
# fallback on the on_llm_start method implementation if they
|
|
@@ -352,7 +352,7 @@ class _TracerCore(ABC):
|
|
|
352
352
|
|
|
353
353
|
def _get_chain_inputs(self, inputs: Any) -> Any:
|
|
354
354
|
"""Get the inputs for a chain run."""
|
|
355
|
-
if self._schema_format in
|
|
355
|
+
if self._schema_format in {"original", "original+chat"}:
|
|
356
356
|
return inputs if isinstance(inputs, dict) else {"input": inputs}
|
|
357
357
|
if self._schema_format == "streaming_events":
|
|
358
358
|
return {
|
|
@@ -363,7 +363,7 @@ class _TracerCore(ABC):
|
|
|
363
363
|
|
|
364
364
|
def _get_chain_outputs(self, outputs: Any) -> Any:
|
|
365
365
|
"""Get the outputs for a chain run."""
|
|
366
|
-
if self._schema_format in
|
|
366
|
+
if self._schema_format in {"original", "original+chat"}:
|
|
367
367
|
return outputs if isinstance(outputs, dict) else {"output": outputs}
|
|
368
368
|
if self._schema_format == "streaming_events":
|
|
369
369
|
return {
|
|
@@ -423,7 +423,7 @@ class _TracerCore(ABC):
|
|
|
423
423
|
if metadata:
|
|
424
424
|
kwargs.update({"metadata": metadata})
|
|
425
425
|
|
|
426
|
-
if self._schema_format in
|
|
426
|
+
if self._schema_format in {"original", "original+chat"}:
|
|
427
427
|
inputs = {"input": input_str}
|
|
428
428
|
elif self._schema_format == "streaming_events":
|
|
429
429
|
inputs = {"input": inputs}
|
|
@@ -773,7 +773,7 @@ async def _astream_events_implementation_v1(
|
|
|
773
773
|
run_log = RunLog(state=None) # type: ignore[arg-type]
|
|
774
774
|
encountered_start_event = False
|
|
775
775
|
|
|
776
|
-
|
|
776
|
+
root_event_filter = _RootEventFilter(
|
|
777
777
|
include_names=include_names,
|
|
778
778
|
include_types=include_types,
|
|
779
779
|
include_tags=include_tags,
|
|
@@ -796,7 +796,7 @@ async def _astream_events_implementation_v1(
|
|
|
796
796
|
with_streamed_output_list=True,
|
|
797
797
|
**kwargs,
|
|
798
798
|
):
|
|
799
|
-
run_log
|
|
799
|
+
run_log += log
|
|
800
800
|
|
|
801
801
|
if not encountered_start_event:
|
|
802
802
|
# Yield the start event for the root runnable.
|
|
@@ -815,7 +815,7 @@ async def _astream_events_implementation_v1(
|
|
|
815
815
|
parent_ids=[], # Not supported in v1
|
|
816
816
|
)
|
|
817
817
|
|
|
818
|
-
if
|
|
818
|
+
if root_event_filter.include_event(event, state["type"]):
|
|
819
819
|
yield event
|
|
820
820
|
|
|
821
821
|
paths = {
|
|
@@ -901,7 +901,7 @@ async def _astream_events_implementation_v1(
|
|
|
901
901
|
data=data,
|
|
902
902
|
parent_ids=[], # Not supported in v1
|
|
903
903
|
)
|
|
904
|
-
if
|
|
904
|
+
if root_event_filter.include_event(event, state["type"]):
|
|
905
905
|
yield event
|
|
906
906
|
|
|
907
907
|
state = run_log.state
|
|
@@ -918,7 +918,7 @@ async def _astream_events_implementation_v1(
|
|
|
918
918
|
},
|
|
919
919
|
parent_ids=[], # Not supported in v1
|
|
920
920
|
)
|
|
921
|
-
if
|
|
921
|
+
if root_event_filter.include_event(event, state["type"]):
|
|
922
922
|
yield event
|
|
923
923
|
|
|
924
924
|
|
|
@@ -130,6 +130,8 @@ class RunLogPatch:
|
|
|
130
130
|
def __eq__(self, other: object) -> bool:
|
|
131
131
|
return isinstance(other, RunLogPatch) and self.ops == other.ops
|
|
132
132
|
|
|
133
|
+
__hash__ = None # type: ignore[assignment]
|
|
134
|
+
|
|
133
135
|
|
|
134
136
|
class RunLog(RunLogPatch):
|
|
135
137
|
"""Run log."""
|
|
@@ -174,6 +176,8 @@ class RunLog(RunLogPatch):
|
|
|
174
176
|
# Then compare that the ops are the same
|
|
175
177
|
return super().__eq__(other)
|
|
176
178
|
|
|
179
|
+
__hash__ = None # type: ignore[assignment]
|
|
180
|
+
|
|
177
181
|
|
|
178
182
|
T = TypeVar("T")
|
|
179
183
|
|
|
@@ -694,7 +698,7 @@ async def _astream_log_implementation(
|
|
|
694
698
|
else:
|
|
695
699
|
state = RunLog(state=None) # type: ignore[arg-type]
|
|
696
700
|
async for log in stream:
|
|
697
|
-
state
|
|
701
|
+
state += log
|
|
698
702
|
yield state
|
|
699
703
|
finally:
|
|
700
704
|
# Wait for the runnable to finish, if not cancelled (eg. by break)
|
langchain_core/utils/_merge.py
CHANGED
|
@@ -64,6 +64,8 @@ def merge_dicts(left: dict[str, Any], *others: dict[str, Any]) -> dict[str, Any]
|
|
|
64
64
|
merged[right_k] = merge_lists(merged[right_k], right_v)
|
|
65
65
|
elif merged[right_k] == right_v:
|
|
66
66
|
continue
|
|
67
|
+
elif isinstance(merged[right_k], int):
|
|
68
|
+
merged[right_k] += right_v
|
|
67
69
|
else:
|
|
68
70
|
msg = (
|
|
69
71
|
f"Additional kwargs key {right_k} already exists in left dict and "
|
langchain_core/utils/env.py
CHANGED
|
@@ -15,12 +15,12 @@ def env_var_is_set(env_var: str) -> bool:
|
|
|
15
15
|
Returns:
|
|
16
16
|
bool: True if the environment variable is set, False otherwise.
|
|
17
17
|
"""
|
|
18
|
-
return env_var in os.environ and os.environ[env_var] not in
|
|
18
|
+
return env_var in os.environ and os.environ[env_var] not in {
|
|
19
19
|
"",
|
|
20
20
|
"0",
|
|
21
21
|
"false",
|
|
22
22
|
"False",
|
|
23
|
-
|
|
23
|
+
}
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
def get_from_dict_or_env(
|
|
@@ -294,8 +294,6 @@ def _convert_any_typed_dicts_to_pydantic(
|
|
|
294
294
|
raise ValueError(msg)
|
|
295
295
|
if arg_desc := arg_descriptions.get(arg):
|
|
296
296
|
field_kwargs["description"] = arg_desc
|
|
297
|
-
else:
|
|
298
|
-
pass
|
|
299
297
|
fields[arg] = (new_arg_type, Field_v1(**field_kwargs))
|
|
300
298
|
else:
|
|
301
299
|
new_arg_type = _convert_any_typed_dicts_to_pydantic(
|
|
@@ -456,7 +454,7 @@ def convert_to_openai_function(
|
|
|
456
454
|
oai_function = {
|
|
457
455
|
k: v
|
|
458
456
|
for k, v in function.items()
|
|
459
|
-
if k in
|
|
457
|
+
if k in {"name", "description", "parameters", "strict"}
|
|
460
458
|
}
|
|
461
459
|
# a JSON schema with title and description
|
|
462
460
|
elif isinstance(function, dict) and "title" in function:
|
|
@@ -734,7 +732,7 @@ def _parse_google_docstring(
|
|
|
734
732
|
docstring_blocks = docstring.split("\n\n")
|
|
735
733
|
if error_on_invalid_docstring:
|
|
736
734
|
filtered_annotations = {
|
|
737
|
-
arg for arg in args if arg not in
|
|
735
|
+
arg for arg in args if arg not in {"run_manager", "callbacks", "return"}
|
|
738
736
|
}
|
|
739
737
|
if filtered_annotations and (
|
|
740
738
|
len(docstring_blocks) < 2
|
|
@@ -770,8 +768,8 @@ def _parse_google_docstring(
|
|
|
770
768
|
if ":" in line:
|
|
771
769
|
arg, desc = line.split(":", maxsplit=1)
|
|
772
770
|
arg = arg.strip()
|
|
773
|
-
arg_name, _,
|
|
774
|
-
if
|
|
771
|
+
arg_name, _, annotations_ = arg.partition(" ")
|
|
772
|
+
if annotations_.startswith("(") and annotations_.endswith(")"):
|
|
775
773
|
arg = arg_name
|
|
776
774
|
arg_descriptions[arg] = desc.strip()
|
|
777
775
|
elif arg:
|
langchain_core/utils/image.py
CHANGED
|
@@ -4,7 +4,7 @@ from typing import Any
|
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
def __getattr__(name: str) -> Any:
|
|
7
|
-
if name in
|
|
7
|
+
if name in {"encode_image", "image_to_data_url"}:
|
|
8
8
|
msg = (
|
|
9
9
|
f"'{name}' has been removed for security reasons.\n\n"
|
|
10
10
|
f"Usage of this utility in environments with user-input paths is a "
|