Оцениваем ваше решение для ВЕТОШИ

Автор: Дмитрий Иванов [Команда P9X]

~8 минут чтения

Введение

Решения на основе RAG (Retrieval-Augmented Generation) повсюду. За последние несколько лет мы стали свидетелями их стремительного роста, поскольку организации используют RAG или гибридные RAG-решения в обслуживании клиентов, здравоохранении, разведке и других областях. Но как мы можем оценить эти решения? И какие методы мы можем использовать, чтобы определить сильные и слабые стороны наших моделей RAG?

В этой статье мы познакомимся с RAG, создав собственного чат-бота с использованием данных открытых исследований с помощью LangChain и других инструментов. Мы также воспользуемся DeepEval для оценки нашего RAG-конвейера как для поискового модуля, так и для генератора. Наконец, мы обсудим методы тестирования решений RAG с участием людей.

Retrieval-Augmented Generation

С появлением больших языковых моделей (LLM) возникло много критических замечаний, когда эти «базовые» предварительно обученные модели давали неверные ответы, несмотря на обучение на огромных наборах данных. Вместе с этим появилась технология Retrieval-Augmented Generation (RAG) — сочетание возможностей поиска и генерации, которые ссылаются на контекстно-специфическую информацию перед созданием ответа.

RAG стала очень популярной за последние несколько лет благодаря своей способности уменьшать количество галлюцинаций и улучшать достоверность фактов. Они гибкие, их легко обновлять, и они намного дешевле, чем тонкая настройка LLM. Мы ежедневно сталкиваемся с решениями RAG. Например, многие организации используют RAG для создания внутренних чат-ботов для сотрудников, чтобы они могли ориентироваться в своей базе знаний, и внешних чат-ботов для поддержки обслуживания клиентов и других бизнес-функций.

Создание RAG-конвейера

Для нашего решения RAG мы будем использовать рефераты из открытых исследований, связанных с искусственным интеллектом. Мы можем использовать эти данные для генерации более «технических» ответов при задании вопросов, связанных с искусственным интеллектом, машинным обучением и т. д.

