Skip to content

Commit

Permalink
Chat settings
Browse files Browse the repository at this point in the history
  • Loading branch information
mruwnik committed Apr 30, 2024
1 parent c55d731 commit 0522be9
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 12 deletions.
13 changes: 10 additions & 3 deletions app/components/Chatbot/ChatEntry.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down Expand Up @@ -104,8 +105,9 @@ const Reference = ({id, title, authors, source, url, index}: Citation) => {
<div>
<Authors authors={authors} />
<span>{' · '}</span>
<Link className="source-link" to={url}>
{referenceSources[source as keyof typeof referenceSources] || new URL(url).host}
<Link className="source-link" to={url} target="_blank" rel="noopener noreferrer">
{referenceSources[source as keyof typeof referenceSources] || new URL(url).host}{' '}
<LinkIcon width="16" height="16" />
</Link>
</div>
</div>
Expand Down Expand Up @@ -158,7 +160,12 @@ const ChatbotReply = ({phase, content, citationsMap}: AssistantEntry) => {
}
})}
</div>
{citations?.slice(0, MAX_REFERENCES).map(Reference)}
{citations && citations.length > 0 && (
<>
<hr />
<div className="padding-top-32">{citations?.slice(0, MAX_REFERENCES).map(Reference)}</div>
</>
)}
{phase === 'followups' ? <p>Checking for followups...</p> : undefined}
</div>
)
Expand Down
12 changes: 9 additions & 3 deletions app/components/Chatbot/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down Expand Up @@ -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<Followup[]>()

// FIXME: Generate session id
Expand Down Expand Up @@ -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)
Expand Down
13 changes: 13 additions & 0 deletions app/components/Chatbot/widgit.css
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
23 changes: 18 additions & 5 deletions app/hooks/useChat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down Expand Up @@ -229,7 +240,8 @@ export const extractAnswer = async (
const fetchLLM = async (
sessionId: string | undefined,
history: HistoryEntry[],
controller: AbortController
controller: AbortController,
settings?: ChatSettings
): Promise<Response | void> =>
fetch(CHATBOT_URL, {
signal: controller.signal,
Expand All @@ -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: settings || {mode: 'default'}}),
}).catch(ignoreAbort)

export const queryLLM = async (
history: HistoryEntry[],
setCurrent: (e: AssistantEntry) => void,
sessionId: string | undefined,
controller: AbortController
controller: AbortController,
settings?: ChatSettings
): Promise<SearchResult> => {
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'}}
Expand Down
4 changes: 4 additions & 0 deletions app/root.css
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,10 @@ svg {
cursor: pointer;
}

.full-height {
height: 100%;
}

/* for troubleshooting */

.pink {
Expand Down
43 changes: 42 additions & 1 deletion app/routes/chat.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,65 @@
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',
completions: 'gpt-3.5-turbo',
} as ChatSettings)
const question = params.get('question') || undefined

const ModeButton = ({name, mode}: {name: string; mode: Mode}) => (
<Button
className={chatSettings.mode === mode ? 'primary-alt' : ''}
action={() => setChatSettings({...chatSettings, mode})}
>
{name}
</Button>
)

const stopBubbling = (e: any) => {
e.preventDefault()
e.stopPropagation()
e.nativeEvent.stopImmediatePropagation()
}

return (
<Page noFooter>
<div className="page-body">
<div className="page-body full-height" onClick={stopBubbling}>
<Chatbot
question={question}
questions={[
'What is AI Safety?',
'How would the AI even get out in the world?',
'Do people seriously worry about existential risk from AI?',
]}
settings={chatSettings}
/>
<div className="settings-container" onClick={stopBubbling}>
{showSettings && (
<div className="settings bordered flex-container">
<div>Answer detail</div>
<ModeButton mode="default" name="Default" />
<ModeButton mode="rookie" name="Detailed" />
<ModeButton mode="concise" name="Concise" />
</div>
)}
<SettingsIcon
width="32"
height="32"
className="pointer"
onClick={() => setShowSettings((current) => !current)}
/>
</div>
</div>
</Page>
)
Expand Down

0 comments on commit 0522be9

Please sign in to comment.