跳转到内容

单元测试

langchain_tests.unit_tests

LangChain 组件的单元测试。

ChatModelUnitTests

基类: ChatModelTests

聊天模型单元测试的基类。

测试子类必须实现 chat_model_classchat_model_params 属性,以指定要测试的模型及其初始化参数。

from typing import Type

from langchain_tests.unit_tests import ChatModelUnitTests
from my_package.chat_models import MyChatModel


class TestMyChatModelUnit(ChatModelUnitTests):
    @property
    def chat_model_class(self) -> Type[MyChatModel]:
        # Return the chat model class to test here
        return MyChatModel

    @property
    def chat_model_params(self) -> dict:
        # Return initialization parameters for the model.
        return {"model": "model-001", "temperature": 0}

注意

各个测试方法的 API 参考包含故障排除提示。

测试子类 必须 实现以下两个属性

chat_model_class:要测试的聊天模型类,例如 ChatParrotLink

@property
def chat_model_class(self) -> Type[ChatParrotLink]:
    return ChatParrotLink

chat_model_params:聊天模型的初始化参数。

@property
def chat_model_params(self) -> dict:
    return {"model": "bird-brain-001", "temperature": 0}

此外,测试子类可以通过选择性地覆盖以下属性来控制测试的功能(例如工具调用或多模态)。展开查看详情

has_tool_calling

布尔属性,指示聊天模型是否支持工具调用。

默认情况下,这取决于聊天模型的 bind_tools 方法是否被重写。通常不需要在测试类上重写它。

重写示例

@property
def has_tool_calling(self) -> bool:
    return True
tool_choice_value

在测试中使用时,用于工具选择的值。

警告

自 0.3.15 版本起已弃用。此属性将在 0.3.20 版本中移除。如果模型不支持强制工具调用,请将 has_tool_choice 属性重写为返回 False。否则,模型应接受 tool_choice 中的 'any' 或工具名称的值。

@property
def tool_choice_value(self) -> str | None:
    return "any"
has_tool_choice

布尔属性,指示聊天模型是否支持通过 tool_choice 参数强制进行工具调用。

默认情况下,这取决于该参数是否包含在相应 bind_tools 方法的签名中。

如果为 True,此功能的最低要求是 tool_choice="any" 将强制进行工具调用,而 tool_choice= 将强制调用特定工具。

重写示例

@property
def has_tool_choice(self) -> bool:
    return False
has_structured_output

布尔属性,指示聊天模型是否支持结构化输出。

默认情况下,这取决于聊天模型是否重写了 with_structured_outputbind_tools 方法。如果打算使用基础实现,则应重写此方法。

请参阅:https://docs.langchain.org.cn/oss/python/langchain/structured-output

@property
def has_structured_output(self) -> bool:
    return True
structured_output_kwargs

字典属性,可用于为 with_structured_output 指定额外的关键字参数。对测试不同的模型很有用。

@property
def structured_output_kwargs(self) -> dict:
    return {"method": "function_calling"}
supports_json_mode

布尔属性,指示聊天模型是否在 with_structured_output 中支持 JSON 模式。

请参阅:https://docs.langchain.org.cn/oss/python/langchain/structured-output

@property
def supports_json_mode(self) -> bool:
    return True
supports_image_inputs

布尔属性,指示聊天模型是否支持图像输入。

默认为 False

如果设置为 True,聊天模型将使用 LangChain ImageContentBlock 格式进行测试

{
    "type": "image",
    "base64": "<base64 image data>",
    "mime_type": "image/jpeg",  # or appropriate MIME type
}

除了 OpenAI Chat Completions 的 image_url

{
    "type": "image_url",
    "image_url": {"url": f"data:image/jpeg;base64,{image_data}"},
}

请参阅 https://docs.langchain.org.cn/oss/python/langchain/models#multimodal

@property
def supports_image_inputs(self) -> bool:
    return True
supports_image_urls

布尔属性,指示聊天模型是否支持来自 URL 的图像输入。

默认为 False

如果设置为 True,聊天模型将使用以下形式的内容块进行测试。

{
    "type": "image",
    "url": "https://...",
}

请参阅 https://docs.langchain.org.cn/oss/python/langchain/models#multimodal

@property
def supports_image_urls(self) -> bool:
    return True
supports_pdf_inputs

布尔属性,指示聊天模型是否支持 PDF 输入。

默认为 False

如果设置为 True,聊天模型将使用 LangChain FileContentBlock 格式进行测试

{
    "type": "file",
    "base64": "<base64 file data>",
    "mime_type": "application/pdf",
}

请参阅 https://docs.langchain.org.cn/oss/python/langchain/models#multimodal

@property
def supports_pdf_inputs(self) -> bool:
    return True
supports_audio_inputs

布尔属性,指示聊天模型是否支持音频输入。

默认为 False

如果设置为 True,聊天模型将使用 LangChain AudioContentBlock 格式进行测试

{
    "type": "audio",
    "base64": "<base64 audio data>",
    "mime_type": "audio/wav",  # or appropriate MIME type
}

请参阅 https://docs.langchain.org.cn/oss/python/langchain/models#multimodal

@property
def supports_audio_inputs(self) -> bool:
    return True
supports_video_inputs

布尔属性,指示聊天模型是否支持图像输入。

默认为 False。目前没有为此功能编写任何测试。

returns_usage_metadata

布尔属性,指示聊天模型是否在调用和流式响应中返回使用元数据。

默认为 True

usage_metadataAIMessage 对象上的一个可选字典属性,用于跟踪输入和输出令牌。 查看更多

@property
def returns_usage_metadata(self) -> bool:
    return False

支持 usage_metadata 的模型也应在 AIMessageresponse_metadata 中返回底层模型的名称。

supports_anthropic_inputs

布尔属性,指示聊天模型是否支持 Anthropic 风格的输入。

这些输入可能包含“工具使用”和“工具结果”内容块,例如:

[
    {"type": "text", "text": "Hmm let me think about that"},
    {
        "type": "tool_use",
        "input": {"fav_color": "green"},
        "id": "foo",
        "name": "color_picker",
    },
]

如果设置为 True,聊天模型将使用这种形式的内容块进行测试。

@property
def supports_anthropic_inputs(self) -> bool:
    return False
supports_image_tool_message

布尔属性,指示聊天模型是否支持包含图像内容的 ToolMessage 对象,例如:

ToolMessage(
    content=[
        {
            "type": "image_url",
            "image_url": {"url": f"data:image/jpeg;base64,{image_data}"},
        },
    ],
    tool_call_id="1",
    name="random_image",
)

(OpenAI Chat Completions 格式),以及 LangChain 的 ImageContentBlock 格式

ToolMessage(
    content=[
        {
            "type": "image",
            "base64": image_data,
            "mime_type": "image/jpeg",
        },
    ],
    tool_call_id="1",
    name="random_image",
)

(标准格式)。

如果设置为 True,聊天模型将使用包含这种形式的 ToolMessage 对象的消息序列进行测试。

@property
def supports_image_tool_message(self) -> bool:
    return False
supports_pdf_tool_message

布尔属性,指示聊天模型是否支持包含 PDF 内容的 ToolMessage 对象,即,

ToolMessage(
    content=[
        {
            "type": "file",
            "base64": pdf_data,
            "mime_type": "application/pdf",
        },
    ],
    tool_call_id="1",
    name="random_pdf",
)

使用 LangChain 的 FileContentBlock 格式。

如果设置为 True,聊天模型将使用包含这种形式的 ToolMessage 对象的消息序列进行测试。

@property
def supports_pdf_tool_message(self) -> bool:
    return False
supported_usage_metadata_details

控制在 invokestream 中发出的使用元数据细节的属性。

usage_metadataAIMessage 对象上的一个可选字典属性,用于跟踪输入和输出令牌。 查看更多

它包含可选的键 input_token_detailsoutput_token_details,可以跟踪与特殊类型令牌(如缓存、音频或推理令牌)相关的使用细节。

仅当提供这些细节时才需要重写。

enable_vcr_tests

控制是否启用依赖 VCR 缓存 HTTP 调用的特定测试(例如基准测试)的属性。

要启用这些测试,请按照以下步骤操作

  1. enable_vcr_tests 属性重写为返回 True

    @property
    def enable_vcr_tests(self) -> bool:
        return True
    
  2. 配置 VCR 以从磁带(cassettes)中排除敏感的头信息和其他信息。

    警告

    VCR 默认会在磁带中记录身份验证头和其他敏感信息。请阅读下文了解如何配置磁带中记录的信息。

    要向 VCR 添加配置,请在 tests/ 目录中添加一个 conftest.py 文件,并在其中实现 vcr_config fixture。

    langchain-tests 从 VCR 磁带中排除了 'authorization''x-api-key''api-key' 这些头信息。要应用此配置,您需要如下所示添加 conftest.py。您还可以排除其他头信息,覆盖默认排除项,或对 VCR 配置应用其他自定义。请参见下面的示例

    tests/conftest.py
    import pytest
    from langchain_tests.conftest import (
        _base_vcr_config as _base_vcr_config,
    )
    
    _EXTRA_HEADERS = [
        # Specify additional headers to redact
        ("user-agent", "PLACEHOLDER"),
    ]
    
    
    def remove_response_headers(response: dict) -> dict:
        # If desired, remove or modify headers in the response.
        response["headers"] = {}
        return response
    
    
    @pytest.fixture(scope="session")
    def vcr_config(_base_vcr_config: dict) -> dict:  # noqa: F811
        """Extend the default configuration from langchain_tests."""
        config = _base_vcr_config.copy()
        config.setdefault("filter_headers", []).extend(_EXTRA_HEADERS)
        config["before_record_response"] = remove_response_headers
    
        return config
    
    压缩磁带

    langchain-tests 包含一个自定义的 VCR 序列化器,它使用 gzip 压缩磁带。要使用它,请将 yaml.gz 序列化器注册到您的 VCR fixture 中,并在配置中启用此序列化器。请参见下面的示例

    tests/conftest.py
    import pytest
    from langchain_tests.conftest import (
        CustomPersister,
        CustomSerializer,
    )
    from langchain_tests.conftest import (
        _base_vcr_config as _base_vcr_config,
    )
    from vcr import VCR
    
    _EXTRA_HEADERS = [
        # Specify additional headers to redact
        ("user-agent", "PLACEHOLDER"),
    ]
    
    
    def remove_response_headers(response: dict) -> dict:
        # If desired, remove or modify headers in the response.
        response["headers"] = {}
        return response
    
    
    @pytest.fixture(scope="session")
    def vcr_config(_base_vcr_config: dict) -> dict:  # noqa: F811
        """Extend the default configuration from langchain_tests."""
        config = _base_vcr_config.copy()
        config.setdefault("filter_headers", []).extend(_EXTRA_HEADERS)
        config["before_record_response"] = remove_response_headers
        # New: enable serializer and set file extension
        config["serializer"] = "yaml.gz"
        config["path_transformer"] = VCR.ensure_suffix(".yaml.gz")
    
        return config
    
    
    def pytest_recording_configure(config: dict, vcr: VCR) -> None:
        vcr.register_persister(CustomPersister())
        vcr.register_serializer("yaml.gz", CustomSerializer())
    

    您可以使用以下命令检查压缩磁带的内容(例如,确保没有记录敏感信息):

    gunzip -k /path/to/tests/cassettes/TestClass_test.yaml.gz
    

    或使用序列化器

    from langchain_tests.conftest import (
        CustomPersister,
        CustomSerializer,
    )
    
    cassette_path = "/path/to/tests/cassettes/TestClass_test.yaml.gz"
    requests, responses = CustomPersister().load_cassette(
        path, CustomSerializer()
    )
    
  3. 运行测试以生成 VCR 磁带。

    示例

    uv run python -m pytest tests/integration_tests/test_chat_models.py::TestMyModel::test_stream_time
    

    这将在 tests/integration_tests/cassettes/ 目录下为该测试生成一个 VCR 磁带。

    警告

    您应该检查生成的磁带,以确保其中不包含敏感信息。如果包含,您可以修改 vcr_config fixture 以排除头信息或在记录响应之前对其进行修改。

    然后,您可以将磁带提交到您的代码仓库。后续的测试运行将使用磁带而不是进行 HTTP 调用。

测试从环境变量初始化

一些单元测试可能需要测试从环境变量进行初始化。可以通过重写 init_from_env_params 属性来启用这些测试(见下文)。

init_from_env_params

此属性在单元测试中用于测试从环境变量进行初始化。它应该返回一个包含三个字典的元组,分别指定环境变量、额外的初始化参数以及要检查的预期实例属性。

默认为空字典。如果未重写,则跳过此测试。

