-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Jay Wang <jay@zijie.wang>
- Loading branch information
Showing
11 changed files
with
340 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
135 changes: 135 additions & 0 deletions
135
examples/rag-playground/src/components/prompt-box/prompt-box.css
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
.prompt-box { | ||
width: 100%; | ||
|
||
display: flex; | ||
box-sizing: border-box; | ||
flex-direction: column; | ||
align-items: center; | ||
|
||
padding: var(--box-padding-v) var(--box-padding-h); | ||
gap: 5px; | ||
} | ||
|
||
textarea { | ||
border: 1px solid var(--gray-300); | ||
border-radius: 5px; | ||
padding: 5px 5px; | ||
width: 100%; | ||
height: auto; | ||
box-sizing: border-box; | ||
font-family: inherit; | ||
font-size: var(--font-d2); | ||
resize: vertical; | ||
max-height: 300px; | ||
|
||
&:focus { | ||
outline: 2px solid var(--focus-border-color); | ||
border: 1px solid var(--focus-border-color); | ||
} | ||
|
||
&::placeholder { | ||
color: var(--gray-600); | ||
} | ||
} | ||
|
||
.header { | ||
font-size: var(--font-u1); | ||
color: var(--gray-600); | ||
line-height: 1; | ||
|
||
width: 100%; | ||
display: flex; | ||
flex-direction: row; | ||
justify-content: center; | ||
align-items: center; | ||
gap: 12px; | ||
|
||
.text-group { | ||
display: flex; | ||
gap: 7px; | ||
align-items: baseline; | ||
overflow: hidden; | ||
} | ||
|
||
.text { | ||
font-weight: 800; | ||
white-space: nowrap; | ||
} | ||
|
||
.token-count { | ||
font-size: var(--font-d2); | ||
color: var(--gray-600); | ||
overflow: hidden; | ||
text-overflow: ellipsis; | ||
white-space: nowrap; | ||
|
||
&[is-oversized] { | ||
color: var(--pink-500); | ||
} | ||
} | ||
} | ||
|
||
.svg-icon { | ||
display: flex; | ||
justify-content: center; | ||
align-items: center; | ||
width: 1em; | ||
height: 1em; | ||
|
||
color: currentColor; | ||
transition: transform 80ms linear; | ||
transform-origin: center; | ||
|
||
& svg { | ||
fill: currentColor; | ||
width: 100%; | ||
height: 100%; | ||
} | ||
} | ||
|
||
.button-group { | ||
display: flex; | ||
flex-flow: row; | ||
align-items: center; | ||
gap: 8px; | ||
} | ||
|
||
button { | ||
all: unset; | ||
|
||
display: flex; | ||
line-height: 1; | ||
font-size: var(--font-d2); | ||
padding: 4px 6px; | ||
border-radius: 5px; | ||
white-space: nowrap; | ||
height: var(--font-d2); | ||
|
||
cursor: pointer; | ||
user-select: none; | ||
-webkit-user-select: none; | ||
|
||
background-color: color-mix(in lab, var(--gray-200), white 20%); | ||
color: var(--gray-800); | ||
display: flex; | ||
flex-flow: row; | ||
align-items: center; | ||
font-size: var(--font-d1); | ||
|
||
&:hover { | ||
background-color: color-mix(in lab, var(--gray-300), white 30%); | ||
} | ||
|
||
&:active { | ||
background-color: color-mix(in lab, var(--gray-300), white 20%); | ||
} | ||
|
||
.svg-icon { | ||
position: relative; | ||
top: 1px; | ||
margin-right: 3px; | ||
color: var(--gray-700); | ||
width: 12px; | ||
height: 12px; | ||
} | ||
} |
152 changes: 152 additions & 0 deletions
152
examples/rag-playground/src/components/prompt-box/prompt-box.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
import { LitElement, css, unsafeCSS, html, PropertyValues } from 'lit'; | ||
import { customElement, property, state, query } from 'lit/decorators.js'; | ||
import { unsafeHTML } from 'lit/directives/unsafe-html.js'; | ||
import { encode } from 'gpt-tokenizer/model/gpt-3.5-turbo'; | ||
import d3 from '../../utils/d3-import'; | ||
|
||
import componentCSS from './prompt-box.css?inline'; | ||
import searchIcon from '../../images/icon-search.svg?raw'; | ||
import expandIcon from '../../images/icon-expand.svg?raw'; | ||
import playIcon from '../../images/icon-play.svg?raw'; | ||
|
||
const numberFormatter = d3.format(','); | ||
|
||
/** | ||
* Prompt box element. | ||
* | ||
*/ | ||
@customElement('mememo-prompt-box') | ||
export class MememoPromptBox extends LitElement { | ||
//==========================================================================|| | ||
// Class Properties || | ||
//==========================================================================|| | ||
@property({ type: String }) | ||
template: string | undefined; | ||
|
||
@property({ type: String }) | ||
userQuery: string | undefined; | ||
|
||
@property({ attribute: false }) | ||
relevantDocuments: string[] | undefined; | ||
|
||
@state() | ||
prompt = ''; | ||
|
||
@state() | ||
tokenCount = 0; | ||
|
||
//==========================================================================|| | ||
// Lifecycle Methods || | ||
//==========================================================================|| | ||
constructor() { | ||
super(); | ||
} | ||
|
||
/** | ||
* This method is called before new DOM is updated and rendered | ||
* @param changedProperties Property that has been changed | ||
*/ | ||
willUpdate(changedProperties: PropertyValues<this>) { | ||
if ( | ||
changedProperties.has('template') || | ||
changedProperties.has('userQuery') || | ||
changedProperties.has('relevantDocuments') | ||
) { | ||
this.updatePrompt(); | ||
} | ||
} | ||
|
||
//==========================================================================|| | ||
// Custom Methods || | ||
//==========================================================================|| | ||
async initData() {} | ||
|
||
/** | ||
* Recompile the prompt using template and provided information. | ||
*/ | ||
updatePrompt() { | ||
if (this.template === undefined) return; | ||
|
||
let prompt = this.template; | ||
|
||
if (this.userQuery !== undefined) { | ||
prompt = prompt.replace('{{user}}', this.userQuery); | ||
} | ||
|
||
if (this.relevantDocuments !== undefined) { | ||
const documents = this.relevantDocuments.join('\n'); | ||
prompt = prompt.replace('{{context}}', documents); | ||
} | ||
|
||
this.prompt = prompt; | ||
this.tokenCount = encode(prompt).length; | ||
} | ||
|
||
//==========================================================================|| | ||
// Event Handlers || | ||
//==========================================================================|| | ||
textareaInput(e: InputEvent) { | ||
const textareaElement = e.currentTarget as HTMLTextAreaElement; | ||
this.template = textareaElement.value; | ||
} | ||
|
||
runButtonClicked() { | ||
// Notify the parent to run the user query | ||
const event = new CustomEvent('runButtonClicked', { | ||
bubbles: true, | ||
composed: true, | ||
detail: this.template | ||
}); | ||
this.dispatchEvent(event); | ||
} | ||
|
||
//==========================================================================|| | ||
// Private Helpers || | ||
//==========================================================================|| | ||
|
||
//==========================================================================|| | ||
// Templates and Styles || | ||
//==========================================================================|| | ||
render() { | ||
return html` | ||
<div class="prompt-box"> | ||
<div class="header"> | ||
<div class="text-group"> | ||
<span class="text">Retrieval Augmented Prompt</span> | ||
<span class="token-count" ?is-oversized=${this.tokenCount > 8000} | ||
>${numberFormatter(this.tokenCount)} tokens</span | ||
> | ||
</div> | ||
<div class="button-group"> | ||
<button @click=${() => this.runButtonClicked()}> | ||
<span class="svg-icon">${unsafeHTML(playIcon)}</span> | ||
run | ||
</button> | ||
<button @click=${() => this.runButtonClicked()}> | ||
<span class="svg-icon">${unsafeHTML(expandIcon)}</span> | ||
view | ||
</button> | ||
</div> | ||
</div> | ||
<textarea rows="5" @input=${(e: InputEvent) => this.textareaInput(e)}> | ||
${this.prompt}</textarea | ||
> | ||
</div> | ||
`; | ||
} | ||
|
||
static styles = [ | ||
css` | ||
${unsafeCSS(componentCSS)} | ||
` | ||
]; | ||
} | ||
|
||
declare global { | ||
interface HTMLElementTagNameMap { | ||
'mememo-prompt-box': MememoPromptBox; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.