Поделиться через


Руководство по внедрению и поиску документов в Службе OpenAI Azure

В этом руководстве вы узнаете, как использовать API внедрения Azure OpenAI для выполнения поиска документов, где будет запрашиваться база знаний, чтобы найти наиболее подходящий документ.

В этом руководстве описано следующее:

  • Установите Azure OpenAI.
  • Скачайте пример набора данных и подготовьте его к анализу.
  • Создайте переменные среды для конечной точки ресурсов и ключа API.
  • Используйте одну из следующих моделей: text-embedding-ada-002 (версия 2), text-embedding-3-large, text-embedding-3-small models.
  • Используйте совместное сходство с результатами поиска ранжирования.

Необходимые компоненты

Настройка

Библиотеки Python

Если вы еще не сделали этого, необходимо установить следующие библиотеки:

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

Скачивание набора данных BillSum

BillSum — это набор данных США законопроектов конгресса и штата Калифорния. Для иллюстрации мы рассмотрим только счета США. Корпус состоит из законопроектов от 103-го-115-го (1993-2018) сессий Конгресса. Данные были разделены на 18 949 счетов за обучение и 3269 тестовых счетов. Корпус BillSum фокусируется на среднем законодательстве от 5000 до 20 000 символов в длину. Дополнительные сведения о проекте и исходном учебном документе, из которого получен этот набор данных, можно найти в репозитории GitHub проекта BillSum

В этом руководстве bill_sum_data.csv используется файл, который можно скачать из примера данных GitHub.

Вы также можете скачать пример данных, выполнив следующую команду на локальном компьютере:

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

Получение ключа и конечной точки

Чтобы успешно выполнить вызов к Azure OpenAI, вам потребуется конечная точка и ключ.

Имя переменной Значение
ENDPOINT Конечная точка службы можно найти в разделе "Ключи" и "Конечная точка" при изучении ресурса из портал Azure. Кроме того, можно найти конечную точку на странице "Развертывания " в Azure AI Studio. Пример конечной точки: https://docs-test-001.openai.azure.com/.
API-KEY Это значение можно найти в разделе Ключи и конечная точка при просмотре ресурса на портале Azure. Вы можете использовать KEY1 или KEY2.

Перейдите к своему ресурсу на портале Azure. Раздел "Ключи и конечная точка " можно найти в разделе "Управление ресурсами". Скопируйте конечную точку и ключ доступа, так как они потребуются для проверки подлинности вызовов API. Вы можете использовать KEY1 или KEY2. Наличие двух ключей позволяет безопасно менять и повторно создавать ключи без прерывания работы службы.

Снимок экрана: пользовательский интерфейс обзора для ресурса Azure OpenAI в портал Azure с конечной точкой и расположением ключей доступа, окружаемых красным цветом.

Переменные среды

Создайте и назначьте переменные постоянной среды для ключа и конечной точки.

Внимание

Если вы используете ключ API, сохраните его в другом месте, например в Azure Key Vault. Не включайте ключ API непосредственно в код и никогда не публикуйте его.

Дополнительные сведения о безопасности служб ИИ см. в статье "Проверка подлинности запросов к службам ИИ Azure".

setx AZURE_OPENAI_API_KEY "REPLACE_WITH_YOUR_KEY_VALUE_HERE" 
setx AZURE_OPENAI_ENDPOINT "REPLACE_WITH_YOUR_ENDPOINT_HERE" 

После задания переменных среды может потребоваться закрыть и повторно открыть записные книжки Jupyter или любую интегрированную среду разработки, чтобы переменные среды были доступны. Хотя мы настоятельно рекомендуем использовать Jupyter Notebook, если по какой-то причине вы не можете изменить любой код, возвращающий кадр данных pandas, используя print(dataframe_name) вместо того, чтобы просто вызывать непосредственно, dataframe_name как часто делается в конце блока кода.

Запустите следующий код в предпочтительной интегрированной среде разработки Python:

Импорт библиотек

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

Теперь необходимо прочитать csv-файл и создать кадр данных pandas. После создания начального кадра данных можно просмотреть содержимое таблицы, выполнив команду df.

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

Выходные данные:

Снимок экрана: исходная таблица кадра данных из CSV-файла.

Начальная таблица содержит больше столбцов, чем нам нужно, мы создадим новый меньший кадр df_bills данных, который будет содержать только столбцы для text, summaryи title.

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

Выходные данные:

Снимок экрана: более мелкие результаты таблицы DataFrame с отображаемыми только текстовыми, сводными и заголовками столбцов.

Затем мы будем выполнять очистку некоторых легких данных, удаляя избыточное пробелы и очищая знак препинания, чтобы подготовить данные для токенизации.

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

Теперь нам нужно удалить все счета, слишком длинные для ограничения маркеров (8192 токенов).

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

Примечание.

В этом случае все счета находятся под ограничением входных маркеров модели, но вы можете использовать приведенный выше метод для удаления записей, которые в противном случае привели бы к сбою внедрения. При столкновении с содержимым, превышающим ограничение внедрения, можно также разделить содержимое на небольшие части, а затем внедрить их одновременно.

