import asyncio from appPublic.registerfunction import RegisterFunction from sqlor.dbpools import DBPools, get_sor_context from ahserver.serverenv import ServerEnv from appPublic.log import debug from appPublic.share_cache import cache_start_listener from .keling import keling_token from .jimeng import jimeng_auth_headers from .utils import ( llm_query_orders, read_webpath, llm_query_price, get_user_tpac, get_tpac_balance, get_llm_by_model, get_llms_by_catelog, get_llms_sort_by_provider, get_llmcatelogs, get_llms_by_catelog_to_customer, get_llmproviders, get_llm, get_llmage_llm, get_llm_catelogs, invalidate_uapi_cache, get_llmusage_by_id, read_ioinfo_content, _warm_llmid_cache, get_llmid_cached, invalidate_llmid_cache, get_plaza_models, ) from .llmclient import ( inference_generator, inference ) from .accounting import ( checkCustomerBalance, llm_charging, get_accounting_llmusages, backend_accounting, llm_accounting, backup_accounted_llmusage, get_failed_accounting_records, llm_accoung_failed ) from .stats import get_llmage_stats from .asyncinference import ( get_asynctask_status, query_task_status, get_today_asynctask_list ) from .product_interface import ( get_product_display, check_product_availability, check_product_consumable, execute_product_service, execute_product_service_stream, calculate_product_cost, ) async def load_product_category_product(parent_category_id): """Return llmage catalogs and published models as standardized import data. Called by product_management.import_categories_and_products(). Only reads source data and returns it in the standard format. Does NOT write to product_management tables — that's product_management's job. Returns: { 'success': True, 'categories': [{'source_id', 'name', 'description', 'product_type', 'product_type_title', 'sort_order'}, ...], 'products': [{'source_category_id', 'resource_ref_id', 'product_code', 'product_name', 'product_type', 'brief_intro', 'sort_order'}, ...] } """ env = ServerEnv() # Read source data from llmage async with get_sor_context(env, 'llmage') as sor: catelogs = await sor.R('llmcatelog', {}) if not catelogs: return {'success': False, 'error': 'llmage中没有产品类别数据'} llm_sql = """select a.id, a.name, a.model, a.description, a.status, m.llmcatelogid, lc.name as catelogname from llm a join llm_api_map m on a.id = m.llmid join llmcatelog lc on m.llmcatelogid = lc.id where m.isdefaultcatelog = '1' and a.status = 'published' order by lc.name, a.name""" llms = await sor.sqlExe(llm_sql, {}) # Build standardized categories categories = [] for c in catelogs: categories.append({ 'source_id': c.id, 'name': c.name, 'description': getattr(c, 'description', '') or '', 'product_type': 'llm_model', 'product_type_title': '大模型按量', 'sort_order': 0, }) # Build standardized products products = [] for llm in (llms or []): products.append({ 'source_category_id': llm.llmcatelogid, 'resource_ref_id': llm.id, 'product_code': llm.model, 'product_name': llm.name, 'product_type': 'llm_model', 'brief_intro': getattr(llm, 'description', '') or '', 'sort_order': 0, 'providerid': getattr(llm, 'providerid', '') or '', }) return { 'success': True, 'categories': categories, 'products': products, } def _on_hot_reload(data=None): """Event handler for hot_reload — invalidate caches.""" from appPublic.log import debug debug(f'[llmage] on_hot_reload called, invalidating caches (data={data})') invalidate_uapi_cache() invalidate_llmid_cache() def load_llmage(): env = ServerEnv() env.llm_query_orders = llm_query_orders env.read_webpath = read_webpath env.get_llm_by_model = get_llm_by_model env.llm_charging = llm_charging env.get_accounting_llmusages = get_accounting_llmusages env.llm_accounting = llm_accounting env.get_today_asynctask_list = get_today_asynctask_list env.get_asynctask_status = get_asynctask_status env.query_task_status = query_task_status env.get_llm = get_llm env.get_llmage_llm = get_llmage_llm env.get_llm_catelogs = get_llm_catelogs env.invalidate_uapi_cache = invalidate_uapi_cache env.inference = inference env.get_user_tpac = get_user_tpac env.get_tpac_balance = get_tpac_balance env.inference_generator = inference_generator 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.checkCustomerBalance = checkCustomerBalance env.get_llmproviders = get_llmproviders env.get_llms_sort_by_provider = get_llms_sort_by_provider env.keling_token = keling_token env.llm_query_price = llm_query_price env.get_llms_by_catelog_to_customer = get_llms_by_catelog_to_customer env.get_plaza_models = get_plaza_models env.backup_accounted_llmusage = backup_accounted_llmusage env.read_ioinfo_content = read_ioinfo_content env.get_llmusage_by_id = get_llmusage_by_id env.get_failed_accounting_records = get_failed_accounting_records env.get_llmage_stats = get_llmage_stats # Product module standard interface env.product_interface = { 'module_name': 'llmage', 'get_product_display': get_product_display, 'check_product_availability': check_product_availability, 'check_product_consumable': check_product_consumable, 'execute_product_service': execute_product_service, 'execute_product_service_stream': execute_product_service_stream, 'calculate_product_cost': calculate_product_cost, 'load_product_category_product': load_product_category_product, } # Bind hot_reload event — module-level function, ref safe (module keeps it alive) cache_start_listener() if hasattr(env, 'event_dispatcher'): env.event_dispatcher.bind('hot_reload', _on_hot_reload) rf = RegisterFunction() rf.register('jimeng_auth_headers', jimeng_auth_headers)