Spaces:
Build error
Build error
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
| 1 |
import logging
|
| 2 |
import os
|
| 3 |
-
import streamlit as st
|
| 4 |
from dotenv import load_dotenv
|
| 5 |
import openai
|
| 6 |
from langchain_openai import ChatOpenAI
|
|
@@ -14,7 +14,7 @@ from langchain_core.messages import AIMessage, HumanMessage
|
|
| 14 |
from langchain_community.document_loaders import TextLoader
|
| 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
|
|
@@ -27,14 +27,126 @@ import smtplib
|
|
| 27 |
from email.mime.multipart import MIMEMultipart
|
| 28 |
from email.mime.text import MIMEText
|
| 29 |
from markdownify import markdownify
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 30 |
|
| 31 |
# Initialize logging and load environment variables
|
| 32 |
logging.basicConfig(level=logging.INFO)
|
| 33 |
logger = logging.getLogger(__name__)
|
| 34 |
load_dotenv()
|
| 35 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 36 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 37 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 38 |
|
| 39 |
# Define and validate API keys
|
| 40 |
openai_api_key = os.getenv("OPENAI_API_KEY")
|
|
@@ -66,7 +178,11 @@ if 'used_trust_tips' not in st.session_state:
|
|
| 66 |
st.session_state.used_trust_tips = set()
|
| 67 |
if 'used_suggestions' not in st.session_state:
|
| 68 |
st.session_state.used_suggestions = set()
|
| 69 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 70 |
def copy_to_clipboard(text):
|
| 71 |
"""Creates a button to copy text to clipboard."""
|
| 72 |
escaped_text = text.replace('\n', '\\n').replace('"', '\\"')
|
|
@@ -124,8 +240,7 @@ def copy_to_clipboard(text):
|
|
| 124 |
</script>
|
| 125 |
"""
|
| 126 |
components.html(copy_icon_html, height=60)
|
| 127 |
-
|
| 128 |
-
|
| 129 |
def send_feedback_via_email(name, email, feedback):
|
| 130 |
"""Sends an email with feedback details."""
|
| 131 |
smtp_server = 'smtp.office365.com'
|
|
@@ -203,7 +318,7 @@ def clean_text(text):
|
|
| 203 |
return cleaned_text
|
| 204 |
|
| 205 |
|
| 206 |
-
|
| 207 |
|
| 208 |
|
| 209 |
def get_trust_tip_and_suggestion():
|
|
@@ -213,15 +328,152 @@ def get_trust_tip_and_suggestion():
|
|
| 213 |
|
| 214 |
|
| 215 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 216 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 217 |
|
| 218 |
-
def
|
| 219 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 220 |
|
| 221 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 222 |
st.header("Let's create something great.")
|
| 223 |
-
|
| 224 |
-
st.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 225 |
<style>
|
| 226 |
.stability { color: rgb(7, 55, 99); font-size: 24px; font-weight: bold; }
|
| 227 |
.development { color: rgb(241, 194, 50); font-size: 24px; font-weight: bold; }
|
|
@@ -230,76 +482,80 @@ def side():
|
|
| 230 |
.vision { color: rgb(255, 153, 0); font-size: 24px; font-weight: bold; }
|
| 231 |
.competence { color: rgb(111, 168, 220); font-size: 24px; font-weight: bold; }
|
| 232 |
</style>
|
| 233 |
-
|
| 234 |
<h3 class="stability">Stability Trust:</h3>
|
| 235 |
<p>Why can I trust you to have built a strong and stable foundation?</p>
|
| 236 |
-
|
| 237 |
<h3 class="development">Development Trust:</h3>
|
| 238 |
<p>Why can I trust you to develop well in the future?</p>
|
| 239 |
-
|
| 240 |
<h3 class="relationship">Relationship Trust:</h3>
|
| 241 |
<p>What appealing relationship qualities can I trust you for?</p>
|
| 242 |
-
|
| 243 |
<h3 class="benefit">Benefit Trust:</h3>
|
| 244 |
<p>What benefits can I trust you for?</p>
|
| 245 |
-
|
| 246 |
<h3 class="vision">Vision Trust:</h3>
|
| 247 |
<p>What Vision and Values can I trust you for?</p>
|
| 248 |
-
|
| 249 |
<h3 class="competence">Competence Trust:</h3>
|
| 250 |
<p>What competencies can I trust you for?</p>
|
| 251 |
-
""", unsafe_allow_html=True
|
| 252 |
-
|
| 253 |
-
|
| 254 |
-
|
| 255 |
-
|
| 256 |
-
|
| 257 |
-
|
| 258 |
-
feedback_name = st.text_input("Name")
|
| 259 |
-
feedback_email_input = st.text_input("Email")
|
| 260 |
-
feedback_text = st.text_area("Feedback")
|
| 261 |
-
|
| 262 |
-
# Submit button within the form
|
| 263 |
-
submit_button = st.form_submit_button("Submit Feedback")
|
| 264 |
-
if submit_button:
|
| 265 |
-
if feedback_name and feedback_email_input and feedback_text:
|
| 266 |
-
with st.spinner('Sending email'):
|
| 267 |
-
send_feedback_via_email(feedback_name, feedback_email_input, feedback_text)
|
| 268 |
-
st.success("Thank you for your feedback!")
|
| 269 |
-
else:
|
| 270 |
-
st.error("Please fill in all fields.")
|
| 271 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 272 |
|
| 273 |
|
| 274 |
|
| 275 |
side()
|
| 276 |
# Load knowledge base
|
| 277 |
-
def load_knowledge_base():
|
| 278 |
-
try:
|
| 279 |
-
loader = TextLoader("./data_source/time_to_rethink_trust_book.md")
|
| 280 |
-
documents = loader.load()
|
| 281 |
-
text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
|
| 282 |
-
docs = text_splitter.split_documents(documents)
|
| 283 |
-
return docs
|
| 284 |
-
except Exception as e:
|
| 285 |
-
logger.error(f"Error loading knowledge base: {e}")
|
| 286 |
-
raise e
|
| 287 |
|
| 288 |
-
knowledge_base = load_knowledge_base()
|
| 289 |
|
| 290 |
-
# Initialize embeddings and FAISS index
|
| 291 |
-
|
| 292 |
-
|
|
|
|
|
|
|
| 293 |
|
| 294 |
# Define search functions
|
| 295 |
def search_knowledge_base(query):
|
| 296 |
-
|
| 297 |
-
|
| 298 |
-
|
| 299 |
-
|
| 300 |
-
|
| 301 |
-
|
| 302 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 303 |
def google_search(query):
|
| 304 |
try:
|
| 305 |
search_client = serpapi.Client(api_key=serper_api_key)
|
|
@@ -347,6 +603,7 @@ tools = [knowledge_base_tool, google_search_tool]
|
|
| 347 |
|
| 348 |
prompt_message = f"""
|
| 349 |
**You are an expert copywriter specializing in creating highly creative marketing content in natural tone that integrates **Trust Builders** into various content formats for any organization. Your goal is to produce compelling, factual,and well-structured material that is concise and based on the knowledgebase, adhering to the following guidelines.The content should be written in an active voice, avoiding third-person perspective .Interconnect the trust-building elements contextually and creatively to enhance the reading flow, making it clear what the impact is on audience. While prompts may mention terms like Stability, Development, Competence, Relationship, Benefit, or Vision, do not include words like "trust","cutting-edge","beacon,"beacon of hope"and "realm" in any of the output. Trust word can be used like here are these eg Development trust builders but in the copy .**
|
|
|
|
| 350 |
### MANDATORY VERIFICATION CHECKLIST:
|
| 351 |
Before submitting **any content**, ensure that each piece includes:
|
| 352 |
1. **Specific Details**:
|
|
@@ -363,11 +620,13 @@ Before submitting **any content**, ensure that each piece includes:
|
|
| 363 |
- "This [specific benefit] for [specific audience]"
|
| 364 |
- **Example**: "This reduces wait times by 47% for patients seeking emergency care."
|
| 365 |
3. *Give [sources] next to each trust building point and heuristics and creative techniques with every copy application*.
|
|
|
|
| 366 |
*SOURCE LINK REQUIREMENTS*
|
| 367 |
1. **Each source link must**:
|
| 368 |
- Be **working and clickable**.
|
| 369 |
- Be **no older than 2 years** unless historically significant.
|
| 370 |
2. Refer knowledge base for description, guiding principles, question to consider and examples for relevant trustbucket then *search on google* and then give relevant trustbuilders.
|
|
|
|
| 371 |
##SPECIFICITY ENFORCEMENT
|
| 372 |
Replace vague phrases with specific details:
|
| 373 |
- ❌ "many" → ✅ exact number.
|
|
@@ -377,6 +636,7 @@ Replace vague phrases with specific details:
|
|
| 377 |
- ��� "industry leader" → ✅ "ranked #1 in customer satisfaction by J.D. Power in 2023".
|
| 378 |
- ❌ "significant impact" → ✅ "47% reduction in processing time".
|
| 379 |
- ❌ "team of experts" → ✅ "157 certified professionals led by Dr. Sarah Chen".
|
|
|
|
| 380 |
###ERROR CHECKING
|
| 381 |
Before submitting, verify and fix:
|
| 382 |
**When query is to find trust builders never mention heuristic and creative techniques**
|
|
@@ -387,6 +647,7 @@ Before submitting, verify and fix:
|
|
| 387 |
5. **No missing specific details** from the mandatory checklist.
|
| 388 |
6. **No prohibited terms included in the copy. For searching it can be used.**.
|
| 389 |
7. ** DONOT INCLUDE heuristic and creative techniques in Trustbuilder queries**
|
|
|
|
| 390 |
###CRITICAL MANDATORY INSTRUCTIONS
|
| 391 |
- **Avoid Prohibited Terms**:
|
| 392 |
- Do **not** mention "trust," "trust buckets," or any category names like "Development," "Stability," "Competence," "Relationship," "Vision" in the final copy.
|
|
@@ -407,7 +668,9 @@ Before submitting, verify and fix:
|
|
| 407 |
-Limit to 3-5 items in each category.
|
| 408 |
Note: When including heuristics and creative techniques, use the single line structure “Heuristics: examples” and “Creative Techniques: examples” with no extra details.
|
| 409 |
- If the query is about trust builders , do not include heuristics or creative techniques,List of TrustBuilders Used.
|
|
|
|
| 410 |
### CONTENT TYPES AND FORMATS
|
|
|
|
| 411 |
#### 1. Annual report article / article
|
| 412 |
- **Introduction**: Start with "Here is a draft of your [Annual Report/Article]. Feel free to suggest further refinements."
|
| 413 |
- **Structure**:
|
|
@@ -428,6 +691,7 @@ Before submitting, verify and fix:
|
|
| 428 |
- **Important Notes**:
|
| 429 |
- **Strictly search and provide accurate source links always**.
|
| 430 |
- Include heuristics and creative techniques if requested.
|
|
|
|
| 431 |
#### 2. Social Media Posts
|
| 432 |
- **Introduction Line**: Start with "Here is a draft of your social media post. Feel free to suggest further refinements."
|
| 433 |
- **Content**:
|
|
@@ -481,6 +745,7 @@ Before submitting, verify and fix:
|
|
| 481 |
-Limit to 3-5 items in each category.
|
| 482 |
Note: When including heuristics and creative techniques, use the structure “Heuristics: examples” and “Creative Techniques: examples” with no extra details.
|
| 483 |
- **Word Count**: Follow any specified word count for the main body. Do not count sub-heading sections in the word count limit.
|
|
|
|
| 484 |
### 5.Trust-Based Queries:**
|
| 485 |
Be over specific with numbers,names,dollars, programs ,awards and action.
|
| 486 |
- When a query seeks a specific number of trust builders (e.g., "5 trust builders"), the AI should:
|
|
@@ -502,9 +767,11 @@ Note: When including heuristics and creative techniques, use the structure “He
|
|
| 502 |
- **People** (5 points)
|
| 503 |
- **Offers/Services** (5 points)
|
| 504 |
- **Important Specificity:** Always include **names**, **numbers** (e.g., $ amounts and years), **programs**, **strategies**, **places**, **awards**, and **actions** by searching on google to add credibility and depth to the content. Ensure that trust-building points are detailed and specific.
|
|
|
|
| 505 |
- **For Specific Categories:**
|
| 506 |
- When a query asks for a specific category (e.g., "Development trust builders"), find 15 trust-building points that are specific with relevant names, numbers like $ amounts and years, programs, strategies, places, awards, and actions specifically for that category.
|
| 507 |
- Categorize these points into Organization, People, and Offers/Services (with 5 points for each category).
|
|
|
|
| 508 |
- **Format:**
|
| 509 |
- **Introduction Line:** Start with "Here are TrustBuilders® for [Selected Categories] at [Organization Name]. Let me know if you want to refine the results or find more."
|
| 510 |
- **Categories:**
|
|
@@ -528,6 +795,7 @@ Note: When including heuristics and creative techniques, use the structure “He
|
|
| 528 |
- [Trust-Building Point 15] - [Source](#)
|
| 529 |
- Ensure each selected category contains 15 trust-building points, categorized as specified.
|
| 530 |
- Provide bullet points under each section with relevant accurate source link.
|
|
|
|
| 531 |
**Important Notes:**
|
| 532 |
- Strictly search and provide accurate source links always.
|
| 533 |
- **No Subheadings or Labels:** Under each main category, list the trust-building points directly as bullet points or numbered lists **without any additional subheadings, labels, descriptors, phrases, or words before the points**.
|
|
@@ -544,18 +812,17 @@ Note: When including heuristics and creative techniques, use the structure “He
|
|
| 544 |
- **Example of Correct Format**:
|
| 545 |
**Organization**
|
| 546 |
- In **2023**, World Vision invested **$150 million** in sustainable agriculture programs across **35 countries**, impacting over **2 million** farmers.This improves food security for vulnerable communities.- [Source](#)
|
|
|
|
| 547 |
### 6. LinkedIn Profile
|
| 548 |
- If requested, generate a LinkedIn profile in a professional manner.
|
| 549 |
- **Avoid prohibited terms** and **flowery language**.
|
|
|
|
| 550 |
### GENERAL QUERIES
|
| 551 |
- Donot use knowledge base for non-trust content.Give quick output according to above given guidance.
|
| 552 |
- **Audience Impact**: Always clarify what the information means to the audience.
|
| 553 |
|
| 554 |
-
"""
|
| 555 |
-
|
| 556 |
-
|
| 557 |
-
|
| 558 |
|
|
|
|
| 559 |
|
| 560 |
prompt_template = ChatPromptTemplate.from_messages([
|
| 561 |
("system", prompt_message),
|
|
@@ -565,7 +832,7 @@ prompt_template = ChatPromptTemplate.from_messages([
|
|
| 565 |
])
|
| 566 |
|
| 567 |
# Create Langchain Agent
|
| 568 |
-
llm = ChatOpenAI(model="gpt-4o", temperature=0.
|
| 569 |
llm_with_tools = llm.bind_tools(tools)
|
| 570 |
|
| 571 |
# Define the agent pipeline
|
|
@@ -684,7 +951,69 @@ if not st.session_state.get("chat_started", False):
|
|
| 684 |
</div>
|
| 685 |
<div style="height: 50px;"></div> <!-- Adds a gap of 50px after the section containers -->
|
| 686 |
""", unsafe_allow_html=True)
|
| 687 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 688 |
|
| 689 |
trust_tips = [
|
| 690 |
"What I don’t know I can’t trust you for. Make sure you know all your great TrustBuilders® and use them over time.",
|
|
@@ -742,6 +1071,7 @@ def add_dot_typing_animation():
|
|
| 742 |
display: flex;
|
| 743 |
align-items: center;
|
| 744 |
}
|
|
|
|
| 745 |
.dot {
|
| 746 |
height: 10px;
|
| 747 |
width: 10px;
|
|
@@ -751,12 +1081,15 @@ def add_dot_typing_animation():
|
|
| 751 |
display: inline-block;
|
| 752 |
animation: dot-blink 1.5s infinite ease-in-out;
|
| 753 |
}
|
|
|
|
| 754 |
.dot:nth-child(2) {
|
| 755 |
animation-delay: 0.2s;
|
| 756 |
}
|
|
|
|
| 757 |
.dot:nth-child(3) {
|
| 758 |
animation-delay: 0.4s;
|
| 759 |
}
|
|
|
|
| 760 |
@keyframes dot-blink {
|
| 761 |
0% {
|
| 762 |
opacity: 0.3;
|
|
@@ -782,76 +1115,210 @@ def display_typing_indicator():
|
|
| 782 |
<span class="dot"></span>
|
| 783 |
</div>
|
| 784 |
"""
|
|
|
|
| 785 |
st.markdown(dot_typing_html, unsafe_allow_html=True)
|
|
|
|
|
|
|
| 786 |
|
| 787 |
-
prompt = st.chat_input("")
|
| 788 |
-
if prompt :
|
| 789 |
-
|
| 790 |
-
st.session_state["chat_started"] = True
|
| 791 |
-
# Add user message to chat history
|
| 792 |
-
st.session_state.chat_history.append({"role": "user", "content": prompt})
|
| 793 |
-
|
| 794 |
|
| 795 |
-
|
| 796 |
-
|
| 797 |
-
|
| 798 |
-
|
| 799 |
-
|
| 800 |
-
|
| 801 |
-
|
| 802 |
-
|
| 803 |
-
|
| 804 |
-
|
| 805 |
-
|
|
|
|
|
|
|
| 806 |
|
| 807 |
-
|
| 808 |
-
|
| 809 |
-
|
| 810 |
-
|
| 811 |
-
|
| 812 |
|
| 813 |
-
"input": f" {prompt} Be in natural tone.Sources should be accurate.Avoid AI jargons.DONOT USE use words that end with '-ing' for headlines and subheadlines when asked to write a article,blog,newsletter.",
|
| 814 |
-
|
| 815 |
-
|
| 816 |
-
"chat_history": st.session_state.chat_history
|
| 817 |
-
})
|
| 818 |
-
full_response = output["output"]
|
| 819 |
-
#full_response= replace_terms(full_response)
|
| 820 |
-
|
| 821 |
-
cleaned_text = clean_text(full_response)
|
| 822 |
-
cleaned_text = re.sub(r'<[^>]*>', '', cleaned_text)
|
| 823 |
-
|
| 824 |
-
|
| 825 |
-
|
| 826 |
-
#cleaned_text = re.sub(r'</span>', '', cleaned_text)
|
| 827 |
-
#cleaned_text = re.sub(r'<span[^>]*>', '', cleaned_text)
|
| 828 |
-
# Display the response
|
| 829 |
-
|
| 830 |
-
trust_tip, suggestion = get_trust_tip_and_suggestion()
|
| 831 |
-
|
| 832 |
-
#combined_text = f"{cleaned_text}\n\n---\n\n**Trust Tip**: {trust_tip}\n\n**Suggestion**: {suggestion}"
|
| 833 |
-
combined_text = f"{cleaned_text}\n\n---\n\n**Trust Tip**: {trust_tip}\n\n**Suggestion**: {suggestion}"
|
| 834 |
-
|
| 835 |
-
#st.markdown(combined_text,unsafe_allow_html=True)
|
| 836 |
-
|
| 837 |
-
#seprtor= st.markdown("---") # Add a separator
|
| 838 |
-
#t_tip= st.markdown(f"**Trust Tip**: {trust_tip}")
|
| 839 |
-
#s_sug- st.markdown(f"**Suggestion**: {suggestion}")
|
| 840 |
-
with response_placeholder:
|
| 841 |
-
with st.chat_message("assistant"):
|
| 842 |
-
st.markdown(combined_text, unsafe_allow_html=True)
|
| 843 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 844 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 845 |
|
| 846 |
-
|
| 847 |
-
|
| 848 |
-
|
| 849 |
-
|
| 850 |
-
|
| 851 |
-
|
| 852 |
-
|
| 853 |
-
|
| 854 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 855 |
|
| 856 |
-
|
| 857 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
import logging
|
| 2 |
import os
|
| 3 |
+
import streamlit as st
|
| 4 |
from dotenv import load_dotenv
|
| 5 |
import openai
|
| 6 |
from langchain_openai import ChatOpenAI
|
|
|
|
| 14 |
from langchain_community.document_loaders import TextLoader
|
| 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
|
|
|
|
| 27 |
from email.mime.multipart import MIMEMultipart
|
| 28 |
from email.mime.text import MIMEText
|
| 29 |
from markdownify import markdownify
|
| 30 |
+
import chargebee
|
| 31 |
+
import pyrebase
|
| 32 |
+
import streamlit.components.v1 as components
|
| 33 |
+
import time
|
| 34 |
+
import warnings
|
| 35 |
+
from streamlit.components.v1 import html
|
| 36 |
+
from langchain.docstore.document import Document
|
| 37 |
+
import firebase_admin
|
| 38 |
+
import uuid
|
| 39 |
+
import json
|
| 40 |
+
import io
|
| 41 |
+
from firebase_admin import credentials, firestore
|
| 42 |
+
import base64
|
| 43 |
+
from pdfminer.high_level import extract_text # Import for PDF text extraction
|
| 44 |
+
|
| 45 |
+
st.set_page_config(layout="wide")
|
| 46 |
+
import logging
|
| 47 |
+
import asyncio
|
| 48 |
+
import re
|
| 49 |
+
# Set up logging to suppress Streamlit warnings about experimental functions
|
| 50 |
+
logging.getLogger('streamlit').setLevel(logging.ERROR)
|
| 51 |
+
|
| 52 |
+
|
| 53 |
+
|
| 54 |
|
| 55 |
# Initialize logging and load environment variables
|
| 56 |
logging.basicConfig(level=logging.INFO)
|
| 57 |
logger = logging.getLogger(__name__)
|
| 58 |
load_dotenv()
|
| 59 |
|
| 60 |
+
chargebee.configure(site="mextconsulting", api_key="live_dBLXn8yG5dFcuIgU5Szebj2KfTcdt4hjpf")
|
| 61 |
+
|
| 62 |
+
# Firebase Configuration
|
| 63 |
+
firebase_config = {
|
| 64 |
+
"apiKey": "AIzaSyAWiaqrduoG7fzmJxBVnVg9nCC4EoEnwfY",
|
| 65 |
+
"authDomain": "trustai-3e7a2.firebaseapp.com",
|
| 66 |
+
"databaseURL": "https://trustai-3e7a2-default-rtdb.firebaseio.com",
|
| 67 |
+
"projectId": "trustai-3e7a2",
|
| 68 |
+
"storageBucket": "trustai-3e7a2.appspot.com",
|
| 69 |
+
"messagingSenderId": "964339831031",
|
| 70 |
+
"appId": "1:964339831031:web:66d21ceea68ab03f1043f2",
|
| 71 |
+
"measurementId": "G-ZMLZQZMHK2"
|
| 72 |
+
}
|
| 73 |
+
# Initialize Firebase
|
| 74 |
+
firebase = pyrebase.initialize_app(firebase_config)
|
| 75 |
+
db = firebase.database()
|
| 76 |
+
storage = firebase.storage()
|
| 77 |
+
|
| 78 |
+
|
| 79 |
+
def convert_pdf_to_md(file):
|
| 80 |
+
"""
|
| 81 |
+
Convert a PDF file to Markdown.
|
| 82 |
+
"""
|
| 83 |
+
try:
|
| 84 |
+
text = extract_text(file)
|
| 85 |
+
return f"# PDF Document\n\n{text}"
|
| 86 |
+
except Exception as e:
|
| 87 |
+
logger.error(f"Error converting PDF to MD: {e}")
|
| 88 |
+
return ""
|
| 89 |
+
|
| 90 |
+
def convert_docx_to_md(file):
|
| 91 |
+
"""
|
| 92 |
+
Convert a Word (DOCX) file to Markdown.
|
| 93 |
+
"""
|
| 94 |
+
try:
|
| 95 |
+
doc = Document(file)
|
| 96 |
+
full_text = '\n'.join([para.text for para in doc.paragraphs])
|
| 97 |
+
return f"# Word Document\n\n{full_text}"
|
| 98 |
+
except Exception as e:
|
| 99 |
+
logger.error(f"Error converting DOCX to MD: {e}")
|
| 100 |
+
return ""
|
| 101 |
+
|
| 102 |
+
def convert_txt_to_md(file):
|
| 103 |
+
"""
|
| 104 |
+
Convert a TXT file to Markdown.
|
| 105 |
+
"""
|
| 106 |
+
try:
|
| 107 |
+
text = file.read().decode("utf-8")
|
| 108 |
+
return f"# Text Document\n\n{text}"
|
| 109 |
+
except Exception as e:
|
| 110 |
+
logger.error(f"Error converting TXT to MD: {e}")
|
| 111 |
+
return ""
|
| 112 |
|
| 113 |
+
def convert_file_to_md(file):
|
| 114 |
+
"""
|
| 115 |
+
Detect file type and convert to Markdown accordingly.
|
| 116 |
+
"""
|
| 117 |
+
if file.type == "application/pdf":
|
| 118 |
+
return convert_pdf_to_md(file)
|
| 119 |
+
elif file.type == "application/vnd.openxmlformats-officedocument.wordprocessingml.document":
|
| 120 |
+
return convert_docx_to_md(file)
|
| 121 |
+
elif file.type == "text/plain":
|
| 122 |
+
return convert_txt_to_md(file)
|
| 123 |
+
else:
|
| 124 |
+
st.sidebar.warning(f"Unsupported file type: {file.type}")
|
| 125 |
+
return ""
|
| 126 |
+
|
| 127 |
+
def merge_markdown_contents(contents):
|
| 128 |
+
"""
|
| 129 |
+
Merge multiple Markdown contents into a single Markdown string.
|
| 130 |
+
"""
|
| 131 |
+
merged_content = "\n\n---\n\n".join(contents)
|
| 132 |
+
return merged_content
|
| 133 |
|
| 134 |
+
def upload_to_firebase(user_id, merged_md_content):
|
| 135 |
+
"""
|
| 136 |
+
Upload the merged Markdown content to Firebase Storage.
|
| 137 |
+
Returns the public URL of the uploaded file.
|
| 138 |
+
"""
|
| 139 |
+
try:
|
| 140 |
+
file_path = f"knowledge_bases/{user_id}/knowledge_base.md"
|
| 141 |
+
# Upload the content as bytes
|
| 142 |
+
storage.child(file_path).put(io.BytesIO(merged_md_content.encode('utf-8')), content_type="text/markdown")
|
| 143 |
+
# Get the download URL
|
| 144 |
+
public_url = storage.child(file_path).get_url(None)
|
| 145 |
+
return public_url
|
| 146 |
+
except Exception as e:
|
| 147 |
+
logger.error(f"Error uploading to Firebase Storage: {e}")
|
| 148 |
+
st.sidebar.error(f"Error uploading files: {e}")
|
| 149 |
+
return None
|
| 150 |
|
| 151 |
# Define and validate API keys
|
| 152 |
openai_api_key = os.getenv("OPENAI_API_KEY")
|
|
|
|
| 178 |
st.session_state.used_trust_tips = set()
|
| 179 |
if 'used_suggestions' not in st.session_state:
|
| 180 |
st.session_state.used_suggestions = set()
|
| 181 |
+
|
| 182 |
+
|
| 183 |
+
backend_url = "https://backend-web-05122eab4e09.herokuapp.com"
|
| 184 |
+
# Suppress Streamlit deprecation and warning messages
|
| 185 |
+
|
| 186 |
def copy_to_clipboard(text):
|
| 187 |
"""Creates a button to copy text to clipboard."""
|
| 188 |
escaped_text = text.replace('\n', '\\n').replace('"', '\\"')
|
|
|
|
| 240 |
</script>
|
| 241 |
"""
|
| 242 |
components.html(copy_icon_html, height=60)
|
| 243 |
+
|
|
|
|
| 244 |
def send_feedback_via_email(name, email, feedback):
|
| 245 |
"""Sends an email with feedback details."""
|
| 246 |
smtp_server = 'smtp.office365.com'
|
|
|
|
| 318 |
return cleaned_text
|
| 319 |
|
| 320 |
|
| 321 |
+
|
| 322 |
|
| 323 |
|
| 324 |
def get_trust_tip_and_suggestion():
|
|
|
|
| 328 |
|
| 329 |
|
| 330 |
|
| 331 |
+
def load_main_data_source():
|
| 332 |
+
try:
|
| 333 |
+
with open("./data_source/time_to_rethink_trust_book.md", "r") as f:
|
| 334 |
+
main_content = f.read()
|
| 335 |
+
|
| 336 |
+
# Split main content into chunks
|
| 337 |
+
text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
|
| 338 |
+
main_texts = text_splitter.split_text(main_content)
|
| 339 |
|
| 340 |
+
# Create Document objects for the main data source
|
| 341 |
+
main_documents = [Document(page_content=text) for text in main_texts]
|
| 342 |
+
return main_documents
|
| 343 |
+
except Exception as e:
|
| 344 |
+
st.error(f"Error loading main data source: {e}")
|
| 345 |
+
return []
|
| 346 |
|
| 347 |
+
def combine_data_sources():
|
| 348 |
+
main_data_source = load_main_data_source()
|
| 349 |
+
user_data_source = load_user_data_source(st.session_state["wix_user_id"])
|
| 350 |
+
|
| 351 |
+
trustbuilders = [Document(page_content=tb["message"]) for tb in st.session_state.get("trustbuilders", {}).values()]
|
| 352 |
+
brand_tonalities = [Document(page_content=bt["message"]) for bt in st.session_state.get("brand_tonality", {}).values()]
|
| 353 |
|
| 354 |
+
return main_data_source + user_data_source + trustbuilders + brand_tonalities
|
| 355 |
+
|
| 356 |
+
|
| 357 |
+
def refresh_faiss_index():
|
| 358 |
+
combined_sources = combine_data_sources()
|
| 359 |
+
if combined_sources:
|
| 360 |
+
embeddings = OpenAIEmbeddings()
|
| 361 |
+
db_faiss = FAISS.from_documents(combined_sources, embeddings)
|
| 362 |
+
st.session_state["faiss_db"] = db_faiss
|
| 363 |
+
|
| 364 |
+
def load_user_data_source(user_id):
|
| 365 |
+
"""
|
| 366 |
+
Load user-uploaded data source from Firebase.
|
| 367 |
+
"""
|
| 368 |
+
try:
|
| 369 |
+
file_path = f"knowledge_bases/{user_id}/knowledge_base.md"
|
| 370 |
+
storage_url = storage.child(file_path).get_url(None)
|
| 371 |
+
response = requests.get(storage_url)
|
| 372 |
+
|
| 373 |
+
if response.status_code == 200:
|
| 374 |
+
user_content = response.text
|
| 375 |
+
st.session_state["user_data_source"] = user_content
|
| 376 |
+
return [Document(page_content=user_content)]
|
| 377 |
+
else:
|
| 378 |
+
return []
|
| 379 |
+
except Exception as e:
|
| 380 |
+
st.error(f"Error loading user data source: {e}")
|
| 381 |
+
return []
|
| 382 |
+
|
| 383 |
+
|
| 384 |
+
|
| 385 |
+
|
| 386 |
+
def store_brand_tonality(user_id, message):
|
| 387 |
+
try:
|
| 388 |
+
tonality_id = str(uuid.uuid4())
|
| 389 |
+
db.child("users").child(user_id).child("brandTonality").child(tonality_id).set({"message": message})
|
| 390 |
+
|
| 391 |
+
# Update st.session_state for instant display in sidebar
|
| 392 |
+
if "brand_tonality" not in st.session_state:
|
| 393 |
+
st.session_state["brand_tonality"] = {}
|
| 394 |
+
st.session_state["brand_tonality"][tonality_id] = {"message": message}
|
| 395 |
+
display_save_confirmation("Brand Tonality")
|
| 396 |
+
except Exception as e:
|
| 397 |
+
st.error(f"Error saving Brand Tonality: {e}")
|
| 398 |
+
|
| 399 |
+
def store_trustbuilder(user_id, message):
|
| 400 |
+
try:
|
| 401 |
+
trustbuilder_id = str(uuid.uuid4())
|
| 402 |
+
db.child("users").child(user_id).child("trustBuilders").child(trustbuilder_id).set({"message": message})
|
| 403 |
+
|
| 404 |
+
# Update st.session_state for instant display in sidebar
|
| 405 |
+
if "trustbuilders" not in st.session_state:
|
| 406 |
+
st.session_state["trustbuilders"] = {}
|
| 407 |
+
st.session_state["trustbuilders"][trustbuilder_id] = {"message": message}
|
| 408 |
+
display_save_confirmation("TrustBuilder")
|
| 409 |
+
except Exception as e:
|
| 410 |
+
st.error(f"Error saving TrustBuilder: {e}")
|
| 411 |
+
|
| 412 |
+
def load_user_content(user_id):
|
| 413 |
+
"""Load TrustBuilders and Brand Tonalities from Firebase."""
|
| 414 |
+
try:
|
| 415 |
+
trustbuilders = db.child("users").child(user_id).child("trustBuilders").get()
|
| 416 |
+
brand_tonalities = db.child("users").child(user_id).child("brandTonality").get()
|
| 417 |
+
st.session_state["TrustBuilders"] = [item.val()["content"] for item in trustbuilders.each()] if trustbuilders.each() else []
|
| 418 |
+
st.session_state["BrandTonality"] = [item.val()["content"] for item in brand_tonalities.each()] if brand_tonalities.each() else []
|
| 419 |
+
except Exception as e:
|
| 420 |
+
st.error(f"Error loading saved content: {e}")
|
| 421 |
+
|
| 422 |
+
def save_content(user_id, content, content_type):
|
| 423 |
+
try:
|
| 424 |
+
entry_id = str(uuid.uuid4())
|
| 425 |
+
db.child("users").child(user_id).child(content_type).child(entry_id).set({"message": content})
|
| 426 |
+
|
| 427 |
+
# Update session state directly after saving to avoid duplicates
|
| 428 |
+
st.session_state[content_type.lower()][entry_id] = {"message": content}
|
| 429 |
+
display_save_confirmation(content_type)
|
| 430 |
+
except Exception as e:
|
| 431 |
+
logger.error(f"Error saving {content_type}: {e}")
|
| 432 |
+
st.error(f"Could not save {content_type}. Please try again.")
|
| 433 |
+
|
| 434 |
+
def display_saved_trustbuilders():
|
| 435 |
+
"""
|
| 436 |
+
Display saved TrustBuilders and Brand Tonality entries with download and delete options.
|
| 437 |
+
"""
|
| 438 |
+
st.sidebar.subheader("Saved TrustBuilders")
|
| 439 |
+
trustbuilders = st.session_state.get("trustbuilders", {})
|
| 440 |
+
for trustbuilder_id, trustbuilder_data in trustbuilders.items():
|
| 441 |
+
st.sidebar.markdown(f"- {trustbuilder_data['message'][:50]}...")
|
| 442 |
+
st.sidebar.markdown(download_link(trustbuilder_data["message"], f"TrustBuilder_{trustbuilder_id}.md"), unsafe_allow_html=True)
|
| 443 |
+
if st.sidebar.button("❌", key=f"del_tb_{trustbuilder_id}"):
|
| 444 |
+
delete_entry("trustBuilders", trustbuilder_id, "trustbuilders")
|
| 445 |
+
st.rerun()
|
| 446 |
+
|
| 447 |
+
st.sidebar.subheader("Saved Brand Tonality")
|
| 448 |
+
brand_tonality = st.session_state.get("brand_tonality", {})
|
| 449 |
+
for tonality_id, tonality_data in brand_tonality.items():
|
| 450 |
+
st.sidebar.markdown(f"- {tonality_data['message'][:50]}...")
|
| 451 |
+
st.sidebar.markdown(download_link(tonality_data["message"], f"BrandTonality_{tonality_id}.md"), unsafe_allow_html=True)
|
| 452 |
+
if st.sidebar.button("❌", key=f"del_bt_{tonality_id}"):
|
| 453 |
+
delete_entry("brandTonality", tonality_id, "brand_tonality")
|
| 454 |
+
st.rerun()
|
| 455 |
+
|
| 456 |
+
|
| 457 |
+
def download_link(content, filename):
|
| 458 |
+
"""
|
| 459 |
+
Create a download link for content.
|
| 460 |
+
"""
|
| 461 |
+
b64 = base64.b64encode(content.encode()).decode()
|
| 462 |
+
return f'<a href="data:text/plain;base64,{b64}" download="{filename}">Download</a>'
|
| 463 |
+
|
| 464 |
+
|
| 465 |
+
|
| 466 |
+
def side():
|
| 467 |
+
with st.sidebar:
|
| 468 |
+
st.image("Trust Logic_Wheel_RGB_Standard.png")
|
| 469 |
st.header("Let's create something great.")
|
| 470 |
+
|
| 471 |
+
with st.sidebar.expander("Explore", expanded=False):
|
| 472 |
+
st.markdown(
|
| 473 |
+
"Our minds assess trust through Six Buckets of Trust® and determine their importance and order in a given situation. We then evaluate why we can or can’t trust someone in these Buckets. Trustifier.ai®, trained on 20 years of TrustLogic® application, helps you identify reasons why your audience can trust you in each Bucket and create trust-optimised solutions. It’s copy AI with substance."
|
| 474 |
+
)
|
| 475 |
+
st.markdown(
|
| 476 |
+
"""
|
| 477 |
<style>
|
| 478 |
.stability { color: rgb(7, 55, 99); font-size: 24px; font-weight: bold; }
|
| 479 |
.development { color: rgb(241, 194, 50); font-size: 24px; font-weight: bold; }
|
|
|
|
| 482 |
.vision { color: rgb(255, 153, 0); font-size: 24px; font-weight: bold; }
|
| 483 |
.competence { color: rgb(111, 168, 220); font-size: 24px; font-weight: bold; }
|
| 484 |
</style>
|
| 485 |
+
|
| 486 |
<h3 class="stability">Stability Trust:</h3>
|
| 487 |
<p>Why can I trust you to have built a strong and stable foundation?</p>
|
| 488 |
+
|
| 489 |
<h3 class="development">Development Trust:</h3>
|
| 490 |
<p>Why can I trust you to develop well in the future?</p>
|
| 491 |
+
|
| 492 |
<h3 class="relationship">Relationship Trust:</h3>
|
| 493 |
<p>What appealing relationship qualities can I trust you for?</p>
|
| 494 |
+
|
| 495 |
<h3 class="benefit">Benefit Trust:</h3>
|
| 496 |
<p>What benefits can I trust you for?</p>
|
| 497 |
+
|
| 498 |
<h3 class="vision">Vision Trust:</h3>
|
| 499 |
<p>What Vision and Values can I trust you for?</p>
|
| 500 |
+
|
| 501 |
<h3 class="competence">Competence Trust:</h3>
|
| 502 |
<p>What competencies can I trust you for?</p>
|
| 503 |
+
""", unsafe_allow_html=True
|
| 504 |
+
)
|
| 505 |
+
st.markdown("For detailed descriptions, visit [Academy](https://www.trustifier.ai/account/academy)")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 506 |
|
| 507 |
+
st.header("Upload Data source")
|
| 508 |
+
|
| 509 |
+
with st.form(key="upload_form"):
|
| 510 |
+
uploaded_files = st.file_uploader("Upload PDF, DOCX, or TXT files", type=["pdf", "docx", "txt"], accept_multiple_files=True)
|
| 511 |
+
submit_button = st.form_submit_button("Upload")
|
| 512 |
+
|
| 513 |
+
if submit_button and uploaded_files:
|
| 514 |
+
md_contents = [convert_file_to_md(file) for file in uploaded_files if convert_file_to_md(file)]
|
| 515 |
+
if md_contents:
|
| 516 |
+
merged_md = merge_markdown_contents(md_contents)
|
| 517 |
+
upload_url = upload_to_firebase(st.session_state["wix_user_id"], merged_md)
|
| 518 |
+
if upload_url:
|
| 519 |
+
st.success("Files uploaded and processed successfully!")
|
| 520 |
+
st.markdown(f"[View your uploaded knowledge base here]({upload_url})", unsafe_allow_html=True)
|
| 521 |
+
refresh_faiss_index()
|
| 522 |
+
# Save Custom Content section
|
| 523 |
+
st.header("Save Custom Content")
|
| 524 |
+
custom_content = st.text_area("Enter content to save")
|
| 525 |
+
|
| 526 |
+
if st.button("Save as Brand Tonality"):
|
| 527 |
+
save_content(st.session_state["wix_user_id"], custom_content, "BrandTonality")
|
| 528 |
+
display_save_confirmation("Brand Tonality")
|
| 529 |
+
if st.button("Save as TrustBuilder"):
|
| 530 |
+
save_content(st.session_state["wix_user_id"], custom_content, "TrustBuilder")
|
| 531 |
+
display_save_confirmation("TrustBuilder")
|
| 532 |
|
| 533 |
|
| 534 |
|
| 535 |
side()
|
| 536 |
# Load knowledge base
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 537 |
|
|
|
|
| 538 |
|
| 539 |
+
# Initialize embeddings and FAISS index only when wix_user_id is set
|
| 540 |
+
|
| 541 |
+
if st.session_state.get("wix_user_id") and "faiss_db" not in st.session_state:
|
| 542 |
+
refresh_faiss_index()
|
| 543 |
+
|
| 544 |
|
| 545 |
# Define search functions
|
| 546 |
def search_knowledge_base(query):
|
| 547 |
+
"""
|
| 548 |
+
Searches the FAISS index using the provided query.
|
| 549 |
+
Returns the most relevant documents based on the query.
|
| 550 |
+
"""
|
| 551 |
+
if "faiss_db" not in st.session_state:
|
| 552 |
+
st.error("FAISS database is not initialized.")
|
| 553 |
+
return []
|
| 554 |
+
|
| 555 |
+
# Retrieve the top 5 most relevant documents
|
| 556 |
+
retrieved_docs = st.session_state["faiss_db"].similarity_search(query, k=5)
|
| 557 |
+
return retrieved_docs
|
| 558 |
+
|
| 559 |
def google_search(query):
|
| 560 |
try:
|
| 561 |
search_client = serpapi.Client(api_key=serper_api_key)
|
|
|
|
| 603 |
|
| 604 |
prompt_message = f"""
|
| 605 |
**You are an expert copywriter specializing in creating highly creative marketing content in natural tone that integrates **Trust Builders** into various content formats for any organization. Your goal is to produce compelling, factual,and well-structured material that is concise and based on the knowledgebase, adhering to the following guidelines.The content should be written in an active voice, avoiding third-person perspective .Interconnect the trust-building elements contextually and creatively to enhance the reading flow, making it clear what the impact is on audience. While prompts may mention terms like Stability, Development, Competence, Relationship, Benefit, or Vision, do not include words like "trust","cutting-edge","beacon,"beacon of hope"and "realm" in any of the output. Trust word can be used like here are these eg Development trust builders but in the copy .**
|
| 606 |
+
|
| 607 |
### MANDATORY VERIFICATION CHECKLIST:
|
| 608 |
Before submitting **any content**, ensure that each piece includes:
|
| 609 |
1. **Specific Details**:
|
|
|
|
| 620 |
- "This [specific benefit] for [specific audience]"
|
| 621 |
- **Example**: "This reduces wait times by 47% for patients seeking emergency care."
|
| 622 |
3. *Give [sources] next to each trust building point and heuristics and creative techniques with every copy application*.
|
| 623 |
+
|
| 624 |
*SOURCE LINK REQUIREMENTS*
|
| 625 |
1. **Each source link must**:
|
| 626 |
- Be **working and clickable**.
|
| 627 |
- Be **no older than 2 years** unless historically significant.
|
| 628 |
2. Refer knowledge base for description, guiding principles, question to consider and examples for relevant trustbucket then *search on google* and then give relevant trustbuilders.
|
| 629 |
+
|
| 630 |
##SPECIFICITY ENFORCEMENT
|
| 631 |
Replace vague phrases with specific details:
|
| 632 |
- ❌ "many" → ✅ exact number.
|
|
|
|
| 636 |
- ��� "industry leader" → ✅ "ranked #1 in customer satisfaction by J.D. Power in 2023".
|
| 637 |
- ❌ "significant impact" → ✅ "47% reduction in processing time".
|
| 638 |
- ❌ "team of experts" → ✅ "157 certified professionals led by Dr. Sarah Chen".
|
| 639 |
+
|
| 640 |
###ERROR CHECKING
|
| 641 |
Before submitting, verify and fix:
|
| 642 |
**When query is to find trust builders never mention heuristic and creative techniques**
|
|
|
|
| 647 |
5. **No missing specific details** from the mandatory checklist.
|
| 648 |
6. **No prohibited terms included in the copy. For searching it can be used.**.
|
| 649 |
7. ** DONOT INCLUDE heuristic and creative techniques in Trustbuilder queries**
|
| 650 |
+
|
| 651 |
###CRITICAL MANDATORY INSTRUCTIONS
|
| 652 |
- **Avoid Prohibited Terms**:
|
| 653 |
- Do **not** mention "trust," "trust buckets," or any category names like "Development," "Stability," "Competence," "Relationship," "Vision" in the final copy.
|
|
|
|
| 668 |
-Limit to 3-5 items in each category.
|
| 669 |
Note: When including heuristics and creative techniques, use the single line structure “Heuristics: examples” and “Creative Techniques: examples” with no extra details.
|
| 670 |
- If the query is about trust builders , do not include heuristics or creative techniques,List of TrustBuilders Used.
|
| 671 |
+
|
| 672 |
### CONTENT TYPES AND FORMATS
|
| 673 |
+
|
| 674 |
#### 1. Annual report article / article
|
| 675 |
- **Introduction**: Start with "Here is a draft of your [Annual Report/Article]. Feel free to suggest further refinements."
|
| 676 |
- **Structure**:
|
|
|
|
| 691 |
- **Important Notes**:
|
| 692 |
- **Strictly search and provide accurate source links always**.
|
| 693 |
- Include heuristics and creative techniques if requested.
|
| 694 |
+
|
| 695 |
#### 2. Social Media Posts
|
| 696 |
- **Introduction Line**: Start with "Here is a draft of your social media post. Feel free to suggest further refinements."
|
| 697 |
- **Content**:
|
|
|
|
| 745 |
-Limit to 3-5 items in each category.
|
| 746 |
Note: When including heuristics and creative techniques, use the structure “Heuristics: examples” and “Creative Techniques: examples” with no extra details.
|
| 747 |
- **Word Count**: Follow any specified word count for the main body. Do not count sub-heading sections in the word count limit.
|
| 748 |
+
|
| 749 |
### 5.Trust-Based Queries:**
|
| 750 |
Be over specific with numbers,names,dollars, programs ,awards and action.
|
| 751 |
- When a query seeks a specific number of trust builders (e.g., "5 trust builders"), the AI should:
|
|
|
|
| 767 |
- **People** (5 points)
|
| 768 |
- **Offers/Services** (5 points)
|
| 769 |
- **Important Specificity:** Always include **names**, **numbers** (e.g., $ amounts and years), **programs**, **strategies**, **places**, **awards**, and **actions** by searching on google to add credibility and depth to the content. Ensure that trust-building points are detailed and specific.
|
| 770 |
+
|
| 771 |
- **For Specific Categories:**
|
| 772 |
- When a query asks for a specific category (e.g., "Development trust builders"), find 15 trust-building points that are specific with relevant names, numbers like $ amounts and years, programs, strategies, places, awards, and actions specifically for that category.
|
| 773 |
- Categorize these points into Organization, People, and Offers/Services (with 5 points for each category).
|
| 774 |
+
|
| 775 |
- **Format:**
|
| 776 |
- **Introduction Line:** Start with "Here are TrustBuilders® for [Selected Categories] at [Organization Name]. Let me know if you want to refine the results or find more."
|
| 777 |
- **Categories:**
|
|
|
|
| 795 |
- [Trust-Building Point 15] - [Source](#)
|
| 796 |
- Ensure each selected category contains 15 trust-building points, categorized as specified.
|
| 797 |
- Provide bullet points under each section with relevant accurate source link.
|
| 798 |
+
|
| 799 |
**Important Notes:**
|
| 800 |
- Strictly search and provide accurate source links always.
|
| 801 |
- **No Subheadings or Labels:** Under each main category, list the trust-building points directly as bullet points or numbered lists **without any additional subheadings, labels, descriptors, phrases, or words before the points**.
|
|
|
|
| 812 |
- **Example of Correct Format**:
|
| 813 |
**Organization**
|
| 814 |
- In **2023**, World Vision invested **$150 million** in sustainable agriculture programs across **35 countries**, impacting over **2 million** farmers.This improves food security for vulnerable communities.- [Source](#)
|
| 815 |
+
|
| 816 |
### 6. LinkedIn Profile
|
| 817 |
- If requested, generate a LinkedIn profile in a professional manner.
|
| 818 |
- **Avoid prohibited terms** and **flowery language**.
|
| 819 |
+
|
| 820 |
### GENERAL QUERIES
|
| 821 |
- Donot use knowledge base for non-trust content.Give quick output according to above given guidance.
|
| 822 |
- **Audience Impact**: Always clarify what the information means to the audience.
|
| 823 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 824 |
|
| 825 |
+
"""
|
| 826 |
|
| 827 |
prompt_template = ChatPromptTemplate.from_messages([
|
| 828 |
("system", prompt_message),
|
|
|
|
| 832 |
])
|
| 833 |
|
| 834 |
# Create Langchain Agent
|
| 835 |
+
llm = ChatOpenAI(model="gpt-4o", temperature=0.6)
|
| 836 |
llm_with_tools = llm.bind_tools(tools)
|
| 837 |
|
| 838 |
# Define the agent pipeline
|
|
|
|
| 951 |
</div>
|
| 952 |
<div style="height: 50px;"></div> <!-- Adds a gap of 50px after the section containers -->
|
| 953 |
""", unsafe_allow_html=True)
|
| 954 |
+
|
| 955 |
+
hide_specific_warning = """
|
| 956 |
+
<script>
|
| 957 |
+
document.addEventListener('DOMContentLoaded', function() {
|
| 958 |
+
const alerts = window.parent.document.querySelectorAll('div[data-testid="stAlert"]');
|
| 959 |
+
alerts.forEach(function(alert) {
|
| 960 |
+
if (alert.innerText.includes('Please replace st.experimental_get_query_params with st.query_params')) {
|
| 961 |
+
alert.style.display = 'none'; // Hide the warning
|
| 962 |
+
alert.style.visibility = 'hidden'; // Make it invisible
|
| 963 |
+
alert.style.height = '0px'; // Set height to zero to remove space
|
| 964 |
+
alert.style.margin = '0px'; // Set margin to zero
|
| 965 |
+
alert.style.padding = '0px'; // Set padding to zero
|
| 966 |
+
}
|
| 967 |
+
});
|
| 968 |
+
});
|
| 969 |
+
</script>
|
| 970 |
+
"""
|
| 971 |
+
|
| 972 |
+
|
| 973 |
+
# Embed the JavaScript in your Streamlit app
|
| 974 |
+
components.html(hide_specific_warning, height=0, scrolling=False)
|
| 975 |
+
|
| 976 |
+
query_params = st.experimental_get_query_params()
|
| 977 |
+
wix_user_id = query_params.get('wix_user_id', [None])[0]
|
| 978 |
+
email = query_params.get('email', [None])[0]
|
| 979 |
+
|
| 980 |
+
# Session state to track user login and message usage
|
| 981 |
+
if "wix_user_id" not in st.session_state:
|
| 982 |
+
st.session_state["wix_user_id"] = wix_user_id
|
| 983 |
+
if "email" not in st.session_state:
|
| 984 |
+
st.session_state["email"] = email
|
| 985 |
+
if "message_limit" not in st.session_state:
|
| 986 |
+
st.session_state["message_limit"] = 0
|
| 987 |
+
if "used_messages" not in st.session_state:
|
| 988 |
+
st.session_state["used_messages"] = 0
|
| 989 |
+
|
| 990 |
+
|
| 991 |
+
def receive_wix_message():
|
| 992 |
+
components.html(
|
| 993 |
+
"""
|
| 994 |
+
<script>
|
| 995 |
+
window.addEventListener('message', function(event) {
|
| 996 |
+
const data = event.data;
|
| 997 |
+
if (data.wixUserId && data.email) {
|
| 998 |
+
window.parent.postMessage({
|
| 999 |
+
'wix_user_id': data.wixUserId,
|
| 1000 |
+
'email': data.email
|
| 1001 |
+
}, "*");
|
| 1002 |
+
|
| 1003 |
+
// Send message back to Streamlit
|
| 1004 |
+
window.parent.postMessage({
|
| 1005 |
+
wix_user_id: data.wixUserId,
|
| 1006 |
+
email: data.email
|
| 1007 |
+
}, "*");
|
| 1008 |
+
}
|
| 1009 |
+
});
|
| 1010 |
+
</script>
|
| 1011 |
+
""",
|
| 1012 |
+
height=0
|
| 1013 |
+
)
|
| 1014 |
+
|
| 1015 |
+
# Calling this function to initialize listening for Wix messages
|
| 1016 |
+
receive_wix_message()
|
| 1017 |
|
| 1018 |
trust_tips = [
|
| 1019 |
"What I don’t know I can’t trust you for. Make sure you know all your great TrustBuilders® and use them over time.",
|
|
|
|
| 1071 |
display: flex;
|
| 1072 |
align-items: center;
|
| 1073 |
}
|
| 1074 |
+
|
| 1075 |
.dot {
|
| 1076 |
height: 10px;
|
| 1077 |
width: 10px;
|
|
|
|
| 1081 |
display: inline-block;
|
| 1082 |
animation: dot-blink 1.5s infinite ease-in-out;
|
| 1083 |
}
|
| 1084 |
+
|
| 1085 |
.dot:nth-child(2) {
|
| 1086 |
animation-delay: 0.2s;
|
| 1087 |
}
|
| 1088 |
+
|
| 1089 |
.dot:nth-child(3) {
|
| 1090 |
animation-delay: 0.4s;
|
| 1091 |
}
|
| 1092 |
+
|
| 1093 |
@keyframes dot-blink {
|
| 1094 |
0% {
|
| 1095 |
opacity: 0.3;
|
|
|
|
| 1115 |
<span class="dot"></span>
|
| 1116 |
</div>
|
| 1117 |
"""
|
| 1118 |
+
|
| 1119 |
st.markdown(dot_typing_html, unsafe_allow_html=True)
|
| 1120 |
+
def display_save_confirmation(type_saved):
|
| 1121 |
+
st.info(f"Content successfully saved as **{type_saved}**!")
|
| 1122 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1123 |
|
| 1124 |
+
def extract_name(email):
|
| 1125 |
+
return email.split('@')[0].capitalize()
|
| 1126 |
+
|
| 1127 |
+
if "trustbuilders" not in st.session_state:
|
| 1128 |
+
st.session_state["trustbuilders"] = {}
|
| 1129 |
+
if "brand_tonality" not in st.session_state:
|
| 1130 |
+
st.session_state["brand_tonality"] = {}
|
| 1131 |
+
|
| 1132 |
+
# Load saved entries upon user login
|
| 1133 |
+
def retrieve_user_data(user_id):
|
| 1134 |
+
try:
|
| 1135 |
+
trustbuilders = db.child("users").child(user_id).child("trustBuilders").get().val() or {}
|
| 1136 |
+
brand_tonality = db.child("users").child(user_id).child("brandTonality").get().val() or {}
|
| 1137 |
|
| 1138 |
+
# Set retrieved data into session state
|
| 1139 |
+
st.session_state["trustbuilders"] = trustbuilders
|
| 1140 |
+
st.session_state["brand_tonality"] = brand_tonality
|
| 1141 |
+
except Exception as e:
|
| 1142 |
+
st.error("Error loading saved entries. Please try again later.")
|
| 1143 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1144 |
|
| 1145 |
+
|
| 1146 |
+
|
| 1147 |
+
|
| 1148 |
+
|
| 1149 |
+
|
| 1150 |
+
# Function to handle queries about saved TrustBuilders or Brand Tonality
|
| 1151 |
+
def handle_memory_queries(prompt):
|
| 1152 |
+
prompt = prompt.lower().strip()
|
| 1153 |
|
| 1154 |
+
# Save as TrustBuilder, removing the phrase from the content
|
| 1155 |
+
if "save this as trustbuilder" in prompt:
|
| 1156 |
+
content_to_save = prompt.replace("save this as trustbuilder", "").strip()
|
| 1157 |
+
if content_to_save: # Only save if there's actual content
|
| 1158 |
+
store_trustbuilder(st.session_state["wix_user_id"], content_to_save)
|
| 1159 |
+
return "TrustBuilder saved successfully!"
|
| 1160 |
+
else:
|
| 1161 |
+
return "Please provide content to save as TrustBuilder."
|
| 1162 |
+
|
| 1163 |
+
# Save as Brand Tonality, removing the phrase from the content
|
| 1164 |
+
elif "save this as brand tonality" in prompt:
|
| 1165 |
+
content_to_save = prompt.replace("save this as brand tonality", "").strip()
|
| 1166 |
+
if content_to_save: # Only save if there's actual content
|
| 1167 |
+
store_brand_tonality(st.session_state["wix_user_id"], content_to_save)
|
| 1168 |
+
return "Brand Tonality saved successfully!"
|
| 1169 |
+
else:
|
| 1170 |
+
return "Please provide content to save as Brand Tonality."
|
| 1171 |
+
|
| 1172 |
+
# Retrieve saved TrustBuilders
|
| 1173 |
+
elif "show my saved trustbuilders" in prompt or "find my saved trustbuilders" in prompt:
|
| 1174 |
+
if st.session_state.get("trustbuilders"):
|
| 1175 |
+
return "\n".join([f"- {entry['message']}" for entry in st.session_state["trustbuilders"].values()])
|
| 1176 |
+
else:
|
| 1177 |
+
return "You haven't saved any TrustBuilders yet."
|
| 1178 |
+
|
| 1179 |
+
# Retrieve saved Brand Tonality
|
| 1180 |
+
elif "show my saved brand tonality" in prompt or "find my saved brand tonality" in prompt:
|
| 1181 |
+
if st.session_state.get("brand_tonality"):
|
| 1182 |
+
return "\n".join([f"- {entry['message']}" for entry in st.session_state["brand_tonality"].values()])
|
| 1183 |
+
else:
|
| 1184 |
+
return "You haven't saved any Brand Tonality entries yet."
|
| 1185 |
|
| 1186 |
+
return None # If no recognized command, proceed with general handling
|
| 1187 |
+
|
| 1188 |
+
|
| 1189 |
+
def delete_entry(category, entry_id, session_key):
|
| 1190 |
+
try:
|
| 1191 |
+
user_id = st.session_state["wix_user_id"]
|
| 1192 |
+
db.child("users").child(user_id).child(category).child(entry_id).remove()
|
| 1193 |
+
del st.session_state[session_key][entry_id] # Remove from session
|
| 1194 |
+
st.experimental_rerun() # Refresh sidebar
|
| 1195 |
+
except Exception as e:
|
| 1196 |
+
st.error(f"Error deleting entry: {e}")
|
| 1197 |
+
|
| 1198 |
+
# Function to download TrustBuilder as a .md file
|
| 1199 |
+
def download_trustbuilder_as_md(content, trustbuilder_id):
|
| 1200 |
+
b64_content = base64.b64encode(content.encode()).decode()
|
| 1201 |
+
download_link = f'<a href="data:text/markdown;base64,{b64_content}" download="TrustBuilder_{trustbuilder_id}.md">Download</a>'
|
| 1202 |
+
st.sidebar.markdown(download_link, unsafe_allow_html=True)
|
| 1203 |
+
|
| 1204 |
+
|
| 1205 |
+
|
| 1206 |
+
|
| 1207 |
+
|
| 1208 |
+
|
| 1209 |
+
# Function to update the message counter in a static location
|
| 1210 |
+
message_counter_placeholder = st.sidebar.empty()
|
| 1211 |
+
|
| 1212 |
+
def update_message_counter():
|
| 1213 |
+
remaining_messages = st.session_state["message_limit"] - st.session_state["used_messages"]
|
| 1214 |
+
message_counter_placeholder.markdown(f"**Messages Left**: {remaining_messages} / {st.session_state['message_limit']}")
|
| 1215 |
+
|
| 1216 |
+
if st.session_state.get("wix_user_id") and st.session_state.get("email"):
|
| 1217 |
+
retrieve_user_data(st.session_state["wix_user_id"])
|
| 1218 |
+
display_saved_trustbuilders()
|
| 1219 |
+
|
| 1220 |
+
user_name = extract_name(st.session_state["email"])
|
| 1221 |
+
welcome_placeholder = st.empty()
|
| 1222 |
+
welcome_placeholder.info(f"**Hello, {user_name}!**")
|
| 1223 |
+
time.sleep(3)
|
| 1224 |
+
welcome_placeholder.empty()
|
| 1225 |
+
def check_user_subscription(wix_user_id):
|
| 1226 |
+
response = requests.get(f"{backend_url}/check-subscription/{wix_user_id}")
|
| 1227 |
+
if response.status_code == 200:
|
| 1228 |
+
data = response.json()
|
| 1229 |
+
st.session_state["message_limit"] = data.get("message_limit", 0)
|
| 1230 |
+
st.session_state["used_messages"] = data.get("used_messages", 0)
|
| 1231 |
+
update_message_counter()
|
| 1232 |
+
else:
|
| 1233 |
+
st.error("Error fetching user subscription details.")
|
| 1234 |
+
|
| 1235 |
+
def update_message_usage(wix_user_id):
|
| 1236 |
+
response = requests.post(f"{backend_url}/update-message-usage/{st.session_state['wix_user_id']}")
|
| 1237 |
+
if response.status_code == 200:
|
| 1238 |
+
st.session_state["used_messages"] += 1
|
| 1239 |
+
update_message_counter()
|
| 1240 |
+
else:
|
| 1241 |
+
st.error("Error updating message usage.")
|
| 1242 |
+
check_user_subscription(st.session_state["wix_user_id"])
|
| 1243 |
+
|
| 1244 |
+
# Input for AI interaction
|
| 1245 |
+
prompt = st.chat_input("")
|
| 1246 |
+
global combined_text
|
| 1247 |
+
if st.session_state["used_messages"] < st.session_state["message_limit"]:
|
| 1248 |
+
if prompt:
|
| 1249 |
+
st.session_state.chat_started = True
|
| 1250 |
+
st.session_state.chat_history.append({"role": "user", "content": prompt})
|
| 1251 |
+
|
| 1252 |
+
# Check if the prompt is a memory query
|
| 1253 |
+
memory_response = handle_memory_queries(prompt)
|
| 1254 |
+
if memory_response:
|
| 1255 |
+
with st.chat_message("assistant"):
|
| 1256 |
+
st.markdown(memory_response)
|
| 1257 |
|
| 1258 |
+
else:
|
| 1259 |
+
# Detect if the user wants to save content based on chatbox prompts
|
| 1260 |
+
save_as_trustbuilder = re.search(r"\b(save|add|store)\s*(this)?\s*(as)?\s*(trust\s*builder|trustbuilder)\b", prompt, re.IGNORECASE)
|
| 1261 |
+
save_as_tonality = re.search(r"\b(save|add|store)\s*(this)?\s*(as)?\s*(brand\s*tonality|tonality)\b", prompt, re.IGNORECASE)
|
| 1262 |
+
|
| 1263 |
+
|
| 1264 |
+
if save_as_trustbuilder or save_as_tonality:
|
| 1265 |
+
user_id = st.session_state["wix_user_id"]
|
| 1266 |
+
if save_as_trustbuilder:
|
| 1267 |
+
store_trustbuilder(user_id, prompt)
|
| 1268 |
+
display_save_confirmation("TrustBuilder")
|
| 1269 |
+
elif save_as_tonality:
|
| 1270 |
+
store_brand_tonality(user_id, prompt)
|
| 1271 |
+
display_save_confirmation("Brand Tonality")
|
| 1272 |
+
|
| 1273 |
+
else:
|
| 1274 |
+
# Generate a response with AI for other types of queries
|
| 1275 |
+
with st.chat_message("user"):
|
| 1276 |
+
st.markdown(prompt)
|
| 1277 |
+
response_placeholder = st.empty()
|
| 1278 |
+
with response_placeholder:
|
| 1279 |
+
with st.chat_message("assistant"):
|
| 1280 |
+
add_dot_typing_animation()
|
| 1281 |
+
display_typing_indicator()
|
| 1282 |
+
cleaned_text = ""
|
| 1283 |
+
# Specialized responses if keywords detected
|
| 1284 |
+
try:
|
| 1285 |
+
#if "trustbuilder" in prompt.lower() or "trust" in prompt.lower():
|
| 1286 |
+
output = agent_executor.invoke({
|
| 1287 |
+
"input": f"{prompt}Be in natural tone.Sources should be accurate.Avoid AI jargons.DONOT USE use words that end with '-ing' for headlines and subheadlines when asked to write a article,blog,newsletter.",
|
| 1288 |
+
"chat_history": st.session_state.chat_history
|
| 1289 |
+
})
|
| 1290 |
+
full_response = output["output"]
|
| 1291 |
+
#full_response= replace_terms(full_response)
|
| 1292 |
+
|
| 1293 |
+
cleaned_text = clean_text(full_response)
|
| 1294 |
+
trust_tip, suggestion = get_trust_tip_and_suggestion()
|
| 1295 |
+
combined_text = f"{cleaned_text}\n\n---\n\n**Trust Tip**: {trust_tip}\n\n**Suggestion**: {suggestion}"
|
| 1296 |
+
with response_placeholder:
|
| 1297 |
+
with st.chat_message("assistant"):
|
| 1298 |
+
st.markdown(combined_text, unsafe_allow_html=True)
|
| 1299 |
+
|
| 1300 |
+
#else:
|
| 1301 |
+
# llm = ChatOpenAI(model="gpt-4o", temperature=0.8)
|
| 1302 |
+
# output = llm.invoke(prompt)
|
| 1303 |
+
# full_response = output["output"]
|
| 1304 |
+
#full_response= replace_terms(full_response)
|
| 1305 |
+
|
| 1306 |
+
# cleaned_text = clean_text(full_response)
|
| 1307 |
+
# trust_tip, suggestion = get_trust_tip_and_suggestion()
|
| 1308 |
+
# combined_text = f"{cleaned_text}\n\n---\n\n**Trust Tip**: {trust_tip}\n\n**Suggestion**: {suggestion}"
|
| 1309 |
+
# with response_placeholder:
|
| 1310 |
+
# with st.chat_message("assistant"):
|
| 1311 |
+
# st.markdown(combined_text, unsafe_allow_html=True)
|
| 1312 |
+
|
| 1313 |
+
update_message_usage(st.session_state["wix_user_id"])
|
| 1314 |
+
|
| 1315 |
+
except Exception as e:
|
| 1316 |
+
logger.error(f"Error generating response: {e}")
|
| 1317 |
+
st.error("An error occurred while generating the response. Please try again.")
|
| 1318 |
+
|
| 1319 |
+
st.session_state.chat_history.append({"role": "assistant", "content": cleaned_text})
|
| 1320 |
+
copy_to_clipboard(cleaned_text)
|
| 1321 |
+
else:
|
| 1322 |
+
st.warning("You have reached your message limit. Please upgrade your plan to continue.")
|
| 1323 |
+
else:
|
| 1324 |
+
st.warning("Please log in to access the chatbot features.")
|