Hämtning av utökad generation (RAG) i Azure AI Search

RAG (Retrieval Augmented Generation) är en arkitektur som utökar funktionerna i en stor språkmodell (LLM) som ChatGPT genom att lägga till ett informationshämtningssystem som tillhandahåller jordningsdata. Genom att lägga till ett informationshämtningssystem får du kontroll över jordningsdata som används av en LLM när den formulerar ett svar. För en företagslösning innebär RAG-arkitektur att du kan begränsa generativ AI till ditt företagsinnehåll som kommer från vektoriserade dokument och bilder och andra dataformat om du har inbäddningsmodeller för innehållet.

Beslutet om vilket informationshämtningssystem som ska användas är avgörande eftersom det avgör indata till LLM. Informationshämtningssystemet bör tillhandahålla:

  • Indexeringsstrategier som läser in och uppdaterar i stor skala, för allt innehåll, med den frekvens du behöver.

  • Frågefunktioner och relevansjustering. Systemet bör returnera relevanta resultat i de korta format som krävs för att uppfylla kraven på tokenlängd för LLM-indata.

  • Säkerhet, global räckvidd och tillförlitlighet för både data och åtgärder.

  • Integrering med inbäddningsmodeller för indexering och chattmodeller eller språktolkningsmodeller för hämtning.

Azure AI Search är en beprövad lösning för informationshämtning i en RAG-arkitektur. Den tillhandahåller indexerings- och frågefunktioner med infrastrukturen och säkerheten i Azure-molnet. Med hjälp av kod och andra komponenter kan du utforma en omfattande RAG-lösning som innehåller alla element för generativ AI framför ditt egenutvecklade innehåll.

Kommentar

Är du nybörjare på copilot- och RAG-begrepp? Titta på Vektorsökning och senaste hämtning för Generative AI-appar.

Microsoft har flera inbyggda implementeringar för att använda Azure AI Search i en RAG-lösning.

Utvalda metoder gör det enkelt att komma igång, men för att få mer kontroll över arkitekturen behöver du en anpassad lösning. Dessa mallar skapar lösningar från slutpunkt till slutpunkt i:

Resten av den här artikeln utforskar hur Azure AI Search passar in i en anpassad RAG-lösning.

En sammanfattning på hög nivå av mönstret ser ut så här:

  • Börja med en användarfråga eller begäran (fråga).
  • Skicka den till Azure AI Search för att hitta relevant information.
  • Skicka de högst rankade sökresultaten till LLM.
  • Använd funktionerna för förståelse och resonemang för naturligt språk i LLM för att generera ett svar på den första prompten.

Azure AI Search innehåller indata till LLM-prompten, men tränar inte modellen. I RAG-arkitekturen finns det ingen extra utbildning. LLM förtränas med offentliga data, men den genererar svar som utökas av information från hämtaren.

RAG-mönster som inkluderar Azure AI Search innehåller de element som anges i följande bild.

Arkitekturdiagram över informationshämtning med sökning och ChatGPT.

  • App-UX (webbapp) för användarupplevelsen
  • Appserver eller orchestrator (integrerings- och samordningslager)
  • Azure AI Search (informationshämtningssystem)
  • Azure OpenAI (LLM för generativ AI)

Webbappen tillhandahåller användarupplevelsen och tillhandahåller presentation, kontext och användarinteraktion. Frågor eller frågor från en användare börjar här. Indata passerar genom integreringsskiktet och går först till informationshämtning för att hämta sökresultaten, men går också till LLM för att ange kontext och avsikt.

Appservern eller orkestratorn är integrationskoden som samordnar överlämningarna mellan informationshämtning och LLM. Ett alternativ är att använda LangChain för att samordna arbetsflödet. LangChain integreras med Azure AI Search, vilket gör det enklare att inkludera Azure AI Search som en retriever i arbetsflödet. Semantisk kernel är ett annat alternativ.

Informationshämtningssystemet innehåller det sökbara indexet, frågelogik och nyttolasten (frågesvar). Sökindexet kan innehålla vektorer eller icke-bevektorinnehåll. Även om de flesta exempel och demonstrationer innehåller vektorfält är det inte ett krav. Frågan körs med hjälp av den befintliga sökmotorn i Azure AI Search, som kan hantera nyckelord (eller term) och vektorfrågor. Indexet skapas i förväg baserat på ett schema som du definierar och läses in med ditt innehåll som kommer från filer, databaser eller lagring.

LLM tar emot den ursprungliga prompten, plus resultatet från Azure AI Search. LLM analyserar resultaten och formulerar ett svar. Om LLM är ChatGPT kan användarinteraktionen vara en konversation fram och tillbaka. Om du använder Davinci kan frågan vara ett fullständigt sammansatt svar. En Azure-lösning använder troligen Azure OpenAI, men det finns inget hårt beroende av den här specifika tjänsten.

