@lzhzzzzwill/cofos 1.1.6 → 1.1.8

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
@@ -162,7 +162,10 @@ function main() {
162
162
  if (!existsSync(chatScript)) die(`Missing script: ${chatScript}`);
163
163
  ensureDeps(py);
164
164
 
165
- console.log(" Loading COFOS 9B + RAG backend from Hugging Face … first run may take a while\n");
165
+ console.log(" Loading COFOS 9B + RAG backend from Hugging Face … first run may take a while");
166
+ if (pdfDir) console.log(" Local PDF RAG: enabled for this session");
167
+ else console.log(" Tip: add local papers with `cofos --pdf-dir ./new_pdfs`");
168
+ console.log("");
166
169
 
167
170
  const backendEnv = {
168
171
  ...process.env,
@@ -188,8 +191,18 @@ function main() {
188
191
 
189
192
  let buf = "", ready = false, generating = false, responseOpen = false, closed = false;
190
193
  const inputQ = [];
191
- const rl = createInterface({ input: process.stdin, terminal: true });
192
- rl.on("line", (l) => { inputQ.push(l); });
194
+ const mainPrompt = C + " cofos " + R;
195
+ const contPrompt = G + " ... " + R;
196
+ const rl = createInterface({
197
+ input: process.stdin,
198
+ output: process.stdout,
199
+ terminal: true,
200
+ prompt: mainPrompt,
201
+ });
202
+ rl.on("line", (l) => {
203
+ if (!ready || generating) inputQ.push(l);
204
+ else if (!handle(l)) ask();
205
+ });
193
206
 
194
207
  // Forward Python stderr (status / progress messages) to our stderr.
195
208
  proc.stderr.on("data", (chunk) => { process.stderr.write(chunk); });
@@ -275,9 +288,12 @@ function main() {
275
288
  ask();
276
289
  }
277
290
 
278
- function ask() {
291
+ function ask(prompt = mainPrompt) {
279
292
  if (closed) return;
280
- try { rl.question(C + " cofos " + R, handle); } catch (_) {}
293
+ try {
294
+ rl.setPrompt(prompt);
295
+ rl.prompt();
296
+ } catch (_) {}
281
297
  }
282
298
 
283
299
  /* ─── multi-line accumulator ─── */
@@ -287,8 +303,8 @@ function main() {
287
303
  // Multi-line continuation: lines ending with "\"
288
304
  if (input.endsWith("\\")) {
289
305
  mlBuf.push(input.slice(0, -1));
290
- try { rl.question(G + " ... " + R, handle); } catch (_) {}
291
- return;
306
+ ask(contPrompt);
307
+ return true;
292
308
  }
293
309
  if (mlBuf.length > 0) {
294
310
  mlBuf.push(input);
@@ -297,20 +313,20 @@ function main() {
297
313
  }
298
314
 
299
315
  input = input.trim();
300
- if (!input) { ask(); return; }
316
+ if (!input) return false;
301
317
 
302
318
  // Local-only commands (don't hit the backend).
303
- if (/^\/(exit|quit)$/.test(input)) { proc.stdin.write("/exit\n"); proc.stdin.end(); return; }
319
+ if (/^\/(exit|quit)$/.test(input)) { proc.stdin.write("/exit\n"); proc.stdin.end(); return true; }
304
320
  if (/^\/(help)$/.test(input)) {
305
- console.log("\n Commands:\n /help Show help\n /exit Quit\n /clear Clear conversation history\n /save Persist conversation history\n /info Model and RAG info\n /topk N Set retrieval top-k\n /rag on|off Enable/disable RAG\n\n Multi-line: end a line with \\ to continue.\n");
306
- ask(); return;
321
+ console.log("\n Commands:\n /help Show help\n /exit Quit\n /clear Clear conversation history\n /save Persist conversation history\n /info Model and RAG info\n /topk N Set retrieval top-k\n /rag on|off Enable/disable RAG\n\n Add local papers to RAG:\n cofos --pdf-dir ./new_pdfs\n cofos --pdf-dir ./new_pdfs --rebuild-pdf-index\n\n Multi-line: end a line with \\ to continue.\n");
322
+ return false;
307
323
  }
308
324
  if (/^\/(clear)$/.test(input)) {
309
325
  mlBuf = [];
310
326
  responseOpen = false;
311
327
  proc.stdin.write(input + "\n");
312
328
  generating = true;
313
- return;
329
+ return true;
314
330
  }
315
331
  if (/^\/(info)$/.test(input)) {
316
332
  console.log(`\n COFOS CLI — v${pkg.version}`);
@@ -320,7 +336,7 @@ function main() {
320
336
  console.log(` HF: ${backendEnv.HF_HOME}`);
321
337
  console.log(" Engine: StudentAdapterInference + transformers + PyTorch");
322
338
  console.log(" Hist: ~/.cofos_history.jsonl\n");
323
- ask(); return;
339
+ return false;
324
340
  }
325
341
 
326
342
  // Forward to backend. Echo a stable user turn so pasted/submitted questions remain visible in the transcript.
@@ -328,6 +344,7 @@ function main() {
328
344
  responseOpen = false;
329
345
  generating = true;
330
346
  proc.stdin.write(input + "\n");
347
+ return true;
331
348
  }
332
349
  }
333
350
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lzhzzzzwill/cofos",
3
- "version": "1.1.6",
3
+ "version": "1.1.8",
4
4
  "description": "COFOS 9B + RAG chat CLI with optional local PDF ingestion.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -104,3 +104,16 @@ student_answer_refinement_user_prompt: 'Question: {question}
104
104
  checklist, or explanation of how you rewrote it.
105
105
 
106
106
  '
107
+ interaction:
108
+ greetings:
109
+ hi: Hello! What would you like to know about COFs or reactive oxygen species?
110
+ hello: Hello! What would you like to know about COFs or reactive oxygen species?
111
+ hey: Hello! What would you like to know about COFs or reactive oxygen species?
112
+ 你好: 你好!你想了解 COF、光催化还是活性氧相关问题?
113
+ 您好: 您好!你想了解 COF、光催化还是活性氧相关问题?
114
+ 嗨: 你好!你想了解 COF、光催化还是活性氧相关问题?
115
+ 在吗: 在的。你想了解哪方面的 COF 或活性氧问题?
116
+ thanks: You're welcome.
117
+ thank you: You're welcome.
118
+ 谢谢: 不客气。
119
+ 感谢: 不客气。
@@ -475,6 +475,7 @@ class StudentAdapterInference:
475
475
  buffer = ""
476
476
  started = False
477
477
  in_think = False
478
+ awaiting_initial_answer = True
478
479
 
479
480
  for chunk in chunks:
480
481
  buffer += chunk
@@ -488,6 +489,16 @@ class StudentAdapterInference:
488
489
  break
489
490
  buffer = buffer[end + len("</think>") :]
490
491
  in_think = False
492
+ awaiting_initial_answer = False
493
+ continue
494
+
495
+ # Some tokenizers suppress the opening <think> marker but still
496
+ # stream the reasoning text followed by </think>. At the start
497
+ # of an answer, drop everything before that closing marker too.
498
+ end_without_start = buffer.find("</think>")
499
+ if awaiting_initial_answer and end_without_start != -1:
500
+ buffer = buffer[end_without_start + len("</think>") :]
501
+ awaiting_initial_answer = False
491
502
  continue
492
503
 
493
504
  start = buffer.find("<think>")
package/scripts/chat.py CHANGED
@@ -373,6 +373,14 @@ def ensure_runtime_data(project_root: Path, config: dict) -> None:
373
373
  print("[chat] Runtime data ready.", file=sys.stderr, flush=True)
374
374
 
375
375
 
376
+
377
+ def _clean_history_content(role: str, content: str) -> str:
378
+ content = content.replace("COF-ROS-Reasoner", "COFOS")
379
+ if role == "assistant":
380
+ content = re.sub(r"(?is)<think>.*?</think>", "", content).strip()
381
+ content = re.sub(r"(?is)^.*?</think>", "", content).strip()
382
+ return content
383
+
376
384
  def _load_history() -> list:
377
385
  """Load recent conversation turns from the persistent history file.
378
386
 
@@ -398,7 +406,9 @@ def _load_history() -> list:
398
406
  and turn.get("role") in {"user", "assistant"}
399
407
  and isinstance(turn.get("content"), str)
400
408
  ):
401
- turns.append(turn)
409
+ cleaned = _clean_history_content(turn["role"], turn["content"])
410
+ if cleaned:
411
+ turns.append({"role": turn["role"], "content": cleaned})
402
412
  except OSError:
403
413
  return []
404
414
 
@@ -463,14 +473,19 @@ def main() -> None:
463
473
  import yaml
464
474
  from inference.student_adapter_inference import StudentAdapterInference, StudentRAGContext
465
475
 
466
- logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s")
467
- for noisy_logger in ("httpx", "httpcore", "huggingface_hub"):
476
+ debug = os.environ.get("COFOS_DEBUG", "").lower() in {"1", "true", "yes", "on"}
477
+ log_level = logging.INFO if debug else logging.WARNING
478
+ logging.basicConfig(
479
+ level=log_level,
480
+ format="%(asctime)s - %(levelname)s - %(message)s",
481
+ force=True,
482
+ )
483
+ for noisy_logger in ("httpx", "httpcore", "huggingface_hub", "transformers"):
468
484
  logging.getLogger(noisy_logger).setLevel(logging.WARNING)
469
485
 
470
486
  config_path = default_config_path(runtime_root) if args.config == DEFAULT_CONFIG else resolve_project_path(runtime_root, args.config)
471
487
  model_path = resolve_project_path(runtime_root, args.model_path)
472
488
 
473
- debug = os.environ.get("COFOS_DEBUG", "").lower() in {"1", "true", "yes", "on"}
474
489
  if debug:
475
490
  print(f"[chat] Runtime root: {runtime_root}", file=sys.stderr, flush=True)
476
491
  print(f"[chat] Cache root: {runtime_cache_root()}", file=sys.stderr, flush=True)