Parse <think> reasoning: show final answer, collapse reasoning, judge on answer
Browse files
app.py
CHANGED
|
@@ -59,11 +59,10 @@ MODEL_ERROR: str | None = None
|
|
| 59 |
MODEL_SETTINGS: dict[str, Any] = {}
|
| 60 |
|
| 61 |
DEFAULT_SYSTEM = (
|
| 62 |
-
"You are First-Principle AI, a small reasoning model.
|
| 63 |
-
"
|
| 64 |
-
"misleading patterns,
|
| 65 |
-
"
|
| 66 |
-
"reason that names the trap."
|
| 67 |
)
|
| 68 |
BLINDSPOT_SYSTEM = (
|
| 69 |
"You are First-Principle AI acting as a blind-spot checker. The user describes "
|
|
@@ -583,9 +582,45 @@ VERDICT_TEXT = {
|
|
| 583 |
}
|
| 584 |
|
| 585 |
|
| 586 |
-
def
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 587 |
head = VERDICT_TEXT.get(verdict, VERDICT_TEXT["unclear"])
|
| 588 |
-
|
|
|
|
| 589 |
|
| 590 |
|
| 591 |
def _thinking_md() -> str:
|
|
@@ -673,10 +708,12 @@ def run_trap(
|
|
| 673 |
|
| 674 |
try:
|
| 675 |
text, meta = _generate(trap["prompt"], system_prompt, max_tokens, temperature, top_p, repeat_penalty)
|
| 676 |
-
|
|
|
|
| 677 |
score = _bump(score, verdict)
|
| 678 |
except Exception as exc: # noqa: BLE001 - surface runtime issues in the UI
|
| 679 |
-
|
|
|
|
| 680 |
"Model load or inference failed.\n\n"
|
| 681 |
f"```\n{exc}\n```\n\n"
|
| 682 |
"The UI is live and the model artifact is published, but the runtime could not "
|
|
@@ -687,7 +724,7 @@ def run_trap(
|
|
| 687 |
|
| 688 |
yield (
|
| 689 |
trap_card_html(trap, revealed=True),
|
| 690 |
-
_answer_md(trap,
|
| 691 |
scoreboard_html(score),
|
| 692 |
_metrics_markdown(meta),
|
| 693 |
score,
|
|
|
|
| 59 |
MODEL_SETTINGS: dict[str, Any] = {}
|
| 60 |
|
| 61 |
DEFAULT_SYSTEM = (
|
| 62 |
+
"You are First-Principle AI, a small reasoning model. Reason briefly — a few "
|
| 63 |
+
"sentences at most — and watch for hidden assumptions, false premises, "
|
| 64 |
+
"misleading patterns, and familiar riddles that have been altered. Then end "
|
| 65 |
+
"with a clear final answer that names the trap in one line."
|
|
|
|
| 66 |
)
|
| 67 |
BLINDSPOT_SYSTEM = (
|
| 68 |
"You are First-Principle AI acting as a blind-spot checker. The user describes "
|
|
|
|
| 582 |
}
|
| 583 |
|
| 584 |
|
| 585 |
+
def _split_think(text: str) -> tuple[str, str]:
|
| 586 |
+
"""Split a reasoning model's output into (reasoning, final answer)."""
|
| 587 |
+
text = (text or "").strip()
|
| 588 |
+
if "<think>" in text:
|
| 589 |
+
if "</think>" in text:
|
| 590 |
+
pre, rest = text.split("</think>", 1)
|
| 591 |
+
reasoning = pre.split("<think>", 1)[-1].strip()
|
| 592 |
+
answer = rest.strip()
|
| 593 |
+
else:
|
| 594 |
+
# generation was cut off before the model finished thinking
|
| 595 |
+
reasoning = text.split("<think>", 1)[-1].strip()
|
| 596 |
+
answer = ""
|
| 597 |
+
else:
|
| 598 |
+
reasoning, answer = "", text
|
| 599 |
+
# some chat templates prefix the final line with "Answer:"
|
| 600 |
+
return reasoning, answer
|
| 601 |
+
|
| 602 |
+
|
| 603 |
+
def _render_reasoning(reasoning: str, answer: str) -> str:
|
| 604 |
+
parts: list[str] = []
|
| 605 |
+
if answer:
|
| 606 |
+
parts.append(answer)
|
| 607 |
+
else:
|
| 608 |
+
parts.append(
|
| 609 |
+
"_The model was still reasoning when it hit the token limit. "
|
| 610 |
+
"Raise **Max tokens** in the Engine Room for the full answer._"
|
| 611 |
+
)
|
| 612 |
+
if reasoning:
|
| 613 |
+
parts.append(
|
| 614 |
+
"\n\n<details><summary>🧠 Show first-principle reasoning</summary>\n\n"
|
| 615 |
+
f"{reasoning}\n\n</details>"
|
| 616 |
+
)
|
| 617 |
+
return "".join(parts)
|
| 618 |
+
|
| 619 |
+
|
| 620 |
+
def _answer_md(trap: dict[str, Any], reasoning: str, answer: str, verdict: str) -> str:
|
| 621 |
head = VERDICT_TEXT.get(verdict, VERDICT_TEXT["unclear"])
|
| 622 |
+
body = _render_reasoning(reasoning, answer)
|
| 623 |
+
return f"{head}\n\n---\n\n**First-Principle AI says:**\n\n{body}"
|
| 624 |
|
| 625 |
|
| 626 |
def _thinking_md() -> str:
|
|
|
|
| 708 |
|
| 709 |
try:
|
| 710 |
text, meta = _generate(trap["prompt"], system_prompt, max_tokens, temperature, top_p, repeat_penalty)
|
| 711 |
+
reasoning, answer = _split_think(text)
|
| 712 |
+
verdict = judge(trap, answer or reasoning)
|
| 713 |
score = _bump(score, verdict)
|
| 714 |
except Exception as exc: # noqa: BLE001 - surface runtime issues in the UI
|
| 715 |
+
reasoning = ""
|
| 716 |
+
answer = (
|
| 717 |
"Model load or inference failed.\n\n"
|
| 718 |
f"```\n{exc}\n```\n\n"
|
| 719 |
"The UI is live and the model artifact is published, but the runtime could not "
|
|
|
|
| 724 |
|
| 725 |
yield (
|
| 726 |
trap_card_html(trap, revealed=True),
|
| 727 |
+
_answer_md(trap, reasoning, answer, verdict),
|
| 728 |
scoreboard_html(score),
|
| 729 |
_metrics_markdown(meta),
|
| 730 |
score,
|