Sdílet prostřednictvím


Kurz: Prozkoumání vkládání a vyhledávání dokumentů ve službě Azure OpenAI

Tento kurz vás provede používáním rozhraní API pro vkládání Azure OpenAI k provádění hledání dokumentů, ve kterém zadáte dotaz na znalostní báze, abyste našli nejrelevavantnější dokument.

V tomto kurzu se naučíte:

  • Nainstalujte Azure OpenAI.
  • Stáhněte si ukázkovou datovou sadu a připravte ji na analýzu.
  • Vytvořte proměnné prostředí pro koncový bod prostředků a klíč rozhraní API.
  • Použijte jeden z následujících modelů: text-embedding-ada-002 (verze 2), text-embedding-3-large, text-embedding-3-small models.
  • K řazení výsledků hledání použijte kosinusovou podobnost .

Požadavky

Nastavení

Knihovny Pythonu

Pokud jste to ještě neudělali, musíte nainstalovat následující knihovny:

pip install openai num2words matplotlib plotly scipy scikit-learn pandas tiktoken

Stažení datové sady BillSum

BillSum je datová sada USA kongresových a kaliforniových státních faktur. Pro ilustraci se podíváme jenom na faktury v USA. Korpus se skládá z vyúčtování z kongresových zasedání 103. Data byla rozdělena na 18 949 faktur za vlak a 3 269 zkušebních faktur. Korpus BillSum se zaměřuje na právní předpisy střední délky od 5 000 do 20 000 znaků. Další informace o projektu a původním akademickém dokumentu, ze kterého je tato datová sada odvozena, najdete v úložišti GitHub projektu BillSum.

V tomto kurzu se bill_sum_data.csv používá soubor, který je možné stáhnout z našich ukázkových dat GitHubu.

Ukázková data si můžete stáhnout také spuštěním následujícího příkazu na místním počítači:

curl "https://raw.githubusercontent.com/Azure-Samples/Azure-OpenAI-Docs-Samples/main/Samples/Tutorials/Embeddings/data/bill_sum_data.csv" --output bill_sum_data.csv

Načtení klíče a koncového bodu

K úspěšnému volání azure OpenAI potřebujete koncový bod a klíč.

Název proměnné Hodnota
ENDPOINT Koncový bod služby najdete v části Klíče a koncový bod při zkoumání vašeho prostředku na webu Azure Portal. Koncový bod najdete také na stránce Nasazení v Azure AI Studiu. Ukázkový koncový bod je: https://docs-test-001.openai.azure.com/.
API-KEY Tuto hodnotu najdete v části Klíče a koncový bod při zkoumání prostředku na webu Azure Portal. Použít můžete předponu KEY1 nebo KEY2.

Na webu Azure Portal přejděte ke svému prostředku. Oddíl Klíče a koncový bod najdete v části Správa prostředků. Zkopírujte koncový bod a přístupový klíč, protože budete potřebovat obojí pro ověřování volání rozhraní API. Použít můžete předponu KEY1 nebo KEY2. Vždy mít dva klíče vám umožní bezpečně otáčet a znovu vygenerovat klíče, aniž by to způsobilo přerušení služeb.

Snímek obrazovky s přehledovým uživatelským rozhraním pro prostředek Azure OpenAI na webu Azure Portal s červeným kruhem umístění koncového bodu a přístupových klíčů

Proměnné prostředí

Vytvořte a přiřaďte trvalé proměnné prostředí pro klíč a koncový bod.

Důležité

Pokud používáte klíč rozhraní API, uložte ho bezpečně někam jinam, například ve službě Azure Key Vault. Nezahrnujte klíč rozhraní API přímo do kódu a nikdy ho nevštěvujte veřejně.

Další informace o zabezpečení služeb AI najdete v tématu Ověřování požadavků na služby Azure AI.

setx AZURE_OPENAI_API_KEY "REPLACE_WITH_YOUR_KEY_VALUE_HERE" 
setx AZURE_OPENAI_ENDPOINT "REPLACE_WITH_YOUR_ENDPOINT_HERE" 

