为ToolUniverse做贡献

We welcome contributions to ToolUniverse!

快速入门

开发环境搭建

  1. 在 GitHub 上派生该仓库

  2. 在本地克隆您的派生仓库:

git clone https://github.com/yourusername/TxAgent.git
cd TxAgent/bio/ToolUniverse
  1. 创建虚拟环境:

python -m venv venv
source venv/bin/activate  # On Windows: venv\Scripts\activate
  1. 以开发模式安装:

pip install -e ".[dev]"
  1. 安装 pre-commit 钩子:

自动设置(推荐):

# Auto-install pre-commit hooks
./setup_precommit.sh

手动设置:

# Install pre-commit if not already installed
pip install pre-commit

# Install hooks
pre-commit install

# Update to latest versions
pre-commit autoupdate

开发依赖项

开发设置包括:

  • pytest - 测试框架

  • black - 代码格式化

  • flake8 - 代码静态检查

  • mypy - 类型检查

  • sphinx - 文档

  • pre-commit - Git 钩子

代码标准

代码风格

我们使用 Black 进行代码格式化,并遵循 PEP 8:

# Format code
black src/tooluniverse/

# Check formatting
black --check src/tooluniverse/

代码检查

使用 flake8 进行代码检查:

flake8 src/tooluniverse/

类型提示

所有新代码应包含类型提示:

from typing import Dict, List, Optional, Any

def process_data(
    data: List[Dict[str, Any]],
    filter_key: Optional[str] = None
) -> Dict[str, int]:
    """Process data and return summary statistics."""
    pass

测试

运行测试

运行测试套件:

# Run all tests
pytest

# Run with coverage
pytest --cov=tooluniverse

# Run specific test file
pytest tests/test_graphql_tool.py

编写测试

为所有新功能编写测试:

import pytest
from unittest.mock import patch, Mock
from tooluniverse import ToolUniverse

class TestToolUniverse:
    def test_init(self):
        tooluni = ToolUniverse()
        assert tooluni is not None

    def test_load_tools(self):
        tooluni = ToolUniverse()
        tooluni.load_tools()
        tool_names, _ = tooluni.refresh_tool_name_desc()
        assert len(tool_names) > 0

    @patch('requests.post')
    def test_opentargets_query(self, mock_post):
        mock_response = Mock()
        mock_response.json.return_value = {"data": {"test": "result"}}
        mock_response.raise_for_status.return_value = None
        mock_post.return_value = mock_response

        tooluni = ToolUniverse()
        tooluni.load_tools()
        query = {
            "name": "OpenTargets_get_disease_id_description_by_name",
            "arguments": {"diseaseName": "test disease"}
        }
        result = tooluni.run(query)
        assert result is not None

测试覆盖率

目标测试覆盖率超过90%:

pytest --cov=tooluniverse --cov-report=html
open htmlcov/index.html

文档

构建文档

cd docs
make html
make serve  # Serve on http://localhost:8080

实时文档

实时编辑:

cd docs
make livehtml

编写文档

  • 记录所有公共 API

  • 在文档字符串中包含示例

  • 更新用户指南以涵盖新功能

  • 为复杂工作流程添加教程

文档字符串格式

使用 Google 风格的文档字符串:

def search_targets(self, disease_id: str, limit: int = 10) -> Dict[str, Any]:
    """Search for targets associated with a disease.

    Args:
        disease_id: The EFO ID of the disease
        limit: Maximum number of results to return

    Returns:
        Dictionary containing target information

    Raises:
        ValueError: If disease_id is invalid
        APIError: If the API request fails

    Example:
        >>> from tooluniverse import ToolUniverse
        >>> tooluni = ToolUniverse()
        >>> tooluni.load_tools()
        >>> query = {"name": "search_targets", "arguments": {"disease_id": "EFO_0000685", "limit": 5}}
        >>> results = tooluni.run(query)
        >>> print(f"Found {len(results['targets'])} targets")
    """

贡献工作流程

1. 创建功能分支

git checkout -b feature/your-feature-name

2. 进行更改

  • 按照我们的标准编写代码

  • 添加全面测试

  • 更新文档

  • 运行测试套件

3. 提交更改

使用规范的提交信息:

git add .
git commit -m "feat: add new drug interaction tool

- Implement DrugInteractionTool class
- Add support for drug-drug interaction queries
- Include comprehensive test coverage
- Update documentation with examples"

提交类型: - feat:新功能 - fix:错误修复 - docs:文档更新 - test:测试新增或修改 - refactor:代码重构 - style:代码风格变更 - chore:构建/维护任务

4. 推送并创建合并请求(PR)

git push origin feature/your-feature-name

然后在 GitHub 上创建一个 Pull Request,内容包括: - 清晰的变更描述 - 相关问题的链接 - 界面更改的截图 - 性能影响说明

贡献类型

错误报告

报告缺陷时,请包括:

  • Python 版本与操作系统

  • ToolUniverse 版本

  • 重现问题的最简代码

  • 完整错误追踪信息

  • 预期行为与实际行为

功能请求

对于新功能,请提供:

  • 清晰的用例描述

  • 拟议的 API 设计

  • 实施建议

  • 对现有代码的影响

新工具

添加新科学工具时:

  1. 彻底调研数据来源

  2. 设计简洁且一致的 API

  3. 实施全面的错误处理

  4. 添加详尽的测试和文档

  5. 包含使用示例

示例新工具结构:

from tooluniverse.base_tool import BaseTool
from typing import Dict, Any, List

class NewScientificTool(BaseTool):
    """Tool for accessing [Data Source Name] API."""

    def __init__(self, config: Dict[str, Any] = None):
        super().__init__(config)
        self.base_url = self.config.get('base_url', 'https://api.example.com')

    def search_data(self, query: str, **kwargs) -> Dict[str, Any]:
        """Search for scientific data.

        Args:
            query: Search query
            **kwargs: Additional search parameters

        Returns:
            Search results with metadata
        """
        self.validate_input(query=query, **kwargs)
        return self._execute_search(query, **kwargs)

文档改进

帮助改进文档:

  • 修正拼写错误和语法问题

  • 添加缺失的示例

  • 澄清易混淆部分

  • 翻译成其他语言

  • 添加视频教程

审核流程

所有贡献均需经过代码审查:

  1. 自动化检查:CI 执行测试、代码规范检查和类型检查

  2. 人工审核:维护者审查代码质量和设计

  3. 文档审核:确保文档清晰完整

  4. 测试:验证功能是否按预期工作

审核标准

  • 代码遵循项目标准

  • 测试覆盖率充足

  • 文档完整且清晰

  • 性能影响在可接受范围内

  • 重大变更是有正当理由的

获取帮助

社区资源

  • GitHub 讨论区:常见问题与创意交流

  • GitHub 问题:错误报告与功能请求

  • 电子邮件:与维护人员直接联系

维护者联系方式

开发技巧

调试

使用内置调试功能:

import logging
logging.basicConfig(level=logging.DEBUG)

# Enable tool debugging
from tooluniverse import ToolUniverse
tooluni = ToolUniverse()
tooluni.load_tools()
# Access specific tools through the registry for debugging

测试 API 变更

针对多个数据源进行测试:

# Test against staging API
export OPENTARGETS_BASE_URL=https://staging-api.opentargets.org
pytest tests/test_graphql_tool.py

性能测试

分析您的更改:

import cProfile
import pstats

profiler = cProfile.Profile()
profiler.enable()

# Your code here

profiler.disable()
stats = pstats.Stats(profiler)
stats.sort_stats('cumulative').print_stats(10)

识别

贡献者将被列入以下内容:

  • 发布说明

  • 贡献者文件

  • 文档致谢

  • 年度贡献者亮点

Thank you for contributing to ToolUniverse!