老胡茶室
老胡茶室

无废话 RAG:实践篇

胡键

简单复习

理论篇中,我们已经了解:

  • embedding 和向量数据库相关概念
  • RAG 的两个阶段:indexing 和 querying
  • 每个阶段典型的组件:
    • indexing 阶段:data loader 、data spliter、embedding model 和 vector db
    • querying 阶段:llm、embedding model、vector db、 retriever 和 reranker(注:如果一篇 RAG 文章不介绍什么是 reranker,大可忽略不读。)
  • langchain.js 基础:
    • 用于 RAG 实现的相关组件
    • 与 pgvector 配合时,相关的数据库表结构,以及如何实现增量更新向量数据。

下面,本文将重点介绍实现 RAG 时需要注意的细节和实践经验。

注:本文假设你已经具备一定的开发经验和了解 RAG 的基本知识,基于此,本文从一开始就没有打算写一篇手把手的扫盲教程,而是将重点放在:实现一个面向真实用户的 RAG 系统时需要注意的细节和实践经验。

当然,你会在文中看到核心数据库表设计、关键函数代码示例,以及诸如 CAG和权限这类典型的高级场景,以便更好地理解这些细节和经验。

通用实现

要实现前文中介绍的通用 RAG 应用架构,一般需要以下功能:

  • 数据源管理
  • Indexing Pipeline
  • Querying
  • Setting

高级一点的,可能会提一提 eval,但这又是一大主题,再说容易跑题,故而在此略过不提,我将另行撰文说明。

有兴趣的可自行先用 deep research 去研究以建立整体概念,若想了解工具,则可以看看 langchain 自己的解决方案:langsmith,或前往老胡茶室的用物志了解其他类似工具。

下面的讨论依旧采用 langchain.js + pgvector 技术选型。

数据库设计

对于 langchain.js + pgvector 组合,实现 RAG 的核心数据库表就两个:

  • documents:存储向量数据和原始文档及其元数据
  • upsertion_records:类似一般 db migration 实现中记录数据库 ddl 变更的表,用于记录原始文档是否改变,实现增量更新。

理论篇已经详细介绍过两张表的结构,在此不再赘述。只提醒一点:除非你明确指明,langchain.js 并不会启用增量更新!

同时,你也无需在项目代码中维护这两张表的定义,因为它们会在第一次使用时自动创建。

然而,光有这两张表并不足以支撑一个实际的应用。根据我们的经验,建议在此基础上,增加以下表:

  • knowledges,存储 RAG 应用的原始文档信息
  • tasks,存储异步任务执行状态
  • settings,存储应用的配置
  • sessions,存储用户会话信息

其中:

  • 强烈建议使用 knowledgestasks
  • 如果不打算给用户太多自定义的选择,如切换 model 或自定义 prompt,则 settings 可以不使用。但我个人建议保留,至少允许高级用户可以自行定义 prompt。
  • 如果不打算把 RAG 做成 chatbot 形式,则 sessions 可以不使用。并且,即使是 chatbot 形式,你还有一个选择就是将会话信息存储在用户本地浏览器中。
...
付费内容

本文是付费文章

以上是此文章的预览内容

数字产品一经出售,概不退款