
阅读时间:〜10分钟
使用Pulsejet Github repo建造艺术装饰式瓦格聊天机器人:https://github.com/jet-engine/art-deco-chatbot
可以从以下链接中读取此博客文章:
大型语言模型(LLMS)已显着提高,提高了他们回答各种问题的能力。但是,他们仍然遇到挑战,尤其是在特定或最近的信息中,通常会导致不准确或“幻觉”。为了解决这些问题,检索增强生成(RAG)方法将文件检索步骤集成到响应生成过程中。该方法使用文档语料库并采用矢量数据库进行有效检索,从而通过三个关键步骤提高了LLM响应的准确性和可靠性:
向量数据库促进了快速相似性搜索和有效的数据管理,从而成为增强LLM功能的强大解决方案。
跨越1920年代到1940年代的咆哮时代的装饰艺术时代,在建筑中留下了令人眼花of乱的遗产。尽管诸如Meta的Llama3.1之类的模型具有功能,但它们的反应可能是不可靠的,尤其是针对装饰艺术特定的细微或详细查询。我们使用装饰艺术聊天机器人的目标是利用抹布来提高装饰艺术体系结构的响应质量,并将这些响应与传统LLM在质量和时间效率方面产生的响应进行比较。
通过设计装饰艺术聊天机器人,我们还旨在展示如何建立复杂的抹布系统。您可以在Art Deco Chatbot GitHub存储库中访问完整的代码。通过检查代码并阅读此读数,您将学习:
Ollama是一个程序,可在本地机器上轻松运行LLM型号。
ollama pull llama3.1 (将用于抹布的LLM)ollama pull nomic-embed-text (将用于抹布的嵌入模型)在这个项目中,我们不仅旨在编写代码以展示如何完成抹布,还要将抹布与查询的基准结果与不同的LLM进行比较和基准测试。这些LLM中的一些不能在本地运行(例如GPT-4o ),而其他LLM则无法在云服务上运行(例如Groq上的Llama3.1:70b )。
Litellm提供了一个统一的接口来查询不同的LLM,使我们的代码更清洁,更可读。建议查看Litellm Python库,但该项目不需要。
从OpenAI和GROQ获取API键在项目中使用它们。请注意,您可能会因使用这些服务而受到费用。虽然可以在撰写本文时免费使用Groq API ,但OpenAI API并非免费。
Pulsejet是一个高性能向量数据库,可有效地存储和检索文档嵌入。设置Pulsejet:
pip install pulsejetdocker run --name pulsejet_container -p 47044-47045:47044-47045 jetngine/pulsejet注意:您可以跳过第一步,因为PulseJet已包含在requirements.txt文件中。
检查PulseJet文档以获取有关运行Pulsejet Docker映像的详细信息,并使用Pulsejet Python库进行矢量数据库操作。
通过运行来安装所有必要的依赖项:
pip install -r requirements.txt
该项目是使用
Python 3.11的conda环境开发的。
由于我们尚未在不同的环境中测试该项目,因此我们建议遵守此配置以获得最佳性能和兼容性。
装饰艺术聊天机器人使用两个YAML文件进行配置: config.template.yaml和secrets.yaml 。这是每个部分的详细分解:
使用您的API键创建一个secrets.yaml文件:yaml文件:
# api_keys:
openai_key : " your_openai_key_here "
groq_key : " your_groq_key_here " # models:
main_model : " llama3.1 "
embed_model : " nomic-embed-text "
# vector_db:
vector_db : " pulsejet "
# pulsejet:
pulsejet_location : " remote "
pulsejet_collection_name : " art-deco "
# paths:
rag_files_path : " rag_files/ "
questions_file_path : " evaluation/questions.csv "
evaluation_path : " evaluation/ "
rag_prompt_path : " evaluation/rag_prompt.txt "
metrics_file_path : " evaluation/metrics.json "
# embeddings:
embeddings_file_path : " embeddings_data/all_embeddings_HSNW.h5 "
use_precalculated_embeddings : true
# llm_models:
all_models :
gpt-4o : " gpt-4o "
groq-llama3.1-8b : " groq/llama-3.1-8b-instant "
groq-llama3.1-70b : " groq/llama-3.1-70b-versatile "
ollama-llama3.1 : " ollama/llama3.1 "
ollama-llama3.1-70b : " ollama/llama3.1:70b "
selected_models :
- " gpt-4o "
- " groq-llama3.1-70b "
- " ollama-llama3.1 "
# rag_parameters:
sentences_per_chunk : 10
chunk_overlap : 2
file_extension : " .txt "这是每个部分的详细说明:
true时,系统将从指定的文件加载嵌入式。当false时,它将生成新的嵌入式并将其保存到此文件中。 在运行项目之前,请确保使用特定设置更新这些配置文件。调整抹布参数可以显着影响抹布系统的性能和准确性。对于特定用例和文档集找到最佳配置可能是必需的。
wiki-bot.py一起运行刮板此步骤是可选的,因为https://huggingface.co/datasets/jetengine/art_deco_usa_ds中可用Wikipedia的所有刮擦文章的内容文件。
您可以下载此数据集并将所有文本文件从其复制到rag_files目录中。如果您打算使用预计算的嵌入式(将在下一部分中进行说明),则实际上不需要下载此数据集。
无需重复刮擦过程。如果您对数据刮擦过程不感兴趣,则可以跳过本节的其余部分。
我们的第一步涉及收集有关Art-Deco架构的知识。鉴于它们在艺术运动中的重要性,我们专注于我们的结构。 wiki-bot.py脚本可自动化相关的Wikipedia文章的收集,将它们组织成一个结构化目录以易于访问。
使用:运行机器人:
python wiki-bot.py
当您使用一个空的rag_files目录运行wiki-bot.py时,它将刮擦的Wikipedia文章的内容保存在rag_files下的名为text的子文件中。该机器人还创建了各种子文件夹来组织不同类型的数据,例如文章URL,参考等。由于我们目前的重点仅在于Wikipedia文章的内容上,以减少混乱,因此我们仅将内容物从text子文件转移到我们的HG数据集并删除了所有其他子文件集。
因此,如果您想自己运行机器人,这是可选的,因为刮擦的文档已经可以在拥抱脸上可用,则需要将所有文件从文本子文件夹复制到rag_files目录,然后将rag_files中的所有sub-folders删除为rag_files_path in config.yaml中rag_files/text text.yaml。
indexing.py索引文档通过运行索引文档:
python indexing.py
该脚本处理文档,生成嵌入并将其存储在Pulsejet中。如果您不想浪费时间来生成嵌入式,则可以从https://huggingface.co/jetengine/rag_art_art_deco_embeddings下载预估计的嵌入式,并设置use_precalculated_embeddings: true 。
在我们的设置生成中,嵌入式大约需要15分钟才能完成,并将向量插入脉冲喷气机大约需要4秒钟。
该脚本输出计时信息:
chat.py进行推断确保您的配置正确,然后运行:
python chat.py
该脚本查询不同的LLM和抹布系统,输出导致HTML,JSON和CSV格式进行比较。
Pulsejet在此项目中用于有效的矢量存储和检索。这是关于如何将Pulsejet集成到我们的装饰艺术聊天机器人项目中的详细概述:
初始化Pulsejet客户端:
client = pj . PulsejetClient ( location = config [ 'pulsejet_location' ])这会创建一个PulseJet客户端。在我们的项目中,我们使用的是一个远程Pulsejet实例,因此该location设置为“远程”。这连接到在Docker容器中运行的PulseJet服务器。
创建一个集合:
client . create_collection ( collection_name , vector_config )这将在Pulsejet中创建一个新的集合来存储我们的文档嵌入。 vector_config参数指定向量存储的配置,例如向量大小和索引类型(例如,HNSW用于有效相似性搜索)。
插入向量:在我们的项目中,我们使用以下模式插入向量:
collection [ 0 ]. insert_single ( collection [ 1 ], embed , meta )一开始这可能会令人困惑,但这是什么意思:
collection[0]实际上是我们的PulseJet客户端实例。collection[1]是我们要插入的集合的名称。embed是我们正在插入的向量。meta是与矢量相关的其他元数据。这等同于致电:
client . insert_single ( collection_name , vector , meta )对于批量插入,我们使用:
client . insert_multi ( collection_name , embeds )这立即插入多个嵌入式,这对于大型数据集更有效。
搜索向量:
results = client [ 'db' ]. search_single ( collection , query_embed , limit = 5 , filter = None )这在指定的PulseJet集合中执行相似性搜索,以找到给定查询向量的最相关文档。 limit参数指定要返回的最大结果数。
在我们的项目中, client['db']用于访问PulseJet客户端的数据库方法。这相当于直接使用客户端:
results = client . search_single ( collection_name , query_vector , limit = 5 , filter = None )关闭连接:
client . close ()当不再需要时,这关闭了与PulseJet数据库的连接。
PulsejetRagClient类是在pulsejet_rag_client.py中定义的,并提供了一个高级接口,用于在我们的抹布系统的上下文中与PulseJet进行交互。这是其关键组成部分的细分:
初始化:
class PulsejetRagClient :
def __init__ ( self , config ):
self . config = config
self . collection_name = config [ 'pulsejet_collection_name' ]
self . main_model = config [ 'main_model' ]
self . embed_model = config [ 'embed_model' ]
self . client = pj . PulsejetClient ( location = config [ 'pulsejet_location' ])使用配置参数初始化客户端,设置PulseJet客户端并存储相关的配置值。
创建一个集合:
def create_collection ( self ):
vector_size = get_vector_size ( self . config [ 'embed_model' ])
vector_params = pj . VectorParams ( size = vector_size , index_type = pj . IndexType . HNSW )
try :
self . client . create_collection ( self . collection_name , vector_params )
logger . info ( f"Created new collection: { self . collection_name } " )
except Exception as e :
logger . info ( f"Collection ' { self . collection_name } ' already exists or error occurred: { str ( e ) } " )此方法在Pulsejet中创建了一个新的集合,并具有指定的参数。它使用get_vector_size函数来确定嵌入的适当向量大小。
插入向量:
def insert_vector ( self , vector , metadata = None ):
try :
self . client . insert_single ( self . collection_name , vector , metadata )
logger . debug ( f"Inserted vector with metadata: { metadata } " )
except Exception as e :
logger . error ( f"Error inserting vector: { str ( e ) } " )
def insert_vectors ( self , vectors , metadatas = None ):
try :
self . client . insert_multi ( self . collection_name , vectors , metadatas )
logger . debug ( f"Inserted { len ( vectors ) } vectors" )
except Exception as e :
logger . error ( f"Error inserting multiple vectors: { str ( e ) } " )这些方法将单个向量和多个向量插入PulseJet集合中,以及它们的相关元数据。
搜索向量:
def search_similar_vectors ( self , query_vector , limit = 5 ):
try :
results = self . client . search_single ( self . collection_name , query_vector , limit = limit , filter = None )
return results
except Exception as e :
logger . error ( f"Error searching for similar vectors: { str ( e ) } " )
return []此方法在Pulsejet集合中执行相似性搜索,以找到给定查询向量的最相关文档。
关闭连接:
def close ( self ):
try :
self . client . close ()
logger . info ( "Closed Pulsejet client connection" )
except Exception as e :
logger . error ( f"Error closing Pulsejet client connection: { str ( e ) } " )当不再需要时,此方法将关闭与PulseJet数据库的连接。
在整个项目中使用PulsejetRagClient与PulseJet相互作用。这是通常的实例化和使用的方式:
创建:
from pulsejet_rag_client import create_pulsejet_rag_client
config = get_config ()
rag_client = create_pulsejet_rag_client ( config )索引文件:
在indexing.py中,我们使用客户端创建集合并插入向量:
rag_client . create_collection ()
for file_name , file_embeddings in embeddings_data . items ():
for chunk_id , content , embed in file_embeddings :
metadata = { "filename" : file_name , "chunk_id" : chunk_id , "content" : content }
rag_client . insert_vector ( embed , metadata )在rag.py中,我们使用客户端在抹布过程中搜索类似的向量:
results = rag_client . search_similar_vectors ( query_embed , limit = 5 )操作完成后,我们关闭连接:
rag_client . close ()此实现为我们的抹布系统中的所有PulseJet操作提供了一个干净的封装接口。
LLama3.1的抹布任务,由于查询长度的增加而花的时间比简单的问题回答更长。装饰艺术聊天机器人展示了如何更好地利用llms的抹布。我们的项目对抹布实施进行了全面的探索,涵盖了从数据刮擦和文档块到嵌入创建以及矢量数据库集成的每个步骤。
随着抹布系统的文档基础的增长,插入和搜索操作的性能变得越来越关键。通过学习如何将Pulsejet Vector数据库集成到成熟的抹布系统中,人们可以从其功能中受益匪浅,尤其是在处理大型文档基础上的RAG应用程序时。
我们的破布响应本来可以更准确。为了提高我们的装饰艺术聊天机器人的表现,我们正在考虑几种实验方法:
我们计划通过以下计划扩展该项目:
我们鼓励您尝试装饰艺术聊天机器人,修改其参数,并将其调整到您自己感兴趣的领域。
作者:Güvençusanmaz