Commit Graph
135 Commits
Author SHA1 Message Date
xsl 6b24bf0b0d feat(gateway): 被动摘除后进入 60s 隔离期,防探测复活横跳
落地 docs/网关摘除隔离期实施方案.md(9·19 worker 磁盘满事故第 3 层防线):
- pool.py: WorkerState.offline_until + _cooldown_seconds();mark_worker_unhealthy
  摘除时设隔离截止时刻,隔离期内探测成功也不复活(_try_revive 守卫)
- pool.py: 删除从未被调用的死代码 _check_worker_health/_mark_failure
- config.py + config.example.json: health_check.cooldown_seconds(默认 60,0=关闭)
- tests/test_gateway_pool.py: 9 用例(摘除设隔离/隔离内不复活/期满复活/整链路等)

网关机已重启验证:启动日志含"隔离期=60s",/gateway-health 正常。
2026-09-20 23:02:18 +08:00
xsl 88fee6474d docs: 网关摘除隔离期实施方案(摘除后 60s 隔离期,防探测复活横跳)
复盘 9·19 worker 磁盘满事故网关未切换的三层原因;给出本仓库 gateway/
pool.py 的隔离期改动说明(WorkerState.offline_until + 被动摘除冷却 +
探测复活守卫 + 删死代码)、配置项、单测建议、部署/验证/回滚步骤。
worker 侧深检(/health 磁盘水位+依赖探测)已在 ubuntu3090_debug_4090
分支 14562d4 上线。
2026-09-20 21:49:36 +08:00
xsl a0f53ad6ad feat: ComfyUI 默认提示词统一改为「填充遮罩区域的头发,人物增加一点磨皮」
- app.py 各接口 Form 默认值与说明、hairline/service.py _REDRAW_PROMPT、
  hairline/redraw.py _DEFAULT_PROMPT、face_analysis/hairline_grow.py 兜底值
- add_hair.json / add_hair2.json / 0716add-hair-api.json / 0716add-hair.json /
  hair_repaint.json 工作流节点60内置文本
- static 测试页、local_test、benchmark 脚本、接口文档同步
注意:新提示词首次请求会因 CLIP 缓存失效变慢一次,之后恢复
2026-09-16 00:27:33 +08:00
xsl 81101715c8 fix(接口2): female 1..5 换发型分支重绘透传 prompt(此前固定为默认值)
同 59e01d3(ubuntu3090_debug),按 main 代码形态适配:main 的
_call_local_redraw 尚无 prompt/max_side/unet_name 参数,此处只加 prompt。

- _call_local_redraw 增加 prompt 入参并转发给 run_redraw(None 时行为不变,
  仍用内置默认「填充遮罩区域的头发」)
- generate_grow_results_swap 换发型分支调用处补传 prompt;自定义提示词现可
  替换工作流节点60文本(与 male / female 6/7 行为一致);prompt 不进
  change_hair(swapHair),仅作用于最后一步 ComfyUI 发际线带重绘
