Spaces:
Build error
Build error
Update app.py
Browse files
app.py
CHANGED
|
@@ -15,12 +15,19 @@ from langchain_community.document_loaders import TextLoader
|
|
| 15 |
from langchain_text_splitters import CharacterTextSplitter
|
| 16 |
import serpapi
|
| 17 |
import requests
|
| 18 |
-
|
|
|
|
|
|
|
|
|
|
| 19 |
# Initialize logging and load environment variables
|
| 20 |
logging.basicConfig(level=logging.INFO)
|
| 21 |
logger = logging.getLogger(__name__)
|
| 22 |
load_dotenv()
|
| 23 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 24 |
# Define and validate API keys
|
| 25 |
openai_api_key = os.getenv("OPENAI_API_KEY")
|
| 26 |
serper_api_key = os.getenv("SERPER_API_KEY")
|
|
@@ -31,6 +38,116 @@ if not openai_api_key or not serper_api_key:
|
|
| 31 |
|
| 32 |
openai.api_key = openai_api_key
|
| 33 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 34 |
# Load knowledge base
|
| 35 |
@st.cache_resource
|
| 36 |
def load_knowledge_base():
|
|
@@ -182,7 +299,107 @@ for message in st.session_state.chat_history:
|
|
| 182 |
st.markdown(message["content"])
|
| 183 |
|
| 184 |
# Chat input
|
| 185 |
-
if
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 186 |
# Add user message to chat history
|
| 187 |
st.session_state.chat_history.append({"role": "user", "content": prompt})
|
| 188 |
|
|
@@ -198,7 +415,7 @@ if prompt := st.chat_input(""):
|
|
| 198 |
try:
|
| 199 |
# Generate response using the agent executor
|
| 200 |
output = agent_executor.invoke({
|
| 201 |
-
"input": f"{prompt}Be specific with numbers, dates, people, and dollar amount.Search and Provide correct sources of all the results . Respond directly to the query without any introductory phrases or meta-commentary. Your response should be natural and read as if it's addressing the query immediately, without any preamble. Create Creative Headlines using main Trust Bucket targeted always use active language like 'Lets dicover'or 'Watch it grow' etc.",
|
| 202 |
|
| 203 |
"chat_history": st.session_state.chat_history
|
| 204 |
})
|
|
@@ -206,10 +423,20 @@ if prompt := st.chat_input(""):
|
|
| 206 |
|
| 207 |
# Display the response
|
| 208 |
message_placeholder.markdown(full_response)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 209 |
except Exception as e:
|
| 210 |
logger.error(f"Error generating response: {e}")
|
| 211 |
full_response = "I apologize, but an error occurred while generating the response. Please try again."
|
| 212 |
message_placeholder.markdown(full_response)
|
| 213 |
|
| 214 |
# Add AI response to chat history
|
| 215 |
-
st.session_state.chat_history.append({"role": "assistant", "content": full_response})
|
|
|
|
|
|
| 15 |
from langchain_text_splitters import CharacterTextSplitter
|
| 16 |
import serpapi
|
| 17 |
import requests
|
| 18 |
+
import streamlit.components.v1 as components
|
| 19 |
+
import smtplib
|
| 20 |
+
from email.mime.multipart import MIMEMultipart
|
| 21 |
+
from email.mime.text import MIMEText
|
| 22 |
# Initialize logging and load environment variables
|
| 23 |
logging.basicConfig(level=logging.INFO)
|
| 24 |
logger = logging.getLogger(__name__)
|
| 25 |
load_dotenv()
|
| 26 |
|
| 27 |
+
if 'chat_active' not in st.session_state:
|
| 28 |
+
st.session_state.chat_active = False
|
| 29 |
+
|
| 30 |
+
|
| 31 |
# Define and validate API keys
|
| 32 |
openai_api_key = os.getenv("OPENAI_API_KEY")
|
| 33 |
serper_api_key = os.getenv("SERPER_API_KEY")
|
|
|
|
| 38 |
|
| 39 |
openai.api_key = openai_api_key
|
| 40 |
|
| 41 |
+
|
| 42 |
+
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
|
| 46 |
+
EMAIL_ADDRESS = os.getenv("EMAIL_ADDRESS")
|
| 47 |
+
EMAIL_PASSWORD = os.getenv("EMAIL_PASSWORD")
|
| 48 |
+
SMTP_SERVER = "mail.privateemail.com"
|
| 49 |
+
SMTP_PORT = 587
|
| 50 |
+
st.markdown("""
|
| 51 |
+
<style>
|
| 52 |
+
.custom-image img {
|
| 53 |
+
width: 100px; /* Set the width to make the image smaller */
|
| 54 |
+
height: auto; /* Keep the aspect ratio */
|
| 55 |
+
}
|
| 56 |
+
</style>
|
| 57 |
+
""", unsafe_allow_html=True)
|
| 58 |
+
|
| 59 |
+
def copy_to_clipboard(text):
|
| 60 |
+
"""Creates a button to copy text to clipboard."""
|
| 61 |
+
escaped_text = text.replace('\n', '\\n').replace('"', '\\"')
|
| 62 |
+
copy_icon_html = f"""
|
| 63 |
+
<style>
|
| 64 |
+
.copy-container {{
|
| 65 |
+
position: relative;
|
| 66 |
+
margin-top: 10px;
|
| 67 |
+
padding-bottom: 30px; /* Space for the button */
|
| 68 |
+
font-size: 0; /* Hide extra space */
|
| 69 |
+
}}
|
| 70 |
+
.copy-button {{
|
| 71 |
+
background: none;
|
| 72 |
+
border: none;
|
| 73 |
+
color: #808080; /* Grey color */
|
| 74 |
+
cursor: pointer;
|
| 75 |
+
font-size: 18px; /* Adjust icon size */
|
| 76 |
+
position: absolute;
|
| 77 |
+
bottom: 0;
|
| 78 |
+
right: 0;
|
| 79 |
+
}}
|
| 80 |
+
.copy-button:hover {{
|
| 81 |
+
color: #606060; /* Darker grey on hover */
|
| 82 |
+
}}
|
| 83 |
+
.copy-message {{
|
| 84 |
+
font-size: 12px;
|
| 85 |
+
color: #4CAF50;
|
| 86 |
+
margin-left: 10px;
|
| 87 |
+
display: none;
|
| 88 |
+
}}
|
| 89 |
+
</style>
|
| 90 |
+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
|
| 91 |
+
<div class="copy-container">
|
| 92 |
+
<button class="copy-button" onclick="copyToClipboard()">
|
| 93 |
+
<i class="fas fa-copy"></i>
|
| 94 |
+
</button>
|
| 95 |
+
<span class="copy-message" id="copy_message">Copied!</span>
|
| 96 |
+
</div>
|
| 97 |
+
|
| 98 |
+
<script>
|
| 99 |
+
function copyToClipboard() {{
|
| 100 |
+
var textArea = document.createElement("textarea");
|
| 101 |
+
textArea.value = "{escaped_text}";
|
| 102 |
+
document.body.appendChild(textArea);
|
| 103 |
+
textArea.select();
|
| 104 |
+
document.execCommand("copy");
|
| 105 |
+
document.body.removeChild(textArea);
|
| 106 |
+
|
| 107 |
+
var copyMessage = document.getElementById("copy_message");
|
| 108 |
+
copyMessage.style.display = "inline";
|
| 109 |
+
setTimeout(function() {{
|
| 110 |
+
copyMessage.style.display = "none";
|
| 111 |
+
}}, 2000);
|
| 112 |
+
}}
|
| 113 |
+
</script>
|
| 114 |
+
"""
|
| 115 |
+
components.html(copy_icon_html, height=60)
|
| 116 |
+
|
| 117 |
+
|
| 118 |
+
def feedback_email(name, email, feedback):
|
| 119 |
+
"""Sends feedback via email."""
|
| 120 |
+
recipient_email = "wajahat698@gmail.com"
|
| 121 |
+
msg = MIMEMultipart()
|
| 122 |
+
msg['From'] = EMAIL_ADDRESS
|
| 123 |
+
msg['To'] = recipient_email
|
| 124 |
+
msg['Subject'] = "Feedback"
|
| 125 |
+
msg.attach(MIMEText(feedback, 'plain'))
|
| 126 |
+
|
| 127 |
+
try:
|
| 128 |
+
with smtplib.SMTP(SMTP_SERVER, SMTP_PORT) as server:
|
| 129 |
+
server.starttls()
|
| 130 |
+
server.login(EMAIL_ADDRESS, EMAIL_PASSWORD)
|
| 131 |
+
server.sendmail(EMAIL_ADDRESS, recipient_email, msg.as_string())
|
| 132 |
+
except Exception as e:
|
| 133 |
+
st.error(f"Error sending email: {e}")
|
| 134 |
+
|
| 135 |
+
|
| 136 |
+
def get_suggestions(response_text):
|
| 137 |
+
"""Generates follow-up questions or suggestions based on the response text."""
|
| 138 |
+
prompt = f"{response_text}\n\nWhat follow-up questions or suggestions would you give ? List 1-2 only points"
|
| 139 |
+
response = openai.chat.completions.create(
|
| 140 |
+
model="gpt-4o",
|
| 141 |
+
messages=[{"role": "user", "content": prompt}]
|
| 142 |
+
)
|
| 143 |
+
suggestions = response.choices[0].message.content
|
| 144 |
+
return suggestions
|
| 145 |
+
|
| 146 |
+
|
| 147 |
+
|
| 148 |
+
|
| 149 |
+
|
| 150 |
+
|
| 151 |
# Load knowledge base
|
| 152 |
@st.cache_resource
|
| 153 |
def load_knowledge_base():
|
|
|
|
| 299 |
st.markdown(message["content"])
|
| 300 |
|
| 301 |
# Chat input
|
| 302 |
+
if not st.session_state.chat_active:
|
| 303 |
+
st.markdown("""
|
| 304 |
+
<script>
|
| 305 |
+
document.addEventListener('DOMContentLoaded', (event) => {
|
| 306 |
+
const svgs = document.querySelectorAll('svg');
|
| 307 |
+
svgs.forEach(svg => {
|
| 308 |
+
if (svg.getAttribute('xmlns') === 'http://www.w3.org/2000/svg' && svg.getAttribute('width') === '18' && svg.getAttribute('height') === '18') {
|
| 309 |
+
svg.style.display = 'none';
|
| 310 |
+
}
|
| 311 |
+
});
|
| 312 |
+
});
|
| 313 |
+
</script>
|
| 314 |
+
|
| 315 |
+
<style>
|
| 316 |
+
/* Hide all <a> elements inside elements with block-container and st-emotion-cache-1eo1tir ea3mdgi5 classes */
|
| 317 |
+
.block-container.st-emotion-cache-1eo1tir.ea3mdgi5 a {
|
| 318 |
+
display: none !important;
|
| 319 |
+
}
|
| 320 |
+
|
| 321 |
+
/* Ensure links in the sidebar are visible and underlined */
|
| 322 |
+
.stSidebar a {
|
| 323 |
+
display: inline !important;
|
| 324 |
+
text-decoration: underline !important;
|
| 325 |
+
color: inherit !important;
|
| 326 |
+
}
|
| 327 |
+
|
| 328 |
+
/* Additional styles */
|
| 329 |
+
.section-container {
|
| 330 |
+
display: flex;
|
| 331 |
+
justify-content: center;
|
| 332 |
+
align-items: stretch;
|
| 333 |
+
flex-wrap: wrap;
|
| 334 |
+
gap: 4px;
|
| 335 |
+
}
|
| 336 |
+
|
| 337 |
+
.section {
|
| 338 |
+
flex: 1;
|
| 339 |
+
min-width: 150px;
|
| 340 |
+
max-width: 90px;
|
| 341 |
+
min-height: 150px;
|
| 342 |
+
border: 1px solid #afafaf;
|
| 343 |
+
border-radius: 10px;
|
| 344 |
+
padding: 5px;
|
| 345 |
+
background-color: transparent;
|
| 346 |
+
margin: 3px;
|
| 347 |
+
text-align: center;
|
| 348 |
+
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
| 349 |
+
box-sizing: border-box;
|
| 350 |
+
font-size: 12px;
|
| 351 |
+
transition: background-color 0.3s ease;
|
| 352 |
+
}
|
| 353 |
+
|
| 354 |
+
.section h2 {
|
| 355 |
+
color: #afafaf;
|
| 356 |
+
font-size: 14px;
|
| 357 |
+
margin-bottom: 8px;
|
| 358 |
+
border-bottom: 1px solid #afafaf;
|
| 359 |
+
padding-bottom: 4px;
|
| 360 |
+
}
|
| 361 |
+
|
| 362 |
+
.section p {
|
| 363 |
+
color: #afafaf;
|
| 364 |
+
font-size: 11px;
|
| 365 |
+
margin: 5px 0;
|
| 366 |
+
line-height: 1.4;
|
| 367 |
+
}
|
| 368 |
+
|
| 369 |
+
@media (max-width: 100px) {
|
| 370 |
+
.section {
|
| 371 |
+
min-width: 90%;
|
| 372 |
+
max-width: 90%;
|
| 373 |
+
}
|
| 374 |
+
}
|
| 375 |
+
</style>
|
| 376 |
+
|
| 377 |
+
<h1 style="text-align: center; background: linear-gradient(45deg, #4b25ea, #bd18e6, #fb590e); -webkit-background-clip: text; color: transparent;">How can I help you today?</h1>
|
| 378 |
+
|
| 379 |
+
<div class="section-container">
|
| 380 |
+
<div class="section">
|
| 381 |
+
<h2>Find</h2>
|
| 382 |
+
<p>Discover all your great TrustBuilders®. <br> Example: Find Development Trust Builders® for World Vision
|
| 383 |
+
</div>
|
| 384 |
+
<div class="section">
|
| 385 |
+
<h2>Create</h2>
|
| 386 |
+
<p>Generate trust-optimised solutions : <br>Example: Find World Vision development TrustBuilders®. Then use them to write a 200-word annual report article. Enthusiastic tone.</p>
|
| 387 |
+
</div>
|
| 388 |
+
<div class="section">
|
| 389 |
+
<h2>Trust-optimise</h2>
|
| 390 |
+
<p>Paste your LinkedIn profile, EDM or blog and ask TrustAI® to improve it using specific Trust Buckets® and add your specific TrustBuilders® as examples.</p>
|
| 391 |
+
</div>
|
| 392 |
+
</div>
|
| 393 |
+
""", unsafe_allow_html=True)
|
| 394 |
+
|
| 395 |
+
else:
|
| 396 |
+
st.write("")
|
| 397 |
+
|
| 398 |
+
|
| 399 |
+
|
| 400 |
+
|
| 401 |
+
if prompt := st.chat_input("") and not st.session_state.chat_active:
|
| 402 |
+
st.session_state.chat_active= True
|
| 403 |
# Add user message to chat history
|
| 404 |
st.session_state.chat_history.append({"role": "user", "content": prompt})
|
| 405 |
|
|
|
|
| 415 |
try:
|
| 416 |
# Generate response using the agent executor
|
| 417 |
output = agent_executor.invoke({
|
| 418 |
+
"input": f"{prompt}Be specific with numbers, dates, people, and dollar amount.Search and Provide correct sources of all the results . Respond directly to the query without any introductory phrases or meta-commentary. Your response should be natural and read as if it's addressing the query immediately, without any preamble. Create Creative Headlines using main Trust Bucket targeted always use active language like 'Lets dicover'or 'Watch it grow' etc. Font and format of the respone should be same donot use any tags <br> etc strictly. ",
|
| 419 |
|
| 420 |
"chat_history": st.session_state.chat_history
|
| 421 |
})
|
|
|
|
| 423 |
|
| 424 |
# Display the response
|
| 425 |
message_placeholder.markdown(full_response)
|
| 426 |
+
follow_up_output = agent_executor.invoke({
|
| 427 |
+
"input": f"Extract 1-2 follow-up questions from the following text: {full_response}",
|
| 428 |
+
"chat_history": st.session_state.chat_history
|
| 429 |
+
})
|
| 430 |
+
follow_up_questions = follow_up_output["output"]
|
| 431 |
+
if follow_up_questions:
|
| 432 |
+
st.markdown(f"Follow-up questions:\n{follow_up_questions}")
|
| 433 |
+
|
| 434 |
+
|
| 435 |
except Exception as e:
|
| 436 |
logger.error(f"Error generating response: {e}")
|
| 437 |
full_response = "I apologize, but an error occurred while generating the response. Please try again."
|
| 438 |
message_placeholder.markdown(full_response)
|
| 439 |
|
| 440 |
# Add AI response to chat history
|
| 441 |
+
st.session_state.chat_history.append({"role": "assistant", "content": full_response})
|
| 442 |
+
copy_to_clipboard(full_response)
|