first commit

This commit is contained in:
yumoqing 2025-07-16 14:28:41 +08:00
commit f4179ad700
351 changed files with 16518 additions and 0 deletions

14
README.md Normal file
View File

@ -0,0 +1,14 @@
# sage
a llm application, which can select differences llm avaiable in the backend, can interacts with the llm, if click the text widget in message showing area, the will call tts server to translate text inside the widget to audio and speak it out
# 变量定义
为上层应用更方便统一使用llm交互的变量名称
## prompt
指用户输入的文本信息
## llmtext
大模型返回的文本信息
## attachfiles
上传文件集
##

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

0
app/README.md Normal file
View File

174
app/ali_sms_send.py Normal file
View File

@ -0,0 +1,174 @@
# -*- coding: utf-8 -*-
# @Time: 2023/4/23 17:18
"""
环境要求
Python 3
安装 SDK 核心库 OpenAPI 使用pip安装包依赖:
pip install alibabacloud_tea_openapi
pip install alibabacloud_dysmsapi20170525
"""
"""
资源到期预警
[开元云科技] 尊敬的用户 您好您的云服务器账号中将于 2023-01-14 23:59:59 到期, 为避免影响到您的使用, 请及时关注并续费
感谢您的支持
资源到期通知
[开元云科技] 尊敬的用户 您好您的云服务器已于昨天到期, 将于今天中午12:00关停服务 为避免影响到您的使用, 请及时关注并续费
新产品上线通知
[开元云科技] 惠上云更简单新产品火热开售王牌性价比享触底尝鲜价立即抢购: http://...
余额不足预警
[开元云科技] 尊敬的用户您好您的余额还有${amount}$, 为避免影响到您的使用, 请及时关注并续费
"""
import random
import re
import asyncio
# from core.exception import CustomException
from alibabacloud_dysmsapi20170525.client import Client as Dysmsapi20170525Client
from alibabacloud_tea_openapi import models as open_api_models
from alibabacloud_dysmsapi20170525 import models as dysmsapi_20170525_models
from alibabacloud_tea_util import models as util_models
from alibabacloud_tea_util.client import Client as UtilClient
import json
import logging
import datetime
from sqlor.dbpools import DBPools
from appPublic.uniqueID import getID as uuid
class AliyunSMS:
# 返回错误码对应:
doc = "https://help.aliyun.com/document_detail/101346.html"
def __init__(self):
self.access_key = 'LTAI5t5w7xsZgueod6uZ3TCD'
self.access_key_secret = 'n1HttSbQvgEbjvf62Gzl1aagfKyIyS'
self.sms_client = self.create_client(self.access_key,
self.access_key_secret)
self.sign_name = '开元云科技'
self.sms_types = {
"SMS_460770222": send_vcode,
}
async def send(self, stype, type_code, phone, ns) -> dict:
"""
主程序入口异步方式
"""
if isinstance(ns, dict):
ns = json.dumps(ns)
send_sms_request = dysmsapi_20170525_models.SendSmsRequest(
phone_numbers=phone,
sign_name=self.sign_name,
template_code=type_code,
template_param=ns
)
runtime = util_models.RuntimeOptions()
try:
# 复制代码运行请自行打印 API 的返回值
resp = await self.sms_client.send_sms_with_options_async(send_sms_request, runtime)
return await self.__validation(stype=stype, type_code=type_code, ns=ns, phone=phone, resp=resp)
except Exception as error:
print(error)
return {
'status': False,
'msg': error
}
# 如有需要,请打印 error
async def send_vcode(self, phone: str, stype: str, vcode) -> dict:
db = DBPools()
async with db.sqlorContext('kboss') as sor:
type_code_li = await sor.R('sms_template', {'name': stype})
if type_code_li:
type_code = type_code_li[0]['code']
else:
sms_record_log = {
'id': uuid(),
'send_type': stype,
'mobile': phone,
'message': str(vcode),
'send_time': datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
'send_status': 0,
'remark': '无法找到:%s, 请查看字符串是否一致' % stype
}
await sor.C('sms_record', sms_record_log)
return {
'status': False,
'msg': 'can not get type code from sms_template, please check...'
}
return await self.send(stype, type_code, phone, vcode)
async def __validation(self, stype, type_code, ns, phone, resp: dysmsapi_20170525_models.SendSmsResponse) -> dict:
"""
验证结果并返回
"""
db = DBPools()
async with db.sqlorContext('kboss') as sor:
send_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
sms_record_log = {
'id': uuid(),
'send_type': stype,
'mobile': phone,
'message': str(ns),
'send_time': send_time,
'send_status': 1
}
if resp.body.code == "OK":
msg = f'{send_time} {phone} 短信发送成功返回code{resp.body.code}'
print(msg)
sms_record_log['send_status'] = 1
await sor.C('sms_record', sms_record_log)
return {
'status': True,
'msg': msg
}
else:
msg = f'{send_time} {phone} 短信发送失败返回code{resp.body.code},请参考文档:{self.doc}'
print(msg)
sms_record_log['send_status'] = 0
sms_record_log['remark'] = msg
await sor.C('sms_record', sms_record_log)
return {
'status': False,
'msg': msg
}
def create_client(self,
access_key_id: str,
access_key_secret: str,
) -> Dysmsapi20170525Client:
"""
使用AK&SK初始化账号Client
@param access_key_id:
@param access_key_secret:
@return: Client
@throws Exception
"""
config = open_api_models.Config(
# 您的 AccessKey ID,
access_key_id=access_key_id,
# 您的 AccessKey Secret,
access_key_secret=access_key_secret
)
# 访问的域名
config.endpoint = f'dysmsapi.aliyuncs.com'
return Dysmsapi20170525Client(config)
async def send_vcode(phone: str, stype:str, vcode: dict) -> dict:
result = await AliyunSMS().send_vcode(phone, stype, vcode)
return result
# if __name__ == '__main__':
# loop = asyncio.get_event_loop()
# loop.run_until_complete(send_vcode('13801015291', '注册登录验证', {'code': '209898'}))
# loop.run_until_complete(send_vcode('13801015291', '供应商结算提醒', {'name': '中金超算 济南超算'}))
# loop.run_until_complete(send_vcode('13801015291', '到期续费通知', {'time': '2023-10-10'}))
# AliyunSMS("13801015291").main_async()

