Смягчите галлюцинации через Генерацию с использованием базы данных векторов Pinecone и Llama-2 от Amazon SageMaker JumpStart

Смягчение галлюцинаций с помощью базы данных векторов Pinecone и Llama-2 от Amazon SageMaker JumpStart

Помимо кажущейся неудержимой адаптации моделей языкового моделирования в различных отраслях, они являются одной из частей более широкой технологической экосистемы, которая обеспечивает новую волну искусственного интеллекта. Многие сценарии использования разговорного ИИ требуют моделей языкового моделирования, таких как Llama 2, Flan T5 и Bloom, чтобы отвечать на запросы пользователей. Эти модели опираются на параметрические знания для ответов на вопросы. Модель изучает эти знания в процессе обучения и закодирует их в параметры модели. Чтобы обновить эти знания, необходимо переобучить модель, что требует много времени и денег.

К счастью, мы также можем использовать исходные знания для информирования наших моделей языкового моделирования. Исходные знания – это информация, подаваемая в модель с помощью входного промпта. Один из популярных подходов к предоставлению исходных знаний – это Retrieval Augmented Generation (RAG). Используя RAG, мы извлекаем соответствующую информацию из внешнего источника данных и передаем эту информацию в модель.

В этой статье блога мы рассмотрим, как развернуть модели языкового моделирования, такие как Llama-2, с использованием Amazon Sagemaker JumpStart и хранить актуальную информацию в наших моделях с помощью Retrieval Augmented Generation (RAG), используя базу данных векторов Pinecone, чтобы предотвратить AI Hallucination.

Retrieval Augmented Generation (RAG) в Amazon SageMaker

Pinecone будет обрабатывать компонент извлечения информации в RAG, но вам понадобятся еще два важных компонента: место для выполнения вывода модели языкового моделирования (LLM) и место для выполнения модели вложения.

Amazon SageMaker Studio – это интегрированная среда разработки (IDE), которая предоставляет единый веб-интерфейс, где можно получить доступ к специальным инструментам для разработки моделей машинного обучения (ML). Она предоставляет SageMaker JumpStart, который является модельным хабом, где пользователи могут найти, предварительно просмотреть и запустить определенную модель в своей учетной записи SageMaker. Он предоставляет предварительно обученные, общедоступные и проприетарные модели для широкого спектра типов проблем, включая Foundation Models.

Amazon SageMaker Studio предоставляет идеальную среду для разработки конвейеров LLM, поддерживающих RAG. Во-первых, с использованием консоли AWS, перейдите в Amazon SageMaker и создайте домен SageMaker Studio, а затем откройте блокнот имени Jupyter Studio.

Предварительные требования

Выполните следующие предварительные шаги:

  1. Настроить Amazon SageMaker Studio.
  2. Присоединиться к домену Amazon SageMaker.
  3. Зарегистрироваться для бесплатной версии базы данных векторов Pinecone.
  4. Библиотеки, необходимые для предварительных требований: SageMaker Python SDK, Pinecone Client

Прохождение решения

Используя блокнот SageMaker Studio, сначала необходимо установить необходимые библиотеки:

!pip install -qU sagemaker pinecone-client==2.2.1 ipywidgets==7.0.0 

Развертывание LLM

В этой статье мы рассмотрим два подхода для развертывания LLM. Первый – это объект HuggingFaceModel. Вы можете использовать это при развертывании LLM (и моделей вложения) напрямую из модельного хаба Hugging Face.

Например, вы можете создать настраиваемую конфигурацию для модели google/flan-t5-xl, как показано на следующем скриншоте:

