product_management
产品管理模块 —— 统一管理产品目录、类别树、资源绑定、订阅、消费引擎及资源模块对接。
模块定位
product_management 是产品生命周期的中枢,负责:
- 管理产品类别树和产品注册表
- 从资源模块(如 llmage)导入类别和产品
- 通过标准接口调度资源模块完成展示、预检、执行、计费
- 管理资源绑定、供应商路由、订阅与配额
- 记录消费日志并生成统计
数据模型
| 表名 | 说明 |
|---|---|
product_category |
产品类别树(parent_id 层级关系,resource_module 标记来源模块) |
product |
产品注册表(resource_ref_id 关联资源模块内部ID) |
product_resource |
产品-资源绑定(一个产品可绑定多个资源,含配额和溢出产品) |
product_resource_supplier |
资源绑定的供应商路由(优先级+权重) |
product_subscription |
产品订阅(月度/按量,含配额跟踪和溢出计费) |
product_usage_log |
消费日志(成本、售价、供应商、计费模式) |
关键字段
product_category
resource_module— 资源模块名称(如llmage),标识该类别下的产品来自哪个模块has_product— 是否可挂产品(1=是,0=仅分类节点)product_type— 产品类型标识(传递给产品的 product_type)
product
resource_ref_id— 资源模块内部 ID(如 llmage 中llm.id),用于直接调用资源模块接口,无需维护 product_code 对照表product_code— 产品编码(业务可读标识)product_type— 产品类型(如llm_model,llm_monthly,compute)
架构设计
1. 资源模块解耦导入
资源模块(如 llmage)和产品模块(product_management)职责分离:
资源模块 产品模块
───────── ─────────
load_product_category_product() import_categories_and_products()
│ 只读自己的数据 │ 调用资源模块获取标准化数据
│ 返回标准化格式 │ 负责所有写入和去重逻辑
└──────────────────┐ │
▼ │
{categories, products}
│ │
└───────────►│
│ 类别: name+parent_id+org_id 去重 → 已存在则跳过
│ 产品: resource_ref_id+org_id 去重 → 已存在则更新
资源模块返回格式:
{
'success': True,
'categories': [
{
'source_id': '资源模块内部类别ID',
'name': '类别名称',
'description': '描述',
'product_type': 'llm_model',
'product_type_title': '大模型API',
'sort_order': 0,
},
],
'products': [
{
'source_category_id': '对应的 source_id',
'resource_ref_id': '资源模块内部ID(如 llm.id)',
'product_code': '产品编码',
'product_name': '产品名称',
'product_type': 'llm_model',
'brief_intro': '简介',
'sort_order': 0,
},
],
}
去重规则:
- 类别:按
name + parent_id + org_id判断,已存在则跳过 - 产品:按
resource_ref_id + org_id判断,已存在则更新(名称、简介等),不存在则创建
2. 资源模块接口调度
产品模块通过 product_interface 字典调度资源模块,所有接口参数统一使用 resource_ref_id:
调用方(UI/API)
│
│ env.get_product_display_info(product_id='xxx')
▼
product_management (调度层)
│ 1. 查 product 表 → 获取 resource_ref_id
│ 2. 查 product_category 表 → 获取 resource_module
│ 3. 从 ServerEnv.product_interface 获取接口实现
│ 4. 调用接口函数,传入 resource_ref_id
▼
资源模块(如 llmage/product_interface.py)
│ 直接用 resource_ref_id 操作自己的数据
└─ 返回结果
3. ServerEnv 注册
模块初始化时将所有方法注册到 ServerEnv:
def load_product_management():
env = ServerEnv()
# 基础 CRUD
env.get_product_brief = get_product_brief
env.get_product_detail = get_product_detail
env.purchase_product = purchase_product
env.use_product = use_product
env.get_category_tree = get_category_tree
env.get_products_by_category = get_products_by_category
env.import_categories_and_products = import_categories_and_products
# 资源模块接口调度
env.get_product_display_info = get_product_display_info
env.check_product_availability = check_product_availability
env.check_product_consumable = check_product_consumable
env.execute_product = execute_product
env.execute_product_stream = execute_product_stream
env.calculate_product_cost = calculate_product_cost
资源模块标准接口规范
任何资源模块(如 llmage、supplychain)要对接产品模块,需实现以下 7 个接口函数并在 load 时注册到 ServerEnv.product_interface:
接口函数列表
| # | 函数名 | 参数 | 返回值 | 用途 |
|---|---|---|---|---|
| 1 | get_product_display |
(resource_ref_id) |
{success, pricing_text, pricing_detail, extra_info} |
展示定价信息 |
| 2 | check_product_availability |
(resource_ref_id, user_org_id) |
{available, reason} |
检查可用性 |
| 3 | check_product_consumable |
(resource_ref_id, user_id, user_org_id) |
{consumable, reason, min_balance, pricing_available} |
消费前综合预检 |
| 4 | execute_product_service |
(resource_ref_id, user_id, user_org_id, request_data) |
{success, result, usage_data, task_id, status} |
执行服务(非流式) |
| 5 | execute_product_service_stream |
(resource_ref_id, user_id, user_org_id, request_data) |
AsyncGenerator[{chunk, usage_data, done}] |
执行服务(流式) |
| 6 | calculate_product_cost |
(resource_ref_id, usage_data, user_org_id) |
{success, amount, cost, discount, pricing_program_id} |
计算费用 |
| 7 | load_product_category_product |
(parent_category_id) |
{success, categories, products} |
导入数据(标准化格式) |
注册方式
资源模块在其 __init__.py 或 init.py 的 load_* 函数中注册:
def load_llmage():
env = ServerEnv()
# ... 其他初始化 ...
from .product_interface import (
get_product_display, check_product_availability,
check_product_consumable, execute_product_service,
execute_product_service_stream, calculate_product_cost,
)
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,
}
resource_ref_id 映射
resource_ref_id存储在product.resource_ref_id字段- 对于 llmage:
resource_ref_id = llm.id - 产品模块调度时自动从 product 表提取该字段,资源模块直接使用
- 资源模块无需知道 product_code,产品模块无需知道资源模块内部结构
核心业务流程
产品导入
UI 操作 → import_category_products.dspy
→ env.import_categories_and_products('llmage', org_id, parent_cat_id, user_id)
→ importlib.import_module('llmage.init')
→ llmage.load_product_category_product(parent_cat_id) # 返回标准化数据
→ 产品模块执行去重写入
→ 返回统计: 新增N类别, 跳过M类别, 新增X产品, 更新Y产品
消费流程
1. 展示阶段
env.get_product_display_info(product_id)
→ 查 product → 查 category → 获取 resource_module
→ 调用 iface.get_product_display(resource_ref_id)
→ 返回定价文本 + 详情
2. 预检阶段
env.check_product_consumable(product_id, user_id, user_org_id)
→ 调用 iface.check_product_consumable(resource_ref_id, user_id, user_org_id)
→ 检查: 模型状态 + ppid定价 + 余额 ≥ min_balance
→ 返回: consumable + reason
3. 执行阶段
env.execute_product(product_id, request_data, user_id, user_org_id)
→ 调用 iface.execute_product_service(resource_ref_id, user_id, user_org_id, request_data)
→ 根据 llm.stream 选择 sync/async/stream 路径
→ 返回: result + usage_data + task_id
4. 计费阶段
env.calculate_product_cost(product_id, usage_data, user_org_id)
→ 调用 iface.calculate_product_cost(resource_ref_id, usage_data, user_org_id)
→ 调用 pricing 模块计算 + 客户折扣
→ 返回: amount + cost + discount
消费引擎 (product_use)
核心消费路由逻辑,支持订阅制和按量制:
product_use(product_id, user_id, user_org_id, used_amount, used_unit)
│
├─ 月度产品 (llm_monthly):
│ ├─ 查有效订阅 → 配额内扣减 (billing_mode='1')
│ └─ 超出配额 → 溢出计费 (overflow_rate × 超出量)
│
├─ 按量产品:
│ └─ sell_price = used_amount × product.price
│
├─ 供应商路由:
│ └─ product_resource → product_resource_supplier (按 priority+weight)
│
├─ 成本计算:
│ └─ supplychain.supplier_resource_price → unit_cost × used_amount
│
└─ 写入 product_usage_log
目录结构
product_management/
├── models/ # 数据模型定义 (JSON)
│ ├── product.json
│ ├── product_category.json
│ ├── product_resource.json
│ ├── product_resource_supplier.json
│ ├── product_subscription.json
│ └── product_usage_log.json
├── product_management/
│ ├── __init__.py # ServerEnv 注册 + 入口函数
│ └── core.py # ProductManager 全部业务逻辑
├── init/
│ └── data.yaml # 初始化数据 (appcodes 编码等)
├── json/ # CRUD 定义 (由 xls2crud 生成)
├── wwwroot/ # 前端页面 (由 xls2ui 生成)
├── README.md
└── setup.py
新增资源模块对接指南
以新模块 supplychain 为例:
- 实现接口函数 — 在
supplychain/product_interface.py中实现上述 7 个函数 - 注册到 ServerEnv — 在
supplychain/init.py的load_supplychain()中注册product_interface字典 - 导入函数 — 实现
load_product_category_product(parent_category_id)返回标准化格式 - 配置 appcodes — 在
init/data.yaml的resource_module下添加supplychain键值对 - 创建类别 — 在 UI 中创建产品类别,
resource_module选择supplychain - 触发导入 — 点击"产品导入"按钮,自动调用导入流程
所有参数使用 resource_ref_id(supplychain 的内部 ID),产品模块自动处理映射。
Description
Languages
Python
96%
Shell
4%