简介
检索增强生成 (RAG) 是一种方法,使语言模型 (LLM) 能够访问广泛的知识库、在其中搜索相关段落并利用这些信息生成精确的响应。
RAG 使 LLM 能够通过利用上下文学习 (ICL) 来动态地利用实时知识,即使最初没有接受过数据训练。
然而,这种方法使得建立和完善 RAG 管道变得更加复杂。
DSPy 有一种无缝的方法来设置 RAG 提示管道。
下面显示了 DSPy RAG 应用程序序列……
DSPy RAG 程序
本笔记本使用了 GPT-3.5(特别是 gpt-3.5-turbo)和 ColBERTv2 retriever。
ColBERTv2 retriever 托管在一个免费服务器上,其搜索索引来自维基百科 2017 年的 “摘要”,其中包含 2017 年转储的文章介绍段落。
下面是在 DSPy 设置中如何配置语言模型和检索器模型。
import dspy
turbo = dspy.OpenAI(model='gpt-3.5-turbo')
colbertv2_wiki17_abstracts = dspy.ColBERTv2(url='http://20.102.90.50:2017/wiki17_abstracts')
dspy.settings.configure(lm=turbo, rm=colbertv2_wiki17_abstracts)
然后加载测试数据:
from dspy.datasets import HotPotQA
# Load the dataset.
dataset = HotPotQA(train_seed=1, train_size=20, eval_seed=2023, dev_size=50, test_size=0)
# Tell DSPy that the 'question' field is the input. Any other fields are labels and/or metadata.
trainset = [x.with_inputs('question') for x in dataset.train]
devset = [x.with_inputs('question') for x in dataset.dev]
len(trainset), len(devset)
然后创建签名......你可以看到上下文、输入和输出字段是如何定义的。
class GenerateAnswer(dspy.Signature):
"""Answer questions with short factoid answers."""
context = dspy.InputField(desc="may contain relevant facts")
question = dspy.InputField()
answer = dspy.OutputField(desc="often between 1 and 5 words")
RAG 管道是作为 DSPy 模块创建的,需要两个方法:
class RAG(dspy.Module):
def __init__(self, num_passages=3):
super().__init__()
self.retrieve = dspy.Retrieve(k=num_passages)
self.generate_answer = dspy.ChainOfThought(GenerateAnswer)
def forward(self, question):
context = self.retrieve(question).passages
prediction = self.generate_answer(context=context, question=question)
return dspy.Prediction(context=context, answer=prediction.answer)
下面是一个训练数据示例:
Example({'question': 'At My Window was released by which American singer-songwriter?',
'answer': 'John Townes Van Zandt'})
(input_keys={'question'}),
Example({'question': 'which American actor was Candace Kita guest starred with ',
'answer': 'Bill Murray'})
(input_keys={'question'}),
Example({'question': 'Which of these publications was most recently published, Who Put the Bomp or Self?',
'answer': 'Self'})
(input_keys={'question'}),
执行程序
下面是带着问题执行的程序...
# Ask any question you like to this simple RAG program.
my_question = "What castle did David Gregory inherit?"
# Get the prediction. This contains `pred.context` and `pred.answer`.
pred = compiled_rag(my_question)
# Print the contexts and the answer.
print(f"Question: {my_question}")
print(f"Predicted Answer: {pred.answer}")
print(f"Retrieved Contexts (truncated): {[c[:200] + '...' for c in pred.context]}")
回复是
Question: What castle did David Gregory inherit?
Predicted Answer: Kinnairdy Castle
Retrieved Contexts (truncated): ['David Gregory (physician) | David Gregory (20 December 1625 – 1720) was a Scottish physician and inventor. His surname is sometimes spelt as Gregorie, the original Scottish spelling. He inherited Kinn...', 'Gregory Tarchaneiotes | Gregory Tarchaneiotes (Greek: Γρηγόριος Ταρχανειώτης , Italian: "Gregorio Tracanioto" or "Tracamoto" ) was a "protospatharius" and the long-reigning catepan of Italy from 998 t...', 'David Gregory (mathematician) | David Gregory (originally spelt Gregorie) FRS (? 1659 – 10 October 1708) was a Scottish mathematician and astronomer. He was professor of mathematics at the University ...']
总结
关于 DSPy 的实现,有几点初步看法: