| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145 |
- """计划组需求明细:物化与读取。"""
- from __future__ import annotations
- from typing import Any
- from sqlalchemy.orm import Session
- from supply_infra.db.repositories.demand_belong_category_repo import DemandBelongCategoryRepository
- from supply_infra.db.repositories.demand_belong_pool_rel_repo import DemandBelongPoolRelRepository
- from supply_infra.db.repositories.multi_demand_pool_di_repo import MultiDemandPoolDiRepository
- from supply_infra.db.session import get_session
- MAX_DEMANDS_PER_BATCH = 30
- def _sort_category_units(
- units: list[tuple[int, int | None, list[Any]]],
- ) -> list[tuple[int, int | None, list[Any]]]:
- """同父分类相邻,同分类作为不可分割单元。"""
- return sorted(
- units,
- key=lambda item: (
- item[1] is None,
- item[1] if item[1] is not None else -1,
- item[0],
- ),
- )
- def pack_category_units(
- units: list[tuple[int, int | None, list[Any]]],
- *,
- max_demands_per_group: int = MAX_DEMANDS_PER_BATCH,
- ) -> list[list[int]]:
- """将分类需求单元打包为计划组;每组尽量不超过 max_demands_per_group 条需求。"""
- cap = max(1, int(max_demands_per_group))
- groups: list[list[int]] = []
- current: list[int] = []
- current_size = 0
- for category_id, _parent_id, demands in _sort_category_units(units):
- size = len(demands)
- if size <= 0:
- continue
- if size > cap:
- if current:
- groups.append(current)
- current = []
- current_size = 0
- groups.append([category_id])
- continue
- if current and current_size + size > cap:
- groups.append(current)
- current = []
- current_size = 0
- current.append(category_id)
- current_size += size
- if current:
- groups.append(current)
- return groups
- def split_even_batches(items: list[Any], *, max_per_batch: int = MAX_DEMANDS_PER_BATCH) -> list[list[Any]]:
- """按总数均分子批次:总数不超过上限则一批;否则递增组数直到每组不超过上限,余数从前组分配。"""
- n = len(items)
- if n == 0:
- return []
- cap = max(1, int(max_per_batch))
- if n <= cap:
- return [items]
- k = 2
- while True:
- base = n // k
- rem = n % k
- max_size = base + 1 if rem > 0 else base
- if max_size <= cap:
- break
- k += 1
- batches: list[list[Any]] = []
- idx = 0
- for i in range(k):
- size = base + (1 if i < rem else 0)
- batches.append(items[idx : idx + size])
- idx += size
- return batches
- def _priority_sort_key(name: str, priority_index: dict) -> tuple:
- return (
- priority_index.get(name, {}).get("source_rank_score") is None,
- -float(priority_index.get(name, {}).get("source_rank_score") or 0),
- float(priority_index.get(name, {}).get("global_demand_rank") or float("inf")),
- name,
- )
- def resolve_demands_for_category_ids(
- biz_dt: str,
- category_ids: list[int],
- *,
- session: Session | None = None,
- ) -> list[dict[str, Any]]:
- """按分类节点解析全部需求池记录(pool_id + demand_name)。"""
- selected_ids = list(dict.fromkeys(int(value) for value in category_ids))
- if session is None:
- with get_session() as owned_session:
- return resolve_demands_for_category_ids(
- biz_dt,
- selected_ids,
- session=owned_session,
- )
- belongs = DemandBelongCategoryRepository(session).list_by_category_ids(selected_ids)
- pool_ids_by_belong = DemandBelongPoolRelRepository(session).get_pool_ids_by_belong_ids(
- [int(row.id) for row in belongs]
- )
- pool_ids = sorted({pool_id for values in pool_ids_by_belong.values() for pool_id in values})
- pool_repo = MultiDemandPoolDiRepository(session)
- pool_rows = pool_repo.get_by_ids(pool_ids)
- from agents.demand_grade_agent.tools.demand_priority import build_demand_priority_index
- priority_index = build_demand_priority_index(pool_repo.list_by_biz_dt(biz_dt))
- candidates: list[dict[str, Any]] = []
- for row in pool_rows:
- if row.biz_dt != biz_dt or not row.demand_name:
- continue
- candidates.append({
- "pool_id": int(row.id),
- "demand_name": str(row.demand_name),
- })
- candidates.sort(
- key=lambda item: (
- *_priority_sort_key(item["demand_name"], priority_index),
- item["pool_id"],
- )
- )
- return candidates
|