product_management

产品管理模块 —— 统一管理产品目录、类别树、资源绑定、订阅、消费引擎及资源模块对接。

模块定位

product_management 是产品生命周期的中枢,负责:

  1. 管理产品类别树和产品注册表
  2. 从资源模块(如 llmage导入类别和产品
  3. 通过标准接口调度资源模块完成展示、预检、执行、计费
  4. 管理资源绑定、供应商路由、订阅与配额
  5. 记录消费日志并生成统计

数据模型

表名 说明
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__.pyinit.pyload_* 函数中注册:

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 字段
  • 对于 llmageresource_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 为例:

  1. 实现接口函数 — 在 supplychain/product_interface.py 中实现上述 7 个函数
  2. 注册到 ServerEnv — 在 supplychain/init.pyload_supplychain() 中注册 product_interface 字典
  3. 导入函数 — 实现 load_product_category_product(parent_category_id) 返回标准化格式
  4. 配置 appcodes — 在 init/data.yamlresource_module 下添加 supplychain 键值对
  5. 创建类别 — 在 UI 中创建产品类别,resource_module 选择 supplychain
  6. 触发导入 — 点击"产品导入"按钮,自动调用导入流程

所有参数使用 resource_ref_idsupplychain 的内部 ID产品模块自动处理映射。

Description
No description provided
Readme 566 KiB
Languages
Python 96%
Shell 4%