Instructions to use FerrellSyntheticIntelligence/fsi-anomaly with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- llama.cpp
How to use FerrellSyntheticIntelligence/fsi-anomaly with llama.cpp:
Install (macOS, Linux)
curl -LsSf https://llama.app/install.sh | sh # Start a local OpenAI-compatible server with a web UI: llama serve -hf FerrellSyntheticIntelligence/fsi-anomaly # Run inference directly in the terminal: llama cli -hf FerrellSyntheticIntelligence/fsi-anomaly
Install from WinGet (Windows)
winget install llama.cpp # Start a local OpenAI-compatible server with a web UI: llama serve -hf FerrellSyntheticIntelligence/fsi-anomaly # Run inference directly in the terminal: llama cli -hf FerrellSyntheticIntelligence/fsi-anomaly
Use pre-built binary
# Download pre-built binary from: # https://github.com/ggerganov/llama.cpp/releases # Start a local OpenAI-compatible server with a web UI: ./llama-server -hf FerrellSyntheticIntelligence/fsi-anomaly # Run inference directly in the terminal: ./llama-cli -hf FerrellSyntheticIntelligence/fsi-anomaly
Build from source code
git clone https://github.com/ggerganov/llama.cpp.git cd llama.cpp cmake -B build cmake --build build -j --target llama-server llama-cli # Start a local OpenAI-compatible server with a web UI: ./build/bin/llama-server -hf FerrellSyntheticIntelligence/fsi-anomaly # Run inference directly in the terminal: ./build/bin/llama-cli -hf FerrellSyntheticIntelligence/fsi-anomaly
Use Docker
docker model run hf.co/FerrellSyntheticIntelligence/fsi-anomaly
- LM Studio
- Jan
- Ollama
How to use FerrellSyntheticIntelligence/fsi-anomaly with Ollama:
ollama run hf.co/FerrellSyntheticIntelligence/fsi-anomaly
- Unsloth Desktop
- Docker Model Runner
How to use FerrellSyntheticIntelligence/fsi-anomaly with Docker Model Runner:
docker model run hf.co/FerrellSyntheticIntelligence/fsi-anomaly
- Lemonade
How to use FerrellSyntheticIntelligence/fsi-anomaly with Lemonade:
Pull the model
# Download Lemonade from https://lemonade-server.ai/ lemonade pull FerrellSyntheticIntelligence/fsi-anomaly
Run and chat with the model
lemonade run user.fsi-anomaly-{{QUANT_TAG}}List all available models
lemonade list
- Atomic Chat
| """TinyLiquid Analyst - neon terminal UI (stdlib curses, zero deps). | |
| An OpenCode-style agent terminal themed like Parrot OS meets Matrix: | |
| near-black background, matrix-green neon, pink/blue/purple accents. | |
| Chat with the analyst/skeptic personas, run SOP-driven cases, search and | |
| read the library, manage case files. | |
| Usage: | |
| .venv/bin/python tui/analyst.py --ckpt ckpt/dpo | |
| .venv/bin/python tui/analyst.py --ckpt ckpt/dpo --case mycase.json | |
| """ | |
| import argparse | |
| import curses | |
| import random | |
| import textwrap | |
| from tui.engine import AnalystEngine | |
| from tui.cli import handle_cmd | |
| WRAP = 78 | |
| # --- neon palette (256-color) --- | |
| C_BG = 0 # terminal default (black) | |
| C_GREEN = 82 # matrix green | |
| C_PINK = 205 | |
| C_BLUE = 39 | |
| C_PURPLE = 141 | |
| C_CYAN = 51 | |
| C_WHITE = 255 | |
| C_DIM = 240 | |
| PAIR = { | |
| "bg": 1, "green": 2, "pink": 3, "blue": 4, "purple": 5, | |
| "cyan": 6, "white": 7, "dim": 8, "user": 9, "model": 10, | |
| "skeptic": 11, "system": 12, "error": 13, "header": 14, | |
| } | |
| def setup_colors(stdscr): | |
| curses.start_color() | |
| curses.use_default_colors() | |
| try: | |
| if curses.COLORS >= 256: | |
| curses.init_pair(PAIR["bg"], C_WHITE, C_BG) | |
| curses.init_pair(PAIR["green"], C_GREEN, C_BG) | |
| curses.init_pair(PAIR["pink"], C_PINK, C_BG) | |
| curses.init_pair(PAIR["blue"], C_BLUE, C_BG) | |
| curses.init_pair(PAIR["purple"], C_PURPLE, C_BG) | |
| curses.init_pair(PAIR["cyan"], C_CYAN, C_BG) | |
| curses.init_pair(PAIR["white"], C_WHITE, C_BG) | |
| curses.init_pair(PAIR["dim"], C_DIM, C_BG) | |
| curses.init_pair(PAIR["user"], C_CYAN, C_BG) | |
| curses.init_pair(PAIR["model"], C_GREEN, C_BG) | |
| curses.init_pair(PAIR["skeptic"], C_PINK, C_BG) | |
| curses.init_pair(PAIR["system"], C_PURPLE, C_BG) | |
| curses.init_pair(PAIR["error"], C_PINK, C_BG) | |
| curses.init_pair(PAIR["header"], C_GREEN, C_BG) | |
| else: | |
| for k in PAIR: | |
| curses.init_pair(PAIR[k], curses.COLOR_WHITE, curses.COLOR_BLACK) | |
| curses.init_pair(PAIR["green"], curses.COLOR_GREEN, curses.COLOR_BLACK) | |
| curses.init_pair(PAIR["pink"], curses.COLOR_RED, curses.COLOR_BLACK) | |
| curses.init_pair(PAIR["blue"], curses.COLOR_CYAN, curses.COLOR_BLACK) | |
| curses.init_pair(PAIR["purple"], curses.COLOR_MAGENTA, curses.COLOR_BLACK) | |
| curses.init_pair(PAIR["cyan"], curses.COLOR_CYAN, curses.COLOR_BLACK) | |
| curses.init_pair(PAIR["user"], curses.COLOR_CYAN, curses.COLOR_BLACK) | |
| curses.init_pair(PAIR["model"], curses.COLOR_GREEN, curses.COLOR_BLACK) | |
| curses.init_pair(PAIR["skeptic"], curses.COLOR_RED, curses.COLOR_BLACK) | |
| curses.init_pair(PAIR["system"], curses.COLOR_MAGENTA, curses.COLOR_BLACK) | |
| curses.init_pair(PAIR["error"], curses.COLOR_RED, curses.COLOR_BLACK) | |
| curses.init_pair(PAIR["header"], curses.COLOR_GREEN, curses.COLOR_BLACK) | |
| except curses.error: | |
| pass | |
| def wrap(text, width): | |
| return "\n".join(textwrap.fill(p, width) for p in text.splitlines()) or " " | |
| class Rain: | |
| """Minimal matrix-rain strip for the header (lightweight, idle-animated).""" | |
| def __init__(self, width, rows=1): | |
| self.width = max(1, width) | |
| self.rows = rows | |
| self.cols = [random.randint(0, self.width - 1) for _ in range(self.rows)] | |
| def frame(self): | |
| chars = [" "] * self.width | |
| for i, c in enumerate(self.cols): | |
| if random.random() < 0.75: | |
| chars[c] = random.choice("01$#&@!?ABCDEF") | |
| self.cols[i] = (c + random.choice([-1, 0, 1])) % self.width | |
| return "".join(chars) | |
| class TerminalUI: | |
| def __init__(self, stdscr, eng): | |
| self.stdscr = stdscr | |
| self.eng = eng | |
| self.lines = [] # list of (kind, text) | |
| self.history = [] | |
| self.hist_idx = -1 | |
| self.scroll = 0 | |
| self.input_text = "" | |
| self.cursor = 0 | |
| self.rain = Rain(10) | |
| self.status = f"persona: analyst | case: {eng.case.name}" | |
| def add(self, kind, text): | |
| for ln in wrap(text, WRAP).splitlines() or [""]: | |
| self.lines.append((kind, ln)) | |
| self.scroll = 0 | |
| def header(self, wd): | |
| title = " TINYLIQUID ANALYST " | |
| left = (wd - len(title)) // 2 | |
| top = "═" * wd | |
| line = " " * left + title | |
| return top, line[:wd], self.rain.frame()[:wd] | |
| def draw(self): | |
| h, wd = self.stdscr.getmaxyx() | |
| top, title, rain = self.header(wd) | |
| body_h = max(1, h - 6) | |
| self.stdscr.erase() | |
| self.stdscr.addnstr(0, 0, top[:wd], wd, curses.color_pair(PAIR["purple"])) | |
| self.stdscr.addnstr(1, 0, title[:wd], wd, curses.color_pair(PAIR["header"])) | |
| self.stdscr.addnstr(2, 0, rain[:wd], wd, curses.color_pair(PAIR["green"])) | |
| start = len(self.lines) - body_h - self.scroll | |
| start = max(0, min(start, max(0, len(self.lines) - body_h))) | |
| for i in range(body_h): | |
| idx = start + i | |
| if idx < len(self.lines): | |
| kind, ln = self.lines[idx] | |
| pair = {"user": PAIR["user"], "model": PAIR["model"], | |
| "skeptic": PAIR["skeptic"], "system": PAIR["system"], | |
| "error": PAIR["error"]}.get(kind, PAIR["white"]) | |
| self.stdscr.addnstr(3 + i, 0, ln[:wd], wd, curses.color_pair(pair)) | |
| self.stdscr.addnstr(h - 3, 0, "─" * wd, wd, curses.color_pair(PAIR["purple"])) | |
| self.stdscr.addnstr(h - 2, 0, self.status[:wd], wd, | |
| curses.color_pair(PAIR["system"]) | curses.A_REVERSE) | |
| prompt = "❯ " | |
| self.stdscr.addnstr(h - 1, 0, prompt + self.input_text[:wd - len(prompt) - 1], wd, | |
| curses.color_pair(PAIR["green"])) | |
| try: | |
| self.stdscr.move(h - 1, min(self.cursor + len(prompt), wd - 1)) | |
| except curses.error: | |
| pass | |
| self.stdscr.refresh() | |
| def run_cmd(self, cmd): | |
| if cmd in ("/quit", "/exit", "/q"): | |
| return False | |
| if cmd == "/clear": | |
| self.lines = [] | |
| self.add("system", "cleared.") | |
| return True | |
| self.add("user", cmd if cmd.startswith("/") else "you> " + cmd) | |
| if not cmd.startswith("/"): | |
| # streamed chat: redraw as tokens arrive | |
| buf = [] | |
| self.lines.append(("model", "…")) | |
| try: | |
| def on_token(tok_id): | |
| buf.append(tok_id) | |
| self.lines[-1] = ("model", self.eng.tok.decode(buf)) | |
| self.draw() | |
| self.eng.chat(cmd, on_token=on_token) | |
| except Exception as e: | |
| self.lines[-1] = ("error", f"error: {e}") | |
| self.draw() | |
| return True | |
| self.lines[-1] = ("model", self.eng.tok.decode(buf)) | |
| self.draw() | |
| return True | |
| try: | |
| out = handle_cmd(self.eng, cmd) | |
| except Exception as e: | |
| out = f"error: {e}" | |
| self.add("error", out) | |
| return True | |
| kind = "skeptic" if cmd.startswith(("/skeptic",)) else "model" | |
| # render JSON reports nicely | |
| if out.strip().startswith("{") or out.strip().startswith("["): | |
| import json as _json | |
| try: | |
| data = _json.loads(out) | |
| out = _json.dumps(data, indent=2, ensure_ascii=False) | |
| except Exception: | |
| pass | |
| for ln in out.splitlines(): | |
| self.add(kind, ln) | |
| return True | |
| def loop(self): | |
| setup_colors(self.stdscr) | |
| curses.curs_set(1) | |
| self.stdscr.timeout(80) | |
| self.add("system", "TinyLiquid Analyst — on-device forensic research terminal") | |
| self.add("dim", "Authorized research/OSINT only. Outputs are decision support, never a verdict.") | |
| self.add("dim", "type /help for commands | /quit to exit") | |
| while True: | |
| self.draw() | |
| try: | |
| ch = self.stdscr.get_wch() | |
| except curses.error: | |
| continue | |
| if ch in ("\n", "\r", "KEY_ENTER"): | |
| cmd = self.input_text.strip() | |
| self.input_text, self.cursor = "", 0 | |
| self.history.append(cmd) | |
| self.hist_idx = len(self.history) | |
| if cmd and not self.run_cmd(cmd): | |
| break | |
| continue | |
| if ch in ("\x7f", "KEY_BACKSPACE"): | |
| if self.cursor > 0: | |
| self.input_text = self.input_text[:self.cursor - 1] + self.input_text[self.cursor:] | |
| self.cursor -= 1 | |
| continue | |
| if ch == "KEY_DC": | |
| self.input_text = self.input_text[:self.cursor] + self.input_text[self.cursor + 1:] | |
| continue | |
| if ch == "KEY_LEFT": | |
| self.cursor = max(0, self.cursor - 1) | |
| continue | |
| if ch == "KEY_RIGHT": | |
| self.cursor = min(len(self.input_text), self.cursor + 1) | |
| continue | |
| if ch == "KEY_HOME": | |
| self.cursor = 0 | |
| continue | |
| if ch == "KEY_END": | |
| self.cursor = len(self.input_text) | |
| continue | |
| if ch in ("KEY_PPAGE",): | |
| self.scroll = min(self.scroll + 5, max(0, len(self.lines) - 1)) | |
| continue | |
| if ch in ("KEY_NPAGE",): | |
| self.scroll = max(0, self.scroll - 5) | |
| continue | |
| if ch == "KEY_UP": | |
| if self.history and self.hist_idx > 0: | |
| self.hist_idx -= 1 | |
| self.input_text = self.history[self.hist_idx] | |
| self.cursor = len(self.input_text) | |
| continue | |
| if ch == "KEY_DOWN": | |
| if self.history and self.hist_idx < len(self.history) - 1: | |
| self.hist_idx += 1 | |
| self.input_text = self.history[self.hist_idx] | |
| self.cursor = len(self.input_text) | |
| else: | |
| self.input_text, self.hist_idx = "", len(self.history) | |
| continue | |
| if isinstance(ch, str) and ch.isprintable(): | |
| self.input_text = self.input_text[:self.cursor] + ch + self.input_text[self.cursor:] | |
| self.cursor += 1 | |
| def main(): | |
| ap = argparse.ArgumentParser() | |
| ap.add_argument("--ckpt", default="ckpt/v8_lora/best.pt") | |
| ap.add_argument("--tok", default="data/tokenizer.json") | |
| ap.add_argument("--case", default=None) | |
| ap.add_argument("--threads", type=int, default=4) | |
| args = ap.parse_args() | |
| eng = AnalystEngine(ckpt=args.ckpt, tok_path=args.tok, threads=args.threads) | |
| if args.case: | |
| eng.load_case(args.case) | |
| def go(stdscr): | |
| ui = TerminalUI(stdscr, eng) | |
| ui.status = f"persona: {eng.persona} | case: {eng.case.name} | {eng.ckpt}" | |
| ui.loop() | |
| try: | |
| curses.wrapper(go) | |
| except KeyboardInterrupt: | |
| pass | |
| print("session ended.") | |
| if __name__ == "__main__": | |
| main() | |