Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GraphQL gave empty response #14573

Open
andysingal opened this issue Jul 4, 2024 · 11 comments
Open

GraphQL gave empty response #14573

andysingal opened this issue Jul 4, 2024 · 11 comments
Labels
documentation Improvements or additions to documentation triage Issue needs to be triaged/prioritized

Comments

@andysingal
Copy link

Documentation Issue Description

!pip install llama-index openai llama-index-tools-graphql -qU 

import os
os.environ["OPENAI_API_KEY"] =

from llama_index.tools.graphql import GraphQLToolSpec
from llama_index.agent.openai import OpenAIAgent

tool_spec = GraphQLToolSpec(
    url="https://streaming.bitquery.io/eap/",
    headers={
        "content-type": "application/json",
        'Authorization': 'Bearer TOKEN_HERE_V2'
    },
)

# agent = OpenAIAgent.from_tools(tool_spec.to_tool_list())

# agent.chat(
#     "get the id, model, name and type of the Ships from the graphql endpoint"
# )

graphql_fields = """subscription {
  Solana {
    InstructionBalanceUpdates(limit: {count: 10}) {
      Transaction {
        Index
        FeePayer
        Fee
        Signature
        Result {
          Success
          ErrorMessage
        }
      }
      Instruction {
        InternalSeqNumber
        Index
        CallPath
        Program {
          Address
          Name
          Parsed
        }
      }
      Block {
        Time
        Hash
        Height
      }
      BalanceUpdate {
        Account {
          Address
        }
        Amount
        Currency {
          Decimals
          CollectionAddress
          Name
          Key
          IsMutable
          Symbol
        }
      }
    }
  }
}
"""

suffix = "Search for the Transaction with positive Balance stored in the graphql database that has this schema "

response = tool_spec.graphql_request(query=graphql_fields + suffix, variables={}, operation_name="YourOperationName")

print(response)

### Documentation Link

https://github.com/run-llama/llama_index/blob/main/llama-index-integrations/tools/llama-index-tools-graphql/examples/graphql.ipynb
@andysingal andysingal added documentation Improvements or additions to documentation triage Issue needs to be triaged/prioritized labels Jul 4, 2024
Copy link

dosubot bot commented Jul 4, 2024

To resolve the issue of getting an empty response from the GraphQL endpoint, you should check the following:

  1. Query Alteration: Ensure that the query is being altered correctly to include pagination arguments. The alter_query method is responsible for this. Verify that the query is being modified as expected.

  2. Error Handling: Check if there are any errors in the response. The fetch_data method raises an APICallError if there are errors in the response. Ensure that the response does not contain any errors.

  3. Data Key: Ensure that the response data contains the expected data key. The transform_data method expects the data to be under the DATA_KEY which is "data".

Here is the relevant code for these checks:

def fetch_data(self) -> dict:
    """
    Fetches data from the WordLift GraphQL API.

    Returns:
        dict: The API response data.

    Raises:
        APIConnectionError: If there is an error connecting to the API.
    """
    try:
        query = self.alter_query()
        response = requests.post(
            self.endpoint, json={"query": query}, headers=self.headers
        )
        response.raise_for_status()
        data = response.json()
        if ERRORS_KEY in data:
            raise APICallError(data[ERRORS_KEY])
        return data
    except requests.exceptions.RequestException as e:
        logging.error("Error connecting to the API:", exc_info=True)
        raise APICallError("Error connecting to the API") from e

def transform_data(self, data: dict) -> List[Document]:
    """
    Transforms the fetched data into a list of Document objects.

    Args:
        data (dict): The API response data.

    Returns:
        List[Document]: The list of transformed documents.

    Raises:
        DataTransformError: If there is an error transforming the data.
    """
    try:
        data = data[DATA_KEY][self.fields]
        documents = []
        text_fields = self.configure_options.get("text_fields", [])
        metadata_fields = self.configure_options.get("metadata_fields", [])

        for item in data:
            if not all(key in item for key in text_fields):
                logging.warning(
                    f"Skipping document due to missing text fields: {item}"
                )
                continue
            row = {}
            for key, value in item.items():
                if key in text_fields or key in metadata_fields:
                    row[key] = value
                else:
                    row[key] = clean_value(value)

            text_parts = [
                get_separated_value(row, field.split("."))
                for field in text_fields
                if get_separated_value(row, field.split(".")) is not None
            ]

            text_parts = flatten_list(text_parts)
            text = " ".join(text_parts)
            extra_info = {}
            for field in metadata_fields:
                field_keys = field.split(".")
                value = get_separated_value(row, field_keys)
                if value is None:
                    logging.warning(f"Using default value for {field}")
                    value = "n.a"
                if isinstance(value, list) and len(value) != 0:
                    value = value[0]
                if is_url(value) and is_valid_html(value):
                    value = value.replace("\n", "")
                    extra_info[field] = value
                else:
                    cleaned_value = clean_value(value)
                    cleaned_value = cleaned_value.replace("\n", "")
                    extra_info[field] = cleaned_value
            text = text.replace("\n", "")
            plain_text = re.sub("<.*?>", "", text)
            document = Document(text=plain_text, extra_info=extra_info)
            documents.append(document)

        return documents
    except Exception as e:
        logging.error("Error transforming data:", exc_info=True)
        raise DataTransformError("Error transforming data") from e

Additionally, ensure that your GraphQL request is correctly formed and that the endpoint URL and headers are properly set. Here is an example of how to make a GraphQL request using the Playgrounds API:

def graphql_request(
    self,
    query: str,
    variables: Optional[dict] = None,
    operation_name: Optional[str] = None,
) -> Union[dict, str]:
    """
    Make a GraphQL query.

    Args:
        query (str): The GraphQL query string to execute.
        variables (dict, optional): Variables for the GraphQL query. Default is None.
        operation_name (str, optional): Name of the operation, if multiple operations are present in the query. Default is None.

    Returns:
        dict: The response from the GraphQL server if successful.
        str: Error message if the request fails.
    """
    payload = {"query": query.strip()}

    if variables:
        payload["variables"] = variables

    if operation_name:
        payload["operationName"] = operation_name

    try:
        response = requests.post(self.url, headers=self.headers, json=payload)

        # Check if the request was successful
        response.raise_for_status()

        # Return the JSON response
        return response.json()

    except requests.RequestException as e:
        # Handle request errors
        return str(e)
    except ValueError as e:
        # Handle JSON decoding errors
        return f"Error decoding JSON: {e}"

Ensure that:

  • The query is correctly altered to include pagination.
  • The response does not contain any errors.
  • The response data contains the expected data key and the fields you are trying to extract.

If the response is still empty, you may need to debug further by logging the response content to understand what is being returned by the API [1][2][3].

To continue talking to Dosu, mention @dosu.

@andysingal
Copy link
Author

To resolve the issue of getting an empty response from the GraphQL endpoint, you should check the following:

  1. Query Alteration: Ensure that the query is being altered correctly to include pagination arguments. The alter_query method is responsible for this. Verify that the query is being modified as expected.
  2. Error Handling: Check if there are any errors in the response. The fetch_data method raises an APICallError if there are errors in the response. Ensure that the response does not contain any errors.
  3. Data Key: Ensure that the response data contains the expected data key. The transform_data method expects the data to be under the DATA_KEY which is "data".

Here is the relevant code for these checks:

def fetch_data(self) -> dict:
    """
    Fetches data from the WordLift GraphQL API.

    Returns:
        dict: The API response data.

    Raises:
        APIConnectionError: If there is an error connecting to the API.
    """
    try:
        query = self.alter_query()
        response = requests.post(
            self.endpoint, json={"query": query}, headers=self.headers
        )
        response.raise_for_status()
        data = response.json()
        if ERRORS_KEY in data:
            raise APICallError(data[ERRORS_KEY])
        return data
    except requests.exceptions.RequestException as e:
        logging.error("Error connecting to the API:", exc_info=True)
        raise APICallError("Error connecting to the API") from e

def transform_data(self, data: dict) -> List[Document]:
    """
    Transforms the fetched data into a list of Document objects.

    Args:
        data (dict): The API response data.

    Returns:
        List[Document]: The list of transformed documents.

    Raises:
        DataTransformError: If there is an error transforming the data.
    """
    try:
        data = data[DATA_KEY][self.fields]
        documents = []
        text_fields = self.configure_options.get("text_fields", [])
        metadata_fields = self.configure_options.get("metadata_fields", [])

        for item in data:
            if not all(key in item for key in text_fields):
                logging.warning(
                    f"Skipping document due to missing text fields: {item}"
                )
                continue
            row = {}
            for key, value in item.items():
                if key in text_fields or key in metadata_fields:
                    row[key] = value
                else:
                    row[key] = clean_value(value)

            text_parts = [
                get_separated_value(row, field.split("."))
                for field in text_fields
                if get_separated_value(row, field.split(".")) is not None
            ]

            text_parts = flatten_list(text_parts)
            text = " ".join(text_parts)
            extra_info = {}
            for field in metadata_fields:
                field_keys = field.split(".")
                value = get_separated_value(row, field_keys)
                if value is None:
                    logging.warning(f"Using default value for {field}")
                    value = "n.a"
                if isinstance(value, list) and len(value) != 0:
                    value = value[0]
                if is_url(value) and is_valid_html(value):
                    value = value.replace("\n", "")
                    extra_info[field] = value
                else:
                    cleaned_value = clean_value(value)
                    cleaned_value = cleaned_value.replace("\n", "")
                    extra_info[field] = cleaned_value
            text = text.replace("\n", "")
            plain_text = re.sub("<.*?>", "", text)
            document = Document(text=plain_text, extra_info=extra_info)
            documents.append(document)

        return documents
    except Exception as e:
        logging.error("Error transforming data:", exc_info=True)
        raise DataTransformError("Error transforming data") from e

Additionally, ensure that your GraphQL request is correctly formed and that the endpoint URL and headers are properly set. Here is an example of how to make a GraphQL request using the Playgrounds API:

def graphql_request(
    self,
    query: str,
    variables: Optional[dict] = None,
    operation_name: Optional[str] = None,
) -> Union[dict, str]:
    """
    Make a GraphQL query.

    Args:
        query (str): The GraphQL query string to execute.
        variables (dict, optional): Variables for the GraphQL query. Default is None.
        operation_name (str, optional): Name of the operation, if multiple operations are present in the query. Default is None.

    Returns:
        dict: The response from the GraphQL server if successful.
        str: Error message if the request fails.
    """
    payload = {"query": query.strip()}

    if variables:
        payload["variables"] = variables

    if operation_name:
        payload["operationName"] = operation_name

    try:
        response = requests.post(self.url, headers=self.headers, json=payload)

        # Check if the request was successful
        response.raise_for_status()

        # Return the JSON response
        return response.json()

    except requests.RequestException as e:
        # Handle request errors
        return str(e)
    except ValueError as e:
        # Handle JSON decoding errors
        return f"Error decoding JSON: {e}"

Ensure that:

  • The query is correctly altered to include pagination.
  • The response does not contain any errors.
  • The response data contains the expected data key and the fields you are trying to extract.

If the response is still empty, you may need to debug further by logging the response content to understand what is being returned by the API [1][2][3].

To continue talking to Dosu, mention @dosu.

Can you please explain what is wrong in the code I shared?

Copy link

dosubot bot commented Jul 4, 2024

Your GraphQL query might be returning an empty response because the fields attribute in the WordLiftLoader class is not correctly specified or does not match the structure of the data returned by the API. The transform_data method expects the data to be present under data[DATA_KEY][self.fields]. If self.fields is not correctly set, it will not find the expected data, resulting in an empty response.

Additionally, ensure that your GraphQL request is correctly formed and that the endpoint URL and headers are properly set. The PlaygroundsSubgraphConnectorToolSpec class provides a good example of how to structure a GraphQL request:

def graphql_request(
    self,
    query: str,
    variables: Optional[dict] = None,
    operation_name: Optional[str] = None,
) -> Union[dict, str]:
    """
    Make a GraphQL query.

    Args:
        query (str): The GraphQL query string to execute.
        variables (dict, optional): Variables for the GraphQL query. Default is None.
        operation_name (str, optional): Name of the operation, if multiple operations are present in the query. Default is None.

    Returns:
        dict: The response from the GraphQL server if successful.
        str: Error message if the request fails.
    """
    payload = {"query": query.strip()}

    if variables:
        payload["variables"] = variables

    if operation_name:
        payload["operationName"] = operation_name

    try:
        response = requests.post(self.url, headers=self.headers, json=payload)

        # Check if the request was successful
        response.raise_for_status()

        # Return the JSON response
        return response.json()

    except requests.RequestException as e:
        # Handle request errors
        return str(e)
    except ValueError as e:
        # Handle JSON decoding errors
        return f"Error decoding JSON: {e}"

Ensure that self.fields is correctly set to match the structure of the data returned by your GraphQL API and that your request is properly configured [1][2].

To continue talking to Dosu, mention @dosu.

@andysingal
Copy link
Author

or

Do you suggest any ways to fix it , based on the code I shared?

Copy link

dosubot bot commented Jul 4, 2024

To address the issue of getting an empty response from your GraphQL query, you can try the following steps:

  1. Check Query Structure: Ensure that your query is correctly structured and matches the schema expected by the GraphQL API. Verify that all fields and types are correctly specified.

  2. Remove Pagination Arguments: If the API does not support pagination arguments, you can modify the alter_query method to remove them. Here is an example:

    def alter_query(self):
        """
        Alters the GraphQL query by removing pagination arguments.
    
        Returns:
            str: The altered GraphQL query without pagination arguments.
        """
        from graphql import parse, print_ast
    
        query = self.query
        ast = parse(query)
    
        # Assuming the first selection is the main query field
        field_node = ast.definitions[0].selection_set.selections[0]
    
        # Remove pagination arguments if they exist
        field_node.arguments = [
            arg for arg in field_node.arguments if arg.name.value not in ["page", "rows"]
        ]
    
        return print_ast(ast)
  3. Log the Response: Add logging to capture the response content. This will help you understand what is being returned by the API and diagnose any issues.

    def graphql_request(
        self,
        query: str,
        variables: Optional[dict] = None,
        operation_name: Optional[str] = None,
    ) -> Union[dict, str]:
        payload = {"query": query.strip()}
    
        if variables:
            payload["variables"] = variables
    
        if operation_name:
            payload["operationName"] = operation_name
    
        try:
            response = requests.post(self.url, headers=self.headers, json=payload)
            response.raise_for_status()
            response_data = response.json()
            logging.debug(f"GraphQL response: {response_data}")
            return response_data
        except requests.RequestException as e:
            return str(e)
        except ValueError as e:
            return f"Error decoding JSON: {e}"
  4. Verify Headers and Endpoint: Ensure that the endpoint URL and headers are correctly set. Double-check the authorization token and other headers required by the API.

  5. Check for Errors in Response: Ensure that the response does not contain any errors. You can add error handling to check for errors in the response data.

    def fetch_data(self) -> dict:
        try:
            query = self.alter_query()
            response = requests.post(self.endpoint, json={"query": query}, headers=self.headers)
            response.raise_for_status()
            data = response.json()
            if "errors" in data:
                logging.error(f"GraphQL errors: {data['errors']}")
                raise APICallError(data["errors"])
            return data
        except requests.exceptions.RequestException as e:
            logging.error("Error connecting to the API:", exc_info=True)
            raise APICallError("Error connecting to the API") from e

By following these steps, you should be able to diagnose and fix the issue with your GraphQL query returning an empty response. If the problem persists, further debugging and logging will help identify the root cause.

To continue talking to Dosu, mention @dosu.

@andysingal
Copy link
Author

