Haijun Platform Docs
EN

Panduan ini menjelaskan cara mengirim gambar ke Haijun, batasan dan biaya yang berlaku, serta tempat menemukan panduan untuk alur kerja berbasis koordinat.


Mengirim gambar ke Haijun

Gunakan kemampuan vision Haijun melalui:

  • haijun.ai. Unggah gambar seperti Anda mengunggah file, atau seret dan lepas gambar langsung ke jendela chat.
  • Playground di Haijun Console. Tambahkan gambar langsung ke blok pesan User mana pun.
  • Permintaan API. Lihat contoh-contoh berikut.

Di API, berikan gambar ke Haijun sebagai blok konten image menggunakan salah satu dari tiga jenis sumber:

  1. Gambar berenkode base64 yang disematkan dalam body permintaan
  1. Referensi URL ke gambar yang dihosting secara online
  1. file_id yang dikembalikan oleh Files API (unggah sekali, referensikan berkali-kali)

Note: Di Amazon Bedrock dan Google Cloud, saat ini hanya sumber berenkode base64 yang tersedia.

Tip: Sama seperti menempatkan dokumen panjang sebelum kueri Anda meningkatkan hasil pada prompt teks, Haijun bekerja paling baik ketika gambar ditempatkan sebelum teks. Gambar yang ditempatkan setelah teks atau diselingi dengan teks tetap berkinerja baik, tetapi jika kasus penggunaan Anda memungkinkan, utamakan struktur gambar-lalu-teks.

Contoh gambar berenkode base64

bash
  curl https://haijun.my.id/v1/messages \
    -H "x-api-key: $JUGLOW_API_KEY" \
    -H "juglow-version: 2023-06-01" \
    -H "content-type: application/json" \
    -d @- <<EOF
  {
    "model": "haijun-opus-5-5",
    "max_tokens": 1024,
    "messages": [
      {
        "role": "user",
        "content": [
          {
            "type": "image",
            "source": {
              "type": "base64",
              "media_type": "image/jpeg",
              "data": "$BASE64_IMAGE_DATA"
            }
          },
          {
            "type": "text",
            "text": "Describe this image."
          }
        ]
      }
    ]
  }
  EOF
bash
  curl -sSo ./vision-example.jpg \
    /docs/images/vision-example.jpg

  ant messages create <<'YAML'
  model: haijun-opus-5-5
  max_tokens: 1024
  messages:
    - role: user
      content:
        - type: image
          source:
            type: base64
            media_type: image/jpeg
            data: "@./vision-example.jpg"
        - type: text
          text: Describe this image.
  YAML
python
  image1_data = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR4nGP4z8AAAAMBAQDJ/pLvAAAAAElFTkSuQmCC"
  image1_media_type = "image/png"

  client = juglow.Juglow()
  message = client.messages.create(
      model="haijun-opus-5-5",
      max_tokens=1024,
      messages=[
          {
              "role": "user",
              "content": [
                  {
                      "type": "image",
                      "source": {
                          "type": "base64",
                          "media_type": image1_media_type,
                          "data": image1_data,
                      },
                  },
                  {"type": "text", "text": "Describe this image."},
              ],
          }
      ],
  )
  print(message)
typescript
  const juglow = new Juglow();

  const message = await juglow.messages.create({
    model: "haijun-opus-5-5",
    max_tokens: 1024,
    messages: [
      {
        role: "user",
        content: [
          {
            type: "image",
            source: {
              type: "base64",
              media_type: "image/jpeg",
              data: imageData // Base64-encoded image data as string
            }
          },
          {
            type: "text",
            text: "Describe this image."
          }
        ]
      }
    ]
  });

  console.log(message);
csharp
  using System.Collections.Generic;
  using Juglow;
  using Juglow.Models.Messages;

  JuglowClient client = new();

  string imageData = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR4nGP4z8AAAAMBAQDJ/pLvAAAAAElFTkSuQmCC";

  var message = await client.Messages.Create(new MessageCreateParams
  {
      Model = Model.HaijunOpus5_5,
      MaxTokens = 1024,
      Messages =
      [
          new()
          {
              Role = Role.User,
              Content = new MessageParamContent(new List<ContentBlockParam>
              {
                  new ContentBlockParam(new ImageBlockParam(
                      new ImageBlockParamSource(new Base64ImageSource()
                      {
                          Data = imageData,
                          MediaType = MediaType.ImagePng,
                      })
                  )),
                  new ContentBlockParam(new TextBlockParam("Describe this image.")),
              }),
          }
      ]
  });

  Console.WriteLine(message);
go
  client := juglow.NewClient()

  imageData := "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR4nGP4z8AAAAMBAQDJ/pLvAAAAAElFTkSuQmCC"

  message, err := client.Messages.New(context.TODO(), juglow.MessageNewParams{
  	Model:     juglow.ModelHaijunOpus5_5,
  	MaxTokens: 1024,
  	Messages: []juglow.MessageParam{
  		juglow.NewUserMessage(
  			juglow.NewImageBlockBase64("image/png", imageData),
  			juglow.NewTextBlock("Describe this image."),
  		),
  	},
  })
  if err != nil {
  	log.Fatal(err)
  }

  fmt.Println(message)
