Genie Flow API
When a Genie Flow data model and state machine are implemented, we can talk to it through a simple
API. This API enables us to start a new session (create a new state machine), send a user_input
event, get the status of longer-running background processes, get a dump of the data model, etc.
The main.py
script sets up all necessary registrations. The following objects need to be
registered:
Registering your model
The data model (which is closely coupled with your state machine) needs to be registered with the API broker. This is done at the same time that you register your model for persistance.
from genie_flow.containers import init_genie_flow
from example_claims.claims import ClaimsModel
genie_environment = init_genie_flow("config.yaml")
genie_environment.register_model("claims_genie", ClaimsModel)
This line will register a Genie Flow Model (ClaimsModel
) as a potential model and state machine
to which the API can talk. Here, claims_genie
is the state machine key that is needed in the
endpoint to ensure API calls are directed towards the correct state machine logic.
So this means that one instance of Genie Flow can handle multiple different state machine logic and models simultaneously. One can register the different Q and A examples discussed in this documentation, at the same time:
from genie_flow.containers import init_genie_flow
from example_qa import (
q_and_a,
q_and_a_cond,
q_and_a_capture,
q_and_a_trans,
)
genie_environment = init_genie_flow("config.yaml")
genie_environment.register_model("q_and_a", q_and_a.QandAModel)
genie_environment.register_model("q_and_a_cond", q_and_a_cond.QandACondModel)
genie_environment.register_model("q_and_a_capture", q_and_a_capture.QandACaptureModel)
genie_environment.register_model("q_and_a_trans", q_and_a_trans.QandATransModel)
This way, any client can start a new session for any of these different models and state machines.
Registering templates
The second aspect that needs to be registered is where Genie Flow can find the templates. Here, it is also required to give a key and the actual path to the directory where the templates are. For instance:
from genie_flow.containers import init_genie_flow
from example_claims.claims import ClaimsModel
genie_environment = init_genie_flow("config.yaml")
genie_environment.register_model("claims_genie", ClaimsModel)
genie_environment.register_template_directory("claims", "example_claims/templates")
example_claims/templates
. That path is relative to the working directory. The key claims
is used in the code as the "virtual directory" when assigning templates to states. These then look
like: some_state_name="claims/my-template.jinja2
.
Running
The API is implemented using FastAPI, a Python package for production-ready API implementations. Excellent documentation on how to run a FastAPI application can be found on their website.
Events
Typically, the client interaction with Genie Flow goes as follows:
- Create a new session - this creates a new data object and initialised state machine
- Memorise the session id
- Present the response from Genie Flow to the user
- If the possible next actions contain 'user_input', capture user input and send that input
to the Genie Flow API with a
user_input
event. - If the possible next actions contain
poll
, wait a bit and send thepoll
event without the user
input - If the possible next actions contain
advance
, send theadvance
event without further input - If there are no possible next actions, the client is done, and the session can be terminated
flowchart LR
start([start]) --> create_session
create_session[client creates session] --> memorize[client memorizes session_id]
memorize --> present_response[client presents response]
present_response --> action_decision{next_actions<br/>contains...}
action_decision -->|user_input|get_user_input
action_decision -->|poll|event_poll[event: 'poll']
action_decision -->|advance|event_advance[event: 'advance']
action_decision -->|none|done([finish])
event_poll --> send_event
event_advance --> send_event
get_user_input --> event_user_input[event: 'user_input' with user input]
event_user_input --> send_event[client sends event]
send_event --> present_response
Endpoints
The following endpoints have been implemented:
Starting a session with endpoint /v1/ai/{state_machine_key}/start_session
A GET request to this endpoint starts a new session. It returns a unique ID that represents the session between the client and the Genie Flow backend application. In the background, the Genie Flow framework creates a newly instantiated data model and an accompanying state machine. The state machine is initiated at the initial state. For any subsequent API calls, this unique identifier should be passed.
The returned object will be a JSON representation of a Genie Flow AIResponse
object,
which has the following attributes:
- session_id (str)
- The unique ID representing the session.
- next_actions (list[str])
- A list of potential next events that can be sent to the state machine.
- error (Optional[str])
- An optional error string if an error occurred during processing of the call.
- response (Optional[str])
- An optional string response from the event.
sending an event - /v1/ai/{state_machine_key}/event/
When the client wants to POST a JSON representation of an EventInput
object to the Genie
Flow API, with the following attributes:
- session_id (str)
- The unique id of the session the API call refers to.
- event (str)
- The name of the event that is being sent.
- event_input (str)
- Additional input that should accompany the event - can be an empty string, but not
null
.
The client will again receive a Genie Flow AIResponse
object back, carrying the response and
possible next actions.
checking state of background task - /v1/ai/{state_machine_key/task_state/{session_id}
Through this GET request, the client will receive a JSON representation of an AIStatusResponse
object that carries the following attributes: session_id
, next_actions
- the same as with
the AIResponse
. And additionally:
ready (bool) A boolean that indicates if the task has finished processing or not.
getting model data - /v1/ai/{state_machine_key}/model/{session_id}
This GET request will retrieve the current state of the data model that is connected to the
given session_id
. A JSON representation of the data model object will be returned.