Appearance
RAG 的多样使用方法及处理技巧
引言
本文旨在综合整理关于检索增强生成(RAG)系统的多样化使用方法和高级处理技巧。RAG 作为提升大型语言模型(LLM)回答准确性和相关性的重要技术,其在实际应用中涉及多种数据处理、查询优化和模型协作策略。本文将详细探讨 Excel 表格处理、图片知识库构建、用户查询(Query)优化、动态知识片段以及 Embedding 与 Rerank 模型的应用等关键内容,旨在为 RAG 系统开发者和实践者提供一份全面且深入的参考指南。今天的分享内容可能包含许多小技巧,虽然不是主干理论,但对于不熟悉 Coze 或 Agent 的开发者来说,这些技巧在实际操作中可能非常重要。
一、Excel 表格的处理方法
Excel 表格是企业中常见的数据存储格式,将其有效融入 RAG 系统对于释放数据价值至关重要。处理 Excel 表格主要有以下几种方式。需要明确的是,并非所有 Excel 文件都适合或需要制作成知识库;有些 Excel 文件可能仅作为输入数据使用。
1. 将 Excel 文件直接作为知识库
最直接的方法是将 Excel 文件本身处理成知识库的一部分。
表格知识库特性:Excel 可以保留其原有的表格格式,并转化为一种特殊的知识库类型(表格知识库)。这种方式适用于需要保持数据表格结构以供检索和理解的场景。
适用场景:当 Excel 中的内容(如产品手册、课程大纲、FAQ、Coze 操作文档等)需要作为参考资料被 LLM 检索和引用时,可以将其转化为表格知识库。例如,可以将 Coze 的每一页文档内容复制整理,分门别类后制作成知识库,方便 Agent 直接回答用户关于平台操作的问题。
处理流程:
- 数据准备:整理 Excel 内容,确保结构清晰。例如,一个课程信息的 Excel 知识库可能包含列:
标签1 (如“课程”),标签2 (如“AI 大模型”),知识主题 (如“课程师资介绍”),知识切片 (详细的师资介绍文本),相关元数据:图片 (教师照片的 URL 链接),相关元数据:视频 (相关视频的 URL 链接),相关元数据:响应方式,相关元数据:槽位或调用工具等。图片和视频是非常常见的元数据。 - 上传与切片:与处理普通文本知识库类似,上传 Excel 文件后,系统会对其进行切片处理。
- 向量化:将切片后的内容(特别是指定的索引列)进行向量化,存入向量数据库。
- 数据准备:整理 Excel 内容,确保结构清晰。例如,一个课程信息的 Excel 知识库可能包含列:
在 Coze 等平台上的实现:
在“知识库”中点击“添加知识库”。
为知识库命名(例如:“课程相关信息”),并填写描述(例如:“老师、课程内容、操作平台等知识信息”)。
选择知识库类型为“表格格式”。
上传 Excel 文件。注意:在 Coze 上,目前一个表格知识库通常只能包含一个 Excel 文件。这与程序员通过代码构建的、可能包含多个表格的知识库不同。
指定索引列:平台会解析 Excel 的列(如
标签1,标签2,知识主题,知识切片,元数据等)。用户必须指定某一列作为“索引列”(例如,选择“知识主题”列)。RAG 系统将主要基于这一列的内容进行相似度检索。这意味着,只有被选为索引列的内容才真正被 RAG 系统用于检索匹配。如果选择“知识主题”作为索引列,那么只有这一列的内容会参与到向量相似度计算中。选择考量:
- 如果选择内容较少的“知识主题”列作为索引,当用户问题与“知识切片”列中的详细描述更匹配时,可能因为索引列不匹配而检索不到。
- 反之,如果“知识切片”列内容过于冗长,也可能影响检索效果。
- 需根据实际情况权衡,选择最能代表行信息核心且利于检索的列。
检索机制:当用户提问时,系统会将问题与索引列的内容进行匹配。匹配成功后,通常会返回包含表头的整行数据作为参考信息给 LLM。返回表头(如
标签1,标签2,知识主题,知识切片)非常重要,因为它告诉 LLM 检索到的各部分数据是什么含义,便于 LLM 理解和使用。
Prompt 优化示例: 在 Agent 的系统提示词(System Prompt)中,可以加入如下指令以规范其行为:
“回答用户的问题,必须参照知识库中的信息。如果在知识库中没有找到匹配的知识,严禁自行发挥回答用户问题。如果在知识库中没有找到回答用户问题的明确依据,则告知用户‘这个问题我不太清楚’。” (注意:即使 Prompt 中有错别字,如“严谨”写成“严禁”,LLM 有时也能理解正确意图,但不建议如此。)
元数据利用:
如果 Excel 的某行知识切片关联了图片或视频(通过 URL 链接存储在特定列,如“相关元数据:图片”),当该行被检索出来后,可以在 Prompt 中指示 Agent:
- 不仅要基于文字知识回答。
- 还要将图片/视频链接一并发给用户,以提供更丰富的回答。
这模拟了传统 RAG 中“相关元数据”的概念,弥补了 Coze 普通文本知识库切片无法直接附加图片/视频的不足。
注意事项:
- 索引列的选择:应选择最能代表该行信息核心内容的列作为索引,且内容应简洁明确,避免过长文本。
- 图片/视频处理:不要直接在单元格粘贴图片/视频文件,应上传到服务器后,将访问链接填入 Excel。
- 单一文件限制:Coze 目前表格知识库只支持单个 Excel 文件。
2. 通过插件读取 Excel 文件内容
当不希望将 Excel 预处理为知识库,或者需要动态处理用户上传的 Excel 文件时,可以使用插件。大语言模型本身“有眼睛(能看懂文本/图片)、有嘴巴(能输出文本/图片),但没有手”,无法直接打开和操作本地文件。因此,需要通过插件或代码等方式将 Excel 内容“喂”给模型。
插件读取原理:在 Agent 中添加专门用于读取 Excel 文件的插件(如 Coze 国内版插件市场中的 "ReadFile/readExcel" 插件,通过搜索"excel"可找到)。插件会直接读取 Excel 文件的内容,并将其转化为纯文本或结构化文本(如 JSON)格式。
应用优势:简化了预处理流程,Agent 可以直接处理用户实时上传的 Excel 文件。
实现方式(以 Coze 为例) :
- 用户上传文件:用户在与 Agent 对话的界面上传 Excel 文件。
- 获取文件链接:文件上传后,Coze 平台会自动将文件存储在服务器上,并为其生成一个临时的 URL 链接。这个链接在插件调用时是可见的。
- 插件调用:Agent 的 Prompt 或工作流逻辑捕获到文件上传事件后,将文件 URL 传递给 Excel 读取插件。
ReadFile/readExcel插件需要一个url参数(Excel 文件的下载地址)和一个可选的sheetName参数(默认为第一个 sheet)。 - 内容提取:插件读取 Excel 内容。例如,
ReadFile/readExcel插件会将每一行数据(通常忽略表头)作为一个独立的记录返回,形成一个列表。 - LLM 处理:提取出的文本内容(所有行的数据)被整合到 LLM 的上下文中,作为回答用户问题的参考资料。
示例 Prompt 逻辑 (Coze 表格问答助手 - 插件版) :
plaintext你是一个专业的Excel解析助手,擅长基于Excel文件内容回答用户问题。请按以下步骤进行工作: 1. 如果用户没有上传文件,也就是你没有收到文件链接URL,则提示用户提供Excel文件。 2. 解析并输出用户上传的Excel文件名称。 3. 调用excel插件读取Excel文件的内容。 4. 解析excel插件的运行结果,并且回答用户问题。注意事项:
- 插件稳定性:第三方插件的稳定性可能不一,需要充分测试。有时多运行几次才能成功。
- Sheet 处理:
ReadFile/readExcel插件默认只读第一个 sheet。若需读取多个 sheet,需多次调用插件并指定不同的sheetName。 - 数据格式:插件返回的数据通常是纯文本列表,每条是 Excel 的一行。原始的表格结构可能丢失,LLM 需要理解这种纯文本化的数据。
3. 让 Agent 具备运行代码的能力读取 Excel
对于更复杂的 Excel 处理需求,或者需要更高准确性的数据提取和计算,可以让 Agent 通过执行代码来读取和解析 Excel 内容。
代码处理方式:Agent 本身不直接执行代码,而是通过调用“代码执行器”(Code Runner)之类的插件/工具来运行预先编写好或由 LLM 动态生成的代码(通常是 Python 代码,使用 pandas 等库)。
优势:
- 灵活性高:可以实现复杂的逻辑,如特定数据清洗、计算、格式转换等。
- 准确性高:相比 LLM 直接理解表格文本,结构化代码处理数据(尤其是数值计算)错误率更低。
- 常用技巧:在 Agent 开发中,使用代码处理数据比单纯依赖模型理解更准确,是非常常用的技巧。
实现流程(以 Coze 为例) :
编写/生成代码:
- 可以预先编写好通用的 Excel 读取和处理 Python 脚本。
- 更常见的是,让 LLM 根据当前需求动态生成 Python 代码。开发者用自然语言清晰描述需求(例如:“我有一个 Excel 文件,它的下载链接是{file_url},文件名是{filename},请帮我写一段 Python 代码,使用 pandas 库读取这个 Excel 文件的所有内容,并将每一行转换成 JSON 对象,最后输出一个包含所有这些 JSON 对象的列表。”),LLM 生成代码。
代码执行器插件调用:
- 将生成的 Python 代码字符串、Excel 文件的 URL 以及文件名等作为参数传递给代码执行器插件(如 Coze 的
CodeRunner)。CodeRunner插件通常需要code(Python 代码)、upload_file_uri(上传文件的 URI)和upload_file_name(上传的文件名)等参数。 - 代码执行器在安全环境中运行这段 Python 代码。
- 将生成的 Python 代码字符串、Excel 文件的 URL 以及文件名等作为参数传递给代码执行器插件(如 Coze 的
结果返回:代码执行成功后,其输出(例如,
print()语句打印的内容,通常是 JSON 字符串)会作为插件的结果返回给 Agent。LLM 利用:Agent 基于代码执行器返回的 JSON 数据来回应用户或执行后续任务。
示例 Python 代码 (由 LLM 生成,用于 Coze CodeRunner) :
python# 导入所需库 import pandas as pd import json import datetime # 用于处理日期时间格式 import re # file_path 会由CodeRunner根据传入的upload_file_uri和upload_file_name在特定目录(如/mnt/data/)下定位 # 这里的 {{filename}} 是一个占位符,实际会被替换 # 这是Coze中代码执行器通常处理文件的方式 file_path = f"/mnt/data/{{filename}}" # 使用pandas读取Excel文件,指定引擎以支持xlsx格式 df = pd.read_excel(file_path, engine='openpyxl') # 定义一个函数来转换日期时间格式,如果值是datetime对象 def convert_timestamp(value): if isinstance(value, datetime.datetime): return value.strftime('%Y年%m月') # 示例格式,可按需修改 return value # 如果不是时间格式,则返回原值 # 遍历DataFrame的所有列,尝试对可能是日期时间类型的列应用转换函数 for col in df.columns: try: df[col] = df[col].apply(convert_timestamp) except Exception: # 如果转换失败(例如,列不是日期时间类型),则跳过 pass # 将处理后的DataFrame转换为JSON字符串,格式为记录列表,并保留非ASCII字符 json_output = df.to_json(orient='records', force_ascii=False) # 打印JSON输出,代码执行器会捕获此输出作为结果 print(json_output)- 注意:上述代码中的
是 Coze 中提示使用变量的方式,实际运行时会被替换。engine='openpyxl'是 pandas 读取 xlsx 文件时常用的引擎。日期时间转换是为了避免直接输出 datetime 对象导致 JSON 序列化问题。
- 注意:上述代码中的
动态处理优势:此方法非常适合处理在 Agent 运行过程中动态出现或由用户实时上传的 Excel 文件,无需预先将其制作成知识库。当 Agent 从其他公司系统接口获取到 Excel 文件时,这种方式也非常适用。
4. Excel 处理的准确性与模型对比
挑战:大语言模型直接处理复杂表格(尤其是包含公式、多层表头、合并单元格的表格)时,准确率可能不高。
测试与验证:
在实际应用中,需要测试不同 LLM(如通义千问、GPT-4o、DeepSeek 等)在特定表格处理任务上的表现。
测试维度可以包括:识别具体单元格数据、执行简单计算、识别数据错误等。
案例:财务行业预算表测试,包含识别表格数据、执行数据计算、识别数据错误等测试类别。
- 通义千问 (Qwen 2.5) 正确率:识别表格数据 94.29%, 执行计算 93.33%, 识别错误 0%。
- Coze (Qwen 2.5 Max) 正确率:识别 94.29%, 计算 96.67%, 错误识别 75%。
- Coze (GPT-4o) 正确率:识别 94.29%, 计算 93.33%, 错误识别 25%。
- DeepSeek (DeepSeek V3) 在其官网测试正确率:识别 65.71%, 错误识别 50%。
- Coze (DeepSeek V3) 正确率:识别 94.29%, 计算 96.67%, 错误识别 50%。
DeepSeek V3 的特殊表现:
- 有案例显示,DeepSeek V3 在自家官网平台处理 Excel 时,倾向于读取单元格的公式本身而非其计算后的数值。这可能导致在某些场景下(如直接查询数值结果)准确率较低。例如,如果一个单元格是
=SUM(A1:A5),它会读取这个公式,而不是 A1 到 A5 的和。 - 然而,在 Coze 等集成了额外处理逻辑的平台上,同样的 DeepSeek V3 模型可能表现更佳。这可能是因为 Coze 平台对 Excel 数据进行了预处理(如将公式计算结果提取出来)再交给 LLM,或者 Prompt 工程做得更好。
- 有案例显示,DeepSeek V3 在自家官网平台处理 Excel 时,倾向于读取单元格的公式本身而非其计算后的数值。这可能导致在某些场景下(如直接查询数值结果)准确率较低。例如,如果一个单元格是
关键启示:
- 输入数据的形态至关重要:最终交给 LLM 的参考资料是什么样子,直接影响其表现。我们关心的是“最后交给大模型的东西到底长什么样子”。
- 平台差异:同一模型在不同平台或产品中的表现可能因预处理、内置 Prompt、后端代码实现等因素而异。DeepSeek 官网产品界面和 Coze 平台对 Excel 的处理方式不同,导致了准确率差异。
- 没有绝对的好坏:某种处理方式(如 DeepSeek 读取公式)在某些场景下可能是劣势,但在需要分析计算逻辑或验证公式正确性的场景下则可能成为优势。
- Excel 数据清洗:需要将 Excel 表格的表头整理为只有一行一列,这样 LLM 才能很好地理解。
5. 应用案例与实践建议
案例:财务预算表分析
- 一个复杂的财务预算表(包含多月份、多产品线、各类成本如房租、服务器、市场营销、办公设备、人力成本、利润率计算等)通常不适合直接做成静态知识库。
- 更常见的做法是用户上传预算表,然后向 Agent 提出分析需求(如“分析各产品线的盈利能力”、“对比不同业务的成本结构”、“某产品是否盈利/扭亏为盈的预期”)。
- 此时,Agent 需要具备动态解析表格并进行计算的能力,通常结合代码执行器实现。
实践建议:
- 明确场景需求:根据具体任务选择最合适的 Excel 处理方式。是要静态知识检索,还是动态文件处理,或是复杂数据分析?
- 数据清洗与规范化:对于要制作成知识库的 Excel,表头应清晰,结构应尽量规范。对于需要代码处理的,也要注意数据格式的一致性。
- Prompt Engineering:清晰指示 LLM 如何使用表格数据,如何解读插件或代码执行器的返回结果。
- 多动手,抠细节:AI 领域的经验很多来自于实践中的细节调整和问题解决。要真正关心交给大模型的 Prompt 是什么。
二、图片作为知识库的内容
图片是另一种重要的信息载体,尤其是在包含图表、示意图、产品截图等的教学或技术文档中。
1. 图片处理的两种模式
模式一:图片作为文字知识的附属元数据
- 描述:在这种模式下,图片本身不直接参与 LLM 的语义理解和问答,而是作为文字知识切片的一个补充说明。
- 应用:当 Agent 根据文字知识回答用户问题后,可以将关联的图片链接一并展示给用户,以增强理解。
- 实现:在知识库(如 Excel 表格知识库)中,为文字知识条目添加一个字段,用于存储相关图片的 URL。
模式二:图片内容作为知识主体被检索和问答
描述:这种模式下,图片中的信息是核心知识,需要 LLM 能够理解图片内容并据此回答问题。
技术挑战:
需要强大的多模态模型(能够理解图像内容)。
目前国内可用的、在 Coze 等平台上易于集成的高质量多模态模型相对有限。Coze 国内版能用的多模态模型可能只有豆包视觉理解模型和阶跃星辰模型。
模型表现差异:
- 豆包视觉理解模型在测试中(如读取知乎 Q3 财报图片中的收入数字)表现不佳,将 8 亿多误读为 10 多亿。
- DeepSeek V3 在自有平台测试时,对同一财报图片的数字读取准确(8.45 亿)。
- 通义千问在自有平台测试时,也准确识别为 8.45 亿。
- 然而,在 Coze 平台上,DeepSeek 和通义千问可能并未直接开放其多模态图片读取能力,导致用户在 Coze 上可能主要依赖豆包模型。
2. 图片知识库的构建与处理(以 Coze 平台为例)
创建图片类型知识库:
- 在 Coze 中可以创建“照片类型”的知识库(例如,命名为“知乎 2024 年三季度财报”)。
- 上传图片文件(例如,财报截图)。
图片转文字/描述:
核心机制:由于图片本身无法直接像文本一样被向量化和高效检索,平台通常会将图片内容转换为文字描述,或者允许用户为图片添加文字描述。这些文字描述随后被用于向量化和检索。
自动标注/OCR:Coze 提供“智能标注”功能,尝试自动从图片中提取文字或生成描述。
- 问题:自动提取的文字可能不准确,或者生成的描述可能不全面,甚至出现无厘头的错误(如将键盘图片识别为“计算机键盘”,有时会将复杂图表错误描述为“中文乐谱”或“一份计算机键盘”),Coze 的这个功能可能“还挺难用”。
手动优化:为了确保检索的准确性,强烈建议手动检查和优化图片对应的文字描述。
- 方法:可以先使用外部能力较强的多模态模型(如 DeepSeek、通义千问,在其自有平台上传图片并要求详细描述图片中的所有内容)生成详细的图片描述,然后将这段准确的描述文字复制粘贴到 Coze 图片知识库中,与对应图片关联。
检索与问答:
- 当用户提问时,系统会将问题与图片关联的文字描述进行相似度匹配。
- 如果匹配成功,Coze 平台的做法通常是将这段文字描述作为参考资料提供给 LLM,LLM 基于这段文字来回答问题。Coze 目前似乎是直接将图片对应的文字(限制 2000 字以内)作为知识库内容。
局限性与建议:
信息损失:图片转文字的过程(无论是 OCR 还是 AI 描述)都可能造成信息损失或失真,尤其是对于包含大量数据、复杂图表或精细细节的图片。用有限的文字完整描述一张复杂图片的所有内容是非常困难的。
数字准确性风险:如果图片中的关键数字在转换过程中出错(例如 OCR 识别错误),将直接影响问答的准确性,因为后续所有基于此错误数字的推断都会是错的。
更优做法(理论上) :理想情况下,当检索到与某图片相关的知识时,应将原始图片直接传递给具备强大图片理解能力的多模态 LLM 进行实时分析和问答,而不是仅仅依赖预先生成的文字描述。LLM 只需就着问题去图片里找对应信息即可,无需解析图片内所有文字。
- 这种做法下,LLM 不需要将整张图片所有文字都读准确,只需针对问题找到图片中相关信息。
- 对于表格类图片,OCR 保留原表格格式很难,直接让多模态模型基于图片问答可能效果更好。
实践建议:
- 如果平台支持且模型能力足够,优先考虑让 LLM 直接基于原始图片回答。
- 如果只能依赖文字描述,务必保证描述的准确性和完整性,最好人工校验或借助高质量多模态模型生成描述。
- 可以考虑混合方案:提供简洁的文字描述用于初步检索,同时在 Prompt 中指示 LLM,如果需要,应结合原始图片(如果能通过链接等方式访问)进行确认。
三、查询(Query)优化
用户向 RAG 系统提出的原始问题(Query)的质量直接影响检索效果和最终答案的准确性。因此,对用户 Query 进行优化是 RAG 系统中的一个重要环节。这需要知识库准备和用户问题处理两方面的“双向奔赴”。
1. 用户 Query 处理的挑战
多轮对话的复杂性:
- 用户的意图可能分散在多轮对话中。例如,用户可能先说“我要订一张去北京的机票”,然后补充“下周三出发”,最后确认“是的”。此时,应该用哪一句作为最终的检索 Query?
- 如果直接使用最后一句话(如“是的”)去检索,几乎不可能找到相关信息。
用户表达的多样性与模糊性:
- 用户可能使用口语化、不规范、甚至错误的表达。
- Query 中可能包含大量与核心意图无关的冗余信息(例如,用户在问职业规划问题前做了大量个人情况铺垫)。
- Query 可能缺乏必要的上下文信息。
2. Query 处理的核心原则:“双向奔赴”
优化 RAG 系统性能,需要在知识库构建和 Query 处理两方面都付出努力。
- 知识库端:知识库的组织(如按城市拆分计费规则)、切片方式、元数据设计等应考虑到用户可能的提问方式和语义匹配。如果知识库准备不当,即使用户问题清晰,也可能因语义不匹配而检索失败。
- Query 端:对用户原始 Query 进行预处理和改写,使其更适合在知识库中进行有效检索。
3. Query 处理的常见技巧
a. Query 清洗与标准化
- 去除口语化表达、错别字。
- 补全缺失的上下文(如果可以从对话历史中推断)。
- 将非标准术语转换为知识库中的标准术语。
b. Query 重写/改写 (Query Rewriting)
目标:将用户原始的、可能不适合直接检索的 Query,转换为一个或多个更精确、更结构化的检索语句。
方法:
- 基于规则:定义一些规则来转换 Query(较简单,但覆盖面有限)。
- 基于 LLM:利用 LLM 的理解和生成能力对 Query 进行改写。例如,在 Prompt 中指示 LLM:“请将以下用户问题简化成 20 字以内,只表达核心重点。”
示例:
- 用户原始 Query(经过多轮对话后,内容冗长):"我学完了 A 课程,也了解了 B 技术,还搞清楚了 C 原理,现在感觉自信多了,但是因为缺乏实际项目经验,找工作时还是有点吃亏,不知道接下来该怎么办,是不是可以考虑 XX 方向或者 YY 方向呢?"
- LLM 改写后的 Query(用于检索):"学完这些课程,缺项目经验,怎么找工作?"
- 效果:使用改写后的简洁 Query 去检索知识库(如一个包含“课程信息”的表格知识库),更容易匹配到相关的职业发展建议或项目经验获取途径的知识片段。如果用原始的长 Query,大量无关文字会误导模型,可能导致检索到不相关的知识或什么都检索不到。
c. 结构化信息提取与利用(填槽)
场景:当用户意图可以被分解为多个结构化字段时(如打车场景中的出发地、目的地、打车时间、所在城市)。
方法:
- 信息收集(填槽) :通过多轮对话或 LLM 的理解能力,从用户输入中提取关键信息,填充到预定义的槽位中。这依赖 LLM 的 Function Call 能力。
- 追问机制:如果必要信息不完整(槽位未填满),Agent 应主动追问用户以补全信息。例如,在 Prompt 中指明需要收集哪些字段,如果缺少信息则进一步询问。
- 基于结构化信息检索:使用提取出的一个或多个结构化字段(例如,仅使用“城市名称”)作为 Query 去检索知识库,而不是整个原始 Query。
示例:打车计费场景
知识库:包含各城市打车计费规则(如北京、上海、厦门等),每个城市一条知识。知识库已按城市切分好。
用户输入流程:
- 用户:“厦门火车站出发。” (只提供了出发地)
- Agent (根据 Prompt 设定的填槽逻辑) 追问:“您的目的地是哪里呢?另外,由于您未提及打车时间,将默认使用当前时间,您看可以吗?”
- 用户:“目的地厦门大学。”
- Agent (信息收集完毕) 解析出:
城市:厦门,出发地:厦门火车站,目的地:厦门大学,打车时间:(当前时间)。
知识库检索:Agent 使用解析出的结构化信息中的
城市:厦门 作为 Query 去检索知识库,可以准确匹配到厦门的计费规则。如果使用用户最后一句话“目的地厦门大学”或原始的“厦门火车站出发”去检索,则很可能失败或匹配到不相关的城市信息。
优势:显著提高检索的准确性和效率,避免了自然语言的模糊性带来的干扰。将用户的大段文字解析成结构化信息后,可以灵活选用其中字段进行操作。
4. 结合工作流(Workflow)实现 Query 优化
在 Coze 等支持工作流的平台上,可以将 Query 优化和知识库检索过程封装到工作流中。
工作流设计:
- 开始节点:接收 Agent 传递过来的用户原始 Query 或初步解析的参数(如
city,origin,destination,time)。工作流名称在 Coze 中通常要求是英文(如taxi_chalk)。 - LLM 节点(Query 处理,可选) :如果需要,可以在工作流内部再调用 LLM 对传入的 Query 进行进一步清洗、改写。
- 知识库检索节点:使用处理后的 Query(或提取出的关键字段,如仅用
city字段的值)去检索指定的知识库(如“打车计费知识库”)。 - 结束节点:将检索结果(如匹配到的知识片段)返回给 Agent。
- 开始节点:接收 Agent 传递过来的用户原始 Query 或初步解析的参数(如
Agent 与工作流的交互:
- Agent 负责与用户交互、通过 Prompt 设定的逻辑收集初步信息(填槽)。
- 当信息收集完整后(例如,出发地、目的地、时间都已获取),Agent 的 Prompt 会指示调用特定的工作流,并将收集到的结构化信息作为参数传递给工作流。
- Agent 的 Prompt 中会定义调用工作流的条件(如“如果缺少信息,则要进一步询问用户相关信息,信息收集全了再启动工作流”)和传递给工作流的参数。
示例:打车计费工作流
taxi_chalkAgent 的 Prompt 指示:需要收集用户的出发地、目的地、打车时间。信息收集完整后,将这些信息(城市、出发地、目的地、时间)作为参数传递给名为
taxi_chalk的工作流。工作流
taxi_chalk内部:- 接收到
city等参数。 - 使用
city参数的值作为 Query,检索“打车计费知识库”。 - 返回匹配到的计费规则列表(可能有多条,按相似度排序)。
- 接收到
Agent 接收工作流返回结果,并按 Prompt 指示(如“将工作流的结果完整输出给用户”)进行后续处理。
好处:
- 将复杂的逻辑处理(如多轮对话后的信息汇总、特定字段提取、基于特定字段的知识库查询)与主 Agent 的对话逻辑解耦。
- 便于管理、测试和复用 Query 处理及检索逻辑。
- 可以实现更精准的知识库调用,例如,确保只用最关键的信息(如城市名)去匹配知识库,而不是用用户随意的问话。
四、知识片段中加入变量(动态知识片段)
标准 RAG 中的知识片段通常是静态的,即其内容在存入知识库后不会改变。然而,很多场景需要根据实时情况或用户信息提供动态内容。
1. 动态知识片段的概念
- 静态知识库的局限:无法处理需要实时更新的信息(如产品库存、理财产品当前收益率)或个性化信息(如“我的助教老师是谁?”、“我们公司现在有多少人?”)。公司人数、理财收益率等都是动态变化的。
- 动态变量的引入:在知识片段模板中预定义一些变量(占位符),在 RAG 系统运行时,通过调用 API、插件或查询数据库等方式获取这些变量的实时值,然后填充到模板中,形成最终的、动态的参考资料。这样,知识库中的知识片段也能“动”起来。
2. 实现动态知识片段的技术方案
这是一个三步过程:
设计包含变量的知识模板:
- 创建知识片段时,将需要动态填充的部分用特定的占位符表示。这些模板可以存储在 Excel 表格知识库的某一列。
- 示例:“你好{学员姓名},你的专属助教老师是:{助教老师姓名},联系电话:{助教电话},微信:{助教微信}。你可以通过电话或微信联系你的助教老师。”
获取实时数据:
当检索到这类包含变量的知识模板时,Agent 需要根据模板中的指示(可能记录在 Excel 知识库的元数据列中,如“响应方式”、“槽位依赖”、“调用工具”)去获取变量的实际值。
数据源:
- 用户提供的信息:例如,Agent 先询问用户的手机号(作为关键槽位)。
- 外部 API/插件:调用公司内部系统 API(如知乎知学堂的学生学习系统 API,用于查询学员信息、订单系统)或第三方插件。这些 API 或插件通常需要由程序员开发。
- 数据库查询:直接查询相关数据库。
填充模板并生成回复:
- 将获取到的实时数据填充到知识模板的对应变量位置。
- 将填充完毕的、包含最新动态信息的知识片段作为参考资料,交给 LLM 生成最终回复。
3. 典型应用案例解析
a. 查询专属助教信息
用户问题:“我的助教老师是谁?” / “我怎么联系我的助教老师?”
知识库中的表格化处理(示例) :
-
标签1: "课程" -
标签2: "服务" -
知识主题(用于检索匹配):“查询我的助教老师联系方式” -
知识切片模板:“你好同学,你的助教老师是:{assistant_name},他的手机号码是:{assistant_phone},他的微信号是:{assistant_wechat}。你可以打电话,也可以加微信联系助教老师。” -
相关元数据:响应方式:“追问填槽,并且调用工具” -
相关元数据:槽位依赖:“学员手机号” (Agent 需要收集这个信息) -
相关元数据:调用工具:“find_assistant_plugin (输入: 学员手机号, 输出: 助教姓名、电话、微信)” (这个插件由知乎知学堂的学生学习系统提供)
-
处理流程:
- Agent 通过“知识主题”列检索到此条知识模板。
- 根据
槽位依赖元数据,Agent 向用户提问:“请提供您的手机号码,以便为您查询助教信息。” - 用户提供手机号。
- Agent 调用
find_assistant_plugin(或对应的 API),传入手机号。 - 插件/API 返回该学员对应的助教的具体信息。
- Agent 将返回的信息(助教姓名、电话、微信)填充到
知识切片模板的占位符中。 - LLM 基于填充后的完整、个性化的信息,生成回复给用户。
b. 查询课程解锁状态
用户问题:“老师您说本周三要解锁三节 Demo 解析课,我怎么在课包里没找到呢?”
类似处理:
- Agent 可能也需要先收集学员手机号或账户信息(槽位依赖)。
- 调用课程管理系统的 API(调用工具)检查该学员账户内是否有这些课程的授权。
- 如果已授权,则告知学员查找路径。
- 如果未授权,但符合条件,系统甚至可以设计成自动调用另一个 API 为学员授权这几节课。
- 将处理结果(如“已为您授权 XX 课程,请到 XX 位置查看”)填充到回复模板中告知用户。
- 这可能需要多个插件或 API 的组合调用,通过 Function Call 实现。
4. 技术实现要点
跨部门协作:
- 业务/产品/运营人员:负责梳理需要动态信息的业务场景,定义用户问题,设计知识模板和交互流程。
- 开发人员:负责提供必要的数据接口(API)、插件或数据库访问能力。例如,在 Coze 中,如果公司内部系统提供了 API,程序员可以编写 Python 代码将其封装成 Coze 插件。
平台实现:
- 在 Coze 等平台上,简单场景可以通过工作流结合 LLM 的填槽和现有工具调用能力实现。
- 复杂场景(如调用公司内部私有 API)通常需要开发自定义插件。
响应策略对比(面对用户提问时) :
- 任由模型自由发挥(胡说八道) :不可取,可能产生错误信息。
- 直接回复“不知道”/“不清楚” :用户体验差,但比胡说八道好。
- 通过模板 + 动态数据生成准确回复:是推荐方案,能提供准确且个性化的服务,是更可靠的做法。
五、Embedding 与 Rerank 模型
为了提高 RAG 系统中知识检索的准确性和相关性,通常会采用 Embedding 模型进行初步检索,并结合 Rerank 模型进行结果重排序。这是 RAG 中的进阶知识。
1. Embedding 模型
a. 基本概念与工作原理
- 核心功能:将文本(句子、段落、文档)转换为固定维度的数学向量(Embedding),使得语义相似的文本在向量空间中的距离更近。
- 架构基础:现代 Embedding 模型(如 BGE、GTE 等)通常基于 Transformer 架构,与 GPT 等大语言模型在底层结构上有相似之处(都能理解语义信息),但 Embedding 模型规模通常较小,其训练目标也与生成式大模型不同。
- 语义理解原理:通过学习大量文本数据,模型能够捕捉词语和句子的语义信息,并将其编码到向量表示中。
b. Embedding 模型的训练
训练目标:
- 使语义相似的文本对产生高相似度的向量(即向量空间中距离近)。
- 使语义不同的文本对产生低相似度的向量(即向量空间中距离远)。
训练数据:通常使用“三元组(Triplet) ”数据进行训练,每条数据包含(一般需要数亿条这样的数据,多数公司自行组织):
Anchor(锚点) :一个基准文本。
- 示例:“秦始皇统一六国后,推行了中央集权的政治体制。”
Positive(正例) :一个与 Anchor 语义高度相似的文本。
- 示例:“秦朝实行了法家思想,中央政府的权力得到了加强。” (与 Anchor 意思相近)
Negative(负例) :一个与 Anchor 语义不相似的文本。
- 示例:“宋朝的科举制度对中国古代的教育体系产生了深远影响。” (与 Anchor 意思不相关)
训练过程:模型通过优化损失函数(如 Triplet Loss),使得 Anchor 与 Positive 的向量距离尽可能小,而 Anchor 与 Negative 的向量距离尽可能大。模型在数亿条这样的三元组数据中学习,调整自身参数,以学会如何为不同文本生成合适的向量表示。
与 GPT 模型的区别:
- 输出:Embedding 模型输出数学向量;GPT 模型输出自然语言文本。
- 主要应用:Embedding 模型主要用于向量检索和相似度计算(私有知识库的核心);GPT 模型用于对话生成、文本创作等。
- 能力与目标:Embedding 模型能力不如 GPT 强,其目标是区分语义相似度;GPT 目标是生成高质量、相关的回复。
c. Embedding 检索的局限性
知识库规模问题(临界点现象) :当知识库中的知识片段数量非常庞大时(如数十万上百万条,具体阈值因场景而异),单纯依赖 Embedding 模型的相似度计算可能会遇到瓶颈。
现象:随着知识片段数量的增加,检索准确率先是提高,但达到一个“临界点”后,准确率反而可能开始下降。
mermaidgraph LR A[知识片段数量较少] --> B(检索准确度较高); C[知识片段数量持续增加] --> D{向量空间变密集}; D --> E(语义区分度下降); E --> F(检索准确度可能下降);原因:
- 向量空间变得过于“拥挤”。
- 许多语义上本有差异的知识片段对应的向量在空间中也靠得很近。
- 模型难以精确区分这些细微但关键的差异,导致“相似”的向量过多,错误召回(召回了不那么相关的片段)或排序不佳的情况增加。模型“看谁都像”。
影响因素:
- 场景宽度:垂直领域(如特定行业的招聘 FAQ)知识本身就比较集中和相似,更容易达到“拥挤”状态,临界点出现更早。通用领域知识库能容纳更多片段。
- 知识密度:在窄场景中硬塞过多知识片段,会更快遇到此问题。
- 向量维度:增加向量维度有一定帮助,但不能完全解决。
2. Rerank(重排序)模型
为了弥补 Embedding 模型在海量数据或细微语义区分上的不足,引入 Rerank 模型进行二次排序。Coze 知识库设置中通常有“结果重排”的开关,建议打开。
a. Rerank 模型的诞生背景与作用
解决的问题:Embedding 模型追求高效率的初步筛选(召回),可能会召回一些相关性不那么高,或者排序不理想的结果(例如,Top5 召回结果中,最相关的可能排在第 3 或第 4)。Rerank 模型则对这些初步候选结果进行更精细、更准确的相关性打分和排序,如同用“放大镜”仔细检查。
工作流程:
初步检索(Embedding) :用户 Query 经过 Embedding 模型向量化后,在向量数据库中检索出 Top-K 个最相似的知识片段(例如,K=5 或 10,此 K 值可在 Coze 中设置“最大召回数量”)。
重排序(Rerank) :Rerank 模型接收用户原始 Query 和这 K 个候选知识片段,对每一个“Query-候选片段”对进行打分,然后根据分数重新排序,将最相关的片段排到最前面。
mermaidgraph TD subgraph RAG检索流程 U[用户Query] --> E_Q[Embedding Query] KB[知识库] -- Embedding --> VDB[向量数据库] E_Q -- 相似度检索 Top-K --> VDB VDB -- K个候选片段 --> Cands U --> RR[Reranker模型] Cands --> RR RR -- 精排打分 --> Sorted_Cands[排序后的片段] Sorted_Cands --> LLM_P[LLM Prompt] end
b. Embedding 与 Rerank 模型的架构与工作方式对比
Embedding 模型(通常是 Bi-Encoder,双编码器) :
Query 和 Document(知识片段)分别通过独立的 Encoder 塔(例如,两个 Transformer 编码器)进行编码,得到各自的向量表示。
然后计算这两个独立生成的向量之间的相似度(如余弦相似度、点积)。
特点:
- 编码过程可以预先对所有文档完成并存储向量。
- 检索时只需编码 Query 并进行高效的向量运算,速度快。
- 但 Query 和 Document 在编码时是独立的,它们之间的交互信息在相似度计算前没有充分利用。
Rerank 模型(通常是 Cross-Encoder,交叉编码器) :
将用户 Query 和每一个候选 Document 拼接在一起(例如,形如
[CLS] Query [SEP] Document [SEP] 的输入序列),作为一个整体输入到同一个强大的 Transformer Encoder 中。模型直接输出一个表示该 Query 与该 Document 之间相关性的分数(通常是一个 0 到 1 之间的标量)。
特点:
- Query 和 Document 在模型内部通过自注意力机制进行了充分的交互和信息融合,能够更准确地判断其真实相关性。
- 但由于每个候选都需要与 Query 一起通过复杂的 Encoder 模型,计算量大,速度慢,因此只适用于对少量(如 Top-K)候选进行重排。它不能用于海量知识库的初筛。
图示对比:
Embedding (Bi-Encoder):
mermaidgraph TD subgraph Bi-Encoder Query --> Encoder1 --> QueryVector Document --> Encoder2 --> DocVector QueryVector -- Similarity --> Score1 DocVector -- Similarity --> Score1 endRerank (Cross-Encoder):
mermaidgraph TD subgraph Cross-Encoder Query_Doc_Pair["Query + Document (Concatenated)"] --> Encoder_Combined --> RelevanceScore end示例效果:
Query: "大连医科大学怎么样?"
候选 1: "大连理工大学怎么样?" (Bi-Encoder 相似度: 0.78,因为字面相似)
候选 2: "大连医科大学创建于 1947 年..." (Bi-Encoder 相似度: 0.55)
经过 Rerank (Cross-Encoder) 后:
- (Query, 候选 1) 相关性得分可能降至 0.55
- (Query, 候选 2) 相关性得分可能升至 0.99 (真实相关)
c. 提升 Rerank 效果的关键技术:难负例挖掘
简单负例 vs. 难负例:
- 简单负例:与 Query 或正例在语义上明显不相关的文档。模型很容易区分。
- 难负例:与 Query 或正例在表面上(如关键词重合度高)相似,但实际语义不相关或存在细微但关键的差异的文档。这些是模型最容易混淆,也最需要学习区分的。
动态难负例训练(腾讯 Conan-Embedding 模型的经验) :
核心思想:在模型训练过程中,持续向模型提供对其而言具有挑战性的难负例,迫使其学习更细致的语义区分能力。
过程:
- 初始训练:模型使用一批包含正例和(较难)负例的数据进行训练。初期,模型可能难以区分这些难负例(即,给难负例的相关性打分也较高)。
- 能力提升:随着训练,模型逐渐能更好地区分这些难负例(给其打分降低)。
- 动态更新负例:当模型对当前批次的难负例已经能很好地区分时(例如,Query 与负例的相似度得分已经很低,说明模型已掌握),这些负例对于模型的进一步提升价值减小。此时,从一个更大的、预先准备好的难负例池中,筛选出对当前模型来说仍然“很难”(即模型计算出的相似度依然较高)的负例,替换掉已掌握的负例,组成新的训练数据包,继续训练。
- 这个过程不断迭代(“换更难的题给模型做”),模型区分细微语义差异的能力持续提升。
难负例的生成:可以通过对抗生成(如使用 AI 对正例进行小幅度、但改变核心语义的修改,使其看起来仍与 Query 相关但实际不符)、人工构造等方式产生。
核心作用总结:这种动态调整训练难度的方法,能让模型学会区分那些最细微、最容易混淆的知识差异,从而大幅提升检索的精准度。
3. 垂直领域的 Embedding 模型微调
目的:通用 Embedding 模型可能无法很好地捕捉特定垂直领域(如医疗、金融、法律、教育)的细微语义和专业术语。通过在该领域的数据上进行微调(Fine-tuning),可以使模型更适应领域特性,提升检索召回的精准度。
微调数据的核心要点是“关联性” :构建能体现领域内知识点之间相关性的数据对。
- 教育:题目-解析对,相似题目对(区分易混淆点),知识点-题目对。
- 医疗:症状描述-诊断方法/对应疾病对。
- 法律:案情描述-适用法条/判决依据对。
- 金融:用户投资方向描述-相关产品/风险评估报告对。
效果:
- 微调可以使原本在向量空间中拥挤、难以区分的领域知识点(因为领域内文本相似度本身就高)对应的向量变得更分散、更易于区分。
- 这从而提高在特定领域内的检索精度。
安全性与适用性:
- 相比微调对话式大模型(如 GPT),微调 Embedding 模型的风险通常更小,也更推荐。
- Embedding 模型主要影响检索召回的质量,其通用能力(如语言理解)的破坏风险相对较低。
- 对话模型的微调如果不得当,很容易破坏其通用的对话能力、逻辑推理能力和行为一致性(变得只会说特定领域的话,或者更容易产生幻觉)。用户提问是不可控的,对话模型需要保持通用性。而知识库内容是可控的。
- 微调后的 Embedding 模型专用于特定领域,可能在其他领域的表现会下降,这是可接受的,因为它提升了目标领域的性能。
4. 常用 Embedding 与 Rerank 模型参考
智源人工智能研究院: BGE (BAAI General Embedding) 系列 (如
bge-large-zh)网易: BCE (Bilingual and Crosslingual Embedding) (多语言支持较好)
阿里: Qwen GTE (General Text Embeddings) (如
gte-Qwen2-7B-instruct)腾讯: Conan-embedding (以动态难负例挖掘技术著称,曾在 HuggingFace 中文 Embedding 榜单排名靠前)
这些机构通常会同时提供配套的 Embedding 和 Rerank 模型。
选择时需考虑:
- 对中文的优化程度。
- 是否支持多语言。
- 参数量(如 3 亿到 70 亿不等)。
- 在特定任务上的评测表现(如 HuggingFace 的 MTEB 榜单)。
Coze 平台使用的 Embedding 模型,据推测可能是字节跳动自研的模型,其具体性能和是否可替换,用户通常无法直接控制。
六、总结与展望
本文详细探讨了 RAG 系统在处理 Excel 表格、图片知识、用户查询优化、动态知识片段以及高级 Embedding 与 Rerank 模型应用等方面的多样化方法和技巧。核心要点包括:
- 数据处理的灵活性:针对不同类型的数据(如 Excel、图片),应采取合适的处理策略(知识库、插件、代码),平衡预处理成本与检索效果。
- Query 理解的重要性:通过 Query 清洗、改写、结构化提取和工作流编排,可以显著提升检索的精准度,尤其是在多轮对话和复杂用户表达场景下。
- 动态知识的价值:通过在知识片段中引入变量并结合实时数据获取(API、插件),RAG 系统能够提供更具时效性和个性化的信息服务。
- 检索模型的协同:Embedding 模型负责高效召回,Rerank 模型负责精准排序,两者结合是提升 RAG 性能的关键。通过难负例挖掘和垂直领域微调,可以进一步优化模型表现。
RAG 系统的构建和优化是一个持续迭代、充满细节调整的过程。没有一劳永逸的解决方案,开发者需要根据具体的业务场景、数据特点和用户需求,不断尝试、测试和调整策略(“见招拆招”)。掌握这些多样化的使用方法和处理技巧,将有助于构建更强大、更智能的 RAG 应用。AI 领域的经验积累往往来自于大量的动手实践和对细节的打磨。