|
import ast
|
|
import gradio as gr
|
|
from functions import example_question_generator, chatbot_func
|
|
from data_sources import connect_graphql
|
|
from utils import message_dict
|
|
|
|
import os
|
|
from dotenv import load_dotenv
|
|
|
|
load_dotenv()
|
|
|
|
graphql_sample_endpoint = os.getenv("GRAPHQL_SAMPLE_ENDPOINT")
|
|
graphql_sample_api_token = os.getenv("GRAPHQL_SAMPLE_API_TOKEN")
|
|
graphql_sample_header_name = os.getenv("GRAPHQL_SAMPLE_HEADER_NAME")
|
|
|
|
def hide_info():
|
|
return gr.update(visible=False)
|
|
|
|
with gr.Blocks() as demo:
|
|
description = gr.HTML("""
|
|
<!-- Header -->
|
|
<div class="max-w-4xl mx-auto mb-12 text-center">
|
|
<div class="bg-blue-50 border border-blue-200 rounded-lg max-w-2xl mx-auto">
|
|
<p>This tool allows users to communicate with and query real time data from a GraphQL API endpoint using natural
|
|
language and the above features.</p>
|
|
<p style="font-weight:bold;">Notice: API querying is the most difficult and experimental feature so far.
|
|
This tool may have variable performance and quality, although it should get better over time as I evaluate use.
|
|
No login information is retained and credentials are passed as session variables until the user leaves or
|
|
refreshes the page in which they disappear. They are never saved to any files.</p>
|
|
<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,
|
|
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
|
|
api token being used.
|
|
And of course, it's probably best to use caution when connecting to a strange AI tool with an unfamiliar author.
|
|
This should be for demonstration purposes.</p>
|
|
<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
|
|
database analytics tool requires.</p>
|
|
</div>
|
|
</div>
|
|
""", elem_classes="description_component")
|
|
|
|
graphql_url = gr.Textbox(label="GraphQL Endpoint URL", value=graphql_sample_endpoint)
|
|
with gr.Row():
|
|
api_token_header_name = gr.Textbox(label="API Token Header Name", value=graphql_sample_header_name)
|
|
api_token = gr.Textbox(label="API Token", value=graphql_sample_api_token, type="password")
|
|
|
|
submit = gr.Button(value="Submit")
|
|
submit.click(fn=hide_info, outputs=description)
|
|
|
|
@gr.render(inputs=[graphql_url,api_token,api_token_header_name], triggers=[submit.click])
|
|
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):
|
|
if request.session_hash not in message_dict:
|
|
message_dict[request.session_hash] = {}
|
|
message_dict[request.session_hash]['graphql'] = None
|
|
if graphql_url:
|
|
print("GraphQL API")
|
|
process_message = process_graphql(graphql_url, api_token, api_token_header_name, request.session_hash)
|
|
gr.HTML(value=process_message[1], padding=False)
|
|
if process_message[0] == "success":
|
|
if "qdl-app-testing" in graphql_url:
|
|
example_questions = [
|
|
["Describe the dataset"],
|
|
["What is the total revenue for this shopify store?"],
|
|
["What is the average duration from the fulfillment of an order to its delivery?"],
|
|
["What is the total value of orders processed in the current month?"],
|
|
["Which product has the highest number of variants in the inventory?"],
|
|
["How many gift cards have been issued this year, and what is their total value?"],
|
|
["How many active apps are currently installed on the store?"],
|
|
["What is the total count of abandoned checkouts over the last month?"]
|
|
]
|
|
else:
|
|
try:
|
|
generated_examples = ast.literal_eval(example_question_generator(request.session_hash, 'graphql', graphql_url, process_message[2], ''))
|
|
example_questions = [
|
|
["Describe the dataset"]
|
|
]
|
|
for example in generated_examples:
|
|
example_questions.append([example])
|
|
except Exception as e:
|
|
print("GRAPHQL QUESTION GENERATION ERROR")
|
|
print(e)
|
|
example_questions = [
|
|
["Describe the dataset"],
|
|
["List the columns in the dataset"],
|
|
["What could this data be used for?"],
|
|
]
|
|
session_hash = gr.Textbox(visible=False, value=request.session_hash)
|
|
graphql_api_string = gr.Textbox(visible=False, value=graphql_url)
|
|
graphql_api_token = gr.Textbox(visible=False, value=api_token)
|
|
graphql_token_header = gr.Textbox(visible=False, value=api_token_header_name)
|
|
titles = gr.Textbox(value=process_message[2], interactive=False, label="GraphQL Types")
|
|
data_source = gr.Textbox(visible=False, value='graphql')
|
|
schema = gr.Textbox(visible=False, value='')
|
|
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")
|
|
chat = gr.ChatInterface(
|
|
fn=chatbot_func,
|
|
type='messages',
|
|
chatbot=bot,
|
|
title="Chat with your Graphql API",
|
|
examples=example_questions,
|
|
concurrency_limit=None,
|
|
additional_inputs=[session_hash, data_source, titles, schema, graphql_api_string, graphql_api_token, graphql_token_header]
|
|
)
|
|
|
|
def process_graphql(graphql_url, api_token, api_token_header_name, session_hash):
|
|
if graphql_url:
|
|
process_message = connect_graphql(graphql_url, api_token, api_token_header_name, session_hash)
|
|
return process_message
|
|
|
|
if __name__ == "__main__":
|
|
demo.launch() |