超越语义相似度:构建支持智能体交互式搜索的混合检索系统
2026/8/23 4:32:16 网站建设 项目流程

1. 项目概述:重新定义智能搜索的“寻回”机制

最近在折腾一个智能体(Agent)项目时,我被一个老问题卡住了:传统的基于语义相似度的检索,在应对复杂、多步骤的Agentic Search(智能体搜索)任务时,总感觉差那么点意思。比如,我想让智能体帮我规划一个技术方案,它需要从海量文档(Corpus)里找到相关的技术规范、过往案例和潜在风险点。单纯靠向量相似度匹配,返回的往往是一堆“听起来像”但“用不上”的片段,智能体还得花大力气去拼凑、推理,效率低下不说,还容易跑偏。

这让我开始重新思考“检索”(Retrieval)这件事。我们是不是太过于依赖“语义相似度”这根独木桥了?尤其是在智能体驱动的搜索场景下,检索的核心目标可能不再是“找到最像的”,而是“找到最能直接支持下一步行动或决策的”。这就是“Beyond Semantic Similarity”(超越语义相似度)想探讨的核心。我们需要的可能是一种更直接、更灵活、能与语料库(Corpus)进行深度“交互”(Direct Corpus Interaction)的检索范式。它允许智能体像侦探一样,在语料库中主动探查、关联、验证,而不仅仅是被动接收一个排序列表。

这个思路,恰好也回应了最近技术社区里的一些热议。比如,在配置数据库连接时常见的“public key retrieval is not allowed”错误,其本质就是一个严格的、基于规则的身份验证检索失败案例——系统不是在找“相似”的密钥,而是在执行一个明确的检索指令。又或者“retrieval of ‘allegro_studio’ license failed”,这同样是一个目标明确的许可验证检索。这些虽然是小场景,但它们揭示了一个共同点:确定性检索。在智能体搜索中,我们同样需要混合确定性的规则检索与灵活的语义检索,让智能体知道“什么时候该精确查找,什么时候可以模糊关联”。

本文将从一个实践者的角度,拆解如何为Agentic Search构建一个“超越语义相似度”的检索系统。我们会深入直接语料交互的设计思路、核心组件(如混合检索策略、交互式查询构建)的实现,以及如何将Embedding Model和Vector Index从“主角”变为“协同工具”。如果你也在构建需要深度理解、多轮交互的智能应用,比如自动化的研究报告生成、复杂的客户支持排障,或者像我一样在搞能自主规划的技术方案助手,那么这篇从踩坑到填坑的经验总结,或许能给你带来一些新的启发。

2. 核心设计思路:从静态匹配到动态对话

传统的检索-Augmented Generation(RAG)流程,可以简化为“查询→向量化→相似度搜索→返回Top-K文档→生成答案”。这个流程是静态的、单向的。智能体提交一个查询,系统返回一堆文档,任务就结束了。但在Agentic Search中,智能体本身是有状态、有目标的。它的搜索行为往往是多轮的、试探性的,并且严重依赖于上下文。

2.1 为何语义相似度在智能体场景中“力不从心”

首先,我们必须肯定语义相似度检索的价值。基于Embedding Model(如OpenAI的text-embedding-ada-002,或开源的BGE、M3E等)和Vector Index(如Pinecone、Weaviate、Milvus、Pgvector)的方案,在处理事实性问答、简单文档查找时非常高效。它能突破关键词匹配的局限,理解用户意图。

