Создайте своего собственного чат-бота с искусственным интеллектом, созданного специально для успеха вашей компании!
Хотите создать персонализированного чат-бота для нужд вашей компании? В этом исследовании мы погрузимся в мир чат-бота Llama — нового претендента в динамической области диалогового искусственного интеллекта. Наше путешествие будет охватывать различные аспекты, включая настройку пакетов, настройку моделей и многое другое!
Подготовка почвы: основные пакеты
Прежде чем углубляться в код, важно убедиться, что у нас установлены все необходимые пакеты. Это обеспечивает плавное движение по мере продвижения вперед:
!pip install pyngrok transformers flask-ngrok huggingface_hub requests beautifulsoup4 nltk scikit-learn sentence-transformers faiss-cpu numpy==1.23.3 flasgger !pip install tensorflow --no-deps !pip install numba --no-deps !CMAKE_ARGS="-DLLAMA_CUBLAS=on" FORCE_CMAKE=1 pip install llama-cpp-python --force-reinstall --upgrade --no-cache-dir --verbose
Модельный путь: указание на ламу
После того, как наша среда подготовлена, нам нужно указать, какую модель мы собираемся использовать:
model_name_or_path = "TheBloke/Llama-2-13B-chat-GGML" model_basename = "llama-2-13b-chat.ggmlv3.q5_1.bin"
Библиотеки в изобилии: импорт наших инструментов
С предварительными этапами покончено, пришло время приступить к делу — нашим библиотекам:
from huggingface_hub import hf_hub_download from llama_cpp import Llama from transformers import AutoTokenizer, AutoModelForCausalLM from flask import Flask, request, jsonify, render_template_string, send_from_directory from flasgger import Swagger, swag_from from pyngrok import ngrok from flask_ngrok import run_with_ngrok import torch, requests, re import numpy as np from bs4 import BeautifulSoup import nltk, faiss from nltk.tokenize import sent_tokenize from google.colab import drive from sentence_transformers import SentenceTransformer nltk.download('punkt') drive.mount('/content/drive')
Получение модели: захват ламы
Когда наша среда настроена, пришло время получить модель ламы:
model_path = hf_hub_download(repo_id=model_name_or_path, filename=model_basename)
Инициализация графического процессора: Лама обретает свою мощь
Истинный потенциал чат-бота Llama раскрывается, когда мы используем ускорение графического процессора:
lcpp_llm = None lcpp_llm = Llama( model_path=model_path, n_threads=2, n_batch=512, n_gpu_layers=32 )
Создание пользовательского интерфейса: чат для взаимодействия
Одной из отличительных черт привлекательного чат-бота является его пользовательский интерфейс. Вот как устроен интерфейс нашего чат-бота Llama:
html_code = """ <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Chat Box</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; font-family: "Nunito", sans-serif; } html, body { background: linear-gradient(120deg, #17bebb, #f0a6ca); overflow: hidden; } .container { display: flex; justify-content: center; align-items: center; flex-direction: column; height: 100vh; width: 100vw; } .container h1 { margin: 0.5em auto; color: #FFF; text-align: center; } .chatbox { background: rgba(255, 255, 255, 0.05); width: 600px; height: 75%; border-radius: 0.2em; position: relative; box-shadow: 1px 1px 12px rgba(0, 0, 0, 0.1); } .chatbox__messages__user-message.user .chatbox__messages__user-message--ind-message { float: right; } .chatbox__messages:nth-of-type(odd) .chatbox__messages__user-message--ind-message:after { content: ""; position: absolute; margin: -1.5em -17.06em; width: 0; height: 0; border-top: 10px solid transparent; border-bottom: 10px solid transparent; border-right: 10px solid rgba(255, 255, 255, 0.2); } .chatbox__messages__user-message.ai .chatbox__messages__user-message--ind-message{ float: left; } .chatbox__messages:nth-of-type(even) .chatbox__messages__user-message--ind-message:after { content: ""; position: absolute; margin: -1.5em 1.87em; width: 0; height: 0; border-top: 10px solid transparent; border-bottom: 10px solid transparent; border-left: 10px solid rgba(255, 255, 255, 0.2); } .chatbox__messages__user-message { width: 450px; } .chatbox__messages__user-message--ind-message { background: rgba(255, 255, 255, 0.2); padding: 1em 0; height: auto; width: 65%; border-radius: 5px; margin: 2em 1em; overflow: auto; } .chatbox__messages__user-message--ind-message > p.name { color: #FFF; font-size: 1em; } .chatbox__messages__user-message--ind-message > p.message { color: #FFF; font-size: 0.7em; margin: 0 2.8em; } .chatbox__user-list { background: rgba(255, 255, 255, 0.1); width: 25%; height: 100%; float: right; border-top-right-radius: 0.2em; border-bottom-right-radius: 0.2em; } .chatbox__user-list h1 { background: rgba(255, 255, 255, 0.05); color: rgba(255, 255, 255, 0.9); font-size: 0.9em; padding: 1em; margin: 0; font-weight: 300; text-align: center; } .chatbox__user, .chatbox__user--away, .chatbox__user--busy, .chatbox__user--active { width: 0.5em; height: 0.5em; border-radius: 100%; margin: 1em 0.7em; } .chatbox__user--active { background: rgba(23, 190, 187, 0.8); } .chatbox__user--busy { background: rgba(252, 100, 113, 0.8); } .chatbox__user--away { background: rgba(255, 253, 130, 0.8); } .chatbox p { float: left; text-align: left; margin: -0.25em 2em; font-size: 0.7em; font-weight: 300; color: #FFF; width: 200px; } .chatbox form { background: #222; } .chatbox form input { background: rgba(255, 255, 255, 0.03); position: absolute; bottom: 0; left: 0; border: none; width: 75%; padding: 1.2em; outline: none; color: rgba(255, 255, 255, 0.9); font-weight: 300; } ::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.9); } :-moz-placeholder { color: rgba(255, 255, 255, 0.9); } ::-moz-placeholder { color: rgba(255, 255, 255, 0.9); } :-ms-input-placeholder { color: rgba(255, 255, 255, 0.9); } .chatbox__send-form { display: flex; align-items: center; margin-top: 1em; padding: 0 1em; } .chatbox__send-form input { flex: 1; } .chatbox__send-form button { background-color: rgba(255, 255, 255, 0.2); border: none; padding: 0.5em 1em; color: #fff; font-weight: bold; border-radius: 5px; cursor: pointer; transition: background-color 0.3s; position: absolute; bottom: 0; right: 0; height: 45px; } .chatbox__send-form button:hover { background-color: rgba(255, 255, 255, 0.4); } </style> <div class='container' ng-cloak ng-app="chatApp"> <img src="/content/logo.png" alt="Your Company Logo" style="max-width: 100%; height: auto;"> <div class='chatbox' ng-controller="MessageCtrl as chatMessage"> <form ng-submit="sendMessage()" class="chatbox__send-form"> <input type="text" ng-model="userMessage" placeholder="Enter your message" ng-keyup="$event.keyCode === 13 && sendMessage()"> <button type="submit">Send</button> </form> <div class="chatbox__messages__user-message-container" id="message-container"> <div class="chatbox__messages__user-message [[message.Class]]" ng-repeat="message in messages"> <div class="chatbox__messages__user-message--ind-message"> <p class="name">[[message.Name]]</p> <p class="message">[[message.Message]]</p> </div> </div> </div> </div> </div> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.14/angular.min.js"></script> <script> (function() { var app = angular.module('chatApp', []).config(function($interpolateProvider) { $interpolateProvider.startSymbol('[['); $interpolateProvider.endSymbol(']]'); }); app.controller('MessageCtrl', function($scope, $http) { $scope.messages = []; $scope.sendMessage = function() { var userMessage = $scope.userMessage; if (userMessage) { $scope.messages.push({ Class: 'user', Name: 'You', Message: userMessage }); $http.post('/generate', { text: userMessage }) .then(function(response) { var assistantMessage = response.data.generated_text; $scope.messages.push({ Class: 'ai', Name: 'AI Assistant', Message: assistantMessage }); }) .catch(function(error) { console.error(error); }); $scope.userMessage = ''; // Clear the input } }; }); })(); </script> </body> </html> """ with open("chat.html", "w") as f: f.write(html_code)
Особенности:
- Интерфейс структурирован с использованием HTML и CSS, с градиентным фоном и центрированным окном чата.
- Сообщения от пользователя и ИИ-помощника отображаются в разных стилях, что позволяет легко их различать.
- AngularJS используется для обработки динамических элементов чата, таких как отображение сообщений и управление взаимодействиями.
- Когда пользователь отправляет сообщение, запрос POST получает ответ ИИ, который затем отображается в окне чата.
Извлечение данных: получение информации с веб-страниц
Универсальный чат-бот может извлекать и предоставлять информацию с веб-страниц. Вот функция, которая это делает:
def get_data_from_url(urls): data = [] for url in urls: response = requests.get(url) if response.status_code == 200: soup = BeautifulSoup(response.content, 'html.parser') tags = ['p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'span'] data.append(' '.join([element.text for tag in tags for element in soup.find_all(tag)])) return data if data else None # Example usage urls = ["https://yourcompany.ai/about", "https://yourcompany.ai/integrations/", ...] # Sample URLs data = get_data_from_url(urls)
Подробнее:
- Функция
get_data_from_url
принимает список URL-адресов и извлекает текстовое содержимое с этих страниц. - Он использует библиотеку
requests
для выполнения HTTP-запросов иBeautifulSoup
для анализа HTML. - Функция ищет определенные теги, такие как абзацы (
p
) и заголовки (h1
,h2
и т. д.), чтобы извлечь текст. - В качестве примера предоставляется список URL-адресов и вызывается функция для получения их содержимого.
Обработка текста: сегментация большого текста
Работа с большими фрагментами текста может оказаться сложной задачей, особенно при попытке сгенерировать ответы или найти совпадения. Таким образом, очень важно разбить текст на удобные куски:
def chunk_text(text, max_length): text = text.replace("\t", "\n") text = re.sub('\n+', '\n', text) chunks = [] sentences = sent_tokenize(text) current_chunk = [] current_length = 0 for sentence in sentences: if current_length + len(sentence) <= max_length: current_chunk.append(sentence) current_length += len(sentence) else: chunks.append(' '.join(current_chunk)) current_chunk = [sentence] current_length = len(sentence) if current_chunk: chunks.append(' '.join(current_chunk)) return chunks
Основные выводы:
- Функция
chunk_text
принимает строку (text
) и максимальную длину (max_length
). - Используя регулярные выражения и токенизацию предложений, функция разбивает текст на более мелкие фрагменты, не разделяя предложения.
- Фрагменты гарантируют, что текст останется связным и значимым для дальнейшей обработки.
Семантический поиск: поиск релевантной информации
После извлечения и сегментации данных следующим шагом будет поиск соответствующей информации на основе запросов пользователей:
# Function to search for a query def search(query, index, all_chunks, urls, model): query_embedding = model.encode([query]) D, I = index.search(query_embedding, 1) # Search for the top 1 most similar embedding url_idx, chunk_idx, chunk = all_chunks[I[0][0]] url = urls[url_idx] return url, D[0][0], chunk model = SentenceTransformer('sentence-transformers/gtr-t5-base') # Load the desired model # Populate all_chunks with the tuple structure all_chunks = [] for url_idx, text in enumerate(data): for chunk_idx, chunk in enumerate(chunk_text(text, 1024)): all_chunks.append((url_idx, chunk_idx, chunk)) # Encode all chunks using the selected model all_embeddings = model.encode([chunk[2] for chunk in all_chunks]) # Create a Faiss index and add embeddings to it index = faiss.IndexIDMap(faiss.IndexFlatIP(model.get_sentence_embedding_dimension())) index.add_with_ids(all_embeddings, np.arange(len(all_embeddings)))
Подробнее:
- Функция
search
принимает запрос и возвращает наиболее релевантный фрагмент текста из предоставленных данных. - Модель SentenceTransformer используется для преобразования запроса и фрагментов данных во внедрения.
- FAISS, библиотека для поиска по сходству, затем используется для поиска фрагмента с наиболее близким к запросу встраиванием.
Запуск чат-бота: взаимодействие через Интернет
Сердцем чат-бота является приложение Flask, которое предоставляет пользователям веб-интерфейс:
app = Flask(__name__) ngrok.set_auth_token("YOUR TOKEN API") run_with_ngrok(app) # This will make the server accessible publicly @app.route('/generate', methods=['POST']) def generate(): text = request.json['text'] # print(text) url, similarity, chunk = search(text, index, all_chunks, urls, model) print(chunk) prompt_template=f'''You are an AI chatbot. Just answer the question, don't asume anything else: USER: From the following information Asnwer the folling: {chunk} Question: {text} ASSISTANT: ''' output = lcpp_llm(prompt=prompt_template, max_tokens=512, temperature=0.2, top_p=0.95, repeat_penalty=1.2, top_k=150, echo=True) text = output['choices'][0]['text'] assistant_reply = text.split("ASSISTANT:")[1].strip() print('done') return jsonify({"generated_text": assistant_reply}) @app.route('/') def home(): try: return render_template_string(open("chat.html").read()) except Exception as e: return f"An error occurred: {e}" @app.route('/content/<path:filename>') def serve_static(filename): try: return send_from_directory('/content/', filename) except Exception as e: return f"Failed to retrieve {filename}. Error: {e}" if __name__ == '__main__': app.run()
Особенности:
- Приложение Flask предоставляет конечную точку
/generate
, которая принимает вводимые пользователем данные и возвращает ответ чат-бота. - Получив запрос пользователя, приложение ищет соответствующую информацию, создает подсказку, а затем генерирует ответ, используя модель Llama.
Заключение
На протяжении всего этого исследования мы стали свидетелями тонкостей настройки чат-бота Llama, от первоначальной установки пакетов до грандиозного финала запуска интерактивного веб-интерфейса. Этот чат-бот использует возможности ускорения графического процессора, семантический поиск и широкий спектр инструментов и библиотек, чтобы предложить пользователям увлекательный и познавательный опыт.
Чат-бот Llama демонстрирует замечательные возможности в области искусственного интеллекта и обработки естественного языка. Это является свидетельством достижений в технологии чат-ботов и дает возможность заглянуть в будущее диалогового искусственного интеллекта.
Для разработчиков и энтузиастов эта реализация служит основой. Он предлагает план, который можно в дальнейшем совершенствовать, настраивать и расширять, что приведет к созданию в будущем еще более сложных и удобных для пользователя систем чат-ботов.
Спасибо, что присоединились ко мне в этом познавательном путешествии. До следующих встреч, продолжайте исследовать и внедрять инновации!