Megosztás a következőn keresztül:


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 használatán a dokumentumkeresés érdekében, ahol lekérdezi a tudásbázist, hogy megtalálja a legrelevánsabb dokumentumot.

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.
  • Használja a következő modellek egyikét: text-embedding-ada-002 (2. verzió), text-embedding-3-large, text-embedding-3-small modellek.
  • A találatok rangsorolásához használjon koszin hasonlóságot .

Előfeltételek

  • Azure-előfizetés – Ingyenes létrehozás
  • 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 notebookok

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 az 5000 és 20 000 karakter hosszúságú közepes hosszúságú jogszabályok állnak. További információkat a projektről és az eredeti akadémiai 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 A szolgáltatásvégpont a Kulcsok > Végpont szakaszban található, amikor az erőforrást az Azure Portalról vizsgálja. A végpontot az Azure AI Foundry portál Üzembe helyezések lapján 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 portálon. 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

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

Fontos

Óvatosan használja az API-kulcsokat. Ne foglalja bele közvetlenül az API-kulcsot a kódba, és soha ne tegye közzé nyilvánosan. Ha egy API-kulcsot használ, biztonságosan tárolja az Azure Key Vaultban. További információ az API-kulcsok biztonságos használatáról az alkalmazásokban: API-kulcsok az Azure Key Vaulttal.

Az AI-szolgáltatások biztonságáról további információt az Azure AI-szolgáltatásokhoz érkező kérelmek hitelesítése című témakörben talál.

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 okból nem tudja használni őket, akkor bármely kódot, amely pandas adatkeretet ad vissza, módosítania kell úgy, hogy print(dataframe_name) használatával, ahelyett hogy közvetlenül meghívná a dataframe_name, ahogyan az gyakran történik egy kódblokk végén.

Futtassa a következő kódot a preferált Python IDE-ben:

Könyvtá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

Kimenet:

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

Az eredeti tábla több oszlopot tartalmaz, mint amennyi szükséges, ezért létrehozunk egy új, kisebb adatkeretet, a df_bills nevű DataFrame-et, amely csak a text, summary és title oszlopokat fogja tartalmazni.

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

Kimenet:

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

Kimenet:

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

A n_tokens oszlop és a szöveg végső tokenizálásá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 dokumentációink esetében szándékosan csonkoljuk a kimenetet, de ha ezt a parancsot az ön környezetében futtatja, a nulladik indextől kezdődően a teljes szöveget darabokra bontva fogja visszaadni. 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 tokenizálá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 azt biztosítja, hogy a modellnek átadott adatok egyike sem haladja meg a tokenizálás és beágyazás során az 8192 bemeneti token 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 esetében alternatív megoldásként átadhat a modellnek egy bemeneti tömböt, amely lehetővé teszi több bemenet egyidejű beágyazását. Amikor egy modellt bemeneti elemek tömbjével lát el, a beágyazási végpontra küldhető bemeneti elemek maximális száma hívásonként 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

Kimenet:

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 Jogok Megtekintési Törvény" legjobb 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

  • 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 A szolgáltatásvégpont a Kulcsok > Végpont szakaszban található, amikor az erőforrást az Azure Portalról vizsgálja. A végpontot az Azure AI Foundry portál Üzembe helyezések lapján 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 portálon. 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

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

Fontos

Óvatosan használja az API-kulcsokat. Ne foglalja bele közvetlenül az API-kulcsot a kódba, és soha ne tegye közzé nyilvánosan. Ha egy API-kulcsot használ, biztonságosan tárolja az Azure Key Vaultban. További információ az API-kulcsok biztonságos használatáról az alkalmazásokban: API-kulcsok az Azure Key Vaulttal.

Az AI-szolgáltatások biztonságáról további információt az Azure AI-szolgáltatásokhoz érkező kérelmek hitelesítése című témakörben talál.

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 helyek és egyéb dokumentumjegyzetek eltávolításával, hogy előkészítse az adatokat a tokenizálásra. 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 tokenek száma meghaladja a modell bemeneti 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

Kimenet:

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 (ennek az oldalnak a kivágott kimenetében).

---
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ája megköveteli, hogy az adattáblának legyen TableName.

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 megtisztí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: