← Back to skills
extension
Category: Productivity & OfficeAPI key requirement unconfirmed

local-file-search

在 Windows + Git Bash 上执行本地文件名索引与检索的操作流程:定位 ai-file-search 工具、用 D:/ 形式路径建立或刷新索引、执行关键词 / 本地 AI / 语义查询、AI 解析回退时拆分核心词并取交集,并始终保持只输出文件基本文件名。当用户要求查找本地文件或资料、检索某课程文档、按名称检索文件、列举目录文件、为大目录建立或刷新索引、给文件搜索测速或验收、生成可移植检索技能交付包、换电脑启用本地文件检索,或本地查询返回 0 结果需要排障时使用。全程只枚举文件名,不读取内容,不联网。

personAuthor: ylyhf2026hubModelScope

本地文件名检索全流程

1. 概述

本地文件名检索的完整生命周期:查询前确认 → 隐私边界 → 建索引与查询 → 零结果排障 → 性能基准 → 可移植打包。

支持三种检索模式:

  • 关键词查询(FTS5):精确文件名匹配,毫秒级响应,优先使用。
  • AI 查询(--ai):本地生成模型将自然语言提取为文件名词片段,再走 FTS5 检索,约 8-10 秒。
  • 语义查询(--semantic):本地 OpenVINO 嵌入模型检索概念相近的文件名,约 4 秒,需预建向量索引。

--ai 与 --semantic 互斥。三种及以上字符的普通查询走 FTS5 快速路径;语义查询适合名称不同但概念相近的文件名。

2. 隐私边界(不可协商)

  • 只枚举目录项中的文件名;禁止打开、读取、哈希或解析被索引文件。
  • 索引数据库仅保存在本机,内部路径只用于去重与同步;查询结果只输出基本文件名。
  • --ai 的生成模型只接收用户查询文本。--semantic 的嵌入模型在建索引时只接收规范化文件名(NFKC、小写),不接收路径或文件内容。
  • 本地模型进程均通过 execFile 启动,不经 Shell。日常索引与查询不使用网络;仅用户手动运行 setup-environment.mjs --install 时,才允许 pip 下载缺失 Python 包,且不会下载模型。
  • 索引库 <工具目录>/data/file-index.sqlite 含本机本地路径,属敏感数据:禁止复制到其他电脑或放进交付包。

3. 查询前确认清单

写检索代码或调用工具前逐项确认(用户本轮已明确的项不重复问):

  1. 搜索根目录:查哪些目录?多目录逐一列出并标注用途。
  2. 查询模式:关键词(含自然语言、语义),还是全量列举?全量列举先约定数量上限。
  3. 输出范围:默认只输出基本文件名;不输出路径、大小、时间戳、权限、哈希等元数据。重名文件重复出现是有意的隐私取舍。要求更多字段视为隐私边界变更,须明确确认。
  4. 规模与性能预期:预估文件数量;上万文件必须用预建索引,禁止实时遍历;几百文件的小目录可直接枚举,仍只输出基本文件名。

4. 环境检查与工具定位

4.1 工具定位

按顺序定位 scripts/ai-file-search.mjs,取第一个存在的位置作为 <工具目录>:

  1. <工作区>/.trae/skills/local-file-search/
  2. <工作区>/.qoder/skills/ai-file-search/(历史迁移副本)
  3. %USERPROFILE%/.trae/skills/local-file-search/
  4. %USERPROFILE%/.qoder/skills/ai-file-search/(历史位置)

用 ls 或 Glob 确认目录存在。以上都没有时向用户询问工具位置,不要自行重写检索实现。之后所有命令用绝对路径调用。

4.2 环境检查

首次使用或换机先做环境检查:

node "<工具目录>/scripts/setup-environment.mjs"

检查 Node.js(node:sqlite 需 22.5+)、Python、openvino 与 openvino-genai。提示缺 Python 包时执行:

node "<工具目录>/scripts/setup-environment.mjs" --install
  • 只装缺失的 openvino / openvino-genai,不升级已有包,绝不下载模型。
  • 模块名与包名不一致(如 openvino_genai → openvino-genai),脚本需维护映射。
  • 缺模型时明确报错并引导按 README 手动下载(如 OpenVINO/Qwen3-Embedding-0.6B-int8-ov),绝不自动下载。
  • 模型放工具目录内固定相对位置(如 models/<模型名>/),环境检查必须以工具目录/配置目录为基准解析;相对路径被解析到目录之外是已出现过的缺陷,报告缺失时定位必须准确。

4.3 模型手动下载

模型绝不会被安装脚本自动下载。需手动下载以下 OpenVINO 官方模型并保留仓库目录结构:

| 用途 | 模型 | 放置位置 | | --- | --- | --- | | --ai 自然语言关键词提取 | OpenVINO/Qwen2.5-1.5B-Instruct-int4-ov | models/Qwen2.5-1.5B-Instruct-int4-ov/ | | --semantic 文件名语义检索 | OpenVINO/Qwen3-Embedding-0.6B-int8-ov | models/Qwen3-Embedding-0.6B-int8-ov/ |

嵌入模型目录至少应直接包含:openvino_model.xml、openvino_model.bin、openvino_tokenizer.xml、openvino_tokenizer.bin、config.json、tokenizer_config.json。

5. 建立与更新索引

5.1 文件名索引

node "<工具目录>/scripts/ai-file-search.mjs" init --root "D:/资料"
node "<工具目录>/scripts/ai-file-search.mjs" index --root "D:/资料"
  • 路径必须写成 D:/ 或 "D:/资料" 形式。写成 D:\(末尾反斜杠)会让 Git Bash 直接报 unexpected EOF while looking for matching '"'(Exit 2),命令根本不会执行,不要在这个写法上重试。
  • init 和 index 都只读取目录项的名称与类型,不打开目标文件。init 会重置整个库,旧结果随之丢失。
  • 每台电脑都应自行建索引;不要复制其他电脑的 data/file-index.sqlite,其中可能包含原电脑的本地路径。
  • 实测基线:D 盘整盘约 391,000 个文件名、约 50 秒、跳过约 190 个不可访问目录;C 盘整盘约 785,000 个文件名、约 146 秒、跳过约 593 个。大目录放在空闲时执行。
  • 输出应包含 Indexed file names: N,N 与目标目录规模相符。

5.2 语义向量索引

在已有文件名索引上生成或更新向量:

node "<工具目录>/scripts/ai-file-search.mjs" semantic-index

也可在更新文件名索引后立即增量更新向量:

node "<工具目录>/scripts/ai-file-search.mjs" index --root "D:/资料" --semantic
  • 嵌入模型只接收规范化文件名(如 唐宋觉醒课程.pdf),不接收路径、文件内容或文件元数据。向量仅保存于本机 SQLite 数据库。
  • 为每个规范化文件名生成向量(Qwen3-Embedding-0.6B 为 1024 维),以归一化 float32 BLOB 存入 SQLite 表 file_name_embeddings。
  • 模型变更(路径或维度不同)时全部向量重建。新增或改名文件只会生成必要的新向量。
  • 池化根因(重要坑):openvino_genai TextEmbeddingPipeline 默认用 CLS 池化,Qwen3 系必须显式设置 pooling_type = LAST_TOKEN。否则向量近共线:实测无关文本余弦从 0.926 修复后降到 0.429。建语义索引前先跑区分度探针(见 §11 验证清单·语义)。

6. 查询

6.1 关键词查询

node "<工具目录>/scripts/ai-file-search.mjs" search --query "项目预算" --limit 30

默认关键词查询,毫秒级(实测约 100 ms),优先使用。

6.2 AI 查询

node "<工具目录>/scripts/ai-file-search.mjs" search --query "找今年的项目预算表" --ai

本地模型把自然语言转成文件名词片段,实测约 8-10 秒。

6.3 语义查询

node "<工具目录>/scripts/ai-file-search.mjs" search --query "唐宋觉醒创业课程" --semantic

文件名向量召回,实测约 4 秒。需先用 index --semantic 或 semantic-index 生成向量索引。与 --ai 互斥。

6.4 查询输出核对

  • 每次查询核对输出首两行:Query parser: ... 与 Matched file names: N。
  • 索引不存在时报 No local index exists. Run init --root <directory> first.,先建索引再查询。
  • 只输出基本文件名;重名重复出现是预期取舍,不为去重补充路径。

7. 零结果排障(按顺序)

  1. 看 Query parser 字段。出现 local-keywords 说明本地模型解析失败并静默回退,此时 0 结果不代表没有匹配文件。
  2. 拆分核心词分别检索再取交集。实测长句 0 命中,核心词单独检索分别命中 1 条与 32 条,取交集收敛到唯一目标。
  3. local-ai 不代表一定命中:检查模型解析出的词是否为整句或泛化短语。若提取结果只有单个片段——整句或如「相关文档」这类泛化短语,而非 2-6 个短词片段——FTS 仍 0 命中,改走第 2 条人工拆词。
  4. 检索片段 >= 3 字符:三元索引只对 3+ 字符走快速路径,1-2 字符退回 LIKE;用 xlsx 而不是 xl。
  5. 去掉泛化词:文件 / 文件夹 / 目录 / 文档 / 脚本 / file / script 等不参与检索,否则 AND 条件清空结果。
  6. 仍 0 结果时向用户确认目标目录是否已被索引覆盖;覆盖范围无法从 config.json 或查询输出得知,不确定时直接按目标根目录重建索引,不要直接回复「未找到」。

8. 多盘/多根目录检索

工具为单索引库设计:search 没有 --root 参数,只检索当前索引库;init 会重置整个库,旧结果随之丢失。需要在多个盘/根目录查同一文件时,逐盘串行执行「init -> index -> search」:

  • 对下一盘执行 init 前,先把当前盘查询结果完整记录到回复(或转存);重置后无法找回。
  • 覆盖不明的旧索引可先查一次作早期参考,但结果无法归属到具体盘;最终结论以逐盘重建后的查询为准。
  • 索引覆盖的根目录无法探知:config.json 与查询输出均不记录当前根目录。覆盖不明时直接按目标根目录重建,不要探测。
  • 实测参考(2026-09-26):C 盘 785,019 个文件名、约 146 秒、跳过 593 个目录;D 盘 392,324 个、约 61 秒、跳过 194 个;关键词查询 3-25 ms。

