Thu, 29 Aug 2024 10:53:59 +0200
Fixed some issues with the logic handling unresponsive servers.
OllamaInterface/OllamaClient.py | file | annotate | diff | comparison | revisions | |
OllamaInterface/OllamaWidget.py | file | annotate | diff | comparison | revisions |
--- a/OllamaInterface/OllamaClient.py Wed Aug 28 18:20:33 2024 +0200 +++ b/OllamaInterface/OllamaClient.py Thu Aug 29 10:53:59 2024 +0200 @@ -53,8 +53,8 @@ @signal finished() emitted to indicate the completion of a request @signal errorOccurred(error:str) emitted to indicate a network error occurred while processing the request - @signal serverStateChanged(ok:bool) emitted to indicate a change of the server - responsiveness + @signal serverStateChanged(ok:bool, msg:str) emitted to indicate a change of the + server responsiveness """ replyReceived = pyqtSignal(str, str, bool) @@ -64,7 +64,7 @@ serverVersion = pyqtSignal(str) finished = pyqtSignal() errorOccurred = pyqtSignal(str) - serverStateChanged = pyqtSignal(bool) + serverStateChanged = pyqtSignal(bool, str) def __init__(self, plugin, parent=None): """ @@ -86,15 +86,13 @@ proxyAuthenticationRequired ) - self.__serverResponding = False + self.__serverResponding = None # start with an unknown state self.__heartbeatTimer = QTimer(self) self.__heartbeatTimer.timeout.connect(self.__periodicHeartbeat) self.__state = OllamaClientState.Waiting self.__localServer = False - self.__serverResponding = False # start with a faulty state - self.__plugin.preferencesChanged.connect(self.__setHeartbeatTimer) self.__setHeartbeatTimer() @@ -106,7 +104,7 @@ @type bool """ self.__localServer = local - self.__serverResponding = False + self.__serverResponding = None def chat(self, model, messages, streaming=True): """ @@ -360,20 +358,21 @@ @return 'ollama' server reply @rtype QNetworkReply """ - ollamaUrl = QUrl( - "{0}://{1}:{2}/api/{3}".format( - self.__plugin.getPreferences("OllamaScheme"), - ( - "127.0.0.1" - if self.__localServer - else self.__plugin.getPreferences("OllamaHost") - ), - ( - self.__plugin.getPreferences("OllamaLocalPort") - if self.__localServer - else self.__plugin.getPreferences("OllamaPort") - ), - endpoint, + ollamaUrl = ( + QUrl( + "http://127.0.0.1:{0}/api/{1}".format( + self.__plugin.getPreferences("OllamaLocalPort"), + endpoint, + ) + ) + if self.__localServer + else QUrl( + "{0}://{1}:{2}/api/{3}".format( + self.__plugin.getPreferences("OllamaScheme"), + self.__plugin.getPreferences("OllamaHost"), + self.__plugin.getPreferences("OllamaPort"), + endpoint, + ) ) ) request = QNetworkRequest(ollamaUrl) @@ -509,6 +508,25 @@ return None, statusCode + def __getHeartbeatUrl(self): + """ + Private method to get the current heartbeat URL. + + @return URL to be contacted by the heartbeat check + @rtype str + """ + return ( + "http://127.0.0.1:{0}".format( + self.__plugin.getPreferences("OllamaLocalPort"), + ) + if self.__localServer + else "{0}://{1}:{2}/".format( + self.__plugin.getPreferences("OllamaScheme"), + self.__plugin.getPreferences("OllamaHost"), + self.__plugin.getPreferences("OllamaPort"), + ) + ) + def heartbeat(self): """ Public method to check, if the 'ollama' server has started and is responsive. @@ -516,14 +534,7 @@ @return flag indicating a responsive 'ollama' server @rtype bool """ - ollamaUrl = QUrl( - "{0}://{1}:{2}/".format( - self.__plugin.getPreferences("OllamaScheme"), - self.__plugin.getPreferences("OllamaHost"), - self.__plugin.getPreferences("OllamaPort"), - ) - ) - request = QNetworkRequest(ollamaUrl) + request = QNetworkRequest(QUrl(self.__getHeartbeatUrl())) reply = self.__networkManager.head(request) while not reply.isFinished(): QCoreApplication.processEvents() @@ -552,5 +563,20 @@ """ responding = self.heartbeat() if responding != self.__serverResponding: - self.serverStateChanged.emit(responding) + msg = ( + "" + if responding + else ( + self.tr( + "<p>Error: The local server at <b>{0}</b> is not responding." + "</p>" + ) + if self.__localServer + else self.tr( + "<p>Error: The configured server at <b>{0}</b> is not" + " responding.</p>" + ) + ).format(self.__getHeartbeatUrl()) + ) + self.serverStateChanged.emit(responding, msg) self.__serverResponding = responding
--- a/OllamaInterface/OllamaWidget.py Wed Aug 28 18:20:33 2024 +0200 +++ b/OllamaInterface/OllamaWidget.py Thu Aug 29 10:53:59 2024 +0200 @@ -83,9 +83,6 @@ self.mainSplitter.setSizes([200, 2000, 100]) - self.newChatButton.setEnabled(False) - self.__handleServerStateChanged(False) - self.__pullProgressDialog = None self.__pulling = False @@ -94,9 +91,12 @@ self.__availableModels = [] - self.__connectClient() + self.__initOllamaMenu() - self.__initOllamaMenu() + self.newChatButton.setEnabled(False) + self.__handleServerStateChanged(False, "") + + self.__connectClient() self.sendButton.clicked.connect(self.__sendMessage) @@ -118,22 +118,6 @@ self.__client.errorOccurred.connect(self.__handleClientError) self.__client.finished.connect(self.__handleClientFinished) - @pyqtSlot(bool) - def __handleServerStateChanged(self, ok): - """ - Private slot handling a change in the 'ollama' server responsiveness. - - @param ok flag indicating a responsive 'ollama' server - @type bool - """ - if ok: - self.__finishSetup() - else: - self.ollamaVersionLabel.setText( - self.tr("<b>Error: The configured server is not responding.</b>") - ) - self.setEnabled(ok) - @pyqtSlot() def __finishSetup(self): """ @@ -159,10 +143,42 @@ """ self.newChatButton.setEnabled(bool(model)) + def __setEnabledState(self, enable): + """ + Private method to set the enabled state of the main widget. + + @param enable enabled state + @type bool + """ + for widget in ( + self.reloadModelsButton, + self.modelComboBox, + self.newChatButton, + self.mainSplitter, + self.__modelMenuAct, + ): + widget.setEnabled(enable) + ############################################################################ ## Methods handling signals from the 'ollama' client. ############################################################################ + @pyqtSlot(bool, str) + def __handleServerStateChanged(self, ok, msg): + """ + Private slot handling a change in the 'ollama' server responsiveness. + + @param ok flag indicating a responsive 'ollama' server + @type bool + @param msg status message + @type str + """ + if ok: + self.__finishSetup() + else: + self.ollamaVersionLabel.setText(msg) + self.__setEnabledState(ok) + @pyqtSlot(str) def __setHeaderLabel(self, version): """ @@ -667,7 +683,7 @@ self.__ollamaMenu = QMenu() self.__ollamaMenu.addMenu(self.__chatHistoryMenu) self.__ollamaMenu.addSeparator() - self.__ollamaMenu.addMenu(self.__modelMenu) + self.__modelMenuAct = self.__ollamaMenu.addMenu(self.__modelMenu) self.__ollamaMenu.addSeparator() self.__ollamaMenu.addMenu(self.__localServerMenu) self.__ollamaMenu.addSeparator() @@ -815,7 +831,6 @@ Private slot to handle the start of a local server. """ self.__client.setMode(True) - self.on_reloadModelsButton_clicked() @pyqtSlot() def __serverStopped(self): @@ -823,7 +838,6 @@ Private slot to handle the stopping of a local server. """ self.__client.setMode(False) - self.on_reloadModelsButton_clicked() @pyqtSlot() def __serverDialogClosed(self):