REST API
Here we present the REST API for running Catch-Phrase NLIs. Access is permitted via an API key and endpoints allow for session management, submitting natural language questions or commands, choosing among interpretations, and confirming commands. There are also end points to get a list of the available corpora, list questions in a corpus, and to execute every question in a corpus and get an execution report. Calls to these endpoints return JSON objects..
We include the python
code at the bottom of this page that shows this API being called for an example of the D & D NLI
running
at
proxy port
8005 on https://c-phrase.com. To get a quick working example, we recommend that you
execute that code in your python environment.
API Key
Set the parameter X-API-Key in your header
to access the NLI. The API-Key itself is literally the NLI username, then a space, followed by the password.
All endpoints require this to be set. For the access to the example database this is set as:
headers = {
'X-API-Key':"rest-test Weeble-123"
}
Endpoints
Session Management
Because calls to Catch-Phrase occasionally require dialog management for things such as resolving ambiguities or confirming updates, we maintain session identifiers to hold dialog state. For the sake of better logging readability, these session identifiers are simply random integer values from 0 to 1 billion.
Get Session
POST /c-phrase/v1/session
Description
Sessions are
opened with a POST and do not take a payload.
Responses
200, 400
The
return value
is a JSON object with the single parameter session which gives the literal session
value that should be passed in on subsequent calls.
Close Session
POST /c-phrase/v1/close-session
Description
To better manage resources, it is strongly advised that sessions are closed at the end of their
use. This is achieved via a POST with a payload
containing the session parameter (note this also works via GET).
Responses
200, 400Natural Language Requests
POST /c-phrase/v1/request
Description
The main entry point of the API is the /c-phrase/v1/request route that accepts an
utterance paired with a session and depending on how Catch-Phrase interprets
the
request it returns a response object of type table-answer,list-answer,
choice-list, confirmation-request or error. The call should be made
using a POST but, for convenience it can also be called with GET.
Responses
200, 400
Table Answer
Table answers either are returned as a direct result of a request, or as the result of choosing an interpretation within a choice list.
-
https://c-phrase.com:8005/c-phrase/v1/request?session=714095900&text=lawful evil dragons HP over 300 - returns:
{ "table-answer": { "columns": [ "name", "image", "hit point", "armor class", "challenge rating", "type", "size", "alignment", "strength", "dexterity", "constitution", "intelligence", "wisdom", "charisma" ], "paraphrase": "lawful evil dragons HP over 300", "rows": [ { "alignment": "Lawful Evil", "armor class": "22", "challenge rating": "23", "charisma": "21", "constitution": "27", "dexterity": "10", "hit point": "481", "image": "link", "intelligence": "18", "name": "Dragon, Chromatic, Blue, Ancient", "size": "Gargantuan", "strength": "29", "type": "Dragon", "wisdom": "17" }, { "alignment": "Lawful Evil", "armor class": "21", "challenge rating": "22", "charisma": "19", "constitution": "25", "dexterity": "12", "hit point": "385", "image": "link", "intelligence": "20", "name": "Dragon, Chromatic, Green, Ancient", "size": "Gargantuan", "strength": "27", "type": "Dragon", "wisdom": "17" } ], "sql": "SELECT DISTINCT \n X1.name, \n ('' || 'images' || ' ') AS images, \n X1.hp, \n X1.ac, \n X1.challenge_rating, \n X1.type, \n X1.size, \n X1.alignment2, \n X1.strength, \n X1.dexterity, \n X1.constitution, \n X1.intelligence, \n X1.wisdom, \n X1.charisma\n\nFROM\n monster AS X1\nWHERE \n X1.hp>300 AND \n X1.type='Dragon' AND \n X1.alignment2='Lawful Evil'", "type": "table" }, "type": "table-answer" }
List Answer
List answers are similar to table answers, but they are over a single column:
-
https://c-phrase.com:8005/c-phrase/v1/request?session=714095900&text=names of Chaotic Good or Chaotic Neutral Feys - returns:
{ "list-answer": { "list": [ "Boggle", "Darkling", "Darkling Elder", "Eladrin, Autumn", "Eladrin, Spring", "Eladrin, Summer", "Eladrin, Winter", "Korred", "Satyr", "Siren" ], "paraphrase": "names of Chaotic Good or Chaotic Neutral Feys", "sql": "..." }, "type": "list-answer" }
Choice List
A choice list gives all the interpretations for an ambiguous question. Immediately after a choice list is returned, then one of the interpretations may be picked on the next call via the choice endpoint. This in turn will generate a table answer, a list answer or, possibly, an error.
-
https://c-phrase.com:8005/c-phrase/v1/request?session=714095900&text=Dragons taking non-standard damage - returns:
{ "choices": [ { "index": "1", "message": "", "text": "imunity_of_monster monsters type Dragon" }, { "index": "2", "message": "", "text": "resistance_of_monster monsters type Dragon" }, { "index": "3", "message": "", "text": "susceptiblity_of_monster monsters type Dragon" } ], "type": "choice-list" } -
This response may be immediately followed up by a choose interpretation operation (see here)
https://c-phrase.com:8005/c-phrase/v1/choice?session=714095900&choice=2 - This then returns:
{ "table-answer": { "columns": [ "monster", "damage" ], "paraphrase": "Dragons taking non-standard damage", "rows": [ { "damage": "Poison", "monster": "Ambush Drake" }, { "damage": "Acid", "monster": "Dragon, Turtle" } ], "sql": "...", "type": "table" }, "type": "table-answer" }
Confirmation Request
Confirmation Requests are returned when a successful update command is processed by catch phrase that needs to be confirmed.
-
https://c-phrase.com:8005/c-phrase/v1/request?session=714095900&text=delete location name Weeble - returns:
{ "confirmation": "delete locations name Weeble", "type": "confirmation-request" }For this to actually be reflected in the database it must be immediately followed up with a call to
https://c-phrase.com:8005/c-phrase/v1/confirm?session=714095900 - returns:
{ "message": "1 row(s) affected by delete locations name Weeble", "type": "confirmed" }
Error
Errors are returned when something fails.
-
https://c-phrase.com:8005/c-phrase/v1/request?session=714095900&text=saskwatch - returns:
{ "error": { "message": "'saskwatch' not recognized.", "type": "cp-fail-no-mapping" }, "type": "error" }
Interaction
As presented above, often the responses from Catch-Phrase require interaction. This is either to pick one of several alternative interpretations or to confirm an update operation. In both cases an error will return if the interaction operation does not immediate follow the returned choice list or confirmation request object
Choose Interpretation
POST /c-phrase/v1/choice
Description
When the response object is a choice-list the API can pick which of the interpretations
to
execute.
The is achieved via a POST on /c-phrase/v1/choice. This in turn will
result in
a
table-answer,list-answer or confirmation response object. The call should be made
using a POST but, for convenience it can also be called with GET.
Confirm
POST /c-phrase/v1/confirm
Description
All update commands need to be explicitly confirmed via the API. This happens when a response object
is
a
confirmation message. To confirm, one performs POST with the
session
as
the
parameter to /c-phrase/v1/confirm. Confirmations are only available as an immediate
operation
on the next turn.The call should be made
using a POST but, for convenience it can also be called with GET.
Working with Corpora
Get Corpora
GET /c-phrase/v1/corpora
A simple GET on /c-phrase/v1/corpora returns a list of corpora configured
for
the
NLI.
This returns a list of the corpus names.
Get Questions
GET /c-phrase/v1/questions
A simple GET on /c-phrase/v1/questions?corpus={corpus_name} returns a list
of
the
questions in
the given corpus.
Evaluate Corpus
POST /c-phrase/v1/evaluate
A POST on /c-phrase/v1/evaluate with a payload of the
corpus_name
will
evaluate every
question in the corpus and return an execution report as a table answer. The call should be made
using a POST but, for convenience it can also be called with GET.
Calling the REST API from Python
We recommend that you get this code working in your environment to quickly get a working example. Then adapt to call your own running NLI.
import requests
import json
base_url = 'https://c-phrase.com:8005'
headers = {'X-API-Key':"rest-test Weeble-123"}
response = requests.post(base_url + "/c-phrase/v1/session", headers=headers, json={})
session = json.loads(response.text)['session']
payload = {
"text": "lawful evil dragons with more than 300 hit points",
"session": session
}
# Request as a POST
response = requests.post(base_url + f"/c-phrase/v1/request", json=payload, headers=headers)
answer = json.loads(response.text)
print(answer['table-answer']['sql'])
# Request as a GET
response = requests.get(base_url + f"/c-phrase/v1/request?session={session}&text=names of Chaotic Good or Chaotic Neutral Feys",
headers=headers)
answer = json.loads(response.text)
print(answer['list-answer']['paraphrase'])
payload = {
"text": "average strength of fiends",
"session": session
}
response = requests.post(base_url + f"/c-phrase/v1/request", json=payload, headers=headers)
answer = json.loads(response.text)
print(answer['table-answer']['paraphrase'])
payload = {
"text": "Dragons taking non-standard damage",
"session": session
}
response = requests.post(base_url + f"/c-phrase/v1/request", json=payload, headers=headers)
answer = json.loads(response.text)
if 'choices' in answer:
response = requests.post(base_url + f"/c-phrase/v1/choice",
json={"session": session, "choice": 2}, headers=headers)
answer = json.loads(response.text)
print(answer['table-answer']['rows'][0]['monster'])
response = requests.post(base_url + f"/c-phrase/v1/request", json={"session": session, "text":"saskwatch"}, headers=headers)
answer = json.loads(response.text)
print(answer['error']['message'])
# Request as a GET
response = requests.get(base_url + f"/c-phrase/v1/request?session={session}&text=how many monsters per type", headers=headers)
answer = json.loads(response.text)
response = requests.post(base_url + f"/c-phrase/v1/request", json={"session": session, "text":"saskwatch"}, headers=headers)
answer = json.loads(response.text)
response = requests.get(base_url + f"/c-phrase/v1/corpora", headers=headers)
answer = json.loads(response.text)
corpus_name = answer['corpora'][0]
response = requests.get(base_url + f"/c-phrase/v1/questions?corpus_name={corpus_name}", headers=headers)
answer = json.loads(response.text)
response = requests.post(base_url + f"/c-phrase/v1/evaluate",
json={"session":session,"corpus_name":corpus_name},
headers=headers)
answer = json.loads(response.text)
response = requests.post(base_url + f"/c-phrase/v1/request", json={"session": session, "text":'add location name "Weeble" description "Humpf"'}, headers=headers)
answer = json.loads(response.text)
response = requests.post(base_url + f"/c-phrase/v1/request", json={"session": session, "text":'add location name "Wonk"'}, headers=headers)
answer = json.loads(response.text)
response = requests.post(base_url + f"/c-phrase/v1/request", json={"session": session, "text":'delete location name Weeble'}, headers=headers)
answer = json.loads(response.text)
response = requests.post(base_url + f"/c-phrase/v1/confirm", json={"session": session}, headers=headers)
answer = json.loads(response.text)
response = requests.post(base_url + "/c-phrase/v1/close-session", json={"session": session}, headers=headers)