Spaces:
Paused
Paused
<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="static\dependencies\jquery\3.6.0\jquery.min.js"></script> | |
<script src="static\dependencies\bootstrap-5.1.3-dist\js\bootstrap.min.js"></script> | |
<link | |
rel="stylesheet" | |
href="static\dependencies\bootstrap-5.1.3-dist\css\bootstrap.min.css" | |
/> | |
<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> | |