- 换词后首次请求因缓存失效重载明显变慢(实测 45s vs 命中 8s),后续恢复
- 文档同步:接口文档.md prompt 参数说明更新
2026-09-14 14:40:20 +08:00
xsl b031ce5bbe security: 清除全部公开测试页硬编码的 worker 内部密码
- 16 个测试页移除 X-Internal-Token 硬编码(网关不校验该头,删除零影响,已线上验证)
- 11/12 系列保留 token 输入框仅清空默认值,直连 worker 调试改为手输
- 接入文档 integration.html:补请求体 2MB 上限与 413 说明、HTTP 层错误提示、接口4 7 字段、补全 9/10/99 测试页入口
2026-09-07 00:35:29 +08:00
xsl ebcaff1295 feat(接口4): 新增轮廓类型 contour_type + 提示词防漏键加固
- 豆包提示词追加「轮廓类型(轮廓偏曲/轮廓适中/轮廓偏直)」,_KEY_MAP 映射为 contour_type
- 提示词显式要求包含全部键:实测豆包随机漏键(面部年龄历史 ~26% 缺失),加固后 9/9 次全字段返回
- 同步接口文档/测试页至 7 字段;测试页顺带移除硬编码内部密码
2026-09-07 00:35:24 +08:00
xsl d242e0fc48 fix(gateway): 补 import asyncio —— rebase 到 origin/main 时丢失(origin/main 头部原本无此导入,接口99 的 _if99_lock 需要) 2026-09-06 23:37:41 +08:00
xsl aadab922a9 docs(网关待改动§9): 补无GUI服务器系统库依赖 + torch CPU源安装说明 + 无GPU实测结论 2026-09-06 23:37:01 +08:00
xsl 8b7bfe2023 feat(接口99): 网关改本机实现(纯CPU+单路排队锁),文档同步
- gateway/app.py: 接口99 从盲转发改为本机实现(同接口4 模式):
  显式 Form 三选一 + 惰性导入(缺依赖仅本接口报1007)+ run_in_threadpool
- 单路排队: _if99_lock 全局互斥——串行推理限制 CPU 峰值 +
  规避 MediaPipe 单例线程安全问题;实测 req2≈2×req1 确认串行
- 网关待改动 §9 重写: 本机实现部署步骤 + 依赖清单(mediapipe/opencv/
  numpy<2,torch CPU 版可选——不装则发际线5点null)+ 权重已入git说明
- 实现说明/接口文档/CLAUDE.md 同步: 接口4/99 网关本机实现不转发
- 实测: BiSeNet 13.3M参数/51MB;CPU单核 0.46-0.65s/张;网关路径
  70/70点;worker 路径保留(测试页直连);pytest 15 通过
2026-09-06 23:37:01 +08:00
xsl 63bd265386 feat(接口99): 人脸特殊点检测 + 网关转发路由;文档同步至当前代码
- worker: POST /api/v1/face/special-points,60 个固定编号关键点(6组)
  + 5 个发际线特殊点(沿指定关键点方向射线步进,与 BiSeNet 头发 mask 首次相交;
  双射线取中点,left_left=mid(333→332, 298→284) 与右侧镜像)
- 网关: 同路径盲转发路由(调用频率低,维持转发不占网关依赖;
  响应无 *_base64 字段,改写逻辑天然跳过)
- 测试页 static/test_interface99.html:分组着色小点 + 点ID标注(可开关)
  + 发际线点大圆标签 + JSON 展示
- 文档: CLAUDE.md 重写至当前架构;实现说明/接口文档补接口 9~12/99 契约;
  网关待改动补 §7(9/10已加) §8(11/12待加) §9(接口99部署步骤)
2026-09-06 23:37:01 +08:00
xsl 989f4d0d18 更新 发际线纹理 2026-08-14 21:11:51 +08:00
xsl 8aeca2eb2b Merge branch 'main' of https://git.xiangsilian.com/xsl/hair 2026-08-08 12:02:14 +08:00
xslandClaude 1dc82149b4 feat: 接口1/6 发际线贴近头顶时改为修正而非弃用置null
顶庭(头顶→发际线)<0.7cm 时不再返回 null:
- 上庭 = 0.95×中庭 反推发际线;若越过头顶则顶庭固定 0.7cm(发际线钉在头顶下方)
- hairline_source 新增 "corrected";to_response 始终输出完整四庭
- 标注图始终正常画发际线横线与庭段
- 接口6 三庭逻辑同步,去 discarded 分支

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-08 11:50:18 +08:00
Ubuntu 924bf42a85 save 2026-08-06 21:53:22 +08:00
xslandCursor 481235c1ee feat: 男性发型追加波浪形(wave=7)
接口2/5 male hair_style 增至 1..7,贴图 man_wave.png 纳入四套纹理目录,同步测试页与接口文档。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-06 21:35:57 +08:00
xsl f68049f001 save 2026-08-04 22:39:27 +08:00
xsl 7725e461eb save code 2026-08-04 22:38:42 +08:00
xsl 7d8dfd93b8 save 2026-08-04 22:38:42 +08:00
Ubuntu 9379fbb8f8 save 2026-08-02 01:27:04 +08:00
xsl c20606c003 save 2026-07-31 23:29:07 +08:00
xslandCursor 1ca033f25a feat: 接口1/6 标注层字号上调一档 + 眉心改用 9 号点定位
- annotation: 自适应字号系数 0.017→0.020(下限 8→9),标注文字更大更清晰
- measure: _brow_center 只取 FaceMesh 9 号点(眉间上点),不再与 151 取中点

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-30 23:02:19 +08:00
UbuntuandCursor 87ff2c15d0 chore: 精简生发提示词,去掉磨皮/美颜要求
统一改为「填充遮罩区域的头发」,涉及后端默认值、ComfyUI 工作流 JSON、
测试页、benchmark 脚本、local_test。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-29 15:57:57 +08:00
UbuntuandCursor c536e4ccb1 feat: 屏蔽接口3(B端生发)
网关层直接拦截返回 1007,不再转发到 worker 池;worker 侧路由同步标记
deprecated 并短路返回,保留原参数签名避免老客户端裸 404。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-29 15:57:46 +08:00
xslandCursor 9fb5b486c0 fix(接口4): worker 移除脸型 Mock + face_shape 改本机 MediaPipe 计算
- worker /api/v1/face/features 不再返回假成功数据,直接告知仅网关实现,
  避免本机误打 :8187 被 Mock 结果误导。
- 网关 ark_api_key 加载优先级改为 gateway/config.json 优先(原先误读
  worker_config.json 里的失效 key)。
- 接口4 face_shape 不再采信豆包结果,改用本机 face/face_shape_classifier.py
  (MediaPipe 7 类)计算覆盖;其余 5 项特征仍走豆包。
- 修复 face_shape_classifier 共享 FaceMesh 实例的线程安全问题(加锁),
  避免网关侧接口4 并发请求时崩溃/结果错乱。
- 新增 /api/v1/debug/face-shape 调试接口 + static/test_face_shape.html
  单图调试页(worker 侧)。
- 更新文档:网关机现在也需要 mediapipe/opencv-python/numpy<2。

⚠️ 部署前提醒:网关机需先安装 mediapipe==0.10.14 / opencv-python==4.10.0.84 /
numpy==1.26.4,否则接口4 会返回 1007「分析服务异常」。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-29 14:41:49 +08:00
xsl a748dfd1e5 Merge branch 'main' of http://git.xiangsilian.com:3000/xsl/hair 2026-07-29 13:26:44 +08:00
xslandCursor 587876f8a0 feat: 脸型分类器(7分类)+批量报告生成
基于 MediaPipe 468 关键点提取几何特征,转 z 分数后与各脸型原型加权匹配。
参考分布与原型靶心取自 1093 张测试集的实测画像,不再靠人工设定绝对阈值。

方形脸占比从 29.6% 降到 13.8%,两处原因:一是参考统计量原先只由 50 张样本
估得,相对全量人群有系统性偏移,且三项偏移都在给方形脸加分;二是原型把
aspect_ratio 当作方形脸的主特征,但实测方脸组该值中位仅 +0.16,真正"宽"的
是圆脸(+1.01),等于在拿脸宽找方脸。

原型参数在「6 张基准标注图判定不变、且领先第二名 >=3 分」的约束下搜索得到。
余量约束是必要的:早前一版余量仅 0.008 分,权重写码时四舍五入就会翻转结论。

