Интеллектуальная обработка документов с помощью Amazon Textract, Amazon Bedrock и LangChain

Умная обработка документов Amazon Textract, Amazon Bedrock и LangChain в действии

В информационную эпоху сегодня огромные объемы данных, содержащихся в бесчисленных документах, представляют собой одновременно и вызов, и возможность для бизнеса. Традиционные методы обработки документов часто не соответствуют требованиям эффективности и точности, открывая простор для инноваций, экономии затрат и оптимизации. Обработка документов претерпела значительные изменения с появлением технологии “умной обработки документов” (IDP). С помощью IDP предприятия могут преобразовывать неструктурированные данные из различных типов документов в структурированные, действенные информации, значительно повышая эффективность и снижая ручные усилия. Однако потенциал не ограничивается этим. Используя генеративный искусственный интеллект (AI) в процессе, мы можем дополнительно улучшить возможности IDP. Генеративный AI не только обеспечивает расширенные возможности в обработке документов, но и предлагает динамичную адаптивность к изменению данных. В этом посте мы рассмотрим синергию IDP и генеративного AI, раскрывая, как они представляют следующую границу в обработке документов.

Мы подробно рассматриваем IDP в нашей серии “Умная обработка документов с использованием AI-сервисов AWS” (Часть 1 и Часть 2). В этом посте мы рассмотрим, как расширить новую или существующую архитектуру IDP с помощью больших языковых моделей (LLM). Конкретнее, мы обсудим, как мы можем интегрировать Amazon Textract с LangChain в качестве загрузчика документов и Amazon Bedrock для извлечения данных из документов и использования возможностей генеративного AI на разных этапах IDP.

Amazon Textract – это служба машинного обучения (ML), которая автоматически извлекает текст, рукописный текст и данные из отсканированных документов. Amazon Bedrock – это полностью управляемая служба, которая предлагает выбор высокопроизводительных базовых моделей (FMs) через простые в использовании API.

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

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

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

  • Классификация документов – Помимо использования Amazon Comprehend, Вы можете использовать LLM для классификации документов с помощью подсказки с небольшим числом примеров различных классов и списком всех возможных классов, а затем запросить модель классифицировать определенный фрагмент текста из документа с использованием одного из классов.
  • Суммаризация – Вы также можете использовать LLM для краткого изложения больших документов с целью предоставления точных резюме в рамках этапа извлечения IDP. Например, система финансового анализа может включать анализ сотен страниц документов о доходах компании. Вы можете использовать языковую модель для краткого изложения ключевых аспектов доходов, что позволяет аналитикам принимать бизнес-решения.
  • Стандартизация и контекстный вопрос-ответ – Помимо извлечения точной информации из документов с использованием функциональности Amazon Textract Analyze Document, вы можете использовать LLM для извлечения информации, которая иначе не является явной в документе. Например, в резюме выписки пациента может быть указана дата поступления пациента в больницу и дата выписки, но может не указываться общее количество дней, проведенных пациентом в больнице. Чтобы определить общее количество дней, проведенных пациентом в больнице, на основе двух дат, извлеченных с помощью Amazon Textract, можно использовать LLM. Затем это значение можно присвоить с известным псевдонимом в формате ключ-значение (нормализованный ключ), что делает его еще более понятным для использования и постобработки.
  • Создание шаблонов и нормализация – Часто IDP-конвейер генерирует вывод, который должен соответствовать определенной определенной схеме. Это необходимо для того, чтобы вывод, полученный с помощью рабочего процесса IDP, можно было использовать во вторичной системе, например, в реляционной базе данных. Определение определенной схемы также позволяет достичь ключевой нормализации, чтобы у нас был известный набор ключей для обработки в логике постобработки. Например, мы можем определить “DOB” как нормализованный ключ для “даты рождения”, “даты рождения”, “даты рождения”, “даты рождения” и так далее, потому что документы могут содержать любое варьирование этих понятий. Мы используем LLM для выполнения таких операций шаблонизации и извлечения нормализованных ключ-значение из любого документа.
  • Проверка орфографии и исправления – Хотя Amazon Textract может извлекать точные значения из отсканированных документов (напечатанных или написанных от руки), вы можете использовать языковую модель для определения существования орфографических ошибок и грамматических ошибок в извлеченных данных. Это важно в ситуациях, когда данные могут быть извлечены из документов низкого качества или написанных от руки и используются для создания маркетинговых материалов, флэш-отчетов и т.д. В дополнение к тому, чтобы человек вручную проверял извлечения с низким баллом от Amazon Textract, вы можете использовать LLM, чтобы ускорить процесс проверки, предоставляя рекомендации по исправлению человеку, рецензирующему текст.

