Spaces:
Running
Running
| # ACE-Step OpenRouter API λ¬Έμ | |
| > AI μμ μμ±μ μν OpenAI Chat Completions νΈν API | |
| **Base URL:** `http://{host}:{port}` (κΈ°λ³Έκ° `http://127.0.0.1:8002`) | |
| --- | |
| ## λͺ©μ°¨ | |
| - [μΈμ¦](#μΈμ¦) | |
| - [μλν¬μΈνΈ](#μλν¬μΈνΈ) | |
| - [POST /v1/chat/completions - μμ μμ±](#1-μμ -μμ±) | |
| - [GET /v1/models - λͺ¨λΈ λͺ©λ‘](#2-λͺ¨λΈ-λͺ©λ‘) | |
| - [GET /health - ν¬μ€ 체ν¬](#3-ν¬μ€-체ν¬) | |
| - [μ λ ₯ λͺ¨λ](#μ λ ₯-λͺ¨λ) | |
| - [μ€λμ€ μ λ ₯](#μ€λμ€-μ λ ₯) | |
| - [μ€νΈλ¦¬λ° μλ΅](#μ€νΈλ¦¬λ°-μλ΅) | |
| - [μμ ](#μμ ) | |
| - [μλ¬ μ½λ](#μλ¬-μ½λ) | |
| --- | |
| ## μΈμ¦ | |
| μλ²μ API ν€κ° μ€μ λ κ²½μ°(νκ²½ λ³μ `OPENROUTER_API_KEY` λλ `--api-key` νλκ·Έ μ¬μ©), λͺ¨λ μμ²μ λ€μ ν€λλ₯Ό ν¬ν¨ν΄μΌ ν©λλ€: | |
| ``` | |
| Authorization: Bearer <your-api-key> | |
| ``` | |
| API ν€κ° μ€μ λμ§ μμ κ²½μ° μΈμ¦μ΄ νμνμ§ μμ΅λλ€. | |
| --- | |
| ## μλν¬μΈνΈ | |
| ### 1. μμ μμ± | |
| **POST** `/v1/chat/completions` | |
| μ±ν λ©μμ§λ‘λΆν° μμ μ μμ±νκ³ μ€λμ€ λ°μ΄ν°μ LMμ΄ μμ±ν λ©νλ°μ΄ν°λ₯Ό λ°νν©λλ€. | |
| #### μμ² νλΌλ―Έν° | |
| | νλ | νμ | νμ | κΈ°λ³Έκ° | μ€λͺ | | |
| |---|---|---|---|---| | |
| | `model` | string | μλμ | μλ | λͺ¨λΈ ID (`/v1/models`μμ νμΈ) | | |
| | `messages` | array | **μ** | - | μ±ν λ©μμ§ λ¦¬μ€νΈ. [μ λ ₯ λͺ¨λ](#μ λ ₯-λͺ¨λ) μ°Έμ‘° | | |
| | `stream` | boolean | μλμ | `false` | μ€νΈλ¦¬λ° μλ΅ νμ±ν. [μ€νΈλ¦¬λ° μλ΅](#μ€νΈλ¦¬λ°-μλ΅) μ°Έμ‘° | | |
| | `audio_config` | object | μλμ | `null` | μ€λμ€ μμ± μ€μ . μλ μ°Έμ‘° | | |
| | `temperature` | float | μλμ | `0.85` | LM μνλ§ μ¨λ | | |
| | `top_p` | float | μλμ | `0.9` | LM nucleus sampling νλΌλ―Έν° | | |
| | `seed` | int \| string | μλμ | `null` | λλ€ μλ. `batch_size > 1`μΌ λ μΌνλ‘ κ΅¬λΆνμ¬ μ¬λ¬ κ° μ§μ κ°λ₯ (μ: `"42,123,456"`) | | |
| | `lyrics` | string | μλμ | `""` | μ§μ μ λ¬λλ κ°μ¬ (λ©μμ§μμ νμ±λ κ°μ¬λ³΄λ€ μ°μ ). μ€μ μ messages ν μ€νΈλ promptλ‘ μ¬μ© | | |
| | `sample_mode` | boolean | μλμ | `false` | LLM sample λͺ¨λ νμ±ν. messages ν μ€νΈκ° sample_queryλ‘ LLMμ μ λ¬λμ΄ prompt/lyrics μλ μμ± | | |
| | `thinking` | boolean | μλμ | `false` | λ κΉμ μΆλ‘ μ μν LLM thinking λͺ¨λ νμ±ν | | |
| | `use_format` | boolean | μλμ | `false` | μ¬μ©μκ° prompt/lyricsλ₯Ό μ 곡ν λ LLM ν¬λ§·ν μΌλ‘ κ°μ | | |
| | `use_cot_caption` | boolean | μλμ | `true` | CoTλ₯Ό ν΅ν΄ μμ μ€λͺ μ μ¬μμ±/κ°μ | | |
| | `use_cot_language` | boolean | μλμ | `true` | CoTλ₯Ό ν΅ν΄ 보컬 μΈμ΄λ₯Ό μλ κ°μ§ | | |
| | `guidance_scale` | float | μλμ | `7.0` | Classifier-free guidance scale | | |
| | `batch_size` | int | μλμ | `1` | μμ±ν μ€λμ€ μ | | |
| | `task_type` | string | μλμ | `"text2music"` | μμ μ ν. [μ€λμ€ μ λ ₯](#μ€λμ€-μ λ ₯) μ°Έμ‘° | | |
| | `repainting_start` | float | μλμ | `0.0` | repaint μμ μμ μμΉ(μ΄) | | |
| | `repainting_end` | float | μλμ | `null` | repaint μμ μ’ λ£ μμΉ(μ΄) | | |
| | `audio_cover_strength` | float | μλμ | `1.0` | μ»€λ² κ°λ (0.0~1.0) | | |
| #### audio_config κ°μ²΄ | |
| | νλ | νμ | κΈ°λ³Έκ° | μ€λͺ | | |
| |---|---|---|---| | |
| | `duration` | float | `null` | μ€λμ€ κΈΈμ΄(μ΄). μλ΅ μ LMμ΄ μλ κ²°μ | | |
| | `bpm` | integer | `null` | λΆλΉ λΉνΈμ(BPM). μλ΅ μ LMμ΄ μλ κ²°μ | | |
| | `vocal_language` | string | `"en"` | 보컬 μΈμ΄ μ½λ (μ: `"ko"`, `"en"`, `"ja"`) | | |
| | `instrumental` | boolean | `null` | 보컬 μλ μ°μ£Όκ³‘ μ¬λΆ. μλ΅ μ κ°μ¬μ λ°λΌ μλ νλ¨ | | |
| | `format` | string | `"mp3"` | μΆλ ₯ μ€λμ€ ν¬λ§· | | |
| | `key_scale` | string | `null` | μ‘°μ± (μ: `"C major"`) | | |
| | `time_signature` | string | `null` | λ°μ (μ: `"4/4"`) | | |
| > **messages ν μ€νΈμ μλ―Έλ λͺ¨λμ λ°λΌ λ€λ¦ λλ€:** | |
| > - `lyrics` μ€μ μ β messages ν μ€νΈ = prompt (μμ μ€λͺ ) | |
| > - `sample_mode: true` μ€μ μ β messages ν μ€νΈ = sample_query (LLMμκ² λͺ¨λ κ²μ μμ±νλλ‘ ν¨) | |
| > - λ λ€ λ―Έμ€μ β μλ κ°μ§: νκ·Έκ° μμΌλ©΄ νκ·Έ λͺ¨λ, κ°μ¬μ²λΌ 보μ΄λ©΄ κ°μ¬ λͺ¨λ, κ·Έ μΈ sample λͺ¨λ | |
| #### messages νμ | |
| μΌλ° ν μ€νΈμ λ©ν°λͺ¨λ¬(ν μ€νΈ + μ€λμ€) λ κ°μ§ νμμ μ§μν©λλ€: | |
| **μΌλ° ν μ€νΈ:** | |
| ```json | |
| { | |
| "messages": [ | |
| {"role": "user", "content": "μ λ ₯ λ΄μ©"} | |
| ] | |
| } | |
| ``` | |
| **λ©ν°λͺ¨λ¬ (μ€λμ€ μ λ ₯ ν¬ν¨):** | |
| ```json | |
| { | |
| "messages": [ | |
| { | |
| "role": "user", | |
| "content": [ | |
| {"type": "text", "text": "μ΄ λ Έλλ₯Ό 컀λ²ν΄μ€"}, | |
| { | |
| "type": "input_audio", | |
| "input_audio": { | |
| "data": "<base64 μ€λμ€ λ°μ΄ν°>", | |
| "format": "mp3" | |
| } | |
| } | |
| ] | |
| } | |
| ] | |
| } | |
| ``` | |
| --- | |
| #### λΉμ€νΈλ¦¬λ° μλ΅ (`stream: false`) | |
| ```json | |
| { | |
| "id": "chatcmpl-a1b2c3d4e5f6g7h8", | |
| "object": "chat.completion", | |
| "created": 1706688000, | |
| "model": "acemusic/acestep-v15-turbo", | |
| "choices": [ | |
| { | |
| "index": 0, | |
| "message": { | |
| "role": "assistant", | |
| "content": "## Metadata\n**Caption:** Upbeat pop song...\n**BPM:** 120\n**Duration:** 30s\n**Key:** C major\n\n## Lyrics\n[Verse 1]\nHello world...", | |
| "audio": [ | |
| { | |
| "type": "audio_url", | |
| "audio_url": { | |
| "url": "data:audio/mpeg;base64,SUQzBAAAAAAAI1RTU0UAAAA..." | |
| } | |
| } | |
| ] | |
| }, | |
| "finish_reason": "stop" | |
| } | |
| ], | |
| "usage": { | |
| "prompt_tokens": 10, | |
| "completion_tokens": 100, | |
| "total_tokens": 110 | |
| } | |
| } | |
| ``` | |
| **μλ΅ νλ μ€λͺ :** | |
| | νλ | μ€λͺ | | |
| |---|---| | |
| | `choices[0].message.content` | LMμ΄ μμ±ν ν μ€νΈ μ 보. Metadata(Caption/BPM/Duration/Key/Time Signature/Language)μ Lyricsλ₯Ό ν¬ν¨. LMμ΄ κ΄μ¬νμ§ μμ κ²½μ° `"Music generated successfully."` λ°ν | | |
| | `choices[0].message.audio` | μ€λμ€ λ°μ΄ν° λ°°μ΄. κ° νλͺ©μ `type` (`"audio_url"`)κ³Ό `audio_url.url` (Base64 Data URL, νμ: `data:audio/mpeg;base64,...`)μ ν¬ν¨ | | |
| | `choices[0].finish_reason` | `"stop"`μ μ μ μλ£λ₯Ό λνλ | | |
| **μ€λμ€ λμ½λ© νμ:** | |
| `audio_url.url` κ°μ Data URL νμ: `data:audio/mpeg;base64,<base64_data>` | |
| μΌν μ΄νμ base64 λ°μ΄ν° λΆλΆμ μΆμΆνμ¬ λμ½λ©νλ©΄ MP3 νμΌμ μ»μ μ μμ΅λλ€: | |
| ```python | |
| import base64 | |
| url = response["choices"][0]["message"]["audio"][0]["audio_url"]["url"] | |
| # "data:audio/mpeg;base64," μ λμ¬ μ κ±° | |
| b64_data = url.split(",", 1)[1] | |
| audio_bytes = base64.b64decode(b64_data) | |
| with open("output.mp3", "wb") as f: | |
| f.write(audio_bytes) | |
| ``` | |
| ```javascript | |
| const url = response.choices[0].message.audio[0].audio_url.url; | |
| const b64Data = url.split(",")[1]; | |
| const audioBytes = atob(b64Data); | |
| // Data URLμ <audio> νκ·Έμ μ§μ μ¬μ© κ°λ₯ | |
| const audio = new Audio(url); | |
| audio.play(); | |
| ``` | |
| --- | |
| ### 2. λͺ¨λΈ λͺ©λ‘ | |
| **GET** `/v1/models` | |
| μ¬μ© κ°λ₯ν λͺ¨λΈ μ 보λ₯Ό λ°νν©λλ€. | |
| #### μλ΅ | |
| ```json | |
| { | |
| "data": [ | |
| { | |
| "id": "acemusic/acestep-v15-turbo", | |
| "name": "ACE-Step", | |
| "created": 1706688000, | |
| "description": "High-performance text-to-music generation model. Supports multiple styles, lyrics input, and various audio durations.", | |
| "input_modalities": ["text", "audio"], | |
| "output_modalities": ["audio", "text"], | |
| "context_length": 4096, | |
| "pricing": {"prompt": "0", "completion": "0", "request": "0"}, | |
| "supported_sampling_parameters": ["temperature", "top_p"] | |
| } | |
| ] | |
| } | |
| ``` | |
| --- | |
| ### 3. ν¬μ€ μ²΄ν¬ | |
| **GET** `/health` | |
| #### μλ΅ | |
| ```json | |
| { | |
| "status": "ok", | |
| "service": "ACE-Step OpenRouter API", | |
| "version": "1.0" | |
| } | |
| ``` | |
| --- | |
| ## μ λ ₯ λͺ¨λ | |
| μμ€ν μ λ§μ§λ§ `user` λ©μμ§μ λ΄μ©μ λ°λΌ μ λ ₯ λͺ¨λλ₯Ό μλμΌλ‘ μ νν©λλ€. `lyrics` λλ `sample_mode` νλλ‘ λͺ μμ μΌλ‘ μ§μ ν μλ μμ΅λλ€. | |
| ### λͺ¨λ 1: νκ·Έ λͺ¨λ (κΆμ₯) | |
| `<prompt>`μ `<lyrics>` νκ·Έλ₯Ό μ¬μ©νμ¬ μμ μ€λͺ κ³Ό κ°μ¬λ₯Ό λͺ μμ μΌλ‘ μ§μ ν©λλ€: | |
| ```json | |
| { | |
| "messages": [ | |
| { | |
| "role": "user", | |
| "content": "<prompt>A gentle acoustic ballad in C major, female vocal</prompt>\n<lyrics>[Verse 1]\nSunlight through the window\nA brand new day begins\n\n[Chorus]\nWe are the dreamers\nWe are the light</lyrics>" | |
| } | |
| ], | |
| "audio_config": { | |
| "duration": 30, | |
| "vocal_language": "en" | |
| } | |
| } | |
| ``` | |
| - `<prompt>...</prompt>` β μμ μ€νμΌ/μ₯λ©΄ μ€λͺ (caption) | |
| - `<lyrics>...</lyrics>` β κ°μ¬ λ΄μ© | |
| - νλμ νκ·Έλ§ μ¬μ©ν μλ μμ | |
| - `use_format: true`μΌ λ LLMμ΄ promptμ lyricsλ₯Ό μλμΌλ‘ κ°μ | |
| ### λͺ¨λ 2: μμ°μ΄ λͺ¨λ (μν λͺ¨λ) | |
| μνλ μμ μ μμ°μ΄λ‘ μ€λͺ ν©λλ€. μμ€ν μ΄ LLMμ μ¬μ©νμ¬ promptμ lyricsλ₯Ό μλμΌλ‘ μμ±ν©λλ€: | |
| ```json | |
| { | |
| "messages": [ | |
| {"role": "user", "content": "μ¬λ¦κ³Ό μ¬νμ κ΄ν μ λλ νμ‘μ λ§λ€μ΄μ€"} | |
| ], | |
| "sample_mode": true, | |
| "audio_config": { | |
| "vocal_language": "ko" | |
| } | |
| } | |
| ``` | |
| νΈλ¦¬κ±° 쑰건: `sample_mode: true`, λλ λ©μμ§μ νκ·Έκ° μκ³ κ°μ¬μ²λΌ 보μ΄μ§ μμ λ μλ νΈλ¦¬κ±°. | |
| ### λͺ¨λ 3: κ°μ¬ μ μ© λͺ¨λ | |
| ꡬ쑰 λ§μ»€κ° μλ κ°μ¬λ₯Ό μ§μ μ λ¬νλ©΄ μμ€ν μ΄ μλμΌλ‘ μΈμν©λλ€: | |
| ```json | |
| { | |
| "messages": [ | |
| { | |
| "role": "user", | |
| "content": "[Verse 1]\nWalking down the street\nFeeling the beat\n\n[Chorus]\nDance with me tonight\nUnder the moonlight" | |
| } | |
| ], | |
| "audio_config": {"duration": 30} | |
| } | |
| ``` | |
| νΈλ¦¬κ±° 쑰건: λ©μμ§μ `[Verse]`, `[Chorus]` λ±μ λ§μ»€κ° ν¬ν¨λκ±°λ μ¬λ¬ μ€μ μ§§μ ν μ€νΈ ꡬ쑰λ₯Ό κ°μ§ κ²½μ°. | |
| ### λͺ¨λ 4: κ°μ¬ + Prompt λΆλ¦¬ | |
| `lyrics` νλλ‘ κ°μ¬λ₯Ό μ§μ μ λ¬νκ³ , messages ν μ€νΈλ μλμΌλ‘ promptλ‘ μ¬μ©λ©λλ€: | |
| ```json | |
| { | |
| "messages": [ | |
| {"role": "user", "content": "Energetic EDM with heavy bass drops"} | |
| ], | |
| "lyrics": "[Verse 1]\nFeel the rhythm in your soul\nLet the music take control\n\n[Drop]\n(instrumental break)", | |
| "audio_config": { | |
| "bpm": 128, | |
| "duration": 60 | |
| } | |
| } | |
| ``` | |
| ### μ°μ£Όκ³‘ λͺ¨λ | |
| `audio_config.instrumental: true` μ€μ : | |
| ```json | |
| { | |
| "messages": [ | |
| {"role": "user", "content": "<prompt>Epic orchestral cinematic score, dramatic and powerful</prompt>"} | |
| ], | |
| "audio_config": { | |
| "instrumental": true, | |
| "duration": 30 | |
| } | |
| } | |
| ``` | |
| --- | |
| ## μ€λμ€ μ λ ₯ | |
| λ©ν°λͺ¨λ¬ messagesλ₯Ό ν΅ν΄ μ€λμ€ νμΌ(base64 μΈμ½λ©)μ μ λ¬νμ¬ cover, repaint λ±μ μμ μ μ¬μ©ν μ μμ΅λλ€. | |
| ### task_type μ ν | |
| | task_type | μ€λͺ | μ€λμ€ μ λ ₯ νμ | | |
| |---|---|---| | |
| | `text2music` | ν μ€νΈμμ μμ μμ± (κΈ°λ³Έκ°) | μ ν (referenceλ‘) | | |
| | `cover` | 컀λ²/μ€νμΌ μ ν | src_audio νμ | | |
| | `repaint` | λΆλΆ 리νμΈν | src_audio νμ | | |
| | `lego` | μ€λμ€ μ ν© | src_audio νμ | | |
| | `extract` | μ€λμ€ μΆμΆ | src_audio νμ | | |
| | `complete` | μ€λμ€ μ΄μ΄μ°κΈ° | src_audio νμ | | |
| ### μ€λμ€ λΌμ°ν κ·μΉ | |
| μ¬λ¬ `input_audio` λΈλ‘μ μμλλ‘ λ€λ₯Έ νλΌλ―Έν°μ λΌμ°ν λ©λλ€ (λ€μ€ μ΄λ―Έμ§ μ λ‘λμ μ μ¬): | |
| | task_type | audio[0] | audio[1] | | |
| |---|---|---| | |
| | `text2music` | reference_audio (μ€νμΌ μ°Έμ‘°) | - | | |
| | `cover/repaint/lego/extract/complete` | src_audio (νΈμ§ λμ μ€λμ€) | reference_audio (μ νμ μ€νμΌ μ°Έμ‘°) | | |
| ### μ€λμ€ μ λ ₯ μμ | |
| **Cover μμ (컀λ²):** | |
| ```json | |
| { | |
| "messages": [ | |
| { | |
| "role": "user", | |
| "content": [ | |
| {"type": "text", "text": "<prompt>Jazz style cover with saxophone</prompt>"}, | |
| { | |
| "type": "input_audio", | |
| "input_audio": {"data": "<base64 μλ³Έ μ€λμ€>", "format": "mp3"} | |
| } | |
| ] | |
| } | |
| ], | |
| "task_type": "cover", | |
| "audio_cover_strength": 0.8, | |
| "audio_config": {"duration": 30} | |
| } | |
| ``` | |
| **Repaint μμ (λΆλΆ 리νμΈν ):** | |
| ```json | |
| { | |
| "messages": [ | |
| { | |
| "role": "user", | |
| "content": [ | |
| {"type": "text", "text": "<prompt>Replace with guitar solo</prompt>"}, | |
| { | |
| "type": "input_audio", | |
| "input_audio": {"data": "<base64 μλ³Έ μ€λμ€>", "format": "mp3"} | |
| } | |
| ] | |
| } | |
| ], | |
| "task_type": "repaint", | |
| "repainting_start": 10.0, | |
| "repainting_end": 20.0, | |
| "audio_config": {"duration": 30} | |
| } | |
| ``` | |
| --- | |
| ## μ€νΈλ¦¬λ° μλ΅ | |
| `"stream": true`λ‘ μ€μ νλ©΄ SSE(Server-Sent Events) μ€νΈλ¦¬λ°μ΄ νμ±νλ©λλ€. | |
| ### μ΄λ²€νΈ νμ | |
| κ° μ΄λ²€νΈλ `data: `λ‘ μμνκ³ JSONμ΄ λ€λ°λ₯΄λ©° μ΄μ€ μ€λ°κΏ `\n\n`μΌλ‘ λλ©λλ€: | |
| ``` | |
| data: {"id":"chatcmpl-xxx","object":"chat.completion.chunk","created":1706688000,"model":"acemusic/acestep-v15-turbo","choices":[{"index":0,"delta":{...},"finish_reason":null}]} | |
| ``` | |
| ### μ€νΈλ¦¬λ° μ΄λ²€νΈ μμ | |
| | λ¨κ³ | delta λ΄μ© | μ€λͺ | | |
| |---|---|---| | |
| | 1. μ΄κΈ°ν | `{"role":"assistant","content":""}` | μ°κ²° μ립 | | |
| | 2. LM μ½ν μΈ | `{"content":"\n\n## Metadata\n..."}` | LM μ¬μ© μ metadataμ lyrics μ μ‘ | | |
| | 3. ννΈλΉνΈ | `{"content":"."}` | μ€λμ€ μμ± μ€ 2μ΄λ§λ€ μ μ‘, μ°κ²° μ μ§ | | |
| | 4. μ€λμ€ λ°μ΄ν° | `{"audio":[{"type":"audio_url","audio_url":{"url":"data:..."}}]}` | μ€λμ€ base64 λ°μ΄ν° | | |
| | 5. μλ£ | `finish_reason: "stop"` | μμ± μλ£ | | |
| | 6. μ’ λ£ | `data: [DONE]` | μ€νΈλ¦Ό μ’ λ£ λ§μ»€ | | |
| ### μ€νΈλ¦¬λ° μλ΅ μμ | |
| ``` | |
| data: {"id":"chatcmpl-abc123","object":"chat.completion.chunk","created":1706688000,"model":"acemusic/acestep-v15-turbo","choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null}]} | |
| data: {"id":"chatcmpl-abc123","object":"chat.completion.chunk","created":1706688000,"model":"acemusic/acestep-v15-turbo","choices":[{"index":0,"delta":{"content":"\n\n## Metadata\n**Caption:** Upbeat pop\n**BPM:** 120"},"finish_reason":null}]} | |
| data: {"id":"chatcmpl-abc123","object":"chat.completion.chunk","created":1706688000,"model":"acemusic/acestep-v15-turbo","choices":[{"index":0,"delta":{"content":"."},"finish_reason":null}]} | |
| data: {"id":"chatcmpl-abc123","object":"chat.completion.chunk","created":1706688000,"model":"acemusic/acestep-v15-turbo","choices":[{"index":0,"delta":{"audio":[{"type":"audio_url","audio_url":{"url":"data:audio/mpeg;base64,..."}}]},"finish_reason":null}]} | |
| data: {"id":"chatcmpl-abc123","object":"chat.completion.chunk","created":1706688000,"model":"acemusic/acestep-v15-turbo","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]} | |
| data: [DONE] | |
| ``` | |
| ### ν΄λΌμ΄μΈνΈ μΈ‘ μ€νΈλ¦¬λ° μ²λ¦¬ | |
| ```python | |
| import json | |
| import httpx | |
| with httpx.stream("POST", "http://127.0.0.1:8002/v1/chat/completions", json={ | |
| "messages": [{"role": "user", "content": "κ²½μΎν κΈ°ν 곑μ μμ±ν΄μ€"}], | |
| "sample_mode": True, | |
| "stream": True, | |
| "audio_config": {"instrumental": True} | |
| }) as response: | |
| content_parts = [] | |
| audio_url = None | |
| for line in response.iter_lines(): | |
| if not line or not line.startswith("data: "): | |
| continue | |
| if line == "data: [DONE]": | |
| break | |
| chunk = json.loads(line[6:]) | |
| delta = chunk["choices"][0]["delta"] | |
| if "content" in delta and delta["content"]: | |
| content_parts.append(delta["content"]) | |
| if "audio" in delta and delta["audio"]: | |
| audio_url = delta["audio"][0]["audio_url"]["url"] | |
| if chunk["choices"][0].get("finish_reason") == "stop": | |
| print("μμ± μλ£!") | |
| print("Content:", "".join(content_parts)) | |
| if audio_url: | |
| import base64 | |
| b64_data = audio_url.split(",", 1)[1] | |
| with open("output.mp3", "wb") as f: | |
| f.write(base64.b64decode(b64_data)) | |
| ``` | |
| ```javascript | |
| const response = await fetch("http://127.0.0.1:8002/v1/chat/completions", { | |
| method: "POST", | |
| headers: { "Content-Type": "application/json" }, | |
| body: JSON.stringify({ | |
| messages: [{ role: "user", content: "κ²½μΎν κΈ°ν 곑μ μμ±ν΄μ€" }], | |
| sample_mode: true, | |
| stream: true, | |
| audio_config: { instrumental: true } | |
| }) | |
| }); | |
| const reader = response.body.getReader(); | |
| const decoder = new TextDecoder(); | |
| let audioUrl = null; | |
| let content = ""; | |
| while (true) { | |
| const { done, value } = await reader.read(); | |
| if (done) break; | |
| const text = decoder.decode(value); | |
| for (const line of text.split("\n")) { | |
| if (!line.startsWith("data: ") || line === "data: [DONE]") continue; | |
| const chunk = JSON.parse(line.slice(6)); | |
| const delta = chunk.choices[0].delta; | |
| if (delta.content) content += delta.content; | |
| if (delta.audio) audioUrl = delta.audio[0].audio_url.url; | |
| } | |
| } | |
| // audioUrlμ <audio src="...">μ μ§μ μ¬μ© κ°λ₯ | |
| ``` | |
| --- | |
| ## μμ | |
| ### μμ 1: μμ°μ΄ μμ± (κ°μ₯ κ°λ¨ν μ¬μ©λ²) | |
| ```bash | |
| curl -X POST http://127.0.0.1:8002/v1/chat/completions \ | |
| -H "Content-Type: application/json" \ | |
| -d '{ | |
| "messages": [ | |
| {"role": "user", "content": "κ³ ν₯κ³Ό μΆμ΅μ κ΄ν λΆλλ¬μ΄ ν¬ν¬ μ‘"} | |
| ], | |
| "sample_mode": true, | |
| "audio_config": {"vocal_language": "ko"} | |
| }' | |
| ``` | |
| ### μμ 2: νκ·Έ λͺ¨λ + νλΌλ―Έν° μ§μ | |
| ```bash | |
| curl -X POST http://127.0.0.1:8002/v1/chat/completions \ | |
| -H "Content-Type: application/json" \ | |
| -d '{ | |
| "messages": [ | |
| { | |
| "role": "user", | |
| "content": "<prompt>Energetic EDM track with heavy bass drops and synth leads</prompt><lyrics>[Verse 1]\nFeel the rhythm in your soul\nLet the music take control\n\n[Drop]\n(instrumental break)</lyrics>" | |
| } | |
| ], | |
| "audio_config": { | |
| "bpm": 128, | |
| "duration": 60, | |
| "vocal_language": "en" | |
| } | |
| }' | |
| ``` | |
| ### μμ 3: μ°μ£Όκ³‘ + LM κ°μ λΉνμ±ν | |
| ```bash | |
| curl -X POST http://127.0.0.1:8002/v1/chat/completions \ | |
| -H "Content-Type: application/json" \ | |
| -d '{ | |
| "messages": [ | |
| { | |
| "role": "user", | |
| "content": "<prompt>Peaceful piano solo, slow tempo, jazz harmony</prompt>" | |
| } | |
| ], | |
| "use_cot_caption": false, | |
| "audio_config": { | |
| "instrumental": true, | |
| "duration": 45 | |
| } | |
| }' | |
| ``` | |
| ### μμ 4: μ€νΈλ¦¬λ° μμ² | |
| ```bash | |
| curl -X POST http://127.0.0.1:8002/v1/chat/completions \ | |
| -H "Content-Type: application/json" \ | |
| -N \ | |
| -d '{ | |
| "messages": [ | |
| {"role": "user", "content": "μμΌ μΆν λ Έλλ₯Ό λ§λ€μ΄μ€"} | |
| ], | |
| "sample_mode": true, | |
| "stream": true | |
| }' | |
| ``` | |
| ### μμ 5: λ©ν° μλ λ°°μΉ μμ± | |
| ```bash | |
| curl -X POST http://127.0.0.1:8002/v1/chat/completions \ | |
| -H "Content-Type: application/json" \ | |
| -d '{ | |
| "messages": [ | |
| {"role": "user", "content": "<prompt>Lo-fi hip hop beat</prompt>"} | |
| ], | |
| "batch_size": 3, | |
| "seed": "42,123,456", | |
| "audio_config": { | |
| "instrumental": true, | |
| "duration": 30 | |
| } | |
| }' | |
| ``` | |
| --- | |
| ## μλ¬ μ½λ | |
| | HTTP μν μ½λ | μ€λͺ | | |
| |---|---| | |
| | 400 | μλͺ»λ μμ² νμ λλ μ ν¨ν μ λ ₯ λλ½ | | |
| | 401 | API ν€ λλ½ λλ μ ν¨νμ§ μμ | | |
| | 429 | μλΉμ€ κ³ΌλΆν, ν κ°λ μ°Έ | | |
| | 500 | μμ μμ± μ€ λ΄λΆ μ€λ₯ λ°μ | | |
| | 503 | λͺ¨λΈμ΄ μμ§ μ΄κΈ°νλμ§ μμ | | |
| | 504 | μμ± νμμμ | | |
| μλ¬ μλ΅ νμ: | |
| ```json | |
| { | |
| "detail": "μλ¬ μ€λͺ λ©μμ§" | |
| } | |
| ``` | |
| --- | |
| ## μλ² μ€μ (νκ²½ λ³μ) | |
| λ€μ νκ²½ λ³μλ‘ μλ²λ₯Ό μ€μ ν μ μμ΅λλ€ (μ΄μ μ°Έκ³ μ©): | |
| | λ³μλͺ | κΈ°λ³Έκ° | μ€λͺ | | |
| |---|---|---| | |
| | `OPENROUTER_API_KEY` | μμ | API μΈμ¦ ν€ | | |
| | `OPENROUTER_HOST` | `127.0.0.1` | λ¦¬μ¨ μ£Όμ | | |
| | `OPENROUTER_PORT` | `8002` | λ¦¬μ¨ ν¬νΈ | | |
| | `ACESTEP_CONFIG_PATH` | `acestep-v15-turbo` | DiT λͺ¨λΈ μ€μ κ²½λ‘ | | |
| | `ACESTEP_DEVICE` | `auto` | μΆλ‘ λλ°μ΄μ€ | | |
| | `ACESTEP_LM_MODEL_PATH` | `acestep-5Hz-lm-0.6B` | LLM λͺ¨λΈ κ²½λ‘ | | |
| | `ACESTEP_LM_BACKEND` | `vllm` | LLM μΆλ‘ λ°±μλ | | |
| | `ACESTEP_QUEUE_MAXSIZE` | `200` | μμ ν μ΅λ μ©λ | | |
| | `ACESTEP_GENERATION_TIMEOUT` | `600` | λΉμ€νΈλ¦¬λ° μμ² νμμμ(μ΄) | | |