测试素材(人像照片)与报告输出体积大,一并加入 .gitignore。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-29 13:16:43 +08:00
xsl 81c7a0b55c feat: 接口1/5/6 发际线弃用逻辑(顶庭<0.7cm)
发际线离头顶<0.7cm时判定分割不可靠,弃用发际线:
顶/上庭字段置null、face_total只算中下庭、标注图保留头顶线去掉发际线、
只标中/下庭。eye1/7竖向范围改用眉心。
2026-07-27 23:21:01 +08:00
xsl 218818bdd0 docs: 同步 integration.html / 接口文档.md / test_interface5.html
- 接口5: 补 generate_grow_image 参数说明(接口文档/integration/test_interface5 加控件)
- 接口1/5/6: 补 left_position/right_position 字段(MediaPipe 21/251号点)
- 接口4: features 字段纠正为固定6个英文字段(原误写~42项含中文, 与代码不符)
- 接口7: 完全移除(代码已 deprecated=True 固定返回错误, 文档却当正常接口详述)
- 错误码: 删错误的'1004已废弃'(1004仍用于接口2/5 gender校验), 补 1004 正确描述 + 1009(X-Internal-Token鉴权)
- test_interface5.html: 加 generate_grow_image 复选框
2026-07-24 00:52:14 +08:00
xsl ae47472a63 feat(接口1/5/6): 返回数据新增 left_position/right_position(MediaPipe 21/251号点)
- face_mesh_landmarks.py: 加常量 LEFT_POSITION=21 / RIGHT_POSITION=251
- measure.py: MeasureResult 收 landmarks/宽高, to_response 顶层输出两点(原图像素 {x,y}, 与 landmarks 同格式)
- measure_face 透传 landmarks(签名不变, 6处调用零改动); __init__ 用 None 默认值守卫向后兼容
- 三接口自动生效: 接口1/6 在 data 顶层, 接口5 在 face_measure 对象里(复用同一 to_response)
- 实测坐标左右镜像合理, 44 个现有测试全过无回归
2026-07-24 00:52:14 +08:00
xsl cd8985e93d feat(接口5): 新增 generate_grow_image 参数控制是否生成生发效果图
- app.py: 接口5 路由加表单参数 generate_grow_image(bool, 默认 True)并透传
- hairline/service.py: generate_hairline_pngs 加同名参数, False 时跳过 ComfyUI 生发、grown_png 恒 None
- 默认行为不变(向后兼容); false 时仅返回三档发际线叠图与中心点, 大幅降低耗时
- 网关字节级透传 multipart, 新参数自动到达 worker, 无需改网关
2026-07-24 00:52:04 +08:00
UbuntuandClaude bb9f55e93c feat(gateway): 全局串行化(并发=1) + 记录入参/出参/耗时日志
并发模型从「每worker并发1 + 多worker并行」改为全局串行:同一时间
只处理1个请求,其余排队;多 worker 仅作热备(主 worker 坏了才用备机)。
接口4(face/features) 走豆包、不占 GPU,不纳入串行。

- pool: asyncio.Semaphore(max_global_concurrency=1) + acquire/release_global_slot
  (依赖单进程 uvicorn 部署,已在注释中标注)
- forward: proxy_request 最外层 acquire 全局槽、try/finally 全路径释放;
  入参 multipart 解析挂 request.state;原重试/故障转移逻辑抽到 _dispatch_with_retries
- reqlog(新): 标量入参保留;图片(file/base64)存盘转URL,绝不内嵌base64;
  出参递归摘要截断(landmarks/长串/大数组)
- logging_middleware: RequestLogEntry 加 request_params/response_data,
  jsonl 全量记录;_load_from_logfile 同步映射防重启丢字段;get_stats recent 暴露
- /gateway-health 暴露 global_max/global_busy/global_waiting
- config: dispatch 新增 max_global_concurrency / max_queue_wait_seconds
- tests: test_reqlog + test_gateway_serialization(9 用例)

顺带提交此前未提交的网关统计(daily stats 接口)与耗时看板(api_timing_dashboard.html)。

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-23 22:56:48 +08:00
xslandCursor 98b9108837 perf(接口2): 稳定混跑耗时至12s内 —— ComfyUI插队 + CLIP挪CPU + 提示词全局统一
问题:接口2 与接口3/5 乱序调用时耗时抖动(最差 15~22s)。两个根因:
1. GPU 24G 常驻 21.4G,Flux-2(3.9G) 无法完全驻留显存,每次采样动态换页,
   速度随空闲显存波动(2s~8s);
2. ComfyUI 单队列 FIFO,接口2 排在接口3/5 批量任务后面。

改动:
- hairline/comfyui.py: run() 新增 front 参数,/prompt 带 "front": true 插队到队列最前;
  redraw.py 透传;service.py 接口2 三处调用(女重绘 + 男有/无遮罩)传 front=True,
  接口3/5 仍走普通队列。
- add_hair.json / 0716add-hair-api.json: 节点61 CLIPLoader device default→cpu。
  qwen CLIP(4G) 不再占显存(文本条件缓存常年命中),ComfyUI 显存 8.8G→4.5G,
  Flux-2 完全驻留,采样稳定 ~3-5s。代价:换 prompt 后首次请求 CPU 编码 ~11s(一次性)。
- 提示词全局统一为「填充遮罩区域的头发,皮肤加一点磨皮,再加一点美颜」:
  app.py 4处默认值、service.py _REDRAW_PROMPT、redraw.py _DEFAULT_PROMPT、
  4个工作流节点60内置文案、测试页(test_interface2/3/7/12/12_final)、local_test。
  任何两个不同 prompt 交替提交都会打爆 CLIP 编码缓存(--cache-classic 只存最近一次),
  之前测试页旧文案与服务端不一致导致交替测试每次 +11s。
- app.py: 接口7 /api/v1/hair/grow-v2 下线(业务弃用;add_hair2.json 的 Klein-9b
  会把常驻 Klein-4b 挤出显存)。保留 stub 返回 1007 明确报错,避免裸 404。

实测(1024 档):接口2女 8.5~10s、接口2男 ~5s、接口3 ~7-10s,交替混跑无尖刺。

Co-authored-by: Cursor <cursoragent@cursor.com>

(cherry-picked from ubuntu3090 e7b62f2;已适配 main 分支代码结构:main 无 _REDRAW_PROMPT/_REDRAW_MAX_SIDE 缩图逻辑,front=True 直接加在 _call_local_redraw / generate_grow_results 的调用点;另把 main 独有的 benchmark_*.py 里的 prompt 一并统一)

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-23 01:35:42 +08:00
xslandCursor d4aae9722c fix(pose): 修正正面照被误判为1003(solvePnP翻转解)
ITERATIVE 偶发收敛到相机后方(tz<0),roll≈±180° 超阈值,
把正面照误判为非正面。检测到负深度时回退 SQPNP 重解正深度解。
补充回归测试。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-21 16:46:05 +08:00
xsl f870c20f7f fix(接口3测试页): base64 图片补 data:image/jpeg;base64, 前缀
后端返回的 hair_growth_image_base64 是裸 base64(无 data: 前缀),
原代码直接赋给 <img>.src,浏览器把 base64 当相对路径请求,
拼成 http://host:8187/9j/4AAQ... 发 GET 导致 400 Bad Request。

参照接口2 测试页的写法,手动拼接 data:image/jpeg;base64, 前缀。
后端代码无需改动(接口2 一直正常)。
2026-07-19 15:14:41 +08:00
xsl 6d9e92f710 chore: torch 升级为 2.11.0+cu128 支持 RTX 5090 (sm_120)
原 torch 2.2.2+cu121 只编到 sm_90,在 RTX 5090 上 GPU 算子报
'no kernel image',接口2 因 SegFormer/BiSeNet 跑不动 GPU 而失败。
venv 实际已升级到 torch 2.11.0+cu128 / torchvision 0.26.0+cu128,
此处同步 requirements.txt 让文档与实际环境一致。

