Spaces:
Runtime error
Runtime error
import json | |
import os | |
import time | |
import random | |
import string | |
import shutil | |
import base64 | |
from pathlib import Path | |
from dotenv import load_dotenv | |
load_dotenv() | |
import streamlit as st | |
from streamlit_option_menu import option_menu | |
from streamlit_lottie import st_lottie | |
import torch | |
from langchain_community.embeddings import HuggingFaceInstructEmbeddings | |
from langchain_community.document_loaders import PyPDFLoader, TextLoader, WikipediaLoader | |
from langchain_community.vectorstores import Chroma | |
from langchain.text_splitter import RecursiveCharacterTextSplitter | |
from langchain.document_loaders.merge import MergedDataLoader | |
from langchain_groq import ChatGroq | |
from langchain.chains.combine_documents import create_stuff_documents_chain | |
from langchain_core.prompts import ChatPromptTemplate | |
from langchain.chains import create_retrieval_chain | |
# langchain-openai==0.1.6 | |
# langchain-text-splitters==0.0.1 | |
# langdetect==1.0.9 | |
# langsmith==0.1.53 | |
# --------------------------------------------------------- Helper Function/Class 1 | |
def loadLottieFile(filePath: str): | |
with open(file=filePath, mode = "r") as f: | |
return json.load(f) | |
# --------------------------------------------------------- Helper Function/Class 2 | |
def loadItOnce(container, animation, height, quality = 'high'): | |
with container.container(): | |
st_lottie(animation_source=animation, height=height, quality=quality) | |
# --------------------------------------------------------- Helper Function/Class 3 | |
def initialRampUp(llamaAnimation): | |
with st.lottie_spinner(llamaAnimation, height = 700): | |
if 'filesUploadedRecords' not in st.session_state: # To Maintain Active File Records | |
st.session_state.filesUploadedRecords = None | |
if 'vdbBuilt' not in st.session_state: # To Maintain Active Vector Database records for corresponding files | |
st.session_state.vdbBuilt = {} | |
if 'vectorDatabase' not in st.session_state: # To Maintain or hold vector database connection | |
st.session_state.vectorDatabase = {} | |
if 'collectionName' not in st.session_state: | |
st.session_state.collectionName = str(''.join(random.choices(string.ascii_letters, k=25))) | |
try: | |
shutil.rmtree('Dump') | |
except: | |
pass | |
os.makedirs('Dump', exist_ok=True) | |
time.sleep(3) | |
# --------------------------------------------------------- Helper Function/Class 4 | |
def image_to_base64(image_path): | |
with open(image_path, "rb") as img_file: | |
encoded_string = base64.b64encode(img_file.read()).decode("utf-8") | |
return encoded_string | |
def set_background_image(base64_image, opacity): | |
# Define custom CSS for setting background image | |
custom_css = f""" | |
<style> | |
[data-testid = 'stApp'] {{ | |
background-image: linear-gradient(rgba(255, 255, 255, {opacity}), rgba(255, 255, 255, {opacity})), url('data:image/jpeg;base64,{base64_image}'); | |
background-size: cover; | |
background-repeat: no-repeat; | |
background-attachment: fixed; /* Ensures the background image remains fixed */ | |
}} | |
[data-testid = 'stHeader']{{ | |
background-color: rgba(0,0,0,0); | |
}} | |
</style> | |
""" | |
# Display custom CSS using markdown | |
st.markdown(custom_css, unsafe_allow_html=True) | |
# --------------------------------------------------------- Helper Function/Class 5 | |
def navigationBar(): | |
# Use the following link to get whichever icon you'd like: | |
# https://getbootstrap.com/ | |
options = [ | |
{"label": "Retrieval Augmented Generation", "icon": "bezier"}, | |
{"label": "Fine Tuning LLMs (Coming Soon)", "icon": "gpu-card"}, | |
{"label": "Forecasting LLMs (Coming Soon)", "icon": "graph-up-arrow"} | |
] | |
selected = option_menu( | |
menu_title= None, #"Ask Me Anything", # Menu title | |
options=[option["label"] for option in options], | |
icons=[option["icon"] for option in options], | |
menu_icon="lightbulb-fill", | |
default_index=0, | |
orientation="horizontal", | |
styles={ | |
"container": { | |
"display": "flex", | |
"flex-direction": "column", | |
"justify-content": "center", | |
"padding": "20px 40px 20px 40px", # Increased top and bottom padding | |
"background-color": "#222", # Dark background color | |
"border-radius": "20px", | |
"width":"100%", | |
"box-shadow": "0px 2px 10px rgba(0, 0, 0, 0.2)", # Shadow effect | |
"margin": "auto", # Center align the navigation bar | |
"overflow-x": "auto", # Allow horizontal scrolling for small screens | |
}, | |
"menu-title": { | |
"font-size": "36px", | |
"font-weight": "bold", | |
"background-color": "#222", | |
"color": "#FFFFFF", # White text color | |
"margin-bottom": "20px", # Spacing below the menu title | |
}, | |
"menu-icon": { | |
"color": "#FFD700", # Golden yellow icon color | |
"font-size": "36px", | |
"margin-right": "10px", | |
}, | |
"icon": { | |
"color": "#FFD700", # Golden yellow icon color | |
"font-size": "36px", | |
"margin-right": "10px", | |
}, | |
"nav-link": { | |
"font-size": "20px", | |
"text-align": "center", | |
"color": "#FFFFFF", # White text color | |
"padding": "10px 20px", | |
"border-radius": "15px", | |
"transition": "background-color 0.3s ease", | |
}, | |
"nav-link-selected": { | |
"background-color": "#FF6347", # Tomato red when selected | |
"color": "#FFFFFF", # White text color when selected | |
} | |
}, | |
) | |
return selected | |
# --------------------------------------------------------- Helper Function/Class 6 | |
def loadEmbeddingsModels(): | |
DEVICE = "cuda:0" if torch.cuda.is_available() else "cpu" | |
# Constructing Embeddings function to pass as an argument in ChromaDB for Calculating Embeddings | |
return HuggingFaceInstructEmbeddings( | |
model_name = "hkunlp/instructor-base", | |
query_instruction = "Represent the query for retrieval: ", | |
model_kwargs = {"device": DEVICE}) | |
# --------------------------------------------------------- Helper Function/Class 7 | |
def removedOrAdded(files): | |
removed = {} | |
# In the beginning, when there are no files | |
# In the end when there are no files | |
if len(files) == 0: | |
if (st.session_state.filesUploadedRecords is not None) and (len(st.session_state.filesUploadedRecords) > 0): | |
removed = {st.session_state.filesUploadedRecords[0].file_id : st.session_state.filesUploadedRecords[0]} | |
st.session_state.filesUploadedRecords = None | |
return removed | |
# Files that were just removed | |
currentFileIds = [file_obj.file_id for file_obj in files] | |
for file in st.session_state.filesUploadedRecords: | |
if file.file_id not in currentFileIds: | |
removed[file.file_id] = file | |
# Removing the crossed off files from active files directory that we maintained | |
for toRemove in removed.values(): | |
st.session_state.filesUploadedRecords.remove(toRemove) | |
return removed | |
# --------------------------------------------------------- Helper Function/Class 8 | |
# To parse PDF and turn to vector embeddings | |
def buildVectorDatabase(files, query, addOrRemove): | |
""" | |
files: Either a list of fileUploader Objects with file details | |
or that one filename which was just removed by the user and should be from the vector Database as well | |
addOrRemove: if true, add else remove | |
""" | |
# Create Embeddings and Add to the Vector Store | |
if addOrRemove: | |
embeddings = loadEmbeddingsModels() | |
collName = st.session_state.collectionName | |
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1024, chunk_overlap=100) | |
loader_map = { | |
'.pdf': PyPDFLoader,# Add more mappings as needed | |
'.txt': TextLoader, | |
'wiki' : WikipediaLoader | |
} | |
docsMergedPDF = [ | |
loader_map[Path(doc).suffix.lower()](file_path=doc) | |
for doc in files | |
] | |
loadersPDF = MergedDataLoader(loaders=docsMergedPDF) | |
pagesPDF = loadersPDF.load_and_split(text_splitter) # Split into pages | |
pagesWiki = [] | |
for wikiQ in query: | |
loader = WikipediaLoader(query=wikiQ, load_max_docs=2) | |
try: | |
pagesW = loader.load_and_split(text_splitter) | |
if len(pagesW) > 0: | |
references = list(set(list(map(lambda x: x.metadata['source'], pagesW)))) | |
st.session_state.vdbBuilt['Keyword ; ' + wikiQ.strip()] = references | |
pagesWiki += pagesW | |
except Exception as e: | |
message = str(e) + '\n' + f'Looks like we could not search for your key word {wikiQ}' | |
st.toast(body=message, icon="⚠️") | |
_ = st.session_state.vdbBuilt.pop('Keyword ; ' + wikiQ.strip(), None) | |
pages = pagesPDF + pagesWiki | |
st.session_state.vectorDatabase = Chroma.from_documents(documents= pages, | |
embedding= embeddings, | |
collection_name= collName, | |
) # Load the pages into vector database (Build ChromaDB) | |
# Delete corresponding embeddings from the vector store | |
else: | |
if files is not None: | |
st.session_state.vectorDatabase._collection.delete(where={"source": {'$eq':files}}) | |
for src in query: | |
st.session_state.vectorDatabase._collection.delete(where={"source": {'$eq':src}}) | |
# --------------------------------------------------------- Helper Function/Class 9 | |
os.environ["TOKENIZERS_PARALLELISM"] = "false" | |
class RetrievalChainGenerator: | |
def __init__(self, model_name, vectorStore): | |
self.model_name = model_name | |
self.groq_api_key = os.environ['GROQ_API_KEY']#os.getenv('GROQ_API_KEY') | |
self.vectorStore = vectorStore | |
self.chain = None | |
self.generate_retrieval_chain() | |
def generate_retrieval_chain(self): | |
llm = ChatGroq(groq_api_key=self.groq_api_key, model_name=self.model_name) | |
prompt = ChatPromptTemplate.from_template(""" | |
Answer the following question based only on the provided context. | |
Think step by step before providing a detailed answer. | |
If using finance terms, briefly explain them for clarity. | |
Always return your complete response in html format. | |
I will tip you $200 if the user finds the answer helpful. | |
<context> | |
{context} | |
</context> | |
Question: {input}""") | |
promptChain = create_stuff_documents_chain(llm= llm, prompt= prompt) | |
retrieverORreferrence = self.vectorStore.as_retriever() | |
retrievalChain = create_retrieval_chain(retrieverORreferrence, promptChain) | |
self.chain = retrievalChain | |
# ---------------------------------------------------------------------------------------xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx----------------------------------------------------------- | |
# --------------------------------------------------------- Front-End Functions/Class 1 | |
import streamlit as st | |
def display_main_title(title_text, container): | |
# Define custom CSS styles for animations and title box | |
custom_css = """ | |
<style> | |
@keyframes pulse { | |
0% { transform: scale(1); box-shadow: 0 0 10px rgba(255, 99, 71, 0.7); } | |
50% { transform: scale(1.05); box-shadow: 0 0 20px rgba(255, 99, 71, 0.9); } | |
100% { transform: scale(1); box-shadow: 0 0 10px rgba(255, 99, 71, 0.7); } | |
} | |
@keyframes shimmer { | |
0% { background-position: -100%; } | |
25% { background-position: -50%; } | |
50% { background-position: 0%; } | |
75% { background-position: 50%; } | |
100% { background-position: 100%; } | |
} | |
@keyframes wiggle { | |
0% { transform: rotate(0); } | |
25% { transform: rotate(2deg); } | |
50% { transform: rotate(-2deg); } | |
75% { transform: rotate(2deg); } | |
100% { transform: rotate(0); } | |
} | |
@keyframes wavy { | |
0% { transform: translateY(0); } | |
25% { transform: translateY(-2px); } | |
50% { transform: translateY(-1px); } | |
75% { transform: translateY(-2px); } | |
100% { transform: translateY(0); } | |
} | |
@keyframes vibration { | |
0% { transform: translate(0, 0); } | |
25% { transform: translate(-1px, 1px); } | |
50% { transform: translate(1px, -1px); } | |
75% { transform: translate(-1px, -1px); } | |
100% { transform: translate(1px, 1px); } | |
} | |
.main-title-container { | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
padding: 20px; | |
border-radius: 10px; | |
box-shadow: 0 0 20px rgba(0,0,0,0.2); | |
background-color: #ff6347; | |
width: fit-content; | |
margin: 20px auto; | |
text-align: center; | |
font-size: 36px; | |
font-weight: bold; | |
color: white; | |
animation: pulse 2s infinite, vibration 0.1s infinite linear alternate; | |
position: relative; | |
overflow: hidden; | |
} | |
.main-title-text { | |
animation: wavy 10s infinite, shimmer 1s linear infinite, wiggle 1s infinite; | |
background-image: linear-gradient(to right, transparent 0%, white 50%, transparent 100%); | |
background-size: 200% 100%; | |
color: transparent; | |
-webkit-background-clip: text; | |
background-clip: text; | |
} | |
</style> | |
""" | |
# Embed custom CSS into the Streamlit app | |
st.markdown(custom_css, unsafe_allow_html=True) | |
# Display main title in a Markdown object with custom CSS class | |
container.markdown(f'<div class="main-title-container"><span class="main-title-text">{title_text}</span></div>', unsafe_allow_html=True) | |
# --------------------------------------------------------- Front-End Functions/Class 2 | |
import streamlit as st | |
def display_alert_note(message, container): | |
# Define custom CSS styles for the alert message | |
custom_css = """ | |
<style> | |
@keyframes pulse { | |
0% { transform: scale(1); } | |
50% { transform: scale(1.03); } | |
100% { transform: scale(1); } | |
} | |
@keyframes wiggle { | |
0% { transform: rotate(0deg); } | |
50% { transform: rotate(6deg); } | |
100% { transform: rotate(0deg); } | |
} | |
.alert-box { | |
position: relative; | |
padding: 20px; | |
border-radius: 10px; | |
background-image: linear-gradient(45deg, #ff4d4d, #ff416c); | |
color: white; | |
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); | |
animation: pulse 2s infinite alternate; | |
transition: transform 0.3s ease-in-out, box-shadow 0.3s ease-in-out; | |
overflow:visible; | |
} | |
.alert-box:hover { | |
transform: scale(1.05); | |
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.3); | |
animation: wiggle 0.3s infinite alternate; | |
} | |
.alert-icon { | |
position: absolute; | |
top: 40px; | |
right: 10px; | |
font-size: 24px; | |
} | |
.alert-flare { | |
} | |
</style> | |
""" | |
# Embed custom CSS into the Streamlit app | |
st.markdown(custom_css, unsafe_allow_html=True) | |
# Display the alert message in a styled text box with icons and visual effects | |
container.markdown(f'<div class="alert-flare"></div><div class="alert-box">{message}<span class="alert-icon">⚠</span></div>', unsafe_allow_html=True) | |
# --------------------------------------------------------- Front-End Functions/Class 3 | |
import streamlit as st | |
def display_attention_text(text, container): | |
# Define custom CSS styles for animations and text box | |
custom_css = """ | |
<style> | |
@keyframes slide-in { | |
0% { | |
transform: translateX(-50px); | |
opacity: 0; | |
} | |
100% { | |
transform: translateX(0); | |
opacity: 1; | |
} | |
} | |
@keyframes slide-in-top { | |
0% { | |
transform: translateY(-100%); /* Start off the screen above */ | |
opacity: 0; /* Hidden initially */ | |
} | |
100% { | |
transform: translateY(0); /* Slide in to the top */ | |
opacity: 1; /* Fully visible */ | |
} | |
} | |
.build-text-container { | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
padding: 20px; | |
border-radius: 10px; | |
background: linear-gradient(to bottom right, #ffd700, #ffdf80); | |
width: fit-content; | |
margin: 20px auto; | |
text-align: center; | |
font-size: 28px; | |
font-weight: bold; | |
color: black; | |
overflow: hidden; | |
} | |
.animated-text-in-attention { | |
display: inline-block; | |
opacity: 0; | |
animation: slide-in-top 2s ease-in-out forwards infinite; | |
} | |
/* Preserve spaces */ | |
.animated-text-in-attention.space { | |
width: 2ch; /* Adjust width to match character width */ | |
visibility: hidden; | |
} | |
</style> | |
""" | |
# Embed custom CSS into the Streamlit app | |
st.markdown(custom_css, unsafe_allow_html=True) | |
# Display text in a Markdown object with custom CSS class | |
animated_text_html = ''.join(f'<span class="animated-text-in-attention" style="animation-delay: {i * 0.0005}s;">{char}</span>' if char != ' ' else '<span class="animated-text-in-attention space"></span>' for i, char in enumerate(text)) | |
text_html = f""" | |
<div class="build-text-container"> | |
{animated_text_html} | |
</div> | |
""" | |
container.markdown(text_html, unsafe_allow_html=True) | |
# --------------------------------------------------------- Front-End Functions/Class 4 | |
import streamlit as st | |
def display_custom_arrow(direction, container): | |
# Define custom CSS styles for arrow animation | |
translateX_value = '70px' if direction.lower() == 'right' else '70px' | |
custom_css = f""" | |
<style> | |
.arrow-container {{ | |
display: flex; | |
align-items: center; | |
justify-content: center; | |
padding: 20px; | |
border-radius: 10px; | |
border: 0px solid #ffaa00; /* Border style */ | |
background: linear-gradient(45deg, rgba(255, 204, 0, 0), rgba(255, 102, 0, 0)); | |
width: fit-content; | |
overflow: visible; | |
transition: transform 0.3s ease-in-out; /* Transition effect */ | |
}} | |
.arrow-svg {{ | |
width: 100; | |
height: 30px; | |
fill: white; | |
animation: arrow-bounce 1s infinite; | |
}} | |
@keyframes arrow-bounce {{ | |
0%, 100% {{ transform: translateX(0); }} | |
50% {{ transform: translateX({translateX_value}); }} | |
}} | |
</style> | |
""" | |
# Embed custom CSS into the Streamlit app | |
container.markdown(custom_css, unsafe_allow_html=True) | |
# Define arrow SVG path based on direction | |
if direction.lower() == 'left': | |
arrow_svg = ''' | |
<svg class="arrow-svg" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> | |
<path d="M14 5l-9 9 9 9" stroke="currentColor" stroke-width="4" fill="none"/> | |
</svg> | |
''' | |
elif direction.lower() == 'right': | |
arrow_svg = ''' | |
<svg class="arrow-svg" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> | |
<path d="M10 19l9-9-9-9" stroke="currentColor" stroke-width="4" fill="none"/> | |
</svg> | |
''' | |
else: | |
pass | |
# Display arrow container with arrow SVG | |
container.markdown(f'<div class="arrow-container">{arrow_svg}</div>', unsafe_allow_html=True) | |
# --------------------------------------------------------- Front-End Functions/Class 5 | |
import streamlit as st | |
def display_heading_box(message, container): | |
# Define custom CSS for the styled text box with updated gradients, height, and animations | |
css = f""" | |
<style> | |
.styled-text-container {{ | |
padding: 10px 10px; | |
border-radius: 10px; | |
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); | |
animation: slide-in 1s ease-out forwards; /* Slide in only once */ | |
display: flex; | |
justify-content: center; /* Center horizontally */ | |
align-items: center; /* Center vertically */ | |
background: linear-gradient(135deg, #fdd835, #4caf50); /* Updated gradient colors */ | |
color: white; | |
width: fit-content; | |
height: auto; /* Adjusted height */ | |
transition: transform 0.3s ease-in-out; /* Smooth transition for transform */ | |
margin-left: auto; /* Center horizontally */ | |
margin-right: auto; | |
}} | |
@keyframes slide-in {{ | |
from {{ | |
transform: translateY(-10px); | |
opacity: 0; | |
}} | |
to {{ | |
transform: translateY(0); | |
opacity: 1; | |
}} | |
}} | |
.styled-text-container:hover {{ | |
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.2); | |
transform: scale(1.05); | |
animation: wiggle 0.5s ease-in-out infinite alternate; /* Wiggle on hover */ | |
}} | |
@keyframes wiggle {{ | |
0% {{ | |
transform: rotate(0deg); | |
}} | |
25% {{ | |
transform: rotate(-5deg); | |
}} | |
50% {{ | |
transform: rotate(5deg); | |
}} | |
75% {{ | |
transform: rotate(-5deg); | |
}} | |
100% {{ | |
transform: rotate(0deg); | |
}} | |
}} | |
</style> | |
""" | |
# Render the Markdown with the styled container and embedded text | |
styled_html = f""" | |
<div class="styled-text-container"> | |
<h3>{message}</h3> | |
</div> | |
""" | |
# Display the Markdown using Streamlit | |
st.markdown(css, unsafe_allow_html=True) | |
container.markdown(styled_html, unsafe_allow_html=True) | |
# --------------------------------------------------------- Front-End Functions/Class 6 | |
import streamlit as st | |
def display_error_message(message, container): | |
# Define custom CSS for the error message box | |
custom_css = """ | |
<style> | |
.error-container { | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
height: auto; | |
background: linear-gradient(135deg, #ff3864, #d81e5b); | |
padding: 20px; | |
border-radius: 15px; | |
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.3); | |
overflow: hidden; | |
width: auto; | |
position: relative; | |
animation: shake 0.8s cubic-bezier(0.36, 0.07, 0.19, 0.97) infinite; | |
} | |
.error-message { | |
color: #ffffff; | |
font-size: 16px; | |
font-weight: bold; | |
text-align: center; | |
opacity: 0.9; | |
} | |
@keyframes shake { | |
0%, 100% { transform: translateX(0); } | |
10%, 30%, 50%, 70%, 90% { transform: translateX(-5px); } | |
20%, 40%, 60%, 80% { transform: translateX(5px); } | |
} | |
</style> | |
""" | |
# Display custom error message using HTML with the defined CSS | |
st.markdown(custom_css, unsafe_allow_html=True) | |
container.markdown(f""" | |
<div class="error-container"> | |
<div class="error-message">{message}</div> | |
</div> | |
""", unsafe_allow_html=True) | |
# --------------------------------------------------------- Front-End Functions/Class 7 | |
import streamlit as st | |
def display_small_text(text, container): | |
# Define custom CSS styles for animations and text box | |
custom_css = """ | |
<style> | |
@keyframes flash { | |
0% { left: -100%; } | |
50% { left: 100%; } | |
100% { left: 100%; } | |
} | |
@keyframes wiggle { | |
0% { transform: rotate(0); } | |
50% { transform: rotate(2deg); } | |
100% { transform: rotate(0); } | |
} | |
@keyframes vibrate { | |
0% { transform: translate(0); } | |
25% { transform: translate(-2px, 2px); } | |
50% { transform: translate(2px, -2px); } | |
75% { transform: translate(-2px, -2px); } | |
100% { transform: translate(2px, 2px); } | |
} | |
.animated-text-container { | |
position: relative; | |
display: block; | |
padding: 10px 50px 10px 50px; | |
border-radius: 10px; | |
box-shadow: 0 0 10px rgba(0,0,0,0.1); | |
background-image: linear-gradient(45deg, #0044ff, #0099ff); | |
transition: box-shadow 0.3s ease-in-out; | |
width: fit-content; | |
margin: 20px auto; | |
text-align: center; | |
} | |
.animated-text-container:hover { | |
box-shadow: 0 0 20px rgba(255,255,255,0.5); | |
animation: vibrate 0.3s ease infinite; | |
} | |
.animated-text { | |
font-size: 24px; | |
font-weight: bold; | |
color: white; | |
display: inline-block; | |
} | |
.animated-text-container:hover .animated-text { | |
animation: wiggle 0.5s infinite alternate; | |
} | |
</style> | |
""" | |
# Embed custom CSS into the Streamlit app | |
st.markdown(custom_css, unsafe_allow_html=True) | |
# Display text in a Markdown object with custom CSS class | |
container.markdown(f'<div class="animated-text-container"><span class="animated-text">{text}</span></div>', unsafe_allow_html=True) | |
# --------------------------------------------------------- Front-End Functions/Class 8 | |
import streamlit as st | |
def display_response_message(message, container): | |
# Define custom CSS for the response message box | |
custom_css = """ | |
<style> | |
.response-container { | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
background-color: #ff6347; | |
padding: 20px; | |
border-radius: 15px; | |
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); | |
animation: pulse 1s ease infinite alternate; | |
} | |
.response-message { | |
color: white; | |
font-size: 24px; | |
text-align: center; | |
opacity: 0; | |
animation: fade-in 0.5s ease forwards, scale-up 0.5s ease forwards; | |
} | |
@keyframes pulse { | |
0% { transform: scale(1); } | |
100% { transform: scale(1.05); } | |
} | |
@keyframes fade-in { | |
0% { opacity: 0; } | |
100% { opacity: 1; } | |
} | |
@keyframes scale-up { | |
0% { transform: scale(0.8); } | |
100% { transform: scale(1); } | |
} | |
</style> | |
""" | |
# Display custom CSS for the response message | |
st.markdown(custom_css, unsafe_allow_html=True) | |
# Create a response container | |
response_container = f'<div class="response-container">' | |
# Create a container for the response message | |
response_container += '<div class="response-message">' | |
response_container += message # Add the message directly | |
response_container += '</div>' # Close the response message container | |
response_container += '</div>' # Close the response container | |
# Display the response container with the message | |
container.markdown(response_container, unsafe_allow_html=True) | |
#--------------------------------------------------------- Front-End Functions/Class 9 | |
def display_question_box(container): | |
# Define custom CSS for the question box | |
custom_css = """ | |
<style> | |
.question-box { | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
padding: 20px; | |
overflow: hidden; | |
height: 100px; /* Adjust height based on icon size */ | |
} | |
.question-icon { | |
width: 75px; | |
height: 75px; | |
fill: black; | |
animation: float-vibrate 1s infinite ease-in-out alternate, | |
rotate 2s infinite linear, | |
pulse 1s infinite alternate, | |
change-color 3s infinite, | |
scale 1.5s infinite alternate; | |
} | |
@keyframes float-vibrate { | |
0% { transform: translateY(0); } | |
50% { transform: translateY(-5px); } | |
100% { transform: translateY(0); } | |
} | |
@keyframes rotate { | |
0% { transform: rotate(0deg); } | |
100% { transform: rotate(360deg); } | |
} | |
@keyframes pulse { | |
0% { opacity: 1; } | |
50% { opacity: 0.7; } | |
100% { opacity: 1; } | |
} | |
@keyframes change-color { | |
0% { fill: black; } | |
25% { fill: red; } | |
50% { fill: green; } | |
75% { fill: blue; } | |
100% { fill: black; } | |
} | |
@keyframes scale { | |
0% { transform: scale(1); } | |
100% { transform: scale(1.2); } | |
} | |
</style> | |
""" | |
# Display custom CSS for the question box within the specified container | |
container.markdown(custom_css, unsafe_allow_html=True) | |
# Create the question box HTML structure with a question mark SVG icon | |
question_box = f""" | |
<div class="question-box"> | |
<svg class="question-icon" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> | |
<text x="12" y="12" font-size="24" text-anchor="middle" alignment-baseline="central">?</text> | |
</svg> | |
<span style="color: black; font-size: 48px;">Llama3</span> | |
</div> | |
""" | |
# Display the question box HTML within the specified container | |
container.markdown(question_box, unsafe_allow_html=True) | |
# --------------------------------------------------------- Front-End Functions/Class 10 | |
import markdown | |
import random | |
def display_citations(heading, contents, container): | |
unique_id = str(random.randint(10000000, 99999999)) | |
css_styles = f""" | |
<style> | |
@keyframes move-in-from-left {{ | |
0% {{ | |
transform: translateX(-100%); | |
opacity: 0; | |
}} | |
100% {{ | |
transform: translateX(0); | |
opacity: 1; | |
}} | |
}} | |
.fancy-container-{unique_id} {{ | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
margin: 30px auto; | |
animation: move-in-from-left 1s ease-out forwards; | |
}} | |
.fancy-card-{unique_id} {{ | |
width: 500px; | |
height: 200px; | |
perspective: 1000px; | |
position: relative; | |
border-radius: 20px; | |
overflow: hidden; /* Ensure contents do not overflow */ | |
}} | |
.fancy-card-inner-{unique_id} {{ | |
width: 100%; | |
height: 100%; | |
text-align: center; | |
transition: transform 1.25s; | |
transform-style: preserve-3d; | |
border-radius: 20px; | |
}} | |
.fancy-card-{unique_id}:hover .fancy-card-inner-{unique_id} {{ | |
transform: rotateY(180deg); | |
}} | |
.fancy-card-front-{unique_id}, .fancy-card-back-{unique_id} {{ | |
position: absolute; | |
width: 100%; | |
height: 100%; | |
backface-visibility: hidden; | |
display: flex; | |
flex-direction: column; /* Stack elements vertically */ | |
justify-content: center; | |
align-items: center; | |
font-size: 24px; | |
padding: 20px; | |
border-radius: 20px; | |
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.3); | |
overflow: hidden; /* Ensure contents do not overflow */ | |
}} | |
.fancy-card-front-{unique_id} {{ | |
background: linear-gradient(to bottom right, #000, #222); | |
color: white; | |
animation: fancy-wiggle 0.5s ease-in-out infinite; | |
}} | |
.fancy-card-front-{unique_id} h2 {{ | |
font-size: 20px; | |
font-style: italic; | |
color: white; | |
margin: 0; /* Remove default margin */ | |
padding: 10px; /* Add padding */ | |
text-align: center; /* Center align text */ | |
word-wrap: break-word; /* Ensure long words wrap */ | |
overflow-wrap: break-word; /* Ensure long words wrap */ | |
word-break: break-all; /* Ensure words break if too long */ | |
}} | |
@keyframes fancy-wiggle {{ | |
0% {{ transform: translateX(-4px); }} | |
50% {{ transform: translateX(4px); }} | |
100% {{ transform: translateX(-4px); }} | |
}} | |
.fancy-card-back-{unique_id} {{ | |
background: linear-gradient(to bottom right, #ffd700, #ffff00); | |
background-color: #f7f7f7; | |
color: #333; | |
transform: rotateY(180deg); | |
overflow: auto; /* Enable vertical and horizontal scrolling */ | |
}} | |
.fancy-card-back-{unique_id} p {{ | |
margin: 10px 0px; /* Add margin to separate paragraphs */ | |
word-break: normal; /* Ensure words break if too long */ | |
}} | |
.fancy-card-back-{unique_id} a {{ | |
color: blue; /* Make links blue */ | |
text-decoration: underline; /* Underline links */ | |
word-wrap: break-word; /* Ensure long links wrap */ | |
overflow-wrap: break-word; /* Ensure long links wrap */ | |
word-break: normal; /* Ensure words break if too long */ | |
display: inline-block; | |
}} | |
</style> | |
""" | |
# Convert markdown contents to HTML | |
html_contents = markdown.markdown(contents) | |
# Define the HTML structure for the fancy card | |
html_content = f""" | |
<div class="fancy-container-{unique_id}" id="{unique_id}"> | |
<div class="fancy-card-{unique_id}" id="{unique_id}"> | |
<div class="fancy-card-inner-{unique_id}" id="{unique_id}"> | |
<div class="fancy-card-front-{unique_id}" id="{unique_id}"> | |
<h2>{heading}</h2> | |
</div> | |
<div class="fancy-card-back-{unique_id}" id="{unique_id}"> | |
{html_contents} | |
</div> | |
</div> | |
</div> | |
</div> | |
""" | |
# Display the fancy card using Streamlit Markdown | |
st.markdown(css_styles, unsafe_allow_html=True) | |
container.markdown(html_content, unsafe_allow_html=True) | |
def display_allCitations(resp, contain): | |
for res in resp['context']: | |
if res.metadata['source'].endswith('.pdf') or res.metadata['source'].endswith('.txt'): | |
headingText = f"{res.metadata['source'].split("---")[-1]}   Page No. {res.metadata['page']}" | |
else: | |
headingText = f"{res.metadata['source']}" | |
contents_text = f"A <br> <br> <br> <br> <br> <br> <br> <br> <br> <br> <br> Content <br><br> {res.page_content}" | |
display_citations(headingText, contents_text, contain) | |
time.sleep(0.5) |