perf: llmid缓存(启动预热+内存查),v1/chat/completions去3表JOIN
This commit is contained in:
parent
5e48622e2a
commit
ef1e228f19
@ -23,6 +23,9 @@ from .utils import (
|
|||||||
invalidate_uapi_cache,
|
invalidate_uapi_cache,
|
||||||
get_llmusage_by_id,
|
get_llmusage_by_id,
|
||||||
read_ioinfo_content,
|
read_ioinfo_content,
|
||||||
|
_warm_llmid_cache,
|
||||||
|
get_llmid_cached,
|
||||||
|
invalidate_llmid_cache,
|
||||||
)
|
)
|
||||||
|
|
||||||
from .llmclient import (
|
from .llmclient import (
|
||||||
@ -122,10 +125,11 @@ order by lc.name, a.name"""
|
|||||||
|
|
||||||
|
|
||||||
def _on_hot_reload(data=None):
|
def _on_hot_reload(data=None):
|
||||||
"""Event handler for hot_reload — wraps invalidate_uapi_cache to accept dispatcher's data arg."""
|
"""Event handler for hot_reload — invalidate caches."""
|
||||||
from appPublic.log import debug
|
from appPublic.log import debug
|
||||||
debug(f'[llmage] on_hot_reload called, invalidating uapi cache (data={data})')
|
debug(f'[llmage] on_hot_reload called, invalidating caches (data={data})')
|
||||||
invalidate_uapi_cache()
|
invalidate_uapi_cache()
|
||||||
|
invalidate_llmid_cache()
|
||||||
|
|
||||||
|
|
||||||
def load_llmage():
|
def load_llmage():
|
||||||
@ -148,6 +152,10 @@ def load_llmage():
|
|||||||
env.get_tpac_balance = get_tpac_balance
|
env.get_tpac_balance = get_tpac_balance
|
||||||
env.inference_generator = inference_generator
|
env.inference_generator = inference_generator
|
||||||
env.get_llms_by_catelog = get_llms_by_catelog
|
env.get_llms_by_catelog = get_llms_by_catelog
|
||||||
|
env.get_llmid_cached = get_llmid_cached
|
||||||
|
env.invalidate_llmid_cache = invalidate_llmid_cache
|
||||||
|
# 启动时预热 llmid 缓存
|
||||||
|
asyncio.ensure_future(_warm_llmid_cache(env))
|
||||||
env.get_llmcatelogs = get_llmcatelogs
|
env.get_llmcatelogs = get_llmcatelogs
|
||||||
env.checkCustomerBalance = checkCustomerBalance
|
env.checkCustomerBalance = checkCustomerBalance
|
||||||
env.get_llmproviders = get_llmproviders
|
env.get_llmproviders = get_llmproviders
|
||||||
|
|||||||
@ -63,6 +63,55 @@ def invalidate_uapi_cache(upappid=None, apiname=None):
|
|||||||
_uapiio_cache.clear()
|
_uapiio_cache.clear()
|
||||||
|
|
||||||
|
|
||||||
|
# =============================================================
|
||||||
|
# Process-level cache for llmid lookup (model+catelogid -> llmid)
|
||||||
|
# =============================================================
|
||||||
|
_llmid_cache = {} # key: "model_name:catelogid" -> llmid
|
||||||
|
|
||||||
|
|
||||||
|
async def _warm_llmid_cache(env):
|
||||||
|
"""启动时全量加载 model+catelogid -> llmid 映射"""
|
||||||
|
global _llmid_cache
|
||||||
|
try:
|
||||||
|
async with get_sor_context(env, 'llmage') as sor:
|
||||||
|
sql = """SELECT a.name, b.id as catelogid, m.llmid
|
||||||
|
FROM llm_api_map m
|
||||||
|
JOIN llm a ON a.id = m.llmid AND a.status = 'published'
|
||||||
|
JOIN llmcatelog b ON b.id = m.llmcatelogid"""
|
||||||
|
recs = await sor.sqlExe(sql, {})
|
||||||
|
for r in recs:
|
||||||
|
key = f"{r.name}:{r.catelogid}"
|
||||||
|
_llmid_cache[key] = r.llmid
|
||||||
|
debug(f'[llmage] llmid cache warmed: {len(_llmid_cache)} entries')
|
||||||
|
except Exception as e:
|
||||||
|
exception(f'[llmage] llmid cache warm failed: {e}')
|
||||||
|
_llmid_cache = {}
|
||||||
|
|
||||||
|
|
||||||
|
async def get_llmid_cached(env, model_name, catelogid):
|
||||||
|
"""从缓存获取 llmid,未命中则查 DB 并缓存"""
|
||||||
|
global _llmid_cache
|
||||||
|
key = f"{model_name}:{catelogid}"
|
||||||
|
if key in _llmid_cache:
|
||||||
|
return _llmid_cache[key]
|
||||||
|
# 缓存未命中,查 DB(兼容模型在缓存预热后新增的场景)
|
||||||
|
async with get_sor_context(env, 'llmage') as sor:
|
||||||
|
sql = """SELECT m.llmid
|
||||||
|
FROM llm_api_map m
|
||||||
|
JOIN llm a ON a.id = m.llmid AND a.name = ${model}$ AND a.status = 'published'
|
||||||
|
JOIN llmcatelog b ON b.id = m.llmcatelogid AND (b.id = ${catelogid}$ OR b.name = ${catelogid}$)"""
|
||||||
|
recs = await sor.sqlExe(sql, {'model': model_name, 'catelogid': catelogid})
|
||||||
|
llmid = recs[0].llmid if recs else None
|
||||||
|
if llmid:
|
||||||
|
_llmid_cache[key] = llmid
|
||||||
|
return llmid
|
||||||
|
|
||||||
|
|
||||||
|
def invalidate_llmid_cache():
|
||||||
|
global _llmid_cache
|
||||||
|
_llmid_cache.clear()
|
||||||
|
|
||||||
|
|
||||||
async def update_llmusage(ns):
|
async def update_llmusage(ns):
|
||||||
env = ServerEnv()
|
env = ServerEnv()
|
||||||
async with get_sor_context(env, 'llmage') as sor:
|
async with get_sor_context(env, 'llmage') as sor:
|
||||||
|
|||||||
@ -29,21 +29,11 @@ if not params_kw.prompt and not params_kw.messages:
|
|||||||
d = return_error('Missing need data(prompt or messages)')
|
d = return_error('Missing need data(prompt or messages)')
|
||||||
return json_response(d, status=400)
|
return json_response(d, status=400)
|
||||||
env = request._run_ns
|
env = request._run_ns
|
||||||
async with get_sor_context(env, 'llmage') as sor:
|
llmid = await env.get_llmid_cached(env, params_kw.model or 'qwen3-max', catelogid)
|
||||||
sql = """select distinct a.* from llm a
|
if not llmid:
|
||||||
join llm_api_map m on a.id = m.llmid
|
debug(f'{params_kw.model=} not found for catelogid={catelogid}')
|
||||||
join llmcatelog b on m.llmcatelogid = b.id
|
return openai_400()
|
||||||
where (b.id = ${catelogid}$ OR b.name = ${catelogid}$)
|
params_kw.llmid = llmid
|
||||||
and a.name=${model}$
|
|
||||||
and a.status = 'published'"""
|
|
||||||
recs = await sor.sqlExe(sql, {
|
|
||||||
'catelogid': catelogid,
|
|
||||||
'model': params_kw.model or 'qwen3-max'
|
|
||||||
})
|
|
||||||
if len(recs) == 0:
|
|
||||||
debug(f'{params_kw.model=} not found')
|
|
||||||
return openai_400()
|
|
||||||
params_kw.llmid = recs[0].id
|
|
||||||
params_kw.llmcatelogid = catelogid
|
params_kw.llmcatelogid = catelogid
|
||||||
|
|
||||||
debug(f'{params_kw.llmid=}')
|
debug(f'{params_kw.llmid=}')
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user