Generate an AI Competition Report with Exa, Anthropic, and Twilio SendGrid

February 08, 2024
Written by
Reviewed by
Sam Agnew
Twilion
Sarah Chieng
Contributor
Opinions expressed by Twilio contributors are their own

Generate an AI Competition Report with Exa, Anthropic, and Twilio SendGrid 

At an AI hackathon recently, my team worked on this project where a user inputs their startup idea and email to a Streamlit web app and then they receive an AI-generated competition report. Read on to learn how Sarah Chieng , Abel Regalado , and I built it using Exa , Anthropic , and Twilio SendGrid in Python!

Picture of a startup brainstorm service using AI

Prerequisites

Configuration

Since you will be installing some Python packages for this project, you need to make a new project directory and a virtual environment .

If you're using a Unix or macOS system, open a terminal and enter the following commands:

mkdir sendgrid-exa-comp-report  
cd sendgrid-exa-comp-report
python3 -m venv venv 
source venv/bin/activate 
pip install streamlit anthropic sendgrid exa_py

If you're following this tutorial on Windows, enter the following commands in a command prompt window:

mkdir sendgrid-exa-comp-report  
cd sendgrid-exa-comp-report
python -m venv venv 
venv\Scripts\activate 
pip install streamlit anthropic sendgrid exa_py

Now it's time to dig into some code!

In that directory, make a file called app.py. Include the following import statements:

from anthropic import Anthropic, HUMAN_PROMPT, AI_PROMPT
from dotenv import dotenv_values
import os
from PIL import Image
import requests
import sendgrid
from sendgrid import SendGridAPIClient
from sendgrid.helpers.mail import (
     Mail, Attachment, FileContent, FileName, FileType, Disposition)
import streamlit as st

On the command line, make a new folder called css. In that folder, make a file called style.css containing the following code:

