From d88ca833170e6815e40689e5e8ce411a02111396 Mon Sep 17 00:00:00 2001 From: Anil Vishnoi Date: Tue, 10 Sep 2024 11:52:45 -0700 Subject: [PATCH] Remove UI component. It's now hosted in instructlab/ui repository Signed-off-by: Anil Vishnoi --- .ansible-lint | 1 - .github/workflows/images.yml | 82 --- .github/workflows/lint-ui.yml | 39 -- .markdownlint-cli2.yaml | 2 - CONTRIBUTING.md | 10 +- Makefile | 26 +- deploy/ansible/README.md | 8 - deploy/ansible/deploy-ui-stack.yml | 18 - deploy/ansible/ui/tasks/main.yaml | 31 - deploy/compose/dev-single-worker-with-ui.yaml | 58 -- docs/dev-env.md | 32 -- ui/.editorconfig | 17 - ui/.env.example | 14 - ui/.eslintrc.json | 22 - ui/.prettierignore | 2 - ui/.prettierrc | 9 - ui/Containerfile | 10 - ui/README.md | 199 ------- ui/apiserver/Containerfile | 43 -- ui/apiserver/Containerfile.chat-with-gpu | 57 -- ui/apiserver/apiserver.go | 493 ---------------- ui/apiserver/go.mod | 42 -- ui/apiserver/go.sum | 127 ---- ui/compose.ui | 83 --- ui/envConfig.ts | 5 - ui/next-env.d.ts | 5 - ui/next.config.js | 7 - ui/package.json | 55 -- ui/public/InstructLab-Logo.svg | 5 - ui/public/bot-icon-chat-32x32.svg | 53 -- ui/public/favicon.ico | Bin 25931 -> 0 bytes ui/public/login-bg.svg | 4 - ui/src/app/404.tsx | 16 - ui/src/app/api/auth/[...nextauth]/route.ts | 120 ---- ui/src/app/api/envConfig/route.ts | 13 - ui/src/app/api/jobs/route.ts | 34 -- ui/src/app/api/playground/chat/route.ts | 103 ---- ui/src/app/api/playground/devchat/route.ts | 95 --- ui/src/app/api/pr/knowledge/route.ts | 36 -- ui/src/app/api/pr/skill/route.ts | 36 -- ui/src/app/contribute/knowledge/page.tsx | 14 - ui/src/app/contribute/skill/page.tsx | 14 - ui/src/app/dashboard/page.tsx | 14 - ui/src/app/error/error.module.css | 41 -- ui/src/app/error/page.tsx | 42 -- ui/src/app/index.tsx | 17 - ui/src/app/jobs/all/page.tsx | 14 - ui/src/app/jobs/failed/page.tsx | 14 - ui/src/app/jobs/pending/page.tsx | 14 - ui/src/app/jobs/running/page.tsx | 14 - ui/src/app/jobs/success/page.tsx | 14 - ui/src/app/layout.tsx | 23 - ui/src/app/login/page.tsx | 109 ---- ui/src/app/page.tsx | 16 - ui/src/app/playground/chat/chat.module.css | 137 ----- ui/src/app/playground/chat/page.tsx | 303 ---------- ui/src/app/playground/devchat/handlers.ts | 127 ---- ui/src/app/playground/devchat/page.tsx | 544 ------------------ .../playground/devchat/playground.module.css | 143 ----- .../playground/devchat/useModelSelector.ts | 75 --- ui/src/app/playground/endpoints/page.tsx | 201 ------- ui/src/common/DisplayColumns.tsx | 16 - ui/src/common/HooksApiServer.tsx | 38 -- ui/src/common/HooksPostChat.tsx | 38 -- ui/src/common/HooksPostKnowledgePR.tsx | 54 -- ui/src/common/HooksPostSkillPR.tsx | 50 -- ui/src/common/JobsLayout.tsx | 10 - ui/src/components/AppLayout.tsx | 162 ------ .../components/ChartJobDistribution/index.tsx | 76 --- ui/src/components/ChartJobDuration/index.tsx | 63 -- ui/src/components/ClientProviders.tsx | 20 - .../components/Contribute/Knowledge/index.tsx | 399 ------------- .../Contribute/Knowledge/knowledge.css | 24 - ui/src/components/Contribute/Skill/index.tsx | 351 ----------- ui/src/components/Contribute/Skill/skill.css | 24 - .../CopyToClipboardButton/index.tsx | 47 -- ui/src/components/CurlCommandModal/index.tsx | 99 ---- ui/src/components/Dashboard/index.tsx | 36 -- ui/src/components/Jobs/All/index.tsx | 141 ----- ui/src/components/Jobs/Failed/index.tsx | 140 ----- ui/src/components/Jobs/Pending/index.tsx | 140 ----- ui/src/components/Jobs/Running/index.tsx | 143 ----- ui/src/components/Jobs/Success/index.tsx | 142 ----- ui/src/components/ThemeToggle/ThemeToggle.tsx | 22 - ui/src/context/ThemeContext.tsx | 26 - ui/src/favicon.ico | Bin 25931 -> 0 bytes ui/src/types/index.ts | 19 - ui/src/utils/dateUtils.ts | 15 - ui/src/utils/tableUtils.ts | 27 - ui/stylePaths.js | 17 - ui/tsconfig.json | 29 - 91 files changed, 5 insertions(+), 6265 deletions(-) delete mode 100644 .github/workflows/lint-ui.yml delete mode 100644 deploy/ansible/deploy-ui-stack.yml delete mode 100644 deploy/ansible/ui/tasks/main.yaml delete mode 100644 deploy/compose/dev-single-worker-with-ui.yaml delete mode 100644 ui/.editorconfig delete mode 100644 ui/.env.example delete mode 100644 ui/.eslintrc.json delete mode 100644 ui/.prettierignore delete mode 100644 ui/.prettierrc delete mode 100644 ui/Containerfile delete mode 100644 ui/README.md delete mode 100644 ui/apiserver/Containerfile delete mode 100644 ui/apiserver/Containerfile.chat-with-gpu delete mode 100644 ui/apiserver/apiserver.go delete mode 100644 ui/apiserver/go.mod delete mode 100644 ui/apiserver/go.sum delete mode 100644 ui/compose.ui delete mode 100644 ui/envConfig.ts delete mode 100644 ui/next-env.d.ts delete mode 100644 ui/next.config.js delete mode 100644 ui/package.json delete mode 100644 ui/public/InstructLab-Logo.svg delete mode 100644 ui/public/bot-icon-chat-32x32.svg delete mode 100644 ui/public/favicon.ico delete mode 100644 ui/public/login-bg.svg delete mode 100644 ui/src/app/404.tsx delete mode 100644 ui/src/app/api/auth/[...nextauth]/route.ts delete mode 100644 ui/src/app/api/envConfig/route.ts delete mode 100644 ui/src/app/api/jobs/route.ts delete mode 100644 ui/src/app/api/playground/chat/route.ts delete mode 100644 ui/src/app/api/playground/devchat/route.ts delete mode 100644 ui/src/app/api/pr/knowledge/route.ts delete mode 100644 ui/src/app/api/pr/skill/route.ts delete mode 100644 ui/src/app/contribute/knowledge/page.tsx delete mode 100644 ui/src/app/contribute/skill/page.tsx delete mode 100644 ui/src/app/dashboard/page.tsx delete mode 100644 ui/src/app/error/error.module.css delete mode 100644 ui/src/app/error/page.tsx delete mode 100644 ui/src/app/index.tsx delete mode 100644 ui/src/app/jobs/all/page.tsx delete mode 100644 ui/src/app/jobs/failed/page.tsx delete mode 100644 ui/src/app/jobs/pending/page.tsx delete mode 100644 ui/src/app/jobs/running/page.tsx delete mode 100644 ui/src/app/jobs/success/page.tsx delete mode 100644 ui/src/app/layout.tsx delete mode 100644 ui/src/app/login/page.tsx delete mode 100644 ui/src/app/page.tsx delete mode 100644 ui/src/app/playground/chat/chat.module.css delete mode 100644 ui/src/app/playground/chat/page.tsx delete mode 100644 ui/src/app/playground/devchat/handlers.ts delete mode 100644 ui/src/app/playground/devchat/page.tsx delete mode 100644 ui/src/app/playground/devchat/playground.module.css delete mode 100644 ui/src/app/playground/devchat/useModelSelector.ts delete mode 100644 ui/src/app/playground/endpoints/page.tsx delete mode 100644 ui/src/common/DisplayColumns.tsx delete mode 100644 ui/src/common/HooksApiServer.tsx delete mode 100644 ui/src/common/HooksPostChat.tsx delete mode 100644 ui/src/common/HooksPostKnowledgePR.tsx delete mode 100644 ui/src/common/HooksPostSkillPR.tsx delete mode 100644 ui/src/common/JobsLayout.tsx delete mode 100644 ui/src/components/AppLayout.tsx delete mode 100644 ui/src/components/ChartJobDistribution/index.tsx delete mode 100644 ui/src/components/ChartJobDuration/index.tsx delete mode 100644 ui/src/components/ClientProviders.tsx delete mode 100644 ui/src/components/Contribute/Knowledge/index.tsx delete mode 100644 ui/src/components/Contribute/Knowledge/knowledge.css delete mode 100644 ui/src/components/Contribute/Skill/index.tsx delete mode 100644 ui/src/components/Contribute/Skill/skill.css delete mode 100644 ui/src/components/CopyToClipboardButton/index.tsx delete mode 100644 ui/src/components/CurlCommandModal/index.tsx delete mode 100644 ui/src/components/Dashboard/index.tsx delete mode 100644 ui/src/components/Jobs/All/index.tsx delete mode 100644 ui/src/components/Jobs/Failed/index.tsx delete mode 100644 ui/src/components/Jobs/Pending/index.tsx delete mode 100644 ui/src/components/Jobs/Running/index.tsx delete mode 100644 ui/src/components/Jobs/Success/index.tsx delete mode 100644 ui/src/components/ThemeToggle/ThemeToggle.tsx delete mode 100644 ui/src/context/ThemeContext.tsx delete mode 100644 ui/src/favicon.ico delete mode 100644 ui/src/types/index.ts delete mode 100644 ui/src/utils/dateUtils.ts delete mode 100644 ui/src/utils/tableUtils.ts delete mode 100644 ui/stylePaths.js delete mode 100644 ui/tsconfig.json diff --git a/.ansible-lint b/.ansible-lint index 6fbec00d..cfa7a802 100644 --- a/.ansible-lint +++ b/.ansible-lint @@ -1,4 +1,3 @@ exclude_paths: - compose.yaml - .github/ - - ui/ diff --git a/.github/workflows/images.yml b/.github/workflows/images.yml index 7faf1831..ea9e30a6 100644 --- a/.github/workflows/images.yml +++ b/.github/workflows/images.yml @@ -48,88 +48,6 @@ jobs: cache-to: type=gha,mode=max file: gobot/Containerfile - push_to_registries_ui: - name: Push UI container image to GHCR - runs-on: ubuntu-latest - permissions: - packages: write - contents: read - steps: - - name: Check out the repo - uses: actions/checkout@v4 - - - name: Log in to the Container registry - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - uses: docker/setup-buildx-action@v3 - - - name: Extract metadata (tags, labels) for UI image - id: ui_meta - uses: docker/metadata-action@v5 - with: - images: | - ghcr.io/${{ github.repository }}/bot-ui - - - name: Build and push ui image - uses: docker/build-push-action@v6 - with: - context: . - platforms: linux/amd64,linux/arm64 - build-args: | - GITHUB_USER=instructlab-bot - GITHUB_TOKEN=${{ secrets.BOT_GITHUB_TOKEN }} - push: true - tags: ${{ steps.ui_meta.outputs.tags }} - labels: ${{ steps.ui_meta.outputs.labels }} - cache-from: type=gha - cache-to: type=gha,mode=max - file: ui/Containerfile - - push_to_registries_apiserver: - name: Push apiserver container image to GHCR - runs-on: ubuntu-latest - permissions: - packages: write - contents: read - steps: - - name: Check out the repo - uses: actions/checkout@v4 - - - name: Log in to the Container registry - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - uses: docker/setup-buildx-action@v3 - - - name: Extract metadata (tags, labels) for apiserver image - id: apiserver_meta - uses: docker/metadata-action@v5 - with: - images: | - ghcr.io/${{ github.repository }}/apiserver - - - name: Build and push apiserver image - uses: docker/build-push-action@v6 - with: - context: . - platforms: linux/amd64,linux/arm64 - build-args: | - GITHUB_USER=instructlab-bot - GITHUB_TOKEN=${{ secrets.BOT_GITHUB_TOKEN }} - push: true - tags: ${{ steps.apiserver_meta.outputs.tags }} - labels: ${{ steps.apiserver_meta.outputs.labels }} - cache-from: type=gha - cache-to: type=gha,mode=max - file: ui/apiserver/Containerfile - push_to_registries_serve: name: Push serve container image to GHCR runs-on: ubuntu-latest diff --git a/.github/workflows/lint-ui.yml b/.github/workflows/lint-ui.yml deleted file mode 100644 index 37d5ed05..00000000 --- a/.github/workflows/lint-ui.yml +++ /dev/null @@ -1,39 +0,0 @@ -name: Lint UI changes - -on: - push: - branches: ["main"] - paths: - - '.github/workflows/lint-ui.yml' - - 'ui/*' - - '!ui/README.md' - pull_request: - branches: ["main"] - paths: - - '.github/workflows/lint-ui.yml' - - 'ui/*' - - '!ui/README.md' - -concurrency: - group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: true - -jobs: - npm-lint: - runs-on: ubuntu-22.04 - steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Setup Node - uses: actions/setup-node@v4 - with: - node-version: '20' - - name: Install dependencies - run: npm install - working-directory: ui - - name: Run UI linting - run: npm run lint - working-directory: ui - - name: Run UI type check - run: npm run type-check - working-directory: ui diff --git a/.markdownlint-cli2.yaml b/.markdownlint-cli2.yaml index e96626e6..ff3647ca 100644 --- a/.markdownlint-cli2.yaml +++ b/.markdownlint-cli2.yaml @@ -9,5 +9,3 @@ globs: - "**/*.md" ignores: - "pkg" - - "**/node_modules/*" - - "**/node_modules/**" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f6ebb812..00d1dff8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -17,12 +17,10 @@ We'd also love PRs. If you're thinking of a large PR, we advise opening up an is ## Submitting a pull request 1. [Fork][fork] and clone the repository. -1. Configure and install the dependencies: `npm install`. -1. Make sure the tests pass on your machine: `npm test`, note: these tests also apply the linter, so there's no need to lint separately. -1. Create a new branch: `git checkout -b my-branch-name`. -1. Make your change, add tests, and make sure the tests still pass. -1. Push to your fork and [submit a pull request][pr]. -1. Pat your self on the back and wait for your pull request to be reviewed and merged. +2. Create a new branch: `git checkout -b my-branch-name`. +3. Make your change, add tests, and make sure the tests still pass. +4. Push to your fork and [submit a pull request][pr]. +5. Pat your self on the back and wait for your pull request to be reviewed and merged. Here are a few things you can do that will increase the likelihood of your pull request being accepted: diff --git a/Makefile b/Makefile index 183c9114..8f3e69a0 100644 --- a/Makefile +++ b/Makefile @@ -100,15 +100,7 @@ ilabserve-base-image: worker/Containerfile.servebase ## Build container image fo $(ECHO_PREFIX) printf " %-12s worker/Containerfile.servebase\n" "[PODMAN]" $(CMD_PREFIX) podman build -f worker/Containerfile.servebase -t ghcr.io/instructlab/instructlab-bot/instructlab-serve-base:main . -apiserver-image: ui/apiserver/Containerfile ## Build continaer image for the Apiserver - $(ECHO_PREFIX) printf " %-12s ui/apiserver/Containerfile\n" "[PODMAN]" - $(CMD_PREFIX) podman build -f ui/apiserver/Containerfile -t ghcr.io/instructlab/instructlab-bot/apiserver:main . - -ui-image: ui/Containerfile ## Build continaer image for the bot ui - $(ECHO_PREFIX) printf " %-12s ui/Containerfile\n" "[PODMAN]" - $(CMD_PREFIX) podman build -f ui/Containerfile -t ghcr.io/instructlab/instructlab-bot/bot-ui:main . - -all-images: gobot-image worker-test-image apiserver-image ui-image ## Build all container images +all-images: gobot-image worker-test-image ## Build all container images $(ECHO_PREFIX) printf " %-12s BUILD ALL CONTAINER IMAGES\n" .PHONY: gobot @@ -154,28 +146,12 @@ run-dev: ## Deploy the bot development stack. $(ECHO_PREFIX) printf "Deploy the development stack\n" $(CMD_PREFIX) podman compose -f ./deploy/compose/dev-single-worker-compose.yaml up -d -.PHONY: run-dev-ui -run-dev-ui: ## Deploy the bot development stack with the UI components. - $(ECHO_PREFIX) printf " %-12s \n" "[RUN DEV UI STACK]" - $(CMD_PREFIX) if [ ! -f .env ]; then \ - echo ".env not found. Copy .env.example to .env and configure it." ; \ - exit 1 ; \ - fi - $(ECHO_PREFIX) printf "Deploy the development stack with UI components\n" - $(CMD_PREFIX) podman compose -f ./deploy/compose/dev-single-worker-with-ui.yaml up -d - .PHONY: stop-dev stop-dev: ## Stop the bot development stack. $(ECHO_PREFIX) printf " %-12s \n" "[STOP DEV STACK]" $(ECHO_PREFIX) printf "Stop the development stack\n" $(CMD_PREFIX) podman compose -f ./deploy/compose/dev-single-worker-compose.yaml down -.PHONY: stop-dev-ui -stop-dev-ui: ## Stop the bot development stack with the UI components. - $(ECHO_PREFIX) printf " %-12s \n" "[STOP DEV UI STACK]" - $(ECHO_PREFIX) printf "Stop the development stack with UI components\n" - $(CMD_PREFIX) podman compose -f ./deploy/compose/dev-single-worker-with-ui.yaml down - .PHONY: redis-stack redis-stack: ## Run a redis-stack container $(ECHO_PREFIX) printf " %-12s redis/redis-stack:latest\n" "[PODMAN]" diff --git a/deploy/ansible/README.md b/deploy/ansible/README.md index 9e50ab20..06ac5ef4 100644 --- a/deploy/ansible/README.md +++ b/deploy/ansible/README.md @@ -117,14 +117,6 @@ This playbook installs all the components in the containers. ansible-playbook -i inventory.txt -e @secrets.enc --ask-vault-pass deploy-bot-stack.yml ``` -## Install the UI stack that works with the Bot stack - -This playbook installs all the required UI components in the containers. - -```console -ansible-playbook -i inventory.txt -e @secrets.enc --ask-vault-pass deploy-ui-stack.yml -``` - ## Install the Worker stack (first time installation) This playbook installs all the required component on the host itself diff --git a/deploy/ansible/deploy-ui-stack.yml b/deploy/ansible/deploy-ui-stack.yml deleted file mode 100644 index 02d967ad..00000000 --- a/deploy/ansible/deploy-ui-stack.yml +++ /dev/null @@ -1,18 +0,0 @@ -# Description: This file is used to deploy the UI stack on the bot node. -# It assumes that the gobot and redis is already deployed on the bot node. -- name: Deploy UI stack on bot node - hosts: botNode - roles: - - role: geerlingguy.docker - become: true - - role: packages - become: true - - role: nexodus - become: true - - role: ui - become: true - vars_files: - - vars.yml - environment: - API_USER: "${API_USER:-}" - API_PASS: "${API_PASS:-}" diff --git a/deploy/ansible/ui/tasks/main.yaml b/deploy/ansible/ui/tasks/main.yaml deleted file mode 100644 index fb995595..00000000 --- a/deploy/ansible/ui/tasks/main.yaml +++ /dev/null @@ -1,31 +0,0 @@ ---- -- name: Log into GHCR - community.docker.docker_login: - registry_url: ghcr.io - username: instructlab-bot - password: "{{ github_token }}" - reauthorize: true - -- name: Start the apiserver container - community.docker.docker_container: - name: apiserver - image: ghcr.io/instructlab/instructlab-bot/apiserver:main - state: started - pull: always - env: - LISTEN_ADDRESS: "${LISTEN_ADDRESS:-:3000}" - REDIS_SERVER: "${REDIS_SERVER:-redis:6379}" - DEBUG_MODE: "${DEBUG_MODE:-false}" - TEST_MODE: "${TEST_MODE:-false}" - BOT_URL: "${BOT_URL:-http://instructlab-bot:8081}" - ports: - - 3000:3000 - -- name: Start the ui container - community.docker.docker_container: - name: ui - image: ghcr.io/instructlab/instructlab-bot/bot-ui:main - state: started - pull: always - ports: - - 8080:8080 diff --git a/deploy/compose/dev-single-worker-with-ui.yaml b/deploy/compose/dev-single-worker-with-ui.yaml deleted file mode 100644 index ac54e988..00000000 --- a/deploy/compose/dev-single-worker-with-ui.yaml +++ /dev/null @@ -1,58 +0,0 @@ -version: "3.4" - -services: - redis: - container_name: redis - image: redis:latest - ports: - - 6379:6379 - - bot: - container_name: bot - image: ghcr.io/instructlab/instructlab-bot/instructlab-gobot:main - env_file: - - ../../.env - depends_on: - - redis - ports: - - 8081:8081 - - - bot-ui: - container_name: ui - image: ghcr.io/instructlab/instructlab-bot/bot-ui:main - ports: - - 8080:8080 - - apiserver: - container_name: apiserver - image: ghcr.io/instructlab/instructlab-bot/apiserver:main - depends_on: - - redis - environment: - # Bind on all interface - LISTEN_ADDRESS: "${LISTEN_ADDRESS:-:3000}" - REDIS_SERVER: "${REDIS_SERVER:-redis:6379}" - API_USER: "${API_USER:-kitteh}" - API_PASS: "${API_PASS:-floofykittens}" - DEBUG_MODE: "${DEBUG_MODE:-true}" - TEST_MODE: "${TEST_MODE:-true}" - BOT_URL: "${BOT_URL:-http://bot:8081}" - ports: - - 3000:3000 - - worker-test: - container_name: worker-test - image: ghcr.io/instructlab/instructlab-bot/instructlab-serve:main - depends_on: - - redis - env_file: - - ../../.env - command: - [ - "/instructlab-bot-worker", - "--test", - "--redis", - "redis:6379", - "generate", - ] diff --git a/docs/dev-env.md b/docs/dev-env.md index 0fff2476..14b154db 100644 --- a/docs/dev-env.md +++ b/docs/dev-env.md @@ -85,38 +85,6 @@ To destroy the stack: make stop-dev ``` -## Setup local development deployment with UI components - -If you want to deploy the bot with the UI components, you need to do the following steps: - -1) Build the ui and apiserver images and set the `/ui/.env`. That .env file will be copied into the container at build time, it needs to be edited before building the image. - - ```text - IL_UI_ADMIN_USERNAME= - IL_UI_ADMIN_PASSWORD= - IL_UI_API_SERVER_USERNAME= - IL_UI_API_SERVER_PASSWORD= - IL_UI_API_SERVER_URL=http://localhost:3000/jobs # Keep this as is. - ``` - -2) Build the images - - ```bash - make all-images - ``` - -3) Run the stack - - ```bash - make run-dev-ui - ``` - -To destroy the stack: - -```bash -make stop-dev-ui -``` - ## Setup testing deployment We use ansible for deploying this setup on the AWS cloud. To deploy this setup, you will need the following to be present on your local machine: diff --git a/ui/.editorconfig b/ui/.editorconfig deleted file mode 100644 index b7eb8409..00000000 --- a/ui/.editorconfig +++ /dev/null @@ -1,17 +0,0 @@ -# Editor configuration, see http://editorconfig.org -root = true - -[*] -charset = utf-8 -indent_style = space -indent_size = 2 -insert_final_newline = true -trim_trailing_whitespace = true - -[*.snap] -max_line_length = off -trim_trailing_whitespace = false - -[*.md] -max_line_length = off -trim_trailing_whitespace = false diff --git a/ui/.env.example b/ui/.env.example deleted file mode 100644 index aee17b08..00000000 --- a/ui/.env.example +++ /dev/null @@ -1,14 +0,0 @@ -IL_UI_ADMIN_USERNAME=admin -IL_UI_ADMIN_PASSWORD=password -IL_UI_API_SERVER_USERNAME=kitteh -IL_UI_API_SERVER_PASSWORD=floofykittens -IL_UI_API_SERVER_URL=http://:8000 -OAUTH_GITHUB_ID= -OAUTH_GITHUB_SECRET= -NEXTAUTH_SECRET= -NEXTAUTH_URL=http://: -IL_GRANITE_API= -IL_GRANITE_MODEL_NAME= -IL_MERLINITE_API= -IL_MERLINITE_MODEL_NAME= -GITHUB_TOKEN= diff --git a/ui/.eslintrc.json b/ui/.eslintrc.json deleted file mode 100644 index 3a1fc1c6..00000000 --- a/ui/.eslintrc.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "extends": [ - "next/core-web-vitals", - "prettier", - "@redhat-cloud-services/eslint-config-redhat-cloud-services", - "eslint:recommended", - "plugin:@typescript-eslint/recommended", - "plugin:react/recommended", - "next", - "plugin:react-hooks/recommended", - "plugin:@next/next/recommended" - ], - "rules": { - "prettier/prettier": "error" - }, - "settings": { - "react": { - "version": "detect" - } - } -} - diff --git a/ui/.prettierignore b/ui/.prettierignore deleted file mode 100644 index 8513a980..00000000 --- a/ui/.prettierignore +++ /dev/null @@ -1,2 +0,0 @@ -package.json -.next diff --git a/ui/.prettierrc b/ui/.prettierrc deleted file mode 100644 index 7a400096..00000000 --- a/ui/.prettierrc +++ /dev/null @@ -1,9 +0,0 @@ -{ - "printWidth": 150, - "arrowParens": "always", - "semi": true, - "tabWidth": 2, - "singleQuote": true, - "jsxSingleQuote": false, - "bracketSpacing": true -} diff --git a/ui/Containerfile b/ui/Containerfile deleted file mode 100644 index b8df9ca5..00000000 --- a/ui/Containerfile +++ /dev/null @@ -1,10 +0,0 @@ -FROM node:22-alpine - -WORKDIR /app - -COPY ui/package*.json ./ -RUN npm install -COPY ui/ . - -RUN npm run build -CMD ["npm", "run", "start"] diff --git a/ui/README.md b/ui/README.md deleted file mode 100644 index 22087a6a..00000000 --- a/ui/README.md +++ /dev/null @@ -1,199 +0,0 @@ -# InstructLab Bot UI - -This is a [Patternfly](https://www.patternfly.org/get-started/develop/) react -deployment for front-ending InstructLab Bot jobs. The framework is based off -[patternfly-react-seed](https://github.com/patternfly/patternfly-react-seed) but -upgraded to use the latest React v6+. The data is all read only from redis, via -the api-server service. - -## Quickstart - -- Build the ui and apiserver images and set the `/ui/.env`. That .env file will - be copied into the container at build time, it needs to be edited before - building the image. - -> Note: Since the UI and API server need to be reachable via host networking in -> this compose file configuration, this needs to be run on Linux since OSX -> container runtimes are userspace and don't support host networking. - -```shell -podman build -f ui/apiserver/Containerfile -t ghcr.io/instructlab/instructlab-bot/apiserver:main . -podman build -f ui/Containerfile -t ghcr.io/instructlab/instructlab-bot/bot-ui:main . -``` - -- Run the [compose.ui](compose.ui). - -## Manually Running the API Server - -To start the api server manually, run the following with some example values. -The client needs to be able to reach the apiserver. If running in a container -and trying to reach the host from a remote site, bind to `--listen-address :3000`. -If all connections are local you could use `--listen-address localhost:3000`. - -```bash -cd ui/apiserver -go run apiserver.go \ - --redis-server localhost:6379 \ - --listen-address :3000 \ - --api-user kitteh \ - --api-pass floofykittens \ - --debug -``` - -## Manually Running the React UI - -To start the UI manually instead of in a container, set the .env in the ui -directory and run the following: - -```bash -cd ui/ -npm run dev -# or for prod -npm run build -npm run start -``` - -## Authentication - -You can either set up the Oauth app in your -[GitHub](https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/creating-an-oauth-app) -account or use the user/pass defined in `.env`. To change those defaults, create -the `/ui/.env` file and fill in the account user/pass with the following. The -same applies to the websocket address of the api-server service. - -Example [.env](.env.example) file. - -```text -IL_UI_ADMIN_USERNAME=admin -IL_UI_ADMIN_PASSWORD=password -IL_UI_API_SERVER_USERNAME= -IL_UI_API_SERVER_PASSWORD= -IL_UI_API_SERVER_URL=http://: -IL_UI_API_CHAT_URL=http:///: -GITHUB_ID= -GITHUB_SECRET= -NEXTAUTH_SECRET= -NEXTAUTH_URL=http://: -``` - -## Development Scripts - -```bash -# Install development/build dependencies -npm install - -# Start the development server -npm run dev - -# Run a production build (outputs to ".next" dir) -npm run build - -# Start the Next.js server (run a production build) -npm run start - -# Lint the project -npm run lint - -# Automatically fix linting issues -npm run lint:fix - -# Format code using Prettier -npm run pretty -``` - -### Summary of Server-Side Rendering and Client-Side Data Handling for Jobs and Chat Routes - -We are leveraging Next.js's app router to handle -[server-side rendering](https://nextjs.org/docs/pages/building-your-application/rendering/server-side-rendering) -(SSR) and client-side data interactions for both jobs and chat functionalities. -Below is a summary of how we manage server-side rendering and client-side data -handling for these routes. - -#### Server-Side Rendering (SSR) - -**API Routes**: - -- We have dedicated API routes for both jobs and chat functionalities that - handle data fetching from the backend. These routes ensure that the data is - sourced from the server. -- The API routes use environment variables to authenticate and interact with the - backend services securely. - -**Server Components**: - -- Components within the `app` directory are treated as server components by - default. These components handle the initial rendering on the server side. -- For pages like jobs and chat, the main page components are designed to be - server components, ensuring that the initial data rendering is performed on - the server. - -#### Client-Side Data Handling - -**Client Components**: - -- Components that utilize client-side hooks (`useState`, `useEffect`, `useRef`, - etc.) are explicitly marked with `'use client'` to indicate they should be - executed on the client side. -- These components are responsible for interacting with the API routes to fetch - and update data dynamically after the initial server-side rendering. - -**Custom Hooks**: - -- Custom hooks, such as `useFetchJobs` and `usePostChat`, encapsulate the logic - for API interactions. These hooks handle the state management and side effects - associated with fetching or posting data. -- By using these hooks, we maintain a clean separation of concerns, keeping the - components focused on rendering and user interaction. - -#### Jobs Functionality - -- **API Route**: The jobs API route fetches job data from the backend and - provides it to the front-end components. -- **Server Component**: The jobs page component fetches the job data server-side - during the initial render. -- **Client Component**: The jobs list component, marked as a client component, - uses the `useFetchJobs` hook to handle dynamic data fetching and updating in - real-time. - -#### Chat Functionality - -- **API Route**: The chat API route handles posting chat messages to the backend - and retrieving responses. -- **Server Component**: The chat page component sets up the overall layout and - structure, rendered server-side initially. -- **Client Component**: The chat form component, marked as a client component, - uses the `usePostChat` hook to handle user interactions, sending messages to - the API, and displaying responses dynamically. - -### Key Points - -- **Separation of Concerns**: By distinguishing between server and client - components, we ensure that server-side rendering is leveraged for the initial - load, while client-side components manage dynamic data interactions. -- **API Integration**: The use of API routes ensures secure and efficient - communication between the front-end and back-end services. -- **Custom Hooks**: Encapsulating data fetching and state management logic in - custom hooks promotes code reusability and maintainability. -- **Explicit Client Components**: Marking components with `'use client'` where - necessary clarifies their role and ensures correct execution context, avoiding - common pitfalls in SSR and CSR (client-side rendering) integration. - -This setup ensures that our application benefits from the performance advantages -of server-side rendering, while still providing a responsive and dynamic user -experience through client-side interactions. - -1. **API Route**: The API route fetches job data from the backend and provides it - to the client. This is already handled correctly with server-side logic. - -2. **Hook for Fetching Jobs**: The `useFetchJobs` hook fetches data from the API. - This is used within a client component since it utilizes React hooks like - `useState` and `useEffect`. - -3. **Jobs Component**: The `AllJobs` component fetches job data using the - `useFetchJobs` hook. This component is a client component. - -4. **Jobs Page Component**: The `AllJobsPage` component renders the `AllJobs` - component within the `AppLayout`. This component is a server component to - leverage SSR. - -The same pattern applies to chat calls to the apiserver. diff --git a/ui/apiserver/Containerfile b/ui/apiserver/Containerfile deleted file mode 100644 index 47501c4b..00000000 --- a/ui/apiserver/Containerfile +++ /dev/null @@ -1,43 +0,0 @@ -# apiserver Containerfile -FROM golang:latest as builder - -ENV WORK_DIR /app - -WORKDIR ${WORK_DIR} - -COPY . ${WORK_DIR}/instructlab-bot - -WORKDIR ${WORK_DIR}/instructlab-bot/ui/apiserver - -# Build the worker binary -RUN go build -o apiserver apiserver.go && \ - chmod +x apiserver - -# Build the apiserver -RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o apiserver . - -# Stage 2: Fedora base image -FROM fedora:latest - -# Install ILab dependencies -RUN dnf update -y && \ - dnf install -y g++ gcc make python3 python3-devel python3-pip git && \ - dnf clean all - -# Set up the Python virtual environment -RUN python3 -m venv /app/venv -ENV PATH="/app/venv/bin:$PATH" - -# Install Python packages and ILab -RUN pip install --upgrade pip && \ - pip cache remove llama_cpp_python && \ - pip install git+https://github.com/instructlab/instructlab.git@stable --extra-index-url=https://download.pytorch.org/whl/cpu - -# Mounted work directory containing certs and config.yaml -WORKDIR /data - -# Copy the Go binary from the builder stage -COPY --from=builder /app/instructlab-bot/ui/apiserver/apiserver /usr/local/bin/apiserver - -# Run the apiserver binary with environment variables -CMD /usr/local/bin/apiserver --listen-address=${LISTEN_ADDRESS:-localhost:3000} --bot-url ${BOT_URL:-http://instructlab-bot:8081} --redis-server=${REDIS_SERVER:-localhost:6379} --api-user=${API_USER:-kitteh} --api-pass=${API_PASS:-floofykittens} --debug=${DEBUG_MODE:-false} --test-mode=${TEST_MODE:-false} diff --git a/ui/apiserver/Containerfile.chat-with-gpu b/ui/apiserver/Containerfile.chat-with-gpu deleted file mode 100644 index 4655e4a6..00000000 --- a/ui/apiserver/Containerfile.chat-with-gpu +++ /dev/null @@ -1,57 +0,0 @@ -# Stage 1: Build the worker binary -FROM golang:latest as builder - -ENV WORK_DIR /app - -WORKDIR ${WORK_DIR} - -COPY . ${WORK_DIR}/instructlab-bot - -WORKDIR ${WORK_DIR}/instructlab-bot/ui/apiserver - -# Build the worker binary -RUN go build -o apiserver apiserver.go && \ - chmod +x apiserver - -# Stage 2: Setup the base environment with CUDA and dependencies -FROM nvcr.io/nvidia/cuda:12.4.1-devel-ubi9 as base - -# Install essential packages, SSH key configuration for ubi, and setup Python -RUN dnf install -y python3.11 openssh git python3-pip make automake gcc gcc-c++ python3.11-devel && \ - ssh-keyscan github.com > ~/.ssh/known_hosts && \ - python3.11 -m ensurepip && \ - dnf install -y gcc && \ - rpm -ivh https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm && \ - dnf config-manager --add-repo https://developer.download.nvidia.com/compute/cuda/repos/rhel9/x86_64/cuda-rhel9.repo && \ - dnf repolist && \ - dnf config-manager --set-enabled cuda-rhel9-x86_64 && \ - dnf config-manager --set-enabled cuda && \ - dnf config-manager --set-enabled epel && \ - dnf update -y && \ - dnf clean all - -# Set CUDA and other environment variables -ENV LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/local/cuda/lib64:/usr/local/cuda/extras/CUPTI/lib64" \ - CUDA_HOME=/usr/local/cuda \ - PATH="/usr/local/cuda/bin:$PATH" \ - XLA_TARGET=cuda120 \ - XLA_FLAGS=--xla_gpu_cuda_data_dir=/usr/local/cuda - -# Reinstall llama-cpp-python with CUDA support -RUN --mount=type=ssh,id=default \ - python3.11 -m pip --no-cache-dir install --force-reinstall nvidia-cuda-nvcc-cu12 && \ - python3.11 -m pip uninstall -y llama-cpp-python && \ - python3.11 -m pip --no-cache-dir install llama-cpp-python==0.2.55 && \ - python3.11 -m pip --no-cache-dir install git+https://github.com/instructlab/instructlab.git@stable && \ - CMAKE_ARGS="-DLLAMA_CUBLAS=on" python3.11 -m pip install --force-reinstall --no-cache-dir llama-cpp-python==0.2.55 - -# Final Stage: Setup the runtime environment -FROM base as serve - -# Copy the Go binary from the builder stage -COPY --from=builder /app/instructlab-bot/ui/apiserver/apiserver /usr/local/bin/apiserver - -VOLUME [ "/data" ] -WORKDIR /data - -CMD /usr/local/bin/apiserver --listen-address=${LISTEN_ADDRESS:-localhost:3000} --redis-server=${REDIS_SERVER:-localhost:6379} --api-user=${API_USER:-kitteh} --api-pass=${API_PASS:-floofykittens} --debug=${DEBUG_MODE:-false} --test-mode=${TEST_MODE:-false} diff --git a/ui/apiserver/apiserver.go b/ui/apiserver/apiserver.go deleted file mode 100644 index aa781965..00000000 --- a/ui/apiserver/apiserver.go +++ /dev/null @@ -1,493 +0,0 @@ -package main - -import ( - "bytes" - "context" - "crypto/tls" - "encoding/json" - "fmt" - "io" - "net/http" - "os" - "os/exec" - "strings" - "time" - - "github.com/gin-contrib/cors" - "github.com/gin-gonic/gin" - "github.com/go-redis/redis/v8" - "github.com/spf13/pflag" - "go.uber.org/zap" -) - -const ( - redisQueueGenerate = "generate" - redisQueueArchive = "archived" -) - -const PreCheckEndpointURL = "https://merlinite-7b-vllm-openai.apps.fmaas-backend.fmaas.res.ibm.com/v1" -const InstructLabBotUrl = "http://bot:8081" - -type ApiServer struct { - router *gin.Engine - logger *zap.SugaredLogger - redis *redis.Client - ctx context.Context - testMode bool - preCheckEndpointURL string - instructLabBotUrl string -} - -type JobData struct { - JobID string `json:"jobID"` - Duration string `json:"duration"` - Status string `json:"status"` - S3URL string `json:"s3URL"` - ModelName string `json:"modelName"` - RepoOwner string `json:"repoOwner"` - Author string `json:"author"` - PrNumber string `json:"prNumber"` - PrSHA string `json:"prSHA"` - RequestTime string `json:"requestTime"` - Errors string `json:"errors"` - RepoName string `json:"repoName"` - JobType string `json:"jobType"` - InstallationID string `json:"installationID"` - Cmd string `json:"cmd"` -} - -type ChatRequest struct { - Question string `json:"question"` - Context string `json:"context"` -} - -type SkillPRRequest struct { - Name string `json:"name"` - Email string `json:"email"` - Task_description string `json:"task_description"` - Task_details string `json:"task_details"` - Title_work string `json:"title_work"` - Link_work string `json:"link_work"` - License_work string `json:"license_work"` - Creators string `json:"creators"` - Questions []string `json:"questions"` - Contexts []string `json:"contexts"` - Answers []string `json:"answers"` -} - -type KnowledgePRRequest struct { - Name string `json:"name"` - Email string `json:"email"` - Task_description string `json:"task_description"` - Task_details string `json:"task_details"` - Repo string `json:"repo"` - Commit string `json:"commit"` - Patterns string `json:"patterns"` - Title_work string `json:"title_work"` - Link_work string `json:"link_work"` - Revision string `json:"revision"` - License_work string `json:"license_work"` - Creators string `json:"creators"` - Domain string `json:"domain"` - Questions []string `json:"questions"` - Answers []string `json:"answers"` -} - -func (api *ApiServer) chatHandler(c *gin.Context) { - - var req ChatRequest - if err := c.ShouldBindJSON(&req); err != nil { - api.logger.Error("Failed to bind JSON:", err) - c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"}) - return - } - - api.logger.Infof("Received chat request - question: %v context: %v", req.Question, req.Context) - - answer, err := api.runIlabChatCommand(req.Question, req.Context) - if err != nil { - api.logger.Error("Failed to execute chat command:", err) - c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to execute command"}) - return - } - - c.JSON(http.StatusOK, gin.H{"answer": answer}) -} - -func (api *ApiServer) skillPRHandler(c *gin.Context) { - - var prData SkillPRRequest - if err := c.ShouldBindJSON(&prData); err != nil { - api.logger.Error("Failed to bind JSON: %v", err) - c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"}) - return - } - - api.logger.Infof("Received Skill pull request data: %v", prData) - - prJson, err := json.Marshal(prData) - if err != nil { - api.logger.Errorf("Error encoding JSON: %v", err) - c.JSON(http.StatusInternalServerError, gin.H{"error": err}) - return - } - - url := fmt.Sprintf("%s/pr/skill", InstructLabBotUrl) - resp, err := api.sendPostRequest(url, bytes.NewBuffer(prJson)) - if err != nil { - api.logger.Errorf("Error sending post request to bot http server: %v -- %v", err, resp) - c.JSON(http.StatusInternalServerError, gin.H{"error": err}) - return - } - defer resp.Body.Close() - - responseBody := new(bytes.Buffer) - _, err = responseBody.ReadFrom(resp.Body) - if err != nil { - api.logger.Errorf("Error reading response body: %v", err) - c.JSON(http.StatusInternalServerError, gin.H{"error": err}) - } - - if resp.StatusCode != http.StatusOK { - api.logger.Errorf("Error response (code : %s) from bot http server: %v", resp.StatusCode, responseBody.String()) - c.JSON(http.StatusInternalServerError, gin.H{"error": responseBody.String()}) - return - } - - api.logger.Infof("Skill pull request response: %v", responseBody.String()) - c.JSON(http.StatusCreated, gin.H{"msg": responseBody.String()}) -} - -func (api *ApiServer) knowledgePRHandler(c *gin.Context) { - - var prData KnowledgePRRequest - if err := c.ShouldBindJSON(&prData); err != nil { - api.logger.Error("Failed to bind JSON:", err) - c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"}) - return - } - - api.logger.Infof("Received Knowledge pull request data: %v", prData) - - prJson, err := json.Marshal(prData) - if err != nil { - api.logger.Errorf("Error encoding JSON: %v", err) - c.JSON(http.StatusInternalServerError, gin.H{"error": err}) - return - } - url := fmt.Sprintf("%s/pr/knowledge", InstructLabBotUrl) - resp, err := api.sendPostRequest(url, bytes.NewBuffer(prJson)) - if err != nil { - api.logger.Errorf("Error sending post request to bot http server: %v -- %v", err, resp) - c.JSON(http.StatusInternalServerError, gin.H{"error": err}) - return - } - - responseBody := new(bytes.Buffer) - _, err = responseBody.ReadFrom(resp.Body) - if err != nil { - api.logger.Errorf("Error reading response body: %v", err) - c.JSON(http.StatusInternalServerError, gin.H{"error": err}) - } - defer resp.Body.Close() - - if resp.StatusCode != http.StatusOK { - api.logger.Errorf("Error response (code : %s) from bot http server: %v", resp.StatusCode, responseBody.String()) - c.JSON(http.StatusInternalServerError, gin.H{"error": responseBody.String()}) - return - } - - api.logger.Infof("Knowledge pull request response: %v", responseBody.String()) - - c.JSON(http.StatusCreated, gin.H{"msg": responseBody.String()}) -} - -// Sent http post request using custom client with zero timeout -func (api *ApiServer) sendPostRequest(url string, body io.Reader) (*http.Response, error) { - client := &http.Client{ - Timeout: 0 * time.Second, - Transport: &http.Transport{ - TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, - }, - } - - request, err := http.NewRequest("POST", url, body) - if err != nil { - api.logger.Errorf("Error creating http request: %v", err) - return nil, err - } - request.Header.Set("Content-Type", "application/json") - response, err := client.Do(request) - if err != nil { - api.logger.Errorf("Error sending http request: %v", err) - return nil, err - } - return response, nil -} - -func (api *ApiServer) getAllJobs(c *gin.Context) { - resultsJobIDs, err := api.redis.LRange(context.Background(), redisQueueGenerate, 0, -1).Result() - if err != nil { - api.logger.Error("Error retrieving results job IDs from Redis", zap.Error(err)) - c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to retrieve results job IDs"}) - return - } - - archiveJobIDs, err := api.redis.LRange(context.Background(), redisQueueArchive, 0, -1).Result() - if err != nil { - api.logger.Error("Error retrieving archive job IDs from Redis", zap.Error(err)) - c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to retrieve archive job IDs"}) - return - } - - jobIDs := append(archiveJobIDs, resultsJobIDs...) - jobs := make([]JobData, 0) - seenIDs := make(map[string]bool) - for _, jobID := range jobIDs { - if _, found := seenIDs[jobID]; !found { - seenIDs[jobID] = true - jobData, err := api.fetchJobData(jobID) - if err != nil { - api.logger.Error("Failed to fetch job data", zap.String("Job ID", jobID), zap.Error(err)) - continue - } - jobs = append(jobs, jobData) - } - } - - c.JSON(http.StatusOK, jobs) -} - -func (api *ApiServer) fetchJobData(jobID string) (JobData, error) { - var jobData JobData - jobData.JobID = jobID - jobData.Duration = api.redis.Get(context.Background(), fmt.Sprintf("jobs:%s:duration", jobID)).Val() - jobData.Status = api.redis.Get(context.Background(), fmt.Sprintf("jobs:%s:status", jobID)).Val() - jobData.S3URL = api.redis.Get(context.Background(), fmt.Sprintf("jobs:%s:s3_url", jobID)).Val() - jobData.ModelName = api.redis.Get(context.Background(), fmt.Sprintf("jobs:%s:model_name", jobID)).Val() - jobData.RepoOwner = api.redis.Get(context.Background(), fmt.Sprintf("jobs:%s:repo_owner", jobID)).Val() - jobData.Author = api.redis.Get(context.Background(), fmt.Sprintf("jobs:%s:author", jobID)).Val() - jobData.PrNumber = api.redis.Get(context.Background(), fmt.Sprintf("jobs:%s:pr_number", jobID)).Val() - jobData.PrSHA = api.redis.Get(context.Background(), fmt.Sprintf("jobs:%s:pr_sha", jobID)).Val() - jobData.RequestTime = api.redis.Get(context.Background(), fmt.Sprintf("jobs:%s:request_time", jobID)).Val() - jobData.Errors = api.redis.Get(context.Background(), fmt.Sprintf("jobs:%s:errors", jobID)).Val() - jobData.RepoName = api.redis.Get(context.Background(), fmt.Sprintf("jobs:%s:repo_name", jobID)).Val() - jobData.JobType = api.redis.Get(context.Background(), fmt.Sprintf("jobs:%s:job_type", jobID)).Val() - jobData.InstallationID = api.redis.Get(context.Background(), fmt.Sprintf("jobs:%s:installation_id", jobID)).Val() - jobData.Cmd = api.redis.Get(context.Background(), fmt.Sprintf("jobs:%s:cmd", jobID)).Val() - - return jobData, nil -} - -func AuthRequired(username, password string) gin.HandlerFunc { - return func(c *gin.Context) { - user, pass, hasAuth := c.Request.BasicAuth() - if hasAuth && user == username && pass == password { - c.Next() - return - } - c.Header("WWW-Authenticate", "Basic realm=\"Authorization Required\"") - c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "Unauthorized"}) - } -} - -func (api *ApiServer) setupRoutes(apiUser, apiPass string) { - api.router.Use(cors.New(cors.Config{ - AllowOrigins: []string{"*"}, - AllowMethods: []string{"GET", "POST", "PUT", "PATCH", "DELETE", "HEAD"}, - AllowHeaders: []string{"*"}, - ExposeHeaders: []string{"Content-Length"}, - AllowCredentials: true, - MaxAge: 12 * time.Hour, - })) - - authorized := api.router.Group("/") - authorized.Use(AuthRequired(apiUser, apiPass)) - authorized.GET("/jobs", api.getAllJobs) - authorized.POST("/chat", api.chatHandler) - authorized.POST("pr/skill", api.skillPRHandler) - authorized.POST("pr/knowledge", api.knowledgePRHandler) - - api.router.GET("/", func(c *gin.Context) { - c.String(http.StatusOK, "IL Redis Queue") - }) -} - -func (api *ApiServer) runIlabChatCommand(question, context string) (string, error) { - if question == "" { - api.logger.Error("Question not found or not a string") - return "", fmt.Errorf("invalid question") - } - - // Append the context to the question if present - if context != "" { - question = fmt.Sprintf("%s Answer this based on the following context: %s.", question, context) - } - - // Construct the command string with the formatted question - commandStr := fmt.Sprintf("chat --quick-question '%s' --tls-insecure", question) - - // Determine the mode and adjust the command string accordingly - var cmd *exec.Cmd - if api.testMode { - // the model name is a dummy example in test mode - commandStr += fmt.Sprintf(" --endpoint-url %s --model %s", api.preCheckEndpointURL, "/shared_model_storage/transformers_cache/models--ibm--merlinite-7b/snapshots/233d12759d5bb9344231dafdb51310ec19d79c0e") - cmdArgs := strings.Fields(commandStr) - cmd = exec.Command("echo", cmdArgs...) - api.logger.Infof("Running in test mode: %s", commandStr) - } else { - modelName, err := api.fetchModelName(true) - if err != nil { - api.logger.Errorf("Failed to fetch model name: %v", err) - return "failed to retrieve the model name", err - } - commandStr += fmt.Sprintf(" --endpoint-url %s --model %s", api.preCheckEndpointURL, modelName) - cmdArgs := strings.Fields(commandStr) - cmd = exec.Command("ilab", cmdArgs...) - api.logger.Infof("Running in production mode with model name %s: %s", modelName, commandStr) - } - - // Set environment and buffers for capturing output - cmd.Env = os.Environ() - var out bytes.Buffer - var errOut bytes.Buffer - cmd.Stdout = &out - cmd.Stderr = &errOut - - // Execute the command and check for errors - err := cmd.Run() - if err != nil { - api.logger.Error("Command failed with error: ", zap.Error(err), zap.String("stderr", errOut.String())) - return "", err - } - - // Log successful execution and return the trimmed output - api.logger.Infof("Command executed successfully, output: %s", out.String()) - return strings.TrimSpace(out.String()), nil -} - -func setupLogger(debugMode bool) *zap.SugaredLogger { - config := zap.NewDevelopmentConfig() - if debugMode { - config.Level = zap.NewAtomicLevelAt(zap.DebugLevel) - } else { - config.Level = zap.NewAtomicLevelAt(zap.InfoLevel) - } - logger, err := config.Build() - if err != nil { - panic(fmt.Sprintf("Cannot build logger: %v", err)) - } - return logger.Sugar() -} - -// fetchModelName hits the defined precheck endpoint with "/models" appended to extract the model name. -// If fullName is true, it returns the entire ID value; if false, it returns the parsed out name after the double hyphens. -func (api *ApiServer) fetchModelName(fullName bool) (string, error) { - // Ensure the endpoint URL ends with "/models" - endpoint := api.preCheckEndpointURL - if !strings.HasSuffix(endpoint, "/") { - endpoint += "/" - } - endpoint += "models" - - http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true} - http.DefaultTransport.(*http.Transport).TLSHandshakeTimeout = 10 * time.Second - http.DefaultTransport.(*http.Transport).ExpectContinueTimeout = 1 * time.Second - - req, err := http.NewRequestWithContext(api.ctx, "GET", endpoint, nil) - if err != nil { - return "", fmt.Errorf("failed to create request: %w", err) - } - - resp, err := http.DefaultClient.Do(req) - if err != nil { - return "", fmt.Errorf("failed to fetch model details: %w", err) - } - defer resp.Body.Close() - - if resp.StatusCode != http.StatusOK { - return "", fmt.Errorf("unexpected status code: %d", resp.StatusCode) - } - - body, err := io.ReadAll(resp.Body) - if err != nil { - return "", fmt.Errorf("failed to read response body: %w", err) - } - - var responseData struct { - Object string `json:"object"` - Data []struct { - ID string `json:"id"` - Object string `json:"object"` - } `json:"data"` - } - - if err := json.Unmarshal(body, &responseData); err != nil { - return "", fmt.Errorf("failed to parse JSON response: %w", err) - } - - if responseData.Object != "list" { - return "", fmt.Errorf("expected object type 'list', got '%s'", responseData.Object) - } - - // Extract the model name or the full ID based on the fullName flag - for _, item := range responseData.Data { - if item.Object == "model" { - if !fullName { - // Otherwise, parse and return the name after the last "--" - parts := strings.Split(item.ID, "/") - for _, part := range parts { - if strings.Contains(part, "--") { - nameParts := strings.Split(part, "--") - if len(nameParts) > 1 { - return nameParts[len(nameParts)-1], nil - } - } - } - } - return item.ID, nil - } - } - - return "", fmt.Errorf("model name not found in response") -} - -func main() { - debugFlag := pflag.Bool("debug", false, "Enable debug mode") - testMode := pflag.Bool("test-mode", false, "Don't run ilab commands, just echo back the ilab command to the chat response") - listenAddress := pflag.String("listen-address", "localhost:3000", "Address to listen on") - redisAddress := pflag.String("redis-server", "localhost:6379", "Redis server address") - apiUser := pflag.String("api-user", "", "API username") - apiPass := pflag.String("api-pass", "", "API password") - preCheckEndpointURL := pflag.String("precheck-endpoint", PreCheckEndpointURL, "Precheck endpoint URL") - InstructLabBotUrl := pflag.String("bot-url", InstructLabBotUrl, "InstructLab Bot URL") - pflag.Parse() - - logger := setupLogger(*debugFlag) - defer logger.Sync() - - if *apiUser == "" || *apiPass == "" { - logger.Fatal("Username and password must be provided") - } - - rdb := redis.NewClient(&redis.Options{ - Addr: *redisAddress, - }) - - router := gin.Default() - svr := ApiServer{ - router: router, - logger: logger, - redis: rdb, - ctx: context.Background(), - testMode: *testMode, - preCheckEndpointURL: *preCheckEndpointURL, - instructLabBotUrl: *InstructLabBotUrl, - } - svr.setupRoutes(*apiUser, *apiPass) - - svr.logger.Info("ApiServer starting", zap.String("listen-address", *listenAddress)) - if err := svr.router.Run(*listenAddress); err != nil { - svr.logger.Error("ApiServer failed to start", zap.Error(err)) - } -} diff --git a/ui/apiserver/go.mod b/ui/apiserver/go.mod deleted file mode 100644 index 85ee17e6..00000000 --- a/ui/apiserver/go.mod +++ /dev/null @@ -1,42 +0,0 @@ -module github.com/instructlab/instructlab-bot/ui/apiserver - -go 1.22.1 - -require ( - github.com/gin-contrib/cors v1.7.1 - github.com/gin-gonic/gin v1.9.1 - github.com/go-redis/redis/v8 v8.11.5 - github.com/spf13/pflag v1.0.5 - go.uber.org/zap v1.27.0 -) - -require ( - github.com/bytedance/sonic v1.11.3 // indirect - github.com/cespare/xxhash/v2 v2.1.2 // indirect - github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect - github.com/chenzhuoyu/iasm v0.9.1 // indirect - github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect - github.com/gabriel-vasile/mimetype v1.4.3 // indirect - github.com/gin-contrib/sse v0.1.0 // indirect - github.com/go-playground/locales v0.14.1 // indirect - github.com/go-playground/universal-translator v0.18.1 // indirect - github.com/go-playground/validator/v10 v10.19.0 // indirect - github.com/goccy/go-json v0.10.2 // indirect - github.com/json-iterator/go v1.1.12 // indirect - github.com/klauspost/cpuid/v2 v2.2.7 // indirect - github.com/leodido/go-urn v1.4.0 // indirect - github.com/mattn/go-isatty v0.0.20 // indirect - github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/pelletier/go-toml/v2 v2.2.0 // indirect - github.com/twitchyliquid64/golang-asm v0.15.1 // indirect - github.com/ugorji/go/codec v1.2.12 // indirect - go.uber.org/multierr v1.10.0 // indirect - golang.org/x/arch v0.7.0 // indirect - golang.org/x/crypto v0.21.0 // indirect - golang.org/x/net v0.23.0 // indirect - golang.org/x/sys v0.18.0 // indirect - golang.org/x/text v0.14.0 // indirect - google.golang.org/protobuf v1.33.0 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect -) diff --git a/ui/apiserver/go.sum b/ui/apiserver/go.sum deleted file mode 100644 index d2fbfe62..00000000 --- a/ui/apiserver/go.sum +++ /dev/null @@ -1,127 +0,0 @@ -github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= -github.com/bytedance/sonic v1.10.0-rc/go.mod h1:ElCzW+ufi8qKqNW0FY314xriJhyJhuoJ3gFZdAHF7NM= -github.com/bytedance/sonic v1.11.3 h1:jRN+yEjakWh8aK5FzrciUHG8OFXK+4/KrAX/ysEtHAA= -github.com/bytedance/sonic v1.11.3/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4= -github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= -github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= -github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= -github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d h1:77cEq6EriyTZ0g/qfRdp61a3Uu/AWrgIq2s0ClJV1g0= -github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d/go.mod h1:8EPpVsBuRksnlj1mLy4AWzRNQYxauNi62uWcE3to6eA= -github.com/chenzhuoyu/iasm v0.9.0/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog= -github.com/chenzhuoyu/iasm v0.9.1 h1:tUHQJXo3NhBqw6s33wkGn9SP3bvrWLdlVIJ3hQBL7P0= -github.com/chenzhuoyu/iasm v0.9.1/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= -github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= -github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= -github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= -github.com/gin-contrib/cors v1.7.1 h1:s9SIppU/rk8enVvkzwiC2VK3UZ/0NNGsWfUKvV55rqs= -github.com/gin-contrib/cors v1.7.1/go.mod h1:n/Zj7B4xyrgk/cX1WCX2dkzFfaNm/xJb6oIUk7WTtps= -github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= -github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= -github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= -github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= -github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= -github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= -github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= -github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= -github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= -github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= -github.com/go-playground/validator/v10 v10.19.0 h1:ol+5Fu+cSq9JD7SoSqe04GMI92cbn0+wvQ3bZ8b/AU4= -github.com/go-playground/validator/v10 v10.19.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= -github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI= -github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= -github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= -github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= -github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= -github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM= -github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= -github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= -github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= -github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= -github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= -github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= -github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= -github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= -github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= -github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= -github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= -github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE= -github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs= -github.com/pelletier/go-toml/v2 v2.2.0 h1:QLgLl2yMN7N+ruc31VynXs1vhMZa7CeHHejIeBAsoHo= -github.com/pelletier/go-toml/v2 v2.2.0/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8= -github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= -github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= -github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= -github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= -github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= -github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= -go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= -go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= -go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ= -go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= -go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= -golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= -golang.org/x/arch v0.7.0 h1:pskyeJh/3AmoQ8CPE95vxHLqp1G1GfGNXTmcl9NEKTc= -golang.org/x/arch v0.7.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= -golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= -golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= -golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= -golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= -golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= -google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= -rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git a/ui/compose.ui b/ui/compose.ui deleted file mode 100644 index 1a1c7612..00000000 --- a/ui/compose.ui +++ /dev/null @@ -1,83 +0,0 @@ -# Multi-Worker Compose File -# 1. Fill in the .env.template from the root of the repo and rename it to .env -# 2. Each worker needs its own volume to mount with a clone of your taxonomy repo fork, example uses /home/fedora/instructlab-worker(n). -# 3 Start the compose stack -# 4. Next, exec into a worker and start instructlab-bot-worker with the following: -# export AWS_ACCESS_KEY_ID=x -# export AWS_SECRET_ACCESS_KEY=x -# export AWS_DEFAULT_REGION=x -# git config --global --add safe.directory /data/taxonomy -# instructlab-bot-worker generate --github-token \ -# --redis redis:6379 \ -# --s3-bucket some-bucket-name \ -# --aws-region us-east-1 -# 5. Add the IP address clients will point their browsers at in the /ui/.env file in the IL_UI_API_SERVER_URL variable -# Make sure the IL_UI_API_SERVER_USERNAME and IL_UI_API_SERVER_PASSWORD match the apiserver API_USER and API_PASS variables -services: - redis: - container_name: redis - image: redis:latest - ports: - - 6379:6379 - - bot: - container_name: bot - image: ghcr.io/instructlab/instructlab-bot/instructlab-gobot:main - env_file: - - ../.env - depends_on: - - redis - - bot-ui: - container_name: bot-ui - image: ghcr.io/instructlab/instructlab-bot/bot-ui:main - network_mode: "host" - - apiserver: - container_name: apiserver - image: ghcr.io/instructlab/instructlab-bot/apiserver:main - network_mode: "host" - depends_on: - - redis - environment: - # Bind on all interface - LISTEN_ADDRESS: "${LISTEN_ADDRESS:-:3000}" - REDIS_SERVER: "${REDIS_SERVER:-localhost:6379}" - API_USER: "${API_USER:-kitteh}" - API_PASS: "${API_PASS:-floofykittens}" - DEBUG_MODE: "${DEBUG_MODE:-false}" - TEST_MODE: "${TEST_MODE:-false}" - - worker1: - container_name: worker1 - image: ghcr.io/instructlab/instructlab-bot/instructlab-serve:main - volumes: - - /home/fedora/instructlab-worker1:/data - entrypoint: ["/bin/bash"] - stdin_open: true - tty: true - env_file: - - ../.env - deploy: - resources: - reservations: - devices: - - driver: nvidia - capabilities: [gpu] - - worker2: - container_name: worker2 - image: ghcr.io/instructlab/instructlab-bot/instructlab-serve:main - volumes: - - /home/fedora/instructlab-worker2:/data - entrypoint: ["/bin/bash"] - stdin_open: true - tty: true - env_file: - - ../.env - deploy: - resources: - reservations: - devices: - - driver: nvidia - capabilities: [gpu] diff --git a/ui/envConfig.ts b/ui/envConfig.ts deleted file mode 100644 index 96b3ab0e..00000000 --- a/ui/envConfig.ts +++ /dev/null @@ -1,5 +0,0 @@ -// envConfig.ts -import { loadEnvConfig } from '@next/env'; - -const projectDir = process.cwd(); -loadEnvConfig(projectDir); diff --git a/ui/next-env.d.ts b/ui/next-env.d.ts deleted file mode 100644 index 4f11a03d..00000000 --- a/ui/next-env.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -/// -/// - -// NOTE: This file should not be edited -// see https://nextjs.org/docs/basic-features/typescript for more information. diff --git a/ui/next.config.js b/ui/next.config.js deleted file mode 100644 index 198a12e2..00000000 --- a/ui/next.config.js +++ /dev/null @@ -1,7 +0,0 @@ -/** @type {import('next').NextConfig} */ -const nextConfig = { - reactStrictMode: true, - transpilePackages: ['@patternfly/react-core', '@patternfly/react-styles', '@patternfly/react-table'], -}; - -module.exports = nextConfig; diff --git a/ui/package.json b/ui/package.json deleted file mode 100644 index 1b2bde23..00000000 --- a/ui/package.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "name": "instructlab-bot-ui", - "version": "0.1.0", - "description": "InstructLab BotUI", - "repository": "https://github.com/instruct-lab/instruct-lab-bot.git", - "homepage": "https://github.com/instruct-lab/instruct-lab-bot", - "license": "Apache-2.0", - "private": true, - "scripts": { - "dev": "next dev", - "build": "next build", - "start": "next start", - "lint": "next lint", - "type-check": "tsc --noEmit", - "lint:fix": "npx eslint --fix 'src/**/*.{js,jsx,ts,tsx}'", - "pretty": "prettier --write 'src/**/*.{js,jsx,ts,tsx,css,md}'" - }, - "dependencies": { - "@fortawesome/free-solid-svg-icons": "^6.5.2", - "@fortawesome/react-fontawesome": "^0.2.2", - "@next/env": "^14.2.3", - "@patternfly/react-charts": "^7.3.0", - "@patternfly/react-core": "^5.3.3", - "@patternfly/react-icons": "^5.3.1", - "@patternfly/react-styles": "^5.3.1", - "@patternfly/react-table": "^5.3.1", - "@types/node": "20.3.1", - "@types/react": "18.2.13", - "@types/react-dom": "18.2.6", - "axios": "^1.7.2", - "eslint": "^8.56.0", - "https": "^1.0.0", - "next": "^14.2.3", - "next-auth": "^4.24.7", - "node-fetch": "^3.3.2", - "react": "18.2.0", - "react-dom": "18.2.0", - "react-query": "^3.39.3", - "typescript": "5.1.3", - "winston": "^3.13.0" - }, - "devDependencies": { - "@next/eslint-plugin-next": "^14.2.3", - "@redhat-cloud-services/eslint-config-redhat-cloud-services": "^2.0.4", - "@types/styled-components": "^5.1.26", - "@types/uuid": "^9.0.8", - "@typescript-eslint/eslint-plugin": "^6.1.0", - "css-loader": "^7.1.1", - "eslint-config-next": "^14.2.3", - "eslint-config-prettier": "^9.1.0", - "eslint-plugin-prettier": "^4.2.1", - "prettier": "2.8.8", - "uuid": "^9.0.1" - } -} diff --git a/ui/public/InstructLab-Logo.svg b/ui/public/InstructLab-Logo.svg deleted file mode 100644 index 0d266dd3..00000000 --- a/ui/public/InstructLab-Logo.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - InstructLab - - diff --git a/ui/public/bot-icon-chat-32x32.svg b/ui/public/bot-icon-chat-32x32.svg deleted file mode 100644 index 8f7f3c4e..00000000 --- a/ui/public/bot-icon-chat-32x32.svg +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ui/public/favicon.ico b/ui/public/favicon.ico deleted file mode 100644 index 718d6fea4835ec2d246af9800eddb7ffb276240c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25931 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 LrJugUA?W`A8`#=m diff --git a/ui/public/login-bg.svg b/ui/public/login-bg.svg deleted file mode 100644 index a4f19e3b..00000000 --- a/ui/public/login-bg.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/ui/src/app/404.tsx b/ui/src/app/404.tsx deleted file mode 100644 index 0668e68e..00000000 --- a/ui/src/app/404.tsx +++ /dev/null @@ -1,16 +0,0 @@ -// pages/404.tsx -import * as React from 'react'; -import { AppLayout } from '../components/AppLayout'; - -const NotFoundPage: React.FunctionComponent = () => { - return ( - -
-

404 - Page Not Found

-

Sorry, the page you are looking for does not exist.

-
-
- ); -}; - -export default NotFoundPage; diff --git a/ui/src/app/api/auth/[...nextauth]/route.ts b/ui/src/app/api/auth/[...nextauth]/route.ts deleted file mode 100644 index 18873192..00000000 --- a/ui/src/app/api/auth/[...nextauth]/route.ts +++ /dev/null @@ -1,120 +0,0 @@ -// src/app/api/auth/[...nextauth]/route.ts -import NextAuth, { NextAuthOptions } from 'next-auth'; -import GitHubProvider from 'next-auth/providers/github'; -import CredentialsProvider from 'next-auth/providers/credentials'; -import axios from 'axios'; -import winston from 'winston'; -import path from 'path'; - -// Logger setup -const logger = winston.createLogger({ - level: 'info', - format: winston.format.combine( - winston.format.timestamp(), - winston.format.printf(({ timestamp, level, message }) => { - return `${timestamp} ${level}: ${message}`; - }) - ), - transports: [new winston.transports.Console(), new winston.transports.File({ filename: path.join(process.cwd(), 'auth.log') })], -}); - -const ORG = 'instructlab'; - -const authOptions: NextAuthOptions = { - providers: [ - GitHubProvider({ - clientId: process.env.OAUTH_GITHUB_ID!, - clientSecret: process.env.OAUTH_GITHUB_SECRET!, - authorization: { params: { scope: 'read:user' } }, - }), - CredentialsProvider({ - name: 'Credentials', - credentials: { - username: { label: 'Username', type: 'text' }, - password: { label: 'Password', type: 'password' }, - }, - authorize: async (credentials) => { - if ( - credentials?.username === (process.env.IL_UI_ADMIN_USERNAME || 'admin') && - credentials?.password === (process.env.IL_UI_ADMIN_PASSWORD || 'password') - ) { - logger.info(`User ${credentials.username} logged in successfully with credentials`); - return { id: '1', name: 'Admin', email: 'admin@example.com' }; - } - logger.warn(`Failed login attempt with username: ${credentials?.username}`); - return null; - }, - }), - ], - secret: process.env.NEXTAUTH_SECRET, - session: { - strategy: 'jwt', - }, - callbacks: { - async jwt({ token, user }) { - if (user) { - token.id = user.id; - } - return token; - }, - async session({ session, token }) { - if (token) { - (session as { id?: string }).id = token.id as string; - } - return session; - }, - async signIn({ account, profile }) { - if (account && account.provider === 'github' && profile) { - const githubProfile = profile as { login: string }; - - try { - const response = await axios.get(`https://api.github.com/orgs/${ORG}/members/${githubProfile.login}`, { - headers: { - Accept: 'application/vnd.github+json', - Authorization: `Bearer ${process.env.GITHUB_TOKEN}`, - 'X-GitHub-Api-Version': '2022-11-28', - }, - validateStatus: (status) => { - return [204, 302, 404].includes(status); - }, - }); - - if (response.status === 204) { - console.log(`User ${githubProfile.login} logged in successfully with GitHub`); - logger.info(`User ${githubProfile.login} logged in successfully with GitHub`); - return true; - } else if (response.status === 404) { - console.log(`User ${githubProfile.login} is not a member of the ${ORG} organization`); - logger.warn(`User ${githubProfile.login} is not a member of the ${ORG} organization`); - return `/error?error=AccessDenied`; // Redirect to custom error page - } else { - console.log(`Unexpected error for user ${githubProfile.login} during organization membership verification`); - logger.error(`Unexpected error for user ${githubProfile.login} during organization membership verification`); - return false; - } - } catch (error) { - if (axios.isAxiosError(error)) { - logger.error(`Error fetching GitHub organization membership for user ${githubProfile.login}: ${error.message}`, { - url: error.config?.url, - method: error.config?.method, - data: error.response?.data, - status: error.response?.status, - }); - } else { - logger.error(`Error fetching GitHub organization membership for user ${githubProfile.login}: ${error}`); - } - return false; - } - } - return true; - }, - }, - pages: { - signIn: '/login', - error: '/error', - }, -}; - -const handler = NextAuth(authOptions); - -export { handler as GET, handler as POST }; diff --git a/ui/src/app/api/envConfig/route.ts b/ui/src/app/api/envConfig/route.ts deleted file mode 100644 index 9b1a2ba8..00000000 --- a/ui/src/app/api/envConfig/route.ts +++ /dev/null @@ -1,13 +0,0 @@ -// src/app/api/envConfig/route.ts -import { NextResponse } from 'next/server'; - -export async function GET() { - const envConfig = { - GRANITE_API: process.env.IL_GRANITE_API || '', - GRANITE_MODEL_NAME: process.env.IL_GRANITE_MODEL_NAME || '', - MERLINITE_API: process.env.IL_MERLINITE_API || '', - MERLINITE_MODEL_NAME: process.env.IL_MERLINITE_MODEL_NAME || '', - }; - - return NextResponse.json(envConfig); -} diff --git a/ui/src/app/api/jobs/route.ts b/ui/src/app/api/jobs/route.ts deleted file mode 100644 index cdef9506..00000000 --- a/ui/src/app/api/jobs/route.ts +++ /dev/null @@ -1,34 +0,0 @@ -// src/app/api/jobs/route.ts -import { NextResponse } from 'next/server'; - -const API_SERVER_URL = process.env.IL_UI_API_SERVER_URL || 'http://localhost:3000'; -const USERNAME = process.env.IL_UI_API_SERVER_USERNAME || 'kitteh'; -const PASSWORD = process.env.IL_UI_API_SERVER_PASSWORD || 'floofykittens'; - -export async function GET() { - const auth = Buffer.from(`${USERNAME}:${PASSWORD}`).toString('base64'); - const headers = { - Authorization: `Basic ${auth}`, - }; - - try { - const response = await fetch(`${API_SERVER_URL}/jobs`, { - method: 'GET', - headers, - }); - - if (!response.ok) { - throw new Error(`HTTP error! status: ${response.status}`); - } - - const result = await response.json(); - return NextResponse.json(result); - } catch (error) { - console.error('Failed to fetch jobs:', error); - return NextResponse.json({ error: 'Failed to fetch jobs' }, { status: 500 }); - } -} - -export function POST() { - return NextResponse.json({ message: 'Method not allowed' }, { status: 405 }); -} diff --git a/ui/src/app/api/playground/chat/route.ts b/ui/src/app/api/playground/chat/route.ts deleted file mode 100644 index 03644cdf..00000000 --- a/ui/src/app/api/playground/chat/route.ts +++ /dev/null @@ -1,103 +0,0 @@ -// src/app/api/playground/chat/route.ts -'use server'; -import { NextRequest, NextResponse } from 'next/server'; -import fetch from 'node-fetch'; -import https from 'https'; -import { PassThrough } from 'stream'; -import '../../../../../envConfig'; - -export async function POST(req: NextRequest) { - try { - const { question, systemRole } = await req.json(); - const apiURL = req.nextUrl.searchParams.get('apiURL'); - const modelName = req.nextUrl.searchParams.get('modelName'); - - if (!apiURL || !modelName) { - return new NextResponse('Missing API URL or Model Name', { status: 400 }); - } - - const messages = [ - { role: 'system', content: systemRole }, - { role: 'user', content: question }, - ]; - - const requestData = { - model: modelName, - messages, - stream: true, - }; - - const agent = new https.Agent({ - rejectUnauthorized: false, - }); - - const chatResponse = await fetch(`${apiURL}/v1/chat/completions`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - accept: 'application/json', - }, - body: JSON.stringify(requestData), - agent: apiURL.startsWith('https') ? agent : undefined, - }); - - if (!chatResponse.body) { - return new NextResponse('Failed to fetch chat response', { status: 500 }); - } - - const passThrough = new PassThrough(); - - chatResponse.body.on('data', (chunk) => { - const chunkString = chunk.toString(); - const lines = chunkString.split('\n').filter((line: string) => line.trim() !== ''); - - for (const line of lines) { - if (line.startsWith('data:')) { - const json = line.replace('data: ', ''); - if (json === '[DONE]') { - passThrough.end(); - return; - } - - try { - const parsed = JSON.parse(json); - const deltaContent = parsed.choices[0].delta?.content; - - if (deltaContent) { - passThrough.write(deltaContent); - } - } catch (err) { - console.error('Error parsing chunk:', err); - } - } - } - }); - - chatResponse.body.on('end', () => { - passThrough.end(); - }); - - const readableStream = new ReadableStream({ - start(controller) { - passThrough.on('data', (chunk) => { - controller.enqueue(chunk); - }); - passThrough.on('end', () => { - controller.close(); - }); - passThrough.on('error', (err) => { - controller.error(err); - }); - }, - }); - - return new NextResponse(readableStream, { - headers: { - 'Content-Type': 'text/plain', - }, - }); - } catch (error) { - console.error('Error processing request:', error); - return new NextResponse('Error processing request', { status: 500 }); - } -} diff --git a/ui/src/app/api/playground/devchat/route.ts b/ui/src/app/api/playground/devchat/route.ts deleted file mode 100644 index f2372ee9..00000000 --- a/ui/src/app/api/playground/devchat/route.ts +++ /dev/null @@ -1,95 +0,0 @@ -// src/app/api/playground/devchat/route.ts -/* eslint-disable @typescript-eslint/ban-ts-comment */ -// @ts-nocheck -'use server'; -import { NextRequest, NextResponse } from 'next/server'; -import fetch from 'node-fetch'; -import https from 'https'; -import http from 'http'; -import { PassThrough } from 'stream'; -import '../../../../../envConfig'; - -export async function POST(req: NextRequest) { - try { - const { question, temperature, maxTokens, topP, frequencyPenalty, presencePenalty, repetitionPenalty, selectedModel, systemRole } = - await req.json(); - - const messages = [ - { role: 'system', content: systemRole }, - { role: 'user', content: question }, - ].filter((message) => message.content); - - // TODO: resolve this typing eslint skip - /* eslint-disable @typescript-eslint/no-explicit-any */ - const requestData: any = { - model: selectedModel.modelName, - messages: messages, - temperature, - max_tokens: maxTokens, - top_p: topP, - frequency_penalty: frequencyPenalty, - presence_penalty: presencePenalty, - repetition_penalty: repetitionPenalty, - stop: ['<|endoftext|>'], - logprobs: false, - stream: true, - }; - - const agent = selectedModel.apiURL.startsWith('https') ? new https.Agent({ rejectUnauthorized: false }) : new http.Agent(); - - const chatResponse = await fetch(`${selectedModel.apiURL}/v1/chat/completions`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - accept: 'application/json', - }, - body: JSON.stringify(requestData), - agent, - }); - - if (!chatResponse.body) { - return new NextResponse('Failed to fetch chat response', { status: 500 }); - } - - const passThrough = new PassThrough(); - - chatResponse.body.on('data', (chunk) => { - const chunkString = chunk.toString(); - const lines = chunkString.split('\n').filter((line: string) => line.trim() !== ''); - - for (const line of lines) { - if (line.startsWith('data:')) { - const json = line.replace('data: ', ''); - if (json === '[DONE]') { - passThrough.end(); - return; - } - - try { - const parsed = JSON.parse(json); - const deltaContent = parsed.choices[0].delta?.content; - - if (deltaContent) { - passThrough.write(deltaContent); // Send the delta content to the client - } - } catch (err) { - console.error('Error parsing chunk:', err); - } - } - } - }); - - chatResponse.body.on('end', () => { - passThrough.end(); - }); - - return new NextResponse(passThrough, { - headers: { - 'Content-Type': 'text/plain', - }, - }); - } catch (error) { - console.error('Error processing request:', error); - return new NextResponse('Error processing request', { status: 500 }); - } -} diff --git a/ui/src/app/api/pr/knowledge/route.ts b/ui/src/app/api/pr/knowledge/route.ts deleted file mode 100644 index 7046ea31..00000000 --- a/ui/src/app/api/pr/knowledge/route.ts +++ /dev/null @@ -1,36 +0,0 @@ -// src/app/api/pr/knowledge/route.ts - -import { NextResponse } from 'next/server'; - -const API_SERVER_URL = process.env.IL_UI_API_SERVER_URL || 'http://localhost:3000'; -const USERNAME = process.env.IL_UI_API_SERVER_USERNAME || 'kitteh'; -const PASSWORD = process.env.IL_UI_API_SERVER_PASSWORD || 'floofykittens'; - -export async function POST(req: Request) { - console.log(`Received request: ${req.method} ${req.url} ${req.body}}`); - - const auth = Buffer.from(`${USERNAME}:${PASSWORD}`).toString('base64'); - const headers = { - 'Content-Type': 'application/json', - Authorization: 'Basic ' + auth, - }; - - try { - const body = await req.json(); - const response = await fetch(`${API_SERVER_URL}/pr/knowledge`, { - method: 'POST', - headers, - body: JSON.stringify(body), - }); - - if (response.status !== 201) { - throw new Error(`HTTP error! status: ${response.status}`); - } - - const result = await response.json(); - return NextResponse.json(result, { status: 201 }); - } catch (error) { - console.error('Failed to post knowledge data:', error); - return NextResponse.json({ error: 'Failed to post knowledge data' }, { status: 500 }); - } -} diff --git a/ui/src/app/api/pr/skill/route.ts b/ui/src/app/api/pr/skill/route.ts deleted file mode 100644 index 9ddbff7d..00000000 --- a/ui/src/app/api/pr/skill/route.ts +++ /dev/null @@ -1,36 +0,0 @@ -// src/app/api/pr/skill/route.ts - -import { NextResponse } from 'next/server'; - -const API_SERVER_URL = process.env.IL_UI_API_SERVER_URL || 'http://localhost:3000'; -const USERNAME = process.env.IL_UI_API_SERVER_USERNAME || 'kitteh'; -const PASSWORD = process.env.IL_UI_API_SERVER_PASSWORD || 'floofykittens'; - -export async function POST(req: Request) { - console.log(`Received request: ${req.method} ${req.url} ${req.body}}`); - - const auth = Buffer.from(`${USERNAME}:${PASSWORD}`).toString('base64'); - const headers = { - 'Content-Type': 'application/json', - Authorization: 'Basic ' + auth, - }; - - try { - const body = await req.json(); - const response = await fetch(`${API_SERVER_URL}/pr/skill`, { - method: 'POST', - headers, - body: JSON.stringify(body), - }); - - if (response.status !== 201) { - throw new Error(`HTTP error! status: ${response.status}`); - } - - const result = await response.json(); - return NextResponse.json(result, { status: 201 }); - } catch (error) { - console.error('Failed to post skill data:', error); - return NextResponse.json({ error: 'Failed to post skill data' }, { status: 500 }); - } -} diff --git a/ui/src/app/contribute/knowledge/page.tsx b/ui/src/app/contribute/knowledge/page.tsx deleted file mode 100644 index cab86364..00000000 --- a/ui/src/app/contribute/knowledge/page.tsx +++ /dev/null @@ -1,14 +0,0 @@ -// src/app/contribute/knowledge/page.tsx -import * as React from 'react'; -import { AppLayout } from '../../../components/AppLayout'; -import { KnowledgeForm } from '../../../components/Contribute/Knowledge'; - -const KnowledgeFormPage: React.FC = () => { - return ( - - - - ); -}; - -export default KnowledgeFormPage; diff --git a/ui/src/app/contribute/skill/page.tsx b/ui/src/app/contribute/skill/page.tsx deleted file mode 100644 index a2b5d3bc..00000000 --- a/ui/src/app/contribute/skill/page.tsx +++ /dev/null @@ -1,14 +0,0 @@ -// src/app/contribute/skill/page.tsx -import * as React from 'react'; -import { AppLayout } from '../../../components/AppLayout'; -import { SkillForm } from '../../../components/Contribute/Skill'; - -const SkillFormPage: React.FC = () => { - return ( - - - - ); -}; - -export default SkillFormPage; diff --git a/ui/src/app/dashboard/page.tsx b/ui/src/app/dashboard/page.tsx deleted file mode 100644 index c3c76e9e..00000000 --- a/ui/src/app/dashboard/page.tsx +++ /dev/null @@ -1,14 +0,0 @@ -// src/app/jobs/dashboard/page.tsx -import * as React from 'react'; -import { AppLayout } from '../../components/AppLayout'; -import { Index } from '../../components/Dashboard'; - -const DashboardPage: React.FC = () => { - return ( - - - - ); -}; - -export default DashboardPage; diff --git a/ui/src/app/error/error.module.css b/ui/src/app/error/error.module.css deleted file mode 100644 index 056902f2..00000000 --- a/ui/src/app/error/error.module.css +++ /dev/null @@ -1,41 +0,0 @@ -/* src/app/error/error.module.css */ -.errorContainer { - text-align: center; - padding: 50px; - font-family: Arial, sans-serif; -} - -.errorTitle { - font-size: 72px; - margin-bottom: 20px; -} - -.errorMessage { - font-size: 24px; - margin-bottom: 20px; -} - -.backLink { - font-size: 20px; - color: #007bff; - text-decoration: none; - display: block; - margin-bottom: 20px; -} - -.backLink:hover { - text-decoration: underline; -} - -.orgLink { - font-size: 18px; -} - -.inlineLink { - color: #007bff; - text-decoration: none; -} - -.inlineLink:hover { - text-decoration: underline; -} diff --git a/ui/src/app/error/page.tsx b/ui/src/app/error/page.tsx deleted file mode 100644 index cbb1ef3a..00000000 --- a/ui/src/app/error/page.tsx +++ /dev/null @@ -1,42 +0,0 @@ -// src/app/error/page.tsx -'use client'; - -import React, { Suspense } from 'react'; -import { useSearchParams } from 'next/navigation'; -import styles from './error.module.css'; - -const ErrorPageContent = () => { - const searchParams = useSearchParams(); - const error = searchParams.get('error'); - - let errorMessage = 'Something went wrong.'; - if (error === 'AccessDenied') { - errorMessage = 'Whoops! You need to be a member of the InstructLab org to access this site. Try joining and then come back!'; - } - - return ( -
-

404

-

{errorMessage}

- - Return to the Login Page - -

- Want to join the InstructLab organization? Visit our - - {' '} - GitHub page - - . -

-
- ); -}; - -const ErrorPage = () => ( - Loading...}> - - -); - -export default ErrorPage; diff --git a/ui/src/app/index.tsx b/ui/src/app/index.tsx deleted file mode 100644 index 32991ff3..00000000 --- a/ui/src/app/index.tsx +++ /dev/null @@ -1,17 +0,0 @@ -// src/app/index.tsx -'use client'; - -import * as React from 'react'; -import { ThemeProvider } from '../context/ThemeContext'; -import '@patternfly/react-core/dist/styles/base.css'; -import Dashboard from './dashboard/page'; - -const Home: React.FunctionComponent = () => { - return ( - - - - ); -}; - -export default Home; diff --git a/ui/src/app/jobs/all/page.tsx b/ui/src/app/jobs/all/page.tsx deleted file mode 100644 index 093e8df0..00000000 --- a/ui/src/app/jobs/all/page.tsx +++ /dev/null @@ -1,14 +0,0 @@ -// src/app/jobs/all/page.tsx -import * as React from 'react'; -import { AppLayout } from '../../../components/AppLayout'; -import { AllJobs } from '../../../components/Jobs/All/'; - -const AllJobsPage: React.FC = () => { - return ( - - - - ); -}; - -export default AllJobsPage; diff --git a/ui/src/app/jobs/failed/page.tsx b/ui/src/app/jobs/failed/page.tsx deleted file mode 100644 index 50776047..00000000 --- a/ui/src/app/jobs/failed/page.tsx +++ /dev/null @@ -1,14 +0,0 @@ -// src/app/jobs/failed/page.tsx -import * as React from 'react'; -import { AppLayout } from '../../../components/AppLayout'; -import { FailedJobs } from '../../../components/Jobs/Failed/'; - -const FailedJobsPage: React.FC = () => { - return ( - - - - ); -}; - -export default FailedJobsPage; diff --git a/ui/src/app/jobs/pending/page.tsx b/ui/src/app/jobs/pending/page.tsx deleted file mode 100644 index 5a5c99e9..00000000 --- a/ui/src/app/jobs/pending/page.tsx +++ /dev/null @@ -1,14 +0,0 @@ -// src/app/jobs/pending/page.tsx -import * as React from 'react'; -import { AppLayout } from '../../../components/AppLayout'; -import { PendingJobs } from '../../../components/Jobs/Pending/'; - -const PendingJobsPage: React.FC = () => { - return ( - - - - ); -}; - -export default PendingJobsPage; diff --git a/ui/src/app/jobs/running/page.tsx b/ui/src/app/jobs/running/page.tsx deleted file mode 100644 index 9987de94..00000000 --- a/ui/src/app/jobs/running/page.tsx +++ /dev/null @@ -1,14 +0,0 @@ -// src/app/jobs/running/page.tsx -import * as React from 'react'; -import { AppLayout } from '../../../components/AppLayout'; -import { RunningJobs } from '../../../components/Jobs/Running/'; - -const RunningPage: React.FC = () => { - return ( - - - - ); -}; - -export default RunningPage; diff --git a/ui/src/app/jobs/success/page.tsx b/ui/src/app/jobs/success/page.tsx deleted file mode 100644 index 9158e559..00000000 --- a/ui/src/app/jobs/success/page.tsx +++ /dev/null @@ -1,14 +0,0 @@ -// src/app/jobs/success/page.tsx -import * as React from 'react'; -import { AppLayout } from '../../../components/AppLayout'; -import { SuccessJobs } from '../../../components/Jobs/Success/'; - -const SuccessJobsPage: React.FC = () => { - return ( - - - - ); -}; - -export default SuccessJobsPage; diff --git a/ui/src/app/layout.tsx b/ui/src/app/layout.tsx deleted file mode 100644 index 296e0d0c..00000000 --- a/ui/src/app/layout.tsx +++ /dev/null @@ -1,23 +0,0 @@ -// src/app/layout.tsx - -import { ReactNode } from 'react'; -import ClientProvider from '../components/ClientProviders'; -import '@patternfly/react-core/dist/styles/base.css'; -import '@patternfly/react-styles/css/components/Menu/menu.css'; - -interface RootLayoutProps { - children: ReactNode; -} - -const RootLayout = ({ children }: RootLayoutProps) => { - return ( - - - - {children} - - - ); -}; - -export default RootLayout; diff --git a/ui/src/app/login/page.tsx b/ui/src/app/login/page.tsx deleted file mode 100644 index c22aed98..00000000 --- a/ui/src/app/login/page.tsx +++ /dev/null @@ -1,109 +0,0 @@ -// src/app/login/page.tsx -'use client'; - -import React, { useState } from 'react'; -import { signIn } from 'next-auth/react'; -import { LoginFooterItem, LoginForm, LoginMainFooterLinksItem, LoginPage } from '@patternfly/react-core/dist/dynamic/components/LoginPage'; -import { ListItem, ListVariant } from '@patternfly/react-core/dist/dynamic/components/List'; - -const Login: React.FunctionComponent = () => { - const [showHelperText, setShowHelperText] = useState(false); - const [username, setUsername] = useState(''); - const [isValidUsername, setIsValidUsername] = useState(true); - const [password, setPassword] = useState(''); - const [isValidPassword, setIsValidPassword] = useState(true); - const [isRememberMeChecked, setIsRememberMeChecked] = useState(false); - - const handleUsernameChange = (event: React.FormEvent, value: string) => { - setUsername(value); - }; - - const handlePasswordChange = (event: React.FormEvent, value: string) => { - setPassword(value); - }; - - const onRememberMeClick = () => { - setIsRememberMeChecked(!isRememberMeChecked); - }; - - const onLoginButtonClick = async (event: React.MouseEvent) => { - event.preventDefault(); - const result = await signIn('credentials', { - redirect: false, - username, - password, - }); - - if (result?.error) { - setIsValidUsername(false); - setIsValidPassword(false); - setShowHelperText(true); - } else { - window.location.href = '/'; - } - }; - - const handleGitHubLogin = () => { - signIn('github', { callbackUrl: '/' }); // Redirect to home page after login - }; - - const socialMediaLoginContent = ( - - - - ); - - const listItem = ( - - - Terms of Use - - - Help - - - Privacy Policy - - - ); - - const loginForm = ( - - ); - - return ( - - {loginForm} - - ); -}; - -export default Login; diff --git a/ui/src/app/page.tsx b/ui/src/app/page.tsx deleted file mode 100644 index 44f19063..00000000 --- a/ui/src/app/page.tsx +++ /dev/null @@ -1,16 +0,0 @@ -// src/app/page.tsx -'use client'; - -import * as React from 'react'; -import { AppLayout } from '../components/AppLayout'; -import { Index } from '../components/Dashboard'; - -const HomePage: React.FC = () => { - return ( - - - - ); -}; - -export default HomePage; diff --git a/ui/src/app/playground/chat/chat.module.css b/ui/src/app/playground/chat/chat.module.css deleted file mode 100644 index f90ba646..00000000 --- a/ui/src/app/playground/chat/chat.module.css +++ /dev/null @@ -1,137 +0,0 @@ -/* Chat Container */ -.chatContainer { - display: flex; - flex-direction: column; - justify-content: flex-start; - width: 100%; - height: 90vh; - background-color: #f7f7f8; - padding: 20px; - box-sizing: border-box; -} - -/* Chat Title */ -.chatTitle { - font-size: 1.5rem; - color: #333; - margin-bottom: 20px; - text-align: center; -} - -/* Messages Container */ -.messagesContainer { - flex-grow: 1; - overflow-y: auto; - padding: 20px; - border: 1px solid #e0e0e0; - background-color: white; -} - -/* Message Styling */ -.message { - display: flex; - align-items: flex-start; - margin-bottom: 20px; - font-size: 0.9rem; /* Smaller bot font size */ -} - -.message pre { - white-space: pre-wrap; - word-wrap: break-word; - overflow-wrap: break-word; - margin: 0; - flex-grow: 1; - font-size: inherit; /* Inherit the smaller font size */ -} - -/* User Message Styling */ -.chatQuestion { - justify-content: flex-end; -} - -.userIcon { - margin-left: 10px; - margin-right: 20px; -} - -/* Bot Message Styling */ -.chatAnswer { - justify-content: flex-start; -} - -.botIcon { - margin-right: 10px; - margin-left: 0; -} - -/* Form Container within the Chat Window */ -.chatFormContainer { - display: flex; - align-items: center; - border-top: 1px solid #e0e0e0; - background-color: white; - padding: 10px; -} - -/* Form Styling */ -.chatForm { - display: flex; - width: 100%; - align-items: center; -} - -/* Input Fields Container */ -.inputFieldsContainer { - display: flex; - align-items: center; - flex-grow: 1; -} - -/* Input Fields */ -.inputFields { - display: flex; - flex-direction: column; - flex-grow: 1; - margin-right: 10px; -} - -.inputField { - margin-bottom: 10px; -} - -.sendButton { - display: flex; - align-items: center; - justify-content: center; - background-color: #007bff; - color: white; - border: none; - width: 50px; - height: 50px; - border-radius: 10px; - cursor: pointer; -} - -.sendButton:hover { - background-color: #0056b3; -} - -/* Spinner Styling */ -.spinner { - display: block; - margin: 20px auto; -} - -.modelSelector { - display: flex; - align-items: center; -} - -.modelSelectorLabel { - margin-right: 10px; - font-weight: bold; -} - -.boldLabel { - font-weight: bold; -} diff --git a/ui/src/app/playground/chat/page.tsx b/ui/src/app/playground/chat/page.tsx deleted file mode 100644 index fd9df08e..00000000 --- a/ui/src/app/playground/chat/page.tsx +++ /dev/null @@ -1,303 +0,0 @@ -// src/app/playground/chat/page.tsx -'use client'; - -import React, { useState, useRef, useEffect } from 'react'; -import { AppLayout } from '@/components/AppLayout'; -import { Button } from '@patternfly/react-core/dist/dynamic/components/Button'; -import { Form } from '@patternfly/react-core/dist/dynamic/components/Form'; -import { FormGroup } from '@patternfly/react-core/dist/dynamic/components/Form'; -import { TextInput, TextArea } from '@patternfly/react-core/'; -import { Select } from '@patternfly/react-core/dist/dynamic/components/Select'; -import { SelectOption, SelectList } from '@patternfly/react-core/dist/dynamic/components/Select'; -import { MenuToggle, MenuToggleElement } from '@patternfly/react-core/dist/dynamic/components/MenuToggle'; -import { Spinner } from '@patternfly/react-core/dist/dynamic/components/Spinner'; -import UserIcon from '@patternfly/react-icons/dist/dynamic/icons/user-icon'; -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { faBroom } from '@fortawesome/free-solid-svg-icons'; -import Image from 'next/image'; -import styles from './chat.module.css'; -import { Endpoint, Message, Model } from '@/types'; -import CopyToClipboardButton from '@/components/CopyToClipboardButton'; - -const ChatPage: React.FC = () => { - const [question, setQuestion] = useState(''); - const [systemRole, setSystemRole] = useState( - 'You are a cautious assistant. You carefully follow instructions.' + - ' You are helpful and harmless and you follow ethical guidelines and promote positive behavior.' - ); - const [messages, setMessages] = useState([]); - const [isLoading, setIsLoading] = useState(false); - const [isSelectOpen, setIsSelectOpen] = useState(false); - const [selectedModel, setSelectedModel] = useState(null); - const [customModels, setCustomModels] = useState([]); - const [defaultModels, setDefaultModels] = useState([]); - const messagesContainerRef = useRef(null); - - useEffect(() => { - const fetchDefaultModels = async () => { - const response = await fetch('/api/envConfig'); - const envConfig = await response.json(); - - const defaultModels: Model[] = [ - { name: 'Granite-7b', apiURL: envConfig.GRANITE_API, modelName: envConfig.GRANITE_MODEL_NAME }, - { name: 'Merlinite-7b', apiURL: envConfig.MERLINITE_API, modelName: envConfig.MERLINITE_MODEL_NAME }, - ]; - - const storedEndpoints = localStorage.getItem('endpoints'); - - const customModels = storedEndpoints - ? JSON.parse(storedEndpoints).map((endpoint: Endpoint) => ({ - name: endpoint.modelName, - apiURL: `${endpoint.url}`, - modelName: endpoint.modelName, - })) - : []; - - setDefaultModels(defaultModels); - setCustomModels(customModels); - setSelectedModel([...defaultModels, ...customModels][0] || null); - }; - - fetchDefaultModels(); - }, []); - - const onToggleClick = () => { - setIsSelectOpen(!isSelectOpen); - }; - - const onSelect = (_event: React.MouseEvent | undefined, value: string | number | undefined) => { - const selected = [...defaultModels, ...customModels].find((model) => model.name === value) || null; - setSelectedModel(selected); - setIsSelectOpen(false); - }; - - const toggle = (toggleRef: React.Ref) => ( - - {selectedModel ? selectedModel.name : 'Select a model'} - - ); - - const dropdownItems = [...defaultModels, ...customModels] - .filter((model) => model.name && model.apiURL && model.modelName) - .map((model, index) => ( - - {model.name} - - )); - - const handleQuestionChange = (event: React.FormEvent, value: string) => { - setQuestion(value); - }; - - const handleSystemRoleChange = (value: string) => { - setSystemRole(value); - }; - - const handleSubmit = async (event: React.FormEvent) => { - event.preventDefault(); - if (!question.trim() || !selectedModel) return; - - setMessages((messages) => [...messages, { text: question, isUser: true }]); - setQuestion(''); - - setIsLoading(true); - - const messagesPayload = [ - { role: 'system', content: systemRole }, - { role: 'user', content: question }, - ]; - - const requestData = { - model: selectedModel.modelName, - messages: messagesPayload, - stream: true, - }; - - if (customModels.some((model) => model.name === selectedModel.name)) { - // Client-side fetch if the selected model is a custom endpoint - try { - const chatResponse = await fetch(`${selectedModel.apiURL}/v1/chat/completions`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - accept: 'application/json', - }, - body: JSON.stringify(requestData), - }); - - if (!chatResponse.body) { - setMessages((messages) => [...messages, { text: 'Failed to fetch chat response', isUser: false }]); - setIsLoading(false); - return; - } - - const reader = chatResponse.body.getReader(); - const textDecoder = new TextDecoder('utf-8'); - let botMessage = ''; - - setMessages((messages) => [...messages, { text: '', isUser: false }]); - - let done = false; - while (!done) { - const { value, done: isDone } = await reader.read(); - done = isDone; - if (value) { - const chunk = textDecoder.decode(value, { stream: true }); - const lines = chunk.split('\n').filter((line) => line.trim() !== ''); - - for (const line of lines) { - if (line.startsWith('data: ')) { - const json = line.replace('data: ', ''); - if (json === '[DONE]') { - setIsLoading(false); - return; - } - - try { - const parsed = JSON.parse(json); - const deltaContent = parsed.choices[0].delta?.content; - - if (deltaContent) { - botMessage += deltaContent; - - setMessages((messages) => { - const updatedMessages = [...messages]; - updatedMessages[updatedMessages.length - 1].text = botMessage; - return updatedMessages; - }); - } - } catch (err) { - console.error('Error parsing chunk:', err); - } - } - } - } - } - - setIsLoading(false); - } catch (error) { - setMessages((messages) => [...messages, { text: 'Error fetching chat response', isUser: false }]); - setIsLoading(false); - } - } else { - // Server-side fetch for default endpoints - const response = await fetch( - `/api/playground/chat?apiURL=${encodeURIComponent(selectedModel.apiURL)}&modelName=${encodeURIComponent(selectedModel.modelName)}`, - { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ question, systemRole }), - } - ); - - if (response.body) { - const reader = response.body.getReader(); - const textDecoder = new TextDecoder('utf-8'); - let botMessage = ''; - - setMessages((messages) => [...messages, { text: '', isUser: false }]); - - (async () => { - for (;;) { - const { value, done } = await reader.read(); - if (done) break; - const chunk = textDecoder.decode(value, { stream: true }); - botMessage += chunk; - - setMessages((messages) => { - const updatedMessages = [...messages]; - updatedMessages[updatedMessages.length - 1].text = botMessage; - return updatedMessages; - }); - } - setIsLoading(false); - })(); - } else { - setMessages((messages) => [...messages, { text: 'Failed to fetch response from the server.', isUser: false }]); - setIsLoading(false); - } - } - }; - - useEffect(() => { - if (messagesContainerRef.current) { - messagesContainerRef.current.scrollTop = messagesContainerRef.current.scrollHeight; - } - }, [messages]); - - const handleCleanup = () => { - setMessages([]); - }; - - return ( - -
-
- Model Selector - - -
- System Role}> -