Updated quality metrics validation tool

Merge request reports

Loading
+0 −0

Empty file added.

+45 −0
Changes for api/routers/analysis.py: 45 added lines, 0 removed lines.
Original line number Diff line number Diff line
"""분석 실행 API 엔드포인트"""

from fastapi import APIRouter, HTTPException
from api.schemas.analysis import AnalysisRunRequest, AnalysisRunResponse
from api.services import analysis_service
router = APIRouter()
service = analysis_service


@router.post("/run", response_model=AnalysisRunResponse)
async def run_analysis(request: AnalysisRunRequest):
    """
    품질 분석 실행

    선택된 지표와 설정값을 바탕으로 분석 수행.
    기존 코드의 run_analysis() 함수를 내부적으로 호출.

    요청 예시:
    {
        "dataset_id": "abc123",
        "metrics": ["completeness", "accuracy"],
        "config": {
            "completeness": {
                "required_columns": ["Na", "Al", "K", "Si"],
                "missing_values": ["?", "N/A", "null"],
                "granularity": "dataset"
            },
            "accuracy": {
                "rules": [
                    {
                        "measured_column": "RI",
                        "method": "statistical_bounds",
                        "k_sigma": 3.0,
                        "center": "mean"
                    }
                ]
            }
        }
    }
    """
    try:
        result = await service.execute(request)
        return result
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))
+59 −0
Changes for api/routers/datasets.py: 59 added lines, 0 removed lines.
Original line number Diff line number Diff line
"""데이터셋 관리 API 엔드포인트"""

from fastapi import APIRouter, UploadFile, File, HTTPException
from api.schemas.datasets import DatasetUploadResponse, DatasetInfo, DatasetPreview
from api.services import dataset_service

router = APIRouter()
service = dataset_service


@router.post("/upload", response_model=DatasetUploadResponse)
async def upload_dataset(file: UploadFile = File(...)):
    """
    데이터셋 업로드

    지원 형식: CSV, XLSX, XLS, ZIP
    기존 코드의 load_dataset() 함수를 내부적으로 호출
    """
    try:
        result = await service.upload_and_parse(file)
        return result
    except Exception as e:
        raise HTTPException(status_code=400, detail=str(e))


@router.post("/reference/upload", response_model=DatasetUploadResponse)
async def upload_reference_dataset(file: UploadFile = File(...)):
    """
    참조 데이터셋 업로드 (Accuracy, Consistency에서 사용)
    """
    try:
        result = await service.upload_and_parse(file, is_reference=True)
        return result
    except Exception as e:
        raise HTTPException(status_code=400, detail=str(e))


@router.get("/", response_model=list[DatasetInfo])
async def list_datasets():
    """업로드된 데이터셋 목록 조회"""
    return service.list_datasets()


@router.get("/{dataset_id}", response_model=DatasetInfo)
async def get_dataset(dataset_id: str):
    """특정 데이터셋 정보 조회"""
    result = service.get_dataset(dataset_id)
    if not result:
        raise HTTPException(status_code=404, detail="Dataset not found")
    return result


@router.get("/{dataset_id}/preview", response_model=DatasetPreview)
async def preview_dataset(dataset_id: str, rows: int = 10):
    """데이터셋 미리보기 (상위 N행)"""
    result = service.get_preview(dataset_id, rows)
    if not result:
        raise HTTPException(status_code=404, detail="Dataset not found")
    return result

api/routers/metrics.py

0 → 100644
+91 −0
Changes for api/routers/metrics.py: 91 added lines, 0 removed lines.
Original line number Diff line number Diff line
"""지표 설정 및 Pre-check API 엔드포인트"""

from fastapi import APIRouter, HTTPException
from api.schemas.metrics import (
    PrecheckRequest, PrecheckResponse,
    MetricConfigRequest
)
from api.services import metric_service

router = APIRouter()
service = metric_service


