langchain-dev-utils 1.2.5__py3-none-any.whl → 1.2.6__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 +39 -0
- langchain_dev_utils/chat_models/base.py +10 -37
- langchain_dev_utils/embeddings/base.py +7 -30
- {langchain_dev_utils-1.2.5.dist-info → langchain_dev_utils-1.2.6.dist-info}/METADATA +9 -6
- {langchain_dev_utils-1.2.5.dist-info → langchain_dev_utils-1.2.6.dist-info}/RECORD +8 -7
- {langchain_dev_utils-1.2.5.dist-info → langchain_dev_utils-1.2.6.dist-info}/WHEEL +0 -0
- {langchain_dev_utils-1.2.5.dist-info → langchain_dev_utils-1.2.6.dist-info}/licenses/LICENSE +0 -0
langchain_dev_utils/__init__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "1.2.
|
|
1
|
+
__version__ = "1.2.6"
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
from importlib import util
|
|
2
|
+
|
|
3
|
+
from pydantic import BaseModel
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def _check_langchain_openai_install() -> None:
|
|
7
|
+
if not util.find_spec("langchain_openai"):
|
|
8
|
+
msg = (
|
|
9
|
+
"Please install langchain_dev_utils[standard],when use 'openai-compatible'"
|
|
10
|
+
)
|
|
11
|
+
raise ImportError(msg)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def _get_base_url_field_name(model_cls: type[BaseModel]) -> str | None:
|
|
15
|
+
"""
|
|
16
|
+
Return 'base_url' if the model has a field named or aliased as 'base_url',
|
|
17
|
+
else return 'api_base' if it has a field named or aliased as 'api_base',
|
|
18
|
+
else return None.
|
|
19
|
+
The return value is always either 'base_url', 'api_base', or None.
|
|
20
|
+
"""
|
|
21
|
+
model_fields = model_cls.model_fields
|
|
22
|
+
|
|
23
|
+
# try model_fields first
|
|
24
|
+
if "base_url" in model_fields:
|
|
25
|
+
return "base_url"
|
|
26
|
+
|
|
27
|
+
if "api_base" in model_fields:
|
|
28
|
+
return "api_base"
|
|
29
|
+
|
|
30
|
+
# then try aliases
|
|
31
|
+
for field_info in model_fields.values():
|
|
32
|
+
if field_info.alias == "base_url":
|
|
33
|
+
return "base_url"
|
|
34
|
+
|
|
35
|
+
for field_info in model_fields.values():
|
|
36
|
+
if field_info.alias == "api_base":
|
|
37
|
+
return "api_base"
|
|
38
|
+
|
|
39
|
+
return None
|
|
@@ -3,7 +3,11 @@ from typing import Any, NotRequired, Optional, TypedDict, cast
|
|
|
3
3
|
from langchain.chat_models.base import _SUPPORTED_PROVIDERS, _init_chat_model_helper
|
|
4
4
|
from langchain_core.language_models.chat_models import BaseChatModel
|
|
5
5
|
from langchain_core.utils import from_env
|
|
6
|
-
|
|
6
|
+
|
|
7
|
+
from langchain_dev_utils._utils import (
|
|
8
|
+
_check_langchain_openai_install,
|
|
9
|
+
_get_base_url_field_name,
|
|
10
|
+
)
|
|
7
11
|
|
|
8
12
|
from .types import ChatModelType, CompatibilityOptions
|
|
9
13
|
|
|
@@ -18,34 +22,6 @@ class ChatModelProvider(TypedDict):
|
|
|
18
22
|
compatibility_options: NotRequired[CompatibilityOptions]
|
|
19
23
|
|
|
20
24
|
|
|
21
|
-
def _get_base_url_field_name(model_cls: type[BaseModel]) -> str | None:
|
|
22
|
-
"""
|
|
23
|
-
Return 'base_url' if the model has a field named or aliased as 'base_url',
|
|
24
|
-
else return 'api_base' if it has a field named or aliased as 'api_base',
|
|
25
|
-
else return None.
|
|
26
|
-
The return value is always either 'base_url', 'api_base', or None.
|
|
27
|
-
"""
|
|
28
|
-
model_fields = model_cls.model_fields
|
|
29
|
-
|
|
30
|
-
# try model_fields first
|
|
31
|
-
if "base_url" in model_fields:
|
|
32
|
-
return "base_url"
|
|
33
|
-
|
|
34
|
-
if "api_base" in model_fields:
|
|
35
|
-
return "api_base"
|
|
36
|
-
|
|
37
|
-
# then try aliases
|
|
38
|
-
for field_info in model_fields.values():
|
|
39
|
-
if field_info.alias == "base_url":
|
|
40
|
-
return "base_url"
|
|
41
|
-
|
|
42
|
-
for field_info in model_fields.values():
|
|
43
|
-
if field_info.alias == "api_base":
|
|
44
|
-
return "api_base"
|
|
45
|
-
|
|
46
|
-
return None
|
|
47
|
-
|
|
48
|
-
|
|
49
25
|
def _parse_model(model: str, model_provider: Optional[str]) -> tuple[str, str]:
|
|
50
26
|
"""Parse model string and provider.
|
|
51
27
|
|
|
@@ -89,7 +65,7 @@ def _load_chat_model_helper(
|
|
|
89
65
|
BaseChatModel: Initialized chat model instance
|
|
90
66
|
"""
|
|
91
67
|
model, model_provider = _parse_model(model, model_provider)
|
|
92
|
-
if model_provider in _MODEL_PROVIDERS_DICT
|
|
68
|
+
if model_provider in _MODEL_PROVIDERS_DICT:
|
|
93
69
|
chat_model = _MODEL_PROVIDERS_DICT[model_provider]["chat_model"]
|
|
94
70
|
if base_url := _MODEL_PROVIDERS_DICT[model_provider].get("base_url"):
|
|
95
71
|
url_key = _get_base_url_field_name(chat_model)
|
|
@@ -98,7 +74,7 @@ def _load_chat_model_helper(
|
|
|
98
74
|
if model_profiles := _MODEL_PROVIDERS_DICT[model_provider].get(
|
|
99
75
|
"model_profiles"
|
|
100
76
|
):
|
|
101
|
-
if model in model_profiles:
|
|
77
|
+
if model in model_profiles and "profile" not in kwargs:
|
|
102
78
|
kwargs.update({"profile": model_profiles[model]})
|
|
103
79
|
return chat_model(model=model, **kwargs)
|
|
104
80
|
|
|
@@ -145,12 +121,9 @@ def register_model_provider(
|
|
|
145
121
|
"""
|
|
146
122
|
base_url = base_url or from_env(f"{provider_name.upper()}_API_BASE", default=None)()
|
|
147
123
|
if isinstance(chat_model, str):
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
raise ImportError(
|
|
152
|
-
"Please install langchain_dev_utils[standard],when chat_model is a 'openai-compatible'"
|
|
153
|
-
)
|
|
124
|
+
_check_langchain_openai_install()
|
|
125
|
+
from .adapters.openai_compatible import _create_openai_compatible_model
|
|
126
|
+
|
|
154
127
|
if base_url is None:
|
|
155
128
|
raise ValueError(
|
|
156
129
|
f"base_url must be provided or set {provider_name.upper()}_API_BASE environment variable when chat_model is a string"
|
|
@@ -2,7 +2,11 @@ from typing import Any, Literal, NotRequired, Optional, TypedDict, Union
|
|
|
2
2
|
|
|
3
3
|
from langchain.embeddings.base import Embeddings, _SUPPORTED_PROVIDERS, init_embeddings
|
|
4
4
|
from langchain_core.utils import from_env, secret_from_env
|
|
5
|
-
|
|
5
|
+
|
|
6
|
+
from langchain_dev_utils._utils import (
|
|
7
|
+
_check_langchain_openai_install,
|
|
8
|
+
_get_base_url_field_name,
|
|
9
|
+
)
|
|
6
10
|
|
|
7
11
|
_EMBEDDINGS_PROVIDERS_DICT = {}
|
|
8
12
|
|
|
@@ -15,34 +19,6 @@ class EmbeddingProvider(TypedDict):
|
|
|
15
19
|
base_url: NotRequired[str]
|
|
16
20
|
|
|
17
21
|
|
|
18
|
-
def _get_base_url_field_name(model_cls: type[BaseModel]) -> str | None:
|
|
19
|
-
"""
|
|
20
|
-
Return 'base_url' if the model has a field named or aliased as 'base_url',
|
|
21
|
-
else return 'api_base' if it has a field named or aliased as 'api_base',
|
|
22
|
-
else return None.
|
|
23
|
-
The return value is always either 'base_url', 'api_base', or None.
|
|
24
|
-
"""
|
|
25
|
-
model_fields = model_cls.model_fields
|
|
26
|
-
|
|
27
|
-
# try model_fields first
|
|
28
|
-
if "base_url" in model_fields:
|
|
29
|
-
return "base_url"
|
|
30
|
-
|
|
31
|
-
if "api_base" in model_fields:
|
|
32
|
-
return "api_base"
|
|
33
|
-
|
|
34
|
-
# then try aliases
|
|
35
|
-
for field_info in model_fields.values():
|
|
36
|
-
if field_info.alias == "base_url":
|
|
37
|
-
return "base_url"
|
|
38
|
-
|
|
39
|
-
for field_info in model_fields.values():
|
|
40
|
-
if field_info.alias == "api_base":
|
|
41
|
-
return "api_base"
|
|
42
|
-
|
|
43
|
-
return None
|
|
44
|
-
|
|
45
|
-
|
|
46
22
|
def _parse_model_string(model_name: str) -> tuple[str, str]:
|
|
47
23
|
"""Parse model string into provider and model name.
|
|
48
24
|
|
|
@@ -119,6 +95,8 @@ def register_embeddings_provider(
|
|
|
119
95
|
"when embeddings_model is a string, the value must be 'openai-compatible'"
|
|
120
96
|
)
|
|
121
97
|
|
|
98
|
+
_check_langchain_openai_install()
|
|
99
|
+
|
|
122
100
|
_EMBEDDINGS_PROVIDERS_DICT.update(
|
|
123
101
|
{
|
|
124
102
|
provider_name: {
|
|
@@ -238,7 +216,6 @@ def load_embeddings(
|
|
|
238
216
|
if embeddings == "openai-compatible":
|
|
239
217
|
kwargs["check_embedding_ctx_length"] = False
|
|
240
218
|
embeddings = "openai"
|
|
241
|
-
|
|
242
219
|
return init_embeddings(
|
|
243
220
|
model=model,
|
|
244
221
|
provider=embeddings,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: langchain-dev-utils
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.6
|
|
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
|
|
@@ -157,6 +157,8 @@ For stream responses obtained using `stream()` and `astream()`, you can use `mer
|
|
|
157
157
|
| `chunks` | List[AIMessageChunk] | Yes | - | List of AIMessageChunk objects |
|
|
158
158
|
|
|
159
159
|
```python
|
|
160
|
+
from langchain_dev_utils.message_convert import merge_ai_message_chunk
|
|
161
|
+
|
|
160
162
|
chunks = list(model.stream("Hello"))
|
|
161
163
|
merged = merge_ai_message_chunk(chunks)
|
|
162
164
|
```
|
|
@@ -174,6 +176,7 @@ For a list, you can use `format_sequence` to format it.
|
|
|
174
176
|
| `with_num` | bool | No | False | If True, add a numeric prefix to each item (e.g., "1. Hello") |
|
|
175
177
|
|
|
176
178
|
```python
|
|
179
|
+
from langchain_dev_utils.message_convert import format_sequence
|
|
177
180
|
text = format_sequence([
|
|
178
181
|
"str1",
|
|
179
182
|
"str2",
|
|
@@ -205,7 +208,7 @@ Includes the following features:
|
|
|
205
208
|
| Parameter | Type | Required | Default | Description |
|
|
206
209
|
|-----------|------|----------|---------|-------------|
|
|
207
210
|
| `message` | AIMessage | Yes | - | AIMessage object |
|
|
208
|
-
| `first_tool_call_only` | bool | No | False | Whether to only
|
|
211
|
+
| `first_tool_call_only` | bool | No | False | Whether to only parse the first tool call |
|
|
209
212
|
|
|
210
213
|
```python
|
|
211
214
|
import datetime
|
|
@@ -234,7 +237,7 @@ if has_tool_calling(response):
|
|
|
234
237
|
Both can accept a `handler` parameter for custom breakpoint return and response handling logic.
|
|
235
238
|
|
|
236
239
|
```python
|
|
237
|
-
from langchain_dev_utils import human_in_the_loop
|
|
240
|
+
from langchain_dev_utils.tool_calling import human_in_the_loop
|
|
238
241
|
from langchain_core.tools import tool
|
|
239
242
|
import datetime
|
|
240
243
|
|
|
@@ -262,7 +265,7 @@ In LangChain v1, the officially provided `create_agent` function can be used to
|
|
|
262
265
|
|
|
263
266
|
| Parameter | Type | Required | Default | Description |
|
|
264
267
|
|-----------|------|----------|---------|-------------|
|
|
265
|
-
| `model` | str
|
|
268
|
+
| `model` | str | Yes | - | Model name or model instance. Can be a string identifier for a model registered with `register_model_provider` or a BaseChatModel instance. |
|
|
266
269
|
| Other parameters | Various | No | - | All other parameters are the same as in `langchain.agents.create_agent` |
|
|
267
270
|
|
|
268
271
|
Usage example:
|
|
@@ -317,7 +320,7 @@ Uses `create_sequential_pipeline`, supported parameters:
|
|
|
317
320
|
|
|
318
321
|
| Parameter | Type | Required | Default | Description |
|
|
319
322
|
|-----------|------|----------|---------|-------------|
|
|
320
|
-
| `sub_graphs` | List[StateGraph] | Yes | - | List of state graphs to combine (must be StateGraph instances) |
|
|
323
|
+
| `sub_graphs` | List[StateGraph\|CompiledStateGraph] | Yes | - | List of state graphs to combine (must be StateGraph instances or CompiledStateGraph instances) |
|
|
321
324
|
| `state_schema` | type | Yes | - | State Schema for the final generated graph |
|
|
322
325
|
| `graph_name` | str | No | - | Name of the final generated graph |
|
|
323
326
|
| `context_schema` | type | No | - | Context Schema for the final generated graph |
|
|
@@ -378,7 +381,7 @@ Uses `create_parallel_pipeline`, supported parameters:
|
|
|
378
381
|
|
|
379
382
|
| Parameter | Type | Required | Default | Description |
|
|
380
383
|
|-----------|------|----------|---------|-------------|
|
|
381
|
-
| `sub_graphs` | List[StateGraph] | Yes | - | List of state graphs to combine |
|
|
384
|
+
| `sub_graphs` | List[StateGraph\|CompiledStateGraph] | Yes | - | List of state graphs to combine (must be StateGraph instances or CompiledStateGraph instances) |
|
|
382
385
|
| `state_schema` | type | Yes | - | State Schema for the final generated graph |
|
|
383
386
|
| `branches_fn` | Callable | Yes | - | Parallel branch function, returns a list of Send objects to control parallel execution |
|
|
384
387
|
| `graph_name` | str | No | - | Name of the final generated graph |
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
langchain_dev_utils/__init__.py,sha256=
|
|
1
|
+
langchain_dev_utils/__init__.py,sha256=vMQK58X8_YZGKzRm0ThvPAKFtpfyejGmUnDrY9RQ13w,22
|
|
2
|
+
langchain_dev_utils/_utils.py,sha256=5bFs4cf3HvkMNkv35V8Sowu4YSXmfF5VNwmv_eHfkgQ,1151
|
|
2
3
|
langchain_dev_utils/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
4
|
langchain_dev_utils/agents/__init__.py,sha256=e17SMQdJIQngbUCr2N1tY-yw0tD3tEnH7PSvyDmVPeQ,127
|
|
4
5
|
langchain_dev_utils/agents/factory.py,sha256=JjdJwPTJpQwAlwQlBalbuGej5Jcpy2Fz6lH3EwEaxQo,3979
|
|
@@ -13,12 +14,12 @@ langchain_dev_utils/agents/middleware/summarization.py,sha256=BtWPJcQBssGAT0nb1c
|
|
|
13
14
|
langchain_dev_utils/agents/middleware/tool_emulator.py,sha256=u9rV24yUB-dyc1uUfUe74B1wOGVI3TZRwxkE1bvGm18,2025
|
|
14
15
|
langchain_dev_utils/agents/middleware/tool_selection.py,sha256=ZqdyK4Yhp2u3GM6B_D6U7Srca9vy1o7s6N_LrV24-dQ,3107
|
|
15
16
|
langchain_dev_utils/chat_models/__init__.py,sha256=YSLUyHrWEEj4y4DtGFCOnDW02VIYZdfAH800m4Klgeg,224
|
|
16
|
-
langchain_dev_utils/chat_models/base.py,sha256=
|
|
17
|
+
langchain_dev_utils/chat_models/base.py,sha256=AYRcGViGJYsquqru_www3zt8-ZCkfzPCrw-dFF6HDts,11661
|
|
17
18
|
langchain_dev_utils/chat_models/types.py,sha256=M0iCGWgXmX1f1vkymH-jNGdFQlsJS5JqpmgHctUS9jw,512
|
|
18
19
|
langchain_dev_utils/chat_models/adapters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
19
20
|
langchain_dev_utils/chat_models/adapters/openai_compatible.py,sha256=4Q8ySa7jS2_AFo0oxLoqeY_aQyPppvV-DAMLt2rmGoE,20192
|
|
20
21
|
langchain_dev_utils/embeddings/__init__.py,sha256=zbEOaV86TUi9Zrg_dH9dpdgacWg31HMJTlTQknA9EKk,244
|
|
21
|
-
langchain_dev_utils/embeddings/base.py,sha256=
|
|
22
|
+
langchain_dev_utils/embeddings/base.py,sha256=lGZWbi6G1M0OcAO_d_k1QAFJm9z9gM0L4UAZ6xFtEoQ,8973
|
|
22
23
|
langchain_dev_utils/message_convert/__init__.py,sha256=xwjaQ1oJoc80xy70oQI4uW3gAmgV5JymJd5hgnA6s3g,458
|
|
23
24
|
langchain_dev_utils/message_convert/content.py,sha256=ApmQ7fUUBO3Ihjm2hYSWd4GrU_CvrjbWla-MA7DAFRc,7758
|
|
24
25
|
langchain_dev_utils/message_convert/format.py,sha256=fh4GyyuZBTMrHeCEwdu9fOh5n8tdli1vDF44jK1i-tI,2373
|
|
@@ -29,7 +30,7 @@ langchain_dev_utils/pipeline/types.py,sha256=T3aROKKXeWvd0jcH5XkgMDQfEkLfPaiOhhV
|
|
|
29
30
|
langchain_dev_utils/tool_calling/__init__.py,sha256=mu_WxKMcu6RoTf4vkTPbA1WSBSNc6YIqyBtOQ6iVQj4,322
|
|
30
31
|
langchain_dev_utils/tool_calling/human_in_the_loop.py,sha256=nbaON9806pv5tpMRQUA_Ch3HJA5HBFgzZR7kQRf6PiY,9819
|
|
31
32
|
langchain_dev_utils/tool_calling/utils.py,sha256=3cNv_Zx32KxdsGn8IkxjWUzxYEEwVJeJgTZTbfSg0pA,2751
|
|
32
|
-
langchain_dev_utils-1.2.
|
|
33
|
-
langchain_dev_utils-1.2.
|
|
34
|
-
langchain_dev_utils-1.2.
|
|
35
|
-
langchain_dev_utils-1.2.
|
|
33
|
+
langchain_dev_utils-1.2.6.dist-info/METADATA,sha256=PhJoxRlERmnMzRumGzLW3kwU58Cg3Tt6MiFibsfIi8U,19090
|
|
34
|
+
langchain_dev_utils-1.2.6.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
35
|
+
langchain_dev_utils-1.2.6.dist-info/licenses/LICENSE,sha256=AWAOzNEcsvCEzHOF0qby5OKxviVH_eT9Yce1sgJTico,1084
|
|
36
|
+
langchain_dev_utils-1.2.6.dist-info/RECORD,,
|
|
File without changes
|
{langchain_dev_utils-1.2.5.dist-info → langchain_dev_utils-1.2.6.dist-info}/licenses/LICENSE
RENAMED
|
File without changes
|