znlgis 博客

GIS开发与技术分享 — GDAL · GeoServer · PostGIS · QGIS · OpenLayers · Cesium · FreeCAD · NPOI

第二章:三层索引架构

在 opengis-skills 仓库中,三层索引架构是整个系统设计的灵魂。它决定了 AI 工具如何发现、加载和利用 67 个技能文件,是所有上层功能的基础。本章将从设计动机出发,逐层深入解析 L1(全局入口)、L2(分类索引)和 L3(项目技能)的结构与协作方式,并通过完整的 AI 加载决策流程展示这套架构在真实场景中的运作机制。

2.1 设计动机

在讨论具体架构之前,理解它要解决什么问题比理解它是什么更重要。

2.1.1 上下文窗口的约束

所有主流 AI 编程助手——Claude、Cursor、Cline、GitHub Copilot Chat、DeepSeek Chat——都有一个共同约束:上下文窗口(context window)是有限的且按 Token 计费。opengis-skills 仓库包含 67 个技能文件,每个 SKILL.md 文件从 200 行到 1500 行不等。如果 AI 工具在每次对话中都全量加载 67 个文件,会产生以下问题:

问题 影响
Token 消耗爆炸 67 个文件 × 平均 800 行 × 约 40 Token/行 ≈ 210 万 Token,远超大多数模型的窗口上限
注意力稀释 AI 难以在海量信息中定位真正相关的 1-2 个技能
成本翻倍 每次全量扫描消耗大量输入 Token,无意义增加 API 费用
响应变慢 大上下文导致推理延迟显著增加

因此需要一个按需加载(on-demand loading)的机制,让 AI 工具在 1-3 个技能文件内就能获取足够的知识来完成任务。

2.1.2 不同场景需要不同粒度的知识

用户的问题千差万别,对应的知识需求粒度也不同:

用户场景 知识需求粒度 对应层级
“我想做 GIS 数据处理,有什么工具?” 概览级:了解可选工具范围和分类 L1 全局入口
“我需要 Python 做空间分析,有哪些库?” 概要级:了解某个领域内的工具和对比 L2 分类索引
“用 GDAL 的 ogr2ogr 怎么把 Shapefile 转成 GeoPackage?” 深度级:某个工具的具体命令、参数和最佳实践 L3 项目技能

如果只有一个层级的索引,要么信息不足(只有概要)、要么信息过载(每次都加载深度内容)。三层架构天然匹配这三种粒度需求,做到”刚好够用的信息量”。

2.1.3 AI 工具需要快速定位

AI 工具在接收用户问题后,需要在数百毫秒内判断应该加载哪个技能文件。这要求索引系统具备以下特性:

  • 可搜索性:能通过标签、关键词、分类快速命中目标技能
  • 递增精度:从 L1(67 个技能的全貌)→ L2(一个分类下的 8-23 个技能)→ L3(1 个技能的深度知识),每一步都缩小范围
  • 低 Token 成本:L1 和 L2 索引文件本身要足够精简(控制在 200-400 行),确保搜索成本可忽略不计

2.1.4 技能之间需要清晰的引用关系

GIS/CAD 等领域的工具不是孤岛。例如:

  • geopipe-agent 引用了 gdalqgis-processgeopandas
  • opengis-all 聚合了 GDAL → QGIS → GeoServer 的全流程
  • shapelygeopandas 常组合使用

三层架构通过相对路径引用../gdal/SKILL.md)构建了一个层级化的知识图谱,让技能之间可以互相导航,AI 工具可以沿着引用链加载相关技能。

2.2 三层架构全景

2.2.1 层级表

层级 名称 文件路径 数量 内容量级 适用场景
L1 全局入口 根目录 SKILL.md 1 个 67 个技能的全量索引 + 标签搜索系统 不确定具体工具时,先加载此文件获取全貌
L2 分类索引 gis/SKILL.mdcad/SKILL.mdcsharp/SKILL.mdai/SKILL.mdiot/SKILL.md3d/SKILL.mdothers/SKILL.md 7 个 该分类下 1-23 个技能的概要 + 领域概述 明确大类但不确定具体工具
L3 项目技能 <category>/<project>/SKILL.md 67 个 单个项目的深度知识(API、工作流、FAQ) 已确定使用哪个工具

2.2.2 三层架构的目录结构映射

opengis-skills/
│
├── SKILL.md                 ← L1:全局入口(67 个技能全量索引 + 标签搜索)
│
├── gis/                     ← 分类目录
│   ├── SKILL.md             ← L2:GIS 分类索引(23 个技能概要)
│   ├── gdal/                ← 子项目
│   │   └── SKILL.md         ← L3:GDAL 命令行技能(452 行深度知识)
│   ├── geopandas/
│   │   └── SKILL.md         ← L3:GeoPandas 技能
│   ├── geoserver/
│   │   └── SKILL.md         ← L3:GeoServer 技能
│   └── ...(共 23 个子项目)
│
├── cad/
│   ├── SKILL.md             ← L2:CAD 分类索引(19 个技能概要)
│   ├── freecad/
│   │   └── SKILL.md         ← L3:FreeCAD 技能
│   └── ...(共 19 个子项目)
│
├── csharp/
│   ├── SKILL.md             ← L2:C# 分类索引(8 个技能概要)
│   └── ...(共 8 个子项目)
│
├── ai/
│   ├── SKILL.md             ← L2:AI 分类索引(8 个技能概要)
│   └── ...(共 8 个子项目)
│
├── iot/
│   ├── SKILL.md             ← L2:IoT 分类索引(1 个技能概要)
│   └── ke3036-keyes-pico/
│       └── SKILL.md         ← L3:Raspberry Pi Pico 技能
│
├── 3d/
│   ├── SKILL.md             ← L2:3D 分类索引(2 个技能概要)
│   └── ...(共 2 个子项目)
│
└── others/
    ├── SKILL.md             ← L2:Others 分类索引(6 个技能概要)
    └── ...(共 6 个子项目)

每个层级都是目录下的 SKILL.md 文件,命名完全一致,形成一种递归式的自描述结构。AI 工具只需记住一条规则:加载某个路径下的 SKILL.md 就能获得该层级的全部信息

2.2.3 AI 加载决策树

下面是 AI 工具从接收用户提问到加载目标技能文件的完整决策路径:

用户提问:"帮我把 Shapefile 转成 GeoJSON"
  ↓
AI 加载 @SKILL.md(根,L1)
  │  成本:300 行 ≈ 12K Token
  │  获得:67 个技能的全量索引 + 标签搜索系统
  ↓
在标签索引中搜索匹配项
  │  搜索 #conversion #vector
  │  匹配:gdal(cli, raster, vector, conversion)
  ↓
定位到 L2 分类索引?
  ├─ 是 → 加载 @gis/SKILL.md 了解更多 GIS 工具选项
  │         成本:200 行 ≈ 8K Token
  │         获得:23 个 GIS 技能的概要 + GIS 数据处理链路
  │
  └─ 否 → 跳过 L2,直接定位到 L3 技能
  ↓
加载 @gis/gdal/SKILL.md(L3)获取详细指导
  │  成本:452 行 ≈ 18K Token
  │  获得:50+ 命令行的完整 API、参数说明、工作流示例、FAQ
  ↓
AI 根���技能内容生成回答
  │  输出:`ogr2ogr -f GeoJSON output.json input.shp`
  │  附带:参数说明、坐标系转换、批量处理脚本
  ↓
可选:加载 @gis/geopandas/SKILL.md 获取 Python 替代方案

总 Token 消耗:L1(12K)+ L2(8K)+ L3(18K)= 约 38K Token。相比于全量加载 67 个文件(约 210 万 Token),节省了 98.2% 的上下文窗口

2.2.4 加载路径的两种模式

三层架构支持两种加载路径,AI 工具可以根据问题的明确程度自适应选择:

直钻模式(Drill-Down):当用户问题具体到某个工具时,直接跳入 L3。

提问:"ogr2ogr 怎么指定输出坐标系?"
  → 跳过 L1/L2 → 直接加载 gis/gdal/SKILL.md

渐进模式(Progressive):当用户问题模糊时,逐级下钻。

提问:"我想做空间数据处理,用什么好?"
  → L1:加载根 SKILL.md,浏览 67 个技能概览
  → L2:发现 GIS 分类有 23 个技能,加载 gis/SKILL.md
  → L3:确定用 GDAL,加载 gis/gdal/SKILL.md

这种双模式设计的关键在于:三层架构不强制逐级加载,而是提供了从任意层级切入的灵活入口。AI 工具只需根据用户问题的语义,选择一个最合适的起点。

2.3 L1:全局入口 SKILL.md

根目录的 SKILL.md 是整个仓库的唯一入口,也是三层架构的基石。它的设计目标是:让 AI 工具在加载这一个文件之后,就能回答以下三个问题:

  1. 这个仓库是做什么的?(概述)
  2. 有哪些技能可以用?(索引表)
  3. 如何找到我需要的技能?(标签搜索)

2.3.1 YAML Frontmatter 设计

根 SKILL.md 的 YAML 前置元数据是整个标签搜索系统的核心:

---
name: opengis-skills
description: "Use when AI coding assistant needs GIS/CAD/C#/AI/IoT/3D domain
expertise for 67+ open-source projects. One-stop skill index with tag-based search
and on-demand loading for GDAL, GeoServer, QGIS, PostGIS, JTS, CesiumJS, FreeCAD,
OpenSCAD, OCCT, NPOI, SqlSugar, Furion, Dify, SuperSplat, Go and more."
tags:
  - gis
  - cad
  - csharp
  - ai
  - iot
  - opensource
  - skills
  - geospatial
  - spatial-analysis
  - mapping
  - 3d-modeling
  - dotnet
  - python
  - java
  - javascript
  - go
  - typescript
  - cpp
---

name 字段:仓库标识名,与 GitHub 仓库名保持一致。AI 工具通过此字段识别仓库。

description 字段:采用 Anthropic Skill 最佳实践的 "Use when..." 格式。这种格式的核心思想是描述”何时使用”而非”这是什么”——对于 AI 工具而言,知道”什么时候应该加载这个技能”比”这个技能包含什么内容”更重要。description 限长 ≤500 字符,确保 AI 在扫描大量技能时能快速判断相关性。

tags 字段:18 个全局标签,覆盖了仓库涉及的 7 种编程语言和 11 个功能领域。标签系统设计的关键原则:

  • 语言标签pythonjavadotnet 等)用于精确匹配用户的技术栈
  • 领域标签giscad3d-modeling 等)用于按功能分类
  • 通用标签opensourceskills)用于仓库级别的搜索

2.3.2 分类导航表

由于根 SKILL.md 是全局入口,它必须用最紧凑的信息密度呈现所有 67 个技能的概况。为此采用了一张按分类组织的导航表:

### 🌍 GIS — 地理信息系统(23 个)

| 技能 | 简介 | 关键标签 |
|------|------|---------|
| [gdal](./gis/gdal/SKILL.md) | GDAL 命令行:栅格/矢量处理事实标准 | `cli` `raster` `vector` `conversion` |
| [geoserver](./gis/geoserver/SKILL.md) | 开源地图服务器(WMS/WFS/WMTS/WCS) | `server` `wms` `wfs` `ogc` |
| [postgis](./gis/postgis/SKILL.md) | PostgreSQL 空间数据库扩展 | `database` `sql` `spatial` |
| ... | ... | ... |

导航表的设计要点:

  1. 表头三列:技能名称(带超链接)、一句话简介、关键标签——刚好满足”判断是否需要加载”的信息量
  2. 按分类分组:GIS 23 个、CAD 19 个、C# 8 个、AI 8 个、IoT 1 个、3D 2 个、Others 6 个——共七个分类,用 emoji 和中文标题区分
  3. 相对路径超链接./gis/gdal/SKILL.md 是相对路径引用,AI 工具可以直接通过路径加载对应文件
  4. 标签列:3-5 个精选标签,提供比一句话简介更精确的匹配维度

2.3.3 标签索引系统(详见 2.6 节)

在导航表之后,根 SKILL.md 提供了按语言和按功能领域的双维度标签索引

### 按语言/平台

