R2R 检索与 RAG 实战指南:从向量搜索、混合检索到流式生成
【免费下载链接】R2RSoTA production-ready AI retrieval system. Agentic Retrieval-Augmented Generation (RAG) with a RESTful API.项目地址: https://gitcode.com/GitHub_Trending/r2/R2R
R2R 是一套生产可用的 AI 检索系统,围绕/retrieval/search与/retrieval/rag两个核心端点,提供了向量搜索、全文搜索、混合搜索(Hybrid Search)以及检索增强生成(RAG)的完整能力。本文以 search-and-rag.md 为主线,结合仓库内的路由实现、服务层源码与集成测试,系统讲解search_mode、search_settings、过滤语法、距离度量、知识图谱增强与流式 RAG 的配置与调用方式。读完本文,你将能够在 R2R 中按需组合语义检索、关键词检索与 LLM 生成,构建可落地、可调试的检索问答管线。
阅读前提:文档与代码示例均针对 R2R v3 API。默认服务地址为
http://localhost:7272,示例中的https://api.sciphi.ai为官方托管服务地址,自建部署时请替换为本地地址。所有请求都需要在Authorization: Bearer头中携带有效令牌(使用认证功能时)。
检索的核心控制面:search_mode与search_settings
无论是调用 Search 还是 RAG 端点,检索过程都由两个参数共同驱动:
search_mode(可选,默认custom):选择预设模式或完全自定义。basic:默认使用简单的语义搜索配置,适合快速上手;advanced:默认使用结合语义与全文的混合搜索配置,召回面更广;custom:通过search_settings对象完全自定义。若custom模式下省略search_settings,则应用默认向量搜索配置。
search_settings(可选):细粒度配置对象。如果与basic或advanced模式同时提供,这些设置会覆盖模式的默认值。关键字段包括:
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
use_semantic_search | bool | true | 启用/禁用基于向量的语义搜索 |
use_fulltext_search | bool | false | 启用/禁用基于关键词的全文搜索 |
use_hybrid_search | bool | false | 启用混合搜索(语义 + 全文),需要配合hybrid_settings |
filters | dict | {} | 使用 MongoDB 风格语法应用复杂过滤规则(见下文"高级过滤") |
limit | int | 10 | 返回结果的最大数量 |
hybrid_settings | object | — | 配置混合搜索的权重(semantic_weight、full_text_weight)、限制(full_text_limit)与融合参数(rrf_k) |
chunk_settings | object | — | 微调向量索引参数,如index_measure(距离度量)、probes、ef_search |
search_strategy | string | "vanilla" | 启用 HyDE 或 RAG-Fusion 等高级 RAG 技术(见 高级 RAG 指南) |
include_scores | bool | true | 是否在结果中包含相关性分数 |
include_metadatas | bool | true | 是否在结果中包含元数据 |
从源码看,这些字段在 py/shared/abstractions/search.py 的SearchSettings中被正式定义。值得注意的默认值与约束:
limit被限制在1 ~ 1000之间(ge=1, le=1_000);- 还提供
offset字段(默认0)用于分页; search_strategy的可选值在服务层被解释为vanilla(基础检索)、hyde(HyDE)与rag_fusion(RAG-Fusion),代码注释中还提及了query_fusion;- 当使用 HyDE 或 RAG-Fusion 策略时,
num_sub_queries(默认5)控制生成子查询/假设文档的数量。
SearchSettings.get_default(mode)方法(search.py)展示了三种模式的实际差异:basic模式仅开启use_semantic_search=True,advanced模式则同时开启语义与全文并默认采用hyde策略,custom模式返回空配置(所有字段使用默认值)。
模式与设置如何合并:路由层的真实逻辑
在 py/core/main/api/v3/retrieval_router.py 的_prepare_search_settings中可以看到模式与覆盖参数的合并逻辑:
- 若
search_mode != custom,先从SearchSettings.get_default(mode.value)取模式默认配置; - 若用户同时提供了
search_settings,则调用merge_search_settings将用户设置逐字段覆盖到模式默认值上(exclude_unset=True保证只有显式设置的字段才参与覆盖); custom模式则直接使用传入的search_settings,否则使用默认的SearchSettings();- 最后调用
select_search_filters(auth_user, effective_settings)为当前用户注入权限相关的过滤条件——非超级用户会被自动追加owner_id == 当前用户或collection_ids与用户可见集合重叠的$or约束(见 search.py)。
这意味着:过滤与权限在路由层自动叠加,即使调用方未显式传filters,非超级用户也只会检索到属于自己的文档或所属集合内的文档。
纯检索:/retrieval/search
/retrieval/search返回原始检索结果,不经过 LLM 生成。它适合需要直接消费检索证据、做二次重排或构建自定义管线的场景。
基本搜索示例
# Uses default settings (likely semantic search in 'custom' mode) results = client.retrieval.search( query="What is DeepSeek R1?", ) # Explicitly using 'basic' mode results_basic = client.retrieval.search( query="What is DeepSeek R1?", search_mode="basic", )// Uses default settings const results = await client.retrieval.search({ query: "What is DeepSeek R1?", }); // Explicitly using 'basic' mode const resultsBasic = await client.retrieval.search({ query: "What is DeepSeek R1?", searchMode: "basic", });# Uses default settings curl -X POST "https://api.sciphi.ai/v3/retrieval/search" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_API_KEY" \ -d '{ "query": "What is DeepSeek R1?" }' # Explicitly using 'basic' mode curl -X POST "https://api.sciphi.ai/v3/retrieval/search" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_API_KEY" \ -d '{ "query": "What is DeepSeek R1?", "search_mode": "basic" }'在路由层(retrieval_router.py),search_app会校验query非空(空查询直接返回 400),随后调用services.retrieval.search(query, effective_settings)并返回WrappedSearchResponse。Python SDK 与 JS SDK 的对应方法分别位于 py/sdk/asnyc_methods/retrieval.py 与 js/sdk/src/v3/clients/retrieval.ts。
响应结构(WrappedSearchResponse)
Search 端点返回WrappedSearchResponse,其中包含AggregateSearchResult对象,主要字段如下:
results.chunk_search_results:相关文本块ChunkSearchResult列表(包含id、document_id、text、score、metadata);results.graph_search_results:相关GraphSearchResult列表(实体、关系、社区),在图检索激活且有结果时出现;results.web_search_results:WebSearchResult列表(若网络搜索被启用;通常网络搜索经由 RAG/Agent 路径完成)。
// Simplified Example Structure { "results": { "chunk_search_results": [ { "score": 0.643, "text": "Document Title: DeepSeek_R1.pdf...", "id": "chunk-uuid-...", "document_id": "doc-uuid-...", "metadata": { ... } }, // ... more chunks ], "graph_search_results": [ // Example: An entity result if graph search ran { "id": "graph-entity-uuid...", "content": { "name": "DeepSeek-R1", "description": "A large language model...", "id": "entity-uuid..." }, "result_type": "ENTITY", "score": 0.95, "metadata": { ... } } // ... potentially relationships or communities ], "web_search_results": [] } }对照 py/shared/abstractions/search.py,ChunkSearchResult的实际字段为id、document_id、owner_id、collection_ids、score、text、metadata;GraphSearchResult(search.py)则通过content字段承载GraphEntityResult/GraphRelationshipResult/GraphCommunityResult三种类型之一,并以result_type区分(entity/relationship/community)。
混合搜索示例
将基于关键词的全文检索与向量检索结合,可以获得更广的召回。
hybrid_results = client.retrieval.search( query="What was Uber's profit in 2020?", search_settings={ "use_hybrid_search": True, "hybrid_settings": { "full_text_weight": 1.0, "semantic_weight": 5.0, "full_text_limit": 200, # How many full-text results to initially consider "rrf_k": 50, # Parameter for Reciprocal Rank Fusion }, "filters": {"metadata.title": {"$in": ["uber_2021.pdf"]}}, # Filter by metadata field "limit": 10 # Final number of results after fusion/ranking }, )const hybridResults = await client.retrieval.search({ query: "What was Uber's profit in 2020?", searchSettings: { useHybridSearch: true, hybridSettings: { fullTextWeight: 1.0, semanticWeight: 5.0, fullTextLimit: 200, rrfK: 50 // Assuming camelCase mapping in JS SDK }, filters: {"metadata.title": {"$in": ["uber_2021.pdf"]}}, limit: 10 }, });curl -X POST "https://api.sciphi.ai/v3/retrieval/search" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_API_KEY" \ -d '{ "query": "What was Uber'\''s profit in 2020?", "search_settings": { "use_hybrid_search": true, "hybrid_settings": { "full_text_weight": 1.0, "semantic_weight": 5.0, "full_text_limit": 200, "rrf_k": 50 }, "filters": {"metadata.title": {"$in": ["uber_2021.pdf"]}}, "limit": 10, "chunk_settings": { "index_measure": "l2_distance" } } }'HybridSearchSettings在 search.py 中定义了四个字段:full_text_weight(默认1.0)、semantic_weight(默认5.0)、full_text_limit(默认200)与rrf_k(默认50)。其中rrf_k是 Reciprocal Rank Fusion(倒数排名融合)的平滑常数k,用于合并两路检索排名;从服务层实现可以看到,RAG-Fusion 策略的融合逻辑_reciprocal_rank_fusion_chunks(py/core/main/services/retrieval_service.py)使用的 RRF 分数公式为1 / (k + rank),默认k=60。
在服务层_vector_search_logic(retrieval_service.py)中,混合检索的条件是use_fulltext_search && use_semantic_search或use_hybrid_search为真,此时调用chunks_handler.hybrid_search(query_vector, query_text, search_settings);随后所有检索结果都会经过completion_embedding.arerank(query, results, limit)做一次基于原查询语义的重排,并为每条结果写入associated_query元数据、在存在标题时拼接Document Title: ...前缀——这也解释了示例响应中text字段为何带有文档标题。
高级过滤
基于文档属性或元数据缩小检索范围。支持的运算符包括$eq、$neq、$gt、$gte、$lt、$lte、$like、$ilike、$in、$nin,并可通过$and与$or组合多个条件。
filtered_results = client.retrieval.search( query="What are the effects of climate change?", search_settings={ "filters": { "$and":[ {"document_type": {"$eq": "pdf"}}, # Assuming 'document_type' is stored {"metadata.year": {"$gt": 2020}} # Access nested metadata fields ] }, "limit": 10 } )const filteredResults = await client.retrieval.search({ query: "What are the effects of climate change?", searchSettings: { filters: { $and: [ {document_type: {$eq: "pdf"}}, {"metadata.year": {$gt: 2020}} ] }, limit: 10 } });从 py/core/providers/database/filters.py 可以看到,FilterOperator定义了完整的运算符集合:除上述列出的比较/匹配运算符外,还包含$overlap(检查数组是否有共同元素,底层映射为 PostgreSQL 的&&)、$contains、$not_contains、$array_contains、$length等,并支持$and/$or组合。值得注意的两点:
$like/$ilike要求字段值为字符串($ilike大小写不敏感);- 当
collection_ids使用$eq时,查询会被自动映射为$overlap(见 filters.py),方便用集合 ID 直接圈定检索范围。
向量搜索的距离度量
通过chunk_settings.index_measure参数可配置向量检索的距离度量。选择合适的度量会显著影响检索质量,具体取决于嵌入模型与使用场景:
cosine_distance(默认):度量向量间的夹角余弦,忽略向量长度。最适合比较不同长度的文档。l2_distance(欧氏距离):度量向量间的直线距离。当方向与长度都重要时适用。max_inner_product:针对寻找方向相似向量的场景优化。适合推荐系统。l1_distance(曼哈顿距离):度量各维度绝对差之和。对离群值不如 L2 敏感。hamming_distance:统计向量各位置不同的数量。最适合二值嵌入。jaccard_distance:度量样本集合间的不相似度。适用于稀疏嵌入。
results = client.retrieval.search( query="What are the key features of quantum computing?", search_settings={ "chunk_settings": { "index_measure": "l2_distance" # Use Euclidean distance instead of default } } )对于大多数文本嵌入模型(如 OpenAI 的模型),推荐使用cosine_distance。对于特殊嵌入或特定场景,可以实验不同度量以找到数据的最优配置。IndexMeasure枚举定义在 py/shared/abstractions/vector.py,后端(如 pgvector)通过算子映射(<=>对应 cosine、<#>对应 max_inner_product 等,见同文件 L60-L72)执行对应索引扫描;ChunkSearchSettings(search.py)中还提供了probes(默认10,ivfflat 索引查询的列表数量)与ef_search(默认40,HNSW 索引的动态候选列表大小),两者调高可提升准确率但降低速度。
知识图谱增强检索
除文本块检索外,R2R 还可以利用知识图谱丰富检索过程,带来以下收益:
- 上下文理解:知识图谱以实体(如人物、组织、概念)与关系(如"就职于""相关于""是……的一种")存储信息。在图谱中检索可以发现纯文本检索容易遗漏的关联与上下文。
- 基于关系的查询:回答依赖连接关系的问题,例如"人物 X 参与了哪些项目?"或"概念 A 与概念 B 之间有何关联?"。
- 结构发现:图检索可以揭示更高层的结构,例如数据中相关实体的社区,或关键连接性概念。
- 结果互补:图结果(实体、关系、社区摘要)通过提供结构化信息与更广上下文,与文本块形成互补。
当知识图谱搜索在 R2R 中激活时,Search 或 RAG 端点返回的AggregateSearchResult会在graph_search_results列表中携带相关项,从而为理解或生成提供更丰富的上下文。
在服务层_graph_search_logic(retrieval_service.py)中,图检索默认通过graph_settings.enabled(默认true)开启,依次执行实体(entities)、关系(relationships)、社区(communities)三类搜索,分别受graph_settings.limits中的entities/relationships/communities键控制(未设置时回退到search_settings.limit),并且同样支持include_scores与include_metadatas开关。因此,即使只调用 Search 端点,只要数据集中构建了知识图谱,返回结果就可能同时包含文本块与图实体/关系/社区。
检索增强生成:/retrieval/rag
R2R 的 RAG 引擎将上文所述的检索能力(文本、向量、混合,以及可选的图谱结果)与 LLM 结合,生成以你摄入文档(以及可选的网络搜索结果)为事实依据、上下文相关的回答。
RAG 生成配置(rag_generation_config)
控制 LLM 生成过程的主要参数:
model:指定使用的 LLM,例如"openai/gpt-4o-mini"、"anthropic/claude-3-haiku-20240307"。默认值在 R2R 配置中设定。stream:布尔值(默认false)。设为true时启用流式响应。temperature、max_tokens、top_p等:标准 LLM 生成参数。
GenerationConfig的完整字段定义在 py/shared/abstractions/llm.py,除上述参数外还包括max_tokens_to_sample(默认1024,兼容max_tokens写法并自动映射)、top_p(默认1.0)、functions/tools、api_base、response_format(支持传入 Pydantic 模型以 JSON Schema 方式结构化输出)以及 Anthropic 的extended_thinking/thinking_budget与 OpenAI 的reasoning_effort。在 retrieval_router.py 中,若请求未显式指定model,路由会自动回退到config.app.quality_llm指定的质量模型。
基本 RAG
使用与 Search 端点相同的search_mode与search_settings检索相关信息,再生成回答。
# Basic RAG call using default search and generation settings rag_response = client.retrieval.rag(query="What is DeepSeek R1?")// Basic RAG call using default settings const ragResponse = await client.retrieval.rag({ query: "What is DeepSeek R1?" });curl -X POST "https://api.sciphi.ai/v3/retrieval/rag" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_API_KEY" \ -d '{ "query": "What is DeepSeek R1?" }'RAG 端点还额外支持task_prompt(自定义任务提示词覆盖默认值)与include_title_if_available(在可用时把文档标题加入 LLM 上下文,默认false)。
响应结构(WrappedRAGResponse)
非流式 RAG 端点返回WrappedRAGResponse,其中RAGResponse对象包含以下字段:
results.generated_answer:LLM 合成的最终回答。results.search_results:用于生成回答的AggregateSearchResult(包含文本块,可能还有图结果与网络结果)。results.citations:Citation对象列表,将回答的各个部分链接到search_results中的具体来源(ChunkSearchResult、GraphSearchResult、WebSearchResult等)。每条引用包含id(文本中使用的短标识符,如[1])与包含来源对象的payload。results.metadata:关于本次生成调用的 LLM 提供商元数据。
// Simplified Example Structure { "results": { "generated_answer": "DeepSeek-R1 is a model that... [1]. It excels in tasks... [2].", "search_results": { "chunk_search_results": [ { "id": "chunk-abc...", "text": "...", "score": 0.8 }, /* ... */ ], "graph_search_results": [ { /* Graph Entity/Relationship */ } ], "web_search_results": [ { "url": "...", "title": "...", "snippet": "..." }, /* ... */ ] }, "citations": [ { "id": "cit.1", // Corresponds to [1] in text "object": "citation", "payload": { /* ChunkSearchResult for chunk-abc... */ } }, { "id": "cit.2", // Corresponds to [2] in text "object": "citation", "payload": { /* WebSearchResult for relevant web page */ } } // ... more citations potentially linking to graph results too ], "metadata": { "model": "openai/gpt-4o-mini", ... } } }非流式 RAG 的完整执行链路在 retrieval_service.py:先执行聚合检索得到aggregated_results,用format_search_results_for_llm构建上下文,从 prompts 库加载system与rag提示词模板并注入query与context,再调用 LLM;回答文本中的短 ID 引用通过extract_citations提取,并借助SearchResultsCollector将短 ID 映射回完整来源对象组装成citations。
RAG 集成网络搜索
通过设置include_web_search=True,可以让 RAG 响应补充来自网络的最新信息。
web_rag_response = client.retrieval.rag( query="What are the latest developments with DeepSeek R1?", include_web_search=True )const webRagResponse = await client.retrieval.rag({ query: "What are the latest developments with DeepSeek R1?", includeWebSearch: true // Use camelCase for JS SDK });curl -X POST "https://api.sciphi.ai/v3/retrieval/rag" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_API_KEY" \ -d '{ "query": "What are the latest developments with DeepSeek R1?", "include_web_search": true }'启用后,R2R 会基于查询执行一次网络搜索(服务层_perform_web_search,见 retrieval_service.py),并将结果合并进AggregateSearchResult.web_search_results,随文档/图谱结果一并提供给 LLM。注意此功能依赖服务端配置的网络搜索提供商(仓库中可看到 py/core/utils/serper.py 与tavily.toml配置示例,以及 py/core/base/agent/tools/built_in/tavily_search.py 等工具)。
RAG 结合混合搜索
通过配置search_settings将混合检索与 RAG 结合。
hybrid_rag_response = client.retrieval.rag( query="Who is Jon Snow?", search_settings={"use_hybrid_search": True} )const hybridRagResponse = await client.retrieval.rag({ query: "Who is Jon Snow?", searchSettings: { useHybridSearch: true }, });# Correctly place use_hybrid_search in search_settings curl -X POST "https://api.sciphi.ai/v3/retrieval/rag" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_API_KEY" \ -d '{ "query": "Who is Jon Snow?", "search_settings": { "use_hybrid_search": true, "limit": 10 } }'流式 RAG(SSE)
在rag_generation_config中设置stream: True,即可将 RAG 响应以 Server-Sent Events(SSE)流的形式接收,非常适合实时应用。
事件类型:
search_results:包含初始AggregateSearchResult(开始时发送一次)。data:完整的AggregateSearchResult对象(文本块,可能有图结果、网络结果)。
message:随生成过程流式推送部分 token。data.delta.content:正在流式传输的文本片段。
citation:当某个引用来源被识别时触发。每个唯一来源在首次被引用时发送一次。data.id:短引用 ID(如"cit.1")。data.payload:完整来源对象(ChunkSearchResult、GraphSearchResult、WebSearchResult等)。data.is_new:若该引用 ID 首次发送则为True。data.span:当前累计文本中引用标记(如[1])出现的起始/结束字符索引。
final_answer:结束时发送一次,包含完整生成回答与结构化引用。data.generated_answer:完整最终文本。data.citations:全部引用列表,包含id、payload以及它们在最终文本中出现的所有spans。
from r2r import ( CitationEvent, FinalAnswerEvent, MessageEvent, SearchResultsEvent, R2RClient, ) # Set stream=True in rag_generation_config result_stream = client.retrieval.rag( query="What is DeepSeek R1?", search_settings={"limit": 25}, rag_generation_config={"stream": True, "model": "openai/gpt-4o-mini"}, include_web_search=True, ) for event in result_stream: if isinstance(event, SearchResultsEvent): print(f"Search results received (Chunks: {len(event.data.data.chunk_search_results)}, Graph: {len(event.data.data.graph_search_results)}, Web: {len(event.data.data.web_search_results)})") elif isinstance(event, MessageEvent): # Access the actual text delta if event.data.delta and event.data.delta.content and event.data.delta.content[0].type == 'text' and event.data.delta.content[0].payload.value: print(event.data.delta.content[0].payload.value, end="", flush=True) elif isinstance(event, CitationEvent): # Payload is only sent when is_new is True if event.data.is_new: print(f"\n<<< New Citation Source Detected: ID={event.data.id} >>>") elif isinstance(event, FinalAnswerEvent): print("\n\n--- Final Answer ---") print(event.data.generated_answer) print("\n--- Citations Summary ---") for cit in event.data.citations: print(f" ID: {cit.id}, Spans: {cit.span}")// Set stream: true in ragGenerationConfig const resultStream = await client.retrieval.rag({ query: "What is DeepSeek R1?", searchSettings: { limit: 25 }, ragGenerationConfig: { stream: true, model: "openai/gpt-4o-mini" }, includeWebSearch: true, }); // Check if we got an async iterator (streaming) if (Symbol.asyncIterator in resultStream) { console.log("Starting stream processing..."); // Loop over each event from the server for await (const event of resultStream) { switch (event.event) { case "search_results": console.log(`\nSearch results received (Chunks: ${event.data.chunk_search_results?.length || 0}, Graph: ${event.data.graph_search_results?.length || 0}, Web: ${event.data.web_search_results?.length || 0})`); break; case "message": // Access the actual text delta if (event.data?.delta?.content?.[0]?.text?.value) { process.stdout.write(event.data.delta.content[0].text.value); } break; case "citation": // Payload only sent when is_new is true if (event.data?.is_new) { process.stdout.write(`\n<<< New Citation Source Detected: ID=${event.data.id} >>>`); } else { // Citation already seen, no need to log payload again } break; case "final_answer": process.stdout.write("\n\n--- Final Answer ---\n"); console.log(event.data.generated_answer); console.log("\n--- Citations Summary ---"); event.data.citations?.forEach(cit => { console.log(` ID: ${cit.id}, Spans: ${JSON.stringify(cit.spans)}`); }); break; default: console.log("\nUnknown or unhandled event:", event.event); } } console.log("\nStream finished."); } else { // Handle non-streaming response if necessary (though we requested stream) console.log("Received non-streaming response:", resultStream); }流式链路的服务端实现在 retrieval_service.py:先通过SSEFormatter.yield_search_results_event发送检索结果事件;随后逐 chunk 消费 LLM 流,对每个文本增量先发送message事件,再用find_new_citation_spans在累计文本中查找新出现的引用短 ID,并通过CitationTracker判定是否为首次出现——首次出现时携带完整payload,后续仅携带id与span;收到finish_reason == "stop"后,发送包含全部引用(含所有出现位置spans)的final_answer事件,最后发送结束信号。路由层(retrieval_router.py)将生成器包装为text/event-stream的StreamingResponse。
自定义 RAG
除search_settings外,可以通过rag_generation_config自定义 RAG 生成过程。
使用 Anthropic 模型并开启网络搜索的示例:
# Requires ANTHROPIC_API_KEY env var if using Anthropic models response = client.retrieval.rag( query="Who was Aristotle and what are his recent influences?", rag_generation_config={ "model":"anthropic/claude-3-haiku-20240307", "stream": False, # Get a single response object "temperature": 0.5 }, include_web_search=True ) print(response.results.generated_answer)// Requires ANTHROPIC_API_KEY env var if using Anthropic models const response = await client.retrieval.rag({ query: "Who was Aristotle and what are his recent influences?", ragGenerationConfig: { model: 'anthropic/claude-3-haiku-20240307', temperature: 0.5, stream: false // Get a single response object }, includeWebSearch: true }); console.log(response.results.generated_answer);# Requires ANTHROPIC_API_KEY env var if using Anthropic models curl -X POST "https://api.sciphi.ai/v3/retrieval/rag" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_API_KEY" \ -d '{ "query": "Who was Aristotle and what are his recent influences?", "rag_generation_config": { "model": "anthropic/claude-3-haiku-20240307", "temperature": 0.5, "stream": false }, "include_web_search": true }'检索策略的分发与实现原理
/retrieval/search与/retrieval/rag共用同一套检索内核:RetrievalService.search(retrieval_service.py)根据search_settings.search_strategy将请求分发到三条路径:
vanilla(默认):_basic_search——对查询做嵌入,执行向量/全文/混合检索,随后做图检索,最后合并为AggregateSearchResult;hyde:_hyde_search——先用 LLM 基于查询生成num_sub_queries个假设文档(使用的提示词模板见 py/core/providers/database/prompts/hyde.yaml,要求生成"互相独立、避免跨文档信息"的候选回答),再对每个假设文档并行做块检索与图检索,最后用原始查询对所有结果做语义重排;rag_fusion:_rag_fusion_search——先用 LLM 生成num_sub_queries - 1个改写查询(连同原查询组成查询集),对每个查询分别做块/图检索,再用 Reciprocal Rank Fusion 对多路排名做融合,最后同样经过一次语义重排。
也就是说,search_strategy不仅作用于 RAG 端点,对纯/retrieval/search同样生效。关于 HyDE 与 RAG-Fusion 的详细原理、流程图与组合用法,可继续阅读 高级 RAG 指南。
测试与验证
仓库在 py/tests/integration/test_retrieval.py 中提供了覆盖检索与 RAG 主路径的集成测试(如use_semantic_search、limit、混合检索、过滤等各类search_settings组合),JS SDK 侧则在 js/sdk/tests/RetrievalIntegrationSuperUser.test.ts 中验证了client.retrieval.search/client.retrieval.rag的端到端行为。结合 docs/cookbooks/rag.md、docs/cookbooks/hybrid-search.md 与 docs/cookbooks/advanced-rag.md 的烹饪手册,可以在本地把检索链路跑通后再逐步叠加混合检索、过滤、图检索与流式 RAG。
小结
R2R 的检索与 RAG 能力为"找到信息并对其进行上下文化"提供了高度灵活的机制:从一行代码的语义搜索,到带权重与 RRF 融合的混合检索,再到叠加元数据过滤、知识图谱增强与网络搜索的完整 RAG 管线,均可通过search_mode、search_settings与rag_generation_config在运行时按需组合。无论你需要简单语义搜索、面向更广召回的混合检索,还是融合文档块、图谱洞察与网络结果(流式或单次响应)的可定制 RAG 生成,这套系统都能通过配置满足具体需求。
【免费下载链接】R2RSoTA production-ready AI retrieval system. Agentic Retrieval-Augmented Generation (RAG) with a RESTful API.项目地址: https://gitcode.com/GitHub_Trending/r2/R2R
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考