Add comprehensive documentation and templates for LangChain skill development

- Introduced a new reference document for streaming output issues, detailing the differences between streaming APIs and providing solutions for common problems.
- Created a structured output issues reference, outlining the use of `with_structured_output`, `response_format`, and schema enforcement strategies.
- Added a user query convention guide to standardize structured questions for skill authors, including block types for queries and data gathering.
- Implemented a template for a chat model, encapsulating API key management, request payload construction, and response handling.
- Established a symlink for the LangChain dev guide in the Claude skills directory for easier access.
- Initialized a skills lock file to manage dependencies and versions for the LangChain dev guide.
This commit is contained in:
yuxuanhui
2026-09-07 16:19:11 +08:00
parent 3cd280d068
commit 7797ff88df
16 changed files with 2981 additions and 0 deletions
@@ -0,0 +1,99 @@
# CN Model Integration Guide
Help developers write LangChain integration classes for a specified Chinese model (e.g., Qwen, GLM, DeepSeek, Moonshot) using the OpenAI-compatible interface.
> [!CAUTION]
> **Never read, write, or access user configuration files such as `.env`, `.env.local`, `credentials.json`, or any other files that may contain secrets or sensitive information.** API Keys and other credentials must always be filled in by the user themselves — do not peek into or modify these files under any circumstances.
## Step 1: Gather Information
Confirm the following details with the user. If the user does not explicitly provide any of these, use reasonable defaults from the provider's documentation.
<!-- gather
prompt: "Confirm the following details for the model integration:"
fields:
- name: model_name
question: "Model name (lowercase, used for directory and class names)"
example: "qwen"
required: true
- name: api_base
question: "API base URL (OpenAI-compatible endpoint)"
example: "https://dashscope.aliyuncs.com/compatible-mode/v1"
required: true
- name: api_key_env
question: "API key environment variable name"
example: "QWEN_API_KEY"
required: true
fallback: "Use reasonable defaults from the provider's documentation."
-->
1. **Model Name** — lowercase, e.g., `qwen`, `glm`, `deepseek`. Used for directory names, class names, and `_llm_type`.
2. **API Base URL** — the model's OpenAI-compatible endpoint URL.
3. **API Key Environment Variable Name** — e.g., `QWEN_API_KEY`.
Additionally, inspect the project directory structure to determine the Python package manager (`uv.lock` → uv, `poetry.lock` → poetry, `requirements.txt` → pip, etc.).
## Step 2: Create Directory and Files
1. Create a top-level directory `<models_dir>/`.
2. Create a model subdirectory `<models_dir>/<model_name>/` with `model_name` in lowercase.
3. Keep the top-level `<models_dir>/__init__.py` empty.
```
<models_dir>/
├── __init__.py # empty
├── <model_name>/
│ ├── __init__.py
│ └── chat_model.py
└── ...
```
## Step 3: Check if DeepSeek
**If the model is DeepSeek**, install `langchain-deepseek` and use `ChatDeepSeek` directly. Skip all subsequent steps.
**If the model is another provider**, continue with the steps below.
## Step 4: Copy the Template
1. Check whether `langchain-openai` is installed; install it if not.
2. Copy the template from [../../template/chat_model.py](../../template/chat_model.py) into the target subdirectory.
3. Create `__init__.py`: `from .chat_model import <CHAT_CLASS_NAME>`
## Step 5: Replace Placeholders
Use grep to list all placeholders, then replace each one with the actual value:
| Placeholder | Description | Example (Qwen) |
|-------------|-------------|----------------|
| `ChatModel` | Class name | `ChatQwen` |
| `PROVIDER_API_KEY` | API Key env var name | `QWEN_API_KEY` |
| `PROVIDER_API_BASE` | API Base env var name | `QWEN_API_BASE` |
| `PROVIDER_API_BASE_URL` | Default API URL | `https://dashscope.aliyuncs.com/compatible-mode/v1` |
| `chat-provider` | Model identifier for `_llm_type` | `chat-qwen` |
| `provider-name` | Value for `response_metadata["model_provider"]` | `dashscope` |
| `Provider` | Provider display name for error messages | `Qwen` |
Each placeholder is a standalone, complete token — simply do a global find-and-replace. Apply replacements in both `chat_model.py` and `__init__.py`.
## Step 6: Configure Model Profile (Optional)
Use `langchain-model-profiles` to download profile information for the model provider. `<provider_name>` is the provider name; try a few likely candidates.
1. Check whether `langchain-model-profiles` is installed; install it if not.
2. Run the download command:
```bash
langchain-profiles refresh --provider <provider_name> --data-dir ./<models_dir>/<model_name>/data
```
On success, a `data/_profiles.py` file is generated under the model directory, which is used by `_get_default_model_profile` in the template. If you cannot find the corresponding provider after several attempts, skip this step.
## Step 7: Write Integration Tests
After the model class is complete, you must write integration tests. See the detailed guide at [integration-tests.md](integration-tests.md).
> [!IMPORTANT]
> **Before running integration tests, you must remind the user to edit the `.env` file themselves and fill in the required API Key and other environment variables.**
>
> When running tests, you will likely encounter common setup issues (package not importable, async test mode, etc.). Refer to the "Common Issues" section at the end of [integration-tests.md](integration-tests.md) for fixes.
@@ -0,0 +1,117 @@
# Chat Model Integration Tests
After writing `chat_model.py`, you must write integration tests to verify the model class works correctly.
## Test Framework
Use `ChatModelIntegrationTests` from `langchain_tests` as the base class, and run tests with pytest.
Install dependencies:
```bash
pip install langchain-tests pytest python-dotenv
```
## Test File Structure
Place test files following standard unit test directory conventions:
```
src/<models_dir>/<model_name>/
├── __init__.py
├── chat_model.py
└── ...
tests/
└── test_chat_<model_name>.py
```
## Standard Test Class
For a new provider (e.g., Qwen, GLM), create a test class that inherits from `ChatModelIntegrationTests` and provides the following properties:
```python
from __future__ import annotations
import pytest
from dotenv import load_dotenv
from langchain_core.language_models import BaseChatModel
from langchain_tests.integration_tests import ChatModelIntegrationTests
from models.qwen.chat_model import ChatQwen # replace with the actual import path
load_dotenv()
class TestChatQwen(ChatModelIntegrationTests):
@property
def chat_model_class(self) -> type[BaseChatModel]:
return ChatQwen
@property
def chat_model_params(self) -> dict:
return {
"model": "qwen-plus",
"temperature": 0,
}
```
### Required Properties
| Property | Description |
|----------|-------------|
| `chat_model_class` | Returns the chat model class under test. |
| `chat_model_params` | Parameters for creating an instance. Must include `model`; `temperature: 0` is recommended for deterministic results. |
## Running Tests
```bash
# Run tests for a single model
pytest tests/test_chat_<model_name>.py -v
# Skip tests marked as xfail (run only expected passes)
pytest tests/test_chat_<model_name>.py -v -m "not xfail"
# Run all model tests
pytest tests/ -v
```
## Common Issues
After setting up the test, you will likely encounter the following issues. Address them before concluding tests pass.
### Model package not importable
By default, the `<models_dir>/` directory is not installed as a Python package, so `from <models_dir>.xxx import ...` in tests will fail. Two changes are needed in `pyproject.toml`:
**1) Add build-system config:**
```toml
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[tool.hatch.build.targets.wheel]
packages = ["<models_dir>"]
```
**2) Install in editable mode:**
```bash
uv pip install -e .
```
Without this, pytest fails with `ModuleNotFoundError: No module named '<models_dir>'`.
### Async tests not running (pytest-asyncio strict mode)
pytest-asyncio defaults to `Mode.STRICT`, which requires every async test to have an `@pytest.mark.asyncio` decorator. `langchain_tests` async methods lack this decorator.
Add to `pyproject.toml`:
```toml
[tool.pytest.ini_options]
asyncio_mode = "auto"
```
Without this, all async tests (`test_ainvoke`, `test_astream`, `test_abatch`, etc.) fail with "async def functions are not natively supported."