Skip to content

AI 项目分类与标签方案评审及 V2 实施计划

评审日期:2026-07-17
评审对象:plans/AI_PROJECT_TAXONOMY_AND_TAGGING_PLAN.md
评审结论:REVISE(方向正确,但不建议按原稿直接实施)

0. 执行摘要

原方案最重要的判断是正确的:Hello-AI 仍需要一个稳定的分类目录,但不能再用单一分类承载项目的全部语义;跨分类属性应由受控标签表达。原方案也正确地区分了 subcategoryId、受控标签和原始 tags/topics 三层信号(原方案 71-79 行)。

但原方案仍然偏重“把分类拆得更细”,标签部分还不足以直接实施:

  1. 顶层分类同时混用了项目形态、能力、平台和行业,二级分类又存在多组重叠,单靠 1-12 的优先级不能稳定处理跨类项目。
  2. 首批标签候选约 114 个,已经接近原稿设定的 80-120 上限;其中 taskaudiencematurity 有较强推断性或与已有字段重复。
  3. categoryIdsubcategorysubcategoryId 和分面对象同时写入项目会制造多个事实源。
  4. 自动打标缺少 evidence、置信度门槛、金标集、人工一致性和回滚机制。
  5. Explore 当前只有单标签状态和单值精确匹配,原方案没有定义多分面筛选的 AND/OR 语义。

V2 推荐采用三层模型:

text
一级分类 + 一个主子类     负责稳定导航和文档分组
        +
2-6 个受控分面标签       负责跨类表达、筛选、推荐和任务入口
        +
原始 tags/topics          负责全文召回、别名发现和 taxonomy 演进

核心决策:

  • 保留 12 个业务顶层分类;trending 继续作为派生榜单。
  • 分类只是 primary shelf(主陈列位置),不再宣称它是项目唯一的语义归属。
  • 二级分类数量按分类规模自适应,不再强制每个大类都是 4-7 个。
  • V1 只启用 4 个标签分面、56 个标签,活跃标签硬上限为 60。
  • 每项目总标签 1-6 个,目标 2-5 个;不为满足数量强制补标签。
  • task 改成标签查询预设,maturity 从已有状态派生,audience 暂缓。
  • taxonomy 是唯一结构事实源;项目只保存稳定 ID,不复制标签分面归属和分类展示名。

1. 评审依据与数据快照

1.1 代码链路

事实证据对方案的影响
评估 Prompt 只把分类 ID、名称和自由文本子类列表拼接给 LLMscripts/evaluation-prompt.js:7-1130-35当前不能保证子类和标签来自受控枚举
入库只校验顶层分类,子类由 LLM 自由写入scripts/discover-and-evaluate.js:649-664必须增加 taxonomy 校验层,且分类失败不能等同于内容拒绝
文档按 project.subcategory 展示文本分组scripts/generate-docs.js:28-3471-83V2 需要由 subcategoryId 查 taxonomy label,同时保留一期兼容
Explore 从父分类派生 categoryIdscripts/generate-explore-data.js:490-513嵌套结构下不应在项目内重复保存 categoryId
相关项目混合使用子类、raw tags 和 topicsscripts/generate-explore-data.js:292-338canonical tag 可提高稳定性,但 raw 信号仍应保留召回价值
Explore 当前只有单个 tag 状态public/explore/assets/app.js:21-29要支持真正的多维标签,需要把状态改成按 facet 分组的多选集合
Explore 只展示全局前 28 个标签public/explore/assets/app.js:600-607不能把 50-100 个标签平铺成一组 chip
搜索 Worker 只做一个标签的精确匹配public/explore/assets/search-worker.js:22-40必须定义同分面 OR、跨分面 AND 的组合规则
Meilisearch 当前只搜索 raw tags/topics/subcategoryscripts/meilisearch-index.js:84-98canonical tagIdssubcategoryId 需要进入索引配置
categories.json 当前从 projects.json 生成scripts/extract-categories.js:8-31引入 taxonomy 后必须重新明确唯一事实源和派生方向

1.2 数据观察

本次只读分析以 2026-07-17 当前工作区为快照。data/projects.json 正在发生未提交变化,因此下列数字用于判断数量级,不作为发布基线:

  • 约 2.1 万条业务分类记录,去重 URL 略少于分类记录,数据中存在重复项目。
  • trending 的项目在业务分类中也存在,说明它本质上应是派生视图,而不是重复存储的分类。
  • 当前 raw tags 有超过 1.2 万种原始拼写,简单归一化后仍超过 1 万种。
  • llm/LLMmcp/MCPPyTorch/pytorch、空格与短横线等同义变体大量存在。
  • 当前每项目 raw tags 中位数约为 4,说明“标签数量”不是主要问题,“语义归一和质量”才是主要问题。
  • 现有大桶仍明显失衡,例如 agents/Agent Frameworksdevtools/SDKs & APIsapplications/Productivity Toolsrobotics_iot/Robotics 均超过所属活跃项目的一半。

data/stats.json:2-4 与当前源数据数量存在时点差异,V2 应给所有派生物写入统一的 taxonomyVersionsourceDigest,避免用不同快照做验收。

2. 多维评审

2.1 评审评分

维度评分结论
战略方向8/10“稳定分类 + 横向标签 + raw 信号”是正确方向
信息架构6/10顶层分类兼容性强,但多种分类轴混杂
二级分类边界5/10提案覆盖面完整,但多组子类直接重叠
标签收敛度4/10六个分面约 114 个候选,首版过大
数据模型5/10有稳定 ID 思路,但存在重复字段和多事实源
自动标注可靠性3/10缺证据、置信度、金标集和错误隔离
搜索与筛选体验5/10指明了改造对象,但未定义多选交互语义
迁移与回滚4/10有 dry-run,没有 inverse patch、原子替换和索引切换
验收可测性4/10覆盖率指标较多,正确性指标不足
向后兼容8/10保留顶层 ID 和 raw tags/topics 的策略合理

2.2 值得保留的设计

  1. 顶层分类 ID 保持稳定。 当前导航、README、文档路径和 Explore 都依赖这些 ID,原方案 38-60 行的兼容性判断成立。
  2. 稳定 ID 与展示 label 分离。 subcategoryId 和中文 label 分离有利于重命名和多语言展示。
  3. canonical 与 raw 信号分层。 GitHub topics 不应直接成为目录或过滤器,原方案 75-79 行的三层思路应保留。
  4. 先 dry-run 再批量迁移。 原方案 446-462 行已经具备正确的迁移顺序雏形。
  5. 同时改造评估、文档、Explore 和搜索。 这避免 taxonomy 只存在于数据文件而没有产品消费端。

2.3 必须修订的问题

A. 分类不是同一条轴

applications 是项目形态,multimodal 是能力/模态,desktop_tools 是平台,finance_business 是行业。一个桌面端金融 Coding Agent 可以同时命中多个顶层分类。原方案 407-420 行的线性优先表只能给出一个结果,却不能解释为什么该结果对用户最有用。

修订原则:承认分类只是主陈列位置,用可停止的决策树确定一个位置;所有未被主分类表达的属性进入标签。

B. 二级分类存在直接重叠

重叠主题原方案中的位置V2 边界
Embedding/Rerankingllmsrag_data模型权重归 llms;检索管线与工具归 rag_data;两者都可打 capability tag
OCRrag_datamultimodal通用 OCR/视觉引擎归 multimodal;面向知识库摄取的文档管线归 rag_data
MCPagentsdevtoolsMCP server/client/integration 归 devtools;Agent runtime 仅因支持 MCP 不迁类,只打 mcp
Local AIinfrastructuredesktop_tools无头运行时/Serving 归 infrastructure;GUI 工作台归 desktop_tools
Coding Agentagentsdevtools自主修改仓库/执行任务归 agents;IDE 补全、代码查询和插件归 devtools

C. 标签首版过大且分面职责重叠

原方案 297-337 行约有 114 个候选标签。主要问题不是 114 这个绝对数字,而是其中有三类不应直接入库:

  • task 是用户查询意图,可以由标签组合生成,不应再复制一套标签。
  • maturity 中的 maintained/inactive 与现有 health 和更新时间重复;tutorial/awesome-list 实际是项目形态。
  • audience 很难从当前 name/description/topics 稳定判断,容易让 LLM 猜测。

原方案要求每项目 3-8 个、最多 10 个(424-432 行),会诱导系统为了达标填充弱标签。V2 改为上限控制,不设置强制平均数。

D. 数据模型存在漂移风险

原方案示例在项目中新增 categoryId、展示文本 subcategorysubcategoryId 和按分面展开的 canonicalTags377-394 行)。但当前项目已经嵌套在父 category 下,Explore 和 Meilisearch 都从父级派生 categoryId。重复写入会导致父分类和项目字段不一致。

