从零构建 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轻量、类型安全、原子化 CSS
BackendFastAPI + SQLAlchemy + aiosqlite + ChromaDB异步 Python、本地向量存储
Embeddingsentence-transformers (all-MiniLM-L6-v2)384 维,仅 80MB,离线运行
LLMDeepSeek / Ollama / Claude 三 Provider 可切换灵活适配不同场景
PackagingPyInstaller + .NET Publish后端打包为单一 exe,桌面端自包含发布

核心模块拆解

1. 工程指纹扫描器 — 不只是数文件

扫描器 (src/scanner/) 生成一个包含 15 个字段的 ProjectFingerprint

fingerprint:
  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_librariespackage.jsondependencies、甚至 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)k=60。简单但有效——不依赖分数归一化,对语义和关键词搜索的分数尺度差异不敏感。

4. 文档生成器 — 按分类定制模板

不同领域的工程需要不同的文档结构。用 Jinja2 模板 + 按一级分类路由:

src/documentor/templates/
├── base.md.j2        ← 基础布局(所有文档共用)
├── embedded.md.j2    ← 嵌入 MCU 信息、外设配置、引脚分配
├── ai_ml.md.j2       ← 模型架构、训练数据、评估指标
├── web.md.j2         ← 前后端分离、API 接口、部署方式
└── default.md.j2     ← 兜底模板

每个模板注入三个信息来源:

  1. README 概述(从工程原始 README 提取)
  2. LLM 摘要(2–4 句中文功能描述)
  3. 规则概述(从指纹数据自动生成的技术栈清单)

5. 事件总线 — 解耦的秘密武器

整个系统通过一个不到 100 行的 EventBus 实现模块间通信:

# 发布者:管道发出进度事件
await event_bus.emit("project.scan_done", {"project_id": id, "fingerprint": fp})

# 订阅者 1:WebSocket 广播给前端
@event_bus.subscribe("project.scan_done")
async def ws_broadcast(event):
    for ws in connected_clients:
        await ws.send_json(event)

# 订阅者 2:任何模块都可以监听
@event_bus.subscribe("project.ready")
async def on_project_ready(event):
    # 比如:发送桌面通知、触发 CI 流水线...
    pass

这带来的好处是:添加新功能不需要修改现有代码。想做桌面通知?订阅 project.ready 事件即可。想做自动备份?订阅 project.ready 事件即可。Pipeline、WebSocket、未来的任何模块完全解耦。


双向 UI:Desktop + Web

DeepClassify 有两套 UI,共用同一套后端 API:

Desktop UI (Avalonia)

面向日常桌面使用的用户。特点:

  • 原生 Windows 窗口,启动快,内存占用低
  • 内置 AI 聊天(SSE 流式),可以直接用自然语言问 “有哪些做电机控制的 STM32 工程?”
  • 知识图谱可视化 — Canvas 手绘节点,力模拟布局,拖拽旋转交互
  • 粉色模式(🌸 少女粉模式)—— 一点小趣味

MVVM 架构使用 CommunityToolkit.Mvvm 的源码生成器:

public partial class SearchViewModel : ObservableObject
{
    [ObservableProperty]
    private string _query = "";

    [RelayCommand]
    private async Task SearchAsync()
    {
        Results = await _api.SearchAsync(Query);
    }
}
// [ObservableProperty] 自动生成 Query 属性 + PropertyChanged
// [RelayCommand] 自动生成 SearchCommand

Web 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 依赖 onnxruntimepypika,这两个包在 PyInstaller 打包时需要显式声明 hidden-import。否则打包后的 exe 跑不起来。BUILD.md 里专门有一节 troubleshooting 记录踩过的坑。

嵌入模型的离线缓存

sentence-transformers 默认从 HuggingFace Hub 下载模型。在国内网络环境下,这可能需要数次重试。系统做了两件事:

  1. 模型缓存到 data/model_cache/,二次启动秒加载
  2. 支持 HF_ENDPOINT=https://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 读你的代码,帮你理解你的代码

Logo

小龙虾开发者社区是 CSDN 旗下专注 OpenClaw 生态的官方阵地,聚焦技能开发、插件实践与部署教程,为开发者提供可直接落地的方案、工具与交流平台,助力高效构建与落地 AI 应用

更多推荐