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

View File

@@ -34,10 +34,18 @@ class MainActivity : Activity() {
companion object { companion object {
private const val N_CTX = 4096 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. // tsjet's persona: confidently, hilariously wrong.
private const val SYSTEM_PROMPT = "" 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") @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 * 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 { 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 = private const val MODEL_URL =
"https://huggingface.co/HauhauCS/Qwen3.5-2B-Uncensored-HauhauCS-Aggressive" + "https://huggingface.co/HauhauCS/Qwen3.5-2B-Uncensored-HauhauCS-Aggressive" +