├── .github └── workflows │ └── publish.yml ├── README.md ├── __init__.py ├── demo ├── demo.png └── demo2.png ├── gemini_nodes.py ├── pyproject.toml └── requirements.txt /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish to Comfy registry 2 | on: 3 | workflow_dispatch: 4 | push: 5 | branches: 6 | - main 7 | - master 8 | paths: 9 | - "pyproject.toml" 10 | 11 | permissions: 12 | issues: write 13 | 14 | jobs: 15 | publish-node: 16 | name: Publish Custom Node to registry 17 | runs-on: ubuntu-latest 18 | if: ${{ github.repository_owner == 'tatookan' }} 19 | steps: 20 | - name: Check out code 21 | uses: actions/checkout@v4 22 | with: 23 | submodules: true 24 | - name: Publish Custom Node 25 | uses: Comfy-Org/publish-node-action@v1 26 | with: 27 | ## Add your own personal access token to your Github Repository secrets and reference it here. 28 | personal_access_token: ${{ secrets.REGISTRY_ACCESS_TOKEN }} 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ComfyUI Gemini Flash 节点 2 | 3 | 这是一个用于ComfyUI的Google Gemini API集成节点,支持文本生成和图像生成功能。通过此节点,您可以在ComfyUI工作流中直接使用Google的Gemini 2.0系列模型。 4 | 特别说明:关于出现[ERROR]API调用错误:'NoneType'object has no attribute'parts 说明你上传的图片或者提示词已经违反了《Generative AI Prohibited Use Policy》,请先使用场景或者产品图测试。 5 | 6 | ![](https://github.com/tatookan/comfyui_ssl_gemini_EXP/blob/main/demo/demo.png?raw=true) 7 | --- 8 | ![](https://github.com/tatookan/comfyui_ssl_gemini_EXP/blob/main/demo/demo2.png?raw=true) 9 | 10 | ## 更新 11 | 2025.3.19:更新支持多图处理功能 12 | ## 功能特点 13 | 14 | - 支持Gemini 2.0系列模型(gemini-2.0-flash, gemini-2.0-flash-exp, gemini-2.0-pro) 15 | - 支持文本到文本生成 16 | - 支持图像到文本生成(图像理解) 17 | - 支持文本到图像生成(仅在其他.py文件中实现) 18 | - 内置代理支持,方便中国用户使用 19 | - 自动依赖检查和安装 20 | - 完善的错误处理和日志记录 21 | 22 | ## 安装方法 23 | 24 | 1. 确保您已经安装了ComfyUI 25 | 2. 将此仓库克隆或下载到ComfyUI的`custom_nodes`目录中: 26 | ``` 27 | cd ComfyUI/custom_nodes 28 | git clone https://github.com/tatookan/comfyui_ssl_gemini_EXP.git 29 | ``` 30 | 3. 安装依赖: 31 | ``` 32 | cd comfyui_ssl_gemini_EXP 33 | pip install -r requirements.txt 34 | ``` 35 | 4. 重启ComfyUI 36 | 37 | ## 使用方法 38 | 39 | ### 1. 配置API密钥 40 | 41 | 首先,您需要获取Google Gemini API密钥: 42 | 1. 访问[Google AI Studio](https://makersuite.google.com/app/apikey) 43 | 2. 创建一个API密钥 44 | 3. 在ComfyUI中使用`💠SSL/API/Gemini/API Key Config`节点输入您的API密钥 45 | 46 | ### 2. 文本生成 47 | 48 | 使用`💠SSL/API/Gemini/Text Prompt`节点进行文本生成: 49 | 50 | - 连接API密钥配置节点到`config`输入 51 | - 在`prompt`中输入您的提示文本 52 | - 调整生成参数(温度、top_p、top_k等) 53 | - 如果需要,可以连接图像到`input_image`输入,实现图像理解功能 54 | 55 | ### 3. 代理设置 56 | 57 | 如果您在中国或其他需要代理的地区: 58 | 59 | 1. 将`use_proxy`设置为`True` 60 | 2. 设置`proxy_host`(默认为127.0.0.1) 61 | 3. 设置`proxy_port`(默认为7890) 62 | 63 | ## 参数说明 64 | 65 | ### API密钥配置节点 66 | 67 | - `api_key`: Google Gemini API密钥 68 | 69 | ### 文本生成节点 70 | 71 | #### 必填参数 72 | 73 | - `config`: API密钥配置 74 | - `prompt`: 提示文本 75 | - `model`: 选择模型(gemini-2.0-flash, gemini-2.0-flash-exp, gemini-2.0-pro) 76 | - `temperature`: 生成温度(0.0-1.0),控制创意程度 77 | - `top_p`: 核采样参数(0.0-1.0) 78 | - `top_k`: 考虑的候选词数量(1-100) 79 | - `max_output_tokens`: 最大输出标记数(1-8192) 80 | - `include_images`: 是否在响应中包含图像(True/False) 81 | 82 | #### 可选参数 83 | 84 | - `input_image`: 输入图像(用于图像理解) 85 | - `use_proxy`: 是否使用代理(True/False) 86 | - `proxy_host`: 代理主机地址 87 | - `proxy_port`: 代理端口 88 | 89 | ## 输出 90 | 91 | 文本生成节点输出: 92 | - `text`: 生成的文本 93 | - `image`: 如果启用了图像生成,则输出图像 94 | 95 | ## 注意事项 96 | -根据谷歌的《Generative AI Prohibited Use Policy》,Gemini API 有以下限制: 97 | -不得用于生成违反法律法规的内容 98 | -不得用于生成有害、欺诈、色情或暴力内容 99 | -不得用于生成侵犯他人隐私或知识产权的内容 100 | -图像生成可能受到额外限制,某些类型的图像可能无法生成 101 | 102 | - 使用此节点需要稳定的网络连接或有效的代理设置 103 | - API请求可能会受到Google服务器负载的影响 104 | - 大型请求可能需要更长的处理时间 105 | - 图像生成功能需要使用支持图像生成的模型(如gemini-2.0-flash-exp) 106 | 107 | ## 故障排除 108 | 109 | - 如果遇到网络连接问题,请检查代理设置 110 | - 如果API请求失败,请检查API密钥是否有效 111 | - 如果依赖安装失败,请手动安装所需的依赖包 112 | 113 | ## 致谢 114 | 115 | 感谢Google提供的Gemini API服务。 116 | 117 | # Contact Details 118 | Email: dianyuanan@vip.qq.com 119 | 加入我的粉丝群: 联系微信: Miss-Y-s-Honey, 并注明来意 120 | 查看我的教程频道 [bilibili@深深蓝hana](https://space.bilibili.com/618554?spm_id_from=333.1007.0.0) 121 | 日常作品分享 [douyin@深深蓝](https://www.douyin.com/user/MS4wLjABAAAAJGu7yCfV3XwKoklBX62bivvat3micLxemdDT0FAmdcGfqbuFS3ItsKWKrBt5Hg16?from_tab_name=) 122 | -------------------------------------------------------------------------------- /__init__.py: -------------------------------------------------------------------------------- 1 | import os 2 | import folder_paths 3 | from .gemini_nodes import NODE_CLASS_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS 4 | 5 | __all__ = ['NODE_CLASS_MAPPINGS', 'NODE_DISPLAY_NAME_MAPPINGS'] 6 | -------------------------------------------------------------------------------- /demo/demo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tatookan/comfyui_ssl_gemini_EXP/2822942e11458a8606a14aecdcd850ed4ad8e92a/demo/demo.png -------------------------------------------------------------------------------- /demo/demo2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tatookan/comfyui_ssl_gemini_EXP/2822942e11458a8606a14aecdcd850ed4ad8e92a/demo/demo2.png -------------------------------------------------------------------------------- /gemini_nodes.py: -------------------------------------------------------------------------------- 1 | import os 2 | import json 3 | import uuid 4 | import torch 5 | import numpy as np 6 | from PIL import Image 7 | import io 8 | import folder_paths 9 | from google import genai 10 | from google.genai import types 11 | import time 12 | import traceback 13 | import threading 14 | import queue 15 | import sys 16 | import importlib 17 | import subprocess 18 | import random 19 | 20 | def check_and_install_dependencies(): 21 | required_packages = { 22 | 'requests': 'requests', 23 | 'pysocks': 'PySocks', 24 | } 25 | 26 | for module_name, package_name in required_packages.items(): 27 | try: 28 | importlib.import_module(module_name) 29 | except ImportError: 30 | print(f"[WARNING] 未找到 {package_name},尝试安装...") 31 | try: 32 | subprocess.check_call([sys.executable, "-m", "pip", "install", package_name]) 33 | print(f"[INFO] 成功安装 {package_name}") 34 | except Exception as e: 35 | print(f"[ERROR] 安装 {package_name} 失败: {str(e)}") 36 | 37 | try: 38 | check_and_install_dependencies() 39 | except Exception as e: 40 | print(f"[WARNING] 检查依赖时出错: {str(e)}") 41 | 42 | class SSL_GeminiAPIKeyConfig: 43 | @classmethod 44 | def INPUT_TYPES(cls): 45 | return { 46 | "required": { 47 | "api_key": ("STRING", {"multiline": False}), 48 | } 49 | } 50 | 51 | RETURN_TYPES = ("GEMINI_CONFIG",) 52 | RETURN_NAMES = ("config",) 53 | FUNCTION = "configure" 54 | CATEGORY = "💠SSL/API/Gemini" 55 | 56 | def configure(self, api_key): 57 | config = {"api_key": api_key} 58 | return (config,) 59 | 60 | 61 | class SSL_GeminiTextPrompt: 62 | @classmethod 63 | def INPUT_TYPES(cls): 64 | return { 65 | "required": { 66 | "config": ("GEMINI_CONFIG",), 67 | "prompt": ("STRING", {"multiline": True}), 68 | "model": (["gemini-2.0-flash", "gemini-2.0-flash-exp", "gemini-2.0-pro"], {"default": "gemini-2.0-flash"}), 69 | "temperature": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}), 70 | "top_p": ("FLOAT", {"default": 0.95, "min": 0.0, "max": 1.0, "step": 0.01}), 71 | "top_k": ("INT", {"default": 40, "min": 1, "max": 100, "step": 1}), 72 | "max_output_tokens": ("INT", {"default": 8192, "min": 1, "max": 8192, "step": 1}), 73 | "include_images": (["True", "False"], {"default": "True"}), 74 | }, 75 | "optional": { 76 | "input_image": ("IMAGE",), 77 | "input_image_2": ("IMAGE",), # 添加第二个图像输入 78 | "use_proxy": (["False", "True"], {"default": "False"}), 79 | "proxy_host": ("STRING", {"default": "127.0.0.1"}), 80 | "proxy_port": ("INT", {"default": 7890, "min": 1, "max": 65535}), 81 | "use_seed": (["True", "False"], {"default": "True"}), 82 | "seed": ("INT", {"default": 0, "min": 0, "max": 2147483647}), 83 | } 84 | } 85 | 86 | RETURN_TYPES = ("STRING", "IMAGE", "INT") 87 | RETURN_NAMES = ("text", "image", "seed") 88 | FUNCTION = "generate" 89 | CATEGORY = "💠SSL/API/Gemini" 90 | 91 | def save_binary_file(self, data, mime_type): 92 | ext = ".bin" 93 | if mime_type == "image/png": 94 | ext = ".png" 95 | elif mime_type == "image/jpeg": 96 | ext = ".jpg" 97 | 98 | output_dir = folder_paths.get_output_directory() 99 | gemini_dir = os.path.join(output_dir, "gemini_outputs") 100 | os.makedirs(gemini_dir, exist_ok=True) 101 | 102 | file_name = os.path.join(gemini_dir, f"gemini_output_{uuid.uuid4()}{ext}") 103 | 104 | with open(file_name, "wb") as f: 105 | f.write(data) 106 | 107 | return file_name 108 | 109 | def generate_empty_image(self, width=64, height=64): 110 | empty_image = np.ones((height, width, 3), dtype=np.float32) * 0.2 111 | tensor = torch.from_numpy(empty_image).unsqueeze(0) 112 | return tensor 113 | 114 | def generate(self, config, prompt, model, temperature, top_p, top_k, max_output_tokens, include_images, 115 | input_image=None, input_image_2=None, use_proxy="False", proxy_host="127.0.0.1", proxy_port=7890, 116 | use_seed="True", seed=0): 117 | original_http_proxy = os.environ.get('HTTP_PROXY') 118 | original_https_proxy = os.environ.get('HTTPS_PROXY') 119 | original_http_proxy_lower = os.environ.get('http_proxy') 120 | original_https_proxy_lower = os.environ.get('https_proxy') 121 | 122 | print(f"[INFO] 开始生成,模型: {model}, 温度: {temperature}") 123 | 124 | # 改进的随机种子处理逻辑 125 | if use_seed == "True": 126 | # 如果种子为0,生成随机种子 127 | if seed == 0: 128 | # 使用当前时间戳和随机数组合生成种子,确保每次运行都不同 129 | current_time = int(time.time() * 1000) 130 | random_component = random.randint(0, 1000000) 131 | actual_seed = (current_time + random_component) % 2147483647 132 | print(f"[INFO] 生成随机种子: {actual_seed}") 133 | else: 134 | # 使用指定的种子值 135 | actual_seed = seed 136 | print(f"[INFO] 使用指定种子: {actual_seed}") 137 | 138 | # 设置随机种子 139 | random.seed(actual_seed) 140 | np.random.seed(actual_seed) 141 | torch.manual_seed(actual_seed) 142 | if torch.cuda.is_available(): 143 | torch.cuda.manual_seed_all(actual_seed) 144 | else: 145 | actual_seed = None 146 | print("[INFO] 未使用种子") 147 | 148 | try: 149 | if use_proxy == "True": 150 | if not proxy_host.startswith(('http://', 'https://')): 151 | proxy_url = f"http://{proxy_host}:{proxy_port}" 152 | else: 153 | proxy_url = f"{proxy_host}:{proxy_port}" 154 | 155 | os.environ['HTTP_PROXY'] = proxy_url 156 | os.environ['HTTPS_PROXY'] = proxy_url 157 | os.environ['http_proxy'] = proxy_url 158 | os.environ['https_proxy'] = proxy_url 159 | os.environ['REQUESTS_CA_BUNDLE'] = '' 160 | 161 | print(f"[INFO] 已启用代理: {proxy_url}") 162 | 163 | print(f"[INFO] 初始化Gemini客户端") 164 | try: 165 | client_options = {} 166 | 167 | if use_proxy == "True": 168 | try: 169 | import google.api_core.http_client 170 | import google.auth.transport.requests 171 | 172 | try: 173 | import requests 174 | from requests.adapters import HTTPAdapter 175 | 176 | class ProxyAdapter(HTTPAdapter): 177 | def __init__(self, proxy_url, **kwargs): 178 | self.proxy_url = proxy_url 179 | super().__init__(**kwargs) 180 | 181 | def add_headers(self, request, **kwargs): 182 | super().add_headers(request, **kwargs) 183 | 184 | session = requests.Session() 185 | proxies = { 186 | "http": proxy_url, 187 | "https": proxy_url 188 | } 189 | session.proxies.update(proxies) 190 | 191 | adapter = ProxyAdapter(proxy_url, max_retries=3) 192 | session.mount('http://', adapter) 193 | session.mount('https://', adapter) 194 | 195 | session.verify = False 196 | 197 | http_client = google.api_core.http_client.RequestsHttpClient(session=session) 198 | client_options["http_client"] = http_client 199 | 200 | print(f"[INFO] 已使用requests库设置代理到HTTP客户端") 201 | except Exception as proxy_error: 202 | print(f"[WARNING] 设置HTTP客户端代理失败: {str(proxy_error)}") 203 | except ImportError as e: 204 | print(f"[WARNING] 导入Google API HTTP客户端库失败: {str(e)}") 205 | 206 | client = genai.Client(api_key=config["api_key"], **client_options) 207 | print(f"[INFO] Gemini客户端初始化成功") 208 | except Exception as e: 209 | print(f"[ERROR] Gemini客户端初始化失败: {str(e)}") 210 | return (f"Gemini客户端初始化失败: {str(e)}", self.generate_empty_image(), actual_seed if actual_seed is not None else 0) 211 | 212 | try: 213 | import socket 214 | test_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 215 | test_socket.settimeout(5) 216 | 217 | test_host = "generativelanguage.googleapis.com" 218 | 219 | if use_proxy == "True": 220 | try: 221 | import socks 222 | test_socket = socks.socksocket() 223 | test_socket.set_proxy(socks.HTTP, proxy_host, proxy_port) 224 | test_socket.settimeout(5) 225 | except ImportError: 226 | print(f"[WARNING] 未安装PySocks库,无法通过代理测试连接") 227 | 228 | test_socket.connect((test_host, 443)) 229 | test_socket.close() 230 | network_ok = True 231 | except Exception as e: 232 | network_ok = False 233 | print(f"[WARNING] 网络连接测试失败: {str(e)}") 234 | 235 | if use_proxy == "True": 236 | try: 237 | import subprocess 238 | cmd = f"curl -x {proxy_url} -s -o /dev/null -w '%{{http_code}}' https://{test_host}" 239 | try: 240 | result = subprocess.run(cmd, shell=True, capture_output=True, text=True, timeout=10) 241 | if result.returncode == 0 and result.stdout.strip() in ['200', '301', '302']: 242 | network_ok = True 243 | else: 244 | print(f"[WARNING] curl代理测试失败,状态码: {result.stdout.strip() if result.stdout else 'N/A'}") 245 | except Exception as curl_error: 246 | print(f"[WARNING] curl测试失败: {str(curl_error)}") 247 | except ImportError: 248 | pass 249 | 250 | contents = [] 251 | 252 | # 处理输入图像 253 | images_to_process = [] 254 | if input_image is not None: 255 | images_to_process.append(input_image) 256 | if input_image_2 is not None: 257 | images_to_process.append(input_image_2) 258 | 259 | # 如果有图像需要处理 260 | if images_to_process: 261 | try: 262 | img_parts = [] 263 | 264 | for img in images_to_process: 265 | img_array = img[0].cpu().numpy() 266 | img_array = (img_array * 255).astype(np.uint8) 267 | pil_img = Image.fromarray(img_array) 268 | 269 | img_byte_arr = io.BytesIO() 270 | pil_img.save(img_byte_arr, format='PNG') 271 | img_bytes = img_byte_arr.getvalue() 272 | 273 | img_part = {"inline_data": {"mime_type": "image/png", "data": img_bytes}} 274 | img_parts.append(img_part) 275 | 276 | # 添加所有图像部分和文本部分 277 | contents = img_parts + [{"text": prompt}] 278 | except Exception as e: 279 | print(f"[ERROR] 处理输入图像时出错: {str(e)}") 280 | return (f"处理输入图像时出错: {str(e)}", self.generate_empty_image(), actual_seed if actual_seed is not None else 0) 281 | else: 282 | contents = prompt 283 | 284 | response_modalities = ["text"] 285 | if include_images == "True": 286 | response_modalities.append("image") 287 | 288 | generate_content_config = types.GenerateContentConfig( 289 | temperature=temperature, 290 | top_p=top_p, 291 | top_k=top_k, 292 | max_output_tokens=max_output_tokens, 293 | response_modalities=response_modalities, 294 | ) 295 | 296 | if use_seed == "True" and actual_seed is not None: 297 | try: 298 | generate_content_config.seed = actual_seed 299 | except Exception as seed_error: 300 | print(f"[WARNING] 无法设置种子到API请求: {str(seed_error)}") 301 | 302 | text_output = "" 303 | image_tensor = None 304 | 305 | try: 306 | print(f"[INFO] 发送API请求到Gemini") 307 | 308 | start_time = time.time() 309 | timeout = 30 310 | 311 | def api_call(): 312 | try: 313 | api_response = client.models.generate_content( 314 | model=model, 315 | contents=contents, 316 | config=generate_content_config, 317 | ) 318 | result_queue.put(("success", api_response)) 319 | except Exception as e: 320 | print(f"[ERROR] API线程中出错: {str(e)}") 321 | result_queue.put(("error", e)) 322 | 323 | result_queue = queue.Queue() 324 | 325 | api_thread = threading.Thread(target=api_call) 326 | api_thread.daemon = True 327 | api_thread.start() 328 | 329 | try: 330 | status, result = result_queue.get(timeout=timeout) 331 | elapsed_time = time.time() - start_time 332 | 333 | if status == "success": 334 | response = result 335 | print(f"[INFO] API请求成功完成,耗时: {elapsed_time:.2f}秒") 336 | else: 337 | print(f"[ERROR] API请求线程中出错,耗时: {elapsed_time:.2f}秒,错误: {str(result)}") 338 | error_str = str(result).lower() 339 | if any(term in error_str for term in ["timeout", "connection", "network", "socket", "连接", "网络"]): 340 | if not network_ok and use_proxy != "True": 341 | return (f"API请求失败: {str(result)}。网络连接测试失败,建议启用代理。", self.generate_empty_image(), actual_seed if actual_seed is not None else 0) 342 | raise result 343 | except queue.Empty: 344 | elapsed_time = time.time() - start_time 345 | print(f"[ERROR] API请求超时,已等待: {elapsed_time:.2f}秒") 346 | 347 | timeout_msg = f"Gemini API请求超时,已等待{timeout}秒。" 348 | if not network_ok: 349 | if use_proxy == "True": 350 | timeout_msg += f"网络连接测试失败,当前使用的代理({proxy_host}:{proxy_port})可能无效,请检查代理设置。" 351 | else: 352 | timeout_msg += "网络连接测试失败,建议启用代理。" 353 | else: 354 | timeout_msg += "网络连接测试成功,但API请求仍然超时,可能是服务器繁忙或请求内容过大。" 355 | 356 | return (timeout_msg, self.generate_empty_image(), actual_seed if actual_seed is not None else 0) 357 | 358 | print(f"[INFO] 收到API响应") 359 | 360 | if hasattr(response, 'candidates') and response.candidates: 361 | for part in response.candidates[0].content.parts: 362 | if hasattr(part, 'text') and part.text is not None: 363 | text_output += part.text 364 | 365 | elif hasattr(part, 'inline_data') and part.inline_data is not None: 366 | try: 367 | inline_data = part.inline_data 368 | mime_type = inline_data.mime_type 369 | data = inline_data.data 370 | 371 | image_path = self.save_binary_file(data, mime_type) 372 | 373 | img = Image.open(image_path) 374 | 375 | if img.mode != 'RGB': 376 | img = img.convert('RGB') 377 | 378 | img_array = np.array(img).astype(np.float32) / 255.0 379 | image_tensor = torch.from_numpy(img_array).unsqueeze(0) 380 | except Exception as e: 381 | print(f"[ERROR] 图像处理错误: {str(e)}") 382 | text_output += f"\n图像处理错误: {str(e)}" 383 | except Exception as e: 384 | print(f"[ERROR] API调用错误: {str(e)}") 385 | text_output = f"API调用错误: {str(e)}" 386 | 387 | if image_tensor is None: 388 | image_tensor = self.generate_empty_image() 389 | 390 | if use_seed == "True" and actual_seed is not None: 391 | seed_info = f"\n\n[种子信息: {actual_seed}]" 392 | text_output += seed_info 393 | 394 | return (text_output, image_tensor, actual_seed if actual_seed is not None else 0) 395 | finally: 396 | if original_http_proxy: 397 | os.environ['HTTP_PROXY'] = original_http_proxy 398 | else: 399 | if 'HTTP_PROXY' in os.environ: 400 | os.environ.pop('HTTP_PROXY') 401 | 402 | if original_https_proxy: 403 | os.environ['HTTPS_PROXY'] = original_https_proxy 404 | else: 405 | if 'HTTPS_PROXY' in os.environ: 406 | os.environ.pop('HTTPS_PROXY') 407 | 408 | if original_http_proxy_lower: 409 | os.environ['http_proxy'] = original_http_proxy_lower 410 | else: 411 | if 'http_proxy' in os.environ: 412 | os.environ.pop('http_proxy') 413 | 414 | if original_https_proxy_lower: 415 | os.environ['https_proxy'] = original_https_proxy_lower 416 | else: 417 | if 'https_proxy' in os.environ: 418 | os.environ.pop('https_proxy') 419 | 420 | if 'REQUESTS_CA_BUNDLE' in os.environ: 421 | os.environ.pop('REQUESTS_CA_BUNDLE') 422 | 423 | try: 424 | import requests 425 | if hasattr(requests, 'Session'): 426 | clean_session = requests.Session() 427 | if hasattr(requests, 'session'): 428 | requests.session = lambda: clean_session 429 | except: 430 | pass 431 | 432 | NODE_CLASS_MAPPINGS = { 433 | "SSL_GeminiAPIKeyConfig": SSL_GeminiAPIKeyConfig, 434 | "SSL_GeminiTextPrompt": SSL_GeminiTextPrompt, 435 | } 436 | 437 | NODE_DISPLAY_NAME_MAPPINGS = { 438 | "SSL_GeminiAPIKeyConfig": "💠SSL Gemini API Key", 439 | "SSL_GeminiTextPrompt": "💠SSL Gemini Text Prompt", 440 | } 441 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | name = "ssl_gemini_exp" 3 | description = "Calling gemini2.0 at comfyui . The project will continue to organize good APIs!" 4 | version = "1.0.2" 5 | license = {file = "LICENSE"} 6 | dependencies = ["google-genai", "numpy", "torch"] 7 | 8 | [project.urls] 9 | Repository = "https://github.com/tatookan/comfyui_ssl_gemini_EXP" 10 | # Used by Comfy Registry https://comfyregistry.org 11 | 12 | [tool.comfy] 13 | PublisherId = "tatookan" 14 | DisplayName = "comfyui_ssl_gemini_EXP" 15 | Icon = "" 16 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | google-genai 2 | numpy 3 | torch 4 | Pillow 5 | torch 6 | --------------------------------------------------------------------------------