Построение системы генерации с поддержкой извлечения (RAG) с использованием FAISS и открытых языковых моделей
Система генерации с поддержкой извлечения (RAG) представляет собой мощный подход, который сочетает в себе креативные возможности больших языковых моделей (LLMs) с фактической точностью систем извлечения. Это решение помогает преодолеть одну из основных проблем LLM — галлюцинацию.
Практические бизнес-решения
В этом руководстве мы создадим полную систему RAG, используя:
- FAISS (Facebook AI Similarity Search) в качестве векторной базы данных
- Sentence Transformers для создания высококачественных эмбеддингов
- Открытую языковую модель от Hugging Face (мы используем легкую модель, совместимую с CPU)
- Пользовательскую базу знаний, которую мы создадим
К концу этого руководства у вас будет работающая система RAG, способная отвечать на вопросы на основе ваших документов с улучшенной точностью и актуальностью. Этот подход полезен для создания специализированных помощников, систем поддержки клиентов или любых приложений, где важно обосновывать ответы LLM конкретными документами.
Шаг 1: Настройка окружения
Сначала необходимо установить все необходимые библиотеки. Для этого руководства мы будем использовать Google Colab.
# Установите необходимые пакеты !pip install -q transformers==4.34.0 !pip install -q sentence-transformers==2.2.2 !pip install -q faiss-cpu==1.7.4 !pip install -q accelerate==0.23.0 !pip install -q einops==0.7.0 !pip install -q langchain==0.0.312 !pip install -q langchain_community !pip install -q pypdf==3.15.1
Шаг 2: Создание базы знаний
Мы создадим простую базу знаний о концепциях ИИ. В реальных сценариях можно использовать для импорта PDF-документов, веб-страниц или баз данных.
import os
import tempfile
# Создаем временный каталог для наших документов
docs_dir = tempfile.mkdtemp()
print(f"Создан временный каталог по адресу: {docs_dir}")
# Создаем образцы документов о концепциях ИИ
documents = {
"vector_databases.txt": "Описание векторных баз данных...",
"embeddings.txt": "Описание эмбеддингов...",
"rag_systems.txt": "Описание систем RAG..."
}
# Записываем документы в файлы
for filename, content in documents.items():
with open(os.path.join(docs_dir, filename), 'w') as f:
f.write(content)
print(f"Создано {len(documents)} документов в {docs_dir}")
Шаг 3: Загрузка и обработка документов
Теперь загрузим эти документы и обработаем их для нашей системы RAG.
from langchain_community.document_loaders import TextLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
# Инициализируем список для хранения наших документов
all_documents = []
# Загружаем каждый текстовый файл
for filename in documents.keys():
file_path = os.path.join(docs_dir, filename)
loader = TextLoader(file_path)
loaded_docs = loader.load()
all_documents.extend(loaded_docs)
print(f"Загружено {len(all_documents)} документов")
# Разбиваем документы на части
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=500,
chunk_overlap=50,
separators=["nn", "n", ".", " ", ""]
)
document_chunks = text_splitter.split_documents(all_documents)
print(f"Создано {len(document_chunks)} частей документов")
Шаг 4: Создание эмбеддингов
Теперь преобразуем наши части документов в векторные эмбеддинги.
from sentence_transformers import SentenceTransformer
import numpy as np
# Инициализируем модель эмбеддингов
model_name = "sentence-transformers/all-MiniLM-L6-v2"
embedding_model = SentenceTransformer(model_name)
# Создаем эмбеддинги для всех частей документов
texts = [doc.page_content for doc in document_chunks]
embeddings = embedding_model.encode(texts)
print(f"Создано {len(embeddings)} эмбеддингов с формой {embeddings.shape}")
Шаг 5: Создание индекса FAISS
Теперь создадим наш индекс FAISS с этими эмбеддингами.
import faiss
# Получаем размерность наших эмбеддингов
dimension = embeddings.shape[1]
# Создаем индекс FAISS
index = faiss.IndexFlatL2(dimension)
# Добавляем наши векторы в индекс
index.add(embeddings.astype(np.float32))
print(f"Создан индекс FAISS с {index.ntotal} векторами")
Шаг 6: Загрузка языковой модели
Теперь загрузим открытую языковую модель от Hugging Face.
from transformers import AutoTokenizer, AutoModelForCausalLM
model_id = "TinyLlama/TinyLlama-1.1B-Chat-v1.0"
tokenizer = AutoTokenizer.from_pretrained(model_id)
model = AutoModelForCausalLM.from_pretrained(model_id, torch_dtype=torch.float32)
print(f"Успешно загружена модель {model_id}")
Шаг 7: Создание нашего RAG-пайплайна
Создадим функцию, которая объединяет извлечение и генерацию.
def rag_response(query, index, embedding_model, llm_model, llm_tokenizer, index_to_doc_map, top_k=3):
# Шаг 1: Преобразуем запрос в эмбеддинг
query_embedding = embedding_model.encode([query])
query_embedding = query_embedding.astype(np.float32)
# Шаг 2: Поиск похожих документов
distances, indices = index.search(query_embedding, top_k)
# Шаг 3: Извлечение фактических частей документов
retrieved_docs = [index_to_doc_map[idx] for idx in indices[0]]
# Создаем контекст из извлеченных документов
context = "nn".join([doc.page_content for doc in retrieved_docs])
# Шаг 4: Создаем запрос для LLM
prompt = f"""<|system|>
Вы полезный ИИ-помощник. Ответьте на вопрос, основываясь только на предоставленном контексте.
Если вы не знаете ответа на основе контекста, скажите "У меня недостаточно информации, чтобы ответить на этот вопрос."
Контекст:
{context}
<|user|>
{query}
<|assistant|>"""
# Шаг 5: Генерация ответа от LLM
input_ids = llm_tokenizer(prompt, return_tensors="pt").input_ids.to(model.device)
generation_config = {
"max_new_tokens": 256,
"temperature": 0.7,
"top_p": 0.95,
"do_sample": True
}
with torch.no_grad():
output = llm_model.generate(input_ids=input_ids, **generation_config)
generated_text = llm_tokenizer.decode(output[0], skip_special_tokens=True)
response = generated_text.split("<|assistant|>")[-1].strip()
return response
Шаг 8: Тестирование нашей системы RAG
Давайте протестируем нашу систему с несколькими вопросами.
test_questions = [
"Что такое FAISS и для чего он используется?",
"Как эмбеддинги захватывают семантическое значение?",
"Каковы преимущества систем RAG?"
]
for question in test_questions:
response = rag_response(query=question, index=index, embedding_model=embedding_model, llm_model=model, llm_tokenizer=tokenizer, index_to_doc_map=index_to_doc_chunk)
print(f"Вопрос: {question}\nОтвет: {response}\n")
Заключение
В этом руководстве мы построили полную систему RAG с использованием FAISS в качестве векторной базы данных и открытой языковой модели. Мы реализовали обработку документов, генерацию эмбеддингов и индексацию векторов, а также интегрировали эти компоненты с техниками расширения запросов для улучшения качества извлечения.
Рекомендуем рассмотреть возможность:
- Реализации повторной оценки запросов с использованием кросс-кодеров
- Создания веб-интерфейса с использованием Gradio или Streamlit
- Добавления возможностей фильтрации метаданных
Если вам нужна помощь в управлении ИИ в бизнесе, свяжитесь с нами по адресу hello@itinai.ru.






















