日期:2026-04-21
上下文:修复同事 agent 失控污染的 tao_dev_1 数据,统一为 howard_dedup 版本;同时系统化去重,建立正确的需求-能力关系。
| 表 | 计数 | 版本分布 |
|---|---|---|
| capability | 315 | 全部 howard_dedup |
| strategy | 94 | 全部 howard_dedup |
| resource | 2508 | 全部 howard_dedup |
| requirement | 99 | 全部 v0(未动,不要动) |
| knowledge | 1046 | 未动 |
| junction 表 | 计数 |
|---|---|
| requirement_capability | 659 ⚠️ 不完整(见待办 2) |
| capability_tool | 1275 |
| capability_knowledge | 0(源数据无) |
| capability_resource | 0(源数据无) |
| strategy_capability | 660 |
| strategy_resource | 2585 |
| requirement_strategy | 94 |
| requirement_resource | 2585 |
| 表 | 是否有 relation_type 列 |
|---|---|
| strategy_capability | ✅ 有(值:'compose') |
| capability_knowledge | ✅ 有 |
| strategy_knowledge | ✅ 有 |
| requirement_capability | ❌ 没有,不要加(按 A 方案,语义 = 研究发现的所有 cap) |
| 其他 junction | 都没有(只有 FK 两列) |
对原 tao_dev_1 + v0 数据做了 4 轮合并:
CAP-tao_dev_1-NN-NN 占位)→ 465 → 331/Users/sunlit/Downloads/output 2/ 99 folder)由于同事的 agent 失控污染:
howard_dedup源数据 schema 不标准但有内容可抢救:
strategy.strategy.phases + capability_mapping (cap name only)strategy.strategy.phases + capability_mapping (capability_id/name)capabilities_extracted 用老 schema(capability_id/capability_name)phases[] 顶层 list + core_workflow 文本execution_phases + key_capabilitiescapabilities_mapping only全部已经手动解析 + DB 写入。
32 条 canonical 的 name/description 被改写以覆盖合并后的语义范围(应用 rename_merged_capabilities.py)。
从 capabilities_extracted.json 的 implements 字段反向回填了 1275 条 cap-tool 关系。
knowhub/scripts/)| 脚本 | 作用 | 幂等 |
|---|---|---|
merge_capabilities.py |
4 轮 canonical 合并映射 + junction 冲突处理 | ✅ |
rename_merged_capabilities.py |
32 条 canonical 改名 | ✅ |
rebuild_howard_dedup.py |
全量重建:purge → seed → ingest output 2/ → 改名 | ✅(resume mode) |
dedup_howard_round4.py |
Round 4 修复 rebuild 产生的 dup | ✅ |
salvage_malformed_folders.py |
早期尝试处理 malformed folder 的脚本(未使用,我后来手动处理了) | - |
所有脚本使用 autocommit=True,每次操作独立提交——连接断了可以直接重跑。
/tmp/knowhub_backup_2026-04-21/(执行 rebuild 前完整快照)
capability.json (365 rows, 原 v0+tao_dev_1 混合状态)strategy.json、resource.json、requirement.json、knowledge.json/tmp/capabilities_all.md(465 条 tao_dev_1 pre-round-1 原始快照,重建时作为别名源)
问题:当前 req_cap=659 基本等于 strat_cap=660 的镜像,只含 strategy 的 workflow_outline 子集。按 A 方案设计应该是所有 capabilities_extracted.json 里出现的 caps 全集(research-discovered)。
操作:
/Users/sunlit/Downloads/output 2/ 的 99 个 foldercapabilities_extracted.json,对每个 cap 用 alias map 解析成 howard_dedup canonical ID(逻辑与 rebuild_howard_dedup.py 的 cap resolution 部分一致)INSERT INTO requirement_capability (requirement_id, capability_id) VALUES (REQ_NN, CAP-X) ON CONFLICT DO NOTHINGcapability_id/capability_name、053 用 phases 里的 caps 等)也要按特殊结构处理——参考 salvage_malformed_folders.py 的逐 folder 处理逻辑预期增量:1016 cap_entries(含重复) - dedup → 约 900 个 (req, cap) pairs;现有 659 → 预期 ~900+。
不要:
relation_type 列User 将提供 032/046/069/085/097 的重跑数据(可能是新的 folder 替换)。 处理时必须:
检查现有孤儿数据:
REQ_032:DB 已有 24 条 resource(folder=032 tag),没 junctionREQ_069:25 条REQ_085:36 条REQ_097:24 条REQ_046:0 条(从未入库)INSERT ... ON CONFLICT 会更新同样的 resource(URL hash ID 确定)按 rebuild_howard_dedup.py 的 ingest_folder 逻辑处理:
关键:req_cap 要写 ALL caps in capabilities_extracted,不只是 strategy 用到的(A 方案)
所有 315 条 capability + 94 条 strategy 的 embedding 都是空。
当用户想启用语义搜索时,批量调用 knowhub/embeddings.py 的 get_embeddings_batch 重算:
for each cap: embedding = get_embedding(f"{name} {description}")
Round 1-3 合并时丢失了 member caps 的 effects + criterion 数据。
用户有备份,可从 /tmp/knowhub_backup_2026-04-21/capability.json 的旧数据里,对当前 howard_dedup caps 做:
[]、criterion 是 '':从备份找同名或同 ID 的老记录合并进来strategy.json 各造一格(phases/execution_phases/capabilities_mapping 等字段名)capabilities_extracted.json 用了老 schemastrategies: [](没产出策略)extracted_capabilities: [](没产出能力){"ping"}strategies 是 str新批次 is_new=true 的 cap 大量是已有能力的重新命名。 建议:pipeline 在产出 is_new=true 前先做 DB 语义查重(name 精确匹配 + embedding cos)。
decisions.md §18 决议 VCAP 退役,但 ingest_research_output.py 还在造 CAP-tao_dev_1-NN-NNknowhub/docs/2026-04-21_rebuild_handoff.md)knowhub/scripts/rebuild_howard_dedup.py 是主逻辑,内含 alias 构建、canonical 选择、junction 写入的全套实现)查询 DB 现状确认未被外部干扰:
python -c "
from knowhub.knowhub_db.pg_capability_store import PostgreSQLCapabilityStore
s=PostgreSQLCapabilityStore(); cur=s._get_cursor()
for t in ['capability','strategy','resource']:
cur.execute(f'SELECT version, COUNT(*) AS c FROM {t} GROUP BY version')
for r in cur.fetchall(): print(f'{t}/{r[\"version\"]}: {r[\"c\"]}')
"
CAP-<hash8(normalized_name)> 或 CAP-NNN(v0 foundation)strategy-<hash8(req_text + "|" + strategy_name)>resource: resource/research/<platform.lower()>/<hash12(url)>
Alias 构建传递闭包(避免 CAP-A → CAP-B → CAP-C 这种链式问题未解析到最终 canonical):
member_to_canonical = {m: final_canonical for ...}
# 遇到循环或多层嵌套时一定要解析到 final
AnalyticDB 约束:
DELETE + INSERTautocommit=True 强制(否则 idle-in-tx 会长期持锁)junction 写入全部用 ON CONFLICT DO NOTHING,避免重复 PK 错误
不要修改 requirement、knowledge 表及其相关 junction