生产型的检索增强生成(RAG)系统中,发送给大型语言模型(LLM)的提示远不止一个简单的问题。它是一套精心设计的指令,一个小型程序,用于指引LLM在处理检索到的上下文时如何生成回答。生产环境要求对提示工程采取更精细的方法。高级方法将精确控制LLM的输出,提高事实依据,处理复杂情况,并确保提示可靠且易于维护。这些方法对于实现RAG系统生成部分所需的质量、准确性和效率非常重要。为清晰和控制设计提示结构摆脱问题和上下文的简单拼接,生产RAG系统中的高级提示通常采用结构化格式。这种清晰性有助于LLM区分指令、用户查询和检索到的文档,从而产生更可预测和可控的输出。良好结构化提示的主要组成部分包括:角色提示(身份设定): 指示LLM扮演特定角色或身份可以显著影响其语气、风格,甚至是其可能优先处理的特定领域知识(在其训练范围内)。例如:“你是一名专业的法律助理。分析提供的合同条款…”“扮演一个乐于助人的客户支持代理。使用友好和富有同情心的语气…” 这有助于使LLM的回答符合应用程序的要求。明确指令: 清楚界定任务、期望的输出格式、任何限制,以及LLM应如何使用检索到的上下文。模糊的指令会导致多样且通常不理想的结果。避免:“总结一下。”推荐:“根据以下文档,提供一份包含主要观点的简洁三句话摘要。侧重于支持主要论点的论据。”上下文分隔: 使用明确的标记来分隔提示的不同部分,特别是检索到的文档。这可以防止LLM将指令与上下文或用户查询混淆。常见方法包括类似XML的标签(例如,<documents>,</documents>)或Markdown围栏。<system_instructions> 你是一名金融分析师。仅根据<documents>部分内的信息回答问题。 如果信息未找到,请说明“所提供的文档中没有可用信息。” 将你的回答格式化为JSON对象,包含“response”和“confidence_level”(高、中、低)键。 </system_instructions> <documents> [文档1文本] --- [文档2文本] ... </documents> <user_query> 根据这些报告,公司第三季度的收入是多少? </user_query> JSON输出:这种结构使LLM更容易解析输入,也使开发者更容易调试和迭代提示。The following diagram illustrates the typical components of a structured prompt for an LLM in a RAG system.digraph G { rankdir=LR; node [shape=box, style="filled", fillcolor="#e9ecef", fontname="Arial"]; edge [fontname="Arial"]; Prompt [label="完整LLM提示", shape=ellipse, fillcolor="#4263eb", fontcolor="white"]; Instructions [label="系统指令\n(角色、任务、限制、输出格式)", fillcolor="#a5d8ff"]; Context [label="检索到的上下文\n(分隔文档)", fillcolor="#96f2d7"]; Query [label="用户查询\n(已处理)", fillcolor="#ffd8a8"]; Prompt -> Instructions [label="包含"]; Prompt -> Context [label="包含"]; Prompt -> Query [label="包含"]; subgraph cluster_components { label = "提示组成部分"; style = "filled"; color = "#dee2e6"; fontname="Arial"; Instructions; Context; Query; } }一张图表,显示了高级LLM提示的常见构建块,包括系统指令、检索到的上下文和用户查询。增强事实依据并减少幻觉RAG系统的一个主要挑战是确保LLM的输出忠实地基于检索到的文档,而不是虚构,这通常被称为幻觉。高级提示工程提供了多种策略:严格遵守来源: 明确指示LLM的回答仅基于所提供的文档。“仅使用所提供上下文中的信息来回答问题。不要使用任何外部知识。”“如果在提供的文档中找不到答案,请回答‘所提供的文档中不包含回答此问题的信息。’”引用说明: 要求LLM引用其信息的来源,通常通过引用文档ID或特定片段。这不仅鼓励事实依据,也有助于可验证性。“在你的回答中,针对每个重要点,指明信息提取自哪个文档ID(例如,[doc_3])。”负面限制: 告诉LLM不要做什么。这可能会出乎意料地有效。“不要猜测或推断文档中明确说明之外的信息。”“避免对所提供上下文未涵盖的主题进行假设。”置信度评分提示: 要求LLM根据所提供的上下文,自我评估其回答的置信度。虽然不是完美的衡量标准,但它可以是一个指标。“在提供答案后,添加一个从1到5的‘confidence_score’,其中5表示根据文档高度自信,1表示低自信。”这些技术结合使用时,可以显著提高RAG系统输出的可信度。控制输出格式和结构为了顺畅集成到应用程序中,LLM的输出通常需要遵守特定格式。提示是实现这一目标的有效方式:请求结构化输出(例如,JSON,XML): 许多现代LLM在明确提示后可以生成JSON等结构化格式的文本。这对于下游的程序化使用很有价值。示例指令: 将你的回答作为JSON对象提供。JSON对象必须包含以下键: - "summary":对发现的简要总结。 - "key_entities":提及的重要实体列表。 - "source_documents":用于形成答案的文档ID列表。指定长度和细节: 指导LLM关于期望的长度或细节程度。“提供一份不超过五条建议的要点列表。”“生成一份大约200字的详细解释。” 请注意,LLM在精确字数方面可能不准确,但此类指令提供了明确的指引。思维链(CoT)和推理步骤: 尽管CoT通常与改善通用LLM任务中的推理能力相关联,但其某些方面可以适用于RAG。例如,你可以指示LLM首先从提供的上下文中提取与查询相关的句子或事实,然后仅基于这些提取的事实合成答案。这可以使生成过程更透明、更有依据。分阶段推理指令: 1. 从提供的文档中识别并列出所有与回答用户问题直接相关的句子。在每个句子前加上其文档ID。 2. *仅*基于步骤1中识别出的句子,给出对用户问题的全面回答。即使中间的“推理步骤”不显示给最终用户,这种结构化方法也可以提高最终答案的质量以及对源材料的忠实度。处理多文档和复杂信息生产RAG系统通常会检索多个文档,这些文档可能包含补充、冗余甚至矛盾的信息。提示可以指导LLM应对这种复杂性:综合指令: 当多个文档共同形成答案时,指示LLM综合信息。“从所有提供的文档中综合出一致的答案,涵盖用户查询的所有方面。”处理矛盾信息: 提供处理差异的策略。“如果在文档中发现矛盾信息,请在答案中说明冲突并引用不同来源。如果可能,根据文档属性(如果提供)指出哪些信息看起来更可信。”更高级的方法可能涉及要求LLM呈现矛盾信息的两个方面。信息优先级(谨慎使用): 如果你的检索或重排序阶段提供了关于文档重要性的信号(例如,时效性、来源权威性),你可以在提示中巧妙地暗示这一点。然而,过度依赖LLM仅从提示中推断复杂的优先级规则可能不可靠;明确的重排序通常更好。“在构建答案时,如果有来自标记为‘官方报告’的文档信息,请优先使用。”提示的迭代开发、模板化和版本管理提示并非一个“设置后就无需管”的组件。它们需要迭代开发、测试和优化,就像任何其他软件一样。提示模板: 使用模板引擎(例如,Python的f-strings,Jinja2,Handlebars)来动态构建提示。这可以将静态指令逻辑与动态数据(查询、上下文)分离。# 示例Python f-string模板 def create_rag_prompt(user_query, retrieved_docs_text, instructions): return f""" {instructions} <retrieved_documents> {retrieved_docs_text} </retrieved_documents> 用户查询: {user_query} 回答: """提示版本管理: 将你的提示模板视为代码。将它们存储在版本控制系统(如Git)中。这允许你跟踪更改、恢复到以前的版本,并管理不同的提示版本以进行A/B测试或特定使用场景。系统化评估: 不要依赖轶事证据来判断提示的有效性。将提示更改与你的RAG评估框架结合(如第6章所述)。衡量提示修改对事实一致性、相关性和任务完成率等指标的影响。措辞上的微小改变有时会产生显著影响。复杂任务的提示链: 对于高度复杂的任务,可以考虑将其分解为一系列LLM调用,每个调用都带有专门的提示。例如,一个提示可能从上下文中提取必要的事实,而随后的提示则可能使用这些事实来生成结构化报告。这种模块化方法可以提高控制和性能,但会增加系统架构的复杂性。高级生产考量还有其他几个因素对于生产级提示很重要:Token效率: LLM API调用通常按Token计费。提示应尽可能简洁且仍有效。过度冗长的指令或冗余的措辞会增加成本和延迟。定期审查提示以寻找在不牺牲性能的情况下简化它们的机会。输入多样性的鲁棒性: 使用广泛的用户查询(包括模糊或措辞不当的查询)和不同类型的检索上下文来测试你的提示。适用于一种输入类型的提示可能不适用于另一种。目标是泛化能力强的提示。处理上下文中的边缘情况: 考虑当检索到的上下文为空、非常短、嘈杂或无关紧要时,你的提示如何指导LLM。例如,你的指令应涵盖未找到相关文档的场景。安全:缓解提示注入风险: 如果用户提供的文本未经适当清理或分隔就直接整合到LLM提示结构中,可能会造成提示注入等漏洞。在这种情况下,用户可能通过精心制作恶意查询来尝试覆盖你的系统指令。虽然完整讨论在第1章“生产RAG中的安全考量”中,但请确保用户输入明确分隔,并且你的系统指令具有权威性。例如,指示LLM始终将<user_query_tag>...</user_query_tag>中的文本视为用户输入,仅此而已。掌握高级提示工程是一个持续的实验和优化过程。通过应用这些方法,你可以显著增强RAG系统生成器生成准确、可靠、格式良好且符合应用程序在生产环境特定需求的能力。对指令的精心编排,对于发挥LLM在RAG流程中的全部潜力非常重要。