Azure OpenAI Service 08 - Azure OpenAI DALL·E 介紹和實做串接

Azure OpenAI Service 除了文字的模型之外,也有產生影像的模型 DALL·E ,我們一樣可以透過提供提示詞之後取得 AI 回應的圖片結果,本文就來介紹如何在 Azure 上面使用這一個模型。

說明

在使用 DALL·E 之前也是要先填寫表單的,表單和申請文字模型是一樣的,若要使用就要記得申請時候勾選,如果之前申請時候沒有申請,就再填一次表單即可。

如果有申請通過的話,可以在 Azure OpenAI Studio 看到選項,但是要注意的是目前只有在美國東部 (East US) 這個資料中心才有提供,如果建立的非此資料中心就會提示無法使用。

資料中心也正確的話,我們就可以透過 playground 來測試這個模型的效果了。

輸入提示詞之後就可以產生對應的圖片出來。

當然也可以點選檢視程式碼來看範例程式,不過目前僅有 Python 和 Json 兩個選項可以選擇,還沒有 C# 的程式碼範例。

沒有 C# 程式碼範例就自己來實做測試了,因為要顯示圖片,所以我開了 ASP.NET Core Web 的 Razor Page 專案,方便後面顯示圖片。畫面上簡單放的提示詞輸入框和送出按鈕。

新增 Post 的方法,apikey 和 apiurl 網址可以在前面 playground 檢視程式碼的時候取得。

public async Task<IActionResult> OnPost(string promptText)
{
    var apikey = "{your api key}";
    var apiUrl = "https://{your openai endpoint}.openai.azure.com/openai/images/generations:submit?api-version=2023-06-01-preview";
    var client = new HttpClient();

    // 1. 先取得 operation-location
    var request = new HttpRequestMessage(HttpMethod.Post, apiUrl);
    request.Headers.Add("api-key", apikey);
    var prompt = new
    {
        prompt = promptText,
        n = 1,
        size = "1024x1024"
    };
    var content = new StringContent(JsonSerializer.Serialize(prompt), null, "application/json");
    request.Content = content;
    var response = await client.SendAsync(request);
    response.EnsureSuccessStatusCode();


    var location = response.Headers.GetValues("operation-location").First();

    // 2. 再取得圖片網址
    var result = new DALLEResponse();
    while (result.status != "succeeded" && result.status != "failed")
    {
        Thread.Sleep(1000);
        request = new HttpRequestMessage(HttpMethod.Get, location);
        request.Headers.Add("api-key", apikey);
        response = await client.SendAsync(request);
        response.EnsureSuccessStatusCode();
        result = JsonSerializer.Deserialize<DALLEResponse>(await response.Content.ReadAsStringAsync());
    }

    if (result.status == "failed")
        return Content($"failed!ErrorCode: {result.error.code}, ErrorMessage: {result.error.message}");

    return Redirect(result.result.data[0].url);
}

首先要呼叫產生影像的請求,輸入的 Json 格式如下,prompt 就是我們的提示詞,n 則為產生的圖片個數可以接受的範圍是 1~5,szie 則為圖片大小接受的值為 256x256、512x512或 1024x1024,當然圖片越大,產生的時間也會越久,費用的話在 Azure 上是算圖片數量,所以不影響到費用,但是 OpenAI 的話就是以圖片大小來計費,這點可能要注意。

n 在 playground 設定範圍會是 1~3,程式呼叫實測可以到 5,OpenAI 則為 10。
{
    "prompt": "USER_PROMPT_GOES_HERE",
    "n": 1,
    "size": "1024x1024"
}

Api 會回傳結果,但是這時候要去回傳結果的 header 取得 operation-location 這一個值,它會是一個網址,我們再去打這個網址,而這網址會顯示目前處理的狀態,我們可以重複一直查詢結果到出現 succeeded 或是 failed,如果是 succeeded 就會帶回圖片位置儲存體帶 SAS Token 網址,可以在一定時間內可以存取,最後就把網頁直接轉到儲存體位置。

如果有成功取得的話就可以正確轉到儲存體位置並顯示圖片了。

失敗的話則在頁面上顯示錯誤訊息,大概比較大機會是因為被內容篩選過濾掉,所以無法正確的產生圖片,根據官方文件說明,產生多張圖片也可能針對每一張去審核圖片,會回傳部分成功跟部分失敗的說明的 Json 結果,我程式範例就沒有針對多張圖片來處理,僅針對一張圖片的回傳結果做處理。

除了直接呼叫 API 之外也可以透過官方套件 Azure OpenAI client library for .NET 來使用,目前最新的 beta 6 版有支援圖片的功能。

透過 SDK 版本來寫會比較精簡一點,我們也不用另外處理要一直去確認狀態的程式碼,SDK 會幫忙做掉,就可以很簡單的取得要的結果了,只是在錯誤的處理上有點奇怪,雖然可以在取的回應之後透過方法 GetRawResponse 來取得原始的回應,但是會在 GetImageGenerationsAsync 就報錯了,這樣根本沒辦法用到 GetRawResponse 來取得是否有錯誤的訊息,可能要看之後 SDK 有沒有更新了。

public async Task<IActionResult> OnPost(string promptText)
{
    var apikey = "{your api key}";
    var apiUrl = "https://{your openai endpoint}.openai.azure.com";

    var client = new OpenAIClient(new Uri(apiUrl), new AzureKeyCredential(apikey));
    try
    {
        var result = await client.GetImageGenerationsAsync(new ImageGenerationOptions()
        {
            Prompt = promptText,
            Size = ImageSize.Size1024x1024,
            ImageCount = 1
        });

        return Redirect(result.Value.Data.First().Url.AbsoluteUri);
    }
    catch (Exception ex)
    {
        return Content(ex.Message);
    }
}

完整範例可以到 GitHub 下載。

結論

目前 DALL·E 還在 Preview,而且也還沒有像 OpenAI 有 Edits 或 Variations 的功能,也可能是有,但是官方範例跟文件都沒提到,就沒辦法確定要輸入的資料和網址為何,所以無法驗證,這可能等之後文件有正式的說明再來驗證跟測試了。

參考資料