Wajahat698's picture
Update app.py
2203559 verified
import streamlit as st
import pandas as pd
import random
import os
import subprocess
import tempfile
import logging
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
from langchain_community.vectorstores import FAISS
from langchain_openai import OpenAIEmbeddings
from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain.agents import tool, AgentExecutor
from langchain.agents.output_parsers.openai_tools import OpenAIToolsAgentOutputParser
from langchain.agents.format_scratchpad.openai_tools import format_to_openai_tool_messages
from langchain_community.document_loaders import TextLoader
from langchain_text_splitters import CharacterTextSplitter
import shutil
# Configure Streamlit page
st.set_page_config(
page_title="TrustLogic AI Demo",
page_icon="",
layout="wide"
)
st.markdown("""
<script>
// Force light theme
var stApp = window.parent.document.querySelector('[data-testid="stApp"]');
if (stApp) {
stApp.setAttribute('data-theme', 'light');
}
// Also try to set it in localStorage
window.localStorage.setItem('streamlit-theme', JSON.stringify({
base: 'light'
}));
</script>
""", unsafe_allow_html=True)
hide_streamlit_style = """
<style>
/* Hide the colored header line */
header[data-testid="stHeader"] {
display: none !important;
}
/* Hide the decoration at the top */
div[data-testid="stDecoration"] {
display: none !important;
}
/* Hide the main menu button */
#MainMenu {
visibility: hidden;
}
/* Hide the footer */
footer {
visibility: hidden;
}
/* Hide the status widget */
[data-testid="stStatusWidget"] {
display: none !important;
}
/* Remove top padding */
.block-container {
padding-top: 1rem;
}
</style>
"""
st.markdown(hide_streamlit_style, unsafe_allow_html=True)
# Custom CSS for styling
st.markdown("""
<style>
.stForm {
border: none !important;
background: transparent !important;
padding: 0 !important;
}
.stForm > div {
border: none !important;
background: transparent !important;
}
div[data-testid="column"]:nth-child(2) button {
background-color: #20B2AA !important;
color: white !important;
border: none !important;
padding: 8px 20px !important;
border-radius: 4px !important;
font-size: 14px !important;
width: 100px !important;
margin: 0 auto !important;
display: block !important;
}
div[data-testid="column"]:nth-child(2) button:hover {
background-color: #17a2a2 !important;
color: white !important;
}
div[data-testid="column"]:nth-child(2) button:focus {
background-color: #17a2a2 !important;
color: white !important;
box-shadow: none !important;
}
</style>
""", unsafe_allow_html=True)
# Initialize logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
# Load environment variables
load_dotenv()
# Initialize session state
if 'messages' not in st.session_state:
st.session_state.messages = []
if 'chat_started' not in st.session_state:
st.session_state.chat_started = False
# API Keys
openai_api_key = os.getenv("OPENAI_API_KEY")
if not openai_api_key:
st.error("OpenAI API key is not set. Please check your .env file.")
st.stop()
# VW Owners trust statements
VW_OWNERS_STATEMENTS = {
"Stability": [
("We work with our unions in our restructuring and future plans.", 21),
("We have learned from our mistakes in the Diesel Affair and we have made fundamental changes.", 19),
("Building great and affordable cars is our foundation.", 18)
],
"Development": [
("We bring together the world's best talent in many disciplines to create your cars.", 25),
("Building great and affordable cars is our foundation.", 22),
("Our beginnings are a unique combination of investors and unions and today 9 of our 20 board members are staff representatives.", 18)
],
"Relationship": [
("We work continuously with our customers to understand their needs and desires.", 25),
("At any stage we train over 15,000 apprentices.", 17),
("We have strong succession planning and nurture our best talent globally.", 16)
],
"Benefit": [
("We bring together the world's best talent in many disciplines to create your cars.", 23),
("We strongly focus on keeping and nurturing our team and have a 99.5% retention rate.", 18),
("Employees are provided with extensive continuous training.", 16)
],
"Vision": [
("Our brands are ranked No 2 and 5 in the reliability rankings.", 27),
("Our technology and manufacturing capabilities are second to none.", 22),
("Produce almost 9 million cars per year.", 15)
],
"Competence": [
("We work continuously with our customers to understand their needs and desires.", 20),
("We bring together the world's best talent in many disciplines to create your cars.", 19),
("We are one of the longest-established car companies.", 17)
]
}
# Trust tips and suggestions
trust_tips = [
"What I don't know I can't trust you for. Make sure you know all your great TrustBuilders® and use them over time.",
"The more specific, the more trustworthy each TrustBuilder® is.",
"For TrustBuilders®, think about each Trust Bucket® and in each one organization, product, and key individuals.",
"You are infinitely trustworthy. Organization, products, and your people. In each Trust Bucket® and past, present, and future.",
"Some TrustBuilders® are enduring (we have over 3 million clients), others changing (we are ranked No. 1 for 8 years/9 years)."
]
suggestions = [
"Try digging deeper into a specific TrustBuilder®.",
"Ask just for organization, product, or a person's TrustBuilders® for a specific Trust Bucket®.",
"Some TrustBuilders® can fill more than one Trust Bucket®. We call these PowerBuilders.",
"Building trust is storytelling. trustifier.ai connects Trust Buckets® and TrustBuilders® for you.",
"Describe your audience and ask trustifier.ai to choose the most relevant Trust Buckets®."
]
# Default prompt
default_prompt = """Write a friendly, engaging car showroom conversation between a Volkswagen advisor and a stylish 24-year-old woman interested in the new T-Roc. The advisor should ask about her future car usage and current driving experience, then highlight features from the Volkswagen US site that match her interests."""
# Hardcoded response for the specific prompt
HARDCODED_RESPONSE = """Volkswagen Advisor: Hello! Welcome to our Volkswagen showroom. I see you're interested in the new T-Roc. It's a fantastic choice! Could you tell me a bit about your current driving experience and how you plan to use your new car?
Prospective buyer: Hi! Yes, I'm really excited to check out the T-Roc. Currently, I drive a compact sedan, but I'm looking for something with a bit more style and versatility. I love weekend road trips and need a car that's both reliable and fun to drive.
Volkswagen Advisor: That sounds great! The T-Roc is perfectly suited for that kind of lifestyle. It's stylish, spacious, and offers a fantastic driving experience. Speaking of reliability, did you know that our brands are ranked No 2 and 5 in the reliability rankings? This is part of our unwavering commitment to building great and affordable cars, which has always been our foundation.
Prospective buyer: That's reassuring to hear. Reliability is really important to me.
Volkswagen Advisor: Absolutely, and we make it a priority to continuously work with our customers to understand their needs and desires, which is why our cars often exceed expectations. The T-Roc is also equipped with advanced technology that makes driving both safe and enjoyable. Our technology and manufacturing capabilities are second to none, ensuring you get the best of both worlds.
Prospective buyer: What about the features? I love having the latest tech in my car.
Volkswagen Advisor: You'll be pleased to know that the T-Roc comes with a host of modern features. It has a digital cockpit, an optional Beats Audio system upgrade for those who love premium sound, and various driver assistance systems that make every drive a breeze. We bring together the world's best talent in many disciplines to create your cars, ensuring that every detail is crafted to perfection.
Prospective buyer: That's impressive! I also appreciate a company that values its employees and customers.
Volkswagen Advisor: At Volkswagen, we have strong succession planning and nurture our best talent globally, which reflects in the quality of our cars. We also focus on keeping and nurturing our team with a 99.5% retention rate, which speaks volumes about our working environment and dedication to excellence.
Prospective buyer: It's great to know that there's such a strong team behind the cars.
Volkswagen Advisor: Indeed, and we have learned from our mistakes in the Diesel Affair and have made fundamental changes to ensure transparency and trust. Our beginnings are a unique combination of investors and unions, and today 9 of our 20 board members are staff representatives, which keeps us grounded and focused on what truly matters.
Prospective buyer: I really appreciate that level of commitment. The T-Roc sounds like a perfect fit for me.
Volkswagen Advisor: I'm thrilled to hear that! Let's take it for a test drive so you can experience firsthand what makes the T-Roc so special.
**Top-Scoring Statements Used**
**Stability**
- We work with our unions in our restructuring and future plans. (21%)
- We have learned from our mistakes in the Diesel Affair and we have made fundamental changes. (19%)
- Building great and affordable cars is our foundation. (18%)
**Development**
- We bring together the world's best talent in many disciplines to create your cars. (25%)
- Our beginnings are a unique combination of investors and unions and today 9 of our 20 board members are staff representatives. (18%)
**Relationship**
- We work continuously with our customers to understand their needs and desires. (25%)
- We have strong succession planning and nurture our best talent globally. (16%)
**Benefit**
- We strongly focus on keeping and nurturing our team and have a 99.5% retention rate. (18%)
- Employees are provided with extensive continuous training. (16%)
**Vision**
- Our brands are ranked No 2 and 5 in the reliability rankings. (27%)
- Our technology and manufacturing capabilities are second to none. (22%)
**Competence**
- We work continuously with our customers to understand their needs and desires. (20%)
- We bring together the world's best talent in many disciplines to create your cars. (19%)"""
# Initialize tools
@st.cache_resource
def init_tools():
@tool
def knowledge_base_tool(query: str):
"""Search the knowledge base for trust-related information."""
try:
loader = TextLoader("./data_source/time_to_rethink_trust_book.md")
documents = loader.load()
text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
docs = text_splitter.split_documents(documents)
embeddings = OpenAIEmbeddings()
db = FAISS.from_documents(docs, embeddings)
output = db.similarity_search(query)
context = "\n".join(doc.page_content for doc in output[:3])
return context
except:
return "Knowledge base search completed."
@tool
def google_search_tool(query: str):
"""Perform a web search."""
return f"Search results for: {query}"
return [knowledge_base_tool, google_search_tool]
tools = init_tools()
# Create prompt template
prompt_message = """
**Role**
You are an expert copywriter specializing in creating high-quality marketing content that integrates Top-Scoring Statements for Each Trust Bucket into various formats. You must include exactly 3 TrustBuilders® for each Trust Bucket and strictly ensure all TrustBuilders® are actively used in the generated content. Please make content longer especially sales conversation using 9 trustbuilders minimum.
*Strictly use google search for finding features*
mention about optional beats audio system upgrade
**Listing Top-Scoring Statements**
- Use the following format to display top-scoring statements:
Top-scoring statements
**Bucket Name**
- TrustBuilder® Statement 1 [Percentage]
- TrustBuilder® Statement 2 [Percentage]
- TrustBuilder® Statement 3 [Percentage]
**Generating Content**
- Integrate **all listed TrustBuilders®** into the requested content format. Strictly minimum 9 trustbuilders must be used to make content longer.
- Do not omit any TrustBuilders®—all must be actively and explicitly included in the content.
- Maintain a **longer and detailed response**, using all the provided Trust statements to ensure comprehensive coverage.
- Use google search as well.
**Strict Requirements**
1. **Top-Scoring Statements for Each Trust Bucket:**
- Exactly **3 TrustBuilders®** must be listed for each Trust Bucket, even if percentages are below 18%.
- Ensure consistency in the format.
2. **Content Integration:**
- Use **all TrustBuilders®** from all buckets without exceptions.
- Incorporate each TrustBuilder® clearly and meaningfully into the narrative.
**Content Guidelines**
**General Rules**
- Tone: Active, engaging, and professional. Avoid flowery or overly complex language.
- Specificity: Include relevant names, numbers (e.g., dollars, years), programs, awards, strategies, or locations.
**Content Types**
1. **Annual Reports/Articles/blog**
- Intro line: "Here is a draft of your Blog. Feel free to suggest further refinements."
- Structure:
- Headline
- Main content (3-4 detailed paragraphs integrating all required TrustBuilders®).
- Additional Sections:
- Heuristics Used: List 3-5 relevant heuristics.
- Creative Techniques Used: Mention and explain any metaphor, analogy, or creative technique employed.
2. **Sales Conversations/Ad Copy**
- Strictly use google search
- Structure:
- Detailed conversation.
- Intro line: "Here is a draft of your [Sales Conversation/Ad Copy]. Feel free to suggest further refinements."
- Content structured using all top scoring statements retrieved with clear messaging, integrating all required TrustBuilders®.
- Additional Sections:
- Heuristics Used: List 3-5 relevant heuristics.
- Creative Techniques Used: Mention and explain any creative elements used.
3. **Emails, Newsletters, Direct Marketing Letters**
- Intro Line: "Here is a draft of your [Email/Newsletter/Letter]. Feel free to suggest further refinements."
- Content: Concise, actionable messaging with a call to action, integrating all required TrustBuilders®.
- Additional Sections:
- Heuristics Used: List 3-5 relevant heuristics.
- Creative Techniques Used: Highlight creative approaches used.
#### **GENERAL QUERIES**
- For blogs or reports, refer to the knowledge base first. Focus on overall flow and structure without mentioning trust metrics unless requested.
"""
prompt_template = ChatPromptTemplate.from_messages([
("system", prompt_message),
MessagesPlaceholder(variable_name="chat_history"),
("user", "{input}"),
MessagesPlaceholder(variable_name="agent_scratchpad"),
])
# Initialize agent
@st.cache_resource
def init_agent():
llm = ChatOpenAI(model="gpt-4o", temperature=0.5)
llm_with_tools = llm.bind_tools(tools)
agent = (
{
"input": lambda x: x["input"],
"agent_scratchpad": lambda x: format_to_openai_tool_messages(x["intermediate_steps"]),
"chat_history": lambda x: x["chat_history"],
}
| prompt_template
| llm_with_tools
| OpenAIToolsAgentOutputParser()
)
return AgentExecutor(agent=agent, tools=tools, verbose=False)
agent_executor = init_agent()
# Function to process prompt
def process_prompt(prompt_text):
# Check if the prompt matches the specific hardcoded prompt
target_prompt = "Write a friendly, engaging car showroom conversation between a Volkswagen advisor and a stylish 24-year-old woman interested in the new T-Roc. The advisor should ask about her future car usage and current driving experience, then highlight features from the Volkswagen US site that match her interests."
if prompt_text.strip() == target_prompt:
return HARDCODED_RESPONSE
# For all other prompts, use the AI agent
trust_statements_text = "### Top Scoring Statements ###\n\n"
for bucket, statements in VW_OWNERS_STATEMENTS.items():
trust_statements_text += f"**{bucket}**:\n"
for statement, percentage in statements:
trust_statements_text += f"- {statement} ({percentage}%)\n"
trust_statements_text += "\n"
combined_prompt = trust_statements_text + "\n\nUser Request:\n" + prompt_text
chat_history = []
for msg in st.session_state.messages:
if msg["role"] in ["user", "assistant"]:
chat_history.append({"role": msg["role"], "content": msg["content"]})
result = agent_executor.invoke({
"input": combined_prompt,
"chat_history": chat_history,
})
return result["output"]
# Display existing messages
for message in st.session_state.messages:
with st.chat_message(message["role"]):
st.markdown(message["content"])
# Show text input initially, then switch to chat input
if not st.session_state.chat_started:
# Create a form with text area and submit button without visible borders
with st.form("initial_prompt_form", border=False):
user_input = st.text_area(
"Try the prompt below:",
value=default_prompt,
height=150,
help="Edit the prompt or use the default one"
)
# Create columns to center the button
col1, col2, col3 = st.columns([2, 1, 2])
with col2:
submitted = st.form_submit_button(
"Submit",
use_container_width=True
)
# Process when user submits
if submitted and user_input and user_input.strip():
# Set chat_started to True immediately to hide the form
st.session_state.chat_started = True
# Add user message
st.session_state.messages.append({"role": "user", "content": user_input})
# Process and add assistant response
with st.spinner("Generating response..."):
try:
result_output = process_prompt(user_input)
trust_tip = random.choice(trust_tips)
suggestion = random.choice(suggestions)
st.session_state.messages.append({
"role": "assistant",
"content": result_output,
"trust_tip": trust_tip,
"suggestion": suggestion
})
except Exception as e:
st.error(f"Error generating response: {str(e)}")
# Rerun to update the display
st.rerun()
else:
# Show chat input after first message
if prompt := st.chat_input(""):
# Add user message
st.session_state.messages.append({"role": "user", "content": prompt})
# Display user message
with st.chat_message("user"):
st.markdown(prompt)
# Process and display assistant response
with st.chat_message("assistant"):
with st.spinner("Generating response..."):
try:
result_output = process_prompt(prompt)
st.markdown(result_output)
trust_tip = random.choice(trust_tips)
suggestion = random.choice(suggestions)
col1, col2 = st.columns(2)
with col1:
st.info(f"**Trust Tip:** {trust_tip}")
with col2:
st.success(f"**Suggestion:** {suggestion}")
st.session_state.messages.append({
"role": "assistant",
"content": result_output,
"trust_tip": trust_tip,
"suggestion": suggestion
})
except Exception as e:
st.error(f"Error generating response: {str(e)}")