@router.post("/precheck", response_model=PrecheckResponse)
async def run_precheck(request: PrecheckRequest):
    """
    데이터셋 기반 지표별 pre-check 수행

    각 지표가 현재 데이터셋으로 평가 가능한지 판단:
    - Satisfied: 바로 계산 가능
    - Configuration Required: 추가 설정 필요
    - Missing Required Input: 입력 부족

    기존 코드의 build_metric_precheck() 함수를 내부적으로 호출
    """
    try:
        return service.run_precheck(request.dataset_id)
    except Exception as e:
        raise HTTPException(status_code=400, detail=str(e))


@router.post("/configure")
async def configure_metrics(config: MetricConfigRequest):
    """
    지표별 설정 저장

    사용자가 선택한 지표와 설정값을 저장.
    이후 /api/analysis/run에서 이 설정을 사용하여 분석 실행.
    """
    try:
        return service.save_config(config)
    except Exception as e:
        raise HTTPException(status_code=400, detail=str(e))


@router.get("/")
async def list_metrics():
    """지원하는 지표 목록 조회"""
    return {
        "metrics": [
            {
                "name": "completeness",
                "description": "필요한 정보가 충분히 존재하는지 평가",
                "requires_config": False,
            },
            {
                "name": "accuracy",
                "description": "데이터 값이 실제 값과 얼마나 일치하는지 평가",
                "requires_config": True,
            },
            {
                "name": "consistency",
                "description": "데이터가 정의된 규칙이나 형식을 준수하는지 평가",
                "requires_config": True,
            },
            {
                "name": "timeliness",
                "description": "데이터가 적시에 수집/처리되었는지 평가",
                "requires_config": True,
            },
            {
                "name": "reliability",
                "description": "데이터의 신뢰성 및 이상치 여부 평가",
                "requires_config": False,
            },
            {
                "name": "uniqueness",
                "description": "데이터 중복 여부 평가",
                "requires_config": False,
            },
        ]
    }


@router.get("/{metric_name}/config-schema")
async def get_metric_config_schema(metric_name: str):
    """특정 지표의 설정 스키마 조회"""
    schema = service.get_config_schema(metric_name)
    if not schema:
        raise HTTPException(status_code=404, detail=f"Unknown metric: {metric_name}")
    return schema

api/routers/results.py

0 → 100644
+59 −0
Changes for api/routers/results.py: 59 added lines, 0 removed lines.
Original line number Diff line number Diff line
"""결과 조회 API 엔드포인트"""

from fastapi import APIRouter, HTTPException
from api.schemas.analysis import AnalysisSummaryResponse, MetricDetailResponse
from api.services import analysis_service

router = APIRouter()
service = analysis_service


@router.get("/{analysis_id}/summary", response_model=AnalysisSummaryResponse)
async def get_analysis_summary(analysis_id: str):
    """
    분석 결과 요약 조회

    모든 평가된 지표의 점수, 상태, 요약 정보 반환.
    N/A인 지표는 사유를 함께 표시.
    """
    result = service.get_summary(analysis_id)
    if not result:
        raise HTTPException(status_code=404, detail="Analysis not found")
    return result


@router.get("/{analysis_id}/details/{metric}", response_model=MetricDetailResponse)
async def get_metric_detail(analysis_id: str, metric: str):
    """
    개별 지표 상세 결과 조회

    지표별 세부 데이터, 규칙별 결과, 샘플 데이터 반환.
    """
    result = service.get_metric_detail(analysis_id, metric)
    if not result:
        raise HTTPException(status_code=404, detail="Result not found")
    return result


@router.get("/{analysis_id}/rules/{metric}")
async def get_metric_rules(analysis_id: str, metric: str):
    """
    지표별 규칙 결과 조회 (Accuracy, Consistency)
    """
    result = service.get_rule_results(analysis_id, metric)
    if not result:
        raise HTTPException(status_code=404, detail="Rule results not found")
    return result


@router.get("/{analysis_id}/samples/{metric}")
async def get_metric_samples(analysis_id: str, metric: str, limit: int = 50):
    """
    지표별 샘플 데이터 조회

    valid/invalid 또는 matching/violating 샘플 반환.
    """
    result = service.get_samples(analysis_id, metric, limit)
    if not result:
        raise HTTPException(status_code=404, detail="Samples not found")
    return result
Loading
Loading