V2 项目只写 subcategoryId、扁平 tagIdstaxonomyVersion;category 来自父级,标签所属 facet 来自 taxonomy,展示 label 也来自 taxonomy。

E. 自动标注没有质量闭环

当前 Prompt 输入只有 name、description、topics(scripts/evaluation-prompt.js:14-20)。这些证据不足以可靠判断 audience、成熟度和复杂任务。原方案虽然提到低置信度 review,但没有定义置信度、证据格式、人工样本或最低正确率。

此外,taxonomy 输出非法不等于项目内容不合格。原方案 490-494 行把失败结果降级到 rejected reason 的做法会混淆“内容拒绝”和“分类待审”。两者必须使用不同队列。

F. 迁移和索引缺少回滚

原方案有 dry-run 和 patch,但没有:

  • 输入文件摘要和 taxonomy 版本;
  • before/after/reason/confidence 记录;
  • inverse patch;
  • 幂等和原子替换;
  • Meilisearch 新索引构建、验证、swap 和旧索引保留;
  • trending 从业务数据重新派生的顺序。

G. 验收指标偏覆盖率,缺少正确率

“98% 有 ID”“未分类低于 2%”“平均 3-8 个标签”都可以通过强制赋值达成,却不能证明标签正确。原方案对子类成立阈值也同时使用了 50 个(64-69 行)和 30 个(534-540 行),口径不一致。

3. V2 目标与非目标

3.1 目标

  1. 用户能通过稳定目录浏览项目,也能通过多维标签找到跨分类项目。
  2. 新增项目只能写入合法分类、子类和标签 ID。
  3. 标签集合规模受控、语义明确、可合并、可废弃、可审计。
  4. 自动打标有证据、有置信度、有人工质量基线。
  5. 迁移可 dry-run、可回滚、可重复执行。
  6. 文档、Explore、相关项目和 Meilisearch 消费同一 taxonomy。

3.2 非目标

  • V1 不追求表达 GitHub 项目的每个技术细节。
  • V1 不把编程语言、厂商名、模型名、许可证和所有 GitHub topics canonical 化。
  • V1 不引入多主分类;多维语义由标签解决。
  • V1 不一次性创建 80-120 个标签,也不根据一次 LLM 输出自动扩充 taxonomy。

4. 信息架构决策

4.1 三层语义模型

层级每项目数量职责是否受控
categoryId1顶层导航、稳定 URL、统计
subcategoryId1当前分类内的主陈列位置
tagIds1-6跨类能力、平台、形态和领域
tags/topics0-N搜索召回、别名学习、趋势发现否,保留原值

这里的“每项目一个分类”不代表项目只属于这个语义类别,只代表项目在目录里有一个稳定落点。一个金融 Coding Agent 可以主陈列在 finance_business,同时具有 agent-runtimecode-generationcliapplicationfinance 标签。

4.2 顶层分类

保留原有 12 个业务分类和 trending 派生入口,不在本轮改变 URL 和导航认知。trending 不参加 LLM 分类、不持久化业务副本,应由业务项目集合生成。

4.3 二级分类规模

不再对所有顶层分类统一要求 4-7 个二级分类,改为按活跃项目规模设置:

顶层分类活跃规模建议子类数子类成立门槛
少于 3002-4至少 30 个且占所属分类 8%,或战略例外
300-10003-5至少 40 个且占所属分类 5%,或战略例外
大于 10004-7至少 50 个且占所属分类 5%,或战略例外

先对原方案提出的子类执行全量 dry-run,再决定启用、合并或保留为标签。不能为了达到子类数量目标而拆出没有稳定用户入口的小桶。

4.4 主分类停止式决策树

按下面顺序命中后停止;实现时每条规则都必须有 include/exclude 样例:

  1. 纯教程、课程、论文清单、Notebook、资源导航 -> learning
  2. 核心交付物是模型权重或模型架构 -> 文本/通用模型归 llms,视觉/音视频模型归 multimodal
  3. 核心价值依赖机器人、传感器、嵌入式设备或自动驾驶环境 -> robotics_iot
  4. 核心价值离不开金融、交易、市场或企业业务数据 -> finance_business
  5. 核心交付物是推理运行时、部署、网关、监控或硬件加速 -> infrastructure
  6. 核心交付物是训练、微调、数据集生产或模型评测 -> finetuning
  7. 核心交付物是检索、索引、文档摄取或知识图谱管线 -> rag_data
  8. 核心行为是自主规划、调用工具并持续执行任务 -> agents
  9. 核心交互依赖桌面、操作系统或浏览器扩展 -> desktop_tools
  10. 面向最终用户的可直接使用产品 -> applications
  11. SDK、IDE 插件、代码分析、API client 和开发脚手架 -> devtools
  12. 仍无法裁决 -> 保留原归属并进入 taxonomy-review.jsonl,不得靠随机优先级写入。

