paint-brush
Xây dựng ứng dụng RAG của riêng bạn: Hướng dẫn từng bước để thiết lập LLM cục bộ bằng Ollama, Python và ChromaDBtừ tác giả@nassermaronie
7,828 lượt đọc
7,828 lượt đọc

Xây dựng ứng dụng RAG của riêng bạn: Hướng dẫn từng bước để thiết lập LLM cục bộ bằng Ollama, Python và ChromaDB

từ tác giả Nasser Maronie13m2024/07/04
Read on Terminal Reader

dài quá đọc không nổi

Hướng dẫn này sẽ hướng dẫn bạn quy trình tạo chatbot tùy chỉnh bằng cách sử dụng [Ollama], [Python 3 và [ChromaDB] Lưu trữ cục bộ ứng dụng Thế hệ truy xuất-tăng cường (RAG) của riêng bạn, nghĩa là bạn có toàn quyền kiểm soát việc thiết lập và tùy chỉnh.
featured image - Xây dựng ứng dụng RAG của riêng bạn: Hướng dẫn từng bước để thiết lập LLM cục bộ bằng Ollama, Python và ChromaDB
Nasser Maronie HackerNoon profile picture
0-item
1-item

Trong thời đại mà quyền riêng tư dữ liệu được đặt lên hàng đầu, việc thiết lập mô hình ngôn ngữ địa phương (LLM) của riêng bạn sẽ cung cấp một giải pháp quan trọng cho cả các công ty và cá nhân. Hướng dẫn này được thiết kế để hướng dẫn bạn trong quá trình tạo chatbot tùy chỉnh bằng Ollama , Python 3ChromaDB , tất cả đều được lưu trữ cục bộ trên hệ thống của bạn. Dưới đây là những lý do chính tại sao bạn cần hướng dẫn này:


  • Tùy chỉnh hoàn toàn: Lưu trữ cục bộ ứng dụng Thế hệ truy xuất-tăng cường (RAG) của riêng bạn có nghĩa là bạn có toàn quyền kiểm soát việc thiết lập và tùy chỉnh. Bạn có thể tinh chỉnh mô hình để phù hợp với nhu cầu cụ thể của mình mà không cần dựa vào các dịch vụ bên ngoài.
  • Quyền riêng tư nâng cao: Bằng cách thiết lập cục bộ mô hình LLM của bạn, bạn tránh được những rủi ro liên quan đến việc gửi dữ liệu nhạy cảm qua internet. Điều này đặc biệt quan trọng đối với các công ty xử lý thông tin bí mật. Huấn luyện mô hình của bạn bằng dữ liệu riêng tư cục bộ đảm bảo rằng dữ liệu của bạn nằm trong tầm kiểm soát của bạn.
  • Bảo mật dữ liệu: Việc sử dụng mô hình LLM của bên thứ ba có thể khiến dữ liệu của bạn có nguy cơ bị vi phạm và sử dụng sai mục đích. Việc triển khai cục bộ giảm thiểu những rủi ro này bằng cách giữ dữ liệu đào tạo của bạn, chẳng hạn như tài liệu PDF, trong môi trường an toàn của bạn.
  • Kiểm soát việc xử lý dữ liệu: Khi bạn lưu trữ LLM của riêng mình, bạn có khả năng quản lý và xử lý dữ liệu của mình chính xác theo cách bạn muốn. Điều này bao gồm việc nhúng dữ liệu riêng tư của bạn vào kho lưu trữ vectơ ChromaDB, đảm bảo rằng quá trình xử lý dữ liệu đáp ứng các tiêu chuẩn và yêu cầu của bạn.
  • Độc lập với kết nối Internet: Chạy chatbot cục bộ có nghĩa là bạn không phụ thuộc vào kết nối Internet. Điều này đảm bảo dịch vụ và quyền truy cập vào chatbot của bạn không bị gián đoạn, ngay cả trong các tình huống ngoại tuyến.


Hướng dẫn này sẽ giúp bạn xây dựng một chatbot cục bộ mạnh mẽ và an toàn, phù hợp với nhu cầu của bạn mà không ảnh hưởng đến quyền riêng tư hoặc quyền kiểm soát.

Mô hình tinh chỉnh


Thế hệ tăng cường truy xuất (RAG)

Tạo tăng cường truy xuất (RAG) là một kỹ thuật tiên tiến kết hợp các điểm mạnh của truy xuất thông tin và tạo văn bản để tạo ra các phản hồi chính xác hơn và phù hợp với ngữ cảnh hơn. Dưới đây là bảng phân tích cách thức hoạt động của RAG và lý do nó mang lại lợi ích:

RAG là gì?

RAG là một mô hình lai giúp nâng cao khả năng của các mô hình ngôn ngữ bằng cách kết hợp cơ sở tri thức bên ngoài hoặc kho tài liệu. Quá trình này bao gồm hai thành phần chính:

  • Truy xuất: Trong giai đoạn này, mô hình truy xuất các tài liệu hoặc mẩu thông tin có liên quan từ nguồn bên ngoài, chẳng hạn như cơ sở dữ liệu hoặc kho lưu trữ vectơ, dựa trên truy vấn đầu vào.
  • Tạo: Thông tin được truy xuất sau đó được mô hình ngôn ngữ tổng quát sử dụng để tạo ra phản hồi mạch lạc và phù hợp với ngữ cảnh.

RAG hoạt động như thế nào?

  • Đầu vào truy vấn: Người dùng nhập một truy vấn hoặc câu hỏi.
  • Truy xuất tài liệu: Hệ thống sử dụng truy vấn để tìm kiếm cơ sở kiến thức bên ngoài, truy xuất các tài liệu hoặc đoạn thông tin có liên quan nhất.
  • Tạo phản hồi: Mô hình tổng quát xử lý thông tin được truy xuất, tích hợp nó với kiến thức của chính nó để tạo ra phản hồi chi tiết và chính xác.
  • Đầu ra: Phản hồi cuối cùng, được bổ sung thêm các chi tiết cụ thể và phù hợp từ cơ sở kiến thức, được trình bày cho người dùng.

Lợi ích của RAG

  • Độ chính xác nâng cao: Bằng cách tận dụng dữ liệu bên ngoài, các mô hình RAG có thể cung cấp câu trả lời chính xác và chi tiết hơn, đặc biệt là cho các truy vấn theo miền cụ thể.
  • Mức độ phù hợp theo ngữ cảnh: Thành phần truy xuất đảm bảo rằng phản hồi được tạo ra dựa trên thông tin cập nhật và có liên quan, cải thiện chất lượng tổng thể của phản hồi.
  • Khả năng mở rộng: Hệ thống RAG có thể dễ dàng mở rộng quy mô để kết hợp lượng dữ liệu khổng lồ, cho phép chúng xử lý nhiều truy vấn và chủ đề khác nhau.
  • Tính linh hoạt: Những mô hình này có thể được điều chỉnh cho phù hợp với nhiều lĩnh vực khác nhau bằng cách cập nhật hoặc mở rộng cơ sở kiến thức bên ngoài, khiến chúng trở nên rất linh hoạt.

Tại sao nên sử dụng RAG cục bộ?

  • Quyền riêng tư và bảo mật: Chạy mô hình RAG cục bộ đảm bảo rằng dữ liệu nhạy cảm vẫn được bảo mật và riêng tư vì nó không cần phải gửi đến các máy chủ bên ngoài.
  • Tùy chỉnh: Bạn có thể điều chỉnh quy trình truy xuất và tạo cho phù hợp với nhu cầu cụ thể của mình, bao gồm cả việc tích hợp các nguồn dữ liệu độc quyền.
  • Độc lập: Thiết lập cục bộ đảm bảo rằng hệ thống của bạn vẫn hoạt động ngay cả khi không có kết nối internet, cung cấp dịch vụ nhất quán và đáng tin cậy.

Bằng cách thiết lập ứng dụng RAG cục bộ bằng các công cụ như Ollama, Python và ChromaDB, bạn có thể tận hưởng lợi ích của các mô hình ngôn ngữ nâng cao trong khi vẫn duy trì quyền kiểm soát dữ liệu và các tùy chọn tùy chỉnh của mình.

ứng dụng RAG


GPU

Việc chạy các mô hình ngôn ngữ lớn (LLM) giống như các mô hình được sử dụng trong Thế hệ tăng cường truy xuất (RAG) đòi hỏi sức mạnh tính toán đáng kể. Một trong những thành phần chính cho phép xử lý và nhúng dữ liệu hiệu quả trong các mô hình này là Bộ xử lý đồ họa (GPU). Đây là lý do tại sao GPU lại cần thiết cho nhiệm vụ này và cách chúng tác động đến hiệu suất thiết lập LLM cục bộ của bạn:

GPU là gì?

GPU là bộ xử lý chuyên dụng được thiết kế để tăng tốc độ hiển thị hình ảnh và video. Không giống như Bộ xử lý trung tâm (CPU), được tối ưu hóa cho các tác vụ xử lý tuần tự, GPU vượt trội ở khả năng xử lý song song. Điều này làm cho chúng đặc biệt phù hợp với các tính toán toán học phức tạp được yêu cầu bởi các mô hình học máy và học sâu.

Tại sao GPU lại quan trọng đối với LLM

  • Sức mạnh xử lý song song: GPU có thể xử lý đồng thời hàng nghìn thao tác, tăng tốc đáng kể các tác vụ như đào tạo và suy luận trong LLM. Tính song song này rất quan trọng đối với khối lượng tính toán lớn liên quan đến việc xử lý các tập dữ liệu lớn và tạo ra phản hồi trong thời gian thực.
  • Hiệu quả trong việc xử lý các mô hình lớn: LLM giống như những LLM được sử dụng trong RAG yêu cầu bộ nhớ và tài nguyên tính toán đáng kể. GPU được trang bị bộ nhớ băng thông cao (HBM) và nhiều lõi, giúp chúng có khả năng quản lý các phép nhân ma trận quy mô lớn và các phép toán tensor cần thiết cho các mô hình này.
  • Nhúng và truy xuất dữ liệu nhanh hơn: Trong thiết lập RAG cục bộ, việc nhúng dữ liệu vào kho lưu trữ vectơ như ChromaDB và truy xuất nhanh các tài liệu liên quan là điều cần thiết để đạt hiệu suất. GPU hiệu suất cao có thể tăng tốc các quá trình này, đảm bảo chatbot của bạn phản hồi kịp thời và chính xác.
  • Cải thiện thời gian đào tạo: Đào tạo LLM liên quan đến việc điều chỉnh hàng triệu (hoặc thậm chí hàng tỷ) tham số. GPU có thể giảm đáng kể thời gian cần thiết cho giai đoạn đào tạo này so với CPU, cho phép cập nhật và cải tiến mô hình của bạn thường xuyên hơn.

Chọn GPU phù hợp

Khi thiết lập LLM cục bộ, việc lựa chọn GPU có thể ảnh hưởng đáng kể đến hiệu suất. Dưới đây là một số yếu tố cần xem xét:

  • Dung lượng bộ nhớ: Các model lớn hơn yêu cầu nhiều bộ nhớ GPU hơn. Hãy tìm GPU có VRAM (RAM video) cao hơn để chứa các bộ dữ liệu và thông số mô hình mở rộng.
  • Khả năng tính toán: GPU càng có nhiều lõi CUDA thì càng có thể xử lý các tác vụ xử lý song song tốt hơn. GPU có khả năng tính toán cao hơn sẽ hiệu quả hơn cho các tác vụ deep learning.
  • Băng thông: Băng thông bộ nhớ cao hơn cho phép truyền dữ liệu nhanh hơn giữa GPU và bộ nhớ của nó, cải thiện tốc độ xử lý tổng thể.

Ví dụ về GPU hiệu suất cao cho LLM

  • NVIDIA RTX 3090: Được biết đến với VRAM cao (24 GB) và lõi CUDA mạnh mẽ, đây là lựa chọn phổ biến cho các tác vụ deep learning.
  • NVIDIA A100: Được thiết kế dành riêng cho AI và máy học, nó mang lại hiệu năng vượt trội với dung lượng bộ nhớ lớn và sức mạnh tính toán cao.
  • AMD Radeon Pro VII: Một đối thủ nặng ký khác với băng thông bộ nhớ cao và khả năng xử lý hiệu quả.

Đầu tư vào GPU hiệu suất cao là rất quan trọng để chạy các mô hình LLM cục bộ. Nó đảm bảo xử lý dữ liệu nhanh hơn, đào tạo mô hình hiệu quả và tạo phản hồi nhanh, giúp ứng dụng RAG cục bộ của bạn trở nên mạnh mẽ và đáng tin cậy hơn. Bằng cách tận dụng sức mạnh của GPU, bạn hoàn toàn có thể nhận ra lợi ích của việc lưu trữ chatbot tùy chỉnh của riêng mình, phù hợp với nhu cầu cụ thể và yêu cầu về quyền riêng tư dữ liệu của bạn.


Điều kiện tiên quyết

Trước khi đi sâu vào thiết lập, hãy đảm bảo bạn có sẵn các điều kiện tiên quyết sau:

  • Python 3: Python là ngôn ngữ lập trình linh hoạt mà bạn sẽ sử dụng để viết mã cho ứng dụng RAG của mình.
  • ChromaDB: Cơ sở dữ liệu vectơ sẽ lưu trữ và quản lý phần nhúng dữ liệu của chúng tôi.
  • Ollama: Để tải xuống và phân phối LLM tùy chỉnh trong máy cục bộ của chúng tôi.

Bước 1: Cài đặt Python 3 và thiết lập môi trường của bạn

Để cài đặt và thiết lập môi trường Python 3 của chúng tôi, hãy làm theo các bước sau: Tải xuống và thiết lập Python 3 trên máy của bạn. Sau đó, hãy đảm bảo Python 3 của bạn đã được cài đặt và chạy thành công:

 $ python3 --version # Python 3.11.7

Tạo một thư mục cho dự án của bạn, ví dụ: local-rag :

 $ mkdir local-rag $ cd local-rag

Tạo một môi trường ảo có tên venv :

 $ python3 -m venv venv

Kích hoạt môi trường ảo:

 $ source venv/bin/activate # Windows # venv\Scripts\activate

Bước 2: Cài đặt ChromaDB và các phần phụ thuộc khác

Cài đặt ChromaDB bằng pip:

 $ pip install --q chromadb

Cài đặt các công cụ Langchain để hoạt động liền mạch với mô hình của bạn:

 $ pip install --q unstructured langchain langchain-text-splitters $ pip install --q "unstructured[all-docs]"

Cài đặt Flask để phân phát ứng dụng của bạn dưới dạng dịch vụ HTTP:

 $ pip install --q flask

Bước 3: Cài đặt Ollama

Để cài đặt Ollama, hãy làm theo các bước sau: Đi tới trang tải xuống Ollama và tải xuống trình cài đặt cho hệ điều hành của bạn. Xác minh cài đặt Ollama của bạn bằng cách chạy:

 $ ollama --version # ollama version is 0.1.47

Kéo mô hình LLM bạn cần. Ví dụ: để sử dụng mô hình Mistral:

 $ ollama pull mistral

Kéo mô hình nhúng văn bản. Ví dụ: để sử dụng mô hình Văn bản nhúng Nomic:

 $ ollama pull nomic-embed-text

Sau đó chạy mô hình Ollama của bạn:

 $ ollama serve

Xây dựng ứng dụng RAG

Bây giờ bạn đã thiết lập môi trường của mình bằng Python, Ollama, ChromaDB và các phần phụ thuộc khác, đã đến lúc xây dựng ứng dụng RAG cục bộ tùy chỉnh của bạn. Trong phần này, chúng ta sẽ tìm hiểu mã Python thực hành và cung cấp cái nhìn tổng quan về cách cấu trúc ứng dụng của bạn.

app.py

Đây là tệp ứng dụng Flask chính. Nó xác định các tuyến để nhúng tệp vào cơ sở dữ liệu vectơ và truy xuất phản hồi từ mô hình.

 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

Mô-đun này xử lý quá trình nhúng, bao gồm lưu các tệp đã tải lên, tải và chia tách dữ liệu cũng như thêm tài liệu vào cơ sở dữ liệu vectơ.

 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

Mô-đun này xử lý các truy vấn của người dùng bằng cách tạo ra nhiều phiên bản của truy vấn, truy xuất các tài liệu liên quan và cung cấp câu trả lời dựa trên ngữ cảnh.

 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

Mô-đun này khởi tạo và trả về phiên bản cơ sở dữ liệu vectơ được sử dụng để lưu trữ và truy xuất các phần nhúng tài liệu.

 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

Chạy ứng dụng của bạn!

Tạo tệp .env để lưu trữ các biến môi trường của bạn:

 TEMP_FOLDER = './_temp' CHROMA_PATH = 'chroma' COLLECTION_NAME = 'local-rag' LLM_MODEL = 'mistral' TEXT_EMBEDDING_MODEL = 'nomic-embed-text'

Chạy tệp app.py để khởi động máy chủ ứng dụng của bạn:

 $ python3 app.py

Khi máy chủ đang chạy, bạn có thể bắt đầu thực hiện yêu cầu tới các điểm cuối sau:

  • Lệnh ví dụ để nhúng tệp PDF (ví dụ: sơ yếu lý lịch.pdf):
 $ 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" }
  • Lệnh ví dụ để đặt câu hỏi cho mô hình của bạn:
 $ 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." }

Phần kết luận

Bằng cách làm theo các hướng dẫn này, bạn có thể chạy và tương tác một cách hiệu quả với ứng dụng RAG cục bộ tùy chỉnh của mình bằng Python, Ollama và ChromaDB, phù hợp với nhu cầu của bạn. Điều chỉnh và mở rộng chức năng khi cần thiết để nâng cao khả năng của ứng dụng của bạn.

Bằng cách khai thác khả năng triển khai cục bộ, bạn không chỉ bảo vệ thông tin nhạy cảm mà còn tối ưu hóa hiệu suất và khả năng phản hồi. Cho dù bạn đang tăng cường tương tác với khách hàng hay hợp lý hóa các quy trình nội bộ, ứng dụng RAG được triển khai cục bộ sẽ mang lại sự linh hoạt và mạnh mẽ để thích ứng và phát triển theo yêu cầu của bạn.

Kiểm tra mã nguồn trong repo này:

https://github.com/firstpersoncode/local-rag


Chúc mừng mã hóa!