Skip to content

Instantly share code, notes, and snippets.

@berggren
Created March 5, 2024 21:01
Show Gist options
  • Save berggren/1b71714bce4345d095484f8a11b2acfa to your computer and use it in GitHub Desktop.
Save berggren/1b71714bce4345d095484f8a11b2acfa to your computer and use it in GitHub Desktop.
<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