일상/앰버서더

Kanana-o API 소개 (feat. 베타 테스터)

JONGSKY 2026. 4. 18. 22:53
728x90
반응형
SMALL

1. 글을 쓰게 된 계기

 

오늘 소개해볼 내용은 Kanana-o API 입니다!


이번에 베타 테스터로 선정되면서 사용방법이나

어떤 기능들이 있는지 살펴보고 소개해드리려고 합니다.

 

Kanana는 카카오가 자체 개발한 AI 모델 라인업인데요
그중에서도 Kanana-oOmni 모델

텍스트·이미지·음성을 한 번에 다룰 수 있는 멀티모달 모델입니다.

 

 

 

2. Kanana-o API 가 뭐야?

 

카카오의 Kanana 모델은 목적에 따라 여러 라인업으로 나뉘어 있습니다.

  • Kanana V — 비전 모델 (이미지 이해)
  • Kanana A — 오디오 모델 (음성 이해)
  • Kanana O — 옴니 모델 (텍스트 + 이미지 + 음성 통합)

 

https://tech.kakao.com/posts/802

 

 

Kanana-o의 핵심은 입력과 출력 모두 여러 모달리티를 지원한다는 점입니다.

예를 들어 이미지와 음성을 동시에 입력으로 받고

텍스트 응답뿐 아니라 음성 응답까지 한 번의 호출로 받을 수 있습니다.

 

지금까지는 이미지 인식 → LLM → TTS 순서로 파이프라인을 직접 연결해야 했던 작업이

옴니 모델에서는 한 번의 API 호출로 끝난다는 것이 가장 큰 차별점입니다.

 

3. Kanana-o API 베타 서비스 소개

 

3-1. 접근 방식

 

Kanana-o API는 OpenAI SDK와 호환됩니다.

즉, 기존에 OpenAI API를 쓰고 있었다면 base_url만 바꿔도 거의 그대로 사용할 수 있습니다.

 

from openai import OpenAI

client = OpenAI(
    base_url="https://kanana-o.a2s-endpoint.kr-central-2.kakaocloud.com/v1",
    api_key="YOUR_API_KEY"
)

 

진입 장벽이 낮아서, 처음 써보시는 분들도 부담 없이 시작할 수 있을 것 같습니다.

 

3-2. 실제 써보기

 

Response as Text — 이미지 이해

 

먼저 가장 기본이 되는 이미지 이해 예제입니다.

이미지 파일을 base64로 인코딩해서 image_url 필드에 넣어주면 됩니다.

import base64

from openai import OpenAI

client = OpenAI(
    base_url="https://kanana-o.a2s-endpoint.kr-central-2.kakaocloud.com/v1",
    api_key=""
)

def b64_of_file(path: str) -> str:
    with open(path, "rb") as f:
        return base64.b64encode(f.read()).decode("utf-8")

# Image understanding
image_b64 = b64_of_file("captioning_lion_1k.jpg")
response = client.chat.completions.create(
    model="kanana-o",
    messages=[
        {
            "role": "user",
            "content": [
                {"type": "image_url", "image_url": {"url": image_b64}},
                {"type": "text", "text": "What is in this image?"}
            ]
        }
    ],
)

print(response.choices[0].message.content)

 

 

Response as Audio — 멀티모달 입출력

 

두 번째는 이미지 + 음성을 입력으로 받고, 텍스트 + 음성으로 응답받는 예제입니다.

옴니 모델의 진가가 드러나는 부분입니다.

 

import base64

from openai import OpenAI

client = OpenAI(
    base_url="https://kanana-o.a2s-endpoint.kr-central-2.kakaocloud.com/v1",
    api_key=""
)

def b64_of_file(path: str) -> str:
    with open(path, "rb") as f:
        return base64.b64encode(f.read()).decode("utf-8")

image_b64 = b64_of_file("captioning_lion_1k.jpg")
audio_b64 = b64_of_file("instruction.wav")
response = client.chat.completions.create(
    model="kanana-o",
    messages=[
        {
            "role": "user",
            "content": [
                {"type": "image_url", "image_url": {"url": image_b64}},
                {"type": "input_audio", "input_audio": {"data": audio_b64, "format": "wav"}},
            ]
        }
    ],
    modalities=["text", "audio"],
    stream=True,
)

 

