update
This commit is contained in:
parent
0b7c9088ad
commit
5aa0fe4303
91
b/cntoai/create_model_apikey.dspy
Normal file
91
b/cntoai/create_model_apikey.dspy
Normal file
@ -0,0 +1,91 @@
|
||||
async def create_model_apikey(ns={}):
|
||||
import aiohttp
|
||||
|
||||
if not ns.get('userid'):
|
||||
ns['userid'] = await get_user()
|
||||
|
||||
if not ns.get('userid'):
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '未找到用户'
|
||||
}
|
||||
|
||||
# 通过userid从user_api_keys表中查询opc_apikey
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
records = await sor.R('user_api_keys', {'userid': ns['userid'], 'action': 'sync'})
|
||||
if not records:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '未找到用户opc_apikey'
|
||||
}
|
||||
|
||||
already_sync_user_key = records[0]['opc_apikey']
|
||||
already_sync_user_appid = records[0]['appid']
|
||||
|
||||
# 目标URL
|
||||
base_url = 'https://ai.atvoe.com'
|
||||
url = f"{base_url}/dapi/apply_apikey.dspy"
|
||||
|
||||
# 请求头
|
||||
headers = {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": "Bearer %s" % already_sync_user_key
|
||||
}
|
||||
|
||||
# 请求体数据
|
||||
payload = {
|
||||
"appname": "cn_ai_user",
|
||||
"description": "",
|
||||
}
|
||||
|
||||
try:
|
||||
# 创建一个异步会话
|
||||
result_sysnc = None
|
||||
async with aiohttp.ClientSession() as session:
|
||||
# 发送POST请求
|
||||
async with session.post(url, headers=headers, data=json.dumps(payload)) as response:
|
||||
# 打印响应状态码
|
||||
debug(f"create_model_apikey状态码: {response.status}")
|
||||
result_sysnc = await response.json()
|
||||
|
||||
if not result_sysnc.get('status') == 'success':
|
||||
debug(f"create_model_apikey创建模型apikey失败: {result_sysnc}")
|
||||
return {
|
||||
'status': False,
|
||||
'msg': f"创建模型apikey失败: {result_sysnc}"
|
||||
}
|
||||
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
# user_api_keys表格 userid/opc_apikey
|
||||
# 首先判断apikey是否存在
|
||||
apikey = result_sysnc['data'][0].get('apikey')
|
||||
appid = result_sysnc['data'][0].get('appid')
|
||||
secretkey = result_sysnc['data'][0].get('secretkey')
|
||||
|
||||
await sor.C('user_api_keys', {
|
||||
'userid': userid,
|
||||
'opc_apikey': apikey,
|
||||
'appid': appid,
|
||||
'secretkey': secretkey,
|
||||
'action': 'user_self_create',
|
||||
'expire_time': None,
|
||||
})
|
||||
|
||||
debug(f"sync_cn_ai_user用户{payload['user']['id']}同步成功")
|
||||
return {
|
||||
'status': True,
|
||||
'msg': '用户同步成功'
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
debug(f"sync_cn_ai_user{userid}同步用户失败: {e}")
|
||||
return {
|
||||
'status': False,
|
||||
'msg': f"sync_cn_ai_user{userid}同步用户失败: {e}"
|
||||
}
|
||||
|
||||
|
||||
ret = await create_model_apikey(params_kw)
|
||||
return ret
|
||||
85
b/cntoai/get_model_apikey.dspy
Normal file
85
b/cntoai/get_model_apikey.dspy
Normal file
@ -0,0 +1,85 @@
|
||||
async def get_model_apikey(ns={}):
|
||||
import aiohttp
|
||||
|
||||
if not ns.get('userid'):
|
||||
ns['userid'] = await get_user()
|
||||
|
||||
if not ns.get('userid'):
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '未找到用户'
|
||||
}
|
||||
|
||||
# 通过userid从user_api_keys表中查询opc_apikey
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
records = await sor.R('user_api_keys', {'userid': ns['userid'], 'action': 'sync'})
|
||||
if not records:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '未找到用户opc_apikey'
|
||||
}
|
||||
|
||||
already_sync_user_key = records[0]['opc_apikey']
|
||||
already_sync_user_appid = records[0]['appid']
|
||||
|
||||
# 目标URL
|
||||
base_url = 'https://ai.atvoe.com'
|
||||
url = f"{base_url}/dapi/apply_apikey.dspy"
|
||||
|
||||
# 请求头
|
||||
headers = {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": "Bearer %s" % already_sync_user_key
|
||||
}
|
||||
|
||||
try:
|
||||
# 创建一个异步会话
|
||||
result_sysnc = None
|
||||
async with aiohttp.ClientSession() as session:
|
||||
# 发送GET请求
|
||||
async with session.get(url, headers=headers) as response:
|
||||
# 打印响应状态码
|
||||
debug(f"get_model_apikey状态码: {response.status}")
|
||||
result_sysnc = await response.json()
|
||||
|
||||
if not result_sysnc.get('status') == 'success':
|
||||
debug(f"get_model_apikey获取模型apikey失败: {result_sysnc}")
|
||||
return {
|
||||
'status': False,
|
||||
'msg': f"获取模型apikey失败: {result_sysnc}"
|
||||
}
|
||||
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
# user_api_keys表格 userid/opc_apikey
|
||||
# 首先判断apikey是否存在
|
||||
apikey = result_sysnc['data'][0].get('apikey')
|
||||
appid = result_sysnc['data'][0].get('appid')
|
||||
secretkey = result_sysnc['data'][0].get('secretkey')
|
||||
|
||||
await sor.C('user_api_keys', {
|
||||
'userid': userid,
|
||||
'opc_apikey': apikey,
|
||||
'appid': appid,
|
||||
'secretkey': secretkey,
|
||||
'action': 'user_self_create',
|
||||
'expire_time': None,
|
||||
})
|
||||
|
||||
debug(f"sync_cn_ai_user用户{payload['user']['id']}同步成功")
|
||||
return {
|
||||
'status': True,
|
||||
'msg': '用户同步成功'
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
debug(f"sync_cn_ai_user{userid}同步用户失败: {e}")
|
||||
return {
|
||||
'status': False,
|
||||
'msg': f"sync_cn_ai_user{userid}同步用户失败: {e}"
|
||||
}
|
||||
|
||||
|
||||
ret = await get_model_apikey(params_kw)
|
||||
return ret
|
||||
49
b/cntoai/model_management_add.dspy
Normal file
49
b/cntoai/model_management_add.dspy
Normal file
@ -0,0 +1,49 @@
|
||||
# 可写入/更新的字段(不含 id、created_at、updated_at)
|
||||
_MODEL_FIELDS = (
|
||||
'llmid', 'provider', 'model_name', 'display_name', 'model_type',
|
||||
'context_length', 'input_token_price', 'output_token_price',
|
||||
'cache_hit_input_price', 'billing_method', 'billing_unit',
|
||||
'capabilities', 'limitations', 'highlights', 'is_active',
|
||||
'description', 'listing_status',
|
||||
)
|
||||
|
||||
|
||||
def _escape(value):
|
||||
if value is None:
|
||||
return None
|
||||
return str(value).replace("'", "''")
|
||||
|
||||
|
||||
def _build_model_dict(ns, include_listing_status=False):
|
||||
data = {}
|
||||
for field in _MODEL_FIELDS:
|
||||
if field in ns and ns.get(field) is not None and ns.get(field) != '':
|
||||
data[field] = ns.get(field)
|
||||
if include_listing_status and 'listing_status' not in data:
|
||||
data['listing_status'] = ns.get('listing_status', 0)
|
||||
return data
|
||||
|
||||
|
||||
async def model_management_add(ns={}):
|
||||
"""新增模型,默认待上架 listing_status=0"""
|
||||
if not ns.get('provider') or not ns.get('model_name'):
|
||||
return {'status': False, 'msg': 'provider and model_name are required'}
|
||||
|
||||
ns_dic = _build_model_dict(ns, include_listing_status=True)
|
||||
if 'listing_status' not in ns_dic:
|
||||
ns_dic['listing_status'] = 0
|
||||
if 'is_active' not in ns_dic:
|
||||
ns_dic['is_active'] = 1
|
||||
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
try:
|
||||
await sor.C('model_management', ns_dic)
|
||||
return {'status': True, 'msg': 'create model success', 'data': ns_dic}
|
||||
except Exception as e:
|
||||
await sor.rollback()
|
||||
return {'status': False, 'msg': 'create model failed, %s' % str(e)}
|
||||
|
||||
|
||||
ret = await model_management_add(params_kw)
|
||||
return ret
|
||||
47
b/cntoai/model_management_detail.dspy
Normal file
47
b/cntoai/model_management_detail.dspy
Normal file
@ -0,0 +1,47 @@
|
||||
# 可写入/更新的字段(不含 id、created_at、updated_at)
|
||||
_MODEL_FIELDS = (
|
||||
'llmid', 'provider', 'model_name', 'display_name', 'model_type',
|
||||
'context_length', 'input_token_price', 'output_token_price',
|
||||
'cache_hit_input_price', 'billing_method', 'billing_unit',
|
||||
'capabilities', 'limitations', 'highlights', 'is_active',
|
||||
'description', 'listing_status',
|
||||
)
|
||||
|
||||
def _escape(value):
|
||||
if value is None:
|
||||
return None
|
||||
return str(value).replace("'", "''")
|
||||
|
||||
|
||||
def _build_model_dict(ns, include_listing_status=False):
|
||||
data = {}
|
||||
for field in _MODEL_FIELDS:
|
||||
if field in ns and ns.get(field) is not None and ns.get(field) != '':
|
||||
data[field] = ns.get(field)
|
||||
if include_listing_status and 'listing_status' not in data:
|
||||
data['listing_status'] = ns.get('listing_status', 0)
|
||||
return data
|
||||
|
||||
async def model_management_detail(ns={}):
|
||||
"""根据 id 获取单条模型(编辑页回显)"""
|
||||
model_id = ns.get('id')
|
||||
if not model_id:
|
||||
return {'status': False, 'msg': 'id is required'}
|
||||
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
try:
|
||||
find_sql = "SELECT * FROM model_management WHERE id = '%s' LIMIT 1;" % _escape(model_id)
|
||||
result = await sor.sqlExe(find_sql, {})
|
||||
if not result:
|
||||
return {'status': False, 'msg': 'model not found'}
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'get model detail success',
|
||||
'data': result[0],
|
||||
}
|
||||
except Exception as e:
|
||||
return {'status': False, 'msg': 'get model detail failed, %s' % str(e)}
|
||||
|
||||
ret = await model_management_detail(params_kw)
|
||||
return ret
|
||||
25
b/cntoai/model_management_list.dspy
Normal file
25
b/cntoai/model_management_list.dspy
Normal file
@ -0,0 +1,25 @@
|
||||
def _escape(value):
|
||||
if value is None:
|
||||
return None
|
||||
return str(value).replace("'", "''")
|
||||
|
||||
async def model_management_list(ns={}):
|
||||
"""上架:listing_status 置为 1"""
|
||||
model_id = ns.get('id')
|
||||
if not model_id:
|
||||
return {'status': False, 'msg': 'id is required'}
|
||||
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
try:
|
||||
update_sql = """
|
||||
UPDATE model_management SET listing_status = 1 WHERE id = '%s';
|
||||
""" % _escape(model_id)
|
||||
await sor.sqlExe(update_sql, {})
|
||||
return {'status': True, 'msg': 'model listed success'}
|
||||
except Exception as e:
|
||||
await sor.rollback()
|
||||
return {'status': False, 'msg': 'model list failed, %s' % str(e)}
|
||||
|
||||
ret = await model_management_list(params_kw)
|
||||
return ret
|
||||
80
b/cntoai/model_management_search.dspy
Normal file
80
b/cntoai/model_management_search.dspy
Normal file
@ -0,0 +1,80 @@
|
||||
# 可写入/更新的字段(不含 id、created_at、updated_at)
|
||||
_MODEL_FIELDS = (
|
||||
'llmid', 'provider', 'model_name', 'display_name', 'model_type',
|
||||
'context_length', 'input_token_price', 'output_token_price',
|
||||
'cache_hit_input_price', 'billing_method', 'billing_unit',
|
||||
'capabilities', 'limitations', 'highlights', 'is_active',
|
||||
'description', 'listing_status',
|
||||
)
|
||||
|
||||
|
||||
def _escape(value):
|
||||
if value is None:
|
||||
return None
|
||||
return str(value).replace("'", "''")
|
||||
|
||||
|
||||
def _build_model_dict(ns, include_listing_status=False):
|
||||
data = {}
|
||||
for field in _MODEL_FIELDS:
|
||||
if field in ns and ns.get(field) is not None and ns.get(field) != '':
|
||||
data[field] = ns.get(field)
|
||||
if include_listing_status and 'listing_status' not in data:
|
||||
data['listing_status'] = ns.get('listing_status', 0)
|
||||
return data
|
||||
|
||||
async def model_management_search(ns={}):
|
||||
"""
|
||||
分页查询模型列表,支持按 model_name / model_type / provider 筛选。
|
||||
返回模型总数、待上架总数、已上架总数。
|
||||
"""
|
||||
import traceback
|
||||
|
||||
page_size = int(ns.get('page_size', 100))
|
||||
current_page = int(ns.get('current_page', 1))
|
||||
offset = (current_page - 1) * page_size
|
||||
|
||||
conditions = ['1=1']
|
||||
if ns.get('model_name'):
|
||||
model_name = ns.get('model_name')
|
||||
conditions.append("model_name LIKE '%s'" % model_name)
|
||||
if ns.get('model_type'):
|
||||
conditions.append("model_type = '%s'" % _escape(ns.get('model_type')))
|
||||
if ns.get('provider'):
|
||||
conditions.append("provider = '%s'" % _escape(ns.get('provider')))
|
||||
if ns.get('listing_status') is not None and ns.get('listing_status') != '':
|
||||
conditions.append("listing_status = '%s'" % _escape(ns.get('listing_status')))
|
||||
|
||||
where_clause = ' AND '.join(conditions)
|
||||
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
try:
|
||||
stats_sql = """SELECT COUNT(*) AS total_count, SUM(CASE WHEN listing_status = 0 THEN 1 ELSE 0 END) AS pending_count, SUM(CASE WHEN listing_status = 1 THEN 1 ELSE 0 END) AS listed_count FROM model_management;"""
|
||||
stats_li = await sor.sqlExe(stats_sql, {})
|
||||
stats = stats_li[0] if stats_li else {}
|
||||
|
||||
count_sql = """SELECT COUNT(*) AS total_count FROM model_management WHERE %s;""" % where_clause
|
||||
filter_total = (await sor.sqlExe(count_sql, {}))[0]['total_count']
|
||||
|
||||
find_sql = """SELECT * FROM model_management WHERE %s ORDER BY updated_at DESC LIMIT %s OFFSET %s;""" % (where_clause, page_size, offset)
|
||||
model_list = await sor.sqlExe(find_sql, {})
|
||||
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'search model success',
|
||||
'data': {
|
||||
'total_count': stats.get('total_count', 0),
|
||||
'pending_count': int(stats.get('pending_count') or 0),
|
||||
'listed_count': int(stats.get('listed_count') or 0),
|
||||
'filter_total': filter_total,
|
||||
'page_size': page_size,
|
||||
'current_page': current_page,
|
||||
'model_list': model_list,
|
||||
},
|
||||
}
|
||||
except Exception as e:
|
||||
return {'status': False, 'msg': 'search model failed, %s' % traceback.format_exc()}
|
||||
|
||||
ret = await model_management_search(params_kw)
|
||||
return ret
|
||||
25
b/cntoai/model_management_unlist.dspy
Normal file
25
b/cntoai/model_management_unlist.dspy
Normal file
@ -0,0 +1,25 @@
|
||||
def _escape(value):
|
||||
if value is None:
|
||||
return None
|
||||
return str(value).replace("'", "''")
|
||||
|
||||
async def model_management_unlist(ns={}):
|
||||
"""下架:listing_status 置为 0(统计归入待上架)"""
|
||||
model_id = ns.get('id')
|
||||
if not model_id:
|
||||
return {'status': False, 'msg': 'id is required'}
|
||||
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
try:
|
||||
update_sql = """
|
||||
UPDATE model_management SET listing_status = 0 WHERE id = '%s';
|
||||
""" % _escape(model_id)
|
||||
await sor.sqlExe(update_sql, {})
|
||||
return {'status': True, 'msg': 'model unlisted success'}
|
||||
except Exception as e:
|
||||
await sor.rollback()
|
||||
return {'status': False, 'msg': 'model unlist failed, %s' % str(e)}
|
||||
|
||||
ret = await model_management_unlist(params_kw)
|
||||
return ret
|
||||
45
b/cntoai/model_management_update.dspy
Normal file
45
b/cntoai/model_management_update.dspy
Normal file
@ -0,0 +1,45 @@
|
||||
# 可写入/更新的字段(不含 id、created_at、updated_at)
|
||||
_MODEL_FIELDS = (
|
||||
'llmid', 'provider', 'model_name', 'display_name', 'model_type',
|
||||
'context_length', 'input_token_price', 'output_token_price',
|
||||
'cache_hit_input_price', 'billing_method', 'billing_unit',
|
||||
'capabilities', 'limitations', 'highlights', 'is_active',
|
||||
'description', 'listing_status',
|
||||
)
|
||||
|
||||
|
||||
def _escape(value):
|
||||
if value is None:
|
||||
return None
|
||||
return str(value).replace("'", "''")
|
||||
|
||||
|
||||
def _build_model_dict(ns, include_listing_status=False):
|
||||
data = {}
|
||||
for field in _MODEL_FIELDS:
|
||||
if field in ns and ns.get(field) is not None and ns.get(field) != '':
|
||||
data[field] = ns.get(field)
|
||||
if include_listing_status and 'listing_status' not in data:
|
||||
data['listing_status'] = ns.get('listing_status', 0)
|
||||
return data
|
||||
|
||||
async def model_management_update(ns={}):
|
||||
"""编辑模型,id 必传"""
|
||||
model_id = ns.get('id')
|
||||
if not model_id:
|
||||
return {'status': False, 'msg': 'id is required'}
|
||||
|
||||
ns_dic = _build_model_dict(ns)
|
||||
ns_dic['id'] = model_id
|
||||
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
try:
|
||||
await sor.U('model_management', ns_dic)
|
||||
return {'status': True, 'msg': 'update model success'}
|
||||
except Exception as e:
|
||||
await sor.rollback()
|
||||
return {'status': False, 'msg': 'update model failed, %s' % str(e)}
|
||||
|
||||
ret = await model_management_update(params_kw)
|
||||
return ret
|
||||
@ -228,8 +228,15 @@ async def process_user_billing(ns={}):
|
||||
providername = ns.get('providername')
|
||||
productname = ns.get('productname')
|
||||
amount = ns.get('amount')
|
||||
use_saleprotocol = ns.get('use_saleprotocol', False)
|
||||
use_saleprotocol = ns.get('use_saleprotocol', True)
|
||||
quantity = int(ns.get('quantity', 1))
|
||||
|
||||
llmid = ns.get('llmid')
|
||||
if not llmid:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'llmid必传'
|
||||
}
|
||||
|
||||
try:
|
||||
amount = round(float(amount), 2)
|
||||
@ -241,9 +248,22 @@ async def process_user_billing(ns={}):
|
||||
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
provider_list = await sor.R('provider', {'name': providername})
|
||||
if not provider_list:
|
||||
return {'status': False, 'msg': '厂商不存在 %s' % providername}
|
||||
product_li = await sor.R('product', {'providerpid': llmid, 'del_flg': '0'})
|
||||
if not product_li:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '未找到对应产品,请确认'
|
||||
}
|
||||
product = product_li[0]
|
||||
productname = product['name']
|
||||
providerid = product['providerid']
|
||||
providername_list = await sor.R('organization', {'id': providerid})
|
||||
if not providername_list:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '厂商不存在 %s' % providername
|
||||
}
|
||||
providername = providername_list[0]['orgname']
|
||||
|
||||
userid_li = await sor.R('user_api_keys', {'opc_apikey': apikey})
|
||||
if not userid_li:
|
||||
@ -262,12 +282,12 @@ async def process_user_billing(ns={}):
|
||||
return {'status': False, 'msg': '用户所属机构不存在'}
|
||||
|
||||
customerid = org_list[0]['id']
|
||||
product = await _lookup_product(sor, providername, productname)
|
||||
if not product:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '未找到对应产品,请确认 providername/productname 与库中 provider、product 配置一致',
|
||||
}
|
||||
# product = await _lookup_product(sor, providername, productname)
|
||||
# if not product:
|
||||
# return {
|
||||
# 'status': False,
|
||||
# 'msg': '未找到对应产品,请确认 providername/productname 与库中 provider、product 配置一致',
|
||||
# }
|
||||
|
||||
list_price = amount
|
||||
unit_price = amount
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user