diff --git a/docs/API.md b/docs/API.md index ed09631..e1f8c0c 100644 --- a/docs/API.md +++ b/docs/API.md @@ -800,26 +800,54 @@ Authorization: Bearer *** 请求成功后自动创建 `llmusage` 记录,状态为 `created`。后台定时任务会定期执行计费流程。 -# 视频制作 API (KTV产线) +# KTV Pipeline API(视频制作) Base url: `https://token.opencomputing.cn/llmage/v1` -供应商: 开元云(北京)科技, 28端点覆盖KTV全流程。 +供应商: 开元云(北京)科技, 14个原子化GPU端点覆盖KTV全流程。 + +## 调用方式 + +所有模型通过 `POST /v1/pipeline/submit` 调用,`catelogid` 固定为 `ktv_pipeline`(无需传参)。 + +### 通用格式 + +```json +// 请求 +{"model": "ky-xxx", ...服务特定参数...} + +// 同步响应 +{"taskid": "luid_xxx", "taskstatus": "SUCCEEDED", "usage": {...}} + +// 异步提交响应 +{"taskid": "luid_xxx", "taskstatus": "PENDING"} +// 异步结果通过 GET /v1/tasks?taskid=xxx 查询 +``` ## 模型列表 -| model | 功能 | 计费 | -|-------|------|------| -| `ktv-media-server` | 流水线/状态/合并/校准/字幕 | 2元/次+0.03元/秒 | -| `ktv-video-eval` | 视频质量评估 | 0.05元/秒 | -| `ktv-realesrgan` | 超分辨率 | 0.5元/张 | -| `ktv-asr` | 语音识别 | 0.01元/秒 | -| `ktv-face` | 人脸检测/识别/比对 | 0.1元/次 | -| `ktv-graph` | 图谱查询/写入 | 0.05~0.1元/次 | -| `ktv-ner` | 实体识别 | 0.5元/千字 | -| `ktv-songrate` | 歌曲评分 | 0.005元/秒 | -| `ktv-synth` | 音乐合成 | 0.2元/秒 | -| `ktv-demucs` | 音频分离 | 0.02元/秒 | -| `ktv-rvc` | 声音转换 | 0.15元/秒 | +| model | 功能 | 模式 | 计费 | +|-------|------|------|------| +| `ky-asr-transcribe` | 语音转文字+时间戳 | 同步 | 0.01元/次 | +| `ky-demucs-separate` | 人声/伴奏分离 | 同步 | 0.01元/次 | +| `ky-face-detect` | 人脸检测 | 同步 | 0.01元/次 | +| `ky-face-recognize` | 人脸识别 | 同步 | 0.01元/次 | +| `ky-face-compare` | 人脸比对 | 同步 | 0.01元/次 | +| `ky-subtitle-render` | 歌词→ASS字幕渲染 | 同步 | 0.01元/次 | +| `ky-merge-video` | 视频+音频+字幕合并 | 同步 | 0.01元/次 | +| `ky-songrate-evaluate` | AI歌曲质量评分 | 同步 | 0.01元/次 | +| `ky-synth-generate` | AI歌声合成 | **异步** | 0.01元/次 | +| `ky-synth-status` | 合成任务状态查询 | 同步 | 0.01元/次 | +| `ky-realesrgan-upscale` | 图像/视频超分辨率 | **异步** | 0.01元/次 | +| `ky-realesrgan-status` | 超分任务状态查询 | 同步 | 0.01元/次 | +| `ky-rvc-convert` | 声音克隆/变声 | 同步 | 0.01元/次 | +| `ky-video-eval-evaluate` | 视频质量评估 | 同步 | 0.01元/次 | -调用方式: `/v1/chat/completions` + `model` 参数。详细参数见 dashboard_for_sage 文档。 +## 模型发现 + +```bash +curl 'https://token.opencomputing.cn/llmage/v1/models?catelogid=ktv_pipeline' \ + -H 'Authorization: Bearer ***' +``` + +详细参数说明和 curl 示例见 [dashboard_for_sage 文档](https://token.opencomputing.cn/dashboard_for_sage/api_doc.md)。 diff --git a/wwwroot/v1/pipeline/submit/index.dspy b/wwwroot/v1/pipeline/submit/index.dspy new file mode 100644 index 0000000..a339d2c --- /dev/null +++ b/wwwroot/v1/pipeline/submit/index.dspy @@ -0,0 +1,74 @@ +# KTV Pipeline / GPU Service Inference API +# POST /v1/pipeline/submit +# catelogid 固定为 ktv_pipeline,无需传 catelogid +# +# Required params: +# model: string - 模型名称,如 "ky-asr-transcribe" +# +# 各服务特定参数见 API 文档 +# +# 同步服务直接返回结果: +# { +# "taskid": "luid_xxx", +# "taskstatus": "SUCCEEDED", +# ...服务特定结果字段..., +# "usage": {...} +# } +# +# 异步服务返回任务信息: +# { +# "taskid": "luid_xxx", +# "taskstatus": "PENDING" +# } +# 异步结果通过 /v1/tasks?taskid=xxx 查询 + +debug_params('params_kw', params_kw) + +userid = await get_user() +userorgid = await get_userorgid() +if userid is None: + debug('need login') + return openai_403() + +# Validate required parameters +if not params_kw.model: + d = return_error('Missing required parameter: model') + return json_response(d, status=400) + +catelogid = 'ktv_pipeline' +params_kw.catelogid = catelogid + +env = request._run_ns +async with get_sor_context(env, 'llmage') as sor: + # Look up llm by model name through llm_api_map (fixed catelogid=ktv_pipeline) + sql = """select distinct a.* from llm a +join llm_api_map m on a.id = m.llmid +join llmcatelog b on m.llmcatelogid = b.id +where (b.id = ${catelogid}$ OR b.name = ${catelogid}$) + and a.name=${model}$ + and a.status = 'published'""" + recs = await sor.sqlExe(sql, { + 'catelogid': catelogid, + 'model': params_kw.model + }) + if len(recs) == 0: + debug(f'{params_kw.model=} not found under ktv_pipeline catalog') + d = return_error(f'Model "{params_kw.model}" not found or not available') + return json_response(d, status=400) + params_kw.llmid = recs[0].id + params_kw.llmcatelogid = catelogid + +debug(f'{params_kw.llmid=}') + +# Check balance +f = await checkCustomerBalance(params_kw.llmid, userid, userorgid) +if not f: + debug(f'{userid=} balance not enough') + return openai_429() + +# Generate task ID +if not params_kw.transno: + params_kw.transno = getID() + +# Call inference +return await inference(request, env=env)