9. 性能基准

对文件名检索引擎做可复现延迟基准,比较三种路径:

| 引擎 | 建索引耗时 | 查询延迟(中位数) | 隐私暴露面 | 备注 | |------|-----------|------------------|-----------|------| | 递归扫描 | 无 | … | 仅枚举 | 基线 | | SQLite FTS5 | … | … | 仅文件名入索引 | 注明脚本路径与校验时间 | | Everything/USN | 外部 | … | 系统级索引 | 未安装则注明 |

流程:

  1. 确认目标目录与规模档位(小 <1 万 / 中 1-10 万 / 大 >10 万文件)。
  2. 定位 ai-file-search 脚本(§4.1),记录脚本路径与校验时间防版本漂移。
  3. 递归扫描基线:对目标根目录计时一次完整递归枚举(仅文件名)。
  4. FTS5 建索引:init 计时,记录索引文件数、跳过目录数。
  5. 查询计时:>= 3 组代表性查询(短词 / 长中文词 / 扩展名),每组 >= 3 次取中位数;区分首查与热查。
  6. Everything(若 es.exe 在 PATH):同查询词计时取中位数;未安装仅记录「未安装,作为外部基线引用已知结论」,不引导安装第三方软件。
  7. 可选 AI 路径:--ai 或 --semantic 延迟单独标注「冷启动、每次独立进程」,不与关键词热路径混合比较。

结论必须包含:FTS5 索引查询显著快于每次递归扫描;Everything 的 NTFS/USN 是精确文件名检索的性能上限,不承诺超过。附环境说明(磁盘类型、杀毒软件、冷/热缓存),注明「非严格实验条件」。

10. 可移植打包

10.1 审查本机依赖

  • Grep 技能目录中的绝对路径模式:[A-Z]:\\、/Users/、/home/,逐一改为可移植形式。
  • 识别三类本机依赖:模型或运行器路径、索引/数据库文件、临时测试产物(__pycache__、*.pyc、测试用配置)。

10.2 相对化配置

  • 配置中的路径改用 {{configDir}} 等占位符,解析基准必须是配置文件所在目录,不能依赖进程启动目录。
  • 模型统一放技能内固定相对目录(如 models/<模型名>),不指向用户盘符。

10.3 幂等环境检查

  • scripts/setup-environment.mjs:检查 Node.js、Python、Python 包,维护模块名->包名映射。
  • --install 仅安装缺失项;已安装依赖跳过并输出 ready。
  • 模型缺失时明确报错并 exit 1,写明模型下载被有意禁用、按 README 手动下载;绝不自动下载。

10.4 排除本机数据

交付包禁止包含:data/、*.sqlite(含旧机器绝对路径)、模型文件本体(用户手动下载)、__pycache__、*.pyc、临时测试配置与测试目录。

10.5 安装位置

  • TRAE 用户级:C:\Users\<用户名>\.trae\skills\local-file-search\
  • TRAE 项目级:<工作区>/.trae/skills/local-file-search/
  • 交付目录名必须与技能名一致。

11. 验证清单

检索

  • [ ] 索引输出含 Indexed file names: N,N 与目标目录规模相符。
  • [ ] 查询输出含 Query parser: 与 Matched file names: 两行。
  • [ ] 命中项均为基本文件名,无路径、无内容片段。
  • [ ] 0 结果时已按 §7 排障,说明回退与拆词实际命中数。

语义

  • [ ] 区分度探针:嵌入 2-3 个明显无关文本(如「猫」与「量子力学」),两两余弦必须 < 0.8;接近 1 说明嵌入退化(先查 §5.2 池化设置),排序不可信。
  • [ ] 建隔离测试集(少量空文件,语义可区分的中文名);向量条数等于文件数、维度一致。
  • [ ] 概念化查询命中目标文件名排首位(以探针通过为前提)。
  • [ ] 增量:新增、改名各只加一条向量,删除后过期向量被清理。
  • [ ] 移走模型后环境检查准确报告缺失且不自动下载。

基准

  • [ ] 三种引擎(或注明缺失原因)均有计时数据。
  • [ ] 每组查询 >= 3 次取中位数。
  • [ ] 报告含隐私核对(未读内容、未输出路径、未联网)。

打包

  • [ ] 无绝对路径残留(Grep [A-Z]:\\)。
  • [ ] 无本机索引数据与模型文件。
  • [ ] 环境检查双状态通过(依赖已装 ready;模型缺失报错不下载)。

12. 换机启用顺序

复制工具目录 -> 用户手动下载模型 -> setup-environment.mjs --install -> 重建索引(init -> index -> index --semantic)。