katara / static /index.html
dkdaniz's picture
Rename home.html to static/index.html
7abeac3
raw
history blame
21.6 kB
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- Bootstrap CSS -->
<link rel="icon" type="image" href="static\social_icons\favicon.png" />
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>
<title>localGPT</title>
</head>
<script>
function openFileSelection() {
const fileInput = document.getElementById("fileInput");
fileInput.accept = ".csv, .pdf, .txt, .doc";
fileInput.click();
fileInput.addEventListener("change", handleFileSelection);
}
function handleFileSelection(event) {
// You can perform some checks on the files here if you want
// Open the modal after file selection
const uploadModal = new bootstrap.Modal(
document.getElementById("uploadModal"),
);
uploadModal.show();
}
function submitPromptForm() {
// Show the modal
$("#responseModal").modal("show");
// Submit the form after a short delay to allow the modal to open
setTimeout(function () {
document.getElementById("promptForm").submit();
}, 5);
}
function submitForm(action) {
var form = document.getElementById("uploadForm");
var input = document.createElement("input");
input.type = "hidden";
input.name = "action";
input.value = action;
form.appendChild(input);
// After the form is submitted, close the current modal and open the new one.
$("#uploadModal").on("hidden.bs.modal", function () {
$("#ingesting-modal").modal("show");
});
if (action == "add" || action == "reset") {
$("#uploadModal").modal("hide");
}
form.submit();
}
</script>
{% if show_response_modal %}
<script>
$(document).ready(function () {
$("#response_modal").modal("show");
});
</script>
{% endif %}
<style>
@import url('https://fonts.googleapis.com/css2?family=Play:wght@400;700&display=swap');
body {
background-image: linear-gradient(90deg, #09203f, #0057ff);
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
.container{
padding: 15px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
max-width: 1000px;
margin: 0 auto;
}
.titlegpt{
font-size: 9vw;
color: white;
font-family: 'Play', sans-serif;
}
.search {
width: 100%;
box-shadow:
inset 0 1px 1px rgba(0, 0, 0, 0.075),
0 0 8px rgba(255, 0, 0, 0.6);
background-color: #fff;
padding: 4px;
border-radius: 5px;
}
::placeholder {
color: rgb(110, 104, 104);
opacity: 1;
}
.search-2 {
position: relative;
width: 100%;
}
.search-2 input {
height: 45px;
border: none;
width: 100%;
padding-left: 100px;
padding-right: 200px;
}
.search-2 input:focus {
border-color: none;
box-shadow: none;
outline: none;
}
.search-2 i {
position: absolute;
top: 12px;
left: -10px;
font-size: 24px;
color: #eee;
}
.search-2 button {
position: absolute;
right: 100px;
top: 0px;
border: none;
height: 45px;
background-color: #ff0059;
color: #fff;
width: 90px;
border-radius: 4px;
}
.search-2 button:hover {
background: #ff0059;
color: #ffffff;
transition: all 0.2s ease;
cursor: pointer;
}
.search-2 .upload_button {
position: absolute;
right: 1px;
top: 0px;
border: none;
height: 45px;
background-color: #ff0059;
color: #fff;
width: 90px;
border-radius: 4px;
}
.cancel_button {
border: none;
height: 45px;
background-color: gray;
color: #fff;
width: 90px;
border-radius: 4px;
}
.cancel_button:hover {
background: rgb(114, 113, 113);
color: #ffffff;
transition: all 0.2s ease;
cursor: pointer;
}
.default_button {
border: none;
height: 45px;
background-color: #ff0059;
color: #fff;
width: 90px;
border-radius: 4px;
}
.default_button:hover {
background: #ff0059;
color: #ffffff;
transition: all 0.2s ease;
cursor: pointer;
}
.upload_button:hover {
background: #ff0059;
color: #ffffff;
transition: all 0.2s ease;
cursor: pointer;
}
.search-2 .tutorial_button {
position: absolute;
left: 1px;
top: 0px;
border: none;
height: 45px;
background-color: #ff0059;
color: #fff;
width: 90px;
border-radius: 4px;
}
.tutorial_button:hover {
background: #ff0059;
color: #ffffff;
transition: all 0.2s ease;
cursor: pointer;
}
.form-control:focus {
border-color: #bc13cf;
box-shadow:
inset 0 1px 1px rgba(0, 0, 0, 0.075),
0 0 8px rgba(255, 0, 0, 0.6);
}
@media (max-width: 800px) {
.search-2 i {
left: 4px;
}
.search-2 input {
padding-left: 34px;
}
.search-2 button {
height: 37px;
top: 5px;
}
.search-2 .tutorial_button {
height: 37px;
top: 5px;
}
.search-2 .upload_button {
height: 37px;
top: 5px;
}
.search-2 input {
height: 45px;
border: none;
width: 100%;
padding-left: 100px;
padding-right: 200px;
}
.default_button {
height: 37px;
}
.cancel_button {
height: 37px;
}
}
.accordion-button:focus {
z-index: 3;
border-color: #ff0059;
box-shadow: 0 0 0 0.25rem rgba(153, 50, 168, 0.25);
}
.accordion-button:not(.collapsed) {
color:#ff0059;
background-color: #f5b3cb;
box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.125);
}
</style>
<body>
<div class="container">
<div class="titlegpt">LocalGPT</div>
<div class="search">
<div class="row">
<div class="col-md-12">
<div class="search-2">
<form
id="promptForm"
action="{{ url_for('home_page') }}"
method="POST"
>
<button
type="button"
class="tutorial_button"
data-bs-toggle="modal"
data-bs-target="#tutorial_modal"
>
Tutorial
</button>
<i class="bx bxs-map"></i>
<input
type="text"
name="user_prompt"
id="searchInput"
placeholder="Tell a summary of what you want to know?"
/>
<button type="button" onclick="submitPromptForm()">
Search
</button>
</form>
<form
id="uploadForm"
action="{{ url_for('home_page') }}"
method="POST"
enctype="multipart/form-data"
>
<input
type="file"
name="documents"
id="fileInput"
style="display: none"
multiple
/>
<button
type="button"
class="upload_button"
onclick="openFileSelection()"
>
Upload
</button>
</form>
</div>
</div>
</div>
</div>
</div>
<!-- For some reason the script needs to go here to make the the enter key also trigger the generating response modal -->
<script>
document
.getElementById("searchInput")
.addEventListener("keydown", function (event) {
if (event.keyCode === 13) {
event.preventDefault(); // Prevent form submission
submitPromptForm(); // Call the function to show the modal
}
});
</script>
<!-- Chat Response Modal -->
<div
class="modal fade"
id="response_modal"
tabindex="-1"
aria-labelledby="response_modal"
aria-hidden="true"
>
<div class="modal-dialog modal-xl modal-dialog-centered">
<div class="modal-content">
<div class="modal-header text-center">
<h5
class="modal-title w-100"
id="response_modal"
style="color: #292b2c"
>
Response
</h5>
</div>
<div class="modal-body text-center" style="color: #292b2c">
<strong>Search</strong>
<br />
<p>{{response_dict['Prompt']}}</p>
<strong>Answer</strong>
<br />
<p style="margin-left: 5%; margin-right: 5%">
{{response_dict['Answer']}}
</p>
<strong>Sources</strong>
<div
class="accordion"
id="accordionExample"
style="margin-top: 10px"
>
{% for item in response_dict['Sources'] %}
<div class="accordion-item">
<h2
class="accordion-header text-center"
id="heading{{ loop.index0 }}"
>
<button
class="accordion-button d-block text-center"
type="button"
data-bs-toggle="collapse"
data-bs-target="#collapse{{ loop.index0 }}"
aria-expanded="true"
aria-controls="collapse{{ loop.index0 }}"
>
{{ item[0] }}
<!-- Source -->
</button>
</h2>
<div
id="collapse{{ loop.index0 }}"
class="accordion-collapse collapse {% if loop.first %}show{% endif %}"
aria-labelledby="heading{{ loop.index0 }}"
data-bs-parent="#accordionExample"
>
<div
class="accordion-body"
style="
text-align: justify;
margin-left: 5%;
margin-right: 5%;
"
>
{{ item[1] }}
<!-- Content -->
</div>
</div>
</div>
{% endfor %}
</div>
</div>
<div class="modal-footer">
<button
type="button"
class="default_button"
data-bs-dismiss="modal"
>
Close
</button>
</div>
</div>
</div>
</div>
<!-- Generating Response Modal -->
<div
class="modal fade"
id="responseModal"
tabindex="-1"
aria-labelledby="responseModalLabel"
aria-hidden="true"
data-bs-backdrop="static"
data-bs-keyboard="false"
>
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header justify-content-center">
<h5
class="modal-title justify-content-center"
id="responseModalLabel"
>
Generating Response
</h5>
</div>
<div class="modal-body text-center">
<p>Please wait...</p>
</div>
</div>
</div>
</div>
<!-- Upload Confirmation Modal -->
<div
class="modal fade"
id="uploadModal"
tabindex="-1"
aria-labelledby="uploadModalLabel"
aria-hidden="true"
>
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header justify-content-center">
<h5
class="modal-title justify-content-center"
id="uploadModalLabel"
>
File Upload Confirmation
</h5>
</div>
<div class="modal-body margin-left: 5%; text-align: left;">
<ul>
<li>
Click
<span style="background-color: #ff0059; color: white">Add</span> if
you want to add the documents selected to your pre-existing
knowledge base.
</li>
<br />
<li>
Click
<span style="background-color: #ff0059; color: white">Reset</span>
if you want to reset your knowledge base, and then use your new
documents as your new knowledge base.
</li>
<br />
<li>
Click
<span style="background-color: gray; color: white">Cancel</span>
if you don't want to make any changes.
</li>
</ul>
</div>
<div class="modal-footer justify-content-center">
<button
type="submit"
name="button_clicked"
value="add_document"
class="default_button"
onclick="submitForm('add')"
>
Add
</button>
<button
type="submit"
name="button_clicked"
value="reset_document"
class="default_button"
onclick="submitForm('reset')"
>
Reset
</button>
<button type="button" class="cancel_button" data-bs-dismiss="modal">
Cancel
</button>
</div>
</div>
</div>
</div>
<!-- Ingesting Documents Modal -->
<div
class="modal fade"
id="ingesting-modal"
tabindex="-1"
role="dialog"
data-bs-backdrop="static"
data-bs-keyboard="false"
>
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header justify-content-center">
<h5 class="modal-title">Ingesting Documents...</h5>
</div>
<div class="modal-body text-center">
<p>Please wait while we ingest the documents.</p>
</div>
</div>
</div>
</div>
<!-- Tutorial Modal -->
<div
class="modal fade"
id="tutorial_modal"
tabindex="-1"
aria-labelledby="tutorial_modal"
aria-hidden="true"
>
<div class="modal-dialog modal-xl modal-dialog-centered">
<div class="modal-content">
<div class="modal-header text-center">
<h5
class="modal-title w-100"
id="tutorial_modal"
style="color: #292b2c"
>
Tutorial
</h5>
</div>
<div class="modal-body" style="color: #292b2c">
<strong style="margin-left: 5%; text-align: left">About</strong>
<br />
<p style="text-align: justify; margin-left: 5%; margin-right: 5%">
Introducing a cutting-edge application that empowers users to
leverage the capabilities of a language model, even in the absence
of an internet connection. This advanced tool serves as an
indispensable resource for accessing information beyond the
confines of traditional language model tools such as chatGPT.
<br /><br />
One of the key advantages of this application is the preservation
of data control. This feature becomes particularly valuable when
handling sensitive data that must remain within the confines of an
organization or personal documents that warrant utmost
confidentiality, eliminating the need to transmit information
through third-party channels.
<br /><br />
Seamlessly integrating personal documents into the system is
effortless, ensuring a smooth user experience. Whether in the form
of text, PDF, CSV, or Excel files, users can conveniently provide
the desired information for inquiry. The application swiftly
processes these documents, effectively creating a comprehensive
database for the model to leverage, enabling accurate and
insightful responses.
<br /><br />
A notable benefit of this approach lies in its efficient resource
utilization. Unlike the resource-intensive retraining processes
employed by alternative methods, the ingestion of documents within
this application demands significantly less compute power. This
efficiency optimization allows for a streamlined user experience,
saving both time and computational resources.
<br /><br />
Discover the unparalleled capabilities of this technical marvel,
as it enables users to tap into the full potential of language
models, all while operating offline. Experience a new era of
information access, bolstering productivity and expanding
possibilities. Embrace this powerful tool and unlock the true
potential of your data today.
</p>
<strong style="margin-left: 5%; text-align: left"
>Upload Documents</strong
>
<br />
<p
style="
line-height: 1.75;
margin-left: 5%;
margin-right: 5%;
text-align: left;
"
>
1. To upload documents for the app to ingest as its new knowledge
base click the
<span style="background-color: #ff0059; color: white">Upload</span>
button.
<br />
2. Select the documents you want to serve as your new knowledge
base to converse with.
<br />
3. Then you will be prompted with a confirmation to either
<span style="background-color: #ff0059; color: white">Add</span> the
documents to your knowledge base,
<span style="background-color: #ff0059; color: white">Reset</span>
your knowledge base with the documents you just selected, or
<span style="background-color: gray; color: white">Cancel</span>
the upload.
<br />
4. There will be a short wait time as the documents get ingested
into the vector database as your new knowledge base.
</p>
<a
href="static/document_examples/constitution.pdf"
style="margin-left: 5%"
download
>
<button class="default_button" style="width: auto">
Example Constitution
</button>
</a>
<a href="static/document_examples/news_articles.zip" download>
<button class="default_button" style="width: auto">
Example News Articles
</button>
</a>
<br />
<br />
<strong style="margin-left: 5%; text-align: left">Searching</strong>
<p
style="
line-height: 1.75;
margin-left: 5%;
margin-right: 5%;
text-align: left;
"
>
1. In order to ask a question, type a question into the search bar
like:
<br />
2.
<span style="background-color: gray; color: white"
>Give me a summary of the documents</span
>
<br />
3. Hit enter on your keyboard or click
<span style="background-color: #ff0059; color: white">Search</span>
<br />
4. Wait while the LLM model consumes the prompt and prepares the
answer.
<br />
5. Once done, it will print the answer and the 4 sources it used
as context from your documents; you can then ask another question
without re-running the script, just wait for the prompt again.
</p>
<br />
</div>
<div class="modal-footer justify-content-center">
<button
type="button"
class="default_button"
data-bs-dismiss="modal"
>
Close
</button>
</div>
</div>
</div>
</div>
</body>
</html>