Share via


Oktatóanyag: Az Azure OpenAI szolgáltatás beágyazásának és a dokumentumkeresésnek a megismerése

Ez az oktatóanyag végigvezeti az Azure OpenAI beágyazási API-val a dokumentumkeresés végrehajtásához, ahol lekérdez egy tudásbázis a legrelevánsabb dokumentum megkereséséhez.

Ebben az oktatóanyagban az alábbiakkal fog megismerkedni:

  • Telepítse az Azure OpenAI-t.
  • Töltsön le egy mintaadatkészletet, és készítse elő elemzésre.
  • Környezeti változók létrehozása az erőforrások végpontjához és az API-kulcshoz.
  • A text-embedding-ada-002 (2. verzió) modell használata
  • A találatok rangsorolásához használjon koszin hasonlóságot .

Előfeltételek

  • Azure-előfizetés – Ingyenes létrehozás
  • A hozzáférést az Azure OpenAI a kívánt Azure-előfizetésen belül kapja meg. Ezen szolgáltatáshoz jelenleg csak alkalmazás útján kapható hozzáférés. Az Azure OpenAI-hoz való hozzáférésre a következő https://aka.ms/oai/accessűrlap kitöltésével jelentkezhet: . Ha probléma merül fel, nyisson meg egy hibát az adattárban, és lépjen velünk kapcsolatba.
  • Azure OpenAI-erőforrás a text-embedding-ada-002 (2. verzió) üzembe helyezett modellel. Ez a modell jelenleg csak bizonyos régiókban érhető el. Ha nem rendelkezik erőforrással, a létrehozás folyamatát az erőforrás-üzembe helyezési útmutatónk dokumentálja.
  • Python 3.8 vagy újabb verzió
  • A következő Python-kódtárak: openai, num2words, matplotlib, plotly, scipy, scikit-learn, pandas, tiktoken.
  • Jupyter notebook

Beállítás

Python-kódtárak

Ha még nem tette meg, telepítenie kell a következő kódtárakat:

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

A BillSum adatkészlet letöltése

A BillSum Egyesült Államok kongresszusi és kaliforniai állami számlák adatkészlete. Illusztrációként csak az amerikai számlákat tekintjük át. A korpusz a Kongresszus 103-115. (1993-2018) üléseinek számláiból áll. Az adatok 18 949 vonatszámlára és 3269 tesztszámlára oszlanak. A BillSum corpus középpontjában a közepes hosszúságú jogszabályok 5000 és 20 000 karakter hosszúságú. A projektről és az eredeti tanulmányról, amelyből ez az adatkészlet származik, a BillSum projekt GitHub-adattárában található.

Ez az oktatóanyag a bill_sum_data.csv GitHub-mintaadatokból letölthető fájlt használja.

A mintaadatok letöltéséhez futtassa a következő parancsot a helyi gépen:

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

Kulcs és végpont lekérése

Az Azure OpenAI-ra való sikeres híváshoz egy végpontra és egy kulcsra van szükség.

Változó neve Érték
ENDPOINT Ez az érték a Kulcsok és végpont szakaszban található meg, amikor megvizsgálja az erőforrást az Azure Portalon. Az értéket az Azure OpenAI Studio>Playground>Code nézetben is megtalálhatja. Példavégpont: https://docs-test-001.openai.azure.com/.
API-KEY Ez az érték a Kulcsok és végpont szakaszban található meg, amikor megvizsgálja az erőforrást az Azure Portalon. A következők bármelyikét használhatja: KEY1 vagy KEY2.

Nyissa meg az erőforrást az Azure Portalon. A Kulcsok > végpont szakasz az Erőforrás-kezelés szakaszban található. Másolja ki a végpontot és a hozzáférési kulcsot, mivel mindkettőre szüksége lesz az API-hívások hitelesítéséhez. A következők bármelyikét használhatja: KEY1 vagy KEY2. A két kulcs mindig lehetővé teszi a kulcsok biztonságos elforgatását és újragenerálását anélkül, hogy szolgáltatáskimaradást okoz.

