Skip to content

Commit

Permalink
use human answers when available
Browse files Browse the repository at this point in the history
  • Loading branch information
mruwnik committed Apr 29, 2024
1 parent 3307060 commit 88ded6f
Show file tree
Hide file tree
Showing 11 changed files with 285 additions and 147 deletions.
74 changes: 52 additions & 22 deletions app/components/Chatbot/ChatEntry.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
import {ComponentType} from 'react'
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 PersonIcon from '~/components/icons-generated/Person'
import StampyIcon from '~/components/icons-generated/Stampy'
import Contents from '~/components/Article/Contents'
import useGlossary from '~/hooks/useGlossary'
import './chat_entry.css'
import type {Entry, AssistantEntry, StampyEntry, Citation} from '~/hooks/useChat'
import type {Entry, AssistantEntry, StampyEntry, Citation, ErrorMessage} from '~/hooks/useChat'

const MAX_REFERENCES = 10
const hints = {
bot: 'bla bla bla something bot',
human: 'bla bla bla by humans',
error: null,
}

const AnswerInfo = ({answerType}: {answerType?: 'human' | 'bot'}) => {
if (!answerType) return null
const AnswerInfo = ({answerType}: {answerType?: 'human' | 'bot' | 'error'}) => {
if (!answerType || !hints[answerType]) return null
return (
<span className="info">
{answerType === 'human' ? <PersonIcon /> : <BotIcon />}
Expand All @@ -31,7 +34,7 @@ const AnswerInfo = ({answerType}: {answerType?: 'human' | 'bot'}) => {
type TitleProps = {
title: string
Icon: ComponentType
answerType?: 'human' | 'bot'
answerType?: 'human' | 'bot' | 'error'
}
const Title = ({title, Icon, answerType}: TitleProps) => (
<div className="flex-container title">
Expand All @@ -48,14 +51,29 @@ const UserQuery = ({content}: Entry) => (
</div>
)

// FIXME: this id should be unique across the page - I doubt it will be now
const ReferenceLink = ({id, reference}: {id: string; reference: string}) => (
<Link id={`#${id}-ref`} to={`#${id}`} className="reference-link">
{reference}
</Link>
)
const md = new MarkdownIt({html: true})
const ReferenceLink = ({id, index, text}: Citation) => {
if (!index || index > MAX_REFERENCES) return ''

const Reference = ({id, title, authors, source, url, reference}: Citation) => {
const parsed = text?.match(/^###.*?###\s+"""(.*?)"""$/ms)
return (
<>
<Link id={`${id}-ref`} to={`#${id}`} className={`reference-link ref-${index}`}>
<span>{index}</span>
</Link>
{parsed && (
<div
className="reference-contents rounded"
dangerouslySetInnerHTML={{
__html: md.render(parsed[1]),
}}
/>
)}
</>
)
}

const Reference = ({id, title, authors, source, url, index}: Citation) => {
const referenceSources = {
arxiv: 'Scientific paper',
blogs: 'Blogpost',
Expand All @@ -65,6 +83,7 @@ const Reference = ({id, title, authors, source, url, reference}: Citation) => {
arbital: 'Arbital',
distill: 'Distill',
'aisafety.info': 'AISafety.info',
youtube: 'YouTube',
}

const Authors = ({authors}: {authors?: string[]}) => {
Expand All @@ -78,8 +97,8 @@ const Reference = ({id, title, authors, source, url, reference}: Citation) => {
}

return (
<div key={id} id={`#${id}`} className="reference padding-bottom-32">
<div className="reference-num small">{reference}</div>
<div key={id} id={id} className="reference padding-bottom-32">
<div className={`reference-num small ref-${index}`}>{index}</div>
<div>
<div className="title">{title}</div>
<div>
Expand All @@ -99,9 +118,7 @@ const ChatbotReply = ({phase, content, citationsMap}: AssistantEntry) => {
citationsMap?.forEach((v) => {
citations.push(v)
})

const references = citations.map(({reference}) => reference).join('')
const referencesRegex = new RegExp(`(\\[[${references}]\\])`)
citations.sort((a, b) => a.index - b.index)

const PhaseState = () => {
switch (phase) {
Expand All @@ -128,17 +145,20 @@ const ChatbotReply = ({phase, content, citationsMap}: AssistantEntry) => {
<div>
<Title title="Stampy" Icon={StampyIcon} answerType="bot" />
<PhaseState />
<div>
{content?.split(referencesRegex).map((chunk, i) => {
if (chunk.match(referencesRegex)) {
const ref = citationsMap?.get(chunk[1])
return <ReferenceLink key={i} id={ref?.id || chunk[i]} reference={chunk[1]} />
<div className="padding-bottom-24">
{content?.split(/(\[\d+\])|(\n)/).map((chunk, i) => {
if (chunk?.match(/(\[\d+\])/)) {
const refId = chunk.slice(1, chunk.length - 1)
const ref = citationsMap?.get(refId)
return ref && <ReferenceLink key={i} {...ref} />
} else if (chunk === '\n') {
return <br key={i} />
} else {
return <span key={i}>{chunk}</span>
}
})}
</div>
{citations?.map(Reference)}
{citations?.slice(0, MAX_REFERENCES).map(Reference)}
{phase === 'followups' ? <p>Checking for followups...</p> : undefined}
</div>
)
Expand All @@ -157,11 +177,21 @@ const StampyArticle = ({pageid, content}: StampyEntry) => {
)
}

const ErrorReply = ({content}: ErrorMessage) => {
return (
<div>
<Title title="Error" Icon={StampyIcon} answerType="error" />
<div>{content}</div>
</div>
)
}

const ChatEntry = (props: Entry) => {
const roles = {
user: UserQuery,
stampy: StampyArticle,
assistant: ChatbotReply,
error: ErrorReply,
} as {[k: string]: ComponentType<Entry>}
const Role = roles[props.role] as ComponentType<Entry>
if (!Role) return null
Expand Down
57 changes: 0 additions & 57 deletions app/components/Chatbot/Widgit.tsx

This file was deleted.

81 changes: 77 additions & 4 deletions app/components/Chatbot/chat_entry.css
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,66 @@ article.stampy {
}

.chat-entry .reference-link {
background: red;
width: var(--spacing-16);
height: var(--spacing-16);
font-size: smaller;
vertical-align: super;
padding: 2px 4px;
margin-left: 2px;
border-radius: var(--border-radius);
}
.chat-entry .reference-link span {
min-width: 10px;
display: inline-block;
text-align: center;
}

.ref-1 {
background: rgb(211, 255, 253);
color: rgb(24, 185, 71);
}

.ref-2 {
background: rgb(255, 221, 244);
color: rgb(251, 0, 158);
}

.ref-3 {
background: rgb(217, 253, 254);
color: rgb(23, 184, 197);
}

.ref-4 {
background: rgb(254, 230, 202);
color: rgb(230, 107, 9);
}

.ref-5 {
background: rgb(244, 223, 255);
color: rgb(164, 3, 254);
}

.ref-6 {
background: rgb(231, 255, 178);
color: rgb(99, 159, 4);
}

.ref-7 {
background: rgb(231, 232, 255);
color: rgb(77, 75, 254);
}

.ref-8 {
background: rgb(255, 254, 156);
color: rgb(144, 140, 5);
}

.ref-9 {
background: rgb(254, 226, 226);
color: rgb(200, 0, 5);
}

.ref-10 {
background: rgb(214, 240, 255);
color: rgb(18, 144, 254);
}

.reference {
Expand All @@ -43,11 +99,28 @@ article.stampy {
.reference .reference-num {
width: var(--spacing-32);
height: var(--spacing-32);
background: red;
border-radius: 6px;
text-align: center;
}

.reference .source-link {
color: var(--colors-teal-500);
}

.reference-contents {
visibility: hidden;
transition: visibility 0.2s;
max-width: 600px;
word-wrap: break-word;
background-color: var(--colors-cool-grey-300);
padding: var(--spacing-16) var(--spacing-24);
position: absolute;
transform: translateX(50%);
text-decoration: unset;
}

.reference-contents:hover,
.reference-link:hover + .reference-contents {
visibility: visible;
transition-delay: 0s;
}
Loading

0 comments on commit 88ded6f

Please sign in to comment.