Po nastavení proměnných prostředí možná budete muset zavřít a znovu otevřít poznámkové bloky Jupyter nebo jakékoli prostředí IDE, které používáte, aby byly proměnné prostředí přístupné. I když důrazně doporučujeme používat poznámkové bloky Jupyter, pokud z nějakého důvodu nebudete muset upravit žádný kód, který vrací datový rámec pandas, namísto print(dataframe_name) pouhého dataframe_name volání přímo, jak se často provádí na konci bloku kódu.

V preferovaném integrovaném vývojovém prostředí Pythonu spusťte následující kód:

Import knihoven

import os
import re
import requests
import sys
from num2words import num2words
import os
import pandas as pd
import numpy as np
import tiktoken
from openai import AzureOpenAI

Teď potřebujeme přečíst soubor CSV a vytvořit datový rámec pandas. Po vytvoření počátečního datového rámce můžeme zobrazit obsah tabulky spuštěním dfpříkazu .

df=pd.read_csv(os.path.join(os.getcwd(),'bill_sum_data.csv')) # This assumes that you have placed the bill_sum_data.csv in the same directory you are running Jupyter Notebooks
df

Výstup:

Snímek obrazovky s počáteční tabulkou datového rámce ze souboru CSV

Počáteční tabulka obsahuje více sloupců, než potřebujeme, vytvoříme nový menší datový rámec, df_bills který bude obsahovat pouze sloupce pro text, summarya title.

df_bills = df[['text', 'summary', 'title']]
df_bills

Výstup:

Snímek obrazovky s menšími výsledky tabulky datového rámce se zobrazenými pouzemi textovými sloupci, souhrnnými sloupci a sloupci nadpisů

V dalším kroku provedeme čištění lehkých dat odebráním nadbytečných prázdných znaků a vyčištěním interpunkce pro přípravu dat na tokenizaci.

pd.options.mode.chained_assignment = None #https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#evaluation-order-matters

# s is input text
def normalize_text(s, sep_token = " \n "):
    s = re.sub(r'\s+',  ' ', s).strip()
    s = re.sub(r". ,","",s)
    # remove all instances of multiple spaces
    s = s.replace("..",".")
    s = s.replace(". .",".")
    s = s.replace("\n", "")
    s = s.strip()
    
    return s

df_bills['text']= df_bills["text"].apply(lambda x : normalize_text(x))

Teď musíme odebrat všechny faktury, které jsou pro limit tokenu příliš dlouhé (8192 tokenů).

tokenizer = tiktoken.get_encoding("cl100k_base")
df_bills['n_tokens'] = df_bills["text"].apply(lambda x: len(tokenizer.encode(x)))
df_bills = df_bills[df_bills.n_tokens<8192]
len(df_bills)
20

Poznámka:

V tomto případě jsou všechny faktury pod limitem vstupního tokenu modelu vložení, ale výše uvedenou techniku můžete použít k odebrání položek, které by jinak způsobily selhání vkládání. Když se setkáte s obsahem, který překračuje limit vkládání, můžete obsah také rozdělit na menší části a pak je vložit po jednom.

Znovu prozkoumáme df_bills.

df_bills

Výstup:

Snímek obrazovky datového rámce s novým sloupcem s názvem n_tokens

Pokud chcete porozumět n_tokens sloupci trochu víc a zjistit, jak se text nakonec tokenizuje, může být užitečné spustit následující kód:

sample_encode = tokenizer.encode(df_bills.text[0]) 
decode = tokenizer.decode_tokens_bytes(sample_encode)
decode

Pro naše dokumenty záměrně zkracujeme výstup, ale spuštění tohoto příkazu ve vašem prostředí vrátí celý text z indexu nula tokenizovaných do bloků dat. Vidíte, že v některých případech je celé slovo reprezentováno jedním tokenem, zatímco v jiných částech slov jsou rozdělené mezi více tokenů.

