LLM之RAG实战(三十六)| 使用LangChain实现多模态RAG

39 篇文章 41 订阅

       我们之前介绍的RAG,更多的是使用输入text来查询相关文档。在某些情况下,信息可以出现在图像或者表格中,然而,之前的RAG则无法检测到其中的内容。

      针对上述情况,我们可以使用多模态大模型来解决,比如GPT-4-Vision,它有非常好的图像理解能力,可以理解图像内部发生的事情。

       现在的问题与我们如何从矢量数据库中检索正确的图像。我们可以参考LangChain博客[1]中两种实现多模态RAG方法。

两种方法如下所示:

  1. Multimodal Embedding (using Open Clip Embedding)

  2. Multi-vector retriever with image summary

一、多模态嵌入(使用CLIP Embedding)

       根据langchain博客[1],多模态嵌入方法的准确率仅为60%,而多向量检索方法的准确率约为90%。然而,多模态嵌入方法非常划算,因为只调用一次GPT-4-Vision。

       对于多模态嵌入方法,我们需要使用Open CLIP Embeddings。CLIP(对比语言-图像预训练)是Open AI于2021年开发的一个嵌入模型,是一个在同一空间共享文本和图像嵌入的嵌入模型。

       多模态嵌入与其他RAG系统类似,现在唯一的区别是图像也嵌入了这个矢量数据库中。但是,这个模型不足以解释图像中的信息,例如,在某些情况下,图像中存在与数字相关的信息,或者数据库中的图像类型相似,嵌入无法从数据库中检索相关图像。

完整的代码可以参考langchain cookbook[2],下图是整体架构图:

下面稍微介绍一下几个关键步骤:

步骤1:从PDF中提取图像

       使用unstructured库抽取PDF信息,并创建一个文本和图像列表。提取的图像需要存储在特定的文件夹中。

# Extract images, tables, and chunk textfrom unstructured.partition.pdf import partition_pdfraw_pdf_elements = partition_pdf(    filename="LCM_2020_1112.pdf",    extract_images_in_pdf=True,    infer_table_structure=True,    chunking_strategy="by_title",    max_characters=4000,    new_after_n_chars=3800,    combine_text_under_n_chars=2000,    image_output_dir_path=path,)

步骤2:创建矢量数据库

        准备矢量数据库,并将图像URI和文本添加到矢量数据库中。

# Create chromavectorstore = Chroma(    collection_name="mm_rag_clip_photos", embedding_function=OpenCLIPEmbeddings())# Get image URIs with .jpg extension onlyimage_uris = sorted(    [        os.path.join(path, image_name)        for image_name in os.listdir(path)        if image_name.endswith(".jpg")    ])print(image_uris)# Add imagesvectorstore.add_images(uris=image_uris)# Add documentsvectorstore.add_texts(texts=texts)

步骤3:QnA管道

       最后一部分是Langchain QnA管道。

chain = (    {        "context": retriever | RunnableLambda(split_image_text_types),        "question": RunnablePassthrough(),    }    | RunnableLambda(prompt_func)    | model    | StrOutputParser())

      如上面的脚本所示,有两个重要的自定义函数在这个管道中发挥着重要作用,分别是:split_image_text_types和prompt_func。

       对于split_image_text_types函数,使用CLIP嵌入获取相关图像后,还需要将图像转换为base64格式,因为GPT-4-Vision的输入是base64格式。

       prompt_func函数是描述如何构建prompt工程。在这里,我们将“问题”和“base64图像”放在提示中。

二、带图像摘要的多向量检索器

       根据langchain的观察结果,该方法比多模态嵌入方法的准确性更高,它使用GPT-4V提取摘要。

      如果使用多矢量方法摘要时,需要提交文档中的所有图片进行摘要。当在矢量数据库中进行相似性搜索时,图像的摘要文本也可以提供信息。

       一般来说,摘要用于查找相关图像,相关图像输入到多模态LLM以回答用户查询。这两条信息需要分开,这就是为什么我们在这种情况下使用多向量检索器[3]的原因。

优点:图像检索精度高

