Удосконалюйте Amazon Lex за допомогою LLM і вдосконалюйте роботу із поширеними запитаннями за допомогою прийому URL-адрес | Веб-сервіси Amazon

Удосконалюйте Amazon Lex за допомогою LLM і вдосконалюйте роботу із поширеними запитаннями за допомогою прийому URL-адрес | Веб-сервіси Amazon

У сучасному цифровому світі більшість споживачів радше знайдуть відповіді на свої запитання щодо обслуговування клієнтів самостійно, а не витрачатимуть час на те, щоб звернутися до компаній та/або постачальників послуг. Ця публікація в блозі досліджує інноваційне рішення для створення чат-бота із запитаннями та відповідями Амазон Лекс який використовує наявні поширені запитання з вашого веб-сайту. Цей інструмент на основі штучного інтелекту може надавати швидкі й точні відповіді на реальні запити, дозволяючи клієнту швидко й легко вирішувати типові проблеми самостійно.

Передача однієї URL-адреси

Багато підприємств опублікували відповіді на поширені запитання для своїх клієнтів, доступні на їхньому веб-сайті. У цьому випадку ми хочемо запропонувати клієнтам чат-бота, який зможе відповісти на їхні запитання з наших опублікованих поширених запитань. У публікації блогу під назвою Удосконалюйте Amazon Lex функціями розмовних поширених запитань за допомогою LLM, ми продемонстрували, як ви можете використовувати комбінацію Amazon Lex і LlamaIndex для створення чат-бота на базі наявних джерел знань, таких як документи PDF або Word. Для підтримки простих поширених запитань на основі веб-сайту поширених запитань нам потрібно створити процес прийому даних, який може сканувати веб-сайт і створювати вбудовування, які LlamaIndex може використовувати для відповідей на запитання клієнтів. У цьому випадку ми будемо спиратися на бота, створеного в попереднє повідомлення в блозі, який запитує ці вбудовування за допомогою висловлювання користувача та повертає відповідь із поширених запитань веб-сайту.

На наступній діаграмі показано, як процес прийому даних і бот Amazon Lex працюють разом для нашого рішення.

Удосконалюйте Amazon Lex за допомогою магістрів права та вдосконалюйте роботу із поширеними запитаннями за допомогою прийому URL-адрес | Amazon Web Services PlatoBlockchain Data Intelligence. Вертикальний пошук. Ai.

У робочому процесі рішення веб-сайт із поширеними запитаннями завантажується через AWS Lambda. Ця функція Lambda сканує веб-сайт і зберігає отриманий текст у файлі Служба простого зберігання Amazon (Amazon S3) відро. Відро S3 потім запускає функцію Lambda, яка використовує LlamaIndex для створення вставок, які зберігаються в Amazon S3. Коли надходить запитання від кінцевого користувача, наприклад «Яка ваша політика повернення?», бот Amazon Lex використовує свою функцію Lambda, щоб запитувати вбудовування за допомогою підходу на основі RAG із LlamaIndex. Щоб отримати додаткові відомості про цей підхід і попередні умови, зверніться до публікації в блозі, Удосконалюйте Amazon Lex функціями розмовних поширених запитань за допомогою LLM.

Після виконання попередніх умов із вищезгаданого блогу, першим кроком є ​​завантаження поширених запитань у сховище документів, яке можна векторизувати та індексувати LlamaIndex. Наступний код показує, як це зробити:

import logging
import sys
import requests
import html2text
from llama_index.readers.schema.base import Document
from llama_index import GPTVectorStoreIndex
from typing import List logging.basicConfig(stream=sys.stdout, level=logging.INFO)
logging.getLogger().addHandler(logging.StreamHandler(stream=sys.stdout)) class EZWebLoader: def __init__(self, default_header: str = None): self._html_to_text_parser = html2text() if default_header is None: self._default_header = {"User-agent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.80 Safari/537.36"} else: self._default_header = default_header def load_data(self, urls: List[str], headers: str = None) -> List[Document]: if headers is None: headers = self._default_header documents = [] for url in urls: response = requests.get(url, headers=headers).text response = self._html2text.html2text(response) documents.append(Document(response)) return documents url = "http://www.zappos.com/general-questions"
loader = EZWebLoader()
documents = loader.load_data([url])
index = GPTVectorStoreIndex.from_documents(documents)

