人类反馈(HF)不仅对生成式 AI 有用,而且是必不可少的,特别是在涉及 RAG 的模型时。生成式 AI 模型在训练期间使用来自各种文档的数据集中的信息。训练 AI 模型的数据固定在模型的参数中;除非再次训练,否则无法更改这些数据。然而,在基于检索的文本和多模态数据集的世界中,有一些信息是我们可以看到并调整的,这就是 HF 的用武之地。通过对 AI 模型从其数据集中提取的内容提供反馈,HF 可以直接影响其未来响应的质量。参与这个过程,使人类成为 RAG 发展的积极参与者,并为 AI 项目增加了新的维度:自适应 RAG。
到目前为止,我们已经探索并实现了朴素、进阶和模块化 RAG。现在,我们将自适应 RAG 添加到我们的生成式 AI 工具箱中。我们知道,即使是拥有最佳指标的最好的生成式 AI 系统,如果不能满足用户的需求,也无法让不满意的用户相信它是有用的。我们将引入带有 HF 循环的自适应 RAG。因此,系统变得自适应,因为用于检索的文档会被更新。将 HF 集成到 RAG 中,形成了一种务实的混合方法,因为它在原本自动化的生成过程中引入了人类的参与。接下来,我们将利用 HF,从头开始用 Python 构建一个混合自适应 RAG 程序,经历从零开始构建 RAG 驱动的生成式 AI 系统的关键步骤。在本章末尾,你将对自适应 RAG 框架有理论上的理解,并具备基于 HF 构建 AI 模型的实际经验。
本章涵盖以下主题:
- 定义自适应 RAG 生态系统
- 将自适应 RAG 应用于增强检索查询
- 使用 HF 自动化增强生成式 AI 输入
- 自动化终端用户反馈排序以触发专家 HF
- 为人类专家创建自动化反馈系统
- 将 HF 与适应性 RAG 集成到 GPT-4o 中
让我们首先定义自适应 RAG。
自适应 RAG
不,RAG 并不能解决我们所有的问题和挑战。RAG 和任何生成模型一样,也可能生成无关或错误的输出!然而,RAG 可能是一个有用的选项,因为我们为生成式 AI 模型提供了相关的文档,以便它生成响应。尽管如此,RAG 输出的质量依赖于底层数据的准确性和相关性,这就需要进行验证!这正是自适应 RAG 的作用所在。自适应 RAG 引入了人类的、现实的、务实的反馈,以改进由 RAG 驱动的生成式 AI 生态系统。
生成式 AI 模型中的核心信息是参数化的(以权重的形式存储)。但在 RAG 的上下文中,这些数据可以被可视化和控制,正如我们在第 2 章《使用 Deep Lake 和 OpenAI 构建 RAG 嵌入向量存储》中所看到的。尽管如此,仍然存在一些挑战;例如,终端用户可能会写出模糊的查询,或者 RAG 的数据检索可能会出错。因此,强烈建议使用 HF 流程以确保系统的可靠性。
第 1 章《为什么选择检索增强生成?》中的图 1.3 表示了完整的 RAG 框架和生态系统。让我们放大自适应 RAG 生态系统,聚焦于涉及的关键流程,如下图所示:
自适应 RAG 生态系统的变体包含以下组件,如图 5.1 所示,检索器的部分包括:
- D1:收集和处理关于 LLM 的维基百科文章,抓取和清洗数据
- D4:检索查询以查询检索数据集
生成器的组件包括:
- G1:终端用户输入
- G2:通过 HF 增强的输入,用于增强用户的初始输入,并进行提示工程,以配置 GPT-4o 模型的提示
- G4:生成和输出,运行生成式 AI 模型并获得响应
评估器的组件包括:
- E1:指标,用于应用余弦相似度测量
- E2:人类反馈,通过终端用户和专家反馈获得并处理系统的最终测量
在本章中,我们将通过在 Google Colab 上用 Python 构建一个混合自适应 RAG 程序来说明自适应 RAG。我们将从头开始构建该程序,以清晰理解自适应过程,该过程可能因项目目标不同而有所变化,但其基本原则保持不变。通过这种动手实践,你将学习如何在现成的 RAG 系统不能满足用户期望时开发和定制它。这非常重要,因为无论性能指标如何,人类用户可能对某些响应不满意。我们还将探索结合人类用户排名来收集对 RAG 驱动的生成式 AI 系统的专家反馈。最后,我们将实现一个自动排名系统,该系统将决定如何增强生成模型的用户输入,提供关于如何在公司中成功实现 RAG 驱动系统的实践见解。
我们将为一个名为公司 C 的假想公司开发一个概念验证。这家公司希望部署一个会话代理来解释什么是 AI,目标是让公司员工理解 AI 的基本术语、概念和应用。负责该 RAG 驱动生成式 AI 示例的机器学习工程师希望未来用户在跨销售、生产和交付领域实施其他 AI 项目时能更好地了解 AI。
公司 C 当前面临严重的客户支持问题。随着产品和服务的不断增加,其 C-phone 系列智能手机产品线在处理大量客户请求时遇到了技术问题。IT 部门希望为这些客户建立一个会话代理,但团队并不十分信服。因此,IT 部门决定首先建立一个会话代理来解释什么是 LLM 以及它如何在 C-phone 系列的客户支持服务中发挥作用。
该程序将是混合且自适应的,以满足公司 C 的需求:
- 混合:现实场景超出了理论框架和配置。该系统是混合的,因为我们在检索过程中集成了可以实时处理的 HF。然而,我们不会仅通过关键词解析文档内容。我们将对文档进行标注(在本例中是维基百科的 URL),这一过程可以自动进行,并在必要时由人类控制和改进。正如我们在本章中所展示的,部分文档将由人类专家反馈替换并重新标注。程序将自动检索人类专家反馈文档和原始检索到的文档,以形成一个混合(人机协作)的动态 RAG 系统。
- 自适应:我们将引入人类用户排名、专家反馈和自动文档重新排名。这一 HF 循环使我们深入了解模块化 RAG 和自适应 RAG。自适应 RAG 利用 RAG 系统的灵活性,使其能够调整对查询的响应。在这种情况下,我们希望触发 HF 来提高输出质量。
现实中的项目不可避免地要求机器学习工程师超越预定类别的边界。务实和需求激励着创造性和创新性的解决方案。例如,对于系统的混合、动态和自适应方面,机器学习工程师可以想象任何与任何类型算法协同工作的过程:传统的软件功能、机器学习聚类算法或任何有效的函数。在现实中的 AI 中,有效的就是好的!
现在是时候构建一个概念验证,以向公司 C 的管理层展示混合自适应 RAG 驱动的生成式 AI 如何成功地帮助他们的团队:
- 证明 AI 可以在扩展和投资项目之前通过概念验证发挥作用
- 展示 AI 系统可以为特定项目进行定制
- 发展坚实的基础技能,以应对任何 AI 挑战
- 构建公司的数据治理和 AI 系统的控制
- 通过解决概念验证期间出现的问题,为系统扩展奠定坚实的基础
让我们开始编程吧!
构建混合自适应 RAG(Python)
现在让我们开始构建一个由混合自适应 RAG 驱动的生成式 AI 配置的概念验证。打开 GitHub 上的 Adaptive_RAG.ipynb。我们将专注于 HF,因此不会使用现有的框架,而是构建我们自己的流水线并引入 HF。
如前所述,程序分为三个独立部分:检索器、生成器和评估器函数,在实际项目的流水线中,这些可以是独立的代理。从一开始就尝试将这些功能分开,因为在一个项目中,可能有多个团队在平行工作,处理 RAG 框架的不同方面。
以下每个部分的标题与 GitHub 上程序中每个部分的名称完全一致。首先介绍的是检索器功能。
1. 检索器
我们首先概述设置 RAG 驱动的生成式 AI 模型环境所需的初始步骤。该过程从安装支持数据检索和处理的必要软件组件和库开始。我们特别介绍了下载关键文件和安装用于有效数据检索和网页抓取的包。
1.1. 安装检索器环境
首先,从 GitHub 仓库的 commons 目录中下载 grequests.py。这个仓库包含多个程序共享的资源,从而避免重复。
下载是标准的,通过以下请求完成:
url = "https://raw.githubusercontent.com/Denis2054/RAG-Driven-Generative-AI/main/commons/grequests.py"
output_file = "grequests.py"
由于我们是从头构建一个 RAG 驱动的生成式 AI 模型,检索器部分只需要两个包。我们将安装:
-
requests,用于检索 Wikipedia 文档的 HTTP 库:
sh 复制代码 !pip install requests==2.32.3 -
beautifulsoup4,用于从网页抓取信息:
sh 复制代码 !pip install beautifulsoup4==4.12.3
现在我们需要一个数据集。
1.2.1. 准备数据集
为了实现概念验证,我们将通过抓取维基百科文章的 URL 来检索 Wikipedia 文档。数据集将为每个文档包含自动生成或人工制作的标签,这是将数据集文档编入索引的第一步:
import requests
from bs4 import BeautifulSoup
import re
# Wikipedia 文章的 URL 映射到关键词
urls = {
"prompt engineering": "https://en.wikipedia.org/wiki/Prompt_engineering",
"artificial intelligence": "https://en.wikipedia.org/wiki/Artificial_intelligence",
"llm": "https://en.wikipedia.org/wiki/Large_language_model",
"llms": "https://en.wikipedia.org/wiki/Large_language_model"
}
每个 URL 前面都有一个或多个标签。这种方法对于相对较小的数据集可能是足够的。
对于特定项目,包括概念验证,这种方法可以为从朴素 RAG(基于关键词的内容搜索)到使用索引搜索数据集(在本例中为标签)提供一个坚实的第一步。接下来我们需要处理数据。
1.2.2. 处理数据
我们首先对要检索的文档应用标准的抓取和文本清理函数:
def fetch_and_clean(url):
# 获取 URL 的内容
response = requests.get(url)
soup = BeautifulSoup(response.content, 'html.parser')
# 查找文章的主要内容,忽略侧边框和标题
content = soup.find('div', {'class': 'mw-parser-output'})
# 移除不太相关的部分,如“See also”、“References”等
for section_title in ['References', 'Bibliography', 'External links', 'See also']:
section = content.find('span', {'id': section_title})
if section:
for sib in section.parent.find_next_siblings():
sib.decompose()
section.parent.decompose()
# 专注于从段落标签中提取和清理文本
paragraphs = content.find_all('p')
cleaned_text = ' '.join(paragraph.get_text(separator=' ', strip=True) for paragraph in paragraphs)
cleaned_text = re.sub(r'[\d+]', '', cleaned_text) # 移除引文标记如 [1]、[2] 等
return cleaned_text
代码根据 URL 获取文档内容,而 URL 则是基于其标签的。根据项目的目标,这种简单的方法可能满足需求。机器学习工程师或开发者必须始终注意不要用代价高且不盈利的功能来过载系统。此外,标注网站 URL 可以引导检索流水线到正确的位置来处理数据,无论采用何种技术(负载均衡、API 调用优化等)。最终,每个项目或子项目将根据其具体需求采用一项或多项技术。
一旦抓取和清理函数准备就绪,我们就可以为用户输入实现检索过程。
1.3. 用户输入的检索过程
第一步是识别用户输入中的关键词。process_query 函数接受两个参数:user_input 和 num_words。要检索的单词数量受到模型输入限制、成本考虑和整体系统性能等因素的约束:
import textwrap
def process_query(user_input, num_words):
user_input = user_input.lower()
# 检查输入中是否包含指定的关键词
matched_keyword = next((keyword for keyword in urls if keyword in user_input), None)
在用户输入中的关键词与 URL 关联的关键词匹配后,触发以下用于抓取和清理数据的函数:
if matched_keyword:
print(f"Fetching data from: {urls[matched_keyword]}")
cleaned_text = fetch_and_clean(urls[matched_keyword])
# 将显示的内容限制为清理后的文本中的指定单词数
words = cleaned_text.split() # 将文本拆分为单词
first_n_words = ' '.join(words[:num_words]) # 将前 n 个单词连接成一个字符串
num_words 参数有助于对文本进行分块。虽然这种基本方法适用于可管理的数据量的用例,但建议在更复杂的场景中将数据嵌入向量中进行处理。
清理后的截断文本随后被格式化用于显示:
# 将前 n 个单词换行为宽度为 80 个字符以便显示
wrapped_text = textwrap.fill(first_n_words, width=80)
print("\nFirst {} words of the cleaned text:".format(num_words))
print(wrapped_text) # 以良好格式打印前 n 个单词的段落
# 为确保一致性,使用完全相同的 first_n_words 作为 GPT-4 提示
prompt = f"Summarize the following information about {matched_keyword}:\n{first_n_words}"
wrapped_prompt = textwrap.fill(prompt, width=80) # 将提示文本换行
print("\nPrompt for Generator:", wrapped_prompt)
# 返回指定数量的单词
return first_n_words
else:
print("No relevant keywords found. Please enter a query related to 'LLM', 'LLMs', or 'Prompt Engineering'.")
return None
请注意,函数最终返回前 n 个单词,提供基于用户查询的简明、相关的信息片段。这种设计使系统能够高效管理数据检索,同时保持用户的参与感。
2. 生成器
生成器生态系统包含多个组件,其中一些与 RAG 驱动生成式 AI 框架中的检索器功能和用户界面重叠:
- 2.1. 基于人类排名的自适应 RAG 选择
这部分功能将基于用户面板随时间的评分。在实际项目的流水线中,该功能可能是一个独立的程序。
- 2.2. 输入
在实际项目中,用户界面(UI)将管理输入。应与用户密切合作,精心设计此界面及其关联的流程,最好在工作坊环境中进行,以充分了解他们的需求和偏好。
- 2.3. 平均排名模拟场景
计算用户评价分数的平均值及其功能。
- 2.4. 在运行生成器之前检查输入
显示输入内容。
- 2.5. 安装生成式 AI 环境
生成式 AI 模型环境的安装(在本例中是 OpenAI)可以是流水线中另一个环境的一部分,其他团队成员可以独立于检索器功能进行工作、实施和部署到生产环境中。
- 2.6. 内容生成
在程序的这一部分中,OpenAI 模型将处理输入并提供一个响应,供评估器评估。
现在我们开始描述自适应 RAG 系统。
2.1. 为增强文档输入集成 HF-RAG
信息检索的动态性以及生成式 AI 模型中上下文相关的数据增强需求,需要一个能够适应不同输入质量水平的灵活系统。我们引入了自适应 RAG 选择系统,该系统利用 HF 分数来确定在 RAG 生态系统中实现文档的最佳检索策略。自适应功能让我们超越了朴素 RAG,构建了一个混合 RAG 系统。
人类评估者为文档的相关性和质量分配从 1 到 5 的平均分数。这些分数触发不同的操作模式,如下图所示:
-
得分为 1 到 2 表示 RAG 系统缺乏补偿能力,建议进行维护或可能需要对模型进行微调。在系统改进之前,RAG 将暂时停用。用户输入会被处理,但不会进行检索。
-
得分为 3 到 4 会启动仅包含人类专家反馈的增强,利用闪卡或信息片段来优化输出。基于文档的 RAG 将被停用,但人类专家反馈数据将增强输入。
-
得分为 5 则会启动关键词搜索 RAG,并在必要时利用之前收集的 HF(如闪卡或有针对性的信息片段)来优化输出。在这种情况下,用户不需要提供新的反馈。
该程序实现了众多场景中的一个。评分系统、评分级别和触发条件会因项目而异,取决于要达到的规范目标。建议与用户小组组织工作坊,以决定如何实现这个自适应 RAG 系统。
这种自适应方法旨在优化自动检索和人类洞察之间的平衡,确保生成模型的输出具有最高的相关性和准确性。现在让我们输入数据。
2.2. 输入
公司 C 的用户被提示输入一个问题:
# 请求用户输入关键词解析
user_input = input("Enter your query: ").lower()
在这个示例和程序中,我们将专注于一个问题和主题:What is an LLM? 。问题会被输入并被模型记住:
Enter your query: What is an LLM?
该程序是一个概念验证,针对希望了解 LLM 的公司 C 的用户小组提出了策略和示例。其他主题可以被添加,程序也可以扩展以满足更多的需求。建议与用户小组组织工作坊,以决定接下来的步骤。
我们已经准备好了环境,现在将激活一个 RAG 场景。
2.3. 平均排名模拟场景
在这个程序中,假设人类用户反馈小组已经使用 3.2 节“人类用户评分”和 3.3 节“人类专家评估”中提供的功能对混合自适应 RAG 系统进行了长时间的评价。用户反馈小组多次对响应进行排名,这会自动更新排名,计算评分的平均值,并将其存储在名为 ranking 的变量中。排名得分将帮助管理团队决定是否降级文档、升级它,或者通过手动或自动功能删除文档。你甚至可以模拟 2.1 节“为增强文档输入集成 HF-RAG”中描述的场景之一。
我们将从 1 到 5 的评分开始,这将暂时停用 RAG 以便查看生成模型的原生响应:
# 选择 1 到 5 之间的得分以运行模拟
ranking = 1
然后,我们将修改这个值,以通过 ranking=5 启动不含额外人类专家反馈的 RAG。最后,我们将修改这个值,以通过 ranking=3 启动不检索文档的含人类反馈的 RAG。
在现实环境中,这些排名将在用户反馈小组组织工作坊以定义系统的预期行为后,按 3.2 和 3.3 节所述的功能自动触发。如果你想运行 2.1 节中描述的三个场景,确保初始化生成模型处理的 text_input 变量以生成响应:
# 初始化生成式 AI 模型模拟的文本
text_input = []
每次切换场景时,请确保重新初始化 text_input。
由于其概率性质,生成式 AI 模型的输出可能会在不同运行之间有所变化。
现在让我们逐步查看 2.1 节中描述的三种评分类别。
评分 1–2:无 RAG
生成式 AI 的输出得分非常低。在管理团队分析和改进系统之前,所有 RAG 功能将停用。在这种情况下,text_input 等于 user_input:
if ranking >= 1 and ranking < 3:
text_input = user_input
在这种情况下,生成式 AI 模型(此处为 GPT-4o)将在第 2.6 节“内容生成”中生成以下输出:
GPT-4 Response:
---------------
It seems like you're asking about "LLM" which stands for "Language Model for Dialogue Applications" or more commonly referred to as a "Large Language Model."
An LLM is a type of artificial intelligence model designed to understand, generate, and interact with human language. These models are trained on vast amounts of text data and use this training to generate text, answer questions, summarize information, translate languages, and perform other language-related tasks. They are a subset of machine learning models known as transformers, which have been revolutionary in the field of natural language processing (NLP).
Examples of LLMs include OpenAI's GPT (Generative Pre-trained Transformer) series and Google's BERT (Bidirectional Encoder Representations from Transformers).
---------------
对于公司 C 的用户小组来说,这种输出在特定用例中并不令人满意。他们无法将这种解释与他们的客户服务问题联系起来。此外,许多用户可能不会继续深入探索,因为他们已经向管理团队描述了自己的需求,并希望得到相关的响应。接下来让我们看看人类专家反馈的 RAG 能提供什么。
评分 3–4:人类专家反馈 RAG
在这种情况下,由于自动化 RAG 文档(评分 5)和无 RAG(评分 1-2)的用户反馈评分不佳,触发了人类专家反馈(见第 3.4 节“人类专家评估”)。人类专家小组填写了一张闪卡,现在已存储为专家级 RAG 文档。
程序首先检查评分并激活 HF 检索:
hf = False
if ranking > 3 and ranking < 5:
hf = True
接着,程序将从专家小组(公司内部选择的专家)数据集中,根据关键词、嵌入或其他符合项目目标的搜索方法获取合适的文档。在这种情况下,我们假设已经找到了合适的闪卡并下载它:
if hf == True:
from grequests import download
directory = "Chapter05"
filename = "human_feedback.txt"
download(directory, filename, private_token)
我们验证文件是否存在,加载其内容,清理后存储在 content 中,并将其分配给 text_input 供 GPT-4 模型使用:
if hf == True:
# 检查 'human_feedback.txt' 是否存在
efile = os.path.exists('human_feedback.txt')
if efile:
# 读取并清理文件内容
with open('human_feedback.txt', 'r') as file:
content = file.read().replace('\n', ' ').replace('#', '') # 删除换行符和标记字符
# print(content) # 取消注释以进行调试或维护显示
text_input = content
print(text_input)
else:
print("File not found")
hf = False
文件的内容解释了什么是 LLM 以及它如何帮助公司 C 改善客户支持:
A Large Language Model (LLM) is an advanced AI system trained on vast amounts of text data to generate human-like text responses. It understands and generates language based on the patterns and information it has learned during training. LLMs are highly effective in various language-based tasks, including answering questions, making recommendations, and facilitating conversations. They can be continually updated with new information and trained to understand specific domains or industries. For the C-phone series customer support, incorporating an LLM could significantly enhance service quality and efficiency. The conversational agent powered by an LLM can provide instant responses to customer inquiries, reducing wait times and freeing up human agents for more complex issues. It can be programmed to handle common technical questions about the C-phone series, troubleshoot problems, guide users through setup processes, and offer tips for optimizing device performance. Additionally, it can be used to gather customer feedback, providing valuable insights into user experiences and product performance. This feedback can then be used to improve products and services. Furthermore, the LLM can be designed to escalate issues to human agents when necessary, ensuring that customers receive the best possible support at all levels. The agent can also provide personalized recommendations for customers based on their usage patterns and preferences, enhancing user satisfaction and loyalty.
如果现在运行第 2.4 和 2.5 节,再运行第 2.6 节以基于此 text_input 生成内容,响应将令人满意:
GPT-4 Response:
---------------
A Large Language Model (LLM) is a sophisticated AI system trained on extensive text data to generate human-like text responses. It understands and generates language based on patterns and information learned during training. LLMs are highly effective in various language-based tasks such as answering questions, making recommendations, and facilitating conversations. They can be continuously updated with new information and trained to understand specific domains or industries. For the C-phone series customer support, incorporating an LLM could significantly enhance service quality and efficiency. The conversational agent powered by an LLM can provide instant responses to customer inquiries, reducing wait times and freeing up human agents for more complex issues. It can be programmed to handle common technical questions about the C-phone series, troubleshoot problems, guide users through setup processes, and offer tips for optimizing device performance. Additionally, it can be used to gather customer feedback, providing valuable insights into user experiences and product performance. This feedback can then be used to improve products and services. Furthermore, the LLM can be designed to escalate issues to human agents when necessary, ensuring that customers receive the best possible support at all levels. The agent can also provide personalized recommendations for customers based on their usage patterns and preferences, enhancing user satisfaction and loyalty.
---------------
前面的响应现在好得多,因为它不仅定义了 LLM,还展示了如何改善公司 C 的 C-phone 系列客户服务。
我们将在第 9 章《增强 AI 模型:微调 RAG 数据和人类反馈》中进一步探讨,通过每日(或尽可能频繁)微调生成式模型以改进其响应,从而减少 RAG 数据的数量。但现在,让我们看看在没有 HF 但有 RAG 文档的情况下,系统能实现什么。
评分 5:没有人类专家反馈文档的 RAG
有些用户不需要包含人类专家 RAG 闪卡、片段或文档的 RAG 文档。这种情况尤其可能发生在软件工程师作为用户时。
在这种情况下,为了优化 API 成本,最大单词数限制为 100,但可以根据需要使用以下代码进行修改:
if ranking >= 5:
max_words = 100 # 限制:可以添加到输入的数据大小
rdata = process_query(user_input, max_words)
print(rdata) # 如有需要用于维护
if rdata:
rdata_clean = rdata.replace('\n', ' ').replace('#', '')
rdata_sentences = rdata_clean.split('. ')
print(rdata)
text_input = rdata
print(text_input)
当我们运行生成式 AI 模型时,会生成一个合理的输出,软件工程师可以将其与他们的业务联系起来:
GPT-4 Response:
---------------
A large language model (LLM) is a type of language model known for its capability to perform general-purpose language generation and other natural language processing tasks such as classification. LLMs develop these abilities by learning statistical relationships from text documents through a computationally intensive training process that includes both self-supervised and semi-supervised learning. These models can generate text, a form of generative AI, by taking an input text and repeatedly predicting the next token or word. LLMs are based on artificial neural networks. As of March 2024, the most advanced and capable LLMs are constructed using a decoder-only transformer architecture.
---------------
我们可以看到输出提及了 2024 年 3 月的数据,尽管 GPT-4-turbo 的训练截止日期是在 2023 年 12 月,如 OpenAI 文档中所述:platform.openai.com/docs/models…。
在生产环境中,对于终端用户来说,输出中的错误可能来自于检索的数据或生成式 AI 模型。这显示了 HF 的重要性。在这种情况下,这一错误希望能通过检索文档或生成式 AI 模型来纠正。但我们保留了这个错误,以说明 HF 不是可选的,而是必要的。
这些时间相关的 RAG 增强明确证明了 RAG 驱动生成式 AI 的必要性。然而,是否足够或者是否需要在封闭环境中进行更多企业级的定制,最终取决于用户。
对于接下来的程序,我们假设 ranking >= 5,以便展示在评估器部分如何实现评估器。接下来,让我们安装生成式 AI 环境,以基于用户输入和检索到的文档生成内容。
2.4.–2.5. 安装生成式 AI 环境
2.4. 在运行生成器之前检查输入
在运行生成器之前检查用户输入和检索到的文档,以便在使用这些信息增强输入之前进行显示。然后继续到 2.5. 安装生成式 AI 环境。
只需运行此部分一次。如果你在第 2.3 节中修改了场景,可以跳过此部分,再次运行生成式 AI 模型。此部分的安装不在本笔记本的顶部,因为项目团队可能选择在另一环境中甚至在生产中的另一台服务器上运行此部分程序。
建议尽可能将检索器和生成器功能分离,因为它们可能由不同的程序在不同的时间激活。一个开发团队可能只负责检索器功能,而另一个团队负责生成器功能。
首先安装 OpenAI:
!pip install openai==1.40.3
然后,检索 API 密钥。将你的 OpenAI 密钥存放在一个安全的位置。在这个例子中,密钥存储在 Google Drive 上:
# API Key
# 将你的密钥存储在文件中并读取(你可以直接在笔记本中输入,但对旁边的人是可见的)
from google.colab import drive
drive.mount('/content/drive')
f = open("drive/MyDrive/files/api_key.txt", "r")
API_KEY = f.readline().strip()
f.close()
# 设置 OpenAI 密钥
import os
import openai
os.environ['OPENAI_API_KEY'] = API_KEY
openai.api_key = os.getenv("OPENAI_API_KEY")
现在我们已准备好进行内容生成。
2.6. 内容生成
要生成内容,首先导入并设置所需内容。我们引入 time 来测量响应速度,并选择 gpt-4o 作为对话模型:
import openai
from openai import OpenAI
import time
client = OpenAI()
gptmodel = "gpt-4o"
start_time = time.time() # 在请求前开始计时
然后定义一个标准的 Gpt-4o 提示,给出足够的信息来生成响应,其余的由模型和 RAG 数据处理:
def call_gpt4_with_full_text(itext):
# 将所有行合并为一个字符串
text_input = '\n'.join(itext)
prompt = f"Please summarize or elaborate on the following content:\n{text_input}"
try:
response = client.chat.completions.create(
model=gptmodel,
messages=[
{"role": "system", "content": "You are an expert Natural Language Processing exercise expert."},
{"role": "assistant", "content": "1. You can read the input and answer in detail."},
{"role": "user", "content": prompt}
],
temperature=0.1 # 添加温度参数以及其他需要的参数
)
return response.choices[0].message.content.strip()
except Exception as e:
return str(e)
然后代码格式化输出:
import textwrap
def print_formatted_response(response):
# 定义换行文本的宽度
wrapper = textwrap.TextWrapper(width=80) # 设置为 80 列宽,可以根据需要调整
wrapped_text = wrapper.fill(text=response)
# 打印带有标题和页脚的格式化响应
print("GPT-4 Response:")
print("---------------")
print(wrapped_text)
print("---------------\n")
# 假设 'gpt4_response' 包含前面 GPT-4 调用的响应
print_formatted_response(gpt4_response)
在第 2.3 节中,我们看到这个响应在 ranking=5 的场景中是令人满意的,正是我们现在正在评估的场景,输出如下:
GPT-4 Response:
---------------
### Summary: A large language model (LLM) is a computational model known for its ability to perform general-purpose language generation and other natural language processing tasks, such as classification. LLMs acquire these abilities by learning statistical relationships from vast amounts of text during a computationally intensive self-supervised and semi-supervised training process. They can be used for text generation, a form of generative AI, by taking input text and repeatedly predicting the next token or word. LLMs are artificial neural networks that use the transformer architecture...
该响应看起来不错,但它真的准确吗?让我们运行评估器来找出答案。
3. 评估器
根据每个项目的规格和需求,我们可以实现尽可能多的数学和人类评估函数。在本节中,我们将实现两个自动化指标:响应时间和余弦相似度评分。然后,我们将实现两个交互式评估功能:人类用户评分和人类专家评估。
3.1. 响应时间
响应时间在 API 调用中被计算并显示:
import time
…
start_time = time.time() # 在请求之前开始计时
…
response_time = time.time() - start_time # 测量响应时间
print(f"Response Time: {response_time:.2f} seconds") # 打印响应时间
在这种情况下,我们可以直接显示响应时间:
print(f"Response Time: {response_time:.2f} seconds") # 打印响应时间
输出将根据网络连接状况和 OpenAI 服务器的容量而有所不同。在这种情况下,输出为:
Response Time: 7.88 seconds
虽然看起来时间较长,但在线对话代理也需要一些时间来回答。决定这个性能是否足够,仍然是管理层的决定。接下来让我们运行余弦相似度评分。
3.2. 余弦相似度评分
余弦相似度测量两个非零向量之间的夹角余弦值。在文本分析的上下文中,这些向量通常是文本的 TF-IDF(词频-逆文档频率)表示,这些表示基于词相对于文档和语料库的重要性来加权。
GPT-4o 的输入 text_input 和模型的响应 gpt4_response 被 TF-IDF 视为两个独立的“文档”。向量化器将文档转换为向量。然后,向量化考虑输入和响应之间术语的共享和强调程度,通过 vectorizer.fit_transform([text1, text2]) 实现。
目的是通过以下函数量化主题和词汇的重叠:
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
def calculate_cosine_similarity(text1, text2):
vectorizer = TfidfVectorizer()
tfidf = vectorizer.fit_transform([text1, text2])
similarity = cosine_similarity(tfidf[0:1], tfidf[1:2])
return similarity[0][0]
# 使用你现有函数的示例
similarity_score = calculate_cosine_similarity(text_input, gpt4_response)
print(f"Cosine Similarity Score: {similarity_score:.3f}")
余弦相似度依赖于 TfidfVectorizer 将两个文档转换为 TF-IDF 向量,然后 cosine_similarity 函数计算这些向量之间的相似度。结果为 1 表示文本完全相同,结果为 0 表示完全不同。函数的输出为:
Cosine Similarity Score: 0.697
得分显示了模型输入和输出之间的较强相似性。但是,人类用户会如何评价这个响应呢?让我们来看看。
3.3. 人类用户评分
人类用户评分界面提供了人类用户反馈。正如本章反复强调的,我建议在通过工作坊充分了解用户需求后,设计该界面和流程。在本节中,我们假设人类用户小组是一组正在测试系统的软件开发人员。
代码首先定义界面的参数:
# 评分参数
counter = 20 # 反馈查询次数
score_history = 30 # 人类反馈总分
threshold = 4 # 触发人类专家反馈的最低评分
在这个模拟中,参数显示系统已经计算了人类反馈:
counter = 20表示用户已输入的评分次数。score_history = 60表示 20 次评分的总分。threshold = 4指出最低平均评分(score_history / counter)达到 4 时,才不会触发人类专家反馈请求。
现在我们运行界面,向这些参数添加一个实例。提供的 Python 代码定义了 evaluate_response 函数,用于评估 GPT-4 等语言模型生成的响应的相关性和连贯性。用户对生成的文本进行评分,范围从 1(差)到 5(优秀),该函数通过递归检查确保输入有效。代码计算平均评分等统计指标,以衡量模型在多次评估中的表现。
评估函数是一个简单的反馈请求,用于获取 1 到 5 之间的值:
import numpy as np
def evaluate_response(response):
print("\nGenerated Response:")
print(response)
print("\nPlease evaluate the response based on the following criteria:")
print("1 - Poor, 2 - Fair, 3 - Good, 4 - Very Good, 5 - Excellent")
score = input("Enter the relevance and coherence score (1-5): ")
try:
score = int(score)
if 1 <= score <= 5:
return score
else:
print("Invalid score. Please enter a number between 1 and 5.")
return evaluate_response(response) # 如果输入无效,递归调用
except ValueError:
print("Invalid input. Please enter a numerical value.")
return evaluate_response(response) # 如果输入无效,递归调用
然后我们调用该函数:
score = evaluate_response(gpt4_response)
print("Evaluator Score:", score)
函数首先显示响应,如以下摘录所示:
Generated Response:
### Summary:
A large language model (LLM) is a computational model…
接着,用户输入 1 到 5 之间的评分,在本例中为 3:
Please evaluate the response based on the following criteria:
1 - Poor, 2 - Fair, 3 - Good, 4 - Very Good, 5 - Excellent
Enter the relevance and coherence score (1-5): 3
代码随后计算统计数据:
counter += 1
score_history += score
mean_score = round(np.mean(score_history / counter), 2)
if counter > 0:
print("Rankings :", counter)
print("Score history : ", mean_score)
输出显示了相对较低的评分:
Evaluator Score: 3
Rankings : 21
Score history : 3.0
评估器的得分是 3,总评分为 3,得分历史也是 3!然而,余弦相似度是积极的。由于我们设置的阈值为 4,因此将触发人类专家评估请求:
threshold = 4
这到底是怎么回事?让我们问问专家,找出答案吧!
3.4. 人类专家评估
指标如余弦相似度确实可以测量相似性,但无法评估深度准确性。时间性能也不能决定响应的准确性。如果评分过低,这是为什么呢?因为用户对响应不满意!
代码首先为人类专家用户下载“点赞”和“点踩”图片:
from grequests import download
# 定义变量
directory = "commons"
filename = "thumbs_up.png"
download(directory, filename, private_token)
# 定义变量
directory = "commons"
filename = "thumbs_down.png"
download(directory, filename, private_token)
触发专家反馈的参数是 counter_threshold 和 score_threshold。用户评分的数量必须超过专家的阈值 counter_threshold,在本场景中为 counter_threshold = 10。评分的平均分阈值在本场景中为 4:score_threshold = 4。现在我们可以模拟触发专家反馈请求:
if counter > counter_threshold and score_history <= score_threshold:
print("Human expert evaluation is required for the feedback loop.")
在这种情况下,由于用户评分较低且评分次数较多,输出将确认需要进入专家反馈循环:
Human expert evaluation is required for the feedback loop.
如前所述,在现实项目中,应该与专家用户组织一个工作坊来定义界面。在本例中,Python 单元格中的标准 HTML 界面将显示“点赞”和“点踩”图标。如果专家点击“点踩”图标,可以输入反馈并将其保存到名为 expert_feedback.txt 的反馈文件中,如下代码片段所示:
import base64
from google.colab import output
from IPython.display import display, HTML
def image_to_data_uri(file_path):
"""
将图像转换为数据 URI。
"""
with open(file_path, 'rb') as image_file:
encoded_string = base64.b64encode(image_file.read()).decode()
return f'data:image/png;base64,{encoded_string}'
thumbs_up_data_uri = image_to_data_uri('/content/thumbs_up.png')
thumbs_down_data_uri = image_to_data_uri('/content/thumbs_down.png')
def display_icons():
# 定义包含两个可点击图片的 HTML 内容
…/…
def save_feedback(feedback):
with open('/content/expert_feedback.txt', 'w') as f:
f.write(feedback)
print("Feedback saved successfully.")
# 注册回调函数
output.register_callback('notebook.save_feedback', save_feedback)
print("Human Expert Adaptive RAG activated")
# 显示带有点击处理程序的图标
display_icons()
代码将显示如下图所示的图标。如果专家用户点击“点踩”图标,他们将被提示输入反馈。
你可以为“点踩”添加一个功能,这表示响应不正确,管理团队需要与用户小组沟通或在用户反馈界面中添加提示。当然,这属于管理层的决策。在我们的场景中,人类专家点击了“点踩”图标,并被提示输入反馈:
人类专家提供了反馈,并保存到 '/content/expert_feedback.txt' 中。通过这个反馈,我们终于发现了不准确之处,问题出现在以下单元格显示的文件内容中:
文本中有一处不准确的陈述: “截至 2024 年 3 月,最大的、最强大的 LLM 使用基于仅解码器的 Transformer 架构构建。”
这段陈述不准确,因为最大的、最强大的大型语言模型,如 Meta 的 Llama 模型,确实使用 Transformer 架构,但它们并非“仅解码器”。这些模型使用的 Transformer 架构包括编码器和解码器组件。
上述专家反馈可以用于改进 RAG 数据集。通过此过程,我们探索了 HF-RAG 交互的深度。现在让我们总结一下这段旅程,并进入下一步。
总结
随着我们对实际 AI 实现方法的实践即将结束,回顾一下我们一起展开的变革之旅是很有意义的。我们探索了自适应 RAG 的动态世界。我们首先研究了 HF(人类反馈)不仅是补充,还对生成式 AI 的提升至关重要,使其成为更强大的工具,定制以满足现实世界的需求。我们描述了自适应 RAG 生态系统,然后动手从头开始构建。从数据收集、处理到查询,我们将这些元素集成到 RAG 驱动的生成式 AI 系统中。我们的做法不仅仅是编写代码;而是通过不断的 HF 循环为 AI 增加适应性。
通过将 GPT-4 的能力与先前会话中的专家洞见以及终端用户的评价结合,我们展示了 HF 的实际应用及其重大影响。我们实现了一个系统,其中输出不仅被生成,还由终端用户进行排名。低评分触发了专家反馈循环,强调了人类干预在改进 AI 响应中的重要性。从头开始构建自适应 RAG 程序确保我们深入理解 HF 是如何将标准的 AI 系统转变为一个不断进化和改进的系统。
这一章不仅仅是学习,它还涉及到实践、反思,将理论知识转化为实践技能。现在我们已经准备好在下一章中将 RAG 驱动的 AI 扩展到生产级别的体量和复杂性。
问题
- 人类反馈在改进 RAG 驱动的生成式 AI 系统中是否至关重要?
- 生成式 AI 模型中的核心数据可以在不重新训练模型的情况下进行更改吗?
- 自适应 RAG 是否包含实时人类反馈循环以改进检索?
- 自适应 RAG 的主要重点是否在于用自动化响应替代所有人类输入?
- 自适应 RAG 中的人类反馈是否可以触发检索到的文档的变化?
- 公司 C 是否仅将自适应 RAG 用于客户支持问题?
- 人类反馈是否仅在 AI 响应具有高用户评分时使用?
- 本章中的程序是否仅提供基于文本的检索输出?
- 混合自适应 RAG 系统是静态的吗,这意味着它无法基于反馈进行调整?
- 用户评分是否在确定 AI 响应的相关性时完全被忽略?
参考文献
- Studying Large Language Model Behaviors Under Realistic Knowledge Conflicts by Evgenii Kortukov, Alexander Rubinstein, Elisa Nguyen, Seong Joon Oh
- OpenAI 模型
延伸阅读
有关本章中实现的向量化器和余弦相似度功能的更多信息,请参考以下链接: