Compare commits

..

No commits in common. "main" and "fix/dark-mode-bg" have entirely different histories.

175 changed files with 902 additions and 12785 deletions

74
.gitignore vendored
View File

@ -1,38 +1,42 @@
# 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
# Python
__pycache__/
conf/config.json
*.py[cod]
*.egg-info/
dist/
build/
# Virtual environment
py3/
# Logs
logs/
# PID files
*.pid
# Generated files
*.pem
*.key
merchant_*.pem
alipay_*.pem
pay_*.pem
# Database
models/mysql.ddl.sql
# pkgs (submodules should be in their own repos)
pkgs/
# wwwroot (linked from module repos)
wwwroot/
# Migration scripts (run once, not needed in repo)
migrate_*.py
reset_*.py
check_*.py
set_*.sh
setup_*.sh
# Sage runtime
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

View File

@ -1,28 +0,0 @@
-----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-----

View File

@ -1,28 +0,0 @@
-----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-----

View File

@ -1,5 +1,6 @@
from ahserver.serverenv import ServerEnv
from sqlor.dbpools import DBPools
from alisms import AliSMS
def PopError(title='Error', message='Error happened'):
return {
@ -48,7 +49,9 @@ 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

View File

@ -1,5 +1,6 @@
import os, sys
import json
import asyncio
import argparse
from appPublic.log import MyLogger, info, debug, warning
from appPublic.folderUtils import ProgramPath
@ -10,7 +11,7 @@ from bricks_for_python.init import load_pybricks
from ahserver.webapp import webapp
from ahserver.serverenv import ServerEnv
from ahserver.configuredServer import add_cleanupctx
from rbac.init import load_rbac
from rbac.init import load_rbac, start_cache_sync
from pricing.init import load_pricing
from appbase.init import load_appbase
from llmage.init import load_llmage
@ -20,19 +21,17 @@ 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 dashboard_for_sage.init import load_dashboard_for_sage
from reallife_asset.init import load_reallife_asset
from discount.init import load_discount
from harnessed_agent.init import load_harnessed_agent
from harnessed_reasoning.init import load_harnessed_reasoning
from hermes_web_cli.init import load_hermes_web_cli
from dashboard_for_sage.init import load_dashboard_for_sage
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 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'
@ -43,10 +42,11 @@ def init():
load_pybricks()
load_appbase()
load_rbac()
asyncio.create_task(start_cache_sync())
load_accounting()
load_unipay()
load_platformbiz()
load_product_management()
load_supplychain()
load_filemgr()
load_llmage()
load_uapi()
@ -55,15 +55,13 @@ def init():
load_rag()
load_pricing()
load_checklang()
# load_harnessed_agent()
# load_harnessed_reasoning()
load_harnessed_agent()
load_harnessed_reasoning()
load_discount()
load_tenant()
load_hermes_web_cli()
load_smssend()
# load_dashboard_for_sage()
load_reallife_asset()
load_bugfix()
load_sage_datamart()
load_dashboard_for_sage()
if __name__ == '__main__':
webapp(init)

View File

@ -1,27 +0,0 @@
#!/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

View File

@ -1,13 +1,18 @@
#!/usr/bin/env python
"""
独立运行的产品后台计费程序
产品记账已从 llmage 迁移到 product_management 模块
独立运行的LLM后台计费程序
sage.py llmage 模块中提取避免多进程模式下重复运行
"""
import os
import sys
import asyncio
import signal
# 切换到 Sage 工作目录
os.chdir(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'py3', 'lib', 'python3.10', 'site-packages'))
sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'pkgs'))
from appPublic.folderUtils import ProgramPath
from appPublic.jsonConfig import getConfig
from sqlor.dbpools import DBPools
@ -20,16 +25,20 @@ 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
# 初始化配置
p = ProgramPath()
config = getConfig(NS={'workdir': os.getcwd(), 'ProgramPath': p})
DBPools(config.databases)
# 导入 llmage 的计费函数
from llmage.accounting import (
backend_accounting
)
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()})')
@ -48,20 +57,13 @@ def main():
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())
loop.run_until_complete(backend_accounting())
except asyncio.CancelledError:
pass
finally:

View File

@ -1,304 +0,0 @@
#!/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 "============================================================"

View File

@ -26,21 +26,18 @@ do
cd $m
$cdir/py3/bin/pip install .
done
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
for m in appbase rbac accounting llmage platformbiz msp cpcc unipay filemgr dapi uapi rag charge pricing discount harnessed_agent harnessed_reasoning dashboard_for_sage product_management
do
echo "install $m module..."
cd $cdir/pkgs
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
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
fi
if [ -d $cdir/pkgs/$m/json ];then
cd $cdir/pkgs/$m/json
./build.sh
@ -94,40 +91,3 @@ 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

View File

@ -1,19 +0,0 @@
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())

119
conf/config.json Executable file
View File

@ -0,0 +1,119 @@
{
"password_key":"!@#$%^&*(*&^%$QWERTYUIqwertyui234567",
"logopath": "$[workdir]$/conf/logo.png",
"tpacs":{
"cnprod":{
"get_tpac_balance_url": "https://www.opencomputing.cn/cntoai/get_user_balance.dspy",
"tpac_accounting_url": "https://www.opencomputing.cn/cntoai/process_user_billing.dspy"
},
"ncmatchdemo":{
"get_tpac_balance_url": "https://www.ncmatch.cn/cntoai/get_user_balance.dspy",
"tpac_accounting_url": "https://www.ncmatch.cn/cntoai/process_user_billing.dspy"
},
"cndemo": {
"get_tpac_balance_url": "https://dev.opencomputing.cn/cntoai/get_user_balance.dspy",
"tpac_accounting_url": "https://dev.opencomputing.cn/cntoai/process_user_billing.dspy"
}
},
"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_path": "$[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"],
[".wss","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"
}
}

Binary file not shown.

View File

@ -1,135 +0,0 @@
# 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/MVAI 写词、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"}'
```
**联系元境团队,获取完整部署方案:元境出品 欢乐随行**

Binary file not shown.

View File

@ -1,208 +0,0 @@
# 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.70.05元/秒,高质量 ⭐推荐
- 豆包 Seedance 2.00.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 都能以一致的方式管理和计费。

Binary file not shown.

View File

@ -1,341 +0,0 @@
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

View File

@ -1,341 +0,0 @@
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
配置账务: 会計構成
重置密码: パスワードリセット
错帐处理: 誤記帳処理
键: キー
长度: 長さ
附属密钥: 付属キー

View File

@ -1,341 +0,0 @@
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
配置账务: 회계 구성
重置密码: 비밀번호 재설정
错帐处理: 오기장 처리
键: 키
长度: 길이
附属密钥: 부속 키

View File

@ -1,341 +0,0 @@
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
配置账务: 配置账务
重置密码: 重置密码
错帐处理: 错帐处理
键: 键
长度: 长度
附属密钥: 附属密钥

View File

@ -1,138 +0,0 @@
#!/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())

View File

@ -1,6 +1,6 @@
{
"models_dir": "${HOME}$/py/accounting/models",
"output_dir": "${HOME}$/py/accounting/wwwroot/accounting_config",
"output_dir": "${HOME}$/py/sage/wwwroot/_a/accounting_config",
"dbname": "sage",
"tblname": "accounting_config",
"params": {

View File

@ -1,3 +0,0 @@
#!/bin/bash
xls2ui -m ../models -o ../wwwroot sage *.json

View File

@ -1,6 +1,6 @@
{
"models_dir": "${HOME}$/py/accounting/models",
"output_dir": "${HOME}$/py/accounting/wwwroot/subject",
"output_dir": "${HOME}$/py/sage/wwwroot/_a/subject",
"dbname": "sage",
"tblname": "subject",
"params": {

View File

@ -8,9 +8,6 @@ paths="""/ any
/favicon.ico any
/top.ui any
/i18n_getmsgs any
/tenant any
/tenant/index.ui any
/get_domain_info.dspy any
/uapi logined
/uapi/uapi logined
/uapi/uapi/delete_uapi.dspy logined
@ -45,8 +42,6 @@ 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
@ -54,12 +49,6 @@ 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/dim_test.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
@ -67,24 +56,7 @@ 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
@ -112,8 +84,6 @@ paths="""/ any
/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
@ -158,56 +128,6 @@ 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
@ -568,7 +488,6 @@ 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
@ -607,19 +526,6 @@ 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
@ -651,61 +557,6 @@ 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
@ -738,19 +589,6 @@ 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
@ -825,7 +663,6 @@ 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
@ -856,15 +693,10 @@ paths="""/ any
/rbac/get_reseller.dspy owner.*
/rbac/users logined
/rbac/users/delete_users.dspy *.admin
/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/users/add_users.dsp *.adminy
/rbac/users/update_users.dsp *.adminy
/rbac/users/index.u *.admini
/rbac/users/get_users.dspy
/rbac/add_adminuser.dspy owner.superuser
/rbac/reseller logined
/rbac/reseller/update_organization.dspy logined
@ -1270,12 +1102,12 @@ 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/product_type_config_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
@ -1283,196 +1115,20 @@ paths="""/ any
/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_type_config_create.dspy logined
/product_management/api/product_type_config_update.dspy logined
/product_management/api/product_type_config_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
/product_management/product_type_config_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
@ -1487,47 +1143,6 @@ paths="""/ any
/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
/hotspot/fetch_now.dspy logined
/hotspot/analyze.dspy logined
/hotspot_source logined
/hotspot_source/index.ui logined
/hotspot_source/get_hotspot_source.dspy logined
/hotspot_source/add_hotspot_source.dspy logined
/hotspot_source/update_hotspot_source.dspy logined
/hotspot_source/delete_hotspot_source.dspy logined
/hotspot_item logined
/hotspot_item/index.ui logined
/hotspot_item/get_hotspot_item.dspy logined
/hotspot_item/add_hotspot_item.dspy logined
/hotspot_item/update_hotspot_item.dspy logined
/hotspot_item/delete_hotspot_item.dspy logined
/hotspot_analysis logined
/hotspot_analysis/index.ui logined
/hotspot_analysis/get_hotspot_analysis.dspy logined
/hotspot_analysis/add_hotspot_analysis.dspy logined
/hotspot_analysis/update_hotspot_analysis.dspy logined
/hotspot_analysis/delete_hotspot_analysis.dspy logined
/hotspot_schedule logined
/hotspot_schedule/index.ui logined
/hotspot_schedule/get_hotspot_schedule.dspy logined
/hotspot_schedule/add_hotspot_schedule.dspy logined
/hotspot_schedule/update_hotspot_schedule.dspy logined
/hotspot_schedule/delete_hotspot_schedule.dspy logined
/hotspot_fetch_log logined
/hotspot_fetch_log/index.ui logined
/hotspot_fetch_log/get_hotspot_fetch_log.dspy logined
/hotspot_fetch_log/add_hotspot_fetch_log.dspy logined
/hotspot_fetch_log/update_hotspot_fetch_log.dspy logined
/hotspot_fetch_log/delete_hotspot_fetch_log.dspy logined
/hotspot_alert logined
/hotspot_alert/index.ui logined
/hotspot_alert/get_hotspot_alert.dspy logined
/hotspot_alert/add_hotspot_alert.dspy logined
/hotspot_alert/update_hotspot_alert.dspy logined
/hotspot_alert/delete_hotspot_alert.dspy logined
"""
@ -1579,7 +1194,7 @@ async def main():
cnt = 0
async with db.sqlorContext('sage') as sor:
for l in paths.split('\n'):
if not l or l.startswith('#'):
if not l:
continue
parts = l.split()
path = parts[0]

View File

@ -1,5 +0,0 @@
for s in $(ls ls pkgs/*/scripts/load_path.py)
do
echo $s
python $s
done

View File

@ -1,28 +0,0 @@
-----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-----

View File

@ -1,9 +0,0 @@
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA100zWM/1Tq+ilWu+JDtS
L499GIkPccQEiWMaR+dYLR0Vzth1Cju1VQK58jG6lhAb0nUgSP5gwqMYZkzFcbe+
dlc54D2IRpujOXBV5cwgyZqHZ8jRI1q0I08DmePZkjV8oUgi86cwLPT68UOjaZbW
M/hRbNivQwFpJ7NAuCntLzHeR9PwrPaY1rEFUotU1tG4/O+sa6LlPuI7DoSvlsQP
LAbAnbrO4rkpB44pg1WHFXXv/jf1hUrp2PBLeZW9ZrnkiC93fBGLnLIRdmTfdwqn
L5xIlQMnBmmalmpMIEFq7Ss2lTUoKtZ6XcnApIctqpMKDAZP9S7OGc5EFn0HPnog
RQIDAQAB
-----END PUBLIC KEY-----

View File

@ -1,166 +0,0 @@
#!/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()

View File

@ -1,68 +0,0 @@
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.')

BIN
models/.DS_Store vendored Normal file

Binary file not shown.

View File

@ -1,83 +0,0 @@
{
"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'"
}
]
}

View File

@ -1,40 +0,0 @@
{
"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'"
}
]
}

View File

@ -1,54 +0,0 @@
{
"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"
]
}
]
}

View File

@ -1,211 +0,0 @@
{
"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"
}
]
}

View File

@ -1,110 +0,0 @@
{
"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'"
}
]
}

View File

@ -1,70 +0,0 @@
{
"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"
]
}
]
}

View File

@ -1,80 +0,0 @@
{
"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"
]
}
]
}

View File

@ -1,57 +0,0 @@
{
"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"
}
]
}

View File

@ -1,73 +0,0 @@
{
"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"
}
]
}

View File

@ -1,69 +0,0 @@
{
"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'"
}
]
}

View File

@ -1,94 +0,0 @@
{
"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"
}
]
}

View File

@ -1,37 +0,0 @@
{
"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
}
]
}

View File

@ -1,57 +0,0 @@
{
"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"
}
]
}

View File

@ -1,64 +0,0 @@
{
"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'"
}
]
}

View File

@ -1,46 +0,0 @@
{
"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'"
}
]
}

View File

@ -1,37 +0,0 @@
{
"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
}
]
}

View File

@ -6578,151 +6578,4 @@ default charset=utf8
comment '模型供应商'
;
-- ============================================
-- 热点雷达系统 - 6 tables
-- ============================================
-- ./hotspot_source (来源配置: API / Browser / Crawler)
drop table if exists hotspot_source;
CREATE TABLE hotspot_source
(
`id` VARCHAR(32) comment 'id',
`name` VARCHAR(200) comment '来源名称',
`type` VARCHAR(20) comment '类型: rss/api/browser/crawler',
`url` VARCHAR(2000) comment '目标URL',
-- API 类型专用
`api_key` VARCHAR(500) comment 'API Key',
`api_secret` VARCHAR(500) comment 'API Secret(加密)',
`headers` TEXT comment '自定义请求头 JSON',
`fetch_method` VARCHAR(10) DEFAULT 'GET' comment 'HTTP方法',
`request_body` TEXT comment 'POST请求体',
-- Browser 类型专用
`browser_headless` VARCHAR(1) DEFAULT '1' comment '无头模式',
`browser_wait_selector` VARCHAR(500) comment '等待元素选择器',
`browser_scroll` VARCHAR(1) DEFAULT '0' comment '是否自动滚动',
-- Crawler 类型专用
`crawler_depth` INT DEFAULT 1 comment '爬取深度',
`crawler_rules` TEXT comment '爬取规则 JSON',
`crawler_start_urls` TEXT comment '起始URL列表 JSON',
-- 通用
`proxy_enabled` VARCHAR(1) DEFAULT '0' comment '启用代理',
`proxy_url` VARCHAR(500) comment '代理地址',
`parser_config` TEXT comment '提取规则 JSON: parser/item_path/field_map/builtin_name',
`enabled` VARCHAR(1) DEFAULT '1' comment '是否启用',
`priority` INT DEFAULT 0 comment '优先级(越大越高)',
`last_fetch` VARCHAR(50) comment '上次抓取时间',
`created_at` VARCHAR(50) comment '创建时间'
,primary key(id)
)
engine=innodb default charset=utf8 comment '热点来源配置'
;
-- ./hotspot_schedule (调度配置)
drop table if exists hotspot_schedule;
CREATE TABLE hotspot_schedule
(
`id` VARCHAR(32) comment 'id',
`source_id` VARCHAR(32) comment '关联来源ID',
`cron_expr` VARCHAR(100) comment 'cron表达式',
`interval_min` INT DEFAULT 60 comment '间隔(分钟)',
`enabled` VARCHAR(1) DEFAULT '1' comment '是否启用',
`last_run` VARCHAR(50) comment '上次运行',
`next_run` VARCHAR(50) comment '下次运行',
`retry_max` INT DEFAULT 3 comment '最大重试',
`retry_count` INT DEFAULT 0 comment '已重试次数'
,primary key(id)
)
engine=innodb default charset=utf8 comment '调度配置'
;
CREATE INDEX hotspot_schedule_source_idx ON hotspot_schedule(source_id);
-- ./hotspot_fetch_log (抓取日志)
drop table if exists hotspot_fetch_log;
CREATE TABLE hotspot_fetch_log
(
`id` VARCHAR(32) comment 'id',
`source_id` VARCHAR(32) comment '关联来源ID',
`start_time` VARCHAR(50) comment '开始时间',
`end_time` VARCHAR(50) comment '结束时间',
`duration_ms` INT DEFAULT 0 comment '耗时(毫秒)',
`status` VARCHAR(20) comment '状态: success/failed/partial',
`items_total` INT DEFAULT 0 comment '抓取总数',
`items_new` INT DEFAULT 0 comment '新增数量',
`items_duplicate` INT DEFAULT 0 comment '重复数量',
`error_msg` TEXT comment '错误信息',
`response_code` INT comment 'HTTP状态码',
`response_size_bytes` INT DEFAULT 0 comment '响应大小'
,primary key(id)
)
engine=innodb default charset=utf8 comment '抓取日志'
;
CREATE INDEX hotspot_fetch_log_source_idx ON hotspot_fetch_log(source_id);
CREATE INDEX hotspot_fetch_log_status_idx ON hotspot_fetch_log(status);
-- ./hotspot_item (热点条目)
drop table if exists hotspot_item;
CREATE TABLE hotspot_item
(
`id` VARCHAR(32) comment 'id',
`source_id` VARCHAR(32) comment '来源ID',
`title` VARCHAR(500) comment '标题',
`url` VARCHAR(2000) comment '原文链接',
`summary` TEXT comment '摘要',
`content` TEXT comment '正文',
`heat_score` DOUBLE(10,2) DEFAULT 0 comment '热度分数',
`heat_velocity` DOUBLE(10,2) DEFAULT 0 comment '热度加速度',
`publish_time` VARCHAR(50) comment '发布时间',
`first_seen` VARCHAR(50) comment '首次发现',
`last_updated` VARCHAR(50) comment '最后更新',
`status` VARCHAR(20) DEFAULT 'emerging' comment '状态: emerging/rising/hot/cooling/expired',
`category` VARCHAR(100) comment '分类',
`tags` VARCHAR(500) comment '标签',
`engagement_count` INT DEFAULT 0 comment '互动数',
`comment_count` INT DEFAULT 0 comment '评论数',
`share_count` INT DEFAULT 0 comment '转发数',
`sentiment` VARCHAR(20) DEFAULT 'neutral' comment '情感: positive/negative/neutral',
`is_verified` VARCHAR(1) DEFAULT '0' comment '是否已验证',
`duplicate_of` VARCHAR(32) comment '重复于(另一热点ID)'
,primary key(id)
)
engine=innodb default charset=utf8 comment '热点条目'
;
CREATE INDEX hotspot_item_source_idx ON hotspot_item(source_id);
CREATE INDEX hotspot_item_status_idx ON hotspot_item(status);
CREATE INDEX hotspot_item_score_idx ON hotspot_item(heat_score);
-- ./hotspot_analysis (五维分析)
drop table if exists hotspot_analysis;
CREATE TABLE hotspot_analysis
(
`id` VARCHAR(32) comment 'id',
`item_id` VARCHAR(32) comment '关联热点ID',
`dimension` VARCHAR(50) comment '维度: time/heat/content/propagation/audience',
`score` DOUBLE(10,2) DEFAULT 0 comment '维度得分(0-100)',
`analysis_data` TEXT comment '分析数据JSON',
`analyzed_at` VARCHAR(50) comment '分析时间'
,primary key(id)
)
engine=innodb default charset=utf8 comment '五维分析'
;
CREATE INDEX hotspot_analysis_item_idx ON hotspot_analysis(item_id);
-- ./hotspot_alert (预警规则)
drop table if exists hotspot_alert;
CREATE TABLE hotspot_alert
(
`id` VARCHAR(32) comment 'id',
`name` VARCHAR(200) comment '规则名称',
`source_id` VARCHAR(32) comment '来源ID(空=全局)',
`condition_type` VARCHAR(50) comment '条件: heat_threshold/velocity/sentiment/status_change',
`condition_value` VARCHAR(500) comment '条件值 JSON',
`enabled` VARCHAR(1) DEFAULT '1' comment '是否启用',
`notify_method` VARCHAR(50) comment '通知方式: email/webhook/sms',
`notify_target` VARCHAR(500) comment '通知目标',
`last_triggered` VARCHAR(50) comment '上次触发时间'
,primary key(id)
)
engine=innodb default charset=utf8 comment '预警规则'
;

View File

@ -1,43 +0,0 @@
{
"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"
}
]
}

View File

@ -1,127 +0,0 @@
{
"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"
}
]
}

View File

@ -1,40 +0,0 @@
{
"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'"
}
]
}

View File

@ -1,77 +0,0 @@
{
"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"
]
}
]
}

View File

@ -1,57 +0,0 @@
{
"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'"
}
]
}

View File

@ -1,31 +0,0 @@
{
"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
}
]
}

View File

@ -1,91 +0,0 @@
{
"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"
]
}
]
}

View File

@ -1,94 +0,0 @@
{
"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"
}
]
}

View File

@ -1,43 +0,0 @@
{
"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"
}
]
}

View File

@ -1,45 +0,0 @@
{
"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"
}
]
}

View File

@ -1,90 +0,0 @@
{
"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"
]
}
]
}

View File

@ -1,51 +0,0 @@
{
"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"
}
]
}

View File

@ -1,28 +0,0 @@
-----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-----

View File

@ -1,50 +0,0 @@
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('密码重置失败')

View File

@ -1,16 +0,0 @@
[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

View File

@ -1,49 +0,0 @@
#!/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"

View File

@ -1,118 +0,0 @@
#!/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/<module>/i18n 或 ~/repos/<module>/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()

View File

@ -1,29 +0,0 @@
# 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

View File

@ -1,9 +0,0 @@
# 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)}

View File

@ -1,96 +0,0 @@
-- ============================================================
-- 豆包大模型接入: 火山方舟 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);

View File

@ -1,101 +0,0 @@
-- ============================================================
-- 腾讯混元大模型接入: 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);

View File

@ -1,31 +0,0 @@
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/; }
}

File diff suppressed because one or more lines are too long

View File

@ -1,69 +0,0 @@
-- 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: 次');

View File

@ -1,381 +0,0 @@
-- ============================================================
-- 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 YAMLprice_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);

View File

@ -1,82 +0,0 @@
-- ============================================================
-- 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);

View File

@ -1,94 +0,0 @@
-- ============================================================
-- 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');

View File

@ -1,38 +0,0 @@
-- ============================================================
-- 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';

View File

@ -1,101 +0,0 @@
-- ============================================================
-- 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 YAMLprice_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;

View File

@ -1,66 +0,0 @@
-- ============================================================
-- 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);

View File

@ -1,21 +0,0 @@
-- ============================================================
-- 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';

View File

@ -1,30 +0,0 @@
#!/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."

View File

@ -1,4 +1,3 @@
import os
import sys
import asyncio
from sqlor.dbpools import DBPools
@ -35,8 +34,7 @@ async def main():
role = sys.argv[1]
path = sys.argv[2]
dbname = os.environ.get('SAGE_RBAC_DB', 'sage')
async with db.sqlorContext(dbname) as sor:
async with db.sqlorContext('sage') as sor:
perms = None
if '%' in path:
perms = await sor.sqlExe("select * from permission where path like ${path}$", {'path': path})

149
start.sh Executable file
View File

@ -0,0 +1,149 @@
#!/bin/bash
# Sage Web Application Start Script
# 多进程支持: 端口复用 + 独立后台程序
#
# 架构说明:
# 1. 独立后台程序 (bin/*.py) - 每个只启动一次,避免重复
# 2. Sage Web Workers - 根据CPU核心数启动多个worker使用端口复用
set -e
# 切换到脚本所在目录
cd "$(dirname "$0")"
# 本地开发环境变量(占位值,生产环境由系统配置)
export ALIPAY_PUB="$(pwd)/alipay_pub.pem"
export ALIPAY_PRIV="$(pwd)/alipay_priv.pem"
export BAIDU_SMS_ACCESS_KEY="dev-placeholder"
export BAIDU_SMS_ACCESS_KEY_SECRET="dev-placeholder"
export BAIDU_SMS_HOST="smsv3.bj.baidubce.com"
export BAIDU_SMS_SIGNATURE_ID="dev-placeholder"
# 配置
WORKDIR="$(pwd)"
PYTHON="./py3/bin/python"
APP_ENTRY="app/sage.py"
PIDFILE="$WORKDIR/sage.pid"
LOGDIR="$WORKDIR/logs"
BINPIDFILE="$WORKDIR/sage_backend.pid"
# 确保logs目录存在
mkdir -p "$LOGDIR"
# 检查Python是否存在
if [ ! -f "$PYTHON" ]; then
echo "错误: 找不到Python解释器 $PYTHON"
echo "请确保已安装虚拟环境: ./py3/bin/python"
exit 1
fi
# 检查应用入口文件是否存在
if [ ! -f "$APP_ENTRY" ]; then
echo "错误: 找不到应用入口文件 $APP_ENTRY"
exit 1
fi
# 检查Redis是否运行session存储依赖
if command -v redis-cli &> /dev/null; then
if ! redis-cli ping &> /dev/null; then
echo "Redis未运行正在启动Redis..."
redis-server --daemonize yes
sleep 1
if redis-cli ping &> /dev/null; then
echo "Redis启动成功"
else
echo "警告: Redis启动失败登录功能可能无法正常工作"
fi
else
echo "Redis运行正常"
fi
fi
echo "========================================="
echo "启动 Sage Web Application"
echo "工作目录: $WORKDIR"
echo "Python: $PYTHON"
echo "========================================="
# 获取端口
PORT=9180
if command -v python3 &> /dev/null; then
PORT=$($PYTHON -c "
import json
try:
with open('$WORKDIR/conf/config.json') as f:
config = json.load(f)
print(config.get('website', {}).get('port', 9180))
except Exception as e:
print(9180)
" 2>/dev/null || echo 9180)
fi
# =========================================
# 步骤 1: 启动独立后台程序
# =========================================
echo ""
echo "--- 启动独立后台程序 ---"
# 清空后台程序 PID 文件
> "$BINPIDFILE"
# 1.1 启动 LLM 后台计费程序
if [ -f "$WORKDIR/bin/backend_accounting.py" ]; then
LOGFILE="$LOGDIR/backend_accounting.log"
echo ">>> 启动 backend_accounting ..."
nohup $PYTHON "$WORKDIR/bin/backend_accounting.py" > "$LOGFILE" 2>&1 &
PID=$!
echo "backend_accounting:$PID" >> "$BINPIDFILE"
sleep 0.5
if kill -0 $PID 2>/dev/null; then
echo " -> backend_accounting PID: $PID (成功)"
else
echo " -> 警告: backend_accounting 启动失败,查看 $LOGFILE"
fi
fi
# =========================================
# 步骤 2: 启动 Sage Web Workers (端口复用)
# =========================================
echo ""
echo "--- 启动 Sage Web Workers (端口复用) ---"
# 获取 CPU 核心数,决定启动多少 Worker
WORKERS=$(nproc)
echo "检测到 ${WORKERS} 个 CPU 核心,准备启动 ${WORKERS} 个 worker 进程..."
echo "所有 worker 共享端口 ${PORT} (SO_REUSEPORT)"
# 清空 Worker PID 文件
> "$PIDFILE"
# 循环启动 Worker
for (( i=0; i<WORKERS; i++ ))
do
LOGFILE="$LOGDIR/sage_worker_${i}.log"
echo ">>> 启动 Worker $((i+1))/${WORKERS} on port $PORT ..."
# 启动服务 - 所有worker使用相同端口依赖ahserver的SO_REUSEPORT支持
nohup $PYTHON $APP_ENTRY --workdir "$WORKDIR" --port $PORT > "$LOGFILE" 2>&1 &
APP_PID=$!
# 保存 PID
echo "$APP_PID" >> "$PIDFILE"
# 短暂等待以检查是否立即崩溃
sleep 1
if kill -0 $APP_PID 2>/dev/null; then
echo " -> Worker PID: $APP_PID (成功)"
else
echo " -> 错误: Worker 启动失败,请查看 $LOGFILE"
fi
done
echo ""
echo "========================================="
echo "所有服务已启动"
echo "Worker PID 文件: $PIDFILE"
echo "Backend PID 文件: $BINPIDFILE"
echo "访问地址: http://localhost:${PORT}"
echo "========================================="

115
stop.sh Executable file
View File

@ -0,0 +1,115 @@
#!/bin/bash
# Sage Web Application Stop Script
# 停止所有 Web Workers 和独立后台程序
set -e
# 切换到脚本所在目录
cd "$(dirname "$0")"
WORKDIR="$(pwd)"
PIDFILE="$WORKDIR/sage.pid"
BINPIDFILE="$WORKDIR/sage_backend.pid"
echo "========================================="
echo "停止 Sage Web Application"
echo "========================================="
# =========================================
# 步骤 1: 停止 Web Workers
# =========================================
echo ""
echo "--- 停止 Web Workers ---"
if [ -f "$PIDFILE" ]; then
echo "读取 Worker PID 文件..."
while IFS= read -r pid || [ -n "$pid" ]; do
pid=$(echo "$pid" | tr -d '[:space:]')
[ -z "$pid" ] && continue
if kill -0 "$pid" 2>/dev/null; then
echo "正在停止 Worker (PID: $pid) ..."
kill "$pid" 2>/dev/null || true
else
echo "Worker (PID: $pid) 已不在运行"
fi
done < "$PIDFILE"
# 等待进程退出
echo "等待服务关闭..."
for i in $(seq 1 10); do
all_stopped=true
while IFS= read -r pid || [ -n "$pid" ]; do
pid=$(echo "$pid" | tr -d '[:space:]')
[ -z "$pid" ] && continue
if kill -0 "$pid" 2>/dev/null; then
all_stopped=false
break
fi
done < "$PIDFILE"
if $all_stopped; then
echo "所有 Worker 已停止 (用时 ${i}s)"
break
fi
sleep 1
done
# 强制杀死仍在运行的进程
while IFS= read -r pid || [ -n "$pid" ]; do
pid=$(echo "$pid" | tr -d '[:space:]')
[ -z "$pid" ] && continue
if kill -0 "$pid" 2>/dev/null; then
echo "强制停止 Worker (PID: $pid)"
kill -9 "$pid" 2>/dev/null || true
fi
done < "$PIDFILE"
# 清理 PID 文件
rm -f "$PIDFILE"
else
echo "未找到 Worker PID 文件 ($PIDFILE)"
fi
# =========================================
# 步骤 2: 停止独立后台程序
# =========================================
echo ""
echo "--- 停止独立后台程序 ---"
if [ -f "$BINPIDFILE" ]; then
echo "读取后台程序 PID 文件..."
while IFS= read -r line || [ -n "$line" ]; do
line=$(echo "$line" | tr -d '[:space:]')
[ -z "$line" ] && continue
# 格式: name:pid
name="${line%%:*}"
pid="${line##*:}"
if kill -0 "$pid" 2>/dev/null; then
echo "正在停止 $name (PID: $pid) ..."
kill "$pid" 2>/dev/null || true
sleep 1
if kill -0 "$pid" 2>/dev/null; then
echo "强制停止 $name (PID: $pid)"
kill -9 "$pid" 2>/dev/null || true
fi
echo " -> $name 已停止"
else
echo "$name (PID: $pid) 已不在运行"
fi
done < "$BINPIDFILE"
# 清理 PID 文件
rm -f "$BINPIDFILE"
else
echo "未找到后台程序 PID 文件 ($BINPIDFILE)"
fi
echo ""
echo "========================================="
echo "所有服务已停止"
echo "========================================="

View File

@ -1,17 +0,0 @@
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)

View File

@ -1,8 +0,0 @@
{% set lang = params_kw._lang or 'zh' %}
{
"widgettype": "ApiDoc",
"options": {
"md_url": "{{entire_url('/docs/api_doc_' + lang + '.md')}}",
"height": "100%"
}
}

View File

@ -1,142 +0,0 @@
# 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).

File diff suppressed because it is too large Load Diff

View File

@ -1,44 +0,0 @@
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'}

View File

@ -1,10 +1,4 @@
{
"widgettype": "VBox",
"options": {
"cheight": 40,
"width": "100%"
},
"subwidgets": [
{
"widgettype":"Tabular",
"options":{
@ -333,6 +327,4 @@
"cache_limit":5
}
}
]
}

View File

@ -1,13 +0,0 @@
# 多租户域名路由:解析当前请求域名对应的租户/分销商
env = request._run_ns
host = request.headers.get('X-Forwarded-Host') or request.host
host = host.split(':')[0]
try:
rec = await env.get_domain_by_host(request, host)
except Exception as e:
return json.dumps({'success': False, 'domain': host, 'error': str(e)}, ensure_ascii=False)
if rec:
result = {'success': True, 'domain': host, 'resellerid': rec.resellerid, 'orgid': rec.orgid}
else:
result = {'success': False, 'domain': host, 'error': 'Domain not found'}
return json.dumps(result, ensure_ascii=False)

View File

@ -1,432 +0,0 @@
{% 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"
}
}

79
wwwroot/i18n/en/i18n.json Normal file
View File

@ -0,0 +1,79 @@
{
"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"
}

View File

@ -0,0 +1,2 @@
{
}

View File

@ -0,0 +1,2 @@
{
}

View File

@ -10,7 +10,6 @@ return [
{
"value":"jp",
"text":"日本语"
},
{
"value":"ko",

View File

@ -1,5 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="10"/>
<line x1="2" y1="12" x2="22" y2="12"/>
<path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/>
</svg>

Before

Width:  |  Height:  |  Size: 347 B

View File

@ -1,5 +1,4 @@
{
"id":"language",
"widgettype":"Text",
"options":{

View File

@ -1,7 +1,5 @@
{
"widgettype":"Menu",
"options":{
"cwidth":11,
"target":"app",

21
wwwroot/i18n/zh/i18n.json Normal file
View File

@ -0,0 +1,21 @@
{
"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":"韩语"
}

View File

@ -1,14 +0,0 @@
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)

Some files were not shown because too many files have changed in this diff Show More