В следующих разделах мы углубимся в то, как Amazon Textract интегрируется в рабочие процессы генеративного искусственного интеллекта с использованием LangChain для обработки документов по каждой из этих конкретных задач. Здесь предоставлены урезанные блоки кода для краткости. Смотрите наш репозиторий GitHub для подробных примеров кода на Python и пошагового руководства.

Загрузчик документов Amazon Textract LangChain

Извлечение текста из документов является важным аспектом при обработке документов с использованием LLMs. Вы можете использовать Amazon Textract для извлечения неструктурированного исходного текста из документов и сохранения оригинальных полуструктурированных или структурированных объектов, таких как пары ключ-значение и таблицы, присутствующих в документе. Пакеты документов, такие как медицинские и страховые претензии или ипотеки, состоят из сложных форм, которые содержат много информации в структурированных, полуструктурированных и неструктурированных форматах. Извлечение документов важно здесь, потому что LLMs получают выгоду от богатого контента для генерации более точных и соответствующих ответов, что в противном случае может повлиять на качество вывода LLMs.

LangChain – мощный открытый фреймворк для интеграции с LLMs. LLMs в целом являются универсальными, но могут иметь проблемы с задачами, связанными с определенной областью, где требуются более глубокий контекст и нюансированные ответы. В таких сценариях LangChain дает разработчикам возможность создавать агентов, которые могут разбивать сложные задачи на более мелкие подзадачи. Подзадачи могут добавлять контекст и память в LLMs, связывая и цепляя LLM подсказки.

LangChain предлагает загрузчики документов, которые могут загружать и преобразовывать данные из документов. Вы можете использовать их для структурирования документов в предпочитаемые форматы, которые могут быть обработаны LLMs. AmazonTextractPDFLoader является типом загрузчика документов-сервиса, который обеспечивает быстрый способ автоматизации обработки документов с использованием Amazon Textract в сочетании с LangChain. Дополнительные сведения о AmazonTextractPDFLoader см. в документации LangChain. Чтобы использовать загрузчик документов Amazon Textract, вы начинаете с его импорта из библиотеки LangChain:

from langchain.document_loaders import AmazonTextractPDFLoader

Вы можете загружать документ с использованием HTTPS URL-адреса, а также документы, размещенные в сервисе простого хранения Amazon (Amazon S3) с помощью URL-адресов объектов Amazon S3 (также называемых доступом в стиле пути):

https_loader = AmazonTextractPDFLoader("https://sample-website.com/sample-doc.pdf")https_document = https_loader.load()s3_loader = AmazonTextractPDFLoader("s3://sample-bucket/sample-doc.pdf")s3_document = s3_loader.load()

Вы также можете сохранять документы в Amazon S3 и ссылаться на них с помощью схемы URL s3://, как объясняется в статье Доступ к бакету с помощью S3://, и передавать этот путь S3 в загрузчик PDF-файлов Amazon Textract:

import boto3textract_client = boto3.client('textract', region_name='us-east-2')file_path = "s3://amazon-textract-public-content/langchain/layout-parser-paper.pdf"loader = AmazonTextractPDFLoader(file_path, client=textract_client)documents = loader.load()

Многостраничный документ будет содержать несколько страниц текста, которые затем можно получить через объекты документов, являющиеся списком страниц. Следующий код выполняет цикл по страницам в объекте документов и выводит текст документа, доступный через атрибут page_content:

print(len(documents))for document in documents:    print(document.page_content)

Классификация документов

Amazon Comprehend и LLMs могут быть эффективно использованы для классификации документов. Amazon Comprehend – это сервис обработки естественного языка (NLP), который использует машинное обучение для извлечения информации из текста. Amazon Comprehend также поддерживает обучение пользовательской модели классификации с учетом структуры документов, таких как PDF, Word и изображения. Дополнительную информацию о классификаторе документов Amazon Comprehend см. в статье Классификатор документов Amazon Comprehend добавляет поддержку структуры для повышения точности.