4.5 典型冲突裁决

项目主分类/子类canonical tags
通用 MCP serverdevtools/mcp-integrationsmcp, library-sdk,按接口补平台
支持 MCP 的多智能体框架agents/multi-agent-systemsmulti-agent, mcp, framework
Embedding 模型权重llms/embedding-rerank-modelsembedding, model
Embedding 检索管线rag_data/search-retrieval-enginesembedding, vector-search, framework
通用 OCR 引擎multimodal/vision-understanding-ocrocr, vision-understanding, library-sdk
面向 RAG 的 PDF 摄取工具rag_data/document-parsing-ocrdocument-parsing, ocr, library-sdk
本地模型无头运行时infrastructure/local-runtime-model-managementlocal-model-runtime, model-serving, self-hosted
本地模型 GUI 客户端desktop_tools/local-ai-workbenchlocal-model-runtime, desktop-app, application
自主修复仓库的 CLI Agentagents/coding-agentsagent-runtime, code-generation, cli, application
IDE 内代码补全插件devtools/ai-ides-code-assistantscode-generation, ide-extension, application
文生图 SaaS 的开源前端applications/creative-content-appsimage-generation, web-app, application

5. 收敛标签体系

5.1 标签设计原则

一个 canonical tag 必须同时满足:

  1. 能回答一个明确、可重复的筛选问题。
  2. 语义预计至少稳定 6 个月,不是短期产品名或热词。
  3. 与已有标签有清晰边界,不把上下位概念当 alias。
  4. 能从 README、topics、仓库元数据或人工判断中找到证据。
  5. 默认覆盖至少 50 个活跃项目;战略能力可例外,但必须记录批准原因。
  6. 活跃标签总数不超过 60;超过上限时执行 one-in-one-out 合并或废弃。

明确不收录为 canonical tag 的内容:

  • 过宽:aimachine-learningopen-sourcedeveloper
  • 具体厂商/产品:openaiclaudegeminiollama;保留为 raw topics 或 alias 证据。
  • 编程语言:pythonrusttypescript;继续用于搜索,不进入首版 facet。
  • 推断性强:end-userproduct-builderproduction-ready
  • 与现有字段重复:maintainedinactivedeprecated

5.2 V1 标签总表

首版共 56 个capability 31 个、platform 9 个、project_type 9 个、domain 7 个。

Capability(31)

标签组tagIds边界说明
本地与模型工具local-model-runtime, embedding, reranking不使用过宽的 llm;只标明确的运行、向量化或重排能力
Agent 与协议agent-runtime, multi-agent, mcp, tool-callingmulti-agent 是更具体能力;mcp 只表示协议兼容,不决定分类
检索与知识rag, graphrag, vector-search, knowledge-graph, document-parsing, ocrOCR 可跨 rag_datamultimodal,由主交付物决定分类
训练与运行fine-tuning, model-training, model-evaluation, model-serving, model-quantization, llm-observability避免泛化为 mlopstrainingevaluation
多模态image-generation, vision-understanding, video-generation, video-understanding, speech-to-text, text-to-speech音乐/通用音频生成暂保留 raw topic,达到门槛后再评估
编程与自动化code-generation, code-search, browser-automation, workflow-automationautomation 太宽,不进入 canonical
机器人与端侧robotics-control, edge-inferenceedge-device 属于 platform,不与能力混写

Platform(9)

cli, web-app, desktop-app, browser-extension, ide-extension, mobile-app, self-hosted, kubernetes, edge-device

平台标签只在存在明确运行或交互证据时写入。仅提供 Dockerfile 不自动产生平台标签;self-hosted 需要文档明确支持自行部署。

Project Type(9)

model, framework, library-sdk, application, database-engine, dataset, benchmark, learning-resource, curated-list

每个项目必须且只能有一个 project_typecurated-listlearning-resource 互斥:资源目录使用前者,课程/教程/Notebook 使用后者。

Domain(7)

finance, healthcare, legal, education, cybersecurity, autonomous-driving, iot

