- handlers_ktv.py: 17 async step handlers for KTV production - Audio/Video preparation (ffmpeg) - Demucs vocal separation (GPU server SSH) - Lyric calibration (SenseVoice ASR + LLM) - Subtitle rendering (ASS karaoke format) - Lyric generation & evaluation (Mode C) - Music generation (Suno/MiniMax API) - Character design & image generation (wan2.7) - Storyboard generation (LLM) - Scene video generation (T2V/Ref2V) - Scene video evaluation (quality threshold) - Scene video concatenation (ffmpeg loop) - KTV synthesis (dual-track + MTV) - llm_bridge.py: async LLM call bridge (harnessed_agent / OpenAI API) - storage.py: extract deps from step_config JSON - init.py: auto-register KTV handlers on load
63 lines
2.0 KiB
Python
63 lines
2.0 KiB
Python
"""LLM bridge for pipeline handlers.
|
|
|
|
Provides a simple async interface for handlers to call LLM APIs.
|
|
Uses harnessed_agent's llm_chat under the hood when available,
|
|
falls back to direct HTTP calls.
|
|
"""
|
|
|
|
import json
|
|
import logging
|
|
import os
|
|
|
|
logger = logging.getLogger("pipeline.llm_bridge")
|
|
|
|
|
|
async def llm_call(prompt: str, model: str = None, temperature: float = 0.7) -> str:
|
|
"""Call LLM and return text response.
|
|
|
|
Tries multiple backends:
|
|
1. harnessed_agent.llm_chat (if loaded in ServerEnv)
|
|
2. Direct OpenAI-compatible API call
|
|
"""
|
|
# Try harnessed_agent first
|
|
try:
|
|
from ahserver.serverenv import ServerEnv
|
|
env = ServerEnv()
|
|
if hasattr(env, 'llm_chat'):
|
|
result = await env.llm_chat(prompt, model=model, temperature=temperature)
|
|
if isinstance(result, dict):
|
|
return result.get("content", result.get("text", str(result)))
|
|
return str(result)
|
|
except Exception:
|
|
pass
|
|
|
|
# Fallback: direct HTTP call to OpenAI-compatible endpoint
|
|
import aiohttp
|
|
|
|
api_base = os.environ.get("LLM_API_BASE", "https://api.openai.com/v1")
|
|
api_key = os.environ.get("LLM_API_KEY", "")
|
|
model = model or os.environ.get("LLM_MODEL", "gpt-4o-mini")
|
|
|
|
if not api_key:
|
|
raise ValueError("No LLM API configured (set LLM_API_KEY env var)")
|
|
|
|
headers = {
|
|
"Authorization": f"Bearer {api_key}",
|
|
"Content-Type": "application/json",
|
|
}
|
|
payload = {
|
|
"model": model,
|
|
"messages": [{"role": "user", "content": prompt}],
|
|
"temperature": temperature,
|
|
}
|
|
|
|
async with aiohttp.ClientSession() as session:
|
|
async with session.post(
|
|
f"{api_base}/chat/completions", headers=headers, json=payload, timeout=aiohttp.ClientTimeout(total=120)
|
|
) as resp:
|
|
if resp.status != 200:
|
|
text = await resp.text()
|
|
raise ValueError(f"LLM API error {resp.status}: {text[:200]}")
|
|
data = await resp.json()
|
|
return data["choices"][0]["message"]["content"]
|