122
app/alisms.py Normal file
View File

@ -0,0 +1,122 @@
# -*- coding: utf-8 -*-
# @Time: 2023/4/23 17:18
"""
环境要求
Python 3
安装 SDK 核心库 OpenAPI 使用pip安装包依赖:
pip install alibabacloud_tea_openapi
pip install alibabacloud_dysmsapi20170525
"""
"""
资源到期预警
[开元云科技] 尊敬的用户 您好您的云服务器账号中将于 2023-01-14 23:59:59 到期, 为避免影响到您的使用, 请及时关注并续费
感谢您的支持
资源到期通知
[开元云科技] 尊敬的用户 您好您的云服务器已于昨天到期, 将于今天中午12:00关停服务 为避免影响到您的使用, 请及时关注并续费
新产品上线通知
[开元云科技] 惠上云更简单新产品火热开售王牌性价比享触底尝鲜价立即抢购: http://...
余额不足预警
[开元云科技] 尊敬的用户您好您的余额还有${amount}$, 为避免影响到您的使用, 请及时关注并续费
"""
import random
import re
import asyncio
from alibabacloud_dysmsapi20170525.client import Client as Dysmsapi20170525Client
from alibabacloud_tea_openapi import models as open_api_models
from alibabacloud_dysmsapi20170525 import models as dysmsapi_20170525_models
from alibabacloud_tea_util import models as util_models
from alibabacloud_tea_util.client import Client as UtilClient
import json
from sqlor.dbpools import DBPools
from appPublic.uniqueID import getID as uuid
from appPublic.timeUtils import timestampstr
from appPublic.log import info, debug, error, warning, critical, exception
"""
self.access_key = 'LTAI5t5w7xsZgueod6uZ3TCD'
self.access_key_secret = 'n1HttSbQvgEbjvf62Gzl1aagfKyIyS'
"""
class AliSMS:
# 返回错误码对应:
doc = "https://help.aliyun.com/document_detail/101346.html"
def __init__(self, apikey, secretkey):
self.access_key = apikey
self.access_key_secret = secretkey
self.sms_client = self.create_client(self.access_key,
self.access_key_secret)
self.sign_name = '开元云科技'
async def send_validate_code(self, cell_no, vcode):
info(f'{cell_no=}, {vcode=}')
return await self.send('SMS_460770222', cell_no, {'code':vcode})
async def send(self, type_code, phone, ns) -> dict:
"""
主程序入口异步方式
"""
if isinstance(ns, dict):
ns = json.dumps(ns)
send_sms_request = dysmsapi_20170525_models.SendSmsRequest(
phone_numbers=phone,
sign_name=self.sign_name,
template_code=type_code,
template_param=ns
)
runtime = util_models.RuntimeOptions()
try:
# 复制代码运行请自行打印 API 的返回值
resp = await self.sms_client.send_sms_with_options_async(send_sms_request, runtime)
if resp.body.code == "OK":
return {
'status': True
}
return {
'status': False,
'msg':f'{timestampstr()} {phone} 短信发送失败返回code{resp.body.code},请参考文档:{self.doc}'
}
except Exception as error:
print(error)
return {
'status': False,
'msg': error
}
def create_client(self,
access_key_id: str,
access_key_secret: str,
) -> Dysmsapi20170525Client:
"""
使用AK&SK初始化账号Client
@param access_key_id:
@param access_key_secret:
@return: Client
@throws Exception
"""
config = open_api_models.Config(
# 您的 AccessKey ID,
access_key_id=access_key_id,
# 您的 AccessKey Secret,
access_key_secret=access_key_secret
)
# 访问的域名
config.endpoint = f'dysmsapi.aliyuncs.com'
return Dysmsapi20170525Client(config)
if __name__ == '__main__':
async def main(sms):
r = await sms.send('SMS_460770222', '13801015292', {'code':'993344'})
print(f'return {r}')
sms = AliSMS('LTAI5t5w7xsZgueod6uZ3TCD', 'n1HttSbQvgEbjvf62Gzl1aagfKyIyS')
asyncio.get_event_loop().run_until_complete(main(sms))

1
app/const.py Normal file
View File

@ -0,0 +1 @@
DBNAME='sage'

77
app/ext.py Normal file
View File

@ -0,0 +1,77 @@
import json
from traceback import print_exc
from appPublic.log import info
from appPublic.registerfunction import RegisterCoroutine
from sqlor.dbpools import DBPools
from appbase.businessdate import get_business_date
from ahserver.serverenv import ServerEnv
async def load_sysparams(*args, **kw):
info('load_sysparams() called')
db = DBPools()
async with db.sqlorContext('sage') as sor:
r = await sor.sqlExe("select * from sysparams", {})
g = ServerEnv()
x = { i.params_name:i.params_value for i in r }
g.sysparams = x
rf = RegisterCoroutine()
rf.register('ahapp_built', load_sysparams)
rf.register(f'sage:sysparams:C:after', load_sysparams)
rf.register(f'sage:sysparams:D:after', load_sysparams)
rf.register(f'sage:sysparams:U:after', load_sysparams)
def get_module_dbname(mname):
return 'sage'
def UiWindow(title, icon, content, cheight=10, cwidth=15):
return {
"widgettype":"PopupWindow",
"options":{
"author":"cc",
"cwidth":cwidth,
"cheight":cheight,
"title":title,
"content":content,
"icon":icon or entire_url('/bricks/imgs/app.png'),
"movable":True,
"auto_open":True
}
}
def UiError(title="出错", message="出错啦", timeout=5):
return {
"widgettype":"Error",
"options":{
"author":"tr",
"timeout":timeout,
"cwidth":15,
"cheight":10,
"title":title,
"message":message
}
}
def UiMessage(title="消息", message="后台消息", timeout=5):
return {
"widgettype":"Message",
"options":{
"author":"tr",
"timeout":timeout,
"cwidth":15,
"cheight":10,
"title":title,
"message":message
}
}
def get_business_date():
return curDateString()
g = ServerEnv()
g.get_module_dbname = get_module_dbname
g.UiError = UiError
g.UiMessage = UiMessage
g.UiWindow = UiWindow
g.get_business_date = get_business_date