При совмещении с LLM документальная классификация становится мощным подходом для управления большими объемами документов. LLM полезны для классификации документов, потому что они могут анализировать текст, шаблоны и контекстуальные элементы в документе с использованием естественного языкового понимания. Вы также можете настраивать их для конкретных классов документов. Когда в IDP-пайплайн вводится новый тип документа, требующий классификации, LLM может обрабатывать текст и категоризировать документ по заданному набору классов. Приведен ниже образец кода, который использует загрузчик документов LangChain, работающий на базе Amazon Textract, для извлечения текста из документа и его использования для классификации. Мы используем модель Anthropic Claude v2 через Amazon Bedrock для выполнения классификации.

В следующем примере мы сначала извлекаем текст из отчета о выписке пациента, а затем с помощью LLM классифицируем его с помощью списка из трех различных типов документов – DISCHARGE_SUMMARY, RECEIPT и PRESCRIPTION. Ниже показан снимок нашего отчета.

Мы используем следующий код:

from langchain.document_loaders import AmazonTextractPDFLoaderfrom langchain.llms import Bedrockfrom langchain.prompts import PromptTemplatefrom langchain.chains import LLMChainloader = AmazonTextractPDFLoader("./samples/document.png")document = loader.load()template = """Given a list of classes, classify the document into one of these classes. Skip any preamble text and just give the class name.<classes>DISCHARGE_SUMMARY, RECEIPT, PRESCRIPTION</classes><document>{doc_text}<document><classification>"""prompt = PromptTemplate(template=template, input_variables=["doc_text"])bedrock_llm = Bedrock(client=bedrock, model_id="anthropic.claude-v2")llm_chain = LLMChain(prompt=prompt, llm=bedrock_llm)class_name = llm_chain.run(document[0].page_content)print(f"The provided document is = {class_name}")

Код выводит следующий результат:

The provided document is a DISCHARGE_SUMMARY

Суммирование документа

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

Используя тот же отчет о выписке в качестве образца, мы используем AmazonTextractPDFLoader для извлечения текста из этого документа. Как и ранее, мы используем модель Claude v2 через Amazon Bedrock и инициализируем ее с помощью образца, содержащего инструкции о том, что нужно делать с текстом (в данном случае – суммировать). Наконец, мы запускаем цепочку LLM, передавая извлеченный текст из загрузчика документов. Это выполняет действие вывода на LLM с промт, содержащим инструкции для суммирования, и текст документа, отмеченный как Document. См. следующий код:

from langchain.document_loaders import AmazonTextractPDFLoaderfrom langchain.llms import Bedrockfrom langchain.prompts import PromptTemplatefrom langchain.chains import LLMChainloader = AmazonTextractPDFLoader("./samples/discharge-summary.png")document = loader.load()template = """Given a full document, give me a concise summary. Skip any preamble text and just give the summary.<document>{doc_text}</document><summary>"""prompt = PromptTemplate(template=template, input_variables=["doc_text"])bedrock_llm = Bedrock(client=bedrock, model_id="anthropic.claude-v2")num_tokens = bedrock_llm.get_num_tokens(document[0].page_content)print (f"Our prompt has {num_tokens} tokens \n\n=========================\n")llm_chain = LLMChain(prompt=prompt, llm=bedrock_llm)summary = llm_chain.run(document[0].page_content)print(summary.replace("</summary>","").strip())

Код генерирует резюме отчета о выписке пациента:

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

В предыдущем примере использовался одностраничный документ для выполнения резюмирования. Однако, скорее всего, вам придется иметь дело с документами, содержащими несколько страниц, требующих резюмирования. Обычным способом выполнения резюмирования на нескольких страницах является сначала генерация резюме по меньшим частям текста, а затем объединение этих меньших резюме для получения окончательного резюме документа. Обратите внимание, что для этого метода требуется несколько вызовов к LLM. Логика для этого может быть создана легко, однако LangChain предоставляет встроенную цепочку summarize, которая может резюмировать большие тексты (из многостраничных документов). Резюмирование может происходить как с использованием опций map_reduce, так и с использованием опций stuff, которые доступны как опции для управления несколькими вызовами к LLM. В следующем примере мы используем map_reduce для резюмирования многостраничного документа. Ниже приведена иллюстрация нашего рабочего процесса.

Давайте начнем с извлечения документа и узнаем общее количество токенов на каждой странице и общее количество страниц:

from langchain.document_loaders import AmazonTextractPDFLoader from langchain.llms import Bedrock bedrock_llm = Bedrock(client=bedrock, model_id="anthropic.claude-v2") loader = AmazonTextractPDFLoader(f"s3://{data_bucket}/bedrock-sample/health_plan.pdf") document = loader.load() num_docs = len(document) print (f"В документе есть {num_docs} страниц") for index, doc in enumerate(document):     num_tokens_first_doc = bedrock_llm.get_num_tokens(doc.page_content)     print (f"Страница {index+1} содержит примерно {num_tokens_first_doc} токенов")В документе есть 5 страниц Страница 1 содержит примерно 533 токенов Страница 2 содержит примерно 1323 токенов Страница 3 содержит примерно 997 токенов Страница 4 содержит примерно 1643 токенов Страница 5 содержит примерно 867 токенов

Затем мы используем встроенную функцию load_summarize_chain из LangChain, чтобы резюмировать весь документ:

from langchain.chains.summarize import load_summarize_chain summary_chain = load_summarize_chain(llm=bedrock_llm,                     chain_type='map_reduce') output = summary_chain.run(document) print(output.strip())

Стандартизация и вопросы-ответы

В этом разделе мы рассмотрим задачи стандартизации и вопросов-ответов.

Стандартизация

Стандартизация вывода является задачей генерации текста, при которой LLM используется для обеспечения согласованного форматирования выходного текста. Эта задача особенно полезна для автоматизации извлечения ключевых сущностей, требующих, чтобы вывод был согласован с желаемыми форматами. Например, мы можем следовать bewt практикам инженерии подсказок для настройки LLM для форматирования дат в формате MM / DD / YYYY, который совместим с столбцом DATE базы данных. В следующем блоке кода показан пример того, как это делается с использованием LLM и инженерии подсказок. Мы не только стандартизируем формат вывода для значений даты, но также подсказываем модели генерировать окончательный вывод в формате JSON, чтобы его было легко использовать в наших последующих приложениях. Мы используем язык выражений LangChain (LCEL), чтобы объединить два действия. Первое действие подсказывает LLM сгенерировать вывод в формате JSON только для дат из документа. Второе действие принимает JSON-вывод и стандартизирует формат даты. Обратите внимание, что это двухшаговое действие может быть выполнено также в один шаг с правильной инженерией подсказок, как мы увидим в нормализации и шаблонизации.

from langchain.document_loaders import AmazonTextractPDFLoader from langchain.llms import Bedrock from langchain.prompts import PromptTemplate from langchain.chains import LLMChain loader = AmazonTextractPDFLoader("./samples/discharge-summary.png") document = loader.load() bedrock_llm = Bedrock(client=bedrock, model_id="anthropic.claude-v2") template1 = """Дан полный документ, ответьте на вопрос и форматируйте вывод в указанном формате. Пропустите весь вводной текст и просто сгенерируйте JSON.<format>{{ "key_name":"key_value"}}</format><document>{doc_text}</document><question>{question}</question>""" template2 = """Учитывая JSON-документ, отформатируйте даты в полях значений точно в указанном формате. Пропустите весь вводной текст и просто сгенерируйте JSON.<format>DD/MM/YYYY</format><json_document>{json_doc}</json_document>""" prompt1 = PromptTemplate(template=template1, input_variables=["doc_text", "question"]) llm_chain = LLMChain(prompt=prompt1, llm=bedrock_llm, verbose=True) prompt2 = PromptTemplate(template=template2, input_variables=["json_doc"]) llm_chain2 = LLMChain(prompt=prompt2, llm=bedrock_llm, verbose=True) chain = (     llm_chain     | {'json_doc': lambda x: x['text'] }      | llm_chain2) std_op = chain.invoke({ "doc_text": document[0].page_content,                         "question": "Можете ли вы дать мне даты приема пациента и выписки?"}) print(std_op['text']){ "admit_date":"07/09/2020", "discharge_date":"08/09/2020"}

Вывод предыдущего фрагмента кода представляет собой структуру JSON с датами 07/09/2020 и 08/09/2020, которые используют формат DD/MM/YYYY и являются датой приема и выписки пациента из больницы соответственно, согласно отчету об выписке.

Вопросы и ответы с повышенной релевантностью

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