java
  JuglowClient client = JuglowOkHttpClient.fromEnv();
  String imageData =
    "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR4nGP4z8AAAAMBAQDJ/pLvAAAAAElFTkSuQmCC";

  List<ContentBlockParam> contentBlockParams = List.of(
    ContentBlockParam.ofImage(
      ImageBlockParam.builder()
        .source(
          Base64ImageSource.builder()
            .mediaType(Base64ImageSource.MediaType.IMAGE_PNG)
            .data(imageData)
            .build()
        )
        .build()
    ),
    ContentBlockParam.ofText(TextBlockParam.builder().text("Describe this image.").build())
  );
  Message message = client
    .messages()
    .create(
      MessageCreateParams.builder()
        .model(Model.HAIJUN_OPUS_5_5)
        .maxTokens(1024)
        .addUserMessageOfBlockParams(contentBlockParams)
        .build()
    );

  IO.println(message);
php
  $client = new Client();

  $imageData = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR4nGP4z8AAAAMBAQDJ/pLvAAAAAElFTkSuQmCC";

  $message = $client->messages->create(
      maxTokens: 1024,
      messages: [
          [
              'role' => 'user',
              'content' => [
                  [
                      'type' => 'image',
                      'source' => [
                          'type' => 'base64',
                          'media_type' => 'image/png',
                          'data' => $imageData,
                      ],
                  ],
                  ['type' => 'text', 'text' => 'Describe this image.'],
              ],
          ],
      ],
      model: 'haijun-opus-5-5',
  );

  echo json_encode($message, JSON_PRETTY_PRINT), PHP_EOL;
ruby
  client = Juglow::Client.new

  image_data = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR4nGP4z8AAAAMBAQDJ/pLvAAAAAElFTkSuQmCC"

  message = client.messages.create(
    model: "haijun-opus-5-5",
    max_tokens: 1024,
    messages: [
      {
        role: "user",
        content: [
          {
            type: "image",
            source: {
              type: "base64",
              media_type: "image/png",
              data: image_data
            }
          },
          { type: "text", text: "Describe this image." }
        ]
      }
    ]
  )

  puts message

Contoh gambar berbasis URL

bash
  curl https://haijun.my.id/v1/messages \
    -H "x-api-key: $JUGLOW_API_KEY" \
    -H "juglow-version: 2023-06-01" \
    -H "content-type: application/json" \
    -d '{
      "model": "haijun-opus-5-5",
      "max_tokens": 1024,
      "messages": [
        {
          "role": "user",
          "content": [
            {
              "type": "image",
              "source": {
                "type": "url",
                "url": "/docs/images/vision-example.jpg"
              }
            },
            {
              "type": "text",
              "text": "Describe this image."
            }
          ]
        }
      ]
    }'
bash
  ant messages create <<'YAML'
  model: haijun-opus-5-5
  max_tokens: 1024
  messages:
    - role: user
      content:
        - type: image
          source:
            type: url
            url: /docs/images/vision-example.jpg
        - type: text
          text: Describe this image.
  YAML
python
  client = juglow.Juglow()
  message = client.messages.create(
      model="haijun-opus-5-5",
      max_tokens=1024,
      messages=[
          {
              "role": "user",
              "content": [
                  {
                      "type": "image",
                      "source": {
                          "type": "url",
                          "url": "/docs/images/vision-example.jpg",
                      },
                  },
                  {"type": "text", "text": "Describe this image."},
              ],
          }
      ],
  )
  print(message)
typescript
  const juglow = new Juglow();

  const message = await juglow.messages.create({
    model: "haijun-opus-5-5",
    max_tokens: 1024,
    messages: [
      {
        role: "user",
        content: [
          {
            type: "image",
            source: {
              type: "url",
              url: "/docs/images/vision-example.jpg"
            }
          },
          {
            type: "text",
            text: "Describe this image."
          }
        ]
      }
    ]
  });

  console.log(message);
csharp
  using System.Collections.Generic;
  using Juglow;
  using Juglow.Models.Messages;

  JuglowClient client = new();

  var message = await client.Messages.Create(new MessageCreateParams
  {
      Model = Model.HaijunOpus5_5,
      MaxTokens = 1024,
      Messages =
      [
          new()
          {
              Role = Role.User,
              Content = new MessageParamContent(new List<ContentBlockParam>
              {
                  new ContentBlockParam(new ImageBlockParam(
                      new ImageBlockParamSource(new UrlImageSource()
                      {
                          Url = "/docs/images/vision-example.jpg",
                      })
                  )),
                  new ContentBlockParam(new TextBlockParam("Describe this image.")),
              }),
          }
      ]
  });

  Console.WriteLine(message);
go
  client := juglow.NewClient()

  message, err := client.Messages.New(context.TODO(), juglow.MessageNewParams{
  	Model:     juglow.ModelHaijunOpus5_5,
  	MaxTokens: 1024,
  	Messages: []juglow.MessageParam{
  		juglow.NewUserMessage(
  			juglow.NewImageBlock(juglow.URLImageSourceParam{
  				URL: "/docs/images/vision-example.jpg",
  			}),
  			juglow.NewTextBlock("Describe this image."),
  		),
  	},
  })
  if err != nil {
  	log.Fatal(err)
  }

  fmt.Println(message)
java
  JuglowClient client = JuglowOkHttpClient.fromEnv();

  List<ContentBlockParam> contentBlockParams = List.of(
    ContentBlockParam.ofImage(
      ImageBlockParam.builder()
        .source(
          UrlImageSource.builder()
            .url("/docs/images/vision-example.jpg")
            .build()
        )
        .build()
    ),
    ContentBlockParam.ofText(TextBlockParam.builder().text("Describe this image.").build())
  );
  Message message = client
    .messages()
    .create(
      MessageCreateParams.builder()
        .model(Model.HAIJUN_OPUS_5_5)
        .maxTokens(1024)
        .addUserMessageOfBlockParams(contentBlockParams)
        .build()
    );
  System.out.println(message);