여기서 중요한 파라미터는 두 가지입니다.

  • modalities=["text", "audio"] — 출력을 텍스트와 음성 모두로 받겠다는 선언
  • stream=True — 스트리밍 응답 사용

스트리밍으로 받은 응답은 청크 단위로 내려오는데

각 청크의 delta.audio 안에 base64 인코딩된 PCM 데이터가 담겨 있습니다.

이를 WAV 파일로 저장하고 이어붙이는 후처리가 필요합니다.

 

import os
import wave

SAMPLE_RATE = 24000
os.makedirs("result", exist_ok=True)

text_content = ""
out_wavs = []
cnt = 0

for chunk in response:
    raw = chunk.model_dump()
    choices = raw.get("choices") or []
    if not choices:
        continue
    delta = choices[0].get("delta") or {}

    content = delta.get("content")
    if isinstance(content, str) and content:
        print(content, end="", flush=True)
        text_content += content

    audio = delta.get("audio")
    if audio is None:
        continue

    audio_b64_data = None
    if isinstance(audio, str):
        audio_b64_data = audio
    elif isinstance(audio, dict):
        audio_b64_data = audio.get("data") or audio.get("audio")

    if isinstance(audio_b64_data, str) and audio_b64_data:
        pcm = base64.b64decode(audio_b64_data, validate=True)
        if pcm:
            out = f"result/{cnt:04d}_chunk.wav"
            cnt += 1
            with wave.open(out, "wb") as wf:
                wf.setnchannels(1)
                wf.setsampwidth(2)
                wf.setframerate(SAMPLE_RATE)
                wf.writeframes(pcm)
            out_wavs.append(out)
            print(f"\nsaved {out}", flush=True)

print(f"Saved {cnt} audio chunk(s) under result/")

if out_wavs:
    all_frames = b""
    for f in out_wavs:
        with wave.open(f, "rb") as wf:
            all_frames += wf.readframes(wf.getnframes())
    with wave.open("result/result.wav", "wb") as wf:
        wf.setnchannels(1)
        wf.setsampwidth(2)
        wf.setframerate(SAMPLE_RATE)
        wf.writeframes(all_frames)
    print("merged -> result/result.wav")
else:
    print("No audio in response")

 

 

오디오 출력 스펙을 정리하면 아래와 같습니다.

  • Sample Rate: 24,000 Hz
  • Channels: 1 (mono)
  • Sample Width: 2 bytes (16-bit PCM)

 

3-3. 성능

https://tech.kakao.com/posts/802

 

 

실제로 사용해봤을 때 이미지 설명도 꽤 정확하게 해주었고

특히 음성 쪽에서 한국어를 감정을 살려서 표현하는 데 특화되어 있다는 느낌을 받았습니다.

 

 

 

 

그리고 카카오 Kanana 에서 말하는 자연스럽게 말하는 AI가 어떤 걸 표현하고자 하는지 느낄 수 있었습니다.

가장 자연스럽게 말하는 AI
억양, 속도, 감정, 화자 특성을 고려해 풍부한 감정과 자연스러운 표현으로 사람처럼 말하고 반응합니다.

 

 

또한 글로벌 멀티모달 모델들도 한국어를 어느 정도 처리하긴 하지만

한국어 맥락과 한국어 발화의 자연스러움에 초점을 맞춘 모델은 흔치 않습니다.

 

이 부분이 Kanana-o의 가장 뚜렷한 차별점이라고 느꼈습니다.

 

4. 참고

 

 

Kanana-o

더욱 똑똑하게 답하며, 더욱 풍부한 감정표현을 향한 Kanana-o의 진화 과정

omni.kanana.ai

 

 

더욱 똑똑하게 답하며, 더욱 풍부한 감정표현을 향한 Kanana-o의 진화 과정 - tech.kakao.com

안녕하세요, 카카오의 AI 모델 개발을 담당하는 카나나(Kanana) 조직의 Ed...

tech.kakao.com

 

 

Kanana-o 신규 모델 및 API 베타 서비스를 공개합니다. - tech.kakao.com

카카오가 독자적인 기술력으로 완성한 가장 뛰어난 옴니(Omni) 모델, Kana...

tech.kakao.com

 

728x90
반응형
LIST