首页 > 分享 > 1小时搭建“汪汪宠物狗”公司的N种模态文档的RAG智能对话机器人

1小时搭建“汪汪宠物狗”公司的N种模态文档的RAG智能对话机器人

项目名称:1小时搭建“汪汪宠物狗”公司的N种模态文档的RAG智能对话机器人

报告日期:2024年8月18日

项目负责人:“汪汪宠物狗”公司创始人“汪汪”

项目概述:

大型语言模型(‌LLM)‌在实际应用中,‌尽管功能强大且多领域适用,‌但常出现幻觉现象,‌即生成的内容包含编造成分或错误。‌为解决这一问题,‌引入了LLM-RAG框架‌。‌

LLM-RAG通过结合检索和生成技术,‌提高了信息检索的准确性和效率,‌并能生成更贴近用户需求的文本。‌其检索库可定期更新,‌确保生成的文本内容基于最新信息,‌同时增强了回复的可解释性和定制能力‌1。‌

研究表明,‌与无RAG的LLM相比,‌RAG系统在回答问题方面的可靠性显著提高。‌在没有上下文的情况下,‌LLM平均只能正确回答34.7%的问题,‌而有了RAG,‌准确率提高到了94%‌2。‌这表明LLM-RAG框架在提升LLM性能方面具有显著优势。‌

基于NVIDIA AI 的智能库NIM,能够在1小时内快速地完成搭建基于文本,网页等等N种模态文档资料的RAG增强问答系统。当前版本代码,只支持了网页,txt格式2种模态文档数据的检索增强生成。后续版本会支持语音,图像,图表,PDF等等更多N种模态文档数据的检索增强生成。希望粉丝们,宝子们多多支持哦。

技术方案与实施步骤

模型选择:

RAG检索增强生成 

RAG检索增强生成(Retrieval Augmented Generation, RAG)是一种结合信息检索和语言生成的技术,旨在提高对用户查询的响应准确性和丰富性。在这一流程中,用户提出问题后,系统通过检索器从多种信息源(如维基百科和私有文档)中获取相关数据。检索到的信息被整合成增强提示,随后通过大型语言模型生成最终答案。这种方法不仅能够提供准确的答案,还能确保信息的时效性和多样性,从而提升用户体验。RAG技术在处理复杂查询和提供背景信息方面展现出了显著的优势,成为现代人工智能系统中重要的组成部分。

RAG框架如下图所示。这张图展示了检索增强生成(RAG)的工作流程,具体步骤如下:

用户提问:用户提出问题,例如“英伟达(NVIDIA)是什么时候成立的?”。

检索器:系统通过检索器访问公开可用的信息(如维基百科)和内部/私有文档(如PDF、DOC等),以获取相关数据。

向量数据库:检索到的信息被存储在向量数据库中,便于快速检索。

增强提示:系统将用户的问题与从数据库中检索到的信息结合,生成增强提示。这一提示包含了相关的上下文信息,例如“英伟达成立于1993年4月5日,由2024年首席执行官黄仁勋(Jensen Huang)创办”。

生成器(LLM):增强提示被发送到大型语言模型(LLM),模型根据提供的上下文生成回答。

AI生成的答案:最终,系统返回生成的答案,例如“英伟达成立于1993年”。

这一流程有效结合了信息检索与生成技术,能够快速、准确地回答用户的问题,提升了用户体验。

LLM-RAG

LLM-RAG(大型语言模型与检索增强生成)是一种结合了大型语言模型(LLM)和信息检索技术的先进框架,旨在提高信息获取和生成的效率与准确性。LLM-RAG通过将检索技术与生成模型结合,能够在面对复杂问题时,提供更准确和上下文相关的回答。其核心思想是利用外部知识库来增强模型的生成能力。

LLM-RAG框架如下图所示。这张图展示了检索增强生成(RAG)的工作流程,具体步骤如下:

文档检索与处理:

数据源:系统从企业知识库中检索各种文档,通常包括PDF文件和其他格式的文档。这些文档包含了组织内的知识和信息。

预处理:检索到的文档经过预处理,以提取有用的信息和结构化数据。预处理的目的是清理数据,使其适合后续的嵌入生成。

文档嵌入:经过预处理的文档被输入到嵌入模型中,生成文档嵌入(document embeddings)。这些嵌入是高维向量,能够捕捉文档的语义特征,使得相似文档能够在向量空间中靠近。

用户查询与响应生成:

用户交互:用户通过聊天机器人网页应用提交查询。用户的问题可以是具体的请求或信息查询。

查询处理:系统接收用户查询,并将其转换为嵌入形式,形成嵌入查询(embedded query)。此步骤确保查询能够与文档嵌入进行有效匹配。

向量数据库检索:嵌入查询被发送到向量数据库,系统根据相似度检索相关的文档嵌入。向量数据库能够快速找到与用户查询相匹配的文档。