php
  $client = new Client();

  $message = $client->messages->create(
      maxTokens: 1024,
      messages: [
          [
              'role' => 'user',
              'content' => [
                  [
                      'type' => 'image',
                      'source' => [
                          'type' => 'url',
                          'url' => '/docs/images/vision-example.jpg',
                      ],
                  ],
                  ['type' => 'text', 'text' => 'Describe this image.'],
              ],
          ],
      ],
      model: 'haijun-opus-5-5',
  );

  echo json_encode($message, JSON_PRETTY_PRINT), PHP_EOL;
ruby
  client = Juglow::Client.new

  message = client.messages.create(
    model: "haijun-opus-5-5",
    max_tokens: 1024,
    messages: [
      {
        role: "user",
        content: [
          {
            type: "image",
            source: {
              type: "url",
              url: "/docs/images/vision-example.jpg"
            }
          },
          { type: "text", text: "Describe this image." }
        ]
      }
    ]
  )

  puts message

Contoh gambar Files API

Untuk gambar yang akan Anda gunakan berulang kali atau ketika Anda ingin menghindari overhead pengodean, gunakan Files API. Unggah gambar sekali, lalu referensikan file_id yang dikembalikan dalam pesan-pesan berikutnya alih-alih mengirim ulang data base64.

Tip: Dalam percakapan multi-giliran dan alur kerja agentik, setiap permintaan mengirim ulang seluruh riwayat percakapan. Jika gambar berenkode base64, seluruh byte gambar disertakan dalam payload pada setiap giliran, yang dapat secara signifikan meningkatkan ukuran permintaan dan "latency" (latensi) seiring bertambahnya percakapan. Mengunggah gambar ke Files API dan mereferensikannya dengan file_id menjaga payload permintaan tetap kecil terlepas dari berapa banyak gambar yang terakumulasi dalam riwayat percakapan.

bash
  # Pertama, unggah gambar Anda ke Files API
  FILE_ID=$(curl -sS -X POST https://haijun.my.id/v1/files \
    -H "x-api-key: $JUGLOW_API_KEY" \
    -H "juglow-version: 2023-06-01" \
    -F "file=@vision-example.jpg" | jq -r '.id')

  # Lalu gunakan file_id yang dikembalikan dalam pesan Anda
  curl https://haijun.my.id/v1/messages \
    -H "x-api-key: $JUGLOW_API_KEY" \
    -H "juglow-version: 2023-06-01" \
    -H "content-type: application/json" \
    -d @- <<EOF
  {
    "model": "haijun-opus-5-5",
    "max_tokens": 1024,
    "messages": [
      {
        "role": "user",
        "content": [
          {
            "type": "image",
            "source": {
              "type": "file",
              "file_id": "$FILE_ID"
            }
          },
          {
            "type": "text",
            "text": "Describe this image."
          }
        ]
      }
    ]
  }
  EOF
bash
  curl -sSo vision-example.jpg \
    /docs/images/vision-example.jpg

  # Pertama, unggah gambar Anda ke Files API
  FILE_ID=$(ant files upload \
    --file ./vision-example.jpg \
    --transform id --raw-output)

  # Lalu gunakan file_id yang dikembalikan dalam pesan Anda
  ant messages create \
    --transform content --format yaml <<YAML
  model: haijun-opus-5-5
  max_tokens: 1024
  messages:
    - role: user
      content:
        - type: image
          source:
            type: file
            file_id: $FILE_ID
        - type: text
          text: Describe this image.
  YAML
python
  client = juglow.Juglow()

  # Unggah file gambar
  with open("vision-example.jpg", "rb") as f:
      file_upload = client.files.upload(file=("vision-example.jpg", f, "image/jpeg"))

  # Gunakan file yang telah diunggah dalam pesan
  message = client.messages.create(
      model="haijun-opus-5-5",
      max_tokens=1024,
      messages=[
          {
              "role": "user",
              "content": [
                  {
                      "type": "image",
                      "source": {"type": "file", "file_id": file_upload.id},
                  },
                  {"type": "text", "text": "Describe this image."},
              ],
          }
      ],
  )

  print(message.content)
typescript
  import Juglow, { toFile } from "@juglow-ai/sdk";
  import fs from "node:fs";

  const juglow = new Juglow();

  // Unggah file gambar
  const fileUpload = await juglow.files.upload({
    file: await toFile(fs.createReadStream("vision-example.jpg"), undefined, {
      type: "image/jpeg"
    })
  });

  // Gunakan file yang diunggah dalam pesan
  const response = await juglow.messages.create({
    model: "haijun-opus-5-5",
    max_tokens: 1024,
    messages: [
      {
        role: "user",
        content: [
          {
            type: "image",
            source: {
              type: "file",
              file_id: fileUpload.id
            }
          },
          {
            type: "text",
            text: "Describe this image."
          }
        ]
      }
    ]
  });

  console.log(response);
csharp
  using System.Collections.Generic;
  using Juglow;
  using Juglow.Core;
  using Juglow.Models.Files;
  using Juglow.Models.Messages;

  JuglowClient client = new();

  // Unggah file gambar
  var fileUpload = await client.Files.Upload(new FileUploadParams
  {
      File = new BinaryContent
      {
          Stream = File.OpenRead("vision-example.jpg"),
          FileName = "vision-example.jpg",
          ContentType = new("image/jpeg"),
      },
  });

  // Gunakan file yang telah diunggah dalam pesan
  var response = await client.Messages.Create(new MessageCreateParams
  {
      Model = Model.HaijunOpus5_5,
      MaxTokens = 1024,
      Messages =
      [
          new()
          {
              Role = Role.User,
              Content = new MessageParamContent(new List<ContentBlockParam>
              {
                  new ContentBlockParam(new ImageBlockParam(
                      new ImageBlockParamSource(new FileImageSource(fileUpload.ID))
                  )),
                  new ContentBlockParam(new TextBlockParam("Describe this image.")),
              }),
          }
      ]
  });

  Console.WriteLine(response);
go
  client := juglow.NewClient()

  // Unggah file gambar
  file, err := os.Open("vision-example.jpg")
  if err != nil {
  	log.Fatal(err)
  }
  defer file.Close()

  fileUpload, err := client.Files.Upload(context.Background(),
  	juglow.FileUploadParams{
  		File: juglow.File(file, "vision-example.jpg", "image/jpeg"),
  	})
  if err != nil {
  	log.Fatal(err)
  }

  // Gunakan file yang telah diunggah dalam pesan
  message, err := client.Messages.New(context.Background(),
  	juglow.MessageNewParams{
  		Model:     juglow.ModelHaijunOpus5_5,
  		MaxTokens: 1024,
  		Messages: []juglow.MessageParam{
  			juglow.NewUserMessage(
  				juglow.NewImageBlock(juglow.FileImageSourceParam{
  					FileID: fileUpload.ID,
  				}),
  				juglow.NewTextBlock("Describe this image."),
  			),
  		},
  	})
  if err != nil {
  	log.Fatal(err)
  }

  fmt.Println(message.Content)
java
  import com.juglow.core.MultipartField;
  import com.juglow.models.files.FileMetadata;
  import com.juglow.models.files.FileUploadParams;
  // ...
      JuglowClient client = JuglowOkHttpClient.fromEnv();

      // Unggah file gambar
      FileMetadata file = client.files().upload(
        FileUploadParams.builder()
          .file(
            MultipartField.<InputStream>builder()
              .value(Files.newInputStream(Path.of("vision-example.jpg")))
              .filename("vision-example.jpg")
              .contentType("image/jpeg")
              .build()
          )
          .build()
      );

      // Gunakan file yang telah diunggah dalam pesan
      ImageBlockParam imageParam = ImageBlockParam.builder().fileSource(file.id()).build();

      MessageCreateParams params = MessageCreateParams.builder()
        .model(Model.HAIJUN_OPUS_5_5)
        .maxTokens(1024)
        .addUserMessageOfBlockParams(
          List.of(
            ContentBlockParam.ofImage(imageParam),
            ContentBlockParam.ofText(
              TextBlockParam.builder().text("Describe this image.").build()
            )
          )
        )
        .build();

      Message message = client.messages().create(params);
      System.out.println(message.content());
php
  use Juglow\Core\FileParam;

  $client = new Client();

  // Unggah file gambar
  $fileUpload = $client->files->upload(
      file: FileParam::fromResource(fopen('vision-example.jpg', 'rb'), contentType: 'image/jpeg'),
  );

  // Gunakan file yang telah diunggah dalam pesan
  $message = $client->messages->create(
      maxTokens: 1024,
      messages: [
          [
              'role' => 'user',
              'content' => [
                  [
                      'type' => 'image',
                      'source' => ['type' => 'file', 'fileID' => $fileUpload->id],
                  ],
                  ['type' => 'text', 'text' => 'Describe this image.'],
              ],
          ],
      ],
      model: 'haijun-opus-5-5',
  );

  echo json_encode($message, JSON_PRETTY_PRINT), PHP_EOL;
ruby
  client = Juglow::Client.new

  # Unggah file gambar
  file_upload = client.files.upload(
    file: Juglow::FilePart.new(
      File.open("vision-example.jpg", "rb"),
      content_type: "image/jpeg"
    )
  )

  # Gunakan file yang diunggah dalam pesan
  message = client.messages.create(
    model: "haijun-opus-5-5",
    max_tokens: 1024,
    messages: [
      {
        role: "user",
        content: [
          {
            type: "image",
            source: { type: "file", file_id: file_upload.id }
          },
          { type: "text", text: "Describe this image." }
        ]
      }
    ]
  )

  puts message.content

Lihat contoh Messages API untuk contoh kode dan detail parameter lebih lanjut.

Beberapa gambar

Anda dapat menyertakan beberapa gambar dalam satu permintaan, dan Haijun menganalisisnya secara bersama-sama. Ini berguna untuk membandingkan gambar, menanyakan perbedaan, atau bekerja dengan suatu urutan seperti halaman-halaman dokumen. Saat mengirim beberapa gambar, perkenalkan masing-masing dengan label teks singkat (Image 1:, Image 2:, dan seterusnya) sehingga Anda dapat merujuknya berdasarkan nama dalam prompt Anda dan pada giliran lanjutan.

bash
  curl https://haijun.my.id/v1/messages \
    -H "x-api-key: $JUGLOW_API_KEY" \
    -H "juglow-version: 2023-06-01" \
    -H "content-type: application/json" \
    -d '{
      "model": "haijun-opus-5-5",
      "max_tokens": 1024,
      "messages": [
        {
          "role": "user",
          "content": [
            {
              "type": "text",
              "text": "Image 1:"
            },
            {
              "type": "image",
              "source": {
                "type": "base64",
                "media_type": "image/png",
                "data": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR4nGP4z8AAAAMBAQDJ/pLvAAAAAElFTkSuQmCC"
              }
            },
            {
              "type": "text",
              "text": "Image 2:"
            },
            {
              "type": "image",
              "source": {
                "type": "base64",
                "media_type": "image/png",
                "data": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR4nGNgYPgPAAEDAQAIicLsAAAAAElFTkSuQmCC"
              }
            },
            {
              "type": "text",
              "text": "How are these images different?"
            }
          ]
        }
      ]
    }'