| 标签 | 相关技能 |
|------|---------|
| `python` | gdal-api, pyqgis, geopandas, shapely, cadquery, freecad, docutranslate |
| `java` | geotools, jts, geometry-api-java, opengis-utils-for-java, ruoyi-cloud |
| `dotnet` / `csharp` | gdal-api, nettopologysuite, geometry-api-net, sharpmap, mapsui, ... |
| ... | ... |

### 按功能领域

| 标签 | 相关技能 |
|------|---------|
| `geometry` | jts, nettopologysuite, shapely, geometry-api-java, geometry-api-net, clipper1, clipper2, ... |
| `raster` | gdal, gdal-api, qgis-process |
| `server` / `wms` / `wfs` | geoserver, geoserver-cloud, geoserver-rest-api |
| ... | ... |

这种双维度索引的价值在于:AI 工具可以用用户问题中的关键词(如”python” + “向量”)在标签系统中做 AND 组合查询,比单纯的关键词匹配更精准。

2.3.4 场景推荐表

为了让 AI 工具在最短路径上找到目标技能,根 SKILL.md 还提供了一张典型场景 → 推荐加载技能的映射表:

| 用户需求 | 加载技能 |
|---------|---------|
| "帮我把 Shapefile 转成 GeoJSON" | `gis/gdal/SKILL.md` |
| "用 Python 计算两个面的交集" | `gis/shapely/SKILL.md` |
| "用 QGIS 批处理做缓冲区分析" | `gis/qgis-process/SKILL.md` |
| "如何发布矢量数据到 GeoServer?" | `gis/geoserver-rest-api/SKILL.md` |
| "PostGIS 怎么建空间索引?" | `gis/postgis/SKILL.md` |
| ... | ... |

这张表的特殊价值在于:它直接给出了答案而非让 AI 自行推断。对于高频场景,AI 工具可以跳过标签搜索,直接通过问题语义匹配表中的一个条目,实现零推理成本的技能定位。

2.3.5 AI 工具使用指南与加载策略

根 SKILL.md 的最后一节是面向 AI 工具的使用指南,核心是两种加载策略:

策略一:按需加载(推荐) 根据用户问题,只加载 1-3 个最相关的 SKILL.md。适用于绝大多数场景,Token 成本最低。

策略二:全量加载 当用户需求横跨多个领域或完全不确定具体工具时,先加载根 SKILL.md 获取全局索引,再按需下钻。这只是第一步的”全局扫描”,后续仍然是精准加载。

此外,文档还列举了不同 AI 工具的加载语法:

# Claude Code / Claude
@SKILL.md                    # 加载根入口
@gis/gdal/SKILL.md           # 加载 GDAL 技能

# Cursor
在 .cursorrules 中引用或在对话中使用 @file 语法

# Cline / Roo Code
直接使用 @ 语法或通过 .clinerules 配置

2.3.6 文件间引用方式

根 SKILL.md 中的所有技能引用都使用相对路径

[gdal](./gis/gdal/SKILL.md)         ← 从根目录到子目录

而子技能文件中回引父目录时使用 ../ 语法:

[../SKILL.md](../SKILL.md)          ← 从子目录回引根目录

这种基于文件系统路径的引用方式有两个优势:

  1. 不依赖外部 URL:即使仓库离线或迁移至 Gitee 等平台,引用链仍然有效
  2. AI 工具直接可用:大多数 AI 工具的 @ 语法就是基于文件路径的,引用路径和加载路径完全一致

2.4 L2:分类索引

L2 分类索引是 L1 和 L3 之间的减震层——当用户问题过于模糊无法直接定位到 L3 时,L2 提供了一个中等粒度的视图,用 200 行的文件覆盖一个领域内 1-23 个技能的关键信息。

仓库共有 7 个 L2 索引文件,对应 7 个分类目录:

分类索引 技能数量 领域覆盖
gis/SKILL.md 23 空间数据处理、地图服务、Web GIS
cad/SKILL.md 19 参数化建模、几何内核、BIM/PCB
csharp/SKILL.md 8 .NET 框架、ORM、Office 操作
ai/SKILL.md 8 LLM 应用、Agent 框架、AI 编程方法论
iot/SKILL.md 1 物联网与嵌入式
3d/SKILL.md 2 3D 高斯泼溅、AEC/BIM 三维数据处理
others/SKILL.md 6 Go 语言、RPA 自动化、邮件平台、Java 脚手架、SSL 证书

2.4.1 以 gis/SKILL.md 为例深度解析

gis/SKILL.md 是最大的 L2 索引文件,涵盖 23 个 GIS 技能。它的结构代表了所有 L2 索引的标准模式。

YAML Frontmatter

---
name: gis-skills
description: "Use when processing geospatial data, publishing map services,
querying spatial databases, performing geometry operations, or building web map
applications. Index of 23 skills: GDAL, GeoServer, QGIS, PostGIS, JTS, GeoPandas,
Shapely, CesiumJS, OpenLayers, NetTopologySuite and more."
tags:
  - gis
  - geospatial
  - mapping
  - spatial-analysis
  - vector
  - raster
  - server
  - webmapping
---

L2 分类索引的 description 采用 "Index of N skills: ..." 的固定格式,让 AI 能立即知道这个索引文件下有多少个可用的子技能。

父级入口引用

> **父级入口:** [../SKILL.md](../SKILL.md) — 全仓 66 技能总索引

每个 L2 索引的第一行都引用回 L1 根入口,形成一个双向导航:从 L1 可以下钻到 L2,从 L2 也能回溯到 L1。这种设计让 AI 工具在加载了过多上下文后可以”退回”到更高层级的视角。

领域数据流图

gis/SKILL.md 在概述中用一段 ASCII 图描绘了 GIS 数据处理的全链路:

数据源 → 命令行处理 → 编程分析 → 空间数据库 → 地图服务 → 前端可视化
 (GDAL)   (GDAL CLI)   (JTS/PyQGIS)  (PostGIS)  (GeoServer) (OpenLayers/Cesium)

这不是装饰,而是帮助 AI 理解工具之间关系的语义地图。当用户说”我想从数据处理到发布地图”时,AI 能立即沿着这条链路找到 GDAL(处理)→ PostGIS(存储)→ GeoServer(发布)→ OpenLayers(可视化)的完整组合。

