langchain-dev-utils 1.3.2__py3-none-any.whl → 1.3.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- langchain_dev_utils/__init__.py +1 -1
- langchain_dev_utils/agents/__init__.py +2 -2
- langchain_dev_utils/agents/middleware/handoffs.py +17 -2
- langchain_dev_utils/agents/wrap.py +138 -4
- langchain_dev_utils/chat_models/adapters/__init__.py +3 -0
- langchain_dev_utils/chat_models/adapters/create_utils.py +53 -0
- langchain_dev_utils/chat_models/adapters/openai_compatible.py +23 -4
- langchain_dev_utils/chat_models/adapters/register_profiles.py +15 -0
- langchain_dev_utils/chat_models/base.py +4 -11
- langchain_dev_utils/embeddings/adapters/__init__.py +3 -0
- langchain_dev_utils/embeddings/adapters/create_utils.py +45 -0
- langchain_dev_utils/embeddings/adapters/openai_compatible.py +75 -0
- langchain_dev_utils/embeddings/base.py +11 -25
- langchain_dev_utils/message_convert/__init__.py +15 -15
- langchain_dev_utils/message_convert/format.py +69 -69
- {langchain_dev_utils-1.3.2.dist-info → langchain_dev_utils-1.3.4.dist-info}/METADATA +1 -1
- {langchain_dev_utils-1.3.2.dist-info → langchain_dev_utils-1.3.4.dist-info}/RECORD +19 -14
- {langchain_dev_utils-1.3.2.dist-info → langchain_dev_utils-1.3.4.dist-info}/WHEEL +0 -0
- {langchain_dev_utils-1.3.2.dist-info → langchain_dev_utils-1.3.4.dist-info}/licenses/LICENSE +0 -0
langchain_dev_utils/__init__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "1.3.
|
|
1
|
+
__version__ = "1.3.4"
|
|
@@ -78,7 +78,19 @@ def _transform_agent_config(
|
|
|
78
78
|
dict[str, AgentConfig]: The transformed agent config.
|
|
79
79
|
"""
|
|
80
80
|
|
|
81
|
+
new_config = {}
|
|
81
82
|
for agent_name, _cfg in config.items():
|
|
83
|
+
new_config[agent_name] = {}
|
|
84
|
+
|
|
85
|
+
if "model" in _cfg:
|
|
86
|
+
new_config[agent_name]["model"] = _cfg["model"]
|
|
87
|
+
if "prompt" in _cfg:
|
|
88
|
+
new_config[agent_name]["prompt"] = _cfg["prompt"]
|
|
89
|
+
if "default" in _cfg:
|
|
90
|
+
new_config[agent_name]["default"] = _cfg["default"]
|
|
91
|
+
if "tools" in _cfg:
|
|
92
|
+
new_config[agent_name]["tools"] = _cfg["tools"]
|
|
93
|
+
|
|
82
94
|
handoffs = _cfg.get("handoffs", [])
|
|
83
95
|
if handoffs == "all":
|
|
84
96
|
handoff_tools = [
|
|
@@ -102,8 +114,11 @@ def _transform_agent_config(
|
|
|
102
114
|
]
|
|
103
115
|
]
|
|
104
116
|
|
|
105
|
-
|
|
106
|
-
|
|
117
|
+
new_config[agent_name]["tools"] = [
|
|
118
|
+
*new_config[agent_name].get("tools", []),
|
|
119
|
+
*handoff_tools,
|
|
120
|
+
]
|
|
121
|
+
return new_config
|
|
107
122
|
|
|
108
123
|
|
|
109
124
|
class HandoffAgentMiddleware(AgentMiddleware):
|
|
@@ -5,11 +5,8 @@ from langchain.tools import ToolRuntime
|
|
|
5
5
|
from langchain_core.messages import AnyMessage, HumanMessage
|
|
6
6
|
from langchain_core.tools import BaseTool, StructuredTool
|
|
7
7
|
from langgraph.graph.state import CompiledStateGraph
|
|
8
|
-
from pydantic import BaseModel, Field
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
class AgentToolInput(BaseModel):
|
|
12
|
-
request: str = Field(description="The input to the agent")
|
|
9
|
+
from langchain_dev_utils.message_convert import format_sequence
|
|
13
10
|
|
|
14
11
|
|
|
15
12
|
def _process_input(request: str, runtime: ToolRuntime) -> str:
|
|
@@ -138,3 +135,140 @@ def wrap_agent_as_tool(
|
|
|
138
135
|
name=tool_name,
|
|
139
136
|
description=tool_description,
|
|
140
137
|
)
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def wrap_all_agents_as_tool(
|
|
141
|
+
agents: list[CompiledStateGraph],
|
|
142
|
+
tool_name: Optional[str] = None,
|
|
143
|
+
tool_description: Optional[str] = None,
|
|
144
|
+
pre_input_hooks: Optional[
|
|
145
|
+
tuple[
|
|
146
|
+
Callable[[str, ToolRuntime], str],
|
|
147
|
+
Callable[[str, ToolRuntime], Awaitable[str]],
|
|
148
|
+
]
|
|
149
|
+
| Callable[[str, ToolRuntime], str]
|
|
150
|
+
] = None,
|
|
151
|
+
post_output_hooks: Optional[
|
|
152
|
+
tuple[
|
|
153
|
+
Callable[[str, list[AnyMessage], ToolRuntime], Any],
|
|
154
|
+
Callable[[str, list[AnyMessage], ToolRuntime], Awaitable[Any]],
|
|
155
|
+
]
|
|
156
|
+
| Callable[[str, list[AnyMessage], ToolRuntime], Any]
|
|
157
|
+
] = None,
|
|
158
|
+
) -> BaseTool:
|
|
159
|
+
"""Wraps all agents as single tool
|
|
160
|
+
|
|
161
|
+
Args:
|
|
162
|
+
agents: The agents to wrap
|
|
163
|
+
tool_name: The name of the tool, default to "task"
|
|
164
|
+
tool_description: The description of the tool
|
|
165
|
+
pre_input_hooks: Hooks to run before the input is processed
|
|
166
|
+
post_output_hooks: Hooks to run after the output is processed
|
|
167
|
+
|
|
168
|
+
Returns:
|
|
169
|
+
BaseTool: The wrapped agents as single tool
|
|
170
|
+
|
|
171
|
+
Example:
|
|
172
|
+
>>> from langchain_dev_utils.agents import wrap_all_agents_as_tool, create_agent
|
|
173
|
+
>>>
|
|
174
|
+
>>> call_agent_tool = wrap_all_agents_as_tool(
|
|
175
|
+
... [time_agent,weather_agent],
|
|
176
|
+
... tool_name="call_sub_agents",
|
|
177
|
+
... tool_description="Used to invoke the sub-agents to perform tasks"
|
|
178
|
+
... )
|
|
179
|
+
>>>
|
|
180
|
+
>>> agent = create_agent("vllm:qwen3-4b", tools=[call_sub_agents_tool], name="agent")
|
|
181
|
+
|
|
182
|
+
>>> response = agent.invoke({"messages": [HumanMessage(content="What time is it now?")]})
|
|
183
|
+
>>> response
|
|
184
|
+
"""
|
|
185
|
+
if len(agents) <= 1:
|
|
186
|
+
raise ValueError("At least more than one agent must be provided")
|
|
187
|
+
|
|
188
|
+
agents_map = {}
|
|
189
|
+
|
|
190
|
+
for agent in agents:
|
|
191
|
+
if agent.name is None:
|
|
192
|
+
raise ValueError("Agent name must not be provided")
|
|
193
|
+
if agent.name in agents_map:
|
|
194
|
+
raise ValueError("Agent name must be unique")
|
|
195
|
+
agents_map[agent.name] = agent
|
|
196
|
+
|
|
197
|
+
process_input = _process_input
|
|
198
|
+
process_input_async = _process_input
|
|
199
|
+
process_output = _process_output
|
|
200
|
+
process_output_async = _process_output
|
|
201
|
+
|
|
202
|
+
if pre_input_hooks:
|
|
203
|
+
if isinstance(pre_input_hooks, tuple):
|
|
204
|
+
process_input = pre_input_hooks[0]
|
|
205
|
+
process_input_async = pre_input_hooks[1]
|
|
206
|
+
else:
|
|
207
|
+
process_input = pre_input_hooks
|
|
208
|
+
process_input_async = pre_input_hooks
|
|
209
|
+
|
|
210
|
+
if post_output_hooks:
|
|
211
|
+
if isinstance(post_output_hooks, tuple):
|
|
212
|
+
process_output = post_output_hooks[0]
|
|
213
|
+
process_output_async = post_output_hooks[1]
|
|
214
|
+
else:
|
|
215
|
+
process_output = post_output_hooks
|
|
216
|
+
process_output_async = post_output_hooks
|
|
217
|
+
|
|
218
|
+
def call_agent(
|
|
219
|
+
agent_name: str,
|
|
220
|
+
description: str,
|
|
221
|
+
runtime: ToolRuntime,
|
|
222
|
+
) -> str:
|
|
223
|
+
task_description = (
|
|
224
|
+
process_input(description, runtime) if process_input else description
|
|
225
|
+
)
|
|
226
|
+
|
|
227
|
+
if agent_name not in agents_map:
|
|
228
|
+
raise ValueError(f"Agent {agent_name} not found")
|
|
229
|
+
|
|
230
|
+
messages = [HumanMessage(content=task_description)]
|
|
231
|
+
response = agents_map[agent_name].invoke({"messages": messages})
|
|
232
|
+
|
|
233
|
+
response = process_output(task_description, response["messages"], runtime)
|
|
234
|
+
return response
|
|
235
|
+
|
|
236
|
+
async def acall_agent(
|
|
237
|
+
agent_name: str,
|
|
238
|
+
description: str,
|
|
239
|
+
runtime: ToolRuntime,
|
|
240
|
+
) -> str:
|
|
241
|
+
if asyncio.iscoroutinefunction(process_input_async):
|
|
242
|
+
task_description = await process_input_async(description, runtime)
|
|
243
|
+
else:
|
|
244
|
+
task_description = cast(str, process_input_async(description, runtime))
|
|
245
|
+
|
|
246
|
+
if agent_name not in agents_map:
|
|
247
|
+
raise ValueError(f"Agent {agent_name} not found")
|
|
248
|
+
|
|
249
|
+
messages = [HumanMessage(content=task_description)]
|
|
250
|
+
response = await agents_map[agent_name].ainvoke({"messages": messages})
|
|
251
|
+
|
|
252
|
+
if asyncio.iscoroutinefunction(process_output_async):
|
|
253
|
+
response = await process_output_async(
|
|
254
|
+
task_description, response["messages"], runtime
|
|
255
|
+
)
|
|
256
|
+
else:
|
|
257
|
+
response = process_output(task_description, response["messages"], runtime)
|
|
258
|
+
|
|
259
|
+
return response
|
|
260
|
+
|
|
261
|
+
if tool_name is None:
|
|
262
|
+
tool_name = "task"
|
|
263
|
+
|
|
264
|
+
if tool_description is None:
|
|
265
|
+
tool_description = (
|
|
266
|
+
"Launch an ephemeral subagent for a task.\nAvailable agents:\n "
|
|
267
|
+
+ format_sequence(list(agents_map.keys()), with_num=True)
|
|
268
|
+
)
|
|
269
|
+
return StructuredTool.from_function(
|
|
270
|
+
func=call_agent,
|
|
271
|
+
coroutine=acall_agent,
|
|
272
|
+
name=tool_name,
|
|
273
|
+
description=tool_description,
|
|
274
|
+
)
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
from typing import Any, Optional, cast
|
|
2
|
+
|
|
3
|
+
from langchain_core.utils import from_env
|
|
4
|
+
|
|
5
|
+
from langchain_dev_utils._utils import _check_pkg_install
|
|
6
|
+
|
|
7
|
+
from ..types import CompatibilityOptions
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def create_openai_compatible_model(
|
|
11
|
+
model_provider: str,
|
|
12
|
+
base_url: Optional[str] = None,
|
|
13
|
+
compatibility_options: Optional[CompatibilityOptions] = None,
|
|
14
|
+
model_profiles: Optional[dict[str, dict[str, Any]]] = None,
|
|
15
|
+
chat_model_cls_name: Optional[str] = None,
|
|
16
|
+
):
|
|
17
|
+
"""Factory function for creating provider-specific OpenAI-compatible model classes.
|
|
18
|
+
|
|
19
|
+
Dynamically generates model classes for different OpenAI-compatible providers,
|
|
20
|
+
configuring environment variable mappings and default base URLs specific to each provider.
|
|
21
|
+
|
|
22
|
+
Args:
|
|
23
|
+
model_provider (str): Identifier for the OpenAI-compatible provider (e.g. `vllm`, `moonshot`)
|
|
24
|
+
base_url (Optional[str], optional): Default API base URL for the provider. Defaults to None. If not provided, will try to use the environment variable.
|
|
25
|
+
compatibility_options (Optional[CompatibilityOptions], optional): Optional configuration for compatibility options with the provider. Defaults to None.
|
|
26
|
+
model_profiles (Optional[dict[str, dict[str, Any]]], optional): Optional model profiles for the provider. Defaults to None.
|
|
27
|
+
chat_model_cls_name (Optional[str], optional): Optional custom class name for the generated model. Defaults to None.
|
|
28
|
+
Returns:
|
|
29
|
+
Type[_BaseChatOpenAICompatible]: Configured model class ready for instantiation with provider-specific settings
|
|
30
|
+
|
|
31
|
+
Examples:
|
|
32
|
+
>>> from langchain_dev_utils.chat_models.adapters import create_openai_compatible_chat_model
|
|
33
|
+
>>> ChatVLLM = create_openai_compatible_chat_model(
|
|
34
|
+
... "vllm",
|
|
35
|
+
... base_url="http://localhost:8000",
|
|
36
|
+
... chat_model_cls_name="ChatVLLM",
|
|
37
|
+
... )
|
|
38
|
+
>>> model = ChatVLLM(model="qwen3-4b")
|
|
39
|
+
>>> model.invoke("hello")
|
|
40
|
+
"""
|
|
41
|
+
_check_pkg_install("langchain_openai")
|
|
42
|
+
from .openai_compatible import _create_openai_compatible_model
|
|
43
|
+
|
|
44
|
+
base_url = (
|
|
45
|
+
base_url or from_env(f"{model_provider.upper()}_API_BASE", default=None)()
|
|
46
|
+
)
|
|
47
|
+
return _create_openai_compatible_model(
|
|
48
|
+
chat_model_cls_name=chat_model_cls_name,
|
|
49
|
+
provider=model_provider,
|
|
50
|
+
base_url=cast(str, base_url),
|
|
51
|
+
compatibility_options=compatibility_options,
|
|
52
|
+
profiles=model_profiles,
|
|
53
|
+
)
|
|
@@ -12,6 +12,7 @@ from typing import (
|
|
|
12
12
|
Type,
|
|
13
13
|
TypeVar,
|
|
14
14
|
Union,
|
|
15
|
+
cast,
|
|
15
16
|
)
|
|
16
17
|
|
|
17
18
|
import openai
|
|
@@ -19,7 +20,11 @@ from langchain_core.callbacks import (
|
|
|
19
20
|
AsyncCallbackManagerForLLMRun,
|
|
20
21
|
CallbackManagerForLLMRun,
|
|
21
22
|
)
|
|
22
|
-
from langchain_core.language_models import
|
|
23
|
+
from langchain_core.language_models import (
|
|
24
|
+
LangSmithParams,
|
|
25
|
+
LanguageModelInput,
|
|
26
|
+
ModelProfile,
|
|
27
|
+
)
|
|
23
28
|
from langchain_core.messages import (
|
|
24
29
|
AIMessage,
|
|
25
30
|
AIMessageChunk,
|
|
@@ -51,6 +56,10 @@ from ..types import (
|
|
|
51
56
|
ResponseFormatType,
|
|
52
57
|
ToolChoiceType,
|
|
53
58
|
)
|
|
59
|
+
from .register_profiles import (
|
|
60
|
+
_get_profile_by_provider_and_model,
|
|
61
|
+
_register_profile_with_provider,
|
|
62
|
+
)
|
|
54
63
|
|
|
55
64
|
_BM = TypeVar("_BM", bound=BaseModel)
|
|
56
65
|
_DictOrPydanticClass = Union[dict[str, Any], type[_BM], type]
|
|
@@ -152,7 +161,7 @@ class _BaseChatOpenAICompatible(BaseChatOpenAI):
|
|
|
152
161
|
Note: This is a template class and should not be exported or instantiated
|
|
153
162
|
directly. Instead, use it as a base class and provide the specific provider
|
|
154
163
|
name through inheritance or the factory function
|
|
155
|
-
`
|
|
164
|
+
`create_openai_compatible_model()`.
|
|
156
165
|
"""
|
|
157
166
|
|
|
158
167
|
model_name: str = Field(alias="model", default="openai compatible model")
|
|
@@ -283,7 +292,10 @@ class _BaseChatOpenAICompatible(BaseChatOpenAI):
|
|
|
283
292
|
def _set_model_profile(self) -> Self:
|
|
284
293
|
"""Set model profile if not overridden."""
|
|
285
294
|
if self.profile is None:
|
|
286
|
-
self.profile =
|
|
295
|
+
self.profile = cast(
|
|
296
|
+
ModelProfile,
|
|
297
|
+
_get_profile_by_provider_and_model(self._provider, self.model_name),
|
|
298
|
+
)
|
|
287
299
|
return self
|
|
288
300
|
|
|
289
301
|
def _create_chat_result(
|
|
@@ -578,6 +590,8 @@ def _create_openai_compatible_model(
|
|
|
578
590
|
provider: str,
|
|
579
591
|
base_url: str,
|
|
580
592
|
compatibility_options: Optional[CompatibilityOptions] = None,
|
|
593
|
+
profiles: Optional[dict[str, dict[str, Any]]] = None,
|
|
594
|
+
chat_model_cls_name: Optional[str] = None,
|
|
581
595
|
) -> Type[_BaseChatOpenAICompatible]:
|
|
582
596
|
"""Factory function for creating provider-specific OpenAI-compatible model classes.
|
|
583
597
|
|
|
@@ -588,14 +602,19 @@ def _create_openai_compatible_model(
|
|
|
588
602
|
provider: Provider identifier (e.g.`vllm`)
|
|
589
603
|
base_url: Default API base URL for the provider
|
|
590
604
|
compatibility_options: Optional configuration for the provider
|
|
605
|
+
profiles: Optional profiles for the provider
|
|
606
|
+
chat_model_cls_name: Optional name for the model class
|
|
591
607
|
|
|
592
608
|
Returns:
|
|
593
609
|
Configured model class ready for instantiation with provider-specific settings
|
|
594
610
|
"""
|
|
595
|
-
chat_model_cls_name = f"Chat{provider.title()}"
|
|
611
|
+
chat_model_cls_name = chat_model_cls_name or f"Chat{provider.title()}"
|
|
596
612
|
if compatibility_options is None:
|
|
597
613
|
compatibility_options = {}
|
|
598
614
|
|
|
615
|
+
if profiles is not None:
|
|
616
|
+
_register_profile_with_provider(provider, profiles)
|
|
617
|
+
|
|
599
618
|
return create_model(
|
|
600
619
|
chat_model_cls_name,
|
|
601
620
|
__base__=_BaseChatOpenAICompatible,
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
_PROFILES = {}
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def _register_profile_with_provider(
|
|
7
|
+
provider_name: str, profile: dict[str, Any]
|
|
8
|
+
) -> None:
|
|
9
|
+
_PROFILES.update({provider_name: profile})
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def _get_profile_by_provider_and_model(
|
|
13
|
+
provider_name: str, model_name: str
|
|
14
|
+
) -> dict[str, Any]:
|
|
15
|
+
return _PROFILES.get(provider_name, {}).get(model_name, {})
|
|
@@ -141,19 +141,12 @@ def register_model_provider(
|
|
|
141
141
|
"when chat_model is a string, the value must be 'openai-compatible'"
|
|
142
142
|
)
|
|
143
143
|
chat_model = _create_openai_compatible_model(
|
|
144
|
-
provider_name,
|
|
145
|
-
base_url,
|
|
144
|
+
provider=provider_name,
|
|
145
|
+
base_url=base_url,
|
|
146
146
|
compatibility_options=compatibility_options,
|
|
147
|
+
profiles=model_profiles,
|
|
147
148
|
)
|
|
148
|
-
_MODEL_PROVIDERS_DICT.update(
|
|
149
|
-
{
|
|
150
|
-
provider_name: {
|
|
151
|
-
"chat_model": chat_model,
|
|
152
|
-
"base_url": base_url,
|
|
153
|
-
"model_profiles": model_profiles,
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
)
|
|
149
|
+
_MODEL_PROVIDERS_DICT.update({provider_name: {"chat_model": chat_model}})
|
|
157
150
|
else:
|
|
158
151
|
if base_url is not None:
|
|
159
152
|
_MODEL_PROVIDERS_DICT.update(
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
from typing import Optional, cast
|
|
2
|
+
|
|
3
|
+
from langchain_core.utils import from_env
|
|
4
|
+
|
|
5
|
+
from langchain_dev_utils._utils import _check_pkg_install
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def create_openai_compatible_embedding(
|
|
9
|
+
embedding_provider: str,
|
|
10
|
+
base_url: Optional[str] = None,
|
|
11
|
+
embedding_model_cls_name: Optional[str] = None,
|
|
12
|
+
):
|
|
13
|
+
"""Factory function for creating provider-specific OpenAI-compatible embedding classes.
|
|
14
|
+
|
|
15
|
+
Dynamically generates embedding classes for different OpenAI-compatible providers,
|
|
16
|
+
configuring environment variable mappings and default base URLs specific to each provider.
|
|
17
|
+
|
|
18
|
+
Args:
|
|
19
|
+
embedding_provider (str): Identifier for the OpenAI-compatible provider (e.g. `vllm`, `moonshot`)
|
|
20
|
+
base_url (Optional[str], optional): Default API base URL for the provider. Defaults to None. If not provided, will try to use the environment variable.
|
|
21
|
+
embedding_model_cls_name (Optional[str], optional): Optional custom class name for the generated embedding. Defaults to None.
|
|
22
|
+
Returns:
|
|
23
|
+
Type[_BaseEmbeddingOpenAICompatible]: Configured embedding class ready for instantiation with provider-specific settings
|
|
24
|
+
|
|
25
|
+
Examples:
|
|
26
|
+
>>> from langchain_dev_utils.embeddings.adapters import create_openai_compatible_embedding
|
|
27
|
+
>>> VLLMEmbedding = create_openai_compatible_embedding(
|
|
28
|
+
... "vllm",
|
|
29
|
+
... base_url="http://localhost:8000",
|
|
30
|
+
... embedding_model_cls_name="VLLMEmbedding",
|
|
31
|
+
... )
|
|
32
|
+
>>> model = VLLMEmbedding(model="qwen3-embedding-8b")
|
|
33
|
+
>>> model.embed_query("hello")
|
|
34
|
+
"""
|
|
35
|
+
_check_pkg_install("langchain_openai")
|
|
36
|
+
from .openai_compatible import _create_openai_compatible_embedding
|
|
37
|
+
|
|
38
|
+
base_url = (
|
|
39
|
+
base_url or from_env(f"{embedding_provider.upper()}_API_BASE", default=None)()
|
|
40
|
+
)
|
|
41
|
+
return _create_openai_compatible_embedding(
|
|
42
|
+
provider=embedding_provider,
|
|
43
|
+
base_url=cast(str, base_url),
|
|
44
|
+
embeddings_cls_name=embedding_model_cls_name,
|
|
45
|
+
)
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
from typing import Optional, Type
|
|
2
|
+
|
|
3
|
+
from langchain_core.utils import from_env, secret_from_env
|
|
4
|
+
from langchain_openai.embeddings import OpenAIEmbeddings
|
|
5
|
+
from pydantic import Field, SecretStr, create_model
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class _BaseEmbeddingOpenAICompatible(OpenAIEmbeddings):
|
|
9
|
+
"""Base class for OpenAI-Compatible embeddings.
|
|
10
|
+
|
|
11
|
+
This class extends the OpenAIEmbeddings class to support
|
|
12
|
+
custom API keys and base URLs for OpenAI-Compatible models.
|
|
13
|
+
|
|
14
|
+
Note: This is a template class and should not be exported or instantiated
|
|
15
|
+
directly. Instead, use it as a base class and provide the specific provider
|
|
16
|
+
name through inheritance or the factory function
|
|
17
|
+
`create_openai_compatible_embedding()`.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
openai_api_key: Optional[SecretStr] = Field(
|
|
21
|
+
default_factory=secret_from_env("OPENAI_COMPATIBLE_API_KEY", default=None),
|
|
22
|
+
alias="api_key",
|
|
23
|
+
)
|
|
24
|
+
"""OpenAI Compatible API key"""
|
|
25
|
+
openai_api_base: str = Field(
|
|
26
|
+
default_factory=from_env("OPENAI_COMPATIBLE_API_BASE", default=""),
|
|
27
|
+
alias="base_url",
|
|
28
|
+
)
|
|
29
|
+
"""OpenAI Compatible API base URL"""
|
|
30
|
+
|
|
31
|
+
check_embedding_ctx_length: bool = False
|
|
32
|
+
"""Whether to check the token length of inputs and automatically split inputs
|
|
33
|
+
longer than embedding_ctx_length. Defaults to False. """
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def _create_openai_compatible_embedding(
|
|
37
|
+
provider: str,
|
|
38
|
+
base_url: str,
|
|
39
|
+
embeddings_cls_name: Optional[str] = None,
|
|
40
|
+
) -> Type[_BaseEmbeddingOpenAICompatible]:
|
|
41
|
+
"""Factory function for creating provider-specific OpenAI-compatible embeddings classes.
|
|
42
|
+
|
|
43
|
+
Dynamically generates embeddings classes for different OpenAI-compatible providers,
|
|
44
|
+
configuring environment variable mappings and default base URLs specific to each provider.
|
|
45
|
+
|
|
46
|
+
Args:
|
|
47
|
+
provider: Provider identifier (e.g.`vllm`)
|
|
48
|
+
base_url: Default API base URL for the provider
|
|
49
|
+
embeddings_cls_name: Optional custom class name for the generated embeddings. Defaults to None.
|
|
50
|
+
|
|
51
|
+
Returns:
|
|
52
|
+
Configured embeddings class ready for instantiation with provider-specific settings
|
|
53
|
+
"""
|
|
54
|
+
embeddings_cls_name = embeddings_cls_name or f"{provider.title()}Embeddings"
|
|
55
|
+
|
|
56
|
+
return create_model(
|
|
57
|
+
embeddings_cls_name,
|
|
58
|
+
__base__=_BaseEmbeddingOpenAICompatible,
|
|
59
|
+
openai_api_base=(
|
|
60
|
+
str,
|
|
61
|
+
Field(
|
|
62
|
+
default_factory=from_env(
|
|
63
|
+
f"{provider.upper()}_API_BASE", default=base_url
|
|
64
|
+
),
|
|
65
|
+
),
|
|
66
|
+
),
|
|
67
|
+
openai_api_key=(
|
|
68
|
+
str,
|
|
69
|
+
Field(
|
|
70
|
+
default_factory=secret_from_env(
|
|
71
|
+
f"{provider.upper()}_API_KEY", default=None
|
|
72
|
+
),
|
|
73
|
+
),
|
|
74
|
+
),
|
|
75
|
+
)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from typing import Any, Literal, NotRequired, Optional, TypedDict, Union
|
|
2
2
|
|
|
3
3
|
from langchain.embeddings.base import _SUPPORTED_PROVIDERS, Embeddings, init_embeddings
|
|
4
|
-
from langchain_core.utils import from_env
|
|
4
|
+
from langchain_core.utils import from_env
|
|
5
5
|
|
|
6
6
|
from langchain_dev_utils._utils import (
|
|
7
7
|
_check_pkg_install,
|
|
@@ -101,12 +101,16 @@ def register_embeddings_provider(
|
|
|
101
101
|
)
|
|
102
102
|
|
|
103
103
|
_check_pkg_install("langchain_openai")
|
|
104
|
+
from .adapters.openai_compatible import _create_openai_compatible_embedding
|
|
104
105
|
|
|
106
|
+
embeddings_model = _create_openai_compatible_embedding(
|
|
107
|
+
provider=provider_name,
|
|
108
|
+
base_url=base_url,
|
|
109
|
+
)
|
|
105
110
|
_EMBEDDINGS_PROVIDERS_DICT.update(
|
|
106
111
|
{
|
|
107
112
|
provider_name: {
|
|
108
113
|
"embeddings_model": embeddings_model,
|
|
109
|
-
"base_url": base_url,
|
|
110
114
|
}
|
|
111
115
|
}
|
|
112
116
|
)
|
|
@@ -220,28 +224,10 @@ def load_embeddings(
|
|
|
220
224
|
|
|
221
225
|
if provider in _EMBEDDINGS_PROVIDERS_DICT:
|
|
222
226
|
embeddings = _EMBEDDINGS_PROVIDERS_DICT[provider]["embeddings_model"]
|
|
223
|
-
if
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
f"API key for {provider} not found. Please set it in the environment."
|
|
229
|
-
)
|
|
230
|
-
kwargs["api_key"] = api_key
|
|
231
|
-
if embeddings == "openai-compatible":
|
|
232
|
-
kwargs["check_embedding_ctx_length"] = False
|
|
233
|
-
embeddings = "openai"
|
|
234
|
-
return init_embeddings(
|
|
235
|
-
model=model,
|
|
236
|
-
provider=embeddings,
|
|
237
|
-
base_url=_EMBEDDINGS_PROVIDERS_DICT[provider]["base_url"],
|
|
238
|
-
**kwargs,
|
|
239
|
-
)
|
|
240
|
-
else:
|
|
241
|
-
if base_url := _EMBEDDINGS_PROVIDERS_DICT[provider].get("base_url"):
|
|
242
|
-
url_key = _get_base_url_field_name(embeddings)
|
|
243
|
-
if url_key is not None:
|
|
244
|
-
kwargs.update({url_key: base_url})
|
|
245
|
-
return embeddings(model=model, **kwargs)
|
|
227
|
+
if base_url := _EMBEDDINGS_PROVIDERS_DICT[provider].get("base_url"):
|
|
228
|
+
url_key = _get_base_url_field_name(embeddings)
|
|
229
|
+
if url_key is not None:
|
|
230
|
+
kwargs.update({url_key: base_url})
|
|
231
|
+
return embeddings(model=model, **kwargs)
|
|
246
232
|
else:
|
|
247
233
|
return init_embeddings(model, provider=provider, **kwargs)
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
from .content import (
|
|
2
|
-
aconvert_reasoning_content_for_chunk_iterator,
|
|
3
|
-
convert_reasoning_content_for_ai_message,
|
|
4
|
-
convert_reasoning_content_for_chunk_iterator,
|
|
5
|
-
merge_ai_message_chunk,
|
|
6
|
-
)
|
|
7
|
-
from .format import format_sequence
|
|
8
|
-
|
|
9
|
-
__all__ = [
|
|
10
|
-
"convert_reasoning_content_for_ai_message",
|
|
11
|
-
"convert_reasoning_content_for_chunk_iterator",
|
|
12
|
-
"aconvert_reasoning_content_for_chunk_iterator",
|
|
13
|
-
"merge_ai_message_chunk",
|
|
14
|
-
"format_sequence",
|
|
15
|
-
]
|
|
1
|
+
from .content import (
|
|
2
|
+
aconvert_reasoning_content_for_chunk_iterator,
|
|
3
|
+
convert_reasoning_content_for_ai_message,
|
|
4
|
+
convert_reasoning_content_for_chunk_iterator,
|
|
5
|
+
merge_ai_message_chunk,
|
|
6
|
+
)
|
|
7
|
+
from .format import format_sequence
|
|
8
|
+
|
|
9
|
+
__all__ = [
|
|
10
|
+
"convert_reasoning_content_for_ai_message",
|
|
11
|
+
"convert_reasoning_content_for_chunk_iterator",
|
|
12
|
+
"aconvert_reasoning_content_for_chunk_iterator",
|
|
13
|
+
"merge_ai_message_chunk",
|
|
14
|
+
"format_sequence",
|
|
15
|
+
]
|
|
@@ -1,69 +1,69 @@
|
|
|
1
|
-
from typing import Sequence, Union
|
|
2
|
-
|
|
3
|
-
from langchain_core.documents import Document
|
|
4
|
-
from langchain_core.messages import (
|
|
5
|
-
AIMessage,
|
|
6
|
-
BaseMessage,
|
|
7
|
-
HumanMessage,
|
|
8
|
-
SystemMessage,
|
|
9
|
-
ToolMessage,
|
|
10
|
-
)
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
def format_sequence(
|
|
14
|
-
inputs: Union[Sequence[Document], Sequence[BaseMessage], Sequence[str]],
|
|
15
|
-
separator: str = "-",
|
|
16
|
-
with_num: bool = False,
|
|
17
|
-
) -> str:
|
|
18
|
-
"""Convert a list of messages, documents, or strings into a formatted string.
|
|
19
|
-
|
|
20
|
-
This function extracts text content from various types (e.g., HumanMessage, Document)
|
|
21
|
-
and joins them into a single string. Optionally adds serial numbers and a custom
|
|
22
|
-
separator between items.
|
|
23
|
-
|
|
24
|
-
Args:
|
|
25
|
-
inputs: A list of inputs. Supported types:
|
|
26
|
-
- langchain_core.messages: HumanMessage, AIMessage, SystemMessage, ToolMessage
|
|
27
|
-
- langchain_core.documents.Document
|
|
28
|
-
- str
|
|
29
|
-
separator: The separator used to join the items. Defaults to "-".
|
|
30
|
-
with_num: If True, prefixes each item with a serial number (e.g., "1. Hello").
|
|
31
|
-
Defaults to False.
|
|
32
|
-
|
|
33
|
-
Returns:
|
|
34
|
-
A formatted string composed of the input contents, joined by `separator`.
|
|
35
|
-
|
|
36
|
-
Example:
|
|
37
|
-
# Format messages with default separator:
|
|
38
|
-
>>> from langchain_dev_utils.message_convert import format_sequence
|
|
39
|
-
>>> from langchain_core.messages import HumanMessage, AIMessage
|
|
40
|
-
>>> messages = [
|
|
41
|
-
... HumanMessage(content="Hello, how are you?"),
|
|
42
|
-
... AIMessage(content="I'm doing well, thank you!")
|
|
43
|
-
... ]
|
|
44
|
-
>>> formatted = format_sequence(messages)
|
|
45
|
-
>>> formatted
|
|
46
|
-
|
|
47
|
-
# Format with custom separator and numbering:
|
|
48
|
-
>>> formatted = format_sequence(messages, separator="---", with_num=True)
|
|
49
|
-
>>> formatted
|
|
50
|
-
"""
|
|
51
|
-
if not inputs:
|
|
52
|
-
return ""
|
|
53
|
-
|
|
54
|
-
outputs = []
|
|
55
|
-
|
|
56
|
-
for input_item in inputs:
|
|
57
|
-
if isinstance(
|
|
58
|
-
input_item, (HumanMessage, AIMessage, SystemMessage, ToolMessage)
|
|
59
|
-
):
|
|
60
|
-
outputs.append(input_item.content)
|
|
61
|
-
elif isinstance(input_item, Document):
|
|
62
|
-
outputs.append(input_item.page_content)
|
|
63
|
-
elif isinstance(input_item, str):
|
|
64
|
-
outputs.append(input_item)
|
|
65
|
-
if with_num:
|
|
66
|
-
outputs = [f"{i + 1}. {output}" for i, output in enumerate(outputs)]
|
|
67
|
-
|
|
68
|
-
str_ = "\n" + separator
|
|
69
|
-
return separator + str_.join(outputs)
|
|
1
|
+
from typing import Sequence, Union
|
|
2
|
+
|
|
3
|
+
from langchain_core.documents import Document
|
|
4
|
+
from langchain_core.messages import (
|
|
5
|
+
AIMessage,
|
|
6
|
+
BaseMessage,
|
|
7
|
+
HumanMessage,
|
|
8
|
+
SystemMessage,
|
|
9
|
+
ToolMessage,
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def format_sequence(
|
|
14
|
+
inputs: Union[Sequence[Document], Sequence[BaseMessage], Sequence[str]],
|
|
15
|
+
separator: str = "-",
|
|
16
|
+
with_num: bool = False,
|
|
17
|
+
) -> str:
|
|
18
|
+
"""Convert a list of messages, documents, or strings into a formatted string.
|
|
19
|
+
|
|
20
|
+
This function extracts text content from various types (e.g., HumanMessage, Document)
|
|
21
|
+
and joins them into a single string. Optionally adds serial numbers and a custom
|
|
22
|
+
separator between items.
|
|
23
|
+
|
|
24
|
+
Args:
|
|
25
|
+
inputs: A list of inputs. Supported types:
|
|
26
|
+
- langchain_core.messages: HumanMessage, AIMessage, SystemMessage, ToolMessage
|
|
27
|
+
- langchain_core.documents.Document
|
|
28
|
+
- str
|
|
29
|
+
separator: The separator used to join the items. Defaults to "-".
|
|
30
|
+
with_num: If True, prefixes each item with a serial number (e.g., "1. Hello").
|
|
31
|
+
Defaults to False.
|
|
32
|
+
|
|
33
|
+
Returns:
|
|
34
|
+
A formatted string composed of the input contents, joined by `separator`.
|
|
35
|
+
|
|
36
|
+
Example:
|
|
37
|
+
# Format messages with default separator:
|
|
38
|
+
>>> from langchain_dev_utils.message_convert import format_sequence
|
|
39
|
+
>>> from langchain_core.messages import HumanMessage, AIMessage
|
|
40
|
+
>>> messages = [
|
|
41
|
+
... HumanMessage(content="Hello, how are you?"),
|
|
42
|
+
... AIMessage(content="I'm doing well, thank you!")
|
|
43
|
+
... ]
|
|
44
|
+
>>> formatted = format_sequence(messages)
|
|
45
|
+
>>> formatted
|
|
46
|
+
|
|
47
|
+
# Format with custom separator and numbering:
|
|
48
|
+
>>> formatted = format_sequence(messages, separator="---", with_num=True)
|
|
49
|
+
>>> formatted
|
|
50
|
+
"""
|
|
51
|
+
if not inputs:
|
|
52
|
+
return ""
|
|
53
|
+
|
|
54
|
+
outputs = []
|
|
55
|
+
|
|
56
|
+
for input_item in inputs:
|
|
57
|
+
if isinstance(
|
|
58
|
+
input_item, (HumanMessage, AIMessage, SystemMessage, ToolMessage)
|
|
59
|
+
):
|
|
60
|
+
outputs.append(input_item.content)
|
|
61
|
+
elif isinstance(input_item, Document):
|
|
62
|
+
outputs.append(input_item.page_content)
|
|
63
|
+
elif isinstance(input_item, str):
|
|
64
|
+
outputs.append(input_item)
|
|
65
|
+
if with_num:
|
|
66
|
+
outputs = [f"{i + 1}. {output}" for i, output in enumerate(outputs)]
|
|
67
|
+
|
|
68
|
+
str_ = "\n" + separator
|
|
69
|
+
return separator + str_.join(outputs)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: langchain-dev-utils
|
|
3
|
-
Version: 1.3.
|
|
3
|
+
Version: 1.3.4
|
|
4
4
|
Summary: A practical utility library for LangChain and LangGraph development
|
|
5
5
|
Project-URL: Source Code, https://github.com/TBice123123/langchain-dev-utils
|
|
6
6
|
Project-URL: repository, https://github.com/TBice123123/langchain-dev-utils
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
langchain_dev_utils/__init__.py,sha256=
|
|
1
|
+
langchain_dev_utils/__init__.py,sha256=9qxIaE8bFi9OKpc20hJx4mYCCa26qBsDb5ixbbRmD9c,23
|
|
2
2
|
langchain_dev_utils/_utils.py,sha256=MFEzR1BjXMj6HEVwt2x2omttFuDJ_rYAEbNqe99r9pM,1338
|
|
3
3
|
langchain_dev_utils/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
-
langchain_dev_utils/agents/__init__.py,sha256=
|
|
4
|
+
langchain_dev_utils/agents/__init__.py,sha256=69_biZzyJvW9OBT1g8TX_77mp9-I_TvWo9QtlvHq83E,177
|
|
5
5
|
langchain_dev_utils/agents/factory.py,sha256=8XB6y_ddf58vXlTLHBL6KCirFqkD2GjtzsuOt98sS7U,3732
|
|
6
6
|
langchain_dev_utils/agents/file_system.py,sha256=Yk3eetREE26WNrnTWLoiDUpOyCJ-rhjlfFDk6foLa1E,8468
|
|
7
7
|
langchain_dev_utils/agents/plan.py,sha256=WwhoiJBmVYVI9bT8HfjCzTJ_SIp9WFil0gOeznv2omQ,6497
|
|
8
|
-
langchain_dev_utils/agents/wrap.py,sha256=
|
|
8
|
+
langchain_dev_utils/agents/wrap.py,sha256=dJbCvljyw-ee43__2uws4H4ZhsyyX1AuavNtHrdWqN8,9485
|
|
9
9
|
langchain_dev_utils/agents/middleware/__init__.py,sha256=QVQibaNHvHPyNTZ2UNFfYL153ZboaCHcoioTHK0FsiY,710
|
|
10
10
|
langchain_dev_utils/agents/middleware/format_prompt.py,sha256=LzYiQXCRvkpfDhGPxhZwdepeU3j-HUWPJqcx3FWsfT4,2357
|
|
11
|
-
langchain_dev_utils/agents/middleware/handoffs.py,sha256=
|
|
11
|
+
langchain_dev_utils/agents/middleware/handoffs.py,sha256=r196Xk0Jws1Tz6JQuvy5HEc3HAAQejCxFmJpB6KrvLU,7230
|
|
12
12
|
langchain_dev_utils/agents/middleware/model_fallback.py,sha256=8xiNjTJ0yiRkPLCRfAGNnqY1TLstj1Anmiqyv5w2mA8,1633
|
|
13
13
|
langchain_dev_utils/agents/middleware/model_router.py,sha256=qBspvj9ZoKfmC1pHWTO0EHHfxjgCUd-TuSbqvZl0kmg,7977
|
|
14
14
|
langchain_dev_utils/agents/middleware/plan.py,sha256=-ZLkp85QQTSCX9thMblacJ1N86h0BYPoTwCfJlJ_jzQ,14981
|
|
@@ -17,15 +17,20 @@ langchain_dev_utils/agents/middleware/tool_call_repair.py,sha256=oZF0Oejemqs9kSn
|
|
|
17
17
|
langchain_dev_utils/agents/middleware/tool_emulator.py,sha256=OgtPhqturaWzF4fRSJ3f_IXvIrYrrAjlpOC5zmLtrkY,2031
|
|
18
18
|
langchain_dev_utils/agents/middleware/tool_selection.py,sha256=dRH5ejR6N02Djwxt6Gd63MYkg6SV5pySlzaRt53OoZk,3113
|
|
19
19
|
langchain_dev_utils/chat_models/__init__.py,sha256=YSLUyHrWEEj4y4DtGFCOnDW02VIYZdfAH800m4Klgeg,224
|
|
20
|
-
langchain_dev_utils/chat_models/base.py,sha256=
|
|
20
|
+
langchain_dev_utils/chat_models/base.py,sha256=X76uaPoJDOLRphFyyeFH_RgEIvPcMoZEZWuRtjPCpl0,11486
|
|
21
21
|
langchain_dev_utils/chat_models/types.py,sha256=MD3cv_ZIe9fCdgwisNfuxAOhy-j4YSs1ZOQYyCjlNKs,927
|
|
22
|
-
langchain_dev_utils/chat_models/adapters/__init__.py,sha256=
|
|
23
|
-
langchain_dev_utils/chat_models/adapters/
|
|
22
|
+
langchain_dev_utils/chat_models/adapters/__init__.py,sha256=4tTbhAAQdpX_gWyWeH97hqS5HnaoqQqW6QBh9Qd1SKs,106
|
|
23
|
+
langchain_dev_utils/chat_models/adapters/create_utils.py,sha256=r8_XWLNF3Yc6sumlBhmgG1QcBa4Dsba7X3f_9YeMeGA,2479
|
|
24
|
+
langchain_dev_utils/chat_models/adapters/openai_compatible.py,sha256=A3_NcmnsrCrHgm1-mGT-JqQVYUBsOzFH0KzSNX6edbY,24876
|
|
25
|
+
langchain_dev_utils/chat_models/adapters/register_profiles.py,sha256=YS9ItCEq2ISoB_bp6QH5NVKOVR9-7la3r7B_xQNxZxE,366
|
|
24
26
|
langchain_dev_utils/embeddings/__init__.py,sha256=zbEOaV86TUi9Zrg_dH9dpdgacWg31HMJTlTQknA9EKk,244
|
|
25
|
-
langchain_dev_utils/embeddings/base.py,sha256=
|
|
26
|
-
langchain_dev_utils/
|
|
27
|
+
langchain_dev_utils/embeddings/base.py,sha256=_no5sGEiBZENaHLWzwLB45tTsDj-bha7nt1GUhWBmP4,8731
|
|
28
|
+
langchain_dev_utils/embeddings/adapters/__init__.py,sha256=yJEZZdzZ2fv1ExezLaNxo0VU9HJTHKYbS3T_XP8Ab9c,114
|
|
29
|
+
langchain_dev_utils/embeddings/adapters/create_utils.py,sha256=K4JlbjG-O5xLY3wxaVt0UZ3QwI--cVb4qyxLATKVAWQ,2012
|
|
30
|
+
langchain_dev_utils/embeddings/adapters/openai_compatible.py,sha256=fPX1GpJ6nwadbVu7mAMEVTIvGL2ZvtfRwkld2CJeHng,2767
|
|
31
|
+
langchain_dev_utils/message_convert/__init__.py,sha256=nnkDa_Im0dCb5u4aa2FRB9tqB8e6H6sEGYK6Vg81u2s,472
|
|
27
32
|
langchain_dev_utils/message_convert/content.py,sha256=2V1g21byg3iLv5RjUW8zv3jwYwV7IH2hNim7jGRsIes,8096
|
|
28
|
-
langchain_dev_utils/message_convert/format.py,sha256=
|
|
33
|
+
langchain_dev_utils/message_convert/format.py,sha256=NdrYX0cJn2-G1ArLSjJ7yO788KV1d83F4Kimpyft0IM,2446
|
|
29
34
|
langchain_dev_utils/pipeline/__init__.py,sha256=eE6WktaLHDkqMeXDIDaLtm-OPTwtsX_Av8iK9uYrceo,186
|
|
30
35
|
langchain_dev_utils/pipeline/parallel.py,sha256=nwZWbdSNeyanC9WufoJBTceotgT--UnPOfStXjgNMOc,5271
|
|
31
36
|
langchain_dev_utils/pipeline/sequential.py,sha256=sYJXQzVHDKUc-UV-HMv38JTPnse1A7sRM0vqSdpHK0k,3850
|
|
@@ -33,7 +38,7 @@ langchain_dev_utils/pipeline/types.py,sha256=T3aROKKXeWvd0jcH5XkgMDQfEkLfPaiOhhV
|
|
|
33
38
|
langchain_dev_utils/tool_calling/__init__.py,sha256=mu_WxKMcu6RoTf4vkTPbA1WSBSNc6YIqyBtOQ6iVQj4,322
|
|
34
39
|
langchain_dev_utils/tool_calling/human_in_the_loop.py,sha256=7Z_QO5OZUR6K8nLoIcafc6osnvX2IYNorOJcbx6bVso,9672
|
|
35
40
|
langchain_dev_utils/tool_calling/utils.py,sha256=S4-KXQ8jWmpGTXYZitovF8rxKpaSSUkFruM8LDwvcvE,2765
|
|
36
|
-
langchain_dev_utils-1.3.
|
|
37
|
-
langchain_dev_utils-1.3.
|
|
38
|
-
langchain_dev_utils-1.3.
|
|
39
|
-
langchain_dev_utils-1.3.
|
|
41
|
+
langchain_dev_utils-1.3.4.dist-info/METADATA,sha256=K8AGEzWWmv-5HYzuNmmu3tboFyikx9zZjoj7H8Pald0,4552
|
|
42
|
+
langchain_dev_utils-1.3.4.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
43
|
+
langchain_dev_utils-1.3.4.dist-info/licenses/LICENSE,sha256=AWAOzNEcsvCEzHOF0qby5OKxviVH_eT9Yce1sgJTico,1084
|
|
44
|
+
langchain_dev_utils-1.3.4.dist-info/RECORD,,
|
|
File without changes
|
{langchain_dev_utils-1.3.2.dist-info → langchain_dev_utils-1.3.4.dist-info}/licenses/LICENSE
RENAMED
|
File without changes
|