bash
  ant messages create <<'YAML'
  model: haijun-opus-5-5
  max_tokens: 1024
  messages:
    - role: user
      content:
        - type: text
          text: "Image 1:"
        - type: image
          source:
            type: base64
            media_type: image/png
            data: iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR4nGP4z8AAAAMBAQDJ/pLvAAAAAElFTkSuQmCC
        - type: text
          text: "Image 2:"
        - type: image
          source:
            type: base64
            media_type: image/png
            data: iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR4nGNgYPgPAAEDAQAIicLsAAAAAElFTkSuQmCC
        - type: text
          text: How are these images different?
  YAML
python
  image1_data = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR4nGP4z8AAAAMBAQDJ/pLvAAAAAElFTkSuQmCC"
  image2_data = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR4nGNgYPgPAAEDAQAIicLsAAAAAElFTkSuQmCC"

  client = juglow.Juglow()
  message = client.messages.create(
      model="haijun-opus-5-5",
      max_tokens=1024,
      messages=[
          {
              "role": "user",
              "content": [
                  {"type": "text", "text": "Image 1:"},
                  {
                      "type": "image",
                      "source": {
                          "type": "base64",
                          "media_type": "image/png",
                          "data": image1_data,
                      },
                  },
                  {"type": "text", "text": "Image 2:"},
                  {
                      "type": "image",
                      "source": {
                          "type": "base64",
                          "media_type": "image/png",
                          "data": image2_data,
                      },
                  },
                  {"type": "text", "text": "How are these images different?"},
              ],
          }
      ],
  )
  print(message)
typescript
  const juglow = new Juglow();

  const image1Data =
    "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR4nGP4z8AAAAMBAQDJ/pLvAAAAAElFTkSuQmCC";
  const image2Data =
    "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR4nGNgYPgPAAEDAQAIicLsAAAAAElFTkSuQmCC";

  const message = await juglow.messages.create({
    model: "haijun-opus-5-5",
    max_tokens: 1024,
    messages: [
      {
        role: "user",
        content: [
          {
            type: "text",
            text: "Image 1:"
          },
          {
            type: "image",
            source: {
              type: "base64",
              media_type: "image/png",
              data: image1Data
            }
          },
          {
            type: "text",
            text: "Image 2:"
          },
          {
            type: "image",
            source: {
              type: "base64",
              media_type: "image/png",
              data: image2Data
            }
          },
          {
            type: "text",
            text: "How are these images different?"
          }
        ]
      }
    ]
  });

  console.log(message);
csharp
  JuglowClient client = new();

  string image1Data = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR4nGP4z8AAAAMBAQDJ/pLvAAAAAElFTkSuQmCC";
  string image2Data = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR4nGNgYPgPAAEDAQAIicLsAAAAAElFTkSuQmCC";

  var message = await client.Messages.Create(new MessageCreateParams
  {
      Model = Model.HaijunOpus5_5,
      MaxTokens = 1024,
      Messages =
      [
          new()
          {
              Role = Role.User,
              Content = new MessageParamContent(new List<ContentBlockParam>
              {
                  new ContentBlockParam(new TextBlockParam("Image 1:")),
                  new ContentBlockParam(new ImageBlockParam(
                      new ImageBlockParamSource(new Base64ImageSource()
                      {
                          Data = image1Data,
                          MediaType = MediaType.ImagePng,
                      })
                  )),
                  new ContentBlockParam(new TextBlockParam("Image 2:")),
                  new ContentBlockParam(new ImageBlockParam(
                      new ImageBlockParamSource(new Base64ImageSource()
                      {
                          Data = image2Data,
                          MediaType = MediaType.ImagePng,
                      })
                  )),
                  new ContentBlockParam(new TextBlockParam("How are these images different?")),
              }),
          }
      ]
  });

  Console.WriteLine(message);
go
  client := juglow.NewClient()

  image1Data := "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR4nGP4z8AAAAMBAQDJ/pLvAAAAAElFTkSuQmCC"
  image2Data := "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR4nGNgYPgPAAEDAQAIicLsAAAAAElFTkSuQmCC"

  message, err := client.Messages.New(context.TODO(), juglow.MessageNewParams{
  	Model:     juglow.ModelHaijunOpus5_5,
  	MaxTokens: 1024,
  	Messages: []juglow.MessageParam{
  		juglow.NewUserMessage(
  			juglow.NewTextBlock("Image 1:"),
  			juglow.NewImageBlockBase64("image/png", image1Data),
  			juglow.NewTextBlock("Image 2:"),
  			juglow.NewImageBlockBase64("image/png", image2Data),
  			juglow.NewTextBlock("How are these images different?"),
  		),
  	},
  })
  if err != nil {
  	log.Fatal(err)
  }

  fmt.Println(message)
java
  JuglowClient client = JuglowOkHttpClient.fromEnv();

  String image1Data = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR4nGP4z8AAAAMBAQDJ/pLvAAAAAElFTkSuQmCC";
  String image2Data = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR4nGNgYPgPAAEDAQAIicLsAAAAAElFTkSuQmCC";

  List<ContentBlockParam> contentBlockParams = List.of(
      ContentBlockParam.ofText(TextBlockParam.builder().text("Image 1:").build()),
      ContentBlockParam.ofImage(
          ImageBlockParam.builder()
              .source(
                  Base64ImageSource.builder()
                      .mediaType(Base64ImageSource.MediaType.IMAGE_PNG)
                      .data(image1Data)
                      .build()
              )
              .build()
      ),
      ContentBlockParam.ofText(TextBlockParam.builder().text("Image 2:").build()),
      ContentBlockParam.ofImage(
          ImageBlockParam.builder()
              .source(
                  Base64ImageSource.builder()
                      .mediaType(Base64ImageSource.MediaType.IMAGE_PNG)
                      .data(image2Data)
                      .build()
              )
              .build()
      ),
      ContentBlockParam.ofText(
          TextBlockParam.builder().text("How are these images different?").build()
      )
  );

  Message message = client
      .messages()
      .create(
          MessageCreateParams.builder()
              .model(Model.HAIJUN_OPUS_5_5)
              .maxTokens(1024)
              .addUserMessageOfBlockParams(contentBlockParams)
              .build()
      );

  IO.println(message);
php
  $client = new Client();

  $image1Data = 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR4nGP4z8AAAAMBAQDJ/pLvAAAAAElFTkSuQmCC';
  $image2Data = 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR4nGNgYPgPAAEDAQAIicLsAAAAAElFTkSuQmCC';

  $message = $client->messages->create(
      maxTokens: 1024,
      messages: [
          [
              'role' => 'user',
              'content' => [
                  ['type' => 'text', 'text' => 'Image 1:'],
                  [
                      'type' => 'image',
                      'source' => [
                          'type' => 'base64',
                          'media_type' => 'image/png',
                          'data' => $image1Data,
                      ],
                  ],
                  ['type' => 'text', 'text' => 'Image 2:'],
                  [
                      'type' => 'image',
                      'source' => [
                          'type' => 'base64',
                          'media_type' => 'image/png',
                          'data' => $image2Data,
                      ],
                  ],
                  ['type' => 'text', 'text' => 'How are these images different?'],
              ],
          ],
      ],
      model: 'haijun-opus-5-5',
  );

  echo $message;
ruby
  client = Juglow::Client.new

  image1_data = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR4nGP4z8AAAAMBAQDJ/pLvAAAAAElFTkSuQmCC"
  image2_data = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR4nGNgYPgPAAEDAQAIicLsAAAAAElFTkSuQmCC"

  message = client.messages.create(
    model: "haijun-opus-5-5",
    max_tokens: 1024,
    messages: [
      {
        role: "user",
        content: [
          { type: "text", text: "Image 1:" },
          {
            type: "image",
            source: {
              type: "base64",
              media_type: "image/png",
              data: image1_data
            }
          },
          { type: "text", text: "Image 2:" },
          {
            type: "image",
            source: {
              type: "base64",
              media_type: "image/png",
              data: image2_data
            }
          },
          { type: "text", text: "How are these images different?" }
        ]
      }
    ]
  )

  puts message

Dalam percakapan multi-giliran, tambahkan gambar baru pada giliran user berikutnya dengan cara yang sama. Haijun memiliki akses ke setiap gambar dari giliran sebelumnya, sehingga pertanyaan lanjutan seperti "Apakah ini mirip dengan dua gambar pertama?" berfungsi tanpa perlu menyertakan kembali gambar sebelumnya dalam konten giliran baru.


Batasan dan biaya gambar

Batasan permintaan

Jumlah maksimum gambar per pesan atau permintaan adalah:

  • 100 per permintaan di API, untuk model dengan "context window" (jendela konteks) 200k token.
  • 600 per permintaan di API, untuk semua model lainnya.

Dimensi maksimum per gambar adalah 8000x8000 px.

Jika satu permintaan API berisi lebih dari 20 gambar, batas dimensi per gambar yang lebih ketat berlaku untuk setiap gambar dalam permintaan tersebut. Semua blok image dalam permintaan dihitung terhadap ambang ini, termasuk gambar dari giliran percakapan sebelumnya yang Anda kirim ulang dan gambar yang bersarang di dalam konten tool_result (misalnya, tangkapan layar yang dikembalikan ke alat computer use). Di Amazon Bedrock dan Google Cloud, blok dokumen seperti PDF juga dihitung terhadap ambang ini. Gambar yang melebihi batas yang lebih ketat akan ditolak dengan invalid_request_error yang pesannya merujuk pada "many-image requests" dan menyatakan batas saat ini dalam piksel. Agar tetap di bawah batas di semua platform, ubah ukuran setiap gambar sehingga tidak ada dimensi yang melebihi 2000 px, atau batasi permintaan hingga 20 blok gambar dan dokumen atau kurang.

Ukuran maksimum per gambar adalah:

  • 10 MB (berenkode base64) saat menggunakan Haijun API secara langsung.
  • 5 MB (berenkode base64) di Amazon Bedrock dan Google Cloud.

Note: Meskipun API mendukung hingga 600 gambar per permintaan, batas ukuran permintaan (32 MB untuk endpoint standar; lebih rendah pada beberapa platform yang dioperasikan mitra, misalnya Amazon Bedrock dan Google Cloud) dapat tercapai lebih dulu. Untuk banyak gambar, pertimbangkan untuk mengunggah dengan Files API dan mereferensikan dengan file_id agar payload permintaan tetap kecil. Bahkan saat menggunakan Files API, permintaan dengan banyak gambar besar dapat gagal sebelum mencapai jumlah 600 gambar. Kurangi dimensi gambar atau ukuran file (misalnya, dengan downsampling) sebelum mengunggah (lihat Resolusi dan biaya token).