生成响应:检索到的相关文档嵌入与用户查询一起被送入大型语言模型(LLM)。LLM利用这些信息生成响应,可能会进行提示调优(prompt tuning),以提高生成文本的质量和相关性。

实时响应:最终,系统生成的文本响应被返回给用户,提供实时、准确的信息。

这一流程的优势在于,它结合了信息检索的高效性和语言生成的灵活性,能够处理复杂的查询并提供上下文丰富的答案。通过这种方式,LLM-RAG不仅提升了用户体验,还能在各种应用场景中发挥重要作用,如客户支持、知识管理和信息检索等领域。

 AI-Agent 

AI-Agent是一种智能系统,能够自主感知环境、做出决策并执行任务。它通过模块化结构实现功能,包括记忆模块(存储信息)、Agent核心(处理用户请求)、规划模块(制定行动计划)和工具执行(调用外部资源),从而在无需人工干预的情况下高效地完成复杂任务。

AI-Agent是一种先进的智能系统,具备感知环境、进行决策和执行任务的能力。其核心功能包括:

自主执行任务:AI-Agent能够独立完成指定任务,无需人工干预,提升了工作效率。

环境感知和决策能力:通过分析环境信息和用户请求,AI-Agent可以做出合理的决策,以适应动态变化的环境。

模块化结构:

记忆模块:负责信息的存储和检索,帮助Agent在执行任务时维持上下文和历史记录。

Agent核心:作为系统的控制中心,处理用户请求并协调各个模块之间的交互。

规划模块:根据目标制定详细的行动计划,确保任务的有效执行和资源的合理利用。

工具执行:能够调用外部工具和资源,以完成具体的操作和任务。

通过以上模块的协同工作,AI-Agent不仅能够灵活应对复杂任务,还能在不断变化的环境中优化决策过程,从而提升整体工作效率和智能化水平。

AI-Agent的框架如下图所示。

数据的构建:

网页格式数据处理:

使用 BeautifulSoup 工具从指定网页(比如,宠物狗的百度百科这个网址 https://baike.baidu.com/item/%E5%AE%A0%E7%89%A9%E7%8B%97/6677317?fr=ge_ala)提取信息。通过解析HTML文档,提取所需的文本内容、标题和其他结构化数据,以便后续处理和分析。在提取信息后,进行数据清洗,包括:去除HTML标签:清除多余的标签,保留纯文本内容。去除冗余信息:删除无关的文本,如广告、导航链接等。统一格式:标准化文本格式,确保一致性(如大小写、空格处理)。

文本格式数据处理:

对于TXT文本数据,直接读取文件内容,确保数据的完整性和原始性。在此过程中,进行以下预处理步骤:去除空行和多余空格:清理文本中的空行和多余的空格,确保数据整洁。字符编码处理:确保文本的字符编码一致,避免乱码问题。分词与标记化:将文本分割为单词或句子或段落,以便后续分析和处理。通过上述数据清洗和预处理步骤,确保数据的质量,为后续的机器学习和深度学习任务提供高质量的基础数据。

向量化处理方法:

在数据处理的过程中,向量化是将文本数据转换为高维向量的重要步骤,这一过程能够使得文本数据适用于机器学习和深度学习任务。具体实现中,我们使用 NVIDIAEmbeddings 模型进行向量化,示例代码如下:

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

此模型将文本数据转换为高维向量,使其能够在机器学习和深度学习任务中使用。

向量化处理将文本转换为数值形式,显著提高了计算效率,便于进行高效的数学运算和模型训练。它能够捕捉文本中的语义关系,从而提升自然语言处理任务的准确性。此外,向量化支持相似度计算,适用于信息检索和推荐系统,且有助于降维和特征提取,减少计算复杂性。最终,向量化增强了模型的泛化能力,使其更好地适应不同的输入数据,从而为后续的机器学习和深度学习任务奠定了高质量的数据基础。

功能整合:  

主要思路:

本方案主要在AI-Agent中进行了RAG检索增强生成,而且RAG的数据源支持了txt格式文件和网页格式的2种模态的增强文档资料,这就可以实现一些特定信息应用需求。比如,

有一个名字叫“汪汪宠物狗”的公司:存在一个名称是“汪汪宠物狗”的公司,“汪汪宠物狗”公司创始人是“汪汪”,这个公司成立于宇宙时间10000年1000月100日。公司的简单介绍如下:‌1.‌公司愿景‌:‌致力于打造一个宠物狗与主人共享幸福生活的乐园,‌让每一只宠物狗都能得到最好的关爱和照顾。‌2.‌公司使命‌:‌通过提供专业的宠物狗服务,‌传播宠物文化,‌增进人与宠物之间的情感联系,‌提升宠物狗的生活品质。‌3.‌核心价值观‌:爱:‌以爱为出发点,‌对待每一只宠物狗如同家人一般。‌专业:‌不断学习和创新,‌提供最高水平的宠物狗服务和产品。‌责任:‌承担起对宠物狗、‌客户和社会的责任,‌积极参与公益活动。4.‌公司历史与创始人故事‌:‌公司由一位热爱宠物狗的资深宠物爱好者创立,‌他/她曾经救助过许多流浪狗,‌并深感宠物狗给人类带来的快乐和陪伴是无价的。‌因此,‌决定创立这家公司,‌将这份爱传递给更多的宠物狗和它们的主人。‌5.‌公司特色项目‌:‌“宠物狗才艺秀”:‌定期举办宠物狗才艺比赛,‌展示宠物狗的智慧和才能。‌“宠物狗公益行”:‌组织志愿者团队,‌参与宠物狗的救助和领养活动,‌推广宠物保护意识。‌“宠物狗主题度假村”:‌打造一个宠物狗和主人可以共同享受的度假村,‌提供豪华住宿和宠物设施。6.‌公司成就与荣誉‌:‌荣获“宇宙时间10000年度的最佳宠物服务品牌”称号,‌由宠物行业协会颁发。‌成为多家宠物慈善机构的合作伙伴,‌共同推动宠物福利事业。‌累计帮助数千只流浪狗找到温暖的家,‌受到社会各界的广泛赞誉。‌7.‌公司未来规划‌:‌扩大业务范围,‌开设更多的宠物狗专卖店和服务中心。‌推出自主研发的宠物狗食品和保健品系列,‌注重天然和健康。‌建立宠物狗训练学校,‌提供专业的宠物狗训练课程和教育服务。‌8.‌公司文化与氛围‌:‌公司内部充满活力和创意,‌鼓励员工提出新的想法和建议。‌定期举办员工培训和团队建设活动,‌提升员工的专业技能和服务意识。‌营造一个温馨、‌和谐的工作环境,‌让员工和宠物狗都能感受到家的温暖。‌

假如我想检索公司名称是“汪汪宠物狗”公司,使用LLM肯定是没有结果,但是如果加入了这个txt文档内容的限制条件,就可以返回我想要的结果了。

同样,假如我想基于某个网页资料的内容,进行相关问题的检索,也可以得到我想要的检索结果信息。

本文中的案例,可以尝试输入一下文本,就可以得到自己想要的检索结果了。

宠物狗的介绍?

宠物狗的介绍?请将结果翻译成中文。

宠物狗的百度百科的介绍?

宠物狗的百度百科的介绍?请将结果翻译成中文。

汪汪宠物狗的公司的介绍?

汪汪宠物狗的公司的介绍,请将结果翻译成中文。

多模态文档数据:

代码中已经实现了txt格式文档和网页2种模态的文档数据的RAG检索增强生成,具体修改的位置如下所示。

def create_embeddings(embedding_path: str = "./embed"):

embedding_path = "./embed"

print(f"Storing embeddings to {embedding_path}")

urls = [

"https://baike.baidu.com/item/%E5%AE%A0%E7%89%A9%E7%8B%97/6677317?fr=ge_ala"

]

def create_embeddings_text(text_path: str = "./zh_data/", embedding_path: str = "./embed"):

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

ps = os.listdir(text_path)

绿色的可以进行网址的修改,以及txt格式文件路径的修改。

这样就可以在AI-Agent中进行RAG检索增强生成了,而且RAG的数据源支持了txt格式文件和网页格式的2种模态的增强文档资料,这就可以实现一些特定信息应用需求。

比如,有一个名字叫“汪汪宠物狗”的公司:存在一个名称是“汪汪宠物狗”的公司。而且有相关的txt格式文档或者网页资料数据。

多模态文档数据合并:

AI-Agent中进行RAG检索增强生成了,而且RAG的数据源支持了txt格式文件和网页格式的2种模态的增强文档资料,这就可以实现一些特定信息应用需求。

比如,有一个名字叫“汪汪宠物狗”的公司:存在一个名称是“汪汪宠物狗”的公司。而且有相关的txt文档或者网页资料数据。

代码中实现了2个函数,因为使用了同一个Embedding Model 的嵌入向量模型,比如

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

所以,可以直接对数据库进行更新写入即可。

create_embeddings() 

create_embeddings_text()

import os

import shutil

def ensure_empty_directory(dir_path):

if os.path.exists(dir_path):

shutil.rmtree(dir_path)

ensure_empty_directory("./embed")

create_embeddings()

create_embeddings_text()

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

text_splitter = CharacterTextSplitter(chunk_size=400, separator="。")

docs = []

metadatas = []

dest_embed_dir = embedding_path

for i, d in enumerate(documents):

splits = text_splitter.split_text(d)

docs.extend(splits)

metadatas.extend([{"source": sources[i]}] * len(splits))

docs = remove_control_chars(docs)

if os.path.exists(dest_embed_dir):

update = FAISS.load_local(folder_path=dest_embed_dir, embeddings=embedder, allow_dangerous_deserialization=True)

update.add_texts(docs, metadatas=metadatas)

update.save_local(folder_path=dest_embed_dir)

else:

os.makedirs(dest_embed_dir)

docsearch = FAISS.from_texts(docs, embedder , metadatas=metadatas)

docsearch.save_local(folder_path=dest_embed_dir)

多模态AI-Agent智能聊天机器人的封装和部署:

使用将多模态智能体封装进Gradio,需要要对函数再进行一次封装,需要满足gr.Interface的函数调用格式。

对于服务api的端口只能使用一次,需要再次更改端口号码。

def chat_gr(query):

qa = ConversationalRetrievalChain(

retriever=docsearch.as_retriever(),

combine_docs_chain=doc_chain,

memory=memory,

question_generator=question_generator,

)

result = qa({"question": query})

rag_result = result.get("answer")

return rag_result

import gradio as gr

multi_modal_chat_agent = gr.Interface(fn=chat_gr,

inputs=['text'],

outputs=['text'],

title="Multi Modal chat agent",

description="Multi Modal chat agent",

allow_flagging="never")

multi_modal_chat_agent.launch(debug=True, share=False, show_api=False, server_port=5003, server_name="0.0.0.0")

本地服务器可以使用一下链接,在浏览器中直接进行访问了。

http://localhost:5003/

实施步骤:

环境搭建:

conda create --name ai_endpoint python=3.8

conda activate ai_endpoint

pip install -i https://mirrors.aliyun.com/pypi/simple  langchain-nvidia-ai-endpoints

pip install -i https://mirrors.aliyun.com/pypi/simple  jupyterlab

pip install -i https://mirrors.aliyun.com/pypi/simple  langchain_core

pip install -i https://mirrors.aliyun.com/pypi/simple  langchain

pip install -i https://mirrors.aliyun.com/pypi/simple  matplotlib

pip install -i https://mirrors.aliyun.com/pypi/simple  numpy

pip install -i https://mirrors.aliyun.com/pypi/simple  faiss-cpu==1.7.2

pip install -i https://mirrors.aliyun.com/pypi/simple  openai

pip install -i https://mirrors.aliyun.com/pypi/simple gradio

pip install -i https://mirrors.aliyun.com/pypi/simple -U langchain-community

jupyter-lab

代码实现:

from langchain_nvidia_ai_endpoints import ChatNVIDIA

from langchain_nvidia_ai_endpoints import NVIDIAEmbeddings

from langchain.chains import ConversationalRetrievalChain, LLMChain

from langchain.chains.conversational_retrieval.prompts import CONDENSE_QUESTION_PROMPT, QA_PROMPT

from langchain.chains.question_answering import load_qa_chain

from langchain.memory import ConversationBufferMemory

from langchain.vectorstores import FAISS

from langchain.text_splitter import RecursiveCharacterTextSplitter

import getpass

import os

if not os.environ.get("NVIDIA_API_KEY", "").startswith("nvapi-"):

nvapi_key = getpass.getpass("Enter your NVIDIA API key: ")

assert nvapi_key.startswith("nvapi-"), f"{nvapi_key[:5]}... is not a valid key"

os.environ["NVIDIA_API_KEY"] = nvapi_key

import re

from typing import List, Union

import requests

from bs4 import BeautifulSoup

def html_document_loader(url: Union[str, bytes]) -> str:

"""

Loads the HTML content of a document from a given URL and return it's content.

Args:

url: The URL of the document.

Returns:

The content of the document.

Raises:

Exception: If there is an error while making the HTTP request.

"""

try:

response = requests.get(url)

html_content = response.text

except Exception as e:

print(f"Failed to load {url} due to exception {e}")

return ""

try:

soup = BeautifulSoup(html_content, "html.parser")

for script in soup(["script", "style"]):

script.extract()

text = soup.get_text()

text = re.sub("s+", " ", text).strip()

return text

except Exception as e:

print(f"Exception {e} while loading document")

return ""

def create_embeddings(embedding_path: str = "./embed"):

embedding_path = "./embed"

print(f"Storing embeddings to {embedding_path}")

urls = [

"https://baike.baidu.com/item/%E5%AE%A0%E7%89%A9%E7%8B%97/6677317?fr=ge_ala"

]

documents = []

for url in urls:

document = html_document_loader(url)

documents.append(document)

text_splitter = RecursiveCharacterTextSplitter(

chunk_size=1000,

chunk_overlap=0,

length_function=len,

)

texts = text_splitter.create_documents(documents)

index_docs(url, text_splitter, texts, embedding_path)

print("Generated embedding successfully")

import re

def remove_control_chars(text_list):

for index, text in enumerate(text_list):

if not isinstance(text, str):

raise ValueError("Input must be a string")

text_list[index] = text

return text_list

def index_docs(url: Union[str, bytes], splitter, documents: List[str], dest_embed_dir) -> None:

"""

Split the document into chunks and create embeddings for the document

Args:

url: Source url for the document.

splitter: Splitter used to split the document

documents: list of documents whose embeddings needs to be created

dest_embed_dir: destination directory for embeddings

Returns:

None

"""

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

text_splitter = CharacterTextSplitter(chunk_size=400, separator="。")

docs = []

metadatas = []

for document in documents:

texts_raw = splitter.split_text(document.page_content)

splits = text_splitter.split_text(texts_raw[0])

docs.extend(splits)

metadatas.extend([document.metadata]*len(splits))

docs = remove_control_chars(docs)

if os.path.exists(dest_embed_dir):

update = FAISS.load_local(folder_path=dest_embed_dir, embeddings=embeddings, allow_dangerous_deserialization=True)

update.add_texts(docs, metadatas=metadatas)

update.save_local(folder_path=dest_embed_dir)

else:

os.makedirs(dest_embed_dir)

docsearch = FAISS.from_texts(docs, embeddings , metadatas=metadatas)

docsearch.save_local(folder_path=dest_embed_dir)

import os

from tqdm import tqdm

from pathlib import Path

from langchain.text_splitter import CharacterTextSplitter

from langchain_nvidia_ai_endpoints import NVIDIAEmbeddings

def create_embeddings_text(text_path: str = "./zh_data/", embedding_path: str = "./embed"):

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

ps = os.listdir(text_path)

data = []

sources = []

for p in ps:

if p.endswith('.txt'):

path2file=text_path+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)

documents=[d for d in data if d != 'n']

len(data), len(documents), data[0]

text_splitter = CharacterTextSplitter(chunk_size=400, separator="。")

docs = []

metadatas = []

dest_embed_dir = embedding_path

for i, d in enumerate(documents):

splits = text_splitter.split_text(d)

docs.extend(splits)

metadatas.extend([{"source": sources[i]}] * len(splits))

docs = remove_control_chars(docs)

if os.path.exists(dest_embed_dir):

update = FAISS.load_local(folder_path=dest_embed_dir, embeddings=embedder, allow_dangerous_deserialization=True)

update.add_texts(docs, metadatas=metadatas)

update.save_local(folder_path=dest_embed_dir)

else:

os.makedirs(dest_embed_dir)

docsearch = FAISS.from_texts(docs, embedder , metadatas=metadatas)

docsearch.save_local(folder_path=dest_embed_dir)

import os

import shutil

def ensure_empty_directory(dir_path):

if os.path.exists(dir_path):

shutil.rmtree(dir_path)

ensure_empty_directory("./embed")

create_embeddings()

create_embeddings_text()

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

embedding_path = "embed/"

docsearch = FAISS.load_local(folder_path=embedding_path, embeddings=embedding_model, allow_dangerous_deserialization=True)

llm = ChatNVIDIA(model="ai-mixtral-8x7b-instruct")

result = llm.invoke("Tell me something about nemo")

print(result.content)

llm = ChatNVIDIA(model="ai-mixtral-8x7b-instruct")

memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True)

question_generator = LLMChain(llm=llm, prompt=CONDENSE_QUESTION_PROMPT)

chat = ChatNVIDIA(model="ai-mixtral-8x7b-instruct", temperature=0.1, max_tokens=1000, top_p=1.0)

doc_chain = load_qa_chain(chat , chain_type="stuff", prompt=QA_PROMPT)

qa = ConversationalRetrievalChain(

retriever=docsearch.as_retriever(),

combine_docs_chain=doc_chain,

memory=memory,

question_generator=question_generator,

)

query = "宠物狗的介绍?"

print(query)

query = "宠物狗的介绍?请将结果翻译成中文。"

print(query)

query = "宠物狗的百度百科的介绍?"

print(query)

query = "宠物狗的百度百科的介绍?请将结果翻译成中文。"

print(query)

query = "汪汪宠物狗的公司的介绍?"

print(query)

query = "汪汪宠物狗的公司的介绍,请将结果翻译成中文。"

print(query)

def chat_gr(query):

qa = ConversationalRetrievalChain(

retriever=docsearch.as_retriever(),

combine_docs_chain=doc_chain,

memory=memory,

question_generator=question_generator,

)

result = qa({"question": query})

rag_result = result.get("answer")

return rag_result

import gradio as gr

multi_modal_chat_agent = gr.Interface(fn=chat_gr,

inputs=['text'],

outputs=['text'],

title="Multi Modal chat agent",

description="Multi Modal chat agent",

allow_flagging="never")

multi_modal_chat_agent.launch(debug=True, share=False, show_api=False, server_port=5003, server_name="0.0.0.0")

测试与调优:

代码中已经实现了txt格式文档和网页2种模态的文档数据的RAG检索增强生成,具体修改的位置如下所示。

def create_embeddings(embedding_path: str = "./embed"):

embedding_path = "./embed"

print(f"Storing embeddings to {embedding_path}")

urls = [

"https://baike.baidu.com/item/%E5%AE%A0%E7%89%A9%E7%8B%97/6677317?fr=ge_ala"

]

def create_embeddings_text(text_path: str = "./zh_data/", embedding_path: str = "./embed"):

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

ps = os.listdir(text_path)

绿色的可以进行网址的修改,以及txt格式文件路径的修改。

这样就可以在AI-Agent中进行RAG检索增强生成了,而且RAG的数据源支持了txt格式文件和网页格式的2种模态的增强文档资料,这就可以实现一些特定信息应用需求。

比如,有一个名字叫“汪汪宠物狗”的公司:存在一个名称是“汪汪宠物狗”的公司。而且有相关的txt格式文档或者网页资料数据。

假如我想检索公司名称是“汪汪宠物狗”公司,使用LLM肯定是没有结果,但是如果加入这个txt格式文档内容的限制条件,就可以返回我想要的结果了。

本文中的案例,可以尝试输入一下文本,就可以得到自己想要的检索结果了。

宠物狗的介绍?

宠物狗的介绍?请将结果翻译成中文。

宠物狗的百度百科的介绍?

宠物狗的百度百科的介绍?请将结果翻译成中文。

汪汪宠物狗的公司的介绍?

汪汪宠物狗的公司的介绍,请将结果翻译成中文。

集成与部署:

AI-Agent中进行RAG检索增强生成了,而且RAG的数据源支持了txt格式文件和网页格式的2种模态的增强文档资料,这就可以实现一些特定信息应用需求。

比如,有一个名字叫“汪汪宠物狗”的公司:存在一个名称是“汪汪宠物狗”的公司。而且有相关的txt或者网页资料数据。

 代码中实现了2个函数,因为使用了同一个Embedding Model 的嵌入向量模型,比如

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

所以,可以直接对数据库进行更新写入即可。

create_embeddings() 

create_embeddings_text()

import os

import shutil

def ensure_empty_directory(dir_path):

if os.path.exists(dir_path):

shutil.rmtree(dir_path)

ensure_empty_directory("./embed")

create_embeddings()

create_embeddings_text()

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

 使用将多模态智能体封装进Gradio,需要要对函数再进行一次封装,需要满足gr.Interface的函数调用格式。

对于服务api的端口只能使用一次,需要再次更改端口号码。

def chat_gr(query):

qa = ConversationalRetrievalChain(

retriever=docsearch.as_retriever(),

combine_docs_chain=doc_chain,

memory=memory,

question_generator=question_generator,

)

result = qa({"question": query})

rag_result = result.get("answer")

return rag_result

import gradio as gr

multi_modal_chat_agent = gr.Interface(fn=chat_gr,

inputs=['text'],

outputs=['text'],

title="Multi Modal chat agent",

description="Multi Modal chat agent",

allow_flagging="never")

multi_modal_chat_agent.launch(debug=True, share=False, show_api=False, server_port=5003, server_name="0.0.0.0")

本地服务器可以使用一下链接,在浏览器中直接进行访问了。

http://localhost:5003/

说明各模块集成方法及最终部署到实际运行环境的步骤。

使用将多模态智能体封装进Gradio,需要要对函数再进行一次封装,需要满足gr.Interface的函数调用格式。

对于服务api的端口只能使用一次,需要再次更改端口号码。

def chat_gr(query):

qa = ConversationalRetrievalChain(

retriever=docsearch.as_retriever(),

combine_docs_chain=doc_chain,

memory=memory,

question_generator=question_generator,

)

result = qa({"question": query})

rag_result = result.get("answer")

return rag_result

import gradio as gr

multi_modal_chat_agent = gr.Interface(fn=chat_gr,

inputs=['text'],

outputs=['text'],

title="Multi Modal chat agent",

description="Multi Modal chat agent",

allow_flagging="never")

multi_modal_chat_agent.launch(debug=True, share=False, show_api=False, server_port=5003, server_name="0.0.0.0")

本地服务器可以使用一下链接,在浏览器中直接进行访问了。

http://localhost:5003/

项目成果与展示:

应用场景展示:

(1)在AI-Agent中进行了RAG检索增强生成,而且RAG的数据源支持了txt格式文件和网页格式的2种模态的增强文档资料,这就可以实现一些特定信息应用需求。比如,

