Izboljšajte Amazon Lex z LLM-ji in izboljšajte izkušnjo s pogostimi vprašanji z vnosom URL-jev | Spletne storitve Amazon

Izboljšajte Amazon Lex z LLM-ji in izboljšajte izkušnjo s pogostimi vprašanji z vnosom URL-jev | Spletne storitve Amazon

V današnjem digitalnem svetu bi večina potrošnikov raje sama poiskala odgovore na svoja vprašanja o storitvah za stranke, kot da bi si vzeli čas in se obrnili na podjetja in/ali ponudnike storitev. Ta objava v spletnem dnevniku raziskuje inovativno rešitev za ustvarjanje chatbota za vprašanja in odgovore Amazon Lex ki uporablja obstoječa pogosta vprašanja z vašega spletnega mesta. To orodje, ki ga poganja AI, lahko zagotovi hitre in natančne odgovore na poizvedbe iz resničnega sveta, kar stranki omogoča hitro in preprosto neodvisno reševanje običajnih težav.

Zaužitje enega URL-ja

Mnoga podjetja imajo na svojem spletnem mestu objavljene odgovore na pogosta vprašanja za svoje stranke. V tem primeru želimo strankam ponuditi chatbota, ki lahko odgovori na njihova vprašanja iz naših objavljenih pogostih vprašanj. V objavi na blogu z naslovom Izboljšajte Amazon Lex s pogovornimi funkcijami pogostih vprašanj z uporabo LLM, smo pokazali, kako lahko uporabite kombinacijo Amazon Lex in LlamaIndex za izgradnjo chatbota, ki ga poganjajo vaši obstoječi viri znanja, kot so dokumenti PDF ali Word. Za podporo preprostih pogostih vprašanj, ki temeljijo na spletnem mestu s pogostimi vprašanji, moramo ustvariti postopek vnosa, ki lahko pajka po spletnem mestu in ustvari vdelave, ki jih lahko LlamaIndex uporabi za odgovore na vprašanja strank. V tem primeru bomo gradili na botu, ustvarjenem v prejšnja objava bloga, ki poizveduje po teh vdelavah z uporabnikovo izjavo in vrne odgovor iz pogostih vprašanj na spletnem mestu.

Naslednji diagram prikazuje, kako postopek vnosa in bot Amazon Lex sodelujeta pri naši rešitvi.

Enhance Amazon Lex with LLMs and improve the FAQ experience using URL ingestion | Amazon Web Services PlatoBlockchain Data Intelligence. Vertical Search. Ai.

V delovnem toku rešitve je spletno mesto s pogostimi vprašanji zaužito prek AWS Lambda. Ta funkcija Lambda pajka po spletnem mestu in shrani nastalo besedilo v Preprosta storitev shranjevanja Amazon (Amazon S3) vedro. Vedro S3 nato sproži funkcijo Lambda, ki uporablja LlamaIndex za ustvarjanje vdelav, ki so shranjene v Amazon S3. Ko prispe vprašanje končnega uporabnika, na primer »Kakšna je vaša politika vračanja?«, bot Amazon Lex uporabi svojo funkcijo Lambda za poizvedovanje po vdelavah z uporabo pristopa, ki temelji na RAG, z LlamaIndex. Za več informacij o tem pristopu in predpogojih si oglejte objavo v spletnem dnevniku, Izboljšajte Amazon Lex s pogovornimi funkcijami pogostih vprašanj z uporabo LLM.

Ko so predpogoji iz zgoraj omenjenega spletnega dnevnika izpolnjeni, je prvi korak vnos pogostih vprašanj v repozitorij dokumentov, ki ga lahko vektorizira in indeksira LlamaIndex. Naslednja koda prikazuje, kako to doseči:

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)

V prejšnjem primeru od Zapposa vzamemo vnaprej določen URL spletnega mesta s pogostimi vprašanji in ga zaužijemo z EZWebLoader razred. S tem razredom smo se pomaknili do URL-ja in naložili vsa vprašanja, ki so na strani, v indeks. Zdaj lahko postavimo vprašanje, kot je "Ali ima Zappos darilne kartice?" in dobite odgovore neposredno iz naših pogostih vprašanj na spletnem mestu. Naslednji posnetek zaslona prikazuje preskusno konzolo bota Amazon Lex, ki odgovarja na to vprašanje iz pogostih vprašanj.

Enhance Amazon Lex with LLMs and improve the FAQ experience using URL ingestion | Amazon Web Services PlatoBlockchain Data Intelligence. Vertical Search. Ai.

To nam je uspelo, ker smo v prvem koraku preiskali URL in ustvarili vdelave, ki jih je LlamaIndex lahko uporabil za iskanje odgovora na naše vprašanje. Funkcija Lambda našega bota prikazuje, kako poteka to iskanje, kadar koli je vrnjen nadomestni namen:

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

Ta rešitev deluje dobro, če ima ena sama spletna stran vse odgovore. Vendar pa večina spletnih mest s pogostimi vprašanji ni zgrajena na eni strani. Če na primer v našem primeru Zappos postavimo vprašanje »Ali imate politiko ujemanja cen?«, dobimo odgovor, ki ni zadovoljiv, kot je prikazano na naslednjem posnetku zaslona.

Enhance Amazon Lex with LLMs and improve the FAQ experience using URL ingestion | Amazon Web Services PlatoBlockchain Data Intelligence. Vertical Search. Ai.

V prejšnji interakciji odgovor o politiki ujemanja cen našemu uporabniku ni v pomoč. Ta odgovor je kratek, ker je navedena pogosta vprašanja povezava do določene strani o politiki ujemanja cen, naše spletno iskanje pa je bilo samo za eno stran. Doseganje boljših odgovorov bo pomenilo tudi iskanje po teh povezavah. Naslednji razdelek prikazuje, kako dobiti odgovore na vprašanja, ki zahtevajo dve ali več ravni globine strani.

Plazenje na ravni N

Ko indeksiramo spletno stran za znanje o pogostih vprašanjih, so lahko informacije, ki jih želimo, vsebovane na povezanih straneh. Na primer, v našem primeru Zappos postavimo vprašanje "Ali imate politiko ujemanja cen?" in odgovor je »Da, obiščite izvedeti več." Če nekdo vpraša "Kakšna je vaša politika ujemanja cen?" potem želimo podati popoln odgovor s pravilnikom. Če to dosežemo, pomeni, da moramo prečkati povezave, da dobimo dejanske informacije za našega končnega uporabnika. Med postopkom vnosa lahko uporabimo naš spletni nalagalnik, da poiščemo sidrne povezave do drugih strani HTML in jih nato prečkamo. Naslednja sprememba kode našega spletnega pajka nam omogoča iskanje povezav na straneh, ki jih indeksiramo. Vključuje tudi nekaj dodatne logike za preprečevanje krožnega pajkanja in omogočanje filtra s predpono.

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)

V prejšnji kodi uvajamo možnost pajkanja N ravni globoko in dajemo predpono, ki nam omogoča, da pajkanje omejimo samo na stvari, ki se začnejo z določenim vzorcem URL-ja. V našem primeru Zappos so vse strani s storitvami za stranke izkoreninjene zappos.com/c, zato to vključimo kot predpono, da omejimo iskanje po vsebini na manjšo in ustreznejšo podmnožico. Koda prikazuje, kako lahko zaužijemo do dve ravni globoko. Logika Lambda našega bota ostaja enaka, ker se ni nič spremenilo, le da pajek zaužije več dokumentov.

Zdaj imamo vse dokumente indeksirane in lahko postavimo podrobnejše vprašanje. Na naslednjem posnetku zaslona naš bot ponuja pravilen odgovor na vprašanje "Ali imate politiko ujemanja cen?"

Enhance Amazon Lex with LLMs and improve the FAQ experience using URL ingestion | Amazon Web Services PlatoBlockchain Data Intelligence. Vertical Search. Ai.

Zdaj imamo popoln odgovor na naše vprašanje o ujemanju cen. Namesto da bi nam preprosto povedali »Da, glejte naš pravilnik«, nam posreduje podrobnosti iz pajkanja na drugi ravni.

Čiščenje

Da se izognete prihodnjim stroškom, nadaljujte z brisanjem vseh virov, ki so bili razporejeni kot del te vaje. Zagotovili smo skript za elegantno zaustavitev končne točke Sagemaker. Podrobnosti o uporabi so v README. Poleg tega, da odstranite vse druge vire, ki jih lahko zaženete cdk destroy v istem imeniku kot drugi ukazi cdk za razveljavitev vseh virov v vašem skladu.

zaključek

Zmožnost vnosa nabora pogostih vprašanj v klepetalni robot omogoča vašim strankam, da najdejo odgovore na svoja vprašanja z enostavnimi poizvedbami v naravnem jeziku. S kombinacijo vgrajene podpore v Amazon Lex za nadomestno obravnavo z rešitvijo RAG, kot je LlamaIndex, lahko našim strankam zagotovimo hitro pot do zadovoljivih, izbranih in odobrenih odgovorov na pogosta vprašanja. Če v naši rešitvi uporabimo pajkanje na ravni N, lahko omogočimo odgovore, ki bi morda lahko obsegali več povezav s pogostimi vprašanji, in zagotovili globlje odgovore na poizvedbe naših strank. Če sledite tem korakom, lahko brezhibno vključite zmogljive zmožnosti Q in A, ki temeljijo na LLM, ter učinkovito vnos URL-jev v vaš klepetalni robot Amazon Lex. Posledica tega so natančnejše, celovitejše in kontekstualno ozaveščene interakcije z uporabniki.


O avtorjih

Enhance Amazon Lex with LLMs and improve the FAQ experience using URL ingestion | Amazon Web Services PlatoBlockchain Data Intelligence. Vertical Search. Ai.Max Henkel-Wallace je inženir za razvoj programske opreme pri AWS Lex. Uživa v izkoriščanju tehnologije za čim večji uspeh strank. Zunaj službe ga navdušuje kuhanje, preživljanje časa s prijatelji in potovanje z nahrbtnikom.

Enhance Amazon Lex with LLMs and improve the FAQ experience using URL ingestion | Amazon Web Services PlatoBlockchain Data Intelligence. Vertical Search. Ai.Song Feng je višji aplikativni znanstvenik pri AWS AI Labs, specializiran za obdelavo naravnega jezika in umetno inteligenco. Njena raziskava raziskuje različne vidike teh področij, vključno z modeliranjem dialoga, ki temelji na dokumentih, razmišljanjem o dialogih, usmerjenih v naloge, in interaktivnim ustvarjanjem besedila z uporabo multimodalnih podatkov.

Enhance Amazon Lex with LLMs and improve the FAQ experience using URL ingestion | Amazon Web Services PlatoBlockchain Data Intelligence. Vertical Search. Ai.John Baker je glavni SDE pri AWS, kjer se ukvarja z obdelavo naravnega jezika, velikimi jezikovnimi modeli in drugimi projekti, povezanimi z ML/AI. Z Amazonom je zaposlen več kot 9 let in je delal v AWS, Alexa in Amazon.com. V prostem času John uživa v smučanju in drugih dejavnostih na prostem po celotnem pacifiškem severozahodu.

Časovni žig:

Več od Strojno učenje AWS