From f3d5055e1d34a26ba81f6e8e6858054deade0d39 Mon Sep 17 00:00:00 2001
From: Jon Kafton <939376+jonkafton@users.noreply.github.com>
Date: Wed, 5 Feb 2025 22:12:20 +0100
Subject: [PATCH 01/18] Update chat page to use Smoot Design AiChat
---
frontends/main/package.json | 2 +-
.../main/src/app-pages/ChatPage/ChatPage.tsx | 61 +++-----------
frontends/main/src/app-pages/ChatPage/send.ts | 78 ------------------
.../AiRecommendationBot.tsx | 79 +++++++++++++++++++
yarn.lock | 25 +++++-
5 files changed, 115 insertions(+), 130 deletions(-)
delete mode 100644 frontends/main/src/app-pages/ChatPage/send.ts
create mode 100644 frontends/main/src/page-components/AiRecommendationBot/AiRecommendationBot.tsx
diff --git a/frontends/main/package.json b/frontends/main/package.json
index 2b3985f5ce..171a5236d3 100644
--- a/frontends/main/package.json
+++ b/frontends/main/package.json
@@ -14,7 +14,7 @@
"@emotion/cache": "^11.13.1",
"@emotion/styled": "^11.11.0",
"@mitodl/course-search-utils": "3.3.2",
- "@mitodl/smoot-design": "^3.0.1",
+ "@mitodl/smoot-design": "^3.1.0",
"@next/bundle-analyzer": "^14.2.15",
"@nlux/react": "^2.17.1",
"@nlux/themes": "^2.17.1",
diff --git a/frontends/main/src/app-pages/ChatPage/ChatPage.tsx b/frontends/main/src/app-pages/ChatPage/ChatPage.tsx
index 056719b8ab..62349c8b00 100644
--- a/frontends/main/src/app-pages/ChatPage/ChatPage.tsx
+++ b/frontends/main/src/app-pages/ChatPage/ChatPage.tsx
@@ -1,61 +1,22 @@
"use client"
-import React, { useMemo } from "react"
-import { makeSend } from "./send"
-import { FeatureFlags } from "@/common/feature_flags"
-import { useFeatureFlagEnabled } from "posthog-js/react"
-import StyledContainer from "@/page-components/StyledContainer/StyledContainer"
+import React from "react"
import { styled } from "ol-components"
-import { NluxAiChat } from "@/page-components/Nlux-AiChat/AiChat"
+import AiRecommendationBot from "@/page-components/AiRecommendationBot/AiRecommendationBot"
-const StyledChat = styled(NluxAiChat)({
- maxHeight: "60vh",
- flex: 1,
+const Container = styled.div({
+ height: "100%",
+ padding: "24px 0",
+ display: "flex",
+ alignItems: "center",
+ justifyContent: "center",
})
-const CONVERSATION_OPTIONS = {
- conversationStarters: [
- {
- prompt:
- "I'm interested in courses on quantum computing that offer certificates.",
- },
- {
- prompt:
- "I want to learn about global warming, can you recommend any videos?",
- },
- {
- prompt:
- "I am curious about AI applications for business. Do you have any free courses about that?",
- },
- {
- prompt:
- "I would like to learn about linear regression, preferably at no cost.",
- },
- ],
-}
-
const ChatPage = () => {
- const recommendationBotEnabled = useFeatureFlagEnabled(
- FeatureFlags.RecommendationBot,
- )
- const send = useMemo(() => {
- return makeSend({ url: "/api/v0/chat_agent/" })
- }, [])
return (
-
- {
- // eslint-disable-next-line no-constant-condition
- recommendationBotEnabled ? (
-
- ) : (
- <>>
- )
- }
-
+
+
+
)
}
diff --git a/frontends/main/src/app-pages/ChatPage/send.ts b/frontends/main/src/app-pages/ChatPage/send.ts
deleted file mode 100644
index edcc672760..0000000000
--- a/frontends/main/src/app-pages/ChatPage/send.ts
+++ /dev/null
@@ -1,78 +0,0 @@
-import { NluxAiChatProps } from "@/page-components/Nlux-AiChat/AiChat"
-
-function getCookie(name: string) {
- const value = `; ${document.cookie}`
- const parts = value.split(`; ${name}=`)
- if (parts.length === 2) {
- return parts.pop()?.split(";").shift()
- }
-}
-
-type EndpointOpts = {
- url: "/api/v0/chat_agent/"
- extraBody?: Record
-}
-
-const makeRequest = async (opts: EndpointOpts, message: string) =>
- fetch(`${process.env.NEXT_PUBLIC_MITOL_API_BASE_URL}${opts.url}`, {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- "X-CSRFToken":
- getCookie(process.env.NEXT_PUBLIC_CSRF_COOKIE_NAME || "csrftoken") ??
- "",
- },
- credentials: "include", // TODO Remove this, should be handled by same-origin
- body: JSON.stringify({ message, ...opts.extraBody }),
- })
-
-const RESPONSE_DELAY = 500
-
-// Function to send query to the server and receive a stream of chunks as response
-const makeSend =
- (
- opts: EndpointOpts,
- processContent: (content: string) => string = (content) => content,
- ): NluxAiChatProps["send"] =>
- async (message, observer) => {
- const response = await makeRequest(opts, message)
-
- if (response.status !== 200) {
- observer.error(new Error("Failed to connect to the server"))
- return
- }
-
- if (!response.body) {
- return
- }
-
- // Read a stream of server-sent events
- // and feed them to the observer as they are being generated
- const reader = response.body.getReader()
- const textDecoder = new TextDecoder()
-
- // eslint-disable-next-line no-constant-condition
- while (true) {
- const { value, done } = await reader.read()
- if (done) {
- /**
- * Without the pause here, some messages were getting displayed completely
- * empty. Unsure why.
- *
- * Maybe related to stream having only a single chunk?
- */
- await new Promise((res) => setTimeout(res, RESPONSE_DELAY))
- break
- }
-
- const content = textDecoder.decode(value)
- if (content) {
- observer.next(processContent(content))
- }
- }
-
- observer.complete()
- }
-
-export { makeSend }
-export type { EndpointOpts }
diff --git a/frontends/main/src/page-components/AiRecommendationBot/AiRecommendationBot.tsx b/frontends/main/src/page-components/AiRecommendationBot/AiRecommendationBot.tsx
new file mode 100644
index 0000000000..8850516769
--- /dev/null
+++ b/frontends/main/src/page-components/AiRecommendationBot/AiRecommendationBot.tsx
@@ -0,0 +1,79 @@
+import React from "react"
+import { styled } from "ol-components"
+import { getCsrfToken } from "@/common/utils"
+
+import { AiChat, AiChatProps } from "@mitodl/smoot-design/ai"
+
+const Container = styled.div(({ theme }) => ({
+ width: "800px",
+ height: "100%",
+ [theme.breakpoints.down("md")]: {
+ width: "100%",
+ },
+}))
+
+const AiChatStyled = styled(AiChat)({
+ height: "60vh",
+})
+
+const INITIAL_MESSAGES: AiChatProps["initialMessages"] = [
+ {
+ content: "What do you want to learn about today?",
+ role: "assistant",
+ },
+ {
+ content:
+ "I'm interested in courses on quantum computing that offer certificates.",
+ role: "user",
+ },
+]
+
+export const STARTERS = [
+ {
+ content:
+ "I'm interested in courses on quantum computing that offer certificates.",
+ },
+ {
+ content:
+ "I want to learn about global warming, can you recommend any videos?",
+ },
+ {
+ content:
+ "I am curious about AI applications for business. Do you have any free courses about that?",
+ },
+ {
+ content:
+ "I would like to learn about linear regression, preferably at no cost.",
+ },
+]
+
+const AiRecommendationBot = () => {
+ return (
+
+ ({
+ message: messages[messages.length - 1].content,
+ }),
+ // onFinish: (message) => {
+ // const contentParts = message.content.split("