微信扫码
添加专属顾问
RAG技术如何突破黑盒困境?本文详解从文档分块到混合检索的全链路优化策略。 核心内容: 1. RAG技术面临的常见实践误区与优化方向 2. 文档分块、索引增强等关键环节的技术解析 3. 召回率与精确率的平衡策略及实践建议
# 设置本地数据保存目录local_data_dir = pathlib.Path("/Users/jiangdanyang/workspaces/python/MarioPython/src/RAG/dataset/ai-arxiv2")# 加载数据集(如果本地存在则从本地加载,否则下载)dataset = load_dataset("jamescalam/ai-arxiv2", split="train", cache_dir=str(local_data_dir))# 初始化编码器encoder = OpenAIEncoder(name="text-embedding-3-small",openai_api_key=os.getenv("AI_API_KEY"),openai_base_url=os.getenv("AI_API_BASE_URL"))chunker = StatisticalChunker(encoder=encoder,min_split_tokens=100,max_split_tokens=500,plot_chunks=True,enable_statistics=True,)chunks_0 = chunker(docs=[dataset["content"][0]], batch_size=500)
Chunking Statistics: - Total Documents: 474 - Total Chunks: 46 - Chunks by Threshold: 41 - Chunks by Max Chunk Size: 4 - Last Chunk: 1 - Minimum Token Size of Chunk: 54 - Maximum Token Size of Chunk: 495 - Similarity Chunk Ratio: 0.89
DOCUMENT_CONTEXT_PROMPT = """<document>{doc_content}</document>"""CHUNK_CONTEXT_PROMPT = """Here is the chunk we want to situate within the whole document<chunk>{chunk_content}</chunk>Please give a short succinct context to situate this chunk within the overall document for the purposes of improving search retrieval of the chunk.Answer only with the succinct context and nothing else."""
Given the following text chunk, generate {n} different questions that this chunk would be a good answer to:Chunk: {chunk}Questions (enumarate the questions with 1. 2., etc.):
first_sentence = "直播分享会AI Living第一场"second_sentence = "直播鲁班小组分享第77期"model = SentenceTransformer("/Users/jiangdanyang/workspaces/python/Model/all-MiniLM-L6-v2")tokenized_first_sentence = model.tokenize([first_sentence])tokenized_second_sentence = model.tokenize([second_sentence])
Sparse向量主要是通过BM25为代表的算法生成,BM25核心就是TF-IDF算法(词频-反向文档频率),返回是某个query相对每个文档编号的分数值(具体算法如下):
# Load the chunkscorpus_json = json.load(open('/Users/jiangdanyang/workspaces/python/MarioPython/src/RAG/dataset/corpus.json'))corpus_text = [doc["text"] for doc in corpus_json]# optional: create a stemmerenglish_stemmer = snowballstemmer.stemmer("english")# Initialize the Tokenizer with the stemmersparse_tokenizer = Tokenizer(stemmer=english_stemmer,lower=True, # lowercase the tokensstopwords="english",# or pass a list of stopwordssplitter=r"\w+",# by default r"(?u)\b\w\w+\b", can also be a function)# Tokenize the corpuscorpus_sparse_tokens = (sparse_tokenizer.tokenize(corpus_text,update_vocab=True, # update the vocab as we tokenizereturn_as="ids"))# Create the BM25 retriever and attach your corpus_json to itsparse_index = bm25s.BM25(corpus=corpus_json)# Now, index the corpus_tokens (the corpus_json is not used yet)sparse_index.index(corpus_sparse_tokens)# Return 10 the most relevant docs according to the querysparse_results, sparse_scores = sparse_index.retrieve(query_tokens, k=10)
Dense向量主要是通过基于Transformer架构的embedding模型来进行编码生成,同时针对查询query,使用同样的embedding模型进行编码,然后再进行向量的相似度比对,找出最相似的n个结果:
#Dense Index# create the vector database clientqdrant =QdrantClient(path="/Users/jiangdanyang/workspaces/python/MarioPython/src/RAG/dataset/qdrant_data")# Create the embedding encoderdense_encoder = SentenceTransformer('/Users/jiangdanyang/workspaces/python/Model/all-MiniLM-L6-v2')collection_name = "hybrid_search"qdrant.recreate_collection(collection_name=collection_name,vectors_config=models.VectorParams(size=dense_encoder.get_sentence_embedding_dimension(),distance=models.Distance.COSINE))# vectorize!qdrant.upload_points(collection_name=collection_name,points=[models.PointStruct(id=idx,vector=dense_encoder.encode(doc["text"]).tolist(),payload=doc) for idx, doc in enumerate(corpus_json) # data is the variable holding all the enriched texts])query_vector = dense_encoder.encode(query).tolist()dense_results = qdrant.search(collection_name=collection_name,query_vector=query_vector,limit=10)
最后针对上述两种方式找出的chunk做综合筛选,这里可以有多种方式,比如比较常用的就是先分别对Sparse向量和Dense向量计算出来的top n个结果的分值做归一化,然后针对统一个Chunk,按照一定的权重(比如Sparse向量计算结果权重0.2,Dense向量计算结果权重0.8)计算一个最终分值,最后返回top n个chunk列表给到下个节点:
# Normalize the two types of scoresdense_scores = np.array([doc.get("dense_score", 0) for doc in documents_with_scores])sparse_scores = np.array([doc.get("sparse_score", 0) for doc in documents_with_scores])dense_scores_normalized = (dense_scores - np.min(dense_scores)) / (np.max(dense_scores) - np.min(dense_scores))sparse_scores_normalized = (sparse_scores - np.min(sparse_scores)) / (np.max(sparse_scores) - np.min(sparse_scores))alpha = 0.2weighted_scores = (1 - alpha) * dense_scores_normalized + alpha * sparse_scores_normalized
如果当前场景的检索需要兼顾关键词和语义的时候,可以考虑混合搜索(需要结合文档内容、chunking和关键字词构建等环节);相对于关键字词匹配检索,混合搜索可以降低查询编写的规范性(不一定要有特定的关键词出现)以及提升查询的容错性(可能会有拼写错误或者不恰当的描述);相对于语义相似检索,混合搜索可以增加一些领域专有信息的更精准匹配,提升检索结果的准确性。
检索的优点是可以在海量的知识里面快速找到和用户query相关的内容块docs,但是检索所返回出来的docs,实际上可能部分和用户query关联度并不大,这个时候就需要通过re-rank这一步,对于检索返回出来的docs做关联度排序,最终选取最相关的top k个doc,做后续的上下文补充。
在RAG链路中,ReRanking的常用技术是Cross-Encoder(交叉编码器),本质一个Bert模型(Encode-only的transformer架构),计算query和每一个doc相关性,返回0~1之间的结果(1代表最相关),示意图和代码示例如下:
from sentence_transformers import CrossEncodercross_encoder = CrossEncoder("/Users/jiangdanyang/workspaces/python/Model/jina-reranker-v1-tiny-en")hybrid_search_results = {}with open('/Users/jiangdanyang/workspaces/python/MarioPython/src/RAG/dataset/dense_results.json') as f:dense_results = json.load(f)for doc in dense_results:hybrid_search_results[doc['id']] = docwith open('/Users/jiangdanyang/workspaces/python/MarioPython/src/RAG/dataset/sparse_results.json') as f:sparse_results = json.load(f)for doc in sparse_results:hybrid_search_results[doc['id']] = docconsole.print(hybrid_search_results)# This is the query that we used for the retrieval of the above documentsquery = "What is context size of Mixtral?"pairs = [[query, doc['text']] for doc in hybrid_search_results.values()]scores = cross_encoder.predict(pairs)
最后进行排序,选择top k个结果补充到context中,然后调用模型拿最后的结果:
client = OpenAI( api_key=os.getenv("AI_API_KEY"), base_url=os.getenv("AI_API_BASE_URL"))completion = client.chat.completions.create( model="qwen_max", messages=[ {"role": "system", "content": "You are chatbot, an research expert. Your top priority is to help guide users to understand reserach papers."}, {"role": "user", "content": query}, {"role": "assistant", "content": str(search_results)} ])AI应用的开发实践进行得非常火热,现阶段可能更多的是对已有的一些基建平台、开发编排工具、现成的横向基础产品做整合使用,结合使用场景做链路设计,但是随着时间推移,还是需要慢慢深入到部分细节,往深水区慢慢前行,本文讲述的RAG只是AI架构中的一块,其他相关的技术,在对待方式上也雷同,都需要经历快速使用、技术细节了解、使用产品实现了解、应用中的设计实现迭代、面向效果的循环优化,快速上手有捷径,得益于比较好的基础设施建设,成本比较低,但是深入追寻效果,切实提升效率或幸福感,需要更深入的探寻,希望对读到这里的小伙伴有帮助;
53AI,企业落地大模型首选服务商
产品:场景落地咨询+大模型应用平台+行业解决方案
承诺:免费POC验证,效果达标后再合作。零风险落地应用大模型,已交付160+中大型企业
2026-10-11
有了大模型,段誉为什么时灵时不灵
2026-10-08
ThinkParse 2.0 发布:内置 MinerU 4.0,把文档解析做成可扩展的企业级系统
2026-10-08
MFS:给 Agent 一个可搜索的上下文文件系统
2026-10-07
从零跑通 Meilisearch 中文搜索:分词与本地化 7 步,含 3 个坑
2026-09-28
Jev 进阶:重排序——让 BM25 的 top-1 准确率从 5% 翻到 18%
2026-09-28
PageIndex:扔掉向量数据库的RAG引擎,准确率从50%冲到98.7%
2026-09-22
阿里云 AgentBridge:为生产级 Agent 构建多源实时上下文
2026-09-20
RAG 3.0 来了:告别传统知识库,企业 AI 正在全面转向“知识智能体”!
2026-07-26
2026-07-25
2026-07-28
2026-08-05
2026-07-29
2026-07-24
2026-07-22
2026-07-26
2026-07-29
2026-08-05
2026-08-19
2026-08-18
2026-08-05
2026-08-05
2026-07-28
2026-07-27
2026-07-26
2026-07-25
欢迎您使用【53AI 官方网站】(以下简称“本网站”或“我们”)。本《会员服务协议》(以下简称“本协议”)是您(以下简称“会员”或“用户”)与【深圳市博思协创网络科技有限公司】之间关于注册、登录及使用本网站会员服务所订立的法律协议。
在您注册或登录前,请务必审慎阅读、充分理解各条款内容,特别是免除或限制责任的条款、知识产权条款、争议解决条款等。此类条款将以加粗形式提示您注意。 当您通过微信公众号授权、手机验证码验证或其他方式成功登录本网站时,即视为您已完全理解并同意接受本协议的全部内容。
一、 定义
本网站:指由【深圳市博思协创网络科技有限公司】运营的,域名为【53ai.com】的网站及相关移动端页面。
会员服务:指本网站向注册会员提供的知识库文章查阅、内容检索及其他相关增值服务。
知识库内容:指本网站发布的包括但不限于文字、图表、数据、研究报告、行业分析等数字化内容资源。
二、 账号注册与登录
登录方式:本网站支持以下登录方式,您可根据实际情况选择:
微信公众号授权登录:您同意将您的微信OpenID信息授权给本网站,用于创建或关联会员账号。
手机验证码登录:您需提供真实有效的手机号码,并通过短信验证码完成身份验证与登录/注册。
账号安全:您的账号仅限您本人使用,禁止赠与、借用、租用、转让或售卖。因您保管不善导致的账号被盗、密码泄露等损失,由您自行承担。
实名认证:根据相关法律法规要求,我们可能要求您在特定功能下完成实名认证。如您拒绝提供,可能无法使用部分或全部服务。
未成年人保护:若您未满18周岁,请在法定监护人的陪同下阅读本协议,并在征得监护人同意后使用本服务。
三、 服务内容与规范
知识库查阅权限:会员登录后,有权按照其会员等级对应的权限范围,在线浏览、检索本网站知识库中的相关文章及内容。
服务变更:我们有权根据业务发展需要,调整、变更或终止部分服务内容,并将以网站公告、公众号消息等方式提前通知。
禁止行为:您在使用服务时不得实施以下行为:
利用技术手段批量爬取、下载、转存知识库内容;
将知识库内容用于商业目的或未经授权地向第三方传播;
干扰本网站正常运行或侵犯其他用户合法权益;
发布违法违规信息或从事违反公序良俗的活动。
四、 知识产权声明
权利归属:本网站知识库中的排版设计、软件代码等内容的知识产权均归【公司全称】或原权利人所有,受《中华人民共和国著作权法》等法律保护。
有限许可:本网站授予会员一项非独占、不可转让、不可转授权的普通许可,仅限于个人学习、研究之目的在线查阅知识库内容。
侵权追责:未经书面许可,任何单位或个人不得以任何形式复制、转载、摘编、镜像、汇编或以其他方式使用上述内容。一经发现,我们保留追究其法律责任的权利。
五、 个人信息保护
我们重视对您个人信息的保护。关于我们如何收集、使用、存储和保护您的个人信息,请单独阅读 《隐私政策》。
您通过微信公众号授权或手机号验证所提供的信息,我们将严格按照《个人信息保护法》的规定处理,仅用于身份识别、服务提供及安全验证等必要用途。
您可以随时通过网站设置或联系客服行使查阅、更正、删除个人信息及撤回授权同意的权利。
六、 免责声明
内容准确性:知识库内容仅供参考,不构成专业建议。我们不对其完整性、准确性、时效性作任何明示或暗示的保证,您应自行判断并承担使用风险。
不可抗力:因自然灾害、政策法规变化、网络故障、第三方平台接口异常(如微信接口维护、运营商短信通道故障)等不可抗力导致的服务中断或延迟,我们不承担违约责任。
第三方链接:本网站可能包含指向第三方网站的链接,该等网站的内容和服务不受我们控制,请您自行甄别风险。
七、 违约责任
如您违反本协议约定,我们有权视情节采取警告、限制功能、暂停服务、注销账号等措施,并保留要求赔偿损失的权利。
如因您的违约行为导致我们遭受行政处罚、第三方索赔或商誉损失,您应承担全部赔偿责任(包括但不限于罚款、赔偿金、律师费、公证费等)。
八、 法律适用与争议解决
本协议的订立、执行和解释均适用中华人民共和国大陆地区法律。
因本协议产生的或与本协议有关的任何争议,双方应友好协商解决;协商不成的,任何一方均可向【公司所在地】有管辖权的人民法院提起诉讼。
九、 其他
本协议构成双方就本服务达成的完整协议,取代此前任何口头或书面约定。
本协议任一条款被认定为无效或不可执行的,不影响其他条款的效力。
我们对本协议享有最终解释权,并在法律允许的范围内保留随时修改的权利。修改后的协议一经公布即生效,继续使用服务即视为同意修订内容。