Compare commits

..

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

208 changed files with 9032 additions and 10473 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-----

50
apitools/README.md Normal file
View File

@ -0,0 +1,50 @@
# API tools
this tool read api specific file in json format, and generates python code
## json file format
{
"apiname":API name
"title":API descriptions
"description":
"data":{
}
mapis:{
methodname:mapi #each methos a key
}
}
mapi has following format
{
"title":name of the api
"descriptions":"description of the api
"url":call url for this api
"method":http method
"headers":haed need to set to
"params":data will sent to api server
"response_type":json, file,
"response_error_type":"json"
"response":resposne return from api server
"error_field":
"error_text_field":
"returnData":[
{
"field":"sssss",
"name":"ggggg"
}
]
}
## header, params, response format
{
name:
type:
required:
value:
description
}
## data in json file
Use ${name} format to refer the data in API's data object,
if name is not in data, replace ${name} as ""
## method call logic
this tool just build all the method api function for coder, and not call logic implement

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)

3
azure/key.py Normal file
View File

@ -0,0 +1,3 @@
apikey='eda4e3707f734f1e955d7bba6ebe68d1'
apikey2='a9250a0802864b889f882e0751b73807'

4
baidu/ak.py Normal file
View File

@ -0,0 +1,4 @@
# AccessKey = "ALTAKpUCiGSkgJE32uxNACxzZ2"
# AccessKeySecret = "2fec1ab19ded48efb81b4564e6986e15"
AccessKey = "SjAN4GHU07LuB8ZYOIstB31G"
AccessKeySecret = "QbakADoGJsM2qjUzIogTkBZruToxYAve"

138
baidu/qianfan_api.py Normal file
View File

@ -0,0 +1,138 @@
import asyncio
import ak
from appPublic.oauth_client import OAuthClient
desc = {
"data":{
"APIKey":ak.AccessKey,
"SecretKey":ak.AccessKeySecret
},
"mapis":{
"get_access_token":{
"url":"https://aip.baidubce.com/oauth/2.0/token",
"method":"POST",
"headers":[
{
"name":"Content-Type",
"value":"application/json"
}
],
"params":[
{
"name":"grant_type",
"value":"client_credentials"
},
{
"name":"client_id",
"value":"${APIKey}"
},
{
"name":"client_secret",
"value":"${SecretKey}"
}
],
"resposne_type":"2",
"error_field":"error",
"error_msg_field":"error_description",
"resp_set_data":[
{
"field":"access_token",
"name":"AccessToken"
},
{
"field":"expires_in",
"name":"TokenExpiresIn"
}
]
},
"chat":{
"url":"https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/completions_pro",
# "url":"http://localhost/test/show.dspy",
"method":"POST",
"headers":[
{
"name":"Content-Type",
"value":"application/json"
}
],
"params":[
{
"name":"access_token",
"value":"${AccessToken}"
}
],
"data":[
{
"name":"messages",
"value":"${messages}"
},
{
"name":"temperature",
"value":0.1
},
{
"name":"top_p",
"value":0.8
},
{
"name":"penalty_score",
"value":1.0
},
{
"name":"stream",
"value":False
},
{
"name":"system",
"value":"开元云助手"
},
{
"name":"stop",
"value":[]
},
{
"name":"max_output_token",
"value":2048
}
],
"resposne_type":"2",
"error_field":"error",
"error_msg_field":"error_description",
"resp_set_data":[
]
}
}
}
async def main(desc):
qianfanapi = OAuthClient(desc)
r = await qianfanapi('get_access_token', {})
print(f'get_access_token: response={r}, data={qianfanapi.data}')
msgs = []
while True:
print('prompt:')
p = input()
if p == '':
continue
if p == 'quit':
break
msg = {
"role":"user",
"content":p
}
msgs.append(msg)
r = await qianfanapi('chat',{"messages":msgs})
try:
print(r['result'])
msg = {
"role":"assistant",
"content":r['result']
}
msgs.append(msg)
except Exception as e:
print(r, e)
pass
if __name__ == '__main__':
asyncio.get_event_loop().run_until_complete(main(desc))

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
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
fi
cd $cdir/pkgs/$m
$cdir/py3/bin/pip install .
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

23
chatglm3_6b/load_model.py Normal file
View File

@ -0,0 +1,23 @@
from appPublic.worker import awaitify
from ahserver.serverEnv import ServerEnv
from transformers import AutoTokenizer, AutoModel
class ChatGLM3:
def __init__(self, model_path, gpu=False):
tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True)
model = AutoModel.from_pretrained(model_path, trust_remote_code=True)
if gpu:
model = model.cuda()
else:
model = model.float()
model = model.eval()
self.model = model
self.tokenizer = tokenizer
def _generate(self, prompt, history=[]):
response, history = self.model.chat(self.tokenizer, prompt, history=history)
return response, history
generate = awaitify(_generate)

View File

@ -0,0 +1,6 @@
transformers==4.30.2
protobuf
cpm_kernels
torch>=2.0
sentencepiece
accelerate

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())

