Compare commits

...

5 Commits

Author SHA1 Message Date
ping
f2b432df51 updte 2026-07-21 17:15:53 +08:00
ping
4af3ff5000 update 2026-07-21 16:13:44 +08:00
ping
35d7fa08ea llm表格 2026-07-21 16:06:04 +08:00
ping
d7e2875375 添加供应商修改 2026-07-21 15:23:56 +08:00
ping
144b3afbc8 update 2026-07-21 11:19:09 +08:00
4 changed files with 271 additions and 14 deletions

View File

@ -35,6 +35,8 @@ async def get_user_balance(ns={}):
}
orgid = await sor.R('organization', {'id': user[0]['orgid']})
balance = await getCustomerBalance(sor, orgid[0]['id'])
ns['balance'] = balance
debug(ns)
return {
'status': 'ok',
'balance': balance

View File

@ -1,5 +1,11 @@
async def sync_model_to_llm(ns={}):
import aiohttp
async def get_sync_orgid(sor):
if ns.get('orgid'):
return ns.get('orgid')
user_li = await sor.R('users', {'id': await get_user()})
return user_li[0].get('orgid') if user_li else ''
# 从数据库读取domain和Bearer token
db = DBPools()
@ -13,6 +19,13 @@ async def sync_model_to_llm(ns={}):
}
domain = domain_li[0]['pvalue']
bearer_token = user_key[0]['pvalue']
# sync_orgid = await get_sync_orgid(sor)
sync_orgid = "mIWUHBeeDM8mwAFPIQ8pS" # 固定写
if not sync_orgid:
return {
'status': False,
'msg': '未找到当前用户所属机构'
}
url = f"{domain}/llmage/list_llms"
header = {
@ -33,29 +46,103 @@ async def sync_model_to_llm(ns={}):
db = DBPools()
async with db.sqlorContext('kboss') as sor:
new_llms_count = 0
sync_products_count = 0
new_llms_list = []
for category_list in result:
for item in category_list.get('llms', []):
provider_orgcode = item.get('providerid')
provider_name = item.get('provider_name') or item.get('providerid') or '模型供应商'
if not provider_orgcode:
continue
provider_ns = {
'orgid': sync_orgid,
'orgcode': provider_orgcode,
'orgname': provider_name,
'name': provider_name,
'description': provider_name,
'appid': item.get('upappid') or '',
'providerkey': provider_orgcode,
'state': '1',
'start_date': '2026-07-01',
'end_date': '9999-12-31',
'settle_flowid': '0',
'salemode': '0',
'settle_mode': '3',
'settle_datep': 'M00',
'contactor': '连战',
'contactor_phone': '13800138000',
'emailaddress': 'lianzhan@cntoai.com',
'address': '北京市海淀区',
'org_type': '4'
}
provider_res = await path_call('../provider/providerAdd.dspy', provider_ns)
if not provider_res.get('status'):
return {
'status': False,
'msg': '供应商同步失败, %s, %s' % (provider_name, provider_res.get('msg'))
}
provider_data = provider_res.get('data') or {}
provider_orgid = provider_data.get('provider_orgid') or provider_data.get('orgid')
protocolid = provider_data.get('protocolid')
if not provider_orgid or not protocolid:
return {
'status': False,
'msg': '供应商同步失败, 未返回provider_orgid或protocolid, %s' % provider_name
}
product_ns = {
'providerid': provider_orgid,
'providerpid': item.get('id'),
'protocolid': protocolid,
'name': item.get('name'),
'product_code': item.get('model'),
'reseller_orgid': sync_orgid,
'label': item.get('catelogname') or category_list.get('catelogname'),
'classify': 'A',
'ptype': '21',
'unit': 'hour',
'discount': '1',
'product_area': '北京'
}
product_res = await path_call('../product/productAdd.dspy', product_ns)
if not product_res.get('status'):
return {
'status': False,
'msg': '产品同步失败, %s, %s' % (item.get('name'), product_res.get('msg'))
}
sync_products_count += 1
# 查找数据库中是否已经存在,不存在就插入
exist_llm = await sor.R('llm', {'model': item.get('model')})
if exist_llm:
# 更新
exits_id = exist_llm[0].get('id')
await sor.U('llm', {'id': exits_id}, item)
continue
new_llms = {
'id': item.get('id'),
'name': item.get('name'),
'model': item.get('model'),
'description': item.get('description'),
'llmcatelogid': item.get('catelog_id') or item.get('catelogid'),
'iconid': item.get('iconid'),
'upappid': item.get('upappid'),
'apiname': item.get('apiname'),
'providerid': item.get('providerid'),
'ownerid': item.get('ownerid') or '0',
'ownerid': item.get('ownerid'),
'enabled_date': item.get('enabled_date'),
'expired_date': item.get('expired_date'),
'query_apiname': item.get('query_apiname') or '',
'min_balance': item.get('min_balance'),
'status': item.get('status'),
'catelogname': item.get('catelogname'),
'catelog_id': item.get('catelog_id'),
'apiname': item.get('apiname'),
'query_apiname': item.get('query_apiname'),
'query_period': item.get('query_period'),
'ppid': item.get('ppid'),
'provider_name': item.get('provider_name'),
'pricing_display': item.get('pricing_display'),
'provider_iconurl': item.get('provider_iconurl')
}
new_llms_count += 1
new_llms_list.append(new_llms.get('model'))
@ -63,7 +150,7 @@ async def sync_model_to_llm(ns={}):
return {
'status': True,
'msg': f"sync_llm_list同步模型成功共插入{new_llms_count}个模型,模型列表: {new_llms_list}"
'msg': f"sync_llm_list同步模型成功同步{sync_products_count}个产品,共插入{new_llms_count}个模型,模型列表: {new_llms_list}"
}
except Exception as e:

145
b/llm.sql Normal file
View File

@ -0,0 +1,145 @@
# 创建表格命令
CREATE TABLE llm (
id VARCHAR(64) NOT NULL COMMENT '唯一标识',
name VARCHAR(50) NOT NULL COMMENT '模型名称',
model VARCHAR(50) NOT NULL COMMENT '模型代号',
description TEXT COMMENT '模型描述',
iconid VARCHAR(50) COMMENT '图标标识',
upappid VARCHAR(50) COMMENT '上层应用ID',
providerid VARCHAR(64) COMMENT '供应商ID',
ownerid VARCHAR(20) DEFAULT '0' COMMENT '所有者ID',
enabled_date DATE COMMENT '启用日期',
expired_date DATE COMMENT '过期日期',
min_balance INT DEFAULT 0 COMMENT '最低余额要求(元)',
status VARCHAR(20) COMMENT '状态如published',
catelogname VARCHAR(50) COMMENT '目录名称(如文生视频)',
catelog_id VARCHAR(20) COMMENT '目录ID',
apiname VARCHAR(50) COMMENT 'API名称',
query_apiname VARCHAR(50) COMMENT '查询API名称',
query_period INT COMMENT '查询周期(秒)',
ppid VARCHAR(64) COMMENT '定价计划ID',
provider_name VARCHAR(100) COMMENT '供应商名称',
pricing_display TEXT COMMENT '定价显示文本',
provider_iconurl VARCHAR(255) COMMENT '供应商图标URL',
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='LLM模型信息表';
# 厂商返回的部分数据示例
[
{
"catelogid": "2i2v",
"catelogname": "首尾帧生视频",
"llms": [
{
"id": "r0ill7L0s6PtBS8mkmg-7",
"name": "viduq3-pro",
"model": "viduq3-pro",
"description": "vidu文生视频,viduq3-pro模型",
"iconid": "vidu",
"upappid": "vidu",
"providerid": "Bu3Z6OXANehbkD6OK5NJb",
"ownerid": "0",
"enabled_date": "2026-01-01",
"expired_date": "9999-12-31",
"min_balance": 10,
"status": "published",
"catelogname": "首尾帧生视频",
"catelog_id": "2i2v",
"apiname": "2i2v",
"query_apiname": "taskStatus",
"query_period": 30,
"ppid": "sF2gcl7UeANKtnZv8hfvL",
"provider_name": "北京生数科技有限公司",
"pricing_display": " - duration: 0.56 元/秒 ",
"provider_iconurl": "https://token.opencomputing.cn/appbase/show_icon.dspy?id=vidu"
}
]
},
{
"catelogid": "asr",
"catelogname": "语音识别",
"llms": [
{
"id": "9glv3S-JSzxholxAblU14",
"name": "qwen3-asr-flash",
"model": "qwen3-asr-flash",
"description": "通义千问系列的录音文件识",
"iconid": "qwen",
"upappid": "tongyi-wan",
"providerid": "6fadgewjraOyvxC_EkHou",
"ownerid": "0",
"enabled_date": "2025-12-01",
"expired_date": "9999-12-31",
"min_balance": 10,
"status": "published",
"catelogname": "语音识别",
"catelog_id": "asr",
"apiname": "short_asr",
"query_apiname": null,
"query_period": null,
"ppid": "16pwEsQeHiOrxC0O6A2j6",
"provider_name": "阿里云",
"provider_iconurl": "https://token.opencomputing.cn/appbase/show_icon.dspy?id=qwen"
}
]
},
{
"catelogid": "digital_human",
"catelogname": "数字人",
"llms": [
{
"id": "KOsAo6YjTdU0KG7_sKUJF",
"name": "wan2.2-s2v",
"model": "wan2.2-s2v",
"description": "模型wan2.2-s2v输入音频和照片用照片中的人生成数字人",
"iconid": "qwen",
"upappid": "tongyi-wan",
"providerid": "6fadgewjraOyvxC_EkHou",
"ownerid": "0",
"enabled_date": "2025-12-19",
"expired_date": "9999-12-31",
"min_balance": 10,
"status": "published",
"catelogname": "数字人",
"catelog_id": "digital_human",
"apiname": "avator",
"query_apiname": "avatorstatus",
"query_period": 10,
"ppid": "0B6aldoAej1PpZ4ydtrEZ",
"provider_name": "阿里云",
"pricing_display": " - duration: 0.5 元/秒 [分辨率=480P]\n - duration: 0.9 元/秒 [分辨率=720P]",
"provider_iconurl": "https://token.opencomputing.cn/appbase/show_icon.dspy?id=qwen"
}
]
},
{
"catelogid": "i2v",
"catelogname": "图生视频",
"llms": [
{
"id": "7y7kfYM0Xasizyi37WvAZ",
"name": "happyhorse-1.0-i2v",
"model": "happyhorse-1.0-i2v",
"description": "HappyHorse图生视频模型以首帧图片为基础支持通过文本描述进行引导生成物理真实、运动流畅的视频。",
"iconid": "qwen",
"upappid": "tongyi-wan",
"providerid": "6fadgewjraOyvxC_EkHou",
"ownerid": "0",
"enabled_date": "2026-04-28",
"expired_date": "9999-12-31",
"min_balance": 10,
"status": "published",
"catelogname": "图生视频",
"catelog_id": "i2v",
"apiname": "i2v-happyhorse",
"query_apiname": "t2vstatus",
"query_period": 10,
"ppid": "knEwDP35DEz5oMAXyvwN3",
"provider_name": "阿里云",
"pricing_display": " - duration: 0.9 元/秒 [SR=720]\n - duration: 1.6 元/秒 [SR=1080]",
"provider_iconurl": "https://token.opencomputing.cn/appbase/show_icon.dspy?id=qwen"
},
]
}
]

View File

@ -82,14 +82,6 @@ async def providerAdd(ns={}):
'status': False,
'msg': 'provider add failed, orgcode is empty'
}
# filter by orgcode
res = await sor.R('organization', {})
orgcodes = [orgc.get('orgcode') for orgc in res]
if org_code in orgcodes:
return {
'status': False,
'msg': 'provider add failed, orgcode has already exist'
}
if not ns.get('orgid'):
orgid_li = await sor.R('users', {'id': await get_user()})
orgid = orgid_li[0].get('orgid') if orgid_li else ''
@ -101,8 +93,33 @@ async def providerAdd(ns={}):
else:
orgid = ns.get('orgid')
# filter by orgcode; existing provider returns ids for idempotent callers
exist_org_li = await sor.R('organization', {'orgcode': org_code, 'del_flg': '0'})
if len(exist_org_li) >= 1:
exist_org = exist_org_li[0]
exist_provider_li = await sor.R('provider', {'orgid': exist_org.get('id'), 'del_flg': '0'})
if not exist_provider_li:
return {
'status': False,
'msg': 'provider add failed, orgcode has already exist but provider not found'
}
exist_protocol_li = await sor.R('saleprotocol', {'offer_orgid': exist_org.get('id'), 'bid_orgid': orgid, 'del_flg': '0'})
if not exist_protocol_li:
exist_protocol_li = await sor.R('saleprotocol', {'offer_orgid': exist_org.get('id'), 'del_flg': '0'})
return {
'status': True,
'msg': 'provider already exist',
'data': {
'orgid': exist_org.get('id'),
'provider_orgid': exist_org.get('id'),
'provider_id': exist_provider_li[0].get('id'),
'protocolid': exist_protocol_li[0].get('id') if exist_protocol_li else None
}
}
# 供应商parentid 和 运营机构id相同
ns_org['parentid'] = orgid
ns_sale_mode['bid_orgid'] = orgid
if not ns_provider.get('start_date'):
ns_provider['start_date'] = time.strftime('%Y-%m-%d %H:%M:%S')
@ -115,7 +132,13 @@ async def providerAdd(ns={}):
await openProviderAccounts(sor, orgid, ns_org['id'])
return {
"status": True,
"msg": "provider add success"
"msg": "provider add success",
"data": {
"orgid": ns_org['id'],
"provider_orgid": ns_org['id'],
"provider_id": ns_provider['id'],
"protocolid": ns_sale_mode['id']
}
}
except Exception as e:
raise e