Skip to main content
欢迎贡献代码!无论你是修复 bug、添加新功能还是改进性能,你的贡献都能为成千上万的开发者带来更好的开发体验。

开始指南

如果你正在寻找可以工作的项目,请查看我们仓库中带有 “help wanted” 标签的问题:

LangChain

标签

LangGraph

标签

Deep Agents

标签
在提交大型的新功能或重构之前,请先打开一个 issue 或在 论坛 发帖讨论。这可以确保与项目目标保持一致,并避免重复工作。

简单修复:提交 bug 修复

对于简单的 bug 修复,你可以立即开始:
1

重现问题

在克隆仓库之前,请确保能够可靠地重现该 bug。这有助于确认问题并提供一个起点来解决它。维护者和其他贡献者应能根据你的描述在无需额外设置或修改的情况下重现该问题。
2

创建分支

为修复的问题创建一个新的分支。这样可以保持更改的组织,并使稍后提交 pull request 更加容易。
git checkout -b your-username/short-bugfix-name
3

编写失败测试

添加在没有你的修复之前会失败的单元测试。这允许我们验证 bug 已被解决并防止回退。
4

进行更改

在遵循我们的 代码质量标准 的前提下修复 bug。只需做出解决问题所需的最小变更。我们强烈建议在开始编码之前就问题发表评论。例如:
“我想解决这个问题。我的计划是 [… 简要描述 …]。这与维护者的期望一致吗?”
一个简短的评论通常可以防止如果初始方法错误而导致浪费努力。
5

验证修复

确保测试通过并且没有引入回退。在提交 pull request 之前确保所有本地测试都已通过。
make format
make lint
make test

# 如果涉及集成,则还需运行:
make integration_tests
# (可能需要设置 API 测试凭证)
6

记录变更

更新文档字符串和/或内联注释,如果行为发生变化的话。
7

提交 pull request

按照提供的 pull request 模板操作。如果适用,请使用 关闭关键字(例如 Fixes #ISSUE_NUMBER)来引用你正在修复的问题,以便在 pull request 合并时自动关闭问题。

完整开发环境设置

对于持续开发或更大规模的贡献:
  1. 请参阅我们的 贡献指南 以了解功能、bug 修复和集成的要求
  2. 按照下面提供的 设置指南 设置你的环境
  3. 理解仓库结构和包组织
  4. 学习我们的 开发工作流,包括测试和 linting

贡献指南

在开始为 LangChain 项目贡献代码之前,请花时间思考一下你为什么要这样做。如果你的唯一目标是添加一个“首次贡献”到你的简历(或者只是寻找一个快速胜利),你可能更适合参加培训营或在线教程。 参与开源项目需要时间和努力,但它也可以帮助你成为一个更好的开发者并学习新技能。然而,重要的是要知道这可能比跟随训练课程更难和慢一些。不过,如果你愿意花时间做好事情的话,为开源做出贡献是值得的!

向后兼容性

除非是为了关键的安全修复,否则不允许对公共 API 进行破坏性的更改。有关主要版本发布的详细信息,请参阅我们的 版本策略
保持兼容性的方式:
始终保留
  • 函数签名和参数名称
  • 类的接口和方法名称
  • 返回值结构和类型
  • 公共 API 的导入路径
可接受的修改
  • 添加新的可选参数
  • 为类添加新方法
  • 在不改变行为的情况下提高性能
  • 添加新模块或函数
  • 这个更改是否会破坏现有的用户代码?
  • 检查你的目标是否是公共的
  • 如果需要,它是否导出在 __init__.py 中?
  • 在测试中是否有现有的用法模式?

新功能

我们希望保持新功能的标准很高。通常情况下,除非有现有问题表明它们具有迫切需求,否则我们不会接受来自外部贡献者的新的核心抽象。这同样适用于基础设施和依赖项的更改。 一般而言,新功能贡献的要求包括:
1

设计讨论

打开一个 issue 来描述:
  • 你解决的问题
  • 提议的 API 设计
  • 预期的使用模式
2

实现

  • 遵循现有代码模式
  • 包含全面的测试和文档
  • 考虑安全影响
3

集成考虑

  • 这个功能如何与现有的功能交互?
  • 是否有性能影响?
  • 是否引入了新的依赖项?
我们将拒绝那些可能导致安全漏洞或报告的功能。

安全指南

安全是首要的。永远不要引入漏洞或不安全的模式。
安全检查清单:
  • 验证和清理所有用户输入
  • 正确地在模板和查询中转义数据
  • 从用户数据中绝不能使用 eval()exec()pickle,因为这可能导致任意代码执行漏洞
  • 使用特定的异常类型
  • 不要在错误消息中暴露敏感信息
  • 实现适当的资源清理
  • 避免添加硬依赖项
  • 保持可选依赖项最小化
  • 审查第三方包的安全问题

开发环境

使用 AI 编码代理? 安装 LangChain Skills 以提高你在 LangChain 生态系统任务中的代理性能,然后点击此页面右上角的“复制页面”按钮并粘贴原始内容到你的代理中,使其自动为你设置环境。
我们的 Python 项目使用 uv 进行依赖管理。请确保安装了最新版本。
我们力求在所有 Python 包中保持设置的一致性。从包目录运行:
uv sync --all-groups
make test  # 在开始开发之前验证单元测试通过
一旦你已经审阅了 贡献指南,请找到你在 仓库结构 部分中工作的组件的包目录。

仓库结构

LangChain 是一个包含多个包的单体仓库:

核心包

  • langchain (位于 libs/langchain/): 主包,包括链、代理和检索逻辑
  • langchain-core (位于 libs/core/): 基础接口和核心抽象
位于 libs/partners/ 中,这些是为特定集成独立版本的包。例如:许多合作伙伴包位于外部仓库中。请参阅 集成列表 以获取详细信息。

开发工作流

预提交钩子

LangChainDeep Agents 仓库包含预提交钩子,这些钩子在每次提交之前自动运行格式化、检查和验证。从仓库根目录安装它们:
pip install pre-commit  # 或: uv tool install pre-commit
pre-commit install
这些钩子强制执行:
  • 不直接向受保护分支提交更改
  • YAML 和 TOML 语法验证
  • 检查尾随空格和文件末尾的修复
  • 标点符号和非标准空格的规范化
  • 每个包的 make formatmake lint

运行测试

目录相对于你工作的包是相对的。
我们倾向于在可能的情况下使用单元测试而不是集成测试。单元测试会在每次 pull request 中运行,因此它们应该快速且可靠。集成测试按计划运行,并需要更多设置,因此应仅用于确认与外部服务的接口点。

单元测试

位置: tests/unit_tests/ 单元测试覆盖不需要调用外部 API 的模块逻辑。如果你添加了新逻辑,你应该添加一个单元测试。在单元测试中检查预处理和后处理,并模拟外部依赖项。 要求:
  • 不允许网络请求
  • 测试所有代码路径,包括边界情况
  • 使用 mock 对外部依赖项进行测试
运行单元测试:
make test

# 或直接:
uv run --group test pytest tests/unit_tests

# 运行特定的测试:
TEST_FILE=tests/unit_tests/test_imports.py make test

集成测试

位置: tests/integration_tests/ 集成测试覆盖需要调用外部 API 的逻辑(通常与其他服务进行集成)。 集成测试需要访问外部服务提供程序 API(这可能会产生费用),因此默认情况下不会运行它们。 并非每次代码更改都需要集成测试,但请记住,在我们的审查过程中我们将单独要求并运行集成测试。 要求:
  • 测试与外部服务的真实集成
  • 使用环境变量来存储 API 密钥
  • 如果凭据不可用,则优雅地跳过
运行集成测试:
make integration_tests

# 或直接:
uv run --group test --group test_integration pytest --retries 3 --retry-delay 1 tests/integration_tests

# 运行特定的测试:
TEST_FILE=tests/integration_tests/test_openai.py make integration_tests

代码质量标准

贡献必须遵守以下质量要求:
必需: 所有函数的完整类型注解
def process_documents(
    docs: list[Document],
    processor: DocumentProcessor,
    *,
    batch_size: int = 100
) -> ProcessingResult:
    """按批次处理文档。

    参数:
        docs: 要处理的文档列表。
        processor: 文档处理器实例。
        batch_size: 每个批次中的文档数量。

    返回值:
        处理结果,包括成功和失败计数。
    """

依赖项

LangChain 包将硬依赖项和可选依赖项区分开来,以保持包轻量级并减少用户的安装开销。
几乎所有新的依赖项都应该为可选的。使用可选依赖项的情况包括:
  • 该依赖项仅用于特定集成或功能
  • 用户可以有意义地不使用此依赖项
  • 该依赖项较大,具有许多传递性依赖
要求:
  • 没有安装依赖项的情况下用户能够导入你的代码而不产生任何副作用(没有警告、错误或异常)
  • pyproject.tomluv.lock 不会更改
添加可选依赖项:
  1. 将依赖项添加到适当的测试依赖文件中(例如,extended_testing_deps.txt
  2. 添加一个至少尝试导入新代码的单元测试。理想情况下,该单元测试使用轻量级固定装置来测试代码逻辑。
  3. 使用 @pytest.mark.requires("package_name") 装饰器为需要依赖项的任何单元测试。

测试编写指南

为了编写有效的测试,有一些好的实践要遵循:
  • 使用自然语言在文档字符串中描述测试
  • 使用描述性的变量名
  • 累积断言
def test_document_processor_handles_empty_input():
    """测试处理器优雅地处理空文档列表。"""
    processor = DocumentProcessor()

    result = processor.process([])

    assert result.success
    assert result.processed_count == 0
    assert len(result.errors) == 0

提交 pull request

一旦你的测试通过且代码符合质量标准:
  1. 推送分支并打开一个 pull request
  2. 按照提供的 pull request 模板操作
  3. 使用 关闭关键字(例如 Fixes #123)来引用你正在修复的问题,以便在 pull request 合并时自动关闭问题
  4. 等待 CI 检查完成
如果你的 pull request 包含 AI 生成的内容,请遵循我们的 LLM 的可接受用途 政策。看起来像是低努力、AI 生成的垃圾内容的 pull request 将会无评论地关闭。
及时解决 CI 失败。维护者可能会在合理的时间框架内关闭未通过 CI 的 pull request。

获取帮助

我们的目标是使开发者的设置尽可能易于访问。如果你遇到任何难以设置的问题,请在 社区 Slack 或打开一个 论坛帖子
你现在可以为 LangChain 贡献高质量的代码了!