@lzhzzzzwill/cofos 1.1.0 → 1.1.3

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/bin/cofos.js CHANGED
@@ -172,6 +172,8 @@ function main() {
172
172
  HF_HUB_ENABLE_HF_TRANSFER: process.env.HF_HUB_ENABLE_HF_TRANSFER || "0",
173
173
  HF_HUB_DOWNLOAD_TIMEOUT: process.env.HF_HUB_DOWNLOAD_TIMEOUT || "120",
174
174
  HF_HUB_ETAG_TIMEOUT: process.env.HF_HUB_ETAG_TIMEOUT || "30",
175
+ HF_HUB_VERBOSITY: process.env.HF_HUB_VERBOSITY || "warning",
176
+ TRANSFORMERS_VERBOSITY: process.env.TRANSFORMERS_VERBOSITY || "warning",
175
177
  };
176
178
  const proc = spawn(py, backendArgs, {
177
179
  stdio: ["pipe", "pipe", "pipe"],
@@ -184,7 +186,7 @@ function main() {
184
186
  proc.stdout.setEncoding("utf-8");
185
187
  proc.stderr.setEncoding("utf-8");
186
188
 
187
- let buf = "", ready = false, generating = false, closed = false;
189
+ let buf = "", ready = false, generating = false, responseOpen = false, closed = false;
188
190
  const inputQ = [];
189
191
  const rl = createInterface({ input: process.stdin, terminal: true });
190
192
  rl.on("line", (l) => { inputQ.push(l); });
@@ -208,27 +210,35 @@ function main() {
208
210
  // dropping it keeps it from being prepended to the next one.
209
211
  if (!generating) { buf = ""; return; }
210
212
 
213
+ if (!responseOpen) {
214
+ const ri = buf.indexOf(RESPONSE);
215
+ if (ri === -1) {
216
+ // Keep enough tail to catch a RESPONSE marker split across chunks.
217
+ const keep = RESPONSE.length - 1;
218
+ if (buf.length > keep) buf = buf.slice(-keep);
219
+ return;
220
+ }
221
+ buf = buf.slice(ri + RESPONSE.length);
222
+ if (buf[0] === "\n") buf = buf.slice(1);
223
+ responseOpen = true;
224
+ }
225
+
211
226
  // Scan for DONE marker — stream everything before it.
212
227
  const di = buf.indexOf(DONE);
213
228
  if (di !== -1) {
214
- // Flush any pre-DONE content (cleaned of RESPONSE marker).
215
- let pre = buf.slice(0, di);
216
- const ri = pre.indexOf(RESPONSE);
217
- if (ri !== -1) pre = pre.slice(ri + RESPONSE.length);
229
+ const pre = buf.slice(0, di);
218
230
  if (pre) process.stdout.write(pre);
219
231
  buf = buf.slice(di + DONE.length);
220
232
  if (buf[0] === "\n") buf = buf.slice(1);
221
233
  generating = false;
234
+ responseOpen = false;
222
235
  console.log("");
223
236
  drain();
224
237
  } else {
225
- // Stream buffered content, keeping only enough tail to catch a
226
- // partial DONE marker.
227
- const keep = DONE.length;
238
+ // Stream buffered content, keeping enough tail to catch a partial DONE marker.
239
+ const keep = DONE.length - 1;
228
240
  if (buf.length > keep) {
229
- let out = buf.slice(0, -keep);
230
- const ri = out.indexOf(RESPONSE);
231
- if (ri !== -1) out = out.slice(ri + RESPONSE.length);
241
+ const out = buf.slice(0, -keep);
232
242
  if (out) process.stdout.write(out);
233
243
  buf = buf.slice(-keep);
234
244
  }
@@ -297,6 +307,7 @@ function main() {
297
307
  }
298
308
  if (/^\/(clear)$/.test(input)) {
299
309
  mlBuf = [];
310
+ responseOpen = false;
300
311
  proc.stdin.write(input + "\n");
301
312
  generating = true;
302
313
  return;
@@ -313,6 +324,7 @@ function main() {
313
324
  }
314
325
 
315
326
  // Forward to backend.
327
+ responseOpen = false;
316
328
  generating = true;
317
329
  proc.stdin.write(input + "\n");
318
330
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lzhzzzzwill/cofos",
3
- "version": "1.1.0",
3
+ "version": "1.1.3",
4
4
  "description": "COFOS 9B + RAG chat CLI with optional local PDF ingestion.",
5
5
  "type": "module",
6
6
  "bin": {
package/scripts/chat.py CHANGED
@@ -24,6 +24,8 @@ os.environ.setdefault("HF_HUB_DISABLE_XET", "1")
24
24
  os.environ.setdefault("HF_HUB_ENABLE_HF_TRANSFER", "0")
25
25
  os.environ.setdefault("HF_HUB_DOWNLOAD_TIMEOUT", "120")
26
26
  os.environ.setdefault("HF_HUB_ETAG_TIMEOUT", "30")
27
+ os.environ.setdefault("HF_HUB_VERBOSITY", "warning")
28
+ os.environ.setdefault("TRANSFORMERS_VERBOSITY", "warning")
27
29
 
28
30
  HISTORY_FILE = os.path.join(os.path.expanduser("~"), ".cofos_history.jsonl")
29
31
  HISTORY_MAX_TURNS = 20
@@ -338,19 +340,35 @@ def ensure_runtime_data(project_root: Path, config: dict) -> None:
338
340
  "runtime/bm25/bm25_info.json": bm25_dir,
339
341
  }
340
342
 
343
+ missing_items = []
341
344
  for remote_path, target_dir in file_map.items():
342
- target_dir.mkdir(parents=True, exist_ok=True)
343
345
  local_name = remote_path.rsplit("/", 1)[-1]
344
346
  local_path = target_dir / local_name
345
- if local_path.exists():
346
- continue
347
+ if not local_path.exists():
348
+ missing_items.append((remote_path, target_dir, local_path))
349
+
350
+ total = len(missing_items)
351
+ if total == 0:
352
+ print("[chat] Runtime data ready.", file=sys.stderr, flush=True)
353
+ return
354
+
355
+ def progress_line(index: int, remote_path: str) -> str:
356
+ width = 18
357
+ filled = int(width * index / total)
358
+ bar = "#" * filled + "-" * (width - filled)
359
+ pct = int(100 * index / total)
360
+ return f"[chat] Runtime data [{index}/{total}] [{bar}] {pct:3d}% {remote_path}"
361
+
362
+ for index, (remote_path, target_dir, local_path) in enumerate(missing_items, 1):
363
+ target_dir.mkdir(parents=True, exist_ok=True)
364
+ print(progress_line(index, remote_path), file=sys.stderr, flush=True)
347
365
  cached = hf_hub_download(
348
366
  repo_id=repo,
349
367
  repo_type="dataset",
350
368
  filename=remote_path,
351
369
  )
352
370
  shutil.copy2(cached, local_path)
353
- print(f"[chat] Downloaded {remote_path} -> {local_path}", file=sys.stderr, flush=True)
371
+ print(f"[chat] -> {local_path}", file=sys.stderr, flush=True)
354
372
 
355
373
  print("[chat] Runtime data ready.", file=sys.stderr, flush=True)
356
374
 
@@ -446,6 +464,8 @@ def main() -> None:
446
464
  from inference.student_adapter_inference import StudentAdapterInference, StudentRAGContext
447
465
 
448
466
  logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s")
467
+ for noisy_logger in ("httpx", "httpcore", "huggingface_hub"):
468
+ logging.getLogger(noisy_logger).setLevel(logging.WARNING)
449
469
 
450
470
  config_path = default_config_path(runtime_root) if args.config == DEFAULT_CONFIG else resolve_project_path(runtime_root, args.config)
451
471
  model_path = resolve_project_path(runtime_root, args.model_path)
@@ -466,7 +486,7 @@ def main() -> None:
466
486
  pdf_changed = parse_pdfs_if_needed(runtime_root, config, force=args.rebuild_pdf_index)
467
487
  build_augmented_bm25_if_needed(runtime_root, config, force=args.rebuild_pdf_index or pdf_changed)
468
488
 
469
- print("[chat] Loading model (this may take 1-2 min on first run) ...", file=sys.stderr, flush=True)
489
+ print("[chat] Loading model weights. First run may download 12GB+ and take tens of minutes; cached runs are much faster ...", file=sys.stderr, flush=True)
470
490
 
471
491
  runner = StudentAdapterInference(
472
492
  config=config,