To address the issue of getting an empty response from your GraphQL query, you can try the following steps:

  1. Check Query Structure: Ensure that your query is correctly structured and matches the schema expected by the GraphQL API. Verify that all fields and types are correctly specified.
  2. Remove Pagination Arguments: If the API does not support pagination arguments, you can modify the alter_query method to remove them. Here is an example:
    def alter_query(self):
        """
        Alters the GraphQL query by removing pagination arguments.
    
        Returns:
            str: The altered GraphQL query without pagination arguments.
        """
        from graphql import parse, print_ast
    
        query = self.query
        ast = parse(query)
    
        # Assuming the first selection is the main query field
        field_node = ast.definitions[0].selection_set.selections[0]
    
        # Remove pagination arguments if they exist
        field_node.arguments = [
            arg for arg in field_node.arguments if arg.name.value not in ["page", "rows"]
        ]
    
        return print_ast(ast)
  3. Log the Response: Add logging to capture the response content. This will help you understand what is being returned by the API and diagnose any issues.
    def graphql_request(
        self,
        query: str,
        variables: Optional[dict] = None,
        operation_name: Optional[str] = None,
    ) -> Union[dict, str]:
        payload = {"query": query.strip()}
    
        if variables:
            payload["variables"] = variables
    
        if operation_name:
            payload["operationName"] = operation_name
    
        try:
            response = requests.post(self.url, headers=self.headers, json=payload)
            response.raise_for_status()
            response_data = response.json()
            logging.debug(f"GraphQL response: {response_data}")
            return response_data
        except requests.RequestException as e:
            return str(e)
        except ValueError as e:
            return f"Error decoding JSON: {e}"
  4. Verify Headers and Endpoint: Ensure that the endpoint URL and headers are correctly set. Double-check the authorization token and other headers required by the API.
  5. Check for Errors in Response: Ensure that the response does not contain any errors. You can add error handling to check for errors in the response data.
    def fetch_data(self) -> dict:
        try:
            query = self.alter_query()
            response = requests.post(self.endpoint, json={"query": query}, headers=self.headers)
            response.raise_for_status()
            data = response.json()
            if "errors" in data:
                logging.error(f"GraphQL errors: {data['errors']}")
                raise APICallError(data["errors"])
            return data
        except requests.exceptions.RequestException as e:
            logging.error("Error connecting to the API:", exc_info=True)
            raise APICallError("Error connecting to the API") from e

By following these steps, you should be able to diagnose and fix the issue with your GraphQL query returning an empty response. If the problem persists, further debugging and logging will help identify the root cause.

To continue talking to Dosu, mention @dosu.

can you share llamaindex version of the code, is the code i shared correct?

Copy link

dosubot bot commented Jul 5, 2024

The code you shared appears to be mostly correct, but there are a few adjustments and best practices you can follow to ensure it works properly with the llama_index library. Here is a version of your code using llama_index:

!pip install llama-index openai llama-index-tools-graphql -qU

import os
import logging
import requests
from llama_index.tools.graphql import GraphQLToolSpec
from llama_index.agent.openai import OpenAIAgent

# Set up logging
logging.basicConfig(level=logging.DEBUG)

# Set the OpenAI API key
os.environ["OPENAI_API_KEY"] = "your_openai_api_key_here"

# Define the GraphQL endpoint and headers
tool_spec = GraphQLToolSpec(
    url="https://streaming.bitquery.io/eap/",
    headers={
        "content-type": "application/json",
        'Authorization': 'Bearer TOKEN_HERE_V2'
    },
)

# Define the GraphQL query
graphql_fields = """
subscription {
  Solana {
    InstructionBalanceUpdates(limit: {count: 10}) {
      Transaction {
        Index
        FeePayer
        Fee
        Signature
        Result {
          Success
          ErrorMessage
        }
      }
      Instruction {
        InternalSeqNumber
        Index
        CallPath
        Program {
          Address
          Name
          Parsed
        }
      }
      Block {
        Time
        Hash
        Height
      }
      BalanceUpdate {
        Account {
          Address
        }
        Amount
        Currency {
          Decimals
          CollectionAddress
          Name
          Key
          IsMutable
          Symbol
        }
      }
    }
  }
}
"""

# Define the suffix for the query
suffix = "Search for the Transaction with positive Balance stored in the graphql database that has this schema"

# Make the GraphQL request
response = tool_spec.graphql_request(query=graphql_fields + suffix, variables={}, operation_name="YourOperationName")

# Log and print the response
logging.debug(f"GraphQL response: {response}")
print(response)

Key Points:

  1. Logging: Added logging to capture the response content for debugging purposes.
  2. Environment Variable: Ensure the OpenAI API key is set correctly.
  3. GraphQL Request: The graphql_request method is used to make the request and handle potential errors.

