Incorporamento del testo e recupero di similarità delle frasi su larga scala con Amazon SageMaker JumpStart

Integrazione testuale e rilevamento di similitudine delle frasi su larga scala con Amazon SageMaker JumpStart

I vettori di testo o le rappresentazioni di testo (embeddings) sono rappresentazioni vettoriali numeriche del testo che vengono generate da modelli di linguaggio di grandi dimensioni (LLM). Dopo che gli LLM sono completamente pre-allenati su un ampio dataset o raffinati da diverse attività, tra cui il completamento del testo, la risposta alle domande e le traduzioni, le rappresentazioni del testo catturano le informazioni semantiche del testo di input. Diverse applicazioni derivate sono rese possibili dalle rappresentazioni del testo, tra cui la ricerca di similarità, il recupero di informazioni, le raccomandazioni e la personalizzazione, le traduzioni multilingue e altro ancora.

Prima che fosse possibile creare applicazioni intelligenti utilizzando le embeddings, le aziende e le organizzazioni dovevano incorporare i loro documenti esistenti, il che può essere costoso e complicato dal punto di vista tecnico. Amazon SageMaker JumpStart è un hub di apprendimento automatico (ML) che aiuta ad accelerare questo processo. Con SageMaker JumpStart, è possibile accedere a modelli di embedding di testo pre-allenati e all’avanguardia da vari fornitori di modelli, tra cui Hugging Face, AI 21 Labs, Cohere e Meta AI. È possibile distribuire senza problemi questi modelli in produzione utilizzando l’interfaccia utente o l’SDK di SageMaker JumpStart. Inoltre, i dati non vengono utilizzati per allenare i modelli sottostanti. Poiché tutti i dati sono crittografati e non escono dalla propria VPC, è possibile fidarsi che i dati rimangano privati e riservati.

In questo articolo, dimostriamo come utilizzare il Python SDK di SageMaker per l’embedding del testo e la similarità delle frasi. La similarità delle frasi coinvolge la valutazione della somiglianza tra due pezzi di testo dopo che sono stati convertiti in embeddings dagli LLM, che è un passaggio fondamentale per applicazioni come Retrieval Augmented Generation (RAG). Dimostriamo come fare quanto segue:

  • Eseguire l’inferenza su un modello di embedding del testo implementato da SageMaker JumpStart
  • Trovare i vicini più vicini per una frase di input con il proprio dataset
  • Eseguire la trasformazione batch su documenti di grandi dimensioni per ridurre i costi

Tutto il codice è disponibile su GitHub.

Implementare un modello di embedding del testo tramite SageMaker JumpStart

Per ospitare un modello su Amazon SageMaker, il primo passaggio consiste nel configurare l’autenticazione e l’utilizzo dei servizi AWS. In Amazon SageMaker Studio, utilizziamo il ruolo di esecuzione associato all’istanza del notebook. Ecco il codice:

import sagemaker, boto3, jsonfrom sagemaker.session import Sessionsagemaker_session = Session()aws_role = sagemaker_session.get_caller_identity_arn()aws_region = boto3.Session().region_namesess = sagemaker.Session()

Su Hugging Face, il Massive Text Embedding Benchmark (MTEB) viene fornito come leaderboard per diverse attività di embedding del testo. Attualmente fornisce 129 dataset di benchmarking su 8 diverse attività in 113 lingue. I migliori modelli di embedding del testo dal leaderboard del MTEB sono resi disponibili da SageMaker JumpStart, tra cui bge, gte, e5 e altri. In questo articolo, utilizziamo huggingface-sentencesimilarity-bge-large-en come esempio. Possiamo utilizzare l’SDK di SageMaker per distribuire questo modello di embedding del testo all’avanguardia:

from sagemaker.jumpstart.model import JumpStartModelmodel_id = "huggingface-sentencesimilarity-bge-large-en"text_embedding_model = JumpStartModel(model_id=model_id)predictor = text_embedding_model.deploy()

Query del modello di embedding del testo

Diamo uno sguardo più approfondito alla query del modello di embedding del testo.

Testo in embedding

Se hai già distribuito un endpoint SageMaker in precedenza, il predictor può essere ripristinato come segue:

from sagemaker.predictor import Predictorfrom sagemaker.deserializers import JSONDeserializerfrom sagemaker.serializers import IdentitySerializerpredictor = Predictor(    endpoint_name=<NOME_DEL_TUO_ENDPOINT>,    deserializer=JSONDeserializer(),    serializer=IdentitySerializer(),)predictor.content_type = "application/x-text"

Dopo che il modello è stato implementato con successo, puoi interrogare il punto finale con un batch di testo di input all’interno di un payload JSON:

sentences = [    # Animali domestici    "Il tuo cane è così carino.",    "Che carino il tuo cane è!",    "Hai un cane così carino!",    # Città    "Sydney è il luogo dove lavoro.",    "Lavoro a Sydney.",    # Colore    "Qual è il colore che ti piace di più?",    "Qual è il tuo colore preferito?",]predictor.predict(json.dumps(sentences).encode('utf-8'))

La correlazione delle incapsulazioni di queste frasi è rappresentata nel seguente grafico.

correlation_heat_map

Come mostrato nel grafico precedente, gli stessi argomenti sono altamente correlati tra di loro, tra cui Animali domestici, Città e Colore; argomenti diversi sono molto dissimili. Ciò indica che l’incapsulamento generato dai LLM (in questo caso, bge) può rappresentare accuratamente le informazioni semantiche.

In questo articolo, abbiamo utilizzato il campione precedente e confrontato la latenza tra diversi modelli di incapsulamento di frasi attualmente disponibili su SageMaker Jumpstart. La latenza è il tempo trascorso dal momento in cui un utente invia una richiesta fino al momento in cui l’applicazione indica che la richiesta è stata completata. I numeri nella seguente tabella rappresentano la latenza media per un totale di 100 richieste utilizzando lo stesso batch di testi di input sulle istanze ml.g5.2xlarge e ml.c6i.xlarge.

Modello Latenza media g5.2xlarge (ms) Latenza media c6i.xlarge (ms) Supporto linguistico
all-MiniLM-L6-v2 19.5 27.9 Inglese
BGE Base It 21.2 114 Inglese
BGE Piccolo It 28.3 45.6 Inglese
BGE Grande It 34.7 337 Inglese
Multilingua E5 Base 22.1 118 Multilingua
Multilingua E5 Grande 39.8 360 Multilingua
E5 Base It 25.6 117 Inglese
E5 Base V2 It 25.2 123 Inglese
E5 Grande It 32.2 339 Inglese
E5 Grande V2 It 32.5 331 Inglese
GTE Base It 22.2 112 Inglese
GTE Piccolo It 19.7 46 Inglese
GTE Grande It 39.7 347 Inglese

Ottieni i vicini più vicini

Il modello implementato di SageMaker JumpStart può anche facilitare il processo di identificazione dei vicini più vicini alle query all’interno del corpus. Quando viene fornito con query e un corpus, il modello produrrà l’corpus_id, che indica la posizione dell’elemento rilevante del corpus nella lista di input del corpus, e uno score che indica il grado di vicinanza alla query. Utilizza i seguenti parametri:

  • corpus – Fornisce l’elenco di input da cui trovare il vicino più vicino
  • queries – Fornisce l’elenco di input per cui trovare il vicino più vicino dal corpus
  • top_k – Il numero di vicini più vicini da trovare dal corpus
  • mode – Impostato come nn_corpus per ottenere i vicini più vicini alle query di input all’interno del corpus

Vedi il seguente codice:

corpus = [    "Amazon SageMaker è un servizio completamente gestito per preparare dati e costruire, addestrare e distribuire modelli di machine learning (ML) per qualsiasi caso d'uso con infrastruttura, strumenti e flussi di lavoro completamente gestiti.",    "Amazon SageMaker archivia il codice in volumi di archiviazione di ML, protetti da gruppi di sicurezza e opzionalmente crittografati a riposo.",    "Amazon SageMaker fornisce un flusso di lavoro completo end-to-end, ma è possibile continuare a utilizzare gli strumenti esistenti con SageMaker. È possibile trasferire facilmente i risultati di ogni fase dentro e fuori da SageMaker a seconda delle esigenze aziendali."]queries = [    "Cos'è Amazon SageMaker?",    "Come protegge Amazon SageMaker il mio codice?",    "Cosa succede se ho il mio notebook, ambiente di addestramento o di hosting nel mio ambiente aziendale?"]payload_nearest_neighbor = {"corpus": corpus, "queries": queries, "top_k": 3, "mode": "nn_corpus"}query_response = predictor.predict(payload_nearest_neighbor)

Ottieniamo il seguente output:

[    [        {'corpus_id': 0, 'score': 0.8992230892181396},        {'corpus_id': 2, 'score': 0.8664969205856323},        {'corpus_id': 1, 'score': 0.8456423282623291}    ],    [        {'corpus_id': 1, 'score': 0.8919335603713989},        {'corpus_id': 0, 'score': 0.840064525604248},        {'corpus_id': 2, 'score': 0.8145401477813721}    ],    [        {'corpus_id': 2, 'score': 0.7712811231613159},        {'corpus_id': 1, 'score': 0.7564010620117188},        {'corpus_id': 0, 'score': 0.7525666356086731}    ]]

Questo risultato significa che la prima query è più simile al primo corpus, la seconda è più vicina al secondo corpus e così via. Questo è un abbinamento corretto in questo esempio.

Abbiamo anche preso il campione precedente e confrontato la latenza tra i diversi modelli di incorporamento delle frasi attualmente disponibili da SageMaker JumpStart. I numeri nella tabella seguente rappresentano la latenza media per un totale di 100 richieste utilizzando lo stesso payload sulle istanze ml.g5.2xlarge e ml.c6i.xlarge.

Modello Latency media g5.2xlarge (ms) Latency media c6i.xlarge (ms) Supporto Linguistico
all-MiniLM-L6-v2 21.7 69.1 Inglese
BGE Base En 29.1 372 Inglese
BGE Small En 29.2 124 Inglese
BGE Large En 47.2 1240 Inglese
Multilingual E5 Base 30 389 Multilingue
Multilingual E5 Large 47.1 1380 Multilingue
E5 Base 30.4 373 Inglese
E5 Base V2 31 409 Inglese
E5 Large 45.9 1230 Inglese
E5 Large V2 49.6 1220 Inglese
GTE Base 30.3 375 Inglese
GTE Small 28.5 129 Inglese
GTE Large 46.6 1320 Inglese

Ottieni i vicini più vicini su un grande dataset

Quando si effettuano richieste all’endpoint di invocazione di SageMaker, i payload sono limitati a circa 5 MB e il timeout della richiesta è impostato a 1 minuto. Se la dimensione del corpus supera questi limiti, è possibile utilizzare un job di addestramento di SageMaker, che genera embedding per il grande dataset e li persiste insieme al modello all’interno dell’endpoint di SageMaker. Pertanto, non è necessario passarli come parte del payload di invocazione. Il processo di ricerca dei vicini più vicini viene eseguito utilizzando SentenceTransformer e la sua funzione di utilità. Il vicino più vicino si basa sulla similarità coseno tra l’embedding della frase di input e gli embedding delle frasi precalcolate durante il job di addestramento.

Nell’esempio seguente, recuperiamo e prepariamo il dataset Amazon_SageMaker_FAQs per utilizzarlo nella ricerca del vicino più vicino a una domanda di input:

!aws s3 cp s3://jumpstart-cache-prod-us-west-2/training-datasets/Amazon_SageMaker_FAQs/Amazon_SageMaker_FAQs.csv Amazon_SageMaker_FAQs.csvimport pandas as pddata = pd.read_csv("Amazon_SageMaker_FAQs.csv", names=["Domande", "Risposte"])data["id"] = data.indexdata_req = data[["id", "Risposte"]]data_req.to_csv("data.csv", index=False, header=False)output_bucket = sess.default_bucket()output_prefix = "jumpstart-example-ss-training"s3_output_location = f"s3://{output_bucket}/{output_prefix}/output"training_dataset_s3_path = f"s3://{output_bucket}/{output_prefix}/data/data.csv"!aws s3 cp data.csv {training_dataset_s3_path}

Per gli iperparametri di addestramento specifici dell’algoritmo, è possibile recuperare o sovrascrivere il SDK di SageMaker:

from sagemaker import hyperparametershyperparameters = hyperparameters.retrieve_default(model_id=model_id, model_version = "*")hyperparameters["batch_size"] = "64"print(hyperparameters)>>> {'max_seq_length': 'None', 'batch_size': '64', 'store_text_with_embedding': 'True'}

L’addestramento di SageMaker consiste in due fasi: creare l’oggetto estimator e avviare il job di addestramento. L’output è un modello preconfezionato con gli embedding del grande dataset utilizzato come dati di addestramento, che può essere distribuito per l’elaborazione per ottenere il vicino più vicino per qualsiasi frase di input. Vedere il codice seguente:

from sagemaker.jumpstart.estimator import JumpStartEstimatorestimator = JumpStartEstimator(    model_id=model_id,    hyperparameters=hyperparameters,    output_path=s3_output_location)estimator.fit(    {"training": f"s3://{output_bucket}/{output_prefix}/data"})predictor = estimator.deploy()

La sintassi della query per convertire il testo in embedding è la stessa di prima. Il codice per ottenere il vicino più vicino, tuttavia, può essere semplificato come segue:

payload_nearest_neighbour = {    "queries": ["È supportato R con Amazon SageMaker?"],    "top_k": 1,    "mode": "nn_train_data",}response = predictor.predict(payload_nearest_neighbour)>>> [[{'id': '9', 'score': 0.9240573048591614}]]data["Risposte"].iloc[int(response[0][0]["id"])]>>> "Sì, R è supportato con Amazon SageMaker. Puoi utilizzare R all'interno delle istanze di notebook di SageMaker, che includono un kernel R preinstallato e la libreria reticulate. Reticulate offre un'interfaccia R per il SDK di Python di Amazon SageMaker, consentendo agli specialisti di ML di creare, addestrare, ottimizzare e distribuire modelli R."

Poiché possibile interrogare anche l’endpoint con domande presenti nel dataset Amazon_SageMaker_FAQs e confrontare quante delle risposte corrispondenti corrette vengono restituite. Nell’esempio seguente, misuriamo l’accuratezza dei migliori 3, dato che potrebbero esserci domande e risposte simili. Ciò significa che se la risposta corretta viene restituita come una delle prime 3 restituzioni, viene considerata una query corretta.

total_correct_answers = 0for i in range(len(data)):    question = data["Domande"].iloc[i]    payload_nearest_neighbor = {        "queries": [question],        "top_k": 3,        "mode": "nn_train_data",    }    response = predictor.predict(payload_nearest_neighbor)    response_ids = [int(res["id"]) for res in response[0]]    if i in response_ids:        total_correct_answers += 1    else:        pred_answer = [data["Risposte"].iloc[response_id] for response_id in response_ids]print(total_correct_answers*100/len(data))>>>81.16883116883118

Esegui una trasformazione batch per ottenere embeddings su grandi dataset

Per le aziende e le organizzazioni con un grande volume di documenti storici che superano la memoria di una singola istanza di endpoint, è possibile utilizzare SageMaker batch transform per risparmiare costi. Quando si avvia un lavoro di trasformazione batch, SageMaker avvia le risorse di calcolo necessarie per elaborare i dati. Durante il lavoro, SageMaker provvede automaticamente a allocare e gestire le risorse di calcolo. Quando il lavoro di trasformazione batch è completo, tali risorse vengono automaticamente pulite, riducendo al minimo i costi. Suddividendo un grande dataset in blocchi più piccoli e utilizzando più istanze, è possibile scalare il calcolo per una inferenza più rapida con costi simili, senza gestire l’infrastruttura. Il payload massimo per la trasformazione batch è 100 MB e il timeout è di 1 ora.

Il formato di input per il nostro lavoro di trasformazione batch è un file JSONL, con voci rappresentate come una riga di JSON, che consiste di id e text_inputs. Ecco il codice seguente:

test_data_file_name = "test.jsonl"test_data = []for i in range(len(data)):    answer = data.loc[i, "Answers"]    payload = {"id": i, "text_inputs": answer}    test_data.append(payload)with open(test_data_file_name, "w") as outfile:    for entry in test_data:        outfile.write(f"{json.dumps(entry)}\n")s3 = boto3.client("s3")s3.upload_file(test_data_file_name, output_bucket, f"{output_prefix}/batch_input/test.jsonl")

Quando i dati sono pronti in Amazon Simple Storage Service (Amazon S3), è possibile creare l’oggetto di trasformazione batch dal modello SageMaker JumpStart, che attiva il lavoro di trasformazione:

s3_input_data_path = f"s3://{output_bucket}/{output_prefix}/batch_input/"s3_output_data_path = f"s3://{output_bucket}/{output_prefix}/batch_output/"batch_transformer = text_embedding_model.transformer(    instance_count=1,    instance_type="ml.p3.2xlarge",    output_path=s3_output_data_path,    assemble_with="Line",    accept="text/csv",    max_payload=1,)batch_transformer.transform(    s3_input_data_path,    content_type="application/jsonlines",    split_type="Line")batch_transformer.wait()

Dopo che il lavoro di trasformazione batch è completo, è possibile scaricare il risultato da Amazon S3:

s3 = boto3.client("s3")s3.download_file(    output_bucket, output_prefix + "/batch_output/" + "test.jsonl.out", "predict.jsonl")with open("predict.jsonl", "r") as json_file:    json_list = list(json_file)

Conclusioni

SageMaker JumpStart fornisce un modo semplice per utilizzare modelli di base di grandi dimensioni all’avanguardia per l’embedding di testi e la ricerca semantica. Con l’interfaccia utente o solo poche righe di codice, è possibile distribuire un modello di embedding di testo altamente accurato e trovare corrispondenze semantiche in grandi dataset, in modo efficiente in termini di scala e costi. SageMaker JumpStart rimuove gli ostacoli all’implementazione della ricerca semantica fornendo un accesso immediato a modelli all’avanguardia come quelli testati sulla MTEB leaderboard. Le aziende e gli sviluppatori possono creare sistemi di ricerca e raccomandazione intelligenti più velocemente.

In questo post è stato dimostrato come trovare domande e risposte semanticamente simili, che possono essere applicate a casi d’uso come RAG, raccomandazioni e personalizzazione, traduzioni multilinguistiche e altro ancora. Con l’avanzamento continuo dei modelli di linguaggio e la semplicità di SageMaker JumpStart, sempre più organizzazioni possono incorporare le capacità di intelligenza artificiale generativa nei loro prodotti. Come prossimo passo, è possibile provare modelli di embedding di testo da SageMaker JumpStart sul proprio dataset per testare e valutare i risultati per i propri casi d’uso RAG.