Skip to content

Commit 3ebda33

Browse files
authored
Update aws.md
1 parent 6af29ed commit 3ebda33

File tree

1 file changed

+178
-2
lines changed

1 file changed

+178
-2
lines changed

ai/aws.md

Lines changed: 178 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,16 @@
44

55
[ai index src](https://github.com/robfatland/nexus/blob/gh-pages/ai/index.md)
66

7+
# Content sections
78

8-
# AI on the Amazon Web Services cloud platform
9+
10+
- AI on AWS pointers
11+
- EC2 working environment build with Q Developer on VS Code Server
12+
- Example Python Streamlit AI playground application
13+
14+
15+
16+
## AI on AWS pointers
917

1018
- [Instructions](https://catalog.workshops.aws/building-agentic-workflows/en-US/bedrock-api)
1119
- Log in to an active account
@@ -21,7 +29,7 @@ a VS Code Server instance on an AWS EC2 instance with Q Developer enabled and a
2129
and bells.
2230

2331

24-
## Build a working environment on EC2 including Q Developer access
32+
## EC2 working environment build with Q Developer on VS Code Server
2533

2634

2735
- EC2: Ubuntu Server latest; say c5.xlarge; keypair; new security group
@@ -173,7 +181,175 @@ G.add_edge('A', 'B')
173181
print(f"NetworkX working: {list(G.edges())}")
174182
```
175183

184+
## Example Python Streamlit AI playground application
185+
186+
187+
```
188+
import io
189+
import json
190+
191+
import boto3
192+
import streamlit as st
193+
from PIL import Image
194+
from transformers import GPT2LMHeadModel, GPT2Tokenizer, DistilBertTokenizer, DistilBertForSequenceClassification
195+
import torch
196+
197+
st.title("Building with Bedrock") # Title of the application
198+
st.subheader("Model Playground")
199+
200+
# Turn base64 string to image with PIL
201+
def base64_to_pil(base64_string):
202+
"""
203+
Purpose:
204+
Turn base64 string to image with PIL
205+
Args/Requests:
206+
base64_string: base64 string of image
207+
Return:
208+
image: PIL image
209+
"""
210+
import base64
211+
212+
imgdata = base64.b64decode(base64_string)
213+
image = Image.open(io.BytesIO(imgdata))
214+
return image
215+
216+
217+
bedrock_runtime = boto3.client(
218+
service_name="bedrock-runtime",
219+
region_name="us-west-2",
220+
)
221+
222+
223+
# Bedrock api call to stable diffusion
224+
def generate_image_sd(text):
225+
"""
226+
Purpose:
227+
Uses Bedrock API to generate an Image
228+
Args/Requests:
229+
text: Prompt
230+
Return:
231+
image: base64 string of image
232+
"""
233+
body = {
234+
"prompt": text,
235+
"output_format": "jpeg",
236+
"seed": 0,
237+
}
238+
239+
body = json.dumps(body)
240+
241+
modelId = "stability.stable-image-core-v1:1"
242+
243+
response = bedrock_runtime.invoke_model(
244+
body=body,
245+
modelId=modelId
246+
)
247+
response_body = json.loads(response["body"].read().decode("utf-8"))
248+
249+
results = response_body["images"][0]
250+
return results
251+
252+
def call_nova(
253+
system_prompt: str,
254+
prompt: str,
255+
model_id: str = "us.amazon.nova-pro-v1:0",
256+
):
257+
prompt_config = {
258+
"system": [
259+
{"text": system_prompt}
260+
],
261+
"messages": [
262+
{
263+
"role": "user",
264+
"content": [
265+
{"text": prompt},
266+
],
267+
}
268+
],
269+
}
270+
body = json.dumps(prompt_config)
271+
272+
modelId = model_id
273+
accept = "application/json"
274+
contentType = "application/json"
275+
276+
response = bedrock_runtime.invoke_model(
277+
body=body, modelId=modelId, accept=accept, contentType=contentType
278+
)
279+
response_body = json.loads(response.get("body").read())
280+
281+
results = response_body["output"]["message"]["content"][0].get("text")
282+
return results
283+
284+
@st.cache_resource
285+
def load_gpt2():
286+
tokenizer = GPT2Tokenizer.from_pretrained("gpt2")
287+
model = GPT2LMHeadModel.from_pretrained("gpt2")
288+
tokenizer.pad_token = tokenizer.eos_token
289+
return tokenizer, model
290+
291+
def generate_gpt2_text(prompt, max_length=100):
292+
tokenizer, model = load_gpt2()
293+
inputs = tokenizer.encode(prompt, return_tensors="pt")
294+
with torch.no_grad():
295+
outputs = model.generate(inputs, max_length=max_length, num_return_sequences=1, pad_token_id=tokenizer.eos_token_id)
296+
return tokenizer.decode(outputs[0], skip_special_tokens=True)
297+
298+
@st.cache_resource
299+
def load_distilbert():
300+
tokenizer = DistilBertTokenizer.from_pretrained("distilbert-base-uncased-finetuned-sst-2-english")
301+
model = DistilBertForSequenceClassification.from_pretrained("distilbert-base-uncased-finetuned-sst-2-english")
302+
return tokenizer, model
303+
304+
def classify_sentiment(text):
305+
tokenizer, model = load_distilbert()
306+
inputs = tokenizer(text, return_tensors="pt", truncation=True, padding=True)
307+
with torch.no_grad():
308+
outputs = model(**inputs)
309+
predictions = torch.nn.functional.softmax(outputs.logits, dim=-1)
310+
labels = ["NEGATIVE", "POSITIVE"]
311+
return f"{labels[predictions.argmax().item()]}: {predictions.max().item():.3f}"
312+
313+
models = ["Stable Image Core", "Amazon Nova Pro", "GPT2", "DistilBERT"]
314+
315+
current_model = st.selectbox("Select Model", models)
316+
317+
318+
if current_model == "Stable Image Core":
319+
# text input
320+
prompt = st.text_area("Enter prompt")
321+
322+
# Generate image from prompt,
323+
if st.button("Generate Image"):
324+
base64_image = generate_image_sd(prompt)
325+
image = base64_to_pil(base64_image)
326+
st.image(image)
327+
328+
if current_model == "Amazon Nova Pro":
329+
system_prompt = st.text_area("Enter system prompt")
330+
prompt = st.text_area("Enter prompt")
331+
332+
# Generate text from prompt,
333+
if st.button("Call Nova"):
334+
generated_text = call_nova(system_prompt, prompt, "us.amazon.nova-pro-v1:0")
335+
st.markdown(generated_text)
336+
337+
if current_model == "GPT2":
338+
prompt = st.text_area("Enter prompt for GPT2")
339+
max_length = st.slider("Max length", 50, 200, 100)
340+
341+
if st.button("Generate Text"):
342+
generated_text = generate_gpt2_text(prompt, max_length)
343+
st.markdown(generated_text)
344+
345+
if current_model == "DistilBERT":
346+
text = st.text_area("Enter text for sentiment analysis")
347+
348+
if st.button("Analyze Sentiment"):
349+
sentiment = classify_sentiment(text)
350+
st.markdown(f"**Sentiment:** {sentiment}")
176351
352+
```
177353

178354

179355

0 commit comments

Comments
 (0)