58
app/global_func.py Normal file
View File

@ -0,0 +1,58 @@
from ahserver.serverenv import ServerEnv
from sqlor.dbpools import DBPools
from alisms import AliSMS
def PopError(title='Error', message='Error happened'):
return {
'widgettype':'Error',
'options':{
'title':title,
'timeout':4,
'message':message
}
}
def PopMessage(title='Error', message='Error happened'):
return {
'widgettype':'Message',
'options':{
'title':title,
'timeout':4,
'message':message
}
}
async def get_llm_types():
db = DBPools()
async with db.sqlorContext('sage') as sor:
ns = {
'order':'name'
}
recs = await sor.R('modeltype', ns)
return recs
return []
async def get_llminstances_by_modeltype(mtid):
db = DBPools()
userorgid = await get_userorgid()
async with db.sqlorContext('sage') as sor:
sql = """select a.* from modelinstance a, modelapi b
where
a.modelid = b.modelid and
a.orgid is null and
b.modeltypeid = ${mtid}$
order by a.name
"""
recs = await sor.sqlExe(sql, {'mtid':mtid, 'userorgid':userorgid})
return recs
return []
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
g.get_llminstances_by_modeltype = get_llminstances_by_modeltype

12
app/id2file.py Executable file
View File

@ -0,0 +1,12 @@
from sqlor.dbpools import runSQL
async def getFilenameFromId(idstr:str) -> str:
sql = "select * from kvobjects where id='%s'" % idstr
recs = await runSQL('homedata',sql)
if recs is None:
return None
if len(recs) == 0:
return None
return recs[0].name

28
app/idfile.py Normal file
View File

@ -0,0 +1,28 @@
import os
from PIL import Image, ExifTags
from io import BytesIO
from aiohttp.web_exceptions import (
HTTPException,
HTTPExpectationFailed,
HTTPForbidden,
HTTPMethodNotAllowed,
HTTPNotFound,
)
from aiohttp.web_response import Response, StreamResponse
from appPublic.registerfunction import RegisterFunction
from appPublic.jsonConfig import getConfig
from ahserver.filedownload import file_download
from id2file import getFilenameFromId
def www_abspath(fp):
if fp[0] == '/':
fp = fp[1:]
config = getConfig()
return os.path.join(config.filesroot, fp)
async def idFileDownload(request, kw, *args):
print(f'idFileDownload(): {args=}, {kw=}')
fname = kw.get('path', None)
path = www_abspath(fname)
return await file_download(request,path)

48
app/phonelogin.py Normal file
View File