Используемые данные поступают из OpenAlex API (https://openalex.org/). Это набор данных/каталог открытых исследований со всего мира. Данные находятся в свободном доступе по лицензии No Rights Reserved (лицензия CC0).

Поступление данных

Сначала нам нужно загрузить наши данные с помощью OpenAlex API. Ниже приведён код для поиска по году публикации и ключевым терминам. Мы проводим поиск по ИИ/МО, используя такие ключевые термины, как «глубокое обучение», «обработка естественного языка», «компьютерное зрение» и т. д.

import pandas as pd
import requests

def import_data(pages, start_year, end_year, search_terms):
    """
    Эта функция используется для использования OpenAlex API, проведения поиска по работам и возврата фрейма данных с соответствующими работами.

    Входы:
    - pages: int, количество страниц для перебора
    - search_terms: str, ключевые слова для поиска (должны быть отформатированы в соответствии со стандартами OpenAlex)
    - start_year и end_year: int, годы, заданные в качестве диапазона для фильтрации работ
    """

    search_results = pd.DataFrame()

    for page in range(1, pages):
        response = requests.get(f'https://api.openalex.org/works?page={page}&per-page=200&filter=publication_year:{start_year}-{end_year},type:article&search={search_terms}')
        data = pd.DataFrame(response.json()['results'])

        search_results = pd.concat([search_results, data])

    search_results = search_results[["id", "title", "display_name", "publication_year", "publication_date",
                                        "type", "countries_distinct_count","institutions_distinct_count",
                                        "has_fulltext", "cited_by_count", "keywords", "referenced_works_count", "abstract_inverted_index"]]

    return(search_results)

ai_search = import_data(30, 2018, 2025, "'artificial intelligence' OR 'deep learn' OR 'neural net' OR 'natural language processing' OR 'machine learn' OR 'large language models' OR 'small language models'")

При запросе базы данных OpenAlex рефераты возвращаются в виде инвертированного индекса. Ниже приведена функция для отмены инвертированного индекса и возврата исходного текста реферата.

def undo_inverted_index(inverted_index):
    """
    Цель функции — «отменить» и инвертированный индекс. Она вводит инвертированный индекс и возвращает исходную строку.
    """

    word_index = []
    words_unindexed = []

    for k,v in inverted_index.items(): 
        for index in v: word_index.append([k,index])

    word_index = sorted(word_index, key = lambda x : x[1])

    for pair in word_index:
        words_unindexed.append(pair[0])
    words_unindexed = ' '.join(words_unindexed)

    return(words_unindexed)

ai_search['original_abstract'] = list(map(undo_inverted_index, ai_search['abstract_inverted_index']))

Создание векторной базы данных

Далее нам нужно сгенерировать вложения для представления рефератов и сохранить их в векторной базе данных. Рекомендуется использовать векторные базы данных, поскольку они предназначены для запросов с низкой задержкой и могут масштабироваться для обработки миллиардов точек данных. Они также используют специализированные алгоритмы индексации и поиска ближайших соседей для быстрого извлечения данных на основе контекстуального и/или семантического сходства, что делает их незаменимыми для приложений LLM.

from langchain_community.docstore.in_memory import InMemoryDocstore
from langchain_community.vectorstores import FAISS
from langchain_huggingface.embeddings import HuggingFaceEmbeddings
from langchain_core.documents import Document

embeddings = HuggingFaceEmbeddings(model_name="thenlper/gte-small")

Создание RAG-конвейера

Теперь давайте разработаем наш RAG-конвейер. Важнейшим компонентом решения RAG является генеративная модель, используемая для генерации ответов. Для этого мы будем использовать модель OpenAI из LangChain.

from langchain_openai import OpenAI
from langchain.chains import RetrievalQA
from langchain import PromptTemplate

OPENAI_API_KEY = os.getenv("OPENAI_API_KEY","API KEY") 

llm = OpenAI(openai_api_key=OPENAI_API_KEY)

Оценка решений RAG

Чтобы начать оценку нашего решения, мы будем использовать другую генеративную модель, чтобы определить, насколько наше решение RAG соответствует определённым критериям. Хотя методы LLM-as-a-Judge имеют некоторые оговорки и их нужно использовать осторожно, они предлагают большую гибкость и эффективность. Они также могут дать подробную информацию в процессе оценки, как вы увидите ниже.

Оценка Retriever

Сначала мы оценим наш ретривер, компонент, который извлекает релевантный контент. Мы будем судить по трём метрикам:

  1. Контекстуальная точность: представляет большую способность системы поиска правильно ранжировать релевантные узлы. Сначала LLM определяет, является ли каждый узел релевантным для ввода, прежде чем рассчитать взвешенную кумулятивную точность.
  2. Контекстуальный отзыв: представляет большую способность системы поиска охватить всю релевантную информацию из общего доступного релевантного набора в вашей базе знаний.
  3. Контекстуальная релевантность: оценивает общую релевантность представленной информации для данного вывода.
from deepeval import evaluate
from deepeval.test_case import LLMTestCase, LLMTestCaseParams
from deepeval.metrics import (
    ContextualPrecisionMetric,
    ContextualRecallMetric,
    ContextualRelevancyMetric)

os.environ["OPENAI_API_KEY"] = "API KEY"

contextual_precision = ContextualPrecisionMetric()
contextual_recall = ContextualRecallMetric()
contextual_relevancy = ContextualRelevancyMetric()

Оценка генерации

Далее мы оценим наш генератор, который генерирует ответы на основе контекста, предоставленного ретривером. Здесь мы вычислим две метрики:

  1. Релевантность ответа: аналогично контекстуальной релевантности, оценивает, может ли шаблон запроса в вашем генераторе инструктировать вашу LLM давать релевантные выходные данные на основе контекста.
  2. Истинность: оценивает, может ли LLM, используемая в вашем генераторе, выдавать информацию, которая не галлюцинирует и не противоречит какой-либо фактической информации, представленной в контексте поиска.
from deepeval.metrics import AnswerRelevancyMetric, FaithfulnessMetric

answer_relevancy = AnswerRelevancyMetric()
faithfulness = FaithfulnessMetric()

Человеческая оценка

Хотя методы LLM-as-a-judge предоставляют нам много полезной информации, они являются общими и должны быть ограничены, поскольку не полностью оценивают применимость в реальных условиях. Люди, однако, могут лучше изучить это, поскольку никто не знает данные лучше, чем эксперты в предметной области в организации.

Человеческая оценка обычно проверяет правильность, качество обоснования и беглость речи. Оценщики должны определить, является ли вывод точным, логически связывает ли извлечённые доказательства с выводом, является ли он естественным и полезным. Важно помнить данные, пользователя и цель вашего решения RAG, чтобы правильно учитывать эти требования, специфичные для предметной области.

Заключение

В этой статье мы смогли создать RAG-конвейер, используя открытые исследования, используя FAISS, LangChain и другие инструменты. Мы также рассмотрели, как мы можем оценить решения RAG, оценивая как наш ретривер, так и генератор. Библиотеки, такие как DeepEval, используют метрики LLM-as-a-judge для создания тестовых случаев и определения релевантности, верности и многого другого. Наконец, мы обсудили, насколько важна человеческая оценка при определении применимости в реальных условиях вашего решения RAG.

Надеюсь, вам понравилась моя статья! Пожалуйста, не стесняйтесь комментировать, задавать вопросы или запрашивать другие темы.

Свяжитесь со мной в LinkedIn: https://www.VK.com/in/alexdavis2020/