搭建本地基于Open Ai 的数据库

方案概述

  1. 1.数据预处理 :解析本地 Markdown 文件,提取文本内容并进行清洗。
  2. 2.向量化索引 :使用 AI 模型(如文本嵌入模型)将文本内容转化为向量,存储到向量数据库(如 Chroma、Faiss 或 Milvus)。
  3. 3.搜索接口 :通过用户输入的自然语言查询,生成查询向量并与索引库中的向量进行相似度匹配,返回最相关的文档或段落。

步骤实现

1. 安装必要的工具和库

  • Python 环境 :推荐使用 Python 来实现自动化流程。

  • 文本解析库 :用于读取和解析 Markdown 文件。

    bash

    复制代码

    pip install markdown  # 解析 Markdown 语法
    pip install python-markdown
  • 文本嵌入模型

    • 云端模型

      (如 OpenAI 的

      text-embedding-ada-002
      

      ):

      bash

      复制代码

      pip install openai
    • 本地模型

      (如

      SentenceTransformers
      

      Llama
      

      ):

      bash

      复制代码

      pip install sentence-transformers
      # 或者安装本地大模型框架如 localAI、Qwen 的本地版本
  • 向量数据库 :用于存储和快速检索向量。

    bash

    复制代码

    pip install chromadb  # 轻量级向量数据库
    pip install faiss-cpu  # Facebook 的高效向量相似度搜索库
  • 前端框架 (可选,用于搭建搜索界面):

    bash

    复制代码

    pip install streamlit  # 轻量级 Web 框架

2. 收集和处理数据

目标 :遍历所有 Markdown 文件,提取文本内容并分块处理。

python

运行复制代码

import os
import markdown
from bs4 import BeautifulSoup  # 清洗 HTML(解析后的 Markdown 可能转为 HTML)
 
def parse_markdown_files(directory):
    docs = []
    metadatas = []
    for root, _, files in os.walk(directory):
        for file in files:
            if file.endswith(".md"):
                file_path = os.path.join(root, file)
                with open(file_path, "r", encoding="utf-8") as f:
                    content = f.read()
                    # 将 Markdown 转为纯文本
                    html = markdown.markdown(content)
                    text = BeautifulSoup(html, "html.parser").get_text()
                    # 分块处理(例如每 500 字符为一段)
                    chunks = [text[i:i+500] for i in range(0, len(text), 500)]
                    docs.extend(chunks)
                    # 添加元数据(如文件路径、标题)
                    metadatas.extend([{"source": file_path, "chunk": i} for i in range(len(chunks))])
    return docs, metadatas

3. 创建向量索引

目标 :将文本块转化为向量并存储到数据库。

使用 OpenAI 的文本嵌入模型

python

运行复制代码

import openai
 
# 设置 OpenAI API 密钥
openai.api_key = "YOUR_API_KEY"
 
def create_embeddings(docs):
    embeddings = []
    for doc in docs:
        response = openai.Embedding.create(
            input=doc,
            model="text-embedding-ada-002"
        )
        embeddings.append(response["data"][0]["embedding"])
    return embeddings
 
# 建立 Chroma 向量数据库
import chromadb
 
client = chromadb.Client()
collection = client.create_collection(name="markdown_search")
docs, metadatas = parse_markdown_files("your_markdown_directory")
embeddings = create_embeddings(docs)
 
collection.add(
    documents=docs,
    embeddings=embeddings,
    metadatas=metadatas
)
使用本地模型(如 SentenceTransformers)

python

运行复制代码

from sentence_transformers import SentenceTransformer
 
model = SentenceTransformer('all-MiniLM-L6-v2')  # 轻量级模型
embeddings = model.encode(docs).tolist()  # 转为列表方便存储
 
# 用 Faiss 保存向量
import faiss
import numpy as np
 
dimension = len(embeddings[0])
index = faiss.IndexFlatL2(dimension)
faiss_data = np.array(embeddings).astype("float32")
index.add(faiss_data)
faiss.write_index(index, "markdown_index.faiss")

4. 搭建搜索接口

目标 :通过用户输入的查询,返回最相关的文档段。

使用 Streamlit 快速搭建 Web 界面

python

运行复制代码

import streamlit as st
import chromadb
import faiss
import numpy as np
 
# 初始化 Chroma 或加载 Faiss 索引
def search_query(query, top_k=5):
    # 方法 1:使用 Chroma
    client = chromadb.Client()
    collection = client.get_collection("markdown_search")
    results = collection.query(
        query_texts=[query],
        n_results=top_k
    )
    return results["documents"][0], results["metadatas"][0]
    
    # 方法 2:使用 Faiss
    # model = SentenceTransformer('all-MiniLM-L6-v2')
    # query_embedding = model.encode([query]).astype("float32")
    # index = faiss.read_index("markdown_index.faiss")
    # distances, indices = index.search(query_embedding, top_k)
    # return [docs[i] for i in indices[0]]
 
# Streamlit 界面
st.title("Markdown 文件智能搜索")
query = st.text_input("输入你的查询:")
if st.button("搜索"):
    results, metadatas = search_query(query)
    for i, (text, metadata) in enumerate(zip(results, metadatas)):
        st.write(f"**结果 {i+1}**:")
        st.write(text)
        st.caption(f"来源:{metadata['source']}(第 {metadata['chunk']} 块)")

5. 高级扩展(可选)

  • 使用 LangChain :一个简化 AI 工作流的框架,支持端到端实现。

    bash

    复制代码

    pip install langchain chromadb

    python

    运行复制代码

    from langchain.text_splitter import MarkdownHeaderTextSplitter
    from langchain.embeddings import OpenAIEmbeddings
    from langchain.vectorstores import Chroma
     
    # 用 LangChain 分割 Markdown(按标题层次)
    splitter = MarkdownHeaderTextSplitter(["#", "##", "###"])
    with open("your_file.md", "r") as f:
        md_file = f.read()
        data = splitter.split_text(md_file)
     
    # 创建索引
    embeddings = OpenAIEmbeddings()
    db = Chroma.from_documents(data, embeddings)
     
    # 查询
    query = "如何配置本地 Markdown 搜索?"
    docs = db.similarity_search(query)
    for doc in docs:
        st.write(doc.page_content)
  • 结合大模型生成答案 :用类似 Qwen 或 GPT 的模型总结结果。

    python

    运行复制代码

    # 示例:用 OpenAI 的 GPT-3.5 生成答案
    def get_answer(query, docs):
        prompt = f"根据以下内容回答问题:\n{query}\n\n内容:\n" + "\n".join(docs)
        response = openai.Completion.create(
            engine="text-davinci-003",
            prompt=prompt,
            max_tokens=150
        )
        return response.choices[0].text.strip()
     
    # 在搜索结果后调用
    answer = get_answer(query, results)
    st.write(f"**答案**:{answer}")

推荐工具和框架

    文本嵌入模型

    • 云端 :OpenAI 的 text-embedding-ada-002(精度高,适合复杂场景)。
    • 本地all-MiniLM-L6-v2(轻量、快,适合小规模数据)、Qwen 系列的本地模型(如 Qwen-Max-WWM-Int8)、Llama 系列。

    向量数据库

    • Chroma :轻量级,易于集成。
    • Faiss :高效向量搜索,适合大规模数据。
    • Milvus :分布式向量数据库,适合企业级应用。

    前端框架

    • Streamlit :快速搭建交互式界面。
    • Flask/Django :自定义 Web 后端。
    • VS Code 插件 :如果需要集成到编辑器(如通过 AI Search 插件)。

注意事项

  1. 1.数据隐私 :如果使用本地模型和数据库(如 Faiss + SentenceTransformers),数据完全在本地处理,适合敏感信息。

    性能优化

    • 分块大小:过大的文本块可能降低搜索精度,过小则增加索引数量。
    • 使用 GPU:加速嵌入生成和向量搜索(如通过 sentence-transformers 的 GPU 支持)。
  2. 3.定期更新索引 :当本地文件发生变化时,需要重新生成索引。

  3. 4.自然语言查询 :AI 的语义理解能力依赖于模型质量,可能需要多次调整查询策略。


完整示例代码

以下是一个基于 Chroma 和 OpenAI 的快速实现:

python

运行复制代码

import os
import markdown
from bs4 import BeautifulSoup
import chromadb
import openai
 
# 1. 解析 Markdown 文件
def load_markdown(directory):
    docs = []
    metadatas = []
    for file in os.listdir(directory):
        if file.endswith(".md"):
            with open(os.path.join(directory, file), "r") as f:
                text = f.read()
                html = markdown.markdown(text)
                cleaned_text = BeautifulSoup(html, "html.parser").get_text()
                chunks = [cleaned_text[i:i+500] for i in range(0, len(cleaned_text), 500)]
                docs.extend(chunks)
                metadatas.extend([{"source": file, "chunk": i} for i in range(len(chunks))])
    return docs, metadatas
 
# 2. 创建索引
def create_index(docs, metadatas):
    # 使用 OpenAI 嵌入模型
    embeddings = openai.Embedding.create(
        input=docs,
        model="text-embedding-ada-002"
    )["data"]
    
    # 存储到 Chroma
    client = chromadb.Client()
    collection = client.create_collection("markdown_search")
    collection.add(
        documents=docs,
        embeddings=[e["embedding"] for e in embeddings],
        metadatas=metadatas
    )
 
# 3. 搜索函数
def search_query(query):
    client = chromadb.Client()
    collection = client.get_collection("markdown_search")
    results = collection.query(
        query_texts=[query],
        n_results=5
    )
    return results["documents"][0], results["metadatas"][0]
 
# 4. 主流程
if __name__ == "__main__":
    directory = "你的 Markdown 文件目录"
    docs, metadatas = load_markdown(directory)
    create_index(docs, metadatas)
    
    # 测试搜索
    query = "如何实现向量化索引?"
    results, metadatas = search_query(query)
    for text, metadata in zip(results, metadatas):
        print(f"来源:{metadata['source']},段落:{text}")

替代方案

    Obsidian + 插件

    Notion + API

    • 将 Markdown 内容导入 Notion,利用 Notion API 和 AI 模型实现搜索(需 Notion 账户)。

通过以上步骤,你可以快速搭建一个本地 Markdown 文件的智能搜索系统。根据需求选择云端或本地模型,并结合简单的界面工具(如 Streamlit)提升用户体验。