从零构建 DeepClassify一个本地代码工程智能管理 Agent拖入代码工程 → 自动扫描 → AI 分类 → 生成文档 → RAG 语义搜索。全程本地运行无需联网你的代码不离开你的机器。github链接https://github.com/lsy511640489/DeepClassify演示视频链接https://www.bilibili.com/video/BV1SVjm6oE4b/缘起为什么我需要这个工具作为一个同时在维护 30 个代码仓库的开发者我面临一个普遍的困境接手同事的项目看不懂这是干什么的三个月前自己从github上拉的代码忘记这是做啥的硬盘里散落着各种嵌入式工程、Web 项目、AI 实验根本分不清现有的方案要么是云端的代码上传到第三方要么是纯手动的写 README 靠自觉。我想要的很简单把代码文件夹拖进去自动告诉我是干什么的然后能随时搜索找到。于是有了 DeepClassify。设计哲学三个核心决策1. 本地优先不是口号所有数据 —— SQLite 数据库、ChromaDB 向量索引、生成的 Markdown 文档 —— 全部存在你的硬盘上。LLM 通过调用本地的 Ollama 或你自己的 DeepSeek API Key 完成代码工程一行都不会上传到第三方服务器。这意味着内网环境也能用没有 API 费用用 Ollama 本地模型时工程代码绝对隐私2. AI 主导分类规则兜底传统的代码分类工具依赖正则匹配检测到.ioc文件 → STM32 工程检测到package.json→ 前端项目。这有两个致命问题覆盖盲区新框架、自研框架、混合工程无法识别误判一个引用了 STM32 HAL 库的 PC 仿真器会被误判为嵌入式工程我的做法是反过来┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ Stage 1 │────▶│ Stage 2 │────▶│ Stage 3 │ │ 规则预筛选 │ │ ★ AI 分类 │ │ 规则校验 │ │ 提取硬信号 │ │ LLM 读源码 │ │ 交叉验证 │ │ 供 AI 参考 │ │ 自主判断 │ │ 矛盾降置信度 │ └──────────────┘ └──────────────┘ └──────────────┘让 AI 读完关键源文件后自己决定 “这个工程是什么”规则只在 AI 不可用时兜底以及在 AI 给出结果后做一致性验证。3. 事件驱动的管道架构整个处理流程被建模为一条 7 步管道拖入工程 → 创建记录 → 扫描指纹 → AI分类 → 生成摘要 → 渲染文档 → 向量索引 │ │ └────────── 每一步通过 EventBus 发出事件 → WebSocket 实时推送 ───────┘前端能实时看到进度“正在扫描文件结构…” → “AI 正在分析工程类型…” → “正在生成文档…” → “完成”技术全景整体架构┌──────────────────────┐ ┌──────────────────────┐ │ Desktop UI │ │ Web UI │ │ Avalonia .NET 10 │ │ React 19 Vite 8 │ │ MVVM Fluent │ │ Tailwind 4 Zustand│ └──────────┬───────────┘ └──────────┬───────────┘ │ HTTP REST │ │ 127.0.0.1:8765/api/v1 │ └──────────┬───────────────┘ │ ┌──────────▼───────────┐ │ FastAPI Backend │ │ Python 3.12 │ │ │ │ ┌────────────────┐ │ │ │ EventBus │ │ │ └───────┬────────┘ │ │ │ │ │ ┌───────▼────────┐ │ │ │ Pipeline │ │ │ │ Scan→Classify │ │ │ │ →Doc→Index │ │ │ └───────┬────────┘ │ │ │ │ │ ┌───────▼────────┐ │ │ │ RAG Engine │ │ │ │ Hybrid Search │ │ │ └────────────────┘ │ └──────────┬───────────┘ │ ┌──────────▼───────────┐ │ Data Layer │ │ SQLite ChromaDB │ │ File System │ └──────────────────────┘技术栈速览层技术选型理由Desktop UIAvalonia 12 .NET 10 CommunityToolkit.Mvvm跨平台桌面框架MVVM 源码生成器消除样板代码Web UIReact 19 TypeScript 6 Tailwind 4 Zustand轻量、类型安全、原子化 CSSBackendFastAPI SQLAlchemy aiosqlite ChromaDB异步 Python、本地向量存储Embeddingsentence-transformers (all-MiniLM-L6-v2)384 维仅 80MB离线运行LLMDeepSeek / Ollama / Claude 三 Provider 可切换灵活适配不同场景PackagingPyInstaller .NET Publish后端打包为单一 exe桌面端自包含发布核心模块拆解1. 工程指纹扫描器 — 不只是数文件扫描器 (src/scanner/) 生成一个包含 15 个字段的ProjectFingerprintfingerprint: file_count: 142 total_size_mb: 3.2 languages: { C: 65%, Python: 20%, CMake: 10%, Assembly: 5% } frameworks: [STM32 HAL, FreeRTOS, CMSIS-DSP] build_systems: [CMake, Makefile] dependencies: [arm-none-eabi-gcc, stm32cube-f4] key_files: [main.c, stm32f4xx_it.c, motor_control.c] key_dirs: [Core/, Drivers/, Middleware/] readme_summary: 基于STM32F407的无刷直流电机FOC控制... source_samples: { motor_control.c: void FOC_Clark(...){...}, ... }关键在于不只是匹配文件名——它会解析CMakeLists.txt中的target_link_libraries、package.json的dependencies、甚至 STM32 CubeMX 的.ioc文件从中提取出有意义的框架和依赖信息。framework_detector.py内置了 35 种框架的签名数据库。2. 三级分类器 — AI 为核心规则为安全网Stage 1 — 预筛选(rule_prefilter.py)快速提取硬信号文件模式、依赖名称、框架签名生成结构化线索{clues:{embedded_signals:[STM32 HAL,FreeRTOS,CMSIS-DSP],likely_l1:embedded,hard_evidence:[.ioc文件存在,startup_stm32f407xx.s 存在]}}这些线索不直接决定分类而是作为 AI 的参考上下文。Stage 2 — AI 分类(llm_classifier.py)构建一个包含指纹数据、预筛选线索和关键源码样本的 Prompt让 LLM 输出{l1:embedded,l2:stm32,l3:motor-control,confidence:0.92,reasoning:该工程包含STM32F407的FOC算法实现使用CMSIS-DSP库进行Clarke/Park变换判断为STM32电机控制工程}LLM 可以自由创建taxonomy.yaml中不存在的新子类别——分类树是开放的。Stage 3 — 校验(rule_validator.py)将 AI 的分类结果与硬信号交叉比对。比如 AI 返回l1: web但工程里有.ioc文件和startup_stm32.s校验器会将置信度从 0.85 降到 0.3 —— 显然是误判。降级路径当 LLM 不可用时离线 / 配额耗尽系统自动切换到纯规则模式——25 条优先级规则逐条尝试最终UnknownRule兜底。3. RAG 混合检索引擎 — 语义 关键词只用向量搜索的问题是搜 “FOC 电机控制” 可能漏掉标题就是foc_motor.c但描述用词不同的文档。只用关键词搜索的问题是搜 “无刷直流电机控制” 找不到只写了 “BLDC Control” 的文档。所以用了混合检索 RRF 融合用户查询: FOC 矢量控制 │ ├──▶ ChromaDB 语义搜索 ──▶ [doc1:0.89, doc3:0.78, doc5:0.72] │ ├──▶ SQLite FTS5 全文搜索 ──▶ [doc3:0.91, doc2:0.85, doc1:0.60] │ └──▶ RRF 融合 ──▶ [doc3, doc1, doc2, doc5] (重排序)RRF (Reciprocal Rank Fusion) 公式score Σ 1/(k rank_i)k60。简单但有效——不依赖分数归一化对语义和关键词搜索的分数尺度差异不敏感。4. 文档生成器 — 按分类定制模板不同领域的工程需要不同的文档结构。用 Jinja2 模板 按一级分类路由src/documentor/templates/ ├── base.md.j2 ← 基础布局所有文档共用 ├── embedded.md.j2 ← 嵌入 MCU 信息、外设配置、引脚分配 ├── ai_ml.md.j2 ← 模型架构、训练数据、评估指标 ├── web.md.j2 ← 前后端分离、API 接口、部署方式 └── default.md.j2 ← 兜底模板每个模板注入三个信息来源README 概述从工程原始 README 提取LLM 摘要2–4 句中文功能描述规则概述从指纹数据自动生成的技术栈清单5. 事件总线 — 解耦的秘密武器整个系统通过一个不到 100 行的EventBus实现模块间通信# 发布者管道发出进度事件awaitevent_bus.emit(project.scan_done,{project_id:id,fingerprint:fp})# 订阅者 1WebSocket 广播给前端event_bus.subscribe(project.scan_done)asyncdefws_broadcast(event):forwsinconnected_clients:awaitws.send_json(event)# 订阅者 2任何模块都可以监听event_bus.subscribe(project.ready)asyncdefon_project_ready(event):# 比如发送桌面通知、触发 CI 流水线...pass这带来的好处是添加新功能不需要修改现有代码。想做桌面通知订阅project.ready事件即可。想做自动备份订阅project.ready事件即可。Pipeline、WebSocket、未来的任何模块完全解耦。双向 UIDesktop WebDeepClassify 有两套 UI共用同一套后端 APIDesktop UI (Avalonia)面向日常桌面使用的用户。特点原生 Windows 窗口启动快内存占用低内置 AI 聊天SSE 流式可以直接用自然语言问 “有哪些做电机控制的 STM32 工程”知识图谱可视化— Canvas 手绘节点力模拟布局拖拽旋转交互粉色模式 少女粉模式—— 一点小趣味MVVM 架构使用 CommunityToolkit.Mvvm 的源码生成器publicpartialclassSearchViewModel:ObservableObject{[ObservableProperty]privatestring_query;[RelayCommand]privateasyncTaskSearchAsync(){Resultsawait_api.SearchAsync(Query);}}// [ObservableProperty] 自动生成 Query 属性 PropertyChanged// [RelayCommand] 自动生成 SearchCommandWeb UI (React)面向浏览器访问的场景比如 NAS 上部署、局域网共享。特点SVG 力导向知识图谱— 600 次迭代物理模拟拖拽缩放项目卡片仪表盘 recharts 饼图Tailwind 暗色模式保护深夜工作的眼睛可拖拽侧边栏宽度持久化到 localStorage数据流全景让我用一个完整的例子串联所有模块1. 用户将 foc_motor_ctrl/ 文件夹拖入 data/inbox/ 2. WatchService (watchdog) └─ 检测到新目录 → 去抖 10s → 验证是否为有效代码工程 └─ emit(project.detected, {path: data/inbox/foc_motor_ctrl}) 3. Pipeline.process_project() ├─ Step 1: 在 SQLite 创建 Project 记录 (status: detected) ├─ Step 2: Scanner 扫描 │ └─ 遍历 142 个文件 → 发现 .ioc startup_stm32f407.s FreeRTOSConfig.h │ └─ 解析 CMakeLists.txt → 提取 arm-none-eabi-gcc, CMSIS-DSP │ └─ 生成 ProjectFingerprint → emit(project.scan_done) ├─ Step 3: Classifier 分类 │ └─ PreFilter → clues: {likely_l1: embedded, signals: [STM32, FreeRTOS]} │ └─ LLM 读取 main.c motor_control.c → 这是 STM32F407 的 FOC 电机控制 │ └─ Validator → 交叉验证通过 → emit(project.classify_done) ├─ Step 4: LLM 摘要 │ └─ 基于STM32F407的FOC矢量控制工程使用FreeRTOS多任务架构... ├─ Step 5: Documentor → Jinja2 渲染 embedded.md.j2 │ └─ 输出到 data/projects/embedded/stm32/foc_motor_ctrl.md ├─ Step 6: RAG Indexer │ └─ Chunker 按 ## 标题分割 → 每个chunk嵌入为384维向量 │ └─ 写入 ChromaDB SQLite FTS5 → emit(project.ready) └─ 完成! status: ready 4. 用户搜索 FOC 矢量控制 └─ Retriever 混合搜索 → ChromaDB 语义 FTS5 关键词 → RRF 融合 └─ 返回: [foc_motor_ctrl (score: 0.94), bldc_driver (score: 0.78), ...] 5. 用户在 AI Chat 中问 foc_motor_ctrl 用了哪些外设 └─ Chat API → RAG 检索相关文档块 → 拼接 Prompt → LLM 回答一些有意思的实现细节去抖 (Debounce) 不只是前端的事文件监听器面临的问题用户拖入一个 500MB 的工程文件夹操作系统需要几秒甚至十几秒才能完成复制。如果每检测到一个新文件就触发处理会变成灾难。解决方案每路径异步去抖——在该路径上 10 秒没有新事件后才触发处理。ChromaDB 的 PyInstaller 兼容ChromaDB 依赖onnxruntime和pypika这两个包在 PyInstaller 打包时需要显式声明 hidden-import。否则打包后的 exe 跑不起来。BUILD.md 里专门有一节 troubleshooting 记录踩过的坑。嵌入模型的离线缓存sentence-transformers默认从 HuggingFace Hub 下载模型。在国内网络环境下这可能需要数次重试。系统做了两件事模型缓存到data/model_cache/二次启动秒加载支持HF_ENDPOINThttps://hf-mirror.com镜像加速知识图谱的简易物理引擎KnowledgeGraph.tsx没有引入 D3 或任何图布局库而是手写了 600 次迭代的力模拟for i in 0..600: cooling exp(-i / 200) # 指数衰减 for each node pair: dx node2.x - node1.x dist max(|dx|, 1) force REPULSION / dist² # Coulomb 斥力 node1.x - force * dx * cooling node2.x force * dx * cooling for nodes in same category: # 同类节点轻微吸引 attract_towards_centroid()简单但效果不错——几百个节点也能在几百毫秒内完成布局。项目结构一览deepClassify/ ├── desktop_ui/ # Desktop UI (Avalonia .NET) │ └── DeepClassify.App/ │ ├── Views/ # .axaml 页面 (6个) │ ├── ViewModels/ # MVVM ViewModel (8个) │ ├── Services/ # ApiClient ThemeService │ └── Models/ # DTO 记录类型 │ ├── web_ui/ # Web UI (React Vite) │ └── src/ │ ├── pages/ # 5个路由页面 │ ├── components/ # Layout / Sidebar / KnowledgeGraph │ └── stores/ # Zustand 状态 │ ├── src/ # Python 后端 │ ├── api/ # FastAPI (18个REST端点 WebSocket) │ ├── pipeline.py # 核心管道 │ ├── scanner/ # 指纹扫描 (50语言, 35框架) │ ├── classifier/ # 三级分类 (AI主导 25条规则) │ ├── documentor/ # Jinja2文档生成 (5套模板) │ ├── rag_engine/ # 混合检索 (ChromaDB FTS5 RRF) │ ├── storage/ # SQLAlchemy SQLite │ └── watch_service/ # 文件系统监听 │ ├── taxonomy.yaml # 分类体系 (9大类, 50子类) ├── design-assets/ # ★ 设计资产 复用指南 │ ├── README.md # 设计资产复用文档 │ └── BLOG.md # 本篇博客 └── docs/ # 架构 RAG 嵌入模型 文档适用场景 局限适合管理大量散落的代码工程嵌入式 / AI / Web / FPGA 混合场景尤其受益团队知识管理 —— 新人来了能快速了解每个工程是干什么的个人开发者整理多年的代码积累对代码隐私有严格要求的环境不适合单个巨型 monorepo 的分类扫描器针对独立工程目录设计需要协作编辑的场景文档生成是单向的动态语言的精确分类Python/JS 工程的框架检测不如 C/C 工程精确写在最后这个项目的核心思路很简单让 AI 读你的代码帮你理解你的代码。