有一个名字叫“汪汪宠物狗”的公司:存在一个名称是“汪汪宠物狗”的公司,“汪汪宠物狗”公司创始人是“汪汪”,这个公司成立于宇宙时间10000年1000月100日。公司的简单介绍如下:‌1.‌公司愿景‌:‌致力于打造一个宠物狗与主人共享幸福生活的乐园,‌让每一只宠物狗都能得到最好的关爱和照顾。‌2.‌公司使命‌:‌通过提供专业的宠物狗服务,‌传播宠物文化,‌增进人与宠物之间的情感联系,‌提升宠物狗的生活品质。‌3.‌核心价值观‌:爱:‌以爱为出发点,‌对待每一只宠物狗如同家人一般。‌专业:‌不断学习和创新,‌提供最高水平的宠物狗服务和产品。‌责任:‌承担起对宠物狗、‌客户和社会的责任,‌积极参与公益活动。4.‌公司历史与创始人故事‌:‌公司由一位热爱宠物狗的资深宠物爱好者创立,‌他/她曾经救助过许多流浪狗,‌并深感宠物狗给人类带来的快乐和陪伴是无价的。‌因此,‌决定创立这家公司,‌将这份爱传递给更多的宠物狗和它们的主人。‌5.‌公司特色项目‌:‌“宠物狗才艺秀”:‌定期举办宠物狗才艺比赛,‌展示宠物狗的智慧和才能。‌“宠物狗公益行”:‌组织志愿者团队,‌参与宠物狗的救助和领养活动,‌推广宠物保护意识。‌“宠物狗主题度假村”:‌打造一个宠物狗和主人可以共同享受的度假村,‌提供豪华住宿和宠物设施。6.‌公司成就与荣誉‌:‌荣获“宇宙时间10000年度的最佳宠物服务品牌”称号,‌由宠物行业协会颁发。‌成为多家宠物慈善机构的合作伙伴,‌共同推动宠物福利事业。‌累计帮助数千只流浪狗找到温暖的家,‌受到社会各界的广泛赞誉。‌7.‌公司未来规划‌:‌扩大业务范围,‌开设更多的宠物狗专卖店和服务中心。‌推出自主研发的宠物狗食品和保健品系列,‌注重天然和健康。‌建立宠物狗训练学校,‌提供专业的宠物狗训练课程和教育服务。‌8.‌公司文化与氛围‌:‌公司内部充满活力和创意,‌鼓励员工提出新的想法和建议。‌定期举办员工培训和团队建设活动,‌提升员工的专业技能和服务意识。‌营造一个温馨、‌和谐的工作环境,‌让员工和宠物狗都能感受到家的温暖。 ‌假如我想检索公司名称是“汪汪宠物狗”公司,使用LLM肯定是没有结果,但是如果假如了这个txt的限制条件,就可以返回我想要的结果了。

同样,假如我想基于某个网页资料的内容,进行相关问题的检索,也可以得到我想要的检索结果信息。

功能演示:

本地服务器可以使用一下链接,在浏览器中直接进行访问了。

http://localhost:5003/

本文中的案例,可以尝试输入一下文本,就可以得到自己想要的检索结果了。

宠物狗的介绍?

宠物狗的介绍?请将结果翻译成中文。

宠物狗的百度百科的介绍?

宠物狗的百度百科的介绍?请将结果翻译成中文。

汪汪宠物狗的公司的介绍?

汪汪宠物狗的公司的介绍,请将结果翻译成中文。

问题与解决方案:

问题分析: 详细描述在项目实施过程中遇到的主要问题。解决措施: 阐述针对每个问题采取的具体解决措施及心路历程,体现问题解决能力。

问题1:创新方案的构思和构建问题。

(1)从RAG本身的多模态信息来源的思路,支持文本,网页,语音,图像,图表,PDF,WORD,PPT等等多种模态的增强文档资料。

(2)从输入查询信息的角度,可以输入支持文本,网页,语音,图像,图表,PDF,WORD,PPT等等多种模态的增强文档资料+query文本查询信息。

选择了(1),而且选择了便于实现的就是txt格式和网页格式的2种模态的增强文档资料。

问题2:就是txt格式和网页2种模态的增强文档资料的向量数据库的合并问题。

解决措施:因为使用了同一个Embedding Model 的嵌入向量模型,比如

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

所以,可以直接对数据库进行更新写入即可。

关键代码如下:

text_splitter = CharacterTextSplitter(chunk_size=400, separator="。")

docs = []

metadatas = []

dest_embed_dir = embedding_path

for i, d in enumerate(documents):

splits = text_splitter.split_text(d)

docs.extend(splits)

metadatas.extend([{"source": sources[i]}] * len(splits))

docs = remove_control_chars(docs)

if os.path.exists(dest_embed_dir):

update = FAISS.load_local(folder_path=dest_embed_dir, embeddings=embedder, allow_dangerous_deserialization=True)

update.add_texts(docs, metadatas=metadatas)

