From b4fcf9c9ab65cbf3ba0ba81199cacd7a716cc8f9 Mon Sep 17 00:00:00 2001 From: Jinyu Xie Date: Tue, 12 Sep 2023 11:27:53 -0700 Subject: [PATCH 1/6] polish api and easy start --- README.md | 25 ++++++++----- docker-compose-dev.yml | 5 ++- docker_release.sh | 0 examples/quickstart.py | 8 ++--- examples/run_simglucose.py | 7 ++-- frontend/lib/gtag.tsx | 44 ----------------------- frontend/src/components/navbar.tsx | 4 --- frontend/src/pages/_app.tsx | 15 -------- frontend/src/pages/_document.tsx | 29 +-------------- loopquest/__init__.py | 1 + loopquest/api.py | 55 ++++++++++++++++++++++------ loopquest/crud.py | 2 ++ loopquest/ui.py | 17 +++++++++ loopquest/utils.py | 57 ++++++++++++++++++++++++++++++ release.sh => pip_release.sh | 0 tests/test_datasets.py | 4 +-- tests/test_wrappers.py | 5 +-- 17 files changed, 153 insertions(+), 125 deletions(-) create mode 100644 docker_release.sh delete mode 100644 frontend/lib/gtag.tsx create mode 100644 loopquest/__init__.py create mode 100644 loopquest/ui.py rename release.sh => pip_release.sh (100%) diff --git a/README.md b/README.md index 7e7d11c..e2112ee 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,17 @@ # :scroll:Loopquest -A Production Tool for Embodied AI. +[![Downloads](https://static.pepy.tech/badge/loopquest)](https://pepy.tech/project/loopquest) +[![Downloads](https://static.pepy.tech/badge/loopquest/month)](https://pepy.tech/project/loopquest) +[![Downloads](https://static.pepy.tech/badge/loopquest/week)](https://pepy.tech/project/loopquest) + +A Production Tool for Embodied AI. ![loopquest frontend](screenshots/loopquest-screenshot.png) - :video_camera:[Tutorial Video - Updated 9/4/2023](https://capture.dropbox.com/UXKQxGkwel6VRZJQ), [Dataset Demo](https://capture.dropbox.com/AOF5rGxHWyRb9T58) - :house:[Discord](https://discord.gg/FTnFYeSy9r) # Major features + - Imitation Learning / Offline Reinforcement Learning Oriented MLOps. Log all the observation, action, reward, rendered images into database with only ONE extra line of code. ```python @@ -16,11 +21,12 @@ env = gymnasium.make("MountainCarContinuous-v0", render_mode="rgb_array") -> ```python -from loopquest.gym_wrappers import LoopquestGymWrapper -env = LoopquestGymWrapper( - gymnasium.make("MountainCarContinuous-v0", render_mode="rgb_array"), "my_experiment" +import loopquest +env = loopquest.make_env( + gymnasium.make("MountainCarContinuous-v0", render_mode="rgb_array") ) ``` + - Directly trainable data for robotics foundation model. Select and download the (observation, action, reward) data with the dataloader interfaces of the most popular deep learning frameworks (e.g. tensorflow, pytorch, huggingface dataset apis). Check [Dataset Quickstart Example](examples/Dataset%20Quickstart.ipynb) for more details. ```python @@ -55,7 +61,9 @@ The data schema will look like 'images': [] } ``` + - All the regular MLOps features are included, e.g. data visualization, simulation rendering, experiment management. + # Installation For stable version, run @@ -103,12 +111,10 @@ bash start_dev_server.sh ```python import gymnasium -from loopquest.gym_wrappers import LoopquestGymWrapper +import loopquest -experiment_name = "test" -env = LoopquestGymWrapper( - gymnasium.make("MountainCarContinuous-v0", render_mode="rgb_array"), - experiment_name, +env = loopquest.make_env( + gymnasium.make("MountainCarContinuous-v0", render_mode="rgb_array") ) obs, info = env.reset() for i in range(100): @@ -118,4 +124,5 @@ for i in range(100): if terminated or truncated: break env.close() + ``` diff --git a/docker-compose-dev.yml b/docker-compose-dev.yml index 8ce6963..9f6e10c 100644 --- a/docker-compose-dev.yml +++ b/docker-compose-dev.yml @@ -12,7 +12,9 @@ services: - BACKEND_URL=http://backend:8000 volumes: - ./frontend:/frontend - - /frontend/node_modules + - ./frontend/package.json:/frontend/package.json + - ./frontend/package-lock.json:/frontend/package-lock.json + - node_modules:/frontend/node_modules depends_on: - backend @@ -51,3 +53,4 @@ services: volumes: db: media_store: + node_modules: diff --git a/docker_release.sh b/docker_release.sh new file mode 100644 index 0000000..e69de29 diff --git a/examples/quickstart.py b/examples/quickstart.py index 1884017..04b58b6 100644 --- a/examples/quickstart.py +++ b/examples/quickstart.py @@ -1,10 +1,8 @@ import gymnasium -from loopquest.gym_wrappers import LoopquestGymWrapper +import loopquest -experiment_name = "test" -env = LoopquestGymWrapper( - gymnasium.make("MountainCarContinuous-v0", render_mode="rgb_array"), - experiment_name, +env = loopquest.make_env( + gymnasium.make("MountainCarContinuous-v0", render_mode="rgb_array") ) obs, info = env.reset() for i in range(100): diff --git a/examples/run_simglucose.py b/examples/run_simglucose.py index 73f2559..8e01514 100644 --- a/examples/run_simglucose.py +++ b/examples/run_simglucose.py @@ -1,5 +1,5 @@ import gymnasium -from loopquest.gym_wrappers import LoopquestGymWrapper +import loopquest from gymnasium.envs.registration import register register( @@ -9,10 +9,7 @@ ) experiment_name = "a test" -env = LoopquestGymWrapper( - gymnasium.make("simglucose/adolescent2-v0"), - experiment_name, -) +env = loopquest.make_env(gymnasium.make("simglucose/adolescent2-v0")) obs, info = env.reset() for i in range(100): action = env.action_space.sample() diff --git a/frontend/lib/gtag.tsx b/frontend/lib/gtag.tsx deleted file mode 100644 index 6bfd07d..0000000 --- a/frontend/lib/gtag.tsx +++ /dev/null @@ -1,44 +0,0 @@ -// export const GA_TRACKING_ID = "G-L92VJ893VL"; // vercel prod 环境数据流跟踪ID -export const GA_TRACKING_ID = "G-S2237K9N4J"; // azure dev 环境数据流跟踪ID - -interface Window { - gtag( - type: "config", - googleAnalyticsId: string, - { page_path }: { page_path: string } - ): void; - gtag( - type: "event", - eventAction: string, - fieldObject: { event_label: string; event_category: string; value?: number } - ): void; -} - -declare let window: Window; - -// https://developers.google.com/analytics/devguides/collection/gtagjs/pages -export const pageview = (url: URL): void => { - if (typeof window !== "undefined") { - window.gtag("config", GA_TRACKING_ID, { - page_path: url.toString(), - }); - } -}; - -type GTagEvent = { - action: string; - category: string; - label: string; - value: number; -}; - -// https://developers.google.com/analytics/devguides/collection/gtagjs/events -export const event = ({ action, category, label, value }: GTagEvent): void => { - if (typeof window !== "undefined") { - window.gtag("event", action, { - event_category: category, - event_label: label, - value, - }); - } -}; diff --git a/frontend/src/components/navbar.tsx b/frontend/src/components/navbar.tsx index 5aad15c..95d2d77 100644 --- a/frontend/src/components/navbar.tsx +++ b/frontend/src/components/navbar.tsx @@ -21,10 +21,6 @@ export default function Navbar() {
  • Datasets
  • - - -
    -
    • About
    • diff --git a/frontend/src/pages/_app.tsx b/frontend/src/pages/_app.tsx index ee38c80..2b75eb0 100644 --- a/frontend/src/pages/_app.tsx +++ b/frontend/src/pages/_app.tsx @@ -3,25 +3,10 @@ import Layout from "@/components/layout"; import type { AppProps } from "next/app"; import { config } from "@fortawesome/fontawesome-svg-core"; import "@fortawesome/fontawesome-svg-core/styles.css"; -import { useRouter } from "next/router"; -import { useEffect } from "react"; -import * as gtag from "../../lib/gtag"; config.autoAddCss = false; -const isProduction = process.env.NODE_ENV === "production"; const App = ({ Component, pageProps }: AppProps): JSX.Element => { - const router = useRouter(); - useEffect(() => { - const handleRouteChange = (url: URL) => { - /* invoke analytics function only for production */ - if (isProduction) gtag.pageview(url); - }; - router.events.on("routeChangeComplete", handleRouteChange); - return () => { - router.events.off("routeChangeComplete", handleRouteChange); - }; - }, [router.events]); return ( diff --git a/frontend/src/pages/_document.tsx b/frontend/src/pages/_document.tsx index ba7460c..ff90303 100644 --- a/frontend/src/pages/_document.tsx +++ b/frontend/src/pages/_document.tsx @@ -1,36 +1,9 @@ import { Html, Head, Main, NextScript } from "next/document"; -import { GA_TRACKING_ID } from "../../lib/gtag"; -const isProduction = process.env.NODE_ENV === "production"; - export default function Document() { - return ( - - {/* enable analytics script only for production */} - {isProduction && ( - <> -