然而,在智能体场景下,它的短板变得明显:

  1. 缺乏精确匹配能力:智能体可能需要查找一个具体的错误代码(如“ERROR 1045”)、一个确切的API端点(GET /api/v1/users/{id})或一个版本号(“React 18.2.0”)。语义搜索可能会返回一堆关于错误处理、API设计或React介绍的文章,但偏偏找不到那个精确的字符串。这就是“public key retrieval is not allowed”这类错误给我们的启示——有些检索必须是精确的。
  2. 无法理解复杂意图与多跳推理:智能体的查询可能是“基于我们上周的会议纪要和当前服务器日志,找出导致服务降级的根本原因”。这是一个需要多跳推理的任务。单纯的语义搜索可能分别找到会议纪要和日志中“相似”的句子,但无法自动建立两者之间的因果或时序关联。智能体需要自己充当这个“关联引擎”。
  3. 对元数据和结构化信息利用不足:语料库中的文档通常带有元数据(作者、日期、类型、标签)和结构(章节、代码块、表格)。纯向量搜索将这些信息扁平化为文本,损失了大量可用于筛选和路由的宝贵信号。例如,智能体可能只想搜索“最近三个月内发布的、标记为‘高优先级’的技术公告”。
  4. 检索过程不透明、不可控:智能体收到一堆文档后,它很难理解“为什么是这些文档被选中”。当结果不理想时,它缺乏调整检索策略的“杠杆”。整个过程像一个黑盒。

2.2 直接语料交互(Direct Corpus Interaction)的核心思想

“直接语料交互”不是一个具体的工具,而是一种设计范式。它的核心思想是将检索系统从一个被动的“文档提供者”,转变为一个智能体可以主动“查询”和“探索”的“知识环境”

在这个范式下:

  • 检索是对话式的:智能体可以发起多轮检索,每一轮都基于上一轮的结果调整策略。例如,先宽泛搜索,再根据返回文档的元数据进行聚焦过滤。
  • 查询是结构化的:查询不再只是一个自然语言字符串,而是一个可以包含精确匹配字段、过滤器、排序规则和语义搜索条件的复杂请求对象。
  • 语料库是“可编程”的:智能体可以通过检索系统,调用语料库背后更原始的能力,比如全文索引、关系查询、图遍历等,而不仅仅是向量比较。
  • 结果是多模态的:返回的不只是文档片段,可能还包括聚合统计信息(“共有多少篇相关文档”)、元数据分布(“相关文档主要来自哪个部门”)、或潜在的探索路径建议(“你是否也想查看与‘X’主题相关的架构图?”)。

注意:这并不意味着抛弃向量搜索。恰恰相反,它是将向量搜索作为工具箱中的一件强大工具,与其他工具(关键词搜索、过滤器、图查询)协同工作。关键在于让智能体学会“因任务选工具”。

2.3 一个实践框架:混合检索与查询规划

基于上述思想,一个可行的实践框架包含两个关键层:

  1. 混合检索层(Hybrid Retrieval Layer)

    • 向量检索(Vector Search):负责捕捉语义相似性和潜在关联。使用Embedding Model将查询和文档片段转换为向量,通过Vector Index进行近似最近邻搜索。
    • 关键词/全文检索(Keyword/Full-Text Search):负责精确匹配、术语查找和利用倒排索引的高效性。可以使用Elasticsearch、Meilisearch或数据库内置的全文搜索功能。
    • 元数据过滤(Metadata Filtering):在所有检索路径之上或之中,应用基于日期、来源、标签、类型等的硬性过滤器。
    • 融合排序(Fusion Ranking):将来自不同检索路径的结果进行去重、打分和重排。常用方法有加权分数融合(Weighted Score Fusion)、倒数排名融合(Reciprocal Rank Fusion, RRF)等。RRF因其简单有效在实践中很受欢迎,它不依赖绝对分数,而是基于各个列表中结果的排名。
  2. 查询规划层(Query Planning Layer)

    • 这是智能体与检索系统交互的“大脑”。它接收智能体的自然语言请求或结构化指令,并将其“编译”成一系列针对混合检索层的子查询。
    • 查询理解:解析用户意图,识别其中的精确实体(产品名、错误码、版本号)、过滤条件(时间、类型)和模糊语义概念。
    • 策略选择:决定查询策略。例如:
      • 如果查询中包含明确的代码片段或错误号,优先使用关键词检索。
      • 如果查询是开放式的概念探讨,优先使用向量检索。
      • 如果是复合型查询,则拆解为多个子查询,分别执行后再融合。
    • 交互管理:维护多轮检索的上下文。例如,第一轮用宽泛语义搜索找到大致方向,第二轮利用第一轮结果中高频出现的元数据标签进行过滤,实现聚焦。

