From 4e8e3035eb1751b36768b0986749cd68cf8a2391 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A7=91=E6=9E=97=5FCyril=20Pilgrim?= Date: Fri, 14 Feb 2025 19:40:23 +0800 Subject: [PATCH] update --- README.md | 4 +- __init__.py | 7 +- __pycache__/__init__.cpython-312.pyc | Bin 1115 -> 1255 bytes __pycache__/google_file_api.cpython-312.pyc | Bin 0 -> 2892 bytes google_file_api.py | 79 ++++++++++++++++++ py/VideoFileUploader.py | 44 ++++++++++ py/__init__.py | 3 +- .../VideoFileUploader.cpython-312.pyc | Bin 0 -> 1902 bytes py/__pycache__/__init__.cpython-312.pyc | Bin 407 -> 448 bytes py/__pycache__/model_loader.cpython-312.pyc | Bin 5051 -> 5051 bytes .../openai_compatible_loader.cpython-312.pyc | Bin 11686 -> 11979 bytes py/openai_compatible_loader.py | 11 ++- 12 files changed, 141 insertions(+), 7 deletions(-) create mode 100644 __pycache__/google_file_api.cpython-312.pyc create mode 100644 google_file_api.py create mode 100644 py/VideoFileUploader.py create mode 100644 py/__pycache__/VideoFileUploader.cpython-312.pyc diff --git a/README.md b/README.md index fd96e40..6552c04 100644 --- a/README.md +++ b/README.md @@ -2,11 +2,11 @@ ## 1. 项目介绍 -ComfyUI-DeepSeek-Toolkit 是一个 ComfyUI 的自定义节点包,旨在帮助用户利用来自中国供应商的强大 AI 大语言模型 (LLM),例如 DeepSeek、Qwen 等。该工具包致力于让更广泛的受众能够访问这些先进的模型,即使是那些计算资源有限的用户。 +ComfyUI-DeepSeek-Toolkit 是一个 ComfyUI 的自定义节点包,旨在帮助用户利用来自中国公司的强大 AI 大语言模型 (LLM),例如 DeepSeek、Qwen 等。该工具包致力于让更广泛的受众能够访问这些先进的模型,即使是那些计算资源有限的用户。 该项目的灵感来自于 DeepSeek 和 Qwen 等令人印象深刻的 LLM 的出现。它旨在通过提供轻量级和 API 驱动的解决方案,将这些前沿 AI 技术与日常用户连接起来,从而将这些模型集成到 ComfyUI 工作流程中。 -ComfyUI-DeepSeek-Toolkit 的使命是使开发人员和创意人员能够在现成的硬件(如旧笔记本电脑)上完成通常需要大量计算能力的任务。该项目设想了一个 AI 民主化并为所有人所用的未来。 +ComfyUI-DeepSeek-Toolkit 的使命是使开发人员和创意人员能够在现成的硬件(如旧笔记本电脑)上完成通常需要大量计算能力的任务。 ## 2. 功能特性 diff --git a/__init__.py b/__init__.py index 973a3d6..37f8dfa 100644 --- a/__init__.py +++ b/__init__.py @@ -4,6 +4,7 @@ from .py.image_understanding import NODE_CLASS_MAPPINGS as IMAGE_UNDERSTANDING_M from .py.model_loader import NODE_CLASS_MAPPINGS as MODEL_LOADER_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS as MODEL_LOADER_DISPLAY_MAPPINGS from .py.openai_compatible_loader import NODE_CLASS_MAPPINGS as OPENAI_COMPATIBLE_LOADER_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS as OPENAI_COMPATIBLE_LOADER_DISPLAY_MAPPINGS from .py.image_preprocessor import NODE_CLASS_MAPPINGS as IMAGE_PREPROCESSOR_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS as IMAGE_PREPROCESSOR_DISPLAY_MAPPINGS +from .py.VideoFileUploader import NODE_CLASS_MAPPINGS as VIDEO_FILE_UPLOADER_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS as VIDEO_FILE_UPLOADER_DISPLAY_MAPPINGS # 新增导入 # 合并所有节点映射 NODE_CLASS_MAPPINGS = { @@ -12,7 +13,8 @@ NODE_CLASS_MAPPINGS = { **IMAGE_UNDERSTANDING_MAPPINGS, **MODEL_LOADER_MAPPINGS, **OPENAI_COMPATIBLE_LOADER_MAPPINGS, - **IMAGE_PREPROCESSOR_MAPPINGS + **IMAGE_PREPROCESSOR_MAPPINGS, + **VIDEO_FILE_UPLOADER_MAPPINGS # 新增合并 } NODE_DISPLAY_NAME_MAPPINGS = { @@ -21,7 +23,8 @@ NODE_DISPLAY_NAME_MAPPINGS = { **IMAGE_UNDERSTANDING_DISPLAY_MAPPINGS, **MODEL_LOADER_DISPLAY_MAPPINGS, **OPENAI_COMPATIBLE_LOADER_DISPLAY_MAPPINGS, - **IMAGE_PREPROCESSOR_DISPLAY_MAPPINGS + **IMAGE_PREPROCESSOR_DISPLAY_MAPPINGS, + **VIDEO_FILE_UPLOADER_DISPLAY_MAPPINGS # 新增合并 } WEB_DIRECTORY = "./web" diff --git a/__pycache__/__init__.cpython-312.pyc b/__pycache__/__init__.cpython-312.pyc index ee2cf676253607c11150fcb21202bfc84c8613f0..15662723ba5dbb3152517413abf8accd17229f24 100644 GIT binary patch delta 371 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 literal 0 HcmV?d00001 diff --git a/google_file_api.py b/google_file_api.py new file mode 100644 index 0000000..1abaf48 --- /dev/null +++ b/google_file_api.py @@ -0,0 +1,79 @@ +import os +import io +import base64 +from typing import Tuple, Optional +import google.generativeai as genai # 导入 Gemini API +import time +import folder_paths +import json + +class GoogleDriveUpload: + """ + A ComfyUI node for uploading video files to Gemini via File API. + """ + + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "api_key": ("STRING", {"multiline": False, "default": ""}), # API 密钥字符串 + "file_path": ("STRING", {"default": "", "label": "Video File Path"}), + "file_name": ("STRING", {"default": "", "label": "File Name"}), + # "mime_type": (["video/mp4", "video/avi", "video/quicktime", "video/x-matroska"], {"default": "video/mp4", "label": "MIME Type"}), # Gemini File API 不需要mime_type + # "folder_id": ("STRING", {"default": "", "label": "Google Drive Folder ID", "description": "Optional: If empty, uploads to root."}), # Gemini File API 不需要folder_id + }, + } + + RETURN_TYPES = ("STRING",) + RETURN_NAMES = ("file_uri",) + FUNCTION = "upload_file" + CATEGORY = "DeepSeek_Toolkit/Google Drive" + + def upload_file(self, api_key: str, file_path: str, file_name: str) -> Tuple[str]: + """ + Uploads a file to Gemini via File API. + + Args: + api_key (str): The Gemini API key. + file_path (str): The path to the file to upload. + file_name (str): The desired name for the file on Gemini. + + Returns: + str: The URI of the uploaded file. + """ + try: + # 1. 验证 API 密钥 + if not api_key: + raise ValueError("API 密钥不能为空") + + # 2. 验证文件路径 + if not os.path.exists(file_path): + raise FileNotFoundError(f"文件未找到: {file_path}") + + # 3. 构建 Gemini API 客户端 + genai.configure(api_key=api_key) + model = genai.GenerativeModel(model_name="gemini-1.5-pro") # 假设使用 gemini-1.5-pro 模型 + client = model + + # 4. 上传文件 + print("Uploading file...") + video_file = client.upload(path=file_path, name=file_name) + file_uri = video_file.uri + print(f"Completed upload: {file_uri}") + + return (file_uri,) + + except Exception as e: + print(f"上传文件时发生错误: {e}") + return (f"Error: {str(e)}",) + + +# 节点类映射 +NODE_CLASS_MAPPINGS = { + "GoogleDriveUpload": GoogleDriveUpload +} + +# 节点显示名称映射 +NODE_DISPLAY_NAME_MAPPINGS = { + "GoogleDriveUpload": "Google Drive Upload (Gemini File API)" +} \ No newline at end of file diff --git a/py/VideoFileUploader.py b/py/VideoFileUploader.py new file mode 100644 index 0000000..8586110 --- /dev/null +++ b/py/VideoFileUploader.py @@ -0,0 +1,44 @@ +import folder_paths +import nodes +import os +from typing import Tuple + +class VideoFileUploader: + """ + Custom node for uploading video files to Gemini API + """ + + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "video_path": ("STRING", {"default": "", "label": "Video File Path"}), + "api_key": ("STRING", {"default": "", "label": "Gemini API Key"}), # 模拟API Key输入 + } + } + + RETURN_TYPES = ("STRING",) + RETURN_NAMES = ("video_url",) + FUNCTION = "upload_video" + CATEGORY = "DeepSeek_Toolkit" + + def upload_video(self, video_path: str, api_key: str) -> Tuple[str]: + """ + Uploads a video file to the Gemini API using the File API. + """ + # 模拟文件上传 + if not os.path.exists(video_path): + raise FileNotFoundError(f"Video file not found: {video_path}") + + # 模拟上传过程 + print(f"[INFO] 上传视频文件: {video_path}") + # 模拟生成视频URL + video_url = f"gemini://file/{os.path.basename(video_path)}" # 模拟视频URL + print(f"[INFO] 视频上传完成,URL: {video_url}") + + return (video_url,) + + +# 注册节点 +NODE_CLASS_MAPPINGS = {"VideoFileUploader": VideoFileUploader} +NODE_DISPLAY_NAME_MAPPINGS = {"VideoFileUploader": "Video File Uploader"} \ No newline at end of file diff --git a/py/__init__.py b/py/__init__.py index 40cfb25..977aad5 100644 --- a/py/__init__.py +++ b/py/__init__.py @@ -3,4 +3,5 @@ from . import image_generation from . import image_understanding from . import model_loader from . import openai_compatible_loader -from . import image_preprocessor \ No newline at end of file +from . import image_preprocessor +from . import VideoFileUploader # 新增导入 \ No newline at end of file diff --git a/py/__pycache__/VideoFileUploader.cpython-312.pyc b/py/__pycache__/VideoFileUploader.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..164bc47e957f0603b9822e70b8e2cd99145d1ef5 GIT binary patch literal 1902 zcmah}Uu;uV7(e%KZ@aGRHiEzy-046Y1cC&k3t-CVw$9Sk{*iE+IR?@$Z52qu#wn-r_Spzad>St1Yr0JYJ%1YOjnH}^^6R(`8UZ&_wF>&gm#>!8bGZHuf(mm5 z-Lhz$@;_s-p~+#RT&(BflLa?rm8NX9g?o=fs%HDDbKzeuC14V%%Y}Pkqs9k<$w+YEw**$IS*Cbny4 zr9fY%Jt(l;$xF`XQZJ)&( zkS*6NihL?`AqZgKw{}Hiv-{X?M?k;W&@Q!#HYC^jAk??w$&rb-Um8x|~ZVhUADySi>T` zi)s^A@h;%Q(Ul-okou9S3GF__OH4(?XbG zV9ZTG8ati_??!CVKg22nnMIESDBN@9!lesWW-iTqHg%^fa(J7!Lkm;4cSW7SW6q}Gi~f63 zrxQM~5LxJRLPzdMNAHKXUYvHMKC=frCL^6hQdOFds*-@JmJO|@Q$DDw=WBVrb>dT1 z%_xAlqoC(4tBmclhGurd4J4S3WpnAI*QaZ{Wb{NVL!^;hayT2GfInzBnvIQ4q)!pf zvQ3kAhFcpmL^&FYS1;NKCMEQzvnGJdp%s=Dq^5+#?iE%P0;?QwP0BUHXw%Nw#B%Qd zkgopOvE{CT*|8=c61HEnnh2JKjJqu6emeMr@|a3IU(`dR*Mpf0Ko7Rqj7TI{G<5j3 z-EYn!g8O@!Tfl&bcD)L)^`fU&kly6P@t8WCh-NbCiD)VXpKFF}bA`v_nN%WrN~M)p zJ9{EsA|3V$e$?Ct*U^5rUIx2ovdhep(UF822ZTXuYV79LyAkA?GZQ0|zc*NO! V)Iq(=I}SJp$DIE7658gb_Ah&H{ssU5 literal 0 HcmV?d00001 diff --git a/py/__pycache__/__init__.cpython-312.pyc b/py/__pycache__/__init__.cpython-312.pyc index 1806aa98121342bd99856ac4d5c89430582ea3b7..df3368a0b0eb9a0068d5ae63eefa1c6f369a85a5 100644 GIT binary patch delta 126 zcmbQve1MtvG%qg~0}yCyu226skyny2VxqdQKng<&dk#Y`dlWk(LnVhM=fsKz2~EaZ zf?=5{srhc1IjNxqIr)hxsYQO8920*lFcoo5mS7Ci;R71P2*kxwK;i>4BO~Ko28p{2 Za(5XN?=nc;Wl+1zpm2{tzK91X4FC{8AI|^) delta 70 zcmX@WJe`^MG%qg~0}!+ptxZ2Tkynz@XQH|#s50=sZf2_k?HQr{o>6Uk=v2ck~0earWY7 z!}Lbr68W1rZnEjUmR&`$8g@8^3`to~yZ%e*KLY3?>-s~+eJsF!25QN__5GlcbQ=zV zmi4URTm11V#P8UJuK$J^`SC{MOu}YPh`uG_COuK*1rP_BkUiM-FUc_HHvShn7aHBAe#ms~H9`o!$Hh)M6h53>6Qbuph>wNRFWlmGW?aqvogT?frO!nLA_t&cd3f~Y7 z6X&rFHuTWoDT#V3;w5d2U=w+6_X>^JLVjZVn%s<~8U6-;wStb21Y5{+n-jDWr#&LK zM>cV=>8!YHM zsiw1_Nq(VJx!W~4jaCo2q&?^2IqV|;QUa1&#cU3z&HcHSp2O}dP2>}+LQXhbJ{z`R z{sFsv=+d-u9;(yEbQF)qJI}K9<|=Rn9X+SXmt%3BFohwaDlv2Jy3Cy`L(0@RCGR-O(df;>DjqtEE_}c zJK^AwK`M<@qG7rrcDJKi2H3UnKRlvnio6`I1N1rzd*W(?)TeoxS+`Pn+nf=fkGLkASTo4xxAR2&Rj*unb|Q0W|*jaE|!9cR2-dPEVXnt24pwvvxY*U z{zCuTDQmHk{sC2%Gt*2f{i15lc|S2ao|=@^(<`U%pL{s~L1LrtrA^<+mT8pype8Q; zeqrOx#dT2ojJN&S==h5-_}0R`zIVqreI0MUxc-m&dH|M)5;+OxNHp@-r3T|@i2F!3 zjvnUz(9$!}$^Ef$plz&)+o%{gFy`VP%T~&J9P*4F6doV;j48qsmwl{3deR_J{*xyC zxJ`J{=@~Z(TPBI(TQ*_b!EHIfM2E2D8aOcF7q^WzN^JY>6RqXjtpdY4nDKU}e$s0d zwtL-^4&hG@Y0@i1#M9)X#(sK%7@H1VViSbe0izTHX$IJzLSDR-PA3s-jym_KnPKX{ z>KVoW`&Y~ShJs~om**wjj*cs{?eY%E@Towt9fs{RlOH$jTZ;0K-<7WMQrCTDhhzJ@ znZo{Xu&_V%_;v&)c-q)jKt2wHc2tv(JGvi+e;z0jBU2l%T-Y4>dXYqn8?U{-iIxiF zj>x^tpXZ;cc7>c-rewJJwX!aXpbYt4bM2`)isq$k8qK__R)X#_*(&3jCx?$lhmMa9 z500N1oywO-qtnS`H2S3`X*i#Z^`W=O!In-FqQ92A9D_Saa-*eDWc~Ut!BmS5 delta 2820 zcmc&#eQaCR6@T|VKYxEdf5&m`BzA+HuO>9j(xgq?6t$&5mV_p>P)wTZx^Ddu-Szx|cbUV^ZLi|CZV3uwvW5~HX5&94w3mt2eYPPU92o|ZV27HfqB5R{d-3#NW_)9j~>2TUU;;e>r2z zE^1O8)O^{d$qlc9fSvjcFC%IoA~lo|c2#X!^Inc{Q`C>=Rd%XY!@1M~Yq%*h}u?o!^UC^XO5$+I|M%4z}iA^nWjQp0|_RhXzh% z1flBE^Z^s73&+CTgXYuSTo)T0iBKmS^7uPlI1UIM`R$@y9crK^U3v+SaCO=sP#bkp znHq8Dx}oaEUDWZspqg=aeK+6)>|_^irh^^qV^7a$67Ip4I^}K2i`0#GO>kLR=H8lo zOHq3oMP(JQUwVi-*pPBKnWplx_=0%8jZcq^dtq1IWrT#5cJ;AqN-8-(jV;K*|BBqr zzEUD+h?%@G$FQE^I|6=~J?xz|?V%Dh74DxIp$;zJdri_&NWi04gsMk_xvnp|qpK=> z2%S`E(V29+RR`~o!tQy;fSOQw zq9#9Z=N@8z@_Rl0Z*UfY`p@-(lzr_Bgx%CZ#q02A;!8(W1JuvH^!vR5UGfaX5Uhr1 zh>xXD#AB@Bk1g)QNqtbNVH(UMEz)qr2Sw3MTV!EfmX|Do=Gwvf@wo1X#2Q!g&)wgG zDam(k7(&hLBv5UmZDemt`zKn;*QWdDP1xVs1n#pG3UY6Iz?-Y>&7D*cF9*93*w4R5 z_W~nQKQ*%LKuF}mOmH+DX}Rct7TgIq!rlr-q{xdA_CYZ0`hSO?3C0cGkVhuCi`@?e zdDvrmsCe=_Vf%b9BP>*T>=)5R;RWf0a1o`Z*s*ZT2!ArNpRI(mJ&ys~$4N>gPw0Hj zs9sXFTqz~i45U)bk?{>v+h4@)9|B;8lP5?|-J~WC?5;^AHLt>FBpxRz=8GOgudv1F z)v-Ey7EH#!F_FlVAUUp!RhYz8PfZFlWPbF8a7fu`Bv?l^jeo$b!7Jqmsma-p2P zP}T~?>~f{FQp{;NvJ48#Qn8rTmeliV&6r=(&gMu>UM^PD9689EoNBI^Th?-z^(Vq>@Wj@XGZj)=(zq#y*0;J6=f_CkplEUQ({ z=gKM}ATksym6e(S;v`1^co@iOP?=V8Wn3ud$x#s1D-`8iymhfZCXDQE!T>)@e5%pE zLH5@~!UT@gzsoF`e470@ncw(F@`1QvOhpm8#1iRa=p0)~|6$E(n;jB1#^hUL5|`hau*`Q!x8=}$ zRJt9Nf$x&$lfvyJS`ek%J(-c?{f0a39)7sfuN)hh8ZHzVp0N91_G~t&2YL>DUv}r!~Bz8Aoanu00+d*f9efR zt_a(rD4Vy;g3+@rdS&ZQd_q_1l<`-jtw{fkg! zO9I6g>A?nbHyYono7^25`>^{)w0W34@w=0!Zq7d2JU+krpblyT2w|;;XLwIDN8{6c zQkS&C>0*vm`_CHpavdS;tN!HU70%XVtwNU1)-xejLH7no9gB|~%pN*A_sH~