diff --git a/.gitignore b/.gitignore index 54c9476..5bb30f3 100644 --- a/.gitignore +++ b/.gitignore @@ -173,3 +173,4 @@ db/* backends/nserver/venv backends/nserver/cache backends/nserver/modules/image_upscale/weights +cache/venvs/ diff --git a/nostr_dvm/dvm.py b/nostr_dvm/dvm.py index 91ede4e..27c09ca 100644 --- a/nostr_dvm/dvm.py +++ b/nostr_dvm/dvm.py @@ -1,5 +1,9 @@ +import importlib import json +import os +import subprocess from datetime import timedelta +from pathlib import Path from nostr_sdk import PublicKey, Keys, Client, Tag, Event, EventBuilder, Filter, HandleNotification, Timestamp, \ init_logger, LogLevel, Options, nip04_encrypt @@ -323,7 +327,8 @@ class DVM: except Exception as e: # Zapping back by error in post-processing is a risk for the DVM because work has been done, # but maybe something with parsing/uploading failed. Try to avoid errors here as good as possible - send_job_status_reaction(original_event, "error", content="Error in Post-processing: " + str(e), + send_job_status_reaction(original_event, "error", + content="Error in Post-processing: " + str(e), dvm_config=self.dvm_config, ) if amount > 0 and self.dvm_config.LNBITS_ADMIN_KEY != "": @@ -466,11 +471,24 @@ class DVM: for dvm in self.dvm_config.SUPPORTED_DVMS: try: if task == dvm.TASK: - request_form = dvm.create_request_from_nostr_event(job_event, self.client, - self.dvm_config) - result = dvm.process(request_form) + + request_form = dvm.create_request_from_nostr_event(job_event, self.client, self.dvm_config) + python_bin = (r'cache/venvs/' + os.path.basename(dvm_config.SCRIPT).split(".py")[0] + + "/bin/python") + subprocess.run([python_bin, dvm_config.SCRIPT, + '--request', json.dumps(request_form), + '--identifier', dvm_config.IDENTIFIER, + '--output', 'output.txt']) + + print("Finished processing, loading data..") + + with open(os.path.abspath('output.txt')) as f: + result = f.readlines()[0] + print(result) + #f.close() + os.remove(os.path.abspath('output.txt')) try: - post_processed = dvm.post_process(result, job_event) + post_processed = dvm.post_process(str(result), job_event) send_nostr_reply_event(post_processed, job_event.as_json()) except Exception as e: send_job_status_reaction(job_event, "error", content=str(e), @@ -495,7 +513,6 @@ class DVM: except Exception as e: print(e) - return self.client.handle_notifications(NotificationHandler()) diff --git a/nostr_dvm/interfaces/dvmtaskinterface.py b/nostr_dvm/interfaces/dvmtaskinterface.py index 8525f6f..83125d7 100644 --- a/nostr_dvm/interfaces/dvmtaskinterface.py +++ b/nostr_dvm/interfaces/dvmtaskinterface.py @@ -1,18 +1,16 @@ import json import os import subprocess +from subprocess import run import sys from threading import Thread - +from venv import create from nostr_sdk import Keys - from nostr_dvm.dvm import DVM from nostr_dvm.utils.admin_utils import AdminConfig from nostr_dvm.utils.dvmconfig import DVMConfig from nostr_dvm.utils.nip89_utils import NIP89Config -from nostr_dvm.utils.nostr_utils import check_and_set_private_key from nostr_dvm.utils.output_utils import post_process_result -from nostr_dvm.utils.zap_utils import check_and_set_ln_bits_keys class DVMTaskInterface: @@ -30,11 +28,13 @@ class DVMTaskInterface: admin_config: AdminConfig dependencies = [] + def __init__(self, name, dvm_config: DVMConfig, nip89config: NIP89Config, admin_config: AdminConfig = None, options=None, task=None): self.init(name, dvm_config, admin_config, nip89config, task) self.options = options - self.install_dependencies(self.dependencies) + self.make_venv(dvm_config) + def init(self, name, dvm_config, admin_config=None, nip89config=None, task=None): self.NAME = name @@ -58,6 +58,16 @@ class DVMTaskInterface: self.dvm_config = dvm_config self.admin_config = admin_config + def make_venv(self, dvm_config): + if dvm_config.SCRIPT != "": + dir = r'cache/venvs/' + os.path.basename(dvm_config.SCRIPT).split(".py")[0] + if not os.path.isdir(dir): + print(dir) + create(dir, with_pip=True, upgrade_deps=True) + for (module, package) in self.dependencies: + print("Installing Module: " + module) + run(["bin/pip", "install", package], cwd=dir) + def run(self): nostr_dvm_thread = Thread(target=self.DVM, args=[self.dvm_config, self.admin_config]) nostr_dvm_thread.start() @@ -87,16 +97,6 @@ class DVMTaskInterface: """Post-process the data and return the result Use default function, if not overwritten""" return post_process_result(result, event) - def install_dependencies(self, packages): - import pip - for module, package in packages: - try: - __import__(module) - except ImportError: - subprocess.check_call([sys.executable, "-m", "pip", "install", package]) - - - @staticmethod def set_options(request_form): print("Setting options...") @@ -105,3 +105,25 @@ class DVMTaskInterface: opts = json.loads(request_form["options"]) print(opts) return dict(opts) + + @staticmethod + def process_args(): + import argparse + parser = argparse.ArgumentParser() + parser.add_argument('--request', dest='request') + parser.add_argument('--identifier', dest='identifier') + parser.add_argument('--output', dest='output') + args = parser.parse_args() + return args + + @staticmethod + def write_output(result, output): + with open(os.path.abspath(output), 'w') as f: + f.write(result) + #f.close() + + def process_venv(self): + pass + + if __name__ == '__main__': + process_venv() diff --git a/nostr_dvm/tasks/advanced_search.py b/nostr_dvm/tasks/advanced_search.py index 793d304..7bd2816 100644 --- a/nostr_dvm/tasks/advanced_search.py +++ b/nostr_dvm/tasks/advanced_search.py @@ -27,9 +27,11 @@ class AdvancedSearch(DVMTaskInterface): TASK: str = "search-content" FIX_COST: float = 0 dvm_config: DVMConfig + dependencies = [("nostr-dvm", "nostr-dvm")] def __init__(self, name, dvm_config: DVMConfig, nip89config: NIP89Config, admin_config: AdminConfig = None, options=None): + dvm_config.SCRIPT = os.path.abspath(__file__) super().__init__(name, dvm_config, nip89config, admin_config, options) def is_input_supported(self, tags): @@ -177,19 +179,28 @@ def build_example(name, identifier, admin_config): admin_config=admin_config) -if __name__ == '__main__': - env_path = Path('.env') - if env_path.is_file(): - print(f'loading environment from {env_path.resolve()}') - dotenv.load_dotenv(env_path, verbose=True, override=True) - else: - raise FileNotFoundError(f'.env file not found at {env_path} ') +def process_venv(): + args = DVMTaskInterface.process_args() + dvm_config = build_default_config(args.identifier) + dvm = AdvancedSearch(name="", dvm_config=dvm_config, nip89config=NIP89Config(), admin_config=None) + result = dvm.process(json.loads(args.request)) + DVMTaskInterface.write_output(result, args.output) - admin_config = AdminConfig() - admin_config.REBROADCAST_NIP89 = False - admin_config.UPDATE_PROFILE = False +#if __name__ == '__main__': +# process_venv() - dvm = build_example("Advanced Nostr Search", "discovery_content_search", admin_config) - dvm.run() - keep_alive() + #if env_path.is_file(): + # print(f'loading environment from {env_path.resolve()}') + # dotenv.load_dotenv(env_path, verbose=True, override=True) + #else: + # raise FileNotFoundError(f'.env file not found at {env_path} ') + # + #admin_config = AdminConfig() + #admin_config.REBROADCAST_NIP89 = False + #admin_config.UPDATE_PROFILE = False + + #dvm = build_example("Advanced Nostr Search", "discovery_content_search", admin_config) + #dvm.run() + + #keep_alive() diff --git a/nostr_dvm/tasks/convert_media.py b/nostr_dvm/tasks/convert_media.py index ef1666c..20ff106 100644 --- a/nostr_dvm/tasks/convert_media.py +++ b/nostr_dvm/tasks/convert_media.py @@ -1,4 +1,5 @@ import json +import os from pathlib import Path import dotenv @@ -30,6 +31,7 @@ class MediaConverter(DVMTaskInterface): def __init__(self, name, dvm_config: DVMConfig, nip89config: NIP89Config, admin_config: AdminConfig = None, options=None): + dvm_config.SCRIPT = os.path.abspath(__file__) super().__init__(name, dvm_config, nip89config, admin_config, options) def is_input_supported(self, tags): @@ -106,20 +108,28 @@ def build_example(name, identifier, admin_config): return MediaConverter(name=name, dvm_config=dvm_config, nip89config=nip89config, admin_config=admin_config) +def process_venv(): + args = DVMTaskInterface.process_args() + dvm_config = build_default_config(args.identifier) + dvm = MediaConverter(name="", dvm_config=dvm_config, nip89config=NIP89Config(), admin_config=None) + result = dvm.process(json.loads(args.request)) + DVMTaskInterface.write_output(result, args.output) -if __name__ == '__main__': - env_path = Path('.env') - if env_path.is_file(): - print(f'loading environment from {env_path.resolve()}') - dotenv.load_dotenv(env_path, verbose=True, override=True) - else: - raise FileNotFoundError(f'.env file not found at {env_path} ') +#if __name__ == '__main__': +# process_venv() - admin_config = AdminConfig() - admin_config.REBROADCAST_NIP89 = False - admin_config.UPDATE_PROFILE = False + #env_path = Path('.env') + #if env_path.is_file(): + # print(f'loading environment from {env_path.resolve()}') + # dotenv.load_dotenv(env_path, verbose=True, override=True) + #else: + # raise FileNotFoundError(f'.env file not found at {env_path} ') - dvm = build_example("Media Bringer", "media_converter", admin_config) - dvm.run() + #admin_config = AdminConfig() + #admin_config.REBROADCAST_NIP89 = False + #admin_config.UPDATE_PROFILE = False - keep_alive() + #dvm = build_example("Media Bringer", "media_converter", admin_config) + #dvm.run() + + #keep_alive() diff --git a/nostr_dvm/tasks/discovery_inactive_follows.py b/nostr_dvm/tasks/discovery_inactive_follows.py index 08a0aeb..6a52df5 100644 --- a/nostr_dvm/tasks/discovery_inactive_follows.py +++ b/nostr_dvm/tasks/discovery_inactive_follows.py @@ -33,6 +33,7 @@ class DiscoverInactiveFollows(DVMTaskInterface): def __init__(self, name, dvm_config: DVMConfig, nip89config: NIP89Config, admin_config: AdminConfig = None, options=None): + dvm_config.SCRIPT = os.path.abspath(__file__) super().__init__(name, dvm_config, nip89config, admin_config, options) def is_input_supported(self, tags): @@ -198,19 +199,26 @@ def build_example(name, identifier, admin_config): return DiscoverInactiveFollows(name=name, dvm_config=dvm_config, nip89config=nip89config, admin_config=admin_config) +def process_venv(): + args = DVMTaskInterface.process_args() + dvm_config = build_default_config(args.identifier) + dvm = DiscoverInactiveFollows(name="", dvm_config=dvm_config, nip89config=NIP89Config(), admin_config=None) + result = dvm.process(json.loads(args.request)) + DVMTaskInterface.write_output(result, args.output) -if __name__ == '__main__': - env_path = Path('.env') - if env_path.is_file(): - print(f'loading environment from {env_path.resolve()}') - dotenv.load_dotenv(env_path, verbose=True, override=True) - else: - raise FileNotFoundError(f'.env file not found at {env_path} ') +#if __name__ == '__main__': +# process_venv() + #env_path = Path('.env') + #if env_path.is_file(): + # print(f'loading environment from {env_path.resolve()}') + # dotenv.load_dotenv(env_path, verbose=True, override=True) + #else: + # raise FileNotFoundError(f'.env file not found at {env_path} ') - admin_config = AdminConfig() - admin_config.REBROADCAST_NIP89 = False - admin_config.UPDATE_PROFILE = False - dvm = build_example("Bygones", "discovery_inactive_follows", admin_config) - dvm.run() + #admin_config = AdminConfig() + #admin_config.REBROADCAST_NIP89 = False + #admin_config.UPDATE_PROFILE = False + #dvm = build_example("Bygones", "discovery_inactive_follows", admin_config) + #dvm.run() - keep_alive() + #keep_alive() diff --git a/nostr_dvm/tasks/imagegeneration_openai_dalle.py b/nostr_dvm/tasks/imagegeneration_openai_dalle.py index 920bfa0..3412784 100644 --- a/nostr_dvm/tasks/imagegeneration_openai_dalle.py +++ b/nostr_dvm/tasks/imagegeneration_openai_dalle.py @@ -1,5 +1,6 @@ import json import os +import time from io import BytesIO from pathlib import Path @@ -28,10 +29,12 @@ class ImageGenerationDALLE(DVMTaskInterface): KIND: int = EventDefinitions.KIND_NIP90_GENERATE_IMAGE TASK: str = "text-to-image" FIX_COST: float = 120 - dependencies = [("openai", "openai==1.3.5")] + dependencies = [("nostr-dvm", "nostr-dvm"), + ("openai", "openai==1.3.5")] def __init__(self, name, dvm_config: DVMConfig, nip89config: NIP89Config, admin_config: AdminConfig = None, options=None): + dvm_config.SCRIPT = os.path.abspath(__file__) super().__init__(name, dvm_config, nip89config, admin_config, options) def is_input_supported(self, tags): @@ -107,6 +110,7 @@ class ImageGenerationDALLE(DVMTaskInterface): n=int(options['number']), ) + image_url = response.data[0].url # rehost the result instead of relying on the openai link response = requests.get(image_url) @@ -151,18 +155,31 @@ def build_example(name, identifier, admin_config): return ImageGenerationDALLE(name=name, dvm_config=dvm_config, nip89config=nip89config, admin_config=admin_config) -if __name__ == '__main__': - env_path = Path('.env') - if env_path.is_file(): - print(f'loading environment from {env_path.resolve()}') - dotenv.load_dotenv(env_path, verbose=True, override=True) - else: - raise FileNotFoundError(f'.env file not found at {env_path} ') +def process_venv(): + args = DVMTaskInterface.process_args() + dvm_config = build_default_config(args.identifier) + dvm = ImageGenerationDALLE(name="", dvm_config=dvm_config, nip89config=NIP89Config(), admin_config=None) + result = "" + while result == "": + result = dvm.process(json.loads(args.request)) + time.sleep(10) - admin_config = AdminConfig() - admin_config.REBROADCAST_NIP89 = False - admin_config.UPDATE_PROFILE = False - dvm = build_example("Dall-E 3", "dalle3", admin_config) - dvm.run() - keep_alive() + DVMTaskInterface.write_output(result, args.output) + +#if __name__ == '__main__': +# process_venv() + #env_path = Path('.env') + #if env_path.is_file(): + # print(f'loading environment from {env_path.resolve()}') + # dotenv.load_dotenv(env_path, verbose=True, override=True) + #else: + # raise FileNotFoundError(f'.env file not found at {env_path} ') + + #admin_config = AdminConfig() + #admin_config.REBROADCAST_NIP89 = False + #admin_config.UPDATE_PROFILE = False + #dvm = build_example("Dall-E 3", "dalle3", admin_config) + #dvm.run() + + #keep_alive() diff --git a/nostr_dvm/tasks/imagegeneration_replicate_sdxl.py b/nostr_dvm/tasks/imagegeneration_replicate_sdxl.py index 480d0ba..0aa7ab0 100644 --- a/nostr_dvm/tasks/imagegeneration_replicate_sdxl.py +++ b/nostr_dvm/tasks/imagegeneration_replicate_sdxl.py @@ -1,15 +1,11 @@ import json import os from io import BytesIO -from pathlib import Path - -import dotenv import requests from PIL import Image from nostr_dvm.interfaces.dvmtaskinterface import DVMTaskInterface from nostr_dvm.utils.admin_utils import AdminConfig -from nostr_dvm.utils.backend_utils import keep_alive from nostr_dvm.utils.definitions import EventDefinitions from nostr_dvm.utils.dvmconfig import DVMConfig, build_default_config from nostr_dvm.utils.nip89_utils import NIP89Config, check_and_set_d_tag @@ -29,10 +25,12 @@ class ImageGenerationReplicateSDXL(DVMTaskInterface): KIND: int = EventDefinitions.KIND_NIP90_GENERATE_IMAGE TASK: str = "text-to-image" FIX_COST: float = 120 - dependencies = [("replicate", "replicate==0.21.1")] + dependencies = [("nostr-dvm", "nostr-dvm"), + ("replicate", "replicate==0.21.1")] def __init__(self, name, dvm_config: DVMConfig, nip89config: NIP89Config, admin_config: AdminConfig = None, options=None): + dvm_config.SCRIPT = os.path.abspath(__file__) super().__init__(name, dvm_config, nip89config, admin_config, options) def is_input_supported(self, tags): @@ -147,18 +145,26 @@ def build_example(name, identifier, admin_config): admin_config=admin_config) -if __name__ == '__main__': - env_path = Path('.env') - if env_path.is_file(): - print(f'loading environment from {env_path.resolve()}') - dotenv.load_dotenv(env_path, verbose=True, override=True) - else: - raise FileNotFoundError(f'.env file not found at {env_path} ') +def process_venv(): + args = DVMTaskInterface.process_args() + dvm_config = build_default_config(args.identifier) + dvm = ImageGenerationReplicateSDXL(name="", dvm_config=dvm_config, nip89config=NIP89Config(), admin_config=None) + result = dvm.process(json.loads(args.request)) + DVMTaskInterface.write_output(result, args.output) - admin_config = AdminConfig() - admin_config.REBROADCAST_NIP89 = False - admin_config.UPDATE_PROFILE = False - dvm = build_example("Stable Diffusion XL", "replicate_sdxl", admin_config) - dvm.run() +#if __name__ == '__main__': +# process_venv() + #env_path = Path('.env') + #if env_path.is_file(): + # print(f'loading environment from {env_path.resolve()}') + # dotenv.load_dotenv(env_path, verbose=True, override=True) + #else: + # raise FileNotFoundError(f'.env file not found at {env_path} ') - keep_alive() + #admin_config = AdminConfig() + #admin_config.REBROADCAST_NIP89 = False + #admin_config.UPDATE_PROFILE = False + #dvm = build_example("Stable Diffusion XL", "replicate_sdxl", admin_config) + #dvm.run() + + #keep_alive() diff --git a/nostr_dvm/tasks/textextraction_google.py b/nostr_dvm/tasks/textextraction_google.py index cbae2c3..2c24ef7 100644 --- a/nostr_dvm/tasks/textextraction_google.py +++ b/nostr_dvm/tasks/textextraction_google.py @@ -27,10 +27,13 @@ class SpeechToTextGoogle(DVMTaskInterface): TASK: str = "speech-to-text" FIX_COST: float = 10 PER_UNIT_COST: float = 0.1 - dependencies = [("speech_recognition", "SpeechRecognition==3.10.0")] + dependencies = [("nostr-dvm", "nostr-dvm"), + ("speech_recognition", "SpeechRecognition==3.10.0")] + def __init__(self, name, dvm_config: DVMConfig, nip89config: NIP89Config, admin_config: AdminConfig = None, options=None): + dvm_config.SCRIPT = os.path.abspath(__file__) super().__init__(name, dvm_config, nip89config, admin_config, options) if options is None: options = {} @@ -155,20 +158,26 @@ def build_example(name, identifier, admin_config): return SpeechToTextGoogle(name=name, dvm_config=dvm_config, nip89config=nip89config, admin_config=admin_config, options=options) +def process_venv(): + args = DVMTaskInterface.process_args() + dvm_config = build_default_config(args.identifier) + dvm = SpeechToTextGoogle(name="", dvm_config=dvm_config, nip89config=NIP89Config(), admin_config=None) + result = dvm.process(json.loads(args.request)) + DVMTaskInterface.write_output(result, args.output) -if __name__ == '__main__': - env_path = Path('.env') - if env_path.is_file(): - print(f'loading environment from {env_path.resolve()}') - dotenv.load_dotenv(env_path, verbose=True, override=True) - else: - raise FileNotFoundError(f'.env file not found at {env_path} ') +#if __name__ == '__main__': +# env_path = Path('.env') +# if env_path.is_file(): +# print(f'loading environment from {env_path.resolve()}') +# dotenv.load_dotenv(env_path, verbose=True, override=True) +# else: +# raise FileNotFoundError(f'.env file not found at {env_path} ') +# +# admin_config = AdminConfig() +# admin_config.REBROADCAST_NIP89 = False +# admin_config.UPDATE_PROFILE = False +# dvm = build_example("Transcriptor", "speech_recognition", admin_config) +# dvm.run() - admin_config = AdminConfig() - admin_config.REBROADCAST_NIP89 = False - admin_config.UPDATE_PROFILE = False - dvm = build_example("Transcriptor", "speech_recognition", admin_config) - dvm.run() - - keep_alive() + # keep_alive() diff --git a/nostr_dvm/tasks/textextraction_pdf.py b/nostr_dvm/tasks/textextraction_pdf.py index e9062cf..8101840 100644 --- a/nostr_dvm/tasks/textextraction_pdf.py +++ b/nostr_dvm/tasks/textextraction_pdf.py @@ -26,11 +26,13 @@ class TextExtractionPDF(DVMTaskInterface): KIND: int = EventDefinitions.KIND_NIP90_EXTRACT_TEXT TASK: str = "pdf-to-text" FIX_COST: float = 0 - dependencies = [("pypdf", "pypdf==3.17.1")] + dependencies = [("nostr-dvm", "nostr-dvm"), + ("pypdf", "pypdf==3.17.1")] def __init__(self, name, dvm_config: DVMConfig, nip89config: NIP89Config, admin_config: AdminConfig = None, options=None): + dvm_config.SCRIPT = os.path.abspath(__file__) super().__init__(name, dvm_config, nip89config, admin_config, options) @@ -116,19 +118,26 @@ def build_example(name, identifier, admin_config): return TextExtractionPDF(name=name, dvm_config=dvm_config, nip89config=nip89config, admin_config=admin_config) +def process_venv(): + args = DVMTaskInterface.process_args() + dvm_config = build_default_config(args.identifier) + dvm = TextExtractionPDF(name="", dvm_config=dvm_config, nip89config=NIP89Config(), admin_config=None) + result = dvm.process(json.loads(args.request)) + DVMTaskInterface.write_output(result, args.output) -if __name__ == '__main__': - env_path = Path('.env') - if env_path.is_file(): - print(f'loading environment from {env_path.resolve()}') - dotenv.load_dotenv(env_path, verbose=True, override=True) - else: - raise FileNotFoundError(f'.env file not found at {env_path} ') - admin_config = AdminConfig() - admin_config.REBROADCAST_NIP89 = False - admin_config.UPDATE_PROFILE = False - dvm = build_example("PDF Extractor", "pdf_extractor", admin_config) - dvm.run() +#if __name__ == '__main__': +# env_path = Path('.env') +# if env_path.is_file(): +# print(f'loading environment from {env_path.resolve()}') +# dotenv.load_dotenv(env_path, verbose=True, override=True) +# else: +# raise FileNotFoundError(f'.env file not found at {env_path} ') - keep_alive() +# admin_config = AdminConfig() +# admin_config.REBROADCAST_NIP89 = False +# admin_config.UPDATE_PROFILE = False +# dvm = build_example("PDF Extractor", "pdf_extractor", admin_config) +# dvm.run() + +# keep_alive() diff --git a/nostr_dvm/tasks/textgeneration_llmlite.py b/nostr_dvm/tasks/textgeneration_llmlite.py index 0a692e7..38090d7 100644 --- a/nostr_dvm/tasks/textgeneration_llmlite.py +++ b/nostr_dvm/tasks/textgeneration_llmlite.py @@ -24,10 +24,12 @@ class TextGenerationOLLAMA(DVMTaskInterface): KIND: int = EventDefinitions.KIND_NIP90_GENERATE_TEXT TASK: str = "text-to-text" FIX_COST: float = 0 - dependencies = [("litellm", "litellm==1.12.3")] + dependencies = [("nostr-dvm", "nostr-dvm"), + ("litellm", "litellm==1.12.3")] def __init__(self, name, dvm_config: DVMConfig, nip89config: NIP89Config, admin_config: AdminConfig = None, options=None): + dvm_config.SCRIPT = os.path.abspath(__file__) super().__init__(name, dvm_config, nip89config, admin_config, options) @@ -125,19 +127,27 @@ def build_example(name, identifier, admin_config): return TextGenerationOLLAMA(name=name, dvm_config=dvm_config, nip89config=nip89config, admin_config=admin_config, options=options) -if __name__ == '__main__': - env_path = Path('.env') - if env_path.is_file(): - print(f'loading environment from {env_path.resolve()}') - dotenv.load_dotenv(env_path, verbose=True, override=True) - else: - raise FileNotFoundError(f'.env file not found at {env_path} ') +def process_venv(): + args = DVMTaskInterface.process_args() + dvm_config = build_default_config(args.identifier) + dvm = TextGenerationOLLAMA(name="", dvm_config=dvm_config, nip89config=NIP89Config(), admin_config=None) + result = dvm.process(json.loads(args.request)) + DVMTaskInterface.write_output(result, args.output) - admin_config = AdminConfig() - admin_config.REBROADCAST_NIP89 = False - admin_config.UPDATE_PROFILE = False - dvm = build_example("LLM", "llmlite", admin_config) - dvm.run() +#if __name__ == '__main__': +# env_path = Path('.env') +# if env_path.is_file(): +# print(f'loading environment from {env_path.resolve()}') +# dotenv.load_dotenv(env_path, verbose=True, override=True) +# else: +# raise FileNotFoundError(f'.env file not found at {env_path} ') +# +# admin_config = AdminConfig() +# admin_config.REBROADCAST_NIP89 = False +# admin_config.UPDATE_PROFILE = False +# +# dvm = build_example("LLM", "llmlite", admin_config) +# dvm.run() - keep_alive() +# keep_alive() diff --git a/nostr_dvm/tasks/translation_google.py b/nostr_dvm/tasks/translation_google.py index 642cf49..e9bcee7 100644 --- a/nostr_dvm/tasks/translation_google.py +++ b/nostr_dvm/tasks/translation_google.py @@ -1,4 +1,5 @@ import json +import os from pathlib import Path import dotenv @@ -25,10 +26,12 @@ class TranslationGoogle(DVMTaskInterface): KIND: int = EventDefinitions.KIND_NIP90_TRANSLATE_TEXT TASK: str = "translation" FIX_COST: float = 0 - dependencies = [("translatepy", "translatepy==2.3")] + dependencies = [("nostr-dvm", "nostr-dvm"), + ("translatepy", "translatepy==2.3")] def __init__(self, name, dvm_config: DVMConfig, nip89config: NIP89Config, admin_config: AdminConfig = None, options=None): + dvm_config.SCRIPT = os.path.abspath(__file__) super().__init__(name, dvm_config, nip89config, admin_config, options) def is_input_supported(self, tags): @@ -141,18 +144,31 @@ def build_example(name, identifier, admin_config): return TranslationGoogle(name=name, dvm_config=dvm_config, nip89config=nip89config, admin_config=admin_config) -if __name__ == '__main__': - env_path = Path('.env') - if env_path.is_file(): - print(f'loading environment from {env_path.resolve()}') - dotenv.load_dotenv(env_path, verbose=True, override=True) - else: - raise FileNotFoundError(f'.env file not found at {env_path} ') - admin_config = AdminConfig() - admin_config.REBROADCAST_NIP89 = False - admin_config.UPDATE_PROFILE = False - dvm = build_example("Google Translator", "google_translator", admin_config) - dvm.run() - keep_alive() +def process_venv(): + args = DVMTaskInterface.process_args() + dvm_config = build_default_config(args.identifier) + dvm = TranslationGoogle(name="", dvm_config=dvm_config, nip89config=NIP89Config(), admin_config=None) + result = dvm.process(json.loads(args.request)) + DVMTaskInterface.write_output(result, args.output) + + + +#if __name__ == '__main__': + #process_venv() + + #env_path = Path('.env') + #if env_path.is_file(): + # print(f'loading environment from {env_path.resolve()}') + # dotenv.load_dotenv(env_path, verbose=True, override=True) + #else: + # raise FileNotFoundError(f'.env file not found at {env_path} ') + + #admin_config = AdminConfig() + #admin_config.REBROADCAST_NIP89 = False + #admin_config.UPDATE_PROFILE = False + #dvm = build_example("Google Translator", "google_translator", admin_config) + #dvm.run() + + #keep_alive() diff --git a/nostr_dvm/tasks/translation_libretranslate.py b/nostr_dvm/tasks/translation_libretranslate.py index 55ab201..9a89c3b 100644 --- a/nostr_dvm/tasks/translation_libretranslate.py +++ b/nostr_dvm/tasks/translation_libretranslate.py @@ -13,7 +13,6 @@ from nostr_dvm.utils.dvmconfig import DVMConfig, build_default_config from nostr_dvm.utils.nip89_utils import NIP89Config, check_and_set_d_tag from nostr_dvm.utils.nostr_utils import get_referenced_event_by_id, get_event_by_id - """ This File contains a Module to call Libre Translate Services @@ -32,6 +31,7 @@ class TranslationLibre(DVMTaskInterface): def __init__(self, name, dvm_config: DVMConfig, nip89config: NIP89Config, admin_config: AdminConfig = None, options=None, task=None): + dvm_config.SCRIPT = os.path.abspath(__file__) super().__init__(name, dvm_config, nip89config, admin_config, options, task) def is_input_supported(self, tags): @@ -81,9 +81,9 @@ class TranslationLibre(DVMTaskInterface): def process(self, request_form): options = DVMTaskInterface.set_options(request_form) request = { - "q": options["text"], + "q": options["text"], "source": "auto", - "target": options["language"] + "target": options["language"] } if options["libre_api_key"] != "": request["api_key"] = options["libre_api_key"] @@ -95,10 +95,10 @@ class TranslationLibre(DVMTaskInterface): reply = json.loads(response.text) if reply.get("translatedText"): translated_text = reply['translatedText'] - #untested - #confidence = reply["detectedLanguage"]['confidence'] - #language = reply["detectedLanguage"]['language'] - #print(translated_text + "language: " + language + "conf: " + confidence) + # untested + # confidence = reply["detectedLanguage"]['confidence'] + # language = reply["detectedLanguage"]['language'] + # print(translated_text + "language: " + language + "conf: " + confidence) else: return response.text @@ -125,12 +125,18 @@ def build_example(name, identifier, admin_config): "nip90Params": { "language": { "required": False, - "values": ["en", "az", "be", "bg", "bn", "bs", "ca", "ceb", "co", "cs", "cy", "da", "de", "el", "eo", "es", - "et", "eu", "fa", "fi", "fr", "fy", "ga", "gd", "gl", "gu", "ha", "haw", "hi", "hmn", "hr", "ht", - "hu", "hy", "id", "ig", "is", "it", "he", "ja", "jv", "ka", "kk", "km", "kn", "ko", "ku", "ky", - "la", "lb", "lo", "lt", "lv", "mg", "mi", "mk", "ml", "mn", "mr", "ms", "mt", "my", "ne", "nl", - "no", "ny", "or", "pa", "pl", "ps", "pt", "ro", "ru", "sd", "si", "sk", "sl", "sm", "sn", "so", - "sq", "sr", "st", "su", "sv", "sw", "ta", "te", "tg", "th", "tl", "tr", "ug", "uk", "ur", "uz", + "values": ["en", "az", "be", "bg", "bn", "bs", "ca", "ceb", "co", "cs", "cy", "da", "de", "el", "eo", + "es", + "et", "eu", "fa", "fi", "fr", "fy", "ga", "gd", "gl", "gu", "ha", "haw", "hi", "hmn", "hr", + "ht", + "hu", "hy", "id", "ig", "is", "it", "he", "ja", "jv", "ka", "kk", "km", "kn", "ko", "ku", + "ky", + "la", "lb", "lo", "lt", "lv", "mg", "mi", "mk", "ml", "mn", "mr", "ms", "mt", "my", "ne", + "nl", + "no", "ny", "or", "pa", "pl", "ps", "pt", "ro", "ru", "sd", "si", "sk", "sl", "sm", "sn", + "so", + "sq", "sr", "st", "su", "sv", "sw", "ta", "te", "tg", "th", "tl", "tr", "ug", "uk", "ur", + "uz", "vi", "xh", "yi", "yo", "zh", "zu"] } } @@ -143,18 +149,25 @@ def build_example(name, identifier, admin_config): admin_config=admin_config, options=options) -if __name__ == '__main__': - env_path = Path('.env') - if env_path.is_file(): - print(f'loading environment from {env_path.resolve()}') - dotenv.load_dotenv(env_path, verbose=True, override=True) - else: - raise FileNotFoundError(f'.env file not found at {env_path} ') +def process_venv(): + args = DVMTaskInterface.process_args() + dvm_config = build_default_config(args.identifier) + dvm = TranslationLibre(name="", dvm_config=dvm_config, nip89config=NIP89Config(), admin_config=None) + result = dvm.process(json.loads(args.request)) + DVMTaskInterface.write_output(result, args.output) - admin_config = AdminConfig() - admin_config.REBROADCAST_NIP89 = False - admin_config.UPDATE_PROFILE = False - dvm = build_example("Libre Translator", "libre_translator", admin_config) - dvm.run() - - keep_alive() +# if __name__ == '__main__': +# env_path = Path('.env') +# if env_path.is_file(): +# print(f'loading environment from {env_path.resolve()}') +# dotenv.load_dotenv(env_path, verbose=True, override=True) +# else: +# raise FileNotFoundError(f'.env file not found at {env_path} ') +# +# admin_config = AdminConfig() +# admin_config.REBROADCAST_NIP89 = False +# admin_config.UPDATE_PROFILE = False +# dvm = build_example("Libre Translator", "libre_translator", admin_config) +# dvm.run() +# +# keep_alive() diff --git a/nostr_dvm/tasks/trending_notes_nostrband.py b/nostr_dvm/tasks/trending_notes_nostrband.py index 480de1f..b915ed7 100644 --- a/nostr_dvm/tasks/trending_notes_nostrband.py +++ b/nostr_dvm/tasks/trending_notes_nostrband.py @@ -29,6 +29,7 @@ class TrendingNotesNostrBand(DVMTaskInterface): def __init__(self, name, dvm_config: DVMConfig, nip89config: NIP89Config, admin_config: AdminConfig = None, options=None): + dvm_config.SCRIPT = os.path.abspath(__file__) super().__init__(name, dvm_config, nip89config, admin_config, options) def is_input_supported(self, tags): @@ -117,20 +118,26 @@ def build_example(name, identifier, admin_config): return TrendingNotesNostrBand(name=name, dvm_config=dvm_config, nip89config=nip89config, admin_config=admin_config) +def process_venv(): + args = DVMTaskInterface.process_args() + dvm_config = build_default_config(args.identifier) + dvm = TrendingNotesNostrBand(name="", dvm_config=dvm_config, nip89config=NIP89Config(), admin_config=None) + result = dvm.process(json.loads(args.request)) + DVMTaskInterface.write_output(result, args.output) -if __name__ == '__main__': - env_path = Path('.env') - if env_path.is_file(): - print(f'loading environment from {env_path.resolve()}') - dotenv.load_dotenv(env_path, verbose=True, override=True) - else: - raise FileNotFoundError(f'.env file not found at {env_path} ') - - admin_config = AdminConfig() - admin_config.REBROADCAST_NIP89 = False - admin_config.UPDATE_PROFILE = False - - dvm = build_example("Trending Notes on Nostr.band", "trending_notes_nostrband", admin_config) - dvm.run() - - keep_alive() +#if __name__ == '__main__': +# env_path = Path('.env') +# if env_path.is_file(): +# print(f'loading environment from {env_path.resolve()}') +# dotenv.load_dotenv(env_path, verbose=True, override=True) +# else: +# raise FileNotFoundError(f'.env file not found at {env_path} ') +# +# admin_config = AdminConfig() +# admin_config.REBROADCAST_NIP89 = False +# admin_config.UPDATE_PROFILE = False +# +# dvm = build_example("Trending Notes on Nostr.band", "trending_notes_nostrband", admin_config) +# dvm.run() +# +# keep_alive() diff --git a/nostr_dvm/tasks/videogeneration_replicate_svd.py b/nostr_dvm/tasks/videogeneration_replicate_svd.py index 9114446..7bf2fe8 100644 --- a/nostr_dvm/tasks/videogeneration_replicate_svd.py +++ b/nostr_dvm/tasks/videogeneration_replicate_svd.py @@ -1,5 +1,6 @@ import json import os +import subprocess from io import BytesIO from pathlib import Path @@ -30,12 +31,18 @@ class VideoGenerationReplicateSVD(DVMTaskInterface): KIND: int = EventDefinitions.KIND_NIP90_GENERATE_VIDEO TASK: str = "image-to-video" FIX_COST: float = 120 - dependencies = [("replicate", "replicate==0.21.1")] + dependencies = [("nostr-dvm", "nostr-dvm"), + ("replicate", "replicate==0.21.1")] def __init__(self, name, dvm_config: DVMConfig, nip89config: NIP89Config, admin_config: AdminConfig = None, options=None): + dvm_config.SCRIPT = os.path.abspath(__file__) + print(dvm_config.SCRIPT) super().__init__(name, dvm_config, nip89config, admin_config, options) + + + def is_input_supported(self, tags): for tag in tags: if tag.as_vec()[0] == 'i': @@ -134,20 +141,27 @@ def build_example(name, identifier, admin_config): return VideoGenerationReplicateSVD(name=name, dvm_config=dvm_config, nip89config=nip89config, admin_config=admin_config) +def process_venv(): + args = DVMTaskInterface.process_args() + dvm_config = build_default_config(args.identifier) + dvm = VideoGenerationReplicateSVD(name="", dvm_config=dvm_config, nip89config=NIP89Config(), admin_config=None) + result = dvm.process(json.loads(args.request)) + DVMTaskInterface.write_output(result, args.output) -if __name__ == '__main__': - env_path = Path('.env') - if env_path.is_file(): - print(f'loading environment from {env_path.resolve()}') - dotenv.load_dotenv(env_path, verbose=True, override=True) - else: - raise FileNotFoundError(f'.env file not found at {env_path} ') - admin_config = AdminConfig() - admin_config.REBROADCAST_NIP89 = False - admin_config.UPDATE_PROFILE = False - - dvm = build_example("Stable Video Diffusion", "replicate_svd", admin_config) - dvm.run() - - keep_alive() +#if __name__ == '__main__': +# env_path = Path('.env') +# if env_path.is_file(): +# print(f'loading environment from {env_path.resolve()}') +# dotenv.load_dotenv(env_path, verbose=True, override=True) +# else: +# raise FileNotFoundError(f'.env file not found at {env_path} ') +# +# admin_config = AdminConfig() +# admin_config.REBROADCAST_NIP89 = False +# admin_config.UPDATE_PROFILE = False +# +# dvm = build_example("Stable Video Diffusion", "replicate_svd", admin_config) +# dvm.run() +# +# keep_alive() diff --git a/nostr_dvm/utils/dvmconfig.py b/nostr_dvm/utils/dvmconfig.py index f43cde4..976cd74 100644 --- a/nostr_dvm/utils/dvmconfig.py +++ b/nostr_dvm/utils/dvmconfig.py @@ -27,6 +27,8 @@ class DVMConfig: LNBITS_ADMIN_KEY = '' # In order to pay invoices, e.g. from the bot to DVMs, or reimburse users. LNBITS_URL = 'https://lnbits.com' LN_ADDRESS = '' + SCRIPT = '' + IDENTIFIER = '' DB: str NEW_USER_BALANCE: int = 0 # Free credits for new users NIP89: NIP89Config @@ -36,6 +38,7 @@ class DVMConfig: def build_default_config(identifier): dvm_config = DVMConfig() dvm_config.PRIVATE_KEY = check_and_set_private_key(identifier) + dvm_config.IDENTIFIER = identifier npub = Keys.from_sk_str(dvm_config.PRIVATE_KEY).public_key().to_bech32() invoice_key, admin_key, wallet_id, user_id, lnaddress = check_and_set_ln_bits_keys(identifier, npub) dvm_config.LNBITS_INVOICE_KEY = invoice_key diff --git a/tests/test_dvm_client.py b/tests/test_dvm_client.py index 298066e..7a5dd35 100644 --- a/tests/test_dvm_client.py +++ b/tests/test_dvm_client.py @@ -69,7 +69,7 @@ def nostr_client_test_image(prompt): def nostr_client_test_image_private(prompt, cashutoken): keys = Keys.from_sk_str(check_and_set_private_key("test_client")) - receiver_keys = Keys.from_sk_str(check_and_set_private_key("sketcher")) + receiver_keys = Keys.from_sk_str(check_and_set_private_key("replicate_sdxl")) # TODO more advanced logic, more parsing, params etc, just very basic test functions for now @@ -125,13 +125,13 @@ def nostr_client(): client.subscribe([dm_zap_filter, dvm_filter]) #nostr_client_test_translation("This is the result of the DVM in spanish", "text", "es", 20, 20) - nostr_client_test_translation("note1p8cx2dz5ss5gnk7c59zjydcncx6a754c0hsyakjvnw8xwlm5hymsnc23rs", "event", "es", 20,20) + #nostr_client_test_translation("note1p8cx2dz5ss5gnk7c59zjydcncx6a754c0hsyakjvnw8xwlm5hymsnc23rs", "event", "es", 20,20) #nostr_client_test_translation("44a0a8b395ade39d46b9d20038b3f0c8a11168e67c442e3ece95e4a1703e2beb", "event", "zh", 20, 20) - #nostr_client_test_image("a beautiful purple ostrich watching the sunset") + nostr_client_test_image("a beautiful purple ostrich watching the sunset") #cashutoken = "cashuAeyJ0b2tlbiI6W3sicHJvb2ZzIjpbeyJpZCI6InZxc1VRSVorb0sxOSIsImFtb3VudCI6MSwiQyI6IjAyNWU3ODZhOGFkMmExYTg0N2YxMzNiNGRhM2VhMGIyYWRhZGFkOTRiYzA4M2E2NWJjYjFlOTgwYTE1NGIyMDA2NCIsInNlY3JldCI6InQ1WnphMTZKMGY4UElQZ2FKTEg4V3pPck5rUjhESWhGa291LzVzZFd4S0U9In0seyJpZCI6InZxc1VRSVorb0sxOSIsImFtb3VudCI6NCwiQyI6IjAyOTQxNmZmMTY2MzU5ZWY5ZDc3MDc2MGNjZmY0YzliNTMzMzVmZTA2ZGI5YjBiZDg2Njg5Y2ZiZTIzMjVhYWUwYiIsInNlY3JldCI6IlRPNHB5WE43WlZqaFRQbnBkQ1BldWhncm44UHdUdE5WRUNYWk9MTzZtQXM9In0seyJpZCI6InZxc1VRSVorb0sxOSIsImFtb3VudCI6MTYsIkMiOiIwMmRiZTA3ZjgwYmMzNzE0N2YyMDJkNTZiMGI3ZTIzZTdiNWNkYTBhNmI3Yjg3NDExZWYyOGRiZDg2NjAzNzBlMWIiLCJzZWNyZXQiOiJHYUNIdHhzeG9HM3J2WWNCc0N3V0YxbU1NVXczK0dDN1RKRnVwOHg1cURzPSJ9XSwibWludCI6Imh0dHBzOi8vbG5iaXRzLmJpdGNvaW5maXhlc3RoaXMub3JnL2Nhc2h1L2FwaS92MS9ScDlXZGdKZjlxck51a3M1eVQ2SG5rIn1dfQ==" - #nostr_client_test_image_private("a beautiful ostrich watching the sunset", cashutoken ) + #nostr_client_test_image_private("a beautiful ostrich watching the sunset") class NotificationHandler(HandleNotification): def handle(self, relay_url, event): print(f"Received new event from {relay_url}: {event.as_json()}")