Meta 모델 API
Meta 모델 API (Model API)
Meta의 Model API를 LiteLLM에서 사용하는 방법을 알아봐요. Muse Spark 추론 모델과 Muse Voice 전사 기능에 접근할 수 있어요.
출처: 문서
본문
| 속성 | 내용 |
|---|---|
| 설명 | Meta의 Model API는 Muse Spark 추론 모델과 Muse Voice 전사 기능에 대한 접근을 제공해요 |
| LiteLLM 라우트 | meta/ |
| 지원 엔드포인트 | /chat/completions, /responses, /v1/messages, /v1/realtime |
| 개발자 포털 | Meta Model API ↗ |
| Speech-to-Text 레퍼런스 | Muse Voice transcription ↗ |
필수 변수
os.environ["META_API_KEY"] = "" # your Meta Model API key
Chat, Responses, Messages 요청은 기본적으로 https://api.meta.ai/v1로 가며, META_API_BASE로 해당 base를 덮어쓸 수 있어요. Muse Voice realtime은 동일한 META_API_KEY를 사용하고 wss://api.meta.ai/v1/asr/realtime에 연결돼요.
지원 모델
info: LiteLLM은 모델 목록·가격·토큰 윈도우 등을 여기서 적극 유지·관리하고 있어요.
| 모델 ID | 입력 컨텍스트 길이 | 입력 모달리티 | 출력 모달리티 |
|---|---|---|---|
muse-spark-1.1 |
1M | Text, Image, Video, PDF | Text |
muse-voice-transcribe-1.0 |
N/A | Audio | Text |
muse-spark-1.1은 함수 호출, 병렬 함수 호출, 구조화 출력, 프롬프트 캐싱, 웹 검색 근거 부여, 그리고 reasoning_effort("minimal"부터 "xhigh"까지)를 통한 추론을 지원해요.
muse-voice-transcribe-1.0은 proxy의 /v1/realtime WebSocket을 통해 제공되는 실시간 speech-to-text 모델이며, 오디오 1초당 과금돼요. 실시간 전용이라 /v1/audio/transcriptions 및 기타 배치·파일 전사 엔드포인트는 지원되지 않아요.
또한 이 API는 기본적으로 Anthropic Messages 포맷도 노출하므로, LiteLLM은 /v1/messages 요청을 변환 없이 https://api.meta.ai/v1/messages로 전달하며 thinking 블록 같은 Anthropic 전용 기능을 그대로 보존해요.
Muse Voice 실시간 전사
LiteLLM은 Muse Voice를 proxy의 OpenAI 호환 /v1/realtime 엔드포인트로 제공해요. 클라이언트는 OpenAI Realtime 전사 프로토콜로 말하고, LiteLLM은 PCM16 오디오를 바이너리 프레임으로 wss://api.meta.ai/v1/asr/realtime에 스트리밍하며 Muse의 전사 프레임을 OpenAI 이벤트로 매핑해요. 아래 Python 예시는 완전한 push to talk 세션 예시예요.
1. config에 모델 추가
config.yaml:
model_list:
- model_name: muse-voice-transcribe
litellm_params:
model: meta/muse-voice-transcribe-1.0
api_key: os.environ/META_API_KEY
api_key는 META_API_KEY로 폴백돼요. api_base는 선택 사항이며 절대 wss:// 또는 https:// URL이어야 해요. LiteLLM은 호스트와 포트를 유지하고 경로만 /v1/asr/realtime으로 교체해요. http://, ws://, 인라인 자격 증명, URL 프래그먼트는 거부되며, realtime 세션에서는 META_API_BASE가 무시돼요.
LiteLLM Proxy 시작:
litellm --config config.yaml
# RUNNING on http://0.0.0.0:4000
2. 연결
ws://localhost:4000/v1/realtime?model=muse-voice-transcribe&intent=transcription
Authorization: Bearer ***로 인증해요. model은 config의 model_name이며 필수이고, intent=transcription만 있으면 proxy의 기본 OpenAI 전사 모델로 라우팅돼요. intent=transcription은 세션을 전사 전용으로 만들고 session.update에 있는 어떤 모델이든 인증받은 모델로 고정해요.
LiteLLM은 Meta에 연결된 후, Muse 핸드셰이크 전에 object: realtime.transcription_session인 session.created를 내보내요.
3. 세션 구성
session.update(또는 transcription_session.update)를 하나 보내요. Muse의 승인은 session.updated로 돌아오며, 이후 업데이트는 무시돼요. session.updated 전에 보낸 오디오는 버퍼링됐다가 재생되므로 바로 스트리밍을 시작할 수 있어요.
{
"type": "session.update",
"session": {
"type": "transcription",
"audio": {
"input": {
"format": {"type": "audio/pcm", "rate": 24000, "channels": 1},
"transcription": {"model": "meta/muse-voice-transcribe-1.0", "language": "en"},
"turn_detection": null
}
}
}
}
필드 규칙:
| 필드 | 규칙 |
|---|---|
format |
type은 audio/pcm, rate는 16000 또는 24000, channels는 1이어야 함. 생략 시 모노 24kHz |
transcription.model |
선택. intent=transcription이면 proxy가 muse-voice-transcribe-1.0으로 교체. 없으면 muse-voice-transcribe-1.0 또는 meta/muse-voice-transcribe-1.0만 허용 |
transcription.language |
선택. 이름 또는 ISO 639 코드로 한 언어에 편향. 리전 접미사는 무시되므로 en-US, zh-Hans, pt-BR 모두 동작 |
turn_detection |
모드를 선택(아래 표). server_vad 외의 type은 거부. type이 없는 객체는 server VAD를 의미 |
| 그 외 | proxy 로그에 경고와 함께 삭제 |
베타 레이아웃: input_audio_format: "pcm16" + input_audio_transcription는 24kHz에서 허용돼요. 한 업데이트에서 두 레이아웃을 섞지 마세요.
지원 언어: 아랍어, 벵골어, 네덜란드어, 영어, 프랑스어, 독일어, 히브리어, 힌디어, 인도네시아어, 이탈리아어, 일본어, 칸나다어, 한국어, 마라티어, 말레이어, 중국어(만다린), 폴란드어, 포르투갈어, 스페인어, 타갈로그어, 타밀어, 텔루구어, 태국어, 터키어, 베트남어.
| Push to talk | Server VAD | |
|---|---|---|
turn_detection |
null |
생략, 또는 {"type": "server_vad"} |
| 턴 경계 | 세션당 한 턴. 언제 끝날지는 사용자가 결정 | Muse가 발화를 감지. 각 발화는 고유 item_id를 가짐 |
| 턴 종료 | input_audio_buffer.commit이 버퍼링된 오디오를 플러시하고 Muse 스트림을 종료 |
input_audio_buffer.commit은 플러시만 수행. 끝날 때 input_audio_buffer.end 전송 |
잘못된 session.update(잘못된 rate, 채널 수, 턴 감지 타입, 언어)는 코드 1006으로 연결을 닫고 error 이벤트는 없어요. 이유는 디버그 레벨로 Error in client ack messages: ...에 기록돼요. 설정 후 프로토콜 위반(4초 초과 append, 잘못된 base64, 홀수 PCM 바이트 등)도 같은 방식으로 닫혀요.
4. 오디오 스트리밍
input_audio_buffer.append는 설정된 rate의 base64 모노 PCM16을 이벤트당 최대 4초까지 운반해요. LiteLLM은 오디오를 80ms 바이너리 프레임으로 재패키징해 실시간으로 Muse에 전달해요. input_audio_buffer.clear는 LiteLLM이 아직 보유 중인 부분 프레임을 버려요. 이미 Muse에 보낸 오디오는 되돌릴 수 없어요. response.create를 포함한 다른 모든 클라이언트 이벤트는 삭제돼요.
Server VAD는 오디오가 실시간으로 계속 도착해야 해요. 휴지 중엔 침묵을 스트리밍하고, 끝나면 (OpenAI 프로토콜의 일부가 아닌 LiteLLM 이벤트인) input_audio_buffer.end를 보내요. 클라이언트가 단순히 보내기를 멈추면 Meta가 코드 1008(Ingress below real-time)로 닫으며, proxy는 이를 error 이벤트 후 1008 닫기로 중계해요.
5. 전사 읽기
| 이벤트 | 필드 | 시점 |
|---|---|---|
session.created |
session.object: realtime.transcription_session |
연결 시, Muse 핸드셰이크 전 |
session.updated |
정규화된 세션: channels 없음, model은 muse-voice-transcribe-1.0, language는 전체 이름 (en → English) |
Muse가 session.update 승인 후 |
input_audio_buffer.speech_started |
item_id |
Muse가 턴 시작 감지 |
conversation.item.input_audio_transcription.delta |
item_id, content_index: 0, delta |
부분 전사 텍스트 |
input_audio_buffer.speech_stopped |
item_id |
Muse가 턴 끝 감지 |
conversation.item.input_audio_transcription.completed |
item_id, content_index: 0, transcript; usage: {"type": "duration", "seconds": 1.36} (이전 completed 이후 새로운 오디오 처리 시) |
턴의 최종 전사 |
error |
error.type: server_error; error.message는 Meta Muse realtime transcription failed, 또는 비-1000 닫기 전 upstream websocket closed with code : |
Muse 오류 보고 또는 비정상 종료 |
턴은 겹칠 수 있고 item_id로 상관관계가 매겨져요. Muse에 더 이상 세그먼트가 없으면 코드 1000(보통 이유 No more transcript segments)으로 닫고 proxy가 그 닫기를 중계해요.
가격 및 사용량
Muse Voice는 입력 오디오 1초당 과금돼요(모델 비용 맵의 input_cost_per_second). usage.seconds는 마지막 과금 지점 이후 Muse가 처리한 오디오(침묵 포함)이므로 발화 길이를 초과할 수 있어요. 마지막 completed 이후의 오디오(예: 꼬리 침묵)는 세션 종료 시 과금돼요.
전사본은 메시지 로깅이 꺼져 있지 않으면 스펜드 로그의 messages에 저장돼요. proxy 로그는 가드레일로 차단된 전사의 첫 80자(경고 레벨)를 제외하고 전사 텍스트를 담지 않아요.
가드레일
mode: realtime_input_transcription 가드레일이 각 완성된 전사에서 실행돼요. completed 이벤트는 가드레일 전에 클라이언트에 도달하며, 델타는 검사되지 않아요. 차단 시 type: guardrail_violation, code: content_policy_violation인 error 이벤트가 전송되며, on_violation: end_session은 코드 1000으로 소켓도 닫아요.
연결마다 guardrails=name1,name2 쿼리 파라미터로 가드레일을 선택할 수 있어요.
warning:
realtime_input_transcription가드레일을 구성하면 LiteLLM이 Muse가 보기 전에 클라이언트의turn_detection: null을{"create_response": false}로 다시 작성해요. 따라서 push to talk 클라이언트는 server VAD 모드에서 실행되며,input_audio_buffer.commit이 더 이상 스트림을 종료하지 않고, 스트리밍을 멈춘 클라이언트는 코드1008로 연결이 끊겨요. Server VAD 클라이언트는 영향을 받지 않아요.
예시 Python 클라이언트
Push to talk: 100ms 청크의 모노 PCM16 WAV 파일을 구성·스트리밍하고, commit한 뒤 proxy가 소켓을 닫을 때까지 이벤트를 읽어요.
import asyncio
import base64
import json
import wave
import websockets
URL = "ws://localhost:4000/v1/realtime?model=muse-voice-transcribe&intent=transcription"
HEADERS = {"Authorization": "Bearer sk-1234"} # your proxy API key
def pcm_chunks(path, chunk_ms=100):
with wave.open(path) as w: # mono PCM16 at 16 kHz or 24 kHz
rate, frames = w.getframerate(), w.readframes(w.getnframes())
step = rate * 2 * chunk_ms // 1000
return rate, [frames[i : i + step] for i in range(0, len(frames), step)]
async def main():
rate, chunks = pcm_chunks("question.wav")
async with websockets.connect(URL, additional_headers=HEADERS) as ws:
print(json.loads(await ws.recv())["type"]) # session.created
await ws.send(json.dumps({
"type": "session.update",
"session": {
"type": "transcription",
"audio": {
"input": {
"format": {"type": "audio/pcm", "rate": rate},
"transcription": {"model": "meta/muse-voice-transcribe-1.0"},
"turn_detection": None,
}
},
},
}))
print(json.loads(await ws.recv())["type"]) # session.updated
for chunk in chunks:
await ws.send(json.dumps({"type": "input_audio_buffer.append", "audio": base64.b64encode(chunk).decode()}))
await asyncio.sleep(0.1)
await ws.send(json.dumps({"type": "input_audio_buffer.commit"}))
try:
while True:
event = json.loads(await ws.recv())
if event["type"] == "conversation.item.input_audio_transcription.delta":
print(event["delta"], end="", flush=True)
elif event["type"] == "conversation.item.input_audio_transcription.completed":
seconds = event.get("usage", {}).get("seconds") # absent when Muse reported no new audio
print(f"\n{event['transcript']} ({seconds} s)")
except websockets.exceptions.ConnectionClosedOK:
pass # close code 1000: no more transcript segments
asyncio.run(main())
session.created
session.updated
What is the weather in Paris?
What is the weather in Paris? (1.36 s)
Server VAD의 경우 None 대신 "turn_detection": {"type": "server_vad"}를 보내고, 마이크가 열려 있는 동안 (침묵 포함) 스트리밍을 계속하며, {"type": "input_audio_buffer.end"}로 마무리해요. 감지된 각 발화는 고유한 item_id로 도착해요.
LiteLLM Python SDK 사용법
비스트리밍
import os
import litellm
from litellm import completion
os.environ["META_API_KEY"] = "" # your Meta Model API key
messages = [{"content": "Hello, how are you?", "role": "user"}]
response = completion(model="meta/muse-spark-1.1", messages=messages)
스트리밍
import os
import litellm
from litellm import completion
os.environ["META_API_KEY"] = "" # your Meta Model API key
messages = [{"content": "Hello, how are you?", "role": "user"}]
response = completion(
model="meta/muse-spark-1.1",
messages=messages,
stream=True
)
for chunk in response:
print(chunk)
추론 노력 (Reasoning Effort)
muse-spark-1.1은 reasoning_effort 값을 "minimal", "low", "medium", "high", "xhigh"로 받아요.
import os
import litellm
from litellm import completion
os.environ["META_API_KEY"] = "" # your Meta Model API key
messages = [{"content": "What is 15% of 2840?", "role": "user"}]
response = completion(
model="meta/muse-spark-1.1",
messages=messages,
reasoning_effort="xhigh"
)
print(response.choices[0].message.content)
print(response.usage.completion_tokens_details.reasoning_tokens)
함수 호출
import os
import litellm
from litellm import completion
os.environ["META_API_KEY"] = "" # your Meta Model API key
messages = [{"content": "What's the weather like in San Francisco?", "role": "user"}]
tools = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get the current weather in a given location",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city and state, e.g. San Francisco, CA"
},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"]
}
},
"required": ["location"]
}
}
}
]
response = completion(
model="meta/muse-spark-1.1",
messages=messages,
tools=tools,
tool_choice="auto"
)
print(response.choices[0].message.tool_calls)
LiteLLM Proxy 사용법
LiteLLM Proxy 설정 파일에 다음을 추가해요.
config.yaml:
model_list:
- model_name: muse-spark-1.1
litellm_params:
model: meta/muse-spark-1.1
api_key: os.environ/META_API_KEY
Proxy 서버 시작:
litellm --config config.yaml
# RUNNING on http://0.0.0.0:4000
Proxy를 통한 Meta Model API - 비스트리밍 (OpenAI SDK):
from openai import OpenAI
client = OpenAI(
base_url="http://localhost:4000", # Your proxy URL
api_key="your-proxy-api-key" # Your proxy API key
)
response = client.chat.completions.create(
model="muse-spark-1.1",
messages=[{"role": "user", "content": "Write a short poem about AI."}],
reasoning_effort="minimal"
)
print(response.choices[0].message.content)
스트리밍:
from openai import OpenAI
client = OpenAI(
base_url="http://localhost:4000", # Your proxy URL
api_key="your-proxy-api-key" # Your proxy API key
)
response = client.chat.completions.create(
model="muse-spark-1.1",
messages=[{"role": "user", "content": "Write a short poem about AI."}],
stream=True
)
for chunk in response:
if chunk.choices[0].delta.content is not None:
print(chunk.choices[0].delta.content, end="")
LiteLLM SDK:
import litellm
response = litellm.completion(
model="litellm_proxy/muse-spark-1.1",
messages=[{"role": "user", "content": "Write a short poem about AI."}],
api_base="http://localhost:4000",
api_key="your-proxy-api-key"
)
print(response.choices[0].message.content)
cURL:
curl http://localhost:4000/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer your-p...-key" \
-d '{
"model": "muse-spark-1.1",
"messages": [{"role": "user", "content": "Write a short poem about AI."}],
"reasoning_effort": "minimal"
}'
Anthropic Messages API
proxy의 /v1/messages 라우트는 meta/ 모델의 요청을 변환 없이 Meta의 네이티브 Anthropic 호환 엔드포인트로 전달해요.
curl http://localhost:4000/v1/messages \
-H "Content-Type: application/json" \
-H "Authorization: Bearer your-p...-key" \
-d '{
"model": "muse-spark-1.1",
"max_tokens": 2048,
"messages": [{"role": "user", "content": "Write a short poem about AI."}]
}'
더 알아보기 (Learn more)
- Meta Model API 개발자 포털
- Muse Voice 실시간 전사
- LiteLLM 리얼타임 가드레일