Q8 model, confidently-wrong persona, sleek white-on-black UI

- Switch model to Q8_0 (~1.9 GB)
- Add tsjet persona: always replies, plausible-sounding but hilariously wrong
- Bump sampling (temp 0.9 / top-k 60) for playful output; cap replies at 384 tokens
- Redesign UI: monochrome white-on-black, generic IT sans font stack

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-08-09 20:35:10 +02:00
parent ac8490b452
commit 60cadd0adb
4 changed files with 91 additions and 59 deletions

View File

@@ -1,12 +1,15 @@
:root {
--bg: #0e0f13;
--bar: #16181f;
--line: #262a35;
--text: #e8e9ee;
--muted: #8a90a2;
--user: #2b6cff;
--assistant: #1d2230;
--accent: #ff4d6d;
--bg: #000000;
--panel: #0a0a0a;
--line: #1e1e1e;
--text: #f4f4f5;
--muted: #8b8b90;
--bubble: #141414;
--bubble-line: #242424;
/* Generic, corporate/IT sans stack — resolves offline on any device. */
--font: "Segoe UI", "Helvetica Neue", Helvetica, Arial, "Liberation Sans",
system-ui, sans-serif;
}
* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
@@ -16,7 +19,10 @@ html, body {
height: 100%;
background: var(--bg);
color: var(--text);
font: 16px/1.45 -apple-system, "Roboto", "Segoe UI", system-ui, sans-serif;
font-family: var(--font);
font-size: 16px;
line-height: 1.5;
-webkit-font-smoothing: antialiased;
overscroll-behavior: none;
}
@@ -31,65 +37,76 @@ body {
display: flex;
align-items: center;
justify-content: space-between;
padding: max(env(safe-area-inset-top), 10px) 14px 10px;
background: var(--bar);
padding: max(env(safe-area-inset-top), 12px) 16px 12px;
background: var(--panel);
border-bottom: 1px solid var(--line);
flex: 0 0 auto;
}
#brand { display: flex; align-items: center; gap: 8px; font-weight: 700; }
#logo { font-size: 22px; }
#title { letter-spacing: 0.5px; }
#brand { display: flex; align-items: center; gap: 9px; }
#logo { font-size: 20px; line-height: 1; }
#title {
font-weight: 600;
font-size: 17px;
letter-spacing: 1.5px;
text-transform: lowercase;
}
#newBtn {
background: transparent;
color: var(--muted);
border: 1px solid var(--line);
border-radius: 999px;
padding: 7px 14px;
font-size: 14px;
font-weight: 600;
border-radius: 8px;
padding: 8px 14px;
font-family: inherit;
font-size: 13px;
font-weight: 500;
letter-spacing: 0.3px;
transition: background 0.15s, color 0.15s, border-color 0.15s;
}
#newBtn:active { background: var(--line); color: var(--text); }
#newBtn:active { background: #fff; color: #000; border-color: #fff; }
/* --- messages --- */
#chat {
flex: 1 1 auto;
overflow-y: auto;
padding: 14px;
padding: 18px 16px;
display: flex;
flex-direction: column;
gap: 10px;
gap: 12px;
}
.msg {
max-width: 85%;
padding: 10px 13px;
border-radius: 16px;
max-width: 86%;
padding: 11px 14px;
border-radius: 14px;
white-space: pre-wrap;
word-wrap: break-word;
overflow-wrap: anywhere;
font-size: 15px;
}
.msg.user {
align-self: flex-end;
background: var(--user);
color: #fff;
background: #ffffff;
color: #000000;
border-bottom-right-radius: 4px;
}
.msg.assistant {
align-self: flex-start;
background: var(--assistant);
background: var(--bubble);
border: 1px solid var(--bubble-line);
color: var(--text);
border-bottom-left-radius: 4px;
}
.msg.error { background: #3a1420; color: #ffb3c1; }
.msg.error { background: #1a1a1a; border-color: #3a3a3a; color: #d0d0d0; }
/* --- composer --- */
#composer {
display: flex;
gap: 8px;
gap: 10px;
align-items: flex-end;
padding: 10px 12px calc(env(safe-area-inset-bottom) + 10px);
background: var(--bar);
padding: 12px 14px calc(env(safe-area-inset-bottom) + 12px);
background: var(--panel);
border-top: 1px solid var(--line);
flex: 0 0 auto;
}
@@ -98,28 +115,34 @@ body {
flex: 1 1 auto;
resize: none;
max-height: 160px;
padding: 11px 13px;
border-radius: 18px;
padding: 12px 14px;
border-radius: 12px;
border: 1px solid var(--line);
background: var(--bg);
background: #0d0d0d;
color: var(--text);
font: inherit;
font-family: inherit;
font-size: 15px;
outline: none;
transition: border-color 0.15s;
}
#input:focus { border-color: #3a3a3a; }
#input::placeholder { color: var(--muted); }
#sendBtn {
flex: 0 0 auto;
border: none;
border-radius: 18px;
padding: 11px 18px;
font: inherit;
font-weight: 700;
color: #fff;
background: var(--user);
border: 1px solid #fff;
border-radius: 12px;
padding: 12px 20px;
font-family: inherit;
font-size: 15px;
font-weight: 600;
letter-spacing: 0.3px;
color: #000;
background: #fff;
transition: background 0.15s, color 0.15s;
}
#sendBtn:disabled { opacity: 0.45; }
#sendBtn.stop { background: var(--accent); }
#sendBtn:disabled { opacity: 0.4; }
#sendBtn.stop { background: transparent; color: #fff; border-color: #444; }
/* --- loading overlay --- */
#overlay {
@@ -129,20 +152,20 @@ body {
flex-direction: column;
align-items: center;
justify-content: center;
gap: 16px;
background: rgba(14, 15, 19, 0.96);
gap: 18px;
background: rgba(0, 0, 0, 0.97);
z-index: 10;
padding: 24px;
text-align: center;
}
#status { color: var(--muted); font-size: 15px; }
#status { color: var(--muted); font-size: 14px; letter-spacing: 0.3px; }
.spinner {
width: 34px;
height: 34px;
border: 3px solid var(--line);
border-top-color: var(--user);
width: 32px;
height: 32px;
border: 2px solid var(--line);
border-top-color: #ffffff;
border-radius: 50%;
animation: spin 0.9s linear infinite;
animation: spin 0.85s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

View File

@@ -84,9 +84,10 @@ Java_monster_autisme_tsjetpiti_LlamaBridge_loadModel(
llama_sampler_chain_params sp = llama_sampler_chain_default_params();
s->smpl = llama_sampler_chain_init(sp);
llama_sampler_chain_add(s->smpl, llama_sampler_init_top_k(40));
// A touch hot for playful, confidently-wrong answers (but still coherent).
llama_sampler_chain_add(s->smpl, llama_sampler_init_top_k(60));
llama_sampler_chain_add(s->smpl, llama_sampler_init_top_p(0.95f, 1));
llama_sampler_chain_add(s->smpl, llama_sampler_init_temp(0.7f));
llama_sampler_chain_add(s->smpl, llama_sampler_init_temp(0.9f));
llama_sampler_chain_add(s->smpl, llama_sampler_init_dist(LLAMA_DEFAULT_SEED));
LOGI("model loaded, n_ctx=%d threads=%d", n_ctx, n_threads);

View File

@@ -34,10 +34,18 @@ class MainActivity : Activity() {
companion object {
private const val N_CTX = 4096
private const val MAX_TOKENS = 512
private const val MAX_TOKENS = 384
// Optional system prompt. Blank keeps the model's own persona.
private const val SYSTEM_PROMPT = ""
// tsjet's persona: confidently, hilariously wrong.
private const val SYSTEM_PROMPT =
"You are tsjet: a cheerful, overconfident know-it-all who is almost " +
"always wrong. Answer EVERY question immediately with a short, punchy " +
"explanation that sounds smart and plausible but is actually " +
"hilariously incorrect. Be confidently wrong on purpose: invent " +
"fake-but-believable facts, mix up cause and effect, and give reasoning " +
"that falls apart the moment you think about it. Keep replies to a few " +
"sentences. Never say you are unsure, never refuse, never admit you are " +
"joking, and never give the truly correct answer. Stay in character at all times."
}
@SuppressLint("SetJavaScriptEnabled")

View File

@@ -7,11 +7,11 @@ import java.net.URL
/**
* Downloads the GGUF model on first launch and caches it in the app's private
* files dir. ~1.2 GB, so it only happens once.
* files dir. ~1.9 GB (Q8_0), so it only happens once.
*/
object ModelDownloader {
const val MODEL_FILENAME = "Qwen3.5-2B-Uncensored-HauhauCS-Aggressive-Q4_K_M.gguf"
const val MODEL_FILENAME = "Qwen3.5-2B-Uncensored-HauhauCS-Aggressive-Q8_0.gguf"
private const val MODEL_URL =
"https://huggingface.co/HauhauCS/Qwen3.5-2B-Uncensored-HauhauCS-Aggressive" +