LLMs также могут ограничивать количество токенов из-за ограничений памяти и аппаратного обеспечения, на котором они выполняются. Для решения этой проблемы используются техники, такие как разделение на фрагменты для разделения больших документов на более мелкие части, соответствующие ограничениям токенов LLMs. С другой стороны, в NLP встраивания используются преимущественно для захвата семантического значения слов и их отношений с другими словами в пространстве высокой размерности. Эти встраивания преобразуют слова в векторы, позволяя моделям эффективно обрабатывать и понимать текстовые данные. Понимая семантические нюансы между словами и фразами, встраивания позволяют LLMs генерировать последовательные и контекстуально соответствующие выходы. Обратите внимание на следующие ключевые термины:

  • Разделение на фрагменты – Этот процесс разделяет большие объемы текста из документов на более мелкие, содержательные фрагменты текста.
  • Встраивания – Это фиксированномерные векторные преобразования каждого фрагмента, сохраняющие семантическую информацию из фрагментов. Эти встраивания затем загружаются в векторную базу данных.
  • Векторная база данных – Это база данных векторных встраиваний или векторов, представляющих контекст слов. Она служит источником знаний, который помогает NLP-задачам в обработке документов. Преимущество векторной базы данных в том, что она предоставляет только необходимый контекст LLMs во время генерации текста, как мы объясняем в следующем разделе.

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

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

В этом посте мы используем подход, основанный на RAG, чтобы выполнять вопросно-ответные системы в контексте документов. В следующем фрагменте кода мы извлекаем текст из документа, а затем разбиваем его на мелкие фрагменты текста. Разделение на фрагменты необходимо, потому что у нас могут быть большие многостраничные документы, а у наших LLMs могут быть ограничения на количество токенов. Эти фрагменты затем загружаются в векторную базу данных для выполнения похожего поиска на последующих шагах. В следующем примере мы используем модель Amazon Titan Embed Text v1, которая выполняет векторные встраивания фрагментов документа:

from langchain.text_splitter import RecursiveCharacterTextSplitter from langchain.embeddings import BedrockEmbeddingsfrom langchain.vectorstores import FAISSfrom langchain.document_loaders import AmazonTextractPDFLoaderfrom langchain.chains import RetrievalQAloader = AmazonTextractPDFLoader("amazon_10k.pdf")document = loader.load()text_splitter = RecursiveCharacterTextSplitter(chunk_size=400,                                               separators=["\n\n", "\n", ".", "!", "?", ",", " ", ""],                                               chunk_overlap=0)texts = text_splitter.split_documents(document)embeddings = BedrockEmbeddings(client=bedrock,                               model_id="amazon.titan-embed-text-v1")db = FAISS.from_documents(documents=texts,                           embedding=embeddings) retriever = db.as_retriever(search_type='mmr', search_kwargs={"k": 3})template = """Отвечайте на вопросы как можно более точно, строго используя только предоставленный текст, и если ответ не содержится в тексте, говорите "Не знаю". Пропустите производные текста и рассуждения и дайте только ответ.<text>{context}</text><question>{question}</question><answer>"""# определите шаблонprompt = PromptTemplate(template=template, input_variables=["context","question"])chain_type_kwargs = { "prompt": qa_prompt, "verbose": False } # измените verbose на True, если вы хотите видеть, что происходитbedrock_llm = Bedrock(client=bedrock, model_id="anthropic.claude-v2")qa = RetrievalQA.from_chain_type(    llm=bedrock_llm,     chain_type="stuff",     retriever=retriever,    chain_type_kwargs=chain_type_kwargs,    verbose=False # измените verbose на True, если вы хотите видеть, что происходит)question="Кто является администратором этого плана?"result = qa.run(question)print(result.strip())

Этот код создает соответствующий контекст для LLM, используя фрагменты текста, возвращаемые действием поиска по сходству из векторной базы данных. В этом примере мы используем открытый исходный код FAISS vector store в качестве примера векторной базы данных для хранения векторных вложений каждого фрагмента текста. Затем мы определяем векторную базу данных как LangChain retriever, которая передается в цепочку RetrievalQA. Это внутренне выполняет запрос на поиск сходств в векторной базе данных, который возвращает топ n (где n=3 в нашем примере) фрагментов текста, которые относятся к вопросу. Наконец, LLM выполняется с соответствующим контекстом (группой соответствующих фрагментов текста) и вопросом для ответа LLM. Чтобы получить последовательное пошаговое описание кода Q&A с RAG, обратитесь к блокноту Python на GitHub.

