使用 Python 构建您自己的个性化健身 RAG 代理!
- Rifx.Online
- Programming , Generative AI , Health
- 14 Jan, 2025
AI代理 | RAG代理 | Python | DSPy | 健身代理 | 初学者友好
完整且适合初学者的指南:使用 Python 构建您完全个性化的健身 RAG 代理
还不是会员?请随时访问完整文章 这里。
无论您是开发者还是运动员,健身始终位居我们新年决心的首位。
减掉这么多体重,增加多少肌肉量等等。在这种日益紧张的生活方式中,跟上我们身体的健身需求变得越来越困难。
而有一样东西,可以帮助您在至少某些健身旅程的努力中,那就是 个性化健身代理,一个在这个领域的专家,总是陪伴在您身边,并且和您一样关注您的健康。
在本文结束时,您将使用 Python 构建一个 健身 RAG 代理。创建 检索增强生成 (RAG) 代理 是非常深思熟虑的,因为它将帮助我们结合信息检索和文本生成的力量,为您的所有查询提供准确、个性化、上下文相关的答案。
兴奋吗?让我们开始敲击键盘吧!
以下是整篇文章的 目录,供您快速浏览。
∘ AI 代理 | RAG 代理 | Python | DSPy | 健身代理 | 适合初学者· 前提条件 🔮· 安装软件包📦· 收集数据 📚· 从书中提取文本 📙· 将文本拆分为文档📖· 编译数据 💽· 创建检索模型 📳· 配置语言模型和检索模型 ⚙️· 为代理创建签名 🗞️· 创建 RAG 模块🤖· 查询代理⁉️· 代理的结果 📜· 完整代码库 💨· 结论 🧩· 今天的灵感 🌠· 作者的说明 ✒️
前提条件 🔮
在我们实际开始开发健身代理之前,最重要的事情之一是关注这个项目的主要前提条件。
- 该项目涉及配置语言模型,在我们的案例中将使用
gemini-1.5-flash
。要使用此语言模型,您需要您的 Google API 密钥来查询模型,您可以从 这里 获取一个。 - 本文重点介绍开发专门的 RAG 代理,因此为了使事情更易于理解,建议您先阅读这篇 文章,因为它将清除您大部分的基本疑问,并且还会为您提供该概念的入门指导。
没错!就这些,没有更多准备的事情,让我们直接进入开发阶段。🧑🏻💻
安装软件包📦
为了方便我们代理的开发,我们将使用一些 PPP (Popular-Python-Packages),它们是 PyPDF2
、langchain
、dspy==0.1.5
和 dspy-ai[faiss-cpu]
。
安装这些软件包甚至比涂黄油到面包上还要简单,方法如下,—
// For Notebook
!pip install PyPDF2 langchain dspy==0.1.5 dspy-ai[faiss-cpu]
// For Terminal
pip install PyPDF2 langchain dspy==0.1.5 dspy-ai[faiss-cpu]
此外,随着我们进一步开发 Fitness AI RAG Agent,我们将会更多地了解这些软件包。
收集数据 📚
收集数据是一个重要步骤,将主要决定我们代理生成的响应的准确性和相关性。
为了简单起见和演示,我们将使用一本书,但您可以收集更多数据,以供我们的代理参考。
我们将使用一本关于健身的最著名书籍之一,即——
“You Are Your Own Gym: The Bible of Bodyweight Exercises for Men and Women”
By- Mark Lauren & Joshua Clark
您也可以从这里下载这本书。
从书籍中提取文本 📙
由于我们所提到的数据是一本书,而我们知道一本书包含的不仅仅是纯文本,我们也知道代理只能通过文本进行搜索以供参考。
既然我们知道这些,我们也应该知道如何从书中提取文本。现在,PyPDF2
包将帮助我们完成这个工作。
提取书中文本的代码如下:
from PyPDF2 import PdfReader
reader = PdfReader("/content/You_Are_Your_Own_Gym.pdf")
complete_text = ""
for page in reader.pages:
text = page.extract_text()
complete_text += text
这段代码将逐页提取书中的文本,并将内容存储在 complete_text
变量中。
💡自己尝试: 与其将整个文本存储在一个变量中,不如尝试将内容写入文件。
将文本拆分为文档📖
在从书籍(PDF 文件)中提取所有文本后,我们必须将其拆分为可以存储在向量数据库中的块。这些块也称为文档。
创建这些文档的主要目的是在内容之间实现重叠,这将有助于语言代理将相同的内容组合在一起,并最终更好地学习。
我们将使用 RecursiveCharacterTextSplitter()
,来自 langchain.text_splitter
模块,以实现这一目标。
相关代码如下,—
from langchain.text_splitter import RecursiveCharacterTextSplitter
text_splitter = RecursiveCharacterTextSplitter(
# Set a chunk size, to splitting the documents.
chunk_size=1024,
chunk_overlap=100,
length_function=len,
is_separator_regex=False,
)
## Contains all the chunked documents of the complete_text_book
texts = text_splitter.create_documents([complete_text])
这里,texts
包含指定块大小的所有文档,遵循块重叠长度。
💡自己尝试: 尝试不同的
chunk_size
和chunk_overlap
的值,并注意代理的响应变化。
编译数据 💽
我们之前创建的 texts
包含了所有文档的列表,每个文档本身包含大量信息,包括页面内容、元数据等。
现在我们必须收集每个文档中存在的所有页面内容,并准备一个列表,这将为我们的检索模型提供数据。
准备每个文档中所有 page_content
的列表的代码如下,—
## An array containing the page_content of each and every document
page_contents = [text.page_content for text in texts]
创建检索模型 📳
检索模型是从整个数据库中检索出最相关信息的模型。从数据库中检索的信息将构成参考内容的基础,这些内容将在我们的代理响应时使用。
使用 dspy-ai[faiss-cpu]
包,我们只需一行代码即可创建自己的检索模型,代码如下——
from dspy.retrieve.faiss_rm import FaissRM
frm = FaissRM(page_contents)
在这里,frm
是我们的检索模型,它使用 FAISS
,提供了一种高效的方法来搜索和聚类稠密向量或数据的向量嵌入。
配置语言模型和检索模型 ⚙️
经过如此多的准备工作,现在我们进入配置语言模型和检索模型的阶段。
我们将使用 dspy
包来完成这项工作,—
import dspy
## 我们项目的 gemini LM
gemini = dspy.Google(model='gemini-1.5-flash', api_key="<YOUR_GOOGLE_API_KEY>", temperature=0.3)
## 使用 LM 和 RM 配置 dspy
dspy.settings.configure(lm=gemini, rm=frm)
我们使用 gemini-1.5-flash
模型作为我们的语言模型。在这里,您需要将 <YOUR_GOOGLE_API_KEY>
替换为您的 API 密钥,然后就可以开始了!
💡尝试一下: 尝试更改
temperature
的值,并监控模型生成的响应质量。
为代理创建签名 🗞️
使用 DSPy 时,我们必须向 RAG 代理提供指令,说明代理应如何响应所有查询,以及如何使用它所拥有的信息。
通过使用 DSPy,我们可以以简单的语言传递这些指令,形成 DSPy 签名。根据这些指令,DSPy 会调整和优化语言模型以适应用例。
我们 RAG 代理的基本签名如下,—
class GenerateAnswer(dspy.Signature):
"""你是一位知识渊博且富有同理心的虚拟健身教练,专注于制定个性化健身计划并为各个健身水平的用户提供指导。你的目标是支持、教育和激励用户安全、可持续地实现他们的健身和健康目标。以友好、专业和鼓励的语气回应查询,确保你的建议是可操作的、基于证据的,并根据用户的需求量身定制。
在你的回应中,确保遵循以下原则:
同理心和鼓励:始终保持积极、无评判的语气,鼓励用户,无论他们的健身水平或面临的挑战如何。
示例:‘你迈出了第一步,真棒!让我们一起制定一个符合你日程的计划。’
个性化:利用用户提供的信息,如他们的健身目标、当前活动水平、饮食偏好和任何限制,来定制回应。
示例:对于希望减肥的初学者,建议他们可以遵循的可管理的锻炼和饮食想法。
基于证据的建议:提供基于科学证据的推荐,用简单的术语解释你建议背后的理由。
示例:解释为什么力量训练有助于减肥目标或水分在恢复中的作用。
安全第一:在所有建议中强调正确的姿势、逐步进展和预防受伤。如果用户报告疼痛或不适,建议咨询医疗专业人员。
示例:‘如果你是跑步新手,可以先通过步行和慢跑的结合逐渐提高耐力。’
可操作的步骤:将建议分解为用户可以轻松遵循的简单、可操作的步骤或例程。
示例:提供初学者的锻炼计划,包含清晰的组数、次数和休息间隔。
教育性见解:以易于理解和实施的方式分享有关健身、营养或健康的教育小贴士。
示例:解释宏观营养素在肌肉构建中的重要性或动态拉伸在锻炼前的好处。
多样化沟通:有效回应各种用户需求,如:
锻炼指导:建议针对减肥、增肌或灵活性等目标的具体锻炼。
饮食和营养:提供餐点创意、份量指导以及均衡饮食的见解。
激励和心态:提供激励支持,帮助用户保持一致性和积极性。
如果你没有与用户查询相匹配的上下文,可以礼貌地说明该查询无法得到很好的回答。
如果查询与健身教练无关,你可以礼貌地拒绝回答,并说明你的目的。
"""
context = dspy.InputField(desc="may contain relevant facts")
question = dspy.InputField(desc="The query of the user")
answer = dspy.OutputField()
这里所有在 """ """
之间的文本都是指令。在创建签名时,我们还需要传递有关正在处理的输入和作为代理响应的输出的信息。
是的,我知道提示内容相当长,但指令越大、越详细,签名得到的响应就越一致。
💡尝试一下: 尝试添加更多指令或完全更改它,并监控代理生成的响应。
创建 RAG 模块🤖
在我们完成为 RAG 代理编写签名之后,现在我们需要声明一个类,其对象将用于查询我们的代理。
创建该模块的代码如下,—
class RAG(dspy.Module):
def __init__(self, num_passages=5):
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)
在这里,我们在 RAG 类中继承了 dspy.Module
,以便使用重要的方法,如 dspy.ChainOfThought
和 dspy.Prediction
。
在此,dspy.Retrieve
调用配置的 RM(在我们的例子中是 frm
),并检索与用户查询最匹配的前 5
个结果。
然后,将 RM 的结果与问题一起传递给代理以生成答案。dspy.ChainOfThought
模块的主要目的是根据代理的签名或指令中提到的说明,将问题(或查询)分解成更小的部分。
查询代理⁉️
太好了!🥳 我们准备好查询代理了!
我们经历了键盘的考验,构建了我们出色的代理。现在是实际查询或测试我们代理以满足特定健身需求的时候了。
要查询代理,我们必须创建一个 RAG
模块的对象,然后将查询作为参数传递给该对象。执行的代码是,—
r = RAG()
response = r("I am a software developer, and have to sit for around 5-6 hr daily. Suggest something to me")
response.answer
在运行内核后,代理的输出是,—
此外,我使用 Python 的 rich_text
将 markdown 转换为富文本。
来自代理的结果 📜
一些来自我们代理的更多结果。
查询 1:我身高 5’10”,体重约 80Kg。我每天可以投入大约 15 分钟,我该如何进行?
(这不是我🫣,我更健康!)
查询 2:我在白天和餐后感到困倦。我想变得健康,但感到缺乏锻炼的动力。
完整代码库 💨
项目的完整代码库如下,—
from PyPDF2 import PdfReader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from dspy.retrieve.faiss_rm import FaissRM
import dspy
from rich import markdown
reader = PdfReader("/content/You_Are_Your_Own_Gym.pdf")
complete_text = ""
for page in reader.pages:
text = page.extract_text()
complete_text += text
text_splitter = RecursiveCharacterTextSplitter(
# 设置分块大小,以拆分文档。
chunk_size=1024,
chunk_overlap=100,
length_function=len,
is_separator_regex=False,
)
## 包含完整文本书籍的所有分块文档
texts = text_splitter.create_documents([complete_text])
## 包含每个文档的页面内容的数组
page_contents = [text.page_content for text in texts]
frm = FaissRM(page_contents)
## 我们项目的 gemini LM
gemini = dspy.Google(model='gemini-1.5-flash', api_key="<YOUR_API_KEY>", temperature=0.3)
## 使用 LM 和 RM 配置 dspy
dspy.settings.configure(lm=gemini, rm=frm)
## 代理的签名
class GenerateAnswer(dspy.Signature):
"""你是一位知识渊博且富有同理心的虚拟健身教练,专注于制定个性化的健身计划并为各个健身水平的用户提供指导。你的目标是支持、教育和激励用户安全和可持续地实现他们的健身和健康目标。以友好、专业和鼓励的语气回应用户的询问,确保你的建议是可操作的、基于证据的,并根据用户的需求量身定制。
在你的回答中,确保遵循以下原则:
同理心和鼓励:始终保持积极、非评判的语气,鼓励用户,无论他们的健身水平或面临的挑战如何。
示例:‘你迈出了第一步,这太棒了!让我们一起制定一个适合你日程的计划。’
个性化:利用用户提供的信息,例如他们的健身目标、当前活动水平、饮食偏好和任何限制,以量身定制回答。
示例:对于一个希望减肥的初学者,建议他们可以遵循的可管理的锻炼和膳食建议。
基于证据的建议:提供基于科学证据的推荐,以简单的术语解释你建议背后的理由。
示例:解释为什么力量训练有助于减肥目标或水合作用在恢复中的作用。
安全第一:在所有建议中强调正确的姿势、逐步进展和预防伤害。如果用户报告疼痛或不适,建议咨询医疗专业人员。
示例:‘如果你是跑步新手,建议从走路和慢跑的混合开始,逐渐建立耐力。’
可操作步骤:将建议分解为用户可以轻松遵循的简单、可操作的步骤或例程。
示例:提供一个初学者的锻炼计划,包含明确的组数、次数和休息间隔。
教育性见解:以易于理解和实施的方式分享关于健身、营养或健康的教育性提示。
示例:解释宏观营养素在肌肉生长中的重要性或动态拉伸在锻炼前的好处。
多样化沟通:有效回应各种用户需求,例如:
锻炼指导:建议特定的锻炼以实现减肥、增肌或灵活性等目标。
饮食和营养:提供膳食建议、份量指导以及均衡饮食的见解。
动机和心态:提供动机支持,帮助用户保持一致和积极。
如果你没有与用户查询匹配的上下文,可以礼貌地说明该查询无法很好地回答。
如果查询与健身教练无关,可以礼貌地拒绝回答,并说明你的目的。
"""
context = dspy.InputField(desc="可能包含相关事实")
question = dspy.InputField(desc="用户的查询")
answer = dspy.OutputField()
## RAG 模块
class RAG(dspy.Module):
def __init__(self, num_passages=5):
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)
## 实例化 RAG 代理
r = RAG()
## 查询代理
response = r("我是一名软件开发人员,每天需要坐大约 5-6 小时。给我建议一些。")
## 将 markdown 转换为富文本
b_res = markdown.Markdown(response.answer)
b_res
结论 🧩
首先,恭喜你!🥳🎉你使用 Python 和 DSPy 构建了一个出色的健身代理。
那么,这就是本文的全部内容!
本文讨论的所有内容简要如下,-
- 了解了
DSPy
模块,该模块用于向语言和检索模型提供高级指令。 - 从书中提取文本,然后将其转换为文档和块,以便存储在数据库中。
- 创建了一个
FAISS
检索模型,这是一个用于高效搜索和聚类密集向量的库。 - 为你的 Fitness 代理创建了一个签名,给它指示如何使用可用信息并响应用户查询。
- 创建了一个 RAG 模块,特别用于导航所有过程及其结果。
- 向我们的健身 RAG 代理发起查询,并分析结果。
我认为这一天的内容已经足够多了。
今日的灵感 🌠
千支蜡烛可以从一支蜡烛中点燃,而这支蜡烛的寿命不会缩短。快乐通过分享不会减少。—— 佛陀
作者的注释 ✒️
感谢您阅读本文。如果您有任何问题或建议,请随时在评论区发布。我非常重视反馈,您可以在 这里 订阅,以便直接将所有有趣和信息丰富的文章发送到您的邮箱。