integrate_graphql (#36)
Browse files- integrate graphql (d5fdc24444980e5064742cf4de726094d66bcd1d)
- app.py +3 -1
 - data_sources/__init__.py +2 -1
 - data_sources/connect_graphql.py +145 -0
 - functions/__init__.py +4 -4
 - functions/chat_functions.py +86 -8
 - functions/query_functions.py +103 -1
 - requirements.txt +2 -0
 - templates/doc_db.py +3 -3
 - templates/graphql.py +109 -0
 - templates/sql_db.py +2 -2
 - tools/tools.py +73 -3
 
    	
        app.py
    CHANGED
    
    | 
         @@ -1,6 +1,6 @@ 
     | 
|
| 1 | 
         
             
            from utils import TEMP_DIR, message_dict
         
     | 
| 2 | 
         
             
            import gradio as gr
         
     | 
| 3 | 
         
            -
            import templates.data_file as data_file, templates.sql_db as sql_db, templates.doc_db as doc_db
         
     | 
| 4 | 
         | 
| 5 | 
         
             
            import os
         
     | 
| 6 | 
         
             
            from getpass import getpass
         
     | 
| 
         @@ -76,6 +76,8 @@ with gr.Blocks(theme=theme, css=css, head=head, delete_cache=(3600,3600)) as dem 
     | 
|
| 76 | 
         
             
                    sql_db.demo.render()
         
     | 
| 77 | 
         
             
                with gr.Tab("Document (MongoDB) Database"):
         
     | 
| 78 | 
         
             
                    doc_db.demo.render()
         
     | 
| 
         | 
|
| 
         | 
|
| 79 | 
         | 
| 80 | 
         
             
                footer = gr.HTML("""<!-- Footer -->
         
     | 
| 81 | 
         
             
                    <footer class="max-w-4xl mx-auto mt-12 text-center text-gray-500 text-sm">
         
     | 
| 
         | 
|
| 1 | 
         
             
            from utils import TEMP_DIR, message_dict
         
     | 
| 2 | 
         
             
            import gradio as gr
         
     | 
| 3 | 
         
            +
            import templates.data_file as data_file, templates.sql_db as sql_db, templates.doc_db as doc_db, templates.graphql as graphql
         
     | 
| 4 | 
         | 
| 5 | 
         
             
            import os
         
     | 
| 6 | 
         
             
            from getpass import getpass
         
     | 
| 
         | 
|
| 76 | 
         
             
                    sql_db.demo.render()
         
     | 
| 77 | 
         
             
                with gr.Tab("Document (MongoDB) Database"):
         
     | 
| 78 | 
         
             
                    doc_db.demo.render()
         
     | 
| 79 | 
         
            +
                with gr.Tab("GraphQL API"):
         
     | 
| 80 | 
         
            +
                    graphql.demo.render()    
         
     | 
| 81 | 
         | 
| 82 | 
         
             
                footer = gr.HTML("""<!-- Footer -->
         
     | 
| 83 | 
         
             
                    <footer class="max-w-4xl mx-auto mt-12 text-center text-gray-500 text-sm">
         
     | 
    	
        data_sources/__init__.py
    CHANGED
    
    | 
         @@ -1,5 +1,6 @@ 
     | 
|
| 1 | 
         
             
            from .upload_file import process_data_upload
         
     | 
| 2 | 
         
             
            from .connect_sql_db import connect_sql_db
         
     | 
| 3 | 
         
             
            from .connect_doc_db import connect_doc_db
         
     | 
| 
         | 
|
| 4 | 
         | 
| 5 | 
         
            -
            __all__ = ["process_data_upload","connect_sql_db","connect_doc_db"]
         
     | 
| 
         | 
|
| 1 | 
         
             
            from .upload_file import process_data_upload
         
     | 
| 2 | 
         
             
            from .connect_sql_db import connect_sql_db
         
     | 
| 3 | 
         
             
            from .connect_doc_db import connect_doc_db
         
     | 
| 4 | 
         
            +
            from .connect_graphql import connect_graphql
         
     | 
| 5 | 
         | 
| 6 | 
         
            +
            __all__ = ["process_data_upload","connect_sql_db","connect_doc_db","connect_graphql"]
         
     | 
    	
        data_sources/connect_graphql.py
    ADDED
    
    | 
         @@ -0,0 +1,145 @@ 
     | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
| 
         | 
|
| 1 | 
         
            +
            import requests
         
     | 
| 2 | 
         
            +
            import os
         
     | 
| 3 | 
         
            +
            import json
         
     | 
| 4 | 
         
            +
            from utils import TEMP_DIR
         
     | 
| 5 | 
         
            +
             
     | 
| 6 | 
         
            +
            def connect_graphql(graphql_url, api_token, graphql_token_header, session_hash):
         
     | 
| 7 | 
         
            +
                try:
         
     | 
| 8 | 
         
            +
                    # Create the GraphQL Introspection Query
         
     | 
| 9 | 
         
            +
                    query = """
         
     | 
| 10 | 
         
            +
                            query IntrospectionQuery {
         
     | 
| 11 | 
         
            +
                                __schema {
         
     | 
| 12 | 
         
            +
                                queryType { name }
         
     | 
| 13 | 
         
            +
                                mutationType { name }
         
     | 
| 14 | 
         
            +
                                subscriptionType { name }
         
     | 
| 15 | 
         
            +
                                types {
         
     | 
| 16 | 
         
            +
                                    ...FullType
         
     | 
| 17 | 
         
            +
                                }
         
     | 
| 18 | 
         
            +
                                directives {
         
     | 
| 19 | 
         
            +
                                    name
         
     | 
| 20 | 
         
            +
                                    description
         
     | 
| 21 | 
         
            +
                                    locations
         
     | 
| 22 | 
         
            +
                                    args {
         
     | 
| 23 | 
         
            +
                                    ...InputValue
         
     | 
| 24 | 
         
            +
                                    }
         
     | 
| 25 | 
         
            +
                                }
         
     | 
| 26 | 
         
            +
                                }
         
     | 
| 27 | 
         
            +
                            }
         
     | 
| 28 | 
         
            +
                            fragment FullType on __Type {
         
     | 
| 29 | 
         
            +
                                kind
         
     | 
| 30 | 
         
            +
                                name
         
     | 
| 31 | 
         
            +
                                description
         
     | 
| 32 | 
         
            +
                                fields(includeDeprecated: true) {
         
     | 
| 33 | 
         
            +
                                name
         
     | 
| 34 | 
         
            +
                                description
         
     | 
| 35 | 
         
            +
                                args {
         
     | 
| 36 | 
         
            +
                                    ...InputValue
         
     | 
| 37 | 
         
            +
                                }
         
     | 
| 38 | 
         
            +
                                type {
         
     | 
| 39 | 
         
            +
                                    ...TypeRef
         
     | 
| 40 | 
         
            +
                                }
         
     | 
| 41 | 
         
            +
                                isDeprecated
         
     | 
| 42 | 
         
            +
                                deprecationReason
         
     | 
| 43 | 
         
            +
                                }
         
     | 
| 44 | 
         
            +
                                inputFields {
         
     | 
| 45 | 
         
            +
                                ...InputValue
         
     | 
| 46 | 
         
            +
                                }
         
     | 
| 47 | 
         
            +
                                interfaces {
         
     | 
| 48 | 
         
            +
                                ...TypeRef
         
     | 
| 49 | 
         
            +
                                }
         
     | 
| 50 | 
         
            +
                                enumValues(includeDeprecated: true) {
         
     | 
| 51 | 
         
            +
                                name
         
     | 
| 52 | 
         
            +
                                description
         
     | 
| 53 | 
         
            +
                                isDeprecated
         
     | 
| 54 | 
         
            +
                                deprecationReason
         
     | 
| 55 | 
         
            +
                                }
         
     | 
| 56 | 
         
            +
                                possibleTypes {
         
     | 
| 57 | 
         
            +
                                ...TypeRef
         
     | 
| 58 | 
         
            +
                                }
         
     | 
| 59 | 
         
            +
                            }
         
     | 
| 60 | 
         
            +
                            fragment InputValue on __InputValue {
         
     | 
| 61 | 
         
            +
                                name
         
     | 
| 62 | 
         
            +
                                description
         
     | 
| 63 | 
         
            +
                                type { ...TypeRef }
         
     | 
| 64 | 
         
            +
                                defaultValue
         
     | 
| 65 | 
         
            +
                            }
         
     | 
| 66 | 
         
            +
                            fragment TypeRef on __Type {
         
     | 
| 67 | 
         
            +
                                kind
         
     | 
| 68 | 
         
            +
                                name
         
     | 
| 69 | 
         
            +
                                ofType {
         
     | 
| 70 | 
         
            +
                                kind
         
     | 
| 71 | 
         
            +
                                name
         
     | 
| 72 | 
         
            +
                                ofType {
         
     | 
| 73 | 
         
            +
                                    kind
         
     | 
| 74 | 
         
            +
                                    name
         
     | 
| 75 | 
         
            +
                                    ofType {
         
     | 
| 76 | 
         
            +
                                    kind
         
     | 
| 77 | 
         
            +
                                    name
         
     | 
| 78 | 
         
            +
                                    ofType {
         
     | 
| 79 | 
         
            +
                                        kind
         
     | 
| 80 | 
         
            +
                                        name
         
     | 
| 81 | 
         
            +
                                        ofType {
         
     | 
| 82 | 
         
            +
                                        kind
         
     | 
| 83 | 
         
            +
                                        name
         
     | 
| 84 | 
         
            +
                                        ofType {
         
     | 
| 85 | 
         
            +
                                            kind
         
     | 
| 86 | 
         
            +
                                            name
         
     | 
| 87 | 
         
            +
                                            ofType {
         
     | 
| 88 | 
         
            +
                                            kind
         
     | 
| 89 | 
         
            +
                                            name
         
     | 
| 90 | 
         
            +
                                            }
         
     | 
| 91 | 
         
            +
                                        }
         
     | 
| 92 | 
         
            +
                                        }
         
     | 
| 93 | 
         
            +
                                    }
         
     | 
| 94 | 
         
            +
                                    }
         
     | 
| 95 | 
         
            +
                                }
         
     | 
| 96 | 
         
            +
                                }
         
     | 
| 97 | 
         
            +
                            }
         
     | 
| 98 | 
         
            +
                            """
         
     | 
| 99 | 
         
            +
                    print("Connecting to GraphQL Endpoint")
         
     | 
| 100 | 
         
            +
                
         
     | 
| 101 | 
         
            +
                    # Access a database
         
     | 
| 102 | 
         
            +
                    headers = {"Content-Type": "application/json"}
         
     | 
| 103 | 
         
            +
                    if graphql_token_header and api_token:
         
     | 
| 104 | 
         
            +
                        headers[graphql_token_header] = api_token
         
     | 
| 105 | 
         
            +
                    response = requests.post(graphql_url, headers=headers, json={"query": query})
         
     | 
| 106 | 
         
            +
                    response.raise_for_status()
         
     | 
| 107 | 
         
            +
             
     | 
| 108 | 
         
            +
                    introspection_result = response.json()
         
     | 
| 109 | 
         
            +
             
     | 
| 110 | 
         
            +
                    client_schema = introspection_result["data"]["__schema"]
         
     | 
| 111 | 
         
            +
             
     | 
| 112 | 
         
            +
                    #Generate the list of types
         
     | 
| 113 | 
         
            +
                    type_names_query = """
         
     | 
| 114 | 
         
            +
                            query IntrospectionQuery {
         
     | 
| 115 | 
         
            +
                                __schema {
         
     | 
| 116 | 
         
            +
                                    types {
         
     | 
| 117 | 
         
            +
                                        name
         
     | 
| 118 | 
         
            +
                                    }
         
     | 
| 119 | 
         
            +
                                }
         
     | 
| 120 | 
         
            +
                            }
         
     | 
| 121 | 
         
            +
                        """
         
     | 
| 122 | 
         
            +
                    types_response = requests.post(graphql_url, headers=headers, json={"query": type_names_query})
         
     | 
| 123 | 
         
            +
             
     | 
| 124 | 
         
            +
                    types_response_results =types_response.json()
         
     | 
| 125 | 
         
            +
             
     | 
| 126 | 
         
            +
                    types_names = types_response_results["data"]
         
     | 
| 127 | 
         
            +
             
     | 
| 128 | 
         
            +
                    type_names = []
         
     | 
| 129 | 
         
            +
                    for name in types_names["__schema"]["types"]:
         
     | 
| 130 | 
         
            +
                        type_names.append(name["name"])
         
     | 
| 131 | 
         
            +
             
     | 
| 132 | 
         
            +
                    session_path = 'graphql'
         
     | 
| 133 | 
         
            +
             
     | 
| 134 | 
         
            +
                    dir_path = TEMP_DIR / str(session_hash) / str(session_path)
         
     | 
| 135 | 
         
            +
                    os.makedirs(dir_path, exist_ok=True)
         
     | 
| 136 | 
         
            +
             
     | 
| 137 | 
         
            +
                    with open(f'{dir_path}/schema.json', 'w') as fp:
         
     | 
| 138 | 
         
            +
                        json.dump(client_schema, fp, indent=2)
         
     | 
| 139 | 
         
            +
             
     | 
| 140 | 
         
            +
                    return ["success","<p style='color:green;text-align:center;font-size:18px;'>GraphQL API connected successful</p>", type_names]
         
     | 
| 141 | 
         
            +
                except Exception as e:
         
     | 
| 142 | 
         
            +
                    print("GraphQL CONNECTION ERROR")
         
     | 
| 143 | 
         
            +
                    print(e)
         
     | 
| 144 | 
         
            +
                    return ["error",f"<p style='color:red;text-align:center;font-size:18px;font-weight:bold;'>ERROR: {e}</p>"]
         
     | 
| 145 | 
         
            +
                    
         
     | 
    	
        functions/__init__.py
    CHANGED
    
    | 
         @@ -1,9 +1,9 @@ 
     | 
|
| 1 | 
         
            -
            from .query_functions import SQLiteQuery, sqlite_query_func,  
     | 
| 2 | 
         
             
            from .chart_functions import table_generation_func, scatter_chart_generation_func, \
         
     | 
| 3 | 
         
             
            line_chart_generation_func, bar_chart_generation_func, pie_chart_generation_func, histogram_generation_func, scatter_chart_fig
         
     | 
| 4 | 
         
            -
            from .chat_functions import sql_example_question_generator, example_question_generator, doc_db_example_question_generator, chatbot_with_fc, sql_chatbot_with_fc, doc_db_chatbot_with_fc
         
     | 
| 5 | 
         
             
            from .stat_functions import regression_func
         
     | 
| 6 | 
         | 
| 7 | 
         
            -
            __all__ = ["SQLiteQuery","sqlite_query_func","sql_query_func","doc_db_query_func","table_generation_func","scatter_chart_generation_func",
         
     | 
| 8 | 
         
             
                       "line_chart_generation_func","bar_chart_generation_func","regression_func", "pie_chart_generation_func", "histogram_generation_func",
         
     | 
| 9 | 
         
            -
                       "scatter_chart_fig","doc_db_example_question_generator","sql_example_question_generator","example_question_generator","chatbot_with_fc","sql_chatbot_with_fc","doc_db_chatbot_with_fc"]
         
     | 
| 
         | 
|
| 1 | 
         
            +
            from .query_functions import SQLiteQuery, sqlite_query_func, sql_query_func, doc_db_query_func, graphql_query_func, graphql_schema_query, graphql_csv_query
         
     | 
| 2 | 
         
             
            from .chart_functions import table_generation_func, scatter_chart_generation_func, \
         
     | 
| 3 | 
         
             
            line_chart_generation_func, bar_chart_generation_func, pie_chart_generation_func, histogram_generation_func, scatter_chart_fig
         
     | 
| 4 | 
         
            +
            from .chat_functions import sql_example_question_generator, example_question_generator, doc_db_example_question_generator, chatbot_with_fc, sql_chatbot_with_fc, doc_db_chatbot_with_fc, graphql_chatbot_with_fc, graphql_example_question_generator
         
     | 
| 5 | 
         
             
            from .stat_functions import regression_func
         
     | 
| 6 | 
         | 
| 7 | 
         
            +
            __all__ = ["SQLiteQuery","sqlite_query_func","sql_query_func","doc_db_query_func","graphql_query_func","graphql_schema_query","graphql_csv_query","table_generation_func","scatter_chart_generation_func",
         
     | 
| 8 | 
         
             
                       "line_chart_generation_func","bar_chart_generation_func","regression_func", "pie_chart_generation_func", "histogram_generation_func",
         
     | 
| 9 | 
         
            +
                       "scatter_chart_fig","doc_db_example_question_generator","sql_example_question_generator","example_question_generator","chatbot_with_fc","sql_chatbot_with_fc","doc_db_chatbot_with_fc","graphql_chatbot_with_fc","graphql_example_question_generator"]
         
     | 
    	
        functions/chat_functions.py
    CHANGED
    
    | 
         @@ -78,6 +78,25 @@ def doc_db_example_question_generator(session_hash, db_collections, db_name, db_ 
     | 
|
| 78 | 
         | 
| 79 | 
         
             
                return example_response["replies"][0].text
         
     | 
| 80 | 
         | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 81 | 
         
             
            def chatbot_with_fc(message, history, session_hash):
         
     | 
| 82 | 
         
             
                from functions import sqlite_query_func, table_generation_func, regression_func, scatter_chart_generation_func, \
         
     | 
| 83 | 
         
             
                    line_chart_generation_func,bar_chart_generation_func,pie_chart_generation_func,histogram_generation_func
         
     | 
| 
         @@ -218,15 +237,15 @@ def doc_db_chatbot_with_fc(message, history, session_hash, db_connection_string, 
     | 
|
| 218 | 
         
             
                else:
         
     | 
| 219 | 
         
             
                    messages = [
         
     | 
| 220 | 
         
             
                        ChatMessage.from_system(
         
     | 
| 221 | 
         
            -
                            f"""You are a helpful and knowledgeable agent who has access to  
     | 
| 222 | 
         
             
                            The schema of these collections is: {db_schema}.
         
     | 
| 223 | 
         
            -
                            You also have access to a function, called table_generation_func, that can take a query.csv file generated from our  
     | 
| 224 | 
         
            -
                            You also have access to a scatter plot function, called scatter_chart_generation_func, that can take a query.csv file generated from our  
     | 
| 225 | 
         
            -
                            You also have access to a line chart function, called line_chart_generation_func, that can take a query.csv file generated from our  
     | 
| 226 | 
         
            -
                            You also have access to a bar graph function, called line_chart_generation_func, that can take a query.csv file generated from our  
     | 
| 227 | 
         
            -
                            You also have access to a pie chart function, called pie_chart_generation_func, that can take a query.csv file generated from our  
     | 
| 228 | 
         
            -
                            You also have access to a histogram function, called histogram_generation_func, that can take a query.csv file generated from our  
     | 
| 229 | 
         
            -
                            You also have access to a linear regression function, called regression_func, that can take a query.csv file generated from our  
     | 
| 230 | 
         
             
                            Could you please always display the generated charts, tables, and visualizations as part of your output?"""
         
     | 
| 231 | 
         
             
                        )
         
     | 
| 232 | 
         
             
                    ]
         
     | 
| 
         @@ -259,4 +278,63 @@ def doc_db_chatbot_with_fc(message, history, session_hash, db_connection_string, 
     | 
|
| 259 | 
         
             
                        message_dict[session_hash]['doc_db'].append(response["replies"][0])
         
     | 
| 260 | 
         
             
                        break
         
     | 
| 261 | 
         | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 262 | 
         
             
                return response["replies"][0].text
         
     | 
| 
         | 
|
| 78 | 
         | 
| 79 | 
         
             
                return example_response["replies"][0].text
         
     | 
| 80 | 
         | 
| 81 | 
         
            +
            def graphql_example_question_generator(session_hash, graphql_endpoint, graphql_types):
         
     | 
| 82 | 
         
            +
                example_response = None
         
     | 
| 83 | 
         
            +
                example_messages = [
         
     | 
| 84 | 
         
            +
                    ChatMessage.from_system(
         
     | 
| 85 | 
         
            +
                        f"You are a helpful and knowledgeable agent who has access to an GraphQL API endpoint called {graphql_endpoint}."
         
     | 
| 86 | 
         
            +
                    )
         
     | 
| 87 | 
         
            +
                ]
         
     | 
| 88 | 
         
            +
             
     | 
| 89 | 
         
            +
                example_messages.append(ChatMessage.from_user(text=f"""We have a GraphQL API endpoint with the following types: {graphql_types}.
         
     | 
| 90 | 
         
            +
                                                              We also have an AI agent with access to the same GraphQL API endpoint that will be performing data analysis.
         
     | 
| 91 | 
         
            +
                                                              Please return an array of seven strings, each one being a question for our data analysis agent
         
     | 
| 92 | 
         
            +
                                                              that we can suggest that you believe will be insightful or helpful to a data analysis looking for
         
     | 
| 93 | 
         
            +
                                                              data insights. Return nothing more than the array of questions because I need that specific data structure
         
     | 
| 94 | 
         
            +
                                                              to process your response. No other response type or data structure will work."""))
         
     | 
| 95 | 
         
            +
             
     | 
| 96 | 
         
            +
                example_response = chat_generator.run(messages=example_messages)
         
     | 
| 97 | 
         
            +
             
     | 
| 98 | 
         
            +
                return example_response["replies"][0].text
         
     | 
| 99 | 
         
            +
             
     | 
| 100 | 
         
             
            def chatbot_with_fc(message, history, session_hash):
         
     | 
| 101 | 
         
             
                from functions import sqlite_query_func, table_generation_func, regression_func, scatter_chart_generation_func, \
         
     | 
| 102 | 
         
             
                    line_chart_generation_func,bar_chart_generation_func,pie_chart_generation_func,histogram_generation_func
         
     | 
| 
         | 
|
| 237 | 
         
             
                else:
         
     | 
| 238 | 
         
             
                    messages = [
         
     | 
| 239 | 
         
             
                        ChatMessage.from_system(
         
     | 
| 240 | 
         
            +
                            f"""You are a helpful and knowledgeable agent who has access to a NoSQL MongoDB Document database which has a series of collections called {db_collections}.
         
     | 
| 241 | 
         
             
                            The schema of these collections is: {db_schema}.
         
     | 
| 242 | 
         
            +
                            You also have access to a function, called table_generation_func, that can take a query.csv file generated from our MongoDB query and returns an iframe that we should display in our chat window.
         
     | 
| 243 | 
         
            +
                            You also have access to a scatter plot function, called scatter_chart_generation_func, that can take a query.csv file generated from our MongoDB query and uses plotly dictionaries to generate a scatter plot and returns an iframe that we should display in our chat window.
         
     | 
| 244 | 
         
            +
                            You also have access to a line chart function, called line_chart_generation_func, that can take a query.csv file generated from our MongoDB query and uses plotly dictionaries to generate a line chart and returns an iframe that we should display in our chat window.
         
     | 
| 245 | 
         
            +
                            You also have access to a bar graph function, called line_chart_generation_func, that can take a query.csv file generated from our MongoDB query and uses plotly dictionaries to generate a bar graph and returns an iframe that we should display in our chat window.
         
     | 
| 246 | 
         
            +
                            You also have access to a pie chart function, called pie_chart_generation_func, that can take a query.csv file generated from our MongoDB query and uses plotly dictionaries to generate a pie chart and returns an iframe that we should display in our chat window.
         
     | 
| 247 | 
         
            +
                            You also have access to a histogram function, called histogram_generation_func, that can take a query.csv file generated from our MongoDB query and uses plotly dictionaries to generate a histogram and returns an iframe that we should display in our chat window.
         
     | 
| 248 | 
         
            +
                            You also have access to a linear regression function, called regression_func, that can take a query.csv file generated from our MongoDB query and a list of column names for our independent and dependent variables and return a regression data string and a regression chart which is returned as an iframe.
         
     | 
| 249 | 
         
             
                            Could you please always display the generated charts, tables, and visualizations as part of your output?"""
         
     | 
| 250 | 
         
             
                        )
         
     | 
| 251 | 
         
             
                    ]
         
     | 
| 
         | 
|
| 278 | 
         
             
                        message_dict[session_hash]['doc_db'].append(response["replies"][0])
         
     | 
| 279 | 
         
             
                        break
         
     | 
| 280 | 
         | 
| 281 | 
         
            +
                return response["replies"][0].text
         
     | 
| 282 | 
         
            +
             
     | 
| 283 | 
         
            +
            def graphql_chatbot_with_fc(message, history, session_hash, graphql_api_string, graphql_api_token, graphql_token_header, graphql_types):
         
     | 
| 284 | 
         
            +
                from functions import graphql_query_func, graphql_schema_query, graphql_csv_query, table_generation_func, regression_func, scatter_chart_generation_func, \
         
     | 
| 285 | 
         
            +
                    line_chart_generation_func,bar_chart_generation_func,pie_chart_generation_func,histogram_generation_func
         
     | 
| 286 | 
         
            +
                import tools.tools as tools
         
     | 
| 287 | 
         
            +
                
         
     | 
| 288 | 
         
            +
                available_functions = {"graphql_query_func": graphql_query_func,"graphql_schema_query": graphql_schema_query,"graphql_csv_query": graphql_csv_query,"table_generation_func":table_generation_func,
         
     | 
| 289 | 
         
            +
                                       "line_chart_generation_func":line_chart_generation_func,"bar_chart_generation_func":bar_chart_generation_func,
         
     | 
| 290 | 
         
            +
                                       "scatter_chart_generation_func":scatter_chart_generation_func, "pie_chart_generation_func":pie_chart_generation_func,
         
     | 
| 291 | 
         
            +
                                       "histogram_generation_func":histogram_generation_func,
         
     | 
| 292 | 
         
            +
                                       "regression_func":regression_func }
         
     | 
| 293 | 
         
            +
             
     | 
| 294 | 
         
            +
                if message_dict[session_hash]['graphql'] != None:
         
     | 
| 295 | 
         
            +
                    message_dict[session_hash]['graphql'].append(ChatMessage.from_user(message))
         
     | 
| 296 | 
         
            +
                else:
         
     | 
| 297 | 
         
            +
                    messages = [
         
     | 
| 298 | 
         
            +
                        ChatMessage.from_system(
         
     | 
| 299 | 
         
            +
                            f"""You are a helpful and knowledgeable agent who has access to a GraphQL API which has the following types: {graphql_types}.
         
     | 
| 300 | 
         
            +
                            We have also saved a schema.json file that contains the entire introspection query that we can use to find out more about each type before making a query.
         
     | 
| 301 | 
         
            +
                            You also have access to a function, called table_generation_func, that can take a query.csv file generated from our GraphQL API query and returns an iframe that we should display in our chat window.
         
     | 
| 302 | 
         
            +
                            You also have access to a scatter plot function, called scatter_chart_generation_func, that can take a query.csv file generated from our GraphQL API query and uses plotly dictionaries to generate a scatter plot and returns an iframe that we should display in our chat window.
         
     | 
| 303 | 
         
            +
                            You also have access to a line chart function, called line_chart_generation_func, that can take a query.csv file generated from our GraphQL API query and uses plotly dictionaries to generate a line chart and returns an iframe that we should display in our chat window.
         
     | 
| 304 | 
         
            +
                            You also have access to a bar graph function, called line_chart_generation_func, that can take a query.csv file generated from our GraphQL API query and uses plotly dictionaries to generate a bar graph and returns an iframe that we should display in our chat window.
         
     | 
| 305 | 
         
            +
                            You also have access to a pie chart function, called pie_chart_generation_func, that can take a query.csv file generated from our GraphQL API query and uses plotly dictionaries to generate a pie chart and returns an iframe that we should display in our chat window.
         
     | 
| 306 | 
         
            +
                            You also have access to a histogram function, called histogram_generation_func, that can take a query.csv file generated from our GraphQL API query and uses plotly dictionaries to generate a histogram and returns an iframe that we should display in our chat window.
         
     | 
| 307 | 
         
            +
                            You also have access to a linear regression function, called regression_func, that can take a query.csv file generated from our GraphQL API query and a list of column names for our independent and dependent variables and return a regression data string and a regression chart which is returned as an iframe.
         
     | 
| 308 | 
         
            +
                            Could you please always display the generated charts, tables, and visualizations as part of your output?"""
         
     | 
| 309 | 
         
            +
                        )
         
     | 
| 310 | 
         
            +
                    ]
         
     | 
| 311 | 
         
            +
                    messages.append(ChatMessage.from_user(message))
         
     | 
| 312 | 
         
            +
                    message_dict[session_hash]['graphql'] = messages
         
     | 
| 313 | 
         
            +
             
     | 
| 314 | 
         
            +
                response = chat_generator.run(messages=message_dict[session_hash]['graphql'], generation_kwargs={"tools": tools.graphql_tools_call(graphql_types)})
         
     | 
| 315 | 
         
            +
             
     | 
| 316 | 
         
            +
                while True:
         
     | 
| 317 | 
         
            +
                    # if OpenAI response is a tool call
         
     | 
| 318 | 
         
            +
                    if response and response["replies"][0].meta["finish_reason"] == "tool_calls" or response["replies"][0].tool_calls:
         
     | 
| 319 | 
         
            +
                        function_calls = response["replies"][0].tool_calls
         
     | 
| 320 | 
         
            +
                        for function_call in function_calls:
         
     | 
| 321 | 
         
            +
                            message_dict[session_hash]['graphql'].append(ChatMessage.from_assistant(tool_calls=[function_call]))
         
     | 
| 322 | 
         
            +
                            ## Parse function calling information
         
     | 
| 323 | 
         
            +
                            function_name = function_call.tool_name
         
     | 
| 324 | 
         
            +
                            function_args = function_call.arguments
         
     | 
| 325 | 
         
            +
             
     | 
| 326 | 
         
            +
                            ## Find the corresponding function and call it with the given arguments
         
     | 
| 327 | 
         
            +
                            function_to_call = available_functions[function_name]
         
     | 
| 328 | 
         
            +
                            function_response = function_to_call(**function_args, session_hash=session_hash, graphql_api_string=graphql_api_string, 
         
     | 
| 329 | 
         
            +
                                                                graphql_api_token=graphql_api_token, graphql_token_header=graphql_token_header, session_folder='graphql')
         
     | 
| 330 | 
         
            +
                            print(function_name)
         
     | 
| 331 | 
         
            +
                            ## Append function response to the messages list using `ChatMessage.from_tool`
         
     | 
| 332 | 
         
            +
                            message_dict[session_hash]['graphql'].append(ChatMessage.from_tool(tool_result=function_response['reply'], origin=function_call))
         
     | 
| 333 | 
         
            +
                            response = chat_generator.run(messages=message_dict[session_hash]['graphql'], generation_kwargs={"tools": tools.graphql_tools_call(graphql_types)})
         
     | 
| 334 | 
         
            +
             
     | 
| 335 | 
         
            +
                    # Regular Conversation
         
     | 
| 336 | 
         
            +
                    else:
         
     | 
| 337 | 
         
            +
                        message_dict[session_hash]['graphql'].append(response["replies"][0])
         
     | 
| 338 | 
         
            +
                        break
         
     | 
| 339 | 
         
            +
                    
         
     | 
| 340 | 
         
             
                return response["replies"][0].text
         
     | 
    	
        functions/query_functions.py
    CHANGED
    
    | 
         @@ -2,6 +2,7 @@ from typing import List 
     | 
|
| 2 | 
         
             
            from typing import AnyStr
         
     | 
| 3 | 
         
             
            from haystack import component
         
     | 
| 4 | 
         
             
            import pandas as pd
         
     | 
| 
         | 
|
| 5 | 
         
             
            pd.set_option('display.max_rows', None)
         
     | 
| 6 | 
         
             
            pd.set_option('display.max_columns', None)
         
     | 
| 7 | 
         
             
            pd.set_option('display.width', None)
         
     | 
| 
         @@ -10,6 +11,8 @@ import sqlite3 
     | 
|
| 10 | 
         
             
            import psycopg2
         
     | 
| 11 | 
         
             
            from pymongo import MongoClient
         
     | 
| 12 | 
         
             
            import pymongoarrow.monkey
         
     | 
| 
         | 
|
| 
         | 
|
| 13 | 
         
             
            from utils import TEMP_DIR
         
     | 
| 14 | 
         
             
            import ast
         
     | 
| 15 | 
         | 
| 
         @@ -164,4 +167,103 @@ def doc_db_query_func(aggregation_pipeline: List[str], db_collection: AnyStr, se 
     | 
|
| 164 | 
         
             
                          You should probably try again.
         
     | 
| 165 | 
         
             
                          """
         
     | 
| 166 | 
         
             
                  print(reply)
         
     | 
| 167 | 
         
            -
                  return {"reply": reply}
         
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
| 
         | 
|
| 2 | 
         
             
            from typing import AnyStr
         
     | 
| 3 | 
         
             
            from haystack import component
         
     | 
| 4 | 
         
             
            import pandas as pd
         
     | 
| 5 | 
         
            +
            from pandasql import sqldf
         
     | 
| 6 | 
         
             
            pd.set_option('display.max_rows', None)
         
     | 
| 7 | 
         
             
            pd.set_option('display.max_columns', None)
         
     | 
| 8 | 
         
             
            pd.set_option('display.width', None)
         
     | 
| 
         | 
|
| 11 | 
         
             
            import psycopg2
         
     | 
| 12 | 
         
             
            from pymongo import MongoClient
         
     | 
| 13 | 
         
             
            import pymongoarrow.monkey
         
     | 
| 14 | 
         
            +
            import json
         
     | 
| 15 | 
         
            +
            import pluck
         
     | 
| 16 | 
         
             
            from utils import TEMP_DIR
         
     | 
| 17 | 
         
             
            import ast
         
     | 
| 18 | 
         | 
| 
         | 
|
| 167 | 
         
             
                          You should probably try again.
         
     | 
| 168 | 
         
             
                          """
         
     | 
| 169 | 
         
             
                  print(reply)
         
     | 
| 170 | 
         
            +
                  return {"reply": reply}
         
     | 
| 171 | 
         
            +
                
         
     | 
| 172 | 
         
            +
            @component
         
     | 
| 173 | 
         
            +
            class GraphQLQuery:
         
     | 
| 174 | 
         
            +
             
     | 
| 175 | 
         
            +
                def __init__(self):
         
     | 
| 176 | 
         
            +
             
     | 
| 177 | 
         
            +
                  self.connection = pluck
         
     | 
| 178 | 
         
            +
             
     | 
| 179 | 
         
            +
                @component.output_types(results=List[str], queries=List[str])
         
     | 
| 180 | 
         
            +
                def run(self, graphql_query, graphql_api_string, graphql_api_token, graphql_token_header, session_hash):
         
     | 
| 181 | 
         
            +
                    print("ATTEMPTING TO RUN GRAPHQL QUERY")
         
     | 
| 182 | 
         
            +
                    dir_path = TEMP_DIR / str(session_hash)
         
     | 
| 183 | 
         
            +
                    results = []
         
     | 
| 184 | 
         
            +
             
     | 
| 185 | 
         
            +
                    headers = {"Content-Type": "application/json"}
         
     | 
| 186 | 
         
            +
                    if graphql_token_header and graphql_api_token:
         
     | 
| 187 | 
         
            +
                      headers[graphql_token_header] = graphql_api_token
         
     | 
| 188 | 
         
            +
             
     | 
| 189 | 
         
            +
                    print(graphql_query)
         
     | 
| 190 | 
         
            +
             
     | 
| 191 | 
         
            +
                    response = self.connection.execute(url=graphql_api_string, headers=headers, query=graphql_query, column_names="short")
         
     | 
| 192 | 
         
            +
             
     | 
| 193 | 
         
            +
                    if response.errors:
         
     | 
| 194 | 
         
            +
                       raise ValueError(response.errors)
         
     | 
| 195 | 
         
            +
                    elif response.data:
         
     | 
| 196 | 
         
            +
                      print("DATA FRAME COMPLETE")
         
     | 
| 197 | 
         
            +
                      print(response)
         
     | 
| 198 | 
         
            +
                      response_frame = response.frames['default']
         
     | 
| 199 | 
         
            +
                      print("RESPONSE FRAME")
         
     | 
| 200 | 
         
            +
                      #print(response_frame)
         
     | 
| 201 | 
         
            +
             
     | 
| 202 | 
         
            +
                      response_frame.to_csv(f'{dir_path}/graphql/query.csv', index=False)
         
     | 
| 203 | 
         
            +
                      print("CSV COMPLETE")
         
     | 
| 204 | 
         
            +
                      results.append(f"{response_frame}") 
         
     | 
| 205 | 
         
            +
                      return {"results": results, "queries": graphql_query}
         
     | 
| 206 | 
         
            +
                
         
     | 
| 207 | 
         
            +
             
     | 
| 208 | 
         
            +
             
     | 
| 209 | 
         
            +
            def graphql_query_func(graphql_query: AnyStr, session_hash, graphql_api_string, graphql_api_token, graphql_token_header, **kwargs):
         
     | 
| 210 | 
         
            +
                graphql_object = GraphQLQuery()
         
     | 
| 211 | 
         
            +
                try:
         
     | 
| 212 | 
         
            +
                  result = graphql_object.run(graphql_query, graphql_api_string, graphql_api_token, graphql_token_header, session_hash)
         
     | 
| 213 | 
         
            +
                  print("RESULT")
         
     | 
| 214 | 
         
            +
                  if len(result["results"][0]) > 1000:
         
     | 
| 215 | 
         
            +
                    print("QUERY TOO LARGE")
         
     | 
| 216 | 
         
            +
                    return {"reply": "query result too large to be processed by llm, the query results are in our query.csv file. If you need to display the results directly, perhaps use the table_generation_func function."}
         
     | 
| 217 | 
         
            +
                  else:   
         
     | 
| 218 | 
         
            +
                    return {"reply": result["results"][0]}
         
     | 
| 219 | 
         
            +
             
     | 
| 220 | 
         
            +
                except Exception as e:
         
     | 
| 221 | 
         
            +
                  reply = f"""There was an error running the GraphQL Query = {graphql_query}
         
     | 
| 222 | 
         
            +
                          The error is {e},
         
     | 
| 223 | 
         
            +
                          You should probably try again.
         
     | 
| 224 | 
         
            +
                          """
         
     | 
| 225 | 
         
            +
                  print(reply)
         
     | 
| 226 | 
         
            +
                  return {"reply": reply}
         
     | 
| 227 | 
         
            +
                
         
     | 
| 228 | 
         
            +
            def graphql_schema_query(graphql_type: AnyStr, session_hash, **kwargs):
         
     | 
| 229 | 
         
            +
                dir_path = TEMP_DIR / str(session_hash)
         
     | 
| 230 | 
         
            +
                try:
         
     | 
| 231 | 
         
            +
                  with open(f'{dir_path}/graphql/schema.json', 'r') as file:
         
     | 
| 232 | 
         
            +
                    data = json.load(file)
         
     | 
| 233 | 
         
            +
             
     | 
| 234 | 
         
            +
                  types_list = data["types"]
         
     | 
| 235 | 
         
            +
                  result = list(filter(lambda item: item["name"] == graphql_type, types_list))
         
     | 
| 236 | 
         
            +
             
     | 
| 237 | 
         
            +
                  print("SCHEMA RESULT")
         
     | 
| 238 | 
         
            +
                  print(graphql_type)
         
     | 
| 239 | 
         
            +
                  print(str(result))
         
     | 
| 240 | 
         
            +
             
     | 
| 241 | 
         
            +
                  return {"reply": str(result)}
         
     | 
| 242 | 
         
            +
             
     | 
| 243 | 
         
            +
                except Exception as e:
         
     | 
| 244 | 
         
            +
                  reply = f"""There was an error querying our schema.json file with the type:{graphql_type}
         
     | 
| 245 | 
         
            +
                          The error is {e},
         
     | 
| 246 | 
         
            +
                          You should probably try again.
         
     | 
| 247 | 
         
            +
                          """
         
     | 
| 248 | 
         
            +
                  print(reply)
         
     | 
| 249 | 
         
            +
                  return {"reply": reply}
         
     | 
| 250 | 
         
            +
             
     | 
| 251 | 
         
            +
            def graphql_csv_query(csv_query: AnyStr, session_hash, **kwargs):
         
     | 
| 252 | 
         
            +
                dir_path = TEMP_DIR / str(session_hash)
         
     | 
| 253 | 
         
            +
                try:
         
     | 
| 254 | 
         
            +
                  query = pd.read_csv(f'{dir_path}/graphql/query.csv')
         
     | 
| 255 | 
         
            +
                  query.Name = 'query'
         
     | 
| 256 | 
         
            +
                  print("GRAPHQL CSV QUERY")
         
     | 
| 257 | 
         
            +
                  queried_df = sqldf(csv_query, locals())
         
     | 
| 258 | 
         
            +
                  print(queried_df)
         
     | 
| 259 | 
         
            +
                  queried_df.to_csv(f'{dir_path}/graphql/query.csv', index=False)
         
     | 
| 260 | 
         
            +
             
     | 
| 261 | 
         
            +
                  return {"reply": "The new query results are in our query.csv file. If you need to display the results directly, perhaps use the table_generation_func function."}
         
     | 
| 262 | 
         
            +
             
     | 
| 263 | 
         
            +
                except Exception as e:
         
     | 
| 264 | 
         
            +
                  reply = f"""There was an error querying our query.csv file with the query:{csv_query}
         
     | 
| 265 | 
         
            +
                          The error is {e},
         
     | 
| 266 | 
         
            +
                          You should probably try again.
         
     | 
| 267 | 
         
            +
                          """
         
     | 
| 268 | 
         
            +
                  print(reply)
         
     | 
| 269 | 
         
            +
                  return {"reply": reply}   
         
     | 
    	
        requirements.txt
    CHANGED
    
    | 
         @@ -10,3 +10,5 @@ psycopg2-binary 
     | 
|
| 10 | 
         
             
            pymongo
         
     | 
| 11 | 
         
             
            pymongoarrow
         
     | 
| 12 | 
         
             
            pymongo_schema
         
     | 
| 
         | 
|
| 
         | 
| 
         | 
|
| 10 | 
         
             
            pymongo
         
     | 
| 11 | 
         
             
            pymongoarrow
         
     | 
| 12 | 
         
             
            pymongo_schema
         
     | 
| 13 | 
         
            +
            pandasql
         
     | 
| 14 | 
         
            +
            pluck
         
     | 
    	
        templates/doc_db.py
    CHANGED
    
    | 
         @@ -17,7 +17,7 @@ with gr.Blocks() as demo: 
     | 
|
| 17 | 
         
             
                                     <p style="font-weight:bold;">Notice: the way this system is designed, no login information is retained and credentials are passed as session variables until the user leaves or 
         
     | 
| 18 | 
         
             
                                      refreshes the page in which they disappear. They are never saved to any files. I also make use of the PyMongoArrow aggregate_pandas_all function to apply pipelines,
         
     | 
| 19 | 
         
             
                                      which can't delete, drop, or add database lines to avoid unhappy accidents or glitches.
         
     | 
| 20 | 
         
            -
                                      That being said, it's probably  
     | 
| 21 | 
         
             
                                      This should be for demonstration purposes.</p>
         
     | 
| 22 | 
         
             
                                      <p>Contact me if this is something you would like built in your organization, on your infrastructure, and with the requisite privacy and control a production
         
     | 
| 23 | 
         
             
                                      database analytics tool requires.</p>
         
     | 
| 
         @@ -38,7 +38,7 @@ with gr.Blocks() as demo: 
     | 
|
| 38 | 
         
             
                submit.click(fn=hide_info, outputs=description)
         
     | 
| 39 | 
         | 
| 40 | 
         
             
                @gr.render(inputs=[connection_string,connection_user,connection_password,doc_db_name], triggers=[submit.click])
         
     | 
| 41 | 
         
            -
                def  
     | 
| 42 | 
         
             
                    if request.session_hash not in message_dict:
         
     | 
| 43 | 
         
             
                        message_dict[request.session_hash] = {}
         
     | 
| 44 | 
         
             
                    message_dict[request.session_hash]['doc_db'] = None
         
     | 
| 
         @@ -78,7 +78,7 @@ with gr.Blocks() as demo: 
     | 
|
| 78 | 
         
             
                            db_name = gr.Textbox(visible=False, value=doc_db_name)
         
     | 
| 79 | 
         
             
                            db_collections = gr.Textbox(value=process_message[2], interactive=False, label="DB Collections")
         
     | 
| 80 | 
         
             
                            db_schema = gr.Textbox(visible=False, value=process_message[3])
         
     | 
| 81 | 
         
            -
                            bot = gr.Chatbot(type='messages', label=" 
     | 
| 82 | 
         
             
                            chat = gr.ChatInterface(
         
     | 
| 83 | 
         
             
                                                fn=doc_db_chatbot_with_fc,
         
     | 
| 84 | 
         
             
                                                type='messages',
         
     | 
| 
         | 
|
| 17 | 
         
             
                                     <p style="font-weight:bold;">Notice: the way this system is designed, no login information is retained and credentials are passed as session variables until the user leaves or 
         
     | 
| 18 | 
         
             
                                      refreshes the page in which they disappear. They are never saved to any files. I also make use of the PyMongoArrow aggregate_pandas_all function to apply pipelines,
         
     | 
| 19 | 
         
             
                                      which can't delete, drop, or add database lines to avoid unhappy accidents or glitches.
         
     | 
| 20 | 
         
            +
                                      That being said, it's probably best to use caution when connecting to a production database to a strange AI tool with an unfamiliar author. 
         
     | 
| 21 | 
         
             
                                      This should be for demonstration purposes.</p>
         
     | 
| 22 | 
         
             
                                      <p>Contact me if this is something you would like built in your organization, on your infrastructure, and with the requisite privacy and control a production
         
     | 
| 23 | 
         
             
                                      database analytics tool requires.</p>
         
     | 
| 
         | 
|
| 38 | 
         
             
                submit.click(fn=hide_info, outputs=description)
         
     | 
| 39 | 
         | 
| 40 | 
         
             
                @gr.render(inputs=[connection_string,connection_user,connection_password,doc_db_name], triggers=[submit.click])
         
     | 
| 41 | 
         
            +
                def db_chat(request: gr.Request, connection_string=connection_string.value, connection_user=connection_user.value, connection_password=connection_password.value, doc_db_name=doc_db_name.value):
         
     | 
| 42 | 
         
             
                    if request.session_hash not in message_dict:
         
     | 
| 43 | 
         
             
                        message_dict[request.session_hash] = {}
         
     | 
| 44 | 
         
             
                    message_dict[request.session_hash]['doc_db'] = None
         
     | 
| 
         | 
|
| 78 | 
         
             
                            db_name = gr.Textbox(visible=False, value=doc_db_name)
         
     | 
| 79 | 
         
             
                            db_collections = gr.Textbox(value=process_message[2], interactive=False, label="DB Collections")
         
     | 
| 80 | 
         
             
                            db_schema = gr.Textbox(visible=False, value=process_message[3])
         
     | 
| 81 | 
         
            +
                            bot = gr.Chatbot(type='messages', label="DocDB Chat Window", render_markdown=True, sanitize_html=False, show_label=True, render=False, visible=True, elem_classes="chatbot")
         
     | 
| 82 | 
         
             
                            chat = gr.ChatInterface(
         
     | 
| 83 | 
         
             
                                                fn=doc_db_chatbot_with_fc,
         
     | 
| 84 | 
         
             
                                                type='messages',
         
     | 
    	
        templates/graphql.py
    ADDED
    
    | 
         @@ -0,0 +1,109 @@ 
     | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
| 
         | 
|
| 1 | 
         
            +
            import ast
         
     | 
| 2 | 
         
            +
            import gradio as gr
         
     | 
| 3 | 
         
            +
            from functions import graphql_example_question_generator, graphql_chatbot_with_fc
         
     | 
| 4 | 
         
            +
            from data_sources import connect_graphql
         
     | 
| 5 | 
         
            +
            from utils import message_dict
         
     | 
| 6 | 
         
            +
             
     | 
| 7 | 
         
            +
            import os
         
     | 
| 8 | 
         
            +
            from dotenv import load_dotenv
         
     | 
| 9 | 
         
            +
             
     | 
| 10 | 
         
            +
            load_dotenv()
         
     | 
| 11 | 
         
            +
             
     | 
| 12 | 
         
            +
            graphql_sample_endpoint = os.getenv("GRAPHQL_SAMPLE_ENDPOINT")
         
     | 
| 13 | 
         
            +
            graphql_sample_api_token = os.getenv("GRAPHQL_SAMPLE_API_TOKEN")
         
     | 
| 14 | 
         
            +
            graphql_sample_header_name = os.getenv("GRAPHQL_SAMPLE_HEADER_NAME")
         
     | 
| 15 | 
         
            +
             
     | 
| 16 | 
         
            +
            def hide_info():
         
     | 
| 17 | 
         
            +
                return gr.update(visible=False)
         
     | 
| 18 | 
         
            +
             
     | 
| 19 | 
         
            +
            with gr.Blocks() as demo:
         
     | 
| 20 | 
         
            +
                description = gr.HTML("""
         
     | 
| 21 | 
         
            +
                                <!-- Header -->
         
     | 
| 22 | 
         
            +
                                <div class="max-w-4xl mx-auto mb-12 text-center">
         
     | 
| 23 | 
         
            +
                                    <div class="bg-blue-50 border border-blue-200 rounded-lg max-w-2xl mx-auto">
         
     | 
| 24 | 
         
            +
                                     <p>This tool allows users to communicate with and query real time data from a GraphQL API endpoint using natural
         
     | 
| 25 | 
         
            +
                                      language and the above features.</p>
         
     | 
| 26 | 
         
            +
                                     <p style="font-weight:bold;">Notice: the way this system is designed, no login information is retained and credentials are passed as session variables until the user leaves or 
         
     | 
| 27 | 
         
            +
                                      refreshes the page in which they disappear. They are never saved to any files.</p>
         
     | 
| 28 | 
         
            +
                                      <p style="font-weight:bold;"> I don't include a function that allows the system to run mutations and I instruct the agent to not alter any data, but it could in theory be possible,
         
     | 
| 29 | 
         
            +
                                      although my testing wasn't able to get the system to alter or write to the api. I would be careful to make sure permissions are restricted for the
         
     | 
| 30 | 
         
            +
                                      api token being used.
         
     | 
| 31 | 
         
            +
                                      And of course, it's probably best to use caution when connecting to a strange AI tool with an unfamiliar author. 
         
     | 
| 32 | 
         
            +
                                      This should be for demonstration purposes.</p>
         
     | 
| 33 | 
         
            +
                                      <p>Contact me if this is something you would like built in your organization, on your infrastructure, and with the requisite privacy and control a production
         
     | 
| 34 | 
         
            +
                                      database analytics tool requires.</p>
         
     | 
| 35 | 
         
            +
                                    </div>
         
     | 
| 36 | 
         
            +
                                </div>
         
     | 
| 37 | 
         
            +
                                    """, elem_classes="description_component")
         
     | 
| 38 | 
         
            +
                
         
     | 
| 39 | 
         
            +
                status_message = gr.HTML(value='<p style="color:green;text-align:center;font-size:18px;">Please be patient while connecting as we need to generate '
         
     | 
| 40 | 
         
            +
                'and read a schema before connection can be successful. This process can take a few minutes.</p>', padding=False)
         
     | 
| 41 | 
         
            +
             
     | 
| 42 | 
         
            +
                graphql_url = gr.Textbox(label="GraphQL Endpoint URL", value=graphql_sample_endpoint)
         
     | 
| 43 | 
         
            +
                with gr.Row():
         
     | 
| 44 | 
         
            +
                    api_token_header_name = gr.Textbox(label="API Token Header Name", value=graphql_sample_header_name)
         
     | 
| 45 | 
         
            +
                    api_token = gr.Textbox(label="API Token", value=graphql_sample_api_token, type="password")
         
     | 
| 46 | 
         
            +
             
     | 
| 47 | 
         
            +
                submit = gr.Button(value="Submit")
         
     | 
| 48 | 
         
            +
                submit.click(fn=hide_info, outputs=description)
         
     | 
| 49 | 
         
            +
             
     | 
| 50 | 
         
            +
                @gr.render(inputs=[graphql_url,api_token,api_token_header_name], triggers=[submit.click])
         
     | 
| 51 | 
         
            +
                def api_chat(request: gr.Request, graphql_url=graphql_url.value, api_token=api_token.value, api_token_header_name=api_token_header_name.value):
         
     | 
| 52 | 
         
            +
                    if request.session_hash not in message_dict:
         
     | 
| 53 | 
         
            +
                        message_dict[request.session_hash] = {}
         
     | 
| 54 | 
         
            +
                    message_dict[request.session_hash]['graphql'] = None
         
     | 
| 55 | 
         
            +
                    if graphql_url:
         
     | 
| 56 | 
         
            +
                        print("GraphQL API")
         
     | 
| 57 | 
         
            +
                        process_message = process_graphql(graphql_url, api_token, api_token_header_name, request.session_hash)
         
     | 
| 58 | 
         
            +
                        gr.HTML(value=process_message[1], padding=False)
         
     | 
| 59 | 
         
            +
                        if process_message[0] == "success":
         
     | 
| 60 | 
         
            +
                            if "qdl-app-testing" in graphql_url:
         
     | 
| 61 | 
         
            +
                                example_questions = [
         
     | 
| 62 | 
         
            +
                                                        ["Describe the dataset"],
         
     | 
| 63 | 
         
            +
                                                        ["What is the total revenue for this shopify store?"],
         
     | 
| 64 | 
         
            +
                                                        ["What is the average duration from the fulfillment of an order to its delivery?"],
         
     | 
| 65 | 
         
            +
                                                        ["What is the total value of orders processed in the current month?"],
         
     | 
| 66 | 
         
            +
                                                        ["Which product has the highest number of variants in the inventory?"],
         
     | 
| 67 | 
         
            +
                                                        ["How many gift cards have been issued this year, and what is their total value?"],
         
     | 
| 68 | 
         
            +
                                                        ["How many active apps are currently installed on the store?"],
         
     | 
| 69 | 
         
            +
                                                        ["What is the total count of abandoned checkouts over the last month?"]
         
     | 
| 70 | 
         
            +
                                                    ]
         
     | 
| 71 | 
         
            +
                            else:
         
     | 
| 72 | 
         
            +
                                try:
         
     | 
| 73 | 
         
            +
                                    generated_examples = ast.literal_eval(graphql_example_question_generator(request.session_hash, graphql_url, process_message[2]))
         
     | 
| 74 | 
         
            +
                                    example_questions = [
         
     | 
| 75 | 
         
            +
                                                            ["Describe the dataset"]
         
     | 
| 76 | 
         
            +
                                                        ]
         
     | 
| 77 | 
         
            +
                                    for example in generated_examples:
         
     | 
| 78 | 
         
            +
                                        example_questions.append([example])
         
     | 
| 79 | 
         
            +
                                except Exception as e:
         
     | 
| 80 | 
         
            +
                                    print("GRAPHQL QUESTION GENERATION ERROR")
         
     | 
| 81 | 
         
            +
                                    print(e)
         
     | 
| 82 | 
         
            +
                                    example_questions = [
         
     | 
| 83 | 
         
            +
                                                        ["Describe the dataset"],
         
     | 
| 84 | 
         
            +
                                                        ["List the columns in the dataset"],
         
     | 
| 85 | 
         
            +
                                                        ["What could this data be used for?"],
         
     | 
| 86 | 
         
            +
                                                    ]
         
     | 
| 87 | 
         
            +
                            session_hash = gr.Textbox(visible=False, value=request.session_hash)
         
     | 
| 88 | 
         
            +
                            graphql_api_string = gr.Textbox(visible=False, value=graphql_url)
         
     | 
| 89 | 
         
            +
                            graphql_api_token = gr.Textbox(visible=False, value=api_token)
         
     | 
| 90 | 
         
            +
                            graphql_token_header = gr.Textbox(visible=False, value=api_token_header_name)
         
     | 
| 91 | 
         
            +
                            graphql_types = gr.Textbox(value=process_message[2], interactive=False, label="GraphQL Types")
         
     | 
| 92 | 
         
            +
                            bot = gr.Chatbot(type='messages', label="GraphQL Chat Window", render_markdown=True, sanitize_html=False, show_label=True, render=False, visible=True, elem_classes="chatbot")
         
     | 
| 93 | 
         
            +
                            chat = gr.ChatInterface(
         
     | 
| 94 | 
         
            +
                                                fn=graphql_chatbot_with_fc,
         
     | 
| 95 | 
         
            +
                                                type='messages',
         
     | 
| 96 | 
         
            +
                                                chatbot=bot,
         
     | 
| 97 | 
         
            +
                                                title="Chat with your Graphql API",
         
     | 
| 98 | 
         
            +
                                                examples=example_questions,
         
     | 
| 99 | 
         
            +
                                                concurrency_limit=None,
         
     | 
| 100 | 
         
            +
                                                additional_inputs=[session_hash, graphql_api_string, graphql_api_token, graphql_token_header, graphql_types]
         
     | 
| 101 | 
         
            +
                                                )
         
     | 
| 102 | 
         
            +
                        
         
     | 
| 103 | 
         
            +
                def process_graphql(graphql_url, api_token, api_token_header_name, session_hash):
         
     | 
| 104 | 
         
            +
                    if graphql_url:
         
     | 
| 105 | 
         
            +
                        process_message = connect_graphql(graphql_url, api_token, api_token_header_name, session_hash)
         
     | 
| 106 | 
         
            +
                    return process_message            
         
     | 
| 107 | 
         
            +
             
     | 
| 108 | 
         
            +
            if __name__ == "__main__":
         
     | 
| 109 | 
         
            +
                demo.launch()
         
     | 
    	
        templates/sql_db.py
    CHANGED
    
    | 
         @@ -17,7 +17,7 @@ with gr.Blocks() as demo: 
     | 
|
| 17 | 
         
             
                                     <p style="font-weight:bold;">Notice: the way this system is designed, no login information is retained and credentials are passed as session variables until the user leaves or 
         
     | 
| 18 | 
         
             
                                      refreshes the page in which they disappear. They are never saved to any files. I also make use of the Pandas read_sql_query function to apply SQL 
         
     | 
| 19 | 
         
             
                                      queries, which can't delete, drop, or add database lines to avoid unhappy accidents or glitches.
         
     | 
| 20 | 
         
            -
                                      That being said, it's probably  
     | 
| 21 | 
         
             
                                      This should be for demonstration purposes.</p>
         
     | 
| 22 | 
         
             
                                      <p>Contact me if this is something you would like built in your organization, on your infrastructure, and with the requisite privacy and control a production
         
     | 
| 23 | 
         
             
                                      database analytics tool requires.</p>
         
     | 
| 
         @@ -76,7 +76,7 @@ with gr.Blocks() as demo: 
     | 
|
| 76 | 
         
             
                            db_pass = gr.Textbox(visible=False, value=sql_pass)
         
     | 
| 77 | 
         
             
                            db_name = gr.Textbox(visible=False, value=sql_db_name)
         
     | 
| 78 | 
         
             
                            db_tables = gr.Textbox(value=process_message[2], interactive=False, label="SQL Tables")
         
     | 
| 79 | 
         
            -
                            bot = gr.Chatbot(type='messages', label=" 
     | 
| 80 | 
         
             
                            chat = gr.ChatInterface(
         
     | 
| 81 | 
         
             
                                                fn=sql_chatbot_with_fc,
         
     | 
| 82 | 
         
             
                                                type='messages',
         
     | 
| 
         | 
|
| 17 | 
         
             
                                     <p style="font-weight:bold;">Notice: the way this system is designed, no login information is retained and credentials are passed as session variables until the user leaves or 
         
     | 
| 18 | 
         
             
                                      refreshes the page in which they disappear. They are never saved to any files. I also make use of the Pandas read_sql_query function to apply SQL 
         
     | 
| 19 | 
         
             
                                      queries, which can't delete, drop, or add database lines to avoid unhappy accidents or glitches.
         
     | 
| 20 | 
         
            +
                                      That being said, it's probably best to use caution when connecting to a production database to a strange AI tool with an unfamiliar author. 
         
     | 
| 21 | 
         
             
                                      This should be for demonstration purposes.</p>
         
     | 
| 22 | 
         
             
                                      <p>Contact me if this is something you would like built in your organization, on your infrastructure, and with the requisite privacy and control a production
         
     | 
| 23 | 
         
             
                                      database analytics tool requires.</p>
         
     | 
| 
         | 
|
| 76 | 
         
             
                            db_pass = gr.Textbox(visible=False, value=sql_pass)
         
     | 
| 77 | 
         
             
                            db_name = gr.Textbox(visible=False, value=sql_db_name)
         
     | 
| 78 | 
         
             
                            db_tables = gr.Textbox(value=process_message[2], interactive=False, label="SQL Tables")
         
     | 
| 79 | 
         
            +
                            bot = gr.Chatbot(type='messages', label="SQL DB Chat Window", render_markdown=True, sanitize_html=False, show_label=True, render=False, visible=True, elem_classes="chatbot")
         
     | 
| 80 | 
         
             
                            chat = gr.ChatInterface(
         
     | 
| 81 | 
         
             
                                                fn=sql_chatbot_with_fc,
         
     | 
| 82 | 
         
             
                                                type='messages',
         
     | 
    	
        tools/tools.py
    CHANGED
    
    | 
         @@ -98,14 +98,84 @@ def doc_db_tools_call(db_collections): 
     | 
|
| 98 | 
         
             
                                "properties": {
         
     | 
| 99 | 
         
             
                                    "aggregation_pipeline": {
         
     | 
| 100 | 
         
             
                                        "type": "string",
         
     | 
| 101 | 
         
            -
                                        "description": "The MongoDB aggregation pipeline to use in the search. Infer this from the user's message. It should be a question or a statement"
         
     | 
| 102 | 
         
             
                                    },
         
     | 
| 103 | 
         
             
                                    "db_collection": {
         
     | 
| 104 | 
         
             
                                        "type": "string",
         
     | 
| 105 | 
         
            -
                                        "description": "The MongoDB collection to use in the search. Infer this from the user's message. It should be a question or a statement",
         
     | 
| 106 | 
         
             
                                    }
         
     | 
| 107 | 
         
             
                                },
         
     | 
| 108 | 
         
            -
                                "required": [" 
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 109 | 
         
             
                            },
         
     | 
| 110 | 
         
             
                        },
         
     | 
| 111 | 
         
             
                    },
         
     | 
| 
         | 
|
| 98 | 
         
             
                                "properties": {
         
     | 
| 99 | 
         
             
                                    "aggregation_pipeline": {
         
     | 
| 100 | 
         
             
                                        "type": "string",
         
     | 
| 101 | 
         
            +
                                        "description": "The MongoDB aggregation pipeline to use in the search. Infer this from the user's message. It should be a question or a statement."
         
     | 
| 102 | 
         
             
                                    },
         
     | 
| 103 | 
         
             
                                    "db_collection": {
         
     | 
| 104 | 
         
             
                                        "type": "string",
         
     | 
| 105 | 
         
            +
                                        "description": "The MongoDB collection to use in the search. Infer this from the user's message. It should be a question or a statement.",
         
     | 
| 106 | 
         
             
                                    }
         
     | 
| 107 | 
         
             
                                },
         
     | 
| 108 | 
         
            +
                                "required": ["aggregation_pipeline","db_collection"],
         
     | 
| 109 | 
         
            +
                            },
         
     | 
| 110 | 
         
            +
                        },
         
     | 
| 111 | 
         
            +
                    },
         
     | 
| 112 | 
         
            +
                ]
         
     | 
| 113 | 
         
            +
             
     | 
| 114 | 
         
            +
                tools_calls.extend(chart_tools)
         
     | 
| 115 | 
         
            +
                tools_calls.extend(stats_tools)
         
     | 
| 116 | 
         
            +
             
     | 
| 117 | 
         
            +
                return tools_calls
         
     | 
| 118 | 
         
            +
             
     | 
| 119 | 
         
            +
            def graphql_tools_call(graphql_types):
         
     | 
| 120 | 
         
            +
                
         
     | 
| 121 | 
         
            +
                types_string = (graphql_types[:625] + '..') if len(graphql_types) > 625 else graphql_types
         
     | 
| 122 | 
         
            +
                    
         
     | 
| 123 | 
         
            +
                tools_calls = [
         
     | 
| 124 | 
         
            +
                    {
         
     | 
| 125 | 
         
            +
                        "type": "function",
         
     | 
| 126 | 
         
            +
                        "function": {
         
     | 
| 127 | 
         
            +
                            "name": "graphql_query_func",
         
     | 
| 128 | 
         
            +
                            "description": f"""This is a tool useful to build a GraphQL query for a GraphQL API endpoint with the following types, {types_string}.
         
     | 
| 129 | 
         
            +
                            There may also be more types in the GraphQL endpoint if the number of types is too large to process. 
         
     | 
| 130 | 
         
            +
                            This function also saves the results of the query to a csv file called query.csv.""",
         
     | 
| 131 | 
         
            +
                            "parameters": {
         
     | 
| 132 | 
         
            +
                                "type": "object",
         
     | 
| 133 | 
         
            +
                                "properties": {
         
     | 
| 134 | 
         
            +
                                    "graphql_query": {
         
     | 
| 135 | 
         
            +
                                        "type": "string",
         
     | 
| 136 | 
         
            +
                                        "description": "The GraphQL query to use in the search. Infer this from the user's message. It should be a question or a statement."
         
     | 
| 137 | 
         
            +
                                    }
         
     | 
| 138 | 
         
            +
                                },
         
     | 
| 139 | 
         
            +
                                "required": ["graphql_query"],
         
     | 
| 140 | 
         
            +
                            },
         
     | 
| 141 | 
         
            +
                        },
         
     | 
| 142 | 
         
            +
                    },
         
     | 
| 143 | 
         
            +
                    {
         
     | 
| 144 | 
         
            +
                        "type": "function",
         
     | 
| 145 | 
         
            +
                        "function": {
         
     | 
| 146 | 
         
            +
                            "name": "graphql_schema_query",
         
     | 
| 147 | 
         
            +
                            "description": f"""This is a tool useful to query a GraphQL type and receive back information about its schema. This is useful because
         
     | 
| 148 | 
         
            +
                            the GraphQL introspection query is too large to be ingested all at once and this allows us to query the schema one type at a time to 
         
     | 
| 149 | 
         
            +
                            view it in manageable bites. You may realize after viewing the schema, that the type you selected was not appropriate for the question
         
     | 
| 150 | 
         
            +
                            you are attempting answer. You may then query additional types to find the appropriate types to use for your GraphQL API query.""",
         
     | 
| 151 | 
         
            +
                            "parameters": {
         
     | 
| 152 | 
         
            +
                                "type": "object",
         
     | 
| 153 | 
         
            +
                                "properties": {
         
     | 
| 154 | 
         
            +
                                    "graphql_type": {
         
     | 
| 155 | 
         
            +
                                        "type": "string",
         
     | 
| 156 | 
         
            +
                                        "description": "The GraphQL type that we want to view the schema of in order to make the proper query with our graphql_query_func. Infer this from the user's message. It should be a question or a statement."
         
     | 
| 157 | 
         
            +
                                    }
         
     | 
| 158 | 
         
            +
                                },
         
     | 
| 159 | 
         
            +
                                "required": ["graphql_type"],
         
     | 
| 160 | 
         
            +
                            },
         
     | 
| 161 | 
         
            +
                        },
         
     | 
| 162 | 
         
            +
                    },
         
     | 
| 163 | 
         
            +
                    {
         
     | 
| 164 | 
         
            +
                        "type": "function",
         
     | 
| 165 | 
         
            +
                        "function": {
         
     | 
| 166 | 
         
            +
                            "name": "graphql_csv_query",
         
     | 
| 167 | 
         
            +
                            "description": f"""This is a tool useful to SQL query our query.csv file that is generated from our GraphQL query. This is useful in a situation
         
     | 
| 168 | 
         
            +
                            where the results of the GraphQL query need additional querying to answer the user question.  The query.csv file is converted to a Pandas dataframe
         
     | 
| 169 | 
         
            +
                            and we query that dataframe with SQL on a table called 'query' before converting it back to a csv file.""",
         
     | 
| 170 | 
         
            +
                            "parameters": {
         
     | 
| 171 | 
         
            +
                                "type": "object",
         
     | 
| 172 | 
         
            +
                                "properties": {
         
     | 
| 173 | 
         
            +
                                    "csv_query": {
         
     | 
| 174 | 
         
            +
                                        "type": "string",
         
     | 
| 175 | 
         
            +
                                        "description": "The pandas dataframe SQL query to use in the search. The table that we query is named 'query'. Infer this from the user's message. It should be a question or a statement"
         
     | 
| 176 | 
         
            +
                                    }
         
     | 
| 177 | 
         
            +
                                },
         
     | 
| 178 | 
         
            +
                                "required": ["csv_query"],
         
     | 
| 179 | 
         
             
                            },
         
     | 
| 180 | 
         
             
                        },
         
     | 
| 181 | 
         
             
                    },
         
     |