Fixed some issues with the logic handling unresponsive servers.

Thu, 29 Aug 2024 10:53:59 +0200

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Thu, 29 Aug 2024 10:53:59 +0200
changeset 13
3fd49d7004b2
parent 12
cf507e6f12d7
child 14
08932ee12a69

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):

eric ide

mercurial