Skip to content

Commit

Permalink
feat: add working DI for thought process. citations don't work yet
Browse files Browse the repository at this point in the history
  • Loading branch information
Shibani Basava authored and Shibani Basava committed Feb 13, 2024
1 parent e6f18be commit a8ce365
Show file tree
Hide file tree
Showing 5 changed files with 224 additions and 136 deletions.
153 changes: 18 additions & 135 deletions packages/chat-component/src/components/chat-component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,26 @@
import { LitElement, html } from 'lit';
import DOMPurify from 'dompurify';
import { customElement, property, query, state } from 'lit/decorators.js';
import { unsafeHTML } from 'lit/directives/unsafe-html.js';
import { chatHttpOptions, globalConfig, requestOptions, MAX_CHAT_HISTORY } from '../config/global-config.js';
import { chatStyle } from '../styles/chat-component.js';
import { unsafeSVG } from 'lit/directives/unsafe-svg.js';
import { chatEntryToString, newListWithEntryAtIndex } from '../utils/index.js';

// TODO: allow host applications to customize these icons

import iconLightBulb from '../../public/svg/lightbulb-icon.svg?raw';
import iconDelete from '../../public/svg/delete-icon.svg?raw';
import iconCancel from '../../public/svg/cancel-icon.svg?raw';
import iconSend from '../../public/svg/send-icon.svg?raw';
import iconClose from '../../public/svg/close-icon.svg?raw';
import iconLogo from '../../public/branding/brand-logo.svg?raw';
import iconUp from '../../public/svg/chevron-up-icon.svg?raw';

import { type TabContent } from './tab-component.js';
import { ChatController } from './chat-controller.js';
import { ChatHistoryController } from './chat-history-controller.js';
import {
lazyMultiInject,
ControllerType,
type ChatInputController,
type ChatInputFooterController,
type CitationController,
type ChatSectionController,
} from './composable.js';
import { ChatContextController } from './chat-context.js';
Expand Down Expand Up @@ -111,14 +106,6 @@ export class ChatComponent extends LitElement {
@state()
isShowingThoughtProcess = false;

@state()
selectedCitation: Citation | undefined = undefined;

@state()
selectedChatEntry: ChatThreadEntry | undefined = undefined;

selectedAsideTab: 'tab-thought-process' | 'tab-support-context' | 'tab-citations' = 'tab-thought-process';

// These are the chat bubbles that will be displayed in the chat
chatThread: ChatThreadEntry[] = [];

Expand All @@ -130,11 +117,8 @@ export class ChatComponent extends LitElement {
@lazyMultiInject(ControllerType.ChatInputFooter)
chatInputFooterComponets: ChatInputFooterController[] | undefined;

@lazyMultiInject(ControllerType.Citation)
citationControllers: CitationController[] | undefined;

@lazyMultiInject(ControllerType.ChatSection)
chatFooterComponents: ChatSectionController[] | undefined;
chatSectionControllers: ChatSectionController[] | undefined;

// Lifecycle method that runs when the component is first connected to the DOM
override connectedCallback(): void {
Expand All @@ -149,13 +133,8 @@ export class ChatComponent extends LitElement {
component.attach(this, this.chatContext);
}
}
if (this.citationControllers) {
for (const component of this.citationControllers) {
component.attach(this, this.chatContext);
}
}
if (this.chatFooterComponents) {
for (const component of this.chatFooterComponents) {
if (this.chatSectionControllers) {
for (const component of this.chatSectionControllers) {
component.attach(this, this.chatContext);
}
}
Expand Down Expand Up @@ -193,15 +172,9 @@ export class ChatComponent extends LitElement {

handleCitationClick(event: CustomEvent): void {
event?.preventDefault();
this.selectedCitation = event?.detail?.citation;

if (!this.isShowingThoughtProcess) {
if (event?.detail?.chatThreadEntry) {
this.selectedChatEntry = event?.detail?.chatThreadEntry;
}
this.handleExpandAside();
this.selectedAsideTab = 'tab-citations';
}
this.chatContext.selectedCitation = event?.detail?.citation;
this.chatContext.selectedChatEntry = event?.detail?.chatThreadEntry;
this.chatContext.setState('showCitations', true);
}

getMessageContext(): Message[] {
Expand Down Expand Up @@ -274,7 +247,7 @@ export class ChatComponent extends LitElement {
this.isChatStarted = false;
this.chatThread = [];
this.isDisabled = false;
this.selectedCitation = undefined;
this.chatContext.selectedCitation = undefined;
this.chatController.reset();
// clean up the current session content from the history too
this.chatHistoryController.saveChatHistory(this.chatThread);
Expand All @@ -293,22 +266,14 @@ export class ChatComponent extends LitElement {
this.chatController.cancelRequest();
}

// show thought process aside
handleExpandAside(event: Event | undefined = undefined): void {
event?.preventDefault();
this.isShowingThoughtProcess = true;
this.selectedAsideTab = 'tab-thought-process';
this.shadowRoot?.querySelector('#overlay')?.classList.add('active');
this.shadowRoot?.querySelector('#chat__containerWrapper')?.classList.add('aside-open');
}

// hide thought process aside
collapseAside(event: Event): void {
event.preventDefault();
this.isShowingThoughtProcess = false;
this.selectedCitation = undefined;
this.shadowRoot?.querySelector('#chat__containerWrapper')?.classList.remove('aside-open');
this.shadowRoot?.querySelector('#overlay')?.classList.remove('active');
event?.preventDefault();
if (this.chatSectionControllers) {
for (const component of this.chatSectionControllers) {
component.close();
}
}
}

renderChatOrCancelButton() {
Expand All @@ -333,64 +298,6 @@ export class ChatComponent extends LitElement {
return this.chatController.isProcessingResponse ? cancelChatButton : submitChatButton;
}

renderChatEntryTabContent(entry: ChatThreadEntry) {
return html` <tab-component
.tabs="${[
{
id: 'tab-thought-process',
label: globalConfig.THOUGHT_PROCESS_LABEL,
},
{
id: 'tab-support-context',
label: globalConfig.SUPPORT_CONTEXT_LABEL,
},
{
id: 'tab-citations',
label: globalConfig.CITATIONS_TAB_LABEL,
},
] as TabContent[]}"
.selectedTabId="${this.selectedAsideTab}"
>
<div slot="tab-thought-process" class="tab-component__content">
${entry && entry.thoughts ? html` <p class="tab-component__paragraph">${unsafeHTML(entry.thoughts)}</p> ` : ''}
</div>
<div slot="tab-support-context" class="tab-component__content">
${entry && entry.dataPoints
? html` <teaser-list-component
.alwaysRow="${true}"
.teasers="${entry.dataPoints.map((d) => {
return { description: d };
})}"
></teaser-list-component>`
: ''}
</div>
${entry && entry.citations
? html`
<div slot="tab-citations" class="tab-component__content">
<citation-list
.citations="${entry.citations}"
.label="${globalConfig.CITATIONS_LABEL}"
.selectedCitation="${this.selectedCitation}"
@on-citation-click="${this.handleCitationClick}"
></citation-list>
${this.selectedCitation
? this.citationControllers?.map((component) =>
component.render(this.selectedCitation, `${this.apiUrl}/content/${this.selectedCitation.text}`),
)
: ''}
</div>
`
: ''}
</tab-component>`;
}

handleChatEntryActionButtonClick(event: CustomEvent) {
if (event.detail?.id === 'chat-show-thought-process') {
this.selectedChatEntry = event.detail?.chatThreadEntry;
this.handleExpandAside(event);
}
}

override willUpdate(): void {
this.isDisabled = this.chatController.generatingAnswer;

Expand All @@ -408,21 +315,12 @@ export class ChatComponent extends LitElement {
renderChatThread(chatThread: ChatThreadEntry[]) {
return html`<chat-thread-component
.chatThread="${chatThread}"
.actionButtons="${[
{
id: 'chat-show-thought-process',
label: globalConfig.SHOW_THOUGH_PROCESS_BUTTON_LABEL_TEXT,
svgIcon: iconLightBulb,
isDisabled: this.isShowingThoughtProcess,
},
] as any}"
.isDisabled="${this.isDisabled}"
.isProcessingResponse="${this.chatController.isProcessingResponse}"
.selectedCitation="${this.selectedCitation}"
.selectedCitation="${this.chatContext.selectedCitation}"
.isCustomBranding="${this.isCustomBranding}"
.svgIcon="${iconLogo}"
.context="${this.chatContext}"
@on-action-button-click="${this.handleChatEntryActionButtonClick}"
@on-citation-click="${this.handleCitationClick}"
@on-followup-click="${this.handleInput}"
>
Expand All @@ -439,9 +337,10 @@ export class ChatComponent extends LitElement {

// Render the chat component as a web component
override render() {
const isAsideEnabled = this.chatSectionControllers?.some((controller) => controller.isEnabled);
return html`
<div id="overlay" class="overlay"></div>
<section id="chat__containerWrapper" class="chat__containerWrapper">
<div id="overlay" class="overlay ${isAsideEnabled ? 'active' : ''}"></div>
<section id="chat__containerWrapper" class="chat__containerWrapper ${isAsideEnabled ? 'aside-open' : ''}">
${this.isCustomBranding && !this.isChatStarted
? html` <chat-stage
svgIcon="${iconLogo}"
Expand Down Expand Up @@ -528,23 +427,7 @@ export class ChatComponent extends LitElement {
)}
</form>
</section>
<!-- ${this.isShowingThoughtProcess
? html`
<aside class="aside" data-testid="aside-thought-process">
<div class="aside__header">
<chat-action-button
.label="${globalConfig.HIDE_THOUGH_PROCESS_BUTTON_LABEL_TEXT}"
actionId="chat-hide-thought-process"
@click="${this.collapseAside}"
.svgIcon="${iconClose}"
>
</chat-action-button>
</div>
${this.renderChatEntryTabContent(this.selectedChatEntry as ChatThreadEntry)}
</aside>
`
: ''} -->
${this.chatFooterComponents?.map((component) => component.render())}
${isAsideEnabled ? this.chatSectionControllers?.map((component) => component.render()) : ''}
</section>
`;
}
Expand Down
11 changes: 11 additions & 0 deletions packages/chat-component/src/components/chat-context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,17 @@ export class ChatContextController implements ReactiveController {

private _isChatStarted: boolean = false;

private _selectedCitation: Citation | undefined = undefined;

public set selectedCitation(citation: Citation | undefined) {
this._selectedCitation = citation;
this.host.requestUpdate();
}

public get selectedCitation() {
return this._selectedCitation;
}

public set isChatStarted(value: boolean) {
this._isChatStarted = value;
this.host.requestUpdate();
Expand Down
Loading

0 comments on commit a8ce365

Please sign in to comment.