Azure AI Search tillhandahåller inte inbyggd LLM-integrering för snabbflöden eller chattkonservering, så du måste skriva kod som hanterar orkestrering och tillstånd. Du kan granska demokällan (Azure-Samples/azure-search-openai-demo) för en skiss av vad en fullständig lösning innebär. Vi rekommenderar också Att Azure AI Studio eller Azure OpenAI Studio skapar RAG-baserade Azure AI Search-lösningar som integreras med LLM:er.

I Azure AI Search lagras allt sökbart innehåll i ett sökindex som finns i söktjänsten. Ett sökindex är utformat för snabba frågor med svarstider på millisekunder, så dess interna datastrukturer finns för att stödja det målet. För detta ändamål lagrar ett sökindex indexerat innehåll och inte hela innehållsfiler som hela PDF-filer eller bilder. Internt inkluderar datastrukturerna inverterade index för tokeniserad text, vektorindex för inbäddningar och oförändrad text för fall där ordagrann matchning krävs (till exempel i filter, fuzzy-sökning, frågor om reguljära uttryck).

När du konfigurerar data för din RAG-lösning använder du de funktioner som skapar och läser in ett index i Azure AI Search. Ett index innehåller fält som duplicerar eller representerar källinnehållet. Ett indexfält kan vara enkel överföring (en rubrik eller beskrivning i ett källdokument blir en rubrik eller beskrivning i ett sökindex), eller ett fält kan innehålla utdata från en extern process, till exempel vektorisering eller färdighetsbearbetning som genererar en representation eller textbeskrivning av en bild.

Eftersom du förmodligen vet vilken typ av innehåll du vill söka igenom bör du överväga de indexeringsfunktioner som gäller för varje innehållstyp:

Innehållstyp Indexerat som Funktioner
text tokens, oförändrad text Indexerare kan hämta oformaterad text från andra Azure-resurser som Azure Storage och Cosmos DB. Du kan också push-överföra JSON-innehåll till ett index. Om du vill ändra text under flygning använder du analysverktyg och normaliserare för att lägga till lexikal bearbetning under indexering. Synonymkartor är användbara om källdokument saknar terminologi som kan användas i en fråga.
text vektorer 1 Text kan segmenteras och vektoriseras externt och sedan indexeras som vektorfält i ditt index.
bild tokens, oförändrad text 2 Kunskaper för OCR och bildanalys kan bearbeta bilder för textigenkänning eller bildegenskaper. Bildinformation konverteras till sökbar text och läggs till i indexet. Kunskaper har ett indexerarekrav.
bild vektorer 1 Bilder kan vektoriseras externt för en matematisk representation av bildinnehåll och sedan indexeras som vektorfält i ditt index. Du kan använda en öppen källkod modell som OpenAI CLIP för att vektorisera text och bilder i samma inbäddningsutrymme.

1 Den allmänt tillgängliga funktionen för vektorstöd kräver att du anropar andra bibliotek eller modeller för datasegmentering och vektorisering. Integrerad vektorisering (förhandsversion) bäddar dock in de här stegen. Kodexempel som visar båda metoderna finns i lagringsplatsen azure-search-vectors.

2Färdigheter är inbyggt stöd för AI-berikande. För OCR och bildanalys gör indexeringspipelinen ett internt anrop till Api:erna för Azure AI Vision. Dessa kunskaper skickar en extraherad avbildning till Azure AI för bearbetning och tar emot utdata som text som indexeras av Azure AI Search.

Vektorer är det bästa alternativet för olika innehåll (flera filformat och språk) eftersom innehållet uttrycks universellt i matematiska representationer. Vektorer stöder också likhetssökning: matchning på koordinaterna som mest liknar vektorfrågan. Jämfört med nyckelordssökning (eller termsökning) som matchar tokeniserade termer är likhetssökningen mer nyanserad. Det är ett bättre val om det finns tvetydighets- eller tolkningskrav i innehållet eller i frågor.

När dina data finns i ett sökindex använder du frågefunktionerna i Azure AI Search för att hämta innehåll.

I ett icke-RAG-mönster gör frågor en tur och retur från en sökklient. Frågan skickas, den körs på en sökmotor och svaret returneras till klientprogrammet. Svaret, eller sökresultatet, består uteslutande av det ordagranna innehållet som finns i ditt index.

I ett RAG-mönster samordnas frågor och svar mellan sökmotorn och LLM. En användares fråga eller fråga vidarebefordras till både sökmotorn och till LLM som en uppmaning. Sökresultaten kommer tillbaka från sökmotorn och omdirigeras till en LLM. Svaret som gör det tillbaka till användaren är generativ AI, antingen en sammanfattning eller ett svar från LLM.

