Numa era em que a privacidade dos dados é fundamental, configurar o seu próprio modelo de idioma local (LLM) proporciona uma solução crucial tanto para empresas como para indivíduos. Este tutorial foi desenvolvido para guiá-lo através do processo de criação de um chatbot personalizado usando Ollama , Python 3 e ChromaDB , todos hospedados localmente em seu sistema. Aqui estão os principais motivos pelos quais você precisa deste tutorial:
Este tutorial irá capacitá-lo a construir um chatbot local robusto e seguro, adaptado às suas necessidades, sem comprometer a privacidade ou o controle.
A geração aumentada de recuperação (RAG) é uma técnica avançada que combina os pontos fortes da recuperação de informações e da geração de texto para criar respostas mais precisas e contextualmente relevantes. Aqui está um resumo de como o RAG funciona e por que é benéfico:
RAG é um modelo híbrido que aprimora as capacidades dos modelos de linguagem incorporando uma base de conhecimento externa ou armazenamento de documentos. O processo envolve dois componentes principais:
Ao configurar um aplicativo RAG local com ferramentas como Ollama, Python e ChromaDB, você pode aproveitar os benefícios de modelos de linguagem avançados enquanto mantém o controle sobre seus dados e opções de personalização.
A execução de grandes modelos de linguagem (LLMs), como os usados na Retrieval-Augmented Generation (RAG), requer um poder computacional significativo. Um dos principais componentes que permitem o processamento eficiente e a incorporação de dados nesses modelos é a Unidade de Processamento Gráfico (GPU). Veja por que as GPUs são essenciais para esta tarefa e como elas afetam o desempenho da configuração local do LLM:
Uma GPU é um processador especializado projetado para acelerar a renderização de imagens e vídeos. Ao contrário das Unidades Centrais de Processamento (CPUs), que são otimizadas para tarefas de processamento sequencial, as GPUs são excelentes no processamento paralelo. Isso os torna particularmente adequados para os cálculos matemáticos complexos exigidos pelo aprendizado de máquina e pelos modelos de aprendizado profundo.
Ao configurar um LLM local, a escolha da GPU pode impactar significativamente o desempenho. Aqui estão alguns fatores a serem considerados:
Investir em uma GPU de alto desempenho é crucial para executar modelos LLM localmente. Ele garante processamento de dados mais rápido, treinamento eficiente de modelos e geração rápida de respostas, tornando seu aplicativo RAG local mais robusto e confiável. Ao aproveitar o poder das GPUs, você pode aproveitar plenamente os benefícios de hospedar seu próprio chatbot personalizado, adaptado às suas necessidades específicas e requisitos de privacidade de dados.
Antes de mergulhar na configuração, certifique-se de ter os seguintes pré-requisitos em vigor:
Para instalar e configurar nosso ambiente Python 3, siga estas etapas: Baixe e configure o Python 3 em sua máquina. Em seguida, certifique-se de que seu Python 3 esteja instalado e executado com sucesso:
$ python3 --version # Python 3.11.7
Crie uma pasta para o seu projeto, por exemplo, local-rag
:
$ mkdir local-rag $ cd local-rag
Crie um ambiente virtual chamado venv
:
$ python3 -m venv venv
Ative o ambiente virtual:
$ source venv/bin/activate # Windows # venv\Scripts\activate
Instale o ChromaDB usando pip:
$ pip install --q chromadb
Instale as ferramentas Langchain para funcionar perfeitamente com o seu modelo:
$ pip install --q unstructured langchain langchain-text-splitters $ pip install --q "unstructured[all-docs]"
Instale o Flask para servir seu aplicativo como um serviço HTTP:
$ pip install --q flask
Para instalar o Ollama, siga estas etapas: Vá para a página de download do Ollama e baixe o instalador para o seu sistema operacional. Verifique a instalação do Ollama executando:
$ ollama --version # ollama version is 0.1.47
Puxe o modelo LLM que você precisa. Por exemplo, para usar o modelo Mistral:
$ ollama pull mistral
Puxe o modelo de incorporação de texto. Por exemplo, para usar o modelo Nomic Embed Text:
$ ollama pull nomic-embed-text
Em seguida, execute seus modelos Ollama:
$ ollama serve
Agora que você configurou seu ambiente com Python, Ollama, ChromaDB e outras dependências, é hora de construir seu aplicativo RAG local personalizado. Nesta seção, examinaremos o código Python prático e forneceremos uma visão geral de como estruturar seu aplicativo.
app.py
Este é o arquivo principal do aplicativo Flask. Ele define rotas para incorporar arquivos ao banco de dados vetorial e recuperar a resposta do modelo.
import os from dotenv import load_dotenv load_dotenv() from flask import Flask, request, jsonify from embed import embed from query import query from get_vector_db import get_vector_db TEMP_FOLDER = os.getenv('TEMP_FOLDER', './_temp') os.makedirs(TEMP_FOLDER, exist_ok=True) app = Flask(__name__) @app.route('/embed', methods=['POST']) def route_embed(): if 'file' not in request.files: return jsonify({"error": "No file part"}), 400 file = request.files['file'] if file.filename == '': return jsonify({"error": "No selected file"}), 400 embedded = embed(file) if embedded: return jsonify({"message": "File embedded successfully"}), 200 return jsonify({"error": "File embedded unsuccessfully"}), 400 @app.route('/query', methods=['POST']) def route_query(): data = request.get_json() response = query(data.get('query')) if response: return jsonify({"message": response}), 200 return jsonify({"error": "Something went wrong"}), 400 if __name__ == '__main__': app.run(host="0.0.0.0", port=8080, debug=True)
embed.py
Este módulo cuida do processo de incorporação, incluindo salvar arquivos carregados, carregar e dividir dados e adicionar documentos ao banco de dados vetorial.
import os from datetime import datetime from werkzeug.utils import secure_filename from langchain_community.document_loaders import UnstructuredPDFLoader from langchain_text_splitters import RecursiveCharacterTextSplitter from get_vector_db import get_vector_db TEMP_FOLDER = os.getenv('TEMP_FOLDER', './_temp') # Function to check if the uploaded file is allowed (only PDF files) def allowed_file(filename): return '.' in filename and filename.rsplit('.', 1)[1].lower() in {'pdf'} # Function to save the uploaded file to the temporary folder def save_file(file): # Save the uploaded file with a secure filename and return the file path ct = datetime.now() ts = ct.timestamp() filename = str(ts) + "_" + secure_filename(file.filename) file_path = os.path.join(TEMP_FOLDER, filename) file.save(file_path) return file_path # Function to load and split the data from the PDF file def load_and_split_data(file_path): # Load the PDF file and split the data into chunks loader = UnstructuredPDFLoader(file_path=file_path) data = loader.load() text_splitter = RecursiveCharacterTextSplitter(chunk_size=7500, chunk_overlap=100) chunks = text_splitter.split_documents(data) return chunks # Main function to handle the embedding process def embed(file): # Check if the file is valid, save it, load and split the data, add to the database, and remove the temporary file if file.filename != '' and file and allowed_file(file.filename): file_path = save_file(file) chunks = load_and_split_data(file_path) db = get_vector_db() db.add_documents(chunks) db.persist() os.remove(file_path) return True return False
query.py
Este módulo processa consultas de usuários gerando múltiplas versões da consulta, recuperando documentos relevantes e fornecendo respostas com base no contexto.
import os from langchain_community.chat_models import ChatOllama from langchain.prompts import ChatPromptTemplate, PromptTemplate from langchain_core.output_parsers import StrOutputParser from langchain_core.runnables import RunnablePassthrough from langchain.retrievers.multi_query import MultiQueryRetriever from get_vector_db import get_vector_db LLM_MODEL = os.getenv('LLM_MODEL', 'mistral') # Function to get the prompt templates for generating alternative questions and answering based on context def get_prompt(): QUERY_PROMPT = PromptTemplate( input_variables=["question"], template="""You are an AI language model assistant. Your task is to generate five different versions of the given user question to retrieve relevant documents from a vector database. By generating multiple perspectives on the user question, your goal is to help the user overcome some of the limitations of the distance-based similarity search. Provide these alternative questions separated by newlines. Original question: {question}""", ) template = """Answer the question based ONLY on the following context: {context} Question: {question} """ prompt = ChatPromptTemplate.from_template(template) return QUERY_PROMPT, prompt # Main function to handle the query process def query(input): if input: # Initialize the language model with the specified model name llm = ChatOllama(model=LLM_MODEL) # Get the vector database instance db = get_vector_db() # Get the prompt templates QUERY_PROMPT, prompt = get_prompt() # Set up the retriever to generate multiple queries using the language model and the query prompt retriever = MultiQueryRetriever.from_llm( db.as_retriever(), llm, prompt=QUERY_PROMPT ) # Define the processing chain to retrieve context, generate the answer, and parse the output chain = ( {"context": retriever, "question": RunnablePassthrough()} | prompt | llm | StrOutputParser() ) response = chain.invoke(input) return response return None
get_vector_db.py
Este módulo inicializa e retorna a instância do banco de dados vetorial usada para armazenar e recuperar embeddings de documentos.
import os from langchain_community.embeddings import OllamaEmbeddings from langchain_community.vectorstores.chroma import Chroma CHROMA_PATH = os.getenv('CHROMA_PATH', 'chroma') COLLECTION_NAME = os.getenv('COLLECTION_NAME', 'local-rag') TEXT_EMBEDDING_MODEL = os.getenv('TEXT_EMBEDDING_MODEL', 'nomic-embed-text') def get_vector_db(): embedding = OllamaEmbeddings(model=TEXT_EMBEDDING_MODEL,show_progress=True) db = Chroma( collection_name=COLLECTION_NAME, persist_directory=CHROMA_PATH, embedding_function=embedding ) return db
Crie o arquivo .env
para armazenar suas variáveis de ambiente:
TEMP_FOLDER = './_temp' CHROMA_PATH = 'chroma' COLLECTION_NAME = 'local-rag' LLM_MODEL = 'mistral' TEXT_EMBEDDING_MODEL = 'nomic-embed-text'
Execute o arquivo app.py
para iniciar seu servidor de aplicativos:
$ python3 app.py
Quando o servidor estiver em execução, você poderá começar a fazer solicitações aos seguintes endpoints:
$ curl --request POST \ --url http://localhost:8080/embed \ --header 'Content-Type: multipart/form-data' \ --form file=@/Users/nassermaronie/Documents/Nasser-resume.pdf # Response { "message": "File embedded successfully" }
$ curl --request POST \ --url http://localhost:8080/query \ --header 'Content-Type: application/json' \ --data '{ "query": "Who is Nasser?" }' # Response { "message": "Nasser Maronie is a Full Stack Developer with experience in web and mobile app development. He has worked as a Lead Full Stack Engineer at Ulventech, a Senior Full Stack Engineer at Speedoc, a Senior Frontend Engineer at Irvins, and a Software Engineer at Tokopedia. His tech stacks include Typescript, ReactJS, VueJS, React Native, NodeJS, PHP, Golang, Python, MySQL, PostgresQL, MongoDB, Redis, AWS, Firebase, and Supabase. He has a Bachelor's degree in Information System from Universitas Amikom Yogyakarta." }
Seguindo estas instruções, você pode executar e interagir efetivamente com seu aplicativo RAG local personalizado usando Python, Ollama e ChromaDB, adaptado às suas necessidades. Ajuste e expanda a funcionalidade conforme necessário para aprimorar os recursos do seu aplicativo.
Ao aproveitar os recursos de implantação local, você não apenas protege informações confidenciais, mas também otimiza o desempenho e a capacidade de resposta. Esteja você melhorando as interações com os clientes ou simplificando processos internos, um aplicativo RAG implantado localmente oferece flexibilidade e robustez para se adaptar e crescer de acordo com suas necessidades.
https://github.com/firstpersoncode/local-rag
Boa codificação!