小白学AI之基于 NIM 建构多模态 AI-Agent

本次实践将着重练习以下内容:

多模态模型基于 NIM 的调用方式
基于 NIM 接口实现 Phi-3-Vision 的推理实践
基于 Gradio 框架建立前端互动界面

本篇博客主要记录自己在学习使用NIM构建多模态AI-Agent过程中所遇到的相关问题以及主要的实现步骤

环境搭建参考上一篇文章环境搭建篇
本练习的第一步也是先要获取到属于自己的API Key,具体的获取方法在上方链接中有详细说明。

第一步 导入工具包并将这里的API Key换成自己申请的

第二步 利用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")
# image_b64 = image2b64("eco-good-bad-chart.png")

将编码后的图像按照格式给到Microsoft Phi 3 vision , 利用其强大能力解析图片中的数据

chart_reading = ChatNVIDIA(model="microsoft/phi-3-vision-128k-instruct")
result = chart_reading.invoke(f'Generate underlying data table of the figure below, : <img src="data:image/png;base64,{image_b64}" />')
print(result.content)

在这里可能会遇到警告,具体如下图所示
在这里插入图片描述警告建议使用model=microsoft/phi-3-vision-128k-instruct,注意加以修改可以避免讨厌的红色警告提示。

第三步 使用LangChain 构建多模态智能体

Agent 应用场景:将图片中的统计图表转换为可以用 python 进行分析的数据

Agent 工作流:

接收图片,读取图片数据
对数据进行调整、分析
生成能够绘制图片的代码,并执行代码
根据处理后的数据绘制图表

接收图片 -> 分析数据 -> 修改数据 -> 生成绘制图片的代码 -> 执行代码 -> 展示结果

这里借助辅助函数用于显示输入, 执行代码等。

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

定义多模态数据分析 Agent

这里首先定义了提示词模板, chart_reading_prompt, 我们输入的图片会边恒base64格式的string传输给它
将处理好的提示词输入给char_reading, 也就是microsoft/phi-3-vision大模型来进行数据分析, 得到我们需要的表格或者说table变量
将Phi3 vision处理好的table和提示词输入给另一个大模型llama3.1, 修改数据并生成代码
将生成的代码通过上面的执行函数来执行python代码, 并得到结果
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

初始化

# 使用全局变量 table 来存储数据
table = None
# 将要处理的图像转换成base64格式
image_b64 = image2b64("economic-assistance-chart.png")

#展示读取的图片
from PIL import Image

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

在这里插入图片描述
在这里插入图片描述

第四步 将多模态智能体封装进Gradio

当我们完成上述任务的时候, 就拥有了一个可以分析图片, 生成代码, 修改数据, 执行代码的智能体

接下来我们给这个智能体添加一个UI界面, 让我们可以更舒服的与之对话

因为在我的虚拟环境中并没有Gradio模块,所以我借助如下代码安装相关库函数

!pip install gradio

我们修改一下执行代码的函数, 因为原生的Python中exec函数的返回是Nan, 所以我们给他添加一个生成图片的路径

在下面的代码中, 路径是作者的PC中的路径, 请您根据您自己的系统更换这个文件夹路径
所以我将如下的路径换成了我自己的
在这里插入图片描述
接下来的步骤就是依次运行如下代码即可
在这里插入图片描述
最终得到的结果如下
在这里插入图片描述
而且在自己输入的保存路径下也会生成一张图片,具体如下所示
在这里插入图片描述
好了,以上就是这次学习的全部内容的相关记录,期待下一次的学习。

  • 25
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值