Создайте контекстного чат-бота для финансовых услуг, используя Amazon SageMaker JumpStart, Llama 2 и Amazon OpenSearch Serverless с Vector Engine.

Вам представляется возможность создать контекстного чат-бота для финансовых услуг с использованием Amazon SageMaker JumpStart, Llama 2 и Amazon OpenSearch Serverless с Vector Engine.

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

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

Преимущества использования SageMaker JumpStart

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

SageMaker JumpStart идеально подходит для использования генеративного ИИ в области финансового обслуживания клиентов, поскольку он предлагает следующее:

  • Возможности настройки – SageMaker JumpStart предоставляет примеры записных книжек и подробные публикации для пошагового руководства по адаптации основных моделей к домену. Вы можете использовать эти ресурсы для оптимизации, адаптации к домену и инструкций по основным моделям или для создания приложений на основе RAG.
  • Безопасность данных – Обеспечение безопасности данных вывода модели является главным. С помощью SageMaker JumpStart вы можете развертывать модели в изолированной сети с использованием предоставления конечных точек, принадлежащих единому арендатору. Кроме того, вы можете управлять контролем доступа к выбранным моделям через возможность частной модели, соответствующей индивидуальным требованиям безопасности.
  • Регуляторные контроли и комплаенсы – Соответствие стандартам, таким как HIPAA BAA, SOC123, PCI и HITRUST CSF, является основной особенностью SageMaker, обеспечивая соответствие строгому регулятивному ландшафту финансового сектора.
  • Выбор моделей – SageMaker JumpStart предлагает выбор из передовых моделей МО, которые постоянно занимают высокие места в признанных отраслевых бенчмарках HELM. Сюда включаются, но не ограничиваются, модели Llama 2, Falcon 40B, AI21 J2 Ultra, AI21 Summarize, Hugging Face MiniLM и BGE.

В этом посте мы рассмотрим создание контекстного чат-бота для финансовых организаций с использованием архитектуры RAG с основной моделью Llama 2 и моделью встроенных представлений Hugging Face GPTJ-6B-FP16, которые доступны в SageMaker JumpStart. Мы также используем Vector Engine для Amazon OpenSearch Serverless (находится в настоящее время на этапе предварительного просмотра) как хранилище векторных данных для хранения встроенных представлений.

Ограничения больших языковых моделей

Большие языковые модели (LLM) обучаются на огромных объемах неструктурированных данных и отлично справляются с общей генерацией текста. В процессе обучения LLM получают и сохраняют фактические знания. Однако готовые к использованию LLM имеют определенные ограничения:

  • Их офлайн-обучение делает их несведущими в актуальной информации.
  • Их обучение на преимущественно обобщенных данных снижает их эффективность в доменно-специфических задачах. Например, финансовая фирма, возможно, предпочла бы, чтобы ее бот Q&A черпал ответы из последних внутренних документов с целью обеспечения точности и соответствия ее бизнес-правилам.
  • Их зависимость от встроенной информации угрожает их интерпретируемости.

Чтобы использовать конкретные данные в LLMs, существуют три распространенных метода:

  • Встраивание данных в модельные подсказки, позволяющее ей использовать этот контекст при генерации вывода. Это может быть без примеров (zero-shot), с ограниченным количеством примеров (few-shot) или с избыточным количеством примеров (many-shot). Такие контекстные подсказки направляют модели на более нюансированные результаты.
  • Настройка модели с использованием пар подсказок и завершений.
  • RAG, который извлекает внешние данные (непараметрические) и интегрирует эти данные в подсказки, обогащая контекст.

Однако первый метод сталкивается с ограничениями модели в отношении размера контекста, что затрудняет ввод длинных документов и может увеличивать затраты. Подход настройки модели, хотя и мощный, требует больших ресурсов, особенно с постоянно меняющимися внешними данными, что приводит к задержкам в развертывании и увеличению затрат. RAG в сочетании с LLMs предлагает решение для упомянутых ограничений.

Поиск с усиленной генерацией

RAG извлекает внешние данные (непараметрические) и интегрирует эти данные в подсказки МО, обогащая контекст. Льюис (Lewis) и др. в 2020 году представили модели RAG, представляющие собой комбинацию предварительно обученной модели последовательности-последовательности (параметрическое хранилище) и плотного векторного индекса Википедии (непараметрическое хранилище), доступного через нейронный поисковик.

Вот как работает RAG:

  • Источники данных – RAG может использовать различные источники данных, включая хранилища документов, базы данных или API.
  • Форматирование данных – Как запрос пользователя, так и документы преобразуются в формат, подходящий для сравнения на соответствие.
  • Вложения – Чтобы облегчить это сравнение, запрос и коллекция документов (или библиотека знаний) преобразуются в числовые вложения с использованием языковых моделей. Эти вложения численно отражают текстовые концепты.
  • Поиск соответствий – Вложение запроса пользователя сравнивается с вложениями коллекции документов, идентифицируя соответствующий текст с помощью поиска сходства в пространстве вложений.
  • Обогащение контекста – Идентифицированный соответствующий текст добавляется к исходной подсказке пользователя, улучшая ее контекст.
  • Обработка LLM – С обогащенным контекстом подсказка подается LLM, который благодаря включению соответствующих внешних данных генерирует релевантные и точные выводы.
  • Асинхронные обновления – Чтобы обеспечить актуальность справочных документов, их можно обновлять асинхронно вместе с их вложением. Это гарантирует, что будущие ответы модели будут основаны на последних сведениях, обеспечивая точность.

В основе RAG – динамический метод внедрения LLMs с информацией реального времени, обеспечивая создание точных и своевременных выводов.

Следующая схема показывает концептуальный ход использования RAG с LLMs.

Обзор решения

Для создания контекстуального чат-бота для финансового приложения вам потребуются следующие шаги:

  1. Используйте модель внедрения SageMaker JumpStart GPT-J-6B для создания вложений для каждого PDF-документа в каталоге загрузки Amazon Simple Storage Service (Amazon S3).
  2. Определите соответствующие документы, выполнив следующие операции:
    • Сгенерируйте вложение для запроса пользователя с использованием той же модели.
    • Используйте OpenSearch Serverless с функцией векторного поиска для поиска K наиболее релевантных индексов документов в пространстве вложений.
    • Извлеките соответствующие документы с использованием идентифицированных индексов.
  3. Объедините извлеченные документы в контекст с подсказкой и вопросом пользователя. Передайте это в SageMaker LLM для генерации ответа.

Мы используем LangChain, популярный фреймворк, для организации этого процесса. LangChain специально разработан для повышения эффективности приложений, работающих на основе LLMs, предлагая универсальный интерфейс для различных LLMs. Он упрощает интеграцию нескольких LLMs, обеспечивает безпроблемное сохранение состояния между вызовами. Кроме того, он повышает эффективность разработчиков с помощью функций, таких как настраиваемые шаблоны подсказок, комплексные агенты создания приложений и специализированные индексы для поиска и извлечения. Для более подробного понимания обратитесь к документации LangChain.

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

Для создания чат-бота, основанного на контексте, вам понадобятся следующие предварительные условия:

Инструкции по настройке векторного движка Amazon OpenSearch без сервера см. в статье Представление векторного движка для Amazon OpenSearch без сервера (предварительная версия).

Чтобы получить полное пошаговое руководство по данному решению, клонируйте репозиторий на GitHub и обратитесь к тетрадке Jupyter.

Развертывание моделей машинного обучения с использованием SageMaker JumpStart

Для развертывания моделей машинного обучения выполните следующие действия:

  1. Разверните модель Llama 2 LLM из SageMaker JumpStart:

    from sagemaker.jumpstart.model import JumpStartModelllm_model = JumpStartModel(model_id = "meta-textgeneration-llama-2-7b-f")llm_predictor = llm_model.deploy()llm_endpoint_name = llm_predictor.endpoint_name
  2. Разверните модель векторных вложений GPT-J:

    embeddings_model = JumpStartModel(model_id = "huggingface-textembedding-gpt-j-6b-fp16")embed_predictor = embeddings_model.deploy()embeddings_endpoint_name = embed_predictor.endpoint_name

Разделение данных на фрагменты и создание объекта векторных вложений документов

В этом разделе вы разделите данные на более мелкие документы. Разделение – это техника разбиения больших текстов на более мелкие фрагменты. Это важный шаг, поскольку он оптимизирует релевантность запроса поиска для нашей модели RAG, что в свою очередь повышает качество чат-бота. Размер фрагмента зависит от таких факторов, как тип документа и используемая модель. Был выбран фрагмент размером 1600 символов, поскольку это приблизительный размер абзаца. По мере улучшения моделей их контекстное окно будет увеличиваться, что позволит использовать более крупные фрагменты.

См. полное решение в тетрадке Jupyter в репозитории GitHub.

  1. Расширьте класс SageMakerEndpointEmbeddings из LangChain, чтобы создать пользовательскую функцию вложений, которая использует ранее созданный конечный точечный SageMaker с моделью gpt-j-6b-fp16:

    from langchain.embeddings import SagemakerEndpointEmbeddingsfrom langchain.embeddings.sagemaker_endpoint import EmbeddingsContentHandlerlogger = logging.getLogger(__name__)# расширение класса SagemakerEndpointEmbeddings из LangChain для предоставления пользовательской функции вложенийclass SagemakerEndpointEmbeddingsJumpStart(SagemakerEndpointEmbeddings):    def embed_documents(        self, texts: List[str], chunk_size: int = 1    ) → List[List[float]]:        """Вычисление вложений документов с использованием конечной точки SageMaker Inference.         Args:            texts: Список текстов для вложения.            chunk_size: Размер фрагмента определяет, сколько входных текстов будет                группироваться вместе в запросе. Если значение равно None, будет использован                размер фрагмента, указанный в классе.        Returns:            Список векторных вложений для каждого текста.        """        results = []        _chunk_size = len(texts) if chunk_size > len(texts) else chunk_size        st = time.time()        for i in range(0, len(texts), _chunk_size):            response = self._embedding_func(texts[i : i + _chunk_size])            results.extend(response)        time_taken = time.time() - st        logger.info(            f"получены результаты для {len(texts)} в {time_taken} с, длина списка вложений - {len(results)}"        )        print(            f"получены результаты для {len(texts)} в {time_taken} с, длина списка вложений - {len(results)}"        )        return results# класс для сериализации/десериализации запросов/ответов в/из модели вложенийclass ContentHandler(EmbeddingsContentHandler):    content_type = "application/json"    accepts = "application/json"     def transform_input(self, prompt: str, model_kwargs={}) → bytes:         input_str = json.dumps({"text_inputs": prompt, **model_kwargs})        return input_str.encode("utf-8")     def transform_output(self, output: bytes) → str:         response_json = json.loads(output.read().decode("utf-8"))        embeddings = response_json["embedding"]        if len(embeddings) == 1:            return [embeddings[0]]        return embeddingsdef create_sagemaker_embeddings_from_js_model(    embeddings_endpoint_name: str, aws_region: str) → SagemakerEndpointEmbeddingsJumpStart:     content_handler = ContentHandler()    embeddings = SagemakerEndpointEmbeddingsJumpStart(        endpoint_name=embeddings_endpoint_name,        region_name=aws_region,        content_handler=content_handler,    )    return embeddings
  2. Создайте объект вложений и сгруппируйте создание вложений документов:

    embeddings = create_sagemaker_embeddings_from_js_model(embeddings_endpoint_name, aws_region)
  3. Эти вложения хранятся в векторном движке с использованием OpenSearchVectorSearch из LangChain. Вы сохраняете эти вложения в следующем разделе. Сохраните вложение документа в безсерверном OpenSearch. Теперь вы готовы итерироваться по разделенным документам, создавать вложения и сохранять эти вложения в индексе векторного поиска Amazon OpenSearch без сервера, созданном в коллекциях поиска векторов. См. следующий код:

    docsearch = OpenSearchVectorSearch.from_texts(texts = [d.page_content for d in docs],embedding=embeddings,opensearch_url=[{'host': _aoss_host, 'port': 443}],http_auth=awsauth,timeout = 300,use_ssl = True,verify_certs = True,connection_class = RequestsHttpConnection,index_name=_aos_index)

Вопросы и ответы по документам

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

