hpce-dev / data /seed.py
์ด๋™ํ˜„
[DOCS] ๋ฐฑ์—”๋“œ ์ „๋ฐ˜ docstring ๋ณด๊ฐ• (Google ์Šคํƒ€์ผ Args/Returns/Raises)
58debbc
Raw
History Blame Contribute Delete
8.28 kB
from __future__ import annotations
"""
์‹œ๋‚˜๋ฆฌ์˜ค ์นดํƒˆ๋กœ๊ทธ ์‹œ๋“œ (Intent / Action / Behavior)
๋“ฑ๋ก๋œ ๋ชจ๋“  ์‹œ๋‚˜๋ฆฌ์˜ค(available_scenarios)๋ฅผ catalog_* ํ…Œ์ด๋ธ”์— scenario_id์™€ ํ•จ๊ป˜ ์ ์žฌํ•œ๋‹ค.
โ†’ AdminPage๊ฐ€ ์‹œ๋‚˜๋ฆฌ์˜ค๋ณ„ ์นดํƒˆ๋กœ๊ทธ๋ฅผ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์กฐํšŒํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•œ๋‹ค.
"""
import json
import logging
from config import settings
from data.executor import get_executor, DuckDBExecutor
from core.engines import config, available_scenarios
logger = logging.getLogger(__name__)
# ์‹œ๋‚˜๋ฆฌ์˜ค ๋ฉ”ํƒ€(scenarios ํ…Œ์ด๋ธ”) ํ‘œ์‹œ์šฉ ์ด๋ฆ„
_SCENARIO_NAMES = {
"cs-myk-v3": "๋งˆ์ดK CS ์ƒ๋‹ด ์‹œ์—ฐ",
"bundle-v3": "๊ฒฐํ•ฉ ์ƒํ’ˆ ์ถ”์ฒœ ์‹œ์—ฐ",
"worker-v3": "์ง์žฅ์ธ ๋ผ์ดํ”„์ผ€์–ด ์‹œ์—ฐ",
}
def seed_catalogs() -> None:
"""๋“ฑ๋ก๋œ ๋ชจ๋“  ์‹œ๋‚˜๋ฆฌ์˜ค์˜ ์นดํƒˆ๋กœ๊ทธ๋ฅผ ์ ์žฌํ•œ๋‹ค.
catalog_intentsยทcatalog_actionsยทcatalog_behaviors๋ฅผ ๋น„์šด ๋’ค
available_scenarios()์˜ ๋ชจ๋“  ์‹œ๋‚˜๋ฆฌ์˜ค๋ฅผ ๋‹ค์‹œ ์ ์žฌํ•œ๋‹ค(์ „์ฒด ๊ต์ฒด).
"""
ex = get_executor()
for tbl in ("catalog_intents", "catalog_actions", "catalog_behaviors"):
ex.execute(f"DELETE FROM {tbl}")
for sid in available_scenarios():
_seed_one(ex, sid)
def _seed_one(ex: DuckDBExecutor, scenario_id: str) -> None:
"""ํ•œ ์‹œ๋‚˜๋ฆฌ์˜ค์˜ ์นดํƒˆ๋กœ๊ทธ๋ฅผ catalog_* ํ…Œ์ด๋ธ”์— ์ ์žฌํ•œ๋‹ค.
์‹œ๋‚˜๋ฆฌ์˜ค ๋ฉ”ํƒ€(scenarios)์™€ IntentยทActionยทBehavior ์นดํƒˆ๋กœ๊ทธ๋ฅผ ์ ์žฌํ•œ๋‹ค.
Action์€ Intent-ํ‚ค 3์ฑ„๋„ ๊ตฌ์กฐ(dict)์™€ ๊ตฌ๋ฒ„์ „ ๋ฆฌ์ŠคํŠธ๋ฅผ ๋ชจ๋‘ ์ฒ˜๋ฆฌํ•˜๊ณ ,
Behavior๋Š” tree-2stepยทsingle-selectยท๊ตฌ๋ฒ„์ „ steps ๊ตฌ์กฐ๋ฅผ ๋ชจ๋‘ ์ฒ˜๋ฆฌํ•œ๋‹ค.
Args:
ex: ์นดํƒˆ๋กœ๊ทธ๋ฅผ ์ ์žฌํ•  DuckDB executor.
scenario_id: ์ ์žฌํ•  ์‹œ๋‚˜๋ฆฌ์˜ค ID.
"""
# โ”€โ”€ ์‹œ๋‚˜๋ฆฌ์˜ค ๋ฉ”ํƒ€ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
taxonomy = config.get_taxonomy(scenario_id)
description = config.load_layer(scenario_id, "input").get("description", "")
ex.execute(
"INSERT OR REPLACE INTO scenarios (id, name, version, description) VALUES (?, ?, ?, ?)",
[
scenario_id,
_SCENARIO_NAMES.get(scenario_id, scenario_id),
taxonomy.get("version", ""),
description,
],
)
# โ”€โ”€ Intent ์นดํƒˆ๋กœ๊ทธ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
rows = [
[
scenario_id,
i["id"], i["name"],
i["L1_id"], i["L1_name"],
i["L2_id"], i["L2_name"],
i["inference_type"],
json.dumps(i.get("features", []), ensure_ascii=False),
]
for i in taxonomy["intents"]
]
ex.executemany(
"INSERT INTO catalog_intents "
"(scenario_id, intent_id, intent_name, L1_id, L1_name, L2_id, L2_name, inference_type, features_json) "
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)",
rows,
)
# โ”€โ”€ Action ์นดํƒˆ๋กœ๊ทธ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
actions_data = config.get_actions(scenario_id)
a_rows: list[list] = []
raw_actions = actions_data["actions"]
if isinstance(raw_actions, dict):
# v0.2.0: Intent-ํ‚ค 3์ฑ„๋„ ๊ตฌ์กฐ โ†’ intent ร— channel ๋กœ ํ‰๋ฉดํ™”
for intent_id, ch_map in raw_actions.items():
for channel, body in ch_map.items():
if isinstance(body, dict): # ๊ณ ๊ฐ์„ผํ„ฐ ์ƒ๋‹ด์‚ฌ ์ปจํ…์ŠคํŠธ (์ƒํ™ฉ+์•ˆ๋‚ด)
message = f"์ƒํ™ฉ: {body.get('situation', '')} / ์•ˆ๋‚ด: {body.get('guidance', '')}"
else:
message = str(body)
a_rows.append([
scenario_id,
f"{intent_id}#{channel}", channel,
json.dumps([intent_id], ensure_ascii=False),
"", channel, message,
])
else:
# ๊ตฌ๋ฒ„์ „: action ๋ฆฌ์ŠคํŠธ
for a in raw_actions:
a_rows.append([
scenario_id,
a["id"], a["name"],
json.dumps(a.get("intents", []), ensure_ascii=False),
a.get("condition", ""), a["channel"], a.get("message", ""),
])
ex.executemany(
"INSERT INTO catalog_actions "
"(scenario_id, action_id, action_name, intents_json, condition, channel, message) "
"VALUES (?, ?, ?, ?, ?, ?, ?)",
a_rows,
)
# โ”€โ”€ Behavior ์นดํƒˆ๋กœ๊ทธ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
behaviors_data = config.get_behaviors(scenario_id)
b_rows: list[list] = []
structure = behaviors_data.get("structure")
if structure == "tree-2step":
# 2๋‹จ๊ณ„ ํŠธ๋ฆฌ: step1.behaviors + step2.by_parent + step2.common
for b in behaviors_data["step1"]["behaviors"]:
b_rows.append([scenario_id, b["id"], 1, b["name"], b["event_type"], b["entity"]])
for parent_id, items in behaviors_data["step2"]["by_parent"].items():
for b in items:
b_rows.append([scenario_id, b["id"], 2, b["name"], b["event_type"], b["entity"]])
for b in behaviors_data["step2"]["common"]:
b_rows.append([scenario_id, b["id"], 2, b["name"], b["event_type"], b["entity"]])
elif structure == "single-select":
# ๋‹จ์ผ ์„ ํƒ: apps[] (1๋‹จ๊ณ„, app_open ๋‹จ์ผํ™”)
for b in behaviors_data["apps"]:
b_rows.append([scenario_id, b["id"], 1, b["name"], b["event_type"], b["entity"]])
else:
# ์˜› ์–‘์‹: steps[] ํ‰๋ฉด
for step_block in behaviors_data["steps"]:
step = step_block["step"]
for b in step_block["behaviors"]:
b_rows.append([scenario_id, b["id"], step, b["name"], b["event_type"], b["entity"]])
ex.executemany(
"INSERT INTO catalog_behaviors "
"(scenario_id, behavior_id, step, behavior_name, event_type, entity) "
"VALUES (?, ?, ?, ?, ?, ?)",
b_rows,
)
logger.info(
f"Seeded catalog [{scenario_id}]: intents={len(rows)} actions={len(a_rows)} behaviors={len(b_rows)}"
)
def load_intents_catalog(scenario_id: str = settings.SCENARIO_ID) -> list[dict]:
"""์‹œ๋‚˜๋ฆฌ์˜ค๋ณ„ Intent ์นดํƒˆ๋กœ๊ทธ๋ฅผ ์กฐํšŒํ•œ๋‹ค.
Args:
scenario_id: ์กฐํšŒํ•  ์‹œ๋‚˜๋ฆฌ์˜ค ID (๊ธฐ๋ณธ๊ฐ’์€ settings.SCENARIO_ID).
Returns:
Intent ์ •์˜ dict์˜ ๋ชฉ๋ก (idยทnameยท๊ณ„์ธตยทinference_typeยทfeatures ํฌํ•จ).
"""
ex = get_executor()
df = ex.to_pandas(
"SELECT intent_id, intent_name, L1_id, L1_name, L2_id, L2_name, inference_type, features_json "
"FROM catalog_intents WHERE scenario_id = ?",
[scenario_id],
)
rows = []
for _, r in df.iterrows():
rows.append({
"id": r["intent_id"],
"name": r["intent_name"],
"L1_id": r["L1_id"],
"L1_name": r["L1_name"],
"L2_id": r["L2_id"],
"L2_name": r["L2_name"],
"inference_type": r["inference_type"],
"features": json.loads(r["features_json"]) if r["features_json"] else [],
})
return rows
def load_behaviors_catalog(scenario_id: str = settings.SCENARIO_ID) -> dict[str, dict]:
"""์‹œ๋‚˜๋ฆฌ์˜ค๋ณ„ Behavior ์นดํƒˆ๋กœ๊ทธ๋ฅผ ์กฐํšŒํ•œ๋‹ค.
Args:
scenario_id: ์กฐํšŒํ•  ์‹œ๋‚˜๋ฆฌ์˜ค ID (๊ธฐ๋ณธ๊ฐ’์€ settings.SCENARIO_ID).
Returns:
behavior_id๋ฅผ ํ‚ค๋กœ ํ•˜๊ณ  stepยทnameยทevent_typeยทentity๋ฅผ ๋‹ด์€ dict๋ฅผ
๊ฐ’์œผ๋กœ ๊ฐ€์ง€๋Š” ๋งคํ•‘.
"""
ex = get_executor()
df = ex.to_pandas(
"SELECT behavior_id, step, behavior_name, event_type, entity "
"FROM catalog_behaviors WHERE scenario_id = ?",
[scenario_id],
)
result = {}
for _, r in df.iterrows():
result[r["behavior_id"]] = {
"step": int(r["step"]),
"name": r["behavior_name"],
"event_type": r["event_type"],
"entity": r["entity"],
}
return result