Chat Explore
Our Chat Explore endpoints allow you to interface with Chat Explore, our flagship "chat with your data" assistant. Our API allows a programmatic interface by which you can supply a project or dataset and a question you'd like to ask about it, and we'll respond with an answer.
As with most other long-running requests, we adopt an asynchronous endpoints model. You can read more about it on the Asynchronous Endpoints page or continue reading here.
These endpoints are currently in beta and are subject to change as we refine them.
Custom Instructions
Chat Explore has the powerful capability for you to provide Custom Instructions that allow you to attach additional context for each call specific to your use case.
In order for Chat Explore to factor in custom instructions attached to the project into calls, you must make these calls with the project_id
parameter rather than the dataset_id
parameter.
Three parameters may be specified:
chatContext
: What you'd like Chat Explore to know about your application to provide better responses. Examples:- This dataset is customer engagement data
- The units of the sales column are in millions
chatInstructions
: Specifics on how you'd like Chat Explore to respond. Examples:- Respond only in Spanish
- Provide short and concise answers only
chatSuggestions
: The Web UI (app.akkio.com
) intelligently generates a list of example questions you may ask Chat Explore as a good starting point. You can customize these instructions by providing a newline-separated list of what you'd like these suggestions to be. Example:What is the average net media cost by campaign ID?
Please show me a chart of the distribution of customer ages.
Please show me a bar chart of company size.
For information on programmatically updating these parameters for a given project, see the Projects endpoints page.
Data Formatting
Images
Similar to the UI, we support returning charts and graphs to support our responses. Each message has an images
field that represents a list of Base64-encoded images attached to that message.
Images are currently Base64 encoded in the .png
format, but may be changed. You can assume a Base64-encoded image, but do not assume it will always be a .png
image.
Tables
Tables are returned as a List of <string, value> maps, where each element of the list corresponds to a row, then each element has a key representing the column name and a value representing the value of that column.
For example, here's how a two-row table of user objects might look like:
[
{
"firstName": "John",
"lastName": "Doe",
"age": 23
},
{
"firstName": "Joanna",
"lastName": "Adams",
"age": 45
}
]
Corresponding to this table:
firstName | lastName | age |
---|---|---|
John | Doe | 23 |
Joanna | Adams | 45 |
Values can be anything JSON-serializable - strings, numbers, floats, and so on - not necessarily a string.
Statelessness
Requests to this API are stateless. To emulate a full conversation, simply take our response from your previous query and add it to the messages
array of your next query. You do not need to explicitly pass any kind of reference to your last query.
Example Request Sequence
Here's a rough outline of how you'd make a request to the Chat Explore API.
HTTP Headers
Header Name | Required | Value |
---|---|---|
X-API-Key | Yes | Your team's API key. See Authentication. |
1. Create Request
First, we'll submit a chat creation request. This will submit the task into our asynchronous processing queue and we'll begin working on it.
POST /api/v1/chat-explore/new
{
"project_id": "<your project id>",
"messages": [
{
"role": "user",
"content": "Please give me one cool chart of this data. Your choice."
}
]
}
You'll receive an object like this containing a task id:
{
"task_id": "<task_id>"
}
Or, as a cURL command:
curl -X POST https://api.akkio.com/api/v1/chat-explore/new \
-H "X-API-Key: your_api_key" \
-H "Content-Type: application/json" \
-d '{"project_id": "your_project_id", "messages": [ { "role": "user", "content": "Please give me one cool chart of this data. Your choice." } ] }'
We'll use this in the next request.
2. Query for Task Status
Next, we'll query the status endpoint at a cadence to see whether the chat is done being created yet. This request might look something like this:
GET /api/v1/chat-explore/status/<task_id>
Note that you must use the same Task ID that you received from the task creation endpoint above.
This will provide you with a status
field set to either SUBMITTED
, IN_PROGRESS
, FAILED
, or SUCCEEDED
. You can read more about each state on the Asynchronous Endpoints page.
Here's an example response you might get:
{
"status": "IN_PROGRESS",
"metadata": {
"type": "IN_PROGRESS"
}
}
You should retry ("poll") this endpoint at a regular cadence until you get a response that looks something like this:
{
"status": "SUCCEEDED",
"metadata": {
"type": "SUCCEEDED",
"location": "/api/v1/chat-explore/chats/123456"
}
}
The location
field is always relative to the API root (https://api.akkio.com/api/v1
), not the overall website root (https://api.akkio.com
). You'll need to remember to construct the end URL from the site name, API root, and the provided location.
Or, as a cURL command:
curl https://api.akkio.com/api/v1/chat-explore/status/task_id_from_previous_result \
-H "X-API-Key: your_api_key"
Armed with this information, we'll move to the last request.
3. Query for Result
Armed with the location we got from the status call, we'll make a request for the end chat.
GET /api/v1/chat-explore/chats/123456
If you're interested in the images returned and you would prefer it to be formatted as a string-serialized Plotly JSON object instead of the default base64-encoded .png
, pass in a image_format=plotly_json
query parameter, and they'll be returned as such.
You'll get a response that looks something like this:
{
"owner": "<owner id>",
"org": "<org id>",
"messages": [
{
"role": "assistant",
"content": "Let's create a scatter plot to visualize the relationship between the living area (in square feet) and the price of the properties.",
"images": null,
"table": null
},
{
"role": "assistant",
"content": "A chart or table will be rendered here. Chat Explore doesn't have direct access to your chart, so it can't read what's on it.",
"images": [
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAArwAAAH0CAYAAADfWf7fAAAgAElEQVR4XuydBZhUVRvH/7uzXXR3CSKolI0BIgooAtLd3d3d3SXd0goifGIrCijSXdLNdkzs97xnmGU2WO7szs5s/O/zfM+HO+eec+7vnJn7u+9977ku0dHR0eBGAiRAAiRAAiRAAiRAAumUgAuFN52OLA [...] AAASUVORK5CYII="
],
"table": null
}
]
}
Or, as a cURL command:
curl https://api.akkio.com/api/v1/chat-explore/chats/123456 \
-H "X-API-Key: your_api_key"
You can take this result and use it however you wish.
Programmatic Examples
We're working on building a set of programmatic wrapper SDKs that provides easy, prebuilt integration in a variety of languages, but here's some examples of how you might interface with this in Python!
Two files exist here -- chat-explore-api.py
and utils.py
. The first imports the second.
# File: `utils.py`
import time
import requests
API_KEY = None
BASE_URL = "api.akkio.com/api"
VERSION = "v1"
PROTOCOL = "https"
ENDPOINT = "chat-explore"
def create_chat_request(project_id, content):
"""
Make API request for chat creation
Returns:
dict: json response
"""
MODE = "new"
url = f"{PROTOCOL}://{BASE_URL}/{VERSION}/{ENDPOINT}/{MODE}"
headers = {"X-API-Key": API_KEY, "Content-Type": "application/json"}
data = {
"project_id": project_id,
"messages": [
{
"role": "user",
"content": content,
}
],
}
response = requests.post(
url,
json=data,
headers=headers,
timeout=120,
)
# Check for HTTP errors
response.raise_for_status()
return response.json()
def check_task_status(task_id):
"""
Check task status from Chat creation POST call
Returns:
dict: json response
"""
MODE = "status"
url = f"{PROTOCOL}://{BASE_URL}/{VERSION}/{ENDPOINT}/{MODE}/{task_id}"
headers = {"X-API-Key": API_KEY, "Content-Type": "application/json"}
response = requests.get(
url,
headers=headers,
timeout=120,
)
# Check for HTTP errors
response.raise_for_status()
return response.json()
def get_chat_results(chat_id):
"""
Get chat results based on chat_id
Returns:
dict: json response
"""
MODE = "chats"
url = f"{PROTOCOL}://{BASE_URL}/{VERSION}/{ENDPOINT}/{MODE}/{chat_id}"
headers = {"X-API-Key": API_KEY, "Content-Type": "application/json"}
response = requests.get(
url,
headers=headers,
timeout=120,
)
# Check for HTTP errors
response.raise_for_status()
return response.json()
# File: chat-explore-api.py
import json
import os
import time
import utils # the other file, provided above
# Setup
API_KEY = "<REPLACE ME>"
utils.API_KEY = API_KEY
# Directory to save responses
resp_directory = "chat_responses"
os.makedirs(resp_directory, exist_ok=True) # Ensure directory exists
# Get project ID from UI (is there any way to query a list of all projects in a Team?)
project_id = "<REPLACE ME>"
# This can get passed in from top level application
content = "Show me a report of spend by device for each placement in a bar chart"
creation_resp = utils.create_chat_request(project_id, content)
print(creation_resp)
task_id = creation_resp["task_id"]
# Set a timeout for 5 minutes (300 seconds)
timeout = 300
start_time = time.time() # Get the current time to measure against the timeout
# Loop until the task status is "SUCCEEDED"
while True:
status = utils.check_task_status(task_id)
print(status)
if status["status"] == "SUCCEEDED":
chat_id = status["metadata"]["location"].split("/chats/")[1]
chat_response = utils.get_chat_results(chat_id)
# File path with project_id and task_id
file_name = f"project_{project_id}_taskid_{task_id}.txt"
file_path = os.path.join(resp_directory, file_name)
# Save the response to a text file
with open(file_path, "w") as file:
json.dump(chat_response, file, indent=4)
print(f"Response saved to {file_path}")
break
elif status["status"] == "FAILED":
print("Task failed.")
break
elif time.time() - start_time > timeout:
print("Task timed out.")
break
# Wait for some time before checking again to avoid overwhelming the server
time.sleep(5) # Sleep for 5 seconds
Additional Resources
- OpenAPI Reference: https://api.akkio.com/api/v1/docs
- OpenAPI Specification: https://api.akkio.com/api/v1/api.yaml