|
在了解这四种实现方式前,我们需要厘清几个相关的概念。 首先是向量嵌入,向量嵌入其实就是将人能理解的文本、图像等信息转换为电脑可以认识的数字的过程。 这些数字组成一个向量(一维数组),用于表示原始内容的语义特征。 
还一个比较重要的是概念是向量维度。 向量维度是指这个数字数组的长度。例如: - 一个384维的向量包含384个数字
- 一个1536维的向量包含1536个数字
维度越高,向量能够捕捉的语义信息就越丰富,但计算成本和存储空间也越大。 这就像是用不同精度的照相机拍照 - 高精度相机能捕捉更多细节,但照片文件也更大。 
在实际应用中,不同模型生成的向量维度不同: - OpenAI的text-embedding-3-small生成1536维向量
- all-MiniLM-L6-v2生成384维向量
- BAAI/bge-large模型生成1024维向量
最后就是相似度,当我们在说两个文本在语义上相似时,实际上就是指它们的向量在高维空间中距离很近。 向量之间的距离(通常用余弦相似度计算)越小,表示内容越相关。 下面是一个例子。 
当两个文本在语义上相似时, 它们的向量在高维空间中距离很近。 例如, "国王" (文本 A) 和 "女王" (文本 B) 的向量距离会很近, 因为它们都与皇室、权力等概念相关。 而 "苹果" (文本 C) 的向量会与 "国王" 和 "女王" 的向量距离很远, 因为它属于水果、食物等完全不同的语义范畴。 向量之间的距离越小 (通常用余弦相似度计算), 表示内容越相关。 在构建检索增强生成(RAG)应用中,向量嵌入是关键环节。 整个流程包括: - 收集非结构化文档(PDF、网页等)
- 将文档分割成较小的文本块
- 使用嵌入模型将这些块转换为向量
- 将向量存储在向量数据库中
- 查询时,将用户问题转换为向量,并获取最相关的文档块

检索增强生成(RAG)的完整流程,向量嵌入是连接文档和查询的关键。 现在,正文开始,四种在Python中实现向量嵌入的方法,每种都有其独特优势和局限性,后面会对这种方式的选择做统一的梳理和总结。 一:本地模型生成嵌入选择在本地运行嵌入模型这理由很简单:不需要API密钥无网络依赖、完全掌控过程隐私保障。 具体的操作步骤不是特别复杂,安装必要的库: pipinstallsentence_transformers 使用预训练模型生成嵌入: fromsentence_transformersimportSentenceTransformer#加载模型-选择了小型通用模型model=SentenceTransformer("all-MiniLM-L6-v2")#为单个文本生成嵌入text="深度学习已经彻底改变了自然语言处理领域"embedding=model.encode(text)print(f"嵌入维度:{len(embedding)}")#输出:嵌入维度:384print(f"嵌入向量的前5个值:{embedding[:5]}")
#例如:[0.045,-0.032,0.076,-0.124,0.253]#批量处理多个文本更高效texts=["深度学习已经彻底改变了自然语言处理领域","向量数据库能够高效存储和查询嵌入向量","检索增强生成通过外部知识弥补了大语言模型的不足"]
embeddings=model.encode(texts)print(f"批量嵌入形状:{embeddings.shape}")
#输出:批量嵌入形状 3,384)可以看到,每个文本被转换成了一个384个数字组成的向量。这些看似随机的数字实际上捕捉了文本的语义特征 - 相似概念的文本会有相似的数值模式。 
图4:使用本地模型生成嵌入并降维可视化,相似文本聚集在一起 那不同模型怎么选呢? all-MiniLM-L6-v2:小巧(~100MB),384维,适合初始原型开发 BAAI/bge-large-en-v1.5:更大(~1.3GB),1024维,搜索质量明显更好 multilingual-e5-large:多语言支持,1024维,在跨语言检索中表现出色 我的踩坑经验:在处理超过10,000个文档时,MacBook上的本地模型变得极慢,所以我一般会将文档分批处理,每批不超过1000个,并将生成的向量保存到磁盘,避免重复计算。 importnumpyasnpfromtqdmimporttqdm#分批处理大量文本batch_size=1000all_embeddings=[]foriintqdm(range(0,len(all_texts),batch_size)):
batch=all_texts[i:i+batch_size]
batch_embeddings=model.encode(batch)
all_embeddings.append(batch_embeddings)#定期保存,防止意外丢失ifi%5000==0:
np.save(f"embeddings_checkpoint_{i}.npy",np.vstack(all_embeddings))
final_embeddings=np.vstack(all_embeddings)方法二:API服务生成嵌入不过随着项目规模扩大,一般都会选择商业API服务。优势明显:专业维护的模型、无需本地资源、稳定可靠的服务。 
图5:通过API服务生成嵌入的架构和流程示意图 以OpenAI的API为例: importopenai#设置API密钥openai.api_key="你的API密钥"#使用OpenAI的嵌入APIresponse=openai.Embedding.create(
model="text-embedding-3-small",input="深度学习已经彻底改变了自然语言处理领域")
embedding=response['data'][0]['embedding']print(f"嵌入维度:{len(embedding)}")
#输出:嵌入维度:1536print(f"嵌入向量的前5个值:{embedding[:5]}")
#例如:[0.002,-0.015,0.023,0.019,-0.007]注意这里生成的是1536维向量,比本地模型的384维要大得多。这些额外的维度使OpenAI的模型能够捕捉更细微的语义差异,通常能提供更精确的相似度匹配。 使用谷歌Gemini的API: fromgoogleimportgenai#创建客户端并配置APIclient=genai.Client(api_key="你的API密钥")#使用Gemini生成嵌入result=client.models.embed_content(
model="gemini-embedding-exp-03-07",
contents="深度学习已经彻底改变了自然语言处理领域")print(f"嵌入维度:{len(result.embeddings)}")方法三:框架集成在大型项目中,使用LangChain能简化开发流程提供统一接口和丰富功能。 
图6:使用LangChain框架整合不同嵌入模型和向量数据库的架构图 安装相关库: pipinstalllangchainlangchain_openai LangChain支持多种嵌入模型,代码几乎完全相同: fromlangchain_openaiimportOpenAIEmbeddingsfromlangchain_community.embeddingsimportHuggingFaceEmbeddings#使用OpenAI嵌入openai_embeddings=OpenAIEmbeddings(
model="text-embedding-3-small",
openai_api_key="你的API密钥")#使用本地HuggingFace模型local_embeddings=HuggingFaceEmbeddings(
model_name="BAAI/bge-large-zh")#两种方式使用相同的APIquery_text="检索增强生成的工作原理是什么?"openai_vector=openai_embeddings.embed_query(query_text)
local_vector=local_embeddings.embed_query(query_text) 框架集成最大的优势是与向量数据库和LLM无缝衔接,构建完整的RAG流程: fromlangchain_openaiimportOpenAIEmbeddings,ChatOpenAIfromlangchain_community.vectorstoresimportChromafromlangchain.text_splitterimportRecursiveCharacterTextSplitterfromlangchain.chainsimportcreate_retrieval_chainfromlangchain.chains.combine_documentsimportcreate_stuff_documents_chainfromlangchain.promptsimportChatPromptTemplate#1.准备文档withopen("knowledge_base.txt","r")asf:
raw_text=f.read()#2.分割文档text_splitter=RecursiveCharacterTextSplitter(chunk_size=1000,chunk_overlap=200)
splits=text_splitter.split_text(raw_text)#3.创建向量存储embedding_model=OpenAIEmbeddings(model="text-embedding-3-small")
vectorstore=Chroma.from_texts(texts=splits,embedding=embedding_model)#4.创建检索器retriever=vectorstore.as_retriever(search_kwargs={"k":3})#5.设置LLM和提示模板llm=ChatOpenAI(model="gpt-3.5-turbo")
prompt=ChatPromptTemplate.from_template("""
基于以下上下文回答问题:
{context}
问题:{input}
""")#6.创建RAG链combine_docs_chain=create_stuff_documents_chain(llm,prompt)
retrieval_chain=create_retrieval_chain(retriever,combine_docs_chain)#7.执行查询result=retrieval_chain.invoke({"input":"什么是向量嵌入?"})print(result["answer"])
图7:使用LangChain实现完整RAG流程的详细步骤示意图 方法四:数据库内置生成嵌入某些向量数据库提供内置功能,可以在存储或查询时直接生成向量嵌入,极大简化开发流程。处理大规模数据时尝试了这种方法,效果非常显著。 
图8:数据库内置向量嵌入功能的工作原理示意图 以Astra DB为例: fromastrapyimportDataAPIClient#连接到数据库client=DataAPIClient("应用令牌")
database=client.get_database("API端点")
collection=database.get_collection("知识库")#插入文档时自动生成嵌入result=collection.insert_one(
{"$vectorize":"大语言模型通过自注意力机制学习文本表示","source":"AI研究论文","date":"2025-01-15"}
)#查询时自动生成向量并搜索query_results=collection.find(
{},
sort={"$vectorize":"注意力机制如何工作?"},
limit=5)内置向量生成的最大优势是简化了整个开发流程,减少了API调用和代码复杂度。 嵌入模型的选择方法论一套选择嵌入模型的方法论: 更高维度通常捕捉更多语义信息,但存储和检索成本更高小型项目:384-512维足够,大型项目:1024维或更高提供更好性能。 不同的领域专业性而言:通用内容推荐象all-MiniLM、text-embedding-3等多域模型,如果是特别的专业内容还是选择领域特定模型或自行微调比较好。 当然不管最后怎么选还是得优化考虑成本效果问题。 
希望能为你在探索向量嵌入技术的道路上提供有价值的参考。 |