3. 系统架构与核心组件实现

理论说完了,我们来点实际的。下面我将以一个“技术方案智能研究助手”为例,展示如何搭建一个支持直接语料交互的检索系统。我们的语料库包含技术博客、API文档、会议纪要、故障报告等多种格式的文档。

3.1 数据预处理与索引构建

良好的检索始于良好的数据准备。这一步的目标是为混合检索准备好多种“索引视图”。

步骤1:文档提取与分块

  • 使用UnstructuredPyPDF2markdownify等库处理不同格式的文档,提取纯文本和元数据(来源、创建时间、作者、预估类型)。
  • 分块策略是关键。不要只用固定大小的滑动窗口。对于技术文档,我采用混合分块:
    • 语义分块:使用LangChainRecursiveCharacterTextSplitter,根据段落、标题进行分割,尽量保持语义完整性。块大小可设为800-1000字符,重叠150字符。
    • 结构分块:对于API文档,按接口端点分块;对于错误文档,按错误代码分块。这为后续的精确检索奠定了基础。
    • 为每个块继承或生成丰富的元数据,如doc_idchunk_indexparent_titlecontent_typetext/code/table)、keywords(从内容中提取的少量关键术语)。

步骤2:构建多路索引

  • 向量索引(Vector Index)
    • 选择Embedding模型:对于中英文混合语料,我测试后选择了BGE-M3,它支持多语言、长文本,且开源可私有部署。使用其embedding模式为每个文本块生成向量。
    • 选择向量数据库:考虑到需要和元数据过滤紧密集成,我选择了支持丰富过滤条件的Weaviate(或QdrantMilvus)。将向量和元数据一并存入。
  • 全文索引(Full-Text Index)
    • 我使用Elasticsearch。将相同的文本块和元数据存入另一个索引。这里特别为content字段配置了适合技术文本的分析器(如移除代码中的符号干扰,增强术语识别)。
    • 同时,将提取的keywords和从标题、章节名中得到的实体,单独存入一个exact_terms字段,使用keyword类型,用于精确匹配。
  • 关系辅助存储
    • 使用一个简单的SQLite或PostgreSQL表,存储文档和块之间的层级关系(document->chunks),以及块与块之间的潜在链接(如“另请参阅”)。这为后续的图遍历式探索预留了接口。

实操心得:分块时一定要保留层级信息(如H1、H2标题)。在元数据中加入section_path(如"安装/配置/参数详解"),能让检索结果在UI上呈现更好的上下文,也便于智能体理解文档结构。

3.2 混合检索器的实现

我们实现一个HybridRetriever类,它封装了与不同索引的交互逻辑。

