feat: add model publish/unpublish (上架/下架) functionality
- llm table: add status field (published/unpublished, default unpublished)
- User-facing queries: filter by status='published' in 11 query points:
- utils.py: get_llms_by_catelog_to_customer, get_llms_by_catelog,
get_llm, get_llmproviders, get_llms_sort_by_provider
- v1 endpoints: chat/completions, image/generations, video/generations
- user pages: t2t, get_type_llms, list_catelog_models,
list_paging_catelog_llms, llmcheck
- CRUD: status column visible/editable with select dropdown
- Admin CRUD list shows ALL models regardless of status
- Migration SQL: sql/add_status_field.sql (existing models set to published)
This commit is contained in:
parent
cb5efd5550
commit
d6e4221a7b
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
__pycache__/
|
||||||
@ -10,18 +10,28 @@
|
|||||||
{"field": "name", "op": "LIKE", "var": "name_input"},
|
{"field": "name", "op": "LIKE", "var": "name_input"},
|
||||||
{"field": "model", "op": "LIKE", "var": "model_input"},
|
{"field": "model", "op": "LIKE", "var": "model_input"},
|
||||||
{"field": "providerid", "op": "=", "var": "providerid_input"},
|
{"field": "providerid", "op": "=", "var": "providerid_input"},
|
||||||
{"field": "upappid", "op": "=", "var": "upappid_input"}
|
{"field": "upappid", "op": "=", "var": "upappid_input"},
|
||||||
|
{"field": "status", "op": "=", "var": "status_input"}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"filter_labels": {
|
"filter_labels": {
|
||||||
"name_input": "名称",
|
"name_input": "名称",
|
||||||
"model_input": "识别名",
|
"model_input": "识别名",
|
||||||
"providerid_input": "供应商",
|
"providerid_input": "供应商",
|
||||||
"upappid_input": "上位系统"
|
"upappid_input": "上位系统",
|
||||||
|
"status_input": "上架状态"
|
||||||
},
|
},
|
||||||
"browserfields": {
|
"browserfields": {
|
||||||
"exclouded": ["id", "ownerid"],
|
"exclouded": ["id", "ownerid"],
|
||||||
"alters": {
|
"alters": {
|
||||||
|
"status": {
|
||||||
|
"uitype": "select",
|
||||||
|
"options": [
|
||||||
|
{"value": "", "text": "全部"},
|
||||||
|
{"value": "published", "text": "已上架"},
|
||||||
|
{"value": "unpublished", "text": "已下架"}
|
||||||
|
]
|
||||||
|
},
|
||||||
"ppid":{
|
"ppid":{
|
||||||
"dataurl":"{{entire_url('/pricing/get_all_pricing_programs.dspy')}}",
|
"dataurl":"{{entire_url('/pricing/get_all_pricing_programs.dspy')}}",
|
||||||
"textField": "name",
|
"textField": "name",
|
||||||
|
|||||||
@ -154,6 +154,7 @@ async def get_llmproviders():
|
|||||||
sql = """select a.providerid, a.iconid, b.orgname
|
sql = """select a.providerid, a.iconid, b.orgname
|
||||||
from llm a, organization b
|
from llm a, organization b
|
||||||
where a.providerid = b.id
|
where a.providerid = b.id
|
||||||
|
and a.status = 'published'
|
||||||
group by a.providerid, a.iconid, b.orgname"""
|
group by a.providerid, a.iconid, b.orgname"""
|
||||||
return await sor.sqlExe(sql, {})
|
return await sor.sqlExe(sql, {})
|
||||||
return []
|
return []
|
||||||
@ -165,6 +166,7 @@ async def get_llms_sort_by_provider():
|
|||||||
sql = """select a.*, b.orgname from llm a, organization b
|
sql = """select a.*, b.orgname from llm a, organization b
|
||||||
where a.enabled_date <= ${today}$
|
where a.enabled_date <= ${today}$
|
||||||
and a.expired_date > ${today}$
|
and a.expired_date > ${today}$
|
||||||
|
and a.status = 'published'
|
||||||
and a.providerid = b.id
|
and a.providerid = b.id
|
||||||
order by a.providerid, a.id
|
order by a.providerid, a.id
|
||||||
"""
|
"""
|
||||||
@ -211,6 +213,7 @@ m.ppid
|
|||||||
join llm_api_map m on a.id = m.llmid
|
join llm_api_map m on a.id = m.llmid
|
||||||
join llmcatelog b on m.llmcatelogid = b.id
|
join llmcatelog b on m.llmcatelogid = b.id
|
||||||
where a.enabled_date <= ${today}$
|
where a.enabled_date <= ${today}$
|
||||||
|
and a.status = 'published'
|
||||||
and m.ppid is not null
|
and m.ppid is not null
|
||||||
and a.expired_date > ${today}$
|
and a.expired_date > ${today}$
|
||||||
"""
|
"""
|
||||||
@ -250,6 +253,7 @@ async def get_llms_by_catelog(catelogid=None, orderby='providerid'):
|
|||||||
join llm_api_map m on a.id = m.llmid
|
join llm_api_map m on a.id = m.llmid
|
||||||
join llmcatelog b on m.llmcatelogid = b.id
|
join llmcatelog b on m.llmcatelogid = b.id
|
||||||
where a.enabled_date <= ${today}$
|
where a.enabled_date <= ${today}$
|
||||||
|
and a.status = 'published'
|
||||||
and a.expired_date > ${today}$"""
|
and a.expired_date > ${today}$"""
|
||||||
params = {'today': today, 'sort': orderby}
|
params = {'today': today, 'sort': orderby}
|
||||||
if catelogid:
|
if catelogid:
|
||||||
@ -311,6 +315,7 @@ and c.id = e.upappid
|
|||||||
and m.apiname = e.name
|
and m.apiname = e.name
|
||||||
and e.ioid = f.id
|
and e.ioid = f.id
|
||||||
and a.id = ${llmid}$
|
and a.id = ${llmid}$
|
||||||
|
and a.status = 'published'
|
||||||
and a.expired_date > ${today}$
|
and a.expired_date > ${today}$
|
||||||
and a.enabled_date <= ${today}$
|
and a.enabled_date <= ${today}$
|
||||||
"""
|
"""
|
||||||
|
|||||||
@ -74,6 +74,14 @@
|
|||||||
"length": 20,
|
"length": 20,
|
||||||
"default": 10,
|
"default": 10,
|
||||||
"dec": 2
|
"dec": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "status",
|
||||||
|
"title": "上架状态",
|
||||||
|
"type": "str",
|
||||||
|
"length": 16,
|
||||||
|
"nullable": "no",
|
||||||
|
"default": "unpublished"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"codes": [
|
"codes": [
|
||||||
|
|||||||
11
sql/add_status_field.sql
Normal file
11
sql/add_status_field.sql
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
-- llmage: 添加模型上架/下架功能
|
||||||
|
-- 执行此 SQL 后,所有现有模型默认已上架,不影响线上使用
|
||||||
|
|
||||||
|
-- 1. 添加 status 字段
|
||||||
|
ALTER TABLE llm ADD COLUMN `status` VARCHAR(16) NOT NULL DEFAULT 'unpublished' COMMENT '上架状态: published/unpublished' AFTER `min_balance`;
|
||||||
|
|
||||||
|
-- 2. 现有模型全部设为已上架
|
||||||
|
UPDATE llm SET status = 'published';
|
||||||
|
|
||||||
|
-- 3. 添加索引(按状态筛选是高频操作)
|
||||||
|
ALTER TABLE llm ADD INDEX `idx_status` (`status`);
|
||||||
@ -44,7 +44,7 @@ try:
|
|||||||
# Paginated data
|
# Paginated data
|
||||||
data_sql = f"""
|
data_sql = f"""
|
||||||
select id, name, model, description, iconid, upappid, providerid,
|
select id, name, model, description, iconid, upappid, providerid,
|
||||||
ownerid, enabled_date, expired_date, min_balance
|
ownerid, enabled_date, expired_date, min_balance, status
|
||||||
from llm{where_clause}
|
from llm{where_clause}
|
||||||
order by model
|
order by model
|
||||||
limit ${limit}$ offset ${offset}$
|
limit ${limit}$ offset ${offset}$
|
||||||
|
|||||||
@ -12,6 +12,7 @@ join uapiio e on d.ioid = e.id
|
|||||||
where b.name=${lt}$
|
where b.name=${lt}$
|
||||||
and a.enabled_date <= ${biz_date}$
|
and a.enabled_date <= ${biz_date}$
|
||||||
and ${biz_date}$ < a.expired_date
|
and ${biz_date}$ < a.expired_date
|
||||||
|
and a.status = 'published'
|
||||||
and ppid is not NULL'''
|
and ppid is not NULL'''
|
||||||
biz_date = await get_business_date(sor)
|
biz_date = await get_business_date(sor)
|
||||||
recs = await sor.sqlExe(sql, {
|
recs = await sor.sqlExe(sql, {
|
||||||
|
|||||||
@ -3,7 +3,7 @@ db = DBPools()
|
|||||||
async with db.sqlorContext(dbname) as sor:
|
async with db.sqlorContext(dbname) as sor:
|
||||||
sql = """select distinct a.* from llm a
|
sql = """select distinct a.* from llm a
|
||||||
join llm_api_map m on a.id = m.llmid
|
join llm_api_map m on a.id = m.llmid
|
||||||
where m.llmcatelogid = ${llmcatelogid}$ and a.id != ${llmid}$"""
|
where m.llmcatelogid = ${llmcatelogid}$ and a.id != ${llmid}$ and a.status = 'published'"""
|
||||||
ns = params_kw.copy()
|
ns = params_kw.copy()
|
||||||
recs = await sor.sqlExe(sql, ns)
|
recs = await sor.sqlExe(sql, ns)
|
||||||
for r in recs.get('rows', []):
|
for r in recs.get('rows', []):
|
||||||
|
|||||||
@ -18,6 +18,7 @@ join llm_api_map m on a.id = m.llmid
|
|||||||
join llmcatelog b on m.llmcatelogid = b.id
|
join llmcatelog b on m.llmcatelogid = b.id
|
||||||
join upapp c on a.upappid = c.id
|
join upapp c on a.upappid = c.id
|
||||||
join uapi e on c.apisetid = e.apisetid and a.apiname = e.name
|
join uapi e on c.apisetid = e.apisetid and a.apiname = e.name
|
||||||
|
where a.status = 'published'
|
||||||
) x left join historyformat y on x.hfid = y.id
|
) x left join historyformat y on x.hfid = y.id
|
||||||
left join uapiio z on x.ioid = z.id
|
left join uapiio z on x.ioid = z.id
|
||||||
where m.llmcatelogid = ${llmcatelogid}$
|
where m.llmcatelogid = ${llmcatelogid}$
|
||||||
|
|||||||
@ -2,7 +2,7 @@ llmid = params_kw.llmid
|
|||||||
today= params_kw.today
|
today= params_kw.today
|
||||||
msgs = []
|
msgs = []
|
||||||
async with get_sor_context(request._run_ns, 'llmage') as sor:
|
async with get_sor_context(request._run_ns, 'llmage') as sor:
|
||||||
sql = "select * from llm where id=${llmid}$ and enabled_date <= ${today}$ and expired_date > ${today}$"
|
sql = "select * from llm where id=${llmid}$ and enabled_date <= ${today}$ and expired_date > ${today}$ and status = 'published'"
|
||||||
ns = {'llmid': llmid, 'today': today}
|
ns = {'llmid': llmid, 'today': today}
|
||||||
recs = await sor.sqlExe(sql, ns.copy())
|
recs = await sor.sqlExe(sql, ns.copy())
|
||||||
if recs:
|
if recs:
|
||||||
|
|||||||
@ -21,7 +21,8 @@ async with get_sor_context(env, 'llmage') as sor:
|
|||||||
join llm_api_map m on a.id = m.llmid
|
join llm_api_map m on a.id = m.llmid
|
||||||
join llmcatelog b on m.llmcatelogid = b.id
|
join llmcatelog b on m.llmcatelogid = b.id
|
||||||
where b.name = ${lctype}$
|
where b.name = ${lctype}$
|
||||||
and a.model=${model}$"""
|
and a.model=${model}$
|
||||||
|
and a.status = 'published'"""
|
||||||
recs = await sor.sqlExe(sql, {
|
recs = await sor.sqlExe(sql, {
|
||||||
'lctype': lctype,
|
'lctype': lctype,
|
||||||
'model': params_kw.model or 'qwen3-max'
|
'model': params_kw.model or 'qwen3-max'
|
||||||
|
|||||||
@ -34,7 +34,8 @@ async with get_sor_context(env, 'llmage') as sor:
|
|||||||
join llm_api_map m on a.id = m.llmid
|
join llm_api_map m on a.id = m.llmid
|
||||||
join llmcatelog b on m.llmcatelogid = b.id
|
join llmcatelog b on m.llmcatelogid = b.id
|
||||||
where b.name = ${lctype}$
|
where b.name = ${lctype}$
|
||||||
and a.model=${model}$"""
|
and a.model=${model}$
|
||||||
|
and a.status = 'published'"""
|
||||||
recs = await sor.sqlExe(sql, {
|
recs = await sor.sqlExe(sql, {
|
||||||
'lctype': lctype,
|
'lctype': lctype,
|
||||||
'model': params_kw.model or 'qwen3-max'
|
'model': params_kw.model or 'qwen3-max'
|
||||||
|
|||||||
@ -53,7 +53,8 @@ async with get_sor_context(env, 'llmage') as sor:
|
|||||||
join llm_api_map m on a.id = m.llmid
|
join llm_api_map m on a.id = m.llmid
|
||||||
join llmcatelog b on m.llmcatelogid = b.id
|
join llmcatelog b on m.llmcatelogid = b.id
|
||||||
where b.name = ${lctype}$
|
where b.name = ${lctype}$
|
||||||
and a.model=${model}$"""
|
and a.model=${model}$
|
||||||
|
and a.status = 'published'"""
|
||||||
recs = await sor.sqlExe(sql, {
|
recs = await sor.sqlExe(sql, {
|
||||||
'lctype': lctype,
|
'lctype': lctype,
|
||||||
'model': params_kw.model
|
'model': params_kw.model
|
||||||
|
|||||||
@ -61,7 +61,8 @@ async with get_sor_context(env, 'llmage') as sor:
|
|||||||
join llm_api_map m on a.id = m.llmid
|
join llm_api_map m on a.id = m.llmid
|
||||||
join llmcatelog b on m.llmcatelogid = b.id
|
join llmcatelog b on m.llmcatelogid = b.id
|
||||||
where b.name = ${lctype}$
|
where b.name = ${lctype}$
|
||||||
and a.model=${model}$"""
|
and a.model=${model}$
|
||||||
|
and a.status = 'published'"""
|
||||||
recs = await sor.sqlExe(sql, {
|
recs = await sor.sqlExe(sql, {
|
||||||
'lctype': lctype,
|
'lctype': lctype,
|
||||||
'model': params_kw.model
|
'model': params_kw.model
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user