langchain 基于ES的数据向量化存储和检索

中文向量化模型候选:

1、sentence-transformers/all-MiniLM-L6-v2 向量维度为384维,支持多种语言。

2、BAAI/bge-m3

3、多语言模型:BAAI/bge-m3 支持的输入长度<=8192

 from langchain_community.embeddings import HuggingFaceBgeEmbeddings

model_name = "sentence-transformers/all-MiniLM-L6-v2"
model_kwargs = {"device": "cpu"}
encode_kwargs = {"normalize_embeddings": True}
embeddings = HuggingFaceBgeEmbeddings(
    model_name=model_name, model_kwargs=model_kwargs, encode_kwargs=encode_kwargs
)

1·、存储源为elasticsearch

from typing import Any, Dict, Iterable

from elasticsearch import Elasticsearch
from elasticsearch.helpers import bulk
from langchain.embeddings import DeterministicFakeEmbedding
from langchain_core.documents import Document
from langchain_core.embeddings import Embeddings
from langchain_elasticsearch import ElasticsearchRetriever

es_url = "http://user:password@localhost:9200"
es_client = Elasticsearch(hosts=[es_url])
es_client.info()

index_name = "test-langchain-retriever"
text_field = "text"
dense_vector_field = "fake_embedding"
num_characters_field = "num_characters"
texts = [
    "foo",
    "bar",
    "world",
    "hello world",
    "hello",
    "foo bar",
    "bla bla foo",
]

def create_index(
    es_client: Elasticsearch,
    index_name: str,
    text_field: str,
    dense_vector_field: str,
    num_characters_field: str,
):
    es_client.indices.create(
        index=index_name,
        mappings={
            "properties": {
                text_field: {"type": "text"},
                dense_vector_field: {"type": "dense_vector"},
                num_characters_field: {"type": "integer"},
            }
        },
    )


def index_data(
    es_client: Elasticsearch,
    index_name: str,
    text_field: str,
    dense_vector_field: str,
    embeddings: Embeddings,
    texts: Iterable[str],
    refresh: bool = True,
) -> None:
    create_index(
        es_client, index_name, text_field, dense_vector_field, num_characters_field
    )

    vectors = embeddings.embed_documents(list(texts))
    requests = [
        {
            "_op_type": "index",
            "_index": index_name,
            "_id": i,
            text_field: text,
            dense_vector_field: vector,
            num_characters_field: len(text),
        }
        for i, (text, vector) in enumerate(zip(texts, vectors))
    ]

    bulk(es_client, requests)

    if refresh:
        es_client.indices.refresh(index=index_name)

index_data(es_client, index_name, text_field, dense_vector_field, embeddings, texts)

2、elasticsearch 向量检索:

es_url = "http://user:password@localhost:9200"

index_name = "test-langchain-retriever"
text_field = "text"
dense_vector_field = "fake_embedding"
num_characters_field = "num_characters"

def gen_dsl(search_query: str) -> Dict:
    vector = embeddings.embed_query(search_query)  # same embeddings as for indexing
    return {
        "knn": {
            "field": dense_vector_field,
            "query_vector": vector,
            "k": 5,
            "num_candidates": 10,
        }
    }


vector_retriever = ElasticsearchRetriever.from_es_params(
    index_name=index_name,
    body_func=vector_query,
    content_field=text_field,
    url=es_url,
)

vector_retriever.invoke("foo")

说明:简单的向量检索,耗时比较长。

原因:1、直接对全局使用了余弦相似度计算。(cos),未做任何优化

            2、返回数据将向量内容全部返回

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
首先,text2vec是一个用于文本向量化的R语言包,它可以将文本转换成数值向量,同时提供了一些常见的向量化方法,例如word2vec, GloVe, fasttext等。而Elasticsearch是一个基于Lucene搜索引擎的开源搜索和分析引擎,它支持全文搜索、结构化搜索、地理位置搜索等。 要使用text2vec和elasticsearch做向量化搜索,一般有以下几个步骤: 1. 使用text2vec将文本转换成数值向量,可以选择合适的向量化方法。 2. 将向量化后的文本存储到elasticsearch中,可以使用elasticsearch的bulk API进行批量插入。 3. 在elasticsearch中创建一个索引,可以选择合适的分词器和搜索器,同时指定向量字段的类型为dense_vector。 4. 执行搜索时,先使用text2vec将查询文本转换成向量,再使用elasticsearch的dense_vector类型的查询进行向量化搜索。 下面是一个简单的R语言示例代码,用于将文本向量化并插入到elasticsearch中: ```R library(text2vec) library(elasticsearch) # 加载数据 data("movie_review") # 使用word2vec将文本向量化 model <- create_word2vec(movie_review$review, iter = 10, threads = 4) vectors <- t(t(apply(model$wv, 1, function(x) x / sqrt(sum(x^2))))) # 连接elasticsearch es <- connect(host = "localhost", port = 9200) # 批量插入向量数据 docs <- lapply(seq_along(movie_review$review), function(i) { list( _index = "movie_reviews", _type = "review", _id = i, _source = list( review = movie_review$review[i], rating = movie_review$rating[i], vector = as.list(vectors[i, ]) ) ) }) bulk(es, docs) ``` 在elasticsearch中创建索引和查询时,可以参考官方文档的说明。注意,在使用向量化搜索时,需要使用elasticsearch的dense_vector类型的查询,例如: ```json { "query": { "script_score": { "query": { "match_all": {} }, "script": { "source": "cosineSimilarity(params.queryVector, 'vector') + 1.0", "params": { "queryVector": [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0] } } } } } ``` 其中,cosineSimilarity是elasticsearch提供的计算余弦相似度的函数,params.queryVector是查询向量。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

会发paper的学渣

您的鼓励和将是我前进的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值