조회하고 진단하기
앞선 문서들에서는 실행 중에 기록을 수집하고, 아티팩트를 등록하며, 여러 후보의 측정값을 비교했습니다.
이 문서에서는 새 점수를 계산하는 과정이 넘어, 로컬 워크스페이스에 이미 저장된 실행과 기록을 다시 읽어 다음 질문에 답하는 과정을 설명합니다.
- 어떤 실행이 저장되어 있나요?
- 한 실행에는 어떤 단계와 기록이 포함되어 있나요?
- 평가 결과는 저장된 기록에서 다시 확인할 수 있나요?
- 실행 기록에서 빠졌거나 확인해야 할 부분이 있나요?
실행 가능한 예제
아래의 예제를 통해 Contexta가 어떻게 실행을 조회하고 진단하는지 알아봅시다.
"""Query a measured model run and diagnose missing package-stage evidence."""
from pathlib import Path
from sklearn.datasets import load_diabetes
from sklearn.linear_model import LinearRegression
from sklearn.metrics import r2_score
from sklearn.model_selection import train_test_split
from contexta import Contexta
from contexta.contract import MetricPayload, MetricRecord, Project, RecordEnvelope, Run, StageExecution
PROJECT_NAME = "diabetes-review"
RUN_NAME = "linear-candidate"
RUN_REF = f"run:{PROJECT_NAME}.{RUN_NAME}"
STARTED_AT = "2026-05-27T09:00:00Z"
ENDED_AT = "2026-05-27T09:05:00Z"
def metric_record(metric_key: str, value: float, stage_name: str, record_name: str) -> MetricRecord:
stage_ref = f"stage:{PROJECT_NAME}.{RUN_NAME}.{stage_name}"
return MetricRecord(
envelope=RecordEnvelope(
record_ref=f"record:{PROJECT_NAME}.{RUN_NAME}.{record_name}",
record_type="metric",
recorded_at=ENDED_AT,
observed_at=ENDED_AT,
producer_ref="sdk.python.local",
run_ref=RUN_REF,
stage_execution_ref=stage_ref,
),
payload=MetricPayload(
metric_key=metric_key,
value=value,
value_type="float",
unit="ratio" if metric_key == "r2" else "rows",
aggregation_scope="stage",
subject_ref=stage_ref,
summary_basis="raw_observation",
),
)
features, targets = load_diabetes(return_X_y=True)
train_x, test_x, train_y, test_y = train_test_split(
features, targets, test_size=0.2, random_state=42
)
model = LinearRegression().fit(train_x, train_y)
r2 = r2_score(test_y, model.predict(test_x))
workspace = Path(".contexta")
ctx = Contexta(workspace=str(workspace), config={"project_name": PROJECT_NAME})
metadata = ctx.metadata_store
try:
metadata.projects.put_project(
Project(project_ref=f"project:{PROJECT_NAME}", name=PROJECT_NAME, created_at=STARTED_AT)
)
metadata.runs.put_run(
Run(
run_ref=RUN_REF,
project_ref=f"project:{PROJECT_NAME}",
name=RUN_NAME,
status="completed",
started_at=STARTED_AT,
ended_at=ENDED_AT,
)
)
for order, stage_name in enumerate(("train", "evaluate", "package")):
metadata.stages.put_stage_execution(
StageExecution(
stage_execution_ref=f"stage:{PROJECT_NAME}.{RUN_NAME}.{stage_name}",
run_ref=RUN_REF,
stage_name=stage_name,
status="completed",
started_at=STARTED_AT,
ended_at=ENDED_AT,
order_index=order,
)
)
ctx.record_store.append(metric_record("training.rows", float(len(train_x)), "train", "training-rows"))
ctx.record_store.append(metric_record("r2", r2, "evaluate", "r2"))
# No package-stage metric is written: diagnostics should make this gap visible.
runs = ctx.list_runs(PROJECT_NAME)
snapshot = ctx.get_run_snapshot(RUN_REF)
queried_r2 = next(record.value for record in snapshot.records if record.key == "r2")
diagnostics = ctx.diagnose_run(RUN_REF)
print(f"Queried runs: {', '.join(run.run_id for run in runs)}")
print(f"Snapshot: {len(snapshot.stages)} stages, {len(snapshot.records)} records")
print(f"Queried r2: {queried_r2:.3f}")
print(f"Diagnostics issues: {len(diagnostics.issues)}")
for issue in diagnostics.issues:
print(f"- {issue.severity}: {issue.code} ({issue.subject_ref})")
finally:
metadata.close()
코드를 query_diagnostics.py로 저장한 뒤, Contexta가 설치된 환경에서 실행하세요.
uv run query_diagnostics.py
이 예제에서는 package 단계에 일부러 메트릭 기록을 남기지 않습니다.
예제에서 수행하는 조사 흐름
이 예제에는 기록 생성과 기록 조회가 함께 들어 있습니다. 각 부분의 역할은 다음과 같습니다.
| 코드 구간 | 역할 |
|---|---|
LinearRegression().fit(...)와 r2_score(...) | 실제 학습 모델의 평가값을 계산합니다. |
metadata.projects.put_project(...) | 조회할 프로젝트의 기준점을 표준 스토어에 저장합니다. |
metadata.runs.put_run(...) | 평가 결과가 속하는 실행을 저장합니다. |
metadata.stages.put_stage_execution(...) | train, evaluate, package 단계를 저장합니다. |
ctx.record_store.append(...) | 계산한 r2와 학습 데이터 행 수를 각 단계의 메트릭 기록으로 저장합니다. |
ctx.list_runs(PROJECT_NAME) | 프로젝트에 저장된 실행 목록을 조회합니다. |
ctx.get_run_snapshot(RUN_REF) | 실행의 단계와 기록을 하나의 스냅샷으로 조립해 읽습니다. |
ctx.diagnose_run(RUN_REF) | 스냅샷의 기록 구성을 검사해 확인할 항목을 찾습니다. |
실행 결과 확인하기
머신러닝 예제에서는 터미널에 다음과 같은 출력이 표시됩니다.
Queried runs: run:diabetes-review.linear-candidate
Snapshot: 3 stages, 2 records
Queried r2: 0.453
Diagnostics issues: 1
- info: missing_stage_metrics (stage:diabetes-review.linear-candidate.package)
이 예제는 diabete 데이터셋을 사용하여 선형 회귀를 진행한 결과를 기반으로 여러가지 조회와 진단이 이루어집니다.
| 출력 | 의미 |
|---|---|
Queried runs | ctx.list_runs(...)가 표준 메타데이터 스토어에서 찾은 실행입니다. |
Snapshot: 3 stages, 2 records | 저장된 실행에는 train, evaluate, package 세 단계가 있지만 메트릭 기록은 두 개뿐입니다. |
Queried r2 | ctx.get_run_snapshot(...)으로 불러온 저장 기록 중 r2 값을 다시 읽은 결과입니다. |
Diagnostics issues: 1 | ctx.diagnose_run(...)이 이 실행에서 확인할 항목을 한 건 발견했습니다. |
missing_stage_metrics | package 단계가 완료로 저장되었지만, 그 단계에 연결된 메트릭 기록이 없습니다. |
실행 목록 조회
runs = ctx.list_runs(PROJECT_NAME)
이 조회는 특정 프로젝트에 어떤 실행이 저장되어 있는지 확인하는 시작점입니다.
예제에서는 run:diabetes-review.linear-candidate 한 건만 저장했으므로, 터미널에도 그 실행 하나가 표시됩니다.
실제 프로젝트에서는 이 목록에서 조사하려는 실행을 고른 뒤, 실행 참조를 get_run_snapshot() 또는 diagnose_run()에 전달할 수 있습니다.
실행 스냅샷 조회
snapshot = ctx.get_run_snapshot(RUN_REF)
queried_r2 = next(record.value for record in snapshot.records if record.key == "r2")
스냅샷은 해당 실행에 연결된 단계 · 레코드 · 아티팩트 · 배치 · 샘플 · 배포와 같은 재료를 한 위치에서 읽을 수 있게 조립한 결과입니다.
이 예제에서는 다음과 같은 구조가 조회됩니다.
run:diabetes-review.linear-candidate
├─ stage:train
│ └─ metric: training.rows = 353
├─ stage:evaluate
│ └─ metric: r2 = 0.453
└─ stage:package
└─ metric: 없음
따라서 Queried r2: 0.453은 실제로 계산되어 스토어에 저장된 메트릭 기록을 스냅샷에서 다시 찾아 읽은 값입니다.
실행 진단
diagnostics = ctx.diagnose_run(RUN_REF)
for issue in diagnostics.issues:
print(issue.severity, issue.code, issue.subject_ref)
진단은 스냅샷에 저장된 구조와 기록을 검사합니다. 기본 정책에서는 완료된 단계에 메트릭 기록이 있는지 살펴봅니다.
이 예제의 train 단계에는 training.rows가 있고, evaluate 단계에는 r2가 있으므로 문제가 없습니다.
하지만 package 단계는 completed 상태이지만 연결된 메트릭 기록을 일부러 남기지 않았습니다. 그 결과 아래 이슈가 반환됩니다.
| 진단 필드 | 값 | 읽는 방법 |
|---|---|---|
severity | info | 실행 자체가 실패하지는 않았지만, 확인할 항목이 있습니다. |
code | missing_stage_metrics | 완료된 단계에 메트릭 기록이 없습니다. |
subject_ref | stage:diabetes-review.linear-candidate.package | 어느 단계의 기록을 보완하거나 검토해야 하는지 가리킵니다. |
여기서 r2 = 0.453이라는 성능 결과와 missing_stage_metrics라는 진단 결과는 서로 다른 질문에 답합니다.
| 기능 | 답하는 질문 |
|---|---|
| 조회 | 저장된 실행과 그 안의 기록은 무엇인가요? |
| 비교 | 여러 실행의 측정 결과는 어떻게 달라졌나요? |
| 진단 | 저장된 기록에서 누락되었거나 의심스러운 지점은 어디인가요? |
즉, 점수가 낮다고 자동으로 진단 이슈가 되는 것은 아닙니다.
반대로 점수가 좋더라도 필요한 단계 기록이 빠져 있다면, 결과를 승인하거나 전달하기 전에 그 빈 부분을 확인해야 합니다.
주요 조회 및 진단 API
| API | 사용 시점 |
|---|---|
ctx.list_runs(...) | 프로젝트에 어떤 실행이 저장되어 있는지 찾을 때 |
ctx.get_run_snapshot(...) | 하나의 실행에 연결된 단계와 기록을 모아 읽을 때 |
ctx.compare_runs(...) | 두 저장 실행의 메트릭과 구조 차이를 볼 때 |
ctx.select_best_run(...) | 같은 메트릭 기준으로 후보 실행을 선택할 때 |
ctx.diagnose_run(...) | 누락, 불완전 상태, 실패한 하위 단위 같은 조사 단서를 찾을 때 |
ctx.traverse_lineage(...) | 실행, 결과물, 배포 사이의 연결을 따라갈 때 |
ctx.build_snapshot_report(...) | 조사 결과를 사람이 읽기 쉬운 리포트로 만들 때 |
관련 문서
- 실행 비교하기: 조회할 후보 실행의 비교 근거를 만드는 방법을 설명합니다.
- 일반적인 Contexta 워크플로: 스냅샷, 리포트, 리니지까지 이어지는 일상 흐름을 다룹니다.
- API 레퍼런스: 조회와 진단 API의 정확한 반환 타입을 확인합니다.