diff --git a/BasicOllama.png b/BasicOllama.png index 91a47a2..0bb0fb8 100644 Binary files a/BasicOllama.png and b/BasicOllama.png differ diff --git a/BasicOllama.py b/BasicOllama.py index 1af45a6..59f0f2a 100644 --- a/BasicOllama.py +++ b/BasicOllama.py @@ -116,11 +116,6 @@ class BasicOllama: "system_prompt": ("STRING", {"default": "", "multiline": True}), }, "optional": { - "image1": ("IMAGE",), - "image2": ("IMAGE",), - "image3": ("IMAGE",), - "image4": ("IMAGE",), - "image5": ("IMAGE",), } } @@ -129,7 +124,7 @@ class BasicOllama: FUNCTION = "generate_content" CATEGORY = "Ollama" - def generate_content(self, prompt, ollama_model, keep_alive, use_sys_prompt_below, saved_sys_prompt, system_prompt, image1=None, image2=None, image3=None, image4=None, image5=None): + def generate_content(self, prompt, ollama_model, keep_alive, use_sys_prompt_below, saved_sys_prompt, system_prompt, **kwargs): if not ollama_model: return ("Ollama models not found. Is Ollama running?",) @@ -155,7 +150,7 @@ class BasicOllama: if system_prompt_content: payload["system"] = system_prompt_content - all_images = [image1, image2, image3, image4, image5] + all_images = [kwargs[key] for key in sorted(kwargs.keys()) if key.startswith('image')] provided_images = [img for img in all_images if img is not None] if provided_images: diff --git a/README.md b/README.md index fc349e6..7b12d4d 100644 --- a/README.md +++ b/README.md @@ -1,96 +1,96 @@ -# ComfyUI-BasicOllama - -A simplified node that provides access to Ollama. It allows you to send prompts, system prompts, and images to your Ollama instance and receive text-based responses. - -## ⚠️ Requirements - -**You must have Ollama installed and running on your local machine for this node to function.** You can download it from [https://ollama.com/](https://ollama.com/). - -## 🚀 Features - -* **Direct Ollama Integration:** Seamlessly connect to your local Ollama instance. -* **Automatic Image Detection:** The node automatically detects if an image is connected and sends it to Ollama for multimodal analysis. -* **System Prompt Support:** Utilize the `system` parameter in the Ollama API for more control over model behavior. -* **Dynamic Prompt Templates:** Easily load your own system prompts from `.txt` files in the `prompts` directory. -* **Multiple Image Inputs:** Input up to five images for analysis. -* **Easy Configuration:** Quickly set up your Ollama URL via a `config.json` file. - -![](https://github.com/BobRandomNumber/ComfyUI-BasicOllama/blob/main/BasicOllama.png) - -## 📦 Installation - -1. **Clone the Repository:** - Navigate to your `ComfyUI/custom_nodes` directory and clone this repository: -  -```bash - git clone https://github.com/BobRandomNumber/ComfyUI-BasicOllama.git -``` - -2. **Install Dependencies:** - Navigate to the newly cloned directory and install the required packages: -  -```bash - cd ComfyUI-BasicOllama -``` -```bash - pip install -r requirements.txt -``` - -3. **Restart your ComfyUI instance to load the new custom node.** - -## ✨ Usage - -The `BasicOllama` node can be found under the `Ollama` category in the ComfyUI menu. Connect optional image/s to the `image` inputs to have it automatically included in your prompt if desired. - -### Inputs - -| Name | Type | Description | -| ---------------------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `prompt` | `STRING` | The main text prompt to send to the Ollama model. | -| `ollama_model` | `COMBO` | A list of available Ollama models on your local instance. | -| `keep_alive` | `INT` | The duration (in minutes) that the Ollama model should remain loaded in memory after the request is complete. | -| `saved_sys_prompt` | `COMBO` | A dropdown list of saved system prompts from the `.txt` files in the `prompts` directory. This is used as the system prompt by default. | -| `use_sys_prompt_below` | `BOOLEAN` | If checked (`True`), the `system_prompt` text box below will be used instead of the dropdown selection. If unchecked (`False`), the `saved_sys_prompt` dropdown is used. | -| `system_prompt` | `STRING` | A multiline text box for a custom, one-off system prompt. This is only active when `use_sys_prompt_below` is checked. | -| `image1` - `image5` | `IMAGE` | Up to five optional image inputs for multimodal models. The node will automatically detect and process any connected images. | - -### Outputs - -| Name | Type | Description | -| ------ | -------- | ----------------------------------------- | -| `text` | `STRING` | The text-based response from the Ollama model. | - -## ✍️ Adding Custom System Prompts - -You can easily add your own reusable system prompts to the `saved_sys_prompt` dropdown menu. - -1. Navigate to the `ComfyUI-BasicOllama/prompts` directory. -2. Create a new text file (e.g., `my_prompt.txt`). -3. Write your system prompt inside this file. For example, if you want a system prompt for generating JSON, the content of the file could be: - -  ``` - You are a helpful assistant that only responds with valid, well-formatted JSON. - ``` - -4. Save the file. -5. Refresh your ComfyUI browser window. - -The name of your file (without the `.txt` extension) will now appear as an option in the `saved_sys_prompt` dropdown. In the example above, you would see `my_prompt` in the list. - -## ⚙️ Configuration - -By default, the `BasicOllama` node will attempt to connect to your Ollama instance at `http://localhost:11434`. - -If your Ollama instance is running on a different URL/port, you can change it by editing the `config.json` file located in the `ComfyUI-BasicOllama` directory: - -```json -{ - "OLLAMA_URL": "http://your-ollama-url:11434" -} -``` - -## 🙏 Attribution - -A special thank you to [@al-swaiti](https://github.com/al-swaiti) for creating the original [ComfyUI-OllamaGemini](https://github.com/al-swaiti/ComfyUI-OllamaGemini) whose Ollama node served as the foundation and inspiration for this. -This project is licensed under the [MIT License](LICENSE). - +# ComfyUI-BasicOllama + +A simplified node that provides access to Ollama. It allows you to send prompts, system prompts, and images to your Ollama instance and receive text-based responses. + +## ⚠️ Requirements + +**You must have Ollama installed and running on your local machine for this node to function.** You can download it from [https://ollama.com/](https://ollama.com/). + +## 🚀 Features + +* **Direct Ollama Integration:** Seamlessly connect to your local Ollama instance. +* **Automatic Image Detection:** The node automatically detects if an image is connected and sends it to Ollama for multimodal analysis. +* **System Prompt Support:** Utilize the `system` parameter in the Ollama API for more control over model behavior. +* **Dynamic Prompt Templates:** Easily load your own system prompts from `.txt` files in the `prompts` directory. +* **Dynamic Image Inputs:** Start with one image input, and automatically add more as you connect them. +* **Easy Configuration:** Quickly set up your Ollama URL via a `config.json` file. + +![](https://github.com/BobRandomNumber/ComfyUI-BasicOllama/blob/main/BasicOllama.png) + +## 📦 Installation + +1. **Clone the Repository:** + Navigate to your `ComfyUI/custom_nodes` directory and clone this repository: +  +```bash + git clone https://github.com/BobRandomNumber/ComfyUI-BasicOllama.git +``` + +2. **Install Dependencies:** + Navigate to the newly cloned directory and install the required packages: +  +```bash + cd ComfyUI-BasicOllama +``` +```bash + pip install -r requirements.txt +``` + +3. **Restart your ComfyUI instance to load the new custom node.** + +## ✨ Usage + +The `BasicOllama` node can be found under the `Ollama` category in the ComfyUI menu. Connect optional image/s to the `image` inputs to have it automatically included in your prompt if desired. + +### Inputs + +| Name | Type | Description | +| ---------------------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `prompt` | `STRING` | The main text prompt to send to the Ollama model. | +| `ollama_model` | `COMBO` | A list of available Ollama models on your local instance. | +| `keep_alive` | `INT` | The duration (in minutes) that the Ollama model should remain loaded in memory after the request is complete. | +| `saved_sys_prompt` | `COMBO` | A dropdown list of saved system prompts from the `.txt` files in the `prompts` directory. This is used as the system prompt by default. | +| `use_sys_prompt_below` | `BOOLEAN` | If checked (`True`), the `system_prompt` text box below will be used instead of the dropdown selection. If unchecked (`False`), the `saved_sys_prompt` dropdown is used. | +| `system_prompt` | `STRING` | A multiline text box for a custom, one-off system prompt. This is only active when `use_sys_prompt_below` is checked. | +| `image` | `IMAGE` | An optional image input for multimodal models. The node starts with one image input, and connecting an image to it will create a new input, allowing for any number of images. | + +### Outputs + +| Name | Type | Description | +| ------ | -------- | ----------------------------------------- | +| `text` | `STRING` | The text-based response from the Ollama model. | + +## ✍️ Adding Custom System Prompts + +You can easily add your own reusable system prompts to the `saved_sys_prompt` dropdown menu. + +1. Navigate to the `ComfyUI-BasicOllama/prompts` directory. +2. Create a new text file (e.g., `my_prompt.txt`). +3. Write your system prompt inside this file. For example, if you want a system prompt for generating JSON, the content of the file could be: + +  ``` + You are a helpful assistant that only responds with valid, well-formatted JSON. + ``` + +4. Save the file. +5. Refresh your ComfyUI browser window. + +The name of your file (without the `.txt` extension) will now appear as an option in the `saved_sys_prompt` dropdown. In the example above, you would see `my_prompt` in the list. + +## ⚙️ Configuration + +By default, the `BasicOllama` node will attempt to connect to your Ollama instance at `http://localhost:11434`. + +If your Ollama instance is running on a different URL/port, you can change it by editing the `config.json` file located in the `ComfyUI-BasicOllama` directory: + +```json +{ + "OLLAMA_URL": "http://your-ollama-url:11434" +} +``` + +## 🙏 Attribution + +A special thank you to [@al-swaiti](https://github.com/al-swaiti) for creating the original [ComfyUI-OllamaGemini](https://github.com/al-swaiti/ComfyUI-OllamaGemini) whose Ollama node served as the foundation and inspiration for this. +This project is licensed under the [MIT License](LICENSE). + diff --git a/__init__.py b/__init__.py index a4d8de3..3214059 100644 --- a/__init__.py +++ b/__init__.py @@ -1,3 +1,4 @@ -from .BasicOllama import NODE_CLASS_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS - -__all__ = ['NODE_CLASS_MAPPINGS', 'NODE_DISPLAY_NAME_MAPPINGS'] +from .BasicOllama import NODE_CLASS_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS + +WEB_DIRECTORY = "./web" +__all__ = ['NODE_CLASS_MAPPINGS', 'NODE_DISPLAY_NAME_MAPPINGS', 'WEB_DIRECTORY'] diff --git a/web/__init__.py b/web/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/web/js/BasicOllama.js b/web/js/BasicOllama.js new file mode 100644 index 0000000..457e70c --- /dev/null +++ b/web/js/BasicOllama.js @@ -0,0 +1,104 @@ + +import { app } from "../../../scripts/app.js" + +const TypeSlot = { + Input: 1, + Output: 2, +}; + +const TypeSlotEvent = { + Connect: true, + Disconnect: false, +}; + +const _ID = "BasicOllama"; +const _PREFIX = "image"; +const _TYPE = "IMAGE"; + +app.registerExtension({ + name: 'cozy_ex.' + _ID, + async beforeRegisterNodeDef(nodeType, nodeData, app) { + // skip the node if it is not the one we want + if (nodeData.name !== _ID) { + return + } + + const onNodeCreated = nodeType.prototype.onNodeCreated; + nodeType.prototype.onNodeCreated = async function () { + const me = onNodeCreated?.apply(this); + // start with a new dynamic input + this.addInput(_PREFIX, _TYPE); + // Ensure the new slot has proper appearance + const slot = this.inputs[this.inputs.length - 1]; + if (slot) { + slot.color_off = "#666"; + } + return me; + } + + const onConnectionsChange = nodeType.prototype.onConnectionsChange + nodeType.prototype.onConnectionsChange = function (slotType, slot_idx, event, link_info, node_slot) { + const me = onConnectionsChange?.apply(this, arguments); + + if (slotType === TypeSlot.Input) { + if (link_info && event === TypeSlotEvent.Connect) { + // get the parent (left side node) from the link + const fromNode = this.graph._nodes.find( + (otherNode) => otherNode.id == link_info.origin_id + ) + + if (fromNode) { + // make sure there is a parent for the link + const parent_link = fromNode.outputs[link_info.origin_slot]; + if (parent_link) { + node_slot.type = parent_link.type; + node_slot.name = `${_PREFIX}_`; + } + } + } else if (event === TypeSlotEvent.Disconnect) { + this.removeInput(slot_idx); + } + + // Track each slot name so we can index the uniques + let idx = 0; + let slot_tracker = {}; + for(const slot of this.inputs) { + if (slot.link === null) { + try { + this.removeInput(idx); + } catch { + + } + continue; + } + idx += 1; + const name = slot.name.split('_')[0]; + + // Correctly increment the count in slot_tracker + let count = (slot_tracker[name] || 0) + 1; + slot_tracker[name] = count; + + // Update the slot name with the count if greater than 1 + slot.name = `${name}_${count}`; + } + + // check that the last slot is a dynamic entry.... + let last = this.inputs[this.inputs.length - 1]; + if (last === undefined || (last.name != _PREFIX || last.type != _TYPE)) { + this.addInput(_PREFIX, _TYPE); + // Set the unconnected slot to appear gray + last = this.inputs[this.inputs.length - 1]; + if (last) { + last.color_off = "#666"; + } + } + + // force the node to resize itself for the new/deleted connections + this?.graph?.setDirtyCanvas(true); + return me; + } + } + return nodeType; + }, + +})