
最近代码托管圈里有一个话题讨论度不低Sourcehut 修改了与 LLM大语言模型相关的服务条款。很多人的第一反应是“平台是不是禁止我用 AI 写代码了”但实际讨论的焦点更可能是“第三方能不能抓取公开仓库去训练模型”。这篇内容不会逐字替官方转述条款因为服务条款是随时可能更新的文本任何人转载都可能断章取义我更想从技术开发者的实际视角出发帮你梳理清楚这类条款变化到底在解决什么问题公开仓库与 AI 训练之间的边界在哪里以及你在自己的项目中能做哪些防护和自查。如果你是一个开源项目维护者或者正在做 LLM 生产落地的数据团队这篇文章会比较有用。你会看到可执行的 Git 检查命令、robots.txt 与网关拦截的配置思路、训练数据合规审计的简易脚本以及一套能放进团队规范的工程建议。1. LLM 服务条款更新从 Sourcehut 谈起1.1 Sourcehut 是一个什么样的平台Sourcehut 在开发者社区里一直有比较独特的定位。它不像常见的商业代码托管平台那样主打图形界面和社交功能而是保留了很重的命令行使用习惯提供 Git 仓库托管、邮件列表、CI/CD、wiki 等功能。使用它的开发者通常对技术有较高要求也更关注自由软件、开放协议和隐私边界。当一个这样的平台调整服务条款时社区反应往往比普通商业平台更敏感。因为它的一部分用户本身就是开源软件作者他们对“代码去往哪里”这件事非常在意。Sourcehut 的条款变化围绕 LLM 展开会让用户想到几个很实际的问题我的源码仓库是不是会被自动爬取平台是否允许第三方为训练大模型而镜像仓库如果我不希望自己的代码进入训练集有没有办法这些问题背后其实有一个共通点代码托管平台不只是存放代码的地方它同时也是一个数据分发入口。只要仓库是公开的理论上任何人都可以通过 Git 协议或网页端获取内容差别只在于获取成本和是否受平台规则约束。1.2 为什么 LLM 与代码托管会扯上关系大语言模型的训练需要海量文本语料而代码是其中非常重要的一类数据。Git 平台上的公开仓库数量庞大、结构清晰、带有版本历史和提交信息对模型训练来说信息量很大。过去几年大量公开代码仓库被用于训练代码模型。围绕这件事的争议一直存在很多开发者并不清楚自己的仓库被采集也不清楚仓库使用的开源许可证是否允许模型训练。代码托管平台通常不会默认禁止第三方抓取公开页面因为公开仓库本身就是供他人阅读、克隆、贡献的。但当抓取目的变成“大规模构建训练集”问题就不太一样了。一次性拉取整个平台仓库、绕过页面频率限制、持续跟踪增量提交这些行为会明显改变平台和用户的成本结构。所以平台方在服务条款里对 LLM 训练行为进行专门描述本质上是在做规则层面的事前划分。1.3 条款讨论不等于“禁止 AI 编程”看到“Sourcehut 条款与 LLM 有关”时别急着理解为平台禁止开发者用 AI 编程工具。服务条款中的 LLM 限制通常约束的是用户对平台数据的使用方式而不是用户是否能在本地编辑器里使用 Copilot 类工具。一个比较合理的理解方向是平台更关心“你是不是把整个公开社区当成了免费数据集”。如果只是个人查看、学习、调试这类行为通常对平台没有明显额外负担但如果是爬虫脚本、分布式采集、镜像整个命名空间就会对基础设施造成压力。服务条款调整往往是给这类行为划出一条更清晰的界线。不过具体条款文本如何表述要以官方发布的版本为准。你可以去 Sourcehut 官方页面查看历史版本或变更说明不要依赖转述。2. 先理清几个容易混淆的边界2.1 公开仓库不等于可以任意使用很多开发者会有一个直觉代码既然已经公开了别人拿来用不是很正常吗从版权角度看“公开”和“授权”是两个概念。把代码放到公开仓库意味着他人可以看见、可以克隆、可以按许可证条款使用但不代表获得了超出许可证范围的授权。大模型训练往往会复制、清洗、改写大量代码片段再把它们压缩进模型参数。这个过程是不是构成版权法意义上的“复制”或“派生”在不同司法辖区可能有不同结论。这里不展开法律判断但作为开发者至少要意识到公开仓库的作者并没有天然放弃权利开源许可证就是作者用来表达“你可以怎么用”的主要工具。2.2 开源许可证管的是“分发”不直接回答“能否训练”常见的 MIT、Apache-2.0、GPL 等开源许可证核心逻辑是约束代码的复制、修改、再分发条件。它们并没有专门为“大模型训练”设计条款因为大多数许可证编写时间远早于如今的大模型时代。所以当你看到一个仓库用的是 MIT 许可证也先不要直接下结论说“一定可以随便训练”。MIT 许可证确实允许大量使用场景但它没有明确讨论模型训练是否属于“衍生作品”。Apache-2.0 里有限制使用商标、保留版权声明等要求训练数据管线是否满足这些要求也需要逐项检查。GPL 系许可证更复杂涉及 Copyleft 传染范围模型参数算不算“对应源码”在业界并没有统一答案。这也是为什么很多 LLM 数据团队开始建立“许可证审查 法务确认”的流程。单靠程序判断许可证名称只能作为粗筛无法替代人工判断。2.3 平台服务条款是一个独立边界开源许可证回答的是作者与使用者之间的版权问题平台服务条款回答的是用户与平台之间的合同问题。即使某个仓库的许可证允许下载和训练平台仍然可以通过服务条款设定额外限制。简单说一个研究团队可以联系仓库作者获得授权但如果它绕过平台限制、用爬虫把整个平台仓库都抓下来可能同时违反平台条款。平台可以封禁账号、限制 IP、删除镜像甚至采取法律手段。因此在做任何训练数据采集前除了看仓库许可证还要确认目标平台的服务条款是否允许这样做。3. 面对条款变化开发者需要做哪些自查平台条款调整后普通开发者能做的最直接的事情不是立刻搬仓库而是先把自己项目的暴露面梳理清楚。下面这几个步骤不依赖具体平台只要本机安装了 Git 就能执行。3.1 检查远端仓库和发布范围先确认你的代码到底推送到了哪些远端。很多开发者同时配置了多个 Git 远程比如开源平台和企业内部服务器。如果某一个远端配置错误可能把内部项目推到公开仓库。# 查看当前仓库的所有远端地址 git remote -v # 查看默认推送目标 git config --get remote.origin.url # 查看本地分支与远端分支跟踪关系 git branch -a # 查看是否不小心推送了标签 git tag运行之后你应该能从输出里确认几个信息origin 指向哪里是否有多个远端是否所有预期的分支和标签都已推送如果一个仓库打算保持私有但远端地址暴露在公司外的网络里就需要立刻处理。建议把git remote -v列入新机器初始化后的第一道检查。很多信息泄露不是发生在代码内容里而是发生在远端地址、分支名、贡献者邮箱这些元数据中。3.2 许可证文件是否齐全没有许可证的仓库在法律上非常尴尬。默认情况下没有许可证意味着作者保留所有权利别人即使看到代码也不能合法地复制、分发或构建衍生作品。但在大模型数据采集场景里没有许可证的仓库反而容易被爬虫无差别收录最终变成有风险的数据源。你可以用下面的命令检查仓库里是否包含常见许可证文件find . -maxdepth 2 -type f \( -iname LICENSE* -o -iname COPYING* -o -iname NOTICE* \) -print如果仓库里没有任何许可证文件建议尽快补充。即使暂时不想选择开源许可证也可以加入LICENSE或README说明明确“保留所有权利未经授权不得用于模型训练”。严格来说这样的声明能起到多大作用取决于具体司法辖区和平台执行情况但总比完全沉默要好。对于维护多个仓库的开发者建议把许可证检查写入 CI 流程。如果平台支持 Webhook 或 CI 脚本可以在每次推送后执行许可证文件存在性检查。3.3 敏感信息是否被误提交公开仓库一旦包含密钥、令牌、内网地址就等于把这些信息暴露给了所有可以读取仓库的人包括自动爬虫和 AI 训练数据采集器。模型训练会把密钥学进参数后续生成的代码也可能无意识复现敏感字符串。# 在当前工作区搜索常见敏感信息核心思路示例 grep -RInE (api[_-]?key|secret|password|token|BEGIN (RSA|EC|OPENSSH) PRIVATE KEY) \ --exclude-dir.git \ --exclude-dirnode_modules \ . | head -20这个命令会产生大量误报所以它只适合做快速摸底不适合作为正式密钥扫描工具。正式的工程方案应该使用 gitleaks、trufflehog 等专业工具并把扫描步骤接进 pre-commit 或 CI。即使没有敏感信息也可以顺手检查.env、.pem、.pfx、.key这类文件有没有被 Git 跟踪git ls-files | grep -Ei (^|/)(\.env|.*\.pem|.*\.pfx|.*\.key)$ || echo No common secret files tracked如果发现历史提交里已经存在敏感信息仅删除当前文件还不够需要改写 Git 历史或使用平台提供的清库工具并立即轮换相关令牌。这个操作风险较高务必在本地完整备份后再执行。4. 如果平台支持如何限制 AI 爬虫4.1 robots.txt 能约束哪些场景很多开发者以为只要在仓库里放一个robots.txtAI 爬虫就不会抓取项目了。这里有个关键误区robots.txt通常由网站服务器读取它的作用是约束访问某个域名路径的网页爬虫。对于公开 Git 仓库来说git clone走的是 Git 协议或 HTTP Smart 协议整个过程通常不读取robots.txt。如果你维护的是代码托管平台的 Web 页面robots.txt可以约束 GPTBot、CCBot 这类网页爬虫访问源码浏览页面。下面是一个常见的配置示例User-agent: GPTBot Disallow: / User-agent: CCBot Disallow: / User-agent: * Allow: /这段配置的意思是禁止 GPTBot 和 CCBot 抓取全站内容但允许普通搜索引擎继续访问。需要注意这个文件要放在网站域名的根路径下而不是塞进某个 Git 仓库里。个人开发者通常无法修改托管平台的根路径配置所以如果你的项目挂在 Sourcehut 这类公共托管平台上想通过 robots.txt 做限制需要平台方在站点级别支持才有效。4.2 Nginx 网关层再挡一道如果你是企业 GitLab、Gitea 或自建代码托管服务的管理员可以在反向代理层直接拦截已知 AI 爬虫的 User-Agent。这里给一个 Nginx 配置片段作为思路参考具体参数要以你的网关版本和架构为准。# /etc/nginx/conf.d/git.example.com.conf 片段 server { listen 443 ssl; server_name git.example.com; # 如果访问者 User-Agent 命中已知 AI 爬虫则直接拒绝 if ($http_user_agent ~* (GPTBot|CCBot|Bytespider|ClaudeBot|anthropic-ai)) { return 403; } location / { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }这个方案可以在 Web 层挡住一部分爬虫但对git clone同样不一定生效因为很多 Git 客户端不会在请求里携带明显的 AI Bot User-Agent。更可靠的限制方式是平台级认证和流量控制例如要求匿名访问限速、登录后克隆、对同一 IP 的并发连接做限制。4.3 为什么无法完全禁止 git clone只要一个仓库是公开的平台就没有办法在不破坏开放性的情况下完全禁止别人克隆。Git 是一个去中心化工具任何拿到仓库的人都可以形成镜像平台只能限制“直接抓取行为”无法控制数据在用户之间的二次流动。所以如果你真的不希望某个项目被他人获取最稳妥的方案不是依赖条款或爬虫拦截而是不要把仓库设为公开。公开仓库在本质上已经等于“允许任何人下载一份完整副本”。服务条款的作用主要是对平台内的大规模采集行为进行约束而不是给代码加密。5. 对 LLM 生产团队构建合规数据管道5.1 生产落地不只是模型代码“Building LLMs for Production”这个话题前阵子很火很多教程都在讲 RAG、微调、推理优化、评估体系。但真正做过生产级大模型项目的人会知道数据来源的合规性才是最容易翻车的部分。模型结构不对可以调推理性能不够可以优化但训练数据里混入未经授权的代码、隐私文本或商业机密一旦上线后果可能远超技术范畴。很多团队在实验阶段从公开仓库采集代码数据模型效果不错但到了生产阶段才发现无法通过合规审查。原因往往出在当初采集时没有记录数据来源没有保存许可证信息也没有保留原始仓库地址和提交哈希。等到想补审计时面对几百 GB 语料已经很难回溯。因此数据管道必须在采集第一行数据时就设计好元数据记录。这里的“元数据”至少包括来源 URL、抓取时间、许可证类型、作者信息、仓库提交哈希。没有这些信息后续任何合规判断都缺少基础。5.2 一份控制训练数据来源的准入清单生产级 LLM 团队在建设代码语料库时可以采用类似供应链管理的思路先定义哪些来源可以进入哪些来源需要额外审批明确获得授权的自有代码可以进入训练集。使用 MIT、Apache-2.0、BSD 等宽松许可证的代码需要进一步确认训练目的和衍生品边界。GPL 系许可证的代码必须标记高风险默认不进入训练集。没有任何许可证声明的代码一律不采集。来自平台服务条款明确禁止抓取的仓库即使技术上能拿到也不进入管道。包含大量个人信息、密钥痕迹、内网地址的仓库需要先做清洗和过滤再评估。这套清单不是法律结论而是工程上的风险控制策略。企业如果计划把模型商用最好再请律师针对目标司法辖区做专项评估。训练数据团队可以基于准入清单把判断流程代码化减少人工逐条审查的工作量。5.3 代码示例基于仓库元数据的许可证粗筛下面是一个简单的 Python 脚本思路输入一份本地已有的仓库元数据 CSV脚本根据许可证字段做粗筛并输出处理建议。这个脚本不负责下载代码只负责规整“已经合法获取的元数据”所以在做数据治理时比较安全。# 文件路径filter_repos.py # 用途根据仓库元数据中的许可证字段对代码语料数据做合规粗筛。 # 输入示例repositories.csv # 一行一个仓库字段可包含 # repo_name,url,license_id,notes # 运行示例 # python filter_repos.py repositories.csv output.csv import csv import sys # 宽松许可证列表只用于初步筛选不构成法律意见 PERMISSIVE_LICENSES { MIT, Apache-2.0, BSD-2-Clause, BSD-3-Clause, ISC, } # 高风险许可证前缀列表 HIGH_RISK_PREFIXES (GPL, LGPL, AGPL, MPL, EPL) def classify_row(row: dict) - tuple: 根据一行元数据返回 (结论, 是否允许进入待审查列表)。 license_id (row.get(license_id) or row.get(license) or ).strip() repo_name row.get(repo_name) or row.get(url) or unknown if not license_id: return f{repo_name}: 缺少许可证声明默认不采集, False if license_id in PERMISSIVE_LICENSES: return ( f{repo_name}: 宽松许可证需人工复查平台条款和仓库内声明后进入待审查列表, True, ) if license_id.startswith(HIGH_RISK_PREFIXES): return f{repo_name}: 高风险许可证({license_id})默认不采集, False return f{repo_name}: 未知许可证({license_id})需人工评估, False def main() - None: if len(sys.argv) 3: print(Usage: python filter_repos.py repositories.csv output.csv) sys.exit(1) input_csv, output_csv sys.argv[1], sys.argv[2] accepted_rows [] audit_lines [] with open(input_csv, newline, encodingutf-8) as f: reader csv.DictReader(f) for row in reader: comment, accepted classify_row(row) audit_lines.append(comment) if accepted: accepted_rows.append(row) with open(audit.log, w, encodingutf-8) as f: f.write(\n.join(audit_lines) \n) with open(output_csv, w, newline, encodingutf-8) as f: if accepted_rows: writer csv.DictWriter(f, fieldnamesaccepted_rows[0].keys()) writer.writeheader() writer.writerows(accepted_rows) else: f.write() print(f审计完成共 {len(audit_lines)} 条记录进入待审查 {len(accepted_rows)} 条。) print(详细结论请查看 audit.log) if __name__ __main__: main()这里的关键点是“先输出审计日志再输出通过名单”。很多团队做数据清洗时只保留能用的数据把被拒绝的数据直接丢弃这样会导致后续无法复盘。更好的做法是保留一份审计日志记录每条数据为什么被拒绝方便法务或安全团队复核。6. 平台内容被 LLM 训练影响的观测思路如果你运营的是自建平台或企业内部分支可能会希望了解自己有没有被 AI 爬虫盯上。最简单的思路是先查看访问日志中的 User-Agent 分布。常见 AI 爬虫 User-Agent 通常包含 GPTBot、CCBot、Bytespider、ClaudeBot、anthropic-ai 等字样。你可以在 Nginx 原始访问日志中检索这些关键词比如# 检索最近访问日志中疑似 AI 爬虫的请求 grep -iE GPTBot|CCBot|Bytespider|ClaudeBot|anthropic-ai /var/log/nginx/access.log | tail -50不过 User-Agent 可以伪造不能完全依赖它做结论。更可靠的方式是结合访问频率和 IP 特征判断有时还需配合 Web 应用防火墙或日志分析工具。自建平台需要注意日志中可能包含访客 IP 等个人信息做分析时要在自己有权处理的数据范围内进行并遵守隐私与安全规范。另一个思路是从 Git 协议流量入手。如果某人通过git clone大规模拉取仓库日志中的访问路径和行为特征通常与普通搜索爬虫不同例如会请求 info/refs、HEAD、objects 等 Git 端点。你可以把这些特征做成告警规则当单 IP 在短时间内访问大量不同仓库时触发限制。7. 常见问题与排查清单面对类似的条款更新开发者问得最多的几个问题可以汇总成下面的表格问题现象常见原因解决思路担心开源仓库被 AI 模型训练公开仓库本身可被任意克隆检查许可证如有需要将仓库设为私有仓库没有 LICENSE 文件作者未主动选择开源协议尽快补充许可证或权利声明在公共托管平台无法设置 robots.txtrobots.txt 属于站点级配置只能在平台支持时生效无法靠仓库内文件解决git clone仍然能拉到代码robots.txt 对 Git 协议无效确认部署/存储需求必要时转为私有仓库训练语料里包含 GPL 代码采集时未做许可证筛选用脚本粗筛建立高风险许可证黑名单历史提交中包含密钥早期提交不规范使用专业工具扫描及时轮换密钥并改写历史API 或爬虫账号被平台封禁采集行为违反平台服务条款停止未授权抓取改用官方 API 并遵守配额排查时可以遵循一个清单先确认自己的代码是不是真的需要公开。公开仓库是否包含版权声明、许可证文件、NOTICE。是否曾经在历史提交中放入敏感信息。如果使用付费平台是否查看过服务条款中关于数据爬取和 AI 训练的内容。训练数据团队在使用外部仓库时是否保留了来源 URL、许可证、提交哈希等元数据。是否存在“平台条款允许但具体仓库作者未授权”的数据来源。只要有一项不确定建议先暂停相关数据处理流程不要带着疑问把数据灌进训练任务。代码训练数据一旦进入模型清除成本和影响范围都很难控制。8. 工程建议与最小行动清单这类服务条款变化真正给开发者带来的提醒不是“某个平台好不好”而是一个更基础的习惯把数据边界当成代码质量的一部分来维护。一次比较稳妥的行动可以概括为下面几件事第一在 Git 仓库中显式声明权利。无论你是否开源都尽量在仓库根部放置许可证或使用说明。没有许可证的公开仓库对作者和潜在用户都是一种模糊状态。如果你不希望代码被外部采集用于 LLM 训练可以用 README 或 LICENSE 文件明确写出限制条件像“允许浏览和克隆但未经授权不得用于训练机器学习模型”这样的表述至少能降低他人误用的可能。第二严格管理密钥和敏感文件。公开仓库是一个长期暴露面历史上任意一次失误提交都可能成为后续模型语料的一部分。建议把密钥扫描加入 Git 提交前的本地钩子同时定期扫描远端仓库。最简单的方式是用 pre-commit 脚本阻止明显的密钥文件进入提交更加完备的方案是引入 gitleaks、trufflehog 等专用工具并把扫描任务接入 CI。第三无论你个人是否同意“代码用于 AI 训练”都要理解协议边界。开源许可证不是万能挡箭牌平台服务条款也不是万能的禁止令。真实世界中代码是否能进入训练集取决于作者授权、许可证条款、平台规则、使用目的和当地法律等多个因素叠加。开发者能做的是让每个项目都有清晰的权利说明同时在采集别人代码时保留完整元数据这样至少能在争议发生时还原决策过程。第四LLM 生产团队要建立可追溯的数据管道。我在前面给出的 Python 粗筛脚本并不是完整的合规方案只是最小值。真正生产级的数据治理还需要把“许可证字段、来源仓库、抓取时间、审批人、风险等级”等字段接入数据库让模型训练启动前可一键生成数据合规报告。这里的核心不是追求一个自动化的“可以/不可以”判断而是要形成一条可回溯的记录链。第五如果项目本身选择留在公共代码托管平台就要接受一个技术现实公开仓库无法被平台单方面加密。如果你在意代码用途最好的方式是让项目在许可证和 README 层面把边界写清楚如果你连“被人读取”都不希望发生那就不要公开。回到 Sourcehut 这次调整本身平台能做的和开发者能做的事情并不完全一样。平台通过服务条款约束大规模数据采集给社区立了一个规则开发者则需要通过自查和规范为自己的项目设定明确边界。服务条款会不断更新技术方案也会继续演进但“先明确授权再处理数据”这条原则不会过时。你可以从今天开始先对自己维护最频繁的仓库跑一遍git remote -v、许可证文件检查和敏感信息扫描把所有结果记录到一个文档里。花不了太多时间却能让项目在外部规则变化时多一份从容。