Det finns ingen frågetyp i Azure AI Search – inte ens semantisk sökning eller vektorsökning – som skapar nya svar. Endast LLM tillhandahåller generativ AI. Här är funktionerna i Azure AI Search som används för att formulera frågor:

Frågefunktion Syfte Varför du ska använda det
Enkel eller fullständig Lucene-syntax Frågekörning över text och icke-numeriskt innehåll Fulltextsökning är bäst för exakta matchningar, snarare än liknande matchningar. Fulltextsökningsfrågor rangordnas med BM25-algoritmen och stöder relevansjustering via bedömningsprofiler. Den stöder också filter och fasetter.
Filter och fasetter Gäller endast för text- eller numeriska fält (icke-belackare). Minskar sökytan baserat på inkluderings- eller exkluderingskriterier. Lägger till precision i dina frågor.
Semantisk rankning Rangordna om en BM25-resultatuppsättning med hjälp av semantiska modeller. Genererar korta bildtext och svar som är användbara som LLM-indata. Enklare än att bedöma profiler, och beroende på ditt innehåll är en mer tillförlitlig teknik för relevansjustering.
Vektorsökning Frågekörning över vektorfält för likhetssökning, där frågesträngen är en eller flera vektorer. Vektorer kan representera alla typer av innehåll på valfritt språk.
Hybridsökning Kombinerar någon av eller alla ovanstående frågetekniker. Vektor- och nonvector-frågor körs parallellt och returneras i en enhetlig resultatuppsättning. De viktigaste vinsterna i precision och återkallande är genom hybridfrågor.

Strukturera frågesvaret

En frågas svar ger indata till LLM, så kvaliteten på sökresultaten är avgörande för att lyckas. Resultatet är en tabellraduppsättning. Resultatets sammansättning eller struktur beror på:

  • Fält som avgör vilka delar av indexet som ingår i svaret.
  • Rader som representerar en matchning från index.

Fält visas i sökresultat när attributet är "hämtningsbart". En fältdefinition i indexschemat har attribut och de avgör om ett fält används i ett svar. Endast "hämtningsbara" fält returneras i fulltext- eller vektorfrågeresultat. Som standard returneras alla "hämtningsbara" fält, men du kan använda "select" för att ange en delmängd. Förutom "hämtningsbar" finns det inga begränsningar för fältet. Fält kan vara av valfri längd eller typ. När det gäller längd finns det ingen gräns för maximal fältlängd i Azure AI Search, men det finns gränser för storleken på en API-begäran.

Rader matchar frågan, rangordnade efter relevans, likhet eller båda. Som standard begränsas resultaten till de 50 bästa matchningarna för fulltextsökning eller k-närmaste granne-matchningar för vektorsökning. Du kan ändra standardvärdena för att öka eller minska gränsen till högst 1 000 dokument. Du kan också använda de översta och hoppa över växlingsparametrar för att hämta resultat som en serie sidsidiga resultat.

Rangordning efter relevans

När du arbetar med komplexa processer, en stor mängd data och förväntningar på millisekunders svar är det viktigt att varje steg tillför värde och förbättrar slutresultatets kvalitet. På informationshämtningssidan är relevansjustering en aktivitet som förbättrar kvaliteten på resultaten som skickas till LLM. Endast de mest relevanta eller mest liknande matchande dokumenten ska ingå i resultaten.

Relevans gäller för nyckelordssökning (nonvector) och hybridfrågor (över fälten nonvector). I Azure AI Search finns det ingen relevansjustering för likhetssöknings- och vektorfrågor. BM25-rangordning är rangordningsalgoritmen för fulltextsökning.

Relevansjustering stöds via funktioner som förbättrar BM25-rangordningen. Dessa metoder omfattar:

  • Bedömningsprofiler som ökar sökpoängen om matchningar hittas i ett specifikt sökfält eller på andra kriterier.
  • Semantisk rangordning som rangordnar om en BM25-resultatuppsättning med hjälp av semantiska modeller från Bing för att ordna om resultaten för en bättre semantisk anpassning till den ursprungliga frågan.

Vid jämförelse- och benchmark-testning ger hybridfrågor med text- och vektorfält, kompletterade med semantisk rangordning över BM25-rankade resultat, de mest relevanta resultaten.

Exempelkod för en Azure AI Search-fråga för RAG-scenarier

Följande kod kopieras från filen retrievethenread.py från en demowebbplats. Den genererar content för LLM från hybridfrågesökningsresultat. Du kan skriva en enklare fråga, men det här exemplet omfattar vektorsökning och nyckelordssökning med semantisk omrankning och stavningskontroll. I demonstrationen används den här frågan för att hämta initialt innehåll.

