AI-Planning / planning-as-a-service

The newly improved planner (and more) in the cloud.
Apache License 2.0
30 stars 7 forks source link

logo100 Planning as a service (PaaS) provides an extendable API to deploy planners online in local or cloud servers. The service provides a queue manager to control a set of workers, which can easily be extended with one of several planners available in PLANUTILS.

Getting Started

Docker Build & Launch

  1. Get sources
git clone https://github.com/AI-Planning/planning-as-a-service
cd planning-as-a-service/server
  1. Create an .env file in the server folder:

Please create a new environment file called .env, and set up the following variable. You can reference the provided .env.example file.

  1. Start Docker:
# make sure you are in the server folder to run the makefile
cd server
sudo make
  1. This will build the latest Planutils Image and install all the selected solvers. You can edit the Dockerfile to update the available solvers.

  2. Then it will expose the Flask application's endpoints on port 5001 as well as a Flower server for monitoring workers on port 5555

To add more workers:

docker compose up -d --scale worker=5 --no-recreate

To shut down:

docker compose down

To change the endpoints, update the code in api/app.py

Task changes should happen in queue/tasks.py

Compatibility Issues

Please be aware that the current Singularity docker image is not compatible with the new Mac M1 CPU.

API

Local Dev

Assuming you are in the server/ directory.

sudo apt-get install redis-server
sudo service redis-server start
virtualenv env
pip install -r requirements.txt

Run server

New terminal (If you are using vscode, do CTRL+SHIFT+` to open a new terminal)

Run Flask:

source env/bin/activate
cd api
python app.py

New terminal and start celery:

source env/bin/activate
cd celery-queue
celery -A tasks worker --loglevel=info

New Terminal and start flower (queue monitoring):

source env/bin/activate
cd celery-queue
flower -A tasks --port=5555 --broker=redis://localhost:6379/0

Debug

Go to server folder and open vscode. Install vscode first. Note that this assumes you have started celery and flower as instructed above.

cd server
code . &

Go to the debug symbol add breakpoints and debug as shown below: image

Example use

A simple python script to send a POST request to the lama-first planner, getting back stdout, stderr, and the generated plan:

import requests
import time
from pprint import pprint

req_body = {
"domain":"(define (domain BLOCKS) (:requirements :strips) (:predicates (on ?x ?y) (ontable ?x) (clear ?x) (handempty) (holding ?x) ) (:action pick-up :parameters (?x) :precondition (and (clear ?x) (ontable ?x) (handempty)) :effect (and (not (ontable ?x)) (not (clear ?x)) (not (handempty)) (holding ?x))) (:action put-down :parameters (?x) :precondition (holding ?x) :effect (and (not (holding ?x)) (clear ?x) (handempty) (ontable ?x))) (:action stack :parameters (?x ?y) :precondition (and (holding ?x) (clear ?y)) :effect (and (not (holding ?x)) (not (clear ?y)) (clear ?x) (handempty) (on ?x ?y))) (:action unstack :parameters (?x ?y) :precondition (and (on ?x ?y) (clear ?x) (handempty)) :effect (and (holding ?x) (clear ?y) (not (clear ?x)) (not (handempty)) (not (on ?x ?y)))))",
"problem":"(define (problem BLOCKS-4-0) (:domain BLOCKS) (:objects D B A C ) (:INIT (CLEAR C) (CLEAR A) (CLEAR B) (CLEAR D) (ONTABLE C) (ONTABLE A) (ONTABLE B) (ONTABLE D) (HANDEMPTY)) (:goal (AND (ON D C) (ON C B) (ON B A))) )"
}

# Send job request to solve endpoint
solve_request_url=requests.post("http://localhost:5001/package/lama/solve", json=req_body).json()

# Query the result in the job
celery_result=requests.post('http://localhost:5001' + solve_request_url['result'])

print('Computing...')
while celery_result.json().get("status","")== 'PENDING':

    # Query the result every 0.5 seconds while the job is executing
    celery_result=requests.post('http://localhost:5001' + solve_request_url['result'])
    time.sleep(0.5)

pprint(celery_result.json())

This python code will run a POST solve request on the lama-first solver, and return the link to access the result from the celery queue. In the meantime, the program polls for the task to be completed, and prints out the returned json when it is.

If you want to use an adaptor to parse the returned plan files, you can specify the arguments when processing the job result:

# Query the result in the job
celery_result=requests.post('http://localhost:5001' + solve_request_url['result'], json={"adaptor":"planning_editor_adaptor"}  )

Adding new Planners

Install a planner available in planutils by adding the installation line in the worker dockerfile.

RUN planutils install -f -y dual-bfws-ffparser

To learn how to setup a new planner in planutils, see the information in planuitls github repo

Editor.Planning.Domains plugin

If you want to edit the plugin exposing the service to the online editor, take a look at the plugin codebase

Docker Flask Celery Redis

A basic Docker Compose template for orchestrating a Flask application & a Celery queue with Redis


Docker structure adapted from https://github.com/mattkohl/docker-flask-celery-redis