Additional Steps:

  • Check Query Structure: Ensure that your query is correctly structured and matches the schema expected by the GraphQL API.
  • Verify Headers and Endpoint: Double-check the endpoint URL and headers, including the authorization token.
  • Error Handling: Ensure that the response does not contain any errors and handle them appropriately.

By following these steps and using the provided code, you should be able to diagnose and fix the issue with your GraphQL query returning an empty response. If the problem persists, further debugging and logging will help identify the root cause [1][2].

To continue talking to Dosu, mention @dosu.

@andysingal
Copy link
Author

The code you shared appears to be mostly correct, but there are a few adjustments and best practices you can follow to ensure it works properly with the llama_index library. Here is a version of your code using llama_index:

!pip install llama-index openai llama-index-tools-graphql -qU

import os
import logging
import requests
from llama_index.tools.graphql import GraphQLToolSpec
from llama_index.agent.openai import OpenAIAgent

# Set up logging
logging.basicConfig(level=logging.DEBUG)

# Set the OpenAI API key
os.environ["OPENAI_API_KEY"] = "your_openai_api_key_here"

# Define the GraphQL endpoint and headers
tool_spec = GraphQLToolSpec(
    url="https://streaming.bitquery.io/eap/",
    headers={
        "content-type": "application/json",
        'Authorization': 'Bearer TOKEN_HERE_V2'
    },
)

# Define the GraphQL query
graphql_fields = """
subscription {
  Solana {
    InstructionBalanceUpdates(limit: {count: 10}) {
      Transaction {
        Index
        FeePayer
        Fee
        Signature
        Result {
          Success
          ErrorMessage
        }
      }
      Instruction {
        InternalSeqNumber
        Index
        CallPath
        Program {
          Address
          Name
          Parsed
        }
      }
      Block {
        Time
        Hash
        Height
      }
      BalanceUpdate {
        Account {
          Address
        }
        Amount
        Currency {
          Decimals
          CollectionAddress
          Name
          Key
          IsMutable
          Symbol
        }
      }
    }
  }
}
"""

# Define the suffix for the query
suffix = "Search for the Transaction with positive Balance stored in the graphql database that has this schema"

# Make the GraphQL request
response = tool_spec.graphql_request(query=graphql_fields + suffix, variables={}, operation_name="YourOperationName")

# Log and print the response
logging.debug(f"GraphQL response: {response}")
print(response)

Key Points:

  1. Logging: Added logging to capture the response content for debugging purposes.
  2. Environment Variable: Ensure the OpenAI API key is set correctly.
  3. GraphQL Request: The graphql_request method is used to make the request and handle potential errors.

Additional Steps:

  • Check Query Structure: Ensure that your query is correctly structured and matches the schema expected by the GraphQL API.
  • Verify Headers and Endpoint: Double-check the endpoint URL and headers, including the authorization token.
  • Error Handling: Ensure that the response does not contain any errors and handle them appropriately.

By following these steps and using the provided code, you should be able to diagnose and fix the issue with your GraphQL query returning an empty response. If the problem persists, further debugging and logging will help identify the root cause [1][2].

To continue talking to Dosu, mention @dosu.

code is similar to what i shared by get empty response

Copy link

dosubot bot commented Jul 5, 2024

To help identify what might be wrong with your code or suggest further debugging steps, here are a few things you can check:

  1. Check the URL and Headers: Ensure that the url and headers you are passing to the GraphQLToolSpec are correct and that the server is reachable.

  2. Verify the Query and Variables: Make sure that the query, variables, and operation_name you are passing to the graphql_request method are correctly formatted and valid.

  3. Inspect the Response: The method graphql_request returns res.text, which is the raw text of the response. You might want to inspect the response status code and content to get more information about why the response is empty.

Here is an example of how you might modify your code to include additional debugging information:

import logging
import requests
from llama_index.tools.graphql import GraphQLToolSpec

# Set up logging
logging.basicConfig(level=logging.DEBUG)

