RAG 开发四大痛点及解决方案
痛点1:知识缺失

知识库缺了必要的上下文,这事儿再常见不过。RAG系统在找不到确切答案时,不是老老实实说不知道,反而提供一些模棱两可的信息,用户被带到沟里,体验自然好不了。那么,怎么破?主要有两条路。
解决方案一:优化数据质量
“垃圾进,垃圾出”这个道理大家都懂。源数据如果质量堪忧——比如存在矛盾信息、乱码、重复——再完美的RAG流程也白搭。高质量的数据是顺畅运行的基石。下面这些策略不仅解决这个痛点,还能顺带应付后续提到的其他问题。
- 清除噪音和无关信息:移除特殊字符、停用词(比如“the”、“a”这类高频词)、HTML标签。
- 识别并修正错误:拼写错误、打字错误、语法错误。拼写检查工具和语言模型能帮上忙。
- 去除重复数据:消除可能干扰检索的重复或近似记录。
解决方案二:优化提示词设计
知识库信息不足,系统容易“硬编”答案。这时候提示词设计很关键。比如说,明确告诉大模型:“如果你确定不了答案,就说不知道。”这能引导模型承认局限、表达得更清晰。当然,这不能保证绝对正确,但数据优化之后配上恰当的提示词,算得上是提高系统透明度的有效手段。
—2
痛点2:更相关的知识没有检索出来
初步检索阶段,关键文档可能因为排名不够高被漏掉,大模型也就没法给出精确响应。有研究直接点破:“问题的答案其实就藏在文档里,只是因为它排名不够高,所以没有被呈现给用户。” 怎么解决?两个方向。
解决方案一:调整 chunk_size 和 similarity_top_k 超参数
chunk_size 和 similarity_top_k 是控制数据检索效率和准确性的两个核心参数。调一调它们,就能在计算效率和检索质量之间找到更好的平衡点。
解决方案二:Rerank 重排序
把检索结果交给大模型之前,先重新排个序,效果提升相当明显。LlamaIndex 的笔记就展示了这一点:
- 直接取前两个节点,结果不够精准。
- 先检索前10个节点,用 CohereRerank 重排序,再取前两个节点,检索精度高出一大截。
参考代码:
import os
from llama_index.postprocessor.cohere_rerank import CohereRerank
api_key = os.environ["COHERE_API_KEY"]
cohere_rerank = CohereRerank(api_key=api_key, top_n=2)
query_engine = index.as_query_engine(
similarity_top_k=10,
node_postprocessors=[cohere_rerank]
)
response = query_engine.query("What did Sam Altman do in this essay?")
—3
痛点3:格式错误
大模型没能按照要求的格式输出,比如表格、列表之类。四种解法供参考。
解决方案一:优化提示词设计
- 明确指出格式要求。
- 简化指令,突出关键术语。
- 提供具体示例。
- 迭代提示词,追加相关问题。
解决方案二:输出解析方法
输出解析可以这样用:
- 为每个提示/查询提供格式化指南。
- 对LLM的输出进行“解析”处理。
以下是用 LangChain 输出解析模块的示例代码(可在 LlamaIndex 中应用):
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader
from llama_index.core.output_parsers import LangchainOutputParser
from llama_index.llms.openai import OpenAI
from langchain.output_parsers import StructuredOutputParser, ResponseSchema
documents = SimpleDirectoryReader("../paul_graham_essay/data").load_data()
index = VectorStoreIndex.from_documents(documents)
response_schemas = [
ResponseSchema(name="Education", description="Describes the author's educational experience/background."),
ResponseSchema(name="Work", description="Describes the author's work experience/background.")
]
lc_output_parser = StructuredOutputParser.from_response_schemas(response_schemas)
output_parser = LangchainOutputParser(lc_output_parser)
llm = OpenAI(output_parser=output_parser)
query_engine = index.as_query_engine(llm=llm)
response = query_engine.query("What are a few things the author did growing up?")
print(str(response))
解决方案三:Pydantic 程序
Pydantic 程序能把输入字符串转换成结构化的 Pydantic 对象。LlamaIndex 提供几种类型:
- :结合文本补全 API 和输出解析,将输入文本转换为用户自定义的结构化对象。
LLM 文本补全 Pydantic 程序
- :利用 LLM 函数调用 API 处理输入文本,转换成用户指定的结构化对象。
LLM 函数调用 Pydantic 程序
- :将输入文本转换成预定义的结构化对象。
预制 Pydantic 程序
一个 OpenAI Pydantic 程序示例:
from pydantic import BaseModel
from typing import List
from llama_index.program.openai import OpenAIPydanticProgram
class Song(BaseModel):
title: str
length_seconds: int
class Album(BaseModel):
name: str
artist: str
songs: List[Song]
prompt_template_str = """
Generate an example album, with an artist and a list of songs.
Using the movie {movie_name} as inspiration.
"""
program = OpenAIPydanticProgram.from_defaults(
output_cls=Album, prompt_template_str=prompt_template_str, verbose=True
)
output = program(movie_name="The Shining", description="Data model for an album.")
解决方案四:OpenAI JSON 模式
通过 OpenAI 的 JSON 模式,将 `response_format` 设为 `{ "type": "json_object" }`,大模型就只能生成可解析为有效 JSON 的字符串。这样输出格式就强制统一了,但注意它并不支持根据特定 schema 做验证。
—4
痛点4:输出不完整
回答没把话说完。虽然部分答复没有错,但需要的信息明明在上下文中,却没能全部给出来。比如问“文档A、B和C中讨论的主要议题是什么?”,如果单独对每份文档查一遍,反而更靠谱。
解决方案一:查询变换
比较类问题在最初的 RAG 方法里表现尤其差。提升推理能力的一个有效方式是引入查询理解层——在向量化查询之前先变换一下。四种常见变换方法:
- :保留原始查询,识别出相关的工具子集,然后指定为合适选项。
路由
- :保留选定的工具,但重新组织查询的表述,以便在同一工具集中应用。
查询重写
- :把查询拆成几个小问题,每个针对不同的工具(由元数据决定)。
子问题分解
- :基于原始查询确定使用的工具,并制定在该工具上运行的具体查询。
ReAct Agent 工具选择
以下是用 HyDE(假设文档嵌入)进行查询重写的示例。给定自然语言查询,首先生成一个假设文档/答案,然后用这个假设文档做嵌入搜索,而不是用原始查询。
documents = SimpleDirectoryReader("../paul_graham_essay/data").load_data()
index = VectorStoreIndex(documents)
query_str = "what did paul graham do after going to RISD"
hyde = HyDEQueryTransform(include_original=True)
query_engine = index.as_query_engine()
query_engine = TransformQueryEngine(query_engine, query_transform=hyde)
response = query_engine.query(query_str)
print(response)
-
- 关于宇宙的好的网名有哪些
- 角色扮演 | 1
- 网名