领域标签默认最多一个。只有项目核心价值无法脱离该领域数据、规则或工作流时才添加;README 中出现一个行业示例不构成领域证据。

5.3 每项目标签数量

Facet数量约束规则
project_type恰好 1无法确定则进入 review
capability0-3只写有直接证据的能力;资源清单和通用数据集可为 0
platform0-2只写真实支持的平台,不从技术栈猜测
domain0-1只写核心领域
总数1-6目标 2-5,不为凑数补标签

5.4 最具体标签优先

taxonomy 应支持 broader 关系,但项目不重复保存父子标签:

  • multi-agent 的 broader 是 agent-runtime;项目只存 multi-agent,筛选 agent-runtime 时通过查询展开命中。
  • graphrag 的 broader 是 rag;项目只存 graphrag
  • browser-extensionbrowser-automation 不是父子关系,一个是平台,一个是能力,可以共存。
  • speech-to-texttext-to-speech 是不同能力,可以共存。

5.5 不入库的任务预设

任务入口由稳定标签表达式生成,避免再维护一套 task 标签:

任务入口查询表达式示例
构建 RAGcapability in (rag, graphrag) AND project_type in (framework, library-sdk)
本地运行模型capability = local-model-runtime AND platform in (self-hosted, desktop-app, edge-device)
构建 Coding Agentcapability = agent-runtime AND capability in (code-generation, code-search)
文档问答capability in (rag, graphrag) AND capability in (document-parsing, ocr)
部署模型服务capability = model-serving
浏览器自动化capability = browser-automation

这些表达式可维护在 data/task-presets.json,当前 scripts/generate-explore-data.js:344-362 已有任务匹配概念,可改为读取 canonical 表达式而不是字符串包含判断。

6. Taxonomy 与项目数据结构

6.1 唯一事实源

新增 data/taxonomy.json,它是下列信息的唯一事实源:

  • category/subcategory 的 ID、label、顺序、别名和边界;
  • tag 的 ID、facet、label、别名、include/exclude、broader 和生命周期;
  • taxonomy 版本和变更记录。

data/categories.json 改为从 taxonomy 生成的轻量导航产物。Prompt、文档、Explore 和 Meilisearch 均通过同一个 scripts/lib/taxonomy.js 读取和校验 taxonomy。

6.2 Taxonomy 示例

json
{
  "version": "2.0.0",
  "facets": ["capability", "platform", "project_type", "domain"],
  "tags": [
    {
      "id": "graphrag",
      "facet": "capability",
      "label": "GraphRAG",
      "description": "Retrieval augmented generation whose retrieval structure is a graph.",
      "aliases": ["graph-rag"],
      "include": ["Graph-based retrieval is a core project capability."],
      "exclude": ["A generic knowledge graph without a RAG pipeline."],
      "broader": "rag",
      "status": "active",
      "replacedBy": null
    }
  ]
}

alias 只能表示同义拼写,不能把 agentmulti-agent 这样的上下位概念互相归一。

6.3 项目记录

项目继续嵌套在 category 下时,不重复存 categoryId

json
{
  "name": "Example",
  "url": "https://github.com/org/example",
  "subcategoryId": "coding-agents",
  "tagIds": ["agent-runtime", "code-generation", "cli", "application"],
  "taxonomyVersion": "2.0.0",
  "tags": ["AI Agent", "Claude Code"],
  "topics": ["coding-agent", "cli"]
}

一期兼容期间可以继续输出 subcategory 展示文本,但它必须由 subcategoryId 和 taxonomy 生成,不再由 LLM 直接写入。兼容期结束后删除持久化展示文本。

6.4 标注审计记录

data/taxonomy-assignments.jsonl 保存自动标注证据,不把大段 evidence 复制进项目主库:

json
{
  "url": "https://github.com/org/example",
  "sourceDigest": "sha256:...",
  "taxonomyVersion": "2.0.0",
  "subcategoryId": {
    "value": "coding-agents",
    "confidence": 0.94,
    "evidence": ["README: autonomous repository task execution"],
    "source": "rules+llm"
  },
  "tagIds": [
    {
      "value": "code-generation",
      "confidence": 0.96,
      "evidence": ["topic:coding-agent", "README: edits repository files"],
      "source": "rules"
    }
  ],
  "reviewRequired": false
}

7. 自动分类与打标管线