子技能分组列表

L2 索引将 23 个 GIS 技能按职能分为 8 个子类:

  • 🧰 数据处理与命令行(4 个:gdal, gdal-api, qgis-process, geopipe-agent)
  • 🗄️ 空间数据库(1 个:postgis)
  • 🔧 几何运算库(5 个:jts, geometry-api-java, geometry-api-net, shapely, geopandas)
  • 🌐 地图服务器(3 个:geoserver, geoserver-rest-api, geoserver-cloud)
  • 🖥️ QGIS 生态(1 个:pyqgis)
  • 🗺️ Web 地图可视化(2 个:cesiumjs, openlayers)
  • 📦 .NET GIS 组件(5 个:nettopologysuite, geometry-api-net, sharpmap, mapsui 等)
  • 🧩 综合/工具集(3 个:opengis-all, geotools, opengis-utils-for-java, opengis-utils-for-net)

每个子类的表格结构与 L1 相同:技能名(带链接)、一句话简介、关键标签。这种一致性让 AI 工具在处理不同层级的信息时无需切换解析逻辑。

快速导航表

| 用户需求 | 推荐加载 |
|---------|---------|
| "Shapefile 转 GeoJSON" | `gdal/SKILL.md` |
| "Python 空间分析" | `geopandas/SKILL.md` + `shapely/SKILL.md` |
| "发布 WMS 地图服务" | `geoserver/SKILL.md` + `geoserver-rest-api/SKILL.md` |
| ... | ... |

与 L1 的场景推荐表不同,L2 的快速导航表粒度更细——同一个”GIS 数据处理”大类下,不同子场景推荐不同的技能组合。例如”Python 空间分析”推荐同时加载 geopandasshapely,因为这两个库在实际使用中高度互补。

相关分类引用

- **[cad/](../cad/SKILL.md)** — CAD 参数化建模、几何运算、BIM/PCB
- **[csharp/](../csharp/SKILL.md)** — .NET 框架、ORM、Office 操作
- **[ai/](../ai/SKILL.md)** — LLM 应用、Agent 框架
- **[3d/](../3d/SKILL.md)** — 3D 高斯泼溅与 Web 三维可视化
- **[iot/](../iot/SKILL.md)** — 物联网与嵌入式

L2 索引的末尾都会列出兄弟分类索引,让 AI 工具在发现”当前分类下没有最佳匹配”时,能横向跳转到其他分类。

2.4.2 其他 L2 分类索引概览

cad/SKILL.md(19 个技能):

与 gis/SKILL.md 结构完整对称,包含 CAD 数据流图:

几何内核 → 参数化建模 → CAD 应用 → 数据交换 → 可视化
  (OCCT)    (FreeCAD)   (QCAD)    (LibreDWG) (Chili3D)

19 个技能按职能分为 7 个子类:几何内核与算法(3 个)、参数化 3D CAD(5 个)、2D CAD 与制图(3 个)、PCB/EDA 设计(1 个)、BIM 与 IFC(2 个)、.NET AutoCAD 开发(4 个)、数据交换与可视化(2 个)。

csharp/SKILL.md(8 个技能)、ai/SKILL.md(8 个技能):结构与上述一致,规模较小。每个都有独立的快速导航表和相关分类引用。

iot/SKILL.md(1 个技能)、3d/SKILL.md(2 个技能)、others/SKILL.md(6 个):虽然技能数量较少,但仍遵循完全一致的 L2 模板。模板的一致性确保了 AI 工具在跨分类切换时不需要切换解析策略。

2.4.3 L2 索引的核心价值

L2 索引在架构中承担三个关键角色:

  1. 知识压缩:将 L1 中一行简介的信息展开为 200 行的领域全景,但比 L3 的单个技能文件仍然精简得多
  2. 智能路由:当用户说”我要做 CAD”但不说具体工具时,L2 帮 AI 判断该推荐 FreeCAD(参数化建模)还是 OpenSCAD(脚本建模)还是 LibreDWG(DWG 文件处理)
  3. 横向导航:L2 索引的相关分类引用让 AI 可以跨领域探索——例如用户问 GIF 数据处理,但又提及需要 .NET 平台,AI 可以从 gis/SKILL.md 跳转到 csharp/SKILL.md 寻找 .NET 平台的 GIS 组件

2.5 L3:项目技能

L3 是整个三层架构的”最后一公里”——当 AI 通过 L1/L2 定位到具体的工具后,L3 提供可以立即用于代码生成的深度知识

2.5.1 以 gis/gdal/SKILL.md 为例深度解析

GDAL 的 L3 技能文件是仓库中最成熟、最完整的典范,共 452 行。它的结构代表了所有 L3 技能的高质量标准。

完整的 Frontmatter

---
name: gdal
description: "Use when processing geospatial raster/vector data via command line 
format conversion (Shapefile to GeoJSON), reprojection, DEM analysis, NDVI
calculation, mosaicking. GDAL/OGR CLI: the industry standard for batch geospatial
data processing with 50+ command-line tools (ogr2ogr, gdalwarp, gdal_translate,
gdal_calc)."

tags:
  - gdal
  - ogr
  - cli
  - raster
  - vector
  - conversion
  - reprojection
  - gis
  - geospatial
---

L3 技能文件的 Frontmatter 有三个关键设计:

  1. name 字段:与项目名称完全一致(gdal),与目录名 gis/gdal/ 对应,确保路径和名称的统一性

  2. description 字段:比 L1/L2 的 description 更长、更具体(但仍在 500 字符内)。前 100 个字符是最重要的——它们直接回答了 AI 工具最关心的问题:”何时加载?”(Use when processing geospatial raster/vector data via command line),然后列举了典型场景(format conversion, reprojection, DEM analysis),最后给出差异化定位(50+ command-line tools)。这种”触发条件 → 典型场景 → 大小估算”的三段式格式,让 AI 在扫描众多 L3 描述时能快速排除不相关的技能

  3. tags 字段:L3 的标签比 L1 更具体。L1 用 pythonjava 等语言标签,L3 用 clirastervectorconversionreprojection功能标签。这形成了标签的层级关系——L1 标签用于全局搜索,L3 标签用于精确匹配

