[C#] Cloudflare FLUX.2 Klein 4B C# 教學:用 Workers AI 直接產生 16:9 AI 圖片

  • 6
  • 0

上一篇測了 Cloudflare Workers AI 的 FLUX.1 Schnell

這次換另外一顆:

@cf/black-forest-labs/flux-2-klein-4b

這顆我覺得比 Schnell 更適合真的拿來做 Blog 圖片

原因很簡單,它可以直接設定圖片的寬高,也支援 seed , width , height ,所以如果我要 16:9,不用自己再裁圖

直接指定 1280 x 720 就可以

1. 使用 FLUX.2 Klein 4B

這次使用的模型是:@cf/black-forest-labs/flux-2-klein-4b
 

Cloudflare Workers AI 的 API Endpoint 一樣是:

https://api.cloudflare.com/client/v4/accounts/{ACCOUNT_ID}/ai/run/{MODEL}

所以完整網址會是:

https://api.cloudflare.com/client/v4/accounts/{ACCOUNT_ID}/ai/run/@cf/black-forest-labs/flux-2-klein-4b

跟上一篇 Schnell 比較不一樣的是,這顆要使用:

multipart/form-data

而不是直接送 JSON

另外它可以直接控制圖片尺寸,所以這次我直接產:

1280 x 720

就是標準 16:9

 

2. C# 實際呼叫

下面是我這次實際測試的版本

一樣直接使用 HttpClient,不需要另外安裝特殊 SDK

static async Task TestFlux_2_klein_4b()
{
    // 要呼叫的 Cloudflare Workers AI 模型名稱
    var model = "@cf/black-forest-labs/flux-2-klein-4b";

    // 這裡直接指定輸出尺寸
    // 1280 x 720 就是標準 16:9
    var width = 1280;
    var height = 720;

    // 這次的測試 Prompt
    // 內容越具體,通常越容易得到可預期的圖片結果
    var prompt = """
        A realistic young Taiwanese female C# software engineer sitting naturally at a desk and working on a laptop,
        young Taiwanese woman in her 20s,
        ponytail hairstyle,
        wearing a simple elegant short dress,
        professional and attractive appearance,
        full upper body clearly visible,
        head, face, neck, shoulders, torso, arms and hands fully connected and anatomically correct,
        natural seated posture,
        both hands resting naturally on the keyboard,
        professional modern software engineering workspace,
        one main monitor and one secondary monitor positioned behind and beside her,
        monitors must not block or intersect the woman's head, face, neck, shoulders or body,
        computer screens visible only as background elements,
        clean modern office,
        soft professional lighting,
        realistic photography,
        natural skin texture,
        highly detailed,
        balanced composition,
        correct human anatomy,
        correct body proportions,
        realistic hands and fingers,
        no duplicated body parts,
        no missing body parts,
        no detached limbs,
        no floating head,
        no extra arms,
        no extra hands,
        no malformed hands,
        no distorted body,
        no overlapping body parts,
        no monitor intersecting the person,
        no readable text,
        no logos
        """;

    // Cloudflare Account ID
    // 正式放文章時建議改成 YOUR_ACCOUNT_ID
    var accountId = "YOUR_ACCOUNT_ID";

    // Workers AI API Token
    // 千萬不要把真實 Token 上傳到 GitHub 或公開文章
    var apiToken = "YOUR_API_TOKEN";

    // 輸出的檔名
    // 用目前時間避免每次產圖都覆蓋前一次結果
    var outputPath =
        "flux-2-klein-output-" +
        DateTime.Now.ToString("yyMMddHHmmss") +
        ".jpg";

    // Cloudflare Workers AI API Endpoint
    var apiUrl =
        $"https://api.cloudflare.com/client/v4/accounts/{accountId}/ai/run/{model}";

    // 建立 HttpClient,並設定 Timeout
    using var client = new HttpClient
    {
        Timeout = TimeSpan.FromMinutes(2)
    };

    // Cloudflare 使用 Bearer Token 驗證
    client.DefaultRequestHeaders.Authorization =
        new AuthenticationHeaderValue(
            "Bearer",
            apiToken);

    // FLUX.2 Klein 4B 要用 multipart/form-data
    // 不是上一篇 FLUX.1 Schnell 那種 JSON Body
    using var form = new MultipartFormDataContent();

    // 加入 Prompt
    form.Add(
        new StringContent(prompt),
        "prompt");

    // 指定輸出寬度
    form.Add(
        new StringContent(width.ToString()),
        "width");

    // 指定輸出高度
    form.Add(
        new StringContent(height.ToString()),
        "height");

    // seed 可用來固定生成方向
    // 相同 Prompt + 相同 seed,通常比較容易得到相近的結果
    form.Add(
        new StringContent("123456"),
        "seed");

    Console.WriteLine($"Model: {model}");
    Console.WriteLine($"Size : {width} x {height}");
    Console.WriteLine("產圖中...");

    // 呼叫 Cloudflare Workers AI API
    using var response =
        await client.PostAsync(
            apiUrl,
            form);

    // 先把回應內容讀出來
    // 如果失敗時也能直接看到錯誤訊息
    var responseJson =
        await response.Content.ReadAsStringAsync();

    // 如果 Cloudflare 回傳失敗,就輸出錯誤資訊
    if (!response.IsSuccessStatusCode)
    {
        Console.Error.WriteLine(
            $"Cloudflare 回傳錯誤:{(int)response.StatusCode} {response.ReasonPhrase}");

        Console.Error.WriteLine(responseJson);
        return;
    }

    // 解析 JSON 回應
    using var document =
        JsonDocument.Parse(responseJson);

    // 產出的圖片會放在 result.image
    // 格式是 Base64 字串
    var base64 =
        document.RootElement
            .GetProperty("result")
            .GetProperty("image")
            .GetString();

    // 如果沒有拿到圖片資料,就直接把原始回應印出來方便除錯
    if (string.IsNullOrWhiteSpace(base64))
    {
        Console.Error.WriteLine(responseJson);
        return;
    }

    // 將 Base64 轉回實際圖片位元組
    var imageBytes =
        Convert.FromBase64String(base64);

    // 把圖片存到本機
    await File.WriteAllBytesAsync(
        outputPath,
        imageBytes);

    Console.WriteLine(
        $"圖片產生完成:{Path.GetFullPath(outputPath)} ({imageBytes.Length:N0} bytes)");
}

這裡跟 Schnell 最大的差異就是

using var form = new MultipartFormDataContent();

然後就可以直接指定

form.Add(
    new StringContent(width.ToString()),
    "width");

form.Add(
    new StringContent(height.ToString()),
    "height");

這樣就可以真的控制輸出圖片尺寸

例如

1280 x 720
1920 x 1080
1024 x 576

全部都是 16:9

seed 也可以用了

上一篇 Schnell 我實測傳入 seed 會直接得到 400

但是 Klein 4B 可以直接使用:

form.Add(
    new StringContent("123456"),
    "seed");

如果 Prompt 跟 seed 都固定,通常會比較容易產生接近的結果

當然如果不在意每次生成結果不同,也可以不傳

 

簡單做個小結論

如果只是要快速大量產圖,我覺得 Schnell 就已經夠用了

但是如果是 Blog Cover 或真的要整合進系統,我目前會比較喜歡 FLUX.2 Klein 4B,畢竟都到 v2 當然必較猛

但是算起來一天大概只能產生九十幾張照片(免費額度)

最主要就是它可以直接指定圖片尺寸

像我要 16:9,就直接給:

1280 x 720

不用再自己裁圖

另外 seed 跟參考圖片也都能用,可玩的東西比 Schnell 多不少

C# 串接一樣不難,只是記得這顆要使用 multipart/form-data

最後還是一樣

Prompt 我會盡量避免要求它直接產生文字,尤其是中文

圖片先生成,真正要顯示的標題或文字再自己後製,結果通常還是比較穩,就都測試產圖了也就多測一個

 

---

The bug existed in all possible states.
Until I ran the code.