Skip to content

Commit dc42e89

Browse files
Merge branch 'master' into mmk/bound_parameters
2 parents ad1b150 + 135a208 commit dc42e89

22 files changed

Lines changed: 273 additions & 43 deletions

File tree

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# Refreshes model profile data for all in-monorepo partner integrations by
2+
# pulling the latest metadata from models.dev via the `langchain-profiles` CLI.
3+
#
4+
# Creates a pull request with any changes. Triggered manually from the Actions UI.
5+
6+
name: "🔄 Refresh Model Profiles"
7+
8+
on:
9+
workflow_dispatch:
10+
11+
permissions:
12+
contents: write
13+
pull-requests: write
14+
15+
jobs:
16+
refresh-profiles:
17+
name: "refresh all partner profiles"
18+
runs-on: ubuntu-latest
19+
steps:
20+
- name: "📋 Checkout"
21+
uses: actions/checkout@v6
22+
23+
- name: "🐍 Set up Python + uv"
24+
uses: ./.github/actions/uv_setup
25+
with:
26+
python-version: "3.12"
27+
working-directory: libs/model-profiles
28+
29+
- name: "📦 Install langchain-profiles CLI"
30+
working-directory: libs/model-profiles
31+
run: uv sync
32+
33+
- name: "🔄 Refresh profiles"
34+
working-directory: libs/model-profiles
35+
run: |
36+
declare -A PROVIDERS=(
37+
[anthropic]=anthropic
38+
[deepseek]=deepseek
39+
[fireworks]=fireworks-ai
40+
[groq]=groq
41+
[huggingface]=huggingface
42+
[mistralai]=mistral
43+
[openai]=openai
44+
[openrouter]=openrouter
45+
[perplexity]=perplexity
46+
[xai]=xai
47+
)
48+
49+
for partner in "${!PROVIDERS[@]}"; do
50+
provider="${PROVIDERS[$partner]}"
51+
data_dir="../../libs/partners/${partner}/langchain_${partner//-/_}/data"
52+
echo "--- Refreshing ${partner} (provider: ${provider}) ---"
53+
echo y | uv run langchain-profiles refresh \
54+
--provider "$provider" \
55+
--data-dir "$data_dir"
56+
done
57+
58+
- name: "🔀 Create pull request"
59+
uses: peter-evans/create-pull-request@v7
60+
with:
61+
branch: bot/refresh-model-profiles
62+
commit-message: "chore(model-profiles): refresh model profile data"
63+
title: "chore(model-profiles): refresh model profile data"
64+
body: |
65+
Automated refresh of model profile data for all in-monorepo partner
66+
integrations via `langchain-profiles refresh`.
67+
68+
🤖 Generated by the `refresh_model_profiles` workflow.
69+
add-paths: libs/partners/**/data/_profiles.py

AGENTS.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,29 @@ def send_email(to: str, msg: str, *, priority: str = "normal") -> bool:
194194
- Ensure American English spelling (e.g., "behavior", not "behaviour")
195195
- Do NOT use Sphinx-style double backtick formatting (` ``code`` `). Use single backticks (`` `code` ``) for inline code references in docstrings and comments.
196196

197+
## Model profiles
198+
199+
Model profiles are generated using the `langchain-profiles` CLI in `libs/model-profiles`. The `--data-dir` must point to the directory containing `profile_augmentations.toml`, not the top-level package directory.
200+
201+
```bash
202+
# Run from libs/model-profiles
203+
cd libs/model-profiles
204+
205+
# Refresh profiles for a partner in this repo
206+
uv run langchain-profiles refresh --provider openai --data-dir ../partners/openai/langchain_openai/data
207+
208+
# Refresh profiles for a partner in an external repo (requires echo y to confirm)
209+
echo y | uv run langchain-profiles refresh --provider google --data-dir /path/to/langchain-google/libs/genai/langchain_google_genai/data
210+
```
211+
212+
Example partners with profiles in this repo:
213+
214+
- `libs/partners/openai/langchain_openai/data/` (provider: `openai`)
215+
- `libs/partners/anthropic/langchain_anthropic/data/` (provider: `anthropic`)
216+
- `libs/partners/perplexity/langchain_perplexity/data/` (provider: `perplexity`)
217+
218+
The `echo y |` pipe is required when `--data-dir` is outside the `libs/model-profiles` working directory.
219+
197220
## Additional resources
198221

199222
- **Documentation:** https://docs.langchain.com/oss/python/langchain/overview and source at https://github.com/langchain-ai/docs or `../docs/`. Prefer the local install and use file search tools for best results. If needed, use the docs MCP server as defined in `.mcp.json` for programmatic access.

CLAUDE.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,29 @@ def send_email(to: str, msg: str, *, priority: str = "normal") -> bool:
194194
- Ensure American English spelling (e.g., "behavior", not "behaviour")
195195
- Do NOT use Sphinx-style double backtick formatting (` ``code`` `). Use single backticks (`` `code` ``) for inline code references in docstrings and comments.
196196

197+
## Model profiles
198+
199+
Model profiles are generated using the `langchain-profiles` CLI in `libs/model-profiles`. The `--data-dir` must point to the directory containing `profile_augmentations.toml`, not the top-level package directory.
200+
201+
```bash
202+
# Run from libs/model-profiles
203+
cd libs/model-profiles
204+
205+
# Refresh profiles for a partner in this repo
206+
uv run langchain-profiles refresh --provider openai --data-dir ../partners/openai/langchain_openai/data
207+
208+
# Refresh profiles for a partner in an external repo (requires echo y to confirm)
209+
echo y | uv run langchain-profiles refresh --provider google --data-dir /path/to/langchain-google/libs/genai/langchain_google_genai/data
210+
```
211+
212+
Example partners with profiles in this repo:
213+
214+
- `libs/partners/openai/langchain_openai/data/` (provider: `openai`)
215+
- `libs/partners/anthropic/langchain_anthropic/data/` (provider: `anthropic`)
216+
- `libs/partners/perplexity/langchain_perplexity/data/` (provider: `perplexity`)
217+
218+
The `echo y |` pipe is required when `--data-dir` is outside the `libs/model-profiles` working directory.
219+
197220
## Additional resources
198221

199222
- **Documentation:** https://docs.langchain.com/oss/python/langchain/overview and source at https://github.com/langchain-ai/docs or `../docs/`. Prefer the local install and use file search tools for best results. If needed, use the docs MCP server as defined in `.mcp.json` for programmatic access.

