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

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

說明

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

2024/08/01 Update: 現在已經不需要額外申請,已全面開放使用。

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

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

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

當然也可以點選檢視程式碼來看範例程式。

因為要顯示圖片,所以我開了 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=2024-02-01";
    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 來使用,目前新版 2.0.0 以上都會搭配 OpenAI 官方套件來使用。

透過 SDK 版本來寫會比較精簡一點,我們也不用另外處理要一直去確認狀態的程式碼,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 AzureOpenAIClient(
		new Uri(apiUrl), 
		new AzureKeyCredential(apikey))
		.GetImageClient("dall-e-3");

    try
    {
        ImageGenerationOptions options = new()
		{
    		Quality = GeneratedImageQuality.High,
    		Size = GeneratedImageSize.W1792xH1024,
    		Style = GeneratedImageStyle.Natural,
    		ResponseFormat = GeneratedImageFormat.Uri
		};

		var image = client.GenerateImage(promptText, options);
		
		return Redirect(image.Value.ImageUri.AbsoluteUri);
    }
    catch (Exception ex)
    {
        return Content(ex.Message);
    }
}

如果想直接把結果的圖片直接下載處理的話也可以用底下程式碼直接回傳圖檔。

ImageGenerationOptions options = new()
{
    Quality = GeneratedImageQuality.High,
    Size = GeneratedImageSize.W1792xH1024,
    Style = GeneratedImageStyle.Natural,
    ResponseFormat = GeneratedImageFormat.Bytes
};

GeneratedImage image = client.GenerateImage(promptText, options);
BinaryData bytes = image.ImageBytes;

return File(bytes.ToStream(), "image/png");

完整範例可以到 GitHub 下載。

結論

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

參考資料