From 25c3a1bdffb516f76ba758f98d406af2e5d12fbc Mon Sep 17 00:00:00 2001
From: Julian <julian@edyoucated.org>
Date: Sun, 10 Mar 2024 11:45:44 +0100
Subject: [PATCH] first running version of dash inside of jupyterlab via proxy

---
 .gitignore                 |  2 ++
 Dockerfile                 | 22 ++++++++++---------
 README.md                  |  2 +-
 app/app.py                 | 44 ++++++++++++++++++++++++++++++++++++++
 app/callbacks.py           | 23 ++++++++++++++++++++
 app/layout.py              | 14 ++++++++++++
 environment.yml            |  7 ++++++
 jupyter_notebook_config.py | 13 +++++++++++
 requirements.txt           | 12 +++++++++++
 9 files changed, 128 insertions(+), 11 deletions(-)
 create mode 100644 .gitignore
 create mode 100644 app/app.py
 create mode 100644 app/callbacks.py
 create mode 100644 app/layout.py
 create mode 100644 environment.yml
 create mode 100644 jupyter_notebook_config.py
 create mode 100644 requirements.txt

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..f75c4cd
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+*env/
+.env
diff --git a/Dockerfile b/Dockerfile
index 8786a75..e5fa561 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,15 +1,17 @@
 FROM jupyter/datascience-notebook:hub-3.1.1
 
-# Install from APT repository
 USER root
-RUN apt-get update -y
-RUN apt-get install -y git
 
-# Install basics
-USER jovyan
-RUN pip3 install --upgrade pip
+COPY requirements.txt environment.yml /tmp/
+RUN conda env update -q -f /tmp/environment.yml && \
+    /opt/conda/bin/pip install -r /tmp/requirements.txt && \
+    conda clean -y --all && \
+    conda env export -n "root" && \
+    jupyter lab build 
+
+COPY jupyter_notebook_config.py ${HOME}/.jupyter/
+
+# copy dash app
+COPY app ${HOME}/app/
+RUN chown -R jovyan ${HOME}/app/
 
-# RUN pip3 install --upgrade pip
-RUN pip install jupyter-server-proxy==4.0.0
-RUN pip install jupyterlab-git==0.42.0
-RUN pip install jupyterlab-gitlab==3.0.0
diff --git a/README.md b/README.md
index 38011d6..0afc659 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,2 @@
-# bücker
+# A Jupyterlab for LLM
 
diff --git a/app/app.py b/app/app.py
new file mode 100644
index 0000000..4975d67
--- /dev/null
+++ b/app/app.py
@@ -0,0 +1,44 @@
+import sys 
+sys.path.append("/home/jovyan")
+
+import argparse
+import logging
+
+from dash import Dash
+
+from layout import layout
+from callbacks import register_callbacks
+
+logging.basicConfig(level=logging.INFO)
+
+
+# get the correct port from proxy
+parser = argparse.ArgumentParser()
+parser.add_argument("--port", type=int)
+args = parser.parse_args()
+port: int = args.port
+
+if not port:
+    raise ValueError(f"Port of proxy server for Dash not found in {args}.")
+else: 
+    logging.debug(f"Dash app running on port {port}.")
+
+# define Dash app
+app = Dash(
+    name=__name__, 
+    requests_pathname_prefix="/dash/"
+)
+
+# define layout
+app.layout = layout
+
+# register all callback functions
+register_callbacks(app=app)
+
+# Run Dash app in the notebook
+app.run(
+    jupyter_mode="jupyterlab", 
+    port=port, 
+    host="localhost",
+    debug=True
+)
diff --git a/app/callbacks.py b/app/callbacks.py
new file mode 100644
index 0000000..9d22226
--- /dev/null
+++ b/app/callbacks.py
@@ -0,0 +1,23 @@
+from dash import (
+    html, 
+    Dash
+)
+from dash.dependencies import (
+    Input, 
+    Output, 
+    State
+)
+
+
+def register_callbacks(app: Dash):
+    @app.callback(
+        Output("output-container", "children"),
+        [Input("send-button", "n_clicks")],
+        [State("input-text", "value")]
+    )
+    def generate_response(n_clicks, input_text):
+        if n_clicks > 0:
+            response = "You said: " + input_text
+            return html.Div(response)
+        else:
+            return ""
diff --git a/app/layout.py b/app/layout.py
new file mode 100644
index 0000000..fbc93fa
--- /dev/null
+++ b/app/layout.py
@@ -0,0 +1,14 @@
+from dash import (
+    html, 
+    dcc
+)
+
+layout = html.Div(
+    className="container",
+    children=[
+        html.H1("GPT Chat", className="mt-5 mb-4"),
+        dcc.Textarea(id="input-text", placeholder="Enter your message:", className="form-control mb-3"),
+        html.Button("Send", id="send-button", n_clicks=0, className="btn btn-primary mb-3"),
+        html.Div(id="output-container")
+    ]
+)
diff --git a/environment.yml b/environment.yml
new file mode 100644
index 0000000..eef32e1
--- /dev/null
+++ b/environment.yml
@@ -0,0 +1,7 @@
+name: "base"
+channels:
+  - defaults
+# dependencies:
+# - add packages here
+# - one per line
+prefix: "/opt/conda"
diff --git a/jupyter_notebook_config.py b/jupyter_notebook_config.py
new file mode 100644
index 0000000..22208d3
--- /dev/null
+++ b/jupyter_notebook_config.py
@@ -0,0 +1,13 @@
+# Configuration file for jupyter-notebook.
+c.ServerProxy.servers = {
+    'dash': {
+        'command': [
+            'python',
+            'app/app.py',
+            '--port',
+            '{port}'
+        ],
+        'absolute_url': False,
+        'new_browser_tab': False
+    }
+}
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..cf2d387
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,12 @@
+jupyter-server-proxy==4.0.0
+jupyterlab-git==0.42.0
+jupyter_server>=2.0
+
+dash
+dash-bootstrap-components
+plotly
+
+openai
+rapidfuzz
+
+python-dotenv
-- 
GitLab