Qanything 2.0源码解析系列5:问答接口中的检索逻辑(以图片为例)
2024-9-23
| 2024-9-26
Words 7376Read Time 19 min
type
Post
status
Published
date
Sep 23, 2024
slug
summary
以图片检索为例子,介绍qanything的检索逻辑(问答逻辑)
tags
category
技术分享
icon
password
😀
前言: 在
Qanything 2.0源码解析系列4: 图片解析逻辑
文章中,介绍了针对一张图片内容是如何处理最后embedding并存入milvus中的。 本文介绍Qanything的问答接口,以图片为例,详细阐述一下Qanything的检索逻辑。
 
RAG问答其实还是涉及到蛮多流程的,主要包含一下内容 1. 检索 (retrieve) 2. 重排 (reranker)图片的话内容较少,其实这一步就不需要了。 3. 大模型问答 (llm answer)

📝 前情提要

notion image
对这样一张图片:
产生了两个父doc,并存入了mysql数据库中,两个父doc如下:
产生了4个子doc,并存入了向量数据库中。4个doc如下:
query的问题如下:

🐵 问答接口

local_doc_chat方法定义在handler文件下
常用请求参数如下:

🤗 检索逻辑

  1. 从mysql File表中查询到这些kb_id对应的status为green的file_id,为green表示该文件的解析逻辑正确处理,doc也都存入了milvus库中。如果有效文件的长度<1,说明没有知识库,设置kb_ids为空,相当于进入和大模型的纯聊天模式了。
    1. 源码在handler.py的第718行。
  1. 核心方法是 handler.py第736行(非流式)的这个方法:
    1. 这个方法内部执行了很多模块,大体如下:
    2. 使用bce-embedding对query:【自如的转租政策是什么?】进行embedding。使用milvus的search方法从库中搜索前top-k个向量,默认topk=30,所以上面存储的4个doc都会被检索出来。
    3. 子doc的处理
      1. 将子doc的doc_id放入ids列表中,4个子doc得到两个doc_id,然后从mysql Documents表中根据doc_id得到父doc的内容。两个doc_id对应两个父doc。这一步根据4个子doc得到了两个父doc。
    4. docs根据page_content内容去重,这里就两个,没有重复的。
      1. 组装prompt, prompt定义在model_config.py文件中
        1. 1)替换掉{{system}}和{{instructions}}
      2. 处理source_documents,得到source_documents、retrieval_documents。
        1. c步骤得到的两个父doc称之为source_documents。
          1) 处理source_documents:
          prompt的默认长度是4096,这里计算一下两个source_documents的token长度+prompt模版的长度+如果有历史问答加上历史+额外的符号的。
          如果超过了4096,就会有source_documents被丢弃,从相似度最高的开始遍历,丢弃相似度低的。因为是图片内容,包含的文字有限。这里source_documents只有两个,都加上也不会超过4096,返回的retrieval_documents和source_documents是一样的,limited_token_nums=3061。
          2)聚合文档, 处理retrieval_documents,1)步骤的内部方法
          retrieval_documents包含两个文档,这两个文档的file_id是一样的,都是一张图片的,根据前面的介绍已知哈。第一个文档是相似度最高的,aggregate_documents这个方法的逻辑是返回相似度最高的这个doc_id对应的file_id的完整文档,会从数据库中查的。也就是说对于两张图片或者pdf之类的,会返回第一个完整文档,超过4096了会截取。逻辑会比较复杂一点,但是对于图片来说,理解起来就很简单了,返回的new_docs就是两个retrieval_documents拼接在一起的doc,也就是整个ocr内容作为一个整体的doc。然后将source_documents赋值new_docs。
          3)根据2)知道,方法1)得到的source_documents是整个图片内容是一个整体的doc, retrieval_documents是两个doc。
           
      3. 将e步骤得到的source_documents和d步骤的模版拼起来。
        1. 得到的prompt如下:
      4. 将f步骤的prompt提问大模型得到结果。
        1. 将answer_result做一些处理,就可以返回给用户【自如的转租政策是什么?】的回答了。

    📎 总结

    图片的问答逻辑相比pdf、doc还是简单很多的,没有太多复杂的逻辑,基本上就是拿到整个ocr的识别结果喂给大模型去处理。
    notion image
    思考:
    一般而言,知识库中很少是以很多张图片组成的。图片文档更合理的逻辑是:用户上传了一张图片或两张图片,然后针对这一两张图片问个问题,相当于是图片理解类任务。比如一张机构和用户的聊天记录,让大模型根据这个图片写一段营销话术。
    因此我认为完全不需要图片ocr完了之后还要split父doc,还要split子doc,还要存向量数据库。因为最终检索出来的内容还是整个ocr识别的结果。不如用户上传一张图片之后直接对其进行ocr存mysql数据库,然后根据用户问题,从数据库拿到ocr结果组装prompt提问大模型。当然Qanything提供了一套更通用的方法。如果你的业务本身就是说图解画类型的,完全可以采用ocr+大模型的方式,省去了embedding和retriever的流程,整体的速度也会快很多。
     

    📎 参考文章

    • Qanything源码
     
    💡
    有问题,欢迎您在底部评论区留言,一起交流~
    以openai的gpt3.5为例的大模型流式输出实现(原始、Sanic、Flask)- 附免费的apikey水龙头Qanything 2.0源码解析系列4: 图片解析逻辑
    Loading...