示例

@property
def init_from_env_params(self) -> Tuple[dict, dict, dict]:
    return (
        {
            "MY_API_KEY": "api_key",
        },
        {
            "model": "bird-brain-001",
        },
        {
            "my_api_key": "api_key",
        },
    )

方法 描述
test_no_overrides_DO_NOT_OVERRIDE

测试没有标准测试被重写。

model

模型 fixture。

my_adder_tool

加法器工具 fixture。

test_init

测试模型初始化。所有集成都应该通过此测试。

test_init_from_env

测试从环境变量进行初始化。

test_init_streaming

测试模型是否可以用 streaming=True 初始化。

test_bind_tool_pydantic

使用 Pydantic 模型测试绑定工具。

test_with_structured_output

测试 with_structured_output 方法。

test_standard_params

测试模型是否正确生成标准参数。

test_serdes

测试模型的序列化和反序列化。

test_init_time

测试聊天模型的初始化时间。

chat_model_class abstractmethod property

chat_model_class: type[BaseChatModel]

要测试的聊天模型类,例如 ChatParrotLink

chat_model_params property

chat_model_params: dict

聊天模型的初始化参数。

has_tool_calling property

has_tool_calling: bool

模型是否支持工具调用。

tool_choice_value property

tool_choice_value: str | None

(None 或 str)在测试中用于工具选择的值。

has_tool_choice property

has_tool_choice: bool

模型是否支持工具调用。

has_structured_output property

has_structured_output: bool

聊天模型是否支持结构化输出。

structured_output_kwargs property

structured_output_kwargs: dict

如果指定,则为 with_structured_output 提供额外的关键字参数。

supports_json_mode property

supports_json_mode: bool

聊天模型是否支持 JSON 模式。

supports_image_inputs property

supports_image_inputs: bool

支持图像输入。

聊天模型是否支持图像输入,默认为 False

supports_image_urls property

supports_image_urls: bool

支持来自 URL 的图像输入。

聊天模型是否支持来自 URL 的图像输入,默认为 False

supports_pdf_inputs property

supports_pdf_inputs: bool

聊天模型是否支持 PDF 输入,默认为 False

supports_audio_inputs property

supports_audio_inputs: bool

支持音频输入。

聊天模型是否支持音频输入,默认为 False

supports_video_inputs property

supports_video_inputs: bool

支持视频输入。

聊天模型是否支持视频输入,默认为 False

目前没有为此功能编写任何测试。

returns_usage_metadata property

returns_usage_metadata: bool

返回使用元数据。

聊天模型是否在调用和流式响应中返回使用元数据。

supports_anthropic_inputs property

supports_anthropic_inputs: bool

聊天模型是否支持 Anthropic 风格的输入。

supports_image_tool_message property

supports_image_tool_message: bool

支持图像 ToolMessage 对象。

聊天模型是否支持包含图像内容的 ToolMessage 对象。

supports_pdf_tool_message property

supports_pdf_tool_message: bool

支持 PDF ToolMessage 对象。

聊天模型是否支持包含 PDF 内容的 ToolMessage 对象。

enable_vcr_tests property

enable_vcr_tests: bool

是否为聊天模型启用 VCR 测试。

警告

有关更多信息,请参阅 上面 <ChatModelTests>enable_vcr_tests 下拉菜单。

supported_usage_metadata_details property

supported_usage_metadata_details: dict[
    Literal["invoke", "stream"],
    list[
        Literal[
            "audio_input",
            "audio_output",
            "reasoning_output",
            "cache_read_input",
            "cache_creation_input",
        ]
    ],
]

支持的使用元数据详情。

在 invoke 和 stream 中会发出哪些使用元数据详情。只有当模型返回这些详情时才需要重写。

standard_chat_model_params property

standard_chat_model_params: dict

标准聊天模型参数。

init_from_env_params property

init_from_env_params: tuple[dict, dict, dict]

从环境变量初始化参数。

用于测试从环境变量初始化的环境变量、额外初始化参数和预期的实例属性。

test_no_overrides_DO_NOT_OVERRIDE

test_no_overrides_DO_NOT_OVERRIDE() -> None

测试没有标准测试被重写。

model

model(request: Any) -> BaseChatModel

模型 fixture。

my_adder_tool

my_adder_tool() -> BaseTool

加法器工具 fixture。

test_init

test_init() -> None

测试模型初始化。所有集成都应该通过此测试。

故障排除

如果此测试失败,请确保

  1. chat_model_params 已指定,并且模型可以从这些参数初始化;
  2. 模型支持标准参数

test_init_from_env

test_init_from_env() -> None

测试从环境变量进行初始化。

依赖于 init_from_env_params 属性。如果该属性未设置,则跳过测试。

故障排除

如果此测试失败,请确保 init_from_env_params 指定正确,并且在初始化过程中从环境变量正确设置了模型参数。

test_init_streaming

test_init_streaming() -> None

测试模型是否可以用 streaming=True 初始化。

这是为了向后兼容。

故障排除

如果此测试失败,请确保模型可以使用布尔值 streaming 参数进行初始化。

test_bind_tool_pydantic

test_bind_tool_pydantic(model: BaseChatModel, my_adder_tool: BaseTool) -> None

使用 Pydantic 模型测试绑定工具。

测试聊天模型是否正确处理传递到 bind_tools 的 Pydantic 模型。如果测试类上的 has_tool_calling 属性为 False,则跳过测试。

故障排除

如果此测试失败,请确保模型的 bind_tools 方法能正确处理 Pydantic V2 模型。langchain_core 实现了一个实用函数,可以适应大多数格式:https://python.langchain.ac.cn/api_reference/core/utils/langchain_core.utils.function_calling.convert_to_openai_tool.html

请在此处查看 bind_tools 的实现示例:https://python.langchain.ac.cn/api_reference/_modules/langchain_openai/chat_models/base.html#BaseChatOpenAI.bind_tools

test_with_structured_output

test_with_structured_output(model: BaseChatModel, schema: Any) -> None

测试 with_structured_output 方法。

如果测试类上的 has_structured_output 属性为 False,则跳过测试。

故障排除

如果此测试失败,请确保模型的 bind_tools 方法能正确处理 Pydantic V2 模型。langchain_core 实现了一个实用函数,可以适应大多数格式:https://python.langchain.ac.cn/api_reference/core/utils/langchain_core.utils.function_calling.convert_to_openai_tool.html

请在此处查看 with_structured_output 的实现示例:https://python.langchain.ac.cn/api_reference/_modules/langchain_openai/chat_models/base.html#BaseChatOpenAI.with_structured_output

test_standard_params

test_standard_params(model: BaseChatModel) -> None

测试模型是否正确生成标准参数。

这些用于追踪目的。

故障排除

如果此测试失败,请检查模型是否支持标准参数

同时检查模型类的命名是否符合惯例(例如,ChatProviderName)。

test_serdes

test_serdes(model: BaseChatModel, snapshot: SnapshotAssertion) -> None

测试模型的序列化和反序列化。

如果聊天模型类上的 is_lc_serializable 属性未被重写为返回 True,则跳过此测试。

故障排除

如果此测试失败,请检查测试类上的 init_from_env_params 属性是否设置正确。

test_init_time

test_init_time(benchmark: BenchmarkFixture) -> None

测试聊天模型的初始化时间。

如果此测试失败,请检查我们是否在模型的初始化过程中引入了不必要的开销。

EmbeddingsUnitTests

基类:EmbeddingsTests

嵌入模型单元测试的基类。

测试子类必须实现 embeddings_class 属性来指定要测试的嵌入模型。您也可以重写 embedding_model_params 属性来指定初始化参数。

from typing import Type

from langchain_tests.unit_tests import EmbeddingsUnitTests
from my_package.embeddings import MyEmbeddingsModel


class TestMyEmbeddingsModelUnit(EmbeddingsUnitTests):
    @property
    def embeddings_class(self) -> Type[MyEmbeddingsModel]:
        # Return the embeddings model class to test here
        return MyEmbeddingsModel

    @property
    def embedding_model_params(self) -> dict:
        # Return initialization parameters for the model.
        return {"model": "model-001"}

注意

各个测试方法的 API 参考包含故障排除提示。

从环境变量进行初始化测试 重写 init_from_env_params 属性将启用从环境变量进行初始化的额外测试。详见下文。

