98 提示工程在RAG中的应用:优化LlamaIndex工作流程

部署运行你感兴趣的模型镜像

提示工程在RAG中的应用:优化LlamaIndex工作流程

在处理大型语言模型(LLM)时,优化提示(prompt)是提升输出质量的关键。本文将介绍如何在LlamaIndex的RAG(检索增强生成)工作流程中应用各种提示技巧,帮助你自定义LlamaIndex管道。

前置知识

在深入学习这些提示技巧之前,你需要了解以下基础知识:

  • Python编程:熟悉Python语言及其常用库。
  • 自然语言处理(NLP):了解基本的NLP概念和技术。
  • 大型语言模型(LLM):了解LLM的基本工作原理和常见应用。

安装与配置

首先,我们需要安装必要的库,并配置OpenAI API密钥。

%pip install llama-index-llms-openai
%pip install llama-index-readers-file pymupdf
!pip install llama-index

import os
import openai

os.environ["OPENAI_API_KEY"] = "sk-..."
openai.api_key = os.environ["OPENAI_API_KEY"]

设置

import logging
import sys

logging.basicConfig(stream=sys.stdout, level=logging.INFO)
logging.getLogger().addHandler(logging.StreamHandler(stream=sys.stdout))

from llama_index.core import VectorStoreIndex
from llama_index.core import PromptTemplate
from IPython.display import Markdown, display

加载数据

我们将从arXiv下载一篇论文并加载到向量存储中。

!mkdir data
!wget --user-agent "Mozilla" "https://arxiv.org/pdf/2307.09288.pdf" -O "data/llama2.pdf"

from pathlib import Path
from llama_index.readers.file import PyMuPDFReader

loader = PyMuPDFReader()
documents = loader.load(file_path="./data/llama2.pdf")

加载到向量存储

from llama_index.core import VectorStoreIndex
from llama_index.llms.openai import OpenAI

gpt35_llm = OpenAI(model="gpt-3.5-turbo")
gpt4_llm = OpenAI(model="gpt-4")

index = VectorStoreIndex.from_documents(documents)

设置查询引擎 / 检索器

query_str = "What are the potential risks associated with the use of Llama 2 as mentioned in the context?"
query_engine = index.as_query_engine(similarity_top_k=2, llm=gpt35_llm)

# 用于测试
vector_retriever = index.as_retriever(similarity_top_k=2)

response = query_engine.query(query_str)
print(str(response))

查看/自定义提示

首先,让我们看看查询引擎的提示,并了解如何自定义它。

查看提示

# 定义提示查看函数
def display_prompt_dict(prompts_dict):
    for k, p in prompts_dict.items():
        text_md = f"**Prompt Key**: {k}<br>" f"**Text:** <br>"
        display(Markdown(text_md))
        print(p.get_template())
        display(Markdown("<br><br>"))

prompts_dict = query_engine.get_prompts()
display_prompt_dict(prompts_dict)

自定义提示

如果我们想做一些不同于标准问答提示的事情呢?让我们尝试使用LangchainHub中的RAG提示。

# 为此,你需要使用langchain对象

from langchain import hub

langchain_prompt = hub.pull("rlm/rag-prompt")

# 注意:提示中的模板变量与查询引擎中的合成器预期的变量不同
# 提示使用context和question,
# 我们期望context_str和query_str

# 这没有问题!让我们添加模板变量映射来映射变量。我们使用LangchainPromptTemplate来映射到LangChain提示。

from llama_index.core.prompts import LangchainPromptTemplate

lc_prompt_tmpl = LangchainPromptTemplate(
    template=langchain_prompt,
    template_var_mappings={"query_str": "question", "context_str": "context"},
)

query_engine.update_prompts(
    {"response_synthesizer:text_qa_template": lc_prompt_tmpl}
)

prompts_dict = query_engine.get_prompts()
display_prompt_dict(prompts_dict)

尝试一下

让我们重新运行查询引擎。

response = query_engine.query(query_str)
print(str(response))

添加少量示例

让我们尝试在提示中添加少量示例,这些示例可以根据查询动态加载!

from llama_index.core.schema import TextNode

few_shot_nodes = []
for line in open("../llama2_qa_citation_events.jsonl", "r"):
    few_shot_nodes.append(TextNode(text=line))

few_shot_index = VectorStoreIndex(few_shot_nodes)
few_shot_retriever = few_shot_index.as_retriever(similarity_top_k=2)

import json

def few_shot_examples_fn(**kwargs):
    query_str = kwargs["query_str"]
    retrieved_nodes = few_shot_retriever.retrieve(query_str)
    # 遍历每个节点,获取json对象

    result_strs = []
    for n in retrieved_nodes:
        raw_dict = json.loads(n.get_content())
        query = raw_dict["query"]
        response_dict = json.loads(raw_dict["response"])
        result_str = f"""\
Query: {query}
Response: {response_dict}"""
        result_strs.append(result_str)
    return "\n\n".join(result_strs)

# 编写带有函数的提示模板
qa_prompt_tmpl_str = """\
Context information is below.
---------------------
{context_str}
---------------------
Given the context information and not prior knowledge, \
answer the query asking about citations over different topics.
Please provide your answer in the form of a structured JSON format containing \
a list of authors as the citations. Some examples are given below.

{few_shot_examples}

Query: {query_str}
Answer: \
"""

qa_prompt_tmpl = PromptTemplate(
    qa_prompt_tmpl_str,
    function_mappings={"few_shot_examples": few_shot_examples_fn},
)

citation_query_str = "Which citations are mentioned in the section on Safety RLHF?"

# 让我们看看带有少量示例函数的格式化提示是什么样子的。(为了简洁起见,我们填充了测试上下文)

print(
    qa_prompt_tmpl.format(
        query_str=citation_query_str, context_str="test_context"
    )
)

query_engine.update_prompts(
    {"response_synthesizer:text_qa_template": qa_prompt_tmpl}
)

display_prompt_dict(query_engine.get_prompts())

response = query_engine.query(citation_query_str)
print(str(response))

上下文转换 - PII示例

我们还可以在提示变量中动态添加上下文转换函数。在这个示例中,我们展示了如何在将context_str输入到上下文窗口之前处理它——具体来说,是屏蔽PII(个人身份信息),以缓解数据隐私/安全方面的担忧。

from llama_index.core.postprocessor import (
    NERPIINodePostprocessor,
    SentenceEmbeddingOptimizer,
)
from llama_index.core import QueryBundle
from llama_index.core.schema import NodeWithScore, TextNode

pii_processor = NERPIINodePostprocessor(llm=gpt4_llm)

def filter_pii_fn(**kwargs):
    # 运行优化器
    query_bundle = QueryBundle(query_str=kwargs["query_str"])

    new_nodes = pii_processor.postprocess_nodes(
        [NodeWithScore(node=TextNode(text=kwargs["context_str"]))],
        query_bundle=query_bundle,
    )
    new_node = new_nodes[0]
    return new_node.get_content()

qa_prompt_tmpl_str = (
    "Context information is below.\n"
    "---------------------\n"
    "{context_str}\n"
    "---------------------\n"
    "Given the context information and not prior knowledge, "
    "answer the query.\n"
    "Query: {query_str}\n"
    "Answer: "
)

qa_prompt_tmpl = PromptTemplate(
    qa_prompt_tmpl_str, function_mappings={"context_str": filter_pii_fn}
)

query_engine.update_prompts(
    {"response_synthesizer:text_qa_template": qa_prompt_tmpl}
)

# 查看提示
retrieved_nodes = vector_retriever.retrieve(query_str)
context_str = "\n\n".join([n.get_content() for n in retrieved_nodes])
print(qa_prompt_tmpl.format(query_str=query_str, context_str=context_str))

response = query_engine.query(query_str)
print(str(response))

总结

通过使用提示工程技巧,你可以在LlamaIndex的RAG工作流程中显著提升输出质量。无论是自定义提示、添加少量示例还是动态上下文转换,这些技巧都能帮助你更好地控制和优化LLM的输出。希望本文能为你提供有价值的参考,让你在实际应用中取得更好的效果。

参考文献:

扩展阅读:

希望这篇博客能为你带来启发和帮助,让我们在编程的世界里,更加高效地驾驭数据和信息!

您可能感兴趣的与本文相关的镜像

Llama Factory

Llama Factory

模型微调
LLama-Factory

LLaMA Factory 是一个简单易用且高效的大型语言模型(Large Language Model)训练与微调平台。通过 LLaMA Factory,可以在无需编写任何代码的前提下,在本地完成上百种预训练模型的微调

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

需要重新演唱

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值