您现在的位置是:网站首页> AI人工智能

向量数据库相关技术收集

摘要

向量数据库相关技术收集


1.jpg

客户端将MCP工具列表和用户问题-》大语言模型-》需要调用MCP的信息返回给调用模型的客户端,客户端调用指定MCP->客户端获得MCP结果-》大语言模型-》返回给最终客户


LangChain.NET如何调用Ollama制作知识库和调用MCP服务

AI学习向量数据库咒语

向量数据库简介

Chroma向量数据库

开源的向量数据库Milvus

超轻量级LibSQL

数据存储样例说明,数据向量化存储查询



向量数据库简介

向量数据库,是专门为向量检索设计的中间件!

向量数据库其实最早在传统的人工智能和机器学习场景中就有所应用。在大模型兴起后,由于目前大模型的token数限制,很多开发者倾向于将数据量庞大的知识、新闻、文献、语料等先通过嵌入(embedding)算法转变为向量数据,然后存储在Chroma等向量数据库中。当用户在大模型带入问题后,将问题本身也embedding,转化为向量,在向量数据库中查找与之最匹配的相关知识,组成大模型的上下文,将其输入给大模型,最终返回模型处理后的文本给用户,这种方式不仅降低大模型的计算量,提高响应速度,也降低成本,并避免了大模型的tokens限制,是一种简单高效的处理手段。此外向量数据库还在大模型记忆存储等领域发挥其不可替代的作用。

Schema类似定义的表结构也就是字段

Schema下的Collections类似相同表结构下的不同表




Chroma向量数据库

官方文档:https://docs.trychroma.com/docs/overview/introduction

#!pip install chromadb

#为了演示方便,我们只取两页(第一章)

