From 66e5502d372578d1b34bcad8f15f1132c45ea9f3 Mon Sep 17 00:00:00 2001
From: jhills20 <70035505+jhills20@users.noreply.github.com>
Date: Fri, 8 Dec 2023 16:45:55 -0800
Subject: [PATCH] Submitting new notebook on creating slides with Assistants
API and DE3 (#862)
---
...ides_with_Assistants_API_and_DALL-E3.ipynb | 992 ++++++++++++++++++
examples/data/NotRealCorp_financial_data.json | 1 +
examples/data/created_slides.pptx | Bin 0 -> 2107240 bytes
images/NotRealCorp_chart.png | Bin 0 -> 185111 bytes
images/dalle_image.png | Bin 0 -> 3147861 bytes
images/data_vis_slide.png | Bin 0 -> 446126 bytes
images/title_slide.png | Bin 0 -> 4284093 bytes
registry.yaml | 10 +
8 files changed, 1003 insertions(+)
create mode 100644 examples/Creating_slides_with_Assistants_API_and_DALL-E3.ipynb
create mode 100644 examples/data/NotRealCorp_financial_data.json
create mode 100644 examples/data/created_slides.pptx
create mode 100644 images/NotRealCorp_chart.png
create mode 100644 images/dalle_image.png
create mode 100644 images/data_vis_slide.png
create mode 100644 images/title_slide.png
diff --git a/examples/Creating_slides_with_Assistants_API_and_DALL-E3.ipynb b/examples/Creating_slides_with_Assistants_API_and_DALL-E3.ipynb
new file mode 100644
index 0000000..c37116f
--- /dev/null
+++ b/examples/Creating_slides_with_Assistants_API_and_DALL-E3.ipynb
@@ -0,0 +1,992 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Creating slides with the Assistants API (GPT-4), and DALL·E-3\n",
+ "\n",
+ "This notebook illustrates the use of the new [Assistants API](https://platform.openai.com/docs/assistants/overview) (GPT-4), and DALL·E-3 in crafting informative and visually appealing slides.
\n",
+ "Creating engaging slides is a pivotal aspect of many jobs, but it can be a laborious and time-consuming task. Additionally, extracting insights from data and articulating them effectively on slides can be challenging.
This cookbook recipe will demonstrate how you can utilize the new Assistants API to faciliate the end to end slide creation process for you without you having to touch Microsoft PowerPoint or Google Slides, saving you valuable time and effort!"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## 0. Setup"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from IPython.display import display, Image\n",
+ "from openai import OpenAI\n",
+ "import pandas as pd\n",
+ "import json\n",
+ "import io\n",
+ "from PIL import Image\n",
+ "import requests\n",
+ "\n",
+ "client = OpenAI()\n",
+ "\n",
+ "#Lets import some helper functions for assistants from https://cookbook.openai.com/examples/assistants_api_overview_python\n",
+ "def show_json(obj):\n",
+ " display(json.loads(obj.model_dump_json()))\n",
+ "\n",
+ "def submit_message(assistant_id, thread, user_message,file_ids=None):\n",
+ " params = {\n",
+ " 'thread_id': thread.id,\n",
+ " 'role': 'user',\n",
+ " 'content': user_message,\n",
+ " }\n",
+ " if file_ids:\n",
+ " params['file_ids']=file_ids\n",
+ "\n",
+ " client.beta.threads.messages.create(\n",
+ " **params\n",
+ ")\n",
+ " return client.beta.threads.runs.create(\n",
+ " thread_id=thread.id,\n",
+ " assistant_id=assistant_id,\n",
+ ")\n",
+ "\n",
+ "def get_response(thread):\n",
+ " return client.beta.threads.messages.list(thread_id=thread.id)\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## 1. Creating the content"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "In this recipe, we will be creating a brief fictional presentation for the quarterly financial review of our company, NotReal Corporation. We want to highlight some key trends we are seeing that are affecting the profitability of our company.
Let's say we have the some financial data at our disposal. Let's load in the data, and take a look..."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "
\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " Year | \n",
+ " Quarter | \n",
+ " Distribution channel | \n",
+ " Revenue ($M) | \n",
+ " Costs ($M) | \n",
+ " Customer count | \n",
+ " Time | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 2021 | \n",
+ " Q1 | \n",
+ " Online Sales | \n",
+ " 1.50 | \n",
+ " 1.301953 | \n",
+ " 150 | \n",
+ " 2021 Q1 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 2021 | \n",
+ " Q1 | \n",
+ " Direct Sales | \n",
+ " 1.50 | \n",
+ " 1.380809 | \n",
+ " 151 | \n",
+ " 2021 Q1 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 2021 | \n",
+ " Q1 | \n",
+ " Retail Partners | \n",
+ " 1.50 | \n",
+ " 1.348246 | \n",
+ " 152 | \n",
+ " 2021 Q1 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 2021 | \n",
+ " Q2 | \n",
+ " Online Sales | \n",
+ " 1.52 | \n",
+ " 1.308608 | \n",
+ " 152 | \n",
+ " 2021 Q2 | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " 2021 | \n",
+ " Q2 | \n",
+ " Direct Sales | \n",
+ " 1.52 | \n",
+ " 1.413305 | \n",
+ " 153 | \n",
+ " 2021 Q2 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " Year Quarter Distribution channel Revenue ($M) Costs ($M) \\\n",
+ "0 2021 Q1 Online Sales 1.50 1.301953 \n",
+ "1 2021 Q1 Direct Sales 1.50 1.380809 \n",
+ "2 2021 Q1 Retail Partners 1.50 1.348246 \n",
+ "3 2021 Q2 Online Sales 1.52 1.308608 \n",
+ "4 2021 Q2 Direct Sales 1.52 1.413305 \n",
+ "\n",
+ " Customer count Time \n",
+ "0 150 2021 Q1 \n",
+ "1 151 2021 Q1 \n",
+ "2 152 2021 Q1 \n",
+ "3 152 2021 Q2 \n",
+ "4 153 2021 Q2 "
+ ]
+ },
+ "execution_count": 2,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "financial_data_path = 'data/NotRealCorp_financial_data.json'\n",
+ "financial_data = pd.read_json(financial_data_path)\n",
+ "financial_data.head(5)\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "As you can see, this data has quarterly revenue, costs and customer data across different distribution channels. Let's create an Assistant\n",
+ "that can act as a personal analyst and make a nice visualization for our PowerPoint!"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "First, we need to upload our file so our Assistant can access it."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "file = client.files.create(\n",
+ " file=open('data/NotRealCorp_financial_data.json',\"rb\"),\n",
+ " purpose='assistants',\n",
+ ")\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Now, we're ready to create our Assistant. We can instruct our assistant to act as a data scientist, and take any queries we give it and run the necessary code to output the proper data visualization. The instructions parameter here is akin to system instructions in the ChatCompletions endpoint, and can help guide the assistant. We can also turn on the tool of Code Interpreter, so our Assistant will be able to code. Finally, we can specifiy any files we want to use, which in this case is just the `financial_data` file we created above."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "assistant = client.beta.assistants.create(\n",
+ " instructions=\"You are a data scientist assistant. When given data and a query, write the proper code and create the proper visualization\",\n",
+ " model=\"gpt-4-1106-preview\",\n",
+ " tools=[{\"type\": \"code_interpreter\"}],\n",
+ " file_ids=[file.id]\n",
+ ")\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Let's create a thread now, and as our first request ask the Assistant to calculate quarterly profits, and then plot the profits by distribution channel over time. The assistant will automatically calculate the profit for each quarter, and also create a new column combining quarter and year, without us having to ask for that directly. We can also specify the colors of each line."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "thread = client.beta.threads.create(\n",
+ " messages=[\n",
+ " {\n",
+ " \"role\": \"user\",\n",
+ " \"content\": \"Calculate profit (revenue minus cost) by quarter and year, and visualize as a line plot across the distribution channels, where the colors of the lines are green, light red, and light blue\",\n",
+ " \"file_ids\": [file.id]\n",
+ " }\n",
+ " ]\n",
+ ")\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "No we can execute the run of our thread"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "\n",
+ "run = client.beta.threads.runs.create(\n",
+ " thread_id=thread.id,\n",
+ " assistant_id=assistant.id,\n",
+ ")\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "We can now start a loop that will check if the image has been created. Note: This may take a few minutes"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "messages = client.beta.threads.messages.list(thread_id=thread.id)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Assistant still working...\n",
+ "Assistant still working...\n",
+ "Assistant still working...\n",
+ "Assistant still working...\n",
+ "Assistant still working...\n",
+ "Assistant still working...\n",
+ "Assistant still working...\n",
+ "Assistant still working...\n",
+ "Assistant still working...\n",
+ "Assistant still working...\n",
+ "Assistant still working...\n",
+ "Assistant still working...\n",
+ "Assistant still working...\n",
+ "Assistant still working...\n",
+ "Assistant still working...\n",
+ "Assistant still working...\n",
+ "Assistant still working...\n",
+ "Plot created!\n"
+ ]
+ }
+ ],
+ "source": [
+ "import time\n",
+ "\n",
+ "while True:\n",
+ " messages = client.beta.threads.messages.list(thread_id=thread.id)\n",
+ " try:\n",
+ " #See if image has been created\n",
+ " messages.data[0].content[0].image_file\n",
+ " #Sleep to make sure run has completed\n",
+ " time.sleep(5)\n",
+ " print('Plot created!')\n",
+ " break\n",
+ " except:\n",
+ " time.sleep(10)\n",
+ " print('Assistant still working...')\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Let's see the messages the Assistant added."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "[MessageContentImageFile(image_file=ImageFile(file_id='file-0rKABLygI02MgwwhpgWdRFY1'), type='image_file'),\n",
+ " MessageContentText(text=Text(annotations=[], value=\"The profit has been calculated for each distribution channel by quarter and year. Next, I'll create a line plot to visualize these profits. As specified, I will use green for the 'Online Sales', light red for 'Direct Sales', and light blue for 'Retail Partners' channels. Let's create the plot.\"), type='text'),\n",
+ " MessageContentText(text=Text(annotations=[], value=\"The JSON data has been successfully restructured into a tabular dataframe format. It includes the year, quarter, distribution channel, revenue, costs, customer count, and a combined 'Time' representation of 'Year Quarter'. Now, we have the necessary information to calculate the profit (revenue minus cost) by quarter and year.\\n\\nTo visualize the profit across the different distribution channels with a line plot, we will proceed with the following steps:\\n\\n1. Calculate the profit for each row in the dataframe.\\n2. Group the data by 'Time' (which is a combination of Year and Quarter) and 'Distribution channel'.\\n3. Aggregate the profit for each group.\\n4. Plot the aggregated profits as a line plot with the distribution channels represented in different colors as requested.\\n\\nLet's calculate the profit for each row and then continue with the visualization.\"), type='text'),\n",
+ " MessageContentText(text=Text(annotations=[], value='The structure of the JSON data shows that it is a dictionary with \"Year\", \"Quarter\", \"Distribution channel\", and potentially other keys that map to dictionaries containing the data. The keys of the inner dictionaries are indices, indicating that the data is tabular but has been converted into a JSON object.\\n\\nTo properly convert this data into a DataFrame, I will restructure the JSON data into a more typical list of dictionaries, where each dictionary represents a row in our target DataFrame. Subsequent to this restructuring, I can then load the data into a Pandas DataFrame. Let\\'s restructure and load the data.'), type='text'),\n",
+ " MessageContentText(text=Text(annotations=[], value=\"The JSON data has been incorrectly loaded into a single-row DataFrame with numerous columns representing each data point. This implies the JSON structure is not as straightforward as expected, and a direct conversion to a flat table is not possible without further processing.\\n\\nTo better understand the JSON structure and figure out how to properly normalize it into a table format, I will print out the raw JSON data structure. We will analyze its format and then determine the correct approach to extract the profit by quarter and year, as well as the distribution channel information. Let's take a look at the JSON structure.\"), type='text'),\n",
+ " MessageContentText(text=Text(annotations=[], value=\"It seems that the file content was successfully parsed as JSON, and thus, there was no exception raised. The variable `error_message` is not defined because the `except` block was not executed.\\n\\nI'll proceed with displaying the data that was parsed from JSON.\"), type='text'),\n",
+ " MessageContentText(text=Text(annotations=[], value=\"It appears that the content of the dataframe has been incorrectly parsed, resulting in an empty dataframe with a very long column name that seems to contain JSON data rather than typical CSV columns and rows.\\n\\nTo address this issue, I will take a different approach to reading the file. I will attempt to parse the content as JSON. If this is not successful, I'll adjust the loading strategy accordingly. Let's try to read the contents as JSON data first.\"), type='text'),\n",
+ " MessageContentText(text=Text(annotations=[], value=\"Before we can calculate profits and visualize the data as requested, I need to first examine the contents of the file that you have uploaded. Let's go ahead and read the file to understand its structure and the kind of data it contains. Once I have a clearer picture of the dataset, we can proceed with the profit calculations. I'll begin by loading the file into a dataframe and displaying the first few entries to see the data schema.\"), type='text'),\n",
+ " MessageContentText(text=Text(annotations=[], value='Calculate profit (revenue minus cost) by quarter and year, and visualize as a line plot across the distribution channels, where the colors of the lines are green, light red, and light blue'), type='text')]"
+ ]
+ },
+ "execution_count": 9,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "messages = client.beta.threads.messages.list(thread_id=thread.id)\n",
+ "[message.content[0] for message in messages.data]\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "We can see that the last message (latest message is shown first) from the assistant contains the image file we are looking for. An interesting note here is that the Assistant was able to attempt several times to parse the JSON data, as the first parsing was unsuccessful, demonstrating the assistant's adaptability."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Quick helper function to convert our output file to a png\n",
+ "def convert_file_to_png(file_id, write_path):\n",
+ " data = client.files.content(file_id)\n",
+ " data_bytes = data.read()\n",
+ " with open(write_path, \"wb\") as file:\n",
+ " file.write(data_bytes)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plot_file_id = messages.data[0].content[0].image_file.file_id\n",
+ "image_path = \"../images/NotRealCorp_chart.png\"\n",
+ "convert_file_to_png(plot_file_id,image_path)\n",
+ "\n",
+ "#Upload\n",
+ "plot_file = client.files.create(\n",
+ " file=open(image_path, \"rb\"),\n",
+ " purpose='assistants'\n",
+ ")\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Let's load in the plot!"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ ""
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Nice! So, with just one sentence, we were able to have our assistant use code interpreter to\n",
+ "calculate the profitability, and graph the three lineplots of the various distribution channels.
\n",
+ "Now we have a nice visual for our slide, but we want some insights to go along with it."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## 2. Generating insights"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "To get insights from our image, we simply need to add a new message to our thread. Our Assistant will know to use the message history to give us some concise takeaways from the visual provided. "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "Run(id='run_NWoygMcBfHUr58fCE4Cn6rxN', assistant_id='asst_3T362kLlTyAq0FUnkvjjQczO', cancelled_at=None, completed_at=None, created_at=1701827074, expires_at=1701827674, failed_at=None, file_ids=['file-piTokyHGllwGITzIpoG8dok3'], instructions='You are a data scientist assistant. When given data and a query, write the proper code and create the proper visualization', last_error=None, metadata={}, model='gpt-4-1106-preview', object='thread.run', required_action=None, started_at=None, status='queued', thread_id='thread_73TgtFoJMlEJvb13ngjTnAo3', tools=[ToolAssistantToolsCode(type='code_interpreter')])"
+ ]
+ },
+ "execution_count": 12,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "submit_message(assistant.id,thread,\"Give me two medium length sentences (~20-30 words per sentence) of the \\\n",
+ " most important insights from the plot you just created.\\\n",
+ " These will be used for a slide deck, and they should be about the\\\n",
+ " 'so what' behind the data.\"\n",
+ ")\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Now, once the run has completed, we can see the latest message"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 13,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "The plot reveals a consistent upward trend in profits for all distribution channels, indicating successful business growth over time. Particularly, 'Online Sales' shows a notable increase, underscoring the importance of digital presence in revenue generation.\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Hard coded wait for a response, as the assistant may iterate on the bullets.\n",
+ "time.sleep(10)\n",
+ "response = get_response(thread)\n",
+ "bullet_points = response.data[0].content[0].text.value\n",
+ "print(bullet_points)\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Cool! So our assistant was able to identify the noteworthy growth in Online Sales profit, and infer that this shows the importance of a large digital presence. Now let's get a compelling title for the slide."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 14,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "Run(id='run_q6E85J31jCw3QkHpjJKl969P', assistant_id='asst_3T362kLlTyAq0FUnkvjjQczO', cancelled_at=None, completed_at=None, created_at=1701827084, expires_at=1701827684, failed_at=None, file_ids=['file-piTokyHGllwGITzIpoG8dok3'], instructions='You are a data scientist assistant. When given data and a query, write the proper code and create the proper visualization', last_error=None, metadata={}, model='gpt-4-1106-preview', object='thread.run', required_action=None, started_at=None, status='queued', thread_id='thread_73TgtFoJMlEJvb13ngjTnAo3', tools=[ToolAssistantToolsCode(type='code_interpreter')])"
+ ]
+ },
+ "execution_count": 14,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "submit_message(assistant.id,thread,\"Given the plot and bullet points you created,\\\n",
+ " come up with a very brief title for a slide. It should reflect just the main insights you came up with.\"\n",
+ ")\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "And the title is:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 15,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\"Ascending Profits & Digital Dominance\"\n"
+ ]
+ }
+ ],
+ "source": [
+ "#Wait as assistant may take a few steps\n",
+ "time.sleep(10)\n",
+ "response = get_response(thread)\n",
+ "title = response.data[0].content[0].text.value\n",
+ "print(title)\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## 3. DALL·E-3 title image"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Nice, now we have a title, a plot and two bullet points. We're almost ready to put this all on a slide, but as a final step, let's have DALL·E-3 come up with an image to use as the title slide of the presentation.
\n",
+ "*Note:* DALL·E-3 is not yet available within the assistants API but is coming soon!
\n",
+ "We'll feed in a brief description of our company (NotRealCorp) and have DALL·E-3 do the rest!"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 16,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "company_summary = \"NotReal Corp is a prominent hardware company that manufactures and sells processors, graphics cards and other essential computer hardware.\"\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 17,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "response = client.images.generate(\n",
+ " model='dall-e-3',\n",
+ " prompt=f\"given this company summary {company_summary}, create an inspirational \\\n",
+ " photo showing the growth and path forward. This will be used at a quarterly\\\n",
+ " financial planning meeting\",\n",
+ " size=\"1024x1024\",\n",
+ " quality=\"hd\",\n",
+ " n=1\n",
+ ")\n",
+ "image_url = response.data[0].url\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Cool, now we can add this image to our thread. First, we can save the image locally, then upload it to the assistants API using the `File` upload endpoint. Let's also take a look at our image"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 18,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "dalle_img_path = '../images/dalle_image.png'\n",
+ "img = requests.get(image_url)\n",
+ "\n",
+ "#Save locally\n",
+ "with open(dalle_img_path,'wb') as file:\n",
+ " file.write(img.content)\n",
+ "\n",
+ "#Upload\n",
+ "dalle_file = client.files.create(\n",
+ " file=open(dalle_img_path, \"rb\"),\n",
+ " purpose='assistants'\n",
+ ")\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ " \n",
+ ""
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## 4. Creating the slides"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "We now have all the content we need to create the slides. While we could simply add a message asking for slides, but let's instead give the assistant a slide template, using the `python-pptx` library, to use. This will ensure we get a deck in the style we want. See the `Extensions` section at the end of the notebook for notes on creating the template."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 19,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "title_template = \"\"\"\n",
+ "from pptx import Presentation\n",
+ "from pptx.util import Inches, Pt\n",
+ "from pptx.enum.text import PP_PARAGRAPH_ALIGNMENT\n",
+ "from pptx.dml.color import RGBColor\n",
+ "\n",
+ "# Create a new presentation object\n",
+ "prs = Presentation()\n",
+ "\n",
+ "# Add a blank slide layout\n",
+ "blank_slide_layout = prs.slide_layouts[6]\n",
+ "slide = prs.slides.add_slide(blank_slide_layout)\n",
+ "\n",
+ "# Set the background color of the slide to black\n",
+ "background = slide.background\n",
+ "fill = background.fill\n",
+ "fill.solid()\n",
+ "fill.fore_color.rgb = RGBColor(0, 0, 0)\n",
+ "\n",
+ "# Add image to the left side of the slide with a margin at the top and bottom\n",
+ "left = Inches(0)\n",
+ "top = Inches(0)\n",
+ "height = prs.slide_height\n",
+ "width = prs.slide_width * 3/5\n",
+ "pic = slide.shapes.add_picture(image_path, left, top, width=width, height=height)\n",
+ "\n",
+ "# Add title text box positioned higher\n",
+ "left = prs.slide_width * 3/5\n",
+ "top = Inches(2)\n",
+ "width = prs.slide_width * 2/5\n",
+ "height = Inches(1)\n",
+ "title_box = slide.shapes.add_textbox(left, top, width, height)\n",
+ "title_frame = title_box.text_frame\n",
+ "title_p = title_frame.add_paragraph()\n",
+ "title_p.text = title_text\n",
+ "title_p.font.bold = True\n",
+ "title_p.font.size = Pt(38)\n",
+ "title_p.font.color.rgb = RGBColor(255, 255, 255)\n",
+ "title_p.alignment = PP_PARAGRAPH_ALIGNMENT.CENTER\n",
+ "\n",
+ "# Add subtitle text box\n",
+ "left = prs.slide_width * 3/5\n",
+ "top = Inches(3)\n",
+ "width = prs.slide_width * 2/5\n",
+ "height = Inches(1)\n",
+ "subtitle_box = slide.shapes.add_textbox(left, top, width, height)\n",
+ "subtitle_frame = subtitle_box.text_frame\n",
+ "subtitle_p = subtitle_frame.add_paragraph()\n",
+ "subtitle_p.text = subtitle_text\n",
+ "subtitle_p.font.size = Pt(22)\n",
+ "subtitle_p.font.color.rgb = RGBColor(255, 255, 255)\n",
+ "subtitle_p.alignment = PP_PARAGRAPH_ALIGNMENT.CENTER\n",
+ "\"\"\"\n",
+ "\n",
+ "data_vis_template = \"\"\"\n",
+ "from pptx import Presentation\n",
+ "from pptx.util import Inches, Pt\n",
+ "from pptx.enum.text import PP_PARAGRAPH_ALIGNMENT\n",
+ "from pptx.dml.color import RGBColor\n",
+ "\n",
+ "# Create a new presentation object\n",
+ "prs = Presentation()\n",
+ "\n",
+ "# Add a blank slide layout\n",
+ "blank_slide_layout = prs.slide_layouts[6]\n",
+ "slide = prs.slides.add_slide(blank_slide_layout)\n",
+ "\n",
+ "# Set the background color of the slide to black\n",
+ "background = slide.background\n",
+ "fill = background.fill\n",
+ "fill.solid()\n",
+ "fill.fore_color.rgb = RGBColor(0, 0, 0)\n",
+ "\n",
+ "# Define placeholders\n",
+ "image_path = data_vis_img\n",
+ "title_text = \"Maximizing Profits: The Dominance of Online Sales & Direct Sales Optimization\"\n",
+ "bullet_points = \"• Online Sales consistently lead in profitability across quarters, indicating a strong digital market presence.\\n• Direct Sales show fluctuations, suggesting variable performance and the need for targeted improvements in that channel.\"\n",
+ "\n",
+ "# Add image placeholder on the left side of the slide\n",
+ "left = Inches(0.2)\n",
+ "top = Inches(1.8)\n",
+ "height = prs.slide_height - Inches(3)\n",
+ "width = prs.slide_width * 3/5\n",
+ "pic = slide.shapes.add_picture(image_path, left, top, width=width, height=height)\n",
+ "\n",
+ "# Add title text spanning the whole width\n",
+ "left = Inches(0)\n",
+ "top = Inches(0)\n",
+ "width = prs.slide_width\n",
+ "height = Inches(1)\n",
+ "title_box = slide.shapes.add_textbox(left, top, width, height)\n",
+ "title_frame = title_box.text_frame\n",
+ "title_frame.margin_top = Inches(0.1)\n",
+ "title_p = title_frame.add_paragraph()\n",
+ "title_p.text = title_text\n",
+ "title_p.font.bold = True\n",
+ "title_p.font.size = Pt(28)\n",
+ "title_p.font.color.rgb = RGBColor(255, 255, 255)\n",
+ "title_p.alignment = PP_PARAGRAPH_ALIGNMENT.CENTER\n",
+ "\n",
+ "# Add hardcoded \"Key Insights\" text and bullet points\n",
+ "left = prs.slide_width * 2/3\n",
+ "top = Inches(1.5)\n",
+ "width = prs.slide_width * 1/3\n",
+ "height = Inches(4.5)\n",
+ "insights_box = slide.shapes.add_textbox(left, top, width, height)\n",
+ "insights_frame = insights_box.text_frame\n",
+ "insights_p = insights_frame.add_paragraph()\n",
+ "insights_p.text = \"Key Insights:\"\n",
+ "insights_p.font.bold = True\n",
+ "insights_p.font.size = Pt(24)\n",
+ "insights_p.font.color.rgb = RGBColor(0, 128, 100)\n",
+ "insights_p.alignment = PP_PARAGRAPH_ALIGNMENT.LEFT\n",
+ "insights_frame.add_paragraph()\n",
+ "\n",
+ "\n",
+ "bullet_p = insights_frame.add_paragraph()\n",
+ "bullet_p.text = bullet_points\n",
+ "bullet_p.font.size = Pt(12)\n",
+ "bullet_p.font.color.rgb = RGBColor(255, 255, 255)\n",
+ "bullet_p.line_spacing = 1.5\n",
+ "\"\"\"\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Let's set a few quick variables for our slides. We want the company name, NotRealCorp, to be on the title slide, and the title of the presentation should 'Quartlerly financial planning metting, Q3, 2023'."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 20,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "title_text = \"NotRealCorp\"\n",
+ "subtitle_text = \"Quarterly financial planning meeting, Q3 2023\"\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "And for the data slide, we have:"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Here we have a template to create a Title Slide. The template below was created by uploading the image of a desirable title slide to GPT-V, and asking for the `python-pptx` code to create that template. The inputs to the template are the image_path, title_text, and subtitle_text."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 21,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "Run(id='run_taLrnOnlDhoywgQFFBOLPlg0', assistant_id='asst_3T362kLlTyAq0FUnkvjjQczO', cancelled_at=None, completed_at=None, created_at=1701827118, expires_at=1701827718, failed_at=None, file_ids=['file-piTokyHGllwGITzIpoG8dok3'], instructions='You are a data scientist assistant. When given data and a query, write the proper code and create the proper visualization', last_error=None, metadata={}, model='gpt-4-1106-preview', object='thread.run', required_action=None, started_at=None, status='queued', thread_id='thread_73TgtFoJMlEJvb13ngjTnAo3', tools=[ToolAssistantToolsCode(type='code_interpreter')])"
+ ]
+ },
+ "execution_count": 21,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "submit_message(assistant.id,thread,f\"Use the included code template to create a PPTX slide that follows the template format, but uses the image, company name/title, and document name/subtitle included:\\\n",
+ "{title_template}. IMPORTANT: Use the image file included in this message as the image_path image in this first slide, and use the Company Name {title_text} as the title_text variable, and \\\n",
+ " use the subtitle_text {subtitle_text} a the subtitle_text variable. \\\n",
+ " NEST, create a SECOND slide using the following code template: {data_vis_template} to create a PPTX slide that follows the template format, but uses the company name/title, and document name/subtitle included:\\\n",
+ "{data_vis_template}. IMPORTANT: Use the line plot image, that is the second attached image in this message, that you created earlier in the thread as the data_vis_img image, and use the data visualization title that you created earlier for the variable title_text, and\\\n",
+ " the bullet points of insights you created earlier for the bullet_points variable. Output these TWO SLIDES as a .pptx file. Make sure the output is two slides, with each slide matching the respective template given in this message.\",\n",
+ " file_ids=[dalle_file.id, plot_file.id]\n",
+ ")\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 22,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Assistant still working on PPTX...\n",
+ "Assistant still working on PPTX...\n",
+ "Assistant still working on PPTX...\n",
+ "Assistant still working on PPTX...\n",
+ "Assistant still working on PPTX...\n",
+ "Assistant still working on PPTX...\n",
+ "Assistant still working on PPTX...\n",
+ "Assistant still working on PPTX...\n",
+ "Assistant still working on PPTX...\n",
+ "Assistant still working on PPTX...\n",
+ "Successfully retrieved pptx_id: file-oa0i63qPH4IaJXYj90aA6L4Q\n"
+ ]
+ }
+ ],
+ "source": [
+ "#May take 1-3 mins\n",
+ "while True:\n",
+ " try:\n",
+ " response = get_response(thread)\n",
+ " pptx_id = response.data[0].content[0].text.annotations[0].file_path.file_id\n",
+ " print(\"Successfully retrieved pptx_id:\", pptx_id)\n",
+ " break\n",
+ " except Exception as e:\n",
+ " print(\"Assistant still working on PPTX...\")\n",
+ " time.sleep(10)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 25,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "pptx_id = response.data[0].content[0].text.annotations[0].file_path.file_id\n",
+ "ppt_file= client.files.content(pptx_id)\n",
+ "file_obj = io.BytesIO(ppt_file.read())\n",
+ "with open(\"data/created_slides.pptx\", \"wb\") as f:\n",
+ " f.write(file_obj.getbuffer())\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Now, we have a PPTX file saved with all of our created content!.
"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Let's look at the screenshots of the .pptx we just created using JUST the assistants API and DALL·E-3. We don't have a `seed` parameter yet in the Assistants API, so the DALL·E-3 image and wordings will be slightly different from what you see when you run this notebook, due to the non-determinism of LLMs, but the outputs should be directionally the same."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "The title slide:"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ ""
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "And the data slide:"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ ""
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## 5. Conclusion"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Woo! While these slides could use some formatting tweaks, we have made some great content using the Assistants API, GPT-4 and DALL·E-3. We were able to take a `.csv` file with financial data, and use our assisant to calculate profit by quarter across distribution channels, plot the results, identify insights and key takeaways from the visualization, and create a summarative title. And, given just a description of our company, NotRealCorp, we used DALL·E-3 to make an awesome title image.
\n",
+ "While we are still a ways away from entirely automating this process without a human in the loop, hopefully this notebook can make the slide creation process a bit easier for you. More importantly, this notebook can ideally give you a glimpse into the potential of the assistants API! We're excited to see what you build."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## 6. Extensions"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "- When DALL·E-3 is incorporated in the Assistants API, we will have the ability to request the generated title image within the thread. \n",
+ "- GPT-4-Vision is not yet supported in the Assistants API, but could have been used to gather insights from the line plot image.\n",
+ "- GPT-4-Vision was used to generate the `python-pptx` template included in this recipe, so a potential extension project could be demonstrating best practices around converting images to slide templates."
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "openai",
+ "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.9.16"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/examples/data/NotRealCorp_financial_data.json b/examples/data/NotRealCorp_financial_data.json
new file mode 100644
index 0000000..4b413c6
--- /dev/null
+++ b/examples/data/NotRealCorp_financial_data.json
@@ -0,0 +1 @@
+{"Year":{"0":2021,"1":2021,"2":2021,"3":2021,"4":2021,"5":2021,"6":2021,"7":2021,"8":2021,"9":2021,"10":2021,"11":2021,"12":2022,"13":2022,"14":2022,"15":2022,"16":2022,"17":2022,"18":2022,"19":2022,"20":2022,"21":2022,"22":2022,"23":2022,"24":2023,"25":2023,"26":2023,"27":2023,"28":2023,"29":2023,"30":2023,"31":2023,"32":2023,"33":2023,"34":2023,"35":2023,"36":2024,"37":2024,"38":2024,"39":2024,"40":2024,"41":2024,"42":2024,"43":2024,"44":2024,"45":2024,"46":2024,"47":2024},"Quarter":{"0":"Q1","1":"Q1","2":"Q1","3":"Q2","4":"Q2","5":"Q2","6":"Q3","7":"Q3","8":"Q3","9":"Q4","10":"Q4","11":"Q4","12":"Q1","13":"Q1","14":"Q1","15":"Q2","16":"Q2","17":"Q2","18":"Q3","19":"Q3","20":"Q3","21":"Q4","22":"Q4","23":"Q4","24":"Q1","25":"Q1","26":"Q1","27":"Q2","28":"Q2","29":"Q2","30":"Q3","31":"Q3","32":"Q3","33":"Q4","34":"Q4","35":"Q4","36":"Q1","37":"Q1","38":"Q1","39":"Q2","40":"Q2","41":"Q2","42":"Q3","43":"Q3","44":"Q3","45":"Q4","46":"Q4","47":"Q4"},"Distribution channel":{"0":"Online Sales","1":"Direct Sales","2":"Retail Partners","3":"Online Sales","4":"Direct Sales","5":"Retail Partners","6":"Online Sales","7":"Direct Sales","8":"Retail Partners","9":"Online Sales","10":"Direct Sales","11":"Retail Partners","12":"Online Sales","13":"Direct Sales","14":"Retail Partners","15":"Online Sales","16":"Direct Sales","17":"Retail Partners","18":"Online Sales","19":"Direct Sales","20":"Retail Partners","21":"Online Sales","22":"Direct Sales","23":"Retail Partners","24":"Online Sales","25":"Direct Sales","26":"Retail Partners","27":"Online Sales","28":"Direct Sales","29":"Retail Partners","30":"Online Sales","31":"Direct Sales","32":"Retail Partners","33":"Online Sales","34":"Direct Sales","35":"Retail Partners","36":"Online Sales","37":"Direct Sales","38":"Retail Partners","39":"Online Sales","40":"Direct Sales","41":"Retail Partners","42":"Online Sales","43":"Direct Sales","44":"Retail Partners","45":"Online Sales","46":"Direct Sales","47":"Retail Partners"},"Revenue ($M)":{"0":1.5,"1":1.5,"2":1.5,"3":1.52,"4":1.52,"5":1.52,"6":1.54,"7":1.54,"8":1.54,"9":1.56,"10":1.56,"11":1.56,"12":1.7,"13":1.6,"14":1.55,"15":1.72,"16":1.62,"17":1.57,"18":1.74,"19":1.64,"20":1.59,"21":1.76,"22":1.66,"23":1.61,"24":1.9,"25":1.7,"26":1.6,"27":1.92,"28":1.72,"29":1.62,"30":1.94,"31":1.74,"32":1.64,"33":1.96,"34":1.76,"35":1.66,"36":2.1,"37":1.8,"38":1.65,"39":2.12,"40":1.82,"41":1.67,"42":2.14,"43":1.84,"44":1.69,"45":2.16,"46":1.86,"47":1.71},"Costs ($M)":{"0":1.3019525402,"1":1.3808087359,"2":1.3482460133,"3":1.3086075747,"4":1.4133047938,"5":1.352737358,"6":1.304110535,"7":1.41112627,"8":1.330751592,"9":1.3017953273,"10":1.4148004859,"11":1.3547054199,"12":1.296946192,"13":1.4191447337,"14":1.3544838289,"15":1.3058357645,"16":1.4119663426,"17":1.3546773599,"18":1.2975034885,"19":1.3984591745,"20":1.3677499231,"21":1.31567092,"22":1.4112211671,"23":1.357272812,"24":1.3185465104,"25":1.384730977,"26":1.364380316,"27":1.2953376608,"28":1.4055968409,"29":1.3874812782,"30":1.3116690015,"31":1.3857341315,"32":1.4179052478,"33":1.3011557968,"34":1.4177867567,"35":1.4124090189,"36":1.3027217824,"37":1.4008739329,"38":1.4566706686,"39":1.3170238655,"40":1.3965864776,"41":1.4768255148,"42":1.2828414423,"43":1.3905822245,"44":1.4784153024,"45":1.283485172,"46":1.4109693476,"47":1.4951570519},"Customer count":{"0":150,"1":151,"2":152,"3":152,"4":153,"5":154,"6":154,"7":155,"8":156,"9":156,"10":157,"11":158,"12":160,"13":161,"14":162,"15":162,"16":163,"17":164,"18":164,"19":165,"20":166,"21":166,"22":167,"23":168,"24":170,"25":171,"26":172,"27":172,"28":173,"29":174,"30":174,"31":175,"32":176,"33":176,"34":177,"35":178,"36":180,"37":181,"38":182,"39":182,"40":183,"41":184,"42":184,"43":185,"44":186,"45":186,"46":187,"47":188},"Time":{"0":"2021 Q1","1":"2021 Q1","2":"2021 Q1","3":"2021 Q2","4":"2021 Q2","5":"2021 Q2","6":"2021 Q3","7":"2021 Q3","8":"2021 Q3","9":"2021 Q4","10":"2021 Q4","11":"2021 Q4","12":"2022 Q1","13":"2022 Q1","14":"2022 Q1","15":"2022 Q2","16":"2022 Q2","17":"2022 Q2","18":"2022 Q3","19":"2022 Q3","20":"2022 Q3","21":"2022 Q4","22":"2022 Q4","23":"2022 Q4","24":"2023 Q1","25":"2023 Q1","26":"2023 Q1","27":"2023 Q2","28":"2023 Q2","29":"2023 Q2","30":"2023 Q3","31":"2023 Q3","32":"2023 Q3","33":"2023 Q4","34":"2023 Q4","35":"2023 Q4","36":"2024 Q1","37":"2024 Q1","38":"2024 Q1","39":"2024 Q2","40":"2024 Q2","41":"2024 Q2","42":"2024 Q3","43":"2024 Q3","44":"2024 Q3","45":"2024 Q4","46":"2024 Q4","47":"2024 Q4"}}
\ No newline at end of file
diff --git a/examples/data/created_slides.pptx b/examples/data/created_slides.pptx
new file mode 100644
index 0000000000000000000000000000000000000000..ce2580fe701ad0c04c564d859a9fe2e762100fe8
GIT binary patch
literal 2107240
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 Malj_>BTL*z%!xw
zX<5c29y#-?omfWd8533kI0s{0V1j`kIFIKvPI0i`zRV|_epNr=$`n%ow01{=tNdNA
z7+sXs>!K|Ble+?i`uXXSSVN-IQKQV$YK3DmjSDn$0I*co-HSwFWU2p3nGGbgQ1SJn
zVeWnPKMK8SvB=3b`pxUpzvdZDCv&_g>hhBUY6h>*RH}!|bUhNOAlFCQHm-YfiiTKr
zY|K39Iz)nKhRlXPFWCbF6ru6@6jxQ*mA)Jv~So0d)uMJOJ=6X__ledb^
zb~x&0UQdjd^+y1+xGELa02!m#83e-*@>3D(63l}wi`E0p$jx%hDo10j)gLF~5V5aWL
z<%6Z_rb7pE>9=RUg*2*=W8#?oRM^Fs{C?i*P_p6{aK*$?w2cguzAx8^i^lR&N7Xw6
zQ=mxG|FNojtSTDtzjDz1Ph!XZ?^XQ=!|>nSoBw$Dwlx2F_}GwpuC?KN51X`NQp+9D
zD^55{@s>T_*RNs~1V+qdQ#E+k8c3-(WOM4pLy9t9$i^sMevMk`E-ZLZ%b<*;%a!-^
zoAgPGxTd8w$@uMD;lRlz>5Q6>gr_7w@)-M7G<&HFHd0XHFSwU{}^1DR_M|vT#n6Xu{d(RGGqsZQ)-5a^!_E<2PJy^E@e=9_?mIZ
zRs=a3V5?o$Hiw*b`|bOSk1p3iT9)G45QC~^oLcmaY3z|co*L(OsrMTRcb+mo$K+%1
zR)oj)vgjP@+L-{te`yDo5vJYG)0#%;(C-u{|?laCwoPe&RK
z()q{Q8a9Wp(xP-Q3R2&hez95Fm@1?5SmErWvHX{vAh|pGI6*|7WqfDTf;50G%
zzyoYShflg&XI*XxWn8DHTF^CwuQL`To^qQeUr86Uhc-z3toE1N*F5iRpag1hD;;&o
zt3)wrWrLC)o&DW`SJnl{QYArVQ#5KXR}0c8vtNt?+YsjWz4`(=yKLIoj50s;qFTJYOs0KS=Q9i6
zqptL=+x@Nj{tu2UVbH1G{J*W<^RFzE{qHUR|6&&WKUUqkJ{g
z&BG};PCC}^uM}%xtBBTPk}(wqUMlg4I|y^VDAbBl*a$6U@BEcUe8V>d64Q!XgA)hI7syvYZM^rqKtYnzIGPi*)F|0{~rwm?ybK7c4uOMCOq5!
zaCIFl%xz3qZ5&LjEZA9`9j$;pHXy^N020r~_wMs8R%ZxE=zhskD!C?R`9{jI#EWH*
z%l2ut8u|4s&v~u|*2~g7o~exTJeGnx>amtQ8k=&5eTBRcPy3&-4r?jYs#KC8RPd1P
zI#;h(Ry%)zeQx;C6d`d>g2zE0pF4kmeV1=fefM!jXgyHMsy}XygRZPTYK!p@Kd-Hy
zXU?47uKZ%F>4ZNyjb3;^+%#`LbDsM&KF2mlKOcggA4iXMNmwCQ*okNr4|?9;mrU`8
zV-8;P=9e_z*C$y0uMz~V18(l?yms8WMHX6%D<_zI?h?96LfkrK@&)^t#`U<}{qcTs
zD3(-L*V}kZ%xaW5*ea@e7_79TTJR$V%rK1qK`Q7p<2myRdhTap)o68?sIIe9Tv{(j
zhzetx!cz3mCk#s6eIo9yUN_;(Ph5#BJNDMpwCmLSDW{p<=8%(akS4j(hI3`etEt{v
zXKI~&&ab#)F1yU*P*GW4w4Z9RmD$Nd65$PguvIr*iwq&;*0d0Kq(i>zrXzUkkWGa@wKj^f4}IdaWg^3eXdY76AknhJ8JFB@E6
zuUF@uYE#%~YUVl$xaBNkM``ZI7Fc3Ko|?Vd=I3AE88MnkSN&mmz6M;A@X+OPD6#D{
z$x1z4bji)0kUwv-u5LQj6CdWOaoF00%0D*gmkcrMN2O0M>PlQ#
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 |