У попередньому прикладі ми беремо попередньо визначену URL-адресу веб-сайту з поширеними запитаннями від Zappos і завантажуємо її за допомогою EZWebLoader клас. За допомогою цього класу ми перейшли до URL-адреси та завантажили всі запитання на сторінці в індекс. Тепер ми можемо поставити запитання на зразок «Чи є у Zappos подарункові картки?» і отримайте відповіді безпосередньо з наших поширених запитань на веб-сайті. На наступному знімку екрана показано тестову консоль бота Amazon Lex, яка відповідає на це запитання з поширених запитань.

Удосконалюйте Amazon Lex за допомогою магістрів права та вдосконалюйте роботу із поширеними запитаннями за допомогою прийому URL-адрес | Amazon Web Services PlatoBlockchain Data Intelligence. Вертикальний пошук. Ai.

Нам вдалося досягти цього, оскільки ми просканували URL-адресу на першому кроці та створили вбудовування, які LlamaIndex міг використовувати для пошуку відповіді на наше запитання. Функція Lambda нашого бота показує, як виконується цей пошук щоразу, коли повертається резервний намір:

import time
import json
import os
import logging
import boto3
from llama_index import StorageContext, load_index_from_storage logger = logging.getLogger()
logger.setLevel(logging.DEBUG) def download_docstore(): # Create an S3 client s3 = boto3.client('s3') # List all objects in the S3 bucket and download each one
try: bucket_name = 'faq-bot-storage-001' s3_response = s3.list_objects_v2(Bucket=bucket_name) if 'Contents' in s3_response: for item in s3_response['Contents']: file_name = item['Key'] logger.debug("Downloading to /tmp/" + file_name) s3.download_file(bucket_name, file_name, '/tmp/' + file_name) logger.debug('All files downloaded from S3 and written to local filesystem.') except Exception as e: logger.error(e)
raise e #download the doc store locally
download_docstore() storage_context = StorageContext.from_defaults(persist_dir="/tmp/")
# load index
index = load_index_from_storage(storage_context)
query_engine = index.as_query_engine() def lambda_handler(event, context): """
Route the incoming request based on intent.
The JSON body of the request is provided in the event slot. """ # By default, treat the user request as coming from the America/New_York time zone. os.environ['TZ'] = 'America/New_York' time.tzset() logger.debug("===== START LEX FULFILLMENT ====") logger.debug(event) slots = {} if "currentIntent" in event and "slots" in event["currentIntent"]: slots = event["currentIntent"]["slots"] intent = event["sessionState"]["intent"] dialogaction = {"type": "Delegate"} message = [] if str.lower(intent["name"]) == "fallbackintent": #execute query from the input given by the user response = str.strip(query_engine.query(event["inputTranscript"]).response) dialogaction["type"] = "Close" message.append({'content': f'{response}', 'contentType': 'PlainText'}) final_response = { "sessionState": { "dialogAction": dialogaction, "intent": intent }, "messages": message } logger.debug(json.dumps(final_response, indent=1)) logger.debug("===== END LEX FULFILLMENT ====") return final_response

Це рішення добре працює, коли на одній веб-сторінці є всі відповіді. Однак більшість сайтів поширених запитань не побудовані на одній сторінці. Наприклад, у нашому прикладі Zappos, якщо ми ставимо запитання «Чи маєте ви політику відповідності цін?», ми отримуємо незадовільну відповідь, як показано на наступному знімку екрана.

Удосконалюйте Amazon Lex за допомогою магістрів права та вдосконалюйте роботу із поширеними запитаннями за допомогою прийому URL-адрес | Amazon Web Services PlatoBlockchain Data Intelligence. Вертикальний пошук. Ai.