[b'SECTION',
 b' ',
 b'1',
 b'.',
 b' SHORT',
 b' TITLE',
 b'.',
 b' This',
 b' Act',
 b' may',
 b' be',
 b' cited',
 b' as',
 b' the',
 b' ``',
 b'National',
 b' Science',
 b' Education',
 b' Tax',
 b' In',
 b'cent',
 b'ive',
 b' for',
 b' Businesses',
 b' Act',
 b' of',
 b' ',
 b'200',
 b'7',
 b"''.",
 b' SEC',
 b'.',
 b' ',
 b'2',
 b'.',
 b' C',
 b'RED',
 b'ITS',
 b' FOR',
 b' CERT',
 b'AIN',
 b' CONTRIBUT',
 b'IONS',
 b' BEN',
 b'EF',
 b'IT',
 b'ING',
 b' SC',

Pokud pak zkontrolujete délku decode proměnné, zjistíte, že odpovídá prvnímu číslu ve sloupci n_tokens.

len(decode)
1466

Teď, když rozumíme tomu, jak tokenizace funguje, můžeme přejít na vkládání. Je důležité si uvědomit, že jsme dokumenty ještě tokenizovali. Sloupec n_tokens je jednoduše způsob, jak zajistit, aby žádná data, která předáme modelu pro tokenizaci a vkládání, překročila limit vstupního tokenu 8 192. Když dokumenty předáme modelu vkládání, rozdělí dokumenty na tokeny podobné (i když nemusí nutně identické) výše uvedeným příkladům a pak převede tokeny na řadu čísel s plovoucí desetinou čárkou, která budou přístupná prostřednictvím vektorového vyhledávání. Tyto vkládání je možné ukládat místně nebo ve službě Azure Database za účelem podpory vektorového vyhledávání. V důsledku toho bude mít každý faktura svůj vlastní odpovídající vektor vložení do nového ada_v2 sloupce na pravé straně datového rámce.

V následujícím příkladu voláme model vkládání jednou pro každou položku, kterou chceme vložit. Při práci s velkými projekty vkládání můžete alternativně předat model pole vstupů pro vložení místo jednoho vstupu najednou. Když předáte modelu pole vstupů, maximální počet vstupních položek na volání koncového bodu vkládání je 2048.

client = AzureOpenAI(
  api_key = os.getenv("AZURE_OPENAI_API_KEY"),  
  api_version = "2024-02-01",
  azure_endpoint = os.getenv("AZURE_OPENAI_ENDPOINT")
)

def generate_embeddings(text, model="text-embedding-ada-002"): # model = "deployment_name"
    return client.embeddings.create(input = [text], model=model).data[0].embedding

df_bills['ada_v2'] = df_bills["text"].apply(lambda x : generate_embeddings (x, model = 'text-embedding-ada-002')) # model should be set to the deployment name you chose when you deployed the text-embedding-ada-002 (Version 2) model
df_bills

Výstup:

Snímek obrazovky s formátovanými výsledky z příkazu df_bills

Když níže spustíme blok vyhledávacího kódu, vložíme vyhledávací dotaz "Můžu získat informace o daňových výnosech kabelové společnosti?". se stejným modelem text-embedding-ada-002 (verze 2). V dalším kroku najdeme nejbližší vložení faktury k nově vloženému textu z dotazu seřazeného podle kosinusové podobnosti.

def cosine_similarity(a, b):
    return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))

def get_embedding(text, model="text-embedding-ada-002"): # model = "deployment_name"
    return client.embeddings.create(input = [text], model=model).data[0].embedding

def search_docs(df, user_query, top_n=4, to_print=True):
    embedding = get_embedding(
        user_query,
        model="text-embedding-ada-002" # model should be set to the deployment name you chose when you deployed the text-embedding-ada-002 (Version 2) model
    )
    df["similarities"] = df.ada_v2.apply(lambda x: cosine_similarity(x, embedding))

    res = (
        df.sort_values("similarities", ascending=False)
        .head(top_n)
    )
    if to_print:
        display(res)
    return res


res = search_docs(df_bills, "Can I get information on cable company tax revenue?", top_n=4)

Výstup:

Snímek obrazovky s formátovanými výsledky res po spuštění vyhledávacího dotazu

Nakonec zobrazíme nejlepší výsledek hledání dokumentů na základě uživatelského dotazu na celou znalostní báze. Vrátí nejvyšší výsledek "Právo daňového poplatníka zobrazit zákon z roku 1993". Tento dokument má skóre kosinus podobnosti 0,76 mezi dotazem a dokumentem:

res["summary"][9]
"Taxpayer's Right to View Act of 1993 - Amends the Communications Act of 1934 to prohibit a cable operator from assessing separate charges for any video programming of a sporting, theatrical, or other entertainment event if that event is performed at a facility constructed, renovated, or maintained with tax revenues or by an organization that receives public financial support. Authorizes the Federal Communications Commission and local franchising authorities to make determinations concerning the applicability of such prohibition. Sets forth conditions under which a facility is considered to have been constructed, maintained, or renovated with tax revenues. Considers events performed by nonprofit or public organizations that receive tax subsidies to be subject to this Act if the event is sponsored by, or includes the participation of a team that is part of, a tax exempt organization."

Požadavky

Poznámka:

Mnoho příkladů v tomto kurzu znovu používá proměnné z kroku do kroku. Nechte stejnou relaci terminálu otevřenou po celou dobu. Pokud dojde ke ztrátě proměnných nastavených v předchozím kroku kvůli zavření terminálu, musíte začít znovu od začátku.

Načtení klíče a koncového bodu

K úspěšnému volání azure OpenAI potřebujete koncový bod a klíč.

Název proměnné Hodnota
ENDPOINT Koncový bod služby najdete v části Klíče a koncový bod při zkoumání vašeho prostředku na webu Azure Portal. Koncový bod najdete také na stránce Nasazení v Azure AI Studiu. Ukázkový koncový bod je: https://docs-test-001.openai.azure.com/.
API-KEY Tuto hodnotu najdete v části Klíče a koncový bod při zkoumání prostředku na webu Azure Portal. Použít můžete předponu KEY1 nebo KEY2.

Na webu Azure Portal přejděte ke svému prostředku. Oddíl Klíče a koncový bod najdete v části Správa prostředků. Zkopírujte koncový bod a přístupový klíč, protože budete potřebovat obojí pro ověřování volání rozhraní API. Použít můžete předponu KEY1 nebo KEY2. Vždy mít dva klíče vám umožní bezpečně otáčet a znovu vygenerovat klíče, aniž by to způsobilo přerušení služeb.

Snímek obrazovky s přehledovým uživatelským rozhraním pro prostředek Azure OpenAI na webu Azure Portal s červeným kruhem umístění koncového bodu a přístupových klíčů

Proměnné prostředí

Vytvořte a přiřaďte trvalé proměnné prostředí pro klíč a koncový bod.

Důležité

Pokud používáte klíč rozhraní API, uložte ho bezpečně někam jinam, například ve službě Azure Key Vault. Nezahrnujte klíč rozhraní API přímo do kódu a nikdy ho nevštěvujte veřejně.

Další informace o zabezpečení služeb AI najdete v tématu Ověřování požadavků na služby Azure AI.

setx AZURE_OPENAI_API_KEY "REPLACE_WITH_YOUR_KEY_VALUE_HERE" 
setx AZURE_OPENAI_ENDPOINT "REPLACE_WITH_YOUR_ENDPOINT_HERE" 

Pro účely tohoto kurzu používáme referenční dokumentaci k PowerShellu 7.4 jako známou a bezpečnou ukázkovou datovou sadu. Jako alternativu se můžete rozhodnout prozkoumat ukázkové datové sady nástrojů Microsoft Research.

Vytvořte složku, do které chcete projekt uložit. Nastavte umístění do složky projektu. Pomocí příkazu stáhněte datovou sadu do místního počítače Invoke-WebRequest a rozbalte archiv. Nakonec nastavte umístění na podsložku obsahující referenční informace pro PowerShell verze 7.4.

New-Item '<FILE-PATH-TO-YOUR-PROJECT>' -Type Directory
Set-Location '<FILE-PATH-TO-YOUR-PROJECT>'

$DocsUri = 'https://github.com/MicrosoftDocs/PowerShell-Docs/archive/refs/heads/main.zip'
Invoke-WebRequest $DocsUri -OutFile './PSDocs.zip'

Expand-Archive './PSDocs.zip'
Set-Location './PSDocs/PowerShell-Docs-main/reference/7.4/'

V tomto kurzu pracujeme s velkým množstvím dat, takže pro efektivní výkon používáme objekt tabulky dat .NET. Datatable obsahuje název sloupců, obsah, přípravu, identifikátor URI, soubor a vektory. Sloupec nadpisu je primární klíč.

