Instructions to use saik0s/comfy_backup with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- llama-cpp-python
How to use saik0s/comfy_backup with llama-cpp-python:
# !pip install llama-cpp-python from llama_cpp import Llama llm = Llama.from_pretrained( repo_id="saik0s/comfy_backup", filename="ComfyUI/models/text_encoders/gemma-3-12b-it-q2_k.gguf", )
llm.create_chat_completion( messages = "No input example has been defined for this model task." )
- Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- llama.cpp
How to use saik0s/comfy_backup 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 saik0s/comfy_backup:Q4_K_S # Run inference directly in the terminal: llama cli -hf saik0s/comfy_backup:Q4_K_S
Install from WinGet (Windows)
winget install llama.cpp # Start a local OpenAI-compatible server with a web UI: llama serve -hf saik0s/comfy_backup:Q4_K_S # Run inference directly in the terminal: llama cli -hf saik0s/comfy_backup:Q4_K_S
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 saik0s/comfy_backup:Q4_K_S # Run inference directly in the terminal: ./llama-cli -hf saik0s/comfy_backup:Q4_K_S
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 saik0s/comfy_backup:Q4_K_S # Run inference directly in the terminal: ./build/bin/llama-cli -hf saik0s/comfy_backup:Q4_K_S
Use Docker
docker model run hf.co/saik0s/comfy_backup:Q4_K_S
- LM Studio
- Jan
- Ollama
How to use saik0s/comfy_backup with Ollama:
ollama run hf.co/saik0s/comfy_backup:Q4_K_S
- Unsloth Studio
How to use saik0s/comfy_backup with Unsloth Studio:
Install Unsloth Studio (macOS, Linux, WSL)
curl -fsSL https://unsloth.ai/install.sh | sh # Run unsloth studio unsloth studio -H 0.0.0.0 -p 8888 # Then open http://localhost:8888 in your browser # Search for saik0s/comfy_backup to start chatting
Install Unsloth Studio (Windows)
irm https://unsloth.ai/install.ps1 | iex # Run unsloth studio unsloth studio -H 0.0.0.0 -p 8888 # Then open http://localhost:8888 in your browser # Search for saik0s/comfy_backup to start chatting
Using HuggingFace Spaces for Unsloth
# No setup required # Open https://huggingface.co/spaces/unsloth/studio in your browser # Search for saik0s/comfy_backup to start chatting
- Pi
How to use saik0s/comfy_backup with Pi:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf saik0s/comfy_backup:Q4_K_S
Configure the model in Pi
# Install Pi: npm install -g @mariozechner/pi-coding-agent # Add to ~/.pi/agent/models.json: { "providers": { "llama-cpp": { "baseUrl": "http://localhost:8080/v1", "api": "openai-completions", "apiKey": "none", "models": [ { "id": "saik0s/comfy_backup:Q4_K_S" } ] } } }Run Pi
# Start Pi in your project directory: pi
- Hermes Agent new
How to use saik0s/comfy_backup with Hermes Agent:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf saik0s/comfy_backup:Q4_K_S
Configure Hermes
# Install Hermes: curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash hermes setup # Point Hermes at the local server: hermes config set model.provider custom hermes config set model.base_url http://127.0.0.1:8080/v1 hermes config set model.default saik0s/comfy_backup:Q4_K_S
Run Hermes
hermes
- Atomic Chat new
- OpenClaw new
How to use saik0s/comfy_backup with OpenClaw:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf saik0s/comfy_backup:Q4_K_S
Configure OpenClaw
# Install OpenClaw: npm install -g openclaw@latest # Register the local server and set it as the default model: openclaw onboard --non-interactive --mode local \ --auth-choice custom-api-key \ --custom-base-url http://127.0.0.1:8080/v1 \ --custom-model-id "saik0s/comfy_backup:Q4_K_S" \ --custom-provider-id llama-cpp \ --custom-compatibility openai \ --custom-text-input \ --accept-risk \ --skip-health
Run OpenClaw
openclaw agent --local --agent main --message "Hello from Hugging Face"
- Docker Model Runner
How to use saik0s/comfy_backup with Docker Model Runner:
docker model run hf.co/saik0s/comfy_backup:Q4_K_S
- Lemonade
How to use saik0s/comfy_backup with Lemonade:
Pull the model
# Download Lemonade from https://lemonade-server.ai/ lemonade pull saik0s/comfy_backup:Q4_K_S
Run and chat with the model
lemonade run user.comfy_backup-Q4_K_S
List all available models
lemonade list
| import type {INodeInputSlot, LGraphNodeConstructor} from "@comfyorg/frontend"; | |
| import type {ComfyNodeDef} from "typings/comfy.js"; | |
| import {app} from "scripts/app.js"; | |
| import {BaseContextNode} from "./context.js"; | |
| import {RgthreeBaseServerNode} from "./base_node.js"; | |
| import {moveArrayItem, wait} from "rgthree/common/shared_utils.js"; | |
| import {RgthreeInvisibleWidget} from "./utils_widgets.js"; | |
| import { | |
| getContextOutputName, | |
| InputMutation, | |
| InputMutationOperation, | |
| } from "./services/context_service.js"; | |
| import {SERVICE as CONTEXT_SERVICE} from "./services/context_service.js"; | |
| const OWNED_PREFIX = "+"; | |
| const REGEX_OWNED_PREFIX = /^\+\s*/; | |
| const REGEX_EMPTY_INPUT = /^\+\s*$/; | |
| export type InputLike = { | |
| name: string; | |
| type: number | string; | |
| label?: string; | |
| link: number | null; | |
| removable?: boolean; | |
| boundingRect: any; | |
| }; | |
| /** | |
| * The base context node that contains some shared between DynamicContext nodes. Not labels | |
| * `abstract` so we can reference `this` in static methods. | |
| */ | |
| export class DynamicContextNodeBase extends BaseContextNode { | |
| protected readonly hasShadowInputs: boolean = false; | |
| getContextInputsList(): InputLike[] { | |
| return this.inputs; | |
| } | |
| provideInputsData() { | |
| const inputs = this.getContextInputsList(); | |
| return inputs | |
| .map((input, index) => ({ | |
| name: this.stripOwnedPrefix(input.name), | |
| type: String(input.type), | |
| index, | |
| })) | |
| .filter((i) => i.type !== "*"); | |
| } | |
| addOwnedPrefix(name: string) { | |
| return `+ ${this.stripOwnedPrefix(name)}`; | |
| } | |
| isOwnedInput(inputOrName: string | null | INodeInputSlot) { | |
| const name = typeof inputOrName == "string" ? inputOrName : inputOrName?.name || ""; | |
| return REGEX_OWNED_PREFIX.test(name); | |
| } | |
| stripOwnedPrefix(name: string) { | |
| return name.replace(REGEX_OWNED_PREFIX, ""); | |
| } | |
| // handleUpstreamMutation(mutation: InputMutation) { | |
| // throw new Error('handleUpstreamMutation not overridden!') | |
| // } | |
| handleUpstreamMutation(mutation: InputMutation) { | |
| console.log(`[node ${this.id}] handleUpstreamMutation`, mutation); | |
| if (mutation.operation === InputMutationOperation.ADDED) { | |
| const slot = mutation.slot; | |
| if (!slot) { | |
| throw new Error("Cannot have an ADDED mutation without a provided slot data."); | |
| } | |
| this.addContextInput( | |
| this.stripOwnedPrefix(slot.name), | |
| slot.type as string, | |
| mutation.slotIndex, | |
| ); | |
| return; | |
| } | |
| if (mutation.operation === InputMutationOperation.REMOVED) { | |
| const slot = mutation.slot; | |
| if (!slot) { | |
| throw new Error("Cannot have an REMOVED mutation without a provided slot data."); | |
| } | |
| this.removeContextInput(mutation.slotIndex); | |
| return; | |
| } | |
| if (mutation.operation === InputMutationOperation.RENAMED) { | |
| const slot = mutation.slot; | |
| if (!slot) { | |
| throw new Error("Cannot have an RENAMED mutation without a provided slot data."); | |
| } | |
| this.renameContextInput(mutation.slotIndex, slot.name); | |
| return; | |
| } | |
| } | |
| override clone() { | |
| const cloned = super.clone()! as DynamicContextNodeBase; | |
| while (cloned.inputs.length > 1) { | |
| cloned.removeInput(cloned.inputs.length - 1); | |
| } | |
| while (cloned.widgets.length > 1) { | |
| cloned.removeWidget(cloned.widgets.length - 1); | |
| } | |
| while (cloned.outputs.length > 1) { | |
| cloned.removeOutput(cloned.outputs.length - 1); | |
| } | |
| return cloned; | |
| } | |
| /** | |
| * Adds the basic output_keys widget. Should be called _after_ specific nodes setup their inputs | |
| * or widgets. | |
| */ | |
| override onNodeCreated() { | |
| const node = this; | |
| this.addCustomWidget( | |
| new RgthreeInvisibleWidget("output_keys", "RGTHREE_DYNAMIC_CONTEXT_OUTPUTS", "", () => { | |
| return (node.outputs || []) | |
| .map((o, i) => i > 0 && o.name) | |
| .filter((n) => n !== false) | |
| .join(","); | |
| }), | |
| ); | |
| } | |
| addContextInput(name: string, type: string, slot = -1) { | |
| const inputs = this.getContextInputsList(); | |
| if (this.hasShadowInputs) { | |
| inputs.push({name, type, link: null, boundingRect: null}); | |
| } else { | |
| this.addInput(name, type); | |
| } | |
| if (slot > -1) { | |
| moveArrayItem(inputs, inputs.length - 1, slot); | |
| } else { | |
| slot = inputs.length - 1; | |
| } | |
| if (type !== "*") { | |
| const output = this.addOutput(getContextOutputName(name), type); | |
| if (type === "COMBO" || String(type).includes(",") || Array.isArray(type)) { | |
| (output as any).widget = true; | |
| } | |
| if (slot > -1) { | |
| moveArrayItem(this.outputs, this.outputs.length - 1, slot); | |
| } | |
| } | |
| this.fixInputsOutputsLinkSlots(); | |
| this.inputsMutated({ | |
| operation: InputMutationOperation.ADDED, | |
| node: this, | |
| slotIndex: slot, | |
| slot: inputs[slot]!, | |
| }); | |
| } | |
| removeContextInput(slotIndex: number) { | |
| if (this.hasShadowInputs) { | |
| const inputs = this.getContextInputsList(); | |
| const input = inputs.splice(slotIndex, 1)[0]; | |
| if (this.outputs[slotIndex]) { | |
| this.removeOutput(slotIndex); | |
| } | |
| } else { | |
| this.removeInput(slotIndex); | |
| } | |
| } | |
| renameContextInput(index: number, newName: string, forceOwnBool: boolean | null = null) { | |
| const inputs = this.getContextInputsList(); | |
| const input = inputs[index]!; | |
| const oldName = input.name; | |
| newName = this.stripOwnedPrefix(newName.trim() || this.getSlotDefaultInputLabel(index)); | |
| if (forceOwnBool === true || (this.isOwnedInput(oldName) && forceOwnBool !== false)) { | |
| newName = this.addOwnedPrefix(newName); | |
| } | |
| if (oldName !== newName) { | |
| input.name = newName; | |
| input.removable = this.isOwnedInput(newName); | |
| this.outputs[index]!.name = getContextOutputName(inputs[index]!.name); | |
| this.inputsMutated({ | |
| node: this, | |
| operation: InputMutationOperation.RENAMED, | |
| slotIndex: index, | |
| slot: input, | |
| }); | |
| } | |
| } | |
| getSlotDefaultInputLabel(slotIndex: number) { | |
| const inputs = this.getContextInputsList(); | |
| const input = inputs[slotIndex]!; | |
| let defaultLabel = this.stripOwnedPrefix(input.name).toLowerCase(); | |
| return defaultLabel.toLocaleLowerCase(); | |
| } | |
| inputsMutated(mutation: InputMutation) { | |
| CONTEXT_SERVICE.onInputChanges(this, mutation); | |
| } | |
| fixInputsOutputsLinkSlots() { | |
| if (!this.hasShadowInputs) { | |
| const inputs = this.getContextInputsList(); | |
| for (let index = inputs.length - 1; index > 0; index--) { | |
| const input = inputs[index]!; | |
| if ((input === null || input === void 0 ? void 0 : input.link) != null) { | |
| app.graph.links[input.link!]!.target_slot = index; | |
| } | |
| } | |
| } | |
| const outputs = this.outputs; | |
| for (let index = outputs.length - 1; index > 0; index--) { | |
| const output = outputs[index]; | |
| if (output) { | |
| output.nameLocked = true; | |
| for (const link of output.links || []) { | |
| app.graph.links[link!]!.origin_slot = index; | |
| } | |
| } | |
| } | |
| } | |
| static override setUp(comfyClass: typeof LGraphNode, nodeData: ComfyNodeDef) { | |
| RgthreeBaseServerNode.registerForOverride(comfyClass, nodeData, this); | |
| // [🤮] ComfyUI only adds "required" inputs to the outputs list when dragging an output to | |
| // empty space, but since RGTHREE_CONTEXT is optional, it doesn't get added to the menu because | |
| // ...of course. So, we'll manually add it. Of course, we also have to do this in a timeout | |
| // because ComfyUI clears out `LiteGraph.slot_types_default_out` in its own 'Comfy.SlotDefaults' | |
| // extension and we need to wait for that to happen. | |
| wait(500).then(() => { | |
| LiteGraph.slot_types_default_out["RGTHREE_DYNAMIC_CONTEXT"] = | |
| LiteGraph.slot_types_default_out["RGTHREE_DYNAMIC_CONTEXT"] || []; | |
| const comfyClassStr = (comfyClass as LGraphNodeConstructor).comfyClass; | |
| if (comfyClassStr) { | |
| LiteGraph.slot_types_default_out["RGTHREE_DYNAMIC_CONTEXT"].push(comfyClassStr); | |
| } | |
| }); | |
| } | |
| } | |