import asyncio from typing import List, Dict, Any, Optional from rank_bm25 import BM25Okapi # 假设我们有访问各索引的客户端 from vector_client import VectorClient # 连接 Weaviate/Qdrant from search_client import SearchClient # 连接 Elasticsearch class HybridRetriever: def __init__(self, vector_client, search_client, fusion_method='rrf'): self.vector_client = vector_client self.search_client = search_client self.fusion_method = fusion_method async def retrieve(self, query: str, filters: Optional[Dict] = None, top_k: int = 10) -> List[Dict]: """ 执行混合检索。 Args: query: 自然语言查询字符串。 filters: 元数据过滤字典,如 {'content_type': 'code', 'date': {'gte': '2023-01-01'}}。 top_k: 期望返回的总结果数。 Returns: 融合并排序后的结果列表。 """ # 1. 并行执行向量检索和全文检索 vector_task = self._vector_search(query, filters, top_k * 2) # 多取一些用于融合 keyword_task = self._keyword_search(query, filters, top_k * 2) vector_results, keyword_results = await asyncio.gather(vector_task, keyword_task) # 2. 结果融合 if self.fusion_method == 'rrf': fused_results = self._rrf_fusion([vector_results, keyword_results], top_k) elif self.fusion_method == 'weighted': # 需要各检索器返回归一化分数 fused_results = self._weighted_fusion([vector_results, keyword_results], weights=[0.6, 0.4], top_k=top_k) else: # 默认简单合并去重 fused_results = self._simple_merge(vector_results, keyword_results, top_k) return fused_results async def _vector_search(self, query: str, filters: Optional[Dict], k: int) -> List[Dict]: """调用向量数据库进行语义搜索""" query_vector = await self.vector_client.embed_query(query) results = await self.vector_client.search( vector=query_vector, filters=self._translate_filters(filters), limit=k, with_metadata=True ) # 格式化结果:{'id': ..., 'content': ..., 'metadata': {...}, 'score': ..., 'retriever': 'vector'} return [self._format_result(r, 'vector') for r in results] async def _keyword_search(self, query: str, filters: Optional[Dict], k: int) -> List[Dict]: """调用全文搜索引擎进行关键词搜索""" # 可以在这里加入简单的查询理解,分离出精确术语 exact_terms = self._extract_exact_terms(query) # 一个简单的启发式函数 search_body = { "query": { "bool": { "must": [ {"match": {"content": {"query": query, "boost": 1}}}, ], "should": [ {"term": {"exact_terms": {"value": term, "boost": 5}}} for term in exact_terms ] if exact_terms else [], "filter": self._build_es_filters(filters) } }, "size": k } results = await self.search_client.search(body=search_body) return [self._format_result(r, 'keyword') for r in results['hits']['hits']] def _rrf_fusion(self, results_lists: List[List[Dict]], top_k: int) -> List[Dict]: """倒数排名融合 (Reciprocal Rank Fusion)""" fused_scores = {} k = 60 # RRF常数,通常设为60 for results in results_lists: for rank, item in enumerate(results, start=1): doc_id = item['id'] if doc_id not in fused_scores: fused_scores[doc_id] = {'score': 0.0, 'data': item} fused_scores[doc_id]['score'] += 1.0 / (k + rank) # 按融合分数排序 sorted_items = sorted(fused_scores.values(), key=lambda x: x['score'], reverse=True) return [item['data'] for item in sorted_items[:top_k]] # ... 其他辅助方法 (_format_result, _translate_filters, _extract_exact_terms, _build_es_filters)

这个HybridRetriever提供了基础的混合检索能力。但真正的“直接交互”能力,需要更上层的智能来驱动。

3.3 智能查询规划器的设计

查询规划器是智能体与检索系统之间的翻译官和策略师。它可以是一个基于规则的引擎,也可以是一个微调的轻量级LLM。

