feat(drivers): add huggingface cloud storage driver - #2799
Conversation
实现了HuggingFace仓库作为存储驱动的完整功能,支持模型/数据集/空间三种仓库类型,支持代理配置、LFS大文件上传、目录创建和删除等操作,同时在drivers/all.go中注册该驱动。
重新导入三个编写过程中因意外丢失的存储驱动
清理仓库中不再需要的.tmp/CloudPaste和.tmp/OpenList-Frontend临时子模块
已改正,感谢提醒 |
|
HF仓库已经支持S3访问了,数据集还不支持 |
所以主要是支持模型和数据集,只是对接API的话顺手做全可能更好,毕竟小白不一定知道HF支持S3,S3配置也有点难度。 |
我看官方说法是桶支持,但标准的模型、数据集几乎不支持 |
确实,不过我试了一下,桶目前是和数据集和模型共享存储空间的 |
当这吃的是私人仓库空间好像,我打算是白嫖公共空间用来挂载AI数据 |
xrgzs
left a comment
There was a problem hiding this comment.
go fmt跑一下,代码格式有问题- 自建请求客户端,无适配OpenList Conf代理配置逻辑,建议先检查一下是否真的需要,否则直接用base中的即可。(让AI看一遍
internal/net) - 文档弄一下:https://github.com/OpenListTeam/OpenList-Docs
| return d.lfsUploadAndCommit(ctx, tmp, filePath, fileName, sha256Hex, size, up) | ||
| } | ||
| return d.streamCommit(ctx, tmp, filePath, fileName, size, up) | ||
| } |
There was a problem hiding this comment.
全量落盘,未使用框架的流式缓存工具 internal/stream.CacheFullAndHash,建议整改
| // hfClient is a dedicated HTTP client for HF API requests, | ||
| // separate from base.HttpClient to avoid keep-alive connection reuse issues. | ||
| func hfClient() *http.Client { | ||
| return &http.Client{ | ||
| Timeout: 30 * time.Minute, | ||
| Transport: &http.Transport{ | ||
| TLSClientConfig: &tls.Config{InsecureSkipVerify: false}, | ||
| DisableKeepAlives: true, | ||
| MaxIdleConns: 0, | ||
| }, | ||
| } | ||
| } |
| // s3Client returns a shared HTTP client for S3 LFS uploads. | ||
| func s3Client() *http.Client { | ||
| s3HTTPClientOnce.Do(func() { | ||
| s3HTTPClient = &http.Client{ | ||
| Timeout: 30 * time.Minute, | ||
| Transport: &http.Transport{ | ||
| TLSClientConfig: &tls.Config{ | ||
| InsecureSkipVerify: false, | ||
| MinVersion: tls.VersionTLS12, | ||
| }, | ||
| DialContext: (&net.Dialer{ | ||
| Timeout: 30 * time.Second, | ||
| KeepAlive: 30 * time.Second, | ||
| }).DialContext, | ||
| ForceAttemptHTTP2: false, | ||
| MaxIdleConns: 2, | ||
| MaxIdleConnsPerHost: 2, | ||
| IdleConnTimeout: 90 * time.Second, | ||
| ResponseHeaderTimeout: 5 * time.Minute, | ||
| ExpectContinueTimeout: 5 * time.Second, | ||
| }, | ||
| } | ||
| }) | ||
| return s3HTTPClient | ||
| } |
文档已提交 OpenListTeam/OpenList-Docs#351 hfClient() 与 s3Client() 的自定义 Transport 现在都会调用 netutil.SetProxyIfConfigured(transport)(internal/net/util.go 中定义),读取 conf.Conf.ProxyAddress 并设置 transport.Proxy,因此两个客户端都会遵循 OpenList Conf 中配置的代理。 关于"是否真的需要自定义客户端,还是直接复用 base 中的":我们排查了 internal/net 和 drivers/base/client.go,结论是这两个客户端有必要保留,理由如下: base.HttpClient(即 net.NewHttpClient())默认带 DisableKeepAlives=false、开启 HTTP/2,且无 S3 上传所需的连接参数定制; |
|
感谢 review,三条意见都已在提交 752f237 中处理完毕:
关于"是否真的需要自定义客户端、能否直接复用 base.HttpClient":排查 internal/net 与 drivers/base/client.go 后,结论是保留自定义客户端是合理的: base.HttpClient(即 net.NewHttpClient())不提供 DisableKeepAlives、禁用 HTTP/2、以及面向 S3 上传的连接参数定制;
|
Summary / 摘要
实现了 HuggingFace 仓库作为 OpenList 存储驱动的完整功能。
用户可感知的变化
HuggingFace驱动类型,支持模型(model) / 数据集(dataset) / 空间(space) 三种仓库repo_id(必填)、api_token、ref(分支/标签/commit SHA,默认 main)、repo_type(默认 model)、hf_proxy(代理地址)重要实现变化
新增 5 个文件:
drivers/huggingface/driver.go(核心逻辑)、meta.go(驱动元数据)、types.go(API 类型)、util.go(工具函数),以及在drivers/all.go注册LFS 上传流程:saveStream 写临时文件 + SHA256 → preupload 检测 → LFS batch API 获取 S3 presigned URL → PUT 直传 S3(支持 fallback 到 POST)→ verify(可选)→ NDJSON commit 提交 lfsFile 引用
小型文件流式提交:io.Pipe + base64 编码 + NDJSON 内嵌,避免写临时文件
自定义 HTTP 客户端:
s3Client()单例共享连接池(5 分钟 ResponseHeaderTimeout),hfClient()独立客户端(DisableKeepAlives)用于 HF APIcontext.WithoutCancel保护 S3 上传 body 不被任务取消中断过滤未签名的
x-amz-*头部,避免 S3 403(X-Amz-SignedHeaders=host)saveStream 增加
fi.Size() != stream.GetSize()校验,提前捕获数据不完整This PR has breaking changes.
/ 此 PR 包含破坏性变更。
This PR changes public API, config, storage format, or migration behavior.
/ 此 PR 修改了公开 API、配置、存储格式或迁移行为。
This PR requires corresponding changes in related repositories.
/ 此 PR 需要关联仓库同步修改。
Related repository PRs / 关联仓库 PR:
Related Issues / 关联 Issue
无
Testing / 测试
go build -o OpenList.exe .— 编译通过,生成 ~124MB 可执行文件Checklist / 检查清单
/ 我已阅读 CONTRIBUTING。
/ 我确认此贡献符合仓库许可证、贡献规范和行为准则。
gofmt,go fmt, orprettierwhere applicable./ 我已按适用情况使用
gofmt、go fmt或prettier格式化变更代码。/ 我已在适用情况下请求相关维护者或代码所有者审查。
AI Disclosure / AI 使用声明
/ 此 PR 包含 AI 辅助内容。
Tools used / 使用工具:
Usage scope / 使用范围:
Code generation / 代码生成
Refactoring / 重构
Documentation / 文档
Tests / 测试
Translation / 翻译
Review assistance / 审查辅助
I have reviewed and validated all AI-assisted content included in this PR.
/ 我已审核并验证此 PR 中的所有 AI 辅助内容。
I have ensured that all AI-assisted commits include
Co-Authored-Byattribution./ 我已确保所有 AI 辅助提交都包含
Co-Authored-By归属信息。I can reproduce all AI-assisted content included in this PR without any AI tools.
/ 我可以在没有任何 AI 工具的情况下重现此 PR 中包含的所有 AI 辅助内容。
如果需要我调整措辞或增减内容,直接说。