Képernyőkép egy Azure OpenAI-erőforrás áttekintő felhasználói felületéről az Azure Portalon, a végpont és a hozzáférési kulcsok helye pirossal bekarikázva.

Környezeti változók

setx AZURE_OPENAI_API_KEY "REPLACE_WITH_YOUR_KEY_VALUE_HERE" 
setx AZURE_OPENAI_ENDPOINT "REPLACE_WITH_YOUR_ENDPOINT_HERE" 

A környezeti változók beállítása után előfordulhat, hogy be kell zárnia és újra meg kell nyitnia a Jupyter-jegyzetfüzeteket vagy a használt IDE-t ahhoz, hogy a környezeti változók elérhetők legyenek. Bár határozottan javasoljuk a Jupyter Notebookok használatát, ha valamilyen oknál fogva nem kell módosítania a pandas-adatkeretet print(dataframe_name) visszaíró kódot ahelyett, hogy közvetlenül hívna meg dataframe_name , ahogyan az a kódblokk végén gyakran történik.

Futtassa a következő kódot az előnyben részesített Python IDE-ben:

Kódtárak importálása

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

Most be kell olvasnunk a csv-fájlt, és létre kell hoznunk egy pandas DataFrame-et. A kezdeti DataFrame létrehozása után a tábla tartalmát a futtatással dftekinthetjük meg.

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

Kimeneti:

Képernyőkép a csv-fájlból származó kezdeti DataFrame-tábla eredményeiről.

A kezdeti tábla több oszlopot tartalmaz, mint amire szükségünk van, létrehozunk egy új, kisebb dataFrame nevű df_bills adatkeretet, amely csak a , summaryés titlea text.

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

Kimeneti:

Képernyőkép a kisebb DataFrame-táblázat eredményeiről, csak szöveg-, összegzés- és címoszlopok jelennek meg.

A következő lépésben némi egyszerű adattisztítást hajtunk végre a redundáns térköz eltávolításával és az írásjelek megtisztításával, hogy előkészítsük az adatokat a tokenizáláshoz.

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))

Most el kell távolítanunk azokat a számlákat, amelyek túl hosszúak a jogkivonat-korláthoz (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

Feljegyzés

Ebben az esetben az összes számla a beágyazási modell bemeneti jogkivonat-korlátja alatt van, de a fenti technikával eltávolíthatja azokat a bejegyzéseket, amelyek egyébként a beágyazás meghiúsulását okozzák. Ha olyan tartalommal szembesül, amely meghaladja a beágyazási korlátot, a tartalmat kisebb darabokra is bonthatja, majd egyenként beágyazhatja őket.

Újra megvizsgáljuk df_bills.

df_bills

Kimeneti:

Képernyőkép a DataFrame-ről egy új, n_tokens nevű oszlopmal.

A n_tokens oszlop és a szöveg jogkivonatos állapotának megértéséhez hasznos lehet a következő kód futtatása:

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

A dokumentumaink esetében szándékosan csonkoljuk a kimenetet, de a parancs környezetében való futtatása a nulla jogkivonatú index teljes szövegét adja vissza adattömbökké. Láthatja, hogy egyes esetekben egy teljes szó egyetlen jogkivonattal van ábrázolva, míg más esetekben a szavak egy része több jogkivonatra oszlik.

[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',

Ha ezután ellenőrzi a decode változó hosszát, a n_tokens oszlop első számával egyezik.

len(decode)
1466

Most, hogy többet tudunk a jogkivonat-készítés működéséről, továbbléphetünk a beágyazásra. Fontos megjegyezni, hogy még nem tokenizáltuk a dokumentumokat. Az n_tokens oszlop egyszerűen lehetővé teszi, hogy a modellnek átadott adatok egyike sem haladja meg a 8192 bemeneti jogkivonat-korlátot. Amikor átadjuk a dokumentumokat a beágyazási modellnek, az a fenti példákhoz hasonló (bár nem feltétlenül azonos) jogkivonatokra bontja a dokumentumokat, majd átalakítja a jogkivonatokat lebegőpontos számok sorozatává, amelyek vektorkereséssel lesznek elérhetők. Ezek a beágyazások helyileg vagy egy Azure Database-ben tárolhatók a Vector Search támogatásához. Ennek eredményeképpen minden számlának saját beágyazási vektora lesz a DataFrame jobb oldalán található új ada_v2 oszlopban.

Az alábbi példában minden beágyazni kívánt elemhez egyszer hívjuk meg a beágyazási modellt. Nagy beágyazási projektek használatakor alternatív megoldásként egy bemeneti tömböt is átadhat a modellnek, amelybe nem egyszerre, hanem egy bemenetet ágyazhat be. A modell átadásakor a bemeneti elemek tömbje a beágyazási végpont hívásonkénti maximális száma 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

Kimeneti:

Képernyőkép df_bills parancs formázott eredményeiről.

Az alábbi keresési kódblokk futtatásakor beágyazzuk a következő keresési lekérdezést : "Kaphatok információt a kábelvállalati adóbevételről?" ugyanazzal a text-embedding-ada-002 (2. verzió) modellel. A következő lépésben megkeressük a legközelebbi, az újonnan beágyazott szövegbe ágyazott számlát a lekérdezésből a koszinusz hasonlósága alapján rangsorolva.

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)

Kimenet:

A keresési lekérdezés futtatása után a res formázott eredményeinek képernyőképe.

Végül a teljes tudásbázis felhasználói lekérdezés alapján megjelenítjük a dokumentumkeresés legfontosabb eredményét. Ez az "1993. évi adófizetői jog" első eredményét adja vissza. A dokumentum koszinuszos hasonlósági pontszáma 0,76 a lekérdezés és a dokumentum között:

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."

Előfeltételek

  • Azure-előfizetés – Ingyenes létrehozás

  • A hozzáférést az Azure OpenAI a kívánt Azure-előfizetésen belül kapja meg.

    Ezen szolgáltatáshoz jelenleg csak alkalmazás útján kapható hozzáférés. Az Azure OpenAI-hoz való hozzáférésre a következő https://aka.ms/oai/accessűrlap kitöltésével jelentkezhet: . Ha probléma merül fel, nyisson meg egy hibát az adattárban, és lépjen velünk kapcsolatba.

  • Azure OpenAI-erőforrás a text-embedding-ada-002 (2. verzió) üzembe helyezett modellel.

    Ez a modell jelenleg csak bizonyos régiókban érhető el. Ha nem rendelkezik erőforrással, a létrehozás folyamatát az erőforrás-üzembe helyezési útmutatónk dokumentálja.

  • PowerShell 7.4

Feljegyzés

Ebben az oktatóanyagban számos példa a változók lépésről lépésre történő újrahasználatára. Tartsa nyitva ugyanazt a terminál munkamenetet. Ha az előző lépésben beállított változók elvesznek a terminál bezárása miatt, az elejétől kezdve újra kell kezdődnie.

Kulcs és végpont lekérése

Az Azure OpenAI-ra való sikeres híváshoz egy végpontra és egy kulcsra van szükség.

Változó neve Érték
ENDPOINT Ez az érték a Kulcsok és végpont szakaszban található meg, amikor megvizsgálja az erőforrást az Azure Portalon. Az értéket az Azure OpenAI Studio>Playground>Code nézetben is megtalálhatja. Példavégpont: https://docs-test-001.openai.azure.com/.
API-KEY Ez az érték a Kulcsok és végpont szakaszban található meg, amikor megvizsgálja az erőforrást az Azure Portalon. A következők bármelyikét használhatja: KEY1 vagy KEY2.

Nyissa meg az erőforrást az Azure Portalon. A Kulcsok > végpont szakasz az Erőforrás-kezelés szakaszban található. Másolja ki a végpontot és a hozzáférési kulcsot, mivel mindkettőre szüksége lesz az API-hívások hitelesítéséhez. A következők bármelyikét használhatja: KEY1 vagy KEY2. A két kulcs mindig lehetővé teszi a kulcsok biztonságos elforgatását és újragenerálását anélkül, hogy szolgáltatáskimaradást okoz.

Képernyőkép egy Azure OpenAI-erőforrás áttekintő felhasználói felületéről az Azure Portalon, a végpont és a hozzáférési kulcsok helye pirossal bekarikázva.

Állandó környezeti változók létrehozása és hozzárendelése a kulcshoz és a végponthoz.

Környezeti változók

setx AZURE_OPENAI_API_KEY "REPLACE_WITH_YOUR_KEY_VALUE_HERE" 
setx AZURE_OPENAI_ENDPOINT "REPLACE_WITH_YOUR_ENDPOINT_HERE" 

Ebben az oktatóanyagban a PowerShell 7.4 referenciadokumentációját használjuk jól ismert és biztonságos mintaadatkészletként. Alternatív megoldásként a Microsoft Research-eszközök mintaadatkészleteit is megismerheti.

Hozzon létre egy mappát, amelyben tárolni szeretné a projektet. Állítsa be a helyet a projektmappába. Töltse le az adathalmazt a helyi gépre a Invoke-WebRequest parancs használatával, majd bontsa ki az archívumot. Végül állítsa be a helyét a PowerShell 7.4-es verziójára vonatkozó referenciainformációkat tartalmazó almappára.

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/'

Ebben az oktatóanyagban nagy mennyiségű adattal dolgozunk, ezért egy .NET-adattábla-objektumot használunk a hatékony teljesítmény érdekében. Az adattábla oszlopcímet, tartalmat, prepet, uri-t, fájlt és vektorokat tartalmaz. A címoszlop az elsődleges kulcs.

A következő lépésben minden markdown-fájl tartalmát betöltjük az adattáblába. A PowerShell-operátorral -match rögzítjük az ismert szövegsorokat title: , és online version:különböző oszlopokban tároljuk őket. Egyes fájlok nem tartalmazzák a szöveg metaadatsorait, de mivel áttekintő oldalak, és nem részletes referencia-dokumentumok, kizárjuk őket az adattáblából.

# 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)
    }
}