Выполните следующие шаги, чтобы отвечать на вопросы с использованием документов:

  1. Для использования конечной точки SageMaker LLM с LangChain вы используете langchain.llms.sagemaker_endpoint.SagemakerEndpoint, которая абстрагирует конечную точку SageMaker LLM. Вы выполняете преобразование для полезной нагрузки запроса и ответа, как показано в следующем коде для интеграции LangChain SageMaker. Обратите внимание, что вам может потребоваться настроить код в ContentHandler на основе типа содержимого и формата, принимаемого моделью LLM, который вы выбрали.

    content_type = "application/json"accepts = "application/json"def transform_input(self, prompt: str, model_kwargs: dict) → bytes:        payload = {            "inputs": [                [                    {                        "role": "system",                        "content": prompt,                    },                    {"role": "user", "content": prompt},                ],            ],            "parameters": {                "max_new_tokens": 1000,                "top_p": 0.9,                "temperature": 0.6,            },        }        input_str = json.dumps(            payload,        )        return input_str.encode("utf-8")def transform_output(self, output: bytes) → str:    response_json = json.loads(output.read().decode("utf-8"))    content = response_json[0]["generation"]["content"]    return contentcontent_handler = ContentHandler()sm_jumpstart_llm=SagemakerEndpoint(        endpoint_name=llm_endpoint_name,        region_name=aws_region,        model_kwargs={"max_new_tokens": 300},        endpoint_kwargs={"CustomAttributes": "accept_eula=true"},        content_handler=content_handler,    )

Теперь вы готовы взаимодействовать с финансовым документом.

  1. Используйте следующий запрос и шаблон для вопроса, касающегося документа:

    from langchain import PromptTemplate, SagemakerEndpointfrom langchain.llms.sagemaker_endpoint import LLMContentHandlerquery = "Summarize the earnings report and also what year is the report for"prompt_template = """Only use context to answer the question at the end. {context} Question: {question}Answer:"""prompt = PromptTemplate(    template=prompt_template, input_variables=["context", "question"])  class ContentHandler(LLMContentHandler):    content_type = "application/json"    accepts = "application/json"    def transform_input(self, prompt: str, model_kwargs: dict) → bytes:        payload = {            "inputs": [                [                    {                        "role": "system",                        "content": prompt,                    },                    {"role": "user", "content": prompt},                ],            ],            "parameters": {                "max_new_tokens": 1000,                "top_p": 0.9,                "temperature": 0.6,            },        }        input_str = json.dumps(            payload,        )        return input_str.encode("utf-8")     def transform_output(self, output: bytes) → str:        response_json = json.loads(output.read().decode("utf-8"))        content = response_json[0]["generation"]["content"]        return contentcontent_handler = ContentHandler() chain = load_qa_chain(    llm=SagemakerEndpoint(        endpoint_name=llm_endpoint_name,        region_name=aws_region,        model_kwargs={"max_new_tokens": 300},        endpoint_kwargs={"CustomAttributes": "accept_eula=true"},        content_handler=content_handler,    ),    prompt=prompt,)sim_docs = docsearch.similarity_search(query, include_metadata=False)chain({"input_documents": sim_docs, "question": query}, return_only_outputs=True)

Очистка

Чтобы избежать будущих затрат, удалите конечные точки вывода SageMaker, которые вы создали в этом ноутбуке SageMaker Studio. Вы можете сделать это, выполнив следующее в своем ноутбуке SageMaker Studio:

# Удаление Модели LLMllm_predictor.delete_model()llm_predictor.delete_predictor(delete_endpoint_config=True)# Удаление Модели Векторных Вложенийembed_predictor.delete_model()embed_predictor.delete_predictor(delete_endpoint_config=True)

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

Заключение

В этом посте мы обсудили использование RAG в качестве подхода, чтобы предоставить предметно-специфический контекст для LLMs. Мы показали, как использовать SageMaker JumpStart для создания контекстного чат-бота на основе RAG для финансовой организации с использованием Llama 2 и OpenSearch Serverless с хранилищем векторных данных на основе векторного движка. Этот метод улучшает генерацию текста с помощью Llama 2 путем динамического использования соответствующего контекста. Мы с нетерпением ждем вашего использования настраиваемых данных и инноваций с использованием этой стратегии на основе RAG в SageMaker JumpStart!