|
|
import streamlit as st |
|
|
st.set_page_config(page_title="B2B Problem Solver", layout="wide") |
|
|
|
|
|
import requests |
|
|
import os |
|
|
import json |
|
|
from bs4 import BeautifulSoup |
|
|
|
|
|
|
|
|
API_OPTIONS = { |
|
|
"OpenAI": { |
|
|
"endpoint": "https://api.openai.com/v1/chat/completions", |
|
|
"env_key": "OPENAI_API_KEY", |
|
|
"models": ["gpt-4", "gpt-3.5-turbo"] |
|
|
}, |
|
|
"Anthropic": { |
|
|
"endpoint": "https://api.anthropic.com/v1/messages", |
|
|
"env_key": "ANTHROPIC_API_KEY", |
|
|
"models": ["claude-3-opus-20240229", "claude-3-sonnet-20240229", "claude-3-haiku-20240307"] |
|
|
}, |
|
|
"Azure OpenAI": { |
|
|
"endpoint": os.getenv("AZURE_OPENAI_ENDPOINT", "https://your-resource-name.openai.azure.com/openai/deployments/your-deployment-name/chat/completions?api-version=2023-05-15"), |
|
|
"env_key": "AZURE_OPENAI_API_KEY", |
|
|
"models": ["your-deployment-name"] |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
PROBLEM_CATEGORIES = [ |
|
|
"Sales Pipeline Issues", |
|
|
"Lead Generation Challenges", |
|
|
"Customer Retention Problems", |
|
|
"Marketing ROI Concerns", |
|
|
"Product-Market Fit", |
|
|
"Team Performance Issues", |
|
|
"Competitive Positioning", |
|
|
"Pricing Strategy", |
|
|
"Market Expansion Difficulties", |
|
|
"Digital Transformation Challenges", |
|
|
"Customer Acquisition Costs", |
|
|
"Other (Please Specify)" |
|
|
] |
|
|
|
|
|
|
|
|
if 'api_provider' not in st.session_state: |
|
|
st.session_state.api_provider = "OpenAI" |
|
|
if 'api_model' not in st.session_state: |
|
|
st.session_state.api_model = API_OPTIONS["OpenAI"]["models"][0] |
|
|
if 'api_key' not in st.session_state: |
|
|
st.session_state.api_key = os.getenv(API_OPTIONS["OpenAI"]["env_key"], "") |
|
|
|
|
|
def scrape_company_info(url): |
|
|
"""Scrapes business information from the given company website URL with improved error handling.""" |
|
|
if not url.startswith("http"): |
|
|
url = f"https://{url}" |
|
|
|
|
|
headers = { |
|
|
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36", |
|
|
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", |
|
|
"Accept-Language": "en-US,en;q=0.5", |
|
|
"Connection": "keep-alive", |
|
|
"Upgrade-Insecure-Requests": "1", |
|
|
"Cache-Control": "max-age=0" |
|
|
} |
|
|
|
|
|
try: |
|
|
response = requests.get(url, headers=headers, timeout=15) |
|
|
response.raise_for_status() |
|
|
soup = BeautifulSoup(response.content, "html.parser") |
|
|
|
|
|
content = [] |
|
|
|
|
|
meta_description = soup.find("meta", {"name": "description"}) |
|
|
if meta_description and meta_description.get("content"): |
|
|
content.append(meta_description["content"]) |
|
|
|
|
|
|
|
|
title = soup.find("title") |
|
|
if title and title.string: |
|
|
content.append(title.string.strip()) |
|
|
|
|
|
|
|
|
for tag in ['h1', 'h2', 'p']: |
|
|
elements = soup.find_all(tag) |
|
|
content.extend([elem.get_text(strip=True) for elem in elements if elem.get_text(strip=True)]) |
|
|
|
|
|
extracted_content = " ".join(content[:1500]) |
|
|
|
|
|
if not extracted_content or len(extracted_content.split()) < 10: |
|
|
return f"Unable to extract sufficient information from {url}. Please enter company details manually." |
|
|
|
|
|
return extracted_content |
|
|
except requests.exceptions.HTTPError as e: |
|
|
if e.response.status_code == 403: |
|
|
return f"Cannot access {url} - Website has blocked our request (403 Forbidden). Please enter company details manually." |
|
|
elif e.response.status_code == 404: |
|
|
return f"Website {url} not found (404). Please check the URL and try again." |
|
|
else: |
|
|
return f"HTTP Error: {str(e)}. Please enter company details manually." |
|
|
except requests.exceptions.ConnectionError: |
|
|
return f"Failed to connect to {url}. Please check the URL or your internet connection." |
|
|
except requests.exceptions.Timeout: |
|
|
return f"Request to {url} timed out. The website may be slow or unavailable." |
|
|
except requests.exceptions.RequestException as e: |
|
|
return f"Error scraping website: {str(e)}. Please enter company details manually." |
|
|
except Exception as e: |
|
|
return f"Unexpected error: {str(e)}. Please enter company details manually." |
|
|
|
|
|
def generate_problem_solution(business_info, problem_category, problem_description): |
|
|
"""Generates a practical solution for the specified business problem using the configured AI provider.""" |
|
|
prompt = f"""As a senior B2B growth strategist with extensive experience helping sales and marketing executives overcome business challenges, provide a practical solution for the following scenario: |
|
|
|
|
|
COMPANY INFORMATION: |
|
|
{business_info} |
|
|
|
|
|
PROBLEM CATEGORY: {problem_category} |
|
|
|
|
|
SPECIFIC PROBLEM: |
|
|
{problem_description} |
|
|
|
|
|
Please provide: |
|
|
|
|
|
1. **Problem Analysis**: Briefly analyze the root causes of this issue based on common patterns in B2B companies. |
|
|
|
|
|
2. **Strategic Solution**: Outline a clear, actionable solution that addresses the core problem. |
|
|
|
|
|
3. **Implementation Steps**: Provide 3-5 specific, tactical steps to implement the solution. |
|
|
|
|
|
4. **Expected Outcomes**: Describe the measurable results and timeframe they can expect. |
|
|
|
|
|
5. **Common Pitfalls**: Note 2-3 potential challenges they might face during implementation and how to avoid them. |
|
|
|
|
|
6. **Resource Requirements**: Briefly list any tools, skills, or resources needed. |
|
|
|
|
|
Format your response in clear markdown with headers and bullet points, keeping it concise, practical, and immediately actionable for busy executives.""" |
|
|
|
|
|
provider = st.session_state.api_provider |
|
|
model = st.session_state.api_model |
|
|
api_key = st.session_state.api_key |
|
|
|
|
|
if not api_key: |
|
|
return f"Error: Missing API key for {provider}. Please configure your API key in the settings." |
|
|
|
|
|
try: |
|
|
if provider == "OpenAI": |
|
|
return call_openai_api(prompt, model, api_key) |
|
|
elif provider == "Anthropic": |
|
|
return call_anthropic_api(prompt, model, api_key) |
|
|
elif provider == "Azure OpenAI": |
|
|
return call_azure_openai_api(prompt, model, api_key) |
|
|
else: |
|
|
return "Error: Invalid API provider selected" |
|
|
except Exception as e: |
|
|
error_message = str(e) |
|
|
return f"API Error: {error_message}\n\nPlease check your API configuration in the settings panel." |
|
|
|
|
|
def call_openai_api(prompt, model, api_key): |
|
|
"""Call the OpenAI API to generate a response.""" |
|
|
headers = { |
|
|
"Authorization": f"Bearer {api_key}", |
|
|
"Content-Type": "application/json" |
|
|
} |
|
|
|
|
|
data = { |
|
|
"model": model, |
|
|
"messages": [ |
|
|
{"role": "system", "content": "You are a senior B2B growth strategist who specializes in solving critical business challenges for sales and marketing executives."}, |
|
|
{"role": "user", "content": prompt} |
|
|
], |
|
|
"temperature": 0.7, |
|
|
"max_tokens": 3500 |
|
|
} |
|
|
|
|
|
response = requests.post(API_OPTIONS["OpenAI"]["endpoint"], json=data, headers=headers) |
|
|
response.raise_for_status() |
|
|
return response.json()["choices"][0]["message"]["content"] |
|
|
|
|
|
def call_anthropic_api(prompt, model, api_key): |
|
|
"""Call the Anthropic API to generate a response.""" |
|
|
headers = { |
|
|
"x-api-key": api_key, |
|
|
"anthropic-version": "2023-06-01", |
|
|
"content-type": "application/json" |
|
|
} |
|
|
|
|
|
data = { |
|
|
"model": model, |
|
|
"messages": [ |
|
|
{"role": "user", "content": prompt} |
|
|
], |
|
|
"max_tokens": 3500 |
|
|
} |
|
|
|
|
|
response = requests.post(API_OPTIONS["Anthropic"]["endpoint"], json=data, headers=headers) |
|
|
response.raise_for_status() |
|
|
return response.json()["content"][0]["text"] |
|
|
|
|
|
def call_azure_openai_api(prompt, model, api_key): |
|
|
"""Call the Azure OpenAI API to generate a response.""" |
|
|
headers = { |
|
|
"api-key": api_key, |
|
|
"Content-Type": "application/json" |
|
|
} |
|
|
|
|
|
data = { |
|
|
"messages": [ |
|
|
{"role": "system", "content": "You are a senior B2B growth strategist who specializes in solving critical business challenges for sales and marketing executives."}, |
|
|
{"role": "user", "content": prompt} |
|
|
], |
|
|
"temperature": 0.7, |
|
|
"max_tokens": 3500 |
|
|
} |
|
|
|
|
|
response = requests.post(API_OPTIONS["Azure OpenAI"]["endpoint"], json=data, headers=headers) |
|
|
response.raise_for_status() |
|
|
return response.json()["choices"][0]["message"]["content"] |
|
|
|
|
|
|
|
|
st.title("🚀 B2B Problem Solver") |
|
|
st.markdown("### Get practical solutions to common business problems hindering your growth") |
|
|
|
|
|
|
|
|
with st.sidebar: |
|
|
st.header("API Settings") |
|
|
st.session_state.api_provider = st.selectbox( |
|
|
"Select AI Provider", |
|
|
options=list(API_OPTIONS.keys()), |
|
|
index=list(API_OPTIONS.keys()).index(st.session_state.api_provider) |
|
|
) |
|
|
|
|
|
st.session_state.api_model = st.selectbox( |
|
|
"Select Model", |
|
|
options=API_OPTIONS[st.session_state.api_provider]["models"], |
|
|
index=min(API_OPTIONS[st.session_state.api_provider]["models"].index(st.session_state.api_model) |
|
|
if st.session_state.api_model in API_OPTIONS[st.session_state.api_provider]["models"] else 0, |
|
|
len(API_OPTIONS[st.session_state.api_provider]["models"]) - 1) |
|
|
) |
|
|
|
|
|
api_key_env = API_OPTIONS[st.session_state.api_provider]["env_key"] |
|
|
api_key_input = st.text_input( |
|
|
f"API Key (or set {api_key_env} environment variable)", |
|
|
type="password", |
|
|
value=st.session_state.api_key |
|
|
) |
|
|
if api_key_input: |
|
|
st.session_state.api_key = api_key_input |
|
|
|
|
|
st.info(f"Current status: {'✅ API key configured' if st.session_state.api_key else '❌ API key missing'}") |
|
|
|
|
|
with st.expander("💡 How it works", expanded=True): |
|
|
st.markdown(""" |
|
|
1. Enter your company details or website URL |
|
|
2. Select your most pressing business challenge |
|
|
3. Receive a customized, actionable solution plan |
|
|
4. Implement the steps to overcome your growth obstacle |
|
|
""") |
|
|
|
|
|
input_method = st.radio("Choose input method:", ["Enter company details manually", "Use company website URL"]) |
|
|
|
|
|
if input_method == "Enter company details manually": |
|
|
company_name = st.text_input("Company Name*") |
|
|
industry = st.text_input("Industry*") |
|
|
company_description = st.text_area("What does your company do?*", help="Describe your products/services and target market.") |
|
|
team_size = st.selectbox("Company Size", ["1-10 employees", "11-50 employees", "51-200 employees", "201-500 employees", "500+ employees"]) |
|
|
|
|
|
st.markdown("### What's your biggest challenge?") |
|
|
problem_category = st.selectbox("Select problem category*", PROBLEM_CATEGORIES) |
|
|
if problem_category == "Other (Please Specify)": |
|
|
custom_category = st.text_input("Please specify your problem category") |
|
|
problem_category = custom_category if custom_category else problem_category |
|
|
|
|
|
problem_description = st.text_area("Describe your specific challenge*", help="Provide details about the problem you're facing and what you've tried so far.") |
|
|
|
|
|
if st.button("Generate Solution"): |
|
|
if not all([company_name, industry, company_description, problem_description]): |
|
|
st.error("Please fill in all required fields marked with *") |
|
|
elif not st.session_state.api_key: |
|
|
st.error(f"Please configure your {st.session_state.api_provider} API key in the sidebar") |
|
|
else: |
|
|
with st.spinner("Analyzing your business challenge and crafting a solution..."): |
|
|
business_info = f""" |
|
|
Company Name: {company_name} |
|
|
Industry: {industry} |
|
|
Company Description: {company_description} |
|
|
Company Size: {team_size} |
|
|
""" |
|
|
solution = generate_problem_solution(business_info, problem_category, problem_description) |
|
|
if solution: |
|
|
if not solution.startswith("Error") and not solution.startswith("API Error"): |
|
|
st.markdown("## Your Customized Solution Plan") |
|
|
st.markdown(solution) |
|
|
|
|
|
with st.expander("Want expert help implementing this solution?"): |
|
|
st.markdown(""" |
|
|
Our growth agency specializes in helping B2B companies implement these solutions and achieve measurable results. |
|
|
|
|
|
**Schedule a free 30-minute consultation** to discuss how we can help you overcome this challenge and accelerate your growth. |
|
|
""") |
|
|
contact_email = st.text_input("Your Email") |
|
|
if st.button("Request Consultation"): |
|
|
if contact_email: |
|
|
st.success("Thank you! We'll be in touch shortly to schedule your consultation.") |
|
|
else: |
|
|
st.warning("Please enter your email address.") |
|
|
else: |
|
|
st.error(solution) |
|
|
|
|
|
else: |
|
|
website_url = st.text_input("Enter your company website URL*", placeholder="e.g., www.example.com") |
|
|
|
|
|
st.markdown("### What's your biggest challenge?") |
|
|
problem_category = st.selectbox("Select problem category*", PROBLEM_CATEGORIES) |
|
|
if problem_category == "Other (Please Specify)": |
|
|
custom_category = st.text_input("Please specify your problem category") |
|
|
problem_category = custom_category if custom_category else problem_category |
|
|
|
|
|
problem_description = st.text_area("Describe your specific challenge*", help="Provide details about the problem you're facing and what you've tried so far.") |
|
|
|
|
|
if st.button("Generate Solution"): |
|
|
if not all([website_url, problem_description]): |
|
|
st.error("Please fill in all required fields marked with *") |
|
|
elif not st.session_state.api_key: |
|
|
st.error(f"Please configure your {st.session_state.api_provider} API key in the sidebar") |
|
|
else: |
|
|
with st.spinner("Extracting company details and generating your solution..."): |
|
|
company_info = scrape_company_info(website_url) |
|
|
if company_info: |
|
|
if company_info.startswith("Cannot access") or company_info.startswith("Unable to extract") or company_info.startswith("Failed to connect") or company_info.startswith("HTTP Error") or company_info.startswith("Unexpected error"): |
|
|
st.warning(company_info) |
|
|
st.info("Please try entering your company details manually instead.") |
|
|
|
|
|
company_name = st.text_input("Company Name*") |
|
|
industry = st.text_input("Industry*") |
|
|
company_description = st.text_area("What does your company do?*", help="Describe your products/services and target market.") |
|
|
team_size = st.selectbox("Company Size", ["1-10 employees", "11-50 employees", "51-200 employees", "201-500 employees", "500+ employees"]) |
|
|
|
|
|
if st.button("Try Again with Manual Details"): |
|
|
if not all([company_name, industry, company_description]): |
|
|
st.error("Please fill in all required fields marked with *") |
|
|
else: |
|
|
with st.spinner("Analyzing your business challenge and crafting a solution..."): |
|
|
business_info = f""" |
|
|
Company Name: {company_name} |
|
|
Industry: {industry} |
|
|
Company Description: {company_description} |
|
|
Company Size: {team_size} |
|
|
""" |
|
|
manual_solution = generate_problem_solution(business_info, problem_category, problem_description) |
|
|
display_solution(manual_solution) |
|
|
else: |
|
|
solution = generate_problem_solution(company_info, problem_category, problem_description) |
|
|
display_solution(solution) |
|
|
|
|
|
|
|
|
st.markdown("---") |
|
|
st.markdown("Powered by [Your Growth Agency Name] | Helping B2B companies overcome growth obstacles since [Year]") |