2023-11-18 20:20:18 +01:00
import os
from pathlib import Path
import dotenv
2023-12-20 17:31:19 +01:00
from sys import platform
2023-12-13 20:00:03 +01:00
from nostr_dvm . bot import Bot
from nostr_dvm . tasks import videogeneration_replicate_svd , imagegeneration_replicate_sdxl , textgeneration_llmlite , \
trending_notes_nostrband , discovery_inactive_follows , translation_google , textextraction_pdf , \
2023-12-20 11:59:42 +01:00
translation_libretranslate , textextraction_google , convert_media , imagegeneration_openai_dalle , texttospeech , \
2023-12-29 00:27:34 +01:00
imagegeneration_sd21_mlx , advanced_search , textgeneration_huggingchat
2023-12-13 20:00:03 +01:00
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
from nostr_dvm . utils . external_dvm_utils import build_external_dvm
from nostr_dvm . utils . nostr_utils import check_and_set_private_key
from nostr_dvm . utils . output_utils import PostProcessFunctionType
from nostr_dvm . utils . zap_utils import check_and_set_ln_bits_keys
2023-12-09 23:58:15 +01:00
from nostr_sdk import Keys
2023-11-18 20:20:18 +01:00
2023-11-20 22:09:38 +01:00
2023-12-01 19:11:13 +01:00
def playground ( ) :
2023-11-24 21:29:24 +01:00
# We will run an optional bot that can communicate with the DVMs
# Note this is very basic for now and still under development
bot_config = DVMConfig ( )
2023-11-30 15:30:49 +01:00
bot_config . PRIVATE_KEY = check_and_set_private_key ( " bot " )
2023-12-09 23:58:15 +01:00
npub = Keys . from_sk_str ( bot_config . PRIVATE_KEY ) . public_key ( ) . to_bech32 ( )
invoice_key , admin_key , wallet_id , user_id , lnaddress = check_and_set_ln_bits_keys ( " bot " , npub )
bot_config . LNBITS_INVOICE_KEY = invoice_key
bot_config . LNBITS_ADMIN_KEY = admin_key # The dvm might pay failed jobs back
2023-11-24 21:29:24 +01:00
bot_config . LNBITS_URL = os . getenv ( " LNBITS_HOST " )
2023-12-09 23:58:15 +01:00
2023-12-01 19:11:13 +01:00
# Generate an optional Admin Config, in this case, whenever we give our DVMs this config, they will (re)broadcast
# their NIP89 announcement
# You can create individual admins configs and hand them over when initializing the dvm,
# for example to whilelist users or add to their balance.
# If you use this global config, options will be set for all dvms that use it.
admin_config = AdminConfig ( )
admin_config . REBROADCAST_NIP89 = False
2023-12-09 23:58:15 +01:00
admin_config . LUD16 = lnaddress
2023-12-01 19:11:13 +01:00
# Set rebroadcast to true once you have set your NIP89 descriptions and d tags. You only need to rebroadcast once you
# want to update your NIP89 descriptions
2023-12-09 23:58:15 +01:00
# Update the DVMs (not the bot) profile. For example after you updated the NIP89 or the lnaddress, you can automatically update profiles here.
2023-12-01 19:11:13 +01:00
admin_config . UPDATE_PROFILE = False
2023-12-09 23:58:15 +01:00
2023-12-01 19:11:13 +01:00
2023-11-23 11:53:57 +01:00
# Spawn some DVMs in the playground and run them
# You can add arbitrary DVMs there and instantiate them here
2023-11-20 19:17:10 +01:00
2023-11-24 21:29:24 +01:00
# Spawn DVM1 Kind 5000: A local Text Extractor from PDFs
2023-12-01 19:11:13 +01:00
pdfextractor = textextraction_pdf . build_example ( " PDF Extractor " , " pdf_extractor " , admin_config )
2023-11-24 21:29:24 +01:00
# If we don't add it to the bot, the bot will not provide access to the DVM
2023-11-23 11:53:57 +01:00
pdfextractor . run ( )
2023-11-20 19:17:10 +01:00
2023-11-29 10:01:20 +01:00
# Spawn DVM2 Kind 5002 Local Text TranslationGoogle, calling the free Google API.
2023-12-01 19:11:13 +01:00
translator = translation_google . build_example ( " Google Translator " , " google_translator " , admin_config )
2023-11-24 21:29:24 +01:00
bot_config . SUPPORTED_DVMS . append ( translator ) # We add translator to the bot
2023-11-23 11:53:57 +01:00
translator . run ( )
2023-11-29 10:01:20 +01:00
# Spawn DVM3 Kind 5002 Local Text TranslationLibre, calling the free LibreTranslateApi, as an alternative.
2023-11-30 08:07:30 +01:00
# This will only run and appear on the bot if an endpoint is set in the .env
2023-11-29 10:01:20 +01:00
if os . getenv ( " LIBRE_TRANSLATE_ENDPOINT " ) is not None and os . getenv ( " LIBRE_TRANSLATE_ENDPOINT " ) != " " :
2023-12-01 19:11:13 +01:00
libre_translator = translation_libretranslate . build_example ( " Libre Translator " , " libre_translator " , admin_config )
2023-11-29 10:01:20 +01:00
bot_config . SUPPORTED_DVMS . append ( libre_translator ) # We add translator to the bot
libre_translator . run ( )
2023-11-30 16:20:45 +01:00
2023-12-05 21:20:45 +01:00
# Spawn DVM4, this one requires an OPENAI API Key and balance with OpenAI, you will move the task to them and pay
2023-11-24 21:29:24 +01:00
# per call. Make sure you have enough balance and the DVM's cost is set higher than what you pay yourself, except, you know,
# you're being generous.
if os . getenv ( " OPENAI_API_KEY " ) is not None and os . getenv ( " OPENAI_API_KEY " ) != " " :
2023-12-01 19:11:13 +01:00
dalle = imagegeneration_openai_dalle . build_example ( " Dall-E 3 " , " dalle3 " , admin_config )
2023-11-24 21:29:24 +01:00
bot_config . SUPPORTED_DVMS . append ( dalle )
dalle . run ( )
2023-11-23 11:53:57 +01:00
2023-12-06 13:46:19 +01:00
if os . getenv ( " REPLICATE_API_TOKEN " ) is not None and os . getenv ( " REPLICATE_API_TOKEN " ) != " " :
2023-12-07 13:58:24 +01:00
sdxlreplicate = imagegeneration_replicate_sdxl . build_example ( " Stable Diffusion XL " , " replicate_sdxl " , admin_config )
2023-12-06 13:46:19 +01:00
bot_config . SUPPORTED_DVMS . append ( sdxlreplicate )
sdxlreplicate . run ( )
2023-12-07 13:58:24 +01:00
if os . getenv ( " REPLICATE_API_TOKEN " ) is not None and os . getenv ( " REPLICATE_API_TOKEN " ) != " " :
svdreplicate = videogeneration_replicate_svd . build_example ( " Stable Video Diffusion " , " replicate_svd " , admin_config )
bot_config . SUPPORTED_DVMS . append ( svdreplicate )
svdreplicate . run ( )
2023-12-06 13:46:19 +01:00
2023-12-01 19:11:13 +01:00
#Let's define a function so we can add external DVMs to our bot, we will instanciate it afterwards
2023-12-05 21:20:45 +01:00
# Spawn DVM5.. oh wait, actually we don't spawn a new DVM, we use the dvmtaskinterface to define an external dvm by providing some info about it, such as
2023-11-30 08:07:30 +01:00
# their pubkey, a name, task, kind etc. (unencrypted)
2023-12-03 22:05:53 +01:00
tasktiger_external = build_external_dvm ( pubkey = " d483935d6bfcef3645195c04c97bbb70aedb6e65665c5ea83e562ca3c7acb978 " ,
2023-12-01 19:11:13 +01:00
task = " text-to-image " ,
kind = EventDefinitions . KIND_NIP90_GENERATE_IMAGE ,
2023-12-03 22:05:53 +01:00
fix_cost = 80 , per_unit_cost = 0 , config = bot_config )
2023-11-30 08:07:30 +01:00
bot_config . SUPPORTED_DVMS . append ( tasktiger_external )
2023-11-30 15:30:49 +01:00
# Don't run it, it's on someone else's machine, and we simply make the bot aware of it.
2023-11-29 15:09:35 +01:00
2023-12-05 21:20:45 +01:00
# DVM: 6 Another external dvm for recommendations:
2023-12-03 22:05:53 +01:00
ymhm_external = build_external_dvm ( pubkey = " 6b37d5dc88c1cbd32d75b713f6d4c2f7766276f51c9337af9d32c8d715cc1b93 " ,
2023-12-01 12:12:46 +01:00
task = " content-discovery " ,
kind = EventDefinitions . KIND_NIP90_CONTENT_DISCOVERY ,
fix_cost = 0 , per_unit_cost = 0 ,
2023-12-03 22:05:53 +01:00
external_post_process = PostProcessFunctionType . LIST_TO_EVENTS , config = bot_config )
2023-12-01 19:11:13 +01:00
# If we get back a list of people or events, we can post-process it to make it readable in social clients
2023-11-30 08:07:30 +01:00
bot_config . SUPPORTED_DVMS . append ( ymhm_external )
2023-12-05 21:20:45 +01:00
# Spawn DVM 7 Find inactive followers
googleextractor = textextraction_google . build_example ( " Extractor " , " speech_recognition " ,
2023-12-13 20:00:03 +01:00
admin_config )
2023-12-05 21:20:45 +01:00
bot_config . SUPPORTED_DVMS . append ( googleextractor )
googleextractor . run ( )
# Spawn DVM 8 A Media Grabber/Converter
media_bringer = convert_media . build_example ( " Media Bringer " , " media_converter " , admin_config )
bot_config . SUPPORTED_DVMS . append ( media_bringer )
media_bringer . run ( )
# Spawn DVM9 Find inactive followers
2023-12-01 19:11:13 +01:00
discover_inactive = discovery_inactive_follows . build_example ( " Bygones " , " discovery_inactive_follows " ,
admin_config )
2023-11-30 15:30:49 +01:00
bot_config . SUPPORTED_DVMS . append ( discover_inactive )
2023-11-30 10:49:08 +01:00
discover_inactive . run ( )
2023-12-10 20:16:01 +01:00
trending = trending_notes_nostrband . build_example ( " Trending Notes on nostr.band " , " trending_notes_nostrband " , admin_config )
bot_config . SUPPORTED_DVMS . append ( trending )
trending . run ( )
2023-12-11 19:41:00 +01:00
ollama = textgeneration_llmlite . build_example ( " LLM " , " llmlite " , admin_config )
bot_config . SUPPORTED_DVMS . append ( ollama )
ollama . run ( )
2023-12-17 14:38:58 +01:00
tts = texttospeech . build_example ( " Text To Speech Test " , " tts " , admin_config )
bot_config . SUPPORTED_DVMS . append ( tts )
tts . run ( )
2023-12-21 16:31:58 +01:00
search = advanced_search . build_example ( " Advanced Search " , " discovery_content_search " , admin_config )
bot_config . SUPPORTED_DVMS . append ( search )
search . run ( )
inactive = discovery_inactive_follows . build_example ( " Inactive People you follow " , " discovery_inactive_follows " , admin_config )
bot_config . SUPPORTED_DVMS . append ( inactive )
inactive . run ( )
2023-12-20 17:31:19 +01:00
2023-12-20 11:59:42 +01:00
if platform == " darwin " :
# Test with MLX for OSX M1/M2/M3 chips
2023-12-20 17:31:19 +01:00
mlx = imagegeneration_sd21_mlx . build_example ( " SD with MLX " , " mlx_sd " , admin_config )
2023-12-20 11:59:42 +01:00
bot_config . SUPPORTED_DVMS . append ( mlx )
mlx . run ( )
2023-12-29 00:27:34 +01:00
hugginchat = textgeneration_huggingchat . build_example ( " Huggingchat " , " hugginchat " , admin_config )
bot_config . SUPPORTED_DVMS . append ( hugginchat )
hugginchat . run ( )
2023-12-05 21:20:45 +01:00
# Run the bot
2023-11-30 08:07:30 +01:00
Bot ( bot_config )
2023-11-28 10:08:43 +01:00
# Keep the main function alive for libraries that require it, like openai
2023-12-01 19:11:13 +01:00
keep_alive ( )
2023-11-22 19:20:34 +01:00
2023-11-18 20:20:18 +01:00
2023-11-24 17:20:29 +01:00
if __name__ == ' __main__ ' :
2023-11-18 20:20:18 +01:00
env_path = Path ( ' .env ' )
2023-12-19 11:36:25 +01:00
if not env_path . is_file ( ) :
with open ( ' .env ' , ' w ' ) as f :
2023-12-19 15:46:30 +01:00
print ( " Writing new .env file " )
2023-12-19 11:36:25 +01:00
f . write ( ' ' )
2023-11-18 20:20:18 +01:00
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 } ' )
2023-12-01 19:11:13 +01:00
playground ( )