当前位置: 首页 > article >正文

Day30上 - ChromaDB 向量数据库

向量数据库

  • vector storage engine
  • 存储向量
  • 关系型数据库:
    • table
      • id, name, age, school, address, ……
      • 增删改查:字符串本身的比较
  • 文档型数据库:
    • mongodb
      • collection:
        • document:
          • json
            • 每个json都是任意的结构
  • 键值对数据库:
    • redis:
      • 内存型,做缓存
      • key-value对
  • 存储向量
    • 虽然叫向量数据库,但是向量部分只是索引,数据本身还是重点
    • 数据查询时,使用向量进行语义化检索,而不是字符串匹配
    • 结构:
      • id, vector, text, metadata
      • id:唯一标识,数据管理时使用
      • vector:向量,用来做语义检索
      • text:文本,信息本身
      • metadata:元数据,用来做过滤
    • 兼容文档型和关系型数据库的特点
  • 常见的向量库:
    • FAISS
    • chromadb
    • pinecone
    • milvus
  • 语义检索:
    • 欧式距离(不开方)
    • 余弦相似度
    • 向量内积

ChromaDB

  • 安装:
    • pip install chromadb
  • 增删改查
    • 如何连接数据库?
    • 如何插入数据?
    • 如何检索数据?
    • 如何删除数据?
    • 如何更新数据?
  • Chroma官方说明文档:https://docs.trychroma.com/docs/overview/introduction
  • 本质:
    • 数据存在那里?
    • 语义检索式怎么实现的?
  • 设计理念:
    • 把数据存在 sqlite 中
    • 自己设计一套语义检索逻辑

ChromaDB 基本操作

1. 安装
pip install chromadb
2. 创建 Chroma 客户端
import chromadb
chroma_client = chromadb.Client()
3. 创建 Collection 集合 

集合是存储嵌入、文档和任何附加元数据的地方

collection = chroma_client.create_collection(name="my_collection")
4. 添加文本到集合中

Chroma存储文本,并自动处理嵌入和索引

collection.add(
    documents=[
        "This is a document about pineapple",
        "This is a document about oranges"
    ],
    ids=["id1", "id2"]
)
5. 查询集合

可以使用查询文本列表查询该集合,Chroma 将返回最相似的 n 个结果。如果未提供 n_results,Chroma 将默认返回 10 个结果。这里我们只添加了 2 篇文档,因此将 n_results 设置为 2。

results = collection.query(
    query_texts=["This is a query document about hawaii"], # Chroma will embed this for you
    n_results=2 # how many results to return
)
print(results)
 6. 检查结果

从上述查询中可以看到,我们关于夏威夷的查询在语义上与关于菠萝的文档最为相似。

{
  'documents': [[
      'This is a document about pineapple',
      'This is a document about oranges'
  ]],
  'ids': [['id1', 'id2']],
  'distances': [[1.0404009819030762, 1.243080496788025]],
  'uris': None,
  'data': None,
  'metadatas': [[None, None]],
  'embeddings': None,
}
7. Demo 
"""
    ChromaDB基本操作
"""

from chromadb import Client

chroma_client = Client()
chroma_client

collection = chroma_client.create_collection(name="my_collection",get_or_create=True)

collection.database

collection.configuration_json

"""
    增删改查
"""
import uuid
def get_uuid():
    return str(uuid.uuid4())

ids = [get_uuid() for _ in range(2)]

documents = ["我今天去上学","天气很好"]

collection.add(ids=ids, documents=documents)
results["ids"]

collection.delete('b837983b-2911-4b15-9cc2-447975541a1e')
collection.get()

collection.update(ids=['3f850c2e-b772-4c99-bf19-2edbf5e3ae28'],
                 documents=["大家今天都很高兴"])
collection.get()


# update + insert
collection.upsert()


ChromaDB 服务端存储

参考 chromadb官方文档:https://docs.trychroma.com/production/chroma-server/client-server-mode

1. 终端输入以下命令,启动本地 Chroma 服务端:

chroma run --path "./chroma_data"

2. 启动成功,可通过8000端口,连接到服务器

from chromadb import HttpClient
chroma_client = HttpClient(host='localhost',port=8000)

3. models.py

from dotenv import load_dotenv
load_dotenv()
from langchain_community.embeddings.dashscope import DashScopeEmbeddings
from langchain_community.chat_models import ChatTongyi

def get_embed():
    """
        连接模型
    """
    return DashScopeEmbeddings(model="text-embedding-v3")

def get_chat():
    """
        连接模型
    """
    return ChatTongyi(model="qwen-turbo", temperature=0.1, top_p=0.7)

4. 语义检索

from models import get_embed
embed = get_embed()
# 语义检索
text = "外面天气怎么样?"
embedding = embed.embed_query(text=text)
collection.query(query_embeddings=embedding, n_results=1)

LangChain 和 Chroma 结合使用

from models import get_embed
from langchain_chroma import Chroma
from chromadb import HttpClient

embed = get_embed()

# 配置连接服务器的信息
client = HttpClient(host="localhost", port=8000)

db = Chroma(client=client, embedding_function=embed)
db.search(query="今天心情好吗?", search_type="similarity_score_threshold")



from models import get_chat
model = get_chat()
model.invoke(input="你好")

retriever = db.as_retriever(search_type="similarity_score_threshold",
                           search_kwargs={"score_threshold": 0.5, "k": 2})
retriever.invoke(input="外面天气怎么样?")

db.similarity_search_with_relevance_scores(query="你好")

数据入库

  • load
    • 读取原始数据(只要文本,不要其他数据)
  • split
    • 把文本切分成一个一个语义独立的段落
  • embed
    • 向量化,入库
file_name = "knowledge/产品介绍.txt"
with open(file=file_name, mode="r", encoding="utf8") as f:
    data = f.read()
    print(data)
# 方式一:按照自己的语义逻辑来切分
documents = [chunk.strip() for chunk in data.split("###") if chunk]
pip install langchain_text_splitters -U
from langchain_text_splitters import RecursiveCharacterTextSplitter
# 定义一个分割器
# 设置的256为切分指导数,实际要小,因为会结合语义切分
splitter = RecursiveCharacterTextSplitter(chunk_size=256)

# splitter.split_text(text=data)

for chunk in splitter.split_text(text=data):
    print(len(chunk))
    print(chunk)
    print('--------------------------')

chunk_size 无论怎么设置都不具备普世性,那么长度到底设置为多少合理呢?

最好的办法是手动区分,即文档手动的去划分语义。

所以第一期项目,设置差不多大小切完即可;到第二期项目时,可以手动去调整一些文档段落的内容,编辑调整一些格式。


http://www.kler.cn/a/509036.html

相关文章:

  • 【Unity3D】利用Hinge Joint 2D组件制作绳索效果
  • 重拾Python学习,先从把python删除开始。。。
  • springboot多环境配置
  • 价值分解方法(QMIX、VDN、FACMAC、VDA2C)整理
  • Vue.js组件开发-实现后端返回二进制文件在浏览器自动下载
  • Java设计模式——单例模式(特性、各种实现、懒汉式、饿汉式、内部类实现、枚举方式、双重校验+锁)
  • 基于springboot+vue的食物营养分析与推荐网站的设计与实现
  • 性能测试实时监听工具Influx+Grafana
  • Banana Pi BPI-RV2 RISC-V路由开发板采用矽昌通信SF2H8898芯片
  • Web开发 -前端部分-CSS-2
  • 搜广推实习面经三
  • 机器学习之决策树(DecisionTree)
  • AD域学习笔记
  • 基于C语言的通讯录实现
  • Kotlin语言的数据库交互
  • UI自动化测试:异常截图和page_source
  • 模拟练习题
  • BilibiliPotPlayer插件的登录第二天失效,无法看高清视频,要删掉浏览器上的cookie
  • Linux初识:【Linux软件包管理器yum】【Linux编辑器-vim的使用】【Linux编译器-gcc/g++的使用】
  • 精度论文:【Focaler-IoU: More Focused Intersection over Union Loss】
  • 生产环境中常用的设计模式
  • 可部署于所有设备上的开源加速 Stable-Diffusion.cpp:让 AI 图像生成更快、更高效!
  • AI刷题-小R的随机播放顺序、不同整数的计数问题
  • 二叉树总结(hot100)
  • 物联网通信协议对比-带表格
  • R数据分析:有调节的中介与有中介的调节的整体介绍