langchain-dev-utils 1.3.1__py3-none-any.whl → 1.3.3__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.
@@ -1 +1 @@
1
- __version__ = "1.3.1"
1
+ __version__ = "1.3.3"
@@ -1,4 +1,4 @@
1
1
  from .factory import create_agent
2
- from .wrap import wrap_agent_as_tool
2
+ from .wrap import wrap_agent_as_tool, wrap_all_agents_as_tool
3
3
 
4
- __all__ = ["create_agent", "wrap_agent_as_tool"]
4
+ __all__ = ["create_agent", "wrap_agent_as_tool", "wrap_all_agents_as_tool"]
@@ -1,13 +1,8 @@
1
1
  from .format_prompt import format_prompt
2
- from .handoffs import HandoffsAgentMiddleware, create_handoffs_tool
2
+ from .handoffs import HandoffAgentMiddleware
3
3
  from .model_fallback import ModelFallbackMiddleware
4
4
  from .model_router import ModelRouterMiddleware
5
- from .plan import (
6
- PlanMiddleware,
7
- create_finish_sub_plan_tool,
8
- create_read_plan_tool,
9
- create_write_plan_tool,
10
- )
5
+ from .plan import PlanMiddleware
11
6
  from .summarization import SummarizationMiddleware
12
7
  from .tool_call_repair import ToolCallRepairMiddleware
13
8
  from .tool_emulator import LLMToolEmulator
@@ -17,14 +12,10 @@ __all__ = [
17
12
  "SummarizationMiddleware",
18
13
  "LLMToolSelectorMiddleware",
19
14
  "PlanMiddleware",
20
- "create_finish_sub_plan_tool",
21
- "create_read_plan_tool",
22
- "create_write_plan_tool",
23
15
  "ModelFallbackMiddleware",
24
16
  "LLMToolEmulator",
25
17
  "ModelRouterMiddleware",
26
18
  "ToolCallRepairMiddleware",
27
19
  "format_prompt",
28
- "create_handoffs_tool",
29
- "HandoffsAgentMiddleware",
20
+ "HandoffAgentMiddleware",
30
21
  ]
@@ -1,4 +1,4 @@
1
- from typing import Any, Awaitable, Callable
1
+ from typing import Any, Awaitable, Callable, Literal
2
2
 
3
3
  from langchain.agents import AgentState
4
4
  from langchain.agents.middleware import AgentMiddleware, ModelRequest, ModelResponse
@@ -19,35 +19,24 @@ class MultiAgentState(AgentState):
19
19
  class AgentConfig(TypedDict):
20
20
  model: NotRequired[str | BaseChatModel]
21
21
  prompt: str | SystemMessage
22
- tools: list[BaseTool | dict[str, Any]]
22
+ tools: NotRequired[list[BaseTool | dict[str, Any]]]
23
23
  default: NotRequired[bool]
24
+ handoffs: list[str] | Literal["all"]
24
25
 
25
26
 
26
- def create_handoffs_tool(
27
- agent_name: str,
28
- tool_name: Optional[str] = None,
29
- tool_description: Optional[str] = None,
30
- ):
27
+ def _create_handoffs_tool(agent_name: str, tool_description: Optional[str] = None):
31
28
  """Create a tool for handoffs to a specified agent.
32
29
 
33
30
  Args:
34
31
  agent_name (str): The name of the agent to transfer to.
35
- tool_name (Optional[str], optional): The name of the tool. Defaults to None.
36
- tool_description (Optional[str], optional): The description of the tool. Defaults to None.
37
32
 
38
33
  Returns:
39
34
  BaseTool: A tool instance for handoffs to the specified agent.
40
-
41
- Example:
42
- Basic usage
43
- >>> from langchain_dev_utils.agents.middleware import create_handoffs_tool
44
- >>> handoffs_tool = create_handoffs_tool("time_agent")
45
35
  """
46
- if tool_name is None:
47
- tool_name = f"transfer_to_{agent_name}"
48
- if not tool_name.endswith("_agent"):
49
- tool_name += "_agent"
50
36
 
37
+ tool_name = f"transfer_to_{agent_name}"
38
+ if not tool_name.endswith("_agent"):
39
+ tool_name += "_agent"
51
40
  if tool_description is None:
52
41
  tool_description = f"Transfer to the {agent_name}"
53
42
 
@@ -75,30 +64,107 @@ def _get_default_active_agent(state: dict[str, AgentConfig]) -> Optional[str]:
75
64
  return None
76
65
 
77
66
 
78
- class HandoffsAgentMiddleware(AgentMiddleware):
67
+ def _transform_agent_config(
68
+ config: dict[str, AgentConfig],
69
+ handoffs_tools: list[BaseTool],
70
+ ) -> dict[str, AgentConfig]:
71
+ """Transform the agent config to add handoffs tools.
72
+
73
+ Args:
74
+ config (dict[str, AgentConfig]): The agent config.
75
+ handoffs_tools (list[BaseTool]): The list of handoffs tools.
76
+
77
+ Returns:
78
+ dict[str, AgentConfig]: The transformed agent config.
79
+ """
80
+
81
+ new_config = {}
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
+
94
+ handoffs = _cfg.get("handoffs", [])
95
+ if handoffs == "all":
96
+ handoff_tools = [
97
+ handoff_tool
98
+ for handoff_tool in handoffs_tools
99
+ if handoff_tool.name != f"transfer_to_{agent_name}"
100
+ ]
101
+ else:
102
+ if not isinstance(handoffs, list):
103
+ raise ValueError(
104
+ f"handoffs for agent {agent_name} must be a list of agent names or 'all'"
105
+ )
106
+
107
+ handoff_tools = [
108
+ handoff_tool
109
+ for handoff_tool in handoffs_tools
110
+ if handoff_tool.name
111
+ in [
112
+ f"transfer_to_{_handoff_agent_name}"
113
+ for _handoff_agent_name in handoffs
114
+ ]
115
+ ]
116
+
117
+ new_config[agent_name]["tools"] = [
118
+ *new_config[agent_name].get("tools", []),
119
+ *handoff_tools,
120
+ ]
121
+ return new_config
122
+
123
+
124
+ class HandoffAgentMiddleware(AgentMiddleware):
79
125
  """Agent middleware for switching between multiple agents.
80
126
  This middleware dynamically replaces model call parameters based on the currently active agent configuration, enabling seamless switching between different agents.
81
127
 
82
128
  Args:
83
129
  agents_config (dict[str, AgentConfig]): A dictionary of agent configurations.
130
+ custom_handoffs_tool_descriptions (Optional[dict[str, str]]): A dictionary of custom tool descriptions for handoffs tools. Defaults to None.
84
131
 
85
132
  Examples:
86
133
  ```python
87
- from langchain_dev_utils.agents.middleware import HandoffsAgentMiddleware
88
- middleware = HandoffsAgentMiddleware(agents_config)
134
+ from langchain_dev_utils.agents.middleware import HandoffAgentMiddleware
135
+ middleware = HandoffAgentMiddleware(agents_config)
89
136
  ```
90
137
  """
91
138
 
92
139
  state_schema = MultiAgentState
93
140
 
94
- def __init__(self, agents_config: dict[str, AgentConfig]):
141
+ def __init__(
142
+ self,
143
+ agents_config: dict[str, AgentConfig],
144
+ custom_handoffs_tool_descriptions: Optional[dict[str, str]] = None,
145
+ ) -> None:
95
146
  default_agent_name = _get_default_active_agent(agents_config)
96
147
  if default_agent_name is None:
97
148
  raise ValueError(
98
149
  "No default agent found, you must set one by set default=True"
99
150
  )
151
+
152
+ if custom_handoffs_tool_descriptions is None:
153
+ custom_handoffs_tool_descriptions = {}
154
+
155
+ handoffs_tools = [
156
+ _create_handoffs_tool(
157
+ agent_name,
158
+ custom_handoffs_tool_descriptions.get(agent_name),
159
+ )
160
+ for agent_name in agents_config.keys()
161
+ ]
100
162
  self.default_agent_name = default_agent_name
101
- self.agents_config = agents_config
163
+ self.agents_config = _transform_agent_config(
164
+ agents_config,
165
+ handoffs_tools,
166
+ )
167
+ self.tools = handoffs_tools
102
168
 
103
169
  def _get_active_agent_config(self, request: ModelRequest) -> dict[str, Any]:
104
170
  active_agent_name = request.state.get("active_agent", self.default_agent_name)
@@ -104,9 +104,14 @@ class PlanState(AgentState):
104
104
  plan: NotRequired[list[Plan]]
105
105
 
106
106
 
107
- def create_write_plan_tool(
107
+ class PlanToolDescription(TypedDict):
108
+ write_plan: NotRequired[str]
109
+ finish_sub_plan: NotRequired[str]
110
+ read_plan: NotRequired[str]
111
+
112
+
113
+ def _create_write_plan_tool(
108
114
  description: Optional[str] = None,
109
- message_key: Optional[str] = None,
110
115
  ) -> BaseTool:
111
116
  """Create a tool for writing initial plan.
112
117
 
@@ -116,22 +121,15 @@ def create_write_plan_tool(
116
121
 
117
122
  Args:
118
123
  description: The description of the tool. Uses default description if not provided.
119
- message_key: The key of the message to be updated. Defaults to "messages".
120
124
 
121
125
  Returns:
122
126
  BaseTool: The tool for writing initial plan.
123
-
124
- Example:
125
- Basic usage:
126
- >>> from langchain_dev_utils.agents.middleware import create_write_plan_tool
127
- >>> write_plan_tool = create_write_plan_tool()
128
127
  """
129
128
 
130
129
  @tool(
131
130
  description=description or _DEFAULT_WRITE_PLAN_TOOL_DESCRIPTION,
132
131
  )
133
132
  def write_plan(plan: list[str], runtime: ToolRuntime):
134
- msg_key = message_key or "messages"
135
133
  return Command(
136
134
  update={
137
135
  "plan": [
@@ -141,7 +139,7 @@ def create_write_plan_tool(
141
139
  }
142
140
  for index, content in enumerate(plan)
143
141
  ],
144
- msg_key: [
142
+ "messages": [
145
143
  ToolMessage(
146
144
  content=f"Plan successfully written, please first execute the {plan[0]} sub-plan (no need to change the status to in_process)",
147
145
  tool_call_id=runtime.tool_call_id,
@@ -153,9 +151,8 @@ def create_write_plan_tool(
153
151
  return write_plan
154
152
 
155
153
 
156
- def create_finish_sub_plan_tool(
154
+ def _create_finish_sub_plan_tool(
157
155
  description: Optional[str] = None,
158
- message_key: Optional[str] = None,
159
156
  ) -> BaseTool:
160
157
  """Create a tool for finishing sub-plan tasks.
161
158
 
@@ -164,15 +161,9 @@ def create_finish_sub_plan_tool(
164
161
 
165
162
  Args:
166
163
  description: The description of the tool. Uses default description if not provided.
167
- message_key: The key of the message to be updated. Defaults to "messages".
168
164
 
169
165
  Returns:
170
166
  BaseTool: The tool for finishing sub-plan tasks.
171
-
172
- Example:
173
- Basic usage:
174
- >>> from langchain_dev_utils.agents.middleware import create_finish_sub_plan_tool
175
- >>> finish_sub_plan_tool = create_finish_sub_plan_tool()
176
167
  """
177
168
 
178
169
  @tool(
@@ -181,7 +172,6 @@ def create_finish_sub_plan_tool(
181
172
  def finish_sub_plan(
182
173
  runtime: ToolRuntime,
183
174
  ):
184
- msg_key = message_key or "messages"
185
175
  plan_list = runtime.state.get("plan", [])
186
176
 
187
177
  sub_finish_plan = ""
@@ -200,7 +190,7 @@ def create_finish_sub_plan_tool(
200
190
  return Command(
201
191
  update={
202
192
  "plan": plan_list,
203
- msg_key: [
193
+ "messages": [
204
194
  ToolMessage(
205
195
  content=sub_finish_plan + sub_next_plan,
206
196
  tool_call_id=runtime.tool_call_id,
@@ -212,7 +202,7 @@ def create_finish_sub_plan_tool(
212
202
  return finish_sub_plan
213
203
 
214
204
 
215
- def create_read_plan_tool(
205
+ def _create_read_plan_tool(
216
206
  description: Optional[str] = None,
217
207
  ):
218
208
  """Create a tool for reading all sub-plans.
@@ -225,11 +215,6 @@ def create_read_plan_tool(
225
215
 
226
216
  Returns:
227
217
  BaseTool: The tool for reading all sub-plans.
228
-
229
- Example:
230
- Basic usage:
231
- >>> from langchain_dev_utils.agents.middleware import create_read_plan_tool
232
- >>> read_plan_tool = create_read_plan_tool()
233
218
  """
234
219
 
235
220
  @tool(
@@ -287,12 +272,8 @@ class PlanMiddleware(AgentMiddleware):
287
272
  tool. If not provided, uses the default `_PLAN_SYSTEM_PROMPT` or
288
273
  `_PLAN_SYSTEM_PROMPT_NOT_READ_PLAN` based on the `use_read_plan_tool`
289
274
  parameter.
290
- write_plan_tool_description: Description of the `write_plan` tool.
291
- If not provided, uses the default `_DEFAULT_WRITE_PLAN_TOOL_DESCRIPTION`.
292
- finish_sub_plan_tool_description: Description of the `finish_sub_plan` tool.
293
- If not provided, uses the default `_DEFAULT_FINISH_SUB_PLAN_TOOL_DESCRIPTION`.
294
- read_plan_tool_description: Description of the `read_plan` tool.
295
- If not provided, uses the default `_DEFAULT_READ_PLAN_TOOL_DESCRIPTION`.
275
+ custom_plan_tool_descriptions: Custom descriptions for the plan tools.
276
+ If not provided, uses the default descriptions.
296
277
  use_read_plan_tool: Whether to use the `read_plan` tool.
297
278
  If not provided, uses the default `True`.
298
279
 
@@ -316,31 +297,34 @@ class PlanMiddleware(AgentMiddleware):
316
297
  self,
317
298
  *,
318
299
  system_prompt: Optional[str] = None,
319
- write_plan_tool_description: Optional[str] = None,
320
- finish_sub_plan_tool_description: Optional[str] = None,
321
- read_plan_tool_description: Optional[str] = None,
300
+ custom_plan_tool_descriptions: Optional[PlanToolDescription] = None,
322
301
  use_read_plan_tool: bool = True,
323
302
  ) -> None:
324
303
  super().__init__()
325
304
 
326
- write_plan_tool_description = (
327
- write_plan_tool_description or _DEFAULT_WRITE_PLAN_TOOL_DESCRIPTION
305
+ if not custom_plan_tool_descriptions:
306
+ custom_plan_tool_descriptions = {}
307
+
308
+ write_plan_tool_description = custom_plan_tool_descriptions.get(
309
+ "write_plan",
310
+ _DEFAULT_WRITE_PLAN_TOOL_DESCRIPTION,
328
311
  )
329
- finish_sub_plan_tool_description = (
330
- finish_sub_plan_tool_description
331
- or _DEFAULT_FINISH_SUB_PLAN_TOOL_DESCRIPTION
312
+ finish_sub_plan_tool_description = custom_plan_tool_descriptions.get(
313
+ "finish_sub_plan",
314
+ _DEFAULT_FINISH_SUB_PLAN_TOOL_DESCRIPTION,
332
315
  )
333
- read_plan_tool_description = (
334
- read_plan_tool_description or _DEFAULT_READ_PLAN_TOOL_DESCRIPTION
316
+ read_plan_tool_description = custom_plan_tool_descriptions.get(
317
+ "read_plan",
318
+ _DEFAULT_READ_PLAN_TOOL_DESCRIPTION,
335
319
  )
336
320
 
337
321
  tools = [
338
- create_write_plan_tool(description=write_plan_tool_description),
339
- create_finish_sub_plan_tool(description=finish_sub_plan_tool_description),
322
+ _create_write_plan_tool(description=write_plan_tool_description),
323
+ _create_finish_sub_plan_tool(description=finish_sub_plan_tool_description),
340
324
  ]
341
325
 
342
326
  if use_read_plan_tool:
343
- tools.append(create_read_plan_tool(description=read_plan_tool_description))
327
+ tools.append(_create_read_plan_tool(description=read_plan_tool_description))
344
328
 
345
329
  if system_prompt is None:
346
330
  if use_read_plan_tool:
@@ -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_time_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
+ )
@@ -134,9 +134,8 @@ class _BaseChatOpenAICompatible(BaseChatOpenAI):
134
134
  from other model providers.
135
135
 
136
136
  **2. Dynamically adapts to choose the most suitable structured-output method**
137
- OpenAICompatibleChatModel adds method="auto" (default), which selects the best
138
- structured-output method (function_calling or json_schema) based on the actual
139
- capabilities of the model provider.
137
+ OpenAICompatibleChatModel selects the best structured-output method (function_calling or json_schema)
138
+ based on the actual capabilities of the model provider.
140
139
 
141
140
  **3. Supports configuration of related parameters**
142
141
  For cases where parameters differ from the official OpenAI API, this library
@@ -527,11 +526,10 @@ class _BaseChatOpenAICompatible(BaseChatOpenAI):
527
526
  schema: Optional[_DictOrPydanticClass] = None,
528
527
  *,
529
528
  method: Literal[
530
- "auto",
531
529
  "function_calling",
532
530
  "json_mode",
533
531
  "json_schema",
534
- ] = "auto",
532
+ ] = "json_schema",
535
533
  include_raw: bool = False,
536
534
  strict: Optional[bool] = None,
537
535
  **kwargs: Any,
@@ -545,7 +543,7 @@ class _BaseChatOpenAICompatible(BaseChatOpenAI):
545
543
 
546
544
  Args:
547
545
  schema: Output schema (Pydantic model class or dictionary definition)
548
- method: Extraction method - defaults to auto,it will choice best method based on provider supported response format
546
+ method: Extraction method - defaults to json_schema, it the provider doesn't support json_schema, it will fallback to function_calling
549
547
  include_raw: Whether to include raw model response alongside parsed output
550
548
  strict: Schema enforcement strictness (provider-dependent)
551
549
  **kwargs: Additional structured output parameters
@@ -553,16 +551,11 @@ class _BaseChatOpenAICompatible(BaseChatOpenAI):
553
551
  Returns:
554
552
  Runnable configured for structured output extraction
555
553
  """
556
- if method not in ["auto", "function_calling", "json_mode", "json_schema"]:
554
+ if method not in ["function_calling", "json_mode", "json_schema"]:
557
555
  raise ValueError(
558
- f"Unsupported method: {method}. Please choose from 'auto', 'function_calling', 'json_mode', 'json_schema'."
556
+ f"Unsupported method: {method}. Please choose from 'function_calling', 'json_mode', 'json_schema'."
559
557
  )
560
- if method == "auto":
561
- if "json_schema" in self.supported_response_format:
562
- method = "json_schema"
563
- else:
564
- method = "function_calling"
565
- elif (
558
+ if (
566
559
  method == "json_schema"
567
560
  and "json_schema" not in self.supported_response_format
568
561
  ):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: langchain-dev-utils
3
- Version: 1.3.1
3
+ Version: 1.3.3
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,17 +1,17 @@
1
- langchain_dev_utils/__init__.py,sha256=-ypEJktJToAL9by62JJKWEzDo_KPCQtmE5kwFgX24z4,22
1
+ langchain_dev_utils/__init__.py,sha256=Vi6om3KImlKsS_Wg5CjUgYffoi2zx7T-SRPnnGL0G7M,22
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=PJ-lSDZv_AXMYA3H4fx-HzJa14tPbkGmq1HX8LNfaPo,125
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=RuchoH_VotPmKFuYEn2SXoSgNxZhSA9jKM0Iv_8oHLk,4718
9
- langchain_dev_utils/agents/middleware/__init__.py,sha256=n3PsbL8LSmariEe94rUMoT0GnUQMrZUNdSj-z4om2cY,962
8
+ langchain_dev_utils/agents/wrap.py,sha256=O8LSieRhlqL4cwf_BPNIiJD3lhTyL6civBHcQPWCqSU,9490
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=aCD90yTiAPyG8pC_DAr0eDi-iYW57W0wt6LzIoKLT_Y,5024
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
- langchain_dev_utils/agents/middleware/plan.py,sha256=0qDCmenxgY_zrwMfOyYlgLfhYNw-HszNLeeOkfj14NA,16002
14
+ langchain_dev_utils/agents/middleware/plan.py,sha256=-ZLkp85QQTSCX9thMblacJ1N86h0BYPoTwCfJlJ_jzQ,14981
15
15
  langchain_dev_utils/agents/middleware/summarization.py,sha256=IoZ2PM1OC3AXwf0DWpfreuPOAipeiYu0KPmAABWXuY0,3087
16
16
  langchain_dev_utils/agents/middleware/tool_call_repair.py,sha256=oZF0Oejemqs9kSn8xbW79FWyVVarL4IGCz0gpqYBkFM,3529
17
17
  langchain_dev_utils/agents/middleware/tool_emulator.py,sha256=OgtPhqturaWzF4fRSJ3f_IXvIrYrrAjlpOC5zmLtrkY,2031
@@ -20,7 +20,7 @@ langchain_dev_utils/chat_models/__init__.py,sha256=YSLUyHrWEEj4y4DtGFCOnDW02VIYZ
20
20
  langchain_dev_utils/chat_models/base.py,sha256=BzaoCIv145eE8b5wNDsbZDHn4EAxe4vdlptp7qXPWKk,11625
21
21
  langchain_dev_utils/chat_models/types.py,sha256=MD3cv_ZIe9fCdgwisNfuxAOhy-j4YSs1ZOQYyCjlNKs,927
22
22
  langchain_dev_utils/chat_models/adapters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
- langchain_dev_utils/chat_models/adapters/openai_compatible.py,sha256=PkOoYNwp2kEhXalUHXCCAnL7LXfeiNoeiQ678suEse4,24492
23
+ langchain_dev_utils/chat_models/adapters/openai_compatible.py,sha256=ws1CTZhyl8gxoY_RCLsV3cDgc8d7yDLWUa6ZfloxuMs,24239
24
24
  langchain_dev_utils/embeddings/__init__.py,sha256=zbEOaV86TUi9Zrg_dH9dpdgacWg31HMJTlTQknA9EKk,244
25
25
  langchain_dev_utils/embeddings/base.py,sha256=BGoWY0L7nG9iRV3d4sSagXhECXrwvS1xA-A_OVltn3k,9406
26
26
  langchain_dev_utils/message_convert/__init__.py,sha256=ZGrHGXPKMrZ_p9MqfIVZ4jgbEyb7aC4Q7X-muuThIYU,457
@@ -33,7 +33,7 @@ langchain_dev_utils/pipeline/types.py,sha256=T3aROKKXeWvd0jcH5XkgMDQfEkLfPaiOhhV
33
33
  langchain_dev_utils/tool_calling/__init__.py,sha256=mu_WxKMcu6RoTf4vkTPbA1WSBSNc6YIqyBtOQ6iVQj4,322
34
34
  langchain_dev_utils/tool_calling/human_in_the_loop.py,sha256=7Z_QO5OZUR6K8nLoIcafc6osnvX2IYNorOJcbx6bVso,9672
35
35
  langchain_dev_utils/tool_calling/utils.py,sha256=S4-KXQ8jWmpGTXYZitovF8rxKpaSSUkFruM8LDwvcvE,2765
36
- langchain_dev_utils-1.3.1.dist-info/METADATA,sha256=6UJeWibp3qpwITK0THhTdFpM8tq7XyLyoUvbkMnRhLc,4552
37
- langchain_dev_utils-1.3.1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
38
- langchain_dev_utils-1.3.1.dist-info/licenses/LICENSE,sha256=AWAOzNEcsvCEzHOF0qby5OKxviVH_eT9Yce1sgJTico,1084
39
- langchain_dev_utils-1.3.1.dist-info/RECORD,,
36
+ langchain_dev_utils-1.3.3.dist-info/METADATA,sha256=PEt8qHRYBK2l-A2djg8eJEuz6uZdxZq-fPa6U6yR8Cc,4552
37
+ langchain_dev_utils-1.3.3.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
38
+ langchain_dev_utils-1.3.3.dist-info/licenses/LICENSE,sha256=AWAOzNEcsvCEzHOF0qby5OKxviVH_eT9Yce1sgJTico,1084
39
+ langchain_dev_utils-1.3.3.dist-info/RECORD,,