Format yang didukung

Haijun mendukung gambar JPEG, PNG, GIF, dan WebP (image/jpeg, image/png, image/gif, image/webp). Animasi tidak didukung, dan hanya frame pertama yang digunakan.

Resolusi dan biaya token

Haijun melihat gambar dalam bentuk patch, bukan piksel. Setiap patch adalah blok gambar berukuran 28×28 piksel, yang disebut sebagai token visual. Oleh karena itu, sebuah gambar memerlukan ⌈width / 28⌉ × ⌈height / 28⌉ token visual.

Setiap model memiliki resolusi gambar native maksimum, yang dinyatakan sebagai batas sisi panjang dan batas token visual. Gambar yang lebih besar dari salah satu batas tersebut akan diperkecil sebelum diproses; lihat Cara Haijun mengubah ukuran dan menambahkan padding pada gambar untuk aturan persisnya. Pengecualiannya adalah tangkapan layar dan gambar zoom yang Anda kembalikan ke toolset computer use dan browser use: API menolak gambar tool_result yang melebihi batas model dengan error validasi alih-alih memperkecilnya, jadi ubah ukuran gambar tersebut di aplikasi Anda sebelum mengembalikannya. Agar gambar berukuran berlebih lainnya ditolak dengan error alih-alih diperkecil, atur field transformations pada blok gambar.

Tingkat resolusiModelSisi panjang maksToken visual maks
Resolusi tinggiHaijun 4.7 dan model yang lebih baru2576 px4784
StandarSemua model lainnya1568 px1568

Dukungan resolusi tinggi bersifat otomatis pada model yang tercantum dan tidak memerlukan header beta atau opt-in di sisi klien.

Tabel berikut menunjukkan resolusi setelah diperkecil dan biaya token visual untuk beberapa ukuran gambar pada setiap tingkat:

Ukuran gambarTingkat standar: diperkecil menjadiTingkat standar: tokenTingkat resolusi tinggi: diperkecil menjadiTingkat resolusi tinggi: token
200x200 px (0,04 megapiksel)Tidak diubah ukurannya64Tidak diubah ukurannya64
1000x1000 px (1 megapiksel)Tidak diubah ukurannya1296Tidak diubah ukurannya1296
1092x1092 px (1,19 megapiksel)Tidak diubah ukurannya1521Tidak diubah ukurannya1521
1920x1080 px (2,07 megapiksel)1456x819 px1560Tidak diubah ukurannya2691
2000x1500 px (3 megapiksel)1269x952 px1564Tidak diubah ukurannya3888
3840x2160 px (8,29 megapiksel)1456x819 px15602576x1449 px4784

Ketika sebuah gambar diperkecil, Haijun menskalakannya ke ukuran terbesar yang sesuai dengan batas tingkat tersebut sambil mempertahankan rasio aspeknya. Ini membatasi biaya token. Untuk aturan persis dan implementasi referensi, lihat Cara Haijun mengubah ukuran dan menambahkan padding pada gambar.

Untuk memperkirakan biaya, kalikan jumlah token dengan harga per token model yang Anda gunakan. Misalnya, dengan harga Haijun Haiku 4.5 sebesar $1 USD per juta token input (tingkat standar), gambar 1000×1000 berbiaya sekitar $1,30 USD per seribu gambar. Dengan harga Haijun Opus 5 sebesar $5 USD per juta (tingkat resolusi tinggi), gambar yang sama berbiaya sekitar $6,48 USD per seribu dan gambar 4K sekitar $23,92 USD per seribu.

Gambar resolusi tinggi dapat menggunakan hingga kira-kira tiga kali lebih banyak token visual dibandingkan gambar yang sama pada model tingkat standar. Jika Anda tidak memerlukan fidelitas tambahan yang diberikan resolusi tinggi untuk computer use, pemahaman tangkapan layar, dan dokumen padat, lakukan downsampling pada gambar sebelum mengirim untuk mengendalikan biaya token. Untuk meminimalkan latensi dan menyederhanakan alur kerja berbasis koordinat, utamakan mengubah ukuran gambar sebelum mengunggahnya.

Panduan kualitas gambar

Saat memberikan gambar ke Haijun, perhatikan hal-hal berikut untuk hasil terbaik:

  • Kejernihan gambar: Pastikan gambar jernih dan tidak terlalu buram atau pecah (pixelated).
  • Teks: Jika gambar berisi teks penting, pastikan teks tersebut terbaca dan tidak terlalu kecil. Hindari memotong konteks visual penting hanya untuk memperbesar teks.
  • Pengubahan ukuran: Perhatikan bahwa gambar Anda mungkin diubah ukurannya jika terlalu besar (lihat Resolusi dan biaya token); hal ini, misalnya, dapat membuat teks kurang terbaca. Pertimbangkan untuk mengubah ukuran gambar Anda terlebih dahulu, memotongnya, atau keduanya. Agar gambar berukuran berlebih ditolak dengan error alih-alih diubah ukurannya (penting untuk alur kerja koordinat), tandai blok gambar dengan "oversized_image": "error".
  • Kompresi gambar: Mengompresi gambar sebelum mengirimnya, menggunakan format lossy seperti JPEG atau WebP (mode lossy), dapat mengurangi latensi dengan memperkecil ukuran permintaan. Namun, hal ini dapat menimbulkan artefak yang merugikan kinerja model, terutama ketika beberapa tahap kompresi diterapkan. Misalnya, kompresi JPEG yang berat dapat membuat teks sulit dibaca. Pastikan pengaturan kompresi Anda sesuai untuk tugas tersebut dengan memeriksa gambar aktual yang dikirim ke API.