V dalším kroku načteme obsah každého souboru Markdownu do tabulky dat. Pomocí operátoru PowerShellu -match zachytáváme známé řádky textu title: a online version:ukládáme je do různých sloupců. Některé soubory neobsahují řádky metadat textu, ale protože jsou to stránky s přehledem a ne podrobné referenční dokumenty, vyloučíme je z datové tabulky.

# make sure your location is the project subfolder

$DataTable = New-Object System.Data.DataTable

'title', 'content', 'prep', 'uri', 'file', 'vectors' | ForEach-Object {
    $DataTable.Columns.Add($_)
} | Out-Null
$DataTable.PrimaryKey = $DataTable.Columns['title']

$md = Get-ChildItem -Path . -Include *.md -Recurse

$md | ForEach-Object {
    $file       = $_.FullName
    $content    = Get-Content $file
    $title      = $content | Where-Object { $_ -match 'title: ' }
    $uri        = $content | Where-Object { $_ -match 'online version: ' }
    if ($title -and $uri) {
        $row                = $DataTable.NewRow()
        $row.title          = $title.ToString().Replace('title: ', '')
        $row.content        = $content | Out-String
        $row.prep           = '' # use later in the tutorial
        $row.uri            = $uri.ToString().Replace('online version: ', '')
        $row.file           = $file
        $row.vectors        = '' # use later in the tutorial
        $Datatable.rows.add($row)
    }
}

Zobrazte data pomocí příkazu (není k dispozici v Cloud Shellu out-gridview ).

$Datatable | out-gridview

Výstup:

Snímek obrazovky s počátečními výsledky tabulky DataTable

Dále proveďte čištění lehkých dat odebráním nadbytečných znaků, prázdných mezer a dalších zápisů dokumentů, aby se data připravila na tokenizaci. Ukázková funkce Invoke-DocPrep ukazuje, jak pomocí operátoru PowerShellu -replace iterovat seznamem znaků, které chcete z obsahu odebrat.

# sample demonstrates how to use `-replace` to remove characters from text content
function Invoke-DocPrep {
param(
    [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
    [string]$content
)
    # tab, line breaks, empty space
    $replace = @('\t','\r\n','\n','\r')
    # non-UTF8 characters
    $replace += @('[^\x00-\x7F]')
    # html
    $replace += @('<table>','</table>','<tr>','</tr>','<td>','</td>')
    $replace += @('<ul>','</ul>','<li>','</li>')
    $replace += @('<p>','</p>','<br>')
    # docs
    $replace += @('\*\*IMPORTANT:\*\*','\*\*NOTE:\*\*')
    $replace += @('<!','no-loc ','text=')
    $replace += @('<--','-->','---','--',':::')
    # markdown
    $replace += @('###','##','#','```')
    $replace | ForEach-Object {
        $content = $content -replace $_, ' ' -replace '  ',' '
    }
    return $content
}

Po vytvoření Invoke-DocPrep funkce pomocí ForEach-Object příkazu uložte připravený obsah do sloupce přípravy pro všechny řádky v datové tabulce. Používáme nový sloupec, takže původní formátování je k dispozici, pokud bychom ho chtěli později načíst.

$Datatable.rows | ForEach-Object { $_.prep = Invoke-DocPrep $_.content }

Znovu zobrazte tabulku dat a podívejte se na změnu.

$Datatable | out-gridview

Když dokumenty předáme modelu vkládání, zakóduje dokumenty do tokenů a pak vrátí řadu čísel s plovoucí desetinou čárkou , která se použije při hledání kosinus podobnosti . Tyto vkládání je možné ukládat místně nebo ve službě, jako je vektorové vyhledávání ve službě Azure AI Search. Každý dokument má vlastní odpovídající vektor vkládání do nového sloupce vektorů .

Další příklad prochází každý řádek v datové tabulce, načte vektory pro předzpracovaný obsah a uloží je do sloupce vektorů . Služba OpenAI omezuje časté požadavky, takže příklad obsahuje exponenciální zpětné vypnutí , jak navrhuje dokumentace.

Po dokončení skriptu by každý řádek měl obsahovat čárkami oddělený seznam 1536 vektorů pro každý dokument. Pokud dojde k chybě a stavový kód je 400, cesta k souboru, název a kód chyby se přidají do proměnné s názvem $errorDocs pro řešení potíží. K nejčastější chybě dochází v případě, že je počet tokenů větší než limit výzvy pro model.

# Azure OpenAI metadata variables
$openai = @{
    api_key     = $Env:AZURE_OPENAI_API_KEY 
    api_base    = $Env:AZURE_OPENAI_ENDPOINT # should look like 'https://<YOUR_RESOURCE_NAME>.openai.azure.com/'
    api_version = '2024-02-01' # may change in the future
    name        = $Env:AZURE_OPENAI_EMBEDDINGS_DEPLOYMENT # custom name you chose for your deployment
}

$headers = [ordered]@{
    'api-key' = $openai.api_key
}

$url = "$($openai.api_base)/openai/deployments/$($openai.name)/embeddings?api-version=$($openai.api_version)"

$Datatable | ForEach-Object {
    $doc = $_

    $body = [ordered]@{
        input = $doc.prep
    } | ConvertTo-Json

    $retryCount = 0
    $maxRetries = 10
    $delay      = 1
    $docErrors = @()

    do {
        try {
            $params = @{
                Uri         = $url
                Headers     = $headers
                Body        = $body
                Method      = 'Post'
                ContentType = 'application/json'
            }
            $response = Invoke-RestMethod @params
            $Datatable.rows.find($doc.title).vectors = $response.data.embedding -join ','
            break
        } catch {
            if ($_.Exception.Response.StatusCode -eq 429) {
                $retryCount++
                [int]$retryAfter = $_.Exception.Response.Headers |
                    Where-Object key -eq 'Retry-After' |
                    Select-Object -ExpandProperty Value

                # Use delay from error header
                if ($delay -lt $retryAfter) { $delay = $retryAfter++ }
                Start-Sleep -Seconds $delay
                # Exponential back-off
                $delay = [math]::min($delay * 1.5, 300)
            } elseif ($_.Exception.Response.StatusCode -eq 400) {
                if ($docErrors.file -notcontains $doc.file) {
                    $docErrors += [ordered]@{
                        error   = $_.exception.ErrorDetails.Message | ForEach-Object error | ForEach-Object message
                        file    = $doc.file
                        title   = $doc.title
                    }
                }
            } else {
                throw
            }
        }
    } while ($retryCount -lt $maxRetries)
}
if (0 -lt $docErrors.count) {
    Write-Host "$($docErrors.count) documents encountered known errors such as too many tokens.`nReview the `$docErrors variable for details."
}

Teď máte místní tabulku databáze v paměti referenční dokumentace k PowerShellu 7.4.

Na základě vyhledávacího řetězce potřebujeme vypočítat další sadu vektorů, aby PowerShell mohl každý dokument seřadit podle podobnosti.

V dalším příkladu se vektory načtou pro hledaný řetězec get a list of running processes.

$searchText = "get a list of running processes"

$body = [ordered]@{
    input = $searchText
} | ConvertTo-Json

$url = "$($openai.api_base)/openai/deployments/$($openai.name)/embeddings?api-version=$($openai.api_version)"

$params = @{
    Uri         = $url
    Headers     = $headers
    Body        = $body
    Method      = 'Post'
    ContentType = 'application/json'
}
$response = Invoke-RestMethod @params
$searchVectors = $response.data.embedding -join ','

A konečně další ukázková funkce, která si půjčí příklad z ukázkového skriptu Measure-VectorSimilarity napsané Lee Holmesem, provede výpočet kosinus podobnosti a potom seřadí každý řádek v datové tabulce.

# Sample function to calculate cosine similarity
function Get-CosineSimilarity ([float[]]$vector1, [float[]]$vector2) {
    $dot = 0
    $mag1 = 0
    $mag2 = 0

    $allkeys = 0..($vector1.Length-1)

    foreach ($key in $allkeys) {
        $dot  += $vector1[$key]  * $vector2[$key]
        $mag1 += ($vector1[$key] * $vector1[$key])
        $mag2 += ($vector2[$key] * $vector2[$key])
    }

    $mag1 = [Math]::Sqrt($mag1)
    $mag2 = [Math]::Sqrt($mag2)

    return [Math]::Round($dot / ($mag1 * $mag2), 3)
}

Příkazy v další ukázkové smyčce procházejí všemi řádky a $Datatable vypočítají kosinus podobnost s hledaný řetězec. Výsledky jsou seřazené a nejlepší tři výsledky jsou uloženy v proměnné s názvem $topThree. Příklad nevrací výstup.

# Calculate cosine similarity for each row and select the top 3
$topThree = $Datatable | ForEach-Object {
    [PSCustomObject]@{
        title = $_.title
        similarity = Get-CosineSimilarity $_.vectors.split(',') $searchVectors.split(',')
    }
} | Sort-Object -property similarity -descending | Select-Object -First 3 | ForEach-Object {
    $title = $_.title
    $Datatable | Where-Object { $_.title -eq $title }
}

Prohlédněte si výstup $topThree proměnné s pouze vlastnostmi názvu a adresy URL v gridview.

$topThree | Select "title", "uri" | Out-GridView

Výstup:

Snímek obrazovky s formátovanými výsledky po dokončení vyhledávacího dotazu

Proměnná $topThree obsahuje všechny informace z řádků v datové tabulce. Například vlastnost obsahu obsahuje původní formát dokumentu. Slouží [0] k indexování první položky v poli.

$topThree[0].content

Zobrazte si celý dokument (zkrácený ve výstupním fragmentu pro tuto stránku).

---
external help file: Microsoft.PowerShell.Commands.Management.dll-Help.xml
Locale: en-US
Module Name: Microsoft.PowerShell.Management
ms.date: 07/03/2023
online version: https://learn.microsoft.com/powershell/module/microsoft.powershell.management/get-process?view=powershell-7.4&WT.mc_id=ps-gethelp
schema: 2.0.0
title: Get-Process
---

# Get-Process

## SYNOPSIS
Gets the processes that are running on the local computer.

## SYNTAX

### Name (Default)

Get-Process [[-Name] <String[]>] [-Module] [-FileVersionInfo] [<CommonParameters>]
# truncated example

A nakonec místo opětovného vygenerování vkládání pokaždé, když budete potřebovat dotazovat datovou sadu, můžete data uložit na disk a v budoucnu je odvolat. Typy WriteXML() objektů DataTable a ReadXML() metody v dalším příkladu proces zjednodušují. Schéma souboru XML vyžaduje, aby datatable měla TableName.

Nahraďte <YOUR-FULL-FILE-PATH> úplnou cestu, do které chcete zapisovat a číst soubor XML. Cesta by měla končit .xml.

# Set DataTable name
$Datatable.TableName = "MyDataTable"

# Writing DataTable to XML
$Datatable.WriteXml("<YOUR-FULL-FILE-PATH>", [System.Data.XmlWriteMode]::WriteSchema)

# Reading XML back to DataTable
$newDatatable = New-Object System.Data.DataTable
$newDatatable.ReadXml("<YOUR-FULL-FILE-PATH>")

Při opětovném použití dat musíte získat vektory každého nového vyhledávacího řetězce (ale ne celou datovou tabulku). Jako výukové cvičení zkuste vytvořit skript PowerShellu Invoke-RestMethod pro automatizaci příkazu pomocí vyhledávacího řetězce jako parametru.

Pomocí tohoto přístupu můžete vkládání použít jako mechanismus vyhledávání v dokumentech v znalostní báze. Uživatel pak může převzít hlavní výsledek hledání a použít ho pro podřízený úkol, který zobrazil výzvu k počátečnímu dotazu.

Vyčištění prostředků

Pokud jste vytvořili prostředek Azure OpenAI výhradně pro dokončení tohoto kurzu a chcete vyčistit a odebrat prostředek Azure OpenAI, budete muset odstranit nasazené modely a pak odstranit prostředek nebo přidruženou skupinu prostředků, pokud je vyhrazený pro testovací prostředek. Odstraněním skupiny prostředků se odstraní také všechny ostatní prostředky, které jsou k ní přidružené.

Další kroky

Další informace o modelech Azure OpenAI: