sage/scripts/ktv_uapi_migration.sql

459 lines
19 KiB
SQL
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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|