AI-AGENT夏季训练营 — RAG带你重新理解表格图像

项目名称:AI-AGENT夏季训练营 RAG带你重新理解表格图像

报告日期:2024818

项目负责人:吴昱君

一,项目概述

        利用NVIDIANIM人工智能平台,进行RAG智能对话机器人的搭建和实践。项目通过先进的自然语言处理技术增强文字的检索能力,使用户能够更快速、准确地找到所需信息。在获取文本内容的同时,利用pyttsx3库可以进行语音播报,此举将对视障人士有一定帮助。同时,利用调用大模型API对图片进行微调重绘,提升视觉呈现效果,增强用户体验。项目的亮点在于其创新性地结合了文本和图像处理功能,为用户提供一站式解决方案。可能的应用场景包括数字图书馆、在线媒体平台和企业内部文档管理等,有助于提高工作效率和信息获取的精确度。

二,技术方案与实施步骤

       1, 模型选择

        选择了"ai-embed-qa-4”embedding model,该项目采用了phi-3-small-128k-instruct 小模型,可以在边缘设备以及移动端流畅部署,在保证回答的准确性时尽量缩小本地部署成本。利用RAG可以让机器幻觉减少出现,增加更高的答案容错率,让机器学习变得更加有效率。

        2,数据的构建

        数据构建过程:利用搜索引擎搜索相应表格图片,将其放入gradio生成的机器人页面进行识别,后在userinput里填写用户要求,对其进行数据处理。

        向量化处理:通过NVIDIA Embeddings工具类调用NIM中的"ai-embed-qa-4"向量化模型。随后使用microsoft/phi-3-small-128k-instruct模型,结合"ai-embed-qa-4"向量化模型,基于本地存储的数据,进行文本数据的RAG功能实现。

  以下是向量化处理的代码:

import os
from tqdm import tqdm
from pathlib import Path

# Here we read in the text data and prepare them into vectorstore
ps = os.listdir("./zh_data/")
data = []
sources = []
for p in ps:
    if p.endswith('.txt'):
        path2file="./zh_data/"+p
        with open(path2file,encoding="utf-8") as f:
            lines=f.readlines()
            for line in lines:
                if len(line)>=1:
                    data.append(line)
                    sources.append(path2file)

        3,功能整合

        通过多模态模型microsoft/phi-3-vision-128k-instruct ,对图片进行识别。随后,使用 LangChain 构建多模态智能体。然后,结合microsoft/phi-3-vision-128k-instruct模型和meta/llama-3.1-405b-instruct模型,通过Gradio构建的前端UI,进行结果的呈现,也可以去后端文件夹查询结果图片。

三,实施步骤

        1,环境搭建

        安装基础miniconda:Miniconda — Anaconda documentation

        安装pip运行库:2024 NVIDIA开发者社区夏令营环境配置指南(Win & Mac)_csdn 2024nvidia开发者-CSDN博客( 在安装时可以选用清华镜像,避免超时同时加快下载速度:pip 下载安装时使用清华大学镜像(各种国内源配置)_pip清华镜像网址-CSDN博客  )

        2,代码实现

        利用NVIDIA-API-KEY进行对话机器人的基础构建:

import getpass
import os

if os.environ.get("NVIDIA_API_KEY", "").startswith("nvapi-"):
    print("Valid NVIDIA_API_KEY already in environment. Delete to reset")
else:
    nvapi_key = getpass.getpass("NVAPI Key (starts with nvapi-): ")
    assert nvapi_key.startswith("nvapi-"), f"{nvapi_key[:5]}... is not a valid key"
    os.environ["NVIDIA_API_KEY"] = nvapi_key

        对SLM初始化:

llm = ChatNVIDIA(model="ai-phi-3-small-128k-instruct", nvidia_api_key=nvapi_key, max_tokens=512)
result = llm.invoke("泰坦尼克号的导演是谁?")
print(result.content)

        初始化ai-embed-qa-4向量模型:

from langchain_nvidia_ai_endpoints import NVIDIAEmbeddings

embedder = NVIDIAEmbeddings(model="ai-embed-qa-4")

将原课件中的泰坦尼克号.txt 替换为肖申克的救赎内容,并以此验证程序可行性。

很显然,在没有进行Shawshenk.txt的训练前,许多答案是不符合实际的。

然而对于进行了训练的模型来说,给出正确的答案是意料之内的。

 (另附我所找的shawshenk内容:)

        3,测试与调优

       原课件当中的nemo进行理论执行:

        在未使用RAG的状况下问nemo:(文不对题)

        对代码进行调优,即配置RAG,给出学习文本:

学习之后利用RAG的回答准确无误:

再让新的summer进行验证:

同时为了让项目更具有兼容性,我在基础上添加了pyttsx3库,利用其语音播报的特性让回答多元化:

import pyttsx3
# 初始化
pt = pyttsx3.init()
pt.save_to_file(rag_result, 'answer.mp3')
pt.runAndWait()

由此一来,在原本后端文件夹内就会生成以rag_result为内容的文本,一段语音播报的answer.mp3

        4,集成与部署

        做好import工作: 

        开始利用Microsoft Phi 3 Vision模型解析图片数据并查看:

def image2b64(image_file):
    with open(image_file, "rb") as f:
        image_b64 = base64.b64encode(f.read()).decode()
        return image_b64

image_b64 = image2b64("economic-assistance-chart.png")

from PIL import Image
display(Image.open("economic-assistance-chart.png"))

        

import re

# 将 langchain 运行状态下的表保存到全局变量中
def save_table_to_global(x):
    global table
    if 'TABLE' in x.content:
        table = x.content.split('TABLE', 1)[1].split('END_TABLE')[0]
    return x

# helper function 用于Debug
def print_and_return(x):
    print(x)
    return x

# 对打模型生成的代码进行处理, 将注释或解释性文字去除掉, 留下pyhon代码
def extract_python_code(text):
    pattern = r'```python\s*(.*?)\s*```'
    matches = re.findall(pattern, text, re.DOTALL)
    return [match.strip() for match in matches]

# 执行由大模型生成的代码
def execute_and_return(x):
    code = extract_python_code(x.content)[0]
    try:
        result = exec(str(code))
        #print("exec result: "+result)
    except ExceptionType:
        print("The code is not executable, don't give up, try again!")
    return x

# 将图片编码成base64格式, 以方便输入给大模型
def image2b64(image_file):
    with open(image_file, "rb") as f:
        image_b64 = base64.b64encode(f.read()).decode()
        return image_b64

def chart_agent(image_b64, user_input, table):
    # Chart reading Runnable
    chart_reading = ChatNVIDIA(model="microsoft/phi-3-vision-128k-instruct")
    chart_reading_prompt = ChatPromptTemplate.from_template(
        'Generate underlying data table of the figure below, : <img src="data:image/png;base64,{image_b64}" />'
    )
    chart_chain = chart_reading_prompt | chart_reading

    # Instruct LLM Runnable
    # instruct_chat = ChatNVIDIA(model="nv-mistralai/mistral-nemo-12b-instruct")
    # instruct_chat = ChatNVIDIA(model="meta/llama-3.1-8b-instruct")
    #instruct_chat = ChatNVIDIA(model="ai-llama3-70b")
    instruct_chat = ChatNVIDIA(model="meta/llama-3.1-405b-instruct")

    instruct_prompt = ChatPromptTemplate.from_template(
        "Do NOT repeat my requirements already stated. Based on this table {table}, {input}" \
        "If has table string, start with 'TABLE', end with 'END_TABLE'." \
        "If has code, start with '```python' and end with '```'." \
        "Do NOT include table inside code, and vice versa."
    )
    instruct_chain = instruct_prompt | instruct_chat

    # 根据“表格”决定是否读取图表
    chart_reading_branch = RunnableBranch(
        (lambda x: x.get('table') is None, RunnableAssign({'table': chart_chain })),
        (lambda x: x.get('table') is not None, lambda x: x),
        lambda x: x
    )
    # 根据需求更新table
    update_table = RunnableBranch(
        (lambda x: 'TABLE' in x.content, save_table_to_global),
        lambda x: x
    )
    # 执行绘制图表的代码
    execute_code = RunnableBranch(
        (lambda x: '```python' in x.content, execute_and_return),
        lambda x: x
    )

    chain = (
        chart_reading_branch
        #| RunnableLambda(print_and_return)
        | instruct_chain
        #| RunnableLambda(print_and_return)
        | update_table
        | execute_code
    )
 return chain.invoke({"image_b64": image_b64, "input": user_input, "table": table}).content

注意:这里需要提前安装一个pip库,否则后面将不能进行:

!pip install gradio -i https://pypi.tuna.tsinghua.edu.cn/simple

确认文件路径以及绘制图表:

global img_path
img_path = '/Users/billy/Desktop/2024_summer_bootcamp/day3'+'image.png'
print(img_path)
def execute_and_return_gr(x):
    code = extract_python_code(x.content)[0]
    try:
        result = exec(str(code))
        #print("exec result: "+result)
    except ExceptionType:
        print("The code is not executable, don't give up, try again!")
    return img_path
def chart_agent_gr(image_b64, user_input, table):

    image_b64 = image2b64(image_b64)
    # Chart reading Runnable
    chart_reading = ChatNVIDIA(model="microsoft/phi-3-vision-128k-instruct")
    chart_reading_prompt = ChatPromptTemplate.from_template(
        'Generate underlying data table of the figure below, : <img src="data:image/png;base64,{image_b64}" />'
    )
    chart_chain = chart_reading_prompt | chart_reading

    # Instruct LLM Runnable
    # instruct_chat = ChatNVIDIA(model="nv-mistralai/mistral-nemo-12b-instruct")
    # instruct_chat = ChatNVIDIA(model="meta/llama-3.1-8b-instruct")
    #instruct_chat = ChatNVIDIA(model="ai-llama3-70b")
    instruct_chat = ChatNVIDIA(model="meta/llama-3.1-405b-instruct")

    instruct_prompt = ChatPromptTemplate.from_template(
        "Do NOT repeat my requirements already stated. Based on this table {table}, {input}" \
        "If has table string, start with 'TABLE', end with 'END_TABLE'." \
        "If has code, start with '```python' and end with '```'." \
        "Do NOT include table inside code, and vice versa."
    )
    instruct_chain = instruct_prompt | instruct_chat

    # 根据“表格”决定是否读取图表
    chart_reading_branch = RunnableBranch(
        (lambda x: x.get('table') is None, RunnableAssign({'table': chart_chain })),
        (lambda x: x.get('table') is not None, lambda x: x),
        lambda x: x
    )
    
    # 根据需求更新table
    update_table = RunnableBranch(
        (lambda x: 'TABLE' in x.content, save_table_to_global),
        lambda x: x
    )

    execute_code = RunnableBranch(
        (lambda x: '```python' in x.content, execute_and_return_gr),
        lambda x: x
    )
    
    # 执行绘制图表的代码
    chain = (
        chart_reading_branch
        | RunnableLambda(print_and_return)
        | instruct_chain
        | RunnableLambda(print_and_return)
        | update_table
        | execute_code
    )

    return chain.invoke({"image_b64": image_b64, "input": user_input, "table": table})

确认了路径和问题之后,就可以愉快的打开gradio前端进行测试了:

四,项目成果与展示

 五,问题与解决方案

        1,问题分析

        pip安装运行慢;

        过程中因为pip安装库缺失导致的报错;

        因为gradio前端不能查看图片而寻找结果

        2,解决方案

        利用清华镜像pip库

        重新安装虚拟环境

        在后端找到根目录对源文件定位

六,项目总结与展望

       在本项目中,结合Nvidia的专业人士课程,对python语言的理解,以及pip安装的经验,让本项目得以迅速完工,并获得预期结果。

        这个项目创新性的将图片处理和聊天文本机器人整合在一起,在大数据时代,面临难以人工处理的大量数据的情况是很容易出现的,为了适应时代所需,在未来数据处理中获得更高的效率,本项目可以为这样的困难提供一个新的方案。

七,附件与参考资料

Miniconda安装:https://docs.anaconda.com/miniconda/
pip运行库安装:2024 NVIDIA开发者社区夏令营环境配置指南(Win & Mac)_csdn 2024nvidia开发者-CSDN博客
pip清华源:pip 下载安装时使用清华大学镜像(各种国内源配置)_pip清华镜像网址-CSDN博客

Nvidia DLI:NVIDIA 深度学习培训中心(DLI)| 实战培训

API-Key获得:Try NVIDIA NIM APIs

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值