class QueryPlanner: def __init__(self, llm_client, retriever: HybridRetriever): self.llm = llm_client # 用于复杂意图解析 self.retriever = retriever async def plan_and_execute(self, user_query: str, conversation_history: List[Dict] = None) -> Dict: """ 解析用户查询,规划检索策略,执行并返回结果。 """ # 1. 查询分析与策略选择 analysis = await self._analyze_query(user_query, conversation_history) # analysis 示例: {'primary_intent': 'find_exact_code', 'entities': ['ERROR 1045'], 'filters': {'content_type': 'code'}, 'strategy': 'keyword_first'} # 2. 构建检索请求 retrieval_request = self._build_retrieval_request(analysis, user_query) # 3. 执行检索(可能多轮) all_results = [] if analysis['strategy'] == 'hybrid_parallel': # 并行混合检索 results = await self.retriever.retrieve( query=retrieval_request['query'], filters=retrieval_request['filters'], top_k=retrieval_request.get('top_k', 10) ) all_results = results elif analysis['strategy'] == 'exploratory': # 探索式多轮检索 # 第一轮:宽泛语义搜索 broad_results = await self.retriever.retrieve( query=user_query, filters={'date': {'gte': '2022-01-01'}}, # 例如,先看近两年的 top_k=15 ) # 分析第一轮结果的元数据共性 common_tags = self._analyze_metadata(broad_results, field='tags') # 第二轮:基于共性聚焦 if common_tags: focused_results = await self.retriever.retrieve( query=user_query, filters={'tags': {'contains_any': common_tags[:2]}}, # 用最常见的标签过滤 top_k=10 ) all_results = self._merge_results(broad_results, focused_results) else: all_results = broad_results # 4. 后处理与上下文丰富 enriched_results = await self._enrich_results(all_results, user_query, analysis) return { 'query_analysis': analysis, 'retrieved_documents': enriched_results, 'suggested_next_actions': self._suggest_next_actions(enriched_results, analysis) } async def _analyze_query(self, query: str, history: List[Dict]) -> Dict: """使用LLM或规则进行查询意图分析""" # 简单规则示例:检测精确实体 entities = self._rule_based_entity_extraction(query) if entities: return {'primary_intent': 'find_exact', 'entities': entities, 'strategy': 'keyword_first'} # 复杂情况调用LLM prompt = f""" 分析以下用户查询的意图,用于文档检索系统。 查询: {query} 历史上下文: {history[-2:] if history else '无'} 请输出JSON格式,包含字段: - primary_intent: 主要意图,如 'compare', 'find_cause', 'get_definition', 'explore' - strategy: 检索策略建议,如 'hybrid_parallel', 'semantic_first', 'exploratory' - suggested_filters: 建议的元数据过滤器,如 {{'content_type': 'report'}} """ analysis_dict = await self.llm.call_json(prompt) return analysis_dict def _suggest_next_actions(self, results: List[Dict], analysis: Dict) -> List[str]: """基于结果和意图,建议智能体下一步可以做什么""" actions = [] if analysis.get('primary_intent') == 'explore' and len(results) > 5: # 如果是在探索,且结果很多,建议按时间或来源过滤 actions.append("根据结果,你可以尝试过滤‘发布年份’来聚焦时间范围。") if any(r['metadata'].get('has_code', False) for r in results): actions.append("部分文档包含代码片段,是否需要我进一步解析代码中的函数调用?") return actions

这个规划器让检索过程变得“可对话”。智能体不仅可以拿到文档,还能获得关于“如何进一步探索”的建议,实现了初步的直接交互。

4. 在Agentic Search工作流中的集成

现在,我们将这个增强型检索系统集成到一个典型的智能体工作流中。假设我们有一个基于LLM的智能体,其核心循环是:思考(Think)、行动(Act)、观察(Observe)。

4.1 检索作为一个核心工具调用

在智能体的“行动”阶段,检索不再是一个孤立的步骤,而是一个可以被灵活调用的工具。

class ResearchAssistantAgent: def __init__(self, llm, planner: QueryPlanner, corpus_interface): self.llm = llm self.planner = planner self.corpus = corpus_interface # 封装了更丰富语料交互的接口 self.conversation_context = [] async def run(self, initial_task: str): self.conversation_context.append({"role": "user", "content": initial_task}) for step in range(5): # 限制轮次 # 1. 思考:决定下一步做什么 thought = await self._think() if "NEED_TO_SEARCH" in thought: # 2. 行动:规划并执行检索 search_intent = self._extract_search_intent(thought) search_results = await self.planner.plan_and_execute( user_query=search_intent, conversation_history=self.conversation_context ) # 3. 观察:处理检索结果,可能触发新的交互 observation = await self._observe_and_interact(search_results) self.conversation_context.append({"role": "system", "content": f"检索结果: {observation}"}) # 根据结果,智能体可能决定进行一轮“直接交互”,比如深入查看某个文档的关联图 if self._should_drill_down(observation): related_docs = await self.corpus.get_connected_documents(observation['focus_doc_id']) observation += f"\n深入关联发现: {related_docs}" elif "CAN_ANSWER" in thought: answer = await self._generate_answer() return answer else: # 其他工具调用... pass async def _observe_and_interact(self, search_results: Dict) -> str: """处理检索结果,并可能发起新的交互式查询""" docs = search_results['retrieved_documents'] suggestions = search_results['suggested_next_actions'] # 基础观察:总结找到了什么 observation = f"找到了 {len(docs)} 份相关文档。" if docs: top_doc_titles = [d['metadata'].get('title', 'N/A')[:50] for d in docs[:3]] observation += f" 最相关的包括: {', '.join(top_doc_titles)}。" # 如果规划器给出了建议,并且结果集很大或模糊,将其作为交互选项 if suggestions and len(docs) > 8: observation += f" 系统建议: {' '.join(suggestions)} 我可以根据你的选择进行下一步聚焦。" # 这里可以设计一个逻辑,让智能体根据策略自动选择一项建议执行,或向用户确认 # 例如,自动选择第一个建议进行过滤 if "过滤‘发布年份’" in suggestions[0]: # 自动发起一轮新的过滤检索 new_filters = {'year': {'gte': 2023}} refined_results = await self.planner.retriever.retrieve( query=search_results['query_analysis'].get('original_query', ''), filters=new_filters, top_k=10 ) observation += f" 已自动应用近期过滤,现在有 {len(refined_results)} 份文档。" docs = refined_results # 更新当前文档集 # 检查结果中是否有高度精确的匹配(如错误码) exact_matches = [d for d in docs if d.get('retriever') == 'keyword' and d.get('score', 0) > 0.9] if exact_matches: observation += f" 其中发现了精确匹配项,可信度较高。" return observation

在这个工作流中,检索不再是单次事件。智能体可以根据初步结果和系统建议,动态发起新的、更精确的检索请求,形成一个“检索-观察-调整-再检索”的循环,这就是“直接语料交互”的生动体现。

4.2 超越检索:真正的语料交互

更进一步的交互,是允许智能体对语料库提出更复杂的问题,而不仅仅是“给我相似的文档”。这需要我们在corpus_interface层提供更高级的API:

  • get_document_graph(doc_id, depth=2): 获取某个文档在引用关系图或内容关联图中的邻居节点。这能帮助智能体进行“顺藤摸瓜”式的探索。
  • aggregate_by_metadata(field, query_filters): 对符合条件的所有文档,就某个元数据字段进行聚合统计(如“所有关于‘缓存’的文档中,最常见的标签是什么?”)。这能帮助智能体快速了解一个领域的知识结构。
  • compare_documents(doc_id_a, doc_id_b, aspect='technical_detail'): 调用LLM对比两份文档在特定方面的异同,返回结构化摘要。这直接支持了比较型搜索意图。

这些功能将语料库从一个被检索的静态集合,提升为一个可被查询、分析和探索的知识图谱。

5. 性能调优与评估挑战

构建这样一个系统,性能和效果评估是两大挑战。

5.1 性能考量

  1. 延迟:混合检索涉及多个网络调用(向量DB、搜索引擎、LLM)。必须采用异步并行(如asyncio.gather)来缩短总耗时。对于关键路径,要设置超时和降级策略(如LLM分析超时则回退到规则分析)。
  2. 缓存策略:对常见的、计算代价高的操作结果进行缓存。
    • 查询向量缓存:对相同的查询文本,缓存其Embedding向量。
    • 融合结果缓存:对“查询+过滤器”的组合键缓存最终的融合结果列表,有效期可较短。
    • LLM分析缓存:对结构化的查询分析结果进行缓存。
  3. 索引更新:设计增量更新管道,确保新文档能快速进入向量索引和全文索引,并保持两者元数据的一致性。

