Skip to content

Commit

Permalink
v34.97; options to integrate internet searches
Browse files Browse the repository at this point in the history
  • Loading branch information
eliranwong committed Sep 12, 2023
1 parent 8a89040 commit 5f2f0b1
Show file tree
Hide file tree
Showing 9 changed files with 128 additions and 34 deletions.
2 changes: 1 addition & 1 deletion UniqueBibleAppVersion.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
34.96
34.97
13 changes: 10 additions & 3 deletions gui/MainWindow.py
Original file line number Diff line number Diff line change
Expand Up @@ -5684,7 +5684,7 @@ def setMainRefMenu(self):
self.mainV.setMenu(menu)

def bibleChat(self, mode):
config.chatGPTApiIncludeDuckDuckGoSearchResults = False
#config.chatGPTApiIncludeDuckDuckGoSearchResults = False
config.chatGPTApiContextInAllInputs = False
fullBookName = BibleBooks().abbrev["eng"][str(config.mainB)][1]
if mode == "verse":
Expand Down Expand Up @@ -5721,14 +5721,21 @@ def runBibleChatPlugins(self):
config.chatGPTApiAvailableFunctions = {}

pluginFolder = os.path.join(os.getcwd(), "plugins", "chatGPT")
# always run 'integrate google searches'
internetSeraches = "integrate google searches"
script = os.path.join(pluginFolder, "{0}.py".format(internetSeraches))
self.execPythonFile(script)
for plugin in FileUtil.fileNamesWithoutExtension(pluginFolder, "py"):
if not plugin in config.chatGPTPluginExcludeList:
if not plugin == internetSeraches and not plugin in config.chatGPTPluginExcludeList:
script = os.path.join(pluginFolder, "{0}.py".format(plugin))
self.execPythonFile(script)
if internetSeraches in config.chatGPTPluginExcludeList:
del config.chatGPTApiFunctionSignatures[0]


def bibleChatAction(self, context="", copiedText=False):
if context:
config.chatGPTApiIncludeDuckDuckGoSearchResults = False
#config.chatGPTApiIncludeDuckDuckGoSearchResults = False
config.chatGPTApiContextInAllInputs = False
config.chatGPTApiPredefinedContext = context
config.bibleChatEntry = self.getClipboardText() if copiedText else self.selectedText().replace("audiotrack ", "").strip()
Expand Down
60 changes: 57 additions & 3 deletions gui/Worker.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,39 @@ def __init__(self, parent):
super().__init__()
self.parent = parent
self.threadpool = QThreadPool()
self.forceLoadingInternetSearches = True

