From 101228c75100c27f48aaf07323f4e405062c98fc Mon Sep 17 00:00:00 2001 From: Chengbiao Jin Date: Fri, 6 Jun 2025 12:56:27 -0700 Subject: [PATCH 1/2] release 1.9.0 deprecate copilot apis --- pyTigerGraph/__init__.py | 2 +- pyTigerGraph/ai/ai.py | 81 +++++++++------------ pyTigerGraph/pyTigerGraphQuery.py | 14 +++- pyTigerGraph/pytgasync/pyTigerGraphBase.py | 2 +- pyTigerGraph/pytgasync/pyTigerGraphQuery.py | 16 +++- 5 files changed, 65 insertions(+), 50 deletions(-) diff --git a/pyTigerGraph/__init__.py b/pyTigerGraph/__init__.py index 7b4172fa..0a46f960 100644 --- a/pyTigerGraph/__init__.py +++ b/pyTigerGraph/__init__.py @@ -2,6 +2,6 @@ from pyTigerGraph.pytgasync.pyTigerGraph import AsyncTigerGraphConnection from pyTigerGraph.common.exception import TigerGraphException -__version__ = "1.8.8" +__version__ = "1.9.0" __license__ = "Apache 2" diff --git a/pyTigerGraph/ai/ai.py b/pyTigerGraph/ai/ai.py index 0cb03c5e..fde6f582 100644 --- a/pyTigerGraph/ai/ai.py +++ b/pyTigerGraph/ai/ai.py @@ -1,8 +1,8 @@ """AI Submodule -The AI submodule is used to interact with the TigerGraph CoPilot service. -It allows users to register custom queries, run natural language queries, and interact with the CoPilot service. +The AI submodule is used to interact with the TigerGraph GraphRAG service. +It allows users to register custom queries, run natural language queries, and interact with the GraphRAG service. -To use the AI submodule, you must first create a TigerGraphConnection object, and verify that you have a TigerGraph CoPilot service running. +To use the AI submodule, you must first create a TigerGraphConnection object, and verify that you have a TigerGraph GraphRAG service running. For example, to use the AI submodule, you can run the following code: @@ -19,12 +19,12 @@ conn.getToken() -conn.ai.configureCoPilotHost(hostname="http://COPILOT_ADDRESS") +conn.ai.configureGraphRAGHost(hostname="http://GRAPHRAG_ADDRESS") conn.ai.query("How many servers are there?") ---- -For a more detailed and varied examples, see the demo notebooks in the (TigerGraph CoPilot GitHub repository)[https://github.com/tigergraph/CoPilot/tree/main/copilot/docs/notebooks]. +For a more detailed and varied examples, see the demo notebooks in the (TigerGraph GraphRAG GitHub repository)[https://github.com/tigergraph/graphrag/tree/main/graphrag/docs/notebooks]. """ import warnings @@ -44,42 +44,33 @@ def __init__(self, conn: TigerGraphConnection) -> None: """ self.conn = conn self.nlqs_host = None - self.aiserver = "supportai" + self.server_mode = "graphrag" if conn.tgCloud: # split scheme and host scheme, host = conn.host.split("://") - self.nlqs_host = scheme + "://copilot-" + host + self.nlqs_host = scheme + "://graphrag-" + host - def configureInquiryAIHost(self, hostname: str): - """ DEPRECATED: Configure the hostname of the InquiryAI service. - Not recommended to use. Use configureCoPilotHost() instead. + def configureGraphRAGHost(self, hostname: str): + """ Configure the hostname of the GraphRAG service. + Not necessary if using TigerGraph GraphRAG on TigerGraph Cloud. Args: hostname (str): - The hostname (and port number) of the InquiryAI serivce. + The hostname (and port number) of the GraphRAG serivce. """ - warnings.warn( - "The `configureInquiryAIHost()` function is deprecated; use `configureCoPilotHost()` function instead.", - DeprecationWarning) self.nlqs_host = hostname + self.server_mode = "graphrag" - def configureCoPilotHost(self, hostname: str): - """ Configure the hostname of the CoPilot service. - Not necessary if using TigerGraph CoPilot on TigerGraph Cloud. - Args: - hostname (str): - The hostname (and port number) of the CoPilot serivce. - """ - self.nlqs_host = hostname - - def configureServerHost(self, hostname: str, aiserver: str): + def configureServerHost(self, hostname: str, server: str): """ Configure the hostname of the AI service. Not necessary if using TigerGraph AI on TigerGraph Cloud. Args: hostname (str): - The hostname (and port number) of the CoPilot serivce. + The hostname (and port number) of the GraphRAG serivce. + server (str): + The service mode of the GraphRAG serivce. """ self.nlqs_host = hostname - self.aiserver = aiserver + self.server_mode = server def registerCustomQuery(self, query_name: str, description: str = None, docstring: str = None, param_types: dict = None): """ Register a custom query with the InquiryAI service. @@ -225,10 +216,10 @@ def query(self, query): url = self.nlqs_host+"/"+self.conn.graphname+"/query" return self.conn._req("POST", url, authMode="pwd", data=data, jsonData=True, resKey=None) - def coPilotHealth(self): - """ Check the health of the CoPilot service. + def healthCheck(self): + """ Check the health of the GraphRAG service. Returns: - JSON response from the CoPilot service. + JSON response from the GraphRAG service. """ url = self.nlqs_host+"/health" return self.conn._req("GET", url, authMode="pwd", resKey=None) @@ -238,22 +229,22 @@ def initializeSupportAI(self): Returns: JSON response from the SupportAI service. """ - return self.initializeAIServer("supportai") + return self.initializeServer("supportai") - def initializeGraphAI(self): + def initializeGraphRAG(self): """ Initialize the GraphAI service. Returns: JSON response from the GraphAI service. """ - return self.initializeAIServer("graphai") + return self.initializeServer("graphrag") - def initializeAIServer(self, server="supportai"): + def initializeServer(self, server="graphrag"): """ Initialize the given service. Returns: JSON response from the given service. """ - self.aiserver = server - url = f"{self.nlqs_host}/{self.conn.graphname}/{self.aiserver}/initialize" + self.server_mode = server + url = f"{self.nlqs_host}/{self.conn.graphname}/{self.server_mode}/initialize" return self.conn._req("POST", url, authMode="pwd", resKey=None) def createDocumentIngest(self, data_source, data_source_config, loader_config, file_format): @@ -277,7 +268,7 @@ def createDocumentIngest(self, data_source, data_source_config, loader_config, f "file_format": file_format } - url = f"{self.nlqs_host}/{self.conn.graphname}/{self.aiserver}/create_ingest" + url = f"{self.nlqs_host}/{self.conn.graphname}/{self.server_mode}/create_ingest" return self.conn._req("POST", url, authMode="pwd", data=data, jsonData=True, resKey=None) def runDocumentIngest(self, load_job_id, data_source_id, data_path, data_source="remote"): @@ -300,7 +291,7 @@ def runDocumentIngest(self, load_job_id, data_source_id, data_path, data_source= "data_source_id": data_source_id, "file_path": data_path } - url = f"{self.nlqs_host}/{self.conn.graphname}/{self.aiserver}/ingest" + url = f"{self.nlqs_host}/{self.conn.graphname}/{self.server_mode}/ingest" return self.conn._req("POST", url, authMode="pwd", data=data, jsonData=True, resKey=None) def searchDocuments(self, query, method="hnswoverlap", method_parameters: dict = {"indices": ["Document", "DocumentChunk", "Entity", "Relationship"], "top_k": 2, "num_hops": 2, "num_seen_min": 2}): @@ -320,7 +311,7 @@ def searchDocuments(self, query, method="hnswoverlap", method_parameters: dict = "method": method, "method_params": method_parameters } - url = self.nlqs_host+"/"+self.conn.graphname+"/supportai/search" + url = self.nlqs_host+"/"+self.conn.graphname+"/"+self.server_mode+"/search" return self.conn._req("POST", url, authMode="pwd", data=data, jsonData=True, resKey=None) def answerQuestion(self, query, method="hnswoverlap", method_parameters: dict = {"indices": ["Document", "DocumentChunk", "Entity", "Relationship"], "top_k": 2, "num_hops": 2, "num_seen_min": 2}): @@ -340,29 +331,29 @@ def answerQuestion(self, query, method="hnswoverlap", method_parameters: dict = "method": method, "method_params": method_parameters } - url = self.nlqs_host+"/"+self.conn.graphname+"/supportai/answerquestion" + url = self.nlqs_host+"/"+self.conn.graphname+"/"+self.server_mode+"/answerquestion" return self.conn._req("POST", url, authMode="pwd", data=data, jsonData=True, resKey=None) - def forceConsistencyUpdate(self, method="supportai"): + def forceConsistencyUpdate(self, server=""): """ Force a consistency update for SupportAI embeddings. Args: method (str): The doc initialization method to run - Currentlty only "supportai" is supported in CoPilot v0.9. Returns: JSON response from the consistency update. """ - url = f"{self.nlqs_host}/{self.conn.graphname}/{method}/forceupdate/" + method = server if server else self.server_mode + url = f"{self.nlqs_host}/{self.conn.graphname}/{method}/forceupdate" return self.conn._req("GET", url, authMode="pwd", resKey=None) - def checkConsistencyProgress(self, method="supportai"): + def checkConsistencyProgress(self, server=""): """ Check the progress of the consistency update. Args: method (str): The doc initialization method to check or run. - Currentlty only "supportai" is supported in CoPilot v0.9. Returns: JSON response from the consistency update progress. """ - url = f"{self.nlqs_host}/{self.conn.graphname}/supportai/consistency_status/{method}" + method = server if server else self.server_mode + url = f"{self.nlqs_host}/{self.conn.graphname}/{method}/consistency_status" return self.conn._req("GET", url, authMode="pwd", resKey=None) diff --git a/pyTigerGraph/pyTigerGraphQuery.py b/pyTigerGraph/pyTigerGraphQuery.py index dce4275f..947bfaff 100644 --- a/pyTigerGraph/pyTigerGraphQuery.py +++ b/pyTigerGraph/pyTigerGraphQuery.py @@ -126,6 +126,12 @@ def installQueries(self, queries: Union[str, list], flag: Union[str, list] = Non logger.info("entry: installQueries") if logger.level == logging.DEBUG: logger.debug("params: " + self._locals(locals())) + self.ver = self.getVer() + major_ver, minor_ver, patch_ver = self.ver.split(".") + if int(major_ver) < 4 or int(major_ver) == 4 and int(minor_ver) == 0: + logger.info("exit: installQueries") + raise TigerGraphException( + "This function is only supported on versions of TigerGraph >= 4.1.0.", 0) params = {} params["graph"] = self.graphname @@ -163,8 +169,14 @@ def getQueryInstallationStatus(self, requestId: str) -> dict: logger.info("entry: getQueryInstallationStatus") if logger.level == logging.DEBUG: logger.debug("params: " + self._locals(locals())) + self.ver = self.getVer() + major_ver, minor_ver, patch_ver = self.ver.split(".") + if int(major_ver) < 4 or int(major_ver) == 4 and int(minor_ver) == 0: + logger.info("exit: getQueryInstallationStatus") + raise TigerGraphException( + "This function is only supported on versions of TigerGraph >= 4.1.0.", 0) - ret = self._req("GET", self.gsUrl + "/gsql/v1/queries/install&requestid=" + requestId, authMode="pwd", resKey="") + ret = self._req("GET", self.gsUrl + "/gsql/v1/queries/install/" + requestId, authMode="pwd", resKey="") if logger.level == logging.DEBUG: logger.debug("return: " + str(ret)) diff --git a/pyTigerGraph/pytgasync/pyTigerGraphBase.py b/pyTigerGraph/pytgasync/pyTigerGraphBase.py index feef2dcf..3da08e2d 100644 --- a/pyTigerGraph/pytgasync/pyTigerGraphBase.py +++ b/pyTigerGraph/pytgasync/pyTigerGraphBase.py @@ -7,7 +7,7 @@ The `AsyncTigerGraphConnection` object is the main object that you will interact with when using pyTigerGraph. It provides the same core functionality as the synchronous `TigerGraphConnection` object, but with asynchronous methods. -**Note:** `AsyncTigerGraphConnection` does not currently support the GDS or TigerGraph CoPilot APIs found in the synchronous version. +**Note:** `AsyncTigerGraphConnection` does not currently support the GDS or TigerGraph GraphRAG APIs found in the synchronous version. To test your connection, you can use the `echo()` method. This method sends a simple request to the server and returns the response. diff --git a/pyTigerGraph/pytgasync/pyTigerGraphQuery.py b/pyTigerGraph/pytgasync/pyTigerGraphQuery.py index 79ff0e20..ac97d7e1 100644 --- a/pyTigerGraph/pytgasync/pyTigerGraphQuery.py +++ b/pyTigerGraph/pytgasync/pyTigerGraphQuery.py @@ -122,6 +122,12 @@ async def installQueries(self, queries: Union[str, list], flag: Union[str, list] logger.info("entry: installQueries") if logger.level == logging.DEBUG: logger.debug("params: " + self._locals(locals())) + self.ver = await self.getVer() + major_ver, minor_ver, patch_ver = self.ver.split(".") + if int(major_ver) < 4 or int(major_ver) == 4 and int(minor_ver) == 0: + logger.info("exit: installQueries") + raise TigerGraphException( + "This function is only supported on versions of TigerGraph >= 4.1.0.", 0) params = {} params["graph"] = self.graphname @@ -143,7 +149,7 @@ async def installQueries(self, queries: Union[str, list], flag: Union[str, list] break else: ret = None - time.sleep(1) + await asyncio.sleep(1) if logger.level == logging.DEBUG: logger.debug("return: " + str(ret)) @@ -168,8 +174,14 @@ async def getQueryInstallationStatus(self, requestId: str) -> dict: logger.info("entry: getQueryInstallationStatus") if logger.level == logging.DEBUG: logger.debug("params: " + self._locals(locals())) + self.ver = await self.getVer() + major_ver, minor_ver, patch_ver = self.ver.split(".") + if int(major_ver) < 4 or int(major_ver) == 4 and int(minor_ver) == 0: + logger.info("exit: getQueryInstallationStatus") + raise TigerGraphException( + "This function is only supported on versions of TigerGraph >= 4.1.0.", 0) - ret = await self._req("GET", self.gsUrl + "/gsql/v1/queries/install&requestid=" + requestId, authMode="pwd") + ret = await self._req("GET", self.gsUrl + "/gsql/v1/queries/install/" + requestId, authMode="pwd", resKey="") if logger.level == logging.DEBUG: logger.debug("return: " + str(ret)) From d427d7ab9e8fedb5103e6d3cc3fd6dcd49f08b45 Mon Sep 17 00:00:00 2001 From: Chengbiao Jin Date: Fri, 6 Jun 2025 13:03:07 -0700 Subject: [PATCH 2/2] revise default search type --- pyTigerGraph/ai/ai.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/pyTigerGraph/ai/ai.py b/pyTigerGraph/ai/ai.py index fde6f582..01ffec9d 100644 --- a/pyTigerGraph/ai/ai.py +++ b/pyTigerGraph/ai/ai.py @@ -294,7 +294,7 @@ def runDocumentIngest(self, load_job_id, data_source_id, data_path, data_source= url = f"{self.nlqs_host}/{self.conn.graphname}/{self.server_mode}/ingest" return self.conn._req("POST", url, authMode="pwd", data=data, jsonData=True, resKey=None) - def searchDocuments(self, query, method="hnswoverlap", method_parameters: dict = {"indices": ["Document", "DocumentChunk", "Entity", "Relationship"], "top_k": 2, "num_hops": 2, "num_seen_min": 2}): + def searchDocuments(self, query, method="hybrid", method_parameters: dict = {"indices": ["Document", "DocumentChunk", "Entity", "Relationship"], "top_k": 2, "num_hops": 2, "num_seen_min": 2}): """ Search documents. Args: query (str): @@ -314,7 +314,7 @@ def searchDocuments(self, query, method="hnswoverlap", method_parameters: dict = url = self.nlqs_host+"/"+self.conn.graphname+"/"+self.server_mode+"/search" return self.conn._req("POST", url, authMode="pwd", data=data, jsonData=True, resKey=None) - def answerQuestion(self, query, method="hnswoverlap", method_parameters: dict = {"indices": ["Document", "DocumentChunk", "Entity", "Relationship"], "top_k": 2, "num_hops": 2, "num_seen_min": 2}): + def answerQuestion(self, query, method="hybrid", method_parameters: dict = {"indices": ["Document", "DocumentChunk", "Entity", "Relationship"], "top_k": 2, "num_hops": 2, "num_seen_min": 2}): """ Answer a question. Args: query (str): @@ -334,7 +334,7 @@ def answerQuestion(self, query, method="hnswoverlap", method_parameters: dict = url = self.nlqs_host+"/"+self.conn.graphname+"/"+self.server_mode+"/answerquestion" return self.conn._req("POST", url, authMode="pwd", data=data, jsonData=True, resKey=None) - def forceConsistencyUpdate(self, server=""): + def forceConsistencyUpdate(self, method=""): """ Force a consistency update for SupportAI embeddings. Args: method (str): @@ -342,11 +342,11 @@ def forceConsistencyUpdate(self, server=""): Returns: JSON response from the consistency update. """ - method = server if server else self.server_mode - url = f"{self.nlqs_host}/{self.conn.graphname}/{method}/forceupdate" + server = method if method else self.server_mode + url = f"{self.nlqs_host}/{self.conn.graphname}/{server}/forceupdate" return self.conn._req("GET", url, authMode="pwd", resKey=None) - def checkConsistencyProgress(self, server=""): + def checkConsistencyProgress(self, method=""): """ Check the progress of the consistency update. Args: method (str): @@ -354,6 +354,6 @@ def checkConsistencyProgress(self, server=""): Returns: JSON response from the consistency update progress. """ - method = server if server else self.server_mode - url = f"{self.nlqs_host}/{self.conn.graphname}/{method}/consistency_status" + server = method if method else self.server_mode + url = f"{self.nlqs_host}/{self.conn.graphname}/{server}/consistency_status" return self.conn._req("GET", url, authMode="pwd", resKey=None)