共计 3698 个字符,预计需要花费 10 分钟才能阅读完成。
背景痛点:RAG 系统中的提示词困境
在构建检索增强生成(RAG)系统时,提示词设计不当会导致两个核心问题:

-
检索噪声放大 :当用户查询意图模糊时,传统静态提示词(如固定前缀的
请根据以下上下文回答)会强制将无关检索结果注入生成阶段,导致答案包含无关信息。例如医疗场景中,检索到相似但不同病症的文档时,生成的回答可能出现危险误导。 -
生成内容偏离意图 :当检索结果与生成模型的解码策略不匹配时,模型会过度依赖自身参数化知识。比如法律咨询场景中,若未在提示词中明确限定
仅依据提供条文回答,模型可能生成与最新法规冲突的内容。
技术方案:动态提示词与语义对齐
静态 vs 动态提示词性能对比
-
静态提示词 示例:
请参考以下文档回答问题:{{context}} 问题:{{question}}缺陷:固定模板无法根据检索结果质量调整生成策略,当
{{context}}相关性低时,模型表现急剧下降。 -
动态提示词 改进方案:
def build_prompt(contexts, question): relevant_ratio = calculate_relevance(contexts, question) if relevant_ratio < 0.3: return f"当前未找到充分依据,请谨慎回答:{question}" else: return f"请严格根据以下证据回答(可信度{relevant_ratio:.0%}):{contexts}\n 问题:{question}"优势:根据检索质量动态调整生成约束条件,降低低质量检索的负面影响。
基于向量相似度的上下文过滤
关键算法步骤:
- 对检索到的 Top- K 文档,计算每段文本与问题的余弦相似度
- 采用 MMR(Maximal Marginal Relevance)重排序平衡相关性与多样性
- 设置动态阈值过滤低相似度片段(建议初始阈值 0.65)
from sklearn.metrics.pairwise import cosine_similarity
def filter_contexts(query_embedding, doc_embeddings, top_k=5, diversity=0.5):
# 计算初始相关性
sim_scores = cosine_similarity([query_embedding], doc_embeddings)[0]
# MMR 重排序
selected = []
while len(selected) < top_k:
mmr_scores = []
for idx in range(len(doc_embeddings)):
if idx not in selected:
rel = sim_scores[idx]
div = max([cosine_similarity([doc_embeddings[idx]],
[doc_embeddings[s]])[0][0] for s in selected] or [0])
mmr_scores.append(rel - diversity * div)
next_idx = np.argmax(mmr_scores)
selected.append(next_idx)
return [docs[i] for i in selected if sim_scores[i] > 0.65]
多轮对话提示词模板设计
支持对话历史的动态注入方案:
def build_multi_turn_prompt(history, current_question):
# 历史对话压缩(避免超过模型 token 限制)compressed_history = summarize_dialog(history)
return f""" 以下是对话背景:{compressed_history}
当前问题:{current_question}
回答时请注意:1. 若问题涉及之前讨论的内容,请保持立场一致
2. 对新问题,请基于最新检索结果回答
3. 如果信息不足,主动要求澄清 """
代码实现:生产级组件开发
动态提示词组装模块(含异常处理)
class DynamicPromptBuilder:
def __init__(self, min_relevance=0.6):
self.min_relevance = min_relevance # 可调参数:最低相关性阈值
def __call__(self, query, contexts):
try:
valid_ctx = [c for c in contexts
if c.relevance_score >= self.min_relevance]
if not valid_ctx:
return {"prompt": f"无法找到可靠依据,请核实问题:{query}",
"fallback": True}
# 动态选择模板
if len(valid_ctx) > 3:
prompt = f"综合以下 {len(valid_ctx)} 条证据回答:{valid_ctx}\n 问题:{query}"
else:
prompt = f"根据关键证据回答:{valid_ctx}\n 问题:{query}"
return {"prompt": prompt, "fallback": False}
except Exception as e:
logging.error(f"Prompt build failed: {str(e)}")
return {"prompt": "系统处理异常,请稍后再试", "fallback": True}
LangChain 与 LlamaIndex 集成示例
from langchain.chains import RetrievalQA
from llama_index import VectorStoreIndex
# 构建混合检索器
index = VectorStoreIndex.load("legal_index")
retriever = index.as_retriever(
similarity_top_k=10,
node_postprocessors=[SimilarityPostprocessor(min_score=0.7),
MMRPostprocessor(diversity=0.4)
]
)
# 动态提示词链
qa_chain = RetrievalQA.from_chain_type(
llm=llm,
chain_type="stuff",
retriever=retriever,
chain_type_kwargs={
"prompt": CustomPromptTemplate(template="""{context_str}\n\n 基于上述内容回答:{query}"
"若信息不足,请说明需要补充哪些具体细节""",
input_variables=["context_str", "query"]
)
}
)
生产环境考量
延迟与质量的平衡策略
- 分级检索:
- 第一级:BM25 快速召回(<100ms)
- 第二级:向量精排(可设置超时 300ms)
-
第三级:模型自生成(作为 fallback)
-
缓存设计:
- 对高频问题缓存完整生成结果(TTL=1h)
- 对相似问题缓存检索结果(使用 MinHash 去重)
对话状态幂等性设计
class ConversationState:
def __init__(self):
self.session_id = str(uuid.uuid4())
self._history = []
def add_utterance(self, user_input, system_response):
# 使用 MD5 摘要实现历史记录幂等
input_hash = hashlib.md5(user_input.encode()).hexdigest()
if self._history and self._history[-1]["input_hash"] == input_hash:
return False
self._history.append({
"input": user_input,
"response": system_response,
"input_hash": input_hash
})
return True
避坑指南
避免过度依赖检索的 3 条规则
- 可信度阈值:当所有检索结果相似度 <0.5 时,触发人工审核流程
- 矛盾检测:对生成内容与检索结果的关键实体进行一致性验证
- 衰减机制:对连续 3 次低质量检索的 query,自动触发检索策略调整
调试工具推荐
- RAG 可视化工具:
- LangSmith:追踪检索 - 生成全链路
-
Weights & Biases:记录向量相似度分布
-
Prompt 版本控制:
- 使用 DVC 管理不同提示词变体的实验数据
- 对生产环境提示词进行 A / B 测试(至少 200 次请求 / 版本)
开放问题与延伸思考
- 如何设计领域自适应的提示词?例如医疗场景可能需要强调
谨慎推断,而客服场景需要简洁明确 - 当用户提问包含隐含假设时(如
为什么 XX 政策不合理),如何通过提示词引导模型识别潜在偏见? - 对于超长文档(如 100 页 PDF),怎样的分块策略能最优平衡检索效率与上下文完整性?
建议读者尝试:
– 在相同检索结果下,对比固定模板与动态提示词的生成质量差异
– 调整 MMR 的 diversity 参数(0.3~0.7 范围),观察回答多样性与准确性的 trade-off
正文完
