File size: 1,700 Bytes
7c447a5 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
// src/services/api.ts
import type { JobConfig } from '../types';
export type PipelinePlots = {
original_sentiment: string;
counterfactual_sentiment: string;
};
export type PipelineResultsDTO = {
data_loaded: number;
model_loaded: string;
generation_file: string;
generation_samples: number;
counterfactual_file: string;
counterfactual_added: number;
counterfactual_total: number;
sampling_method: string;
sentiment_subset_file: string;
sentiment_subset_size: number;
cf_sentiment_subset_file: string;
cf_sentiment_subset_size: number;
// 後端還會給 stereotype 的欄位,但前端不需要可不宣告
config_used: import('../types').JobConfig;
metrics: import('../types').JobMetrics & {
finalMeanDiff: number;
cfFinalMeanDiff: number;
};
plots: PipelinePlots;
};
export type PipelineResponseDTO = {
status: 'success' | 'error';
message: string;
timestamp: string;
results: PipelineResultsDTO;
};
const BASE = import.meta.env.VITE_API_BASE ?? '/api';
async function runPipeline(config: any) {
const r = await fetch(`${BASE}/pipeline`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ config }),
});
if (!r.ok) {
const text = await r.text();
throw new Error(`Pipeline failed (${r.status}): ${text}`);
}
return r.json();
}
async function checkHealth() {
const r = await fetch(`${BASE}/health`);
return r.json();
}
function resolvePath(p?: string) {
if (!p) return '';
if (p.startsWith('http')) return p;
const path = p.startsWith('/') ? p : `/${p}`;
return `${BASE}${path}`;
}
export const MLBiasAPI = { runPipeline, checkHealth, resolvePath };
|