addition of comparison tables

This commit is contained in:
Madhu 2025-01-12 22:35:52 +05:30
parent 9c6540efd1
commit 2243b6d54c

View file

@ -4,6 +4,7 @@ from phi.agent import Agent
from phi.tools.firecrawl import FirecrawlTools from phi.tools.firecrawl import FirecrawlTools
from phi.model.openai import OpenAIChat from phi.model.openai import OpenAIChat
from phi.tools.duckduckgo import DuckDuckGo from phi.tools.duckduckgo import DuckDuckGo
import pandas as pd
# Streamlit UI # Streamlit UI
st.set_page_config(page_title="AI Competitor Intelligence Agent", layout="wide") st.set_page_config(page_title="AI Competitor Intelligence Agent", layout="wide")
@ -48,14 +49,21 @@ if "openai_api_key" in st.session_state and "firecrawl_api_key" in st.session_st
) )
firecrawl_agent = Agent( firecrawl_agent = Agent(
model=OpenAIChat(id="gpt-4", api_key=st.session_state.openai_api_key), model=OpenAIChat(id="gpt-4o-mini", api_key=st.session_state.openai_api_key),
tools=[firecrawl_tools, DuckDuckGo()], tools=[firecrawl_tools, DuckDuckGo()],
show_tool_calls=True, show_tool_calls=True,
markdown=True markdown=True
) )
analysis_agent = Agent( analysis_agent = Agent(
model=OpenAIChat(id="gpt-4", api_key=st.session_state.openai_api_key), model=OpenAIChat(id="gpt-4o-mini", api_key=st.session_state.openai_api_key),
show_tool_calls=True,
markdown=True
)
# New agent for comparing competitor data
comparison_agent = Agent(
model=OpenAIChat(id="gpt-4o-mini", api_key=st.session_state.openai_api_key),
show_tool_calls=True, show_tool_calls=True,
markdown=True markdown=True
) )
@ -87,29 +95,99 @@ if "openai_api_key" in st.session_state and "firecrawl_api_key" in st.session_st
crawl_response = firecrawl_agent.run(f"Crawl and summarize {competitor_url}") crawl_response = firecrawl_agent.run(f"Crawl and summarize {competitor_url}")
crawled_data = crawl_response.content crawled_data = crawl_response.content
structured_info = firecrawl_agent.run(
f"""Extract the following information from the crawled data:
- Product pricing and features: Extract exact pricing numbers from their pricing page.
- Technology stack information
- Marketing messaging/positioning
- Customer testimonials/case studies
- Latest news and developments (use DuckDuckGo to search for the latest news and developments)
Crawled Data:
{crawled_data}
"""
)
return { return {
"competitor": competitor_url, "competitor": competitor_url,
"data": structured_info.content "data": crawled_data
} }
except Exception as e: except Exception as e:
st.error(f"Error extracting info for {competitor_url}: {e}")
return { return {
"competitor": competitor_url, "competitor": competitor_url,
"error": str(e) "error": str(e)
} }
def generate_comparison_report(competitor_data: list) -> None:
"""
Generate and display a comparison report of competitor data.
Args:
competitor_data: List of dictionaries containing competitor information
"""
# Combine all competitor data into a single string
combined_data = "\n\n".join([str(data) for data in competitor_data])
# Updated system prompt for more structured output
system_prompt = """
As an expert business analyst, analyze the competitor data and create a structured comparison table.
Format the data in EXACTLY this markdown table structure:
| Company | Pricing | Key Features | Tech Stack | Marketing Focus | Customer Feedback |
|---------|---------|--------------|------------|-----------------|-------------------|
| [Company Name 1] | ... | ... | ... | ... | ... |
| [Company Name 2] | ... | ... | ... | ... | ... |
| [Company Name 3] | ... | ... | ... | ... | ... |
Rules:
1. Always include all columns
2. Use the exact column names specified above
3. Keep entries concise but informative
4. Use pipe symbols (|) to separate columns
5. Include the separator row (|---|) after headers
Competitor Data:
{combined_data}
"""
# Get comparison table from agent
comparison_response = comparison_agent.run(
system_prompt.format(combined_data=combined_data)
)
# Display the raw markdown table first
# st.subheader("Competitor Comparison (Markdown)")
# st.markdown(comparison_response.content)
try:
# Split the markdown table into lines and clean them
table_lines = [
line.strip()
for line in comparison_response.content.split('\n')
if line.strip() and '|' in line
]
# Extract headers (first row)
headers = [
col.strip()
for col in table_lines[0].split('|')
if col.strip()
]
# Extract data rows (skip header and separator rows)
data_rows = []
for line in table_lines[2:]: # Skip header and separator rows
row_data = [
cell.strip()
for cell in line.split('|')
if cell.strip()
]
if len(row_data) == len(headers):
data_rows.append(row_data)
# Create DataFrame with explicit index
df = pd.DataFrame(
data_rows,
columns=headers,
index=range(len(data_rows))
)
# Display the DataFrame
st.subheader("Competitor Comparison (Table)")
st.table(df)
except Exception as e:
st.error(f"Error converting table to DataFrame: {str(e)}")
st.write("Raw table data for debugging:", table_lines)
def generate_analysis_report(competitor_data: list): def generate_analysis_report(competitor_data: list):
combined_data = "\n\n".join([str(data) for data in competitor_data]) combined_data = "\n\n".join([str(data) for data in competitor_data])
@ -144,11 +222,16 @@ if "openai_api_key" in st.session_state and "firecrawl_api_key" in st.session_st
competitor_info = extract_competitor_info(url) competitor_info = extract_competitor_info(url)
competitor_data.append(competitor_info) competitor_data.append(competitor_info)
# Generate and display comparison report
with st.spinner("Generating comparison table..."):
generate_comparison_report(competitor_data)
# Generate and display final analysis report
with st.spinner("Generating analysis report..."): with st.spinner("Generating analysis report..."):
analysis_report = generate_analysis_report(competitor_data) analysis_report = generate_analysis_report(competitor_data)
st.success("Analysis complete!")
st.subheader("Competitor Analysis Report") st.subheader("Competitor Analysis Report")
st.markdown(analysis_report) st.markdown(analysis_report)
st.success("Analysis complete!")
else: else:
st.error("Please provide either a URL or a description.") st.error("Please provide either a URL or a description.")