Created
March 5, 2024 21:01
-
-
Save berggren/1b71714bce4345d095484f8a11b2acfa to your computer and use it in GitHub Desktop.
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
<template> | |
<v-container v-if="appStore.activeLLM" fluid style="margin-top: 5vh"> | |
<v-card flat class="mx-auto" max-width="700px" color="transparent"> | |
<template v-slot:title> | |
<h2>Forensic Research Assistant</h2> | |
</template> | |
<template v-slot:subtitle> | |
Connected to | |
<strong>{{ appStore.activeLLM.display_name }}</strong> using model | |
<strong>{{ appStore.activeLLM.model }}</strong> | |
</template> | |
<template v-slot:text> | |
<v-text-field | |
v-model="query" | |
placeholder="Your research journey starts here.." | |
prepend-inner-icon="mdi-console-line" | |
variant="outlined" | |
hide-details | |
autofocus | |
auto-grow | |
:disabled="disableInput" | |
@keydown.enter.exact.prevent="submitQuery(query, true)" | |
> | |
<template v-slot:append-inner> | |
<v-dialog v-if="prompt" max-width="700px"> | |
<template v-slot:activator="{ props }"> | |
<v-btn | |
v-bind="props" | |
size="x-small" | |
variant="text" | |
class="text-none" | |
>Full prompt</v-btn | |
> | |
</template> | |
<template v-slot:default="{ isActive }"> | |
<v-card class="pa-4"> | |
<v-card-text>{{ prompt }}</v-card-text> | |
<v-card-actions> | |
<v-spacer></v-spacer> | |
<v-btn text="Close" @click="isActive.value = false"></v-btn> | |
</v-card-actions> | |
</v-card> | |
</template> | |
</v-dialog> | |
</template> | |
</v-text-field> | |
<v-card | |
flat | |
max-height="700px" | |
max-width="700px" | |
class="overflow-auto" | |
color="transparent" | |
> | |
<v-chip-group column class="mb-3"> | |
<v-chip | |
v-for="examplePrompt in examplePrompts" | |
:key="examplePrompt" | |
size="small" | |
variant="outlined" | |
@click="exampleQuery(examplePrompt)" | |
><i>{{ examplePrompt }}</i></v-chip | |
> | |
</v-chip-group> | |
<v-skeleton-loader | |
v-if="isGenerating" | |
:loading="isGenerating" | |
type="paragraph" | |
></v-skeleton-loader> | |
<div | |
style="font-family: monospace; width: 650px" | |
:class="$vuetify.theme.name === 'dark' ? 'code-font-color' : ''" | |
v-html="summary" | |
></div> | |
<div v-if="sources.length" class="mt-8"> | |
<div v-if="suggestions.length"> | |
<strong>Follow up questions</strong> | |
<v-list density="compact" style="background-color: transparent"> | |
<v-list-item | |
v-for="(question, index) in suggestions" | |
:key="index" | |
variant="text" | |
size="small" | |
@click="followUp(question)" | |
> | |
{{ question }} | |
</v-list-item> | |
</v-list> | |
</div> | |
<strong>Sources</strong> | |
<v-chip-group column> | |
<v-chip | |
v-for="(source, index) in sources" | |
:key="index" | |
variant="tonal" | |
size="small" | |
:href="source.source" | |
target="_blank" | |
> | |
{{ source.source }} | |
</v-chip> | |
</v-chip-group> | |
</div> | |
</v-card> | |
</template> | |
</v-card> | |
</v-container> | |
</template> | |
<script> | |
import RestApiClient from "@/RestApiClient"; | |
import DOMPurify from "dompurify"; | |
import { useAppStore } from "@/stores/app"; | |
import { marked } from "marked"; | |
export default { | |
name: "Rag", | |
components: {}, | |
data() { | |
return { | |
appStore: useAppStore(), | |
query: "", | |
sources: [], | |
suggestions: [], | |
summary: "", | |
prompt: "", | |
disableInput: false, | |
isGenerating: false, | |
examplePrompts: [ | |
"What is the file structure of a gzip file?", | |
"What do you know about sqlite3?", | |
], | |
}; | |
}, | |
methods: { | |
async submitQuery(query = this.query, clearMemory = false) { | |
if (query.trim() === "") { | |
return; | |
} | |
if (clearMemory) { | |
this.clearMemory(); | |
} | |
let memory = localStorage.getItem("memory") || "[]"; | |
memory = JSON.parse(memory); | |
this.prompt = ""; | |
this.summary = ""; | |
this.sources = []; | |
this.suggestions = []; | |
this.isGenerating = true; | |
this.disableInput = true; | |
const response = await RestApiClient.sendRagPrompt( | |
query, | |
memory, | |
this.appStore.activeLLM.name | |
); | |
this.prompt = response.prompt; | |
this.summary = this.toHtml(response.summary); | |
this.sources = response.sources; | |
this.suggestions = response.suggestions; | |
this.isGenerating = false; | |
this.disableInput = false; | |
}, | |
exampleQuery(query) { | |
this.clearMemory(); | |
this.query = query; | |
this.submitQuery(query); | |
}, | |
followUp(question) { | |
this.addMemory(this.query); | |
this.query = question; | |
this.prompt = this.submitQuery(question); | |
}, | |
addMemory(query) { | |
let memory = localStorage.getItem("memory") || "[]"; | |
memory = JSON.parse(memory); | |
memory.push(query); | |
console.log("memory addMemory", memory); | |
localStorage.setItem("memory", JSON.stringify(memory)); | |
}, | |
clearMemory() { | |
let memory = []; | |
localStorage.setItem("memory", JSON.stringify(memory)); | |
}, | |
toHtml(markdown) { | |
return DOMPurify.sanitize(marked(markdown)); | |
}, | |
}, | |
mounted() { | |
this.$eventBus.on("llm-changed", (data) => { | |
this.submitQuery(); | |
}); | |
}, | |
}; | |
</script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment