פיתוח סוכן נתונים באמצעות HTTP ו-Python

בדף הזה נסביר איך משתמשים ב-Python כדי לשלוח בקשות HTTP ל-Conversational Analytics API (הגישה אליו מתבצעת דרך geminidataanalytics.googleapis.com).

קוד Python לדוגמה שבדף הזה מראה איך לבצע את הפעולות הבאות:

אפשר גם להריץ את דוגמאות הקוד שבדף הזה במחברות של Colaboratory בנושא HTTP של Conversational Analytics API.

גרסה מלאה של קוד לדוגמה כלולה בסוף הדף, יחד עם פונקציות העזר שמשמשות לשידור של תגובת ה-API.

הגדרת ההגדרות הראשוניות והאימות

הקוד לדוגמה ב-Python מבצע את המשימות הבאות:

  • ייבוא הספריות הנדרשות של Python
  • הגדרת משתנים לפרויקט החיוב, הוראות למערכת ושאלה לסוכנות הנתונים
  • הצגת אסימון גישה לאימות HTTP באמצעות ה-CLI של Google Cloud
from pygments import highlight, lexers, formatters
import pandas as pd
import json as json_lib
import requests
import json
import altair as alt
import IPython
from IPython.display import display, HTML
import google.auth
from google.auth.transport.requests import Request

from google.colab import auth
auth.authenticate_user()

billing_project = 'YOUR-BILLING-PROJECT'
system_description = 'YOUR-SYSTEM-INSTRUCTIONS'
question = 'YOUR-QUESTION-HERE'

access_token = !gcloud auth application-default print-access-token
headers = {
    "Authorization": f"Bearer {access_token[0]}",
    "Content-Type": "application/json",
}

מחליפים את ערכי הדוגמה באופן הבא:

  • YOUR-BILLING-PROJECT: המזהה של פרויקט החיוב שבו הפעלתם את ממשקי ה-API הנדרשים.
  • YOUR-SYSTEM-INSTRUCTIONS: הוראות מערכת שמנחות את ההתנהגות של הסוכן ומאפשרות לכם להתאים אישית את הסוכן לצרכים שלכם. לדוגמה, אפשר להשתמש בהוראות המערכת כדי להגדיר מונחים עסקיים (למשל, מהו 'לקוח נאמן'), לשלוט באורך התשובה ('סיכום בפחות מ-20 מילים') או להגדיר את עיצוב הנתונים ('התאמה לסטנדרטים של החברה'). מחליפים את הטקסט של placeholder בהוראות שרלוונטיות לנתונים ולתרחיש לדוגמה.
  • YOUR-QUESTION-HERE: שאלה בשפה טבעית ששולחים לסוכנות הנתונים.

אימות מול Looker

אם אתם מתכננים להתחבר למקור נתונים של Looker, תצטרכו לבצע אימות למכונה של Looker.

שימוש במפתחות API

דוגמת הקוד הבאה ב-Python מראה איך לאמת את הסוכן במכונה של Looker באמצעות מפתחות API.

looker_credentials = {
    "oauth": {
        "secret": {
          "client_id": "YOUR-LOOKER-CLIENT-ID",
          "client_secret": "YOUR-LOOKER-CLIENT-SECRET",
        }
    }
}

מחליפים את ערכי הדוגמה באופן הבא:

  • YOUR-LOOKER-CLIENT-ID: מזהה הלקוח של מפתח Looker API שנוצר.
  • YOUR-LOOKER-CLIENT-SECRET: סוד הלקוח של מפתח Looker API שנוצר.

שימוש באסימוני גישה

דוגמת הקוד הבאה ב-Python מראה איך לאמת את הסוכן במכונה של Looker באמצעות אסימוני גישה.

looker_credentials = {
   "oauth": {
       "token": {
         "access_token": "YOUR-TOKEN",
       }
   }
}

מחליפים את ערכי הדוגמה באופן הבא:

  • YOUR-TOKEN: הערך של access_token שיוצרים כדי לבצע אימות ב-Looker.

התחברות למקור נתונים

דוגמאות הקוד הבאות ב-Python מדגימות איך להגדיר את מקור הנתונים של Looker, BigQuery או Looker Studio לשימוש של הסוכן.

חיבור לנתונים של Looker

הקוד לדוגמה הבא מגדיר חיבור ל-Looker Explore. כדי ליצור חיבור למכונה של Looker, צריך לוודא שיצרתם מפתחות API של Looker, כפי שמתואר במאמר אימות והתחברות למקור נתונים באמצעות Conversational Analytics API.

looker_data_source = {
    "looker": {
      "explore_references": {
          "looker_instance_uri": "https://your_company.looker.com",
          "lookml_model": "your_model",
          "explore": "your_explore",
      },
    }
}

מחליפים את ערכי הדוגמה באופן הבא:

  • https://your_company.looker.com: כתובת ה-URL המלאה של מכונה של Looker.
  • your_model: השם של מודל ה-LookML שכולל את ה-Explore שאליו רוצים להתחבר.
  • your_explore: השם של Looker Explore שרוצים שסוכן הנתונים ישלח אליו שאילתה.

התחברות לנתוני BigQuery

בקוד לדוגמה הבא מוגדר חיבור לטבלה ב-BigQuery.

bigquery_data_sources = {
   "bq" :  {
        "tableReferences": [
        {
            "projectId": "bigquery-public-data",
            "datasetId": "san_francisco",
            "tableId": "street_trees",
        }
        ]
    }
}

מחליפים את ערכי הדוגמה באופן הבא:

  • bigquery-public-data: המזהה של Google Cloud הפרויקט שמכיל את מערך הנתונים והטבלה ב-BigQuery שאליהם רוצים להתחבר. כדי להתחבר למערך נתונים ציבורי, מציינים bigquery-public-data.
  • san_francisco: המזהה של מערך הנתונים ב-BigQuery.
  • street_trees: המזהה של טבלת BigQuery.

חיבור לנתונים של Looker Studio

הקוד לדוגמה הבא מגדיר חיבור למקור נתונים ב-Looker Studio.

looker_studio_data_source = {
    "studio":{
        "studio_references":
         [
            {
              "studio_datasource_id": "studio_datasource_id"
            }
         ]
    }
}

מחליפים את studio_datasource_id במזהה של מקור הנתונים.

יצירת סוכן נתונים

דוגמת הקוד הבאה ממחישה איך יוצרים את סוכן הנתונים על ידי שליחת בקשת HTTP POST לנקודת הקצה ליצירת סוכן הנתונים. מטען הייעודי (payload) של הבקשה כולל את הפרטים הבאים:

  • שם המשאב המלא של הסוכן. הערך הזה כולל את מזהה הפרויקט, המיקום ומזהה ייחודי של הסוכן.
  • התיאור של סוכן הנתונים.
  • ההקשר של סוכן הנתונים, כולל תיאור המערכת (הוגדר בקטע הגדרת ההגדרות הראשוניות והאימות) ומקור הנתונים שבו סוכן הנתונים משתמש (הוגדר בקטע קישור למקור נתונים).

אפשר גם להפעיל ניתוח מתקדם באמצעות Python על ידי הכללת הפרמטר options בתוכן של הבקשה.

data_agent_url = f"https://geminidataanalytics.googleapis.com/v1alpha/projects/{billing_project}/locations/{location}/dataAgents"

data_agent_id = "data_agent_1"

data_agent_payload = {
      "name": f"projects/{billing_project}/locations/{location}/dataAgents/{data_agent_id}", # Optional
      "description": "This is the description of data_agent_1.", # Optional

      "data_analytics_agent": {
          "published_context": {
              "datasource_references": bigquery_data_sources,
              "system_instruction": system_instruction,
              # Optional: To enable advanced analysis with Python, include the following options block:
              "options": {
                  "analysis": {
                      "python": {
                          "enabled": True
                      }
                  }
              }
          }
      }
  }

params = {"data_agent_id": data_agent_id} # Optional

data_agent_response = requests.post(
    data_agent_url, params=params, json=data_agent_payload, headers=headers
)

if data_agent_response.status_code == 200:
    print("Data Agent created successfully!")
    print(json.dumps(data_agent_response.json(), indent=2))
else:
    print(f"Error creating Data Agent: {data_agent_response.status_code}")
    print(data_agent_response.text)

מחליפים את ערכי הדוגמה באופן הבא:

  • data_agent_1: מזהה ייחודי של סוכן הנתונים. הערך הזה משמש בשם המשאב של הסוכן וכפרמטר השאילתה של כתובת ה-URL data_agent_id.
  • This is the description of data_agent_1.: תיאור של סוכן הנתונים.

יצירת שיחה

דוגמת הקוד הבאה מראה איך ליצור שיחה עם סוכן הנתונים.

conversation_url = f"https://geminidataanalytics.googleapis.com/v1alpha/projects/{billing_project}/locations/{location}/conversations"

data_agent_id = "data_agent_1"
conversation_id = "conversation_1"

conversation_payload = {
    "agents": [
        f"projects/{billing_project}/locations/{location}/dataAgents/{data_agent_id}"
    ],
    "name": f"projects/{billing_project}/locations/{location}/conversations/{conversation_id}"
}
params = {
    "conversation_id": conversation_id
}

conversation_response = requests.post(conversation_url, headers=headers, params=params, json=conversation_payload)

if conversation_response.status_code == 200:
    print("Conversation created successfully!")
    print(json.dumps(conversation_response.json(), indent=2))
else:
    print(f"Error creating Conversation: {conversation_response.status_code}")
    print(conversation_response.text)

מחליפים את ערכי הדוגמה באופן הבא:

  • data_agent_1: המזהה של סוכן הנתונים, כפי שמוגדר בבלוק הקוד לדוגמה בקטע יצירת סוכן נתונים.
  • conversation_1: מזהה ייחודי של השיחה.

שימוש ב-API לשאילת שאלות

אחרי שיוצרים סוכן נתונים ושיחה, אפשר לשאול שאלות לגבי הנתונים באמצעות אחת מהשיטות הבאות:

  • צ'אט עם שמירת מצב: Google Cloud אחסון וניהול של היסטוריית השיחות. צריך לשלוח רק את ההודעה הנוכחית בכל צומת.
  • צ'אט ללא שמירת מצב: האפליקציה שלכם אחראית על שמירת היסטוריית השיחות. Google Cloud לא שומרת את היסטוריית השיחות בין הבקשות. עליכם לכלול את ההודעות הקודמות הרלוונטיות יחד עם ההודעה החדשה בכל שלב.

מידע נוסף על שיחות עם כמה תשובות זמין במאמר יצירת שיחה עם כמה תשובות.

צ'אט עם שמירת מצב

שליחת בקשת צ'אט עם שמירת מצב עם הפניה לשיחה

בדוגמת הקוד הבאה מוסבר איך לשאול את השאלות לגבי ה-API באמצעות השיחה שהגדרתם בשלבים הקודמים. בדוגמה הזו נעשה שימוש בפונקציית העזר get_stream כדי להעביר את התגובה בסטרימינג.

chat_url = f"https://geminidataanalytics.googleapis.com/v1alpha/projects/{billing_project}/locations/{location}:chat"

data_agent_id = "data_agent_1"
conversation_id = "conversation_1"

# Construct the payload
chat_payload = {
    "parent": f"projects/{billing_project}/locations/global",
    "messages": [
        {
            "userMessage": {
                "text": "Make a bar graph for the top 5 states by the total number of airports"
            }
        }
    ],
    "conversation_reference": {
        "conversation": f"projects/{billing_project}/locations/{location}/conversations/{conversation_id}",
        "data_agent_context": {
            "data_agent": f"projects/{billing_project}/locations/{location}/dataAgents/{data_agent_id}",
            # "credentials": looker_credentials
        }
    }
}

# Call the get_stream function to stream the response
get_stream(chat_url, chat_payload)

מחליפים את ערכי הדוגמה באופן הבא:

  • data_agent_1: המזהה של סוכן הנתונים, כפי שמוגדר בבלוק הקוד לדוגמה בקטע יצירת סוכן נתונים.
  • conversation_1: מזהה ייחודי של השיחה.
  • Make a bar graph for the top 5 states by the total number of airports שימשה כהנחיה לדוגמה.

צ'אט ללא שמירת מצב

שליחת בקשת צ'אט ללא מצב עם הפניה לסוכנות נתונים

בדוגמת הקוד הבאה מוסבר איך לשאול את ה-API שאלה ללא מצב באמצעות סוכן הנתונים שהגדרתם בשלבים הקודמים. בדוגמה הזו נעשה שימוש בפונקציית העזר get_stream כדי להעביר את התגובה בסטרימינג.

chat_url = f"https://geminidataanalytics.googleapis.com/v1alpha/projects/{billing_project}/locations/{location}:chat"

data_agent_id = "data_agent_1"

# Construct the payload
chat_payload = {
    "parent": f"projects/{billing_project}/locations/global",
    "messages": [
        {
            "userMessage": {
                "text": "Make a bar graph for the top 5 states by the total number of airports"
            }
        }
    ],
    "data_agent_context": {
        "data_agent": f"projects/{billing_project}/locations/{location}/dataAgents/{data_agent_id}",
        # "credentials": looker_credentials
    }
}

# Call the get_stream function to stream the response
get_stream(chat_url, chat_payload)

מחליפים את ערכי הדוגמה באופן הבא:

  • data_agent_1: המזהה של סוכן הנתונים, כפי שמוגדר בבלוק הקוד לדוגמה בקטע יצירת סוכן נתונים.
  • Make a bar graph for the top 5 states by the total number of airports שימשה כהנחיה לדוגמה.

שליחת בקשת צ'אט ללא שמירת מצב עם הקשר בשורה

קוד לדוגמה שמראה איך לשאול את ה-API שאלה ללא מצב באמצעות הקשר בשורה. בדוגמה הזו נעשה שימוש בפונקציית העזר get_stream כדי להעביר את התגובה בסטרימינג, ומקור הנתונים הוא BigQuery.

אפשר גם להפעיל ניתוח מתקדם באמצעות Python על ידי הכללת הפרמטר options בתוכן של הבקשה.

chat_url = f"https://geminidataanalytics.googleapis.com/v1alpha/projects/{billing_project}/locations/global:chat"

# Construct the payload
chat_payload = {
    "parent": f"projects/{billing_project}/locations/global",
    "messages": [
        {
            "userMessage": {
                "text": "Make a bar graph for the top 5 states by the total number of airports"
            }
        }
    ],
    "inline_context": {
        "datasource_references": bigquery_data_sources,
          # Optional: To enable advanced analysis with Python, include the following options block:
          "options": {
              "analysis": {
                  "python": {
                      "enabled": True
                  }
              }
          }
    }
}

# Call the get_stream function to stream the response
get_stream(chat_url, chat_payload)

דוגמת קוד מקצה לקצה

דוגמת הקוד הבאה, שניתן להרחיב, מכילה את כל המשימות שמפורטות במדריך הזה.

פיתוח סוכן נתונים באמצעות HTTP ו-Python

        from pygments import highlight, lexers, formatters
        import pandas as pd
        import json as json_lib
        import requests
        import json
        import altair as alt
        import IPython
        from IPython.display import display, HTML
        import requests
        import google.auth
        from google.auth.transport.requests import Request

        from google.colab import auth
        auth.authenticate_user()

        access_token = !gcloud auth application-default print-access-token
        headers = {
            "Authorization": f"Bearer {access_token[0]}",
            "Content-Type": "application/json",
        }

        ################### Data source details ###################

        billing_project = "your_billing_project"
        location = "global"
        system_instruction = "Help the user in analyzing their data"


        # BigQuery data source
        bigquery_data_sources = {
            "bq": {
            "tableReferences": [
                {
                "projectId": "bigquery-public-data",
                "datasetId": "san_francisco",
                "tableId": "street_trees"
                }
            ]
            }
        }

        # Looker data source
        looker_credentials = {
            "oauth": {
                "secret": {
                "client_id": "your_looker_client_id",
                "client_secret": "your_looker_client_secret",
                }
            }
        }
        # # To use access_token for authentication, uncomment the following looker_credentials code block and comment out the previous looker_credentials code block.
        # looker_credentials = {
        #     "oauth": {
        #         "token": {
        #           "access_token": "your_looker_access_token",
        #         }
        #     }
        # }
        looker_data_source = {
            "looker": {
            "explore_references": {
                "looker_instance_uri": "https://my_company.looker.com",
                "lookml_model": "my_model",
                "explore": "my_explore",
            },
            # "credentials": looker_credentials # Uncomment this when using looker as datasource in stateless chat
            }
        }

        # Looker Studio data source
        looker_studio_data_source = {
            "studio":{
                "studio_references":
                [
                    {
                    "datasource_id": "your_studio_datasource_id"
                    }
                ]
            }
        }

        ################### Create data agent ###################
        data_agent_url = f"https://geminidataanalytics.googleapis.com/v1alpha/projects/{billing_project}/locations/{location}/dataAgents"

        data_agent_id = "data_agent_1"

        data_agent_payload = {
            "name": f"projects/{billing_project}/locations/{location}/dataAgents/{data_agent_id}", # Optional
            "description": "This is the description of data_agent.", # Optional

            "data_analytics_agent": {
                "published_context": {
                    "datasource_references": bigquery_data_sources,
                    "system_instruction": system_instruction,
                    # Optional: To enable advanced analysis with Python, include the following options block:
                    "options": {
                        "analysis": {
                            "python": {
                                "enabled": True
                            }
                        }
                    }
                }
            }
        }

        params = {"data_agent_id": data_agent_id} # Optional

        data_agent_response = requests.post(
            data_agent_url, params=params, json=data_agent_payload, headers=headers
        )

        if data_agent_response.status_code == 200:
            print("Data Agent created successfully!")
            print(json.dumps(data_agent_response.json(), indent=2))
        else:
            print(f"Error creating Data Agent: {data_agent_response.status_code}")
            print(data_agent_response.text)


        ################### Create conversation ###################

        conversation_url = f"https://geminidataanalytics.googleapis.com/v1alpha/projects/{billing_project}/locations/{location}/conversations"

        data_agent_id = "data_agent_1"
        conversation_id = "conversation _1"

        conversation_payload = {
            "agents": [
                f"projects/{billing_project}/locations/{location}/dataAgents/{data_agent_id}"
            ],
            "name": f"projects/{billing_project}/locations/{location}/conversations/{conversation_id}"
        }
        params = {
            "conversation_id": conversation_id
        }

        conversation_response = requests.post(conversation_url, headers=headers, params=params, json=conversation_payload)

        if conversation_response.status_code == 200:
            print("Conversation created successfully!")
            print(json.dumps(conversation_response.json(), indent=2))
        else:
            print(f"Error creating Conversation: {conversation_response.status_code}")
            print(conversation_response.text)


        ################### Chat with the API by using conversation (stateful) ####################

        chat_url = f"https://geminidataanalytics.googleapis.com/v1alpha/projects/{billing_project}/locations/{location}:chat"

        data_agent_id = "data_agent_1"
        conversation_id = "conversation _1"

        # Construct the payload
        chat_payload = {
            "parent": f"projects/{billing_project}/locations/global",
            "messages": [
                {
                    "userMessage": {
                        "text": "Make a bar graph for the top 5 states by the total number of airports"
                    }
                }
            ],
            "conversation_reference": {
                "conversation": f"projects/{billing_project}/locations/{location}/conversations/{conversation_id}",
                "data_agent_context": {
                    "data_agent": f"projects/{billing_project}/locations/{location}/dataAgents/{data_agent_id}",
                    # "credentials": looker_credentials #Uncomment this if your dataAgent contains looker dataSource
                }
            }
        }

        # Call the get_stream function to stream the response
        get_stream(chat_url, chat_payload)

        ################### Chat with the API by using dataAgents (stateless) ####################

        chat_url = f"https://geminidataanalytics.googleapis.com/v1alpha/projects/{billing_project}/locations/{location}:chat"

        data_agent_id = "data_agent_1"

        # Construct the payload
        chat_payload = {
            "parent": f"projects/{billing_project}/locations/global",
            "messages": [
                {
                    "userMessage": {
                        "text": "Make a bar graph for the top 5 states by the total number of airports"
                    }
                }
            ],
            "data_agent_context": {
                "data_agent": f"projects/{billing_project}/locations/{location}/dataAgents/{data_agent_id}",
                # "credentials": looker_credentials #Uncomment this if your dataAgent contains looker as dataSource
            }
        }

        # Call the get_stream function to stream the response
        get_stream(chat_url, chat_payload)

        ################### Chat with the API by using inline context (stateless) ####################

        chat_url = f"https://geminidataanalytics.googleapis.com/v1alpha/projects/{billing_project}/locations/global:chat"

        # Construct the payload
        chat_payload = {
            "parent": f"projects/{billing_project}/locations/global",
            "messages": [
                {
                    "userMessage": {
                        "text": "Make a bar graph for the top 5 states by the total number of airports"
                    }
                }
            ],
            "inline_context": {
                "datasource_references": bigquery_data_sources,
                # Optional - if wanting to use advanced analysis with python
                "options": {
                    "analysis": {
                        "python": {
                            "enabled": True
                        }
                    }
                }
            }
        }

        # Call the get_stream function to stream the response
        get_stream(chat_url, chat_payload)

    

דוגמת הקוד הבאה, שניתן להרחיב, מכילה את פונקציות העזרה של Python שמשמשות לשידור תשובות בצ'אט.