@ -0,0 +1,48 @@
from rand import randint
from sqlor.dbpools import DBPools
from ahserver.serverenv import ServerEnv
from appPublic.uniqueID import getID
from appPublic.timeUtils import timestampstr
from alisms import AliSMS
from const import DBNAME, VALID_SECONDS
async def gen_validatecode(phone_no){
codes = []
while len(codes) < 6:
v = randint(0,13)
if v >= 10:
continue
codes.append(str(v))
code = ''.join(codes)
sms = AliSMS()
r = sms.send(
ns = {
'id':getID(),
'code':''.join(code),
'timestamp':timestampstr()
}
db = DBPools()
async with db.sqlorContext(DBNAME) as sor:
await sor.C('validatecode', ns)
return ns['id']
return None
async def validate_code(id:str, code:str) -> boolean:
db = DBPools()
sql = """select * from validatecode
where id= ${id}$
and code = ${code}$
and timestamp + ${valid_secords}$ >= ${curr_timestamp}$"""
ns = {
'id':id,
'code':code,
'valid_seconds':VALID_SECONDS,
'curr_timestamp':time.time()
}
async with db.sqlorContext(DBNAME) as sor:
r = await sor.sqlExe(sql, ns.copy())
if len(r) < 1:
return False
return True
return False

153
app/rf.py Normal file
View File

@ -0,0 +1,153 @@
import hashlib
import hmac
import base64
import datetime
import time
import jwt
from appPublic.registerfunction import RegisterFunction
from appPublic.rc4 import password, unpassword
from appPublic.jsonConfig import getConfig
from appPublic.log import debug
rf = RegisterFunction()
def get_module_dbname(modulename):
return 'sage'
rf.register('get_module_dbname', get_module_dbname)
def zhipu_token(uk_dic:dict):
apikey = uk_dic.get('apikey')
exp_seconds = 86400
try:
id, secret = apikey.split(".")
except Exception as e:
raise Exception("invalid apikey", e)
payload = {
"api_key": id,
"exp": int(round(time.time() * 1000)) + exp_seconds * 1000,
"timestamp": int(round(time.time() * 1000)),
}
uk_dic.update({'token':jwt.encode(
payload,
secret,
algorithm="HS256",
headers={"alg": "HS256", "sign_type": "SIGN"},
)})
return uk_dic
rf.register('zhipu_token', zhipu_token)
def shangtang_apikey(uk_dic):
apikey = uk_dic.get("apikey")
secretkey = uk_dic.get("secretkey")
current_time = int(time.time())
headers = {
"alg": "HS256",
"typ": "JWT"
}
payload = {
"iss": apikey,
"exp": current_time + 1800,
"nbf": current_time - 5
}
token = jwt.encode(payload, secretkey, algorithm="HS256", headers=headers)
return {
"apikey": apikey,
"secretkey": secretkey,
"authorization": token
}
rf.register('shangtang_apikey', shangtang_apikey)
# body_str body请求体
def mengzi_apikey(uk_dic):
body_str = uk_dic.get("body_str")
access_key = uk_dic.get("apikey")
access_secret = uk_dic.get("secretkey")
md5 = hashlib.md5(body_str.encode('utf-8')).digest()
content_md5 = base64.b64encode(md5).decode('utf-8')
date_str = datetime.datetime.utcnow().strftime('%a,%d %b %Y %H:%M:%S GMT')
nonce = str(int(datetime.datetime.utcnow().timestamp() * 1000))
string_to_sign = "\n".join([
"POST",
"application/json",
content_md5,
"application/json",
date_str,
"HMAC-SHA256",
nonce,
""
])
signature = base64.b64encode(
hmac.new(access_secret.encode('utf-8'), string_to_sign.encode('utf-8'), hashlib.sha256).digest()).decode('utf-8')
authorization = access_key + ":" + signature
return {
"apikey": access_key,
"secretkey": access_secret,
"content_md5": content_md5,
"date_header": date_str,
"nonce": nonce,
"authorization": authorization,
}
rf.register('mengzi_apikey', mengzi_apikey)
def tiangong_apikey(uk_dic):
app_key = uk_dic.get("apikey")
app_secret = uk_dic.get("secretkey")
# 获取当前的时间戳
timestamp = str(int(time.time()))
# 计算sign
sign_str = app_key + app_secret + timestamp
sign = hashlib.md5(sign_str.encode()).hexdigest()
return {
"apikey": app_key,
"secretkey": app_secret,
"sign": sign,
"timestamp": timestamp,
}
rf.register('tiangong_apikey', tiangong_apikey)
default_pkey='456ft7ygubhinjlmkjiuyg7t65'
def encode_password(ns):
config = getConfig()
pwd = ns.get('password');
pkey = config.password_key or default_pkey
debug(f'encode_password(): {pwd=}, {pkey=}')
crypt = password(pwd, key=pkey)
ns['password'] = crypt
def decode_password(ns):
config.getConfig()
pkey = config.password_key or default_pkey
crypt = ns.get('password')
pwd = unpassword(crypt, key=pkey)
ns['password'] = pwd;
return pwd
# {dbname}:{tablename}:c:before
def cut_b64_image_header(b64img):
debug('cut_b64_image_header() called .........')
if isinstance(b64img, str):
return b64img.split(';base64,')[-1]
if isinstance(b64img, list):
ret = []
for s in b64img:
ret.append(s.split(';base64,')[-1])
return ret
rf.register('cut_b64_image_header', cut_b64_image_header)
# rf.register('password', encode_password)
# rf.register('sage:hostdev:c:before', encode_password)
# rf.register('sage:hostdev:u:before', encode_password)
# rf.register('sage:users:c:before', encode_password)
# rf.register('sage:users:u:before', encode_password)
# rf.register('unpassword', decode_password)

54
app/sage.py Normal file
View File

@ -0,0 +1,54 @@
import os, sys
import argparse
from appPublic.log import MyLogger, info, debug, warning
from appPublic.folderUtils import ProgramPath
from appPublic.jsonConfig import getConfig
from appPublic.registerfunction import RegisterFunction
from ahserver.configuredServer import ConfiguredServer
from ahserver.serverenv import ServerEnv
from rbac.init import load_rbac
from appbase.init import load_appbase
from basellm.init import load_basellm
from filemgr.init import load_filemgr
from uapi.init import load_uapi
from global_func import set_globalvariable
from pf_pay.init import load_pf_pay
from platformbiz.init import load_platformbiz
from accounting.init import load_accounting
from ext import *
from rf import *
__version__ = '0.0.1'
if __name__ == '__main__':
parser = argparse.ArgumentParser(prog="Sage")
parser.add_argument('-w', '--workdir')
parser.add_argument('-p', '--port')
args = parser.parse_args()
workdir = args.workdir or os.getcwd()
p = ProgramPath()
config = getConfig(workdir, NS={'workdir':workdir, 'ProgramPath':p})
if config.logger:
logger = MyLogger(config.logger.name or 'sage',
levelname=config.logger.levelname or 'debug',
logfile=config.logger.logfile or None)
else:
logger = MyLogger('sage', levelname='debug')
info(f'====================sage version={__version__}')
# server = ConfiguredServer(auth_klass=MyAuthAPI, workdir=workdir)
server = ConfiguredServer(workdir=workdir)
rf = RegisterFunction()
set_globalvariable()
load_appbase()
load_rbac()
load_accounting()
load_pf_pay()
load_platformbiz()
load_basellm()
load_filemgr()
load_uapi()
port = args.port or config.website.port or 8080
port = int(port)
server.run(port=port)

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

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

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

3
conf/alipay/private.txt Normal file
View File

@ -0,0 +1,3 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCNEFKfj8jib0cWXyEml7I7cTKyUMAMJmcIfoNNeFcNvp7pNH8cB9QpHvQIOrPTwuyxw591iGWkLCzfKRJc1K594hl558OVrJrB7sM716jyCT1SOqlFcMvuk1Eq3ayMCTR2gyMqdnzaxbSedpPDFQXCXeT5AWDq+IPI1un32Qi35jl0sZu8Ve8KKzaFogig/MkDONShMb593B89p1qRie5HfeHMilcMy4Q1jJ7eo83Q2PfsE0NIuDj6gm38+GcFr3n0h24KeGUANkjU4DhBN2hKwqcpyPFmFio+JWIB8u8dH+8nKS81p8PgqeiKaeJEMWMes1VCeBtICoiyTVgYCpY9AgMBAAECggEALigdIOCnVpAarpNKAZq5UwHjGL2bWV5ncDwVMpAhy/mHfb8TqFRXc20RZG/wz2WElVXxI0ASIfniZNLHk2B0B/SnaWAQezUTHknF0BrsyOWFDxbqtDIISHQjpucJwnhwliaqpwZGLD9srj0WdEq4q7SVa3SsBbZzSJAp1lNJqwJJf7GZUL+5riuSSBBqv+ZExBEwFRlJL8mjOqlISgQQanU5N6ROr5h5vQ3kn2KsXNZdkroEVSA9aeCHn1nDZLE3qCRLhSyOCSmx4YqTO3neFYN50Zo7QoE40LLzSK5SACctp/AWzq12GN9f5iGya6mf+t4pKF/SjZ6ogFZo9QOCcQKBgQDB50aVaBSDsRLXcSFveFPUrOtIzOBmNtuaq96ibqHj+3fGmji6XKIoWN2Yd0Iet6CK7Ph0hKQgljtiaRWSi0cmkqZU4NvZerNWKWxBhnVBkZRqPdyHjEG47qJCaz7wv72S2kQTh3yBap8o/Mtt1M+2QDG0TkHfbjF2mI1q6dnzCwKBgQC6PRwHyArbcqCy48NGTgmxUBJhHIz1zKB/7xX+uPzUyMfvx4bHwwih8bL362zQMlpxwjm28qFQ8/Dh1/baavnrEztaqUChnD6sb2xENP26PNCmxoho71AInVnp0vKEYDw7jYfc5pvl46nlvK8ErbKeohL8gzfew7lit+sUP6lo1wKBgFr9zs+Z0daip7bV7dzDWIN6ycaV7c/JenAwqv8Kb4nunZxjDq/VfHr2iLZdcHe9r+bBoS38eJCaLy/VJDxqg28Ebm1yP3jk7XdHZPeywx+L01uvv+cT2FuSEC6e6SBMugdJyZxoffK1OA8h4cyeiwJ5SVnVR3Az455FpEdBifdVAoGABf5DcaipWMiGjVsxBIksXK1j+gYOLzbHj3ZlMc5ILJzNelTkbHdFRtjdVocX+Fc2e+SxMMb8E/vVq57kjcDVjBARX+iEcO7zQV9Qj51Y8O5WFJfc+euBmtVdeF3WehYSuiPi1GQDblF2PTNmOnNQhTRYAhJC8QNBawDaKsulqv8CgYA1fxxqgYqV3BKh4stzDnczt9bPMrCmWmwo2RkVykJMZv/jtXzefPOE27Q+COp5dxLxRnYnGc55B4COVov0p8y05KABOTvN1IJR5BwJLST+gofZW2X3Zd2swAVO758hbpDukKP1A3BeHFoe40S2udGqgntVsMHQhnWUlnDAH++C5A==
-----END RSA PRIVATE KEY-----

3
conf/alipay/public.txt Normal file
View File

@ -0,0 +1,3 @@
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgD4YlfnWKd4vEHsim6vxLwustbnBBh9IUJwF5rGJ3b7wjYyzMnQZ36Cgf81A685IQ+Ni9GogNDaUWZx9V+qGxZRwaLbktSLnUNwPMudKlUoPyQtqyygU+Bmwg1B+UBzZsz8eG72qOuvu9xNbT72QZqFxzLlo0vzWldijnaPcqukUhTaeIYe1AObI9v3ySAa72GkGCHaSkQqvBLydCJt2mu3zJYhPMKre1oNmQkGYUxLKCwonbABaugOEl7t1vL8mAMlwFg2ihJbYiogGfr2Imt/Y1jy8rftiW41opX1UQ30rgfRYeuEsKvVwuoyqffGHeBSjs53xZkYStYKj0m+8AQIDAQAB
-----END PUBLIC KEY-----

100
conf/config.json Executable file
View File

@ -0,0 +1,100 @@
{
"password_key":"!@#$%^&*(*&^%$QWERTYUIqwertyui234567",
"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"
}
},
"filesroot":"$[workdir]$/files",
"databases":{
"sage":{
"driver":"aiomysql",
"async_mode":true,
"coding":"utf8",
"maxconn":100,
"dbname":"sage",
"kwargs":{
"user":"test",
"db":"sage",
"password":"QUZVcXg5V1p1STMybG5Ia6mX9D0v7+g=",
"host":"db"
}
}
},
"website":{
"paths":[
["$[workdir]$/wwwroot",""]
],
"client_max_size":10000,
"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":"idFileDownload"
}
],
"processors":[
[".ws","ws"],
[".xterm","xterm"],
[".proxy","proxy"],
[".llm", "llm"],
[".llms", "llms"],
[".llma", "llma"],
[".xlsxds","xlsxds"],
[".sqlds","sqlds"],
[".tmpl.js","tmpl"],
[".tmpl.css","tmpl"],
[".html.tmpl","tmpl"],
[".bcrud", "bricks_crud"],
[".tmpl","tmpl"],
[".app","app"],
[".bui","bui"],
[".ui","bui"],
[".dspy","dspy"],
[".md","md"]
],
"rsakey":{
"privatekey":"$[workdir]$/conf/rsa_private_key.pem",
"publickey":"$[workdir]$/conf/rsa_public_key.pem"
},
"session_max_time":3000,
"session_issue_time":2500,
"session_redis":{
"url":"redis://127.0.0.1:6379"
}
},
"langMapping":{
"zh-Hans-CN":"zh-cn",
"zh-CN":"zh-cn",
"en-us":"en",
"en-US":"en"
}
}

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.

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