import sagemakerfrom sagemaker.huggingface import (HuggingFaceModel, get_huggingface_llm_image_uri)role = sagemaker.get_execution_role()hub_config = {'HF_MODEL_ID':'google/flan-t5-xl', # model_id from hf.co/models'HF_TASK':'text-generation' # NLP task you want to use for predictions# retrieve the llm image urillm_image = get_huggingface_llm_image_uri("huggingface", version="0.8.2"&)huggingface_model = HuggingFaceModel(env=hub_config, role=role, # iam role with permissions to create an Endpoint image_uri=llm_image)

При развертывании моделей напрямую из Hugging Face инициализируйте my_model_configuration следующим образом:

  • Конфигурация env сообщает нам, какую модель мы хотим использовать и для какой задачи.
  • Наша исполняющая роль SageMaker дает нам разрешения для развертывания модели.
  • image_uri – это конфигурация изображения, специально предназначенная для развертывания LLM из Hugging Face.

В качестве альтернативы, SageMaker имеет набор моделей, непосредственно совместимых с более простым объектом JumpStartModel. Эта модель поддерживает множество популярных LLM, таких как Llama 2, и может быть инициализирована следующим образом:

import sagemaker from sagemaker.jumpstart.model import JumpStartModel role = sagemaker.get_execution_role() my_model = JumpStartModel(model_id = "meta-textgeneration-llama-2-7b-f")

Деплойте оба варианта my_model, как показано на скриншоте:

predictor = my_model.deploy(    initial_instance_count=1, instance_type="ml.g5.4xlarge", endpoint_name="llama-2-generator")

Запрос к предварительно обученной LLM

С нашим инициализированным LLM эндпоинтом вы можете начать запросы. Формат наших запросов может варьироваться (особенно между разговорными и неразговорными LLM), но процесс обычно одинаков. Для модели Hugging Face выполните следующее:

# https://aws.amazon.com/blogs/machine-learning/llama-2-foundation-models-from-meta-are-now-available-in-amazon-sagemaker-jumpstart/prompt = """Ответьте на следующий вопрос, исходя из данного контекста. Если вы не знаете ответ и контекст не содержит ответа, честно скажите "Не знаю".ВОПРОС:"""payload = {    "inputs":        [        [         {"role": "system", "content": prompt},         {"role": "user", "content": question},        ]         ],   "parameters":{"max_new_tokens": 64, "top_p": 0.9, "temperature": 0.6, "return_full_text": False}}out = predictor.predict(payload, custom_attributes='accept_eula=true')out[0]['generation']['content']

Вы можете найти решение в репозитории GitHub.

Сгенерированный ответ, который мы получаем здесь, не имеет особого смысла — это галлюцинация.

Предоставление дополнительного контекста LLM

Llama 2 пытается ответить на наш вопрос исключительно на основе внутренних параметров модели. Очевидно, что параметры модели не сохраняют знания о том, с какими экземплярами можно использовать Managed Spot Training в SageMaker.

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

context = """Managed Spot Training можно использовать со всеми поддерживаемыми экземплярами в Amazon SageMaker. Managed Spot Training поддерживается во всех регионах AWS, где в настоящее время доступен Amazon SageMaker."""prompt_template = """Ответьте на следующий вопрос, исходя из данного контекста. Если вы не знаете ответ и контекст не содержит ответа, честно скажите "Не знаю".КОНТЕКСТ:{context}ВОПРОС:"""text_input = prompt_template.replace("{context}", context).replace("{question}", question)payload = {    "inputs":        [        [         {"role": "system", "content": text_input},         {"role": "user", "content": question},        ]         ],   "parameters":{"max_new_tokens": 64, "top_p": 0.9, "temperature": 0.6, "return_full_text": False}}out = predictor.predict(payload, custom_attributes='accept_eula=true')generated_text = out[0]['generation']['content']print(f"[Ввод]: {question}\n[Вывод]: {generated_text}")[Ввод]: С какими экземплярами я могу использовать Managed Spot Training в SageMaker?[Вывод]: Исходя из данного контекста, вы можете использовать Managed Spot Training со всеми поддерживаемыми экземплярами в Amazon SageMaker. Поэтому ответ: Со всеми экземплярами, поддерживаемыми в Amazon SageMaker.

Теперь мы видим правильный ответ на вопрос; это было легко! Однако пользователь вряд ли будет вставлять контексты в свои подсказки, он уже знает ответ на свой вопрос.

Вместо ручного вставления одного контекста автоматически определяйте соответствующую информацию из более обширной базы данных информации. Для этого вам понадобится Retrieval Augmented Generation.

Получение с улучшенной аугментацией

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

После извлечения этих релевантных записей выберите несколько из них и включите их в LLM-подсказку в качестве дополнительного контекста, предоставляя LLM высоко релевантные исходные знания. Это двухэтапный процесс, в котором:

  • Индексация заполняет векторный индекс информацией из набора данных.
  • Извлечение происходит во время запроса и заключается в извлечении соответствующей информации из векторного индекса.

Оба шага требуют эмбеддинг-модели для преобразования нашего читаемого человеком обычного текста в семантическое векторное пространство. Используйте высокоэффективный модуль MiniLM sentence transformer от Hugging Face, как показано на следующем снимке экрана. Эта модель не является LLM и, следовательно, не инициализируется так же, как наша модель Llama 2.

hub_config = {    "HF_MODEL_ID": "sentence-transformers/all-MiniLM-L6-v2",  # идентификатор модели с hf.co/models    "HF_TASK": "feature-extraction",}huggingface_model = HuggingFaceModel(    env=hub_config,    role=role,    transformers_version="4.6",  # используемая версия transformers    pytorch_version="1.7",  # используемая версия pytorch    py_version="py36",  # версия Python в DLC)

В hub_config укажите идентификатор модели, как показано на снимке экрана выше, но для задачи используйте feature-extraction, так как мы генерируем векторные эмбеддинги, а не текст как в LLM. Затем инициализируйте конфигурацию модели с помощью HuggingFaceModel, как и раньше, но на этот раз без изображения LLM и с некоторыми параметрами версии.

encoder = huggingface_model.deploy(    initial_instance_count=1, instance_type="ml.t2.large", endpoint_name="minilm-embedding")

Вы можете повторно развернуть модель с помощью deploy, используя более маленький экземпляр (только CPU) ml.t2.large. Модель MiniLM является небольшой, поэтому ей не требуется много памяти и она не нуждается в GPU, потому что она может быстро создавать эмбеддинги даже на процессоре. При желании вы можете запустить модель быстрее на GPU.

Для создания эмбеддингов используйте метод predict и передайте список контекстов для кодирования через ключ inputs, как показано ниже:

out = encoder.predict({"inputs": ["некоторый текст здесь", "еще немного текста здесь"]})

Передаются два входных контекста, возвращающих два эмбеддинга вектора контекстов, как показано:

len(out)

2

Размерность вектора эмбеддинга модели MiniLM составляет 384, что означает, что каждый выходной векторный эмбеддинг MiniLM должен иметь размерность 384. Однако, посмотрев на длину наших эмбеддингов, вы увидите следующее:

len(out[0]), len(out[1])

(8, 8)

Два списка содержат по восемь элементов каждый. MiniLM сначала обрабатывает текст на этапе токенизации. Эта токенизация преобразует наш читаемый человеком обычный текст в список ID токенов, понятных модели. В выходных особенностях модели можно увидеть эмбеддинги на уровне токенов. Один из этих эмбеддингов показывает ожидаемую размерность 384, как показано:

len(out[0][0])

384

Преобразуйте эти эмбеддинги на уровне токенов в эмбеддинги на уровне документа, используя среднее значение по каждому векторному измерению, как показано на следующей иллюстрации.

Операция среднего пуллинга для получения одного вектора размерности 384.

import numpy as np embeddings = np.mean(np.array(out), axis=1)embeddings.shape(2, 384)

С двумя векторными вложениями размерностью 384 для каждого входного текста. Чтобы облегчить нашу жизнь, оберните процесс кодирования в единую функцию, как показано на следующем скриншоте:

from typing import Listdef embed_docs(docs: List[str]) -> List[List[float]]:    out = encoder.predict({"inputs": docs})    embeddings = np.mean(np.array(out), axis=1)    return embeddings.tolist()

Загрузка набора данных

Загрузите часто задаваемые вопросы Amazon SageMaker в качестве базы знаний, чтобы получить данные, содержащие столбцы вопросов и ответов.

Загрузить часто задаваемые вопросы Amazon SageMaker

При выполнении поиска ищите только ответы, чтобы можно было удалить столбец вопросов. Подробнее в блокноте.

Наш набор данных и система векторизации готовы. Теперь нам нужно найти место, где хранить эти вложения.

Индексация

База данных векторов Pinecone хранит векторные вложения и ищет их эффективно в масштабе. Для создания базы данных вам понадобится бесплатный API-ключ Pinecone.

import pineconeimport os# добавьте API-ключ Pinecone из app.pinecone.ioapi_key = os.environ.get("PINECONE_API_KEY") or "YOUR_API_KEY"# задайте среду Pinecone - найдите рядом с ключом API в консолиenv = os.environ.get("PINECONE_ENVIRONMENT") or "YOUR_ENV"pinecone.init(api_key=api_key, environment=env)

После подключения к базе данных векторов Pinecone создайте единственный векторный индекс (аналогично таблице в традиционных базах данных). Назовите индекс retrieval-augmentation-aws и согласуйте параметры индекса dimension и metric с требованиями модели вложений (в данном случае MiniLM).

import timeindex_name = "retrieval-augmentation-aws"if index_name in pinecone.list_indexes():    pinecone.delete_index(index_name)pinecone.create_index(name=index_name, dimension=embeddings.shape[1], metric="cosine")# дождитесь завершения инициализации индексаwhile not pinecone.describe_index(index_name).status["ready"]:    time.sleep(1)

Для начала вставки данных выполните следующее:

from tqdm.auto import tqdmbatch_size = 2  # можно увеличить, но для этого понадобится больший размер экземпляра, иначе заполнится памятьinstance runs out of memoryvector_limit = 1000answers = df_knowledge[:vector_limit]index = pinecone.Index(index_name)for i in tqdm(range(0, len(answers), batch_size)):    # find end of batch    i_end = min(i + batch_size, len(answers))    # create IDs batch    ids = [str(x) for x in range(i, i_end)]    # create metadata batch    metadatas = [{"text": text} for text in answers["Answer"][i:i_end]]    # create embeddings    texts = answers["Answer"][i:i_end].tolist()    embeddings = embed_docs(texts)    # create records list for upsert    records = zip(ids, embeddings, metadatas)    # upsert to Pinecone    index.upsert(vectors=records)

Вы можете начать запросы к индексу с вопроса, изложенного ранее в этой статье.

# извлечь вложения для заданных вопросовquery_vec = embed_docs(question)[0]# запрос в Pineconeres = index.query(query_vec, top_k=1, include_metadata=True)# показать результатres{'matches': [{'id': '90','metadata': {'text': 'Managed Spot Training can be used with all ''instances supported in Amazon ''SageMaker.\r\n'},'score': 0.881181657,'values': []}],'namespace': ''}

Выведенный выше результат показывает, что мы возвращаем соответствующие контексты, чтобы помочь нам ответить на наш вопрос. Поскольку top_k = 1, функция index.query возвращает лучший результат вместе с метаданными, которые гласят Managed Spot Training can be used with all instances supported in Amazon.

Дополнение к запросу

Используйте полученные контексты для дополнительной информации и решите максимальное количество контекста, которое нужно передать в LLM. Используйте ограничение в 1000 символов, чтобы итеративно добавлять каждый полученный контекст к запросу, пока не превысите длину контента.

Дополнение к запросу

Дополнение к запросу

Вставьте context_str в запрос LLM, как показано на следующем скриншоте:

payload = create_payload(question, context_str)out = predictor.predict(payload, custom_attributes='accept_eula=true')generated_text = out[0]['generation']['content']print(f"[Вход]: {question}\n[Выход]: {generated_text}")

[Вход]: Какие экземпляры можно использовать с управляемым тренировочным запуском в SageMaker?[Выход]:  Исходя из предоставленного контекста, можно использовать управляемый тренировочный запуск с любыми экземплярами, которые поддерживаются в Amazon SageMaker. Таким образом, ответ такой:Все экземпляры, поддерживаемые в Amazon SageMaker.

Логика работает, поэтому оберните это в одну функцию для сохранения порядка.

def rag_query(question: str) -> str:    # создание вектора запроса    query_vec = embed_docs(question)[0]    # запрос к Pinecone    res = index.query(query_vec, top_k=5, include_metadata=True)    # получение контекстов    contexts = [match.metadata["text"] for match in res.matches]    # создание строки с несколькими контекстами    context_str = construct_context(contexts=contexts)    # создание усиленного запроса с данными извлечения    payload = create_payload(question, context_str)    # предсказание    out = predictor.predict(payload, custom_attributes='accept_eula=true')    return out[0]["generation"]["content"]

Теперь вы можете задавать вопросы, как показано ниже:

rag_query("Поддерживает ли SageMaker экземпляры Spot?")'Да, Amazon SageMaker поддерживает экземпляры Spot для управляемого тренировочного запуска. Исходя из предоставленного контекста, управляемый тренировочный запуск можно использовать с любыми экземплярами, поддерживаемыми в Amazon SageMaker. Управляемый тренировочный запуск поддерживается во всех регионах AWS, в которых в настоящее время доступен Amazon SageMaker.\n\nСледовательно, ответ на ваш вопрос:\n\nДа, SageMaker поддерживает экземпляры Spot во всех регионах, где доступен Amazon SageMaker.'

Очистка

Для предотвращения неожиданных расходов удалите модель и эндпоинт.

encoder.delete_model()encoder.delete_endpoint()

Вывод

В этой статье мы познакомили вас с RAG с открытыми LLM на SageMaker. Мы также показали, как развернуть модели Amazon SageMaker Jumpstart с помощью Llama 2, Hugging Face LLMs с помощью Flan T5 и модели векторного кодирования с помощью MiniLM.

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

Чтобы запустить этот пример самостоятельно, клонируйте этот репозиторий GitHub и пройдите через предыдущие шаги, используя Notebook по вопросно-ответной системе на GitHub.