Generatywna analiza danych

Zbuduj solidne rozwiązanie zamiany tekstu na SQL, generujące złożone zapytania, samokorygujące i wysyłające zapytania do różnych źródeł danych | Usługi internetowe Amazona

Data:

Structured Query Language (SQL) to złożony język, który wymaga zrozumienia baz danych i metadanych. Dzisiaj, generatywna sztuczna inteligencja może pomóc osobom bez znajomości języka SQL. To generatywne zadanie AI nosi nazwę Text-to-SQL i generuje zapytania SQL na podstawie przetwarzania języka naturalnego (NLP) i konwertuje tekst na poprawny semantycznie kod SQL. Rozwiązanie przedstawione w tym poście ma na celu wyniesienie działań analityki korporacyjnej na wyższy poziom poprzez skrócenie ścieżki do danych przy użyciu języka naturalnego.

Wraz z pojawieniem się dużych modeli językowych (LLM), generowanie SQL oparte na NLP przeszło znaczącą transformację. Wykazując wyjątkową wydajność, LLM są teraz w stanie generować dokładne zapytania SQL na podstawie opisów w języku naturalnym. Jednak wyzwania nadal pozostają. Po pierwsze, język ludzki jest z natury niejednoznaczny i zależny od kontekstu, podczas gdy SQL jest precyzyjny, matematyczny i uporządkowany. Ta luka może skutkować niedokładną konwersją potrzeb użytkownika na wygenerowany kod SQL. Po drugie, może być konieczne zbudowanie funkcji zamiany tekstu na SQL dla każdej bazy danych, ponieważ dane często nie są przechowywane w jednym miejscu docelowym. Konieczne może być odtworzenie możliwości każdej bazy danych, aby umożliwić użytkownikom generowanie kodu SQL w oparciu o NLP. Po trzecie, pomimo szerszego zastosowania scentralizowanych rozwiązań analitycznych, takich jak jeziora danych i hurtownie, złożoność wzrasta wraz z różnymi nazwami tabel i innymi metadanymi wymaganymi do utworzenia kodu SQL dla żądanych źródeł. Dlatego też gromadzenie kompleksowych i wysokiej jakości metadanych również pozostaje wyzwaniem. Aby dowiedzieć się więcej o najlepszych praktykach i wzorcach projektowych zamiany tekstu na SQL, zobacz Generowanie wartości z danych przedsiębiorstwa: najlepsze praktyki dotyczące Text2SQL i generatywnej sztucznej inteligencji.

Nasze rozwiązanie ma na celu sprostanie tym wyzwaniom związanym z wykorzystaniem Amazońska skała macierzysta i Usługi analityczne AWS. Używamy Antropiczny Claude v2.1 na Amazon Bedrock jako nasz LLM. Aby sprostać tym wyzwaniom, nasze rozwiązanie najpierw uwzględnia metadane źródeł danych w pliku Katalog danych kleju AWS w celu zwiększenia dokładności generowanego zapytania SQL. Przepływ pracy obejmuje również pętlę końcowej oceny i korekty, na wypadek zidentyfikowania jakichkolwiek problemów SQL Amazonka Atena, który jest używany jako silnik SQL. Atena pozwala nam także korzystać z mnóstwa obsługiwane punkty końcowe i łączniki aby objąć duży zestaw źródeł danych.

Po przejściu przez kolejne etapy budowania rozwiązania przedstawiamy wyniki niektórych scenariuszy testowych o różnym poziomie złożoności SQL. Na koniec omówimy, jak łatwo można włączyć różne źródła danych do zapytań SQL.

Omówienie rozwiązania

Nasza architektura obejmuje trzy krytyczne komponenty: generację rozszerzoną pobierania (RAG) z metadanymi bazy danych, wieloetapową pętlę samokorekty oraz technologię Athena jako nasz silnik SQL.

Używamy metody RAG do pobierania opisów tabel i opisów schematów (kolumn) z metastore AWS Glue, aby mieć pewność, że żądanie jest powiązane z właściwą tabelą i zbiorami danych. W naszym rozwiązaniu zbudowaliśmy poszczególne kroki umożliwiające uruchomienie frameworku RAG z katalogiem danych kleju AWS w celach demonstracyjnych. Można jednak również skorzystać bazy wiedzy w Amazon Bedrock, aby szybko tworzyć rozwiązania RAG.

