File size: 3,015 Bytes
f0b240d 7e7e06a f0b240d 0f0ce9b f0b240d 0f0ce9b f0b240d 7e7e06a f0b240d 46cc63a f0b240d | 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 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | import type {
ModelStatusEntry,
PredictResponse,
PredictionsListResponse,
SuggestedVideo,
VideoResponse,
} from "../types/api";
const BASE = import.meta.env.VITE_API_BASE_URL ?? "";
function parseApiError(body: unknown, fallback: string): string {
if (!body || typeof body !== "object") return fallback;
const detail = (body as { detail?: unknown }).detail;
if (typeof detail === "string") return detail;
if (Array.isArray(detail)) {
return detail
.map((item) => {
if (item && typeof item === "object" && "msg" in item) {
return String((item as { msg: unknown }).msg);
}
return String(item);
})
.join("; ");
}
return fallback;
}
async function request<T>(path: string, init?: RequestInit): Promise<T> {
const res = await fetch(`${BASE}${path}`, {
...init,
headers: { "Content-Type": "application/json", ...init?.headers },
});
if (!res.ok) {
const err = await res.json().catch(() => ({}));
throw new Error(parseApiError(err, res.statusText));
}
return res.json() as Promise<T>;
}
export function predict(text: string, threshold: number) {
return request<PredictResponse>("/predict", {
method: "POST",
body: JSON.stringify({ text, threshold }),
});
}
export function predictVideo(url: string, maxComments: number, threshold: number) {
return request<VideoResponse>("/predict-video", {
method: "POST",
body: JSON.stringify({ url, max_comments: maxComments, threshold }),
});
}
export function getModels() {
return request<{ available: string[]; active: string }>("/models");
}
export async function getModelsStatus() {
try {
return await request<{ models: ModelStatusEntry[]; active: string }>("/models/status");
} catch (e) {
if (e instanceof Error && e.message.toLowerCase().includes("not found")) {
const legacy = await getModels();
return {
active: legacy.active,
models: legacy.available.map((name) => ({
name,
available: true,
reason: null,
type: "unknown",
})),
};
}
throw e;
}
}
export function setModel(name: string) {
return request<{ message: string; model: string }>("/models/select", {
method: "POST",
body: JSON.stringify({ model_name: name }),
});
}
export function getSuggestedVideos() {
return request<{ videos: SuggestedVideo[]; max_comments: number }>("/videos/suggested");
}
export function listPredictions(videoId?: string, limit = 20) {
const params = new URLSearchParams();
if (videoId) params.set("video_id", videoId);
params.set("limit", String(limit));
return request<PredictionsListResponse>(`/predictions?${params.toString()}`);
}
export function getModelInfo() {
return request<{
name: string;
description: string;
predictions_served: number;
display_banner?: string | null;
train_test_gap_pp?: number | null;
recommended_threshold?: number | null;
accuracy?: string;
}>("/model-info");
}
|