diff --git a/BasicOllama.jpg b/BasicOllama.jpg new file mode 100644 index 0000000..78021bd Binary files /dev/null and b/BasicOllama.jpg differ diff --git a/BasicOllama.py b/BasicOllama.py index c1f7675..1549994 100644 --- a/BasicOllama.py +++ b/BasicOllama.py @@ -60,12 +60,21 @@ def get_ollama_url(): with open(config_path, 'r') as f: config = json.load(f) ollama_url = config.get("OLLAMA_URL", "http://localhost:11434") - except: - print("Error: Ollama URL not found, using default") + except FileNotFoundError: + print("Error: config.json not found, using default Ollama URL.") + ollama_url = "http://localhost:11434" + except json.JSONDecodeError: + print("Error: Could not decode config.json, using default Ollama URL.") + ollama_url = "http://localhost:11434" + except Exception as e: + print(f"An unexpected error occurred: {e}, using default Ollama URL.") ollama_url = "http://localhost:11434" return ollama_url class BasicOllama: + _connection_error_printed = False + _success_message_printed = False + def __init__(self): self.ollama_url = get_ollama_url() @@ -74,13 +83,21 @@ class BasicOllama: ollama_url = get_ollama_url() try: response = requests.get(f"{ollama_url}/api/tags") - if response.status_code == 200: - models = response.json().get('models', []) - return [model['name'] for model in models] - return ["llama2"] - except Exception as e: - print(f"Error fetching Ollama models: {str(e)}") - return ["llama2"] + response.raise_for_status() + models = response.json().get('models', []) + + if not cls._success_message_printed: + print("Ollama available.") + cls._success_message_printed = True + + cls._connection_error_printed = False # Reset on success + return [model['name'] for model in models] + except requests.exceptions.RequestException: + cls._success_message_printed = False # Reset on failure + if not cls._connection_error_printed: + print("Failed connection to Ollama.") + cls._connection_error_printed = True + return [] @classmethod def INPUT_TYPES(cls): @@ -92,7 +109,6 @@ class BasicOllama: return { "required": { "prompt": ("STRING", {"default": "", "multiline": True}), - "input_type": ([ "text", "image"], {"default": "text"}), "ollama_model": (cls.get_ollama_models(),), "keep_alive": ("INT", {"default": 0, "min": 0, "max": 60, "step": 1}), "saved_sys_prompt": (prompt_structures,), @@ -113,14 +129,17 @@ class BasicOllama: FUNCTION = "generate_content" CATEGORY = "Ollama" - def generate_content(self, prompt, input_type, 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, image1=None, image2=None, image3=None, image4=None, image5=None): + if not ollama_model: + return ("Ollama models not found. Is Ollama running?",) + url = f"{self.ollama_url}/api/generate" system_prompt_content = "" if use_sys_prompt_below: system_prompt_content = system_prompt + print("Applying user provided system prompt") else: - # Dynamically load templates and apply the selected one prompt_templates = get_prompt_files() if saved_sys_prompt in prompt_templates: system_prompt_content = prompt_templates[saved_sys_prompt] @@ -128,32 +147,23 @@ class BasicOllama: payload = { "model": ollama_model, + "prompt": prompt, + "stream": False, + "keep_alive": f"{keep_alive}m", } if system_prompt_content: payload["system"] = system_prompt_content - payload.update({ - "prompt": prompt, - "stream": False, - "keep_alive": f"{keep_alive}m" - }) + all_images = [image1, image2, image3, image4, image5] + provided_images = [img for img in all_images if img is not None] + + if provided_images: + print(f"Processing {len(provided_images)} image(s) for Ollama API") + image_data = [tensor_to_base64(img) for img in provided_images] + payload["images"] = image_data try: - if input_type == "image": - all_images = [image1, image2, image3, image4, image5] - provided_images = [img for img in all_images if img is not None] - - if provided_images: - print(f"Processing {len(provided_images)} image(s) for Ollama API") - image_data = [] - for img in provided_images: - base64_image = tensor_to_base64(img) - image_data.append(base64_image) - - payload["images"] = image_data - payload["prompt"] = f"Analyze these image(s): {prompt}" - response = requests.post(url, json=payload) response.raise_for_status() @@ -182,8 +192,17 @@ class BasicOllama: textoutput = clean_text return (textoutput,) + except requests.exceptions.RequestException as e: + error_message = f"API Error: {e}" + if e.response: + error_message += f"\nStatus Code: {e.response.status_code}" + try: + error_message += f"\nResponse: {e.response.json()}" + except json.JSONDecodeError: + error_message += f"\nResponse: {e.response.text}" + return (error_message,) except Exception as e: - return (f"API Error: {str(e)}",) + return (f"An unexpected error occurred: {e}",) NODE_CLASS_MAPPINGS = { "BasicOllama": BasicOllama, diff --git a/README.md b/README.md index 7f431d7..7eec7ae 100644 --- a/README.md +++ b/README.md @@ -6,51 +6,52 @@ A simplified node that provides access to Ollama. It allows you to send prompts, **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/). -![](https://github.com/BobRandomNumber/ComfyUI-BasicOllama/blob/main/BasicOllama.png) +!\[](https://github.com/BobRandomNumber/ComfyUI-BasicOllama/blob/main/BasicOllama.jpg) ## 🚀 Features -* **Direct Ollama Integration:** Seamlessly connect to your local Ollama instance. -* **System Prompt Support:** Utilize the `system` parameter in the Ollama API for more control over model behavior. -* **Dynamic Prompt Templates:** Load system prompts from `.txt` files in the `prompts` directory. -* **Text and Image Support:** Send both text prompts and images to multimodal Ollama models. -* **Multiple Image Inputs:** Input up to five images for analysis. -* **Easy Configuration:** Quickly set up your Ollama URL via a `config.json` file. +* **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, simplifying the workflow. +* **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. ## 📦 Installation -1. **Clone the Repository:** - Navigate to your `ComfyUI/custom_nodes` directory and clone this repository: - ```bash +1. **Clone the Repository:** + Navigate to your `ComfyUI/custom\_nodes` directory and clone this repository: + +  ```bash git clone https://github.com/BobRandomNumber/ComfyUI-BasicOllama ``` -2. **Install Dependencies:** - Navigate to the newly cloned directory and install the required packages: - ```bash +2. **Install Dependencies:** + Navigate to the newly cloned directory and install the required packages: + +  ```bash cd ComfyUI-BasicOllama pip install -r requirements.txt ``` -3. **Restart ComfyUI:** - Restart your ComfyUI instance to load the new custom node. +3. **Restart ComfyUI:** + 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. +The `BasicOllama` node can be found under the `Ollama` category in the ComfyUI menu. Simply connect an image to one of the `image` inputs to have it automatically included in your prompt. ### Inputs -| Name | Type | Description | -| ---------------------- | ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `prompt` | `STRING` | The main text prompt to send to the Ollama model. | -| `input_type` | `COMBO` (`text`, `image`) | The type of input to send. `text` for text-only prompts, and `image` to include images. | -| `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` (Optional) | Up to five optional image inputs for multimodal models. | +| 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 @@ -58,6 +59,23 @@ The `BasicOllama` node can be found under the `Ollama` category in the ComfyUI m | ------ | -------- | ----------------------------------------- | | `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`. @@ -66,11 +84,12 @@ If your Ollama instance is running on a different URL/port, you can change it by ```json { - "OLLAMA_URL": "http://your-ollama-url:11434" + "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) which served as the foundation for this. +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). +