(20-3-02)基于《哈利·波特》系列图书内容的问答系统:LangChain多文档检索器(02)Prompt Template(提示模板)+Retriever Chain(检索链)+格式化输出

8.5.5  Prompt Template(提示模板)

在自然语言处理(NLP)和聊天机器人的设计中,"Prompt Template"(提示模板)是一个预定义的文本格式,用于引导或激发大型语言模型(LLM)生成特定的回答或输出。下面的代码定义了一个用于与语言模型交互的提示模板(prompt template),并且创建了一个PromptTemplate对象,最后还演示了如何使用这个提示模板与一个语言模型链(LLMChain)一起工作。

prompt_template = """
Don't try to make up an answer, if you don't know just say that you don't know.
Answer in the same language the question was asked.
Use only the following pieces of context to answer the question at the end.

{context}

Question: {question}
Answer:"""


PROMPT = PromptTemplate(
    template = prompt_template, 
    input_variables = ["context", "question"]
)
# llm_chain = LLMChain(prompt=PROMPT, llm=llm)

上述代码的目的是创建一个结构化的方式来与语言模型交互,使得模型能够根据给定的上下文和问题生成答案。这种方式可以用于聊天机器人、问答系统或其他需要从文本中提取信息的场景。通过使用提示模板,可以确保模型接收到一致的、格式良好的输入,从而提高其生成答案的质量和相关性。

8.5.6  Retriever Chain(检索链)

在自然语言处理(NLP)和在LangChain中,Retriever Chain(检索链)结合了文本检索和生成答案的步骤,以提供一个完整的问答(question-answering, QA)解决方案。通过这种方式,检索链结合了精确的检索能力和语言模型的生成能力,提供了一种强大的方法来构建能够理解和回答问题的智能系统。

(1)下面代码使用LangChain构建一个检索问答(RetrievalQA)系统,该系统结合了向量数据库检索和大型语言模型(LLM)生成答案的能力。

retriever = vectordb.as_retriever(search_kwargs = {"k": CFG.k, "search_type" : "similarity"})

qa_chain = RetrievalQA.from_chain_type(
    llm = llm,
    chain_type = "stuff", # map_reduce, map_rerank, stuff, refine
    retriever = retriever, 
    chain_type_kwargs = {"prompt": PROMPT},
    return_source_documents = True,
    verbose = False
)

通过上述代码配置了一个问答系统,首先使用FAISS向量数据库检索与用户查询相关的文档,然后利用大型语言模型生成答案。这个系统可以用于构建聊天机器人、问答接口或其他需要自动文本理解和生成的应用程序。

(2)下面的代码使用了一个名为 max_marginal_relevance_search 的最大边际相关性搜索方法,它是向量数据库 vectordb 的一部分,用于执行一种特定的检索任务,旨在找到与给定问题最相关的文档或文档段落。

question = "Which are Hagrid's favorite animals?"
vectordb.max_marginal_relevance_search(question, k = CFG.k)

执行后会输出:

[Document(page_content='would warn Hagrid myself, but I am  banished — it would be unwise \nfor me to go too near the forest now — Hagrid has troubles enough, \nwithout a centaurs’ battle.” \n“But — what’s Hagrid attempting to do?” said Harry nervously. \nFirenze looked at Harry impassively. \n“Hagrid has recently rendered me a great service,” said Firenze,', metadata={'source': '/kaggle/input/harry-potter-books-in-pdf-1-7/HP books/Harry Potter - Book 5 - The Order of the Phoenix.pdf', 'page': 619}),

 Document(page_content="wisely. Behind him, Buckbeak spat a few ferret bones onto Hagrid'spillow.", metadata={'source': '/kaggle/input/harry-potter-books-in-pdf-1-7/HP books/Harry Potter - Book 3 - The Prisoner of Azkaban.pdf', 'page': 228}),

 Document(page_content='says Draco Malfoy, a fourth-year student. “We all hate Hagrid, but we’re just too scared to say \nanything.” \nHagrid has no intention of ceasing his campaign \nof intimidation, however. In conversation with a \nDaily Prophet  reporter last month, he admitted \nbreeding creatures he has dubbed “Blast-Ended \nSkrewts,” highly dangerous crosses between manti-\ncores and fire-crabs. The creation of new breeds of magical creature is, of course, an activity usually \nclosely observed by the Department for the Regu-\nlation and Control of Magical Creatures. Hagrid, however, considers himself to be above such petty \nrestrictions.', metadata={'source': '/kaggle/input/harry-potter-books-in-pdf-1-7/HP books/Harry Potter - Book 4 - The Goblet of Fire.pdf', 'page': 453}),

 Document(page_content='smile from behind his bushy beard. Hagrid would have liked', metadata={'source': '/kaggle/input/harry-potter-books-in-pdf-1-7/HP books/Harry Potter - Book 4 - The Goblet of Fire.pdf', 'page': 212}),

 Document(page_content='“Aragog,” said Harry and Hagrid together.', metadata={'source': '/kaggle/input/harry-potter-books-in-pdf-1-7/HP books/Harry Potter - Book 6 - The Half-Blood Prince.pdf', 'page': 544}),

 Document(page_content='Must-Not-Be-Named were killed by Aurors work-\ning against the Dark Side, Fridwulfa was not \namong them. It is possible she escaped to one of \nthe giant communities still existing in foreign \nmountain ranges. If his antics during Care of Mag-\nical Creatures lessons are any guide, however, Frid-\nwulfa’s son appears to have inherited her brutal nature. \nIn a bizarre twist, Hagrid is reputed to have \ndeveloped a close friend ship with the boy who \nbrought around You-Know-Who’s fall from \npower — thereby driving Hagrid’s own mother,', metadata={'source': '/kaggle/input/harry-potter-books-in-pdf-1-7/HP books/Harry Potter - Book 4 - The Goblet of Fire.pdf', 'page': 454})]

最大边际相关性搜索特别适用于问答系统,因为它不仅寻找最相关的信息,还确保了检索结果的多样性,这有助于提供更全面的答案。在实际应用中,这种方法可以帮助系统生成包含多个相关信息点的综合回答,而不是仅仅重复相同的信息。

(3)在下面的代码中,vectordb.similarity_search(question, k = CFG.k)行执行了一个相似性搜索,旨在从向量数据库 vectordb 中检索与查询问题 "Which are Hagrid's favorite animals?" 最相关的文档或文档段落。

question = "Which are Hagrid's favorite animals?"
vectordb.similarity_search(question, k = CFG.k)

执行后会输出:

[Document(page_content='would warn Hagrid myself, but I am  banished — it would be unwise \nfor me to go too near the forest now — Hagrid has troubles enough, \nwithout a centaurs’ battle.” \n“But — what’s Hagrid attempting to do?” said Harry nervously. \nFirenze looked at Harry impassively. \n“Hagrid has recently rendered me a great service,” said Firenze,', metadata={'source': '/kaggle/input/harry-potter-books-in-pdf-1-7/HP books/Harry Potter - Book 5 - The Order of the Phoenix.pdf', 'page': 619}),

 Document(page_content="Harry could sort of see what Hagrid meant. Once you got over the first\nshock of seeing something that was, half horse, half bird, you startedto appreciate the hippogriffs' gleaming coats, changing smoothly fromfeather to hair, each of them a different color: stormy gray, bronze,", metadata={'source': '/kaggle/input/harry-potter-books-in-pdf-1-7/HP books/Harry Potter - Book 3 - The Prisoner of Azkaban.pdf', 'page': 91}),

 Document(page_content='CHAPTER  THIRTEEN \n\x91 198 \x91 nothing better than a pet drag on, as Harry, Ron, and Hermione \nknew only too well — he had owned one for a brief period during \ntheir first year, a vicious Norweg ian Ridgeback by the name of \nNorbert. Hagrid simply loved monstrous creatures, the more \nlethal, the better. \n“Well, at least the skrewts are sma ll,” said Ron as they made their \nway back up to the castle for lunch an hour later. \n“They are now, ” said Hermione in an exasperated voice, “but \nonce Hagrid’s found out what they eat, I expect they’ll be six feet \nlong.” \n“Well, that won’t matter if they turn out to cure seasickness or \nsomething, will it?” said Ro n, grinning slyly at her. \n“You know perfectly we ll I only said that to shut Malfoy up,”', metadata={'source': '/kaggle/input/harry-potter-books-in-pdf-1-7/HP books/Harry Potter - Book 4 - The Goblet of Fire.pdf', 'page': 213}),

 Document(page_content='“What are they, Hagrid?” asked Harry, trying to sound \ninterested rather than revolted, but putting down his \nrock cake all the same. \n“Jus’ giant grubs,” said Hagrid. \n“And they grow into … ?” said Ron, looking \napprehensive. \n“They won’ grow inter nuthin’,” said Hagrid. “I got ’em \nter feed ter Aragog.” \nAnd without warning, he burst into tears. \n“Hagrid!” cried Hermione, leaping up, hurrying \naround the table the long way to avoid the barrel of \nmaggots, and putting an arm around his shaking \nshoulders. “What is it?”', metadata={'source': '/kaggle/input/harry-potter-books-in-pdf-1-7/HP books/Harry Potter - Book 6 - The Half-Blood Prince.pdf', 'page': 256}),

 Document(page_content='“Aragog,” said Harry and Hagrid together.', metadata={'source': '/kaggle/input/harry-potter-books-in-pdf-1-7/HP books/Harry Potter - Book 6 - The Half-Blood Prince.pdf', 'page': 544}),

 Document(page_content='Hagrid stooped down, bestowed upon Harry a cursory and rib-\n618', metadata={'source': '/kaggle/input/harry-potter-books-in-pdf-1-7/HP books/Harry Potter - Book 7 - The Deathly Hallows.pdf', 'page': 625})]

请注意,具体的输出结果和搜索逻辑会依赖于 vectordb 对象的实现细节,以及FAISS向量数据库的配置。此外,为了执行这个搜索,需要确保向量数据库已经被正确加载,并且包含与《哈利·波特》系列相关的文本的嵌入。

8.5.7  格式化输出

格式化输出对于提供高质量的用户体验至关重要,尤其是在处理文本密集型的应用,如聊天机器人、问答系统或任何形式的自动文本生成服务时。

(1)下面这段代码定义了两个函数,用于处理和格式化大型语言模型(LLM)的输出,以及添加引用来源。函数wrap_text_preserve_newlines负责将文本内容自动换行,以适应特定的宽度,同时保留原有的换行。函数process_llm_response则用于进一步处理LLM的输出,不仅包括自动换行,还包括添加引用来源,使得最终的输出更加完整和规范。

def wrap_text_preserve_newlines(text, width=700):
    # 根据换行符将输入文本分割成行
    lines = text.split('\n')

    # 对每一行分别进行自动换行处理
    wrapped_lines = [textwrap.fill(line, width=width) for line in lines]

    # 使用换行符将换行后的行重新组合在一起
    wrapped_text = '\n'.join(wrapped_lines)

    return wrapped_text

def process_llm_response(llm_response):
    # 使用上一个函数对LLM的响应结果进行自动换行处理
    ans = wrap_text_preserve_newlines(llm_response['result'])
    
    # 从LLM响应中提取并格式化来源文档的信息
    sources_used = ' \n'.join(
        [
            # 获取每个来源的PDF文件名(不包含后缀)和页码
            source.metadata['source'].split('/')[-1][:-4] + ' - page: ' + str(source.metadata['page'])
            for source in llm_response['source_documents']
        ]
    )
    
    # 将格式化后的文本和来源信息拼接起来
    ans = ans + '\n\nSources: \n' + sources_used
    return ans

上述两个函数共同工作,以确保LLM的输出不仅在视觉上更加易读,而且还清楚地指明了信息的来源,增加了回答的可信度和透明度。这对于构建用户信任和提供高质量用户体验的问答系统非常重要。

(2)定义函数 llm_ans ,用于处理用户查询,生成模型的回答,并计算整个处理过程所需的时间。通过这个函数,不仅能够得到查询的答案,还能了解到生成这个答案所需的时间,这对于评估系统性能和了解处理延迟非常有用。

def llm_ans(query):
    # 记录开始时间
    start = time.time()
    
    # 使用qa_chain(问答链)处理查询,并获取响应
    llm_response = qa_chain.invoke(query)
    # 处理模型的响应,包括格式化文本和添加引用来源
    ans = process_llm_response(llm_response)
    
    # 记录结束时间
    end = time.time()

    # 计算经过的时间(秒),并转换为整数
    time_elapsed = int(round(end - start, 0))
    # 格式化经过时间的字符串表示
    time_elapsed_str = f'\n\nTime elapsed: {time_elapsed} s'
    # 将经过时间的信息追加到答案的末尾,并返回最终答案
    return ans + time_elapsed_str

  • 10
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

码农三叔

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

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

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

打赏作者

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

抵扣说明:

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

余额充值