langchain-dev-utils 1.4.0__py3-none-any.whl → 1.4.1__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/_utils.py +4 -2
- langchain_dev_utils/agents/middleware/__init__.py +5 -3
- langchain_dev_utils/agents/middleware/format_prompt.py +137 -47
- langchain_dev_utils/agents/middleware/tool_call_repair.py +3 -0
- langchain_dev_utils/chat_models/adapters/openai_compatible.py +7 -3
- {langchain_dev_utils-1.4.0.dist-info → langchain_dev_utils-1.4.1.dist-info}/METADATA +2 -1
- {langchain_dev_utils-1.4.0.dist-info → langchain_dev_utils-1.4.1.dist-info}/RECORD +10 -10
- {langchain_dev_utils-1.4.0.dist-info → langchain_dev_utils-1.4.1.dist-info}/WHEEL +0 -0
- {langchain_dev_utils-1.4.0.dist-info → langchain_dev_utils-1.4.1.dist-info}/licenses/LICENSE +0 -0
langchain_dev_utils/__init__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "1.4.
|
|
1
|
+
__version__ = "1.4.1"
|
langchain_dev_utils/_utils.py
CHANGED
|
@@ -23,13 +23,15 @@ def _transform_node_to_tuple(
|
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
def _check_pkg_install(
|
|
26
|
-
pkg: Literal["langchain_openai", "json_repair"],
|
|
26
|
+
pkg: Literal["langchain_openai", "json_repair", "jinja2"],
|
|
27
27
|
) -> None:
|
|
28
28
|
if not util.find_spec(pkg):
|
|
29
29
|
if pkg == "langchain_openai":
|
|
30
30
|
msg = "Please install langchain_dev_utils[standard],when use 'openai-compatible'"
|
|
31
|
-
|
|
31
|
+
elif pkg == "json_repair":
|
|
32
32
|
msg = "Please install langchain_dev_utils[standard] to use ToolCallRepairMiddleware."
|
|
33
|
+
else:
|
|
34
|
+
msg = "Please install langchain_dev_utils[standard] to use FormatPromptMiddleware."
|
|
33
35
|
raise ImportError(msg)
|
|
34
36
|
|
|
35
37
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
from .format_prompt import format_prompt
|
|
1
|
+
from .format_prompt import FormatPromptMiddleware, format_prompt
|
|
2
2
|
from .handoffs import HandoffAgentMiddleware
|
|
3
3
|
from .model_fallback import ModelFallbackMiddleware
|
|
4
4
|
from .model_router import ModelRouterMiddleware
|
|
5
5
|
from .plan import PlanMiddleware
|
|
6
6
|
from .summarization import SummarizationMiddleware
|
|
7
|
-
from .tool_call_repair import ToolCallRepairMiddleware
|
|
7
|
+
from .tool_call_repair import ToolCallRepairMiddleware, tool_call_repair
|
|
8
8
|
from .tool_emulator import LLMToolEmulator
|
|
9
9
|
from .tool_selection import LLMToolSelectorMiddleware
|
|
10
10
|
|
|
@@ -16,6 +16,8 @@ __all__ = [
|
|
|
16
16
|
"LLMToolEmulator",
|
|
17
17
|
"ModelRouterMiddleware",
|
|
18
18
|
"ToolCallRepairMiddleware",
|
|
19
|
-
"
|
|
19
|
+
"FormatPromptMiddleware",
|
|
20
20
|
"HandoffAgentMiddleware",
|
|
21
|
+
"tool_call_repair",
|
|
22
|
+
"format_prompt",
|
|
21
23
|
]
|
|
@@ -1,66 +1,156 @@
|
|
|
1
|
-
from
|
|
1
|
+
from typing import Awaitable, Callable, Literal
|
|
2
|
+
|
|
3
|
+
from langchain.agents.middleware import ModelRequest
|
|
4
|
+
from langchain.agents.middleware.types import (
|
|
5
|
+
AgentMiddleware,
|
|
6
|
+
ModelCallResult,
|
|
7
|
+
ModelResponse,
|
|
8
|
+
)
|
|
9
|
+
from langchain_core.messages import SystemMessage
|
|
2
10
|
from langchain_core.prompts.string import get_template_variables
|
|
3
11
|
|
|
12
|
+
from langchain_dev_utils._utils import _check_pkg_install
|
|
13
|
+
|
|
4
14
|
|
|
5
|
-
|
|
6
|
-
def format_prompt(request: ModelRequest) -> str:
|
|
15
|
+
class FormatPromptMiddleware(AgentMiddleware):
|
|
7
16
|
"""Format the system prompt with variables from state and context.
|
|
8
17
|
|
|
9
18
|
This middleware function extracts template variables from the system prompt
|
|
10
19
|
and populates them with values from the agent's state and runtime context.
|
|
11
20
|
Variables are first resolved from the state, then from the context if not found.
|
|
12
21
|
|
|
22
|
+
Args:
|
|
23
|
+
template_format: The format of the template. Defaults to "f-string".
|
|
24
|
+
|
|
13
25
|
Example:
|
|
14
|
-
>>> from langchain_dev_utils.agents.middleware import format_prompt
|
|
15
|
-
>>> from langchain.agents import create_agent
|
|
16
|
-
>>> from langchain_core.messages import HumanMessage
|
|
17
|
-
>>> from dataclasses import dataclass
|
|
18
|
-
>>>
|
|
19
|
-
>>> @dataclass
|
|
20
|
-
... class Context:
|
|
21
|
-
... name: str
|
|
22
|
-
... user: str
|
|
23
|
-
>>>
|
|
24
|
-
>>> agent=create_agent(
|
|
25
|
-
... model=model,
|
|
26
|
-
... tools=tools,
|
|
27
|
-
... system_prompt="You are a helpful assistant. Your name is {name}. Your user is {user}.",
|
|
28
|
-
... middleware=[format_prompt],
|
|
29
|
-
... context_schema=Context,
|
|
30
|
-
... )
|
|
31
|
-
>>> agent.invoke(
|
|
32
|
-
... {
|
|
33
|
-
... "messages": [HumanMessage(content="Hello")],
|
|
34
|
-
... },
|
|
35
|
-
... context=Context(name="assistant", user="Tom"),
|
|
36
|
-
... )
|
|
37
26
|
|
|
27
|
+
# Use format_prompt middleware instance rather than FormatPromptMiddleware class (Recommended)
|
|
28
|
+
|
|
29
|
+
```python
|
|
30
|
+
from langchain_dev_utils.agents.middleware import format_prompt
|
|
31
|
+
from langchain.agents import create_agent
|
|
32
|
+
from langchain_core.messages import HumanMessage
|
|
33
|
+
from dataclasses import dataclass
|
|
34
|
+
|
|
35
|
+
@dataclass
|
|
36
|
+
class Context:
|
|
37
|
+
name: str
|
|
38
|
+
user: str
|
|
39
|
+
|
|
40
|
+
agent = create_agent(
|
|
41
|
+
model=model,
|
|
42
|
+
tools=tools,
|
|
43
|
+
system_prompt="You are a helpful assistant. Your name is {name}. Your user is {user}.",
|
|
44
|
+
middleware=[format_prompt],
|
|
45
|
+
context_schema=Context,
|
|
46
|
+
)
|
|
47
|
+
agent.invoke(
|
|
48
|
+
{
|
|
49
|
+
"messages": [HumanMessage(content="Hello")],
|
|
50
|
+
},
|
|
51
|
+
context=Context(name="assistant", user="Tom"),
|
|
52
|
+
)
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
# Use FormatPromptMiddleware class(Use when template_format is jinja2)
|
|
56
|
+
|
|
57
|
+
```python
|
|
58
|
+
from langchain_dev_utils.agents.middleware import FormatPromptMiddleware
|
|
59
|
+
from langchain.agents import create_agent
|
|
60
|
+
from langchain_core.messages import HumanMessage
|
|
61
|
+
from dataclasses import dataclass
|
|
62
|
+
|
|
63
|
+
@dataclass
|
|
64
|
+
class Context:
|
|
65
|
+
name: str
|
|
66
|
+
user: str
|
|
67
|
+
|
|
68
|
+
agent = create_agent(
|
|
69
|
+
model=model,
|
|
70
|
+
tools=tools,
|
|
71
|
+
system_prompt="You are a helpful assistant. Your name is {{ name }}. Your user is {{ user }}.",
|
|
72
|
+
middleware=[FormatPromptMiddleware(template_format="jinja2")],
|
|
73
|
+
context_schema=Context,
|
|
74
|
+
)
|
|
75
|
+
agent.invoke(
|
|
76
|
+
{
|
|
77
|
+
"messages": [HumanMessage(content="Hello")],
|
|
78
|
+
},
|
|
79
|
+
context=Context(name="assistant", user="Tom"),
|
|
80
|
+
)
|
|
81
|
+
```
|
|
38
82
|
"""
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
83
|
+
|
|
84
|
+
def __init__(
|
|
85
|
+
self,
|
|
86
|
+
*,
|
|
87
|
+
template_format: Literal["f-string", "jinja2"] = "f-string",
|
|
88
|
+
) -> None:
|
|
89
|
+
super().__init__()
|
|
90
|
+
|
|
91
|
+
self.template_format = template_format
|
|
92
|
+
|
|
93
|
+
if template_format == "jinja2":
|
|
94
|
+
_check_pkg_install("jinja2")
|
|
95
|
+
|
|
96
|
+
def _format_prompt(self, request: ModelRequest) -> str:
|
|
97
|
+
"""Add the plan system prompt to the system message."""
|
|
98
|
+
system_msg = request.system_message
|
|
99
|
+
if system_msg is None:
|
|
100
|
+
raise ValueError(
|
|
101
|
+
"system_message must be provided,while use format_prompt in middleware."
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
system_prompt = "\n".join(
|
|
105
|
+
[content.get("text", "") for content in system_msg.content_blocks]
|
|
43
106
|
)
|
|
107
|
+
variables = get_template_variables(system_prompt, self.template_format)
|
|
108
|
+
|
|
109
|
+
format_params = {}
|
|
110
|
+
|
|
111
|
+
state = request.state
|
|
112
|
+
for key in variables:
|
|
113
|
+
if var := state.get(key, None):
|
|
114
|
+
format_params[key] = var
|
|
44
115
|
|
|
45
|
-
|
|
46
|
-
[content.get("text", "") for content in system_msg.content_blocks]
|
|
47
|
-
)
|
|
48
|
-
variables = get_template_variables(system_prompt, "f-string")
|
|
116
|
+
other_var_keys = set(variables) - set(format_params.keys())
|
|
49
117
|
|
|
50
|
-
|
|
118
|
+
if other_var_keys:
|
|
119
|
+
context = request.runtime.context
|
|
120
|
+
if context is not None:
|
|
121
|
+
for key in other_var_keys:
|
|
122
|
+
if var := getattr(context, key, None):
|
|
123
|
+
format_params[key] = var
|
|
51
124
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
if var := state.get(key, None):
|
|
55
|
-
format_params[key] = var
|
|
125
|
+
if self.template_format == "jinja2":
|
|
126
|
+
from jinja2 import Template
|
|
56
127
|
|
|
57
|
-
|
|
128
|
+
template = Template(system_prompt)
|
|
129
|
+
return template.render(**format_params)
|
|
130
|
+
else:
|
|
131
|
+
return system_prompt.format(**format_params)
|
|
132
|
+
|
|
133
|
+
def wrap_model_call(
|
|
134
|
+
self,
|
|
135
|
+
request: ModelRequest,
|
|
136
|
+
handler: Callable[[ModelRequest], ModelResponse],
|
|
137
|
+
) -> ModelCallResult:
|
|
138
|
+
"""Update the system prompt with variables from state and context."""
|
|
139
|
+
prompt = self._format_prompt(request)
|
|
140
|
+
request = request.override(system_message=SystemMessage(content=prompt))
|
|
141
|
+
return handler(request)
|
|
142
|
+
|
|
143
|
+
async def awrap_model_call(
|
|
144
|
+
self,
|
|
145
|
+
request: ModelRequest,
|
|
146
|
+
handler: Callable[[ModelRequest], Awaitable[ModelResponse]],
|
|
147
|
+
) -> ModelCallResult:
|
|
148
|
+
"""Update the system prompt with variables from state and context."""
|
|
149
|
+
prompt = self._format_prompt(request)
|
|
150
|
+
override_request = request.override(
|
|
151
|
+
system_message=SystemMessage(content=prompt)
|
|
152
|
+
)
|
|
153
|
+
return await handler(override_request)
|
|
58
154
|
|
|
59
|
-
if other_var_keys:
|
|
60
|
-
context = request.runtime.context
|
|
61
|
-
if context is not None:
|
|
62
|
-
for key in other_var_keys:
|
|
63
|
-
if var := getattr(context, key, None):
|
|
64
|
-
format_params[key] = var
|
|
65
155
|
|
|
66
|
-
|
|
156
|
+
format_prompt = FormatPromptMiddleware()
|
|
@@ -261,6 +261,8 @@ class _BaseChatOpenAICompatible(BaseChatOpenAI):
|
|
|
261
261
|
payload_messages.append(_convert_message_to_dict(m))
|
|
262
262
|
|
|
263
263
|
payload["messages"] = payload_messages
|
|
264
|
+
if "tools" in payload and len(payload["tools"]) == 0:
|
|
265
|
+
payload.pop("tools")
|
|
264
266
|
return payload
|
|
265
267
|
|
|
266
268
|
@model_validator(mode="after")
|
|
@@ -302,6 +304,8 @@ class _BaseChatOpenAICompatible(BaseChatOpenAI):
|
|
|
302
304
|
ModelProfile,
|
|
303
305
|
_get_profile_by_provider_and_model(self._provider, self.model_name),
|
|
304
306
|
)
|
|
307
|
+
if "json_schema" in self.supported_response_format:
|
|
308
|
+
self.profile.update({"structured_output": True})
|
|
305
309
|
return self
|
|
306
310
|
|
|
307
311
|
def _create_chat_result(
|
|
@@ -347,9 +351,9 @@ class _BaseChatOpenAICompatible(BaseChatOpenAI):
|
|
|
347
351
|
if isinstance(model_extra, dict) and (
|
|
348
352
|
reasoning := model_extra.get("reasoning")
|
|
349
353
|
):
|
|
350
|
-
rtn.generations[0].message.additional_kwargs[
|
|
351
|
-
|
|
352
|
-
|
|
354
|
+
rtn.generations[0].message.additional_kwargs[
|
|
355
|
+
"reasoning_content"
|
|
356
|
+
] = reasoning
|
|
353
357
|
|
|
354
358
|
return rtn
|
|
355
359
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: langchain-dev-utils
|
|
3
|
-
Version: 1.4.
|
|
3
|
+
Version: 1.4.1
|
|
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
|
|
@@ -12,6 +12,7 @@ Requires-Dist: langchain-core>=1.2.5
|
|
|
12
12
|
Requires-Dist: langchain>=1.2.0
|
|
13
13
|
Requires-Dist: langgraph>=1.0.0
|
|
14
14
|
Provides-Extra: standard
|
|
15
|
+
Requires-Dist: jinja2>=3.1.6; extra == 'standard'
|
|
15
16
|
Requires-Dist: json-repair>=0.53.1; extra == 'standard'
|
|
16
17
|
Requires-Dist: langchain-openai; extra == 'standard'
|
|
17
18
|
Description-Content-Type: text/markdown
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
langchain_dev_utils/__init__.py,sha256
|
|
2
|
-
langchain_dev_utils/_utils.py,sha256=
|
|
1
|
+
langchain_dev_utils/__init__.py,sha256=nxjQ6mMSJJKqkpX2IY-1BmdpErEa1Lx5hYzk9ULB09w,23
|
|
2
|
+
langchain_dev_utils/_utils.py,sha256=EC1mlQggFvso1csYxCrk4XbXkJuK_8zrrjsD19ELzgk,4806
|
|
3
3
|
langchain_dev_utils/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
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/wrap.py,sha256=ufxcOCLDE4Aw2TbgcyFYor0BXXaJDzLTTJJyyD4x7bQ,12011
|
|
7
|
-
langchain_dev_utils/agents/middleware/__init__.py,sha256=
|
|
8
|
-
langchain_dev_utils/agents/middleware/format_prompt.py,sha256=
|
|
7
|
+
langchain_dev_utils/agents/middleware/__init__.py,sha256=SiTibbzv2QC0FvGKN_1A10yOO62F7wtdScbGARjkyjA,808
|
|
8
|
+
langchain_dev_utils/agents/middleware/format_prompt.py,sha256=HrgHsMCnfHQ-Eh_RY-h56otAJ62-2zJJHbOi2kRyEiw,5303
|
|
9
9
|
langchain_dev_utils/agents/middleware/handoffs.py,sha256=rSkNXxqtjB8_xT0HUdxnKbchgY76BuTPX-Zc69H-_wI,7687
|
|
10
10
|
langchain_dev_utils/agents/middleware/model_fallback.py,sha256=8xiNjTJ0yiRkPLCRfAGNnqY1TLstj1Anmiqyv5w2mA8,1633
|
|
11
11
|
langchain_dev_utils/agents/middleware/model_router.py,sha256=IidYq72tPLa053gEg5IQpPzDzyCxYYEvpgT1K4qBwXw,7862
|
|
12
12
|
langchain_dev_utils/agents/middleware/plan.py,sha256=Zz0dh1BRbsVgROmhjH2IIqylSsuKHZXJx0iztMBm8EU,14719
|
|
13
13
|
langchain_dev_utils/agents/middleware/summarization.py,sha256=IoZ2PM1OC3AXwf0DWpfreuPOAipeiYu0KPmAABWXuY0,3087
|
|
14
|
-
langchain_dev_utils/agents/middleware/tool_call_repair.py,sha256=
|
|
14
|
+
langchain_dev_utils/agents/middleware/tool_call_repair.py,sha256=mO21g9nzukdjNcERTg63jS7UOEF47Wx8yd7CqFS_VVQ,3580
|
|
15
15
|
langchain_dev_utils/agents/middleware/tool_emulator.py,sha256=OgtPhqturaWzF4fRSJ3f_IXvIrYrrAjlpOC5zmLtrkY,2031
|
|
16
16
|
langchain_dev_utils/agents/middleware/tool_selection.py,sha256=dRH5ejR6N02Djwxt6Gd63MYkg6SV5pySlzaRt53OoZk,3113
|
|
17
17
|
langchain_dev_utils/chat_models/__init__.py,sha256=YSLUyHrWEEj4y4DtGFCOnDW02VIYZdfAH800m4Klgeg,224
|
|
@@ -19,7 +19,7 @@ langchain_dev_utils/chat_models/base.py,sha256=G_SNvd53ogho-LRgD7DCD65xj51J2JxmO
|
|
|
19
19
|
langchain_dev_utils/chat_models/types.py,sha256=MD3cv_ZIe9fCdgwisNfuxAOhy-j4YSs1ZOQYyCjlNKs,927
|
|
20
20
|
langchain_dev_utils/chat_models/adapters/__init__.py,sha256=4tTbhAAQdpX_gWyWeH97hqS5HnaoqQqW6QBh9Qd1SKs,106
|
|
21
21
|
langchain_dev_utils/chat_models/adapters/create_utils.py,sha256=r8_XWLNF3Yc6sumlBhmgG1QcBa4Dsba7X3f_9YeMeGA,2479
|
|
22
|
-
langchain_dev_utils/chat_models/adapters/openai_compatible.py,sha256=
|
|
22
|
+
langchain_dev_utils/chat_models/adapters/openai_compatible.py,sha256=I9MXplglcTSzrRx8Y7sDGliiT7_Wiugv3wdv5y1cpr0,27418
|
|
23
23
|
langchain_dev_utils/chat_models/adapters/register_profiles.py,sha256=YS9ItCEq2ISoB_bp6QH5NVKOVR9-7la3r7B_xQNxZxE,366
|
|
24
24
|
langchain_dev_utils/embeddings/__init__.py,sha256=zbEOaV86TUi9Zrg_dH9dpdgacWg31HMJTlTQknA9EKk,244
|
|
25
25
|
langchain_dev_utils/embeddings/base.py,sha256=GXFKZSAExMtCFUpsd6mY4NxCWCrq7JAatBw3kS9LaKY,8803
|
|
@@ -40,7 +40,7 @@ langchain_dev_utils/pipeline/types.py,sha256=T3aROKKXeWvd0jcH5XkgMDQfEkLfPaiOhhV
|
|
|
40
40
|
langchain_dev_utils/tool_calling/__init__.py,sha256=mu_WxKMcu6RoTf4vkTPbA1WSBSNc6YIqyBtOQ6iVQj4,322
|
|
41
41
|
langchain_dev_utils/tool_calling/human_in_the_loop.py,sha256=7Z_QO5OZUR6K8nLoIcafc6osnvX2IYNorOJcbx6bVso,9672
|
|
42
42
|
langchain_dev_utils/tool_calling/utils.py,sha256=S4-KXQ8jWmpGTXYZitovF8rxKpaSSUkFruM8LDwvcvE,2765
|
|
43
|
-
langchain_dev_utils-1.4.
|
|
44
|
-
langchain_dev_utils-1.4.
|
|
45
|
-
langchain_dev_utils-1.4.
|
|
46
|
-
langchain_dev_utils-1.4.
|
|
43
|
+
langchain_dev_utils-1.4.1.dist-info/METADATA,sha256=QqpJZwTwFUIzwIXZRjfSVGHMrtZG7pJ6salBq_zYEL0,4808
|
|
44
|
+
langchain_dev_utils-1.4.1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
45
|
+
langchain_dev_utils-1.4.1.dist-info/licenses/LICENSE,sha256=AWAOzNEcsvCEzHOF0qby5OKxviVH_eT9Yce1sgJTico,1084
|
|
46
|
+
langchain_dev_utils-1.4.1.dist-info/RECORD,,
|
|
File without changes
|
{langchain_dev_utils-1.4.0.dist-info → langchain_dev_utils-1.4.1.dist-info}/licenses/LICENSE
RENAMED
|
File without changes
|