File size: 3,084 Bytes
abf3c4b 52739ad d9f07b6 44215ae d9f07b6 44215ae | 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 | // Resolve where the API lives, in priority order:
// 1. An HF Space variable `DOCUASK_API_URL` (read at runtime β set it in the
// Static Space settings so the URL can change without a rebuild).
// 2. A build-time `VITE_API_URL` (baked in via frontend/.env.production).
// 3. "/api" β local dev (Vite proxy) and the combined single-origin image.
function resolveApiBase() {
if (typeof window !== "undefined") {
const fromHf = window.huggingface?.variables?.DOCUASK_API_URL;
if (fromHf) return fromHf.replace(/\/$/, "");
}
if (import.meta.env.VITE_API_URL) {
return import.meta.env.VITE_API_URL.replace(/\/$/, "");
}
return "/api";
}
export const API_BASE = resolveApiBase();
/** Extract a human-readable message from a FastAPI error response. */
async function errorDetail(res) {
try {
const data = await res.json();
if (typeof data.detail === "string") return data.detail;
if (Array.isArray(data.detail) && data.detail[0]?.msg) return data.detail[0].msg;
} catch {
// fall through to a generic message
}
return `Upload failed (HTTP ${res.status}).`;
}
/** GET /health β returns the status string ("ok"). */
export async function getHealth() {
const res = await fetch(`${API_BASE}/health`);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const data = await res.json();
return data.status;
}
/** POST /documents with a PDF file. Resolves to the document payload. */
export async function uploadFile(file) {
const form = new FormData();
form.append("file", file);
const res = await fetch(`${API_BASE}/documents`, { method: "POST", body: form });
if (!res.ok) throw new Error(await errorDetail(res));
return res.json();
}
/** POST /documents with raw text. Resolves to the document payload. */
export async function uploadText(text) {
const form = new FormData();
form.append("text", text);
const res = await fetch(`${API_BASE}/documents`, { method: "POST", body: form });
if (!res.ok) throw new Error(await errorDetail(res));
return res.json();
}
/** POST /ask β resolves to { interaction_id, answer, source_passage, ... }. */
export async function askQuestion(documentId, question) {
const res = await fetch(`${API_BASE}/ask`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ document_id: documentId, question }),
});
if (!res.ok) throw new Error(await errorDetail(res));
return res.json();
}
/** POST /feedback β attach a π/π ("up" | "down") to an interaction. */
export async function sendFeedback(interactionId, feedback) {
const res = await fetch(`${API_BASE}/feedback`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ interaction_id: interactionId, feedback }),
});
if (!res.ok) throw new Error(await errorDetail(res));
return res.json();
}
/** GET /stats β dashboard metrics. */
export async function getStats() {
const res = await fetch(`${API_BASE}/stats`);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
return res.json();
}
|