7.1 证据优先级

  1. 当前合法分类和人工锁定结果。
  2. 精确 URL/owner/name 规则。
  3. taxonomy alias 与 GitHub topics 的精确匹配。
  4. README 中明确的功能、安装和使用场景证据。
  5. description、项目名和仓库元数据。
  6. LLM 在白名单内的结构化判断。

scripts/extract-readmes.js 已经能维护 README 抓取结果和 manifest,可复用该离线证据链,不应只依赖当前 Prompt 的 name/description/topics。

7.2 自动决策门槛

  • 每个自动分类或标签必须返回 value/confidence/evidence/source
  • 经金标集校准后,confidence >= 0.90 且无规则冲突才自动写入。
  • 0.70 <= confidence < 0.90 进入 taxonomy-review.jsonl,保留旧归属。
  • confidence < 0.70 不写该标签;项目类型或子类不确定时进入 review。
  • 违反数量、facet、互斥或 broader 规则的输出一律不入库。
  • taxonomy 判断失败写入分类 review,不写入内容 rejected-projects

7.3 金标集

首版建立至少 600 个项目的分层金标集:

  • 12 个业务分类各抽 30 个,共 360 个;覆盖每个候选子类。
  • 典型跨类冲突 120 个:MCP、OCR、Embedding、Local AI、Coding Agent、金融 Agent 等。
  • 空子类、重复 URL、低频标签和历史异常 120 个。

至少 200 个样本由两人独立标注,用于计算 Cohen's kappa;其余样本用于离线 precision/recall 和 macro-F1。12 个分类的抽样还要按候选子类分层,不能只按分类总量均匀抽样。

7.4 Taxonomy 校验器

新增 scripts/validate-taxonomy.js,至少校验:

  • category/subcategory/tag ID 全局唯一;
  • alias 归一化后不冲突;
  • tag facet 合法,broader 不成环;
  • status=deprecated 必须有 replacedBy 或明确删除原因;
  • 每项目子类属于父 category;
  • 每项目恰好一个 project type,总标签不超过 6;
  • 不保存父子冗余标签;
  • URL 唯一,trending 不作为业务源数据重复参与;
  • 所有项目和派生物的 taxonomy version/source digest 一致。

8. 产品筛选与搜索规则

8.1 筛选语义

  • 同一 facet 多选使用 ORcli OR desktop-app
  • 不同 facet 之间使用 ANDagent-runtime AND (cli OR desktop-app) AND finance
  • category/subcategory 与标签之间使用 AND
  • raw tags/topics 只参与全文召回,不进入 canonical facet 计数。
  • broader 查询由搜索层展开,例如选择 agent-runtime 时同时命中 multi-agent

8.2 Explore 交互

  • 标签按 capability/platform/project_type/domain 分组,不平铺 56 个标签。
  • 每组默认显示动态计数最高的 6-10 个,其余通过组内搜索或展开查看。
  • 计数基于当前筛选结果联动更新;零结果标签禁用。
  • 已选条件可单独删除,并写入 URL,刷新或分享后可恢复。
  • 任务入口只应用预设筛选条件,不生成另一种项目属性。

8.3 相关项目

相关项目权重建议:

  1. 相同最具体 capability tag;
  2. 相同 subcategory;
  3. 相同 project type/platform/domain;
  4. raw tags/topics 仅作为较低权重补充;
  5. 高频标签需要 IDF 或上限,避免 applicationframework 主导相似度。

9. 实施计划

阶段 0:冻结可复现基线

