整合 Rasa、LangChain 和 FastAPI 的开源聊天机器人框架,为 AI 应用原型开发提供快速起点。
💬 RasaGPT 是首个构建于 Rasa 和 Langchain 之上的无头 LLM 聊天机器人平台。它既是一套样板代码,也是 Rasa 与 Telegram 的参考实现,并利用 Langchain 等 LLM 库完成索引、检索和上下文注入。
📚 资源:https://rasagpt.dev
🧑💻 Github:https://github.com/paulpierre/RasaGPT
🧙 作者:@paulpierre
💬 Rasa 是一个开源的 Python 机器学习框架,用于实现文本和语音对话自动化:包括 NLU、对话管理,以及连接 Slack、Facebook 等平台——可用于创建聊天机器人和语音助手。
Rasa 是一个非常流行(甚至可以说是事实标准?)且足够易用的聊天机器人框架。它内置的 NLU 机器学习流水线已经过时,但在 LLM 时代,它可以作为重新构想聊天机器人框架的概念起点。
RasaGPT 开箱即用。许多实现过程中令人头疼的问题都已经得到解决,你不必再亲自处理,包括:
使用 FastAPI 创建自己的专有机器人端点,并内置文档上传和“训练”流水线
如何集成 Langchain/LlamaIndex 与 Rasa
解决 LLM 库的依赖冲突以及元数据传递问题
在 MacOS 上通过 Docker 运行 Rasa
通过 ngrok 为聊天机器人配置反向代理
使用自定义 schema 实现 pgvector,而不是使用 Langchain 高度固化的 PGVector 类
在 Rasa 与你自己的后端/应用程序之间添加多租户支持(Rasa 原生并不支持)、会话和元数据
这个故事的开端并不陌生。一位朋友带着一个问题找到了我。我在 Google 和 Github 上四处搜寻,希望找到一个将 LLM 与 Rasa 集成的可靠参考实现,但最终一无所获。我觉得这是满足自己好奇心的绝佳机会,于是两天后做出了概念验证,一周后便有了现在这个成果。
⚠️ 买者自慎:这离生产级代码还差得很远,而且充斥着提示词注入以及常见的安全漏洞。我只希望它能对某些人有所帮助 😊
入门非常简单,只需确保满足以下依赖条件即可。
⚠️⚠️⚠️ 非 MACOS 用户请注意: 如果你使用的是 Linux 或 Windows,需要将 docker-compose.yml 第 64 行以及这里的 actions Dockerfile 第 1 行中的镜像名称从 khalosa/rasa-aarch64:3.5.2 改为 rasa/rasa:latest
# Get the code
git clone https://github.com/paulpierre/RasaGPT.git
cd RasaGPT
## Setup the .env file
cp .env-example .env
# Edit your .env file and add all the necessary credentials
make install
# Type "make" to see more options
make
完整的应用程序与 API
LLM 使用 Langchain 从任意数据语料库中“学习”
通过 FastAPI 上传文档并完成全部“训练”
上传时实现文档版本控制和自动“重新训练”
通过 FastAPI 和 SQLModel 自定义异步端点与数据库模型
机器人判断是否需要转交人工处理
机器人根据用户问题和回答自动生成标签
内置通过 Swagger 和 Redoc 生成的完整 API 文档
内置 PGAdmin,方便你浏览数据库
启动时会自动为你生成 Ngrok 端点,因此始终可以通过 https://t.me/yourbotname 访问机器人
通过 pgvector 和 Postgres 函数,在 Postgres 中内置嵌入相似度搜索
内置虚拟数据,方便测试和实验
拥有无限的应用场景,包括服务台、客户支持、测验、在线学习、龙与地下城等
构建于 Rasa 之上,Rasa 是开源聊天平台领域的黄金标准
通过 Docker 支持 MacOS M1/M2(Rasa 官方镜像缺少对 MacOS 架构的支持)
支持 Telegram,并可轻松集成 Slack、Whatsapp、Line、SMS 等平台
使用来自 Huggingface 的 BERT 等 NLU 模型,或 Keras、Tensorflow 等库/框架设置复杂的对话流水线,并将 OpenAI GPT 作为备用方案
使用 Langchain 扩展智能体、记忆等能力
schema 支持多租户、会话和数据存储
自定义智能体人格
保存全部聊天历史,并根据所有交互创建嵌入,为未来的检索策略做好准备
根据知识库语料和客户反馈自动生成嵌入
Docker 与 Docker compose(Docker desktop MacOS)
Telegram 机器人凭据
git clone https://github.com/paulpierre/RasaGPT.git
cd RasaGPT
cp .env-example .env
# Edit your .env file and all the credentials
你随时都可以直接输入 make,它会显示选项列表,这些选项主要用于调试:
最简单的入门方式是使用根目录下的 Makefile。它会按照正确的顺序安装并运行 RasaGPT 的全部服务。
make install
# This will automatically install and run RasaGPT
# After installation, to run again you can simply run
make run
本地 Python 环境
如果你希望专注于基于 API 进行开发,这种方式会很有用。项目为此单独准备了一个 Makefile,它会为你创建本地虚拟环境。
# Assuming you are already in the RasaGPT directory
cd app/api
make install
# This will automatically install and run RasaGPT
# After installation, to run again you can simply run
make run
同样,输入 make 即可查看完整的命令列表。
安装过程应该是自动化的,效果如下:
👉 完整安装日志:https://app.warp.dev/block/vflua6Eue29EPk8EVvW8Kd
从整体上看,Docker 的安装过程包含以下步骤:
检查并确保 .env 可用
使用 pgvector 初始化数据库
数据库模型创建数据库 schema
训练 Rasa 模型,使其准备就绪并可以运行
为 Rasa 配置 ngrok,使 Telegram 能够通过 webhook 回连你的 API 服务器
设置 Rasa actions 服务器,使 Rasa 能够与 RasaGPT API 通信
通过 seed.py 使用虚拟数据填充数据库
访问 👉 https://t.me/yourbotsname 即可开始与机器人聊天
访问 👉 https://localhost:9999/ 即可查看全部日志,该页面会实时显示所有 Docker 容器的日志
访问 👉 https://localhost:8888/docs 即可查看 API 端点文档
在此页面中,你可以创建和更新实体,也可以向知识库上传文档。
这个机器人只是一个概念验证,尚未针对检索进行优化。目前,它使用长度为 1000 个字符的分块进行索引,并使用基础欧氏距离进行检索,因此质量时好时坏。
你可以在 RESULTS.MD 文件中查看该机器人的成功与失败示例。总体而言,我估计通过索引优化和调整 LLM 配置,可以将输出质量提升 70% 以上。
👉 点击查看 RESULTS.MD 中演示数据的问答结果
REST API 非常直观,请访问文档 👉 http://localhost:8888/docs
以下实体支持基本的 CRUD 操作,并返回 JSON。
可以将其视为一家作为你客户的公司,适用于 SaaS/多租户场景。默认情况下,项目已提供一组虚拟组织。
[
{
"id": 1,
"uuid": "d2a642e6-c81a-4a43-83e2-22cee3562452",
"display_name": "Pepe Corp.",
"namespace": "pepe",
"bot_url": null,
"created_at": "2023-05-05T10:42:45.933976",
"updated_at": "2023-05-05T10:42:45.933979"
},
{
"id": 2,
"uuid": "7d574f88-6c0b-4c1f-9368-367956b0e90f",
"display_name": "Umbrella Corp",
"namespace": "acme",
"bot_url": null,
"created_at": "2023-05-05T10:43:03.555484",
"updated_at": "2023-05-05T10:43:03.555488"
},
{
"id": 3,
"uuid": "65105a15-2ef0-4898-ac7a-8eafee0b283d",
"display_name": "Cyberdine Systems",
"namespace": "cyberdine",
"bot_url": null,
"created_at": "2023-05-05T10:43:04.175424",
"updated_at": "2023-05-05T10:43:04.175428"
},
{
"id": 4,
"uuid": "b7fb966d-7845-4581-a537-818da62645b5",
"display_name": "Bluth Companies",
"namespace": "bluth",
"bot_url": null,
"created_at": "2023-05-05T10:43:04.697801",
"updated_at": "2023-05-05T10:43:04.697804"
},
{
"id": 5,
"uuid": "9283d017-b24b-4ecd-bf35-808b45e258cf",
"display_name": "Evil Corp",
"namespace": "evil",
"bot_url": null,
"created_at": "2023-05-05T10:43:05.102546",
"updated_at": "2023-05-05T10:43:05.102549"
}
]
可以将其视为属于某家公司的产品。你可以像下面这样查看属于某个组织的项目列表:
[
{
"id": 1,
"documents": [
{
"id": 1,
"uuid": "92604623-e37c-4935-bf08-0e9efa8b62f7",
"display_name": "project-pepetamine.md",
"node_count": 3
}
],
"document_count": 1,
"uuid": "44a4b60b-9280-4b21-a676-00612be9aa87",
"display_name": "Pepetamine",
"created_at": "2023-05-05T10:42:46.060930",
"updated_at": "2023-05-05T10:42:46.060934"
},
{
"id": 2,
"documents": [
{
"id": 2,
"uuid": "b408595a-3426-4011-9b9b-8e260b244f74",
"display_name": "project-frogonil.md",
"node_count": 3
}
],
"document_count": 1,
"uuid": "5ba6b812-de37-451d-83a3-8ccccadabd69",
"display_name": "Frogonil",
"created_at": "2023-05-05T10:42:48.043936",
"updated_at": "2023-05-05T10:42:48.043940"
},
{
"id": 3,
"documents": [
{
"id": 3,
"uuid": "b99d373a-3317-4699-a89e-90897ba00db6",
"display_name": "project-kekzal.md",
"node_count": 3
}
],
"document_count": 1,
"uuid": "1be4360c-f06e-4494-bf20-e7c73a56f003",
"display_name": "Kekzal",
"created_at": "2023-05-05T10:42:49.092675",
"updated_at": "2023-05-05T10:42:49.092678"
},
{
"id": 4,
"documents": [
{
"id": 4,
"uuid": "94da307b-5993-4ddd-a852-3d8c12f95f3f",
"display_name": "project-memetrex.md",
"node_count": 3
}
],
"document_count": 1,
"uuid": "1fd7e772-365c-451b-a7eb-4d529b0927f0",
"display_name": "Memetrex",
"created_at": "2023-05-05T10:42:50.184817",
"updated_at": "2023-05-05T10:42:50.184821"
},
{
"id": 5,
"documents": [
{
"id": 5,
"uuid": "6deff180-3e3e-4b09-ae5a-6502d031914a",
"display_name": "project-pepetrak.md",
"node_count": 4
}
],
"document_count": 1,
"uuid": "a389eb58-b504-48b4-9bc3-d3c93d2fbeaa",
"display_name": "PepeTrak",
"created_at": "2023-05-05T10:42:51.293352",
"updated_at": "2023-05-05T10:42:51.293355"
},
{
"id": 6,
"documents": [
{
"id": 6,
"uuid": "2e3c2155-cafa-4c6b-b7cc-02bb5156715b",
"display_name": "project-memegen.md",
"node_count": 5
}
],
"document_count": 1,
"uuid": "cec4154f-5d73-41a5-a764-eaf62fc3db2c",
"display_name": "MemeGen",
"created_at": "2023-05-05T10:42:52.562037",
"updated_at": "2023-05-05T10:42:52.562040"
},
{
"id": 7,
"documents": [
{
"id": 7,
"uuid": "baabcb6f-e14c-4d59-a019-ce29973b9f5c",
"display_name": "project-neurokek.md",
"node_count": 5
}
],
"document_count": 1,
"uuid": "4a1a0542-e314-4ae7-9961-720c2d092f04",
"display_name": "Neuro-kek",
"created_at": "2023-05-05T10:42:53.689537",
"updated_at": "2023-05-05T10:42:53.689539"
},
{
"id": 8,
"documents": [
{
"id": 8,
"uuid": "5be007ec-5c89-4bc4-8bfd-448a3659c03c",
"display_name": "org-about_the_company.md",
"node_count": 5
},
{
"id": 9,
"uuid": "c2b3fb39-18c0-4f3e-9c21-749b86942cba",
"display_name": "org-board_of_directors.md",
"node_count": 3
},
{
"id": 10,
"uuid": "41aa81a9-13a9-4527-a439-c2ac0215593f",
"display_name": "org-company_story.md",
"node_count": 4
},
{
"id": 11,
"uuid": "91c59eb8-8c05-4f1f-b09d-fcd9b44b5a20",
"display_name": "org-corporate_philosophy.md",
"node_count": 4
},
{
"id": 12,
"uuid": "631fc3a9-7f5f-4415-8283-78ff582be483",
"display_name": "org-customer_support.md",
"node_count": 3
},
{
"id": 13,
"uuid": "d4c3d3db-6f24-433e-b2aa-52a70a0af976",
"display_name": "org-earnings_fy2023.md",
"node_count": 5
},
{
"id": 14,
"uuid": "08dd478b-414b-46c4-95c0-4d96e2089e90",
可以将它理解为与产品相关的资料,例如 FAQ 页面或包含财务报表收益数据的 PDF。你可以像下面这样查看与某个组织的项目关联的所有文档:
{
"id": 1,
"uuid": "44a4b60b-9280-4b21-a676-00612be9aa87",
"organization": {
"id": 1,
"uuid": "d2a642e6-c81a-4a43-83e2-22cee3562452",
"display_name": "Pepe Corp.",
"bot_url": null,
"status": 2,
"created_at": "2023-05-05T10:42:45.933976",
"updated_at": "2023-05-05T10:42:45.933979",
"namespace": "pepe"
},
"document_count": 1,
"documents": [
{
"id": 1,
"uuid": "92604623-e37c-4935-bf08-0e9efa8b62f7",
"organization_id": 1,
"project_id": 1,
"display_name": "project-pepetamine.md",
"url": "",
"data": "# Pepetamine\n\nProduct Name: Pepetamine\n\nPurpose: Increases cognitive focus just like the Limitless movie\n\n**How to Use**\n\nPepetamine is available in the form of rare Pepe-coated tablets. The recommended dosage is one tablet per day, taken orally with a glass of water, preferably while browsing your favorite meme forum for maximum cognitive enhancement. For optimal results, take Pepetamine 30 minutes before engaging in mentally demanding tasks, such as decoding ancient Pepe hieroglyphics or creating your next viral meme masterpiece.\n\n**Side Effects**\n\nSome potential side effects of Pepetamine may include:\n\n1. Uncontrollable laughter and a sudden appreciation for dank memes\n2. An inexplicable desire to collect rare Pepes\n3. Enhanced meme creation skills, potentially leading to internet fame\n4. Temporary green skin pigmentation, resembling the legendary Pepe himself\n5. Spontaneously speaking in \"feels good man\" language\n\nWhile most side effects are generally harmless, consult your memologist if side effects persist or become bothersome.\n\n**Precautions**\n\nBefore taking Pepetamine, please consider the following precautions:\n\n1. Do not use Pepetamine if you have a known allergy to rare Pepes or dank memes.\n2. Pepetamine may not be suitable for individuals with a history of humor deficiency or meme intolerance.\n3. Exercise caution when driving or operating heavy machinery, as Pepetamine may cause sudden fits of laughter or intense meme ideation.\n\n**Interactions**\n\nPepetamine may interact with other substances, including:\n\n1. Normie supplements: Combining Pepetamine with normie supplements may result in meme conflicts and a decreased sense of humor.\n2. Caffeine: The combination of Pepetamine and caffeine may cause an overload of energy, resulting in hyperactive meme creation and potential internet overload.\n\nConsult your memologist if you are taking any other medications or substances to ensure compatibility with Pepetamine.\n\n**Overdose**\n\nIn case of an overdose, symptoms may include:\n\n1. Uncontrollable meme creation\n2. Delusions of grandeur as the ultimate meme lord\n3. Time warps into the world of Pepe\n\nIf you suspect an overdose, contact your local meme emergency service or visit the nearest meme treatment facility. Remember, the key to enjoying Pepetamine is to use it responsibly, and always keep in mind the wise words of our legendary Pepe: \"Feels good man.\"",
"hash": "fdee6da2b5441080dd78e7850d3d2e1403bae71b9e0526b9dcae4c0782d95a78",
"version": 1,
"status": 2,
"created_at": "2023-05-05T10:42:46.755428",
"updated_at": "2023-05-05T10:42:46.755431"
}
],
"display_name": "Pepetamine",
"created_at": "2023-05-05T10:42:46.060930",
"updated_at": "2023-05-05T10:42:46.060934"
}
尽管 API 并未公开这一概念,但节点是文档中用于生成嵌入向量的一个分块。节点既用于检索搜索,也用于上下文注入。节点隶属于文档。
用户代表正在与机器人交谈的人。用户不一定隶属于某个组织或产品,但这种关系会记录在下文的 ChatSession 中。
虽然 API 并未公开这一概念,但它表示用户与机器人之间的一组问答。每个此类对象都可以通过自动生成的 session_id 灵活标识。聊天会话包含丰富的元数据,可用于训练和优化。通过 /chat 端点创建的 ChatSession 实际上会与组织关联(出于多租户安全目的)。
Rasa 负责与通信渠道集成,在本例中是 Telegram。具体来说,它负责将用户反馈提交到目标 webhook。在我们的场景中,目标是 FastAPI 服务器的 /webhooks/{channel}/webhook。
具体来说,它负责将用户反馈提交到目标 webhook。在我们的场景中,目标是 FastAPI 服务器的 /webhooks/{channel}/webhook。
Rasa 包含两个组件:核心 Rasa 应用,以及一个独立运行的 Rasa actions 服务器。
Rasa 必须通过几个 YAML 文件进行配置(已完成):
config.yml - 包含 NLU 流水线和策略配置。关键是设置 FallbackClassifier 的阈值
credentials.yml - 包含 Webhook 路径和 Telegram 凭据。辅助服务 rasa-credentials 会通过 app/rasa-credentials/main.py 更新此文件
domain.yml - 包含聊天入口逻辑配置,例如意图以及针对该意图执行的动作。我们在这里添加 action_gpt_fallback 动作,它会触发我们的 actions server
endpoints.yml - 在这里设置自定义 action 端点,供 Rasa 触发回退逻辑
nlu.yml - 在这里设置 out_of_scope 意图
rules.yml - 为此意图设置一条规则,使其触发 action_gpt_fallback 动作
actions.py - 在这里通过 ActionGPTFallback 类定义并实现我们的动作。name 方法返回我们在上面为意图定义的动作
config.yml - 包含 NLU 流水线和策略配置。关键是设置 FallbackClassifier 的阈值
credentials.yml - 包含 Webhook 路径和 Telegram 凭据。辅助服务 rasa-credentials 会通过 app/rasa-credentials/main.py 更新此文件
domain.yml - 包含聊天入口逻辑配置,例如意图以及针对该意图执行的动作。我们在这里添加 action_gpt_fallback 动作,它会触发我们的 actions server
endpoints.yml - 在这里设置自定义 action 端点,供 Rasa 触发回退逻辑
nlu.yml - 在这里设置 out_of_scope 意图
rules.yml - 为此意图设置一条规则,使其触发 action_gpt_fallback 动作
actions.py - 在这里通过 ActionGPTFallback 类定义并实现我们的动作。name 方法返回我们在上面为意图定义的动作
必须训练 Rasa 的 NLU 模型,可以通过 CLI 执行 rasa train 来完成。当你运行 make install 时,这一步会自动完成
训练完成后,必须通过 rasa run 启动 Rasa core
必须单独使用 rasa run actions 启动 Rasa action server
Rasa 会使用 credentials.yml 中的回调 Webhook 自动更新 Telegram Bot API。
默认情况下,该地址是静态的。由于我们是在本地计算机上运行,因此利用 Ngrok 生成一个可公开访问的 URL,并通过反向隧道连接到 Docker 容器
rasa-credentials 服务会替你处理此过程。Ngrok 作为服务运行;准备就绪后,rasa-credentials 会调用本地 Ngrok API 获取隧道 URL、更新 credentials.yml 文件,并替你重启 Rasa
Telegram 会将消息发送到我们的 FastAPI server Webhook。为什么不直接发送给 Rasa?因为我们希望能够灵活地捕获元数据,而在 Rasa 中实现这一点非常麻烦,并且将其集中到 API server 是更理想的方案
FastAPI server 会将消息转发到 Rasa Webhook
然后,Rasa 会根据用户意图确定要执行的动作。由于本演示弱化了其他意图,因此消息会进入 actions.py 中运行的回退动作
自定义动作会捕获元数据,并将 FastAPI 返回的响应转发给用户
pgvector 是 Postgres 的一个插件,会被自动安装,使你能够存储和计算向量数据类型。我们使用自己的实现,因为 Langchain 的 PGVector 类不够灵活,无法适配我们的 schema,而我们希望保留灵活性。
默认情况下,在 Postgres 中,如果数据库尚未初始化,容器路径 /docker-entry-initdb.d 下的所有文件都会被执行。在 Postgres Dockerfile 中,我们复制了 create_db.sh,它会为数据库创建 db 和用户
在 Makefile 的 models 命令中,我们会运行 API 容器内的 models.py,根据模型创建数据表。
enable_vector 方法会在数据库中启用 pgvector 扩展
训练数据会被加载到数据库中
如果索引不存在,则会为数据建立索引,并将其存储在名为 index.json 的文件中
LlamaIndex 使用基础的 GPTSimpleVectorIndex 查找相关数据,并将其注入 prompt。
通过 prompt 中的护栏,让对话保持聚焦
用户将在 Telegram 中聊天,消息会根据现有意图进行筛选
如果检测不到匹配的意图,而是匹配到 out_of_scope,则会根据 rules.yml 触发 action_gpt_fallback 动作
随后,ActionGPTFallback 函数会调用 FastAPI API server
API 使用 LlamaIndex 查找相关的已索引内容,将其注入 prompt,然后发送给 OpenAI 进行推理
该 prompt 包含对话护栏,其中包括:要求以 JSON 格式返回数据;根据用户的问题创建分类标签;如果对话应升级给人工处理(即没有匹配的上下文),则返回一个布尔值
要求以 JSON 格式返回数据
根据用户的问题创建分类标签
如果对话应升级给人工处理(即没有匹配的上下文),则返回一个布尔值
实现 LlamaIndex 优化
实现聊天历史记录
实现 Query Routers 抽象,以判断应使用哪种搜索策略(one-shot 与 few-shot)
探索其他索引方法,例如 Tree indexes、Keyword indexes
添加聊天历史记录,以便即时回忆和设置上下文
添加一个辅助的对抗性智能体(Dual pattern model),它可能具备以下功能:判断问题是否已得到回答;如果没有,则重新优化搜索策略;确保没有发生 prompt injection
判断问题是否已得到回答;如果没有,则重新优化搜索策略
确保没有发生 prompt injection
通过探索以下方式提高基线相似度搜索效果:基于历史查询定期生成“伪造”的文档嵌入,并通过 HyDE pattern 将其关联到真实文档;基于文档定期生成“伪造”的用户查询,并将其关联到真实文档,使用户输入搜索能够更好地匹配这些“伪造”查询
基于历史查询定期生成“伪造”的文档嵌入,并通过 HyDE pattern 将其关联到真实文档
基于文档定期生成“伪造”的用户查询,并将其关联到真实文档,使用户输入搜索能够更好地匹配这些“伪造”查询
通常,只需访问 👉 http://localhost:9999/ 即可检查 Docker 容器日志
始终检查 Ngrok 和 Telegram 的 Webhook 是否匹配。只需执行以下命令:
curl -sS "https://api.telegram.org/bot<your-bot-secret-token>/getWebhookInfo" | json_pp
……应该返回:
{
"ok": true,
"result": {
"url": "https://b280-04-115-40-112.ngrok-free.app/webhooks/telegram/webhook",
"has_custom_certificate": false,
"pending_update_count": 0,
"max_connections": 40,
"ip_address": "1.2.