From cf2e2f699cf5f4e8ec722cb6b288599a958c7e53 Mon Sep 17 00:00:00 2001 From: yumoqing Date: Mon, 6 Jul 2026 11:42:44 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20KTV=E6=9C=8D=E5=8A=A1uapi=E8=A1=A5?= =?UTF-8?q?=E5=85=A8=20=E2=80=94=2014=E4=B8=AAGPU=E7=AB=AF=E7=82=B9=20stre?= =?UTF-8?q?am/data/response/ioid=20=E8=A1=A5=E5=85=A8=20+=20uapiio?= =?UTF-8?q?=E5=AE=9A=E4=B9=89=20+=20RBAC=E6=9D=83=E9=99=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/ktv_uapi_migration.sql | 458 +++++++++++++++++++++++ scripts/ktv_uapi_migration_p1_uapiio.sql | 93 +++++ scripts/ktv_uapi_migration_p2_uapi.sql | 316 ++++++++++++++++ scripts/ktv_uapi_migration_p3_rbac.sql | 38 ++ 4 files changed, 905 insertions(+) create mode 100644 scripts/ktv_uapi_migration.sql create mode 100644 scripts/ktv_uapi_migration_p1_uapiio.sql create mode 100644 scripts/ktv_uapi_migration_p2_uapi.sql create mode 100644 scripts/ktv_uapi_migration_p3_rbac.sql diff --git a/scripts/ktv_uapi_migration.sql b/scripts/ktv_uapi_migration.sql new file mode 100644 index 00000000..54963eb2 --- /dev/null +++ b/scripts/ktv_uapi_migration.sql @@ -0,0 +1,458 @@ +1|-- ============================================================ +2|-- KTV服务 uapi/uapiio 补全迁移脚本 +3|-- 为14个GPU服务端点补全 stream/data/response/ioid 字段 +4|-- 执行环境: Sage生产数据库 +5|-- ============================================================ +6| +7|-- ============================================================ +8|-- 1. uapiio 输入字段定义 +9|-- ============================================================ +10| +11|-- ASR语音识别 +12|INSERT INTO uapiio (id, name, description, input_fields) VALUES ( +13| 'ktv_asr_transcribe_io', 'KTV语音识别', '上传音频文件,返回识别文本和时间戳', +14| '{"audio_url":{"type":"string","required":true,"description":"音频文件URL"},"language":{"type":"string","required":false,"default":"zh","description":"语言代码"}}' +15|) ON DUPLICATE KEY UPDATE description=VALUES(description), input_fields=VALUES(input_fields); +16| +17|-- Demucs音频分离 +18|INSERT INTO uapiio (id, name, description, input_fields) VALUES ( +19| 'ktv_demucs_separate_io', 'KTV音频分离', '分离人声和伴奏', +20| '{"audio_url":{"type":"string","required":true,"description":"音频文件URL"}}' +21|) ON DUPLICATE KEY UPDATE description=VALUES(description), input_fields=VALUES(input_fields); +22| +23|-- 人脸检测 +24|INSERT INTO uapiio (id, name, description, input_fields) VALUES ( +25| 'ktv_face_detect_io', 'KTV人脸检测', '检测图像中的人脸位置', +26| '{"image_url":{"type":"string","required":true,"description":"图像URL"}}' +27|) ON DUPLICATE KEY UPDATE description=VALUES(description), input_fields=VALUES(input_fields); +28| +29|-- 人脸识别 +30|INSERT INTO uapiio (id, name, description, input_fields) VALUES ( +31| 'ktv_face_recognize_io', 'KTV人脸识别', '识别人脸身份', +32| '{"image_url":{"type":"string","required":true,"description":"图像URL"},"face_id":{"type":"string","required":false,"description":"人脸ID"}}' +33|) ON DUPLICATE KEY UPDATE description=VALUES(description), input_fields=VALUES(input_fields); +34| +35|-- 人脸比对 +36|INSERT INTO uapiio (id, name, description, input_fields) VALUES ( +37| 'ktv_face_compare_io', 'KTV人脸比对', '比较两张人脸的相似度', +38| '{"image_url1":{"type":"string","required":true,"description":"图像1 URL"},"image_url2":{"type":"string","required":true,"description":"图像2 URL"}}' +39|) ON DUPLICATE KEY UPDATE description=VALUES(description), input_fields=VALUES(input_fields); +40| +41|-- 字幕渲染 +42|INSERT INTO uapiio (id, name, description, input_fields) VALUES ( +43| 'ktv_subtitle_render_io', 'KTV字幕渲染', '将歌词时间轴渲染为ASS字幕文件', +44| '{"lyrics_json":{"type":"string","required":true,"description":"歌词时间轴JSON [{\"text\":\"...\",\"start\":0,\"end\":3},...]"},"width":{"type":"integer","required":false,"default":1920,"description":"视频宽度"},"height":{"type":"integer","required":false,"default":1080,"description":"视频高度"}}' +45|) ON DUPLICATE KEY UPDATE description=VALUES(description), input_fields=VALUES(input_fields); +46| +47|-- 视频合并 +48|INSERT INTO uapiio (id, name, description, input_fields) VALUES ( +49| 'ktv_merge_video_io', 'KTV视频合并', '合并视频、音频和字幕', +50| '{"video_url":{"type":"string","required":false,"description":"视频URL"},"audio_url":{"type":"string","required":false,"description":"音频URL"},"subtitle_url":{"type":"string","required":false,"description":"字幕ASS文件URL"},"output_format":{"type":"string","required":false,"default":"mp4","description":"输出格式"}}' +51|) ON DUPLICATE KEY UPDATE description=VALUES(description), input_fields=VALUES(input_fields); +52| +53|-- 歌曲评分 +54|INSERT INTO uapiio (id, name, description, input_fields) VALUES ( +55| 'ktv_songrate_evaluate_io', 'KTV歌曲评分', 'AI评估歌曲质量', +56| '{"audio_url":{"type":"string","required":true,"description":"音频文件URL"},"scene":{"type":"string","required":false,"default":"pop","description":"场景类型(pop/folk/rock等)"}}' +57|) ON DUPLICATE KEY UPDATE description=VALUES(description), input_fields=VALUES(input_fields); +58| +59|-- 音乐合成(异步提交) +60|INSERT INTO uapiio (id, name, description, input_fields) VALUES ( +61| 'ktv_synth_generate_io', 'KTV音乐合成', 'AI歌声合成(异步任务)', +62| '{"lyrics":{"type":"string","required":true,"description":"歌词文本"},"style":{"type":"string","required":false,"default":"pop","description":"演唱风格"},"reference_audio":{"type":"string","required":false,"description":"参考音频URL(声音克隆)"}}' +63|) ON DUPLICATE KEY UPDATE description=VALUES(description), input_fields=VALUES(input_fields); +64| +65|-- 合成状态查询 +66|INSERT INTO uapiio (id, name, description, input_fields) VALUES ( +67| 'ktv_synth_status_io', 'KTV合成状态', '查询音乐合成任务状态', +68| '{"task_id":{"type":"string","required":true,"description":"任务ID"}}' +69|) ON DUPLICATE KEY UPDATE description=VALUES(description), input_fields=VALUES(input_fields); +70| +71|-- 超分辨率(异步提交) +72|INSERT INTO uapiio (id, name, description, input_fields) VALUES ( +73| 'ktv_realesrgan_upscale_io', 'KTV超分辨率', '图像/视频超分辨率(异步任务)', +74| '{"image_url":{"type":"string","required":true,"description":"图像URL"},"scale":{"type":"integer","required":false,"default":2,"description":"放大倍数"}}' +75|) ON DUPLICATE KEY UPDATE description=VALUES(description), input_fields=VALUES(input_fields); +76| +77|-- 超分状态查询 +78|INSERT INTO uapiio (id, name, description, input_fields) VALUES ( +79| 'ktv_realesrgan_status_io', 'KTV超分状态', '查询超分任务状态', +80| '{"task_id":{"type":"string","required":true,"description":"任务ID"}}' +81|) ON DUPLICATE KEY UPDATE description=VALUES(description), input_fields=VALUES(input_fields); +82| +83|-- RVC声音转换(异步) +84|INSERT INTO uapiio (id, name, description, input_fields) VALUES ( +85| 'ktv_rvc_convert_io', 'KTV声音转换', '声音克隆/变声(异步任务)', +86| '{"audio_url":{"type":"string","required":true,"description":"输入音频URL"},"voice_model":{"type":"string","required":true,"description":"目标声音模型名"}}' +87|) ON DUPLICATE KEY UPDATE description=VALUES(description), input_fields=VALUES(input_fields); +88| +89|-- 视频评估 +90|INSERT INTO uapiio (id, name, description, input_fields) VALUES ( +91| 'ktv_video_eval_evaluate_io', 'KTV视频评估', '评估视频质量', +92| '{"video_url":{"type":"string","required":true,"description":"视频URL"}}' +93|) ON DUPLICATE KEY UPDATE description=VALUES(description), input_fields=VALUES(input_fields); +94| + +-- ============================================================ +-- Part 2: uapi 字段补全 + async 模型 query_apiname 更新 +-- ============================================================ +1|-- ============================================================ +2|-- KTV服务 uapi 补全迁移脚本 Part 2 +3|-- 更新14条uapi记录:stream/data/response/ioid/headers +4|-- ============================================================ +5| +6|-- ============================================================ +7|-- 1. ASR语音识别 (sync) +8|-- GPU: /asr/api/asr-transcribe → localhost:9925 +9|-- uapiio: ktv_asr_transcribe_io +10|-- ============================================================ +11|UPDATE uapi SET +12| stream = 'sync', +13| headers = '{"Content-Type": "application/json"}', +14| data = '{ +15| "audio_url": "{{audio_url}}" +16|{% if language %} +17| ,"language": "{{language}}" +18|{% endif %} +19|}', +20| response = '{ +21| "status": "{{status}}", +22| "text": "{{text}}", +23| "segments": {{json.dumps(segments, ensure_ascii=False)}}, +24| "usage": {"audio_seconds": {{audio_seconds|float}}} +25|}', +26| ioid = 'ktv_asr_transcribe_io' +27|WHERE id = 'uapi_ktv_asr_transcribe'; +28| +29|-- ============================================================ +30|-- 2. Demucs音频分离 (sync) +31|-- GPU: /demucs/api/demucs-separate → localhost:9083 +32|-- ============================================================ +33|UPDATE uapi SET +34| stream = 'sync', +35| headers = '{"Content-Type": "application/json"}', +36| data = '{ +37| "audio_url": "{{audio_url}}" +38|}', +39| response = '{ +40| "status": "{{status}}", +41| "vocals_url": "{{vocals_url}}", +42| "accompaniment_url": "{{accompaniment_url}}", +43| "usage": {"audio_seconds": {{audio_seconds|float}}} +44|}', +45| ioid = 'ktv_demucs_separate_io' +46|WHERE id = 'uapi_ktv_demucs_separate'; +47| +48|-- ============================================================ +49|-- 3. 人脸检测 (sync) +50|-- GPU: /face/api/face-detect → localhost:9091 +51|-- ============================================================ +52|UPDATE uapi SET +53| stream = 'sync', +54| headers = '{"Content-Type": "application/json"}', +55| data = '{ +56| "image_url": "{{image_url}}" +57|}', +58| response = '{ +59| "status": "{{status}}", +60| "faces": {{json.dumps(faces, ensure_ascii=False)}}, +61| "usage": {"detect_count": {{faces|length}}} +62|}', +63| ioid = 'ktv_face_detect_io' +64|WHERE id = 'uapi_ktv_face_detect'; +65| +66|-- ============================================================ +67|-- 4. 人脸识别 (sync) +68|-- ============================================================ +69|UPDATE uapi SET +70| stream = 'sync', +71| headers = '{"Content-Type": "application/json"}', +72| data = '{ +73| "image_url": "{{image_url}}" +74|{% if face_id %} +75| ,"face_id": "{{face_id}}" +76|{% endif %} +77|}', +78| response = '{ +79| "status": "{{status}}", +80| "matches": {{json.dumps(matches, ensure_ascii=False)}}, +81| "usage": {"recognize_count": {{matches|length}}} +82|}', +83| ioid = 'ktv_face_recognize_io' +84|WHERE id = 'uapi_ktv_face_recognize'; +85| +86|-- ============================================================ +87|-- 5. 人脸比对 (sync) +88|-- ============================================================ +89|UPDATE uapi SET +90| stream = 'sync', +91| headers = '{"Content-Type": "application/json"}', +92| data = '{ +93| "image_url1": "{{image_url1}}", +94| "image_url2": "{{image_url2}}" +95|}', +96| response = '{ +97| "status": "{{status}}", +98| "similarity": {{similarity|float}}, +99| "usage": {"compare_count": 1} +100|}', +101| ioid = 'ktv_face_compare_io' +102|WHERE id = 'uapi_ktv_face_compare'; +103| +104|-- ============================================================ +105|-- 6. 字幕渲染 (sync) +106|-- GPU: /subtitle/api/subtitle-render → localhost:9080 +107|-- ============================================================ +108|UPDATE uapi SET +109| stream = 'sync', +110| headers = '{"Content-Type": "application/json"}', +111| data = '{ +112| "lyrics_json": {{lyrics_json}} +113|{% if width %} +114| ,"width": {{width}} +115|{% endif %} +116|{% if height %} +117| ,"height": {{height}} +118|{% endif %} +119|}', +120| response = '{ +121| "status": "{{status}}", +122| "ass_url": "{{ass_url}}", +123| "usage": {"subtitle_count": {{segments|length}}} +124|}', +125| ioid = 'ktv_subtitle_render_io' +126|WHERE id = 'uapi_ktv_subtitle_render'; +127| +128|-- ============================================================ +129|-- 7. 视频合并 (sync) +130|-- GPU: /merge/api/merge-video → localhost:9080 +131|-- ============================================================ +132|UPDATE uapi SET +133| stream = 'sync', +134| headers = '{"Content-Type": "application/json"}', +135| data = '{ +136|{% if video_url %} +137| "video_url": "{{video_url}}" +138|{% endif %} +139|{% if audio_url %} +140| ,"audio_url": "{{audio_url}}" +141|{% endif %} +142|{% if subtitle_url %} +143| ,"subtitle_url": "{{subtitle_url}}" +144|{% endif %} +145|{% if output_format %} +146| ,"output_format": "{{output_format}}" +147|{% endif %} +148|}', +149| response = '{ +150| "status": "{{status}}", +151| "output_url": "{{output_url}}", +152| "duration": {{duration|float}}, +153| "usage": {"output_seconds": {{duration|float}}} +154|}', +155| ioid = 'ktv_merge_video_io' +156|WHERE id = 'uapi_ktv_merge_video'; +157| +158|-- ============================================================ +159|-- 8. 歌曲评分 (sync) +160|-- GPU: /songrate/api/songrate-evaluate → localhost:8901 +161|-- ============================================================ +162|UPDATE uapi SET +163| stream = 'sync', +164| headers = '{"Content-Type": "application/json"}', +165| data = '{ +166| "audio_url": "{{audio_url}}" +167|{% if scene %} +168| ,"scene": "{{scene}}" +169|{% endif %} +170|}', +171| response = '{ +172| "status": "{{status}}", +173| "score": {{score|float}}, +174| "details": {{json.dumps(details, ensure_ascii=False)}}, +175| "usage": {"audio_seconds": {{audio_seconds|float}}} +176|}', +177| ioid = 'ktv_songrate_evaluate_io' +178|WHERE id = 'uapi_ktv_songrate_evaluate'; +179| +180|-- ============================================================ +181|-- 9. 音乐合成 (async - 提交任务) +182|-- GPU: /synth/api/synth-generate → localhost:9084 +183|-- ============================================================ +184|UPDATE uapi SET +185| stream = 'async', +186| headers = '{"Content-Type": "application/json"}', +187| data = '{ +188| "lyrics": "{{lyrics}}" +189|{% if style %} +190| ,"style": "{{style}}" +191|{% endif %} +192|{% if reference_audio %} +193| ,"reference_audio": "{{reference_audio}}" +194|{% endif %} +195|}', +196| response = '{ +197| "taskid": "{{task_id}}", +198| "taskstatus": "PENDING" +199|}', +200| ioid = 'ktv_synth_generate_io' +201|WHERE id = 'uapi_ktv_synth_generate'; +202| +203|-- ============================================================ +204|-- 10. 合成状态查询 (sync) +205|-- GPU: /synth/api/synth-status → localhost:9084 +206|-- ============================================================ +207|UPDATE uapi SET +208| stream = 'sync', +209| headers = '{"Content-Type": "application/json"}', +210| data = '{"task_id": "{{task_id}}"}', +211| response = '{ +212|{% if status == "SUCCEEDED" %} +213| "taskstatus": "SUCCEEDED", +214| "output_url": "{{output_url}}", +215| "usage": {"audio_seconds": {{duration|float}}} +216|{% elif status == "FAILED" %} +217| "taskstatus": "FAILED", +218| "error": "{{error}}" +219|{% else %} +220| "taskstatus": "PENDING" +221|{% endif %} +222|}', +223| ioid = 'ktv_synth_status_io' +224|WHERE id = 'uapi_ktv_synth_status'; +225| +226|-- ============================================================ +227|-- 11. 超分辨率 (async - 提交任务) +228|-- GPU: /realesrgan/api/realesrgan-upscale → localhost:9082 +229|-- ============================================================ +230|UPDATE uapi SET +231| stream = 'async', +232| headers = '{"Content-Type": "application/json"}', +233| data = '{ +234| "image_url": "{{image_url}}" +235|{% if scale %} +236| ,"scale": {{scale}} +237|{% endif %} +238|}', +239| response = '{ +240| "taskid": "{{task_id}}", +241| "taskstatus": "PENDING" +242|}', +243| ioid = 'ktv_realesrgan_upscale_io' +244|WHERE id = 'uapi_ktv_realesrgan_upscale'; +245| +246|-- ============================================================ +247|-- 12. 超分状态查询 (sync) +248|-- GPU: /realesrgan/api/realesrgan-status → localhost:9082 +249|-- ============================================================ +250|UPDATE uapi SET +251| stream = 'sync', +252| headers = '{"Content-Type": "application/json"}', +253| data = '{"task_id": "{{task_id}}"}', +254| response = '{ +255|{% if status == "SUCCEEDED" %} +256| "taskstatus": "SUCCEEDED", +257| "output_url": "{{output_url}}", +258| "usage": {"image_count": 1} +259|{% elif status == "FAILED" %} +260| "taskstatus": "FAILED", +261| "error": "{{error}}" +262|{% else %} +263| "taskstatus": "PENDING" +264|{% endif %} +265|}', +266| ioid = 'ktv_realesrgan_status_io' +267|WHERE id = 'uapi_ktv_realesrgan_status'; +268| +269|-- ============================================================ +270|-- 13. RVC声音转换 (sync) +271|-- GPU: /rvc/api/rvc-convert → localhost:9085 +272|-- ============================================================ +273|UPDATE uapi SET +274| stream = 'sync', +275| headers = '{"Content-Type": "application/json"}', +276| data = '{ +277| "audio_url": "{{audio_url}}", +278| "voice_model": "{{voice_model}}" +279|}', +280| response = '{ +281| "status": "{{status}}", +282| "output_url": "{{output_url}}", +283| "usage": {"audio_seconds": {{audio_seconds|float}}} +284|}', +285| ioid = 'ktv_rvc_convert_io' +286|WHERE id = 'uapi_ktv_rvc_convert'; +287| +288|-- ============================================================ +289|-- 14. 视频评估 (sync) +290|-- GPU: /video-eval/api/video-eval-evaluate → localhost:8902 +291|-- ============================================================ +292|UPDATE uapi SET +293| stream = 'sync', +294| headers = '{"Content-Type": "application/json"}', +295| data = '{ +296| "video_url": "{{video_url}}" +297|}', +298| response = '{ +299| "status": "{{status}}", +300| "score": {{score|float}}, +301| "details": {{json.dumps(details, ensure_ascii=False)}}, +302| "usage": {"video_seconds": {{video_seconds|float}}} +303|}', +304| ioid = 'ktv_video_eval_evaluate_io' +305|WHERE id = 'uapi_ktv_video_eval_evaluate'; +306| +307|-- ============================================================ +308|-- 关键:更新 llm_api_map 中的 async 模型的 query_apiname +309|-- synth-generate 查询 synth-status +310|-- realesrgan-upscale 查询 realesrgan-status +311|-- ============================================================ +312|UPDATE llm_api_map SET query_apiname = 'synth-status', query_period = 5 +313|WHERE llmid = 'llm_ktv_synth_generate' AND llmcatelogid = 'ktv_pipeline'; +314| +315|UPDATE llm_api_map SET query_apiname = 'realesrgan-status', query_period = 3 +316|WHERE llmid = 'llm_ktv_realesrgan_upscale' AND llmcatelogid = 'ktv_pipeline'; +317| + +-- ============================================================ +-- Part 3: RBAC 权限 +-- ============================================================ +1|-- ============================================================ +2|-- KTV Pipeline v1 API RBAC 权限配置 +3|-- 新增 /v1/pipeline/submit 端点权限 +4|-- ============================================================ +5| +6|-- 权限路径(供 load_path.py 或不直接支持的模块参考) +7|-- 目录级 +8|-- /llmage/v1/pipeline logined +9|-- /llmage/v1/pipeline/submit logined +10|-- 文件级 +11|-- /llmage/v1/pipeline/submit/index.dspy logined +12| +13|-- ============================================================ +14|-- Customer 角色权限(API调用者需要) +15|-- ============================================================ +16|INSERT INTO permission (id, path, name) +17|SELECT REPLACE(UUID(), '-', ''), '/llmage/v1/pipeline/submit/index.dspy', 'KTV流水线提交' +18|WHERE NOT EXISTS ( +19| SELECT 1 FROM permission WHERE path = '/llmage/v1/pipeline/submit/index.dspy' +20|); +21| +22|-- 为 customer.admin 和 customer.user 角色授予权限 +23|-- 注意:以下语句依赖 set_role_perm.py 或等效的角色-权限关联表 +24|-- 如果用的是直接 role_permission 表: +25|INSERT IGNORE INTO role_permission (role_id, permission_id) +26|SELECT r.id, p.id +27|FROM role r, permission p +28|WHERE r.name IN ('customer.admin', 'customer.user') +29|AND p.path = '/llmage/v1/pipeline/submit/index.dspy'; +30| +31|-- ============================================================ +32|-- 管理角色权限 +33|-- ============================================================ +34|INSERT IGNORE INTO role_permission (role_id, permission_id) +35|SELECT r.id, p.id +36|FROM role r, permission p +37|WHERE r.name IN ('owner.superuser', 'owner.admin', 'reseller.admin', 'reseller.operator') +38|AND p.path = '/llmage/v1/pipeline/submit/index.dspy'; +39| diff --git a/scripts/ktv_uapi_migration_p1_uapiio.sql b/scripts/ktv_uapi_migration_p1_uapiio.sql new file mode 100644 index 00000000..e32aa3b1 --- /dev/null +++ b/scripts/ktv_uapi_migration_p1_uapiio.sql @@ -0,0 +1,93 @@ +-- ============================================================ +-- KTV服务 uapi/uapiio 补全迁移脚本 +-- 为14个GPU服务端点补全 stream/data/response/ioid 字段 +-- 执行环境: Sage生产数据库 +-- ============================================================ + +-- ============================================================ +-- 1. uapiio 输入字段定义 +-- ============================================================ + +-- ASR语音识别 +INSERT INTO uapiio (id, name, description, input_fields) VALUES ( + 'ktv_asr_transcribe_io', 'KTV语音识别', '上传音频文件,返回识别文本和时间戳', + '{"audio_url":{"type":"string","required":true,"description":"音频文件URL"},"language":{"type":"string","required":false,"default":"zh","description":"语言代码"}}' +) ON DUPLICATE KEY UPDATE description=VALUES(description), input_fields=VALUES(input_fields); + +-- Demucs音频分离 +INSERT INTO uapiio (id, name, description, input_fields) VALUES ( + 'ktv_demucs_separate_io', 'KTV音频分离', '分离人声和伴奏', + '{"audio_url":{"type":"string","required":true,"description":"音频文件URL"}}' +) ON DUPLICATE KEY UPDATE description=VALUES(description), input_fields=VALUES(input_fields); + +-- 人脸检测 +INSERT INTO uapiio (id, name, description, input_fields) VALUES ( + 'ktv_face_detect_io', 'KTV人脸检测', '检测图像中的人脸位置', + '{"image_url":{"type":"string","required":true,"description":"图像URL"}}' +) ON DUPLICATE KEY UPDATE description=VALUES(description), input_fields=VALUES(input_fields); + +-- 人脸识别 +INSERT INTO uapiio (id, name, description, input_fields) VALUES ( + 'ktv_face_recognize_io', 'KTV人脸识别', '识别人脸身份', + '{"image_url":{"type":"string","required":true,"description":"图像URL"},"face_id":{"type":"string","required":false,"description":"人脸ID"}}' +) ON DUPLICATE KEY UPDATE description=VALUES(description), input_fields=VALUES(input_fields); + +-- 人脸比对 +INSERT INTO uapiio (id, name, description, input_fields) VALUES ( + 'ktv_face_compare_io', 'KTV人脸比对', '比较两张人脸的相似度', + '{"image_url1":{"type":"string","required":true,"description":"图像1 URL"},"image_url2":{"type":"string","required":true,"description":"图像2 URL"}}' +) ON DUPLICATE KEY UPDATE description=VALUES(description), input_fields=VALUES(input_fields); + +-- 字幕渲染 +INSERT INTO uapiio (id, name, description, input_fields) VALUES ( + 'ktv_subtitle_render_io', 'KTV字幕渲染', '将歌词时间轴渲染为ASS字幕文件', + '{"lyrics_json":{"type":"string","required":true,"description":"歌词时间轴JSON [{\"text\":\"...\",\"start\":0,\"end\":3},...]"},"width":{"type":"integer","required":false,"default":1920,"description":"视频宽度"},"height":{"type":"integer","required":false,"default":1080,"description":"视频高度"}}' +) ON DUPLICATE KEY UPDATE description=VALUES(description), input_fields=VALUES(input_fields); + +-- 视频合并 +INSERT INTO uapiio (id, name, description, input_fields) VALUES ( + 'ktv_merge_video_io', 'KTV视频合并', '合并视频、音频和字幕', + '{"video_url":{"type":"string","required":false,"description":"视频URL"},"audio_url":{"type":"string","required":false,"description":"音频URL"},"subtitle_url":{"type":"string","required":false,"description":"字幕ASS文件URL"},"output_format":{"type":"string","required":false,"default":"mp4","description":"输出格式"}}' +) ON DUPLICATE KEY UPDATE description=VALUES(description), input_fields=VALUES(input_fields); + +-- 歌曲评分 +INSERT INTO uapiio (id, name, description, input_fields) VALUES ( + 'ktv_songrate_evaluate_io', 'KTV歌曲评分', 'AI评估歌曲质量', + '{"audio_url":{"type":"string","required":true,"description":"音频文件URL"},"scene":{"type":"string","required":false,"default":"pop","description":"场景类型(pop/folk/rock等)"}}' +) ON DUPLICATE KEY UPDATE description=VALUES(description), input_fields=VALUES(input_fields); + +-- 音乐合成(异步提交) +INSERT INTO uapiio (id, name, description, input_fields) VALUES ( + 'ktv_synth_generate_io', 'KTV音乐合成', 'AI歌声合成(异步任务)', + '{"lyrics":{"type":"string","required":true,"description":"歌词文本"},"style":{"type":"string","required":false,"default":"pop","description":"演唱风格"},"reference_audio":{"type":"string","required":false,"description":"参考音频URL(声音克隆)"}}' +) ON DUPLICATE KEY UPDATE description=VALUES(description), input_fields=VALUES(input_fields); + +-- 合成状态查询 +INSERT INTO uapiio (id, name, description, input_fields) VALUES ( + 'ktv_synth_status_io', 'KTV合成状态', '查询音乐合成任务状态', + '{"task_id":{"type":"string","required":true,"description":"任务ID"}}' +) ON DUPLICATE KEY UPDATE description=VALUES(description), input_fields=VALUES(input_fields); + +-- 超分辨率(异步提交) +INSERT INTO uapiio (id, name, description, input_fields) VALUES ( + 'ktv_realesrgan_upscale_io', 'KTV超分辨率', '图像/视频超分辨率(异步任务)', + '{"image_url":{"type":"string","required":true,"description":"图像URL"},"scale":{"type":"integer","required":false,"default":2,"description":"放大倍数"}}' +) ON DUPLICATE KEY UPDATE description=VALUES(description), input_fields=VALUES(input_fields); + +-- 超分状态查询 +INSERT INTO uapiio (id, name, description, input_fields) VALUES ( + 'ktv_realesrgan_status_io', 'KTV超分状态', '查询超分任务状态', + '{"task_id":{"type":"string","required":true,"description":"任务ID"}}' +) ON DUPLICATE KEY UPDATE description=VALUES(description), input_fields=VALUES(input_fields); + +-- RVC声音转换(异步) +INSERT INTO uapiio (id, name, description, input_fields) VALUES ( + 'ktv_rvc_convert_io', 'KTV声音转换', '声音克隆/变声(异步任务)', + '{"audio_url":{"type":"string","required":true,"description":"输入音频URL"},"voice_model":{"type":"string","required":true,"description":"目标声音模型名"}}' +) ON DUPLICATE KEY UPDATE description=VALUES(description), input_fields=VALUES(input_fields); + +-- 视频评估 +INSERT INTO uapiio (id, name, description, input_fields) VALUES ( + 'ktv_video_eval_evaluate_io', 'KTV视频评估', '评估视频质量', + '{"video_url":{"type":"string","required":true,"description":"视频URL"}}' +) ON DUPLICATE KEY UPDATE description=VALUES(description), input_fields=VALUES(input_fields); diff --git a/scripts/ktv_uapi_migration_p2_uapi.sql b/scripts/ktv_uapi_migration_p2_uapi.sql new file mode 100644 index 00000000..15971fea --- /dev/null +++ b/scripts/ktv_uapi_migration_p2_uapi.sql @@ -0,0 +1,316 @@ +-- ============================================================ +-- KTV服务 uapi 补全迁移脚本 Part 2 +-- 更新14条uapi记录:stream/data/response/ioid/headers +-- ============================================================ + +-- ============================================================ +-- 1. ASR语音识别 (sync) +-- GPU: /asr/api/asr-transcribe → localhost:9925 +-- uapiio: ktv_asr_transcribe_io +-- ============================================================ +UPDATE uapi SET + stream = 'sync', + headers = '{"Content-Type": "application/json"}', + data = '{ + "audio_url": "{{audio_url}}" +{% if language %} + ,"language": "{{language}}" +{% endif %} +}', + response = '{ + "status": "{{status}}", + "text": "{{text}}", + "segments": {{json.dumps(segments, ensure_ascii=False)}}, + "usage": {"audio_seconds": {{audio_seconds|float}}} +}', + ioid = 'ktv_asr_transcribe_io' +WHERE id = 'uapi_ktv_asr_transcribe'; + +-- ============================================================ +-- 2. Demucs音频分离 (sync) +-- GPU: /demucs/api/demucs-separate → localhost:9083 +-- ============================================================ +UPDATE uapi SET + stream = 'sync', + headers = '{"Content-Type": "application/json"}', + data = '{ + "audio_url": "{{audio_url}}" +}', + response = '{ + "status": "{{status}}", + "vocals_url": "{{vocals_url}}", + "accompaniment_url": "{{accompaniment_url}}", + "usage": {"audio_seconds": {{audio_seconds|float}}} +}', + ioid = 'ktv_demucs_separate_io' +WHERE id = 'uapi_ktv_demucs_separate'; + +-- ============================================================ +-- 3. 人脸检测 (sync) +-- GPU: /face/api/face-detect → localhost:9091 +-- ============================================================ +UPDATE uapi SET + stream = 'sync', + headers = '{"Content-Type": "application/json"}', + data = '{ + "image_url": "{{image_url}}" +}', + response = '{ + "status": "{{status}}", + "faces": {{json.dumps(faces, ensure_ascii=False)}}, + "usage": {"detect_count": {{faces|length}}} +}', + ioid = 'ktv_face_detect_io' +WHERE id = 'uapi_ktv_face_detect'; + +-- ============================================================ +-- 4. 人脸识别 (sync) +-- ============================================================ +UPDATE uapi SET + stream = 'sync', + headers = '{"Content-Type": "application/json"}', + data = '{ + "image_url": "{{image_url}}" +{% if face_id %} + ,"face_id": "{{face_id}}" +{% endif %} +}', + response = '{ + "status": "{{status}}", + "matches": {{json.dumps(matches, ensure_ascii=False)}}, + "usage": {"recognize_count": {{matches|length}}} +}', + ioid = 'ktv_face_recognize_io' +WHERE id = 'uapi_ktv_face_recognize'; + +-- ============================================================ +-- 5. 人脸比对 (sync) +-- ============================================================ +UPDATE uapi SET + stream = 'sync', + headers = '{"Content-Type": "application/json"}', + data = '{ + "image_url1": "{{image_url1}}", + "image_url2": "{{image_url2}}" +}', + response = '{ + "status": "{{status}}", + "similarity": {{similarity|float}}, + "usage": {"compare_count": 1} +}', + ioid = 'ktv_face_compare_io' +WHERE id = 'uapi_ktv_face_compare'; + +-- ============================================================ +-- 6. 字幕渲染 (sync) +-- GPU: /subtitle/api/subtitle-render → localhost:9080 +-- ============================================================ +UPDATE uapi SET + stream = 'sync', + headers = '{"Content-Type": "application/json"}', + data = '{ + "lyrics_json": {{lyrics_json}} +{% if width %} + ,"width": {{width}} +{% endif %} +{% if height %} + ,"height": {{height}} +{% endif %} +}', + response = '{ + "status": "{{status}}", + "ass_url": "{{ass_url}}", + "usage": {"subtitle_count": {{segments|length}}} +}', + ioid = 'ktv_subtitle_render_io' +WHERE id = 'uapi_ktv_subtitle_render'; + +-- ============================================================ +-- 7. 视频合并 (sync) +-- GPU: /merge/api/merge-video → localhost:9080 +-- ============================================================ +UPDATE uapi SET + stream = 'sync', + headers = '{"Content-Type": "application/json"}', + data = '{ +{% if video_url %} + "video_url": "{{video_url}}" +{% endif %} +{% if audio_url %} + ,"audio_url": "{{audio_url}}" +{% endif %} +{% if subtitle_url %} + ,"subtitle_url": "{{subtitle_url}}" +{% endif %} +{% if output_format %} + ,"output_format": "{{output_format}}" +{% endif %} +}', + response = '{ + "status": "{{status}}", + "output_url": "{{output_url}}", + "duration": {{duration|float}}, + "usage": {"output_seconds": {{duration|float}}} +}', + ioid = 'ktv_merge_video_io' +WHERE id = 'uapi_ktv_merge_video'; + +-- ============================================================ +-- 8. 歌曲评分 (sync) +-- GPU: /songrate/api/songrate-evaluate → localhost:8901 +-- ============================================================ +UPDATE uapi SET + stream = 'sync', + headers = '{"Content-Type": "application/json"}', + data = '{ + "audio_url": "{{audio_url}}" +{% if scene %} + ,"scene": "{{scene}}" +{% endif %} +}', + response = '{ + "status": "{{status}}", + "score": {{score|float}}, + "details": {{json.dumps(details, ensure_ascii=False)}}, + "usage": {"audio_seconds": {{audio_seconds|float}}} +}', + ioid = 'ktv_songrate_evaluate_io' +WHERE id = 'uapi_ktv_songrate_evaluate'; + +-- ============================================================ +-- 9. 音乐合成 (async - 提交任务) +-- GPU: /synth/api/synth-generate → localhost:9084 +-- ============================================================ +UPDATE uapi SET + stream = 'async', + headers = '{"Content-Type": "application/json"}', + data = '{ + "lyrics": "{{lyrics}}" +{% if style %} + ,"style": "{{style}}" +{% endif %} +{% if reference_audio %} + ,"reference_audio": "{{reference_audio}}" +{% endif %} +}', + response = '{ + "taskid": "{{task_id}}", + "taskstatus": "PENDING" +}', + ioid = 'ktv_synth_generate_io' +WHERE id = 'uapi_ktv_synth_generate'; + +-- ============================================================ +-- 10. 合成状态查询 (sync) +-- GPU: /synth/api/synth-status → localhost:9084 +-- ============================================================ +UPDATE uapi SET + stream = 'sync', + headers = '{"Content-Type": "application/json"}', + data = '{"task_id": "{{task_id}}"}', + response = '{ +{% if status == "SUCCEEDED" %} + "taskstatus": "SUCCEEDED", + "output_url": "{{output_url}}", + "usage": {"audio_seconds": {{duration|float}}} +{% elif status == "FAILED" %} + "taskstatus": "FAILED", + "error": "{{error}}" +{% else %} + "taskstatus": "PENDING" +{% endif %} +}', + ioid = 'ktv_synth_status_io' +WHERE id = 'uapi_ktv_synth_status'; + +-- ============================================================ +-- 11. 超分辨率 (async - 提交任务) +-- GPU: /realesrgan/api/realesrgan-upscale → localhost:9082 +-- ============================================================ +UPDATE uapi SET + stream = 'async', + headers = '{"Content-Type": "application/json"}', + data = '{ + "image_url": "{{image_url}}" +{% if scale %} + ,"scale": {{scale}} +{% endif %} +}', + response = '{ + "taskid": "{{task_id}}", + "taskstatus": "PENDING" +}', + ioid = 'ktv_realesrgan_upscale_io' +WHERE id = 'uapi_ktv_realesrgan_upscale'; + +-- ============================================================ +-- 12. 超分状态查询 (sync) +-- GPU: /realesrgan/api/realesrgan-status → localhost:9082 +-- ============================================================ +UPDATE uapi SET + stream = 'sync', + headers = '{"Content-Type": "application/json"}', + data = '{"task_id": "{{task_id}}"}', + response = '{ +{% if status == "SUCCEEDED" %} + "taskstatus": "SUCCEEDED", + "output_url": "{{output_url}}", + "usage": {"image_count": 1} +{% elif status == "FAILED" %} + "taskstatus": "FAILED", + "error": "{{error}}" +{% else %} + "taskstatus": "PENDING" +{% endif %} +}', + ioid = 'ktv_realesrgan_status_io' +WHERE id = 'uapi_ktv_realesrgan_status'; + +-- ============================================================ +-- 13. RVC声音转换 (sync) +-- GPU: /rvc/api/rvc-convert → localhost:9085 +-- ============================================================ +UPDATE uapi SET + stream = 'sync', + headers = '{"Content-Type": "application/json"}', + data = '{ + "audio_url": "{{audio_url}}", + "voice_model": "{{voice_model}}" +}', + response = '{ + "status": "{{status}}", + "output_url": "{{output_url}}", + "usage": {"audio_seconds": {{audio_seconds|float}}} +}', + ioid = 'ktv_rvc_convert_io' +WHERE id = 'uapi_ktv_rvc_convert'; + +-- ============================================================ +-- 14. 视频评估 (sync) +-- GPU: /video-eval/api/video-eval-evaluate → localhost:8902 +-- ============================================================ +UPDATE uapi SET + stream = 'sync', + headers = '{"Content-Type": "application/json"}', + data = '{ + "video_url": "{{video_url}}" +}', + response = '{ + "status": "{{status}}", + "score": {{score|float}}, + "details": {{json.dumps(details, ensure_ascii=False)}}, + "usage": {"video_seconds": {{video_seconds|float}}} +}', + ioid = 'ktv_video_eval_evaluate_io' +WHERE id = 'uapi_ktv_video_eval_evaluate'; + +-- ============================================================ +-- 关键:更新 llm_api_map 中的 async 模型的 query_apiname +-- synth-generate 查询 synth-status +-- realesrgan-upscale 查询 realesrgan-status +-- ============================================================ +UPDATE llm_api_map SET query_apiname = 'synth-status', query_period = 5 +WHERE llmid = 'llm_ktv_synth_generate' AND llmcatelogid = 'ktv_pipeline'; + +UPDATE llm_api_map SET query_apiname = 'realesrgan-status', query_period = 3 +WHERE llmid = 'llm_ktv_realesrgan_upscale' AND llmcatelogid = 'ktv_pipeline'; diff --git a/scripts/ktv_uapi_migration_p3_rbac.sql b/scripts/ktv_uapi_migration_p3_rbac.sql new file mode 100644 index 00000000..e909a14c --- /dev/null +++ b/scripts/ktv_uapi_migration_p3_rbac.sql @@ -0,0 +1,38 @@ +-- ============================================================ +-- KTV Pipeline v1 API RBAC 权限配置 +-- 新增 /v1/pipeline/submit 端点权限 +-- ============================================================ + +-- 权限路径(供 load_path.py 或不直接支持的模块参考) +-- 目录级 +-- /llmage/v1/pipeline logined +-- /llmage/v1/pipeline/submit logined +-- 文件级 +-- /llmage/v1/pipeline/submit/index.dspy logined + +-- ============================================================ +-- Customer 角色权限(API调用者需要) +-- ============================================================ +INSERT INTO permission (id, path, name) +SELECT REPLACE(UUID(), '-', ''), '/llmage/v1/pipeline/submit/index.dspy', 'KTV流水线提交' +WHERE NOT EXISTS ( + SELECT 1 FROM permission WHERE path = '/llmage/v1/pipeline/submit/index.dspy' +); + +-- 为 customer.admin 和 customer.user 角色授予权限 +-- 注意:以下语句依赖 set_role_perm.py 或等效的角色-权限关联表 +-- 如果用的是直接 role_permission 表: +INSERT IGNORE INTO role_permission (role_id, permission_id) +SELECT r.id, p.id +FROM role r, permission p +WHERE r.name IN ('customer.admin', 'customer.user') +AND p.path = '/llmage/v1/pipeline/submit/index.dspy'; + +-- ============================================================ +-- 管理角色权限 +-- ============================================================ +INSERT IGNORE INTO role_permission (role_id, permission_id) +SELECT r.id, p.id +FROM role r, permission p +WHERE r.name IN ('owner.superuser', 'owner.admin', 'reseller.admin', 'reseller.operator') +AND p.path = '/llmage/v1/pipeline/submit/index.dspy';