annidy / notes

0 stars 0 forks source link

RAG #319

Open annidy opened 3 months ago

annidy commented 3 months ago

RAG目前流程已基本成型,基本的原理都是先本地数据向量化,然后在查询问题时,先找出向量最相近的K个数据,再组装成一个prompt给大模型生成答案

sequenceDiagram
    participant User as 用户
    participant Embeddings as 文本向量化
    participant VectorDB as 向量数据库
    participant LLAM as 语言模型

    User ->> Embeddings: 上传数据
    Embeddings ->> VectorDB: 存储向量

    User ->> Embeddings: 提问问题
    Embeddings ->> VectorDB: 查询
    VectorDB -->> Embeddings: 返回Top K
    Embeddings -->> User: 知识库结果

    User ->> LLAM: Prompt with knowledge
    LLAM -->> User: 返回答案

文本向量化关乎到搜索到准确性,有多种实现方案:

  1. 使用本地模型。通常需要搭配一些框架,比如Ollam、LangChain、SentenceTransformers。
  2. 本地计算很消耗资源,也可使用云API。(LangChain封装了一些)
  3. 完全标准化的,比如milvus?

输入知识库前,通常还需要进行文本拆分/清洗(ETL)。主要原因是:1. 文本长度关乎token长度,向量数据库不能无限存储;2. 某些模型对输入的token有长度限制,超过字数无法文本向量化。分割的方案有:

  1. langchain.text_splitter提供了一些简单的模式匹配实现分割。Demo
  2. 使用NLP库来处理,比如spacy。分句后还需要合并多个句子成为chunk,多少个句子合并为一个chunk通常根据经验来设置

存储向量和查询向量就比较工程化。faiss是目前性能较好的检索,直接使用向量数据库也是可行的。

  1. Faiss语义检索
  2. LangChain Chroma
  3. 云向量库:qdrant

知识库返回的数据还需要语言组织后才能返回给用户。有时知识库找不到答案(或者返回了完全无关的语料),这时就需要OpenAI这类通用大模型来回答。

与大模型交互涉及到Prompt提示词工程,包括:角色定义(你是一个AI机器人……)、提示上下文(请根据以下信息回答……)、输出示例(可用要求结构化输出数据)等,相比在WebUI上的交互,每次token消耗比实际输入的问题多很多。比如问题10个字,上下文加起来有几百字,消耗token可能就上千。

Tutorial

Local Retrieval Augmented Generation (RAG) from Scratch (step by step tutorial) coderabbit214/document-ai