В качестве альтернативы FAISS вы также можете использовать возможности векторной базы данных Amazon OpenSearch Service, Amazon Relational Database Service (Amazon RDS) для PostgreSQL с разширением pgvector или open-source Chroma Database.

Q&A с табличными данными

Обработка табличных данных в документах может быть сложной для LLM из-за своей структурной сложности. Amazon Textract может быть дополнен LLM, так как он позволяет извлекать таблицы из документов во вложенном формате элементов, таких как страница, таблица и ячейки. Выполнение Q&A с табличными данными является многопроцессорным процессом и может быть достигнуто через самостоятельный запрос. Ниже приведен обзор шагов:

  1.  Извлеките таблицы из документов с помощью Amazon Textract. С Amazon Textract можно извлечь структуру таблицы (строки, столбцы, заголовки) из документа.
  2.  Сохраните табличные данные в векторной базе данных вместе с информацией о метаданных, такой как наименования заголовков и описание каждого заголовка.
  3. Используйте подсказку для создания структурированного запроса с использованием LLM для извлечения данных из таблицы.
  4. Используйте запрос для извлечения соответствующих данных таблицы из векторной базы данных.

Например, в банковском выписке, при условии запроса “Какие транзакции с более чем $1000 вкладов”, LLM будет выполнять следующие шаги:

  1. Создайте запрос, например, “Query: transactions” , “filter: greater than (Deposit$)”.
  2. Преобразуйте запрос в структурированный запрос.
  3. Примените структурированный запрос к векторной базе данных, где хранятся наши таблицы.

Для последовательного по шагам обхода исходного кода Q&A с табличными данными обратитесь к блокноту Python в GitHub.

Шаблонизация и нормализация

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

output_template= {    "doctor_name":{ "type": "string", "description": "Полное имя врача или поставщика" },    "provider_id":{ "type": "string", "description": "Идентификатор врача или поставщика" },    "patient_name":{ "type": "string", "description": "Полное имя пациента" },    …}

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

из langchain.llms import Bedrockfrom langchain.prompts import PromptTemplate from langchain.chains import LLMChaintemplate = """Вы - полезный ассистент. Пожалуйста, извлеките следующие детали из документа и отформатируйте вывод в формате JSON с использованием ключей. Пропустите любой предварительный текст и сгенерируйте окончательный ответ.<details>{details}</details><keys>{keys}</keys><document>{doc_text}<document><final_answer>"""details = "\n".join([f"{key}: {value['description']}" for key, value in output_template.items()])keys = "\n".join([f"{key}" for key, value in output_template.items()])prompt = PromptTemplate(template=template, input_variables=["details", "keys", "doc_text"])bedrock_llm = Bedrock(client=bedrock, model_id="anthropic.claude-v2")llm_chain = LLMChain(prompt=prompt, llm=bedrock_llm)output = llm_chain.run({"doc_text": full_text, "details": details, "keys": keys})print(output){  "doctor_name": "Mateo Jackson, Phd",  "provider_id": "XA/7B/00338763",   "patient_name": "John Doe",  … }

Как видите, часть {keys} подсказки представляет собой ключи из нашего шаблона, а {details} – ключи вместе с их описанием. В данном случае мы не подсказываем модель явно с форматом вывода, за исключением указания в инструкции на генерацию вывода в формате JSON. Это работает в большинстве случаев; однако, поскольку вывод от LLM является недетерминированным текстовым формированием, мы хотим указать формат явно как часть инструкции в подсказке. Чтобы решить эту проблему, мы можем использовать модуль structured output parser из LangChain, чтобы воспользоваться автоматизированным созданием подсказок, которое помогает преобразовать наш шаблон в формат инструкции. Мы используем ранее определенный шаблон для создания инструкции по оформлению формата вот так:

from langchain.output_parsers import ResponseSchemafrom langchain.output_parsers import StructuredOutputParserresponse_schems = list()for key, value in output_template.items():    schema = ResponseSchema(name=key, description=value['description'], type=value['type'])    response_schems.append(schema)output_parser = StructuredOutputParser.from_response_schemas(response_schems)format_instructions= output_parser.get_format_instructions()print(format_instructions)

Теперь переменная format_instructions содержит инструкцию по оформлению формата:

Выход должен быть отформатирован как фрагмент кода Markdown в следующей схеме, включая ведущие и замыкающие "```json" и "```":```json{ "doctor_name": string  // Полное имя врача или поставщика    "provider_id": string  // Идентификатор врача или поставщика   "patient_name": string  // Полное имя пациента        …}```

Затем мы используем эту переменную в нашей исходной подсказке в качестве инструкции к Востоку, чтобы он извлекал и форматировал вывод в желаемой схеме, внесите небольшие изменения в подсказку:

template = """Вы - полезный ассистент. Пожалуйста, извлеките следующие детали из документа и строго следуйте инструкциям, описанным в инструкции по форматированию вывода. Пропустите любой предварительный текст и сгенерируйте окончательный ответ. Не создавайте неполный ответ.<details>{details}</details><format_instructions>{format_instructions}</format_instructions><document>{doc_text}<document><final_answer>"""

Пока что мы только извлекли данные из документа в желаемой схеме. Однако нам все еще нужно провести некоторую стандартизацию. Например, мы хотим извлечь дату поступления и дату выписки пациента в формате ДД/ММ/ГГГГ. В этом случае мы дополняем description ключа инструкцией по форматированию:

new_output_template= {       …     "admitted_date":{ "type": "string",  "description": "Дата поступления пациента в больницу, должна быть отформатирована в формате ДД/ММ/ГГГГ." },    "discharge_date":{ "type": "string",  "description": "Дата выписки пациента из больницы, должна быть отформатирована в формате ДД/ММ/ГГГГ."     …}

Прочитайте блокнот Python в GitHub для полного шаг за шагом руководства и объяснения.

Проверка орфографии и коррекции

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

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

Далее приведен плохо написанный образец документа с тем же текстом, как описано ранее.

Извлекаем документ с помощью загрузчика документов Amazon Textract, а затем настраиваем LLM с помощью промпта, чтобы исправить извлеченный текст и исправить ошибки в орфографии и/или грамматике:

from langchain.document_loaders import AmazonTextractPDFLoaderfrom langchain.llms import Bedrockfrom langchain.prompts import PromptTemplatefrom langchain.chains import LLMChainloader = AmazonTextractPDFLoader("./samples/hand_written_note.pdf")document = loader.load()template = """Дан детальный "Документ", выполните проверку орфографии и грамматики. Обеспечить результат когерентный, отлаженный и без ошибок. Пропустите любой вводной текст и дайте ответ.<document>{doc_text}</<document><answer>"""prompt = PromptTemplate(template=template, input_variables=["doc_text"])llm = Bedrock(client=bedrock, model_id="anthropic.claude-v2")llm_chain = LLMChain(prompt=prompt, llm=llm)try:    txt = document[0].page_content    std_op = llm_chain.run({"doc_text": txt})        print("Извлеченный текст")    print("==============")    print(txt)    print("\nИсправленный текст")    print("==============")    print(std_op.strip())    print("\n")except Exception as e:    print(str(e))

Результат предыдущего кода показывает оригинальный текст, извлеченный загрузчиком документов, а затем исправленный текст, сгенерированный LLM:

Извлеченный текст==============Patient John Doe, who was ad mitta with sever pnequonia, has shown Signif i art improumet & can be safely discharged. Follow w/s are scheduled for nen week. Patient John Doe, who was ad mitta with sever pnequonia, has shown Signif i art improumet & can be safely discharged. Follow w/s are scheduled for nen week. Исправленный текст==============Patient John Doe, who was admitted with severe pneumonia, has shown significant improvement and can be safely discharged. Follow-up appointments are scheduled for next week.

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

Заключение

Генеративный ИИ изменяет способ обработки документов с использованием IDP для вывода выводов. В посте Enhancing AWS intelligent document processing with generative AI мы обсудили различные этапы конвейера и как AWS-клиент Ricoh улучшает свой конвейер IDP с помощью LLM. В этом посте мы обсудили различные механизмы дополнения рабочего процесса IDP с помощью LLM с использованием Amazon Bedrock, Amazon Textract и популярного фреймворка LangChain. Вы можете начать работу с новым загрузчиком документов Amazon Textract с помощью LangChain уже сегодня, используя образцовые блокноты, доступные в нашем репозитории GitHub. Для получения дополнительной информации о работе с генеративным ИИ на AWS см. Объявление о новых инструментах для создания решений с использованием генеративного ИИ на AWS.