5.2 效果评估

评估“超越语义相似度”的检索系统比评估传统检索更复杂。准确率(Precision)和召回率(Recall)仍然重要,但不够。

  1. 任务完成度评估:这是最根本的。给定一个智能体任务(如“写一份关于X的故障分析报告”),最终生成报告的质量和完整性,是检索系统好坏的终极指标。可以采用人工评分或使用强大的LLM(如GPT-4)作为裁判,评估报告是否涵盖了关键原因、解决方案和引用来源。
  2. 交互效率评估:衡量智能体需要多少轮“检索-交互”才能完成任务。更少的轮次意味着检索系统提供的上下文和引导更有效。
  3. 检索结果多样性评估:避免返回大量同质化结果。可以使用结果集中不同文档的IDF加权内容向量之间的平均余弦距离来衡量多样性。一个好的系统应该在保证相关性的前提下,提供多视角的信息。
  4. 人工评估关键用例:针对“精确查找”、“多跳推理”、“探索性搜索”等关键场景,构建测试集,进行人工评估,判断系统是否比纯语义搜索更能满足需求。

6. 常见陷阱与实战心得

在实现和迭代这套系统的过程中,我踩过不少坑,也积累了一些不一定在官方文档里能找到的经验。

陷阱一:过度依赖LLM进行查询分析初期,我试图用LLM解析所有用户查询,生成复杂的结构化请求。这带来了两个问题:1) 延迟显著增加;2) LLM有时会“过度解读”或“ hallucinate”出不存在的过滤条件。解决方案是采用分层策略:首先用一套轻量级、快速的规则(正则表达式、关键词列表)处理常见的精确匹配和简单过滤。只有规则无法处理时,才调用LLM。这大大降低了延迟和成本。

陷阱二:融合排序的权重僵化一开始我为向量搜索和关键词搜索设置了固定的融合权重(如0.7和0.3)。但发现对于不同的查询类型,最优权重是不同的。技术概念查询可能向量权重高,而错误码查询则关键词权重要高得多。解决方案是动态权重调整。根据查询分析的结果来微调权重。例如,当检测到“精确实体”时,大幅提高关键词检索的权重;当查询是抽象概念时,则提高向量检索的权重。

实操心得:元数据是黄金花在设计和丰富文档元数据上的时间,回报率极高。除了基本的来源、时间,我们后来增加了:

  • estimated_read_time:基于内容长度估算,用于智能体决策是否深入阅读。
  • content_quality_score:一个简单的启发式分数,基于文档结构完整性、是否有代码示例、拼写错误率等。在融合排序时给予高质量文档轻微加分。
  • entity_links:一个列表,存储本块内容中链接到的其他文档或块的ID。这是实现“图遍历”式交互的基础。 这些元数据成为了智能体与语料库进行丰富交互的“控件”。

关于“public key retrieval is not allowed”的启示这个错误提醒我们,在智能体与外部系统(如数据库)交互时,检索可能失败,且原因非常具体。在我们的检索系统中,我们也应该设计明确的错误处理和信息反馈机制。当一次检索返回结果为空时,不能简单地说“没找到”,而应像这个错误信息一样,尽可能给出可能的原因和方向:“未找到精确匹配‘ERROR 1045’的文档。你是否在寻找‘MySQL访问被拒绝’的通用解决方案?或者尝试搜索‘ERROR 1045 (28000)’这个完整代码?” 这本身就是一种有价值的“交互”。

最后一点体会:构建支持Agentic Search的检索系统,是一个从“以文档为中心”到“以智能体任务为中心”的思维转变。我们不再仅仅优化“查全率”和“查准率”,而是开始思考如何让检索过程本身成为智能体解决问题、构建认知的协作伙伴。这条路还很长,但每一次让智能体更顺畅、更精准地找到所需信息,都让我们离真正智能的“数字员工”更近了一步。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询