update.save_local(folder_path=dest_embed_dir)

else:

os.makedirs(dest_embed_dir)

docsearch = FAISS.from_texts(docs, embedder , metadatas=metadatas)

docsearch.save_local(folder_path=dest_embed_dir)

问题3:遇到了使用其他网页,其他txt资料进行向量化的错误问题。

解决措施:刚开始以为是txt文档中的控制字符的问题,去掉控制字符依旧没有解决这个问题。只能一行一行的删减txt文档中的文字,发现了只要字符窜的长度太长了就会有问题。只要修改代码中字符串的长度了就可以解决问题了。也就是使用“。”进行分割就正常了。如果是英文资料需要用“.”。也可以自己编写一个分割函数,兼容2种模式。

    text_splitter = CharacterTextSplitter(chunk_size=400, separator="。")

从此推断,网页也是这个问题。修改代码如下:   

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

text_splitter = CharacterTextSplitter(chunk_size=400, separator="。")

docs = []

metadatas = []

for document in documents:

texts_raw = splitter.split_text(document.page_content)

splits = text_splitter.split_text(texts_raw[0])

docs.extend(splits)

metadatas.extend([document.metadata]*len(splits))

docs = remove_control_chars(docs)

if os.path.exists(dest_embed_dir):

update = FAISS.load_local(folder_path=dest_embed_dir, embeddings=embeddings, allow_dangerous_deserialization=True)

update.add_texts(docs, metadatas=metadatas)

update.save_local(folder_path=dest_embed_dir)

else:

os.makedirs(dest_embed_dir)

docsearch = FAISS.from_texts(docs, embeddings , metadatas=metadatas)

docsearch.save_local(folder_path=dest_embed_dir)

问题4:将多模态智能体封装进Gradio错误。

解决措施:需要对函数再进行一次封装,需要满足gr.Interface的函数调用格式。对于服务api的端口只能使用一次,需要再次更改端口号码。

def chat_gr(query):

qa = ConversationalRetrievalChain(

retriever=docsearch.as_retriever(),

combine_docs_chain=doc_chain,

memory=memory,

question_generator=question_generator,

)

result = qa({"question": query})

rag_result = result.get("answer")

return rag_result

import gradio as gr

multi_modal_chat_agent = gr.Interface(fn=chat_gr,

inputs=['text'],

outputs=['text'],

title="Multi Modal chat agent",

description="Multi Modal chat agent",

allow_flagging="never")

multi_modal_chat_agent.launch(debug=True, share=False, show_api=False, server_port=5003, server_name="0.0.0.0")

项目总结与展望:

项目评估: 对项目的整体表现进行客观评估,总结成功点和存在的不足。

目前已经实现了txt格式和网页2种模态的增强文档资料进行RAG了。但是,还有很多可以做,比如,语音,图像,PDF,WORD,PPT等等多种模态的增强文档资料都很容易集成进去的。

未来方向: 基于项目经验,提出未来可能的改进方向和发展规划。

未来会在考虑

(1)在RAG阶段加入更多的模态:文本,网页,语音,图像,图表,PDF,WORD,PPT等等多种模态的增强文档资料。

(2)在输入查询信息的直接就支持:文本,网页,语音,图像,图表,PDF,WORD,PPT等等多种模态的增强文档资料输入,以及query查询信息也支持文本,网页,语音,图像,图表,PDF,WORD,PPT等等多种模态的查询信息输入了。

附件与参考资料

NVIDIA AI Endpoint介绍页面: NVIDIA AI Foundation Endpoints | ️ LangChainNVIDIA NIM页面: Try NVIDIA NIM APIsNVIDIA DLI课程学习资料页面:NVIDIA 深度学习培训中心(DLI)| 在线实战培训

相关知识

1小时搭建“汪汪宠物狗”公司的N种模态文档的RAG智能对话机器人
25家企业亮相智谱AI Z计划首届路演!张鹏:AGI生态基金“Z基金”正式推出
受邀参加了智谱AI Z Demo Day,让我再一次相信 AGI!
汪汪队的翻译官: Traini完成千万元天使轮融资
进击的人工智能:从产品角度,深度解析「对话机器人」 – 人人都是产品经理,
融资丨硅谷宠物共情AI公司Traini获千万天使轮融资
汪汪队的翻译官:Traini完成千万元天使轮融资
智能毛皮,让宠物机器人更懂主人的情绪
宠物狗宠物鸟宠物猫机器人最新资讯
对话Traini:4人创业公司用大模型翻译“狗语”,已获得20万用户

网址: 1小时搭建“汪汪宠物狗”公司的N种模态文档的RAG智能对话机器人 https://m.mcbbbk.com/newsview93391.html

所属分类:萌宠日常
上一篇: 朴槿惠给宠物狗宝宝取名:“和平”
下一篇: 2024最新常见宠物价格表(宠物