diff --git a/product_management/__init__.py b/product_management/__init__.py index 80fda7c..ef42251 100644 --- a/product_management/__init__.py +++ b/product_management/__init__.py @@ -100,6 +100,15 @@ async def calculate_product_cost(product_id=None, product_code=None, usage_data= return await manager.calculate_product_cost(product_id, product_code, usage_data, user_org_id) +async def llm_id_to_product_id(llm_id): + """Convert LLM model ID (llmage.llm.id) to product ID (product.id). + + Uses the product.resource_ref_id → llm.id mapping established during import. + """ + manager = get_manager() + return await manager.llm_id_to_product_id(llm_id) + + def load_product_management(): """Register all functions with ServerEnv so they can be called from .ui/.dspy files.""" env = ServerEnv() @@ -118,4 +127,5 @@ def load_product_management(): env.execute_product = execute_product env.execute_product_stream = execute_product_stream env.calculate_product_cost = calculate_product_cost + env.llm_id_to_product_id = llm_id_to_product_id return True diff --git a/product_management/core.py b/product_management/core.py index acae3e3..8610ca4 100644 --- a/product_management/core.py +++ b/product_management/core.py @@ -1327,3 +1327,18 @@ class ProductManager: user_org_id = self._get_current_org_id() return await fn(ref_id, usage_data or {}, user_org_id) + + async def llm_id_to_product_id(self, llm_id): + """Convert LLM model ID (llmage.llm.id) to product ID (product.id). + + Uses resource_ref_id mapping: product.resource_ref_id = llm.id + and product.product_type = 'llm_model'. + """ + dbname = self._get_dbname() + async with DBPools().sqlorContext(dbname) as sor: + sql = """SELECT id FROM product +WHERE resource_ref_id = ${llm_id}$ AND product_type = 'llm_model' LIMIT 1""" + recs = await sor.sqlExe(sql, {'llm_id': llm_id}) + if recs: + return recs[0].id + return None