从 0 到 1 搭建本地代码知识库:FastAPI + ChromaDB 落地实践

摘要:在企业级开发中,通用大模型往往面临“不懂业务代码”的尴尬。本文复盘了如何利用开源工具(ChromaDB + Python AST)搭建一套轻量级的本地 RAG(检索增强生成)系统,实现对私有代码库的语义检索与自动同步。


🛑 背景:当 AI 读不懂我的代码

最近在维护一个基于 Spring Boot 的后台脚手架项目时,我遇到了一个典型痛点:

  • 场景:我想让 AI 帮我写一个新功能的 Service 层代码。
  • 问题:AI 不知道我的项目里已经封装了哪些工具类(Utils),也不知道我的 BaseEntity 里有哪些通用字段。它生成的代码往往是“通用的”,而不是“适配我的项目的”。
  • 尝试:一开始我尝试把相关文件复制粘贴给 AI,但随着项目变大,上下文窗口(Context Window)很快就不够用了,而且手动复制非常繁琐。

核心诉求:我需要一个能“自动阅读”并“记住”整个项目代码的系统,当我提问时,它能自己去代码库里找答案。


🛠️ 技术选型:为什么是 ChromaDB?

为了实现这个目标,我调研了市面上常见的向量数据库方案:

  1. Pinecone/Milvus:功能强大,但需要部署服务端,太重了。
  2. Elasticsearch:虽然支持向量检索,但对于一个脚手架项目来说,引入 ES 会大大增加用户的部署成本。
  3. ChromaDB最终选择。它是一个嵌入式的向量数据库,可以直接以 Python 库的形式运行,数据存储在本地文件(SQLite + Parquet),零部署成本

🏗️ 架构设计:RAG 最小闭环

整套系统的架构非常简洁,由三个核心模块组成:

  1. Ingest (摄取):解析 Java 代码,提取类、方法、注解信息。
  2. Vector Store (存储):将文本转化为向量(Embedding),存入 ChromaDB。
  3. Watcher (监听):实时监听文件变更,自动更新向量库。
    请添加图片描述

1. 代码解析与切片 (Python AST)

直接把整个文件塞给 AI 效果并不好,我们需要按“语义”进行切片。对于 Java 代码,我写了一个简单的解析器:

# ai-engine/knowledge_ingest.py (核心逻辑片段)

def parse_java_file(file_path):
    with open(file_path, 'r', encoding='utf-8') as f:
        content = f.read()
    
    # 提取类名、注解等元数据
    # 这里使用正则表达式或 javalang 库进行 AST 解析
    # ...
    
    return {
        "content": content,
        "metadata": {
            "source": file_path,
            "type": "java_class"
        }
    }

2. 向量化存储 (ChromaDB)

初始化 ChromaDB 非常简单,它会自动帮我们下载默认的 Embedding 模型(all-MiniLM-L6-v2),不需要自己折腾 PyTorch。

# ai-engine/vector_store.py

import chromadb
import os

# 指定本地持久化路径
PERSIST_DIRECTORY = os.path.join(os.path.dirname(__file__), "chroma_db")

class VectorStore:
    def __init__(self):
        # 初始化持久化客户端
        self.client = chromadb.PersistentClient(path=PERSIST_DIRECTORY)
        # 获取集合
        self.collection = self.client.get_or_create_collection(name="swiftboot_codebase")

    def add_documents(self, chunks):
        # 自动向量化并存储
        self.collection.add(
            documents=[chunk['content'] for chunk in chunks],
            metadatas=[chunk['metadata'] for chunk in chunks],
            ids=[chunk['id'] for chunk in chunks]
        )

3. 与后端集成 (Java + SSE)

在 Java 后端,我通过 HTTP 接口调用 Python 的检索服务,并将检索到的上下文(Context)拼接到 System Prompt 中。为了提升体验,我还接入了 SSE 实现流式响应。

// SysAiController.java

// 1. 调用 Python RAG 接口检索相关代码
String ragContext = callRagEngine(userQuery);

// 2. 组装 System Prompt
String systemPrompt = "你是智能助手...请优先根据以下代码回答:\n" + ragContext;

// 3. 流式推送到前端
SseEmitter emitter = new SseEmitter(0L);
streamGemini(emitter, systemPrompt, userQuery);

📈 效果与总结

经过这套改造,现在的开发体验发生了质的变化:

  • 准确率提升:AI 生成的代码会自动使用项目里的 SecurityUtils.getUserId(),而不是瞎编一个 UserContext.getId()
  • 自动化:修改了代码,后台 Watchdog 自动更新索引,无需人工干预。
  • 轻量级:整个 AI 引擎作为一个独立的 Python 进程运行,不侵入主业务代码。

这也验证了一个观点:在垂直领域,“小模型 + 优质知识库” 的效果往往优于单纯的"超大模型"。


🔗 参考资料

本文提到的这套 RAG 架构代码已完整开源,包含前端 Vue3 组件、Java 后端控制器以及 Python AI 引擎。

作者: 17334981104 (同微)
如果觉得有帮助,欢迎 Star 支持!

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