75 lines
3.3 KiB
Python
75 lines
3.3 KiB
Python
"""init_base — 공유 베이스 정책(_base) 시드 (P5, 계획서 D).
|
||
|
||
시뮬레이터로 UCB Q-Table 을 학습시켜 learning 스키마의 _base(scope=base) 버전에 저장한다.
|
||
신규 테넌트는 cold-start 시 이 베이스를 warm-start 복제해 어느 정도 학습된 상태로 시작한다.
|
||
|
||
실행: cd agent && APP_ENV=local python -m tools.init_base [--action-space 9] [--episodes 500]
|
||
차원(state×action)은 신규 테넌트와 호환돼야 복제된다(데모 테넌트=162×9).
|
||
"""
|
||
|
||
import argparse
|
||
import asyncio
|
||
|
||
from common.database.db_session_manager import DB_SESSION_MNG
|
||
from common.database.model.models import BASE_COMPANY_ID
|
||
from common.logger import LOG
|
||
from eval_harness.buyer import HeuristicBuyer, Scenario, best_actions, make_card_effectiveness
|
||
from eval_harness.registry import build_policy
|
||
from eval_harness.simulator import run_episode
|
||
from negotiation.qtable.infra.repository.learning_repository import LearningRepository
|
||
from tenancy.config_loader import TenantConfigLoader
|
||
|
||
|
||
async def seed_base(action_space: int = 9, episodes: int = 500, seed: int = 123,
|
||
anchor: float = 8000, target: float = 10000) -> dict:
|
||
cfg = TenantConfigLoader().load(BASE_COMPANY_ID) # _base: state 162
|
||
S = cfg.state.state_space_size
|
||
A = action_space
|
||
lr, gamma = cfg.policy.learning_rate, cfg.policy.gamma
|
||
|
||
# 시뮬레이터로 베이스 학습
|
||
policy = build_policy("qtable_ucb", cfg.state, A, cfg.policy, seed=seed)
|
||
eff = make_card_effectiveness(A, seed=seed)
|
||
buyer = HeuristicBuyer(eff, seed=seed)
|
||
scenario = Scenario(anchor_price=anchor, target_price=target)
|
||
for i in range(episodes):
|
||
buyer.reseed(seed * 100_000 + i)
|
||
run_episode(policy, buyer, scenario, cfg.state, cfg.reward, A, learn=True)
|
||
|
||
# _base 버전(scope=base)에 저장 (재시드 시 기존 셀 비우고 갱신)
|
||
repo = LearningRepository(BASE_COMPANY_ID)
|
||
vid = await repo.get_or_create_active_version(
|
||
state_space_size=S, action_space_size=A, learning_rate=lr, discount_factor=gamma,
|
||
scope=1, version_name="base_v000")
|
||
await repo.reset_learning() # 이전 셀 정리(버전은 유지)
|
||
cells = policy.qtable.nonzero_cells()
|
||
for st, a, q, c in cells:
|
||
await repo.upsert_cell(vid, st, a, q, c)
|
||
|
||
return {"version_id": str(vid), "state_space": S, "action_space": A,
|
||
"episodes": episodes, "cells": len(cells), "good_cards": best_actions(eff)}
|
||
|
||
|
||
async def _main(args):
|
||
info = await seed_base(action_space=args.action_space, episodes=args.episodes)
|
||
print("=" * 56)
|
||
print(" 베이스 정책 시드 완료 (_base, scope=base)")
|
||
print(f" 버전: {info['version_id']} 차원: {info['state_space']}x{info['action_space']}")
|
||
print(f" 학습 에피소드: {info['episodes']} 저장 셀: {info['cells']}")
|
||
print(f" (숨은) 좋은 카드: {info['good_cards']}")
|
||
print(" → 이제 신규 테넌트 첫 협상 시 warm-start 로 이 베이스를 복제합니다.")
|
||
print("=" * 56)
|
||
await DB_SESSION_MNG.dispose_all()
|
||
|
||
|
||
def main():
|
||
ap = argparse.ArgumentParser(description="공유 베이스 정책 시드 (P5)")
|
||
ap.add_argument("--action-space", type=int, default=9)
|
||
ap.add_argument("--episodes", type=int, default=500)
|
||
args = ap.parse_args()
|
||
asyncio.run(_main(args))
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main()
|