news 2026/10/17 19:29:40

基于GitHub Actions自动化聚合500个AI模型动态的网站搭建实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于GitHub Actions自动化聚合500个AI模型动态的网站搭建实践

1. 从一条推送说起:为什么要盯住500个AI模型

我平时有个习惯,早上泡咖啡的时候会顺手刷一遍模型发布列表。这个习惯大概从两年前开始,那时候能叫得上名字的模型也就几十个,手动翻一翻还能跟得上。到了今年,情况完全变了——几乎每天都有新模型冒出来,有开源的、有闭源的,有做文本的、有做图像的、有专门跑在端侧的,还有一堆微调版本和量化版本。光是记清楚哪个模型叫什么、什么时候发的、参数多大、支持什么模态,就已经很费脑子了。

真正让我下决心动手做这个网站的,是连续两次踩坑。第一次是团队要选一个开源模型做本地推理,我凭印象推荐了一个,结果同事一查,那个模型已经出了三个后续版本,我推荐的那个在长文本任务上早就被超越了。第二次更尴尬,客户问某个模型支不支持工具调用,我拍脑袋说支持,结果人家翻出官方文档,那个能力是下一个版本才加的。这两件事让我意识到,靠人脑记忆和零散收藏夹来跟踪模型动态,已经彻底不够用了。

所以我做了个网站,核心目标就一句话:把500个AI模型的动态集中到一个地方,自动更新,随时可查。它解决的不是什么高深问题,就是信息聚合和变化追踪。适合谁看呢?我觉得三类人最需要:一是做AI应用开发的工程师,选型的时候要横向对比;二是技术团队的负责人,要判断某个方向值不值得投入;三是像我这样喜欢折腾本地部署的爱好者,想知道哪个模型又出了新量化版本。这个网站不生产模型,它只是模型动态的搬运工和整理者。

2. 整体设计思路:为什么是“聚合+自动化”而不是“人工编辑”

2.1 核心矛盾:信息源太多,人工维护必死

一开始我想得很简单,不就是列个表格吗,手动填一填不就行了。结果第一周我就放弃了。模型动态的来源太分散了:有的在代码托管平台的发布页,有的在模型社区的模型卡,有的在官方博客,还有的只在技术报告里提一句。更麻烦的是更新频率完全不可预测,有的模型半年不动,有的模型一周发三个版本。如果靠人工去每个源头检查,那这个网站还没上线我就先累死了。

所以整体设计的第一原则就是:能自动化的绝不手动。网站本身只做三件事——抓取、存储、展示。抓取交给定时任务,存储交给结构化数据库,展示交给前端页面。我作为维护者,只需要在初期配置好数据源和解析规则,后面基本不用天天盯着。

2.2 方案选型:为什么用GitHub Actions而不是自建服务器

这里要解释一个关键选择。很多人做这类聚合网站,第一反应是租一台服务器,跑个定时脚本。我一开始也这么想,但算了一笔账就放弃了。一台最便宜的云服务器,一年也要几百块,还要自己处理系统更新、依赖升级、进程守护、日志清理。对于我这种个人项目来说,运维成本太高了。

GitHub Actions的好处在于,它本身就是为自动化任务设计的。我可以把抓取脚本放在仓库里,配置一个定时工作流,让它每隔几小时跑一次。跑完的结果直接提交回仓库,或者推送到数据库。整个过程不需要我维护任何服务器,也不需要担心脚本挂了没人重启。而且Actions的免费额度对于这种轻量级抓取任务来说完全够用,一天跑几次,一个月下来也用不了多少额度。

当然,这个方案也有代价。Actions的运行环境是临时的,每次跑都是一个干净容器,所以不能在里面存状态。我的做法是把所有需要持久化的数据都放到外部存储里,脚本本身只负责“读源、解析、写库”这三步。这样即使某次任务失败,也不会影响已有数据。

2.3 数据模型:怎么描述一个“模型动态”

在设计数据库表的时候,我纠结了很久。一个模型动态到底包含哪些字段?最开始我想得很复杂,什么训练数据、评测分数、推理成本都想塞进去。后来发现,字段越多,抓取难度越大,因为很多信息在源头就不完整。最后我定了一个最小可用集合:

字段名说明是否必填
model_name模型名称是
source来源平台标识是
release_date发布日期否
version版本号或标签否
modality支持模态(文本/图像/音频等)否
parameter_size参数量描述否
license许可类型否
url原始链接是
first_seen首次抓取时间是
last_updated最后更新时间是

这个表结构的好处是,即使某个字段抓不到,也不影响整条记录入库。前端展示的时候,缺失字段就显示“未知”或者留空,不会报错。而且first_seen和last_updated这两个时间戳非常关键,它们能让我知道哪些模型是新出现的,哪些是最近有更新的。

3. 核心细节解析:抓取、解析、去重、展示

3.1 抓取策略:不同来源用不同节奏

500个模型不是来自一个地方,所以抓取策略也不能一刀切。我把来源分成了三类,每类用不同的抓取频率和解析方式。

第一类是代码托管平台的发布页。这类来源的特点是结构相对规整,有固定的API或者页面结构。对于这类来源,我直接用平台的API来拉取发布列表,拿到JSON之后解析出模型名称、版本号、发布时间和描述。API的好处是稳定,不容易因为页面改版而失效。

第二类是模型社区的模型卡页面。这类来源的结构差异很大,有的模型卡写得很规范,有的就几行字。对于这类来源,我用的是HTML解析加启发式规则。比如先找页面里有没有“Model Details”这样的标题,有的话就提取下面的键值对;没有的话就退而求其次,从页面标题和描述里提取模型名称和基本信息。

第三类是官方博客和技术报告。这类来源最难抓,因为格式完全不固定。我的做法是只抓标题和摘要,然后用关键词匹配来判断是不是模型发布相关的文章。如果是,就提取标题里的模型名称和发布日期,正文内容不抓,只保留链接。

注意:抓取频率不要设得太高。我一开始设了每半小时跑一次,结果有些平台会返回频率限制错误。后来改成每三小时跑一次,稳定多了。对于更新不频繁的来源,甚至可以一天跑一次。

3.2 解析难点:模型名称的归一化

这是整个项目里最头疼的问题。同一个模型,在不同来源里的写法可能完全不一样。比如一个模型叫“XYZ-7B”,在代码托管平台上可能写成“xyz-7b”,在模型社区里可能写成“XYZ 7B”,在博客里可能写成“XYZ七B”。如果不做归一化,数据库里就会出现一堆重复记录。

我的做法是分两步走。第一步是规则归一化:把所有名称转成小写,去掉空格和特殊符号,把中文数字转成阿拉伯数字。第二步是模糊匹配:对于归一化之后仍然不完全一样的名称,用编辑距离来判断是不是同一个模型。如果编辑距离小于某个阈值,就认为是同一个模型的不同写法,合并成一条记录。

这个阈值我调了好几次。设得太小,会把不同模型合并;设得太大,又会漏掉真正的重复。最后我定的是编辑距离不超过2,并且要求两个名称的长度差不超过3。这个参数不是理论最优,但在我实际抓取的数据上表现最稳。

3.3 去重与更新:怎么判断“这条动态是不是新的”

去重逻辑其实比想象中复杂。不是简单地把名称一样的去掉就行,因为同一个模型会有多个版本。我的判断逻辑是这样的:

  • 如果model_name和version都相同,认为是同一条记录,只更新last_updated。
  • 如果model_name相同但version不同,认为是同一个模型的新版本,插入新记录。
  • 如果model_name不同但url相同,认为是同一来源的重复抓取,忽略。
  • 如果model_name和url都不同,但归一化名称高度相似,进入人工审核队列。

最后这条“人工审核队列”是我后来加的。因为完全自动化的模糊匹配总会有误判,与其让它自动合并出错,不如先标记出来,我每周花十分钟过一遍。这个设计看起来不够“全自动”,但实际用下来,它避免了很多脏数据。

3.4 前端展示:怎么让500条数据不吓人

500个模型如果全部平铺在一个列表里,用户根本看不过来。所以前端我做了三层过滤和两种视图。

第一层过滤是按模态筛选,文本、图像、音频、多模态,点一下就能缩小范围。第二层是按时间筛选,最近一周、最近一月、最近三月。第三层是按来源筛选,只看某个平台的动态。

两种视图分别是时间线视图和表格视图。时间线视图适合快速浏览最近发生了什么,表格视图适合横向对比多个模型的参数。默认打开的是时间线视图,因为大部分用户进来就是想看看“最近有什么新东西”。

实操心得:前端不要做太重的框架。我用的是最基础的HTML加一点原生JavaScript,数据通过静态JSON加载。这样页面加载速度非常快,而且部署简单,直接扔到静态托管服务上就行。

4. 实操过程:从零搭建的完整步骤

4.1 第一步:确定数据源清单

在写任何代码之前,我先花了两天时间整理数据源。具体做法是打开一个空白表格,列出我能想到的所有模型发布渠道,然后逐个验证是否可抓取。验证的标准有三个:页面是否能正常访问、是否有稳定的结构、是否允许自动化访问。