numpy 保持 1.26.4(<2,mediapipe/scikit-image 依赖),cu128 兼容。
2026-07-18 16:30:18 +08:00
xsl b58cd4c441 优化为4b 模型 2026-07-18 15:30:31 +08:00
xslandCursor 659c037270 feat: ComfyUI 改走 10.60.74.221,测试页上传图超阈值自动降采样
将 worker 默认 ComfyUI 地址改为远端 10.60.74.221:8188;前端测试页在像素超过 1536000 时等比缩小到 786432 以内。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-17 02:23:35 +08:00
xsl c1bb9614c7 save code 2026-07-17 01:54:04 +08:00
xsl 2b1f528ddd perf: 接口2/12 跳过 viz 叠图生成,省 ~80ms
compute_mask 新增 render_viz 开关(默认 True 保持接口11 行为不变)。
接口2/12 路径(generate_hairline_redraw)传 render_viz=False,跳过 6+ 张
overlay JPG 的 _jpg_b64 编码(baseline/upper/hair_seg/mask/hairline/pushed),
只保留必需的数据字段(_inner_pts/_outer_pts/_upper_mask/mask_pixels)。
2026-07-17 01:37:53 +08:00
xsl d9e96aca87 chore: 重绘服务改走内网 10.60.74.221:8899
gpu_worker 与重绘服务在同一内网,走内网地址(3ms 延迟,比公网更稳定)。
三处调用地址(service.py / test_interface12 / test_interface12_final)
由公网 117.50.183.232 改为内网 10.60.74.221。仍可用 HAIR_LOCAL_REDRAW_URL 覆盖。
2026-07-17 00:57:58 +08:00
xsl 8aed389d79 chore: 重绘服务拆到远程机器 117.50.183.232:8899
接口2 female 后端(generate_grow_results_swap)、test_interface12.html、
test_interface12_final.html 三处重绘调用地址由本机 127.0.0.1:8899 改为远程
117.50.183.232:8899,本机不再跑重绘服务(释放本机显存)。

地址仍可用 HAIR_LOCAL_REDRAW_URL 环境变量覆盖。
2026-07-17 00:44:20 +08:00
xsl c72e3ceda9 asdf 2026-07-17 00:32:13 +08:00
xsl 99ce21334a asdf 2026-07-17 00:26:47 +08:00
xsl 5fbc03a6df feat: 接口12/接口2 发际线重绘改走 local_test 外部 ComfyUI 服务
后端 generate_hairline_redraw 跳过内置 Flux-2 重绘,改为产出 final(接缝融合基底)
+ 纯红遮罩 PNG(redraw_band_mask_base64,遮罩区=(255,0,0,255)、其余全透明)。

接口2 female(generate_grow_results_swap) 取 final+遮罩后在后端调 local_test
(0716add-hair.json 工作流) 完成重绘,结果作为生发图返回;male 分支不变。

测试页 test_interface12.html / test_interface12_final.html 改为两阶段:
先生成 final+纯红遮罩,再前端调 local_test 重绘并展示;color_match 默认不勾选。

local_test/app.py 加 CORS 头(OPTIONS 预检),支持浏览器跨域直连。
2026-07-17 00:00:15 +08:00
xsl 0bbb15d668 添加服务 2026-07-16 22:57:12 +08:00
xsl 632e75317b 接口6 增加字段 2026-07-16 12:38:10 +08:00
xsl 1cd4115b26 Merge branch 'main' of http://git.xiangsilian.com:3000/xsl/hair 2026-07-16 09:38:53 +08:00
xslandCursor e8a2c5a8a1 fix: 日志目录去掉硬编码 /home/xsl,改为基于仓库根解析(支持 HAIR_LOG_DIR 覆盖)
worker 部署到 /home/ubuntu 等其他路径时,原硬编码 /home/xsl/hair/log
会导致 Permission denied。改为相对仓库根,兼容多机部署。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-16 08:07:03 +08:00
xsl 0f8a7e27c0 部署线上5090时候的改动git commit -m 部署线上5090时候的改动。 2026-07-16 07:54:07 +08:00
xsl 12f34c44f2 修改发型为最终发型 2026-07-16 00:22:54 +08:00