У попередній взаємодії відповідь щодо політики відповідності цін не є корисною для нашого користувача. Ця відповідь коротка, оскільки посилання на поширені запитання є посиланням на певну сторінку про політику відповідності цін, а наше веб-сканування стосувалося лише однієї сторінки. Отримання кращих відповідей також означатиме сканування цих посилань. У наступному розділі показано, як отримати відповіді на запитання, які потребують двох або більше рівнів глибини сторінки.

N-рівневий сканування

Коли ми скануємо веб-сторінку в пошуках поширених запитань, інформація, яку ми хочемо, може міститися на пов’язаних сторінках. Наприклад, у нашому прикладі Zappos ми ставимо запитання «Чи є у вас політика відповідності цін?» і відповідь: «Так, будь ласка, відвідайте щоб дізнатися більше». Якщо хтось запитає: «Яка ваша політика відповідності цін?» тоді ми хочемо дати повну відповідь із політикою. Досягнення цього означає, що нам потрібно переходити за посиланнями, щоб отримати фактичну інформацію для нашого кінцевого користувача. Під час процесу прийому даних ми можемо використовувати наш веб-завантажувач, щоб знаходити прив’язки на інші HTML-сторінки, а потім переходити по них. Наступна зміна коду нашого веб-сканера дозволяє нам знаходити посилання на сторінках, які ми скануємо. Він також містить деяку додаткову логіку, щоб уникнути циклічного сканування та дозволити фільтр за префіксом.

import logging
import requests
import html2text
from llama_index.readers.schema.base import Document
from typing import List
import re def find_http_urls_in_parentheses(s: str, prefix: str = None): pattern = r'((https?://[^)]+))' urls = re.findall(pattern, s) matched = [] if prefix is not None: for url in urls: if str(url).startswith(prefix): matched.append(url) else: matched = urls return list(set(matched)) # remove duplicates by converting to set, then convert back to list class EZWebLoader: def __init__(self, default_header: str = None): self._html_to_text_parser = html2text if default_header is None: self._default_header = {"User-agent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.80 Safari/537.36"} else: self._default_header = default_header def load_data(self, urls: List[str], num_levels: int = 0, level_prefix: str = None, headers: str = None) -> List[Document]: logging.info(f"Number of urls: {len(urls)}.") if headers is None: headers = self._default_header documents = [] visited = {} for url in urls: q = [url] depth = num_levels for page in q: if page not in visited: #prevent cycles by checking to see if we already crawled a link logging.info(f"Crawling {page}") visited[page] = True #add entry to visited to prevent re-crawling pages response = requests.get(page, headers=headers).text response = self._html_to_text_parser.html2text(response) #reduce html to text documents.append(Document(response)) if depth > 0: #crawl linked pages ingest_urls = find_http_urls_in_parentheses(response, level_prefix) logging.info(f"Found {len(ingest_urls)} pages to crawl.") q.extend(ingest_urls) depth -= 1 #reduce the depth counter so we go only num_levels deep in our crawl else: logging.info(f"Skipping {page} as it has already been crawled") logging.info(f"Number of documents: {len(documents)}.") return documents url = "http://www.zappos.com/general-questions"
loader = EZWebLoader()
#crawl the site with 1 level depth and prefix of "/c/" for customer service root
documents = loader.load_data([url], num_levels=1, level_prefix="https://www.zappos.com/c/")
index = GPTVectorStoreIndex.from_documents(documents)

У попередньому коді ми представили можливість сканувати N рівнів глибини та надали префікс, який дозволяє нам обмежити сканування лише речами, які починаються з певного шаблону URL-адреси. У нашому прикладі Zappos усі сторінки обслуговування клієнтів ґрунтуються zappos.com/c, тому ми включаємо це як префікс, щоб обмежити наше сканування меншою та релевантнішою підмножиною. Код показує, як ми можемо заглиблювати до двох рівнів. Логіка Lambda нашого бота залишається незмінною, оскільки нічого не змінилося, за винятком того, що сканер завантажує більше документів.

