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:
@@ -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); } }
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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" +
|
||||
|
||||
Reference in New Issue
Block a user