Az adatok megtekintése a out-gridview parancs használatával (a Cloud Shellben nem érhető el).

$Datatable | out-gridview

Kimenet:

Képernyőkép a DataTable kezdeti eredményeiről.

Ezután végezzen némi egyszerű adattisztítást extra karakterek, üres terület és egyéb dokumentumjegyzetek eltávolításával, hogy előkészítse az adatokat a jogkivonatok készítésére. A mintafüggvény Invoke-DocPrep bemutatja, hogyan használhatja a PowerShell-operátort -replace a tartalomból eltávolítani kívánt karakterek listájának iterálására.

# 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
}

A függvény létrehozása Invoke-DocPrep után a ForEach-Object paranccsal az előkészített tartalmat az előkészítő oszlopban tárolhatja az adattábla összes sorához. Új oszlopot használunk, hogy az eredeti formázás elérhető legyen, ha később szeretnénk lekérni.

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

A módosítás megtekintéséhez tekintse meg újra az adattáblát.

$Datatable | out-gridview

Amikor átadjuk a dokumentumokat a beágyazási modellnek, az tokenekbe kódolja a dokumentumokat, majd lebegőpontos számsorozatot ad vissza, amelyet egy koszinusos hasonlósági kereséshez használunk. Ezek a beágyazások helyileg vagy egy olyan szolgáltatásban tárolhatók, mint a Vector Search az Azure AI Searchben. Minden dokumentum saját beágyazási vektorral rendelkezik az új vektorok oszlopában.

A következő példa végighalad az adattábla minden során, lekéri az előre feldolgozott tartalom vektorait, és tárolja őket a vektorok oszlopában. Az OpenAI szolgáltatás szabályozza a gyakori kéréseket, ezért a példában a dokumentáció által javasolt exponenciális visszalépés szerepel.

