合作伙伴集成模式:独立包 + 标准测试
合作伙伴集成模式:独立包 + 标准测试
学习目标
本章要解决什么问题:LangChain 如何管理 17+ 第三方集成包(OpenAI、Anthropic、Ollama 等),保证每个集成质量一致且能独立发版?
读者将学到:
- partners/ 目录结构与独立包模式
- standard-tests 共享测试框架的架构
- 新伙伴集成的添加与 CI 流程
前置知识
本章涉及插件/集成系统的通用原理,建议先阅读:
项目实践
Partners 目录结构
每个 partner 是一个独立的 Python 包,位于 libs/partners/{name}/:
libs/partners/├── openai/ # langchain-openai==1.2.2├── anthropic/ # langchain-anthropic==1.0.0├── ollama/ # langchain-ollama├── google-genai/ # langchain-google-genai├── groq/ # langchain-groq├── mistralai/ # langchain-mistralai├── fireworks/ # langchain-fireworks├── huggingface/ # langchain-huggingface├── deepseek/ # langchain-deepseek├── xai/ # langchain-xai├── perplexity/ # langchain-perplexity├── chroma/ # langchain-chroma├── qdrant/ # langchain-qdrant├── exa/ # langchain-exa├── nomic/ # langchain-nomic└── ...命名约定:
- PyPI 包名:
langchain-{partner} - Python 模块名:
langchain_{partner}(连字符替换为下划线) - 目录名:
{partner}(纯名称)
独立包结构
每个 partner 包是标准的 Python 包,包含自己的 pyproject.toml:
[project]name = "langchain-openai"version = "1.2.2"requires-python = ">=3.10.0,<4.0.0"dependencies = [ "langchain-core>=1.4.0,<2.0.0", "openai>=2.26.0,<3.0.0", "tiktoken>=0.7.0,<1.0.0",]
[tool.uv.sources]langchain-core = { path = "../../core", editable = true }
[dependency-groups]test = ["langchain-core>=1.4.0,<2.0.0"]lint = ["ruff>=0.15.0,<0.16.0"]typing = ["mypy>=1.19.1,<1.20.0"]关键设计:
- 每个包只依赖
langchain-core和对应的第三方 SDK - 通过
[tool.uv.sources]引用本地 core 包(editable installs) - 独立版本号,互不影响
Standard-Tests 共享测试框架
libs/standard-tests/ 提供一套标准化的测试基类,所有 partner 包复用同一套测试:
libs/standard-tests/├── langchain_tests/│ ├── unit_tests/│ │ ├── chat_models.py # ChatModel 单元测试基类│ │ ├── embeddings.py # Embeddings 单元测试基类│ │ └── tools.py # Tools 单元测试基类│ ├── integration_tests/│ │ ├── chat_models.py # ChatModel 集成测试基类│ │ ├── embeddings.py # Embeddings 集成测试基类│ │ ├── vectorstores.py # VectorStore 集成测试基类│ │ ├── retrievers.py # Retriever 集成测试基类│ │ ├── cache.py # Cache 集成测试基类│ │ ├── base_store.py # BaseStore 集成测试基类│ │ ├── indexer.py # Indexer 集成测试基类│ │ └── sandboxes.py # Sandbox 集成测试基类│ └── utils/ # 测试工具└── pyproject.toml # PyPI 包: langchain-tests测试基类的使用方式:
# partner 包中的测试文件from langchain_tests.unit_tests import ChatModelUnitTestsfrom langchain_tests.integration_tests import ChatModelIntegrationTests
class TestOpenAIChatModel(ChatModelUnitTests): @pytest.fixture() def chat_model_class(self): return ChatOpenAI
@pytest.fixture() def chat_model_params(self): return {"model": "gpt-4o-mini"}关键特性:
- Partner 开发者只需提供
chat_model_class和chat_model_params,继承基类即可获得完整测试套件 - 统一测试标准:所有 partner 包通过相同的测试用例,保证集成质量一致
- pytest 插件注册:
langchain-tests作为 pytest11 插件注册,自动发现测试
可选依赖入口
langchain 主包通过 optional dependencies 提供便捷的集成入口:
[project.optional-dependencies]anthropic = ["langchain-anthropic"]openai = ["langchain-openai"]google-vertexai = ["langchain-google-vertexai"]ollama = ["langchain-ollama"]用户可以通过 pip install "langchain[openai,anthropic]" 一次安装多个集成。
问题与规避
Partner 包与 Core 版本不兼容
问题:Partner 包可能依赖特定版本的 langchain-core,而 Core 更新后可能引入破坏性变更。
对策:CI 中有 check_core_versions.yml workflow 检测 Core 版本与 Partner 的兼容性。Partner 包的依赖约束使用 >=X.Y.Z,<X+1.0.0 格式,锁定主版本。
集成测试的 API 密钥管理
问题:partner 集成测试需要对应服务的 API 密钥,不能要求开发者配置所有密钥。
对策:CI 通过 check_diffs.yml 变更检测,只运行被修改包相关的测试。集成测试标记为 @pytest.mark.requires,可按需跳过。
设计取舍
独立包 vs 单一包内集成
| 方案 | 优势 | 代价 |
|---|---|---|
| 独立包 | 独立发版、依赖隔离、第三方可维护 | 需要标准测试保证质量一致性 |
| 单一包内集成 | 统一版本、用户安装简单 | 依赖膨胀、发版耦合、维护负担集中 |
LangChain 选择独立包,因为每个 partner 的 SDK 版本演进速度不同——OpenAI SDK 可能一周更新三次,而 Ollama 可能一个月更新一次。独立发版避免了等待同步的问题。
Standard-Tests vs 各包独立测试
| 方案 | 优势 | 代价 |
|---|---|---|
| Standard-Tests | 测试标准统一、新增集成自动获得测试、减少重复代码 | 基类需要向后兼容所有集成 |
| 各包独立测试 | 每个包自由定制测试 | 测试标准不一致、新集成容易遗漏关键用例 |
LangChain 选择 Standard-Tests 作为共享测试基类,partner 包只需继承并配置参数即可获得完整测试套件。