OllamaInterface/OllamaClient.py

changeset 11
3641ea6b55d5
parent 9
c471738b75b3
child 13
3fd49d7004b2
equal deleted inserted replaced
10:734921ab2b89 11:3641ea6b55d5
45 from the 'ollama' server was received 45 from the 'ollama' server was received
46 @signal modelsList(modelNames:list[str]) emitted after the list of model 46 @signal modelsList(modelNames:list[str]) emitted after the list of model
47 names was obtained from the 'ollama' server 47 names was obtained from the 'ollama' server
48 @signal pullStatus(msg:str, id:str, total:int, completed:int) emitted to indicate 48 @signal pullStatus(msg:str, id:str, total:int, completed:int) emitted to indicate
49 the status of a pull request as reported by the 'ollama' server 49 the status of a pull request as reported by the 'ollama' server
50 @signal pullError(msg:str) emitted to indicate an error during a pull operation
50 @signal serverVersion(version:str) emitted after the server version was obtained 51 @signal serverVersion(version:str) emitted after the server version was obtained
51 from the 'ollama' server 52 from the 'ollama' server
52 @signal finished() emitted to indicate the completion of a request 53 @signal finished() emitted to indicate the completion of a request
53 @signal errorOccurred(error:str) emitted to indicate a network error occurred 54 @signal errorOccurred(error:str) emitted to indicate a network error occurred
54 while processing the request 55 while processing the request
56 responsiveness 57 responsiveness
57 """ 58 """
58 59
59 replyReceived = pyqtSignal(str, str, bool) 60 replyReceived = pyqtSignal(str, str, bool)
60 modelsList = pyqtSignal(list) 61 modelsList = pyqtSignal(list)
61 pullStatus = pyqtSignal(str, str, int, int) 62 pullStatus = pyqtSignal(str, str, "unsigned long int", "unsigned long int")
63 pullError = pyqtSignal(str)
62 serverVersion = pyqtSignal(str) 64 serverVersion = pyqtSignal(str)
63 finished = pyqtSignal() 65 finished = pyqtSignal()
64 errorOccurred = pyqtSignal(str) 66 errorOccurred = pyqtSignal(str)
65 serverStateChanged = pyqtSignal(bool) 67 serverStateChanged = pyqtSignal(bool)
66 68
75 """ 77 """
76 super().__init__(parent=parent) 78 super().__init__(parent=parent)
77 79
78 self.__plugin = plugin 80 self.__plugin = plugin
79 self.__replies = [] 81 self.__replies = []
82 self.__pullReply = None
80 83
81 self.__networkManager = QNetworkAccessManager(self) 84 self.__networkManager = QNetworkAccessManager(self)
82 self.__networkManager.proxyAuthenticationRequired.connect( 85 self.__networkManager.proxyAuthenticationRequired.connect(
83 proxyAuthenticationRequired 86 proxyAuthenticationRequired
84 ) 87 )
176 Public method to ask the 'ollama' server to pull the given model. 179 Public method to ask the 'ollama' server to pull the given model.
177 180
178 @param model name of the model 181 @param model name of the model
179 @type str 182 @type str
180 """ 183 """
181 # TODO: not implemented yet
182 ollamaRequest = { 184 ollamaRequest = {
183 "name": model, 185 "model": model,
184 } 186 }
185 self.__sendRequest( 187 self.__sendRequest(
186 "pull", data=ollamaRequest, processResponse=self.__processPullResponse 188 "pull", data=ollamaRequest, processResponse=self.__processPullResponse
187 ) 189 )
188 190
191 Private method to process a pull response of the 'ollama' server. 193 Private method to process a pull response of the 'ollama' server.
192 194
193 @param response dictionary containing the pull response 195 @param response dictionary containing the pull response
194 @type dict 196 @type dict
195 """ 197 """
196 with contextlib.suppress(KeyError): 198 if "error" in response:
197 status = response["status"] 199 self.pullError.emit(response["error"])
198 idStr = response.get("digest", "")[:20] 200 else:
199 total = response.get("total", 0) 201 with contextlib.suppress(KeyError):
200 completed = response.get("completed", 0) 202 status = response["status"]
201 self.pullStatus.emit(status, idStr, total, completed) 203 idStr = response.get("digest", "")[:20]
204 total = response.get("total", 0)
205 completed = response.get("completed", 0)
206 self.pullStatus.emit(status, idStr, total, completed)
207
208 def abortPull(self):
209 """
210 Public method to abort an ongoing pull operation.
211 """
212 if self.__pullReply is not None:
213 self.__pullReply.close()
202 214
203 def remove(self, model): 215 def remove(self, model):
204 """ 216 """
205 Public method to ask the 'ollama' server to delete the given model. 217 Public method to ask the 'ollama' server to delete the given model.
206 218
397 self.__state = OllamaClientState.Requesting 409 self.__state = OllamaClientState.Requesting
398 410
399 reply = self.__getServerReply(endpoint=endpoint, data=data) 411 reply = self.__getServerReply(endpoint=endpoint, data=data)
400 reply.finished.connect(lambda: self.__replyFinished(reply)) 412 reply.finished.connect(lambda: self.__replyFinished(reply))
401 reply.readyRead.connect(lambda: self.__processData(reply, processResponse)) 413 reply.readyRead.connect(lambda: self.__processData(reply, processResponse))
402 self.__replies.append(reply) 414 if endpoint == "pull":
415 self.__pullReply = reply
416 else:
417 self.__replies.append(reply)
403 418
404 def __replyFinished(self, reply): 419 def __replyFinished(self, reply):
405 """ 420 """
406 Private method to handle the finished signal of the reply. 421 Private method to handle the finished signal of the reply.
407 422
408 @param reply reference to the finished network reply object 423 @param reply reference to the finished network reply object
409 @type QNetworkReply 424 @type QNetworkReply
410 """ 425 """
411 self.__state = OllamaClientState.Finished 426 self.__state = OllamaClientState.Finished
412 427
413 if reply in self.__replies: 428 if reply == self.__pullReply:
429 self.__pullReply = None
430 elif reply in self.__replies:
414 self.__replies.remove(reply) 431 self.__replies.remove(reply)
415 432
416 reply.deleteLater() 433 reply.deleteLater()
434
435 self.finished.emit()
417 436
418 def __errorOccurred(self, errorCode, reply): 437 def __errorOccurred(self, errorCode, reply):
419 """ 438 """
420 Private method to handle a network error of the given reply. 439 Private method to handle a network error of the given reply.
421 440
422 @param errorCode error code reported by the reply 441 @param errorCode error code reported by the reply
423 @type QNetworkReply.NetworkError 442 @type QNetworkReply.NetworkError
424 @param reply reference to the network reply object 443 @param reply reference to the network reply object
425 @type QNetworkReply 444 @type QNetworkReply
426 """ 445 """
427 if errorCode != QNetworkReply.NetworkError.NoError: 446 if errorCode not in (
447 QNetworkReply.NetworkError.NoError,
448 QNetworkReply.NetworkError.OperationCanceledError,
449 ):
428 self.errorOccurred.emit( 450 self.errorOccurred.emit(
429 self.tr("<p>A network error occurred.</p><p>Error: {0}</p>").format( 451 self.tr("<p>A network error occurred.</p><p>Error: {0}</p>").format(
430 reply.errorString() 452 reply.errorString()
431 ) 453 )
432 ) 454 )

eric ide

mercurial