Базовый RAG за 15 минут
1. Введение
RAG - это метод, который позволяет LLM использовать релевантную информацию из внешних источнков в своих ответах. В этом гайде мы создадим полный RAG пайплайн, используя актуальную информацию о недавно вышедших фильмах/сериалах.
Наш гайд будет включать следующие шаги:
- Загрузка статей и нарезка на chunks
- Создание embeddings и загрузка в векторную БД
- Реализация базового семантического поиска
- Подключение LLM модели
- Проверка отсутствия информации у LLM
- Общение с LLM по информации из внешних источников
2. Подготовка окружения
Установим и импортируем необходимые библиотеки:
#!pip install langchain
#!pip install langchain-compressa
#!pip install langchain_community
#!pip install requests
#!pip install beautifulsoup4
#!pip install faiss-cpu - если вы з апускаете на CPU
#!pip install faiss-gpu - если вы запускаете на GPU с поддержкой CUDA
import os
import requests
from bs4 import BeautifulSoup
from langchain_compressa import CompressaEmbeddings, ChatCompressa
from langchain_core.documents import Document
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_core.prompts import ChatPromptTemplate
from langchain.chains import create_retrieval_chain
from langchain_community.vectorstores import FAISS
from langchain.chains.combine_documents import create_stuff_documents_chain
Для ячейки ниже вам понадобится API ключ Compressa. Вы можете получить его после регистрации.
os.environ["COMPRESSA_API_KEY"] = "ваш ключ"
# Если вы запускаете локально на Macbook, укажите также следующие переменные в окружении
# os.environ["TOKENIZERS_PARALLELISM"] = "false"
# os.environ["KMP_DUPLICATE_LIB_OK"] = "TRUE"
3. Загрузка веб-страниц и нарезка на chunks
Загрузим информацию о свежих фильмах и сериалах с Wikipedia, а затем нарежем их на chunks (отрывки из статей)
# Для нашего примера возьмем сериал Сёгун и фильм Мастер и Маргарита
urls = [
"https://ru.wikipedia.org/wiki/Мастер_и_Маргарита_(фильм,_2024)",
"https://ru.wikipedia.org/wiki/Сёгун_(телесериал,_2024)"
]
def fetch_wikipedia_content(url):
# Отправляем GET-запрос к указанному URL
response = requests.get(url)
# Создаем объект BeautifulSoup для парсинга HTML-контента
soup = BeautifulSoup(response.content, 'html.parser')
# Находим основной контейнер с содержимым статьи
content = soup.find(id="mw-content-text").find(class_="mw-parser-output")
text = []
# Итерируемся по всем элементам 'p', 'h2' и 'h3' в основном контенте
for element in content.find_all(['p', 'h2', 'h3']):
if element.name == 'p':
# Если это параграф, добавляем его текст как есть
text.append(element.text)
elif element.name in ['h2', 'h3']:
# Если это заголовок, форматируем его с ## и добавляем перенос строки
text.append(f"\n## {element.text.strip()}\n")
# Объединяем все элементы текста в одну строку, разделяя их переносами строк
return '\n'.join(text)
documents = [Document(page_content=fetch_wikipedia_content(url)) for url in urls]
#Проверим, что все загрузилось корректно
print (documents)
# Разбиваем документы на чанки, конкретные настройки приведены для примера
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=500, chunk_overlap=100, add_start_index=True
)
chunks = text_splitter.split_documents(documents)
print(f"Всего создано чанков: {len(chunks)}")
print(f"Пример чанка:\n{chunks[0].page_content[:1000]}...")
4. Создание эмбеддингов
Превращаем полученнные куски текстов в embeddings и загружаем в векторную БД для дальнейшего поиска по ней. Для примера будем использовать Faiss, но можно взять и любую другую векторную БД на выбор (например, ChromaDB или Qdrant)
embeddings = CompressaEmbeddings(api_key=os.getenv("COMPRESSA_API_KEY"), base_url="https://compressa-api.mil-team.ru/v1")
# Создаем и заполняем векторное хранилище
vectorstore = FAISS.from_documents(chunks, embeddings)
print("Векторное хранилище успешно создано")