Cognita
为什么使用 Cognita?
Langchain/LlamaIndex 提供了易于使用的抽象,可以用于在 jupyter 笔记本上快速进行实验和原型设计。但当项目进入生产阶段时,需要考虑比如组件应该是模块化的、易于扩展和伸缩的等限制。Cognita 就是在这种情况下发挥作用的工具。 Cognita 在底层使用 Langchain/Llamaindex,并且为你的代码库提供了一种组织方式,使每个 RAG 组件模块化、API 驱动并且易于扩展。Cognita 可以很容易地在本地设置,同时,还为你提供了一个无代码UI支持的生产就绪环境。Cognita 默认支持增量索引。
你可以在这里试用 Cognita:https://cognita.truefoundry.com
🎉 Cognita 的新功能
- [2024年8月] Cognita 现在使用 pydantic v2。
- [2024年7月] 引入
model gateway
,一个用于管理所有模型及其配置的单文件。 - [2024年6月] Cognita 现在支持由 Prisma 和 Postgress 驱动的自身 Metadatastore。你现在可以完全通过 UI 使用 Cognita,而不需要
local.metadata.yaml
文件。你可以通过 UI 创建集合、数据源并进行索引。这使得使用 Cognita 更加简单,无需代码更改。 - [2024年6月] 增加了一键本地部署 Cognita 的功能。你现在可以使用 docker-compose 运行整个 Cognita 系统。这使得本地测试和开发更加简单。
- [2024年5月] 增加了使用 Infninty Server 的 Embedding 和 Reranking 支持。你现在可以使用 huggingface 上的各种 embedding 和 reranking 服务来托管服务。这减少了主 Cognita 系统的负担,使其更具伸缩性。
- [2024年5月] 清理了可选包安装的依赖项要求,包括向量数据库、解析器、嵌入器和重排序器。
- [2024年5月] 条件 docker 构建,带有可选包安装的参数。
- [2024年4月] 支持使用 GPT-4 的多模态视觉解析器。
目录
- Cognita
- 🎉 Cognita 的新功能
- 目录
- :rocket: 快速开始:本地运行 Cognita
- :hammer_and_pick: 项目架构
- :bulb: 编写查询控制器(QnA):
- :whale: 通过 Truefoundry 部署快速开始:
- :sparkling_heart: 开源贡献
- :crystal_ball: 未来发展
- Star 历史
介绍
Cognita 是一个开源框架,用于组织你的 RAG 代码库,并提供一个前端来进行不同 RAG 定制的交互。它提供了一种简单的方式来组织你的代码库,使其在本地测试变得容易,同时也能在生产环境中部署。将 RAG 系统从 Jupyter Notebook 推向生产时,通常会出现以下关键问题:
- 分块和嵌入作业:分块和嵌入代码通常需要抽象出来,并作为一个作业进行部署。有时,作业需要按计划运行,或通过事件触发,以保持数据的更新。
- 查询服务:生成查询答案的代码需要包装在一个例如 FastAPI 的 API 服务器中,并作为一个服务进行部署。这个服务应该能够同时处理多个查询,并且能够随着流量的增加进行自动扩展。
- LLM / 嵌入模型部署:通常,如果我们使用开源模型,我们会在 Jupyter notebook 中加载模型。这在生产中需要作为一个单独的服务进行托管,并且需要通过 API 调用模型。
- 向量数据库部署:大多数测试在内存或磁盘上的向量数据库上进行。然而,在生产中,数据库需要以更具伸缩性和可靠的方式部署。
Cognita 使得定制和实验 RAG 系统中的每个部分变得非常容易,同时仍然能够很好地部署它。它还附带一个 UI,使得尝试不同 RAG 配置并实时查看结果变得更加容易。你可以在本地使用它,也可选择是否使用任何 Truefoundry 组件。不过,使用 Truefoundry 组件使得测试不同模型和在可扩展的方式中部署系统更加容易。Cognita 允许你使用一个应用托管多个 RAG 系统。
使用 Cognita 的优势:
- 一个中央可重用的解析器、加载器、嵌入器和检索器仓库。
- 非技术用户可以通过 UI 进行交互——上传文档并使用开发团队构建的模块进行问答。
- 完全 API 驱动——允许与其他系统集成。
如果你与 Truefoundry AI Gateway 一起使用 Cognita,你可以为用户查询获得日志、度量和反馈机制。
特点:
- 支持多个文档检索器,使用
相似性搜索
、查询分解
、文档重排序
等等。 - 支持使用
mixedbread-ai
的最新开源嵌入和重排序。 - 支持使用
ollama
的 LLM。 - 支持批量递增索引(减少计算负担),跟踪已索引的文档并防止重新索引这些文档。
:rocket: 快速开始:本地运行 Cognita
:whale: 使用 Docker compose(推荐 - 25+版本)
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 Key,你可以取消注释 models_config.yaml
中的 openai
提供者,并在 compose.env
中更新 OPENAI_API_KEY
。
现在,你可以运行以下命令来启动服务:
docker-compose --env-file compose.env up
- 组合文件使用
compose.env
文件来获取环境变量。你可以根据需要修改它。 - 组合文件将启动以下服务:
cognita-db
- 用于存储集合和数据源元数据的 Postgres 实例。qdrant-server
- 用于启动本地向量数据库服务器。cognita-backend
- 用于启动 Cognita 的 FastAPI 后端服务器。cognita-frontend
- 用于启动 Cognita 的前端。
- 一旦服务启动,你可以在
http://localhost:6333
访问 qdrant 服务器,在http://localhost:8000
访问后端,在http://localhost:5001
访问前端。
要启动其他服务,例如 ollama
和 infinity-server
,你可以运行以下命令:
docker-compose --env-file compose.env --profile ollama --profile infinity up
-
这将启动用于 LLM、嵌入和重排序的其他服务器
ollama
和infinity-server
。你可以在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
在 Cognita 中开发
Docker compose 是本地运行整个 Cognita 系统的极好方式。你在 backend
文件夹中进行的任何更改都将自动反映在运行的后端服务器中。你可以通过更改后端代码来测试不同的 API 和端点。
:hammer_and_pick: 项目架构
整体而言,Cognita 的架构由多个实体组成
Cognita 组件:
-
数据源 - 这些是包含你要索引的文档的地方。通常这些是 S3 存储桶、数据库、TrueFoundry Artifacts 甚至是本地磁盘
-
元数据存储 - 该存储包含关于集合本身的元数据。集合指的是来自一个或多个数据源的文档集合。对于每个集合,集合元数据存储有
- 集合的名称
- 相关联的向量数据库集合的名称
- 链接的数据源
- 每个数据源的解析配置
- 使用的嵌入模型和配置
-
LLM 网关 - 这是一个中央代理,允许通过统一的 API 格式代理请求到各种嵌入和 LLM 模型。这可以是 OpenAIChat、OllamaChat,甚至是使用 TF LLM Gateway 的 TruefoundryChat。
-
向量数据库 - 该数据库存储每个集合的已解析文件的嵌入和元数据。可以查询以获取基于过滤器的相似块或精确匹配的结果。目前我们支持
Qdrant
和SingleStore
作为选择的向量数据库。 -
索引作业 - 这是一个负责协调索引流程的异步作业。索引可以手动启动或定期在 cron 时间表上运行。它将
- 扫描数据源以获取文件列表
- 检查向量数据库状态以过滤出未更改的文件
- 下载并解析文件以创建具有相关元数据的更小块
- 使用 AI Gateway 将这些块进行嵌入,并将它们放入向量数据库
此部分的源代码在
backend/indexer/
中
-
API 服务器 - 此组件同步处理用户查询以生成带有参考文档的答案。每个应用对于检索和回答过程都有完全的控制权。一般来说,当用户发送请求时
- 相应的查询控制器根据配置引导检索器或多步骤代理。
- 使用者的问题通过 AI Gateway 进行处理和嵌入。
- 一个或多个检索器与向量数据库交互以获取相关块和元数据。
- 使用 LLM 通过 AI 网关形成最终答案。
- 在返回答案之前,可以选择丰富相关文档在处理过程中的元数据。例如,添加预签名的 URL。
此组件的代码在
backend/server/
中
数据索引:
- 某个时间表上的 cron 将触发索引作业
- 与集合关联的数据源被 扫描 以获取所有数据点(文件)
- 作业将向量数据库状态与数据源状态进行比较,以确定 新添加的文件、更新的文件和删除的文件。新添加和更新的文件将 下载
- 新添加和更新的文件将 解析并分块 成更小的块,每个块都有自己的元数据
- 使用嵌入模型(如
text-ada-002
来自openai
或mxbai-embed-large-v1
来自mixedbread-ai
)来 嵌入 这些块 - 将嵌入的块连同自动生成和提供的元数据一起放入向量数据库
:question: 使用 API 服务器进行问答:
-
用户发送带有查询的请求
-
请求被路由到应用的查询控制器之一
-
在向量数据库上构建一个或多个检索器
-
然后构建问题回答链/代理。它嵌入用户查询并获取相似的块。
-
一个单次问题回答链只生成一个给定相似块的答案。代理可以进行多步骤推理并在得出结论前使用许多工具。在这两种情况下,API 服务器使用 LLM 模型(如 GPT 3.5,GPT 4 等)
-
在返回答案之前,可以用例如预签名 URL 等内容更新相关块的元数据。
-
答案和相关文档块在响应中返回。
注意: 在代理的情况下,中间步骤也可以被流式传输。这由特定应用来决定。
为你的用例定制代码
Cognita 的宗旨是:
一切都可用,一切都可定制。
Cognita 使得在解析器、加载器、模型和检索器之间切换变得非常容易。
定制数据加载器:
-
你可以通过继承
backend/modules/dataloaders/loader.py
中的BaseDataLoader
类来编写自己的数据加载器 -
最后,在
backend/modules/dataloaders/__init__.py
中注册加载器 -
在根目录下,通过以下代码作为
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)
定制嵌入器:
- 代码库目前使用
OpenAIEmbeddings
注册为default
。 - 你可以在
backend/modules/embedder/__init__.py
中注册自定义的嵌入。 - 你还可以添加自己的嵌入器,示例见
backend/modules/embedder/mixbread_embedder.py
。它继承了 langchain embedding 类。
定制解析器:
-
你可以通过继承
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)
添加自定义向量数据库:
- 要添加自己的向量数据库接口,你可以继承
backend/modules/vector_db/base.py
中的BaseVectorDB
- 在
backend/modules/vector_db/__init__.py
中注册向量数据库
:bulb: 编写查询控制器(QnA):
负责实现 RAG 应用查询接口的代码。这些查询控制器中定义的方法将作为你的 FastAPI 服务器中的路由。
添加自定义查询控制器的步骤:
- 在
backend/modules/query_controllers/
中添加查询控制器类 - 为你的类添加
query_controller
修饰器,并 @post("/answer") def answer(query: str):编写代码来表达你的答案逻辑
此API将暴露为 POST /my-controller/answer
...
...
from backend.modules.query_controllers.sample_controller.controller import MyCustomController
例如,我们在
backend/modules/query_controllers/example
中实现了示例控制器。请参考以便更好理解
:whale: 快速开始:使用Truefoundry部署:
为了能够在自己的文档上进行查询,请按照以下步骤操作:
-
注册TrueFoundry,点击这里
- 填写表格并以组织(如<org_name>)注册
- 点击
提交
后,你将被重定向到你的仪表板端点,即 https://<org_name>.truefoundry.cloud - 完成邮件验证
- 在你的仪表板端点登录平台,即 https://<org_name>.truefoundry.cloud
注意:请保存好你的仪表板端点,我们将其称为“TFY_HOST”,其结构应为“https://<org_name>.truefoundry.cloud”
-
设置集群,使用TrueFoundry托管快速设置
- 给你的**Cluster一个唯一的名字并点击启动集群**
- 将花费几分钟为你准备一个集群
- 在配置主机域部分为预填写的IP点击
注册
- 接下来,
添加
一个Docker Registry以推送你的docker镜像 - 接着,部署一个模型,你可以选择
跳过
此步骤
-
添加一个 存储集成
-
创建一个 ML Repo
-
导航到 ML Repo 标签
-
点击右上角的
+ 新的 ML Repo
按钮 -
给你的 ML Repo 一个唯一的名字(如 'docs-qa-llm')
-
选择 存储集成
-
点击
提交
后,你的 ML Repo 将被创建更多详情请参考:链接
-
-
创建一个 工作空间
- 导航到 工作空间 标签
- 点击右上角的
+ 新工作空间
按钮 - 选择你的 集群
- 给你的 工作空间 取个名字(如 'docs-qa-llm')
- 启用 ML Repo 访问 并
添加 ML Repo 访问权限
- 选择你的 ML Repo 并将角色设为 项目管理员
- 点击
提交
后,一个新的 工作空间 将被创建。你可以通过点击 FQN 来复制 工作空间 FQN。
更多详情请参考:链接
-
部署 RAG 应用
- 导航到 部署 标签
- 点击右上角的
+ 新部署
按钮 - 选择
应用目录
- 选择你的工作空间
- 选择 RAG 应用
- 填写部署模板
- 给你的部署一个名字
- 添加 ML Repo
- 你可以添加一个现有的Qdrant数据库或创建一个新的
- 默认情况下,
main
分支用于部署(你可以在显示高级字段
中找到此选项)。如有需要,你可以更改分支名称和Git存储库。确保重新选择主分支,因为SHA提交不会自动更新。
- 点击
提交
后,你的应用将被部署。
使用 RAG UI:
以下步骤将展示如何使用cognita UI来查询文档:
-
创建数据源
- 点击
数据源
标签 - 点击
+ 新的数据源
- 数据源类型可以是本地目录的文件、网页url、github url或者提供Truefoundry artifact FQN
- 例如:如果选择
本地目录
,则从你的计算机中上传文件并点击提交
- 例如:如果选择
- 创建的数据源列表将在数据源标签中可见
- 点击
-
创建集合
- 点击
集合
标签 - 点击
+ 新的集合
- 输入集合名称
- 选择嵌入模型
- 添加先前创建的数据源和必要的配置
- 点击
处理
来创建集合并索引数据
- 点击
-
在你创建集合之后,数据摄取将开始,你可以通过选择集合标签中的你的集合来查看其状态。稍后你还可以添加更多的数据源并在集合中进行索引。
-
响应生成
- 选择集合
- 选择LLM及其配置
- 选择文档检索器
- 编写提示或使用默认提示
- 提出查询
:sparkling_heart: 开源贡献
欢迎你的贡献!随时提供想法、反馈,或创建问题和错误报告!在贡献之前,请阅读贡献指南。
:crystal_ball: 未来发展
欢迎对以下即将到来的发展贡献:
- 支持其他向量数据库如
Chroma
、Weaviate
等 - 支持
标量 + 二进制量化
嵌入 - 支持不同检索器的
RAG 评估
- 支持
RAG 可视化
- 支持带上下文的对话机器人
- 支持如
stable-lm-3b
,dragon-yi-6b
等优化的RAG LLMs - 支持
图数据库