def getResponse(self, messages, progress_callback):
responses = ""
if config.chatGPTApiLoadingInternetSearches == "always" and self.forceLoadingInternetSearches:
#print("loading internet searches ...")
try:
self.forceLoadingInternetSearches = False
completion = openai.ChatCompletion.create(
model=config.chatGPTApiModel,
messages=messages,
max_tokens=config.chatGPTApiMaxTokens,
temperature=config.chatGPTApiTemperature,
n=1,
functions=config.integrate_google_searches_signature,
function_call={"name": "integrate_google_searches"},
)
response_message = completion["choices"][0]["message"]
if response_message.get("function_call"):
function_args = json.loads(response_message["function_call"]["arguments"])
fuction_to_call = config.chatGPTApiAvailableFunctions.get("integrate_google_searches")
function_response = fuction_to_call(function_args)
messages.append(response_message) # extend conversation with assistant's reply
messages.append(
{
"role": "function",
"name": "integrate_google_searches",
"content": function_response,
}
)
return self.getResponse(messages, progress_callback)
except:
print("Unable to load internet resources.")
try:
if config.chatGPTApiNoOfChoices == 1 and (config.chatGPTApiFunctionCall == "none" or not config.chatGPTApiFunctionSignatures):
completion = openai.ChatCompletion.create(
Expand Down Expand Up @@ -135,9 +165,33 @@ def getResponse(self, messages, progress_callback):
response_message = completion["choices"][0]["message"]
if response_message.get("function_call"):
function_name = response_message["function_call"]["name"]
fuction_to_call = config.chatGPTApiAvailableFunctions[function_name]
function_args = json.loads(response_message["function_call"]["arguments"])
function_response = fuction_to_call(function_args)
if function_name == "python":
config.pythonFunctionResponse = ""
function_args = response_message["function_call"]["arguments"]
insert_string = "import config\nconfig.pythonFunctionResponse = "
if "\n" in function_args:
substrings = function_args.rsplit("\n", 1)
new_function_args = f"{substrings[0]}\n{insert_string}{substrings[-1]}"
else:
new_function_args = f"{insert_string}{function_args}"
try:
exec(new_function_args, globals())
function_response = str(config.pythonFunctionResponse)
except:
function_response = function_args
info = {"information": function_response}
function_response = json.dumps(info)
else:
#if not function_name in config.chatGPTApiAvailableFunctions:
# print("unexpected function name: ", function_name)
fuction_to_call = config.chatGPTApiAvailableFunctions.get(function_name, "integrate_google_searches")
try:
function_args = json.loads(response_message["function_call"]["arguments"])
except:
function_args = response_message["function_call"]["arguments"]
if function_name == "integrate_google_searches":
function_args = {"keywords": function_args}
function_response = fuction_to_call(function_args)

# check function response
# print("Got this function response:", function_response)
Expand Down
6 changes: 6 additions & 0 deletions latest_changes.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
Changes in 34.97:
Improved plugin "Bible Chat"
* added options to integrate internet searches: "always", "auto", "none"
* support calling "python" function
* fixed opening url

Changes in 34.96:
* Add a plugin to integrate Google searches into ChatGPT responses.

Expand Down
17 changes: 9 additions & 8 deletions patches.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1382,12 +1382,13 @@
(34.95, "file", "lang/language_ru.py")
(34.95, "file", "lang/language_zh_HANS.py")
(34.95, "file", "lang/language_zh_HANT.py")
(34.95, "file", "gui/MainWindow.py")
(34.95, "file", "gui/Worker.py")
(34.96, "file", "plugins/menu/Bible Chat.py")
(34.96, "file", "util/checkup.py")
(34.96, "file", "util/ConfigUtil.py")
(34.96, "file", "util/LocalCliHandler.py")
(34.96, "file", "latest_changes.txt")
(34.96, "file", "UniqueBibleAppVersion.txt")
(34.96, "file", "patches.txt")
(34.97, "file", "gui/MainWindow.py")
(34.97, "file", "gui/Worker.py")
(34.97, "file", "plugins/menu/Bible Chat.py")
(34.97, "file", "util/ConfigUtil.py")
(34.97, "file", "util/LocalCliHandler.py")
(34.97, "file", "plugins/chatGPT/integrate google searches.py")
(34.97, "file", "latest_changes.txt")
(34.97, "file", "UniqueBibleAppVersion.txt")
(34.97, "file", "patches.txt")
13 changes: 7 additions & 6 deletions plugins/chatGPT/integrate google searches.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,22 @@

# Use google https://pypi.org/project/googlesearch-python/ to search internet for information, about which ChatGPT doesn't know.

def get_internet_info(function_args):
def integrate_google_searches(function_args):
# retrieve argument values from a dictionary
#print(function_args)
keywords = function_args.get("keywords") # required

news = {}
info = {}
for index, item in enumerate(googlesearch.search(keywords, advanced=True, num_results=config.chatGPTApiMaximumInternetSearchResults)):
news[f"result {index}"] = {
info[f"result {index}"] = {
"title": item.title,
"url": item.url,
"description": item.description,
}
return json.dumps(news)
return json.dumps(info)

functionSignature = {
"name": "get_internet_info",
"name": "integrate_google_searches",
"description": "Search internet for keywords when ChatGPT does not have information",
"parameters": {
"type": "object",
Expand All @@ -31,5 +31,6 @@ def get_internet_info(function_args):
},
}

config.integrate_google_searches_signature = [functionSignature]
config.chatGPTApiFunctionSignatures.append(functionSignature)
config.chatGPTApiAvailableFunctions["get_internet_info"] = get_internet_info
config.chatGPTApiAvailableFunctions["integrate_google_searches"] = integrate_google_searches
37 changes: 27 additions & 10 deletions plugins/menu/Bible Chat.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,15 @@ def __init__(self, parent=None):
initialIndex = index
index += 1
self.functionCallingBox.setCurrentIndex(initialIndex)
self.loadingInternetSearchesBox = QComboBox()
initialIndex = 0
index = 0
for key in ("always", "auto", "none"):
self.loadingInternetSearchesBox.addItem(key)
if key == config.chatGPTApiLoadingInternetSearches:
initialIndex = index
index += 1
self.loadingInternetSearchesBox.setCurrentIndex(initialIndex)
self.maxTokenEdit = QLineEdit(str(config.chatGPTApiMaxTokens))
self.maxTokenEdit.setToolTip("The maximum number of tokens to generate in the completion.\nThe token count of your prompt plus max_tokens cannot exceed the model's context length. Most models have a context length of 2048 tokens (except for the newest models, which support 4096).")
self.maxInternetSearchResults = QLineEdit(str(config.chatGPTApiMaximumInternetSearchResults))
Expand Down Expand Up @@ -156,16 +165,17 @@ def __init__(self, parent=None):
layout.addRow(f"{predefinedContext} [{optional}]:", self.predefinedContextBox)
layout.addRow(f"{context} [{optional}]:", self.contextEdit)
layout.addRow(f"{applyContext} [{optional}]:", self.applyContextIn)
#layout.addRow(f"{latestOnlineSearchResults} [{optional}]:", self.includeInternetSearches)
layout.addRow(f"{latestOnlineSearchResults} [{optional}]:", self.loadingInternetSearchesBox)
layout.addRow(f"{maximumOnlineSearchResults} [{optional}]:", self.maxInternetSearchResults)
layout.addRow(f"{autoScroll} [{optional}]:", self.autoScrollingCheckBox)
layout.addRow(f"{runPythonScriptGlobally} [{optional}]:", self.runPythonScriptGloballyCheckBox)
#layout.addRow(f"{language} [{optional}]:", self.languageBox)
layout.addWidget(buttonBox)
#self.includeInternetSearches.stateChanged.connect(self.toggleIncludeDuckDuckGoSearchResults)
self.autoScrollingCheckBox.stateChanged.connect(self.toggleAutoScrollingCheckBox)
self.chatAfterFunctionCalledCheckBox.stateChanged.connect(self.toggleChatAfterFunctionCalled)
self.runPythonScriptGloballyCheckBox.stateChanged.connect(self.toggleRunPythonScriptGlobally)
self.functionCallingBox.currentIndexChanged.connect(self.functionCallingBoxChanged)
self.loadingInternetSearchesBox.currentIndexChanged.connect(self.loadingInternetSearchesBoxChanged)

self.setLayout(layout)

Expand All @@ -192,15 +202,19 @@ def apiModel(self):
def functionCalling(self):
return self.functionCallingBox.currentText()

def max_token(self):
return self.maxTokenEdit.text().strip()
def functionCallingBoxChanged(self):
if self.functionCallingBox.currentText() == "none" and self.loadingInternetSearchesBox.currentText() == "auto":
self.loadingInternetSearchesBox.setCurrentText("none")

"""
def include_internet_searches(self):
return self.includeDuckDuckGoSearchResults
def loadingInternetSearches(self):
return self.loadingInternetSearchesBox.currentText()

def toggleIncludeDuckDuckGoSearchResults(self, state):
self.includeDuckDuckGoSearchResults = True if state else False"""
def loadingInternetSearchesBoxChanged(self, _):
if self.loadingInternetSearchesBox.currentText() == "auto":
self.functionCallingBox.setCurrentText("auto")

def max_token(self):
return self.maxTokenEdit.text().strip()

def enable_auto_scrolling(self):
return self.chatGPTApiAutoScrolling
Expand Down Expand Up @@ -650,6 +664,7 @@ def showApiDialog(self):
config.chatAfterFunctionCalled = dialog.enable_chatAfterFunctionCalled()
config.chatGPTApiModel = dialog.apiModel()
config.chatGPTApiFunctionCall = dialog.functionCalling()
config.chatGPTApiLoadingInternetSearches = dialog.loadingInternetSearches()
config.chatGPTApiPredefinedContext = dialog.predefinedContext()
config.chatGPTApiContextInAllInputs = dialog.contextInAllInputs()
config.chatGPTApiContext = dialog.context()
Expand Down Expand Up @@ -696,7 +711,9 @@ def webBrowse(self, userInput=""):
if not userInput:
self.noTextSelection()
return
if not self.validate_url(userInput):
if self.validate_url(userInput):
url = userInput
else:
userInput = urllib.parse.quote(userInput)
url = f"https://www.google.com/search?q={userInput}"
webbrowser.open(url)
Expand Down
4 changes: 4 additions & 0 deletions util/ConfigUtil.py
Original file line number Diff line number Diff line change
Expand Up @@ -559,6 +559,10 @@ def getCurrentVenvDir():
setConfig("chatGPTApiContextInAllInputs", """
# ChatGP API - predefined context in all inputs.""",
False)
setConfig("chatGPTApiLoadingInternetSearches", """
# ChatGPT API - always loading internet searches.
# options - 'always', 'auto', 'none'.""",
"auto")
setConfig("chatGPTApiMaximumInternetSearchResults", """
# ChatGPT API - maximum number of internet search results to be integrated.""",
5)
Expand Down
10 changes: 7 additions & 3 deletions util/LocalCliHandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -2307,6 +2307,7 @@ def startChat():
".contextInFirstInputOnly",
".contextInAllInputs",
".latestSearches",
".autolatestSearches",
".noLatestSearches",
".share" if config.terminalEnableTermuxAPI else ".save",
)
Expand Down Expand Up @@ -2367,10 +2368,13 @@ def startChat():
multilineInput = True
self.print("Multi-line user input enabled!")
elif feature == ".latestSearches":
config.chatGPTApiIncludeDuckDuckGoSearchResults = True
self.print("Latest online search results enabled!")
config.chatGPTApiLoadingInternetSearches = "always"
self.print("Latest online search results always enabled!")
elif feature == ".autolatestSearches":
config.chatGPTApiLoadingInternetSearches = "auto"
self.print("Latest online search results enabled, if necessary!")
elif feature == ".noLatestSearches":
config.chatGPTApiIncludeDuckDuckGoSearchResults = False
config.chatGPTApiLoadingInternetSearches = "none"
self.print("Latest online search results disabled!")
elif feature == ".contextInFirstInputOnly":
config.chatGPTApiContextInAllInputs = False
Expand Down

0 comments on commit 5f2f0b1

Please sign in to comment.