专为模块化应用设计的RAG框架,支持灵活组件化搭建;对构建AI知识库系统的团队高度实用。
本项目不再积极维护。我们感谢所有贡献者的贡献。
Langchain/LlamaIndex 提供易于使用的抽象,可用于在 Jupyter 笔记本上进行快速实验和原型设计。但是,当项目移到生产环境时,会面临一些约束,如组件应该是模块化、易扩展和易扩容的。这正是 Cognita 发挥作用的地方。Cognita 在底层使用 Langchain/LlamaIndex,并为你的代码库提供组织结构,其中每个 RAG 组件都是模块化的、API 驱动的,并且易于扩展。Cognita 可以轻松用于本地设置,同时也提供生产就绪的环境以及无代码 UI 支持。Cognita 默认还支持增量索引。
你可以在以下地址尝试 Cognita:https://cognita.truefoundry.com
[2024 年 9 月] Cognita 现在拥有 AudioParser(https://github.com/fedirz/faster-whisper-server)和 VideoParser(AudioParser + MultimodalParser)。
[2024 年 8 月] Cognita 已迁移到使用 pydantic v2。
[2024 年 7 月] 推出 model gateway,这是一个用于管理所有模型及其配置的单一文件。
[2024 年 6 月] Cognita 现在拥有自己的 Metadatastore,由 Prisma 和 PostgreSQL 提供支持。你现在可以完全通过 UI 使用 Cognita,而无需本地 metadata.yaml 文件。你可以通过 UI 创建集合、数据源并对其进行索引。这样可以更容易地使用 Cognita,无需进行任何代码更改。
[2024 年 6 月] 添加了 Cognita 的一键本地部署功能。你现在可以使用 docker-compose 运行整个 Cognita 系统。这样可以更容易地在本地进行测试和开发。
[2024 年 5 月] 添加了使用 Infinity Server 进行嵌入和重排的支持。你现在可以使用托管服务来获得 Hugging Face 上可用的各种嵌入和重排服务。这减轻了主 Cognita 系统的负担,使其更易扩展。
[2024 年 5 月] 清理了向量数据库、解析器、嵌入器和重排器的可选包安装依赖项。
[2024 年 5 月] 具有可选包安装参数的条件性 Docker 构建。
[2024 年 4 月] 使用 GPT-4 支持多模态视觉解析器。
目录
Cognita 是一个开源框架,用于组织你的 RAG 代码库,并附带一个前端来尝试不同的 RAG 定制。它提供了一种简单的方式来组织你的代码库,使得在本地测试变得容易,同时也能够在生产就绪的环境中部署。从 Jupyter 笔记本生产化 RAG 系统时出现的关键问题包括:
分块和嵌入作业:分块和嵌入代码通常需要被抽象出来并部署为一项作业。有时该作业需要按计划运行或通过事件触发,以保持数据最新。
查询服务:从查询生成答案的代码需要被封装到 API 服务器(如 FastAPI)中,并应部署为一项服务。该服务应能够同时处理多个查询,并且能够随着流量增加而自动扩展。
LLM/嵌入模型部署:通常,如果我们使用开源模型,我们会在 Jupyter 笔记本中加载模型。在生产环境中,这需要作为单独的服务托管,模型需要通过 API 调用。
向量数据库部署:大多数测试发生在内存或磁盘上的向量数据库。但在生产环境中,数据库需要以更可扩展和可靠的方式部署。
Cognita 使得定制和实验 RAG 系统的所有方面变得非常容易,同时仍然能够以良好的方式部署它。它还附带一个 UI,可以更容易地尝试不同的 RAG 配置并实时查看结果。你可以在本地使用它,或者使用/不使用任何 Truefoundry 组件。但是,使用 Truefoundry 组件可以更容易地测试不同的模型并以可扩展的方式部署系统。Cognita 允许你使用一个应用程序托管多个 RAG 系统。
使用 Cognita 的优势包括:
Cognita 及其所有服务都可以使用 docker-compose 运行。这是在本地运行 Cognita 的推荐方式。从以下地址为你的系统安装 Docker 和 docker-compose:Docker Compose
在启动服务之前,我们需要配置我们进行嵌入和生成答案所需的模型提供者。
首先,将 models_config.sample.yaml 复制到 models_config.yaml
cp models_config.sample.yaml models_config.yaml
默认情况下,配置已启用本地提供者,这些提供者需要 infinity 和 ollama 服务器来在本地运行嵌入和 LLM。但是,如果你有 OpenAI API 密钥,你可以取消注释 models_config.yaml 中的 openai 提供者,并更新 compose.env 中的 OPENAI_API_KEY
现在,你可以运行以下命令来启动服务:
docker-compose --env-file compose.env up
compose 文件使用 compose.env 文件作为环境变量。你可以根据需要修改它。
compose 文件将启动以下服务:
一旦服务启动,你可以在 http://localhost:6333 访问 qdrant 服务器,在 http://localhost:8000 访问后端,在 http://localhost:5001 访问前端。
要启动其他服务(如 ollama 和 infinity-server),你可以运行以下命令:
docker-compose --env-file compose.env --profile ollama --profile infinity up
这将启动 ollama 和 infinity-server 的额外服务器,可分别用于 LLM、嵌入和重排。你可以在 http://localhost:7997 访问 infinity-server。
如果要在本地构建后端/前端镜像,例如当你添加新的需求/包/从 Github 拉取新版本时,你可以向命令添加 --build 标志。
docker-compose --env-file compose.env up --build
docker-compose --env-file compose.env --profile ollama --profile infinity up --build
Docker compose 是在本地运行整个 Cognita 系统的好方式。后端文件夹中所做的任何更改都会自动反映在运行中的后端服务器中。您可以通过更改后端代码来测试不同的 API 和端点。
总体上,Cognita 的架构由几个实体组成
数据源 - 这些是包含要被索引的文档的位置。通常这些是 S3 存储桶、数据库、TrueFoundry Artifacts 或甚至本地磁盘
数据源 - 这些是包含要被索引的文档的位置。通常这些是 S3 存储桶、数据库、TrueFoundry Artifacts 或甚至本地磁盘
元数据存储 - 此存储包含关于集合本身的元数据。集合是指来自一个或多个数据源的一组文档的组合。对于每个集合,集合元数据存储集合名称关联的向量 DB 集合名称链接的数据源每个数据源的解析配置要使用的嵌入模型和配置
元数据存储 - 此存储包含关于集合本身的元数据。集合是指来自一个或多个数据源的一组文档的组合。对于每个集合,集合元数据存储
集合名称
关联的向量 DB 集合名称
每个数据源的解析配置
要使用的嵌入模型和配置
LLM 网关 - 这是一个中央代理,允许通过统一的 API 格式代理对多个提供商的各种嵌入和 LLM 模型的请求。这可以是 OpenAIChat、OllamaChat,甚至使用 TF LLM 网关的 TruefoundryChat。
LLM 网关 - 这是一个中央代理,允许通过统一的 API 格式代理对多个提供商的各种嵌入和 LLM 模型的请求。这可以是 OpenAIChat、OllamaChat,甚至使用 TF LLM 网关的 TruefoundryChat。
向量 DB - 这存储了集合已解析文件的嵌入和元数据。可以查询它以获取相似的块或基于过滤器的精确匹配。我们目前支持 Qdrant 和 SingleStore 作为我们选择的向量数据库。
向量 DB - 这存储了集合已解析文件的嵌入和元数据。可以查询它以获取相似的块或基于过滤器的精确匹配。我们目前支持 Qdrant 和 SingleStore 作为我们选择的向量数据库。
索引任务 - 这是一个异步任务,负责编排索引流程。索引可以手动启动或定期按照 cron 计划运行。它将扫描数据源以获取文档列表检查向量 DB 状态以过滤掉未更改的文档下载并解析文件以创建更小的块,每个块都有关联的元数据使用 AI 网关嵌入这些块并将其放入向量 DB。源代码位于 backend/indexer/
索引任务 - 这是一个异步任务,负责编排索引流程。索引可以手动启动或定期按照 cron 计划运行。它将
扫描数据源以获取文档列表
检查向量 DB 状态以过滤掉未更改的文档
下载并解析文件以创建更小的块,每个块都有关联的元数据
使用 AI 网关嵌入这些块并将其放入向量 DB。源代码位于 backend/indexer/
源代码位于 backend/indexer/
API 服务器 - 此组件同步处理用户查询以生成带有参考信息的答案。每个应用程序对检索和答案过程拥有完全控制权。从广义上讲,当用户发送请求时,相应的查询控制器根据配置启动检索器或多步 AI 智能体。使用 AI 网关处理并嵌入用户的问题。一个或多个检索器与向量 DB 交互以获取相关的块和元数据。通过 AI 网关使用 LLM 形成最终答案。在该过程中获取的相关文档的元数据可以可选地进行扩展。例如添加预签名 URL。此组件的代码位于 backend/server/
API 服务器 - 此组件同步处理用户查询以生成带有参考信息的答案。每个应用程序对检索和答案过程拥有完全控制权。从广义上讲,当用户发送请求时
相应的查询控制器根据配置启动检索器或多步 AI 智能体。
使用 AI 网关处理并嵌入用户的问题。
一个或多个检索器与向量 DB 交互以获取相关的块和元数据。
通过 AI 网关使用 LLM 形成最终答案。
在该过程中获取的相关文档的元数据可以可选地进行扩展。例如添加预签名 URL。此组件的代码位于 backend/server/
此组件的代码位于 backend/server/
某个计划上的 Cron 将触发索引任务
扫描与集合关联的数据源以获取所有数据点(文件)
该任务比较 VectorDB 状态与数据源状态,以确定新添加的文件、更新的文件和删除的文件。下载新文件和更新的文件
解析新添加和更新的文件,并将其分块成更小的片段,每个片段都有自己的元数据
使用嵌入模型(如来自 openai 的 text-ada-002 或来自 mixedbread-ai 的 mxbai-embed-large-v1)嵌入块
将嵌入的块放入 VectorDB,带有自动生成和提供的元数据
❓ 使用 API 服务器进行问答:
用户发送包含其查询的请求
用户发送包含其查询的请求
它被路由到应用的查询控制器之一
它被路由到应用的查询控制器之一
在向量 DB 之上构造一个或多个检索器
在向量 DB 之上构造一个或多个检索器
然后构建问答链或 AI 智能体。它嵌入用户查询并获取相似的块。
然后构建问答链或 AI 智能体。它嵌入用户查询并获取相似的块。
单步问答链只是根据相似的块生成答案。AI 智能体可以执行多步推理,并在得出答案之前使用许多工具。在这两种情况下,API 服务器都使用 LLM 模型(如 GPT 3.5、GPT 4 等)
单步问答链只是根据相似的块生成答案。AI 智能体可以执行多步推理,并在得出答案之前使用许多工具。在这两种情况下,API 服务器都使用 LLM 模型(如 GPT 3.5、GPT 4 等)
在返回答案之前,相关块的元数据可以使用诸如预签名 URL、周围幻灯片、外部数据源链接之类的内容进行更新。
在返回答案之前,相关块的元数据可以使用诸如预签名 URL、周围幻灯片、外部数据源链接之类的内容进行更新。
答案和相关文档块在响应中返回。注意:在 AI 智能体的情况下,中间步骤也可以流式传输。由具体应用程序决定。
答案和相关文档块在响应中返回。
注意:在 AI 智能体的情况下,中间步骤也可以流式传输。由具体应用程序决定。
为您的用例自定义代码
Cognita 采用的标语是 -
一切都可用,一切都可定制。
Cognita 使在解析器、加载器、模型和检索器之间轻松切换成为可能。
自定义数据加载器:
您可以通过继承来自 backend/modules/dataloaders/loader.py 的 BaseDataLoader 类来编写自己的数据加载器
您可以通过继承来自 backend/modules/dataloaders/loader.py 的 BaseDataLoader 类来编写自己的数据加载器
最后,在 backend/modules/dataloaders/init.py 中注册加载器
最后,在 backend/modules/dataloaders/init.py 中注册加载器
在 localdir 上测试数据加载器,在根目录中,将以下代码复制为 test.py 并执行。我们演示如何在此处测试现有的 LocalDirLoader:
from backend.modules.dataloaders import LocalDirLoader
from backend.types import DataSource
data_source = DataSource(
type="local",
uri="sample-data/creditcards",
)
loader = LocalDirLoader()
loaded_data_pts = loader.load_full_data(
data_source=data_source,
dest_dir="test/creditcards",
)
for data_pt in loaded_data_pts:
print(data_pt)
自定义嵌入器:
代码库目前默认使用 Langchain 的 OpenAIEmbeddings 来生成嵌入
你可以在 models_config.yaml 文件中注册任何 OpenAI 兼容的自定义嵌入向量,重启服务器即可生效。
你可以通过继承 backend/modules/parsers/parser.py 中的 BaseParser 类来编写自己的解析器。
最后,在 backend/modules/parsers/__init__.py 中注册解析器。
在项目根目录,复制以下代码作为 test.py 并执行。这里展示如何测试现有的 MarkdownParser:
import asyncio
from backend.modules.parsers import MarkdownParser
parser = MarkdownParser()
chunks = asyncio.run(
parser.get_chunks(
filepath="sample-data/creditcards/diners-club-black.md",
)
)
print(chunks)
要为 VectorDB 添加自己的接口,你可以继承 backend/modules/vector_db/base.py 中的 BaseVectorDB。
在 backend/modules/vector_db/__init__.py 中注册该 vectordb。
代码通过实现 RAG 应用的查询接口来负责。这些查询控制器中定义的方法会被添加为 FastAPI 服务器的路由。
在 backend/modules/query_controllers/ 中添加你的查询控制器类。
为你的类添加 query_controller 装饰器,并传入自定义控制器的名称作为参数:
from backend.server.decorator import query_controller
@query_controller("/my-controller")
class MyCustomController():
...
根据需要向该控制器添加方法,并使用我们的 http 装饰器(如 post、get、delete)使你的方法成为 API:
from backend.server.decorator import post
@query_controller("/my-controller")
class MyCustomController():
...
@post("/answer")
def answer(query: str):
# 编写代码来表达你的回答逻辑
# 该 API 将暴露为 POST /my-controller/answer
...
在 backend/modules/query_controllers/__init__.py 中导入你的自定义控制器类:
...
from backend.modules.query_controllers.sample_controller.controller import MyCustomController
作为参考,我们在 backend/modules/query_controllers/example 中实现了示例控制器。请参考该示例以获得更好的理解。
按照以下步骤来查询你自己的文档:
注册 TrueFoundry,请参考这里。
填写表格并注册为一个组织(比如 <org_name>)。
提交后,你将被重定向到你的仪表板端点,即 https://<org_name>.truefoundry.cloud。
完成邮箱验证。
在仪表板端点登录该平台,即 https://<org_name>.truefoundry.cloud。
注意:保存你的仪表板端点,我们将其称为 "TFY_HOST",其结构应该如下:https://<org_name>.truefoundry.cloud。
使用 TrueFoundry 托管服务以快速设置。
给你的集群起一个唯一的名字,然后点击"启动集群"。
这需要几分钟来为你配置一个集群。
在"配置主机域"部分,点击为预先填充的 IP 地址进行注册。
接下来,添加一个 Docker Registry 来推送你的 docker 镜像。
接下来,部署一个模型,你也可以选择跳过该步骤。
添加存储集成。
导航到"ML Repo"选项卡。
点击右上角的"+ New ML Repo"按钮。
给你的 ML Repo 起一个唯一的名字(比如 docs-qa-llm)。
选择存储集成。
提交后,你的 ML Repo 将被创建。更多细节请参考链接。
导航到"Workspace"选项卡。
点击右上角的"+ New Workspace"按钮。
选择你的集群。
给你的工作空间起一个名字(比如 docs-qa-llm)。
启用 ML Repo 访问并添加 ML Repo 访问。
选择你的 ML Repo 并将角色设为项目管理员。
提交后,一个新的工作空间将被创建。你可以通过点击 FQN 来复制工作空间的 FQN。更多细节请参考链接。