.stApp > header {
    background-color: transparent;
}
.stApp {
    margin: auto;
    font-family: -apple-system, BlinkMacSystemFont, sans-serif;
    overflow: auto;
    background: linear-gradient(315deg, #4f2991 3%, #7dc4ff 38%, #36cfcc 68%, #a92ed3 98%);
    animation: gradient 15s ease infinite;
    background-size: 400% 400%;
    background-attachment: fixed;
}

In app.py, add the following lines beneath import streamlit as st to use that CSS code:

with open('./css/style.css') as f:
    css = f.read()
st.markdown(f'<style>{css}</style>', unsafe_allow_html=True)

Make a .env file and include the following, replacing the values with your API keys:

ANTHROPIC_API_KEY=
EXA_API_KEY=
SENDGRID_API_KEY=

Access those API keys with the following Python code that creates an Exa object, sets the example_idea variable, and adds a title, subtext, and an image (which you can get from GitHub here ) to the Streamlit app:

config = dotenv_values(".env")
EXA_API_KEY = config.get('EXA_API_KEY')
SENDGRID_API_KEY = config.get('SENDGRID_API_KEY')
ANTHROPIC_API_KEY = config.get('ANTHROPIC_API_KEY')
example_idea = "women's tennis clothes"
st.title("Who Done it: Diligence AI") 
st.write("You think you have original ideas? You don't.😘") 
image = Image.open('competition.jpeg')
st.image(image)

Create a Streamlit text area and text input so the user can input their startup idea and email:

idea = st.text_area("""
Describe your startup idea in as much depth as you'd like💡. 
We'll show you who's building something similar:""", example_idea)
user_email = st.text_input("Email to get report📧")

Generate Competitors with Exa Helper Function

Next, add this helper function to perform a snippet search for competitors relating to an input string (a user's startup idea).

def find_competitors(idea):
    search = "Here's my company idea, " + idea + ". Here's a company that's doing it:"
    url = "https://api.exa.ai/search/snippet"
    payload = { "query": search,
            "snippetLength": 3,
            "useAutoprompt": False,
            "numResults": 5,
    }
    headers = {
        "accept": "application/json",
        "content-type": "application/json",
        "x-api-key": EXA_API_KEY
    }
    response = requests.post(url, json=payload, headers=headers)
    response_json = response.json()
    results = response_json['results']
    # print(f'results {results}')
    return results

If a user clicks the Generate competitors report button, a spinner is displayed and the find_competitors function is called on the user input idea. We loop through the output generated by Exa, parsing it for company title, URL, and a snippet about the related company from the web. This is added to an array competitors.

if st.button('Generate competitors report👩🏻‍🏫'):
    # exa semantic search,
    with st.spinner('Processing📈...'):
        startup_research = find_competitors(idea)
        competitors = []
        
        for competitor in startup_research:
            url = competitor['url']
            title = competitor['title']
            summary = competitor['snippet']  # company created on: {dateCreated}
            competitors.append(f'{title}: {url}. - Summary: {summary}\n\n')

Pass Data to Anthropic to Generate Report

Craft a prompt to pass to Anthropic's Claude 2.1 model.

“HUMAN_PROMPT” and “AI_PROMPT” are strings to craft the correct prompt structure for the generation pipeline. They surround the "PROMPT" which includes the data generated by Exa–that's RAG by Exa!

We call Anthropic's completions API, passing it all the prompts.

PROMPT= f"Summarize the following external data into multiple paragraphs going over the pros for each company, what makes them different or special, and including their website according to the external data: {competitors}"
        anthropic = Anthropic(
            api_key=ANTHROPIC_API_KEY
        )
        completion = anthropic.completions.create(
            model="claude-2.1",
            max_tokens_to_sample=700,
            prompt=f"{HUMAN_PROMPT}: {PROMPT}. {AI_PROMPT}",
        )
        print(completion.completion)
        report = completion.completion

Combine the introduction, report, and conclusion, and then send it as an email with Twilio SendGrid in Python!

If the email is sent, a message is shown in the Streamliti web app telling the user to check their email for the report. Otherwise, an error message is displayed.

report = f'{intro} \n{report}\n {conclusion}'
    print(f'report printed {report}')
    message = Mail(
            from_email='existing_ideas@ai.com',
            to_emails=user_email,
            subject='Your competition report🔥',
            html_content=f'{report}'
        )
    sg = SendGridAPIClient(api_key=SENDGRID_API_KEY)
    response = sg.send(message)
    print(response.status_code, response.body, response.headers)
    if response.status_code == 202:
        st.success("Email sent! Check your email for your personal competitors report")
        print(f"Response Code: {response.status_code} \n Message sent!")
    else:
        st.warning("Email not sent--check console")

Lastly, add a footer to the webapp that also links to the GitHub repo.

footer="""<style>
a:link , a:visited{
color: blue;
background-color: transparent;
text-decoration: underline;
}
a:hover,  a:active {
color: red;
background-color: transparent;
text-decoration: underline;
}
footer {
  margin-top: auto;
  text-align: center;
}
</style>
<footer>
<p>Developed with ❤ in SF🌁</p> 
<p>✅ out the code on <a href="https://github.com/elizabethsiegle/agihouse-rag-finetune-hackathon/tree/blog" target="_blank">GitHub</a></p>
</footer>
"""
st.markdown(footer,unsafe_allow_html=True)

The complete code can be found here on GitHub !

What's Next for AI-generated Content with Twilio SendGrid?

Email is the perfect medium for long-form AI-generated content. You can do so much more with Anthropic, Exa, and Twilio SendGrid, like searching the web and summarizing relevant web pages, news articles, research papers, and more.

Developers can use Exa to perform Retrieval Augmented Generation (RAG) and then question-answering (QA) on podcasts, lectures, interviews, and so many other web pages and articles. I can't wait to see what you build–let me know online what you're working on with AI!

Let me know online what you're building!