A szkript befejezése után minden sornak 1536 vektor vesszővel tagolt listájával kell rendelkeznie az egyes dokumentumokhoz. Ha hiba történik, és az állapotkód az 400, a rendszer hozzáadja a fájl elérési útját, címét és hibakódját a hibaelhárításhoz elnevezett $errorDocs változóhoz. A leggyakoribb hiba akkor fordul elő, ha a jogkivonatok száma meghaladja a modell kérési korlátját.

# 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."
}

Most már rendelkezik a PowerShell 7.4 referencia-dokumentációjának helyi memóriabeli adatbázis-táblázatával.

Egy keresési sztring alapján egy másik vektorkészletet kell kiszámítanunk, hogy a PowerShell hasonlóság alapján rangsorolhassa az egyes dokumentumokat.

A következő példában a keresési sztring get a list of running processesvektorai lesznek lekérve.

$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 ','

Végül a következő mintafüggvény, amely egy példát vesz fel a Lee Holmes által írt Measure-VectorSimilarity példaszkriptből, egy koszinusz hasonlósági számítást végez, majd rangsorolja az adattáblában lévő sorokat.

# 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)
}

A következő példában szereplő parancsok végighaladnak az összes soron, $Datatable és kiszámítják a keresési sztring koszinuszbeli hasonlóságát. Az eredmények rendezése és az első három találat tárolása egy névvel ellátott $topThreeváltozóban történik. A példa nem ad vissza kimenetet.

# 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 }
}

Tekintse át a $topThree változó kimenetét, csak cím - és URL-tulajdonságokkal a gridview-ban.

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

Kimeneti:

Képernyőkép a formázott eredményekről a keresési lekérdezés befejeződése után.

A $topThree változó az adattábla soraiból származó összes információt tartalmazza. A tartalomtulajdonság például az eredeti dokumentumformátumot tartalmazza. A tömb első elemébe való indexeléshez használható [0] .

$topThree[0].content

Tekintse meg a teljes dokumentumot (a lap kimeneti kódrészletében csonkolt).

---
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

Végül ahelyett, hogy minden alkalommal újra létrehozza a beágyazásokat, amikor le kell kérdeznie az adathalmazt, tárolhatja az adatokat a lemezre, és a jövőben visszahívhatja őket. A WriteXML() Következő példában szereplő DataTable objektumtípusok és ReadXML() metódusok leegyszerűsítik a folyamatot. Az XML-fájl sémájának táblanévvel kell rendelkeznie az adattáblának.

Cserélje le <YOUR-FULL-FILE-PATH> a teljes elérési utat, ahol meg szeretné írni és olvasni az XML-fájlt. Az elérési útnak a következővel kell végződnie .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>")

Az adatok újrafelhasználása során be kell szereznie az egyes új keresési sztringek vektorait (de a teljes adattáblát nem). Tanulási gyakorlatként hozzon létre egy PowerShell-szkriptet, amellyel paraméterként automatizálhatja a Invoke-RestMethod parancsot a keresési sztringgel.

Ezzel a módszerrel a beágyazásokat keresési mechanizmusként használhatja egy tudásbázis dokumentumaiban. A felhasználó ezután a legfelső keresési eredményt veheti fel, és felhasználhatja az alsóbb rétegbeli feladatához, amely a kezdeti lekérdezést kéri.

Az erőforrások eltávolítása

Ha kizárólag az oktatóanyag elvégzéséhez létrehozott egy Azure OpenAI-erőforrást, és törölni szeretne egy Azure OpenAI-erőforrást, törölnie kell az üzembe helyezett modelleket, majd törölnie kell az erőforrást vagy a kapcsolódó erőforráscsoportot, ha az a teszterőforráshoz van rendelve. Az erőforráscsoport törlése a hozzá társított egyéb erőforrásokat is törli.

Következő lépések

További információ az Azure OpenAI modelljeiről: