chore: import upstream snapshot with attribution
Code Quality / Python Lint & Format (push) Has been cancelled
Code Quality / Python Tests (push) Has been cancelled
Code Quality / JavaScript/TypeScript Lint (advisory) (push) Has been cancelled
Security Scan / CodeQL Analysis (python) (push) Has been cancelled
Security Scan / Dependency Review (push) Has been cancelled
Security Scan / CodeQL Analysis (javascript-typescript) (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 13:43:57 +08:00
commit 3fbbd7970c
12165 changed files with 1331979 additions and 0 deletions
@@ -0,0 +1,86 @@
from openai import OpenAI
import os
import re
from dotenv import load_dotenv
# load environment variables from .env file
load_dotenv()
# SECURITY: Validate environment variables with helpful error messages
def get_required_env(var_name: str) -> str:
"""Get a required environment variable or raise an error with helpful message."""
value = os.getenv(var_name)
if not value:
raise ValueError(f"Missing required environment variable: {var_name}. Please set it in your .env file.")
return value
# SECURITY: Input validation functions
def validate_number_input(value: str, min_val: int = 1, max_val: int = 20) -> int:
"""Validate and sanitize numeric input."""
try:
num = int(value)
if num < min_val or num > max_val:
raise ValueError(f"Number must be between {min_val} and {max_val}")
return num
except ValueError:
raise ValueError(f"Please enter a valid number between {min_val} and {max_val}")
def validate_text_input(value: str, max_length: int = 500) -> str:
"""Validate and sanitize text input to prevent prompt injection."""
if len(value) > max_length:
raise ValueError(f"Input too long. Maximum {max_length} characters allowed.")
# Remove potentially dangerous characters/patterns
sanitized = re.sub(r'[<>{}[\]|\\`]', '', value)
# Limit to alphanumeric, spaces, commas, and basic punctuation
if not re.match(r'^[\w\s,.\'-]+$', sanitized, re.UNICODE):
raise ValueError("Input contains invalid characters")
return sanitized.strip()
# configure the OpenAI client against the Azure OpenAI (Microsoft Foundry) v1 endpoint
client = OpenAI(
api_key=get_required_env('AZURE_OPENAI_API_KEY'),
base_url=f"{get_required_env('AZURE_OPENAI_ENDPOINT').rstrip('/')}/openai/v1/",
)
deployment = get_required_env('AZURE_OPENAI_DEPLOYMENT')
# SECURITY: Validate all user inputs
try:
no_recipes_input = input("No of recipes (for example, 5): ")
no_recipes = validate_number_input(no_recipes_input, 1, 20)
ingredients_input = input("List of ingredients (for example, chicken, potatoes, and carrots): ")
ingredients = validate_text_input(ingredients_input, 500)
filter_input = input("Filter (for example, vegetarian, vegan, or gluten-free): ")
filter_value = validate_text_input(filter_input, 100) if filter_input.strip() else "none"
except ValueError as e:
print(f"Input validation error: {e}")
exit(1)
# interpolate the number of recipes into the prompt and ingredients
# Note: Using validated and sanitized inputs
prompt = f"Show me {no_recipes} recipes for a dish with the following ingredients: {ingredients}. Per recipe, list all the ingredients used, no {filter_value}: "
response = client.responses.create(model=deployment, input=prompt, max_output_tokens=600, temperature=0.1, store=False)
# print response
print("Recipes:")
old_prompt_result = response.output_text
if not old_prompt_result:
print("No response received.")
else:
print(old_prompt_result)
prompt_shopping = "Produce a shopping list, and please don't include ingredients that I already have at home: "
new_prompt = f"Given ingredients at home {ingredients} and these generated recipes: {old_prompt_result}, {prompt_shopping}"
response = client.responses.create(model=deployment, input=new_prompt, max_output_tokens=600, temperature=0, store=False)
# print response
print("\n=====Shopping list ======= \n")
if response.output_text:
print(response.output_text)
else:
print("No response received.")
@@ -0,0 +1,27 @@
# pylint: disable=all
from openai import OpenAI
import os
from dotenv import load_dotenv
# load environment variables from .env file
load_dotenv()
# configure the OpenAI client against the Azure OpenAI (Microsoft Foundry) v1 endpoint
client = OpenAI(
api_key=os.environ['AZURE_OPENAI_API_KEY'],
base_url=f"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/",
)
deployment=os.environ['AZURE_OPENAI_DEPLOYMENT']
# add your completion code
prompt = "Complete the following: Once upon a time there was a"
# make a request using the Responses API
response = client.responses.create(model=deployment, input=prompt, store=False)
# print response
print(response.output_text)
# very unhappy _____.
# Once upon a time there was a very unhappy mermaid.
@@ -0,0 +1,760 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Build text generation apps\n",
"\n",
"You've seen so far through this curriculum that there are core concepts like prompts and even a whole discipline called \"prompt engineering\". Many tools you can interact with like ChatGPT, Office 365, Microsoft Power Platform and more, support you using prompts to accomplish something.\n",
"\n",
"For you to add such an experience to an app, you need to understand concepts like prompts, completions and choose a library to work with. That's exactly what you'll learn in this chapter.\n",
"\n",
"## Introduction\n",
"\n",
"In this chapter, you will:\n",
"\n",
"- Learn about the openai library and its core concepts.\n",
"- Build a text generation app using openai.\n",
"- Understand how to use concepts like prompt, temperature, and tokens to build a text generation app.\n",
"\n",
"## Learning goals\n",
"\n",
"At the end of this lesson, you'll be able to:\n",
"\n",
"- Explain what a text generation app is.\n",
"- Build a text generation app using openai.\n",
"- Configure your app to use more or less tokens and also change the temperature, for a varied output.\n",
"\n",
"## What is a text generation app?\n",
"\n",
"Normally when you build an app it has some kind of interface like the following:\n",
"\n",
"- Command-based. Console apps are typical apps where you type a command and it carries out a task. For example, `git` is a command-based app.\n",
"- User interface (UI). Some apps have graphical user interfaces (GUIs) where you click buttons, input text, select options and more.\n",
"\n",
"### Console and UI apps are limited\n",
"\n",
"Compare it to a command-based app where you type a command: \n",
"\n",
"- **It's limited**. You can't just type any command, only the ones that the app supports.\n",
"- **Language specific**. Some apps support many languages, but by default the app is built for a specific language, even if you can add more language support. \n",
"\n",
"### Benefits of text generation apps\n",
"\n",
"So how is a text generation app different?\n",
"\n",
"In a text generation app, you have more flexibility, you're not limited to a set of commands or a specific input language. Instead, you can use natural language to interact with the app. Another benefit is that because you're already interacting with a data source that has been trained on a vast corpus of information, whereas a traditional app might be limited on what's in a database. \n",
"\n",
"### What can I build with a text generation app?\n",
"\n",
"There are many things you can build. For example:\n",
"\n",
"- **A chatbot**. A chatbot answering questions about topics, like your company and its products could be a good match.\n",
"- **Helper**. LLMs are great at things like summarizing text, getting insights from text, producing text like resumes and more.\n",
"- **Code assistant**. Depending on the language model you use, you can build a code assistant that helps you write code. For example, you can use a product like GitHub Copilot as well as ChatGPT to help you write code.\n",
"\n",
"## How can I get started?\n",
"\n",
"Well, you need to find a way to integrate with an LLM which usually entails the following two approaches:\n",
"\n",
"- Use an API. Here you're constructing web requests with your prompt and get generated text back.\n",
"- Use a library. Libraries help encapsulate the API calls and make them easier to use.\n",
"\n",
"## Libraries/SDKs\n",
"\n",
"There are a few well known libraries for working with LLMs like:\n",
"\n",
"- **openai**, this library makes it easy to connect to your model and send in prompts.\n",
"\n",
"Then there are libraries that operate on a higher level like:\n",
"\n",
"- **Langchain**. Langchain is well known and supports Python.\n",
"- **Semantic Kernel**. Semantic Kernel is a library by Microsoft supporting the languages C#, Python, and Java.\n",
"\n",
"## First app using openai\n",
"\n",
"Let's see how we can build our first app, what libraries we need, how much is required and so on.\n",
"\n",
"### Install openai\n",
"\n",
" > [!NOTE] This step is not necessary if run this notebook on Codespaces or within a Devcontainer\n",
"\n",
"\n",
"There are many libraries out there for interacting with OpenAI or Azure OpenAI. It's possible to use numerous programming languages as well like C#, Python, JavaScript, Java and more. \n",
"We've chosen to use the `openai` Python library, so we'll use `pip` to install it.\n",
"\n",
"```bash\n",
"pip install openai\n",
"```\n",
"\n",
"If you aren't running this notebook in a Codespaces or a Dev Container, you also need to install [Python](https://www.python.org/) on your machine.\n",
"\n",
"### Create a resource\n",
"\n",
"In case you didn't already, you need to carry out the following steps:\n",
"\n",
"- Create an account on Azure <https://azure.microsoft.com/free/>.\n",
"- Create an Azure OpenAI resource in [Microsoft Foundry](https://ai.azure.com?WT.mc_id=academic-105485-koreyst). See this guide for how to [create a resource](https://learn.microsoft.com/azure/ai-services/openai/how-to/create-resource?pivots=web-portal&WT.mc_id=academic-105485-koreyst).\n",
"\n",
"\n",
"### Locate API key and endpoint\n",
"\n",
"At this point, you need to tell your `openai` library what API key to use. To find your API key, go to the \"Keys and Endpoint\" section of your Azure OpenAI resource and copy the \"Key 1\" value.\n",
"\n",
" ![Keys and Endpoint resource blade in Azure Portal](https://learn.microsoft.com/azure/ai-services/openai/media/quickstarts/endpoint.png?WT.mc_id=academic-105485-koreyst)\n",
"\n",
"Now that you have this information copied, let's instruct the libraries to use it.\n",
"\n",
"> [!NOTE]\n",
"> It's worth separating your API key from your code. You can do so by using environment variables.\n",
"> - Set the environment variable `AZURE_OPENAI_API_KEY` to your API key in your .env file. If you already completed the previous exercises of this course, you are all set up.\n",
"\n",
"\n",
"### Setup configuration Azure\n",
"\n",
"If you're using Azure OpenAI, here's how you set up configuration. The Responses API is served from the Azure OpenAI **v1 endpoint**, so we point the `OpenAI` client at `<your-endpoint>/openai/v1/`:\n",
"\n",
"```python\n",
"client = OpenAI(\n",
" api_key=os.environ['AZURE_OPENAI_API_KEY'],\n",
" base_url=f\"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/\",\n",
" )\n",
"\n",
"deployment = os.environ['AZURE_OPENAI_DEPLOYMENT']\n",
"```\n",
"\n",
"Above we're setting the following:\n",
"\n",
"- `api_key`, this is your API key found in the Azure Portal.\n",
"- `base_url`, this is your Azure OpenAI endpoint with `/openai/v1/` appended. You can find the endpoint in the Azure Portal next to your API key. Using the v1 endpoint means you no longer need to pass an `api_version`.\n",
"- `deployment`, this is the name of the model deployment you created in the Foundry portal.\n",
"\n",
"> [!NOTE]\n",
"> `os.environ` is a mapping that reads environment variables. You can use it to read environment variables like `AZURE_OPENAI_API_KEY` and `AZURE_OPENAI_ENDPOINT`.\n",
"\n",
"## Generate text\n",
"\n",
"The way to generate text is to use the `responses.create` method. Here's an example:\n",
"\n",
"```python\n",
"prompt = \"Complete the following: Once upon a time there was a\"\n",
"\n",
"response = client.responses.create(model=deployment, input=prompt, store=False)\n",
"print(response.output_text)\n",
"```\n",
"\n",
"In the above code, we create a response object and pass in the model we want to use and the prompt. Then we print the generated text.\n",
"\n",
"### Chat responses\n",
"\n",
"The Responses API is well suited for both single-turn text generation and multi-turn chatbots - you simply provide more messages in the `input` list to build up a conversation:\n",
"\n",
"```python\n",
"client = OpenAI(\n",
" api_key=os.environ['AZURE_OPENAI_API_KEY'],\n",
" base_url=f\"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/\",\n",
" )\n",
"\n",
"deployment = os.environ['AZURE_OPENAI_DEPLOYMENT']\n",
"\n",
"response = client.responses.create(model=deployment, input=[{\"role\": \"user\", \"content\": \"Hello world\"}], store=False)\n",
"print(response.output_text)\n",
"```\n",
"\n",
"More on this functionality in a coming chapter.\n",
"\n",
"## Exercise - your first text generation app\n",
"\n",
"Now that we learned how to set up and configure Azure OpenAI service, it's time to build your first text generation app. To build your app, follow these steps:\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"1. Create a virtual environment and install openai:\n",
"\n",
" > [!NOTE] This step is not necessary if you run this notebook on Codespaces or within a Devcontainer"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Create virtual environment\n",
"! python -m venv venv\n",
"# Activate virtual environment\n",
"! source venv/bin/activate\n",
"# Install openai package\n",
"! pip install openai"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"> [!NOTE]\n",
"> If you're using Windows type `venv\\Scripts\\activate` instead of `source venv/bin/activate`. \n",
"\n",
"> [!NOTE]\n",
"> Locate your Azure OpenAI key by going to https://portal.azure.com/ and search for `Open AI` and select the `Open AI resource` and then select `Keys and Endpoint` and copy the `Key 1` value."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"1. Create a *app.py* file and give it the following code:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"from openai import OpenAI\n",
"from dotenv import load_dotenv\n",
"load_dotenv()\n",
"\n",
"client = OpenAI(\n",
" api_key=os.environ['AZURE_OPENAI_API_KEY'],\n",
" base_url=f\"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/\",\n",
" )\n",
"\n",
"deployment=os.environ['AZURE_OPENAI_DEPLOYMENT']\n",
"\n",
"# add your completion code\n",
"prompt = \"Complete the following: Once upon a time there was a\"\n",
"\n",
"# make a request using the Responses API\n",
"response = client.responses.create(model=deployment, input=prompt, store=False)\n",
"\n",
"# print response\n",
"print(response.output_text)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
" You should see an output like the following:\n",
"\n",
" ```output\n",
" very unhappy _____.\n",
"\n",
" Once upon a time there was a very unhappy mermaid.\n",
" ```"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Different types of prompts, for different things\n",
"\n",
"Now you've seen how to generate text using a prompt. You even have a program up and running that you can modify and change to generate different types of text. \n",
"\n",
"Prompts can be used for all sorts of tasks. For example:\n",
"\n",
"- **Generate a type of text**. For example, you can generate a poem, questions for a quiz etc.\n",
"- **Lookup information**. You can use prompts to look for information like the following example 'What does CORS mean in web development?'.\n",
"- **Generate code**. You can use prompts to generate code, for example developing a regular expression used to validate emails or why not generate an entire program, like a web app? \n",
"\n",
"## A more practical use case: a recipe generator\n",
"\n",
"Imagine you have ingredients at home and you want to cook something. For that, you need a recipe. A way to find recipes is to use a search engine or you could use an LLM to do so.\n",
"\n",
"You could write a prompt like so:\n",
"\n",
"> \"Show me 5 recipes for a dish with the following ingredients: chicken, potatoes, and carrots. Per recipe, list all the ingredients used\"\n",
"\n",
"Given the above prompt, you might get a response similar to:\n",
"\n",
"```output\n",
"1. Roasted Chicken and Vegetables: \n",
"Ingredients: \n",
"- 4 chicken thighs\n",
"- 2 potatoes, cut into cubes\n",
"- 2 carrots, cut into cubes\n",
"- 2 tablespoons olive oil\n",
"- 2 cloves garlic, minced\n",
"- 1 teaspoon dried thyme\n",
"- 1 teaspoon dried oregano\n",
"- Salt and pepper, to taste\n",
"\n",
"2. Chicken and Potato Stew: \n",
"Ingredients: \n",
"- 2 tablespoons olive oil\n",
"- 1 onion, diced\n",
"- 2 cloves garlic, minced\n",
"- 2 chicken breasts, cut into cubes\n",
"- 2 potatoes, cut into cubes\n",
"- 2 carrots, cut into cubes\n",
"- 1 teaspoon dried oregano\n",
"- 1 teaspoon dried thyme\n",
"- 1 cup chicken broth\n",
"- Salt and pepper, to taste\n",
"\n",
"3. Chicken and Potato Bake: \n",
"Ingredients: \n",
"- 2 tablespoons olive oil\n",
"- 2 chicken breasts, cut into cubes\n",
"- 2 potatoes, cut into cubes\n",
"- 2 carrots, cut into cubes\n",
"- 1 onion, diced\n",
"- 2 cloves garlic, minced\n",
"- 1 teaspoon dried oregano\n",
"- 1 teaspoon dried thyme\n",
"- 1 cup chicken broth\n",
"- Salt and pepper, to taste\n",
"\n",
"4. Chicken and Potato Soup: \n",
"Ingredients: \n",
"- 2 tablespoons olive oil\n",
"- 1 onion, diced\n",
"- 2 cloves garlic, minced\n",
"- 2 chicken breasts, cut into cubes\n",
"- 2 potatoes, cut into cubes\n",
"- 2 carrots, cut into cubes\n",
"- 1 teaspoon dried oregano\n",
"- 1 teaspoon dried thyme\n",
"- 4 cups chicken broth\n",
"- Salt and pepper, to taste\n",
"\n",
"5. Chicken and Potato Hash: \n",
"Ingredients: \n",
"- 2 tablespoons olive oil\n",
"- 2 chicken breasts, cut into cubes\n",
"- 2 potatoes, cut into cubes\n",
"- 2 carrots, cut into cubes\n",
"- 1 onion, diced\n",
"- 2 cloves garlic, minced\n",
"- 1 teaspoon dried oregano\n",
"```\n",
"\n",
"This outcome is great, I know what to cook. At this point, what could be useful improvements are:\n",
"\n",
"- Filtering out ingredients I don't like or am allergic to.\n",
"- Produce a shopping list, in case I don't have all the ingredients at home.\n",
"\n",
"For the above cases, let's add an additional prompt:\n",
"\n",
"> \"Please remove recipes with garlic as I'm allergic and replace it with something else. Also, please produce a shopping list for the recipes, considering I already have chicken, potatoes and carrots at home.\"\n",
"\n",
"Now you have a new result, namely:\n",
"\n",
"```output\n",
"1. Roasted Chicken and Vegetables: \n",
"Ingredients: \n",
"- 4 chicken thighs\n",
"- 2 potatoes, cut into cubes\n",
"- 2 carrots, cut into cubes\n",
"- 2 tablespoons olive oil\n",
"- 1 teaspoon dried thyme\n",
"- 1 teaspoon dried oregano\n",
"- Salt and pepper, to taste\n",
"\n",
"2. Chicken and Potato Stew: \n",
"Ingredients: \n",
"- 2 tablespoons olive oil\n",
"- 1 onion, diced\n",
"- 2 chicken breasts, cut into cubes\n",
"- 2 potatoes, cut into cubes\n",
"- 2 carrots, cut into cubes\n",
"- 1 teaspoon dried oregano\n",
"- 1 teaspoon dried thyme\n",
"- 1 cup chicken broth\n",
"- Salt and pepper, to taste\n",
"\n",
"3. Chicken and Potato Bake: \n",
"Ingredients: \n",
"- 2 tablespoons olive oil\n",
"- 2 chicken breasts, cut into cubes\n",
"- 2 potatoes, cut into cubes\n",
"- 2 carrots, cut into cubes\n",
"- 1 onion, diced\n",
"- 1 teaspoon dried oregano\n",
"- 1 teaspoon dried thyme\n",
"- 1 cup chicken broth\n",
"- Salt and pepper, to taste\n",
"\n",
"4. Chicken and Potato Soup: \n",
"Ingredients: \n",
"- 2 tablespoons olive oil\n",
"- 1 onion, diced\n",
"- 2 chicken breasts, cut into cubes\n",
"- 2 potatoes, cut into cubes\n",
"- 2 carrots, cut into cubes\n",
"- 1 teaspoon dried oregano\n",
"- 1 teaspoon dried thyme\n",
"- 4 cups chicken broth\n",
"- Salt and pepper, to taste\n",
"\n",
"5. Chicken and Potato Hash: \n",
"Ingredients: \n",
"- 2 tablespoons olive oil\n",
"- 2 chicken breasts, cut into cubes\n",
"- 2 potatoes, cut into cubes\n",
"- 2 carrots, cut into cubes\n",
"- 1 onion, diced\n",
"- 1 teaspoon dried oregano\n",
"\n",
"Shopping List: \n",
"- Olive oil\n",
"- Onion\n",
"- Thyme\n",
"- Oregano\n",
"- Salt\n",
"- Pepper\n",
"```\n",
"\n",
"That's your five recipes, with no garlic mentioned and you also have a shopping list considering what you already have at home. "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Exercise - build a recipe generator\n",
"\n",
"Now that we have played out a scenario, let's write code to match the demonstrated scenario. To do so, follow these steps:\n",
"\n",
"1. Use the existing *app.py* file as a starting point\n",
"1. Locate the `prompt` variable and change its code to the following:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"from openai import OpenAI\n",
"from dotenv import load_dotenv\n",
"\n",
"# load environment variables from .env file\n",
"load_dotenv()\n",
"\n",
"client = OpenAI(\n",
" api_key=os.environ['AZURE_OPENAI_API_KEY'],\n",
" base_url=f\"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/\",\n",
" )\n",
"\n",
"deployment = os.environ['AZURE_OPENAI_DEPLOYMENT']\n",
"\n",
"prompt = \"Show me 5 recipes for a dish with the following ingredients: chicken, potatoes, and carrots. Per recipe, list all the ingredients used\"\n",
"\n",
"# make a request using the Responses API\n",
"response = client.responses.create(model=deployment, input=prompt, max_output_tokens=600, store=False)\n",
"\n",
"# print response\n",
"print(response.output_text)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"If you now run the code, you should see an output similar to:\n",
"\n",
"```output\n",
"-Chicken Stew with Potatoes and Carrots: 3 tablespoons oil, 1 onion, chopped, 2 cloves garlic, minced, 1 carrot, peeled and chopped, 1 potato, peeled and chopped, 1 bay leaf, 1 thyme sprig, 1/2 teaspoon salt, 1/4 teaspoon black pepper, 1 1/2 cups chicken broth, 1/2 cup dry white wine, 2 tablespoons chopped fresh parsley, 2 tablespoons unsalted butter, 1 1/2 pounds boneless, skinless chicken thighs, cut into 1-inch pieces\n",
"-Oven-Roasted Chicken with Potatoes and Carrots: 3 tablespoons extra-virgin olive oil, 1 tablespoon Dijon mustard, 1 tablespoon chopped fresh rosemary, 1 tablespoon chopped fresh thyme, 4 cloves garlic, minced, 1 1/2 pounds small red potatoes, quartered, 1 1/2 pounds carrots, quartered lengthwise, 1/2 teaspoon salt, 1/4 teaspoon black pepper, 1 (4-pound) whole chicken\n",
"-Chicken, Potato, and Carrot Casserole: cooking spray, 1 large onion, chopped, 2 cloves garlic, minced, 1 carrot, peeled and shredded, 1 potato, peeled and shredded, 1/2 teaspoon dried thyme leaves, 1/4 teaspoon salt, 1/4 teaspoon black pepper, 2 cups fat-free, low-sodium chicken broth, 1 cup frozen peas, 1/4 cup all-purpose flour, 1 cup 2% reduced-fat milk, 1/4 cup grated Parmesan cheese\n",
"\n",
"-One Pot Chicken and Potato Dinner: 2 tablespoons olive oil, 1 pound boneless, skinless chicken thighs, cut into 1-inch pieces, 1 large onion, chopped, 3 cloves garlic, minced, 1 carrot, peeled and chopped, 1 potato, peeled and chopped, 1 bay leaf, 1 thyme sprig, 1/2 teaspoon salt, 1/4 teaspoon black pepper, 2 cups chicken broth, 1/2 cup dry white wine\n",
"\n",
"-Chicken, Potato, and Carrot Curry: 1 tablespoon vegetable oil, 1 large onion, chopped, 2 cloves garlic, minced, 1 carrot, peeled and chopped, 1 potato, peeled and chopped, 1 teaspoon ground coriander, 1 teaspoon ground cumin, 1/2 teaspoon ground turmeric, 1/2 teaspoon ground ginger, 1/4 teaspoon cayenne pepper, 2 cups chicken broth, 1/2 cup dry white wine, 1 (15-ounce) can chickpeas, drained and rinsed, 1/2 cup raisins, 1/2 cup chopped fresh cilantro\n",
"```\n",
"\n",
"> NOTE, your LLM is nondeterministic, so you might get different results every time you run the program.\n",
"\n",
"Great, let's see how we can improve things. To improve things, we want to make sure the code is flexible, so ingredients and number of recipes can be improved and changed. "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"1. Let's change the code in the following way:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"from openai import OpenAI\n",
"from dotenv import load_dotenv\n",
"\n",
"# load environment variables from .env file\n",
"load_dotenv()\n",
"\n",
"client = OpenAI(\n",
" api_key=os.environ['AZURE_OPENAI_API_KEY'],\n",
" base_url=f\"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/\",\n",
" )\n",
"\n",
"deployment = os.environ['AZURE_OPENAI_DEPLOYMENT']\n",
"\n",
"no_recipes = input(\"No of recipes (for example, 5: \")\n",
"\n",
"ingredients = input(\"List of ingredients (for example, chicken, potatoes, and carrots: \")\n",
"\n",
"# interpolate the number of recipes into the prompt an ingredients\n",
"prompt = f\"Show me {no_recipes} recipes for a dish with the following ingredients: {ingredients}. Per recipe, list all the ingredients used\"\n",
"\n",
"# make a request using the Responses API\n",
"response = client.responses.create(model=deployment, input=prompt, max_output_tokens=600, store=False)\n",
"\n",
"# print response\n",
"print(response.output_text)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"-Strawberry shortcake: milk, flour, baking powder, sugar, salt, unsalted butter, strawberries, whipped cream \n",
"-Strawberry milk: milk, strawberries, sugar, vanilla extract\n",
"```\n",
"\n",
"### Improve by adding filter and shopping list\n",
"\n",
"We now have a working app capable of producing recipes and it's flexible as it relies on inputs from the user, both on the number of recipes but also the ingredients used.\n",
"\n",
"To further improve it, we want to add the following:\n",
"\n",
"- **Filter out ingredients**. We want to be able to filter out ingredients we don't like or are allergic to. To accomplish this change, we can edit our existing prompt and add a filter condition to the end of it like so:\n",
"\n",
" ```python\n",
" filter = input(\"Filter (for example, vegetarian, vegan, or gluten-free: \")\n",
"\n",
" prompt = f\"Show me {no_recipes} recipes for a dish with the following ingredients: {ingredients}. Per recipe, list all the ingredients used, no {filter}\"\n",
" ```\n",
"\n",
" Above, we add `{filter}` to the end of the prompt and we also capture the filter value from the user.\n",
"\n",
" An example input of running the program can now look like so:\n",
" \n",
" ```output \n",
" No of recipes (for example, 5: 3\n",
" List of ingredients (for example, chicken, potatoes, and carrots: onion,milk\n",
" Filter (for example, vegetarian, vegan, or gluten-free: no milk\n",
"\n",
" 1. French Onion Soup\n",
"\n",
" Ingredients:\n",
" \n",
" -1 large onion, sliced\n",
" -3 cups beef broth\n",
" -1 cup milk\n",
" -6 slices french bread\n",
" -1/4 cup shredded Parmesan cheese\n",
" -1 tablespoon butter\n",
" -1 teaspoon dried thyme\n",
" -1/4 teaspoon salt\n",
" -1/4 teaspoon black pepper\n",
" \n",
" Instructions:\n",
" \n",
" 1. In a large pot, sauté onions in butter until golden brown.\n",
" 2. Add beef broth, milk, thyme, salt, and pepper. Bring to a boil.\n",
" 3. Reduce heat and simmer for 10 minutes.\n",
" 4. Place french bread slices on soup bowls.\n",
" 5. Ladle soup over bread.\n",
" 6. Sprinkle with Parmesan cheese.\n",
" \n",
" 2. Onion and Potato Soup\n",
" \n",
" Ingredients:\n",
" \n",
" -1 large onion, chopped\n",
" -2 cups potatoes, diced\n",
" -3 cups vegetable broth\n",
" -1 cup milk\n",
" -1/4 teaspoon black pepper\n",
" \n",
" Instructions:\n",
" \n",
" 1. In a large pot, sauté onions in butter until golden brown.\n",
" 2. Add potatoes, vegetable broth, milk, and pepper. Bring to a boil.\n",
" 3. Reduce heat and simmer for 10 minutes.\n",
" 4. Serve hot.\n",
" \n",
" 3. Creamy Onion Soup\n",
" \n",
" Ingredients:\n",
" \n",
" -1 large onion, chopped\n",
" -3 cups vegetable broth\n",
" -1 cup milk\n",
" -1/4 teaspoon black pepper\n",
" -1/4 cup all-purpose flour\n",
" -1/2 cup shredded Parmesan cheese\n",
" \n",
" Instructions:\n",
" \n",
" 1. In a large pot, sauté onions in butter until golden brown.\n",
" 2. Add vegetable broth, milk, and pepper. Bring to a boil.\n",
" 3. Reduce heat and simmer for 10 minutes.\n",
" 4. In a small bowl, whisk together flour and Parmesan cheese until smooth.\n",
" 5. Add to soup and simmer for an additional 5 minutes, or until soup has thickened.\n",
" ```\n",
"\n",
" As you can see, any recipes with milk in it has been filtered out. But, if you're lactose intolerant, you might want to filter out recipes with cheese in them as well, so there's a need to be clear.\n",
"\n",
"- **Produce a shopping list**. We want to produce a shopping list, considering what we already have at home.\n",
"\n",
" For this functionality, we could either try to solve everything in one prompt or we could split it up into two prompts. Let's try the latter approach. Here we're suggesting adding an additional prompt, but for that to work, we need to add the result of the former prompt as context to the latter prompt. \n",
"\n",
" Locate the part in the code that prints out the result from the first prompt and add the following code below:\n",
" \n",
" ```python\n",
" old_prompt_result = response.output_text\n",
" prompt = \"Produce a shopping list for the generated recipes and please don't include ingredients that I already have.\"\n",
" \n",
" new_prompt = f\"{old_prompt_result} {prompt}\"\n",
" messages = [{\"role\": \"user\", \"content\": new_prompt}]\n",
" response = client.responses.create(model=deployment, input=messages, max_output_tokens=1200, store=False)\n",
" \n",
" # print response\n",
" print(\"Shopping list:\")\n",
" print(response.output_text)\n",
" ```\n",
"\n",
" Note the following:\n",
"\n",
" - We're constructing a new prompt by adding the result from the first prompt to the new prompt: \n",
" \n",
" ```python\n",
" new_prompt = f\"{old_prompt_result} {prompt}\"\n",
" messages = [{\"role\": \"user\", \"content\": new_prompt}]\n",
" ```\n",
"\n",
" - We make a new request, but also considering the number of tokens we asked for in the first prompt, so this time we say `max_output_tokens` is 1200. \n",
"\n",
" ```python\n",
" response = client.responses.create(model=deployment, input=messages, max_output_tokens=1200, store=False)\n",
" ``` \n",
"\n",
" Taking this code for a spin, we now arrive at the following output:\n",
"\n",
" ```output\n",
" No of recipes (for example, 5: 2\n",
" List of ingredients (for example, chicken, potatoes, and carrots: apple,flour\n",
" Filter (for example, vegetarian, vegan, or gluten-free: sugar\n",
" Recipes:\n",
" or milk.\n",
" \n",
" -Apple and flour pancakes: 1 cup flour, 1/2 tsp baking powder, 1/2 tsp baking soda, 1/4 tsp salt, 1 tbsp sugar, 1 egg, 1 cup buttermilk or sour milk, 1/4 cup melted butter, 1 Granny Smith apple, peeled and grated\n",
" -Apple fritters: 1-1/2 cups flour, 1 tsp baking powder, 1/4 tsp salt, 1/4 tsp baking soda, 1/4 tsp nutmeg, 1/4 tsp cinnamon, 1/4 tsp allspice, 1/4 cup sugar, 1/4 cup vegetable shortening, 1/4 cup milk, 1 egg, 2 cups shredded, peeled apples\n",
" Shopping list:\n",
" -Flour, baking powder, baking soda, salt, sugar, egg, buttermilk, butter, apple, nutmeg, cinnamon, allspice \n",
" ```\n",
" \n",
"- **A word on token length**. We should consider how many tokens we need to generate the text we want. Tokens cost money, so where possible, we should try to be economical with the number of tokens we use. For example, can we phrase the prompt so that we can use less tokens?\n",
"\n",
" To change tokens used, you can use the `max_output_tokens` parameter. For example, if you want to use 100 tokens, you would do:\n",
"\n",
" ```python\n",
" response = client.responses.create(model=deployment, input=messages, max_output_tokens=100, store=False)\n",
" ```\n",
"\n",
"- **Experimenting with temperature**. Temperature is something we haven't mentioned so far but is an important context for how our program performs. The higher the temperature value the more random the output will be. Conversely the lower the temperature value the more predictable the output will be. Consider whether you want variation in your output or not.\n",
"\n",
" To alter the temperature, you can use the `temperature` parameter. For example, if you want to use a temperature of 0.5, you would do:\n",
"\n",
" ```python\n",
" response = client.responses.create(model=deployment, input=messages, temperature=0.5, store=False)\n",
" ```\n",
"\n",
" > Note, the closer to 1.0, the more varied the output.\n",
"\n",
"\n",
"\n",
"## Assignment\n",
"\n",
"For this assignment, you can choose what to build.\n",
"\n",
"Here are some suggestions:\n",
"\n",
"- Tweak the recipe generator app to improve it further. Play around with temperature values, and the prompts to see what you can come up with.\n",
"- Build a \"study buddy\". This app should be able to answer questions about a topic for example Python, you could have prompts like \"What is a certain topic in Python?\", or you could have a prompt that says, show me code for a certain topic etc.\n",
"- History bot, make history come alive, instruct the bot to play a certain historical character and ask it questions about its life and times. \n",
"\n",
"## Solution\n",
"\n",
"### Study buddy\n",
"\n",
"- \"You're an expert on the Python language\n",
"\n",
" Suggest a beginner lesson for Python in the following format:\n",
" \n",
" Format:\n",
" - concepts:\n",
" - brief explanation of the lesson:\n",
" - exercise in code with solutions\"\n",
"\n",
"Above is a starter prompt, see how you can use it and tweak it to your liking.\n",
"\n",
"### History bot\n",
"\n",
"Here's some prompts you could be using:\n",
"\n",
"- \"You are Abe Lincoln, tell me about yourself in 3 sentences, and respond using grammar and words like Abe would have used\"\n",
"- \"You are Abe Lincoln, respond using grammar and words like Abe would have used:\n",
"\n",
" Tell me about your greatest accomplishments, in 300 words:\"\n",
"\n",
"## Knowledge check\n",
"\n",
"What does the concept temperature do?\n",
"\n",
"1. It controls how random the output is.\n",
"1. It controls how big the response is.\n",
"1. It controls how many tokens are used.\n",
"\n",
"A: 1\n",
"\n",
"What's a good way to store secrets like API keys?\n",
"\n",
"1. In code.\n",
"1. In a file.\n",
"1. In environment variables.\n",
"\n",
"A: 3, because environment variables are not stored in code and can be loaded from the code. \n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "venv",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.9"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
@@ -0,0 +1,34 @@
from openai import OpenAI
import os
from dotenv import load_dotenv
# load environment variables from .env file
load_dotenv()
# configure the OpenAI client against the Azure OpenAI (Microsoft Foundry) v1 endpoint
client = OpenAI(
api_key=os.environ['AZURE_OPENAI_API_KEY'],
base_url=f"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/",
)
deployment=os.environ['AZURE_OPENAI_DEPLOYMENT']
# add your completion code
persona = input("Tell me the historical character I want to be: ")
question = input("Ask your question about the historical character: ")
prompt = f"""
You are going to play as a historical character {persona}.
Whenever certain questions are asked, you need to remember facts about the timelines and incidents and respond the accurate answer only. Don't create content yourself. If you don't know something, tell that you don't remember.
Provide answer for the question: {question}
"""
# make a request using the Responses API
response = client.responses.create(model=deployment, input=prompt, store=False)
# print response
print(response.output_text)
# very unhappy _____.
# Once upon a time there was a very unhappy mermaid.
@@ -0,0 +1,37 @@
from openai import OpenAI
import os
from dotenv import load_dotenv
# load environment variables from .env file
load_dotenv()
# configure the OpenAI client against the Azure OpenAI (Microsoft Foundry) v1 endpoint
client = OpenAI(
api_key=os.environ['AZURE_OPENAI_API_KEY'],
base_url=f"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/",
)
deployment=os.environ['AZURE_OPENAI_DEPLOYMENT']
# add your completion code
question = input("Ask your questions on python language to your study buddy: ")
prompt = f"""
You are an expert on the python language.
Whenever certain questions are asked, you need to provide response in below format.
- Concept
- Example code showing the concept implementation
- explanation of the example and how the concept is done for the user to understand better.
Provide answer for the question: {question}
"""
# make a request using the Responses API
response = client.responses.create(model=deployment, input=prompt, store=False)
# print response
print(response.output_text)
# very unhappy _____.
# Once upon a time there was a very unhappy mermaid.
@@ -0,0 +1,39 @@
import os
from azure.ai.inference import ChatCompletionsClient
from azure.ai.inference.models import SystemMessage, UserMessage
from azure.core.credentials import AzureKeyCredential
# Get these from your Microsoft Foundry project's "Overview" page
# (GitHub Models is retiring end of July 2026 - see https://ai.azure.com/catalog/models)
token = os.environ["AZURE_INFERENCE_CREDENTIAL"]
endpoint = os.environ["AZURE_INFERENCE_ENDPOINT"]
model_name = "gpt-4o-mini"
client = ChatCompletionsClient(
endpoint=endpoint,
credential=AzureKeyCredential(token),
)
prompt = "Show me 5 recipes for a dish with the following ingredients: chicken, potatoes, and carrots. Per recipe, list all the ingredients used"
response = client.complete(
messages=[
{
"role": "system",
"content": "You are a helpful assistant.",
},
{
"role": "user",
"content": prompt,
},
],
model=model_name,
# Optional parameters
temperature=1.,
max_tokens=1000,
top_p=1.
)
if response.choices and response.choices[0].message is not None:
print(response.choices[0].message.content)
@@ -0,0 +1,853 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Build text generation apps\n",
"\n",
"You've seen so far through this curriculum that there are core concepts like prompts and even a whole discipline called \"prompt engineering\". Many tools you can interact with like ChatGPT, Office 365, Microsoft Power Platform and more, support you using prompts to accomplish something.\n",
"\n",
"For you to add such an experience to an app, you need to understand concepts like prompts, completions and choose a library to work with. That's exactly what you'll learn in this chapter.\n",
"\n",
"## Introduction\n",
"\n",
"In this chapter, you will:\n",
"\n",
"- Learn about the openai library and its core concepts.\n",
"- Build a text generation app using openai.\n",
"- Understand how to use concepts like prompt, temperature, and tokens to build a text generation app.\n",
"\n",
"## Learning goals\n",
"\n",
"At the end of this lesson, you'll be able to:\n",
"\n",
"- Explain what a text generation app is.\n",
"- Build a text generation app using openai.\n",
"- Configure your app to use more or less tokens and also change the temperature, for a varied output.\n",
"\n",
"## What is a text generation app?\n",
"\n",
"Normally when you build an app it has some kind of interface like the following:\n",
"\n",
"- Command-based. Console apps are typical apps where you type a command and it carries out a task. For example, `git` is a command-based app.\n",
"- User interface (UI). Some apps have graphical user interfaces (GUIs) where you click buttons, input text, select options and more.\n",
"\n",
"### Console and UI apps are limited\n",
"\n",
"Compare it to a command-based app where you type a command: \n",
"\n",
"- **It's limited**. You can't just type any command, only the ones that the app supports.\n",
"- **Language specific**. Some apps support many languages, but by default the app is built for a specific language, even if you can add more language support. \n",
"\n",
"### Benefits of text generation apps\n",
"\n",
"So how is a text generation app different?\n",
"\n",
"In a text generation app, you have more flexibility, you're not limited to a set of commands or a specific input language. Instead, you can use natural language to interact with the app. Another benefit is that because you're already interacting with a data source that has been trained on a vast corpus of information, whereas a traditional app might be limited on what's in a database. \n",
"\n",
"### What can I build with a text generation app?\n",
"\n",
"There are many things you can build. For example:\n",
"\n",
"- **A chatbot**. A chatbot answering questions about topics, like your company and its products could be a good match.\n",
"- **Helper**. LLMs are great at things like summarizing text, getting insights from text, producing text like resumes and more.\n",
"- **Code assistant**. Depending on the language model you use, you can build a code assistant that helps you write code. For example, you can use a product like GitHub Copilot as well as ChatGPT to help you write code.\n",
"\n",
"## How can I get started?\n",
"\n",
"Well, you need to find a way to integrate with an LLM which usually entails the following two approaches:\n",
"\n",
"- Use an API. Here you're constructing web requests with your prompt and get generated text back.\n",
"- Use a library. Libraries help encapsulate the API calls and make them easier to use.\n",
"\n",
"## Libraries/SDKs\n",
"\n",
"There are a few well known libraries for working with LLMs like:\n",
"\n",
"- **openai**, this library makes it easy to connect to your model and send in prompts.\n",
"\n",
"Then there are libraries that operate on a higher level like:\n",
"\n",
"- **Langchain**. Langchain is well known and supports Python.\n",
"- **Semantic Kernel**. Semantic Kernel is a library by Microsoft supporting the languages C#, Python, and Java.\n",
"\n",
"## First app using Microsoft Foundry Models Playground and Azure AI Inference SDK\n",
"\n",
"Let's see how we can build our first app, what libraries we need, how much is required and so on.\n",
"\n",
"> **Note:** GitHub Models is retiring at the end of July 2026. The steps below have been updated to use [Microsoft Foundry Models](https://ai.azure.com/catalog/models?WT.mc_id=academic-105485-koreyst), which offers the same \"explore, try in a playground, and call with an API key\" experience GitHub Models offered, now hosted directly in the Microsoft Foundry portal. Prefer to work fully offline instead? See [Foundry Local](https://foundrylocal.ai?WT.mc_id=academic-105485-koreyst) for running models on your own device, no cloud subscription required.\n",
"\n",
"### What is Microsoft Foundry Models?\n",
"\n",
"Welcome to [Microsoft Foundry Models](https://ai.azure.com/catalog/models?WT.mc_id=academic-105485-koreyst)! The Foundry model catalog gives you a single place to explore and try hundreds of AI models - from OpenAI, Meta, Mistral, Cohere, Microsoft, and more - hosted on Azure, all accessible via a free playground and, once deployed, callable from your favorite code IDE.\n",
"\n",
"### What do I need?\n",
"\n",
"* A Microsoft account and an [Azure subscription](https://aka.ms/azure/free?WT.mc_id=academic-105485-koreyst) (a free account works)\n",
"* A [Microsoft Foundry project](https://ai.azure.com?WT.mc_id=academic-105485-koreyst)\n",
"\n",
"Lets get started!\n",
"\n",
"### Find a model and test it\n",
"\n",
"Navigate to the [Microsoft Foundry Models catalog](https://ai.azure.com/catalog/models?WT.mc_id=academic-105485-koreyst)\n",
"\n",
"![Microsoft Foundry Models catalog showing a list of model cards such as Cohere, Meta llama, Mistral and GPT models](../images/GithubModelsMainScreen.png?WT.mc_id=academic-105485-koreyst)\n",
"\n",
"Choose a model - for example OpenAI GPT-4o mini\n",
"\n",
"Here you will see the model card. You can:\n",
"* Read details about the model in the readme, benchmarks, and license tabs\n",
"* Deploy the model to your Foundry project\n",
"* Once deployed, interact with the model directly in the playground\n",
"\n",
"![Microsoft Foundry Models GPT-4o Model Card](../images/GithubModels-modelcard.png?WT.mc_id=academic-105485-koreyst)\n",
"\n",
"Open the **Playground** to interact with the model, add system prompts and change parameter details - and also get all the code you need to run this from anywhere, in Python, JavaScript, C#, and REST.\n",
"\n",
"![Microsoft Foundry Models Playground experience with code and languages shown](../images/GithubModels-plagroundcode.png?WT.mc_id=academic-105485-koreyst) \n",
"\n",
"\n",
"### Lets use the model in our own IDE\n",
"\n",
"Two options here:\n",
"1. **GitHub Codespaces** - seamless integration with Codespaces\n",
"2. **VS Code (or any favorite IDE)** - you'll need the **endpoint** and **API key** from your Foundry project\n",
"\n",
"\n",
"Either way, you'll find these values on the **Overview** page of your Foundry project.\n",
"\n",
"![Get Started screen showing you how to access Codespaces or use a personal access token to setup in your own IDE](../images/GithubModels-getstarted.png?WT.mc_id=academic-105485-koreyst)\n",
"\n",
"### 1.Codespaces \n",
"\n",
"* Create a new codespace (or use an existing)\n",
"* VS Code will open in your browser with a set of sample notebooks in multiple languages you can try\n",
"* Run the sample ```./githubmodels-app.py```. \n",
"\n",
"> Note: In codespaces, save your Foundry endpoint and key as Codespaces secrets so you don't have to set them locally.\n",
"\n",
"**Now move to 'Generate Text' section below to continue this assignment**\n",
"\n",
"### 2. VS Code (or any favorite IDE)\n",
"\n",
"From your Microsoft Foundry project you have all the information you need to run in your favorite IDE. This example will show VS Code\n",
"\n",
"* Deploy a chat model such as `gpt-4o-mini` in your Foundry project\n",
"* Copy the project's **endpoint** and **API key** from the Overview page\n",
"* Create environment variables to store them: `AZURE_INFERENCE_ENDPOINT` and `AZURE_INFERENCE_CREDENTIAL` - samples available in bash, powershell and windows command prompt\n",
"* Install dependencies: ```pip install azure-ai-inference```\n",
"* Copy basic sample code into a .py file\n",
"* navigate to where your code is saved and run the file: ```python filename.py```\n",
"\n",
"Don't forget by using the Azure AI Inference SDK, you can easily experiment with different models by modifying the value of `model_name` in the code. \n",
"\n",
"The following models are available in the Microsoft Foundry Models catalog:\n",
"\n",
"* OpenAI: gpt-4o, gpt-4o-mini, gpt-4.1, gpt-4.1-mini, o3-mini, text-embedding-3-large, text-embedding-3-small\n",
"* Meta: Meta-Llama-3.1-405B-Instruct, Meta-Llama-3.1-70B-Instruct, Meta-Llama-3.1-8B-Instruct, Llama-3.2-11B-Vision-Instruct, Llama-3.2-90B-Vision-Instruct, Llama-4-Scout-17B-16E-Instruct\n",
"* Mistral AI: Mistral-large-2411, Mistral-small-2503, Codestral-2501, Ministral-3B\n",
"* Microsoft: Phi-4, Phi-4-mini-instruct, Phi-4-multimodal-instruct, Phi-4-reasoning\n",
"* Cohere: Cohere-command-r-plus-08-2024, Cohere-embed-v3-multilingual, Cohere-embed-v3-english\n",
"* DeepSeek: DeepSeek-V3, DeepSeek-R1\n",
"\n",
"\n",
"\n",
"**Now move to 'Generate Text' section below to continue this assignment**\n",
"\n",
"## Generate text with ChatCompletions\n",
"\n",
"The way to generate text is to use the `ChatCompletionsClient` class. \n",
"In `samples/python/azure_ai_inference/basic.py`, in the response section of code, update the code the user role by changing the content parameter to below:\n",
"\n",
"```python\n",
"\n",
"response = client.complete(\n",
" messages=[\n",
" {\n",
" \"role\": \"system\",\n",
" \"content\": \"You are a helpful assistant.\",\n",
" },\n",
" {\n",
" \"role\": \"user\",\n",
" \"content\": \"Complete the following: Once upon a time there was a\",\n",
" },\n",
" ],\n",
" model=model_name,\n",
" # Optional parameters\n",
" temperature=1.,\n",
" max_tokens=1000,\n",
" top_p=1. \n",
")\n",
"\n",
"```\n",
"\n",
"Run the updated file to see the output\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Different types of prompts, for different things\n",
"\n",
"Now you've seen how to generate text using a prompt. You even have a program up and running that you can modify and change to generate different types of text. \n",
"\n",
"Prompts can be used for all sorts of tasks. For example:\n",
"\n",
"- **Generate a type of text**. For example, you can generate a poem, questions for a quiz etc.\n",
"- **Lookup information**. You can use prompts to look for information like the following example 'What does CORS mean in web development?'.\n",
"- **Generate code**. You can use prompts to generate code, for example developing a regular expression used to validate emails or why not generate an entire program, like a web app? \n",
"\n",
"## Exercise: a recipe generator\n",
"\n",
"Imagine you have ingredients at home and you want to cook something. For that, you need a recipe. A way to find recipes is to use a search engine or you could use an LLM to do so.\n",
"\n",
"You could write a prompt like so:\n",
"\n",
"> \"Show me 5 recipes for a dish with the following ingredients: chicken, potatoes, and carrots. Per recipe, list all the ingredients used\"\n",
"\n",
"Given the above prompt, you might get a response similar to:\n",
"\n",
"```output\n",
"1. Roasted Chicken and Vegetables: \n",
"Ingredients: \n",
"- 4 chicken thighs\n",
"- 2 potatoes, cut into cubes\n",
"- 2 carrots, cut into cubes\n",
"- 2 tablespoons olive oil\n",
"- 2 cloves garlic, minced\n",
"- 1 teaspoon dried thyme\n",
"- 1 teaspoon dried oregano\n",
"- Salt and pepper, to taste\n",
"\n",
"2. Chicken and Potato Stew: \n",
"Ingredients: \n",
"- 2 tablespoons olive oil\n",
"- 1 onion, diced\n",
"- 2 cloves garlic, minced\n",
"- 2 chicken breasts, cut into cubes\n",
"- 2 potatoes, cut into cubes\n",
"- 2 carrots, cut into cubes\n",
"- 1 teaspoon dried oregano\n",
"- 1 teaspoon dried thyme\n",
"- 1 cup chicken broth\n",
"- Salt and pepper, to taste\n",
"\n",
"3. Chicken and Potato Bake: \n",
"Ingredients: \n",
"- 2 tablespoons olive oil\n",
"- 2 chicken breasts, cut into cubes\n",
"- 2 potatoes, cut into cubes\n",
"- 2 carrots, cut into cubes\n",
"- 1 onion, diced\n",
"- 2 cloves garlic, minced\n",
"- 1 teaspoon dried oregano\n",
"- 1 teaspoon dried thyme\n",
"- 1 cup chicken broth\n",
"- Salt and pepper, to taste\n",
"\n",
"4. Chicken and Potato Soup: \n",
"Ingredients: \n",
"- 2 tablespoons olive oil\n",
"- 1 onion, diced\n",
"- 2 cloves garlic, minced\n",
"- 2 chicken breasts, cut into cubes\n",
"- 2 potatoes, cut into cubes\n",
"- 2 carrots, cut into cubes\n",
"- 1 teaspoon dried oregano\n",
"- 1 teaspoon dried thyme\n",
"- 4 cups chicken broth\n",
"- Salt and pepper, to taste\n",
"\n",
"5. Chicken and Potato Hash: \n",
"Ingredients: \n",
"- 2 tablespoons olive oil\n",
"- 2 chicken breasts, cut into cubes\n",
"- 2 potatoes, cut into cubes\n",
"- 2 carrots, cut into cubes\n",
"- 1 onion, diced\n",
"- 2 cloves garlic, minced\n",
"- 1 teaspoon dried oregano\n",
"```\n",
"\n",
"This outcome is great, I know what to cook. At this point, what could be useful improvements are:\n",
"\n",
"- Filtering out ingredients I don't like or am allergic to.\n",
"- Produce a shopping list, in case I don't have all the ingredients at home.\n",
"\n",
"For the above cases, let's add an additional prompt:\n",
"\n",
"> \"Please remove recipes with garlic as I'm allergic and replace it with something else. Also, please produce a shopping list for the recipes, considering I already have chicken, potatoes and carrots at home.\"\n",
"\n",
"Now you have a new result, namely:\n",
"\n",
"```output\n",
"1. Roasted Chicken and Vegetables: \n",
"Ingredients: \n",
"- 4 chicken thighs\n",
"- 2 potatoes, cut into cubes\n",
"- 2 carrots, cut into cubes\n",
"- 2 tablespoons olive oil\n",
"- 1 teaspoon dried thyme\n",
"- 1 teaspoon dried oregano\n",
"- Salt and pepper, to taste\n",
"\n",
"2. Chicken and Potato Stew: \n",
"Ingredients: \n",
"- 2 tablespoons olive oil\n",
"- 1 onion, diced\n",
"- 2 chicken breasts, cut into cubes\n",
"- 2 potatoes, cut into cubes\n",
"- 2 carrots, cut into cubes\n",
"- 1 teaspoon dried oregano\n",
"- 1 teaspoon dried thyme\n",
"- 1 cup chicken broth\n",
"- Salt and pepper, to taste\n",
"\n",
"3. Chicken and Potato Bake: \n",
"Ingredients: \n",
"- 2 tablespoons olive oil\n",
"- 2 chicken breasts, cut into cubes\n",
"- 2 potatoes, cut into cubes\n",
"- 2 carrots, cut into cubes\n",
"- 1 onion, diced\n",
"- 1 teaspoon dried oregano\n",
"- 1 teaspoon dried thyme\n",
"- 1 cup chicken broth\n",
"- Salt and pepper, to taste\n",
"\n",
"4. Chicken and Potato Soup: \n",
"Ingredients: \n",
"- 2 tablespoons olive oil\n",
"- 1 onion, diced\n",
"- 2 chicken breasts, cut into cubes\n",
"- 2 potatoes, cut into cubes\n",
"- 2 carrots, cut into cubes\n",
"- 1 teaspoon dried oregano\n",
"- 1 teaspoon dried thyme\n",
"- 4 cups chicken broth\n",
"- Salt and pepper, to taste\n",
"\n",
"5. Chicken and Potato Hash: \n",
"Ingredients: \n",
"- 2 tablespoons olive oil\n",
"- 2 chicken breasts, cut into cubes\n",
"- 2 potatoes, cut into cubes\n",
"- 2 carrots, cut into cubes\n",
"- 1 onion, diced\n",
"- 1 teaspoon dried oregano\n",
"\n",
"Shopping List: \n",
"- Olive oil\n",
"- Onion\n",
"- Thyme\n",
"- Oregano\n",
"- Salt\n",
"- Pepper\n",
"```\n",
"\n",
"That's your five recipes, with no garlic mentioned and you also have a shopping list considering what you already have at home. "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Exercise - build a recipe generator\n",
"\n",
"Now that we have played out a scenario, let's write code to match the demonstrated scenario. To do so, follow these steps:\n",
"\n",
"1. Use the existing file as a starting point\n",
"1. Create a `prompt` variable and change the sample code as below:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"from azure.ai.inference import ChatCompletionsClient\n",
"from azure.ai.inference.models import SystemMessage, UserMessage\n",
"from azure.core.credentials import AzureKeyCredential\n",
"\n",
"# Get these from your Microsoft Foundry project's \"Overview\" page\n",
"token = os.environ[\"AZURE_INFERENCE_CREDENTIAL\"]\n",
"endpoint = os.environ[\"AZURE_INFERENCE_ENDPOINT\"]\n",
"\n",
"model_name = \"gpt-4o-mini\"\n",
"\n",
"client = ChatCompletionsClient(\n",
" endpoint=endpoint,\n",
" credential=AzureKeyCredential(token),\n",
")\n",
"\n",
"prompt = \"Show me 5 recipes for a dish with the following ingredients: chicken, potatoes, and carrots. Per recipe, list all the ingredients used\"\n",
"\n",
"response = client.complete(\n",
" messages=[\n",
" {\n",
" \"role\": \"system\",\n",
" \"content\": \"You are a helpful assistant.\",\n",
" },\n",
" {\n",
" \"role\": \"user\",\n",
" \"content\": prompt,\n",
" },\n",
" ],\n",
" model=model_name,\n",
" # Optional parameters\n",
" temperature=1.,\n",
" max_tokens=1000,\n",
" top_p=1. \n",
")\n",
"\n",
"print(response.choices[0].message.content)\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"If you now run the code, you should see an output similar to:\n",
"\n",
"```output\n",
"### Recipe 1: Classic Chicken Stew\n",
"#### Ingredients:\n",
"- 2 lbs chicken thighs or drumsticks, skinless\n",
"- 4 cups chicken broth\n",
"- 4 medium potatoes, peeled and diced\n",
"- 4 large carrots, peeled and sliced\n",
"- 1 large onion, chopped\n",
"- 2 cloves garlic, minced\n",
"- 2 celery stalks, sliced\n",
"- 1 tsp dried thyme\n",
"- 1 tsp dried rosemary\n",
"- Salt and pepper to taste\n",
"- 2 tbsp olive oil\n",
"- 2 tbsp flour (optional, for thickening)\n",
"\n",
"### Recipe 2: Chicken and Vegetable Roast\n",
"#### Ingredients:\n",
"- 4 chicken breasts or thighs\n",
"- 4 medium potatoes, cut into wedges\n",
"- 4 large carrots, cut into sticks\n",
"- 1 large onion, cut into wedges\n",
"- 3 cloves garlic, minced\n",
"- 1/4 cup olive oil \n",
"- 1 tsp paprika\n",
"- 1 tsp dried oregano\n",
"- Salt and pepper to taste\n",
"- Juice of 1 lemon\n",
"- Fresh parsley, chopped (for garnish)\n",
"(continued ...)\n",
"```\n",
"\n",
"> NOTE, your LLM is nondeterministic, so you might get different results every time you run the program.\n",
"\n",
"Great, let's see how we can improve things. To improve things, we want to make sure the code is flexible, so ingredients and number of recipes can be improved and changed. "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"1. Let's change the code in the following way:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"from azure.ai.inference import ChatCompletionsClient\n",
"from azure.ai.inference.models import SystemMessage, UserMessage\n",
"from azure.core.credentials import AzureKeyCredential\n",
"\n",
"# Get these from your Microsoft Foundry project's \"Overview\" page\n",
"token = os.environ[\"AZURE_INFERENCE_CREDENTIAL\"]\n",
"endpoint = os.environ[\"AZURE_INFERENCE_ENDPOINT\"]\n",
"\n",
"model_name = \"gpt-4o-mini\"\n",
"\n",
"client = ChatCompletionsClient(\n",
" endpoint=endpoint,\n",
" credential=AzureKeyCredential(token),\n",
")\n",
"\n",
"no_recipes = input(\"No of recipes (for example, 5): \")\n",
"\n",
"ingredients = input(\"List of ingredients (for example, chicken, potatoes, and carrots): \")\n",
"\n",
"# interpolate the number of recipes into the prompt an ingredients\n",
"prompt = f\"Show me {no_recipes} recipes for a dish with the following ingredients: {ingredients}. Per recipe, list all the ingredients used\"\n",
"\n",
"response = client.complete(\n",
" messages=[\n",
" {\n",
" \"role\": \"system\",\n",
" \"content\": \"You are a helpful assistant.\",\n",
" },\n",
" {\n",
" \"role\": \"user\",\n",
" \"content\": prompt,\n",
" },\n",
" ],\n",
" model=model_name,\n",
" # Optional parameters\n",
" temperature=1.,\n",
" max_tokens=1000,\n",
" top_p=1. \n",
")\n",
"\n",
"print(response.choices[0].message.content)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"Taking the code for a test run, could look like this:\n",
" \n",
"```output\n",
"No of recipes (for example, 5): 2\n",
"List of ingredients (for example, chicken, potatoes, and carrots): milk, strawberries\n",
"\n",
"Sure! Here are two recipes featuring milk and strawberries:\n",
"\n",
"### Recipe 1: Strawberry Milkshake\n",
"\n",
"#### Ingredients:\n",
"- 1 cup milk\n",
"- 1 cup strawberries, hulled and sliced\n",
"- 2 tablespoons sugar (optional, to taste)\n",
"- 1/2 teaspoon vanilla extract\n",
"- 5-6 ice cubes\n",
"\n",
"#### Instructions:\n",
"1. Combine the milk, strawberries, sugar (if using), and vanilla extract in a blender.\n",
"2. Blend on high until smooth and creamy.\n",
"3. Add the ice cubes and blend again until the ice is fully crushed and the milkshake is frothy.\n",
"4. Pour into a glass and serve immediately.\n",
"\n",
"### Recipe 2: Strawberry Panna Cotta\n",
"\n",
"#### Ingredients:\n",
"- 1 cup milk\n",
"- 1 cup strawberries, hulled and pureed\n",
"- 1/4 cup sugar\n",
"- 1 teaspoon vanilla extract\n",
"- 1 envelope unflavored gelatin (about 2 1/2 teaspoons)\n",
"- 2 tablespoons cold water\n",
"- 1 cup heavy cream\n",
"\n",
"#### Instructions:\n",
"1. Sprinkle the gelatin over the cold water in a small bowl and let it stand for about 5-10 minutes to soften.\n",
"2. In a saucepan, combine the milk, heavy cream, and sugar. Cook over medium heat, stirring frequently until the sugar is dissolved and the mixture begins to simmer. Do not let it boil.\n",
"3. Remove the saucepan from the heat and stir in the softened gelatin until completely dissolved.\n",
"4. Stir in the vanilla extract and allow the mixture to cool slightly.\n",
"5. Divide the mixture evenly into serving cups or molds and refrigerate for at least 4 hours or until set.\n",
"6. To prepare the strawberry puree, blend the strawberries until smooth.\n",
"7. Once the panna cotta is set, spoon the strawberry puree over the top of each panna cotta.\n",
"8. Serve chilled.\n",
"\n",
"Enjoy these delightful recipes!\n",
"```\n",
"\n",
"### Improve by adding filter and shopping list\n",
"\n",
"We now have a working app capable of producing recipes and it's flexible as it relies on inputs from the user, both on the number of recipes but also the ingredients used.\n",
"\n",
"To further improve it, we want to add the following:\n",
"\n",
"- **Filter out ingredients**. We want to be able to filter out ingredients we don't like or are allergic to. To accomplish this change, we can edit our existing prompt and add a filter condition to the end of it like so:\n",
"\n",
" ```python\n",
" filter = input(\"Filter (for example, vegetarian, vegan, or gluten-free: \")\n",
"\n",
" prompt = f\"Show me {no_recipes} recipes for a dish with the following ingredients: {ingredients}. Per recipe, list all the ingredients used, no {filter}\"\n",
" ```\n",
"\n",
" Above, we add `{filter}` to the end of the prompt and we also capture the filter value from the user.\n",
"\n",
" An example input of running the program can now look like so:\n",
" \n",
" ```output \n",
" No of recipes (for example, 5): 2\n",
" List of ingredients (for example, chicken, potatoes, and carrots): onion, milk\n",
" Filter (for example, vegetarian, vegan, or gluten-free: no milk\n",
" Certainly! Here are two recipes using onion but omitting milk:\n",
" \n",
" ### Recipe 1: Caramelized Onions\n",
" \n",
" #### Ingredients:\n",
" - 4 large onions, thinly sliced\n",
" - 2 tablespoons olive oil\n",
" - 1 tablespoon butter\n",
" - 1 teaspoon salt\n",
" - 1 teaspoon sugar (optional)\n",
" - 1 tablespoon balsamic vinegar (optional)\n",
" \n",
" #### Instructions:\n",
" 1. Heat the olive oil and butter in a large skillet over medium heat until the butter is melted.\n",
" 2. Add the onions and stir to coat them with the oil and butter mixture.\n",
" 3. Add salt (and sugar if using) to the onions.\n",
" 4. Cook the onions, stirring occasionally, for about 45 minutes to an hour until they are golden brown and caramelized.\n",
" 5. If using, add balsamic vinegar during the last 5 minutes of cooking.\n",
" 6. Remove from heat and serve as a topping for burgers, steak, or as a side dish.\n",
" \n",
" ### Recipe 2: French Onion Soup\n",
" \n",
" #### Ingredients:\n",
" - 4 large onions, thinly sliced\n",
" - 3 tablespoons unsalted butter\n",
" - 2 cloves garlic, minced\n",
" - 1 teaspoon sugar\n",
" - 1 teaspoon salt\n",
" - 1/4 cup dry white wine (optional)\n",
" - 4 cups beef broth\n",
" - 4 cups chicken broth\n",
" - 1 bay leaf\n",
" - 1 teaspoon fresh thyme, chopped (or 1/2 teaspoon dried thyme)\n",
" - 1 baguette, sliced\n",
" - 2 cups Gruyère cheese, grated\n",
" \n",
" #### Instructions:\n",
" 1. Melt the butter in a large pot over medium heat.\n",
" 2. Add the onions, garlic, sugar, and salt, and cook, stirring frequently, until the onions are deeply caramelized (about 30-35 minutes).\n",
" 3. If using, add the white wine and cook until it evaporates, about 3-5 minutes.\n",
" 4. Add the beef and chicken broths, bay leaf, and thyme. Bring to a simmer and cook for another 30 minutes. Remove the bay leaf.\n",
" 5. Preheat the oven to 400°F (200°C).\n",
" 6. Place the baguette slices on a baking sheet and toast them in the preheated oven until golden brown, about 5 minutes.\n",
" 7. Ladle the soup into oven-safe bowls and place a slice of toasted baguette on top of each bowl.\n",
" 8. Sprinkle the grated Gruyère cheese generously over the baguette slices.\n",
" 9. Place the bowls under the broiler until the cheese is melted and bubbly, about 3-5 minutes.\n",
" 10. Serve hot.\n",
" \n",
" Enjoy your delicious onion dishes!\n",
" ```\n",
" \n",
"- **Produce a shopping list**. We want to produce a shopping list, considering what we already have at home.\n",
"\n",
" For this functionality, we could either try to solve everything in one prompt or we could split it up into two prompts. Let's try the latter approach. Here we're suggesting adding an additional prompt, but for that to work, we need to add the result of the former prompt as context to the latter prompt. \n",
"\n",
" Locate the part in the code that prints out the result from the first prompt and add the following code below:\n",
" \n",
" ```python\n",
" old_prompt_result = response.choices[0].message.content\n",
" prompt = \"Produce a shopping list for the generated recipes and please don't include ingredients that I already have.\"\n",
" \n",
" new_prompt = f\"{old_prompt_result} {prompt}\"\n",
" \n",
" response = client.complete(\n",
" messages=[\n",
" {\n",
" \"role\": \"system\",\n",
" \"content\": \"You are a helpful assistant.\",\n",
" },\n",
" {\n",
" \"role\": \"user\",\n",
" \"content\": new_prompt,\n",
" },\n",
" ],\n",
" model=model_name,\n",
" # Optional parameters\n",
" temperature=1.,\n",
" max_tokens=1200,\n",
" top_p=1. \n",
" )\n",
" \n",
" # print response\n",
" print(\"Shopping list:\")\n",
" print(response.choices[0].message.content)\n",
" ```\n",
"\n",
"\n",
" Note the following:\n",
"\n",
" - We're constructing a new prompt by adding the result from the first prompt to the new prompt: \n",
" \n",
" ```python\n",
" new_prompt = f\"{old_prompt_result} {prompt}\"\n",
" messages = [{\"role\": \"user\", \"content\": new_prompt}]\n",
" ```\n",
"\n",
" - We make a new request, but also considering the number of tokens we asked for in the first prompt, so this time we say `max_tokens` is 1200. **A word on token length**. We should consider how many tokens we need to generate the text we want. Tokens cost money, so where possible, we should try to be economical with the number of tokens we use. For example, can we phrase the prompt so that we can use less tokens?\n",
"\n",
" ```python\n",
" response = client.complete(\n",
" messages=[\n",
" {\n",
" \"role\": \"system\",\n",
" \"content\": \"You are a helpful assistant.\",\n",
" },\n",
" {\n",
" \"role\": \"user\",\n",
" \"content\": new_prompt,\n",
" },\n",
" ],\n",
" model=model_name,\n",
" # Optional parameters\n",
" temperature=1.,\n",
" max_tokens=1200,\n",
" top_p=1. \n",
" ) \n",
" ``` \n",
"\n",
" Taking this code for a spin, we now arrive at the following output:\n",
"\n",
" ```output\n",
" No of recipes (for example, 5): 1\n",
" List of ingredients (for example, chicken, potatoes, and carrots): strawberry, milk\n",
" Filter (for example, vegetarian, vegan, or gluten-free): nuts\n",
" \n",
" Certainly! Here's a simple and delicious recipe for a strawberry milkshake using strawberry and milk as primary ingredients:\n",
" \n",
" ### Strawberry Milkshake\n",
" \n",
" #### Ingredients:\n",
" - 1 cup fresh strawberries, hulled\n",
" - 1 cup cold milk\n",
" - 1 tablespoon honey or sugar (optional, to taste)\n",
" - 1/2 teaspoon vanilla extract (optional)\n",
" - 3-4 ice cubes\n",
" \n",
" #### Instructions:\n",
" 1. Wash and hull the strawberries, then slice them in half.\n",
" 2. In a blender, combine the strawberries, cold milk, honey or sugar (if using), vanilla extract (if using), and ice cubes.\n",
" 3. Blend until smooth and frothy.\n",
" 4. Pour the milkshake into a glass.\n",
" 5. Serve immediately and enjoy your refreshing strawberry milkshake!\n",
" \n",
" This recipe is nut-free and makes for a delightful and quick treat!\n",
" Shopping list:\n",
" Sure! Heres the shopping list for the Strawberry Milkshake recipe based on the ingredients provided. Please adjust based on what you already have at home:\n",
" \n",
" ### Shopping List:\n",
" - Fresh strawberries (1 cup)\n",
" - Milk (1 cup)\n",
" \n",
" Optional:\n",
" - Honey or sugar (1 tablespoon)\n",
" - Vanilla extract (1/2 teaspoon)\n",
" - Ice cubes (3-4)\n",
" \n",
" Feel free to omit the optional ingredients if you prefer or if you already have them on hand. Enjoy your delicious strawberry milkshake!\n",
" ```\n",
" \n",
"- **Experimenting with temperature**. Temperature is something we haven't mentioned so far but is an important context for how our program performs. The higher the temperature value the more random the output will be. Conversely the lower the temperature value the more predictable the output will be. Consider whether you want variation in your output or not.\n",
"\n",
" To alter the temperature, you can use the `temperature` parameter. For example, if you want to use a temperature of 0.5, you would do:\n",
"\n",
"```python\n",
" response = client.complete(\n",
" messages=[\n",
" {\n",
" \"role\": \"system\",\n",
" \"content\": \"You are a helpful assistant.\",\n",
" },\n",
" {\n",
" \"role\": \"user\",\n",
" \"content\": new_prompt,\n",
" },\n",
" ],\n",
" model=model_name,\n",
" # Optional parameters\n",
" temperature=0.5,\n",
" max_tokens=1200,\n",
" top_p=1. \n",
" )\n",
"```\n",
"\n",
" > Note, the closer to 1.0, the more varied the output.\n",
"\n",
"\n",
"## Assignment\n",
"\n",
"For this assignment, you can choose what to build.\n",
"\n",
"Here are some suggestions:\n",
"\n",
"- Tweak the recipe generator app to improve it further. Play around with temperature values, and the prompts to see what you can come up with.\n",
"- Build a \"study buddy\". This app should be able to answer questions about a topic for example Python, you could have prompts like \"What is a certain topic in Python?\", or you could have a prompt that says, show me code for a certain topic etc.\n",
"- History bot, make history come alive, instruct the bot to play a certain historical character and ask it questions about its life and times. \n",
"\n",
"## Solution\n",
"\n",
"### Study buddy\n",
"\n",
"- \"You're an expert on the Python language\n",
"\n",
" Suggest a beginner lesson for Python in the following format:\n",
" \n",
" Format:\n",
" - concepts:\n",
" - brief explanation of the lesson:\n",
" - exercise in code with solutions\"\n",
"\n",
"Above is a starter prompt, see how you can use it and tweak it to your liking.\n",
"\n",
"### History bot\n",
"\n",
"Here's some prompts you could be using:\n",
"\n",
"- \"You are Abe Lincoln, tell me about yourself in 3 sentences, and respond using grammar and words like Abe would have used\"\n",
"- \"You are Abe Lincoln, respond using grammar and words like Abe would have used:\n",
"\n",
" Tell me about your greatest accomplishments, in 300 words:\"\n",
"\n",
"## Knowledge check\n",
"\n",
"What does the concept temperature do?\n",
"\n",
"1. It controls how random the output is.\n",
"1. It controls how big the response is.\n",
"1. It controls how many tokens are used.\n",
"\n",
"A: 1\n",
"\n",
"What's a good way to store secrets like API keys?\n",
"\n",
"1. In code.\n",
"1. In a file.\n",
"1. In environment variables.\n",
"\n",
"A: 3, because environment variables are not stored in code and can be loaded from the code. "
]
}
],
"metadata": {
"kernelspec": {
"display_name": "venv",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.9"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
@@ -0,0 +1,40 @@
from openai import OpenAI
import os
from dotenv import load_dotenv
# load environment variables from .env file
load_dotenv()
# configure Azure OpenAI service client
client = OpenAI()
deployment = "gpt-4o-mini"
no_recipes = input("No of recipes (for example, 5: ")
ingredients = input("List of ingredients (for example, chicken, potatoes, and carrots: ")
filter = input("Filter (for example, vegetarian, vegan, or gluten-free: ")
# interpolate the number of recipes into the prompt an ingredients
prompt = f"Show me {no_recipes} recipes for a dish with the following ingredients: {ingredients}. Per recipe, list all the ingredients used, no {filter}: "
response = client.responses.create(model=deployment, input=prompt, max_output_tokens=600, temperature=0.1, store=False)
# print response
print("Recipes:")
old_prompt_result = response.output_text
if not old_prompt_result:
print("No response received.")
else:
print(old_prompt_result)
prompt_shopping = "Produce a shopping list, and please don't include ingredients that I already have at home: "
new_prompt = f"Given ingredients at home {ingredients} and these generated recipes: {old_prompt_result}, {prompt_shopping}"
response = client.responses.create(model=deployment, input=new_prompt, max_output_tokens=600, temperature=0, store=False)
# print response
print("\n=====Shopping list ======= \n")
if response.output_text:
print(response.output_text)
+22
View File
@@ -0,0 +1,22 @@
from openai import OpenAI
import os
from dotenv import load_dotenv
# load environment variables from .env file
load_dotenv()
# configure OpenAI service client
client = OpenAI()
deployment = "gpt-4o-mini"
# add your completion code
prompt = "Complete the following: Once upon a time there was a"
# make a request using the Responses API
response = client.responses.create(model=deployment, input=prompt, store=False)
# print response
print(response.output_text)
# very unhappy _____.
# Once upon a time there was a very unhappy mermaid.
@@ -0,0 +1,755 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Build text generation apps\n",
"\n",
"You've seen so far through this curriculum that there are core concepts like prompts and even a whole discipline called \"prompt engineering\". Many tools you can interact with like ChatGPT, Office 365, Microsoft Power Platform and more, support you using prompts to accomplish something.\n",
"\n",
"For you to add such an experience to an app, you need to understand concepts like prompts, completions and choose a library to work with. That's exactly what you'll learn in this chapter.\n",
"\n",
"## Introduction\n",
"\n",
"In this chapter, you will:\n",
"\n",
"- Learn about the openai library and its core concepts.\n",
"- Build a text generation app using openai.\n",
"- Understand how to use concepts like prompt, temperature, and tokens to build a text generation app.\n",
"\n",
"## Learning goals\n",
"\n",
"At the end of this lesson, you'll be able to:\n",
"\n",
"- Explain what a text generation app is.\n",
"- Build a text generation app using openai.\n",
"- Configure your app to use more or less tokens and also change the temperature, for a varied output.\n",
"\n",
"## What is a text generation app?\n",
"\n",
"Normally when you build an app it has some kind of interface like the following:\n",
"\n",
"- Command-based. Console apps are typical apps where you type a command and it carries out a task. For example, `git` is a command-based app.\n",
"- User interface (UI). Some apps have graphical user interfaces (GUIs) where you click buttons, input text, select options and more.\n",
"\n",
"### Console and UI apps are limited\n",
"\n",
"Compare it to a command-based app where you type a command: \n",
"\n",
"- **It's limited**. You can't just type any command, only the ones that the app supports.\n",
"- **Language specific**. Some apps support many languages, but by default the app is built for a specific language, even if you can add more language support. \n",
"\n",
"### Benefits of text generation apps\n",
"\n",
"So how is a text generation app different?\n",
"\n",
"In a text generation app, you have more flexibility, you're not limited to a set of commands or a specific input language. Instead, you can use natural language to interact with the app. Another benefit is that because you're already interacting with a data source that has been trained on a vast corpus of information, whereas a traditional app might be limited on what's in a database. \n",
"\n",
"### What can I build with a text generation app?\n",
"\n",
"There are many things you can build. For example:\n",
"\n",
"- **A chatbot**. A chatbot answering questions about topics, like your company and its products could be a good match.\n",
"- **Helper**. LLMs are great at things like summarizing text, getting insights from text, producing text like resumes and more.\n",
"- **Code assistant**. Depending on the language model you use, you can build a code assistant that helps you write code. For example, you can use a product like GitHub Copilot as well as ChatGPT to help you write code.\n",
"\n",
"## How can I get started?\n",
"\n",
"Well, you need to find a way to integrate with an LLM which usually entails the following two approaches:\n",
"\n",
"- Use an API. Here you're constructing web requests with your prompt and get generated text back.\n",
"- Use a library. Libraries help encapsulate the API calls and make them easier to use.\n",
"\n",
"## Libraries/SDKs\n",
"\n",
"There are a few well known libraries for working with LLMs like:\n",
"\n",
"- **openai**, this library makes it easy to connect to your model and send in prompts.\n",
"\n",
"Then there are libraries that operate on a higher level like:\n",
"\n",
"- **Langchain**. Langchain is well known and supports Python.\n",
"- **Semantic Kernel**. Semantic Kernel is a library by Microsoft supporting the languages C#, Python, and Java.\n",
"\n",
"## First app using openai\n",
"\n",
"Let's see how we can build our first app, what libraries we need, how much is required and so on.\n",
"\n",
"### Install openai\n",
"\n",
" > [!NOTE] This step is not necessary if run this notebook on Codespaces or within a Devcontainer\n",
"\n",
"\n",
"There are many libraries out there for interacting with OpenAI or Azure OpenAI. It's possible to use numerous programming languages as well like C#, Python, JavaScript, Java and more. \n",
"We've chosen to use the `openai` Python library, so we'll use `pip` to install it.\n",
"\n",
"```bash\n",
"pip install openai\n",
"```\n",
"\n",
"If you aren't running this notebook in a Codespaces or a Dev Container, you also need to install [Python](https://www.python.org/) on your machine.\n",
"\n",
"### Create a resource and locate your API key\n",
"\n",
"In case you didn't already, you need to carry out the following steps:\n",
"\n",
"- Create an account on OpenAI <https://platform.openai.com/signup>.\n",
"- Now, get your API keys <https://platform.openai.com/api-keys>. \n",
"\n",
">[!NOTE]\n",
"> It's worth separating your API key from your code. You can do so by using environment variables.\n",
"> - Set the environment variable `OPENAI_KEY` to your API key in your .env file. If you already completed the previous exercises of this course, you are all set up.\n",
"> - It is important to note that the API Key will only be accessible once. Therefore, it is imperative to verify that it has been copied correctly. In the event that it does not function as intended, it is recommended to delete the key and generate a new one.\n",
"\n",
"\n",
"### Setup configuration OpenAI\n",
"\n",
"If you're using OpenAI, here's how you setup configuration:\n",
"\n",
"```python\n",
"client = OpenAI(\n",
" api_key = os.environ['OPENAI_API_KEY']\n",
" )\n",
"\n",
"deployment = \"gpt-4o-mini\"\n",
"```\n",
"\n",
"Above we're setting the following:\n",
"\n",
"- `api_key`, this is your API key found in the OpenAI dashboard.\n",
"- `deployment`, this is your GPT version.\n",
"\n",
"> [!NOTE]\n",
"> `os.environ` is a function that reads environment variables. You can use it to read environment variables like `OPENAI_API_KEY`.\n",
"\n",
"## Generate text\n",
"\n",
"The way to generate text is to use the `responses.create` method. Here's an example:\n",
"\n",
"```python\n",
"prompt = \"Complete the following: Once upon a time there was a\"\n",
"\n",
"response = client.responses.create(model=deployment, input=prompt, store=False)\n",
"print(response.output_text)\n",
"```\n",
"\n",
"In the above code, we create a response object and pass in the model we want to use and the prompt. Then we print the generated text.\n",
"\n",
"### Chat responses\n",
"\n",
"So far, you've seen how we can generate text from a single prompt. The Responses API is also well suited for chatbots - you provide a list of messages as the `input` to build up a conversation. Here's an example of using it:\n",
"\n",
"```python\n",
"client = OpenAI(\n",
" api_key = os.environ['OPENAI_API_KEY']\n",
" )\n",
"\n",
"deployment = \"gpt-4o-mini\"\n",
"\n",
"response = client.responses.create(model=deployment, input=[{\"role\": \"user\", \"content\": \"Hello world\"}], store=False)\n",
"print(response.output_text)\n",
"```\n",
"\n",
"More on this functionality in a coming chapter.\n",
"\n",
"## Exercise - your first text generation app\n",
"\n",
"Now that we learned how to set up and configure OpenAI service, it's time to build your first text generation app. To build your app, follow these steps:\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"1. Create a virtual environment and install openai:\n",
"\n",
" > [!NOTE] This step is not necessary if you run this notebook on Codespaces or within a Devcontainer"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Create virtual environment\n",
"! python -m venv venv\n",
"# Activate virtual environment\n",
"! source venv/bin/activate\n",
"# Install openai package\n",
"! pip install openai"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"> [!NOTE]\n",
"> If you're using Windows type `venv\\Scripts\\activate` instead of `source venv/bin/activate`. \n",
"\n",
"> [!NOTE]\n",
"> Locate your OpenAI key by going to https://platform.openai.com/settings/organization/api-keys and search for `API keys`. You can create a new key there and immediate copy the value."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"1. Create a *app.py* file and give it the following code:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"from openai import OpenAI\n",
"from dotenv import load_dotenv\n",
"\n",
"# load environment variables from .env file\n",
"load_dotenv()\n",
"\n",
"client = OpenAI(\n",
" api_key = os.environ['OPENAI_API_KEY']\n",
")\n",
"\n",
"deployment = \"gpt-4o-mini\"\n",
"\n",
"# add your completion code\n",
"prompt = \"Complete the following: Once upon a time there was a\"\n",
"\n",
"# make a request using the Responses API\n",
"response = client.responses.create(model=deployment, input=prompt, store=False)\n",
"\n",
"# print response\n",
"print(response.output_text)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
" You should see an output like the following:\n",
"\n",
" ```output\n",
" very unhappy _____.\n",
"\n",
" Once upon a time there was a very unhappy mermaid.\n",
" ```"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Different types of prompts, for different things\n",
"\n",
"Now you've seen how to generate text using a prompt. You even have a program up and running that you can modify and change to generate different types of text. \n",
"\n",
"Prompts can be used for all sorts of tasks. For example:\n",
"\n",
"- **Generate a type of text**. For example, you can generate a poem, questions for a quiz etc.\n",
"- **Lookup information**. You can use prompts to look for information like the following example 'What does CORS mean in web development?'.\n",
"- **Generate code**. You can use prompts to generate code, for example developing a regular expression used to validate emails or why not generate an entire program, like a web app? \n",
"\n",
"## A more practical use case: a recipe generator\n",
"\n",
"Imagine you have ingredients at home and you want to cook something. For that, you need a recipe. A way to find recipes is to use a search engine or you could use an LLM to do so.\n",
"\n",
"You could write a prompt like so:\n",
"\n",
"> \"Show me 5 recipes for a dish with the following ingredients: chicken, potatoes, and carrots. Per recipe, list all the ingredients used\"\n",
"\n",
"Given the above prompt, you might get a response similar to:\n",
"\n",
"```output\n",
"1. Roasted Chicken and Vegetables: \n",
"Ingredients: \n",
"- 4 chicken thighs\n",
"- 2 potatoes, cut into cubes\n",
"- 2 carrots, cut into cubes\n",
"- 2 tablespoons olive oil\n",
"- 2 cloves garlic, minced\n",
"- 1 teaspoon dried thyme\n",
"- 1 teaspoon dried oregano\n",
"- Salt and pepper, to taste\n",
"\n",
"2. Chicken and Potato Stew: \n",
"Ingredients: \n",
"- 2 tablespoons olive oil\n",
"- 1 onion, diced\n",
"- 2 cloves garlic, minced\n",
"- 2 chicken breasts, cut into cubes\n",
"- 2 potatoes, cut into cubes\n",
"- 2 carrots, cut into cubes\n",
"- 1 teaspoon dried oregano\n",
"- 1 teaspoon dried thyme\n",
"- 1 cup chicken broth\n",
"- Salt and pepper, to taste\n",
"\n",
"3. Chicken and Potato Bake: \n",
"Ingredients: \n",
"- 2 tablespoons olive oil\n",
"- 2 chicken breasts, cut into cubes\n",
"- 2 potatoes, cut into cubes\n",
"- 2 carrots, cut into cubes\n",
"- 1 onion, diced\n",
"- 2 cloves garlic, minced\n",
"- 1 teaspoon dried oregano\n",
"- 1 teaspoon dried thyme\n",
"- 1 cup chicken broth\n",
"- Salt and pepper, to taste\n",
"\n",
"4. Chicken and Potato Soup: \n",
"Ingredients: \n",
"- 2 tablespoons olive oil\n",
"- 1 onion, diced\n",
"- 2 cloves garlic, minced\n",
"- 2 chicken breasts, cut into cubes\n",
"- 2 potatoes, cut into cubes\n",
"- 2 carrots, cut into cubes\n",
"- 1 teaspoon dried oregano\n",
"- 1 teaspoon dried thyme\n",
"- 4 cups chicken broth\n",
"- Salt and pepper, to taste\n",
"\n",
"5. Chicken and Potato Hash: \n",
"Ingredients: \n",
"- 2 tablespoons olive oil\n",
"- 2 chicken breasts, cut into cubes\n",
"- 2 potatoes, cut into cubes\n",
"- 2 carrots, cut into cubes\n",
"- 1 onion, diced\n",
"- 2 cloves garlic, minced\n",
"- 1 teaspoon dried oregano\n",
"```\n",
"\n",
"This outcome is great, I know what to cook. At this point, what could be useful improvements are:\n",
"\n",
"- Filtering out ingredients I don't like or am allergic to.\n",
"- Produce a shopping list, in case I don't have all the ingredients at home.\n",
"\n",
"For the above cases, let's add an additional prompt:\n",
"\n",
"> \"Please remove recipes with garlic as I'm allergic and replace it with something else. Also, please produce a shopping list for the recipes, considering I already have chicken, potatoes and carrots at home.\"\n",
"\n",
"Now you have a new result, namely:\n",
"\n",
"```output\n",
"1. Roasted Chicken and Vegetables: \n",
"Ingredients: \n",
"- 4 chicken thighs\n",
"- 2 potatoes, cut into cubes\n",
"- 2 carrots, cut into cubes\n",
"- 2 tablespoons olive oil\n",
"- 1 teaspoon dried thyme\n",
"- 1 teaspoon dried oregano\n",
"- Salt and pepper, to taste\n",
"\n",
"2. Chicken and Potato Stew: \n",
"Ingredients: \n",
"- 2 tablespoons olive oil\n",
"- 1 onion, diced\n",
"- 2 chicken breasts, cut into cubes\n",
"- 2 potatoes, cut into cubes\n",
"- 2 carrots, cut into cubes\n",
"- 1 teaspoon dried oregano\n",
"- 1 teaspoon dried thyme\n",
"- 1 cup chicken broth\n",
"- Salt and pepper, to taste\n",
"\n",
"3. Chicken and Potato Bake: \n",
"Ingredients: \n",
"- 2 tablespoons olive oil\n",
"- 2 chicken breasts, cut into cubes\n",
"- 2 potatoes, cut into cubes\n",
"- 2 carrots, cut into cubes\n",
"- 1 onion, diced\n",
"- 1 teaspoon dried oregano\n",
"- 1 teaspoon dried thyme\n",
"- 1 cup chicken broth\n",
"- Salt and pepper, to taste\n",
"\n",
"4. Chicken and Potato Soup: \n",
"Ingredients: \n",
"- 2 tablespoons olive oil\n",
"- 1 onion, diced\n",
"- 2 chicken breasts, cut into cubes\n",
"- 2 potatoes, cut into cubes\n",
"- 2 carrots, cut into cubes\n",
"- 1 teaspoon dried oregano\n",
"- 1 teaspoon dried thyme\n",
"- 4 cups chicken broth\n",
"- Salt and pepper, to taste\n",
"\n",
"5. Chicken and Potato Hash: \n",
"Ingredients: \n",
"- 2 tablespoons olive oil\n",
"- 2 chicken breasts, cut into cubes\n",
"- 2 potatoes, cut into cubes\n",
"- 2 carrots, cut into cubes\n",
"- 1 onion, diced\n",
"- 1 teaspoon dried oregano\n",
"\n",
"Shopping List: \n",
"- Olive oil\n",
"- Onion\n",
"- Thyme\n",
"- Oregano\n",
"- Salt\n",
"- Pepper\n",
"```\n",
"\n",
"That's your five recipes, with no garlic mentioned and you also have a shopping list considering what you already have at home. "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Exercise - build a recipe generator\n",
"\n",
"Now that we have played out a scenario, let's write code to match the demonstrated scenario. To do so, follow these steps:\n",
"\n",
"1. Use the existing *app.py* file as a starting point\n",
"1. Locate the `prompt` variable and change its code to the following:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"from openai import OpenAI\n",
"from dotenv import load_dotenv\n",
"\n",
"# load environment variables from .env file\n",
"load_dotenv()\n",
"\n",
"client = OpenAI(\n",
" api_key = os.environ['OPENAI_API_KEY']\n",
")\n",
"\n",
"deployment = \"gpt-4o-mini\"\n",
"\n",
"prompt = \"Show me 5 recipes for a dish with the following ingredients: chicken, potatoes, and carrots. Per recipe, list all the ingredients used\"\n",
"\n",
"# make a request using the Responses API\n",
"response = client.responses.create(model=deployment, input=prompt, max_output_tokens=600, store=False)\n",
"\n",
"# print response\n",
"print(response.output_text)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"If you now run the code, you should see an output similar to:\n",
"\n",
"```output\n",
"-Chicken Stew with Potatoes and Carrots: 3 tablespoons oil, 1 onion, chopped, 2 cloves garlic, minced, 1 carrot, peeled and chopped, 1 potato, peeled and chopped, 1 bay leaf, 1 thyme sprig, 1/2 teaspoon salt, 1/4 teaspoon black pepper, 1 1/2 cups chicken broth, 1/2 cup dry white wine, 2 tablespoons chopped fresh parsley, 2 tablespoons unsalted butter, 1 1/2 pounds boneless, skinless chicken thighs, cut into 1-inch pieces\n",
"-Oven-Roasted Chicken with Potatoes and Carrots: 3 tablespoons extra-virgin olive oil, 1 tablespoon Dijon mustard, 1 tablespoon chopped fresh rosemary, 1 tablespoon chopped fresh thyme, 4 cloves garlic, minced, 1 1/2 pounds small red potatoes, quartered, 1 1/2 pounds carrots, quartered lengthwise, 1/2 teaspoon salt, 1/4 teaspoon black pepper, 1 (4-pound) whole chicken\n",
"-Chicken, Potato, and Carrot Casserole: cooking spray, 1 large onion, chopped, 2 cloves garlic, minced, 1 carrot, peeled and shredded, 1 potato, peeled and shredded, 1/2 teaspoon dried thyme leaves, 1/4 teaspoon salt, 1/4 teaspoon black pepper, 2 cups fat-free, low-sodium chicken broth, 1 cup frozen peas, 1/4 cup all-purpose flour, 1 cup 2% reduced-fat milk, 1/4 cup grated Parmesan cheese\n",
"\n",
"-One Pot Chicken and Potato Dinner: 2 tablespoons olive oil, 1 pound boneless, skinless chicken thighs, cut into 1-inch pieces, 1 large onion, chopped, 3 cloves garlic, minced, 1 carrot, peeled and chopped, 1 potato, peeled and chopped, 1 bay leaf, 1 thyme sprig, 1/2 teaspoon salt, 1/4 teaspoon black pepper, 2 cups chicken broth, 1/2 cup dry white wine\n",
"\n",
"-Chicken, Potato, and Carrot Curry: 1 tablespoon vegetable oil, 1 large onion, chopped, 2 cloves garlic, minced, 1 carrot, peeled and chopped, 1 potato, peeled and chopped, 1 teaspoon ground coriander, 1 teaspoon ground cumin, 1/2 teaspoon ground turmeric, 1/2 teaspoon ground ginger, 1/4 teaspoon cayenne pepper, 2 cups chicken broth, 1/2 cup dry white wine, 1 (15-ounce) can chickpeas, drained and rinsed, 1/2 cup raisins, 1/2 cup chopped fresh cilantro\n",
"```\n",
"\n",
"> NOTE, your LLM is nondeterministic, so you might get different results every time you run the program.\n",
"\n",
"Great, let's see how we can improve things. To improve things, we want to make sure the code is flexible, so ingredients and number of recipes can be improved and changed. "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"1. Let's change the code in the following way:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"from openai import OpenAI\n",
"from dotenv import load_dotenv\n",
"\n",
"# load environment variables from .env file\n",
"load_dotenv()\n",
"\n",
"client = OpenAI(\n",
" api_key = os.environ['OPENAI_API_KEY']\n",
")\n",
"\n",
"deployment = \"gpt-4o-mini\"\n",
"\n",
"no_recipes = input(\"No of recipes (for example, 5: \")\n",
"\n",
"ingredients = input(\"List of ingredients (for example, chicken, potatoes, and carrots: \")\n",
"\n",
"# interpolate the number of recipes into the prompt an ingredients\n",
"prompt = f\"Show me {no_recipes} recipes for a dish with the following ingredients: {ingredients}. Per recipe, list all the ingredients used\"\n",
"\n",
"# make a request using the Responses API\n",
"response = client.responses.create(model=deployment, input=prompt, max_output_tokens=600, store=False)\n",
"\n",
"# print response\n",
"print(response.output_text)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Taking the code for a test run, could look like this:\n",
" \n",
"```output\n",
"No of recipes (for example, 5: 3\n",
"List of ingredients (for example, chicken, potatoes, and carrots: milk,strawberries\n",
"\n",
"-Strawberry milk shake: milk, strawberries, sugar, vanilla extract, ice cubes\n",
"-Strawberry shortcake: milk, flour, baking powder, sugar, salt, unsalted butter, strawberries, whipped cream \n",
"-Strawberry milk: milk, strawberries, sugar, vanilla extract\n",
"```\n",
"\n",
"### Improve by adding filter and shopping list\n",
"\n",
"We now have a working app capable of producing recipes and it's flexible as it relies on inputs from the user, both on the number of recipes but also the ingredients used.\n",
"\n",
"To further improve it, we want to add the following:\n",
"\n",
"- **Filter out ingredients**. We want to be able to filter out ingredients we don't like or are allergic to. To accomplish this change, we can edit our existing prompt and add a filter condition to the end of it like so:\n",
"\n",
" ```python\n",
" filter = input(\"Filter (for example, vegetarian, vegan, or gluten-free: \")\n",
"\n",
" prompt = f\"Show me {no_recipes} recipes for a dish with the following ingredients: {ingredients}. Per recipe, list all the ingredients used, no {filter}\"\n",
" ```\n",
"\n",
" Above, we add `{filter}` to the end of the prompt and we also capture the filter value from the user.\n",
"\n",
" An example input of running the program can now look like so:\n",
" \n",
" ```output \n",
" No of recipes (for example, 5: 3\n",
" List of ingredients (for example, chicken, potatoes, and carrots: onion,milk\n",
" Filter (for example, vegetarian, vegan, or gluten-free: no milk\n",
"\n",
" 1. French Onion Soup\n",
"\n",
" Ingredients:\n",
" \n",
" -1 large onion, sliced\n",
" -3 cups beef broth\n",
" -1 cup milk\n",
" -6 slices french bread\n",
" -1/4 cup shredded Parmesan cheese\n",
" -1 tablespoon butter\n",
" -1 teaspoon dried thyme\n",
" -1/4 teaspoon salt\n",
" -1/4 teaspoon black pepper\n",
" \n",
" Instructions:\n",
" \n",
" 1. In a large pot, sauté onions in butter until golden brown.\n",
" 2. Add beef broth, milk, thyme, salt, and pepper. Bring to a boil.\n",
" 3. Reduce heat and simmer for 10 minutes.\n",
" 4. Place french bread slices on soup bowls.\n",
" 5. Ladle soup over bread.\n",
" 6. Sprinkle with Parmesan cheese.\n",
" \n",
" 2. Onion and Potato Soup\n",
" \n",
" Ingredients:\n",
" \n",
" -1 large onion, chopped\n",
" -2 cups potatoes, diced\n",
" -3 cups vegetable broth\n",
" -1 cup milk\n",
" -1/4 teaspoon black pepper\n",
" \n",
" Instructions:\n",
" \n",
" 1. In a large pot, sauté onions in butter until golden brown.\n",
" 2. Add potatoes, vegetable broth, milk, and pepper. Bring to a boil.\n",
" 3. Reduce heat and simmer for 10 minutes.\n",
" 4. Serve hot.\n",
" \n",
" 3. Creamy Onion Soup\n",
" \n",
" Ingredients:\n",
" \n",
" -1 large onion, chopped\n",
" -3 cups vegetable broth\n",
" -1 cup milk\n",
" -1/4 teaspoon black pepper\n",
" -1/4 cup all-purpose flour\n",
" -1/2 cup shredded Parmesan cheese\n",
" \n",
" Instructions:\n",
" \n",
" 1. In a large pot, sauté onions in butter until golden brown.\n",
" 2. Add vegetable broth, milk, and pepper. Bring to a boil.\n",
" 3. Reduce heat and simmer for 10 minutes.\n",
" 4. In a small bowl, whisk together flour and Parmesan cheese until smooth.\n",
" 5. Add to soup and simmer for an additional 5 minutes, or until soup has thickened.\n",
" ```\n",
"\n",
" As you can see, any recipes with milk in it has been filtered out. But, if you're lactose intolerant, you might want to filter out recipes with cheese in them as well, so there's a need to be clear.\n",
"\n",
"- **Produce a shopping list**. We want to produce a shopping list, considering what we already have at home.\n",
"\n",
" For this functionality, we could either try to solve everything in one prompt or we could split it up into two prompts. Let's try the latter approach. Here we're suggesting adding an additional prompt, but for that to work, we need to add the result of the former prompt as context to the latter prompt. \n",
"\n",
" Locate the part in the code that prints out the result from the first prompt and add the following code below:\n",
" \n",
" ```python\n",
" old_prompt_result = response.output_text\n",
" prompt = \"Produce a shopping list for the generated recipes and please don't include ingredients that I already have.\"\n",
" \n",
" new_prompt = f\"{old_prompt_result} {prompt}\"\n",
" messages = [{\"role\": \"user\", \"content\": new_prompt}]\n",
" response = client.responses.create(model=deployment, input=messages, max_output_tokens=1200, store=False)\n",
" \n",
" # print response\n",
" print(\"Shopping list:\")\n",
" print(response.output_text)\n",
" ```\n",
"\n",
" Note the following:\n",
"\n",
" - We're constructing a new prompt by adding the result from the first prompt to the new prompt: \n",
" \n",
" ```python\n",
" new_prompt = f\"{old_prompt_result} {prompt}\"\n",
" messages = [{\"role\": \"user\", \"content\": new_prompt}]\n",
" ```\n",
"\n",
" - We make a new request, but also considering the number of tokens we asked for in the first prompt, so this time we say `max_output_tokens` is 1200. \n",
"\n",
" ```python\n",
" response = client.responses.create(model=deployment, input=messages, max_output_tokens=1200, store=False)\n",
" ``` \n",
"\n",
" Taking this code for a spin, we now arrive at the following output:\n",
"\n",
" ```output\n",
" No of recipes (for example, 5: 2\n",
" List of ingredients (for example, chicken, potatoes, and carrots: apple,flour\n",
" Filter (for example, vegetarian, vegan, or gluten-free: sugar\n",
" Recipes:\n",
" or milk.\n",
" \n",
" -Apple and flour pancakes: 1 cup flour, 1/2 tsp baking powder, 1/2 tsp baking soda, 1/4 tsp salt, 1 tbsp sugar, 1 egg, 1 cup buttermilk or sour milk, 1/4 cup melted butter, 1 Granny Smith apple, peeled and grated\n",
" -Apple fritters: 1-1/2 cups flour, 1 tsp baking powder, 1/4 tsp salt, 1/4 tsp baking soda, 1/4 tsp nutmeg, 1/4 tsp cinnamon, 1/4 tsp allspice, 1/4 cup sugar, 1/4 cup vegetable shortening, 1/4 cup milk, 1 egg, 2 cups shredded, peeled apples\n",
" Shopping list:\n",
" -Flour, baking powder, baking soda, salt, sugar, egg, buttermilk, butter, apple, nutmeg, cinnamon, allspice \n",
" ```\n",
" \n",
"- **A word on token length**. We should consider how many tokens we need to generate the text we want. Tokens cost money, so where possible, we should try to be economical with the number of tokens we use. For example, can we phrase the prompt so that we can use less tokens?\n",
"\n",
" To change tokens used, you can use the `max_output_tokens` parameter. For example, if you want to use 100 tokens, you would do:\n",
"\n",
" ```python\n",
" response = client.responses.create(model=deployment, input=messages, max_output_tokens=100, store=False)\n",
" ```\n",
"\n",
"- **Experimenting with temperature**. Temperature is something we haven't mentioned so far but is an important context for how our program performs. The higher the temperature value the more random the output will be. Conversely the lower the temperature value the more predictable the output will be. Consider whether you want variation in your output or not.\n",
"\n",
" To alter the temperature, you can use the `temperature` parameter. For example, if you want to use a temperature of 0.5, you would do:\n",
"\n",
" ```python\n",
" response = client.responses.create(model=deployment, input=messages, temperature=0.5, store=False)\n",
" ```\n",
"\n",
" > Note, the closer to 1.0, the more varied the output.\n",
"\n",
"\n",
"\n",
"## Assignment\n",
"\n",
"For this assignment, you can choose what to build.\n",
"\n",
"Here are some suggestions:\n",
"\n",
"- Tweak the recipe generator app to improve it further. Play around with temperature values, and the prompts to see what you can come up with.\n",
"- Build a \"study buddy\". This app should be able to answer questions about a topic for example Python, you could have prompts like \"What is a certain topic in Python?\", or you could have a prompt that says, show me code for a certain topic etc.\n",
"- History bot, make history come alive, instruct the bot to play a certain historical character and ask it questions about its life and times. \n",
"\n",
"## Solution\n",
"\n",
"### Study buddy\n",
"\n",
"- \"You're an expert on the Python language\n",
"\n",
" Suggest a beginner lesson for Python in the following format:\n",
" \n",
" Format:\n",
" - concepts:\n",
" - brief explanation of the lesson:\n",
" - exercise in code with solutions\"\n",
"\n",
"Above is a starter prompt, see how you can use it and tweak it to your liking.\n",
"\n",
"### History bot\n",
"\n",
"Here's some prompts you could be using:\n",
"\n",
"- \"You are Abe Lincoln, tell me about yourself in 3 sentences, and respond using grammar and words like Abe would have used\"\n",
"- \"You are Abe Lincoln, respond using grammar and words like Abe would have used:\n",
"\n",
" Tell me about your greatest accomplishments, in 300 words:\"\n",
"\n",
"## Knowledge check\n",
"\n",
"What does the concept temperature do?\n",
"\n",
"1. It controls how random the output is.\n",
"1. It controls how big the response is.\n",
"1. It controls how many tokens are used.\n",
"\n",
"A: 1\n",
"\n",
"What's a good way to store secrets like API keys?\n",
"\n",
"1. In code.\n",
"1. In a file.\n",
"1. In environment variables.\n",
"\n",
"A: 3, because environment variables are not stored in code and can be loaded from the code. \n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "venv",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.9"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
@@ -0,0 +1,30 @@
from openai import OpenAI
import os
from dotenv import load_dotenv
# load environment variables from .env file
load_dotenv()
# configure OpenAI service client
client = OpenAI()
deployment="gpt-4o-mini"
# add your completion code
persona = input("Tell me the historical character I want to be: ")
question = input("Ask your question about the historical character: ")
prompt = f"""
You are going to play as a historical character {persona}.
Whenever certain questions are asked, you need to remember facts about the timelines and incidents and respond the accurate answer only. Don't create content yourself. If you don't know something, tell that you don't remember.
Provide answer for the question: {question}
"""
# make a request using the Responses API
response = client.responses.create(model=deployment, input=prompt, store=False)
# print response
print(response.output_text)
# very unhappy _____.
# Once upon a time there was a very unhappy mermaid.
@@ -0,0 +1,33 @@
from openai import OpenAI
import os
from dotenv import load_dotenv
# load environment variables from .env file
load_dotenv()
# configure Azure OpenAI service client
client = OpenAI()
deployment="gpt-4o-mini"
# add your completion code
question = input("Ask your questions on python language to your study buddy: ")
prompt = f"""
You are an expert on the python language.
Whenever certain questions are asked, you need to provide response in below format.
- Concept
- Example code showing the concept implementation
- explanation of the example and how the concept is done for the user to understand better.
Provide answer for the question: {question}
"""
# make a request using the Responses API
response = client.responses.create(model=deployment, input=prompt, store=False)
# print response
print(response.output_text)
# very unhappy _____.
# Once upon a time there was a very unhappy mermaid.
@@ -0,0 +1,2 @@
openai==1.55.1
python-dotenv==1.2.2