mirror of
https://github.com/hwchase17/langchain.git
synced 2025-08-13 14:50:00 +00:00
x
This commit is contained in:
parent
01bf59679c
commit
254e59c2ce
@ -29,10 +29,11 @@ pip install poetry
|
|||||||
Next, come up with a name for your package. For this guide, we'll use `langchain-parrot-link`.
|
Next, come up with a name for your package. For this guide, we'll use `langchain-parrot-link`.
|
||||||
You can confirm that the name is available on PyPi by searching for it on the [PyPi website](https://pypi.org/).
|
You can confirm that the name is available on PyPi by searching for it on the [PyPi website](https://pypi.org/).
|
||||||
|
|
||||||
Next, create your new Python package with Poetry:
|
Next, create your new Python package with Poetry, and navigate into the new directory with `cd`:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
poetry new langchain-parrot-link
|
poetry new langchain-parrot-link
|
||||||
|
cd langchain-parrot-link
|
||||||
```
|
```
|
||||||
|
|
||||||
Add main dependencies using Poetry, which will add them to your `pyproject.toml` file:
|
Add main dependencies using Poetry, which will add them to your `pyproject.toml` file:
|
||||||
@ -48,10 +49,10 @@ with your published package, or just installing them separately when you run tes
|
|||||||
`langchain-tests` will provide the [standard tests](../standard_tests) we will use later.
|
`langchain-tests` will provide the [standard tests](../standard_tests) we will use later.
|
||||||
We recommended pinning these to the latest version: <img src="https://img.shields.io/pypi/v/langchain-tests" style={{position:"relative",top:4,left:3}} />
|
We recommended pinning these to the latest version: <img src="https://img.shields.io/pypi/v/langchain-tests" style={{position:"relative",top:4,left:3}} />
|
||||||
|
|
||||||
Note: Replace `{latest version}` with the latest version of `langchain-tests` below.
|
Note: Replace `<latest_version>` with the latest version of `langchain-tests` below.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
poetry add --group test pytest pytest-socket langchain-tests=={latest version}
|
poetry add --group test pytest pytest-socket langchain-tests==<latest_version>
|
||||||
```
|
```
|
||||||
|
|
||||||
You're now ready to start writing your integration package!
|
You're now ready to start writing your integration package!
|
||||||
|
@ -10,10 +10,12 @@
|
|||||||
"---\n",
|
"---\n",
|
||||||
"# How to add standard tests to an integration\n",
|
"# How to add standard tests to an integration\n",
|
||||||
"\n",
|
"\n",
|
||||||
"When creating either a custom class for yourself or a new tool to publish in a LangChain integration, it is important to add standard tests to ensure it works as expected. This guide will show you how to add standard tests to a tool, and you can **[Skip to the test templates](#standard-test-templates-per-component)** for implementing tests for each integration.\n",
|
"When creating either a custom class for yourself or to publish in a LangChain integration, it is important to add standard tests to ensure it works as expected. This guide will show you how to add standard tests to a custom chat model, and you can **[Skip to the test templates](#standard-test-templates-per-component)** for implementing tests for each integration type.\n",
|
||||||
"\n",
|
"\n",
|
||||||
"## Setup\n",
|
"## Setup\n",
|
||||||
"\n",
|
"\n",
|
||||||
|
"If you're coming from the [previous guide](../package), you have already installed these dependencies, and you can skip this section.\n",
|
||||||
|
"\n",
|
||||||
"First, let's install 2 dependencies:\n",
|
"First, let's install 2 dependencies:\n",
|
||||||
"\n",
|
"\n",
|
||||||
"- `langchain-core` will define the interfaces we want to import to define our custom tool.\n",
|
"- `langchain-core` will define the interfaces we want to import to define our custom tool.\n",
|
||||||
@ -53,29 +55,7 @@
|
|||||||
"cell_type": "markdown",
|
"cell_type": "markdown",
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"source": [
|
"source": [
|
||||||
"Let's say we're publishing a package, `langchain_parrot_link`, that exposes a\n",
|
"Let's say we're publishing a package, `langchain_parrot_link`, that exposes the chat model from the [guide on implementing the package](../package). We can add the standard tests to the package by following the steps below."
|
||||||
"tool called `ParrotMultiplyTool`:"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"cell_type": "code",
|
|
||||||
"execution_count": null,
|
|
||||||
"metadata": {},
|
|
||||||
"outputs": [],
|
|
||||||
"source": [
|
|
||||||
"# title=\"langchain_parrot_link/tools.py\"\n",
|
|
||||||
"from langchain_core.tools import BaseTool\n",
|
|
||||||
"\n",
|
|
||||||
"\n",
|
|
||||||
"class ParrotMultiplyTool(BaseTool):\n",
|
|
||||||
" name: str = \"ParrotMultiplyTool\"\n",
|
|
||||||
" description: str = (\n",
|
|
||||||
" \"Multiply two numbers like a parrot. Parrots always add \"\n",
|
|
||||||
" \"eighty for their matey.\"\n",
|
|
||||||
" )\n",
|
|
||||||
"\n",
|
|
||||||
" def _run(self, a: int, b: int) -> int:\n",
|
|
||||||
" return a * b + 80"
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -85,70 +65,33 @@
|
|||||||
"And we'll assume you've structured your package the same way as the main LangChain\n",
|
"And we'll assume you've structured your package the same way as the main LangChain\n",
|
||||||
"packages:\n",
|
"packages:\n",
|
||||||
"\n",
|
"\n",
|
||||||
"```\n",
|
"```plaintext\n",
|
||||||
"/\n",
|
"langchain-parrot-link/\n",
|
||||||
"├── langchain_parrot_link/\n",
|
"├── langchain_parrot_link/\n",
|
||||||
"│ └── tools.py\n",
|
"│ ├── __init__.py\n",
|
||||||
"└── tests/\n",
|
"│ └── chat_models.py\n",
|
||||||
" ├── unit_tests/\n",
|
"├── tests/\n",
|
||||||
" │ └── test_tools.py\n",
|
"│ ├── __init__.py\n",
|
||||||
" └── integration_tests/\n",
|
"│ └── test_chat_models.py\n",
|
||||||
" └── test_tools.py\n",
|
"├── pyproject.toml\n",
|
||||||
|
"└── README.md\n",
|
||||||
"```\n",
|
"```\n",
|
||||||
"\n",
|
"\n",
|
||||||
"## Add and configure standard tests\n",
|
"## Add and configure standard tests\n",
|
||||||
"\n",
|
"\n",
|
||||||
"There are 2 namespaces in the `langchain-tests` package: \n",
|
"There are 2 namespaces in the `langchain-tests` package: \n",
|
||||||
"\n",
|
"\n",
|
||||||
"- [unit tests](../../../concepts/testing.mdx#unit-tests) (`langchain_tests.unit_tests`): designed to be used to test the tool in isolation and without access to external services\n",
|
"- [unit tests](../../../concepts/testing.mdx#unit-tests) (`langchain_tests.unit_tests`): designed to be used to test the component in isolation and without access to external services\n",
|
||||||
"- [integration tests](../../../concepts/testing.mdx#unit-tests) (`langchain_tests.integration_tests`): designed to be used to test the tool with access to external services (in particular, the external service that the tool is designed to interact with).\n",
|
"- [integration tests](../../../concepts/testing.mdx#unit-tests) (`langchain_tests.integration_tests`): designed to be used to test the component with access to external services (in particular, the external service that the component is designed to interact with).\n",
|
||||||
"\n",
|
"\n",
|
||||||
"Both types of tests are implemented as [`pytest` class-based test suites](https://docs.pytest.org/en/7.1.x/getting-started.html#group-multiple-tests-in-a-class).\n",
|
"Both types of tests are implemented as [`pytest` class-based test suites](https://docs.pytest.org/en/7.1.x/getting-started.html#group-multiple-tests-in-a-class).\n",
|
||||||
"\n",
|
"\n",
|
||||||
"By subclassing the base classes for each type of standard test (see below), you get all of the standard tests for that type, and you\n",
|
"By subclassing the base classes for each type of standard test (see below), you get all of the standard tests for that type, and you\n",
|
||||||
"can override the properties that the test suite uses to configure the tests.\n",
|
"can override the properties that the test suite uses to configure the tests.\n",
|
||||||
"\n",
|
"\n",
|
||||||
"### Standard tools tests\n",
|
"### Standard chat model tests\n",
|
||||||
"\n",
|
"\n",
|
||||||
"Here's how you would configure the standard unit tests for the custom tool, e.g. in `tests/test_tools.py`:"
|
"Here's how you would configure the standard unit tests for the custom chat model:"
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"cell_type": "code",
|
|
||||||
"execution_count": null,
|
|
||||||
"metadata": {
|
|
||||||
"title": "tests/test_custom_tool.py"
|
|
||||||
},
|
|
||||||
"outputs": [],
|
|
||||||
"source": [
|
|
||||||
"# title=\"tests/unit_tests/test_tools.py\"\n",
|
|
||||||
"from typing import Type\n",
|
|
||||||
"\n",
|
|
||||||
"from langchain_parrot_link.tools import ParrotMultiplyTool\n",
|
|
||||||
"from langchain_tests.unit_tests import ToolsUnitTests\n",
|
|
||||||
"\n",
|
|
||||||
"\n",
|
|
||||||
"class TestParrotMultiplyToolUnit(ToolsUnitTests):\n",
|
|
||||||
" @property\n",
|
|
||||||
" def tool_constructor(self) -> Type[ParrotMultiplyTool]:\n",
|
|
||||||
" return ParrotMultiplyTool\n",
|
|
||||||
"\n",
|
|
||||||
" @property\n",
|
|
||||||
" def tool_constructor_params(self) -> dict:\n",
|
|
||||||
" # if your tool constructor instead required initialization arguments like\n",
|
|
||||||
" # `def __init__(self, some_arg: int):`, you would return those here\n",
|
|
||||||
" # as a dictionary, e.g.: `return {'some_arg': 42}`\n",
|
|
||||||
" return {}\n",
|
|
||||||
"\n",
|
|
||||||
" @property\n",
|
|
||||||
" def tool_invoke_params_example(self) -> dict:\n",
|
|
||||||
" \"\"\"\n",
|
|
||||||
" Returns a dictionary representing the \"args\" of an example tool call.\n",
|
|
||||||
"\n",
|
|
||||||
" This should NOT be a ToolCall dict - i.e. it should not\n",
|
|
||||||
" have {\"name\", \"id\", \"args\"} keys.\n",
|
|
||||||
" \"\"\"\n",
|
|
||||||
" return {\"a\": 2, \"b\": 3}"
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -157,34 +100,52 @@
|
|||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [],
|
"outputs": [],
|
||||||
"source": [
|
"source": [
|
||||||
"# title=\"tests/integration_tests/test_tools.py\"\n",
|
"# title=\"tests/unit_tests/test_chat_models.py\"\n",
|
||||||
|
"from typing import Tuple, Type\n",
|
||||||
|
"\n",
|
||||||
|
"from langchain_parrot_link.chat_models import ChatParrotLink\n",
|
||||||
|
"from langchain_tests.unit_tests import ChatModelUnitTests\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"class TestChatParrotLinkUnit(ChatModelUnitTests):\n",
|
||||||
|
" @property\n",
|
||||||
|
" def chat_model_class(self) -> Type[ChatParrotLink]:\n",
|
||||||
|
" return ChatParrotLink\n",
|
||||||
|
"\n",
|
||||||
|
" @property\n",
|
||||||
|
" def chat_model_params(self) -> dict:\n",
|
||||||
|
" return {\n",
|
||||||
|
" \"model\": \"bird-brain-001\",\n",
|
||||||
|
" \"temperature\": 0,\n",
|
||||||
|
" \"parrot_buffer_length\": 50,\n",
|
||||||
|
" }"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# title=\"tests/integration_tests/test_chat_models.py\"\n",
|
||||||
"from typing import Type\n",
|
"from typing import Type\n",
|
||||||
"\n",
|
"\n",
|
||||||
"from langchain_parrot_link.tools import ParrotMultiplyTool\n",
|
"from langchain_parrot_link.chat_models import ChatParrotLink\n",
|
||||||
"from langchain_tests.integration_tests import ToolsIntegrationTests\n",
|
"from langchain_tests.integration_tests import ChatModelIntegrationTests\n",
|
||||||
"\n",
|
"\n",
|
||||||
"\n",
|
"\n",
|
||||||
"class TestParrotMultiplyToolIntegration(ToolsIntegrationTests):\n",
|
"class TestChatParrotLinkIntegration(ChatModelIntegrationTests):\n",
|
||||||
" @property\n",
|
" @property\n",
|
||||||
" def tool_constructor(self) -> Type[ParrotMultiplyTool]:\n",
|
" def chat_model_class(self) -> Type[ChatParrotLink]:\n",
|
||||||
" return ParrotMultiplyTool\n",
|
" return ChatParrotLink\n",
|
||||||
"\n",
|
"\n",
|
||||||
" @property\n",
|
" @property\n",
|
||||||
" def tool_constructor_params(self) -> dict:\n",
|
" def chat_model_params(self) -> dict:\n",
|
||||||
" # if your tool constructor instead required initialization arguments like\n",
|
" return {\n",
|
||||||
" # `def __init__(self, some_arg: int):`, you would return those here\n",
|
" \"model\": \"bird-brain-001\",\n",
|
||||||
" # as a dictionary, e.g.: `return {'some_arg': 42}`\n",
|
" \"temperature\": 0,\n",
|
||||||
" return {}\n",
|
" \"parrot_buffer_length\": 50,\n",
|
||||||
"\n",
|
" }"
|
||||||
" @property\n",
|
|
||||||
" def tool_invoke_params_example(self) -> dict:\n",
|
|
||||||
" \"\"\"\n",
|
|
||||||
" Returns a dictionary representing the \"args\" of an example tool call.\n",
|
|
||||||
"\n",
|
|
||||||
" This should NOT be a ToolCall dict - i.e. it should not\n",
|
|
||||||
" have {\"name\", \"id\", \"args\"} keys.\n",
|
|
||||||
" \"\"\"\n",
|
|
||||||
" return {\"a\": 2, \"b\": 3}"
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -228,7 +189,8 @@
|
|||||||
"Above, we implement the **unit** and **integration** standard tests for a tool. Below are the templates for implementing the standard tests for each component:\n",
|
"Above, we implement the **unit** and **integration** standard tests for a tool. Below are the templates for implementing the standard tests for each component:\n",
|
||||||
"\n",
|
"\n",
|
||||||
"<details>\n",
|
"<details>\n",
|
||||||
" <summary>Chat Models</summary>"
|
" <summary>Chat Models</summary>\n",
|
||||||
|
" <p>Note: The standard tests for chat models are implemented in the example in the main body of this guide too.</p>"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -251,7 +213,11 @@
|
|||||||
"\n",
|
"\n",
|
||||||
" @property\n",
|
" @property\n",
|
||||||
" def chat_model_params(self) -> dict:\n",
|
" def chat_model_params(self) -> dict:\n",
|
||||||
" return {\"model\": \"bird-brain-001\", \"temperature\": 0}"
|
" return {\n",
|
||||||
|
" \"model\": \"bird-brain-001\",\n",
|
||||||
|
" \"temperature\": 0,\n",
|
||||||
|
" \"parrot_buffer_length\": 50,\n",
|
||||||
|
" }"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -274,7 +240,11 @@
|
|||||||
"\n",
|
"\n",
|
||||||
" @property\n",
|
" @property\n",
|
||||||
" def chat_model_params(self) -> dict:\n",
|
" def chat_model_params(self) -> dict:\n",
|
||||||
" return {\"model\": \"bird-brain-001\", \"temperature\": 0}"
|
" return {\n",
|
||||||
|
" \"model\": \"bird-brain-001\",\n",
|
||||||
|
" \"temperature\": 0,\n",
|
||||||
|
" \"parrot_buffer_length\": 50,\n",
|
||||||
|
" }"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -338,8 +308,7 @@
|
|||||||
"source": [
|
"source": [
|
||||||
"</details>\n",
|
"</details>\n",
|
||||||
"<details>\n",
|
"<details>\n",
|
||||||
" <summary>Tools/Toolkits</summary>\n",
|
" <summary>Tools/Toolkits</summary>"
|
||||||
" <p>Note: The standard tests for tools/toolkits are implemented in the example in the main body of this guide too.</p>"
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user