Создание системы RAG с использованием FAISS и открытых LLM для бизнеса


Построение системы генерации с поддержкой извлечения (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.



Новости в сфере искусственного интеллекта