Distribuera grundmodeller med Amazon SageMaker, iterera och övervaka med TruEra | Amazon webbtjänster

Distribuera grundmodeller med Amazon SageMaker, iterera och övervaka med TruEra | Amazon webbtjänster

Källnod: 3033627

Den här bloggen är skriven tillsammans med Josh Reini, Shayak Sen och Anupam Datta från TruEra

Amazon SageMaker JumpStart tillhandahåller en mängd olika förtränade grundmodeller som Llama-2 och Mistal 7B som snabbt kan distribueras till en slutpunkt. Dessa grundmodeller fungerar bra med generativa uppgifter, från att skapa text och sammanfattningar, svara på frågor till att producera bilder och videor. Trots dessa modellers stora generaliseringsförmåga finns det ofta användningsfall där dessa modeller måste anpassas till nya uppgifter eller domäner. Ett sätt att yttra detta behov är genom att utvärdera modellen mot en kurerad datauppsättning av grundsanningar. Efter att behovet av att anpassa grundmodellen är klart kan du använda en uppsättning tekniker för att utföra det. Ett populärt tillvägagångssätt är att finjustera modellen med hjälp av en datauppsättning som är skräddarsydd för användningsfallet. Finjustering kan förbättra grundmodellen och dess effektivitet kan återigen mätas mot grundsanningsdataset. Detta anteckningsbok visar hur man finjusterar modeller med SageMaker JumpStart.

En utmaning med detta tillvägagångssätt är att kurerade datauppsättningar av grundsanningar är dyra att skapa. I det här inlägget tar vi oss an denna utmaning genom att utöka detta arbetsflöde med ett ramverk för utökningsbara, automatiserade utvärderingar. Vi börjar med en grundmodell från SageMaker JumpStart och utvärderar den med TruLens, ett bibliotek med öppen källkod för att utvärdera och spåra appar för stora språkmodeller (LLM). Efter att vi identifierat behovet av anpassning kan vi använda finjustering i SageMaker JumpStart och bekräfta förbättringar med TruLens.

TruLens utvärderingar använder en abstraktion av återkopplingsfunktioner. Dessa funktioner kan implementeras på flera sätt, inklusive modeller i BERT-stil, lämpliga LLM:er och mer. TruLens integration med Amazonas berggrund låter dig köra utvärderingar med hjälp av LLM:er tillgängliga från Amazon Bedrock. Tillförlitligheten hos Amazon Bedrock-infrastrukturen är särskilt värdefull för användning vid utvärderingar över utveckling och produktion.

Det här inlägget fungerar både som en introduktion till TruEras plats i den moderna LLM-appstacken och en praktisk guide för att använda Amazon SageMaker och TruEra att distribuera, finjustera och iterera på LLM-appar. Här är den kompletta anteckningsbok med kodexempel för att visa prestandautvärdering med TruLens

TruEra i LLM-appstacken

TruEra bor på observerbarhetslagret av LLM-appar. Även om nya komponenter har arbetat sig in i beräkningsskiktet (finjustering, promptteknik, modell-API) och lagringslagret (vektordatabaser), kvarstår behovet av observerbarhet. Detta behov sträcker sig från utveckling till produktion och kräver sammanlänkade möjligheter för testning, felsökning och produktionsövervakning, som illustreras i följande figur.

I utvecklingen kan du använda öppen källkod TruLens för att snabbt utvärdera, felsöka och iterera på dina LLM-appar i din miljö. En omfattande uppsättning utvärderingsmått, inklusive både LLM-baserade och traditionella mätvärden tillgängliga i TruLens, låter dig mäta din app mot kriterier som krävs för att flytta din applikation till produktion.

I produktionen kan dessa loggar och utvärderingsmått bearbetas i skala med TruEra produktionsövervakning. Genom att koppla samman produktionsövervakning med testning och felsökning kan nedgångar i prestanda som hallucinationer, säkerhet, säkerhet med mera identifieras och korrigeras.

Distribuera grundmodeller i SageMaker

Du kan distribuera grundmodeller som Llama-2 i SageMaker med bara två rader Python-kod:

from sagemaker.jumpstart.model import JumpStartModel
pretrained_model = JumpStartModel(model_id="meta-textgeneration-llama-2-7b")
pretrained_predictor = pretrained_model.deploy()

Anropa modellens slutpunkt

Efter implementeringen kan du anropa den distribuerade modellens slutpunkt genom att först skapa en nyttolast som innehåller dina indata och modellparametrar:

payload = {
    "inputs": "I believe the meaning of life is",
    "parameters": {
        "max_new_tokens": 64,
        "top_p": 0.9,
        "temperature": 0.6,
        "return_full_text": False,
    },
}

Sedan kan du helt enkelt skicka denna nyttolast till slutpunktens förutsägelsemetod. Observera att du måste skicka attributet för att acceptera licensavtalet för slutanvändare varje gång du anropar modellen:

response = pretrained_predictor.predict(payload, custom_attributes="accept_eula=true")

Utvärdera prestanda med TruLens

Nu kan du använda TruLens för att ställa in din utvärdering. TruLens är ett observerbarhetsverktyg som erbjuder en utbyggbar uppsättning feedbackfunktioner för att spåra och utvärdera LLM-drivna appar. Feedbackfunktioner är viktiga här för att verifiera frånvaron av hallucinationer i appen. Dessa återkopplingsfunktioner implementeras genom att använda hyllmodeller från leverantörer som Amazon Bedrock. Amazon Bedrock-modeller är en fördel här på grund av deras verifierade kvalitet och tillförlitlighet. Du kan ställa in leverantören med TruLens med följande kod:

from trulens_eval import Bedrock
# Initialize AWS Bedrock feedback function collection class:
provider = Bedrock(model_id = "amazon.titan-tg1-large", region_name="us-east-1")

I det här exemplet använder vi tre återkopplingsfunktioner: svarsrelevans, kontextrelevans och jordadhet. Dessa utvärderingar har snabbt blivit standarden för hallucinationsdetektering i kontextaktiverade frågesvarsapplikationer och är särskilt användbara för oövervakade applikationer, som täcker de allra flesta av dagens LLM-applikationer.

Låt oss gå igenom var och en av dessa feedbackfunktioner för att förstå hur de kan gynna oss.

Kontextrelevans

Kontext är en avgörande indata för kvaliteten på vår applikations svar, och det kan vara användbart att programmatiskt säkerställa att det angivna sammanhanget är relevant för inmatningsfrågan. Detta är avgörande eftersom detta sammanhang kommer att användas av LLM för att bilda ett svar, så all irrelevant information i sammanhanget kan vävas in i en hallucination. TruLens låter dig utvärdera sammanhangets relevans genom att använda strukturen för den serialiserade posten:

f_context_relevance = (Feedback(provider.relevance, name = "Context Relevance")
                       .on(Select.Record.calls[0].args.args[0])
                       .on(Select.Record.calls[0].args.args[1])
                      )

Eftersom sammanhanget som tillhandahålls till LLM:er är det mest följdriktiga steget i en RAG-pipeline (Retrieval Augmented Generation) är kontextrelevans avgörande för att förstå kvaliteten på hämtningar. Genom att arbeta med kunder över olika sektorer har vi sett en mängd olika fellägen identifierade med denna utvärdering, såsom ofullständig kontext, främmande irrelevant kontext eller till och med brist på tillräckligt tillgängligt sammanhang. Genom att identifiera arten av dessa fellägen kan våra användare anpassa sin indexering (som inbäddningsmodell och chunking) och hämtningsstrategier (som meningsfönster och automerging) för att mildra dessa problem.

Jordning

Efter att sammanhanget har hämtats, formas det sedan till ett svar av en LLM. LLM är ofta benägna att avvika från de fakta som tillhandahålls, överdriva eller utöka till ett korrekt klingande svar. För att verifiera att applikationen är grundad bör du dela upp svaret i separata påståenden och självständigt söka efter bevis som stöder var och en inom det hämtade sammanhanget.

grounded = Groundedness(groundedness_provider=provider)

f_groundedness = (Feedback(grounded.groundedness_measure, name = "Groundedness")
                .on(Select.Record.calls[0].args.args[1])
                .on_output()
                .aggregate(grounded.grounded_statements_aggregator)
            )

Frågor med jordning kan ofta vara en nedströmseffekt av sammanhangsrelevans. När LLM saknar tillräckligt sammanhang för att bilda ett evidensbaserat svar, är det mer sannolikt att hallucinera i sitt försök att generera ett rimligt svar. Även i de fall där fullständig och relevant kontext tillhandahålls, kan LLM hamna i problem med jordning. Särskilt har detta utspelat sig i applikationer där LLM svarar i en viss stil eller används för att slutföra en uppgift som den inte är väl lämpad för. Grundade utvärderingar gör det möjligt för TruLens-användare att bryta ner LLM-svar påstående för anspråk för att förstå var LLM oftast hallucinerar. Att göra det har visat sig vara särskilt användbart för att belysa vägen framåt för att eliminera hallucinationer genom förändringar på modellsidan (som uppmaning, modellval och modellparametrar).

Svarsrelevans

Slutligen måste svaret fortfarande besvara den ursprungliga frågan. Du kan verifiera detta genom att utvärdera relevansen av det slutliga svaret på användarinmatningen:

f_answer_relevance = (Feedback(provider.relevance, name = "Answer Relevance")
                      .on(Select.Record.calls[0].args.args[0])
                      .on_output()
                      )

Genom att nå tillfredsställande utvärderingar för denna triad kan du göra ett nyanserat uttalande om din ansökans riktighet; denna applikation är verifierad att vara hallucinationsfri upp till gränsen för dess kunskapsbas. Med andra ord, om vektordatabasen endast innehåller korrekt information, är svaren från den kontextaktiverade frågesvarsappen också korrekta.

Grund sanningsutvärdering

Utöver dessa återkopplingsfunktioner för att upptäcka hallucinationer har vi en testdatauppsättning, DataBricks-Dolly-15k, som gör det möjligt för oss att lägga till grund sanningslikhet som ett fjärde utvärderingsmått. Se följande kod:

from datasets import load_dataset

dolly_dataset = load_dataset("databricks/databricks-dolly-15k", split="train")

# To train for question answering/information extraction, you can replace the assertion in next line to example["category"] == "closed_qa"/"information_extraction".
summarization_dataset = dolly_dataset.filter(lambda example: example["category"] == "summarization")
summarization_dataset = summarization_dataset.remove_columns("category")

# We split the dataset into two where test data is used to evaluate at the end.
train_and_test_dataset = summarization_dataset.train_test_split(test_size=0.1)

# Rename columns
test_dataset = pd.DataFrame(test_dataset)
test_dataset.rename(columns={"instruction": "query"}, inplace=True)

# Convert DataFrame to a list of dictionaries
golden_set = test_dataset[["query","response"]].to_dict(orient='records')

# Create a Feedback object for ground truth similarity
ground_truth = GroundTruthAgreement(golden_set)
# Call the agreement measure on the instruction and output
f_groundtruth = (Feedback(ground_truth.agreement_measure, name = "Ground Truth Agreement")
                 .on(Select.Record.calls[0].args.args[0])
                 .on_output()
                )

Bygg applikationen

När du har ställt in dina utvärderare kan du bygga din ansökan. I det här exemplet använder vi en kontextaktiverad QA-applikation. I den här applikationen ger du instruktionen och sammanhanget till kompletteringsmotorn:

def base_llm(instruction, context):
    # For instruction fine-tuning, we insert a special key between input and output
    input_output_demarkation_key = "nn### Response:n"
    payload = {
        "inputs": template["prompt"].format(
            instruction=instruction, context=context
        )
        + input_output_demarkation_key,
        "parameters": {"max_new_tokens": 200},
    }
    
    return pretrained_predictor.predict(
        payload, custom_attributes="accept_eula=true"
    )[0]["generation"]

När du har skapat appen och feedbackfunktionerna är det enkelt att skapa en inpackad applikation med TruLens. Denna inpackade applikation, som vi kallar base_recorder, kommer att logga och utvärdera applikationen varje gång den anropas:

base_recorder = TruBasicApp(base_llm, app_id="Base LLM", feedbacks=[f_groundtruth, f_answer_relevance, f_context_relevance, f_groundedness])

for i in range(len(test_dataset)):
    with base_recorder as recording:
        base_recorder.app(test_dataset["query"][i], test_dataset["context"][i])

Resultat med bas Lama-2

När du har kört applikationen på varje post i testdatasetet kan du se resultaten i din SageMaker-anteckningsbok med tru.get_leaderboard(). Följande skärmdump visar resultatet av utvärderingen. Svarsrelevansen är oroväckande låg, vilket indikerar att modellen kämpar för att konsekvent följa instruktionerna.

Finjustera Llama-2 med SageMaker Jumpstart

Steg för att finjustera Llama-2-modellen med SageMaker Jumpstart finns också i denna anteckningsbok.

För att ställa in för finjustering måste du först ladda ner träningssetet och ställa in en mall för instruktioner

# Dumping the training data to a local file to be used for training.
train_and_test_dataset["train"].to_json("train.jsonl")

import json

template = {
    "prompt": "Below is an instruction that describes a task, paired with an input that provides further context. "
    "Write a response that appropriately completes the request.nn"
    "### Instruction:n{instruction}nn### Input:n{context}nn",
    "completion": " {response}",
}
with open("template.json", "w") as f:
    json.dump(template, f)

Ladda sedan upp både datasetet och instruktionerna till en Amazon enkel lagringstjänst (Amazon S3) hink för träning:

from sagemaker.s3 import S3Uploader
import sagemaker
import random

output_bucket = sagemaker.Session().default_bucket()
local_data_file = "train.jsonl"
train_data_location = f"s3://{output_bucket}/dolly_dataset"
S3Uploader.upload(local_data_file, train_data_location)
S3Uploader.upload("template.json", train_data_location)
print(f"Training data: {train_data_location}")

För att finjustera i SageMaker kan du använda SageMaker JumpStart Estimator. Vi använder för det mesta standardhyperparametrar här, förutom att vi ställer in instruktionsjustering till sant:

from sagemaker.jumpstart.estimator import JumpStartEstimator

estimator = JumpStartEstimator(
    model_id=model_id,
    environment={"accept_eula": "true"},
    disable_output_compression=True,  # For Llama-2-70b, add instance_type = "ml.g5.48xlarge"
)
# By default, instruction tuning is set to false. Thus, to use instruction tuning dataset you use
estimator.set_hyperparameters(instruction_tuned="True", epoch="5", max_input_length="1024")
estimator.fit({"training": train_data_location})

När du har tränat modellen kan du distribuera den och skapa din applikation precis som du gjorde tidigare:

finetuned_predictor = estimator.deploy()

def finetuned_llm(instruction, context):
    # For instruction fine-tuning, we insert a special key between input and output
    input_output_demarkation_key = "nn### Response:n"
    payload = {
        "inputs": template["prompt"].format(
            instruction=instruction, context=context
        )
        + input_output_demarkation_key,
        "parameters": {"max_new_tokens": 200},
    }
    
    return finetuned_predictor.predict(
        payload, custom_attributes="accept_eula=true"
    )[0]["generation"]

finetuned_recorder = TruBasicApp(finetuned_llm, app_id="Finetuned LLM", feedbacks=[f_groundtruth, f_answer_relevance, f_context_relevance, f_groundedness])

Utvärdera den finjusterade modellen

Du kan köra modellen igen på ditt testset och se resultaten, denna gång i jämförelse med basen Llama-2:

for i in range(len(test_dataset)):
    with finetuned_recorder as recording:
        finetuned_recorder.app(test_dataset["query"][i], test_dataset["context"][i])

tru.get_leaderboard(app_ids=[‘Base LLM’,‘Finetuned LLM’])

Den nya, finjusterade Llama-2-modellen har förbättrats avsevärt vad gäller svarsrelevans och jordadhet, tillsammans med likheten med testsetet för grundsannhet. Denna stora kvalitetsförbättring sker på bekostnad av en liten ökning av latensen. Denna ökning av latens är ett direkt resultat av att finjusteringen ökar storleken på modellen.

Du kan inte bara se dessa resultat i anteckningsboken, utan du kan också utforska resultaten i TruLens UI genom att köra tru.run_dashboard(). Om du gör det kan du ge samma samlade resultat på leaderboard-sidan, men ger dig också möjlighet att dyka djupare in i problematiska poster och identifiera fellägen för applikationen.

För att förstå förbättringen av appen på rekordnivå kan du gå till utvärderingssidan och undersöka feedbackpoängen på en mer detaljerad nivå.

Till exempel, om du ställer den grundläggande LLM frågan "Vilken är den mest kraftfulla Porsche flat sex-motorn", hallucinerar modellen följande.

Dessutom kan du undersöka den programmatiska utvärderingen av denna post för att förstå programmets prestanda mot var och en av de återkopplingsfunktioner du har definierat. Genom att undersöka resultaten för jordad återkoppling i TruLens kan du se en detaljerad uppdelning av de bevis som finns tillgängliga för att stödja varje påstående som görs av LLM.

Om du exporterar samma post för din finjusterade LLM i TruLens, kan du se att finjustering med SageMaker JumpStart dramatiskt förbättrade jordningen av svaret.

Genom att använda ett automatiskt utvärderingsarbetsflöde med TruLens kan du mäta din applikation över en bredare uppsättning mätvärden för att bättre förstå dess prestanda. Viktigt är att du nu kan förstå den här prestandan dynamiskt för alla användningsfall – även de där du inte har samlat grundsanningen.

Hur TruLens fungerar

Efter att du har skapat en prototyp för din LLM-applikation kan du integrera TruLens (visas tidigare) för att instrumentera dess anropsstack. Efter att anropsstacken är instrumenterad kan den sedan loggas vid varje körning till en loggningsdatabas som finns i din miljö.

Förutom instrumenterings- och loggningsmöjligheterna är utvärdering en viktig del av värde för TruLens-användare. Dessa utvärderingar implementeras i TruLens av återkopplingsfunktioner som körs ovanpå din instrumenterade anropsstack, och i sin tur uppmanar externa modellleverantörer att producera feedbacken själv.

Efter feedback slutledning skrivs feedbackresultaten till loggdatabasen, från vilken du kan köra TruLens instrumentpanel. TruLens instrumentpanel, som körs i din miljö, låter dig utforska, iterera och felsöka din LLM-app.

I stor skala kan dessa loggar och utvärderingar skickas till TruEra för observerbarhet i produktionen som kan bearbeta miljontals observationer per minut. Genom att använda TruEra Observability Platform kan du snabbt upptäcka hallucinationer och andra prestandaproblem och zooma in på en enda post på några sekunder med integrerad diagnostik. Genom att flytta till en diagnostisk synvinkel kan du enkelt identifiera och mildra fellägen för din LLM-app som hallucinationer, dålig hämtningskvalitet, säkerhetsproblem och mer.

Utvärdera för ärliga, ofarliga och hjälpsamma svar

Genom att nå tillfredsställande utvärderingar för denna triad kan du nå en högre grad av förtroende för sanningshalten i svaren den ger. Utöver sanningshalten har TruLens brett stöd för de utvärderingar som behövs för att förstå din LLM:s prestanda på axeln "Ärlig, ofarlig och hjälpsam". Våra användare har haft enorm nytta av möjligheten att identifiera inte bara hallucinationer som vi diskuterade tidigare, utan också problem med säkerhet, säkerhet, språkmatchning, koherens med mera. Dessa är alla röriga, verkliga problem som LLM-apputvecklare möter och kan identifieras direkt med TruLens.

Slutsats

Det här inlägget diskuterade hur du kan påskynda produktionen av AI-applikationer och använda grundmodeller i din organisation. Med SageMaker JumpStart, Amazon Bedrock och TruEra kan du distribuera, finjustera och iterera på grundmodeller för din LLM-applikation. Kolla in det här länk för att ta reda på mer om TruEra och prova  anteckningsbok själv.


Om författarna

Josh Reini är en kärnbidragsgivare till TruLens med öppen källkod och grundaren Developer Relations Data Scientist på TruEra där han är ansvarig för utbildningsinitiativ och fostra en blomstrande gemenskap av AI-kvalitetsutövare.

Shayak Sen är CTO och medgrundare av TruEra. Shayak är fokuserad på att bygga system och leda forskning för att göra maskininlärningssystem mer förklarliga, integritetskompatibla och rättvisa.

Anupam Datta är medgrundare, VD och chefsforskare för TruEra. Innan TruEra tillbringade han 15 år på fakulteten vid Carnegie Mellon University (2007-22), senast som anställd professor i elektro- och datorteknik och datavetenskap.

Vivek Gangasani är en AI/ML Startup Solutions Architect för generativa AI-startups på AWS. Han hjälper nya GenAI-startups att bygga innovativa lösningar med hjälp av AWS-tjänster och accelererad beräkning. För närvarande är han fokuserad på att utveckla strategier för att finjustera och optimera slutledningsprestanda för stora språkmodeller. På fritiden tycker Vivek om att vandra, titta på film och prova olika kök.

Tidsstämpel:

Mer från AWS maskininlärning