78 lines
2.9 KiB
Python
78 lines
2.9 KiB
Python
"""Low-level helper methods for experiment sync service."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from .shared import Any, Dict, Experiment, ExperimentTruthNodeSync, Optional, TruthNode, and_, now_cn_aware, select
|
|
|
|
|
|
class ExperimentSyncHelpersMixin:
|
|
"""Fetchers and sync-data mutation helpers."""
|
|
|
|
async def _get_experiment(self, experiment_id: int, tenant_id: int) -> Optional[Experiment]:
|
|
result = await self.db.execute(
|
|
select(Experiment).where(
|
|
and_(Experiment.id == experiment_id, Experiment.tenant_id == tenant_id)
|
|
)
|
|
)
|
|
return result.scalar_one_or_none()
|
|
|
|
async def _get_truth_node(self, truth_node_id: int, tenant_id: int) -> Optional[TruthNode]:
|
|
result = await self.db.execute(
|
|
select(TruthNode).where(
|
|
and_(TruthNode.id == truth_node_id, TruthNode.tenant_id == tenant_id)
|
|
)
|
|
)
|
|
return result.scalar_one_or_none()
|
|
|
|
async def _get_sync_record(self, sync_id: int, tenant_id: int) -> Optional[ExperimentTruthNodeSync]:
|
|
result = await self.db.execute(
|
|
select(ExperimentTruthNodeSync).where(
|
|
and_(ExperimentTruthNodeSync.id == sync_id, ExperimentTruthNodeSync.tenant_id == tenant_id)
|
|
)
|
|
)
|
|
return result.scalar_one_or_none()
|
|
|
|
def _calc_confidence(self, current_score: Optional[float]) -> float:
|
|
score = float(current_score or 0.0)
|
|
if score > 1:
|
|
score /= 100.0
|
|
return round(max(0.0, min(1.0, score)), 2)
|
|
|
|
def _build_sync_data(
|
|
self,
|
|
experiment: Experiment,
|
|
truth_node: TruthNode,
|
|
sync_type: str,
|
|
) -> Dict[str, Any]:
|
|
return {
|
|
"sync_type": sync_type,
|
|
"experiment_summary": {
|
|
"id": experiment.id,
|
|
"title": experiment.title,
|
|
"status": experiment.status,
|
|
"target_metric": experiment.target_metric,
|
|
"current_score": experiment.current_score,
|
|
},
|
|
"previous_truth_content": truth_node.content,
|
|
}
|
|
|
|
async def _apply_sync_to_truth_node(
|
|
self,
|
|
record: ExperimentTruthNodeSync,
|
|
truth_node: TruthNode,
|
|
) -> None:
|
|
content = truth_node.content if isinstance(truth_node.content, dict) else {}
|
|
if not isinstance(content, dict):
|
|
content = {"raw": str(truth_node.content)}
|
|
sync_section = content.get("experiment_sync", {})
|
|
sync_section["last_sync"] = {
|
|
"sync_id": record.id,
|
|
"sync_type": record.sync_type,
|
|
"confidence_score": record.confidence_score,
|
|
"experiment_summary": (record.sync_data or {}).get("experiment_summary", {}),
|
|
"applied_at": now_cn_aware().isoformat(),
|
|
}
|
|
content["experiment_sync"] = sync_section
|
|
truth_node.content = content
|
|
truth_node.version = int(truth_node.version or 1) + 1
|