头部引用块

> **项目地址:** <https://github.com/OSGeo/gdal>
>
> **官方文档:** <https://gdal.org/en/latest/>
>
> **源码命令文档:** <https://gdal.org/en/latest/programs/>
>
> **许可证:** MIT

头部引用块是一个固定的四行元数据模板,每个 L3 技能都必须包含。它的作用是:

  • 让 AI 工具知道可以到官方文档获取更实时的信息(减少幻觉)
  • 让人类读者快速了解项目背景
  • 让许可证合规性一目了然

正文结构:L3 技能的正文按以下固定章节编排(顺序保证一致):

章节 内容 行数占比
概述 项目定位、特性矩阵、能力边界 5%
环境准备/安装 各平台安装命令、版本验证 10%
核心 API/命令 50+ 命令行的完整参数表 + 代码示例 50%
典型工作流 6 个端到端操作模式的 Shell 脚本 15%
AI 使用建议 推荐工作流、关键注意事项 10%
常见问题(FAQ) 常见错误与解决方案 5%
参考资源 官方文档链接、相关技能引用 5%

代码示例标准格式

# 格式转换(Shapefile → GeoJSON)
ogr2ogr output.geojson input.shp

# 指定输出格式(Shapefile → GeoPackage)
ogr2ogr -f GPKG output.gpkg input.shp

# 重投影(WGS84 → Web Mercator)
ogr2ogr -t_srs EPSG:3857 output.shp input.shp

每个代码块遵循统一的规范:

  1. 注释行用中文描述操作目标(如”格式转换(Shapefile → GeoJSON)”),让 AI 立即理解示例的意图
  2. 命令本身使用标准的命令行格式,参数按出现频率排序(常用参数在前)
  3. 注释和命令之间无空行——保持紧凑,减少 Token 消耗

2.5.2 reference 子目录拆分策略

当 L3 技能文件超过 500 行时,会将详细参数表和高级示例拆分到 reference/ 子目录。以 gis/gdal/ 为例:

gis/gdal/
├── SKILL.md                    # 主文件(452 行):核心 API + 常用工作流
└── reference/
    ├── vector-tools.md         # 矢量工具完整参数表和高级示例
    └── raster-tools.md         # 栅格工具完整参数表和高级示例

拆分原则:

  • 主文件保留最少 80% 场景所需的最小知识量——核心命令、常用参数、典型工作流
  • reference 文件存放 20% 高级场景所需的详尽内容——完整参数表、边界情况、性能调优细节
  • 主文件和 reference 之间用相对路径链接:[reference/vector-tools.md](reference/vector-tools.md)

这种”主文件 + reference”的模式,让 AI 在处理常规问题(如格式转换)时只加载主文件(452 行),处理高级问题(如矢量工具的特定参数组合)时才加载 reference 文件。它本质上是在 L3 内部也做了一层按需加载

2.5.3 opengis-all:特殊的一站式聚合技能

在 L3 层级中,gis/opengis-all/ 是一个特殊的存在——它不是单个工具的技能,而是聚合了 5 个 L3 技能的端到端工作流文档

> **涵盖工具与项目:**
>
> | 工具/接口 | 项目地址 | 文档 | 许可证 |
> |-----------|----------|------|--------|
> | GDAL 命令行 | <https://github.com/OSGeo/gdal> | <https://gdal.org/en/latest/programs/> | MIT |
> | GDAL API | ... | ... | MIT |
> | qgis_process | ... | ... | GPL-2.0+ |
> | PyQGIS | ... | ... | GPL-2.0+ |
> | GeoServer REST API | ... | ... | GPL-2.0+ |

它的正文按工作流阶段组织(而非按工具):

阶段一:数据获取与生成 → 阶段二:数据处理与转换 → 阶段三:空间分析 → 阶段四:服务发布

每个阶段同时展示多个工具的等价用法:

# 矢量格式转换的三种方式

## GDAL 命令行(ogr2ogr)
ogr2ogr output.geojson input.shp

## GDAL Python API
gdal.VectorTranslate("output.geojson", "input.shp", format="GeoJSON")

## qgis_process
qgis_process run native:reprojectlayer -- INPUT=input.shp TARGET_CRS=EPSG:4326 OUTPUT=output.geojson

opengis-all 的设计回答了”当用户需要一个完整的 GIS 工作流(从数据到服务),应该加载什么?”这一问题。它处理了跨工具协作场景,它本身是一个 L3 文件,但内部引用了其他 L3 文件作为”详细内容的入口”。

2.5.4 geopipe-agent:跨技能引用示例

gis/geopipe-agent/SKILL.md 展示了 L3 技能如何横向引用其他 L3 技能

## 相关技能

- **gdal** — 命令行数据处理:[../gdal/SKILL.md](../gdal/SKILL.md)
- **qgis-process** — QGIS 命令行处理工具:[../qgis-process/SKILL.md](../qgis-process/SKILL.md)
- **pyqgis** — QGIS Python 绑定:[../pyqgis/SKILL.md](../pyqgis/SKILL.md)
- **geopandas** — Python 矢量数据处理:[../geopandas/SKILL.md](../geopandas/SKILL.md)
- **postgis** — 空间数据库:[../postgis/SKILL.md](../postgis/SKILL.md)

这些引用形成了跨技能的横向导航。例如,当 AI 加载 geopipe-agent 后发现某个功能(如栅格分析)在当前技能中没有覆盖时,可以通过横向引用加载 gdal 技能获取补充知识。

2.5.5 L3 技能的通用编写规范

所有 67 个 L3 技能遵循统一的编写规范(详见第三章),核心约束为:

  1. YAML frontmatternamedescription"Use when..." 格式,≤500 字符)、tags(用于搜索)
  2. 头部引用块 — 项目地址、官方文档、许可证
  3. 正文章节(按固定顺序)——概述 → 安装 → 核心 API → 工作流 → 最佳实践 → FAQ → 参考资源
  4. 语言 — 中文为主,代码/命令/API 使用原文格式
  5. 规模控制 — 主文件 300-1500 行;超过 500 行时拆分到 reference/
  6. 代码示例 — 基于上游官方文档实地核对,避免编造 API

