fableforge-ai/ghost-writer
4
1import os2import re3 4# ---- Fix gradio 4.44 / gradio_client schema bug (bool not iterable) ----5import gradio_client.utils as _gcu6_orig_j2p = _gcu._json_schema_to_python_type7def _safe_j2p(schema, defs=None):8 if isinstance(schema, bool):9 return "bool"10 return _orig_j2p(schema, defs)11_gcu._json_schema_to_python_type = _safe_j2p12_orig_gt = _gcu.get_type13def _safe_gt(schema):14 if not isinstance(schema, dict):15 return "any"16 return _orig_gt(schema)17_gcu.get_type = _safe_gt18 19import gradio as gr20from llama_cpp import Llama21 22MODEL_REPO = "King3Djbl/mythos-9b-unhinged"23GGUF_FILE = "mythos-9b-unhinged-Q4_K_M.gguf"24 25print("Loading", MODEL_REPO, GGUF_FILE)26llm = Llama.from_pretrained(27 repo_id=MODEL_REPO,28 filename=GGUF_FILE,29 n_ctx=2048,30 n_threads=os.cpu_count(),31 chat_format="chatml",32 verbose=False,33)34print("Model loaded.")35 36 37def chat(messages, max_tokens=220, temperature=0.9):38 out = llm.create_chat_completion(39 messages=messages, max_tokens=max_tokens, temperature=temperature, top_p=0.9,40 )41 return out["choices"][0]["message"]["content"].strip()42 43FOOTER = '---\n### 🌌 More FableForge demos\n🍺 [Infinite NPC](https://huggingface.co/spaces/fableforge-ai/infinite-npc) · 👻 [Ghost Writer](https://huggingface.co/spaces/fableforge-ai/ghost-writer) · 🌳 [Story Tree](https://huggingface.co/spaces/fableforge-ai/semantic-story-tree) · 🎭 [Dual-GM](https://huggingface.co/spaces/King3Djbl/dual-gm-simulator) · 🧭 [**Nexus hub →**](https://huggingface.co/spaces/fableforge-ai/fableforge-nexus)\n\n⬇️ [**Download the model**](https://huggingface.co/King3Djbl/mythos-9b-unhinged) · 🐦 [Share on X](https://twitter.com/intent/tweet?text=%F0%9F%94%AE%20FableForge%3A%20a%20galaxy%20of%20live%20AI%20demos%20powered%20by%20one%20open%209B%20model.%20Play%20them%20free%3A&url=https%3A//huggingface.co/spaces/fableforge-ai/fableforge-nexus) · 👽 [Post to Reddit](https://www.reddit.com/submit?url=https%3A//huggingface.co/spaces/fableforge-ai/fableforge-nexus&title=%F0%9F%94%AE%20FableForge%3A%20a%20galaxy%20of%20live%20AI%20demos%20powered%20by%20one%20open%209B%20model.%20Play%20them%20free%3A)\n\n*One open model. Infinite worlds. ⭐ Like this Space to boost it.*'44 45STYLES = ["Match my style", "Literary", "Hardboiled noir", "Whimsical fairytale", "Cosmic horror", "Punchy thriller"]46 47 48def ghost(draft, style, length):49 draft = draft or ""50 sys = "You are a ghost co-writer. Continue the user's text SEAMLESSLY from exactly where it stops. "51 sys += "Do not repeat their text, do not add commentary — output only the continuation. "52 if style and style != "Match my style":53 sys += "Write in this style: " + style + ". "54 cont = chat(55 [{"role": "system", "content": sys},56 {"role": "user", "content": draft if draft.strip() else "Begin a story."}],57 max_tokens=int(length), temperature=0.9,58 )59 joiner = "" if (not draft or draft.endswith((" ", "\n"))) else " "60 return (draft + joiner + cont).strip()61 62 63with gr.Blocks(title="Ghost Writer", theme=gr.themes.Soft(primary_hue="slate")) as demo:64 gr.Markdown(65 "# 👻 Ghost Writer\n"66 "Write a little, then let the ghost continue your prose. Keep hitting **Continue** to co-write.\n"67 "> ⏳ Free CPU — each continuation takes ~15-30s."68 )69 text = gr.Textbox(label="Your manuscript", lines=16,70 placeholder="The lighthouse keeper hadn't spoken to another soul in three winters, until…")71 with gr.Row():72 style = gr.Dropdown(STYLES, value="Match my style", label="Voice", scale=2)73 length = gr.Slider(40, 300, value=120, step=20, label="Continue by (tokens)", scale=2)74 go = gr.Button("👻 Continue", variant="primary", scale=1)75 go.click(ghost, [text, style, length], text)76 gr.Markdown(FOOTER)77 78if __name__ == "__main__":79 demo.queue(default_concurrency_limit=1).launch(server_name="0.0.0.0", server_port=7860, show_api=False)80 