文章首发CSDN——《使用开源Embedding模型嵌入高维空间向量》
发现问题
今天在学AI的时候发现一个问题:我想将分割后的文档嵌入到Qdrant数据库中,并用moonshot访问。但是我发现moonshot模型不适合生成嵌入,也就是说,没有通常意义下的embeddings方法。
探索过程
这个问题困扰了我好长时间,一直在搜资料怎样让moonshot可以生成嵌入,最终也没找到方法...
不过过程中ai还是给出了一个可行的解决方法
AI:可以使用OpenAI的嵌入模型
我:???
我肯定知道OpenAI的模型能用啊...
这里还是贴一下OpenAI使用的代码吧,有条件的可以使用这个:
需要再安装一个库
pip install qdrant-client
#将分割嵌入并存储在矢量数据库Qdrant中
from langchain.vectorstores import Qdrant
from langchain.embeddings import OpenAIEmbeddings
vectorstore = Qdrant.from_documents(
documents=chunked_documents, # 以分块的文档
embedding=OpenAIEmbeddings(), # 用OpenAI的Embedding Model做嵌入
location=":memory:", # in-memory 存储
collection_name="my_documents",) # 指定collection_name
需要提前配置好OpenAI的key
进一步探索
其实上面的回答并不能解决实际问题,毕竟,要是能用OpenAI的模型也就不去费这个劲了~
那么,看看火山模型是怎么解决的!
from langchain_community.vectorstores import Qdrant
from volcenginesdkarkruntime import Ark
from langchain.pydantic_v1 import BaseModel
from typing import Dict, List, Any
from langchain.embeddings.base import Embeddings
# 火山模型
class DoubaoEmbeddings(BaseModel, Embeddings):
client: Ark = None
api_key: str = ""
model: str
def __init__(self, **data: Any):
super().__init__(**data)
if self.api_key == "":
self.api_key = os.environ["OPENAI_API_KEY"]
self.client = Ark(
base_url=os.environ["OPENAI_BASE_URL"],
api_key=self.api_key
)
def embed_query(self, text: str) -> List[float]:
embeddings = self.client.embeddings.create(model=self.model, input=text)
return embeddings.data[0].embedding
def embed_documents(self, texts: List[str]) -> List[List[float]]:
return [self.embed_query(text) for text in texts]
class Config:
arbitrary_types_allowed = True
vectorstore = Qdrant.from_documents(
documents=chunked_documents, # 以分块的文档
embedding=DoubaoEmbeddings(
model=os.environ["EMBEDDING_MODELEND"],
), # 用OpenAI的Embedding Model做嵌入
location=":memory:", # in-memory 存储
collection_name="my_documents",
) # 指定collection_name
诶! 我有个主意
我们把里面的换成moonshot的不就行了?
答案是:不行!
会报如下错:
raise AttributeError(f'{type(self).__name__!r} object has no attribute {item!r}')
AttributeError: 'Moonshot' object has no attribute 'embeddings'
也是,拿过来改改就能用也太不合理了
最终探索
到了这步有点进行不下去了,突然想到一个问题:
嵌入模型必须和语言模型一致才能使用吗?
诶,还真不是!
Embedding模型在NLP中只负责将词汇映射为高维空间向量,与后续的语言模型并不需要使用统一个。
那现在问题就很简单了,有没有什么开源的Embedding模型呢?
Sentence Transformers (Sentence-BERT):这是一个基于 BERT 的嵌入模型,可以生成高质量的句子嵌入。
上手!
先下载一下对应的库
pip install transformers
接下来就是见证奇迹的时刻
from langchain_community.vectorstores import Qdrant
from typing import Dict, List, Any
from sentence_transformers import SentenceTransformer
class SentenceBERTEmbeddings:
def __init__(self, model_name='all-MiniLM-L6-v2'):
self.model = SentenceTransformer(model_name)
def embed_query(self, text: str) -> List[float]:
return self.model.encode(text).tolist()
def embed_documents(self, texts: List[str]) -> List[List[float]]:
return [self.embed_query(text) for text in texts]
def __call__(self, text: str) -> List[float]:
return self.embed_query(text)
class Config:
arbitrary_types_allowed = True
vectorstore = Qdrant.from_documents(
documents=chunked_documents, # 以分块的文档
embedding=SentenceBERTEmbeddings(), # 用OpenAI的Embedding Model做嵌入
location=":memory:", # in-memory 存储
collection_name="my_documents",) # 指定collection_name
搞定!
拓展
什么是NLP?
NLP(Natural Language Processing),也就是人们常说的 自然语言处理,就是研究如何让计算机读懂人类语言,即将人的自然语言转换为计算机可以阅读的指令。
分词是 NLP 任务的一个起始,分词的好坏会影响整体模型的好坏。并且分词不一样,语义不一样。
hanLP 是 NLP 处理工具,它是处理文本的工具,hanlp 拥有:中文分词、命名实体识别、摘要关键字、句法分析、简繁拼音转换、智能推荐。
NLP 还有很多处理工具,不同的处理工具处理的方法不一样,例如对一个词标注的标注可能不一样。
开源Embedding模型只有Sentence-BERT这一个吗?
当然不是,这里简单列举几个:
- Word2Vec:由Google提出的一种词向量化方法,基于分布假设——出现在相似上下文中的单词往往具有相似的意义。
- GloVe (Global Vectors for Word Representation) :由斯坦福大学的研究人员提出,结合全局统计信息与局部上下文信息来构建词向量。
- BERT (Bidirectional Encoder Representations from Transformers) :基于Transformer架构设计而成的预训练语言模型,能够在双向上下文中对句子进行编码。
- FastText:由Facebook提出,可以捕捉到词汇的n-gram特征,从而更好地处理词的形态变化和拼写错误。
更多的可以去 Huggingface上的MTEB排行榜了解一下