项目名称:AI-AGENT夏季训练营 — RAG带你重新理解表格图像
报告日期:2024年8月18日
项目负责人:吴昱君
一,项目概述
利用NVIDIA的NIM人工智能平台,进行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