logo
Menu
How to make AI News Summary Subscription Service

How to make AI News Summary Subscription Service

Provides customized news to customers by summarizing the news using the antique model.

Hyunjoong Shin
Amazon Employee
Published May 13, 2024

Purpose of development of AI News Summary Subscription Service

So much news is being generated in real time. Users want to receive news that they are interested in quickly and only important information. Therefore, to address this, users click on the categories they want to subscribe to directly and receive newsletters summarized in AI for related news.

Architecture Description

Image preview
1. In Streamlit, insert User Data, include email, category
2. Set up the Cron expression on EventBridge to run Lambda at a specific time.
3. When a certain time is triggered, DynamoDB gets information about users.
4. Use Bedrock to summarize the news information received from the external API.
5. We select and send only news that fits the category selected by the customer.

Prerequisites

- The AWS CLI must be credentialed (in the current example, use AdministratorAccess permissions)
- You must create a table in DynamoDB with Email as the key value.
- The IAM role used for AWS lambda must include DynamoDB Full Access, Bedrock Full Access, and SES Full Access.
- Email entering DynamoDB must be SES credentialed.

Step1. Setting Front

- You can put your email address and category in the form below.
- Install Streamlit from Python IDE to use Streamlit.
1
pip install streamlit
- Create a file called NewsFront.py from Python IDE and enter the code below.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import streamlit as st

with st.form(key='my_form'):
email = st.text_input('Enter your email')
options = st.multiselect("Choos an option",('IT','Social','Sports'),default=[])
submit_button = st.form_submit_button(label='Submit')

if submit_button:
if len(options)>0:
if not check_member(email):
add_member(email,options)
st.success("Your email has been registered successfuly.")
else:
st.error("Your email is already registered")
else:
st.error("Please input the option")
- Install the following and bot3 to put the email address in DynamoDB and enter the code below
1
pip install boto3
- Code to put your email address and options on the table. Please enter your own table. (NewsFront.py)
- Add a code that checks for duplication before inserting an email.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import boto3

dynamodb = boto3.resource('dynamodb')
table_name = '<TableName>'
table = dynamodb.Table(table_name)

def add_member(email, options):
table.put_item(
Item={
'email': email,
'options': options
}
)

def check_member(email):
response = table.get_item(
Key={
'email': email
}
)
try:
response.get('Item')['email']
return True
except:
return False

Step2. Setting Backend

- Generates the function from AWS Lambda function to the latest version of Python.
- In this case, the Lambda function must be created by attaching the IAM Role mentioned in the prerequisite. (DynamoDBFullAccess, BedrockFullAccess,SESFullAccess)
- After the AWS Lambda function is generated, modify the code as below: (Lambda function: Send_news)
- A code that receives the input of the prompt and outputs the result using clade-v2.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
def get_anthropic_result(prompt):
bedrock = boto3.client(service_name='bedrock-runtime',region_name="us-east-1")

body = json.dumps({
"prompt": "\n\nHuman:{} \n\nAssistant:".format(prompt),
"max_tokens_to_sample": 500,
"temperature": 0.3,
"top_p": 0.9,
})

modelId = 'anthropic.claude-v2'
accept = 'application/json'
contentType = 'application/json'

response = bedrock.invoke_model(body=body, modelId=modelId, accept=accept, contentType=contentType)
response_body = json.loads(response.get('body').read())

print(response_body)
completion = response_body.get('completion')
news_json=json.loads(completion)
return news_json
- Code that format documents to send to users in html format.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
def create_html(news_title,news_link,news_json,option_list):
news_json = news_json
news_list = [news_json["it_news"], news_json["social_news"], news_json["sports_news"]]
html_output = "<html> <body><ul>"
for option in option_list:
if option=="IT":
html_output +="<h1>{}</h1>".format(news_title[0])
html_output +="<h2>IT News </h2>"
html_output += "<p>{}</p>".format(news_list[0])
html_output +="<a href={}>{}</a>".format(news_link[0],news_link[0])
elif option=="Social":
html_output +="<h1>{}</h1>".format(news_title[1])
html_output +="<h2>Social News </h2>"
html_output += "<p>{}</p>".format(news_list[1])
html_output +="<a href={}>{}</a>".format(news_link[1],news_link[1])
elif option=="Sports":
html_output +="<h1>{}</h1>".format(news_title[2])
html_output +="<h2>Sports News </h2>"
html_output += "<li>{}</li>".format(news_list[2])
html_output +="<h3>{}</h3>".format(news_link[2])
html_output += "</ul></body></html>"
return html_output
- Code that uses AWS SES to send an email to an account with SES credentials.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
def send_email(sender,receiver,news):
client_ses = boto3.client('ses')
temp_time=datetime.now()
now_time=temp_time.strftime('%Y-%m-%d')
response = client_ses.send_email(
Destination={
'ToAddresses': [receiver]
},
Message={
'Body': {
'Text': {
'Charset': 'UTF-8',
'Data': news,
}
},
'Subject': {
'Charset': 'UTF-8',
'Data': 'Today custom news ( Timeline: {} )'.format(now_time),
},
},
Source=sender
)
- Code that returns users' information (emails, categories) stored in DynamoDB.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
def get_user_information():
dynamodb = boto3.client('dynamodb')
table_name = 'user'

data=dynamodb.scan(TableName=table_name)
emails,options_lists = [],[]

for item in data["Items"]:
email = item["email"]["S"]
emails.append(email)
options_list = [option["S"] for option in item["options"]["L"]]
options_lists.append(options_list)

return emails,options_lists
- In the get_news function, data must be retrieved using the news API.
(Note: There is no news API service provided by Amazon, so this part needs to be set up personally.)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
def lambda_handler(event, context):
# Get the title and link of the news through the api that fetches news.
# The part that calls api will be omitted to use 3rd party, let's say get_news(category) as an example.
it_news =get_news(category="it")
social_news = get_news(category="social")
sports_news = get_news(category="sports")

it_news=[it_news['title'],it_news['originallink']]
social_news=[social_news['title'],social_news['originallink']]
sports_news=[sports_news['title'],sports_news['originallink']]

news_title=[it_news[0],social_news[0],sports_news[0]]
news_link=[it_news[1],social_news[1],sports_news[1]]

prompt="Summarize each article in the 3 links below in 500 characters and print out only JSON as below " \
"Article1:{} Article2:{} Article13 : {}".format(it_news[1],social_news[1],sports_news[1])+\
"Example:{ { it_news : Summerize1 social_news : Summerize2 sports_news : Summerize3} "
news_json=get_anthropic_result(prompt)

sender="<SenderEmail>"
email_list,options_list=get_user_information()

for i in range(len(email_list)):
news_html=create_html(news_title,news_link,news_json,options_list[i])
send_email(sender, email_list[i], news_html)

Step3. To set up a trigger

- Set the trigger using the cron expression.
- In the current example, the trigger is set to occur starting at 12:00 p.m. every day.

Step4. Test

- At a certain time, the news for the category selected by the user is summarized and emailed.

 

Any opinions in this post are those of the individual author and may not reflect the opinions of AWS.

Comments