2.6 标签索引系统

标签索引是三层架构中最核心的搜索机制。它独立于文件层级,以横切方式连接所有技能。

2.6.1 标签体系设计

仓库使用双层标签体系:

第一层:语言/平台标签

标签 覆盖技能数 示例技能
python 7 gdal-api, pyqgis, geopandas, shapely, cadquery, freecad, docutranslate
java 5 geotools, jts, geometry-api-java, opengis-utils-for-java, ruoyi-cloud
dotnet / csharp 17 gdal-api, nettopologysuite, geometry-api-net, mapsui, furion, npoi, sqlsugar, …
javascript / typescript 4 cesiumjs, openlayers, chili3d, admin-net-frontend
cpp / c 4 gdal-api, occt, librecad, libredwg
go 3 go, robotgo, robotgo-flow

第二层:功能领域标签

标签 语义 覆盖技能数
geometry 几何运算(布尔、缓冲区、拓扑) 8
raster 栅格处理 3
vector 矢量处理 4
server / wms / wfs 地图服务器与 OGC 服务 3
3d 三维建模、可视化 10
2d 二维制图、渲染 5
orm / database ORM 框架、数据库 3
agent / llm AI Agent、大语言模型 8
pipeline / workflow 数据流水线、工作流编排 4
automation / rpa 桌面自动化、RPA 2
autocad AutoCAD 二次开发 4

2.6.2 标签搜索的工作原理

标签搜索不是传统意义上的全文搜索引擎——它依赖 AI 工具的语义理解能力,而非简单的字符串匹配。具体流程:

  1. 标签收集:AI 加载根 SKILL.md 后,获取所有的标签索引表
  2. 语义映射:AI 分析用户问题中的关键词(如”用 Python 处理栅格数据”),将其映射到 python + raster 标签
  3. 交集运算:在两个标签的候选技能集中取交集
    • python 标签命中:{gdal-api, pyqgis, geopandas, shapely, cadquery, freecad, docutranslate}
    • raster 标签命中:{gdal, gdal-api, qgis-process}
    • 交集:{gdal-api}
  4. 结果排序:如果交集有多个技能,按标签匹配度(命中标签越多越靠前)排序

2.6.3 标签搜索优于关键词搜索的原因

维度 关键词搜索 标签搜索
精确度 “vector” 可能匹配到”矢量”相关的任意文本 vector 标签只匹配真正处理矢量数据的技能
覆盖率 “gdal” 关键词搜不到 “geopandas” python + raster 标签可以跨工具发现相关技能
歧义性 “server” 可能匹配到 Web 服务器而非地图服务器 server 标签只在 GIS 上下文中用于 GeoServer 等地图服务器
可组合性 难以做多条件组合 python AND raster 天然支持组合查询

2.6.4 标签在 AI 工具中的实际使用

AI 工具使用标签搜索的典型提示(Prompt)模式:

用户问题:"用 Python 做矢量数据格式转换"

AI 内部推理:
  1. 关键词提取:python, 矢量, 格式转换
  2. 标签映射:python + vector + conversion
  3. 在 L1 标签索引中匹配:
     - python: {gdal-api, pyqgis, geopandas, shapely, ...}
     - vector: {gdal, gdal-api, geopandas, geotools}
     - conversion: {gdal}
  4. 三标签交集: {gdal-api}(GDAL Python API)
  5. 双标签交集: {gdal, gdal-api, geopandas}(后两者是 Python 生态)
  6. 最优匹配: gdal-api(三标签命中)→ geopandas(双标签命中,更 Pythonic)
  7. 决策:加载 gis/gdal-api/SKILL.md 和 gis/geopandas/SKILL.md

2.7 引用关系与导航

三层架构的引用系统形成了一个可遍历的知识图谱

2.7.1 三个方向的引用

引用方向 语法 示例 触发场景
向上引用 ../SKILL.md L2 → L1, L3 → L2 “这个分类下没有合适的,回上级目录看看”
向下引用 ./subproject/SKILL.md L1 → L2 → L3 “找到一个匹配的分类/技能,加载详情”
横向引用 ../other-project/SKILL.md L3 → L3 “需要搭配使用其他工具”

2.7.2 从 L1 到 L3 的逐级下钻

L1: SKILL.md(根)                     [67 个技能的全量索引]
  ├─→ gis/gdal/SKILL.md                [GDAL 命令行]
  ├─→ gis/geopandas/SKILL.md           [Python 矢量处理]
  ├─→ cad/freecad/SKILL.md             [参数化 3D CAD]
  └─→ ...
    │
    ├─→ L2: gis/SKILL.md               [23 个 GIS 技能概要]
    │     ├─→ gdal/SKILL.md            [GDAL 命令行]
    │     │     └─→ reference/vector-tools.md    [矢量工具详细参数]
    │     └─→ ...
    │
    └─→ L2: cad/SKILL.md               [19 个 CAD 技能概要]
          └─→ ...

2.7.3 L3 间的横向引用网络

以 GIS 分类为例,展示 L3 项目技能之间的横向引用关系:

opengis-all ───────────→ gdal ──────────────→ gdal-api
    │        聚合引用      │   兄弟引用          │
    │                      │                     │
    ├──→ qgis-process      ├──→ gdal-api        ├──→ geopandas
    ├──→ pyqgis            ├──→ qgis-process    └──→ postgis
    ├──→ geoserver-rest-api├──→ postgis
    └──→ geopipe-agent     ├──→ pyqgis
                            └──→ opengis-all

每个箭头代表一个 [../xxx/SKILL.md] 的 Markdown 链接。这个网络的关键特性:

  • opengis-all 是 Hub 节点:聚合了 5 个技能,作为一站式入口
  • gdal 是核心节点:被最多技能引用(6 个),因为它是 GIS 数据处理的事实标准
  • geopipe-agent 是叶子节点:引用了多个技能,但被引用较少(新兴项目)

2.7.4 引用链的实际利用

AI 工具可以利用引用链实现自动化的上下文扩展