פונקציות עזרה ב-Python להעברה בזמן אמת של תשובות בצ'אט

        def is_json(str):
          try:
              json_object = json_lib.loads(str)
          except ValueError as e:
              return False
          return True

        def handle_text_response(resp):
          parts = resp['parts']
          print(''.join(parts))

        def get_property(data, field_name, default = ''):
          return data[field_name] if field_name in data else default

        def display_schema(data):
          fields = data['fields']
          df = pd.DataFrame({
            "Column": map(lambda field: get_property(field, 'name'), fields),
            "Type": map(lambda field: get_property(field, 'type'), fields),
            "Description": map(lambda field: get_property(field, 'description', '-'), fields),
            "Mode": map(lambda field: get_property(field, 'mode'), fields)
          })
          display(df)

        def display_section_title(text):
          display(HTML('<h2>{}</h2>'.format(text)))

        def format_bq_table_ref(table_ref):
          return '{}.{}.{}'.format(table_ref['projectId'], table_ref['datasetId'], table_ref['tableId'])

        def format_looker_table_ref(table_ref):
          return 'lookmlModel: {}, explore: {}, lookerInstanceUri: {}'.format(table_ref['lookmlModel'], table_ref['explore'], table_ref['lookerInstanceUri'])

        def display_datasource(datasource):
          source_name = ''

          if 'studioDatasourceId' in datasource:
            source_name = datasource['studioDatasourceId']
          elif 'lookerExploreReference' in datasource:
            source_name = format_looker_table_ref(datasource['lookerExploreReference'])
          else:
            source_name = format_bq_table_ref(datasource['bigqueryTableReference'])

          print(source_name)
          display_schema(datasource['schema'])

        def handle_schema_response(resp):
          if 'query' in resp:
            print(resp['query']['question'])
          elif 'result' in resp:
            display_section_title('Schema resolved')
            print('Data sources:')
            for datasource in resp['result']['datasources']:
              display_datasource(datasource)

        def handle_data_response(resp):
          if 'query' in resp:
            query = resp['query']
            display_section_title('Retrieval query')
            print('Query name: {}'.format(query['name']))
            print('Question: {}'.format(query['question']))
            print('Data sources:')
            for datasource in query['datasources']:
              display_datasource(datasource)
          elif 'generatedSql' in resp:
            display_section_title('SQL generated')
            print(resp['generatedSql'])
          elif 'result' in resp:
            display_section_title('Data retrieved')

            fields = map(lambda field: get_property(field, 'name'), resp['result']['schema']['fields'])
            dict = {}

            for field in fields:
              dict[field] = map(lambda el: get_property(el, field), resp['result']['data'])

            display(pd.DataFrame(dict))

        def handle_chart_response(resp):
          if 'query' in resp:
            print(resp['query']['instructions'])
          elif 'result' in resp:
            vegaConfig = resp['result']['vegaConfig']
            alt.Chart.from_json(json_lib.dumps(vegaConfig)).display();

        def handle_error(resp):
          display_section_title('Error')
          print('Code: {}'.format(resp['code']))
          print('Message: {}'.format(resp['message']))

        def get_stream(url, json):
          s = requests.Session()

          acc = ''

          with s.post(url, json=json, headers=headers, stream=True) as resp:
            for line in resp.iter_lines():
              if not line:
                continue

              decoded_line = str(line, encoding='utf-8')

              if decoded_line == '[{':
                acc = '{'
              elif decoded_line == '}]':
                acc += '}'
              elif decoded_line == ',':
                continue
              else:
                acc += decoded_line

              if not is_json(acc):
                continue

              data_json = json_lib.loads(acc)

              if not 'systemMessage' in data_json:
                if 'error' in data_json:
                    handle_error(data_json['error'])
                continue

              if 'text' in data_json['systemMessage']:
                handle_text_response(data_json['systemMessage']['text'])
              elif 'schema' in data_json['systemMessage']:
                handle_schema_response(data_json['systemMessage']['schema'])
              elif 'data' in data_json['systemMessage']:
                handle_data_response(data_json['systemMessage']['data'])
              elif 'chart' in data_json['systemMessage']:
                handle_chart_response(data_json['systemMessage']['chart'])
              else:
                colored_json = highlight(acc, lexers.JsonLexer(), formatters.TerminalFormatter())
                print(colored_json)
                print('\n')
                acc = ''