99 lines
5.0 KiB
Markdown
99 lines
5.0 KiB
Markdown
---
|
||
name: matting-client-and-test
|
||
overview: 实现 pkg/matting 抠图服务 Go 客户端,补齐配置读取并把端口对齐到 8001,然后在本地安装依赖、下载 BiRefNet_lite 模型并启动服务,用 image.png 跑通真实抠图测试。
|
||
todos:
|
||
- id: implement-matting-client
|
||
content: 实现 pkg/matting 客户端 Matting 与 HealthCheck 方法
|
||
status: completed
|
||
- id: wire-matting-config
|
||
content: 接线配置:main.go 读取 MattingModel,config.yaml 端口改 8001
|
||
status: completed
|
||
- id: write-matting-test
|
||
content: 编写 matting_test.go,读取 image.png 并断言 PNG 结果
|
||
status: completed
|
||
dependencies:
|
||
- implement-matting-client
|
||
- id: prepare-matting-service
|
||
content: 创建 venv 安装依赖并启动 8001 抠图服务
|
||
status: completed
|
||
- id: run-real-matting-test
|
||
content: 运行 go test 完成 image.png 真实抠图验证
|
||
status: completed
|
||
dependencies:
|
||
- write-matting-test
|
||
- prepare-matting-service
|
||
---
|
||
|
||
## 用户需求
|
||
|
||
完成 Go 后端 `pkg/matting` 抠图客户端封装,并用仓库根目录下的 `image.png` 进行真实抠图测试。
|
||
|
||
## 已确认的补充约束
|
||
|
||
- 测试方式:本地启动真实抠图服务跑通(安装 torch 等依赖、下载 BiRefNet_lite 模型、启动 8001 服务、用 image.png 真实抠图验证)。
|
||
- 服务端口:将 `config.yaml` 中 `MattingModel.Port` 改为 8001,与 Python 服务默认端口一致。
|
||
|
||
## 核心功能
|
||
|
||
- 实现 `pkg/matting` 客户端,封装对 Python 抠图服务 `POST /matting` 的 multipart 上传调用,返回透明底 PNG 字节。
|
||
- 提供客户端初始化(从全局配置读取 Host/Port)与可指定地址的构造方式,便于测试解耦。
|
||
- 补充主程序配置加载,使 `MattingModel` 配置真正生效。
|
||
- 编写测试用例,读取 `image.png` 作为输入,验证返回结果为合法 PNG 图片。
|
||
- 在本地搭建并启动 Python 抠图服务,完成端到端真实抠图验证。
|
||
|
||
## 技术栈
|
||
|
||
- 语言:Go(复用现有 `net/http`、`mime/multipart`、`context` 标准库)。
|
||
- 参考实现:`pkg/tokenhub/client.go`(Client 结构体 + NewClient 从 global 配置读取 + 带 Timeout 的 httpClient)。
|
||
- 服务端:已有 `thirdparty/matting_server/main.py`(FastAPI,`POST /matting` multipart 字段名 `file`,返回 `image/png`)。
|
||
|
||
## 实现方案
|
||
|
||
### 客户端设计(新建 `pkg/matting/matting.go`)
|
||
|
||
- 采用与 `tokenhub.Client` 一致的轻量客户端模式,不引入第三方 HTTP 库。
|
||
- `Client` 持有 `baseURL` 与 `httpClient`(Timeout 建议 120s,抠图为 CPU/GPU 推理耗时较长)。
|
||
- `NewClient()` 从 `global.MattingModelSetting.Host/Port` 拼接 `http://host:port`。
|
||
- `NewClientWithAddr(host string, port int)` 便于测试与解耦,避免依赖全局配置初始化。
|
||
- `Matting(ctx, imageData []byte) ([]byte, error)`:构造 multipart/form-data,字段名 `file`(与 Python 端 `UploadFile = File(...)` 对齐),发送 POST 到 `/matting`,读取并返回响应体;非 200 时返回带状态码与响应体摘要的错误。
|
||
- `HealthCheck(ctx) error`:GET `/healthz`,用于服务启动后确认就绪与测试前置检查。
|
||
|
||
### 配置接线
|
||
|
||
- `main.go` 的 `setupSetting()` 补 `setting.ReadSection("MattingModel", &global.MattingModelSetting)`,避免 `global.MattingModelSetting` 为 nil 导致 `NewClient` panic。
|
||
- `configs/config.yaml`:`MattingModel.Port` 由 80 改为 8001;移除结构体不支持的 `retry` 字段。
|
||
- `configs/config.example.yaml`:补 `MattingModel`(Host 127.0.0.1 / Port 8001)示例段。
|
||
|
||
### 测试设计(新建 `pkg/matting/matting_test.go`)
|
||
|
||
- 读取 `../../image.png`(测试文件位于 `pkg/matting/` 下)。
|
||
- 使用 `NewClientWithAddr("127.0.0.1", 8001)` 调用 `Matting`。
|
||
- 断言返回字节非空、以 PNG 魔数 `\x89PNG` 开头;将结果写入 `t.TempDir()` 下的文件便于人工核验。
|
||
- 可选:先调用 `HealthCheck` 确认服务就绪,失败时给出明确提示。
|
||
|
||
### 环境准备与真实跑通
|
||
|
||
- 使用独立 venv 隔离 Python 依赖,`pip install -r thirdparty/matting_server/requirements.txt`(CPU 版 torch)。
|
||
- 启动 `thirdparty/matting_server/main.py`(监听 8001),等待 BiRefNet_lite 模型下载与加载完成。
|
||
- 执行 `go test ./pkg/matting/ -run TestMatting -v` 完成真实抠图验证。
|
||
|
||
## 关键代码结构
|
||
|
||
```
|
||
type Client struct {
|
||
baseURL string
|
||
httpClient *http.Client
|
||
}
|
||
|
||
func NewClient() *Client
|
||
func NewClientWithAddr(host string, port int) *Client
|
||
func (c *Client) Matting(ctx context.Context, imageData []byte) ([]byte, error)
|
||
func (c *Client) HealthCheck(ctx context.Context) error
|
||
```
|
||
|
||
## 实现注意事项
|
||
|
||
- multipart 写入需正确 `Close()` 并设置 `Content-Type: multipart/form-data; boundary=...`。
|
||
- 请求与响应体需 `defer resp.Body.Close()`,避免连接泄漏。
|
||
- 错误信息应包含 HTTP 状态码与响应体摘要(截断),便于定位模型侧错误,避免打印大体积二进制。
|
||
- 不引入与现有项目冲突的新架构或第三方依赖,保持 `pkg` 包风格一致。 |