a streamlit version of a Microsoft Teams Copilot
To upload files, please first save the app
import streamlit as st
import time
import random
import os
from dotenv import load_dotenv
# Load environment variables
load_dotenv()
# Page configuration
st.set_page_config(
page_title="Teams Copilot",
page_icon="🤖",
layout="wide"
)
# Custom CSS for Teams-like UI
st.markdown("""
<style>
.main {
background-color: #f5f5f5;
}
.chat-container {
background-color: white;
border-radius: 8px;
padding: 20px;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
height: 70vh;
overflow-y: auto;
margin-bottom: 20px;
}
.sidebar {
background-color: #f3f2f1;
padding: 20px;
border-radius: 8px;
}
.user-message {
background-color: #e9eaf6;
padding: 10px 15px;
border-radius: 18px;
margin: 10px 0;
max-width: 80%;
align-self: flex-end;
margin-left: auto;
}
.assistant-message {
background-color: #f0f0f0;
padding: 10px 15px;
border-radius: 18px;
margin: 10px 0;
max-width: 80%;
}
.stTextInput input {
border-radius: 20px;
border: 1px solid #dadce0;
padding: 10px 15px;
}
.copilot-header {
color: #6264A7;
display: flex;
align-items: center;
margin-bottom: 20px;
}
.copilot-header h1 {
margin-left: 10px;
}
.feature-card {
background-color: white;
border-radius: 8px;
padding: 15px;
margin-bottom: 15px;
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
cursor: pointer;
}
.feature-card:hover {
box-shadow: 0 2px 5px rgba(0,0,0,0.2);
}
.feature-title {
color: #6264A7;
font-weight: bold;
margin-bottom: 5px;
}
.feature-description {
color: #666;
font-size: 0.9em;
}
</style>
""", unsafe_allow_html=True)
# Initialize session state
if "messages" not in st.session_state:
st.session_state.messages = []
if "current_prompt" not in st.session_state:
st.session_state.current_prompt = ""
# Create the layout
col1, col2 = st.columns([1, 3])
with col1:
st.markdown('<div class="sidebar">', unsafe_allow_html=True)
st.markdown("### Copilot features")
# Feature cards
features = [
{
"title": "Summarize meeting",
"description": "Generate a summary of meeting notes, action items, and key decisions.",
"prompt": "Summarize the last meeting we had about the quarterly report."
},
{
"title": "Draft an email",
"description": "Create professional email drafts based on your requirements.",
"prompt": "Draft an email to the team about the upcoming project deadline."
},
{
"title": "Create a presentation",
"description": "Generate outline and content for presentations.",
"prompt": "Create a presentation outline for our new product launch."
},
{
"title": "Answer questions",
"description": "Get answers to your questions about work-related topics.",
"prompt": "What's the best way to organize a remote team meeting?"
}
]
for feature in features:
feature_html = f"""
<div class="feature-card" onclick="document.getElementById('chat-input').value='{feature['prompt']}';">
<div class="feature-title">{feature['title']}</div>
<div class="feature-description">{feature['description']}</div>
</div>
"""
st.markdown(feature_html, unsafe_allow_html=True)
st.markdown("</div>", unsafe_allow_html=True)
with col2:
# Copilot header
st.markdown(
'<div class="copilot-header"><span style="font-size:30px;">🤖</span><h1>Teams Copilot</h1></div>',
unsafe_allow_html=True
)
# Chat container
st.markdown('<div class="chat-container">', unsafe_allow_html=True)
# Display chat messages
for message in st.session_state.messages:
if message["role"] == "user":
st.markdown(f'<div class="user-message">{message["content"]}</div>', unsafe_allow_html=True)
else:
st.markdown(f'<div class="assistant-message">{message["content"]}</div>', unsafe_allow_html=True)
st.markdown('</div>', unsafe_allow_html=True)
# Chat input
def submit_message():
if st.session_state.user_input and st.session_state.user_input.strip():
# Add user message to chat
user_message = st.session_state.user_input
st.session_state.messages.append({"role": "user", "content": user_message})
st.session_state.user_input = ""
# Generate response
with st.spinner("Thinking..."):
response = generate_response(user_message)
# Add assistant response to chat
st.session_state.messages.append({"role": "assistant", "content": response})
st.rerun()
# Input field
st.text_input("", key="user_input", on_change=submit_message, placeholder="Type your message here...", label_visibility="collapsed", id="chat-input")
# Generate responses based on user input
def generate_response(prompt):
"""
This function would normally use the OpenAI API or a similar service.
For this example, we'll use a simple mock response generator.
"""
# If you have an OpenAI API key, you can use this instead
if os.getenv("OPENAI_API_KEY"):
try:
import openai
openai.api_key = os.getenv("OPENAI_API_KEY")
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=[
{"role": "system", "content": "You are Teams Copilot, a helpful AI assistant for Microsoft Teams. Provide helpful, concise, and professional responses."},
{"role": "user", "content": prompt}
],
temperature=0.7,
max_tokens=500
)
return response.choices[0].message.content
except Exception as e:
st.error(f"Error accessing OpenAI API: {e}")
# Fall back to mock responses if API call fails
return mock_response_generator(prompt)
else:
# Use mock responses when no API key is available
return mock_response_generator(prompt)
def mock_response_generator(prompt):
"""Generate mock responses based on prompt keywords"""
time.sleep(1) # Simulate thinking time
# Simple keyword-based responses
prompt_lower = prompt.lower()
if "summarize" in prompt_lower or "meeting" in prompt_lower:
return """# Meeting Summary
**Date:** April 15, 2023
**Participants:** Marketing team, Product team, Leadership
## Key Discussion Points:
- Q1 performance exceeded targets by 12%
- New product launch scheduled for Q3
- Budget allocation for upcoming campaigns
## Action Items:
1. Sarah to finalize the quarterly report by Friday
2. John to coordinate with Design on new visuals
3. Team to review projections for Q2 by next week
Would you like me to add more details to any section?"""
elif "email" in prompt_lower or "draft" in prompt_lower:
return """Subject: Important Update on Project Deadline
Hi Team,
I hope this email finds you well. I wanted to provide an update regarding our upcoming project deadline.
Due to the additional requirements that came in last week, we've adjusted the timeline for deliverables. The new deadline is May 15th, which gives us an additional week to ensure quality and thoroughness.
Please review your assigned tasks and let me know if you foresee any challenges with the new timeline. We'll discuss this further in our team meeting on Wednesday.
Thank you for your continued dedication to this project.
Best regards,
[Your Name]"""
elif "presentation" in prompt_lower or "slides" in prompt_lower:
return """# Product Launch Presentation Outline
## 1. Introduction (2 slides)
- Company mission and vision
- Brief overview of market opportunity
## 2. Product Overview (3-4 slides)
- Key features and benefits
- Unique selling proposition
- Demo or product visuals
## 3. Market Analysis (2-3 slides)
- Target audience
- Competitor analysis
- Market positioning
## 4. Launch Strategy (3 slides)
- Marketing campaign details
- Distribution channels
- Timeline and key milestones
## 5. Projected Outcomes (2 slides)
- Sales forecasts
- Success metrics
- Long-term vision
## 6. Q&A (1 slide)
Would you like me to expand on any section?"""
elif "remote" in prompt_lower or "team meeting" in prompt_lower:
return """# Best Practices for Organizing Remote Team Meetings
1. **Set clear objectives**: Define the purpose and goals of the meeting in advance.
2. **Create and share an agenda**: Distribute it at least 24 hours before the meeting.
3. **Keep it concise**: Aim for 30-45 minutes when possible to maintain focus.
4. **Choose the right tools**: Ensure your video conferencing platform has necessary features like screen sharing and recording.
5. **Establish meeting etiquette**: Guidelines for muting, camera use, and participation.
6. **Include interactive elements**: Polls, breakout rooms, or collaborative documents to increase engagement.
7. **Follow up promptly**: Send meeting notes and action items within 24 hours.
Would you like more specific recommendations for any of these areas?"""
else:
responses = [
"I understand you're asking about '{}'. Could you provide more details so I can give you a more helpful response?",
"I'd be happy to help with '{}'. Could you elaborate a bit more on what specifically you're looking for?",
"Thanks for your question about '{}'. To provide the most relevant information, could you share more context?",
"I can assist with '{}'. Would you like general information or do you have specific requirements in mind?"
]
return random.choice(responses).format(prompt[:30] + "..." if len(prompt) > 30 else prompt)
Hi! I can help you with any questions about Streamlit and Python. What would you like to know?