如何在LangChain中构建并使用自定义向量数据库

1. 自定义向量数据库对接

向量数据库的发展非常迅速,几乎每隔几天就会出现新的向量数据库产品。LangChain 不可能集成所有的向量数据库,此外,一些封装好的数据库可能存在 bug 或者其他问题。这种情况下,我们需要考虑创建自定义向量数据库,以实现特定需求。

在 LangChain 中,实现自定义向量数据库的类主要有两种模式:

  • 继承已有封装的数据库类 :通常用于扩展现有类的功能或者修复已知问题。
  • 继承基类 VectorStore :通常用于对接新的向量数据库。

在 LangChain 中,继承 VectorStore 后,只需要实现以下三个基础方法即可正常使用:

  • add_texts:将对应的数据添加到向量数据库中。
  • similarity_search:实现最基础的相似性搜索功能。
  • from_texts:从特定的文本列表、元数据列表中构建向量数据库。

此外,还有一些使用频率较低的方法,LangChain 并未将其定义为虚方法。如果在未实现的情况下直接调用这些方法,会引发异常。具体包括:

  • delete():删除向量数据库中的数据。
  • _select_relevance_score_fn():根据距离计算相似性得分的函数。
  • similarity_search_with_score():附带得分的相似性搜索功能。
  • similarity_search_by_vector():传递向量进行相似性搜索。
  • max_marginal_relevance_search():最大边际相关性搜索功能。
  • max_marginal_relevance_search_by_vector():传递向量进行最大边际相关性搜索功能。

资料推荐


2. 自定义 VectorStore 示例

要在 LangChain 中对接自定义向量数据,本质上就是将向量数据库提供的方法集成到 add_textssimilarity_searchfrom_texts 方法下,例如自建一个基于内存+欧几里得距离的“向量数据库”,示例如下:

import uuid
from typing import List, Optional, Any, Iterable, Type

import dotenv
import numpy as np
from langchain_core.documents import Document
from langchain_core.embeddings import Embeddings
from langchain_core.vectorstores import VectorStore
from langchain_openai import OpenAIEmbeddings


class MemoryVectorStore(VectorStore):
    """自定义向量数据库"""
    store: dict = {}  # 在内存中开辟位置存储向量

    def __init__(self, embedding: Embeddings, **kwargs):
        self._embedding = embedding

    def add_texts(self, texts: Iterable[str], metadatas: Optional[List[dict]] = None, **kwargs: Any) -> List[str]:
        """将数据添加到内存向量数据库中"""
        # 1.判断metadatas和texts的长度是否保持一致
        if metadatas is not None and len(metadatas) != len(texts):
            raise ValueError("元数据格式必须和文本数据保持一致")

        # 2.将文本转换为向量
        embeddings = self._embedding.embed_documents(texts)

        # 3.生成uuid
        ids = [str(uuid.uuid4()) for text in texts]

        # 4.将原始文本、向量、元数据、id构建字典并存储
        for idx, text in enumerate(texts):
            self.store[ids[idx]] = {
                "id": ids[idx],
                "vector": embeddings[idx],
                "text": text,
                "metadata": metadatas[idx] if metadatas is not None else {}
            }

        return ids

    def similarity_search(self, query: str, k: int = 4, **kwargs: Any) -> List[Document]:
        """执行相似性搜索"""
        # 1.将query转换成向量
        embedding = self._embedding.embed_query(query)

        # 2.循环遍历记忆存储,计算欧几里得距离
        result: list = []
        for key, record in self.store.items():
            distance = self._euclidean_distance(embedding, record["vector"])
            result.append({
                "distance": distance,
                **record,
            })

        # 3.找到欧几里得距离最小的k条记录
        sorted_result = sorted(result, key=lambda x: x["distance"])
        result_k = sorted_result[:k]

        # 4.循环构建文档列表并返回
        documents = [
            Document(page_content=item["text"], metadata={**item["metadata"], "score": item["distance"]})
            for item in result_k
        ]

        return documents

    @classmethod
    def from_texts(cls: Type["MemoryVectorStore"], texts: List[str], embedding: Embeddings,
                   metadatas: Optional[List[dict]] = None,
                   **kwargs: Any) -> "MemoryVectorStore":
        """通过文本、嵌入模型、元数据构建向量数据库"""
        memory_vector_store = cls(embedding=embedding, **kwargs)
        memory_vector_store.add_texts(texts, metadatas)
        return memory_vector_store

    @classmethod
    def _euclidean_distance(cls, vec1, vec2) -> float:
        """计算两个向量的欧几里得距离"""
        return np.linalg.norm(np.array(vec1) - np.array(vec2))


dotenv.load_dotenv()

# 1.创建初始数据与嵌入模型
texts = [
    "笨笨是一只很喜欢睡觉的猫咪",
    "我喜欢在夜晚听音乐,这让我感到放松。",
    "猫咪在窗台上打盹,看起来非常可爱。",
    "学习新技能是每个人都应该追求的目标。",
    "我最喜欢的食物是意大利面,尤其是番茄酱的那种。",
    "昨晚我做了一个奇怪的梦,梦见自己在太空飞行。",
    "我的手机突然关机了,让我有些焦虑。",
    "阅读是我每天都会做的事情,我觉得很充实。",
    "他们一起计划了一次周末的野餐,希望天气能好。",
    "我的狗喜欢追逐球,看起来非常开心。",
]
metadatas = [
    {"page": 1},
    {"page": 2},
    {"page": 3},
    {"page": 4},
    {"page": 5},
    {"page": 6, "account_id": 1},
    {"page": 7},
    {"page": 8},
    {"page": 9},
    {"page": 10},
]
embedding = OpenAIEmbeddings(model="text-embedding-3-small")

# 2.构建自定义向量数据库
db = MemoryVectorStore.from_texts(texts, embedding, metadatas)

# 3.执行检索
print(db.similarity_search("我养了一只猫,叫笨笨"))
<think>嗯,用户想了解或使用Marqo向量数据库,特别是询问使用指南或解决方案。首先,我需要确定Marqo的基本信息和使用方法。根据提供的引用,Marqo的官方文档应该是首要推荐的资源,因为官方文档通常最权威和详细。用户可能需要安装配置、核心功能、应用场景等方面的指导。 接下来,检查用户提供的引用内容。引用[1]提到了Marqo的官方文档、LangChain集成指南和GitHub仓库,这些都是关键资源。需要将这些资源整理出来,分步骤介绍。另外,引用[3]提到了Marqo学习资料汇总,可能包含额外的教程或案例,可以补充推荐。 用户可能对如何快速开始使用Marqo感兴趣,所以应该包括安装步骤和基础操作的代码示例,比如创建索引和添加文档。同时,结合LangChain的集成也是一个重要点,因为引用[4]提到了与LangChain的交互系统,可能需要说明如何利用LangChain模块进行问题与答案数据的加载和应用。 需要确保回答结构清晰,分点说明,比如安装配置、核心功能、解决方案和常见问题。每个部分下提供具体步骤或示例代码,帮助用户逐步操作。同时,要提醒用户参考官方文档以获取最新信息,避免过时的内容。 另外,用户可能关心Marqo的应用场景和优势,比如与传统数据库的区别,引用[2]提到传统数据库可能支持向量搜索,但Marqo作为专门的向量数据库可能有更好的性能或集成功能。这部分需要简要对比,突出Marqo的优势。 最后,生成相关问题时要围绕用户可能进一步的需求,比如性能优化、应用案例、与传统数据库对比等,确保覆盖用户潜在的问题。</think>### Marqo 向量数据库使用指南与解决方案 #### 1. **安装与配置** Marqo支持通过Docker快速部署,适合本地开发与云端环境。 ```bash docker pull marqoai/marqo:latest docker run -p 8882:8882 --add-host host.docker.internal:host-gateway marqoai/marqo:latest ``` 启动后可通过`http://localhost:8882`访问Web界面[^1]。 #### 2. **核心功能** - **向量索引创建** 使用Python客户端创建索引指定向量模型(如CLIP、BERT): ```python from marqo import Client client = Client("http://localhost:8882") client.create_index("my_index", model="hf/all_datasets_v4_MiniLM-L6") ``` - **数据插入与搜索** 添加文档执行多模态搜索(支持文本、图像): ```python client.index("my_index").add_documents([{"_id": "1", "text": "A red apple", "image": "http://example.com/apple.jpg"}]) results = client.index("my_index").search("red fruit", searchable_attributes=["text", "image"]) ``` #### 3. **集成LangChain** Marqo与LangChain深度集成,可用于构建问答系统或知识库[^4]: ```python from langchain.vectorstores import Marqo vectorstore = Marqo(url="http://localhost:8882", index_name="my_index") retriever = vectorstore.as_retriever() ``` #### 4. **典型应用场景** - **跨模态搜索**:同时检索文本与图片(如电商商品搜索)[^3]。 - **推荐系统**:基于用户行为向量生成个性化推荐。 - **语义分析**:通过BERT等模型理解长文本语义。 #### 5. **性能优化建议** - **分片与副本**:通过`index_settings`调整分片数提升吞吐量。 - **模型选择**:轻量模型(如MiniLM)适合实时场景,大型模型(如ResNet)适合精度优先任务[^1]。 - **缓存机制**:对高频查询结果缓存以减少计算开销。 #### 6. **常见问题** - **资源占用**:默认配置需至少4GB内存,生产环境建议8GB以上。 - **数据格式**:非结构化数据需预处理为键值对形式(如JSON)。 - **模型适配**:自定义模型需通过Docker挂载至`/model_cache`目录[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值