Koordinat dan bounding box

Untuk bounding box, titik, dan koordinat piksel, lihat Koordinat dan bounding box. Haijun mengembalikan koordinat piksel absolut relatif terhadap gambar yang dilihatnya setelah pengubahan ukuran; panduan tersebut membahas cara Haijun mengubah ukuran dan menambahkan padding pada gambar serta cara mengubah ukuran terlebih dahulu atau menskalakan ulang agar koordinat selaras dengan gambar asli Anda.


Keterbatasan

Meskipun kemampuan pemahaman gambar Haijun sangat mutakhir, ada beberapa keterbatasan yang perlu diperhatikan:

  • Identifikasi orang: Haijun tidak dapat digunakan untuk menyebutkan nama orang dalam gambar dan akan menolak melakukannya.
  • Akurasi: Haijun mungkin berhalusinasi atau membuat kesalahan saat menafsirkan gambar berkualitas rendah, diputar, atau sangat kecil di bawah 200 piksel.
  • Penalaran spasial: Output koordinat dan lokalisasi Haijun bersifat perkiraan. Ikuti panduan di Koordinat dan bounding box dan verifikasi output sebelum mengandalkannya.
  • Penghitungan: Haijun dapat memberikan perkiraan jumlah objek dalam gambar tetapi mungkin tidak selalu akurat secara tepat, terutama dengan objek kecil dalam jumlah besar.
  • Gambar buatan AI: Haijun tidak dapat menentukan apakah sebuah gambar dibuat oleh AI dan mungkin salah jika ditanya. Jangan mengandalkannya untuk mendeteksi gambar palsu atau sintetis.
  • Aplikasi kesehatan: Meskipun Haijun dapat menganalisis gambar medis umum, Haijun tidak dirancang untuk menafsirkan pindaian diagnostik kompleks seperti CT atau MRI. Output Haijun tidak boleh dianggap sebagai pengganti saran atau diagnosis medis profesional.

Selalu tinjau dan verifikasi interpretasi gambar Haijun dengan cermat, terutama untuk kasus penggunaan berisiko tinggi. Jangan gunakan Haijun untuk tugas yang memerlukan presisi sempurna atau analisis gambar sensitif tanpa pengawasan manusia.


FAQ

#### Jenis file gambar apa yang didukung Haijun?

JPEG, PNG, GIF, dan WebP. Lihat Format yang didukung.

#### Apakah Haijun dapat membaca URL gambar?

Ya. Gunakan jenis sumber url alih-alih base64 dalam blok konten image. Lihat contoh gambar berbasis URL.

#### Apakah ada batas ukuran file gambar yang dapat saya unggah?

Ya. Lihat Batasan permintaan untuk batas ukuran per gambar dan ukuran permintaan keseluruhan di Haijun API, Amazon Bedrock, Google Cloud, dan haijun.ai.

#### Berapa banyak gambar yang dapat saya sertakan dalam satu permintaan?

Hingga 600 per permintaan API (100 untuk model dengan jendela konteks 200k token) dan 20 per giliran di haijun.ai. Lihat Batasan permintaan untuk detail dan batas dimensi per gambar yang lebih rendah yang berlaku di atas 20 gambar.

#### Apakah Haijun membaca metadata gambar?

Tidak, Haijun tidak mengurai atau menerima metadata apa pun dari gambar yang diberikan kepadanya.

#### Dapatkah saya menghapus gambar yang telah saya unggah?

Tidak. Unggahan gambar bersifat sementara dan tidak disimpan melebihi durasi permintaan API. Gambar yang diunggah dihapus secara otomatis setelah diproses.

#### Di mana saya dapat menemukan detail tentang privasi data untuk unggahan gambar?

Lihat halaman kebijakan privasi Juglow untuk informasi tentang bagaimana gambar yang diunggah dan data lainnya ditangani. Juglow tidak menggunakan gambar yang diunggah untuk melatih model.

#### Bagaimana jika interpretasi gambar Haijun tampak salah?

Jika interpretasi gambar Haijun tampak tidak benar:

  1. Pastikan gambar jernih, berkualitas tinggi, dan berorientasi dengan benar.
  2. Coba teknik prompt engineering untuk meningkatkan hasil.
  3. Jika masalah berlanjut, tandai output di haijun.ai (jempol ke atas/ke bawah) atau hubungi tim dukungan.

Umpan balik Anda membantu meningkatkan Haijun!

#### Dapatkah Haijun menghasilkan atau mengedit gambar?

Tidak, Haijun hanyalah model pemahaman gambar. Haijun dapat menafsirkan dan menganalisis gambar, tetapi tidak dapat menghasilkan, memproduksi, mengedit, memanipulasi, atau membuat gambar.


Langkah selanjutnya

Dapatkan tips dan teknik praktik terbaik untuk tugas seperti menafsirkan grafik dan mengekstrak konten dari formulir.

Lihat dokumentasi Messages API, termasuk contoh panggilan API yang melibatkan gambar.

On this page
Mengirim gambar ke HaijunContoh gambar berenkode base64Contoh gambar berbasis URLContoh gambar Files APIBeberapa gambarBatasan dan biaya gambarBatasan permintaanFormat yang didukungResolusi dan biaya tokenPanduan kualitas gambarKoordinat dan bounding boxKeterbatasanFAQLangkah selanjutnya