# Use semantic ranker if requested and if retrieval mode is text or hybrid (vectors + text)
if overrides.get("semantic_ranker") and has_text:
    r = await self.search_client.search(query_text,
                                  filter=filter,
                                  query_type=QueryType.SEMANTIC,
                                  query_language="en-us",
                                  query_speller="lexicon",
                                  semantic_configuration_name="default",
                                  top=top,
                                  query_caption="extractive|highlight-false" if use_semantic_captions else None,
                                  vector=query_vector,
                                  top_k=50 if query_vector else None,
                                  vector_fields="embedding" if query_vector else None)
else:
    r = await self.search_client.search(query_text,
                                  filter=filter,
                                  top=top,
                                  vector=query_vector,
                                  top_k=50 if query_vector else None,
                                  vector_fields="embedding" if query_vector else None)
if use_semantic_captions:
    results = [doc[self.sourcepage_field] + ": " + nonewlines(" . ".join([c.text for c in doc['@search.captions']])) async for doc in r]
else:
    results = [doc[self.sourcepage_field] + ": " + nonewlines(doc[self.content_field]) async for doc in r]
content = "\n".join(results)

Integreringskod och LLM:er

En RAG-lösning som innehåller Azure AI Search kräver andra komponenter och kod för att skapa en komplett lösning. Medan föregående avsnitt beskriver informationshämtning via Azure AI Search och vilka funktioner som används för att skapa och fråga sökbart innehåll, introducerar det här avsnittet LLM-integrering och interaktion.

Notebook-filer i demolagringsplatserna är en bra startpunkt eftersom de visar mönster för att skicka sökresultat till en LLM. Merparten av koden i en RAG-lösning består av anrop till LLM så du behöver utveckla en förståelse för hur dessa API:er fungerar, vilket ligger utanför omfånget för den här artikeln.

Följande cellblock i notebook-filen chat-read-retrieve-read.ipynb visar sökanrop i kontexten för en chattsession:

# Execute this cell multiple times updating user_input to accumulate chat history
user_input = "Does my plan cover annual eye exams?"

# Exclude category, to simulate scenarios where there's a set of docs you can't see
exclude_category = None

if len(history) > 0:
    completion = openai.Completion.create(
        engine=AZURE_OPENAI_GPT_DEPLOYMENT,
        prompt=summary_prompt_template.format(summary="\n".join(history), question=user_input),
        temperature=0.7,
        max_tokens=32,
        stop=["\n"])
    search = completion.choices[0].text
else:
    search = user_input

# Alternatively simply use search_client.search(q, top=3) if not using semantic ranking
print("Searching:", search)
print("-------------------")
filter = "category ne '{}'".format(exclude_category.replace("'", "''")) if exclude_category else None
r = search_client.search(search, 
                         filter=filter,
                         query_type=QueryType.SEMANTIC, 
                         query_language="en-us", 
                         query_speller="lexicon", 
                         semantic_configuration_name="default", 
                         top=3)
results = [doc[KB_FIELDS_SOURCEPAGE] + ": " + doc[KB_FIELDS_CONTENT].replace("\n", "").replace("\r", "") for doc in r]
content = "\n".join(results)

prompt = prompt_prefix.format(sources=content) + prompt_history + user_input + turn_suffix

completion = openai.Completion.create(
    engine=AZURE_OPENAI_CHATGPT_DEPLOYMENT, 
    prompt=prompt, 
    temperature=0.7, 
    max_tokens=1024,
    stop=["<|im_end|>", "<|im_start|>"])

prompt_history += user_input + turn_suffix + completion.choices[0].text + "\n<|im_end|>" + turn_prefix
history.append("user: " + user_input)
history.append("assistant: " + completion.choices[0].text)

print("\n-------------------\n".join(history))
print("\n-------------------\nPrompt:\n" + prompt)

Så här kommer du igång

  • Granska indexeringsbegrepp och strategier för att avgöra hur du vill mata in och uppdatera data. Bestäm om du vill använda vektorsökning, nyckelordssökning eller hybridsökning. Vilken typ av innehåll du behöver söka efter och vilken typ av frågor du vill köra avgör indexdesignen.

  • Läs om hur du skapar frågor för att lära dig mer om syntax och krav för sökbegäran.

Kommentar

Vissa Azure AI Search-funktioner är avsedda för mänsklig interaktion och är inte användbara i ett RAG-mönster. Mer specifikt kan du hoppa över automatisk komplettering och förslag. Andra funktioner som fasetter och orderby kan vara användbara, men skulle vara ovanliga i ett RAG-scenario.

Se även