markdown存储到faiss向量数据库

一、faiss接收的数据接口

在这里插入图片描述
add_docunments接收的documents是一个document对象的列表。

Document 对象的列表(List of Documents),是 LangChain 中的一种数据结构。每个 Document 对象包含两个主要属性:

  1. metadata:文档的元数据

    • 这里包含 file_name(文件名)
    • 例如:{'file_name': '01-通过-史国阳-硕士-算法岗.md'}
  2. page_content:文档的实际内容

    • 包含简历的具体文本内容
    • 被分成了多个片段(chunks)

数据结构示例:

documents = [
    Document(
        metadata={'file_name': '01-通过-xxx-硕士-算法岗.md'},
        page_content='# 基本信息\n\n**姓名:** xxx\n...'
    ),
    Document(
        metadata={'file_name': '01-通过-xxx-硕士-算法岗.md'},
        page_content='- **广联达科技股份有限公司**\n...'
    ),
    # ... 更多 Document 对象
]

这种结构通常用于:

  • 文档向量化
  • 文本分块处理
  • 构建向量数据库
  • 文档检索和问答系统

在之前的faiss学习的例子中,就是使用的这种对象列表。每一个document都有数据内容和相应的元信息,元信息可以用来存储一些标识符、属性、限制这类,以方便进行条件查询。

在这里插入图片描述

二、Markdown文件切分并处理为document列表

在这里插入图片描述

1.markdown分割器

在这里插入图片描述

让我解释这个 MarkdownHeaderTextSplitter 的初始化:

from langchain.text_splitter import MarkdownHeaderTextSplitter

# 定义要分割的标题级别
headers_to_split_on = [
    ("#", "header1"),          # H1 标题
    ("##", "header2"),         # H2 标题
    ("###", "header3"),        # H3 标题
]

# 创建分割器实例
markdown_splitter = MarkdownHeaderTextSplitter(
    headers_to_split_on,
    strip_headers=False        # 保留标题在分割后的文本中
)

这个分割器的作用是:

  1. 根据 Markdown 标题层级分割文本
  2. 每个分割后的片段会包含其对应的标题信息

参数说明:

  • headers_to_split_on:定义要识别的标题级别

    • 每个元组包含 (标题符号, 元数据键名)
    • 例如:(“#”, “header1”) 表示 H1 标题
  • strip_headers=False

    • True: 移除分割后文本中的标题
    • False: 保留标题在文本中

使用示例:

text = """
# 个人简历

## 教育背景
本科毕业于北京大学

## 工作经验
### 公司A
担任软件工程师
### 公司B
担任高级工程师
"""

splits = markdown_splitter.split_text(text)
# 结果示例:
# [
#     Document(
#         page_content="# 个人简历",
#         metadata={"header1": "个人简历"}
#     ),
#     Document(
#         page_content="## 教育背景\n本科毕业于北京大学",
#         metadata={"header1": "个人简历", "header2": "教育背景"}
#     ),
#     ...
# ]

这种分割方式特别适合:

  • 结构化处理 Markdown 文档
  • 保留文档的层级结构
  • 基于标题进行文档检索
  • 问答系统中的上下文管理

切分器自动将markdown处理为document列表

2.文本分割器

在这里插入图片描述

让我解释这个文本分割器的配置:

text_splitter = RecursiveCharacterTextSplitter.from_tiktoken_encoder(
    chunk_size=500,      # 每个文本块的最大token数
    chunk_overlap=50     # 相邻文本块之间的重叠token数
)

这是一个使用 tiktoken 编码器的递归文本分割器,主要参数:

  1. chunk_size=500

    • 每个文本块的最大长度(以token为单位)
    • token是GPT模型的基本处理单位
    • 500 tokens 大约对应 375-425 个汉字或 150-200 个英文单词
  2. chunk_overlap=50

    • 相邻文本块之间重叠的token数
    • 用于保持上下文连贯性
    • 防止句子或段落在分割时被生硬切断

使用示例:

text = """这是一个很长的文档,需要被分割成小块。
这样可以更好地处理和分析。每个块都会包含一定数量的文本。
相邻的块之间会有一些重叠,确保上下文的连续性。"""

chunks = text_splitter.split_text(text)
# 结果会是多个较小的、有重叠的文本块

这种分割方式的优点:

  • 使用 tiktoken(OpenAI的分词器)确保准确的token计数
  • 递归分割保证更自然的文本边界
  • 重叠部分维持了上下文连贯性
  • 适合后续的向量化和语义搜索

3.添加文件名

在这里插入图片描述
保证每个简历块都有名字,防止简历块分割之后,因为没有名字,六神无主了。因为有的时候发现简历中会带导师、博导师名字。分割之后,会认为这个博导师名字占有了这个简历内容。

三、整体流程

所以,不仅需要有该数据的接口,也要有转换为该接口的方法,两者都需要。就像两个齿轮,尺寸要契合才能一起运动。
在这里插入图片描述

源代码

import os
import jieba
import time
import pickle
from langchain_text_splitters import MarkdownHeaderTextSplitter, RecursiveCharacterTextSplitter
from langchain_community.embeddings import OpenAIEmbeddings, OllamaEmbeddings
from langchain_openai import OpenAIEmbeddings
import faiss
from langchain_community.docstore.in_memory import InMemoryDocstore
from langchain_community.vectorstores import FAISS
from uuid import uuid4
from langchain_core.documents import Document
OPENAI_API_KEY='sk-xxx'

 # 初始化embeddings
embeddings = OpenAIEmbeddings(model="text-embedding-3-large",api_key=OPENAI_API_KEY)
# 初始化index
index = faiss.IndexFlatL2(len(embeddings.embed_query("hello world")))

# 初始化vector_store
vector_store = FAISS(
    embedding_function=embeddings,
    index=index,
    docstore=InMemoryDocstore(),
    index_to_docstore_id={},
)

# 批量读取 markdown 文件并处理
def split_text_from_mds(folder_path):
    text_splits = []
    for filename in os.listdir(folder_path):
        if filename.endswith(".md"):
            file_splits = process_markdown(filename, folder_path)
            text_splits.extend(file_splits)
    return text_splits

def process_markdown(file_name, folder_path):

    ## 读取文件
    print(f"Processing file: {file_name}")
    file_path = os.path.join(folder_path, file_name)
    with open(file_path, 'r', encoding='utf-8') as file:
        content = file.read()
    
    md_header_splits = markdown_splitter.split_text(content)
    ## 针对每个切分,添加metadata 文件名,并计算token数
    for split in md_header_splits:
        split.metadata['file_name'] = file_name
        # tokens = list(jieba.cut(split.page_content))
        # print(len(tokens))
    ## 对每个切分进行字符级切分 
    ## todo:容易把相同快切断
    char_splits = text_splitter.split_documents(md_header_splits)
    return char_splits

# 切分器
## Markdown header split
headers_to_split_on = [
    ("#", "Header 1"),
    ("##", "Header 2"),
    ("###", "Header 3"),
    ("####", "Header 4"),
    ("#####", "Header 5"),
    ("######", "Header 6"),
]
markdown_splitter = MarkdownHeaderTextSplitter(headers_to_split_on, strip_headers=False)

## Char-level splits
text_splitter = RecursiveCharacterTextSplitter.from_tiktoken_encoder(
    chunk_size=500, chunk_overlap=50
)


def add_vector_store(documents, vector_store):
    """
    将文档添加到已有的向量库中
    
    Args:
        documents: 文档列表,每个文档包含文本内容和元数据
        vector_store: 已初始化的FAISS向量库实例
    
    Returns:
        添加文档后的FAISS向量库实例
    """
    try:
        
        # 生成文档的唯一标识符
        uuids = [str(uuid4()) for _ in range(len(documents))]
        
        # 记录开始时间
        start_time = time.time()
        
        vector_store.add_documents(documents=documents, ids=uuids)
        
        # 计算处理时间
        process_time = time.time() - start_time
        print(f"向量化处理耗时: {process_time:.2f} 秒")
        return vector_store
    
    except Exception as e:
        print(f"创建向量库时发生错误: {str(e)}")
        raise


if __name__ == "__main__":
    # 批量文件测试
    folder_path = os.path.join('D:/code/project/flask_project','data')
    folder_splits = split_text_from_mds(folder_path)
    # 输出为document对象的列表,是LangChain的一种数据结构,每个Document对象包含page_content和metadata
    vector_store = add_vector_store(folder_splits, vector_store)
    print("向量库创建完成")
    # 可选:保存向量库到本地
    vector_store.save_local("data_vectors")

    ## 保存为pickle文件
    output_path = 'output'
    if not os.path.exists(output_path):
        os.makedirs(output_path)
    with open(f'{output_path}/folder_splits.pkl', 'wb') as f:
        pickle.dump(folder_splits, f)


<think>好的,我现在需要处理用户关于向量数据库的查询。用户希望列出常见的向量数据库及其特点。首先,我得回忆一下系统指令,确保格式正确,比如行内数学表达式用$...$,独立公式用$$...$$,并且生成相关问题。同时,需要用中文回答,正确引用参考资料。 用户提到的参考资料有三个,其中引用[1]提到了Milvus,引用[2]解释了向量数据库的基本概念和核心能力,引用[3]是Milvus的入门指南。我需要综合这些信息,整理出常见的向量数据库列表,并描述它们的特点。 首先,我需要确认用户的问题:支持向量操作的数据库有哪些,以及它们的特点。根据引用[1],市场上涌现了许多向量数据库解决方案,包括Milvus。引用[2]和[3]详细说明了向量数据库的功能和Milvus的特点。 接下来,我应该列出其他常见的向量数据库,比如Pinecone、FAISS、Annoy、Weaviate、Qdrant、Chroma等。每个数据库的特点需要简要说明,比如开源与否、分布式架构、支持的索引算法、适用场景等。 需要注意的是,用户可能希望了解每个数据库的独特之处,比如Milvus的高扩展性和多向量支持,Pinecone的全托管服务,FAISS的高效相似性搜索等。同时,必须正确引用资料中的内容,比如引用[1]、[2]、[3]提到的Milvus相关信息。 在整理过程中,要确保LaTeX格式正确,但根据用户的问题,可能涉及数学表达式较少,但如果有的话,比如向量距离计算,需用行内格式。例如,余弦相似性可以写成$\cos(\theta)$。 然后,生成相关问题。根据用户示例,问题应该围绕向量数据库的应用、选择因素、与传统数据库的区别、性能优化以及Milvus的具体应用场景等。需要确保问题与主题相关,并且能够帮助用户进一步探索。 最后,检查结构是否清晰,引用是否正确,是否符合系统指令的所有要求,比如使用中文,避免markdown,正确分段等。</think>以下是常见的向量数据库及其特点的详细介绍: ### 1. **Milvus** - **特点**: - 开源且高度可扩展的分布式向量数据库,支持多种索引算法(如IVF、HNSW)[^3] - 支持多向量和混合查询(向量+结构化数据) - 适用于大规模非结构化数据处理,如图像检索、推荐系统[^1][^3] - 提供Python/Java SDK,集成机器学习框架(如TensorFlow、PyTorch) ### 2. **Pinecone** - **特点**: - 全托管云服务,无需维护基础设施 - 实时更新和低延迟检索,适合动态数据场景(如实时推荐) - 支持稀疏向量和稠密向量混合存储 ### 3. **FAISS (Facebook AI Similarity Search)** - **特点**: - 开源库而非独立数据库,专注于高效相似性搜索 - 支持GPU加速,适合高维向量快速检索 - 需结合传统数据库(如Redis)实现完整数据管理[^2] ### 4. **Annoy (Approximate Nearest Neighbors Oh Yeah)** - **特点**: - 轻量级开源库,基于树结构实现近似最近邻搜索 - 内存占用低,适用于中小规模数据集 - 常用于快速原型开发 ### 5. **Weaviate** - **特点**: - 开源向量搜索引擎,内置机器学习模型自动生成向量 - 支持语义搜索和图结构数据关联 - 提供RESTful API和GraphQL接口 ### 6. **Qdrant** - **特点**: - 开源向量数据库,支持过滤条件和混合查询 - 提供分布式部署和数据分片功能 - 强调可解释性和可配置的距离度量(如欧氏距离、余弦相似度$\cos(\theta)$) ### 7. **Chroma** - **特点**: - 轻量级开源数据库,专为AI应用设计 - 集成LangChain等工具链,简化自然语言处理任务 - 支持快速嵌入和检索 --- ### 核心能力对比(基于引用[2]) | 能力 | 描述 | |------------|--------------------------------------------------------------------| | **管理** | 高效组织非结构化数据,支持AI模型应用 | | **存储** | 高维向量存储,兼容多种数据类型(如图像、文本) | | **检索** | 基于相似性(如$L_2$范数或$\cos(\theta)$)的高效搜索,响应时间短 | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

海绵波波107

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值