Skip to content

Commit

Permalink
Create a system tray launcher
Browse files Browse the repository at this point in the history
  • Loading branch information
tnunamak committed Mar 20, 2024
1 parent d57c9e9 commit 6424b21
Show file tree
Hide file tree
Showing 13 changed files with 282 additions and 46 deletions.
9 changes: 0 additions & 9 deletions hooks/hook-llama_index.py

This file was deleted.

62 changes: 61 additions & 1 deletion poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ python-multipart = "^0.0.9"
ngrok = "^1.0.0"
python-dotenv = "^1.0.1"
pillow = "^10.2.0"
pyqt6 = "^6.6.1"
swig = "^4.2.1"

# Experimental GPU Features
Expand Down
5 changes: 4 additions & 1 deletion selfie.spec
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,14 @@ a = Analysis(
datas=[
('./selfie/parsers/chat/blacklist_patterns.yaml', 'selfie/parsers/chat/'),
('./selfie/web/', 'selfie/web/'),
('./selfie/images/', 'selfie/images/'),
*connector_files,
],
hiddenimports=[
'tiktoken_ext',
'tiktoken_ext.openai_public',
'onnxconverter_common', # Logs say hidden import 'onnxconverter_common' not found
'llama_index',
],
hookspath=['./hooks'],
hooksconfig={},
Expand Down Expand Up @@ -71,10 +73,11 @@ coll = COLLECT(
upx=True,
upx_exclude=[],
name='selfie',
debug="all",
)

app = BUNDLE(coll,
name='Selfie.app',
icon='Selfie.icns',
bundle_identifier='com.vana.selfie',
)
)
81 changes: 49 additions & 32 deletions selfie/__main__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import multiprocessing
import platform
import sys
import argparse
import uvicorn
import webbrowser
Expand All @@ -12,6 +15,16 @@
logger.setLevel(logging.INFO)


def get_default_gpu_mode():
os_name = platform.system()
architecture = platform.machine()

if os_name == 'Darwin' and architecture == 'arm64':
return True

return False


def serialize_args_to_env(args):
for arg, value in vars(args).items():
env_var = f"SELFIE_{arg.upper()}"
Expand All @@ -20,31 +33,32 @@ def serialize_args_to_env(args):

def deserialize_args_from_env():
return argparse.Namespace(
share=os.getenv('SELFIE_SHARE') == 'True',
share=os.getenv('SELFIE_SHARE') == 'False',
port=int(os.getenv('SELFIE_PORT', default_port)),
gpu=os.getenv('SELFIE_GPU') == 'True',
reload=os.getenv('SELFIE_RELOAD') == 'True',
verbose=os.getenv('SELFIE_VERBOSE') == 'True',
gpu=os.getenv('SELFIE_GPU') == str(get_default_gpu_mode()),
reload=os.getenv('SELFIE_RELOAD') == 'False',
verbose=os.getenv('SELFIE_VERBOSE') == 'False',
headless=os.getenv('SELFIE_HEADLESS') == 'False',
)


def parse_args():
if os.getenv('SELFIE_RELOAD') == 'True':
return deserialize_args_from_env()
else:
parser = argparse.ArgumentParser(description="Run the selfie app.")
parser.add_argument("--share", action="store_true", help="Share the API via ngrok")
parser.add_argument("--port", type=int, default=int(os.getenv('PORT', default_port)), help="Specify the port to run on")
parser.add_argument("--gpu", action="store_true", help="Enable GPU support")
parser.add_argument("--reload", action="store_true", help="Enable hot-reloading")
parser.add_argument("--verbose", action="store_true", help="Enable verbose logging")
args = parser.parse_args()
serialize_args_to_env(args)
return args
parser = argparse.ArgumentParser(description="Run the selfie app.")
parser.add_argument("--share", action="store_true", help="Share the API via ngrok")
parser.add_argument("--port", type=int, default=int(os.getenv('PORT', default_port)), help="Specify the port to run on")
parser.add_argument("--gpu", default=get_default_gpu_mode(), action="store_true", help="Enable GPU support")
parser.add_argument("--reload", action="store_true", help="Enable hot-reloading")
parser.add_argument("--verbose", action="store_true", help="Enable verbose logging")
parser.add_argument("--headless", action="store_true", help="Run in headless mode (no GUI)")
args = parser.parse_args()
serialize_args_to_env(args)
return args


def get_configured_app(shareable=False):
args = parse_args()
args = deserialize_args_from_env()

logger.info(f"Running with args: {args}")

if args.verbose:
logging.getLogger("selfie").setLevel(level=logging.DEBUG)
Expand All @@ -58,38 +72,41 @@ def get_configured_app(shareable=False):

listener = ngrok.forward(args.port, authtoken_from_env=True, domain=ngrok_domain)
logger.info(f"Application is available at {listener.url()}")
# Update config directly as modifying args won't affect the env vars
os.environ['SELFIE_HOST'] = listener.url()
del os.environ['SELFIE_PORT']

logger.info("Creating app configuration")

create_app_config(**vars(args))

# Ensure this import happens after configuration is set
from selfie.api import app
return app

return app

def main():
args = parse_args()

def start_fastapi_server():
args = deserialize_args_from_env()
if args.reload:
if args.share:
raise ValueError("Reloading with sharing enabled is not supported.")
uvicorn.run("selfie.__main__:get_configured_app", host="0.0.0.0", port=args.port, reload=True, factory=True)
else:
app = get_configured_app(shareable=True)
fastapi_app = get_configured_app(shareable=True)
uvicorn.run(fastapi_app, host="0.0.0.0", port=args.port)

@app.on_event("startup")
async def on_startup():
webbrowser.open(get_app_config().base_url)

@app.on_event("shutdown")
async def on_shutdown():
ngrok.disconnect()
def main():
load_dotenv() # Load environment variables
args = parse_args()

uvicorn.run(app, host="0.0.0.0", port=args.port)
if args.headless:
start_fastapi_server()
else:
from selfie.selfie_gui import SystemTrayApp
system_tray_app = SystemTrayApp(sys.argv)
sys.exit(system_tray_app.exec()) # Start the PyQt application event loop


if __name__ == "__main__":
load_dotenv()
multiprocessing.freeze_support()
multiprocessing.set_start_method('spawn')
main()
1 change: 1 addition & 0 deletions selfie/embeddings/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ def __init__(self, character_name, storage_path: str = config.embeddings_storage
if not hasattr(self, 'is_initialized'):
logger.info("Initializing DataIndex")
self.storage_path = os.path.join(storage_path, "index")
logger.info(f"Storage path: {self.storage_path}")
os.makedirs(storage_path, exist_ok=True)

self.completion = completion or get_default_completion()
Expand Down
2 changes: 1 addition & 1 deletion selfie/embeddings/importance_scorer.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,4 +86,4 @@ def normalize_score(self, score):
Normalize the score to a range of [0, 1].
Assumes the original score is in [1, 10].
"""
return 0 if score is 0 else (score - 1) / 9
return 0 if score == 0 else (score - 1) / 9
Loading

0 comments on commit 6424b21

Please sign in to comment.