Merge branch 'master' into wip-v0.4

This commit is contained in:
Mason Daugherty
2025-08-11 15:10:42 -04:00
committed by GitHub
19 changed files with 206 additions and 63 deletions

20
libs/core/uv.lock generated
View File

@@ -1170,7 +1170,7 @@ requires-dist = [
[package.metadata.requires-dev] [package.metadata.requires-dev]
codespell = [{ name = "codespell", specifier = ">=2.2.0,<3.0.0" }] codespell = [{ name = "codespell", specifier = ">=2.2.0,<3.0.0" }]
lint = [{ name = "ruff", specifier = ">=0.12.2,<0.13" }] lint = [{ name = "ruff", specifier = ">=0.12.8,<0.13" }]
test = [{ name = "langchain-core", editable = "." }] test = [{ name = "langchain-core", editable = "." }]
test-integration = [] test-integration = []
typing = [ typing = [
@@ -1184,10 +1184,14 @@ version = "0.3.9"
source = { directory = "../text-splitters" } source = { directory = "../text-splitters" }
dependencies = [ dependencies = [
{ name = "langchain-core" }, { name = "langchain-core" },
{ name = "pip" },
] ]
[package.metadata] [package.metadata]
requires-dist = [{ name = "langchain-core", editable = "." }] requires-dist = [
{ name = "langchain-core", editable = "." },
{ name = "pip", specifier = ">=25.2" },
]
[package.metadata.requires-dev] [package.metadata.requires-dev]
dev = [ dev = [
@@ -1196,7 +1200,7 @@ dev = [
] ]
lint = [ lint = [
{ name = "langchain-core", editable = "." }, { name = "langchain-core", editable = "." },
{ name = "ruff", specifier = ">=0.12.2,<0.13" }, { name = "ruff", specifier = ">=0.12.8,<0.13" },
] ]
test = [ test = [
{ name = "freezegun", specifier = ">=1.2.2,<2.0.0" }, { name = "freezegun", specifier = ">=1.2.2,<2.0.0" },
@@ -1213,6 +1217,7 @@ test-integration = [
{ name = "sentence-transformers", specifier = ">=3.0.1" }, { name = "sentence-transformers", specifier = ">=3.0.1" },
{ name = "spacy", specifier = ">=3.8.7,<4.0.0" }, { name = "spacy", specifier = ">=3.8.7,<4.0.0" },
{ name = "thinc", specifier = ">=8.3.6,<9.0.0" }, { name = "thinc", specifier = ">=8.3.6,<9.0.0" },
{ name = "tiktoken", specifier = ">=0.8.0,<1.0.0" },
{ name = "transformers", specifier = ">=4.51.3,<5.0.0" }, { name = "transformers", specifier = ">=4.51.3,<5.0.0" },
] ]
typing = [ typing = [
@@ -1993,6 +1998,15 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/9e/c3/059298687310d527a58bb01f3b1965787ee3b40dce76752eda8b44e9a2c5/pexpect-4.9.0-py2.py3-none-any.whl", hash = "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523", size = 63772, upload-time = "2023-11-25T06:56:14.81Z" }, { url = "https://files.pythonhosted.org/packages/9e/c3/059298687310d527a58bb01f3b1965787ee3b40dce76752eda8b44e9a2c5/pexpect-4.9.0-py2.py3-none-any.whl", hash = "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523", size = 63772, upload-time = "2023-11-25T06:56:14.81Z" },
] ]
[[package]]
name = "pip"
version = "25.2"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/20/16/650289cd3f43d5a2fadfd98c68bd1e1e7f2550a1a5326768cddfbcedb2c5/pip-25.2.tar.gz", hash = "sha256:578283f006390f85bb6282dffb876454593d637f5d1be494b5202ce4877e71f2", size = 1840021, upload-time = "2025-07-30T21:50:15.401Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/b7/3f/945ef7ab14dc4f9d7f40288d2df998d1837ee0888ec3659c813487572faa/pip-25.2-py3-none-any.whl", hash = "sha256:6d67a2b4e7f14d8b31b8b52648866fa717f45a1eb70e83002f4331d07e953717", size = 1752557, upload-time = "2025-07-30T21:50:13.323Z" },
]
[[package]] [[package]]
name = "platformdirs" name = "platformdirs"
version = "4.3.8" version = "4.3.8"

View File

@@ -201,15 +201,41 @@ class _EmbeddingDistanceChainMixin(Chain):
np.ndarray: The cosine distance. np.ndarray: The cosine distance.
""" """
try: try:
from langchain_community.utils.math import cosine_similarity from langchain_core.vectorstores.utils import _cosine_similarity
except ImportError as e:
msg = ( return 1.0 - _cosine_similarity(a, b)
"The cosine_similarity function is required to compute cosine distance." except ImportError:
" Please install the langchain-community package using" # Fallback to scipy if available
" `pip install langchain-community`." try:
) from scipy.spatial.distance import cosine
raise ImportError(msg) from e
return 1.0 - cosine_similarity(a, b) return cosine(a.flatten(), b.flatten())
except ImportError:
# Pure numpy fallback
if _check_numpy():
np = _import_numpy()
a_flat = a.flatten()
b_flat = b.flatten()
dot_product = np.dot(a_flat, b_flat)
norm_a = np.linalg.norm(a_flat)
norm_b = np.linalg.norm(b_flat)
if norm_a == 0 or norm_b == 0:
return 0.0
return 1.0 - (dot_product / (norm_a * norm_b))
# Pure Python implementation
a_flat = a if hasattr(a, "__len__") else [a]
b_flat = b if hasattr(b, "__len__") else [b]
if hasattr(a, "flatten"):
a_flat = a.flatten()
if hasattr(b, "flatten"):
b_flat = b.flatten()
dot_product = sum(x * y for x, y in zip(a_flat, b_flat))
norm_a = sum(x * x for x in a_flat) ** 0.5
norm_b = sum(x * x for x in b_flat) ** 0.5
if norm_a == 0 or norm_b == 0:
return 0.0
return 1.0 - (dot_product / (norm_a * norm_b))
@staticmethod @staticmethod
def _euclidean_distance(a: Any, b: Any) -> Any: def _euclidean_distance(a: Any, b: Any) -> Any:
@@ -222,12 +248,17 @@ class _EmbeddingDistanceChainMixin(Chain):
Returns: Returns:
np.floating: The Euclidean distance. np.floating: The Euclidean distance.
""" """
if _check_numpy(): try:
import numpy as np from scipy.spatial.distance import euclidean
return np.linalg.norm(a - b) return euclidean(a.flatten(), b.flatten())
except ImportError:
if _check_numpy():
import numpy as np
return sum((x - y) * (x - y) for x, y in zip(a, b)) ** 0.5 return np.linalg.norm(a - b)
return sum((x - y) * (x - y) for x, y in zip(a, b)) ** 0.5
@staticmethod @staticmethod
def _manhattan_distance(a: Any, b: Any) -> Any: def _manhattan_distance(a: Any, b: Any) -> Any:
@@ -240,11 +271,16 @@ class _EmbeddingDistanceChainMixin(Chain):
Returns: Returns:
np.floating: The Manhattan distance. np.floating: The Manhattan distance.
""" """
if _check_numpy(): try:
np = _import_numpy() from scipy.spatial.distance import cityblock
return np.sum(np.abs(a - b))
return sum(abs(x - y) for x, y in zip(a, b)) return cityblock(a.flatten(), b.flatten())
except ImportError:
if _check_numpy():
np = _import_numpy()
return np.sum(np.abs(a - b))
return sum(abs(x - y) for x, y in zip(a, b))
@staticmethod @staticmethod
def _chebyshev_distance(a: Any, b: Any) -> Any: def _chebyshev_distance(a: Any, b: Any) -> Any:
@@ -257,11 +293,16 @@ class _EmbeddingDistanceChainMixin(Chain):
Returns: Returns:
np.floating: The Chebyshev distance. np.floating: The Chebyshev distance.
""" """
if _check_numpy(): try:
np = _import_numpy() from scipy.spatial.distance import chebyshev
return np.max(np.abs(a - b))
return max(abs(x - y) for x, y in zip(a, b)) return chebyshev(a.flatten(), b.flatten())
except ImportError:
if _check_numpy():
np = _import_numpy()
return np.max(np.abs(a - b))
return max(abs(x - y) for x, y in zip(a, b))
@staticmethod @staticmethod
def _hamming_distance(a: Any, b: Any) -> Any: def _hamming_distance(a: Any, b: Any) -> Any:
@@ -274,11 +315,16 @@ class _EmbeddingDistanceChainMixin(Chain):
Returns: Returns:
np.floating: The Hamming distance. np.floating: The Hamming distance.
""" """
if _check_numpy(): try:
np = _import_numpy() from scipy.spatial.distance import hamming
return np.mean(a != b)
return sum(1 for x, y in zip(a, b) if x != y) / len(a) return hamming(a.flatten(), b.flatten())
except ImportError:
if _check_numpy():
np = _import_numpy()
return np.mean(a != b)
return sum(1 for x, y in zip(a, b) if x != y) / len(a)
def _compute_score(self, vectors: Any) -> float: def _compute_score(self, vectors: Any) -> float:
"""Compute the score based on the distance metric. """Compute the score based on the distance metric.

24
libs/langchain/uv.lock generated
View File

@@ -1,5 +1,5 @@
version = 1 version = 1
revision = 2 revision = 3
requires-python = ">=3.9, <4.0" requires-python = ">=3.9, <4.0"
resolution-markers = [ resolution-markers = [
"python_full_version >= '3.13' and platform_python_implementation == 'PyPy'", "python_full_version >= '3.13' and platform_python_implementation == 'PyPy'",
@@ -2241,7 +2241,7 @@ test = [
test-integration = [] test-integration = []
typing = [ typing = [
{ name = "langchain-text-splitters", directory = "../text-splitters" }, { name = "langchain-text-splitters", directory = "../text-splitters" },
{ name = "mypy", specifier = ">=1.15,<1.16" }, { name = "mypy", specifier = ">=1.17.1,<1.18" },
{ name = "types-pyyaml", specifier = ">=6.0.12.2,<7.0.0.0" }, { name = "types-pyyaml", specifier = ">=6.0.12.2,<7.0.0.0" },
{ name = "types-requests", specifier = ">=2.28.11.5,<3.0.0.0" }, { name = "types-requests", specifier = ">=2.28.11.5,<3.0.0.0" },
] ]
@@ -2445,7 +2445,7 @@ requires-dist = [
[package.metadata.requires-dev] [package.metadata.requires-dev]
codespell = [{ name = "codespell", specifier = ">=2.2.0,<3.0.0" }] codespell = [{ name = "codespell", specifier = ">=2.2.0,<3.0.0" }]
lint = [{ name = "ruff", specifier = ">=0.12.2,<0.13" }] lint = [{ name = "ruff", specifier = ">=0.12.8,<0.13" }]
test = [{ name = "langchain-core", editable = "../core" }] test = [{ name = "langchain-core", editable = "../core" }]
test-integration = [] test-integration = []
typing = [ typing = [
@@ -2459,10 +2459,14 @@ version = "0.3.9"
source = { editable = "../text-splitters" } source = { editable = "../text-splitters" }
dependencies = [ dependencies = [
{ name = "langchain-core" }, { name = "langchain-core" },
{ name = "pip" },
] ]
[package.metadata] [package.metadata]
requires-dist = [{ name = "langchain-core", editable = "../core" }] requires-dist = [
{ name = "langchain-core", editable = "../core" },
{ name = "pip", specifier = ">=25.2" },
]
[package.metadata.requires-dev] [package.metadata.requires-dev]
dev = [ dev = [
@@ -2471,7 +2475,7 @@ dev = [
] ]
lint = [ lint = [
{ name = "langchain-core", editable = "../core" }, { name = "langchain-core", editable = "../core" },
{ name = "ruff", specifier = ">=0.12.2,<0.13" }, { name = "ruff", specifier = ">=0.12.8,<0.13" },
] ]
test = [ test = [
{ name = "freezegun", specifier = ">=1.2.2,<2.0.0" }, { name = "freezegun", specifier = ">=1.2.2,<2.0.0" },
@@ -2488,6 +2492,7 @@ test-integration = [
{ name = "sentence-transformers", specifier = ">=3.0.1" }, { name = "sentence-transformers", specifier = ">=3.0.1" },
{ name = "spacy", specifier = ">=3.8.7,<4.0.0" }, { name = "spacy", specifier = ">=3.8.7,<4.0.0" },
{ name = "thinc", specifier = ">=8.3.6,<9.0.0" }, { name = "thinc", specifier = ">=8.3.6,<9.0.0" },
{ name = "tiktoken", specifier = ">=0.8.0,<1.0.0" },
{ name = "transformers", specifier = ">=4.51.3,<5.0.0" }, { name = "transformers", specifier = ">=4.51.3,<5.0.0" },
] ]
typing = [ typing = [
@@ -3333,6 +3338,15 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/41/67/936f9814bdd74b2dfd4822f1f7725ab5d8ff4103919a1664eb4874c58b2f/pillow-11.1.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:4637b88343166249fe8aa94e7c4a62a180c4b3898283bb5d3d2fd5fe10d8e4e0", size = 2626353, upload-time = "2025-01-02T08:13:52.725Z" }, { url = "https://files.pythonhosted.org/packages/41/67/936f9814bdd74b2dfd4822f1f7725ab5d8ff4103919a1664eb4874c58b2f/pillow-11.1.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:4637b88343166249fe8aa94e7c4a62a180c4b3898283bb5d3d2fd5fe10d8e4e0", size = 2626353, upload-time = "2025-01-02T08:13:52.725Z" },
] ]
[[package]]
name = "pip"
version = "25.2"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/20/16/650289cd3f43d5a2fadfd98c68bd1e1e7f2550a1a5326768cddfbcedb2c5/pip-25.2.tar.gz", hash = "sha256:578283f006390f85bb6282dffb876454593d637f5d1be494b5202ce4877e71f2", size = 1840021, upload-time = "2025-07-30T21:50:15.401Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/b7/3f/945ef7ab14dc4f9d7f40288d2df998d1837ee0888ec3659c813487572faa/pip-25.2-py3-none-any.whl", hash = "sha256:6d67a2b4e7f14d8b31b8b52648866fa717f45a1eb70e83002f4331d07e953717", size = 1752557, upload-time = "2025-07-30T21:50:13.323Z" },
]
[[package]] [[package]]
name = "platformdirs" name = "platformdirs"
version = "4.3.6" version = "4.3.6"

View File

@@ -105,6 +105,8 @@ ignore = [
"D105", # pydocstyle: Missing docstring in magic method "D105", # pydocstyle: Missing docstring in magic method
"D107", # pydocstyle: Missing docstring in __init__ "D107", # pydocstyle: Missing docstring in __init__
"D407", # pydocstyle: Missing-dashed-underline-after-section "D407", # pydocstyle: Missing-dashed-underline-after-section
"D203",
"D213",
"D214", # Section over-indented, doesn't play well with reStructuredText "D214", # Section over-indented, doesn't play well with reStructuredText
"COM812", # Messes with the formatter "COM812", # Messes with the formatter
"ISC001", # Messes with the formatter "ISC001", # Messes with the formatter

View File

@@ -598,7 +598,7 @@ requires-dist = [
[package.metadata.requires-dev] [package.metadata.requires-dev]
codespell = [{ name = "codespell", specifier = ">=2.2.0,<3.0.0" }] codespell = [{ name = "codespell", specifier = ">=2.2.0,<3.0.0" }]
lint = [{ name = "ruff", specifier = ">=0.12.2,<0.13" }] lint = [{ name = "ruff", specifier = ">=0.12.8,<0.13" }]
test = [{ name = "langchain-core", editable = "../../core" }] test = [{ name = "langchain-core", editable = "../../core" }]
test-integration = [] test-integration = []
typing = [ typing = [

View File

@@ -95,6 +95,8 @@ ignore = [
"D104", # Missing docstring in public package "D104", # Missing docstring in public package
"D105", # Missing docstring in magic method "D105", # Missing docstring in magic method
"D107", # Missing docstring in __init__ "D107", # Missing docstring in __init__
"D203",
"D213",
"COM812", # Messes with the formatter "COM812", # Messes with the formatter
"ISC001", # Messes with the formatter "ISC001", # Messes with the formatter
"PERF203", # Rarely useful "PERF203", # Rarely useful

View File

@@ -88,6 +88,8 @@ ignore = [
"D104", # Missing docstring in public package "D104", # Missing docstring in public package
"D105", # Missing docstring in magic method "D105", # Missing docstring in magic method
"D107", # Missing docstring in __init__ "D107", # Missing docstring in __init__
"D203",
"D213",
"COM812", # Messes with the formatter "COM812", # Messes with the formatter
"ISC001", # Messes with the formatter "ISC001", # Messes with the formatter
"PERF203", # Rarely useful "PERF203", # Rarely useful

View File

@@ -485,7 +485,7 @@ requires-dist = [
[package.metadata.requires-dev] [package.metadata.requires-dev]
codespell = [{ name = "codespell", specifier = ">=2.2.0,<3.0.0" }] codespell = [{ name = "codespell", specifier = ">=2.2.0,<3.0.0" }]
lint = [{ name = "ruff", specifier = ">=0.12.2,<0.13" }] lint = [{ name = "ruff", specifier = ">=0.12.8,<0.13" }]
test = [{ name = "langchain-core", editable = "../../core" }] test = [{ name = "langchain-core", editable = "../../core" }]
test-integration = [] test-integration = []
typing = [ typing = [

View File

@@ -102,6 +102,8 @@ ignore = [
"D104", # pydocstyle: Missing docstring in public package "D104", # pydocstyle: Missing docstring in public package
"D105", # pydocstyle: Missing docstring in magic method "D105", # pydocstyle: Missing docstring in magic method
"D107", # pydocstyle: Missing docstring in __init__ "D107", # pydocstyle: Missing docstring in __init__
"D203",
"D213",
"D407", # pydocstyle: Missing-dashed-underline-after-section "D407", # pydocstyle: Missing-dashed-underline-after-section
"COM812", # Messes with the formatter "COM812", # Messes with the formatter
"ISC001", # Messes with the formatter "ISC001", # Messes with the formatter

View File

@@ -8,10 +8,14 @@ UV_FROZEN = true
# Define a variable for the test file path. # Define a variable for the test file path.
TEST_FILE ?= tests/unit_tests/ TEST_FILE ?= tests/unit_tests/
integration_test: TEST_FILE = tests/integration_tests/ integration_test integration_tests: TEST_FILE = tests/integration_tests/
# note: leaving out integration_tests (with s) command to skip release testing for now # note: leaving out integration_tests (with s) command to skip release testing for now
# TODO(erick) configure ollama server to run in CI, in separate repo # TODO(erick) configure ollama server to run in CI, in separate repo
# Define variables for test model configuration
OLLAMA_TEST_MODEL ?= llama3.1
OLLAMA_REASONING_TEST_MODEL ?= deepseek-r1:1.5b
# unit tests are run with the --disable-socket flag to prevent network calls # unit tests are run with the --disable-socket flag to prevent network calls
test tests: test tests:
@@ -22,10 +26,9 @@ test_watch:
# integration tests are run without the --disable-socket flag to allow network calls # integration tests are run without the --disable-socket flag to allow network calls
integration_test: integration_test integration_tests:
uv run --group test --group test_integration pytest $(TEST_FILE) OLLAMA_TEST_MODEL=$(OLLAMA_TEST_MODEL) OLLAMA_REASONING_TEST_MODEL=$(OLLAMA_REASONING_TEST_MODEL) uv run --group test --group test_integration pytest $(TEST_FILE)
# note: leaving out integration_tests (with s) command to skip release testing for now # note: leaving out integration_tests (with s) command to skip release testing for now
# TODO(erick) configure ollama server to run in CI, in separate repo
###################### ######################
# LINTING AND FORMATTING # LINTING AND FORMATTING
@@ -70,3 +73,6 @@ help:
@echo 'test - run unit tests' @echo 'test - run unit tests'
@echo 'tests - run unit tests' @echo 'tests - run unit tests'
@echo 'test TEST_FILE=<test_file> - run all tests in file' @echo 'test TEST_FILE=<test_file> - run all tests in file'
@echo 'integration_test - run integration tests'
@echo 'integration_test OLLAMA_TEST_MODEL=<model> - run integration tests with specific model'
@echo ' Example: make integration_test OLLAMA_TEST_MODEL=llama3.1'

View File

@@ -145,10 +145,14 @@ def _parse_arguments_from_tool_call(
""" """
if "function" not in raw_tool_call: if "function" not in raw_tool_call:
return None return None
function_name = raw_tool_call["function"]["name"]
arguments = raw_tool_call["function"]["arguments"] arguments = raw_tool_call["function"]["arguments"]
parsed_arguments: dict = {} parsed_arguments: dict = {}
if isinstance(arguments, dict): if isinstance(arguments, dict):
for key, value in arguments.items(): for key, value in arguments.items():
# Filter out metadata fields like 'functionName' that echo function name
if key == "functionName" and value == function_name:
continue
if isinstance(value, str): if isinstance(value, str):
parsed_value = _parse_json_string( parsed_value = _parse_json_string(
value, skip=True, raw_tool_call=raw_tool_call value, skip=True, raw_tool_call=raw_tool_call

View File

@@ -1,10 +1,12 @@
"""Test Ollama embeddings.""" """Test Ollama embeddings."""
import os
from langchain_tests.integration_tests import EmbeddingsIntegrationTests from langchain_tests.integration_tests import EmbeddingsIntegrationTests
from langchain_ollama.embeddings import OllamaEmbeddings from langchain_ollama.embeddings import OllamaEmbeddings
MODEL_NAME = "llama3.1" MODEL_NAME = os.environ.get("OLLAMA_TEST_MODEL", "llama3.1")
class TestOllamaEmbeddings(EmbeddingsIntegrationTests): class TestOllamaEmbeddings(EmbeddingsIntegrationTests):

View File

@@ -1,13 +1,15 @@
"""Test OllamaLLM llm.""" """Test OllamaLLM llm."""
import os
import pytest import pytest
from langchain_core.outputs import GenerationChunk from langchain_core.outputs import GenerationChunk
from langchain_core.runnables import RunnableConfig from langchain_core.runnables import RunnableConfig
from langchain_ollama.llms import OllamaLLM from langchain_ollama.llms import OllamaLLM
MODEL_NAME = "llama3.1" MODEL_NAME = os.environ.get("OLLAMA_TEST_MODEL", "llama3.1")
REASONING_MODEL_NAME = "deepseek-r1:1.5b" REASONING_MODEL_NAME = os.environ.get("OLLAMA_REASONING_TEST_MODEL", "deepseek-r1:1.5b")
SAMPLE = "What is 3^3?" SAMPLE = "What is 3^3?"

View File

@@ -50,6 +50,41 @@ def test__parse_arguments_from_tool_call() -> None:
assert isinstance(response["arg_1"], str) assert isinstance(response["arg_1"], str)
def test__parse_arguments_from_tool_call_with_function_name_metadata() -> None:
"""Test that functionName metadata is filtered out from tool arguments.
Some models may include metadata like ``functionName`` in the arguments
that just echoes the function name. This should be filtered out for
no-argument tools to return an empty dictionary.
"""
# Test case where arguments contain functionName metadata
raw_tool_call_with_metadata = {
"function": {
"name": "magic_function_no_args",
"arguments": {"functionName": "magic_function_no_args"},
}
}
response = _parse_arguments_from_tool_call(raw_tool_call_with_metadata)
assert response == {}
# Test case where arguments contain both real args and metadata
raw_tool_call_mixed = {
"function": {
"name": "some_function",
"arguments": {"functionName": "some_function", "real_arg": "value"},
}
}
response_mixed = _parse_arguments_from_tool_call(raw_tool_call_mixed)
assert response_mixed == {"real_arg": "value"}
# Test case where functionName has different value (should be preserved)
raw_tool_call_different = {
"function": {"name": "function_a", "arguments": {"functionName": "function_b"}}
}
response_different = _parse_arguments_from_tool_call(raw_tool_call_different)
assert response_different == {"functionName": "function_b"}
@contextmanager @contextmanager
def _mock_httpx_client_stream( def _mock_httpx_client_stream(
*args: Any, **kwargs: Any *args: Any, **kwargs: Any

View File

@@ -356,7 +356,7 @@ test = [
test-integration = [] test-integration = []
typing = [ typing = [
{ name = "langchain-text-splitters", directory = "../../text-splitters" }, { name = "langchain-text-splitters", directory = "../../text-splitters" },
{ name = "mypy", specifier = ">=1.15,<1.16" }, { name = "mypy", specifier = ">=1.17.1,<1.18" },
{ name = "types-pyyaml", specifier = ">=6.0.12.2,<7.0.0.0" }, { name = "types-pyyaml", specifier = ">=6.0.12.2,<7.0.0.0" },
{ name = "types-requests", specifier = ">=2.28.11.5,<3.0.0.0" }, { name = "types-requests", specifier = ">=2.28.11.5,<3.0.0.0" },
] ]
@@ -456,7 +456,7 @@ requires-dist = [
[package.metadata.requires-dev] [package.metadata.requires-dev]
codespell = [{ name = "codespell", specifier = ">=2.2.0,<3.0.0" }] codespell = [{ name = "codespell", specifier = ">=2.2.0,<3.0.0" }]
lint = [{ name = "ruff", specifier = ">=0.12.2,<0.13" }] lint = [{ name = "ruff", specifier = ">=0.12.8,<0.13" }]
test = [{ name = "langchain-core", editable = "../../core" }] test = [{ name = "langchain-core", editable = "../../core" }]
test-integration = [] test-integration = []
typing = [ typing = [

View File

@@ -73,6 +73,9 @@ ignore = [ "UP007", "UP045" ]
docstring-code-format = true docstring-code-format = true
skip-magic-trailing-comma = true skip-magic-trailing-comma = true
[tool.ruff.lint.isort]
split-on-trailing-comma = false
[tool.coverage.run] [tool.coverage.run]
omit = ["tests/*"] omit = ["tests/*"]

View File

@@ -1,5 +1,5 @@
version = 1 version = 1
revision = 2 revision = 3
requires-python = ">=3.9" requires-python = ">=3.9"
resolution-markers = [ resolution-markers = [
"python_full_version >= '3.13' and platform_python_implementation == 'PyPy'", "python_full_version >= '3.13' and platform_python_implementation == 'PyPy'",
@@ -588,7 +588,7 @@ typing = [
[package.metadata] [package.metadata]
requires-dist = [ requires-dist = [
{ name = "langchain-core", editable = "../../core" }, { name = "langchain-core", editable = "../../core" },
{ name = "openai", specifier = ">=1.99.3,<2.0.0" }, { name = "openai", specifier = ">=1.86.0,<2.0.0" },
{ name = "tiktoken", specifier = ">=0.7,<1" }, { name = "tiktoken", specifier = ">=0.7,<1" },
] ]
@@ -662,7 +662,7 @@ requires-dist = [
[package.metadata.requires-dev] [package.metadata.requires-dev]
codespell = [{ name = "codespell", specifier = ">=2.2.0,<3.0.0" }] codespell = [{ name = "codespell", specifier = ">=2.2.0,<3.0.0" }]
lint = [{ name = "ruff", specifier = ">=0.12.2,<0.13" }] lint = [{ name = "ruff", specifier = ">=0.12.8,<0.13" }]
test = [{ name = "langchain-core", editable = "../../core" }] test = [{ name = "langchain-core", editable = "../../core" }]
test-integration = [] test-integration = []
typing = [ typing = [

37
uv.lock generated
View File

@@ -1,5 +1,5 @@
version = 1 version = 1
revision = 2 revision = 3
requires-python = ">=3.9" requires-python = ">=3.9"
resolution-markers = [ resolution-markers = [
"python_full_version >= '3.13' and platform_python_implementation == 'PyPy'", "python_full_version >= '3.13' and platform_python_implementation == 'PyPy'",
@@ -2259,15 +2259,11 @@ dependencies = [
requires-dist = [ requires-dist = [
{ name = "async-timeout", marker = "python_full_version < '3.11'", specifier = ">=4.0.0,<5.0.0" }, { name = "async-timeout", marker = "python_full_version < '3.11'", specifier = ">=4.0.0,<5.0.0" },
{ name = "langchain-anthropic", marker = "extra == 'anthropic'" }, { name = "langchain-anthropic", marker = "extra == 'anthropic'" },
{ name = "langchain-aws", marker = "extra == 'aws'" },
{ name = "langchain-azure-ai", marker = "extra == 'azure-ai'" },
{ name = "langchain-cohere", marker = "extra == 'cohere'" },
{ name = "langchain-community", marker = "extra == 'community'" }, { name = "langchain-community", marker = "extra == 'community'" },
{ name = "langchain-core", editable = "libs/core" }, { name = "langchain-core", editable = "libs/core" },
{ name = "langchain-deepseek", marker = "extra == 'deepseek'" }, { name = "langchain-deepseek", marker = "extra == 'deepseek'" },
{ name = "langchain-fireworks", marker = "extra == 'fireworks'" }, { name = "langchain-fireworks", marker = "extra == 'fireworks'" },
{ name = "langchain-google-genai", marker = "extra == 'google-genai'" }, { name = "langchain-google-genai", marker = "extra == 'google-genai'" },
{ name = "langchain-google-vertexai", marker = "extra == 'google-vertexai'" },
{ name = "langchain-groq", marker = "extra == 'groq'" }, { name = "langchain-groq", marker = "extra == 'groq'" },
{ name = "langchain-huggingface", marker = "extra == 'huggingface'" }, { name = "langchain-huggingface", marker = "extra == 'huggingface'" },
{ name = "langchain-mistralai", marker = "extra == 'mistralai'" }, { name = "langchain-mistralai", marker = "extra == 'mistralai'" },
@@ -2276,14 +2272,13 @@ requires-dist = [
{ name = "langchain-perplexity", marker = "extra == 'perplexity'" }, { name = "langchain-perplexity", marker = "extra == 'perplexity'" },
{ name = "langchain-text-splitters", editable = "libs/text-splitters" }, { name = "langchain-text-splitters", editable = "libs/text-splitters" },
{ name = "langchain-together", marker = "extra == 'together'" }, { name = "langchain-together", marker = "extra == 'together'" },
{ name = "langchain-xai", marker = "extra == 'xai'" },
{ name = "langsmith", specifier = ">=0.1.17" }, { name = "langsmith", specifier = ">=0.1.17" },
{ name = "pydantic", specifier = ">=2.7.4,<3.0.0" }, { name = "pydantic", specifier = ">=2.7.4,<3.0.0" },
{ name = "pyyaml", specifier = ">=5.3" }, { name = "pyyaml", specifier = ">=5.3" },
{ name = "requests", specifier = ">=2,<3" }, { name = "requests", specifier = ">=2,<3" },
{ name = "sqlalchemy", specifier = ">=1.4,<3" }, { name = "sqlalchemy", specifier = ">=1.4,<3" },
] ]
provides-extras = ["community", "anthropic", "openai", "azure-ai", "cohere", "google-vertexai", "google-genai", "fireworks", "ollama", "together", "mistralai", "huggingface", "groq", "aws", "deepseek", "xai", "perplexity"] provides-extras = ["community", "anthropic", "openai", "google-genai", "fireworks", "ollama", "together", "mistralai", "huggingface", "groq", "deepseek", "perplexity"]
[package.metadata.requires-dev] [package.metadata.requires-dev]
codespell = [{ name = "codespell", specifier = ">=2.2.0,<3.0.0" }] codespell = [{ name = "codespell", specifier = ">=2.2.0,<3.0.0" }]
@@ -2483,7 +2478,7 @@ wheels = [
[[package]] [[package]]
name = "langchain-core" name = "langchain-core"
version = "0.3.72" version = "0.3.74"
source = { editable = "libs/core" } source = { editable = "libs/core" }
dependencies = [ dependencies = [
{ name = "jsonpatch" }, { name = "jsonpatch" },
@@ -2534,7 +2529,7 @@ test = [
test-integration = [] test-integration = []
typing = [ typing = [
{ name = "langchain-text-splitters", directory = "libs/text-splitters" }, { name = "langchain-text-splitters", directory = "libs/text-splitters" },
{ name = "mypy", specifier = ">=1.15,<1.16" }, { name = "mypy", specifier = ">=1.17.1,<1.18" },
{ name = "types-pyyaml", specifier = ">=6.0.12.2,<7.0.0.0" }, { name = "types-pyyaml", specifier = ">=6.0.12.2,<7.0.0.0" },
{ name = "types-requests", specifier = ">=2.28.11.5,<3.0.0.0" }, { name = "types-requests", specifier = ">=2.28.11.5,<3.0.0.0" },
] ]
@@ -2618,7 +2613,7 @@ dependencies = [
[[package]] [[package]]
name = "langchain-groq" name = "langchain-groq"
version = "0.3.6" version = "0.3.7"
source = { editable = "libs/partners/groq" } source = { editable = "libs/partners/groq" }
dependencies = [ dependencies = [
{ name = "groq" }, { name = "groq" },
@@ -2627,7 +2622,7 @@ dependencies = [
[package.metadata] [package.metadata]
requires-dist = [ requires-dist = [
{ name = "groq", specifier = ">=0.29.0,<1" }, { name = "groq", specifier = ">=0.30.0,<1" },
{ name = "langchain-core", editable = "libs/core" }, { name = "langchain-core", editable = "libs/core" },
] ]
@@ -2819,7 +2814,7 @@ typing = []
[[package]] [[package]]
name = "langchain-openai" name = "langchain-openai"
version = "0.3.28" version = "0.3.29"
source = { editable = "libs/partners/openai" } source = { editable = "libs/partners/openai" }
dependencies = [ dependencies = [
{ name = "langchain-core" }, { name = "langchain-core" },
@@ -2889,10 +2884,14 @@ version = "0.3.9"
source = { editable = "libs/text-splitters" } source = { editable = "libs/text-splitters" }
dependencies = [ dependencies = [
{ name = "langchain-core" }, { name = "langchain-core" },
{ name = "pip" },
] ]
[package.metadata] [package.metadata]
requires-dist = [{ name = "langchain-core", editable = "libs/core" }] requires-dist = [
{ name = "langchain-core", editable = "libs/core" },
{ name = "pip", specifier = ">=25.2" },
]
[package.metadata.requires-dev] [package.metadata.requires-dev]
dev = [ dev = [
@@ -2901,7 +2900,7 @@ dev = [
] ]
lint = [ lint = [
{ name = "langchain-core", editable = "libs/core" }, { name = "langchain-core", editable = "libs/core" },
{ name = "ruff", specifier = ">=0.12.2,<0.13" }, { name = "ruff", specifier = ">=0.12.8,<0.13" },
] ]
test = [ test = [
{ name = "freezegun", specifier = ">=1.2.2,<2.0.0" }, { name = "freezegun", specifier = ">=1.2.2,<2.0.0" },
@@ -2918,6 +2917,7 @@ test-integration = [
{ name = "sentence-transformers", specifier = ">=3.0.1" }, { name = "sentence-transformers", specifier = ">=3.0.1" },
{ name = "spacy", specifier = ">=3.8.7,<4.0.0" }, { name = "spacy", specifier = ">=3.8.7,<4.0.0" },
{ name = "thinc", specifier = ">=8.3.6,<9.0.0" }, { name = "thinc", specifier = ">=8.3.6,<9.0.0" },
{ name = "tiktoken", specifier = ">=0.8.0,<1.0.0" },
{ name = "transformers", specifier = ">=4.51.3,<5.0.0" }, { name = "transformers", specifier = ">=4.51.3,<5.0.0" },
] ]
typing = [ typing = [
@@ -4438,6 +4438,15 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/41/67/936f9814bdd74b2dfd4822f1f7725ab5d8ff4103919a1664eb4874c58b2f/pillow-11.1.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:4637b88343166249fe8aa94e7c4a62a180c4b3898283bb5d3d2fd5fe10d8e4e0", size = 2626353, upload-time = "2025-01-02T08:13:52.725Z" }, { url = "https://files.pythonhosted.org/packages/41/67/936f9814bdd74b2dfd4822f1f7725ab5d8ff4103919a1664eb4874c58b2f/pillow-11.1.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:4637b88343166249fe8aa94e7c4a62a180c4b3898283bb5d3d2fd5fe10d8e4e0", size = 2626353, upload-time = "2025-01-02T08:13:52.725Z" },
] ]
[[package]]
name = "pip"
version = "25.2"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/20/16/650289cd3f43d5a2fadfd98c68bd1e1e7f2550a1a5326768cddfbcedb2c5/pip-25.2.tar.gz", hash = "sha256:578283f006390f85bb6282dffb876454593d637f5d1be494b5202ce4877e71f2", size = 1840021, upload-time = "2025-07-30T21:50:15.401Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/b7/3f/945ef7ab14dc4f9d7f40288d2df998d1837ee0888ec3659c813487572faa/pip-25.2-py3-none-any.whl", hash = "sha256:6d67a2b4e7f14d8b31b8b52648866fa717f45a1eb70e83002f4331d07e953717", size = 1752557, upload-time = "2025-07-30T21:50:13.323Z" },
]
[[package]] [[package]]
name = "platformdirs" name = "platformdirs"
version = "4.3.6" version = "4.3.6"