用户:"用 GDAL 做缓冲区分区分析并发布到 GeoServer"
  ↓ AI 加载 gis/gdal/SKILL.md
  ↓ 发现 gdal 的"相关技能"中引用了 geoserver-rest-api
  ↓ 自动加载 gis/geoserver-rest-api/SKILL.md
  ↓ 发现还需要 postgis 做数据存储
  ↓ 自动加载 gis/postgis/SKILL.md
  ↓ 形成完整方案:GDAL 处理 → PostGIS 存储 → GeoServer REST API 发布

这种”沿引用链自动扩展上下文”的能力,是三层架构相比独立文件集合的本质优势。

2.8 AI 工具中的实际加载流程

本节展示一个端到端的加载决策流程,从用户提问到 AI 生成最终回答的完整过程。

2.8.1 完整流程拆解

用户:"帮我把 Shapefile 转成 GeoJSON"

┌─────────────────────────────────────────────────────────┐
│ 第一步:意图分析与标签映射                                │
│                                                         │
│ AI 分析用户问题,提取关键信息:                            │
│   - 操作:格式转换(Shapefile → GeoJSON)                 │
│   - 数据格式:Shapefile(矢量)                          │
│   - 目标格式:GeoJSON                                    │
│   - 隐含标签:#conversion #vector #cli                   │
│                                                         │
│ AI 决策:问题具体且明确 → 跳��� L2,直钻 L3               │
└────────────────────────┬────────────────────────────────┘
                         ↓
┌─────────────────────────────────────────────────────────┐
│ 第二步:L1 扫描与匹配                                     │
│                                                         │
│ AI 加载 @SKILL.md(根,L1),扫描标签索引:                │
│                                                         │
│ 在标签索引中搜索 #conversion #vector:                    │
│   - conversion 标签匹配:gdal                            │
│   - vector 标签匹配:gdal, gdal-api, geopandas, geotools │
│                                                         │
│ 交集 + 排序:gdal(2 标签命中,且 conversion 是精确匹配)   │
│                                                         │
│ 验证场景推荐表:                                          │
│   "帮我把 Shapefile 转成 GeoJSON" → gis/gdal/SKILL.md   │
│                                                         │
│ 双重验证一致 → 确定目标:gis/gdal/SKILL.md                │
└────────────────────────┬────────────────────────────────┘
                         ↓
┌─────────────────────────────────────────────────────────┐
│ 第三步:L3 知识提取                                       │
│                                                         │
│ AI 加载 @gis/gdal/SKILL.md(L3),提取相关章节:           │
│                                                         │
│ 1. 矢量数据工具 → ogr2ogr 命令                           │
│    ogr2ogr output.geojson input.shp                      │
│                                                         │
│ 2. 常见使用模式 → 批量格式转换脚本                        │
│    for shp in *.shp; do                                  │
│      ogr2ogr -f GeoJSON "${shp%.shp}.geojson" "$shp"     │
│    done                                                  │
│                                                         │
│ 3. 数据格式支持 → Shapefile (.shp), GeoJSON (.geojson)   │
│                                                         │
│ 4. AI 使用建议 → 使用 JSON 输出了解数据,再执行转换        │
└────────────────────────┬────────────────────────────────┘
                         ↓
┌─────────────────────────────────────────────────────────┐
│ 第四步:回答生成                                          │
│                                                         │
│ AI 根据 L3 知识生成结构化回答:                            │
│                                                         │
│ 1. 基本转换命令:                                         │
│    ogr2ogr -f GeoJSON output.json input.shp              │
│                                                         │
│ 2. 带额外选项的版本:                                      │
│    ogr2ogr -f GeoJSON output.json input.shp \            │
│      -t_srs EPSG:4326  # 同时重投影到 WGS84              │
│                                                         │
│ 3. 批量转换脚本:                                         │
│    (完整的 for 循环脚本)                                │
│                                                         │
│ 4. 补充说明:                                             │
│    - 如果需要 Python 方案,可以加载 geopandas 技能        │
│    - 如果需要坐标系转换,使用 -t_srs 参数                  │
│    - 安装方法:apt-get install gdal-bin                   │
└─────────────────────────────────────────────────────────┘
                         ↓
┌─────────────────────────────────────────────────────────┐
│ 第五步(可选):横向扩展                                   │
│                                                         │
│ 如果用户追问:"有没有 Python 的方式?"                     │
│                                                         │
│ AI 回到 L1 标签索引,搜索 #python #vector:               │
│   匹配:gdal-api(GDAL Python 绑定)                      │
│          geopandas(Python 矢量处理)                     │
│                                                         │
│ AI 加载 @gis/geopandas/SKILL.md                          │
│   获取:                                                 │
│   import geopandas as gpd                                │
│   gdf = gpd.read_file("input.shp")                       │
│   gdf.to_file("output.geojson", driver="GeoJSON")        │
│                                                         │
│ AI 提供 Python 替代方案并对比两种方式                     │
└─────────────────────────────────────────────────────────┘

2.8.2 不同场景的加载路径对比

用户提问 加载路径 文件数 Token 估算
“Shapefile 转 GeoJSON” 直钻 L1 → L3 2(根 SKILL.md + gdal/SKILL.md) ~30K
“Python 做 GIS 分析用什么?” 渐进 L1 → L2 → L3(s) 3+(根 SKILL.md + gis/SKILL.md + 多个 L3) ~50K
“ogr2ogr 怎么指定输出坐标系?” 直钻 L3 1(gdal/SKILL.md) ~18K
“完整 GIS 管道:数据→分析→服务” L1 → L3(opengis-all) 2(根 SKILL.md + opengis-all/SKILL.md) ~50K
“CAD 建模和 GIS 数据处理” L1 → 两个 L2 → 两个方向的 L3 4+ ~80K

2.8.3 加载决策的优化策略

AI 工具在使用三层架构时可以应用以下优化策略:

  1. 缓存 L1 索引:根 SKILL.md 的标签索引表不常变化,可以缓存为结构化数据,后续查询无需重新加载整个文件
  2. 场景表优先:先检查场景推荐表——如果命中,跳过标签搜索,直接加载推荐的技能
  3. L2 作为备选:只有当 L1 的标签搜索返回 3 个以上候选时,才加载 L2 分类索引用以细化选择
  4. reference 延迟加载:先加载 L3 主文件(通常 < 500 行);只有当用户追问高级用法时才加载 reference 子文件

2.9 与其他知识组织方式的对比

理解三层索引架构的价值,最好的方式是对比其他常见的知识组织方法。

2.9.1 vs 官方文档(全量塞入)

维度 官方文档全量加载 opengis-skills 三层索引
Token 消耗 极大(官方文档动辄数百页) 最小(每次只加载 1-3 个技能文件)
信息密度 低(大量导航、版本说明、贡献指南等非核心内容) 高(只保留 API、工作流、FAQ 等可操作知识)
时效性 依赖文档版本 依赖 SKILL.md 的更新频率(可通过引用官方文档链接补充)
AI 友好度 低(官方文档为人类设计,结构复杂) 高(专门为 AI 工具设计,”Use when…” 触发式描述)
维护成本 零(直接引用) 需要持续与上游文档同步

官方文档是”原材料”,三层索引是”经过预处理的半成品”。AI 工具真正需要的是半成品——已经提取出关键 API、典型工作流、常见问题的精华内容,而不是 XML 标签、版本迁移指南和贡献者名单。

2.9.2 vs RAG(向量检索)

维度 RAG(向量检索) 三层索引 + 标签搜索
搜索方式 语义相似度匹配(Embedding → 向量搜索) 结构化标签匹配 + AI 语义理解
精度 依赖 Embedding 模型质量和分块策略 依赖标签设计质量和 skill description 的”Use when…“触发式描述
基础设施 需要向量数据库 + Embedding 服务 零依赖,纯文件系统
透明度 黑盒(为什么匹配到这个片段?) 白盒(标签交集 + 层级路径清晰可见)
上下文连贯性 返回零散片段,可能不完整 返回完整的技能文件,上下文自包含
部署难度 中高(需要搭建检索管线) 极低(git clone + 加载文件)

三层索引和 RAG 并非互斥关系。在实际使用中,可以结合两者:RAG 用于初步搜索(找到语义相关的技能),三层索引用于精确定位和深度加载。opengis-skills 当前选择了纯文件系统的标签搜索方案,是因为 GIS/CAD/3D 等领域的工具数量有限(67 个),结构化标签已经足够精准,不需要借助 Embedding 的模糊匹配能力。

2.9.3 vs 提示词模板(Prompt Templates)

维度 提示词模板 三层索引
可组合性 低(每个模板是独立的,难以组合) 高(技能之间通过引用关系组合)
可引用性 无(模板之间没有显式引用) 强(相对路径引用形成知识图谱)
更新维护 每个模板独立更新 修改一个技能文件,引用它的其他技能自动受益
组织方式 扁平列表 层级+标签双维度索引
适用规模 几个到几十个模板 几十到几百个技能

提示词模板适用于3-5 个高频场景的速查,三层索引适用于50+ 个工具的系统化管理。opengis-skills 的 67 个技能如果以扁平列表的方式组织,AI 工具需要线性扫描整个列表才能定位目标——这正是三层架构要解决的”搜索成本随技能数量线性增长”的问题。

2.9.4 vs 微调模型(Fine-tuned Models)

维度 微调模型 三层索引
知识更新 需要重新训练或持续预训练 编辑 SKILL.md 文件即可
知识范围 局限于训练数据中的版本 始终指向最新版本的官方文档
成本 高昂(GPU 训练 + 模型托管) 极低(Markdown 文件)
灵活性 固定(模型权重不可动态修改) 灵活(可动态加载、组合、替换技能)
跨模型适用 每个模型需要单独微调 一份技能文件适用于所有支持 @ 语法或文件加载的 AI 工具

微调模型的优势在于零加载延迟——知识已经编码在模型权重中。三层索引的优势在于动态性和可维护性——新增一个库的支持只需要创建一个 SKILL.md 文件,不需要重新训练模型。在开源 GIS/CAD 工具领域(新版本、新库频繁出现),三层索引的动态更新能力远比微调模型的固定知识更具实用价值。

2.9.5 三层索引的核心竞争力总结

特性 三层索引 传统方式
加载粒度 按需:1-3 个文件(30-80K Token) 全量:所有文档(200万+ Token)
搜索方式 结构化标签 + 层级导航 全文搜索或手动翻阅
知识更新 编辑 Markdown 文件 重新索引或替换文档
技能组合 引用链自动扩展上下文 需 AI 自行拼接知识
部署方式 git clone + @ 语法 依赖特定工具或 API
适用模型 所有支持文件加载的 AI 工具 视具体方案而定

三层索引架构的设计哲学可以用一句话概括:用最少的 Token 提供刚好够用的信息,让 AI 工具在正确的层级做出正确的判断。它不是最复杂的技术方案,但它是最适合当前 AI 工具上下文约束的方案——在 Token 窗口有限、按 Token 计费的现实下,信息密度的优化比搜索算法的精度更重要。

2.10 本章小结

三层索引架构是 opengis-skills 仓库的核心设计,它通过 L1(全局入口)→ L2(分类索引)→ L3(项目技能) 的三级分层解决了四个关键问题:

  1. Token 效率:按需加载 1-3 个技能文件(约 30-80K Token),相比全量加载(约 210 万 Token)节省 98% 以上的上下文窗口
  2. 粒度匹配:L1 提供 67 个技能的全局概览,L2 提供某个领域的 1-23 个技能概要,L3 提供单个工具的深度知识——每一层刚好匹配一种典型的知识需求
  3. 智能路由:标签索引系统让 AI 工具通过 语言 + 功能 的双维度标签组合快速定位目标技能,场景推荐表让高频问题实现零推理成本的直接命中
  4. 知识网络:文件之间的相对路径引用构建了一个可遍历的知识图谱,AI 工具可以沿着引用链自动扩展上下文,实现跨技能的协作方案

在下一章中,我们将深入分析 L3 技能的核心组件——SKILL.md 编写规范,包括 YAML frontmatter 的精确字段定义、正文章节的编排原则、代码示例的格式化标准,以及如何将一个开源项目的官方文档转化为 AI 友好的结构化知识。