0
files/README.md Normal file
View File

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

0
i18n/README.md Normal file
View File

9
initln Executable file
View File

@ -0,0 +1,9 @@
#!/usr/bin/env bash
for m in accounting appbase basellm filemgr msp platformbiz rag rbac uapi
do
cd ~/py/$m/json
sh ./build.sh
cd ~/py/sage/wwwroot
ln -s ~/py/$m/wwwroot $m
done

17
json/acc_balance.json Normal file
View File

@ -0,0 +1,17 @@
{
"models_dir": "${HOME}$/py/accounting/models",
"output_dir": "${HOME}$/py/sage/wwwroot/_a/acc_balance",
"dbname": "sage",
"tblname": "acc_balance",
"params": {
"browserfields": {
"exclouded": ["id"],
"alters": {}
},
"editexclouded": [
"id"
],
"record_toolbar": null,
"content_view": null
}
}

17
json/acc_detail.json Normal file
View File

@ -0,0 +1,17 @@
{
"models_dir": "${HOME}$/py/accounting/models",
"output_dir": "${HOME}$/py/sage/wwwroot/_a/acc_detail",
"dbname": "sage",
"tblname": "acc_detail",
"params": {
"browserfields": {
"exclouded": ["id"],
"alters": {}
},
"editexclouded": [
"id"
],
"record_toolbar": null,
"content_view": null
}
}

17
json/account.json Normal file
View File

@ -0,0 +1,17 @@
{
"models_dir": "${HOME}$/py/accounting/models",
"output_dir": "${HOME}$/py/sage/wwwroot/_a/account",
"dbname": "sage",
"tblname": "account",
"params": {
"browserfields": {
"exclouded": ["id"],
"alters": {}
},
"editexclouded": [
"id"
],
"record_toolbar": null,
"content_view": null
}
}

28
json/account_config.json Normal file
View File

@ -0,0 +1,28 @@
{
"models_dir": "${HOME}$/py/accounting/models",
"output_dir": "${HOME}$/py/accounting/wwwroot/account_config",
"dbname": "sage",
"tblname": "account_config",
"params": {
"sortby":[
"partytype",
"subjectname"
],
"browserfields": {
"exclouded": ["id", "subjectid"],
"alters": {
"partytype":{
"cwidth":8
},
"subjectname":{
"cwidth":12
}
}
},
"editexclouded": [
"id"
],
"record_toolbar": null,
"content_view": null
}
}

View File

@ -0,0 +1,40 @@
{
"models_dir": "${HOME}$/py/accounting/models",
"output_dir": "${HOME}$/py/sage/wwwroot/_a/accounting_config",
"dbname": "sage",
"tblname": "accounting_config",
"params": {
"browserfields": {
"exclouded": ["id"],
"alters":{
"action":{
"cwidth":12
},
"specstr":{
"cwidth":6
},
"accounting_orgtype":{
"cwidth":12
},
"accounting_dir":{
"cwidth":3
},
"orgtype":{
"cwidth":6
},
"subjectname":{
"cwidth":10
},
"amt_pattern":{
"cwidth":20
}
}
},
"sortby":["action", "accounting_orgtype", "accounting_dir", "orgtype" ],
"editexclouded": [
"id"
],
"record_toolbar": null,
"content_view": null
}
}

17
json/accounting_log.json Normal file
View File

@ -0,0 +1,17 @@
{
"models_dir": "${HOME}$/py/accounting/models",
"output_dir": "${HOME}$/py/sage/wwwroot/_a/accounting_log",
"dbname": "sage",
"tblname": "accounting_log",
"params": {
"browserfields": {
"exclouded": [],
"alters": {}
},
"editexclouded": [
"id"
],
"record_toolbar": null,
"content_view": null
}
}

17
json/apidata.json Normal file
View File

@ -0,0 +1,17 @@
{
"models_dir": "${HOME}$/py/sage/models",
"output_dir": "${HOME}$/py/sage/wwwroot/_a/apidata",
"dbname": "sage",
"tblname": "apidata",
"params": {
"browserfields": {
"excloud": [],
"cwidth": {}
},
"editexclouded": [
"id"
],
"record_toolbar": null,
"content_view": null
}
}

17
json/apiparams.json Normal file
View File

@ -0,0 +1,17 @@
{
"models_dir": "${HOME}$/py/sage/models",
"output_dir": "${HOME}$/py/sage/wwwroot/_a/apiparams",
"dbname": "sage",
"tblname": "apiparams",
"params": {
"browserfields": {
"excloud": [],
"cwidth": {}
},
"editexclouded": [
"id"
],
"record_toolbar": null,
"content_view": null
}
}

24
json/appcodes.json Normal file
View File

@ -0,0 +1,24 @@
{
"models_dir": "${HOME}$/py/sage/models",
"output_dir": "${HOME}$/py/sage/wwwroot/_a/appcodes",
"dbname": "sage",
"tblname": "appcodes",
"params": {
"browserfields": {
"exclouded": [],
"alters": {}
},
"editexclouded": [
],
"record_toolbar": null,
"content_view": {
"widgettype":"urlwidget",
"options":{
"url":"{{entire_url('../appcodes_kv')}}",
"params":{
"parentid":"${id}"
}
}
}
}
}

22
json/appcodes_kv.json Normal file
View File

@ -0,0 +1,22 @@
{
"models_dir": "${HOME}$/py/sage/models",
"output_dir": "${HOME}$/py/sage/wwwroot/_a/appcodes_kv",
"dbname": "sage",
"tblname": "appcodes_kv",
"params": {
"sortby":"k",
"notitle":true,
"browserfields": {
"exclouded": [
"id",
"parentid"
],
"alters": {}
},
"editexclouded": [
"id", "parentid"
],
"record_toolbar": null,
"content_view": null
}
}

17
json/bill.json Normal file
View File

@ -0,0 +1,17 @@
{
"models_dir": "${HOME}$/py/accounting/models",
"output_dir": "${HOME}$/py/sage/wwwroot/_a/bill",
"dbname": "sage",
"tblname": "bill",
"params": {
"browserfields": {
"exclouded": [],
"alters": {}
},
"editexclouded": [
"id"
],
"record_toolbar": null,
"content_view": null
}
}

17
json/bill_detail.json Normal file
View File

@ -0,0 +1,17 @@
{
"models_dir": "${HOME}$/py/accounting/models",
"output_dir": "${HOME}$/py/sage/wwwroot/_a/bill_detail",
"dbname": "sage",
"tblname": "bill_detail",
"params": {
"browserfields": {
"exclouded": [],
"alters": {}
},
"editexclouded": [
"id"
],
"record_toolbar": null,
"content_view": null
}
}

47
json/feelog.json Normal file
View File

@ -0,0 +1,47 @@
{
"models_dir": "${HOME}$/py/sage/models",
"output_dir": "${HOME}$/py/sage/wwwroot/fee/feelog",
"dbname": "sage",
"tblname": "feelog",
"params": {
"sortby":"transtime desc",
"noedit":true,
"browserfields": {
"exclouded": ["id"],
"alters":{
"transtime":{
"cwidth":14
},
"modelinstanceid":{
"cwidth":10
},
"modeltypeid":{
"cwidth":5
},
"customerid":{
"cwidth":20
},
"userid":{
"cwidth":4
},
"pricing_mode":{
"cwidth":5
},
"resp_time":{
"cwidth":6
},
"finish_time":{
"cwidth":6
},
"estimate":{
"cwidth":4
}
}
},
"editexclouded": [
"id"
],
"record_toolbar": null,
"content_view": null
}
}

17
json/httpapi.json Normal file
View File

@ -0,0 +1,17 @@
{
"models_dir": "${HOME}$/py/sage/models",
"output_dir": "${HOME}$/py/sage/wwwroot/_a/httpapi",
"dbname": "sage",
"tblname": "httpapi",
"params": {
"browserfields": {
"exclouded": ["id"],
"cwidth": {}
},
"editexclouded": [
"id"
],
"record_toolbar": null,
"content_view": null
}
}

17
json/minimax_acc.json Normal file
View File

@ -0,0 +1,17 @@
{
"models_dir": "${HOME}$/py/sage/models",
"output_dir": "${HOME}$/py/sage/wwwroot/_a/minimax_acc",
"dbname": "sage",
"tblname": "minimax_acc",
"params": {
"browserfields": {
"excloud": [],
"cwidth": {}
},
"editexclouded": [
"id"
],
"record_toolbar": null,
"content_view": null
}
}

17
json/minimax_bill.json Normal file
View File

@ -0,0 +1,17 @@
{
"models_dir": "${HOME}$/py/sage/models",
"output_dir": "${HOME}$/py/sage/wwwroot/_a/minimax_bill",
"dbname": "sage",
"tblname": "minimax_bill",
"params": {
"browserfields": {
"excloud": [],
"cwidth": {}
},
"editexclouded": [
"id"
],
"record_toolbar": null,
"content_view": null
}
}

18
json/modelapi.json Normal file
View File

@ -0,0 +1,18 @@
{
"models_dir": "${HOME}$/py/sage/models",
"output_dir": "${HOME}$/py/sage/wwwroot/_a/modelapi",
"dbname": "sage",
"tblname": "modelapi",
"params": {
"browserfields": {
"exclouded": ["id"],
"cwidth": {}
},
"editexclouded": [
"id",
"modelid"
],
"record_toolbar": null,
"content_view": null
}
}

20
json/modelinstance.json Normal file
View File

@ -0,0 +1,20 @@
{
"models_dir": "${HOME}$/py/sage/models",
"output_dir": "${HOME}$/py/sage/wwwroot/_a/modelinstance",
"dbname": "sage",
"tblname": "modelinstance",
"params": {
"logined_userorgid":"ownerid",
"sortby":"modelid_text",
"browserfields": {
"exclouded": ["id"],
"cwidth": {}
},
"editexclouded": [
"id",
"ownerid"
],
"record_toolbar": null,
"content_view": null
}
}

17
json/modeliodata.json Normal file
View File

@ -0,0 +1,17 @@
{
"models_dir": "${HOME}$/py/sage/models",
"output_dir": "${HOME}$/py/sage/wwwroot/_a/modeliodata",
"dbname": "sage",
"tblname": "modeliodata",
"params": {
"browserfields": {
"excloud": [],
"cwidth": {}
},
"editexclouded": [
"id"
],
"record_toolbar": null,
"content_view": null
}
}

17
json/modelpricing.json Normal file
View File

@ -0,0 +1,17 @@
{
"models_dir": "${HOME}$/py/sage/models",
"output_dir": "${HOME}$/py/sage/wwwroot/_a/modelpricing",
"dbname": "sage",
"tblname": "modelpricing",
"params": {
"browserfields": {
"excloud": [],
"cwidth": {}
},
"editexclouded": [
"id"
],
"record_toolbar": null,
"content_view": null
}
}

17
json/modelprovider.json Normal file
View File

@ -0,0 +1,17 @@
{
"models_dir": "${HOME}$/py/sage/models",
"output_dir": "${HOME}$/py/sage/wwwroot/_a/modelprovider",
"dbname": "sage",
"tblname": "modelprovider",
"params": {
"browserfields": {
"excloud": [],
"cwidth": {}
},
"editexclouded": [
"id"
],
"record_toolbar": null,
"content_view": null
}
}

32
json/models.json Normal file
View File

@ -0,0 +1,32 @@
{
"models_dir": "${HOME}$/py/sage/models",
"output_dir": "${HOME}$/py/sage/wwwroot/_a/models",
"dbname": "sage",
"tblname": "models",
"title":"模型世界",
"params": {
"sortby":"name",
"browserfields": {
"exclouded": ["id"],
"cwidth": {}
},
"editexclouded": [
"id"
],
"subtables":[
{
"field":"modelid",
"title":"模型API",
"url":"../modelapi",
"subtable":"modelapi"
},
{
"field":"modelid",
"title":"模型定价",
"url":"../modelpricing",
"subtable":"modelpricing"
}
],
"record_toolbar": null
}
}

15
json/modeltype.json Normal file
View File

@ -0,0 +1,15 @@
{
"models_dir": "${HOME}$/py/sage/models",
"output_dir": "${HOME}$/py/sage/wwwroot/_a/modeltype",
"dbname": "sage",
"tblname": "modeltype",
"params": {
"sortby":"id",
"browserfields": {
"excloud": [],
"cwidth": {}
},
"editexclouded": [
]
}
}

17
json/modeltypein.json Normal file
View File

@ -0,0 +1,17 @@
{
"models_dir": "${HOME}$/py/sage/models",
"output_dir": "${HOME}$/py/sage/wwwroot/_a/modeltypein",
"dbname": "sage",
"tblname": "modeltypein",
"params": {
"browserfields": {
"excloud": [],
"cwidth": {}
},
"editexclouded": [
"id"
],
"record_toolbar": null,
"content_view": null
}
}

17
json/modeltypeout.json Normal file
View File

@ -0,0 +1,17 @@
{
"models_dir": "${HOME}$/py/sage/models",
"output_dir": "${HOME}$/py/sage/wwwroot/_a/modeltypeout",
"dbname": "sage",
"tblname": "modeltypeout",
"params": {
"browserfields": {
"excloud": [],
"cwidth": {}
},
"editexclouded": [
"id"
],
"record_toolbar": null,
"content_view": null
}
}

17
json/org_roles.json Normal file
View File

@ -0,0 +1,17 @@
{
"models_dir": "${HOME}$/py/sage/models",
"output_dir": "${HOME}$/py/sage/wwwroot/_a/org_roles",
"dbname": "sage",
"tblname": "org_roles",
"params": {
"browserfields": {
"excloud": [],
"cwidth": {}
},
"editexclouded": [
"id"
],
"record_toolbar": null,
"content_view": null
}
}

25
json/organization.json Normal file
View File

@ -0,0 +1,25 @@
{
"models_dir": "${HOME}$/py/sage/models",
"output_dir": "${HOME}$/py/sage/wwwroot/_a/organization",
"dbname": "sage",
"tblname": "organization",
"params": {
"browserfields": {
"exclouded": ["id"],
"cwidth": {}
},
"editexclouded": [
"id"
],
"record_toolbar": null,
"content_view": {
"widgettype":"urlwidget",
"options":{
"params":{
"orgid":"${id}"
},
"url":"{{entire_url('../orgtypes')}}"
}
}
}
}

16
json/orgtype.json Normal file
View File

@ -0,0 +1,16 @@
{
"models_dir": "${HOME}$/py/sage/models",
"output_dir": "${HOME}$/py/sage/wwwroot/_a/orgtype",
"dbname": "sage",
"tblname": "orgtype",
"params": {
"browserfields": {
"excloud": ["id" ],
"cwidth": {}
},
"editexclouded": [
"id"
],
"record_toolbar": null
}
}

16
json/orgtypes.json Normal file
View File

@ -0,0 +1,16 @@
{
"models_dir": "${HOME}$/py/sage/models",
"output_dir": "${HOME}$/py/sage/wwwroot/_a/orgtypes",
"dbname": "sage",
"tblname": "orgtypes",
"params": {
"browserfields": {
"exclouded": ["id" ],
"cwidth": {}
},
"editexclouded": [
"id", "orgid"
],
"record_toolbar": null
}
}

17
json/permission.json Normal file
View File

@ -0,0 +1,17 @@
{
"models_dir": "${HOME}$/py/sage/models",
"output_dir": "${HOME}$/py/sage/wwwroot/_a/permission",
"dbname": "sage",
"tblname": "permission",
"params": {
"browserfields": {
"excloud": [],
"cwidth": {}
},
"editexclouded": [
"id"
],
"record_toolbar": null,
"content_view": null
}
}

17
json/role.json Normal file
View File

@ -0,0 +1,17 @@
{
"models_dir": "${HOME}$/py/sage/models",
"output_dir": "${HOME}$/py/sage/wwwroot/_a/role",
"dbname": "sage",
"tblname": "role",
"params": {
"browserfields": {
"excloud": [],
"cwidth": {}
},
"editexclouded": [
"id"
],
"record_toolbar": null,
"content_view": null
}
}

17
json/rolepermission.json Normal file
View File

@ -0,0 +1,17 @@
{
"models_dir": "${HOME}$/py/sage/models",
"output_dir": "${HOME}$/py/sage/wwwroot/_a/rolepermission",
"dbname": "sage",
"tblname": "rolepermission",
"params": {
"browserfields": {
"excloud": [],
"cwidth": {}
},
"editexclouded": [
"id"
],
"record_toolbar": null,
"content_view": null
}
}

31
json/subject.json Normal file
View File

@ -0,0 +1,31 @@
{
"models_dir": "${HOME}$/py/accounting/models",
"output_dir": "${HOME}$/py/sage/wwwroot/_a/subject",
"dbname": "sage",
"tblname": "subject",
"params": {
"sortby":[
"subjecttype",
"name"
],
"browserfields": {
"exclouded": ["id"],
"alters": {
"balance_side":{
"cwidth":4
},
"subjecttype":{
"cwidth":4
},
"name":{
"uitype":"str"
}
}
},
"editexclouded": [
"id"
],
"record_toolbar": null,
"content_view": null
}
}

5
json/t.sh Normal file
View File

@ -0,0 +1,5 @@
for fn in *.json
do
sed 's/\/Users\/ymq/\$\{HOME\}\$/g' -i $fn
done

17
json/token_usgae.json Normal file
View File

@ -0,0 +1,17 @@
{
"models_dir": "${HOME}$/py/sage/models",
"output_dir": "${HOME}$/py/sage/wwwroot/_a/token_usgae",
"dbname": "sage",
"tblname": "token_usgae",
"params": {
"browserfields": {
"excloud": [],
"cwidth": {}
},
"editexclouded": [
"id"
],
"record_toolbar": null,
"content_view": null
}
}

20
json/userapikey.json Normal file
View File

@ -0,0 +1,20 @@
{
"models_dir": "${HOME}$/py/sage/models",
"output_dir": "${HOME}$/py/sage/wwwroot/_a/userapikey",
"dbname": "sage",
"tblname": "userapikey",
"params": {
"logined_userorgid":"ownerid",
"browserfields": {
"excloud": [
"id", "ownerid"
],
"cwidth": {}
},
"editexclouded": [
"id", "ownerid"
],
"record_toolbar": null,
"content_view": null
}
}

17
json/userdepartment.json Normal file
View File

@ -0,0 +1,17 @@
{
"models_dir": "${HOME}$/py/sage/models",
"output_dir": "${HOME}$/py/sage/wwwroot/_a/userdepartment",
"dbname": "sage",
"tblname": "userdepartment",
"params": {
"browserfields": {
"excloud": [],
"cwidth": {}
},
"editexclouded": [
"id"
],
"record_toolbar": null,
"content_view": null
}
}

23
json/userrole.json Normal file
View File

@ -0,0 +1,23 @@
{
"models_dir": "${HOME}$/py/sage/models",
"output_dir": "${HOME}$/py/sage/wwwroot/_a/userrole",
"dbname": "sage",
"tblname": "userrole",
"params": {
"relation":{
"outter_field":"roleid",
"param_field":"userid"
},
"binds":[],
"browserfields": {
"excloud": [],
"alters":{
}
},
"editexclouded": [
"id"
],
"record_toolbar": null,
"content_view": null
}
}

25
json/users.json Normal file
View File

@ -0,0 +1,25 @@
{
"models_dir": "${HOME}$/py/sage/models",
"output_dir": "${HOME}$/py/sage/wwwroot/_a/users",
"dbname": "sage",
"tblname": "users",
"params": {
"browserfields": {
"excloud": [],
"cwidth": {}
},
"editexclouded": [
"id"
],
"record_toolbar": null,
"content_view": {
"widgettype":"urlwidget",
"options":{
"url":"{{entire_url('../userrole1')}}",
"params":{
"userid":"${id}"
}
}
}
}
}

19
json/xterm.json Normal file
View File

@ -0,0 +1,19 @@
{
"models_dir": "${HOME}$/py/sage/models",
"output_dir": "${HOME}$/py/sage/wwwroot/_a/xterm",
"dbname": "sage",
"tblname": "xterm",
"params": {
"logined_userid":"ownerid",
"browserfields": {
"exclouded": ["id", "ownerid"],
"cwidth": {}
},
"editexclouded": [
"id",
"ownerid"
],
"record_toolbar": null,
"content_view": null
}
}

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.

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