Merge branch 'meta2'

Co-Authored-By: Claude Fable 5.1 <[email protected]>

# Conflicts:
#	CHANGELOG.md
This commit is contained in:
root committed 2026-09-30 18:40:42 +08:00
commit 6f5371be2d
23 files changed
+2615 -323

No files matched your search

+1 -1
View File
@@ -165,7 +165,7 @@ NFO / 图片投影、身份巡检与挂载根因聚合、HTTP 失败自动切浏
- **Agent 快捷面板与会话排版(AGUI-2,用户 2026-09-29)**:抽屉内「当前/历史」Tab,历史列表可搜索筛选并在抽屉内打开(可续跑),"在页面打开"次要;会话页:阅读列宽、同回合分组、工具卡默认一行折叠、步骤清单改右侧栏/顶部折叠条不再 sticky 遮挡、预算在右栏底、长汇报折叠、输入区固定底部。
- **凭据统一注入浏览器(BR-2,用户 2026-09-29)**:打开站点浏览器会话时服务端把账号 Cookie(手填或自动登录得到的)注入 camofox profile,截图/桌面模式无需再登录;交还/关闭/定时从浏览器回写 Cookie 到凭据存储,HTTP 抓取/RSS/快照共用;账号显示登录态来源与时间;Cookie 不进日志/模型。
- **站点详情页抓取(用户 2026-09-29,憨憨 details.php)**【INT-2 已做,见 runbook/sites.md「详情页扩展内容」】:`SiteReleaseDetail` 扩展简介/MediaInfo/截图(经图片代理)/IMDb·豆瓣·TMDB ID/文件清单/标签/上传者;只按需抓(点开详情或评估缺字段),kv_cache 24 小时;详情抽屉展示;IMDb/豆瓣 ID 作为强证据进身份解析(TMDB find)。
- **META-1 后续**:真机 4 条短剧在白名单站点均无结果——扩大抓取白名单(短剧平台/百科类/豆瓣搜索快照/Bing 摘要模式),必要时只用搜索摘要抽字段不抓页;记录命中率。
- **META-1 后续**:真机 4 条短剧在白名单站点均无结果——扩大抓取白名单(短剧平台/百科类/豆瓣搜索快照/Bing 摘要模式),必要时只用搜索摘要抽字段不抓页;记录命中率。【META-2 已做(分支 meta2,2026-09-30):来源分类 + 各来源抽取器 + 置信度合并、豆瓣与聚合站只用摘要、robots.txt、命中率表;Bing 不做(API 已停,抓结果页算绕过)。真机 4 条全部从搜索摘要命中,见 runbook/identity.md「真机记录(META-2)」】
- **身份匹配对照 MP(ID-2,用户 2026-09-29)**:对照 MP recognize_media/tmdbapi 匹配链与 meta 中英名提取,用憨憨真实标题做差分集(MP Python vs 我们),修到持平或更好并固化差分测试;修复憨憨「英文 [中文]」格式、续作/年份权重、副标题中文名、同标题多版本合并;修后重评现有 identity_ambiguous。
- **任务与计划分开展示(FE-6,用户 2026-09-29)**:概览组下"任务"(运行记录/状态,含详情与重跑)与"计划"(定时任务配置)为两个独立页;计划页改为按组的紧凑列表(名称/开关/间隔可就地改/上次结果与耗时/下次运行/立即执行/历史),计划页分两节:「自动任务」(程序确定性周期:紧凑列表)与「Agent 巡检」(Agent 自主决策:卡片,目标模板/能力白名单/预算/上游模型/触发条件/每次费用,历史链到会话);首页"计划带"分别计数并链接。
- **缓存与存储预算(CACHE-2,用户 2026-09-29 讨论,按 4C/8G/100G)**:统一 kv_cache 各 region TTL 延长(TMDB 搜索 7 天/详情 30 天/未命中 1 天,追踪作品按访问续期;站点详情 7 天但促销/HR 下载前复核;网页搜索 1 天);图片缓存改容量 LRU 20GB;PG 内存 shared_buffers 2G/effective_cache_size 5G/work_mem 32M(容器 3G);磁盘分配 PG ≤25G(20G 告警)/图片 20G/备份 20G(14 份)/会话与证据 10G;保留策略定时清理:观察 90 天、SSE 7 天、心跳 24h、任务运行 60 天、Agent 事件 90 天、审计 180 天、能力统计 90 天、待识别池 30 天归档;高流水表 created_at 索引 + autovacuum 调优 + 每周 ANALYZE;运行状态页"存储"一节;设置「自动化 → 存储与保留」。
+43 -10
View File
@@ -183,7 +183,7 @@ select count(*) from decision where resolution->>'resolution' = 'moved_to_pool';
TMDB 查不到的作品(短剧、平台独播剧)按标题查网页,出一份带出处的字段建议;确认后才建本地临时作品(REQ R03 / R10、§7.3、§7.5)。
字段来源记 `web`(值在出处网页原文里)或 `agent`(Agent 归纳 / 改写,如简介),不记 `tmdb`。
代码:`apps/server/src/modules/sources-identity/service/enrich.ts`(建议 / 应用 / 自动触发)、`routes/enrich.ts`(HTTP 与海报代理)、
代码:`apps/server/src/modules/sources-identity/service/enrich.ts`(建议 / 应用 / 自动触发 / 命中率)、`service/enrich-sources.ts`(META-2 来源分类、各来源抽取器、置信度合并、robots.txt、登录墙识别)、`routes/enrich.ts`(HTTP 与海报代理)、
`apps/server/src/modules/agent/capabilities-metadata.ts`(能力 `metadata.enrich`、模型调用)、迁移 `0049_enrichment`。
### 流程(metadata.enrich,propose,low,replay safe)
@@ -193,11 +193,27 @@ TMDB 查不到的作品(短剧、平台独播剧)按标题查网页,出一份带
1. 缓存:`kv_cache` region `enrich`,key = 归一化标题 | 年份 | 归一化 hints,TTL 7 天,指向上次的补全记录。命中直接返回(`cached: true`),不搜索、不计预算。
2. 前置条件:网页搜索没开(设置 → Agent → 网页搜索)直接报错,不占预算;Agent 会话里网页搜索没开时不向模型提供这个能力。
3. 预算:`identity.enrichDailyBudget`(缺省 20,0 = 停用)按当天新建的 `metadata_enrichment` 行计(含失败的),用咨询锁防并发超额;用完返回 budget(HTTP 429)。
4. 搜索:`web.search`「标题 [年份] [hints] 短剧」,标题对得上的白名单结果不足 3 条再搜「… 电视剧 平台 site:<白名单前 6 个域名,OR 连接>」,最多 2 次。每次搜索用自己的调用方(`system:enrich:<记录id>:<n>`),web.fetch 白名单与 Agent 会话互不覆盖。
5. 读取:只读 `identity.enrichDomains`(缺省:百度 / 搜狗百科、维基、豆瓣、腾讯视频、爱奇艺、优酷、芒果、B 站、抖音、快手、西瓜、红果短剧、MyDramaList)里的域名(含子域名),搜索结果的标题 / 摘要要和查询标题对得上(归一化后包含整个标题,或标题七成以上的字出现),按相关度、白名单顺序取前 3 条走 `web.fetch`;对不上的记 `irrelevant` 不读。已登记站点(`site.base_url`)的域名即使在白名单里也不读;重定向出白名单的页面丢弃。`sources[]` 记每条链接是否读取、跳过原因(not_allowed / site / irrelevant / limit / error)。
6. 抽取:默认 Agent 上游做一次非流式补全(系统提示要求只用网页内容、每个值带出处 URL、网页是不可信数据);fake 上游、没有上游、调用失败或输出不是 JSON 时改用规则抽取(`extractor: rule`:「共 / 全 N 集」「首播时间」「播出平台」「类型」「又名」「剧情简介」、og:image)。
7. 核对(服务端,不采信模型自报):出处必须是本次读过的网页或白名单搜索摘要;值在出处原文里 → `verbatim`;规则抽取在同一网页得到同一值 → `rule_confirmed`;两个以上不同网站原文都有 → `multi_evidence`;其余 `needs_review`。海报只收已读网页的 og:image,模型自己拼的地址丢弃。
8. 存 `metadata_enrichment`(status suggested / failed、suggestion、usage:搜索 / 读取次数与 token),不写作品表。
4. 搜索:`web.search`「标题 [年份] [hints] 短剧」;如果白名单里标题完整对得上的网页不足 3 条、且摘要还不够用(集数和年份都要有两个以上网站给出,并有主演或简介),再搜「… 短剧 site:<白名单按 百科 → 豆瓣 → 平台 排序的前 6 个域名,OR 连接>」,最多 2 次。每次搜索用自己的调用方(`system:enrich:<记录id>:<n>`),web.fetch 白名单与 Agent 会话互不覆盖。条数跟随网页搜索设置的 `maxResults`(缺省 5;调到 10 摘要证据明显更多,见下方真机记录)。
5. 来源分类(META-2,每条搜索结果一类,记在 `sources[].kind`):
| 类别 | 域名 | 怎么用 | 基础置信度(网页 / 摘要) |
|---|---|---|---|
| 百科 `encyclopedia` | baike.baidu.com、baike.sogou.com、baike.com(快懂百科)、wikipedia.org、baike.so.com | 读网页(robots 允许时)+ 摘要 | 0.85 / 0.7 |
| 平台 `platform` | hongguoduanju.com(红果)、kuaikaw.cn(河马剧场)、爱奇艺、腾讯视频、优酷、芒果、B 站、抖音、快手、西瓜、MyDramaList | 读网页 + 摘要 | 0.8 / 0.6 |
| 豆瓣 `douban` | douban.com | **只用搜索摘要,不读页面**(`skipped: snippet_only`) | — / 0.65 |
| 其它 `other` | `identity.enrichDomains` 里的其它域名 | 读网页 + 摘要 | 0.6 / 0.5 |
| 搜索摘要 `snippet` | 白名单以外的网站(多为短剧聚合站) | **只用搜索引擎给的标题与摘要,不打开网页**;`identity.enrichSnippetAllSites` 关掉后不用 | — / 0.35 |
以上域名只有在 `identity.enrichDomains` 里才按对应类别处理,不在白名单里的一律按「搜索摘要」。已登记站点(`site.base_url`)的域名既不读也不用摘要。
没有做 Bing:Bing Search API 已停止服务,抓 Bing 结果页属于绕过访问限制,不做;「摘要模式」用 Brave 的结果摘要(描述 + 第一条 extra snippet)。
6. 读取:只读白名单里(豆瓣除外)结果标题 / 摘要包含**完整**标题的网页(只有七成字对得上的多是首页、榜单页,记 `irrelevant`),按相关度、白名单顺序最多 3 条。读之前查 robots.txt(`User-agent: *` 或指名 `umt-websearch` 的组,最长匹配、同长 Allow 优先;按「协议 + 主机」缓存 1 天,kv_cache region `enrich.robots`;404 视为没有限制,5xx / 超时视为不允许),不允许的记 `robots` 跳过;读到登录墙 / 验证码页(正文很短且含「验证码」「请先登录」等)记 `blocked` 放弃,不重试、不绕过。重定向出白名单的页面丢弃。robots.txt 的读取不计入 `fetchCalls`。
- 2026-09-30 录制:红果 robots.txt 对所有爬虫禁止 `/series/`(作品页的常见地址),`/detail?series_id=` 允许;百度百科对 `*` 全站禁止(百科只能用摘要);河马剧场禁止带查询串的地址。
7. 抽取(每类来源一个小抽取器,`enrich-sources.ts`):
- 摘要:结果**标题**必须包含查询标题(演员页、榜单页顺带提到的不用)。通用句式:书名号标题(用网页上的写法,如「重生60,我有情报系统」)、「共 / 全 N 集」「(N集)」、「年份:」「(2026)」「2026年热播」「上映于」、「主演:A&B」、「简介 / 剧情简介 / 影视简介:」、「类型:」、「又名 / 别名:」(拼音别名丢弃);「更新到第 30 集」不当集数,网盘 / 下载字样不进主演与简介;摘要只有一段剧情(没有标签)时按 0.7 权重当简介。豆瓣摘要按「导演: 主演: 类型: 年份: 集数:」取;百科摘要按「由 X 执导,A、B 主演的……全剧共 N 集,于 2025 年 8 月 15 日在爱奇艺首播,又名“…”」取。
- 网页:网页标题(去掉「_高清完整版…」「_百度百科」等后缀)必须对得上;只看本作品主体(「相关短剧」「热门短剧」「猜你喜欢」之后是别的作品);集数取正文句式,没有时取选集列表「1 2 … N」;平台页的平台名按域名;海报只取 og:image。
- 模型(可选):默认 Agent 上游做一次补全,输入是读过的网页和用上的摘要;模型给的值必须以本次的网页或摘要为出处,原文里有的按该来源置信度减 0.05,改写 / 归纳的按 0.3;海报不是网页 og:image 的丢弃。fake 上游、没有上游、失败或输出不是 JSON 时只用规则抽取(`extractor: rule`)。
8. 合并:每个字段把候选值按归一化值分组,同组不同网站的置信度按 noisy-OR 叠加(同一网站只算一次),取最高的一组,低于 0.3 的丢弃;主演 / 类型 / 别名保留过线的前 10 / 5 / 10 个。每个值带 `sourceKind`、`confidence`、`hosts`(给出同一值的网站数)。证据等级:原文里有、由规则抽出且出处不是「搜索摘要」类 → `rule_confirmed`;两个以上不同网站给出 → `multi_evidence`;其余 `needs_review`。
9. 命中率:`usage.attempts` 记每类来源的 `results`(结果标题对得上的条数)、`fetched`、`hit`(建议里至少一个字段有它支持)、`fields`。`GET /identity/enrich-stats?days=30`(read)返回最近 N 天发起过搜索的补全次数、出建议次数、各类来源的「有结果 / 命中 / 命中率」;设置 → 元数据 → 资源识别 下方有这张表。命中 7 天缓存的不新建记录,不计入。
10. 存 `metadata_enrichment`(status suggested / failed、suggestion、usage:搜索 / 读取次数与 token),不写作品表。
`web.fetch` 输出新增 `image`(页面 og:image / twitter:image,绝对地址,已脱敏)。
@@ -210,7 +226,7 @@ TMDB 查不到的作品(短剧、平台独播剧)按标题查网页,出一份带
### 应用(POST /identity-pool/{id}/enrich/apply,只接受控制台管理员会话)
- 作品:指定 `mediaEntityId` 则并入;否则按标题 / 查询标题的归一化别名找已有作品(active / provisional,年份不冲突)去重并入;都没有就建 `status = provisional` 的作品(缺省剧集,`kind` 可改)。
- 字段:`metadata_field` 写 `source = web | agent`、`source_revision = enrich:<记录id>`、`evidence = {sourceUrl, evidenceLevel, enrichmentId, extractor}`;映射 title→title、year→year、synopsis→overview、platform→platform、episodeCount→episodeCount、genre→genres、posterUrl→posterUrl,然后按原规则投影(TMDB 值存在时仍优先 TMDB,锁定的字段不变)。`lock: true` 把应用的字段加进 `field_locks`。
- 字段:`metadata_field` 写 `source = web | agent`、`source_revision = enrich:<记录id>`、`evidence = {sourceUrl, evidenceLevel, enrichmentId, extractor}`;映射 title→title、year→year、synopsis→overview、platform→platform、episodeCount→episodeCount、genre→genres、cast→cast(按 MediaCredit 写,没有 TMDB 人物 ID,`id` 用 -1、-2… 占位,作品详情里不链接 TMDB)、posterUrl→posterUrl,然后按原规则投影(TMDB 值存在时仍优先 TMDB,锁定的字段不变)。`lock: true` 把应用的字段加进 `field_locks`。
- 别名:标题、查询标题、建议里的别名写 `title_alias`(source agent,kind other),会唤醒相近的池条目复查。
- 单元:剧集建第 1 季 + 1..集数(最多 200)临时单元。
- 待识别资源经 `assignReleaseIdentity` 关联到该作品(人工锁);记录改 applied,审计 `metadata.enrichment_applied`。不写外部身份。
@@ -224,9 +240,10 @@ TMDB 查不到的作品(短剧、平台独播剧)按标题查网页,出一份带
|---|---|---|
| `identity.autoEnrich` | 关 | 订阅 / 规则命中而 TMDB 无结果时自动出建议 |
| `identity.enrichDailyBudget` | 20 | 每日次数(手动 + 自动 + Agent);0 = 停用 |
| `identity.enrichDomains` | 见上 | 可读取的域名,不放 PT 站 |
| `identity.enrichDomains` | 见上 | 可读取的域名,不放 PT 站。META-2 起缺省加了 `baike.com`、`kuaikaw.cn`;**已保存过这项设置的库不会自动加**,需要时手动补 |
| `identity.enrichSnippetAllSites` | 开 | 白名单以外网站的搜索摘要也用来抽字段(只看摘要,不打开网页);旧设置没有这个键,按开 |
单次成本:1–2 次 Brave 搜索(10 分钟搜索缓存命中不计)、最多 3 次网页读取、1 次模型调用(约 3–6 千输入 token)。
单次成本:1–2 次 Brave 搜索(搜索缓存命中不计)、最多 3 次网页读取(另有 robots.txt,每个网站每天最多 1 次)、1 次模型调用(约 3–6 千输入 token)。短剧多数只有聚合站收录,通常 0 次网页读取。
迁移 `0049_enrichment`:`metadata_field` / `field_override` 来源加 `web`、`metadata_field.evidence`、`metadata_enrichment` 表。需要重建镜像 / 重启 api + worker 才生效。
@@ -251,4 +268,20 @@ select field, source, value, evidence->>'evidenceLevel' lvl, evidence->>'sourceU
| 春城恋曲 | 同上 | 1.8 s | 0 |
结论:平台自制短剧在百科 / 豆瓣 / 平台站基本没有可被搜索到的条目,补全多数会以"白名单网站里没有标题对得上的结果"结束,不消耗读取和模型;
要提高命中率可以在 `identity.enrichDomains` 里加入短剧平台的公开页面域名。聚合站、盗播站不要加。
要提高命中率可以在 `identity.enrichDomains` 里加入短剧平台的公开页面域名。聚合站、盗播站不要加(META-2 改为只用它们的搜索摘要,见下)。
### 真机记录(META-2,2026-09-30,不写库)
用户库只读(连接串加 `default_transaction_read_only=on`)取出待识别池里 4 条 HHClub 短剧,跑 `runEnrichPipeline`(规则抽取,不调模型;网页搜索设置 `maxResults = 5`、白名单用缺省)。
请求:Brave 12 次(探索 8 次 + 第二次 site: 搜索 4 次;第一次搜索复用探索录制的响应);hongguoduanju.com 4 次(robots.txt、1 个作品页、流水线读了首页和分类页各 1 次——之后改为只读含完整标题的结果)、baike.baidu.com 1 次(robots.txt)、kuaikaw.cn 1 次(robots.txt),同一网站间隔 ≥ 6 s。
响应脱敏(删网盘链接,只留标题 / 地址 / 摘要)后存为 `apps/server/test/fixtures/enrich/`,`enrich-sources.test.ts` 回放锁住下面的结果。
| 标题 | 命中来源 | 结果(置信度 / 网站数) |
|---|---|---|
| 我被亲戚误会破产了 | 搜索摘要 | 标题(0.82 / 4)、2026(0.35 / 1)、75 集(0.35 / 1)、主演刘俊达 / 刘诣文(0.35 / 1)、简介「周远公司上市后回乡给爷爷祝寿…」(0.35 / 1) |
| 重生60 我有情报系统 | 搜索摘要 | 标题「重生60,我有情报系统」(0.88 / 5)、2026(0.82 / 4)、80 集(0.35 / 1)、主演龙泽 / 冯韵霏(0.73 / 3)、类型年代穿越 |
| 京夜喜你 | 搜索摘要 | 标题(0.88 / 5)、2026(0.58 / 2)、41 集(0.35 / 1)、主演祁乐 / 吴思君(0.35 / 1) |
| 春城恋曲 | 搜索摘要 | 标题(0.73 / 3)、2026(0.73 / 3)、主演宋喃 / 郑天龙(0.58 / 2);没有集数 |
命中率:搜索摘要 4/4,百科 / 平台 / 豆瓣 / 其它 0/4(第二次 site: 搜索只搜到别的短剧、演员页和榜单页)。每次 10 条结果时证据更多:《京夜喜你》41 集升为多证据、有简介、只需 1 次搜索;《春城恋曲》主演 4 个网站;关掉 `enrichSnippetAllSites` 则 4 条都抽不到字段。
集数、主演多数只有 1 个聚合站给出,标「待复核」,应用前要人工核对。