照片策展助手 tanweiping1012-source/PhotoFilterAgent
DeepSeek Harness跑在 DeepSeek Harness 上的照片策展 agent:本地 Vision 分类 + 连拍组比较 +…
30.7/100
综合分
1
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/10/9 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
该插件未发布到 npm,按作者文档从 GitHub 源安装即可(静态检查只覆盖 npm 路径,不代表插件不可用)。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add tanweiping1012-source/PhotoFilterAgent该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:需留意
图例:✓ 通过! 需注意— 未判定 / 无数据· 「未判定」= 本站尚无数据,不代表插件有问题
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
依赖的 DSH / Cordis 模块
@deepseek-ai/schemastery@deepseek-ai/cordis@deepseek-ai/dsh-tools@deepseek-ai/dsh-agent-preset-registry给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
功能亮点
- 本地Vision分类
- 连拍组比较
- 按需视觉打分
README
由 DeepSeek 最新模型翻译生成PhotoFilterAgent
旅行回来几千上万张照片,帮你挑出值得留的那几十张。
它是一个跑在 DeepSeek Harness(DSH)上的智能体:你在网页里跟它说「从这个文件夹挑 20 张」,它在你的 Mac 上把照片过一遍,给你一份名单,你点头之后再把这些照片复制到一个新文件夹。原图只读,永远不移动、不删除、不改名。
- 想直接用 → 快速上手
- 想知道它挑得准不准 → 它能帮你到什么程度
- 想看懂或改代码 → 给开发者的说明
快速上手
你需要有
- 一台 Mac(看人脸和眼睛用的是苹果系统自带的 Vision 框架)
- Xcode 命令行工具(xcode-select --install)、Node.js 22.19 以上或 24 以上、pnpm(npm install -g pnpm)、git、Python 3.9 以上
- 约 6GB 磁盘空间(Python 环境约 2GB,第一次运行会下载约 3.6GB 模型)
- 一个 MiniMax 的 API Key(智能体用它聊天;打开视觉复核时也用它当裁判。
展开完整文档(README 剩余 1 节)
PhotoFilterAgent 旅行回来几千上万张照片,帮你挑出值得留的那几十张。 它是一个跑在 DeepSeek Harness(DSH)上的智能体:你在网页里跟它说「从这个文件夹挑 20 张」,它在你的 Mac 上把照片过一遍,给你一份名单,你点头之后再把这些照片复制到一个新文件夹。原图只读,永远不移动、不删除、不改名。 - 想直接用 → 快速上手 - 想知道它挑得准不准 → 它能帮你到什么程度 - 想看懂或改代码 → 给开发者的说明 快速上手 你需要有 - 一台 Mac(看人脸和眼睛用的是苹果系统自带的 Vision 框架) - Xcode 命令行工具(xcode-select --install)、Node.js 22.19 以上或 24 以上、pnpm(npm install -g pnpm)、git、Python 3.9 以上 - 约 6GB 磁盘空间(Python 环境约 2GB,第一次运行会下载约 3.6GB 模型) - 一个 MiniMax 的 API Key(智能体用它聊天;打开视觉复核时也用它当裁判。换别的模型见 dsh-v4/README.md) 装(一条命令) git clone https://github.com/tanweiping1012-source/PhotoFilterAgent.git cd PhotoFilterAgent PHOTOS=~/Pictures/我的旅行照片 ./install.sh PHOTOS 是允许智能体读取的照片根目录,它只能处理这个目录里的照片。install.sh 会装好 DSH(固定到本项目验证过的 0.2.0-rc.2,不用你另外下载)、编译本地分析程序、建 Python 环境,再把智能体的配置装进 ~/.dsh-photo-filter。每一步都先检查,已经做好的就跳过,可以放心重复运行。 跑 cd ~/deepseek-harness && DSH_HOME=~/.dsh-photo-filter pnpm dsh --profile photo-v4 (install.sh 结束时会打印这条命令,照着复制就行;装的时候用 HARNESS= 换过 DSH 目录的,路径以它打印的为准。)终端会打印一个带 token 的网址(dsh web: http://127.0.0.1:…/?token=…),用浏览器打开。第一次用先填 MiniMax 的 API Key:网页左下角「设置 → 模型 → minimax-cn → 编辑」,或者启动前 export MINIMAX_CN_API_KEY=你的key(两种都有时环境变量优先)。然后直接说: 请从 /Users/你/Pictures/我的旅行照片 里挑 20 张最好的照片 它会依次扫描目录、排序,把名单、这次花了几次模型调用、名单是怎么来的告诉你。之后可以接着问「为什么选了 p012」「换成有氛围的那种」「把这 20 张复制到 ~/Downloads/精选」(智能体会先给你一个确认码,按规则等你回复才复制。码对话模型也看得到,所以这一步靠它守规则,不是开关;复制只在你的电脑上进行,不发照片)。对话里照片只用 p001 这样的编号,真实文件名不进对话。 不想开网页,也可以在命令行跑一次性任务: cd ~/deepseek-harness && DSH_HOME=~/.dsh-photo-filter pnpm dsh --profile photo-v4-headless "从 ~/Pictures/我的旅行照片 挑 20 张最好的照片" 哪里不对劲,先跑自检,它会指出哪一层没装好: bash dsh-v4/doctor.sh 花多少钱、照片会不会发出去 - 默认配置下排序不发照片:三步全在你的电脑上算。花钱的只有对话本身(按你用的模型计费)。 - 让视觉大模型当裁判的「视觉复核」默认关。实测它没让结果变好:同一批 299 张照片,开着它跑 5 次,撞上主人精选 7、5、7、7、6 张,纯本地排序是 7 张,却每次多花约 120 次调用、10 分钟(见第二步与第三步的 A/B)。 - 想自己试,把 profile 里的 stage2Vlm 改成 true(见 dsh-v4/README.md)。打开后,第二步按组从大到小逐组打擂台,最多 60 局(约 120 次调用);每次发 512 像素的整幅小图和 448 像素的人脸特写,拍摄时间、地点、相机型号都剥掉,不发文件名和路径。跑完它会告诉你确切调用次数。 - 你在对话里要求「再精细一点」时,智能体可以用视觉模型再比几对照片。发图之前,网页会弹出审批,写明比几对、约几次调用、发哪几张,你点同意才发;这个问答由 DSH 直接问你,对话模型看不到也替你答不了。命令行模式没有审批界面,就一律不发。 - 不需要你先给它一批「我喜欢的照片」当例子。实测给了例子也没让结果变好,所以默认不要。 另有一种装法:把智能体打成 DSH 的标准插件包,装进你已有的 DSH 网页 profile(还没发布到 npm),见 release/README.md。 它能帮你到什么程度 我们拿一批真实的旅行照片做过测试:309 张人像,照片的主人自己从里面挑出了 20 张最喜欢的。然后让程序在不知道答案的情况下挑一遍(纯本地排序,同样的照片每次给同样的名单。智能体的默认配置跑的就是这一套;命令行排序器要带上 --engine,结果才完全相同。2026-10-01 用当前代码复测): | 让程序挑 | 撞上你心头好的 | 如果闭眼乱挑 | | 10 张 | 2 张(跟运气区分不开,p≈0.13) | 0.6 张 | | 20 张 | 6 张 | 1.3 张 | | 50 张 | 10 张 | 3.2 张 | 挑 20 张时它比乱挑好四倍多,挑 50 张时约三倍,这两档都排除了运气(p < 0.001);挑 10 张只多对一张多,跟运气区分不开。而且挑 20 张里也就 6 张是你真想要的。 所以它干的事是:把 309 张缩到 20 张,让你在这 20 张里挑。 你少翻 289 张,最后拍板的还是你。如果你想要能直接发朋友圈的成品,这个 agent 还在努力迭代。 整体思路:把一件事拆成三步 「帮我挑照片」听起来是一件事,其实是三件,而且难度天差地别: | 阶段 | 详情 | 当前结果 | | 第一步:过滤废片 | 扔掉明显不能要的 | workflow 程序做得好 | | 第二步:局部最优 | 连拍六张留最好的一两张 | workflow(VLM 裁判可选,默认关) | | 第三步:全局最优 | 从剩下的选出最值得留的,帮你直接挑选出朋友圈 | 千人千面,只能帮你缩小范围 | 越往后越主观,程序能帮的忙就越少。 至于第三步的成绩算高还是算低,现在没有参照:没有第二个人从同一批照片里挑过,两个人本来能重合多少,没人知道(见下面第二步的结论)。 第二步的 VLM 裁判默认关闭。第四轮实测:同一批 299 张照片,开着它跑 5 次撞上主人精选 7、5、7、7、6 张,纯本地排序是 7 张,没有一次更高(见下面第二步、第三步的 A/B)。 下面逐步讲每一步用了什么、怎么做的、测出来什么结果。 第一步 · 过滤废片 要解决什么 闭着眼的、糊掉的、低头看地的。这类照片不用你看第二眼。 原理 眼睛睁开的时候,眼睛轮廓是扁的椭圆;闭上的时候被压成一条线。 所以量一下眼睛轮廓的「高 ÷ 宽」,睁着的时候这个值明显大,闭着的时候明显小。 这个方法叫眼睛纵横比(Eye Aspect Ratio),是业界判断眨眼的标准做法,不需要任何联网的模型。 用了什么 苹果系统自带的 Vision 框架(你的 Mac 上本来就有,免费、离线): | 用的功能 | 干什么 | | VNDetectFaceLandmarksRequest | 找出眼睛、鼻子、嘴的轮廓点 | | VNDetectFaceCaptureQualityRequest | 给「这张脸拍得怎么样」打个 0–1 的分 | | VNDetectFaceRectanglesRequest(第 3 版) | 给出头的朝向角度 | 第三个必须显式指定第 3 版,默认版本不返回角度,会静默给出空值。 具体怎么做 ① 眼部检测必须在高清人脸上做。 程序为了快,平时是拿缩到 1024 像素的小图分析的。但这批照片是「人站在雪山前」那种环境人像,人只占画面 8% —— 缩完之后脸只剩 74 像素,眼睛根本看不清。 而原图是 7728 像素宽的,同一张脸有 564 像素,绰绰有余。 所以流程改成: 在 1024px 小图上找到脸在哪(快) ↓ 按人脸大小反推需要多高的分辨率,从原图解出那一档 ↓ 把人脸连同周围 60% 的余量裁出来(要看得见眉毛和脸颊,只给眼眶检不出) ↓ 在这张约 320 像素的高清人脸上重做关键点 判断门槛也从「脸占画面多大比例」换成「脸实际有多少像素」(要求 ≥160)——后者才是关键点可靠性的真正决定因素,前者把分辨率写死了。 结果:能判断眼睛的照片从 32% 涨到 100%。 ② 把「低头」和「闭眼」分开。 低头的时候眼睑会遮住眼球,高÷宽这个值同样会掉下来 —— 程序会把低头误判成闭眼。实测有一张照片主人自己选进精选的低头照就这么被扔掉了。 修法:读头的俯仰角。平视时约 5–7°,明显低头时约 15°。 超过 12° 就报「低头」,不报「闭眼」,也不否决。 (为什么低头不否决?因为实测把低头也当废片扔掉,会误伤照片主人的 2 张精选。 低头确实不太好看 —— 低头的照片只有 5% 被主人接受,全体是 27% ——但这个相关性还不够硬,不足以支持一票否决。) 这一步的验收标准不是准确率,是误杀率 两类错误的代价完全不对称: 少扔了(该删的没删)→ 你多翻几张,没什么损失错扔了(好照片被删)→ 你永远看不到它了,不可逆 所以设计目标是「在零误杀的前提下,能扔掉多少」。 评测结果 能判断眼睛的照片 32% → 100% 扔掉 52 / 309 张误杀(照片主人的 20 张精选) 0 张 ✅ 误杀(照片主人另外标注的可接受照片) 0 张 ✅ 阈值 0.22 正好卡在临界点:放宽到 0.25 就开始误伤 5 张好照片。 第二步 · 局部最优(连拍里留最好的) 要解决什么 你按了六下快门,其实只需要一张。 原理 这六张几乎一模一样 —— 光线一样、构图一样、清晰度一样, 差别只在表情和眼神。差别维度少,反而好比较。 关键的设计选择是:用两两比较,不用各自打分。 因为「给一张照片打 7 分」这件事在我们的实测里非常不可靠:让视觉大模型给同一张照片打两次分,两次的差距,比不同照片之间的真实差距还大。 尺子的抖动超过了要测的东西。 而「这两张哪张更好」就稳得多 —— 有参照物的判断,比凭空打分可靠。 ⚠️ 这个对比有一个已知的混淆,必须说明。 做那次打分实测时,发给模型的是 512px 整幅图,人脸中位数只有 45 像素(最小 21px),100% 低于本项目自己后来定的 96px「能看清脸」门槛。 在看不清眼睛的图上判「眼神好不好」,分数当然抖 —— 那更可能是信号不在图里,而不是「打分这种形式」本身的问题。 现在发的是 448px 人脸特写,但两两比较和打分从未在这个条件下做过头对头对比。 所以上面这句「比较比打分可靠」,目前只是一个合理猜想,不是已验证的结论。 用了什么 ① 认出「哪些照片是一组的」:CLIP 图像特征 CLIP 是 OpenAI 的一个开源模型(用的是 ViT-L/14 这一档),它能把一张照片变成一串 768 个数字,内容相近的照片,这串数字也相近。 两张照片像不像,就看这两串数字的余弦相似度(一个 0~1 的数,越大越像)。 阈值不能写死。 相似度没有绝对刻度 —— 同一个阈值在不同批照片上表现完全不同。我们试过写死 0.86,结果把 309 张照片分成了 2 组。 改成自适应:算出这批照片两两相似度的分布,取 98 分位当阈值(也就是「最像的那 2% 才算一组」),并设一个 0.90 的下限。 聚类用贪心组长法:按文件名顺序遍历,每张照片要么加入某个已有的组,要么自己当新组的组长。不用单链接聚类,因为那会让连拍一路串成一大坨。 分组顺序故意不按分数排。否则换一个打分方式就换一套分组,两次结果没法比较 —— 实测同一份打分只改分组顺序,最终命中会在 3~5 张之间跳。 ② 组内排序:一个专门评人脸的模型 用 topiq_nr-face(来自开源工具包 pyiqa),专门评「这张脸拍得怎么样」。 我们把六个通用美学模型都测了一遍,只有两个能超过随机水平: | 模型 | 判别能力(0.5 = 等于抛硬币) | | liqe | 0.449 | | clipiqa+ | 0.473 | | nima | 0.481 | | topiq_iaa | 0.512 | | musiq-ava | 0.548 | | laion_aes | 0.583 ✅ | | topiq_nr-face | 0.608 ✅ | 有人脸时用 topiq_nr-face,没人脸时退回 laion_aes。 两个融合起来反而更差(我们试过七次融合,没有一次让最终名单变好)。 具体怎么做:擂台赛 本地分最高的那张当擂主 ↓ 其余按分数从高到低依次挑战 ↓ 挑战者赢 → 换他当擂主继续应战平局 → 擂主不下台 ↓ 最后站着的那张当组内冠军 为什么是擂台赛不是全循环? 全循环要比 n×(n-1)/2 次,在这 309 张上是 1114 局;擂台赛只要 n-1 局,共 169 局。 为什么不只比前 3 名? 实测照片主人选中的那张,常常排在组内第 5、6、8 甚至第 14 位 —— 只比前几名会直接漏掉。(组内超过 8 张的会截断,因为超过 8 张的组很少,为它们多花一倍成本不值。) 平局为什么擂主不下台? 平局很常见,不该因为一次没分出高下就换人。 这让结果对判断噪声更稳。 VLM 用在哪一步 只用在这里 —— 擂台赛的每一局,判「这两张哪张更好」。 它不参与打分、不参与分组、不参与最终选片。 「裁判」就是决定这两张哪张好的那个角色,程序里做成了可替换的三种: | 裁判 | 怎么判 | 花钱吗 | | 本地分(默认) | 比 topiq_nr-face 的分数 | 不花 | | VLM(可选,默认关) | 把图发给模型问哪张更好 | 每局 2 次调用 | | 先知 | 直接查人工标注的答案 | 不花,只用于自测 | 发给 VLM 的必须是「整幅小图 + 高清人脸」两张 这是个容易忽略但很致命的细节。 发给模型的整幅小图最长边 512 像素。而这批是环境人像,人只占画面很小一块 —— 人脸在小图上只剩约 30 个像素,309 张里有 91% 不足 48 像素: | 小图长边 | 人脸还剩多少像素 | 能判断表情吗 | | 512px(原来发的) | 30 | ❌ 完全不能 | | 1024px | 61 | ⚠️ 勉强 | | 1536px | 91 | ⚠️ 勉强 | 而提示词却在要求模型判断「笑是不是到眼睛里、有没有僵硬」—— 它根本看不见,只能猜。 所以每张照片发两幅图: 整幅画面(512px) → 看构图、姿态、环境人脸特写(448px) → 看表情、眼神 人脸从原图裁(不是从小图放大),裁的时候连同周围一圈余量,要看得见眉毛和脸颊。这和第一步里本地检测眼睛用的是同一个道理,也是同一个坑:缩小之后脸就没了。 做成可换是为了能分开归因: - 赛制本身对不对?→ 用「先知」跑一遍,应该接近满分 - 裁判判断力如何?→ 换本地分 / 视觉模型对比 混在一起时,一个坏结果没法归因 —— 分不清是赛制错了还是模型不行。 用视觉模型时的四条约束: 1. 只发最长边 512 像素的整幅小图 + 448 像素的人脸裁切(合计约 58KB),拍摄时间、地点、相机型号全部剥掉,不发文件名和路径 2. 正反各问一次(先给 A 后给 B 问一次,调换顺序再问一次)。 两次答案不一致记为「翻覆」,不定赢家,擂主不下台。 (当初这么设计是怕模型偏爱第一张;后来的标定排除了位置偏好,不一致的主因是模型答不稳,见文末补充一节) 3. 模型必须通过结构化输出回答,不接受自由文本;上场前先做一次能力探测,不通过就整轮停下,不允许静默换成别的模型 4. 打哪些局:所有至少两张的组,按组从大到小,逐组打满擂台(每组最多 8 张),打到下一组放不下 60 局为止,后面更小的组就不打了(约 120 次调用)。 不按「会不会进名单」挑组 —— 那种挑法的规则一条都没验证过 这一步做得怎么样 —— 一次 A/B 测试 先说一个前提:这个任务没有唯一答案。 连拍里那几张本来就差不多 ——照片主人隔一段时间自己再挑一遍,也只有 50% 跟上次一样。 所以程序选了另一张,不见得算错。 那怎么判断这一步值不值得做得更好?我们直接量最终交到你手上的照片。 这一步可以让视觉大模型当裁判(默认用不花钱的本地算法)。于是有个很自然的想法: 把「什么算好照片」写清楚给它,再给它看几组你自己挑过的例子,它是不是就能挑得更像你? 跑三遍完整流程来回答。同一批 299 张照片、同一个人的 20 张精选当答案,每次只多给模型一样东西: | | 一份判据 | 你挑过的例子 | | 第一遍 | ✗ | ✗ | | 第二遍 | ✓ | ✗ | | 第三遍 | ✓ | ✓ | 结果:三遍交出的 20 张,完全一样 | | 撞上主人精选 | | | 闭着眼睛乱挑 | 1.3 / 20 | 6.5% | | 不花钱的本地算法 | 7 / 20 | 35% | | 第一遍(什么都不给) | 7 / 20 | 35% | | 第二遍(给判据) | 7 / 20 | 35% | | 第三遍(判据 + 例子) | 7 / 20 | 35% | 不只是张数一样 —— 三个文件夹里的照片,文件名相同,内容逐字节相同。 三遍一共花了约 490 次付费调用,你拿到手的照片一张都没变。 (这一轮把当例子用的那 10 张从候选池里拿掉了 —— 不能拿它见过答案的照片去考它 ——所以这里的基准是 7 张,跟后面第三步那张表里的 6 张口径不同。) 但模型的判断确实变了 翻开中间过程看,三遍的判决差得很明显: | | 第一遍 | 第二遍 | 第三遍 | | 每局给模型看几张图 | 4 张 | 4 张 | 24 张 | | 比了多少局 / 花了多少次调用 | 60 / 120 | 60 / 120 | 60 / 120 | | 判「前一张更好」 | 12 局 | 17 局 | 15 局 | | 判「后一张更好」 | 8 局 | 4 局 | 6 局 | | 判「两张都好」 | 3 局 | 2 局 | 6 局 | | 判「两张都不够格」 | 0 局 | 1 局 | 1 局 | | 正反问两遍,答案不一致(这局作废) | 37 局 | 36 局 | 32 局 | | 认出图上编码的比例 | 98.3% | 98.3% | 100% | | 比的是不是同一批照片对 | 60 局 | 逐对相同 ✓ | 逐对相同 ✓ | 加了判据之后,判「后一张更好」从 8 局掉到 4 局 —— 它的口味确实被影响了。 两行需要解释一下: - 正反问两遍指的是同一对照片,换个顺序再问一次;两次说法不一致这一局就作废。 三遍里作废的都超过一半 —— 模型对这类题本来就答不稳,详见本文末尾那节一致性测试。 - 认出图上编码:每张图上烧了一个 4 位随机码,要求模型抄回来。抄对率 98~100%,说明它确实看到了图,不是在瞎猜。 那为什么照片没变 因为模型的意见到不了最终名单。 第二步只在同一组连拍内部比较,选出这一组的代表。 真正决定「哪些代表能进最终 20 张」的是第三步(下一节讲)—— 而那 20 张,来自 20 个不同的组: 只有 2 张,来自模型比过的组其余 18 张,模型从头到尾没看过 而那 2 张参与的每一局都赢了 —— 按规则,不输就不换人。 所以照片不变,是结构决定的,跟判据和例子写得好不好没关系。 2026-09-12 查出:这一轮的判决当时其实没有传到排序器(代码漏传了一个参数,已修)。 修好后用存档下来的实验组 2(判据 + 例子)的判决重放一遍(0 次付费调用;另两组的判决已经丢了),交出的 20 张一张没变,还是 7/20 ——结论成立,只是证据链比当时以为的短。详见附录。 结论 判据和例子到底有没有用,这一轮答不了。 模型的意见和最终名单之间没有通路 —— 我们量的是一段断开的电线。 这跟「判据和例子没用」是完全不同的两句话。 它也指出了下一步该改哪里:让模型优先去比那些真正决定名单的组,而不是像现在这样比最大的几组。这个改动不用多花钱,但截至 2026-09-30 还没改 ——改了等于让一个还没证明有用的裁判真正影响名单,要当作新实验先定判据再跑。 还有一件事这一轮也答不了:7/20 算好还是算差,现在没人知道。 答案是一个人的选择,两个人挑同一批照片本来重合度就不高 ——除非再找一个人从同一批照片里挑 20 张,否则没有参照系。 完整报告 → 第二步 A/B 实验报告 含全部原始数据、四次失败的执行记录、以及六条被我们自己推翻的判断。 跑之前写死的判据在 CRITERIA-RUBRIC-ANCHORS.md,跑完一个字没改。 第三步 · 全局最优(选出最值得发的) 要解决什么,以及为什么它最难 前两步问的是「这张照片好不好」—— 有客观答案。 第三步问的是「你想留哪张」—— 答案在你脑子里,照片本身没有这个信息。 同一批照片,你和你朋友挑出来的会是两批不同的照片,谁也没错。 原理:与其猜你的口味,不如匹配你的行为 我们比对了「照片主人自己挑的 20 张」和「程序挑的 20 张」的时间分布: 主人自己挑的 最挤的一个时间段里 5 张,覆盖了整趟行程 94% 的时间跨度程序原本挑的 最挤的一个时间段里 14 张 ← 全挤在十几分钟里 人是「这段行程的每一段都挑几张」,程序是「把最好的那一段整段端走」。 而挤在一段里等于自己砍掉了覆盖面 —— 打分信号本来就弱,只作用在照片池的一小部分上更浪费。 具体怎么做 把照片按拍摄顺序切成 10 段 ↓ 每段最多挑 ⌈目标张数 ÷ 10⌉ 张 ↓ 同一个连拍组最多进 2 张 ↓ 第二步选出的组内冠军优先,其次才看分数高低 最后那条很关键:组内名次是第一排序键,全局分数只是第二排序键。 这样每个组的冠军都排在所有组的亚军之前 —— 相当于又加了一层多样性保证。 (我们试过按「拍摄间隔突然变大」来自动切段,实测比固定切 10 段更差。 因为自动切出来的段大小差很多,一个只有 2 张的小场景和一个 40 张的大场景拿到同样的配额,小场景就被过度代表了。) 试过但没成功的:学你的口味 最自然的想法是让你标几张喜欢的,程序学。我们试了,失败。 标注 10~15 张时,融合之后最终名单反而更差,30 次随机划分里只赢了 7 次。 而且有个更根本的问题:普通用户不会先给你一批标注。 一个要求用户先做作业才能用的工具,不是工具。 所以这个功能默认关闭。你给的标注会被记录,但不参与排序 ——程序会如实告诉你「收到了但没用上,因为实测没有收益」,而不是粉饰成「正在学习你的口味」。 评测结果 | 让程序挑 | 撞上主人精选 | 乱挑的期望 | 好多少倍 | | 10 张 | 2 张 | 0.6 | 不算(跟运气区分不开,p≈0.13) | | 20 张 | 6 张 | 1.3 | 4.6 倍 | | 50 张 | 10 张 | 3.2 | 3.1 倍 | 下一步该往哪走? 有个反直觉但数据支持的结论:别直接攻第三步。 第三步的机制一行没改、光靠改进前两步,挑 50 张就从 8 张涨到了 10 张。 前两步是第三步的输入 —— 废片扔得更干净、组内选得更准,第三步的候选池就更好。这比在信号本来就弱的第三层加机制有效得多。 试过:让视觉大模型复核第三步(默认关闭) 第三步挑完之后,可以让视觉大模型在每个时间段里比一次「已经入选的 vs 候补」:两张照片正着问一遍、反着问一遍,候补两次都赢才换人。 我们做了一次完整的 A/B:同一批 299 张照片,四种配置各跑 5 次,一共 20 次有效运行(连同中途出故障作废的,约 3300 次模型调用)。 第二步的视觉复核全程开着,四组只差这一步。同一批照片纯本地排序是 7 张: | 配置 | 5 次的得分(撞上主人精选几张) | 第三步让精选变少 | 变多 | 不变 | | 不开(对照) | 7 · 5 · 7 · 7 · 6 | — | — | — | | 开,不给提示 | 7 · 6 · 6 · 5 · 7 | 1 次 | 1 次 | 3 次 | | 开,给一份挑选标准 | 6 · 7 · 5 · 6 · 4 | 2 次 | 2 次 | 1 次 | | 开,标准 + 8 张范例照片 | 8 · 5 · 7 · 7 · 7 | 1 次 | 2 次 | 2 次 | 「变少 / 变多 / 不变」比的是同一次运行里第三步之前和之后。对照组那一行也是第二步视觉复核开着的:它 5 次之间差 2 张,全部来自第二步裁判的不稳定。 实测有把精选换下去的情况。 开着的 15 次一共换了 36 次人:换上精选 12 次、换下精选 13 次,合起来精选少了 1 张。不开的那组自己五次之间就能差 2 张,开了之后的变化都没超出这个幅度 —— 测不出它有用,加标准、加范例也测不出区别。 为什么没用,是两个原因叠在一起: - 局面不对称:本地排序在第三步已经挑得不差。裁判一共比了 150 局,其中 77 局两张都不是(或都是)主人精选,不影响得分;剩下的局里,57 局是「已选上的就是主人精选」,它判对了不加分、判错就扣分;只有 16 局是「精选还在候补」,判对才加分。 - 裁判不够准、也不够稳:它明确表态、而且恰好一张是主人精选的局里,判对 28/41,大约三分之二,比乱猜好;但扣分的机会是加分的 3.6 倍,三分之二刚好打平。它还有很多局拿不定主意 —— 同一对照片正反各问一遍,只有一半的时候两次答案一致。 还有一条结构上限:每个时间段最多 2 张、同一连拍组最多 2 张,在这批照片上任何第三步机制最多撞上 14 张,到不了 20。 所以它默认关闭。想自己试,开法见 dsh-v4/README.md;完整数据见 端到端 A/B 报告。 整条链路长什么样 你的照片文件夹 │ ├─ 建缓存:缩到 1024 像素,剥掉全部元数据 ├─ 算特征:CLIP ViT-L/14 → 每张 768 个数字 ├─ 算质量:topiq_nr-face(有脸)/ laion_aes(无脸) └─ 苹果 Vision:人脸质量、睁眼程度(高清人脸上测)、头的俯仰角 │ 第一步 闭眼的扔掉(低头的只标记,不扔) │ 第二步 按 CLIP 相似度分组 → 组内擂台赛 → 定出组内名次 │ 第三步 时间段配额 + 同组上限 2 + 组内名次优先 │ └→ 最终名单 命令行排序器全部在你的电脑上跑完,0 次付费调用,同样的照片永远给同样的结果。 第一次约 5 分钟(建缓存),之后每次 1.6 秒。 智能体默认跑的就是这一条。打开视觉复核后多一件事:第二步按组从大到小,逐组请视觉模型当裁判打擂台(最多 60 局、约 120 次调用,要十分钟左右)。模型的答案会变,所以打开后结果不再逐次相同。 只用命令行排序器 不需要 DSH、不需要 API Key、一张图都不发出去。没有对话,也没有视觉模型复核。 你需要有 一台 Mac(要用苹果自带的人脸识别)、Python 3.9 或更新、一个装照片的文件夹。 装 (cd engine && swift build -c release) # 本地分析引擎:看人脸、判断闭眼 cd ranker python3 -m venv .venv && source .venv/bin/activate pip install -r requirements.txt 第一次会下载几个模型(合计约 3.6GB),之后就不用了。 跑 python -m photofilter_rank.cli pick ~/Desktop/我的照片 --target 20 --engine ../engine/.build/release/photofilter --engine 别省:不给它,闭眼的照片挡不掉,人脸质量也退回较弱的指标(同一批 309 张,挑 20 张从 6 张掉到 5 张),排序器会打出警告。带上它,结果和智能体默认配置逐张相同。 程序会打印一份名单。它不会动你的原图 —— 不移动、不删除、不改名、不覆盖。 先小规模试试: python -m photofilter_rank.cli scan ~/Desktop/我的照片 你的照片会去哪里 命令行排序器:哪里都不去。 所有分析、打分、比较都在你自己的电脑上完成,不需要注册,不需要 API Key,不需要联网(除了第一次下模型)。 智能体: 默认配置下排序哪里都不去。会把照片发给视觉模型当裁判的有两种情况:你打开了视觉复核(stage2Vlm / stage3Vlm,这是开关);或者你在网页的审批里同意了「再精细比几对」—— 不点同意(或在命令行模式下),这个工具一张照片都不发。 发的是 512 像素的整幅小图和 448 像素的人脸特写,剥掉全部元数据,不发文件名和路径。 对话模型本身看不到照片,只看得到 p001 这样的编号。原图永远只读。 它做不到的 1. 风景照做不了。 我们单独测了 161 张风景照,六个业界通用的美学评分模型判别能力全在 0.46~0.55 之间(0.5 就是抛硬币)。为了确认这不是没调好,我们又用故意无关的判据做对照 —— 结果「照片里有没有文字」和「是不是黄金时刻的光线」得分一样高。这条路确实走不通。 2. 人像和风景混在一起的文件夹会出问题。 程序按整个文件夹的人脸比例决定用哪套标准,而真实用户的文件夹就是混的。 已知缺陷,还没修。 3. 只在一个人的照片上验证过。 换个人可能表现不一样。 4. 眼睛天生细长的人可能被误判成闭眼。 用的是固定阈值,理论上对不同眼型不公平。我们试过按每个人自己的基准判断,但测试集基本是同一个人,验证不了。目前没有证据证明它是公平的。 5. 让视觉大模型当裁判,至今测不出它有用。 第二步、第三步各做过 A/B,给判据、给范例都测不出区别。一个直接的原因是模型对同一问题答不稳:输入逐字节相同、重复问一遍有 62.8% 改口,详见下面「补充」一节。所以视觉复核默认关。 补充 · VLM 对比评判的一致性测试(2026-09-03) 在「第二步 · 局部最优」里,擂台赛每一局都要问视觉模型「这两张哪张更好」。 我们一直观察到一个现象:同一对照片对调位置问两遍,模型经常给出互相矛盾的答案。 这一轮专门做了一次标定,把可能的原因拆开。79 张照片 / 78 对 / 394 次调用。 结果 | 对调位置问两遍,一致 | 37 / 78 = 47.4% | | 对调位置问两遍,不一致 | 41 / 78 = 52.6% | 不一致的原因,经对照测试逐条排除: | 猜测 | 判定 | 怎么测的 | | 模型偏好某个位置 | 排除 | 同一批照片排在前 72%、排在后 72%,被选中比例完全一样 | | 模型没读到图(图太小、人脸太糊) | 排除 | 图上烧 4 位随机码要求抄回,310/312 抄对;原图 vs 重度模糊副本 10/10 全部选中清晰那张 | | 模型没看图、硬编赢家 | 排除 | 同一张照片的两个副本(差异严格为零)问 36 次,34 次如实答「分不出」 | | 模型对同一问题本身答不稳 | 确认 · 主因 | temperature=0、输入逐字节完全相同的重复调用,62.8% 改变答案 | 关键一条:什么都不改重复问一遍的不一致率(62.8%),高于对调位置的不一致率(52.6%)。 也就是说,观测到的全部不一致都能被「模型答不稳」解释完,不需要位置偏好这个假设。 跨进程复核 38% 与同进程 38% 一致,排除了会话状态残留。 这对本项目意味着什么 - 上面「发给 VLM 的必须是整幅小图 + 高清人脸」那套做法,这次拿到了正面证据:烧码 310/312 抄对、模糊对照 10/10,说明模型确实读到了小图上的细节。 - 擂台赛现在的规则是「正反问两遍,不一致记为翻覆、擂主不下台」。按这个不一致率,一半以上的局实际上由本地分定。这不是判据写得不好,是调用本身不稳定。 - 任何提示词 / 评分标准的 A/B 对比,都必须排在这个问题解决之后 ——在基准线搞清楚之前,小于噪声的差异测不出来(那一轮想测的效应不到 10 个百分点)。 完整报告 → 连拍场景下,VLM 的对比评判一致性测试 报告写给没参与过本项目的读者,含完整方法、逐条对照设计、原始数据口径与已知缺陷。 预登记判据见 INSTRUMENT-CHECK.md,跑之前就写死了。 本报告只测一致性(同一问题问两遍答案稳不稳),不评价模型判得对不对 —— 那是另一个话题。 想再了解一点 | 你想知道 | 去哪看 | | 代码怎么组织、一次运行里发生了什么 | 给开发者的说明 | | 智能体的配置、换模型、DSH 版本 | dsh-v4/README.md | | 第三步视觉复核那次 A/B 的全部数据 | 端到端 A/B 报告 | | 第二步那次 A/B 测试的全部数据 | 第二步 A/B 实验报告 | | 这个工具是怎么一步步做出来的 | 版本演进 | | 怎么判断一个选片程序好不好 | 测量方法 | | 命令行的全部用法 | 排序器说明 | | VLM 对比评判到底稳不稳 | 一致性测试报告 |
预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
tanweiping1012-source/PhotoFilterAgent
跑在 DeepSeek Harness 上的照片策展 agent:本地 Vision 分类 + 连拍组比较 +…
相关插件 · 市场 / 管理
插件精选列表awesome-dsh-plugin/awesome-dsh-plugin
DeepSeek Harness(dsh)插件精选列表
★ 22,225未汉化DSH
73.6
新词雷达zhuyansen/new-term-radar
new-term-radar新词雷达
★ 2,049已汉化MCP
72.8
插件生态导航0xsline/awesome-deepseek-harness
安装 贡献指南 DeepSeek Docs 公开插件目录 Issues
★ 1,188已汉化DSH
72.6
技能注册中心iflytek/skillhub
企业级开源智能体技能注册中心——发布、发现并管理组织内可复用的技能包。
★ 5,370已汉化DSH
71.9
插件市场目录imsai-sh/awesome-deepseek-harness-plugins
面向 DeepSeek Harnessdsh生态的社区插件目录,共收录 13941 个插件含 PR 收录与…
★ 355已汉化DSH
71.8
插件精选清单Anil-matcha/awesome-dsh-plugin
DeepSeek Harnessdsh精选指南——DeepSeek…
★ 1,013已汉化DSH
71.7
这个插件是你维护的吗?
作者本人可认领并核对本条目;认领通过后,详情页会显示「作者已认领」标记。