From d6e4221a7b36e65e8479d7347458a6103e7c6a6b Mon Sep 17 00:00:00 2001 From: yumoqing Date: Thu, 28 May 2026 23:42:29 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20add=20model=20publish/unpublish=20(?= =?UTF-8?q?=E4=B8=8A=E6=9E=B6/=E4=B8=8B=E6=9E=B6)=20functionality?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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) --- .gitignore | 1 + json/llm.json | 14 ++++++++++++-- llmage/utils.py | 5 +++++ models/llm.json | 8 ++++++++ sql/add_status_field.sql | 11 +++++++++++ wwwroot/api/llm_list.dspy | 2 +- wwwroot/get_type_llms.dspy | 1 + wwwroot/list_catelog_models.dspy | 2 +- wwwroot/list_paging_catelog_llms.dspy | 1 + wwwroot/llmcheck.dspy | 2 +- wwwroot/t2t/index.dspy | 3 ++- wwwroot/v1/chat/completions/index.dspy | 3 ++- wwwroot/v1/image/generations/index.dspy | 3 ++- wwwroot/v1/video/generations/index.dspy | 3 ++- 14 files changed, 50 insertions(+), 9 deletions(-) create mode 100644 .gitignore create mode 100644 sql/add_status_field.sql diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c18dd8d --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +__pycache__/ diff --git a/json/llm.json b/json/llm.json index 8f3ea63..c2cd2a7 100644 --- a/json/llm.json +++ b/json/llm.json @@ -10,18 +10,28 @@ {"field": "name", "op": "LIKE", "var": "name_input"}, {"field": "model", "op": "LIKE", "var": "model_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": { "name_input": "名称", "model_input": "识别名", "providerid_input": "供应商", - "upappid_input": "上位系统" + "upappid_input": "上位系统", + "status_input": "上架状态" }, "browserfields": { "exclouded": ["id", "ownerid"], "alters": { + "status": { + "uitype": "select", + "options": [ + {"value": "", "text": "全部"}, + {"value": "published", "text": "已上架"}, + {"value": "unpublished", "text": "已下架"} + ] + }, "ppid":{ "dataurl":"{{entire_url('/pricing/get_all_pricing_programs.dspy')}}", "textField": "name", diff --git a/llmage/utils.py b/llmage/utils.py index 3d00cb6..d0bc67f 100644 --- a/llmage/utils.py +++ b/llmage/utils.py @@ -154,6 +154,7 @@ async def get_llmproviders(): sql = """select a.providerid, a.iconid, b.orgname from llm a, organization b where a.providerid = b.id + and a.status = 'published' group by a.providerid, a.iconid, b.orgname""" return await sor.sqlExe(sql, {}) return [] @@ -165,6 +166,7 @@ async def get_llms_sort_by_provider(): sql = """select a.*, b.orgname from llm a, organization b where a.enabled_date <= ${today}$ and a.expired_date > ${today}$ + and a.status = 'published' and a.providerid = b.id order by a.providerid, a.id """ @@ -211,6 +213,7 @@ m.ppid join llm_api_map m on a.id = m.llmid join llmcatelog b on m.llmcatelogid = b.id where a.enabled_date <= ${today}$ + and a.status = 'published' and m.ppid is not null 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 llmcatelog b on m.llmcatelogid = b.id where a.enabled_date <= ${today}$ + and a.status = 'published' and a.expired_date > ${today}$""" params = {'today': today, 'sort': orderby} if catelogid: @@ -311,6 +315,7 @@ and c.id = e.upappid and m.apiname = e.name and e.ioid = f.id and a.id = ${llmid}$ +and a.status = 'published' and a.expired_date > ${today}$ and a.enabled_date <= ${today}$ """ diff --git a/models/llm.json b/models/llm.json index ade8a75..5259993 100644 --- a/models/llm.json +++ b/models/llm.json @@ -74,6 +74,14 @@ "length": 20, "default": 10, "dec": 2 + }, + { + "name": "status", + "title": "上架状态", + "type": "str", + "length": 16, + "nullable": "no", + "default": "unpublished" } ], "codes": [ diff --git a/sql/add_status_field.sql b/sql/add_status_field.sql new file mode 100644 index 0000000..431d930 --- /dev/null +++ b/sql/add_status_field.sql @@ -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`); diff --git a/wwwroot/api/llm_list.dspy b/wwwroot/api/llm_list.dspy index f6ef7cf..a13b467 100644 --- a/wwwroot/api/llm_list.dspy +++ b/wwwroot/api/llm_list.dspy @@ -44,7 +44,7 @@ try: # Paginated data data_sql = f""" 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} order by model limit ${limit}$ offset ${offset}$ diff --git a/wwwroot/get_type_llms.dspy b/wwwroot/get_type_llms.dspy index 9144023..1c9d0fa 100644 --- a/wwwroot/get_type_llms.dspy +++ b/wwwroot/get_type_llms.dspy @@ -12,6 +12,7 @@ join uapiio e on d.ioid = e.id where b.name=${lt}$ and a.enabled_date <= ${biz_date}$ and ${biz_date}$ < a.expired_date + and a.status = 'published' and ppid is not NULL''' biz_date = await get_business_date(sor) recs = await sor.sqlExe(sql, { diff --git a/wwwroot/list_catelog_models.dspy b/wwwroot/list_catelog_models.dspy index d904f28..27b4caf 100644 --- a/wwwroot/list_catelog_models.dspy +++ b/wwwroot/list_catelog_models.dspy @@ -3,7 +3,7 @@ db = DBPools() async with db.sqlorContext(dbname) as sor: sql = """select distinct a.* from llm a 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() recs = await sor.sqlExe(sql, ns) for r in recs.get('rows', []): diff --git a/wwwroot/list_paging_catelog_llms.dspy b/wwwroot/list_paging_catelog_llms.dspy index 0aee5fe..2043a9c 100644 --- a/wwwroot/list_paging_catelog_llms.dspy +++ b/wwwroot/list_paging_catelog_llms.dspy @@ -18,6 +18,7 @@ join llm_api_map m on a.id = m.llmid join llmcatelog b on m.llmcatelogid = b.id join upapp c on a.upappid = c.id 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 left join uapiio z on x.ioid = z.id where m.llmcatelogid = ${llmcatelogid}$ diff --git a/wwwroot/llmcheck.dspy b/wwwroot/llmcheck.dspy index 771902a..61789b2 100644 --- a/wwwroot/llmcheck.dspy +++ b/wwwroot/llmcheck.dspy @@ -2,7 +2,7 @@ llmid = params_kw.llmid today= params_kw.today msgs = [] 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} recs = await sor.sqlExe(sql, ns.copy()) if recs: diff --git a/wwwroot/t2t/index.dspy b/wwwroot/t2t/index.dspy index fec2032..58ad527 100644 --- a/wwwroot/t2t/index.dspy +++ b/wwwroot/t2t/index.dspy @@ -21,7 +21,8 @@ async with get_sor_context(env, 'llmage') as sor: join llm_api_map m on a.id = m.llmid join llmcatelog b on m.llmcatelogid = b.id where b.name = ${lctype}$ - and a.model=${model}$""" + and a.model=${model}$ + and a.status = 'published'""" recs = await sor.sqlExe(sql, { 'lctype': lctype, 'model': params_kw.model or 'qwen3-max' diff --git a/wwwroot/v1/chat/completions/index.dspy b/wwwroot/v1/chat/completions/index.dspy index 13aab70..6850c23 100644 --- a/wwwroot/v1/chat/completions/index.dspy +++ b/wwwroot/v1/chat/completions/index.dspy @@ -34,7 +34,8 @@ async with get_sor_context(env, 'llmage') as sor: join llm_api_map m on a.id = m.llmid join llmcatelog b on m.llmcatelogid = b.id where b.name = ${lctype}$ - and a.model=${model}$""" + and a.model=${model}$ + and a.status = 'published'""" recs = await sor.sqlExe(sql, { 'lctype': lctype, 'model': params_kw.model or 'qwen3-max' diff --git a/wwwroot/v1/image/generations/index.dspy b/wwwroot/v1/image/generations/index.dspy index 45168c9..067c014 100644 --- a/wwwroot/v1/image/generations/index.dspy +++ b/wwwroot/v1/image/generations/index.dspy @@ -53,7 +53,8 @@ async with get_sor_context(env, 'llmage') as sor: join llm_api_map m on a.id = m.llmid join llmcatelog b on m.llmcatelogid = b.id where b.name = ${lctype}$ - and a.model=${model}$""" + and a.model=${model}$ + and a.status = 'published'""" recs = await sor.sqlExe(sql, { 'lctype': lctype, 'model': params_kw.model diff --git a/wwwroot/v1/video/generations/index.dspy b/wwwroot/v1/video/generations/index.dspy index f83545b..29a94c6 100644 --- a/wwwroot/v1/video/generations/index.dspy +++ b/wwwroot/v1/video/generations/index.dspy @@ -61,7 +61,8 @@ async with get_sor_context(env, 'llmage') as sor: join llm_api_map m on a.id = m.llmid join llmcatelog b on m.llmcatelogid = b.id where b.name = ${lctype}$ - and a.model=${model}$""" + and a.model=${model}$ + and a.status = 'published'""" recs = await sor.sqlExe(sql, { 'lctype': lctype, 'model': params_kw.model