libs/core/langchain_core/sys_info.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,9 @@ def print_sys_info(*, additional_pkgs: Sequence[str] = ()) -> None:
4141
"""
4242
# Packages that do not start with "langchain" prefix.
4343
other_langchain_packages = [
44-
"langserve",
4544
"langsmith",
45+
"deepagents",
46+
"deepagents-cli",
4647
]
4748

4849
langchain_pkgs = [

libs/core/langchain_core/utils/_merge.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,15 @@ def merge_lists(left: list | None, *others: list | None) -> list | None:
117117
to_merge = [
118118
i
119119
for i, e_left in enumerate(merged)
120-
if "index" in e_left and e_left["index"] == e["index"]
120+
if (
121+
"index" in e_left
122+
and e_left["index"] == e["index"] # index matches
123+
and ( # IDs not inconsistent
124+
e_left.get("id") is None
125+
or e.get("id") is None
126+
or e_left["id"] == e["id"]
127+
)
128+
)
121129
]
122130
if to_merge:
123131
# TODO: Remove this once merge_dict is updated with special
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
"""langchain-core version information and utilities."""
22

3-
VERSION = "1.2.13"
3+
VERSION = "1.2.14"

libs/core/pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ classifiers = [
2121
"Topic :: Software Development :: Libraries :: Python Modules",
2222
]
2323

24-
version = "1.2.13"
24+
version = "1.2.14"
2525
requires-python = ">=3.10.0,<4.0.0"
2626
dependencies = [
2727
"langsmith>=0.3.45,<1.0.0",
@@ -133,7 +133,7 @@ ignore-var-parameters = true # ignore missing documentation for *args and **kwa
133133
"langchain_core/sys_info.py" = [ "T201",]
134134
"tests/unit_tests/test_tools.py" = [ "ARG",]
135135
"tests/**" = [ "D1", "PLR2004", "S", "SLF",]
136-
"scripts/**" = [ "INP", "S",]
136+
"scripts/**" = [ "INP", "S", "T201",]
137137

138138
[tool.coverage.run]
139139
omit = [ "tests/*",]

libs/core/scripts/check_imports.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717
SourceFileLoader(module_name, file).load_module()
1818
except Exception:
1919
has_failure = True
20-
print(file) # noqa: T201
20+
print(file)
2121
traceback.print_exc()
22-
print() # noqa: T201
22+
print()
2323

2424
sys.exit(1 if has_failure else 0)

libs/core/scripts/check_version.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,31 +33,31 @@ def main() -> int:
3333
version_path = package_dir / "langchain_core" / "version.py"
3434

3535
if not pyproject_path.exists():
36-
print(f"Error: {pyproject_path} not found") # noqa: T201
36+
print(f"Error: {pyproject_path} not found")
3737
return 1
3838

3939
if not version_path.exists():
40-
print(f"Error: {version_path} not found") # noqa: T201
40+
print(f"Error: {version_path} not found")
4141
return 1
4242

4343
pyproject_version = get_pyproject_version(pyproject_path)
4444
version_py_version = get_version_py_version(version_path)
4545

4646
if pyproject_version is None:
47-
print("Error: Could not find version in pyproject.toml") # noqa: T201
47+
print("Error: Could not find version in pyproject.toml")
4848
return 1
4949

5050
if version_py_version is None:
51-
print("Error: Could not find VERSION in langchain_core/version.py") # noqa: T201
51+
print("Error: Could not find VERSION in langchain_core/version.py")
5252
return 1
5353

5454
if pyproject_version != version_py_version:
55-
print("Error: Version mismatch detected!") # noqa: T201
56-
print(f" pyproject.toml: {pyproject_version}") # noqa: T201
57-
print(f" langchain_core/version.py: {version_py_version}") # noqa: T201
55+
print("Error: Version mismatch detected!")
56+
print(f" pyproject.toml: {pyproject_version}")
57+
print(f" langchain_core/version.py: {version_py_version}")
5858
return 1
5959

60-
print(f"Version check passed: {pyproject_version}") # noqa: T201
60+
print(f"Version check passed: {pyproject_version}")
6161
return 0
6262

6363

libs/core/tests/unit_tests/test_messages.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -916,6 +916,47 @@ def test_merge_tool_calls() -> None:
916916
assert len(merged) == 2
917917

918918

919+
def test_merge_tool_calls_parallel_same_index() -> None:
920+
"""Test parallel tool calls with same index but different IDs."""
921+
# Two parallel tool calls with the same index but different IDs
922+
left = create_tool_call_chunk(
923+
name="read_file", args='{"path": "foo.txt"}', id="tooluse_ABC", index=0
924+
)
925+
right = create_tool_call_chunk(
926+
name="search_text", args='{"query": "bar"}', id="tooluse_DEF", index=0
927+
)
928+
merged = merge_lists([left], [right])
929+
assert merged is not None
930+
assert len(merged) == 2
931+
assert merged[0]["name"] == "read_file"
932+
assert merged[0]["id"] == "tooluse_ABC"
933+
assert merged[1]["name"] == "search_text"
934+
assert merged[1]["id"] == "tooluse_DEF"
935+
936+
# Streaming continuation: same index, id=None on continuation chunk
937+
# should still merge correctly with the original chunk
938+
first = create_tool_call_chunk(name="tool1", args="", id="id1", index=0)
939+
continuation = create_tool_call_chunk(
940+
name=None, args='{"key": "value"}', id=None, index=0
941+
)
942+
merged = merge_lists([first], [continuation])
943+
assert merged is not None
944+
assert len(merged) == 1
945+
assert merged[0]["name"] == "tool1"
946+
assert merged[0]["args"] == '{"key": "value"}'
947+
assert merged[0]["id"] == "id1"
948+
949+
# Three parallel tool calls all with the same index
950+
tc1 = create_tool_call_chunk(name="tool_a", args="{}", id="id_a", index=0)
951+
tc2 = create_tool_call_chunk(name="tool_b", args="{}", id="id_b", index=0)
952+
tc3 = create_tool_call_chunk(name="tool_c", args="{}", id="id_c", index=0)
953+
merged = merge_lists([tc1], [tc2], [tc3])
954+
assert merged is not None
955+
assert len(merged) == 3
956+
assert [m["name"] for m in merged] == ["tool_a", "tool_b", "tool_c"]
957+
assert [m["id"] for m in merged] == ["id_a", "id_b", "id_c"]
958+
959+
919960
def test_tool_message_serdes() -> None:
920961
message = ToolMessage(
921962
"foo", artifact={"bar": {"baz": 123}}, tool_call_id="1", status="error"

0 commit comments

Comments
 (0)