缺点:这种方法非常昂贵,因为GPT-4-Vision非常昂贵,尤其是如果你想总结许多图像,如果你有成本问题,可能会是一个问题。

完整的代码可以参考langchain cookbook[4],下图是整体架构图:

       该方法也可以很好地回答图像中的问题,唯一的问题是整个过程比较缓慢,大概是因为GPT-4-Vision需要时间来处理整个事情。

下面稍微介绍一下几个关键步骤:

步骤1:提取图像

该步骤与上述多模态嵌入方法类似。

步骤2:生成文本和图像摘要

     使用generate_text_summarys和generate_mg_summarys函数生成每个文本和图像的摘要。数据结构,如下所示:

{"input":text, "summary":text_summaries}, {"input":table, "summary":table_summaries},{"input":image_base64, "summary":image_summaries }

        此结构将添加到多矢量检索器中。

步骤3:创建多矢量检索器

      使用下面的python脚本将上述数据结构添加到多向量检索器中,我们还需要指定矢量数据库。

# The vectorstore to use to index the summariesvectorstore = Chroma(    collection_name="mm_rag_cj_blog", embedding_function=OpenAIEmbeddings())# Create retrieverretriever_multi_vector_img = create_multi_vector_retriever(    vectorstore,    text_summaries,    texts,    table_summaries,    tables,    image_summaries,    img_base64_list,)

     使用create_multi_vector_requirer函数初始化多向量。langchain中的MultiVectorRetriever是一个创建多向量检索器的类,在这里我们需要添加向量存储、文档存储和key_id作为输入。

      该案例中,我们的文档存储设置为InMemoryStore,将不会持久化。因此需要使用另一个langchain存储类来使其持久化,可以参考[5]。

       docstore很重要,它存储我们的图像和文本,而不是摘要。摘要存储在矢量存储中。

def create_multi_vector_retriever(    vectorstore, text_summaries, texts, table_summaries, tables, image_summaries, images):    """    Create retriever that indexes summaries, but returns raw images or texts    """    # Initialize the storage layer    store = InMemoryStore()    id_key = "doc_id"    # Create the multi-vector retriever    retriever = MultiVectorRetriever(        vectorstore=vectorstore,        docstore=store,        id_key=id_key,    )    # Helper function to add documents to the vectorstore and docstore    def add_documents(retriever, doc_summaries, doc_contents):        doc_ids = [str(uuid.uuid4()) for _ in doc_contents]        summary_docs = [            Document(page_content=s, metadata={id_key: doc_ids[i]})            for i, s in enumerate(doc_summaries)        ]        retriever.vectorstore.add_documents(summary_docs)        retriever.docstore.mset(list(zip(doc_ids, doc_contents)))    # Add texts, tables, and images    # Check that text_summaries is not empty before adding    if text_summaries:        add_documents(retriever, text_summaries, texts)    # Check that table_summaries is not empty before adding    if table_summaries:        add_documents(retriever, table_summaries, tables)    # Check that image_summaries is not empty before adding    if image_summaries:        add_documents(retriever, image_summaries, images)    return retriever

步骤4:QnA管道

       最后一步与前面的方法类似。只有检索器不同,现在我们使用的是多向量检索器。

三、结论

       如果使用多模态RAG,这两种方法是合适的。其实谷歌也发布了他们的多模态嵌入[6],亚马逊也有Titan多模态嵌入[7]。相信在未来,多模态嵌入将有许多选择。

参考文献:

[1] https://blog.langchain.dev/multi-modal-rag-template/

[2] https://github.com/langchain-ai/langchain/blob/master/cookbook/multi_modal_RAG_chroma.ipynb

[3] https://python.langchain.com/docs/modules/data_connection/retrievers/multi_vector

[4] https://github.com/langchain-ai/langchain/blob/master/cookbook/Multi_modal_RAG.ipynb

[5] https://python.langchain.com/docs/integrations/stores/file_system

[6] https://cloud.google.com/vertex-ai/docs/generative-ai/embeddings/get-multimodal-embeddings

[7] https://docs.aws.amazon.com/bedrock/latest/userguide/titan-multiemb-models.html

  • 18
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wshzd

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值