@fastino-ai/pioneer-cli 0.2.10 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +48 -58
- package/dist/index.js +208 -0
- package/dist/yoga.wasm +0 -0
- package/package.json +9 -11
- package/src/api.ts +0 -3187
- package/src/chat/ChatApp.tsx +0 -1028
- package/src/chat/index.ts +0 -7
- package/src/client/ToolExecutor.ts +0 -175
- package/src/client/WebSocketClient.ts +0 -379
- package/src/client/index.ts +0 -2
- package/src/config.ts +0 -225
- package/src/index.tsx +0 -6677
- package/src/telemetry.ts +0 -173
- package/src/tests/api.test.ts +0 -104
- package/src/tests/config-functions.test.ts +0 -163
- package/src/tests/config.test.ts +0 -33
- package/src/tests/file-resolver-edge-cases.test.ts +0 -92
- package/src/tests/telemetry.test.ts +0 -111
- package/src/tests/tool-types.test.ts +0 -104
- package/src/tests/utils.test.ts +0 -90
- package/src/tools/bash.ts +0 -184
- package/src/tools/filesystem.ts +0 -444
- package/src/tools/index.ts +0 -22
- package/src/tools/sandbox.ts +0 -310
- package/src/tools/types.ts +0 -25
- package/src/utils/FileResolver.ts +0 -321
- package/src/utils/index.ts +0 -6
package/src/api.ts
DELETED
|
@@ -1,3187 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Felix API client for Pioneer CLI.
|
|
3
|
-
* Calls the real /felix/* endpoints.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { getApiKey, getBaseUrl } from "./config.js";
|
|
7
|
-
|
|
8
|
-
export interface ApiResult<T = unknown> {
|
|
9
|
-
ok: boolean;
|
|
10
|
-
status: number;
|
|
11
|
-
data?: T;
|
|
12
|
-
error?: string;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Format authentication error with helpful fix instructions.
|
|
17
|
-
*/
|
|
18
|
-
function formatAuthError(originalError?: string): string {
|
|
19
|
-
return [
|
|
20
|
-
"Authentication failed. Please login to Pioneer:",
|
|
21
|
-
"",
|
|
22
|
-
" pioneer auth login",
|
|
23
|
-
"",
|
|
24
|
-
"Don't have an account? Sign up at https://agent.pioneer.ai/",
|
|
25
|
-
originalError ? `\nDetails: ${originalError}` : "",
|
|
26
|
-
]
|
|
27
|
-
.filter(Boolean)
|
|
28
|
-
.join("\n");
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Check if error is authentication-related.
|
|
33
|
-
*/
|
|
34
|
-
function isAuthError(status: number, errorText: string): boolean {
|
|
35
|
-
return (
|
|
36
|
-
status === 401 ||
|
|
37
|
-
status === 403 ||
|
|
38
|
-
errorText.toLowerCase().includes("authentication") ||
|
|
39
|
-
errorText.toLowerCase().includes("api key") ||
|
|
40
|
-
errorText.toLowerCase().includes("unauthorized")
|
|
41
|
-
);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
function extractErrorMessage(payload: unknown): string | undefined {
|
|
45
|
-
if (!payload) return undefined;
|
|
46
|
-
if (typeof payload === "string") return payload;
|
|
47
|
-
|
|
48
|
-
if (Array.isArray(payload)) {
|
|
49
|
-
const parts = payload
|
|
50
|
-
.map((item) => extractErrorMessage(item))
|
|
51
|
-
.filter((item): item is string => Boolean(item && item.trim()));
|
|
52
|
-
return parts.length > 0 ? parts.join("; ") : undefined;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
if (typeof payload === "object") {
|
|
56
|
-
const record = payload as Record<string, unknown>;
|
|
57
|
-
|
|
58
|
-
if (typeof record.detail === "string") return record.detail;
|
|
59
|
-
if (record.detail !== undefined) {
|
|
60
|
-
const detailMessage = extractErrorMessage(record.detail);
|
|
61
|
-
if (detailMessage) return detailMessage;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
if (typeof record.message === "string") return record.message;
|
|
65
|
-
if (typeof record.error === "string") return record.error;
|
|
66
|
-
if (typeof record.msg === "string") return record.msg;
|
|
67
|
-
|
|
68
|
-
if (Array.isArray(record.loc) && typeof record.msg === "string") {
|
|
69
|
-
return `${record.loc.join(".")}: ${record.msg}`;
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
return undefined;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
async function request<T = unknown>(
|
|
77
|
-
method: string,
|
|
78
|
-
path: string,
|
|
79
|
-
body?: unknown
|
|
80
|
-
): Promise<ApiResult<T>> {
|
|
81
|
-
const baseUrl = getBaseUrl().replace(/\/$/, "");
|
|
82
|
-
const apiKey = getApiKey();
|
|
83
|
-
const url = `${baseUrl}${path}`;
|
|
84
|
-
|
|
85
|
-
const headers: Record<string, string> = {
|
|
86
|
-
"Content-Type": "application/json",
|
|
87
|
-
"User-Agent": "pioneer-cli/0.1.0",
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
if (apiKey) {
|
|
91
|
-
headers["X-API-Key"] = apiKey;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
try {
|
|
95
|
-
const res = await fetch(url, {
|
|
96
|
-
method,
|
|
97
|
-
headers,
|
|
98
|
-
body: body ? JSON.stringify(body) : undefined,
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
const text = await res.text();
|
|
102
|
-
let data: T | undefined;
|
|
103
|
-
try {
|
|
104
|
-
data = JSON.parse(text) as T;
|
|
105
|
-
} catch {
|
|
106
|
-
// Not JSON
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
if (!res.ok) {
|
|
110
|
-
const rawError = data ? JSON.stringify(data) : text || `HTTP ${res.status}`;
|
|
111
|
-
const extractedError = extractErrorMessage(data) || text || `HTTP ${res.status}`;
|
|
112
|
-
|
|
113
|
-
// Format authentication errors with helpful instructions
|
|
114
|
-
if (isAuthError(res.status, rawError)) {
|
|
115
|
-
return {
|
|
116
|
-
ok: false,
|
|
117
|
-
status: res.status,
|
|
118
|
-
error: formatAuthError(extractedError),
|
|
119
|
-
};
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
return {
|
|
123
|
-
ok: false,
|
|
124
|
-
status: res.status,
|
|
125
|
-
error: extractedError,
|
|
126
|
-
};
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
return { ok: true, status: res.status, data };
|
|
130
|
-
} catch (err) {
|
|
131
|
-
return {
|
|
132
|
-
ok: false,
|
|
133
|
-
status: 0,
|
|
134
|
-
error: err instanceof Error ? err.message : String(err),
|
|
135
|
-
};
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
140
|
-
// Common Types
|
|
141
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
142
|
-
|
|
143
|
-
export interface DatasetRef {
|
|
144
|
-
name: string;
|
|
145
|
-
version: string;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
149
|
-
// Auth - validate API key by calling /felix/datasets
|
|
150
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
151
|
-
|
|
152
|
-
export async function validateApiKey(apiKey: string): Promise<ApiResult> {
|
|
153
|
-
const baseUrl = getBaseUrl().replace(/\/$/, "");
|
|
154
|
-
const url = `${baseUrl}/felix/datasets`;
|
|
155
|
-
|
|
156
|
-
try {
|
|
157
|
-
const res = await fetch(url, {
|
|
158
|
-
method: "GET",
|
|
159
|
-
headers: {
|
|
160
|
-
"Content-Type": "application/json",
|
|
161
|
-
"User-Agent": "pioneer-cli/0.1.0",
|
|
162
|
-
"X-API-Key": apiKey,
|
|
163
|
-
},
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
if (res.ok) {
|
|
167
|
-
return { ok: true, status: res.status };
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
if (res.status === 401 || res.status === 403) {
|
|
171
|
-
return { ok: false, status: res.status, error: "Invalid API key" };
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
const text = await res.text();
|
|
175
|
-
return { ok: false, status: res.status, error: text || `HTTP ${res.status}` };
|
|
176
|
-
} catch (err) {
|
|
177
|
-
return {
|
|
178
|
-
ok: false,
|
|
179
|
-
status: 0,
|
|
180
|
-
error: err instanceof Error ? err.message : String(err),
|
|
181
|
-
};
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
186
|
-
// Datasets
|
|
187
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
188
|
-
|
|
189
|
-
export interface Dataset {
|
|
190
|
-
id: string;
|
|
191
|
-
user_id: string;
|
|
192
|
-
dataset_name: string;
|
|
193
|
-
dataset_path: string;
|
|
194
|
-
dataset_type: string;
|
|
195
|
-
size?: number;
|
|
196
|
-
sample_size?: number;
|
|
197
|
-
train_ratio?: number;
|
|
198
|
-
version_number?: string;
|
|
199
|
-
root_dataset_id?: string;
|
|
200
|
-
project_id?: string;
|
|
201
|
-
schema?: Record<string, unknown>;
|
|
202
|
-
schema_warnings?: string[];
|
|
203
|
-
validation?: Record<string, unknown>;
|
|
204
|
-
annotation_status?: "none" | "in_progress" | "completed";
|
|
205
|
-
annotation_config?: Record<string, unknown>;
|
|
206
|
-
annotation_progress?: Record<string, unknown>;
|
|
207
|
-
status?: "initialized" | "uploading" | "converting" | "validating" | "ready" | "failed" | "generating" | "queued";
|
|
208
|
-
processing_error?: string;
|
|
209
|
-
type?: "training" | "evaluation" | "benchmark";
|
|
210
|
-
visibility?: "private" | "public";
|
|
211
|
-
is_competition?: boolean;
|
|
212
|
-
labels?: string[];
|
|
213
|
-
generation_type?: string;
|
|
214
|
-
is_seed?: boolean;
|
|
215
|
-
synthesis_session_id?: string;
|
|
216
|
-
column_mapping?: Record<string, string>;
|
|
217
|
-
created_at: string;
|
|
218
|
-
updated_at?: string;
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
export interface DatasetListResponse {
|
|
222
|
-
success: boolean;
|
|
223
|
-
datasets: Dataset[];
|
|
224
|
-
count: number;
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
export async function listDatasets(
|
|
228
|
-
options: { includeAllVersions?: boolean } = {}
|
|
229
|
-
): Promise<ApiResult<DatasetListResponse>> {
|
|
230
|
-
const params = new URLSearchParams();
|
|
231
|
-
if (options.includeAllVersions) {
|
|
232
|
-
params.set("include_all_versions", "true");
|
|
233
|
-
}
|
|
234
|
-
const query = params.toString();
|
|
235
|
-
const url = query ? `/felix/datasets?${query}` : "/felix/datasets";
|
|
236
|
-
return request<DatasetListResponse>("GET", url);
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
export async function getDataset(dataset: DatasetRef): Promise<ApiResult<Dataset>> {
|
|
240
|
-
return request<Dataset>("GET", `/felix/datasets/${dataset.name}/${dataset.version}`);
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
export interface UploadUrlRequest {
|
|
244
|
-
dataset_name: string;
|
|
245
|
-
dataset_type?: "classification" | "ner" | "custom" | "decoder";
|
|
246
|
-
format?: "jsonl" | "csv" | "parquet";
|
|
247
|
-
content_type?: string;
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
export interface UploadUrlResponse {
|
|
251
|
-
upload_url?: string;
|
|
252
|
-
presigned_url?: string;
|
|
253
|
-
dataset_id: string;
|
|
254
|
-
key: string;
|
|
255
|
-
expires_in: number;
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
export async function getUploadUrl(
|
|
259
|
-
req: UploadUrlRequest
|
|
260
|
-
): Promise<ApiResult<UploadUrlResponse>> {
|
|
261
|
-
return request<UploadUrlResponse>("POST", "/felix/datasets/upload/url", req);
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
export interface ProcessUploadRequest {
|
|
265
|
-
dataset_id: string;
|
|
266
|
-
dataset_name: string;
|
|
267
|
-
dataset_type?: "classification" | "ner" | "custom" | "decoder";
|
|
268
|
-
format?: "jsonl" | "csv" | "parquet";
|
|
269
|
-
schema?: Record<string, string>;
|
|
270
|
-
project_id?: string;
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
export async function processUpload(
|
|
274
|
-
req: ProcessUploadRequest
|
|
275
|
-
): Promise<ApiResult<Dataset>> {
|
|
276
|
-
return request<Dataset>("POST", "/felix/datasets/upload/process", req);
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
export async function deleteDataset(dataset: DatasetRef): Promise<ApiResult> {
|
|
280
|
-
return request("DELETE", `/felix/datasets/${dataset.name}/${dataset.version}`);
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
export async function deleteAllDatasetVersions(name: string): Promise<ApiResult> {
|
|
284
|
-
return request("DELETE", `/felix/datasets/${name}`);
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
export interface DatasetVersionsResponse {
|
|
288
|
-
success: boolean;
|
|
289
|
-
versions: Dataset[];
|
|
290
|
-
count: number;
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
export async function listDatasetVersions(
|
|
294
|
-
name: string
|
|
295
|
-
): Promise<ApiResult<DatasetVersionsResponse>> {
|
|
296
|
-
return request<DatasetVersionsResponse>("GET", `/felix/datasets/${name}`);
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
export interface DatasetMetadataUpdate {
|
|
300
|
-
dataset_name?: string;
|
|
301
|
-
dataset_type?: "ner" | "classification" | "custom" | "decoder";
|
|
302
|
-
project_id?: string;
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
export async function updateDatasetMetadata(
|
|
306
|
-
dataset: DatasetRef,
|
|
307
|
-
update: DatasetMetadataUpdate
|
|
308
|
-
): Promise<ApiResult<Dataset>> {
|
|
309
|
-
return request<Dataset>(
|
|
310
|
-
"PUT",
|
|
311
|
-
`/felix/datasets/${dataset.name}/${dataset.version}`,
|
|
312
|
-
update
|
|
313
|
-
);
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
export async function previewDataset(
|
|
317
|
-
dataset: DatasetRef,
|
|
318
|
-
options: { limit?: number; offset?: number } = {}
|
|
319
|
-
): Promise<ApiResult<Record<string, unknown>>> {
|
|
320
|
-
const params = new URLSearchParams();
|
|
321
|
-
if (options.limit) params.set("limit", String(options.limit));
|
|
322
|
-
if (options.offset) params.set("offset", String(options.offset));
|
|
323
|
-
const query = params.toString();
|
|
324
|
-
const url = `/felix/datasets/${dataset.name}/${dataset.version}/preview${query ? `?${query}` : ""}`;
|
|
325
|
-
return request<Record<string, unknown>>("GET", url);
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
export interface DatasetUploadRequest {
|
|
329
|
-
dataset_name: string;
|
|
330
|
-
dataset_type?: "ner" | "classification" | "custom" | "decoder";
|
|
331
|
-
format?: "jsonl" | "csv" | "parquet";
|
|
332
|
-
schema?: Record<string, string>;
|
|
333
|
-
project_id?: string;
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
export async function uploadDataset(
|
|
337
|
-
filePath: string,
|
|
338
|
-
options: DatasetUploadRequest
|
|
339
|
-
): Promise<ApiResult<Dataset>> {
|
|
340
|
-
try {
|
|
341
|
-
const fs = await import("fs");
|
|
342
|
-
const path = await import("path");
|
|
343
|
-
const fileContent = fs.readFileSync(filePath);
|
|
344
|
-
const filename = path.basename(filePath);
|
|
345
|
-
|
|
346
|
-
// Detect format from file extension if not provided
|
|
347
|
-
const ext = path.extname(filename).slice(1) as "jsonl" | "csv" | "parquet";
|
|
348
|
-
const format = options.format || ext || "jsonl";
|
|
349
|
-
|
|
350
|
-
// Step 1: Get presigned upload URL
|
|
351
|
-
const urlResult = await getUploadUrl({
|
|
352
|
-
dataset_name: options.dataset_name,
|
|
353
|
-
dataset_type: options.dataset_type,
|
|
354
|
-
format,
|
|
355
|
-
content_type: "application/octet-stream",
|
|
356
|
-
});
|
|
357
|
-
|
|
358
|
-
if (!urlResult.ok || !urlResult.data) {
|
|
359
|
-
return {
|
|
360
|
-
ok: false,
|
|
361
|
-
status: urlResult.status,
|
|
362
|
-
error: urlResult.error || "Failed to get upload URL",
|
|
363
|
-
};
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
const { dataset_id } = urlResult.data;
|
|
367
|
-
const uploadUrl = urlResult.data.upload_url || urlResult.data.presigned_url;
|
|
368
|
-
if (!uploadUrl) {
|
|
369
|
-
return {
|
|
370
|
-
ok: false,
|
|
371
|
-
status: 500,
|
|
372
|
-
error: "Upload URL not provided by backend",
|
|
373
|
-
};
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
// Step 2: Upload file directly to S3 via presigned URL
|
|
377
|
-
const uploadRes = await fetch(uploadUrl, {
|
|
378
|
-
method: "PUT",
|
|
379
|
-
headers: {
|
|
380
|
-
"Content-Type": "application/octet-stream",
|
|
381
|
-
},
|
|
382
|
-
body: fileContent,
|
|
383
|
-
});
|
|
384
|
-
|
|
385
|
-
if (!uploadRes.ok) {
|
|
386
|
-
return {
|
|
387
|
-
ok: false,
|
|
388
|
-
status: uploadRes.status,
|
|
389
|
-
error: `Failed to upload file to S3: HTTP ${uploadRes.status}`,
|
|
390
|
-
};
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
// Step 3: Trigger processing
|
|
394
|
-
const processResult = await processUpload({
|
|
395
|
-
dataset_id,
|
|
396
|
-
dataset_name: options.dataset_name,
|
|
397
|
-
dataset_type: options.dataset_type,
|
|
398
|
-
format,
|
|
399
|
-
schema: options.schema,
|
|
400
|
-
project_id: options.project_id,
|
|
401
|
-
});
|
|
402
|
-
|
|
403
|
-
return processResult;
|
|
404
|
-
} catch (err) {
|
|
405
|
-
return {
|
|
406
|
-
ok: false,
|
|
407
|
-
status: 0,
|
|
408
|
-
error: err instanceof Error ? err.message : String(err),
|
|
409
|
-
};
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
export interface DatasetDownloadResponse {
|
|
414
|
-
download_url: string;
|
|
415
|
-
file_path?: string;
|
|
416
|
-
size?: number;
|
|
417
|
-
dataset_name?: string;
|
|
418
|
-
version?: string;
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
export async function downloadDataset(
|
|
422
|
-
dataset: DatasetRef,
|
|
423
|
-
format: "csv" | "jsonl" | "parquet" = "jsonl",
|
|
424
|
-
outputPath?: string
|
|
425
|
-
): Promise<ApiResult<DatasetDownloadResponse>> {
|
|
426
|
-
const baseUrl = getBaseUrl().replace(/\/$/, "");
|
|
427
|
-
const apiKey = getApiKey();
|
|
428
|
-
const downloadUrl = `${baseUrl}/felix/datasets/${dataset.name}/${dataset.version}/download?format=${format}`;
|
|
429
|
-
|
|
430
|
-
// Generate default filename if not specified
|
|
431
|
-
const safeDatasetName = dataset.name.replace(/[^a-zA-Z0-9-_]/g, "_");
|
|
432
|
-
if (!outputPath) {
|
|
433
|
-
outputPath = `${safeDatasetName}_${dataset.version}.${format}`;
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
// Download the file
|
|
437
|
-
const headers: Record<string, string> = {
|
|
438
|
-
"User-Agent": "pioneer-cli/0.1.0",
|
|
439
|
-
};
|
|
440
|
-
|
|
441
|
-
if (apiKey) {
|
|
442
|
-
headers["X-API-Key"] = apiKey;
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
try {
|
|
446
|
-
const res = await fetch(downloadUrl, {
|
|
447
|
-
method: "GET",
|
|
448
|
-
headers,
|
|
449
|
-
});
|
|
450
|
-
|
|
451
|
-
if (!res.ok) {
|
|
452
|
-
const text = await res.text();
|
|
453
|
-
return {
|
|
454
|
-
ok: false,
|
|
455
|
-
status: res.status,
|
|
456
|
-
error: text || `HTTP ${res.status}`,
|
|
457
|
-
};
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
// Write the file
|
|
461
|
-
const fs = await import("fs");
|
|
462
|
-
const path = await import("path");
|
|
463
|
-
const buffer = await res.arrayBuffer();
|
|
464
|
-
fs.writeFileSync(outputPath, Buffer.from(buffer));
|
|
465
|
-
|
|
466
|
-
// Resolve to absolute path for user feedback
|
|
467
|
-
const absolutePath = path.resolve(outputPath);
|
|
468
|
-
|
|
469
|
-
return {
|
|
470
|
-
ok: true,
|
|
471
|
-
status: 200,
|
|
472
|
-
data: {
|
|
473
|
-
download_url: downloadUrl,
|
|
474
|
-
file_path: absolutePath,
|
|
475
|
-
size: buffer.byteLength,
|
|
476
|
-
dataset_name: dataset.name,
|
|
477
|
-
version: dataset.version,
|
|
478
|
-
},
|
|
479
|
-
};
|
|
480
|
-
} catch (err) {
|
|
481
|
-
return {
|
|
482
|
-
ok: false,
|
|
483
|
-
status: 0,
|
|
484
|
-
error: err instanceof Error ? err.message : String(err),
|
|
485
|
-
};
|
|
486
|
-
}
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
export interface DatasetAnalysisRequest {
|
|
490
|
-
dataset: DatasetRef;
|
|
491
|
-
task_type: string;
|
|
492
|
-
analyses: string[];
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
// Diversity Analysis Types
|
|
496
|
-
export interface DiversityPoint {
|
|
497
|
-
x?: number;
|
|
498
|
-
y?: number;
|
|
499
|
-
z?: number;
|
|
500
|
-
w?: number;
|
|
501
|
-
coordinates: number[];
|
|
502
|
-
text?: string;
|
|
503
|
-
token_count?: number;
|
|
504
|
-
labels?: string[];
|
|
505
|
-
metadata?: Record<string, unknown>;
|
|
506
|
-
sample_index?: number;
|
|
507
|
-
similarity_to_centroid?: number;
|
|
508
|
-
embedding?: number[];
|
|
509
|
-
}
|
|
510
|
-
|
|
511
|
-
export interface DiversityVisualization {
|
|
512
|
-
method: "pca" | "tsne";
|
|
513
|
-
dimensions: number;
|
|
514
|
-
points: DiversityPoint[];
|
|
515
|
-
tsne_perplexity?: number;
|
|
516
|
-
similarity_range?: { min: number; max: number };
|
|
517
|
-
token_count_range?: { min: number; max: number };
|
|
518
|
-
}
|
|
519
|
-
|
|
520
|
-
export interface DiversityLLMAnalysis {
|
|
521
|
-
reasoning_trace: string;
|
|
522
|
-
summary: string;
|
|
523
|
-
diversity_rating: "low" | "moderate" | "high" | "excellent";
|
|
524
|
-
key_observations: string[];
|
|
525
|
-
recommendations: string[];
|
|
526
|
-
model_used: string;
|
|
527
|
-
}
|
|
528
|
-
|
|
529
|
-
export interface DiversityAnalysis {
|
|
530
|
-
vendi_score: number;
|
|
531
|
-
sample_size: number;
|
|
532
|
-
interpretation?: string;
|
|
533
|
-
visualization?: DiversityVisualization;
|
|
534
|
-
llm_analysis?: DiversityLLMAnalysis;
|
|
535
|
-
}
|
|
536
|
-
|
|
537
|
-
// Distribution Analysis Types
|
|
538
|
-
export interface DistributionAnalysis {
|
|
539
|
-
label_counts: Record<string, number>;
|
|
540
|
-
total_samples: number;
|
|
541
|
-
unique_labels: number;
|
|
542
|
-
most_common_label?: string;
|
|
543
|
-
least_common_label?: string;
|
|
544
|
-
imbalance_ratio?: number;
|
|
545
|
-
}
|
|
546
|
-
|
|
547
|
-
// Duplicates Analysis Types
|
|
548
|
-
export interface DuplicatesAnalysis {
|
|
549
|
-
total_duplicates: number;
|
|
550
|
-
duplicate_groups: number;
|
|
551
|
-
duplicate_percentage: number;
|
|
552
|
-
examples?: Array<{ text: string; count: number }>;
|
|
553
|
-
}
|
|
554
|
-
|
|
555
|
-
// Outliers Analysis Types
|
|
556
|
-
export interface OutliersAnalysis {
|
|
557
|
-
total_outliers: number;
|
|
558
|
-
outlier_percentage: number;
|
|
559
|
-
method: string;
|
|
560
|
-
threshold?: number;
|
|
561
|
-
examples?: Array<{ text: string; score: number; reason?: string }>;
|
|
562
|
-
}
|
|
563
|
-
|
|
564
|
-
// Splits Analysis Types
|
|
565
|
-
export interface SplitsAnalysis {
|
|
566
|
-
train_size: number;
|
|
567
|
-
validation_size: number;
|
|
568
|
-
test_size?: number;
|
|
569
|
-
train_percentage: number;
|
|
570
|
-
validation_percentage: number;
|
|
571
|
-
test_percentage?: number;
|
|
572
|
-
}
|
|
573
|
-
|
|
574
|
-
export interface DatasetAnalysisResponse {
|
|
575
|
-
summary: Record<string, unknown>;
|
|
576
|
-
distribution?: DistributionAnalysis;
|
|
577
|
-
duplicates?: DuplicatesAnalysis;
|
|
578
|
-
outliers?: OutliersAnalysis;
|
|
579
|
-
correlations?: Record<string, unknown>;
|
|
580
|
-
splits?: SplitsAnalysis;
|
|
581
|
-
errors?: Record<string, unknown>;
|
|
582
|
-
diversity?: DiversityAnalysis;
|
|
583
|
-
natural_language_response?: string;
|
|
584
|
-
}
|
|
585
|
-
|
|
586
|
-
export async function analyzeDataset(
|
|
587
|
-
dataset: DatasetRef,
|
|
588
|
-
taskType: string,
|
|
589
|
-
analyses: string[]
|
|
590
|
-
): Promise<ApiResult<DatasetAnalysisResponse>> {
|
|
591
|
-
return request<DatasetAnalysisResponse>("POST", "/felix/dataset/analyze", {
|
|
592
|
-
dataset_name: dataset.name,
|
|
593
|
-
dataset_version: dataset.version,
|
|
594
|
-
task_type: taskType,
|
|
595
|
-
analyses: analyses,
|
|
596
|
-
});
|
|
597
|
-
}
|
|
598
|
-
|
|
599
|
-
export interface DatasetLLMAnalysisRequest {
|
|
600
|
-
task_type: "ner" | "classification" | "generative";
|
|
601
|
-
task_description?: string;
|
|
602
|
-
labels?: string[];
|
|
603
|
-
dataset?: Record<string, unknown>[];
|
|
604
|
-
dataset_name?: string;
|
|
605
|
-
dataset_version?: string;
|
|
606
|
-
}
|
|
607
|
-
|
|
608
|
-
export async function analyzeDatasetLLM(
|
|
609
|
-
req: DatasetLLMAnalysisRequest
|
|
610
|
-
): Promise<ApiResult<DiversityLLMAnalysis>> {
|
|
611
|
-
return request<DiversityLLMAnalysis>("POST", "/felix/dataset/analyze_llm", req);
|
|
612
|
-
}
|
|
613
|
-
|
|
614
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
615
|
-
// Dataset Generation
|
|
616
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
617
|
-
|
|
618
|
-
export interface RecordField {
|
|
619
|
-
name: string;
|
|
620
|
-
type?: string;
|
|
621
|
-
description?: string;
|
|
622
|
-
allowed_values?: string[];
|
|
623
|
-
}
|
|
624
|
-
|
|
625
|
-
export interface ConstraintRequest {
|
|
626
|
-
description: string;
|
|
627
|
-
choices?: string[];
|
|
628
|
-
probability?: number;
|
|
629
|
-
}
|
|
630
|
-
|
|
631
|
-
export interface GenerateResponse {
|
|
632
|
-
success: boolean;
|
|
633
|
-
data: Record<string, unknown>[];
|
|
634
|
-
count: number;
|
|
635
|
-
task_type: string;
|
|
636
|
-
token_usage?: number;
|
|
637
|
-
dataset?: Record<string, unknown>;
|
|
638
|
-
}
|
|
639
|
-
|
|
640
|
-
export type GenerateTaskType =
|
|
641
|
-
| "ner"
|
|
642
|
-
| "classification"
|
|
643
|
-
| "custom"
|
|
644
|
-
| "decoder"
|
|
645
|
-
| "records"
|
|
646
|
-
| "fields";
|
|
647
|
-
|
|
648
|
-
export interface GenerateAsyncResponse {
|
|
649
|
-
job_id: string;
|
|
650
|
-
status?: string;
|
|
651
|
-
dataset_name: string;
|
|
652
|
-
task_type: GenerateTaskType;
|
|
653
|
-
is_seed?: boolean;
|
|
654
|
-
message?: string;
|
|
655
|
-
}
|
|
656
|
-
|
|
657
|
-
export interface GenerateJobStatus {
|
|
658
|
-
job_id: string;
|
|
659
|
-
status: "queued" | "generating" | "ready" | "failed" | string;
|
|
660
|
-
data?: Record<string, unknown>[];
|
|
661
|
-
count?: number;
|
|
662
|
-
task_type?: string;
|
|
663
|
-
token_usage?: number;
|
|
664
|
-
dataset?: Record<string, unknown>;
|
|
665
|
-
error?: string;
|
|
666
|
-
is_seed?: boolean;
|
|
667
|
-
created_at?: string;
|
|
668
|
-
}
|
|
669
|
-
|
|
670
|
-
export interface GenerateRequest {
|
|
671
|
-
task_type: GenerateTaskType;
|
|
672
|
-
dataset_name: string;
|
|
673
|
-
num_examples?: number;
|
|
674
|
-
domain_description?: string;
|
|
675
|
-
temperature?: number;
|
|
676
|
-
quality?: "light" | "medium" | "heavy";
|
|
677
|
-
generation_profile?: "auto" | "fast" | "balanced" | "quality";
|
|
678
|
-
session_id?: string;
|
|
679
|
-
config_num_examples?: number;
|
|
680
|
-
seed?: number;
|
|
681
|
-
labels?: string[];
|
|
682
|
-
classified_examples?: Record<string, unknown>[];
|
|
683
|
-
multi_label?: boolean;
|
|
684
|
-
class_balance?: Record<string, number>;
|
|
685
|
-
batch_size?: number;
|
|
686
|
-
negative_ratio?: number;
|
|
687
|
-
fields?: RecordField[];
|
|
688
|
-
input_fields?: RecordField[];
|
|
689
|
-
output_fields?: RecordField[];
|
|
690
|
-
prompt?: string;
|
|
691
|
-
output_format?: Record<string, unknown>;
|
|
692
|
-
infer_output_format?: boolean;
|
|
693
|
-
instruction?: string;
|
|
694
|
-
constraints?: ConstraintRequest[];
|
|
695
|
-
multiplicator?: Record<string, unknown>;
|
|
696
|
-
include_reasoning_trace?: boolean;
|
|
697
|
-
reasoning_effort?: "low" | "medium" | "high";
|
|
698
|
-
use_meta_felix?: boolean;
|
|
699
|
-
min_criteria?: number;
|
|
700
|
-
target_choices?: number;
|
|
701
|
-
project_id?: string;
|
|
702
|
-
type?: "training" | "evaluation" | "split";
|
|
703
|
-
visibility?: "private" | "public";
|
|
704
|
-
split_ratio?: Record<string, number>;
|
|
705
|
-
}
|
|
706
|
-
|
|
707
|
-
const GENERATION_POLL_INTERVAL_MS = 2000;
|
|
708
|
-
const GENERATION_MAX_ATTEMPTS = 300; // 10 minutes
|
|
709
|
-
|
|
710
|
-
function sleep(ms: number): Promise<void> {
|
|
711
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
712
|
-
}
|
|
713
|
-
|
|
714
|
-
function makeDefaultDatasetName(taskType: GenerateTaskType): string {
|
|
715
|
-
return `${taskType}-dataset-${Date.now()}`;
|
|
716
|
-
}
|
|
717
|
-
|
|
718
|
-
export async function startGeneration(
|
|
719
|
-
req: GenerateRequest,
|
|
720
|
-
options: { isSeed?: boolean; synthesisSessionId?: string } = {}
|
|
721
|
-
): Promise<ApiResult<GenerateAsyncResponse>> {
|
|
722
|
-
const params = new URLSearchParams();
|
|
723
|
-
if (options.isSeed) params.set("is_seed", "true");
|
|
724
|
-
if (options.synthesisSessionId) {
|
|
725
|
-
params.set("synthesis_session_id", options.synthesisSessionId);
|
|
726
|
-
}
|
|
727
|
-
const query = params.toString();
|
|
728
|
-
const url = query ? `/generate?${query}` : "/generate";
|
|
729
|
-
return request<GenerateAsyncResponse>("POST", url, req);
|
|
730
|
-
}
|
|
731
|
-
|
|
732
|
-
export async function getGenerationJobStatus(
|
|
733
|
-
jobId: string
|
|
734
|
-
): Promise<ApiResult<GenerateJobStatus>> {
|
|
735
|
-
return request<GenerateJobStatus>("GET", `/generate/jobs/${jobId}`);
|
|
736
|
-
}
|
|
737
|
-
|
|
738
|
-
export async function waitForGenerationJob(
|
|
739
|
-
jobId: string,
|
|
740
|
-
options: { pollIntervalMs?: number; maxAttempts?: number } = {}
|
|
741
|
-
): Promise<ApiResult<GenerateJobStatus>> {
|
|
742
|
-
const pollIntervalMs = options.pollIntervalMs ?? GENERATION_POLL_INTERVAL_MS;
|
|
743
|
-
const maxAttempts = options.maxAttempts ?? GENERATION_MAX_ATTEMPTS;
|
|
744
|
-
|
|
745
|
-
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
746
|
-
const statusResult = await getGenerationJobStatus(jobId);
|
|
747
|
-
if (!statusResult.ok || !statusResult.data) {
|
|
748
|
-
if (statusResult.status === 404 && attempt < 5) {
|
|
749
|
-
await sleep(pollIntervalMs);
|
|
750
|
-
continue;
|
|
751
|
-
}
|
|
752
|
-
return {
|
|
753
|
-
ok: false,
|
|
754
|
-
status: statusResult.status,
|
|
755
|
-
error: statusResult.error ?? "Failed to fetch generation status",
|
|
756
|
-
};
|
|
757
|
-
}
|
|
758
|
-
|
|
759
|
-
if (statusResult.data.status === "ready") {
|
|
760
|
-
return statusResult;
|
|
761
|
-
}
|
|
762
|
-
|
|
763
|
-
if (statusResult.data.status === "failed") {
|
|
764
|
-
return {
|
|
765
|
-
ok: false,
|
|
766
|
-
status: statusResult.status || 500,
|
|
767
|
-
error: statusResult.data.error ?? "Generation failed",
|
|
768
|
-
};
|
|
769
|
-
}
|
|
770
|
-
|
|
771
|
-
await sleep(pollIntervalMs);
|
|
772
|
-
}
|
|
773
|
-
|
|
774
|
-
return {
|
|
775
|
-
ok: false,
|
|
776
|
-
status: 408,
|
|
777
|
-
error: `Generation timed out for job ${jobId}. Use 'pioneer dataset get <name[:version]>' once ready.`,
|
|
778
|
-
};
|
|
779
|
-
}
|
|
780
|
-
|
|
781
|
-
async function generateDataset(req: GenerateRequest): Promise<ApiResult<GenerateJobStatus>> {
|
|
782
|
-
const startResult = await startGeneration(req);
|
|
783
|
-
if (!startResult.ok || !startResult.data) {
|
|
784
|
-
return {
|
|
785
|
-
ok: false,
|
|
786
|
-
status: startResult.status,
|
|
787
|
-
error: startResult.error ?? "Failed to start generation job",
|
|
788
|
-
};
|
|
789
|
-
}
|
|
790
|
-
|
|
791
|
-
return waitForGenerationJob(startResult.data.job_id);
|
|
792
|
-
}
|
|
793
|
-
|
|
794
|
-
export interface InferLabelsResponse {
|
|
795
|
-
success: boolean;
|
|
796
|
-
labels: string[];
|
|
797
|
-
count: number;
|
|
798
|
-
}
|
|
799
|
-
|
|
800
|
-
export interface InferFieldsResponse {
|
|
801
|
-
success: boolean;
|
|
802
|
-
input_fields: RecordField[];
|
|
803
|
-
output_fields: RecordField[];
|
|
804
|
-
mode: string;
|
|
805
|
-
reasoning: string;
|
|
806
|
-
}
|
|
807
|
-
|
|
808
|
-
// NER Generation
|
|
809
|
-
export interface GenerateNERRequest {
|
|
810
|
-
labels: string[];
|
|
811
|
-
num_examples?: number;
|
|
812
|
-
domain_description?: string;
|
|
813
|
-
seed?: number;
|
|
814
|
-
session_id?: string;
|
|
815
|
-
config_num_examples?: number;
|
|
816
|
-
temperature?: number;
|
|
817
|
-
constraints?: ConstraintRequest[];
|
|
818
|
-
save_dataset?: boolean;
|
|
819
|
-
dataset_name?: string;
|
|
820
|
-
project_id?: string;
|
|
821
|
-
generation_profile?: "auto" | "fast" | "balanced" | "quality";
|
|
822
|
-
include_reasoning_trace?: boolean;
|
|
823
|
-
reasoning_effort?: "low" | "medium" | "high";
|
|
824
|
-
quality?: "light" | "medium" | "heavy";
|
|
825
|
-
type?: "training" | "evaluation" | "split";
|
|
826
|
-
visibility?: "private" | "public";
|
|
827
|
-
negative_ratio?: number;
|
|
828
|
-
split_ratio?: Record<string, number>;
|
|
829
|
-
multiplicator?: Record<string, unknown>;
|
|
830
|
-
use_meta_felix?: boolean;
|
|
831
|
-
min_criteria?: number;
|
|
832
|
-
target_choices?: number;
|
|
833
|
-
classified_examples?: Record<string, unknown>[];
|
|
834
|
-
}
|
|
835
|
-
|
|
836
|
-
export async function generateNER(
|
|
837
|
-
req: GenerateNERRequest
|
|
838
|
-
): Promise<ApiResult<GenerateJobStatus>> {
|
|
839
|
-
return generateDataset({
|
|
840
|
-
task_type: "ner",
|
|
841
|
-
dataset_name: req.dataset_name ?? makeDefaultDatasetName("ner"),
|
|
842
|
-
labels: req.labels,
|
|
843
|
-
num_examples: req.num_examples,
|
|
844
|
-
domain_description: req.domain_description,
|
|
845
|
-
seed: req.seed,
|
|
846
|
-
session_id: req.session_id,
|
|
847
|
-
config_num_examples: req.config_num_examples,
|
|
848
|
-
temperature: req.temperature,
|
|
849
|
-
constraints: req.constraints,
|
|
850
|
-
project_id: req.project_id,
|
|
851
|
-
generation_profile: req.generation_profile,
|
|
852
|
-
include_reasoning_trace: req.include_reasoning_trace,
|
|
853
|
-
reasoning_effort: req.reasoning_effort,
|
|
854
|
-
quality: req.quality,
|
|
855
|
-
min_criteria: req.min_criteria,
|
|
856
|
-
target_choices: req.target_choices,
|
|
857
|
-
type: req.type,
|
|
858
|
-
visibility: req.visibility,
|
|
859
|
-
negative_ratio: req.negative_ratio,
|
|
860
|
-
split_ratio: req.split_ratio,
|
|
861
|
-
multiplicator: req.multiplicator,
|
|
862
|
-
use_meta_felix: req.use_meta_felix,
|
|
863
|
-
classified_examples: req.classified_examples,
|
|
864
|
-
});
|
|
865
|
-
}
|
|
866
|
-
|
|
867
|
-
export interface LabelExistingNERRequest {
|
|
868
|
-
labels: string[];
|
|
869
|
-
inputs: string[];
|
|
870
|
-
domain_description?: string;
|
|
871
|
-
seed?: number;
|
|
872
|
-
temperature?: number;
|
|
873
|
-
constraints?: ConstraintRequest[];
|
|
874
|
-
save_dataset?: boolean;
|
|
875
|
-
dataset_name?: string;
|
|
876
|
-
project_id?: string;
|
|
877
|
-
}
|
|
878
|
-
|
|
879
|
-
export async function labelExistingNER(
|
|
880
|
-
req: LabelExistingNERRequest
|
|
881
|
-
): Promise<ApiResult<GenerateResponse>> {
|
|
882
|
-
return request<GenerateResponse>("POST", "/generate/ner/label-existing", req);
|
|
883
|
-
}
|
|
884
|
-
|
|
885
|
-
export interface InferNERLabelsRequest {
|
|
886
|
-
domain_description: string;
|
|
887
|
-
}
|
|
888
|
-
|
|
889
|
-
export async function inferNERLabels(
|
|
890
|
-
req: InferNERLabelsRequest
|
|
891
|
-
): Promise<ApiResult<InferLabelsResponse>> {
|
|
892
|
-
return request<InferLabelsResponse>("POST", "/generate/ner/infer-labels", req);
|
|
893
|
-
}
|
|
894
|
-
|
|
895
|
-
// Classification Generation
|
|
896
|
-
export interface GenerateClassificationRequest {
|
|
897
|
-
labels: string[];
|
|
898
|
-
num_examples?: number;
|
|
899
|
-
domain_description?: string;
|
|
900
|
-
seed?: number;
|
|
901
|
-
class_balance?: Record<string, number>;
|
|
902
|
-
session_id?: string;
|
|
903
|
-
config_num_examples?: number;
|
|
904
|
-
temperature?: number;
|
|
905
|
-
batch_size?: number;
|
|
906
|
-
constraints?: ConstraintRequest[];
|
|
907
|
-
multi_label?: boolean;
|
|
908
|
-
save_dataset?: boolean;
|
|
909
|
-
dataset_name?: string;
|
|
910
|
-
project_id?: string;
|
|
911
|
-
generation_profile?: "auto" | "fast" | "balanced" | "quality";
|
|
912
|
-
include_reasoning_trace?: boolean;
|
|
913
|
-
reasoning_effort?: "low" | "medium" | "high";
|
|
914
|
-
quality?: "light" | "medium" | "heavy";
|
|
915
|
-
min_criteria?: number;
|
|
916
|
-
target_choices?: number;
|
|
917
|
-
split_ratio?: Record<string, number>;
|
|
918
|
-
negative_ratio?: number;
|
|
919
|
-
multiplicator?: Record<string, unknown>;
|
|
920
|
-
use_meta_felix?: boolean;
|
|
921
|
-
type?: "training" | "evaluation" | "split";
|
|
922
|
-
visibility?: "private" | "public";
|
|
923
|
-
}
|
|
924
|
-
|
|
925
|
-
export async function generateClassification(
|
|
926
|
-
req: GenerateClassificationRequest
|
|
927
|
-
): Promise<ApiResult<GenerateJobStatus>> {
|
|
928
|
-
return generateDataset({
|
|
929
|
-
task_type: "classification",
|
|
930
|
-
dataset_name: req.dataset_name ?? makeDefaultDatasetName("classification"),
|
|
931
|
-
labels: req.labels,
|
|
932
|
-
num_examples: req.num_examples,
|
|
933
|
-
domain_description: req.domain_description,
|
|
934
|
-
seed: req.seed,
|
|
935
|
-
class_balance: req.class_balance,
|
|
936
|
-
session_id: req.session_id,
|
|
937
|
-
config_num_examples: req.config_num_examples,
|
|
938
|
-
temperature: req.temperature,
|
|
939
|
-
batch_size: req.batch_size,
|
|
940
|
-
constraints: req.constraints,
|
|
941
|
-
multi_label: req.multi_label,
|
|
942
|
-
project_id: req.project_id,
|
|
943
|
-
generation_profile: req.generation_profile,
|
|
944
|
-
include_reasoning_trace: req.include_reasoning_trace,
|
|
945
|
-
reasoning_effort: req.reasoning_effort,
|
|
946
|
-
quality: req.quality,
|
|
947
|
-
min_criteria: req.min_criteria,
|
|
948
|
-
target_choices: req.target_choices,
|
|
949
|
-
split_ratio: req.split_ratio,
|
|
950
|
-
multiplicator: req.multiplicator,
|
|
951
|
-
use_meta_felix: req.use_meta_felix,
|
|
952
|
-
type: req.type,
|
|
953
|
-
visibility: req.visibility,
|
|
954
|
-
negative_ratio: req.negative_ratio,
|
|
955
|
-
});
|
|
956
|
-
}
|
|
957
|
-
|
|
958
|
-
export interface LabelExistingClassificationRequest {
|
|
959
|
-
labels: string[];
|
|
960
|
-
inputs: string[];
|
|
961
|
-
domain_description?: string;
|
|
962
|
-
seed?: number;
|
|
963
|
-
class_balance?: Record<string, number>;
|
|
964
|
-
temperature?: number;
|
|
965
|
-
batch_size?: number;
|
|
966
|
-
constraints?: ConstraintRequest[];
|
|
967
|
-
multi_label?: boolean;
|
|
968
|
-
save_dataset?: boolean;
|
|
969
|
-
dataset_name?: string;
|
|
970
|
-
project_id?: string;
|
|
971
|
-
}
|
|
972
|
-
|
|
973
|
-
export async function labelExistingClassification(
|
|
974
|
-
req: LabelExistingClassificationRequest
|
|
975
|
-
): Promise<ApiResult<GenerateResponse>> {
|
|
976
|
-
return request<GenerateResponse>("POST", "/generate/classification/label-existing", req);
|
|
977
|
-
}
|
|
978
|
-
|
|
979
|
-
export interface InferClassificationLabelsRequest {
|
|
980
|
-
domain_description: string;
|
|
981
|
-
}
|
|
982
|
-
|
|
983
|
-
export async function inferClassificationLabels(
|
|
984
|
-
req: InferClassificationLabelsRequest
|
|
985
|
-
): Promise<ApiResult<InferLabelsResponse>> {
|
|
986
|
-
return request<InferLabelsResponse>("POST", "/generate/classification/infer-labels", req);
|
|
987
|
-
}
|
|
988
|
-
|
|
989
|
-
// Custom Generation
|
|
990
|
-
export interface GenerateCustomRequest {
|
|
991
|
-
prompt: string;
|
|
992
|
-
output_format?: Record<string, unknown>;
|
|
993
|
-
infer_output_format?: boolean;
|
|
994
|
-
num_examples?: number;
|
|
995
|
-
seed?: number;
|
|
996
|
-
session_id?: string;
|
|
997
|
-
temperature?: number;
|
|
998
|
-
constraints?: ConstraintRequest[];
|
|
999
|
-
save_dataset?: boolean;
|
|
1000
|
-
dataset_name?: string;
|
|
1001
|
-
project_id?: string;
|
|
1002
|
-
generation_profile?: "auto" | "fast" | "balanced" | "quality";
|
|
1003
|
-
include_reasoning_trace?: boolean;
|
|
1004
|
-
reasoning_effort?: "low" | "medium" | "high";
|
|
1005
|
-
quality?: "light" | "medium" | "heavy";
|
|
1006
|
-
min_criteria?: number;
|
|
1007
|
-
target_choices?: number;
|
|
1008
|
-
split_ratio?: Record<string, number>;
|
|
1009
|
-
negative_ratio?: number;
|
|
1010
|
-
multiplicator?: Record<string, unknown>;
|
|
1011
|
-
use_meta_felix?: boolean;
|
|
1012
|
-
type?: "training" | "evaluation" | "split";
|
|
1013
|
-
visibility?: "private" | "public";
|
|
1014
|
-
}
|
|
1015
|
-
|
|
1016
|
-
export async function generateCustom(
|
|
1017
|
-
req: GenerateCustomRequest
|
|
1018
|
-
): Promise<ApiResult<GenerateJobStatus>> {
|
|
1019
|
-
return generateDataset({
|
|
1020
|
-
task_type: "custom",
|
|
1021
|
-
dataset_name: req.dataset_name ?? makeDefaultDatasetName("custom"),
|
|
1022
|
-
prompt: req.prompt,
|
|
1023
|
-
output_format: req.output_format,
|
|
1024
|
-
infer_output_format: req.infer_output_format,
|
|
1025
|
-
num_examples: req.num_examples,
|
|
1026
|
-
seed: req.seed,
|
|
1027
|
-
session_id: req.session_id,
|
|
1028
|
-
min_criteria: req.min_criteria,
|
|
1029
|
-
temperature: req.temperature,
|
|
1030
|
-
constraints: req.constraints,
|
|
1031
|
-
project_id: req.project_id,
|
|
1032
|
-
generation_profile: req.generation_profile,
|
|
1033
|
-
include_reasoning_trace: req.include_reasoning_trace,
|
|
1034
|
-
reasoning_effort: req.reasoning_effort,
|
|
1035
|
-
target_choices: req.target_choices,
|
|
1036
|
-
quality: req.quality,
|
|
1037
|
-
split_ratio: req.split_ratio,
|
|
1038
|
-
negative_ratio: req.negative_ratio,
|
|
1039
|
-
multiplicator: req.multiplicator,
|
|
1040
|
-
use_meta_felix: req.use_meta_felix,
|
|
1041
|
-
type: req.type,
|
|
1042
|
-
visibility: req.visibility,
|
|
1043
|
-
});
|
|
1044
|
-
}
|
|
1045
|
-
|
|
1046
|
-
// Records Generation
|
|
1047
|
-
export interface GenerateRecordsRequest {
|
|
1048
|
-
fields: RecordField[];
|
|
1049
|
-
dataset_name?: string;
|
|
1050
|
-
num_examples?: number;
|
|
1051
|
-
domain_description?: string;
|
|
1052
|
-
seed?: number;
|
|
1053
|
-
temperature?: number;
|
|
1054
|
-
constraints?: ConstraintRequest[];
|
|
1055
|
-
quality?: "light" | "medium" | "heavy";
|
|
1056
|
-
generation_profile?: "auto" | "fast" | "balanced" | "quality";
|
|
1057
|
-
include_reasoning_trace?: boolean;
|
|
1058
|
-
reasoning_effort?: "low" | "medium" | "high";
|
|
1059
|
-
min_criteria?: number;
|
|
1060
|
-
target_choices?: number;
|
|
1061
|
-
split_ratio?: Record<string, number>;
|
|
1062
|
-
negative_ratio?: number;
|
|
1063
|
-
multiplicator?: Record<string, unknown>;
|
|
1064
|
-
project_id?: string;
|
|
1065
|
-
use_meta_felix?: boolean;
|
|
1066
|
-
type?: "training" | "evaluation" | "split";
|
|
1067
|
-
visibility?: "private" | "public";
|
|
1068
|
-
classified_examples?: Record<string, unknown>[];
|
|
1069
|
-
}
|
|
1070
|
-
|
|
1071
|
-
export async function generateRecords(
|
|
1072
|
-
req: GenerateRecordsRequest
|
|
1073
|
-
): Promise<ApiResult<GenerateJobStatus>> {
|
|
1074
|
-
return generateDataset({
|
|
1075
|
-
task_type: "records",
|
|
1076
|
-
dataset_name: req.dataset_name ?? makeDefaultDatasetName("records"),
|
|
1077
|
-
fields: req.fields,
|
|
1078
|
-
num_examples: req.num_examples,
|
|
1079
|
-
domain_description: req.domain_description,
|
|
1080
|
-
seed: req.seed,
|
|
1081
|
-
temperature: req.temperature,
|
|
1082
|
-
constraints: req.constraints,
|
|
1083
|
-
project_id: req.project_id,
|
|
1084
|
-
generation_profile: req.generation_profile,
|
|
1085
|
-
include_reasoning_trace: req.include_reasoning_trace,
|
|
1086
|
-
reasoning_effort: req.reasoning_effort,
|
|
1087
|
-
quality: req.quality,
|
|
1088
|
-
min_criteria: req.min_criteria,
|
|
1089
|
-
target_choices: req.target_choices,
|
|
1090
|
-
split_ratio: req.split_ratio,
|
|
1091
|
-
negative_ratio: req.negative_ratio,
|
|
1092
|
-
multiplicator: req.multiplicator,
|
|
1093
|
-
use_meta_felix: req.use_meta_felix,
|
|
1094
|
-
type: req.type,
|
|
1095
|
-
visibility: req.visibility,
|
|
1096
|
-
classified_examples: req.classified_examples,
|
|
1097
|
-
});
|
|
1098
|
-
}
|
|
1099
|
-
|
|
1100
|
-
// Fields Generation
|
|
1101
|
-
export interface GenerateFieldsRequest {
|
|
1102
|
-
input_fields: RecordField[];
|
|
1103
|
-
output_fields: RecordField[];
|
|
1104
|
-
dataset_name?: string;
|
|
1105
|
-
num_examples?: number;
|
|
1106
|
-
domain_description?: string;
|
|
1107
|
-
seed?: number;
|
|
1108
|
-
temperature?: number;
|
|
1109
|
-
constraints?: ConstraintRequest[];
|
|
1110
|
-
save_dataset?: boolean;
|
|
1111
|
-
quality?: "light" | "medium" | "heavy";
|
|
1112
|
-
generation_profile?: "auto" | "fast" | "balanced" | "quality";
|
|
1113
|
-
include_reasoning_trace?: boolean;
|
|
1114
|
-
reasoning_effort?: "low" | "medium" | "high";
|
|
1115
|
-
min_criteria?: number;
|
|
1116
|
-
target_choices?: number;
|
|
1117
|
-
split_ratio?: Record<string, number>;
|
|
1118
|
-
negative_ratio?: number;
|
|
1119
|
-
multiplicator?: Record<string, unknown>;
|
|
1120
|
-
project_id?: string;
|
|
1121
|
-
use_meta_felix?: boolean;
|
|
1122
|
-
type?: "training" | "evaluation" | "split";
|
|
1123
|
-
visibility?: "private" | "public";
|
|
1124
|
-
classified_examples?: Record<string, unknown>[];
|
|
1125
|
-
}
|
|
1126
|
-
|
|
1127
|
-
export async function generateFields(
|
|
1128
|
-
req: GenerateFieldsRequest
|
|
1129
|
-
): Promise<ApiResult<GenerateJobStatus>> {
|
|
1130
|
-
return generateDataset({
|
|
1131
|
-
task_type: "fields",
|
|
1132
|
-
dataset_name: req.dataset_name ?? makeDefaultDatasetName("fields"),
|
|
1133
|
-
input_fields: req.input_fields,
|
|
1134
|
-
output_fields: req.output_fields,
|
|
1135
|
-
num_examples: req.num_examples,
|
|
1136
|
-
domain_description: req.domain_description,
|
|
1137
|
-
seed: req.seed,
|
|
1138
|
-
temperature: req.temperature,
|
|
1139
|
-
constraints: req.constraints,
|
|
1140
|
-
project_id: req.project_id,
|
|
1141
|
-
generation_profile: req.generation_profile,
|
|
1142
|
-
include_reasoning_trace: req.include_reasoning_trace,
|
|
1143
|
-
reasoning_effort: req.reasoning_effort,
|
|
1144
|
-
quality: req.quality,
|
|
1145
|
-
min_criteria: req.min_criteria,
|
|
1146
|
-
target_choices: req.target_choices,
|
|
1147
|
-
split_ratio: req.split_ratio,
|
|
1148
|
-
negative_ratio: req.negative_ratio,
|
|
1149
|
-
multiplicator: req.multiplicator,
|
|
1150
|
-
use_meta_felix: req.use_meta_felix,
|
|
1151
|
-
type: req.type,
|
|
1152
|
-
visibility: req.visibility,
|
|
1153
|
-
classified_examples: req.classified_examples,
|
|
1154
|
-
});
|
|
1155
|
-
}
|
|
1156
|
-
|
|
1157
|
-
export interface LabelExistingFieldsRequest {
|
|
1158
|
-
input_fields: RecordField[];
|
|
1159
|
-
output_fields: RecordField[];
|
|
1160
|
-
inputs: Record<string, unknown>[];
|
|
1161
|
-
domain_description?: string;
|
|
1162
|
-
seed?: number;
|
|
1163
|
-
temperature?: number;
|
|
1164
|
-
constraints?: ConstraintRequest[];
|
|
1165
|
-
save_dataset?: boolean;
|
|
1166
|
-
dataset_name?: string;
|
|
1167
|
-
project_id?: string;
|
|
1168
|
-
}
|
|
1169
|
-
|
|
1170
|
-
export async function labelExistingFields(
|
|
1171
|
-
req: LabelExistingFieldsRequest
|
|
1172
|
-
): Promise<ApiResult<GenerateResponse>> {
|
|
1173
|
-
return request<GenerateResponse>("POST", "/generate/fields/label-existing", req);
|
|
1174
|
-
}
|
|
1175
|
-
|
|
1176
|
-
export interface InferFieldsRequest {
|
|
1177
|
-
domain_description: string;
|
|
1178
|
-
}
|
|
1179
|
-
|
|
1180
|
-
export async function inferFields(
|
|
1181
|
-
req: InferFieldsRequest
|
|
1182
|
-
): Promise<ApiResult<InferFieldsResponse>> {
|
|
1183
|
-
return request<InferFieldsResponse>("POST", "/generate/fields/infer-fields", req);
|
|
1184
|
-
}
|
|
1185
|
-
|
|
1186
|
-
export interface ImprovePromptRequest {
|
|
1187
|
-
prompt: string;
|
|
1188
|
-
data_type?: string;
|
|
1189
|
-
}
|
|
1190
|
-
|
|
1191
|
-
export interface ImprovePromptResponse {
|
|
1192
|
-
success: boolean;
|
|
1193
|
-
improved_prompt: string;
|
|
1194
|
-
summary: string;
|
|
1195
|
-
}
|
|
1196
|
-
|
|
1197
|
-
export async function improvePrompt(
|
|
1198
|
-
req: ImprovePromptRequest
|
|
1199
|
-
): Promise<ApiResult<ImprovePromptResponse>> {
|
|
1200
|
-
return request<ImprovePromptResponse>("POST", "/generate/improve-prompt", req);
|
|
1201
|
-
}
|
|
1202
|
-
|
|
1203
|
-
export interface InferAdvancedRequest {
|
|
1204
|
-
prompt: string;
|
|
1205
|
-
data_type?: string;
|
|
1206
|
-
labels?: string[];
|
|
1207
|
-
}
|
|
1208
|
-
|
|
1209
|
-
export interface InferredConstraint {
|
|
1210
|
-
description: string;
|
|
1211
|
-
choices?: string[];
|
|
1212
|
-
probability?: number;
|
|
1213
|
-
}
|
|
1214
|
-
|
|
1215
|
-
export interface InferredMultiplicator {
|
|
1216
|
-
prompt: string;
|
|
1217
|
-
choices: string[];
|
|
1218
|
-
}
|
|
1219
|
-
|
|
1220
|
-
export interface InferAdvancedResponse {
|
|
1221
|
-
success: boolean;
|
|
1222
|
-
constraints: InferredConstraint[];
|
|
1223
|
-
multiplicator?: InferredMultiplicator;
|
|
1224
|
-
}
|
|
1225
|
-
|
|
1226
|
-
export async function inferAdvanced(
|
|
1227
|
-
req: InferAdvancedRequest
|
|
1228
|
-
): Promise<ApiResult<InferAdvancedResponse>> {
|
|
1229
|
-
return request<InferAdvancedResponse>("POST", "/generate/infer-advanced", req);
|
|
1230
|
-
}
|
|
1231
|
-
|
|
1232
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
1233
|
-
// Training Jobs
|
|
1234
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
1235
|
-
|
|
1236
|
-
export interface TrainingJob {
|
|
1237
|
-
id: string;
|
|
1238
|
-
user_id: string;
|
|
1239
|
-
project_id?: string;
|
|
1240
|
-
model_name?: string;
|
|
1241
|
-
datasets: Array<{ name: string; version?: string }>;
|
|
1242
|
-
base_model: string;
|
|
1243
|
-
validation_data_percentage: number;
|
|
1244
|
-
nr_epochs: number;
|
|
1245
|
-
learning_rate: number;
|
|
1246
|
-
batch_size: number;
|
|
1247
|
-
trained_model_path?: string;
|
|
1248
|
-
job_reference?: string;
|
|
1249
|
-
instance_type?: string;
|
|
1250
|
-
status: string;
|
|
1251
|
-
error_message?: string;
|
|
1252
|
-
created_at: string;
|
|
1253
|
-
updated_at: string;
|
|
1254
|
-
started_at?: string;
|
|
1255
|
-
completed_at?: string;
|
|
1256
|
-
model_auto_selected?: boolean;
|
|
1257
|
-
model_selection_reason?: string;
|
|
1258
|
-
task_type?: string;
|
|
1259
|
-
labels?: string[];
|
|
1260
|
-
example?: string;
|
|
1261
|
-
deployment_status?: string;
|
|
1262
|
-
metrics?: Record<string, unknown>;
|
|
1263
|
-
version_number?: string;
|
|
1264
|
-
root_job_id?: string;
|
|
1265
|
-
}
|
|
1266
|
-
|
|
1267
|
-
export interface TrainingJobListResponse {
|
|
1268
|
-
success: boolean;
|
|
1269
|
-
training_jobs: TrainingJob[];
|
|
1270
|
-
count: number;
|
|
1271
|
-
}
|
|
1272
|
-
|
|
1273
|
-
export async function listJobs(
|
|
1274
|
-
options: { status?: string; project_id?: string; limit?: number } = {}
|
|
1275
|
-
): Promise<ApiResult<TrainingJobListResponse>> {
|
|
1276
|
-
const params = new URLSearchParams();
|
|
1277
|
-
if (options.status) params.set("status", options.status);
|
|
1278
|
-
if (options.project_id) params.set("project_id", options.project_id);
|
|
1279
|
-
if (options.limit !== undefined) params.set("limit", String(options.limit));
|
|
1280
|
-
const query = params.toString();
|
|
1281
|
-
const url = query ? `/felix/training-jobs?${query}` : "/felix/training-jobs";
|
|
1282
|
-
return request<TrainingJobListResponse>("GET", url);
|
|
1283
|
-
}
|
|
1284
|
-
|
|
1285
|
-
export async function getJob(jobId: string): Promise<ApiResult<TrainingJob>> {
|
|
1286
|
-
return request<TrainingJob>("GET", `/felix/training-jobs/${jobId}`);
|
|
1287
|
-
}
|
|
1288
|
-
|
|
1289
|
-
/**
|
|
1290
|
-
* Assign (or unassign) a training job to a project. The deploy endpoint
|
|
1291
|
-
* (`POST /projects/{id}/deployments`) requires the job's `project_id` to
|
|
1292
|
-
* match the target project, so callers typically PATCH this before deploy.
|
|
1293
|
-
*
|
|
1294
|
-
* @param jobId Training job UUID.
|
|
1295
|
-
* @param projectId Project UUID to attach to, or `null` to unassign.
|
|
1296
|
-
*/
|
|
1297
|
-
export async function updateTrainingJob(
|
|
1298
|
-
jobId: string,
|
|
1299
|
-
body: { project_id: string | null }
|
|
1300
|
-
): Promise<ApiResult<{ success?: boolean; message?: string }>> {
|
|
1301
|
-
return request<{ success?: boolean; message?: string }>(
|
|
1302
|
-
"PATCH",
|
|
1303
|
-
`/felix/training-jobs/${jobId}`,
|
|
1304
|
-
body
|
|
1305
|
-
);
|
|
1306
|
-
}
|
|
1307
|
-
|
|
1308
|
-
export interface TrainingJobCreateRequest {
|
|
1309
|
-
model_name: string;
|
|
1310
|
-
datasets: DatasetRef[];
|
|
1311
|
-
base_model?: string;
|
|
1312
|
-
auto_select_model?: boolean;
|
|
1313
|
-
validation_data_percentage?: number;
|
|
1314
|
-
nr_epochs?: number;
|
|
1315
|
-
learning_rate?: number;
|
|
1316
|
-
batch_size?: number;
|
|
1317
|
-
save_steps?: number;
|
|
1318
|
-
wandb_api_key?: string;
|
|
1319
|
-
project_id?: string;
|
|
1320
|
-
training_type?: "full" | "lora";
|
|
1321
|
-
lora_r?: number;
|
|
1322
|
-
lora_alpha?: number;
|
|
1323
|
-
lora_dropout?: number;
|
|
1324
|
-
enable_probe_override?: boolean;
|
|
1325
|
-
probe_delta_threshold?: number;
|
|
1326
|
-
}
|
|
1327
|
-
|
|
1328
|
-
export async function createJob(
|
|
1329
|
-
req: TrainingJobCreateRequest
|
|
1330
|
-
): Promise<ApiResult<TrainingJob>> {
|
|
1331
|
-
return request<TrainingJob>("POST", "/felix/training-jobs", req);
|
|
1332
|
-
}
|
|
1333
|
-
|
|
1334
|
-
export interface TrainingLog {
|
|
1335
|
-
id: string;
|
|
1336
|
-
job_id: string;
|
|
1337
|
-
timestamp: string;
|
|
1338
|
-
level: string;
|
|
1339
|
-
message: string;
|
|
1340
|
-
source: string;
|
|
1341
|
-
}
|
|
1342
|
-
|
|
1343
|
-
export interface TrainingLogsResponse {
|
|
1344
|
-
job_id: string;
|
|
1345
|
-
logs: TrainingLog[];
|
|
1346
|
-
total_logs: number;
|
|
1347
|
-
}
|
|
1348
|
-
|
|
1349
|
-
export async function getJobLogs(
|
|
1350
|
-
jobId: string
|
|
1351
|
-
): Promise<ApiResult<TrainingLogsResponse>> {
|
|
1352
|
-
return request<TrainingLogsResponse>("GET", `/felix/training-jobs/${jobId}/logs`);
|
|
1353
|
-
}
|
|
1354
|
-
|
|
1355
|
-
export async function deleteJob(jobId: string): Promise<ApiResult> {
|
|
1356
|
-
return request("DELETE", `/felix/training-jobs/${jobId}`);
|
|
1357
|
-
}
|
|
1358
|
-
|
|
1359
|
-
export interface StopJobResponse {
|
|
1360
|
-
success: boolean;
|
|
1361
|
-
message: string;
|
|
1362
|
-
job_id: string;
|
|
1363
|
-
status: string;
|
|
1364
|
-
}
|
|
1365
|
-
|
|
1366
|
-
export async function stopJob(
|
|
1367
|
-
jobId: string
|
|
1368
|
-
): Promise<ApiResult<StopJobResponse>> {
|
|
1369
|
-
return request<StopJobResponse>("POST", `/felix/training-jobs/${jobId}/stop`);
|
|
1370
|
-
}
|
|
1371
|
-
|
|
1372
|
-
export interface TerminateJobResponse {
|
|
1373
|
-
success: boolean;
|
|
1374
|
-
message: string;
|
|
1375
|
-
job_id: string;
|
|
1376
|
-
deleted_checkpoints: number;
|
|
1377
|
-
}
|
|
1378
|
-
|
|
1379
|
-
export async function terminateJob(
|
|
1380
|
-
jobId: string
|
|
1381
|
-
): Promise<ApiResult<TerminateJobResponse>> {
|
|
1382
|
-
return request<TerminateJobResponse>(
|
|
1383
|
-
"POST",
|
|
1384
|
-
`/felix/training-jobs/${jobId}/terminate`
|
|
1385
|
-
);
|
|
1386
|
-
}
|
|
1387
|
-
|
|
1388
|
-
export async function syncJob(jobId: string): Promise<ApiResult<TrainingJob>> {
|
|
1389
|
-
return request<TrainingJob>("POST", `/felix/training-jobs/${jobId}/sync`);
|
|
1390
|
-
}
|
|
1391
|
-
|
|
1392
|
-
export interface Checkpoint {
|
|
1393
|
-
id: string;
|
|
1394
|
-
job_id: string;
|
|
1395
|
-
epoch: number;
|
|
1396
|
-
step?: number;
|
|
1397
|
-
training_loss?: number;
|
|
1398
|
-
validation_loss?: number;
|
|
1399
|
-
accuracy?: number;
|
|
1400
|
-
learning_rate?: number;
|
|
1401
|
-
gpu_memory_used?: number;
|
|
1402
|
-
gpu_memory_total?: number;
|
|
1403
|
-
}
|
|
1404
|
-
|
|
1405
|
-
export interface CheckpointListResponse {
|
|
1406
|
-
success: boolean;
|
|
1407
|
-
checkpoints: Checkpoint[];
|
|
1408
|
-
count: number;
|
|
1409
|
-
}
|
|
1410
|
-
|
|
1411
|
-
export async function listCheckpoints(
|
|
1412
|
-
jobId: string
|
|
1413
|
-
): Promise<ApiResult<CheckpointListResponse>> {
|
|
1414
|
-
return request<CheckpointListResponse>(
|
|
1415
|
-
"GET",
|
|
1416
|
-
`/felix/training-jobs/${jobId}/checkpoints`
|
|
1417
|
-
);
|
|
1418
|
-
}
|
|
1419
|
-
|
|
1420
|
-
export interface DeployCheckpointResponse {
|
|
1421
|
-
success: boolean;
|
|
1422
|
-
message: string;
|
|
1423
|
-
job_id: string;
|
|
1424
|
-
checkpoint_id: string;
|
|
1425
|
-
mme_path: string;
|
|
1426
|
-
}
|
|
1427
|
-
|
|
1428
|
-
export async function deployCheckpoint(
|
|
1429
|
-
jobId: string,
|
|
1430
|
-
checkpointId: string
|
|
1431
|
-
): Promise<ApiResult<DeployCheckpointResponse>> {
|
|
1432
|
-
return request<DeployCheckpointResponse>(
|
|
1433
|
-
"POST",
|
|
1434
|
-
`/felix/training-jobs/${jobId}/checkpoints/${checkpointId}/deploy`
|
|
1435
|
-
);
|
|
1436
|
-
}
|
|
1437
|
-
|
|
1438
|
-
export interface UpdateModelNameResponse {
|
|
1439
|
-
success: boolean;
|
|
1440
|
-
message: string;
|
|
1441
|
-
job_id: string;
|
|
1442
|
-
model_name: string;
|
|
1443
|
-
}
|
|
1444
|
-
|
|
1445
|
-
export async function updateModelName(
|
|
1446
|
-
jobId: string,
|
|
1447
|
-
modelName: string
|
|
1448
|
-
): Promise<ApiResult<UpdateModelNameResponse>> {
|
|
1449
|
-
return request<UpdateModelNameResponse>(
|
|
1450
|
-
"PATCH",
|
|
1451
|
-
`/felix/training-jobs/${jobId}/model-name`,
|
|
1452
|
-
{ model_name: modelName }
|
|
1453
|
-
);
|
|
1454
|
-
}
|
|
1455
|
-
|
|
1456
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
1457
|
-
// Models
|
|
1458
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
1459
|
-
|
|
1460
|
-
export interface DeployedModel {
|
|
1461
|
-
id: string;
|
|
1462
|
-
job_id: string | null;
|
|
1463
|
-
model_name?: string;
|
|
1464
|
-
s3_model_uri?: string;
|
|
1465
|
-
mme_model_filename?: string;
|
|
1466
|
-
endpoint_name?: string;
|
|
1467
|
-
is_base_model: boolean;
|
|
1468
|
-
deployed_at?: string | null;
|
|
1469
|
-
last_used_at?: string | null;
|
|
1470
|
-
invocation_count: number;
|
|
1471
|
-
created_at?: string | null;
|
|
1472
|
-
updated_at?: string | null;
|
|
1473
|
-
}
|
|
1474
|
-
|
|
1475
|
-
export interface DeployedModelsListResponse {
|
|
1476
|
-
success: boolean;
|
|
1477
|
-
models: DeployedModel[];
|
|
1478
|
-
count: number;
|
|
1479
|
-
}
|
|
1480
|
-
|
|
1481
|
-
interface AnthropicCompatibleModelEntry {
|
|
1482
|
-
id?: string;
|
|
1483
|
-
display_name?: string;
|
|
1484
|
-
type?: string;
|
|
1485
|
-
created_at?: string | null;
|
|
1486
|
-
created?: number;
|
|
1487
|
-
owned_by?: string;
|
|
1488
|
-
}
|
|
1489
|
-
|
|
1490
|
-
interface AnthropicCompatibleModelsResponse {
|
|
1491
|
-
data?: AnthropicCompatibleModelEntry[];
|
|
1492
|
-
}
|
|
1493
|
-
|
|
1494
|
-
function isLikelyJobId(value: unknown): value is string {
|
|
1495
|
-
if (typeof value !== "string") return false;
|
|
1496
|
-
return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value);
|
|
1497
|
-
}
|
|
1498
|
-
|
|
1499
|
-
export async function listModels(
|
|
1500
|
-
options: { includeBase?: boolean } = {}
|
|
1501
|
-
): Promise<ApiResult<DeployedModelsListResponse>> {
|
|
1502
|
-
const params = new URLSearchParams();
|
|
1503
|
-
if (options.includeBase !== undefined) {
|
|
1504
|
-
params.set("include_base", String(options.includeBase));
|
|
1505
|
-
}
|
|
1506
|
-
const query = params.toString();
|
|
1507
|
-
const legacyUrl = query ? `/felix/models?${query}` : "/felix/models";
|
|
1508
|
-
const legacy = await request<DeployedModelsListResponse>("GET", legacyUrl);
|
|
1509
|
-
if (legacy.ok || legacy.status !== 404) {
|
|
1510
|
-
return legacy;
|
|
1511
|
-
}
|
|
1512
|
-
|
|
1513
|
-
// Backend removed /felix/models. Fall back to the canonical
|
|
1514
|
-
// Anthropic/OpenAI-compatible catalog and adapt to DeployedModel.
|
|
1515
|
-
const fallback = await request<AnthropicCompatibleModelsResponse>("GET", "/v1/models");
|
|
1516
|
-
if (!fallback.ok) {
|
|
1517
|
-
return {
|
|
1518
|
-
ok: false,
|
|
1519
|
-
status: fallback.status,
|
|
1520
|
-
error: fallback.error ?? "Failed to list deployed models.",
|
|
1521
|
-
};
|
|
1522
|
-
}
|
|
1523
|
-
const entries = fallback.data?.data ?? [];
|
|
1524
|
-
const models: DeployedModel[] = entries
|
|
1525
|
-
.filter((entry) => entry && (options.includeBase || entry.owned_by !== "anthropic"))
|
|
1526
|
-
.map((entry) => {
|
|
1527
|
-
const id = typeof entry.id === "string" ? entry.id : "";
|
|
1528
|
-
return {
|
|
1529
|
-
id,
|
|
1530
|
-
job_id: isLikelyJobId(id) ? id : null,
|
|
1531
|
-
model_name: entry.display_name || id || undefined,
|
|
1532
|
-
is_base_model: entry.owned_by === "anthropic" || entry.owned_by === "openai",
|
|
1533
|
-
deployed_at: entry.created_at ?? null,
|
|
1534
|
-
last_used_at: null,
|
|
1535
|
-
invocation_count: 0,
|
|
1536
|
-
created_at: entry.created_at ?? null,
|
|
1537
|
-
updated_at: entry.created_at ?? null,
|
|
1538
|
-
};
|
|
1539
|
-
});
|
|
1540
|
-
|
|
1541
|
-
return {
|
|
1542
|
-
ok: true,
|
|
1543
|
-
status: fallback.status,
|
|
1544
|
-
data: {
|
|
1545
|
-
success: true,
|
|
1546
|
-
models,
|
|
1547
|
-
count: models.length,
|
|
1548
|
-
},
|
|
1549
|
-
};
|
|
1550
|
-
}
|
|
1551
|
-
|
|
1552
|
-
export async function deleteModel(jobId: string): Promise<ApiResult> {
|
|
1553
|
-
return request("DELETE", `/felix/models/${jobId}`);
|
|
1554
|
-
}
|
|
1555
|
-
|
|
1556
|
-
export interface TrainedModel {
|
|
1557
|
-
id: string;
|
|
1558
|
-
job_id?: string;
|
|
1559
|
-
model_name?: string;
|
|
1560
|
-
trained_model_path?: string;
|
|
1561
|
-
datasets?: Array<{
|
|
1562
|
-
name: string;
|
|
1563
|
-
version: string;
|
|
1564
|
-
}>;
|
|
1565
|
-
base_model?: string;
|
|
1566
|
-
validation_data_percentage?: number;
|
|
1567
|
-
nr_epochs?: number;
|
|
1568
|
-
learning_rate?: number;
|
|
1569
|
-
batch_size?: number;
|
|
1570
|
-
instance_type?: string;
|
|
1571
|
-
status: string;
|
|
1572
|
-
error_message?: string | null;
|
|
1573
|
-
created_at?: string | null;
|
|
1574
|
-
updated_at?: string | null;
|
|
1575
|
-
started_at?: string | null;
|
|
1576
|
-
completed_at?: string | null;
|
|
1577
|
-
model_auto_selected?: boolean;
|
|
1578
|
-
model_selection_reason?: string | null;
|
|
1579
|
-
metrics?: {
|
|
1580
|
-
final_training_loss?: number;
|
|
1581
|
-
final_validation_loss?: number;
|
|
1582
|
-
best_validation_loss?: number;
|
|
1583
|
-
eval_f1_score?: number;
|
|
1584
|
-
eval_precision?: number;
|
|
1585
|
-
eval_recall?: number;
|
|
1586
|
-
eval_accuracy?: number;
|
|
1587
|
-
eval_validation_loss?: number;
|
|
1588
|
-
};
|
|
1589
|
-
}
|
|
1590
|
-
|
|
1591
|
-
export interface TrainedModelsListResponse {
|
|
1592
|
-
success: boolean;
|
|
1593
|
-
training_jobs: TrainedModel[];
|
|
1594
|
-
count: number;
|
|
1595
|
-
}
|
|
1596
|
-
|
|
1597
|
-
export async function listTrainedModels(): Promise<
|
|
1598
|
-
ApiResult<TrainedModelsListResponse>
|
|
1599
|
-
> {
|
|
1600
|
-
return request<TrainedModelsListResponse>("GET", "/felix/trained-models");
|
|
1601
|
-
}
|
|
1602
|
-
|
|
1603
|
-
export interface AllModelsResponse {
|
|
1604
|
-
deployed: DeployedModel[];
|
|
1605
|
-
trained: TrainedModel[];
|
|
1606
|
-
projects: ProjectResponse[];
|
|
1607
|
-
}
|
|
1608
|
-
|
|
1609
|
-
export async function listAllModels(): Promise<ApiResult<AllModelsResponse>> {
|
|
1610
|
-
const [deployedResult, trainedResult, projectsResult] = await Promise.all([
|
|
1611
|
-
listModels(),
|
|
1612
|
-
listTrainedModels(),
|
|
1613
|
-
listProjects(),
|
|
1614
|
-
]);
|
|
1615
|
-
|
|
1616
|
-
if (!deployedResult.ok) {
|
|
1617
|
-
return { ok: false, status: deployedResult.status, error: deployedResult.error };
|
|
1618
|
-
}
|
|
1619
|
-
if (!trainedResult.ok) {
|
|
1620
|
-
return { ok: false, status: trainedResult.status, error: trainedResult.error };
|
|
1621
|
-
}
|
|
1622
|
-
if (!projectsResult.ok) {
|
|
1623
|
-
return { ok: false, status: projectsResult.status, error: projectsResult.error };
|
|
1624
|
-
}
|
|
1625
|
-
|
|
1626
|
-
return {
|
|
1627
|
-
ok: true,
|
|
1628
|
-
status: 200,
|
|
1629
|
-
data: {
|
|
1630
|
-
deployed: deployedResult.data?.models ?? [],
|
|
1631
|
-
trained: trainedResult.data?.training_jobs ?? [],
|
|
1632
|
-
projects: projectsResult.data?.projects ?? [],
|
|
1633
|
-
},
|
|
1634
|
-
};
|
|
1635
|
-
}
|
|
1636
|
-
|
|
1637
|
-
export interface ModelDownloadResponse {
|
|
1638
|
-
success?: boolean;
|
|
1639
|
-
job_id?: string;
|
|
1640
|
-
download_url: string;
|
|
1641
|
-
expires_in_seconds?: number;
|
|
1642
|
-
file_name?: string;
|
|
1643
|
-
message?: string;
|
|
1644
|
-
}
|
|
1645
|
-
|
|
1646
|
-
export async function downloadModel(
|
|
1647
|
-
jobId: string
|
|
1648
|
-
): Promise<ApiResult<ModelDownloadResponse>> {
|
|
1649
|
-
return request<ModelDownloadResponse>(
|
|
1650
|
-
"GET",
|
|
1651
|
-
`/felix/training-jobs/${jobId}/download`
|
|
1652
|
-
);
|
|
1653
|
-
}
|
|
1654
|
-
|
|
1655
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
1656
|
-
// Inference
|
|
1657
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
1658
|
-
|
|
1659
|
-
export interface EncoderInferenceRequest {
|
|
1660
|
-
model_id: string;
|
|
1661
|
-
task: "extract_entities" | "classify_text" | "extract_json" | "schema";
|
|
1662
|
-
text: string | string[];
|
|
1663
|
-
schema: string[] | Record<string, unknown>;
|
|
1664
|
-
threshold?: number;
|
|
1665
|
-
include_confidence?: boolean;
|
|
1666
|
-
include_spans?: boolean;
|
|
1667
|
-
format_results?: boolean;
|
|
1668
|
-
is_warmup?: boolean;
|
|
1669
|
-
store?: boolean;
|
|
1670
|
-
project_id?: string;
|
|
1671
|
-
}
|
|
1672
|
-
|
|
1673
|
-
export interface InferenceMessage {
|
|
1674
|
-
role: "system" | "user" | "assistant";
|
|
1675
|
-
content: string;
|
|
1676
|
-
}
|
|
1677
|
-
|
|
1678
|
-
export interface GenerateInferenceRequest {
|
|
1679
|
-
model_id: string;
|
|
1680
|
-
task: "generate";
|
|
1681
|
-
messages: InferenceMessage[];
|
|
1682
|
-
max_tokens?: number;
|
|
1683
|
-
temperature?: number;
|
|
1684
|
-
top_p?: number;
|
|
1685
|
-
include_reasoning_trace?: boolean;
|
|
1686
|
-
is_warmup?: boolean;
|
|
1687
|
-
store?: boolean;
|
|
1688
|
-
project_id?: string;
|
|
1689
|
-
}
|
|
1690
|
-
|
|
1691
|
-
export type InferenceRequest = EncoderInferenceRequest | GenerateInferenceRequest;
|
|
1692
|
-
|
|
1693
|
-
export interface EncoderInferenceResponse {
|
|
1694
|
-
type: "encoder";
|
|
1695
|
-
inference_id: string;
|
|
1696
|
-
result: Record<string, unknown> | unknown[];
|
|
1697
|
-
model_id: string;
|
|
1698
|
-
latency_ms: number;
|
|
1699
|
-
token_usage: number;
|
|
1700
|
-
model_used: string;
|
|
1701
|
-
}
|
|
1702
|
-
|
|
1703
|
-
export interface GenerateInferenceResponse {
|
|
1704
|
-
type: "decoder";
|
|
1705
|
-
inference_id: string;
|
|
1706
|
-
completion: string;
|
|
1707
|
-
reasoning_trace?: string | null;
|
|
1708
|
-
model_id: string;
|
|
1709
|
-
latency_ms: number;
|
|
1710
|
-
}
|
|
1711
|
-
|
|
1712
|
-
export type InferenceResponse = EncoderInferenceResponse | GenerateInferenceResponse;
|
|
1713
|
-
|
|
1714
|
-
export async function runInference(
|
|
1715
|
-
req: InferenceRequest
|
|
1716
|
-
): Promise<ApiResult<InferenceResponse>> {
|
|
1717
|
-
return request<InferenceResponse>("POST", "/inference", req);
|
|
1718
|
-
}
|
|
1719
|
-
|
|
1720
|
-
export interface TextCompletionRequest {
|
|
1721
|
-
model: string;
|
|
1722
|
-
prompt: string;
|
|
1723
|
-
temperature?: number;
|
|
1724
|
-
max_tokens?: number;
|
|
1725
|
-
stop?: string[] | string;
|
|
1726
|
-
echo?: boolean;
|
|
1727
|
-
extra_body?: Record<string, unknown>;
|
|
1728
|
-
}
|
|
1729
|
-
|
|
1730
|
-
export interface TextCompletionUsage {
|
|
1731
|
-
prompt_tokens: number;
|
|
1732
|
-
completion_tokens: number;
|
|
1733
|
-
total_tokens: number;
|
|
1734
|
-
}
|
|
1735
|
-
|
|
1736
|
-
export interface TextCompletionChoice {
|
|
1737
|
-
index?: number;
|
|
1738
|
-
text: string;
|
|
1739
|
-
finish_reason?: string | null;
|
|
1740
|
-
}
|
|
1741
|
-
|
|
1742
|
-
export interface TextCompletionResponse {
|
|
1743
|
-
id?: string;
|
|
1744
|
-
object?: string;
|
|
1745
|
-
created?: number;
|
|
1746
|
-
model: string;
|
|
1747
|
-
choices: TextCompletionChoice[];
|
|
1748
|
-
usage: TextCompletionUsage;
|
|
1749
|
-
}
|
|
1750
|
-
|
|
1751
|
-
export async function runTextCompletion(
|
|
1752
|
-
req: TextCompletionRequest
|
|
1753
|
-
): Promise<ApiResult<TextCompletionResponse>> {
|
|
1754
|
-
return request<TextCompletionResponse>("POST", "/v1/completions", req);
|
|
1755
|
-
}
|
|
1756
|
-
|
|
1757
|
-
export interface BaseModelInfo {
|
|
1758
|
-
id: string;
|
|
1759
|
-
name?: string;
|
|
1760
|
-
label?: string;
|
|
1761
|
-
/**
|
|
1762
|
-
* One of "encoder" | "decoder" — the architectural family of the model.
|
|
1763
|
-
* Note: backend used to expose this as `type`; the field is now `task_type`.
|
|
1764
|
-
*/
|
|
1765
|
-
task_type?: string;
|
|
1766
|
-
supports_inference?: boolean;
|
|
1767
|
-
supports_on_demand_inference?: boolean;
|
|
1768
|
-
supports_training?: boolean;
|
|
1769
|
-
description?: string;
|
|
1770
|
-
tier?: "enterprise" | "open" | string;
|
|
1771
|
-
context_window?: number;
|
|
1772
|
-
license?: string;
|
|
1773
|
-
input_price_per_million?: number;
|
|
1774
|
-
output_price_per_million?: number;
|
|
1775
|
-
}
|
|
1776
|
-
|
|
1777
|
-
export interface BaseModelsResponse {
|
|
1778
|
-
models: BaseModelInfo[];
|
|
1779
|
-
}
|
|
1780
|
-
|
|
1781
|
-
export async function listBaseModels(): Promise<
|
|
1782
|
-
ApiResult<BaseModelsResponse | BaseModelInfo[]>
|
|
1783
|
-
> {
|
|
1784
|
-
return request<BaseModelsResponse | BaseModelInfo[]>("GET", "/base-models");
|
|
1785
|
-
}
|
|
1786
|
-
|
|
1787
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
1788
|
-
// Agent chat
|
|
1789
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
1790
|
-
|
|
1791
|
-
export interface AgentChatHistoryItem {
|
|
1792
|
-
role: "user" | "assistant" | "system" | string;
|
|
1793
|
-
content: string;
|
|
1794
|
-
}
|
|
1795
|
-
|
|
1796
|
-
export interface ChatSessionMessage {
|
|
1797
|
-
id?: string;
|
|
1798
|
-
session_id?: string;
|
|
1799
|
-
role: string;
|
|
1800
|
-
content: string;
|
|
1801
|
-
message_index?: number;
|
|
1802
|
-
created_at?: string;
|
|
1803
|
-
tool_call_id?: string | null;
|
|
1804
|
-
tool_calls?: Array<{
|
|
1805
|
-
id?: string;
|
|
1806
|
-
name?: string;
|
|
1807
|
-
args?: Record<string, unknown>;
|
|
1808
|
-
}> | null;
|
|
1809
|
-
images?: Array<Record<string, unknown>> | null;
|
|
1810
|
-
}
|
|
1811
|
-
|
|
1812
|
-
export interface ChatSessionResponse {
|
|
1813
|
-
id: string;
|
|
1814
|
-
user_id: string;
|
|
1815
|
-
title: string;
|
|
1816
|
-
created_at: string;
|
|
1817
|
-
updated_at: string;
|
|
1818
|
-
is_archived: boolean;
|
|
1819
|
-
project_id: string | null;
|
|
1820
|
-
modal_sandbox_id: string | null;
|
|
1821
|
-
raw_message_tree_present?: boolean;
|
|
1822
|
-
messages: ChatSessionMessage[];
|
|
1823
|
-
}
|
|
1824
|
-
|
|
1825
|
-
export interface CreateChatSessionRequest {
|
|
1826
|
-
first_message?: string;
|
|
1827
|
-
title?: string;
|
|
1828
|
-
project_id?: string;
|
|
1829
|
-
}
|
|
1830
|
-
|
|
1831
|
-
export interface UpdateChatSessionRequest {
|
|
1832
|
-
title?: string;
|
|
1833
|
-
is_archived?: boolean;
|
|
1834
|
-
}
|
|
1835
|
-
|
|
1836
|
-
export interface AppendSessionMessagesRequest {
|
|
1837
|
-
messages: Array<{
|
|
1838
|
-
role: string;
|
|
1839
|
-
content: string;
|
|
1840
|
-
tool_call_id?: string;
|
|
1841
|
-
tool_calls?: Array<{
|
|
1842
|
-
id?: string;
|
|
1843
|
-
name?: string;
|
|
1844
|
-
args?: Record<string, unknown>;
|
|
1845
|
-
[key: string]: unknown;
|
|
1846
|
-
}>;
|
|
1847
|
-
}>;
|
|
1848
|
-
}
|
|
1849
|
-
|
|
1850
|
-
export interface ChatSessionListResponse {
|
|
1851
|
-
success: boolean;
|
|
1852
|
-
sessions: Array<Pick<ChatSessionResponse, "id" | "user_id" | "title" | "created_at" | "updated_at" | "is_archived">>;
|
|
1853
|
-
}
|
|
1854
|
-
|
|
1855
|
-
export interface AgentChatRequest {
|
|
1856
|
-
message: string;
|
|
1857
|
-
conversation_id?: string;
|
|
1858
|
-
history?: AgentChatHistoryItem[];
|
|
1859
|
-
resume_value?: string;
|
|
1860
|
-
}
|
|
1861
|
-
|
|
1862
|
-
export interface AgentChatResponse {
|
|
1863
|
-
answer: string;
|
|
1864
|
-
conversation_id: string;
|
|
1865
|
-
tool_calls_made?: number;
|
|
1866
|
-
}
|
|
1867
|
-
|
|
1868
|
-
export interface AutoAgentRun {
|
|
1869
|
-
agent_run_id: string;
|
|
1870
|
-
status: string;
|
|
1871
|
-
created_at?: string;
|
|
1872
|
-
updated_at?: string;
|
|
1873
|
-
project_id?: string;
|
|
1874
|
-
model_id?: string;
|
|
1875
|
-
result_url?: string;
|
|
1876
|
-
run_type?: string;
|
|
1877
|
-
[key: string]: unknown;
|
|
1878
|
-
}
|
|
1879
|
-
|
|
1880
|
-
export async function agentChat(
|
|
1881
|
-
req: AgentChatRequest
|
|
1882
|
-
): Promise<ApiResult<AgentChatResponse>> {
|
|
1883
|
-
const baseUrl = getBaseUrl().replace(/\/$/, "");
|
|
1884
|
-
const apiKey = getApiKey();
|
|
1885
|
-
const url = `${baseUrl}/auto-agent/clarify`;
|
|
1886
|
-
const headers: Record<string, string> = {
|
|
1887
|
-
"Content-Type": "application/json",
|
|
1888
|
-
"User-Agent": "pioneer-cli/0.1.0",
|
|
1889
|
-
};
|
|
1890
|
-
|
|
1891
|
-
if (apiKey) {
|
|
1892
|
-
headers["X-API-Key"] = apiKey;
|
|
1893
|
-
}
|
|
1894
|
-
|
|
1895
|
-
try {
|
|
1896
|
-
const res = await fetch(url, {
|
|
1897
|
-
method: "POST",
|
|
1898
|
-
headers,
|
|
1899
|
-
body: JSON.stringify(req),
|
|
1900
|
-
});
|
|
1901
|
-
|
|
1902
|
-
const text = await res.text();
|
|
1903
|
-
|
|
1904
|
-
let parsedJson: unknown;
|
|
1905
|
-
try {
|
|
1906
|
-
parsedJson = JSON.parse(text);
|
|
1907
|
-
} catch {
|
|
1908
|
-
// Ignore; some responses may be SSE/event text or empty.
|
|
1909
|
-
}
|
|
1910
|
-
|
|
1911
|
-
const parseAgentStream = (raw: string): AgentChatResponse | undefined => {
|
|
1912
|
-
const direct = parseAgentPayload(raw);
|
|
1913
|
-
if (direct) return direct;
|
|
1914
|
-
|
|
1915
|
-
const events = raw
|
|
1916
|
-
.split("\n")
|
|
1917
|
-
.map((line) => line.trim())
|
|
1918
|
-
.filter((line) => line.startsWith("data:"));
|
|
1919
|
-
const fallback: AgentChatResponse = {
|
|
1920
|
-
answer: "",
|
|
1921
|
-
conversation_id: "",
|
|
1922
|
-
};
|
|
1923
|
-
|
|
1924
|
-
for (const eventLine of events) {
|
|
1925
|
-
const payload = eventLine.slice(5).trim();
|
|
1926
|
-
if (!payload) continue;
|
|
1927
|
-
|
|
1928
|
-
let event: Record<string, unknown> | undefined;
|
|
1929
|
-
try {
|
|
1930
|
-
event = JSON.parse(payload);
|
|
1931
|
-
} catch {
|
|
1932
|
-
continue;
|
|
1933
|
-
}
|
|
1934
|
-
if (typeof event === "object" && event) {
|
|
1935
|
-
const type = typeof event.type === "string" ? event.type : undefined;
|
|
1936
|
-
|
|
1937
|
-
if (type === "delta" && typeof event.content === "string") {
|
|
1938
|
-
fallback.answer += event.content;
|
|
1939
|
-
}
|
|
1940
|
-
|
|
1941
|
-
if (typeof event.content === "string" && !fallback.answer) {
|
|
1942
|
-
fallback.answer = event.content;
|
|
1943
|
-
}
|
|
1944
|
-
|
|
1945
|
-
if (typeof event.answer === "string") {
|
|
1946
|
-
fallback.answer = event.answer;
|
|
1947
|
-
}
|
|
1948
|
-
|
|
1949
|
-
if (typeof event.conversation_id === "string") {
|
|
1950
|
-
fallback.conversation_id = event.conversation_id;
|
|
1951
|
-
}
|
|
1952
|
-
|
|
1953
|
-
if (typeof event.tool_calls_made === "number") {
|
|
1954
|
-
fallback.tool_calls_made = event.tool_calls_made;
|
|
1955
|
-
}
|
|
1956
|
-
|
|
1957
|
-
if (type === "complete") {
|
|
1958
|
-
if (typeof event.conversation_id === "string") {
|
|
1959
|
-
fallback.conversation_id = event.conversation_id;
|
|
1960
|
-
}
|
|
1961
|
-
if (typeof event.answer === "string") {
|
|
1962
|
-
fallback.answer = event.answer;
|
|
1963
|
-
}
|
|
1964
|
-
}
|
|
1965
|
-
}
|
|
1966
|
-
}
|
|
1967
|
-
|
|
1968
|
-
if (fallback.answer || fallback.conversation_id) {
|
|
1969
|
-
return fallback;
|
|
1970
|
-
}
|
|
1971
|
-
return undefined;
|
|
1972
|
-
};
|
|
1973
|
-
|
|
1974
|
-
const parseAgentPayload = (raw: string): AgentChatResponse | undefined => {
|
|
1975
|
-
if (!raw.trim()) {
|
|
1976
|
-
return undefined;
|
|
1977
|
-
}
|
|
1978
|
-
if (typeof parsedJson !== "object" || parsedJson === null) {
|
|
1979
|
-
return undefined;
|
|
1980
|
-
}
|
|
1981
|
-
|
|
1982
|
-
const payload = parsedJson as Record<string, unknown>;
|
|
1983
|
-
const answer = typeof payload.answer === "string" ? payload.answer : "";
|
|
1984
|
-
const conversationId =
|
|
1985
|
-
typeof payload.answer === "string" && typeof payload.conversation_id === "string"
|
|
1986
|
-
? payload.conversation_id
|
|
1987
|
-
: typeof payload.conversation_id === "string"
|
|
1988
|
-
? payload.conversation_id
|
|
1989
|
-
: "";
|
|
1990
|
-
|
|
1991
|
-
if (!answer && !conversationId && typeof payload.detail !== "string") {
|
|
1992
|
-
return undefined;
|
|
1993
|
-
}
|
|
1994
|
-
|
|
1995
|
-
return {
|
|
1996
|
-
answer,
|
|
1997
|
-
conversation_id: conversationId,
|
|
1998
|
-
...(typeof payload.tool_calls_made === "number"
|
|
1999
|
-
? { tool_calls_made: payload.tool_calls_made }
|
|
2000
|
-
: {}),
|
|
2001
|
-
};
|
|
2002
|
-
};
|
|
2003
|
-
|
|
2004
|
-
const parsedResponse = parseAgentStream(text);
|
|
2005
|
-
|
|
2006
|
-
if (!res.ok) {
|
|
2007
|
-
const rawError = parsedJson ? JSON.stringify(parsedJson) : text || `HTTP ${res.status}`;
|
|
2008
|
-
const extractedError = extractErrorMessage(parsedJson) || text || `HTTP ${res.status}`;
|
|
2009
|
-
if (isAuthError(res.status, rawError)) {
|
|
2010
|
-
return {
|
|
2011
|
-
ok: false,
|
|
2012
|
-
status: res.status,
|
|
2013
|
-
error: formatAuthError(extractedError),
|
|
2014
|
-
};
|
|
2015
|
-
}
|
|
2016
|
-
return {
|
|
2017
|
-
ok: false,
|
|
2018
|
-
status: res.status,
|
|
2019
|
-
error: extractedError,
|
|
2020
|
-
};
|
|
2021
|
-
}
|
|
2022
|
-
|
|
2023
|
-
if (parsedResponse) {
|
|
2024
|
-
return { ok: true, status: res.status, data: parsedResponse };
|
|
2025
|
-
}
|
|
2026
|
-
|
|
2027
|
-
return {
|
|
2028
|
-
ok: true,
|
|
2029
|
-
status: res.status,
|
|
2030
|
-
data: {
|
|
2031
|
-
answer: text || "",
|
|
2032
|
-
conversation_id: "",
|
|
2033
|
-
},
|
|
2034
|
-
};
|
|
2035
|
-
} catch (err) {
|
|
2036
|
-
return {
|
|
2037
|
-
ok: false,
|
|
2038
|
-
status: 0,
|
|
2039
|
-
error: err instanceof Error ? err.message : String(err),
|
|
2040
|
-
};
|
|
2041
|
-
}
|
|
2042
|
-
}
|
|
2043
|
-
|
|
2044
|
-
// Agent session persistence APIs (Pioneer MLE agent)
|
|
2045
|
-
export async function createAgentSession(
|
|
2046
|
-
req: CreateChatSessionRequest
|
|
2047
|
-
): Promise<ApiResult<ChatSessionResponse>> {
|
|
2048
|
-
return request<ChatSessionResponse>("POST", "/mle-agent/sessions", req);
|
|
2049
|
-
}
|
|
2050
|
-
|
|
2051
|
-
export async function getAgentSession(
|
|
2052
|
-
sessionId: string
|
|
2053
|
-
): Promise<ApiResult<ChatSessionResponse>> {
|
|
2054
|
-
return request<ChatSessionResponse>("GET", `/mle-agent/sessions/${sessionId}`);
|
|
2055
|
-
}
|
|
2056
|
-
|
|
2057
|
-
export async function listAgentSessions(): Promise<ApiResult<ChatSessionListResponse>> {
|
|
2058
|
-
return request<ChatSessionListResponse>("GET", "/mle-agent/sessions");
|
|
2059
|
-
}
|
|
2060
|
-
|
|
2061
|
-
export async function appendSessionMessages(
|
|
2062
|
-
sessionId: string,
|
|
2063
|
-
req: AppendSessionMessagesRequest
|
|
2064
|
-
): Promise<ApiResult<{ success: boolean; session_id: string; messages_added: number }>> {
|
|
2065
|
-
return request<{ success: boolean; session_id: string; messages_added: number }>(
|
|
2066
|
-
"POST",
|
|
2067
|
-
`/mle-agent/sessions/${sessionId}/messages`,
|
|
2068
|
-
req
|
|
2069
|
-
);
|
|
2070
|
-
}
|
|
2071
|
-
|
|
2072
|
-
export async function updateAgentSession(
|
|
2073
|
-
sessionId: string,
|
|
2074
|
-
req: UpdateChatSessionRequest
|
|
2075
|
-
): Promise<ApiResult<ChatSessionResponse>> {
|
|
2076
|
-
return request<ChatSessionResponse>("PATCH", `/mle-agent/sessions/${sessionId}`, req);
|
|
2077
|
-
}
|
|
2078
|
-
|
|
2079
|
-
export async function deleteAgentSession(sessionId: string): Promise<ApiResult<{ success: boolean }>> {
|
|
2080
|
-
return request<{ success: boolean }>("DELETE", `/mle-agent/sessions/${sessionId}`);
|
|
2081
|
-
}
|
|
2082
|
-
|
|
2083
|
-
export async function listAutoAgentRuns(
|
|
2084
|
-
limit = 20,
|
|
2085
|
-
offset = 0
|
|
2086
|
-
): Promise<ApiResult<{ runs: AutoAgentRun[] }>> {
|
|
2087
|
-
return request<{ runs: AutoAgentRun[] }>(
|
|
2088
|
-
"GET",
|
|
2089
|
-
`/auto-agent/runs?limit=${limit}&offset=${offset}`
|
|
2090
|
-
);
|
|
2091
|
-
}
|
|
2092
|
-
|
|
2093
|
-
export async function getAutoAgentRun(
|
|
2094
|
-
runId: string
|
|
2095
|
-
): Promise<ApiResult<AutoAgentRun>> {
|
|
2096
|
-
return request<AutoAgentRun>("GET", `/auto-agent/run/${runId}`);
|
|
2097
|
-
}
|
|
2098
|
-
|
|
2099
|
-
export async function stopAutoAgentRun(
|
|
2100
|
-
runId: string
|
|
2101
|
-
): Promise<ApiResult<{ success: boolean }>> {
|
|
2102
|
-
return request<{ success: boolean }>("POST", `/auto-agent/run/${runId}/stop`);
|
|
2103
|
-
}
|
|
2104
|
-
|
|
2105
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
2106
|
-
// Decoder Generation
|
|
2107
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
2108
|
-
|
|
2109
|
-
export interface GenerateDecoderRequest {
|
|
2110
|
-
domain_description: string;
|
|
2111
|
-
instruction?: string;
|
|
2112
|
-
num_examples?: number;
|
|
2113
|
-
temperature?: number;
|
|
2114
|
-
generation_profile?: "auto" | "fast" | "balanced" | "quality";
|
|
2115
|
-
quality?: "light" | "medium" | "heavy";
|
|
2116
|
-
include_reasoning_trace?: boolean;
|
|
2117
|
-
reasoning_effort?: "low" | "medium" | "high";
|
|
2118
|
-
constraints?: ConstraintRequest[];
|
|
2119
|
-
save_dataset?: boolean;
|
|
2120
|
-
dataset_name?: string;
|
|
2121
|
-
project_id?: string;
|
|
2122
|
-
use_meta_felix?: boolean;
|
|
2123
|
-
session_id?: string;
|
|
2124
|
-
config_num_examples?: number;
|
|
2125
|
-
min_criteria?: number;
|
|
2126
|
-
target_choices?: number;
|
|
2127
|
-
split_ratio?: Record<string, number>;
|
|
2128
|
-
negative_ratio?: number;
|
|
2129
|
-
multiplicator?: Record<string, unknown>;
|
|
2130
|
-
type?: "training" | "evaluation" | "split";
|
|
2131
|
-
visibility?: "private" | "public";
|
|
2132
|
-
}
|
|
2133
|
-
|
|
2134
|
-
export async function generateDecoder(
|
|
2135
|
-
req: GenerateDecoderRequest
|
|
2136
|
-
): Promise<ApiResult<GenerateJobStatus>> {
|
|
2137
|
-
return generateDataset({
|
|
2138
|
-
task_type: "decoder",
|
|
2139
|
-
dataset_name: req.dataset_name ?? makeDefaultDatasetName("decoder"),
|
|
2140
|
-
domain_description: req.domain_description,
|
|
2141
|
-
instruction: req.instruction,
|
|
2142
|
-
num_examples: req.num_examples,
|
|
2143
|
-
temperature: req.temperature,
|
|
2144
|
-
generation_profile: req.generation_profile,
|
|
2145
|
-
quality: req.quality,
|
|
2146
|
-
constraints: req.constraints,
|
|
2147
|
-
project_id: req.project_id,
|
|
2148
|
-
include_reasoning_trace: req.include_reasoning_trace,
|
|
2149
|
-
reasoning_effort: req.reasoning_effort,
|
|
2150
|
-
use_meta_felix: req.use_meta_felix,
|
|
2151
|
-
session_id: req.session_id,
|
|
2152
|
-
config_num_examples: req.config_num_examples,
|
|
2153
|
-
min_criteria: req.min_criteria,
|
|
2154
|
-
target_choices: req.target_choices,
|
|
2155
|
-
split_ratio: req.split_ratio,
|
|
2156
|
-
negative_ratio: req.negative_ratio,
|
|
2157
|
-
multiplicator: req.multiplicator,
|
|
2158
|
-
type: req.type,
|
|
2159
|
-
visibility: req.visibility,
|
|
2160
|
-
});
|
|
2161
|
-
}
|
|
2162
|
-
|
|
2163
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
2164
|
-
// Evaluations
|
|
2165
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
2166
|
-
|
|
2167
|
-
export interface BaselineModel {
|
|
2168
|
-
id: string;
|
|
2169
|
-
name: string;
|
|
2170
|
-
provider: string;
|
|
2171
|
-
description: string;
|
|
2172
|
-
}
|
|
2173
|
-
|
|
2174
|
-
export interface BaselineModelsResponse {
|
|
2175
|
-
success: boolean;
|
|
2176
|
-
models: BaselineModel[];
|
|
2177
|
-
count: number;
|
|
2178
|
-
}
|
|
2179
|
-
|
|
2180
|
-
export async function listBaselineModels(): Promise<ApiResult<BaselineModelsResponse>> {
|
|
2181
|
-
return request<BaselineModelsResponse>("GET", "/felix/baseline-models");
|
|
2182
|
-
}
|
|
2183
|
-
|
|
2184
|
-
export interface Evaluation {
|
|
2185
|
-
id: string;
|
|
2186
|
-
user_id: string;
|
|
2187
|
-
project_id?: string;
|
|
2188
|
-
model_id: string;
|
|
2189
|
-
dataset_name: string;
|
|
2190
|
-
dataset_version: string;
|
|
2191
|
-
provider?: string;
|
|
2192
|
-
model_name?: string;
|
|
2193
|
-
f1_score?: number;
|
|
2194
|
-
precision_score?: number;
|
|
2195
|
-
recall_score?: number;
|
|
2196
|
-
accuracy?: number;
|
|
2197
|
-
validation_loss?: number;
|
|
2198
|
-
total_tokens?: number;
|
|
2199
|
-
total_cost_usd?: number;
|
|
2200
|
-
total_latency_ms?: number;
|
|
2201
|
-
max_examples?: number;
|
|
2202
|
-
seed?: number;
|
|
2203
|
-
sample_count?: number;
|
|
2204
|
-
evaluation_time_ms?: number;
|
|
2205
|
-
status: string;
|
|
2206
|
-
job_reference?: string;
|
|
2207
|
-
error_message?: string;
|
|
2208
|
-
created_at: string;
|
|
2209
|
-
completed_at?: string;
|
|
2210
|
-
}
|
|
2211
|
-
|
|
2212
|
-
export interface EvaluationListResponse {
|
|
2213
|
-
success: boolean;
|
|
2214
|
-
evaluations: Evaluation[];
|
|
2215
|
-
count: number;
|
|
2216
|
-
}
|
|
2217
|
-
|
|
2218
|
-
export async function listEvaluations(): Promise<
|
|
2219
|
-
ApiResult<EvaluationListResponse>
|
|
2220
|
-
> {
|
|
2221
|
-
return request<EvaluationListResponse>("GET", "/felix/evaluations");
|
|
2222
|
-
}
|
|
2223
|
-
|
|
2224
|
-
export async function getEvaluation(
|
|
2225
|
-
evalId: string
|
|
2226
|
-
): Promise<ApiResult<Evaluation>> {
|
|
2227
|
-
return request<Evaluation>("GET", `/felix/evaluations/${evalId}`);
|
|
2228
|
-
}
|
|
2229
|
-
|
|
2230
|
-
export interface EvaluationCreateRequest {
|
|
2231
|
-
dataset: DatasetRef;
|
|
2232
|
-
model_id: string;
|
|
2233
|
-
base_model?: string;
|
|
2234
|
-
comparison_models?: string[];
|
|
2235
|
-
dataset_names?: string[];
|
|
2236
|
-
provider?: "felix" | "openai" | "together";
|
|
2237
|
-
max_examples?: number;
|
|
2238
|
-
seed?: number;
|
|
2239
|
-
task_type?: string;
|
|
2240
|
-
text_column?: string;
|
|
2241
|
-
label_column?: string;
|
|
2242
|
-
project_id?: string;
|
|
2243
|
-
}
|
|
2244
|
-
|
|
2245
|
-
export interface EvaluationCreateResponse {
|
|
2246
|
-
success: boolean;
|
|
2247
|
-
evaluations: Evaluation[];
|
|
2248
|
-
count: number;
|
|
2249
|
-
}
|
|
2250
|
-
|
|
2251
|
-
export async function createEvaluation(
|
|
2252
|
-
req: EvaluationCreateRequest
|
|
2253
|
-
): Promise<ApiResult<EvaluationCreateResponse>> {
|
|
2254
|
-
const { dataset, ...rest } = req;
|
|
2255
|
-
const baseModel = req.base_model ?? req.model_id;
|
|
2256
|
-
return request<EvaluationCreateResponse>("POST", "/felix/evaluations", {
|
|
2257
|
-
...rest,
|
|
2258
|
-
base_model: baseModel,
|
|
2259
|
-
dataset_name: dataset.name,
|
|
2260
|
-
dataset_version: dataset.version,
|
|
2261
|
-
});
|
|
2262
|
-
}
|
|
2263
|
-
|
|
2264
|
-
export interface ModelWithEvaluation {
|
|
2265
|
-
model_id: string;
|
|
2266
|
-
model_name: string;
|
|
2267
|
-
is_base_model: boolean;
|
|
2268
|
-
evaluation?: Evaluation;
|
|
2269
|
-
}
|
|
2270
|
-
|
|
2271
|
-
export interface DatasetEvaluationsResponse {
|
|
2272
|
-
success: boolean;
|
|
2273
|
-
dataset_name: string;
|
|
2274
|
-
dataset_version: string;
|
|
2275
|
-
sample_count: number;
|
|
2276
|
-
models: ModelWithEvaluation[];
|
|
2277
|
-
count: number;
|
|
2278
|
-
}
|
|
2279
|
-
|
|
2280
|
-
export async function getDatasetEvaluations(
|
|
2281
|
-
dataset: DatasetRef
|
|
2282
|
-
): Promise<ApiResult<DatasetEvaluationsResponse>> {
|
|
2283
|
-
return request<DatasetEvaluationsResponse>(
|
|
2284
|
-
"GET",
|
|
2285
|
-
`/felix/datasets/${dataset.name}/${dataset.version}/evaluations`
|
|
2286
|
-
);
|
|
2287
|
-
}
|
|
2288
|
-
|
|
2289
|
-
export interface DeleteEvaluationResponse {
|
|
2290
|
-
success: boolean;
|
|
2291
|
-
message: string;
|
|
2292
|
-
}
|
|
2293
|
-
|
|
2294
|
-
export async function deleteEvaluation(
|
|
2295
|
-
evaluationId: string
|
|
2296
|
-
): Promise<ApiResult<DeleteEvaluationResponse>> {
|
|
2297
|
-
return request<DeleteEvaluationResponse>("DELETE", `/felix/evaluations/${evaluationId}`);
|
|
2298
|
-
}
|
|
2299
|
-
|
|
2300
|
-
export interface UpdateEvaluationProjectRequest {
|
|
2301
|
-
evaluation_id: string;
|
|
2302
|
-
project_id?: string;
|
|
2303
|
-
}
|
|
2304
|
-
|
|
2305
|
-
export interface UpdateEvaluationProjectResponse {
|
|
2306
|
-
success: boolean;
|
|
2307
|
-
message: string;
|
|
2308
|
-
}
|
|
2309
|
-
|
|
2310
|
-
export async function updateEvaluationProject(
|
|
2311
|
-
req: UpdateEvaluationProjectRequest
|
|
2312
|
-
): Promise<ApiResult<UpdateEvaluationProjectResponse>> {
|
|
2313
|
-
return request<UpdateEvaluationProjectResponse>(
|
|
2314
|
-
"PATCH",
|
|
2315
|
-
`/felix/evaluations/${req.evaluation_id}/project`,
|
|
2316
|
-
{ project_id: req.project_id }
|
|
2317
|
-
);
|
|
2318
|
-
}
|
|
2319
|
-
|
|
2320
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
2321
|
-
// Benchmarks
|
|
2322
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
2323
|
-
|
|
2324
|
-
export interface BenchmarkInfo {
|
|
2325
|
-
name: string;
|
|
2326
|
-
description: string;
|
|
2327
|
-
task: string;
|
|
2328
|
-
dataset_source?: string;
|
|
2329
|
-
metrics: string[];
|
|
2330
|
-
}
|
|
2331
|
-
|
|
2332
|
-
export interface ListBenchmarksResponse {
|
|
2333
|
-
success: boolean;
|
|
2334
|
-
benchmarks: Record<string, BenchmarkInfo[]>;
|
|
2335
|
-
count: number;
|
|
2336
|
-
}
|
|
2337
|
-
|
|
2338
|
-
export async function listBenchmarks(): Promise<ApiResult<ListBenchmarksResponse>> {
|
|
2339
|
-
return request<ListBenchmarksResponse>("GET", "/felix/benchmarks");
|
|
2340
|
-
}
|
|
2341
|
-
|
|
2342
|
-
export interface BenchmarkEvaluationRequest {
|
|
2343
|
-
model_id: string;
|
|
2344
|
-
task: "ner" | "text_classification";
|
|
2345
|
-
benchmark: string;
|
|
2346
|
-
max_samples?: number;
|
|
2347
|
-
split?: string;
|
|
2348
|
-
benchmark_config?: Record<string, unknown>;
|
|
2349
|
-
}
|
|
2350
|
-
|
|
2351
|
-
export interface BenchmarkEvaluationResponse {
|
|
2352
|
-
success: boolean;
|
|
2353
|
-
evaluation_id: string;
|
|
2354
|
-
status: "pending" | "running" | "complete" | "errored";
|
|
2355
|
-
task: string;
|
|
2356
|
-
benchmark: string;
|
|
2357
|
-
model_id: string;
|
|
2358
|
-
metrics?: Record<string, unknown>;
|
|
2359
|
-
error_message?: string;
|
|
2360
|
-
created_at: string;
|
|
2361
|
-
completed_at?: string;
|
|
2362
|
-
}
|
|
2363
|
-
|
|
2364
|
-
export async function startBenchmarkEvaluation(
|
|
2365
|
-
req: BenchmarkEvaluationRequest
|
|
2366
|
-
): Promise<ApiResult<BenchmarkEvaluationResponse>> {
|
|
2367
|
-
return request<BenchmarkEvaluationResponse>("POST", "/felix/benchmarks/evaluate", req);
|
|
2368
|
-
}
|
|
2369
|
-
|
|
2370
|
-
export async function getBenchmarkEvaluation(
|
|
2371
|
-
evaluationId: string
|
|
2372
|
-
): Promise<ApiResult<BenchmarkEvaluationResponse>> {
|
|
2373
|
-
return request<BenchmarkEvaluationResponse>(
|
|
2374
|
-
"GET",
|
|
2375
|
-
`/felix/benchmarks/evaluate/${evaluationId}`
|
|
2376
|
-
);
|
|
2377
|
-
}
|
|
2378
|
-
|
|
2379
|
-
export async function cancelBenchmarkEvaluation(
|
|
2380
|
-
evaluationId: string
|
|
2381
|
-
): Promise<ApiResult<{ success: boolean; message: string }>> {
|
|
2382
|
-
return request<{ success: boolean; message: string }>(
|
|
2383
|
-
"POST",
|
|
2384
|
-
`/felix/benchmarks/evaluate/${evaluationId}/cancel`
|
|
2385
|
-
);
|
|
2386
|
-
}
|
|
2387
|
-
|
|
2388
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
2389
|
-
// Data Editing (operates on persisted datasets)
|
|
2390
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
2391
|
-
|
|
2392
|
-
export interface PIIFinding {
|
|
2393
|
-
row_index: number;
|
|
2394
|
-
column: string;
|
|
2395
|
-
entity_type: string;
|
|
2396
|
-
text: string;
|
|
2397
|
-
start: number;
|
|
2398
|
-
end: number;
|
|
2399
|
-
score: number;
|
|
2400
|
-
}
|
|
2401
|
-
|
|
2402
|
-
export interface DataEditingScanRequest {
|
|
2403
|
-
dataset: DatasetRef;
|
|
2404
|
-
columns?: string[];
|
|
2405
|
-
threshold?: number;
|
|
2406
|
-
}
|
|
2407
|
-
|
|
2408
|
-
export interface DataEditingScanResponse {
|
|
2409
|
-
success: boolean;
|
|
2410
|
-
dataset_id: string;
|
|
2411
|
-
scan_type: "pii" | "phd";
|
|
2412
|
-
findings_count: number;
|
|
2413
|
-
affected_rows: number;
|
|
2414
|
-
findings: PIIFinding[];
|
|
2415
|
-
}
|
|
2416
|
-
|
|
2417
|
-
export async function scanForPII(
|
|
2418
|
-
req: DataEditingScanRequest
|
|
2419
|
-
): Promise<ApiResult<DataEditingScanResponse>> {
|
|
2420
|
-
const { dataset, ...rest } = req;
|
|
2421
|
-
return request<DataEditingScanResponse>("POST", "/felix/data-editing/scan-pii", {
|
|
2422
|
-
...rest,
|
|
2423
|
-
dataset_name: dataset.name,
|
|
2424
|
-
dataset_version: dataset.version,
|
|
2425
|
-
});
|
|
2426
|
-
}
|
|
2427
|
-
|
|
2428
|
-
export async function scanForPHD(
|
|
2429
|
-
req: DataEditingScanRequest
|
|
2430
|
-
): Promise<ApiResult<DataEditingScanResponse>> {
|
|
2431
|
-
const { dataset, ...rest } = req;
|
|
2432
|
-
return request<DataEditingScanResponse>("POST", "/felix/data-editing/scan-phd", {
|
|
2433
|
-
...rest,
|
|
2434
|
-
dataset_name: dataset.name,
|
|
2435
|
-
dataset_version: dataset.version,
|
|
2436
|
-
});
|
|
2437
|
-
}
|
|
2438
|
-
|
|
2439
|
-
export interface DataEditingDismissOutlierRequest {
|
|
2440
|
-
dataset: DatasetRef;
|
|
2441
|
-
fingerprint: string;
|
|
2442
|
-
}
|
|
2443
|
-
|
|
2444
|
-
export interface DataEditingDismissOutlierResponse {
|
|
2445
|
-
success: boolean;
|
|
2446
|
-
}
|
|
2447
|
-
|
|
2448
|
-
export async function dismissOutlier(
|
|
2449
|
-
req: DataEditingDismissOutlierRequest
|
|
2450
|
-
): Promise<ApiResult<DataEditingDismissOutlierResponse>> {
|
|
2451
|
-
const { dataset, ...rest } = req;
|
|
2452
|
-
return request<DataEditingDismissOutlierResponse>("POST", "/felix/dataset/outliers/dismiss", {
|
|
2453
|
-
...rest,
|
|
2454
|
-
dataset_name: dataset.name,
|
|
2455
|
-
dataset_version: dataset.version,
|
|
2456
|
-
});
|
|
2457
|
-
}
|
|
2458
|
-
|
|
2459
|
-
export interface DataEditingRemoveRequest {
|
|
2460
|
-
dataset: DatasetRef;
|
|
2461
|
-
findings: PIIFinding[];
|
|
2462
|
-
redaction_method?: "redact" | "remove_row" | "mask";
|
|
2463
|
-
save_as_new?: boolean;
|
|
2464
|
-
}
|
|
2465
|
-
|
|
2466
|
-
export interface DataEditingRemoveResponse {
|
|
2467
|
-
success: boolean;
|
|
2468
|
-
dataset_id: string;
|
|
2469
|
-
new_dataset_id?: string;
|
|
2470
|
-
rows_affected: number;
|
|
2471
|
-
entities_removed: number;
|
|
2472
|
-
message: string;
|
|
2473
|
-
}
|
|
2474
|
-
|
|
2475
|
-
export async function removePII(
|
|
2476
|
-
req: DataEditingRemoveRequest
|
|
2477
|
-
): Promise<ApiResult<DataEditingRemoveResponse>> {
|
|
2478
|
-
const { dataset, ...rest } = req;
|
|
2479
|
-
return request<DataEditingRemoveResponse>("POST", "/felix/data-editing/remove-pii", {
|
|
2480
|
-
...rest,
|
|
2481
|
-
dataset_name: dataset.name,
|
|
2482
|
-
dataset_version: dataset.version,
|
|
2483
|
-
});
|
|
2484
|
-
}
|
|
2485
|
-
|
|
2486
|
-
export interface DataEditingSubsampleRequest {
|
|
2487
|
-
dataset: DatasetRef;
|
|
2488
|
-
method?: "random" | "balanced" | "stratified";
|
|
2489
|
-
n: number;
|
|
2490
|
-
label_column?: string;
|
|
2491
|
-
seed?: number;
|
|
2492
|
-
save_as_new?: boolean;
|
|
2493
|
-
}
|
|
2494
|
-
|
|
2495
|
-
export interface DataEditingSubsampleResponse {
|
|
2496
|
-
success: boolean;
|
|
2497
|
-
dataset_id: string;
|
|
2498
|
-
new_dataset_id: string;
|
|
2499
|
-
original_rows: number;
|
|
2500
|
-
new_rows: number;
|
|
2501
|
-
method: string;
|
|
2502
|
-
message: string;
|
|
2503
|
-
}
|
|
2504
|
-
|
|
2505
|
-
export async function subsampleDataset(
|
|
2506
|
-
req: DataEditingSubsampleRequest
|
|
2507
|
-
): Promise<ApiResult<DataEditingSubsampleResponse>> {
|
|
2508
|
-
const { dataset, ...rest } = req;
|
|
2509
|
-
return request<DataEditingSubsampleResponse>("POST", "/felix/data-editing/subsample", {
|
|
2510
|
-
...rest,
|
|
2511
|
-
dataset_name: dataset.name,
|
|
2512
|
-
dataset_version: dataset.version,
|
|
2513
|
-
});
|
|
2514
|
-
}
|
|
2515
|
-
|
|
2516
|
-
export interface DataEditingCheckLabelsRequest {
|
|
2517
|
-
dataset: DatasetRef;
|
|
2518
|
-
text_column: string;
|
|
2519
|
-
label_column: string;
|
|
2520
|
-
sample_size?: number;
|
|
2521
|
-
}
|
|
2522
|
-
|
|
2523
|
-
export interface LabelCheckResult {
|
|
2524
|
-
row_index: number;
|
|
2525
|
-
text: string;
|
|
2526
|
-
current_label: string;
|
|
2527
|
-
suggested_label: string;
|
|
2528
|
-
confidence: number;
|
|
2529
|
-
reasoning: string;
|
|
2530
|
-
}
|
|
2531
|
-
|
|
2532
|
-
export interface DataEditingCheckLabelsResponse {
|
|
2533
|
-
success: boolean;
|
|
2534
|
-
dataset_id: string;
|
|
2535
|
-
checked_count: number;
|
|
2536
|
-
issues_found: number;
|
|
2537
|
-
results: LabelCheckResult[];
|
|
2538
|
-
}
|
|
2539
|
-
|
|
2540
|
-
export async function checkLabels(
|
|
2541
|
-
req: DataEditingCheckLabelsRequest
|
|
2542
|
-
): Promise<ApiResult<DataEditingCheckLabelsResponse>> {
|
|
2543
|
-
const { dataset, ...rest } = req;
|
|
2544
|
-
return request<DataEditingCheckLabelsResponse>("POST", "/felix/data-editing/check-labels", {
|
|
2545
|
-
...rest,
|
|
2546
|
-
dataset_name: dataset.name,
|
|
2547
|
-
dataset_version: dataset.version,
|
|
2548
|
-
});
|
|
2549
|
-
}
|
|
2550
|
-
|
|
2551
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
2552
|
-
// Hugging Face Integration
|
|
2553
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
2554
|
-
|
|
2555
|
-
export interface HuggingFacePushRequest {
|
|
2556
|
-
hf_token: string;
|
|
2557
|
-
repo_id: string;
|
|
2558
|
-
private?: boolean;
|
|
2559
|
-
commit_message?: string;
|
|
2560
|
-
}
|
|
2561
|
-
|
|
2562
|
-
export interface HuggingFacePushResponse {
|
|
2563
|
-
success: boolean;
|
|
2564
|
-
url: string;
|
|
2565
|
-
repo_id: string;
|
|
2566
|
-
version: string;
|
|
2567
|
-
message: string;
|
|
2568
|
-
}
|
|
2569
|
-
|
|
2570
|
-
export async function pushDatasetToHub(
|
|
2571
|
-
dataset: DatasetRef,
|
|
2572
|
-
options: HuggingFacePushRequest
|
|
2573
|
-
): Promise<ApiResult<HuggingFacePushResponse>> {
|
|
2574
|
-
return request<HuggingFacePushResponse>(
|
|
2575
|
-
"POST",
|
|
2576
|
-
`/felix/datasets/${dataset.name}/${dataset.version}/push-to-hub`,
|
|
2577
|
-
options
|
|
2578
|
-
);
|
|
2579
|
-
}
|
|
2580
|
-
|
|
2581
|
-
export interface HuggingFacePushModelRequest {
|
|
2582
|
-
hf_token: string;
|
|
2583
|
-
repo_id: string;
|
|
2584
|
-
private?: boolean;
|
|
2585
|
-
commit_message?: string;
|
|
2586
|
-
}
|
|
2587
|
-
|
|
2588
|
-
export interface HuggingFacePushModelResponse {
|
|
2589
|
-
success: boolean;
|
|
2590
|
-
url: string;
|
|
2591
|
-
repo_id: string;
|
|
2592
|
-
job_id: string;
|
|
2593
|
-
message: string;
|
|
2594
|
-
}
|
|
2595
|
-
|
|
2596
|
-
export async function pushModelToHub(
|
|
2597
|
-
jobId: string,
|
|
2598
|
-
options: HuggingFacePushModelRequest
|
|
2599
|
-
): Promise<ApiResult<HuggingFacePushModelResponse>> {
|
|
2600
|
-
return request<HuggingFacePushModelResponse>(
|
|
2601
|
-
"POST",
|
|
2602
|
-
`/felix/training-jobs/${jobId}/push-to-hub`,
|
|
2603
|
-
options
|
|
2604
|
-
);
|
|
2605
|
-
}
|
|
2606
|
-
|
|
2607
|
-
export interface HuggingFacePullRequest {
|
|
2608
|
-
repo_id: string;
|
|
2609
|
-
hf_token: string;
|
|
2610
|
-
revision?: string;
|
|
2611
|
-
name?: string;
|
|
2612
|
-
}
|
|
2613
|
-
|
|
2614
|
-
export async function pullDatasetFromHub(
|
|
2615
|
-
options: HuggingFacePullRequest
|
|
2616
|
-
): Promise<ApiResult<Dataset>> {
|
|
2617
|
-
return request<Dataset>(
|
|
2618
|
-
"POST",
|
|
2619
|
-
"/felix/datasets/pull-from-hub",
|
|
2620
|
-
options
|
|
2621
|
-
);
|
|
2622
|
-
}
|
|
2623
|
-
|
|
2624
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
2625
|
-
// Constraints Generation
|
|
2626
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
2627
|
-
|
|
2628
|
-
export interface GenerateNERConstraintsRequest {
|
|
2629
|
-
labels: string[];
|
|
2630
|
-
domain_description?: string;
|
|
2631
|
-
min_criteria?: number;
|
|
2632
|
-
}
|
|
2633
|
-
|
|
2634
|
-
export interface GenerateClassificationConstraintsRequest {
|
|
2635
|
-
labels: string[];
|
|
2636
|
-
domain_description?: string;
|
|
2637
|
-
min_criteria?: number;
|
|
2638
|
-
}
|
|
2639
|
-
|
|
2640
|
-
export interface GenerateRecordsConstraintsRequest {
|
|
2641
|
-
fields: RecordField[];
|
|
2642
|
-
domain_description?: string;
|
|
2643
|
-
min_criteria?: number;
|
|
2644
|
-
}
|
|
2645
|
-
|
|
2646
|
-
export interface GenerateConstraintsResponse {
|
|
2647
|
-
success: boolean;
|
|
2648
|
-
constraints: ConstraintRequest[];
|
|
2649
|
-
count: number;
|
|
2650
|
-
token_usage?: number;
|
|
2651
|
-
}
|
|
2652
|
-
|
|
2653
|
-
export async function generateNERConstraints(
|
|
2654
|
-
req: GenerateNERConstraintsRequest
|
|
2655
|
-
): Promise<ApiResult<GenerateConstraintsResponse>> {
|
|
2656
|
-
return request<GenerateConstraintsResponse>(
|
|
2657
|
-
"POST",
|
|
2658
|
-
"/felix/constraints/ner",
|
|
2659
|
-
req
|
|
2660
|
-
);
|
|
2661
|
-
}
|
|
2662
|
-
|
|
2663
|
-
export async function generateClassificationConstraints(
|
|
2664
|
-
req: GenerateClassificationConstraintsRequest
|
|
2665
|
-
): Promise<ApiResult<GenerateConstraintsResponse>> {
|
|
2666
|
-
return request<GenerateConstraintsResponse>(
|
|
2667
|
-
"POST",
|
|
2668
|
-
"/felix/constraints/classification",
|
|
2669
|
-
req
|
|
2670
|
-
);
|
|
2671
|
-
}
|
|
2672
|
-
|
|
2673
|
-
export async function generateRecordsConstraints(
|
|
2674
|
-
req: GenerateRecordsConstraintsRequest
|
|
2675
|
-
): Promise<ApiResult<GenerateConstraintsResponse>> {
|
|
2676
|
-
return request<GenerateConstraintsResponse>(
|
|
2677
|
-
"POST",
|
|
2678
|
-
"/felix/constraints/records",
|
|
2679
|
-
req
|
|
2680
|
-
);
|
|
2681
|
-
}
|
|
2682
|
-
|
|
2683
|
-
export interface ExpandConstraintChoicesRequest {
|
|
2684
|
-
constraint: ConstraintRequest;
|
|
2685
|
-
task_description: string;
|
|
2686
|
-
max_count?: number;
|
|
2687
|
-
}
|
|
2688
|
-
|
|
2689
|
-
export interface ExpandConstraintChoicesResponse {
|
|
2690
|
-
success: boolean;
|
|
2691
|
-
constraint: ConstraintRequest;
|
|
2692
|
-
expanded_choices: string[];
|
|
2693
|
-
count: number;
|
|
2694
|
-
token_usage?: number;
|
|
2695
|
-
}
|
|
2696
|
-
|
|
2697
|
-
export async function expandConstraintChoices(
|
|
2698
|
-
req: ExpandConstraintChoicesRequest
|
|
2699
|
-
): Promise<ApiResult<ExpandConstraintChoicesResponse>> {
|
|
2700
|
-
return request<ExpandConstraintChoicesResponse>(
|
|
2701
|
-
"POST",
|
|
2702
|
-
"/felix/constraints/expand",
|
|
2703
|
-
req
|
|
2704
|
-
);
|
|
2705
|
-
}
|
|
2706
|
-
|
|
2707
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
2708
|
-
// Dataset Augmentation
|
|
2709
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
2710
|
-
|
|
2711
|
-
export interface AugmentationOperation {
|
|
2712
|
-
type: "remove_duplicates" | "remove_outliers" | "balance";
|
|
2713
|
-
enabled: boolean;
|
|
2714
|
-
}
|
|
2715
|
-
|
|
2716
|
-
export interface DatasetAugmentationRequest {
|
|
2717
|
-
task_type: "ner" | "classification";
|
|
2718
|
-
operations: AugmentationOperation[];
|
|
2719
|
-
new_dataset_name: string;
|
|
2720
|
-
dataset_name?: string;
|
|
2721
|
-
dataset_version?: string;
|
|
2722
|
-
dataset?: Record<string, unknown>[];
|
|
2723
|
-
target_distribution?: Record<string, number>;
|
|
2724
|
-
domain_description?: string;
|
|
2725
|
-
labels?: string[];
|
|
2726
|
-
}
|
|
2727
|
-
|
|
2728
|
-
export interface DatasetAugmentationResponse {
|
|
2729
|
-
success: boolean;
|
|
2730
|
-
original_dataset_name?: string;
|
|
2731
|
-
original_dataset_version?: string;
|
|
2732
|
-
new_dataset: Dataset;
|
|
2733
|
-
modifications: Record<string, unknown>;
|
|
2734
|
-
distribution_comparison: Record<string, unknown>[];
|
|
2735
|
-
message: string;
|
|
2736
|
-
}
|
|
2737
|
-
|
|
2738
|
-
export async function augmentDataset(
|
|
2739
|
-
req: DatasetAugmentationRequest
|
|
2740
|
-
): Promise<ApiResult<DatasetAugmentationResponse>> {
|
|
2741
|
-
return request<DatasetAugmentationResponse>(
|
|
2742
|
-
"POST",
|
|
2743
|
-
"/felix/dataset/augment",
|
|
2744
|
-
req
|
|
2745
|
-
);
|
|
2746
|
-
}
|
|
2747
|
-
|
|
2748
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
2749
|
-
// Dataset Query
|
|
2750
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
2751
|
-
|
|
2752
|
-
export interface DatasetQueryRequest {
|
|
2753
|
-
dataset_name: string;
|
|
2754
|
-
code: string;
|
|
2755
|
-
version?: string;
|
|
2756
|
-
timeout?: number;
|
|
2757
|
-
max_rows_returned?: number;
|
|
2758
|
-
}
|
|
2759
|
-
|
|
2760
|
-
export interface DatasetQueryResponse {
|
|
2761
|
-
success: boolean;
|
|
2762
|
-
dataset_name: string;
|
|
2763
|
-
dataset_version: string;
|
|
2764
|
-
result: unknown;
|
|
2765
|
-
result_type: "dataframe" | "series" | "scalar" | "string" | "none";
|
|
2766
|
-
row_count?: number;
|
|
2767
|
-
columns?: string[];
|
|
2768
|
-
execution_time_ms: number;
|
|
2769
|
-
truncated: boolean;
|
|
2770
|
-
message: string;
|
|
2771
|
-
}
|
|
2772
|
-
|
|
2773
|
-
export async function queryDataset(
|
|
2774
|
-
req: DatasetQueryRequest
|
|
2775
|
-
): Promise<ApiResult<DatasetQueryResponse>> {
|
|
2776
|
-
return request<DatasetQueryResponse>("POST", "/felix/dataset/query", req);
|
|
2777
|
-
}
|
|
2778
|
-
|
|
2779
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
2780
|
-
// Dataset Grow
|
|
2781
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
2782
|
-
|
|
2783
|
-
export interface GrowDatasetRequest {
|
|
2784
|
-
dataset_id: string;
|
|
2785
|
-
new_dataset_name: string;
|
|
2786
|
-
target_size: number;
|
|
2787
|
-
class_balance?: boolean;
|
|
2788
|
-
domain_description?: string;
|
|
2789
|
-
temperature?: number;
|
|
2790
|
-
session_id?: string;
|
|
2791
|
-
}
|
|
2792
|
-
|
|
2793
|
-
export interface GrowDatasetResponse {
|
|
2794
|
-
success: boolean;
|
|
2795
|
-
dataset: Record<string, unknown>;
|
|
2796
|
-
original_size: number;
|
|
2797
|
-
new_size: number;
|
|
2798
|
-
generated_count: number;
|
|
2799
|
-
distribution: Record<string, number>;
|
|
2800
|
-
token_usage?: number;
|
|
2801
|
-
}
|
|
2802
|
-
|
|
2803
|
-
export async function growDataset(
|
|
2804
|
-
req: GrowDatasetRequest
|
|
2805
|
-
): Promise<ApiResult<GrowDatasetResponse>> {
|
|
2806
|
-
return request<GrowDatasetResponse>("POST", "/felix/dataset/grow", req);
|
|
2807
|
-
}
|
|
2808
|
-
|
|
2809
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
2810
|
-
// Embeddings
|
|
2811
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
2812
|
-
|
|
2813
|
-
export interface EmbeddingsRequest {
|
|
2814
|
-
text: string;
|
|
2815
|
-
model?: string;
|
|
2816
|
-
}
|
|
2817
|
-
|
|
2818
|
-
export interface EmbeddingsResponse {
|
|
2819
|
-
embedding: number[];
|
|
2820
|
-
}
|
|
2821
|
-
|
|
2822
|
-
export async function createEmbeddings(
|
|
2823
|
-
req: EmbeddingsRequest
|
|
2824
|
-
): Promise<ApiResult<EmbeddingsResponse>> {
|
|
2825
|
-
return request<EmbeddingsResponse>("POST", "/felix/embeddings", req);
|
|
2826
|
-
}
|
|
2827
|
-
|
|
2828
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
2829
|
-
// Activity
|
|
2830
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
2831
|
-
|
|
2832
|
-
export interface ActivityEvent {
|
|
2833
|
-
id: string;
|
|
2834
|
-
type: "project" | "dataset" | "model" | "evaluation" | "notebook" | "deployment";
|
|
2835
|
-
name: string;
|
|
2836
|
-
item_id: string;
|
|
2837
|
-
created_by: string;
|
|
2838
|
-
created_at: string;
|
|
2839
|
-
project_id?: string;
|
|
2840
|
-
}
|
|
2841
|
-
|
|
2842
|
-
export interface ActivityLogResponse {
|
|
2843
|
-
success: boolean;
|
|
2844
|
-
events?: ActivityEvent[];
|
|
2845
|
-
count: number;
|
|
2846
|
-
}
|
|
2847
|
-
|
|
2848
|
-
export async function listActivity(
|
|
2849
|
-
options: { limit?: number } = {}
|
|
2850
|
-
): Promise<ApiResult<ActivityLogResponse>> {
|
|
2851
|
-
const params = new URLSearchParams();
|
|
2852
|
-
if (options.limit) params.set("limit", String(options.limit));
|
|
2853
|
-
const query = params.toString();
|
|
2854
|
-
const url = query ? `/felix/activity?${query}` : "/felix/activity";
|
|
2855
|
-
return request<ActivityLogResponse>("GET", url);
|
|
2856
|
-
}
|
|
2857
|
-
|
|
2858
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
2859
|
-
// Projects
|
|
2860
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
2861
|
-
|
|
2862
|
-
export interface ProjectCreateRequest {
|
|
2863
|
-
name?: string;
|
|
2864
|
-
icon?: string;
|
|
2865
|
-
repo?: string;
|
|
2866
|
-
description?: string;
|
|
2867
|
-
active_model_id?: string;
|
|
2868
|
-
selected_model_id?: string;
|
|
2869
|
-
example?: Record<string, unknown>;
|
|
2870
|
-
}
|
|
2871
|
-
|
|
2872
|
-
export interface ProjectUpdateRequest {
|
|
2873
|
-
name?: string;
|
|
2874
|
-
icon?: string;
|
|
2875
|
-
repo?: string;
|
|
2876
|
-
description?: string;
|
|
2877
|
-
selected_model_id?: string;
|
|
2878
|
-
}
|
|
2879
|
-
|
|
2880
|
-
export interface ProjectResponse {
|
|
2881
|
-
id: string;
|
|
2882
|
-
user_id: string;
|
|
2883
|
-
name: string;
|
|
2884
|
-
icon?: string;
|
|
2885
|
-
repo?: string;
|
|
2886
|
-
description?: string;
|
|
2887
|
-
selected_model_id?: string;
|
|
2888
|
-
example?: Record<string, unknown>;
|
|
2889
|
-
created_at: string;
|
|
2890
|
-
updated_at: string;
|
|
2891
|
-
}
|
|
2892
|
-
|
|
2893
|
-
export interface ProjectListResponse {
|
|
2894
|
-
success: boolean;
|
|
2895
|
-
projects: ProjectResponse[];
|
|
2896
|
-
count: number;
|
|
2897
|
-
}
|
|
2898
|
-
|
|
2899
|
-
export interface ProjectDeleteResponse {
|
|
2900
|
-
success: boolean;
|
|
2901
|
-
message: string;
|
|
2902
|
-
project_id: string;
|
|
2903
|
-
}
|
|
2904
|
-
|
|
2905
|
-
export interface ProjectDeploymentCreate {
|
|
2906
|
-
training_job_id: string;
|
|
2907
|
-
reason?: string;
|
|
2908
|
-
}
|
|
2909
|
-
|
|
2910
|
-
export interface ProjectDeploymentResponse {
|
|
2911
|
-
/** Deployment record id. */
|
|
2912
|
-
id?: string;
|
|
2913
|
-
project_id?: string;
|
|
2914
|
-
/** Set when a fine-tuned checkpoint was deployed. */
|
|
2915
|
-
training_job_id?: string | null;
|
|
2916
|
-
/**
|
|
2917
|
-
* Set to the stock HuggingFace base model id when a base-model deploy was
|
|
2918
|
-
* performed. May also be populated for training-job deploys (post backend
|
|
2919
|
-
* enrichment) so the record always carries "what stock model is serving".
|
|
2920
|
-
*/
|
|
2921
|
-
base_model?: string | null;
|
|
2922
|
-
deployed_by?: string;
|
|
2923
|
-
reason?: string;
|
|
2924
|
-
deployed_at?: string;
|
|
2925
|
-
// Legacy/optional fields kept for older response shapes.
|
|
2926
|
-
success?: boolean;
|
|
2927
|
-
message?: string;
|
|
2928
|
-
deployment_id?: string;
|
|
2929
|
-
}
|
|
2930
|
-
|
|
2931
|
-
export interface ProjectDatasetCountResponse {
|
|
2932
|
-
project_id: string;
|
|
2933
|
-
dataset_count: number;
|
|
2934
|
-
can_delete: boolean;
|
|
2935
|
-
}
|
|
2936
|
-
|
|
2937
|
-
export interface QualityMetricsResponse {
|
|
2938
|
-
project_id: string;
|
|
2939
|
-
pass_count: number;
|
|
2940
|
-
fail_count: number;
|
|
2941
|
-
uncertain_count: number;
|
|
2942
|
-
total_judged: number;
|
|
2943
|
-
pass_rate: number;
|
|
2944
|
-
fail_rate: number;
|
|
2945
|
-
}
|
|
2946
|
-
|
|
2947
|
-
export async function listProjects(): Promise<ApiResult<ProjectListResponse>> {
|
|
2948
|
-
return request<ProjectListResponse>("GET", "/projects");
|
|
2949
|
-
}
|
|
2950
|
-
|
|
2951
|
-
export async function createProject(
|
|
2952
|
-
req: ProjectCreateRequest
|
|
2953
|
-
): Promise<ApiResult<ProjectResponse>> {
|
|
2954
|
-
return request<ProjectResponse>("POST", "/projects", req);
|
|
2955
|
-
}
|
|
2956
|
-
|
|
2957
|
-
export async function getProject(projectId: string): Promise<ApiResult<ProjectResponse>> {
|
|
2958
|
-
return request<ProjectResponse>("GET", `/projects/${projectId}`);
|
|
2959
|
-
}
|
|
2960
|
-
|
|
2961
|
-
export async function updateProject(
|
|
2962
|
-
projectId: string,
|
|
2963
|
-
req: ProjectUpdateRequest
|
|
2964
|
-
): Promise<ApiResult<ProjectResponse>> {
|
|
2965
|
-
return request<ProjectResponse>("PATCH", `/projects/${projectId}`, req);
|
|
2966
|
-
}
|
|
2967
|
-
|
|
2968
|
-
export async function deleteProject(
|
|
2969
|
-
projectId: string
|
|
2970
|
-
): Promise<ApiResult<ProjectDeleteResponse>> {
|
|
2971
|
-
return request<ProjectDeleteResponse>("DELETE", `/projects/${projectId}`);
|
|
2972
|
-
}
|
|
2973
|
-
|
|
2974
|
-
export async function getProjectDatasetCount(
|
|
2975
|
-
projectId: string
|
|
2976
|
-
): Promise<ApiResult<ProjectDatasetCountResponse>> {
|
|
2977
|
-
return request<ProjectDatasetCountResponse>(
|
|
2978
|
-
"GET",
|
|
2979
|
-
`/projects/${projectId}/dataset-count`
|
|
2980
|
-
);
|
|
2981
|
-
}
|
|
2982
|
-
|
|
2983
|
-
export async function getProjectQualityMetrics(
|
|
2984
|
-
projectId: string
|
|
2985
|
-
): Promise<ApiResult<QualityMetricsResponse>> {
|
|
2986
|
-
return request<QualityMetricsResponse>(
|
|
2987
|
-
"GET",
|
|
2988
|
-
`/projects/${projectId}/quality-metrics`
|
|
2989
|
-
);
|
|
2990
|
-
}
|
|
2991
|
-
|
|
2992
|
-
export async function deployTrainingJobToProject(
|
|
2993
|
-
projectId: string,
|
|
2994
|
-
req: ProjectDeploymentCreate
|
|
2995
|
-
): Promise<ApiResult<ProjectDeploymentResponse>> {
|
|
2996
|
-
return request<ProjectDeploymentResponse>(
|
|
2997
|
-
"POST",
|
|
2998
|
-
`/projects/${projectId}/deployments`,
|
|
2999
|
-
req
|
|
3000
|
-
);
|
|
3001
|
-
}
|
|
3002
|
-
|
|
3003
|
-
export async function rollbackProjectDeployment(
|
|
3004
|
-
projectId: string,
|
|
3005
|
-
deploymentId: string
|
|
3006
|
-
): Promise<ApiResult<ProjectDeploymentResponse>> {
|
|
3007
|
-
return request<ProjectDeploymentResponse>(
|
|
3008
|
-
"POST",
|
|
3009
|
-
`/projects/${projectId}/deployments/${deploymentId}/rollback`
|
|
3010
|
-
);
|
|
3011
|
-
}
|
|
3012
|
-
|
|
3013
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
3014
|
-
// Presets
|
|
3015
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
3016
|
-
|
|
3017
|
-
export interface PresetMetadata {
|
|
3018
|
-
id: string;
|
|
3019
|
-
name: string;
|
|
3020
|
-
description: string;
|
|
3021
|
-
task_type: string;
|
|
3022
|
-
tags?: string[];
|
|
3023
|
-
}
|
|
3024
|
-
|
|
3025
|
-
export interface PresetDetail {
|
|
3026
|
-
id: string;
|
|
3027
|
-
name: string;
|
|
3028
|
-
description: string;
|
|
3029
|
-
task_type: string;
|
|
3030
|
-
config: Record<string, unknown>;
|
|
3031
|
-
tags?: string[];
|
|
3032
|
-
}
|
|
3033
|
-
|
|
3034
|
-
export async function listPresets(): Promise<ApiResult<PresetMetadata[]>> {
|
|
3035
|
-
return request<PresetMetadata[]>("GET", "/felix/presets");
|
|
3036
|
-
}
|
|
3037
|
-
|
|
3038
|
-
export async function getPreset(
|
|
3039
|
-
presetId: string
|
|
3040
|
-
): Promise<ApiResult<PresetDetail>> {
|
|
3041
|
-
return request<PresetDetail>("GET", `/felix/presets/${presetId}`);
|
|
3042
|
-
}
|
|
3043
|
-
|
|
3044
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
3045
|
-
// Adaptive Annotation
|
|
3046
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
3047
|
-
|
|
3048
|
-
export interface StartAnnotationSessionRequest {
|
|
3049
|
-
column_name: string;
|
|
3050
|
-
input_columns: string[];
|
|
3051
|
-
task_description: string;
|
|
3052
|
-
task_type?: "classification" | "scoring" | "entity_extraction" | "json_extraction";
|
|
3053
|
-
output_dataset_name?: string;
|
|
3054
|
-
possible_labels?: Array<{ name: string; description?: string }>;
|
|
3055
|
-
scoring_criteria?: Array<Record<string, unknown>>;
|
|
3056
|
-
entity_types?: Array<{ name: string; description?: string }>;
|
|
3057
|
-
json_schema?: Array<Record<string, unknown>>;
|
|
3058
|
-
auto_accept_threshold?: number;
|
|
3059
|
-
}
|
|
3060
|
-
|
|
3061
|
-
export interface StartAnnotationSessionResponse {
|
|
3062
|
-
success: boolean;
|
|
3063
|
-
session_id: string;
|
|
3064
|
-
dataset_id: string;
|
|
3065
|
-
task_type: string;
|
|
3066
|
-
total_items: number;
|
|
3067
|
-
}
|
|
3068
|
-
|
|
3069
|
-
export async function startAnnotationSession(
|
|
3070
|
-
datasetId: string,
|
|
3071
|
-
req: StartAnnotationSessionRequest
|
|
3072
|
-
): Promise<ApiResult<StartAnnotationSessionResponse>> {
|
|
3073
|
-
return request<StartAnnotationSessionResponse>(
|
|
3074
|
-
"POST",
|
|
3075
|
-
`/felix/datasets/annotate/${datasetId}/start`,
|
|
3076
|
-
req
|
|
3077
|
-
);
|
|
3078
|
-
}
|
|
3079
|
-
|
|
3080
|
-
export interface NextAnnotationItemResponse {
|
|
3081
|
-
complete: boolean;
|
|
3082
|
-
rate_limited?: boolean;
|
|
3083
|
-
auto_accepted_in_call?: number;
|
|
3084
|
-
item_id?: number;
|
|
3085
|
-
item_data?: Record<string, unknown>;
|
|
3086
|
-
task_type?: string;
|
|
3087
|
-
task_description?: string;
|
|
3088
|
-
possible_labels?: string[];
|
|
3089
|
-
scoring_criteria?: Array<Record<string, unknown>>;
|
|
3090
|
-
entity_types?: Array<Record<string, unknown>>;
|
|
3091
|
-
json_schema?: Array<Record<string, unknown>>;
|
|
3092
|
-
suggestion?: Record<string, unknown>;
|
|
3093
|
-
stats?: Record<string, unknown>;
|
|
3094
|
-
}
|
|
3095
|
-
|
|
3096
|
-
export async function getNextAnnotationItem(
|
|
3097
|
-
datasetId: string,
|
|
3098
|
-
options: { maxAutoAccept?: number } = {}
|
|
3099
|
-
): Promise<ApiResult<NextAnnotationItemResponse>> {
|
|
3100
|
-
const params = new URLSearchParams();
|
|
3101
|
-
if (options.maxAutoAccept !== undefined) {
|
|
3102
|
-
params.set("max_auto_accept", String(options.maxAutoAccept));
|
|
3103
|
-
}
|
|
3104
|
-
const query = params.toString();
|
|
3105
|
-
const url = `/felix/datasets/annotate/${datasetId}/next${query ? `?${query}` : ""}`;
|
|
3106
|
-
return request<NextAnnotationItemResponse>("GET", url);
|
|
3107
|
-
}
|
|
3108
|
-
|
|
3109
|
-
export interface AnnotationFeedbackRequest {
|
|
3110
|
-
item_id: number;
|
|
3111
|
-
thumb: "up" | "down";
|
|
3112
|
-
corrected_label?: string;
|
|
3113
|
-
corrected_criteria?: Record<string, string>;
|
|
3114
|
-
corrected_entities?: string[][];
|
|
3115
|
-
corrected_json?: Record<string, unknown>;
|
|
3116
|
-
}
|
|
3117
|
-
|
|
3118
|
-
export interface AnnotationFeedbackResponse {
|
|
3119
|
-
success: boolean;
|
|
3120
|
-
item_id: number;
|
|
3121
|
-
action: "up" | "down";
|
|
3122
|
-
was_correct: boolean;
|
|
3123
|
-
similar_items_queued?: number;
|
|
3124
|
-
stats?: Record<string, unknown>;
|
|
3125
|
-
}
|
|
3126
|
-
|
|
3127
|
-
export async function submitAnnotationFeedback(
|
|
3128
|
-
datasetId: string,
|
|
3129
|
-
req: AnnotationFeedbackRequest
|
|
3130
|
-
): Promise<ApiResult<AnnotationFeedbackResponse>> {
|
|
3131
|
-
return request<AnnotationFeedbackResponse>(
|
|
3132
|
-
"POST",
|
|
3133
|
-
`/felix/datasets/annotate/${datasetId}/feedback`,
|
|
3134
|
-
req
|
|
3135
|
-
);
|
|
3136
|
-
}
|
|
3137
|
-
|
|
3138
|
-
export interface AnnotationStatsResponse {
|
|
3139
|
-
total_items: number;
|
|
3140
|
-
annotated: number;
|
|
3141
|
-
remaining: number;
|
|
3142
|
-
auto_accepted: number;
|
|
3143
|
-
human_annotated: number;
|
|
3144
|
-
auto_accept_rate: number;
|
|
3145
|
-
label_stats?: Record<string, unknown>;
|
|
3146
|
-
}
|
|
3147
|
-
|
|
3148
|
-
export async function getAnnotationStats(
|
|
3149
|
-
datasetId: string
|
|
3150
|
-
): Promise<ApiResult<AnnotationStatsResponse>> {
|
|
3151
|
-
return request<AnnotationStatsResponse>(
|
|
3152
|
-
"GET",
|
|
3153
|
-
`/felix/datasets/annotate/${datasetId}/stats`
|
|
3154
|
-
);
|
|
3155
|
-
}
|
|
3156
|
-
|
|
3157
|
-
export interface AnnotationDownloadResponse {
|
|
3158
|
-
data: Record<string, unknown>[];
|
|
3159
|
-
columns: string[];
|
|
3160
|
-
rows: number;
|
|
3161
|
-
stats?: AnnotationStatsResponse;
|
|
3162
|
-
}
|
|
3163
|
-
|
|
3164
|
-
export async function downloadAnnotatedData(
|
|
3165
|
-
datasetId: string
|
|
3166
|
-
): Promise<ApiResult<AnnotationDownloadResponse>> {
|
|
3167
|
-
return request<AnnotationDownloadResponse>(
|
|
3168
|
-
"GET",
|
|
3169
|
-
`/felix/datasets/annotate/${datasetId}/download`
|
|
3170
|
-
);
|
|
3171
|
-
}
|
|
3172
|
-
|
|
3173
|
-
export interface EndAnnotationSessionResponse {
|
|
3174
|
-
success: boolean;
|
|
3175
|
-
message: string;
|
|
3176
|
-
final_stats?: AnnotationStatsResponse;
|
|
3177
|
-
}
|
|
3178
|
-
|
|
3179
|
-
export async function endAnnotationSession(
|
|
3180
|
-
datasetId: string
|
|
3181
|
-
): Promise<ApiResult<EndAnnotationSessionResponse>> {
|
|
3182
|
-
return request<EndAnnotationSessionResponse>(
|
|
3183
|
-
"DELETE",
|
|
3184
|
-
`/felix/datasets/annotate/${datasetId}/session`
|
|
3185
|
-
);
|
|
3186
|
-
}
|
|
3187
|
-
|