class GraphQLToolSpec(BaseToolSpec):
    """Requests Tool."""

    spec_functions = ["graphql_request"]

    def __init__(self, url: str, headers: Optional[dict] = {}):
        self.headers = headers
        self.url = url

    def graphql_request(self, query: str, variables: str, operation_name: str):
        r"""
        Use this tool to make a GraphQL query against the server.

        Args:
            query (str): The GraphQL query to execute
            variables (str): The variable values for the query
            operation_name (str): The name for the query

        example input:
            "query":"query Ships {\n  ships {\n    id\n    model\n    name\n    type\n    status\n  }\n}",
            "variables":{},
            "operation_name":"Ships"

        """
        res = requests.post(
            self.url,
            headers=self.headers,
            json={
                "query": query,
                "variables": variables,
                "operationName": operation_name,
            },
        )
        
        # Debugging information
        logging.debug(f"Status Code: {res.status_code}")
        logging.debug(f"Response Text: {res.text}")
        
        return res.text

# Define the GraphQL endpoint and headers
tool_spec = GraphQLToolSpec(
    url="https://streaming.bitquery.io/eap/",
    headers={
        "content-type": "application/json",
        'Authorization': 'Bearer TOKEN_HERE_V2'
    },
)

# Define the GraphQL query
graphql_fields = """
subscription {
  Solana {
    InstructionBalanceUpdates(limit: {count: 10}) {
      Transaction {
        Index
        FeePayer
        Fee
        Signature
        Result {
          Success
          ErrorMessage
        }
      }
      Instruction {
        InternalSeqNumber
        Index
        CallPath
        Program {
          Address
          Name
          Parsed
        }
      }
      Block {
        Time
        Hash
        Height
      }
      BalanceUpdate {
        Account {
          Address
        }
        Amount
        Currency {
          Decimals
          CollectionAddress
          Name
          Key
          IsMutable
          Symbol
        }
      }
    }
  }
}
"""

# Define the suffix for the query
suffix = "Search for the Transaction with positive Balance stored in the graphql database that has this schema"

# Make the GraphQL request
response = tool_spec.graphql_request(query=graphql_fields + suffix, variables={}, operation_name="YourOperationName")

# Log and print the response
logging.debug(f"GraphQL response: {response}")
print(response)

By printing the status code and response text, you can get more insight into what might be going wrong. If the status code is not 200, it indicates an error. The response text might contain error messages or other information that can help you debug the issue.

Additionally, here are some examples from the llama_index library that might help you set up your GraphQL requests correctly:

Unauthenticated Server Example

from llama_index.tools.graphql.base import GraphQLToolSpec

# Unauthenticated example against a public server
url = "https://spacex-production.up.railway.app/"
headers = {
    "content-type": "application/json",
}

graphql_spec = GraphQLToolSpec(url=url, headers=headers)
agent = OpenAIAgent.from_tools(
    graphql_spec.to_tool_list(),
    verbose=True,
)

print(agent.chat("get the id, name and type of the Ships from the graphql endpoint"))

Authenticated Server Example

# Authenticated example against a Shopify store

url = "https://your-store.myshopify.com/admin/api/2023-07/graphql.json"
headers = {
    "accept-language": "en-US,en;q=0.9",
    "content-type": "application/json",
    "X-Shopify-Access-Token": "your-admin-key",
}

graphql_spec = GraphQLToolSpec(url=url, headers=headers)
agent = OpenAIAgent.from_tools(
    graphql_spec.to_tool_list(),
    verbose=True,
)

print(
    agent.chat("get the id and title of the first 3 products from the graphql server")
)

These examples show how to set up both unauthenticated and authenticated GraphQL requests using the llama_index library. Make sure your setup aligns with these examples, especially regarding the URL and headers [1][2][3].

To continue talking to Dosu, mention @dosu.

@andysingal
Copy link
Author

To help identify what might be wrong with your code or suggest further debugging steps, here are a few things you can check:

  1. Check the URL and Headers: Ensure that the url and headers you are passing to the GraphQLToolSpec are correct and that the server is reachable.
  2. Verify the Query and Variables: Make sure that the query, variables, and operation_name you are passing to the graphql_request method are correctly formatted and valid.
  3. Inspect the Response: The method graphql_request returns res.text, which is the raw text of the response. You might want to inspect the response status code and content to get more information about why the response is empty.

Here is an example of how you might modify your code to include additional debugging information:

import logging
import requests
from llama_index.tools.graphql import GraphQLToolSpec

# Set up logging
logging.basicConfig(level=logging.DEBUG)

class GraphQLToolSpec(BaseToolSpec):
    """Requests Tool."""

    spec_functions = ["graphql_request"]

    def __init__(self, url: str, headers: Optional[dict] = {}):
        self.headers = headers
        self.url = url

    def graphql_request(self, query: str, variables: str, operation_name: str):
        r"""
        Use this tool to make a GraphQL query against the server.

        Args:
            query (str): The GraphQL query to execute
            variables (str): The variable values for the query
            operation_name (str): The name for the query

        example input:
            "query":"query Ships {\n  ships {\n    id\n    model\n    name\n    type\n    status\n  }\n}",
            "variables":{},
            "operation_name":"Ships"

        """
        res = requests.post(
            self.url,
            headers=self.headers,
            json={
                "query": query,
                "variables": variables,
                "operationName": operation_name,
            },
        )
        
        # Debugging information
        logging.debug(f"Status Code: {res.status_code}")
        logging.debug(f"Response Text: {res.text}")
        
        return res.text

# Define the GraphQL endpoint and headers
tool_spec = GraphQLToolSpec(
    url="https://streaming.bitquery.io/eap/",
    headers={
        "content-type": "application/json",
        'Authorization': 'Bearer TOKEN_HERE_V2'
    },
)

# Define the GraphQL query
graphql_fields = """
subscription {
  Solana {
    InstructionBalanceUpdates(limit: {count: 10}) {
      Transaction {
        Index
        FeePayer
        Fee
        Signature
        Result {
          Success
          ErrorMessage
        }
      }
      Instruction {
        InternalSeqNumber
        Index
        CallPath
        Program {
          Address
          Name
          Parsed
        }
      }
      Block {
        Time
        Hash
        Height
      }
      BalanceUpdate {
        Account {
          Address
        }
        Amount
        Currency {
          Decimals
          CollectionAddress
          Name
          Key
          IsMutable
          Symbol
        }
      }
    }
  }
}
"""

# Define the suffix for the query
suffix = "Search for the Transaction with positive Balance stored in the graphql database that has this schema"

# Make the GraphQL request
response = tool_spec.graphql_request(query=graphql_fields + suffix, variables={}, operation_name="YourOperationName")

# Log and print the response
logging.debug(f"GraphQL response: {response}")
print(response)

By printing the status code and response text, you can get more insight into what might be going wrong. If the status code is not 200, it indicates an error. The response text might contain error messages or other information that can help you debug the issue.

Additionally, here are some examples from the llama_index library that might help you set up your GraphQL requests correctly:

Unauthenticated Server Example

from llama_index.tools.graphql.base import GraphQLToolSpec

# Unauthenticated example against a public server
url = "https://spacex-production.up.railway.app/"
headers = {
    "content-type": "application/json",
}

graphql_spec = GraphQLToolSpec(url=url, headers=headers)
agent = OpenAIAgent.from_tools(
    graphql_spec.to_tool_list(),
    verbose=True,
)

print(agent.chat("get the id, name and type of the Ships from the graphql endpoint"))

Authenticated Server Example

# Authenticated example against a Shopify store

url = "https://your-store.myshopify.com/admin/api/2023-07/graphql.json"
headers = {
    "accept-language": "en-US,en;q=0.9",
    "content-type": "application/json",
    "X-Shopify-Access-Token": "your-admin-key",
}

graphql_spec = GraphQLToolSpec(url=url, headers=headers)
agent = OpenAIAgent.from_tools(
    graphql_spec.to_tool_list(),
    verbose=True,
)

print(
    agent.chat("get the id and title of the first 3 products from the graphql server")
)

These examples show how to set up both unauthenticated and authenticated GraphQL requests using the llama_index library. Make sure your setup aligns with these examples, especially regarding the URL and headers [1][2][3].

To continue talking to Dosu, mention @dosu.

can someone from llama index team look in to it?

Copy link

dosubot bot commented Jul 5, 2024

@logan-markewich, this one's a bit out of my wheelhouse, could you step in and provide your guidance?

To continue talking to Dosu, mention @dosu.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation triage Issue needs to be triaged/prioritized
1 participant