Направете своя личен AI с Langchain + LLaMA 2 +Flask
LLMs (Large Language Models) в момента са център на внимание в общността на AI. С появата на GPT-4 LLMs станаха толкова масови, че разработчиците тясно интегрират тези модели в няколко приложения. Въпреки че традиционните LLM са невероятни за повечето случаи на употреба, те са склонни да не успяват, когато искате да ги използвате готови с лични данни. Въпреки че можете да интегрирате вашите лични данни с GPT-4 чрез техните API, това не е най-добрата идея, тъй като не искате вашите чувствителни данни да се изпращат до сървъри на трети страни.
Решаване на проблема със сигурността
ЕДИНСТВЕНИЯТ начин, по който можете да сте сигурни, че вашите данни се обработват сигурно, е да използвате LLM с отворен код, които ви дават пълен контрол и гъвкавост.
Какви са предимствата?
- Разминете се с използването дори на модел с параметри 7B чрез подходящо бързо проектиране и фина настройка
- Използването на LLM с по-нисък параметър е изчислително по-бързо, а квантуването на модела го прави още по-ефективен, което води до по-ниски оперативни разходи
- Имате пълен контрол върху целия процес, така че данните остават на ВАШИТЕ сървъри
- Лесно персонализиран, за да отговори на вашите нарастващи изисквания поради природата с отворен код
Съдържание
- Създаване на прост интерфейс за чат отпред с 🐍 Flask
- Изтегляне на 🦙 LLM
- Съпоставяне и обработка на лични данни с 🦜🔗 Langchain
- 🦜🔗 Langchain Retrival QA обект за търсене по сходство на векторни бази данни
- Създаване на персонализиран шаблон за подкана
Стъпка 1: Създаване на прост интерфейс за чат отпред с 🐍 Flask
За нашия потребителски интерфейс ще използваме Flask, за да създадем просто уеб приложение. Ще има само една динамична страница, където ще взаимодействате с LLM. За да започнете, продължете напред и клонирайте това repo на github за целия код. Предлагам ви да използвате само кода за предния край и персонализирате всичко останало въз основа на вашите нужди!
Кодът е много прост, тъй като използваме само предния край за получаване на потребителската заявка и връщане на резултата. Ако искате да разберете повече за форматирането на отговора, вижте файла main.js в директорията static/.
# Main script from flask import Flask, render_template, request from utils import setup_dbqa app = Flask(__name__) @app.route("/") def index(): return render_template("index.html") @app.route("/get", methods=["GET", "POST"]) def chat(): msg = request.form["msg"] input = msg try: return get_chat_response(input) except ValueError: return "You have exceeded the token limit! Sorry for the inconvenience!" # Gets the response by passing the prompt to QA Object def get_chat_response(input): response = dbqa({"query": input}) return response["result"] if __name__ == "__main__": dbqa = setup_dbqa() #This is the RetreivalQA Object app.run(debug=True, port=2000)
Стъпка 2: Изтегляне на LLM
Изборът на LLM за този случай на използване ще бъде моделът за чат с параметри 7B на LLaMA-2. Това е добър избор за изводи върху обобщен набор от лични данни. Чувствайте се свободни да проучите други LLMs, които смятате, че биха подхождали по-добре на вашия случай на употреба.
Например „LLaMA“ фино настроени модели като „Vicuna“ е добър вариант, ако имате много задачи, базирани на инструкции, и „Koala“, ако имате задачи, базирани на диалог. Ако искате да научите повече за това кой LLM отговаря най-добре на вашите нужди, вижте този LLM индекс от Sapling.ai.
В този блог ще направим извод, базиран на процесора. За да направим това, ще използваме GGML формата на LLM, тъй като той значително увеличава изчислителната ефективност чрез използване на различни техники за оптимизация (основно квантуване).
Какво е GGML? Квантуване?
GGML е тензорна библиотека, написана на C++, която използва целочислено квантуване и други алгоритми за оптимизация като ADAM и L-BFGS, за да позволи LLM извод в среда, базирана на процесора.
Основната оптимизация се крие в квантуването, при което теглата на модела, които са числа с плаваща запетая, се компресират до 4-битови или 8-битови цели числа. Това намалява прецизността на теглата, което води до удар в производителността, но драстично подобрява ефективността, тъй като използването на RAM и диск е значително по-ниско. Ако искате да научите повече за квантуването, вижте тази страница.
Изтегляне на LLM във формат GGML
Можете да изтеглите LLM по ваш избор от тук. За този блог ще използвам основната версия LLaMA-7B-Chat. Ако LLM, който искате да използвате, все още не присъства във формат GGML на huggingface, винаги можете да го преобразувате в GGML локално, като следвате това видео и това repo на github.
Използване на LLM в python с 🦜🔗 Langchain
За да използваме LLM с Python, трябва да използваме свързвания на Python, които ви позволяват да предавате данни или да извиквате функции между Python и C++ в този случай. За да направим това, ще използваме библиотеката CTransformers от Langchain.
#======= llm.py =========== from langchain.llms import CTransformers # Local CTransformers wrapper for Llama-2-7B-Chat llm = CTransformers( model="/Users/deveshparagiri/Downloads/models/sage-v2-q8_0.bin", model_type="llama", # Model type Llama config={"max_new_tokens": 256, "temperature": 0.5}, )
Стъпка 3: Съпоставяне и обработка на лични данни с 🦜🔗 Langchain
Сега, след като LLM е изтеглен, следващата стъпка е да създадем нашата векторна база данни с нашите лични документи. Създайте директория с данни/ в папката на вашия проект и качете всичките си лични документи там. Първо, документите трябва да се заредят и след това да се разделят на правилни части, преди да се създадат векторни вграждания въз основа на тях.
Нарязване
Разделянето на данните е от решаващо значение за извършване на добро търсене на семантично сходство. Най-елементарният начин за групиране би бил просто разделянето на текста на базата на фиксирана дължина (Чънкиране с фиксиран размер). Това обаче не е най-добрият начин да го направим, тъй като трябва да разделяме, като същевременно поддържаме подобие на контекста. Един от начините да направите това е рекурсивно разделяне на парчета, където парчетата са с подобен размер, като същевременно се запазва контекстът. За да научите повече за тънкостите на групирането и неговото въздействие върху изводите, щракнете тук.
Векторна база данни и вграждания
След като бъдат разделени на парчета, те се преобразуват във векторни вграждания с помощта на нашия модел all-MiniLM-L6-v2 и се съхраняват в Milvus, векторна база данни. Ако засега не искате да изберете традиционна векторна база данни, можете също да използвате обвивката FAISS в Langchain, за да индексирате и съхранявате локално вгражданията. За да настроите milvus, уверете се, че сте pip install pymilvus
и
Кодът по-долу се изпълнява само веднъж, за да се създаде векторна база данни, която ще се използва като справка от нашия LLM, за да отговори на нашите запитвания.
#========= db_build.py =========== from langchain.vectorstores import Milvus from langchain.text_splitter import RecursiveCharacterTextSplitter from langchain.document_loaders import PyPDFLoader, DirectoryLoader, Docx2txtLoader, CSVLoader from langchain.embeddings import HuggingFaceEmbeddings from dbconfig import CONNECTION_HOST, CONNECTION_PORT, COLLECTION_NAME # Embedding model loading embeddings = HuggingFaceEmbeddings( model_name="sentence-transformers/all-MiniLM-L6-v2", model_kwargs={"device": "cpu"} ) # Recursive text splitting text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50) def load_data(directory): """This function loads and splits the files Parameters: `directory (str): Path where data is located` Returns: List: Returns a list of processed Langchain Document objects """ # Inititating all loaders pdf_loader = DirectoryLoader(directory, glob="*.pdf", loader_cls=PyPDFLoader) docx_loader = DirectoryLoader(directory, glob="*.docx", loader_cls=Docx2txtLoader) spotify_loader = CSVLoader(file_path=f"{directory}spotify.csv") insta_following_loader = CSVLoader(file_path=f"{directory}insta_following.csv") insta_followers_loader = CSVLoader(file_path=f"{directory}insta_followers.csv") # Loading all documents pdf_documents = pdf_loader.load() docx_documents = docx_loader.load() spotify_documents = spotify_loader.load() insta_following_documents = insta_following_loader.load() insta_followers_documents = insta_followers_loader.load() # Adding all loaded documents to one single list of Documents corpus = pdf_documents corpus.extend(docx_documents) corpus.extend(spotify_documents) corpus.extend(insta_following_documents) corpus.extend(insta_followers_documents) corpus.extend(spotify_documents) # Resetting metadata for all type of documents to make it compatible for vector DB for document in corpus: document.metadata = {"source": document.metadata["source"]} # Splitting all documents corpus_processed = text_splitter.split_documents(corpus) return corpus_processed def vectordb_store(corpus_processed): """This function takes in the split documents, creates vector embeddings, indexes and stores them in Milvus. Parameters: corpus_processed (List): List of Langchain Document objects Returns: Milvus Vector DB Object """ vector_db = Milvus.from_documents( corpus_processed, embedding=embeddings, connection_args={"host": "127.0.0.1", "port": "19530"}, collection_name=COLLECTION_NAME, ) return vector_db if __name__ == "__main__": vectordb_store(load_data("data/"))
Стъпка 4: 🦜🔗 Langchain Retrival QA обект за търсене на сходство във векторна база данни
Нашата векторна база данни е създадена въз основа на нашите лични документи. Сега трябва да можем да търсим в тази векторна база данни въз основа на нашата заявка към LLM, да намерим най-подходящите данни и да ги изпратим обратно на нашия LLM за извод. За да разберете по-добре целия работен процес, вижте архитектурата на целия процес по-долу.
За да активираме търсенето във vectorDB, ще създадем обект RetreivalQA в Langchain. Ние основно предаваме обекта LLM, източника на vectorDB и подканата (потребителска заявка) към този обект и той връща най-близкия резултат от търсенето. В моя случай връщам само най-подходящото търсене, но можете да получите най-добрите K подходящи търсения, като промените параметъра search_kwargs.
#======= utils.py ============ from langchain.chains import RetrievalQA from langchain.embeddings import HuggingFaceEmbeddings from langchain.vectorstores import Milvus from llm import llm from pymilvus import connections def build_retrieval_qa(llm, prompt, vectordb): """This function builds the RetreivalQA object` Parameters: llm (Object): The llm object prompt (Object): The prompt template vectordb (Object): The vector store Returns: RetreivalQA Object: Returns the best result """ # Only retreiving the first best result dbqa = RetrievalQA.from_chain_type( llm=llm, chain_type="stuff", retriever=vectordb.as_retriever(search_kwargs={"k": 1}), return_source_documents=True, chain_type_kwargs={"prompt": prompt}, ) return dbqa def setup_dbqa(): """This function instantiates the RetreivalQA object Parameters: llm (Object): The llm object prompt (Object): The prompt template vectordb (Object): The vector store Returns: RetreivalQA Object: Returns created object """ embeddings = HuggingFaceEmbeddings( model_name="sentence-transformers/all-MiniLM-L6-v2", model_kwargs={"device": "cpu"}, ) connections.connect("default", host="localhost", port="19530") vector_db: Milvus = Milvus( embedding_function=embeddings, connection_args={"host": "127.0.0.1", "port": "19530"}, collection_name="mystore", ) qa_prompt = set_qa_prompt() dbqa = build_retrieval_qa(llm, qa_prompt, vector_db) return dbqa
Стъпка 5: Създаване на персонализиран шаблон за подкана
Персонализираният шаблон за подкана е много полезен, като дава представа какъв тип подкана ще получите от потребителя и начина, по който вашият модел трябва да отговори. Например използвах този шаблон за подкана по-долу, но вие можете да създадете свой собствен въз основа на вашите изисквания.
# ================================================================================ # Creating the template based on which the model will reply # ================================================================================ from langchain import PromptTemplate qa_template = """ You are Dev's personal A.I assistant named S.A.G.E. You are a helpful and honest assistant who has access to my personal information. Please ensure that your responses are socially unbiased and positive in nature. Censor any explicit content. If a question does not make any sense, or is not factually coherent, explain why instead of answering something not correct. If you don't know the answer to a question, please don't share false information. Only answer based on what is presented. Use the following context to answer the user's question. Context: {context} Question: {question} Only return the answer and nothing else. Answer: """ def set_qa_prompt(): """This function wraps the prompt template in a PromptTemplate object Parameters: Returns: PromptTemplate Object: Returns the prompt template object """ prompt = PromptTemplate( template=qa_template, input_variables=["context", "question"] ) return prompt
Това е само най-основният пример за шаблон за подкана. Наистина можете да използвате „бързото инженерство“, за да проектирате курирани отговори. Например, можете да използвате шаблон Few Shot Prompt. Това е начин за обучение на модела върху конкретни изходни данни чрез предоставяне на няколко примера.
from langchain import FewShotPromptTemplate # create our examples examples = [ { "query": "How are you?", "answer": "I can't complain but sometimes I still do." }, { "query": "What time is it?", "answer": "It's time to get a watch." } ] # create a example template example_template = """ User: {query} AI: {answer} """ # create a prompt example from above template example_prompt = PromptTemplate( input_variables=["query", "answer"], template=example_template ) # now break our previous prompt into a prefix and suffix # the prefix is our instructions prefix = """The following are exerpts from conversations with an AI assistant. The assistant is typically sarcastic and witty, producing creative and funny responses to the users questions. Here are some examples: """ # and the suffix our user input and output indicator suffix = """ User: {query} AI: """ # now create the few shot prompt template few_shot_prompt_template = FewShotPromptTemplate( examples=examples, example_prompt=example_prompt, prefix=prefix, suffix=suffix, input_variables=["query"], example_separator="\n\n" )
За по-стриктно обучение на конкретни данни трябва да настроите фино модела на вашите лични данни. Това може да се направи с T4 GPU с един екземпляр в Google Colab (ще отнеме известно време в зависимост от размера на набора от данни), при условие че използвате PEFT (Parameter Efficient Fine Tuning) техники като QLoRA. За кода за фина настройка вижте моя бележник на Google Colab тук. Разгледайте този ресурс, ако искате да научите повече за QLoRA.
Това е всичко за създаване на ваш собствен персонализиран и сигурен AI асистент. Щракнете тук, за да изтеглите целия код на проекта.
На обикновен английски
Благодарим ви, че сте част от нашата общност! Преди да тръгнете:
- Не пропускайте да ръкопляскате и следвайте писателя! 👏
- Можете да намерите още повече съдържание в PlainEnglish.io 🚀
- Регистрирайте се за нашия безплатен седмичен бюлетин. 🗞️
- Следвайте ни в Twitter (X), LinkedIn, YouTube и Раздори.