RAG-搞懂嵌入向量的生成
上文我们讲到如何对文档进行分块那文档分块后就能直接放入向量数据库中并检索了吗答案是否定的文档分块后需要通过嵌入模型将数据转成向量表示。所以本文主要讲述如何将数据转成向量以及选择合适的嵌入模型。在文档切块后通过embedding将文本计算成向量表示并存入向量库代码实现相似度匹配通过openAI的text-embedding-3-small嵌入模型实现查询哪位用户最关注“浙江某科技有限公司”。将文本转换成稠密向量Dense通过语义相似度找到这位用户。流程如下企业财务报表.csv实现import os from dotenv import load_dotenv load_dotenv() import pandas as pd import numpy as np from sklearn.metrics.pairwise import cosine_similarity from openai import OpenAI # 客户端 client OpenAI( base_urlos.getenv(PROXY_AI_BASE_URL), api_keyos.getenv(PROXY_AI_API_KEY) ) # # user_id, company_name # df pd.read_csv(企业财务报表.csv, encodingutf-8) # # 生成向量函数 # def get_embedding(text): rsp client.embeddings.create(input[text], modeltext-embedding-3-small) return np.array(rsp.data[0].embedding) # # 为每个企业生成一个简单的文本 # company_names df[company_name].unique() company_texts {c: f企业名称{c} for c in company_names} # # 生成企业向量 # company_vectors {} for c in company_names: vec get_embedding(company_texts[c]) company_vectors[c] vec print(f\n企业{c}) print(向量前10个值, vec[:10]) # -- 打印真实向量 # # 生成用户向量关注企业的平均向量 # user_vectors {} for user_id, group in df.groupby(user_id): vecs [company_vectors[row[company_name]] for _, row in group.iterrows()] user_vectors[user_id] np.mean(vecs, axis0) # # 随便选一个目标企业 # target_company 浙江某科技有限公司 target_vec company_vectors[target_company] # # 计算相似度 # results [] for uid, uvec in user_vectors.items(): sim cosine_similarity([uvec], [target_vec])[0][0] results.append((uid, sim)) result_df pd.DataFrame(results, columns[user_id, similarity]) result_df result_df.sort_values(bysimilarity, ascendingFalse) print(\n) print(f最可能关注 {target_company} 的用户) print(result_df.head())输出结果从结果上看user011是最关注“浙江某科技有限公司”的用户。关键词检索用BM25算法把关键词文本变成稀疏向量。其流程财务文本-分词营业收入、净利润、资产负债率…-统计词频-计算BM25分数重要关键词高分-输出【稀疏向量】{编号:分数}实现from collections import Counter import math # # 企业财务知识文本你的项目场景 # finance_texts [ 2024年公司营业收入12.5亿元同比增长18%净利润1.8亿元, 企业资产负债率22%流动比率1.98偿债能力处于健康水平, 研发投入1.9亿元占总营收比例15.2%同比提升2.3个百分点, 经营活动现金流净额3.2亿元比去年同期增加1.1亿元, 公司毛利率14.6%期间费用率控制在8.3%盈利能力稳定 ] # 超参数BM25标准 k1 1.5 b 0.75 # # 构建财务词表 # vocabulary set(word for text in finance_texts for word in text.split()) vocab_to_idx {word: idx for idx, word in enumerate(vocabulary)} # # 计算 IDF # N len(finance_texts) df Counter(word for text in finance_texts for word in set(text.split())) idf {word: math.log((N - df[word] 0.5) / (df[word] 0.5) 1) for word in vocabulary} # # 平均文本长度 # avg_text_len sum(len(text.split()) for text in finance_texts) / N # # BM25 稀疏嵌入关键词权重 # def bm25_sparse_embedding(text): tf Counter(text.split()) text_len len(text.split()) embedding {} for word, freq in tf.items(): if word in vocabulary: idx vocab_to_idx[word] score idf[word] * (freq * (k1 1)) / (freq k1 * (1 - b b * text_len / avg_text_len)) embedding[idx] score return embedding # # 输出每个财务文本的稀疏向量 # for i, text in enumerate(finance_texts): sparse_emb bm25_sparse_embedding(text) print(f\n 财务文本 {i1} ) print(f内容{text}) print(fBM25稀疏嵌入关键词权重{sparse_emb})结果混合检索通过bge-m3 生成三种向量用于RAG混合检索。实现import os import numpy as np from dotenv import load_dotenv from openai import OpenAI load_dotenv() # 线上BGE-M3 API配置 client OpenAI( base_urlos.getenv(PROXY_AI_BASE_URL), api_keyos.getenv(PROXY_AI_API_KEY) ) def get_bge_m3_three_vectors(text: str): 调用线上BGE-M3 API同时返回 dense / sparse / colbert 三种向量 response client.embeddings.create( inputtext, modelBAAI/bge-m3, encoding_formatfloat, extra_body{ return_sparse: True, return_colbert: True } ) data response.data[0] return { dense: np.array(data.embedding, dtypenp.float32), sparse: data.sparse_embedding, # dict: {index: weight} colbert: np.array(data.colbert_embedding, dtypenp.float32) } def main(): finance_text 2024年公司营业收入12.5亿元同比增长18%净利润1.8亿元 vectors get_bge_m3_three_vectors(finance_text) print( 财务文本 ) print(finance_text) print( * 60) print(\n✅ 稠密向量 Dense) print(f维度: {vectors[dense].shape}) print(f前8个值: {np.round(vectors[dense][:8], 4)}) print(\n✅ 稀疏向量 Sparse) print(f非零元素: {len(vectors[sparse])}) print(前5个权重:, dict(list(vectors[sparse].items())[:5])) print(\n✅ Colbert多向量) print(f形状: {vectors[colbert].shape} (token数 × 1024)) print(第一个token向量前5个值:, np.round(vectors[colbert][0][:5], 4)) if __name__ __main__: main()稠密向量 (Dense)→ 语义检索稀疏向量 (Sparse)→ 关键词匹配多向量 (Colbert)→ 细粒度匹配向量的表示形式稠密向量dense一串固定维度的浮点数组如384/768/1024/1536维每一维几乎都有值。代表BGE、OpenAI Embedding、Jina举例[0.123, -0.456, 0.789, ..., 0.222]优点表达语义强适合“ 语义相近 ” 检索缺点对精确匹配编号、ID、专有名词可能不如关键词检索稳定稀疏向量sparse大多元素是0维度巨大。但是非常稀疏常用 “词频/特征-权重 ” 字典表示。代表BM25、TF-IDF、bge-m3 sparse举例[0,0,0,2.3,0,0,1.8,...0,3.1]优点精确匹配强特别适合编号、ID、专有名词缺点对语义改写的泛化能力弱多向量Multi-vector一个文本多套向量表示检索时做更细粒度匹配代表ColBERT、BGE-M3优点检索精度高、混合检索跨语言检索缺点索引更大、检索更慢、工程复杂嵌入模型的选择不同场景下的嵌入模型选择场景embedding 类型模型什么时候选它传纯文本回答稠密 denseOpenAItext-embedding-3-smallJinajina-embeddings-v3用户提问是“说法各不相同”要靠语义找到相关的段落关键词/专有名词精确命中稀疏 sparse / BM25BM25精确命中关键词通常工业级RAG中文混合hybriddensesparseBAAI/bge-m3绝大多数情况下这是更稳的选择多语言中文支持多语言/中文更强的 densebge-m3 / Jina /OpenAI不同模型中文检索质量差异很大建议用你自己的小评测集验证MTEB排行榜衡量文本嵌入模型的参考下面的图会告诉你在不同参数规模下哪个模型最快哪个模型最准哪个最省资源。地址https://huggingface.co/spaces/mteb/leaderboardY轴Mean (Task)代表模型在所有基准任务上的平均得分。分数越高、语义理解能力越强检索越准。X轴Number of Active Parameters代表模型的激活参数量。数值越大、模型越重、能力越强。气泡颜色/大小颜色越深/越大表示允许输入/生成的token上限越高、就是上下文长度越长。点到气泡上可以看到具体的模型配置/版本。所以根据上图想要低成本快速上线的选择最左边的模型想要长上下文的选择最上面的模型。想要超长文档处理的选择最右边的模型。总结文档分块后不能直接检索必须通过嵌入模型转为向量再存入向量数据库才能实现高效语义 / 关键词匹配。学AI大模型的正确顺序千万不要搞错了2026年AI风口已来各行各业的AI渗透肉眼可见超多公司要么转型做AI相关产品要么高薪挖AI技术人才机遇直接摆在眼前有往AI方向发展或者本身有后端编程基础的朋友直接冲AI大模型应用开发转岗超合适就算暂时不打算转岗了解大模型、RAG、Prompt、Agent这些热门概念能上手做简单项目也绝对是求职加分王给大家整理了超全最新的AI大模型应用开发学习清单和资料手把手帮你快速入门学习路线:✅大模型基础认知—大模型核心原理、发展历程、主流模型GPT、文心一言等特点解析✅核心技术模块—RAG检索增强生成、Prompt工程实战、Agent智能体开发逻辑✅开发基础能力—Python进阶、API接口调用、大模型开发框架LangChain等实操✅应用场景开发—智能问答系统、企业知识库、AIGC内容生成工具、行业定制化大模型应用✅项目落地流程—需求拆解、技术选型、模型调优、测试上线、运维迭代✅面试求职冲刺—岗位JD解析、简历AI项目包装、高频面试题汇总、模拟面经以上6大模块看似清晰好上手实则每个部分都有扎实的核心内容需要吃透我把大模型的学习全流程已经整理好了抓住AI时代风口轻松解锁职业新可能希望大家都能把握机遇实现薪资/职业跃迁这份完整版的大模型 AI 学习资料已经上传CSDN朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费】