Komponent wieloetapowy pozwala LLM poprawić wygenerowane zapytanie SQL pod kątem dokładności. Tutaj wygenerowany kod SQL jest wysyłany w przypadku błędów składniowych. Używamy komunikatów o błędach Athena, aby wzbogacić nasze monity o LLM w celu uzyskania dokładniejszych i skuteczniejszych poprawek w wygenerowanym SQL.

Komunikaty o błędach pojawiające się czasami od usługi Athena można traktować jako informację zwrotną. Konsekwencje kosztowe etapu korekcji błędów są znikome w porównaniu z dostarczoną wartością. Możesz nawet uwzględnić te kroki naprawcze jako przykłady wzmocnionego uczenia się pod nadzorem, aby dostroić swoje LLM. Jednak dla uproszczenia nie omówiliśmy tego przepływu w naszym poście.

Należy pamiętać, że zawsze istnieje ryzyko wystąpienia niedokładności, które naturalnie wiąże się z generatywnymi rozwiązaniami AI. Nawet jeśli komunikaty o błędach Athena są bardzo skuteczne w ograniczaniu tego ryzyka, możesz dodać więcej kontroli i widoków, takich jak opinie ludzi lub przykładowe zapytania w celu dostrojenia, aby jeszcze bardziej zminimalizować takie ryzyko.

Athena nie tylko pozwala nam korygować zapytania SQL, ale także upraszcza dla nas ogólny problem, ponieważ służy jako hub, w którym szprychy stanowią wiele źródeł danych. Zarządzanie dostępem, składnia SQL i inne funkcje są obsługiwane przez Athenę.

Poniższy schemat ilustruje architekturę rozwiązania.

Pokazano architekturę rozwiązania i przebieg procesu.

Rysunek 1. Architektura rozwiązania i przebieg procesów.

Przebieg procesu obejmuje następujące kroki:

  1. Utwórz katalog danych kleju AWS za pomocą robota AWS Glue (lub inną metodą).
  2. Korzystanie z Model Titan-Text-Embeddings na Amazon Bedrock, przekonwertuj metadane na elementy osadzone i zapisz je w pliku Amazon OpenSearch bez serwera sklep wektorowy, który służy jako nasza baza wiedzy w ramach naszego RAG.

Na tym etapie proces jest gotowy na przyjęcie zapytania w języku naturalnym. Kroki 7–9 przedstawiają pętlę korekcyjną, jeśli ma to zastosowanie.

  1. Użytkownik wprowadza zapytanie w języku naturalnym. Interfejs czatu można udostępnić za pomocą dowolnej aplikacji internetowej. Dlatego w naszym poście nie omówiliśmy szczegółów interfejsu użytkownika.
  2. Rozwiązanie wykorzystuje framework RAG poprzez wyszukiwanie podobieństw, który dodaje dodatkowy kontekst z metadanych z bazy danych wektorów. Ta tabela służy do znajdowania właściwej tabeli, bazy danych i atrybutów.
  3. Zapytanie jest łączone z kontekstem i wysyłane do Antropiczny Claude v2.1 na Amazon Bedrock.
  4. Model pobiera wygenerowane zapytanie SQL i łączy się z usługą Athena w celu sprawdzenia poprawności składni.
  5. Jeśli usługa Athena wyświetli komunikat o błędzie informujący, że składnia jest nieprawidłowa, w modelu zostanie użyty tekst błędu z odpowiedzi Ateny.
  6. Nowy monit dodaje odpowiedź Ateny.
  7. Model tworzy poprawiony kod SQL i kontynuuje proces. Iterację tę można wykonać wielokrotnie.
  8. Na koniec uruchamiamy SQL za pomocą Atheny i generujemy dane wyjściowe. Tutaj dane wyjściowe są prezentowane użytkownikowi. Ze względu na prostotę architektoniczną nie pokazaliśmy tego kroku.

Wymagania wstępne

W przypadku tego stanowiska należy spełnić następujące wymagania wstępne:

  1. mieć Konto AWS.
  2. Zainstalować dotychczasowy Interfejs wiersza poleceń AWS (interfejs wiersza poleceń AWS).
  3. Skonfiguruj SDK dla Pythona (Boto3).
  4. Utwórz katalog danych kleju AWS za pomocą robota AWS Glue (lub inną metodą).
  5. Korzystanie z Model Titan-Text-Embeddings na Amazon Bedrock, przekonwertuj metadane na elementy osadzone i przechowuj je w systemie OpenSearch Serverless sklep wektorowy.

Zaimplementuj rozwiązanie

Możesz użyć następujących Notatnik Jupyter, który zawiera wszystkie fragmenty kodu podane w tej sekcji, umożliwiające skompilowanie rozwiązania. Zalecamy użycie Studio Amazon SageMaker aby otworzyć ten notatnik za pomocą instancji ml.t3.medium z jądrem Python 3 (Data Science). Aby uzyskać instrukcje, zobacz Trenuj model uczenia maszynowego. Wykonaj następujące kroki, aby skonfigurować rozwiązanie:

  1. Utwórz bazę wiedzy w usłudze OpenSearch Service dla frameworka RAG:
    def add_documnets(self,index_name: str,file_name:str):
    
    documents = JSONLoader(file_path=file_name, jq_schema='.', text_content=False, json_lines=False).load()
    docs = OpenSearchVectorSearch.from_documents(embedding=self.embeddings, opensearch_url=self.opensearch_domain_endpoint, http_auth=self.http_auth, documents=documents, index_name=index_name, engine="faiss")
    index_exists = self.check_if_index_exists(index_name,aws_region,opensearch_domain_endpoint,http_auth)
    if not index_exists :
    logger.info(f'index :{index_name} is not existing ')
    sys.exit(-1)
    else:
    logger.info(f'index :{index_name} Got created')

  2. Zbuduj zachętę (final_question) poprzez połączenie danych wprowadzanych przez użytkownika w języku naturalnym (user_query), odpowiednie metadane z magazynu wektorów (vector_search_match) i nasze instrukcje (details):
    def userinput(user_query):
    logger.info(f'Searching metadata from vector store')
    
    # vector_search_match=rqst.getEmbeddding(user_query)
    vector_search_match = rqst.getOpenSearchEmbedding(index_name,user_query)
    
    # print(vector_search_match)
    details = "It is important that the SQL query complies with Athena syntax. 
    During join if column name are same please use alias ex llm.customer_id 
    in select statement. It is also important to respect the type of columns: 
    if a column is string, the value should be enclosed in quotes. 
    If you are writing CTEs then include all the required columns. 
    While concatenating a non string column, make sure cast the column to string. 
    For date columns comparing to string , please cast the string input."
    final_question = "nnHuman:"+details + vector_search_match + user_query+ "nnAssistant:"
    answer = rqst.generate_sql(final_question)
    return answer

  3. Wywołaj Amazon Bedrock dla LLM (Claude v2) i poproś go o wygenerowanie zapytania SQL. W poniższym kodzie podejmuje wiele prób w celu zilustrowania kroku samokorekty:x
    try:
    logger.info(f'we are in Try block to generate the sql and count is :{attempt + 1}')
    generated_sql = self.llm.predict(prompt)
    query_str = generated_sql.split("```")[1]
    query_str = " ".join(query_str.split("n")).strip()
    sql_query = query_str[3:] if query_str.startswith("sql") else query_str
    
    # return sql_query
    syntaxcheckmsg=rqstath.syntax_checker(sql_query)
    if syntaxcheckmsg=='Passed':
    logger.info(f'syntax checked for query passed in attempt number :{attempt + 1}')
    return sql_query

  4. Jeśli pojawią się jakiekolwiek problemy z wygenerowanym zapytaniem SQL ({sqlgenerated}) z odpowiedzi Ateny ({syntaxcheckmsg}), nowy monit (prompt) jest generowany na podstawie odpowiedzi, a model ponownie próbuje wygenerować nowy kod SQL:
    else:
    prompt = f"""{prompt} 
    This is syntax error: {syntaxcheckmsg}.
    To correct this, please generate an alternative SQL query which will correct the syntax error. The updated query should take care of all the syntax issues encountered. Follow the instructions mentioned above to remediate the error.
    Update the below SQL query to resolve the issue:
    {sqlgenerated}
    Make sure the updated SQL query aligns with the requirements provided in the initial question."""
    prompts.append(prompt)

  5. Po wygenerowaniu kodu SQL wywoływany jest klient Athena w celu uruchomienia i wygenerowania danych wyjściowych:
    query_execution = self.athena_client.start_query_execution(
    QueryString=query_string,
    ResultConfiguration=result_config,
    QueryExecutionContext=query_execution_context, )
    execution_id = query_execution["QueryExecutionId"]

Przetestuj rozwiązanie

W tej sekcji uruchamiamy nasze rozwiązanie z różnymi przykładowymi scenariuszami, aby przetestować różne poziomy złożoności zapytań SQL.

Aby przetestować naszą zamianę tekstu na SQL, używamy dwóch zbiory danych dostępne w IMDB. Podzbiory danych IMDb są dostępne do użytku osobistego i niekomercyjnego. Możesz pobrać zbiory danych i przechowywać je Usługa Amazon Simple Storage (Amazon S3). Możesz użyć następującego fragmentu kodu Spark SQL, aby utworzyć tabele w AWS Glue. W tym przykładzie używamy title_ratings i title:

source_title_ratings3_path = 's3://llm-athena-output/input_data/title.ratings.tsv'
target_title_s3_path='s3://llm-athena-output/output_data/imdb_stg/title_ratings'
source_titleratingdf=spark.read.csv(source_title_ratings3_path,sep="t",header=True)
source_titleratingdf.write.mode('overwrite').format('parquet').option('path', target_title_s3_path).saveAsTable('imdb_stg.title_ratings')

Przechowuj dane w Amazon S3 i metadane w AWS Glue

W tym scenariuszu nasz zbiór danych jest przechowywany w zasobniku S3. Athena posiada złącze S3, które umożliwia wykorzystanie Amazon S3 jako źródła danych, z którego można odpytywać.

W przypadku naszego pierwszego zapytania podajemy dane wejściowe „Jestem w tym nowy. Czy możesz mi pomóc zobaczyć wszystkie tabele i kolumny w schemacie imdb?”

Poniżej znajduje się wygenerowane zapytanie:

WITH tables AS (
SELECT table_name
FROM information_schema.tables
WHERE table_schema = 'imdb_stg'),
columns AS (
SELECT
c.table_name,
c.column_name,
c.data_type,
c.is_nullable,
c.column_default,
c.ordinal_position
FROM information_schema.columns c
WHERE c.table_schema = 'imdb_stg')
SELECT
t.table_name,
c.column_name,
c.data_type,
c.is_nullable,
c.column_default,
c.ordinal_position
FROM tables t
INNER JOIN columns c
ON t.table_name = c.table_name
ORDER BY
t.table_name,
c.ordinal_position
LIMIT 10;

Poniższy zrzut ekranu i kod przedstawiają nasze dane wyjściowe.

Tabela przedstawiająca atrybuty przykładowego zbioru danych IMBD.

table_name column_name data_type
0 title titleid varchar
1 title ordering integer
2 title title varchar
3 title region varchar
4 title language varchar

W przypadku drugiego zapytania prosimy „Pokaż mi cały tytuł i szczegóły w regionie USA, którego ocena jest większa niż 9.5”.

Oto nasze wygenerowane zapytanie:

WITH us_titles AS (
SELECT t.title, t.region, tr.averageRating, tr.numVotes
FROM imdb_stg.title t
INNER JOIN imdb_stg.title_ratings tr
ON t.titleId = tr.tconst
WHERE t.region = 'US' AND cast(tr.averageRating as varchar) > '9.5'
)
SELECT title, region, averageRating, numVotes
FROM us_titles
LIMIT 100;

Odpowiedź jest następująca.

Tabela pokazująca wyniki zapytania sql

title region averageRating numVotes
0 The Way You Saw Me US 9.7 8
1 The Brother Side of the Wake US 9.6 20
2 Ignis Fatuus US 9.6 11
3 Love and Hip Hop Atlanta US 9.9 11
4 ronny/lily US 9.7 14781

W trzecim zapytaniu wpisujemy „Świetna odpowiedź! Teraz pokaż mi wszystkie tytuły typu oryginalnego, które mają ocenę wyższą niż 7.5 i nie pochodzą z regionu USA.

Generowane jest następujące zapytanie:

WITH titles AS (
SELECT t.titleId,
t.title,
t.types,
t.isOriginalTitle,
cast(tr.averageRating as decimal(3,1)) as averageRating,
tr.numVotes,
t.region
FROM imdb_stg.title t
INNER JOIN imdb_stg.title_ratings tr
ON t.titleId = tr.tconst
WHERE t.isOriginalTitle = '1'
AND cast(tr.averageRating as decimal(3,1)) > 7.5
AND t.region != 'US')
SELECT *
FROM titles
LIMIT 100;

Otrzymujemy następujące wyniki.

Pojedynczy wiersz pokazujący wynik zapytania SQL.

titleId title types isOriginalTitle averageRating numVotes region
0 tt0986264 Taare Zameen Par original 1 8.3 203760 XWW

Wygeneruj samodzielnie poprawiony kod SQL

Ten scenariusz symuluje zapytanie SQL, które ma problemy ze składnią. W tym przypadku wygenerowany kod SQL zostanie automatycznie poprawiony na podstawie odpowiedzi z usługi Athena. W poniższej odpowiedzi Atena dała COLUMN_NOT_FOUND błąd i wspomniałem o tym table_description nie można rozwiązać:

Status : {'State': 'FAILED', 'StateChangeReason': "COLUMN_NOT_FOUND: line 1:50: Column 'table_description' 
cannot be resolved or requester is not authorized to access requested resources",
'SubmissionDateTime': datetime.datetime(2024, 1, 14, 14, 38, 57, 501000, tzinfo=tzlocal()),
'CompletionDateTime': datetime.datetime(2024, 1, 14, 14, 38, 57, 778000, tzinfo=tzlocal()),
'AthenaError': {'ErrorCategory': 2, 'ErrorType': 1006, 'Retryable': False, 'ErrorMessage': "COLUMN_NOT_FOUND: 
line 1:50: Column 'table_description' cannot be resolved or requester is not authorized to 
access requested resources"}}
COLUMN_NOT_FOUND: line 1:50: Column 'table_description' cannot be resolved or requester is not authorized to access requested resources
Try Count: 2
2024-01-14 14:39:02,521,llm_execute,MainProcess,INFO,Try Count: 2
we are in Try block to generate the sql and count is :2
2024-01-14 14:39:02,521,llm_execute,MainProcess,INFO,we are in Try block to generate the sql and count is :2
Executing: Explain WITH tables AS ( SELECT table_name FROM information_schema.tables WHERE table_schema = 'imdb_stg' ), columns AS ( SELECT c.table_name, c.column_name, c.data_type, c.is_nullable, c.column_default, c.ordinal_position FROM information_schema.columns c WHERE c.table_schema = 'imdb_stg' ) SELECT t.table_name, c.column_name, c.data_type, c.is_nullable, c.column_default, c.ordinal_position FROM tables t INNER JOIN columns c ON t.table_name = c.table_name ORDER BY t.table_name, c.ordinal_position LIMIT 10;
I am checking the syntax here
execution_id: 904857c3-b7ac-47d0-8e7e-6b9d0456099b
Status : {'State': 'SUCCEEDED', 'SubmissionDateTime': datetime.datetime(2024, 1, 14, 14, 39, 29, 537000, tzinfo=tzlocal()), 'CompletionDateTime': datetime.datetime(2024, 1, 14, 14, 39, 30, 183000, tzinfo=tzlocal())}
syntax checked for query passed in tries number :2

Korzystanie z rozwiązania z innymi źródłami danych

Aby móc korzystać z rozwiązania z innymi źródłami danych, Athena wykona to zadanie za Ciebie. Aby to zrobić, Atena używa złącza źródła danych z którymi można korzystać zapytania sfederowane. Konektor można uznać za rozszerzenie silnika zapytań Athena. Istnieją gotowe łączniki źródeł danych Athena dla źródeł danych takich jak Dzienniki Amazon CloudWatch, Amazon DynamoDB, Amazon DocumentDB (z kompatybilnością MongoDB), Usługa relacyjnych baz danych Amazon (Amazon RDS) oraz relacyjne źródła danych zgodne z JDBC, takie jak MySQL i PostgreSQL na licencji Apache 2.0. Po skonfigurowaniu połączenia z dowolnym źródłem danych możesz użyć powyższej bazy kodu, aby rozszerzyć rozwiązanie. Aby uzyskać więcej informacji, zobacz Wysyłaj zapytania do dowolnego źródła danych za pomocą nowego, stowarzyszonego zapytania Amazon Athena.

Sprzątać

Aby oczyścić zasoby, możesz zacząć od sprzątanie wiadra S3 gdzie znajdują się dane. Jeśli Twoja aplikacja nie odwołuje się do Amazon Bedrock, nie poniesie żadnych kosztów. Ze względu na najlepsze praktyki w zakresie zarządzania infrastrukturą zalecamy usunięcie zasobów utworzonych w ramach tej demonstracji.

Wnioski

W tym poście przedstawiliśmy rozwiązanie, które pozwala wykorzystać NLP do generowania złożonych zapytań SQL przy użyciu różnorodnych zasobów udostępnianych przez Athenę. Zwiększyliśmy także dokładność generowanych zapytań SQL poprzez wieloetapową pętlę oceny opartą na komunikatach o błędach z dalszych procesów. Dodatkowo wykorzystaliśmy metadane z katalogu danych kleju AWS, aby uwzględnić nazwy tabel zadawane w zapytaniu za pośrednictwem platformy RAG. Następnie przetestowaliśmy rozwiązanie w różnych realistycznych scenariuszach o różnych poziomach złożoności zapytań. Na koniec omówiliśmy, jak zastosować to rozwiązanie do różnych źródeł danych obsługiwanych przez Athenę.

Amazon Bedrock znajduje się w centrum tego rozwiązania. Amazon Bedrock może pomóc w tworzeniu wielu generatywnych aplikacji AI. Aby rozpocząć korzystanie z Amazon Bedrock, zalecamy wykonanie poniższej krótkiej instrukcji GitHub repo i zapoznanie się z tworzeniem generatywnych aplikacji AI. Możesz też spróbować bazy wiedzy w Amazon Bedrock, aby szybko budować takie rozwiązania RAG.


O autorach

Panda Sanjeeba jest inżynierem danych i uczenia maszynowego w Amazon. Mając doświadczenie w AI/ML, Data Science i Big Data, Sanjeeb projektuje i rozwija innowacyjne rozwiązania w zakresie danych i ML, które rozwiązują złożone wyzwania techniczne i osiągają strategiczne cele dla globalnych sprzedawców 3P zarządzających swoimi biznesami na Amazon. Poza pracą jako inżynier danych i uczenia maszynowego w Amazon Sanjeeb Panda jest zapalonym entuzjastą jedzenia i muzyki.

Burak Gozluklu jest głównym architektem rozwiązań specjalistycznych AI/ML z siedzibą w Bostonie, MA. Pomaga klientom strategicznym w wdrażaniu technologii AWS, a w szczególności rozwiązań generatywnej AI, aby osiągnąć ich cele biznesowe. Burak posiada tytuł doktora inżynierii lotniczej i kosmicznej uzyskany na METU, tytuł magistra inżynierii systemów oraz post-doc z dynamiki systemów na MIT w Cambridge w stanie Massachusetts. Burak nadal jest pracownikiem naukowym w MIT. Burak jest pasjonatem jogi i medytacji.

spot_img

Najnowsza inteligencja

spot_img