Мы еще раз рассмотрим df_bills.

df_bills

Выходные данные:

Снимок экрана: кадр данных с новым столбцом с именем n_tokens.

Чтобы понять, как n_tokens столбец немного больше, а также как текст в конечном счете токенизирован, можно выполнить следующий код:

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

Для наших документов мы намеренно усечены выходные данные, но выполнение этой команды в вашей среде вернет полный текст из индекса нулевого маркера в блоки. В некоторых случаях целое слово представлено одним маркером, а в других частях слов разделено по нескольким маркерам.

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

Если проверить длину переменной decode , она будет соответствовать первому числу в столбце n_tokens.

len(decode)
1466

Теперь, когда мы понимаем, как работает маркеризация, мы можем перейти к внедрению. Важно отметить, что мы еще не токенизировали документы. Столбец n_tokens — это просто способ убедиться, что ни один из данных, которые мы передаваем в модель для токенизации и внедрения, превышает ограничение входного маркера 8192. Когда мы передаем документы в модель внедрения, документы будут разбиты на маркеры, аналогичные (хотя и не обязательно идентичным) приведенным выше примерам, а затем преобразовывают маркеры в ряд чисел с плавающей запятой, которые будут доступны через векторный поиск. Эти внедрения можно хранить локально или в базе данных Azure для поддержки векторного поиска. В результате каждый счет будет иметь свой собственный вектор внедрения в новый ada_v2 столбец справа от кадра данных.

В приведенном ниже примере мы вызываем модель внедрения один раз на каждый элемент, который мы хотим внедрить. При работе с большими проектами внедрения можно также передать модель массива входных данных для внедрения, а не одного ввода одновременно. При передаче модели массив входных данных максимальное количество входных элементов для каждого вызова в конечную точку внедрения составляет 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

Выходные данные:

Снимок экрана: форматированные результаты из команды df_bills.

По мере запуска блока кода поиска ниже мы внедряем поисковый запрос "Можно ли получить информацию о доходах от налогообложения кабельной компании?" с той же моделью text-embedding-ada-002 (версия 2). Далее мы найдем ближайший счет, внедренный в недавно внедренный текст из нашего запроса, ранжированный по подобию косинуса.

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)

Выходные данные:

Снимок экрана: форматированные результаты res после запуска поискового запроса.

Наконец, мы покажем верхний результат поиска документов на основе запроса пользователя ко всему база знаний. Это возвращает верхний результат "Право налогоплательщика на просмотр закона 1993 года". Этот документ содержит оценку сходства 0,76 между запросом и документом:

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

Необходимые компоненты

Примечание.

Многие примеры в этом руководстве повторно используют переменные на шаге к шагу. Сохраняйте один и тот же сеанс терминала на протяжении всего сеанса. Если переменные, заданные на предыдущем шаге, теряются из-за закрытия терминала, необходимо начать с начала.

Получение ключа и конечной точки

Чтобы успешно выполнить вызов к Azure OpenAI, вам потребуется конечная точка и ключ.

Имя переменной Значение
ENDPOINT Конечная точка службы можно найти в разделе "Ключи" и "Конечная точка" при изучении ресурса из портал Azure. Кроме того, можно найти конечную точку на странице "Развертывания " в Azure AI Studio. Пример конечной точки: https://docs-test-001.openai.azure.com/.
API-KEY Это значение можно найти в разделе Ключи и конечная точка при просмотре ресурса на портале Azure. Вы можете использовать KEY1 или KEY2.

Перейдите к своему ресурсу на портале Azure. Раздел "Ключи и конечная точка " можно найти в разделе "Управление ресурсами". Скопируйте конечную точку и ключ доступа, так как они потребуются для проверки подлинности вызовов API. Вы можете использовать KEY1 или KEY2. Наличие двух ключей позволяет безопасно менять и повторно создавать ключи без прерывания работы службы.

Снимок экрана: пользовательский интерфейс обзора для ресурса Azure OpenAI в портал Azure с конечной точкой и расположением ключей доступа, окружаемых красным цветом.

Переменные среды

Создайте и назначьте переменные постоянной среды для ключа и конечной точки.

Внимание

Если вы используете ключ API, сохраните его в другом месте, например в Azure Key Vault. Не включайте ключ API непосредственно в код и никогда не публикуйте его.

Дополнительные сведения о безопасности служб ИИ см. в статье "Проверка подлинности запросов к службам ИИ Azure".

setx AZURE_OPENAI_API_KEY "REPLACE_WITH_YOUR_KEY_VALUE_HERE" 
setx AZURE_OPENAI_ENDPOINT "REPLACE_WITH_YOUR_ENDPOINT_HERE" 

В этом руководстве мы используем справочную документацию По PowerShell 7.4 в качестве известного и безопасного набора данных. В качестве альтернативы можно изучить примеры наборов данных в средствах Microsoft Research.

Создайте папку, в которой вы хотите сохранить проект. Укажите расположение в папке проекта. Скачайте набор данных на локальный компьютер с помощью Invoke-WebRequest команды, а затем разверните архив. Наконец, задайте расположение вложенной папке, содержащей справочные сведения для PowerShell версии 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/'

