news 2026/9/12 1:14:16

Composio Python SDK 文档生成器:基于 griffe 的 MDX 参考文档自动化流水线

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Composio Python SDK 文档生成器:基于 griffe 的 MDX 参考文档自动化流水线

Composio Python SDK 文档生成器:基于 griffe 的 MDX 参考文档自动化流水线

【免费下载链接】composioComposio powers 1000+ toolkits, tool search, context management, authentication, and a sandboxed workbench to help you build AI agents that turn intent into action.项目地址: https://gitcode.com/GitHub_Trending/co/composio

本文聚焦 Composio 开源仓库中的 SDK 文档生成模块:python/scripts/README.md 与其核心实现 generate-docs.py。该模块使用 griffe 解析 Python 源码与 docstring,自动生成docs/content/reference/sdk-reference/python/下的 MDX 参考文档,并配套回归测试与 CI 自动提 PR 流程。读完本文,你将掌握该文档生成器的运行方式、三类核心配置(EXPECTED_CLASSESCLASS_MODULESDECORATORS_TO_DOCUMENT)的作用、MDX 产物结构,以及如何在自己的 Python 项目中复用这套「源码即文档」的生成模式。

一、背景:为什么 SDK 参考文档需要自动生成

Composio 的 Python SDK(python/composio/sdk.py)是一个公开 API 面较大的包:以Composio类为入口,向下暴露toolstoolkitstriggersconnected_accountsauth_configsmcp等多个子模块对象,每个对象又包含大量方法与参数。如果全部手写文档,极易出现「源码改了、文档忘了同步」的问题,且方法签名、参数默认值、返回类型等信息手抄成本高、错误率也高。

该模块的解决方案是「源码即事实」:由 griffe 直接读取源码中的类型注解与 docstring,把结构化数据转换为 MDX 文件,再通过 CI 在源码变更后自动生成并提交 PR。整个链条保证了参考文档与实现保持同源,这也是开发者引用参考文档时能放心依赖其准确性的根本原因。

二、快速开始:一条命令生成全部文档

按 python/scripts/README.md 中的说明,在仓库根目录下执行:

cd python uv run --with griffe python scripts/generate-docs.py

其中:

  • cd python:生成脚本 generate-docs.py 位于python/scripts/下,其脚本内PACKAGE_DIR = SCRIPT_DIR.parent会把python/作为待分析包根目录与 griffe 的搜索路径;
  • uv run --with griffe:使用 uv 临时注入 griffe 依赖后运行脚本,无需预先修改项目的依赖清单。若环境中没有 griffe,脚本会打印Error: griffe not installed. Run: pip install griffe并以非零状态退出(见 generate-docs.py 中load_griffe()的懒加载逻辑);
  • 输出目录为仓库根下的docs/content/reference/sdk-reference/python/(由脚本内OUTPUT_DIR常量计算得到)。

运行结束后,控制台会依次打印加载包、发现各个类、处理装饰器以及最终生成统计等信息,例如Done! Generated N class docs + index

三、工作原理:三步流水线

README 用三个步骤概括了整体流程,结合源码可以展开为更完整的执行序列:

  1. 提取:griffe 解析composio/**/*.py,从 docstring、类型注解与类/方法结构中得到结构化数据。对应源码中griffe.load("composio", search_paths=[str(PACKAGE_DIR)])的调用;
  2. 转换generate-docs.py将结构化数据转换为 MDX 文件——为每个公开类生成独立页面,并生成索引页与导航配置;
  3. 输出:全部文件写入docs/content/reference/sdk-reference/python/,包括每个类的.mdx页面、index.mdx汇总页与meta.json导航清单。

实际执行时main()函数的完整顺序如下(可对照 generate-docs.py 验证):

  1. 懒加载 griffe,校验环境;
  2. 清理并重建输出目录(shutil.rmtree+mkdir);
  3. 加载composio包,定位sdk模块中的Composio类;
  4. 遍历CLASS_MODULES中的模块,在成员里查找EXPECTED_CLASSES声明的类,同时建立「属性名 → 类名」映射(prop_to_class),供Composio页面的属性交叉链接使用;
  5. 补充处理ADDITIONAL_CLASSES中那些不以composio.<属性>方式直接暴露、但仍属公开 API 的类(如ToolRouterSession);
  6. 对每个类执行extract_class_info,提取属性、方法、参数、返回值与示例;
  7. 处理DECORATORS_TO_DOCUMENT声明的修饰器并生成文档片段;
  8. 生成index.mdxmeta.json

四、配置详解:三类核心配置项

README 列出三个核心配置,源码中还有若干辅助配置共同决定「文档化哪些内容」。

4.1EXPECTED_CLASSES:类名到Composio属性的映射

EXPECTED_CLASSES = { "Tools": "tools", "Toolkits": "toolkits", "Triggers": "triggers", "ConnectedAccounts": "connected_accounts", "AuthConfigs": "auth_configs", "MCP": "mcp", }
  • :类名(如Tools);
  • :该类在Composio实例上对应的属性名(如composio.tools)。

该映射的意义在于:生成Composio类页面时,属性表格中的toolstoolkits等条目会被渲染为指向对应类页面的链接(类型列显示为`Tools`等类名),形成「入口类 → 子模块类」的交叉引用结构。实际产物可见 composio.mdx 的 Properties 表格。

同时该映射也用于在 sdk.py 的__init__中确认这些属性确实由构造器初始化(self.tools = Tools(...)self.toolkits = Toolkits(...)等),保证「文档声明的 API」与「运行时存在的 API」一一对应。

4.2CLASS_MODULES:类搜索范围

CLASS_MODULES = [ "core.models.tools", "core.models.toolkits", "core.models.triggers", "core.models.connected_accounts", "core.models.auth_configs", "core.models.mcp", ]

脚本按点号逐级下钻 griffe 的package.members树,只有出现在这些模块中的类才会被纳入文档范围。与EXPECTED_CLASSES一一对应的 6 个模块,恰好覆盖了 SDK 的主要子领域:工具、工具包、触发器、连接账户、认证配置与 MCP。每个类找到后,其访问路径会被标记为composio.<property>(如composio.tools),并打印Found Tools (via composio.tools)之类的日志。

4.3DECORATORS_TO_DOCUMENT:需要文档化的修饰器

DECORATORS_TO_DOCUMENT = [ ("before_execute", "composio.core.models._modifiers"), ("after_execute", "composio.core.models._modifiers"), ("before_file_upload", "composio.core.models._modifiers"), ("schema_modifier", "composio.core.models._modifiers"), ]

每个元组的第一个元素是装饰器函数名,第二个元素是其在包内的模块路径。这 4 个装饰器全部位于 python/composio/core/models/_modifiers.py,是 SDK 的自定义工具修饰能力:before_execute/after_execute分别在工具执行前后改写请求参数或响应,before_file_upload拦截文件上传(返回新路径/URL 或False中止上传),schema_modifier在运行期修改工具 schema。生成器会为每个装饰器渲染一段签名示例,例如@before_execute(modifier=..., tools=..., toolkits=...)配合def my_modifier(...)占位,帮助用户理解修饰器的调用形态;完整说明可见 index.mdx 的 Decorators 小节。

4.4 辅助配置:过滤、重命名与补充

源码中还定义了以下几组影响文档产物的辅助配置:

  • SKIP_CLASSES{"WithLogger", "SDKConfig", "TProvider"},过滤日志基类、SDK 配置 TypedDict 与泛型占位等内部/辅助类;
  • ADDITIONAL_CLASSES{"ToolRouterSession": "core.models.tool_router_session"},补充那些不通过composio.<属性>暴露、但属于公开 API 的类(源码注释特别说明SessionContextImpl因属内部实现细节而刻意不收录);
  • DISPLAY_NAME_OVERRIDES{"ToolRouterSession": "Session"},实现「源码类名不变、文档展示名规范化为 Session」的纯展示层重命名;
  • SLUG_OVERRIDES{"ToolRouterSession": "session"},控制输出文件名与 URL slug。

正是后两组配置,使 session.mdx 以Session名称对外呈现,同时meta.json中登记为session页,而无需对源码做破坏性改名。

五、输出产物:MDX 文件的结构

5.1 目录清单

运行生成器后,docs/content/reference/sdk-reference/python/下会包含(与当前仓库现状一致):

  • index.mdx:汇总页,含安装提示、类清单表格、Quick Start 代码示例与 Decorators 小节;
  • composio.mdxtools.mdxtoolkits.mdxtriggers.mdxconnected-accounts.mdxauth-configs.mdxmcp.mdxsession.mdx:每个类的独立页面;
  • meta.json:Fumadocs 导航元数据,pages数组按composio → tools → ... → session的顺序声明页面(与SLUG_OVERRIDES保持一致)。

5.2 单页结构(以tools.mdx为例)

每个类页面由generate_class_mdx()生成,典型结构为:

  1. YAML frontmattertitledescription,description 取类 docstring 首段并做长度截断(超过 150 字符截为 147 字符加省略号),同时会把 reStructuredText 风格的双反引号 code 规范化为单反引号;
  2. 弃用提示:若类 docstring 含.. deprecated::指令,则渲染为<Callout type="warn" title="Deprecated">警告块;
  3. Properties 表格:列出公开属性(跳过下划线开头成员);当属性名命中prop_to_class时渲染为指向类页面的 Markdown 链接,类型列显示类名;当属性无描述时自动降级为两列表格;
  4. Methods 小节:每个方法包含描述、Python 签名代码块(参数按name: type输出,有默认值的标记= ...)、参数表格(?后缀标注可选参数,|转义为\|以兼容表格)、返回值说明(None/Any省略)、示例代码块,方法之间以---分隔;
  5. View source 链接:页面底部为每个对象输出指向源码文件行号位置的链接(由 griffe 提供的filepathlineno计算得出)。

以 tools.mdx 为例,读者可以看到get()execute()proxy()get_raw_tool_router_meta_tools()等方法的完整签名与参数表,其中get()的返回类型按 provider 泛型动态推断(如 OpenAIProvider 返回list[ChatCompletionToolParam]),这正体现了生成器对泛型标注的忠实呈现。

六、docstring 与类型的规范化处理

为了让生成文档「可读、可复制」,脚本对原始源码信息做了多层规范化:

  • 类型清理(format_type:去掉typing.typing_extensions.composio.client.types.等前缀;将Optional[X]改写为X | None;把Unpack[...]简化为内部类型;超过 60 字符的超长类型截断为 57 字符加...
  • docstring 分区解析(parse_docstring:逐行识别:param name::returns:/:return:Example区段与.. deprecated::指令,分别归入 description、params、returns、examples、deprecated 字段;多行描述会正确拼接;
  • 示例规范化(normalize_example:用textwrap.dedent去除缩进,若示例自身带有 python ... 围栏则剥离围栏内容,避免生成「嵌套代码块」的非法 MDX。

这些细节并非无关紧要——回归测试 python/tests/test_generate_docs.py 专门验证了两点:Triggers.parse()生成的示例必须是可直接ast.parse的合法 Python(保证「复制即用」);docstring 示例中的嵌套 Markdown 围栏会被剥离,不会污染最终 MDX。

七、测试保障:回归测试如何守护产物质量

测试文件通过importlib.util.spec_from_file_location动态加载scripts/generate-docs.py(不执行main(),仅导入模块),从而在无 griffe 的测试环境下单测解析逻辑,这正是脚本把 griffe 做成懒加载的原因。测试内容:

  1. test_triggers_parse_generated_example_is_valid_python:用真实类的Triggers.parse.__doc__parse_docstring,断言示例存在且可通过ast.parse语法校验,防止 docstring 改动后生成不可复制的示例代码;
  2. test_generated_examples_do_not_keep_nested_markdown_fences:验证normalize_example会剥离示例内嵌的 python 围栏。

也就是说,文档生成器自身也受 CI 测试保护,任何会让「生成的示例代码失配」的 docstring 变更都会在测试阶段被拦截。

八、CI 自动化:源码变更自动生成并提交 PR

README 提到的.github/workflows/generate-sdk-docs.yml在仓库中真实存在,其generate-python-docsjob 完整实现了「触发 → 生成 → 提 PR → 请求评审」的闭环:

  • 触发条件pushnext分支,且路径匹配python/composio/**python/scripts/generate-docs.py.github/workflows/generate-sdk-docs.ymlmise.toml/mise.lock等;同时支持workflow_dispatch手动触发;
  • 运行步骤:生成 GitHub App token → checkout → 用setup-python-uvaction 准备 uv 环境 → 执行cd python && uv run --with griffe python scripts/generate-docs.py
  • 提 PR:使用peter-evans/create-pull-requestdocs/content/reference/sdk-reference/python/目录的变更提交为标题为docs: update Python SDK reference from source的 PR,base 分支为next,并自动把提交者添加为 reviewer。

值得留意的是,同一个工作流还包含generate-ts-docsjob,对应 TypeScript 侧的文档生成(pnpm --filter @composio/core generate:docs),说明「源码变更自动同步 SDK 参考文档」是整个仓库的通用工程实践,Python 侧只是其中一半。该工作流还约束了permissions: contents: read的最小权限原则,仅在需要写回内容的 job 内放开contents: writepull-requests: write

九、落地实践:如何把该模式复用到自己的项目

这套生成器的设计对任何维护 Python SDK 文档的团队都有直接借鉴价值:

  1. 让文档生成成为构建步骤的一部分:与手写文档相比,griffe 直接从类型注解与 docstring 提取信息,签名与参数永远与源码同步;
  2. 用配置声明「文档化范围」:用「类名 → 入口属性」映射和「模块列表」精确圈定公开 API,配合SKIP_CLASSES屏蔽内部类,避免把实现细节泄露进面向用户的参考文档;
  3. 展示层与源码解耦DISPLAY_NAME_OVERRIDES/SLUG_OVERRIDES这类纯展示覆盖,让团队可以在不破坏源码兼容性的前提下规范化文档中的类名与 URL;
  4. 用测试守护生成器自身:像 test_generate_docs.py 那样,把「生成的示例必须可运行、生成的 MDX 必须合法」固化为自动化断言;
  5. 用 CI 完成闭环:在源码路径变更时自动重新生成并提 PR,配合人工评审,让文档更新成为可追踪、可审查的常规流程。

如果你需要在本仓库中查看最终产物,可直接阅读 index.mdx(总览与 Quick Start)、composio.mdx(入口类属性交叉链接)以及 tools.mdx(方法级参考页范式),并结合 generate-docs.py 源码理解每段产物背后的生成逻辑。

【免费下载链接】composioComposio powers 1000+ toolkits, tool search, context management, authentication, and a sandboxed workbench to help you build AI agents that turn intent into action.项目地址: https://gitcode.com/GitHub_Trending/co/composio

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/12 1:13:27

Matlab实战:小波阈值去噪提升语音识别准确率

1. 语音信号处理中的小波阈值去噪实战 去年调试一个语音识别项目时&#xff0c;发现环境噪声严重影响识别准确率。传统滤波方法要么残留噪声&#xff0c;要么损伤语音特征&#xff0c;直到尝试了小波阈值去噪。这个方法在保留语音特征的同时&#xff0c;能有效消除随机噪声&…

作者头像 李华
网站建设 2026/9/12 1:11:21

豆包AI辅助Vivado开发实战:从时序约束到代码生成的高效工作流

1. 用AI“豆包”给Vivado开发流程提速&#xff0c;这事靠不靠谱&#xff1f;先说结论&#xff1a;靠谱&#xff0c;但别指望它帮你把整个工程写完。最近我把豆包&#xff08;网页版和桌面客户端都用过&#xff09;真正接进了日常Vivado开发流程里&#xff0c;用了大概三周时间&…

作者头像 李华
网站建设 2026/9/12 1:11:14

电容选型硬核指南:五大类型特性对比与实战避坑

电容这玩意儿&#xff0c;看着就两个引脚&#xff0c;但真正做硬件的人都知道&#xff0c;选电容才是电路设计里最容易被坑的地方。不同类型电容的核心特性差异&#xff0c;直接决定了一块板子是稳定运行还是天天出幺蛾子。我见过太多新人在滤波电容上栽跟头&#xff0c;也见过…

作者头像 李华
网站建设 2026/9/12 1:04:08

供应链数字化转型:从预测到物流的智能升级

1. 供应链管理概述&#xff1a;从传统到数字化的演进供应链管理&#xff08;Supply Chain Management, SCM&#xff09;这个领域最早可以追溯到20世纪80年代&#xff0c;当时企业开始意识到单纯优化内部生产流程已经不够&#xff0c;需要把视野扩展到整个供需网络。我2008年刚入…

作者头像 李华