涉及文件:data/projects.jsondata/stats.jsonpublic/explore/data/*

  1. 记录源文件 SHA-256、项目行数、唯一 URL、重复 URL、空/非法子类和生成物时间。
  2. 先按 URL 去重业务数据;保留冲突报告,不静默丢弃不同分类记录。
  3. trending 改为派生输出,确保它不污染业务唯一性和分类统计。
  4. 所有 dry-run 报告带 sourceDigest,源文件变化后旧报告不得应用。

阶段 1:定义 taxonomy 和共享 loader

涉及文件:新增 data/taxonomy.jsonscripts/lib/taxonomy.jsscripts/validate-taxonomy.js

  1. 写入顶层分类、经 dry-run 验证的子类、56 个 V1 标签和边界规则。
  2. 实现 ID/alias/facet/broader/status 校验。
  3. 修改 scripts/extract-categories.js,由 taxonomy 生成 data/categories.json
  4. 为 loader 和 validator 增加单元测试,包括 alias 冲突和 broader 环路。

阶段 2:建立金标集并验证子类

涉及文件:新增 data/taxonomy-gold.jsonlscripts/audit-taxonomy.js

  1. 按第 7.3 节建立 600 个样本。
  2. 对原方案候选子类跑全量分布,输出 active/raw 数量、最大桶占比、冲突率和低置信率。
  3. 不满足第 4.3 节门槛的候选子类合并或降级为标签。
  4. 固化分类冲突样例作为回归测试。

阶段 3:现有项目 dry-run 打标

涉及文件:新增 scripts/classify-existing-projects.jsdata/taxonomy-assignments.jsonl

  1. 先应用确定性 alias/include/exclude 规则。
  2. 再读取 README 信号;证据不足时才调用 LLM。
  3. 输出版本化 patch:url/before/after/reason/confidence/evidence
  4. 同时生成 inverse patch、review 队列和分布报告。
  5. dry-run 默认写新文件,禁止直接覆盖 data/projects.json

阶段 4:改造新增项目评估

涉及文件:scripts/evaluation-prompt.jsscripts/discover-and-evaluate.js

  1. Prompt 只允许返回 taxonomy 中的 category/subcategory/tag ID。
  2. 输入增加可用 README 摘要或结构化信号。
  3. 输出增加逐项 confidence/evidence,不再返回自由文本子类。
  4. 入库前通过共享 validator;分类不确定进入 review,内容不合格才进入 rejected。
  5. 新增 Prompt 与入库校验测试,覆盖非法 ID、跨 facet、超量标签和低置信结果。

阶段 5:改造消费端

涉及文件:

  • scripts/generate-docs.js
  • scripts/generate-explore-data.js
  • public/explore/assets/app.js
  • public/explore/assets/search-worker.js
  • scripts/meilisearch-index.js
  • scripts/meilisearch-tui.js

工作内容:

  1. 文档从 taxonomy 解析子类顺序和 label。
  2. Explore 输出按 facet 分组的标签、broader 展开和动态计数所需数据。
  3. Worker 支持同 facet OR、跨 facet AND。
  4. 相关项目优先使用 canonical capability,raw 信号降权。
  5. Meilisearch 增加 subcategoryIdtagIds 和按 facet 派生的 filter 字段。
  6. 任务路径改读 data/task-presets.json

阶段 6:分批迁移与发布

  1. 先迁移金标集和 500 个非金标样本,人工检查错误类型和分布。
  2. 达到第 10 节质量门槛后,再生成全量 patch。
  3. 原子替换项目前重新校验 sourceDigest,替换后立即运行 validator。
  4. 重建文档、Explore 数据和站点构建。
  5. Meilisearch 使用新索引名构建;验证计数和查询后执行 index swap。
  6. 旧项目文件、inverse patch 和旧索引至少保留一个发布周期。

阶段 7:持续治理

  1. 每月输出 taxonomy drift:高频 raw topic、未映射信号、标签增长和低置信队列。
  2. 每季度审查低使用标签、近义标签和 project type/domain 误标。
  3. 新增 tag 必须提交覆盖数据、include/exclude、与现有标签重合率和迁移影响。
  4. active 标签达到 60 后执行 one-in-one-out,不直接扩容。

10. 验收标准

10.1 数据完整性

  • trending URL 重复数为 0。
  • 非法 category/subcategory/tag ID 为 0。
  • 子类与父分类不一致为 0。
  • project type 缺失或多于一个为 0。
  • 每项目 tagIds 为 1-6 个,父子冗余标签为 0。
  • trending 完全由业务项目派生,不作为 LLM 可选分类。
  • taxonomy、项目、Explore 数据和搜索索引版本一致。

10.2 分类与标签正确性

  • 金标集主分类准确率不低于 90%。
  • 子分类 macro-F1 不低于 0.85。
  • canonical tag micro precision 不低于 0.90、micro recall 不低于 0.80。
  • 双人标注样本 Cohen's kappa 不低于 0.80。
  • 自动写入的每个分类和标签都有 evidence,低置信结果不会覆盖旧归属。
  • 新增项目不能生成 taxonomy 外 ID。

10.3 Taxonomy 收敛度

  • V1 active tag 数不超过 60。
  • 新增普通标签需覆盖至少 50 个活跃项目;战略例外必须在 taxonomy changelog 中记录。
  • alias 冲突为 0,deprecated tag 均有替代或删除说明。
  • 低于 30 个活跃项目且连续两个季度没有增长的非战略标签必须合并、降级为 raw 或废弃。

10.4 产品体验

  • Explore 可同时选择多个 facet,同组 OR、跨组 AND 的结果与测试夹具一致。
  • 动态计数、零结果禁用和 URL 状态恢复通过端到端测试。
  • raw topics 仍能被全文搜索,但不出现在 canonical facet 中。
  • 至少 6 个任务预设能稳定生成可解释的标签表达式和结果。
  • 相比发布前基线,主要查询的零结果率不升高,筛选响应耗时不退化超过 20%。

10.5 工程与回滚

  • npm run ai:generate-docs 成功。
  • npm run explore:generate-data 成功。
  • npm run docs:build 成功。
  • taxonomy loader/validator、Prompt 校验、迁移幂等和筛选逻辑测试通过。
  • 同一 patch 重复执行不会产生额外变化。
  • inverse patch 回滚演练成功。
  • Meilisearch 新索引验证和 swap 演练成功,失败时可切回旧索引。

11. 风险与缓解

风险影响缓解
为了覆盖率强制打标签precision 下降、筛选失真不设最低 capability 数;以 precision 和 evidence 为门槛
主分类边界仍有争议用户对目录落点困惑分类只作 primary shelf;保存争议样本并迭代停止式规则
标签过快膨胀UI 噪声和维护成本上升V1 上限 60、晋升门槛、one-in-one-out
LLM 置信度未校准高分错误自动入库以金标集校准;低置信 review;规则校验兜底
taxonomy 多源漂移Prompt、页面、索引不一致单一 loader、版本和 source digest 校验
迁移覆盖用户正在更新的数据数据丢失或 patch 错位输入摘要、默认写新文件、应用前 digest 校验和原子替换
多选筛选造成零结果用户认为标签无用动态计数、零结果禁用、任务预设和筛选可撤销
长尾能力被收敛掉新兴方向不可发现raw topics 保留召回;月度 drift 报告;战略例外机制

12. ADR:选择“主分类 + 收敛分面标签”

Decision

采用一个稳定主分类、一个主子类、1-6 个受控分面标签和原始搜索信号并行的混合模型。

Drivers

  1. 保持现有 URL、导航和文档生成兼容。
  2. 表达项目跨能力、平台、形态和行业的真实多维属性。
  3. 控制标签规模、自动标注误差和长期治理成本。

Alternatives considered

  1. 纯分类树:实现简单,但跨类项目只能被迫选择一个语义归属,继续制造重叠子类。
  2. 纯标签目录:表达灵活,但会破坏现有导航认知,且 2 万项目的首屏探索成本过高。
  3. 多主分类 + 标签:表达力最强,但统计、去重、文档生成和 URL 规则复杂,当前收益不足以覆盖迁移成本。
  4. 主分类 + 收敛分面标签:既保留导航,又能表达多维语义,且可渐进迁移。

Why chosen

第四种方案在兼容性、表达力、实现复杂度和治理成本之间最均衡。它也允许未来在不改变项目数据的前提下,增加任务入口和新的浏览视图。

Consequences

  • 分类不再被解释为项目完整本体,只是稳定陈列位置。
  • 产品需要真正支持分面多选,而不是只增加一个标签字段。
  • taxonomy 变成核心业务数据,需要版本、测试和变更治理。
  • 自动标注必须接受“少打但准确”,不能以标签数量作为成功指标。

Follow-ups

  1. 先实施阶段 0-2,验证子类和 56 个标签的真实分布。
  2. 分布与金标结果通过后,再决定是否进入全量迁移。
  3. V1 上线一个季度后,根据 drift 报告评估是否晋升 audio-generationprivacy3d-spatial 等候选标签。

13. 最终建议

原方案不应废弃,而应作为“候选分类和标签素材库”。实际实施以本 V2 的约束为准:

  1. 先把分类定义降级为主陈列位置,解决“一个项目并非只属于一个语义类别”的根本矛盾。
  2. 首版只启用 56 个受控标签和 4 个 facet,不实施 task/audience/maturity 三套持久化标签。
  3. 先做分布 dry-run 和金标集,不直接回填 2 万项目。
  4. 用 evidence、precision、recall 和回滚演练决定是否发布,而不是用覆盖率和平均标签数决定。

满足以上条件后,“分类时顺便打标签”是合理且应当同步完成的,可以避免未来再次扫描全库;但同步打标必须产出可审计证据和版本化 patch,不能只扩展现有 LLM Prompt 后直接写回主库。