Мы работаем с большим объемом данных в этом руководстве, поэтому мы используем объект таблицы данных .NET для эффективной производительности. В наборе данных есть заголовки столбцов, содержимое, подготовка, URI, файл и векторы. Столбец заголовка является первичным ключом.

На следующем шаге мы загружаем содержимое каждого файла markdown в таблицу данных. Оператор PowerShell -match также используется для записи известных строк текста title: и online version:хранения их в разных столбцах. Некоторые файлы не содержат строки метаданных текста, но так как они обзорные страницы и не подробные справочные документы, мы исключим их из набора данных.

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

Просмотрите данные с помощью out-gridview команды (недоступно в Cloud Shell).

$Datatable | out-gridview

Выходные данные:

Снимок экрана: начальные результаты DataTable.

Затем выполните очистку некоторых легких данных, удалив дополнительные символы, пустое пространство и другие нотации документов, чтобы подготовить данные для маркеризации. В примере функции Invoke-DocPrep показано, как использовать оператор PowerShell -replace для итерации по списку символов, которые вы хотите удалить из содержимого.

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

После создания Invoke-DocPrep функции используйте ForEach-Object команду для хранения подготовленного содержимого в столбце подготовки для всех строк в наборе данных. Мы используем новый столбец, чтобы исходный формат был доступен, если мы хотели бы получить его позже.

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

Просмотрите таблицы данных еще раз, чтобы увидеть изменения.

$Datatable | out-gridview

При передаче документов в модель внедрения он кодирует документы в маркеры, а затем возвращает ряд чисел с плавающей запятой для использования в поиске сходства косинуса. Эти внедрения можно хранить локально или в службе, например векторном поиске в Azure AI. Каждый документ имеет собственный вектор внедрения в новый столбец векторов .

Следующий пример циклирует каждую строку в наборе данных, извлекает векторы для предварительно обработанного содержимого и сохраняет их в столбце векторов . Служба OpenAI регулирует частые запросы, поэтому пример включает экспоненциальный обратный выход , как показано в документации.

После завершения скрипта каждая строка должна иметь список с разделителями-запятыми 1536 векторов для каждого документа. Если возникает ошибка, а код состояния — 400путь к файлу, заголовок и код ошибки добавляются в переменную с именем $errorDocs для устранения неполадок. Наиболее распространенная ошибка возникает, когда число маркеров превышает ограничение запроса для модели.

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

Теперь у вас есть локальная таблица базы данных в памяти в документации по PowerShell 7.4.

На основе строки поиска необходимо вычислить другой набор векторов, чтобы PowerShell могли ранжировать каждый документ по подобию.

В следующем примере векторы извлекаются для строки 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 ','

Наконец, следующая пример функции, которая заимствует пример из примера скрипта Measure-VectorSimilarity , написанной Ли Холмсом, выполняет вычисление сходства косинуса, а затем ранжирует каждую строку в таблицы данных.

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

Команды в следующем примере выполняют цикл по всем строкам $Datatable и вычисляют сходство косинуса со строкой поиска. Результаты сортируются, а первые три результата хранятся в переменной с именем $topThree. Пример не возвращает выходные данные.

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

Просмотрите выходные данные переменной $topThree с только свойствами заголовка и URL-адреса в gridview.

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

Выходные данные:

Снимок экрана: форматированные результаты после завершения поискового запроса.

Переменная $topThree содержит все сведения из строк в наборе данных. Например, свойство содержимого содержит исходный формат документа. Используется [0] для индексирования первого элемента в массиве.

$topThree[0].content

Просмотрите полный документ (усеченный в фрагменте выходных данных для этой страницы).

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

Наконец, вместо повторного создания внедренных операций каждый раз, когда необходимо запросить набор данных, можно хранить данные на диск и отозвать его в будущем. Методы WriteXML() типов объектов DataTable в следующем примере ReadXML() упрощают процесс. Схема XML-файла требует наличия таблицы TableName.

Замените <YOUR-FULL-FILE-PATH> полный путь, в котором вы хотите написать и прочитать XML-файл. Путь должен заканчиваться .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>")

При повторном использовании данных необходимо получить векторы каждой новой строки поиска (но не весь набор данных). В ходе обучения попробуйте создать скрипт PowerShell, чтобы автоматизировать Invoke-RestMethod команду с помощью строки поиска в качестве параметра.

С помощью этого подхода можно использовать внедрение в качестве механизма поиска в документах в база знаний. Затем пользователь может взять верхний результат поиска и использовать его для своей нижней задачи, которая запросила исходный запрос.

Очистка ресурсов

Если вы создали ресурс Azure OpenAI исключительно для выполнения этого руководства и хотите очистить и удалить ресурс Azure OpenAI, необходимо удалить развернутые модели, а затем удалить ресурс или связанную группу ресурсов, если она выделена тестовым ресурсом. При удалении группы ресурсов также удаляются все связанные с ней ресурсы.

Следующие шаги

Дополнительные сведения о моделях Azure OpenAI: