ranranrunforit commited on
Commit
6d42820
·
verified ·
1 Parent(s): 78a0227

Upload 33 files

Browse files
Files changed (2) hide show
  1. server.py +17 -7
  2. ui_kits/chan-compass/views.jsx +18 -3
server.py CHANGED
@@ -311,10 +311,16 @@ async def export_dataset():
311
  path = finetune_data.export()
312
  if not path:
313
  return JSONResponse({"path": "", "count": 0, "download": ""})
314
- # copy into a served dir so the browser can download it
 
315
  import shutil
316
- served_dir = os.path.join(HERE, "exports")
317
- os.makedirs(served_dir, exist_ok=True)
 
 
 
 
 
318
  fname = os.path.basename(path)
319
  try:
320
  shutil.copy(path, os.path.join(served_dir, fname))
@@ -326,10 +332,14 @@ async def export_dataset():
326
 
327
  @app.get("/download/{fname}")
328
  async def download_file(fname: str):
329
- served = os.path.join(HERE, "exports", os.path.basename(fname))
330
- if os.path.exists(served):
331
- return FileResponse(served, filename=os.path.basename(fname),
332
- media_type="application/jsonl")
 
 
 
 
333
  return JSONResponse({"error": "not found"}, status_code=404)
334
 
335
 
 
311
  path = finetune_data.export()
312
  if not path:
313
  return JSONResponse({"path": "", "count": 0, "download": ""})
314
+ # Copy into a WRITABLE served dir. In Docker, /app is read-only for the
315
+ # non-root user, so use /data (persistent) when available, else the temp dir.
316
  import shutil
317
+ import tempfile
318
+ base = paths.DATA_ROOT if paths.PERSISTENT else tempfile.gettempdir()
319
+ served_dir = os.path.join(base, "exports")
320
+ try:
321
+ os.makedirs(served_dir, exist_ok=True)
322
+ except OSError:
323
+ served_dir = tempfile.gettempdir()
324
  fname = os.path.basename(path)
325
  try:
326
  shutil.copy(path, os.path.join(served_dir, fname))
 
332
 
333
  @app.get("/download/{fname}")
334
  async def download_file(fname: str):
335
+ import tempfile
336
+ base = paths.DATA_ROOT if paths.PERSISTENT else tempfile.gettempdir()
337
+ fname = os.path.basename(fname)
338
+ for d in (os.path.join(base, "exports"), os.path.join(tempfile.gettempdir(), "exports"),
339
+ tempfile.gettempdir()):
340
+ served = os.path.join(d, fname)
341
+ if os.path.exists(served):
342
+ return FileResponse(served, filename=fname, media_type="application/jsonl")
343
  return JSONResponse({"error": "not found"}, status_code=404)
344
 
345
 
ui_kits/chan-compass/views.jsx CHANGED
@@ -428,9 +428,24 @@ function ModelView() {
428
  };
429
  const [dlUrl, setDlUrl] = useState("");
430
  const exportDs = async () => {
431
- const r = await API.exportDataset();
432
- if (r.download) { setDl("Exported " + r.count + " pairs."); setDlUrl(r.download); }
433
- else { setDl("No pairs captured yet — run a few Signals AI interprets first."); setDlUrl(""); }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
434
  };
435
  return (
436
  <div style={{display:"flex", flexDirection:"column", gap:"var(--space-300)"}}>
 
428
  };
429
  const [dlUrl, setDlUrl] = useState("");
430
  const exportDs = async () => {
431
+ setDl("⏳ Exporting…"); setDlUrl("");
432
+ try {
433
+ const r = await API.exportDataset();
434
+ if (r && r.download) {
435
+ setDl("✅ Exported " + r.count + " pairs.");
436
+ setDlUrl(r.download);
437
+ // also trigger the download immediately
438
+ const a = document.createElement("a");
439
+ a.href = r.download; a.download = "";
440
+ document.body.appendChild(a); a.click(); a.remove();
441
+ } else {
442
+ setDl("No pairs captured yet — run a few Signals AI interprets first.");
443
+ setDlUrl("");
444
+ }
445
+ } catch (e) {
446
+ setDl("❌ Export failed: " + e.message);
447
+ setDlUrl("");
448
+ }
449
  };
450
  return (
451
  <div style={{display:"flex", flexDirection:"column", gap:"var(--space-300)"}}>