Skip to content

Commit

Permalink
Compatibility with NVDA 2024.1, adding a System for Updating and Down…
Browse files Browse the repository at this point in the history
…loading Libraries (#38)
  • Loading branch information
aaclause committed Jan 28, 2024
2 parents 1b4c402 + e958606 commit 651d4f8
Show file tree
Hide file tree
Showing 8 changed files with 363 additions and 57 deletions.
98 changes: 57 additions & 41 deletions addon/globalPlugins/openai/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,19 @@
import ui
from logHandler import log
from scriptHandler import script, getLastScriptRepeatCount
from . import configspec
from . import updatecheck
from .apikeymanager import APIKeyManager
from .consts import (
ADDON_DIR, DATA_DIR,
DEFAULT_MODEL, DEFAULT_TOP_P, DEFAULT_N,
TOP_P_MIN, TOP_P_MAX,
N_MIN, N_MAX,
TTS_VOICES, TTS_MODELS, TTS_DEFAULT_VOICE, TTS_DEFAULT_MODEL
LIBS_DIR_PY,
TTS_MODELS, TTS_VOICES
)
from .recordthread import RecordThread

additionalLibsPath = os.path.join(ADDON_DIR, "lib")
sys.path.insert(0, additionalLibsPath)
sys.path.insert(0, LIBS_DIR_PY)
import mss
from openai import OpenAI
sys.path.remove(additionalLibsPath)
sys.path.remove(LIBS_DIR_PY)

addonHandler.initTranslation()

Expand All @@ -34,40 +32,9 @@
ROOT_ADDON_DIR
).manifest

confSpecs = {
"use_org": "boolean(default=False)",
"model": f"string(default={DEFAULT_MODEL.name})",
"topP": f"integer(min={TOP_P_MIN}, max={TOP_P_MAX}, default={DEFAULT_TOP_P})",
"n": f"integer(min={N_MIN}, max={N_MAX}, default={DEFAULT_N})",
"stream": "boolean(default=True)",
"TTSModel": f"option({', '.join(TTS_MODELS)}, default={TTS_DEFAULT_MODEL})",
"TTSVoice": f"option({', '.join(TTS_VOICES)}, default={TTS_DEFAULT_VOICE})",
"blockEscapeKey": "boolean(default=False)",
"conversationMode": "boolean(default=True)",
"saveSystem": "boolean(default=true)",
"advancedMode": "boolean(default=False)",
"images": {
"maxHeight": "integer(min=0, default=720)",
"maxWidth": "integer(min=0, default=0)",
"quality": "integer(min=0, max=100, default=85)",
"resize": "boolean(default=False)",
"resizeInfoDisplayed": "boolean(default=False)",
"useCustomPrompt": "boolean(default=False)",
"customPromptText": 'string(default="")'
},
"audio": {
"sampleRate": "integer(min=8000, max=48000, default=16000)",
"channels": "integer(min=1, max=2, default=1)",
"dtype": "string(default=int16)"
},
"renewClient": "boolean(default=False)",
"debug": "boolean(default=False)"
}
config.conf.spec["OpenAI"] = confSpecs
conf = config.conf["OpenAI"]

NO_AUTHENTICATION_KEY_PROVIDED_MSG = _("No authentication key provided. Please set it in the Preferences dialog.")

conf = config.conf["OpenAI"]
api_key_manager = APIKeyManager(DATA_DIR)

class SettingsDlg(gui.settingsDialogs.SettingsPanel):
Expand All @@ -76,6 +43,31 @@ class SettingsDlg(gui.settingsDialogs.SettingsPanel):

def makeSettings(self, settingsSizer):
sHelper = gui.guiHelper.BoxSizerHelper(self, sizer=settingsSizer)

updateGroupLabel = _("Update")
updateSizer = wx.StaticBoxSizer(wx.VERTICAL, self, label=updateGroupLabel)
updateBox = updateSizer.GetStaticBox()
updateGroup = gui.guiHelper.BoxSizerHelper(self, sizer=updateSizer)

self.updateCheck = updateGroup.addItem(
wx.CheckBox(
updateBox,
label=_("Check for &updates on startup and periodically")
)
)
self.updateCheck.SetValue(conf["update"]["check"])

self.updateChannel = updateGroup.addLabeledControl(
_("&Channel:"),
wx.Choice,
choices=["stable", "dev"]
)
self.updateChannel.SetSelection(
1 if conf["update"]["channel"] == "dev" else 0
)

sHelper.addItem(updateSizer)

APIKey = api_key_manager.get_api_key()
if not APIKey: APIKey = ''
APIKeyOrg = api_key_manager.get_api_key(use_org=True)
Expand Down Expand Up @@ -224,7 +216,7 @@ def makeSettings(self, settingsSizer):

self.useCustomPrompt = imageGroup.addItem(
wx.CheckBox(
imageBox,
imageBox,
label=_("Customize default text &prompt")
)
)
Expand Down Expand Up @@ -265,6 +257,8 @@ def onDefaultPrompt(self, evt):
self.customPromptText.Enable(False)

def onSave(self):
conf["update"]["check"] = self.updateCheck.GetValue()
conf["update"]["channel"] = self.updateChannel.GetString(self.updateChannel.GetSelection())
api_key = self.APIKey.GetValue().strip()
api_key_manager.save_api_key(api_key)
api_key_org = self.org_key.GetValue().strip()
Expand Down Expand Up @@ -326,6 +320,9 @@ def createMenu(self):
_("Show the Open AI dialog")
)
gui.mainFrame.sysTrayIcon.Bind(wx.EVT_MENU, self.onShowMainDialog, item)

self.submenu.AppendSeparator()

item = self.submenu.Append(
wx.ID_ANY,
_("API &keys"),
Expand All @@ -345,6 +342,19 @@ def createMenu(self):
)
gui.mainFrame.sysTrayIcon.Bind(wx.EVT_MENU, self.onGitRepo, item)

self.submenu.AppendSeparator()

item = self.submenu.Append(
wx.ID_ANY,
_("Check for &updates..."),
_("Check for updates")
)
gui.mainFrame.sysTrayIcon.Bind(
wx.EVT_MENU,
self.onCheckForUpdates,
item
)

addon_name = ADDON_INFO["name"]
addon_version = ADDON_INFO["version"]
self.submenu_item = gui.mainFrame.sysTrayIcon.menu.InsertMenu(
Expand Down Expand Up @@ -381,6 +391,12 @@ def onDocumentation(self, evt):
os.startfile(fp)
break

def onCheckForUpdates(self, evt):
updatecheck.check_update(
auto=False
)
updatecheck.update_last_check()

def terminate(self):
gui.settingsDialogs.NVDASettingsDialog.categoryClasses.remove(SettingsDlg)
gui.mainFrame.sysTrayIcon.menu.DestroyItem(self.submenu_item)
Expand Down
49 changes: 49 additions & 0 deletions addon/globalPlugins/openai/configspec.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import config
from .consts import (
DEFAULT_MODEL,
DEFAULT_TOP_P,
DEFAULT_N,
TOP_P_MIN,
TOP_P_MAX,
N_MIN,
N_MAX,
TTS_MODELS,
TTS_DEFAULT_MODEL,
TTS_VOICES,
TTS_DEFAULT_VOICE
)

confSpecs = {
"update": {
"check": "boolean(default=True)",
"channel": "string(default='stable')"
},
"use_org": "boolean(default=False)",
"model": f"string(default={DEFAULT_MODEL.name})",
"topP": f"integer(min={TOP_P_MIN}, max={TOP_P_MAX}, default={DEFAULT_TOP_P})",
"n": f"integer(min={N_MIN}, max={N_MAX}, default={DEFAULT_N})",
"stream": "boolean(default=True)",
"TTSModel": f"option({', '.join(TTS_MODELS)}, default={TTS_DEFAULT_MODEL})",
"TTSVoice": f"option({', '.join(TTS_VOICES)}, default={TTS_DEFAULT_VOICE})",
"blockEscapeKey": "boolean(default=False)",
"conversationMode": "boolean(default=True)",
"saveSystem": "boolean(default=true)",
"advancedMode": "boolean(default=False)",
"images": {
"maxHeight": "integer(min=0, default=720)",
"maxWidth": "integer(min=0, default=0)",
"quality": "integer(min=0, max=100, default=85)",
"resize": "boolean(default=False)",
"resizeInfoDisplayed": "boolean(default=False)",
"useCustomPrompt": "boolean(default=False)",
"customPromptText": 'string(default="")'
},
"audio": {
"sampleRate": "integer(min=8000, max=48000, default=16000)",
"channels": "integer(min=1, max=2, default=1)",
"dtype": "string(default=int16)"
},
"renewClient": "boolean(default=False)",
"debug": "boolean(default=False)"
}
config.conf.spec["OpenAI"] = confSpecs
12 changes: 11 additions & 1 deletion addon/globalPlugins/openai/consts.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import os
import sys
import globalVars
import addonHandler
from .model import Model
Expand Down Expand Up @@ -54,4 +55,13 @@
"organization of the interface. If the image does not correspond to a computer screen, just generate "
"a detailed visual description. If the user sends an image alone without additional instructions in text, "
"describe the image exactly as prescribed in this system prompt. Adhere strictly to the instructions in "
"this system prompt to describe images. Don’t add any additional details unless the user specifically ask you.")
"this system prompt to describe images. Don’t add any additional details unless the user specifically ask you."
)
LIBS_DIR = os.path.join(DATA_DIR, "libs")
LIBS_DIR_PY = os.path.join(
LIBS_DIR,
"lib_py%s.%s" % (
sys.version_info.major,
sys.version_info.minor
)
)
8 changes: 4 additions & 4 deletions addon/globalPlugins/openai/imagehelper.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@
import os
import sys
from logHandler import log
from .consts import ADDON_DIR
from .consts import ADDON_DIR, LIBS_DIR_PY

additionalLibsPath = os.path.join(ADDON_DIR, "lib")
sys.path.insert(0, additionalLibsPath)
sys.path.append(LIBS_DIR_PY)
from openai import OpenAI
from PIL import Image
import fractions
sys.path.remove(additionalLibsPath)
sys.path.remove(LIBS_DIR_PY)


def get_image_dimensions(path):
"""
Expand Down
19 changes: 13 additions & 6 deletions addon/globalPlugins/openai/maindialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from logHandler import log
from .consts import (
ADDON_DIR, DATA_DIR,
LIBS_DIR_PY,
MODELS, MODEL_VISION,
TOP_P_MIN, TOP_P_MAX,
N_MIN, N_MAX,
Expand All @@ -33,11 +34,10 @@
from .recordthread import RecordThread
from .resultevent import ResultEvent, EVT_RESULT_ID

additionalLibsPath = os.path.join(ADDON_DIR, "lib")
sys.path.insert(0, additionalLibsPath)
sys.path.insert(0, LIBS_DIR_PY)
import openai
import markdown2
sys.path.remove(additionalLibsPath)
sys.path.remove(LIBS_DIR_PY)

addonHandler.initTranslation()

Expand Down Expand Up @@ -771,12 +771,19 @@ def onModelChange(self, evt):
defaultMaxOutputToken = 1024
self.maxTokens.SetValue(defaultMaxOutputToken)
if self.conf["advancedMode"]:
self.temperature.SetRange(0, model.maxTemperature * 100)
self.temperature.SetRange(
0,
int(model.maxTemperature * 100)
)
key_temperature = "temperature_%s" % model.name
if key_temperature in self.data:
self.temperature.SetValue(self.data[key_temperature])
self.temperature.SetValue(
int(self.data[key_temperature])
)
else:
self.temperature.SetValue(model.defaultTemperature * 100)
self.temperature.SetValue(
int(model.defaultTemperature * 100)
)

def onOk(self, evt):
if not self.promptText.GetValue().strip() and not self.pathList:
Expand Down
7 changes: 3 additions & 4 deletions addon/globalPlugins/openai/recordthread.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,13 @@
import core
import ui

from .consts import ADDON_DIR, DATA_DIR
from .consts import ADDON_DIR, DATA_DIR, LIBS_DIR_PY
from .resultevent import ResultEvent

additionalLibsPath = os.path.join(ADDON_DIR, "lib")
sys.path.insert(0, additionalLibsPath)
sys.path.insert(0, LIBS_DIR_PY)
import numpy as np
import sounddevice as sd
sys.path.remove(additionalLibsPath)
sys.path.remove(LIBS_DIR_PY)

addonHandler.initTranslation()

Expand Down
Loading

0 comments on commit 651d4f8

Please sign in to comment.