diff --git a/app/components/Chatbot/ChatEntry.tsx b/app/components/Chatbot/ChatEntry.tsx
index c28a2d9d..bebefc51 100644
--- a/app/components/Chatbot/ChatEntry.tsx
+++ b/app/components/Chatbot/ChatEntry.tsx
@@ -3,6 +3,7 @@ import {Link} from '@remix-run/react'
import MarkdownIt from 'markdown-it'
import QuestionMarkIcon from '~/components/icons-generated/QuestionMark'
import BotIcon from '~/components/icons-generated/Bot'
+import LinkIcon from '~/components/icons-generated/Link'
import PersonIcon from '~/components/icons-generated/Person'
import StampyIcon from '~/components/icons-generated/Stampy'
import Contents from '~/components/Article/Contents'
@@ -104,8 +105,9 @@ const Reference = ({id, title, authors, source, url, index}: Citation) => {
{' ยท '}
-
- {referenceSources[source as keyof typeof referenceSources] || new URL(url).host}
+
+ {referenceSources[source as keyof typeof referenceSources] || new URL(url).host}{' '}
+
@@ -158,7 +160,12 @@ const ChatbotReply = ({phase, content, citationsMap}: AssistantEntry) => {
}
})}
- {citations?.slice(0, MAX_REFERENCES).map(Reference)}
+ {citations && citations.length > 0 && (
+ <>
+
+ {citations?.slice(0, MAX_REFERENCES).map(Reference)}
+ >
+ )}
{phase === 'followups' ? Checking for followups...
: undefined}
)
diff --git a/app/components/Chatbot/index.tsx b/app/components/Chatbot/index.tsx
index 68682070..9412a470 100644
--- a/app/components/Chatbot/index.tsx
+++ b/app/components/Chatbot/index.tsx
@@ -3,7 +3,7 @@ import {Link, useFetcher} from '@remix-run/react'
import StampyIcon from '~/components/icons-generated/Stampy'
import SendIcon from '~/components/icons-generated/PlaneSend'
import Button from '~/components/Button'
-import {queryLLM, Entry, AssistantEntry, StampyEntry, Followup} from '~/hooks/useChat'
+import {queryLLM, Entry, AssistantEntry, StampyEntry, Followup, ChatSettings} from '~/hooks/useChat'
import ChatEntry from './ChatEntry'
import './widgit.css'
import {questionUrl} from '~/routesMapper'
@@ -138,7 +138,12 @@ const SplashScreen = ({
>
)
-export const Chatbot = ({question, questions}: {question?: string; questions?: string[]}) => {
+type ChatbotProps = {
+ question?: string
+ questions?: string[]
+ settings?: ChatSettings
+}
+export const Chatbot = ({question, questions, settings}: ChatbotProps) => {
const [followups, setFollowups] = useState()
// FIXME: Generate session id
@@ -231,7 +236,8 @@ export const Chatbot = ({question, questions}: {question?: string; questions?: s
[...history, message],
updateReply,
sessionId,
- newController
+ newController,
+ settings
)
if (!newController.signal.aborted) {
updateReply(result)
diff --git a/app/components/Chatbot/widgit.css b/app/components/Chatbot/widgit.css
index 1aaea416..a54b8512 100644
--- a/app/components/Chatbot/widgit.css
+++ b/app/components/Chatbot/widgit.css
@@ -20,3 +20,16 @@
width: 100%;
}
}
+
+.settings-container {
+ position: absolute;
+ bottom: var(--spacing-16);
+ left: var(--spacing-16);
+}
+
+.settings {
+ padding: var(--spacing-32);
+ margin-bottom: var(--spacing-24);
+ flex-direction: column;
+ gap: var(--spacing-24);
+}
diff --git a/app/hooks/useChat.ts b/app/hooks/useChat.ts
index a8563ad6..d4d6c946 100644
--- a/app/hooks/useChat.ts
+++ b/app/hooks/useChat.ts
@@ -61,7 +61,18 @@ export type SearchResult = {
result: Entry
}
-export type Mode = 'rookie' | 'concise' | 'default' | 'discord'
+type Model =
+ | 'gpt-3.5-turbo'
+ | 'gpt-4'
+ | 'gpt-4-turbo-preview'
+ | 'claude-3-opus-20240229'
+ | 'claude-3-sonnet-20240229'
+ | 'claude-3-haiku-20240307'
+export type Mode = 'rookie' | 'concise' | 'default'
+export type ChatSettings = {
+ mode?: Mode
+ completions?: Model
+}
const DATA_HEADER = 'data: '
const EVENT_END_HEADER = 'event: close'
@@ -229,7 +240,8 @@ export const extractAnswer = async (
const fetchLLM = async (
sessionId: string | undefined,
history: HistoryEntry[],
- controller: AbortController
+ controller: AbortController,
+ settings?: ChatSettings
): Promise =>
fetch(CHATBOT_URL, {
signal: controller.signal,
@@ -240,18 +252,19 @@ const fetchLLM = async (
'Content-Type': 'application/json',
Accept: 'text/event-stream',
},
- body: JSON.stringify({sessionId, history, settings: {mode: 'default'}}),
+ body: JSON.stringify({sessionId, history, settings}),
}).catch(ignoreAbort)
export const queryLLM = async (
history: HistoryEntry[],
setCurrent: (e: AssistantEntry) => void,
sessionId: string | undefined,
- controller: AbortController
+ controller: AbortController,
+ settings?: ChatSettings
): Promise => {
setCurrent({...makeEntry(), phase: 'started'})
// do SSE on a POST request.
- const res = await fetchLLM(sessionId, history, controller)
+ const res = await fetchLLM(sessionId, history, controller, settings)
if (!res) {
return {result: {role: 'error', content: 'No response from server'}}
diff --git a/app/root.css b/app/root.css
index bce98dcc..0de35ba7 100644
--- a/app/root.css
+++ b/app/root.css
@@ -392,6 +392,10 @@ svg {
cursor: pointer;
}
+.full-height {
+ height: 100%;
+}
+
/* for troubleshooting */
.pink {
diff --git a/app/routes/chat.tsx b/app/routes/chat.tsx
index 1adef68e..265c39cc 100644
--- a/app/routes/chat.tsx
+++ b/app/routes/chat.tsx
@@ -1,16 +1,37 @@
+import {useState} from 'react'
import {ShouldRevalidateFunction, useSearchParams} from '@remix-run/react'
+import SettingsIcon from '~/components/icons-generated/Settings'
import Page from '~/components/Page'
import Chatbot from '~/components/Chatbot'
+import {ChatSettings, Mode} from '~/hooks/useChat'
+import Button from '~/components/Button'
export const shouldRevalidate: ShouldRevalidateFunction = () => false
export default function App() {
const [params] = useSearchParams()
+ const [showSettings, setShowSettings] = useState(false)
+ const [chatSettings, setChatSettings] = useState({mode: 'default'} as ChatSettings)
const question = params.get('question') || undefined
+ const ModeButton = ({name, mode}: {name: string; mode: Mode}) => (
+
+ )
+
+ const stopBubbling = (e: any) => {
+ e.preventDefault()
+ e.stopPropagation()
+ e.nativeEvent.stopImmediatePropagation()
+ }
+
return (
-
+
+
+ {showSettings && (
+
+ )}
+
setShowSettings((current) => !current)}
+ />
+
)