最后我筛出了大约20个核心来源,覆盖了大部分主流模型。这个数量不是越多越好,因为每增加一个来源,就多一套解析规则要维护。我的原则是:宁可少抓几个小众来源,也要保证核心来源的稳定性。

4.2 第二步:搭建抓取脚本

抓取脚本我用的是Python,主要考虑是生态成熟,处理HTTP请求和HTML解析的库都很完善。脚本的结构很简单,就是一个来源一个函数,每个函数负责拉取数据并返回统一格式的字典列表。

import requests from bs4 import BeautifulSoup def fetch_source_a(): url = "https://example.com/api/releases" resp = requests.get(url, timeout=30) data = resp.json() results = [] for item in data: results.append({ "model_name": item.get("name"), "version": item.get("tag_name"), "release_date": item.get("published_at"), "url": item.get("html_url"), "source": "source_a" }) return results

每个函数都加了超时和异常处理,因为网络请求失败是常态,不能让一个来源的失败影响整个任务。所有函数跑完之后,把结果合并成一个列表,交给下一步处理。

4.3 第三步:配置GitHub Actions工作流

工作流文件放在仓库的.github/workflows目录下,核心配置就是定时触发和运行脚本。

name: model-tracker on: schedule: - cron: '0 */3 * * *' workflow_dispatch: jobs: fetch: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v5 with: python-version: '3.11' - name: Install dependencies run: pip install requests beautifulsoup4 - name: Run fetch script run: python fetch.py - name: Commit and push run: | git config user.name "tracker-bot" git config user.email "bot@example.com" git add data/ git diff --quiet && git diff --staged --quiet || git commit -m "update model data" git push

这个配置里有两个细节值得说。一是workflow_dispatch,它允许我手动触发任务,调试的时候非常方便。二是提交前的git diff检查,如果没有变化就不提交,避免产生一堆空提交记录。

4.4 第四步:数据存储与前端对接

抓取结果我存成了JSON文件,按日期分目录存放。这样做的好处是版本可控,每次更新都能看到差异。前端加载的时候,先读一个索引文件,找到最新的数据文件,然后再加载具体内容。

async function loadLatestData() { const indexResp = await fetch('/data/index.json'); const index = await indexResp.json(); const latest = index.files[index.files.length - 1]; const dataResp = await fetch(`/data/${latest}`); return await dataResp.json(); }

这个方案的好处是简单,不需要数据库,也不需要后端服务。坏处是数据量大了之后,JSON文件会很大。不过500个模型的元数据,压缩之后也就几百KB,完全在可接受范围内。

4.5 第五步:部署与域名配置

前端页面我托管在一个静态托管服务上,绑定了一个自己买的域名。部署流程就是推送代码,托管服务自动构建和发布。整个过程不需要手动上传文件,也不需要配置服务器。

注意:静态托管服务通常有缓存,更新数据之后可能需要等几分钟才能生效。如果着急看到最新数据,可以在URL后面加一个时间戳参数来绕过缓存。

5. 常见问题与排查技巧实录

5.1 抓取失败:怎么快速定位是哪个来源出了问题

抓取任务跑失败是家常便饭。我的排查流程是这样的:先看日志里哪个来源报了异常,然后单独跑那个来源的抓取函数,看是网络问题还是解析问题。如果是网络问题,通常是超时或者频率限制,等一会儿再试就行。如果是解析问题,通常是页面结构变了,需要更新解析规则。

为了提高排查效率,我在脚本里给每个来源都加了独立的日志前缀。这样在Actions的日志里搜索来源名称,就能快速定位到相关记录。

5.2 数据重复:为什么会出现同一条记录多次入库

前面提到过去重逻辑,但实际运行中还是会出现重复。最常见的原因是同一个模型在不同来源里的名称差异太大,模糊匹配没识别出来。另一个原因是抓取时间间隔太短,同一个来源被连续抓了两次,而第二次抓取时页面还没更新,导致旧数据被当成新数据插入。

解决方法是加一个“抓取窗口”判断:如果某条记录的url和上次抓取的一样,并且last_updated在24小时以内,就跳过不处理。这个简单的规则过滤掉了大部分误报。

5.3 页面加载慢:500条数据怎么优化

一开始我把所有数据一次性加载到前端,结果页面打开要好几秒。后来改成了分页加载,每次只加载50条,滚动到底部再加载下一批。同时把JSON文件做了压缩,去掉了不必要的空格和换行。

还有一个优化是给数据加了索引。前端加载的时候,先加载一个轻量的索引文件,里面只有模型名称和ID,用户点击某个模型再加载详情。这样首屏加载时间从几秒降到了几百毫秒。

5.4 常见问题速查表

问题现象可能原因排查方法解决措施
任务失败,日志显示超时网络不稳定或来源限流单独运行该来源脚本增加超时时间,降低抓取频率
数据出现重复记录名称归一化不彻底检查归一化后的名称调整模糊匹配阈值
前端页面空白JSON文件路径错误检查浏览器控制台修正索引文件路径
数据更新延迟静态托管缓存查看响应头缓存时间加时间戳参数或手动刷新缓存
某个来源长期无数据页面结构改版手动访问来源页面更新解析规则

实操心得:不要追求100%的自动化。我每周会花十分钟看一眼人工审核队列,处理那些模糊匹配拿不准的记录。这十分钟的投入,比调半天算法参数划算得多。

6. 这套东西还能怎么扩展

网站上线之后,陆续有朋友问能不能加一些功能。我挑了几个成本低、价值高的方向在考虑。

第一个方向是模型对比。现在只能看单个模型的详情,如果能选两个模型并排对比参数和版本历史,对选型会很有帮助。技术上不难,就是把两个模型的详情数据加载到同一个页面里做差异高亮。

第二个方向是变更提醒。现在用户需要主动来网站看,如果能订阅某个模型的更新,有变化的时候发个通知,会更省心。实现方式可以是邮件订阅,也可以是生成一个RSS feed,让用户自己用阅读器订阅。

第三个方向是数据导出。有些用户想把数据导到自己的表格里做进一步分析。这个最简单,加一个导出CSV的按钮就行。

不过这些扩展我都不着急做。我的原则是先把核心的抓取和展示做稳,再考虑锦上添花。毕竟这个网站的价值在于数据准确和更新及时,功能再多,数据不准也没人用。

最后分享一个我在维护过程中体会最深的小技巧:给每个数据源写一个健康检查脚本。这个脚本不抓数据,只检查来源页面是否能正常访问、返回状态码是否正常。我把它放在抓取任务之前跑,如果某个来源健康检查不通过,就跳过它的抓取,避免因为一个来源的问题导致整个任务失败。这个小小的前置检查,让我的任务成功率从大概七成提升到了九成以上。

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

结构化表达:用可执行图表驱动跨角色对齐与工程落地

1. 项目概述:这不是画图,是用结构化思维解决真实问题的底层能力“diagram-design”这个标题乍看像一个工具操作指南,但在我带过的几十个跨领域项目里,它从来不是关于“怎么把流程图画得好看”,而是关于如何把模糊的业务…

作者头像 李华
网站建设 2026/10/17 19:25:54

树莓派入门避坑指南:系统烧录、GPIO与网络配置全覆盖

简介:《树莓派用户指南:从入门到实践》是一本由树莓派基金会创始人埃本厄普顿和加雷斯哈弗克里合著的电子书,以PDF格式提供,面向零基础用户和已有一定经验的开发者,覆盖从树莓派开箱设置、系统初始化到高级配置的完整学…

作者头像 李华
网站建设 2026/10/17 19:25:39

HTML5 Notification API 桌面通知实战:权限、参数与去重全解析

1. 桌面通知到底是个什么东西第一次在浏览器里看到右下角弹出系统级的通知卡片,我以为是装了什么插件。后来翻代码才发现,这玩意儿是浏览器原生能力,一行new Notification(标题)就能调起来。它不依赖任何第三方库,不需要引入外部脚…

作者头像 李华
网站建设 2026/10/17 19:25:03

视觉目标跟踪丢失后如何重定位:从判定到工程落地

1. 从“跟丢”说起:为什么重定位是视觉跟踪的必修课做过视觉目标跟踪的人都有一个共识:跟踪算法在理想场景下跑得再漂亮,都不如它在目标丢失后能不能自己找回来更能说明问题。我最早接触跟踪任务时,天真地以为只要把检测器做好、把…

作者头像 李华
网站建设 2026/10/17 19:22:16

新型储能白皮书怎么读?从装机口径到项目测算的实操指南

简介:《中国新型储能行业发展白皮书》由储能领跑者联盟发布,是一份面向能源行业分析师、企业决策者、政策研究者及投资者的行业研究报告,旨在厘清碳中和背景下新型储能的市场机遇与技术挑战。内容涵盖全球源网侧、工商业、户用储能市场概况&a…

作者头像 李华