Зараз у нас є всі документи проіндексовані, і ми можемо поставити більш детальне запитання. На наступному скріншоті наш бот дає правильну відповідь на запитання «Чи є у вас політика відповідності цін?»

Удосконалюйте Amazon Lex за допомогою магістрів права та вдосконалюйте роботу із поширеними запитаннями за допомогою прийому URL-адрес | Amazon Web Services PlatoBlockchain Data Intelligence. Вертикальний пошук. Ai.

Тепер ми маємо вичерпну відповідь на наше запитання щодо відповідності цін. Замість того, щоб просто сказати «Так, дивіться нашу політику», він надає нам деталі сканування другого рівня.

Прибирати

Щоб уникнути майбутніх витрат, видаліть усі ресурси, які були розгорнуті в рамках цієї вправи. Ми надали сценарій для витонченого завершення роботи кінцевої точки Sagemaker. Деталі використання знаходяться в README. Крім того, щоб видалити всі інші ресурси, які ви можете запустити cdk destroy у тому ж каталозі, що й інші команди cdk, щоб деініціалізувати всі ресурси у вашому стеку.

Висновок

Можливість завантажувати набір поширених запитань у чат-бот дає змогу вашим клієнтам знаходити відповіді на свої запитання за допомогою простих запитів природною мовою. Об’єднавши вбудовану підтримку в Amazon Lex для резервної обробки з рішенням RAG, таким як LlamaIndex, ми можемо надати нашим клієнтам швидкий шлях до отримання задовольняючих, підібраних і затверджених відповідей на поширені запитання. Застосувавши N-рівневе сканування в нашому рішенні, ми можемо дозволити відповіді, які, можливо, охоплюватимуть кілька посилань на поширені запитання та надавати глибші відповіді на запити наших клієнтів. Дотримуючись цих кроків, ви зможете безперешкодно включити потужні можливості Q і A на основі LLM та ефективне введення URL-адрес у свій чат-бот Amazon Lex. Це призводить до більш точної, комплексної взаємодії з користувачами з урахуванням контексту.


Про авторів

Удосконалюйте Amazon Lex за допомогою магістрів права та вдосконалюйте роботу із поширеними запитаннями за допомогою прийому URL-адрес | Amazon Web Services PlatoBlockchain Data Intelligence. Вертикальний пошук. Ai.Макс Хенкель-Воллес є інженером з розробки програмного забезпечення в AWS Lex. Йому подобається працювати, використовуючи технології для досягнення максимального успіху клієнтів. Поза роботою він захоплюється кулінарією, проводить час з друзями та подорожує з рюкзаком.

Удосконалюйте Amazon Lex за допомогою магістрів права та вдосконалюйте роботу із поширеними запитаннями за допомогою прийому URL-адрес | Amazon Web Services PlatoBlockchain Data Intelligence. Вертикальний пошук. Ai.Сонг Фен є старшим науковим співробітником AWS AI Labs, який спеціалізується на обробці природної мови та штучному інтелекті. Її дослідження вивчає різні аспекти цих сфер, включаючи моделювання діалогів, заснованих на документах, міркування для діалогів, орієнтованих на завдання, та створення інтерактивного тексту з використанням мультимодальних даних.

Удосконалюйте Amazon Lex за допомогою магістрів права та вдосконалюйте роботу із поширеними запитаннями за допомогою прийому URL-адрес | Amazon Web Services PlatoBlockchain Data Intelligence. Вертикальний пошук. Ai.Джон Бейкер є головним SDE в AWS, де він працює над обробкою природної мови, моделями великих мов та іншими проектами, пов’язаними з ML/AI. Він працює в Amazon понад 9 років і працював у AWS, Alexa та Amazon.com. У вільний час Джон любить кататися на лижах та займатися іншими видами активного відпочинку на північному заході Тихого океану.

Часова мітка:

Більше від AWS Машинне навчання