diff --git a/app/sft.py b/app/sft.py index c5aabc7..97ae573 100644 --- a/app/sft.py +++ b/app/sft.py @@ -271,3 +271,39 @@ def get_stats() -> dict[str, object]: "by_task_type": by_task_type, "export_ready": export_ready, } + + +# ── GET /config ───────────────────────────────────────────────────────────── + +@router.get("/config") +def get_sft_config() -> dict: + """Return the current SFT configuration (bench_results_dir).""" + f = _config_file() + if not f.exists(): + return {"bench_results_dir": ""} + try: + raw = yaml.safe_load(f.read_text(encoding="utf-8")) or {} + except yaml.YAMLError: + return {"bench_results_dir": ""} + return raw.get("sft", {"bench_results_dir": ""}) + + +class SftConfigPayload(BaseModel): + bench_results_dir: str + + +@router.post("/config") +def post_sft_config(payload: SftConfigPayload) -> dict: + """Write the bench_results_dir setting to the config file.""" + f = _config_file() + f.parent.mkdir(parents=True, exist_ok=True) + try: + raw = yaml.safe_load(f.read_text(encoding="utf-8")) if f.exists() else {} + raw = raw or {} + except yaml.YAMLError: + raw = {} + raw["sft"] = {"bench_results_dir": payload.bench_results_dir} + tmp = f.with_suffix(".tmp") + tmp.write_text(yaml.dump(raw, allow_unicode=True, sort_keys=False), encoding="utf-8") + tmp.rename(f) + return {"ok": True} diff --git a/web/src/components/AppSidebar.vue b/web/src/components/AppSidebar.vue index f691c9b..051feda 100644 --- a/web/src/components/AppSidebar.vue +++ b/web/src/components/AppSidebar.vue @@ -65,8 +65,9 @@ const navItems = [ { path: '/', icon: '🃏', label: 'Label' }, { path: '/fetch', icon: '📥', label: 'Fetch' }, { path: '/stats', icon: '📊', label: 'Stats' }, - { path: '/benchmark', icon: '🏁', label: 'Benchmark' }, - { path: '/settings', icon: '⚙️', label: 'Settings' }, + { path: '/benchmark', icon: '🏁', label: 'Benchmark' }, + { path: '/corrections', icon: '✍️', label: 'Corrections' }, + { path: '/settings', icon: '⚙️', label: 'Settings' }, ] const stowed = ref(localStorage.getItem(LS_KEY) === 'true') diff --git a/web/src/router/index.ts b/web/src/router/index.ts index 9e64197..24f9321 100644 --- a/web/src/router/index.ts +++ b/web/src/router/index.ts @@ -5,15 +5,17 @@ import LabelView from '../views/LabelView.vue' const FetchView = () => import('../views/FetchView.vue') const StatsView = () => import('../views/StatsView.vue') const BenchmarkView = () => import('../views/BenchmarkView.vue') -const SettingsView = () => import('../views/SettingsView.vue') +const SettingsView = () => import('../views/SettingsView.vue') +const CorrectionsView = () => import('../views/CorrectionsView.vue') export const router = createRouter({ history: createWebHashHistory(), routes: [ - { path: '/', component: LabelView, meta: { title: 'Label' } }, - { path: '/fetch', component: FetchView, meta: { title: 'Fetch' } }, - { path: '/stats', component: StatsView, meta: { title: 'Stats' } }, - { path: '/benchmark', component: BenchmarkView, meta: { title: 'Benchmark' } }, - { path: '/settings', component: SettingsView, meta: { title: 'Settings' } }, + { path: '/', component: LabelView, meta: { title: 'Label' } }, + { path: '/fetch', component: FetchView, meta: { title: 'Fetch' } }, + { path: '/stats', component: StatsView, meta: { title: 'Stats' } }, + { path: '/benchmark', component: BenchmarkView, meta: { title: 'Benchmark' } }, + { path: '/corrections', component: CorrectionsView, meta: { title: 'Corrections' } }, + { path: '/settings', component: SettingsView, meta: { title: 'Settings' } }, ], }) diff --git a/web/src/views/SettingsView.vue b/web/src/views/SettingsView.vue index f09c924..bcfe7ac 100644 --- a/web/src/views/SettingsView.vue +++ b/web/src/views/SettingsView.vue @@ -110,6 +110,63 @@ + +
+

cf-orch Integration

+

+ Import SFT (supervised fine-tuning) candidates from cf-orch benchmark runs. +

+ +
+ +
+ +
+ + + {{ saveStatus }} +
+ + + + + + + + + + + + + + + + + + +
TimestampCandidatesImported
{{ run.timestamp }}{{ run.candidate_count }}{{ run.already_imported ? '✓' : '—' }} + +
+ +
+ Imported {{ importResult.imported }}, skipped {{ importResult.skipped }}. +
+
+