??? note "`init_from_env_params`"

    This property is used in unit tests to test initialization from
    environment variables. It should return a tuple of three dictionaries
    that specify the environment variables, additional initialization args,
    and expected instance attributes to check.

    Defaults to empty dicts. If not overridden, the test is skipped.

    ```python
    @property
    def init_from_env_params(self) -> Tuple[dict, dict, dict]:
        return (
            {
                "MY_API_KEY": "api_key",
            },
            {
                "model": "model-001",
            },
            {
                "my_api_key": "api_key",
            },
        )
    ```
方法 描述
test_no_overrides_DO_NOT_OVERRIDE

测试没有标准测试被重写。

model

嵌入模型 fixture。

test_init

测试模型初始化。

test_init_from_env

测试从环境变量进行初始化。

embeddings_class abstractmethod property

embeddings_class: type[Embeddings]

嵌入类。

embedding_model_params property

embedding_model_params: dict

嵌入模型参数。

init_from_env_params property

init_from_env_params: tuple[dict, dict, dict]

从环境变量初始化参数。

此属性在单元测试中用于测试从环境变量进行初始化。它应该返回一个包含三个字典的元组,分别指定环境变量、额外的初始化参数以及要检查的预期实例属性。

test_no_overrides_DO_NOT_OVERRIDE

test_no_overrides_DO_NOT_OVERRIDE() -> None

测试没有标准测试被重写。

model

model() -> Embeddings

嵌入模型 fixture。

test_init

test_init() -> None

测试模型初始化。

故障排除

如果此测试失败,请确保 embedding_model_params 已指定,并且模型可以从这些参数初始化。

test_init_from_env

test_init_from_env() -> None

测试从环境变量进行初始化。

依赖于 init_from_env_params 属性。如果该属性未设置,则跳过测试。

故障排除

如果此测试失败,请确保 init_from_env_params 指定正确,并且在初始化过程中从环境变量正确设置了模型参数。

ToolsUnitTests

基类:ToolsTests

工具单元测试的基类。

方法 描述
test_no_overrides_DO_NOT_OVERRIDE

测试没有标准测试被重写。

tool

工具 fixture。

test_init

测试初始化。

test_init_from_env

测试工具是否可以从环境变量初始化。

test_has_name

测试工具是否具有一个 name 属性以传递给聊天模型。

test_has_input_schema

测试工具是否具有输入模式。

test_input_schema_matches_invoke_params

测试提供的示例参数是否与声明的输入模式匹配。

tool_constructor abstractmethod property

tool_constructor: type[BaseTool] | BaseTool

返回要测试的工具的类或实例。

tool_constructor_params property

tool_constructor_params: dict

返回一个要传递给工具构造函数的参数字典。

tool_invoke_params_example property

tool_invoke_params_example: dict

返回一个表示示例工具调用“args”的字典。

这不应是一个 ToolCall 字典——它不应包含 {"name", "id", "args"} 这些键。

init_from_env_params property

init_from_env_params: tuple[dict, dict, dict]

从环境变量初始化参数。

返回用于从环境变量初始化的环境变量、初始化参数和预期的实例属性。

test_no_overrides_DO_NOT_OVERRIDE

test_no_overrides_DO_NOT_OVERRIDE() -> None

测试没有标准测试被重写。

tool

tool() -> BaseTool

工具 fixture。

test_init

test_init() -> None

测试初始化。

测试工具是否可以使用 tool_constructortool_constructor_params进行初始化。如果此测试失败,请检查在 tool_constructor_params 中定义的关键字参数是否有效。

test_init_from_env

test_init_from_env() -> None

测试工具是否可以从环境变量初始化。

test_has_name

test_has_name(tool: BaseTool) -> None

测试工具是否具有一个 name 属性以传递给聊天模型。

如果此测试失败,请为您的工具添加一个 name 参数。

test_has_input_schema

test_has_input_schema(tool: BaseTool) -> None

测试工具是否具有输入模式。

如果此测试失败,请为您的工具添加一个 args_schema

请参阅本指南,并查看在 CustomCalculatorTool.args_schema 属性中如何配置 CalculatorInput

test_input_schema_matches_invoke_params

test_input_schema_matches_invoke_params(tool: BaseTool) -> None

测试提供的示例参数是否与声明的输入模式匹配。

如果此测试失败,请更新 tool_invoke_params_example 属性以匹配工具的输入模式 (args_schema)。

© . This site is unofficial and not affiliated with LangChain, Inc.