diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..4da53783 --- /dev/null +++ b/.gitignore @@ -0,0 +1,38 @@ +# Generated i18n files — run merge_i18n.py to regenerate +wwwroot/i18n/zh/ +wwwroot/i18n/en/ +wwwroot/i18n/jp/ +wwwroot/i18n/ko/ + +py3/ +app/__pycache__/ +logs/ +*.pyc +__pycache__/ +conf/config.json +sage.pid +sage_backend.pid +start.sh +stop.sh +wwwroot/bricks +wwwroot/bugfix +wwwroot/pricing +wwwroot/supplychain + +# Module wwwroot symlinks (managed by build.sh, not tracked in git) +wwwroot/accounting +wwwroot/appbase +wwwroot/charge +wwwroot/cpcc +wwwroot/dapi +wwwroot/dashboard_for_sage +wwwroot/discount +wwwroot/filemgr +wwwroot/llmage +wwwroot/msp +wwwroot/platformbiz +wwwroot/product_management +wwwroot/rag +wwwroot/rbac +wwwroot/uapi +wwwroot/unipay diff --git a/alipay_priv.pem b/alipay_priv.pem new file mode 100644 index 00000000..5ceb3417 --- /dev/null +++ b/alipay_priv.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCJHRwndZ5KgGu2 +I5Q3/SkcDrdq59UOeWy5F0rz0GVujfz2/pWNqNcym+IDyrUoxFiYcYbqsu3IKeBU +PXIy4WIhjP++qnd+tKQvOUltxtC21Wpxh60HwFxqUnecC/szgSQEHGJOnHwAH0xX +tBf0MbtlOWxefeHYrVIb3nK9FYRzK0b7g/n35QZ8TYlKVLUhoBakqFQfTmQQFwoT +hu/1WiTwt+E8Gkixd83bMVl4Y6YXbyslIXcuG3WA43FnylgkutvbbkO8NpoZzwIr +Px8wD3wgxUqpuqbfOjXeHvPyInUzGKtuRxYNmW+b1+0ERKTSNsMm50T+Jehq6gK2 +qGT1k5ydAgMBAAECggEABkxPrRb/qge+FYQK3IuEu4+IKKFKLbuxcnW5xqXtktIe +KtuaKQNMEedhJAVypChosrqRlO7vxyr37UapRoxdwpFvHztF+Tb497ECSMhCHAkv +i37M7uHiHNbO5wcR3IAeabtCtL5cCnFlmKhiv/UXg4MgvDJnZlmHv6n3IUJUxClz +3Cxnbt3C66Vbl1ES9vtu9obbMm3W3oFGH+7zJItVQyWa4uYBnAyOICTncT5tMR9k +gWuXITrt/cB9+PAJa7NZsPORPxHygV4bbo+7OH6sBLh1c+Rcm3oSNyejkzRaKFO2 +tWUcsyFvIUd/h61BMG123mBWT4XgPo0pTCBkfPohDQKBgQC4fNRz6DSjT3OgF9+7 +fLhU+58ED+UtMWKBbKx+PZZfaumxWf8ZbKeLanrnxkCWIr7aVyVl567gq5I5lvN3 +jSIDM9A/hgJqFJ8wJ0sW8Q2Fv+loLxANgf8XboSpcy8uADPO7r83D/UhuseHy42L +vQ0ex8WoH0V39PeqBHqcjbZMAwKBgQC+Qz+PFLfcWfvoLQr2aGhe4AQmFSmM5szb +xntkEcD0Dj/34kHOdbKfTThOwo+X8gf3nPcA2WWz3ytQPhZQueNHsR6qcJwzI9WU +yULwnS9Ukdu6bHO74D+1ehM2jZVc2s2V58b2hr5yNz3Z/tlv9txttESBhyCi4bcO +zLzhxeUi3wKBgQCN0sDMHc0hYnnDr7a5/eYCxrB2wfVvKZDNaAquvY+06I6gXUwD +cojWX1P+i2SpRiqr1OSWE2ZXpu2xQf8Gf8OO7K0BuHZwsEu0C/DowQShNmgrREq1 +56J/k+F+FmNFnLg3M0hh/u12MY0kMnIs43eLmw2y8d9ImVQvKmRLp5FlmwKBgEiD +tOvBh7nSCfKZiD4V2QGf+7TQCAANzzJMWabwJUxfSf4eG9qmfSe99KIAAV51/pdf +Gb0XHm4JtqZko3itAHTIitmHBeFv3O1SL9Mo9WsUFFzfDNUkSOPP3RbDq5OySPzD +U8+N13QMneRB/3lu6uBc/mcnq0apJG3dlneuRwCdAoGAYZsNbg84qE5o9Jy9dZG8 +mTSoS7H/hFZR0XFx3ur6YIBVQ5Ajr//jJinItxMuqV/TEeMdMBJ9DrN+osgPahmq +KNzovtG8spGMbssXY6yMQtM0RPeI+/16TZiWcScnkYQ7QfkwWBRbvQgjUhE6E5Sn +v+Sp46nTaBhBn6iKNVJrhhE= +-----END PRIVATE KEY----- diff --git a/alipay_pub.pem b/alipay_pub.pem new file mode 100644 index 00000000..395bbd59 --- /dev/null +++ b/alipay_pub.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCmBNz4GpYlwpIy +7uhXTYpCy125vcGltsMjDr7xNehDSkwrQZYOfHoCALE8o1hTEeAXaZN/wls6AEUT +o4i2KB+g3EXDNtm298zydpaWyh8HDhLkzsPeVxT2t2BE6vsusa5/IeQWmnjfU4Un +erSee+EHkrimzAkCLezynOeR69hobkZzhFfPvDm3ur79wJcttRmwbeF0fM6Nvsx2 +CY5f1g9ZQb5UY0tfsN7qNFR/Hm6f5Du4nIAt7CwVUheCrjvvh8dByNJBpmSJfqOI +BipzbBDWTQm0s8+d29noUU/rMRAwBfAToG73nCpJoiFLlvw+DCjR4y/FtE5wgHXm +a1wCl1MdAgMBAAECggEAHfpe1EYouqTJtXzCY5FS2ADU6cdEAmJgFiKBhBjR2eS+ +oEj1iaQce+QYHPT56/YcWt3rjnRP+Mc3sfYjp5DTNT7RMhDje1B/p4CWbKAOvj1i +WAKmB6390RcHwSoVNTdMZRR/lT1LejggoSJdHwkLd0ydHzFUpxoX4S9H+Wd26lRE +UiMDZuytWdJaW+xDdHTLrgO7m2bgp7qA1QAekEodsMDSorPgw8sNx7o5v0ZruYZi +SXKx6V1zhjFtTcWjCQgV51+4h6NQdjkG5aEyrrdV1hl7uqJMFRHt5EkczD9y/m7g +jdmufhD0TLYbubSop3tBy68S9c6Hat6LTEFJsnwogQKBgQDoi6sGQPI/+tUbNFFH +n0XqbYhOZKD8J3sTW3Qtmo0rAZgtHVtzpgSs2+X836Qit5RghQA+GPX4lwbBoG3h +MjOjxET6YEk15pnzeiqQrPhxJgNSc05DigQTjQg7OgtP8AELvQc63kuJ97A3Ivol +KMEmqWI0VVybCrsDgXssaCAb8QKBgQC2w3owPrQT0ORWgmFDVwyquPrpkVdBk+1w +sE29hban9/3ykmVDgYS0Iyji0VvcBmD+SxUGavyVzKuRbxo4anOdjZMTH8yLaCZ4 +RWiCMpIoM9QrB89my++X14V0n+wucvHromTYYdbewku5ReUV0Ivr/HDquCx+4vtD +3fAv3i3F7QKBgQCYPJdCCNKOwA8zOBTd5o9G4V4StB4P9WjFS2HLWRqBxRFyt31f +QJhe8bamzWIOuFASv/9gp8afb3+k0vocK1lTJPJjVxWWi9jNZHTpMdOTf2c9Wu8p +l/kDM5jn7R/qvRxyKtXI3C5nrBdYgTVxjjSkss7vo9J0TZoQuXuBnskmgQKBgFa0 +J9yJcr7P4/OSiPf8bRr1BLwX4nBO8F78lPTrYXsQMF6KyxWadU1MPNJWBiE8uXkK +P6A60zdx0Jb/QU4wWkcNag+xj0U3lMCMFQdnXGVMKUR8wQ0AhNrhOQPZ9p8WkuR5 +tyPcTqaBQJFVsleGB0teCGeiFiHgJtnMiWz8F3UFAoGAQCHHLm5UY0KR71eSiF/Z +RjcfuEy1KIi8IN2QGRWoonghWdtZiGhx/PeieaOVLs9XMR1uX+mLG1G9lKSVNdxs +S+y7engCTTS4JbkWN5Hv+LoXKv0y8As9e3ddk+OEO5iiW1ZyTyhrFCek2Xl8dSbq +aWHluS2LQFVNlDX5I1lTeuI= +-----END PRIVATE KEY----- diff --git a/app/global_func.py b/app/global_func.py index 80b5d024..9ebfd7df 100644 --- a/app/global_func.py +++ b/app/global_func.py @@ -1,6 +1,5 @@ from ahserver.serverenv import ServerEnv from sqlor.dbpools import DBPools -from alisms import AliSMS def PopError(title='Error', message='Error happened'): return { @@ -49,9 +48,7 @@ async def get_llminstances_by_modeltype(mtid): def set_globalvariable(): - sms_engine = sms = AliSMS('LTAI5t5w7xsZgueod6uZ3TCD', 'n1HttSbQvgEbjvf62Gzl1aagfKyIyS') g = ServerEnv() - g.sms_engine = sms_engine g.PopError = PopError g.PopMessage = PopMessage g.get_llm_types = get_llm_types diff --git a/app/sage.py b/app/sage.py index 64778df8..2502f138 100644 --- a/app/sage.py +++ b/app/sage.py @@ -1,6 +1,5 @@ import os, sys import json -import asyncio import argparse from appPublic.log import MyLogger, info, debug, warning from appPublic.folderUtils import ProgramPath @@ -21,47 +20,23 @@ from dapi.init import load_dapi from rag.init import load_rag from msp.init import load_msp from checklang.init import load_checklang -from skillagent.init import load_skillagent -from dagflow.init import load_dagflow +# from dashboard_for_sage.init import load_dashboard_for_sage +from reallife_asset.init import load_reallife_asset from discount.init import load_discount - from global_func import set_globalvariable from unipay.init import load_unipay -from platformbiz.init import load_platformbiz +from product_management.init import load_product_management +from supplychain.init import load_supplychain from accounting.init import load_accounting -from woa.init import load_woa +from bugfix.init import load_bugfix +from discount.init import load_discount +from tenant.init import load_tenant from smssend import load_smssend +from sage_datamart import load_sage_datamart from ext import * from rf import * __version__ = '0.0.1' -async def run_zmq_proxy(app): - task = asyncio.create_task(run_proxy()) - app['zmq_proxy_task'] = task - task1 = asyncio.create_task(woa_msghande()) - yield - task1.cancel() - task.cancel() - -async def msg_handler(msgstr): - debug(f'get message:{msgstr}') - msg = DictObject(**json.loads(msgstr)) - ret = { - "msgtype": "text", # 要返回的消息类型 - "content": "收到" # 每个类型的消息所需要的数据 - } - retstr = json.dumps(ret, ensure_ascii=False) - await zmq_publish(msg.subscribe_id, retstr) - -async def woa_msghande(): - config = getConfig() - debug(f'woa_msghander on({config.woa_handler_id}) starting ....') - try: - await zmq_subscribe(config.woa_handler_id, msg_handler) - except Exception as e: - debug(f'Exception:{e}') - debug('woa_msghandler stopped.................') - def init(): rf = RegisterFunction() set_globalvariable() @@ -70,22 +45,25 @@ def init(): load_rbac() load_accounting() load_unipay() - load_platformbiz() - load_llmage() + load_product_management() + load_supplychain() load_filemgr() + load_llmage() load_uapi() load_dapi() load_msp() load_rag() load_pricing() load_checklang() - load_skillagent() - load_dagflow() + # load_harnessed_agent() + # load_harnessed_reasoning() load_discount() - load_woa() + load_tenant() load_smssend() - add_cleanupctx(run_zmq_proxy) + # load_dashboard_for_sage() + load_reallife_asset() + load_bugfix() + load_sage_datamart() if __name__ == '__main__': webapp(init) - diff --git a/backup/config.sh b/backup/config.sh new file mode 100644 index 00000000..aa4377c3 --- /dev/null +++ b/backup/config.sh @@ -0,0 +1,27 @@ +#!/bin/bash +# Sage 冷备配置 — 修改 STANDBY_IP 后即可使用 +# 生成时间: 2026-07-04 + +# ===== 主机(当前生产) ===== +PRIMARY_IP="192.168.16.2" +PRIMARY_DB_PORT=3306 +PRIMARY_SAGE_DIR="/d/ymq/repos/sage" +PRIMARY_FILES_DIR="${PRIMARY_SAGE_DIR}/files" + +# ===== 备机(必填!) ===== +STANDBY_IP="" # <-- 改成你的备机 IP +STANDBY_SSH_USER="root" +STANDBY_SSH_PORT=22 +STANDBY_SAGE_DIR="/d/ymq/repos/sage" +STANDBY_FILES_DIR="${STANDBY_SAGE_DIR}/files" + +# ===== 数据库复制账号 ===== +REPL_USER="repl" +REPL_PASSWORD="Repl...n +# ===== lsyncd ===== +LSYNCD_CONF="/etc/lsyncd/lsyncd.conf.lua" +LSYNCD_LOG="/var/log/lsyncd.log" + +# ===== 健康检查 ===== +HEALTH_CHECK_INTERVAL=10 +MAX_FAIL_COUNT=3 diff --git a/bin/backend_accounting.py b/bin/backend_accounting.py new file mode 100644 index 00000000..972d6ad2 --- /dev/null +++ b/bin/backend_accounting.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python +""" +独立运行的产品后台计费程序。 +产品记账已从 llmage 迁移到 product_management 模块。 +""" +import os +import sys +import asyncio +import signal + +from appPublic.folderUtils import ProgramPath +from appPublic.jsonConfig import getConfig +from sqlor.dbpools import DBPools +from ahserver.serverenv import ServerEnv +from ahserver.globalEnv import initEnv +from appPublic.log import MyLogger, debug, exception, info +from accounting.init import load_accounting +from appbase.init import load_appbase +from llmage.init import load_llmage +from pricing.init import load_pricing +from discount.init import load_discount +from dapi.init import load_dapi +from product_management import get_manager + +def get_module_dbname(m): + return 'sage' + +def main(): + # 初始化配置 + p = ProgramPath() + config = getConfig(NS={'workdir': os.getcwd(), 'ProgramPath': p}) + db = DBPools(config.databases) + logger = MyLogger('backend_accounting', levelname='info', + logfile=os.path.join(os.getcwd(), 'logs', 'backend_accounting.log')) + info(f'Backend accounting process started (PID: {os.getpid()})') + + loop = asyncio.new_event_loop() + asyncio.set_event_loop(loop) + + def handle_signal(signum, frame): + info(f'Received signal {signum}, shutting down...') + for task in asyncio.all_tasks(loop): + task.cancel() + loop.stop() + + signal.signal(signal.SIGTERM, handle_signal) + signal.signal(signal.SIGINT, handle_signal) + initEnv() + env = ServerEnv() + env.get_module_dbname = get_module_dbname + # Mock event_dispatcher for standalone mode + class _MockDispatcher: + def bind(self, *a, **kw): pass + env.event_dispatcher = _MockDispatcher() + load_appbase() + load_accounting() + load_pricing() + load_discount() + load_dapi() + load_llmage() + + manager = get_manager() + try: + loop.run_until_complete(manager.backend_accounting()) + except asyncio.CancelledError: + pass + finally: + loop.close() + info('Backend accounting process stopped.') + +if __name__ == '__main__': + main() diff --git a/bin/backup_api.sh b/bin/backup_api.sh new file mode 100755 index 00000000..c355b38a --- /dev/null +++ b/bin/backup_api.sh @@ -0,0 +1,304 @@ +#!/bin/bash +# ============================================================ +# backup_api.sh +# 自动从 conf/config.json 读取数据库配置,扫描所有模块的 +# models 目录提取表名,导出为 SQL 文件。 +# +# 运行目录: sage.py 所在目录 (即 repos/sage/) +# +# 用法: +# cd /path/to/sage && bash bin/backup_api.sh [options] +# +# 选项: +# -p PASSWORD 直接指定密码 (覆盖config.json中的加密密码) +# -h HOST 覆盖数据库主机 +# -o OUTPUT_DIR 输出目录 (默认: ./sql_dumps) +# --no-data 只导出表结构,不导出数据 +# --help 显示帮助 +# ============================================================ + +set -euo pipefail + +# --- 定位工作目录 (sage.py 所在目录) --- +SAGE_DIR="$(cd "$(dirname "$0")/.." && pwd)" +REPOS_DIR="$(cd "$SAGE_DIR/.." && pwd)" +CONFIG_FILE="$SAGE_DIR/conf/config.json" + +if [[ ! -f "$CONFIG_FILE" ]]; then + echo "错误: 找不到配置文件 $CONFIG_FILE" + echo "请在 sage.py 所在目录下运行此脚本" + exit 1 +fi + +# 默认参数 +OUTPUT_DIR="./sql_dumps" +NO_DATA="" +PASSWORD_OVERRIDE="" +HOST_OVERRIDE="" + +usage() { + sed -n '2,/^# ===/p' "$0" | grep '^#' | sed 's/^# \?//' + exit 0 +} + +# 解析参数 +while [[ $# -gt 0 ]]; do + case "$1" in + -p) PASSWORD_OVERRIDE="$2"; shift 2 ;; + -h) HOST_OVERRIDE="$2"; shift 2 ;; + -o) OUTPUT_DIR="$2"; shift 2 ;; + --no-data) NO_DATA="--no-data"; shift ;; + --help) usage ;; + *) echo "未知参数: $1"; exit 1 ;; + esac +done + +# --- 从 config.json 提取数据库配置并解密密码 --- +read_config() { + # Use the sage venv if available, otherwise system python + local PYTHON="python3" + if [[ -x "$SAGE_DIR/py3/bin/python3" ]]; then + PYTHON="$SAGE_DIR/py3/bin/python3" + fi + + $PYTHON -c " +import re, json, sys, os + +# 读取并修复 config.json (可能有非标准 JSON) +text = open('$CONFIG_FILE').read() +# 移除无 key 的裸对象 (如 hot_reload) +text = re.sub(r',\s*\{[^{}]*\"hot_reload\"[^{}]*\{[^{}]*\}[^{}]*\}', '', text) +config = json.loads(text) + +# 获取数据库配置 (取第一个数据库) +db_name = list(config['databases'].keys())[0] +db_cfg = config['databases'][db_name]['kwargs'] +password_key = config.get('password_key', 'QRIVSRHrthhwyjy176556332') + +# 尝试 RC4 解密 +try: + from appPublic.rc4 import unpassword + decrypted = unpassword(db_cfg['password'], key=password_key) +except ImportError: + # Fallback: inline RC4 implementation + import base64 + from hashlib import sha1 + class RC4: + def __init__(self): + self.bcoding = 'iso-8859-1' + self.dcoding = 'utf8' + self.salt = b'AFUqx9WZuI32lnHk' + def _crypt(self, data, key): + x = 0; box = list(range(256)) + for i in range(256): + x = (x + box[i] + key[i % len(key)]) % 256 + box[i], box[x] = box[x], box[i] + x = y = 0; out = [] + for char in data: + x = (x + 1) % 256; y = (y + box[x]) % 256 + box[x], box[y] = box[y], box[x] + out.append(chr(char ^ box[(box[x] + box[y]) % 256])) + return ''.join(out).encode(self.bcoding) + def decode(self, data, key): + if isinstance(data, str): data = data.encode(self.dcoding) + key = key.encode(self.bcoding) + data = base64.b64decode(data) + a = sha1(key + self.salt); k = a.digest() + return self._crypt(data[16:], k).decode(self.dcoding) + rc4 = RC4() + decrypted = rc4.decode(db_cfg['password'], password_key) +except Exception as e: + decrypted = '' + +# 如果解密失败或为空,使用原始值 +if not decrypted: + decrypted = db_cfg['password'] + +host = '$HOST_OVERRIDE' if '$HOST_OVERRIDE' else db_cfg.get('host', 'localhost') +port = str(db_cfg.get('port', '3306')) +user = db_cfg.get('user', 'root') +database = db_cfg.get('db', 'sage') + +# Shell-safe output +print(f'HOST={host}') +print(f'PORT={port}') +print(f'USER={user}') +print(f'DATABASE={database}') +# Password needs quoting for special chars +print(f\"PASSWORD='{decrypted}'\") +" +} + +echo "正在读取配置..." +eval "$(read_config)" + +# 命令行密码覆盖 +if [[ -n "$PASSWORD_OVERRIDE" ]]; then + PASSWORD="$PASSWORD_OVERRIDE" +fi + +if [[ -z "$PASSWORD" ]]; then + echo "错误: 密码为空。请使用 -p 参数指定密码,或检查 config.json 中的密码配置" + exit 1 +fi + +# 构建 mysqldump 基础命令 (密码通过环境变量传递,避免命令行暴露) +export MYSQL_PWD="$PASSWORD" +MYSQLDUMP_CMD="mysqldump -h${HOST} -P${PORT} -u${USER}" + +# --- 各模块排除的表 (大数据量/日志表) --- +declare -A MODULE_EXCLUDES +MODULE_EXCLUDES["llmage"]="llmusage llmusage_accounting_failed llmusage_history" +MODULE_EXCLUDES["uapi"]="uapiset uptask" +MODULE_EXCLUDES["accounting"]="accountingdetail accountinghistory" +MODULE_EXCLUDES["harnessed_agent"]="harnessed_agent_log" +MODULE_EXCLUDES["harnessed_reasoning"]="harnessed_reasoning_log" + +# --- 从 models/*.json 提取表名 --- +get_tables() { + local module_dir="$1" + shift + local excludes=("$@") + local tables=() + + if [[ ! -d "$module_dir/models" ]]; then + return + fi + + for f in "$module_dir/models"/*.json; do + [[ -f "$f" ]] || continue + local tbl + tbl=$(python3 -c " +import json, sys +try: + d = json.load(open('$f')) + s = d.get('summary', []) + if isinstance(s, list) and len(s) > 0: + print(s[0].get('name', '')) + elif isinstance(s, dict): + print(s.get('name', '')) +except: + pass +" 2>/dev/null) + if [[ -z "$tbl" ]]; then + continue + fi + # 检查排除 + local excluded=false + for ex in "${excludes[@]+"${excludes[@]}"}"; do + if [[ "$tbl" == "$ex" ]]; then + excluded=true + break + fi + done + if [[ "$excluded" == "false" ]]; then + tables+=("$tbl") + fi + done + echo "${tables[@]}" +} + +# --- 自动发现所有模块 --- +discover_modules() { + for dir in "$REPOS_DIR"/*/; do + [[ -d "$dir/models" ]] || continue + local name + name=$(basename "$dir") + # 跳过无模型文件的模块 + if ls "$dir/models/"*.json &>/dev/null; then + echo "$name" + fi + done +} + +# --- 创建输出目录 --- +mkdir -p "$OUTPUT_DIR" + +TIMESTAMP=$(date +%Y%m%d_%H%M%S) + +echo "============================================================" +echo " Sage 全模块表数据导出" +echo " 时间: $(date '+%Y-%m-%d %H:%M:%S')" +echo " 数据库: ${DATABASE}@${HOST}:${PORT}" +echo " 用户: ${USER}" +echo " 模块目录: ${REPOS_DIR}" +echo " 输出目录: ${OUTPUT_DIR}" +echo "============================================================" + +# 发现所有模块 +MODULES=($(discover_modules)) +echo "" +echo "发现 ${#MODULES[@]} 个模块: ${MODULES[*]}" + +TOTAL_TABLES=0 +TOTAL_FILES=0 +FAILED_MODULES=() + +for module in "${MODULES[@]}"; do + module_dir="$REPOS_DIR/$module" + echo "" + echo "--- 模块: $module ---" + + # 获取排除列表 + excludes_str="${MODULE_EXCLUDES[$module]:-}" + excludes_arr=() + if [[ -n "$excludes_str" ]]; then + read -ra excludes_arr <<< "$excludes_str" + fi + + tables=$(get_tables "$module_dir" "${excludes_arr[@]+"${excludes_arr[@]}"}") + + if [[ -z "$tables" ]]; then + echo " 跳过: 未找到表定义" + continue + fi + + echo " 表: $tables" + + # 生成 SQL 文件 + outfile="${OUTPUT_DIR}/${module}_${TIMESTAMP}.sql" + table_count=0 + + for tbl in $tables; do + echo -n " 导出 $tbl ... " + if ${MYSQLDUMP_CMD} \ + --single-transaction \ + --routines \ + --triggers \ + --set-gtid-purged=OFF \ + --column-names \ + --complete-insert \ + $NO_DATA \ + "$DATABASE" "$tbl" >> "$outfile" 2>/dev/null; then + echo "OK" + ((table_count++)) + else + echo "跳过(表不存在或无权限)" + fi + done + + if [[ $table_count -gt 0 ]]; then + echo " => $outfile ($table_count 个表)" + ((TOTAL_TABLES += table_count)) + ((TOTAL_FILES++)) + else + rm -f "$outfile" + echo " => 无有效表数据" + FAILED_MODULES+=("$module") + fi +done + +# 清理密码环境变量 +unset MYSQL_PWD + +echo "" +echo "============================================================" +echo " 导出完成" +echo " 模块数: ${#MODULES[@]}" +echo " 文件数: $TOTAL_FILES" +echo " 表总数: $TOTAL_TABLES" +if [[ ${#FAILED_MODULES[@]} -gt 0 ]]; then + echo " 无数据模块: ${FAILED_MODULES[*]}" +fi +echo " 输出目录: $(cd "$OUTPUT_DIR" && pwd)" +echo "============================================================" diff --git a/build.sh b/build.sh index 19206a8c..4cfad948 100755 --- a/build.sh +++ b/build.sh @@ -18,7 +18,7 @@ cd bricks/bricks ./build.sh cd $cdir/wwwroot ln -s $cdir/pkgs/bricks/dist $dir/wwwroot/bricks -for m in apppublic sqlor ahserver bricks-for-python xls2ddl checklang, skillagent dagflow discount +for m in apppublic sqlor ahserver bricks-for-python xls2ddl checklang do echo "install $m module..." cd $cdir/pkgs @@ -26,18 +26,21 @@ do cd $m $cdir/py3/bin/pip install . done -for m in appbase rbac accounting llmage platformbiz msp cpcc unipay filemgr dapi uapi rag charge pricing dagflow wechat-office-account discount +for m in appbase rbac accounting llmage msp cpcc unipay filemgr dapi uapi rag charge pricing discount harnessed_agent harnessed_reasoning sage_datamart product_management supplychain reallife_asset bugfix do echo "install $m module..." cd $cdir/pkgs - git clone https://git.opencomputing.cn/yumoqing/$m - cd $m - $cdir/py3/bin/pip install . - if [ -d $cdir/pkgs/$m/models ];then - cd $cdir/pkgs/$m/models - xls2ddl mysql . > mysql.ddl.sql - mysql -h db -utest -ptest123 sage < mysql.ddl.sql + if [ ! -d "$cdir/pkgs/$m" ];then + git clone https://git.opencomputing.cn/yumoqing/$m + cd $cdir/pkgs/$m + if [ -d $cdir/pkgs/$m/models ];then + cd $cdir/pkgs/$m/models + xls2ddl mysql . > mysql.ddl.sql + mysql -h db -utest -ptest123 sage < mysql.ddl.sql + fi fi + cd $cdir/pkgs/$m + $cdir/py3/bin/pip install . if [ -d $cdir/pkgs/$m/json ];then cd $cdir/pkgs/$m/json ./build.sh @@ -91,3 +94,40 @@ if ! echo "$cc"|grep -Fq "$new_cron"; then else echo "任务已存在,未重复添加。" fi + +# 每日 8:00 抓取外汇牌价 +forex_cron="0 8 * * * curl -s http://localhost:9180/accounting/api/fetch_forex_rates.dspy" +if ! echo "$cc"|grep -Fq "fetch_forex_rates"; then + (echo "$cc";echo "$forex_cron") | crontab - +else + echo "汇率任务已存在,未重复添加。" +fi + +# sage_datamart ETL crontab +cc=$(crontab -l 2>/dev/null) + +# 每5分钟增量同步 llmusage → dm_model_call_fact +dm_sync_cron="*/5 * * * * curl -s http://localhost:9180/sage_datamart/cron/etl_sync.dspy" +if ! echo "$cc"|grep -Fq "etl_sync"; then + (echo "$cc";echo "$dm_sync_cron") | crontab - + cc=$(crontab -l 2>/dev/null) +else + echo "datamart sync任务已存在,未重复添加。" +fi + +# 每小时聚合 dm_model_perf_daily +dm_agg_cron="15 * * * * curl -s http://localhost:9180/sage_datamart/cron/etl_aggregate.dspy" +if ! echo "$cc"|grep -Fq "etl_aggregate"; then + (echo "$cc";echo "$dm_agg_cron") | crontab - + cc=$(crontab -l 2>/dev/null) +else + echo "datamart aggregate任务已存在,未重复添加。" +fi + +# 每天 02:00 聚合供应商性价比 +dm_prov_cron="0 2 * * * curl -s http://localhost:9180/sage_datamart/cron/etl_provider_cost.dspy" +if ! echo "$cc"|grep -Fq "etl_provider_cost"; then + (echo "$cc";echo "$dm_prov_cron") | crontab - +else + echo "datamart provider_cost任务已存在,未重复添加。" +fi diff --git a/check_bricks_perms.py b/check_bricks_perms.py new file mode 100644 index 00000000..7b45986b --- /dev/null +++ b/check_bricks_perms.py @@ -0,0 +1,19 @@ +import asyncio +from sqlor.dbpools import DBPools +from appPublic.jsonConfig import getConfig + +async def main(): + config = getConfig('.') + db = DBPools(config.databases) + async with db.sqlorContext('sage') as sor: + perms = await sor.sqlExe( + "select p.path from permission p inner join rolepermission rp on p.id=rp.permid where rp.roleid='any' and p.path like ${path}$", + {'path': '/bricks/%'} + ) + print(f'Found {len(perms)} bricks paths with any role:') + for p in perms[:15]: + print(f' {p.path}') + if len(perms) > 15: + print(f' ... and {len(perms)-15} more') + +asyncio.get_event_loop().run_until_complete(main()) diff --git a/conf/config.json b/conf/config.json deleted file mode 100755 index 344f71f3..00000000 --- a/conf/config.json +++ /dev/null @@ -1,104 +0,0 @@ -{ - "password_key":"!@#$%^&*(*&^%$QWERTYUIqwertyui234567", - "logopath": "$[workdir]$/conf/logo.png", - "woa_handler_id":"woa_subscribe_type", - "logger":{ - "name":"sage", - "levelname":"clientinfo", - "logfile":"$[workdir]$/logs/sage.log" - }, - "pay":{ - "alipay":{ - "public_key_file":"$[workdir]$/conf/alipay/public.txt", - "private_key_file":"$[workdir]$/conf/alipay/private.txt", - "appid":"2021005111636494", - "callback":"https://sage.opencomputing.cn/api/callback/alipay" - }, - "paypal":{ - "mode":"sandbox", - "client_id":"myid", - "client_secret":"mysecret", - "return_url":"ret_url", - "cancel_url":"cancel_url" - } - }, - "skills_dir": "$[workdir]$/skills", - "filesroot":"$[workdir]$/files", - "databases":{ - "sage":{ - "driver":"mysql", - "kwargs":{ - "user":"test", - "db":"sage", - "password":"SS+C1MDMJrslBwGzYIv3nQ==", - "charset": "utf8mb4", - "host":"db" - } - } - }, - "zmq_url": "tcp://127.0.0.1:5555", - "website":{ - "paths":[ - ["$[workdir]$/wwwroot",""] - ], - "client_max_size":1000000000, - "host":"0.0.0.0", - "port":9080, - "coding":"utf-8", - "ssl_gg":{ - "crtfile":"$[workdir]$/conf/www.bsppo.com.pem", - "keyfile":"$[workdir]$/conf/www.bsppo.com.key" - }, - "indexes":[ - "index.html", - "index.tmpl", - "index.ui", - "index.dspy", - "index.md" - ], - "startswiths":[ - { - "leading":"/idfile", - "registerfunction":"idfile" - },{ - "leading":"/i18n_getmsgs", - "registerfunction":"i18n" - } - ], - "processors":[ - [".ws","ws"], - [".xterm","xterm"], - [".proxy","proxy"], - [".llm", "llm"], - [".llms", "llms"], - [".llma", "llma"], - [".xlsxds","xlsxds"], - [".sqlds","sqlds"], - [".tmpl.js","tmpl"], - [".tmpl.css","tmpl"], - [".html.tmpl","tmpl"], - [".bcrud", "bricks_crud"], - [".tmpl","tmpl"], - [".app","app"], - [".bui","bui"], - [".ui","bui"], - [".dspy","dspy"], - [".md","md"] - ], - "rsakey":{ - "privatekey":"$[workdir]$/conf/rsa_private_key.pem", - "publickey":"$[workdir]$/conf/rsa_public_key.pem" - }, - "session_max_time":3000, - "session_issue_time":2500, - "session_redis":{ - "url":"redis://127.0.0.1:6379" - } - }, - "langMapping":{ - "zh-Hans-CN":"zh-cn", - "zh-CN":"zh-cn", - "en-us":"en", - "en-US":"en" - } -} diff --git a/docs/OPC智能服务平台.pptx b/docs/OPC智能服务平台.pptx new file mode 100644 index 00000000..8e13b1db Binary files /dev/null and b/docs/OPC智能服务平台.pptx differ diff --git a/docs/marketing-promo.md b/docs/marketing-promo.md new file mode 100644 index 00000000..47011583 --- /dev/null +++ b/docs/marketing-promo.md @@ -0,0 +1,135 @@ +# Sage 智能平台 — 市场宣传稿 + +## 一句话 + +**Sage:让 AI 服务成为可运营、可计费、可编排的商业产品。** + +--- + +## 我们解决了什么问题 + +AI 时代的企业面临三个核心难题: + +1. **模型太多,管理太难** — 通义、DeepSeek、MiniMax、火山方舟……每个供应商 API 不同,接入成本高 +2. **计费复杂,算不清账** — 按 token?按秒?按次?不同模型不同定价,客户账单一团乱 +3. **产线分散,效率低下** — 多个 AI 服务各自为政,无法编排成完整的业务流程 + +**Sage 用一套平台解决全部问题。** + +--- + +## 核心能力 + +### ① 统一模型网关 — 一个接口,接入所有 AI + +``` +OpenAI 兼容 API Sage llmage 网关 上游 AI 服务 +───────────────── ───────────────── ───────────── +/v1/chat → → 通义千问 +/v1/image → 模型路由 + → 通义万相 +/v1/video → 计费 + 权限 → MiniMax +/v1/models → → 火山方舟 +/pipeline/submit → → 自建 GPU 服务 +``` + +- **146+ 模型**已接入,文本/图像/视频/语音全覆盖 +- **OpenAI 兼容 API**,零代码迁移 +- **一行配置**新增模型,无需改代码 + +### ② 智能计费引擎 — 每一分钱都算得清清楚楚 + +| 计费方式 | 示例 | +|---------|------| +| 按量计费 | ASR 语音识别:0.01元/秒 | +| 按次计费 | 人脸检测:0.10元/次 | +| 按时长 | 视频生成:0.05元/秒 | +| 套餐/折扣 | 客户专属折扣、分销商差价 | + +- 实时余额检查,欠费自动拦截 +- 后台自动记账,零人工对账 +- 支持多级分销折扣体系 + +### ③ KTV 产线 — 从一首歌到一部 MV,全自动 + +``` +上传音频 → 自动分离人声/伴奏 → AI 生成 28 个场景视频 + → 逐字卡拉OK字幕 → 片头+水印 → 输出 KTV + MTV +``` + +**全部通过 API 自动化完成**,无需人工介入。 + +- 内置模型选择流程:客户看到费用预估,自主选择视频模型 +- 费用透明:每个子步骤独立计费,总费用一目了然 +- 容错机制:20% 容错预算,自动重试失败任务 + +### ④ 完整商业闭环 + +``` +客户注册 → API Key 管理 → 余额充值 → 调用服务 → 自动记账 → 账单导出 +``` + +- 多租户隔离,数据安全 +- 分销商/供应商多级管理体系 +- 优惠券、折扣、促销活动支持 + +--- + +## 谁在用 / 谁能用 + +| 用户类型 | 使用场景 | +|---------|---------| +| **AI 服务商** | 将自己的 GPU 服务包装为 API 产品,上架销售 | +| **内容创作者** | 一键制作 KTV/MV,AI 写词、AI 演唱、AI 视频 | +| **企业 IT** | 统一管理公司所有 AI 服务接入,控制成本 | +| **代理商** | 代理销售 AI 服务,赚取差价佣金 | +| **开发者** | 通过 OpenAI 兼容 API 快速开发 AI 应用 | + +--- + +## 技术亮点 + +- **异步任务引擎**:长耗时任务自动轮询,不阻塞用户 +- **供应商抽象层**:更换底层模型只需改配置,不换代码 +- **xls2ddl 建表**:Excel 设计数据库,自动生成 DDL + CRUD +- **浏览器测试**:CDP 协议自动化端到端测试 +- **热更新**:配置修改即时生效,无需重启 + +--- + +## 与竞品的差异 + +| 对比维度 | Sage | 传统 API 网关 | 单一模型平台 | +|---------|------|-------------|------------| +| 模型接入 | 146+ 任意供应商 | 有限 | 自有模型 | +| 计费能力 | 按量/按次/套餐/折扣 | 简单限额 | 固定定价 | +| 产线编排 | 多步骤自动化 | ❌ | ❌ | +| 客户管理 | 多租户+分销 | ❌ | 简单 | +| 部署方式 | 私有化部署 | 云服务 | SaaS | + +--- + +## 案例:KTV 产线实测数据 + +**《女儿国的秋》制作全过程:** + +| 步骤 | 服务 | 耗时 | 费用 | +|------|------|------|------| +| 音频分离 | Demucs (full) | 65秒 | 1.31元 | +| 场景生成 | HappyHorse T2V × 28 | ~10分钟 | ~14元 | +| 视频合成 | ffmpeg | 30秒 | — | +| **总计** | | | **~16元** | + +产出:213MB KTV 视频(双音轨+卡拉OK字幕)+ 210MB MTV 视频 + +--- + +## 立即开始 + +```bash +# 一行命令体验 KTV 产线 +curl -X POST https://your-sage.com/llmage/v1/pipeline/submit \ + -H "Authorization: Bearer YOUR_KEY" \ + -d '{"model":"ky-demucs-separate","audio_file":"song.mp3"}' +``` + +**联系元境团队,获取完整部署方案:元境出品 欢乐随行** diff --git a/docs/marketing-promo.pptx b/docs/marketing-promo.pptx new file mode 100644 index 00000000..51cc9c5f Binary files /dev/null and b/docs/marketing-promo.pptx differ diff --git a/docs/technical-whitepaper.md b/docs/technical-whitepaper.md new file mode 100644 index 00000000..fa5580db --- /dev/null +++ b/docs/technical-whitepaper.md @@ -0,0 +1,208 @@ +# Sage 智能平台技术白皮书 + +## 一、平台概述 + +Sage 是一个面向 AI 时代的智能服务管理平台,集模型网关、计费引擎、产线编排、权限管理于一体,为企业提供从 API 接入到业务结算的全链路基础设施。 + +**核心理念**:一套平台,统一管理所有 AI 服务的接入、调度、计费和客户关系。 + +## 二、系统架构 + +``` +┌──────────────────────────────────────────────────────────┐ +│ 客户端层 │ +│ Web 管理后台 │ API 调用 (OpenAI 兼容) │ CLI Agent │ +└──────────────┬───────────────────────────────────────────┘ + │ +┌──────────────▼───────────────────────────────────────────┐ +│ Sage 平台核心 │ +│ │ +│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌────────────┐ │ +│ │ 权限管理 │ │ 模型网关 │ │ 计费引擎 │ │ 产线编排 │ │ +│ │ RBAC + │ │ llmage │ │ Pricing │ │ Pipeline │ │ +│ │ Session │ │ UAPI │ │ Engine │ │ Orchestrator│ │ +│ └──────────┘ └──────────┘ └──────────┘ └────────────┘ │ +│ │ +│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌────────────┐ │ +│ │ 文件管理 │ │ 知识库 │ │ 营销引擎 │ │ 多语言 │ │ +│ │ FileMgr │ │ RAG/KDB │ │ Discount │ │ i18n │ │ +│ └──────────┘ └──────────┘ └──────────┘ └────────────┘ │ +└──────────────┬───────────────────────────────────────────┘ + │ +┌──────────────▼───────────────────────────────────────────┐ +│ 基础设施层 │ +│ ahserver (异步HTTP) │ sqlor (数据库) │ Redis │ Nginx │ +│ Hermes Agent │ 浏览器测试 (CDP) │ SSH 远程调度 │ +└──────────────────────────────────────────────────────────┘ +``` + +## 三、核心模块 + +### 3.1 模型网关 (llmage) + +**功能**:统一的 AI 模型接入层,支持 OpenAI 兼容 API。 + +| 特性 | 说明 | +|------|------| +| 多供应商 | 同时接入通义、MiniMax、火山方舟、Vidu、自建 GPU 等 | +| 协议统一 | 标准 `/v1/chat/completions`、`/v1/models` 等 OpenAI 兼容接口 | +| 异步任务 | 内置 asyncinference 引擎,支持 submit→poll→result 异步流水线 | +| 数据模板 | Jinja2 模板引擎,灵活适配不同供应商的请求/响应格式 | +| 参数映射 | `_file` 命名规范,自动处理文件 → URL 转换 | + +**已接入模型**:146+ 模型,涵盖文本对话、文生图、文生视频、语音识别、人脸识别、音频分离、歌曲评分、声音转换、超分辨率等。 + +### 3.2 计费引擎 (Pricing) + +**功能**:灵活的多维度计费系统,支持按量计费、套餐计费、渠道折扣。 + +| 特性 | 说明 | +|------|------| +| 按量计费 | 支持 audio_seconds、image_count、video_seconds 等多种计价因子 | +| 独立定价 | 每个模型独立 ppid,不同服务不同单价 | +| 自动记账 | backend_accounting 后台循环处理,实时结算 | +| 余额管控 | checkCustomerBalance 前置检查,欠费自动阻拦 | +| 定价模板 | YAML 格式定价数据,price_factors + unit_prices 灵活配置 | + +**定价示例(KTV 产线)**: + +| 服务 | 单价 | 计价因子 | +|------|------|---------| +| 语音识别 | 0.01元/秒 | audio_seconds | +| 音频分离 | 0.02元/秒 | audio_seconds | +| 人脸检测 | 0.10元/次 | detect_count | +| 字幕渲染 | 0.01元/条 | subtitle_count | +| 超分辨率 | 0.50元/张 | image_count | +| 声音转换 | 0.15元/秒 | audio_seconds | + +### 3.3 权限管理 (RBAC) + +**功能**:基于角色的访问控制,支持 Session 管理、跨进程缓存同步。 + +| 特性 | 说明 | +|------|------| +| 角色体系 | 支持 admin/logined/anonymous/any 四级默认角色 + 自定义角色 | +| 路径权限 | 每个 DSPY/UI 端点可独立配置访问权限 | +| Session 管理 | Redis 存储,跨进程共享,自动过期 | +| 缓存同步 | 权限变更自动广播所有工作进程 | +| 审计日志 | 完整的访问日志和操作记录 | + +### 3.4 产线编排 (Pipeline) + +**功能**:将多个 AI 原子服务编排为完整的业务流程。 + +**KTV 产线示例**(14 个 GPU 服务 → llmage API 统一调度): + +``` +音频准备 → Demucs 分离(人声/伴奏/MIDI) → ASR 语音识别(逐字时间戳) + ↓ ↓ + 人声提取 精准字幕生成 + ↓ ↓ + RVC 变声 卡拉OK渲染 + ↓ ↓ + ┌──────────────── 视频合并 ────────────────────┘ + ↓ +输出:KTV 视频(双音轨) + MTV 视频 + ASS 字幕 +``` + +**核心特性**: +- 全链路通过 llmage API 调度,不直连 GPU +- 异步任务自动轮询 +- 自动记账(每个子任务独立计费) +- 费用预估 + 模型选择(客户参与决策) + +### 3.5 模型选择与费用预估 + +产线内置智能模型选择流程: + +``` +故事板生成 → 模型选择(费用预估) → 视频生成 + ↓ + 客户看到: + - 快乐马:0.03元/秒,快速经济 + - 通义万象 WAN 2.7:0.05元/秒,高质量 ⭐推荐 + - 豆包 Seedance 2.0:0.08元/秒,旗舰级 + ↓ + 客户选择 → 按选择生成 +``` + +**费用预估包含**: +- 总视频时长 × 单价 = 基础费用 +- 20% 容错系数(重试/失败) +- 其他服务费用明细(demucs + ASR + 字幕等) + +## 四、技术特性 + +### 4.1 异步流水线 + +Sage 的 asyncinference 引擎提供完整的异步任务管理: + +``` +POST /v1/pipeline/submit → {"taskid":"...","status":"PENDING"} + → 后台轮询 (每 5s) + → GET /status?task_id=xxx → {"status":"SUCCEEDED","usage":"..."} + → 自动更新 llmusage → 触发记账 +``` + +### 4.2 供应商抽象 (UAPI) + +通过统一的 UAPI 层实现供应商无关的接口抽象: + +```yaml +供应商配置: + ktv-gateway: https://ktv.opencomputing.net:10443 + tongyi-wan: https://dashscope.aliyuncs.com + vidu: https://api.vidu.com + +端点模板: + demucs-separate: POST /demucs/api/demucs-separate + asr-transcribe: POST /asr/api/asr-transcribe + realesrgan-upscale: POST /realesrgan/api/realesrgan-upscale +``` + +每个端点通过 Jinja2 模板处理请求/响应转换,实现供应商 API 差异的透明化。 + +### 4.3 数据库设计规范 + +- 统一使用 xls2ddl 建表工具 +- 字符集标准:`utf8mb4 COLLATE utf8mb4_unicode_ci` +- 支持 emoji、多语言字符 +- 自增 ID + UUID 双标识体系 + +### 4.4 前端框架 + +- 基于 bricks-mp(自研 JSON 驱动 UI 框架) +- 支持 Jinja2 服务端渲染 +- 暗色主题、响应式布局 +- 浏览器端到端测试(CDP 协议) + +## 五、部署架构 + +``` +┌─────────────────┐ ┌──────────────────┐ +│ tokentest │ │ production │ +│ 测试环境 │ │ 生产环境 │ +├─────────────────┤ ├──────────────────┤ +│ Sage :9180 │ │ Sage :9180 │ +│ MariaDB │ │ MariaDB │ +│ Redis │ │ Redis │ +│ Nginx :443 │ │ Nginx :443 │ +└────────┬────────┘ └────────┬─────────┘ + │ │ + └───────────┬───────────┘ + │ + ┌──────────▼──────────┐ + │ GPU 计算集群 │ + │ opencomputing.net │ + ├─────────────────────┤ + │ Demucs :9083 │ + │ ASR :9925 │ + │ RealESRGAN :9082 │ + │ Face :9081 │ + │ ... │ + └─────────────────────┘ +``` + +## 六、总结 + +Sage 平台通过统一的模型网关、灵活的计费引擎、完善的权限管理和可编排的产线系统,为企业提供了一站式的 AI 服务商业化平台。无论是简单的 API 代理还是复杂的多步骤 AI 工作流,Sage 都能以一致的方式管理和计费。 diff --git a/docs/元境平台-市场宣传.pptx b/docs/元境平台-市场宣传.pptx new file mode 100644 index 00000000..b7f14ac5 Binary files /dev/null and b/docs/元境平台-市场宣传.pptx differ diff --git a/i18n/en/msg.txt b/i18n/en/msg.txt new file mode 100644 index 00000000..dabb0bf4 --- /dev/null +++ b/i18n/en/msg.txt @@ -0,0 +1,341 @@ +API: API +API Key管理: API Key Management +Add Error: Add Error +Add Success: Add Success +Cancel: Cancel +Conform: Confirm +DeepSeek: DeepSeek +Delete Error: Delete Error +Delete Success: Delete Success +Discard: Discard +Error: Error +LocalOllama: LocalOllama +Login: Login +Login Error: Login Error +Message: Message +MiniMax: MiniMax +RBAC工具: RBAC Tools +Reset: Reset +Reset Password: Reset Password +Submit: Submit +Token交易记录: Token Transaction Records +Update Error: Update Error +Update Success: Update Success +Welcome back: Welcome back +\u4ea4\u6613\u65e5\u671f: Transaction Date +\u4ea4\u6613\u65f6\u95f4: Transaction Time +\u4f1a\u8bdd\u6587\u4ef6\u540d: Session Filename +\u4f9b\u5e94\u5546id: Supplier ID +\u5176\u4ed6token\u4ef7\u683c: Other Token Price +\u5176\u4ed6tokens\u6d88\u8d39\u6570: Other Tokens Consumed +\u51fd\u6570\u540d: Function Name +\u54cd\u5e94\u65f6\u95f4: Response Time +\u5b8c\u6210\u65f6\u95f4: Completion Time +\u5ba2\u6237id: Customer ID +\u5bc6\u7801: Password +\u624b\u673a: Phone +\u6a21\u578b\u5b9e\u4f8bid: Model Instance ID +\u6a21\u578b\u7c7b\u578bid: Model Type ID +\u7528\u6237\u540d: Username +\u7528\u6237id: User ID +\u8ba1\u6b21\u4ef7\u683c: Per-Call Price +\u8ba1\u6b21\u91d1\u989d: Per-Call Amount +\u8ba1\u8d39\u6a21\u5f0f: Billing Mode +\u8ba1\u8d39token\u6570\u91cf: Billed Token Count +\u8bb0\u8d26\u72b6\u6001: Accounting Status +\u8bc4\u4ef7: Rating +\u8f93\u5165token\u4ef7\u683c: Input Token Price +\u8f93\u5165token\u6d88\u8d39\u6570: Input Tokens Consumed +\u8f93\u5165token\u91d1\u989d: Input Token Amount +\u8f93\u51fatoken\u4ef7\u683c: Output Token Price +\u8f93\u51fatoken\u6d88\u8d39\u6570: Output Tokens Consumed +\u8f93\u51fatoken\u91d1\u989d: Output Token Amount +\u90ae\u4ef6\u5730\u5740: Email Address +\u9644\u5c5e\u5bc6\u94a5: Associated Key +api\u5bc6\u94a5: API Secret +api密码: API Password +api密钥: API Secret +api用户: API User +failed: failed +http程序接口: HTTP Program Interface +id: ID +io数据id: IO Data ID +logout success: Logout Success +minimax账单: MiniMax Bill +minimax账号: MiniMax Account +minimax账号id: MiniMax Account ID +ok: OK +system error: System Error +token使用表: Token Usage Table +token数量: Token Count +token每天统计: Daily Token Statistics +token消耗量Top5: Top 5 Token Consumption +user name or password error: Username or Password Error +user register: User Register + 角色: Role +© 2024 版权所有, 开元云(北京)科技有限公司: © 2024 All Rights Reserved, Kaiyuan Cloud (Beijing) Technology Co., Ltd. +上位系统: Upper System +上位系统管理: Upper System Management +下位系统接口: Lower System Interface +主营业务描述: Main Business Description +主页: Home +交易日期: Transaction Date +交易时间: Transaction Time +产品管理: Product Management +产品类别管理: Product Category Management +产品类型管理: Product Type Management +产品类型规格: Product Type Specifications +代客充值: Agent Recharge +代理: Agent +仪表盘: Dashboard +会计分录配置: Accounting Entry Configuration +会话文件名: Session Filename +余额与充值: Balance and Recharge +使用日期: Usage Date +使用时间: Usage Time +供应协议: Supply Agreement +供应商id: Supplier ID +供应商充值: Supplier Recharge +供应商名: Supplier Name (Short) +供应商名称: Supplier Name +供应商对账: Supplier Reconciliation +供应商明细对账: Supplier Detail Reconciliation +供应商模型列表: Supplier Model List +供应商管理: Supplier Management +供应商结算: Supplier Settlement +供应商财务: Supplier Finance +供应链管理: Supply Chain Management +供销协议管理: Supply and Sales Agreement Management +信用额度: Credit Limit +值: Value +元境平台: Yuanjing Platform +充值: Recharge +关于我们: About Us +其他tokens: Other Tokens +其他价格: Other Price +其他金额: Other Amount +函数名: Function Name +分销协议: Distribution Agreement +分销协议管理: Distribution Agreement Management +分销商对账: Distributor Reconciliation +分销商管理: Distributor Management +分销商结算: Distributor Settlement +创建时间: Creation Time +创建时间戳: Creation Timestamp +删除标志: Delete Flag +刷新权限缓存: Refresh Permission Cache +单模型对话: Single Model Conversation +参与方科目配置: Participant Account Configuration +发送验证码: Send Verification Code +名称: Name +启动日期: Start Date +命令: Command +响应时间: Response Time +响应模式: Response Mode +图标: Icon +在响应包中的位置: Position in Response Package +地址: Address +多模型对话: Multi-Model Conversation +多级标志: Multi-Level Flag +大模型: Large Model +大模型API调用: Large Model API Call +大模型费用: Large Model Cost +大模型费用W: Large Model Cost (W) +失效日期: Expiration Date +姓名: Full Name +完成时间: Completion Time +定价管理: Pricing Management +实例名: Instance Name (Short) +实例名称: Instance Name +实例说明: Instance Description +客户id: Customer ID +客户信用额度: Customer Credit Limit +密码: Password +小数点数: Decimal Places +属主id: Owner ID +帐务: Accounting +带历史信息: With History +应用: Application +应用编码表: Application Code Table +开始日期: Start Date +开帐: Open Account +微信: WeChat +性能最优Top5: Top 5 Best Performance +我: Me +我的订单: My Orders +我的账单: My Bills +我的账户: My Account +我的资源: My Resources +所在地区id: District ID +所在城市id: City ID +所在省id: Province ID +所属机构: Affiliated Organization +手机: Phone +手机号: Phone Number +手机验证码: Phone Verification Code +扫描未授权文件: Scan Unauthorized Files +接口id: Interface ID +接口ur: Interface URL +接口内容: Interface Content +接口参数: Interface Parameters +接口名: Interface Name (Short) +接口名称: Interface Name +接口描述: Interface Description +接口提供方: Interface Provider +接口输入输出: Interface Input/Output +接口集: Interface Set +推理: Inference +描述: Description +提示词: Prompt +数据IO: Data IO +数据值: Data Value +数据名: Data Name +数据看板: Data Dashboard +数据类型: Data Type +明细对账: Detail Reconciliation +是否多模态: Is Multimodal +是否必须: Is Required +显示名: Display Name +智普: Zhipu +智能体: AI Agent +月之暗面: Moonshot +服务目录: Service Catalog +服务管理: Service Management +机构: Organization +机构id: Organization ID +机构别名: Organization Alias +机构名称: Organization Name +机构拥有角色: Organization Roles +机构类型: Organization Type +机构编码: Organization Code +机构角色: Organization Role +权限: Permission +权限id: Permission ID +权限管理: Permission Management +查询路径权限角色: Query Path Permission Role +标题: Title +模型: Model +模型id: Model ID +模型供应商: Model Provider +模型列表: Model List +模型名称: Model Name +模型图标URL: Model Icon URL +模型实例: Model Instance +模型实例id: Model Instance ID +模型广场: Model Marketplace +模型或实例id: Model or Instance ID +模型接口: Model Interface +模型消息模版: Model Message Template +模型用量: Model Usage +模型管理: Model Management +模型类型: Model Type +模型类型id: Model Type ID +模型类型输入数据: Model Type Input Data +模型类型输出数据: Model Type Output Data +模型计费: Model Billing +模型计费日志: Model Billing Log +模型说明: Model Description +模型调优: Model Tuning +模型输入输出数据: Model Input/Output Data +消费token数: Consumed Token Count +消费日期: Consumption Date +消费时间戳: Consumption Timestamp +消费金额: Consumption Amount +添加供应商: Add Supplier +添加管理员: Add Administrator +父id: Parent ID +父数据id: Parent Data ID +父机构id: Parent Organization ID +父权限id: Parent Permission ID +用户: User +用户api密码表: User API Password Table +用户id: User ID +用户名: Username +用户密码: User Password +用户消息模版: User Message Template +用户状态: User Status +用户管理: User Management +用户角色: User Role +用户部门表: User Department Table +百川: Baichuan +百度千帆: Baidu Qianfan +真人素材: Real Person Material +私有知识库: Private Knowledge Base +科目设置: Account Settings +科目配置: Account Configuration +签退: Sign Out +类型: Type +类型名: Type Name +类型说明: Type Description +系统参数管理: System Parameter Management +系统日志: System Log +系统权限管理: System Permission Management +系统消息模版: System Message Template +系统管理: System Management +组号: Group Number +组织结构代码: Organization Structure Code +终端: Terminal +终端名称: Terminal Name +结束日期: End Date +编码名称: Code Name +编码键值表: Code Key-Value Table +联系人: Contact Person +联系人电话: Contact Phone +英文名: English Name +营业执照: Business License +角色: Role +角色id: Role ID +角色名称: Role Name +角色权限管理: Role Permission Management +角色权限表: Role Permission Table +角色管理: Role Management +角色编码: Role Code +计次价格: Per-Call Price +计次金额: Per-Call Amount +计费模式: Billing Mode +计费类型: Billing Type +记账失败记录: Accounting Failure Records +记账状态: Accounting Status +设备组: Device Group +评价: Rating +评价最高Top5: Top 5 Highest Rated +说明: Description +调用名: Call Name +调用数量Top5: Top 5 Call Volume +豆包: Doubao +财务处理: Financial Processing +账务中心: Accounting Center +账务设置: Accounting Settings +账务配置: Accounting Configuration +账单查询: Bill Inquiry +账号: Account +账号apikey: Account API Key +账号名称: Account Name +账号密码: Account Password +账号状态: Account Status +费用记录: Expense Records +路径: Path +身份证: ID Card +输入tokens: Input Tokens +输入token数: Input Token Count +输入价格: Input Price +输入字段: Input Field +输入显示: Input Display +输入类型: Input Type +输入金额: Input Amount +输出tokens: Output Tokens +输出token数: Output Token Count +输出价格: Output Price +输出显示: Output Display +输出金额: Output Amount +运营商配置: Operator Configuration +通义千问: Tongyi Qianwen +邮件地址: Email Address +邮箱: Email +部门id: Department ID +配置账务: Configure Accounting +重置密码: Reset Password +错帐处理: Error Account Handling +键: Key +长度: Length +附属密钥: Associated Key diff --git a/i18n/jp/msg.txt b/i18n/jp/msg.txt new file mode 100644 index 00000000..609867e7 --- /dev/null +++ b/i18n/jp/msg.txt @@ -0,0 +1,341 @@ +API: API +API Key管理: APIキー管理 +Add Error: 追加エラー +Add Success: 追加成功 +Cancel: キャンセル +Conform: 確認 +DeepSeek: DeepSeek +Delete Error: 削除エラー +Delete Success: 削除成功 +Discard: 破棄 +Error: エラー +LocalOllama: LocalOllama +Login: ログイン +Login Error: ログインエラー +Message: メッセージ +MiniMax: MiniMax +RBAC工具: RBACツール +Reset: リセット +Reset Password: パスワードリセット +Submit: 送信 +Token交易记录: Token取引記録 +Update Error: 更新エラー +Update Success: 更新成功 +Welcome back: お帰りなさい +\u4ea4\u6613\u65e5\u671f: 取引日 +\u4ea4\u6613\u65f6\u95f4: 取引時間 +\u4f1a\u8bdd\u6587\u4ef6\u540d: セッションファイル名 +\u4f9b\u5e94\u5546id: サプライヤーID +\u5176\u4ed6token\u4ef7\u683c: その他Token価格 +\u5176\u4ed6tokens\u6d88\u8d39\u6570: その他Token消費数 +\u51fd\u6570\u540d: 関数名 +\u54cd\u5e94\u65f6\u95f4: レスポンス時間 +\u5b8c\u6210\u65f6\u95f4: 完了時間 +\u5ba2\u6237id: 顧客ID +\u5bc6\u7801: パスワード +\u624b\u673a: 携帯電話 +\u6a21\u578b\u5b9e\u4f8bid: モデルインスタンスID +\u6a21\u578b\u7c7b\u578bid: モデルタイプID +\u7528\u6237\u540d: ユーザー名 +\u7528\u6237id: ユーザーID +\u8ba1\u6b21\u4ef7\u683c: 回数制価格 +\u8ba1\u6b21\u91d1\u989d: 回数制金額 +\u8ba1\u8d39\u6a21\u5f0f: 課金モード +\u8ba1\u8d39token\u6570\u91cf: 課金Token数 +\u8bb0\u8d26\u72b6\u6001: 記帳ステータス +\u8bc4\u4ef7: 評価 +\u8f93\u5165token\u4ef7\u683c: 入力Token価格 +\u8f93\u5165token\u6d88\u8d39\u6570: 入力Token消費数 +\u8f93\u5165token\u91d1\u989d: 入力Token金額 +\u8f93\u51fatoken\u4ef7\u683c: 出力Token価格 +\u8f93\u51fatoken\u6d88\u8d39\u6570: 出力Token消費数 +\u8f93\u51fatoken\u91d1\u989d: 出力Token金額 +\u90ae\u4ef6\u5730\u5740: メールアドレス +\u9644\u5c5e\u5bc6\u94a5: 付属キー +api\u5bc6\u94a5: APIシークレット +api密码: APIパスワード +api密钥: APIシークレット +api用户: APIユーザー +failed: 失敗 +http程序接口: HTTPプログラムインターフェース +id: ID +io数据id: IOデータID +logout success: ログアウト成功 +minimax账单: MiniMax請求書 +minimax账号: MiniMaxアカウント +minimax账号id: MiniMaxアカウントID +ok: OK +system error: システムエラー +token使用表: Token使用表 +token数量: Token数 +token每天统计: Token日次統計 +token消耗量Top5: Token消費量トップ5 +user name or password error: ユーザー名またはパスワードエラー +user register: ユーザー登録 + 角色: ロール +© 2024 版权所有, 开元云(北京)科技有限公司: © 2024 著作権所有、開元雲(北京)科技有限公司 +上位系统: 上位システム +上位系统管理: 上位システム管理 +下位系统接口: 下位システムインターフェース +主营业务描述: 主要業務記述 +主页: ホーム +交易日期: 取引日 +交易时间: 取引時間 +产品管理: 製品管理 +产品类别管理: 製品カテゴリ管理 +产品类型管理: 製品タイプ管理 +产品类型规格: 製品タイプ仕様 +代客充值: 代理チャージ +代理: エージェント +仪表盘: ダッシュボード +会计分录配置: 仕訳設定 +会话文件名: セッションファイル名 +余额与充值: 残高とチャージ +使用日期: 使用日 +使用时间: 使用時間 +供应协议: 供給契約 +供应商id: サプライヤーID +供应商充值: サプライヤーチャージ +供应商名: サプライヤー名 +供应商名称: サプライヤー名称 +供应商对账: サプライヤー照合 +供应商明细对账: サプライヤー明細照合 +供应商模型列表: サプライヤーモデル一覧 +供应商管理: サプライヤー管理 +供应商结算: サプライヤー決済 +供应商财务: サプライヤー財務 +供应链管理: サプライチェーン管理 +供销协议管理: 供給販売契約管理 +信用额度: 与信限度額 +值: 値 +元境平台: 元境プラットフォーム +充值: チャージ +关于我们: 私たちについて +其他tokens: その他Tokens +其他价格: その他価格 +其他金额: その他金額 +函数名: 関数名 +分销协议: 販売代理契約 +分销协议管理: 販売代理契約管理 +分销商对账: 販売代理店照合 +分销商管理: 販売代理店管理 +分销商结算: 販売代理店決済 +创建时间: 作成日時 +创建时间戳: 作成タイムスタンプ +删除标志: 削除フラグ +刷新权限缓存: 権限キャッシュ更新 +单模型对话: 単一モデル対話 +参与方科目配置: 参加者科目設定 +发送验证码: 認証コード送信 +名称: 名称 +启动日期: 開始日 +命令: コマンド +响应时间: レスポンス時間 +响应模式: レスポンスモード +图标: アイコン +在响应包中的位置: レスポンスパッケージ内の位置 +地址: アドレス +多模型对话: マルチモデル対話 +多级标志: マルチレベルフラグ +大模型: 大規模モデル +大模型API调用: 大規模モデルAPI呼び出し +大模型费用: 大規模モデル費用 +大模型费用W: 大規模モデル費用W +失效日期: 有効期限 +姓名: 氏名 +完成时间: 完了時間 +定价管理: 価格設定管理 +实例名: インスタンス名 +实例名称: インスタンス名称 +实例说明: インスタンス説明 +客户id: 顧客ID +客户信用额度: 顧客与信限度額 +密码: パスワード +小数点数: 小数点桁数 +属主id: オーナーID +帐务: 会計 +带历史信息: 履歴情報付き +应用: アプリケーション +应用编码表: アプリケーションコード表 +开始日期: 開始日 +开帐: 口座開設 +微信: WeChat +性能最优Top5: パフォーマンス最優秀トップ5 +我: 自分 +我的订单: マイオーダー +我的账单: マイ請求書 +我的账户: マイアカウント +我的资源: マイリソース +所在地区id: 所在区域ID +所在城市id: 所在城市ID +所在省id: 所在省ID +所属机构: 所属機関 +手机: 携帯電話 +手机号: 携帯電話番号 +手机验证码: 携帯電話認証コード +扫描未授权文件: 未認可ファイルスキャン +接口id: インターフェースID +接口ur: インターフェースURL +接口内容: インターフェース内容 +接口参数: インターフェースパラメータ +接口名: インターフェース名 +接口名称: インターフェース名称 +接口描述: インターフェース記述 +接口提供方: インターフェース提供者 +接口输入输出: インターフェース入出力 +接口集: インターフェースセット +推理: 推論 +描述: 記述 +提示词: プロンプト +数据IO: データIO +数据值: データ値 +数据名: データ名 +数据看板: データダッシュボード +数据类型: データタイプ +明细对账: 明細照合 +是否多模态: マルチモーダルかどうか +是否必须: 必須かどうか +显示名: 表示名 +智普: 智譜 +智能体: AIエージェント +月之暗面: Moonshot +服务目录: サービスカタログ +服务管理: サービス管理 +机构: 機関 +机构id: 機関ID +机构别名: 機関別名 +机构名称: 機関名称 +机构拥有角色: 機関所有ロール +机构类型: 機関タイプ +机构编码: 機関コード +机构角色: 機関ロール +权限: 権限 +权限id: 権限ID +权限管理: 権限管理 +查询路径权限角色: クエリパス権限ロール +标题: タイトル +模型: モデル +模型id: モデルID +模型供应商: モデルサプライヤー +模型列表: モデル一覧 +模型名称: モデル名称 +模型图标URL: モデルアイコンURL +模型实例: モデルインスタンス +模型实例id: モデルインスタンスID +模型广场: モデルマーケットプレイ스 +模型或实例id: モデルまたはインスタンスID +模型接口: モデルインターフェース +模型消息模版: モデルメッセージテンプレート +模型用量: モデル使用量 +模型管理: モデル管理 +模型类型: モデルタイプ +模型类型id: モデルタイプID +模型类型输入数据: モデルタイプ入力データ +模型类型输出数据: モデルタイプ出力データ +模型计费: モデル課金 +模型计费日志: モデル課金ログ +模型说明: モデル説明 +模型调优: モデルチューニング +模型输入输出数据: モデル入出力データ +消费token数: 消費Token数 +消费日期: 消費日 +消费时间戳: 消費タイムスタンプ +消费金额: 消費金額 +添加供应商: サプライヤー追加 +添加管理员: 管理者追加 +父id: 親ID +父数据id: 親データID +父机构id: 親機関ID +父权限id: 親権限ID +用户: ユーザー +用户api密码表: ユーザーAPIパスワード表 +用户id: ユーザーID +用户名: ユーザー名 +用户密码: ユーザーパスワード +用户消息模版: ユーザーメッセージテンプレート +用户状态: ユーザーステータス +用户管理: ユーザー管理 +用户角色: ユーザーロール +用户部门表: ユーザー部門表 +百川: 百川 +百度千帆: Baidu Qianfan +真人素材: 実写素材 +私有知识库: プライベートナレッジベース +科目设置: 科目設定 +科目配置: 科目構成 +签退: サインアウト +类型: タイプ +类型名: タイプ名 +类型说明: タイプ説明 +系统参数管理: システムパラメータ管理 +系统日志: システムログ +系统权限管理: システム権限管理 +系统消息模版: システムメッセージテンプレート +系统管理: システム管理 +组号: グループ番号 +组织结构代码: 組織構造コード +终端: ターミナル +终端名称: ターミナル名 +结束日期: 終了日 +编码名称: コード名称 +编码键值表: コードキーバリュー表 +联系人: 連絡先 +联系人电话: 連絡先電話番号 +英文名: 英語名 +营业执照: 営業許可証 +角色: ロール +角色id: ロールID +角色名称: ロール名称 +角色权限管理: ロール権限管理 +角色权限表: ロール権限表 +角色管理: ロール管理 +角色编码: ロールコード +计次价格: 回数制価格 +计次金额: 回数制金額 +计费模式: 課金モード +计费类型: 課金タイプ +记账失败记录: 記帳失敗記録 +记账状态: 記帳ステータス +设备组: デバイスグループ +评价: 評価 +评价最高Top5: 最高評価トップ5 +说明: 説明 +调用名: 呼び出し名 +调用数量Top5: 呼び出し数量トップ5 +豆包: 豆包 +财务处理: 財務処理 +账务中心: 会計センター +账务设置: 会計設定 +账务配置: 会計構成 +账单查询: 請求書照会 +账号: アカウント +账号apikey: アカウントAPIキー +账号名称: アカウント名称 +账号密码: アカウントパスワード +账号状态: アカウントステータス +费用记录: 費用記録 +路径: パス +身份证: 身分証 +输入tokens: 入力Tokens +输入token数: 入力Token数 +输入价格: 入力価格 +输入字段: 入力フィールド +输入显示: 入力表示 +输入类型: 入力タイプ +输入金额: 入力金額 +输出tokens: 出力Tokens +输出token数: 出力Token数 +输出价格: 出力価格 +输出显示: 出力表示 +输出金额: 出力金額 +运营商配置: オペレーター設定 +通义千问: 通義千問 +邮件地址: メールアドレス +邮箱: メール +部门id: 部門ID +配置账务: 会計構成 +重置密码: パスワードリセット +错帐处理: 誤記帳処理 +键: キー +长度: 長さ +附属密钥: 付属キー diff --git a/i18n/ko/msg.txt b/i18n/ko/msg.txt new file mode 100644 index 00000000..00114059 --- /dev/null +++ b/i18n/ko/msg.txt @@ -0,0 +1,341 @@ +API: API +API Key管理: API 키 관리 +Add Error: 추가 오류 +Add Success: 추가 성공 +Cancel: 취소 +Conform: 확인 +DeepSeek: DeepSeek +Delete Error: 삭제 오류 +Delete Success: 삭제 성공 +Discard: 폐기 +Error: 오류 +LocalOllama: LocalOllama +Login: 로그인 +Login Error: 로그인 오류 +Message: 메시지 +MiniMax: MiniMax +RBAC工具: RBAC 도구 +Reset: 초기화 +Reset Password: 비밀번호 재설정 +Submit: 제출 +Token交易记录: Token 거래 기록 +Update Error: 업데이트 오류 +Update Success: 업데이트 성공 +Welcome back: 다시 오신 것을 환영합니다 +\u4ea4\u6613\u65e5\u671f: 거래 날짜 +\u4ea4\u6613\u65f6\u95f4: 거래 시간 +\u4f1a\u8bdd\u6587\u4ef6\u540d: 세션 파일명 +\u4f9b\u5e94\u5546id: 공급업체 ID +\u5176\u4ed6token\u4ef7\u683c: 기타 Token 가격 +\u5176\u4ed6tokens\u6d88\u8d39\u6570: 기타 Tokens 소비량 +\u51fd\u6570\u540d: 함수명 +\u54cd\u5e94\u65f6\u95f4: 응답 시간 +\u5b8c\u6210\u65f6\u95f4: 완료 시간 +\u5ba2\u6237id: 고객 ID +\u5bc6\u7801: 비밀번호 +\u624b\u673a: 휴대폰 +\u6a21\u578b\u5b9e\u4f8bid: 모델 인스턴스 ID +\u6a21\u578b\u7c7b\u578bid: 모델 유형 ID +\u7528\u6237\u540d: 사용자명 +\u7528\u6237id: 사용자 ID +\u8ba1\u6b21\u4ef7\u683c: 회차 가격 +\u8ba1\u6b21\u91d1\u989d: 회차 금액 +\u8ba1\u8d39\u6a21\u5f0f: 과금 모드 +\u8ba1\u8d39token\u6570\u91cf: 과금 Token 수량 +\u8bb0\u8d26\u72b6\u6001: 기장 상태 +\u8bc4\u4ef7: 평가 +\u8f93\u5165token\u4ef7\u683c: 입력 Token 가격 +\u8f93\u5165token\u6d88\u8d39\u6570: 입력 Token 소비량 +\u8f93\u5165token\u91d1\u989d: 입력 Token 금액 +\u8f93\u51fatoken\u4ef7\u683c: 출력 Token 가격 +\u8f93\u51fatoken\u6d88\u8d39\u6570: 출력 Token 소비량 +\u8f93\u51fatoken\u91d1\u989d: 출력 Token 금액 +\u90ae\u4ef6\u5730\u5740: 이메일 주소 +\u9644\u5c5e\u5bc6\u94a5: 부속 키 +api\u5bc6\u94a5: API 비밀키 +api密码: API 비밀번호 +api密钥: API 비밀키 +api用户: API 사용자 +failed: 실패 +http程序接口: HTTP 프로그램 인터페이스 +id: ID +io数据id: IO 데이터 ID +logout success: 로그아웃 성공 +minimax账单: MiniMax 청구서 +minimax账号: MiniMax 계정 +minimax账号id: MiniMax 계정 ID +ok: 확인 +system error: 시스템 오류 +token使用表: Token 사용 테이블 +token数量: Token 수량 +token每天统计: Token 일일 통계 +token消耗量Top5: Token 소비량 Top5 +user name or password error: 사용자명 또는 비밀번호 오류 +user register: 사용자 등록 + 角色: 역할 +© 2024 版权所有, 开元云(北京)科技有限公司: © 2024 모든 권리 보유, 카이위안윈(베이징) 기술 유한공사 +上位系统: 상위 시스템 +上位系统管理: 상위 시스템 관리 +下位系统接口: 하위 시스템 인터페이스 +主营业务描述: 주요 업무 설명 +主页: 홈 +交易日期: 거래 날짜 +交易时间: 거래 시간 +产品管理: 제품 관리 +产品类别管理: 제품 카테고리 관리 +产品类型管理: 제품 유형 관리 +产品类型规格: 제품 유형 사양 +代客充值: 대리 충전 +代理: 에이전트 +仪表盘: 대시보드 +会计分录配置: 회계 분개 설정 +会话文件名: 세션 파일명 +余额与充值: 잔액 및 충전 +使用日期: 사용 날짜 +使用时间: 사용 시간 +供应协议: 공급 계약 +供应商id: 공급업체 ID +供应商充值: 공급업체 충전 +供应商名: 공급업체명 +供应商名称: 공급업체 명칭 +供应商对账: 공급업체 대조 +供应商明细对账: 공급업체 세부 대조 +供应商模型列表: 공급업체 모델 목록 +供应商管理: 공급업체 관리 +供应商结算: 공급업체 정산 +供应商财务: 공급업체 재무 +供应链管理: 공급망 관리 +供销协议管理: 공급 판매 계약 관리 +信用额度: 신용 한도 +值: 값 +元境平台: 위안징 플랫폼 +充值: 충전 +关于我们: 회사 소개 +其他tokens: 기타 Tokens +其他价格: 기타 가격 +其他金额: 기타 금액 +函数名: 함수명 +分销协议: 유통 계약 +分销协议管理: 유통 계약 관리 +分销商对账: 유통업체 대조 +分销商管理: 유통업체 관리 +分销商结算: 유통업체 정산 +创建时间: 생성 시간 +创建时间戳: 생성 타임스탬프 +删除标志: 삭제 플래그 +刷新权限缓存: 권한 캐시 새로고침 +单模型对话: 단일 모델 대화 +参与方科目配置: 참여자 계정 설정 +发送验证码: 인증 코드 전송 +名称: 명칭 +启动日期: 시작 날짜 +命令: 명령 +响应时间: 응답 시간 +响应模式: 응답 모드 +图标: 아이콘 +在响应包中的位置: 응답 패키지 내 위치 +地址: 주소 +多模型对话: 멀티 모델 대화 +多级标志: 다단계 플래그 +大模型: 대규모 모델 +大模型API调用: 대규모 모델 API 호출 +大模型费用: 대규모 모델 비용 +大模型费用W: 대규모 모델 비용 W +失效日期: 만료 날짜 +姓名: 성명 +完成时间: 완료 시간 +定价管理: 가격 관리 +实例名: 인스턴스명 +实例名称: 인스턴스 명칭 +实例说明: 인스턴스 설명 +客户id: 고객 ID +客户信用额度: 고객 신용 한도 +密码: 비밀번호 +小数点数: 소수점 자릿수 +属主id: 소유자 ID +帐务: 회계 +带历史信息: 이력 정보 포함 +应用: 애플리케이션 +应用编码表: 애플리케이션 코드 테이블 +开始日期: 시작 날짜 +开帐: 계좌 개설 +微信: 위챗 +性能最优Top5: 성능 최적 Top5 +我: 나 +我的订单: 내 주문 +我的账单: 내 청구서 +我的账户: 내 계정 +我的资源: 내 리소스 +所在地区id: 소재 지역 ID +所在城市id: 소재 도시 ID +所在省id: 소재 성 ID +所属机构: 소속 기관 +手机: 휴대폰 +手机号: 휴대폰 번호 +手机验证码: 휴대폰 인증 코드 +扫描未授权文件: 미인가 파일 스캔 +接口id: 인터페이스 ID +接口ur: 인터페이스 URL +接口内容: 인터페이스 내용 +接口参数: 인터페이스 매개변수 +接口名: 인터페이스명 +接口名称: 인터페이스 명칭 +接口描述: 인터페이스 설명 +接口提供方: 인터페이스 제공자 +接口输入输出: 인터페이스 입출력 +接口集: 인터페이스 세트 +推理: 추론 +描述: 설명 +提示词: 프롬프트 +数据IO: 데이터 IO +数据值: 데이터 값 +数据名: 데이터명 +数据看板: 데이터 대시보드 +数据类型: 데이터 유형 +明细对账: 세부 대조 +是否多模态: 멀티모달 여부 +是否必须: 필수 여부 +显示名: 표시명 +智普: 즈푸 +智能体: AI 에이전트 +月之暗面: 문샷 +服务目录: 서비스 카탈로그 +服务管理: 서비스 관리 +机构: 기관 +机构id: 기관 ID +机构别名: 기관 별칭 +机构名称: 기관 명칭 +机构拥有角色: 기관 보유 역할 +机构类型: 기관 유형 +机构编码: 기관 코드 +机构角色: 기관 역할 +权限: 권한 +权限id: 권한 ID +权限管理: 권한 관리 +查询路径权限角色: 조회 경로 권한 역할 +标题: 제목 +模型: 모델 +模型id: 모델 ID +模型供应商: 모델 공급업체 +模型列表: 모델 목록 +模型名称: 모델 명칭 +模型图标URL: 모델 아이콘 URL +模型实例: 모델 인스턴스 +模型实例id: 모델 인스턴스 ID +模型广场: 모델 마켓플레이스 +模型或实例id: 모델 또는 인스턴스 ID +模型接口: 모델 인터페이스 +模型消息模版: 모델 메시지 템플릿 +模型用量: 모델 사용량 +模型管理: 모델 관리 +模型类型: 모델 유형 +模型类型id: 모델 유형 ID +模型类型输入数据: 모델 유형 입력 데이터 +模型类型输出数据: 모델 유형 출력 데이터 +模型计费: 모델 과금 +模型计费日志: 모델 과금 로그 +模型说明: 모델 설명 +模型调优: 모델 튜닝 +模型输入输出数据: 모델 입출력 데이터 +消费token数: 소비 Token 수 +消费日期: 소비 날짜 +消费时间戳: 소비 타임스탬프 +消费金额: 소비 금액 +添加供应商: 공급업체 추가 +添加管理员: 관리자 추가 +父id: 부모 ID +父数据id: 부모 데이터 ID +父机构id: 부모 기관 ID +父权限id: 부모 권한 ID +用户: 사용자 +用户api密码表: 사용자 API 비밀번호 테이블 +用户id: 사용자 ID +用户名: 사용자명 +用户密码: 사용자 비밀번호 +用户消息模版: 사용자 메시지 템플릿 +用户状态: 사용자 상태 +用户管理: 사용자 관리 +用户角色: 사용자 역할 +用户部门表: 사용자 부서 테이블 +百川: 바이촨 +百度千帆: 바이두 치안판 +真人素材: 실사 소재 +私有知识库: 개인 지식 베이스 +科目设置: 계정 설정 +科目配置: 계정 구성 +签退: 로그아웃 +类型: 유형 +类型名: 유형명 +类型说明: 유형 설명 +系统参数管理: 시스템 매개변수 관리 +系统日志: 시스템 로그 +系统权限管理: 시스템 권한 관리 +系统消息模版: 시스템 메시지 템플릿 +系统管理: 시스템 관리 +组号: 그룹 번호 +组织结构代码: 조직 구조 코드 +终端: 터미널 +终端名称: 터미널명 +结束日期: 종료 날짜 +编码名称: 코드 명칭 +编码键值表: 코드 키-값 테이블 +联系人: 연락처 +联系人电话: 연락처 전화 +英文名: 영문명 +营业执照: 사업자 등록증 +角色: 역할 +角色id: 역할 ID +角色名称: 역할 명칭 +角色权限管理: 역할 권한 관리 +角色权限表: 역할 권한 테이블 +角色管理: 역할 관리 +角色编码: 역할 코드 +计次价格: 회차 가격 +计次金额: 회차 금액 +计费模式: 과금 모드 +计费类型: 과금 유형 +记账失败记录: 기장 실패 기록 +记账状态: 기장 상태 +设备组: 디바이스 그룹 +评价: 평가 +评价最高Top5: 최고 평가 Top5 +说明: 설명 +调用名: 호출명 +调用数量Top5: 호출 수량 Top5 +豆包: 더우바오 +财务处理: 재무 처리 +账务中心: 회계 센터 +账务设置: 회계 설정 +账务配置: 회계 구성 +账单查询: 청구서 조회 +账号: 계정 +账号apikey: 계정 API 키 +账号名称: 계정 명칭 +账号密码: 계정 비밀번호 +账号状态: 계정 상태 +费用记录: 비용 기록 +路径: 경로 +身份证: 신분증 +输入tokens: 입력 Tokens +输入token数: 입력 Token 수 +输入价格: 입력 가격 +输入字段: 입력 필드 +输入显示: 입력 표시 +输入类型: 입력 유형 +输入金额: 입력 금액 +输出tokens: 출력 Tokens +输出token数: 출력 Token 수 +输出价格: 출력 가격 +输出显示: 출력 표시 +输出金额: 출력 금액 +运营商配置: 운영자 구성 +通义千问: 퉁이 치엔원 +邮件地址: 이메일 주소 +邮箱: 이메일 +部门id: 부서 ID +配置账务: 회계 구성 +重置密码: 비밀번호 재설정 +错帐处理: 오기장 처리 +键: 키 +长度: 길이 +附属密钥: 부속 키 diff --git a/i18n/zh/msg.txt b/i18n/zh/msg.txt new file mode 100644 index 00000000..665b6331 --- /dev/null +++ b/i18n/zh/msg.txt @@ -0,0 +1,341 @@ +API: API +API Key管理: API Key管理 +Add Error: Add Error +Add Success: Add Success +Cancel: Cancel +Conform: Conform +DeepSeek: DeepSeek +Delete Error: Delete Error +Delete Success: Delete Success +Discard: Discard +Error: Error +LocalOllama: LocalOllama +Login: Login +Login Error: Login Error +Message: Message +MiniMax: MiniMax +RBAC工具: RBAC工具 +Reset: Reset +Reset Password: Reset Password +Submit: Submit +Token交易记录: Token交易记录 +Update Error: Update Error +Update Success: Update Success +Welcome back: Welcome back +\u4ea4\u6613\u65e5\u671f: \u4ea4\u6613\u65e5\u671f +\u4ea4\u6613\u65f6\u95f4: \u4ea4\u6613\u65f6\u95f4 +\u4f1a\u8bdd\u6587\u4ef6\u540d: \u4f1a\u8bdd\u6587\u4ef6\u540d +\u4f9b\u5e94\u5546id: \u4f9b\u5e94\u5546id +\u5176\u4ed6token\u4ef7\u683c: \u5176\u4ed6token\u4ef7\u683c +\u5176\u4ed6tokens\u6d88\u8d39\u6570: \u5176\u4ed6tokens\u6d88\u8d39\u6570 +\u51fd\u6570\u540d: \u51fd\u6570\u540d +\u54cd\u5e94\u65f6\u95f4: \u54cd\u5e94\u65f6\u95f4 +\u5b8c\u6210\u65f6\u95f4: \u5b8c\u6210\u65f6\u95f4 +\u5ba2\u6237id: \u5ba2\u6237id +\u5bc6\u7801: \u5bc6\u7801 +\u624b\u673a: \u624b\u673a +\u6a21\u578b\u5b9e\u4f8bid: \u6a21\u578b\u5b9e\u4f8bid +\u6a21\u578b\u7c7b\u578bid: \u6a21\u578b\u7c7b\u578bid +\u7528\u6237\u540d: \u7528\u6237\u540d +\u7528\u6237id: \u7528\u6237id +\u8ba1\u6b21\u4ef7\u683c: \u8ba1\u6b21\u4ef7\u683c +\u8ba1\u6b21\u91d1\u989d: \u8ba1\u6b21\u91d1\u989d +\u8ba1\u8d39\u6a21\u5f0f: \u8ba1\u8d39\u6a21\u5f0f +\u8ba1\u8d39token\u6570\u91cf: \u8ba1\u8d39token\u6570\u91cf +\u8bb0\u8d26\u72b6\u6001: \u8bb0\u8d26\u72b6\u6001 +\u8bc4\u4ef7: \u8bc4\u4ef7 +\u8f93\u5165token\u4ef7\u683c: \u8f93\u5165token\u4ef7\u683c +\u8f93\u5165token\u6d88\u8d39\u6570: \u8f93\u5165token\u6d88\u8d39\u6570 +\u8f93\u5165token\u91d1\u989d: \u8f93\u5165token\u91d1\u989d +\u8f93\u51fatoken\u4ef7\u683c: \u8f93\u51fatoken\u4ef7\u683c +\u8f93\u51fatoken\u6d88\u8d39\u6570: \u8f93\u51fatoken\u6d88\u8d39\u6570 +\u8f93\u51fatoken\u91d1\u989d: \u8f93\u51fatoken\u91d1\u989d +\u90ae\u4ef6\u5730\u5740: \u90ae\u4ef6\u5730\u5740 +\u9644\u5c5e\u5bc6\u94a5: \u9644\u5c5e\u5bc6\u94a5 +api\u5bc6\u94a5: api\u5bc6\u94a5 +api密码: api密码 +api密钥: api密钥 +api用户: api用户 +failed: failed +http程序接口: http程序接口 +id: id +io数据id: io数据id +logout success: logout success +minimax账单: minimax账单 +minimax账号: minimax账号 +minimax账号id: minimax账号id +ok: ok +system error: system error +token使用表: token使用表 +token数量: token数量 +token每天统计: token每天统计 +token消耗量Top5: token消耗量Top5 +user name or password error: user name or password error +user register: user register + 角色:  角色 +© 2024 版权所有, 开元云(北京)科技有限公司: © 2024 版权所有, 开元云(北京)科技有限公司 +上位系统: 上位系统 +上位系统管理: 上位系统管理 +下位系统接口: 下位系统接口 +主营业务描述: 主营业务描述 +主页: 主页 +交易日期: 交易日期 +交易时间: 交易时间 +产品管理: 产品管理 +产品类别管理: 产品类别管理 +产品类型管理: 产品类型管理 +产品类型规格: 产品类型规格 +代客充值: 代客充值 +代理: 代理 +仪表盘: 仪表盘 +会计分录配置: 会计分录配置 +会话文件名: 会话文件名 +余额与充值: 余额与充值 +使用日期: 使用日期 +使用时间: 使用时间 +供应协议: 供应协议 +供应商id: 供应商id +供应商充值: 供应商充值 +供应商名: 供应商名 +供应商名称: 供应商名称 +供应商对账: 供应商对账 +供应商明细对账: 供应商明细对账 +供应商模型列表: 供应商模型列表 +供应商管理: 供应商管理 +供应商结算: 供应商结算 +供应商财务: 供应商财务 +供应链管理: 供应链管理 +供销协议管理: 供销协议管理 +信用额度: 信用额度 +值: 值 +元境平台: 元境平台 +充值: 充值 +关于我们: 关于我们 +其他tokens: 其他tokens +其他价格: 其他价格 +其他金额: 其他金额 +函数名: 函数名 +分销协议: 分销协议 +分销协议管理: 分销协议管理 +分销商对账: 分销商对账 +分销商管理: 分销商管理 +分销商结算: 分销商结算 +创建时间: 创建时间 +创建时间戳: 创建时间戳 +删除标志: 删除标志 +刷新权限缓存: 刷新权限缓存 +单模型对话: 单模型对话 +参与方科目配置: 参与方科目配置 +发送验证码: 发送验证码 +名称: 名称 +启动日期: 启动日期 +命令: 命令 +响应时间: 响应时间 +响应模式: 响应模式 +图标: 图标 +在响应包中的位置: 在响应包中的位置 +地址: 地址 +多模型对话: 多模型对话 +多级标志: 多级标志 +大模型: 大模型 +大模型API调用: 大模型API调用 +大模型费用: 大模型费用 +大模型费用W: 大模型费用W +失效日期: 失效日期 +姓名: 姓名 +完成时间: 完成时间 +定价管理: 定价管理 +实例名: 实例名 +实例名称: 实例名称 +实例说明: 实例说明 +客户id: 客户id +客户信用额度: 客户信用额度 +密码: 密码 +小数点数: 小数点数 +属主id: 属主id +帐务: 帐务 +带历史信息: 带历史信息 +应用: 应用 +应用编码表: 应用编码表 +开始日期: 开始日期 +开帐: 开帐 +微信: 微信 +性能最优Top5: 性能最优Top5 +我: 我 +我的订单: 我的订单 +我的账单: 我的账单 +我的账户: 我的账户 +我的资源: 我的资源 +所在地区id: 所在地区id +所在城市id: 所在城市id +所在省id: 所在省id +所属机构: 所属机构 +手机: 手机 +手机号: 手机号 +手机验证码: 手机验证码 +扫描未授权文件: 扫描未授权文件 +接口id: 接口id +接口ur: 接口ur +接口内容: 接口内容 +接口参数: 接口参数 +接口名: 接口名 +接口名称: 接口名称 +接口描述: 接口描述 +接口提供方: 接口提供方 +接口输入输出: 接口输入输出 +接口集: 接口集 +推理: 推理 +描述: 描述 +提示词: 提示词 +数据IO: 数据IO +数据值: 数据值 +数据名: 数据名 +数据看板: 数据看板 +数据类型: 数据类型 +明细对账: 明细对账 +是否多模态: 是否多模态 +是否必须: 是否必须 +显示名: 显示名 +智普: 智普 +智能体: 智能体 +月之暗面: 月之暗面 +服务目录: 服务目录 +服务管理: 服务管理 +机构: 机构 +机构id: 机构id +机构别名: 机构别名 +机构名称: 机构名称 +机构拥有角色: 机构拥有角色 +机构类型: 机构类型 +机构编码: 机构编码 +机构角色: 机构角色 +权限: 权限 +权限id: 权限id +权限管理: 权限管理 +查询路径权限角色: 查询路径权限角色 +标题: 标题 +模型: 模型 +模型id: 模型id +模型供应商: 模型供应商 +模型列表: 模型列表 +模型名称: 模型名称 +模型图标URL: 模型图标URL +模型实例: 模型实例 +模型实例id: 模型实例id +模型广场: 模型广场 +模型或实例id: 模型或实例id +模型接口: 模型接口 +模型消息模版: 模型消息模版 +模型用量: 模型用量 +模型管理: 模型管理 +模型类型: 模型类型 +模型类型id: 模型类型id +模型类型输入数据: 模型类型输入数据 +模型类型输出数据: 模型类型输出数据 +模型计费: 模型计费 +模型计费日志: 模型计费日志 +模型说明: 模型说明 +模型调优: 模型调优 +模型输入输出数据: 模型输入输出数据 +消费token数: 消费token数 +消费日期: 消费日期 +消费时间戳: 消费时间戳 +消费金额: 消费金额 +添加供应商: 添加供应商 +添加管理员: 添加管理员 +父id: 父id +父数据id: 父数据id +父机构id: 父机构id +父权限id: 父权限id +用户: 用户 +用户api密码表: 用户api密码表 +用户id: 用户id +用户名: 用户名 +用户密码: 用户密码 +用户消息模版: 用户消息模版 +用户状态: 用户状态 +用户管理: 用户管理 +用户角色: 用户角色 +用户部门表: 用户部门表 +百川: 百川 +百度千帆: 百度千帆 +真人素材: 真人素材 +私有知识库: 私有知识库 +科目设置: 科目设置 +科目配置: 科目配置 +签退: 签退 +类型: 类型 +类型名: 类型名 +类型说明: 类型说明 +系统参数管理: 系统参数管理 +系统日志: 系统日志 +系统权限管理: 系统权限管理 +系统消息模版: 系统消息模版 +系统管理: 系统管理 +组号: 组号 +组织结构代码: 组织结构代码 +终端: 终端 +终端名称: 终端名称 +结束日期: 结束日期 +编码名称: 编码名称 +编码键值表: 编码键值表 +联系人: 联系人 +联系人电话: 联系人电话 +英文名: 英文名 +营业执照: 营业执照 +角色: 角色 +角色id: 角色id +角色名称: 角色名称 +角色权限管理: 角色权限管理 +角色权限表: 角色权限表 +角色管理: 角色管理 +角色编码: 角色编码 +计次价格: 计次价格 +计次金额: 计次金额 +计费模式: 计费模式 +计费类型: 计费类型 +记账失败记录: 记账失败记录 +记账状态: 记账状态 +设备组: 设备组 +评价: 评价 +评价最高Top5: 评价最高Top5 +说明: 说明 +调用名: 调用名 +调用数量Top5: 调用数量Top5 +豆包: 豆包 +财务处理: 财务处理 +账务中心: 账务中心 +账务设置: 账务设置 +账务配置: 账务配置 +账单查询: 账单查询 +账号: 账号 +账号apikey: 账号apikey +账号名称: 账号名称 +账号密码: 账号密码 +账号状态: 账号状态 +费用记录: 费用记录 +路径: 路径 +身份证: 身份证 +输入tokens: 输入tokens +输入token数: 输入token数 +输入价格: 输入价格 +输入字段: 输入字段 +输入显示: 输入显示 +输入类型: 输入类型 +输入金额: 输入金额 +输出tokens: 输出tokens +输出token数: 输出token数 +输出价格: 输出价格 +输出显示: 输出显示 +输出金额: 输出金额 +运营商配置: 运营商配置 +通义千问: 通义千问 +邮件地址: 邮件地址 +邮箱: 邮箱 +部门id: 部门id +配置账务: 配置账务 +重置密码: 重置密码 +错帐处理: 错帐处理 +键: 键 +长度: 长度 +附属密钥: 附属密钥 diff --git a/import_codes.py b/import_codes.py new file mode 100644 index 00000000..3bd99278 --- /dev/null +++ b/import_codes.py @@ -0,0 +1,138 @@ +#!/usr/bin/env python3 +""" +导入 init/data.json 中的 appcodes / appcodes_kv 编码字典到 sage 数据库。 + +用法: + cd ~/repos/sage + py3/bin/python import_codes.py ../supplychain/init/data.json + py3/bin/python import_codes.py ../product_management/init/data.json ../supplychain/init/data.json +""" +import sys +import json +import os +import asyncio +import argparse + +# 修正 venv site-packages 路径(venv 可能是旧版 Python 创建的) +_script_dir = os.path.dirname(os.path.abspath(__file__)) +_venv_lib = os.path.join(_script_dir, 'py3', 'lib') +if os.path.isdir(_venv_lib): + for _d in os.listdir(_venv_lib): + _sp = os.path.join(_venv_lib, _d, 'site-packages') + if os.path.isdir(_sp) and _sp not in sys.path: + sys.path.insert(0, _sp) + +# 添加本地依赖路径(editable install 可能指向 Docker 路径) +_repos_dir = os.path.dirname(_script_dir) +for _dep in ['apppublic', 'sqlor']: + _dep_dir = os.path.join(_repos_dir, _dep) + if os.path.isdir(_dep_dir) and _dep_dir not in sys.path: + sys.path.insert(0, _dep_dir) + +from appPublic.jsonConfig import getConfig +from sqlor.dbpools import DBPools + + +async def import_data_json(sor, filepath): + """将单个 data.json 中的 appcodes 和 appcodes_kv 导入数据库""" + with open(filepath, 'r', encoding='utf-8') as f: + data = json.load(f) + + # 导入 appcodes — 支持两种格式: + # 格式1: [{"id":..., "name":..., "hierarchy_flg":...}] + # 格式2: [{"parentid":..., "parentname":..., "items":[...]}] + appcodes = data.get('appcodes', []) + codes_count = 0 + kv_count = 0 + + for item in appcodes: + # 格式2: parentid/parentname + 内嵌 items + if 'parentid' in item and 'items' in item: + parentid = item['parentid'] + parentname = item.get('parentname', parentid) + await sor.sqlExe(""" + INSERT INTO appcodes (id, name, hierarchy_flg) + VALUES (${id}$, ${name}$, ${hierarchy_flg}$) + ON DUPLICATE KEY UPDATE name=VALUES(name), hierarchy_flg=VALUES(hierarchy_flg) + """, { + 'id': parentid, + 'name': parentname, + 'hierarchy_flg': item.get('hierarchy_flg', '0') + }) + codes_count += 1 + # 导入内嵌的 kv 条目 + for kv_item in item.get('items', []): + kv_id = f"{parentid}_{kv_item['k']}" + await sor.sqlExe(""" + INSERT INTO appcodes_kv (id, parentid, k, v) + VALUES (${id}$, ${parentid}$, ${k}$, ${v}$) + ON DUPLICATE KEY UPDATE id=VALUES(id), v=VALUES(v) + """, { + 'id': kv_id, + 'parentid': parentid, + 'k': kv_item['k'], + 'v': kv_item['v'] + }) + kv_count += 1 + # 格式1: 标准 id/name + elif 'id' in item: + await sor.sqlExe(""" + INSERT INTO appcodes (id, name, hierarchy_flg) + VALUES (${id}$, ${name}$, ${hierarchy_flg}$) + ON DUPLICATE KEY UPDATE name=VALUES(name), hierarchy_flg=VALUES(hierarchy_flg) + """, { + 'id': item['id'], + 'name': item['name'], + 'hierarchy_flg': item.get('hierarchy_flg', '0') + }) + codes_count += 1 + + print(f" appcodes: {codes_count} 条") + + # 导入独立 appcodes_kv (格式1兼容) + appcodes_kv = data.get('appcodes_kv', []) + for item in appcodes_kv: + await sor.sqlExe(""" + INSERT INTO appcodes_kv (id, parentid, k, v) + VALUES (${id}$, ${parentid}$, ${k}$, ${v}$) + ON DUPLICATE KEY UPDATE id=VALUES(id), v=VALUES(v) + """, { + 'id': item['id'], + 'parentid': item['parentid'], + 'k': item['k'], + 'v': item['v'] + }) + kv_count += 1 + if appcodes_kv: + print(f" appcodes_kv: {len(appcodes_kv)} 条 (独立)") + + print(f" appcodes_kv: {kv_count} 条 (合计)") + return codes_count, kv_count + + +async def main(): + parser = argparse.ArgumentParser(description='导入编码字典到 sage 数据库') + parser.add_argument('files', nargs='+', help='init/data.json 文件路径') + args = parser.parse_args() + + # 使用 getConfig() 获取配置,DBPools 初始化数据库池 + config = getConfig('.') + db = DBPools(config.databases) + + print(f"连接数据库: sage") + + total_codes = 0 + total_kv = 0 + + async with db.sqlorContext('sage') as sor: + for filepath in args.files: + print(f"导入: {filepath}") + c, kv = await import_data_json(sor, filepath) + total_codes += c + total_kv += kv + + print(f"\n完成! 共导入 appcodes: {total_codes} 条, appcodes_kv: {total_kv} 条") + + +if __name__ == '__main__': + asyncio.run(main()) diff --git a/json/accounting_config.json b/json/accounting_config.json index 72d168f5..654379dc 100644 --- a/json/accounting_config.json +++ b/json/accounting_config.json @@ -1,6 +1,6 @@ { "models_dir": "${HOME}$/py/accounting/models", - "output_dir": "${HOME}$/py/sage/wwwroot/_a/accounting_config", + "output_dir": "${HOME}$/py/accounting/wwwroot/accounting_config", "dbname": "sage", "tblname": "accounting_config", "params": { diff --git a/json/build.sh b/json/build.sh new file mode 100755 index 00000000..0a87fe35 --- /dev/null +++ b/json/build.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +xls2ui -m ../models -o ../wwwroot sage *.json diff --git a/json/subject.json b/json/subject.json index 40b59823..1b5044d4 100644 --- a/json/subject.json +++ b/json/subject.json @@ -1,6 +1,6 @@ { "models_dir": "${HOME}$/py/accounting/models", - "output_dir": "${HOME}$/py/sage/wwwroot/_a/subject", + "output_dir": "${HOME}$/py/accounting/wwwroot/subject", "dbname": "sage", "tblname": "subject", "params": { diff --git a/load_path.py b/load_path.py index b846951d..ea027855 100644 --- a/load_path.py +++ b/load_path.py @@ -8,6 +8,8 @@ paths="""/ any /favicon.ico any /top.ui any /i18n_getmsgs any +/tenant any +/tenant/index.ui any /uapi logined /uapi/uapi logined /uapi/uapi/delete_uapi.dspy logined @@ -42,6 +44,8 @@ paths="""/ any /uapi/uapiset/index.ui logined /uapi/uapiset/delete_uapiset.dspy logined /uapi/menu.ui any +/uapi/copy_uapi.ui logined +/uapi/api/copy_uapi.dspy logined /llmage logined /llmage/llmcost.dspy logined /llmage/menu.ui any @@ -49,6 +53,11 @@ paths="""/ any /llmage/llm_dialog.ui logined /llmage/show_same_catelog_llm.ui logined /llmage/model_estimate.dspy logined +/llmage/model_plaza.ui logined +/llmage/plaza_model_cards.ui logined +/llmage/api/get_plaza_models.dspy logined +/llmage/api/plaza_categories.dspy logined +/llmage/api/plaza_providers.dspy logined /llmage/show_llms.ui logined /llmage/llmusage logined /llmage/llmusage/update_llmusage.dspy logined @@ -56,7 +65,24 @@ paths="""/ any /llmage/llmusage/add_llmusage.dspy logined /llmage/llmusage/index.ui logined /llmage/llmusage/get_llmusage.dspy logined +/llmage/llm_metrics logined +/llmage/llm_metrics/get_llm_metrics.dspy logined +/llmage/llm_metrics/index.ui logined +/llmage/user_llm_policy logined +/llmage/user_llm_policy/get_user_llm_policy.dspy logined +/llmage/user_llm_policy/add_user_llm_policy.dspy logined +/llmage/user_llm_policy/update_user_llm_policy.dspy logined +/llmage/user_llm_policy/delete_user_llm_policy.dspy logined +/llmage/user_llm_policy/index.ui logined /llmage/llmcheck.dspy logined +/llmage/check_model_record.dspy logined +/llmage/check_date_status.dspy logined +/llmage/check_upapp.dspy logined +/llmage/check_uapi.dspy logined +/llmage/check_uapiio.dspy logined +/llmage/check_llm_api_map.dspy logined +/llmage/check_pricing_program.dspy logined +/llmage/check_pricing_data.dspy logined /llmage/imgs any /llmage/imgs/kdb.svg any /llmage/list_catelog_models.dspy any @@ -74,6 +100,18 @@ paths="""/ any /llmage/llm/add_llm.dspy logined /llmage/show_llms_by_providers.ui logined /llmage/list_paging_catelog_llms.dspy logined +/llmage/v1/chat/completions logined +/llmage/v1/chat/completions/index.dspy logined +/llmage/v1/models logined +/llmage/v1/models/index.dspy logined +/llmage/v1/tasks logined +/llmage/v1/tasks/index.dspy logined +/llmage/v1/video/generations logined +/llmage/v1/video/generations/index.dspy logined +/llmage/v1/image/generations logined +/llmage/v1/image/generations/index.dspy logined +/llmage/v1/pricing logined +/llmage/v1/pricing/index.dspy logined /public any /public/mainpage any /public/mainpage/wish.webp any @@ -118,6 +156,56 @@ paths="""/ any /public/llmsquare/statistic/total_usage.dspy any /public/about any /public/about/index_zh.md any + +# sage_datamart +/sage_datamart logined +/sage_datamart/index.ui logined +/sage_datamart/menu.ui any +/sage_datamart/api/currency_stats.dspy logined +/sage_datamart/api/customer_models.dspy logined +/sage_datamart/api/daily_trend.dspy logined +/sage_datamart/api/distributor_currency.dspy logined +/sage_datamart/api/distributor_customers.dspy logined +/sage_datamart/api/distributor_financial.dspy logined +/sage_datamart/api/financial_chart.dspy logined +/sage_datamart/api/financial_summary.dspy logined +/sage_datamart/api/hourly_concurrency.dspy logined +/sage_datamart/api/model_perf.dspy logined +/sage_datamart/api/provider_roi.dspy logined +/sage_datamart/api/realtime_cards.dspy logined +/sage_datamart/api/stats.dspy logined +/sage_datamart/api/top_models.dspy logined +/sage_datamart/api/top_providers.dspy logined +/sage_datamart/api/top_users.dspy logined +/sage_datamart/api/user_apikeys.dspy logined +/sage_datamart/cron/etl_aggregate.dspy logined +/sage_datamart/cron/etl_provider_cost.dspy logined +/sage_datamart/cron/etl_sync.dspy logined +/sage_datamart/provider_roi.ui logined +/sage_datamart/rt_card_active.ui logined +/sage_datamart/rt_card_amount.ui logined +/sage_datamart/rt_card_calls.ui logined +/sage_datamart/rt_card_fail.ui logined +/sage_datamart/rt_card_online.ui logined +/sage_datamart/rt_card_success.ui logined +/sage_datamart/rt_card_users.ui logined +/sage_datamart/sect_currency.ui logined +/sage_datamart/sect_customer_currency.ui logined +/sage_datamart/sect_distributor_currency.ui logined +/sage_datamart/sect_distributor_financial.ui logined +/sage_datamart/sect_model_perf.ui logined +/sage_datamart/sect_provider_roi.ui logined +/sage_datamart/sect_top_models.ui logined +/sage_datamart/sect_top_providers.ui logined +/sage_datamart/sect_top_users.ui logined +/sage_datamart/sect_user_apikeys.ui logined +/sage_datamart/stat_avg_ttft.ui logined +/sage_datamart/stat_fail_calls.ui logined +/sage_datamart/stat_success_rate.ui logined +/sage_datamart/stat_today_amount.ui logined +/sage_datamart/stat_today_usage.ui logined +/sage_datamart/stat_total_calls.ui logined +/sage_datamart/stat_total_users.ui logined /public/about/index.md any /public/about/index.ui any /public/about/index_en.md any @@ -478,7 +566,18 @@ paths="""/ any /bricks/bricks.js any /bricks/css any /bricks/css/bricks.css any +/bricks/css/api_doc.css any +/dashboard_for_sage logined +/dashboard_for_sage/index.ui logined +/dashboard_for_sage/menu.ui any +/dashboard_for_sage/today_usage.ui logined +/dashboard_for_sage/today_amount.ui logined +/dashboard_for_sage/total_users.ui logined +/dashboard_for_sage/concurrent_users.ui logined +/dashboard_for_sage/accounting_errors.ui logined +/dashboard_for_sage/top_models_chart.ui logined /accounting logined +/accounting/index.ui logined /accounting/mybalance.dspy logined /accounting/open_reseller_provider_accounts.dspy logined /accounting/open_owner_accounts.dspy logined @@ -506,6 +605,19 @@ paths="""/ any /accounting/subject/index.ui logined /accounting/account_config logined /accounting/account_config/update_account_config.dspy logined +/accounting/credit_limit logined +/accounting/credit_limit/credit_manage.ui logined +/accounting/credit_limit/credit_overview.ui logined +/accounting/credit_limit/hub.ui logined +/accounting/credit_limit/index.ui logined +/accounting/credit_limit/get_credit_limit.dspy logined +/accounting/credit_limit/add_credit_limit.dspy logined +/accounting/credit_limit/update_credit_limit.dspy logined +/accounting/credit_limit/delete_credit_limit.dspy logined +/accounting/credit_limit/api logined +/accounting/credit_limit/api/set_credit_form.ui logined +/accounting/credit_limit/api/set_customer_credit.dspy logined +/accounting/credit_limit/api/credit_summary.dspy logined /accounting/account_config/get_account_config.dspy logined /accounting/account_config/index.ui logined /accounting/account_config/add_account_config.dspy logined @@ -537,6 +649,61 @@ paths="""/ any /accounting/acc_detail/index.ui logined /accounting/acc_detail/get_acc_detail.dspy logined /accounting/open_reseller_accounts.dspy logined +/cpcc logined +/cpcc/index.ui logined +/cpcc/menu.ui any +/cpcc/top.ui logined +/cpcc/bottom.ui logined +/cpcc/center.ui logined +/cpcc/app_panel.ui logined +/cpcc/components logined +/cpcc/components/index.ui logined +/cpcc/components/get_components.dspy logined +/cpcc/components/add_components.dspy logined +/cpcc/components/update_components.dspy logined +/cpcc/components/delete_components.dspy logined +/cpcc/cpccluster logined +/cpcc/cpccluster/index.ui logined +/cpcc/cpccluster/get_cpccluster.dspy logined +/cpcc/cpccluster/add_cpccluster.dspy logined +/cpcc/cpccluster/update_cpccluster.dspy logined +/cpcc/cpccluster/delete_cpccluster.dspy logined +/cpcc/cpclist logined +/cpcc/cpclist/index.ui logined +/cpcc/cpclist/get_cpclist.dspy logined +/cpcc/cpclist/add_cpclist.dspy logined +/cpcc/cpclist/update_cpclist.dspy logined +/cpcc/cpclist/delete_cpclist.dspy logined +/cpcc/cpcnode logined +/cpcc/cpcnode/index.ui logined +/cpcc/cpcnode/get_cpcnode.dspy logined +/cpcc/cpcnode/add_cpcnode.dspy logined +/cpcc/cpcnode/update_cpcnode.dspy logined +/cpcc/cpcnode/delete_cpcnode.dspy logined +/cpcc/cpcpod logined +/cpcc/cpcpod/index.ui logined +/cpcc/cpcpod/get_cpcpod.dspy logined +/cpcc/cpcpod/get_node_labels.dspy logined +/cpcc/cpcpod/new_cpcpodyaml.dspy logined +/cpcc/cpcpod/new_podyaml.ui logined +/cpcc/cpcpodyaml logined +/cpcc/cpcpodyaml/index.ui logined +/cpcc/cpcpodyaml/get_cpcpodyaml.dspy logined +/cpcc/cpcpodyaml/update_cpcpodyaml.dspy logined +/cpcc/cpcpodyaml/delete_cpcpodyaml.dspy logined +/cpcc/cpcworker logined +/cpcc/cpcworker/index.ui logined +/cpcc/cpcworker/get_cpcworker.dspy logined +/cpcc/cpcworker/get_availableworker.dspy logined +/cpcc/cpcworker/add_cpcworker.dspy logined +/cpcc/cpcworker/update_cpcworker.dspy logined +/cpcc/cpcworker/delete_cpcworker.dspy logined +/cpcc/cpcworker/new_cpcworker.dspy logined +/cpcc/cpcworker/new_worker.ui logined +/cpcc/handy logined +/cpcc/handy/get_cpcnodes.dspy logined +/cpcc/handy/new_cluster.dspy logined +/cpcc/handy/new_cluster.ui logined /appbase logined /appbase/menu.ui any /appbase/appcodes_kv owner.superuser @@ -569,6 +736,19 @@ paths="""/ any /appbase/svgicon/add_svgicon.dspy owner.superuser /appbase/svgicon/update_svgicon.dspy owner.superuser /appbase/svgicon/index.ui owner.superuser +/accounting/currency_list owner.superuser +/accounting/currency_list/index.ui owner.superuser +/accounting/currency_list/get_currency_list.dspy owner.superuser +/accounting/currency_list/add_currency_list.dspy owner.superuser +/accounting/currency_list/update_currency_list.dspy owner.superuser +/accounting/currency_list/delete_currency_list.dspy owner.superuser +/accounting/exchange_rate_list owner.superuser +/accounting/exchange_rate_list/index.ui owner.superuser +/accounting/exchange_rate_list/get_exchange_rate_list.dspy owner.superuser +/accounting/exchange_rate_list/add_exchange_rate_list.dspy owner.superuser +/accounting/exchange_rate_list/update_exchange_rate_list.dspy owner.superuser +/accounting/exchange_rate_list/delete_exchange_rate_list.dspy owner.superuser + /msp logined /msp/keypress.ui logined /msp/devgroup logined @@ -622,6 +802,7 @@ paths="""/ any /msp/mspcatelog/delete_mspcatelog.dspy logined /msp/mspcatelog/new_mspcatelog.dspy logined /pricing logined +/pricing/index.ui logined /pricing/pricing_program logined /pricing/pricing_program/add_pricing_program.dspy logined /pricing/pricing_program/index.ui logined @@ -642,6 +823,7 @@ paths="""/ any /pricing/pricing_program_timing/get_pricing_program_timing.dspy logined /pricing/pricing_program_timing/index.ui logined /pricing/pricing_program_timing/add_pricing_program_timing.dspy logined +/pricing/pricing_data_display.ui logined /api /api/callback /api/callback/alipay @@ -666,15 +848,21 @@ paths="""/ any /dagflow/new_instance.ui logined /API.md any /rbac logined +/rbac/index.ui logined /rbac/phone_login.dspy any /rbac/refresh_userperm.dspy any /rbac/get_reseller.dspy owner.* /rbac/users logined /rbac/users/delete_users.dspy *.admin -/rbac/users/add_users.dsp *.adminy -/rbac/users/update_users.dsp *.adminy -/rbac/users/index.u *.admini -/rbac/users/get_users.dspy +/rbac/users/add_users.dspy *.admin +/rbac/users/update_users.dspy *.admin +/rbac/users/index.ui *.admin +/rbac/users/get_users.dspy *.admin +/rbac/users/enable_user.dspy *.admin +/rbac/users/disable_user.dspy *.admin +/rbac/api/add_user.dspy *.admin +/rbac/api/update_user.dspy *.admin +/rbac/api/get_search_roleid.dspy logined /rbac/add_adminuser.dspy owner.superuser /rbac/reseller logined /rbac/reseller/update_organization.dspy logined @@ -928,6 +1116,7 @@ paths="""/ any /filemgr/folder/index.ui logined /filemgr/folder/new_folder.dspy logined /platformbiz logined +/platformbiz/index.ui logined /platformbiz/agreement logined /platformbiz/agreement/update_agreement.dspy logined /platformbiz/agreement/add_agreement.dspy logined @@ -1079,6 +1268,223 @@ paths="""/ any /unipay/imgs/payment_log.svg any /unipay/usermenu.ui logined /unipay/refund.ui customer.* +/unipay/transfer_info.ui logined +/product_management logined +/product_management/index.ui logined +/product_management/menu.ui any +/product_management/category_manage.ui logined +/product_management/product_manage.ui logined +/product_management/api/category_options.dspy logined +/product_management/api/product_category_create.dspy logined +/product_management/api/product_category_update.dspy logined +/product_management/api/product_category_delete.dspy logined +/product_management/api/product_create.dspy logined +/product_management/api/product_update.dspy logined +/product_management/api/product_delete.dspy logined +/product_management/api/product_brief.dspy logined +/product_management/api/product_detail.dspy logined +/product_management/api/product_purchase.dspy logined +/product_management/api/product_use.dspy logined +/product_management/product_category_tree logined +/product_management/product_list logined +/supplychain logined +/supplychain/api/calculate_accounting.dspy logined +/supplychain/api/add_sub_distributor_admin.dspy logined +/supplychain/agreement_discount_setting.ui logined +/supplychain/contract_discount_setting.ui logined +/supplychain/api/get_agreement_discount_items.dspy logined +/supplychain/api/get_contract_discount_items.dspy logined +/supplychain/api/save_agreement_discount.dspy logined +/supplychain/api/save_contract_discount.dspy logined +/supplychain/api/distribution_agreement_items_create.dspy logined +/supplychain/api/distribution_agreement_items_delete.dspy logined +/supplychain/api/distribution_agreement_items_update.dspy logined +/supplychain/api/distribution_agreements_create.dspy logined +/supplychain/api/distribution_agreements_delete.dspy logined +/supplychain/api/distribution_agreements_update.dspy logined +/supplychain/api/ensure_distribution_agreement.dspy logined +/supplychain/api/ensure_supply_contract.dspy logined +/supplychain/api/get_search_agreement_id.dspy logined +/supplychain/api/get_search_contract_id.dspy logined +/supplychain/api/get_search_orgid.dspy logined +/supplychain/api/get_search_prodtypeid.dspy logined +/supplychain/api/get_search_productid.dspy logined +/supplychain/api/get_search_sub_distributor_id.dspy logined +/supplychain/api/get_search_sub_reseller_id.dspy logined +/supplychain/api/get_search_supplier_id.dspy logined +/supplychain/api/get_search_supply_relation_id.dspy logined +/supplychain/api/import_supplier_product.dspy logined +/supplychain/api/platform_supply_products_create.dspy logined +/supplychain/api/platform_supply_products_delete.dspy logined +/supplychain/api/platform_supply_products_update.dspy logined +/supplychain/api/platform_supply_relations_create.dspy logined +/supplychain/api/platform_supply_relations_delete.dspy logined +/supplychain/api/platform_supply_relations_update.dspy logined +/supplychain/api/product_supplier_mapping_create.dspy logined +/supplychain/api/product_supplier_mapping_delete.dspy logined +/supplychain/api/product_supplier_mapping_update.dspy logined +/supplychain/api/query_dist_discount.dspy logined +/supplychain/api/query_platform_products.dspy logined +/supplychain/api/query_platform_suppliers.dspy logined +/supplychain/api/query_supply_discount.dspy logined +/supplychain/api/reset_sub_distributor_admin_pwd.dspy logined +/supplychain/api/sales_ledger_create.dspy logined +/supplychain/api/sales_ledger_delete.dspy logined +/supplychain/api/sales_ledger_update.dspy logined +/supplychain/api/sub_distributors_create.dspy logined +/supplychain/api/sub_distributors_delete.dspy logined +/supplychain/api/sub_distributors_update.dspy logined +/supplychain/api/sub_resellers_create.dspy logined +/supplychain/api/sub_resellers_delete.dspy logined +/supplychain/api/sub_resellers_update.dspy logined +/supplychain/api/supplier_resource_price_create.dspy logined +/supplychain/api/supplier_resource_price_delete.dspy logined +/supplychain/api/supplier_resource_price_update.dspy logined +/supplychain/api/suppliers_create.dspy logined +/supplychain/api/suppliers_delete.dspy logined +/supplychain/api/suppliers_update.dspy logined +/supplychain/api/supply_contract_items_create.dspy logined +/supplychain/api/supply_contract_items_delete.dspy logined +/supplychain/api/supply_contract_items_update.dspy logined +/supplychain/api/supply_contracts_create.dspy logined +/supplychain/api/supply_contracts_delete.dspy logined +/supplychain/api/supply_contracts_update.dspy logined +/supplychain/api/supplychain_accounting_create.dspy logined +/supplychain/api/supplychain_accounting_delete.dspy logined +/supplychain/api/supplychain_accounting_update.dspy logined +/supplychain/api/contract_attach_list.dspy logined +/supplychain/api/contract_attach.ui logined +/supplychain/api/contract_upload.dspy logined +/supplychain/api/contract_attach_delete.dspy logined +/supplychain/distribution_agreement_items_list logined +/supplychain/distribution_agreement_items_list/add_distribution_agreement_items.dspy logined +/supplychain/distribution_agreement_items_list/delete_distribution_agreement_items.dspy logined +/supplychain/distribution_agreement_items_list/get_distribution_agreement_items.dspy logined +/supplychain/distribution_agreement_items_list/index.ui logined +/supplychain/distribution_agreement_items_list/update_distribution_agreement_items.dspy logined +/supplychain/distribution_agreements_list logined +/supplychain/distribution_agreements_list/add_distribution_agreements.dspy logined +/supplychain/distribution_agreements_list/delete_distribution_agreements.dspy logined +/supplychain/distribution_agreements_list/get_distribution_agreements.dspy logined +/supplychain/distribution_agreements_list/index.ui logined +/supplychain/distribution_agreements_list/update_distribution_agreements.dspy logined +/supplychain/platform_supply_products_list logined +/supplychain/platform_supply_products_list/add_platform_supply_products.dspy logined +/supplychain/platform_supply_products_list/delete_platform_supply_products.dspy logined +/supplychain/platform_supply_products_list/get_platform_supply_products.dspy logined +/supplychain/platform_supply_products_list/index.ui logined +/supplychain/platform_supply_products_list/update_platform_supply_products.dspy logined +/supplychain/platform_supply_relations_list logined +/supplychain/platform_supply_relations_list/add_platform_supply_relations.dspy logined +/supplychain/platform_supply_relations_list/delete_platform_supply_relations.dspy logined +/supplychain/platform_supply_relations_list/get_platform_supply_relations.dspy logined +/supplychain/platform_supply_relations_list/index.ui logined +/supplychain/platform_supply_relations_list/update_platform_supply_relations.dspy logined +/supplychain/product_supplier_mapping_list logined +/supplychain/product_supplier_mapping_list/add_product_supplier_mapping.dspy logined +/supplychain/product_supplier_mapping_list/delete_product_supplier_mapping.dspy logined +/supplychain/product_supplier_mapping_list/get_product_supplier_mapping.dspy logined +/supplychain/product_supplier_mapping_list/index.ui logined +/supplychain/product_supplier_mapping_list/update_product_supplier_mapping.dspy logined +/supplychain/sales_ledger_list logined +/supplychain/sales_ledger_list/add_sales_ledger.dspy logined +/supplychain/sales_ledger_list/delete_sales_ledger.dspy logined +/supplychain/sales_ledger_list/get_sales_ledger.dspy logined +/supplychain/sales_ledger_list/index.ui logined +/supplychain/sales_ledger_list/update_sales_ledger.dspy logined +/supplychain/sub_distributors_list logined +/supplychain/sub_distributors_list/add_sub_distributors.dspy logined +/supplychain/sub_distributors_list/delete_sub_distributors.dspy logined +/supplychain/sub_distributors_list/get_sub_distributors.dspy logined +/supplychain/sub_distributors_list/index.ui logined +/supplychain/sub_distributors_list/update_sub_distributors.dspy logined +/supplychain/sub_resellers_list logined +/supplychain/sub_resellers_list/add_sub_resellers.dspy logined +/supplychain/sub_resellers_list/delete_sub_resellers.dspy logined +/supplychain/sub_resellers_list/get_sub_resellers.dspy logined +/supplychain/sub_resellers_list/index.ui logined +/supplychain/sub_resellers_list/update_sub_resellers.dspy logined +/supplychain/supplier_resource_price_list logined +/supplychain/supplier_resource_price_list/index.ui logined +/supplychain/suppliers_list logined +/supplychain/suppliers_list/add_suppliers.dspy logined +/supplychain/suppliers_list/delete_suppliers.dspy logined +/supplychain/suppliers_list/get_suppliers.dspy logined +/supplychain/suppliers_list/index.ui logined +/supplychain/suppliers_list/update_suppliers.dspy logined +/supplychain/supply_contract_items_list logined +/supplychain/supply_contract_items_list/add_supply_contract_items.dspy logined +/supplychain/supply_contract_items_list/delete_supply_contract_items.dspy logined +/supplychain/supply_contract_items_list/get_supply_contract_items.dspy logined +/supplychain/supply_contract_items_list/index.ui logined +/supplychain/supply_contract_items_list/update_supply_contract_items.dspy logined +/supplychain/supply_contracts_list logined +/supplychain/supply_contracts_list/add_supply_contracts.dspy logined +/supplychain/supply_contracts_list/delete_supply_contracts.dspy logined +/supplychain/supply_contracts_list/get_supply_contracts.dspy logined +/supplychain/supply_contracts_list/index.ui logined +/supplychain/supply_contracts_list/update_supply_contracts.dspy logined +/supplychain/supplychain_accounting_list logined +/supplychain/supplychain_accounting_list/add_supplychain_accounting.dspy logined +/supplychain/supplychain_accounting_list/delete_supplychain_accounting.dspy logined +/supplychain/supplychain_accounting_list/get_supplychain_accounting.dspy logined +/supplychain/supplychain_accounting_list/index.ui logined +/supplychain/supplychain_accounting_list/update_supplychain_accounting.dspy logined +/supplychain/accounting.ui logined +/supplychain/distribution_agreements.ui logined +/supplychain/index.ui logined +/supplychain/menu.ui logined +/supplychain/provider_detail_reconcile.ui logined +/supplychain/provider_recharge.ui logined +/supplychain/provider_reconcile.ui logined +/supplychain/provider_settlement.ui logined +/supplychain/reseller_detail_reconcile.ui logined +/supplychain/reseller_reconcile.ui logined +/supplychain/reseller_settlement.ui logined +/supplychain/sub_distributors.ui logined +/supplychain/suppliers.ui logined +/supplychain/supply_contracts.ui logined +/supplychain/add_provider_recharge.dspy logined +/supplychain/add_provider_settlement.dspy logined +/supplychain/get_provider_detail_reconcile.dspy logined +/supplychain/get_provider_recharge.dspy logined +/supplychain/get_provider_reconcile.dspy logined +/supplychain/get_provider_settlement.dspy logined +/supplychain/get_reseller_detail_reconcile.dspy logined +/supplychain/get_reseller_reconcile.dspy logined +/supplychain/get_reseller_settlement.dspy logined +/supplychain/update_provider_recharge.dspy logined +/supplychain/update_provider_settlement.dspy logined +/supplychain/update_reseller_settlement.dspy logined +/imgs/supply_contract_items.svg any +/imgs/supply_contracts.svg any +/imgs/contract_attach.svg any +/imgs/distribution_agreement_items.svg any +/imgs/sub_resellers.svg any +/imgs/sub_distributors.svg any +/imgs/suppliers.svg any +/imgs/globe.svg any +/imgs/setting.svg any +/imgs/userrole.svg any +/appbase/get_code.dspy logined +/appbase/get_icon.dspy logined +/shell_theme.css any +/shell_theme.js any +/download/** logined +/global_menu.ui logined +/shell.ui logined +/index.ui any +/dashboard_for_sage/shell.ui logined +/dashboard_for_sage/global_menu.ui any +/dashboard_for_sage/shell_theme.css any +/dashboard_for_sage/shell_theme.js any +/dashboard_for_sage/stat_active_users.ui logined +/dashboard_for_sage/stat_new_users_month.ui logined +/dashboard_for_sage/stat_total_orgs.ui logined +/dashboard_for_sage/table_top_providers_amount.ui logined +/dashboard_for_sage/table_top_providers_count.ui logined +/dashboard_for_sage/table_top_users_count.ui logined +/dashboard_for_sage/chart_top_models.ui logined /hotspot logined /hotspot/index.ui logined /hotspot/stats.dspy logined @@ -1153,7 +1559,7 @@ async def main(): cnt = 0 async with db.sqlorContext('sage') as sor: for l in paths.split('\n'): - if not l: + if not l or l.startswith('#'): continue parts = l.split() path = parts[0] diff --git a/load_path.sh b/load_path.sh new file mode 100644 index 00000000..ac3c4a95 --- /dev/null +++ b/load_path.sh @@ -0,0 +1,5 @@ +for s in $(ls ls pkgs/*/scripts/load_path.py) +do + echo $s + python $s +done diff --git a/merchant_private_key.pem b/merchant_private_key.pem new file mode 100644 index 00000000..2f6520d1 --- /dev/null +++ b/merchant_private_key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDXTTNYz/VOr6KV +a74kO1Ivj30YiQ9xxASJYxpH51gtHRXO2HUKO7VVArnyMbqWEBvSdSBI/mDCoxhm +TMVxt752VzngPYhGm6M5cFXlzCDJmodnyNEjWrQjTwOZ49mSNXyhSCLzpzAs9Prx +Q6NpltYz+FFs2K9DAWkns0C4Ke0vMd5H0/Cs9pjWsQVSi1TW0bj876xrouU+4jsO +hK+WxA8sBsCdus7iuSkHjimDVYcVde/+N/WFSunY8Et5lb1mueSIL3d8EYucshF2 +ZN93CqcvnEiVAycGaZqWakwgQWrtKzaVNSgq1npdycCkhy2qkwoMBk/1Ls4ZzkQW +fQc+eiBFAgMBAAECggEACF22mUStB1uDZmnJkxM/B7Wvd1M0GqHMSO5lG6Ndfy56 +WQ96+zFqXWnkTqLCDLy5gaPaSk8GjlAG50q9miqfdKFbdvkAVGx0NKVgOrRQ5D4x +KF/arvrPG/Dt3Rf7R1dbhwTZK6POfaC5wF0P4Rviw1UEQCxQ7lPRGzrRUMnh4b7s +q3ceJ58wY3LB4UND0DLCMwh23XjyVPNOy3fnJ4f5sJSh9ddCcZVheNZ6YvQmucio +WPdWKUXV3phPxO6YGfIqcaNdkSUFkpQywCitmiuAcK/LqUmHV9S8CMpHodzk/U8U +BWQyq79h3imrkydssnEBhi2EYhpJcugjwA+0I8T3TQKBgQDik4ez5lLeACznCS1D +ZNHCpJFVqwVNW+VmdF9nCgyRDCixwUbBwg6fHmJiAyG4LZnsSaRQhtbTwP8Q1wnk +xefPcCFEacwkbyD/zbfsAWNYUAdnP5DB0bDOULjSP5NlMdgYfM86d99mhWRGpx1m +VSwTIeBNGGBokoivY07T5y4yFwKBgQDzQthecCwu3I2YV+3fjtBAtx47xwxP+weN +VNpowT0cJ/Uf7FB6A2P2t/A0fPOarcbuVMROdcdEeScszFQhmJxnBb0YLfotdK6M +42FHX7+dQ812Kh7+6h+mV1qzGllVeAFqur79C3uwq/MvPHaZxLwSzV+tSupjUUUx +cLUGszUGAwKBgQDaIx9rXDw77/9LD9K8J7yroLUrvVOFfwwE79VJ5qrimsozGNl+ +gc6B80bVBh7Yq06d5uiDfs4lYJIxLFciIkdjt5jPvOwFx9gFb5G7bjqvM51tEg3U +DIYknCLUiNDnhG2AZek9aVtz4MkCHLJ5a1bbtKm2j9mB1FI0SXADI3eeUQKBgQDh +JcA/ABFUuhtvogpu/K5xB0s7Rop1yECAJcYUaK3Xzn/IsR73HwY5hpsS6YdKZYaW +dexPNiFdlciVZPSFN8uiaqROqddAlRstGRKjTdJ6ixOyR1/yzdzHR1iSJlQCkBS3 +pOo6KJOtvChTUuHuhjEQMfdY29q+W6zwCoHyFpF/4wKBgQDiYcg8wpceWpGA1rbf +miY/tysjRe4KnFRr/4QSfIlhxubHyTuteviI92TemLWQzBmZ1iK0AimLDUGawulf +Qrnuz53SLznQs4gNoUHuP4V+0W5BFuWy0CHzoxS2fRSUNSWhdJgBJTsSpC9q+IVW +eXfGkqt1kXKZ9JP5Hjnz1FBCTg== +-----END PRIVATE KEY----- diff --git a/merchant_public_key.pem b/merchant_public_key.pem new file mode 100644 index 00000000..28951b11 --- /dev/null +++ b/merchant_public_key.pem @@ -0,0 +1,9 @@ +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA100zWM/1Tq+ilWu+JDtS +L499GIkPccQEiWMaR+dYLR0Vzth1Cju1VQK58jG6lhAb0nUgSP5gwqMYZkzFcbe+ +dlc54D2IRpujOXBV5cwgyZqHZ8jRI1q0I08DmePZkjV8oUgi86cwLPT68UOjaZbW +M/hRbNivQwFpJ7NAuCntLzHeR9PwrPaY1rEFUotU1tG4/O+sa6LlPuI7DoSvlsQP +LAbAnbrO4rkpB44pg1WHFXXv/jf1hUrp2PBLeZW9ZrnkiC93fBGLnLIRdmTfdwqn +L5xIlQMnBmmalmpMIEFq7Ss2lTUoKtZ6XcnApIctqpMKDAZP9S7OGc5EFn0HPnog +RQIDAQAB +-----END PUBLIC KEY----- diff --git a/merge_i18n.py b/merge_i18n.py new file mode 100644 index 00000000..24b02267 --- /dev/null +++ b/merge_i18n.py @@ -0,0 +1,166 @@ +#!/usr/bin/env python3 +""" +合并所有Sage模块的i18n内容到 wwwroot/i18n + +模块清单与 build.sh 保持一致(第29行 for m in ...), +读取每个模块的 i18n/{lang}/msg.txt, +合并输出到 wwwroot/i18n/{lang}/i18n.json + msg.txt。 + +冲突策略:按 build.sh 中模块顺序,后加载的覆盖先加载的。 + sage 自身排在首位(优先级最低)。 +""" + +import json +import re +import sys +from pathlib import Path + +# --- 配置 --- +SAGE_DIR = Path(__file__).resolve().parent # /d/ymq/repos/sage +REPOS_DIR = SAGE_DIR.parent # /d/ymq/repos +I18N_OUTPUT_DIR = SAGE_DIR / 'wwwroot' / 'i18n' # 输出目标 +LANGS = ['zh', 'en', 'jp', 'ko'] # 支持的语言 + + +def parse_build_sh(build_sh_path): + """从 build.sh 中提取模块清单(第29行 for m in ...) + + build.sh 有两个 for m in 循环: + - 第21行: pip基础库(apppublic, sqlor, ahserver, ...) + - 第29行: Sage业务模块(appbase, rbac, accounting, ...) + 我们取第二个(业务模块),与 sage 的 wwwroot 符号链接配置一致。 + """ + with open(build_sh_path, 'r', encoding='utf-8') as f: + content = f.read() + + # 匹配所有 "for m in ..." 行 —— 只到行尾(不用 \s 防止跨行匹配到 do) + matches = re.findall(r'^for m in ((?:[a-z][\w-]*[ \t]*)+)$', content, re.MULTILINE) + if len(matches) < 2: + sys.exit(f"错误: 在 build.sh 中找到 {len(matches)} 个 for m in 行,期望至少2个") + + # 第二个 for m in 是 Sage 业务模块清单 + modules_str = matches[1] + modules = [m for m in modules_str.strip().split() if '-' not in m] + # 业务模块 → bricks(最后加载,优先级最高,确保框架内置文本不被覆盖) + # bricks 是基础框架,不在 build.sh 业务模块循环中,需手动加入 + result = ['sage'] + modules + ['bricks'] + return result + + +def find_module_i18n_dir(module_name): + """查找模块的 i18n 目录(先查 repos/ 同级目录,再查 sage/pkgs/ 内)""" + candidate = REPOS_DIR / module_name / 'i18n' + if candidate.is_dir(): + return candidate + candidate = SAGE_DIR / 'pkgs' / module_name / 'i18n' + if candidate.is_dir(): + return candidate + return None + + +def parse_msg_txt(filepath): + """解析 msg.txt,格式: key: value(每行一个)""" + result = {} + if not filepath.is_file(): + return result + + with open(filepath, 'r', encoding='utf-8') as f: + for line in f: + line = line.rstrip('\n').rstrip('\r') + if not line: + continue + # 格式: key: value + idx = line.find(': ') + if idx > 0: + key = line[:idx] + value = line[idx+2:] + result[key] = value + else: + # 可能只有 key 没有 value,或者格式不对,跳过 + idx = line.find(':') + if idx > 0: + key = line[:idx] + value = line[idx+1:] + result[key] = value + return result + + +def merge_i18n(modules): + """合并所有模块的 i18n,返回 {lang: {key: value}}""" + merged = {lang: {} for lang in LANGS} + + for module_name in modules: + i18n_dir = find_module_i18n_dir(module_name) + if not i18n_dir: + print(f" [跳过] {module_name}: 未找到i18n目录") + continue + + for lang in LANGS: + msg_file = i18n_dir / lang / 'msg.txt' + if msg_file.is_file(): + translations = parse_msg_txt(msg_file) + count = len(translations) + before = len(merged[lang]) + merged[lang].update(translations) + after = len(merged[lang]) + new_keys = after - before + if new_keys > 0 or count > 0: + print(f" {module_name}/{lang}: {count}条, 新增{new_keys}个唯一key") + else: + print(f" [警告] {module_name}/{lang}: msg.txt 不存在") + + return merged + + +def write_output(merged): + """将合并结果写入 wwwroot/i18n/{lang}/i18n.json 和 msg.txt""" + for lang in LANGS: + lang_dir = I18N_OUTPUT_DIR / lang + lang_dir.mkdir(parents=True, exist_ok=True) + + data = merged[lang] + + # 写入 i18n.json(前端读取此文件) + json_file = lang_dir / 'i18n.json' + with open(json_file, 'w', encoding='utf-8') as f: + json.dump(data, f, ensure_ascii=False, indent='\t') + + # 同时写入 msg.txt(人类可读格式) + msg_file = lang_dir / 'msg.txt' + with open(msg_file, 'w', encoding='utf-8') as f: + for key, value in data.items(): + f.write(f"{key}: {value}\n") + + print(f" 写入: {json_file} ({len(data)} 条)") + print(f" 写入: {msg_file} ({len(data)} 条)") + + +def main(): + build_sh_path = SAGE_DIR / 'build.sh' + if not build_sh_path.is_file(): + print(f"错误: 找不到 {build_sh_path}") + sys.exit(1) + + print(f"解析 build.sh: {build_sh_path}") + modules = parse_build_sh(build_sh_path) + print(f"发现 {len(modules)} 个模块:") + for m in modules: + has_i18n = (REPOS_DIR / m / 'i18n').is_dir() + status = '✓' if has_i18n else '✗' + print(f" {status} {m}") + + print(f"\n开始合并 i18n...") + merged = merge_i18n(modules) + + print(f"\n合并结果:") + for lang in LANGS: + print(f" {lang}: {len(merged[lang])} 个唯一key") + + print(f"\n写入 wwwroot/i18n...") + write_output(merged) + + print(f"\n完成!") + + +if __name__ == '__main__': + main() diff --git a/migrate_llm_catelog.py b/migrate_llm_catelog.py new file mode 100644 index 00000000..7d900560 --- /dev/null +++ b/migrate_llm_catelog.py @@ -0,0 +1,68 @@ +import asyncio +from sqlor.dbpools import DBPools +from appPublic.jsonConfig import getConfig +from appPublic.uniqueID import getID + +async def migrate(): + config = getConfig('.') + db = DBPools(config.databases) + + # sage数据库 + dbname = 'sage' + + async with db.sqlorContext(dbname) as sor: + # 1. Create table if not exists + print("Creating llm_catalog_rel table...") + create_sql = """ + CREATE TABLE IF NOT EXISTS llm_catalog_rel ( + id VARCHAR(32) NOT NULL PRIMARY KEY, + llmid VARCHAR(32) NOT NULL, + llmcatelogid VARCHAR(32) NOT NULL, + INDEX idx_llm (llmid), + INDEX idx_catelog (llmcatelogid) + ) + """ + try: + await sor.sqlExe(create_sql, {}) + print("Table llm_catalog_rel created or exists.") + except Exception as e: + print(f"Create table warning: {e}") + + # 2. Migrate data + print("Migrating data...") + sql = "select id, llmcatelogid from llm where llmcatelogid is not null and llmcatelogid != ''" + rows = await sor.sqlExe(sql, {}) + print(f"Found {len(rows)} records to migrate.") + + migrated = 0 + for r in rows: + new_id = getID() + data = { + 'id': new_id, + 'llmid': r['id'], + 'llmcatelogid': r['llmcatelogid'] + } + try: + await sor.C('llm_catalog_rel', data) + migrated += 1 + except Exception as e: + print(f"Insert error for {r['id']}: {e}") + + print(f"Migration complete. Migrated {migrated} records.") + + # 3. Drop column + print("Dropping column llmcatelogid from llm...") + try: + await sor.sqlExe("alter table llm drop column llmcatelogid", {}) + print("Column dropped.") + except Exception as e: + print(f"Drop column error: {e}") + + return True + +if __name__ == '__main__': + success = asyncio.get_event_loop().run_until_complete(migrate()) + if success: + print('Migration complete.') + else: + print('Migration failed.') diff --git a/migrate_llm_catelog_prod.py b/migrate_llm_catelog_prod.py new file mode 100644 index 00000000..be95f485 --- /dev/null +++ b/migrate_llm_catelog_prod.py @@ -0,0 +1,124 @@ +#!/usr/bin/env python3 +""" +Production Migration Script for llm -> llm_catalog_rel. +This script handles: +1. Creating the new relationship table if it doesn't exist. +2. Migrating existing single-type associations to the new table. +3. Dropping the old column (optional but recommended). + +Usage: + cd /home/hermesai/repos/sage + ./py3/bin/python migrate_llm_catelog_prod.py +""" +import asyncio +import sys +sys.path.insert(0, '.') + +from sqlor.dbpools import DBPools +from appPublic.jsonConfig import getConfig +from appPublic.uniqueID import getID + +async def migrate(): + config = getConfig('.') + db = DBPools(config.databases) + + # Sage 数据库 + dbname = 'sage' + + async with db.sqlorContext(dbname) as sor: + # 1. 检查列是否存在 + check_col_sql = "select count(*) as cnt from information_schema.columns where table_schema = database() and table_name = 'llm' and column_name = 'llmcatelogid'" + res = await sor.sqlExe(check_col_sql, {}) + has_column = res[0].cnt > 0 if res else False + + if not has_column: + print("[SKIP] Column 'llmcatelogid' does not exist in 'llm' table. Migration not needed.") + return True + + # 2. 创建表 (如果不存在) + print("[STEP 1] Ensuring table 'llm_catalog_rel' exists...") + create_sql = """ + CREATE TABLE IF NOT EXISTS llm_catalog_rel ( + id VARCHAR(32) NOT NULL PRIMARY KEY, + llmid VARCHAR(32) NOT NULL, + llmcatelogid VARCHAR(32) NOT NULL, + UNIQUE KEY uq_llm_catelog (llmid, llmcatelogid), + INDEX idx_llm (llmid), + INDEX idx_catelog (llmcatelogid) + ) + """ + try: + await sor.sqlExe(create_sql, {}) + print(" -> Table created or exists.") + except Exception as e: + print(f" -> Table creation warning: {e}") + + # 2.1 确保唯一索引存在 + print("[STEP 1.1] Ensuring unique index 'uq_llm_catelog' exists...") + try: + await sor.sqlExe("ALTER TABLE llm_catalog_rel ADD UNIQUE INDEX uq_llm_catelog (llmid, llmcatelogid)", {}) + print(" -> Unique index added.") + except Exception as e: + if "Duplicate key name" in str(e) or "Multiple primary key defined" in str(e): + print(" -> Unique index already exists.") + else: + print(f" -> Index creation warning (may already exist): {e}") + + # 3. 迁移数据 + print("[STEP 2] Migrating data...") + sql = "select id, llmcatelogid from llm where llmcatelogid is not null and llmcatelogid != ''" + rows = await sor.sqlExe(sql, {}) + print(f" -> Found {len(rows)} records to migrate.") + + migrated_count = 0 + error_count = 0 + + for r in rows: + # Check if already migrated to avoid duplicates if re-running + check_rel_sql = "select count(*) as cnt from llm_catalog_rel where llmid = ${llmid}$ and llmcatelogid = ${catelogid}$" + rel_res = await sor.sqlExe(check_rel_sql, {'llmid': r['id'], 'catelogid': r['llmcatelogid']}) + if rel_res and rel_res[0].cnt > 0: + continue + + new_id = getID() + data = { + 'id': new_id, + 'llmid': r['id'], + 'llmcatelogid': r['llmcatelogid'] + } + try: + await sor.C('llm_catalog_rel', data) + migrated_count += 1 + except Exception as e: + print(f" -> Error migrating {r['id']}: {e}") + error_count += 1 + + print(f" -> Migration complete. Inserted: {migrated_count}, Errors: {error_count}") + + # 4. 删除旧列 (生产环境谨慎执行,建议确认迁移成功后手动执行) + # print("[STEP 3] Dropping old column 'llmcatelogid'...") + # try: + # await sor.sqlExe("alter table llm drop column llmcatelogid", {}) + # print(" -> Column dropped.") + # except Exception as e: + # print(f" -> Drop column error: {e}") + + print("\n[MIGRATION DONE]") + print("Please verify data in 'llm_catalog_rel'.") + print("If correct, you may manually run: alter table llm drop column llmcatelogid;") + + return True + +if __name__ == '__main__': + print("Starting production migration...") + try: + success = asyncio.get_event_loop().run_until_complete(migrate()) + if success: + sys.exit(0) + else: + sys.exit(1) + except Exception as e: + print(f"FATAL ERROR: {e}") + import traceback + traceback.print_exc() + sys.exit(1) diff --git a/models/.DS_Store b/models/.DS_Store deleted file mode 100644 index 5008ddfc..00000000 Binary files a/models/.DS_Store and /dev/null differ diff --git a/models/apiparams.json b/models/apiparams.json new file mode 100644 index 00000000..baa19994 --- /dev/null +++ b/models/apiparams.json @@ -0,0 +1,83 @@ +{ + "summary": [ + { + "name": "apiparams", + "title": "接口参数", + "primary": [ + "id" + ] + } + ], + "fields": [ + { + "name": "id", + "title": "id", + "type": "str", + "length": 32 + }, + { + "name": "params_type", + "title": "接口名称", + "type": "str", + "length": 1 + }, + { + "name": "objid", + "title": "模型或实例id", + "type": "str", + "length": 32 + }, + { + "name": "apidataid", + "title": "父数据id", + "type": "str", + "length": 32 + }, + { + "name": "datatype", + "title": "数据类型", + "type": "str", + "length": 2 + }, + { + "name": "value", + "title": "数据值", + "type": "str", + "length": 1000 + } + ], + "indexes": [ + { + "name": "idx1", + "idxtype": "index", + "idxfields": [ + "apidataid" + ] + }, + { + "name": "idx2", + "idxtype": "unique", + "idxfields": [ + "apidataid", + "params_type", + "objid" + ] + } + ], + "codes": [ + { + "field": "params_type", + "table": "appcodes_kv", + "valuefield": "k", + "textfield": "v", + "cond": "parentid='params_type'" + }, + { + "field": "datatype", + "table": "appcodes_kv", + "valuefield": "k", + "textfield": "v", + "cond": "parentid='datatype'" + } + ] +} \ No newline at end of file diff --git a/models/appcodes.json b/models/appcodes.json new file mode 100644 index 00000000..f0c3a0fa --- /dev/null +++ b/models/appcodes.json @@ -0,0 +1,40 @@ +{ + "summary": [ + { + "name": "appcodes", + "title": "应用编码表", + "primary": [ + "id" + ] + } + ], + "fields": [ + { + "name": "id", + "title": "id", + "type": "str", + "length": 32 + }, + { + "name": "name", + "title": "编码名称", + "type": "str", + "length": 255 + }, + { + "name": "hierarchy_flg", + "title": "多级标志", + "type": "str", + "length": 1 + } + ], + "codes": [ + { + "field": "hierarchy_flg", + "table": "appcodes_kv", + "valuefield": "k", + "textfield": "v", + "cond": "parentid='code_hierarchy'" + } + ] +} \ No newline at end of file diff --git a/models/appcodes_kv.json b/models/appcodes_kv.json new file mode 100644 index 00000000..5d8aa391 --- /dev/null +++ b/models/appcodes_kv.json @@ -0,0 +1,54 @@ +{ + "summary": [ + { + "name": "appcodes_kv", + "title": "编码键值表", + "primary": [ + "id" + ] + } + ], + "fields": [ + { + "name": "id", + "title": "id", + "type": "str", + "length": 32 + }, + { + "name": "parentid", + "title": "父id", + "type": "str", + "length": 32 + }, + { + "name": "k", + "title": "键", + "type": "str", + "length": 32 + }, + { + "name": "v", + "title": "值", + "type": "str", + "length": 255 + } + ], + "indexes": [ + { + "name": "idx1", + "idxtype": "unique", + "idxfields": [ + "parentid", + "k" + ] + }, + { + "name": "idx2", + "idxtype": "index", + "idxfields": [ + "parentid" + ] + } + ] +} \ No newline at end of file diff --git a/models/feelog.json b/models/feelog.json new file mode 100644 index 00000000..508a0895 --- /dev/null +++ b/models/feelog.json @@ -0,0 +1,211 @@ +{ + "summary": [ + { + "name": "feelog", + "title": "模型计费日志", + "primary": [ + "id" + ], + "catelog": "entity" + } + ], + "fields": [ + { + "name": "id", + "title": "id", + "type": "str", + "length": 32 + }, + { + "name": "transdate", + "title": "交易日期", + "type": "date" + }, + { + "name": "transtime", + "title": "交易时间", + "type": "timestamp" + }, + { + "name": "modelinstanceid", + "title": "模型实例id", + "type": "str", + "length": 32 + }, + { + "name": "modeltypeid", + "title": "模型类型id", + "type": "str", + "length": 32 + }, + { + "name": "customerid", + "title": "客户id", + "type": "str", + "length": 32 + }, + { + "name": "userid", + "title": "用户id", + "type": "str", + "length": 32 + }, + { + "name": "pricing_mode", + "title": "计费模式", + "type": "str", + "length": 30 + }, + { + "name": "dialog_file", + "title": "会话文件名", + "type": "str", + "length": 400 + }, + { + "name": "input_tokens", + "title": "输入tokens", + "type": "long" + }, + { + "name": "output_tokens", + "title": "输出tokens", + "type": "long" + }, + { + "name": "other_tokens", + "title": "其他tokens", + "type": "long" + }, + { + "name": "input_price", + "title": "输入价格", + "type": "float", + "length": 18, + "dec": 2 + }, + { + "name": "output_price", + "title": "输出价格", + "type": "float", + "length": 18, + "dec": 2 + }, + { + "name": "other_price", + "title": "其他价格", + "type": "float", + "length": 18, + "dec": 2 + }, + { + "name": "timing_price", + "title": "计次价格", + "type": "float", + "length": 18, + "dec": 2 + }, + { + "name": "timing_amount", + "title": "计次金额", + "type": "float", + "length": 18, + "dec": 2 + }, + { + "name": "input_amount", + "title": "输入金额", + "type": "float", + "length": 18, + "dec": 2 + }, + { + "name": "output_amount", + "title": "输出金额", + "type": "float", + "length": 18, + "dec": 2 + }, + { + "name": "other_amount", + "title": "其他金额", + "type": "float", + "length": 18, + "dec": 2 + }, + { + "name": "accounting_status", + "title": "记账状态", + "type": "str", + "length": 30 + }, + { + "name": "resp_time", + "title": "响应时间", + "type": "float", + "length": 18, + "dec": 2 + }, + { + "name": "finish_time", + "title": "完成时间", + "type": "float", + "length": 18, + "dec": 2 + }, + { + "name": "estimate", + "title": "评价", + "type": "short" + } + ], + "indexes": [ + { + "name": "idx1", + "idxtype": "index", + "idxfields": [ + "transdate" + ] + }, + { + "name": "idx2", + "idxtype": "index", + "idxfields": [ + "customerid" + ] + }, + { + "name": "idx3", + "idxtype": "index", + "idxfields": [ + "userid" + ] + } + ], + "codes": [ + { + "field": "modelinstanceid", + "table": "modelinstance", + "valuefield": "id", + "textfield": "name" + }, + { + "field": "modeltypeid", + "table": "modeltypes", + "valuefield": "id", + "textfield": "name" + }, + { + "field": "customerid", + "table": "organization", + "valuefield": "id", + "textfield": "orgname" + }, + { + "field": "userid", + "table": "users", + "valuefield": "id", + "textfield": "username" + } + ] +} \ No newline at end of file diff --git a/models/httpapi.json b/models/httpapi.json new file mode 100644 index 00000000..b2aee20a --- /dev/null +++ b/models/httpapi.json @@ -0,0 +1,110 @@ +{ + "summary": [ + { + "name": "httpapi", + "title": "http程序接口", + "primary": [ + "id" + ] + } + ], + "fields": [ + { + "name": "id", + "title": "id", + "type": "str", + "length": 32 + }, + { + "name": "apiname", + "title": "接口名", + "type": "str", + "length": 100 + }, + { + "name": "label", + "title": "接口名称", + "type": "str", + "length": 100 + }, + { + "name": "providerid", + "title": "接口提供方", + "type": "str", + "length": 32 + }, + { + "name": "apiinfo", + "title": "接口内容", + "type": "str", + "length": 4000 + }, + { + "name": "apinote", + "title": "接口描述", + "type": "str", + "length": 500 + }, + { + "name": "use_session", + "title": "带历史信息", + "type": "str", + "length": 1 + }, + { + "name": "response_mode", + "title": "响应模式", + "type": "str", + "length": 50 + }, + { + "name": "system_msg_format", + "title": "系统消息模版", + "type": "str", + "length": 1000 + }, + { + "name": "user_msg_format", + "title": "用户消息模版", + "type": "str", + "length": 1000 + }, + { + "name": "llm_msg_format", + "title": "模型消息模版", + "type": "str", + "length": 1000 + } + ], + "indexes": [ + { + "name": "idx1", + "idxtype": "unique", + "idxfields": [ + "apiname" + ] + } + ], + "codes": [ + { + "field": "providerid", + "table": "supplychain.suppliers", + "valuefield": "id", + "textfield": "supplier_name" + }, + { + "field": "use_session", + "table": "appcodes_kv", + "valuefield": "k", + "textfield": "v", + "cond": "parentid='yesno'" + }, + { + "field": "response_mode", + "table": "appcodes_kv", + "valuefield": "k", + "textfield": "v", + "cond": "parentid='resp_mode'" + } + ] +} \ No newline at end of file diff --git a/models/minimax_acc.json b/models/minimax_acc.json new file mode 100644 index 00000000..d9e4ef89 --- /dev/null +++ b/models/minimax_acc.json @@ -0,0 +1,70 @@ +{ + "summary": [ + { + "name": "minimax_acc", + "title": "minimax账号", + "primary": [ + "id" + ] + } + ], + "fields": [ + { + "name": "id", + "title": "id", + "type": "str", + "length": 32 + }, + { + "name": "userid", + "title": "用户id", + "type": "str", + "length": 100 + }, + { + "name": "acc_id", + "title": "minimax账号id", + "type": "str", + "length": 100 + }, + { + "name": "acc_name", + "title": "账号名称", + "type": "str", + "length": 300 + }, + { + "name": "password", + "title": "账号密码", + "type": "str", + "length": 100 + }, + { + "name": "apikey", + "title": "账号apikey", + "type": "str", + "length": 4000 + }, + { + "name": "groupid", + "title": "组号", + "type": "str", + "length": 100 + }, + { + "name": "acc_status", + "title": "账号状态", + "type": "short", + "default": 0 + } + ], + "indexes": [ + { + "name": "idx1", + "idxtype": "unique", + "idxfields": [ + "userid" + ] + } + ] +} \ No newline at end of file diff --git a/models/minimax_bill.json b/models/minimax_bill.json new file mode 100644 index 00000000..aedcc08a --- /dev/null +++ b/models/minimax_bill.json @@ -0,0 +1,80 @@ +{ + "summary": [ + { + "name": "minimax_bill", + "title": "minimax账单", + "primary": [ + "id" + ] + } + ], + "fields": [ + { + "name": "id", + "title": "id", + "type": "str", + "length": 32 + }, + { + "name": "customerid", + "title": "客户id", + "type": "str", + "length": 32 + }, + { + "name": "acc_id", + "title": "用户id", + "type": "str", + "length": 100 + }, + { + "name": "modelinstanceid", + "title": "模型实例id", + "type": "str", + "length": 100 + }, + { + "name": "acc_name", + "title": "账号名称", + "type": "str", + "length": 100, + "default": "0" + }, + { + "name": "consume_time", + "title": "消费时间戳", + "type": "timestamp" + }, + { + "name": "consume_token", + "title": "消费token数", + "type": "long" + }, + { + "name": "consume_amt", + "title": "消费金额", + "type": "float", + "length": 18, + "dec": 2 + }, + { + "name": "create_at", + "title": "创建时间", + "type": "timestamp" + }, + { + "name": "consume_date", + "title": "消费日期", + "type": "date" + } + ], + "indexes": [ + { + "name": "idx1", + "idxtype": "index", + "idxfields": [ + "customerid" + ] + } + ] +} \ No newline at end of file diff --git a/models/modelapi.json b/models/modelapi.json new file mode 100644 index 00000000..41b3f685 --- /dev/null +++ b/models/modelapi.json @@ -0,0 +1,57 @@ +{ + "summary": [ + { + "name": "modelapi", + "title": "模型接口", + "primary": [ + "id" + ] + } + ], + "fields": [ + { + "name": "id", + "title": "id", + "type": "str", + "length": 32 + }, + { + "name": "modelid", + "title": "模型id", + "type": "str", + "length": 32 + }, + { + "name": "apiid", + "title": "接口id", + "type": "str", + "length": 32 + }, + { + "name": "modeltypeid", + "title": "模型类型", + "type": "str", + "length": 32 + } + ], + "codes": [ + { + "field": "modelid", + "table": "models", + "valuefield": "id", + "textfield": "name" + }, + { + "field": "apiid", + "table": "httpapi", + "valuefield": "id", + "textfield": "apiname" + }, + { + "field": "modeltypeid", + "table": "modeltype", + "valuefield": "id", + "textfield": "name" + } + ] +} \ No newline at end of file diff --git a/models/modelinstance.json b/models/modelinstance.json new file mode 100644 index 00000000..5f819f08 --- /dev/null +++ b/models/modelinstance.json @@ -0,0 +1,73 @@ +{ + "summary": [ + { + "name": "modelinstance", + "title": "模型实例", + "primary": [ + "id" + ] + } + ], + "fields": [ + { + "name": "id", + "title": "id", + "type": "str", + "length": 32 + }, + { + "name": "modelid", + "title": "模型id", + "type": "str", + "length": 32 + }, + { + "name": "name", + "title": "实例名", + "type": "str", + "length": 100 + }, + { + "name": "label", + "title": "实例名称", + "type": "str", + "length": 100 + }, + { + "name": "description", + "title": "实例说明", + "type": "str", + "length": 500 + }, + { + "name": "base_url", + "title": "接口ur", + "type": "str", + "length": 500 + }, + { + "name": "ownerid", + "title": "属主id", + "type": "str", + "length": 32 + }, + { + "name": "enable_date", + "title": "启动日期", + "type": "date" + }, + { + "name": "expore_date", + "title": "失效日期", + "type": "date" + } + ], + "codes": [ + { + "field": "modelid", + "table": "models", + "valuefield": "id", + "textfield": "name" + } + ] +} \ No newline at end of file diff --git a/models/modeliodata.json b/models/modeliodata.json new file mode 100644 index 00000000..f69d5949 --- /dev/null +++ b/models/modeliodata.json @@ -0,0 +1,69 @@ +{ + "summary": [ + { + "name": "modeliodata", + "title": "模型输入输出数据", + "primary": [ + "id" + ] + } + ], + "fields": [ + { + "name": "id", + "title": "id", + "type": "str", + "length": 32 + }, + { + "name": "name", + "title": "数据名", + "type": "str", + "length": 100 + }, + { + "name": "label", + "title": "标题", + "type": "str", + "length": 500 + }, + { + "name": "datatype", + "title": "数据类型", + "type": "str", + "length": 2 + }, + { + "name": "uitype", + "title": "输入类型", + "type": "str", + "length": 2 + }, + { + "name": "length", + "title": "长度", + "type": "short" + }, + { + "name": "dec", + "title": "小数点数", + "type": "short" + } + ], + "codes": [ + { + "field": "uitype", + "table": "appcodes_kv", + "valuefield": "k", + "textfield": "v", + "cond": "parentid='uitype'" + }, + { + "field": "datatype", + "table": "appcodes_kv", + "valuefield": "k", + "textfield": "v", + "cond": "parentid='datatype'" + } + ] +} \ No newline at end of file diff --git a/models/modelpricing.json b/models/modelpricing.json new file mode 100644 index 00000000..91024c1c --- /dev/null +++ b/models/modelpricing.json @@ -0,0 +1,94 @@ +{ + "summary": [ + { + "name": "modelpricing", + "title": "模型计费", + "primary": [ + "id" + ] + } + ], + "fields": [ + { + "name": "id", + "title": "id", + "type": "str", + "length": 32 + }, + { + "name": "modelinstanceid", + "title": "模型实例id", + "type": "str", + "length": 32 + }, + { + "name": "modeltypeid", + "title": "模型类型id", + "type": "str", + "length": 32 + }, + { + "name": "enable_date", + "title": "开始日期", + "type": "date" + }, + { + "name": "expired_date", + "title": "失效日期", + "type": "date" + }, + { + "name": "pricing_mode", + "title": "计费类型", + "type": "str", + "length": 30 + }, + { + "name": "token_cnt", + "title": "token数量", + "type": "long" + }, + { + "name": "input_price", + "title": "输入价格", + "type": "float", + "length": 18, + "dec": 2 + }, + { + "name": "output_price", + "title": "输出价格", + "type": "float", + "length": 18, + "dec": 2 + }, + { + "name": "timing_price", + "title": "计次价格", + "type": "float", + "length": 18, + "dec": 2 + } + ], + "codes": [ + { + "field": "pricing_mode", + "table": "appcodes_kv", + "valuefield": "k", + "textfield": "v", + "cond": "parentid='pricing_mode'" + }, + { + "field": "modelinstanceid", + "table": "modelinstance", + "valuefield": "id", + "textfield": "name" + }, + { + "field": "modeltypeid", + "table": "modeltype", + "valuefield": "id", + "textfield": "name" + } + ] +} \ No newline at end of file diff --git a/models/modelprovider.json b/models/modelprovider.json new file mode 100644 index 00000000..65cfe68c --- /dev/null +++ b/models/modelprovider.json @@ -0,0 +1,37 @@ +{ + "summary": [ + { + "name": "modelprovider", + "title": "模型供应商", + "primary": [ + "id" + ] + } + ], + "fields": [ + { + "name": "id", + "title": "id", + "type": "str", + "length": 32 + }, + { + "name": "name", + "title": "供应商名", + "type": "str", + "length": 32 + }, + { + "name": "label", + "title": "供应商名称", + "type": "str", + "length": 32 + }, + { + "name": "description", + "title": "说明", + "type": "str", + "length": 500 + } + ] +} \ No newline at end of file diff --git a/models/models.json b/models/models.json new file mode 100644 index 00000000..73ccd26c --- /dev/null +++ b/models/models.json @@ -0,0 +1,57 @@ +{ + "summary": [ + { + "name": "models", + "title": "大模型", + "primary": [ + "id" + ] + } + ], + "fields": [ + { + "name": "id", + "title": "id", + "type": "str", + "length": 32 + }, + { + "name": "name", + "title": "英文名", + "type": "str", + "length": 100 + }, + { + "name": "title", + "title": "模型名称", + "type": "str", + "length": 100 + }, + { + "name": "description", + "title": "模型说明", + "type": "str", + "length": 500 + }, + { + "name": "icon_url", + "title": "模型图标URL", + "type": "str", + "length": 500 + }, + { + "name": "providerid", + "title": "供应商id", + "type": "str", + "length": 32 + } + ], + "codes": [ + { + "field": "providerid", + "table": "organization", + "valuefield": "id", + "textfield": "orgname" + } + ] +} \ No newline at end of file diff --git a/models/modeltype.json b/models/modeltype.json new file mode 100644 index 00000000..e256899a --- /dev/null +++ b/models/modeltype.json @@ -0,0 +1,64 @@ +{ + "summary": [ + { + "name": "modeltype", + "title": "模型类型", + "primary": [ + "id" + ] + } + ], + "fields": [ + { + "name": "id", + "title": "id", + "type": "str", + "length": 32 + }, + { + "name": "name", + "title": "类型名", + "type": "str", + "length": 100 + }, + { + "name": "description", + "title": "类型说明", + "type": "str", + "length": 500 + }, + { + "name": "is_multiple", + "title": "是否多模态", + "type": "str", + "length": 1 + }, + { + "name": "input_fields", + "title": "输入字段", + "type": "str", + "length": 4000 + }, + { + "name": "input_view", + "title": "输入显示", + "type": "str", + "length": 4000 + }, + { + "name": "output_view", + "title": "输出显示", + "type": "str", + "length": 4000 + } + ], + "codes": [ + { + "field": "is_multiple", + "table": "appcodes_kv", + "valuefield": "k", + "textfield": "v", + "cond": "parentid='yesno'" + } + ] +} \ No newline at end of file diff --git a/models/modeltypein.json b/models/modeltypein.json new file mode 100644 index 00000000..167b8554 --- /dev/null +++ b/models/modeltypein.json @@ -0,0 +1,46 @@ +{ + "summary": [ + { + "name": "modeltypein", + "title": "模型类型输入数据", + "primary": [ + "id" + ] + } + ], + "fields": [ + { + "name": "id", + "title": "id", + "type": "str", + "length": 32 + }, + { + "name": "modeltypeid", + "title": "模型类型id", + "type": "str", + "length": 32 + }, + { + "name": "iodataid", + "title": "io数据id", + "type": "str", + "length": 32 + }, + { + "name": "required", + "title": "是否必须", + "type": "str", + "length": 1 + } + ], + "codes": [ + { + "field": "required", + "table": "appcodes_kv", + "valuefield": "k", + "textfield": "v", + "cond": "parentid='yesno'" + } + ] +} \ No newline at end of file diff --git a/models/modeltypeout.json b/models/modeltypeout.json new file mode 100644 index 00000000..6cc38d5d --- /dev/null +++ b/models/modeltypeout.json @@ -0,0 +1,37 @@ +{ + "summary": [ + { + "name": "modeltypeout", + "title": "模型类型输出数据", + "primary": [ + "id" + ] + } + ], + "fields": [ + { + "name": "id", + "title": "id", + "type": "str", + "length": 32 + }, + { + "name": "modeltypeid", + "title": "模型类型id", + "type": "str", + "length": 32 + }, + { + "name": "iodataid", + "title": "io数据id", + "type": "str", + "length": 32 + }, + { + "name": "resp_keys", + "title": "在响应包中的位置", + "type": "str", + "length": 1 + } + ] +} \ No newline at end of file diff --git a/models/org_roles.json b/models/org_roles.json new file mode 100644 index 00000000..280abc7f --- /dev/null +++ b/models/org_roles.json @@ -0,0 +1,43 @@ +{ + "summary": [ + { + "name": "org_roles", + "title": "机构角色", + "primary": [ + "id" + ] + } + ], + "fields": [ + { + "name": "id", + "title": "id", + "type": "str", + "length": 32 + }, + { + "name": "orgid", + "title": "机构编码", + "type": "str", + "length": 32 + }, + { + "name": "roleid", + "title": "角色编码", + "type": "str", + "length": 32 + }, + { + "name": "del_flg", + "title": "删除标志", + "type": "str", + "length": 1, + "default": "0" + }, + { + "name": "create_at", + "title": "创建时间戳", + "type": "timestamp" + } + ] +} \ No newline at end of file diff --git a/models/organization.json b/models/organization.json new file mode 100644 index 00000000..edad3cd4 --- /dev/null +++ b/models/organization.json @@ -0,0 +1,127 @@ +{ + "summary": [ + { + "name": "organization", + "title": "机构", + "primary": [ + "id" + ] + } + ], + "fields": [ + { + "name": "id", + "title": "机构编码", + "type": "str", + "length": 32 + }, + { + "name": "orgname", + "title": "机构名称", + "type": "str", + "length": 100 + }, + { + "name": "alias_name", + "title": "机构别名", + "type": "str", + "length": 100 + }, + { + "name": "contactor", + "title": "联系人", + "type": "str", + "length": 32 + }, + { + "name": "contactor_phone", + "title": "联系人电话", + "type": "str", + "length": 100 + }, + { + "name": "province_id", + "title": "所在省id", + "type": "str", + "length": 32 + }, + { + "name": "city_id", + "title": "所在城市id", + "type": "str", + "length": 32 + }, + { + "name": "distinct_id", + "title": "所在地区id", + "type": "str", + "length": 32 + }, + { + "name": "emailaddress", + "title": "邮箱", + "type": "str", + "length": 256 + }, + { + "name": "address", + "title": "地址", + "type": "str", + "length": 400 + }, + { + "name": "main_business", + "title": "主营业务描述", + "type": "str", + "length": 1000 + }, + { + "name": "orgcode", + "title": "组织结构代码", + "type": "str", + "length": 100 + }, + { + "name": "license_img", + "title": "营业执照", + "type": "str", + "length": 400 + }, + { + "name": "id_img", + "title": "身份证", + "type": "str", + "length": 400 + }, + { + "name": "parentid", + "title": "父机构id", + "type": "str", + "length": 32 + }, + { + "name": "org_type", + "title": "机构类型", + "type": "str", + "length": 32 + }, + { + "name": "accountid", + "title": "账号", + "type": "str", + "length": 32 + }, + { + "name": "del_flg", + "title": "删除标志", + "type": "str", + "length": 1, + "default": "0" + }, + { + "name": "create_at", + "title": "创建时间戳", + "type": "timestamp" + } + ] +} \ No newline at end of file diff --git a/models/orgtypes.json b/models/orgtypes.json new file mode 100644 index 00000000..7e5c2abf --- /dev/null +++ b/models/orgtypes.json @@ -0,0 +1,40 @@ +{ + "summary": [ + { + "name": "orgtypes", + "title": "机构拥有角色", + "primary": [ + "id" + ] + } + ], + "fields": [ + { + "name": "id", + "title": "id", + "type": "str", + "length": 32 + }, + { + "name": "orgid", + "title": "机构id", + "type": "str", + "length": 32 + }, + { + "name": "orgtypeid", + "title": "机构类型", + "type": "str", + "length": 100 + } + ], + "codes": [ + { + "field": "orgtypeid", + "table": "appcodes_kv", + "valuefield": "k", + "textfield": "v", + "cond": "parentid='org_type'" + } + ] +} \ No newline at end of file diff --git a/models/permission.json b/models/permission.json new file mode 100644 index 00000000..978332c1 --- /dev/null +++ b/models/permission.json @@ -0,0 +1,77 @@ +{ + "summary": [ + { + "name": "permission", + "title": "权限", + "primary": [ + "id" + ] + } + ], + "fields": [ + { + "name": "id", + "title": "权限id", + "type": "str", + "length": 32 + }, + { + "name": "name", + "title": "名称", + "type": "str", + "length": 255 + }, + { + "name": "description", + "title": "描述", + "type": "str", + "length": 255 + }, + { + "name": "ptype", + "title": "类型", + "type": "str", + "length": 20 + }, + { + "name": "parentid", + "title": "父权限id", + "type": "str", + "length": 32 + }, + { + "name": "path", + "title": "路径", + "type": "str", + "length": 255 + }, + { + "name": "title", + "title": "标题", + "type": "str", + "length": 255 + }, + { + "name": "icon", + "title": "图标", + "type": "str", + "length": 255 + } + ], + "indexes": [ + { + "name": "idx1", + "idxtype": "index", + "idxfields": [ + "ptype" + ] + }, + { + "name": "idx2", + "idxtype": "index", + "idxfields": [ + "parentid" + ] + } + ] +} \ No newline at end of file diff --git a/models/role.json b/models/role.json new file mode 100644 index 00000000..5c36614a --- /dev/null +++ b/models/role.json @@ -0,0 +1,57 @@ +{ + "summary": [ + { + "name": "role", + "title": " 角色", + "primary": [ + "id" + ] + } + ], + "fields": [ + { + "name": "id", + "title": "角色id", + "type": "str", + "length": 32 + }, + { + "name": "orgtypeid", + "title": "机构类型", + "type": "str", + "length": 32, + "default": "0" + }, + { + "name": "role", + "title": "角色", + "type": "str", + "length": 100 + }, + { + "name": "rolelabel", + "title": "角色名称", + "type": "str", + "length": 100 + } + ], + "indexes": [ + { + "name": "idx1", + "idxtype": "unique", + "idxfields": [ + "orgtypeid", + " role" + ] + } + ], + "codes": [ + { + "field": "orgtypeid", + "table": "appcodes_kw", + "valuefield": "k", + "textfield": "v", + "cond": "parentid='org_type'" + } + ] +} \ No newline at end of file diff --git a/models/rolepermission.json b/models/rolepermission.json new file mode 100644 index 00000000..1d4209cc --- /dev/null +++ b/models/rolepermission.json @@ -0,0 +1,31 @@ +{ + "summary": [ + { + "name": "rolepermission", + "title": "角色权限表", + "primary": [ + "id" + ] + } + ], + "fields": [ + { + "name": "id", + "title": "id", + "type": "str", + "length": 32 + }, + { + "name": "roleid", + "title": "角色id", + "type": "str", + "length": 32 + }, + { + "name": "permid", + "title": "权限id", + "type": "str", + "length": 32 + } + ] +} \ No newline at end of file diff --git a/models/token_usage.json b/models/token_usage.json new file mode 100644 index 00000000..07de4281 --- /dev/null +++ b/models/token_usage.json @@ -0,0 +1,91 @@ +{ + "summary": [ + { + "name": "token_usgae", + "title": "token使用表", + "primary": [ + "id" + ] + } + ], + "fields": [ + { + "name": "id", + "title": "id", + "type": "str", + "length": 32 + }, + { + "name": "customerid", + "title": "客户id", + "type": "str", + "length": 32 + }, + { + "name": "userid", + "title": "用户id", + "type": "str", + "length": 32 + }, + { + "name": "callname", + "title": "调用名", + "type": "str", + "length": 100 + }, + { + "name": "modelinstanceid", + "title": "模型实例id", + "type": "str", + "length": 255 + }, + { + "name": "u_date", + "title": "使用日期", + "type": "date", + "length": 255 + }, + { + "name": "u_time", + "title": "使用时间", + "type": "timestamp", + "length": 32 + }, + { + "name": "input_usage", + "title": "输入token数", + "type": "long" + }, + { + "name": "output_usage", + "title": "输出token数", + "type": "long" + } + ], + "indexes": [ + { + "name": "idx1", + "idxtype": "index", + "idxfields": [ + "userid" + ] + }, + { + "name": "idx2", + "idxtype": "index", + "idxfields": [ + "customerid", + "userid", + "modelinstanceid" + ] + }, + { + "name": "idx3", + "idxtype": "index", + "idxfields": [ + "customerid", + "modelinstanceid" + ] + } + ] +} \ No newline at end of file diff --git a/models/userapikey.json b/models/userapikey.json new file mode 100644 index 00000000..877a7452 --- /dev/null +++ b/models/userapikey.json @@ -0,0 +1,94 @@ +{ + "summary": [ + { + "name": "userapikey", + "title": "用户api密码表", + "primary": [ + "id" + ] + } + ], + "fields": [ + { + "name": "id", + "title": "id", + "type": "str", + "length": 32 + }, + { + "name": "providerid", + "title": "供应商id", + "type": "str", + "length": 200 + }, + { + "name": "ownerid", + "title": "属主id", + "type": "str", + "length": 32, + "default": "0" + }, + { + "name": "apikey", + "title": "api密钥", + "type": "str", + "length": 4000, + "default": "0" + }, + { + "name": "secretkey", + "title": "附属密钥", + "type": "str", + "length": 4000 + }, + { + "name": "rfname", + "title": "函数名", + "type": "str", + "length": 400 + }, + { + "name": "apiuser", + "title": "api用户", + "type": "str", + "length": 100 + }, + { + "name": "apipasswd", + "title": "api密码", + "type": "str", + "length": 32 + } + ], + "indexes": [ + { + "name": "idx1", + "idxtype": "unique", + "idxfields": [ + "providerid", + "customerid" + ] + }, + { + "name": "idx2", + "idxtype": "index", + "idxfields": [ + "customerid" + ] + } + ], + "codes": [ + { + "field": "providerid", + "table": "organization", + "valuefield": "id", + "textfield": "orgname" + }, + { + "field": "ownerid", + "table": "organization", + "valuefield": "id", + "textfield": "orgname" + } + ] +} \ No newline at end of file diff --git a/models/userdepartment.json b/models/userdepartment.json new file mode 100644 index 00000000..809aa871 --- /dev/null +++ b/models/userdepartment.json @@ -0,0 +1,43 @@ +{ + "summary": [ + { + "name": "userdepartment", + "title": "用户部门表", + "primary": [ + "id" + ] + } + ], + "fields": [ + { + "name": "id", + "title": "id", + "type": "str", + "length": 32 + }, + { + "name": "userid", + "title": "用户id", + "type": "str", + "length": 32 + }, + { + "name": "depid", + "title": "部门id", + "type": "str", + "length": 32 + }, + { + "name": "del_flg", + "title": "删除标志", + "type": "str", + "length": 1, + "default": "0" + }, + { + "name": "create_at", + "title": "创建时间戳", + "type": "timestamp" + } + ] +} \ No newline at end of file diff --git a/models/userroles.json b/models/userroles.json new file mode 100644 index 00000000..d7cc3568 --- /dev/null +++ b/models/userroles.json @@ -0,0 +1,45 @@ +{ + "summary": [ + { + "name": "userrole", + "title": "用户角色", + "primary": [ + "id" + ] + } + ], + "fields": [ + { + "name": "id", + "title": "用户id", + "type": "str", + "length": 32 + }, + { + "name": "userid", + "title": "用户id", + "type": "str", + "length": 32 + }, + { + "name": "roleid", + "title": "角色id", + "type": "str", + "length": 32 + } + ], + "codes": [ + { + "field": "userid", + "table": "users", + "valuefield": "id", + "textfield": "username" + }, + { + "field": "roleid", + "table": "role", + "valuefield": "id", + "textfield": "role" + } + ] +} \ No newline at end of file diff --git a/models/users.json b/models/users.json new file mode 100644 index 00000000..b0219d55 --- /dev/null +++ b/models/users.json @@ -0,0 +1,90 @@ +{ + "summary": [ + { + "name": "users", + "title": "用户", + "primary": [ + "id" + ] + } + ], + "fields": [ + { + "name": "id", + "title": "用户id", + "type": "str", + "length": 32 + }, + { + "name": "username", + "title": "用户名", + "type": "str", + "length": 255 + }, + { + "name": "name", + "title": "姓名", + "type": "str", + "length": 255 + }, + { + "name": "password", + "title": "密码", + "type": "str", + "length": 255 + }, + { + "name": "email", + "title": "邮件地址", + "type": "str", + "length": 255 + }, + { + "name": "orgid", + "title": "所属机构", + "type": "str", + "length": 32 + }, + { + "name": "nick_name", + "title": "显示名", + "type": "str", + "length": 255 + }, + { + "name": "address", + "title": "地址", + "type": "str", + "length": 255 + }, + { + "name": "mobile", + "title": "手机", + "type": "str", + "length": 255 + }, + { + "name": "user_status", + "title": "用户状态", + "type": "str", + "length": 1, + "default": "0" + } + ], + "indexes": [ + { + "name": "idx1", + "idxtype": "index", + "idxfields": [ + "orgid" + ] + }, + { + "name": "idx2", + "idxtype": "unique", + "idxfields": [ + "username" + ] + } + ] +} \ No newline at end of file diff --git a/models/xterm.json b/models/xterm.json new file mode 100644 index 00000000..5ea4ae4e --- /dev/null +++ b/models/xterm.json @@ -0,0 +1,51 @@ +{ + "summary": [ + { + "name": "xterm", + "title": "终端", + "primary": [ + "id" + ] + } + ], + "fields": [ + { + "name": "id", + "title": "id", + "type": "str", + "length": 32 + }, + { + "name": "name", + "title": "终端名称", + "type": "str", + "length": 400 + }, + { + "name": "hostid", + "title": "描述", + "type": "str", + "length": 500 + }, + { + "name": "ownerid", + "title": "属主id", + "type": "str", + "length": 32 + }, + { + "name": "cmd", + "title": "命令", + "type": "str", + "length": 2000 + } + ], + "codes": [ + { + "field": "hostid", + "table": "hostdev", + "valuefield": "id", + "textfield": "name" + } + ] +} \ No newline at end of file diff --git a/pay_private_key.pem b/pay_private_key.pem new file mode 100644 index 00000000..2b27ec0c --- /dev/null +++ b/pay_private_key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDLwRhu06ULipoH +eO89TdCMUiGsafCqzbLlCVDxRcHXLZV4fiNQAwVLonYHZnlNq/kYzJbsXWyqz+FF +RanbD47JSPlMPGZOoYZ2ANVLQIk8OD9RfWjuDcw/0RtjmiaPnqgRZluNU7gvWYEF ++JBFTHiGUKdopuR5rVctq37b64azB6XsGRmQfvmuoG2bW/SIngnI1ReBR9W3Jhf6 +lFG3EaW6VaW12JbgbHGC+UwjzlzQYJgeaKOyCLXvo6fGnqZ1dgQy/Fs5YmGX6emT +VO6t+Sgh1ipJeWl3192g+ntLzkokjtjsUw1UVXkPMCOsuo8tVN7upgK+ubDtMv5P +pPxAWYuzAgMBAAECggEAFgFE0r9KbVcq2xC9VwkUM1CxcKNBCdP3nz26Kfx8epvi +hHtW8/lc3+DBT3uf29AYBwzIEJSRu6wsv474+6llTylxkcFaKTbPmedCzILr71Qs +c8VlXi72S+luRFEDG3KpOGEuFQghdaz8aWPWrO1H0ksGnB+eFY1aGMVoiMwZ0DQb +asXW52rbuS/fpC5cg3ydsz6icDHyb/J1Zqp/UeHTL36Wl6pg+CDcKeYIWJ4tb//F +IGW4xvN3s49HqhtYK0VUNTP3dyabyLb9VQFLuAEJpdjZHQgzeqgHugRv1RVGzIls +SX2lRJz2e13W6Zp/TNtBKYfOaNLsHG4O4wawpkvmzQKBgQDiYvVLe+HwRgEIZciB +q6Jo9E8D3BCar3Wl6AFyNqePI32XaYazJwbXt4Ir9VRExFAL0gFfe8BWlk3ZJSvl +I6orE9Wc0J5/qHGasim4Jhs8YQhBj3sEo964RCgM88Aj5aQAsgQ0LtM3u9kcwju/ +c5mXEYyzwBrodbPm6Tz8ZTFOJQKBgQDmaD8nlYkJPP4zgTSvKCZnWBuCa35mn7TV +ZqD0mUNzdE3ySClVORxV3AxBOQaDV8cJFqGWz3NfSBtzthUe/NpUI2IDWYFNp2SO +2eNcV0Oiq9m1LXiGZfO4AMui+0iALm2e+ArVqjewVc5QsPiuY4aztci1IcPH0jJi +Dm2CRuKu9wKBgDIa5uGLDKmqRMZACM2yWCLUl7xp837ZALf0joVh1VoX588gOwDh +zWDnK7dg+AK0VGcZVtZ0RFCluZsq3/k6GIqqPCgWAE6O0H4Fmrg4LuUBMNuZzwdq +4Xt1Ekwzkr4fMFo7DDUke/kk6Vu1HZY1FrRZ3QNXrFzw2B1uV+Ig33XFAoGAHWM4 +gu0AwIvmBF27gYfGdjH3uEfLpH1ETF+9sdUGlGhGNNvdYcBaC914Nq12VjRQ76jS +TXECTyncToLv6LbphgfJTZIR+vyZx9qktDdxKgNvTjuRftrsHhED6DLSyX6ifr82 +apA+cCBRo1sfLOcG3E8YXXoEBa2avYUHlLFD4nsCgYB/7t/ZukC100AInglfUW68 +QXSNZTm7hk7N3mdZ83KQ5FarihdNWOAixy/0I0KMgr8QDDzDj8rlcODl0hLlyJta +0D3nb94Kzq86TFjX3t9vSfXJnGzIqhFY63QEegOcGuALGH3fp6GQUV7rUty831q/ +XbjVeIOQP4Rbda60fSDAYg== +-----END PRIVATE KEY----- diff --git a/reset_superuser_password.py b/reset_superuser_password.py new file mode 100644 index 00000000..f1f505d5 --- /dev/null +++ b/reset_superuser_password.py @@ -0,0 +1,50 @@ +import asyncio +from sqlor.dbpools import DBPools +from appPublic.jsonConfig import getConfig +from ahserver.globalEnv import password_encode + +async def reset_superuser_password(): + config = getConfig('.') + db = DBPools(config.databases) + + # 直接使用sage数据库(从配置看只有一个sage数据库) + # rbac模块的表应该也在sage数据库中 + dbname = 'sage' + + new_password = 'admin123' + encoded_password = password_encode(new_password) + + async with db.sqlorContext(dbname) as sor: + # 先检查superuser是否存在 + users = await sor.R('users', {'username': 'superuser'}) + if not users: + print('superuser用户不存在') + return False + + user = users[0] + print(f'找到用户: id={user.id}, username={user.username}') + + # 更新密码 + ns = { + 'id': user.id, + 'password': encoded_password + } + await sor.U('users', ns) + print(f'密码已更新为新密码: {new_password}') + + # 验证更新 - 使用sqlExe直接查询 + verify_sql = "select username from users where username='superuser' and password=${password}$" + verify_result = await sor.sqlExe(verify_sql, {'password': encoded_password}) + if verify_result: + print('密码验证成功') + else: + print('密码验证失败') + + return True + +if __name__ == '__main__': + success = asyncio.get_event_loop().run_until_complete(reset_superuser_password()) + if success: + print('superuser密码重置完成') + else: + print('密码重置失败') diff --git a/sage.service b/sage.service new file mode 100644 index 00000000..8c367279 --- /dev/null +++ b/sage.service @@ -0,0 +1,16 @@ +[Unit] +Wants=systemd-networkd.service + +[Service] +User=hermesai +Group=hermesai +Type=forking +WorkingDirectory=/home/hermesai/repos/sage +ExecStart=/home/hermesai/repos/sage/start.sh +ExecStop=/home/hermesai/repos/sage/stop.sh +StandardOutput=append:/var/log/sage/sage.log +StandardError=append:/var/log/sage/sage.log +SyslogIdentifier=sage + +[Install] +WantedBy=multi-user.target diff --git a/script/deploy_shell.sh b/script/deploy_shell.sh new file mode 100644 index 00000000..99fdc362 --- /dev/null +++ b/script/deploy_shell.sh @@ -0,0 +1,49 @@ +#!/bin/bash +# Deploy sage shell files to production wwwroot +# Usage: bash ~/sage/script/deploy_shell.sh +# +# This script copies index.ui and global_menu.ui from the git repo +# to the production wwwroot directory (which is gitignored). + +set -e + +SAGE_DIR="${SAGE_HOME:-$HOME/sage}" +SAGE_WWWROOT="$SAGE_DIR/wwwroot" +SAGE_REPO="$HOME/repos/sage/wwwroot" + +echo "Deploying sage shell files..." +echo "Source: $SAGE_REPO" +echo "Target: $SAGE_WWWROOT" +echo "" + +# Ensure wwwroot exists +mkdir -p "$SAGE_WWWROOT" + +# Copy index.ui +if [ -f "$SAGE_REPO/index.ui" ]; then + cp "$SAGE_REPO/index.ui" "$SAGE_WWWROOT/index.ui" + echo "✓ index.ui (Shell layout with sidebar)" +else + echo "✗ index.ui not found in $SAGE_REPO" + exit 1 +fi + +# Copy global_menu.ui +if [ -f "$SAGE_REPO/global_menu.ui" ]; then + cp "$SAGE_REPO/global_menu.ui" "$SAGE_WWWROOT/global_menu.ui" + echo "✓ global_menu.ui (Global navigation menu)" +else + echo "✗ global_menu.ui not found in $SAGE_REPO" + exit 1 +fi + +# Remove old symlinks if exist +rm -f "$SAGE_WWWROOT/dashboard_for_sage" 2>/dev/null || true + +echo "" +echo "Deployed to $SAGE_WWWROOT/" +echo "" +echo "Next steps:" +echo " 1. cd ~/repos/dashboard_for_sage && git pull" +echo " 2. cd ~/repos/bricks && git pull && bash build.sh" +echo " 3. cd ~/sage && ./stop.sh && ./start.sh" diff --git a/script/merge_i18n.py b/script/merge_i18n.py new file mode 100644 index 00000000..56532268 --- /dev/null +++ b/script/merge_i18n.py @@ -0,0 +1,118 @@ +#!/usr/bin/env python3 +""" +合并所有模块的i18n到wwwroot/i18n目录 + +用法: python3 script/merge_i18n.py +""" + +import os +import json +from pathlib import Path +from collections import OrderedDict + + +def parse_msg_txt(filepath): + """解析msg.txt文件,返回字典""" + result = OrderedDict() + if not os.path.exists(filepath): + return result + + with open(filepath, 'r', encoding='utf-8') as f: + for line in f: + line = line.strip() + if not line or line.startswith('#'): + continue + if ':' in line: + key, value = line.split(':', 1) + result[key.strip()] = value.strip() + return result + + +def write_msg_txt(data, filepath): + """写入msg.txt文件""" + os.makedirs(os.path.dirname(filepath), exist_ok=True) + with open(filepath, 'w', encoding='utf-8') as f: + for key, value in data.items(): + f.write(f"{key}: {value}\n") + + +def write_i18n_json(data, filepath): + """写入i18n.json文件""" + os.makedirs(os.path.dirname(filepath), exist_ok=True) + with open(filepath, 'w', encoding='utf-8') as f: + json.dump(data, f, ensure_ascii=False, indent=2) + + +def get_modules_from_lnwww(): + """从lnwww.sh读取模块列表""" + lnwww_path = Path(__file__).parent.parent / 'wwwroot' / 'lnwww.sh' + if not lnwww_path.exists(): + print(f"警告: {lnwww_path} 不存在") + return [] + + modules = [] + with open(lnwww_path, 'r', encoding='utf-8') as f: + for line in f: + line = line.strip() + if line.startswith('for m in'): + # "for m in xxx yyy zzz" -> "xxx yyy zzz" + parts = line.split('for m in ', 1)[1].strip().split() + modules = [p for p in parts if p != 'do'] + break + return modules + + +def merge_i18n(): + """主函数:合并i18n""" + sage_root = Path(__file__).parent.parent + wwwroot_i18n = sage_root / 'wwwroot' / 'i18n' + base_i18n = sage_root / 'i18n' + + # 获取模块列表 + modules = get_modules_from_lnwww() + print(f"发现模块: {', '.join(modules)}") + + # 语言列表 + languages = ['zh', 'en', 'jp', 'ko'] + + for lang in languages: + print(f"\n处理语言: {lang}") + + # 从基础i18n开始 + merged = OrderedDict() + base_msg = base_i18n / lang / 'msg.txt' + if base_msg.exists(): + merged.update(parse_msg_txt(base_msg)) + print(f" ✓ 加载基础i18n: {len(merged)} 条") + + # 合并每个模块的i18n + for module in modules: + # 模块可能在 ~/py//i18n 或 ~/repos//i18n + module_i18n_paths = [ + Path.home() / 'py' / module / 'i18n' / lang / 'msg.txt', + Path.home() / 'repos' / module / 'i18n' / lang / 'msg.txt', + ] + + for msg_path in module_i18n_paths: + if msg_path.exists(): + before = len(merged) + merged.update(parse_msg_txt(msg_path)) + added = len(merged) - before + print(f" ✓ {module}: +{added} 条 (共 {len(merged)} 条)") + break + + # 写入结果 + out_msg = wwwroot_i18n / lang / 'msg.txt' + out_json = wwwroot_i18n / lang / 'i18n.json' + + write_msg_txt(merged, out_msg) + write_i18n_json(merged, out_json) + + print(f" → 写入 {out_msg}") + print(f" → 写入 {out_json}") + + print("\n✓ 合并完成") + + +if __name__ == '__main__': + merge_i18n() diff --git a/scripts/demucs-status.dspy b/scripts/demucs-status.dspy new file mode 100644 index 00000000..aa8c9f2e --- /dev/null +++ b/scripts/demucs-status.dspy @@ -0,0 +1,29 @@ +# Demucs 任务状态查询 +# GET /demucs/api/demucs-status?task_id=xxx +task_id = params_kw.task_id +if not task_id: + return {"error": "task_id is required"} + +env = request._run_ns +longtasks = env.longtasks +if not longtasks: + return {"error": "longtasks not available"} + +task = await longtasks.get_redis_task(task_id) +if not task or not task.get("created_at"): + return {"task_id": task_id, "status": "not_found"} + +status = task.get("status", "unknown") +result = {"task_id": task_id, "status": status} + +if status == "SUCCEEDED": + data = task.get("result", {}) + result["vocals_url"] = data.get("vocals_path", "") + result["accompaniment_url"] = data.get("accompaniment_path", "") + result["duration"] = data.get("duration", 0) + # worker 须在 result 中包含 usage 字段 + result["usage"] = data.get("usage", {"audio_seconds": data.get("duration", 0)}) +elif status == "FAILED": + result["error"] = task.get("error", str(task.get("result", ""))) + +return result diff --git a/scripts/demucs_worker_usage_fix.py b/scripts/demucs_worker_usage_fix.py new file mode 100644 index 00000000..d6501a7d --- /dev/null +++ b/scripts/demucs_worker_usage_fix.py @@ -0,0 +1,9 @@ +# Patch for /data/ymq/demucs-service/workers/separate.py +# In run_separate_full(), ensure the return dict includes: +# "usage": {"audio_seconds": duration} + +# Find the return statement in run_separate_full and add usage field. +# The function currently returns something like: +# return {"vocals_path": ..., "accompaniment_path": ..., "duration": ...} +# +# Add: "usage": {"audio_seconds": result.get("duration", 0)} diff --git a/scripts/doubao_models_migration.sql b/scripts/doubao_models_migration.sql new file mode 100644 index 00000000..ff8c0c28 --- /dev/null +++ b/scripts/doubao_models_migration.sql @@ -0,0 +1,96 @@ +-- ============================================================ +-- 豆包大模型接入: 火山方舟 ARK API +-- +-- 模型: +-- 1. doubao-2.1-pro — 豆包大模型2.1 Pro (文本对话) +-- 2. doubao-seedream-5.0 — 豆包图像创作模型5.0 (文生图) +-- 3. doubao-speech-2.0 — 豆包语音识别模型2.0 (语音识别) +-- +-- Provider: 豆包 (Cy-zrc4DgLIFuA0KMQzlw) +-- Upapp: huoshanfangzhou (火山方舟, baseurl: https://ark.cn-beijing.volces.com/api/v3) +-- ============================================================ + +-- ===================== Part 1: llm ===================== +INSERT INTO llm (id,name,model,description,iconid,upappid,providerid,ownerid,enabled_date,expired_date,min_balance,status) VALUES +('llm_doubao_21_pro','doubao-2.1-pro','doubao-seed-2-1-pro-260628','豆包大模型2.1 Pro — 260628版本,256K上下文,文本对话',NULL,'huoshanfangzhou','Cy-zrc4DgLIFuA0KMQzlw','0','2025-01-01','2099-12-31',0.00,'published'), +('llm_doubao_seedream_5','doubao-seedream-5.0','doubao-seedream-5-0-260128','豆包图像创作模型5.0 — 260128版本,文生图',NULL,'huoshanfangzhou','Cy-zrc4DgLIFuA0KMQzlw','0','2025-01-01','2099-12-31',0.00,'published'), +('llm_doubao_speech_2','doubao-speech-2.0','doubao-speech-2.0','豆包语音识别模型2.0 — 语音转文字',NULL,'huoshanfangzhou','Cy-zrc4DgLIFuA0KMQzlw','0','2025-01-01','2099-12-31',0.00,'published') +ON DUPLICATE KEY UPDATE model=VALUES(model), description=VALUES(description); + +-- ===================== Part 2: llm_api_map ===================== +INSERT INTO llm_api_map (id,llmid,llmcatelogid,apiname,query_apiname,query_period,ppid,isdefaultcatelog) VALUES +-- 豆包2.1 Pro → 文本对话 (t2t) +('map_doubao_21_pro','llm_doubao_21_pro','t2t','doubao-chat',NULL,NULL,'pp_doubao_21_pro','1'), +-- 豆包图像5.0 → 文生图 (t2i) +('map_doubao_seedream_5','llm_doubao_seedream_5','t2i','doubao-image',NULL,NULL,'pp_doubao_seedream_5','1'), +-- 豆包语音2.0 → 语音识别 (asr) +('map_doubao_speech_2','llm_doubao_speech_2','asr','doubao-asr',NULL,NULL,'pp_doubao_speech_2','1') +ON DUPLICATE KEY UPDATE apiname=VALUES(apiname), ppid=VALUES(ppid); + +-- ===================== Part 3: uapi ===================== +-- 3a. 文本对话 (OpenAI-compatible chat) — sync +INSERT INTO uapi (id,name,title,description,need_auth,stream,path,httpmethod,chunk_match,headers,params,data,response,ioid,callbackurl,upappid) VALUES +('uapi_doubao_chat','doubao-chat','豆包大模型对话','豆包2.1 Pro文本对话','0','sync','/chat/completions','POST',NULL,'{"Content-Type":"application/json"}',NULL, +'{%if stream==True%}"stream_options":{"include_usage":true},"stream":true,{%endif%} +"messages":[ +{%if sys_prompt%}{"role":"system","content":{{json.dumps(sys_prompt,ensure_ascii=False)}}},{%endif%} +{"role":"user","content":[{%if image_file%}{"type":"image_url","image_url":"{{b64media2url(request,image_file)}}"},{%endif%}{%if video_file%}{"type":"video_url","video_url":"{{b64media2url(request,video_file)}}"},{%endif%}{%if audio_file%}{"type":"audio_url","audio_url":"{{b64media2url(request,audio_file)}}"},{%endif%}{"type":"text","text":{{json.dumps(prompt,ensure_ascii=False)}}}]} +], +"model":"{{model}}"', +'{"id":"{{id}}","object":"chat.completion","created":{{created}},"model":"{{model}}","choices":{{json.dumps(choices,ensure_ascii=False)}},"usage":{{json.dumps(usage,ensure_ascii=False)}}}', +NULL,NULL,'huoshanfangzhou') +ON DUPLICATE KEY UPDATE data=VALUES(data), response=VALUES(response); + +-- 3b. 图像生成 (async, ARK contents/generations) — async +INSERT INTO uapi (id,name,title,description,need_auth,stream,path,httpmethod,chunk_match,headers,params,data,response,ioid,callbackurl,upappid) VALUES +('uapi_doubao_image','doubao-image','豆包图像创作','豆包Seedream5.0图像生成','0','async','/contents/generations/tasks','POST',NULL,'{"Content-Type":"application/json"}',NULL, +'{"model":"{{model}}","content":[{"type":"text","text":{{json.dumps(prompt,ensure_ascii=False)}}}],"size":"{{size or \"1024x1024\"}}"}', +'{"taskid":"{{id}}","taskstatus":"PENDING","status":"PENDING"}', +NULL,NULL,'huoshanfangzhou') +ON DUPLICATE KEY UPDATE data=VALUES(data), response=VALUES(response); + +-- 3c. 语音识别 (sync, ARK audio/transcriptions) — sync +INSERT INTO uapi (id,name,title,description,need_auth,stream,path,httpmethod,chunk_match,headers,params,data,response,ioid,callbackurl,upappid) VALUES +('uapi_doubao_asr','doubao-asr','豆包语音识别','豆包Speech2.0语音转文字','0','sync','/audio/transcriptions','POST',NULL,'{"Content-Type":"multipart/form-data"}',NULL, +'{"model":"{{model}}"{%if audio_file%},"file":"{{b64media2url(request,audio_file)}}"{%endif%}{%if language%},"language":"{{language}}"{%endif%}}', +'{"text":"{{text}}"{%if segments%},"segments":{{json.dumps(segments,ensure_ascii=False)}}{%endif%}{%if usage%},"usage":{{json.dumps(usage,ensure_ascii=False)}}{%endif%}}', +NULL,NULL,'huoshanfangzhou') +ON DUPLICATE KEY UPDATE data=VALUES(data), response=VALUES(response); + + +-- ===================== Part 3b: uapiio (输入输出字段定义) ===================== +INSERT INTO uapiio (id,name,description,input_fields) VALUES +('doubao_chat_io','豆包大模型对话','文本对话输入输出','{"prompt":{"type":"string","required":true,"description":"用户输入文本"},"sys_prompt":{"type":"string","required":false,"description":"系统提示词"},"image_file":{"type":"string","required":false,"description":"图像URL(多模态)"},"max_tokens":{"type":"integer","required":false,"default":1024,"description":"最大输出token数"}}'), +('doubao_image_io','豆包图像创作','文生图输入输出','{"prompt":{"type":"string","required":true,"description":"图像描述文本"},"size":{"type":"string","required":false,"default":"1024x1024","description":"图像尺寸"},"n":{"type":"integer","required":false,"default":1,"description":"生成数量"}}'), +('doubao_asr_io','豆包语音识别','语音转文字输入输出','{"audio_file":{"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); + +-- Link uapi to uapiio +UPDATE uapi SET ioid='doubao_chat_io' WHERE id='uapi_doubao_chat'; +UPDATE uapi SET ioid='doubao_image_io' WHERE id='uapi_doubao_image'; +UPDATE uapi SET ioid='doubao_asr_io' WHERE id='uapi_doubao_asr'; + +-- ===================== Part 4: pricing_program ===================== +INSERT INTO pricing_program (id,name,ownerid,providerid,pricing_belong,description) VALUES +('pp_doubao_21_pro','豆包大模型2.1 Pro',NULL,'Cy-zrc4DgLIFuA0KMQzlw',NULL,'文本对话·按token计费'), +('pp_doubao_seedream_5','豆包图像创作5.0',NULL,'Cy-zrc4DgLIFuA0KMQzlw',NULL,'文生图·按张计费'), +('pp_doubao_speech_2','豆包语音识别2.0',NULL,'Cy-zrc4DgLIFuA0KMQzlw',NULL,'语音识别·按秒计费') +ON DUPLICATE KEY UPDATE name=VALUES(name); + +-- ===================== Part 5: pricing_program_timing ===================== +INSERT INTO pricing_program_timing (id,ppid,name,pricing_data,enabled_date,expired_date) VALUES +-- 文本对话: 按1K tokens计费 +('pt_doubao_21_pro','pp_doubao_21_pro','豆包2.1 Pro定价', +'unit_values:\n completion_tokens: 1000\n prompt_tokens: 1000\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: completion_tokens\n unit_prices: 0.001\n unit: 1K tokens\n- price_factors: prompt_tokens\n unit_prices: 0.0005\n unit: 1K tokens', +'2025-01-01','9999-12-31'), + +-- 图像生成: 按张计费 +('pt_doubao_seedream_5','pp_doubao_seedream_5','豆包Seedream5.0定价', +'unit_values:\n image_count: 1\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: image_count\n unit_prices: 0.02\n unit: image_count', +'2025-01-01','9999-12-31'), + +-- 语音识别: 按秒计费 +('pt_doubao_speech_2','pp_doubao_speech_2','豆包Speech2.0定价', +'unit_values:\n audio_seconds: 1\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: audio_seconds\n unit_prices: 0.004\n unit: audio_seconds', +'2025-01-01','9999-12-31') +ON DUPLICATE KEY UPDATE ppid=VALUES(ppid), pricing_data=VALUES(pricing_data); diff --git a/scripts/hunyuan_models_migration.sql b/scripts/hunyuan_models_migration.sql new file mode 100644 index 00000000..f59bdbde --- /dev/null +++ b/scripts/hunyuan_models_migration.sql @@ -0,0 +1,101 @@ +-- ============================================================ +-- 腾讯混元大模型接入: Hunyuan via tokenhub.tencentmaas.com +-- +-- 模型: +-- 1. hy3 — 混元 Hy3 (旗舰对话模型) +-- 2. hy-vision-2.0-instruct — HY-Vision 2.0 (视觉理解) +-- 3. hy-image-3.0-plus — HY Image V3.0 (文生图) +-- 4. hy-video-1.5 — HY Video 1.5 (文/图生视频) +-- +-- 定价来源: 腾讯官方文档 +-- Provider: 腾讯 (wNME9nrITooowlmCuR_XB) +-- Upapp: hunyun (5QXZ-AMP0K0NrcpZiTomA, baseurl: https://tokenhub.tencentmaas.com/v1) +-- ============================================================ + +-- ===================== Part 1: llm ===================== +INSERT INTO llm (id,name,model,description,iconid,upappid,providerid,ownerid,enabled_date,expired_date,min_balance,status) VALUES +('llm_hunyuan_hy3','hy3','hy3','混元 Hy3 — 旗舰对话模型,295B参数,128K上下文',NULL,'5QXZ-AMP0K0NrcpZiTomA','wNME9nrITooowlmCuR_XB','0','2025-01-01','2099-12-31',0.00,'published'), +('llm_hunyuan_vision2','hy-vision-2.0-instruct','hy-vision-2.0-instruct','HY-Vision 2.0 — 视觉理解,406B参数',NULL,'5QXZ-AMP0K0NrcpZiTomA','wNME9nrITooowlmCuR_XB','0','2025-01-01','2099-12-31',0.00,'published'), +('llm_hunyuan_image3','hy-image-3.0-plus','hy-image-v3.0','HY Image V3.0 — 文生图',NULL,'5QXZ-AMP0K0NrcpZiTomA','wNME9nrITooowlmCuR_XB','0','2025-01-01','2099-12-31',0.00,'published'), +('llm_hunyuan_video','hy-video-1.5','hy-video-1.5','HY Video 1.5 — 文/图生视频',NULL,'5QXZ-AMP0K0NrcpZiTomA','wNME9nrITooowlmCuR_XB','0','2025-01-01','2099-12-31',0.00,'published') +ON DUPLICATE KEY UPDATE model=VALUES(model), description=VALUES(description); + +-- ===================== Part 2: llm_api_map ===================== +INSERT INTO llm_api_map (id,llmid,llmcatelogid,apiname,query_apiname,query_period,ppid,isdefaultcatelog) VALUES +('map_hunyuan_hy3','llm_hunyuan_hy3','t2t','t2t',NULL,NULL,'pp_hunyuan_hy3','1'), +('map_hunyuan_vision2','llm_hunyuan_vision2','vision','ti2t',NULL,NULL,'pp_hunyuan_vision2','1'), +('map_hunyuan_image3','llm_hunyuan_image3','t2i','hunyuan-image-tokenhub','hunyuan-image-query','5','pp_hunyuan_image3','1'), +('map_hunyuan_video','llm_hunyuan_video','t2v','hunyuan-video-submit','hunyuan-video-query','5','pp_hunyuan_video','1') +ON DUPLICATE KEY UPDATE apiname=VALUES(apiname), query_apiname=VALUES(query_apiname), query_period=VALUES(query_period), ppid=VALUES(ppid); + +-- ===================== Part 3: uapiio ===================== +INSERT INTO uapiio (id,name,description,input_fields) VALUES +('hunyuan_chat_io','混元文本对话','文本对话','[{"name":"prompt","label":"用户输入","uitype":"text","required":true},{"name":"sys_prompt","label":"系统提示词","uitype":"text","required":false},{"name":"image_file","label":"图像URL","uitype":"image","required":false},{"name":"max_tokens","label":"最大输出Token","uitype":"number","required":false,"default":1024},{"name":"stream","label":"流式输出","uitype":"switch","required":false}]'), +('hunyuan_vision_io','混元视觉理解','视觉理解','[{"name":"prompt","label":"用户输入","uitype":"text","required":true},{"name":"image_file","label":"图像URL","uitype":"image","required":true},{"name":"sys_prompt","label":"系统提示词","uitype":"text","required":false},{"name":"max_tokens","label":"最大输出Token","uitype":"number","required":false,"default":1024}]'), +('hunyuan_image_io','混元图像生成','文生图(3.0)','[{"name":"prompt","label":"文本描述","uitype":"text","required":true},{"name":"image_file","label":"参考图URL","uitype":"image","required":false},{"name":"resolution","label":"分辨率","uitype":"text","required":false,"default":"1024:1024"},{"name":"seed","label":"随机种子","uitype":"number","required":false},{"name":"logo_add","label":"水印开关","uitype":"switch","required":false,"default":1},{"name":"revise","label":"Prompt改写","uitype":"switch","required":false,"default":1}]'), +('hunyuan_video_io','混元生视频','文/图生视频','[{"name":"prompt","label":"视频描述","uitype":"text","required":true},{"name":"image_file","label":"输入图像(图生视频)","uitype":"image","required":false},{"name":"resolution","label":"分辨率","uitype":"text","required":false,"default":"720P"}]') +ON DUPLICATE KEY UPDATE description=VALUES(description),input_fields=VALUES(input_fields); + +UPDATE uapi SET ioid='hunyuan_chat_io' WHERE id='AP29-fYCll4l-byxm3DHN' AND upappid='5QXZ-AMP0K0NrcpZiTomA'; +UPDATE uapi SET ioid='hunyuan_vision_io' WHERE id='qStjXm_Meu0nBjiRzdPew' AND upappid='5QXZ-AMP0K0NrcpZiTomA'; + +-- ===================== Part 4: image uapi (tokenhub, async + query) ===================== +INSERT INTO uapi (id,name,title,description,need_auth,stream,path,httpmethod,headers,data,response,ioid,upappid) VALUES +('uapi_hn_img_submit','hunyuan-image-tokenhub','混元生图3.0','异步提交','1','async','/api/image/submit','POST', +'{"Content-Type":"application/json"}', +'{"model":"hy-image-v3.0","prompt":"{{prompt}}"{%if image_file%},"images":["{{image_file}}"]{%endif%}{%if resolution%},"resolution":"{{resolution}}"{%endif%}{%if seed%},"seed":{{seed}}{%endif%}{%if logo_add%},"logo_add":{{logo_add}}{%endif%}{%if revise%},"revise":{{revise}}{%endif%}}', +'{"taskid":"{{id}}","taskstatus":"{{status}}","status":"{{status}}"}', +'hunyuan_image_io','5QXZ-AMP0K0NrcpZiTomA') +ON DUPLICATE KEY UPDATE data=VALUES(data),response=VALUES(response),path=VALUES(path); + +INSERT INTO uapi (id,name,title,description,need_auth,stream,path,httpmethod,headers,data,response,ioid,upappid) VALUES +('uapi_hn_img_query','hunyuan-image-query','混元生图3.0查询','任务查询','1','sync','/api/image/query','POST', +'{"Content-Type":"application/json"}', +'{"model":"hy-image-v3.0","id":"{{taskid}}"}', +'{"taskid":"{{id}}","taskstatus":"{{status}}","status":"{{status}}"{%if data%},"data":{{json.dumps(data,ensure_ascii=False)}}{%endif%}}', +'hunyuan_image_io','5QXZ-AMP0K0NrcpZiTomA') +ON DUPLICATE KEY UPDATE data=VALUES(data),response=VALUES(response),path=VALUES(path); + +-- ===================== Part 5: video uapi (tokenhub, async + query) ===================== +INSERT INTO uapi (id,name,title,description,need_auth,stream,path,httpmethod,headers,data,response,ioid,upappid) VALUES +('uapi_hn_vid_submit','hunyuan-video-submit','混元生视频','异步提交','1','async','/api/video/submit','POST', +'{"Content-Type":"application/json"}', +'{"model":"hy-video-1.5","prompt":"{{prompt}}"{%if image_file%},"images":["{{image_file}}"]{%endif%}{%if resolution%},"resolution":"{{resolution}}"{%endif%}}', +'{"taskid":"{{id}}","taskstatus":"{{status}}","status":"{{status}}"}', +'hunyuan_video_io','5QXZ-AMP0K0NrcpZiTomA') +ON DUPLICATE KEY UPDATE data=VALUES(data),response=VALUES(response),path=VALUES(path); + +INSERT INTO uapi (id,name,title,description,need_auth,stream,path,httpmethod,headers,data,response,ioid,upappid) VALUES +('uapi_hn_vid_query','hunyuan-video-query','混元生视频查询','任务查询','1','sync','/api/video/query','POST', +'{"Content-Type":"application/json"}', +'{"model":"hy-video-1.5","id":"{{taskid}}"}', +'{"taskid":"{{id}}","taskstatus":"{{status}}","status":"{{status}}"{%if data%},"data":{{json.dumps(data,ensure_ascii=False)}}{%endif%}}', +'hunyuan_video_io','5QXZ-AMP0K0NrcpZiTomA') +ON DUPLICATE KEY UPDATE data=VALUES(data),response=VALUES(response),path=VALUES(path); + +-- ===================== Part 6: pricing_program ===================== +INSERT INTO pricing_program (id,name,ownerid,providerid,pricing_belong,description) VALUES +('pp_hunyuan_hy3','混元Hy3旗舰对话',NULL,'wNME9nrITooowlmCuR_XB',NULL,'输入1元/百万,输出4元/百万'), +('pp_hunyuan_vision2','HY-Vision 2.0视觉',NULL,'wNME9nrITooowlmCuR_XB',NULL,'输入7.5元/百万,输出17.5元/百万'), +('pp_hunyuan_image3','HY Image V3.0',NULL,'wNME9nrITooowlmCuR_XB',NULL,'0.2元/张'), +('pp_hunyuan_video','HY Video 1.5',NULL,'wNME9nrITooowlmCuR_XB',NULL,'1.5元/次(1.0元/积分×1.5积分)') +ON DUPLICATE KEY UPDATE name=VALUES(name); + +-- ===================== Part 7: pricing_program_timing ===================== +INSERT INTO pricing_program_timing (id,ppid,name,pricing_data,enabled_date,expired_date) VALUES +('pt_hunyuan_hy3','pp_hunyuan_hy3','混元Hy3', +'unit_values:\n completion_tokens: 1000\n prompt_tokens: 1000\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: completion_tokens\n unit_prices: 0.004\n unit: 1K tokens\n- price_factors: prompt_tokens\n unit_prices: 0.001\n unit: 1K tokens', +'2025-01-01','9999-12-31'), + +('pt_hunyuan_vision2','pp_hunyuan_vision2','HY-Vision 2.0', +'unit_values:\n completion_tokens: 1000\n prompt_tokens: 1000\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: completion_tokens\n unit_prices: 0.0175\n unit: 1K tokens\n- price_factors: prompt_tokens\n unit_prices: 0.0075\n unit: 1K tokens', +'2025-01-01','9999-12-31'), + +('pt_hunyuan_image3','pp_hunyuan_image3','HY Image V3.0', +'unit_values:\n image_count: 1\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: image_count\n unit_prices: 0.2\n unit: image_count', +'2025-01-01','9999-12-31'), + +('pt_hunyuan_video','pp_hunyuan_video','HY-Video 1.5', +'unit_values:\n video_count: 1\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: video_count\n unit_prices: 1.5\n unit: video_count', +'2025-01-01','9999-12-31') +ON DUPLICATE KEY UPDATE ppid=VALUES(ppid), pricing_data=VALUES(pricing_data); diff --git a/scripts/ktv-nginx-10443.conf b/scripts/ktv-nginx-10443.conf new file mode 100644 index 00000000..c363b747 --- /dev/null +++ b/scripts/ktv-nginx-10443.conf @@ -0,0 +1,31 @@ +server { + listen 10443; + server_name ktv.opencomputing.net; + root /var/www/html; + client_max_body_size 20g; + proxy_buffering off; + + ssl_certificate /etc/letsencrypt/live/opencomputing.net/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/opencomputing.net/privkey.pem; + + add_header Access-Control-Allow-Origin *; + proxy_set_header X-Forwarded-Host $host; + proxy_set_header X-Forwarded-server $host; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Scheme $scheme; + proxy_set_header X-Forwarded-Port $server_port; + proxy_set_header X-real-ip $remote_addr; + proxy_send_timeout 600s; + proxy_read_timeout 600s; + + location /asr/ { proxy_pass http://localhost:9925/; } + location /demucs/ { proxy_pass http://localhost:9083/; } + location /face/ { proxy_pass http://localhost:9091/; } + location /subtitle/ { proxy_pass http://localhost:9080/; } + location /merge/ { proxy_pass http://localhost:9080/; } + location /songrate/ { proxy_pass http://localhost:8901/; } + location /synth/ { proxy_pass http://localhost:9084/; } + location /realesrgan/ { proxy_pass http://localhost:9082/; } + location /rvc/ { proxy_pass http://localhost:9085/; } + location /video-eval/ { proxy_pass http://localhost:8902/; } +} diff --git a/scripts/ktv_production_data.sql b/scripts/ktv_production_data.sql new file mode 100644 index 00000000..c257bd1d --- /dev/null +++ b/scripts/ktv_production_data.sql @@ -0,0 +1,313 @@ +-- KTV Production Data Export (JSON-quoted) +-- llm +/*M!999999\- enable the sandbox mode */ +-- MariaDB dump 10.19 Distrib 10.6.23-MariaDB, for debian-linux-gnu (x86_64) +-- +-- Host: localhost Database: sage +-- ------------------------------------------------------ +-- Server version 10.6.23-MariaDB-0ubuntu0.22.04.1 + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8mb4 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Dumping data for table `llm` +-- +-- WHERE: id LIKE "llm_ktv%" + +LOCK TABLES `llm` WRITE; +/*!40000 ALTER TABLE `llm` DISABLE KEYS */; +INSERT INTO `llm` (`id`, `name`, `model`, `description`, `iconid`, `upappid`, `providerid`, `ownerid`, `enabled_date`, `expired_date`, `min_balance`, `status`) VALUES ('llm_ktv_asr_transcribe','asr-transcribe','asr-transcribe','KTV语音识别',NULL,'ktv-gateway','FZoJv7EUEdKL3pUt0BQ5S','0','2025-01-01','2099-12-31',0.00,'published'),('llm_ktv_demucs_separate','demucs-separate','demucs-separate','KTV音频分离',NULL,'ktv-gateway','FZoJv7EUEdKL3pUt0BQ5S','0','2025-01-01','2099-12-31',0.00,'published'),('llm_ktv_face_compare','face-compare','face-compare','KTV人脸比对',NULL,'ktv-gateway','FZoJv7EUEdKL3pUt0BQ5S','0','2025-01-01','2099-12-31',0.00,'published'),('llm_ktv_face_detect','face-detect','face-detect','KTV人脸检测',NULL,'ktv-gateway','FZoJv7EUEdKL3pUt0BQ5S','0','2025-01-01','2099-12-31',0.00,'published'),('llm_ktv_face_recognize','face-recognize','face-recognize','KTV人脸识别',NULL,'ktv-gateway','FZoJv7EUEdKL3pUt0BQ5S','0','2025-01-01','2099-12-31',0.00,'published'),('llm_ktv_merge_video','merge-video','merge-video','KTV视频合并',NULL,'ktv-gateway','FZoJv7EUEdKL3pUt0BQ5S','0','2025-01-01','2099-12-31',0.00,'published'),('llm_ktv_realesrgan_status','realesrgan-status','realesrgan-status','KTV超分状态',NULL,'ktv-gateway','FZoJv7EUEdKL3pUt0BQ5S','0','2025-01-01','2099-12-31',0.00,'published'),('llm_ktv_realesrgan_upscale','realesrgan-upscale','realesrgan-upscale','KTV超分辨率',NULL,'ktv-gateway','FZoJv7EUEdKL3pUt0BQ5S','0','2025-01-01','2099-12-31',0.00,'published'),('llm_ktv_rvc_convert','rvc-convert','rvc-convert','KTV声音转换',NULL,'ktv-gateway','FZoJv7EUEdKL3pUt0BQ5S','0','2025-01-01','2099-12-31',0.00,'published'),('llm_ktv_songrate_evaluate','songrate-evaluate','songrate-evaluate','KTV歌曲评分',NULL,'ktv-gateway','FZoJv7EUEdKL3pUt0BQ5S','0','2025-01-01','2099-12-31',0.00,'published'),('llm_ktv_subtitle_render','subtitle-render','subtitle-render','KTV字幕渲染',NULL,'ktv-gateway','FZoJv7EUEdKL3pUt0BQ5S','0','2025-01-01','2099-12-31',0.00,'published'),('llm_ktv_synth_status','synth-status','synth-status','KTV合成状态',NULL,'ktv-gateway','FZoJv7EUEdKL3pUt0BQ5S','0','2025-01-01','2099-12-31',0.00,'published'),('llm_ktv_video_eval_evaluate','video-eval-evaluate','video-eval-evaluate','KTV视频评估',NULL,'ktv-gateway','FZoJv7EUEdKL3pUt0BQ5S','0','2025-01-01','2099-12-31',0.00,'published'); +/*!40000 ALTER TABLE `llm` ENABLE KEYS */; +UNLOCK TABLES; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- Dump completed on 2026-07-08 11:02:16 + +-- llm_api_map +/*M!999999\- enable the sandbox mode */ +-- MariaDB dump 10.19 Distrib 10.6.23-MariaDB, for debian-linux-gnu (x86_64) +-- +-- Host: localhost Database: sage +-- ------------------------------------------------------ +-- Server version 10.6.23-MariaDB-0ubuntu0.22.04.1 + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8mb4 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Dumping data for table `llm_api_map` +-- +-- WHERE: llmid LIKE "llm_ktv%" + +LOCK TABLES `llm_api_map` WRITE; +/*!40000 ALTER TABLE `llm_api_map` DISABLE KEYS */; +INSERT INTO `llm_api_map` (`id`, `llmid`, `llmcatelogid`, `apiname`, `query_apiname`, `query_period`, `ppid`, `isdefaultcatelog`) VALUES ('map_ktv_asr_transcribe','llm_ktv_asr_transcribe','ktv_pipeline','asr-transcribe','asr-status',5,'pp_ktv_asr','1'),('map_ktv_demucs_separate','llm_ktv_demucs_separate','ktv_pipeline','demucs-separate','demucs-status',5,'pp_ktv_demucs','1'),('map_ktv_face_compare','llm_ktv_face_compare','ktv_pipeline','face-compare',NULL,NULL,'pp_ktv_face_compare','1'),('map_ktv_face_detect','llm_ktv_face_detect','ktv_pipeline','face-detect',NULL,NULL,'pp_ktv_face_detect','1'),('map_ktv_face_recognize','llm_ktv_face_recognize','ktv_pipeline','face-recognize',NULL,NULL,'pp_ktv_face_recognize','1'),('map_ktv_merge_video','llm_ktv_merge_video','ktv_pipeline','merge-video',NULL,NULL,'pp_ktv_merge','1'),('map_ktv_realesrgan_status','llm_ktv_realesrgan_status','ktv_pipeline','realesrgan-status',NULL,NULL,'pp_ktv_realesrgan_status','1'),('map_ktv_realesrgan_upscale','llm_ktv_realesrgan_upscale','ktv_pipeline','realesrgan-upscale','realesrgan-status',5,'pp_ktv_realesrgan','1'),('map_ktv_rvc_convert','llm_ktv_rvc_convert','ktv_pipeline','rvc-convert',NULL,NULL,'pp_ktv_rvc','1'),('map_ktv_songrate_evaluate','llm_ktv_songrate_evaluate','ktv_pipeline','songrate-evaluate',NULL,NULL,'pp_ktv_songrate','1'),('map_ktv_subtitle_render','llm_ktv_subtitle_render','ktv_pipeline','subtitle-render',NULL,NULL,'pp_ktv_subtitle','1'),('map_ktv_synth_status','llm_ktv_synth_status','ktv_pipeline','synth-status',NULL,NULL,'pp_ktv_synth_status','1'),('map_ktv_video_eval_evaluate','llm_ktv_video_eval_evaluate','ktv_pipeline','video-eval-evaluate',NULL,NULL,'pp_ktv_video_eval','1'); +/*!40000 ALTER TABLE `llm_api_map` ENABLE KEYS */; +UNLOCK TABLES; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- Dump completed on 2026-07-08 11:02:16 + +-- uapi +/*M!999999\- enable the sandbox mode */ +-- MariaDB dump 10.19 Distrib 10.6.23-MariaDB, for debian-linux-gnu (x86_64) +-- +-- Host: localhost Database: sage +-- ------------------------------------------------------ +-- Server version 10.6.23-MariaDB-0ubuntu0.22.04.1 + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8mb4 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Dumping data for table `uapi` +-- +-- WHERE: upappid="ktv-gateway" + +LOCK TABLES `uapi` WRITE; +/*!40000 ALTER TABLE `uapi` DISABLE KEYS */; +INSERT INTO `uapi` (`id`, `name`, `title`, `description`, `need_auth`, `stream`, `path`, `httpmethod`, `chunk_match`, `headers`, `params`, `data`, `response`, `ioid`, `callbackurl`, `upappid`) VALUES ('uapi_ktv_asr_status','asr-status','ASR Status','Query ASR task','0','sync','/asr/api/task?task_id={{taskid}}','GET',NULL,'{\"Content-Type\":\"application/json\"}',NULL,NULL,'{\"status\":\"{{status}}\",\"segments\":{{json.dumps(segments,ensure_ascii=False)}},\"usage\":{{json.dumps(usage,ensure_ascii=False)}}}','ktv_asr_transcribe_io',NULL,'ktv-gateway'),('uapi_ktv_asr_transcribe','asr-transcribe','KTV语音识别','KTV语音识别','0','async','/asr/api/asr-transcribe','POST',NULL,'{\"Content-Type\":\"application/json\"}',NULL,'{\"audio_path\":\"{{audio_file}}\"{%if language%},\"language\":\"{{language}}\"{%endif%}}','{\"taskid\":\"{{task_id}}\",\"taskstatus\":\"PENDING\",\"status\":\"PENDING\"}','ktv_asr_transcribe_io',NULL,'ktv-gateway'),('uapi_ktv_demucs_separate','demucs-separate','KTV音频分离','KTV音频分离','0','async','/demucs/api/demucs-separate','POST',NULL,'{\"Content-Type\":\"application/json\"}',NULL,'{\"audio_path\":\"{{audio_file}}\"{%if task_type%},\"task_type\":\"{{task_type}}\"{%endif%}}','{\"taskid\":\"{{task_id}}\",\"taskstatus\":\"PENDING\",\"status\":\"PENDING\"}','ktv_demucs_separate_io',NULL,'ktv-gateway'),('uapi_ktv_demucs_status','demucs-status','Demucs Query','Query demucs task','0','sync','/demucs/api/demucs-status?task_id={{taskid}}','GET',NULL,'{\"Content-Type\":\"application/json\"}',NULL,NULL,'{\"status\":\"{{status}}\",\"vocals_url\":\"{{vocals_url}}\",\"accompaniment_url\":\"{{accompaniment_url}}\",\"duration\":{{duration}},\"usage\":{{json.dumps(usage,ensure_ascii=False)}}}','ktv_demucs_separate_io',NULL,'ktv-gateway'),('uapi_ktv_face_compare','face-compare','KTV人脸比对','KTV人脸比对','0','sync','/face/api/face-compare','POST',NULL,'{\"Content-Type\":\"application/json\"}',NULL,'{\"embedding1\":\"{{image_file1}}\",\"embedding2\":\"{{image_file2}}\"}','{% if error %}{\"error\":\"{{error}}\"}{% else %}{\"status\":\"{{status}}\",\"similarity\":{{similarity}},\"usage\":{{json.dumps(usage,ensure_ascii=False)}}}{% endif %}','ktv_face_compare_io',NULL,'ktv-gateway'),('uapi_ktv_face_detect','face-detect','KTV人脸检测','KTV人脸检测','0','sync','/face/api/face-detect','POST',NULL,'{\"Content-Type\":\"application/json\"}',NULL,'{\"images\":[\"{{image_file}}\"]}','{% if error %}{\"error\":\"{{error}}\"}{% else %}{\"status\":\"{{status}}\",\"faces\":{{json.dumps(faces,ensure_ascii=False)}},\"usage\":{{json.dumps(usage,ensure_ascii=False)}}}{% endif %}','ktv_face_detect_io',NULL,'ktv-gateway'),('uapi_ktv_face_recognize','face-recognize','KTV人脸识别','KTV人脸识别','0','sync','/face/api/face-recognize','POST',NULL,'{\"Content-Type\":\"application/json\"}',NULL,'{\"images\":[\"{{image_file}}\"]{%if face_id%},\"face_id\":\"{{face_id}}\"{%endif%}}','{% if error %}{\"error\":\"{{error}}\"}{% else %}{\"status\":\"{{status}}\",\"matches\":{{json.dumps(matches,ensure_ascii=False)}},\"usage\":{{json.dumps(usage,ensure_ascii=False)}}}{% endif %}','ktv_face_recognize_io',NULL,'ktv-gateway'),('uapi_ktv_merge_video','merge-video','KTV视频合并','KTV视频合并','0','sync','/merge/api/merge-video','POST',NULL,'{\"Content-Type\":\"application/json\"}',NULL,'{%set c=joiner(\",\")%}{{%if video_file%}{{c()}}\"video_url\":\"{{video_file}}\"{%endif%}{%if audio_file%}{{c()}}\"audio_path\":\"{{audio_file}}\"{%endif%}{%if subtitle_file%}{{c()}}\"subtitle_url\":\"{{subtitle_file}}\"{%endif%}{%if output_format%}{{c()}}\"output_format\":\"{{output_format}}\"{%endif%}}','{% if error %}{\"error\":\"{{error}}\"}{% else %}{\"status\":\"{{status}}\",\"output_url\":\"{{output_url}}\",\"duration\":{{duration}},\"usage\":{{json.dumps(usage,ensure_ascii=False)}}}{% endif %}','ktv_merge_video_io',NULL,'ktv-gateway'),('uapi_ktv_realesrgan_status','realesrgan-status','KTV超分状态','KTV超分状态','0','sync','/realesrgan/api/realesrgan-status?task_id={{taskid}}','GET',NULL,'{\"Content-Type\":\"application/json\"}',NULL,NULL,'{\"status\":\"{{status}}\",\"output_url\":\"{{output_url}}\",\"usage\":{{json.dumps(usage,ensure_ascii=False)}}}','ktv_realesrgan_status_io',NULL,'ktv-gateway'),('uapi_ktv_realesrgan_upscale','realesrgan-upscale','KTV超分辨率','KTV超分辨率','0','async','/realesrgan/api/realesrgan-upscale','POST',NULL,'{\"Content-Type\":\"application/json\"}',NULL,'{\"image_url\":\"{{image_file}}\"{%if scale%},\"scale\":{{scale}}{%endif%}}','{\"taskid\":\"{{task_id}}\",\"taskstatus\":\"PENDING\",\"status\":\"PENDING\"}','ktv_realesrgan_upscale_io',NULL,'ktv-gateway'),('uapi_ktv_rvc_convert','rvc-convert','KTV声音转换','KTV声音转换','0','sync','/rvc/api/rvc-convert','POST',NULL,'{\"Content-Type\":\"application/json\"}',NULL,'{\"audio_path\":\"{{audio_file}}\",\"model\":\"{{voice_model}}\"}','{% if error %}{\"error\":\"{{error}}\"}{% else %}{\"status\":\"{{status}}\",\"output_url\":\"{{output_url}}\",\"usage\":{{json.dumps(usage,ensure_ascii=False)}}}{% endif %}','ktv_rvc_convert_io',NULL,'ktv-gateway'),('uapi_ktv_songrate_evaluate','songrate-evaluate','KTV歌曲评分','KTV歌曲评分','0','sync','/songrate/api/songrate-evaluate','POST',NULL,'{\"Content-Type\":\"application/json\"}',NULL,'{\"audio_path\":\"{{audio_file}}\"{%if scene%},\"scene\":\"{{scene}}\"{%endif%}}','{% if error %}{\"error\":\"{{error}}\"}{% else %}{\"status\":\"{{status}}\",\"score\":{{score}},\"details\":{{json.dumps(details,ensure_ascii=False)}},\"usage\":{{json.dumps(usage,ensure_ascii=False)}}}{% endif %}','ktv_songrate_evaluate_io',NULL,'ktv-gateway'),('uapi_ktv_subtitle_render','subtitle-render','KTV字幕渲染','KTV字幕渲染','0','sync','/subtitle/api/subtitle-render','POST',NULL,'{\"Content-Type\":\"application/json\"}',NULL,'{\"lyrics\":{{lyrics_json}}{%if width%},\"width\":{{width}}{%endif%}{%if height%},\"height\":{{height}}{%endif%}}','{% if error %}{\"error\":\"{{error}}\"}{% else %}{\"status\":\"{{status}}\",\"ass_url\":\"{{ass_url}}\",\"usage\":{{json.dumps(usage,ensure_ascii=False)}}}{% endif %}','ktv_subtitle_render_io',NULL,'ktv-gateway'),('uapi_ktv_synth_status','synth-status','KTV合成状态','KTV合成状态','0','sync','/synth/api/synth-status?task_id={{taskid}}','GET',NULL,'{\"Content-Type\":\"application/json\"}','{\"task_id\":\"{{prompt}}\"}',NULL,'{%if status==\"SUCCEEDED\"%}{\"taskstatus\":\"SUCCEEDED\",\"output_url\":\"{{output_url}}\",\"usage\":{{json.dumps(usage,ensure_ascii=False)}}}{%elif status==\"FAILED\"%}{\"taskstatus\":\"FAILED\",\"error\":\"{{error}}\"}{%else%}{\"taskstatus\":\"PENDING\"}{%endif%}','ktv_synth_status_io',NULL,'ktv-gateway'),('uapi_ktv_video_eval_evaluate','video-eval-evaluate','KTV视频评估','KTV视频评估','0','sync','/video-eval/api/video-eval-evaluate','POST',NULL,'{\"Content-Type\":\"application/json\"}',NULL,'{\"video_url\":\"{{video_file}}\"}','{% if error %}{\"error\":\"{{error}}\"}{% else %}{\"status\":\"{{status}}\",\"score\":{{score}},\"details\":{{json.dumps(details,ensure_ascii=False)}},\"usage\":{{json.dumps(usage,ensure_ascii=False)}}}{% endif %}','ktv_video_eval_evaluate_io',NULL,'ktv-gateway'); +/*!40000 ALTER TABLE `uapi` ENABLE KEYS */; +UNLOCK TABLES; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- Dump completed on 2026-07-08 11:02:16 + +-- uapiio +/*M!999999\- enable the sandbox mode */ +-- MariaDB dump 10.19 Distrib 10.6.23-MariaDB, for debian-linux-gnu (x86_64) +-- +-- Host: localhost Database: sage +-- ------------------------------------------------------ +-- Server version 10.6.23-MariaDB-0ubuntu0.22.04.1 + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8mb4 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Dumping data for table `uapiio` +-- +-- WHERE: id LIKE "ktv_%" + +LOCK TABLES `uapiio` WRITE; +/*!40000 ALTER TABLE `uapiio` DISABLE KEYS */; +INSERT INTO `uapiio` (`id`, `name`, `description`, `input_fields`) VALUES ('ktv_asr_transcribe_io','KTV语音识别','上传音频文件,返回识别文本和时间戳','{\"audio_file\":{\"type\":\"string\",\"required\":true,\"description\":\"音频文件URL\"},\"language\":{\"type\":\"string\",\"required\":false,\"default\":\"zh\",\"description\":\"语言代码\"}}'),('ktv_demucs_separate_io','KTV音频分离','分离人声和伴奏','{\"audio_file\":{\"type\":\"string\",\"required\":true,\"description\":\"音频文件URL\"}}'),('ktv_face_compare_io','KTV人脸比对','比较两张人脸的相似度','{\"image_file1\":{\"type\":\"string\",\"required\":true,\"description\":\"图像1 URL\"},\"image_file2\":{\"type\":\"string\",\"required\":true,\"description\":\"图像2 URL\"}}'),('ktv_face_detect_io','KTV人脸检测','检测图像中的人脸位置','{\"image_file\":{\"type\":\"string\",\"required\":true,\"description\":\"图像URL\"}}'),('ktv_face_recognize_io','KTV人脸识别','识别人脸身份','{\"image_file\":{\"type\":\"string\",\"required\":true,\"description\":\"图像URL\"},\"face_id\":{\"type\":\"string\",\"required\":false,\"description\":\"人脸ID\"}}'),('ktv_merge_video_io','KTV视频合并','合并视频、音频和字幕','{\"video_file\":{\"type\":\"string\",\"required\":false,\"description\":\"视频URL\"},\"audio_file\":{\"type\":\"string\",\"required\":false,\"description\":\"音频URL\"},\"subtitle_file\":{\"type\":\"string\",\"required\":false,\"description\":\"ASS字幕URL\"},\"output_format\":{\"type\":\"string\",\"required\":false,\"default\":\"mp4\",\"description\":\"输出格式\"}}'),('ktv_realesrgan_status_io','KTV超分状态','查询超分任务状态','{\"task_id\":{\"type\":\"string\",\"required\":true,\"description\":\"任务ID\"}}'),('ktv_realesrgan_upscale_io','KTV超分辨率','图像/视频超分辨率(异步任务)','{\"image_file\":{\"type\":\"string\",\"required\":true,\"description\":\"图像URL\"},\"scale\":{\"type\":\"integer\",\"required\":false,\"default\":2,\"description\":\"放大倍数\"}}'),('ktv_rvc_convert_io','KTV声音转换','声音克隆/变声','{\"audio_file\":{\"type\":\"string\",\"required\":true,\"description\":\"输入音频URL\"},\"voice_model\":{\"type\":\"string\",\"required\":true,\"description\":\"目标声音模型名\"}}'),('ktv_songrate_evaluate_io','KTV歌曲评分','AI评估歌曲质量','{\"audio_file\":{\"type\":\"string\",\"required\":true,\"description\":\"音频文件URL\"},\"scene\":{\"type\":\"string\",\"required\":false,\"default\":\"pop\",\"description\":\"场景类型\"}}'),('ktv_subtitle_render_io','KTV字幕渲染','将歌词时间轴渲染为ASS字幕文件','{\"lyrics_json\":{\"type\":\"string\",\"required\":true,\"description\":\"歌词时间轴JSON\"},\"width\":{\"type\":\"integer\",\"required\":false,\"default\":1920,\"description\":\"视频宽度\"},\"height\":{\"type\":\"integer\",\"required\":false,\"default\":1080,\"description\":\"视频高度\"}}'),('ktv_synth_generate_io','KTV音乐合成','AI歌声合成(异步任务)','{\"lyrics\":{\"type\":\"string\",\"required\":true,\"description\":\"歌词文本\"},\"style\":{\"type\":\"string\",\"required\":false,\"default\":\"pop\",\"description\":\"演唱风格\"},\"audio_file\":{\"type\":\"string\",\"required\":false,\"description\":\"参考音频URL(声音克隆)\"}}'),('ktv_synth_status_io','KTV合成状态','查询音乐合成任务状态','{\"task_id\":{\"type\":\"string\",\"required\":true,\"description\":\"任务ID\"}}'),('ktv_video_eval_evaluate_io','KTV视频评估','评估视频质量','{\"video_file\":{\"type\":\"string\",\"required\":true,\"description\":\"视频URL\"}}'); +/*!40000 ALTER TABLE `uapiio` ENABLE KEYS */; +UNLOCK TABLES; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- Dump completed on 2026-07-08 11:02:16 + +-- pricing_program +/*M!999999\- enable the sandbox mode */ +-- MariaDB dump 10.19 Distrib 10.6.23-MariaDB, for debian-linux-gnu (x86_64) +-- +-- Host: localhost Database: sage +-- ------------------------------------------------------ +-- Server version 10.6.23-MariaDB-0ubuntu0.22.04.1 + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8mb4 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Dumping data for table `pricing_program` +-- +-- WHERE: id LIKE "pp_ktv%" OR id="pp_ktv" + +LOCK TABLES `pricing_program` WRITE; +/*!40000 ALTER TABLE `pricing_program` DISABLE KEYS */; +INSERT INTO `pricing_program` (`id`, `name`, `ownerid`, `providerid`, `pricing_belong`, `description`) VALUES ('pp_ktv','KTV产线计费',NULL,'FZoJv7EUEdKL3pUt0BQ5S',NULL,NULL),('pp_ktv_asr','KTV-语音识别',NULL,'FZoJv7EUEdKL3pUt0BQ5S',NULL,NULL),('pp_ktv_demucs','KTV-音频分离',NULL,'FZoJv7EUEdKL3pUt0BQ5S',NULL,NULL),('pp_ktv_face_compare','KTV-人脸比对',NULL,'FZoJv7EUEdKL3pUt0BQ5S',NULL,NULL),('pp_ktv_face_detect','KTV-人脸检测',NULL,'FZoJv7EUEdKL3pUt0BQ5S',NULL,NULL),('pp_ktv_face_recognize','KTV-人脸识别',NULL,'FZoJv7EUEdKL3pUt0BQ5S',NULL,NULL),('pp_ktv_merge','KTV-视频合并',NULL,'FZoJv7EUEdKL3pUt0BQ5S',NULL,NULL),('pp_ktv_realesrgan','KTV-超分辨率',NULL,'FZoJv7EUEdKL3pUt0BQ5S',NULL,NULL),('pp_ktv_realesrgan_status','KTV-超分状态',NULL,'FZoJv7EUEdKL3pUt0BQ5S',NULL,NULL),('pp_ktv_rvc','KTV-声音转换',NULL,'FZoJv7EUEdKL3pUt0BQ5S',NULL,NULL),('pp_ktv_songrate','KTV-歌曲评分',NULL,'FZoJv7EUEdKL3pUt0BQ5S',NULL,NULL),('pp_ktv_subtitle','KTV-字幕渲染',NULL,'FZoJv7EUEdKL3pUt0BQ5S',NULL,NULL),('pp_ktv_synth','KTV-音乐合成',NULL,'FZoJv7EUEdKL3pUt0BQ5S',NULL,NULL),('pp_ktv_synth_status','KTV-合成状态',NULL,'FZoJv7EUEdKL3pUt0BQ5S',NULL,NULL),('pp_ktv_video_eval','KTV-视频评估',NULL,'FZoJv7EUEdKL3pUt0BQ5S',NULL,NULL); +/*!40000 ALTER TABLE `pricing_program` ENABLE KEYS */; +UNLOCK TABLES; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- Dump completed on 2026-07-08 11:02:16 + +-- pricing_program_timing +/*M!999999\- enable the sandbox mode */ +-- MariaDB dump 10.19 Distrib 10.6.23-MariaDB, for debian-linux-gnu (x86_64) +-- +-- Host: localhost Database: sage +-- ------------------------------------------------------ +-- Server version 10.6.23-MariaDB-0ubuntu0.22.04.1 + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8mb4 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Dumping data for table `pricing_program_timing` +-- +-- WHERE: ppid LIKE "pp_ktv%" OR ppid="pp_ktv" + +LOCK TABLES `pricing_program_timing` WRITE; +/*!40000 ALTER TABLE `pricing_program_timing` DISABLE KEYS */; +INSERT INTO `pricing_program_timing` (`id`, `ppid`, `name`, `pricing_data`, `enabled_date`, `expired_date`) VALUES ('pt_ktv_asr_transcribe','pp_ktv_asr','KTV语音识别','unit_values:\n audio_seconds: 1\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: audio_seconds\n unit_prices: 0.01\n unit: audio_seconds','2025-01-01','9999-12-31'),('pt_ktv_demucs_separate','pp_ktv_demucs','KTV音频分离','unit_values:\n audio_seconds: 1\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: audio_seconds\n unit_prices: 0.02\n unit: audio_seconds','2025-01-01','9999-12-31'),('pt_ktv_face_compare','pp_ktv_face_compare','KTV人脸比对','unit_values:\n compare_count: 1\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: compare_count\n unit_prices: 0.10\n unit: compare_count','2025-01-01','9999-12-31'),('pt_ktv_face_detect','pp_ktv_face_detect','KTV人脸检测','unit_values:\n detect_count: 1\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: detect_count\n unit_prices: 0.10\n unit: detect_count','2025-01-01','9999-12-31'),('pt_ktv_face_recognize','pp_ktv_face_recognize','KTV人脸识别','unit_values:\n recognize_count: 1\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: recognize_count\n unit_prices: 0.10\n unit: recognize_count','2025-01-01','9999-12-31'),('pt_ktv_merge_video','pp_ktv_merge','KTV视频合并','unit_values:\n output_seconds: 1\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: output_seconds\n unit_prices: 0.01\n unit: output_seconds','2025-01-01','9999-12-31'),('pt_ktv_realesrgan_status','pp_ktv_realesrgan_status','KTV超分状态','unit_values:\n 次: 1\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: flat\n unit_prices: 0.01\n unit: 次','2025-01-01','9999-12-31'),('pt_ktv_realesrgan_upscale','pp_ktv_realesrgan','KTV超分辨率','unit_values:\n image_count: 1\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: image_count\n unit_prices: 0.50\n unit: image_count','2025-01-01','9999-12-31'),('pt_ktv_rvc_convert','pp_ktv_rvc','KTV声音转换','unit_values:\n audio_seconds: 1\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: audio_seconds\n unit_prices: 0.15\n unit: audio_seconds','2025-01-01','9999-12-31'),('pt_ktv_songrate_evaluate','pp_ktv_songrate','KTV歌曲评分','unit_values:\n audio_seconds: 1\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: audio_seconds\n unit_prices: 0.005\n unit: audio_seconds','2025-01-01','9999-12-31'),('pt_ktv_subtitle_render','pp_ktv_subtitle','KTV字幕渲染','unit_values:\n subtitle_count: 1\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: subtitle_count\n unit_prices: 0.01\n unit: subtitle_count','2025-01-01','9999-12-31'),('pt_ktv_synth_status','pp_ktv_synth_status','KTV合成状态','unit_values:\n 次: 1\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: flat\n unit_prices: 0.01\n unit: 次','2025-01-01','9999-12-31'),('pt_ktv_video_eval_evaluate','pp_ktv_video_eval','KTV视频评估','unit_values:\n video_seconds: 1\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: video_seconds\n unit_prices: 0.05\n unit: video_seconds','2025-01-01','9999-12-31'); +/*!40000 ALTER TABLE `pricing_program_timing` ENABLE KEYS */; +UNLOCK TABLES; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- Dump completed on 2026-07-08 11:02:16 + +-- upapp +/*M!999999\- enable the sandbox mode */ +-- MariaDB dump 10.19 Distrib 10.6.23-MariaDB, for debian-linux-gnu (x86_64) +-- +-- Host: localhost Database: sage +-- ------------------------------------------------------ +-- Server version 10.6.23-MariaDB-0ubuntu0.22.04.1 + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8mb4 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Dumping data for table `upapp` +-- +-- WHERE: id="ktv-gateway" + +LOCK TABLES `upapp` WRITE; +/*!40000 ALTER TABLE `upapp` DISABLE KEYS */; +INSERT INTO `upapp` (`id`, `name`, `description`, `ownerid`, `auth_apiname`, `secretkey`, `baseurl`, `myappid`, `dynamic_func`) VALUES ('ktv-gateway','KTV产线网关','0','0',NULL,NULL,'https://ktv.opencomputing.net:10443',NULL,NULL); +/*!40000 ALTER TABLE `upapp` ENABLE KEYS */; +UNLOCK TABLES; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- Dump completed on 2026-07-08 11:02:16 + +-- upappkey +/*M!999999\- enable the sandbox mode */ +-- MariaDB dump 10.19 Distrib 10.6.23-MariaDB, for debian-linux-gnu (x86_64) +-- +-- Host: localhost Database: sage +-- ------------------------------------------------------ +-- Server version 10.6.23-MariaDB-0ubuntu0.22.04.1 + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8mb4 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Dumping data for table `upappkey` +-- +-- WHERE: upappid="ktv-gateway" + +LOCK TABLES `upappkey` WRITE; +/*!40000 ALTER TABLE `upappkey` DISABLE KEYS */; +INSERT INTO `upappkey` (`id`, `upappid`, `ownerid`, `apikey`, `apiuser`, `apipasswd`, `orgid`, `is_first`) VALUES ('ktv_gateway_key','ktv-gateway','UiEi7hKqAmU1-jqQEVhZe','',NULL,NULL,'0',NULL); +/*!40000 ALTER TABLE `upappkey` ENABLE KEYS */; +UNLOCK TABLES; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- Dump completed on 2026-07-08 11:02:16 + diff --git a/scripts/ktv_services_registration.sql b/scripts/ktv_services_registration.sql new file mode 100644 index 00000000..73f5cc96 --- /dev/null +++ b/scripts/ktv_services_registration.sql @@ -0,0 +1,69 @@ +-- KTV产线网关: 14端点 +INSERT INTO sage.upapp (id,name,baseurl,ownerid) VALUES ('ktv-gateway','KTV产线网关','https://ktv.opencomputing.net:10443','0') ON DUPLICATE KEY UPDATE baseurl=VALUES(baseurl); + +-- llm (model=功能名, name=ky-model) +INSERT INTO sage.llm (id,name,model,description,providerid,ownerid,upappid,min_balance,enabled_date,expired_date,status) VALUES ('llm_ktv_asr_transcribe','ky-asr-transcribe','asr-transcribe','KTV语音识别','FZoJv7EUEdKL3pUt0BQ5S','0','ktv-gateway',0,'2025-01-01','2099-12-31','published'); +INSERT INTO sage.llm (id,name,model,description,providerid,ownerid,upappid,min_balance,enabled_date,expired_date,status) VALUES ('llm_ktv_demucs_separate','ky-demucs-separate','demucs-separate','KTV音频分离','FZoJv7EUEdKL3pUt0BQ5S','0','ktv-gateway',0,'2025-01-01','2099-12-31','published'); +INSERT INTO sage.llm (id,name,model,description,providerid,ownerid,upappid,min_balance,enabled_date,expired_date,status) VALUES ('llm_ktv_face_detect','ky-face-detect','face-detect','KTV人脸检测','FZoJv7EUEdKL3pUt0BQ5S','0','ktv-gateway',0,'2025-01-01','2099-12-31','published'); +INSERT INTO sage.llm (id,name,model,description,providerid,ownerid,upappid,min_balance,enabled_date,expired_date,status) VALUES ('llm_ktv_face_recognize','ky-face-recognize','face-recognize','KTV人脸识别','FZoJv7EUEdKL3pUt0BQ5S','0','ktv-gateway',0,'2025-01-01','2099-12-31','published'); +INSERT INTO sage.llm (id,name,model,description,providerid,ownerid,upappid,min_balance,enabled_date,expired_date,status) VALUES ('llm_ktv_face_compare','ky-face-compare','face-compare','KTV人脸比对','FZoJv7EUEdKL3pUt0BQ5S','0','ktv-gateway',0,'2025-01-01','2099-12-31','published'); +INSERT INTO sage.llm (id,name,model,description,providerid,ownerid,upappid,min_balance,enabled_date,expired_date,status) VALUES ('llm_ktv_subtitle_render','ky-subtitle-render','subtitle-render','KTV字幕渲染','FZoJv7EUEdKL3pUt0BQ5S','0','ktv-gateway',0,'2025-01-01','2099-12-31','published'); +INSERT INTO sage.llm (id,name,model,description,providerid,ownerid,upappid,min_balance,enabled_date,expired_date,status) VALUES ('llm_ktv_merge_video','ky-merge-video','merge-video','KTV视频合并','FZoJv7EUEdKL3pUt0BQ5S','0','ktv-gateway',0,'2025-01-01','2099-12-31','published'); +INSERT INTO sage.llm (id,name,model,description,providerid,ownerid,upappid,min_balance,enabled_date,expired_date,status) VALUES ('llm_ktv_songrate_evaluate','ky-songrate-evaluate','songrate-evaluate','KTV歌曲评分','FZoJv7EUEdKL3pUt0BQ5S','0','ktv-gateway',0,'2025-01-01','2099-12-31','published'); +INSERT INTO sage.llm (id,name,model,description,providerid,ownerid,upappid,min_balance,enabled_date,expired_date,status) VALUES ('llm_ktv_synth_generate','ky-synth-generate','synth-generate','KTV音乐合成','FZoJv7EUEdKL3pUt0BQ5S','0','ktv-gateway',0,'2025-01-01','2099-12-31','published'); +INSERT INTO sage.llm (id,name,model,description,providerid,ownerid,upappid,min_balance,enabled_date,expired_date,status) VALUES ('llm_ktv_synth_status','ky-synth-status','synth-status','KTV合成状态','FZoJv7EUEdKL3pUt0BQ5S','0','ktv-gateway',0,'2025-01-01','2099-12-31','published'); +INSERT INTO sage.llm (id,name,model,description,providerid,ownerid,upappid,min_balance,enabled_date,expired_date,status) VALUES ('llm_ktv_realesrgan_upscale','ky-realesrgan-upscale','realesrgan-upscale','KTV超分辨率','FZoJv7EUEdKL3pUt0BQ5S','0','ktv-gateway',0,'2025-01-01','2099-12-31','published'); +INSERT INTO sage.llm (id,name,model,description,providerid,ownerid,upappid,min_balance,enabled_date,expired_date,status) VALUES ('llm_ktv_realesrgan_status','ky-realesrgan-status','realesrgan-status','KTV超分状态','FZoJv7EUEdKL3pUt0BQ5S','0','ktv-gateway',0,'2025-01-01','2099-12-31','published'); +INSERT INTO sage.llm (id,name,model,description,providerid,ownerid,upappid,min_balance,enabled_date,expired_date,status) VALUES ('llm_ktv_rvc_convert','ky-rvc-convert','rvc-convert','KTV声音转换','FZoJv7EUEdKL3pUt0BQ5S','0','ktv-gateway',0,'2025-01-01','2099-12-31','published'); +INSERT INTO sage.llm (id,name,model,description,providerid,ownerid,upappid,min_balance,enabled_date,expired_date,status) VALUES ('llm_ktv_video_eval_evaluate','ky-video-eval-evaluate','video-eval-evaluate','KTV视频评估','FZoJv7EUEdKL3pUt0BQ5S','0','ktv-gateway',0,'2025-01-01','2099-12-31','published'); + +-- uapi (path=/{servicename}/api/{apiname}) +INSERT INTO sage.uapi (id,name,title,description,path,httpmethod,upappid) VALUES ('uapi_ktv_asr_transcribe','asr-transcribe','KTV语音识别','KTV语音识别','/asr/api/asr-transcribe','POST','ktv-gateway'); +INSERT INTO sage.uapi (id,name,title,description,path,httpmethod,upappid) VALUES ('uapi_ktv_demucs_separate','demucs-separate','KTV音频分离','KTV音频分离','/demucs/api/demucs-separate','POST','ktv-gateway'); +INSERT INTO sage.uapi (id,name,title,description,path,httpmethod,upappid) VALUES ('uapi_ktv_face_detect','face-detect','KTV人脸检测','KTV人脸检测','/face/api/face-detect','POST','ktv-gateway'); +INSERT INTO sage.uapi (id,name,title,description,path,httpmethod,upappid) VALUES ('uapi_ktv_face_recognize','face-recognize','KTV人脸识别','KTV人脸识别','/face/api/face-recognize','POST','ktv-gateway'); +INSERT INTO sage.uapi (id,name,title,description,path,httpmethod,upappid) VALUES ('uapi_ktv_face_compare','face-compare','KTV人脸比对','KTV人脸比对','/face/api/face-compare','POST','ktv-gateway'); +INSERT INTO sage.uapi (id,name,title,description,path,httpmethod,upappid) VALUES ('uapi_ktv_subtitle_render','subtitle-render','KTV字幕渲染','KTV字幕渲染','/subtitle/api/subtitle-render','POST','ktv-gateway'); +INSERT INTO sage.uapi (id,name,title,description,path,httpmethod,upappid) VALUES ('uapi_ktv_merge_video','merge-video','KTV视频合并','KTV视频合并','/merge/api/merge-video','POST','ktv-gateway'); +INSERT INTO sage.uapi (id,name,title,description,path,httpmethod,upappid) VALUES ('uapi_ktv_songrate_evaluate','songrate-evaluate','KTV歌曲评分','KTV歌曲评分','/songrate/api/songrate-evaluate','POST','ktv-gateway'); +INSERT INTO sage.uapi (id,name,title,description,path,httpmethod,upappid) VALUES ('uapi_ktv_synth_generate','synth-generate','KTV音乐合成','KTV音乐合成','/synth/api/synth-generate','POST','ktv-gateway'); +INSERT INTO sage.uapi (id,name,title,description,path,httpmethod,upappid) VALUES ('uapi_ktv_synth_status','synth-status','KTV合成状态','KTV合成状态','/synth/api/synth-status','GET','ktv-gateway'); +INSERT INTO sage.uapi (id,name,title,description,path,httpmethod,upappid) VALUES ('uapi_ktv_realesrgan_upscale','realesrgan-upscale','KTV超分辨率','KTV超分辨率','/realesrgan/api/realesrgan-upscale','POST','ktv-gateway'); +INSERT INTO sage.uapi (id,name,title,description,path,httpmethod,upappid) VALUES ('uapi_ktv_realesrgan_status','realesrgan-status','KTV超分状态','KTV超分状态','/realesrgan/api/realesrgan-status','GET','ktv-gateway'); +INSERT INTO sage.uapi (id,name,title,description,path,httpmethod,upappid) VALUES ('uapi_ktv_rvc_convert','rvc-convert','KTV声音转换','KTV声音转换','/rvc/api/rvc-convert','POST','ktv-gateway'); +INSERT INTO sage.uapi (id,name,title,description,path,httpmethod,upappid) VALUES ('uapi_ktv_video_eval_evaluate','video-eval-evaluate','KTV视频评估','KTV视频评估','/video-eval/api/video-eval-evaluate','POST','ktv-gateway'); + +-- llm_api_map +INSERT INTO sage.llm_api_map (id,llmid,llmcatelogid,apiname,isdefaultcatelog) VALUES ('map_ktv_asr_transcribe','llm_ktv_asr_transcribe','ktv_pipeline','asr-transcribe','1'); +INSERT INTO sage.llm_api_map (id,llmid,llmcatelogid,apiname,isdefaultcatelog) VALUES ('map_ktv_demucs_separate','llm_ktv_demucs_separate','ktv_pipeline','demucs-separate','1'); +INSERT INTO sage.llm_api_map (id,llmid,llmcatelogid,apiname,isdefaultcatelog) VALUES ('map_ktv_face_detect','llm_ktv_face_detect','ktv_pipeline','face-detect','1'); +INSERT INTO sage.llm_api_map (id,llmid,llmcatelogid,apiname,isdefaultcatelog) VALUES ('map_ktv_face_recognize','llm_ktv_face_recognize','ktv_pipeline','face-recognize','1'); +INSERT INTO sage.llm_api_map (id,llmid,llmcatelogid,apiname,isdefaultcatelog) VALUES ('map_ktv_face_compare','llm_ktv_face_compare','ktv_pipeline','face-compare','1'); +INSERT INTO sage.llm_api_map (id,llmid,llmcatelogid,apiname,isdefaultcatelog) VALUES ('map_ktv_subtitle_render','llm_ktv_subtitle_render','ktv_pipeline','subtitle-render','1'); +INSERT INTO sage.llm_api_map (id,llmid,llmcatelogid,apiname,isdefaultcatelog) VALUES ('map_ktv_merge_video','llm_ktv_merge_video','ktv_pipeline','merge-video','1'); +INSERT INTO sage.llm_api_map (id,llmid,llmcatelogid,apiname,isdefaultcatelog) VALUES ('map_ktv_songrate_evaluate','llm_ktv_songrate_evaluate','ktv_pipeline','songrate-evaluate','1'); +INSERT INTO sage.llm_api_map (id,llmid,llmcatelogid,apiname,isdefaultcatelog) VALUES ('map_ktv_synth_generate','llm_ktv_synth_generate','ktv_pipeline','synth-generate','1'); +INSERT INTO sage.llm_api_map (id,llmid,llmcatelogid,apiname,isdefaultcatelog) VALUES ('map_ktv_synth_status','llm_ktv_synth_status','ktv_pipeline','synth-status','1'); +INSERT INTO sage.llm_api_map (id,llmid,llmcatelogid,apiname,isdefaultcatelog) VALUES ('map_ktv_realesrgan_upscale','llm_ktv_realesrgan_upscale','ktv_pipeline','realesrgan-upscale','1'); +INSERT INTO sage.llm_api_map (id,llmid,llmcatelogid,apiname,isdefaultcatelog) VALUES ('map_ktv_realesrgan_status','llm_ktv_realesrgan_status','ktv_pipeline','realesrgan-status','1'); +INSERT INTO sage.llm_api_map (id,llmid,llmcatelogid,apiname,isdefaultcatelog) VALUES ('map_ktv_rvc_convert','llm_ktv_rvc_convert','ktv_pipeline','rvc-convert','1'); +INSERT INTO sage.llm_api_map (id,llmid,llmcatelogid,apiname,isdefaultcatelog) VALUES ('map_ktv_video_eval_evaluate','llm_ktv_video_eval_evaluate','ktv_pipeline','video-eval-evaluate','1'); + +-- pricing_program +INSERT INTO sage.pricing_program (id,providerid,name) VALUES ('pp_ktv','FZoJv7EUEdKL3pUt0BQ5S','KTV产线计费') ON DUPLICATE KEY UPDATE providerid=VALUES(providerid); + +-- pricing_program_timing (0.01元/次) +INSERT INTO sage.pricing_program_timing (id,ppid,name,pricing_data) VALUES ('pt_ktv_asr_transcribe','pp_ktv','KTV语音识别','unit_values:\n 次: 1\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: flat\n unit_prices: 0.01\n unit: 次'); +INSERT INTO sage.pricing_program_timing (id,ppid,name,pricing_data) VALUES ('pt_ktv_demucs_separate','pp_ktv','KTV音频分离','unit_values:\n 次: 1\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: flat\n unit_prices: 0.01\n unit: 次'); +INSERT INTO sage.pricing_program_timing (id,ppid,name,pricing_data) VALUES ('pt_ktv_face_detect','pp_ktv','KTV人脸检测','unit_values:\n 次: 1\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: flat\n unit_prices: 0.01\n unit: 次'); +INSERT INTO sage.pricing_program_timing (id,ppid,name,pricing_data) VALUES ('pt_ktv_face_recognize','pp_ktv','KTV人脸识别','unit_values:\n 次: 1\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: flat\n unit_prices: 0.01\n unit: 次'); +INSERT INTO sage.pricing_program_timing (id,ppid,name,pricing_data) VALUES ('pt_ktv_face_compare','pp_ktv','KTV人脸比对','unit_values:\n 次: 1\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: flat\n unit_prices: 0.01\n unit: 次'); +INSERT INTO sage.pricing_program_timing (id,ppid,name,pricing_data) VALUES ('pt_ktv_subtitle_render','pp_ktv','KTV字幕渲染','unit_values:\n 次: 1\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: flat\n unit_prices: 0.01\n unit: 次'); +INSERT INTO sage.pricing_program_timing (id,ppid,name,pricing_data) VALUES ('pt_ktv_merge_video','pp_ktv','KTV视频合并','unit_values:\n 次: 1\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: flat\n unit_prices: 0.01\n unit: 次'); +INSERT INTO sage.pricing_program_timing (id,ppid,name,pricing_data) VALUES ('pt_ktv_songrate_evaluate','pp_ktv','KTV歌曲评分','unit_values:\n 次: 1\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: flat\n unit_prices: 0.01\n unit: 次'); +INSERT INTO sage.pricing_program_timing (id,ppid,name,pricing_data) VALUES ('pt_ktv_synth_generate','pp_ktv','KTV音乐合成','unit_values:\n 次: 1\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: flat\n unit_prices: 0.01\n unit: 次'); +INSERT INTO sage.pricing_program_timing (id,ppid,name,pricing_data) VALUES ('pt_ktv_synth_status','pp_ktv','KTV合成状态','unit_values:\n 次: 1\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: flat\n unit_prices: 0.01\n unit: 次'); +INSERT INTO sage.pricing_program_timing (id,ppid,name,pricing_data) VALUES ('pt_ktv_realesrgan_upscale','pp_ktv','KTV超分辨率','unit_values:\n 次: 1\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: flat\n unit_prices: 0.01\n unit: 次'); +INSERT INTO sage.pricing_program_timing (id,ppid,name,pricing_data) VALUES ('pt_ktv_realesrgan_status','pp_ktv','KTV超分状态','unit_values:\n 次: 1\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: flat\n unit_prices: 0.01\n unit: 次'); +INSERT INTO sage.pricing_program_timing (id,ppid,name,pricing_data) VALUES ('pt_ktv_rvc_convert','pp_ktv','KTV声音转换','unit_values:\n 次: 1\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: flat\n unit_prices: 0.01\n unit: 次'); +INSERT INTO sage.pricing_program_timing (id,ppid,name,pricing_data) VALUES ('pt_ktv_video_eval_evaluate','pp_ktv','KTV视频评估','unit_values:\n 次: 1\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: flat\n unit_prices: 0.01\n unit: 次'); \ No newline at end of file diff --git a/scripts/ktv_uapi_migration.sql b/scripts/ktv_uapi_migration.sql new file mode 100644 index 00000000..eff7110e --- /dev/null +++ b/scripts/ktv_uapi_migration.sql @@ -0,0 +1,381 @@ +-- ============================================================ +-- KTV服务 uapi/uapiio 补全迁移 Part 1 +-- 输入字段使用 _file 命名规范(与 Sage image/video/audio 统一) +-- ============================================================ + +-- ASR语音识别 +INSERT INTO uapiio (id, name, description, input_fields) VALUES ( + 'ktv_asr_transcribe_io', 'KTV语音识别', '上传音频文件,返回识别文本和时间戳', + '{"audio_file":{"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_file":{"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_file":{"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_file":{"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_file1":{"type":"string","required":true,"description":"图像1 URL"},"image_file2":{"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"},"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_file":{"type":"string","required":false,"description":"视频URL"},"audio_file":{"type":"string","required":false,"description":"音频URL"},"subtitle_file":{"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_file":{"type":"string","required":true,"description":"音频文件URL"},"scene":{"type":"string","required":false,"default":"pop","description":"场景类型"}}' +) 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_file":{"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_file":{"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_file":{"type":"string","required":true,"description":"视频URL"}}' +) ON DUPLICATE KEY UPDATE description=VALUES(description), input_fields=VALUES(input_fields); +-- ============================================================ +-- KTV服务 uapi 补全 Part 2 +-- data使用_file命名; response用{%if error%}容错透传GPU响应 +-- async: synth-generate(5s轮询), realesrgan-upscale(3s轮询) +-- ============================================================ + +-- 1. ASR语音识别 (sync) +UPDATE uapi SET stream='sync',headers='{"Content-Type":"application/json"}', + data='{"audio_file":"{{audio_file}}"{%if language%},"language":"{{language}}"{%endif%}}', + response='{%if error%}{"error":"{{error}}"}{%else%}{"status":"{{status}}","text":"{{text}}","segments":{{json.dumps(segments,ensure_ascii=False)}},"usage":{{json.dumps(usage,ensure_ascii=False)}}}{%endif%}', + ioid='ktv_asr_transcribe_io' WHERE id='uapi_ktv_asr_transcribe'; + +-- 2. Demucs音频分离 (async) +UPDATE uapi SET stream='async',headers='{"Content-Type":"application/json"}', + data='{"audio_path":"{{audio_file}}"{%if task_type%},"task_type":"{{task_type}}"{%endif%}}', + response='{"taskid":"{{task_id}}","taskstatus":"PENDING","status":"PENDING"}', + ioid='ktv_demucs_separate_io' WHERE id='uapi_ktv_demucs_separate'; + +-- 3. 人脸检测 (sync) +UPDATE uapi SET stream='sync',headers='{"Content-Type":"application/json"}', + data='{"image_file":"{{image_file}}"}', + response='{%if error%}{"error":"{{error}}"}{%else%}{"status":"{{status}}","faces":{{json.dumps(faces,ensure_ascii=False)}},"usage":{{json.dumps(usage,ensure_ascii=False)}}}{%endif%}', + 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_file":"{{image_file}}"{%if face_id%},"face_id":"{{face_id}}"{%endif%}}', + response='{%if error%}{"error":"{{error}}"}{%else%}{"status":"{{status}}","matches":{{json.dumps(matches,ensure_ascii=False)}},"usage":{{json.dumps(usage,ensure_ascii=False)}}}{%endif%}', + 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_file1":"{{image_file1}}","image_file2":"{{image_file2}}"}', + response='{%if error%}{"error":"{{error}}"}{%else%}{"status":"{{status}}","similarity":{{similarity}},"usage":{{json.dumps(usage,ensure_ascii=False)}}}{%endif%}', + ioid='ktv_face_compare_io' WHERE id='uapi_ktv_face_compare'; + +-- 6. 字幕渲染 (sync) +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='{%if error%}{"error":"{{error}}"}{%else%}{"status":"{{status}}","ass_url":"{{ass_url}}","usage":{{json.dumps(usage,ensure_ascii=False)}}}{%endif%}', + ioid='ktv_subtitle_render_io' WHERE id='uapi_ktv_subtitle_render'; + +-- 7. 视频合并 (sync) +UPDATE uapi SET stream='sync',headers='{"Content-Type":"application/json"}', + data='{%set c=joiner(",")%}{{%if video_file%}{{c()}}"video_file":"{{video_file}}"{%endif%}{%if audio_file%}{{c()}}"audio_file":"{{audio_file}}"{%endif%}{%if subtitle_file%}{{c()}}"subtitle_file":"{{subtitle_file}}"{%endif%}{%if output_format%}{{c()}}"output_format":"{{output_format}}"{%endif%}}', + response='{%if error%}{"error":"{{error}}"}{%else%}{"status":"{{status}}","output_url":"{{output_url}}","duration":{{duration}},"usage":{{json.dumps(usage,ensure_ascii=False)}}}{%endif%}', + ioid='ktv_merge_video_io' WHERE id='uapi_ktv_merge_video'; + +-- 8. 歌曲评分 (sync) +UPDATE uapi SET stream='sync',headers='{"Content-Type":"application/json"}', + data='{"audio_file":"{{audio_file}}"{%if scene%},"scene":"{{scene}}"{%endif%}}', + response='{%if error%}{"error":"{{error}}"}{%else%}{"status":"{{status}}","score":{{score}},"details":{{json.dumps(details,ensure_ascii=False)}},"usage":{{json.dumps(usage,ensure_ascii=False)}}}{%endif%}', + ioid='ktv_songrate_evaluate_io' WHERE id='uapi_ktv_songrate_evaluate'; + +-- 9. 合成状态查询 (sync) +UPDATE uapi SET stream='sync',headers='{"Content-Type":"application/json"}', + data='{"task_id":"{{task_id}}"}', + response='{%if error%}{"error":"{{error}}"}{%elif status=="SUCCEEDED"%}{"taskstatus":"SUCCEEDED","output_url":"{{output_url}}","usage":{{json.dumps(usage,ensure_ascii=False)}}}{%elif status=="FAILED"%}{"taskstatus":"FAILED","error":"{{error}}"}{%else%}{"taskstatus":"PENDING"}{%endif%}', + ioid='ktv_synth_status_io' WHERE id='uapi_ktv_synth_status'; + +-- 11. 超分辨率 (async提交) +UPDATE uapi SET stream='async',headers='{"Content-Type":"application/json"}', + data='{"image_file":"{{image_file}}"{%if scale%},"scale":{{scale}}{%endif%}}', + response='{"taskid":"{{task_id}}","taskstatus":"PENDING"}', + ioid='ktv_realesrgan_upscale_io' WHERE id='uapi_ktv_realesrgan_upscale'; + +-- 12. 超分状态查询 (sync) +UPDATE uapi SET stream='sync',headers='{"Content-Type":"application/json"}', + data=NULL, + response='{"status":"{{status}}","output_url":"{{output_url}}","usage":{{json.dumps(usage,ensure_ascii=False)}}}', + ioid='ktv_realesrgan_status_io' WHERE id='uapi_ktv_realesrgan_status'; + +-- 13. RVC声音转换 (sync) +UPDATE uapi SET stream='sync',headers='{"Content-Type":"application/json"}', + data='{"audio_file":"{{audio_file}}","voice_model":"{{voice_model}}"}', + response='{%if error%}{"error":"{{error}}"}{%else%}{"status":"{{status}}","output_url":"{{output_url}}","usage":{{json.dumps(usage,ensure_ascii=False)}}}{%endif%}', + ioid='ktv_rvc_convert_io' WHERE id='uapi_ktv_rvc_convert'; + +-- 14. 视频评估 (sync) +UPDATE uapi SET stream='sync',headers='{"Content-Type":"application/json"}', + data='{"video_file":"{{video_file}}"}', + response='{%if error%}{"error":"{{error}}"}{%else%}{"status":"{{status}}","score":{{score}},"details":{{json.dumps(details,ensure_ascii=False)}},"usage":{{json.dumps(usage,ensure_ascii=False)}}}{%endif%}', + ioid='ktv_video_eval_evaluate_io' WHERE id='uapi_ktv_video_eval_evaluate'; + +-- async query_apiname +UPDATE llm_api_map SET query_apiname='realesrgan-status',query_period=5 WHERE llmid='llm_ktv_realesrgan_upscale'; + +-- ppid (v1/models 过滤要求 ppid IS NOT NULL) +UPDATE llm_api_map SET ppid='pp_ktv' WHERE llmid LIKE 'llm_ktv%' AND ppid IS NULL; + +-- upappkey (API调用鉴权必需) +INSERT INTO upappkey (id,upappid,ownerid,apikey,orgid) +SELECT 'ktv_gateway_key','ktv-gateway','UiEi7hKqAmU1-jqQEVhZe','','0' +WHERE NOT EXISTS (SELECT 1 FROM upappkey WHERE upappid='ktv-gateway'); +-- ============================================================ +-- 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'; +-- ============================================================ +-- KTV服务 定价修复 Part 4 +-- 每个模型独立ppid + 按量计费(price_factors=字段名) +-- ============================================================ + +-- 1. 创建独立ppid(每模型一个) +INSERT INTO pricing_program (id,providerid,name) VALUES +('pp_ktv_asr','FZoJv7EUEdKL3pUt0BQ5S','KTV-语音识别'), +('pp_ktv_demucs','FZoJv7EUEdKL3pUt0BQ5S','KTV-音频分离'), +('pp_ktv_face_detect','FZoJv7EUEdKL3pUt0BQ5S','KTV-人脸检测'), +('pp_ktv_face_recognize','FZoJv7EUEdKL3pUt0BQ5S','KTV-人脸识别'), +('pp_ktv_face_compare','FZoJv7EUEdKL3pUt0BQ5S','KTV-人脸比对'), +('pp_ktv_subtitle','FZoJv7EUEdKL3pUt0BQ5S','KTV-字幕渲染'), +('pp_ktv_merge','FZoJv7EUEdKL3pUt0BQ5S','KTV-视频合并'), +('pp_ktv_songrate','FZoJv7EUEdKL3pUt0BQ5S','KTV-歌曲评分'), + +('pp_ktv_synth_status','FZoJv7EUEdKL3pUt0BQ5S','KTV-合成状态'), +('pp_ktv_realesrgan','FZoJv7EUEdKL3pUt0BQ5S','KTV-超分辨率'), +('pp_ktv_realesrgan_status','FZoJv7EUEdKL3pUt0BQ5S','KTV-超分状态'), +('pp_ktv_rvc','FZoJv7EUEdKL3pUt0BQ5S','KTV-声音转换'), +('pp_ktv_video_eval','FZoJv7EUEdKL3pUt0BQ5S','KTV-视频评估') +ON DUPLICATE KEY UPDATE providerid=VALUES(providerid); + +-- 2. 迁移 pricing_program_timing 到新 ppid +UPDATE pricing_program_timing SET ppid='pp_ktv_asr' WHERE id='pt_ktv_asr_transcribe'; +UPDATE pricing_program_timing SET ppid='pp_ktv_demucs' WHERE id='pt_ktv_demucs_separate'; +UPDATE pricing_program_timing SET ppid='pp_ktv_face_detect' WHERE id='pt_ktv_face_detect'; +UPDATE pricing_program_timing SET ppid='pp_ktv_face_recognize' WHERE id='pt_ktv_face_recognize'; +UPDATE pricing_program_timing SET ppid='pp_ktv_face_compare' WHERE id='pt_ktv_face_compare'; +UPDATE pricing_program_timing SET ppid='pp_ktv_subtitle' WHERE id='pt_ktv_subtitle_render'; +UPDATE pricing_program_timing SET ppid='pp_ktv_merge' WHERE id='pt_ktv_merge_video'; +UPDATE pricing_program_timing SET ppid='pp_ktv_songrate' WHERE id='pt_ktv_songrate_evaluate'; + +UPDATE pricing_program_timing SET ppid='pp_ktv_synth_status' WHERE id='pt_ktv_synth_status'; +UPDATE pricing_program_timing SET ppid='pp_ktv_realesrgan' WHERE id='pt_ktv_realesrgan_upscale'; +UPDATE pricing_program_timing SET ppid='pp_ktv_realesrgan_status' WHERE id='pt_ktv_realesrgan_status'; +UPDATE pricing_program_timing SET ppid='pp_ktv_rvc' WHERE id='pt_ktv_rvc_convert'; +UPDATE pricing_program_timing SET ppid='pp_ktv_video_eval' WHERE id='pt_ktv_video_eval_evaluate'; + +-- 3. 更新 pricing_data YAML:price_factors=字段名(按量计费) +-- asr: audio_seconds × 0.01 +UPDATE pricing_program_timing SET pricing_data='unit_values:\n audio_seconds: 1\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: audio_seconds\n unit_prices: 0.01\n unit: audio_seconds' WHERE id='pt_ktv_asr_transcribe'; + +-- demucs: audio_seconds × 0.02 +UPDATE pricing_program_timing SET pricing_data='unit_values:\n audio_seconds: 1\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: audio_seconds\n unit_prices: 0.02\n unit: audio_seconds' WHERE id='pt_ktv_demucs_separate'; + +-- face-detect: detect_count × 0.10 +UPDATE pricing_program_timing SET pricing_data='unit_values:\n detect_count: 1\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: detect_count\n unit_prices: 0.10\n unit: detect_count' WHERE id='pt_ktv_face_detect'; + +-- face-recognize: recognize_count × 0.10 +UPDATE pricing_program_timing SET pricing_data='unit_values:\n recognize_count: 1\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: recognize_count\n unit_prices: 0.10\n unit: recognize_count' WHERE id='pt_ktv_face_recognize'; + +-- face-compare: compare_count × 0.10 +UPDATE pricing_program_timing SET pricing_data='unit_values:\n compare_count: 1\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: compare_count\n unit_prices: 0.10\n unit: compare_count' WHERE id='pt_ktv_face_compare'; + +-- subtitle: subtitle_count × 0.01 +UPDATE pricing_program_timing SET pricing_data='unit_values:\n subtitle_count: 1\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: subtitle_count\n unit_prices: 0.01\n unit: subtitle_count' WHERE id='pt_ktv_subtitle_render'; + +-- merge: output_seconds × 0.01 +UPDATE pricing_program_timing SET pricing_data='unit_values:\n output_seconds: 1\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: output_seconds\n unit_prices: 0.01\n unit: output_seconds' WHERE id='pt_ktv_merge_video'; + +-- songrate: audio_seconds × 0.005 +UPDATE pricing_program_timing SET pricing_data='unit_values:\n audio_seconds: 1\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: audio_seconds\n unit_prices: 0.005\n unit: audio_seconds' WHERE id='pt_ktv_songrate_evaluate'; + +-- synth-generate: audio_seconds × 0.20 +UPDATE pricing_program_timing SET pricing_data='unit_values:\n audio_seconds: 1\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: audio_seconds\n unit_prices: 0.20\n unit: audio_seconds' WHERE id='pt_ktv_synth_generate'; + +-- synth-status: flat 0.01 +UPDATE pricing_program_timing SET pricing_data='unit_values:\n 次: 1\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: flat\n unit_prices: 0.01\n unit: 次' WHERE id='pt_ktv_synth_status'; + +-- realesrgan-upscale: image_count × 0.50 +UPDATE pricing_program_timing SET pricing_data='unit_values:\n image_count: 1\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: image_count\n unit_prices: 0.50\n unit: image_count' WHERE id='pt_ktv_realesrgan_upscale'; + +-- realesrgan-status: flat 0.01 +UPDATE pricing_program_timing SET pricing_data='unit_values:\n 次: 1\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: flat\n unit_prices: 0.01\n unit: 次' WHERE id='pt_ktv_realesrgan_status'; + +-- rvc: audio_seconds × 0.15 +UPDATE pricing_program_timing SET pricing_data='unit_values:\n audio_seconds: 1\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: audio_seconds\n unit_prices: 0.15\n unit: audio_seconds' WHERE id='pt_ktv_rvc_convert'; + +-- video-eval: video_seconds × 0.05 +UPDATE pricing_program_timing SET pricing_data='unit_values:\n video_seconds: 1\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: video_seconds\n unit_prices: 0.05\n unit: video_seconds' WHERE id='pt_ktv_video_eval_evaluate'; + +-- 4. 更新 llm_api_map 指向独立 ppid +UPDATE llm_api_map SET ppid='pp_ktv_asr' WHERE llmid='llm_ktv_asr_transcribe'; +UPDATE llm_api_map SET ppid='pp_ktv_demucs' WHERE llmid='llm_ktv_demucs_separate'; +UPDATE llm_api_map SET ppid='pp_ktv_face_detect' WHERE llmid='llm_ktv_face_detect'; +UPDATE llm_api_map SET ppid='pp_ktv_face_recognize' WHERE llmid='llm_ktv_face_recognize'; +UPDATE llm_api_map SET ppid='pp_ktv_face_compare' WHERE llmid='llm_ktv_face_compare'; +UPDATE llm_api_map SET ppid='pp_ktv_subtitle' WHERE llmid='llm_ktv_subtitle_render'; +UPDATE llm_api_map SET ppid='pp_ktv_merge' WHERE llmid='llm_ktv_merge_video'; +UPDATE llm_api_map SET ppid='pp_ktv_songrate' WHERE llmid='llm_ktv_songrate_evaluate'; + +UPDATE llm_api_map SET ppid='pp_ktv_synth_status' WHERE llmid='llm_ktv_synth_status'; +UPDATE llm_api_map SET ppid='pp_ktv_realesrgan' WHERE llmid='llm_ktv_realesrgan_upscale'; +UPDATE llm_api_map SET ppid='pp_ktv_realesrgan_status' WHERE llmid='llm_ktv_realesrgan_status'; +UPDATE llm_api_map SET ppid='pp_ktv_rvc' WHERE llmid='llm_ktv_rvc_convert'; +UPDATE llm_api_map SET ppid='pp_ktv_video_eval' WHERE llmid='llm_ktv_video_eval_evaluate'; + +-- 修复 pricing_program 字符集不一致(生产环境 utf8mb4_general_ci vs organization utf8mb4_unicode_ci) +ALTER TABLE pricing_program MODIFY ownerid VARCHAR(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; +ALTER TABLE pricing_program MODIFY providerid VARCHAR(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; +-- ============================================================ +-- KTV服务 数据模板修复 Part 5 +-- 匹配GPU实际参数名 + demucs async改造 +-- ============================================================ + +-- asr: audio_file → audio_path +UPDATE uapi SET data='{"audio_path":"{{audio_file}}"{%if language%},"language":"{{language}}"{%endif%}}' WHERE id='uapi_ktv_asr_transcribe'; + +-- demucs: audio_file → audio_path +UPDATE uapi SET data='{"audio_path":"{{audio_file}}"{%if task_type%},"task_type":"{{task_type}}"{%endif%}}' WHERE id='uapi_ktv_demucs_separate'; + +-- face-detect: image_file → images list +UPDATE uapi SET data='{"images":["{{image_file}}"]}' WHERE id='uapi_ktv_face_detect'; + +-- face-recognize: image_file → images list +UPDATE uapi SET data='{"images":["{{image_file}}"]{%if face_id%},"face_id":"{{face_id}}"{%endif%}}' WHERE id='uapi_ktv_face_recognize'; + +-- face-compare: image_file1→embedding1, image_file2→embedding2 +UPDATE uapi SET data='{"embedding1":"{{image_file1}}","embedding2":"{{image_file2}}"}' WHERE id='uapi_ktv_face_compare'; + +-- subtitle: lyrics_json → lyrics +UPDATE uapi SET data='{"lyrics":{{lyrics_json}}{%if width%},"width":{{width}}{%endif%}{%if height%},"height":{{height}}{%endif%}}' WHERE id='uapi_ktv_subtitle_render'; + +-- merge: video_file→video_url, audio_file→audio_path +UPDATE uapi SET data='{%set c=joiner(",")%}{{%if video_file%}{{c()}}"video_url":"{{video_file}}"{%endif%}{%if audio_file%}{{c()}}"audio_path":"{{audio_file}}"{%endif%}{%if subtitle_file%}{{c()}}"subtitle_url":"{{subtitle_file}}"{%endif%}{%if output_format%}{{c()}}"output_format":"{{output_format}}"{%endif%}}' WHERE id='uapi_ktv_merge_video'; + +-- songrate: audio_file→audio_path +UPDATE uapi SET data='{"audio_path":"{{audio_file}}"{%if scene%},"scene":"{{scene}}"{%endif%}}' WHERE id='uapi_ktv_songrate_evaluate'; + +-- synth-status: GET, params in query string, no body +UPDATE uapi SET httpmethod='GET', data=NULL, path='/synth/api/synth-status?task_id={{taskid}}' WHERE id='uapi_ktv_synth_status'; + +-- realesrgan-upscale: image_file→image_url +UPDATE uapi SET data='{"image_url":"{{image_file}}"{%if scale%},"scale":{{scale}}{%endif%}}' WHERE id='uapi_ktv_realesrgan_upscale'; + +-- realesrgan-status: GET, params in query string, no body +UPDATE uapi SET httpmethod='GET', data=NULL, path='/realesrgan/api/realesrgan-status?task_id={{taskid}}' WHERE id='uapi_ktv_realesrgan_status'; + +-- rvc: audio_file→audio_path, voice_model→model +UPDATE uapi SET data='{"audio_path":"{{audio_file}}","model":"{{voice_model}}"}' WHERE id='uapi_ktv_rvc_convert'; + +-- video-eval: video_file→video_url +UPDATE uapi SET data='{"video_url":"{{video_file}}"}' WHERE id='uapi_ktv_video_eval_evaluate'; + +-- ============================================================ +-- demucs async 改造: status 查询端点 + query_apiname +-- ============================================================ + +INSERT INTO uapi (id,name,title,description,path,httpmethod,upappid,stream,headers,data,response,ioid) +VALUES ('uapi_ktv_demucs_status','demucs-status','Demucs Status', +'Query demucs task','/demucs/api/demucs-status?task_id={{taskid}}','GET', +'ktv-gateway','sync','{"Content-Type":"application/json"}',NULL, +'{"status":"{{status}}","vocals_url":"{{vocals_url}}","accompaniment_url":"{{accompaniment_url}}","duration":{{duration}},"usage":{{json.dumps(usage,ensure_ascii=False)}}}', +'ktv_demucs_separate_io') +ON DUPLICATE KEY UPDATE response=VALUES(response); + +UPDATE llm_api_map SET query_apiname='demucs-status',query_period=5 WHERE llmid='llm_ktv_demucs_separate'; + +-- ============================================================ +-- 补充缺失的 pricing_program_timing 记录 +-- ============================================================ +INSERT INTO pricing_program_timing (id,ppid,name,pricing_data,enabled_date,expired_date) VALUES +('pt_ktv_face_compare','pp_ktv_face_compare','KTV人脸比对','unit_values:\n compare_count: 1\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: compare_count\n unit_prices: 0.10\n unit: compare_count','2025-01-01','9999-12-31'), +('pt_ktv_synth_status','pp_ktv_synth_status','KTV合成状态','unit_values:\n 次: 1\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: flat\n unit_prices: 0.01\n unit: 次','2025-01-01','9999-12-31'), +('pt_ktv_realesrgan_status','pp_ktv_realesrgan_status','KTV超分状态','unit_values:\n 次: 1\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: flat\n unit_prices: 0.01\n unit: 次','2025-01-01','9999-12-31') +ON DUPLICATE KEY UPDATE ppid=VALUES(ppid), pricing_data=VALUES(pricing_data); diff --git a/scripts/ktv_uapi_migration_p1_uapiio.sql b/scripts/ktv_uapi_migration_p1_uapiio.sql new file mode 100644 index 00000000..6950755a --- /dev/null +++ b/scripts/ktv_uapi_migration_p1_uapiio.sql @@ -0,0 +1,82 @@ +-- ============================================================ +-- KTV服务 uapi/uapiio 补全迁移 Part 1 +-- 输入字段使用 _file 命名规范(与 Sage image/video/audio 统一) +-- ============================================================ + +-- ASR语音识别 +INSERT INTO uapiio (id, name, description, input_fields) VALUES ( + 'ktv_asr_transcribe_io', 'KTV语音识别', '上传音频文件,返回识别文本和时间戳', + '{"audio_file":{"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_file":{"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_file":{"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_file":{"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_file1":{"type":"string","required":true,"description":"图像1 URL"},"image_file2":{"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"},"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_file":{"type":"string","required":false,"description":"视频URL"},"audio_file":{"type":"string","required":false,"description":"音频URL"},"subtitle_file":{"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_file":{"type":"string","required":true,"description":"音频文件URL"},"scene":{"type":"string","required":false,"default":"pop","description":"场景类型"}}' +) 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_file":{"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_file":{"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_file":{"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..c07a8a5c --- /dev/null +++ b/scripts/ktv_uapi_migration_p2_uapi.sql @@ -0,0 +1,94 @@ +-- ============================================================ +-- KTV服务 uapi 补全 Part 2 +-- data使用_file命名; response用{%if error%}容错透传GPU响应 +-- async: synth-generate(5s轮询), realesrgan-upscale(3s轮询) +-- ============================================================ + +-- 1. ASR语音识别 (sync) +UPDATE uapi SET stream='sync',headers='{"Content-Type":"application/json"}', + data='{"audio_file":"{{audio_file}}"{%if language%},"language":"{{language}}"{%endif%}}', + response='{%if error%}{"error":"{{error}}"}{%else%}{"status":"{{status}}","text":"{{text}}","segments":{{json.dumps(segments,ensure_ascii=False)}},"usage":{{json.dumps(usage,ensure_ascii=False)}}}{%endif%}', + ioid='ktv_asr_transcribe_io' WHERE id='uapi_ktv_asr_transcribe'; + +-- 2. Demucs音频分离 (async) +UPDATE uapi SET stream='async',headers='{"Content-Type":"application/json"}', + data='{"audio_path":"{{audio_file}}"{%if task_type%},"task_type":"{{task_type}}"{%endif%}}', + response='{"taskid":"{{task_id}}","taskstatus":"PENDING","status":"PENDING"}', + ioid='ktv_demucs_separate_io' WHERE id='uapi_ktv_demucs_separate'; + +-- 3. 人脸检测 (sync) +UPDATE uapi SET stream='sync',headers='{"Content-Type":"application/json"}', + data='{"image_file":"{{image_file}}"}', + response='{%if error%}{"error":"{{error}}"}{%else%}{"status":"{{status}}","faces":{{json.dumps(faces,ensure_ascii=False)}},"usage":{{json.dumps(usage,ensure_ascii=False)}}}{%endif%}', + 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_file":"{{image_file}}"{%if face_id%},"face_id":"{{face_id}}"{%endif%}}', + response='{%if error%}{"error":"{{error}}"}{%else%}{"status":"{{status}}","matches":{{json.dumps(matches,ensure_ascii=False)}},"usage":{{json.dumps(usage,ensure_ascii=False)}}}{%endif%}', + 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_file1":"{{image_file1}}","image_file2":"{{image_file2}}"}', + response='{%if error%}{"error":"{{error}}"}{%else%}{"status":"{{status}}","similarity":{{similarity}},"usage":{{json.dumps(usage,ensure_ascii=False)}}}{%endif%}', + ioid='ktv_face_compare_io' WHERE id='uapi_ktv_face_compare'; + +-- 6. 字幕渲染 (sync) +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='{%if error%}{"error":"{{error}}"}{%else%}{"status":"{{status}}","ass_url":"{{ass_url}}","usage":{{json.dumps(usage,ensure_ascii=False)}}}{%endif%}', + ioid='ktv_subtitle_render_io' WHERE id='uapi_ktv_subtitle_render'; + +-- 7. 视频合并 (sync) +UPDATE uapi SET stream='sync',headers='{"Content-Type":"application/json"}', + data='{%set c=joiner(",")%}{{%if video_file%}{{c()}}"video_file":"{{video_file}}"{%endif%}{%if audio_file%}{{c()}}"audio_file":"{{audio_file}}"{%endif%}{%if subtitle_file%}{{c()}}"subtitle_file":"{{subtitle_file}}"{%endif%}{%if output_format%}{{c()}}"output_format":"{{output_format}}"{%endif%}}', + response='{%if error%}{"error":"{{error}}"}{%else%}{"status":"{{status}}","output_url":"{{output_url}}","duration":{{duration}},"usage":{{json.dumps(usage,ensure_ascii=False)}}}{%endif%}', + ioid='ktv_merge_video_io' WHERE id='uapi_ktv_merge_video'; + +-- 8. 歌曲评分 (sync) +UPDATE uapi SET stream='sync',headers='{"Content-Type":"application/json"}', + data='{"audio_file":"{{audio_file}}"{%if scene%},"scene":"{{scene}}"{%endif%}}', + response='{%if error%}{"error":"{{error}}"}{%else%}{"status":"{{status}}","score":{{score}},"details":{{json.dumps(details,ensure_ascii=False)}},"usage":{{json.dumps(usage,ensure_ascii=False)}}}{%endif%}', + ioid='ktv_songrate_evaluate_io' WHERE id='uapi_ktv_songrate_evaluate'; + +-- 9. 合成状态查询 (sync) +UPDATE uapi SET stream='sync',headers='{"Content-Type":"application/json"}', + data='{"task_id":"{{task_id}}"}', + response='{%if error%}{"error":"{{error}}"}{%elif status=="SUCCEEDED"%}{"taskstatus":"SUCCEEDED","output_url":"{{output_url}}","usage":{{json.dumps(usage,ensure_ascii=False)}}}{%elif status=="FAILED"%}{"taskstatus":"FAILED","error":"{{error}}"}{%else%}{"taskstatus":"PENDING"}{%endif%}', + ioid='ktv_synth_status_io' WHERE id='uapi_ktv_synth_status'; + +-- 11. 超分辨率 (async提交) +UPDATE uapi SET stream='async',headers='{"Content-Type":"application/json"}', + data='{"image_file":"{{image_file}}"{%if scale%},"scale":{{scale}}{%endif%}}', + response='{"taskid":"{{task_id}}","taskstatus":"PENDING"}', + ioid='ktv_realesrgan_upscale_io' WHERE id='uapi_ktv_realesrgan_upscale'; + +-- 12. 超分状态查询 (sync) +UPDATE uapi SET stream='sync',headers='{"Content-Type":"application/json"}', + data=NULL, + response='{"status":"{{status}}","output_url":"{{output_url}}","usage":{{json.dumps(usage,ensure_ascii=False)}}}', + ioid='ktv_realesrgan_status_io' WHERE id='uapi_ktv_realesrgan_status'; + +-- 13. RVC声音转换 (sync) +UPDATE uapi SET stream='sync',headers='{"Content-Type":"application/json"}', + data='{"audio_file":"{{audio_file}}","voice_model":"{{voice_model}}"}', + response='{%if error%}{"error":"{{error}}"}{%else%}{"status":"{{status}}","output_url":"{{output_url}}","usage":{{json.dumps(usage,ensure_ascii=False)}}}{%endif%}', + ioid='ktv_rvc_convert_io' WHERE id='uapi_ktv_rvc_convert'; + +-- 14. 视频评估 (sync) +UPDATE uapi SET stream='sync',headers='{"Content-Type":"application/json"}', + data='{"video_file":"{{video_file}}"}', + response='{%if error%}{"error":"{{error}}"}{%else%}{"status":"{{status}}","score":{{score}},"details":{{json.dumps(details,ensure_ascii=False)}},"usage":{{json.dumps(usage,ensure_ascii=False)}}}{%endif%}', + ioid='ktv_video_eval_evaluate_io' WHERE id='uapi_ktv_video_eval_evaluate'; + +-- async query_apiname +UPDATE llm_api_map SET query_apiname='realesrgan-status',query_period=5 WHERE llmid='llm_ktv_realesrgan_upscale'; + +-- ppid (v1/models 过滤要求 ppid IS NOT NULL) +UPDATE llm_api_map SET ppid='pp_ktv' WHERE llmid LIKE 'llm_ktv%' AND ppid IS NULL; + +-- upappkey (API调用鉴权必需) +INSERT INTO upappkey (id,upappid,ownerid,apikey,orgid) +SELECT 'ktv_gateway_key','ktv-gateway','UiEi7hKqAmU1-jqQEVhZe','','0' +WHERE NOT EXISTS (SELECT 1 FROM upappkey WHERE upappid='ktv-gateway'); 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'; diff --git a/scripts/ktv_uapi_migration_p4_pricing.sql b/scripts/ktv_uapi_migration_p4_pricing.sql new file mode 100644 index 00000000..30d8899c --- /dev/null +++ b/scripts/ktv_uapi_migration_p4_pricing.sql @@ -0,0 +1,101 @@ +-- ============================================================ +-- KTV服务 定价修复 Part 4 +-- 每个模型独立ppid + 按量计费(price_factors=字段名) +-- ============================================================ + +-- 1. 创建独立ppid(每模型一个) +INSERT INTO pricing_program (id,providerid,name) VALUES +('pp_ktv_asr','FZoJv7EUEdKL3pUt0BQ5S','KTV-语音识别'), +('pp_ktv_demucs','FZoJv7EUEdKL3pUt0BQ5S','KTV-音频分离'), +('pp_ktv_face_detect','FZoJv7EUEdKL3pUt0BQ5S','KTV-人脸检测'), +('pp_ktv_face_recognize','FZoJv7EUEdKL3pUt0BQ5S','KTV-人脸识别'), +('pp_ktv_face_compare','FZoJv7EUEdKL3pUt0BQ5S','KTV-人脸比对'), +('pp_ktv_subtitle','FZoJv7EUEdKL3pUt0BQ5S','KTV-字幕渲染'), +('pp_ktv_merge','FZoJv7EUEdKL3pUt0BQ5S','KTV-视频合并'), +('pp_ktv_songrate','FZoJv7EUEdKL3pUt0BQ5S','KTV-歌曲评分'), + +('pp_ktv_synth_status','FZoJv7EUEdKL3pUt0BQ5S','KTV-合成状态'), +('pp_ktv_realesrgan','FZoJv7EUEdKL3pUt0BQ5S','KTV-超分辨率'), +('pp_ktv_realesrgan_status','FZoJv7EUEdKL3pUt0BQ5S','KTV-超分状态'), +('pp_ktv_rvc','FZoJv7EUEdKL3pUt0BQ5S','KTV-声音转换'), +('pp_ktv_video_eval','FZoJv7EUEdKL3pUt0BQ5S','KTV-视频评估') +ON DUPLICATE KEY UPDATE providerid=VALUES(providerid); + +-- 2. 迁移 pricing_program_timing 到新 ppid +UPDATE pricing_program_timing SET ppid='pp_ktv_asr' WHERE id='pt_ktv_asr_transcribe'; +UPDATE pricing_program_timing SET ppid='pp_ktv_demucs' WHERE id='pt_ktv_demucs_separate'; +UPDATE pricing_program_timing SET ppid='pp_ktv_face_detect' WHERE id='pt_ktv_face_detect'; +UPDATE pricing_program_timing SET ppid='pp_ktv_face_recognize' WHERE id='pt_ktv_face_recognize'; +UPDATE pricing_program_timing SET ppid='pp_ktv_face_compare' WHERE id='pt_ktv_face_compare'; +UPDATE pricing_program_timing SET ppid='pp_ktv_subtitle' WHERE id='pt_ktv_subtitle_render'; +UPDATE pricing_program_timing SET ppid='pp_ktv_merge' WHERE id='pt_ktv_merge_video'; +UPDATE pricing_program_timing SET ppid='pp_ktv_songrate' WHERE id='pt_ktv_songrate_evaluate'; + +UPDATE pricing_program_timing SET ppid='pp_ktv_synth_status' WHERE id='pt_ktv_synth_status'; +UPDATE pricing_program_timing SET ppid='pp_ktv_realesrgan' WHERE id='pt_ktv_realesrgan_upscale'; +UPDATE pricing_program_timing SET ppid='pp_ktv_realesrgan_status' WHERE id='pt_ktv_realesrgan_status'; +UPDATE pricing_program_timing SET ppid='pp_ktv_rvc' WHERE id='pt_ktv_rvc_convert'; +UPDATE pricing_program_timing SET ppid='pp_ktv_video_eval' WHERE id='pt_ktv_video_eval_evaluate'; + +-- 3. 更新 pricing_data YAML:price_factors=字段名(按量计费) +-- asr: audio_seconds × 0.01 +UPDATE pricing_program_timing SET pricing_data='unit_values:\n audio_seconds: 1\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: audio_seconds\n unit_prices: 0.01\n unit: audio_seconds' WHERE id='pt_ktv_asr_transcribe'; + +-- demucs: audio_seconds × 0.02 +UPDATE pricing_program_timing SET pricing_data='unit_values:\n audio_seconds: 1\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: audio_seconds\n unit_prices: 0.02\n unit: audio_seconds' WHERE id='pt_ktv_demucs_separate'; + +-- face-detect: detect_count × 0.10 +UPDATE pricing_program_timing SET pricing_data='unit_values:\n detect_count: 1\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: detect_count\n unit_prices: 0.10\n unit: detect_count' WHERE id='pt_ktv_face_detect'; + +-- face-recognize: recognize_count × 0.10 +UPDATE pricing_program_timing SET pricing_data='unit_values:\n recognize_count: 1\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: recognize_count\n unit_prices: 0.10\n unit: recognize_count' WHERE id='pt_ktv_face_recognize'; + +-- face-compare: compare_count × 0.10 +UPDATE pricing_program_timing SET pricing_data='unit_values:\n compare_count: 1\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: compare_count\n unit_prices: 0.10\n unit: compare_count' WHERE id='pt_ktv_face_compare'; + +-- subtitle: subtitle_count × 0.01 +UPDATE pricing_program_timing SET pricing_data='unit_values:\n subtitle_count: 1\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: subtitle_count\n unit_prices: 0.01\n unit: subtitle_count' WHERE id='pt_ktv_subtitle_render'; + +-- merge: output_seconds × 0.01 +UPDATE pricing_program_timing SET pricing_data='unit_values:\n output_seconds: 1\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: output_seconds\n unit_prices: 0.01\n unit: output_seconds' WHERE id='pt_ktv_merge_video'; + +-- songrate: audio_seconds × 0.005 +UPDATE pricing_program_timing SET pricing_data='unit_values:\n audio_seconds: 1\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: audio_seconds\n unit_prices: 0.005\n unit: audio_seconds' WHERE id='pt_ktv_songrate_evaluate'; + +-- synth-generate: audio_seconds × 0.20 +UPDATE pricing_program_timing SET pricing_data='unit_values:\n audio_seconds: 1\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: audio_seconds\n unit_prices: 0.20\n unit: audio_seconds' WHERE id='pt_ktv_synth_generate'; + +-- synth-status: flat 0.01 +UPDATE pricing_program_timing SET pricing_data='unit_values:\n 次: 1\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: flat\n unit_prices: 0.01\n unit: 次' WHERE id='pt_ktv_synth_status'; + +-- realesrgan-upscale: image_count × 0.50 +UPDATE pricing_program_timing SET pricing_data='unit_values:\n image_count: 1\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: image_count\n unit_prices: 0.50\n unit: image_count' WHERE id='pt_ktv_realesrgan_upscale'; + +-- realesrgan-status: flat 0.01 +UPDATE pricing_program_timing SET pricing_data='unit_values:\n 次: 1\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: flat\n unit_prices: 0.01\n unit: 次' WHERE id='pt_ktv_realesrgan_status'; + +-- rvc: audio_seconds × 0.15 +UPDATE pricing_program_timing SET pricing_data='unit_values:\n audio_seconds: 1\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: audio_seconds\n unit_prices: 0.15\n unit: audio_seconds' WHERE id='pt_ktv_rvc_convert'; + +-- video-eval: video_seconds × 0.05 +UPDATE pricing_program_timing SET pricing_data='unit_values:\n video_seconds: 1\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: video_seconds\n unit_prices: 0.05\n unit: video_seconds' WHERE id='pt_ktv_video_eval_evaluate'; + +-- 4. 更新 llm_api_map 指向独立 ppid +UPDATE llm_api_map SET ppid='pp_ktv_asr' WHERE llmid='llm_ktv_asr_transcribe'; +UPDATE llm_api_map SET ppid='pp_ktv_demucs' WHERE llmid='llm_ktv_demucs_separate'; +UPDATE llm_api_map SET ppid='pp_ktv_face_detect' WHERE llmid='llm_ktv_face_detect'; +UPDATE llm_api_map SET ppid='pp_ktv_face_recognize' WHERE llmid='llm_ktv_face_recognize'; +UPDATE llm_api_map SET ppid='pp_ktv_face_compare' WHERE llmid='llm_ktv_face_compare'; +UPDATE llm_api_map SET ppid='pp_ktv_subtitle' WHERE llmid='llm_ktv_subtitle_render'; +UPDATE llm_api_map SET ppid='pp_ktv_merge' WHERE llmid='llm_ktv_merge_video'; +UPDATE llm_api_map SET ppid='pp_ktv_songrate' WHERE llmid='llm_ktv_songrate_evaluate'; + +UPDATE llm_api_map SET ppid='pp_ktv_synth_status' WHERE llmid='llm_ktv_synth_status'; +UPDATE llm_api_map SET ppid='pp_ktv_realesrgan' WHERE llmid='llm_ktv_realesrgan_upscale'; +UPDATE llm_api_map SET ppid='pp_ktv_realesrgan_status' WHERE llmid='llm_ktv_realesrgan_status'; +UPDATE llm_api_map SET ppid='pp_ktv_rvc' WHERE llmid='llm_ktv_rvc_convert'; +UPDATE llm_api_map SET ppid='pp_ktv_video_eval' WHERE llmid='llm_ktv_video_eval_evaluate'; + +-- 修复 pricing_program 字符集不一致(生产环境 utf8mb4_general_ci vs organization utf8mb4_unicode_ci) +ALTER TABLE pricing_program MODIFY ownerid VARCHAR(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; +ALTER TABLE pricing_program MODIFY providerid VARCHAR(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; diff --git a/scripts/ktv_uapi_migration_p5_datafix.sql b/scripts/ktv_uapi_migration_p5_datafix.sql new file mode 100644 index 00000000..3c2894c5 --- /dev/null +++ b/scripts/ktv_uapi_migration_p5_datafix.sql @@ -0,0 +1,66 @@ +-- ============================================================ +-- KTV服务 数据模板修复 Part 5 +-- 匹配GPU实际参数名 + demucs async改造 +-- ============================================================ + +-- asr: audio_file → audio_path +UPDATE uapi SET data='{"audio_path":"{{audio_file}}"{%if language%},"language":"{{language}}"{%endif%}}' WHERE id='uapi_ktv_asr_transcribe'; + +-- demucs: audio_file → audio_path +UPDATE uapi SET data='{"audio_path":"{{audio_file}}"{%if task_type%},"task_type":"{{task_type}}"{%endif%}}' WHERE id='uapi_ktv_demucs_separate'; + +-- face-detect: image_file → images list +UPDATE uapi SET data='{"images":["{{image_file}}"]}' WHERE id='uapi_ktv_face_detect'; + +-- face-recognize: image_file → images list +UPDATE uapi SET data='{"images":["{{image_file}}"]{%if face_id%},"face_id":"{{face_id}}"{%endif%}}' WHERE id='uapi_ktv_face_recognize'; + +-- face-compare: image_file1→embedding1, image_file2→embedding2 +UPDATE uapi SET data='{"embedding1":"{{image_file1}}","embedding2":"{{image_file2}}"}' WHERE id='uapi_ktv_face_compare'; + +-- subtitle: lyrics_json → lyrics +UPDATE uapi SET data='{"lyrics":{{lyrics_json}}{%if width%},"width":{{width}}{%endif%}{%if height%},"height":{{height}}{%endif%}}' WHERE id='uapi_ktv_subtitle_render'; + +-- merge: video_file→video_url, audio_file→audio_path +UPDATE uapi SET data='{%set c=joiner(",")%}{{%if video_file%}{{c()}}"video_url":"{{video_file}}"{%endif%}{%if audio_file%}{{c()}}"audio_path":"{{audio_file}}"{%endif%}{%if subtitle_file%}{{c()}}"subtitle_url":"{{subtitle_file}}"{%endif%}{%if output_format%}{{c()}}"output_format":"{{output_format}}"{%endif%}}' WHERE id='uapi_ktv_merge_video'; + +-- songrate: audio_file→audio_path +UPDATE uapi SET data='{"audio_path":"{{audio_file}}"{%if scene%},"scene":"{{scene}}"{%endif%}}' WHERE id='uapi_ktv_songrate_evaluate'; + +-- synth-status: GET, params in query string, no body +UPDATE uapi SET httpmethod='GET', data=NULL, path='/synth/api/synth-status?task_id={{taskid}}' WHERE id='uapi_ktv_synth_status'; + +-- realesrgan-upscale: image_file→image_url +UPDATE uapi SET data='{"image_url":"{{image_file}}"{%if scale%},"scale":{{scale}}{%endif%}}' WHERE id='uapi_ktv_realesrgan_upscale'; + +-- realesrgan-status: GET, params in query string, no body +UPDATE uapi SET httpmethod='GET', data=NULL, path='/realesrgan/api/realesrgan-status?task_id={{taskid}}' WHERE id='uapi_ktv_realesrgan_status'; + +-- rvc: audio_file→audio_path, voice_model→model +UPDATE uapi SET data='{"audio_path":"{{audio_file}}","model":"{{voice_model}}"}' WHERE id='uapi_ktv_rvc_convert'; + +-- video-eval: video_file→video_url +UPDATE uapi SET data='{"video_url":"{{video_file}}"}' WHERE id='uapi_ktv_video_eval_evaluate'; + +-- ============================================================ +-- demucs async 改造: status 查询端点 + query_apiname +-- ============================================================ + +INSERT INTO uapi (id,name,title,description,path,httpmethod,upappid,stream,headers,data,response,ioid) +VALUES ('uapi_ktv_demucs_status','demucs-status','Demucs Status', +'Query demucs task','/demucs/api/demucs-status?task_id={{taskid}}','GET', +'ktv-gateway','sync','{"Content-Type":"application/json"}',NULL, +'{"status":"{{status}}","vocals_url":"{{vocals_url}}","accompaniment_url":"{{accompaniment_url}}","duration":{{duration}},"usage":{{json.dumps(usage,ensure_ascii=False)}}}', +'ktv_demucs_separate_io') +ON DUPLICATE KEY UPDATE response=VALUES(response); + +UPDATE llm_api_map SET query_apiname='demucs-status',query_period=5 WHERE llmid='llm_ktv_demucs_separate'; + +-- ============================================================ +-- 补充缺失的 pricing_program_timing 记录 +-- ============================================================ +INSERT INTO pricing_program_timing (id,ppid,name,pricing_data,enabled_date,expired_date) VALUES +('pt_ktv_face_compare','pp_ktv_face_compare','KTV人脸比对','unit_values:\n compare_count: 1\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: compare_count\n unit_prices: 0.10\n unit: compare_count','2025-01-01','9999-12-31'), +('pt_ktv_synth_status','pp_ktv_synth_status','KTV合成状态','unit_values:\n 次: 1\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: flat\n unit_prices: 0.01\n unit: 次','2025-01-01','9999-12-31'), +('pt_ktv_realesrgan_status','pp_ktv_realesrgan_status','KTV超分状态','unit_values:\n 次: 1\nfields:\n price_factors:\n type: string\n role: factor\n label: 计价因子\n unit_prices:\n type: float\n role: factor\n label: 单位定价\n unit:\n type: string\n role: factor\n label: 计价单位\npricings:\n- price_factors: flat\n unit_prices: 0.01\n unit: 次','2025-01-01','9999-12-31') +ON DUPLICATE KEY UPDATE ppid=VALUES(ppid), pricing_data=VALUES(pricing_data); diff --git a/scripts/ktv_uapi_migration_p6_happyhorse.sql b/scripts/ktv_uapi_migration_p6_happyhorse.sql new file mode 100644 index 00000000..657076ee --- /dev/null +++ b/scripts/ktv_uapi_migration_p6_happyhorse.sql @@ -0,0 +1,21 @@ +-- ============================================================ +-- HappyHorse + image model name 修复 +-- upstream aliyun 不认识中文模型名,需用英文 model identifier +-- ============================================================ + +-- t2v (HappyHorse 文生视频) +UPDATE uapi SET data = REPLACE(data, '"model": "{{model}}"', '"model": "happyhorse-1.0-t2v"') +WHERE name='t2v' AND upappid='tongyi-wan'; + +-- wan2.7-image-pro +UPDATE uapi SET data = REPLACE(data, '"model": "{{model}}"', '"model": "wan2.7-image-pro"') +WHERE name='wan2.7-image-sync' AND upappid='tongyi-wan'; + +-- ============================================================ +-- ASR 修复: data JSON格式 + async + status端点 +-- ============================================================ + +UPDATE uapi SET stream='async', + data='{"audio_path":"{{audio_file}}"{%if language%},"language":"{{language}}"{%endif%}}', + response='{"taskid":"{{task_id}}","taskstatus":"PENDING","status":"PENDING"}' +WHERE id='uapi_ktv_asr_transcribe'; diff --git a/set_core_perms.sh b/set_core_perms.sh new file mode 100755 index 00000000..74d55899 --- /dev/null +++ b/set_core_perms.sh @@ -0,0 +1,30 @@ +#!/bin/bash +set -e +cd "$(dirname "$0")" + +COUNT=0 +set_perm() { + python set_role_perm.py "$1" "$2" > /dev/null 2>&1 + COUNT=$((COUNT + 1)) +} + +echo ">>> Setting core paths to any role..." + +# Core UI files +for p in "/index.ui" "/top.ui" "/center.ui" "/bottom.ui"; do + set_perm "any" "$p" +done + +# bricks/* - all files and subdirectories +while IFS= read -r file; do + rel="${file#/home/hermesai/repos/sage/wwwroot}" + set_perm "any" "$rel" +done < <(find wwwroot/bricks -type f 2>/dev/null) + +# public/* - all files and subdirectories +while IFS= read -r file; do + rel="${file#/home/hermesai/repos/sage/wwwroot}" + set_perm "any" "$rel" +done < <(find wwwroot/public -type f 2>/dev/null) + +echo "Done. Set ${COUNT} paths to any." diff --git a/set_role_perm.py b/set_role_perm.py index 2ac5633d..92653159 100644 --- a/set_role_perm.py +++ b/set_role_perm.py @@ -1,3 +1,4 @@ +import os import sys import asyncio from sqlor.dbpools import DBPools @@ -34,7 +35,8 @@ async def main(): role = sys.argv[1] path = sys.argv[2] - async with db.sqlorContext('sage') as sor: + dbname = os.environ.get('SAGE_RBAC_DB', 'sage') + async with db.sqlorContext(dbname) as sor: perms = None if '%' in path: perms = await sor.sqlExe("select * from permission where path like ${path}$", {'path': path}) diff --git a/setup_harnessed_perms.sh b/setup_harnessed_perms.sh new file mode 100644 index 00000000..d664e91e --- /dev/null +++ b/setup_harnessed_perms.sh @@ -0,0 +1,322 @@ +#!/bin/bash +# setup_harnessed_perms.sh +# 为 harnessed_agent(执行层)和 harnessed_reasoning(推理层)模块配置 RBAC 角色权限 +# +# 角色职责定义: +# owner.superuser — 系统级管理员:系统机构类型管理、角色管理、权限管理、添加业主机构管理员 +# 系统初始化时由代码自动创建,拥有全部权限 +# *.admin — 机构管理员(owner/reseller/provider/customer.admin): +# 添加本机构人员、分配人员角色、管理系统级配置 +# reseller.operator — 运营:产品管理、供应商合同、产品定价、统一客户折扣、营销活动 +# reseller.sale — 销售:客户管理、客户特殊折扣设定 +# reseller.accountant — 财务:线下客户充值、分销商/供应商对账结算 +# reseller.maintainer — 维护:系统运维 +# logined — 所有已登录用户(含上述所有角色) +# +# 权限分级策略(基于业务功能分析): +# 1. public — 静态资源(CSS),any 角色可用 +# 2. logined — 控制台主页、数据查看、核心使用功能,所有登录用户可用 +# 3. admin — 系统配置管理、Agent/推理配置,仅 superuser 和机构管理员 +# 4. superuser — 技能部署等高危操作,仅系统超级管理员 +# +# 运行位置: sage 项目根目录 (包含 set_role_perm.py 的目录) +# 用法: bash setup_harnessed_perms.sh + +set -e + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +cd "$SCRIPT_DIR" + +COUNT=0 +set_perm() { + local role="$1" + local path="$2" + python set_role_perm.py "${role}" "${path}" + COUNT=$((COUNT + 1)) +} + +# 角色分组 +ALL_LOGINED=("logined" "owner.superuser" "owner.admin" "reseller.admin" "provider.admin" "customer.admin" "reseller.operator" "reseller.sale" "reseller.accountant" "reseller.maintainer" "customer.customer") +ADMIN_ROLES=("owner.superuser" "owner.admin" "reseller.admin" "provider.admin" "customer.admin") +SUPERUSER_ONLY=("owner.superuser") + +echo "============================================" +echo " harnessed 模块权限初始化" +echo "============================================" + +# ============================================= +# 层级 1: PUBLIC — 静态资源 +# ============================================= +echo "" +echo ">>> [1/4] Public: 静态资源 (any)" +PUBLIC_FILES=( + "/harnessed_agent/ios_design.css" + "/harnessed_reasoning/ios_design.css" +) +for f in "${PUBLIC_FILES[@]}"; do + set_perm "any" "${f}" +done + +# ============================================= +# 层级 2: LOGINED — 所有登录用户可用 +# ============================================= +echo "" +echo ">>> [2/4] Logined: 控制台 + 数据查看 + 核心使用 (所有登录用户)" + +LOGINED_PATHS=( + # ========== harnessed_agent ========== + # 控制台/主页(用户使用入口) + "/harnessed_agent/hermes_agent.ui" + "/harnessed_agent/agent_console.ui" + "/harnessed_agent/menu.ui" + + # 数据查看(所有登录用户可查看自己的数据) + "/harnessed_agent/sessions.ui" + "/harnessed_agent/skills.ui" + "/harnessed_agent/tasks.ui" + "/harnessed_agent/workflows.ui" + "/harnessed_agent/memory.ui" + "/harnessed_agent/tools.ui" + "/harnessed_agent/remote_skills.ui" + + # CRUD 列表页 — 目录路径(ahserver indexes 匹配)+ /index.ui + "/harnessed_agent/hermes_memory" + "/harnessed_agent/hermes_memory/index.ui" + "/harnessed_agent/hermes_sessions" + "/harnessed_agent/hermes_sessions/index.ui" + "/harnessed_agent/hermes_skills" + "/harnessed_agent/hermes_skills/index.ui" + "/harnessed_agent/hermes_tasks" + "/harnessed_agent/hermes_tasks/index.ui" + "/harnessed_agent/hermes_workflows" + "/harnessed_agent/hermes_workflows/index.ui" + "/harnessed_agent/hermes_executions" + "/harnessed_agent/hermes_executions/index.ui" + "/harnessed_agent/hermes_executions_task" + "/harnessed_agent/hermes_executions_task/index.ui" + "/harnessed_agent/hermes_tasks_workflow" + "/harnessed_agent/hermes_tasks_workflow/index.ui" + "/harnessed_agent/harnessed_remote_skills" + "/harnessed_agent/harnessed_remote_skills/index.ui" + "/harnessed_agent/harnessed_agent_config_view" + "/harnessed_agent/harnessed_agent_config_view/index.ui" + "/harnessed_agent/executions_by_workflow" + "/harnessed_agent/executions_by_workflow/index.ui" + "/harnessed_agent/task_dependencies" + "/harnessed_agent/task_dependencies/index.ui" + + # CRUD 数据读取(get_*.dspy) + "/harnessed_agent/hermes_memory/get_hermes_memory.dspy" + "/harnessed_agent/hermes_sessions/get_hermes_sessions.dspy" + "/harnessed_agent/hermes_skills/get_hermes_skills.dspy" + "/harnessed_agent/hermes_tasks/get_hermes_tasks.dspy" + "/harnessed_agent/hermes_workflows/get_hermes_workflows.dspy" + "/harnessed_agent/hermes_executions/get_hermes_executions.dspy" + "/harnessed_agent/hermes_executions_task/get_hermes_executions_task.dspy" + "/harnessed_agent/hermes_tasks_workflow/get_hermes_tasks_workflow.dspy" + "/harnessed_agent/harnessed_remote_skills/get_harnessed_remote_skills.dspy" + "/harnessed_agent/harnessed_agent_config_view/get_harnessed_agent_config_view.dspy" + "/harnessed_agent/executions_by_workflow/get_executions_by_workflow.dspy" + "/harnessed_agent/task_dependencies/get_task_dependencies.dspy" + + # CRUD 数据写入(用户管理自己的数据) + # 记忆管理(用户可增删改自己的记忆) + "/harnessed_agent/hermes_memory/add_hermes_memory.dspy" + "/harnessed_agent/hermes_memory/update_hermes_memory.dspy" + "/harnessed_agent/hermes_memory/delete_hermes_memory.dspy" + "/harnessed_agent/api/hermes_memory_create.dspy" + "/harnessed_agent/api/hermes_memory_update.dspy" + "/harnessed_agent/api/hermes_memory_delete.dspy" + # 任务管理(用户可创建/管理自己的任务) + "/harnessed_agent/hermes_tasks/add_hermes_tasks.dspy" + "/harnessed_agent/hermes_tasks/update_hermes_tasks.dspy" + "/harnessed_agent/hermes_tasks/delete_hermes_tasks.dspy" + "/harnessed_agent/api/hermes_tasks_create.dspy" + "/harnessed_agent/api/hermes_tasks_update.dspy" + "/harnessed_agent/api/hermes_tasks_delete.dspy" + # 技能管理(用户可管理自己的技能) + "/harnessed_agent/hermes_skills/add_hermes_skills.dspy" + "/harnessed_agent/hermes_skills/update_hermes_skills.dspy" + "/harnessed_agent/hermes_skills/delete_hermes_skills.dspy" + "/harnessed_agent/api/hermes_skills_create.dspy" + "/harnessed_agent/api/hermes_skills_update.dspy" + "/harnessed_agent/api/hermes_skills_delete.dspy" + # 会话管理(用户可管理自己的会话) + "/harnessed_agent/hermes_sessions/add_hermes_sessions.dspy" + "/harnessed_agent/hermes_sessions/update_hermes_sessions.dspy" + "/harnessed_agent/hermes_sessions/delete_hermes_sessions.dspy" + "/harnessed_agent/api/hermes_sessions_create.dspy" + "/harnessed_agent/api/hermes_sessions_update.dspy" + "/harnessed_agent/api/hermes_sessions_delete.dspy" + # 工作流管理(用户可管理自己的工作流) + "/harnessed_agent/hermes_workflows/add_hermes_workflows.dspy" + "/harnessed_agent/hermes_workflows/update_hermes_workflows.dspy" + "/harnessed_agent/hermes_workflows/delete_hermes_workflows.dspy" + "/harnessed_agent/api/hermes_workflows_create.dspy" + "/harnessed_agent/api/hermes_workflows_update.dspy" + "/harnessed_agent/api/hermes_workflows_delete.dspy" + # 执行记录(用户可创建/更新执行记录) + "/harnessed_agent/hermes_executions/add_hermes_executions.dspy" + "/harnessed_agent/hermes_executions/update_hermes_executions.dspy" + "/harnessed_agent/hermes_executions/delete_hermes_executions.dspy" + "/harnessed_agent/api/hermes_executions_create.dspy" + "/harnessed_agent/api/hermes_executions_update.dspy" + "/harnessed_agent/api/hermes_executions_delete.dspy" + # 执行任务 + "/harnessed_agent/hermes_executions_task/add_hermes_executions_task.dspy" + "/harnessed_agent/hermes_executions_task/update_hermes_executions_task.dspy" + "/harnessed_agent/hermes_executions_task/delete_hermes_executions_task.dspy" + "/harnessed_agent/api/hermes_executions_task_create.dspy" + "/harnessed_agent/api/hermes_executions_task_update.dspy" + "/harnessed_agent/api/hermes_executions_task_delete.dspy" + # 任务-工作流关联 + "/harnessed_agent/hermes_tasks_workflow/add_hermes_tasks_workflow.dspy" + "/harnessed_agent/hermes_tasks_workflow/update_hermes_tasks_workflow.dspy" + "/harnessed_agent/hermes_tasks_workflow/delete_hermes_tasks_workflow.dspy" + "/harnessed_agent/api/hermes_tasks_workflow_create.dspy" + "/harnessed_agent/api/hermes_tasks_workflow_update.dspy" + "/harnessed_agent/api/hermes_tasks_workflow_delete.dspy" + # 远程技能 + "/harnessed_agent/harnessed_remote_skills/add_harnessed_remote_skills.dspy" + "/harnessed_agent/harnessed_remote_skills/update_harnessed_remote_skills.dspy" + "/harnessed_agent/harnessed_remote_skills/delete_harnessed_remote_skills.dspy" + "/harnessed_agent/api/harnessed_remote_skills_create.dspy" + "/harnessed_agent/api/harnessed_remote_skills_update.dspy" + "/harnessed_agent/api/harnessed_remote_skills_delete.dspy" + # 执行-工作流关联 + "/harnessed_agent/executions_by_workflow/add_executions_by_workflow.dspy" + "/harnessed_agent/executions_by_workflow/update_executions_by_workflow.dspy" + "/harnessed_agent/executions_by_workflow/delete_executions_by_workflow.dspy" + "/harnessed_agent/api/executions_by_workflow_create.dspy" + "/harnessed_agent/api/executions_by_workflow_update.dspy" + "/harnessed_agent/api/executions_by_workflow_delete.dspy" + # 任务依赖 + "/harnessed_agent/task_dependencies/add_task_dependencies.dspy" + "/harnessed_agent/task_dependencies/update_task_dependencies.dspy" + "/harnessed_agent/task_dependencies/delete_task_dependencies.dspy" + "/harnessed_agent/api/task_dependencies_create.dspy" + "/harnessed_agent/api/task_dependencies_update.dspy" + "/harnessed_agent/api/task_dependencies_delete.dspy" + + # Agent 核心执行(用户使用功能) + "/harnessed_agent/api/agent_execute.dspy" + "/harnessed_agent/api/agent_config_get.dspy" + "/harnessed_agent/hermes.dspy" + + # ========== harnessed_reasoning ========== + # 控制台/主页 + "/harnessed_reasoning/hermes_reasoning.ui" + "/harnessed_reasoning/reasoning_console.ui" + "/harnessed_reasoning/menu.ui" + + # WSS WebSocket 端点(nginx去掉/wss前缀后应用收到的path) + "/harnessed_reasoning/reasoning_console.wss" + + # 数据查看 + "/harnessed_reasoning/harnessed_reasoning_sessions_crud.ui" + "/harnessed_reasoning/harnessed_reasoning_config_view.ui" + + # CRUD 列表页 — 目录路径 + /index.ui + "/harnessed_reasoning/harnessed_reasoning_sessions_crud" + "/harnessed_reasoning/harnessed_reasoning_sessions_crud/index.ui" + "/harnessed_reasoning/harnessed_reasoning_session_detail" + "/harnessed_reasoning/harnessed_reasoning_session_detail/index.ui" + "/harnessed_reasoning/harnessed_reasoning_config_view" + "/harnessed_reasoning/harnessed_reasoning_config_view/index.ui" + + # CRUD 数据读取 + "/harnessed_reasoning/harnessed_reasoning_sessions_crud/get_harnessed_reasoning_sessions_crud.dspy" + "/harnessed_reasoning/harnessed_reasoning_session_detail/get_harnessed_reasoning_session_detail.dspy" + "/harnessed_reasoning/harnessed_reasoning_config_view/get_harnessed_reasoning_config_view.dspy" + + # CRUD 数据写入(用户管理自己的推理会话数据) + "/harnessed_reasoning/harnessed_reasoning_sessions_crud/add_harnessed_reasoning_sessions_crud.dspy" + "/harnessed_reasoning/harnessed_reasoning_sessions_crud/update_harnessed_reasoning_sessions_crud.dspy" + "/harnessed_reasoning/harnessed_reasoning_sessions_crud/delete_harnessed_reasoning_sessions_crud.dspy" + "/harnessed_reasoning/harnessed_reasoning_session_detail/add_harnessed_reasoning_session_detail.dspy" + "/harnessed_reasoning/harnessed_reasoning_session_detail/update_harnessed_reasoning_session_detail.dspy" + "/harnessed_reasoning/harnessed_reasoning_session_detail/delete_harnessed_reasoning_session_detail.dspy" + + # 推理核心功能(所有登录用户可用) + "/harnessed_reasoning/api/reasoning_submit.dspy" + "/harnessed_reasoning/api/sessions_list.dspy" + "/harnessed_reasoning/api/config_get.dspy" +) + +for p in "${LOGINED_PATHS[@]}"; do + for role in "${ALL_LOGINED[@]}"; do + set_perm "${role}" "${p}" + done +done + +# ============================================= +# 层级 3: ADMIN — 系统配置管理 +# ============================================= +echo "" +echo ">>> [3/4] Admin: 系统配置管理 (superuser + 机构管理员)" + +ADMIN_PATHS=( + # harnessed_agent — Agent 系统配置(影响整个系统的LLM设置) + "/harnessed_agent/agent_config.ui" + "/harnessed_agent/agent_config_form.ui" + "/harnessed_agent/api/agent_config_save.dspy" + "/harnessed_agent/api/harnessed_agent_config_create.dspy" + "/harnessed_agent/api/harnessed_agent_config_update.dspy" + "/harnessed_agent/api/harnessed_agent_config_delete.dspy" + "/harnessed_agent/harnessed_agent_config_view/add_harnessed_agent_config_view.dspy" + "/harnessed_agent/harnessed_agent_config_view/update_harnessed_agent_config_view.dspy" + "/harnessed_agent/harnessed_agent_config_view/delete_harnessed_agent_config_view.dspy" + + # harnessed_reasoning — 推理系统配置 + "/harnessed_reasoning/api/config_save.dspy" + "/harnessed_reasoning/harnessed_reasoning_config_view/add_harnessed_reasoning_config_view.dspy" + "/harnessed_reasoning/harnessed_reasoning_config_view/update_harnessed_reasoning_config_view.dspy" + "/harnessed_reasoning/harnessed_reasoning_config_view/delete_harnessed_reasoning_config_view.dspy" +) + +for p in "${ADMIN_PATHS[@]}"; do + for role in "${ADMIN_ROLES[@]}"; do + set_perm "${role}" "${p}" + done +done + +# ============================================= +# 层级 4: SUPERUSER — 系统级高危操作 +# ============================================= +echo "" +echo ">>> [4/4] Superuser: 技能部署等高危操作 (仅 owner.superuser)" + +SUPERUSER_PATHS=( + # 技能部署(可能影响全局) + "/harnessed_agent/deploy_skill.ui" + "/harnessed_agent/execute_remote_skill.ui" +) + +for p in "${SUPERUSER_PATHS[@]}"; do + for role in "${SUPERUSER_ONLY[@]}"; do + set_perm "${role}" "${p}" + done +done + +# ============================================= +# 完成 +# ============================================= +echo "" +echo "============================================" +echo " 权限配置完成,共设置 ${COUNT} 条权限" +echo "============================================" +echo "" +echo "权限摘要:" +echo " Public (any): ${#PUBLIC_FILES[@]} 个路径" +echo " Logined (所有登录用户): ${#LOGINED_PATHS[@]} 个路径 x ${#ALL_LOGINED[@]} 角色 = $((${#LOGINED_PATHS[@]} * ${#ALL_LOGINED[@]})) 条" +echo " Admin (superuser+机构管理员): ${#ADMIN_PATHS[@]} 个路径 x ${#ADMIN_ROLES[@]} 角色 = $((${#ADMIN_PATHS[@]} * ${#ADMIN_ROLES[@]})) 条" +echo " Superuser (系统级): ${#SUPERUSER_PATHS[@]} 个路径 x ${#SUPERUSER_ONLY[@]} 角色 = $((${#SUPERUSER_PATHS[@]} * ${#SUPERUSER_ONLY[@]})) 条" +echo "" +echo "角色说明:" +echo " owner.superuser — 系统级: 机构类型/角色/权限管理" +echo " *.admin — 机构级: 添加本机构人员、分配角色" +echo " reseller.operator — 运营: 产品/合同/定价/折扣/营销" +echo " reseller.sale — 销售: 客户管理/特殊折扣" +echo " reseller.accountant — 财务: 充值/对账/结算" +echo "" +echo "注意: 修改权限后需重启应用以刷新 RBAC 缓存。" diff --git a/setup_rbac_perms.sh b/setup_rbac_perms.sh new file mode 100644 index 00000000..e1822ab9 --- /dev/null +++ b/setup_rbac_perms.sh @@ -0,0 +1,274 @@ +#!/bin/bash +# setup_rbac_perms.sh +# 为 rbac 模块配置 RBAC 角色权限 +# +# 角色职责定义: +# owner.superuser — 系统级:机构类型管理、角色管理、权限管理、添加业主管理员 +# 系统初始化时由代码自动创建 +# *.admin — 机构级:添加本机构人员、分配人员角色 +# reseller.operator — 运营:产品管理、供应商合同、定价、统一折扣、营销 +# reseller.sale — 销售:客户管理、客户特殊折扣 +# reseller.accountant — 财务:线下充值、对账结算 +# reseller.maintainer — 运维维护 +# customer.customer — 终端客户用户 +# logined — 所有已登录用户 +# +# 权限分级策略(基于rbac业务功能分析): +# 1. public — 登录/注册/密码重置等认证相关,any 角色可用 +# 2. logined — 用户自助服务(个人信息、API Key管理),所有登录用户可用 +# 3. admin — 用户管理、角色分配、机构管理,仅 superuser 和机构管理员 +# 4. superuser — 系统级管理(机构类型/角色/权限/缓存刷新),仅 owner.superuser +# +# 运行位置: sage 项目根目录 (包含 set_role_perm.py 的目录) +# 用法: bash setup_rbac_perms.sh + +set -e + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +cd "$SCRIPT_DIR" + +COUNT=0 +set_perm() { + local role="$1" + local path="$2" + python set_role_perm.py "${role}" "${path}" + COUNT=$((COUNT + 1)) +} + +# 角色分组 +ALL_LOGINED=("logined" "owner.superuser" "owner.admin" "reseller.admin" "provider.admin" "customer.admin" "reseller.operator" "reseller.sale" "reseller.accountant" "reseller.maintainer" "customer.customer") +ADMIN_ROLES=("owner.superuser" "owner.admin" "reseller.admin" "provider.admin" "customer.admin") +SUPERUSER_ONLY=("owner.superuser") + +echo "============================================" +echo " rbac 模块权限初始化" +echo "============================================" + +# ============================================= +# 层级 1: PUBLIC — 登录/注册/认证 +# 任何用户(含未登录)均可访问 +# ============================================= +echo "" +echo ">>> [1/4] Public: 登录/注册/认证 (any)" + +PUBLIC_PATHS=( + # 登录页面 + "/rbac/user/login.ui" + "/rbac/userpassword_login.ui" + "/rbac/user/wechat_login.ui" + "/rbac/user/up_login.dspy" + "/rbac/userpassword_login.dspy" + "/rbac/phone_login.dspy" + # 注册 + "/rbac/user/register.ui" + "/rbac/user/register.dspy" + # 短信验证码 + "/rbac/gen_sms_code.dspy" + # 扫码 + "/rbac/qr_scan.ui" + # 用户同步 + "/rbac/usersync/index.dspy" + # 图片资源 + "/rbac/imgs/organization.svg" + "/rbac/imgs/orgtype.svg" + "/rbac/imgs/permission.svg" + "/rbac/imgs/role.svg" + "/rbac/imgs/rolepermission.svg" + "/rbac/imgs/userrole.svg" + "/rbac/imgs/users.svg" +) + +for p in "${PUBLIC_PATHS[@]}"; do + set_perm "any" "${p}" +done + +# ============================================= +# 层级 2: LOGINED — 用户自助服务 +# 所有登录用户可用 +# ============================================= +echo "" +echo ">>> [2/4] Logined: 用户自助服务 (所有登录用户)" + +LOGINED_PATHS=( + # 用户个人信息 + "/rbac/user/userinfo.ui" + "/rbac/user/user.ui" + "/rbac/user/user_panel.ui" + "/rbac/user/myrole.ui" + "/rbac/usermenu.ui" + # 登出 + "/rbac/user/logout.dspy" + # 密码重置 + "/rbac/user/reset_password/index.ui" + "/rbac/user/reset_password/reset_password.dspy" + # 角色查询(只读,用户可查看自己的角色) + "/rbac/get_normal_roles.dspy" + + # ========== User API Key CRUD(用户管理自己的API Key) ========== + "/rbac/user/userapikey/index.ui" + "/rbac/user/userapikey/get_userapikey.dspy" + "/rbac/user/userapikey/add_userapikey.dspy" + "/rbac/user/userapikey/update_userapikey.dspy" + "/rbac/user/userapikey/delete_userapikey.dspy" + "/rbac/userapp" + "/rbac/userapp/index.ui" + "/rbac/userapp/get_userapp.dspy" + "/rbac/userapp/add_userapp.dspy" + "/rbac/userapp/update_userapp.dspy" + "/rbac/userapp/delete_userapp.dspy" + + # ========== User Department CRUD(用户管理自己的部门信息) ========== + "/rbac/userdepartment" + "/rbac/userdepartment/index.ui" + "/rbac/userdepartment/get_userdepartment.dspy" + "/rbac/userdepartment/add_userdepartment.dspy" + "/rbac/userdepartment/update_userdepartment.dspy" + "/rbac/userdepartment/delete_userdepartment.dspy" + + # ========== User Role CRUD(用户角色关联,用户可查看自己的角色) ========== + "/rbac/userrole" + "/rbac/userrole/index.ui" + "/rbac/userrole/get_userrole.dspy" +) + +for p in "${LOGINED_PATHS[@]}"; do + for role in "${ALL_LOGINED[@]}"; do + set_perm "${role}" "${p}" + done +done + +# ============================================= +# 层级 3: ADMIN — 机构管理(用户/角色/机构) +# superuser + 各机构管理员 +# ============================================= +echo "" +echo ">>> [3/4] Admin: 机构管理 (superuser + 机构管理员)" + +ADMIN_PATHS=( + # ========== 添加管理员/供应商/分销商 ========== + "/rbac/add_adminuser.ui" + "/rbac/add_adminuser.dspy" + "/rbac/add_provider.ui" + "/rbac/add_provider.dspy" + "/rbac/get_provider.dspy" + "/rbac/add_reseller.dspy" + "/rbac/get_reseller.dspy" + + # ========== Users CRUD(用户管理) ========== + "/rbac/users" + "/rbac/users/index.ui" + "/rbac/users/get_users.dspy" + "/rbac/users/add_users.dspy" + "/rbac/users/update_users.dspy" + "/rbac/users/delete_users.dspy" + + # ========== Provider CRUD(供应商管理,alias=provider) ========== + "/rbac/provider" + "/rbac/provider/index.ui" + "/rbac/provider/get_provider.dspy" + "/rbac/provider/add_provider.dspy" + "/rbac/provider/update_provider.dspy" + "/rbac/provider/delete_provider.dspy" + + # ========== Reseller CRUD(分销商管理,alias=reseller) ========== + "/rbac/reseller" + "/rbac/reseller/index.ui" + "/rbac/reseller/get_reseller.dspy" + "/rbac/reseller/add_reseller.dspy" + "/rbac/reseller/update_reseller.dspy" + "/rbac/reseller/delete_reseller.dspy" + + # ========== Organization CRUD(机构管理) ========== + "/rbac/organization" + "/rbac/organization/index.ui" + "/rbac/organization/get_organization.dspy" + "/rbac/organization/add_organization.dspy" + "/rbac/organization/update_organization.dspy" + "/rbac/organization/delete_organization.dspy" + + # ========== User Role CRUD(管理员可分配角色) ========== + "/rbac/userrole/add_userrole.dspy" + "/rbac/userrole/update_userrole.dspy" + "/rbac/userrole/delete_userrole.dspy" + + # ========== 管理员菜单 ========== + "/rbac/admin_menu.ui" +) + +for p in "${ADMIN_PATHS[@]}"; do + for role in "${ADMIN_ROLES[@]}"; do + set_perm "${role}" "${p}" + done +done + +# ============================================= +# 层级 4: SUPERUSER — 系统级管理 +# 仅 owner.superuser +# ============================================= +echo "" +echo ">>> [4/4] Superuser: 系统级管理 (仅 owner.superuser)" + +SUPERUSER_PATHS=( + # 添加超级管理员(系统初始化) + "/rbac/add_superuser.dspy" + + # ========== Role CRUD(角色管理 — 系统级) ========== + "/rbac/role" + "/rbac/role/index.ui" + "/rbac/role/get_role.dspy" + "/rbac/role/add_role.dspy" + "/rbac/role/update_role.dspy" + "/rbac/role/delete_role.dspy" + + # ========== Role Permission CRUD(角色权限管理 — 系统级) ========== + "/rbac/rolepermission" + "/rbac/rolepermission/index.ui" + "/rbac/rolepermission/get_rolepermission.dspy" + "/rbac/rolepermission/add_rolepermission.dspy" + "/rbac/rolepermission/update_rolepermission.dspy" + "/rbac/rolepermission/delete_rolepermission.dspy" + + # ========== Permission CRUD(权限管理 — 系统级) ========== + "/rbac/permission" + "/rbac/permission/index.ui" + "/rbac/permission/get_permission.dspy" + "/rbac/permission/add_permission.dspy" + "/rbac/permission/update_permission.dspy" + "/rbac/permission/delete_permission.dspy" + + # ========== Org Types CRUD(机构类型管理 — 系统级) ========== + "/rbac/orgtypes" + "/rbac/orgtypes/index.ui" + "/rbac/orgtypes/get_orgtypes.dspy" + "/rbac/orgtypes/add_orgtypes.dspy" + "/rbac/orgtypes/update_orgtypes.dspy" + "/rbac/orgtypes/delete_orgtypes.dspy" + + # 刷新权限缓存(系统级操作) + "/rbac/refresh_userperm.dspy" + + # 获取所有角色(含系统级角色) + "/rbac/get_all_roles.dspy" +) + +for p in "${SUPERUSER_PATHS[@]}"; do + for role in "${SUPERUSER_ONLY[@]}"; do + set_perm "${role}" "${p}" + done +done + +# ============================================= +# 完成 +# ============================================= +echo "" +echo "============================================" +echo " 权限配置完成,共设置 ${COUNT} 条权限" +echo "============================================" +echo "" +echo "权限摘要:" +echo " Public (any): ${#PUBLIC_PATHS[@]} 个路径 x 1 角色 = ${#PUBLIC_PATHS[@]} 条" +echo " Logined (所有登录用户): ${#LOGINED_PATHS[@]} 个路径 x ${#ALL_LOGINED[@]} 角色 = $((${#LOGINED_PATHS[@]} * ${#ALL_LOGINED[@]})) 条" +echo " Admin (superuser+机构管理员): ${#ADMIN_PATHS[@]} 个路径 x ${#ADMIN_ROLES[@]} 角色 = $((${#ADMIN_PATHS[@]} * ${#ADMIN_ROLES[@]})) 条" +echo " Superuser (系统级): ${#SUPERUSER_PATHS[@]} 个路径 x ${#SUPERUSER_ONLY[@]} 角色 = $((${#SUPERUSER_PATHS[@]} * ${#SUPERUSER_ONLY[@]})) 条" +echo "" +echo "注意: 修改权限后需重启应用以刷新 RBAC 缓存。" diff --git a/wwwroot/API.md b/wwwroot/API.md index 306df9af..452dcca3 100644 --- a/wwwroot/API.md +++ b/wwwroot/API.md @@ -109,6 +109,90 @@ } } ``` +## 下游APIkey + +### 获得apikey list +* path /dapi/downapps.dspy +* method GET +* return +``` + { + "status": "ok", + "data": { + "apikeys": [ + { + "id": # 应用id + "appname": # 应用名 + } + ] + } + } + or + { + "status": "error", + "data": { + "message": # 出错信息 + } + } +``` +### 申请APIkey +* path /dapi/apply_apikey.dspy +* method POST +* headers +``` +{ + "Content-Type": "application/json" +} +``` +* data +``` +{ + "appname": # 必须 + "description": # 可选 +} +``` +* return +``` + { + "status": "ok" + } + or + { + "status": "error", + "data": { + "message": 出错信息 + } + } +``` + +### 查看AKIKEY +* path /dapi/get_apikey.dspy +* method GET +* params +``` +{ + "id": # "获得apikey list" 返回到id +} +``` +* return +``` + { + "status": "ok", + "data": { + "appname": # app名称 + "aapikey": # apikey + "secretkey": # 加密key + } + } + or + { + "status": "error", + "data": { + "message": # 出错信息 + } + } +``` + ## 账户管理 ### 查询账户余额 @@ -324,3 +408,83 @@ d = { "response": # 后台返回信息,有状态,错误信息或videod url } } + +## 测试定价项目 +* path /pricing/test_pricing_program.dspy +* method POST +* params +* data +``` +{ + "ppid": #定价项目id + "data": # 模型返回的usage的字典数据 +} +``` +return +计价成功 +``` +{ + "status": "ok", + "data": { + "ppid": ppid, + "data": data, + "result": x + } +} +``` +或 +``` +{ + "status": "error", + "data": { + "message": # 错误信息 + } +} +``` +## 获取模型类型列表 +* path /llmage/list_llmcatelogs +* method GET +* params 无 +* return +``` +{ + id + name +} +``` + +## 获得模型列表 +* path /llmage/list_llms +* method GET +* params +``` +{ + lctype # 模型类型, 缺省较为全部 + orderby # 排序列, 缺省为privoderid +} +``` +* return +``` +[ + # 模型信息 + { + "id": "_hsqebBHzmTPrKKL1lTkK", + "name": "千问3-235B-Thinking-2507", + "model": "qwen3-235b-a22b-thinking-2507", + "description": "通义千问3-235B-A22B-Thinking-2507,基于Qwen3的思考模式开源模型,相较上一版本(通义千问3-235B-A22B)逻辑能力、通用能力、知识增强及创作能力均有大幅提升,适用于高难度强推理场景。", + "llmcatelogid": "text2text", + "iconid": "qwen", + "upappid": "ali-qwen", + "apiname": "t2t", + "providerid": "6fadgewjraOyvxC_EkHou", + "ownerid": "0", + "enabled_date": "2025-09-04", + "expired_date": "9999-12-31", + "query_apiname": "", + "query_period": null, + "ppid": "4S3nNFQu_tkmqPJxD8gg4", + "catelogname": "文生文", + "catelog_id": "text2text" + } +] +``` diff --git a/wwwroot/check_rf.dspy b/wwwroot/check_rf.dspy new file mode 100644 index 00000000..ca088466 --- /dev/null +++ b/wwwroot/check_rf.dspy @@ -0,0 +1,17 @@ +import json +from appPublic.registerfunction import RegisterFunction +from appPublic.log import debug + +rf = RegisterFunction() +funcs = list(rf.registKW.keys()) +debug(f'check_rf: Registered functions: {funcs}') + +# Try to call password directly +pw_func = rf.get('password') +debug(f'check_rf: password function = {pw_func}') + +result = { + 'functions': funcs, + 'has_password': pw_func is not None +} +return json.dumps(result, ensure_ascii=False) diff --git a/wwwroot/docs/api_doc.ui b/wwwroot/docs/api_doc.ui new file mode 100644 index 00000000..f6c82f41 --- /dev/null +++ b/wwwroot/docs/api_doc.ui @@ -0,0 +1,8 @@ +{% set lang = params_kw._lang or 'zh' %} +{ + "widgettype": "ApiDoc", + "options": { + "md_url": "{{entire_url('/docs/api_doc_' + lang + '.md')}}", + "height": "100%" + } +} diff --git a/wwwroot/docs/api_doc_en.md b/wwwroot/docs/api_doc_en.md new file mode 100644 index 00000000..cfb512fe --- /dev/null +++ b/wwwroot/docs/api_doc_en.md @@ -0,0 +1,142 @@ +# Yuanjing API Documentation + +--- + +## LLM API + +Base url: `https://token.opencomputing.cn/llmage/v1` + +All endpoints require Bearer Token authentication. + +--- + +## POST /v1/chat/completions + +Text generation endpoint, OpenAI-compatible. + +### Required Parameters + +| Parameter | Type | Description | +|-----------|------|-------------| +| `model` | string | Model name, e.g. `"qwen3-max"` | +| `messages` or `prompt` | array / string | Conversation messages or text prompt | + +### Optional Parameters + +| Parameter | Type | Description | +|-----------|------|-------------| +| `catelogid` | string | Catalog type ID, default `"t2t"`, Chinese names supported | +| `stream` | boolean | Enable streaming output | +| `off_peak` | boolean | Use off-peak pricing | +| `transno` | string | Transaction ID (auto-generated if omitted) | + +### Example Request + +```json +{ + "model": "qwen3-max", + "messages": [ + {"role": "user", "content": "Hello"} + ], + "stream": false +} +``` + +```bash +# Non-streaming +curl -X POST 'https://token.opencomputing.cn/llmage/v1/chat/completions' \\n -H 'Authorization: Bearer ***' \\n -H 'Content-Type: application/json' \\n -d '{\\n \"model\": \"qwen3-max\",\\n \"messages\": [{\"role\": \"user\", \"content\": \"Hello, introduce yourself\"}],\\n \"stream\": false\\n }' + +# Streaming +curl -X POST 'https://token.opencomputing.cn/llmage/v1/chat/completions' \\n -H 'Authorization: Bearer ***' \\n -H 'Content-Type: application/json' \\n -d '{\\n \"model\": \"qwen3-max\",\\n \"messages\": [{\"role\": \"user\", \"content\": \"Write a poem about spring\"}],\\n \"stream\": true\\n }' +``` + +### Response Format + +**Non-streaming:** + +```json +{ + "id": "luid_xxx", + "object": "chat.completion", + "model": "qwen3-max", + "choices": [{ + "index": 0, + "message": {"role": "assistant", "content": "Hi there!"}, + "finish_reason": "stop" + }], + "usage": {"prompt_tokens": 10, "completion_tokens": 5, "total_tokens": 15} +} +``` + +**Streaming (SSE):** + +``` +data: {"choices": [{"delta": {"content": "Hi"}, "index": 0}]} +data: {"choices": [{"delta": {"content": " there!"}, "index": 0}]} +data: [DONE] +``` + +### Error Responses + +| Status | Description | +|--------|-------------| +| 400 | Missing required parameters or model not found | +| 403 | Not authenticated | +| 429 | Insufficient account balance | + +--- + +## POST /v1/video/generations + +Video generation endpoint. + +### Required Parameters + +| Parameter | Type | Description | +|-----------|------|-------------| +| `model` | string | Model name, e.g. `"keling-2.1"` | +| `catelogid` | string | Catalog type: `"t2v"` / `"i2v"` / `"r2v"` | +| `prompt` | string | Generation prompt | + +### Optional Parameters + +| Parameter | Type | Description | +|-----------|------|-------------| +| `image_url` | string | Reference image URL for I2V | +| `duration` | string | Video duration, e.g. `"5s"` | +| `resolution` | string | Resolution, e.g. `"1080p"` | +| `n` | integer | Number of generations | +| `transno` | string | Transaction ID | + +### Example Request + +```json +{ + "model": "keling-2.1", + "catelogid": "t2v", + "prompt": "A beautiful sunset over the ocean", + "duration": "5s", + "resolution": "1080p" +} +``` + +### Response Format + +Video generation is typically async: + +```json +{ + "id": "luid_xxx", + "object": "video.generation", + "model": "keling-2.1", + "status": "submitted", + "taskid": "task_xxx", + "created": 1716912000 +} +``` + +Query task status via `/v1/tasks?taskid=xxx`. + +--- + +For detailed model-specific parameters (Vidu, Seedance, Wan, Kling, Hailuo, HappyHorse), see the [Chinese documentation](/docs/api_doc_zh.md). diff --git a/wwwroot/docs/api_doc_zh.md b/wwwroot/docs/api_doc_zh.md new file mode 100644 index 00000000..f912dd1b --- /dev/null +++ b/wwwroot/docs/api_doc_zh.md @@ -0,0 +1,2408 @@ +# 元境API 文档 + +--- + +# 大模型 API + +Base url: `https://token.opencomputing.cn/llmage/v1` + +所有 API 端点需要 Bearer Token 认证 + +--- + +## POST /v1/chat/completions + +文本生成接口,兼容 OpenAI 格式。 + +### 必填参数 + +| 参数 | 类型 | 说明 | +|------|------|------| +| `model` | string | 模型名称,如 `"qwen3-max"` | +| `messages` 或 `prompt` | array / string | 对话消息数组或文本提示 | + +### 可选参数 + +| 参数 | 类型 | 说明 | +|------|------|------| +| `catelogid` | string | 目录类型ID,默认 `"t2t"`,也支持中文名(向后兼容) | +| `stream` | boolean | 是否启用流式输出 | +| `off_peak` | boolean | 是否使用非高峰时段 | +| `transno` | string | 交易流水号(不传则自动生成) | + +### 请求示例 + +```json +{ + "model": "qwen3-max", + "messages": [ + {"role": "user", "content": "Hello"} + ], + "stream": false +} +``` + +```bash +# 非流式 +curl -X POST 'https://token.opencomputing.cn/llmage/v1/chat/completions' \ + -H 'Authorization: Bearer ***' \ + -H 'Content-Type: application/json' \ + -d '{ + "model": "qwen3-max", + "messages": [{"role": "user", "content": "你好,请介绍你自己"}], + "stream": false + }' + +# 流式 +curl -X POST 'https://token.opencomputing.cn/llmage/v1/chat/completions' \ + -H 'Authorization: Bearer ***' \ + -H 'Content-Type: application/json' \ + -d '{ + "model": "qwen3-max", + "messages": [{"role": "user", "content": "写一首关于春天的诗"}], + "stream": true + }' +``` + +### 响应格式 + +**非流式响应:** + +```json +{ + "id": "luid_xxx", + "object": "chat.completion", + "model": "qwen3-max", + "choices": [{ + "index": 0, + "message": {"role": "assistant", "content": "Hi there!"}, + "finish_reason": "stop" + }], + "usage": {"prompt_tokens": 10, "completion_tokens": 5, "total_tokens": 15} +} +``` + +**流式响应 (SSE):** + +``` +data: {"choices": [{"delta": {"content": "Hi"}, "index": 0}]} +data: {"choices": [{"delta": {"content": " there!"}, "index": 0}]} +data: [DONE] +``` + +### 错误响应 + +| 状态码 | 说明 | +|--------|------| +| 400 | 缺少必填参数或模型不存在 | +| 403 | 未登录 | +| 429 | 账户余额不足 | + +--- + +## POST /v1/video/generations + +视频生成接口。 + +### 必填参数 + +| 参数 | 类型 | 说明 | +|------|------|------| +| `model` | string | 模型名称,如 `"keling-2.1"` | +| `catelogid` | string | 目录类型ID,如 `"t2v"` / `"i2v"` / `"r2v"` | +| `prompt` | string | 生成提示词 | + +### 可选参数 + +| 参数 | 类型 | 说明 | +|------|------|------| +| `image_url` | string | 图生视频时提供参考图 URL | +| `duration` | string | 视频时长,如 `"5s"` | +| `resolution` | string | 分辨率,如 `"1080p"` | +| `n` | integer | 生成数量 | +| `transno` | string | 交易流水号 | + +### 请求示例 + +```json +{ + "model": "keling-2.1", + "catelogid": "t2v", + "prompt": "A beautiful sunset over the ocean", + "duration": "5s", + "resolution": "1080p" +} +``` + +### 响应格式 + +视频生成通常为异步任务,提交后返回任务信息: + +```json +{ + "id": "luid_xxx", + "object": "video.generation", + "model": "keling-2.1", + "status": "submitted", + "taskid": "task_xxx", + "created": 1716912000 +} +``` + +通过 `/v1/tasks?taskid=xxx` 查询任务状态。 + +### curl 测试用例 + +```bash +# ---- Vidu T2V 文生视频 ---- +curl -X POST 'https://token.opencomputing.cn/llmage/v1/video/generations' \ + -H 'Authorization: Bearer *** \ + -H 'Content-Type: application/json' \ + -d '{ + "model": "viduq3-pro", + "catelogid": "t2v", + "prompt": "一只猫在草地上奔跑", + "duration": 5, + "ratio": "16:9", + "resolution": "720p" + }' + +# ---- Vidu I2V 图生视频 ---- +curl -X POST 'https://token.opencomputing.cn/llmage/v1/video/generations' \ + -H 'Authorization: Bearer *** \ + -H 'Content-Type: application/json' \ + -d '{ + "model": "viduq3-pro", + "catelogid": "i2v", + "prompt": "画面中的人物微笑挥手", + "image_file": "https://example.com/first_frame.jpg", + "duration": 5, + "ratio": "16:9" + }' + +# ---- Vidu Ref2V 参考生视频(主体模式) ---- +curl -X POST 'https://token.opencomputing.cn/llmage/v1/video/generations' \ + -H 'Authorization: Bearer *** \ + -H 'Content-Type: application/json' \ + -d '{ + "model": "viduq3-pro", + "catelogid": "r2v", + "prompt": "一个女孩在海边跳舞", + "subjects": [ + {"images": ["https://example.com/character.jpg"]} + ], + "duration": 5, + "aspect_ratio": "16:9" + }' + +# ---- Seedance T2V 文生视频 ---- +curl -X POST 'https://token.opencomputing.cn/llmage/v1/video/generations' \ + -H 'Authorization: Bearer *** \ + -H 'Content-Type: application/json' \ + -d '{ + "model": "doubao-seedance-2-0-260128", + "catelogid": "t2v", + "prompt": "一杯咖啡冒着热气,阳光从窗外洒入", + "resolution": "720p", + "duration": 8, + "ratio": "16:9" + }' + +# ---- Seedance TI2V 文图生视频 ---- +curl -X POST 'https://token.opencomputing.cn/llmage/v1/video/generations' \ + -H 'Authorization: Bearer *** \ + -H 'Content-Type: application/json' \ + -d '{ + "model": "doubao-seedance-2-0-260128", + "catelogid": "i2v", + "prompt": "画面中的汽车缓缓启动驶向远方", + "image1_file": "https://example.com/car.jpg", + "resolution": "720p", + "duration": 8 + }' + +# ---- Seedance R2V 多模态参考生视频 ---- +curl -X POST 'https://token.opencomputing.cn/llmage/v1/video/generations' \ + -H "Authorization: Bearer *** \ + -F "model=doubao-seedance-2-0-260128" \ + -F "catelogid=r2v" \ + -F "prompt=第一优先级:人物主体形象严格参考@图1。第二优先级:学习机产品外观严格参考@图2。第三优先级:门店背景空间严格参考@图3。视频主角只有一人,为@图1中的女性人物。人物外貌、脸型、五官、发型、气质、服装必须与@图1保持一致。保持知性温婉、干净利落的女性形象。服装为浅蓝色短袖针织上衣、米白色半身长裙、白色浅口单鞋。人物始终位于画面中心,主体占画面面积60%以上,面部清晰锐利。人物手持学习机,外观严格参考@图2。必须保持白色边框机身、橙色支架、底部笔槽结构、屏幕正面朝向镜头。不允许替换成其他电子设备。不允许产品变形、悬空、缺角、穿模。背景场景严格参考@图3,保持作业帮门店的橙红色主背景墙、100标识、暖白灯光和真实展示空间氛围。背景只作为场景识别与空间陪衬,不允许喧宾夺主,不要求生成清晰可读文字,不允许复杂宣传文案抢镜。镜头为竖屏中近景,人物自然站立面对镜头,轻微微笑,稳定展示学习机。双手或单手自然托持学习机,动作轻柔克制。整体为写实高清商业宣传短视频风格,画面明亮,人物皮肤自然通透,产品结构准确。禁止字幕、文字叠加、花字、水印。禁止出现第二个主要人物。禁止人物换脸、换装、肢体错误。禁止学习机外观错误、产品漂浮、手穿模。" \ + -F "ratio=9:16" \ + -F "resolution=1080p" \ + -F "duration=5" \ + -F "image_files=asset://asset-20260617135652-dczbp" \ + -F "image_files=asset://asset-20260617135840-ljmv9" \ + -F "image_files=asset://asset-20260617135924-s69z8" + +# ---- 通义万象 T2V 文生视频 ---- +curl -X POST 'https://token.opencomputing.cn/llmage/v1/video/generations' \ + -H 'Authorization: Bearer *** \ + -H 'Content-Type: application/json' \ + -d '{ + "model": "wan2.6-t2v", + "catelogid": "t2v", + "prompt": "一条金鱼在清澈的水中游动", + "size": "1920*1080", + "duration": "5" + }' + +# ---- 通义万象 I2V 图生视频 ---- +curl -X POST 'https://token.opencomputing.cn/llmage/v1/video/generations' \ + -H 'Authorization: Bearer *** \ + -H 'Content-Type: application/json' \ + -d '{ + "model": "wan2.6-i2v", + "catelogid": "i2v", + "prompt": "画面中的花朵慢慢绽放", + "image_file": "https://example.com/flower.jpg", + "size": "1920*1080" + }' + +# ---- 通义万象 Ref2V 角色参考生视频 ---- +curl -X POST 'https://token.opencomputing.cn/llmage/v1/video/generations' \ + -H 'Authorization: Bearer *** \ + -H 'Content-Type: application/json' \ + -d '{ + "model": "wan2.6-r2v", + "catelogid": "r2v", + "prompt": "角色在公园中散步", + "video1_file": "https://example.com/character_video.mp4", + "size": "1920*1080", + "duration": "10" + }' + +# ---- 可灵 T2V 文生视频 ---- +curl -X POST 'https://token.opencomputing.cn/llmage/v1/video/generations' \ + -H 'Authorization: Bearer *** \ + -H 'Content-Type: application/json' \ + -d '{ + "model": "kling-v2-1-master", + "catelogid": "t2v", + "prompt": "夕阳下的海滩,海浪拍打礁石" + }' + +# ---- 海螺 TI2V 图生视频 ---- +curl -X POST 'https://token.opencomputing.cn/llmage/v1/video/generations' \ + -H 'Authorization: Bearer *** \ + -H 'Content-Type: application/json' \ + -d '{ + "model": "hailuo", + "catelogid": "i2v", + "prompt": "画面中的孩子开心地跑向镜头", + "image_file": "https://example.com/child.jpg", + "resolution": "768P", + "duration": 6 + }' + +# ---- 快乐马 T2V 文生视频 ---- +curl -X POST 'https://token.opencomputing.cn/llmage/v1/video/generations' \ + -H 'Authorization: Bearer *** \ + -H 'Content-Type: application/json' \ + -d '{ + "model": "happyhorse-1.0-t2v", + "catelogid": "t2v", + "prompt": "一匹骏马在草原上奔驰", + "size": "1920*1080", + "duration": "5" + }' +``` + +### 各模型输入参数明细 + +> 以下为各平台/模型的具体输入参数。调用时通过 `model` + `catelogid` 自动路由到对应供应商。 + +--- + +#### Vidu 平台 + +##### T2V - 文生视频 + +| 参数名 | 类型 | 必填 | 默认值 | 说明 | 可选值 | +|--------|------|------|--------|------|--------| +| `model` | string | 是 | `viduq3-pro` | 模型名称 | `viduq3-turbo`, `viduq3-pro` | +| `prompt` | string | 是 | - | 提示词 | - | +| `off_peak` | string | 否 | `N` | 错峰执行 | `Y`, `N` | +| `duration` | integer | 否 | `10` | 视频长度(1-16秒) | 1-16 | +| `ratio` | string | 否 | `16:9` | 长宽比 | `16:9`, `9:16`, `4:3`, `3:4`, `1:1` | +| `resolution` | string | 否 | `1080p` | 分辨率 | `540p`, `720p`, `1080p` | + +##### I2V - 图生视频 + +| 参数名 | 类型 | 必填 | 默认值 | 说明 | 可选值 | +|--------|------|------|--------|------|--------| +| `model` | string | 是 | `viduq3-pro` | 模型名称 | `viduq3-pro`, `viduq3-turbo` | +| `prompt` | string | 是 | - | 提示词 | - | +| `image_file` | image | 是 | - | 首帧图片 | - | +| `off_peak` | string | 否 | `N` | 错峰执行 | `Y`, `N` | +| `duration` | integer | 否 | `10` | 视频长度(1-16秒) | 1-16 | +| `ratio` | string | 否 | `16:9` | 长宽比 | `16:9`, `9:16`, `4:3`, `3:4`, `1:1` | +| `resolution` | string | 否 | `1080p` | 分辨率 | `540p`, `720p`, `1080p` | + +##### 2I2V - 首尾帧生视频 + +| 参数名 | 类型 | 必填 | 默认值 | 说明 | +|--------|------|------|--------|------| +| `model` | string | 否 | `viduq2` | 模型名称 | +| `payload` | string | 是 | `2i2v` | 固定值 | +| `off_peak` | boolean | 否 | `false` | 错峰模式 | +| `images` | array | 是 | - | 两张图片URL `[首帧, 尾帧]` | +| `duration` | integer | 否 | `10` | 视频时长 | +| `prompt` | string | 是 | - | 提示词 | +| `audio` | boolean | 否 | `true` | 音频直出 | +| `seed` | integer | 否 | `12345` | 随机种子 | +| `aspect_ratio` | string | 否 | `16:9` | 画面比例 | +| `resolution` | string | 否 | `1080p` | 分辨率 | + +##### Ref2V - 参考生视频 v2(主体模式) + +> 使用主体(图片/视频/文字)生成视频,支持 viduq3-turbo/q3/q2-pro/q2/q1/2.0 + +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| `model` | string | 是 | 模型名称 | +| `subjects` | array | 是 | 主体列表(最多7个图片/文字主体,每个主体最多3张图) | +| `prompt` | string | 是 | 提示词 | +| `audio` | boolean | 否 | 音视频直出 | +| `audio_type` | string | 否 | 音频类型 | +| `duration` | integer | 否 | 视频时长 | +| `seed` | integer | 否 | 随机种子 | +| `aspect_ratio` | string | 否 | 画面比例 | +| `resolution` | string | 否 | 分辨率 | +| `movement_amplitude` | string | 否 | 运动幅度 | +| `off_peak` | boolean | 否 | 错峰模式 | +| `auto_subjects` | boolean | 否 | 智能主体 | + +##### Ref2V - 参考生视频 v2(非主体模式) + +> 直接上传图片参考生成视频,支持 viduq3-mix/q3-turbo/q3/q2-pro/q2/q1/2.0 + +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| `model` | string | 是 | 模型名称 | +| `images` | array | 是 | 参考图片URL列表(1-7张) | +| `videos` | array | 否 | 参考视频URL列表(仅viduq2-pro) | +| `prompt` | string | 是 | 提示词 | +| `audio` | boolean | 否 | 音视频直出 | +| `bgm` | boolean | 否 | 背景音乐 | +| `duration` | integer | 否 | 视频时长 | +| `seed` | integer | 否 | 随机种子 | +| `aspect_ratio` | string | 否 | 画面比例 | +| `resolution` | string | 否 | 分辨率 | +| `off_peak` | boolean | 否 | 错峰模式 | + +##### Ref2V - 参考生视频 v1 + +| 参数名 | 类型 | 必填 | 默认值 | 说明 | 可选值 | +|--------|------|------|--------|------|--------| +| `model` | string | 是 | `viduq2-pro` | 模型名称 | `viduq2`, `viduq1`, `vidu2.0` | +| `prompt` | string | 是 | - | 提示词 | - | +| `off_peak` | string | 否 | `N` | 错峰执行 | `Y`, `N` | +| `duration` | integer | 否 | `10` | 视频长度 | - | +| `ratio` | string | 否 | `16:9` | 长宽比 | `16:9`, `9:16`, `4:3`, `3:4`, `1:1` | +| `resolution` | string | 否 | `1080p` | 分辨率 | `540p`, `720p`, `1080p` | + +--- + +#### Seedance 平台(火山方舟)— Seedance 2.0 + +> 上游 API: `POST https://ark.cn-beijing.volces.com/api/v3/contents/generations/tasks` +> SDK: `pip install 'volcengine-python-sdk[ark]'` +> 开通条件: 账户余额 >= 200元 或已购资源包 +> 任务ID仅保存7天,视频URL 24小时有效 + +##### 模型列表 + +| 模型 | Model ID | 1080p | 有声视频 | 联网搜索 | +|------|----------|-------|----------|----------| +| Seedance 2.0 | `doubao-seedance-2-0-260128` | ✅ | ✅ | ✅ | +| Seedance 2.0 Fast | `doubao-seedance-2-0-fast-260128` | ❌ | ✅ | ✅ | + +##### T2V - 文生视频 + +| 参数名 | 类型 | 必填 | 默认值 | 说明 | 可选值 | +|--------|------|------|--------|------|--------| +| `model` | string | 是 | `doubao-seedance-2-0-260128` | 模型名称 | `doubao-seedance-2-0-260128`, `doubao-seedance-2-0-fast-260128` | +| `prompt` | string | 是 | - | 提示词(中文<=500字,英文<=1000词) | - | +| `resolution` | string | 否 | `720p` | 分辨率 | `480p`, `720p`, `1080p`(Fast不支持) | +| `duration` | integer | 否 | `5` | 视频长度[4,15]秒, 或-1自动选择 | 4-15, -1 | +| `ratio` | string | 否 | `adaptive` | 宽高比 | `16:9`, `4:3`, `1:1`, `3:4`, `9:16`, `21:9`, `adaptive` | +| `generate_audio` | boolean | 否 | `true` | 是否生成同步音效(人声+音效+BGM) | `true`, `false` | +| `watermark` | boolean | 否 | `false` | 是否含AI生成水印 | `true`, `false` | +| `return_last_frame` | boolean | 否 | `false` | 返回尾帧图片(用于连续视频拼接) | `true`, `false` | +| `priority` | integer | 否 | `0` | 执行优先级(0-9,越大越优先) | 0-9 | +| `tools` | array | 否 | - | 联网搜索 `[{"type":"web_search"}]` | `web_search` | + +##### TI2V - 首帧/首尾帧生视频 + +| 参数名 | 类型 | 必填 | 默认值 | 说明 | 可选值 | +|--------|------|------|--------|------|--------| +| `model` | string | 是 | `doubao-seedance-2-0-260128` | 模型名称 | 同上 | +| `prompt` | string | 是 | - | 提示词 | - | +| `image1_file` | image | 是 | - | 首帧图片(role=first_frame) | - | +| `image2_file` | image | 否 | - | 尾帧图片(role=last_frame) | - | +| `resolution` | string | 否 | `720p` | 分辨率 | `480p`, `720p`, `1080p` | +| `duration` | integer | 否 | `5` | 视频长度[4,15]秒 | 4-15, -1 | +| `ratio` | string | 否 | `adaptive` | 宽高比(adaptive时以首帧为准) | 同上 | + +> 首尾帧图片宽高比不一致时,以首帧为准,尾帧自动裁剪适配。 + +##### Ref2V - 多模态参考生视频(Seedance 2.0 核心能力) + +传入参考图片(1-9张) + 参考视频(1-3个) + 参考音频,基于素材+提示词生成视频。 + +| 参数名 | 类型 | 必填 | 默认值 | 说明 | +|--------|------|------|--------|------| +| `model` | string | 是 | `doubao-seedance-2-0-260128` | 模型名称 | +| `prompt` | string | 是 | - | 提示词,用"图片1""视频1""音频1"指代素材 | +| `image_files` | array | 否 | - | 参考图片URL列表(1-9张), role=reference_image | +| `video_files` | array | 否 | - | 参考视频URL列表(1-3个,总时长<=15s), role=reference_video | +| `audio_files` | array | 否 | - | 参考音频URL列表, role=reference_audio(须搭配图/视频) | +| `resolution` | string | 否 | `720p` | 分辨率 | +| `duration` | integer | 否 | `5` | 视频长度[4,15]秒 | 4-15, -1 | +| `ratio` | string | 否 | `adaptive` | 宽高比 | +| `generate_audio` | boolean | 否 | `true` | 是否生成同步音效 | + +> **三种图片场景互斥不可混用**: 首帧(first_frame) / 首尾帧(first_frame+last_frame) / 参考图(reference_image) +> **音频不可单独传入**: 须至少包含1个参考视频或图片。 +> **人脸限制**: 不支持直接上传含真人人脸的参考图/视频。可用模型生成的含人脸产物、预置虚拟人像(asset://ID)、或已授权真人素材。 + +##### 输入素材规格 + +| 类型 | 格式 | 限制 | +|------|------|------| +| 图片 | jpeg/png/webp/bmp/tiff/gif/heic/heif | 宽高比(0.4,2.5), 宽高300-6000px, <30MB | +| 视频 | mp4/mov (H.264/H.265+AAC/MP3) | 480p/720p/1080p, 时长2-15s, <50MB, FPS 24-60 | +| 音频 | mp3/wav/aac | 不可单独传入,须搭配图/视频 | + +> 图片URL支持三种格式: 公网URL / Base64(`data:image/png;base64,...`) / 素材ID(`asset://ASSET_ID`) + +##### 输出视频像素表 (Seedance 2.0) + +| 分辨率 | 16:9 | 4:3 | 1:1 | 3:4 | 9:16 | 21:9 | +|--------|------|-----|-----|-----|------|------| +| 480p | 864×496 | 752×560 | 640×640 | 560×752 | 496×864 | 992×432 | +| 720p | 1280×720 | 1112×834 | 960×960 | 834×1112 | 720×1280 | 1470×630 | +| 1080p | 1920×1080 | 1664×1248 | 1440×1440 | 1248×1664 | 1080×1920 | 2206×946 | + +##### Ref2V 提示词写法 + +用"图片1/2""视频1""音频1"指代素材,按时间轴描述场景: + +``` +全程使用视频1的第一视角构图,全程使用音频1作为背景音乐。 +第一人称视角果茶宣传广告;首帧为图片1,你的手摘下一颗带晨露的苹果, +轻脆的碰撞声;2-4秒:快速切镜,将苹果块投入雪克杯,加入冰块与茶底, +用力摇晃;4-6秒:成品特写,分层果茶倒入透明杯; +6-8秒:手持举杯,将图片2中的果茶举到镜头前,尾帧定格为图片2。 +背景声音统一为女生音色。 +``` + +> 对话内容用双引号包裹可优化音频生成效果。 + +--- + +#### 通义万象(DashScope) + +##### T2V - 文生视频 + +| 参数名 | 类型 | 必填 | 默认值 | 说明 | +|--------|------|------|--------|------| +| `model` | string | 是 | - | 模型名称(如 `wan2.6-t2v`) | +| `prompt` | string | 是 | - | 提示词 | +| `negative_prompt` | string | 否 | - | 反向提示词 | +| `audio_file` | audio | 否 | - | 配音文件 | +| `size` | string | 否 | `1920*1080` | 视频尺寸 | +| `duration` | string | 否 | `15` | 视频时长 | + +**size 可选值:** `832*480`, `480*832`, `624*624`, `1280*720`, `720*1280`, `960*960`, `1088*832`, `832*1088`, `1920*1080`, `1080*1920`, `1440*1440`, `1632*1248`, `1248*1632` + +**duration 可选值:** `5`, `10`, `15` + +##### I2V - 图生视频 + +可用模型:`wan2.6-i2v`, `wan2.6-i2v-flash` + +> 输入参数与 T2V 类似,额外需要首帧图片。 + +##### 2I2V - 首尾帧生视频 + +| 参数名 | 类型 | 必填 | 默认值 | 说明 | +|--------|------|------|--------|------| +| `model` | string | 是 | - | 模型名称 | +| `prompt` | string | 是 | - | 提示词 | +| `negative_prompt` | string | 否 | - | 反向提示词 | +| `image1_file` | image | 是 | - | 首帧图片 | +| `image2_file` | image | 是 | - | 尾帧图片 | +| `resolution` | string | 否 | `1080P` | 分辨率 | +| `duration` | integer | - | `5` | 固定5秒 | + +##### Ref2V - 角色参考生视频 + +> 参考输入视频中的角色形象和音色,搭配提示词生成保持角色一致性的视频。可以输入1-3个人物视频,每个视频一个角色。 + +| 参数名 | 类型 | 必填 | 默认值 | 说明 | +|--------|------|------|--------|------| +| `model` | string | 是 | - | 模型名称(如 `wan2.6-r2v`) | +| `prompt` | string | 是 | - | 提示词 | +| `video1_file` | video | 是 | - | 角色一视频 | +| `video2_file` | video | 否 | - | 角色二视频 | +| `video3_file` | video | 否 | - | 角色三视频 | +| `size` | string | 否 | `1920*1080` | 视频尺寸 | +| `duration` | string | 否 | `10` | 视频时长 | + +**size 可选值:** 同 T2V + +**duration 可选值:** `10`, `15` + +##### IA2V - 图像音频生视频 + +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| `image_file` | image | 是 | 图像 | +| `audio_file` | audio | 是 | 音频 | + +--- + +#### 可灵(Kling) + +##### T2V - 文生视频 + +| 参数名 | 类型 | 必填 | 默认值 | 说明 | 可选值 | +|--------|------|------|--------|------|--------| +| `model` | string | 是 | - | 模型名称 | `kling-v2-1-master`, `kling-v2-master`, `kling-v1-6`, `kling-v1` | +| `prompt` | string | 是 | - | 提示词 | - | +| `negative_prompt` | string | 否 | - | 反向提示词 | - | + +--- + +#### 海螺(Hailuo/MiniMax) + +##### TI2V - 图生视频 + +| 参数名 | 类型 | 必填 | 默认值 | 说明 | 可选值 | +|--------|------|------|--------|------|--------| +| `prompt` | string | 是 | - | 提示词 | - | +| `image_file` | image | 否 | - | 首帧图片 | - | +| `image_file1` | image | 否 | - | 尾帧图片 | - | +| `resolution` | string | 否 | `768P` | 尺寸 | `768P`, `1080P` | +| `duration` | integer | 否 | `6` | 视频长度 | `6`(6秒), `10`(10秒) | + +--- + +#### 快乐马(HappyHorse) + +> 基于通义万象平台(tongyi-wan),输入参数与通义万象对应类型一致。 + +##### T2V - 文生视频 + +输入参数同通义万象 T2V。可用模型:`happyhorse-1.0-t2v` + +##### I2V - 图生视频 + +输入参数同通义万象 I2V。可用模型:`happyhorse-1.0-i2v` + +> **注意:** 图片参数名为 `image_file`(非 `image_url`),传入图片 URL。 + +##### Ref2V - 参考生视频 + +输入参数同通义万象 Ref2V,额外支持: + +| 参数名 | 说明 | +|--------|------| +| `resolution` | 可选 `1080P`(默认), `720P` | +| `ratio` | 可选 `16:9`(默认), `9:16`, `3:4`, `4:3` | + +可用模型:`happyhorse-1.0-r2v`(参考图像数量1-9张,支持多角色参考) + +--- + +## POST /v1/image/generations + +图像生成接口。 + +### 必填参数 + +| 参数 | 类型 | 说明 | +|------|------|------| +| `model` | string | 模型名称,如 `"qwen-image-2.0-pro"` | +| `catelogid` | string | 目录类型ID,文生图固定为 `"t2i"` | +| `prompt` | string | 生成提示词 | + +### 可选参数 + +| 参数 | 类型 | 说明 | +|------|------|------| +| `image_url` | string | 图生图时提供参考图 URL | +| `size` | string | 尺寸,如 `"1024*1024"` | +| `n` | integer | 生成数量 | +| `style` | string | 风格参数 | +| `quality` | string | 质量参数 | +| `transno` | string | 交易流水号 | + +### 请求示例 + +```json +{ + "model": "qwen-image-2.0-pro", + "catelogid": "t2i", + "prompt": "A beautiful sunset over the ocean", + "size": "1024*1024", + "n": 1 +} +``` + +### 响应格式 + +直接返回图像数据。 + +**成功响应:** + +```json +{ + "status": "SUCCEEDED", + "usage": { + "image_count": 1, + "input_tokens": 22, + "output_tokens": 2, + "size": "1024*1024", + "total_tokens": 24 + }, + "image_count": 1, + "image": ["https://token.opencomputing.cn/idfile?path=/tmp/...png"] +} +``` + +> `usage` 字段因模型不同可能返回不同内容:万象系列返回 `input_tokens`/`output_tokens`/`size`/`total_tokens`;千问系列返回 `height`/`width`/`image_count`。 + +**失败响应:** + +参数缺失: + +```json +{ + "status": "error", + "data": { + "message": "Missing required parameter: prompt" + } +} +``` + +模型不存在或参数无效: + +```json +{ + "error": { + "message": "Parameters error.", + "type": "invalidparameters", + "param": null, + "code": "invalidparameters" + } +} +``` + +### curl 测试用例 + +```bash +# ---- 万象 wan2.7-image-pro(同步) ---- +curl -X POST 'https://token.opencomputing.cn/llmage/v1/image/generations' \ + -H 'Authorization: Bearer *** \ + -H 'Content-Type: application/json' \ + -d '{ + "model": "wan2.7-image-pro", + "catelogid": "t2i", + "prompt": "一只可爱的橘猫趴在窗台上晒太阳", + "size": "1024*1024", + "n": 1 + }' + +# ---- 万象 wan2.7-image-plus(同步) ---- +curl -X POST 'https://token.opencomputing.cn/llmage/v1/image/generations' \ + -H 'Authorization: Bearer *** \ + -H 'Content-Type: application/json' \ + -d '{ + "model": "wan2.7-image-plus", + "catelogid": "t2i", + "prompt": "一幅水墨山水画", + "size": "2048*2048", + "n": 1 + }' + +# ---- 千问图像 qwen-image-2.0-pro(同步,图生图) ---- +curl -X POST 'https://token.opencomputing.cn/llmage/v1/image/generations' \ + -H 'Authorization: Bearer *** \ + -H 'Content-Type: application/json' \ + -d '{ + "model": "qwen-image-2.0-pro", + "catelogid": "t2i", + "prompt": "将这张图片转换为油画风格", + "image_file": "https://example.com/photo.jpg", + "size": "2048*2048", + "n": 1, + "watermark": false, + "prompt_extend": true + }' + +# ---- 千问图像 qwen-image-plus(同步) ---- +curl -X POST 'https://token.opencomputing.cn/llmage/v1/image/generations' \ + -H 'Authorization: Bearer *** \ + -H 'Content-Type: application/json' \ + -d '{ + "model": "qwen-image-plus", + "catelogid": "t2i", + "prompt": "赛博朋克风格的城市夜景", + "size": "1024*1024", + "n": 1 + }' +``` + +### 各模型输入参数明细 + +> 以下为各平台/模型的具体输入参数。调用时通过 `model` + `catelogid` 自动路由到对应供应商。 + +--- + +#### 万象图像(Wan-Image) + +##### T2I - 文生图 + +| 参数名 | 类型 | 必填 | 默认值 | 说明 | 可选值 | +|--------|------|------|--------|------|--------| +| `model` | string | 是 | - | 模型名称 | 见下方模型列表 | +| `catelogid` | string | 是 | `t2i` | 目录类型ID,文生图固定为 `t2i` | `t2i` | +| `prompt` | string | 是 | - | 提示词 | - | +| `size` | string | 否 | `1024*1024` | 图像尺寸 | `512*512`, `1024*1024`, `2048*2048` 等 | +| `n` | integer | 否 | `1` | 生成数量 | 1-4 | + +**可用模型:** + +| 模型名称 | 说明 | 价格 | +|----------|------|------| +| `wan2.7-image-pro` | 万象专业版,创意性、稳定性、写实质感全面升级 | 0.5元/张 | +| `wan2.7-image-plus` | 万象Plus版,高分辨率图像生成,性价比高 | 0.2元/张 | + +--- + +#### 千问图像(Qwen-Image) + +##### qwen-image-2.0 系列 - 文生图 + +| 参数名 | 类型 | 必填 | 默认值 | 说明 | 可选值 | +|--------|------|------|--------|------|--------| +| `model` | string | 是 | - | 模型名称 | `qwen-image-2.0-pro`, `qwen-image-2.0-2026-03-03` | +| `catelogid` | string | 是 | `t2i` | 目录类型ID,文生图固定为 `t2i` | `t2i` | +| `prompt` | string | 是 | - | 提示词 | - | +| `image_file` | image | 否 | - | 参考图 URL(图生图) | - | +| `size` | string | 否 | `2048*2048` | 图像尺寸 | `512*512`, `1024*1024`, `2048*2048` 等 | +| `n` | integer | 否 | `1` | 生成数量 | 1-4 | +| `watermark` | boolean | 否 | `false` | 是否添加水印 | `true`, `false` | +| `prompt_extend` | boolean | 否 | `true` | 是否扩展提示词 | `true`, `false` | + +**可用模型:** + +| 模型名称 | 说明 | 价格 | +|----------|------|------| +| `qwen-image-2.0-pro` | 千问图像生成Pro系列,文字渲染、真实质感、语义遵循能力更强 | 0.5元/张 | +| `qwen-image-2.0-2026-03-03` | 千问图像生成2.0快照版(2026-03-03),兼顾效果与响应速度 | 0.5元/张 | + +--- + +##### qwen-image-plus 系列 - 文生图 + +| 参数名 | 类型 | 必填 | 默认值 | 说明 | 可选值 | +|--------|------|------|--------|------|--------| +| `model` | string | 是 | - | 模型名称 | `qwen-image-plus`, `qwen-image-plus-2026-01-09` | +| `catelogid` | string | 是 | `t2i` | 目录类型ID,文生图固定为 `t2i` | `t2i` | +| `prompt` | string | 是 | - | 提示词 | - | +| `size` | string | 否 | `1024*1024` | 图像尺寸 | `512*512`, `1024*1024`, `2048*2048` 等 | +| `n` | integer | 否 | `1` | 生成数量 | 1-4 | + +**可用模型:** + +| 模型名称 | 说明 | 价格 | +|----------|------|------| +| `qwen-image-plus` | 千问图像Plus系列,擅长多样化艺术风格与文字渲染 | 0.2元/张 | +| `qwen-image-plus-2026-01-09` | 千问图像Plus快照版(2026-01-09),为qwen-image-max的蒸馏加速版 | 0.2元/张 | + +--- + +## POST /v1/music/generations + +音乐生成接口。 + +### 必填参数 + +| 参数 | 类型 | 说明 | +|------|------|------| +| `model` | string | 模型名称,如 `"music-2.6"`, `"music-2.5"` | +| `catelogid` | string | 目录类型ID,固定为 `"music_gen"` | +| `prompt` | string | 音乐风格描述(风格、情绪、场景),如 `"流行音乐, 开心, 适合阳光明媚的下午"` | +| `lyrics` | string | 歌词内容,使用 `\n` 分隔每行,可包含结构标签 | + +### 歌词结构标签 + +歌词中可包含以下结构标签来优化生成的音乐结构: +- `[Intro]` - 前奏 +- `[Verse]` - 主歌 +- `[Pre Chorus]` - 预副歌 +- `[Chorus]` - 副歌 +- `[Bridge]` - 桥段 +- `[Outro]` - 尾声 +- `[Interlude]` - 间奏 +- `[Hook]` - 记忆点 +- `[Build Up]` - 情绪铺垫 +- `[Solo]` - 独奏 + +### 请求示例 + +```json +{ + "model": "music-2.6", + "catelogid": "music_gen", + "prompt": "Pop music, happy, suitable for a sunny day", + "lyrics": "[Intro]\n\n[Verse]\nWalking down the street\nFeeling the beat\n\n[Chorus]\nDancing in the sun\nHaving so much fun" +} +``` + +```bash +curl -X POST 'https://token.opencomputing.cn/llmage/v1/music/generations' \ + -H 'Authorization: Bearer *** + -H 'Content-Type: application/json' \ + -d '{ + "model": "music-2.6", + "catelogid": "music_gen", + "prompt": "流行音乐, 欢快, 适合阳光明媚的下午", + "lyrics": "[Intro]\n\n[Verse]\n走在阳光下\n感受每一刻\n\n[Chorus]\n在阳光下跳舞\n享受美好时光" + }' +``` + +### 响应格式 + +MiniMax 音乐生成为同步接口,直接返回音频URL: + +```json +{ + "id": "luid_xxx", + "object": "music.generation", + "model": "music-2.6", + "status": "SUCCEEDED", + "audio": "https://...", + "created": 1716912000 +} +``` + +### 可用模型 + +| 模型名称 | model 参数 | 说明 | +|---------|-----------|------| +| MiniMax Music 2.6 | `music-2.6` | 最新版本,音质最佳 | +| MiniMax Music 2.5 | `music-2.5` | 支持14种段落级结构标签,物理级高保真 | + +### MiniMax Music 2.5 特性 + +Music 2.5 在「段落级强控制」与「物理级高保真」两大技术难题上实现突破: +- 开放全段落标签控制,精准支持14种结构变体 +- 长度限制:歌词内容 [1, 3500] 个字符 +- prompt 长度限制:[10, 300] 个字符 + +### 错误响应 + +| 状态码 | 说明 | +|--------|------| +| 400 | 缺少必填参数或模型不存在 | +| 403 | 未登录 | +| 429 | 账户余额不足 | + +--- + +## POST /v1/audio/speech + +文本转语音(TTS)接口。 + +### 必填参数 + +| 参数 | 类型 | 说明 | +|------|------|------| +| `model` | string | 模型名称,如 `"speech-2.6-turbo"`, `"speech-2.6-hd"` | +| `catelogid` | string | 目录类型ID,固定为 `"tts"` | +| `prompt` | string | 需要合成的文本内容,最长 10,000 字符 | + +### 可选参数 + +| 参数 | 类型 | 说明 | +|------|------|------| +| `speaker` | string | 说话人/音色ID,如 `"female-tianmei"` | +| `speed` | float | 语速,默认 `1.0` | +| `emotion` | string | 情感,如 `"happy"`, `"sad"` | +| `transno` | string | 交易流水号 | + +### 请求示例 + +```json +{ + "model": "speech-2.6-turbo", + "catelogid": "tts", + "prompt": "你好,欢迎使用语音合成服务", + "speaker": "female-tianmei", + "speed": 1.0, + "emotion": "happy" +} +``` + +```bash +curl -X POST 'https://token.opencomputing.cn/llmage/v1/audio/speech' \ + -H 'Authorization: Bearer *** + -H 'Content-Type: application/json' \ + -d '{ + "model": "speech-2.6-turbo", + "catelogid": "tts", + "prompt": "你好,欢迎使用语音合成服务", + "speaker": "female-tianmei", + "speed": 1.0, + "emotion": "happy" + }' +``` + +### 响应格式 + +MiniMax TTS 为流式接口,逐块返回音频数据(hex编码自动转base64): + +```json +{ + "status": "SUCCEEDED", + "audio": "base64_encoded_audio_data" +} +``` + +### 可用模型 + +| 模型名称 | model 参数 | 说明 | +|---------|-----------|------| +| MiniMax Speech 2.6 Turbo | `speech-2.6-turbo` | 极速版,更快更优惠,适用于语音聊天和数字人 | +| MiniMax Speech 2.6 HD | `speech-2.6-hd` | 高清版,超低延时,更高自然度 | +| MiniMax Speech 2.5 HD | `speech-2.5-hd-preview` | Preview版本 | +| F5-TTS 本地 | `f5tts` | 本地部署,零样本声音克隆,多语言支持 | + +### 错误响应 + +| 状态码 | 说明 | +|--------|------| +| 400 | 缺少必填参数或模型不存在 | +| 403 | 未登录 | +| 429 | 账户余额不足 | + +--- + +## POST /v1/audio/transcriptions + +语音识别(ASR)接口,将音频转为文本。 + +### 必填参数 + +| 参数 | 类型 | 说明 | +|------|------|------| +| `model` | string | 模型名称,如 `"qwen3-asr-flash"`, `"parakeet-tdt-0.6b-v2"` | +| `catelogid` | string | 目录类型ID,固定为 `"asr"` | +| `audio_file` | string | 音频文件URL | + +### 可选参数 + +| 参数 | 类型 | 说明 | +|------|------|------| +| `language` | string | 语言代码(部分模型支持) | +| `transno` | string | 交易流水号 | + +### 请求示例 + +```json +{ + "model": "qwen3-asr-flash", + "catelogid": "asr", + "audio_file": "https://example.com/audio.wav" +} +``` + +```bash +curl -X POST 'https://token.opencomputing.cn/llmage/v1/audio/transcriptions' \ + -H 'Authorization: Bearer *** + -H 'Content-Type: application/json' \ + -d '{ + "model": "qwen3-asr-flash", + "catelogid": "asr", + "audio_file": "https://example.com/audio.wav" + }' +``` + +### 响应格式 + +```json +{ + "text": "识别出的文本内容", + "usage": { + "duration_seconds": 5.2 + } +} +``` + +### 可用模型 + +| 模型名称 | model 参数 | 说明 | +|---------|-----------|------| +| 通义千问 ASR | `qwen3-asr-flash` | 多语种识别、歌唱识别、情感识别、噪声拒识,0.00026元/秒 | +| Nvidia ASR | `parakeet-tdt-0.6b-v2` | 仅支持英文,6亿参数,支持标点/大小写/时间戳 | + +### 通义千问 ASR 核心功能 + +- 多语种识别:涵盖普通话及多种方言(粤语、四川话等) +- 复杂环境适应:自动语种检测与智能非人声过滤 +- 歌唱识别:伴随BGM下也能实现整首歌曲转写 +- 上下文增强:通过配置上下文提高识别准确率 +- 情感识别:支持惊讶、平静、愉快、悲伤、厌恶、愤怒、恐惧 + +### 错误响应 + +| 状态码 | 说明 | +|--------|------| +| 400 | 缺少必填参数或模型不存在 | +| 403 | 未登录 | +| 429 | 账户余额不足 | + +--- + +## GET /v1/tasks + +查询异步任务状态(仅用于视频生成等异步任务)。 + +### 必填参数 + +| 参数 | 类型 | 说明 | +|------|------|------| +| `taskid` | string | 任务 ID | + +### 请求示例 + +``` +GET /llmage/v1/tasks?taskid=task_xxx +``` + +### 响应格式 + +```json +{ + "status": "ok", + "data": { + "status": "SUCCEEDED", + "output": [...] + } +} +``` + +任务状态值: `UNKNOWN` / `SUCCEEDED` / `FAILED` + +```bash +curl 'https://token.opencomputing.cn/llmage/v1/tasks?taskid=task_xxx' \ + -H 'Authorization: Bearer ***' +``` + +--- + +## GET /v1/models + +列出可用模型列表。 + +### 可选参数 + +| 参数 | 类型 | 说明 | +|------|------|------| +| `catelogid` | string | 按目录类型过滤 | +| `orderby` | string | 排序字段 | + +### 请求示例 + +``` +GET /llmage/v1/models +``` + +### 响应格式 + +```json +{ + "object": "list", + "data": [ + { + "id": "qwen3-max", + "object": "model", + "created": 1748044800, + "owned_by": "opencomputing.ai" + } + ] +} +``` + +```bash +# 获取全部模型 +curl 'https://token.opencomputing.cn/llmage/v1/models' \ + -H 'Authorization: Bearer ***' + +# 按目录过滤(如只获取文生视频模型) +curl 'https://token.opencomputing.cn/llmage/v1/models?catelogid=t2v' \ + -H 'Authorization: Bearer ***' +``` + +--- + +## GET /v1/models/catelog + +按分类目录获取可用模型列表,可排除指定模型。仅返回已上架(published)状态的模型。 + +### 必填参数 + +| 参数 | 类型 | 说明 | +|------|------|------| +| `catelogid` | string | 目录类型ID,如 `"t2t"`, `"t2v"`, `"t2i"` 等 | + +### 可选参数 + +| 参数 | 类型 | 说明 | +|------|------|------| +| `exclude_id` | string | 排除指定模型ID(常用于"相关推荐"场景) | + +### 请求示例 + +``` +GET /llmage/v1/models/catelog?catelogid=t2t +GET /llmage/v1/models/catelog?catelogid=t2v&exclude_id=abc123 +``` + +### 响应格式 + +```json +{ + "total": 5, + "rows": [ + { + "id": "xxx", + "name": "qwen3-max", + "model": "qwen3-max", + "description": "{...}", + "providerid": "...", + "upappid": "...", + "status": "published", + ... + } + ] +} +``` + +> 与 `/v1/models` 的区别:此接口返回模型的完整信息(含供应商、上位应用等),`/v1/models` 返回 OpenAI 兼容的精简格式。 + +### 错误响应 + +| 状态码 | 说明 | +|--------|------| +| 400 | 缺少 catelogid 参数 | + +```bash +# 获取文生文模型列表 +curl 'https://token.opencomputing.cn/llmage/v1/models/catelog?catelogid=t2t' \ + -H 'Authorization: Bearer ***' + +# 获取文生视频模型列表(排除某模型) +curl 'https://token.opencomputing.cn/llmage/v1/models/catelog?catelogid=t2v&exclude_id=abc123' \ + -H 'Authorization: Bearer ***' + +# 获取文生图模型列表 +curl 'https://token.opencomputing.cn/llmage/v1/models/catelog?catelogid=t2i' \ + -H 'Authorization: Bearer ***' +``` + +--- + +## GET /v1/pricing + +获取模型定价展示信息,根据模型名称查询其关联的定价程序并返回可读的定价文本。 + +### 必填参数 + +| 参数 | 类型 | 说明 | +|------|------|------| +| `model` | string | 模型名称,如 `"qwen3.7-max"` | + +### 可选参数 + +| 参数 | 类型 | 说明 | +|------|------|------| +| `catelogid` | string | 目录类型ID,默认 `"t2t"` | + +### 请求示例 + +``` +GET /llmage/v1/pricing?model=qwen3.7-max +``` + +```bash +curl 'https://token.opencomputing.cn/llmage/v1/pricing?model=qwen3.7-max' \ + -H 'Authorization: Bearer *** +``` + +### 响应格式 + +```json +{ + "status": "ok", + "data": { + "ppid": "pp_xxx", + "name": "qwen3.7-max", + "pricing_type": "per_use", + "display_text": "【通义千问 qwen3.7-max】定价:\n - 输入Token: 12 元/百万 [模型=qwen3.7-max]\n - 输出Token: 48 元/百万 [模型=qwen3.7-max]", + "items": [ + { + "factor": "输入Token", + "price": 12, + "unit": "百万", + "filters": "模型=qwen3.7-max" + } + ] + } +} +``` + +### 错误响应 + +```json +{"status": "error", "message": "model parameter required"} +``` + +```json +{"status": "error", "message": "model 'xxx' not found or has no pricing"} +``` + +--- + +## 通用说明 + +### catelogid 目录类型ID对照表 + +| ID | 中文名 | 说明 | +|----|--------|------| +| `t2t` | 文生文 | 文本生成(默认) | +| `t2i` | 文生图 | 图像生成 | +| `t2v` | 文生视频 | 文本生成视频 | +| `i2v` | 图生视频 | 图像生成视频 | +| `r2v` | 参考生视频 | 参考图像生成视频 | +| `tts` | 语音合成 | 文本转语音 | +| `asr` | 语音识别 | 语音转文本 | +| `vision` | 图理解 | 图像理解 | +| `ai_search` | AI搜索 | AI搜索 | +| `digital_human` | 数字人 | 数字人 | +| `music_gen` | 音乐生成 | 音乐生成 | +| `text_cls` | 文本分类 | 文本分类 | +| `3d_gen` | 3D生成 | 3D模型生成 | +| `video_tool` | 视频工具 | 视频处理工具 | +| `translate` | 翻译 | 文本翻译 | + +> 向后兼容:catelogid 参数同时支持新ID(如 `"t2v"`)和旧中文名(如 `"文生视频"`),推荐使用新ID。 + +### 参数统一 + +所有 v1 接口统一使用 `catelogid` 参数标识目录类型,替代原有的 `lctype` / `llmcatelogid`。 + +### 认证 + +所有接口需要 Bearer Token 认证,请求头中携带: + +``` +Authorization: Bearer *** +``` + +--- + +# 真人素材 API + +真人素材 API 提供真人人像认证、素材上传和素材管理功能。使用与大模型 API 相同的 APIKEY 认证。 + +**Base URL**: `https://token.opencomputing.cn` + +**认证**: Bearer Token(与大模型 API 相同) + +## 业务流程 + +1. **真人认证**:发起认证请求,获取 H5 链接供终端用户完成人脸识别 +2. **查询已认证组合**:查询当前机构下所有已认证的组合 ID +3. **上传素材**:使用已认证的组合 ID 上传图片/视频 +4. **状态同步**:轮询检查素材处理状态 + +--- + +## POST /reallife_asset/api/rl_verify.dspy + +获取真人认证链接(H5)。 + +### 请求参数 + +| 参数 | 必填 | 说明 | +|------|------|------| +| `vendor` | 是 | 供应商标识 | +| `project_name` | 否 | 项目名称,默认 `default` | +| `name` | 否 | 认证名称,方便识别 | + +> `user_id` 和 `org_id` 由 Bearer Token 自动获取 + +### 请求示例 + +```bash +curl -X POST 'https://token.opencomputing.cn/reallife_asset/api/rl_verify.dspy' \ + -H 'Authorization: Bearer *** \ + -H 'Content-Type: application/json' \ + -d '{ + "vendor": "volcengine", + "project_name": "default", + "name": "张三" + }' +``` + +### 响应示例 + +```json +{ + "status": "ok", + "data": { + "id": "local_group_id_xxx", + "h5_link": "https://... (H5页面链接,120秒有效)", + "byted_token": "..." + } +} +``` + +--- + +## POST /reallife_asset/api/rl_query_groups.dspy + +查询已认证的组合列表。 + +### 请求参数 + +无需参数,系统自动从 Bearer Token 获取 `org_id`。 + +### 请求示例 + +```bash +curl -X POST 'https://token.opencomputing.cn/reallife_asset/api/rl_query_groups.dspy' \ + -H 'Authorization: Bearer ***' +``` + +### 响应示例 + +```json +{ + "status": "ok", + "data": { + "groups": [ + { + "vendor_group_id": "volc-asset-group-xxx", + "vendor": "volcengine", + "name": "模特张三", + "status": "active", + "create_time": "2026-05-28 15:30:00" + } + ] + } +} +``` + +--- + +## POST /reallife_asset/api/rl_upload.dspy + +上传素材到已认证的组合。 + +### 请求参数 + +| 参数 | 必填 | 说明 | +|------|------|------| +| `vendor_group_id` | 是 | 已认证的组合 ID | +| `source_url` | 是 | 素材 URL 或 `data:` base64 编码 | +| `asset_type` | 否 | `Image`(默认)或 `Video` | +| `name` | 否 | 素材名称 | + +### 请求示例 + +```bash +curl -X POST 'https://token.opencomputing.cn/reallife_asset/api/rl_upload.dspy' \ + -H 'Authorization: Bearer *** \ + -H 'Content-Type: application/json' \ + -d '{ + "vendor_group_id": "volc-asset-group-xxx", + "source_url": "https://bucket.oss.com/photo.jpg", + "asset_type": "Image", + "name": "模特A" + }' +``` + +### 响应示例 + +```json +{ + "status": "ok", + "data": { + "id": "asset_record_id_xxx", + "vendor_asset_id": "asset-2026...", + "status": "Processing" + } +} +``` + +> 上传是异步操作,需调用 `rl_status` 轮询状态。 + +--- + +## POST /reallife_asset/api/rl_status.dspy + +查询素材处理状态。 + +### 请求参数 + +| 参数 | 必填 | 说明 | +|------|------|------| +| `asset_id` | 是 | 上传时返回的记录 ID | + +### 请求示例 + +```bash +curl -X POST 'https://token.opencomputing.cn/reallife_asset/api/rl_status.dspy' \ + -H 'Authorization: Bearer *** \ + -H 'Content-Type: application/json' \ + -d '{ + "asset_id": "asset_record_id_xxx" + }' +``` + +### 响应示例 + +```json +{ + "status": "ok", + "data": { + "status": "Active", + "url": "https://... (临时下载链接,12小时有效)" + } +} +``` + +> 素材永久存储。`url` 过期后可再次调用获取新链接。 + +--- + +## POST /reallife_asset/api/rl_assets.dspy + +查询组合下所有素材。 + +### 请求参数 + +| 参数 | 必填 | 说明 | +|------|------|------| +| `vendor_group_id` | 是 | 已认证的组合 ID | + +### 请求示例 + +```bash +curl -X POST 'https://token.opencomputing.cn/reallife_asset/api/rl_assets.dspy' \ + -H 'Authorization: Bearer *** \ + -H 'Content-Type: application/json' \ + -d '{ + "vendor_group_id": "volc-asset-group-xxx" + }' +``` + +### 响应示例 + +```json +{ + "status": "ok", + "data": { + "assets": [ + { + "id": "asset_record_id_xxx", + "vendor_asset_id": "asset-2026...", + "name": "模特A", + "asset_type": "Image", + "status": "Active", + "url": "https://...", + "create_time": "2026-05-28 15:30:00" + } + ], + "total": 3 + } +} +``` + +--- + +## 真人素材错误说明 + +| 错误信息 | 原因 | 解决方案 | +|----------|------|----------| +| `供应商配置不存在` | 未配置 AK/SK | 联系管理员 | +| `供应商服务已停用` | 配置非 active | 联系管理员激活 | +| `无效的素材组合ID或无权访问` | ID 不属于当前机构 | 检查认证和 ID | +| `素材不存在或无权访问` | ID 无效 | 检查 ID | +| `尚未完成认证或认证失败` | 认证未完成 | 等待 H5 认证完成 | + +--- + +# 虚拟人素材 API + +私域虚拟人素材管理 API,用于创建虚拟人素材组合、上传素材、查询状态等。与真人素材 API 使用相同的认证方式,但素材存储在私域空间,仅当前机构可访问。 + +**Base URL**: `https://token.opencomputing.cn` + +**认证**: Bearer Token(与大模型 API 相同) + +## 业务流程 + +1. **创建素材组合**:为虚拟人创建一个素材组合 +2. **查询素材组合**:查看当前机构下所有虚拟人素材组合 +3. **上传素材**:向素材组合上传图片/视频/音频素材 +4. **状态同步**:轮询检查素材处理状态 +5. **查询素材列表**:查看组合下所有素材 + +--- + +## POST /reallife_asset/api/rl_virtual_create_group.dspy + +创建私域虚拟人素材组合。 + +### 请求参数 + +| 参数 | 必填 | 说明 | +|------|------|------| +| `vendor` | 是 | 供应商标识 | +| `name` | 是 | 组合名称 | +| `description` | 否 | 组合描述 | +| `project_name` | 否 | 项目名称,默认 `default` | + +> `user_id` 和 `org_id` 由 Bearer Token 自动获取 + +### 请求示例 + +```bash +curl -X POST 'https://token.opencomputing.cn/reallife_asset/api/rl_virtual_create_group.dspy' \ + -H 'Authorization: Bearer *** \ + -H 'Content-Type: application/json' \ + -d '{ + "vendor": "volcengine", + "name": "虚拟角色A", + "description": "测试组合" + }' +``` + +### 响应示例 + +```json +{ + "status": "ok", + "data": { + "id": "local_group_id_xxx", + "vendor_group_id": "volc-virtual-group-xxx" + } +} +``` + +--- + +## POST /reallife_asset/api/rl_virtual_groups.dspy + +查询当前机构的私域虚拟人素材组合列表。 + +### 请求参数 + +无需参数,系统自动从 Bearer Token 获取 `org_id`。 + +### 请求示例 + +```bash +curl -X POST 'https://token.opencomputing.cn/reallife_asset/api/rl_virtual_groups.dspy' \ + -H 'Authorization: Bearer ***' +``` + +### 响应示例 + +```json +{ + "status": "ok", + "data": { + "groups": [ + { + "vendor_group_id": "volc-virtual-group-xxx", + "vendor": "volcengine", + "name": "虚拟角色A", + "status": "active", + "create_time": "2026-06-01 10:00:00" + } + ] + } +} +``` + +--- + +## POST /reallife_asset/api/rl_virtual_upload.dspy + +上传虚拟人素材到私域素材组合。 + +### 请求参数 + +| 参数 | 必填 | 说明 | +|------|------|------| +| `vendor_group_id` | 是 | 已创建的虚拟人素材组合 ID | +| `source_url` | 是 | 素材 URL 或 `data:` base64 编码 | +| `asset_type` | 否 | `Image`(默认)、`Video`、`Audio` | +| `name` | 否 | 素材名称 | + +### 请求示例 + +```bash +curl -X POST 'https://token.opencomputing.cn/reallife_asset/api/rl_virtual_upload.dspy' \ + -H 'Authorization: Bearer *** \ + -H 'Content-Type: application/json' \ + -d '{ + "vendor_group_id": "volc-virtual-group-xxx", + "source_url": "https://bucket.oss.com/virtual_avatar.jpg", + "asset_type": "Image", + "name": "虚拟人正面" + }' +``` + +### 响应示例 + +```json +{ + "status": "ok", + "data": { + "id": "asset_record_id_xxx", + "vendor_asset_id": "virtual-asset-2026...", + "status": "Processing" + } +} +``` + +> 上传是异步操作,需调用 `rl_virtual_status` 轮询状态。 + +--- + +## POST /reallife_asset/api/rl_virtual_status.dspy + +查询虚拟人素材处理状态。 + +### 请求参数 + +| 参数 | 必填 | 说明 | +|------|------|------| +| `asset_id` | 是 | 上传时返回的记录 ID | + +### 请求示例 + +```bash +curl -X POST 'https://token.opencomputing.cn/reallife_asset/api/rl_virtual_status.dspy' \ + -H 'Authorization: Bearer *** \ + -H 'Content-Type: application/json' \ + -d '{ + "asset_id": "asset_record_id_xxx" + }' +``` + +### 响应示例 + +```json +{ + "status": "ok", + "data": { + "status": "Active", + "url": "https://... (临时下载链接,12小时有效)" + } +} +``` + +> 素材永久存储。`url` 过期后可再次调用获取新链接。 + +--- + +## POST /reallife_asset/api/rl_virtual_assets.dspy + +查询指定虚拟人素材组合下的素材列表。 + +### 请求参数 + +| 参数 | 必填 | 说明 | +|------|------|------| +| `vendor_group_id` | 是 | 虚拟人素材组合 ID | + +### 请求示例 + +```bash +curl -X POST 'https://token.opencomputing.cn/reallife_asset/api/rl_virtual_assets.dspy' \ + -H 'Authorization: Bearer *** \ + -H 'Content-Type: application/json' \ + -d '{ + "vendor_group_id": "volc-virtual-group-xxx" + }' +``` + +### 响应示例 + +```json +{ + "status": "ok", + "data": { + "assets": [ + { + "id": "asset_record_id_xxx", + "vendor_asset_id": "virtual-asset-2026...", + "name": "虚拟人正面", + "asset_type": "Image", + "status": "Active", + "url": "https://...", + "create_time": "2026-06-01 10:00:00" + } + ], + "total": 1 + } +} +``` + +--- + +## 虚拟人素材错误说明 + +| 错误信息 | 原因 | 解决方案 | +|----------|------|----------| +| `vendor和name为必填参数` | 创建组合时缺少必填字段 | 提供 vendor 和 name | +| `vendor_group_id和source_url为必填参数` | 上传素材时缺少必填字段 | 提供组合 ID 和素材 URL | +| `asset_id为必填参数` | 查询状态时缺少 asset_id | 提供素材记录 ID | +| `创建失败` | 组合创建失败 | 检查参数和供应商配置 | +| `上传失败` | 素材上传失败 | 检查 URL 是否可访问 | +| `查询失败` | 查询操作失败 | 检查 ID 是否属于当前机构 | + +# KTV Pipeline API(视频制作) + +Base url: `https://token.opencomputing.cn/llmage/v1` + +KTV产线GPU服务由开元云(北京)科技有限公司提供,覆盖14个原子化GPU端点:语音识别、音频分离、人脸检测/识别/比对、字幕渲染、视频合并、歌曲评分、音乐合成、超分辨率、声音转换、视频评估。 + +## 调用方式 + +所有 KTV Pipeline 服务通过 `/v1/pipeline/submit` 调用,`catelogid` 固定为 `ktv_pipeline`(无需传)。 + +``` +POST /v1/pipeline/submit +``` + +### 通用请求格式 + +| 参数 | 类型 | 必填 | 说明 | +|------|------|------|------| +| `model` | string | 是 | 模型名,见下方模型列表 | +| 业务参数 | - | 见各端点 | 各端点特定参数 | + +### 通用响应格式 + +**同步服务(直接返回结果):** + +```json +{ + "taskid": "luid_xxx", + "taskstatus": "SUCCEEDED", + "usage": {"...": N} +} +``` + +**异步服务(提交后轮询):** + +```json +{ + "taskid": "luid_xxx", + "taskstatus": "PENDING" +} +``` + +异步任务通过 `GET /v1/tasks?taskid=xxx` 查询状态。 + +--- + +## 模型列表 + +| model | 类型 | 功能 | 模式 | 计费 | +|-------|------|------|------|------| +| `ky-asr-transcribe` | 语音 | 语音转文字+时间戳 | 同步 | 0.01元/秒 | +| `ky-demucs-separate` | 音频 | 人声/伴奏分离 | 同步 | 0.02元/秒 | +| `ky-face-detect` | 视觉 | 人脸检测 | 同步 | 0.10元/次 | +| `ky-face-recognize` | 视觉 | 人脸识别 | 同步 | 0.10元/次 | +| `ky-face-compare` | 视觉 | 人脸比对 | 同步 | 0.10元/次 | +| `ky-subtitle-render` | 视频 | 歌词→ASS字幕渲染 | 同步 | 0.01元/条 | +| `ky-merge-video` | 视频 | 视频+音频+字幕合并 | 同步 | 0.01元/秒 | +| `ky-songrate-evaluate` | 音频 | AI歌曲质量评分 | 同步 | 0.005元/秒 | +| `ky-synth-generate` | 音频 | AI歌声合成 | **异步** | 0.20元/秒 | +| `ky-synth-status` | 音频 | 合成任务状态查询 | 同步 | 0.01元/次 | +| `ky-realesrgan-upscale` | 视觉 | 图像/视频超分辨率 | **异步** | 0.50元/张 | +| `ky-realesrgan-status` | 视觉 | 超分任务状态查询 | 同步 | 0.01元/次 | +| `ky-rvc-convert` | 音频 | 声音克隆/变声 | 同步 | 0.15元/秒 | +|| `ky-video-eval-evaluate` | 视频 | 视频质量评估 | 同步 | 0.05元/秒 | +|| `doubao-2.1-pro` | 文本 | 豆包大模型2.1 Pro | 同步 | 0.001元/1K tokens | +|| `doubao-seedream-5.0` | 图像 | 豆包图像创作5.0 | **异步** | 0.02元/张 | +|| `doubao-speech-2.0` | 语音 | 豆包语音识别2.0 | 同步 | 0.004元/秒 | +|| `hy3` | 文本 | 混元Hy3旗舰对话 | 同步 | 0.015/0.06元/1K tokens | +|| `hy-vision-2.0-instruct` | 视觉 | HY-Vision 2.0视觉理解 | 同步 | 0.003/0.009元/1K tokens | +|| `hy-image-3.0-plus` | 图像 | HY Image 3.0 Plus文生图 | 同步 | 0.02元/张 | +|| `hy-video-1.5-i2v` | 视频 | HY Video 1.5 图生视频 | **异步** | 0.15元/秒 | +|| `hy-video-1.5-t2v` | 视频 | HY Video 1.5 文生视频 | **异步** | 0.10元/秒 | + +--- + +## 各端点详细说明 + +### 1. 语音识别 — ky-asr-transcribe + +上传音频文件,返回识别文本和逐句时间戳。 + +| 参数 | 类型 | 必填 | 说明 | +|------|------|------|------| +| `audio_file` | string | 是 | 音频文件URL(支持 http/https) | +| `language` | string | 否 | 语言代码,默认 `zh` | + +```bash +curl -X POST 'https://token.opencomputing.cn/llmage/v1/pipeline/submit' \ + -H 'Authorization: Bearer ***' \ + -H 'Content-Type: application/json' \ + -d '{"model":"ky-asr-transcribe","audio_file":"https://example.com/audio.mp3","language":"zh"}' +``` + +**响应:** + +```json +{ + "taskid": "luid_xxx", + "taskstatus": "SUCCEEDED", + "text": "完整识别文本", + "segments": [ + {"text": "第一句", "start": 0.0, "end": 3.5}, + {"text": "第二句", "start": 4.0, "end": 7.2} + ], + "usage": {"audio_seconds": 10.5} +} +``` + +--- + +### 2. 音频分离 — ky-demucs-separate + +分离音频中的人声和伴奏。支持两种模式。 + +**分离模式:** + +| mode | `task_type` | 说明 | +|------|-------------|------| +| 两轨分离(默认) | `separate` | 分离人声(vocals)和伴奏(no_vocals),返回2个文件 | +| 全轨MIDI替换 | `separate_full` | 分离人声+drums+bass+other四轨,每个乐器轨转MIDI后用GM音源替换,混音为伴奏 | + +**全轨MIDI替换流程:** +1. demucs 4轨分离 → vocals / drums / bass / other +2. 每个乐器轨 basic-pitch → MIDI +3. MIDI 用 FluidR3_GM SoundFont 渲染(drums=ch10鼓组, bass=prog34电贝司, other=prog1钢琴) +4. ffmpeg 混音 → accompaniment.wav + +| 参数 | 类型 | 必填 | 说明 | +|------|------|------|------| +| `audio_file` | string | 是 | 音频文件URL | +| `task_type` | string | 否 | `separate`(默认,两轨)或 `separate_full`(全轨MIDI替换) | + +```bash +# 两轨分离(默认) +curl -X POST 'https://token.opencomputing.cn/llmage/v1/pipeline/submit' \ + -H 'Authorization: Bearer ***' \ + -H 'Content-Type: application/json' \ + -d '{"model":"ky-demucs-separate","audio_file":"https://example.com/music.mp3"}' + +# 全轨MIDI替换 +curl -X POST 'https://token.opencomputing.cn/llmage/v1/pipeline/submit' \ + -H 'Authorization: Bearer ***' \ + -H 'Content-Type: application/json' \ + -d '{"model":"ky-demucs-separate","audio_file":"https://example.com/music.mp3","task_type":"separate_full"}' +``` + +**响应(两轨模式):** + +```json +{ + "taskid": "luid_xxx", + "taskstatus": "SUCCEEDED", + "vocals_url": "https://token.opencomputing.cn/.../vocals.wav", + "accompaniment_url": "https://token.opencomputing.cn/.../no_vocals.wav", + "mode": "2stem", + "usage": {"audio_seconds": 240.0} +} +``` + +**响应(全轨MIDI替换模式):** + +```json +{ + "taskid": "luid_xxx", + "taskstatus": "SUCCEEDED", + "vocals_url": "https://token.opencomputing.cn/.../vocals.wav", + "accompaniment_url": "https://token.opencomputing.cn/.../accompaniment.wav", + "drums_midi_url": "https://token.opencomputing.cn/.../drums.wav", + "bass_midi_url": "https://token.opencomputing.cn/.../bass.wav", + "other_midi_url": "https://token.opencomputing.cn/.../other.wav", + "mode": "full", + "usage": {"audio_seconds": 240.0} +} +``` + +--- + +### 3. 人脸检测 — ky-face-detect + +检测图像中的人脸位置。 + +| 参数 | 类型 | 必填 | 说明 | +|------|------|------|------| +| `image_file` | string | 是 | 图像URL | + +```bash +curl -X POST 'https://token.opencomputing.cn/llmage/v1/pipeline/submit' \ + -H 'Authorization: Bearer ***' \ + -H 'Content-Type: application/json' \ + -d '{"model":"ky-face-detect","image_file":"https://example.com/photo.jpg"}' +``` + +**响应:** + +```json +{ + "taskid": "luid_xxx", + "taskstatus": "SUCCEEDED", + "faces": [ + {"x": 100, "y": 150, "w": 80, "h": 100, "confidence": 0.98} + ], + "usage": {"detect_count": 1} +} +``` + +--- + +### 4. 人脸识别 — ky-face-recognize + +识别图像中人脸的身份。 + +| 参数 | 类型 | 必填 | 说明 | +|------|------|------|------| +| `image_file` | string | 是 | 图像URL | +| `face_id` | string | 否 | 指定识别目标ID | + +```bash +curl -X POST 'https://token.opencomputing.cn/llmage/v1/pipeline/submit' \ + -H 'Authorization: Bearer ***' \ + -H 'Content-Type: application/json' \ + -d '{"model":"ky-face-recognize","image_file":"https://example.com/face.jpg"}' +``` + +**响应:** + +```json +{ + "taskid": "luid_xxx", + "taskstatus": "SUCCEEDED", + "matches": [ + {"face_id": "person_001", "confidence": 0.95, "name": "张三"} + ], + "usage": {"recognize_count": 1} +} +``` + +--- + +### 5. 人脸比对 — ky-face-compare + +比较两张人脸的相似度。 + +| 参数 | 类型 | 必填 | 说明 | +|------|------|------|------| +| `image_file1` | string | 是 | 第一张图像URL | +| `image_file2` | string | 是 | 第二张图像URL | + +```bash +curl -X POST 'https://token.opencomputing.cn/llmage/v1/pipeline/submit' \ + -H 'Authorization: Bearer ***' \ + -H 'Content-Type: application/json' \ + -d '{"model":"ky-face-compare","image_file1":"https://example.com/face1.jpg","image_file2":"https://example.com/face2.jpg"}' +``` + +**响应:** + +```json +{ + "taskid": "luid_xxx", + "taskstatus": "SUCCEEDED", + "similarity": 0.92, + "usage": {"compare_count": 1} +} +``` + +--- + +### 6. 字幕渲染 — ky-subtitle-render + +将歌词时间轴数据渲染为ASS格式字幕文件。 + +| 参数 | 类型 | 必填 | 说明 | +|------|------|------|------| +| `lyrics_json` | string | 是 | 歌词时间轴JSON字符串 | +| `width` | integer | 否 | 视频宽度,默认 1920 | +| `height` | integer | 否 | 视频高度,默认 1080 | + +```bash +curl -X POST 'https://token.opencomputing.cn/llmage/v1/pipeline/submit' \ + -H 'Authorization: Bearer ***' \ + -H 'Content-Type: application/json' \ + -d '{"model":"ky-subtitle-render","lyrics_json":"[{\"text\":\"第一句歌词\",\"start\":0,\"end\":3.5}]","width":1920,"height":1080}' +``` + +**响应:** + +```json +{ + "taskid": "luid_xxx", + "taskstatus": "SUCCEEDED", + "ass_url": "https://token.opencomputing.cn/.../karaoke.ass", + "usage": {"subtitle_count": 42} +} +``` + +--- + +### 7. 视频合并 — ky-merge-video + +合并视频、音频和字幕为最终成品。 + +| 参数 | 类型 | 必填 | 说明 | +|------|------|------|------| +| `video_file` | string | 否 | 视频文件URL | +| `audio_file` | string | 否 | 音频文件URL | +| `subtitle_file` | string | 否 | ASS字幕文件URL | +| `output_format` | string | 否 | 输出格式,默认 `mp4` | + +```bash +curl -X POST 'https://token.opencomputing.cn/llmage/v1/pipeline/submit' \ + -H 'Authorization: Bearer ***' \ + -H 'Content-Type: application/json' \ + -d '{"model":"ky-merge-video","video_file":"https://example.com/video.mp4","audio_file":"https://example.com/audio.mp3","subtitle_file":"https://example.com/sub.ass"}' +``` + +**响应:** + +```json +{ + "taskid": "luid_xxx", + "taskstatus": "SUCCEEDED", + "output_url": "https://token.opencomputing.cn/.../output.mp4", + "duration": 180.0, + "usage": {"output_seconds": 180.0} +} +``` + +--- + +### 8. 歌曲评分 — ky-songrate-evaluate + +AI评估歌曲质量,返回多维度评分。 + +| 参数 | 类型 | 必填 | 说明 | +|------|------|------|------| +| `audio_file` | string | 是 | 音频文件URL | +| `scene` | string | 否 | 场景类型,如 `pop`/`folk`/`rock`,默认 `pop` | + +```bash +curl -X POST 'https://token.opencomputing.cn/llmage/v1/pipeline/submit' \ + -H 'Authorization: Bearer ***' \ + -H 'Content-Type: application/json' \ + -d '{"model":"ky-songrate-evaluate","audio_file":"https://example.com/song.mp3","scene":"pop"}' +``` + +**响应:** + +```json +{ + "taskid": "luid_xxx", + "taskstatus": "SUCCEEDED", + "score": 8.5, + "details": { + "rhythm": 8.2, + "pitch": 9.0, + "emotion": 8.3, + "technique": 8.5 + }, + "usage": {"audio_seconds": 240.0} +} +``` + +--- + +### 9. 音乐合成 — ky-synth-generate(异步) + +AI歌声合成,提交后返回任务ID,需轮询状态。 + +| 参数 | 类型 | 必填 | 说明 | +|------|------|------|------| +| `lyrics` | string | 是 | 歌词文本 | +| `style` | string | 否 | 演唱风格,默认 `pop` | +| `audio_file` | string | 否 | 参考音频URL(用于声音克隆) | + +```bash +curl -X POST 'https://token.opencomputing.cn/llmage/v1/pipeline/submit' \ + -H 'Authorization: Bearer ***' \ + -H 'Content-Type: application/json' \ + -d '{"model":"ky-synth-generate","lyrics":"春天的花开秋天的风","style":"pop"}' +``` + +**提交响应:** + +```json +{ + "taskid": "luid_xxx", + "taskstatus": "PENDING" +} +``` + +**查询状态:** `GET /v1/tasks?taskid=luid_xxx` + +**完成响应:** + +```json +{ + "taskid": "luid_xxx", + "taskstatus": "SUCCEEDED", + "output_url": "https://token.opencomputing.cn/.../synth.wav", + "usage": {"audio_seconds": 180.0} +} +``` + +--- + +### 10. 合成状态查询 — ky-synth-status + +查询音乐合成任务的当前状态。 + +| 参数 | 类型 | 必填 | 说明 | +|------|------|------|------| +| `task_id` | string | 是 | 异步任务ID | + +```bash +curl 'https://token.opencomputing.cn/llmage/v1/pipeline/submit' \ + -H 'Authorization: Bearer ***' \ + -H 'Content-Type: application/json' \ + -d '{"model":"ky-synth-status","task_id":"luid_xxx"}' +``` + +--- + +### 11. 超分辨率 — ky-realesrgan-upscale(异步) + +图像/视频超分辨率放大,提交后返回任务ID。 + +| 参数 | 类型 | 必填 | 说明 | +|------|------|------|------| +| `image_file` | string | 是 | 图像URL | +| `scale` | integer | 否 | 放大倍数,默认 2 | + +```bash +curl -X POST 'https://token.opencomputing.cn/llmage/v1/pipeline/submit' \ + -H 'Authorization: Bearer ***' \ + -H 'Content-Type: application/json' \ + -d '{"model":"ky-realesrgan-upscale","image_file":"https://example.com/photo.jpg","scale":4}' +``` + +**完成响应:** + +```json +{ + "taskid": "luid_xxx", + "taskstatus": "SUCCEEDED", + "output_url": "https://token.opencomputing.cn/.../upscaled.png", + "usage": {"image_count": 1} +} +``` + +--- + +### 12. 超分状态查询 — ky-realesrgan-status + +查询超分辨率任务的当前状态。 + +| 参数 | 类型 | 必填 | 说明 | +|------|------|------|------| +| `task_id` | string | 是 | 异步任务ID | + +```bash +curl 'https://token.opencomputing.cn/llmage/v1/pipeline/submit' \ + -H 'Authorization: Bearer ***' \ + -H 'Content-Type: application/json' \ + -d '{"model":"ky-realesrgan-status","task_id":"luid_xxx"}' +``` + +--- + +### 13. 声音转换 — ky-rvc-convert + +声音克隆/变声,将输入音频转换为目标声音。 + +| 参数 | 类型 | 必填 | 说明 | +|------|------|------|------| +| `audio_file` | string | 是 | 输入音频URL | +| `voice_model` | string | 是 | 目标声音模型名 | + +```bash +curl -X POST 'https://token.opencomputing.cn/llmage/v1/pipeline/submit' \ + -H 'Authorization: Bearer ***' \ + -H 'Content-Type: application/json' \ + -d '{"model":"ky-rvc-convert","audio_file":"https://example.com/input.wav","voice_model":"singer_a"}' +``` + +**响应:** + +```json +{ + "taskid": "luid_xxx", + "taskstatus": "SUCCEEDED", + "output_url": "https://token.opencomputing.cn/.../converted.wav", + "usage": {"audio_seconds": 60.0} +} +``` + +--- + +### 14. 视频评估 — ky-video-eval-evaluate + +评估视频质量,返回多维度评分。 + +| 参数 | 类型 | 必填 | 说明 | +|------|------|------|------| +| `video_file` | string | 是 | 视频URL | + +```bash +curl -X POST 'https://token.opencomputing.cn/llmage/v1/pipeline/submit' \ + -H 'Authorization: Bearer ***' \ + -H 'Content-Type: application/json' \ + -d '{"model":"ky-video-eval-evaluate","video_file":"https://example.com/video.mp4"}' +``` + +**响应:** + +```json +{ + "taskid": "luid_xxx", + "taskstatus": "SUCCEEDED", + "score": 85.0, + "details": { + "sharpness": 90, + "color": 82, + "stability": 88, + "composition": 80 + }, + "usage": {"video_seconds": 60.0} +} +``` + +--- + + + +--- + +## 豆包大模型 API + +### 豆包大模型2.1 Pro — doubao-2.1-pro + +字节跳动自研大模型,256K上下文,支持文本对话和多模态理解。 +通过火山引擎 ARK API 接入。 + +| 参数 | 类型 | 必填 | 说明 | +|------|------|------|------| +| `prompt` | string | 是 | 用户输入文本 | +| `sys_prompt` | string | 否 | 系统提示词 | +| `max_tokens` | int | 否 | 最大输出 token 数,默认 1024 | +| `stream` | boolean | 否 | 流式输出 | + +```bash +curl -X POST 'https://token.opencomputing.cn/llmage/v1/chat/completions' \ + -H 'Authorization: Bearer ***' \ + -H 'Content-Type: application/json' \ + -d '{"model":"doubao-2.1-pro","prompt":"介绍一下你自己","max_tokens":100}' +``` + +**响应:** OpenAI 兼容格式 + +```json +{ + "id": "chatcmpl-xxx", + "model": "doubao-2.1-pro", + "choices": [{"index": 0, "message": {"role": "assistant", "content": "..."}}], + "usage": {"prompt_tokens": 10, "completion_tokens": 50, "total_tokens": 60} +} +``` + +### 豆包图像创作5.0 — doubao-seedream-5.0 + +Seedream 5.0 文生图模型,通过火山引擎 ARK API 接入。 + +| 参数 | 类型 | 必填 | 说明 | +|------|------|------|------| +| `prompt` | string | 是 | 图像描述文本 | +| `size` | string | 否 | 图像尺寸,默认 `"1024x1024"` | +| `n` | integer | 否 | 生成数量,默认 1 | + +```bash +curl -X POST 'https://token.opencomputing.cn/llmage/v1/image/generations' \ + -H 'Authorization: Bearer ***' \ + -H 'Content-Type: application/json' \ + -d '{"model":"doubao-seedream-5.0","catelogid":"t2i","prompt":"a beautiful sunset","size":"1024x1024"}' +``` + +### 豆包语音识别2.0 — doubao-speech-2.0 + +Speech 2.0 语音转文字模型,通过火山引擎 ARK API 接入。 + +| 参数 | 类型 | 必填 | 说明 | +|------|------|------|------| +| `audio_file` | string | 是 | 音频文件URL | +| `language` | string | 否 | 语言代码,默认 `"zh"` | + +```bash +curl -X POST 'https://token.opencomputing.cn/llmage/v1/audio/transcriptions' \ + -H 'Authorization: Bearer ***' \ + -H 'Content-Type: application/json' \ + -d '{"model":"doubao-speech-2.0","catelogid":"asr","audio_file":"https://example.com/audio.mp3"}' +``` + +```json +{"text": "识别文本", "usage": {"audio_seconds": 10.5}} +``` + +--- + +## 模型发现 + +列出所有 KTV Pipeline 可用模型: + +```bash +curl 'https://token.opencomputing.cn/llmage/v1/models?catelogid=ktv_pipeline' \ + -H 'Authorization: Bearer ***' +``` + +## 错误说明 + +| 错误信息 | 原因 | 解决方案 | +|----------|------|----------| +| `Model "xxx" not found` | 模型名不存在或未发布 | 检查 model 值,或用 /v1/models 查询 | +| `Missing required parameter` | 缺少必填参数 | 参考上方各端点参数表 | +| `余额不足` | 账户余额低于模型最低余额要求 | 充值 | +| `模型未配置定价` | 模型缺少 ppid 配置 | 联系管理员 | +| `gpu not available` | GPU资源不足 | 稍后重试 diff --git a/wwwroot/exec_migrate.dspy b/wwwroot/exec_migrate.dspy new file mode 100644 index 00000000..51c0208c --- /dev/null +++ b/wwwroot/exec_migrate.dspy @@ -0,0 +1,44 @@ +dbname = get_module_dbname('llmage') +db = DBPools() +async with db.sqlorContext(dbname) as sor: + # Create table + sql = """ + CREATE TABLE IF NOT EXISTS llm_catalog_rel ( + id VARCHAR(32) NOT NULL PRIMARY KEY, + llmid VARCHAR(32) NOT NULL, + llmcatelogid VARCHAR(32) NOT NULL, + INDEX idx_llm (llmid), + INDEX idx_catelog (llmcatelogid) + ) + """ + try: + await sor.sqlExe(sql, {}) + print("Table llm_catalog_rel created or exists.") + except Exception as e: + print(f"Create table error: {e}") + + # Migrate data + sql = "select id, llmcatelogid from llm where llmcatelogid is not null and llmcatelogid != ''" + rows = await sor.sqlExe(sql, {}) + print(f"Found {len(rows)} records to migrate.") + + for r in rows: + data = { + 'llmid': r['id'], + 'llmcatelogid': r['llmcatelogid'] + } + try: + await sor.C('llm_catalog_rel', data) + except Exception as e: + print(f"Insert error: {e}") + + print("Migration complete.") + + # Drop column + try: + await sor.sqlExe("alter table llm drop column llmcatelogid", {}) + print("Column llmcatelogid dropped.") + except Exception as e: + print(f"Drop column error: {e}") + +return {'status': 'ok'} diff --git a/wwwroot/fee/feelog/index.ui b/wwwroot/fee/feelog/index.ui index 3f9e605f..04a2378a 100644 --- a/wwwroot/fee/feelog/index.ui +++ b/wwwroot/fee/feelog/index.ui @@ -1,4 +1,10 @@ - +{ + "widgettype": "VBox", + "options": { + "cheight": 40, + "width": "100%" + }, + "subwidgets": [ { "widgettype":"Tabular", "options":{ @@ -327,4 +333,6 @@ "cache_limit":5 } +} + ] } diff --git a/wwwroot/global_menu.ui b/wwwroot/global_menu.ui new file mode 100644 index 00000000..0186c12e --- /dev/null +++ b/wwwroot/global_menu.ui @@ -0,0 +1,432 @@ +{% set roles = get_user_roles(get_user()) %} +{% set role_str = roles|join(',') %} +{% set is_customer = 'customer.' in role_str %} +{% set is_customer_admin = 'customer.admin' in roles %} +{% set is_superuser = 'owner.superuser' in roles %} +{% set is_reseller_operator = 'reseller.operator' in roles %} +{% set is_any_admin = '.admin' in role_str %} +{ + "widgettype": "Menu", + "id": "global_nav_menu", + "options": { + "width": "100%", + "height": "100%", + "items": [ +{% if is_customer %} + { + "name": "dashboard", + "label": "仪表盘", + "icon": "{{entire_url('/imgs/dashboard.svg')}}", + "url": "{{entire_url('/sage_datamart/index.ui')}}", + "target": "app.sage_main_content" + } + ,{ + "name": "model_plaza", + "label": "模型广场", + "icon": "{{entire_url('/imgs/cubes.svg')}}", + "url": "{{entire_url('/llmage/model_plaza.ui')}}", + "target": "app.sage_main_content" + } + ,{ + "name": "reallife_asset", + "label": "真人素材", + "icon": "{{entire_url('/imgs/user-circle.svg')}}", + "url": "{{entire_url('/reallife_asset/index.ui')}}", + "target": "app.sage_main_content" + } + ,{ + "name": "llm_api", + "label": "大模型API调用", + "icon": "{{entire_url('/imgs/rocket.svg')}}", + "url": "{{entire_url('/docs/api_doc.ui')}}", + "target": "app.sage_main_content" + } +{% if is_customer_admin %} + ,{ + "name": "users", + "label": "用户管理", + "icon": "{{entire_url('/imgs/users.svg')}}", + "url": "{{entire_url('/rbac/users')}}", + "target": "app.sage_main_content" + } + ,{ + "name": "accounting_center", + "label": "账务中心", + "icon": "{{entire_url('/imgs/coins.svg')}}", + "items": [ + { + "name": "my_accounts", + "label": "余额与充值", + "url": "{{entire_url('/accounting/myaccounts.ui')}}", + "target": "app.sage_main_content" + }, + { + "name": "credit_overview", + "label": "信用额度", + "url": "{{entire_url('/accounting/credit_limit/credit_overview.ui')}}", + "target": "app.sage_main_content" + }, + { + "name": "billing_query", + "label": "账单查询", + "url": "{{entire_url('/accounting/billing.ui')}}", + "target": "app.sage_main_content" + } + ] + } +{% endif %} +{% else %} + { + "name": "dashboard", + "label": "仪表盘", + "icon": "{{entire_url('/imgs/dashboard.svg')}}", + "url": "{{entire_url('/sage_datamart/index.ui')}}", + "target": "app.sage_main_content" + } + ,{ + "name": "llm_api", + "label": "大模型API调用", + "icon": "{{entire_url('/imgs/rocket.svg')}}", + "url": "{{entire_url('/docs/api_doc.ui')}}", + "target": "app.sage_main_content" + } + ,{ + "name": "llmage", + "label": "模型管理", + "icon": "{{entire_url('/imgs/cubes.svg')}}", + "items": [ + { + "name": "llmusage", + "label": "模型用量", + "url": "{{entire_url('/llmage/llmusage')}}", + "target": "app.sage_main_content" + }, + { + "name": "catelog", + "label": "模型类型", + "url": "{{entire_url('/llmage/llmcatelog_list')}}", + "target": "app.sage_main_content" + }, + { + "name": "model_plaza", + "label": "模型广场", + "url": "{{entire_url('/llmage/model_plaza.ui')}}", + "target": "app.sage_main_content" + }, + { + "name": "llm", + "label": "模型", + "url": "{{entire_url('/llmage/llm')}}", + "target": "app.sage_main_content" + }, + { + "name": "failed_accounting", + "label": "记账失败记录", + "url": "{{entire_url('/llmage/failed_accounting.ui')}}", + "target": "app.sage_main_content" + } + ] + } + ,{ + "name": "pricing", + "label": "定价管理", + "icon": "{{entire_url('/imgs/coins.svg')}}", + "url": "{{entire_url('/pricing/pricing_program')}}", + "target": "app.sage_main_content" + } + ,{ + "name": "discount", + "label": "折扣管理", + "icon": "{{entire_url('/imgs/percent.svg')}}", + "items": [ + { + "name": "discount_list", + "label": "折扣方案", + "url": "{{entire_url('/discount/discount_list/index.ui')}}", + "target": "app.sage_main_content" + }, + { + "name": "discount_detail_list", + "label": "折扣产品明细", + "url": "{{entire_url('/discount/discount_detail_list/index.ui')}}", + "target": "app.sage_main_content" + }, + { + "name": "discount_marketing_list", + "label": "营销方案", + "url": "{{entire_url('/discount/discount_marketing_list/index.ui')}}", + "target": "app.sage_main_content" + }, + { + "name": "discount_promo_code_list", + "label": "促销码", + "url": "{{entire_url('/discount/discount_promo_code_list/index.ui')}}", + "target": "app.sage_main_content" + }, + { + "name": "discount_customer_bind_list", + "label": "客户归属", + "url": "{{entire_url('/discount/discount_customer_bind_list/index.ui')}}", + "target": "app.sage_main_content" + }, + { + "name": "free_customer_assign", + "label": "自由客户分配", + "url": "{{entire_url('/discount/free_customer_assign/index.ui')}}", + "target": "app.sage_main_content" + }, + { + "name": "customer_reassign", + "label": "客户再分配", + "url": "{{entire_url('/discount/customer_reassign/index.ui')}}", + "target": "app.sage_main_content" + } + ] + } + ,{ + "name": "accounting_center", + "label": "账务中心", + "icon": "{{entire_url('/imgs/coins.svg')}}", + "items": [ + { + "name": "acc_config", + "label": "账务配置", + "items": [ + { + "name": "subject_manage", + "label": "科目设置", + "url": "{{entire_url('/accounting/subject/index.ui')}}", + "target": "app.sage_main_content" + }, + { + "name": "account_config", + "label": "账务设置", + "url": "{{entire_url('/accounting/account_config/index.ui')}}", + "target": "app.sage_main_content" + }, + { + "name": "accounting_config", + "label": "会计分录配置", + "url": "{{entire_url('/accounting/accounting_config/index.ui')}}", + "target": "app.sage_main_content" + } + ] + }, + { + "name": "acc_process", + "label": "财务处理", + "items": [ + { + "name": "credit_limit_manage", + "label": "客户信用额度", + "url": "{{entire_url('/accounting/credit_limit/credit_manage.ui')}}", + "target": "app.sage_main_content" + }, + { + "name": "proxy_recharge", + "label": "代客充值", + "url": "{{entire_url('/accounting/proxy_recharge.ui')}}", + "target": "app.sage_main_content" + } + ] + }, + { + "name": "reseller_settle", + "label": "分销商结算", + "items": [ + { + "name": "reseller_reconcile", + "label": "分销商对账", + "url": "{{entire_url('/supplychain/reseller_reconcile.ui')}}", + "target": "app.sage_main_content" + }, + { + "name": "reseller_detail_reconcile", + "label": "明细对账", + "url": "{{entire_url('/supplychain/reseller_detail_reconcile.ui')}}", + "target": "app.sage_main_content" + }, + { + "name": "reseller_settlement", + "label": "分销商结算", + "url": "{{entire_url('/supplychain/reseller_settlement.ui')}}", + "target": "app.sage_main_content" + } + ] + }, + { + "name": "provider_finance", + "label": "供应商财务", + "items": [ + { + "name": "provider_recharge", + "label": "供应商充值", + "url": "{{entire_url('/supplychain/provider_recharge.ui')}}", + "target": "app.sage_main_content" + }, + { + "name": "provider_reconcile", + "label": "供应商对账", + "url": "{{entire_url('/supplychain/provider_reconcile.ui')}}", + "target": "app.sage_main_content" + }, + { + "name": "provider_detail_reconcile", + "label": "供应商明细对账", + "url": "{{entire_url('/supplychain/provider_detail_reconcile.ui')}}", + "target": "app.sage_main_content" + }, + { + "name": "provider_settlement", + "label": "供应商结算", + "url": "{{entire_url('/supplychain/provider_settlement.ui')}}", + "target": "app.sage_main_content" + } + ] + } + ] + } + ,{ + "name": "supply_chain", + "label": "供应链管理", + "icon": "{{entire_url('/imgs/truck.svg')}}", + "items": [ + { + "name": "provider", + "label": "供应商管理", + "url": "{{entire_url('/supplychain/suppliers_list')}}", + "target": "app.sage_main_content" + }, + { + "name": "reseller", + "label": "分销商管理", + "url": "{{entire_url('/supplychain/sub_distributors_list')}}", + "target": "app.sage_main_content" + } + ] + } + ,{ + "name": "product_management", + "label": "产品管理", + "icon": "{{entire_url('/imgs/cubes.svg')}}", + "items": [ + { + "name": "category", + "label": "产品类别管理", + "url": "{{entire_url('/product_management/product_category_tree')}}", + "target": "app.sage_main_content" + }, + { + "name": "product", + "label": "产品管理", + "url": "{{entire_url('/product_management/product_list')}}", + "target": "app.sage_main_content" + } + ] + } + ,{ + "name": "uapi", + "label": "上位系统管理", + "icon": "{{entire_url('/imgs/server.svg')}}", + "items": [ + { + "name": "upapp", + "label": "上位系统", + "url": "{{entire_url('/uapi/upapp/index.ui')}}", + "target": "app.sage_main_content" + }, + { + "name": "uapiio", + "label": "数据IO", + "url": "{{entire_url('/uapi/uapiio/index.ui')}}", + "target": "app.sage_main_content" + } + ] + } +{% endif %} + {% if is_any_admin %} + ,{ + "name": "users", + "label": "用户管理", + "icon": "{{entire_url('/imgs/users.svg')}}", + "url": "{{entire_url('/rbac/users')}}", + "target": "app.sage_main_content" + } +{% endif %} + {% if is_reseller_operator or is_superuser %} + ,{ + "name": "tenant_manage", + "label": "租户管理", + "icon": "{{entire_url('/imgs/globe.svg')}}", + "url": "{{entire_url('/tenant/')}}", + "target": "app.sage_main_content" + } +{% endif %} + {% if is_superuser %} + ,{ + "name": "system_permission", + "label": "系统权限管理", + "icon": "{{entire_url('/imgs/key.svg')}}", + "items": [ + { + "name": "role", + "label": "角色管理", + "url": "{{entire_url('/rbac/role')}}", + "target": "app.sage_main_content" + }, + { + "name": "permission", + "label": "权限管理", + "url": "{{entire_url('/rbac/permission')}}", + "target": "app.sage_main_content" + }, + { + "name": "rolepermission", + "label": "角色权限管理", + "url": "{{entire_url('/rbac/rolepermission')}}", + "target": "app.sage_main_content" + } + ] + } + ,{ + "name": "sys_config", + "label": "基础配置", + "icon": "{{entire_url('/imgs/setting.svg')}}", + "children": [ + { + "name": "appcodes", + "label": "编码管理", + "url": "{{entire_url('/appbase/appcodes')}}", + "target": "app.sage_main_content" + }, + { + "name": "svgicon", + "label": "图标管理", + "url": "{{entire_url('/appbase/svgicon')}}", + "target": "app.sage_main_content" + }, + { + "name": "currency", + "label": "币种管理", + "url": "{{entire_url('/accounting/currency_list')}}", + "target": "app.sage_main_content" + }, + { + "name": "exchange_rate", + "label": "汇率管理", + "url": "{{entire_url('/accounting/exchange_rate_list')}}", + "target": "app.sage_main_content" + } + ] + }{% endif %} + ,{ + "name": "apikey_manage", + "label": "API Key管理", + "icon": "{{entire_url('/imgs/key.svg')}}", + "url": "{{entire_url('/dapi/downapp/')}}", + "target": "app.sage_main_content" + } + ], + "menuitem_css": "menuitem" + } +} diff --git a/wwwroot/i18n/en/i18n.json b/wwwroot/i18n/en/i18n.json deleted file mode 100644 index a9595bf2..00000000 --- a/wwwroot/i18n/en/i18n.json +++ /dev/null @@ -1,79 +0,0 @@ -{ - "en":"Engish", - "zh":"中文", - "jp":"日本语", - "ko":"韩语", - "启用日期": "Enabled date", - "失效日期": "Expired date", - "大语言模型": "LLMS", - "体验": "Experience", - "3D生成": "3D generate", - "AI搜索": "AI search", - "图像理解": "Visual understanding", - "密码": "Password", - "数字人": "Digital human", - "文图生视频": "Text image to video", - "文本分类": "Text classification", - "文生图": "Text to graghic", - "文生文": "Text to Text", - "文生语音": "Text to Speech", - "语言翻译": "Language transation", - "语音识别": "Audio Speech Recognize", - "音乐生成": "Music generate", - "充值": "Recharge", - "地址": "Address", - "帐务": "Accounting", - "平台运营": "Platform Business", - "我": "Me", - "我的角色": "My roles", - "手机": "Cell Phone", - "用户": "User", - "用户名": "User name", - "用户状态": "User Status", - "用户角色": "User roles", - "签退": "Logout", - "邮件地址": "Mail address", - "重置密码": "Reset password", - "主页": "home", - "模型广场": "llms", - "私有知识库": "my rags", - "关于我们": "About us", - "用户功能": "User functions", - "© 2024 版权所有, 开元云(北京)科技有限公司": "©2024 Open Computing AI", - "上位系统": "Up Application", - "下位系统": "Down Application", - "下位系统apikey": "Down App key", - "下位系统接口": "Down API", - "产品管理": "Product Mgr", - "供应协议": "Supply Agreement", - "供应商模型列表": "Llms by Supplier", - "元境平台": "YuanJing Platform", - "分销协议": "Distribution Agreement", - "套餐管理": "Package Mgr", - "套餐选择": "Package Options", - "定价管理": "Pricing Mgr", - "定价类型": "Pricing type", - "定价项目": "Pricing program", - "我的知识库": "My Rags", - "接口输入输出": "API input", - "接口集": "API set", - "服务目录": "Service catelog", - "服务管理": "Service Mgr", - "服务选择": "Service Options", - "服务配置": "Service Config", - "模型": "LLM maintain", - "模型列表": "LLM list", - "模型用量": "Llm Usage", - "模型管理": "LLm Mgr", - "模型类型": "Llm type", - "添加供应商": "Add supplier", - "爬取配置": "Crawle config", - "用户管理": "User Mgr", - "知识库加持大模型": "Rags based LLM", - "知识库管理": "Rags Mgr", - "知识获取": "Knowledge acquistion", - "网上知识源": "Knowledge resource on network", - "设备组": "Device group", - "配置": "Configuration", - "进入主菜单": "call main menu" -} diff --git a/wwwroot/i18n/jp/i18n.json b/wwwroot/i18n/jp/i18n.json deleted file mode 100644 index 2c63c085..00000000 --- a/wwwroot/i18n/jp/i18n.json +++ /dev/null @@ -1,2 +0,0 @@ -{ -} diff --git a/wwwroot/i18n/ko/i18n.json b/wwwroot/i18n/ko/i18n.json deleted file mode 100644 index 2c63c085..00000000 --- a/wwwroot/i18n/ko/i18n.json +++ /dev/null @@ -1,2 +0,0 @@ -{ -} diff --git a/wwwroot/i18n/langs.dspy b/wwwroot/i18n/langs.dspy index 3e85efc3..f169166e 100644 --- a/wwwroot/i18n/langs.dspy +++ b/wwwroot/i18n/langs.dspy @@ -10,6 +10,7 @@ return [ { "value":"jp", "text":"日本语" + }, { "value":"ko", diff --git a/wwwroot/i18n/language.svg b/wwwroot/i18n/language.svg new file mode 100644 index 00000000..1226e8e6 --- /dev/null +++ b/wwwroot/i18n/language.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/wwwroot/i18n/language.ui b/wwwroot/i18n/language.ui index e166b481..c7923d67 100644 --- a/wwwroot/i18n/language.ui +++ b/wwwroot/i18n/language.ui @@ -1,4 +1,5 @@ { + "id":"language", "widgettype":"Text", "options":{ diff --git a/wwwroot/i18n/menu.ui b/wwwroot/i18n/menu.ui index 03ed878f..6f78c5ac 100644 --- a/wwwroot/i18n/menu.ui +++ b/wwwroot/i18n/menu.ui @@ -1,5 +1,7 @@ { + "widgettype":"Menu", + "options":{ "cwidth":11, "target":"app", diff --git a/wwwroot/i18n/zh/i18n.json b/wwwroot/i18n/zh/i18n.json deleted file mode 100644 index b9441002..00000000 --- a/wwwroot/i18n/zh/i18n.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "Destroy this window":"销毁窗口", - "fullscreen this window":"全屏", - "minimize this window":"最小化", - "change UI language":"改变界面语言", - "Add record":"增加记录", - "add new record":"增加新记录", - "update selected record":"修改选定记录", - "clone selected record":"克隆选定记录", - "delete selected record":"删除选定记录", - "show all the closed window": "显示所有最小化的窗口", - "Submit":"提交", - "You need login to use llm":"请先登录", - "Not enrogh balance to use llm":"您余额不足以运行此模型", - "Cancel":"放弃", - "Reset":"重置", - "zh":"中文", - "en":"English", - "jp":"日本语", - "ko":"韩语" -} diff --git a/wwwroot/i18n_getmsgs.dspy b/wwwroot/i18n_getmsgs.dspy new file mode 100644 index 00000000..4bd8ba55 --- /dev/null +++ b/wwwroot/i18n_getmsgs.dspy @@ -0,0 +1,14 @@ +import json +import os + +lang = params.get('lang', 'zh') +i18n_dir = os.path.join(os.path.dirname(__file__), 'i18n', lang) +i18n_file = os.path.join(i18n_dir, 'i18n.json') + +if os.path.exists(i18n_file): + with open(i18n_file, 'r', encoding='utf-8') as f: + msgs = json.load(f) +else: + msgs = {} + +return json.dumps(msgs, ensure_ascii=False) diff --git a/wwwroot/imgs/coins.svg b/wwwroot/imgs/coins.svg new file mode 100644 index 00000000..7c55e689 --- /dev/null +++ b/wwwroot/imgs/coins.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/wwwroot/imgs/copy.svg b/wwwroot/imgs/copy.svg new file mode 100644 index 00000000..a71aa39f --- /dev/null +++ b/wwwroot/imgs/copy.svg @@ -0,0 +1 @@ + diff --git a/wwwroot/imgs/cubes.svg b/wwwroot/imgs/cubes.svg new file mode 100644 index 00000000..d681d313 --- /dev/null +++ b/wwwroot/imgs/cubes.svg @@ -0,0 +1,3 @@ + + + diff --git a/wwwroot/imgs/dashboard.svg b/wwwroot/imgs/dashboard.svg new file mode 100644 index 00000000..17373c45 --- /dev/null +++ b/wwwroot/imgs/dashboard.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/wwwroot/imgs/delete.svg b/wwwroot/imgs/delete.svg new file mode 100644 index 00000000..8ac37e00 --- /dev/null +++ b/wwwroot/imgs/delete.svg @@ -0,0 +1 @@ + diff --git a/wwwroot/imgs/edit.svg b/wwwroot/imgs/edit.svg new file mode 100644 index 00000000..8353cb57 --- /dev/null +++ b/wwwroot/imgs/edit.svg @@ -0,0 +1 @@ + diff --git a/wwwroot/imgs/globe.svg b/wwwroot/imgs/globe.svg new file mode 100644 index 00000000..415cd389 --- /dev/null +++ b/wwwroot/imgs/globe.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/wwwroot/imgs/key.svg b/wwwroot/imgs/key.svg new file mode 100644 index 00000000..28ba15e4 --- /dev/null +++ b/wwwroot/imgs/key.svg @@ -0,0 +1,3 @@ + + + diff --git a/wwwroot/imgs/msp.svg b/wwwroot/imgs/msp.svg new file mode 100644 index 00000000..0c3dbeb6 --- /dev/null +++ b/wwwroot/imgs/msp.svg @@ -0,0 +1,10 @@ + + + + + + + + + S + diff --git a/wwwroot/imgs/newkey.svg b/wwwroot/imgs/newkey.svg new file mode 100644 index 00000000..a2baae7f --- /dev/null +++ b/wwwroot/imgs/newkey.svg @@ -0,0 +1 @@ + diff --git a/wwwroot/imgs/percent.svg b/wwwroot/imgs/percent.svg new file mode 100644 index 00000000..6256c3e3 --- /dev/null +++ b/wwwroot/imgs/percent.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/wwwroot/imgs/rocket.svg b/wwwroot/imgs/rocket.svg new file mode 100644 index 00000000..797152db --- /dev/null +++ b/wwwroot/imgs/rocket.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/wwwroot/imgs/setting.svg b/wwwroot/imgs/setting.svg new file mode 100644 index 00000000..8f4f1445 --- /dev/null +++ b/wwwroot/imgs/setting.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/wwwroot/imgs/user-circle.svg b/wwwroot/imgs/user-circle.svg new file mode 100644 index 00000000..3aa9001a --- /dev/null +++ b/wwwroot/imgs/user-circle.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/wwwroot/imgs/userrole.svg b/wwwroot/imgs/userrole.svg new file mode 100644 index 00000000..21536e36 --- /dev/null +++ b/wwwroot/imgs/userrole.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/wwwroot/imgs/users.svg b/wwwroot/imgs/users.svg new file mode 100644 index 00000000..49d2509d --- /dev/null +++ b/wwwroot/imgs/users.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/wwwroot/index.ui b/wwwroot/index.ui index 2cbe9385..761ddde2 100644 --- a/wwwroot/index.ui +++ b/wwwroot/index.ui @@ -1,27 +1,191 @@ { - "widgettype":"VBox", - "options":{ - "width":"100%", - "height":"100%" - }, - "subwidgets":[ - { - "widgettype":"urlwidget", - "options":{ - "url":"{{entire_url('top.ui')}}" - } - }, - { - "widgettype":"urlwidget", - "options":{ - "url":"{{entire_url('center.ui')}}" - } - }, - { - "widgettype":"urlwidget", - "options":{ - "url":"{{entire_url('bottom.ui')}}" - } - } - ] + "widgettype": "VBox", + "options": { + "css": "sage-shell", + "width": "100%", + "height": "100%" + }, + "subwidgets": [ + { + "widgettype": "HBox", + "options": { + "css": "sage-topbar", + "width": "100%", + "height": "56px", + "padding": "0 16px", + "alignItems": "center" + }, + "subwidgets": [ + { + "widgettype": "Button", + "id": "sidebar_toggle_btn", + "options": { + "css": "sidebar-toggle", + "label": "", + "width": "36px", + "height": "36px", + "padding": "0" + }, + "binds": [ + { + "wid": "self", + "event": "click", + "actiontype": "script", + "target": "self", + "script": "sageToggleSidebar()" + } + ] + }, + { + "widgettype": "Svg", + "id": "tenant_logo", + "options": { + "css": "sage-logo", + "rate": 2, + "url": "{{entire_url('/imgs/ocai.svg')}}" + } + }, + { + "widgettype": "Title4", + "id": "tenant_brand_title", + "options": { + "css": "sage-brand-title", + "text": "元境", + "fontWeight": "bold", + "marginLeft": "8px" + } + }, + { + "widgettype": "Filler" + }, + { + "widgettype": "Button", + "id": "theme_toggle_btn", + "options": { + "css": "theme-toggle", + "label": "", + "width": "36px", + "height": "36px", + "padding": "0" + }, + "binds": [ + { + "wid": "self", + "event": "click", + "actiontype": "script", + "target": "self", + "script": "sageToggleTheme()" + } + ] + }, + { + "widgettype": "urlwidget", + "options": { + "url": "{{entire_url('i18n/language.ui')}}" + } + }, + { + "widgettype": "Svg", + "options": { + "css": "clickable", + "rate": 2, + "tip": "显示所有已最小化的窗口", + "url": "{{entire_url('/bricks/imgs/app-dock.svg')}}" + }, + "binds": [ + { + "wid": "self", + "event": "click", + "actiontype": "script", + "target": "app", + "script": "bricks.app.show_windows_panel(event)" + } + ] + }, + { + "widgettype": "urlwidget", + "options": { + "url": "{{entire_url('/rbac/user/user_panel.ui')}}" + } + } + ], + "binds": [ + { + "wid": "app", + "event": "user_logined", + "actiontype": "script", + "target": "self", + "script": "fetch('{{entire_url('/tenant_brand_data.dspy')}}').then(r=>r.json()).then(d=>{var l=bricks.getWidgetById('tenant_logo',bricks.app);if(l&&d.iconid)l.opts.url='{{entire_url('/appbase/show_icon.dspy')}}?id='+d.iconid;l.refresh();var t=bricks.getWidgetById('tenant_brand_title',bricks.app);if(t)t.opts.text=d.orgname;t.refresh();})" + } + ] + }, + { + "widgettype": "HBox", + "options": { + "width": "100%", + "height": "calc(100% - 56px)" + }, + "subwidgets": [ + { + "widgettype": "VBox", + "id": "sage_sidebar", + "options": { + "css": "sage-sidebar", + "width": "240px", + "height": "100%" + }, + "subwidgets": [ + { + "widgettype": "urlwidget", + "options": { + "url": "{{entire_url('global_menu.ui')}}" + } + } + ], + "binds": [ + { + "wid": "app", + "event": "user_logined", + "actiontype": "script", + "target": "self", + "script": "sageReloadMenu()" + }, + { + "wid": "app", + "event": "sage_logout", + "actiontype": "script", + "target": "self", + "script": "sageReloadMenu()" + } + ] + }, + { + "widgettype": "VBox", + "id": "sage_main_content", + "options": { + "css": "sage-main", + "height": "100%", + "padding": "24px" + }, + "binds": [ + { + "wid": "app", + "event": "user_logined", + "actiontype": "script", + "target": "self", + "script": "sageOnLogin('{{entire_url('/sage_datamart/index.ui')}}')" + } + ], + "subwidgets": [ + { + "widgettype": "urlwidget", + "options": { + "url": "{{entire_url('/sage_datamart/index.ui')}}" + } + } + ] + } + ] + } + ] } diff --git a/wwwroot/index_carousel.ui b/wwwroot/index_carousel.ui new file mode 100644 index 00000000..a2bc47ab --- /dev/null +++ b/wwwroot/index_carousel.ui @@ -0,0 +1,11 @@ +{ + "id": "app", "widgettype": "VBox", + "options": {"css": "filler", "width": "100%", "height": "100%", "padding": "0", "overflow": "auto"}, + "subwidgets": [ + {"widgettype": "urlwidget", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/index_zh.ui')}}"} + } + ], + "binds": [{"wid": "app", "event": "ready", "actiontype": "script", + "script": "var l=localStorage.getItem('hermes-lang');if(l&&l!=='zh')location.href='/tokentest.opencomputing.cn/index_'+l+'.ui';var t=document.createElement('script');t.src='{{entire_url('/tokentest.opencomputing.cn/theme.js')}}';document.head.appendChild(t);var s=document.createElement('script');s.src='{{entire_url('/tokentest.opencomputing.cn/carousel.js')}}';document.head.appendChild(s);var sort=document.createElement('script');sort.src='{{entire_url('/tokentest.opencomputing.cn/Sortable.min.js')}}';document.head.appendChild(sort);" + }] +} diff --git a/wwwroot/lnmodules.sh b/wwwroot/lnmodules.sh index d9038574..6e5c8d44 100755 --- a/wwwroot/lnmodules.sh +++ b/wwwroot/lnmodules.sh @@ -1,6 +1,5 @@ #!/bin/sh -for m in appbase accounting rbac platformbiz basellm do echo $m rm $m diff --git a/wwwroot/lnwww.sh b/wwwroot/lnwww.sh index 040dd47e..7ad581ee 100644 --- a/wwwroot/lnwww.sh +++ b/wwwroot/lnwww.sh @@ -1,5 +1,4 @@ -for m in accounting appbase basellm filemgr msp pf_pay platformbiz rag rbac sage sqlor uapi do ln -s ~/py/$m/wwwroot $m done diff --git a/wwwroot/menu.ui b/wwwroot/menu.ui index 9a9fc99d..bb1fe615 100644 --- a/wwwroot/menu.ui +++ b/wwwroot/menu.ui @@ -10,10 +10,25 @@ "label": "主页", "url": "{{entire_url('public')}}" }, + { + "name": "dashboard", + "label": "数据看板", + "url": "{{entire_url('/dashboard_for_sage')}}" + }, + { + "name": "hotspot", + "label": "热点雷达", + "url": "{{entire_url('hotspot')}}" + }, { "name": "agent", - "label": "智能体", - "url": "{{entire_url('skillagent')}}" + "label": "代理", + "submenu": "{{entire_url('/harnessed_agent/menu.ui')}}" + }, + { + "name": "reasoning", + "label": "推理", + "submenu": "{{entire_url('/harnessed_reasoning/menu.ui')}}" }, { "name": "pricing", @@ -25,11 +40,6 @@ "label": "模型管理", "submenu": "{{entire_url('/llmage/menu.ui')}}" }, - { - "name": "rag", - "label": "知识库管理", - "submenu": "{{entire_url('/rag/menu.ui')}}" - }, { "name": "upapp", "label": "上位系统", @@ -103,6 +113,22 @@ "name": "permission", "label": "权限管理", "url": "{{entire_url('rbac/permission')}}" + }, + { + "name": "rbac_tools", + "label": "RBAC工具", + "items":[ + { + "name": "list_path_roles", + "label": "查询路径权限角色", + "url": "{{entire_url('rbac/list_path_roles.ui')}}" + }, + { + "name": "find_unauth_files", + "label": "扫描未授权文件", + "url": "{{entire_url('rbac/find_unauth_files.dspy')}}" + } + ] } {% endif %} {% if 'reseller.operator' in roles or 'customer.operator' in roles or 'owner.operator' in roles %} @@ -132,12 +158,10 @@ ,{ "name": "prodtype", "label": "产品类型管理", - "url": "{{entire_url('/platformbiz/prodtype')}}" }, { "name": "prodtypespec", "label": "产品类型规格", - "url": "{{entire_url('/platformbiz/prodtypespec')}}" } {% endif %} {% if 'provider.operator' in roles %} @@ -145,12 +169,10 @@ { "name": "product", "label": "产品管理", - "url": "{{entire_url('/platformbiz/product')}}" } ,{ "name": "reseller", "label": "分销协议", - "url": "{{entire_url('/platformbiz/retail_agree')}}" } {% endif %} {% if 'reseller.operator' in roles or 'customer.operator' in roles %} @@ -158,34 +180,21 @@ { "name": "addprovider", "label": "添加供应商", - "url": "{{entire_url('/platformbiz/add_provider.ui')}}" + "url": "{{entire_url('/rbac/add_provider.ui')}}" }, { "name": "providermgr", "label": "供应协议", - "url": "{{entire_url('/platformbiz/provide_agree')}}" }, { "name": "product", "label": "产品管理", - "url": "{{entire_url('/platformbiz/product')}}" } {% endif %} - ,{ - "name": "hotspot", - "label": "热点雷达", - "url": "{{entire_url('hotspot')}}" - }, - { - "name": "skillmgr", - "label": "技能管理", - "submenu": "{{entire_url('/skillagent/menu.ui')}}" - } {% if 'reseller.sale' in roles %} ,{ "name": "reseller", "label": "分销协议", - "url": "{{entire_url('/platformbiz/retail_agree')}}" } {% endif %} {% if 'custmer.admin' in roles or 'reseller.admin' in roles %} diff --git a/wwwroot/public/api/api_en.md b/wwwroot/public/api/api_en.md new file mode 100644 index 00000000..38dcbb0d --- /dev/null +++ b/wwwroot/public/api/api_en.md @@ -0,0 +1,392 @@ +# Yuanjing Platform API + +Yuanjing Platform provides downstream systems with an API compatible with the OpenAI interface protocol. To enable the API, downstream systems need to follow these steps: +* Register an account +* Log in +* Apply for APIKEY +* Recharge (Top-up) + +After completing the above steps, you can implement inference services for Text-to-Text, Text-to-Video, Image-to-Video, and Reference-to-Video according to the following examples. + +For models supported by the Yuanjing platform, please refer to the Model Square. + +## Apply for APIKEY + +Users need to log in via mobile on the Yuanjing platform (https://ai.opencomputing.cn) and click "Create APIKEY". + +Enter the information and click submit, and the APIKEY creation is complete. + +Click "Copy apikey", see the apikey in the pop-up window, and copy it. + +## Recharge +Users need to recharge on the Yuanjing platform. Currently, Alipay is supported. + +## View Current Balance + +* User Login +* Call up user menu +* Click "Finance" + +## API Base URL +https://opencomputing.ai + +## OpenAI Compatible Interface +We provide a set of APIs compatible with OpenAI. + +### Text Generation +* path: /llmage/v1/chat/completions +* method: 'POST' +* headers +``` +{ + "Content-Type": "application/json", + "Authorization": "Bearer " # APIKEY applied by the customer from the Yuanjing platform +} +``` +* data +{ + "model": # Model ID, the name provided by the supplier + "prompt": # Prompt, must be entered + "sys_prompt" # System prompt, optional + "stream" # Stream output switch + "..." # Other prompts +} + +* Return +Streaming or non-streaming results conforming to the OpenAI protocol. + +* Streaming: +``` +./oc.curl 你是谁 +data: {"id": "chatcmpl-2665dfd8-e05f-9d7f-adff-3c53c174a454", "object": "chat.completion.chunk", "created": 1775019761, "choices": [{"logprobs": null, "index": 0, "delta": {"content": "", "role": "assistant"}}], "model": "qwen3-max", "reasoning_content": null, "content": "", "finish": "0", "llmusageid": "K9_veNBxeqvrFfbGWXs0R"} +data: {"id": "chatcmpl-2665dfd8-e05f-9d7f-adff-3c53c174a454", "object": "chat.completion.chunk", "created": 1775019761, "choices": [{"delta": {"content": "\u6211\u662f", "role": null}, "index": 0}], "model": "qwen3-max", "reasoning_content": null, "content": "\u6211\u662f", "finish": "0", "llmusageid": "K9_veNBxeqvrFfbGWXs0R"} +data: {"id": "chatcmpl-2665dfd8-e05f-9d7f-adff-3c53c174a454", "object": "chat.completion.chunk", "created": 1775019761, "choices": [{"delta": {"content": "\u901a\u4e49\u5343", "role": null}, "index": 0}], "model": "qwen3-max", "reasoning_content": null, "content": "\u901a\u4e49\u5343", "finish": "0", "llmusageid": "K9_veNBxeqvrFfbGWXs0R"} +data: {"id": "chatcmpl-2665dfd8-e05f-9d7f-adff-3c53c174a454", "object": "chat.completion.chunk", "created": 1775019761, "choices": [{"delta": {"content": "\u95ee\uff0c\u963f\u91cc\u5df4\u5df4\u96c6\u56e2\u65d7\u4e0b\u7684", "role": null}, "index": 0}], "model": "qwen3-max", "reasoning_content": null, "content": "\u95ee\uff0c\u963f\u91cc\u5df4\u5df4\u96c6\u56e2\u65d7\u4e0b\u7684", "finish": "0", "llmusageid": "K9_veNBxeqvrFfbGWXs0R"} +data: {"id": "chatcmpl-2665dfd8-e05f-9d7f-adff-3c53c174a454", "object": "chat.completion.chunk", "created": 1775019761, "choices": [{"delta": {"content": "\u8d85\u5927\u89c4\u6a21\u8bed\u8a00\u6a21\u578b\u3002\u6211\u80fd\u591f", "role": null}, "index": 0}], "model": "qwen3-max", "reasoning_content": null, "content": "\u8d85\u5927\u89c4\u6a21\u8bed\u8a00\u6a21\u578b\u3002\u6211\u80fd\u591f", "finish": "0", "llmusageid": "K9_veNBxeqvrFfbGWXs0R"} +data: {"id": "chatcmpl-2665dfd8-e05f-9d7f-adff-3c53c174a454", "object": "chat.completion.chunk", "created": 1775019761, "choices": [{"delta": {"content": "\u56de\u7b54\u95ee\u9898\u3001\u521b\u4f5c\u6587\u5b57\uff0c", "role": null}, "index": 0}], "model": "qwen3-max", "reasoning_content": null, "content": "\u56de\u7b54\u95ee\u9898\u3001\u521b\u4f5c\u6587\u5b57\uff0c", "finish": "0", "llmusageid": "K9_veNBxeqvrFfbGWXs0R"} +data: {"id": "chatcmpl-2665dfd8-e05f-9d7f-adff-3c53c174a454", "object": "chat.completion.chunk", "created": 1775019761, "choices": [{"delta": {"content": "\u6bd4\u5982\u5199\u6545\u4e8b\u3001\u5199\u516c", "role": null}, "index": 0}], "model": "qwen3-max", "reasoning_content": null, "content": "\u6bd4\u5982\u5199\u6545\u4e8b\u3001\u5199\u516c", "finish": "0", "llmusageid": "K9_veNBxeqvrFfbGWXs0R"} +data: {"id": "chatcmpl-2665dfd8-e05f-9d7f-adff-3c53c174a454", "object": "chat.completion.chunk", "created": 1775019761, "choices": [{"delta": {"content": "\u6587\u3001\u5199\u90ae\u4ef6\u3001\u5199\u5267\u672c", "role": null}, "index": 0}], "model": "qwen3-max", "reasoning_content": null, "content": "\u6587\u3001\u5199\u90ae\u4ef6\u3001\u5199\u5267\u672c", "finish": "0", "llmusageid": "K9_veNBxeqvrFfbGWXs0R"} +data: {"id": "chatcmpl-2665dfd8-e05f-9d7f-adff-3c53c174a454", "object": "chat.completion.chunk", "created": 1775019761, "choices": [{"delta": {"content": "\u3001\u903b\u8f91\u63a8\u7406\u3001\u7f16\u7a0b\u7b49\u7b49", "role": null}, "index": 0}], "model": "qwen3-max", "reasoning_content": null, "content": "\u3001\u903b\u8f91\u63a8\u7406\u3001\u7f16\u7a0b\u7b49\u7b49", "finish": "0", "llmusageid": "K9_veNBxeqvrFfbGWXs0R"} +data: {"id": "chatcmpl-2665dfd8-e05f-9d7f-adff-3c53c174a454", "object": "chat.completion.chunk", "created": 1775019761, "choices": [{"delta": {"content": "\uff0c\u8fd8\u80fd\u8868\u8fbe\u89c2\u70b9\uff0c\u73a9\u6e38\u620f", "role": null}, "index": 0}], "model": "qwen3-max", "reasoning_content": null, "content": "\uff0c\u8fd8\u80fd\u8868\u8fbe\u89c2\u70b9\uff0c\u73a9\u6e38\u620f", "finish": "0", "llmusageid": "K9_veNBxeqvrFfbGWXs0R"} +data: {"id": "chatcmpl-2665dfd8-e05f-9d7f-adff-3c53c174a454", "object": "chat.completion.chunk", "created": 1775019761, "choices": [{"delta": {"content": "\u7b49\u3002\u5982\u679c\u4f60\u6709\u4efb\u4f55\u95ee\u9898\u6216", "role": null}, "index": 0}], "model": "qwen3-max", "reasoning_content": null, "content": "\u7b49\u3002\u5982\u679c\u4f60\u6709\u4efb\u4f55\u95ee\u9898\u6216", "finish": "0", "llmusageid": "K9_veNBxeqvrFfbGWXs0R"} +data: {"id": "chatcmpl-2665dfd8-e05f-9d7f-adff-3c53c174a454", "object": "chat.completion.chunk", "created": 1775019761, "choices": [{"delta": {"content": "\u9700\u8981\u5e2e\u52a9\uff0c\u6b22\u8fce\u968f\u65f6\u544a\u8bc9\u6211", "role": null}, "index": 0}], "model": "qwen3-max", "reasoning_content": null, "content": "\u9700\u8981\u5e2e\u52a9\uff0c\u6b22\u8fce\u968f\u65f6\u544a\u8bc9\u6211", "finish": "0", "llmusageid": "K9_veNBxeqvrFfbGWXs0R"} +data: {"id": "chatcmpl-2665dfd8-e05f-9d7f-adff-3c53c174a454", "object": "chat.completion.chunk", "created": 1775019761, "choices": [{"delta": {"content": "\uff01", "role": null}, "index": 0}], "model": "qwen3-max", "reasoning_content": null, "content": "\uff01", "finish": "0", "llmusageid": "K9_veNBxeqvrFfbGWXs0R"} +data: {"id": "chatcmpl-2665dfd8-e05f-9d7f-adff-3c53c174a454", "object": "chat.completion.chunk", "created": 1775019761, "choices": [{"delta": {"content": "", "role": null}, "index": 0, "finish_reason": "stop"}], "model": "qwen3-max", "reasoning_content": null, "content": "", "finish": "0", "llmusageid": "K9_veNBxeqvrFfbGWXs0R"} +data: {"id": "chatcmpl-2665dfd8-e05f-9d7f-adff-3c53c174a454", "object": "chat.completion.chunk", "created": 1775019761, "choices": [], "model": "qwen3-max", "finish": "1", "usage": {"total_tokens": 70, "completion_tokens": 60, "prompt_tokens": 10, "prompt_tokens_details": {"cached_tokens": 0}}, "llmusageid": "K9_veNBxeqvrFfbGWXs0R"} +data: [DONE] +``` + +* Non-streaming +``` +./oc.curl 你是谁 +{"id": "chatcmpl-eea7abb9-24d5-9f70-b6f6-d7da4f22a8b8", "object": "chat.completion", "created": 1775011902, "choices": [{"finish_reason": "stop", "index": 0, "message": {"content": "我是通义千问,阿里巴巴集团旗下的超大规模语言模型。我能够回答问题、创作文字,比如写故事、写公文、写邮件、写剧本、逻辑推理、编程等等,还能表达观点,玩游戏等。如果你有任何问题或需要帮助,欢迎随时告诉我!", "role": "assistant"}}], "model": "qwen3-max", "reasoning_content": null, "content": "我是通义千问,阿里巴巴集团旗下的超大规模语言模型。我能够回答问题、创作文字,比如写故事、写公文、写邮件、写剧本、逻辑推理、编程等等,还能表达观点,玩游戏等。如果你有任何问题或需要帮助,欢迎随时告诉我!", "finish": "1", "usage": {"completion_tokens": 60, "prompt_tokens": 10, "prompt_tokens_details": {"cached_tokens": 0}, "total_tokens": 70}} +``` + +## Text-to-Video +Currently supported: +| Model ID | Provider | Model Name | +|--------|--------|--------| +| o5vfXYD5BURJWRTWpopE5 | Alibaba Cloud | happyhorse-1.0-t2v | +| YjjGgxO_Xma8PWsMjJvps | Doubao | doubao-seedance-2-0-260128 | +| TWay-xd0p0pkEX-_Kuhto | We Token AI | dreamina-seedance-2-0-260128(*), dreamina-seedance-2-0-fast-260128 | +| CrEMkFQfRCmbmopZsCqLj | Doubao | doubao-seedance-1-5-pro-251215 | +| CrEMkFQfRCmbmopZsCqLj | Doubao | doubao-seedance-1-5-pro-251215 | +| u9HZyfDoqU6uKI6M1BTks | Tongyi Wanxiang | wan2.6-t2v | +| r0ill7L0s6PtBS8mkmg-7 | vidu | viduq3-pro | +| YjjGgxO_Xma8PWsMjJvps | Doubao | eedance2.0 (Not enabled)| + +### happyhorse-1.0-t2v Upload Data Requirements +| Field (Name) | Type | Required | Default | Description | +| :--- | :--- | :--- | :--- | :--- | +| llmid | Model ID | Yes | - | - | +| model | Model Name | No | happyhorse-1.0-t2v | - | +| prompt | string | Yes | - | Prompt words. Used to describe the video content you want to generate. | +| resolution | string | No | `720p` | Video size. Specify the resolution of the generated video.
Optional values:
`480p`, `720p`, `1080p` | +| ratio | string | No | adaptive | Optional: adaptive, 16:9, 4:3, 1:1, 3:4, 9:16, 21:9 | +| duration | integer | No | `5` | Video duration. Specify the length of the generated video (seconds).
Optional values: integer seconds | + +### seedance 2.0 Upload Data Requirements +| Field (Name) | Type | Required | Default | Description | +| :--- | :--- | :--- | :--- | :--- | +| llmid | Model ID | Yes | - | - | +| model | Model Name | No | doubao-seedance-2-0-260128 | doubao-seedance-2-0-260128 or doubao-seedance-2-0-fast-260128 | +| prompt | string | Yes | - | Prompt words. Used to describe the video content you want to generate. | +| resolution | string | No | `720p` | Video size. Specify the resolution of the generated video.
Optional values:
`480p`, `720p`, `1080p` | +| ratio | string | No | adaptive | Optional: adaptive, 16:9, 4:3, 1:1, 3:4, 9:16, 21:9 | +| duration | integer | No | `5` | Video duration. Specify the length of the generated video (seconds).
Optional values: integer seconds | + +### Wanxiang Upload Data Requirements +| Field (Name) | Type | Required | Default | Description | +| :--- | :--- | :--- | :--- | :--- | +| llmid | Model ID | Yes | - | - | +| model | Model Name | No | (Starred) | - | +| prompt | string | Yes | - | Prompt words. Used to describe the video content you want to generate. | +| negative_prompt | string | No | (empty) | Negative prompt words. Used to describe content you want to avoid in the video. | +| size | string | No | `1920*1080` | Video size. Specify the resolution of the generated video.
Optional values:
`832*480`, `480*832`, `624*624`, `1280*720`, `720*1280`, `960*960`, `1088*832`, `832*1088`, `1920*1080`, `1080*1920`, `1440*1440`, `1632*1248`, `1248*1632` | +| duration | integer | No | `15` | Video duration. Specify the length of the generated video (seconds).
Optional values:
`5`, `10`, `15` | + +### Vidu Upload Parameters +| Field (Name) | Type | Required | Default | Description | +| :--- | :--- | :--- | :--- | :--- | +| llmid | Model ID | Yes | - | - | +| prompt | string | Yes | - | Prompt words. Used to describe the content of the generated video. | +| off_peak | string | No | `N` | Off-peak execution. Whether to enable non-peak hour generation.
Optional values: `Y` (Yes), `N` (No) | +| duration | integer | No | `10` | Video length. The duration of the generated video (seconds).
Range: 1-16 seconds (according to field description) | +| ratio | string | No | `16:9` | Aspect ratio. Specify the video's picture ratio.
Optional values:
`16:9`, `9:16`, `4:3`, `3:4`, `1:1` | +| resolution | string | No | `1080p` | Resolution. Specify the clarity of the generated video.
Optional values:
`540p`, `720p`, `1080p` | + +### Seedance Upload Data Requirements +| Field | Type | Required | Default | Description | +| :--- | :--- | :--- | :--- | :--- | +| llmid | Model ID | Yes | - | - | +| prompt | string | Yes | - | Prompt words. Describe the content of the generated video. | +| radio | string | No | - | Aspect ratio. Specify the aspect ratio of the video.
Optional values:
`16:9`, `keep_ratio`, `4:3`, `1:1`, `3:4`, `9:16`, `9:21`, `21:9`, `adaptive` | +| resolution | string | No | `1080p` | Resolution. Specify video clarity.
Optional values:
`480p`, `720p`, `1080p` | +| duration | integer | No | `12` | Video length. Video duration (seconds). | + +### Example +Example using seedance: +``` +#!/usr/bin/env bash +curl -X POST https://opencomputing.ai/llmage/video \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer Optional values:
`720P`, `1080P` | +| duration | integer | No | `5` | Video duration. Specify the length of the generated video (seconds).
Optional values: integer seconds | + +Example: +``` +#!/usr/bin/env bash +curl -X POST https://opencomputing.ai/llmage/video \ + -H "Authorization: Bearer " \ + -F "llmid=o5vfXYD5BURJWRTWpopE5" \ + -F "prompt=一起来调科目三" \ + -F "duration=15" \ + -F "resolution=720P" \ + -F "image1_file=@./02.jpg" +``` + +### seedance 2.0 Upload Data Requirements +| Field (Name) | Type | Required | Default | Description | +| :--- | :--- | :--- | :--- | :--- | +| llmid | Model ID | Yes | - | - | +| model | Model Name | No | doubao-seedance-2-0-260128 | doubao-seedance-2-0-260128 or doubao-seedance-2-0-fast-260128 | +| prompt | string | Yes | - | Prompt words. Describe the video content you want to generate. | +| image1_file | image file | Yes | - | First frame image. | +| image2_file | image file | Yes | - | Last frame image. | +| resolution | string | No | `720p` | Video size. Specify video resolution.
Optional values:
`480p`, `720p`, `1080p` | +| ratio | string | No | adaptive | Optional: adaptive, 16:9, 4:3, 1:1, 3:4, 9:16, 21:9 | +| duration | integer | No | `5` | Video duration. Specify generated video length (seconds). | + +### Tongyi Wanxiang Upload Data Requirements +| Field (Name) | Type | Required | Default | Description | +| :--- | :--- | :--- | :--- | :--- | +| llmid | Model ID | Yes | - | - | +| prompt | string | Yes | - | Prompt words. | +| negative_prompt | string | No | (empty) | Negative prompt words. | +| size | string | No | `1920*1080` | Video size.
Optional: `1280*720`, etc. | +| duration | integer | No | `15` | Video length.
Optional: `5`, `10`, `15` | +| image_file1 | string/file | Yes | - | First frame image. (URL or Base64). | +| image_file2 | string/file | Yes | - | Last frame image. (URL or Base64). | + +### Vidu Upload Data Requirements +| Field (Name) | Type | Required | Default | Description | +| :--- | :--- | :--- | :--- | :--- | +| llmid | Model ID | Yes | - | - | +| model | string | No | `viduq3-pro` | Model version.
Optional: `viduq2-turbo`, `viduq3-pro` | +| prompt | string | Yes | - | Prompt text. | +| off_peak | string | No | `N` | Off-peak execution. `Y` (Yes), `N` (No) | +| image_file1 | string/file | Yes | - | First frame image. | +| image_file2 | string/file | Yes | - | Last frame image. | +| duration | integer | No | `10` | Video length. 1-16 seconds. | +| ratio | string | No | `16:9` | Aspect ratio. | +| resolution | string | No | `1080p` | Resolution. | + +### Seedance 1.5 Upload Data Requirements +| Field | Type | Required | Default | Description | +| :--- | :--- | :--- | :--- | :--- | +| llmid | Model ID | Yes | - | - | +| prompt | string | Yes | - | Prompt text describing the video content. | +| radio | string | No | - | Aspect ratio. | +| resolution | string | No | `1080p` | Resolution. | +| duration | integer | No | `12` | Video length (seconds). | +| image_file1 | string | No | - | First frame image. | +| image_file2 | string | No | - | Last frame image. | + +Example using seedance 1.5: +``` +#!/usr/bin/env bash +curl -X POST https://opencomputing.ai/llmage/video \ + -H "Authorization: Bearer " # APIKEY applied by the customer from the Yuanjing platform +} +``` +* data +Except for llmid, different models require different data. Please refer to the upload data instructions. + +* Return +``` +{ + "taskid": # Task ID, used later to query execution results + "status": # Status includes: + # SUCCEEDED: Success + # FAILED: Failed + # CREATED: Created + # PENDING: Queued + # RUNNING: Running +} +``` + +Return example: +``` +{ + "taskid": "936759404378734592", + "status": "created" +} +``` + +### Example +seedance 2.0 Reference-to-Video +``` +curl -X POST https://opencomputing.ai/llmage/video \ + -H "Authorization: Bearer " \ + -F "llmid=dmPXF65TD1riKj9KaxLmg" \ + -F "model": "doubao-seedance-2-0-260128" \ + -F "image_files=@./1.jpg" \ + -F "image_files=@./2.jpg" \ + -F "prompt=平滑过度从第一张图片到第二张图片" \ + -F "ratio=4:3" \ + -F "resolution=720p" \ + -F "duration=4" +``` + +## Query Task Status +* path: /llmage/tasks +* method: GET +* headers +``` +{ + "Content-Type": "application/json", + "Authorization": "Bearer " # APIKEY applied from Yuanjing platform +} +``` +* params +``` +{ + "taskid": "936759404378734592" +} +``` +* Return +``` +{ + "status": # Status: SUCCEEDED, FAILED, CREATED, PENDING, RUNNING + "taskid": # Task number generated by the supplier; if failed, taskid is meaningless + "usage": # Valid when status==SUCCEEDED, billing information + "image": # Video cover URL + "video": # Video URL +} +``` + +Return example: +``` +{ + "usage": { # Billing varies by supplier and model + "action": "t2v", + "credits": 10, + "type": "text2video", + "model": "viduq3-pro", + "resolution": "540p", + "off_peak": false, + "duration": 1 + }, + "image": "https://opencomputing.ai/idfile?path=/tmp/19/43/137/39/cover.jpeg", + "video": "https://opencomputing.ai/idfile?path=/tmp/137/173/31/47/video.mp4", + "status": "SUCCEEDED" +} +``` + +### Example +``` +#!/usr/bin/env bash +curl -X POST https://opencomputing.ai/llmage/tasks?taskid= \ + -H "Authorization: Bearer " +``` + +## Error Information + +* 401: {"error": "Invalid API Key"} +* 400: {"error": "Missing required parameter: prompt"} +* 429: {"error": "Insufficient balance"} diff --git a/wwwroot/public/api/api_jp.md b/wwwroot/public/api/api_jp.md new file mode 100644 index 00000000..c4d049b3 --- /dev/null +++ b/wwwroot/public/api/api_jp.md @@ -0,0 +1,204 @@ +# 元境プラットフォーム API + +元境(Yuanjing)プラットフォームは、下位システム向けに OpenAI インターフェースプロトコルと互換性のある API を提供します。API を有効にするには、以下の手順に従ってください: +* アカウント登録 +* ログイン +* APIKEY の申請 +* チャージ(入金) + +上記の手順完了後、以下の例に従ってテキスト生成、テキストから動画(T2V)、画像から動画(I2V)、リファレンスから動画(R2V)の推論サービスを実装できます。 + +サポートされているモデルについては、「モデル広場(Model Square)」をご参照ください。 + +## APIKEY の申請 + +ユーザーは元境プラットフォーム(https://ai.opencomputing.cn)に携帯電話でログインし、「APIKEYの作成(创建APIKEY)」をクリックする必要があります。 + +情報を入力して送信すると、APIKEY の作成が完了します。 + +「apikeyをコピー(复制apikey)」をクリックし、ポップアップウィンドウに表示された APIKEY をコピーしてください。 + +## チャージ +ユーザーは元境プラットフォーム上でチャージを行う必要があります。現在、Alipay(支付宝)に対応しています。 + +## 現在の残高確認 + +* ユーザーログイン +* ユーザーメニューを呼び出す +* 「財務(财务)」をクリック + +## API ベース URL +https://opencomputing.ai + +## OpenAI 互換インターフェース +OpenAI と互換性のある一連の API を提供しています。 + +### テキスト生成 +* パス: /llmage/v1/chat/completions +* メソッド: 'POST' +* ヘッダー +``` +{ + "Content-Type": "application/json", + "Authorization": "Bearer " # 元境プラットフォームから申請したAPIKEY +} +``` +* データ +{ + "model": # モデル識別コード(プロバイダーから提供されたモデル名) + "prompt": # プロンプト(必須入力) + "sys_prompt" # システムプロンプト(任意) + "stream" # ストリーミング出力スイッチ + "..." # その他のパラメータ +} + +* レスポンス +OpenAI プロトコルに準拠したストリーミングまたは非ストリーミングの結果を返します。 + +* ストリーミング: +``` +./oc.curl 你是谁 +data: {"id": "chatcmpl-2665dfd8-e05f-9d7f-adff-3c53c174a454", "object": "chat.completion.chunk", "created": 1775019761, "choices": [{"logprobs": null, "index": 0, "delta": {"content": "", "role": "assistant"}}], "model": "qwen3-max", "reasoning_content": null, "content": "", "finish": "0", "llmusageid": "K9_veNBxeqvrFfbGWXs0R"} +... +data: [DONE] +``` + +* 非ストリーミング +``` +./oc.curl 你是谁 +{"id": "chatcmpl-eea7abb9-24d5-9f70-b6f6-d7da4f22a8b8", "object": "chat.completion", "created": 1775011902, "choices": [{"finish_reason": "stop", "index": 0, "message": {"content": "我是通义千问...", "role": "assistant"}}], "model": "qwen3-max", "usage": {"total_tokens": 70}} +``` + +## テキストから動画 (Text-to-Video) +現在サポートされているモデル: +| モデルID | プロバイダー | モデル名 | +|--------|--------|--------| +| o5vfXYD5BURJWRTWpopE5 | Alibaba Cloud | happyhorse-1.0-t2v | +| YjjGgxO_Xma8PWsMjJvps | Doubao | doubao-seedance-2-0-260128 | +| TWay-xd0p0pkEX-_Kuhto | We Token AI | dreamina-seedance-2-0-260128(*), dreamina-seedance-2-0-fast-260128 | +| CrEMkFQfRCmbmopZsCqLj | Doubao | doubao-seedance-1-5-pro-251215 | +| u9HZyfDoqU6uKI6M1BTks | Tongyi Wanxiang | wan2.6-t2v | +| r0ill7L0s6PtBS8mkmg-7 | vidu | viduq3-pro | + +### happyhorse-1.0-t2v アップロード要件 +| フィールド名 (Name) | タイプ | 必須 | デフォルト値 | 説明 | +| :--- | :--- | :--- | :--- | :--- | +| llmid | モデル番号 | はい | - | - | +| model | モデル名 | いいえ | happyhorse-1.0-t2v | - | +| prompt | string | はい | - | プロンプト。生成したい動画の内容を記述します。 | +| resolution | string | いいえ | `720p` | 動画サイズ(解像度)。
選択肢:
`480p`, `720p`, `1080p` | +| ratio | string | いいえ | adaptive | アスペクト比。選択肢: adaptive, 16:9, 4:3, 1:1, 3:4, 9:16, 21:9 | +| duration | integer | いいえ | `5` | 動画の長さ(秒)。
選択肢: 整数 | + +### seedance 2.0 アップロード要件 +| フィールド名 (Name) | タイプ | 必須 | デフォルト値 | 説明 | +| :--- | :--- | :--- | :--- | :--- | +| llmid | モデル番号 | はい | - | - | +| model | モデル名 | いいえ | doubao-seedance-2-0-260128 | doubao-seedance-2-0-260128 または doubao-seedance-2-0-fast-260128 | +| prompt | string | はい | - | プロンプト。生成したい動画の内容を記述します。 | +| resolution | string | いいえ | `720p` | 動画解像度。
選択肢:
`480p`, `720p`, `1080p` | +| ratio | string | いいえ | adaptive | アスペクト比。 | +| duration | integer | いいえ | `5` | 動画の長さ(秒)。 | + +### 万象 (Wanxiang) アップロード要件 +| フィールド名 (Name) | タイプ | 必須 | デフォルト値 | 説明 | +| :--- | :--- | :--- | :--- | :--- | +| llmid | モデル番号 | はい | - | - | +| prompt | string | はい | - | プロンプト。生成したい動画の内容を記述します。 | +| negative_prompt | string | いいえ | (空) | ネガティブプロンプト。動画に含めたくない内容を記述します。 | +| size | string | いいえ | `1920*1080` | 動画サイズ。
選択肢:
`1280*720`, `1920*1080` 等 | +| duration | integer | いいえ | `15` | 動画の長さ(秒)。
選択肢: `5`, `10`, `15` | + +### 例 (Example) +seedance を使用した例: +``` +#!/usr/bin/env bash +curl -X POST https://opencomputing.ai/llmage/video \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer " \ + -F "llmid=o5vfXYD5BURJWRTWpopE5" \ + -F "prompt=一起来调科目三" \ + -F "duration=15" \ + -F "resolution=720P" \ + -F "image1_file=@./02.jpg" +``` + +## リファレンスから動画 (Reference-to-Video) +### seedance 2.0 アップロード要件 +| フィールド名 | タイプ | 必須 | デフォルト値 | 説明 | +| :--- | :--- | :--- | :--- | :--- | +| image_files | 配列 | はい | [] | リファレンス画像配列。 | +| video_files | 配列 | いいえ | [] | リファレンス動画配列。 | + +## タスク送信 +* パス: /llmage/video +* メソッド: POST +* ヘッダー +``` +{ + "Content-Type": "application/json", + "Authorization": "Bearer " # 元境プラットフォームから申請したAPIKEY +} +``` + +* レスポンス +``` +{ + "taskid": # タスクID。後の実行結果照会に使用します。 + "status": # 状態: SUCCEEDED, FAILED, CREATED, PENDING, RUNNING +} +``` + +## タスク状態の照会 +* パス: /llmage/tasks +* メソッド: GET +* ヘッダー +``` +{ + "Content-Type": "application/json", + "Authorization": "Bearer " +} +``` +* パラメータ +``` +{ + "taskid": "936759404378734592" +} +``` +* レスポンス +``` +{ + "status": # 状態 + "usage": # status==SUCCEEDED時に有効。課金情報。 + "image": # 動画カバーURL + "video": # 動画URL +} +``` + +## エラーメッセージ + +* 401: {"error": "Invalid API Key"} (無効なAPIキー) +* 400: {"error": "Missing required parameter: prompt"} (必須パラメータ不足) +* 429: {"error": "Insufficient balance"} (残高不足) diff --git a/wwwroot/public/api/api_ko.md b/wwwroot/public/api/api_ko.md new file mode 100644 index 00000000..fbcfea8f --- /dev/null +++ b/wwwroot/public/api/api_ko.md @@ -0,0 +1,204 @@ +# 원경(Yuanjing) 플랫폼 API + +원경 플랫폼은 하위 시스템을 위해 OpenAI 인터페이스 프로토콜과 호환되는 API를 제공합니다. API를 활성화하려면 하위 시스템에서 다음 단계를 수행해야 합니다: +* 계정 등록 +* 로그인 +* APIKEY 신청 +* 충전 + +위 단계를 완료하면 다음 예시에 따라 텍스트 생성, 텍스트 기반 비디오(T2V), 이미지 기반 비디오(I2V), 참조 기반 비디오(R2V) 추론 서비스를 구현할 수 있습니다. + +원경 플랫폼에서 지원하는 모델은 '모델 광장(Model Square)'을 참조하십시오. + +## APIKEY 신청 + +사용자는 원경 플랫폼(https://ai.opencomputing.cn)에 모바일로 로그인한 후 "APIKEY 생성(创建APIKEY)"을 클릭해야 합니다. + +정보를 입력하고 제출하면 APIKEY 생성이 완료됩니다. + +"apikey 복사(复制apikey)"를 클릭하여 팝업 창에 표시된 apikey를 복사하십시오. + +## 충전 +사용자는 원경 플랫폼에서 충전을 진행해야 합니다. 현재 Alipay(알리페이)를 지원합니다. + +## 현재 잔액 확인 + +* 사용자 로그인 +* 사용자 메뉴 호출 +* '재무(财务)' 클릭 + +## API 기본 URL +https://opencomputing.ai + +## OpenAI 호환 인터페이스 +OpenAI와 호환되는 일련의 API를 제공합니다. + +### 텍스트 생성 +* 경로: /llmage/v1/chat/completions +* 메서드: 'POST' +* 헤더 +``` +{ + "Content-Type": "application/json", + "Authorization": "Bearer " # 원경 플랫폼에서 신청한 APIKEY +} +``` +* 데이터 +{ + "model": # 모델 식별 코드 (공급업체가 제공한 모델 이름) + "prompt": # 프롬프트 (필수 입력) + "sys_prompt" # 시스템 프롬프트 (선택 사항) + "stream" # 스트림 출력 스위치 + "..." # 기타 매개변수 +} + +* 반환값 +OpenAI 프로토콜을 준수하는 스트리밍 또는 비스트리밍 결과를 반환합니다. + +* 스트리밍: +``` +./oc.curl 你是谁 +data: {"id": "chatcmpl-2665dfd8-e05f-9d7f-adff-3c53c174a454", "object": "chat.completion.chunk", "created": 1775019761, "choices": [{"logprobs": null, "index": 0, "delta": {"content": "", "role": "assistant"}}], "model": "qwen3-max", "reasoning_content": null, "content": "", "finish": "0", "llmusageid": "K9_veNBxeqvrFfbGWXs0R"} +... +data: [DONE] +``` + +* 비스트리밍 +``` +./oc.curl 你是谁 +{"id": "chatcmpl-eea7abb9-24d5-9f70-b6f6-d7da4f22a8b8", "object": "chat.completion", "created": 1775011902, "choices": [{"finish_reason": "stop", "index": 0, "message": {"content": "我是通义千问...", "role": "assistant"}}], "model": "qwen3-max", "usage": {"total_tokens": 70}} +``` + +## 텍스트 기반 비디오 (Text-to-Video) +현재 지원되는 모델: +| 모델 ID | 제공사 | 모델 이름 | +|--------|--------|--------| +| o5vfXYD5BURJWRTWpopE5 | Alibaba Cloud | happyhorse-1.0-t2v | +| YjjGgxO_Xma8PWsMjJvps | Doubao | doubao-seedance-2-0-260128 | +| TWay-xd0p0pkEX-_Kuhto | We Token AI | dreamina-seedance-2-0-260128(*), dreamina-seedance-2-0-fast-260128 | +| CrEMkFQfRCmbmopZsCqLj | Doubao | doubao-seedance-1-5-pro-251215 | +| u9HZyfDoqU6uKI6M1BTks | Tongyi Wanxiang | wan2.6-t2v | +| r0ill7L0s6PtBS8mkmg-7 | vidu | viduq3-pro | + +### happyhorse-1.0-t2v 업로드 요구 사항 +| 필드명 (Name) | 유형 | 필수 여부 | 기본값 | 설명 | +| :--- | :--- | :--- | :--- | :--- | +| llmid | 모델 번호 | 예 | - | - | +| model | 모델 이름 | 아니요 | happyhorse-1.0-t2v | - | +| prompt | string | 예 | - | 프롬프트. 생성하려는 비디오 내용을 설명합니다. | +| resolution | string | 아니요 | `720p` | 비디오 해상도.
선택 가능 값:
`480p`, `720p`, `1080p` | +| ratio | string | 아니요 | adaptive | 화면 비율. 선택 가능 값: adaptive, 16:9, 4:3, 1:1, 3:4, 9:16, 21:9 | +| duration | integer | 아니요 | `5` | 비디오 길이(초).
선택 가능 값: 정수 | + +### seedance 2.0 업로드 요구 사항 +| 필드명 (Name) | 유형 | 필수 여부 | 기본값 | 설명 | +| :--- | :--- | :--- | :--- | :--- | +| llmid | 모델 번호 | 예 | - | - | +| model | 모델 이름 | 아니요 | doubao-seedance-2-0-260128 | doubao-seedance-2-0-260128 또는 doubao-seedance-2-0-fast-260128 | +| prompt | string | 예 | - | 프롬프트. 생성하려는 비디오 내용을 설명합니다. | +| resolution | string | 아니요 | `720p` | 비디오 해상도. | +| ratio | string | 아니요 | adaptive | 화면 비율. | +| duration | integer | 아니요 | `5` | 비디오 길이(초). | + +### 완샹(Wanxiang) 업로드 요구 사항 +| 필드명 (Name) | 유형 | 필수 여부 | 기본값 | 설명 | +| :--- | :--- | :--- | :--- | :--- | +| llmid | 모델 번호 | 예 | - | - | +| prompt | string | 예 | - | 프롬프트. 생성하려는 비디오 내용을 설명합니다. | +| negative_prompt | string | 아니요 | (비어 있음) | 부정 프롬프트. 비디오에 포함되지 않기를 바라는 내용을 설명합니다. | +| size | string | 아니요 | `1920*1080` | 비디오 크기.
선택 가능 값:
`1280*720`, `1920*1080` 등 | +| duration | integer | 아니요 | `15` | 비디오 길이(초).
선택 가능 값: `5`, `10`, `15` | + +### 예시 (Example) +seedance를 사용한 예: +``` +#!/usr/bin/env bash +curl -X POST https://opencomputing.ai/llmage/video \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer " \ + -F "llmid=o5vfXYD5BURJWRTWpopE5" \ + -F "prompt=一起来调科目三" \ + -F "duration=15" \ + -F "resolution=720P" \ + -F "image1_file=@./02.jpg" +``` + +## 참조 기반 비디오 (Reference-to-Video) +### seedance 2.0 업로드 요구 사항 +| 필드명 | 유형 | 필수 여부 | 기본값 | 설명 | +| :--- | :--- | :--- | :--- | :--- | +| image_files | 배열 | 예 | [] | 참조 이미지 배열. | +| video_files | 배열 | 아니요 | [] | 참조 비디오 배열. | + +## 작업 제출 +* 경로: /llmage/video +* 메서드: POST +* 헤더 +``` +{ + "Content-Type": "application/json", + "Authorization": "Bearer " # 원경 플랫폼에서 신청한 APIKEY +} +``` + +* 반환값 +``` +{ + "taskid": # 작업 ID. 나중에 실행 결과 조회에 사용됩니다. + "status": # 상태: SUCCEEDED, FAILED, CREATED, PENDING, RUNNING +} +``` + +## 작업 상태 조회 +* 경로: /llmage/tasks +* 메서드: GET +* 헤더 +``` +{ + "Content-Type": "application/json", + "Authorization": "Bearer " +} +``` +* 매개변수 +``` +{ + "taskid": "936759404378734592" +} +``` +* 반환값 +``` +{ + "status": # 상태 + "usage": # status==SUCCEEDED일 때 유효. 과금 정보. + "image": # 비디오 커버 URL + "video": # 비디오 URL +} +``` + +## 오류 메시지 + +* 401: {"error": "Invalid API Key"} (유효하지 않은 API 키) +* 400: {"error": "Missing required parameter: prompt"} (필수 매개변수 누락) +* 429: {"error": "Insufficient balance"} (잔액 부족) diff --git a/wwwroot/public/api/api_zh.md b/wwwroot/public/api/api_zh.md index cbb49805..e238fefa 100644 --- a/wwwroot/public/api/api_zh.md +++ b/wwwroot/public/api/api_zh.md @@ -1,277 +1,482 @@ # 元境平台API -元境平台为下游系统提供兼容openai接口协议的API,下游系统需要开通元境平台的API,要做以下步骤 +元境平台为下游系统提供兼容openai接口协议的API和真人素材管理API。使用平台API需要做以下步骤: * 注册一个账号 * 登录 * 申请APIKEY * 充值 -完成上述步骤后, 可以按照下面的例子实现文生文,文生视频,图生视频,参考生视频的模型推理服务 +完成上述步骤后,可以按照下面的接口文档实现各类服务。 -元境平台支持的模型,请参看模型广场 +元境平台支持的模型,请参看模型广场。 ## 申请APIKEY -用户需要在元境平台(https://opencomputing.ai)上注册和登录, 登录后点击左上角元境平台进入菜单,点击“下位系统接口-下位系统, 在界面中点击“创建APIKEY” +用户需要在元境平台(https://ai.opencomputing.cn)上用手机登录,登录"创建APIKEY" 输入信息后点击提交,APIKEY创建完成 -点击"复制apikey", 在弹出窗口看到apikey, 复制他 +点击"复制apikey",在弹出窗口看到apikey,复制它 ## 充值 用户需要在元境平台上充值,目前支持alipay(支付宝)充值 -操作方法 - -* 用户登录 -* 呼出用户菜单(点击右上角用户名) -* 点击充值 -* 输入充值信息 -在弹出界面中选择支付宝充值,输入合适的金额,点击提交转支付宝充值页面, 完成后等1分钟,查看账户当前余额 - ## 查看当前余额 * 用户登录 * 呼出用户菜单 * 点击财务 -## base url +--- + +# 一、大模型API(兼容OpenAI) + +## API对接的base url https://opencomputing.ai -## openai 兼容接口 -我们提供一套兼容openai的API -### 文本生成 -* path /llmage/t2t +## 查询可用模型列表 +* path /llmage/v1/models +* method GET +* headers +``` +{ + "Content-Type": "application/json", + "Authorization": "Bearer " +} +``` +* params (可选) +``` +{ + "catelogid": "t2v" # 按分类筛选,如 t2t/t2i/t2v/i2v/ref2v 等 +} +``` + +## 文本生成 +* path /llmage/v1/chat/completions * method 'POST' * headers ``` { "Content-Type": "application/json", - "Authorization": "Bearer " # 客户从元境平台申请到的APIKEY + "Authorization": "Bearer " } ``` * data +``` { - "model": # 模型识别码, 是供应方提供给model名字 - “prompt": # 提示词, 必须输入 - "sys_prompt" # 系统提示词,可选 - “stream” # 流式输出开关 - "..." # 其他提示词 + "model": "<模型名>", # 模型识别码,如 qwen3-max + "catelogid": "t2t", # 可选,默认 t2t + "prompt": "你的问题", # 提示词,必须输入 + "sys_prompt": "", # 系统提示词,可选 + "stream": true # 流式输出开关 } +``` * 返回 符合openai协议的流式或非流式结果 * 流式: ``` -./oc.curl 你是谁 -data: {"id": "chatcmpl-2665dfd8-e05f-9d7f-adff-3c53c174a454", "object": "chat.completion.chunk", "created": 1775019761, "choices": [{"logprobs": null, "index": 0, "delta": {"content": "", "role": "assistant"}}], "model": "qwen3-max", "reasoning_content": null, "content": "", "finish": "0", "llmusageid": "K9_veNBxeqvrFfbGWXs0R"} -data: {"id": "chatcmpl-2665dfd8-e05f-9d7f-adff-3c53c174a454", "object": "chat.completion.chunk", "created": 1775019761, "choices": [{"delta": {"content": "\u6211\u662f", "role": null}, "index": 0}], "model": "qwen3-max", "reasoning_content": null, "content": "\u6211\u662f", "finish": "0", "llmusageid": "K9_veNBxeqvrFfbGWXs0R"} -data: {"id": "chatcmpl-2665dfd8-e05f-9d7f-adff-3c53c174a454", "object": "chat.completion.chunk", "created": 1775019761, "choices": [{"delta": {"content": "\u901a\u4e49\u5343", "role": null}, "index": 0}], "model": "qwen3-max", "reasoning_content": null, "content": "\u901a\u4e49\u5343", "finish": "0", "llmusageid": "K9_veNBxeqvrFfbGWXs0R"} -data: {"id": "chatcmpl-2665dfd8-e05f-9d7f-adff-3c53c174a454", "object": "chat.completion.chunk", "created": 1775019761, "choices": [{"delta": {"content": "\u95ee\uff0c\u963f\u91cc\u5df4\u5df4\u96c6\u56e2\u65d7\u4e0b\u7684", "role": null}, "index": 0}], "model": "qwen3-max", "reasoning_content": null, "content": "\u95ee\uff0c\u963f\u91cc\u5df4\u5df4\u96c6\u56e2\u65d7\u4e0b\u7684", "finish": "0", "llmusageid": "K9_veNBxeqvrFfbGWXs0R"} -data: {"id": "chatcmpl-2665dfd8-e05f-9d7f-adff-3c53c174a454", "object": "chat.completion.chunk", "created": 1775019761, "choices": [{"delta": {"content": "\u8d85\u5927\u89c4\u6a21\u8bed\u8a00\u6a21\u578b\u3002\u6211\u80fd\u591f", "role": null}, "index": 0}], "model": "qwen3-max", "reasoning_content": null, "content": "\u8d85\u5927\u89c4\u6a21\u8bed\u8a00\u6a21\u578b\u3002\u6211\u80fd\u591f", "finish": "0", "llmusageid": "K9_veNBxeqvrFfbGWXs0R"} -data: {"id": "chatcmpl-2665dfd8-e05f-9d7f-adff-3c53c174a454", "object": "chat.completion.chunk", "created": 1775019761, "choices": [{"delta": {"content": "\u56de\u7b54\u95ee\u9898\u3001\u521b\u4f5c\u6587\u5b57\uff0c", "role": null}, "index": 0}], "model": "qwen3-max", "reasoning_content": null, "content": "\u56de\u7b54\u95ee\u9898\u3001\u521b\u4f5c\u6587\u5b57\uff0c", "finish": "0", "llmusageid": "K9_veNBxeqvrFfbGWXs0R"} -data: {"id": "chatcmpl-2665dfd8-e05f-9d7f-adff-3c53c174a454", "object": "chat.completion.chunk", "created": 1775019761, "choices": [{"delta": {"content": "\u6bd4\u5982\u5199\u6545\u4e8b\u3001\u5199\u516c", "role": null}, "index": 0}], "model": "qwen3-max", "reasoning_content": null, "content": "\u6bd4\u5982\u5199\u6545\u4e8b\u3001\u5199\u516c", "finish": "0", "llmusageid": "K9_veNBxeqvrFfbGWXs0R"} -data: {"id": "chatcmpl-2665dfd8-e05f-9d7f-adff-3c53c174a454", "object": "chat.completion.chunk", "created": 1775019761, "choices": [{"delta": {"content": "\u6587\u3001\u5199\u90ae\u4ef6\u3001\u5199\u5267\u672c", "role": null}, "index": 0}], "model": "qwen3-max", "reasoning_content": null, "content": "\u6587\u3001\u5199\u90ae\u4ef6\u3001\u5199\u5267\u672c", "finish": "0", "llmusageid": "K9_veNBxeqvrFfbGWXs0R"} -data: {"id": "chatcmpl-2665dfd8-e05f-9d7f-adff-3c53c174a454", "object": "chat.completion.chunk", "created": 1775019761, "choices": [{"delta": {"content": "\u3001\u903b\u8f91\u63a8\u7406\u3001\u7f16\u7a0b\u7b49\u7b49", "role": null}, "index": 0}], "model": "qwen3-max", "reasoning_content": null, "content": "\u3001\u903b\u8f91\u63a8\u7406\u3001\u7f16\u7a0b\u7b49\u7b49", "finish": "0", "llmusageid": "K9_veNBxeqvrFfbGWXs0R"} -data: {"id": "chatcmpl-2665dfd8-e05f-9d7f-adff-3c53c174a454", "object": "chat.completion.chunk", "created": 1775019761, "choices": [{"delta": {"content": "\uff0c\u8fd8\u80fd\u8868\u8fbe\u89c2\u70b9\uff0c\u73a9\u6e38\u620f", "role": null}, "index": 0}], "model": "qwen3-max", "reasoning_content": null, "content": "\uff0c\u8fd8\u80fd\u8868\u8fbe\u89c2\u70b9\uff0c\u73a9\u6e38\u620f", "finish": "0", "llmusageid": "K9_veNBxeqvrFfbGWXs0R"} -data: {"id": "chatcmpl-2665dfd8-e05f-9d7f-adff-3c53c174a454", "object": "chat.completion.chunk", "created": 1775019761, "choices": [{"delta": {"content": "\u7b49\u3002\u5982\u679c\u4f60\u6709\u4efb\u4f55\u95ee\u9898\u6216", "role": null}, "index": 0}], "model": "qwen3-max", "reasoning_content": null, "content": "\u7b49\u3002\u5982\u679c\u4f60\u6709\u4efb\u4f55\u95ee\u9898\u6216", "finish": "0", "llmusageid": "K9_veNBxeqvrFfbGWXs0R"} -data: {"id": "chatcmpl-2665dfd8-e05f-9d7f-adff-3c53c174a454", "object": "chat.completion.chunk", "created": 1775019761, "choices": [{"delta": {"content": "\u9700\u8981\u5e2e\u52a9\uff0c\u6b22\u8fce\u968f\u65f6\u544a\u8bc9\u6211", "role": null}, "index": 0}], "model": "qwen3-max", "reasoning_content": null, "content": "\u9700\u8981\u5e2e\u52a9\uff0c\u6b22\u8fce\u968f\u65f6\u544a\u8bc9\u6211", "finish": "0", "llmusageid": "K9_veNBxeqvrFfbGWXs0R"} -data: {"id": "chatcmpl-2665dfd8-e05f-9d7f-adff-3c53c174a454", "object": "chat.completion.chunk", "created": 1775019761, "choices": [{"delta": {"content": "\uff01", "role": null}, "index": 0}], "model": "qwen3-max", "reasoning_content": null, "content": "\uff01", "finish": "0", "llmusageid": "K9_veNBxeqvrFfbGWXs0R"} -data: {"id": "chatcmpl-2665dfd8-e05f-9d7f-adff-3c53c174a454", "object": "chat.completion.chunk", "created": 1775019761, "choices": [{"delta": {"content": "", "role": null}, "index": 0, "finish_reason": "stop"}], "model": "qwen3-max", "reasoning_content": null, "content": "", "finish": "0", "llmusageid": "K9_veNBxeqvrFfbGWXs0R"} -data: {"id": "chatcmpl-2665dfd8-e05f-9d7f-adff-3c53c174a454", "object": "chat.completion.chunk", "created": 1775019761, "choices": [], "model": "qwen3-max", "finish": "1", "usage": {"total_tokens": 70, "completion_tokens": 60, "prompt_tokens": 10, "prompt_tokens_details": {"cached_tokens": 0}}, "llmusageid": "K9_veNBxeqvrFfbGWXs0R"} +data: {"id": "chatcmpl-xxx", "object": "chat.completion.chunk", "created": 1775019761, "choices": [{"logprobs": null, "index": 0, "delta": {"content": "", "role": "assistant"}}], "model": "qwen3-max", "reasoning_content": null, "content": "", "finish": "0"} +... data: [DONE] ``` * 非流式 ``` -./oc.curl 你是谁 -{"id": "chatcmpl-eea7abb9-24d5-9f70-b6f6-d7da4f22a8b8", "object": "chat.completion", "created": 1775011902, "choices": [{"finish_reason": "stop", "index": 0, "message": {"content": "我是通义千问,阿里巴巴集团旗下的超大规模语言模型。我能够回答问题、创作文字,比如写故事、写公文、写邮件、写剧本、逻辑推理、编程等等,还能表达观点,玩游戏等。如果你有任何问题或需要帮助,欢迎随时告诉我!", "role": "assistant"}}], "model": "qwen3-max", "reasoning_content": null, "content": "我是通义千问,阿里巴巴集团旗下的超大规模语言模型。我能够回答问题、创作文字,比如写故事、写公文、写邮件、写剧本、逻辑推理、编程等等,还能表达观点,玩游戏等。如果你有任何问题或需要帮助,欢迎随时告诉我!", "finish": "1", "usage": {"completion_tokens": 60, "prompt_tokens": 10, "prompt_tokens_details": {"cached_tokens": 0}, "total_tokens": 70}} +{"id": "chatcmpl-xxx", "object": "chat.completion", "created": 1775011902, "choices": [{"finish_reason": "stop", "index": 0, "message": {"content": "我是通义千问...", "role": "assistant"}}], "model": "qwen3-max", "content": "我是通义千问...", "finish": "1", "usage": {...}} ``` -## 文生视频 -目前支持: -| 模型id | 供应商 | 模型名 | -|--------|--------|--------| -| CrEMkFQfRCmbmopZsCqLj | 豆包 | doubao-seedance-1-5-pro-251215 | -| u9HZyfDoqU6uKI6M1BTks | 通义万象 | wan2.6-t2v | -| r0ill7L0s6PtBS8mkmg-7 | vidu | viduq3-pro | -| YjjGgxO_Xma8PWsMjJvps | 豆包 | eedance2.0 (未开通)| +## 文生图 +| 模型名 | 供应商 | 说明 | +|--------|--------|------| +| wan2.2-t2i-plus | 阿里百炼 | 万相2.2专业版,创意性、稳定性、写实质感全面升级 | +| wan2.5-t2i-preview | 阿里百炼 | 万相2.5 preview版 | +| wan2.2-t2i-flash | 阿里百炼 | 万相2.2极速版,速度快,性价比高 | +| cogview-3-flash | 智谱AI | CogView-3-Flash 免费图像生成 | -### 万象上传数据要求 +### 上传数据要求 | 字段名 (Name) | 类型 (Type) | 必填 (Required) | 默认值 (Default) | 说明 (Description) | | :--- | :--- | :--- | :--- | :--- | -| llmid | 模型编号 | 是 | - | - | -| prompt | string | 是 | - | 提示词。用于描述你希望生成的视频内容。 | -| negative_prompt | string | 否 | (empty) | 反向提示词。用于描述你希望视频中避免出现的内容。 | -| size | string | 否 | `1920*1080` | 视频尺寸。指定生成视频的分辨率。
可选值:
`832*480`, `480*832`, `624*624`, `1280*720`, `720*1280`, `960*960`, `1088*832`, `832*1088`, `1920*1080`, `1080*1920`, `1440*1440`, `1632*1248`, `1248*1632` | -| duration | integer | 否 | `15` | 视频时长。指定生成视频的长度(秒)。
可选值:
`5`, `10`, `15` | - -### vidu 上传参数 -| 字段名 (Name) | 类型 (Type) | 必填 (Required) | 默认值 (Default) | 说明 (Description) | -| :--- | :--- | :--- | :--- | :--- | -| llmid | 模型编号 | 是 | - | - | -| prompt | string | 是 | - | 提示词。用于描述生成视频的内容。 | -| off_peak | string | 否 | `N` | 错峰执行。是否开启非高峰时段生成。
可选值:`Y` (是), `N` (否) | -| duration | integer | 否 | `10` | 视频长度。生成视频的时长(秒)。
范围:1-16 秒 (根据字段描述) | -| ratio | string | 否 | `16:9` | 长宽比。指定视频的画面比例。
可选值:
`16:9`, `9:16`, `4:3`, `3:4`, `1:1` | -| resolution | string | 否 | `1080p` | 分辨率。指定生成视频的清晰度。
可选值:
`540p`, `720p`, `1080p` | - -### seedance 上传数据要求 -| 字段名 | 类型 | 必填 | 默认值 | 说明 | -| :--- | :--- | :--- | :--- | :--- | -| llmid | 模型编号 | 是 | - | - | -| prompt | string | 是 | - | 提示词。描述生成视频的内容。 | -| radio | string | 否 | - | 宽高比例。指定视频的长宽比。
可选值:
`16:9`, `keep_ratio`, `4:3`, `1:1`, `3:4`, `9:16`, `9:21`, `21:9`, `adaptive` | -| resolution | string | 否 | `1080p` | 分辨率。指定视频清晰度。
可选值:
`480p`, `720p`, `1080p` | -| duration | integer | 否 | `12` | 视频长度。视频时长(秒)。 | - -### 例子 -使用seedance的例子 -``` -#!/usr/bin/env bash -curl -X POST https://opencomputing.ai/llmage/video \ - -H "Content-Type: application/json" \ - -H "Authorization: Bearer 可选值:
`832*480`, `480*832`, `624*624`, `1280*720`, `720*1280`, `960*960`, `1088*832`, `832*1088`, `1920*1080`, `1080*1920`, `1440*1440`, `1632*1248`, `1248*1632` | -| duration | integer | 否 | `15` | 视频时长。指定生成视频的长度(秒)。
可选值:
`5`, `10`, `15` | -| image_file1 | string/file | 是 | - | 首帧图片。视频的起始画面(通常为图片 URL 或 Base64)。 | -| image_file2 | string/file | 是 | - | 尾帧图片。视频的结束画面(通常为图片 URL 或 Base64)。 | - -### vidu 上传数据要求 -| 字段名 (Name) | 类型 (Type) | 必填 (Required) | 默认值 (Default) | 说明 (Description) | -| :--- | :--- | :--- | :--- | :--- | -| llmid | 模型编号 | 是 | - | - | -| model | string | 否 | `viduq3-pro` | 模型。选择生成视频所使用的模型版本。
可选值:
`viduq2-turbo`, `viduq3-pro` | -| prompt | string | 是 | - | 提示词。描述视频内容的文本。 | -| off_peak | string | 否 | `N` | 错峰执行。是否开启非高峰时段生成。
可选值:
`Y` (是), `N` (否) | -| image_file1 | string/file | 是 | - | 首帧图片。视频的起始画面(通常为图片 URL 或 Base64)。 | -| image_file2 | string/file | 是 | - | 尾帧图片。视频的结束画面(通常为图片 URL 或 Base64)。 | -| duration | integer | 否 | `10` | 视频长度。生成视频的时长(秒)。
范围:1-16 秒 | -| ratio | string | 否 | `16:9` | 长宽比。指定视频的画面比例。
可选值:
`16:9`, `9:16`, `4:3`, `3:4`, `1:1` | -| resolution | string | 否 | `1080p` | 分辨率。指定生成视频的清晰度。
可选值:
`540p`, `720p`, `1080p` | - -### seedance 上传数据要求 -| 字段名 | 类型 | 必填 | 默认值 | 说明 | -| :--- | :--- | :--- | :--- | :--- | -| llmid | 模型编号 | 是 | - | - | -| prompt | string | 是 | - | 提示词。描述视频内容的文本。 | -| radio | string | 否 | - | 宽高比例。指定视频的长宽比。
可选值:
`16:9`, `keep_ratio`, `4:3`, `1:1`, `3:4`, `9:16`, `9:21`, `21:9`, `adaptive` | -| resolution | string | 否 | `1080p` | 分辨率。指定视频清晰度。
可选值:
`480p`, `720p`, `1080p` | -| duration | integer | 否 | `12` | 视频长度。视频时长(秒)。 | -| image_file1 | string | 否 | - | 首帧图片。视频开始的画面(URL 或 Base64)。 | -| image_file2 | string | 否 | - | 尾帧图片。视频结束的画面(URL 或 Base64)。 | - -### 例子 -使用seedance的例子 -``` -``` -## 参考生视频 -| 模型id | 供应商 | 模型名 | -|--------|--------|--------| -| VooAIOtJdawpZjusWEzrh | 豆包 | doubao-seedance-1-5-pro-251215 | - -### seedance上传数据要求 -| 字段名 | 类型 | 必填 | 默认值 | 说明 | -| :--- | :--- | :--- | :--- | :--- | -| prompt | string | 是 | - | 提示词。描述视频内容的文本。 | -| radio | string | 否 | - | 宽高比例。指定视频的长宽比。
可选值:
`16:9`, `4:3`, `1:1`, `3:4`, `9:16`, `9:21`, `21:9` | -| resolution | string | 否 | `1080p` | 分辨率。指定视频清晰度。
可选值:
`480p`, `720p`, `1080p` | -| duration | integer | 否 | `12` | 视频长度。视频时长(秒)。 | -| image_file1 | string | 是 | - | 参考图片1。主要的参考画面(URL 或 Base64)。 | -| image_file2 | string | 否 | - | 参考图片2。额外的参考画面。 | -| image_file3 | string | 否 | - | 参考图片3。额外的参考画面。 | - -### 例子 +| model | string | 是 | - | 模型名。如 wan2.2-t2i-plus | +| catelogid | string | 是 | - | 分类标识。固定为 `t2i` | +| prompt | string | 是 | - | 提示词。用于描述你希望生成的图片内容。 | +| negative_prompt | string | 否 | (empty) | 负面提示词。用于描述你希望避免出现的内容。 | ### 任务提交 -* path /llmage/video -* method POST +* path /llmage/v1/image/generations +* method POST * headers ``` { "Content-Type": "application/json", - "Authorization": "Bearer " # 客户从元境平台申请到的APIKEY + "Authorization": "Bearer " } ``` * data -除llmid外,不同的模型需要的数据不同,请看上传数据说明 +``` +{ + "model": "wan2.2-t2i-plus", + "catelogid": "t2i", + "prompt": "一只猫坐在月亮上", + "negative_prompt": "模糊,低质量" +} +``` +* 返回 +``` +{ + "taskid": "xxx", + "status": "CREATED" +} +``` + +### 例子 +```bash +curl -X POST https://opencomputing.ai/llmage/v1/image/generations \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer *** \ + -d '{ + "model": "wan2.2-t2i-plus", + "catelogid": "t2i", + "prompt": "一只猫坐在月亮上,水彩画风格" + }' +``` + +## 文生视频 +| 模型名 | 供应商 | 说明 | +|--------|--------|------| +| happyhorse-1.0-t2v | 阿里云 | 快乐马文生视频 | +| doubao-seedance-2-0-260128 | 豆包 | seedance 2.0 | +| dreamina-seedance-2-0-260128 | We Token AI | 豆包海外版 | +| doubao-seedance-1-5-pro-251215 | 豆包 | seedance 1.5 | +| wan2.6-t2v | 通义万象 | 万象2.6文生视频 | +| viduq3-pro | vidu | vidu文生视频 | + +### happyhorse-1.0-t2v 上传数据要求 +| 字段名 (Name) | 类型 (Type) | 必填 (Required) | 默认值 (Default) | 说明 (Description) | +| :--- | :--- | :--- | :--- | :--- | +| model | string | 是 | - | 模型名。`happyhorse-1.0-t2v` | +| catelogid | string | 是 | - | 分类标识。固定为 `t2v` | +| prompt | string | 是 | - | 提示词。 | +| resolution | string | 否 | `720P` | 分辨率。可选:`720P`, `1080P` | +| ratio | string | 否 | adaptive | 宽高比。可选:`16:9`, `4:3`, `1:1`, `3:4`, `9:16` | +| duration | integer | 否 | `5` | 视频时长(秒)。 | + +### seedance 2.0 上传数据要求 +| 字段名 (Name) | 类型 (Type) | 必填 (Required) | 默认值 (Default) | 说明 (Description) | +| :--- | :--- | :--- | :--- | :--- | +| model | string | 是 | - | 模型名。`doubao-seedance-2-0-260128` 或 `doubao-seedance-2-0-fast-260128` | +| catelogid | string | 是 | - | 分类标识。固定为 `t2v` | +| prompt | string | 是 | - | 提示词。 | +| resolution | string | 否 | `720p` | 分辨率。可选:`480p`, `720p`, `1080p` | +| ratio | string | 否 | adaptive | 宽高比。可选:`16:9`, `4:3`, `1:1`, `3:4`, `9:16` | +| duration | integer | 否 | `5` | 视频时长(秒)。 | + +### 万象 上传数据要求 +| 字段名 (Name) | 类型 (Type) | 必填 (Required) | 默认值 (Default) | 说明 (Description) | +| :--- | :--- | :--- | :--- | :--- | +| model | string | 是 | - | 模型名。`wan2.6-t2v` | +| catelogid | string | 是 | - | 分类标识。固定为 `t2v` | +| prompt | string | 是 | - | 提示词。 | +| negative_prompt | string | 否 | (empty) | 负面提示词。 | +| size | string | 否 | `1920*1080` | 视频尺寸。可选:`832*480`, `480*832`, `624*624`, `1280*720`, `720*1280`, `960*960`, `1920*1080`, `1080*1920`, `1440*1440` | +| duration | integer | 否 | `15` | 视频时长(秒)。可选:`5`, `10`, `15` | + +### vidu 上传参数 +| 字段名 (Name) | 类型 (Type) | 必填 (Required) | 默认值 (Default) | 说明 (Description) | +| :--- | :--- | :--- | :--- | :--- | +| model | string | 是 | - | 模型名。`viduq3-pro` | +| catelogid | string | 是 | - | 分类标识。固定为 `t2v` | +| prompt | string | 是 | - | 提示词。 | +| off_peak | string | 否 | `N` | 错峰执行。可选:`Y` (是), `N` (否) | +| duration | integer | 否 | `10` | 视频长度(秒)。范围:1-16 秒 | +| ratio | string | 否 | `16:9` | 宽高比。可选:`16:9`, `9:16`, `4:3`, `3:4`, `1:1` | +| resolution | string | 否 | `1080p` | 分辨率。可选:`540p`, `720p`, `1080p` | + +### seedance 1.5 上传数据要求 +| 字段名 | 类型 | 必填 | 默认值 | 说明 | +| :--- | :--- | :--- | :--- | :--- | +| model | string | 是 | - | 模型名。`doubao-seedance-1-5-pro-251215` | +| catelogid | string | 是 | - | 分类标识。固定为 `t2v` | +| prompt | string | 是 | - | 提示词。 | +| ratio | string | 否 | - | 宽高比。可选:`16:9`, `4:3`, `1:1`, `3:4`, `9:16`, `adaptive` | +| resolution | string | 否 | `1080p` | 分辨率。可选:`480p`, `720p`, `1080p` | +| duration | integer | 否 | `12` | 视频时长(秒)。 | + +### 任务提交 +* path /llmage/v1/video/generations +* method POST +* headers +``` +{ + "Content-Type": "application/json", + "Authorization": "Bearer " +} +``` +* data +不同的模型需要的数据不同,请看上方各模型的上传数据说明。必须包含 model 和 catelogid。 * 返回 ``` { - "taskid": # 任务id, 后续使用此id查询执行结果 - "status": # 状态 有: - # SUCCEEDED: 成功 - # FAILED:失败 - # CREATED:已创建 - # PENDING:排队中 - # RUNNING:运行中 -} -``` -返回例子: -``` -{ - "taskid": "936759404378734592", - "status": "created" + "taskid": "xxx", + "status": "CREATED" } ``` +### 例子 +快乐马文生视频 +```bash +curl -X POST https://opencomputing.ai/llmage/v1/video/generations \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer *** \ + -d '{ + "model": "happyhorse-1.0-t2v", + "catelogid": "t2v", + "prompt": "天上飞过各式各样的万圣节南瓜", + "ratio": "4:3", + "resolution": "720P", + "duration": 4 + }' +``` +seedance 1.5 文生视频 +```bash +curl -X POST https://opencomputing.ai/llmage/v1/video/generations \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer *** \ + -d '{ + "model": "doubao-seedance-1-5-pro-251215", + "catelogid": "t2v", + "prompt": "小猫在抓老鼠", + "duration": 5, + "ratio": "16:9", + "resolution": "480p" + }' +``` + +## 图生视频 +| 模型名 | 供应商 | 说明 | +|--------|--------|------| +| happyhorse-1.0-i2v | 阿里云 | 快乐马图生视频(首帧) | +| doubao-seedance-2-0-260128 | 豆包 | seedance 2.0 图生视频 | +| dreamina-seedance-2-0-260128 | We Token AI | 豆包海外版图生视频 | +| doubao-seedance-1-5-pro-251215 | 豆包 | seedance 1.5 图生视频 | +| viduq3-pro | vidu | vidu首尾帧图生视频 | +| wan2.6-r2v | 通义万象 | 万象2.6预置角色生视频 | + +### 快乐马上传数据要求 +| 字段名 (Name) | 类型 (Type) | 必填 (Required) | 默认值 (Default) | 说明 (Description) | +| :--- | :--- | :--- | :--- | :--- | +| model | string | 是 | - | 模型名。`happyhorse-1.0-i2v` | +| catelogid | string | 是 | - | 分类标识。固定为 `i2v` | +| prompt | string | 是 | - | 提示词。 | +| image_file | file | 是 | - | 首帧图片。 | +| resolution | string | 否 | `720P` | 分辨率。可选:`720P`, `1080P` | +| duration | integer | 否 | `5` | 视频时长(秒)。 | + +### seedance 2.0 上传数据要求 +| 字段名 (Name) | 类型 (Type) | 必填 (Required) | 默认值 (Default) | 说明 (Description) | +| :--- | :--- | :--- | :--- | :--- | +| model | string | 是 | - | 模型名。`doubao-seedance-2-0-260128` | +| catelogid | string | 是 | - | 分类标识。固定为 `i2v` | +| prompt | string | 是 | - | 提示词。 | +| image1_file | file | 是 | - | 首帧图片。 | +| image2_file | file | 是 | - | 尾帧图片。 | +| resolution | string | 否 | `720p` | 分辨率。可选:`480p`, `720p`, `1080p` | +| ratio | string | 否 | adaptive | 宽高比。可选:`16:9`, `4:3`, `1:1`, `3:4`, `9:16` | +| duration | integer | 否 | `5` | 视频时长(秒)。 | + +### 通义万象上传数据要求 +| 字段名 (Name) | 类型 (Type) | 必填 (Required) | 默认值 (Default) | 说明 (Description) | +| :--- | :--- | :--- | :--- | :--- | +| model | string | 是 | - | 模型名。`wan2.6-r2v` | +| catelogid | string | 是 | - | 分类标识。固定为 `i2v` | +| prompt | string | 是 | - | 提示词。 | +| negative_prompt | string | 否 | (empty) | 负面提示词。 | +| size | string | 否 | `1920*1080` | 视频尺寸。 | +| duration | integer | 否 | `15` | 视频时长(秒)。可选:`5`, `10`, `15` | +| image_file1 | file | 是 | - | 首帧图片。 | +| image_file2 | file | 是 | - | 尾帧图片。 | + +### vidu 上传数据要求 +| 字段名 (Name) | 类型 (Type) | 必填 (Required) | 默认值 (Default) | 说明 (Description) | +| :--- | :--- | :--- | :--- | :--- | +| model | string | 是 | - | 模型名。`viduq3-pro` | +| catelogid | string | 是 | - | 分类标识。固定为 `i2v` | +| prompt | string | 是 | - | 提示词。 | +| off_peak | string | 否 | `N` | 错峰执行。可选:`Y` (是), `N` (否) | +| image_file1 | file | 是 | - | 首帧图片。 | +| image_file2 | file | 是 | - | 尾帧图片。 | +| duration | integer | 否 | `10` | 视频长度(秒)。范围:1-16 秒 | +| ratio | string | 否 | `16:9` | 宽高比。可选:`16:9`, `9:16`, `4:3`, `3:4`, `1:1` | +| resolution | string | 否 | `1080p` | 分辨率。可选:`540p`, `720p`, `1080p` | + +### seedance 1.5 上传数据要求 +| 字段名 | 类型 | 必填 | 默认值 | 说明 | +| :--- | :--- | :--- | :--- | :--- | +| model | string | 是 | - | 模型名。`doubao-seedance-1-5-pro-251215` | +| catelogid | string | 是 | - | 分类标识。固定为 `i2v` | +| prompt | string | 是 | - | 提示词。 | +| ratio | string | 否 | - | 宽高比。可选:`16:9`, `4:3`, `1:1`, `3:4`, `9:16`, `adaptive` | +| resolution | string | 否 | `1080p` | 分辨率。可选:`480p`, `720p`, `1080p` | +| duration | integer | 否 | `12` | 视频时长(秒)。 | +| image_file1 | file | 否 | - | 首帧图片。 | +| image_file2 | file | 否 | - | 尾帧图片。 | + +### 任务提交 +* path /llmage/v1/video/generations +* method POST +* headers +``` +{ + "Content-Type": "application/json", + "Authorization": "Bearer " +} +``` +* data +不同的模型需要的数据不同,请看上方各模型的上传数据说明。必须包含 model 和 catelogid。 + +* 返回 +``` +{ + "taskid": "xxx", + "status": "CREATED" +} +``` + +### 例子 +快乐马图生视频 +```bash +curl -X POST https://opencomputing.ai/llmage/v1/video/generations \ + -H "Authorization: Bearer *** \ + -F "model=happyhorse-1.0-i2v" \ + -F "catelogid=i2v" \ + -F "prompt=图片变换为万圣节各种南瓜飞上天" \ + -F "duration=15" \ + -F "resolution=720P" \ + -F "image_file=@./02.jpg" +``` +seedance 2.0 图生视频 +```bash +curl -X POST https://opencomputing.ai/llmage/v1/video/generations \ + -H "Authorization: Bearer *** \ + -F "model=doubao-seedance-2-0-260128" \ + -F "catelogid=i2v" \ + -F "prompt=从图片1到图片2丝滑转换" \ + -F "duration=5" \ + -F "ratio=16:9" \ + -F "resolution=480p" \ + -F "image1_file=@./myimg1.jpg" \ + -F "image2_file=@./myimg2.jpg" +``` + +## 参考生视频 +| 模型名 | 供应商 | 说明 | +|--------|--------|------| +| happyhorse-1.0-r2v | 阿里云 | 快乐马参考生视频 | +| doubao-seedance-2-0-260128 | 豆包 | seedance 2.0 参考生视频 | +| dreamina-seedance-2-0-260128 | We Token AI | 豆包海外版参考生视频 | + +### 快乐马 上传数据要求 +| 字段名 | 类型 | 必填 | 默认值 | 说明 | +| :--- | :--- | :--- | :--- | :--- | +| model | string | 是 | - | 模型名。`happyhorse-1.0-r2v` | +| catelogid | string | 是 | - | 分类标识。固定为 `ref2v` | +| prompt | string | 是 | - | 提示词。 | +| ratio | string | 否 | - | 宽高比。可选:`16:9`, `4:3`, `1:1`, `3:4`, `9:16` | +| resolution | string | 否 | `1080P` | 分辨率。可选:`720P`, `1080P` | +| duration | integer | 否 | `15` | 视频时长(秒)。 | +| image_files | 数组 | 是 | [] | 参考图片数组。最多9个图片文件 | + +### seedance 2.0 上传数据要求 +| 字段名 | 类型 | 必填 | 默认值 | 说明 | +| :--- | :--- | :--- | :--- | :--- | +| model | string | 是 | - | 模型名。`doubao-seedance-2-0-260128` | +| catelogid | string | 是 | - | 分类标识。固定为 `ref2v` | +| prompt | string | 是 | - | 提示词。 | +| ratio | string | 否 | - | 宽高比。可选:`16:9`, `4:3`, `1:1`, `3:4`, `9:16` | +| resolution | string | 否 | `1080p` | 分辨率。可选:`480p`, `720p`, `1080p` | +| duration | integer | 否 | `12` | 视频时长(秒)。 | +| image_files | 数组 | 是 | [] | 参考图片数组。 | +| video_files | 数组 | 否 | [] | 参考视频数组。 | +| audio_files | 数组 | 否 | [] | 参考音频数组。 | + +### 任务提交 +* path /llmage/v1/video/generations +* method POST +* headers +``` +{ + "Content-Type": "application/json", + "Authorization": "Bearer " +} +``` +* data +不同的模型需要的数据不同,请看上方各模型的上传数据说明。必须包含 model 和 catelogid。 + +* 返回 +``` +{ + "taskid": "xxx", + "status": "CREATED" +} +``` + +### 例子 +seedance 2.0 参考生视频 +```bash +curl -X POST https://opencomputing.ai/llmage/v1/video/generations \ + -H "Authorization: Bearer *** \ + -F "model=doubao-seedance-2-0-260128" \ + -F "catelogid=ref2v" \ + -F "image_files=@./1.jpg" \ + -F "image_files=@./2.jpg" \ + -F "prompt=平滑过渡从第一张图片到第二张图片" \ + -F "ratio=4:3" \ + -F "resolution=720p" \ + -F "duration=4" +``` +快乐马参考生视频 +```bash +curl -X POST https://opencomputing.ai/llmage/v1/video/generations \ + -H "Authorization: Bearer *** \ + -F "model=happyhorse-1.0-r2v" \ + -F "catelogid=ref2v" \ + -F "image_files=@./1.jpg" \ + -F "image_files=@./2.jpg" \ + -F "prompt=平滑过渡从第一张图片到第二张图片" \ + -F "ratio=4:3" \ + -F "resolution=720P" \ + -F "duration=4" +``` + ## 查询任务状态 -* path /llmage/tasks -* method GET +* path /llmage/v1/tasks +* method GET * headers ``` { "Content-Type": "application/json", - "Authorization": "Bearer " # 客户从元境平台申请到的APIKEY + "Authorization": "Bearer " } ``` * params ``` { - "taskid": "936759404378734592" + "taskid": "xxx" } ``` * 返回 ``` { - "status": # 状态 有: - # SUCCEEDED: 成功 - # FAILED:失败 - # CREATED:已创建 - # PENDING:排队中 - # RUNNING:运行中 - "taskid": # 供应商生成的任务号,如果失败taskid无意义 - "usage": # status==SUCCEEDED时有效,计费信息 - "image": # 视频封面url - "video": # 视频url + "status": "SUCCEEDED", # SUCCEEDED/FAILED/CREATED/PENDING/RUNNING + "taskid": "xxx", # 供应商任务号 + "usage": {...}, # SUCCEEDED时有效,计费信息 + "image": "https://...", # 图片/视频封面url + "video": "https://..." # 视频url } ``` 返回例子: ``` { - "usage": { # 由于各个供应商,模型的计价方式不同 - # usage的内容会有所变化 + "usage": { "action": "t2v", "credits": 10, "type": "text2video", @@ -287,15 +492,248 @@ curl -X POST https://opencomputing.ai/llmage/video \ ``` ### 例子 +```bash +curl -X GET "https://opencomputing.ai/llmage/v1/tasks?taskid=xxx" \ + -H "Authorization: Bearer *** ``` -#!/usr/bin/env bash -curl -X GET https://opencomputing.ai/llmage/tasks?taskid=$1 \ - -H "Content-Type: application/json" \ - -H "Authorization: Bearer " + +--- + +# 二、真人素材API + +真人素材API提供真人人像认证、素材上传和素材管理功能。所有接口通过 **Bearer Token** 认证,与大模型API使用相同的APIKEY。 + +## API对接的base url +https://token.opencomputing.cn + +## 业务流程 + +1. **真人认证**:调用方发起认证请求,获取 H5 链接供终端用户完成人脸识别。 +2. **查询已认证组合**:查询当前机构下所有已认证的组合 ID,用于上传素材时选择有效的 group_id。 +3. **上传素材**:使用已认证的组合 ID 上传图片/视频,系统验证组合归属关系。 +4. **状态同步**:轮询检查素材处理状态。 + +## 1. 获取真人认证链接 (H5) +**Endpoint**: `POST /reallife_asset/api/rl_verify.dspy` + +检查供应商配置通过后,调用供应商接口创建认证会话。 + +### 请求参数 +| 参数 | 必填 | 说明 | +|------|------|------| +| `vendor` | 是 | 供应商标识 | +| `project_name` | 否 | 项目名称,默认 `default` | +| `name` | 否 | 认证名称,方便识别的名称,查询组合列表时显示 | + +> `user_id` 和 `org_id` 由 Bearer Token 自动获取,无需传递。 + +### 请求示例 +```bash +curl -X POST 'https://token.opencomputing.cn/reallife_asset/api/rl_verify.dspy' \ + -H 'Authorization: Bearer *** \ + -H 'Content-Type: application/json' \ + -d '{ + "vendor": "volcengine", + "project_name": "default", + "name": "张三" + }' ``` + +### 返回示例 +**成功**: +```json +{ + "status": "ok", + "data": { + "id": "local_group_id_xxx", + "h5_link": "https://... (H5页面链接,120秒有效)", + "byted_token": "..." + } +} +``` +**失败**(未配置): +```json +{ + "status": "error", + "data": {"message": "供应商配置不存在"} +} +``` + +**注意**:终端用户在 H5 页面完成认证后,系统将自动登记该机构与组合 ID 的映射关系。 + +## 2. 查询已认证的组合列表 +**Endpoint**: `POST /reallife_asset/api/rl_query_groups.dspy` + +查询当前机构下所有已认证的组合 ID,用于上传素材时选择有效的 `group_id`。 + +### 请求参数 +无需参数,系统自动从 Bearer Token 获取 `org_id`。 + +### 请求示例 +```bash +curl -X POST 'https://token.opencomputing.cn/reallife_asset/api/rl_query_groups.dspy' \ + -H 'Authorization: Bearer *** +``` + +### 返回示例 +```json +{ + "status": "ok", + "data": { + "groups": [ + { + "vendor_group_id": "volc-asset-group-xxx", + "vendor": "volcengine", + "name": "模特张三", + "status": "active", + "create_time": "2026-05-28 15:30:00" + } + ] + } +} +``` + +## 3. 上传素材 +**Endpoint**: `POST /reallife_asset/api/rl_upload.dspy` + +向已认证的素材组合上传图片或视频素材。 + +### 请求参数 +| 参数 | 必填 | 说明 | +|------|------|------| +| `vendor_group_id` | 是 | 认证成功后获得的供应商组合 ID(通过 `rl_query_groups` 查询) | +| `source_url` | 是 | 素材的公网 URL 或 `data:` 格式的 base64 编码(系统自动转为公网地址) | +| `asset_type` | 否 | 素材类型:`Image` (默认) 或 `Video` | +| `name` | 否 | 素材名称 | + +### 请求示例(公网 URL) +```bash +curl -X POST 'https://token.opencomputing.cn/reallife_asset/api/rl_upload.dspy' \ + -H 'Authorization: Bearer *** \ + -H 'Content-Type: application/json' \ + -d '{ + "vendor_group_id": "volc-asset-group-xxx", + "source_url": "https://bucket.oss.com/photo.jpg", + "asset_type": "Image", + "name": "模特A" + }' +``` + +### 请求示例(base64 直接上传) +```bash +curl -X POST 'https://token.opencomputing.cn/reallife_asset/api/rl_upload.dspy' \ + -H 'Authorization: Bearer *** \ + -H 'Content-Type: application/json' \ + -d '{ + "vendor_group_id": "volc-asset-group-xxx", + "source_url": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQ...", + "asset_type": "Image", + "name": "模特B" + }' +``` + +### 返回示例 +```json +{ + "status": "ok", + "data": { + "id": "asset_record_id_xxx", + "vendor_asset_id": "asset-2026...", + "status": "Processing" + } +} +``` + +**注意**:上传是异步操作,初始状态为 `Processing`,需调用查询素材状态接口轮询。 + +## 4. 查询素材状态 +**Endpoint**: `POST /reallife_asset/api/rl_status.dspy` + +查询素材的处理状态(Processing / Active / Failed)。 + +### 请求参数 +| 参数 | 必填 | 说明 | +|------|------|------| +| `asset_id` | 是 | 上传素材时返回的本地记录 ID | + +### 请求示例 +```bash +curl -X POST 'https://token.opencomputing.cn/reallife_asset/api/rl_status.dspy' \ + -H 'Authorization: Bearer *** \ + -H 'Content-Type: application/json' \ + -d '{ + "asset_id": "asset_record_id_xxx" + }' +``` + +### 返回示例 +```json +{ + "status": "ok", + "data": { + "status": "Active", + "url": "https://... (临时下载链接,12小时有效)" + } +} +``` + +> **说明**:素材永久存储在服务器上。`url` 是临时签名下载链接,过期后可通过再次调用 `rl_status` 获取新链接。素材的永久引用为上传时返回的 `vendor_asset_id`。 + +## 5. 查询组合下所有素材 +**Endpoint**: `POST /reallife_asset/api/rl_assets.dspy` + +查询指定 `vendor_group_id` 下的所有素材列表。 + +### 请求参数 +| 参数 | 必填 | 说明 | +|------|------|------| +| `vendor_group_id` | 是 | 认证成功后获得的供应商组合 ID | + +### 请求示例 +```bash +curl -X POST 'https://token.opencomputing.cn/reallife_asset/api/rl_assets.dspy' \ + -H 'Authorization: Bearer *** \ + -H 'Content-Type: application/json' \ + -d '{ + "vendor_group_id": "volc-asset-group-xxx" + }' +``` + +### 返回示例 +```json +{ + "status": "ok", + "data": { + "assets": [ + { + "id": "asset_record_id_xxx", + "vendor_asset_id": "asset-2026...", + "name": "模特A", + "asset_type": "Image", + "status": "Active", + "url": "https://... (临时下载链接)", + "create_time": "2026-05-28 15:30:00" + } + ], + "total": 3 + } +} +``` + +--- + ## 错误信息 -* 401: {"error": "Invalid API Key"} -* 400: {"error": "Missing required parameter: prompt"} -* 429: {"error": "Insufficient balance"} (余额不足) +### 大模型API错误 +* 401: `{"error": "Invalid API Key"}` +* 400: `{"error": "Missing required parameter: prompt"}` +* 429: `{"error": "Insufficient balance"}` (余额不足) +### 真人素材API错误 +| 错误信息 | 原因 | 解决方案 | +|----------|------|----------| +| `供应商配置不存在` | 营运人员未配置 AK/SK | 联系管理员配置 | +| `供应商服务已停用` | 供应商配置状态非 active | 联系管理员激活配置 | +| `无效的素材组合ID或无权访问` | vendor_group_id 不属于当前机构 | 确认是否已完成认证并使用正确的 ID | +| `素材不存在或无权访问` | asset_id 无效或归属错误 | 检查 ID 是否正确 | +| `尚未完成认证或认证失败` | 认证未完成 | 等待用户完成 H5 认证 | diff --git a/wwwroot/public/api/index.ui b/wwwroot/public/api/index.ui index 08b772bf..6b197202 100644 --- a/wwwroot/public/api/index.ui +++ b/wwwroot/public/api/index.ui @@ -13,5 +13,22 @@ "md_url":"{{entire_url('api_')}}{{params_kw._lang}}.md" } } +{% for myjs in jsfiles() %} + ,{ + "widgettype": "Text", + "options": { + "text": "{{myjs}}" + } + } +{% endfor %} +{% for mycss in cssfiles() %} + ,{ + "widgettype": "Text", + "options": { + "text": "{{mycss}}" + } + } +{% endfor %} + ] } diff --git a/wwwroot/public/llmsquare/statistic/feelog/index.ui b/wwwroot/public/llmsquare/statistic/feelog/index.ui index 08bc8dc1..3db82f82 100644 --- a/wwwroot/public/llmsquare/statistic/feelog/index.ui +++ b/wwwroot/public/llmsquare/statistic/feelog/index.ui @@ -1,4 +1,10 @@ - +{ + "widgettype": "VBox", + "options": { + "cheight": 40, + "width": "100%" + }, + "subwidgets": [ { "id":"feelog", "widgettype":"Tabular", @@ -324,4 +330,6 @@ "cache_limit":5 } +} + ] } diff --git a/wwwroot/public/mainpage/index.ui b/wwwroot/public/mainpage/index.ui index 29d3022e..3e432488 100644 --- a/wwwroot/public/mainpage/index.ui +++ b/wwwroot/public/mainpage/index.ui @@ -3,20 +3,30 @@ "options":{ "height": "100%", "width": "100%" + }, "subwidgets":[ { - "widgettype":"MdWidget", + "widgettype": "VScrollPanel", "options":{ - "width":"50%", - "md_url":"{{entire_url('mainpage_')}}{{params_kw._lang}}.md", - "height":"100%" - } + "height": "100%", + "width": "50%" + }, + "subwidgets": [ + { + "widgettype":"MdWidget", + "options":{ + "width":"100%", + "md_url":"{{entire_url('mainpage_')}}{{params_kw._lang}}.md" + } + } + ] }, { "widgettype": "Image", "options": { "width": "49%", + "height": "auto", "url": "{{entire_url('wish.webp')}}" } } diff --git a/wwwroot/public/mainpage/mainpage_en.md b/wwwroot/public/mainpage/mainpage_en.md index 9d507130..8c39241a 100644 --- a/wwwroot/public/mainpage/mainpage_en.md +++ b/wwwroot/public/mainpage/mainpage_en.md @@ -1,15 +1,19 @@ -# Everything is Easy Now -In ancient times, if you wanted to build a barrel, you had to master carpentry. To build a carriage, you needed years of experience. To write an app? You definitely had to learn coding. +# Our Apologies +We are running a bit behind schedule. We promised that you could start making wishes on May 1st, but the "Wishing Well" is still under construction and cannot yet accept your requests. -Hence the old saying: "If you don't have the diamond-tipped drill, don't take on the porcelain repair job." In other words, young man, don't be so naive and overestimate your abilities! +We are working hard to catch up, and our next goal is to have the Wishing Well ready by June 1st. -These days, you still need that "diamond-tipped drill," but it doesn't have to be in your hand. You just need to call upon the AI that has it. +# Everything Has Become Easy +In the old days, to make a wooden bucket, you had to master carpentry; to build a carriage, you needed years of craftsmanship; to write an app, you had to know how to code. -Your job? Simply write a clear specification manual and tell the AI: "Let it happen." +As the ancient proverb goes: "Don't take on porcelain work if you don't have the diamond drill." In other words, young man, don't be overambitious. -This is Specification Sheet Programming. Doesn't it feel just like making a wish upon a genie? +Today, you still need a "diamond drill," but it no longer needs to be in your own hands. You only need to call upon an AI that possesses that drill. -Who doesn't know how to make a wish? +What you need to do is draft a precise Product Specification and tell the AI: "Go ahead, build it." -Starting May 1st, 2026, come on over to https://opencomputing.ai and make yours! +This is "Specification-Based Programming." Doesn't it feel like making a wish to a Genie in a lamp? +And who doesn't know how to make a wish? + +Starting from June 1st, 2026, come to opencomputing.ai and make your wish. diff --git a/wwwroot/public/mainpage/mainpage_jp.md b/wwwroot/public/mainpage/mainpage_jp.md index d97a50b5..60b7944b 100644 --- a/wwwroot/public/mainpage/mainpage_jp.md +++ b/wwwroot/public/mainpage/mainpage_jp.md @@ -1,16 +1,19 @@ -# 何でもすぐに作れる時代 +# お詫び +予定より遅れております。5月1日から「願い事」を受け付けると約束していましたが、現在「願いの池」を建設中のため、まだ受け付けることができません。 -昔の時代、桶を作りたければ大工の技術を習得しなければならず、車を作りたければ長年の経験が必要でした。アプリを作りたければ、プログラミングができなくてはなりませんでした。 +現在、急ピッチで作業を進めており、次の目標として6月1日までに完成させる予定です。 -昔の人はよく言いました。「金刚钻(こんごうさん)を持たざれば、瓷器(さいき)の仕事は請け負うなかれ。若造は分別のない真似をするな。」 +# 何事も容易になる時代 +昔、木の桶を作るには木工の技術が必要でした。馬車を作るには長年の経験が必要でした。アプリを書くにはプログラミングを学ばなければなりませんでした。 -今でも「金刚钻」は必要ですが、それを自分の手に持つ必要はありません。その「金刚钻」を持っているAIを呼べばいいのです。 +古くからの格言に「金剛鑽(ダイヤモンドのドリル)がなければ、陶磁器の細工は引き受けるな」という言葉があります。「若者よ、身の程を知れ」という意味です。 -あなたの仕事は、製品の仕様書をきちんと作成し、AIに「やってくれ」と言うだけ。 +現代でも「金剛鑽」は必要ですが、それはあなたの手にある必要はありません。そのドリルを持つAIを呼び出せばいいのです。 -これが「仕様書プログラミング」です。まるで魔法のランプのジーニーに願い事をするようなものではありませんか? +あなたがすべきことは、製品の「仕様書」をまとめ、AIに「さあ、作れ」と伝えることだけです。 -願い事をするのなんて、誰にでもできますよね。 +これこそが「仕様書プログラミング」です。まるでランプの魔神に願い事をしているようではありませんか? -2026年5月1日から、opencomputing.aiで願いを叶えてみませんか。 +願い事なら、誰でもできるはずです。 +2026年6月1日から、opencomputing.ai で願いを託してみてください。 diff --git a/wwwroot/public/mainpage/mainpage_ko.md b/wwwroot/public/mainpage/mainpage_ko.md new file mode 100644 index 00000000..a90aa17e --- /dev/null +++ b/wwwroot/public/mainpage/mainpage_ko.md @@ -0,0 +1,19 @@ +# 사과드립니다 +약속했던 5월 1일보다 일정이 늦어졌습니다. "소원의 연못"이 아직 완공되지 않아 여러분의 소원을 받을 준비가 되지 않았습니다. + +저희는 현재 박차를 가하고 있으며, 다음 목표인 6월 1일까지는 완공될 수 있도록 노력하겠습니다. + +# 무엇이든 쉬워지는 세상 +옛날에는 나무통을 만들려면 목공 기술을 배워야 했고, 수레를 만들려면 수년간의 제작 경험이 필요했으며, 앱을 만들려면 코딩을 할 줄 알아야 했습니다. + +옛 명언에 "금강찬(다이아몬드 드릴)이 없으면 도자기 일을 맡지 마라"는 말이 있습니다. 젊은이여, 천지분간을 못 하고 덤비지 말라는 뜻이었죠. + +지금도 "금강찬"은 필요하지만, 굳이 당신의 손에 있을 필요는 없습니다. 그 드릴을 가진 AI를 호출하기만 하면 됩니다. + +당신이 할 일은 제품의 규격 설명서를 잘 작성하여 AI에게 "자, 만들어라"라고 말하는 것뿐입니다. + +이것이 바로 "규격 설명서 프로그래밍"입니다. 마치 램프의 지니에게 소원을 비는 것 같지 않나요? + +소원을 비는 것쯤이야 누구나 할 수 있는 일이죠. + +2026년 6월 1일부터, opencomputing.ai에서 당신의 소원을 빌어보세요. diff --git a/wwwroot/public/mainpage/mainpage_zh.md b/wwwroot/public/mainpage/mainpage_zh.md index a880dd56..e6de0319 100644 --- a/wwwroot/public/mainpage/mainpage_zh.md +++ b/wwwroot/public/mainpage/mainpage_zh.md @@ -1,3 +1,8 @@ +# 抱歉 +我们延迟了, 说好的5月1日可以来许愿的, 由于许愿池还没建好,还不能接收大家的许愿 + +我们在努力赶工,下一个希望在6月1日前建好许愿池 + # 做什么都容易 在古代,人们要做一个木桶,必须要学会木工技能, 要造一部车,必须要有多年的造车经验,要写一个app, 必须要会编程 diff --git a/wwwroot/shell_theme.css b/wwwroot/shell_theme.css new file mode 120000 index 00000000..fe14dae1 --- /dev/null +++ b/wwwroot/shell_theme.css @@ -0,0 +1 @@ +../../dashboard_for_sage/wwwroot/shell_theme.css \ No newline at end of file diff --git a/wwwroot/shell_theme.js b/wwwroot/shell_theme.js new file mode 120000 index 00000000..af0c87ec --- /dev/null +++ b/wwwroot/shell_theme.js @@ -0,0 +1 @@ +../../dashboard_for_sage/wwwroot/shell_theme.js \ No newline at end of file diff --git a/wwwroot/tenant/imgs/case-forestry.png b/wwwroot/tenant/imgs/case-forestry.png new file mode 100644 index 00000000..e900a0a5 Binary files /dev/null and b/wwwroot/tenant/imgs/case-forestry.png differ diff --git a/wwwroot/tenant/imgs/case-port.png b/wwwroot/tenant/imgs/case-port.png new file mode 100644 index 00000000..ad16ae43 Binary files /dev/null and b/wwwroot/tenant/imgs/case-port.png differ diff --git a/wwwroot/tenant/imgs/case-railway.png b/wwwroot/tenant/imgs/case-railway.png new file mode 100644 index 00000000..79c14027 Binary files /dev/null and b/wwwroot/tenant/imgs/case-railway.png differ diff --git a/wwwroot/tenant/imgs/hero-bg.png b/wwwroot/tenant/imgs/hero-bg.png new file mode 100644 index 00000000..d5e4d015 Binary files /dev/null and b/wwwroot/tenant/imgs/hero-bg.png differ diff --git a/wwwroot/tenant/imgs/logo.png b/wwwroot/tenant/imgs/logo.png new file mode 100644 index 00000000..f8fce947 Binary files /dev/null and b/wwwroot/tenant/imgs/logo.png differ diff --git a/wwwroot/tenant/index.ui b/wwwroot/tenant/index.ui new file mode 100644 index 00000000..e13c41ac --- /dev/null +++ b/wwwroot/tenant/index.ui @@ -0,0 +1,192 @@ +{ + "widgettype": "VBox", + "options": { + "css": "tenant-landing", + "width": "100%", + "spacing": 0 + }, + "subwidgets": [ + { + "widgettype": "HBox", + "options": { + "css": "tenant-header", + "width": "100%", + "padding": "0 40px", + "alignItems": "center", + "justifyContent": "space-between" + }, + "subwidgets": [ + { + "widgettype": "Image", + "options": { + "url": "{{entire_url('/tenant/imgs/logo.png')}}", + "css": "tenant-logo" + } + }, + { + "widgettype": "HBox", + "options": { + "css": "tenant-nav", + "spacing": "30px", + "alignItems": "center" + }, + "subwidgets": [ + {"widgettype": "Text", "options": {"text": "Home", "css": "nav-link"}}, + {"widgettype": "Text", "options": {"text": "Products", "css": "nav-link"}}, + {"widgettype": "Text", "options": {"text": "Use Cases", "css": "nav-link"}}, + {"widgettype": "Text", "options": {"text": "News", "css": "nav-link"}} + ] + }, + { + "widgettype": "Button", + "options": {"label": "Login", "css": "login-btn"}, + "binds": [{ + "wid": "self", + "event": "click", + "actiontype": "script", + "script": "window.location.href='{{entire_url('/rbac/user/login.ui')}}';" + }] + } + ] + }, + { + "widgettype": "HBox", + "options": { + "css": "tenant-hero", + "width": "100%", + "padding": "100px 40px", + "alignItems": "center", + "justifyContent": "space-between" + }, + "subwidgets": [ + { + "widgettype": "VBox", + "options": {"css": "hero-content", "width": "50%", "spacing": "24px"}, + "subwidgets": [ + {"widgettype": "Text", "options": {"text": "One Platform · Intelligent Leap · Across All Industries", "css": "hero-title"}}, + {"widgettype": "Text", "options": {"text": "Make AI Everywhere, Make AI Easy", "css": "hero-subtitle"}}, + {"widgettype": "Button", "options": {"label": "Solutions", "css": "hero-btn"}} + ] + }, + { + "widgettype": "Image", + "options": { + "url": "{{entire_url('/tenant/imgs/hero-bg.png')}}", + "css": "hero-image" + } + } + ] + }, + { + "widgettype": "VBox", + "options": {"css": "tenant-solutions", "width": "100%", "padding": "80px 40px", "spacing": "40px"}, + "subwidgets": [ + {"widgettype": "Text", "options": {"text": "AI + Solutions", "css": "section-title"}}, + { + "widgettype": "HBox", + "options": {"css": "solution-cards", "width": "100%", "spacing": "24px", "justifyContent": "center"}, + "subwidgets": [ + { + "widgettype": "VBox", + "options": {"css": "solution-card", "width": "30%", "padding": "24px", "spacing": "16px"}, + "subwidgets": [ + {"widgettype": "Text", "options": {"text": "Instant Answers", "css": "card-title"}}, + {"widgettype": "Text", "options": {"text": "AI-powered Q&A engine built on enterprise private knowledge bases, supporting natural language queries for business data, technical specifications, and policy documents.", "css": "card-text"}}, + { + "widgettype": "VBox", + "options": {"spacing": "8px"}, + "subwidgets": [ + {"widgettype": "Text", "options": {"text": "< 3 sec Response time", "css": "card-stat"}}, + {"widgettype": "Text", "options": {"text": "100% Source traceability", "css": "card-stat"}} + ] + } + ] + }, + { + "widgettype": "VBox", + "options": {"css": "solution-card", "width": "30%", "padding": "24px", "spacing": "16px"}, + "subwidgets": [ + {"widgettype": "Text", "options": {"text": "Collaborative Intelligence", "css": "card-title"}}, + {"widgettype": "Text", "options": {"text": "Multiple AI agents collaborate autonomously based on role specialization, completing the full workflow of information gathering, data analysis, logical reasoning, and conclusion generation.", "css": "card-text"}}, + { + "widgettype": "VBox", + "options": {"spacing": "8px"}, + "subwidgets": [ + {"widgettype": "Text", "options": {"text": "10x+ Efficiency improvement", "css": "card-stat"}}, + {"widgettype": "Text", "options": {"text": "Real-time Multi-source fusion", "css": "card-stat"}} + ] + } + ] + }, + { + "widgettype": "VBox", + "options": {"css": "solution-card", "width": "30%", "padding": "24px", "spacing": "16px"}, + "subwidgets": [ + {"widgettype": "Text", "options": {"text": "Spatial Intelligence", "css": "card-title"}}, + {"widgettype": "Text", "options": {"text": "Integrating Geographic Information Systems, satellite remote sensing imagery, and drone aerial photography, AI automatically identifies land feature boundaries and analyzes spatial relationships.", "css": "card-text"}}, + { + "widgettype": "VBox", + "options": {"spacing": "8px"}, + "subwidgets": [ + {"widgettype": "Text", "options": {"text": "Days to minutes", "css": "card-stat"}}, + {"widgettype": "Text", "options": {"text": "90%+ Detection accuracy", "css": "card-stat"}} + ] + } + ] + } + ] + } + ] + }, + { + "widgettype": "VBox", + "options": {"css": "tenant-cases", "width": "100%", "padding": "80px 40px", "spacing": "40px"}, + "subwidgets": [ + {"widgettype": "Text", "options": {"text": "Use Cases", "css": "section-title"}}, + { + "widgettype": "HBox", + "options": {"css": "case-cards", "width": "100%", "spacing": "24px", "justifyContent": "center"}, + "subwidgets": [ + { + "widgettype": "VBox", + "options": {"css": "case-card", "width": "30%", "spacing": "16px"}, + "subwidgets": [ + {"widgettype": "Image", "options": {"url": "{{entire_url('/tenant/imgs/case-railway.png')}}", "css": "case-image"}}, + {"widgettype": "Text", "options": {"text": "Smart Engineering", "css": "case-title"}}, + {"widgettype": "Text", "options": {"text": "China Railway · Huitobid", "css": "case-company"}}, + {"widgettype": "Text", "options": {"text": "Built intelligent bidding system covering the full lifecycle from document analysis to smart bid compilation.", "css": "case-desc"}} + ] + }, + { + "widgettype": "VBox", + "options": {"css": "case-card", "width": "30%", "spacing": "16px"}, + "subwidgets": [ + {"widgettype": "Image", "options": {"url": "{{entire_url('/tenant/imgs/case-forestry.png')}}", "css": "case-image"}}, + {"widgettype": "Text", "options": {"text": "Smart Harvesting", "css": "case-title"}}, + {"widgettype": "Text", "options": {"text": "Nanning Forestry Bureau", "css": "case-company"}}, + {"widgettype": "Text", "options": {"text": "Intelligent forest harvesting spatial review system integrating GIS, satellite remote sensing, and UAV data.", "css": "case-desc"}} + ] + }, + { + "widgettype": "VBox", + "options": {"css": "case-card", "width": "30%", "spacing": "16px"}, + "subwidgets": [ + {"widgettype": "Image", "options": {"url": "{{entire_url('/tenant/imgs/case-port.png')}}", "css": "case-image"}}, + {"widgettype": "Text", "options": {"text": "Digital Transformation", "css": "case-title"}}, + {"widgettype": "Text", "options": {"text": "Beibu Gulf Port Big Data", "css": "case-company"}}, + {"widgettype": "Text", "options": {"text": "Full-stack AI agent solution covering bidding, investment decision-making, and contract review.", "css": "case-desc"}} + ] + } + ] + } + ] + }, + { + "widgettype": "HBox", + "options": {"css": "tenant-footer", "width": "100%", "padding": "40px", "justifyContent": "center", "alignItems": "center"}, + "subwidgets": [ + {"widgettype": "Text", "options": {"text": "© 2024 Open Computing. All rights reserved.", "css": "footer-text"}} + ] + } + ] +} diff --git a/wwwroot/tenant/landing.css b/wwwroot/tenant/landing.css new file mode 100644 index 00000000..cd2458f5 --- /dev/null +++ b/wwwroot/tenant/landing.css @@ -0,0 +1,139 @@ +/* ===== Tenant Landing Page ===== */ + +/* Header */ +.tenant-header { + background: rgba(255,255,255,0.95); + box-shadow: 0 2px 8px rgba(0,0,0,0.06); + position: sticky; + top: 0; + z-index: 100; +} + +.nav-item { + cursor: pointer; + font-size: 15px; + color: #333; + transition: color 0.2s; +} +.nav-item:hover { + color: #6366f1; +} + +/* Hero */ +.tenant-hero { + background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 50%, #a855f7 100%); + color: #fff; + text-align: center; + min-height: 400px; + display: flex; + flex-direction: column; + justify-content: center; +} + +.hero-title { + color: #fff !important; + font-size: 42px !important; + font-weight: 700 !important; +} + +.hero-subtitle { + color: rgba(255,255,255,0.85) !important; + font-size: 20px !important; + font-weight: 400 !important; + margin-top: 16px !important; +} + +/* Buttons */ +.primary.large { + background: #fff !important; + color: #6366f1 !important; + font-size: 16px !important; + padding: 12px 32px !important; + border-radius: 8px !important; +} + +.secondary.large { + background: transparent !important; + color: #fff !important; + border: 2px solid rgba(255,255,255,0.6) !important; + font-size: 16px !important; + padding: 12px 32px !important; + border-radius: 8px !important; +} + +/* Solutions */ +.tenant-solutions { + background: #f8f9fa; +} + +.section-title { + text-align: center; + font-size: 32px !important; + font-weight: 700 !important; + color: #1a1a2e !important; +} + +.solution-card { + background: #fff; + border-radius: 12px; + box-shadow: 0 4px 20px rgba(0,0,0,0.08); + transition: transform 0.2s, box-shadow 0.2s; +} +.solution-card:hover { + transform: translateY(-4px); + box-shadow: 0 8px 30px rgba(0,0,0,0.12); +} + +/* Cases */ +.case-card { + background: #fff; + border-radius: 12px; + overflow: hidden; + box-shadow: 0 4px 20px rgba(0,0,0,0.08); +} + +.case-image { + border-radius: 0; +} + +.case-title { + padding: 16px 16px 4px; + font-weight: 600 !important; +} + +.case-subtitle { + padding: 0 16px 16px; + color: #666; + font-size: 14px; +} + +/* Footer */ +.tenant-footer { + background: #1a1a2e; +} + +.footer-text { + color: rgba(255,255,255,0.6); + font-size: 14px; +} + +/* Dark mode support */ +[data-theme="dark"] .tenant-header { + background: rgba(30,30,46,0.95); +} +[data-theme="dark"] .nav-item { + color: #ccc; +} +[data-theme="dark"] .tenant-solutions { + background: #1e1e2e; +} +[data-theme="dark"] .solution-card { + background: #2a2a3e; + color: #eee; +} +[data-theme="dark"] .case-card { + background: #2a2a3e; +} +[data-theme="dark"] .case-subtitle { + color: #aaa; +} diff --git a/wwwroot/tenant/tenant.css b/wwwroot/tenant/tenant.css new file mode 100644 index 00000000..9d881d47 --- /dev/null +++ b/wwwroot/tenant/tenant.css @@ -0,0 +1,197 @@ +.tenant-landing { + background: #fff; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; +} + +.tenant-header { + background: rgba(255,255,255,0.95); + box-shadow: 0 2px 8px rgba(0,0,0,0.06); + position: sticky; + top: 0; + z-index: 100; + height: 80px; +} + +.tenant-logo img { + height: 50px; +} + +.tenant-nav { + gap: 30px; +} + +.nav-link { + cursor: pointer; + font-size: 15px; + color: #374151; + font-weight: 500; + transition: color 0.2s; +} + +.nav-link:hover { + color: #3b82f6; +} + +.login-btn { + background: #3b82f6 !important; + color: #fff !important; + border: none !important; + padding: 10px 24px !important; + border-radius: 8px !important; + font-size: 14px !important; + font-weight: 600 !important; + cursor: pointer !important; +} + +.login-btn:hover { + background: #2563eb !important; +} + +.tenant-hero { + background: linear-gradient(180deg, #f0f7ff 0%, #fff 60%, #f5f8ff 100%); + min-height: 520px; +} + +.hero-content { + color: #111827; +} + +.hero-title { + font-size: 56px !important; + font-weight: 800 !important; + line-height: 1.15 !important; + color: #111827 !important; +} + +.hero-subtitle { + font-size: 22px !important; + color: #4b5563 !important; + font-weight: 400 !important; +} + +.hero-btn { + background: #3b82f6 !important; + color: #fff !important; + border: none !important; + padding: 14px 36px !important; + border-radius: 8px !important; + font-size: 16px !important; + font-weight: 600 !important; + cursor: pointer !important; +} + +.hero-btn:hover { + background: #2563eb !important; +} + +.hero-image { + width: 45%; +} + +.tenant-solutions { + background: #fff; +} + +.section-title { + font-size: 36px !important; + font-weight: 700 !important; + text-align: center !important; + color: #111827 !important; + margin-bottom: 20px !important; +} + +.solution-cards { + display: flex; + justify-content: center; + gap: 24px; +} + +.solution-card { + background: #fff; + border-radius: 16px; + box-shadow: 0 4px 24px rgba(0,0,0,0.06); + transition: transform 0.2s, box-shadow 0.2s; +} + +.solution-card:hover { + transform: translateY(-4px); + box-shadow: 0 8px 30px rgba(0,0,0,0.12); +} + +.card-title { + font-size: 24px !important; + font-weight: 700 !important; + color: #111827 !important; +} + +.card-text { + font-size: 15px !important; + color: #6b7280 !important; + line-height: 1.6 !important; +} + +.card-stat { + font-size: 14px !important; + color: #3b82f6 !important; + font-weight: 600 !important; +} + +.tenant-cases { + background: #f8faff; +} + +.case-cards { + display: flex; + justify-content: center; + gap: 24px; +} + +.case-card { + background: #fff; + border-radius: 16px; + overflow: hidden; + box-shadow: 0 4px 24px rgba(0,0,0,0.06); + transition: transform 0.2s; +} + +.case-card:hover { + transform: translateY(-4px); +} + +.case-image img { + width: 100%; + height: 200px; + object-fit: cover; +} + +.case-title { + font-size: 20px !important; + font-weight: 700 !important; + color: #111827 !important; + padding: 0 20px !important; +} + +.case-company { + font-size: 14px !important; + color: #3b82f6 !important; + font-weight: 600 !important; + padding: 0 20px !important; +} + +.case-desc { + font-size: 14px !important; + color: #6b7280 !important; + line-height: 1.6 !important; + padding: 0 20px 20px !important; +} + +.tenant-footer { + background: #111827; + color: #fff; + min-height: 80px; +} + +.footer-text { + color: rgba(255,255,255,0.6); + font-size: 14px !important; +} diff --git a/wwwroot/tenant_brand.ui b/wwwroot/tenant_brand.ui new file mode 100644 index 00000000..0dfe323b --- /dev/null +++ b/wwwroot/tenant_brand.ui @@ -0,0 +1,26 @@ +# 租户品牌设置 - 设置左上角图标和系统名称 +userorgid = await get_userorgid() +env = request._run_ns +async with get_sor_context(env, 'sage') as sor: + org = (await sor.sqlExe('SELECT orgname, iconid FROM organization WHERE id = ${orgid}$', {'orgid': userorgid}))[0] + +result = { + "widgettype": "VBox", + "options": {"width": "100%", "padding": "20px", "spacing": 16}, + "subwidgets": [ + {"widgettype": "Title3", "options": {"text": "租户品牌设置"}}, + {"widgettype": "Text", "options": {"text": "设置左上角显示的图标和系统名称"}}, + { + "widgettype": "Form", + "options": { + "url": entire_url('./tenant_brand_save.dspy'), + "cols": 1, + "submit_label": "保存", + "fields": [ + {"name": "orgname", "type": "text", "label": "系统名称", "default": org.orgname or ''}, + {"name": "iconid", "type": "file", "label": "图标(SVG/PNG)", "uitype": "file", "accept": ".svg,.png,.jpg"} + ] + } + } + ] +} diff --git a/wwwroot/tenant_brand_data.dspy b/wwwroot/tenant_brand_data.dspy new file mode 100644 index 00000000..097798d2 --- /dev/null +++ b/wwwroot/tenant_brand_data.dspy @@ -0,0 +1,11 @@ +# 返回租户品牌数据(系统名+图标) +userorgid = await get_userorgid() +env = request._run_ns +async with get_sor_context(env, 'sage') as sor: + orgs = await sor.sqlExe('SELECT orgname, iconid, brand_name FROM organization WHERE id = ${orgid}$', {'orgid': userorgid}) + org = orgs[0] if orgs else None + display_name = org.brand_name if org and org.brand_name else (org.orgname if org and org.orgname else 'OpenComputing') + iconid = org.iconid if org and org.iconid else '' + +result = json.dumps({"orgname": display_name, "iconid": iconid}, ensure_ascii=False) +return result diff --git a/wwwroot/tenant_brand_save.dspy b/wwwroot/tenant_brand_save.dspy new file mode 100644 index 00000000..833a37da --- /dev/null +++ b/wwwroot/tenant_brand_save.dspy @@ -0,0 +1,13 @@ +# 保存租户品牌设置 +userorgid = await get_userorgid() +orgname = params_kw.get('orgname', '') +iconid = params_kw.get('iconid', '') + +env = request._run_ns +async with get_sor_context(env, 'sage') as sor: + await sor.U('organization', {'id': userorgid, 'orgname': orgname, 'iconid': iconid}) + +result = { + "widgettype": "Message", + "options": {"title": "成功", "message": "品牌设置已保存,刷新页面生效", "type": "success"} +} diff --git a/wwwroot/test_rf.dspy b/wwwroot/test_rf.dspy new file mode 100644 index 00000000..65525bf1 --- /dev/null +++ b/wwwroot/test_rf.dspy @@ -0,0 +1,10 @@ +import json +from appPublic.registerfunction import RegisterFunction +from appPublic.log import debug + +rf = RegisterFunction() +funcs = list(rf.registKW.keys()) +debug(f'Registered functions: {funcs}') + +result = {'functions': funcs} +return json.dumps(result, ensure_ascii=False) diff --git a/wwwroot/tokentest.opencomputing.cn/Sortable.min.js b/wwwroot/tokentest.opencomputing.cn/Sortable.min.js new file mode 100644 index 00000000..bb995335 --- /dev/null +++ b/wwwroot/tokentest.opencomputing.cn/Sortable.min.js @@ -0,0 +1,2 @@ +/*! Sortable 1.15.2 - MIT | git://github.com/SortableJS/Sortable.git */ +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t=t||self).Sortable=e()}(this,function(){"use strict";function e(e,t){var n,o=Object.keys(e);return Object.getOwnPropertySymbols&&(n=Object.getOwnPropertySymbols(e),t&&(n=n.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),o.push.apply(o,n)),o}function I(o){for(var t=1;tt.length)&&(e=t.length);for(var n=0,o=new Array(e);n"===e[0]&&(e=e.substring(1)),t))try{if(t.matches)return t.matches(e);if(t.msMatchesSelector)return t.msMatchesSelector(e);if(t.webkitMatchesSelector)return t.webkitMatchesSelector(e)}catch(t){return}}function P(t,e,n,o){if(t){n=n||document;do{if(null!=e&&(">"!==e[0]||t.parentNode===n)&&p(t,e)||o&&t===n)return t}while(t!==n&&(t=(i=t).host&&i!==document&&i.host.nodeType?i.host:i.parentNode))}var i;return null}var g,m=/\s+/g;function k(t,e,n){var o;t&&e&&(t.classList?t.classList[n?"add":"remove"](e):(o=(" "+t.className+" ").replace(m," ").replace(" "+e+" "," "),t.className=(o+(n?" "+e:"")).replace(m," ")))}function R(t,e,n){var o=t&&t.style;if(o){if(void 0===n)return document.defaultView&&document.defaultView.getComputedStyle?n=document.defaultView.getComputedStyle(t,""):t.currentStyle&&(n=t.currentStyle),void 0===e?n:n[e];o[e=!(e in o||-1!==e.indexOf("webkit"))?"-webkit-"+e:e]=n+("string"==typeof n?"":"px")}}function v(t,e){var n="";if("string"==typeof t)n=t;else do{var o=R(t,"transform")}while(o&&"none"!==o&&(n=o+" "+n),!e&&(t=t.parentNode));var i=window.DOMMatrix||window.WebKitCSSMatrix||window.CSSMatrix||window.MSCSSMatrix;return i&&new i(n)}function b(t,e,n){if(t){var o=t.getElementsByTagName(e),i=0,r=o.length;if(n)for(;i=n.left-e&&i<=n.right+e,e=r>=n.top-e&&r<=n.bottom+e;return o&&e?a=t:void 0}}),a);if(e){var n,o={};for(n in t)t.hasOwnProperty(n)&&(o[n]=t[n]);o.target=o.rootEl=e,o.preventDefault=void 0,o.stopPropagation=void 0,e[K]._onDragOver(o)}}var i,r,a}function Bt(t){V&&V.parentNode[K]._isOutsideThisEl(t.target)}function Ft(t,e){if(!t||!t.nodeType||1!==t.nodeType)throw"Sortable: `el` must be an HTMLElement, not ".concat({}.toString.call(t));this.el=t,this.options=e=a({},e),t[K]=this;var n,o,i={group:null,sort:!0,disabled:!1,store:null,handle:null,draggable:/^[uo]l$/i.test(t.nodeName)?">li":">*",swapThreshold:1,invertSwap:!1,invertedSwapThreshold:null,removeCloneOnHide:!0,direction:function(){return Pt(t,this.options)},ghostClass:"sortable-ghost",chosenClass:"sortable-chosen",dragClass:"sortable-drag",ignore:"a, img",filter:null,preventOnFilter:!0,animation:0,easing:null,setData:function(t,e){t.setData("Text",e.textContent)},dropBubble:!1,dragoverBubble:!1,dataIdAttr:"data-id",delay:0,delayOnTouchOnly:!1,touchStartThreshold:(Number.parseInt?Number:window).parseInt(window.devicePixelRatio,10)||1,forceFallback:!1,fallbackClass:"sortable-fallback",fallbackOnBody:!1,fallbackTolerance:0,fallbackOffset:{x:0,y:0},supportPointer:!1!==Ft.supportPointer&&"PointerEvent"in window&&!u,emptyInsertThreshold:5};for(n in W.initializePlugins(this,t,i),i)n in e||(e[n]=i[n]);for(o in kt(e),this)"_"===o.charAt(0)&&"function"==typeof this[o]&&(this[o]=this[o].bind(this));this.nativeDraggable=!e.forceFallback&&Nt,this.nativeDraggable&&(this.options.touchStartThreshold=1),e.supportPointer?h(t,"pointerdown",this._onTapStart):(h(t,"mousedown",this._onTapStart),h(t,"touchstart",this._onTapStart)),this.nativeDraggable&&(h(t,"dragover",this),h(t,"dragenter",this)),Dt.push(this.el),e.store&&e.store.get&&this.sort(e.store.get(this)||[]),a(this,x())}function jt(t,e,n,o,i,r,a,l){var s,c,u=t[K],d=u.options.onMove;return!window.CustomEvent||y||w?(s=document.createEvent("Event")).initEvent("move",!0,!0):s=new CustomEvent("move",{bubbles:!0,cancelable:!0}),s.to=e,s.from=t,s.dragged=n,s.draggedRect=o,s.related=i||e,s.relatedRect=r||X(e),s.willInsertAfter=l,s.originalEvent=a,t.dispatchEvent(s),c=d?d.call(u,s,a):c}function Ht(t){t.draggable=!1}function Lt(){Tt=!1}function Kt(t){return setTimeout(t,0)}function Wt(t){return clearTimeout(t)}Ft.prototype={constructor:Ft,_isOutsideThisEl:function(t){this.el.contains(t)||t===this.el||(mt=null)},_getDirection:function(t,e){return"function"==typeof this.options.direction?this.options.direction.call(this,t,e,V):this.options.direction},_onTapStart:function(e){if(e.cancelable){var n=this,o=this.el,t=this.options,i=t.preventOnFilter,r=e.type,a=e.touches&&e.touches[0]||e.pointerType&&"touch"===e.pointerType&&e,l=(a||e).target,s=e.target.shadowRoot&&(e.path&&e.path[0]||e.composedPath&&e.composedPath()[0])||l,c=t.filter;if(!function(t){xt.length=0;var e=t.getElementsByTagName("input"),n=e.length;for(;n--;){var o=e[n];o.checked&&xt.push(o)}}(o),!V&&!(/mousedown|pointerdown/.test(r)&&0!==e.button||t.disabled)&&!s.isContentEditable&&(this.nativeDraggable||!u||!l||"SELECT"!==l.tagName.toUpperCase())&&!((l=P(l,t.draggable,o,!1))&&l.animated||tt===l)){if(ot=j(l),rt=j(l,t.draggable),"function"==typeof c){if(c.call(this,e,l,this))return q({sortable:n,rootEl:s,name:"filter",targetEl:l,toEl:o,fromEl:o}),G("filter",n,{evt:e}),void(i&&e.cancelable&&e.preventDefault())}else if(c=c&&c.split(",").some(function(t){if(t=P(s,t.trim(),o,!1))return q({sortable:n,rootEl:t,name:"filter",targetEl:l,fromEl:o,toEl:o}),G("filter",n,{evt:e}),!0}))return void(i&&e.cancelable&&e.preventDefault());t.handle&&!P(s,t.handle,o,!1)||this._prepareDragStart(e,a,l)}}},_prepareDragStart:function(t,e,n){var o,i=this,r=i.el,a=i.options,l=r.ownerDocument;n&&!V&&n.parentNode===r&&(o=X(n),Q=r,Z=(V=n).parentNode,J=V.nextSibling,tt=n,lt=a.group,ct={target:Ft.dragged=V,clientX:(e||t).clientX,clientY:(e||t).clientY},ft=ct.clientX-o.left,pt=ct.clientY-o.top,this._lastX=(e||t).clientX,this._lastY=(e||t).clientY,V.style["will-change"]="all",o=function(){G("delayEnded",i,{evt:t}),Ft.eventCanceled?i._onDrop():(i._disableDelayedDragEvents(),!s&&i.nativeDraggable&&(V.draggable=!0),i._triggerDragStart(t,e),q({sortable:i,name:"choose",originalEvent:t}),k(V,a.chosenClass,!0))},a.ignore.split(",").forEach(function(t){b(V,t.trim(),Ht)}),h(l,"dragover",Yt),h(l,"mousemove",Yt),h(l,"touchmove",Yt),h(l,"mouseup",i._onDrop),h(l,"touchend",i._onDrop),h(l,"touchcancel",i._onDrop),s&&this.nativeDraggable&&(this.options.touchStartThreshold=4,V.draggable=!0),G("delayStart",this,{evt:t}),!a.delay||a.delayOnTouchOnly&&!e||this.nativeDraggable&&(w||y)?o():Ft.eventCanceled?this._onDrop():(h(l,"mouseup",i._disableDelayedDrag),h(l,"touchend",i._disableDelayedDrag),h(l,"touchcancel",i._disableDelayedDrag),h(l,"mousemove",i._delayedDragTouchMoveHandler),h(l,"touchmove",i._delayedDragTouchMoveHandler),a.supportPointer&&h(l,"pointermove",i._delayedDragTouchMoveHandler),i._dragStartTimer=setTimeout(o,a.delay)))},_delayedDragTouchMoveHandler:function(t){t=t.touches?t.touches[0]:t;Math.max(Math.abs(t.clientX-this._lastX),Math.abs(t.clientY-this._lastY))>=Math.floor(this.options.touchStartThreshold/(this.nativeDraggable&&window.devicePixelRatio||1))&&this._disableDelayedDrag()},_disableDelayedDrag:function(){V&&Ht(V),clearTimeout(this._dragStartTimer),this._disableDelayedDragEvents()},_disableDelayedDragEvents:function(){var t=this.el.ownerDocument;f(t,"mouseup",this._disableDelayedDrag),f(t,"touchend",this._disableDelayedDrag),f(t,"touchcancel",this._disableDelayedDrag),f(t,"mousemove",this._delayedDragTouchMoveHandler),f(t,"touchmove",this._delayedDragTouchMoveHandler),f(t,"pointermove",this._delayedDragTouchMoveHandler)},_triggerDragStart:function(t,e){e=e||"touch"==t.pointerType&&t,!this.nativeDraggable||e?this.options.supportPointer?h(document,"pointermove",this._onTouchMove):h(document,e?"touchmove":"mousemove",this._onTouchMove):(h(V,"dragend",this),h(Q,"dragstart",this._onDragStart));try{document.selection?Kt(function(){document.selection.empty()}):window.getSelection().removeAllRanges()}catch(t){}},_dragStarted:function(t,e){var n;wt=!1,Q&&V?(G("dragStarted",this,{evt:e}),this.nativeDraggable&&h(document,"dragover",Bt),n=this.options,t||k(V,n.dragClass,!1),k(V,n.ghostClass,!0),Ft.active=this,t&&this._appendGhost(),q({sortable:this,name:"start",originalEvent:e})):this._nulling()},_emulateDragOver:function(){if(ut){this._lastX=ut.clientX,this._lastY=ut.clientY,Rt();for(var t=document.elementFromPoint(ut.clientX,ut.clientY),e=t;t&&t.shadowRoot&&(t=t.shadowRoot.elementFromPoint(ut.clientX,ut.clientY))!==e;)e=t;if(V.parentNode[K]._isOutsideThisEl(t),e)do{if(e[K])if(e[K]._onDragOver({clientX:ut.clientX,clientY:ut.clientY,target:t,rootEl:e})&&!this.options.dragoverBubble)break}while(e=(t=e).parentNode);Xt()}},_onTouchMove:function(t){if(ct){var e=this.options,n=e.fallbackTolerance,o=e.fallbackOffset,i=t.touches?t.touches[0]:t,r=$&&v($,!0),a=$&&r&&r.a,l=$&&r&&r.d,e=Mt&&yt&&E(yt),a=(i.clientX-ct.clientX+o.x)/(a||1)+(e?e[0]-Ct[0]:0)/(a||1),l=(i.clientY-ct.clientY+o.y)/(l||1)+(e?e[1]-Ct[1]:0)/(l||1);if(!Ft.active&&!wt){if(n&&Math.max(Math.abs(i.clientX-this._lastX),Math.abs(i.clientY-this._lastY))D.right+10||S.clientY>x.bottom&&S.clientX>x.left:S.clientY>D.bottom+10||S.clientX>x.right&&S.clientY>x.top)||m.animated)){if(m&&(t=n,e=r,C=X(B((_=this).el,0,_.options,!0)),_=L(_.el,_.options,$),e?t.clientX<_.left-10||t.clientY

在线咨询

请留下您的联系方式,我们的顾问将尽快与您联系

信息仅用于顾问联系

';m.style.cssText='position:fixed;top:0;left:0;width:100%;height:100%;z-index:9999';document.body.appendChild(m);}"}]}], "id": "bottom"} \ No newline at end of file diff --git a/wwwroot/tokentest.opencomputing.cn/bottom_jp.ui b/wwwroot/tokentest.opencomputing.cn/bottom_jp.ui new file mode 100644 index 00000000..25711e4b --- /dev/null +++ b/wwwroot/tokentest.opencomputing.cn/bottom_jp.ui @@ -0,0 +1 @@ +{"widgettype": "VBox", "options": {"css": "bottom", "width": "100%", "spacing": 0}, "subwidgets": [{"widgettype": "HBox", "options": {"css": "footer", "width": "100%", "padding": "60px 40px", "spacing": "80px", "justifyContent": "center"}, "subwidgets": [{"widgettype": "VBox", "options": {"spacing": "16px"}, "subwidgets": [{"widgettype": "Image", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/imgs/logo.png')}}", "css": "footer-logo"}}, {"widgettype": "Text", "options": {"text": "让AI无处不在,让AI触手可及", "css": "footer-tagline"}}]}, {"widgettype": "VBox", "options": {"spacing": "12px"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "产品与服务", "css": "footer-heading"}}, {"widgettype": "Text", "options": {"text": "OPC", "css": "footer-link"}}, {"widgettype": "Text", "options": {"text": "算力市场", "css": "footer-link"}}, {"widgettype": "Text", "options": {"text": "Token市场", "css": "footer-link"}}, {"widgettype": "Text", "options": {"text": "元境", "css": "footer-link"}}, {"widgettype": "Text", "options": {"text": "训练推理", "css": "footer-link"}}, {"widgettype": "Text", "options": {"text": "Agent Store", "css": "footer-link"}}, {"widgettype": "Text", "options": {"text": "供应广场", "css": "footer-link"}}]}, {"widgettype": "VBox", "options": {"spacing": "12px"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "联系我们", "css": "footer-heading"}}, {"widgettype": "Text", "options": {"text": "地址:北京市朝阳区东三环中路65号富力中心", "css": "footer-link"}}, {"widgettype": "Text", "options": {"text": "邮箱:Open-computing@kaiyuancloud.cn", "css": "footer-link"}}, {"widgettype": "Text", "options": {"text": "电话:400-6150805 010-65917875", "css": "footer-link"}}, {"widgettype": "HBox", "options": {"spacing": "24px"}, "subwidgets": [{"widgettype": "VBox", "options": {"spacing": "6px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Image", "options": {"url": "https://www.opencomputing.cn/static/img/img.936873a3.png", "css": "footer-qr"}}, {"widgettype": "Text", "options": {"text": "在线咨询", "css": "footer-qr-label"}}]}, {"widgettype": "VBox", "options": {"spacing": "6px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Image", "options": {"url": "https://www.opencomputing.cn/static/img/kefu.96ff99fe.jpg", "css": "footer-qr"}}, {"widgettype": "Text", "options": {"text": "关注公众号", "css": "footer-qr-label"}}]}]}]}]}, {"widgettype": "HBox", "options": {"css": "footer-icp-bar", "width": "100%", "padding": "16px 40px", "justifyContent": "center", "alignItems": "center"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "京ICP备2022001945号-2", "css": "footer-icp-link"}, "binds": [{"wid": "self", "event": "click", "actiontype": "script", "script": "window.open('https://beian.miit.gov.cn/','_blank');"}]}, {"widgettype": "Text", "options": {"text": "开元云(北京)科技有限公司", "css": "footer-icp-text"}}]}, {"widgettype": "VBox", "options": {"css": "float-chat", "spacing": "4px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Image", "options": {"url": "https://www.opencomputing.cn/static/img/ocai.9af463db.jpg", "css": "float-chat-avatar"}}, {"widgettype": "Text", "options": {"text": "在线咨询", "css": "float-chat-label"}}], "binds": [{"wid": "self", "event": "click", "actiontype": "script", "script": "var m=document.getElementById('cmodal');if(!m){m=document.createElement('div');m.id='cmodal';m.innerHTML='

在线咨询

请留下您的联系方式,我们的顾问将尽快与您联系

信息仅用于顾问联系

';m.style.cssText='position:fixed;top:0;left:0;width:100%;height:100%;z-index:9999';document.body.appendChild(m);}"}]}], "id": "bottom"} \ No newline at end of file diff --git a/wwwroot/tokentest.opencomputing.cn/bottom_ko.ui b/wwwroot/tokentest.opencomputing.cn/bottom_ko.ui new file mode 100644 index 00000000..25711e4b --- /dev/null +++ b/wwwroot/tokentest.opencomputing.cn/bottom_ko.ui @@ -0,0 +1 @@ +{"widgettype": "VBox", "options": {"css": "bottom", "width": "100%", "spacing": 0}, "subwidgets": [{"widgettype": "HBox", "options": {"css": "footer", "width": "100%", "padding": "60px 40px", "spacing": "80px", "justifyContent": "center"}, "subwidgets": [{"widgettype": "VBox", "options": {"spacing": "16px"}, "subwidgets": [{"widgettype": "Image", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/imgs/logo.png')}}", "css": "footer-logo"}}, {"widgettype": "Text", "options": {"text": "让AI无处不在,让AI触手可及", "css": "footer-tagline"}}]}, {"widgettype": "VBox", "options": {"spacing": "12px"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "产品与服务", "css": "footer-heading"}}, {"widgettype": "Text", "options": {"text": "OPC", "css": "footer-link"}}, {"widgettype": "Text", "options": {"text": "算力市场", "css": "footer-link"}}, {"widgettype": "Text", "options": {"text": "Token市场", "css": "footer-link"}}, {"widgettype": "Text", "options": {"text": "元境", "css": "footer-link"}}, {"widgettype": "Text", "options": {"text": "训练推理", "css": "footer-link"}}, {"widgettype": "Text", "options": {"text": "Agent Store", "css": "footer-link"}}, {"widgettype": "Text", "options": {"text": "供应广场", "css": "footer-link"}}]}, {"widgettype": "VBox", "options": {"spacing": "12px"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "联系我们", "css": "footer-heading"}}, {"widgettype": "Text", "options": {"text": "地址:北京市朝阳区东三环中路65号富力中心", "css": "footer-link"}}, {"widgettype": "Text", "options": {"text": "邮箱:Open-computing@kaiyuancloud.cn", "css": "footer-link"}}, {"widgettype": "Text", "options": {"text": "电话:400-6150805 010-65917875", "css": "footer-link"}}, {"widgettype": "HBox", "options": {"spacing": "24px"}, "subwidgets": [{"widgettype": "VBox", "options": {"spacing": "6px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Image", "options": {"url": "https://www.opencomputing.cn/static/img/img.936873a3.png", "css": "footer-qr"}}, {"widgettype": "Text", "options": {"text": "在线咨询", "css": "footer-qr-label"}}]}, {"widgettype": "VBox", "options": {"spacing": "6px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Image", "options": {"url": "https://www.opencomputing.cn/static/img/kefu.96ff99fe.jpg", "css": "footer-qr"}}, {"widgettype": "Text", "options": {"text": "关注公众号", "css": "footer-qr-label"}}]}]}]}]}, {"widgettype": "HBox", "options": {"css": "footer-icp-bar", "width": "100%", "padding": "16px 40px", "justifyContent": "center", "alignItems": "center"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "京ICP备2022001945号-2", "css": "footer-icp-link"}, "binds": [{"wid": "self", "event": "click", "actiontype": "script", "script": "window.open('https://beian.miit.gov.cn/','_blank');"}]}, {"widgettype": "Text", "options": {"text": "开元云(北京)科技有限公司", "css": "footer-icp-text"}}]}, {"widgettype": "VBox", "options": {"css": "float-chat", "spacing": "4px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Image", "options": {"url": "https://www.opencomputing.cn/static/img/ocai.9af463db.jpg", "css": "float-chat-avatar"}}, {"widgettype": "Text", "options": {"text": "在线咨询", "css": "float-chat-label"}}], "binds": [{"wid": "self", "event": "click", "actiontype": "script", "script": "var m=document.getElementById('cmodal');if(!m){m=document.createElement('div');m.id='cmodal';m.innerHTML='

在线咨询

请留下您的联系方式,我们的顾问将尽快与您联系

信息仅用于顾问联系

';m.style.cssText='position:fixed;top:0;left:0;width:100%;height:100%;z-index:9999';document.body.appendChild(m);}"}]}], "id": "bottom"} \ No newline at end of file diff --git a/wwwroot/tokentest.opencomputing.cn/bottom_zh.ui b/wwwroot/tokentest.opencomputing.cn/bottom_zh.ui new file mode 100644 index 00000000..25711e4b --- /dev/null +++ b/wwwroot/tokentest.opencomputing.cn/bottom_zh.ui @@ -0,0 +1 @@ +{"widgettype": "VBox", "options": {"css": "bottom", "width": "100%", "spacing": 0}, "subwidgets": [{"widgettype": "HBox", "options": {"css": "footer", "width": "100%", "padding": "60px 40px", "spacing": "80px", "justifyContent": "center"}, "subwidgets": [{"widgettype": "VBox", "options": {"spacing": "16px"}, "subwidgets": [{"widgettype": "Image", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/imgs/logo.png')}}", "css": "footer-logo"}}, {"widgettype": "Text", "options": {"text": "让AI无处不在,让AI触手可及", "css": "footer-tagline"}}]}, {"widgettype": "VBox", "options": {"spacing": "12px"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "产品与服务", "css": "footer-heading"}}, {"widgettype": "Text", "options": {"text": "OPC", "css": "footer-link"}}, {"widgettype": "Text", "options": {"text": "算力市场", "css": "footer-link"}}, {"widgettype": "Text", "options": {"text": "Token市场", "css": "footer-link"}}, {"widgettype": "Text", "options": {"text": "元境", "css": "footer-link"}}, {"widgettype": "Text", "options": {"text": "训练推理", "css": "footer-link"}}, {"widgettype": "Text", "options": {"text": "Agent Store", "css": "footer-link"}}, {"widgettype": "Text", "options": {"text": "供应广场", "css": "footer-link"}}]}, {"widgettype": "VBox", "options": {"spacing": "12px"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "联系我们", "css": "footer-heading"}}, {"widgettype": "Text", "options": {"text": "地址:北京市朝阳区东三环中路65号富力中心", "css": "footer-link"}}, {"widgettype": "Text", "options": {"text": "邮箱:Open-computing@kaiyuancloud.cn", "css": "footer-link"}}, {"widgettype": "Text", "options": {"text": "电话:400-6150805 010-65917875", "css": "footer-link"}}, {"widgettype": "HBox", "options": {"spacing": "24px"}, "subwidgets": [{"widgettype": "VBox", "options": {"spacing": "6px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Image", "options": {"url": "https://www.opencomputing.cn/static/img/img.936873a3.png", "css": "footer-qr"}}, {"widgettype": "Text", "options": {"text": "在线咨询", "css": "footer-qr-label"}}]}, {"widgettype": "VBox", "options": {"spacing": "6px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Image", "options": {"url": "https://www.opencomputing.cn/static/img/kefu.96ff99fe.jpg", "css": "footer-qr"}}, {"widgettype": "Text", "options": {"text": "关注公众号", "css": "footer-qr-label"}}]}]}]}]}, {"widgettype": "HBox", "options": {"css": "footer-icp-bar", "width": "100%", "padding": "16px 40px", "justifyContent": "center", "alignItems": "center"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "京ICP备2022001945号-2", "css": "footer-icp-link"}, "binds": [{"wid": "self", "event": "click", "actiontype": "script", "script": "window.open('https://beian.miit.gov.cn/','_blank');"}]}, {"widgettype": "Text", "options": {"text": "开元云(北京)科技有限公司", "css": "footer-icp-text"}}]}, {"widgettype": "VBox", "options": {"css": "float-chat", "spacing": "4px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Image", "options": {"url": "https://www.opencomputing.cn/static/img/ocai.9af463db.jpg", "css": "float-chat-avatar"}}, {"widgettype": "Text", "options": {"text": "在线咨询", "css": "float-chat-label"}}], "binds": [{"wid": "self", "event": "click", "actiontype": "script", "script": "var m=document.getElementById('cmodal');if(!m){m=document.createElement('div');m.id='cmodal';m.innerHTML='

在线咨询

请留下您的联系方式,我们的顾问将尽快与您联系

信息仅用于顾问联系

';m.style.cssText='position:fixed;top:0;left:0;width:100%;height:100%;z-index:9999';document.body.appendChild(m);}"}]}], "id": "bottom"} \ No newline at end of file diff --git a/wwwroot/tokentest.opencomputing.cn/carousel.js b/wwwroot/tokentest.opencomputing.cn/carousel.js new file mode 100644 index 00000000..79b54364 --- /dev/null +++ b/wwwroot/tokentest.opencomputing.cn/carousel.js @@ -0,0 +1,51 @@ +// Carousel auto-rotation + hover-flip +(function init(){ +var cards=document.querySelectorAll('.carousel-card'); +if(!cards.length){setTimeout(init,500);return;} +var cardArr=Array.from(cards),N=cardArr.length; + +var track=document.querySelector('.carousel-track'); +if(track){track.style.position='relative';track.style.display='block';} + +var mid=Math.floor(N/2); +cardArr.forEach(function(c,i){ + var s=c.style; + s.position='absolute';s.width='280px';s.height='360px'; + s.left='50%';s.top='50%';s.marginLeft='-140px';s.marginTop='-180px'; + s.cursor='pointer';s.transformOrigin='center center';s.willChange='transform,opacity'; + c.setAttribute('data-pos',String(i-mid)); +}); + +// 5 visible levels: 0(center) ±1 ±2 — smooth, continuous, no gaps +var posCfg=[ + {s:1,x:0,z:5,o:1}, // 0 + {s:.85,x:220,z:4,o:.7}, // ±1 + {s:.65,x:390,z:3,o:.4}, // ±2 + {s:.45,x:520,z:2,o:.15}, // ±3 — dim edge + {s:0,x:560,z:1,o:0} // ±4 — invisible, wrap point +]; + +function rotate(dir){ + cardArr.forEach(function(c){ + var p=parseInt(c.getAttribute('data-pos'))||0; + var np=p-dir;if(np>4)np=-4;if(np<-4)np=4; + c.setAttribute('data-pos',String(np)); + }); + cardArr.forEach(function(c){ + var p=parseInt(c.getAttribute('data-pos'))||0; + var a=Math.abs(p),d=posCfg[Math.min(a,4)],x=p>=0?d.x:-d.x; + c.style.transition='all .6s cubic-bezier(.25,.1,.25,1)'; + c.style.transform='translateX('+x+'px) scale('+d.s+')'; + c.style.zIndex=d.z;c.style.opacity=d.o; + c.style.pointerEvents=a>3?'none':'auto'; + }); +} +rotate(0); + +cardArr.forEach(function(c){ + c.addEventListener('mouseenter',function(){c.classList.add('flipped');}); + c.addEventListener('mouseleave',function(){c.classList.remove('flipped');}); +}); + +setInterval(function(){rotate(1);},3000); +})(); diff --git a/wwwroot/tokentest.opencomputing.cn/center_home_en.ui b/wwwroot/tokentest.opencomputing.cn/center_home_en.ui new file mode 100644 index 00000000..528d3a3d --- /dev/null +++ b/wwwroot/tokentest.opencomputing.cn/center_home_en.ui @@ -0,0 +1 @@ +{"widgettype": "VBox", "options": {"css": "center-area", "width": "100%", "spacing": 0}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "hero", "width": "100%", "padding": "120px 40px 100px", "alignItems": "center", "spacing": "16px"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "One Platform · Intelligent Leap ·", "css": "hero-title"}}, {"widgettype": "Text", "options": {"text": "Across All Industries.", "css": "hero-title2"}}, {"widgettype": "Text", "options": {"text": "Make AI Everywhere, Make AI Easy", "css": "hero-sub"}}, {"widgettype": "HBox", "options": {"spacing": "16px"}, "subwidgets": [{"widgettype": "Button", "options": {"label": "Solutions", "css": "hero-btn-primary"}}, {"widgettype": "Button", "options": {"label": "Contact Sales", "css": "hero-btn-outline"}}]}]}, {"widgettype": "VBox", "options": {"css": "section", "width": "100%", "padding": "80px 40px 60px", "spacing": "40px"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "AI + Solutions", "css": "section-title"}}, {"widgettype": "VBox", "options": {"css": "carousel-container"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "carousel-track"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs0", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Full Protection", "css": "card-title"}}, {"widgettype": "Text", "options": {"text": "Device Intelligent Monitoring", "css": "card-subtitle"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Full Protection", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "Build independent monitoring strategies for each device, presenting real-time operational status through 3D visualization. AI automatically identifies anomalies, pinpoints fault locations, and outputs detailed diagnostic recommendations and troubleshooting steps in seconds.", "css": "card-text-white"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs1", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Read and Comprehend", "css": "card-title"}}, {"widgettype": "Text", "options": {"text": "Smart Document Parsing", "css": "card-subtitle"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Read and Comprehend", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "One-click parsing of PDF, Word, and scanned documents. AI automatically extracts key clauses, qualification requirements, and scoring criteria with structured presentation. Not just OCR, but semantic understanding, importance assessment, and risk flagging.", "css": "card-text-white"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs2", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "On-Site Intelligence", "css": "card-title"}}, {"widgettype": "Text", "options": {"text": "Edge AI Inference", "css": "card-subtitle"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "On-Site Intelligence", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "Deploy AI inference at the production edge with lightweight algorithms for millisecond-level real-time decisions. Data stays on-premises — no cloud upload needed. Redundant architecture ensures 7×24 continuous operation, zero downtime for production inspection.", "css": "card-text-white"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs3", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Collaborative Intelligence", "css": "card-title"}}, {"widgettype": "Text", "options": {"text": "Multi-Agent Collaboration", "css": "card-subtitle"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Collaborative Intelligence", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "Multiple AI agents collaborate by role, autonomously handling data collection, analysis, reasoning, and conclusion generation. Dynamic task allocation and context sharing transform complex decisions from human-dependent workflows to parallel agent execution.", "css": "card-text-white"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs4", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Spatial Intelligence", "css": "card-title"}}, {"widgettype": "Text", "options": {"text": "GIS Smart Analysis", "css": "card-subtitle"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Spatial Intelligence", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "Fusing GIS, satellite remote sensing, and UAV imagery, AI automatically identifies terrain boundaries, overlays spatial relationships, and verifies compliance constraints. Upgrades traditional manual geospatial comparison to minute-level automated spatial intelligence.", "css": "card-text-white"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs5", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Predictive Insight", "css": "card-title"}}, {"widgettype": "Text", "options": {"text": "Machine Vision Inspection", "css": "card-subtitle"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Predictive Insight", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "Deep learning-based full-width defect detection for high-speed production lines, covering surface treatment, coating, welding, and assembly. AI compares every inch of product pixel-by-pixel at millisecond speed — zero quality compromise.", "css": "card-text-white"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs6", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Instant Answers", "css": "card-title"}}, {"widgettype": "Text", "options": {"text": "Smart Q&A Knowledge Base", "css": "card-subtitle"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Instant Answers", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "Enterprise private knowledge base AI Q&A engine supporting natural language queries on business data, technical specs, and institutional documents. Every answer cites authoritative sources — traceable and verifiable. Expert knowledge is as accessible as asking a colleague.", "css": "card-text-white"}}]}]}]}]}]}]}, {"widgettype": "VBox", "options": {"css": "section section-alt", "width": "100%", "padding": "80px 40px", "spacing": "40px"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Use Cases", "css": "section-title"}}, {"widgettype": "HBox", "options": {"css": "case-cards", "width": "100%", "spacing": "24px", "justifyContent": "center"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip-front", "spacing": "0"}, "subwidgets": [{"widgettype": "Image", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/imgs/case-railway.png')}}", "css": "case-img"}}, {"widgettype": "Text", "options": {"text": "Smart Engineering", "css": "case-name"}}, {"widgettype": "Text", "options": {"text": "China Railway Group · Huitobid", "css": "case-client"}}, {"widgettype": "Text", "options": {"text": "Built the Huitobid and HuiTu Large Model for China Railway Group, establishing a…", "css": "case-desc"}}]}, {"widgettype": "VBox", "options": {"css": "case-flip-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Smart Engineering", "css": "case-back-title"}}, {"widgettype": "Text", "options": {"text": "Built the Huitobid and HuiTu Large Model for China Railway Group, establishing a Joint Innovation Center and AI Application Innovation Platform. Covering the full bidding lifecycle — intelligent document analysis, automatic qualification matching, pricing decision support, and smart bid compilation.", "css": "case-back-desc"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "case-flip"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip-front", "spacing": "0"}, "subwidgets": [{"widgettype": "Image", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/imgs/case-forestry.png')}}", "css": "case-img"}}, {"widgettype": "Text", "options": {"text": "Smart Harvesting", "css": "case-name"}}, {"widgettype": "Text", "options": {"text": "Nanning Forestry Bureau", "css": "case-client"}}, {"widgettype": "Text", "options": {"text": "Developed an Intelligent Forest Harvesting Spatial Review System integrating GIS…", "css": "case-desc"}}]}, {"widgettype": "VBox", "options": {"css": "case-flip-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Smart Harvesting", "css": "case-back-title"}}, {"widgettype": "Text", "options": {"text": "Developed an Intelligent Forest Harvesting Spatial Review System integrating GIS spatial analysis, satellite remote sensing, and multi-source UAV data. Harvesting boundaries are automatically verified for compliance, review reports are generated with one click, and the approval cycle is compressed from days to minutes.", "css": "case-back-desc"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "case-flip"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip-front", "spacing": "0"}, "subwidgets": [{"widgettype": "Image", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/imgs/case-port.png')}}", "css": "case-img"}}, {"widgettype": "Text", "options": {"text": "Digital Transformation", "css": "case-name"}}, {"widgettype": "Text", "options": {"text": "Beibu Gulf Port Big Data", "css": "case-client"}}, {"widgettype": "Text", "options": {"text": "Developed a full-stack AI agent solution covering bidding, investment decision-m…", "css": "case-desc"}}]}, {"widgettype": "VBox", "options": {"css": "case-flip-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Digital Transformation", "css": "case-back-title"}}, {"widgettype": "Text", "options": {"text": "Developed a full-stack AI agent solution covering bidding, investment decision-making, and contract review. The Bid Agent Engine enables bid document generation in seconds; the Investment Strategy Agent compresses weeks of research into minutes; the Contract Review Agent boosts review efficiency by over 60%.", "css": "case-back-desc"}}]}]}]}]}]}, {"widgettype": "VBox", "options": {"css": "cta", "width": "100%", "padding": "80px 40px", "spacing": "24px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "How Do These Solutions Work in Practice?", "css": "cta-title"}}, {"widgettype": "Text", "options": {"text": "Get industry-specific AI solutions.", "css": "cta-sub"}}, {"widgettype": "Button", "options": {"label": "Contact Us →", "css": "hero-btn-primary"}}]}, {"widgettype": "VBox", "options": {"css": "section", "width": "100%", "padding": "80px 40px", "spacing": "40px"}, "subwidgets": [{"widgettype": "HBox", "options": {"width": "100%", "justifyContent": "space-between", "alignItems": "center"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Company News", "css": "section-title"}}, {"widgettype": "Text", "options": {"text": "View More →", "css": "view-more"}}]}, {"widgettype": "HBox", "options": {"width": "100%", "spacing": "24px"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "news-card", "spacing": "16px"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Kaiyuan Cloud Certified with Level-3 Security Protection Filing", "css": "news-title"}}, {"widgettype": "Text", "options": {"text": "Dec 2024", "css": "news-date"}}]}, {"widgettype": "VBox", "options": {"css": "news-card", "spacing": "16px"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Kaiyuan Cloud Wins Bid for Beijing Academy of AI (BAAI) Project", "css": "news-title"}}, {"widgettype": "Text", "options": {"text": "Oct 2024", "css": "news-date"}}]}]}]}], "id": "center"} \ No newline at end of file diff --git a/wwwroot/tokentest.opencomputing.cn/center_home_jp.ui b/wwwroot/tokentest.opencomputing.cn/center_home_jp.ui new file mode 100644 index 00000000..528d3a3d --- /dev/null +++ b/wwwroot/tokentest.opencomputing.cn/center_home_jp.ui @@ -0,0 +1 @@ +{"widgettype": "VBox", "options": {"css": "center-area", "width": "100%", "spacing": 0}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "hero", "width": "100%", "padding": "120px 40px 100px", "alignItems": "center", "spacing": "16px"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "One Platform · Intelligent Leap ·", "css": "hero-title"}}, {"widgettype": "Text", "options": {"text": "Across All Industries.", "css": "hero-title2"}}, {"widgettype": "Text", "options": {"text": "Make AI Everywhere, Make AI Easy", "css": "hero-sub"}}, {"widgettype": "HBox", "options": {"spacing": "16px"}, "subwidgets": [{"widgettype": "Button", "options": {"label": "Solutions", "css": "hero-btn-primary"}}, {"widgettype": "Button", "options": {"label": "Contact Sales", "css": "hero-btn-outline"}}]}]}, {"widgettype": "VBox", "options": {"css": "section", "width": "100%", "padding": "80px 40px 60px", "spacing": "40px"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "AI + Solutions", "css": "section-title"}}, {"widgettype": "VBox", "options": {"css": "carousel-container"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "carousel-track"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs0", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Full Protection", "css": "card-title"}}, {"widgettype": "Text", "options": {"text": "Device Intelligent Monitoring", "css": "card-subtitle"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Full Protection", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "Build independent monitoring strategies for each device, presenting real-time operational status through 3D visualization. AI automatically identifies anomalies, pinpoints fault locations, and outputs detailed diagnostic recommendations and troubleshooting steps in seconds.", "css": "card-text-white"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs1", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Read and Comprehend", "css": "card-title"}}, {"widgettype": "Text", "options": {"text": "Smart Document Parsing", "css": "card-subtitle"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Read and Comprehend", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "One-click parsing of PDF, Word, and scanned documents. AI automatically extracts key clauses, qualification requirements, and scoring criteria with structured presentation. Not just OCR, but semantic understanding, importance assessment, and risk flagging.", "css": "card-text-white"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs2", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "On-Site Intelligence", "css": "card-title"}}, {"widgettype": "Text", "options": {"text": "Edge AI Inference", "css": "card-subtitle"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "On-Site Intelligence", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "Deploy AI inference at the production edge with lightweight algorithms for millisecond-level real-time decisions. Data stays on-premises — no cloud upload needed. Redundant architecture ensures 7×24 continuous operation, zero downtime for production inspection.", "css": "card-text-white"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs3", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Collaborative Intelligence", "css": "card-title"}}, {"widgettype": "Text", "options": {"text": "Multi-Agent Collaboration", "css": "card-subtitle"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Collaborative Intelligence", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "Multiple AI agents collaborate by role, autonomously handling data collection, analysis, reasoning, and conclusion generation. Dynamic task allocation and context sharing transform complex decisions from human-dependent workflows to parallel agent execution.", "css": "card-text-white"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs4", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Spatial Intelligence", "css": "card-title"}}, {"widgettype": "Text", "options": {"text": "GIS Smart Analysis", "css": "card-subtitle"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Spatial Intelligence", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "Fusing GIS, satellite remote sensing, and UAV imagery, AI automatically identifies terrain boundaries, overlays spatial relationships, and verifies compliance constraints. Upgrades traditional manual geospatial comparison to minute-level automated spatial intelligence.", "css": "card-text-white"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs5", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Predictive Insight", "css": "card-title"}}, {"widgettype": "Text", "options": {"text": "Machine Vision Inspection", "css": "card-subtitle"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Predictive Insight", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "Deep learning-based full-width defect detection for high-speed production lines, covering surface treatment, coating, welding, and assembly. AI compares every inch of product pixel-by-pixel at millisecond speed — zero quality compromise.", "css": "card-text-white"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs6", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Instant Answers", "css": "card-title"}}, {"widgettype": "Text", "options": {"text": "Smart Q&A Knowledge Base", "css": "card-subtitle"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Instant Answers", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "Enterprise private knowledge base AI Q&A engine supporting natural language queries on business data, technical specs, and institutional documents. Every answer cites authoritative sources — traceable and verifiable. Expert knowledge is as accessible as asking a colleague.", "css": "card-text-white"}}]}]}]}]}]}]}, {"widgettype": "VBox", "options": {"css": "section section-alt", "width": "100%", "padding": "80px 40px", "spacing": "40px"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Use Cases", "css": "section-title"}}, {"widgettype": "HBox", "options": {"css": "case-cards", "width": "100%", "spacing": "24px", "justifyContent": "center"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip-front", "spacing": "0"}, "subwidgets": [{"widgettype": "Image", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/imgs/case-railway.png')}}", "css": "case-img"}}, {"widgettype": "Text", "options": {"text": "Smart Engineering", "css": "case-name"}}, {"widgettype": "Text", "options": {"text": "China Railway Group · Huitobid", "css": "case-client"}}, {"widgettype": "Text", "options": {"text": "Built the Huitobid and HuiTu Large Model for China Railway Group, establishing a…", "css": "case-desc"}}]}, {"widgettype": "VBox", "options": {"css": "case-flip-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Smart Engineering", "css": "case-back-title"}}, {"widgettype": "Text", "options": {"text": "Built the Huitobid and HuiTu Large Model for China Railway Group, establishing a Joint Innovation Center and AI Application Innovation Platform. Covering the full bidding lifecycle — intelligent document analysis, automatic qualification matching, pricing decision support, and smart bid compilation.", "css": "case-back-desc"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "case-flip"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip-front", "spacing": "0"}, "subwidgets": [{"widgettype": "Image", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/imgs/case-forestry.png')}}", "css": "case-img"}}, {"widgettype": "Text", "options": {"text": "Smart Harvesting", "css": "case-name"}}, {"widgettype": "Text", "options": {"text": "Nanning Forestry Bureau", "css": "case-client"}}, {"widgettype": "Text", "options": {"text": "Developed an Intelligent Forest Harvesting Spatial Review System integrating GIS…", "css": "case-desc"}}]}, {"widgettype": "VBox", "options": {"css": "case-flip-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Smart Harvesting", "css": "case-back-title"}}, {"widgettype": "Text", "options": {"text": "Developed an Intelligent Forest Harvesting Spatial Review System integrating GIS spatial analysis, satellite remote sensing, and multi-source UAV data. Harvesting boundaries are automatically verified for compliance, review reports are generated with one click, and the approval cycle is compressed from days to minutes.", "css": "case-back-desc"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "case-flip"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip-front", "spacing": "0"}, "subwidgets": [{"widgettype": "Image", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/imgs/case-port.png')}}", "css": "case-img"}}, {"widgettype": "Text", "options": {"text": "Digital Transformation", "css": "case-name"}}, {"widgettype": "Text", "options": {"text": "Beibu Gulf Port Big Data", "css": "case-client"}}, {"widgettype": "Text", "options": {"text": "Developed a full-stack AI agent solution covering bidding, investment decision-m…", "css": "case-desc"}}]}, {"widgettype": "VBox", "options": {"css": "case-flip-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Digital Transformation", "css": "case-back-title"}}, {"widgettype": "Text", "options": {"text": "Developed a full-stack AI agent solution covering bidding, investment decision-making, and contract review. The Bid Agent Engine enables bid document generation in seconds; the Investment Strategy Agent compresses weeks of research into minutes; the Contract Review Agent boosts review efficiency by over 60%.", "css": "case-back-desc"}}]}]}]}]}]}, {"widgettype": "VBox", "options": {"css": "cta", "width": "100%", "padding": "80px 40px", "spacing": "24px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "How Do These Solutions Work in Practice?", "css": "cta-title"}}, {"widgettype": "Text", "options": {"text": "Get industry-specific AI solutions.", "css": "cta-sub"}}, {"widgettype": "Button", "options": {"label": "Contact Us →", "css": "hero-btn-primary"}}]}, {"widgettype": "VBox", "options": {"css": "section", "width": "100%", "padding": "80px 40px", "spacing": "40px"}, "subwidgets": [{"widgettype": "HBox", "options": {"width": "100%", "justifyContent": "space-between", "alignItems": "center"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Company News", "css": "section-title"}}, {"widgettype": "Text", "options": {"text": "View More →", "css": "view-more"}}]}, {"widgettype": "HBox", "options": {"width": "100%", "spacing": "24px"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "news-card", "spacing": "16px"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Kaiyuan Cloud Certified with Level-3 Security Protection Filing", "css": "news-title"}}, {"widgettype": "Text", "options": {"text": "Dec 2024", "css": "news-date"}}]}, {"widgettype": "VBox", "options": {"css": "news-card", "spacing": "16px"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Kaiyuan Cloud Wins Bid for Beijing Academy of AI (BAAI) Project", "css": "news-title"}}, {"widgettype": "Text", "options": {"text": "Oct 2024", "css": "news-date"}}]}]}]}], "id": "center"} \ No newline at end of file diff --git a/wwwroot/tokentest.opencomputing.cn/center_home_ko.ui b/wwwroot/tokentest.opencomputing.cn/center_home_ko.ui new file mode 100644 index 00000000..528d3a3d --- /dev/null +++ b/wwwroot/tokentest.opencomputing.cn/center_home_ko.ui @@ -0,0 +1 @@ +{"widgettype": "VBox", "options": {"css": "center-area", "width": "100%", "spacing": 0}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "hero", "width": "100%", "padding": "120px 40px 100px", "alignItems": "center", "spacing": "16px"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "One Platform · Intelligent Leap ·", "css": "hero-title"}}, {"widgettype": "Text", "options": {"text": "Across All Industries.", "css": "hero-title2"}}, {"widgettype": "Text", "options": {"text": "Make AI Everywhere, Make AI Easy", "css": "hero-sub"}}, {"widgettype": "HBox", "options": {"spacing": "16px"}, "subwidgets": [{"widgettype": "Button", "options": {"label": "Solutions", "css": "hero-btn-primary"}}, {"widgettype": "Button", "options": {"label": "Contact Sales", "css": "hero-btn-outline"}}]}]}, {"widgettype": "VBox", "options": {"css": "section", "width": "100%", "padding": "80px 40px 60px", "spacing": "40px"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "AI + Solutions", "css": "section-title"}}, {"widgettype": "VBox", "options": {"css": "carousel-container"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "carousel-track"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs0", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Full Protection", "css": "card-title"}}, {"widgettype": "Text", "options": {"text": "Device Intelligent Monitoring", "css": "card-subtitle"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Full Protection", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "Build independent monitoring strategies for each device, presenting real-time operational status through 3D visualization. AI automatically identifies anomalies, pinpoints fault locations, and outputs detailed diagnostic recommendations and troubleshooting steps in seconds.", "css": "card-text-white"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs1", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Read and Comprehend", "css": "card-title"}}, {"widgettype": "Text", "options": {"text": "Smart Document Parsing", "css": "card-subtitle"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Read and Comprehend", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "One-click parsing of PDF, Word, and scanned documents. AI automatically extracts key clauses, qualification requirements, and scoring criteria with structured presentation. Not just OCR, but semantic understanding, importance assessment, and risk flagging.", "css": "card-text-white"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs2", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "On-Site Intelligence", "css": "card-title"}}, {"widgettype": "Text", "options": {"text": "Edge AI Inference", "css": "card-subtitle"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "On-Site Intelligence", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "Deploy AI inference at the production edge with lightweight algorithms for millisecond-level real-time decisions. Data stays on-premises — no cloud upload needed. Redundant architecture ensures 7×24 continuous operation, zero downtime for production inspection.", "css": "card-text-white"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs3", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Collaborative Intelligence", "css": "card-title"}}, {"widgettype": "Text", "options": {"text": "Multi-Agent Collaboration", "css": "card-subtitle"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Collaborative Intelligence", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "Multiple AI agents collaborate by role, autonomously handling data collection, analysis, reasoning, and conclusion generation. Dynamic task allocation and context sharing transform complex decisions from human-dependent workflows to parallel agent execution.", "css": "card-text-white"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs4", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Spatial Intelligence", "css": "card-title"}}, {"widgettype": "Text", "options": {"text": "GIS Smart Analysis", "css": "card-subtitle"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Spatial Intelligence", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "Fusing GIS, satellite remote sensing, and UAV imagery, AI automatically identifies terrain boundaries, overlays spatial relationships, and verifies compliance constraints. Upgrades traditional manual geospatial comparison to minute-level automated spatial intelligence.", "css": "card-text-white"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs5", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Predictive Insight", "css": "card-title"}}, {"widgettype": "Text", "options": {"text": "Machine Vision Inspection", "css": "card-subtitle"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Predictive Insight", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "Deep learning-based full-width defect detection for high-speed production lines, covering surface treatment, coating, welding, and assembly. AI compares every inch of product pixel-by-pixel at millisecond speed — zero quality compromise.", "css": "card-text-white"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs6", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Instant Answers", "css": "card-title"}}, {"widgettype": "Text", "options": {"text": "Smart Q&A Knowledge Base", "css": "card-subtitle"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Instant Answers", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "Enterprise private knowledge base AI Q&A engine supporting natural language queries on business data, technical specs, and institutional documents. Every answer cites authoritative sources — traceable and verifiable. Expert knowledge is as accessible as asking a colleague.", "css": "card-text-white"}}]}]}]}]}]}]}, {"widgettype": "VBox", "options": {"css": "section section-alt", "width": "100%", "padding": "80px 40px", "spacing": "40px"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Use Cases", "css": "section-title"}}, {"widgettype": "HBox", "options": {"css": "case-cards", "width": "100%", "spacing": "24px", "justifyContent": "center"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip-front", "spacing": "0"}, "subwidgets": [{"widgettype": "Image", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/imgs/case-railway.png')}}", "css": "case-img"}}, {"widgettype": "Text", "options": {"text": "Smart Engineering", "css": "case-name"}}, {"widgettype": "Text", "options": {"text": "China Railway Group · Huitobid", "css": "case-client"}}, {"widgettype": "Text", "options": {"text": "Built the Huitobid and HuiTu Large Model for China Railway Group, establishing a…", "css": "case-desc"}}]}, {"widgettype": "VBox", "options": {"css": "case-flip-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Smart Engineering", "css": "case-back-title"}}, {"widgettype": "Text", "options": {"text": "Built the Huitobid and HuiTu Large Model for China Railway Group, establishing a Joint Innovation Center and AI Application Innovation Platform. Covering the full bidding lifecycle — intelligent document analysis, automatic qualification matching, pricing decision support, and smart bid compilation.", "css": "case-back-desc"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "case-flip"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip-front", "spacing": "0"}, "subwidgets": [{"widgettype": "Image", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/imgs/case-forestry.png')}}", "css": "case-img"}}, {"widgettype": "Text", "options": {"text": "Smart Harvesting", "css": "case-name"}}, {"widgettype": "Text", "options": {"text": "Nanning Forestry Bureau", "css": "case-client"}}, {"widgettype": "Text", "options": {"text": "Developed an Intelligent Forest Harvesting Spatial Review System integrating GIS…", "css": "case-desc"}}]}, {"widgettype": "VBox", "options": {"css": "case-flip-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Smart Harvesting", "css": "case-back-title"}}, {"widgettype": "Text", "options": {"text": "Developed an Intelligent Forest Harvesting Spatial Review System integrating GIS spatial analysis, satellite remote sensing, and multi-source UAV data. Harvesting boundaries are automatically verified for compliance, review reports are generated with one click, and the approval cycle is compressed from days to minutes.", "css": "case-back-desc"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "case-flip"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip-front", "spacing": "0"}, "subwidgets": [{"widgettype": "Image", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/imgs/case-port.png')}}", "css": "case-img"}}, {"widgettype": "Text", "options": {"text": "Digital Transformation", "css": "case-name"}}, {"widgettype": "Text", "options": {"text": "Beibu Gulf Port Big Data", "css": "case-client"}}, {"widgettype": "Text", "options": {"text": "Developed a full-stack AI agent solution covering bidding, investment decision-m…", "css": "case-desc"}}]}, {"widgettype": "VBox", "options": {"css": "case-flip-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Digital Transformation", "css": "case-back-title"}}, {"widgettype": "Text", "options": {"text": "Developed a full-stack AI agent solution covering bidding, investment decision-making, and contract review. The Bid Agent Engine enables bid document generation in seconds; the Investment Strategy Agent compresses weeks of research into minutes; the Contract Review Agent boosts review efficiency by over 60%.", "css": "case-back-desc"}}]}]}]}]}]}, {"widgettype": "VBox", "options": {"css": "cta", "width": "100%", "padding": "80px 40px", "spacing": "24px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "How Do These Solutions Work in Practice?", "css": "cta-title"}}, {"widgettype": "Text", "options": {"text": "Get industry-specific AI solutions.", "css": "cta-sub"}}, {"widgettype": "Button", "options": {"label": "Contact Us →", "css": "hero-btn-primary"}}]}, {"widgettype": "VBox", "options": {"css": "section", "width": "100%", "padding": "80px 40px", "spacing": "40px"}, "subwidgets": [{"widgettype": "HBox", "options": {"width": "100%", "justifyContent": "space-between", "alignItems": "center"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Company News", "css": "section-title"}}, {"widgettype": "Text", "options": {"text": "View More →", "css": "view-more"}}]}, {"widgettype": "HBox", "options": {"width": "100%", "spacing": "24px"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "news-card", "spacing": "16px"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Kaiyuan Cloud Certified with Level-3 Security Protection Filing", "css": "news-title"}}, {"widgettype": "Text", "options": {"text": "Dec 2024", "css": "news-date"}}]}, {"widgettype": "VBox", "options": {"css": "news-card", "spacing": "16px"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Kaiyuan Cloud Wins Bid for Beijing Academy of AI (BAAI) Project", "css": "news-title"}}, {"widgettype": "Text", "options": {"text": "Oct 2024", "css": "news-date"}}]}]}]}], "id": "center"} \ No newline at end of file diff --git a/wwwroot/tokentest.opencomputing.cn/center_home_zh.ui b/wwwroot/tokentest.opencomputing.cn/center_home_zh.ui new file mode 100644 index 00000000..5e95d5b8 --- /dev/null +++ b/wwwroot/tokentest.opencomputing.cn/center_home_zh.ui @@ -0,0 +1 @@ +{"widgettype": "VBox", "options": {"css": "center-area", "width": "100%", "spacing": 0}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "hero", "width": "100%", "padding": "120px 40px 100px", "alignItems": "center", "spacing": "16px"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "一个平台,千行百业", "css": "hero-title"}}, {"widgettype": "Text", "options": {"text": "智能跃迁", "css": "hero-title2"}}, {"widgettype": "Text", "options": {"text": "让AI无处不在,让智能如此简单", "css": "hero-sub"}}, {"widgettype": "HBox", "options": {"spacing": "16px"}, "subwidgets": [{"widgettype": "Button", "options": {"label": "解决方案", "css": "hero-btn-primary"}}, {"widgettype": "Button", "options": {"label": "联系销售", "css": "hero-btn-outline"}}]}]}, {"widgettype": "VBox", "options": {"css": "section", "width": "100%", "padding": "80px 40px 60px", "spacing": "40px"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "AI+解决方案", "css": "section-title"}}, {"widgettype": "VBox", "options": {"css": "carousel-container"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "carousel-track"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs0", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "洞察入微", "css": "card-title"}}, {"widgettype": "Text", "options": {"text": "机器视觉检测", "css": "card-subtitle"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "洞察入微", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "基于深度学习的高速产线全幅面缺陷检测能力,覆盖表面处理、涂层喷涂、焊接装配等全流程质检环节。不是抽样检查,而是每一寸产品都经过AI逐像素比对,在毫秒级时间内完成缺陷识别与分类,确保出厂品质零妥协。", "css": "card-text-white"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs1", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "一问即达", "css": "card-title"}}, {"widgettype": "Text", "options": {"text": "智能问答知识库", "css": "card-subtitle"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "一问即达", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "基于企业私有知识库构建的AI问答引擎,支持自然语言直接查询业务数据、技术规范、制度文件。每条回答自动标注权威来源,信息可追溯、可验证。让专家级知识不再锁在文档里,而是像问同事一样即问即答。", "css": "card-text-white"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs2", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "全程守护", "css": "card-title"}}, {"widgettype": "Text", "options": {"text": "设备智能监控", "css": "card-subtitle"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "全程守护", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "为每台设备构建独立监控策略,通过三维可视化实时呈现运行状态。AI自动识别异常并高亮定位故障点,同步输出详细诊断建议和排查步骤。将运维人员从\"盯屏找问题\"解放出来,让系统主动告诉你问题在哪、怎么修。", "css": "card-text-white"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs3", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "触文即懂", "css": "card-title"}}, {"widgettype": "Text", "options": {"text": "智能文档解析", "css": "card-subtitle"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "触文即懂", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "支持PDF、Word、扫描件等多种格式一键解析,AI自动提取关键条款、资质要求、评分细则等核心信息并结构化呈现。不是简单的OCR文字识别,而是理解文档语义、判断信息重要性、标注风险点,让冗长文档的核心内容一目了然。", "css": "card-text-white"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs4", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "端侧即算", "css": "card-title"}}, {"widgettype": "Text", "options": {"text": "边缘AI推理", "css": "card-subtitle"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "端侧即算", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "将AI推理能力部署在生产现场边缘侧,通过轻量化算法实现毫秒级实时决策。数据无需回传云端,在本地即可完成从感知到判断的全流程,确保数据不出厂、响应零延迟。冗余架构设计保障7×24小时持续运行,产线检测永不中断。", "css": "card-text-white"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs5", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "群智协作", "css": "card-title"}}, {"widgettype": "Text", "options": {"text": "多智能体协同", "css": "card-subtitle"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "群智协作", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "多个AI智能体按角色分工,自主完成信息采集、数据分析、逻辑推理与结论生成的全流程协作。支持动态任务分配与上下文共享,将复杂业务决策从\"人串联\"变为\"智能体并行\",大幅压缩高知识密度工作的完成周期。", "css": "card-text-white"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs6", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "空间觉醒", "css": "card-title"}}, {"widgettype": "Text", "options": {"text": "GIS智能分析", "css": "card-subtitle"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "空间觉醒", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "融合地理信息系统、卫星遥感影像、无人机航拍等多维空间数据,AI自动识别地物边界、叠加分析空间关系、校验合规约束。将传统需要人工逐层比对的地理空间判断,升级为分钟级自动完成的空间智能决策。", "css": "card-text-white"}}]}]}]}]}]}]}, {"widgettype": "VBox", "options": {"css": "section section-alt", "width": "100%", "padding": "80px 40px", "spacing": "40px"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "应用案例", "css": "section-title"}}, {"widgettype": "HBox", "options": {"css": "case-cards", "width": "100%", "spacing": "24px", "justifyContent": "center"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip-front", "spacing": "0"}, "subwidgets": [{"widgettype": "Image", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/imgs/case-railway.png')}}", "css": "case-img"}}, {"widgettype": "Text", "options": {"text": "智慧工程", "css": "case-name"}}, {"widgettype": "Text", "options": {"text": "中国中铁 · 汇投标", "css": "case-client"}}, {"widgettype": "Text", "options": {"text": "为中国中铁打造汇投标和慧途大模型,建立联合创新中心和AI应用创新平台。覆盖文档分析、资质匹配、定价决策、智能编制全投标生命周期,实现人力密集型到AI驱动的跃迁式…", "css": "case-desc"}}]}, {"widgettype": "VBox", "options": {"css": "case-flip-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "智慧工程", "css": "case-back-title"}}, {"widgettype": "Text", "options": {"text": "为中国中铁打造汇投标和慧途大模型,建立联合创新中心和AI应用创新平台。覆盖文档分析、资质匹配、定价决策、智能编制全投标生命周期,实现人力密集型到AI驱动的跃迁式变革。", "css": "case-back-desc"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "case-flip"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip-front", "spacing": "0"}, "subwidgets": [{"widgettype": "Image", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/imgs/case-forestry.png')}}", "css": "case-img"}}, {"widgettype": "Text", "options": {"text": "智慧采伐", "css": "case-name"}}, {"widgettype": "Text", "options": {"text": "南宁市林业局", "css": "case-client"}}, {"widgettype": "Text", "options": {"text": "为南宁林业局开发智能森林采伐空间审核系统,集成GIS空间分析、卫星遥感和无人机多源数据,采伐边界自动合规验证,一键生成审核报告,审批周期从天压缩到分钟。", "css": "case-desc"}}]}, {"widgettype": "VBox", "options": {"css": "case-flip-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "智慧采伐", "css": "case-back-title"}}, {"widgettype": "Text", "options": {"text": "为南宁林业局开发智能森林采伐空间审核系统,集成GIS空间分析、卫星遥感和无人机多源数据,采伐边界自动合规验证,一键生成审核报告,审批周期从天压缩到分钟。", "css": "case-back-desc"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "case-flip"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip-front", "spacing": "0"}, "subwidgets": [{"widgettype": "Image", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/imgs/case-port.png')}}", "css": "case-img"}}, {"widgettype": "Text", "options": {"text": "数智化转型", "css": "case-name"}}, {"widgettype": "Text", "options": {"text": "北部湾港大数据", "css": "case-client"}}, {"widgettype": "Text", "options": {"text": "为北部湾港大数据打造全栈AI智能体解决方案,覆盖招投标、投资决策、合同审查。投标引擎秒级生成标书,投策引擎将数周报告压缩到分钟级,合同审查效率提升60%+。", "css": "case-desc"}}]}, {"widgettype": "VBox", "options": {"css": "case-flip-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "数智化转型", "css": "case-back-title"}}, {"widgettype": "Text", "options": {"text": "为北部湾港大数据打造全栈AI智能体解决方案,覆盖招投标、投资决策、合同审查。投标引擎秒级生成标书,投策引擎将数周报告压缩到分钟级,合同审查效率提升60%+。", "css": "case-back-desc"}}]}]}]}]}]}, {"widgettype": "VBox", "options": {"css": "cta", "width": "100%", "padding": "80px 40px", "spacing": "24px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "这些解决方案在实践中如何运作?", "css": "cta-title"}}, {"widgettype": "Text", "options": {"text": "获取针对您行业的AI解决方案。", "css": "cta-sub"}}, {"widgettype": "Button", "options": {"label": "联系我们 →", "css": "hero-btn-primary"}}]}, {"widgettype": "VBox", "options": {"css": "section", "width": "100%", "padding": "80px 40px", "spacing": "40px"}, "subwidgets": [{"widgettype": "HBox", "options": {"width": "100%", "justifyContent": "space-between", "alignItems": "center"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "企业动态", "css": "section-title"}}, {"widgettype": "Text", "options": {"text": "查看更多 →", "css": "view-more"}}]}, {"widgettype": "HBox", "options": {"width": "100%", "spacing": "24px"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "news-card", "spacing": "16px"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "权威认证!开元云科技完成三级等保备案", "css": "news-title"}}, {"widgettype": "Text", "options": {"text": "2024年12月", "css": "news-date"}}]}, {"widgettype": "VBox", "options": {"css": "news-card", "spacing": "16px"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "开元云科技中标北京智源人工智能研究院项目", "css": "news-title"}}, {"widgettype": "Text", "options": {"text": "2024年10月", "css": "news-date"}}]}]}]}], "id": "center"} \ No newline at end of file diff --git a/wwwroot/tokentest.opencomputing.cn/compute/index_zh.ui b/wwwroot/tokentest.opencomputing.cn/compute/index_zh.ui new file mode 100644 index 00000000..265733d1 --- /dev/null +++ b/wwwroot/tokentest.opencomputing.cn/compute/index_zh.ui @@ -0,0 +1 @@ +{"widgettype": "VBox", "options": {"css": "page", "width": "100%", "spacing": 0}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "prod-hero", "width": "100%", "padding": "120px 40px 80px", "alignItems": "center", "spacing": "20px"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "算力市场", "css": "prod-hero-title"}}, {"widgettype": "Text", "options": {"text": "高性能GPU算力按需租用,覆盖训练、推理、渲染等多场景,弹性伸缩按量付费,释放无限算力潜能。", "css": "prod-hero-sub"}}]}, {"widgettype": "VBox", "options": {"css": "section", "width": "100%", "padding": "80px 40px", "spacing": "20px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "核心能力", "css": "section-title"}}, {"widgettype": "HBox", "options": {"width": "100%", "spacing": "24px", "justifyContent": "center"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "prod-card", "spacing": "20px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "🖥️", "css": "prod-card-icon"}}, {"widgettype": "Text", "options": {"text": "GPU实例", "css": "prod-card-title"}}, {"widgettype": "Text", "options": {"text": "NVIDIA A100/H100/RTX4090等主流GPU,按小时/包月灵活租用,即开即用。", "css": "prod-card-desc"}}, {"widgettype": "Button", "options": {"label": "浏览算力", "css": "prod-card-btn"}}]}, {"widgettype": "VBox", "options": {"css": "prod-card", "spacing": "20px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "📦", "css": "prod-card-icon"}}, {"widgettype": "Text", "options": {"text": "批量计算", "css": "prod-card-title"}}, {"widgettype": "Text", "options": {"text": "大规模并行计算任务调度引擎,支持万核级弹性伸缩,高效利用闲置算力。", "css": "prod-card-desc"}}, {"widgettype": "Button", "options": {"label": "了解更多", "css": "prod-card-btn"}}]}, {"widgettype": "VBox", "options": {"css": "prod-card", "spacing": "20px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "⚡", "css": "prod-card-icon"}}, {"widgettype": "Text", "options": {"text": "Spot实例", "css": "prod-card-title"}}, {"widgettype": "Text", "options": {"text": "低价抢占式算力,最高节省80%成本,适合容错性高的批处理与测试任务。", "css": "prod-card-desc"}}, {"widgettype": "Button", "options": {"label": "立即体验", "css": "prod-card-btn"}}]}]}]}]} \ No newline at end of file diff --git a/wwwroot/tokentest.opencomputing.cn/compute/landing.css b/wwwroot/tokentest.opencomputing.cn/compute/landing.css new file mode 100644 index 00000000..8d2a3ba6 --- /dev/null +++ b/wwwroot/tokentest.opencomputing.cn/compute/landing.css @@ -0,0 +1,19 @@ +.prod-hero{background:linear-gradient(180deg,#f0f7ff 0%,#fff 60%,#f5f8ff 100%)!important;min-height:360px;justify-content:center!important} +.prod-hero-title{font-size:48px!important;font-weight:800!important;color:#111827!important;text-align:center!important} +.prod-hero-sub{font-size:18px!important;color:#4b5563!important;text-align:center!important;max-width:700px;line-height:1.7!important} +.prod-card{background:#fff;border-radius:16px;padding:40px 32px!important;box-shadow:0 4px 24px rgba(0,0,0,0.06);width:340px!important;min-height:280px;transition:transform .2s,box-shadow .2s} +.prod-card:hover{transform:translateY(-6px);box-shadow:0 12px 40px rgba(0,0,0,0.1)} +.prod-card-icon{font-size:48px!important;text-align:center!important} +.prod-card-title{font-size:24px!important;font-weight:700!important;color:#111827!important;text-align:center!important} +.prod-card-desc{font-size:15px!important;color:#6b7280!important;line-height:1.7!important;text-align:center!important} +.prod-card-btn{background:#000!important;color:#fff!important;border:none!important;padding:12px 32px!important;border-radius:99px!important;font-size:15px!important;font-weight:600!important;cursor:pointer!important} +.prod-card-btn:hover{background:#1f2937!important} + +[data-theme="dark"] .prod-hero{background:linear-gradient(180deg,#0f172a 0%,#1e293b 60%,#0f172a 100%)!important} +[data-theme="dark"] .prod-hero-title{color:#f1f5f9!important} +[data-theme="dark"] .prod-hero-sub{color:#94a3b8!important} +[data-theme="dark"] .prod-card{background:#1e293b;box-shadow:0 4px 24px rgba(0,0,0,0.2)} +[data-theme="dark"] .prod-card:hover{box-shadow:0 12px 40px rgba(0,0,0,0.3)} +[data-theme="dark"] .prod-card-title{color:#f1f5f9!important} +[data-theme="dark"] .prod-card-desc{color:#94a3b8!important} +[data-theme="dark"] .prod-card-btn{background:#f1f5f9!important;color:#0f172a!important} diff --git a/wwwroot/tokentest.opencomputing.cn/home_center.ui b/wwwroot/tokentest.opencomputing.cn/home_center.ui new file mode 100644 index 00000000..1e96fc1e --- /dev/null +++ b/wwwroot/tokentest.opencomputing.cn/home_center.ui @@ -0,0 +1 @@ +{"widgettype": "VBox", "options": {"css": "page", "width": "100%", "spacing": 0}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "hero", "width": "100%", "padding": "120px 40px 100px", "alignItems": "center", "spacing": "24px"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "一个平台 · 智能跨越 · 全行业覆盖", "css": "hero-title"}}, {"widgettype": "Text", "options": {"text": "让AI无处不在,让AI触手可及", "css": "hero-sub"}}, {"widgettype": "HBox", "options": {"spacing": "16px"}, "subwidgets": [{"widgettype": "Button", "options": {"label": "解决方案", "css": "hero-btn-primary"}}, {"widgettype": "Button", "options": {"label": "联系销售", "css": "hero-btn-outline"}}]}]}, {"widgettype": "VBox", "options": {"css": "section", "width": "100%", "padding": "80px 40px 60px", "spacing": "40px"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "AI + 解决方案", "css": "section-title"}}, {"widgettype": "VBox", "options": {"css": "carousel-container"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "carousel-track"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs0", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "🛡️", "css": "card-icon"}}, {"widgettype": "Text", "options": {"text": "全面防护", "css": "card-title"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "全面防护", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "多层次AI安全防护体系,覆盖数据加密、访问控制、威胁检测与合规审计全链路。", "css": "card-text-white"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs1", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "📖", "css": "card-icon"}}, {"widgettype": "Text", "options": {"text": "阅读理解", "css": "card-title"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "阅读理解", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "深度理解非结构化文档,自动提取关键信息,支持合同、报告、论文等多场景。", "css": "card-text-white"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs2", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "🏭", "css": "card-icon"}}, {"widgettype": "Text", "options": {"text": "现场智能", "css": "card-title"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "现场智能", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "AI视觉+物联网融合,实时监测生产现场,异常预警、质量检测、安全管控一体化。", "css": "card-text-white"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs3", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "🤝", "css": "card-icon"}}, {"widgettype": "Text", "options": {"text": "协同智能", "css": "card-title"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "协同智能", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "多个AI智能体角色化自主协作,完成信息采集、分析、推理和结论生成全流程。", "css": "card-text-white"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs4", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "🌍", "css": "card-icon"}}, {"widgettype": "Text", "options": {"text": "空间智能", "css": "card-title"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "空间智能", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "集成GIS、卫星遥感与无人机数据,AI自动识别地物边界并分析空间关系。", "css": "card-text-white"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs5", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "🔮", "css": "card-icon"}}, {"widgettype": "Text", "options": {"text": "预测洞察", "css": "card-title"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "预测洞察", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "基于历史数据与实时指标,AI预测趋势、识别风险、优化决策,先人一步。", "css": "card-text-white"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs6", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "🔬", "css": "card-icon"}}, {"widgettype": "Text", "options": {"text": "微观洞察", "css": "card-title"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "微观洞察", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "AI显微镜图像分析,自动识别细胞、材料等微观结构,精度达到专业级水平。", "css": "card-text-white"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs7", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "💬", "css": "card-icon"}}, {"widgettype": "Text", "options": {"text": "即时问答", "css": "card-title"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "即时问答", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "基于企业私有知识库的AI问答引擎,自然语言查询,秒级精准响应业务问题。", "css": "card-text-white"}}]}]}]}]}]}]}, {"widgettype": "VBox", "options": {"css": "section section-alt", "width": "100%", "padding": "80px 40px", "spacing": "40px"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "应用案例", "css": "section-title"}}, {"widgettype": "HBox", "options": {"css": "case-cards", "width": "100%", "spacing": "24px", "justifyContent": "center"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip-front", "spacing": "0"}, "subwidgets": [{"widgettype": "Image", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/imgs/case-railway.png')}}", "css": "case-img"}}, {"widgettype": "Text", "options": {"text": "智慧工程", "css": "case-name"}}, {"widgettype": "Text", "options": {"text": "中国中铁 · 汇投标", "css": "case-client"}}, {"widgettype": "Text", "options": {"text": "构建覆盖文档分析到智能投标文件编制的全生命周期智能招标系统。", "css": "case-desc"}}]}, {"widgettype": "VBox", "options": {"css": "case-flip-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "智慧工程", "css": "case-back-title"}}, {"widgettype": "Text", "options": {"text": "为中国中铁打造汇投标和慧途大模型,建立联合创新中心和AI应用创新平台。全面覆盖投标全生命周期。", "css": "case-back-desc"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "case-flip"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip-front", "spacing": "0"}, "subwidgets": [{"widgettype": "Image", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/imgs/case-forestry.png')}}", "css": "case-img"}}, {"widgettype": "Text", "options": {"text": "智慧采伐", "css": "case-name"}}, {"widgettype": "Text", "options": {"text": "南宁市林业局", "css": "case-client"}}, {"widgettype": "Text", "options": {"text": "集成GIS、卫星遥感和无人机数据的智能森林采伐空间审核系统。", "css": "case-desc"}}]}, {"widgettype": "VBox", "options": {"css": "case-flip-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "智慧采伐", "css": "case-back-title"}}, {"widgettype": "Text", "options": {"text": "为南宁林业局开发智能森林采伐空间审核系统,采伐边界自动合规验证,一键生成审核报告。", "css": "case-back-desc"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "case-flip"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip-front", "spacing": "0"}, "subwidgets": [{"widgettype": "Image", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/imgs/case-port.png')}}", "css": "case-img"}}, {"widgettype": "Text", "options": {"text": "数智化转型", "css": "case-name"}}, {"widgettype": "Text", "options": {"text": "北部湾港大数据", "css": "case-client"}}, {"widgettype": "Text", "options": {"text": "覆盖招标、投资决策、合同审查的全栈AI智能体解决方案。", "css": "case-desc"}}]}, {"widgettype": "VBox", "options": {"css": "case-flip-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "数智化转型", "css": "case-back-title"}}, {"widgettype": "Text", "options": {"text": "为北部湾港大数据打造全栈AI智能体解决方案,投标引擎秒级生成标书,合同审查效率提升60%+。", "css": "case-back-desc"}}]}]}]}]}]}, {"widgettype": "VBox", "options": {"css": "cta", "width": "100%", "padding": "80px 40px", "spacing": "24px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "这些解决方案在实践中如何运作?", "css": "cta-title"}}, {"widgettype": "Text", "options": {"text": "获取针对您行业的AI解决方案。", "css": "cta-sub"}}, {"widgettype": "Button", "options": {"label": "联系我们 →", "css": "hero-btn-primary"}}]}, {"widgettype": "VBox", "options": {"css": "section", "width": "100%", "padding": "80px 40px", "spacing": "40px"}, "subwidgets": [{"widgettype": "HBox", "options": {"width": "100%", "justifyContent": "space-between", "alignItems": "center"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "企业动态", "css": "section-title"}}, {"widgettype": "Text", "options": {"text": "查看更多 →", "css": "view-more"}}]}, {"widgettype": "HBox", "options": {"width": "100%", "spacing": "24px"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "news-card", "spacing": "16px"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "权威认证!开元云科技完成三级等保备案", "css": "news-title"}}, {"widgettype": "Text", "options": {"text": "开元云科技顺利通过国家信息系统安全等级保护三级认证。", "css": "news-desc"}}, {"widgettype": "Text", "options": {"text": "2024年12月", "css": "news-date"}}]}, {"widgettype": "VBox", "options": {"css": "news-card", "spacing": "16px"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "开元云科技中标北京智源人工智能研究院项目", "css": "news-title"}}, {"widgettype": "Text", "options": {"text": "成功中标智源研究院AI项目,为顶级AI研究机构提供算力平台与智能服务支撑。", "css": "news-desc"}}, {"widgettype": "Text", "options": {"text": "2024年10月", "css": "news-date"}}]}]}]}]} \ No newline at end of file diff --git a/wwwroot/tokentest.opencomputing.cn/index_en.ui b/wwwroot/tokentest.opencomputing.cn/index_en.ui new file mode 100644 index 00000000..1f787aa9 --- /dev/null +++ b/wwwroot/tokentest.opencomputing.cn/index_en.ui @@ -0,0 +1 @@ +{"widgettype": "VBox", "options": {"css": "page", "width": "100%", "spacing": 0}, "subwidgets": [{"widgettype": "HBox", "options": {"css": "header", "width": "100%", "padding": "0 40px", "alignItems": "center", "justifyContent": "space-between"}, "subwidgets": [{"widgettype": "Image", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/imgs/logo.png')}}", "css": "logo"}, "id": "logo", "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/center_home_en.ui')}}"}}]}, {"widgettype": "HBox", "options": {"css": "nav-area"}, "subwidgets": [{"widgettype": "HBox", "options": {"css": "nav-links", "spacing": "32px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Home", "css": "nav-link active"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/center_home_en.ui')}}"}}]}, {"widgettype": "VBox", "options": {"css": "products-menu"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Products ▾", "css": "nav-link"}}, {"widgettype": "VBox", "options": {"css": "products-dropdown"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "OPC", "css": "dropdown-item"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/opc/index_en.ui')}}"}}]}, {"widgettype": "Text", "options": {"text": "Compute Market", "css": "dropdown-item"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/compute/index_en.ui')}}"}}]}, {"widgettype": "Text", "options": {"text": "Token Market", "css": "dropdown-item"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/llmage/model_plaza.ui')}}"}}]}, {"widgettype": "Text", "options": {"text": "Yuanjing", "css": "dropdown-item"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/yunjing/index_en.ui')}}"}}]}, {"widgettype": "Text", "options": {"text": "Train & Infer", "css": "dropdown-item"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/train/index_en.ui')}}"}}]}, {"widgettype": "Text", "options": {"text": "Agent Store", "css": "dropdown-item"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/agent/index_en.ui')}}"}}]}, {"widgettype": "Text", "options": {"text": "Supply Square", "css": "dropdown-item"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/supplychain/index_en.ui')}}"}}]}]}]}, {"widgettype": "Text", "options": {"text": "Use Cases", "css": "nav-link"}}, {"widgettype": "Text", "options": {"text": "News", "css": "nav-link"}}]}]}, {"widgettype": "HBox", "options": {"css": "header-actions", "spacing": "12px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Button", "options": {"label": "☀", "css": "theme-btn"}, "id": "themeToggle", "binds": [{"wid": "self", "event": "click", "actiontype": "script", "script": "if(window._toggleTheme)window._toggleTheme();var t=document.documentElement.getAttribute('data-theme');var b=document.getElementById('themeToggle');if(b){var s=b.querySelector('div');if(s)s.textContent=t==='dark'?'☾':'☀';}"}]}, {"widgettype": "Button", "options": {"label": "EN/中", "css": "lang-btn"}, "binds": [{"wid": "self", "event": "click", "actiontype": "script", "script": "localStorage.setItem('hermes-lang','zh');location.href='/tokentest.opencomputing.cn/index_zh.ui';"}]}, {"widgettype": "Button", "options": {"label": "Login", "css": "login-pill"}, "binds": [{"wid": "self", "event": "click", "actiontype": "script", "script": "window.location.href='{{entire_url(\"/rbac/user/login.ui\")}}';"}]}]}]}, {"widgettype": "VBox", "options": {"css": "center-area", "width": "100%", "spacing": 0}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "hero", "width": "100%", "padding": "120px 40px 100px", "alignItems": "center", "spacing": "16px"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "One Platform · Intelligent Leap ·", "css": "hero-title"}}, {"widgettype": "Text", "options": {"text": "Across All Industries.", "css": "hero-title2"}}, {"widgettype": "Text", "options": {"text": "Make AI Everywhere, Make AI Easy", "css": "hero-sub"}}, {"widgettype": "HBox", "options": {"spacing": "16px"}, "subwidgets": [{"widgettype": "Button", "options": {"label": "Solutions", "css": "hero-btn-primary"}}, {"widgettype": "Button", "options": {"label": "Contact Sales", "css": "hero-btn-outline"}}]}]}, {"widgettype": "VBox", "options": {"css": "section", "width": "100%", "padding": "80px 40px 60px", "spacing": "40px"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "AI + Solutions", "css": "section-title"}}, {"widgettype": "VBox", "options": {"css": "carousel-container"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "carousel-track"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs0", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Full Protection", "css": "card-title"}}, {"widgettype": "Text", "options": {"text": "Device Intelligent Monitoring", "css": "card-subtitle"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Full Protection", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "Build independent monitoring strategies for each device, presenting real-time operational status through 3D visualization. AI automatically identifies anomalies, pinpoints fault locations, and outputs detailed diagnostic recommendations and troubleshooting steps in seconds.", "css": "card-text-white"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs1", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Read and Comprehend", "css": "card-title"}}, {"widgettype": "Text", "options": {"text": "Smart Document Parsing", "css": "card-subtitle"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Read and Comprehend", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "One-click parsing of PDF, Word, and scanned documents. AI automatically extracts key clauses, qualification requirements, and scoring criteria with structured presentation. Not just OCR, but semantic understanding, importance assessment, and risk flagging.", "css": "card-text-white"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs2", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "On-Site Intelligence", "css": "card-title"}}, {"widgettype": "Text", "options": {"text": "Edge AI Inference", "css": "card-subtitle"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "On-Site Intelligence", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "Deploy AI inference at the production edge with lightweight algorithms for millisecond-level real-time decisions. Data stays on-premises — no cloud upload needed. Redundant architecture ensures 7×24 continuous operation, zero downtime for production inspection.", "css": "card-text-white"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs3", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Collaborative Intelligence", "css": "card-title"}}, {"widgettype": "Text", "options": {"text": "Multi-Agent Collaboration", "css": "card-subtitle"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Collaborative Intelligence", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "Multiple AI agents collaborate by role, autonomously handling data collection, analysis, reasoning, and conclusion generation. Dynamic task allocation and context sharing transform complex decisions from human-dependent workflows to parallel agent execution.", "css": "card-text-white"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs4", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Spatial Intelligence", "css": "card-title"}}, {"widgettype": "Text", "options": {"text": "GIS Smart Analysis", "css": "card-subtitle"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Spatial Intelligence", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "Fusing GIS, satellite remote sensing, and UAV imagery, AI automatically identifies terrain boundaries, overlays spatial relationships, and verifies compliance constraints. Upgrades traditional manual geospatial comparison to minute-level automated spatial intelligence.", "css": "card-text-white"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs5", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Predictive Insight", "css": "card-title"}}, {"widgettype": "Text", "options": {"text": "Machine Vision Inspection", "css": "card-subtitle"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Predictive Insight", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "Deep learning-based full-width defect detection for high-speed production lines, covering surface treatment, coating, welding, and assembly. AI compares every inch of product pixel-by-pixel at millisecond speed — zero quality compromise.", "css": "card-text-white"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs6", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Instant Answers", "css": "card-title"}}, {"widgettype": "Text", "options": {"text": "Smart Q&A Knowledge Base", "css": "card-subtitle"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Instant Answers", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "Enterprise private knowledge base AI Q&A engine supporting natural language queries on business data, technical specs, and institutional documents. Every answer cites authoritative sources — traceable and verifiable. Expert knowledge is as accessible as asking a colleague.", "css": "card-text-white"}}]}]}]}]}]}]}, {"widgettype": "VBox", "options": {"css": "section section-alt", "width": "100%", "padding": "80px 40px", "spacing": "40px"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Use Cases", "css": "section-title"}}, {"widgettype": "HBox", "options": {"css": "case-cards", "width": "100%", "spacing": "24px", "justifyContent": "center"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip-front", "spacing": "0"}, "subwidgets": [{"widgettype": "Image", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/imgs/case-railway.png')}}", "css": "case-img"}}, {"widgettype": "Text", "options": {"text": "Smart Engineering", "css": "case-name"}}, {"widgettype": "Text", "options": {"text": "China Railway Group · Huitobid", "css": "case-client"}}, {"widgettype": "Text", "options": {"text": "Built the Huitobid and HuiTu Large Model for China Railway Group, establishing a…", "css": "case-desc"}}]}, {"widgettype": "VBox", "options": {"css": "case-flip-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Smart Engineering", "css": "case-back-title"}}, {"widgettype": "Text", "options": {"text": "Built the Huitobid and HuiTu Large Model for China Railway Group, establishing a Joint Innovation Center and AI Application Innovation Platform. Covering the full bidding lifecycle — intelligent document analysis, automatic qualification matching, pricing decision support, and smart bid compilation.", "css": "case-back-desc"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "case-flip"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip-front", "spacing": "0"}, "subwidgets": [{"widgettype": "Image", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/imgs/case-forestry.png')}}", "css": "case-img"}}, {"widgettype": "Text", "options": {"text": "Smart Harvesting", "css": "case-name"}}, {"widgettype": "Text", "options": {"text": "Nanning Forestry Bureau", "css": "case-client"}}, {"widgettype": "Text", "options": {"text": "Developed an Intelligent Forest Harvesting Spatial Review System integrating GIS…", "css": "case-desc"}}]}, {"widgettype": "VBox", "options": {"css": "case-flip-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Smart Harvesting", "css": "case-back-title"}}, {"widgettype": "Text", "options": {"text": "Developed an Intelligent Forest Harvesting Spatial Review System integrating GIS spatial analysis, satellite remote sensing, and multi-source UAV data. Harvesting boundaries are automatically verified for compliance, review reports are generated with one click, and the approval cycle is compressed from days to minutes.", "css": "case-back-desc"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "case-flip"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip-front", "spacing": "0"}, "subwidgets": [{"widgettype": "Image", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/imgs/case-port.png')}}", "css": "case-img"}}, {"widgettype": "Text", "options": {"text": "Digital Transformation", "css": "case-name"}}, {"widgettype": "Text", "options": {"text": "Beibu Gulf Port Big Data", "css": "case-client"}}, {"widgettype": "Text", "options": {"text": "Developed a full-stack AI agent solution covering bidding, investment decision-m…", "css": "case-desc"}}]}, {"widgettype": "VBox", "options": {"css": "case-flip-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Digital Transformation", "css": "case-back-title"}}, {"widgettype": "Text", "options": {"text": "Developed a full-stack AI agent solution covering bidding, investment decision-making, and contract review. The Bid Agent Engine enables bid document generation in seconds; the Investment Strategy Agent compresses weeks of research into minutes; the Contract Review Agent boosts review efficiency by over 60%.", "css": "case-back-desc"}}]}]}]}]}]}, {"widgettype": "VBox", "options": {"css": "cta", "width": "100%", "padding": "80px 40px", "spacing": "24px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "How Do These Solutions Work in Practice?", "css": "cta-title"}}, {"widgettype": "Text", "options": {"text": "Get industry-specific AI solutions.", "css": "cta-sub"}}, {"widgettype": "Button", "options": {"label": "Contact Us →", "css": "hero-btn-primary"}}]}, {"widgettype": "VBox", "options": {"css": "section", "width": "100%", "padding": "80px 40px", "spacing": "40px"}, "subwidgets": [{"widgettype": "HBox", "options": {"width": "100%", "justifyContent": "space-between", "alignItems": "center"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Company News", "css": "section-title"}}, {"widgettype": "Text", "options": {"text": "View More →", "css": "view-more"}}]}, {"widgettype": "HBox", "options": {"width": "100%", "spacing": "24px"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "news-card", "spacing": "16px"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Kaiyuan Cloud Certified with Level-3 Security Protection Filing", "css": "news-title"}}, {"widgettype": "Text", "options": {"text": "Dec 2024", "css": "news-date"}}]}, {"widgettype": "VBox", "options": {"css": "news-card", "spacing": "16px"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Kaiyuan Cloud Wins Bid for Beijing Academy of AI (BAAI) Project", "css": "news-title"}}, {"widgettype": "Text", "options": {"text": "Oct 2024", "css": "news-date"}}]}]}]}], "id": "center"}, {"widgettype": "HBox", "options": {"css": "footer", "width": "100%", "padding": "60px 40px", "spacing": "80px", "justifyContent": "center"}, "subwidgets": [{"widgettype": "VBox", "options": {"spacing": "16px"}, "subwidgets": [{"widgettype": "Image", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/imgs/logo.png')}}", "css": "footer-logo"}}, {"widgettype": "Text", "options": {"text": "让AI无处不在,让AI触手可及", "css": "footer-tagline"}}]}, {"widgettype": "VBox", "options": {"spacing": "12px"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "产品与服务", "css": "footer-heading"}}, {"widgettype": "Text", "options": {"text": "OPC", "css": "footer-link"}}, {"widgettype": "Text", "options": {"text": "算力市场", "css": "footer-link"}}, {"widgettype": "Text", "options": {"text": "Token市场", "css": "footer-link"}}, {"widgettype": "Text", "options": {"text": "元境", "css": "footer-link"}}, {"widgettype": "Text", "options": {"text": "训练推理", "css": "footer-link"}}, {"widgettype": "Text", "options": {"text": "Agent Store", "css": "footer-link"}}, {"widgettype": "Text", "options": {"text": "供应广场", "css": "footer-link"}}]}, {"widgettype": "VBox", "options": {"spacing": "12px"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "联系我们", "css": "footer-heading"}}, {"widgettype": "Text", "options": {"text": "地址:北京市朝阳区东三环中路65号富力中心", "css": "footer-link"}}, {"widgettype": "Text", "options": {"text": "邮箱:Open-computing@kaiyuancloud.cn", "css": "footer-link"}}, {"widgettype": "Text", "options": {"text": "电话:400-6150805 010-65917875", "css": "footer-link"}}, {"widgettype": "HBox", "options": {"spacing": "24px"}, "subwidgets": [{"widgettype": "VBox", "options": {"spacing": "6px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Image", "options": {"url": "https://www.opencomputing.cn/static/img/img.936873a3.png", "css": "footer-qr"}}, {"widgettype": "Text", "options": {"text": "在线咨询", "css": "footer-qr-label"}}]}, {"widgettype": "VBox", "options": {"spacing": "6px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Image", "options": {"url": "https://www.opencomputing.cn/static/img/kefu.96ff99fe.jpg", "css": "footer-qr"}}, {"widgettype": "Text", "options": {"text": "关注公众号", "css": "footer-qr-label"}}]}]}]}]}, {"widgettype": "HBox", "options": {"css": "footer-icp-bar", "width": "100%", "padding": "16px 40px", "justifyContent": "center", "alignItems": "center"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "京ICP备2022001945号-2", "css": "footer-icp-link"}, "binds": [{"wid": "self", "event": "click", "actiontype": "script", "script": "window.open('https://beian.miit.gov.cn/','_blank');"}]}, {"widgettype": "Text", "options": {"text": "开元云(北京)科技有限公司", "css": "footer-icp-text"}}]}, {"widgettype": "VBox", "options": {"css": "float-chat", "spacing": "4px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Image", "options": {"url": "https://www.opencomputing.cn/static/img/ocai.9af463db.jpg", "css": "float-chat-avatar"}}, {"widgettype": "Text", "options": {"text": "在线咨询", "css": "float-chat-label"}}], "binds": [{"wid": "self", "event": "click", "actiontype": "script", "script": "var m=document.getElementById('cmodal');if(!m){m=document.createElement('div');m.id='cmodal';m.innerHTML='

在线咨询

请留下您的联系方式,我们的顾问将尽快与您联系

信息仅用于顾问联系

';m.style.cssText='position:fixed;top:0;left:0;width:100%;height:100%;z-index:9999';document.body.appendChild(m);}"}]}]} \ No newline at end of file diff --git a/wwwroot/tokentest.opencomputing.cn/index_jp.ui b/wwwroot/tokentest.opencomputing.cn/index_jp.ui new file mode 100644 index 00000000..1f787aa9 --- /dev/null +++ b/wwwroot/tokentest.opencomputing.cn/index_jp.ui @@ -0,0 +1 @@ +{"widgettype": "VBox", "options": {"css": "page", "width": "100%", "spacing": 0}, "subwidgets": [{"widgettype": "HBox", "options": {"css": "header", "width": "100%", "padding": "0 40px", "alignItems": "center", "justifyContent": "space-between"}, "subwidgets": [{"widgettype": "Image", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/imgs/logo.png')}}", "css": "logo"}, "id": "logo", "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/center_home_en.ui')}}"}}]}, {"widgettype": "HBox", "options": {"css": "nav-area"}, "subwidgets": [{"widgettype": "HBox", "options": {"css": "nav-links", "spacing": "32px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Home", "css": "nav-link active"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/center_home_en.ui')}}"}}]}, {"widgettype": "VBox", "options": {"css": "products-menu"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Products ▾", "css": "nav-link"}}, {"widgettype": "VBox", "options": {"css": "products-dropdown"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "OPC", "css": "dropdown-item"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/opc/index_en.ui')}}"}}]}, {"widgettype": "Text", "options": {"text": "Compute Market", "css": "dropdown-item"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/compute/index_en.ui')}}"}}]}, {"widgettype": "Text", "options": {"text": "Token Market", "css": "dropdown-item"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/llmage/model_plaza.ui')}}"}}]}, {"widgettype": "Text", "options": {"text": "Yuanjing", "css": "dropdown-item"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/yunjing/index_en.ui')}}"}}]}, {"widgettype": "Text", "options": {"text": "Train & Infer", "css": "dropdown-item"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/train/index_en.ui')}}"}}]}, {"widgettype": "Text", "options": {"text": "Agent Store", "css": "dropdown-item"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/agent/index_en.ui')}}"}}]}, {"widgettype": "Text", "options": {"text": "Supply Square", "css": "dropdown-item"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/supplychain/index_en.ui')}}"}}]}]}]}, {"widgettype": "Text", "options": {"text": "Use Cases", "css": "nav-link"}}, {"widgettype": "Text", "options": {"text": "News", "css": "nav-link"}}]}]}, {"widgettype": "HBox", "options": {"css": "header-actions", "spacing": "12px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Button", "options": {"label": "☀", "css": "theme-btn"}, "id": "themeToggle", "binds": [{"wid": "self", "event": "click", "actiontype": "script", "script": "if(window._toggleTheme)window._toggleTheme();var t=document.documentElement.getAttribute('data-theme');var b=document.getElementById('themeToggle');if(b){var s=b.querySelector('div');if(s)s.textContent=t==='dark'?'☾':'☀';}"}]}, {"widgettype": "Button", "options": {"label": "EN/中", "css": "lang-btn"}, "binds": [{"wid": "self", "event": "click", "actiontype": "script", "script": "localStorage.setItem('hermes-lang','zh');location.href='/tokentest.opencomputing.cn/index_zh.ui';"}]}, {"widgettype": "Button", "options": {"label": "Login", "css": "login-pill"}, "binds": [{"wid": "self", "event": "click", "actiontype": "script", "script": "window.location.href='{{entire_url(\"/rbac/user/login.ui\")}}';"}]}]}]}, {"widgettype": "VBox", "options": {"css": "center-area", "width": "100%", "spacing": 0}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "hero", "width": "100%", "padding": "120px 40px 100px", "alignItems": "center", "spacing": "16px"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "One Platform · Intelligent Leap ·", "css": "hero-title"}}, {"widgettype": "Text", "options": {"text": "Across All Industries.", "css": "hero-title2"}}, {"widgettype": "Text", "options": {"text": "Make AI Everywhere, Make AI Easy", "css": "hero-sub"}}, {"widgettype": "HBox", "options": {"spacing": "16px"}, "subwidgets": [{"widgettype": "Button", "options": {"label": "Solutions", "css": "hero-btn-primary"}}, {"widgettype": "Button", "options": {"label": "Contact Sales", "css": "hero-btn-outline"}}]}]}, {"widgettype": "VBox", "options": {"css": "section", "width": "100%", "padding": "80px 40px 60px", "spacing": "40px"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "AI + Solutions", "css": "section-title"}}, {"widgettype": "VBox", "options": {"css": "carousel-container"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "carousel-track"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs0", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Full Protection", "css": "card-title"}}, {"widgettype": "Text", "options": {"text": "Device Intelligent Monitoring", "css": "card-subtitle"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Full Protection", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "Build independent monitoring strategies for each device, presenting real-time operational status through 3D visualization. AI automatically identifies anomalies, pinpoints fault locations, and outputs detailed diagnostic recommendations and troubleshooting steps in seconds.", "css": "card-text-white"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs1", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Read and Comprehend", "css": "card-title"}}, {"widgettype": "Text", "options": {"text": "Smart Document Parsing", "css": "card-subtitle"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Read and Comprehend", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "One-click parsing of PDF, Word, and scanned documents. AI automatically extracts key clauses, qualification requirements, and scoring criteria with structured presentation. Not just OCR, but semantic understanding, importance assessment, and risk flagging.", "css": "card-text-white"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs2", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "On-Site Intelligence", "css": "card-title"}}, {"widgettype": "Text", "options": {"text": "Edge AI Inference", "css": "card-subtitle"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "On-Site Intelligence", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "Deploy AI inference at the production edge with lightweight algorithms for millisecond-level real-time decisions. Data stays on-premises — no cloud upload needed. Redundant architecture ensures 7×24 continuous operation, zero downtime for production inspection.", "css": "card-text-white"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs3", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Collaborative Intelligence", "css": "card-title"}}, {"widgettype": "Text", "options": {"text": "Multi-Agent Collaboration", "css": "card-subtitle"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Collaborative Intelligence", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "Multiple AI agents collaborate by role, autonomously handling data collection, analysis, reasoning, and conclusion generation. Dynamic task allocation and context sharing transform complex decisions from human-dependent workflows to parallel agent execution.", "css": "card-text-white"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs4", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Spatial Intelligence", "css": "card-title"}}, {"widgettype": "Text", "options": {"text": "GIS Smart Analysis", "css": "card-subtitle"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Spatial Intelligence", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "Fusing GIS, satellite remote sensing, and UAV imagery, AI automatically identifies terrain boundaries, overlays spatial relationships, and verifies compliance constraints. Upgrades traditional manual geospatial comparison to minute-level automated spatial intelligence.", "css": "card-text-white"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs5", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Predictive Insight", "css": "card-title"}}, {"widgettype": "Text", "options": {"text": "Machine Vision Inspection", "css": "card-subtitle"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Predictive Insight", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "Deep learning-based full-width defect detection for high-speed production lines, covering surface treatment, coating, welding, and assembly. AI compares every inch of product pixel-by-pixel at millisecond speed — zero quality compromise.", "css": "card-text-white"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs6", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Instant Answers", "css": "card-title"}}, {"widgettype": "Text", "options": {"text": "Smart Q&A Knowledge Base", "css": "card-subtitle"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Instant Answers", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "Enterprise private knowledge base AI Q&A engine supporting natural language queries on business data, technical specs, and institutional documents. Every answer cites authoritative sources — traceable and verifiable. Expert knowledge is as accessible as asking a colleague.", "css": "card-text-white"}}]}]}]}]}]}]}, {"widgettype": "VBox", "options": {"css": "section section-alt", "width": "100%", "padding": "80px 40px", "spacing": "40px"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Use Cases", "css": "section-title"}}, {"widgettype": "HBox", "options": {"css": "case-cards", "width": "100%", "spacing": "24px", "justifyContent": "center"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip-front", "spacing": "0"}, "subwidgets": [{"widgettype": "Image", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/imgs/case-railway.png')}}", "css": "case-img"}}, {"widgettype": "Text", "options": {"text": "Smart Engineering", "css": "case-name"}}, {"widgettype": "Text", "options": {"text": "China Railway Group · Huitobid", "css": "case-client"}}, {"widgettype": "Text", "options": {"text": "Built the Huitobid and HuiTu Large Model for China Railway Group, establishing a…", "css": "case-desc"}}]}, {"widgettype": "VBox", "options": {"css": "case-flip-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Smart Engineering", "css": "case-back-title"}}, {"widgettype": "Text", "options": {"text": "Built the Huitobid and HuiTu Large Model for China Railway Group, establishing a Joint Innovation Center and AI Application Innovation Platform. Covering the full bidding lifecycle — intelligent document analysis, automatic qualification matching, pricing decision support, and smart bid compilation.", "css": "case-back-desc"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "case-flip"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip-front", "spacing": "0"}, "subwidgets": [{"widgettype": "Image", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/imgs/case-forestry.png')}}", "css": "case-img"}}, {"widgettype": "Text", "options": {"text": "Smart Harvesting", "css": "case-name"}}, {"widgettype": "Text", "options": {"text": "Nanning Forestry Bureau", "css": "case-client"}}, {"widgettype": "Text", "options": {"text": "Developed an Intelligent Forest Harvesting Spatial Review System integrating GIS…", "css": "case-desc"}}]}, {"widgettype": "VBox", "options": {"css": "case-flip-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Smart Harvesting", "css": "case-back-title"}}, {"widgettype": "Text", "options": {"text": "Developed an Intelligent Forest Harvesting Spatial Review System integrating GIS spatial analysis, satellite remote sensing, and multi-source UAV data. Harvesting boundaries are automatically verified for compliance, review reports are generated with one click, and the approval cycle is compressed from days to minutes.", "css": "case-back-desc"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "case-flip"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip-front", "spacing": "0"}, "subwidgets": [{"widgettype": "Image", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/imgs/case-port.png')}}", "css": "case-img"}}, {"widgettype": "Text", "options": {"text": "Digital Transformation", "css": "case-name"}}, {"widgettype": "Text", "options": {"text": "Beibu Gulf Port Big Data", "css": "case-client"}}, {"widgettype": "Text", "options": {"text": "Developed a full-stack AI agent solution covering bidding, investment decision-m…", "css": "case-desc"}}]}, {"widgettype": "VBox", "options": {"css": "case-flip-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Digital Transformation", "css": "case-back-title"}}, {"widgettype": "Text", "options": {"text": "Developed a full-stack AI agent solution covering bidding, investment decision-making, and contract review. The Bid Agent Engine enables bid document generation in seconds; the Investment Strategy Agent compresses weeks of research into minutes; the Contract Review Agent boosts review efficiency by over 60%.", "css": "case-back-desc"}}]}]}]}]}]}, {"widgettype": "VBox", "options": {"css": "cta", "width": "100%", "padding": "80px 40px", "spacing": "24px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "How Do These Solutions Work in Practice?", "css": "cta-title"}}, {"widgettype": "Text", "options": {"text": "Get industry-specific AI solutions.", "css": "cta-sub"}}, {"widgettype": "Button", "options": {"label": "Contact Us →", "css": "hero-btn-primary"}}]}, {"widgettype": "VBox", "options": {"css": "section", "width": "100%", "padding": "80px 40px", "spacing": "40px"}, "subwidgets": [{"widgettype": "HBox", "options": {"width": "100%", "justifyContent": "space-between", "alignItems": "center"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Company News", "css": "section-title"}}, {"widgettype": "Text", "options": {"text": "View More →", "css": "view-more"}}]}, {"widgettype": "HBox", "options": {"width": "100%", "spacing": "24px"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "news-card", "spacing": "16px"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Kaiyuan Cloud Certified with Level-3 Security Protection Filing", "css": "news-title"}}, {"widgettype": "Text", "options": {"text": "Dec 2024", "css": "news-date"}}]}, {"widgettype": "VBox", "options": {"css": "news-card", "spacing": "16px"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Kaiyuan Cloud Wins Bid for Beijing Academy of AI (BAAI) Project", "css": "news-title"}}, {"widgettype": "Text", "options": {"text": "Oct 2024", "css": "news-date"}}]}]}]}], "id": "center"}, {"widgettype": "HBox", "options": {"css": "footer", "width": "100%", "padding": "60px 40px", "spacing": "80px", "justifyContent": "center"}, "subwidgets": [{"widgettype": "VBox", "options": {"spacing": "16px"}, "subwidgets": [{"widgettype": "Image", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/imgs/logo.png')}}", "css": "footer-logo"}}, {"widgettype": "Text", "options": {"text": "让AI无处不在,让AI触手可及", "css": "footer-tagline"}}]}, {"widgettype": "VBox", "options": {"spacing": "12px"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "产品与服务", "css": "footer-heading"}}, {"widgettype": "Text", "options": {"text": "OPC", "css": "footer-link"}}, {"widgettype": "Text", "options": {"text": "算力市场", "css": "footer-link"}}, {"widgettype": "Text", "options": {"text": "Token市场", "css": "footer-link"}}, {"widgettype": "Text", "options": {"text": "元境", "css": "footer-link"}}, {"widgettype": "Text", "options": {"text": "训练推理", "css": "footer-link"}}, {"widgettype": "Text", "options": {"text": "Agent Store", "css": "footer-link"}}, {"widgettype": "Text", "options": {"text": "供应广场", "css": "footer-link"}}]}, {"widgettype": "VBox", "options": {"spacing": "12px"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "联系我们", "css": "footer-heading"}}, {"widgettype": "Text", "options": {"text": "地址:北京市朝阳区东三环中路65号富力中心", "css": "footer-link"}}, {"widgettype": "Text", "options": {"text": "邮箱:Open-computing@kaiyuancloud.cn", "css": "footer-link"}}, {"widgettype": "Text", "options": {"text": "电话:400-6150805 010-65917875", "css": "footer-link"}}, {"widgettype": "HBox", "options": {"spacing": "24px"}, "subwidgets": [{"widgettype": "VBox", "options": {"spacing": "6px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Image", "options": {"url": "https://www.opencomputing.cn/static/img/img.936873a3.png", "css": "footer-qr"}}, {"widgettype": "Text", "options": {"text": "在线咨询", "css": "footer-qr-label"}}]}, {"widgettype": "VBox", "options": {"spacing": "6px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Image", "options": {"url": "https://www.opencomputing.cn/static/img/kefu.96ff99fe.jpg", "css": "footer-qr"}}, {"widgettype": "Text", "options": {"text": "关注公众号", "css": "footer-qr-label"}}]}]}]}]}, {"widgettype": "HBox", "options": {"css": "footer-icp-bar", "width": "100%", "padding": "16px 40px", "justifyContent": "center", "alignItems": "center"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "京ICP备2022001945号-2", "css": "footer-icp-link"}, "binds": [{"wid": "self", "event": "click", "actiontype": "script", "script": "window.open('https://beian.miit.gov.cn/','_blank');"}]}, {"widgettype": "Text", "options": {"text": "开元云(北京)科技有限公司", "css": "footer-icp-text"}}]}, {"widgettype": "VBox", "options": {"css": "float-chat", "spacing": "4px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Image", "options": {"url": "https://www.opencomputing.cn/static/img/ocai.9af463db.jpg", "css": "float-chat-avatar"}}, {"widgettype": "Text", "options": {"text": "在线咨询", "css": "float-chat-label"}}], "binds": [{"wid": "self", "event": "click", "actiontype": "script", "script": "var m=document.getElementById('cmodal');if(!m){m=document.createElement('div');m.id='cmodal';m.innerHTML='

在线咨询

请留下您的联系方式,我们的顾问将尽快与您联系

信息仅用于顾问联系

';m.style.cssText='position:fixed;top:0;left:0;width:100%;height:100%;z-index:9999';document.body.appendChild(m);}"}]}]} \ No newline at end of file diff --git a/wwwroot/tokentest.opencomputing.cn/index_ko.ui b/wwwroot/tokentest.opencomputing.cn/index_ko.ui new file mode 100644 index 00000000..1f787aa9 --- /dev/null +++ b/wwwroot/tokentest.opencomputing.cn/index_ko.ui @@ -0,0 +1 @@ +{"widgettype": "VBox", "options": {"css": "page", "width": "100%", "spacing": 0}, "subwidgets": [{"widgettype": "HBox", "options": {"css": "header", "width": "100%", "padding": "0 40px", "alignItems": "center", "justifyContent": "space-between"}, "subwidgets": [{"widgettype": "Image", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/imgs/logo.png')}}", "css": "logo"}, "id": "logo", "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/center_home_en.ui')}}"}}]}, {"widgettype": "HBox", "options": {"css": "nav-area"}, "subwidgets": [{"widgettype": "HBox", "options": {"css": "nav-links", "spacing": "32px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Home", "css": "nav-link active"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/center_home_en.ui')}}"}}]}, {"widgettype": "VBox", "options": {"css": "products-menu"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Products ▾", "css": "nav-link"}}, {"widgettype": "VBox", "options": {"css": "products-dropdown"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "OPC", "css": "dropdown-item"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/opc/index_en.ui')}}"}}]}, {"widgettype": "Text", "options": {"text": "Compute Market", "css": "dropdown-item"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/compute/index_en.ui')}}"}}]}, {"widgettype": "Text", "options": {"text": "Token Market", "css": "dropdown-item"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/llmage/model_plaza.ui')}}"}}]}, {"widgettype": "Text", "options": {"text": "Yuanjing", "css": "dropdown-item"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/yunjing/index_en.ui')}}"}}]}, {"widgettype": "Text", "options": {"text": "Train & Infer", "css": "dropdown-item"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/train/index_en.ui')}}"}}]}, {"widgettype": "Text", "options": {"text": "Agent Store", "css": "dropdown-item"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/agent/index_en.ui')}}"}}]}, {"widgettype": "Text", "options": {"text": "Supply Square", "css": "dropdown-item"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/supplychain/index_en.ui')}}"}}]}]}]}, {"widgettype": "Text", "options": {"text": "Use Cases", "css": "nav-link"}}, {"widgettype": "Text", "options": {"text": "News", "css": "nav-link"}}]}]}, {"widgettype": "HBox", "options": {"css": "header-actions", "spacing": "12px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Button", "options": {"label": "☀", "css": "theme-btn"}, "id": "themeToggle", "binds": [{"wid": "self", "event": "click", "actiontype": "script", "script": "if(window._toggleTheme)window._toggleTheme();var t=document.documentElement.getAttribute('data-theme');var b=document.getElementById('themeToggle');if(b){var s=b.querySelector('div');if(s)s.textContent=t==='dark'?'☾':'☀';}"}]}, {"widgettype": "Button", "options": {"label": "EN/中", "css": "lang-btn"}, "binds": [{"wid": "self", "event": "click", "actiontype": "script", "script": "localStorage.setItem('hermes-lang','zh');location.href='/tokentest.opencomputing.cn/index_zh.ui';"}]}, {"widgettype": "Button", "options": {"label": "Login", "css": "login-pill"}, "binds": [{"wid": "self", "event": "click", "actiontype": "script", "script": "window.location.href='{{entire_url(\"/rbac/user/login.ui\")}}';"}]}]}]}, {"widgettype": "VBox", "options": {"css": "center-area", "width": "100%", "spacing": 0}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "hero", "width": "100%", "padding": "120px 40px 100px", "alignItems": "center", "spacing": "16px"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "One Platform · Intelligent Leap ·", "css": "hero-title"}}, {"widgettype": "Text", "options": {"text": "Across All Industries.", "css": "hero-title2"}}, {"widgettype": "Text", "options": {"text": "Make AI Everywhere, Make AI Easy", "css": "hero-sub"}}, {"widgettype": "HBox", "options": {"spacing": "16px"}, "subwidgets": [{"widgettype": "Button", "options": {"label": "Solutions", "css": "hero-btn-primary"}}, {"widgettype": "Button", "options": {"label": "Contact Sales", "css": "hero-btn-outline"}}]}]}, {"widgettype": "VBox", "options": {"css": "section", "width": "100%", "padding": "80px 40px 60px", "spacing": "40px"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "AI + Solutions", "css": "section-title"}}, {"widgettype": "VBox", "options": {"css": "carousel-container"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "carousel-track"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs0", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Full Protection", "css": "card-title"}}, {"widgettype": "Text", "options": {"text": "Device Intelligent Monitoring", "css": "card-subtitle"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Full Protection", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "Build independent monitoring strategies for each device, presenting real-time operational status through 3D visualization. AI automatically identifies anomalies, pinpoints fault locations, and outputs detailed diagnostic recommendations and troubleshooting steps in seconds.", "css": "card-text-white"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs1", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Read and Comprehend", "css": "card-title"}}, {"widgettype": "Text", "options": {"text": "Smart Document Parsing", "css": "card-subtitle"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Read and Comprehend", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "One-click parsing of PDF, Word, and scanned documents. AI automatically extracts key clauses, qualification requirements, and scoring criteria with structured presentation. Not just OCR, but semantic understanding, importance assessment, and risk flagging.", "css": "card-text-white"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs2", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "On-Site Intelligence", "css": "card-title"}}, {"widgettype": "Text", "options": {"text": "Edge AI Inference", "css": "card-subtitle"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "On-Site Intelligence", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "Deploy AI inference at the production edge with lightweight algorithms for millisecond-level real-time decisions. Data stays on-premises — no cloud upload needed. Redundant architecture ensures 7×24 continuous operation, zero downtime for production inspection.", "css": "card-text-white"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs3", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Collaborative Intelligence", "css": "card-title"}}, {"widgettype": "Text", "options": {"text": "Multi-Agent Collaboration", "css": "card-subtitle"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Collaborative Intelligence", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "Multiple AI agents collaborate by role, autonomously handling data collection, analysis, reasoning, and conclusion generation. Dynamic task allocation and context sharing transform complex decisions from human-dependent workflows to parallel agent execution.", "css": "card-text-white"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs4", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Spatial Intelligence", "css": "card-title"}}, {"widgettype": "Text", "options": {"text": "GIS Smart Analysis", "css": "card-subtitle"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Spatial Intelligence", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "Fusing GIS, satellite remote sensing, and UAV imagery, AI automatically identifies terrain boundaries, overlays spatial relationships, and verifies compliance constraints. Upgrades traditional manual geospatial comparison to minute-level automated spatial intelligence.", "css": "card-text-white"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs5", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Predictive Insight", "css": "card-title"}}, {"widgettype": "Text", "options": {"text": "Machine Vision Inspection", "css": "card-subtitle"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Predictive Insight", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "Deep learning-based full-width defect detection for high-speed production lines, covering surface treatment, coating, welding, and assembly. AI compares every inch of product pixel-by-pixel at millisecond speed — zero quality compromise.", "css": "card-text-white"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs6", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Instant Answers", "css": "card-title"}}, {"widgettype": "Text", "options": {"text": "Smart Q&A Knowledge Base", "css": "card-subtitle"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Instant Answers", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "Enterprise private knowledge base AI Q&A engine supporting natural language queries on business data, technical specs, and institutional documents. Every answer cites authoritative sources — traceable and verifiable. Expert knowledge is as accessible as asking a colleague.", "css": "card-text-white"}}]}]}]}]}]}]}, {"widgettype": "VBox", "options": {"css": "section section-alt", "width": "100%", "padding": "80px 40px", "spacing": "40px"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Use Cases", "css": "section-title"}}, {"widgettype": "HBox", "options": {"css": "case-cards", "width": "100%", "spacing": "24px", "justifyContent": "center"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip-front", "spacing": "0"}, "subwidgets": [{"widgettype": "Image", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/imgs/case-railway.png')}}", "css": "case-img"}}, {"widgettype": "Text", "options": {"text": "Smart Engineering", "css": "case-name"}}, {"widgettype": "Text", "options": {"text": "China Railway Group · Huitobid", "css": "case-client"}}, {"widgettype": "Text", "options": {"text": "Built the Huitobid and HuiTu Large Model for China Railway Group, establishing a…", "css": "case-desc"}}]}, {"widgettype": "VBox", "options": {"css": "case-flip-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Smart Engineering", "css": "case-back-title"}}, {"widgettype": "Text", "options": {"text": "Built the Huitobid and HuiTu Large Model for China Railway Group, establishing a Joint Innovation Center and AI Application Innovation Platform. Covering the full bidding lifecycle — intelligent document analysis, automatic qualification matching, pricing decision support, and smart bid compilation.", "css": "case-back-desc"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "case-flip"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip-front", "spacing": "0"}, "subwidgets": [{"widgettype": "Image", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/imgs/case-forestry.png')}}", "css": "case-img"}}, {"widgettype": "Text", "options": {"text": "Smart Harvesting", "css": "case-name"}}, {"widgettype": "Text", "options": {"text": "Nanning Forestry Bureau", "css": "case-client"}}, {"widgettype": "Text", "options": {"text": "Developed an Intelligent Forest Harvesting Spatial Review System integrating GIS…", "css": "case-desc"}}]}, {"widgettype": "VBox", "options": {"css": "case-flip-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Smart Harvesting", "css": "case-back-title"}}, {"widgettype": "Text", "options": {"text": "Developed an Intelligent Forest Harvesting Spatial Review System integrating GIS spatial analysis, satellite remote sensing, and multi-source UAV data. Harvesting boundaries are automatically verified for compliance, review reports are generated with one click, and the approval cycle is compressed from days to minutes.", "css": "case-back-desc"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "case-flip"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip-front", "spacing": "0"}, "subwidgets": [{"widgettype": "Image", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/imgs/case-port.png')}}", "css": "case-img"}}, {"widgettype": "Text", "options": {"text": "Digital Transformation", "css": "case-name"}}, {"widgettype": "Text", "options": {"text": "Beibu Gulf Port Big Data", "css": "case-client"}}, {"widgettype": "Text", "options": {"text": "Developed a full-stack AI agent solution covering bidding, investment decision-m…", "css": "case-desc"}}]}, {"widgettype": "VBox", "options": {"css": "case-flip-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Digital Transformation", "css": "case-back-title"}}, {"widgettype": "Text", "options": {"text": "Developed a full-stack AI agent solution covering bidding, investment decision-making, and contract review. The Bid Agent Engine enables bid document generation in seconds; the Investment Strategy Agent compresses weeks of research into minutes; the Contract Review Agent boosts review efficiency by over 60%.", "css": "case-back-desc"}}]}]}]}]}]}, {"widgettype": "VBox", "options": {"css": "cta", "width": "100%", "padding": "80px 40px", "spacing": "24px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "How Do These Solutions Work in Practice?", "css": "cta-title"}}, {"widgettype": "Text", "options": {"text": "Get industry-specific AI solutions.", "css": "cta-sub"}}, {"widgettype": "Button", "options": {"label": "Contact Us →", "css": "hero-btn-primary"}}]}, {"widgettype": "VBox", "options": {"css": "section", "width": "100%", "padding": "80px 40px", "spacing": "40px"}, "subwidgets": [{"widgettype": "HBox", "options": {"width": "100%", "justifyContent": "space-between", "alignItems": "center"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Company News", "css": "section-title"}}, {"widgettype": "Text", "options": {"text": "View More →", "css": "view-more"}}]}, {"widgettype": "HBox", "options": {"width": "100%", "spacing": "24px"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "news-card", "spacing": "16px"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Kaiyuan Cloud Certified with Level-3 Security Protection Filing", "css": "news-title"}}, {"widgettype": "Text", "options": {"text": "Dec 2024", "css": "news-date"}}]}, {"widgettype": "VBox", "options": {"css": "news-card", "spacing": "16px"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Kaiyuan Cloud Wins Bid for Beijing Academy of AI (BAAI) Project", "css": "news-title"}}, {"widgettype": "Text", "options": {"text": "Oct 2024", "css": "news-date"}}]}]}]}], "id": "center"}, {"widgettype": "HBox", "options": {"css": "footer", "width": "100%", "padding": "60px 40px", "spacing": "80px", "justifyContent": "center"}, "subwidgets": [{"widgettype": "VBox", "options": {"spacing": "16px"}, "subwidgets": [{"widgettype": "Image", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/imgs/logo.png')}}", "css": "footer-logo"}}, {"widgettype": "Text", "options": {"text": "让AI无处不在,让AI触手可及", "css": "footer-tagline"}}]}, {"widgettype": "VBox", "options": {"spacing": "12px"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "产品与服务", "css": "footer-heading"}}, {"widgettype": "Text", "options": {"text": "OPC", "css": "footer-link"}}, {"widgettype": "Text", "options": {"text": "算力市场", "css": "footer-link"}}, {"widgettype": "Text", "options": {"text": "Token市场", "css": "footer-link"}}, {"widgettype": "Text", "options": {"text": "元境", "css": "footer-link"}}, {"widgettype": "Text", "options": {"text": "训练推理", "css": "footer-link"}}, {"widgettype": "Text", "options": {"text": "Agent Store", "css": "footer-link"}}, {"widgettype": "Text", "options": {"text": "供应广场", "css": "footer-link"}}]}, {"widgettype": "VBox", "options": {"spacing": "12px"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "联系我们", "css": "footer-heading"}}, {"widgettype": "Text", "options": {"text": "地址:北京市朝阳区东三环中路65号富力中心", "css": "footer-link"}}, {"widgettype": "Text", "options": {"text": "邮箱:Open-computing@kaiyuancloud.cn", "css": "footer-link"}}, {"widgettype": "Text", "options": {"text": "电话:400-6150805 010-65917875", "css": "footer-link"}}, {"widgettype": "HBox", "options": {"spacing": "24px"}, "subwidgets": [{"widgettype": "VBox", "options": {"spacing": "6px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Image", "options": {"url": "https://www.opencomputing.cn/static/img/img.936873a3.png", "css": "footer-qr"}}, {"widgettype": "Text", "options": {"text": "在线咨询", "css": "footer-qr-label"}}]}, {"widgettype": "VBox", "options": {"spacing": "6px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Image", "options": {"url": "https://www.opencomputing.cn/static/img/kefu.96ff99fe.jpg", "css": "footer-qr"}}, {"widgettype": "Text", "options": {"text": "关注公众号", "css": "footer-qr-label"}}]}]}]}]}, {"widgettype": "HBox", "options": {"css": "footer-icp-bar", "width": "100%", "padding": "16px 40px", "justifyContent": "center", "alignItems": "center"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "京ICP备2022001945号-2", "css": "footer-icp-link"}, "binds": [{"wid": "self", "event": "click", "actiontype": "script", "script": "window.open('https://beian.miit.gov.cn/','_blank');"}]}, {"widgettype": "Text", "options": {"text": "开元云(北京)科技有限公司", "css": "footer-icp-text"}}]}, {"widgettype": "VBox", "options": {"css": "float-chat", "spacing": "4px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Image", "options": {"url": "https://www.opencomputing.cn/static/img/ocai.9af463db.jpg", "css": "float-chat-avatar"}}, {"widgettype": "Text", "options": {"text": "在线咨询", "css": "float-chat-label"}}], "binds": [{"wid": "self", "event": "click", "actiontype": "script", "script": "var m=document.getElementById('cmodal');if(!m){m=document.createElement('div');m.id='cmodal';m.innerHTML='

在线咨询

请留下您的联系方式,我们的顾问将尽快与您联系

信息仅用于顾问联系

';m.style.cssText='position:fixed;top:0;left:0;width:100%;height:100%;z-index:9999';document.body.appendChild(m);}"}]}]} \ No newline at end of file diff --git a/wwwroot/tokentest.opencomputing.cn/index_zh.ui b/wwwroot/tokentest.opencomputing.cn/index_zh.ui new file mode 100644 index 00000000..973b9ea3 --- /dev/null +++ b/wwwroot/tokentest.opencomputing.cn/index_zh.ui @@ -0,0 +1 @@ +{"widgettype": "VBox", "options": {"css": "page", "width": "100%", "spacing": 0}, "subwidgets": [{"widgettype": "HBox", "options": {"css": "header", "width": "100%", "padding": "0 40px", "alignItems": "center", "justifyContent": "space-between"}, "subwidgets": [{"widgettype": "Image", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/imgs/logo.png')}}", "css": "logo"}, "id": "logo", "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/center_home_zh.ui')}}"}}]}, {"widgettype": "HBox", "options": {"css": "nav-area"}, "subwidgets": [{"widgettype": "HBox", "options": {"css": "nav-links", "spacing": "32px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "首页", "css": "nav-link active"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/center_home_zh.ui')}}"}}]}, {"widgettype": "VBox", "options": {"css": "products-menu"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "产品 ▾", "css": "nav-link"}}, {"widgettype": "VBox", "options": {"css": "products-dropdown"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "OPC", "css": "dropdown-item"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/opc/index_zh.ui')}}"}}]}, {"widgettype": "Text", "options": {"text": "算力市场", "css": "dropdown-item"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/compute/index_zh.ui')}}"}}]}, {"widgettype": "Text", "options": {"text": "Token市场", "css": "dropdown-item"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/llmage/model_plaza.ui')}}"}}]}, {"widgettype": "Text", "options": {"text": "元境", "css": "dropdown-item"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/yunjing/index_zh.ui')}}"}}]}, {"widgettype": "Text", "options": {"text": "训练推理", "css": "dropdown-item"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/train/index_zh.ui')}}"}}]}, {"widgettype": "Text", "options": {"text": "Agent Store", "css": "dropdown-item"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/agent/index_zh.ui')}}"}}]}, {"widgettype": "Text", "options": {"text": "供应广场", "css": "dropdown-item"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/supplychain/index_zh.ui')}}"}}]}]}]}, {"widgettype": "Text", "options": {"text": "案例", "css": "nav-link"}}, {"widgettype": "Text", "options": {"text": "动态", "css": "nav-link"}}]}]}, {"widgettype": "HBox", "options": {"css": "header-actions", "spacing": "12px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Button", "options": {"label": "☀", "css": "theme-btn"}, "id": "themeToggle", "binds": [{"wid": "self", "event": "click", "actiontype": "script", "script": "if(window._toggleTheme)window._toggleTheme();var t=document.documentElement.getAttribute('data-theme');var b=document.getElementById('themeToggle');if(b){var s=b.querySelector('div');if(s)s.textContent=t==='dark'?'☾':'☀';}"}]}, {"widgettype": "Button", "options": {"label": "中/EN", "css": "lang-btn"}, "binds": [{"wid": "self", "event": "click", "actiontype": "script", "script": "localStorage.setItem('hermes-lang','en');location.href='/tokentest.opencomputing.cn/index_en.ui';"}]}, {"widgettype": "Button", "options": {"label": "登录", "css": "login-pill"}, "binds": [{"wid": "self", "event": "click", "actiontype": "script", "script": "window.location.href='{{entire_url(\"/rbac/user/login.ui\")}}';"}]}]}]}, {"widgettype": "VBox", "options": {"css": "center-area", "width": "100%", "spacing": 0}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "hero", "width": "100%", "padding": "120px 40px 100px", "alignItems": "center", "spacing": "16px"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "一个平台,千行百业", "css": "hero-title"}}, {"widgettype": "Text", "options": {"text": "智能跃迁", "css": "hero-title2"}}, {"widgettype": "Text", "options": {"text": "让AI无处不在,让智能如此简单", "css": "hero-sub"}}, {"widgettype": "HBox", "options": {"spacing": "16px"}, "subwidgets": [{"widgettype": "Button", "options": {"label": "解决方案", "css": "hero-btn-primary"}}, {"widgettype": "Button", "options": {"label": "联系销售", "css": "hero-btn-outline"}}]}]}, {"widgettype": "VBox", "options": {"css": "section", "width": "100%", "padding": "80px 40px 60px", "spacing": "40px"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "AI+解决方案", "css": "section-title"}}, {"widgettype": "VBox", "options": {"css": "carousel-container"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "carousel-track"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs0", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "洞察入微", "css": "card-title"}}, {"widgettype": "Text", "options": {"text": "机器视觉检测", "css": "card-subtitle"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "洞察入微", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "基于深度学习的高速产线全幅面缺陷检测能力,覆盖表面处理、涂层喷涂、焊接装配等全流程质检环节。不是抽样检查,而是每一寸产品都经过AI逐像素比对,在毫秒级时间内完成缺陷识别与分类,确保出厂品质零妥协。", "css": "card-text-white"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs1", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "一问即达", "css": "card-title"}}, {"widgettype": "Text", "options": {"text": "智能问答知识库", "css": "card-subtitle"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "一问即达", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "基于企业私有知识库构建的AI问答引擎,支持自然语言直接查询业务数据、技术规范、制度文件。每条回答自动标注权威来源,信息可追溯、可验证。让专家级知识不再锁在文档里,而是像问同事一样即问即答。", "css": "card-text-white"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs2", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "全程守护", "css": "card-title"}}, {"widgettype": "Text", "options": {"text": "设备智能监控", "css": "card-subtitle"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "全程守护", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "为每台设备构建独立监控策略,通过三维可视化实时呈现运行状态。AI自动识别异常并高亮定位故障点,同步输出详细诊断建议和排查步骤。将运维人员从\"盯屏找问题\"解放出来,让系统主动告诉你问题在哪、怎么修。", "css": "card-text-white"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs3", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "触文即懂", "css": "card-title"}}, {"widgettype": "Text", "options": {"text": "智能文档解析", "css": "card-subtitle"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "触文即懂", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "支持PDF、Word、扫描件等多种格式一键解析,AI自动提取关键条款、资质要求、评分细则等核心信息并结构化呈现。不是简单的OCR文字识别,而是理解文档语义、判断信息重要性、标注风险点,让冗长文档的核心内容一目了然。", "css": "card-text-white"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs4", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "端侧即算", "css": "card-title"}}, {"widgettype": "Text", "options": {"text": "边缘AI推理", "css": "card-subtitle"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "端侧即算", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "将AI推理能力部署在生产现场边缘侧,通过轻量化算法实现毫秒级实时决策。数据无需回传云端,在本地即可完成从感知到判断的全流程,确保数据不出厂、响应零延迟。冗余架构设计保障7×24小时持续运行,产线检测永不中断。", "css": "card-text-white"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs5", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "群智协作", "css": "card-title"}}, {"widgettype": "Text", "options": {"text": "多智能体协同", "css": "card-subtitle"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "群智协作", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "多个AI智能体按角色分工,自主完成信息采集、数据分析、逻辑推理与结论生成的全流程协作。支持动态任务分配与上下文共享,将复杂业务决策从\"人串联\"变为\"智能体并行\",大幅压缩高知识密度工作的完成周期。", "css": "card-text-white"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs6", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "空间觉醒", "css": "card-title"}}, {"widgettype": "Text", "options": {"text": "GIS智能分析", "css": "card-subtitle"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "空间觉醒", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "融合地理信息系统、卫星遥感影像、无人机航拍等多维空间数据,AI自动识别地物边界、叠加分析空间关系、校验合规约束。将传统需要人工逐层比对的地理空间判断,升级为分钟级自动完成的空间智能决策。", "css": "card-text-white"}}]}]}]}]}]}]}, {"widgettype": "VBox", "options": {"css": "section section-alt", "width": "100%", "padding": "80px 40px", "spacing": "40px"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "应用案例", "css": "section-title"}}, {"widgettype": "HBox", "options": {"css": "case-cards", "width": "100%", "spacing": "24px", "justifyContent": "center"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip-front", "spacing": "0"}, "subwidgets": [{"widgettype": "Image", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/imgs/case-railway.png')}}", "css": "case-img"}}, {"widgettype": "Text", "options": {"text": "智慧工程", "css": "case-name"}}, {"widgettype": "Text", "options": {"text": "中国中铁 · 汇投标", "css": "case-client"}}, {"widgettype": "Text", "options": {"text": "为中国中铁打造汇投标和慧途大模型,建立联合创新中心和AI应用创新平台。覆盖文档分析、资质匹配、定价决策、智能编制全投标生命周期,实现人力密集型到AI驱动的跃迁式…", "css": "case-desc"}}]}, {"widgettype": "VBox", "options": {"css": "case-flip-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "智慧工程", "css": "case-back-title"}}, {"widgettype": "Text", "options": {"text": "为中国中铁打造汇投标和慧途大模型,建立联合创新中心和AI应用创新平台。覆盖文档分析、资质匹配、定价决策、智能编制全投标生命周期,实现人力密集型到AI驱动的跃迁式变革。", "css": "case-back-desc"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "case-flip"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip-front", "spacing": "0"}, "subwidgets": [{"widgettype": "Image", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/imgs/case-forestry.png')}}", "css": "case-img"}}, {"widgettype": "Text", "options": {"text": "智慧采伐", "css": "case-name"}}, {"widgettype": "Text", "options": {"text": "南宁市林业局", "css": "case-client"}}, {"widgettype": "Text", "options": {"text": "为南宁林业局开发智能森林采伐空间审核系统,集成GIS空间分析、卫星遥感和无人机多源数据,采伐边界自动合规验证,一键生成审核报告,审批周期从天压缩到分钟。", "css": "case-desc"}}]}, {"widgettype": "VBox", "options": {"css": "case-flip-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "智慧采伐", "css": "case-back-title"}}, {"widgettype": "Text", "options": {"text": "为南宁林业局开发智能森林采伐空间审核系统,集成GIS空间分析、卫星遥感和无人机多源数据,采伐边界自动合规验证,一键生成审核报告,审批周期从天压缩到分钟。", "css": "case-back-desc"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "case-flip"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip-front", "spacing": "0"}, "subwidgets": [{"widgettype": "Image", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/imgs/case-port.png')}}", "css": "case-img"}}, {"widgettype": "Text", "options": {"text": "数智化转型", "css": "case-name"}}, {"widgettype": "Text", "options": {"text": "北部湾港大数据", "css": "case-client"}}, {"widgettype": "Text", "options": {"text": "为北部湾港大数据打造全栈AI智能体解决方案,覆盖招投标、投资决策、合同审查。投标引擎秒级生成标书,投策引擎将数周报告压缩到分钟级,合同审查效率提升60%+。", "css": "case-desc"}}]}, {"widgettype": "VBox", "options": {"css": "case-flip-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "数智化转型", "css": "case-back-title"}}, {"widgettype": "Text", "options": {"text": "为北部湾港大数据打造全栈AI智能体解决方案,覆盖招投标、投资决策、合同审查。投标引擎秒级生成标书,投策引擎将数周报告压缩到分钟级,合同审查效率提升60%+。", "css": "case-back-desc"}}]}]}]}]}]}, {"widgettype": "VBox", "options": {"css": "cta", "width": "100%", "padding": "80px 40px", "spacing": "24px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "这些解决方案在实践中如何运作?", "css": "cta-title"}}, {"widgettype": "Text", "options": {"text": "获取针对您行业的AI解决方案。", "css": "cta-sub"}}, {"widgettype": "Button", "options": {"label": "联系我们 →", "css": "hero-btn-primary"}}]}, {"widgettype": "VBox", "options": {"css": "section", "width": "100%", "padding": "80px 40px", "spacing": "40px"}, "subwidgets": [{"widgettype": "HBox", "options": {"width": "100%", "justifyContent": "space-between", "alignItems": "center"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "企业动态", "css": "section-title"}}, {"widgettype": "Text", "options": {"text": "查看更多 →", "css": "view-more"}}]}, {"widgettype": "HBox", "options": {"width": "100%", "spacing": "24px"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "news-card", "spacing": "16px"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "权威认证!开元云科技完成三级等保备案", "css": "news-title"}}, {"widgettype": "Text", "options": {"text": "2024年12月", "css": "news-date"}}]}, {"widgettype": "VBox", "options": {"css": "news-card", "spacing": "16px"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "开元云科技中标北京智源人工智能研究院项目", "css": "news-title"}}, {"widgettype": "Text", "options": {"text": "2024年10月", "css": "news-date"}}]}]}]}], "id": "center"}, {"widgettype": "HBox", "options": {"css": "footer", "width": "100%", "padding": "60px 40px", "spacing": "80px", "justifyContent": "center"}, "subwidgets": [{"widgettype": "VBox", "options": {"spacing": "16px"}, "subwidgets": [{"widgettype": "Image", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/imgs/logo.png')}}", "css": "footer-logo"}}, {"widgettype": "Text", "options": {"text": "让AI无处不在,让AI触手可及", "css": "footer-tagline"}}]}, {"widgettype": "VBox", "options": {"spacing": "12px"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "产品与服务", "css": "footer-heading"}}, {"widgettype": "Text", "options": {"text": "OPC", "css": "footer-link"}}, {"widgettype": "Text", "options": {"text": "算力市场", "css": "footer-link"}}, {"widgettype": "Text", "options": {"text": "Token市场", "css": "footer-link"}}, {"widgettype": "Text", "options": {"text": "元境", "css": "footer-link"}}, {"widgettype": "Text", "options": {"text": "训练推理", "css": "footer-link"}}, {"widgettype": "Text", "options": {"text": "Agent Store", "css": "footer-link"}}, {"widgettype": "Text", "options": {"text": "供应广场", "css": "footer-link"}}]}, {"widgettype": "VBox", "options": {"spacing": "12px"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "联系我们", "css": "footer-heading"}}, {"widgettype": "Text", "options": {"text": "地址:北京市朝阳区东三环中路65号富力中心", "css": "footer-link"}}, {"widgettype": "Text", "options": {"text": "邮箱:Open-computing@kaiyuancloud.cn", "css": "footer-link"}}, {"widgettype": "Text", "options": {"text": "电话:400-6150805 010-65917875", "css": "footer-link"}}, {"widgettype": "HBox", "options": {"spacing": "24px"}, "subwidgets": [{"widgettype": "VBox", "options": {"spacing": "6px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Image", "options": {"url": "https://www.opencomputing.cn/static/img/img.936873a3.png", "css": "footer-qr"}}, {"widgettype": "Text", "options": {"text": "在线咨询", "css": "footer-qr-label"}}]}, {"widgettype": "VBox", "options": {"spacing": "6px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Image", "options": {"url": "https://www.opencomputing.cn/static/img/kefu.96ff99fe.jpg", "css": "footer-qr"}}, {"widgettype": "Text", "options": {"text": "关注公众号", "css": "footer-qr-label"}}]}]}]}]}, {"widgettype": "HBox", "options": {"css": "footer-icp-bar", "width": "100%", "padding": "16px 40px", "justifyContent": "center", "alignItems": "center"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "京ICP备2022001945号-2", "css": "footer-icp-link"}, "binds": [{"wid": "self", "event": "click", "actiontype": "script", "script": "window.open('https://beian.miit.gov.cn/','_blank');"}]}, {"widgettype": "Text", "options": {"text": "开元云(北京)科技有限公司", "css": "footer-icp-text"}}]}, {"widgettype": "VBox", "options": {"css": "float-chat", "spacing": "4px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Image", "options": {"url": "https://www.opencomputing.cn/static/img/ocai.9af463db.jpg", "css": "float-chat-avatar"}}, {"widgettype": "Text", "options": {"text": "在线咨询", "css": "float-chat-label"}}], "binds": [{"wid": "self", "event": "click", "actiontype": "script", "script": "var m=document.getElementById('cmodal');if(!m){m=document.createElement('div');m.id='cmodal';m.innerHTML='

在线咨询

请留下您的联系方式,我们的顾问将尽快与您联系

信息仅用于顾问联系

';m.style.cssText='position:fixed;top:0;left:0;width:100%;height:100%;z-index:9999';document.body.appendChild(m);}"}]}]} \ No newline at end of file diff --git a/wwwroot/tokentest.opencomputing.cn/main_content.ui b/wwwroot/tokentest.opencomputing.cn/main_content.ui new file mode 100644 index 00000000..b61727bf --- /dev/null +++ b/wwwroot/tokentest.opencomputing.cn/main_content.ui @@ -0,0 +1 @@ +{"widgettype": "VBox", "options": {"css": "main-content", "width": "100%", "spacing": 0}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "section", "width": "100%", "padding": "80px 40px 60px", "spacing": "40px"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "AI + 解决方案", "css": "section-title"}}, {"widgettype": "VBox", "options": {"css": "carousel-container"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "carousel-track"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs0", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "🛡️", "css": "card-icon"}}, {"widgettype": "Text", "options": {"text": "全面防护", "css": "card-title"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "全面防护", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "多层次AI安全防护体系,覆盖数据加密、访问控制、威胁检测与合规审计全链路。", "css": "card-text-white"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs1", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "📖", "css": "card-icon"}}, {"widgettype": "Text", "options": {"text": "阅读理解", "css": "card-title"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "阅读理解", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "深度理解非结构化文档,自动提取关键信息,支持合同、报告、论文等多场景。", "css": "card-text-white"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs2", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "🏭", "css": "card-icon"}}, {"widgettype": "Text", "options": {"text": "现场智能", "css": "card-title"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "现场智能", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "AI视觉+物联网融合,实时监测生产现场,异常预警、质量检测、安全管控一体化。", "css": "card-text-white"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs3", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "🤝", "css": "card-icon"}}, {"widgettype": "Text", "options": {"text": "协同智能", "css": "card-title"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "协同智能", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "多个AI智能体角色化自主协作,完成信息采集、分析、推理和结论生成全流程。", "css": "card-text-white"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs4", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "🌍", "css": "card-icon"}}, {"widgettype": "Text", "options": {"text": "空间智能", "css": "card-title"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "空间智能", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "集成GIS、卫星遥感与无人机数据,AI自动识别地物边界并分析空间关系。", "css": "card-text-white"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs5", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "🔮", "css": "card-icon"}}, {"widgettype": "Text", "options": {"text": "预测洞察", "css": "card-title"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "预测洞察", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "基于历史数据与实时指标,AI预测趋势、识别风险、优化决策,先人一步。", "css": "card-text-white"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs6", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "🔬", "css": "card-icon"}}, {"widgettype": "Text", "options": {"text": "微观洞察", "css": "card-title"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "微观洞察", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "AI显微镜图像分析,自动识别细胞、材料等微观结构,精度达到专业级水平。", "css": "card-text-white"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "carousel-card cs-card"}, "id": "cs7", "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "cs-card-front"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "💬", "css": "card-icon"}}, {"widgettype": "Text", "options": {"text": "即时问答", "css": "card-title"}}]}, {"widgettype": "VBox", "options": {"css": "cs-card-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "即时问答", "css": "card-title-white"}}, {"widgettype": "Text", "options": {"text": "基于企业私有知识库的AI问答引擎,自然语言查询,秒级精准响应业务问题。", "css": "card-text-white"}}]}]}]}]}]}]}, {"widgettype": "VBox", "options": {"css": "section section-alt", "width": "100%", "padding": "80px 40px", "spacing": "40px"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "应用案例", "css": "section-title"}}, {"widgettype": "HBox", "options": {"css": "case-cards", "width": "100%", "spacing": "24px", "justifyContent": "center"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip-front", "spacing": "0"}, "subwidgets": [{"widgettype": "Image", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/imgs/case-railway.png')}}", "css": "case-img"}}, {"widgettype": "Text", "options": {"text": "智慧工程", "css": "case-name"}}, {"widgettype": "Text", "options": {"text": "中国中铁 · 汇投标", "css": "case-client"}}, {"widgettype": "Text", "options": {"text": "构建覆盖文档分析到智能投标文件编制的全生命周期智能招标系统。", "css": "case-desc"}}]}, {"widgettype": "VBox", "options": {"css": "case-flip-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "智慧工程", "css": "case-back-title"}}, {"widgettype": "Text", "options": {"text": "为中国中铁打造汇投标和慧途大模型,建立联合创新中心和AI应用创新平台。全面覆盖投标全生命周期。", "css": "case-back-desc"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "case-flip"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip-front", "spacing": "0"}, "subwidgets": [{"widgettype": "Image", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/imgs/case-forestry.png')}}", "css": "case-img"}}, {"widgettype": "Text", "options": {"text": "智慧采伐", "css": "case-name"}}, {"widgettype": "Text", "options": {"text": "南宁市林业局", "css": "case-client"}}, {"widgettype": "Text", "options": {"text": "集成GIS、卫星遥感和无人机数据的智能森林采伐空间审核系统。", "css": "case-desc"}}]}, {"widgettype": "VBox", "options": {"css": "case-flip-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "智慧采伐", "css": "case-back-title"}}, {"widgettype": "Text", "options": {"text": "为南宁林业局开发智能森林采伐空间审核系统,采伐边界自动合规验证,一键生成审核报告。", "css": "case-back-desc"}}]}]}]}, {"widgettype": "VBox", "options": {"css": "case-flip"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip-inner"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "case-flip-front", "spacing": "0"}, "subwidgets": [{"widgettype": "Image", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/imgs/case-port.png')}}", "css": "case-img"}}, {"widgettype": "Text", "options": {"text": "数智化转型", "css": "case-name"}}, {"widgettype": "Text", "options": {"text": "北部湾港大数据", "css": "case-client"}}, {"widgettype": "Text", "options": {"text": "覆盖招标、投资决策、合同审查的全栈AI智能体解决方案。", "css": "case-desc"}}]}, {"widgettype": "VBox", "options": {"css": "case-flip-back"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "数智化转型", "css": "case-back-title"}}, {"widgettype": "Text", "options": {"text": "为北部湾港大数据打造全栈AI智能体解决方案,投标引擎秒级生成标书,合同审查效率提升60%+。", "css": "case-back-desc"}}]}]}]}]}]}, {"widgettype": "VBox", "options": {"css": "cta", "width": "100%", "padding": "80px 40px", "spacing": "24px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "这些解决方案在实践中如何运作?", "css": "cta-title"}}, {"widgettype": "Text", "options": {"text": "获取针对您行业的AI解决方案。", "css": "cta-sub"}}, {"widgettype": "Button", "options": {"label": "联系我们 →", "css": "hero-btn-primary"}}]}]} \ No newline at end of file diff --git a/wwwroot/tokentest.opencomputing.cn/opc/index_zh.ui b/wwwroot/tokentest.opencomputing.cn/opc/index_zh.ui new file mode 100644 index 00000000..2ebe74be --- /dev/null +++ b/wwwroot/tokentest.opencomputing.cn/opc/index_zh.ui @@ -0,0 +1 @@ +{"widgettype": "VBox", "options": {"css": "page", "width": "100%", "spacing": 0}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "prod-hero", "width": "100%", "padding": "120px 40px 80px", "alignItems": "center", "spacing": "20px"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "OPC 公共服务平台", "css": "prod-hero-title"}}, {"widgettype": "Text", "options": {"text": "开放式云计算公共服务平台,提供算力交易、模型市集、开发工具一站式服务,助力企业快速拥抱AI。", "css": "prod-hero-sub"}}]}, {"widgettype": "VBox", "options": {"css": "section", "width": "100%", "padding": "80px 40px", "spacing": "20px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "核心能力", "css": "section-title"}}, {"widgettype": "HBox", "options": {"width": "100%", "spacing": "24px", "justifyContent": "center"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "prod-card", "spacing": "20px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "🪙", "css": "prod-card-icon"}}, {"widgettype": "Text", "options": {"text": "Token市集", "css": "prod-card-title"}}, {"widgettype": "Text", "options": {"text": "汇聚全球优质大模型API,统一接入标准,按量计费灵活高效,让AI能力触手可及。", "css": "prod-card-desc"}}, {"widgettype": "Button", "options": {"label": "立即体验", "css": "prod-card-btn"}}]}, {"widgettype": "VBox", "options": {"css": "prod-card", "spacing": "20px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "🔧", "css": "prod-card-icon"}}, {"widgettype": "Text", "options": {"text": "创镜工坊", "css": "prod-card-title"}}, {"widgettype": "Text", "options": {"text": "AI应用快速构建平台,低代码拖拽式开发,海量模板即开即用,分钟级搭建智能体。", "css": "prod-card-desc"}}, {"widgettype": "Button", "options": {"label": "了解更多", "css": "prod-card-btn"}}]}, {"widgettype": "VBox", "options": {"css": "prod-card", "spacing": "20px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "☁️", "css": "prod-card-icon"}}, {"widgettype": "Text", "options": {"text": "云枢基座", "css": "prod-card-title"}}, {"widgettype": "Text", "options": {"text": "高性能GPU算力调度中心,支持模型训练与推理,弹性伸缩,极致性价比。", "css": "prod-card-desc"}}, {"widgettype": "Button", "options": {"label": "了解更多", "css": "prod-card-btn"}}]}]}]}]} \ No newline at end of file diff --git a/wwwroot/tokentest.opencomputing.cn/opc/landing.css b/wwwroot/tokentest.opencomputing.cn/opc/landing.css new file mode 100644 index 00000000..8d2a3ba6 --- /dev/null +++ b/wwwroot/tokentest.opencomputing.cn/opc/landing.css @@ -0,0 +1,19 @@ +.prod-hero{background:linear-gradient(180deg,#f0f7ff 0%,#fff 60%,#f5f8ff 100%)!important;min-height:360px;justify-content:center!important} +.prod-hero-title{font-size:48px!important;font-weight:800!important;color:#111827!important;text-align:center!important} +.prod-hero-sub{font-size:18px!important;color:#4b5563!important;text-align:center!important;max-width:700px;line-height:1.7!important} +.prod-card{background:#fff;border-radius:16px;padding:40px 32px!important;box-shadow:0 4px 24px rgba(0,0,0,0.06);width:340px!important;min-height:280px;transition:transform .2s,box-shadow .2s} +.prod-card:hover{transform:translateY(-6px);box-shadow:0 12px 40px rgba(0,0,0,0.1)} +.prod-card-icon{font-size:48px!important;text-align:center!important} +.prod-card-title{font-size:24px!important;font-weight:700!important;color:#111827!important;text-align:center!important} +.prod-card-desc{font-size:15px!important;color:#6b7280!important;line-height:1.7!important;text-align:center!important} +.prod-card-btn{background:#000!important;color:#fff!important;border:none!important;padding:12px 32px!important;border-radius:99px!important;font-size:15px!important;font-weight:600!important;cursor:pointer!important} +.prod-card-btn:hover{background:#1f2937!important} + +[data-theme="dark"] .prod-hero{background:linear-gradient(180deg,#0f172a 0%,#1e293b 60%,#0f172a 100%)!important} +[data-theme="dark"] .prod-hero-title{color:#f1f5f9!important} +[data-theme="dark"] .prod-hero-sub{color:#94a3b8!important} +[data-theme="dark"] .prod-card{background:#1e293b;box-shadow:0 4px 24px rgba(0,0,0,0.2)} +[data-theme="dark"] .prod-card:hover{box-shadow:0 12px 40px rgba(0,0,0,0.3)} +[data-theme="dark"] .prod-card-title{color:#f1f5f9!important} +[data-theme="dark"] .prod-card-desc{color:#94a3b8!important} +[data-theme="dark"] .prod-card-btn{background:#f1f5f9!important;color:#0f172a!important} diff --git a/wwwroot/tokentest.opencomputing.cn/supplychain/index_zh.ui b/wwwroot/tokentest.opencomputing.cn/supplychain/index_zh.ui new file mode 100644 index 00000000..2ce8e674 --- /dev/null +++ b/wwwroot/tokentest.opencomputing.cn/supplychain/index_zh.ui @@ -0,0 +1 @@ +{"widgettype": "VBox", "options": {"css": "page", "width": "100%", "spacing": 0}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "prod-hero", "width": "100%", "padding": "120px 40px 80px", "alignItems": "center", "spacing": "20px"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "供应广场", "css": "prod-hero-title"}}, {"widgettype": "Text", "options": {"text": "企业级AI能力交易市场,连接技术供需双方,一站式完成需求发布、方案匹配、合同签署与项目交付。", "css": "prod-hero-sub"}}]}, {"widgettype": "VBox", "options": {"css": "section", "width": "100%", "padding": "80px 40px", "spacing": "20px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "核心能力", "css": "section-title"}}, {"widgettype": "HBox", "options": {"width": "100%", "spacing": "24px", "justifyContent": "center"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "prod-card", "spacing": "20px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "📋", "css": "prod-card-icon"}}, {"widgettype": "Text", "options": {"text": "需求发布", "css": "prod-card-title"}}, {"widgettype": "Text", "options": {"text": "发布AI项目需求与技术规格,智能匹配优质服务商,快速获取方案报价。", "css": "prod-card-desc"}}, {"widgettype": "Button", "options": {"label": "发布需求", "css": "prod-card-btn"}}]}, {"widgettype": "VBox", "options": {"css": "prod-card", "spacing": "20px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "🏢", "css": "prod-card-icon"}}, {"widgettype": "Text", "options": {"text": "服务商入驻", "css": "prod-card-title"}}, {"widgettype": "Text", "options": {"text": "展示AI解决方案与成功案例,获取精准项目机会,拓展商业版图。", "css": "prod-card-desc"}}, {"widgettype": "Button", "options": {"label": "立即入驻", "css": "prod-card-btn"}}]}, {"widgettype": "VBox", "options": {"css": "prod-card", "spacing": "20px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "🤝", "css": "prod-card-icon"}}, {"widgettype": "Text", "options": {"text": "项目协作", "css": "prod-card-title"}}, {"widgettype": "Text", "options": {"text": "在线沟通、合同签署、进度追踪、验收交付全流程数字化管理。", "css": "prod-card-desc"}}, {"widgettype": "Button", "options": {"label": "了解更多", "css": "prod-card-btn"}}]}]}]}]} \ No newline at end of file diff --git a/wwwroot/tokentest.opencomputing.cn/supplychain/landing.css b/wwwroot/tokentest.opencomputing.cn/supplychain/landing.css new file mode 100644 index 00000000..8d2a3ba6 --- /dev/null +++ b/wwwroot/tokentest.opencomputing.cn/supplychain/landing.css @@ -0,0 +1,19 @@ +.prod-hero{background:linear-gradient(180deg,#f0f7ff 0%,#fff 60%,#f5f8ff 100%)!important;min-height:360px;justify-content:center!important} +.prod-hero-title{font-size:48px!important;font-weight:800!important;color:#111827!important;text-align:center!important} +.prod-hero-sub{font-size:18px!important;color:#4b5563!important;text-align:center!important;max-width:700px;line-height:1.7!important} +.prod-card{background:#fff;border-radius:16px;padding:40px 32px!important;box-shadow:0 4px 24px rgba(0,0,0,0.06);width:340px!important;min-height:280px;transition:transform .2s,box-shadow .2s} +.prod-card:hover{transform:translateY(-6px);box-shadow:0 12px 40px rgba(0,0,0,0.1)} +.prod-card-icon{font-size:48px!important;text-align:center!important} +.prod-card-title{font-size:24px!important;font-weight:700!important;color:#111827!important;text-align:center!important} +.prod-card-desc{font-size:15px!important;color:#6b7280!important;line-height:1.7!important;text-align:center!important} +.prod-card-btn{background:#000!important;color:#fff!important;border:none!important;padding:12px 32px!important;border-radius:99px!important;font-size:15px!important;font-weight:600!important;cursor:pointer!important} +.prod-card-btn:hover{background:#1f2937!important} + +[data-theme="dark"] .prod-hero{background:linear-gradient(180deg,#0f172a 0%,#1e293b 60%,#0f172a 100%)!important} +[data-theme="dark"] .prod-hero-title{color:#f1f5f9!important} +[data-theme="dark"] .prod-hero-sub{color:#94a3b8!important} +[data-theme="dark"] .prod-card{background:#1e293b;box-shadow:0 4px 24px rgba(0,0,0,0.2)} +[data-theme="dark"] .prod-card:hover{box-shadow:0 12px 40px rgba(0,0,0,0.3)} +[data-theme="dark"] .prod-card-title{color:#f1f5f9!important} +[data-theme="dark"] .prod-card-desc{color:#94a3b8!important} +[data-theme="dark"] .prod-card-btn{background:#f1f5f9!important;color:#0f172a!important} diff --git a/wwwroot/tokentest.opencomputing.cn/tenant.css b/wwwroot/tokentest.opencomputing.cn/tenant.css new file mode 100644 index 00000000..3efe64e0 --- /dev/null +++ b/wwwroot/tokentest.opencomputing.cn/tenant.css @@ -0,0 +1,151 @@ +/* === BASE === */ +.page{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif;background:#fff} +.header{background:rgba(255,255,255,0.92);backdrop-filter:blur(12px);position:sticky;top:0;z-index:100;height:72px;box-shadow:0 1px 3px rgba(0,0,0,0.04)} +.logo{height:38px!important;width:auto!important;object-fit:contain!important;cursor:pointer!important} +.nav-area{flex:1;display:flex;justify-content:center} +.nav-links{gap:32px} +.nav-link{cursor:pointer;font-size:17px;color:#111827!important;font-weight:500;white-space:nowrap} +.nav-link:hover{color:#1e6fff!important} +.nav-link.active{color:#1e6fff!important;font-weight:600} +.products-menu{position:relative} +.products-dropdown{display:none;position:absolute;top:100%;left:-16px;background:#fff;border-radius:12px;box-shadow:0 8px 40px rgba(0,0,0,0.12);padding:8px 0;min-width:160px;z-index:200;flex-direction:column} +.products-menu:hover .products-dropdown{display:flex} +.dropdown-item{cursor:pointer;font-size:16px;color:#111827!important;padding:10px 20px!important;white-space:nowrap} +.dropdown-item:hover{background:#f3f4f6!important} +.header-actions{gap:12px} +.theme-btn{background:transparent!important;border:1px solid #d1d5db!important;color:#111827!important;padding:6px 10px!important;border-radius:8px!important;font-size:16px!important;cursor:pointer!important;min-width:36px} +.theme-btn:hover{background:#f3f4f6!important} +.lang-btn{background:transparent!important;border:1px solid #d1d5db!important;color:#1e6fff!important;padding:6px 12px!important;border-radius:6px!important;font-size:15px!important;cursor:pointer!important;font-weight:500} +.lang-btn:hover{background:#eff6ff!important} +.login-pill{background:#000!important;color:#fff!important;border:none!important;padding:8px 22px!important;border-radius:99px!important;font-size:16px!important;font-weight:600!important;cursor:pointer!important} +.login-pill:hover{background:#1f2937!important} + +/* === HERO === */ +.hero{background:linear-gradient(180deg,#f0f7ff 0%,#fff 60%,#f5f8ff 100%)!important;min-height:520px;justify-content:center!important} +.hero-title{font-size:56px!important;font-weight:800!important;line-height:1.15!important;color:#111827!important;text-align:center!important;max-width:800px} +.hero-sub{font-size:22px!important;color:#4b5563!important;text-align:center!important} +.hero-btn-primary{background:#000!important;color:#fff!important;border:none!important;padding:14px 32px!important;border-radius:99px!important;font-size:16px!important;font-weight:600!important;cursor:pointer!important} +.hero-btn-primary:hover{background:#1f2937!important} +.hero-btn-outline{background:transparent!important;color:#111827!important;border:2px solid #d1d5db!important;padding:14px 32px!important;border-radius:99px!important;font-size:16px!important;font-weight:600!important;cursor:pointer!important} +.hero-btn-outline:hover{background:#f3f4f6!important} + +/* === SECTION === */ +.section{background:#fff!important} +.section-alt{background:#f8faff!important} +.section-title{font-size:32px!important;font-weight:700!important;color:#111827!important;text-align:left!important} + +/* === CAROUSEL widget sizing === */ +.carousel-widget{width:100%!important;overflow:visible!important} + +/* === CARD TEXT helpers === */ +.card-icon{font-size:44px!important;text-align:center!important} +.card-title{font-size:22px!important;font-weight:700!important;color:#111827!important;text-align:center!important} +.card-title-white{font-size:20px!important;font-weight:700!important;color:#fff!important;text-align:center!important} +.card-text-white{font-size:14px!important;color:rgba(255,255,255,0.9)!important;line-height:1.6!important;text-align:center!important} + +/* === CAROUSEL LAYOUT === */ +.carousel-container{position:relative;width:100%;height:460px;display:flex;align-items:center;justify-content:center;overflow:visible} +.carousel-track{position:relative!important;width:100%;height:100%;display:block!important} +.carousel-card{position:absolute!important;width:280px!important;height:360px!important;transition:all .5s cubic-bezier(.4,0,.2,1);cursor:pointer;transform-origin:center center;perspective:1000px} + +/* === CARD FLIP === */ +.cs-card-inner{position:relative!important;width:100%!important;height:100%!important;transition:transform .6s cubic-bezier(.4,0,.2,1);transform-style:preserve-3d} +.cs-card.flipped .cs-card-inner{transform:rotateY(180deg)} +.cs-card-front,.cs-card-back{position:absolute!important;width:100%!important;height:100%!important;backface-visibility:hidden;-webkit-backface-visibility:hidden;top:0;left:0;border-radius:16px;overflow:hidden} +.cs-card-back{transform:rotateY(180deg)} +.cs-card-front{background:#fff;box-shadow:0 18px 54px rgba(90,60,160,0.1),0 4px 16px rgba(90,60,160,0.05);display:flex;flex-direction:column;align-items:center;justify-content:center;padding:28px;gap:16px} +.cs-card-back{background:#3b82f6;box-shadow:0 18px 54px rgba(59,130,246,0.2);display:flex;flex-direction:column;align-items:center;justify-content:center;padding:24px;gap:16px} + +/* === CASE FLIP === */ +.case-cards{display:flex;justify-content:center;gap:24px;flex-wrap:wrap} +.case-flip{perspective:1000px;height:460px;cursor:pointer;width:350px!important;flex-shrink:0} +.case-flip-inner{position:relative!important;width:100%!important;height:100%!important;transition:transform .6s cubic-bezier(.4,0,.2,1);transform-style:preserve-3d} +.case-flip:hover .case-flip-inner{transform:rotateY(180deg)} +.case-flip-front,.case-flip-back{position:absolute!important;width:100%!important;height:100%!important;backface-visibility:hidden;-webkit-backface-visibility:hidden;top:0;left:0;border-radius:16px;overflow:hidden} +.case-flip-back{transform:rotateY(180deg)} +.case-flip-front{background:#fff;box-shadow:0 4px 24px rgba(0,0,0,0.06);display:flex;flex-direction:column} +.case-flip-back{background:#111827;box-shadow:0 4px 24px rgba(0,0,0,0.15);display:flex;flex-direction:column;align-items:center;justify-content:center;padding:32px;gap:16px} + +/* === CASE FLIP overrides === */ +.case-flip-widget{width:380px!important;height:460px!important} +.case-img{width:100%!important;height:220px!important;object-fit:cover!important} +.case-name{font-size:22px!important;font-weight:700!important;color:#111827!important;padding:16px 20px 0!important} +.case-client{font-size:15px!important;color:#3b82f6!important;font-weight:600!important;padding:4px 20px!important} +.case-desc{font-size:14px!important;color:#6b7280!important;line-height:1.6!important;padding:8px 20px 20px!important} +.case-back-title{font-size:26px!important;font-weight:700!important;color:#fff!important;text-align:center!important} +.case-back-desc{font-size:15px!important;color:rgba(255,255,255,0.85)!important;line-height:1.8!important;text-align:center!important} + +/* === CTA === */ +.cta{background:linear-gradient(135deg,#f0f7ff,#eff6ff)!important} +.cta-title{font-size:34px!important;font-weight:700!important;color:#111827!important;text-align:center!important} +.cta-sub{font-size:18px!important;color:#4b5563!important;text-align:center!important} + +/* === NEWS === */ +.view-more{cursor:pointer;font-size:16px;color:#1e6fff!important;font-weight:500} +.news-card{background:#fff;border-radius:12px;padding:28px!important;box-shadow:0 2px 12px rgba(0,0,0,0.04);flex:1} +.news-title{font-size:20px!important;font-weight:700!important;color:#111827!important;line-height:1.4!important} +.news-desc{font-size:15px!important;color:#6b7280!important;line-height:1.6!important} +.news-date{font-size:13px!important;color:#9ca3af!important} + +/* === FOOTER === */ +.footer{background:#111827!important;color:#fff} +.footer-logo{height:32px!important;width:auto!important;object-fit:contain!important} +.footer-tagline{font-size:14px!important;color:rgba(255,255,255,0.5)!important} +.footer-heading{font-size:16px!important;color:#fff!important;font-weight:600!important} +.footer-link{font-size:14px!important;color:rgba(255,255,255,0.6)!important;cursor:pointer} +.footer-link:hover{color:#fff!important} +.footer-copyright{font-size:12px!important;color:rgba(255,255,255,0.35)!important;margin-top:8px!important} +.footer-consult{cursor:pointer!important;color:#60a5fa!important} +.footer-consult:hover{color:#93c5fd!important} +.footer-qr{width:100px!important;height:100px!important;object-fit:contain!important} +.footer-qr-label{font-size:12px!important;color:rgba(255,255,255,0.5)!important} + +/* === ICP BAR === */ +.footer-icp-bar{background:#0a0a1a!important} +.footer-icp-link{font-size:12px!important;color:rgba(255,255,255,0.35)!important;cursor:pointer!important} +.footer-icp-link:hover{color:rgba(255,255,255,0.6)!important} +.footer-icp-text{font-size:12px!important;color:rgba(255,255,255,0.25)!important;margin-left:12px!important} +[data-theme="dark"] .footer-icp-bar{background:#000!important} + +/* === CONTACT MODAL === */ +.contact-overlay{position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.4)} +.contact-dialog{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);background:#fff;border-radius:16px;padding:32px;width:380px;max-width:90vw;box-shadow:0 20px 60px rgba(0,0,0,0.2);z-index:10000} + +/* === FLOATING CHAT === */ +.float-chat{position:fixed!important;bottom:32px;right:24px;z-index:999;cursor:pointer!important;align-items:center!important} +.float-chat-avatar{width:56px!important;height:56px!important;border-radius:50%!important;object-fit:cover!important;box-shadow:0 4px 16px rgba(0,0,0,0.15)} +.float-chat-label{font-size:11px!important;color:#6b7280!important;text-align:center!important} + +/* ===== DARK THEME ===== */ +[data-theme="dark"] .page{background:#0f172a} +[data-theme="dark"] .header{background:rgba(15,23,42,0.92)!important;box-shadow:0 1px 3px rgba(0,0,0,0.3)} +[data-theme="dark"] .nav-link{color:#94a3b8!important} +[data-theme="dark"] .nav-link:hover{color:#60a5fa!important} +[data-theme="dark"] .nav-link.active{color:#60a5fa!important} +[data-theme="dark"] .theme-btn{color:#94a3b8!important;border-color:#334155!important} +[data-theme="dark"] .lang-btn{color:#60a5fa!important;border-color:#334155!important} +[data-theme="dark"] .login-pill{background:#f1f5f9!important;color:#0f172a!important} +[data-theme="dark"] .hero{background:linear-gradient(180deg,#0f172a 0%,#1e293b 60%,#0f172a 100%)!important} +[data-theme="dark"] .hero-title{color:#f1f5f9!important} +[data-theme="dark"] .hero-sub{color:#94a3b8!important} +[data-theme="dark"] .hero-btn-primary{background:#f1f5f9!important;color:#0f172a!important} +[data-theme="dark"] .hero-btn-outline{color:#f1f5f9!important;border-color:#475569!important} +[data-theme="dark"] .section{background:#0f172a!important} +[data-theme="dark"] .section-alt{background:#1e293b!important} +[data-theme="dark"] .section-title{color:#f1f5f9!important} +[data-theme="dark"] .products-dropdown{background:#1e293b;box-shadow:0 8px 40px rgba(0,0,0,0.4)} +[data-theme="dark"] .dropdown-item{color:#e2e8f0!important} +[data-theme="dark"] .dropdown-item:hover{background:#334155!important} +[data-theme="dark"] .card-title{color:#f1f5f9!important} +[data-theme="dark"] .case-name{color:#f1f5f9!important} +[data-theme="dark"] .case-desc{color:#94a3b8!important} +[data-theme="dark"] .cta{background:#1e293b!important} +[data-theme="dark"] .cta-title{color:#f1f5f9!important} +[data-theme="dark"] .cta-sub{color:#94a3b8!important} +[data-theme="dark"] .news-card{background:#1e293b;box-shadow:0 2px 12px rgba(0,0,0,0.2)} +[data-theme="dark"] .news-title{color:#f1f5f9!important} +[data-theme="dark"] .news-desc{color:#94a3b8!important} +[data-theme="dark"] .footer{background:#020617!important} +[data-theme="dark"] .cs-card-front{background:#1e293b;box-shadow:0 18px 54px rgba(0,0,0,0.3)} +[data-theme="dark"] .cs-card-back{background:#3b82f6} +[data-theme="dark"] .case-flip-front{background:#1e293b;box-shadow:0 4px 24px rgba(0,0,0,0.2)} diff --git a/wwwroot/tokentest.opencomputing.cn/theme.js b/wwwroot/tokentest.opencomputing.cn/theme.js new file mode 100644 index 00000000..5cd1b0b3 --- /dev/null +++ b/wwwroot/tokentest.opencomputing.cn/theme.js @@ -0,0 +1,14 @@ +(function(){ + var d=document.documentElement,stored=localStorage.getItem('hermes-theme'); + var params=new URLSearchParams(location.search); + var force=params.get('theme')||stored||'light'; + function apply(){if(d.getAttribute('data-theme')!==force)d.setAttribute('data-theme',force);} + apply(); + new MutationObserver(function(m){m.forEach(function(x){if(x.attributeName==='data-theme')apply();})}).observe(d,{attributes:true}); + setInterval(apply,300); + window._toggleTheme=function(){ + force=force==='dark'?'light':'dark'; + localStorage.setItem('hermes-theme',force); + apply(); + }; +})(); diff --git a/wwwroot/tokentest.opencomputing.cn/top_en.ui b/wwwroot/tokentest.opencomputing.cn/top_en.ui new file mode 100644 index 00000000..23c08ae3 --- /dev/null +++ b/wwwroot/tokentest.opencomputing.cn/top_en.ui @@ -0,0 +1 @@ +{"widgettype": "VBox", "options": {"css": "top", "width": "100%", "spacing": 0}, "subwidgets": [{"widgettype": "HBox", "options": {"css": "header", "width": "100%", "padding": "0 40px", "alignItems": "center", "justifyContent": "space-between"}, "subwidgets": [{"widgettype": "Image", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/imgs/logo.png')}}", "css": "logo"}, "id": "logo", "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/center_home_en.ui')}}"}}]}, {"widgettype": "HBox", "options": {"css": "nav-area"}, "subwidgets": [{"widgettype": "HBox", "options": {"css": "nav-links", "spacing": "32px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Home", "css": "nav-link active"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/center_home_en.ui')}}"}}]}, {"widgettype": "VBox", "options": {"css": "products-menu"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Products ▾", "css": "nav-link"}}, {"widgettype": "VBox", "options": {"css": "products-dropdown"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "OPC", "css": "dropdown-item"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/opc/index_en.ui')}}"}}]}, {"widgettype": "Text", "options": {"text": "Compute Market", "css": "dropdown-item"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/compute/index_en.ui')}}"}}]}, {"widgettype": "Text", "options": {"text": "Token Market", "css": "dropdown-item"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/llmage/model_plaza.ui')}}"}}]}, {"widgettype": "Text", "options": {"text": "Yuanjing", "css": "dropdown-item"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/yunjing/index_en.ui')}}"}}]}, {"widgettype": "Text", "options": {"text": "Train & Infer", "css": "dropdown-item"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/train/index_en.ui')}}"}}]}, {"widgettype": "Text", "options": {"text": "Agent Store", "css": "dropdown-item"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/agent/index_en.ui')}}"}}]}, {"widgettype": "Text", "options": {"text": "Supply Square", "css": "dropdown-item"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/supplychain/index_en.ui')}}"}}]}]}]}, {"widgettype": "Text", "options": {"text": "Use Cases", "css": "nav-link"}}, {"widgettype": "Text", "options": {"text": "News", "css": "nav-link"}}]}]}, {"widgettype": "HBox", "options": {"css": "header-actions", "spacing": "12px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Button", "options": {"label": "☀", "css": "theme-btn"}, "id": "themeToggle", "binds": [{"wid": "self", "event": "click", "actiontype": "script", "script": "if(window._toggleTheme)window._toggleTheme();var t=document.documentElement.getAttribute('data-theme');var b=document.getElementById('themeToggle');if(b){var s=b.querySelector('div');if(s)s.textContent=t==='dark'?'☾':'☀';}"}]}, {"widgettype": "Button", "options": {"label": "EN/中", "css": "lang-btn"}, "binds": [{"wid": "self", "event": "click", "actiontype": "script", "script": "localStorage.setItem('hermes-lang','zh');location.href='/tokentest.opencomputing.cn/index_zh.ui';"}]}, {"widgettype": "Button", "options": {"label": "Login", "css": "login-pill"}, "binds": [{"wid": "self", "event": "click", "actiontype": "script", "script": "window.location.href='{{entire_url(\"/rbac/user/login.ui\")}}';"}]}]}]}]} \ No newline at end of file diff --git a/wwwroot/tokentest.opencomputing.cn/top_jp.ui b/wwwroot/tokentest.opencomputing.cn/top_jp.ui new file mode 100644 index 00000000..23c08ae3 --- /dev/null +++ b/wwwroot/tokentest.opencomputing.cn/top_jp.ui @@ -0,0 +1 @@ +{"widgettype": "VBox", "options": {"css": "top", "width": "100%", "spacing": 0}, "subwidgets": [{"widgettype": "HBox", "options": {"css": "header", "width": "100%", "padding": "0 40px", "alignItems": "center", "justifyContent": "space-between"}, "subwidgets": [{"widgettype": "Image", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/imgs/logo.png')}}", "css": "logo"}, "id": "logo", "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/center_home_en.ui')}}"}}]}, {"widgettype": "HBox", "options": {"css": "nav-area"}, "subwidgets": [{"widgettype": "HBox", "options": {"css": "nav-links", "spacing": "32px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Home", "css": "nav-link active"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/center_home_en.ui')}}"}}]}, {"widgettype": "VBox", "options": {"css": "products-menu"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Products ▾", "css": "nav-link"}}, {"widgettype": "VBox", "options": {"css": "products-dropdown"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "OPC", "css": "dropdown-item"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/opc/index_en.ui')}}"}}]}, {"widgettype": "Text", "options": {"text": "Compute Market", "css": "dropdown-item"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/compute/index_en.ui')}}"}}]}, {"widgettype": "Text", "options": {"text": "Token Market", "css": "dropdown-item"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/llmage/model_plaza.ui')}}"}}]}, {"widgettype": "Text", "options": {"text": "Yuanjing", "css": "dropdown-item"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/yunjing/index_en.ui')}}"}}]}, {"widgettype": "Text", "options": {"text": "Train & Infer", "css": "dropdown-item"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/train/index_en.ui')}}"}}]}, {"widgettype": "Text", "options": {"text": "Agent Store", "css": "dropdown-item"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/agent/index_en.ui')}}"}}]}, {"widgettype": "Text", "options": {"text": "Supply Square", "css": "dropdown-item"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/supplychain/index_en.ui')}}"}}]}]}]}, {"widgettype": "Text", "options": {"text": "Use Cases", "css": "nav-link"}}, {"widgettype": "Text", "options": {"text": "News", "css": "nav-link"}}]}]}, {"widgettype": "HBox", "options": {"css": "header-actions", "spacing": "12px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Button", "options": {"label": "☀", "css": "theme-btn"}, "id": "themeToggle", "binds": [{"wid": "self", "event": "click", "actiontype": "script", "script": "if(window._toggleTheme)window._toggleTheme();var t=document.documentElement.getAttribute('data-theme');var b=document.getElementById('themeToggle');if(b){var s=b.querySelector('div');if(s)s.textContent=t==='dark'?'☾':'☀';}"}]}, {"widgettype": "Button", "options": {"label": "EN/中", "css": "lang-btn"}, "binds": [{"wid": "self", "event": "click", "actiontype": "script", "script": "localStorage.setItem('hermes-lang','zh');location.href='/tokentest.opencomputing.cn/index_zh.ui';"}]}, {"widgettype": "Button", "options": {"label": "Login", "css": "login-pill"}, "binds": [{"wid": "self", "event": "click", "actiontype": "script", "script": "window.location.href='{{entire_url(\"/rbac/user/login.ui\")}}';"}]}]}]}]} \ No newline at end of file diff --git a/wwwroot/tokentest.opencomputing.cn/top_ko.ui b/wwwroot/tokentest.opencomputing.cn/top_ko.ui new file mode 100644 index 00000000..23c08ae3 --- /dev/null +++ b/wwwroot/tokentest.opencomputing.cn/top_ko.ui @@ -0,0 +1 @@ +{"widgettype": "VBox", "options": {"css": "top", "width": "100%", "spacing": 0}, "subwidgets": [{"widgettype": "HBox", "options": {"css": "header", "width": "100%", "padding": "0 40px", "alignItems": "center", "justifyContent": "space-between"}, "subwidgets": [{"widgettype": "Image", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/imgs/logo.png')}}", "css": "logo"}, "id": "logo", "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/center_home_en.ui')}}"}}]}, {"widgettype": "HBox", "options": {"css": "nav-area"}, "subwidgets": [{"widgettype": "HBox", "options": {"css": "nav-links", "spacing": "32px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Home", "css": "nav-link active"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/center_home_en.ui')}}"}}]}, {"widgettype": "VBox", "options": {"css": "products-menu"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "Products ▾", "css": "nav-link"}}, {"widgettype": "VBox", "options": {"css": "products-dropdown"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "OPC", "css": "dropdown-item"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/opc/index_en.ui')}}"}}]}, {"widgettype": "Text", "options": {"text": "Compute Market", "css": "dropdown-item"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/compute/index_en.ui')}}"}}]}, {"widgettype": "Text", "options": {"text": "Token Market", "css": "dropdown-item"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/llmage/model_plaza.ui')}}"}}]}, {"widgettype": "Text", "options": {"text": "Yuanjing", "css": "dropdown-item"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/yunjing/index_en.ui')}}"}}]}, {"widgettype": "Text", "options": {"text": "Train & Infer", "css": "dropdown-item"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/train/index_en.ui')}}"}}]}, {"widgettype": "Text", "options": {"text": "Agent Store", "css": "dropdown-item"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/agent/index_en.ui')}}"}}]}, {"widgettype": "Text", "options": {"text": "Supply Square", "css": "dropdown-item"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/supplychain/index_en.ui')}}"}}]}]}]}, {"widgettype": "Text", "options": {"text": "Use Cases", "css": "nav-link"}}, {"widgettype": "Text", "options": {"text": "News", "css": "nav-link"}}]}]}, {"widgettype": "HBox", "options": {"css": "header-actions", "spacing": "12px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Button", "options": {"label": "☀", "css": "theme-btn"}, "id": "themeToggle", "binds": [{"wid": "self", "event": "click", "actiontype": "script", "script": "if(window._toggleTheme)window._toggleTheme();var t=document.documentElement.getAttribute('data-theme');var b=document.getElementById('themeToggle');if(b){var s=b.querySelector('div');if(s)s.textContent=t==='dark'?'☾':'☀';}"}]}, {"widgettype": "Button", "options": {"label": "EN/中", "css": "lang-btn"}, "binds": [{"wid": "self", "event": "click", "actiontype": "script", "script": "localStorage.setItem('hermes-lang','zh');location.href='/tokentest.opencomputing.cn/index_zh.ui';"}]}, {"widgettype": "Button", "options": {"label": "Login", "css": "login-pill"}, "binds": [{"wid": "self", "event": "click", "actiontype": "script", "script": "window.location.href='{{entire_url(\"/rbac/user/login.ui\")}}';"}]}]}]}]} \ No newline at end of file diff --git a/wwwroot/tokentest.opencomputing.cn/top_zh.ui b/wwwroot/tokentest.opencomputing.cn/top_zh.ui new file mode 100644 index 00000000..2917afd4 --- /dev/null +++ b/wwwroot/tokentest.opencomputing.cn/top_zh.ui @@ -0,0 +1 @@ +{"widgettype": "VBox", "options": {"css": "top", "width": "100%", "spacing": 0}, "subwidgets": [{"widgettype": "HBox", "options": {"css": "header", "width": "100%", "padding": "0 40px", "alignItems": "center", "justifyContent": "space-between"}, "subwidgets": [{"widgettype": "Image", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/imgs/logo.png')}}", "css": "logo"}, "id": "logo", "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/center_home_zh.ui')}}"}}]}, {"widgettype": "HBox", "options": {"css": "nav-area"}, "subwidgets": [{"widgettype": "HBox", "options": {"css": "nav-links", "spacing": "32px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "首页", "css": "nav-link active"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/center_home_zh.ui')}}"}}]}, {"widgettype": "VBox", "options": {"css": "products-menu"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "产品 ▾", "css": "nav-link"}}, {"widgettype": "VBox", "options": {"css": "products-dropdown"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "OPC", "css": "dropdown-item"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/opc/index_zh.ui')}}"}}]}, {"widgettype": "Text", "options": {"text": "算力市场", "css": "dropdown-item"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/compute/index_zh.ui')}}"}}]}, {"widgettype": "Text", "options": {"text": "Token市场", "css": "dropdown-item"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/llmage/model_plaza.ui')}}"}}]}, {"widgettype": "Text", "options": {"text": "元境", "css": "dropdown-item"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/yunjing/index_zh.ui')}}"}}]}, {"widgettype": "Text", "options": {"text": "训练推理", "css": "dropdown-item"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/train/index_zh.ui')}}"}}]}, {"widgettype": "Text", "options": {"text": "Agent Store", "css": "dropdown-item"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/agent/index_zh.ui')}}"}}]}, {"widgettype": "Text", "options": {"text": "供应广场", "css": "dropdown-item"}, "binds": [{"wid": "self", "event": "click", "actiontype": "urlwidget", "target": "root.center", "options": {"url": "{{entire_url('/tokentest.opencomputing.cn/supplychain/index_zh.ui')}}"}}]}]}]}, {"widgettype": "Text", "options": {"text": "案例", "css": "nav-link"}}, {"widgettype": "Text", "options": {"text": "动态", "css": "nav-link"}}]}]}, {"widgettype": "HBox", "options": {"css": "header-actions", "spacing": "12px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Button", "options": {"label": "☀", "css": "theme-btn"}, "id": "themeToggle", "binds": [{"wid": "self", "event": "click", "actiontype": "script", "script": "if(window._toggleTheme)window._toggleTheme();var t=document.documentElement.getAttribute('data-theme');var b=document.getElementById('themeToggle');if(b){var s=b.querySelector('div');if(s)s.textContent=t==='dark'?'☾':'☀';}"}]}, {"widgettype": "Button", "options": {"label": "中/EN", "css": "lang-btn"}, "binds": [{"wid": "self", "event": "click", "actiontype": "script", "script": "localStorage.setItem('hermes-lang','en');location.href='/tokentest.opencomputing.cn/index_en.ui';"}]}, {"widgettype": "Button", "options": {"label": "登录", "css": "login-pill"}, "binds": [{"wid": "self", "event": "click", "actiontype": "script", "script": "window.location.href='{{entire_url(\"/rbac/user/login.ui\")}}';"}]}]}]}]} \ No newline at end of file diff --git a/wwwroot/tokentest.opencomputing.cn/train/index_zh.ui b/wwwroot/tokentest.opencomputing.cn/train/index_zh.ui new file mode 100644 index 00000000..a12c09ad --- /dev/null +++ b/wwwroot/tokentest.opencomputing.cn/train/index_zh.ui @@ -0,0 +1 @@ +{"widgettype": "VBox", "options": {"css": "page", "width": "100%", "spacing": 0}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "prod-hero", "width": "100%", "padding": "120px 40px 80px", "alignItems": "center", "spacing": "20px"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "训练推理", "css": "prod-hero-title"}}, {"widgettype": "Text", "options": {"text": "一站式模型训练与推理平台,支持PyTorch/TensorFlow等主流框架,分布式训练加速,自动调参优化。", "css": "prod-hero-sub"}}]}, {"widgettype": "VBox", "options": {"css": "section", "width": "100%", "padding": "80px 40px", "spacing": "20px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "核心能力", "css": "section-title"}}, {"widgettype": "HBox", "options": {"width": "100%", "spacing": "24px", "justifyContent": "center"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "prod-card", "spacing": "20px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "🧠", "css": "prod-card-icon"}}, {"widgettype": "Text", "options": {"text": "模型训练", "css": "prod-card-title"}}, {"widgettype": "Text", "options": {"text": "支持主流深度学习框架,分布式训练引擎加速迭代,内置AutoML自动调参。", "css": "prod-card-desc"}}, {"widgettype": "Button", "options": {"label": "开始训练", "css": "prod-card-btn"}}]}, {"widgettype": "VBox", "options": {"css": "prod-card", "spacing": "20px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "🚀", "css": "prod-card-icon"}}, {"widgettype": "Text", "options": {"text": "模型推理", "css": "prod-card-title"}}, {"widgettype": "Text", "options": {"text": "高性能在线推理服务,支持实时与批量两种模式,毫秒级响应延迟。", "css": "prod-card-desc"}}, {"widgettype": "Button", "options": {"label": "部署模型", "css": "prod-card-btn"}}]}, {"widgettype": "VBox", "options": {"css": "prod-card", "spacing": "20px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "📈", "css": "prod-card-icon"}}, {"widgettype": "Text", "options": {"text": "实验管理", "css": "prod-card-title"}}, {"widgettype": "Text", "options": {"text": "训练指标实时可视化,实验对比分析,模型版本管理与一键回滚。", "css": "prod-card-desc"}}, {"widgettype": "Button", "options": {"label": "了解更多", "css": "prod-card-btn"}}]}]}]}]} \ No newline at end of file diff --git a/wwwroot/tokentest.opencomputing.cn/train/landing.css b/wwwroot/tokentest.opencomputing.cn/train/landing.css new file mode 100644 index 00000000..8d2a3ba6 --- /dev/null +++ b/wwwroot/tokentest.opencomputing.cn/train/landing.css @@ -0,0 +1,19 @@ +.prod-hero{background:linear-gradient(180deg,#f0f7ff 0%,#fff 60%,#f5f8ff 100%)!important;min-height:360px;justify-content:center!important} +.prod-hero-title{font-size:48px!important;font-weight:800!important;color:#111827!important;text-align:center!important} +.prod-hero-sub{font-size:18px!important;color:#4b5563!important;text-align:center!important;max-width:700px;line-height:1.7!important} +.prod-card{background:#fff;border-radius:16px;padding:40px 32px!important;box-shadow:0 4px 24px rgba(0,0,0,0.06);width:340px!important;min-height:280px;transition:transform .2s,box-shadow .2s} +.prod-card:hover{transform:translateY(-6px);box-shadow:0 12px 40px rgba(0,0,0,0.1)} +.prod-card-icon{font-size:48px!important;text-align:center!important} +.prod-card-title{font-size:24px!important;font-weight:700!important;color:#111827!important;text-align:center!important} +.prod-card-desc{font-size:15px!important;color:#6b7280!important;line-height:1.7!important;text-align:center!important} +.prod-card-btn{background:#000!important;color:#fff!important;border:none!important;padding:12px 32px!important;border-radius:99px!important;font-size:15px!important;font-weight:600!important;cursor:pointer!important} +.prod-card-btn:hover{background:#1f2937!important} + +[data-theme="dark"] .prod-hero{background:linear-gradient(180deg,#0f172a 0%,#1e293b 60%,#0f172a 100%)!important} +[data-theme="dark"] .prod-hero-title{color:#f1f5f9!important} +[data-theme="dark"] .prod-hero-sub{color:#94a3b8!important} +[data-theme="dark"] .prod-card{background:#1e293b;box-shadow:0 4px 24px rgba(0,0,0,0.2)} +[data-theme="dark"] .prod-card:hover{box-shadow:0 12px 40px rgba(0,0,0,0.3)} +[data-theme="dark"] .prod-card-title{color:#f1f5f9!important} +[data-theme="dark"] .prod-card-desc{color:#94a3b8!important} +[data-theme="dark"] .prod-card-btn{background:#f1f5f9!important;color:#0f172a!important} diff --git a/wwwroot/tokentest.opencomputing.cn/yunjing/index_zh.ui b/wwwroot/tokentest.opencomputing.cn/yunjing/index_zh.ui new file mode 100644 index 00000000..ee5c5720 --- /dev/null +++ b/wwwroot/tokentest.opencomputing.cn/yunjing/index_zh.ui @@ -0,0 +1 @@ +{"widgettype": "VBox", "options": {"css": "page", "width": "100%", "spacing": 0}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "prod-hero", "width": "100%", "padding": "120px 40px 80px", "alignItems": "center", "spacing": "20px"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "元境", "css": "prod-hero-title"}}, {"widgettype": "Text", "options": {"text": "下一代AI原生应用开发与运行平台,提供从模型训练到应用交付的全链路支持,让AI应用开发如搭积木般简单。", "css": "prod-hero-sub"}}]}, {"widgettype": "VBox", "options": {"css": "section", "width": "100%", "padding": "80px 40px", "spacing": "20px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "核心能力", "css": "section-title"}}, {"widgettype": "HBox", "options": {"width": "100%", "spacing": "24px", "justifyContent": "center"}, "subwidgets": [{"widgettype": "VBox", "options": {"css": "prod-card", "spacing": "20px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "🌐", "css": "prod-card-icon"}}, {"widgettype": "Text", "options": {"text": "智能应用", "css": "prod-card-title"}}, {"widgettype": "Text", "options": {"text": "可视化拖拽搭建AI原生应用,丰富组件库与行业模板,零代码快速交付。", "css": "prod-card-desc"}}, {"widgettype": "Button", "options": {"label": "开始创建", "css": "prod-card-btn"}}]}, {"widgettype": "VBox", "options": {"css": "prod-card", "spacing": "20px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "📊", "css": "prod-card-icon"}}, {"widgettype": "Text", "options": {"text": "数据面板", "css": "prod-card-title"}}, {"widgettype": "Text", "options": {"text": "实时监控应用运行状态、调用量、延迟、成本等关键指标,一目了然。", "css": "prod-card-desc"}}, {"widgettype": "Button", "options": {"label": "查看面板", "css": "prod-card-btn"}}]}, {"widgettype": "VBox", "options": {"css": "prod-card", "spacing": "20px", "alignItems": "center"}, "subwidgets": [{"widgettype": "Text", "options": {"text": "🔗", "css": "prod-card-icon"}}, {"widgettype": "Text", "options": {"text": "服务编排", "css": "prod-card-title"}}, {"widgettype": "Text", "options": {"text": "多模型协同编排引擎,构建复杂AI工作流,支持条件分支与循环控制。", "css": "prod-card-desc"}}, {"widgettype": "Button", "options": {"label": "了解更多", "css": "prod-card-btn"}}]}]}]}]} \ No newline at end of file diff --git a/wwwroot/tokentest.opencomputing.cn/yunjing/landing.css b/wwwroot/tokentest.opencomputing.cn/yunjing/landing.css new file mode 100644 index 00000000..8d2a3ba6 --- /dev/null +++ b/wwwroot/tokentest.opencomputing.cn/yunjing/landing.css @@ -0,0 +1,19 @@ +.prod-hero{background:linear-gradient(180deg,#f0f7ff 0%,#fff 60%,#f5f8ff 100%)!important;min-height:360px;justify-content:center!important} +.prod-hero-title{font-size:48px!important;font-weight:800!important;color:#111827!important;text-align:center!important} +.prod-hero-sub{font-size:18px!important;color:#4b5563!important;text-align:center!important;max-width:700px;line-height:1.7!important} +.prod-card{background:#fff;border-radius:16px;padding:40px 32px!important;box-shadow:0 4px 24px rgba(0,0,0,0.06);width:340px!important;min-height:280px;transition:transform .2s,box-shadow .2s} +.prod-card:hover{transform:translateY(-6px);box-shadow:0 12px 40px rgba(0,0,0,0.1)} +.prod-card-icon{font-size:48px!important;text-align:center!important} +.prod-card-title{font-size:24px!important;font-weight:700!important;color:#111827!important;text-align:center!important} +.prod-card-desc{font-size:15px!important;color:#6b7280!important;line-height:1.7!important;text-align:center!important} +.prod-card-btn{background:#000!important;color:#fff!important;border:none!important;padding:12px 32px!important;border-radius:99px!important;font-size:15px!important;font-weight:600!important;cursor:pointer!important} +.prod-card-btn:hover{background:#1f2937!important} + +[data-theme="dark"] .prod-hero{background:linear-gradient(180deg,#0f172a 0%,#1e293b 60%,#0f172a 100%)!important} +[data-theme="dark"] .prod-hero-title{color:#f1f5f9!important} +[data-theme="dark"] .prod-hero-sub{color:#94a3b8!important} +[data-theme="dark"] .prod-card{background:#1e293b;box-shadow:0 4px 24px rgba(0,0,0,0.2)} +[data-theme="dark"] .prod-card:hover{box-shadow:0 12px 40px rgba(0,0,0,0.3)} +[data-theme="dark"] .prod-card-title{color:#f1f5f9!important} +[data-theme="dark"] .prod-card-desc{color:#94a3b8!important} +[data-theme="dark"] .prod-card-btn{background:#f1f5f9!important;color:#0f172a!important} diff --git a/wwwroot/user/userapikey/index.ui b/wwwroot/user/userapikey/index.ui index fa784c84..aa1dd1b3 100644 --- a/wwwroot/user/userapikey/index.ui +++ b/wwwroot/user/userapikey/index.ui @@ -1,4 +1,10 @@ - +{ + "widgettype": "VBox", + "options": { + "cheight": 40, + "width": "100%" + }, + "subwidgets": [ { "widgettype":"Tabular", "options":{ @@ -123,4 +129,6 @@ "cache_limit":5 } +} + ] } diff --git a/wwwroot/user_panel.ui b/wwwroot/user_panel.ui index 623dd0a7..0923273d 100644 --- a/wwwroot/user_panel.ui +++ b/wwwroot/user_panel.ui @@ -1,6 +1,8 @@ { "id":"user_panel", + "widgettype":"VBox", + "options":{ "width":"100px" }, diff --git a/xlsx2json_models.py b/xlsx2json_models.py new file mode 100644 index 00000000..a15ece8d --- /dev/null +++ b/xlsx2json_models.py @@ -0,0 +1,177 @@ +#!/usr/bin/env python3 +""" +将 Sage 相关模块 models/ 目录下的 .xlsx 文件转换为 .json 数据表定义文件。 + +用法(在 Sage 虚拟环境中运行): + python ~/repos/sage/xlsx2json_models.py # 转换所有模块 + python ~/repos/sage/xlsx2json_models.py llmage # 只转换 llmage + python ~/repos/sage/xlsx2json_models.py --dry-run # 预览 +""" +import sys +import os +import json +import argparse + +# Sage 虚拟环境路径 +sage_root = os.path.expanduser('~/repos/sage') +sys.path.insert(0, sage_root) +sys.path.insert(0, os.path.join(sage_root, 'py3/lib/python3.10/site-packages')) + +from appPublic.folderUtils import listFile +from xls2ddl.xlsxData import xlsxFactory, CRUDData + +# Sage 相关模块列表 +SAGE_MODULES = [ + 'msp', 'cpcc', 'unipay', 'filemgr', 'dapi', 'uapi', + 'rag', 'charge', 'pricing', 'discount', 'hermes-web-cli', +] + + +def xlsx_to_json_dict(xlsx_path): + """将 xlsx 文件读取并转换为 json 格式的 dict。""" + d = xlsxFactory(xlsx_path) + if d is None: + return None + data = d.get_data() + + # 只保留目标字段 + result = {} + + # summary: 确保 primary 是 list + if 'summary' in data: + result['summary'] = [] + for s in data['summary']: + entry = {'name': s.get('name'), 'title': s.get('title')} + primary = s.get('primary', '') + if isinstance(primary, list): + entry['primary'] = primary + elif primary: + entry['primary'] = [p.strip() for p in str(primary).split(',')] + else: + entry['primary'] = [] + if s.get('catelog'): + entry['catelog'] = s['catelog'] + result['summary'].append(entry) + + # fields: 清理 None 值 + if 'fields' in data: + result['fields'] = [] + for f in data['fields']: + entry = {'name': f.get('name'), 'title': f.get('title'), 'type': f.get('type')} + if f.get('length') is not None: + entry['length'] = f['length'] + if f.get('nullable') is not None: + entry['nullable'] = f['nullable'] + if f.get('default') is not None: + entry['default'] = f['default'] + result['fields'].append(entry) + + # indexes: 从 validation 中的 idx 操作转换,或直接用 indexes sheet + if 'indexes' in data and data['indexes']: + result['indexes'] = data['indexes'] + elif 'validation' in data: + indexes = [] + for v in data['validation']: + if v.get('oper') == 'idx': + idx = {'name': v.get('name'), 'idxtype': 'index'} + val = v.get('value', '') + parts = val.split(':') + if len(parts) >= 2: + idx['idxtype'] = parts[0] + idx['idxfields'] = [f.strip() for f in parts[1].split(',')] + indexes.append(idx) + if indexes: + result['indexes'] = indexes + + # codes + if 'codes' in data and data['codes']: + result['codes'] = data['codes'] + + return result + + +def convert_module(module_name, dry_run=False): + """转换单个模块的 models 目录。""" + module_dir = os.path.expanduser(f'~/repos/{module_name}') + models_dir = os.path.join(module_dir, 'models') + + if not os.path.isdir(models_dir): + print(f" [SKIP] {module_name}: models/ directory not found") + return 0, 0 + + xlsx_files = [f for f in listFile(models_dir) if f.endswith('.xlsx')] + if not xlsx_files: + print(f" [SKIP] {module_name}: no .xlsx files") + return 0, 0 + + converted = 0 + skipped = 0 + + for xlsx_path in xlsx_files: + table_name = os.path.splitext(os.path.basename(xlsx_path))[0] + json_path = os.path.join(models_dir, f'{table_name}.json') + + # 跳过已经是 json 的文件 + if os.path.exists(json_path): + print(f" [EXIST] {table_name}.json already exists") + skipped += 1 + continue + + try: + result = xlsx_to_json_dict(xlsx_path) + if result is None: + print(f" [FAIL] {table_name}: could not read xlsx") + skipped += 1 + continue + + if dry_run: + print(f" [DRY] Would create {table_name}.json ({len(result.get('fields', []))} fields)") + converted += 1 + continue + + with open(json_path, 'w', encoding='utf-8') as f: + json.dump(result, f, ensure_ascii=False, indent=4) + + print(f" [OK] {table_name}.json ({len(result.get('fields', []))} fields)") + converted += 1 + + except Exception as e: + print(f" [FAIL] {table_name}: {e}") + skipped += 1 + + return converted, skipped + + +def main(): + parser = argparse.ArgumentParser(description='Convert models/*.xlsx to models/*.json') + parser.add_argument('modules', nargs='*', help='Module names to convert (default: all)') + parser.add_argument('--dry-run', action='store_true', help='Preview without writing files') + args = parser.parse_args() + + modules = args.modules if args.modules else SAGE_MODULES + dry_run = args.dry_run + + print("=" * 60) + print(" Sage Models: xlsx -> json 转换") + print("=" * 60) + print(f"Modules: {', '.join(modules)}") + print(f"Dry run: {dry_run}") + print() + + total_converted = 0 + total_skipped = 0 + + for mod in modules: + print(f"[{mod}]") + c, s = convert_module(mod, dry_run=dry_run) + total_converted += c + total_skipped += s + print() + + print("=" * 60) + print(f" 完成: 转换 {total_converted}, 跳过 {total_skipped}") + print("=" * 60) + + +if __name__ == '__main__': + main()