#!/usr/bin/env python3 """ app.py — SmolLM2-360M-Think Demo — HuggingFace Spaces DuoNeural (Archon + Jesse + Aura) — 2026 Demonstrates Think Instillation: a 360M model reasoning through multiple-choice questions using learned traces, trained via SFT + GRPO with dead-prompt filtering. """ import re import torch import gradio as gr from transformers import AutoModelForCausalLM, AutoTokenizer model = None tokenizer = None DEVICE = "cpu" MODEL_ID = "DuoNeural/SmolLM2-360M-Think-R18" EXAMPLES = [ ["What is the main function of the mitochondria in a cell?", "(A) Producing proteins\n(B) Generating energy (ATP)\n(C) Storing genetic material\n(D) Breaking down waste"], ["Which planet in our solar system has the most moons?", "(A) Jupiter\n(B) Saturn\n(C) Uranus\n(D) Neptune"], ["What gas do plants take in during photosynthesis?", "(A) Oxygen\n(B) Nitrogen\n(C) Carbon dioxide\n(D) Hydrogen"], ["If a car travels 60 miles per hour, how far will it go in 2.5 hours?", "(A) 100 miles\n(B) 120 miles\n(C) 150 miles\n(D) 180 miles"], ["Which of the following is an example of a conductor of electricity?", "(A) Rubber\n(B) Wood\n(C) Copper\n(D) Plastic"], ["What is the chemical formula for water?", "(A) CO2\n(B) NaCl\n(C) H2O\n(D) O2"], ] PROMPT_TEMPLATE = """Answer the following multiple choice question. Think step by step before answering. Question: {question} Choices: {choices} Reasoning: """ def load_model(): global model, tokenizer if model is not None: return tokenizer = AutoTokenizer.from_pretrained(MODEL_ID) model = AutoModelForCausalLM.from_pretrained( MODEL_ID, torch_dtype=torch.float32, low_cpu_mem_usage=True, ).to(DEVICE) model.eval() def parse_output(full_text: str): """Extract content and final answer from model output.""" think_match = re.search(r"(.*?)", full_text, re.DOTALL) think_content = think_match.group(1).strip() if think_match else "" # Look for answer pattern (A)/(B)/(C)/(D) after after_think = full_text[think_match.end():] if think_match else full_text answer_match = re.search(r"\(([ABCD])\)", after_think) answer = f"({answer_match.group(1)})" if answer_match else "No clear answer found" return think_content, answer, after_think.strip() def generate(question: str, choices: str, max_new_tokens: int, temperature: float, top_p: float): if not question.strip(): return "", "", "", "Please enter a question." load_model() prompt = PROMPT_TEMPLATE.format( question=question.strip(), choices=choices.strip(), ) inputs = tokenizer(prompt, return_tensors="pt").to(DEVICE) input_len = inputs["input_ids"].shape[1] with torch.no_grad(): outputs = model.generate( **inputs, max_new_tokens=int(max_new_tokens), temperature=float(temperature), top_p=float(top_p), do_sample=(temperature > 0.01), pad_token_id=tokenizer.eos_token_id, eos_token_id=tokenizer.eos_token_id, ) # Decode only the generated portion generated_ids = outputs[0][input_len:] raw_output = tokenizer.decode(generated_ids, skip_special_tokens=True) # The model started mid- tag, so reconstruct full_with_think = "" + raw_output think_content, answer, after_think = parse_output(full_with_think) # Build colored HTML for the reasoning trace think_html = _render_think_html(think_content) if think_content else _no_think_html() answer_html = _render_answer_html(answer) return think_html, answer_html, raw_output def _render_think_html(think_content: str) -> str: # Escape HTML and preserve newlines escaped = think_content.replace("&", "&").replace("<", "<").replace(">", ">") lines = escaped.split("\n") rendered_lines = [] for line in lines: line = line.strip() if not line: rendered_lines.append("") continue rendered_lines.append(f'{line}') body = "
".join(rendered_lines) return f"""
◆ REASONING TRACE <think>
{body}
</think>
""" def _no_think_html() -> str: return """
No <think> trace found in output. The model may have skipped reasoning.
""" def _render_answer_html(answer: str) -> str: is_valid = re.match(r"\([ABCD]\)", answer) color = "#2ea043" if is_valid else "#f85149" border = "#238636" if is_valid else "#da3633" icon = "✓" if is_valid else "?" return f"""
{icon} {answer}
Model's final answer
""" def fill_example(question, choices): return question, choices def build_demo(): with gr.Blocks( title="SmolLM2-360M-Think — DuoNeural Think Instillation", theme=gr.themes.Base(primary_hue="blue", secondary_hue="purple", neutral_hue="slate"), css=""" .gradio-container { background: #010409; color: #e6edf3; } .gr-button-primary { background: #1f6feb !important; border: 1px solid #388bfd !important; } footer { display: none !important; } """ ) as demo: gr.Markdown(""" # 🧠 SmolLM2-360M-Think **Think Instillation** — DuoNeural, 2026 A 360M model trained to reason through problems using `` traces before answering. No giant teacher model. No distillation. Just GRPO with dead-prompt filtering teaching a small model to think for itself. **28/100 correct on ARC-Easy** (GRPO helped: post_SFT=0.250 → final=0.280 with +0.030 delta) Type a multiple-choice question below and watch the model reason through it. """) with gr.Row(): with gr.Column(scale=2): question_in = gr.Textbox( label="Question", placeholder="What is the main function of the mitochondria in a cell?", lines=3, ) choices_in = gr.Textbox( label="Answer Choices", placeholder="(A) Producing proteins\n(B) Generating energy\n(C) Storing DNA\n(D) Breaking down waste", lines=4, value="(A) Producing proteins\n(B) Generating energy (ATP)\n(C) Storing genetic material\n(D) Breaking down waste", ) with gr.Column(scale=1): max_tokens = gr.Slider(64, 512, value=256, step=32, label="Max reasoning tokens") temperature = gr.Slider(0.0, 1.2, value=0.7, step=0.1, label="Temperature") top_p = gr.Slider(0.5, 1.0, value=0.9, step=0.05, label="Top-p") think_btn = gr.Button("Think + Answer", variant="primary", size="lg") gr.Markdown("**Examples** — click any row to load it:") examples_table = gr.Examples( examples=EXAMPLES, inputs=[question_in, choices_in], label=None, ) gr.Markdown("### 💭 Reasoning Trace") think_out = gr.HTML() gr.Markdown("### 🎯 Final Answer") answer_out = gr.HTML() with gr.Accordion("Raw model output", open=False): raw_out = gr.Textbox(label="Raw generated text", lines=8, interactive=False) think_btn.click( fn=generate, inputs=[question_in, choices_in, max_tokens, temperature, top_p], outputs=[think_out, answer_out, raw_out], ) question_in.change(fn=None, inputs=None, outputs=None) gr.Markdown(""" --- **DuoNeural** — open research lab · one human, two AIs, shared curiosity Think Instillation technique by Archon (DuoNeural). GRPO with dead-prompt filtering. Model: [DuoNeural/SmolLM2-360M-Think-R18](https://huggingface.co/DuoNeural/SmolLM2-360M-Think-R18) · [huggingface.co/DuoNeural](https://huggingface.co/DuoNeural) """) return demo if __name__ == "__main__": demo = build_demo() demo.launch(server_name="0.0.0.0", server_port=7860, share=False)