5
codellama/load_model.py Normal file
View File

@ -0,0 +1,5 @@
from transformers import AutoTokenizer, AutoModelForCausalLM
tokenizer = AutoTokenizer.from_pretrained("codellama/CodeLlama-7b-hf")
tokenizer.save_pretrained('CodeLlama-7b-tokenizer')
model = AutoModelForCausalLM.from_pretrained("codellama/CodeLlama-7b-hf")
model.save_pretrained('CodeLlama-7b-model')

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"
}
}

View File

@ -0,0 +1,9 @@
text = params_kw.get('text')
lang = params_kw.get('lang', 'cn')
if lang == cn:
b = await cn_tts.generate(text)
return b
if lang == en:
b = await en_tts.generate(text)
return b

15
coquitts/load_model.py Normal file
View File

@ -0,0 +1,15 @@
from apppublic.worker import awaitify
from coquitts.coqui import CoquiTTS
g = ServerEnv()
# e = CoquiTTS('tts_models/en/ljspeech/vits--neon')
# g.en_tts = e
e = CoquiTTS('tts_models/zh-CN/baker/tacotron2-DDC-GST')
g.cn_tts = e
if __name__ == '__main__':
import asyncio
b = await e.generate('你好吗?我很好。')
with open('w.wav','wb') as f:
f.write(b)

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

@ -0,0 +1,88 @@
# code from https://platform.openai.com/docs/tutorials/web-qa-embeddings
import pandas as pd
import tiktoken
max_tokens = 500
# Function to split the text into chunks of a maximum number of tokens
def split_into_many(text, max_tokens = max_tokens):
# Split the text into sentences
sentences = text.split('. ')
# Get the number of tokens for each sentence
n_tokens = [len(tokenizer.encode(" " + sentence)) for sentence in sentences]
chunks = []
tokens_so_far = 0
chunk = []
# Loop through the sentences and tokens joined together in a tuple
for sentence, token in zip(sentences, n_tokens):
# If the number of tokens so far plus the number of tokens in the current sentence is greater
# than the max number of tokens, then add the chunk to the list of chunks and reset
# the chunk and tokens so far
if tokens_so_far + token > max_tokens:
chunks.append(". ".join(chunk) + ".")
chunk = []
tokens_so_far = 0
# If the number of tokens in the current sentence is greater than the max number of
# tokens, go to the next sentence
if token > max_tokens:
continue
# Otherwise, add the sentence to the chunk and add the number of tokens to the total
chunk.append(sentence)
tokens_so_far += token + 1
return chunks
def remove_newlines(serie):
serie = serie.str.replace('\n', ' ')
serie = serie.str.replace('\\n', ' ')
serie = serie.str.replace(' ', ' ')
serie = serie.str.replace(' ', ' ')
return serie
class EmbeddingsBuilder:
def __init__(self):
pass
def txt2csv(self, sourcePath, csvfile):
# Create a list to store the text files
texts=[]
# Get all the text files in the text directory
for file in os.listdir(sourcePath):
# Open the file and read the text
with open(sourcePath + file, "r", encoding="UTF-8") as f:
text = f.read()
# Omit the first 11 lines and the last 4 lines, then replace -, _, and #update with spaces.
texts.append((file, text))
# Create a dataframe from the list of texts
df = pd.DataFrame(texts, columns = ['title', 'text'])
# Set the text column to be the raw text with the newlines removed
df['text'] = df.fname + ". " + remove_newlines(df.text)
# Load the cl100k_base tokenizer which is designed to work with the ada-002 model
tokenizer = tiktoken.get_encoding("cl100k_base")
# Tokenize the text and save the number of tokens to a new column
df['n_tokens'] = df.text.apply(lambda x: len(tokenizer.encode(x)))
shortened = []
# Loop through the dataframe
for row in df.iterrows():
# If the text is None, go to the next row
if row[1]['text'] is None:
continue
# If the number of tokens is greater than the max number of tokens, split the text into chunks
if row[1]['n_tokens'] > max_tokens:
shortened += split_into_many(row[1]['text'])
# Otherwise, add the text to the list of shortened texts
else:
shortened.append( row[1]['text'] )
df = pd.DataFrame(shortened, columns = ['text'])
df['n_tokens'] = df.text.apply(lambda x: len(tokenizer.encode(x)))
df.to_csv(csvfile)

70
fastchat/load_model.py Normal file
View File

@ -0,0 +1,70 @@
import time
from fastchat.serve.inference import ChatIO
from fastchat.model.model_adapter import (
load_model,
# get_conversation_template,
get_generate_stream_function,
)
from ahserver.serverenv import ServerEnv
from appPublic.worker import awaitify
class FastChatModel:
def __init__(self, model_path, device='cpu',
temperature=1.0,
context_len=100000,
debug=False
):
self.model_path = model_path
self.device = device
self.debug = debug
self.temperature=temperature
self.context_len = context_len
self.model, self.tokenizer = load_model(
model_path,
device=device,
debug=debug
)
self.generate_stream_func = get_generate_stream_function(self.model, self.model_path)
def _generate(self, prompt):
gen_params = {
"model": self.model_path,
"prompt": prompt,
"temperature": self.temperature,
"max_new_tokens": self.context_len,
"stream":False,
"echo": False,
}
output_stream = self.generate_stream_func(
self.model,
self.tokenizer,
gen_params,
self.device,
context_len=self.context_len
)
t = time.time()
output = ''
for i,s in enumerate(output_stream):
if self.debug:
print(i, ':', s['text'], '\n')
return s['text']
generate = awaitify(_generate)
g = ServerEnv()
# m = FastChatModel('./vicuna-7b-v1.5' device='mps')
# m = FastChatModel('/Users/ymq/models/hub/CodeLlama-13b-Instruct-hf')
m = FastChatModel('/Users/ymq/models/hub/CodeLlama-13-hf')
g.fschat = m
if __name__ == '__main__':
import asyncio
async def main():
while True:
print('input prompt:')
p = input()
x = await m.generate(p)
print(f'answer:\n{x}')
asyncio.get_event_loop().run_until_complete(main())

View File

@ -0,0 +1 @@
fschat

2
gpt4all/generate.dspy Normal file
View File

@ -0,0 +1,2 @@
prompt = params_kw.get('prompt')
return await gpt4all_engine.generate(prompt)

25
gpt4all/load_model.py Normal file
View File

@ -0,0 +1,25 @@
from gpt4all import GPT4All
from ahserver.serverenv import ServerEnv
from appPublic.worker import awaitify
class GadgetGpt4all:
def __init__(self, model_name):
self.model_name = model_name
self.model = GPT4All(model_name,device='intel')
# device='amd', device='intel'
def _generate(text):
return self.model.generate(text, max_tokens=10000000)
generate = awaitify(_generate)
g = ServerEnv()
m = GadgetGpt4all('orca-mini-3b-gguf2-q4_0.gguf')
g.gpt4all_model = m
if __name__ == '__main__':
import asyncio
asyncio.get_event_loop().run_until_complete(g.generate('what is the color of lotus'))
output = model.generate("The capital of France is ", max_tokens=3)
print(output)

1
gpt4all/requirements.txt Normal file
View File

@ -0,0 +1 @@
gpt4all

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())

17
initln Executable file
View File

@ -0,0 +1,17 @@
#!/usr/bin/env bash
for m in apppublic sqlor ahserver accounting appbase basellm filemgr msp platformbiz rag rbac uapi
do
echo $m ...............
cd ~/py/$m
git pull
if [ -f "setup.cfg" ];then
pip install .
fi
if [ -d "json" ];then
cd ~/py/$m/json
sh ./build.sh
cd ~/py/sage/wwwroot
ln -s ~/py/$m/wwwroot $m
fi
done

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/show_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.')

267
minimax/api.py Normal file
View File

@ -0,0 +1,267 @@
from appPublic.dictObject import DictObject
from appPublic.oauth_client import OAuthClient
api_desc = {
"data":{
"apikey":'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJHcm91cE5hbWUiOiJtb3FpbmcgeXUiLCJVc2VyTmFtZSI6Im1vcWluZyB5dSIsIkFjY291bnQiOiIiLCJTdWJqZWN0SUQiOiIxNzY4NTM3NjQ1ODMyNDg3NjAyIiwiUGhvbmUiOiIxMzgwMTAxNTI5MiIsIkdyb3VwSUQiOiIxNzY4NTM3NjQ1ODI4MjkyOTMwIiwiUGFnZU5hbWUiOiIiLCJNYWlsIjoiIiwiQ3JlYXRlVGltZSI6IjIwMjQtMDQtMTAgMTg6MDA6NTMiLCJpc3MiOiJtaW5pbWF4In0.VaRRHr9XMUSYhZOKVS2PRZv6Y9VCaW4JX2ks4QZX3aFr_emjnDbGv5HfNskf54piflEAeTMW4Qw1nG7bqhYea7N5LKHGf0YpesPGSoqxwyZUR4oaJNNVUsSe6eiLbdYSDO2wMb_hV5xyawh-lYe1reBKWaPVuOjfTrDhxzA0IBmzl-jAQhL8-kIZet2uX-p3NjxElpo_zjmVV_hA1BJEvTwuAk8ka-1SBZmXciMhBi1fJG4jcqoHCCN_JHJ7pgjKr5bk2Zw5qCqiU2Ecsc-kPIEK1SI5EYoLszT43UpJ8_wV4Pm07UBCn3vktAa0fjKDSUArPkBoYWSkgKDMWlmxig',
"group_id":'1768537645828292930'
},
"sub_account":{
"path":"/v1/sub_account",
"method":"POST",
"headers":[
{
"name":"Content-Type",
"value":"application/json"
},
{
"name":"Authorization",
"value":"Bearer ${apikey}"
}
],
"params":[
{
"name":"GroupId",
"value":"${group_id}"
}
],
"data":[
{
"name":"account_name",
"value":"${account_name}"
}
],
"resp":[
{
"name":"subject_id",
"resp_keys":"subject_id"
},
{
"name":"account_name",
"resp_keys":"account",
},
{
"name":"password",
"resp_keys":"password"
},
{
"name":"group_id",
"resp_keys":"group_id"
},
{
"name":"apikey",
"resp_keys":"token"
}
],
"error_if":{
"error_keys":"base_resp.status_code",
"op":"!=",
"value":0,
"code_keys":"base_resp.status_code",
"msg_keys":"base_resp.status_msg"
}
},
"sub_delete":{
"path":"/v1/sub_account/${sub_account_id}",
"method":"DELETE",
"headers":[
{
"name":"Content-Type",
"value":"application/json"
},
{
"name":"Authorization",
"value":"Bearer ${apikey}"
}
],
"params":[
{
"name":"GroupId",
"value":"${group_id}"
}
],
"error_if":{
"error_keys":"base_resp.status_code",
"op":"!=",
"value":0,
"code_keys":"base_resp.status_code",
"msg_keys":"base_resp.status_msg"
}
},
"change_sub_status":{
"path":"/v1/sub_account/${sub_account_id}/status",
"method":"PUT",
"headers":[
{
"name":"Content-Type",
"value":"application/json"
},
{
"name":"Authorization",
"value":"Bearer ${apikey}"
}
],
"params":[
{
"name":"GroupId",
"value":"${group_id}"
}
],
"data":[
{
"name":"status",
"value":"${status}"
}
],
"error_if":{
"error_keys":"base_resp.status_code",
"op":"!=",
"value":0,
"code_keys":"base_resp.status_code",
"msg_keys":"base_resp.status_msg"
}
},
"change_sub_apikey":{
"path":"/v1/sub_account/${sub_account_id}/token",
"method":"PUT",
"headers":[
{
"name":"Content-Type",
"value":"application/json"
},
{
"name":"Authorization",
"value":"Bearer ${apikey}"
}
],
"params":[
{
"name":"GroupId",
"value":"${group_id}"
}
],
"resp":[
{
"name":"apikey",
"resp_keys":"token"
}
],
"error_if":{
"error_keys":"base_resp.status_code",
"op":"!=",
"value":0,
"code_keys":"base_resp.status_code",
"msg_keys":"base_resp.status_msg"
}
},
"get_sub_bill":{
"path":"/v1/sub_account/${sub_account_id}/bill",
"method":"GET",
"headers":[
{
"name":"Content-Type",
"value":"application/json"
},
{
"name":"Authorization",
"value":"Bearer ${apikey}"
}
],
"params":[
{
"name":"GroupId",
"value":"${group_id}"
},
{
"name":"method",
"value":"${bill_type}"
}
],
"resp":[
{
"name":"bills",
"resp_keys":"bill_list"
}
],
"error_if":{
"error_keys":"base_resp.status_code",
"op":"!=",
"value":0,
"code_keys":"base_resp.status_code",
"msg_keys":"base_resp.status_msg"
}
},
"bill":{
"path":"/v1/batch_query_bill",
"method":"GET",
"headers":[
{
"name":"Content-Type",
"value":"application/json"
},
{
"name":"Authorization",
"value":"Bearer ${apikey}"
}
],
"params":[
{
"name":"GroupId",
"value":"${group_id}"
},
{
"name":"start_date",
"value":"${start_date}"
},
{
"name":"end_date",
"value":"${end_date}"
}
],
"resp":[
{
"name":"bills",
"resp_keys":"bill_list"
}
],
"error_if":{
"error_keys":"base_resp.status_code",
"op":"!=",
"value":0,
"code_keys":"base_resp.status_code",
"msg_keys":"base_resp.status_msg"
}
}
}
if __name__ == '__main__':
import asyncio
async def main():
m = OAuthClient(DictObject(**api_desc))
# sub_account test ok
# resp = await m('https://api.minimax.chat', 'sub_account', {'account_name':'test1'})
# sub_delete test ok
# resp = await m('https://api.minimax.chat', 'sub_delete', {'sub_account_id':'1765984131482656836'})
# change_sub_status test ok
# resp = await m('https://api.minimax.chat', 'change_sub_status',
# {'sub_account_id':'1766027179931476048', 'status':0})
# change_sub_apikey test ok
# resp = await m('https://api.minimax.chat', 'change_sub_apikey',
# {'sub_account_id':'1766027179931476048'})
# get_sub_bill test, wait data to check
# resp = await m('https://api.minimax.chat', 'get_sub_bill',
# {'sub_account_id':'1766027179931476048',
# bill test ok
resp = await m('https://api.minimax.chat', 'bill',
{
'start_date':'20240419',
'end_date':'20240419'})
print(resp)
async def t():
for i in range(100):
await main()
with open('t.py', 'r') as f:
print('-------------------',f.fileno())
asyncio.get_event_loop().run_until_complete(main())

185
minimax/minimax.py Normal file
View File

@ -0,0 +1,185 @@
from appPublic.jsonConfig import getConfig
from appPublic.oauth_client import OAuthClient
from appPublic.uniqueID import getID
from sqlor.dbpools import DBPools
from ahserver.globalEnv import get_definition
from .api import api_desc
class MinimaxAdm:
def __init__(self, dbname, url_base='https://api.minimax.chat'):
self.api_desc = api_desc
self.name = api_desc.name
self.dbname = dbname
self.url_base = url_base
self.api = OAuthClient(DictObject(**self.api_desc))
async def write_usage(self, userid, model, usage):
ns = {
'id':getID(),
'userid':userid,
'apiname':self.name,
'model':model,
'u_date':curdate(),
'u_time':curtime(),
'input_usage':usage.input_token,
'output_usage':usage.output_token,
'total_usage':usage.total_token
}
db = DBPools()
async with db.sqlorContext(self.dbname) as sor:
await sor.C('token_usage', ns)
async def get_account(self, userid):
db = DBPools()
async with db.sqlorContext(self.dbname) as sor:
ns = {'userid':userid}
r = await sor.sqlExe('select * from minimax_acc where userid=${userid}$', ns)
if len(r) > 0:
return r[0]
return None
asyncdef get_username(self, userid):
db = DBPools()
async with db.sqlorContext(self.dbname) as sor:
ns = {'userid':userid}
r = await sor.sqlExe('select * from users where userid=${userid}$', ns)
if len(r) > 0:
return r[0].username
return None
async def new_account(self, ns):
db = DBPools()
async with db.sqlContext(self.dbname) as sor:
await sor.C('minimax_acc', ns)
return True
return False
async def open_accoount(self, userid):
acc = await self.get_account(userid)
if acc:
return acc
username = self.get_username(userid)
if not username:
return False
resp = await self.api(self.url_base,
'sub_account',
{'account_name':username})
if resp.status != 'ok':
print(resp)
return False
d = resp.data
ns = {
'id':getID(),
'userid':userid,
'acc_id:d.subject_id,
'acc_name':d.account,
'password':d.password,
'apikey':d.token,
'groupid':d.group_id,
'acc_status':0
}
r = await self.new_account(self, ns)
return r
async def delete_account(self, ns):
db = DBPools()
async with db.sqlContext(self.dbname) as sor:
await sor.D('minimax_acc', ns)
return True
return False
async def update_acc(self, ns):
db = DBPools()
async with db.sqlorContext(self.dbname) as sor:
r = await sor.U('minimax_acc', ns)
return r
return False
async def delete_acc(self, userid):
acc = await self.get_account(userid)
if acc is None:
return False
if acc.acc_status == 0:
print(f'{acc_name} minimax acc is using, please disable it first')
return False
resp = await self.api(self.url_base,
'sub_delete',
{'sub_account_id':acc.acc_id})
if resp.status == 'ok':
r = await self.delete_account(acc)
return r
return False
async def acc_enable(self, userid):
return await self._acc_change_status(self, user, 0)
async def acc_disable(self, userid):
return await self._acc_change_status(self, user, 2)
async def _acc_change_status(self, userid, status):
acc = await self.get_account(userid)
if acc is None:
return False
if acc.acc_status == status:
return True
resp = await self.api(self.url_base, 'ststus', {
'sub_account_id':acc.acc_id,
'status':status
})
if resp.status != 'ok':
return False
ns = {
'id':acc.id,
'status':status
}
return await self.update_acc(ns):
async def reset_apikey(self, userid):
acc = await self.get_account(userid)
if acc is None:
return False
resp = await self.api(self.url_base, 'token', {
'sub_account_id':acc.acc_id
})
if resp.status != 'ok':
return False
ns = {
'id':acc.id,
'apikey':resp.apikey
}
return await self.update_acc(ns):
async def get_daily_bill(self, dat):
acc = await self.get_account(userid)
if acc is None:
return False
d = ''.join(dat.split('-'))
resp = await self.api(self.url_base, 'bill', {
'start_date':d,
'end_date':d
})
if resp.status != 'ok':
return await self.append_bill(resp.data.bills, dat)
async def append_bill(bills, dat):
db = DBPools()
for b in bills:
ns = {
'id':getID(),
'acc_id':b.creator_id,
'acc_name':b.creator_name,
'model':b.model,
'consume_time':b.consume_time,
'consume_token':b.consume_token,
'consume_amt':b.consume_cash,
'create_at':b.create_at,
'consume_date':dat
}
r = False
async with db.sqlorContext(self.dbname) as sor:
sor.C('minimax_bill', ns)
r = True
if not r:
print(f'{ns} write to db error')
return True

92
minimax/t Normal file
View File

@ -0,0 +1,92 @@
{
'status': 'ok',
'data': {
'bills': [
{
'method': 'chatcompletion-pro',
'consume_cash': '0.0075',
'consume_token': '75',
'created_at': 1713517200,
'status': 'SUCCESS',
'model': 'abab6-chat',
'mail': '主账户',
'creator_id': '',
'api_token_name': 'open computing',
'group_id': '1768537645828292930',
'creator_name': '主账户',
'ymd': '',
'consume_time': '2024年04月19日 17:00-18:00'
}, {
'method': 'chatcompletion-pro',
'consume_cash': '0.0057',
'consume_token': '57',
'created_at': 1713434400,
'status': 'SUCCESS',
'model': 'abab6-chat',
'mail': '主账户',
'creator_id': '',
'api_token_name': 'open computing',
'group_id': '1768537645828292930',
'creator_name': '主账户',
'ymd': '',
'consume_time': '2024年04月18日 18:00-19:00'
}, {
'method': 'chatcompletion-pro',
'consume_cash': '0.0467',
'consume_token': '467',
'created_at': 1713430800,
'status': 'SUCCESS',
'model': 'abab6-chat',
'mail': '主账户',
'creator_id': '',
'api_token_name': 'open computing',
'group_id': '1768537645828292930',
'creator_name': '主账户',
'ymd': '',
'consume_time': '2024年04月18日 17:00-18:00'
}, {
'method': 'chatcompletion-pro',
'consume_cash': '0.1040',
'consume_token': '1040',
'created_at': 1713348000,
'status': 'SUCCESS',
'model': 'abab6-chat',
'mail': '主账户',
'creator_id': '',
'api_token_name': 'open computing',
'group_id': '1768537645828292930',
'creator_name': '主账户',
'ymd': '',
'consume_time': '2024年04月17日 18:00-19:00'
}, {
'method': 'chatcompletion-pro',
'consume_cash': '0.1102',
'consume_token': '1102',
'created_at': 1713344400,
'status': 'SUCCESS',
'model': 'abab6-chat',
'mail': '主账户',
'creator_id': '',
'api_token_name': 'open computing',
'group_id': '1768537645828292930',
'creator_name': '主账户',
'ymd': '',
'consume_time': '2024年04月17日 17:00-18:00'
}, {
'method': 'chatcompletion-pro',
'consume_cash': '0.0106',
'consume_token': '708',
'created_at': 1713340800,
'status': 'SUCCESS',
'model': 'abab5.5-chat',
'mail': '主账户',
'creator_id': '',
'api_token_name': 'open computing',
'group_id': '1768537645828292930',
'creator_name': '主账户',
'ymd': '',
'consume_time': '2024年04月17日 16:00-17:00'
}
]
}
}

BIN
models/.DS_Store vendored Normal file

Binary file not shown.

BIN
models/apiparams.xlsx Normal file

Binary file not shown.

BIN
models/appcodes.xlsx Normal file

Binary file not shown.

BIN
models/appcodes_kv.xlsx Normal file

Binary file not shown.

BIN
models/feelog.xlsx Normal file

Binary file not shown.

BIN
models/httpapi.xlsx Normal file

Binary file not shown.

BIN
models/minimax_acc.xlsx Normal file

Binary file not shown.

BIN
models/minimax_bill.xlsx Normal file

Binary file not shown.

BIN
models/modelapi.xlsx Normal file

Binary file not shown.

BIN
models/modelinstance.xlsx Normal file

Binary file not shown.

BIN
models/modeliodata.xlsx Normal file

Binary file not shown.

BIN
models/modelpricing.xlsx Normal file

Binary file not shown.

BIN
models/modelprovider.xlsx Normal file

Binary file not shown.

BIN
models/models.xlsx Normal file

Binary file not shown.

BIN
models/modeltype.xlsx Normal file

Binary file not shown.

BIN
models/modeltypein.xlsx Normal file

Binary file not shown.

BIN
models/modeltypeout.xlsx Normal file

Binary file not shown.

6581
models/mysql.ddl.sql Normal file

File diff suppressed because it is too large Load Diff

BIN
models/org_roles.xlsx Normal file

Binary file not shown.

BIN
models/organization.xlsx Normal file

Binary file not shown.

BIN
models/orgtypes.xlsx Normal file

Binary file not shown.

BIN
models/permission.xlsx Normal file

Binary file not shown.

BIN
models/role.xlsx Normal file

Binary file not shown.

BIN
models/rolepermission.xlsx Normal file

Binary file not shown.

BIN
models/token_usage.xlsx Normal file

Binary file not shown.

BIN
models/userapikey.xlsx Normal file

Binary file not shown.

BIN
models/userdepartment.xlsx Normal file

Binary file not shown.

BIN
models/userroles.xlsx Normal file

Binary file not shown.

BIN
models/users.xlsx Normal file

Binary file not shown.

BIN
models/xterm.xlsx Normal file

Binary file not shown.

1
moonshot/key.py Normal file
View File

@ -0,0 +1 @@
sk-fHOyIKC2mlIDfGwUQV6SwjwVJkjBJgkNWYv82yt3OdpYh592

113
ollama/api.py Normal file
View File

@ -0,0 +1,113 @@
import asyncio
from appPublic.oauth_client import OAuthClient
desc = {
"data":{
"oops":1
},
"mapis":{
"generate":{
"url":"https://sage.opencomputing.cn/ollama/api/generate",
"method":"POST",
"headers":[
],
"params":[
],
"data":[
{
"name":"model",
"value":"${model}"
},
{
"name":"prompt",
"value":"${prompt}"
},
{
"name":"context",
"value":"${context}"
},
{
"name":"stream",
"value":True
},
],
"resposne_type":"2",
"error_field":"error",
"error_msg_field":"error_description",
"resp_set_data":[
]
},
"chat":{
# "url":"https://sage.opencomputing.cn/ollama/api/chat",
"url":"http://localhost:11434/api/chat",
"method":"POST",
"headers":[
],
"params":[
],
"data":[
{
"name":"model",
"value":"${model}"
},
{
"name":"messages",
"value":"${messages}"
},
{
"name":"stream",
"value":True
},
],
"resposne_type":"2",
"error_field":"error",
"error_msg_field":"error_description",
"resp_set_data":[
]
}
}
}
async def generate(desc):
ollama = OAuthClient(desc)
context = []
while True:
print('prompt:')
p = input()
if p == '':
continue
if p == 'quit':
break
r = await ollama('generate', {
"model":"llama2:13b",
"context":context,
"prompt":p
})
context = r['context']
print('ollama:', r['response'])
async def chat(desc):
ollama = OAuthClient(desc)
msgs = []
while True:
print('prompt:')
p = input()
if p == '':
continue
if p == 'quit':
break
msg = {
"role":"user",
"content":p
}
msgs.append(msg)
r = await ollama('chat', {
"model":"llama2:7b",
"messages":msgs
})
msgs.append(r['message'])
response = r['message']['content']
print('ollama:', response)
if __name__ == '__main__':
asyncio.get_event_loop().run_until_complete(chat(desc))

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-----

1
qianwen/key.py Normal file
View File

@ -0,0 +1 @@
apikey='sk-ca5dfeb58d494f32a9cf1e9f064370c8'

72
qianwen/qianwen.py Normal file
View File

@ -0,0 +1,72 @@
import sys
import os
from http import HTTPStatus
import dashscope
from dashscope.api_entities.dashscope_response import Role
from appPublic.worker import awaitify
from key import apikey
def get_user_apikey(apiname, user):
return apikey
class QianWen:
def __init__(self, user):
self.key = get_user_apikey('qianwen', user)
def _generate(self, p, model, h, stream):
h.append({
'role':'user',
'content':p
})
dashscope.api_key = self.key
response = dashscope.Generation.call(
model,
messages=h,
stream=stream,
incremental_output=True,
result_format='message')
if stream:
return response
if response.status_code == HTTPStatus.OK:
return response
raise Exception(f'Qianwen Error:{response.status_code}:{resposne.message}')
async def generate(self, p, model='qwen-turbo', h=[], chunk_func=None):
reco = awaitify(self._generate)
stream = True
if chunk_func is None:
stream = False
resp = await reco(p, model, h, stream)
if stream:
for r in resp:
chunk_func(r.output.choices[0].message.content)
else:
return resp.choices[0].message.content
a_content = ''
async def main():
global a_content
def f(t):
global a_content
a_content += t
sys.stdout.write(t)
sys.stdout.flush()
h = []
ai = QianWen('aaa')
while True:
print('prompt:')
p = input()
if p == '':
continue
a_content = ''
print('answer:')
await ai.generate(p, h=h, chunk_func=f)
h.append({'role': 'assistant', 'content':a_content})
print('\n')
if __name__ == '__main__':
import asyncio
asyncio.get_event_loop().run_until_complete(main())

2
qianwen/requirements.txt Normal file
View File

@ -0,0 +1,2 @@
python=3.10
dashscope

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

36
script/cpc.nginx Normal file
View File

@ -0,0 +1,36 @@
server {
server_name cpc.opencomputing.cn;
location / {
add_header Access-Control-Allow-Origin *;
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;
proxy_pass http://10.60.179.61:30880/;
}
listen 443 ssl; # managed by Certbot
ssl_certificate /d/ymq/py/script/fullchain.pem; # managed by Certbot
ssl_certificate_key /d/ymq/py/script/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
if ($host = cpc.opencomputing.cn) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
server_name cpc.opencomputing.cn;
return 404; # managed by Certbot
}

122
script/fakelog.py Normal file
View File

@ -0,0 +1,122 @@
import sys
from traceback import format_exc
import asyncio
from appPublic.uniqueID import getID
from appPublic.timeUtils import days_between, strdate_add
from random import randint, random
from sqlor.dbpools import DBPools
databases = {
"sage":{
"driver":"aiomysql",
"async_mode":True,
"coding":"utf8",
"maxconn":100,
"dbname":"sage",
"kwargs":{
"user":"test",
"db":"sage",
"password":"QUZVcXg5V1p1STMybG5Ia6mX9D0v7+g=",
"host":"localhost"
}
}
}
def get_modelid():
return sys.argv[4]
return 'AuJYPP051dQJW9njyXhIu'
def get_date(d1, d2):
days = days_between(d1, d2) - 1
if (d1 > d2):
d = d2
d2 = d1
d1 = d
return strdate_add(d1, days=random() * (days + 1))
def get_time(d):
tf = 7 * 60 * 60
tt = 21 * 60 * 60
ti = tf + int(random() * (tt - tf))
h = int(ti / 3600)
m = int((ti - h * 3600) / 60)
s = ti % 60
return '%s %02d:%02d:%02d' % (d, h, m, s)
async def get_users(sor):
sql = "select id from users"
users = await sor.sqlExe(sql, {})
return users
def get_user(users):
cnt = len(users)
return users[randint(0, cnt - 1)].id
async def get_modeltype(sor, mii):
try:
sql = """select b.modeltypeid
from modelinstance a, modelapi b
where a.modelid = b.modelid
and a.id = ${id}$"""
recs = await sor.sqlExe(sql, {'id':mii})
if len(recs) > 0:
cnt = len(recs)
return recs[randint(0,cnt-1)].modeltypeid
else:
print(f'{sql=}, {mii=} not found')
return None
except Exception as e:
tbc = format_exc()
print(f'{e}, {tbc=}')
async def main():
db = DBPools(databases)
mti_tokens = {
'semanticsunderstanding':8839818053,
'dialogsemantics':4475142259,
'textclassify':6931846764,
'textmatching':3896737113
}
async with db.sqlorContext('sage') as sor:
userids = await get_users(sor)
mii = 'AuJYPP051dQJW9njyXhIu'
for mti, max_token in mti_tokens.items():
while max_token > 0:
input_t = 1000 + randint(0, 1000000)
output_t = 1000 + randint(0, 1000000)
token_cnt = input_t + output_t
if token_cnt > max_token:
t = int (token_cnt - max_token) / 2
input_t -= t
output_t = max_token - input_t
max_token = 0
else:
max_token -= token_cnt
transdate = get_date('2024-11-01', '2024-12-01')
transtime = get_time(transdate)
modeltypeid = mti
userid = get_user(userids)
pricing_mode = 'token'
accounting_status = 'not_accounting_yet'
id = getID()
d = {
"id":id,
"transdate":transdate,
"transtime":transtime,
"modelinstanceid":mii,
"modeltypeid":modeltypeid,
"userid":userid,
"pricing_mode":pricing_mode,
"input_tokens":input_t,
"output_tokens":output_t,
"token_cnt":token_cnt,
"accounting_status":accounting_status
}
await sor.C('feelog', d)
if __name__ == '__main__':
asyncio.get_event_loop().run_until_complete(main())

3
script/killname Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
ps -ef|grep "$1"|grep -v grep|awk '{print("kill -9", $2)}'|sh

69
script/perms.py Normal file
View File

@ -0,0 +1,69 @@
import os
import sys
from traceback import format_exc
import asyncio
from appPublic.uniqueID import getID
from appPublic.timeUtils import days_between, strdate_add
from appPublic.jsonConfig import getConfig
from random import randint, random
from appPublic.folderUtils import listFile
from sqlor.dbpools import DBPools
databases = {
"sage":{
"driver":"aiomysql",
"async_mode":True,
"coding":"utf8",
"maxconn":100,
"dbname":"sage",
"kwargs":{
"user":"test",
"db":"sage",
"password":"QUZVcXg5V1p1STMybG5Ia6mX9D0v7+g=",
"host":"localhost"
}
}
}
async def insert_perm(path):
db = DBPools()
async with db.sqlorContext('sage') as sor:
ns = {
'id':getID(),
'path':path
}
await sor.C('permission', ns)
av_folders = [
'/index.ui',
'/user.ui',
'/top.ui',
'/center',
'/bottom.ui',
'/app_panel.ui',
'/bricks',
'/imgs',
'/login.ui',
'/up_login.dspy',
'/public',
'/tmp'
]
async def main():
root = os.path.abspath('../wwwroot')
for f in listFile(root, rescursive=True):
cnt = len(root)
pth = f[cnt:]
print(f'{f=},{root=},{pth=}, {cnt=}')
act = True
for f in av_folders:
if pth.startswith(f):
act = False
break
if act:
await insert_perm(pth)
if __name__ == '__main__':
DBPools(databases)
asyncio.get_event_loop().run_until_complete(main())

48
script/sage.nginx Normal file
View File

@ -0,0 +1,48 @@
server {
autoindex on;
client_max_body_size 20m;
server_name pd4e.com;
index index.html index.htm;
proxy_buffering off;
location ~^/ip$ {
return 200 "$remote_addr";
}
location /wss/ {
proxy_pass http://localhost:9081/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Path 'wss';
}
location / {
add_header Access-Control-Allow-Origin *;
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-Forwarded-Url "$scheme://$host:$server_port$request_uri";
proxy_set_header X-real-ip $remote_addr;
proxy_send_timeout 600s;
proxy_read_timeout 600s;
proxy_pass http://localhost:9180/;
}
listen 10443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/pd4e.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/pd4e.com/privkey.pem; # managed by Certbot
}
server {
if ($host = pd4e.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
}

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);

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