paragraphs = extract_text_from_pdf(

"ilama2.pdf"

page_numbers=[2, 3], min_line_length=10


import chromadb

from chromadb.config import Settings 

class MyVectorDBConnector:

 def init(self,collectionname,embedding fn):

        #内存模式

        chroma_client=chromadb.client(Settings(allow_reset=True))

        #数据持久化

        #chroma_client=chromadb.Persistentclient(path="./chroma")

        #注意:为了演示,实际不需要每次reset(),并且是不可逆的,它是复位清空数据

        chroma_client.reset()

        

        #创建一个collection

        self.collection=chroma_client.get_or_create_collection(name=collection_name) 

        self.embedding_fn = embedding_fn  #模型文本向量化函数,如果不设置数据库默认的模型all-MiniLM-L6-v2


def add_documents(self,documents):

      '''向collection 中添加文档与向量 

      self.collection.add(

             embeddings=self.embedding_fn(documents),#每个文档的向量        

             documents=documents,#文档的原文

             ids=[f"id{i}" for i in range(len(documents))]#每个文档的id

        )

def search(self,query,top_n):  #top_n表示检索几个文档出来

       '''检索向量数据库!

       results = self.collection.query(

               query_embeddings=self.embedding_fn([queryl), 

               n_results=top_n

        )

       return results




pip install -U python-dotenv


import numpy as np

from numpy import dot

from numpy.linalg import norm 

from openai import OpenAI 

import os


#加载环境变量


from dotenv import load_dotenv,find_dotenv

- = load_dotenv(find_dotenv(), verbose=True) #读取本地.enV文件,里面定义了OPENAI_API_KEY

client=OpenAI()


def get_embeddings(texts,model="text-embedding-ada-oo2",dimensions=None):

    '''封装OpenAI的Embedding模型接口 

     if model == "text-embedding-ada-002":

        dimensions = None 

     if dimensions:

        data = client.embeddings.create(

             input=texts, model=model,dimensions=dimensions).data

      else:

         data = client.embeddings.create(input=texts, model=model).data 

      return [x.embedding for x in data]


#创建一个向量数据库对象

vector_db=MyVectorDBConnector("demo",get_embeddings) 

#向向量数据库中添加文档

vector_db.add_documents(paragraphs) 

user_query ="Llama 2有多少参数"

# user_query = "Does Llama 2 have a conversational variant"

results = vector_db.search(user_query,2) 

for para in results['documents'][0]:

      print(para+"\n")



开源的向量数据库Milvus

点击查看原文

进入Milvus主页

Milvus 向量数据库快速入门

先认几个关键词

1.jpg

部署使用

五步跑通「单机体验」+ 三步升级「小集群」

单机 5 步

1.拉镜像 docker run milvusdb/milvus:v2.4.3

2.建楼 create_collection()——确定字段维度、主键、向量字段。

3.搬人 insert() → flush()。

4.装电梯 create_index();小数据直接 FLAT,大数据先 IVF,再视情况换 HNSW。

5.开门找人 load() → search()/query();用完可 release().

最常用的 5 步操作

1.建楼:create collection,把字段都定义好

2.搬人:insert,把向量和元信息塞进去;记得 flush() 真正落盘

3.装电梯:create index,选对索引类型,未来搜索才快

4.请保安开门:load,没 load 就像门锁着,啥也搜不到

5.找人:search(可加条件 expr),或者只按字段 query


索引调优口诀

1.小样本先 FLAT 做 baseline——它慢但最准,方便肉眼看 Recall。

2.百 万级优先 IVF_FLAT:调 nlist=√N 起步;提高 nprobe 越准越慢。

千万级冲 HNSW:关键参 M (边数) 和 efConstruction (建图宽度),调高两倍能大幅增 Recall。

3.超高并发记得“机+内存”一起扩——索引放内存,多副本才分摊 QPS。


别踩这些坑

1.向量维度要统一:128 就全 128,别混着来。

2.插完别忘 flush:不 flush 就像东西放购物车没结账,搜索不到。

3.没 load 就搜索:会报错,先 load()。

4.内存不够全加载:用 Partition,分批 load()。

5.精度不满意:调 nprobe(IVF)或换 HNSW 试试。


十大踩坑 + 急救方案

1.jpg

再进阶一点点

1.Hybrid Search:边比向量相似度,边过滤价格 < 500 这种条件,SQL 味道更浓。

2.一致性模式:默认够用;真要跨机房强一致性就选 Strong。

3.持久化:Milvus 本身用 RocksDB + MinIO 存数据,你不用操心怎么落盘。

4.与 RAG 的关系:大模型把文本→向量,Milvus 负责“最近邻检索”,再把查到的文档喂回模型。


跟其它工具怎么配?

1.LangChain / LlamaIndex:把 Milvus VectorStore 接进去即可,RAG 极速上线。

2.Spark / Flink:批量离线写入 Milvus;确保分批 1 万条以内避免 RPC 超时。

3.Airflow:定时 ETL → Embedding → Milvus;flush、compact 都能写成 task。


“到底需要多大机器?”——粗算公式

内存 ≈ (向量维度 × 4 bytes × 向量条数 × 1.4 倍索引系数)﹢ 元数据大小

例:1 亿条 768 维 → 768×4×1e8×1.4 ≈ 430 GB(得至少 512 GB 机器,或分区加载)。


硬盘 ≈ 内存 × 1.2(索引 + RocksDB + 日志)。


Python 端到端 Demo (含增删改查)

from pymilvus import connections, Collection, utility, DataType, FieldSchema, CollectionSchema

import numpy as np


connections.connect(host="localhost", port="19530")


# 1. 建楼(如果已存在就删掉重建)

if utility.has_collection("demo"): utility.drop_collection("demo")


schema = CollectionSchema([

    FieldSchema("id", DataType.INT64, is_primary=True, auto_id=True),

    FieldSchema("title", DataType.VARCHAR, max_length=200),

    FieldSchema("price", DataType.FLOAT),

    FieldSchema("emb", DataType.FLOAT_VECTOR, dim=128)

])

col = Collection("demo", schema)


# 2. 插 10 条数据

titles = [f"商品{i}" for i in range(10)]

prices = [i * 10.0 for i in range(10)]

vecs   = np.random.random((10, 128)).tolist()

col.insert([titles, prices, vecs]); col.flush()


# 3. 建 IVF 索引 & 加载

col.create_index("emb", {"index_type":"IVF_FLAT","metric_type":"L2","params":{"nlist":64}})

col.load()


# 4. 搜索 + 过滤价格 < 50

qv = [np.random.random(128).tolist()]

hits = col.search(qv, "emb", {"metric_type":"L2","params":{"nprobe":8}}, limit=5, expr="price < 50")

print([(h.entity.get('title'), h.distance) for h in hits[0]])


# 5. 删除一条,再查

del_id = hits[0][0].id

col.delete(f"id in [{del_id}]"); col.flush()


AI学习向量数据库咒语

向量数据库检索返回结果的格式是啥?给个详细介绍和例子

向量数据库在现实项目中在哪些领域使用



###【豆包】

Q:向量数据库检索返回结果的格式是啥?给个详细介绍和例子

A:...

这个问题很实用,向量数据库检索结果没有统一标准格式,但核心都包含 “匹配数据 + 相似度 + 元数据” 三要素,不同数据库仅字段命名和结构细节有差异。

核心组成部分

向量数据库检索结果的核心是 “让用户明确‘匹配了什么、匹配度多高、附加信息是什么’”,关键组成包括:

1.相似度分数:量化查询向量与库中向量的匹配程度,常见范围 0-1(1 为完全匹配)或 0-100,部分数据库支持自定义分数范围。

2.元数据:用户插入数据时附带的非向量信息,如文本内容、数据 ID、分类标签、时间戳等,是检索结果的核心业务信息。

3.数据标识:唯一标识匹配结果的 ID(如主键 ID),用于关联原始数据或进一步操作(如更新、删除)。

4.可选字段:部分数据库可返回存储的原始向量、数据分片信息、检索耗时等辅助数据。

主流向量数据库格式例子

以下是 3 个常用向量数据库的检索结果格式,均基于 “查询文本向量,匹配相似文本” 的场景(插入时存储 “text” 元数据、“category” 标签和向量)。

1. Milvus(开源主流)

Milvus 返回结果为字典列表,结构清晰,字段命名规范:

python

运行

# 检索查询:“推荐一本科幻小说”

retrieval_results = [

    {

        "id": 1003,  # 数据唯一标识

        "distance": 0.92,  # 相似度(距离越小越匹配,部分配置下为分数越大越匹配)

        "entity": {  # 元数据与向量

            "text": "《三体》是经典科幻小说,讲述人类文明与三体文明的碰撞",

            "category": "科幻",

            "vector": [0.12, 0.34, 0.56, ..., 0.98]  # 可选返回,默认不返回

        },

        "partition_name": "_default"  # 数据所在分片(可选)

    },

    {

        "id": 2015,

        "distance": 0.87,

        "entity": {

            "text": "《基地》系列构建了庞大的银河帝国科幻体系",

            "category": "科幻",

            "vector": [0.15, 0.31, 0.52, ..., 0.91]

        },

        "partition_name": "_default"

    }

]

2. Chroma(轻量开源)

Chroma 返回结果为嵌套字典,字段更简洁,适合快速开发:

python

运行

# 检索查询:“推荐一本科幻小说”

retrieval_results = {

    "ids": ["doc_1003", "doc_2015"],  # 匹配数据的ID列表

    "distances": [0.08, 0.13],  # 相似度(L2距离,越小越匹配)

    "metadatas": [  # 元数据列表,与ID一一对应

        {"text": "《三体》是经典科幻小说,讲述人类文明与三体文明的碰撞", "category": "科幻"},

        {"text": "《基地》系列构建了庞大的银河帝国科幻体系", "category": "科幻"}

    ],

    "embeddings": [  # 向量列表(默认不返回,需手动指定)

        [0.12, 0.34, 0.56, ..., 0.98],

        [0.15, 0.31, 0.52, ..., 0.91]

    ]

}

3. Pinecone(云原生向量数据库)

Pinecone 返回结果为字典列表,突出 “匹配度分数” 和 “元数据”,支持自定义字段:

python

运行

# 检索查询:“推荐一本科幻小说”

retrieval_results = [

    {

        "id": "doc_1003",

        "score": 0.92,  # 相似度分数(0-1,越大越匹配)

        "metadata": {

            "text": "《三体》是经典科幻小说,讲述人类文明与三体文明的碰撞",

            "category": "科幻",

            "author": "刘慈欣",

            "publish_year": 2008  # 自定义元数据字段

        }

    },

    {

        "id": "doc_2015",

        "score": 0.87,

        "metadata": {

            "text": "《基地》系列构建了庞大的银河帝国科幻体系",

            "category": "科幻",

            "author": "阿西莫夫",

            "publish_year": 1951

        }

    }

]

格式共性与差异总结

共性:所有向量数据库都会返回 “ID + 相似度 + 元数据”,确保用户能定位匹配结果、判断匹配质量、获取业务信息。

差异:字段命名(如 “distance”“score”)、结构形式(列表 / 嵌套字典)、可选字段(是否返回向量、分片信息)不同,需根据数据库文档调整解析逻辑。

要不要我帮你整理一份主流向量数据库检索结果解析代码模板,直接适配 Milvus、Chroma、Pinecone 的格式转换?


Q:这个返回的数据如何给大模型,请给几个使用LangChain.NET调用的详细例子

A:...

在LangChain.NET中,将向量数据库的检索结果传递给大模型的核心逻辑是:将检索到的相关文档(含元数据)整理为 “上下文(Context)”,结合用户原始问题构建提示词(Prompt),再调用大模型生成回答。以下是基于不同场景的详细例子,涵盖基础流程、结果筛选、元数据利用等场景,使用 OpenAI 模型作为示例大模型。

前置准备

1.安装依赖包(通过 NuGet)

bash

Install-Package LangChain

Install-Package LangChain.OpenAI  # 大模型依赖

Install-Package LangChain.VectorStores.Milvus  # 若用Milvus(可选)

Install-Package LangChain.VectorStores.Chroma  # 若用Chroma(可选)

2.配置密钥:设置 OpenAI API 密钥(OPENAI_API_KEY)和向量数据库连接信息(如 Milvus 的地址、端口)。

例子 1:基础流程(直接使用检索结果)

场景:从向量数据库检索到相关文档后,直接拼接为上下文,调用大模型回答用户问题。

步骤解析

1.模拟向量数据库检索结果(实际中可通过 LangChain 的VectorStore接口获取);

2.将检索结果的文本内容拼接为上下文;

3.用PromptTemplate构建包含上下文和问题的提示;

4.用LLMChain串联提示和大模型,生成回答。

csharp

using LangChain;

using LangChain.OpenAI;

using LangChain.Providers;

using LangChain.VectorStores;


// 1. 模拟向量数据库检索结果(实际中替换为真实VectorStore的检索调用)

var searchResults = new List<Document>

{

    new Document

    {

        PageContent = "《三体》是刘慈欣创作的科幻小说,讲述了地球人类文明和三体文明的信息交流、生死搏杀及两个文明在宇宙中的兴衰历程。",

        Metadata = new Dictionary<string, object>

        {

            {"id", "1003"},

            {"score", 0.92},  // 相似度分数

            {"category", "科幻小说"}

        }

    },

    new Document

    {

        PageContent = "《基地》系列是艾萨克·阿西莫夫的代表作,描绘了在银河帝国衰落之际,心理史学家哈里·谢顿建立基地以保存人类文明的故事。",

        Metadata = new Dictionary<string, object>

        {

            {"id", "2015"},

            {"score", 0.87},

            {"category", "科幻小说"}

        }

    }

};


// 2. 构建上下文(拼接所有检索到的文档内容)

var context = string.Join("\n\n", searchResults.Select(d => d.PageContent));


// 3. 定义提示词模板(告知大模型“基于上下文回答问题”)

var promptTemplate = PromptTemplate.FromTemplate(

    "请根据以下上下文回答用户的问题。\n" +

    "上下文:{context}\n" +

    "问题:{question}\n" +

    "回答:"

);


// 4. 初始化OpenAI大模型(支持GPT-3.5/4)

var openAiModel = new OpenAiChatModel(

    modelId: "gpt-3.5-turbo",

    apiKey: Environment.GetEnvironmentVariable("OPENAI_API_KEY")

);


// 5. 创建链(串联提示和模型)

var chain = promptTemplate | openAiModel;


// 6. 执行链(传入上下文和用户问题)

var userQuestion = "推荐两本经典科幻小说并简要介绍?";

var result = await chain.InvokeAsync(new Dictionary<string, object>

{

    {"context", context},

    {"question", userQuestion}

});


// 输出结果

Console.WriteLine(result);

输出示例

plaintext

《三体》是刘慈欣创作的科幻小说,讲述了地球人类文明和三体文明的信息交流、生死搏杀及两个文明在宇宙中的兴衰历程。《基地》系列是艾萨克·阿西莫夫的代表作,描绘了在银河帝国衰落之际,心理史学家哈里·谢顿建立基地以保存人类文明的故事。

例子 2:带结果筛选(只保留高相似度文档)

场景:向量数据库可能返回低相似度结果,需筛选后再传递给大模型(如只保留分数 > 0.8 的结果)。

csharp

// 1. 模拟检索结果(包含低相似度数据)

var searchResults = new List<Document>

{

    new Document

    {

        PageContent = "《三体》相关内容...",

        Metadata = new Dictionary<string, object> {{"score", 0.92}}

    },

    new Document

    {

        PageContent = "《基地》相关内容...",

        Metadata = new Dictionary<string, object> {{"score", 0.87}}

    },

    new Document  // 低相似度结果(需过滤)

    {

        PageContent = "《红楼梦》是古典小说...",

        Metadata = new Dictionary<string, object> {{"score", 0.65}}

    }

};


// 2. 筛选高相似度结果(只保留score > 0.8的)

var filteredResults = searchResults

    .Where(d => (double)d.Metadata["score"] > 0.8)

    .ToList();


// 3. 构建上下文(仅用筛选后的结果)

var context = string.Join("\n\n", filteredResults.Select(d => d.PageContent));


// 后续步骤(提示词、模型调用)与例子1一致...

例子 3:利用元数据增强上下文

场景:向量数据库返回的元数据(如作者、出版时间)可补充到上下文,帮助大模型生成更丰富的回答。

csharp

// 1. 模拟含详细元数据的检索结果

var searchResults = new List<Document>

{

    new Document

    {

        PageContent = "《三体》讲述了地球与三体文明的碰撞...",

        Metadata = new Dictionary<string, object>

        {

            {"id", "1003"},

            {"score", 0.92},

            {"author", "刘慈欣"},

            {"publish_year", 2008}

        }

    },

    new Document

    {

        PageContent = "《基地》构建了银河帝国的科幻体系...",

        Metadata = new Dictionary<string, object>

        {

            {"id", "2015"},

            {"score", 0.87},

            {"author", "艾萨克·阿西莫夫"},

            {"publish_year", 1951}

        }

    }

};


// 2. 构建上下文(包含元数据:将文本+作者+出版时间拼接)

var context = string.Join("\n\n", searchResults.Select(d => 

    $"{d.PageContent}\n作者:{d.Metadata["author"]}\n出版时间:{d.Metadata["publish_year"]}"

));


// 3. 用户问题:“推荐两本科幻小说,包括作者和出版时间”

// 后续步骤(提示词、模型调用)与例子1一致...

输出示例:

plaintext

《三体》讲述了地球与三体文明的碰撞...

作者:刘慈欣

出版时间:2008


《基地》构建了银河帝国的科幻体系...

作者:艾萨克·阿西莫夫

出版时间:1951

例子 4:通过 LangChain 的 VectorStore 直接检索并调用

实际开发中,通常直接通过 LangChain 的VectorStore接口检索(无需手动模拟结果),以下是结合 Milvus 的完整流程:

csharp

using LangChain.VectorStores.Milvus;


// 1. 初始化Milvus向量存储(连接数据库)

var milvusStore = new MilvusVectorStore(

    host: "localhost",  // Milvus地址

    port: 19530,        // 端口

    collectionName: "books",  // 集合名

    dimension: 1536     // 向量维度(如OpenAI embedding的维度)

);


// 2. 检索相似文档(传入用户问题的向量,或直接用文本+嵌入模型检索)

var embeddingModel = new OpenAiEmbeddingModel(apiKey: "..."); // 嵌入模型

var userQuestion = "推荐经典科幻小说";

var searchResults = await milvusStore.SimilaritySearchAsync(

    query: userQuestion,

    embeddingModel: embeddingModel,

    limit: 3  // 最多返回3条

);


// 3. 后续步骤:构建上下文、调用大模型(与例子1相同)

var context = string.Join("\n\n", searchResults.Select(d => d.PageContent));

// ...(提示词和模型调用代码)

关键总结

上下文构建:核心是将向量数据库返回的PageContent(文本内容)拼接,必要时加入元数据增强信息;

结果筛选:通过Metadata中的相似度分数过滤低质量结果,避免干扰大模型;

LangChain 链:用PromptTemplate定义逻辑,LLMChain串联提示和大模型,简化调用流程;

向量存储集成:直接使用 LangChain 的VectorStore接口(如MilvusVectorStore)可无缝衔接检索与大模型调用。

如果需要针对特定向量数据库(如 Chroma、Pinecone)的详细集成代码,可以告诉我,我会补充对应示例。


####【豆包】

Q:向量数据库在现实项目中在哪些领域使用

A:...

领域 推荐向量数据库 核心原因

AI 大模型 / RAG Milvus、Chroma 支持高维向量、分布式部署(Milvus),轻量易上手(Chroma)

计算机视觉 FAISS、Qdrant 检索速度快(FAISS),支持图像 / 视频特征向量(Qdrant)

推荐系统 Milvus、Pinecone 支持大规模用户 / 物品向量,高并发检索

生物医药 FAISS、Milvus 支持高维分子向量,检索效率高

工业 IoT Qdrant、Milvus 支持时序向量,适配传感器数据



超轻量级LibSQL

libSQL 本质是嵌入式关系型数据库(SQLite 分支),而非原生向量数据库,但它通过扩展支持向量存储和相似性查询,可作为轻量级向量数据库使用

libSQL 本身不内置向量类型和向量索引,但它支持 SQL 扩展机制,通过官方或第三方扩展可以添加向量存储和相似性查询能力。核心扩展有两种:

1. 官方推荐:vector0 扩展(轻量级向量支持)

libSQL 官方提供了 vector0 扩展(类似 SQLite 的 json1 扩展),功能包括:

支持向量数据类型(VECTOR(n),n 为向量维度,比如 VECTOR(1536) 对应 OpenAI 嵌入);

支持常见向量距离计算(欧氏距离 L2、余弦相似度 COSINE、内积 IP);

支持向量索引(基于 FAISS 或 HNSW 实现,需编译时启用对应依赖);

语法完全兼容 SQL,可直接在表中定义向量列,结合关系型数据一起查询。

示例用法(创建向量表 + 相似性查询):

-- 1. 加载 vector0 扩展

LOAD EXTENSION vector0;


-- 2. 创建带向量列的表(id + 文本 + 向量)

CREATE TABLE docs (

  id INTEGER PRIMARY KEY,

  content TEXT,

  embedding VECTOR(1536)  -- 1536维向量(对应GPT-3.5/4嵌入)

);


-- 3. 插入向量数据(嵌入值需提前通过模型生成,比如OpenAI的text-embedding-3-small)

INSERT INTO docs (content, embedding)

VALUES ('libSQL 是 SQLite 分支', '[0.123, 0.456, ..., 0.789]');


-- 4. 向量相似性查询(找与目标向量最相似的前5条)

SELECT content, COSINE(embedding, '[0.111, 0.444, ..., 0.777]') AS similarity

FROM docs

ORDER BY similarity DESC

LIMIT 5;


2. 第三方扩展:libsql-vector(更完整的向量能力)

如果需要更复杂的向量索引优化(比如动态维度、批量插入优化),社区有第三方扩展 libsql-vector,基于 HNSW 算法,支持更高性能的相似性查询,适合中等规模向量数据(万~百万级)。



数据存储样例说明,数据向量化存储查询

{

  "id": "doc-789-chunk-1",

  "embedding": [0.0456, 0.0123, -0.0345, ...],  // 1024维float32数组

  "text": "Cherry Studio 采用libSQL作为向量数据库",

  "metadata": {

    "source": "AI工具知识库.pdf",

    "page": 5,

    "chunk_id": "1",

    "created_at": 1735689600  // 时间戳

  }

}


####【豆包】

Q:chunk_id 是啥详细讲解从程序员角度

A:...

chunk_id 是一个用于唯一标识和管理 “文本块”(Text Chunk)的标识符

唯一标识每一个被切分出来的文本块。

追踪这个文本块来自哪个原始文档、哪个章节、哪一页。

管理这些文本块的生命周期(增、删、改、查)。

chunk_id 就是为了解决这些问题而存在的。

chunk_id 本质上是一个字符串(string)类型的唯一标识符(Unique Identifier, UUID)。

它的核心特性是全局唯一性,确保在整个知识库系统中,没有任何两个不同的文本块会拥有相同的chunk_id

常见的 chunk_id 生成方式

1.使用标准 UUID:这是最常见、最推荐的方式

2.复合 ID(Composite ID)

将多个有意义的信息拼接起来,用分隔符(如_或:)连接

3.自增整数(Auto-incrementing Integer)

在数据库表中使用自增主键作为chunk_id

场景:处理一个上传的 PDF 文件,并将其存入知识库。

步骤 1: 文档上传与预处理

import uuid

from PyPDF2 import PdfReader


def process_document(file_path):

    # 1. 为整个文档生成一个唯一ID (document_id)

    document_id = str(uuid.uuid4())

    

    # 模拟文档元数据

    metadata = {

        "document_id": document_id,

        "title": "关于libSQL的介绍",

        "file_path": file_path,

        "upload_time": "2023-10-27"

    }

    

    # 2. 读取PDF并切分成块

    reader = PdfReader(file_path)

    chunks = []

    chunk_index = 0

    

    for page_num, page in enumerate(reader.pages):

        text = page.extract_text()

        

        # 这里使用一个简单的按长度分割的策略,实际会更智能(如按段落、句子)

        # chunk_size = 200  # 假设每个块大约200个字符

        # for i in range(0, len(text), chunk_size):

        #     chunk_text = text[i:i+chunk_size]

            

        #     # 3. 为每个块生成唯一的 chunk_id

        #     chunk_id = str(uuid.uuid4()) # 使用UUID

        #     # 或者使用复合ID

        #     # chunk_id = f"doc_{document_id}_page_{page_num+1}_chunk_{chunk_index}"


        #     chunk_index += 1

            

        #     # 4. 构建块数据结构

        #     chunk_data = {

        #         "chunk_id": chunk_id,

        #         "document_id": document_id,

        #         "page_number": page_num + 1,

        #         "text": chunk_text,

        #         "metadata": metadata # 关联文档元数据

        #     }

        #     chunks.append(chunk_data)

        

        # 简化:假设每页就是一个块

        chunk_id = str(uuid.uuid4())

        chunk_data = {

            "chunk_id": chunk_id,

            "document_id": document_id,

            "page_number": page_num + 1,

            "text": text,

            "metadata": metadata

        }

        chunks.append(chunk_data)


    return chunks


# 调用函数处理文档

document_chunks = process_document("libsql_intro.pdf")


步骤 2: 向量化与存储


import openai


# 假设我们有一个向量数据库客户端

class VectorDB:

    def add(self, chunk_id, embedding, text, metadata):

        # 将向量、文本和元数据存入数据库

        print(f"[DB] Storing chunk: {chunk_id}")

        # ... 实际的数据库写入操作 ...


# 初始化

vector_db = VectorDB()

openai.api_key = "YOUR_API_KEY"


def embed_and_store_chunks(chunks):

    for chunk in chunks:

        # 1. 调用Embedding模型(如OpenAI的text-embedding-3-small)

        response = openai.Embedding.create(

            model="text-embedding-3-small",

            input=chunk["text"]

        )

        embedding = response['data'][0]['embedding']

        

        # 2. 将 (chunk_id, embedding, text, metadata) 存入向量数据库

        vector_db.add(

            chunk_id=chunk["chunk_id"],

            embedding=embedding,

            text=chunk["text"],

            metadata=chunk["metadata"]

        )


# 调用函数进行向量化和存储

embed_and_store_chunks(document_chunks)


步骤 3: 查询与召回

def retrieve_relevant_chunks(query_text, top_k=3):

    # 1. 将用户查询向量化

    response = openai.Embedding.create(

        model="text-embedding-3-small",

        input=query_text

    )

    query_embedding = response['data'][0]['embedding']

    

    # 2. 在向量数据库中进行相似性搜索

    # 数据库会返回 top_k 个与查询向量最相似的结果

    # 每个结果都包含了 chunk_id 和相似度分数

    search_results = vector_db.search(query_embedding, top_k=top_k)

    

    # 示例 search_results:

    # [

    #   {"chunk_id": "chunk123...", "similarity": 0.92, "text": "..."},

    #   {"chunk_id": "chunk456...", "similarity": 0.87, "text": "..."},

    # ]

    

    return search_results


# 用户查询

user_query = "libSQL 和 SQLite 有什么区别?"

relevant_chunks = retrieve_relevant_chunks(user_query)


# 打印结果

for result in relevant_chunks:

    print(f"--- 相关文本块 (ID: {result['chunk_id']}, 相似度: {result['similarity']:.2f}) ---")

    print(result['text'])

    print("\n")











Top