Migrate all notebooks to API V1 (#914)

Co-authored-by: ayush rajgor <ayushrajgorar@gmail.com>
pull/1022/head
Gabor Cselle 4 months ago committed by GitHub
parent d891437737
commit 2c441ab9a2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -53,6 +53,11 @@ prakul:
website: "https://www.linkedin.com/in/prakulagarwal"
avatar: "https://media.licdn.com/dms/image/D5603AQEUug83qKgRBg/profile-displayphoto-shrink_800_800/0/1675384960197?e=1706140800&v=beta&t=qxkDbBr-Bk2ASpcwbR5JVPD6yS-vzmIwNHAa8ApyDq4"
gaborcselle:
name: "Gabor Cselle"
website: "https://www.linkedin.com/in/gaborcselle"
avatar: "https://avatars.githubusercontent.com/u/54096?s=96&v=4"
nghiauet:
name: "Nghia Pham"
website: "https://www.linkedin.com/in/deptraicucmanh/"

@ -191,8 +191,10 @@
],
"source": [
"from openai import OpenAI\n",
"import os\n",
"\n",
"client = OpenAI(api_key=os.environ.get(\"OPENAI_API_KEY\", \"<your OpenAI API key if not set as env var>\"))\n",
"\n",
"client = OpenAI()\n",
"\n",
"assistant = client.beta.assistants.create(\n",
" name=\"Math Tutor\",\n",
@ -586,7 +588,7 @@
"\n",
"MATH_ASSISTANT_ID = assistant.id # or a hard-coded ID like \"asst-...\"\n",
"\n",
"client = OpenAI()\n",
"client = OpenAI(api_key=os.environ.get(\"OPENAI_API_KEY\", \"<your OpenAI API key if not set as env var>\"))\n",
"\n",
"def submit_message(assistant_id, thread, user_message):\n",
" client.beta.threads.messages.create(\n",

@ -1,189 +0,0 @@
from typing import List, Union
from smokey import Smokey
import openai
def get_candidates(
prompt: str,
stop: List[str],
temperature: float,
priming_prefix: str,
engine: str,
n: int = 5,
) -> List[str]:
"""
Generate N candidate completions based on the prompt, generated with a specific temperature.
:param prompt: The prompt to start the conversation with.
:param stop: A list of tokens that indicate the end of the generation.
:param temperature: The temperature of the generation.
:param priming_prefix: The prefix to use for the priming.
:param engine: The engine to use for the generation.
:param n: The number of completions to generate.
:return: A list of completions.
"""
response = openai.Completion.create(
engine=engine,
prompt=prompt,
temperature=temperature,
max_tokens=150,
top_p=1,
frequency_penalty=0,
presence_penalty=0,
stop=stop,
n=n,
)
responses = [priming_prefix + choice.text for choice in response.choices]
return responses
def rindex(lst: List, value: str) -> int:
"""
Return the index of the last occurrence of a value in a list.
:param lst: The list to search in.
:param value: The value to search for.
:return: The index of the last occurrence of the value.
"""
try:
return len(lst) - lst[::-1].index(value) - 1
except ValueError:
raise ValueError(f"Answer start token `{value}` not found in the eval template")
def eval_candidate(
candidate_answer: str,
original_instruction: str,
eval_template: str,
answer_start_token: str,
engine: str,
) -> float:
"""
Evaluate a candidate answer by calculating the average log probability
of the original instruction, given the candidate answer with a specific
evaluation template, aimed at reconstructing the original instruction.
:param candidate_answer: The candidate answer to evaluate.
:param original_instruction: The original instruction.
:param eval_template: The template to use for the evaluation.
:param answer_start_token: The token to use to indicate the start of the answer.
:param engine: The engine to use for the evaluation.
:return: The evaluation of the candidate answer.
"""
response = openai.Completion.create(
engine=engine,
prompt=eval_template.format(candidate_answer, original_instruction),
temperature=0,
max_tokens=0,
top_p=1,
frequency_penalty=0,
presence_penalty=0,
logprobs=1,
echo=True,
)
answer_start = rindex(
response["choices"][0]["logprobs"]["tokens"], answer_start_token
)
logprobs = response["choices"][0]["logprobs"]["token_logprobs"][answer_start + 1 :]
return sum(logprobs) / len(logprobs)
def backtranslation(
prompt_template: str,
additional_info: str,
instruction: str,
eval_template: str,
priming_prefix: str = "SELECT",
stop1: List[str] = ["#", ";"],
answer_start_token: str = "--",
n: int = 5,
temperature: float = 0.5,
return_all_results: bool = False,
engine: str = "davinci-codex",
) -> Union[str, List[str, float]]:
"""
Generate a number of SQL queries given a natural language instruction,
and pick the best one based on the average log probability of explaining the
candidate SQL query with the exact original instruction, when prompted for
a natural language explanation of the candidate SQL query.
:param prompt_template: The template to use for the prompt to generate SQL.
:param additional_info: Additional information to include in the prompt
(SQL Tables, and their properties).
:param instruction: The instruction in natural language.
:param eval_template: The template to use for the evaluation.
:param priming_prefix: The prefix to use for the priming of the SQL query.
:param stop1: A list of tokens that indicate the end of the generation.
:param answer_start_token: The token to use to indicate the start of the
natural answer.
:param n: The number of candidates to generate.
:param temperature: The temperature of the generation.
:param return_all_results: Whether to return all results or just the best one.
:param engine: The engine to use for the generation and evaluation.
:return: The best SQL query, or a list of all scored generated SQL queries.
"""
prompt_template = prompt_template.format(
additional_info, instruction, priming_prefix
)
candidates = []
responses = get_candidates(
prompt_template, stop1, temperature, priming_prefix, engine=engine, n=n
)
for i in range(n):
quality = eval_candidate(
responses[i],
instruction,
eval_template,
answer_start_token,
engine=engine,
)
candidates.append((responses[i], quality))
candidates.sort(key=lambda x: x[1], reverse=True)
if return_all_results:
return candidates
return candidates[0][0]
def main(
nl_query: str = "Return the name of each department that had more than 10 employees in June 2021",
eval_template: str = "{};\n-- Explanation of the above query in human readable format\n-- {}",
table_definitions: str = "# Employee(id, name, department_id)\n# Department(id, name, address)\n# Salary_Payments(id, employee_id, amount, date)\n",
prompt_template: str = "### Postgres SQL tables, with their properties:\n#\n{}#\n### {}\n{}",
n: int = 3,
temperature: float = 0.3,
engine: str = "davinci-codex",
):
"""
Generate a number of SQL queries given a natural language instruction,
and pick the best one based on the highest backtranslation score.
:param nl_query: The natural language query.
:param eval_template: The template to use for the evaluation.
:param table_definitions: The definitions of the tables used in the query.
:param prompt_template: The template to use for the prompt to generate SQL.
:param n: The number of candidates to generate.
:param temperature: The temperature of the generation.
:param engine: The engine to use for the generation and evaluation.
:return: The best SQL query, or a list of all scored generated SQL queries.
"""
result = backtranslation(
prompt_template,
table_definitions,
nl_query,
eval_template,
priming_prefix="SELECT",
temperature=temperature,
n=n,
engine=engine,
)
print(result)
if __name__ == "__main__":
Smokey(main)

File diff suppressed because one or more lines are too long

@ -58,8 +58,7 @@
"import os\n",
"from ast import literal_eval\n",
"\n",
"#openai.api_key = os.getenv(\"OPENAI_API_KEY\")\n",
"client = OpenAI()\n",
"client = OpenAI(api_key=os.environ.get(\"OPENAI_API_KEY\", \"<your OpenAI API key if not set as env var>\"))\n",
"COMPLETIONS_MODEL = \"gpt-3.5-turbo\"\n",
"\n",
"# This path leads to a file with data and precomputed embeddings\n",
@ -399,7 +398,7 @@
" .sample(transactions_per_cluster, random_state=42)\n",
" .values\n",
" )\n",
" completion = client.chat.completions.create(\n",
" response = client.chat.completions.create(\n",
" model=COMPLETIONS_MODEL,\n",
" # We'll include a prompt to instruct the model what sort of description we're looking for\n",
" messages=[\n",
@ -413,7 +412,7 @@
" frequency_penalty=0,\n",
" presence_penalty=0,\n",
" )\n",
" print(completion.choices[0].message.content.replace(\"\\n\", \"\"))\n",
" print(response.choices[0].message.content.replace(\"\\n\", \"\"))\n",
" print(\"\\n\")\n",
"\n",
" sample_cluster_rows = embedding_df[embedding_df.Cluster == i].sample(transactions_per_cluster, random_state=42)\n",

@ -25,13 +25,14 @@
"source": [
"from IPython.display import display, Image\n",
"from openai import OpenAI\n",
"import os\n",
"import pandas as pd\n",
"import json\n",
"import io\n",
"from PIL import Image\n",
"import requests\n",
"\n",
"client = OpenAI()\n",
"client = OpenAI(api_key=os.environ.get(\"OPENAI_API_KEY\", \"<your OpenAI API key if not set as env var>\"))\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",

@ -38,9 +38,12 @@
"import mwclient # for downloading example Wikipedia articles\n",
"import mwparserfromhell # for splitting Wikipedia articles into sections\n",
"import openai # for generating embeddings\n",
"import os # for environment variables\n",
"import pandas as pd # for DataFrames to store article sections and embeddings\n",
"import re # for cutting <ref> links out of Wikipedia articles\n",
"import tiktoken # for counting tokens\n"
"import tiktoken # for counting tokens\n",
"\n",
"client = openai.OpenAI(api_key=os.environ.get(\"OPENAI_API_KEY\", \"<your OpenAI API key if not set as env var>\"))"
]
},
{
@ -612,10 +615,10 @@
" batch_end = batch_start + BATCH_SIZE\n",
" batch = wikipedia_strings[batch_start:batch_end]\n",
" print(f\"Batch {batch_start} to {batch_end-1}\")\n",
" response = openai.Embedding.create(model=EMBEDDING_MODEL, input=batch)\n",
" for i, be in enumerate(response[\"data\"]):\n",
" assert i == be[\"index\"] # double check embeddings are in same order as input\n",
" batch_embeddings = [e[\"embedding\"] for e in response[\"data\"]]\n",
" response = client.embeddings.create(model=EMBEDDING_MODEL, input=batch)\n",
" for i, be in enumerate(response.data):\n",
" assert i == be.index # double check embeddings are in same order as input\n",
" batch_embeddings = [e.embedding for e in response.data]\n",
" embeddings.extend(batch_embeddings)\n",
"\n",
"df = pd.DataFrame({\"text\": wikipedia_strings, \"embedding\": embeddings})\n"

@ -24,22 +24,25 @@
},
{
"cell_type": "code",
"execution_count": 1,
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"from openai import OpenAI\n",
"import os\n",
"import openai\n",
"from tenacity import retry, wait_random_exponential, stop_after_attempt, retry_if_not_exception_type\n",
"\n",
"client = OpenAI(api_key=os.environ.get(\"OPENAI_API_KEY\", \"<your OpenAI API key if not set as env var>\"))\n",
"\n",
"EMBEDDING_MODEL = 'text-embedding-ada-002'\n",
"EMBEDDING_CTX_LENGTH = 8191\n",
"EMBEDDING_ENCODING = 'cl100k_base'\n",
"\n",
"# let's make sure to not retry on an invalid request, because that is what we want to demonstrate\n",
"@retry(wait=wait_random_exponential(min=1, max=20), stop=stop_after_attempt(6), retry=retry_if_not_exception_type(openai.InvalidRequestError))\n",
"@retry(wait=wait_random_exponential(min=1, max=20), stop=stop_after_attempt(6), retry=retry_if_not_exception_type(openai.BadRequestError))\n",
"def get_embedding(text_or_tokens, model=EMBEDDING_MODEL):\n",
" return openai.Embedding.create(input=text_or_tokens, model=model)[\"data\"][0][\"embedding\"]"
" return client.embeddings.create(input=text_or_tokens, model=model).data[0].embedding"
]
},
{
@ -51,14 +54,14 @@
},
{
"cell_type": "code",
"execution_count": 2,
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"This model's maximum context length is 8191 tokens, however you requested 10001 tokens (10001 in your prompt; 0 for the completion). Please reduce your prompt; or completion length.\n"
"Error code: 400 - {'error': {'message': \"This model's maximum context length is 8192 tokens, however you requested 10001 tokens (10001 in your prompt; 0 for the completion). Please reduce your prompt; or completion length.\", 'type': 'invalid_request_error', 'param': None, 'code': None}}\n"
]
}
],
@ -66,7 +69,7 @@
"long_text = 'AGI ' * 5000\n",
"try:\n",
" get_embedding(long_text)\n",
"except openai.InvalidRequestError as e:\n",
"except openai.BadRequestError as e:\n",
" print(e)"
]
},
@ -267,7 +270,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.9"
"version": "3.11.5"
},
"vscode": {
"interpreter": {

@ -44,7 +44,7 @@
},
{
"cell_type": "code",
"execution_count": 5,
"execution_count": 11,
"metadata": {},
"outputs": [],
"source": [
@ -53,6 +53,8 @@
"import openai\n",
"import tiktoken\n",
"\n",
"client = openai.OpenAI(api_key=os.environ.get(\"OPENAI_API_KEY\", \"<your OpenAI API key if not set as env var>\"))\n",
"\n",
"# Extract the raw text from each PDF using textract\n",
"text = textract.process('data/fia_f1_power_unit_financial_regulations_issue_1_-_2022-08-16.pdf', method='pdfminer').decode('utf-8')\n",
"clean_text = text.replace(\" \", \" \").replace(\"\\n\", \"; \").replace(';',' ')"
@ -67,7 +69,7 @@
},
{
"cell_type": "code",
"execution_count": 28,
"execution_count": 20,
"metadata": {},
"outputs": [
{
@ -96,13 +98,13 @@
"template_prompt=f'''Extract key pieces of information from this regulation document.\n",
"If a particular piece of information is not present, output \\\"Not specified\\\".\n",
"When you extract a key piece of information, include the closest page number.\n",
"Use the following format:\\n0. Who is the author\\n1. What is the amount of the \"Power Unit Cost Cap\" in USD, GBP and EUR\\n2. What is the value of External Manufacturing Costs in USD\\n3. What is the Capital Expenditure Limit in USD\\n\\nDocument: \\\"\\\"\\\"{document}\\\"\\\"\\\"\\n\\n0. Who is the author: Tom Anderson (Page 1)\\n1.'''\n",
"Use the following format:\\n0. Who is the author\\n1. What is the amount of the \"Power Unit Cost Cap\" in USD, GBP and EUR\\n2. What is the value of External Manufacturing Costs in USD\\n3. What is the Capital Expenditure Limit in USD\\n\\nDocument: \\\"\\\"\\\"<document>\\\"\\\"\\\"\\n\\n0. Who is the author: Tom Anderson (Page 1)\\n1.'''\n",
"print(template_prompt)"
]
},
{
"cell_type": "code",
"execution_count": 29,
"execution_count": 17,
"metadata": {},
"outputs": [],
"source": [
@ -127,19 +129,23 @@
" i = j\n",
"\n",
"def extract_chunk(document,template_prompt):\n",
" \n",
" prompt=template_prompt.replace('<document>',document)\n",
" prompt = template_prompt.replace('<document>',document)\n",
"\n",
" response = openai.Completion.create(\n",
" model='text-davinci-003', \n",
" prompt=prompt,\n",
" temperature=0,\n",
" max_tokens=1500,\n",
" top_p=1,\n",
" frequency_penalty=0,\n",
" presence_penalty=0\n",
" )\n",
" return \"1.\" + response['choices'][0]['text']"
" messages = [\n",
" {\"role\": \"system\", \"content\": \"You help extract information from documents.\"},\n",
" {\"role\": \"user\", \"content\": prompt}\n",
" ]\n",
"\n",
" response = client.chat.completions.create(\n",
" model='gpt-4', \n",
" messages=messages,\n",
" temperature=0,\n",
" max_tokens=1500,\n",
" top_p=1,\n",
" frequency_penalty=0,\n",
" presence_penalty=0\n",
" )\n",
" return \"1.\" + response.choices[0].message.content"
]
},
{
@ -228,7 +234,7 @@
"template_prompt=f'''Extract key pieces of information from this regulation document.\n",
"If a particular piece of information is not present, output \\\"Not specified\\\".\n",
"When you extract a key piece of information, include the closest page number.\n",
"Use the following format:\\n0. Who is the author\\n1. How is a Minor Overspend Breach calculated\\n2. How is a Major Overspend Breach calculated\\n3. Which years do these financial regulations apply to\\n\\nDocument: \\\"\\\"\\\"{document}\\\"\\\"\\\"\\n\\n0. Who is the author: Tom Anderson (Page 1)\\n1.'''\n",
"Use the following format:\\n0. Who is the author\\n1. How is a Minor Overspend Breach calculated\\n2. How is a Major Overspend Breach calculated\\n3. Which years do these financial regulations apply to\\n\\nDocument: \\\"\\\"\\\"<document>\\\"\\\"\\\"\\n\\n0. Who is the author: Tom Anderson (Page 1)\\n1.'''\n",
"print(template_prompt)"
]
},
@ -306,9 +312,9 @@
],
"metadata": {
"kernelspec": {
"display_name": "embed_retrieve",
"display_name": "Python 3",
"language": "python",
"name": "embed_retrieve"
"name": "python3"
},
"language_info": {
"codemirror_mode": {
@ -320,12 +326,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.9"
},
"vscode": {
"interpreter": {
"hash": "5997d090960a54cd76552f75eca12ec3b416cf9d01a1a5af08ae48cf90878791"
}
"version": "3.11.3"
}
},
"nbformat": 4,

File diff suppressed because one or more lines are too long

@ -21,7 +21,7 @@
"metadata": {},
"source": [
"For context, from the function calling notebook above:\n",
"> `functions` is an optional parameter in the Chat Completion API which can be used to provide function specifications. The purpose of this is to enable models to generate function arguments which adhere to the provided specifications. Note that the API will not actually execute any function calls. It is up to developers to execute function calls using model outputs."
"> `tools` is an optional parameter in the Chat Completion API which can be used to provide function specifications. The purpose of this is to enable models to generate function arguments which adhere to the provided specifications. Note that the API will not actually execute any function calls. It is up to developers to execute function calls using model outputs."
]
},
{
@ -33,7 +33,7 @@
"invocations, and incorrect invocations).\\\n",
"Before fine tuning for function calling, it's best to begin with:\n",
"- Improvements to the function definitions. Make them more clear, and more distinct from one another.\n",
"- Experiment with prompt engineering: often a more detailed prompt can help the model call the correct function.\\\n",
"- Experiment with prompt engineering: often a more detailed prompt can help the model call the correct function.\n",
"\n",
"*If* the steps above fail to improve function calling to a satisfactory level, then you can try fine tuning for function calling."
]
@ -76,17 +76,16 @@
"outputs": [],
"source": [
"# !pip install tenacity\n",
"# !pip insta openai\n",
"# !pip install typing\n"
"# !pip install openai\n",
"# !pip install typing"
]
},
{
"cell_type": "code",
"execution_count": 2,
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import openai\n",
"import numpy as np\n",
"import json\n",
"import os\n",
@ -95,7 +94,8 @@
"from tenacity import retry, wait_random_exponential, stop_after_attempt\n",
"from typing import Any, Dict, List, Generator\n",
"import ast\n",
"client = OpenAI()\n"
"\n",
"client = OpenAI(api_key=os.environ.get(\"OPENAI_API_KEY\", \"<your OpenAI API key if not set as env var>\"))"
]
},
{
@ -114,17 +114,17 @@
},
{
"cell_type": "code",
"execution_count": 3,
"execution_count": 22,
"metadata": {},
"outputs": [],
"source": [
"def get_chat_completion(\n",
" messages: list[dict[str, str]],\n",
" model: str = \"gpt-4\",\n",
" model: str = \"gpt-3.5-turbo\",\n",
" max_tokens=500,\n",
" temperature=1.0,\n",
" stop=None,\n",
" functions=None,\n",
" tools=None,\n",
") -> str:\n",
" params = {\n",
" 'model': model,\n",
@ -132,9 +132,8 @@
" 'max_tokens': max_tokens,\n",
" 'temperature': temperature,\n",
" 'stop': stop,\n",
" 'tools': tools,\n",
" }\n",
" if functions:\n",
" params['tools'] = functions\n",
"\n",
" completion = client.chat.completions.create(**params)\n",
" return completion.choices[0].message\n"
@ -158,7 +157,7 @@
},
{
"cell_type": "code",
"execution_count": 4,
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
@ -176,7 +175,7 @@
},
{
"cell_type": "code",
"execution_count": 5,
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
@ -468,7 +467,7 @@
},
{
"cell_type": "code",
"execution_count": 6,
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
@ -507,7 +506,7 @@
" messages = []\n",
" messages.append({\"role\": \"system\", \"content\": DRONE_SYSTEM_PROMPT})\n",
" messages.append({\"role\": \"user\", \"content\": prompt})\n",
" completion = get_chat_completion(model=\"gpt-3.5-turbo\",messages=messages,functions=function_list)\n",
" completion = get_chat_completion(model=\"gpt-3.5-turbo\",messages=messages,tools=function_list)\n",
" print(prompt)\n",
" print(completion.tool_calls[0].function,'\\n')\n"
]
@ -532,26 +531,6 @@
" \"Change drone's paint job color\"]\n"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"ChatCompletionMessage(content=None, role='assistant', function_call=None, tool_calls=[ChatCompletionMessageToolCall(id='call_6rwNKuIgO7l8Izw5qoFcuSuk', function=Function(arguments='{}', name='reject_request'), type='function')])"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"completion\n"
]
},
{
"cell_type": "code",
"execution_count": 10,
@ -567,17 +546,17 @@
"\n",
"\n",
"Initiate live-streaming on social media\n",
"Function(arguments='{\\n\"mode\": \"video\"\\n}', name='control_camera') \n",
"Function(arguments='{\\n\"mode\": \"video\",\\n\"duration\": 0\\n}', name='control_camera') \n",
"\n",
"\n",
"\n",
"Scan environment for heat signatures\n",
"Function(arguments='{\\n \"mode\": \"photo\"\\n}', name='control_camera') \n",
"Function(arguments='{ \"mode\": \"photo\" }', name='control_camera') \n",
"\n",
"\n",
"\n",
"Enable stealth mode\n",
"Function(arguments='{\\n \"pattern\": \"solid\",\\n \"color\": \"black\"\\n}', name='configure_led_display') \n",
"Function(arguments='{\\n \"mode\": \"off\"\\n}', name='set_drone_lighting') \n",
"\n",
"\n",
"\n",
@ -594,7 +573,7 @@
" messages = []\n",
" messages.append({\"role\": \"system\", \"content\": DRONE_SYSTEM_PROMPT})\n",
" messages.append({\"role\": \"user\", \"content\": prompt})\n",
" completion = get_chat_completion(model=\"gpt-3.5-turbo\",messages=messages,functions=function_list)\n",
" completion = get_chat_completion(model=\"gpt-3.5-turbo\",messages=messages,tools=function_list)\n",
" print(prompt)\n",
" try:\n",
" print(completion.tool_calls[0].function,'\\n')\n",
@ -609,7 +588,7 @@
"metadata": {},
"source": [
"Now we run into some problems.\n",
"The model here should reject all of these requests, as they are impossible given the functions, however instead the model calls functions that are somewhat related to the request, but incorrect. The model sets the camera to video when asked to begin 'live streaming to social media', and changes the LED's to blue when asked to 'change the paint color'...\\\n",
"The model here should reject all of these requests, as they are impossible given the functions, however instead the model calls functions that are somewhat related to the request, but incorrect. The model sets the camera to video when asked to begin 'live streaming to social media', and changes the LED's to blue when asked to 'change the paint color'...\n",
"<br>\n",
"In this simple case, more prompt engineering may resolve some of these issues, but for the purpose of this example we will demonstrate how fine tuning can be used to improve performance. Additionally, while this case is relatively straightforward, as the number of and complexity of the functions increases, fine tuning becomes more and more impactful."
]
@ -843,7 +822,7 @@
},
{
"cell_type": "code",
"execution_count": 14,
"execution_count": 19,
"metadata": {},
"outputs": [],
"source": [
@ -860,7 +839,7 @@
" \"arguments\": arguments\n",
" }\n",
" messages = [{\"role\": \"user\", \"content\": INVOCATION_FILLER_PROMPT.format(invocation=input_object,function=function)}]\n",
" input_object = get_chat_completion(model='gpt-4',messages=messages, max_tokens = 200,temperature=.1).content\n",
" input_object = get_chat_completion(model='gpt-4', messages=messages, max_tokens = 200, temperature=.1).content\n",
" else:\n",
" input_object = {\n",
" \"name\": func_name,\n",
@ -879,7 +858,7 @@
},
{
"cell_type": "code",
"execution_count": 15,
"execution_count": 20,
"metadata": {},
"outputs": [],
"source": [
@ -904,7 +883,7 @@
},
{
"cell_type": "code",
"execution_count": 16,
"execution_count": 23,
"metadata": {},
"outputs": [
{
@ -928,7 +907,7 @@
"\u001b[34m12.3% complete\u001b[0m\n",
"{'name': 'control_drone_movement', 'arguments': {'direction': 'right', 'distance': 10}}\n",
"\u001b[34m14.0% complete\u001b[0m\n",
"{'name': 'control_drone_movement', 'arguments': {'direction': 'up', 'distance': 10}}\n",
"{'name': 'control_drone_movement', 'arguments': {'direction': 'up', 'distance': 20}}\n",
"\u001b[34m15.8% complete\u001b[0m\n",
"{'name': 'control_drone_movement', 'arguments': {'direction': 'down', 'distance': 10}}\n",
"\u001b[34m17.5% complete\u001b[0m\n",
@ -946,7 +925,7 @@
"\u001b[34m28.1% complete\u001b[0m\n",
"{'name': 'control_camera', 'arguments': {'mode': 'panorama', 'duration': 0}}\n",
"\u001b[34m29.8% complete\u001b[0m\n",
"{'name': 'control_gimbal', 'arguments': {'tilt': 45, 'pan': 90}}\n",
"{'name': 'control_gimbal', 'arguments': {'tilt': 45, 'pan': 30}}\n",
"\u001b[34m31.6% complete\u001b[0m\n",
"{'name': 'set_drone_lighting', 'arguments': {'mode': 'on'}}\n",
"\u001b[34m33.3% complete\u001b[0m\n",
@ -1029,7 +1008,7 @@
}
],
"source": [
"training_examples_unformatted = create_commands(input_objects)\n"
"training_examples_unformatted = create_commands(input_objects)"
]
},
{
@ -1041,7 +1020,7 @@
},
{
"cell_type": "code",
"execution_count": 17,
"execution_count": 24,
"metadata": {},
"outputs": [],
"source": [
@ -1069,7 +1048,7 @@
},
{
"cell_type": "code",
"execution_count": 18,
"execution_count": 25,
"metadata": {},
"outputs": [],
"source": [
@ -1092,7 +1071,7 @@
},
{
"cell_type": "code",
"execution_count": 19,
"execution_count": 26,
"metadata": {},
"outputs": [],
"source": [
@ -1115,7 +1094,7 @@
},
{
"cell_type": "code",
"execution_count": 20,
"execution_count": 27,
"metadata": {},
"outputs": [],
"source": [
@ -1124,7 +1103,7 @@
},
{
"cell_type": "code",
"execution_count": 21,
"execution_count": 28,
"metadata": {},
"outputs": [],
"source": [
@ -1171,7 +1150,6 @@
" file_id = file.id\n",
" print(file_id)\n",
" ft = client.fine_tuning.jobs.create(\n",
" # model=\"gpt-4-0613\",\n",
" model=\"gpt-3.5-turbo\",\n",
" training_file=file_id,\n",
")\n"
@ -1224,7 +1202,7 @@
" messages = []\n",
" messages.append({\"role\": \"system\", \"content\": DRONE_SYSTEM_PROMPT})\n",
" messages.append({\"role\": \"user\", \"content\": eval_question})\n",
" completion = get_chat_completion(model=\"ft:gpt-3.5-turbo-0613:openai-internal::8DloQKS2\",messages=messages,functions=function_list)\n",
" completion = get_chat_completion(model=\"ft:gpt-3.5-turbo-0613:openai-internal::8DloQKS2\",messages=messages,tools=function_list)\n",
" print(eval_question)\n",
" print(completion.tool_calls[0].function.name,'\\n')\n"
]
@ -1267,7 +1245,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.16"
"version": "3.11.5"
}
},
"nbformat": 4,

@ -58,12 +58,11 @@
"outputs": [],
"source": [
"import json\n",
"import openai\n",
"from openai import OpenAI\n",
"import os\n",
"import requests\n",
"\n",
"client = OpenAI()\n"
"client = OpenAI(api_key=os.environ.get(\"OPENAI_API_KEY\", \"<your OpenAI API key if not set as env var>\"))"
]
},
{
@ -228,7 +227,7 @@
},
{
"cell_type": "code",
"execution_count": 5,
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
@ -252,33 +251,36 @@
" {\"role\": \"user\", \"content\": user_input}\n",
"],\n",
" temperature=0,\n",
" functions=[\n",
" tools=[\n",
" {\n",
" \"name\": \"call_google_places_api\",\n",
" \"description\": \"This function calls the Google Places API to find the top places of a specified type near a specific location. It can be used when a user expresses a need (e.g., feeling hungry or tired) or wants to find a certain type of place (e.g., restaurant or hotel).\",\n",
" \"parameters\": {\n",
" \"type\": \"object\",\n",
" \"properties\": {\n",
" \"place_type\": {\n",
" \"type\": \"string\",\n",
" \"description\": \"The type of place to search for.\"\n",
" \"type\": \"function\",\n",
" \"function\" : {\n",
" \"name\": \"call_google_places_api\",\n",
" \"description\": \"This function calls the Google Places API to find the top places of a specified type near a specific location. It can be used when a user expresses a need (e.g., feeling hungry or tired) or wants to find a certain type of place (e.g., restaurant or hotel).\",\n",
" \"parameters\": {\n",
" \"type\": \"object\",\n",
" \"properties\": {\n",
" \"place_type\": {\n",
" \"type\": \"string\",\n",
" \"description\": \"The type of place to search for.\"\n",
" }\n",
" }\n",
" },\n",
" \"result\": {\n",
" \"type\": \"array\",\n",
" \"items\": {\n",
" \"type\": \"string\"\n",
" }\n",
" }\n",
" },\n",
" \"result\": {\n",
" \"type\": \"array\",\n",
" \"items\": {\n",
" \"type\": \"string\"\n",
" }\n",
" }\n",
" }\n",
" ],\n",
" )\n",
"\n",
" print(response.choices[0].message.function_call)\n",
" print(response.choices[0].message.tool_calls)\n",
"\n",
" if response.choices[0].finish_reason=='function_call':\n",
" function_call = response.choices[0].message.function_call\n",
" if response.choices[0].finish_reason=='tool_calls':\n",
" function_call = response.choices[0].message.tool_calls[0].function\n",
" if function_call.name == \"call_google_places_api\":\n",
" place_type = json.loads(function_call.arguments)[\"place_type\"]\n",
" places = call_google_places_api(user_id, place_type, food_preference)\n",
@ -302,15 +304,15 @@
},
{
"cell_type": "code",
"execution_count": 6,
"execution_count": 8,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"FunctionCall(arguments='{\\n \"place_type\": \"restaurant\"\\n}', name='call_google_places_api')\n",
"I couldn't find any places of interest nearby.\n"
"[ChatCompletionMessageToolCall(id='call_Q1mXIi7D6GhobfE4tkruX7nB', function=Function(arguments='{\\n \"place_type\": \"restaurant\"\\n}', name='call_google_places_api'), type='function')]\n",
"Here are some places you might be interested in: Sotto Mare is a restaurant located at 552 Green Street. It has a rating of 4.6 based on 3765 user reviews. Mona Lisa Restaurant is a restaurant located at 353 Columbus Avenue #3907. It has a rating of 4.4 based on 1888 user reviews.\n"
]
}
],
@ -338,7 +340,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.16"
"version": "3.11.5"
},
"orig_nbformat": 4
},

File diff suppressed because one or more lines are too long

@ -27,7 +27,7 @@
"import os\n",
"import requests\n",
"\n",
"client = OpenAI()"
"client = OpenAI(api_key=os.environ.get(\"OPENAI_API_KEY\", \"<your OpenAI API key if not set as env var>\"))"
]
},
{

@ -27,109 +27,14 @@
},
{
"cell_type": "code",
"execution_count": 1,
"execution_count": null,
"id": "80e71f33",
"metadata": {
"pycharm": {
"is_executing": true
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/PyYAML-6.0-py3.11.egg-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n",
"\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/PyYAML-6.0-py3.11.egg-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n",
"\u001b[0mRequirement already satisfied: scipy in /opt/homebrew/lib/python3.11/site-packages (1.10.1)\n",
"Requirement already satisfied: numpy<1.27.0,>=1.19.5 in /opt/homebrew/lib/python3.11/site-packages (from scipy) (1.24.3)\n",
"\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/PyYAML-6.0-py3.11.egg-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n",
"\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/PyYAML-6.0-py3.11.egg-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n",
"\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/PyYAML-6.0-py3.11.egg-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n",
"\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/PyYAML-6.0-py3.11.egg-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n",
"\u001b[0mRequirement already satisfied: tenacity in /opt/homebrew/lib/python3.11/site-packages (8.2.2)\n",
"\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/PyYAML-6.0-py3.11.egg-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n",
"\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/PyYAML-6.0-py3.11.egg-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n",
"\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/PyYAML-6.0-py3.11.egg-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n",
"\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/PyYAML-6.0-py3.11.egg-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n",
"\u001b[0mRequirement already satisfied: tiktoken in /opt/homebrew/lib/python3.11/site-packages (0.4.0)\n",
"Requirement already satisfied: regex>=2022.1.18 in /opt/homebrew/lib/python3.11/site-packages (from tiktoken) (2023.6.3)\n",
"Requirement already satisfied: requests>=2.26.0 in /opt/homebrew/lib/python3.11/site-packages (from tiktoken) (2.30.0)\n",
"Requirement already satisfied: charset-normalizer<4,>=2 in /opt/homebrew/lib/python3.11/site-packages (from requests>=2.26.0->tiktoken) (3.1.0)\n",
"Requirement already satisfied: idna<4,>=2.5 in /opt/homebrew/lib/python3.11/site-packages (from requests>=2.26.0->tiktoken) (3.4)\n",
"Requirement already satisfied: urllib3<3,>=1.21.1 in /opt/homebrew/lib/python3.11/site-packages (from requests>=2.26.0->tiktoken) (1.25.11)\n",
"Requirement already satisfied: certifi>=2017.4.17 in /opt/homebrew/lib/python3.11/site-packages (from requests>=2.26.0->tiktoken) (2023.5.7)\n",
"\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/PyYAML-6.0-py3.11.egg-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n",
"\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/PyYAML-6.0-py3.11.egg-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n",
"\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/PyYAML-6.0-py3.11.egg-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n",
"\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/PyYAML-6.0-py3.11.egg-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n",
"\u001b[0mRequirement already satisfied: termcolor in /opt/homebrew/lib/python3.11/site-packages (2.3.0)\n",
"\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/PyYAML-6.0-py3.11.egg-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n",
"\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/PyYAML-6.0-py3.11.egg-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n",
"\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/PyYAML-6.0-py3.11.egg-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n",
"\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/PyYAML-6.0-py3.11.egg-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n",
"\u001b[0mRequirement already satisfied: openai in /opt/homebrew/lib/python3.11/site-packages (0.27.6)\n",
"Requirement already satisfied: requests>=2.20 in /opt/homebrew/lib/python3.11/site-packages (from openai) (2.30.0)\n",
"Requirement already satisfied: tqdm in /opt/homebrew/lib/python3.11/site-packages (from openai) (4.65.0)\n",
"Requirement already satisfied: aiohttp in /opt/homebrew/lib/python3.11/site-packages (from openai) (3.8.4)\n",
"Requirement already satisfied: charset-normalizer<4,>=2 in /opt/homebrew/lib/python3.11/site-packages (from requests>=2.20->openai) (3.1.0)\n",
"Requirement already satisfied: idna<4,>=2.5 in /opt/homebrew/lib/python3.11/site-packages (from requests>=2.20->openai) (3.4)\n",
"Requirement already satisfied: urllib3<3,>=1.21.1 in /opt/homebrew/lib/python3.11/site-packages (from requests>=2.20->openai) (1.25.11)\n",
"Requirement already satisfied: certifi>=2017.4.17 in /opt/homebrew/lib/python3.11/site-packages (from requests>=2.20->openai) (2023.5.7)\n",
"Requirement already satisfied: attrs>=17.3.0 in /opt/homebrew/lib/python3.11/site-packages (from aiohttp->openai) (23.1.0)\n",
"Requirement already satisfied: multidict<7.0,>=4.5 in /opt/homebrew/lib/python3.11/site-packages (from aiohttp->openai) (6.0.4)\n",
"Requirement already satisfied: async-timeout<5.0,>=4.0.0a3 in /opt/homebrew/lib/python3.11/site-packages (from aiohttp->openai) (4.0.2)\n",
"Requirement already satisfied: yarl<2.0,>=1.0 in /opt/homebrew/lib/python3.11/site-packages (from aiohttp->openai) (1.9.2)\n",
"Requirement already satisfied: frozenlist>=1.1.1 in /opt/homebrew/lib/python3.11/site-packages (from aiohttp->openai) (1.3.3)\n",
"Requirement already satisfied: aiosignal>=1.1.2 in /opt/homebrew/lib/python3.11/site-packages (from aiohttp->openai) (1.3.1)\n",
"\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/PyYAML-6.0-py3.11.egg-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n",
"\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/PyYAML-6.0-py3.11.egg-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n",
"\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/PyYAML-6.0-py3.11.egg-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n",
"\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/PyYAML-6.0-py3.11.egg-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n",
"\u001b[0mRequirement already satisfied: requests in /opt/homebrew/lib/python3.11/site-packages (2.30.0)\n",
"Requirement already satisfied: charset-normalizer<4,>=2 in /opt/homebrew/lib/python3.11/site-packages (from requests) (3.1.0)\n",
"Requirement already satisfied: idna<4,>=2.5 in /opt/homebrew/lib/python3.11/site-packages (from requests) (3.4)\n",
"Requirement already satisfied: urllib3<3,>=1.21.1 in /opt/homebrew/lib/python3.11/site-packages (from requests) (1.25.11)\n",
"Requirement already satisfied: certifi>=2017.4.17 in /opt/homebrew/lib/python3.11/site-packages (from requests) (2023.5.7)\n",
"\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/PyYAML-6.0-py3.11.egg-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n",
"\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/PyYAML-6.0-py3.11.egg-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n",
"\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/PyYAML-6.0-py3.11.egg-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n",
"\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/PyYAML-6.0-py3.11.egg-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n",
"\u001b[0mRequirement already satisfied: arxiv in /opt/homebrew/lib/python3.11/site-packages (1.4.7)\n",
"Requirement already satisfied: feedparser in /opt/homebrew/lib/python3.11/site-packages (from arxiv) (6.0.10)\n",
"Requirement already satisfied: sgmllib3k in /opt/homebrew/lib/python3.11/site-packages (from feedparser->arxiv) (1.0.0)\n",
"\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/PyYAML-6.0-py3.11.egg-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n",
"\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/PyYAML-6.0-py3.11.egg-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n",
"\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/PyYAML-6.0-py3.11.egg-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n",
"\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/PyYAML-6.0-py3.11.egg-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[0mRequirement already satisfied: pandas in /opt/homebrew/lib/python3.11/site-packages (2.0.1)\n",
"Requirement already satisfied: python-dateutil>=2.8.2 in /opt/homebrew/lib/python3.11/site-packages (from pandas) (2.8.2)\n",
"Requirement already satisfied: pytz>=2020.1 in /opt/homebrew/lib/python3.11/site-packages (from pandas) (2023.3)\n",
"Requirement already satisfied: tzdata>=2022.1 in /opt/homebrew/lib/python3.11/site-packages (from pandas) (2023.3)\n",
"Requirement already satisfied: numpy>=1.21.0 in /opt/homebrew/lib/python3.11/site-packages (from pandas) (1.24.3)\n",
"Requirement already satisfied: six>=1.5 in /opt/homebrew/lib/python3.11/site-packages (from python-dateutil>=2.8.2->pandas) (1.16.0)\n",
"\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/PyYAML-6.0-py3.11.egg-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n",
"\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/PyYAML-6.0-py3.11.egg-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n",
"\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/PyYAML-6.0-py3.11.egg-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n",
"\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/PyYAML-6.0-py3.11.egg-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n",
"\u001b[0mRequirement already satisfied: PyPDF2 in /opt/homebrew/lib/python3.11/site-packages (3.0.1)\n",
"\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/PyYAML-6.0-py3.11.egg-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n",
"\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/PyYAML-6.0-py3.11.egg-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n",
"\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/PyYAML-6.0-py3.11.egg-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n",
"\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/PyYAML-6.0-py3.11.egg-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n",
"\u001b[0mRequirement already satisfied: tqdm in /opt/homebrew/lib/python3.11/site-packages (4.65.0)\n",
"\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/PyYAML-6.0-py3.11.egg-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n",
"\u001b[0m\u001b[33mWARNING: Skipping /opt/homebrew/lib/python3.11/site-packages/PyYAML-6.0-py3.11.egg-info due to invalid metadata entry 'name'\u001b[0m\u001b[33m\n",
"\u001b[0m"
]
}
],
"outputs": [],
"source": [
"!pip install scipy\n",
"!pip install tenacity\n",
@ -169,7 +74,9 @@
"from tqdm import tqdm\n",
"from termcolor import colored\n",
"\n",
"GPT_MODEL = \"gpt-3.5-turbo-0613\"\n",
"client = openai.OpenAI(api_key=os.environ.get(\"OPENAI_API_KEY\", \"<your OpenAI API key if not set as env var>\"))\n",
"\n",
"GPT_MODEL = \"gpt-3.5-turbo\"\n",
"EMBEDDING_MODEL = \"text-embedding-ada-002\"\n"
]
},
@ -230,7 +137,7 @@
"source": [
"@retry(wait=wait_random_exponential(min=1, max=40), stop=stop_after_attempt(3))\n",
"def embedding_request(text):\n",
" response = openai.Embedding.create(input=text, model=EMBEDDING_MODEL)\n",
" response = client.embeddings.create(input=text, model=EMBEDDING_MODEL)\n",
" return response\n",
"\n",
"\n",
@ -257,7 +164,7 @@
" file_reference = [\n",
" result.title,\n",
" result.download_pdf(data_dir),\n",
" response[\"data\"][0][\"embedding\"],\n",
" response.data[0].embedding,\n",
" ]\n",
"\n",
" # Write to file\n",
@ -309,7 +216,7 @@
") -> list[str]:\n",
" \"\"\"Returns a list of strings and relatednesses, sorted from most related to least.\"\"\"\n",
" query_embedding_response = embedding_request(query)\n",
" query_embedding = query_embedding_response[\"data\"][0][\"embedding\"]\n",
" query_embedding = query_embedding_response.data[0].embedding\n",
" strings_and_relatednesses = [\n",
" (row[\"filepath\"], relatedness_fn(query_embedding, row[\"embedding\"]))\n",
" for i, row in df.iterrows()\n",
@ -362,10 +269,10 @@
"def extract_chunk(content, template_prompt):\n",
" \"\"\"This function applies a prompt to some input content. In this case it returns a summarized chunk of text\"\"\"\n",
" prompt = template_prompt + content\n",
" response = openai.ChatCompletion.create(\n",
" response = openai.chat.completions.create(\n",
" model=GPT_MODEL, messages=[{\"role\": \"user\", \"content\": prompt}], temperature=0\n",
" )\n",
" return response[\"choices\"][0][\"message\"][\"content\"]\n",
" return response.choices[0].message.content\n",
"\n",
"\n",
"def summarize_text(query):\n",
@ -418,7 +325,7 @@
"\n",
" # Final summary\n",
" print(\"Summarizing into overall summary\")\n",
" response = openai.ChatCompletion.create(\n",
" response = client.chat.completions.create(\n",
" model=GPT_MODEL,\n",
" messages=[\n",
" {\n",
@ -498,7 +405,7 @@
}
],
"source": [
"print(chat_test_response[\"choices\"][0][\"message\"][\"content\"])\n"
"print(chat_test_response.choices[0].message.content)\n"
]
},
{
@ -527,7 +434,7 @@
" }\n",
" json_data = {\"model\": model, \"messages\": messages}\n",
" if functions is not None:\n",
" json_data.update({\"functions\": functions})\n",
" json_data.update({\"tools\": functions})\n",
" try:\n",
" response = requests.post(\n",
" \"https://api.openai.com/v1/chat/completions\",\n",
@ -561,7 +468,7 @@
" \"system\": \"red\",\n",
" \"user\": \"green\",\n",
" \"assistant\": \"blue\",\n",
" \"function\": \"magenta\",\n",
" \"tools\": \"magenta\",\n",
" }\n",
" for message in self.conversation_history:\n",
" print(\n",
@ -581,38 +488,44 @@
"source": [
"# Initiate our get_articles and read_article_and_summarize functions\n",
"arxiv_functions = [\n",
" {\n",
" \"name\": \"get_articles\",\n",
" \"description\": \"\"\"Use this function to get academic papers from arXiv to answer user questions.\"\"\",\n",
" \"parameters\": {\n",
" \"type\": \"object\",\n",
" \"properties\": {\n",
" \"query\": {\n",
" \"type\": \"string\",\n",
" \"description\": f\"\"\"\n",
" User query in JSON. Responses should be summarized and should include the article URL reference\n",
" \"\"\",\n",
" }\n",
" { \n",
" \"type\": \"function\",\n",
" \"function\": {\n",
" \"name\": \"get_articles\",\n",
" \"description\": \"\"\"Use this function to get academic papers from arXiv to answer user questions.\"\"\",\n",
" \"parameters\": {\n",
" \"type\": \"object\",\n",
" \"properties\": {\n",
" \"query\": {\n",
" \"type\": \"string\",\n",
" \"description\": f\"\"\"\n",
" User query in JSON. Responses should be summarized and should include the article URL reference\n",
" \"\"\",\n",
" }\n",
" },\n",
" \"required\": [\"query\"],\n",
" },\n",
" \"required\": [\"query\"],\n",
" },\n",
" }\n",
" },\n",
" {\n",
" \"name\": \"read_article_and_summarize\",\n",
" \"description\": \"\"\"Use this function to read whole papers and provide a summary for users.\n",
" You should NEVER call this function before get_articles has been called in the conversation.\"\"\",\n",
" \"parameters\": {\n",
" \"type\": \"object\",\n",
" \"properties\": {\n",
" \"query\": {\n",
" \"type\": \"string\",\n",
" \"description\": f\"\"\"\n",
" Description of the article in plain text based on the user's query\n",
" \"\"\",\n",
" }\n",
" \"type\": \"function\",\n",
" \"function\": {\n",
" \"name\": \"read_article_and_summarize\",\n",
" \"description\": \"\"\"Use this function to read whole papers and provide a summary for users.\n",
" You should NEVER call this function before get_articles has been called in the conversation.\"\"\",\n",
" \"parameters\": {\n",
" \"type\": \"object\",\n",
" \"properties\": {\n",
" \"query\": {\n",
" \"type\": \"string\",\n",
" \"description\": f\"\"\"\n",
" Description of the article in plain text based on the user's query\n",
" \"\"\",\n",
" }\n",
" },\n",
" \"required\": [\"query\"],\n",
" },\n",
" \"required\": [\"query\"],\n",
" },\n",
" }\n",
" }\n",
"]\n"
]
@ -627,8 +540,8 @@
"def chat_completion_with_function_execution(messages, functions=[None]):\n",
" \"\"\"This function makes a ChatCompletion API call with the option of adding functions\"\"\"\n",
" response = chat_completion_request(messages, functions)\n",
" full_message = response.json()[\"choices\"][0]\n",
" if full_message[\"finish_reason\"] == \"function_call\":\n",
" full_message = response.json().choices[0]\n",
" if full_message.finish_reason == \"tool_calls\":\n",
" print(f\"Function generation requested, calling function\")\n",
" return call_arxiv_function(messages, full_message)\n",
" else:\n",
@ -640,10 +553,10 @@
" \"\"\"Function calling function which executes function calls when the model believes it is necessary.\n",
" Currently extended by adding clauses to this if statement.\"\"\"\n",
"\n",
" if full_message[\"message\"][\"function_call\"][\"name\"] == \"get_articles\":\n",
" if full_message.message.tool_calls[0].function.name == \"get_articles\":\n",
" try:\n",
" parsed_output = json.loads(\n",
" full_message[\"message\"][\"function_call\"][\"arguments\"]\n",
" full_message.message.tool_calls[0].function.arguments\n",
" )\n",
" print(\"Getting search results\")\n",
" results = get_articles(parsed_output[\"query\"])\n",
@ -653,8 +566,8 @@
" print(f\"Error message: {e}\")\n",
" messages.append(\n",
" {\n",
" \"role\": \"function\",\n",
" \"name\": full_message[\"message\"][\"function_call\"][\"name\"],\n",
" \"role\": \"tool\",\n",
" \"tool_call_id\": full_message.message.tool_calls[0].id,\n",
" \"content\": str(results),\n",
" }\n",
" )\n",
@ -667,10 +580,10 @@
" raise Exception(\"Function chat request failed\")\n",
"\n",
" elif (\n",
" full_message[\"message\"][\"function_call\"][\"name\"] == \"read_article_and_summarize\"\n",
" full_message.message.tool_calls[0].function.name == \"read_article_and_summarize\"\n",
" ):\n",
" parsed_output = json.loads(\n",
" full_message[\"message\"][\"function_call\"][\"arguments\"]\n",
" full_message.message.tool_calls[0].function.arguments\n",
" )\n",
" print(\"Finding and reading paper\")\n",
" summary = summarize_text(parsed_output[\"query\"])\n",
@ -770,7 +683,7 @@
"chat_response = chat_completion_with_function_execution(\n",
" paper_conversation.conversation_history, functions=arxiv_functions\n",
")\n",
"assistant_message = chat_response[\"choices\"][0][\"message\"][\"content\"]\n",
"assistant_message = chat_response.choices[0].message.content\n",
"paper_conversation.add_message(\"assistant\", assistant_message)\n",
"display(Markdown(assistant_message))\n"
]
@ -841,7 +754,7 @@
"updated_response = chat_completion_with_function_execution(\n",
" paper_conversation.conversation_history, functions=arxiv_functions\n",
")\n",
"display(Markdown(updated_response[\"choices\"][0][\"message\"][\"content\"]))\n"
"display(Markdown(updated_response.choices[0].message.content))\n"
]
}
],

@ -12,7 +12,7 @@
"\n",
"`tools` is an optional parameter in the Chat Completion API which can be used to provide function specifications. The purpose of this is to enable models to generate function arguments which adhere to the provided specifications. Note that the API will not actually execute any function calls. It is up to developers to execute function calls using model outputs.\n",
"\n",
"Within the `tools` parameter, if the `functions` parameter is provided then by default the model will decide when it is appropriate to use one of the functions. The API can be forced to use a specific function by setting the `tool_choice` parameter to `{\"name\": \"<insert-function-name>\"}`. The API can also be forced to not use any function by setting the `tool_choice` parameter to `\"none\"`. If a function is used, the output will contain `\"finish_reason\": \"function_call\"` in the response, as well as a `tool_choice` object that has the name of the function and the generated function arguments.\n",
"Within the `tools` parameter, if the `functions` parameter is provided then by default the model will decide when it is appropriate to use one of the functions. The API can be forced to use a specific function by setting the `tool_choice` parameter to `{\"type\": \"function\", \"function\": {\"name\": \"<insert-function-name>\"}}`. The API can also be forced to not use any function by setting the `tool_choice` parameter to `\"none\"`. If a function is used, the output will contain `\"finish_reason\": \"tool_calls\"` in the response, as well as a `tool_choice` object that has the name of the function and the generated function arguments. For details, see the API [Documentation](https://platform.openai.com/docs/api-reference/chat/create)\n",
"\n",
"### Overview\n",
"\n",
@ -63,6 +63,8 @@
"from tenacity import retry, wait_random_exponential, stop_after_attempt\n",
"from termcolor import colored\n",
"\n",
"openai.api_key = \"YOUR_API_KEY\" # or set via environment variable 'OPENAI_API_KEY'\n",
"\n",
"GPT_MODEL = \"gpt-3.5-turbo-0613\""
]
},

@ -89,7 +89,7 @@
},
{
"cell_type": "code",
"execution_count": 2,
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
@ -433,7 +433,7 @@
},
{
"cell_type": "code",
"execution_count": 14,
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
@ -480,7 +480,7 @@
},
{
"cell_type": "code",
"execution_count": 15,
"execution_count": 4,
"metadata": {},
"outputs": [
{
@ -519,7 +519,10 @@
"source": [
"# let's verify the function above matches the OpenAI API response\n",
"\n",
"import openai\n",
"from openai import OpenAI\n",
"import os\n",
"\n",
"client = OpenAI(api_key=os.environ.get(\"OPENAI_API_KEY\", \"<your OpenAI API key if not set as env var>\"))\n",
"\n",
"example_messages = [\n",
" {\n",
@ -564,15 +567,20 @@
" # example token count from the function defined above\n",
" print(f\"{num_tokens_from_messages(example_messages, model)} prompt tokens counted by num_tokens_from_messages().\")\n",
" # example token count from the OpenAI API\n",
" response = openai.ChatCompletion.create(\n",
" model=model,\n",
" messages=example_messages,\n",
" temperature=0,\n",
" max_tokens=1, # we're only counting input tokens here, so let's not waste tokens on the output\n",
" )\n",
" print(f'{response[\"usage\"][\"prompt_tokens\"]} prompt tokens counted by the OpenAI API.')\n",
" response = client.chat.completions.create(model=model,\n",
" messages=example_messages,\n",
" temperature=0,\n",
" max_tokens=1)\n",
" print(f'{response.usage.prompt_tokens} prompt tokens counted by the OpenAI API.')\n",
" print()\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
@ -591,7 +599,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.13"
"version": "3.11.5"
},
"vscode": {
"interpreter": {

@ -53,8 +53,7 @@
"import pandas as pd\n",
"from pprint import pprint\n",
"\n",
"OPENAI_API_KEY = os.getenv(\"OPENAI_API_KEY\", \"\")\n",
"openai.api_key = OPENAI_API_KEY"
"client = openai.OpenAI(api_key=os.environ.get(\"OPENAI_API_KEY\", \"<your OpenAI API key if not set as env var>\"))"
]
},
{
@ -421,14 +420,14 @@
],
"source": [
"with open(training_file_name, \"rb\") as training_fd:\n",
" training_response = openai.files.create(\n",
" training_response = client.files.create(\n",
" file=training_fd, purpose=\"fine-tune\"\n",
" )\n",
"\n",
"training_file_id = training_response.id\n",
"\n",
"with open(validation_file_name, \"rb\") as validation_fd:\n",
" validation_response = openai.files.create(\n",
" validation_response = client.files.create(\n",
" file=validation_fd, purpose=\"fine-tune\"\n",
" )\n",
"validation_file_id = validation_response.id\n",
@ -465,7 +464,7 @@
}
],
"source": [
"response = openai.fine_tuning.jobs.create(\n",
"response = client.fine_tuning.jobs.create(\n",
" training_file=training_file_id,\n",
" validation_file=validation_file_id,\n",
" model=\"gpt-3.5-turbo\",\n",
@ -507,7 +506,7 @@
}
],
"source": [
"response = openai.fine_tuning.jobs.retrieve(job_id)\n",
"response = client.fine_tuning.jobs.retrieve(job_id)\n",
"\n",
"print(\"Job ID:\", response.id)\n",
"print(\"Status:\", response.status)\n",
@ -556,7 +555,7 @@
}
],
"source": [
"response = openai.fine_tuning.jobs.list_events(job_id)\n",
"response = client.fine_tuning.jobs.list_events(job_id)\n",
"\n",
"events = response.data\n",
"events.reverse()\n",
@ -588,7 +587,7 @@
}
],
"source": [
"response = openai.fine_tuning.jobs.retrieve(job_id)\n",
"response = client.fine_tuning.jobs.retrieve(job_id)\n",
"fine_tuned_model_id = response.fine_tuned_model\n",
"\n",
"if fine_tuned_model_id is None: \n",
@ -664,7 +663,7 @@
}
],
"source": [
"response = openai.chat.completions.create(\n",
"response = client.chat.completions.create(\n",
" model=fine_tuned_model_id, messages=test_messages, temperature=0, max_tokens=500\n",
")\n",
"print(response.choices[0].message.content)"

@ -36,12 +36,15 @@
},
{
"cell_type": "code",
"execution_count": 2,
"execution_count": 22,
"metadata": {},
"outputs": [],
"source": [
"# import the OpenAI Python library for calling the OpenAI API\n",
"import openai\n"
"from openai import OpenAI\n",
"import os\n",
"\n",
"client = OpenAI(api_key=os.environ.get(\"OPENAI_API_KEY\", \"<your OpenAI API key if not set as env var>\"))"
]
},
{
@ -49,17 +52,37 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"## 2. An example chat API call\n",
"## 2. An example chat completion API call\n",
"\n",
"A chat API call has two required inputs:\n",
"- `model`: the name of the model you want to use (e.g., `gpt-3.5-turbo`, `gpt-4`, `gpt-3.5-turbo-0613`, `gpt-3.5-turbo-16k-0613`)\n",
"A chat completion API call parameters,\n",
"**Required**\n",
"- `model`: the name of the model you want to use (e.g., `gpt-3.5-turbo`, `gpt-4`, `gpt-3.5-turbo-16k-1106`)\n",
"- `messages`: a list of message objects, where each object has two required fields:\n",
" - `role`: the role of the messenger (either `system`, `user`, or `assistant`)\n",
" - `role`: the role of the messenger (either `system`, `user`, `assistant` or `tool`)\n",
" - `content`: the content of the message (e.g., `Write me a beautiful poem`)\n",
"\n",
"Messages can also contain an optional `name` field, which give the messenger a name. E.g., `example-user`, `Alice`, `BlackbeardBot`. Names may not contain spaces.\n",
"\n",
"As of June 2023, you can also optionally submit a list of `functions` that tell GPT whether it can generate JSON to feed into a function. For details, see the [documentation](https://platform.openai.com/docs/guides/gpt/function-calling), [API reference](https://platform.openai.com/docs/api-reference/chat), or the Cookbook guide [How to call functions with chat models](How_to_call_functions_with_chat_models.ipynb).\n",
"**Optional**\n",
"- `frequency_penalty`: Penalizes tokens based on their frequency, reducing repetition.\n",
"- `logit_bias`: Modifies likelihood of specified tokens with bias values.\n",
"- `logprobs`: Returns log probabilities of output tokens if true.\n",
"- `top_logprobs`: Specifies the number of most likely tokens to return at each position.\n",
"- `max_tokens`: Sets the maximum number of generated tokens in chat completion.\n",
"- `n`: Generates a specified number of chat completion choices for each input.\n",
"- `presence_penalty`: Penalizes new tokens based on their presence in the text.\n",
"- `response_format`: Specifies the output format, e.g., JSON mode.\n",
"- `seed`: Ensures deterministic sampling with a specified seed.\n",
"- `stop`: Specifies up to 4 sequences where the API should stop generating tokens.\n",
"- `stream`: Sends partial message deltas as tokens become available.\n",
"- `temperature`: Sets the sampling temperature between 0 and 2.\n",
"- `top_p`: Uses nucleus sampling; considers tokens with top_p probability mass.\n",
"- `tools`: Lists functions the model may call.\n",
"- `tool_choice`: Controls the model's function calls (none/auto/function).\n",
"- `user`: Unique identifier for end-user monitoring and abuse detection.\n",
"\n",
"\n",
"As of January 2024, you can also optionally submit a list of `functions` that tell GPT whether it can generate JSON to feed into a function. For details, see the [documentation](https://platform.openai.com/docs/guides/function-calling), [API reference](https://platform.openai.com/docs/api-reference/chat), or the Cookbook guide [How to call functions with chat models](How_to_call_functions_with_chat_models.ipynb).\n",
"\n",
"Typically, a conversation will start with a system message that tells the assistant how to behave, followed by alternating user and assistant messages, but you are not required to follow this format.\n",
"\n",
@ -68,44 +91,13 @@
},
{
"cell_type": "code",
"execution_count": 3,
"execution_count": 2,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<OpenAIObject chat.completion id=chatcmpl-7UkgnSDzlevZxiy0YjZcLYdUMz5yZ at 0x118e394f0> JSON: {\n",
" \"id\": \"chatcmpl-7UkgnSDzlevZxiy0YjZcLYdUMz5yZ\",\n",
" \"object\": \"chat.completion\",\n",
" \"created\": 1687563669,\n",
" \"model\": \"gpt-3.5-turbo-0301\",\n",
" \"choices\": [\n",
" {\n",
" \"index\": 0,\n",
" \"message\": {\n",
" \"role\": \"assistant\",\n",
" \"content\": \"Orange who?\"\n",
" },\n",
" \"finish_reason\": \"stop\"\n",
" }\n",
" ],\n",
" \"usage\": {\n",
" \"prompt_tokens\": 39,\n",
" \"completion_tokens\": 3,\n",
" \"total_tokens\": 42\n",
" }\n",
"}"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"outputs": [],
"source": [
"# Example OpenAI Python library request\n",
"MODEL = \"gpt-3.5-turbo\"\n",
"response = openai.ChatCompletion.create(\n",
"response = client.chat.completions.create(\n",
" model=MODEL,\n",
" messages=[\n",
" {\"role\": \"system\", \"content\": \"You are a helpful assistant.\"},\n",
@ -114,9 +106,48 @@
" {\"role\": \"user\", \"content\": \"Orange.\"},\n",
" ],\n",
" temperature=0,\n",
")\n",
"\n",
"response\n"
")\n"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"{\n",
" \"id\": \"chatcmpl-8dee9DuEFcg2QILtT2a6EBXZnpirM\",\n",
" \"choices\": [\n",
" {\n",
" \"finish_reason\": \"stop\",\n",
" \"index\": 0,\n",
" \"logprobs\": null,\n",
" \"message\": {\n",
" \"content\": \"Orange who?\",\n",
" \"role\": \"assistant\",\n",
" \"function_call\": null,\n",
" \"tool_calls\": null\n",
" }\n",
" }\n",
" ],\n",
" \"created\": 1704461729,\n",
" \"model\": \"gpt-3.5-turbo-0613\",\n",
" \"object\": \"chat.completion\",\n",
" \"system_fingerprint\": null,\n",
" \"usage\": {\n",
" \"completion_tokens\": 3,\n",
" \"prompt_tokens\": 35,\n",
" \"total_tokens\": 38\n",
" }\n",
"}\n"
]
}
],
"source": [
"print(json.dumps(json.loads(response.model_dump_json()), indent=4))"
]
},
{
@ -126,14 +157,19 @@
"source": [
"As you can see, the response object has a few fields:\n",
"- `id`: the ID of the request\n",
"- `object`: the type of object returned (e.g., `chat.completion`)\n",
"- `created`: the timestamp of the request\n",
"- `model`: the full name of the model used to generate the response\n",
"- `usage`: the number of tokens used to generate the replies, counting prompt, completion, and total\n",
"- `choices`: a list of completion objects (only one, unless you set `n` greater than 1)\n",
" - `message`: the message object generated by the model, with `role` and `content`\n",
" - `finish_reason`: the reason the model stopped generating text (either `stop`, or `length` if `max_tokens` limit was reached)\n",
" - `index`: the index of the completion in the list of choices"
" - `index`: The index of the choice in the list of choices.\n",
" - `logprobs`: Log probability information for the choice.\n",
" - `message`: the message object generated by the model\n",
" - `content`: content of message\n",
" - `role`: The role of the author of this message.\n",
" - `tool_calls`: The tool calls generated by the model, such as function calls. if the tools is given\n",
"- `created`: the timestamp of the request\n",
"- `model`: the full name of the model used to generate the response\n",
"- `object`: the type of object returned (e.g., `chat.completion`)\n",
"- `system_fingerprint`: This fingerprint represents the backend configuration that the model runs with.\n",
"- `usage`: the number of tokens used to generate the replies, counting prompt, completion, and total"
]
},
{
@ -146,7 +182,7 @@
},
{
"cell_type": "code",
"execution_count": 4,
"execution_count": 9,
"metadata": {},
"outputs": [
{
@ -155,13 +191,13 @@
"'Orange who?'"
]
},
"execution_count": 4,
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"response['choices'][0]['message']['content']\n"
"response.choices[0].message.content\n"
]
},
{
@ -176,20 +212,36 @@
},
{
"cell_type": "code",
"execution_count": 5,
"execution_count": 10,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Ahoy matey! Asynchronous programming be like havin' a crew o' pirates workin' on different tasks at the same time. Ye see, instead o' waitin' for one task to be completed before startin' the next, ye can assign tasks to yer crew and let 'em work on 'em simultaneously. This way, ye can get more done in less time and keep yer ship sailin' smoothly. It be like havin' a bunch o' pirates rowin' the ship at different speeds, but still gettin' us to our destination. Arrr!\n"
"Arr, me matey! Let me tell ye a tale of asynchronous programming, in the style of the fearsome pirate Blackbeard!\n",
"\n",
"Picture this, me hearties. In the vast ocean of programming, there be times when ye need to perform multiple tasks at once. But fear not, for asynchronous programming be here to save the day!\n",
"\n",
"Ye see, in traditional programming, ye be waitin' for one task to be done before movin' on to the next. But with asynchronous programming, ye can be takin' care of multiple tasks at the same time, just like a pirate multitaskin' on the high seas!\n",
"\n",
"Instead of waitin' for a task to be completed, ye can be sendin' it off on its own journey, while ye move on to the next task. It be like havin' a crew of trusty sailors, each takin' care of their own duties, without waitin' for the others.\n",
"\n",
"Now, ye may be wonderin', how does this sorcery work? Well, me matey, it be all about callbacks and promises. When ye be sendin' off a task, ye be attachin' a callback function to it. This be like leavin' a message in a bottle, tellin' the task what to do when it be finished.\n",
"\n",
"While the task be sailin' on its own, ye can be movin' on to the next task, without wastin' any precious time. And when the first task be done, it be sendin' a signal back to ye, lettin' ye know it be finished. Then ye can be takin' care of the callback function, like openin' the bottle and readin' the message inside.\n",
"\n",
"But wait, there be more! With promises, ye can be makin' even fancier arrangements. Instead of callbacks, ye be makin' a promise that the task will be completed. It be like a contract between ye and the task, swearin' that it will be done.\n",
"\n",
"Ye can be attachin' multiple promises to a task, promisin' different outcomes. And when the task be finished, it be fulfillin' the promises, lettin' ye know it be done. Then ye can be handlin' the fulfillments, like collectin' the rewards of yer pirate adventures!\n",
"\n",
"So, me hearties, that be the tale of asynchronous programming, told in the style of the fearsome pirate Blackbeard! With callbacks and promises, ye can be takin' care of multiple tasks at once, just like a pirate conquerin' the seven seas!\n"
]
}
],
"source": [
"# example with a system message\n",
"response = openai.ChatCompletion.create(\n",
"response = client.chat.completions.create(\n",
" model=MODEL,\n",
" messages=[\n",
" {\"role\": \"system\", \"content\": \"You are a helpful assistant.\"},\n",
@ -198,31 +250,43 @@
" temperature=0,\n",
")\n",
"\n",
"print(response['choices'][0]['message']['content'])\n"
"print(response.choices[0].message.content)\n"
]
},
{
"cell_type": "code",
"execution_count": 6,
"execution_count": 11,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Ahoy mateys! Let me tell ye about asynchronous programming, arrr! It be like havin' a crew of sailors workin' on different tasks at the same time, without waitin' for each other to finish. Ye see, in traditional programming, ye have to wait for one task to be completed before movin' on to the next. But with asynchronous programming, ye can start multiple tasks at once and let them run in the background while ye focus on other things.\n",
"Arr, me hearties! Gather 'round and listen up, for I be tellin' ye about the mysterious art of asynchronous programming, in the style of the fearsome pirate Blackbeard!\n",
"\n",
"It be like havin' a lookout keepin' watch for enemy ships while the rest of the crew be busy with their own tasks. They don't have to stop what they're doin' to keep an eye out, because the lookout be doin' it for them. And when the lookout spots an enemy ship, they can alert the crew and everyone can work together to defend the ship.\n",
"Now, ye see, in the world of programming, there be times when we need to perform tasks that take a mighty long time to complete. These tasks might involve fetchin' data from the depths of the internet, or performin' complex calculations that would make even Davy Jones scratch his head.\n",
"\n",
"In the same way, asynchronous programming allows different parts of yer code to work together without gettin' in each other's way. It be especially useful for tasks that take a long time to complete, like loadin' large files or connectin' to a server. Instead of makin' yer program wait for these tasks to finish, ye can let them run in the background while yer program continues to do other things.\n",
"In the olden days, we pirates used to wait patiently for each task to finish afore movin' on to the next one. But that be a waste of precious time, me hearties! We be pirates, always lookin' for ways to be more efficient and plunder more booty!\n",
"\n",
"So there ye have it, me hearties! Asynchronous programming be like havin' a crew of sailors workin' together without gettin' in each other's way. It be a powerful tool for any programmer, and one that can help ye sail the seas of code with ease!\n"
"That be where asynchronous programming comes in, me mateys. It be a way to tackle multiple tasks at once, without waitin' for each one to finish afore movin' on. It be like havin' a crew of scallywags workin' on different tasks simultaneously, while ye be overseein' the whole operation.\n",
"\n",
"Ye see, in asynchronous programming, we be breakin' down our tasks into smaller chunks called \"coroutines.\" Each coroutine be like a separate pirate, workin' on its own task. When a coroutine be startin' its work, it don't wait for the task to finish afore movin' on to the next one. Instead, it be movin' on to the next task, lettin' the first one continue in the background.\n",
"\n",
"Now, ye might be wonderin', \"But Blackbeard, how be we know when a task be finished if we don't wait for it?\" Ah, me hearties, that be where the magic of callbacks and promises come in!\n",
"\n",
"When a coroutine be startin' its work, it be attachin' a callback or a promise to it. This be like leavin' a message in a bottle, tellin' the coroutine what to do when it be finished. So, while the coroutine be workin' away, the rest of the crew be movin' on to other tasks, plunderin' more booty along the way.\n",
"\n",
"When a coroutine be finished with its task, it be sendin' a signal to the callback or fulfillin' the promise, lettin' the rest of the crew know that it be done. Then, the crew can gather 'round and handle the results of the completed task, celebratin' their victory and countin' their plunder.\n",
"\n",
"So, me hearties, asynchronous programming be like havin' a crew of pirates workin' on different tasks at once, without waitin' for each one to finish afore movin' on. It be a way to be more efficient, plunder more booty, and conquer the vast seas of programming!\n",
"\n",
"Now, set sail, me mateys, and embrace the power of asynchronous programming like true pirates of the digital realm! Arr!\n"
]
}
],
"source": [
"# example without a system message\n",
"response = openai.ChatCompletion.create(\n",
"response = client.chat.completions.create(\n",
" model=MODEL,\n",
" messages=[\n",
" {\"role\": \"user\", \"content\": \"Explain asynchronous programming in the style of the pirate Blackbeard.\"},\n",
@ -230,7 +294,7 @@
" temperature=0,\n",
")\n",
"\n",
"print(response['choices'][0]['message']['content'])\n"
"print(response.choices[0].message.content)\n"
]
},
{
@ -257,28 +321,28 @@
},
{
"cell_type": "code",
"execution_count": 7,
"execution_count": 12,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Sure! Fractions are a way of representing a part of a whole. The top number of a fraction is called the numerator, and it represents how many parts of the whole we are talking about. The bottom number is called the denominator, and it represents how many equal parts the whole is divided into.\n",
"Of course! Fractions are a way to represent parts of a whole. They are made up of two numbers: a numerator and a denominator. The numerator tells you how many parts you have, and the denominator tells you how many equal parts make up the whole.\n",
"\n",
"For example, if we have a pizza that is divided into 8 equal slices, and we take 3 slices, we can represent that as the fraction 3/8. The numerator is 3 because we took 3 slices, and the denominator is 8 because the pizza was divided into 8 slices.\n",
"Let's take an example to understand this better. Imagine you have a pizza that is divided into 8 equal slices. If you eat 3 slices, you can represent that as the fraction 3/8. Here, the numerator is 3 because you ate 3 slices, and the denominator is 8 because the whole pizza is divided into 8 slices.\n",
"\n",
"To add or subtract fractions, we need to have a common denominator. This means that the denominators of the fractions need to be the same. To do this, we can find the least common multiple (LCM) of the denominators and then convert each fraction to an equivalent fraction with the LCM as the denominator.\n",
"Fractions can also be used to represent numbers less than 1. For example, if you eat half of a pizza, you can write it as 1/2. Here, the numerator is 1 because you ate one slice, and the denominator is 2 because the whole pizza is divided into 2 equal parts.\n",
"\n",
"To multiply fractions, we simply multiply the numerators together and the denominators together. To divide fractions, we multiply the first fraction by the reciprocal of the second fraction (flip the second fraction upside down).\n",
"Now, let's talk about equivalent fractions. Equivalent fractions are different fractions that represent the same amount. For example, 1/2 and 2/4 are equivalent fractions because they both represent half of something. To find equivalent fractions, you can multiply or divide both the numerator and denominator by the same number.\n",
"\n",
"Now, here's a question to check for understanding: If we have a pizza that is divided into 12 equal slices, and we take 4 slices, what is the fraction that represents how much of the pizza we took?\n"
"Here's a question to check your understanding: If you have a cake divided into 12 equal slices and you eat 4 slices, what fraction of the cake did you eat?\n"
]
}
],
"source": [
"# An example of a system message that primes the assistant to explain concepts in great depth\n",
"response = openai.ChatCompletion.create(\n",
"response = client.chat.completions.create(\n",
" model=MODEL,\n",
" messages=[\n",
" {\"role\": \"system\", \"content\": \"You are a friendly and helpful teaching assistant. You explain concepts in great depth using simple terms, and you give examples to help people learn. At the end of each explanation, you ask a question to check for understanding\"},\n",
@ -287,25 +351,25 @@
" temperature=0,\n",
")\n",
"\n",
"print(response[\"choices\"][0][\"message\"][\"content\"])\n"
"print(response.choices[0].message.content)\n"
]
},
{
"cell_type": "code",
"execution_count": 8,
"execution_count": 13,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Fractions represent a part of a whole. They consist of a numerator (top number) and a denominator (bottom number) separated by a line. The numerator represents how many parts of the whole are being considered, while the denominator represents the total number of equal parts that make up the whole.\n"
"Fractions represent parts of a whole. They have a numerator (top number) and a denominator (bottom number).\n"
]
}
],
"source": [
"# An example of a system message that primes the assistant to give brief, to-the-point answers\n",
"response = openai.ChatCompletion.create(\n",
"response = client.chat.completions.create(\n",
" model=MODEL,\n",
" messages=[\n",
" {\"role\": \"system\", \"content\": \"You are a laconic assistant. You reply with brief, to-the-point answers with no elaboration.\"},\n",
@ -314,7 +378,7 @@
" temperature=0,\n",
")\n",
"\n",
"print(response[\"choices\"][0][\"message\"][\"content\"])\n"
"print(response.choices[0].message.content)\n"
]
},
{
@ -333,20 +397,20 @@
},
{
"cell_type": "code",
"execution_count": 9,
"execution_count": 14,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"We don't have enough time to complete the entire project perfectly.\n"
"This sudden change in direction means we don't have enough time to complete the entire project for the client.\n"
]
}
],
"source": [
"# An example of a faked few-shot conversation to prime the model into translating business jargon to simpler speech\n",
"response = openai.ChatCompletion.create(\n",
"response = client.chat.completions.create(\n",
" model=MODEL,\n",
" messages=[\n",
" {\"role\": \"system\", \"content\": \"You are a helpful, pattern-following assistant.\"},\n",
@ -361,7 +425,7 @@
" temperature=0,\n",
")\n",
"\n",
"print(response[\"choices\"][0][\"message\"][\"content\"])\n"
"print(response.choices[0].message.content)\n"
]
},
{
@ -376,20 +440,20 @@
},
{
"cell_type": "code",
"execution_count": 10,
"execution_count": 15,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"This sudden change in plans means we don't have enough time to do everything for the client's project.\n"
"This sudden change in direction means we don't have enough time to complete the entire project for the client.\n"
]
}
],
"source": [
"# The business jargon translation example, but with example names for the example messages\n",
"response = openai.ChatCompletion.create(\n",
"response = client.chat.completions.create(\n",
" model=MODEL,\n",
" messages=[\n",
" {\"role\": \"system\", \"content\": \"You are a helpful, pattern-following assistant that translates corporate jargon into plain English.\"},\n",
@ -402,7 +466,7 @@
" temperature=0,\n",
")\n",
"\n",
"print(response[\"choices\"][0][\"message\"][\"content\"])\n"
"print(response.choices[0].message.content)\n"
]
},
{
@ -444,7 +508,7 @@
},
{
"cell_type": "code",
"execution_count": 11,
"execution_count": 16,
"metadata": {},
"outputs": [],
"source": [
@ -494,35 +558,29 @@
},
{
"cell_type": "code",
"execution_count": 13,
"execution_count": 23,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"gpt-3.5-turbo-0301\n",
"127 prompt tokens counted by num_tokens_from_messages().\n",
"127 prompt tokens counted by the OpenAI API.\n",
"\n",
"gpt-3.5-turbo-0613\n",
"gpt-3.5-turbo-1106\n",
"Warning: gpt-3.5-turbo may update over time. Returning num tokens assuming gpt-3.5-turbo-0613.\n",
"129 prompt tokens counted by num_tokens_from_messages().\n",
"129 prompt tokens counted by the OpenAI API.\n",
"\n",
"gpt-3.5-turbo\n",
"Warning: gpt-3.5-turbo may update over time. Returning num tokens assuming gpt-3.5-turbo-0613.\n",
"129 prompt tokens counted by num_tokens_from_messages().\n",
"127 prompt tokens counted by the OpenAI API.\n",
"\n",
"gpt-4-0314\n",
"129 prompt tokens counted by num_tokens_from_messages().\n",
"129 prompt tokens counted by the OpenAI API.\n",
"\n",
"gpt-4-0613\n",
"gpt-4\n",
"Warning: gpt-4 may update over time. Returning num tokens assuming gpt-4-0613.\n",
"129 prompt tokens counted by num_tokens_from_messages().\n",
"129 prompt tokens counted by the OpenAI API.\n",
"\n",
"gpt-4\n",
"gpt-4-1106-preview\n",
"Warning: gpt-4 may update over time. Returning num tokens assuming gpt-4-0613.\n",
"129 prompt tokens counted by num_tokens_from_messages().\n",
"129 prompt tokens counted by the OpenAI API.\n",
@ -532,9 +590,6 @@
],
"source": [
"# let's verify the function above matches the OpenAI API response\n",
"\n",
"import openai\n",
"\n",
"example_messages = [\n",
" {\n",
" \"role\": \"system\",\n",
@ -567,26 +622,33 @@
"]\n",
"\n",
"for model in [\n",
" \"gpt-3.5-turbo-0301\",\n",
" \"gpt-3.5-turbo-0613\",\n",
" # \"gpt-3.5-turbo-0301\",\n",
" # \"gpt-4-0314\",\n",
" # \"gpt-4-0613\",\n",
" \"gpt-3.5-turbo-1106\",\n",
" \"gpt-3.5-turbo\",\n",
" \"gpt-4-0314\",\n",
" \"gpt-4-0613\",\n",
" \"gpt-4\",\n",
" \"gpt-4-1106-preview\",\n",
" ]:\n",
" print(model)\n",
" # example token count from the function defined above\n",
" print(f\"{num_tokens_from_messages(example_messages, model)} prompt tokens counted by num_tokens_from_messages().\")\n",
" # example token count from the OpenAI API\n",
" response = openai.ChatCompletion.create(\n",
" model=model,\n",
" messages=example_messages,\n",
" temperature=0,\n",
" max_tokens=1, # we're only counting input tokens here, so let's not waste tokens on the output\n",
" )\n",
" print(f'{response[\"usage\"][\"prompt_tokens\"]} prompt tokens counted by the OpenAI API.')\n",
" response = client.chat.completions.create(model=model,\n",
" messages=example_messages,\n",
" temperature=0,\n",
" max_tokens=1)\n",
" token = response.usage.prompt_tokens\n",
" print(f'{token} prompt tokens counted by the OpenAI API.')\n",
" print()\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
@ -605,7 +667,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.9"
"version": "3.11.5"
},
"orig_nbformat": 4,
"vscode": {

@ -48,6 +48,18 @@
"- [OpenAI Rate Limit Increase Request form](https://forms.gle/56ZrwXXoxAN1yt6i9)\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import openai\n",
"import os\n",
"\n",
"client = openai.OpenAI(api_key=os.environ.get(\"OPENAI_API_KEY\", \"<your OpenAI API key if not set as env var>\"))"
]
},
{
"cell_type": "markdown",
"metadata": {},
@ -69,9 +81,6 @@
"metadata": {},
"outputs": [],
"source": [
"from openai import OpenAI # for making OpenAI API requests\n",
"client = OpenAI()\n",
"\n",
"# request a bunch of completions in a loop\n",
"for _ in range(100):\n",
" client.chat.completions.create(\n",
@ -132,8 +141,6 @@
}
],
"source": [
"from openai import OpenAI # for OpenAI API calls\n",
"client = OpenAI()\n",
"from tenacity import (\n",
" retry,\n",
" stop_after_attempt,\n",
@ -177,10 +184,6 @@
],
"source": [
"import backoff # for exponential backoff\n",
"from openai import OpenAI # for OpenAI API calls\n",
"import openai\n",
"client = OpenAI() \n",
"\n",
"\n",
"@backoff.on_exception(backoff.expo, openai.RateLimitError)\n",
"def completions_with_backoff(**kwargs):\n",
@ -220,10 +223,6 @@
"import random\n",
"import time\n",
"\n",
"import openai\n",
"from openai import OpenAI\n",
"client = OpenAI()\n",
"\n",
"# define a retry decorator\n",
"def retry_with_exponential_backoff(\n",
" func,\n",
@ -316,8 +315,6 @@
"source": [
"# imports\n",
"import time\n",
"from openai import OpenAI\n",
"client = OpenAI()\n",
"\n",
"# Define a function that adds a delay to a Completion API call\n",
"def delayed_completion(delay_in_seconds: float = 1, **kwargs):\n",
@ -383,10 +380,6 @@
}
],
"source": [
"from openai import OpenAI # for making OpenAI API requests\n",
"client = OpenAI() \n",
"\n",
"\n",
"num_stories = 10\n",
"content = \"Once upon a time,\"\n",
"\n",
@ -432,15 +425,11 @@
}
],
"source": [
"from openai import OpenAI # for making OpenAI API requests\n",
"client = OpenAI() \n",
"\n",
"\n",
"num_stories = 10\n",
"prompts = [\"Once upon a time,\"] * num_stories\n",
"\n",
"# batched example, with 10 stories completions per request\n",
"response = client.completions.create(\n",
"response = client.chat.completions.create(\n",
" model=\"curie\",\n",
" prompt=prompts,\n",
" max_tokens=20,\n",

@ -26,8 +26,7 @@
"Below, this notebook shows:\n",
"1. What a typical chat completion response looks like\n",
"2. What a streaming chat completion response looks like\n",
"3. How much time is saved by streaming a chat completion\n",
"4. How to stream non-chat completions (used by older models like `text-davinci-003`)"
"3. How much time is saved by streaming a chat completion"
]
},
{
@ -36,19 +35,20 @@
"metadata": {},
"outputs": [],
"source": [
"# !pip install openai==1.3.7"
"# !pip install openai"
]
},
{
"cell_type": "code",
"execution_count": 2,
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"# imports\n",
"import time # for measuring time duration of API calls\n",
"from openai import OpenAI\n",
"client = OpenAI() # for OpenAI API calls"
"import os\n",
"client = OpenAI(api_key=os.environ.get(\"OPENAI_API_KEY\", \"<your OpenAI API key if not set as env var>\"))"
]
},
{
@ -63,28 +63,28 @@
},
{
"cell_type": "code",
"execution_count": 3,
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Full response received 7.90 seconds after request\n",
"Full response received 5.27 seconds after request\n",
"Full response received:\n",
"ChatCompletion(id='chatcmpl-8SjX2G5nLRWrfnnPeFn9HAaJvSVZf', choices=[Choice(finish_reason='stop', index=0, message=ChatCompletionMessage(content='1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100.', role='assistant', function_call=None, tool_calls=None))], created=1701858900, model='gpt-3.5-turbo-0613', object='chat.completion', system_fingerprint=None, usage=CompletionUsage(completion_tokens=299, prompt_tokens=36, total_tokens=335))\n"
"ChatCompletion(id='chatcmpl-8ZB8ywkV5DuuJO7xktqUcNYfG8j6I', choices=[Choice(finish_reason='stop', index=0, logprobs=None, message=ChatCompletionMessage(content='1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100.', role='assistant', function_call=None, tool_calls=None))], created=1703395008, model='gpt-3.5-turbo-0613', object='chat.completion', system_fingerprint=None, usage=CompletionUsage(completion_tokens=299, prompt_tokens=36, total_tokens=335))\n"
]
}
],
"source": [
"# Example of an OpenAI ChatCompletion request\n",
"# https://platform.openai.com/docs/guides/chat\n",
"# https://platform.openai.com/docs/guides/text-generation/chat-completions-api\n",
"\n",
"# record the time before the request is sent\n",
"start_time = time.time()\n",
"\n",
"# send a ChatCompletion request to count to 100\n",
"completion = client.chat.completions.create(\n",
"response = client.chat.completions.create(\n",
" model='gpt-3.5-turbo',\n",
" messages=[\n",
" {'role': 'user', 'content': 'Count to 100, with a comma between each number and no newlines. E.g., 1, 2, 3, ...'}\n",
@ -96,7 +96,7 @@
"\n",
"# print the time delay and text received\n",
"print(f\"Full response received {response_time:.2f} seconds after request\")\n",
"print(f\"Full response received:\\n{completion}\")\n"
"print(f\"Full response received:\\n{response}\")\n"
]
},
{
@ -104,14 +104,14 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"The reply can be extracted with `response['choices'][0]['message']`.\n",
"The reply can be extracted with `response.choices[0].message`.\n",
"\n",
"The content of the reply can be extracted with `response['choices'][0]['message']['content']`."
"The content of the reply can be extracted with `response.choices[0].message.content`."
]
},
{
"cell_type": "code",
"execution_count": 4,
"execution_count": 5,
"metadata": {},
"outputs": [
{
@ -126,10 +126,10 @@
}
],
"source": [
"reply = completion.choices[0].message\n",
"reply = response.choices[0].message\n",
"print(f\"Extracted reply: \\n{reply}\")\n",
"\n",
"reply_content = completion.choices[0].message.content\n",
"reply_content = response.choices[0].message.content\n",
"print(f\"Extracted content: \\n{reply_content}\")\n"
]
},
@ -147,20 +147,20 @@
},
{
"cell_type": "code",
"execution_count": 5,
"execution_count": 6,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"ChatCompletionChunk(id='chatcmpl-8SjXATR0aAejfQHMDHkNYYRTiUdca', choices=[Choice(delta=ChoiceDelta(content='', function_call=None, role='assistant', tool_calls=None), finish_reason=None, index=0)], created=1701858908, model='gpt-3.5-turbo-0613', object='chat.completion.chunk', system_fingerprint=None)\n",
"ChatCompletionChunk(id='chatcmpl-8ZB9m2Ubv8FJs3CIb84WvYwqZCHST', choices=[Choice(delta=ChoiceDelta(content='', function_call=None, role='assistant', tool_calls=None), finish_reason=None, index=0, logprobs=None)], created=1703395058, model='gpt-3.5-turbo-0613', object='chat.completion.chunk', system_fingerprint=None)\n",
"\n",
"****************\n",
"ChatCompletionChunk(id='chatcmpl-8SjXATR0aAejfQHMDHkNYYRTiUdca', choices=[Choice(delta=ChoiceDelta(content='2', function_call=None, role=None, tool_calls=None), finish_reason=None, index=0)], created=1701858908, model='gpt-3.5-turbo-0613', object='chat.completion.chunk', system_fingerprint=None)\n",
"ChatCompletionChunk(id='chatcmpl-8ZB9m2Ubv8FJs3CIb84WvYwqZCHST', choices=[Choice(delta=ChoiceDelta(content='2', function_call=None, role=None, tool_calls=None), finish_reason=None, index=0, logprobs=None)], created=1703395058, model='gpt-3.5-turbo-0613', object='chat.completion.chunk', system_fingerprint=None)\n",
"2\n",
"****************\n",
"ChatCompletionChunk(id='chatcmpl-8SjXATR0aAejfQHMDHkNYYRTiUdca', choices=[Choice(delta=ChoiceDelta(content=None, function_call=None, role=None, tool_calls=None), finish_reason='stop', index=0)], created=1701858908, model='gpt-3.5-turbo-0613', object='chat.completion.chunk', system_fingerprint=None)\n",
"ChatCompletionChunk(id='chatcmpl-8ZB9m2Ubv8FJs3CIb84WvYwqZCHST', choices=[Choice(delta=ChoiceDelta(content=None, function_call=None, role=None, tool_calls=None), finish_reason='stop', index=0, logprobs=None)], created=1703395058, model='gpt-3.5-turbo-0613', object='chat.completion.chunk', system_fingerprint=None)\n",
"None\n",
"****************\n"
]
@ -168,9 +168,10 @@
],
"source": [
"# Example of an OpenAI ChatCompletion request with stream=True\n",
"# https://platform.openai.com/docs/guides/chat\n",
"# https://platform.openai.com/docs/api-reference/streaming#chat/create-stream\n",
"\n",
"completion = client.chat.completions.create(\n",
"# a ChatCompletion request\n",
"response = client.chat.completions.create(\n",
" model='gpt-3.5-turbo',\n",
" messages=[\n",
" {'role': 'user', 'content': \"What's 1+1? Answer in one word.\"}\n",
@ -179,7 +180,7 @@
" stream=True # this time, we set stream=True\n",
")\n",
"\n",
"for chunk in completion:\n",
"for chunk in response:\n",
" print(chunk)\n",
" print(chunk.choices[0].delta.content)\n",
" print(\"****************\")"
@ -208,328 +209,328 @@
},
{
"cell_type": "code",
"execution_count": 6,
"execution_count": 8,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Message received 0.99 seconds after request: \n",
"Message received 1.06 seconds after request: 1\n",
"Message received 1.06 seconds after request: ,\n",
"Message received 1.06 seconds after request: \n",
"Message received 1.14 seconds after request: 2\n",
"Message received 1.14 seconds after request: ,\n",
"Message received 1.14 seconds after request: \n",
"Message received 1.20 seconds after request: 3\n",
"Message received 1.20 seconds after request: ,\n",
"Message received 1.20 seconds after request: \n",
"Message received 1.27 seconds after request: 4\n",
"Message received 0.31 seconds after request: \n",
"Message received 0.31 seconds after request: 1\n",
"Message received 0.34 seconds after request: ,\n",
"Message received 0.34 seconds after request: \n",
"Message received 0.34 seconds after request: 2\n",
"Message received 0.39 seconds after request: ,\n",
"Message received 0.39 seconds after request: \n",
"Message received 0.39 seconds after request: 3\n",
"Message received 0.42 seconds after request: ,\n",
"Message received 0.42 seconds after request: \n",
"Message received 0.42 seconds after request: 4\n",
"Message received 0.47 seconds after request: ,\n",
"Message received 0.47 seconds after request: \n",
"Message received 0.47 seconds after request: 5\n",
"Message received 0.51 seconds after request: ,\n",
"Message received 0.51 seconds after request: \n",
"Message received 0.51 seconds after request: 6\n",
"Message received 0.55 seconds after request: ,\n",
"Message received 0.55 seconds after request: \n",
"Message received 0.55 seconds after request: 7\n",
"Message received 0.59 seconds after request: ,\n",
"Message received 0.59 seconds after request: \n",
"Message received 0.59 seconds after request: 8\n",
"Message received 0.63 seconds after request: ,\n",
"Message received 0.63 seconds after request: \n",
"Message received 0.63 seconds after request: 9\n",
"Message received 0.67 seconds after request: ,\n",
"Message received 0.67 seconds after request: \n",
"Message received 0.67 seconds after request: 10\n",
"Message received 0.71 seconds after request: ,\n",
"Message received 0.71 seconds after request: \n",
"Message received 0.71 seconds after request: 11\n",
"Message received 0.75 seconds after request: ,\n",
"Message received 0.75 seconds after request: \n",
"Message received 0.75 seconds after request: 12\n",
"Message received 0.98 seconds after request: ,\n",
"Message received 0.98 seconds after request: \n",
"Message received 0.98 seconds after request: 13\n",
"Message received 1.02 seconds after request: ,\n",
"Message received 1.02 seconds after request: \n",
"Message received 1.02 seconds after request: 14\n",
"Message received 1.04 seconds after request: ,\n",
"Message received 1.04 seconds after request: \n",
"Message received 1.04 seconds after request: 15\n",
"Message received 1.08 seconds after request: ,\n",
"Message received 1.08 seconds after request: \n",
"Message received 1.08 seconds after request: 16\n",
"Message received 1.12 seconds after request: ,\n",
"Message received 1.12 seconds after request: \n",
"Message received 1.12 seconds after request: 17\n",
"Message received 1.16 seconds after request: ,\n",
"Message received 1.16 seconds after request: \n",
"Message received 1.16 seconds after request: 18\n",
"Message received 1.19 seconds after request: ,\n",
"Message received 1.19 seconds after request: \n",
"Message received 1.19 seconds after request: 19\n",
"Message received 1.23 seconds after request: ,\n",
"Message received 1.23 seconds after request: \n",
"Message received 1.23 seconds after request: 20\n",
"Message received 1.27 seconds after request: ,\n",
"Message received 1.27 seconds after request: \n",
"Message received 1.34 seconds after request: 5\n",
"Message received 1.34 seconds after request: ,\n",
"Message received 1.34 seconds after request: \n",
"Message received 1.40 seconds after request: 6\n",
"Message received 1.40 seconds after request: ,\n",
"Message received 1.40 seconds after request: \n",
"Message received 1.47 seconds after request: 7\n",
"Message received 1.48 seconds after request: ,\n",
"Message received 1.48 seconds after request: \n",
"Message received 1.56 seconds after request: 8\n",
"Message received 1.56 seconds after request: ,\n",
"Message received 1.56 seconds after request: \n",
"Message received 1.63 seconds after request: 9\n",
"Message received 1.63 seconds after request: ,\n",
"Message received 1.63 seconds after request: \n",
"Message received 1.71 seconds after request: 10\n",
"Message received 1.71 seconds after request: ,\n",
"Message received 1.71 seconds after request: \n",
"Message received 1.78 seconds after request: 11\n",
"Message received 1.78 seconds after request: ,\n",
"Message received 1.78 seconds after request: \n",
"Message received 1.86 seconds after request: 12\n",
"Message received 1.27 seconds after request: 21\n",
"Message received 1.31 seconds after request: ,\n",
"Message received 1.31 seconds after request: \n",
"Message received 1.31 seconds after request: 22\n",
"Message received 1.35 seconds after request: ,\n",
"Message received 1.35 seconds after request: \n",
"Message received 1.35 seconds after request: 23\n",
"Message received 1.39 seconds after request: ,\n",
"Message received 1.39 seconds after request: \n",
"Message received 1.39 seconds after request: 24\n",
"Message received 1.43 seconds after request: ,\n",
"Message received 1.43 seconds after request: \n",
"Message received 1.43 seconds after request: 25\n",
"Message received 1.47 seconds after request: ,\n",
"Message received 1.47 seconds after request: \n",
"Message received 1.47 seconds after request: 26\n",
"Message received 1.51 seconds after request: ,\n",
"Message received 1.51 seconds after request: \n",
"Message received 1.51 seconds after request: 27\n",
"Message received 1.55 seconds after request: ,\n",
"Message received 1.55 seconds after request: \n",
"Message received 1.55 seconds after request: 28\n",
"Message received 1.59 seconds after request: ,\n",
"Message received 1.59 seconds after request: \n",
"Message received 1.59 seconds after request: 29\n",
"Message received 1.59 seconds after request: ,\n",
"Message received 1.59 seconds after request: \n",
"Message received 1.59 seconds after request: 30\n",
"Message received 1.59 seconds after request: ,\n",
"Message received 1.59 seconds after request: \n",
"Message received 1.59 seconds after request: 31\n",
"Message received 1.59 seconds after request: ,\n",
"Message received 1.59 seconds after request: \n",
"Message received 1.60 seconds after request: 32\n",
"Message received 1.60 seconds after request: ,\n",
"Message received 1.60 seconds after request: \n",
"Message received 1.60 seconds after request: 33\n",
"Message received 1.60 seconds after request: ,\n",
"Message received 1.60 seconds after request: \n",
"Message received 1.67 seconds after request: 34\n",
"Message received 1.67 seconds after request: ,\n",
"Message received 1.67 seconds after request: \n",
"Message received 1.68 seconds after request: 35\n",
"Message received 1.68 seconds after request: ,\n",
"Message received 1.68 seconds after request: \n",
"Message received 1.86 seconds after request: 36\n",
"Message received 1.86 seconds after request: ,\n",
"Message received 1.86 seconds after request: \n",
"Message received 2.20 seconds after request: 13\n",
"Message received 2.20 seconds after request: ,\n",
"Message received 2.20 seconds after request: \n",
"Message received 2.31 seconds after request: 14\n",
"Message received 1.90 seconds after request: 37\n",
"Message received 1.90 seconds after request: ,\n",
"Message received 1.90 seconds after request: \n",
"Message received 1.94 seconds after request: 38\n",
"Message received 1.94 seconds after request: ,\n",
"Message received 1.94 seconds after request: \n",
"Message received 1.98 seconds after request: 39\n",
"Message received 1.98 seconds after request: ,\n",
"Message received 1.98 seconds after request: \n",
"Message received 2.05 seconds after request: 40\n",
"Message received 2.05 seconds after request: ,\n",
"Message received 2.05 seconds after request: \n",
"Message received 2.09 seconds after request: 41\n",
"Message received 2.09 seconds after request: ,\n",
"Message received 2.09 seconds after request: \n",
"Message received 2.14 seconds after request: 42\n",
"Message received 2.14 seconds after request: ,\n",
"Message received 2.14 seconds after request: \n",
"Message received 2.14 seconds after request: 43\n",
"Message received 2.14 seconds after request: ,\n",
"Message received 2.14 seconds after request: \n",
"Message received 2.14 seconds after request: 44\n",
"Message received 2.14 seconds after request: ,\n",
"Message received 2.14 seconds after request: \n",
"Message received 2.14 seconds after request: 45\n",
"Message received 2.14 seconds after request: ,\n",
"Message received 2.14 seconds after request: \n",
"Message received 2.15 seconds after request: 46\n",
"Message received 2.15 seconds after request: ,\n",
"Message received 2.15 seconds after request: \n",
"Message received 2.30 seconds after request: 47\n",
"Message received 2.30 seconds after request: ,\n",
"Message received 2.30 seconds after request: \n",
"Message received 2.30 seconds after request: 48\n",
"Message received 2.30 seconds after request: ,\n",
"Message received 2.30 seconds after request: \n",
"Message received 2.30 seconds after request: 49\n",
"Message received 2.30 seconds after request: ,\n",
"Message received 2.30 seconds after request: \n",
"Message received 2.31 seconds after request: 50\n",
"Message received 2.31 seconds after request: ,\n",
"Message received 2.31 seconds after request: \n",
"Message received 2.38 seconds after request: 15\n",
"Message received 2.38 seconds after request: ,\n",
"Message received 2.39 seconds after request: 51\n",
"Message received 2.39 seconds after request: ,\n",
"Message received 2.39 seconds after request: \n",
"Message received 2.46 seconds after request: 16\n",
"Message received 2.46 seconds after request: ,\n",
"Message received 2.46 seconds after request: \n",
"Message received 2.53 seconds after request: 17\n",
"Message received 2.53 seconds after request: ,\n",
"Message received 2.53 seconds after request: \n",
"Message received 2.61 seconds after request: 18\n",
"Message received 2.61 seconds after request: ,\n",
"Message received 2.61 seconds after request: \n",
"Message received 2.67 seconds after request: 19\n",
"Message received 2.67 seconds after request: ,\n",
"Message received 2.67 seconds after request: \n",
"Message received 2.74 seconds after request: 20\n",
"Message received 2.74 seconds after request: ,\n",
"Message received 2.74 seconds after request: \n",
"Message received 2.83 seconds after request: 21\n",
"Message received 2.83 seconds after request: ,\n",
"Message received 2.83 seconds after request: \n",
"Message received 2.89 seconds after request: 22\n",
"Message received 2.40 seconds after request: 52\n",
"Message received 2.40 seconds after request: ,\n",
"Message received 2.40 seconds after request: \n",
"Message received 2.48 seconds after request: 53\n",
"Message received 2.48 seconds after request: ,\n",
"Message received 2.48 seconds after request: \n",
"Message received 2.49 seconds after request: 54\n",
"Message received 2.49 seconds after request: ,\n",
"Message received 2.49 seconds after request: \n",
"Message received 2.68 seconds after request: 55\n",
"Message received 2.68 seconds after request: ,\n",
"Message received 2.68 seconds after request: \n",
"Message received 2.72 seconds after request: 56\n",
"Message received 2.72 seconds after request: ,\n",
"Message received 2.72 seconds after request: \n",
"Message received 2.77 seconds after request: 57\n",
"Message received 2.77 seconds after request: ,\n",
"Message received 2.77 seconds after request: \n",
"Message received 2.80 seconds after request: 58\n",
"Message received 2.80 seconds after request: ,\n",
"Message received 2.80 seconds after request: \n",
"Message received 2.85 seconds after request: 59\n",
"Message received 2.85 seconds after request: ,\n",
"Message received 2.85 seconds after request: \n",
"Message received 2.88 seconds after request: 60\n",
"Message received 2.88 seconds after request: ,\n",
"Message received 2.88 seconds after request: \n",
"Message received 2.88 seconds after request: 61\n",
"Message received 2.88 seconds after request: ,\n",
"Message received 2.88 seconds after request: \n",
"Message received 2.89 seconds after request: 62\n",
"Message received 2.89 seconds after request: ,\n",
"Message received 2.89 seconds after request: \n",
"Message received 2.89 seconds after request: 63\n",
"Message received 2.89 seconds after request: ,\n",
"Message received 2.89 seconds after request: \n",
"Message received 3.02 seconds after request: 23\n",
"Message received 3.02 seconds after request: ,\n",
"Message received 3.03 seconds after request: \n",
"Message received 3.09 seconds after request: 24\n",
"Message received 3.09 seconds after request: ,\n",
"Message received 3.09 seconds after request: \n",
"Message received 3.15 seconds after request: 25\n",
"Message received 3.15 seconds after request: ,\n",
"Message received 3.16 seconds after request: \n",
"Message received 3.22 seconds after request: 26\n",
"Message received 3.22 seconds after request: ,\n",
"Message received 3.22 seconds after request: \n",
"Message received 3.30 seconds after request: 27\n",
"Message received 3.30 seconds after request: ,\n",
"Message received 3.30 seconds after request: \n",
"Message received 3.37 seconds after request: 28\n",
"Message received 2.92 seconds after request: 64\n",
"Message received 2.92 seconds after request: ,\n",
"Message received 2.92 seconds after request: \n",
"Message received 3.37 seconds after request: 65\n",
"Message received 3.37 seconds after request: ,\n",
"Message received 3.37 seconds after request: \n",
"Message received 3.55 seconds after request: 29\n",
"Message received 3.55 seconds after request: ,\n",
"Message received 3.55 seconds after request: \n",
"Message received 3.55 seconds after request: 30\n",
"Message received 3.55 seconds after request: ,\n",
"Message received 3.55 seconds after request: \n",
"Message received 3.55 seconds after request: 31\n",
"Message received 3.55 seconds after request: ,\n",
"Message received 3.56 seconds after request: \n",
"Message received 3.56 seconds after request: 32\n",
"Message received 3.56 seconds after request: ,\n",
"Message received 3.56 seconds after request: \n",
"Message received 3.56 seconds after request: 33\n",
"Message received 3.38 seconds after request: 66\n",
"Message received 3.38 seconds after request: ,\n",
"Message received 3.38 seconds after request: \n",
"Message received 3.38 seconds after request: 67\n",
"Message received 3.38 seconds after request: ,\n",
"Message received 3.38 seconds after request: \n",
"Message received 3.38 seconds after request: 68\n",
"Message received 3.38 seconds after request: ,\n",
"Message received 3.38 seconds after request: \n",
"Message received 3.42 seconds after request: 69\n",
"Message received 3.42 seconds after request: ,\n",
"Message received 3.42 seconds after request: \n",
"Message received 3.43 seconds after request: 70\n",
"Message received 3.43 seconds after request: ,\n",
"Message received 3.43 seconds after request: \n",
"Message received 3.46 seconds after request: 71\n",
"Message received 3.46 seconds after request: ,\n",
"Message received 3.46 seconds after request: \n",
"Message received 3.47 seconds after request: 72\n",
"Message received 3.47 seconds after request: ,\n",
"Message received 3.47 seconds after request: \n",
"Message received 3.50 seconds after request: 73\n",
"Message received 3.50 seconds after request: ,\n",
"Message received 3.50 seconds after request: \n",
"Message received 3.51 seconds after request: 74\n",
"Message received 3.51 seconds after request: ,\n",
"Message received 3.51 seconds after request: \n",
"Message received 3.52 seconds after request: 75\n",
"Message received 3.52 seconds after request: ,\n",
"Message received 3.52 seconds after request: \n",
"Message received 3.54 seconds after request: 76\n",
"Message received 3.54 seconds after request: ,\n",
"Message received 3.54 seconds after request: \n",
"Message received 3.56 seconds after request: 77\n",
"Message received 3.56 seconds after request: ,\n",
"Message received 3.56 seconds after request: \n",
"Message received 3.60 seconds after request: 34\n",
"Message received 3.60 seconds after request: ,\n",
"Message received 3.60 seconds after request: \n",
"Message received 3.63 seconds after request: 35\n",
"Message received 3.63 seconds after request: ,\n",
"Message received 3.63 seconds after request: \n",
"Message received 3.95 seconds after request: 36\n",
"Message received 3.59 seconds after request: 78\n",
"Message received 3.59 seconds after request: ,\n",
"Message received 3.59 seconds after request: \n",
"Message received 3.59 seconds after request: 79\n",
"Message received 3.59 seconds after request: ,\n",
"Message received 3.59 seconds after request: \n",
"Message received 3.59 seconds after request: 80\n",
"Message received 3.59 seconds after request: ,\n",
"Message received 3.59 seconds after request: \n",
"Message received 3.61 seconds after request: 81\n",
"Message received 3.61 seconds after request: ,\n",
"Message received 3.61 seconds after request: \n",
"Message received 3.65 seconds after request: 82\n",
"Message received 3.65 seconds after request: ,\n",
"Message received 3.65 seconds after request: \n",
"Message received 3.85 seconds after request: 83\n",
"Message received 3.85 seconds after request: ,\n",
"Message received 3.85 seconds after request: \n",
"Message received 3.90 seconds after request: 84\n",
"Message received 3.90 seconds after request: ,\n",
"Message received 3.90 seconds after request: \n",
"Message received 3.95 seconds after request: 85\n",
"Message received 3.95 seconds after request: ,\n",
"Message received 3.95 seconds after request: \n",
"Message received 4.02 seconds after request: 37\n",
"Message received 4.02 seconds after request: ,\n",
"Message received 4.02 seconds after request: \n",
"Message received 4.08 seconds after request: 38\n",
"Message received 4.00 seconds after request: 86\n",
"Message received 4.00 seconds after request: ,\n",
"Message received 4.00 seconds after request: \n",
"Message received 4.04 seconds after request: 87\n",
"Message received 4.04 seconds after request: ,\n",
"Message received 4.04 seconds after request: \n",
"Message received 4.08 seconds after request: 88\n",
"Message received 4.08 seconds after request: ,\n",
"Message received 4.08 seconds after request: \n",
"Message received 4.17 seconds after request: 39\n",
"Message received 4.17 seconds after request: ,\n",
"Message received 4.17 seconds after request: \n",
"Message received 4.22 seconds after request: 40\n",
"Message received 4.22 seconds after request: ,\n",
"Message received 4.22 seconds after request: \n",
"Message received 4.29 seconds after request: 41\n",
"Message received 4.29 seconds after request: ,\n",
"Message received 4.29 seconds after request: \n",
"Message received 4.37 seconds after request: 42\n",
"Message received 4.37 seconds after request: ,\n",
"Message received 4.37 seconds after request: \n",
"Message received 4.37 seconds after request: 43\n",
"Message received 4.37 seconds after request: ,\n",
"Message received 4.37 seconds after request: \n",
"Message received 4.37 seconds after request: 44\n",
"Message received 4.37 seconds after request: ,\n",
"Message received 4.37 seconds after request: \n",
"Message received 4.38 seconds after request: 45\n",
"Message received 4.38 seconds after request: ,\n",
"Message received 4.38 seconds after request: \n",
"Message received 4.39 seconds after request: 46\n",
"Message received 4.12 seconds after request: 89\n",
"Message received 4.12 seconds after request: ,\n",
"Message received 4.12 seconds after request: \n",
"Message received 4.18 seconds after request: 90\n",
"Message received 4.18 seconds after request: ,\n",
"Message received 4.18 seconds after request: \n",
"Message received 4.18 seconds after request: 91\n",
"Message received 4.18 seconds after request: ,\n",
"Message received 4.18 seconds after request: \n",
"Message received 4.18 seconds after request: 92\n",
"Message received 4.18 seconds after request: ,\n",
"Message received 4.18 seconds after request: \n",
"Message received 4.19 seconds after request: 93\n",
"Message received 4.19 seconds after request: ,\n",
"Message received 4.19 seconds after request: \n",
"Message received 4.20 seconds after request: 94\n",
"Message received 4.20 seconds after request: ,\n",
"Message received 4.20 seconds after request: \n",
"Message received 4.23 seconds after request: 95\n",
"Message received 4.23 seconds after request: ,\n",
"Message received 4.23 seconds after request: \n",
"Message received 4.27 seconds after request: 96\n",
"Message received 4.27 seconds after request: ,\n",
"Message received 4.27 seconds after request: \n",
"Message received 4.39 seconds after request: 97\n",
"Message received 4.39 seconds after request: ,\n",
"Message received 4.39 seconds after request: \n",
"Message received 4.39 seconds after request: 98\n",
"Message received 4.39 seconds after request: ,\n",
"Message received 4.39 seconds after request: \n",
"Message received 4.66 seconds after request: 47\n",
"Message received 4.66 seconds after request: ,\n",
"Message received 4.66 seconds after request: \n",
"Message received 4.66 seconds after request: 48\n",
"Message received 4.66 seconds after request: ,\n",
"Message received 4.66 seconds after request: \n",
"Message received 4.66 seconds after request: 49\n",
"Message received 4.66 seconds after request: ,\n",
"Message received 4.66 seconds after request: \n",
"Message received 4.69 seconds after request: 50\n",
"Message received 4.69 seconds after request: ,\n",
"Message received 4.69 seconds after request: \n",
"Message received 4.80 seconds after request: 51\n",
"Message received 4.80 seconds after request: ,\n",
"Message received 4.80 seconds after request: \n",
"Message received 4.83 seconds after request: 52\n",
"Message received 4.83 seconds after request: ,\n",
"Message received 4.83 seconds after request: \n",
"Message received 4.95 seconds after request: 53\n",
"Message received 4.95 seconds after request: ,\n",
"Message received 4.95 seconds after request: \n",
"Message received 4.97 seconds after request: 54\n",
"Message received 4.97 seconds after request: ,\n",
"Message received 4.97 seconds after request: \n",
"Message received 5.31 seconds after request: 55\n",
"Message received 5.31 seconds after request: ,\n",
"Message received 5.31 seconds after request: \n",
"Message received 5.37 seconds after request: 56\n",
"Message received 5.37 seconds after request: ,\n",
"Message received 5.37 seconds after request: \n",
"Message received 5.47 seconds after request: 57\n",
"Message received 5.47 seconds after request: ,\n",
"Message received 5.47 seconds after request: \n",
"Message received 5.54 seconds after request: 58\n",
"Message received 5.54 seconds after request: ,\n",
"Message received 5.54 seconds after request: \n",
"Message received 5.60 seconds after request: 59\n",
"Message received 5.60 seconds after request: ,\n",
"Message received 5.60 seconds after request: \n",
"Message received 5.66 seconds after request: 60\n",
"Message received 5.66 seconds after request: ,\n",
"Message received 5.66 seconds after request: \n",
"Message received 5.67 seconds after request: 61\n",
"Message received 5.67 seconds after request: ,\n",
"Message received 5.67 seconds after request: \n",
"Message received 5.67 seconds after request: 62\n",
"Message received 5.67 seconds after request: ,\n",
"Message received 5.67 seconds after request: \n",
"Message received 5.67 seconds after request: 63\n",
"Message received 5.67 seconds after request: ,\n",
"Message received 5.67 seconds after request: \n",
"Message received 5.69 seconds after request: 64\n",
"Message received 5.69 seconds after request: ,\n",
"Message received 5.69 seconds after request: \n",
"Message received 5.95 seconds after request: 65\n",
"Message received 5.95 seconds after request: ,\n",
"Message received 5.95 seconds after request: \n",
"Message received 5.95 seconds after request: 66\n",
"Message received 5.95 seconds after request: ,\n",
"Message received 5.95 seconds after request: \n",
"Message received 5.95 seconds after request: 67\n",
"Message received 5.95 seconds after request: ,\n",
"Message received 5.95 seconds after request: \n",
"Message received 5.97 seconds after request: 68\n",
"Message received 5.97 seconds after request: ,\n",
"Message received 5.97 seconds after request: \n",
"Message received 6.08 seconds after request: 69\n",
"Message received 6.08 seconds after request: ,\n",
"Message received 6.08 seconds after request: \n",
"Message received 6.10 seconds after request: 70\n",
"Message received 6.10 seconds after request: ,\n",
"Message received 6.10 seconds after request: \n",
"Message received 6.17 seconds after request: 71\n",
"Message received 6.17 seconds after request: ,\n",
"Message received 6.17 seconds after request: \n",
"Message received 6.24 seconds after request: 72\n",
"Message received 6.24 seconds after request: ,\n",
"Message received 6.24 seconds after request: \n",
"Message received 6.35 seconds after request: 73\n",
"Message received 6.35 seconds after request: ,\n",
"Message received 6.35 seconds after request: \n",
"Message received 6.37 seconds after request: 74\n",
"Message received 6.37 seconds after request: ,\n",
"Message received 6.37 seconds after request: \n",
"Message received 6.45 seconds after request: 75\n",
"Message received 6.45 seconds after request: ,\n",
"Message received 6.45 seconds after request: \n",
"Message received 6.52 seconds after request: 76\n",
"Message received 6.52 seconds after request: ,\n",
"Message received 6.52 seconds after request: \n",
"Message received 6.59 seconds after request: 77\n",
"Message received 6.59 seconds after request: ,\n",
"Message received 6.59 seconds after request: \n",
"Message received 6.83 seconds after request: 78\n",
"Message received 6.83 seconds after request: ,\n",
"Message received 6.83 seconds after request: \n",
"Message received 6.83 seconds after request: 79\n",
"Message received 6.84 seconds after request: ,\n",
"Message received 6.84 seconds after request: \n",
"Message received 6.84 seconds after request: 80\n",
"Message received 6.84 seconds after request: ,\n",
"Message received 6.84 seconds after request: \n",
"Message received 6.85 seconds after request: 81\n",
"Message received 6.85 seconds after request: ,\n",
"Message received 6.85 seconds after request: \n",
"Message received 6.92 seconds after request: 82\n",
"Message received 6.92 seconds after request: ,\n",
"Message received 6.92 seconds after request: \n",
"Message received 7.23 seconds after request: 83\n",
"Message received 7.23 seconds after request: ,\n",
"Message received 7.23 seconds after request: \n",
"Message received 7.30 seconds after request: 84\n",
"Message received 7.30 seconds after request: ,\n",
"Message received 7.30 seconds after request: \n",
"Message received 7.37 seconds after request: 85\n",
"Message received 7.37 seconds after request: ,\n",
"Message received 7.37 seconds after request: \n",
"Message received 7.43 seconds after request: 86\n",
"Message received 7.43 seconds after request: ,\n",
"Message received 7.43 seconds after request: \n",
"Message received 7.70 seconds after request: 87\n",
"Message received 7.70 seconds after request: ,\n",
"Message received 7.70 seconds after request: \n",
"Message received 7.71 seconds after request: 88\n",
"Message received 7.71 seconds after request: ,\n",
"Message received 7.71 seconds after request: \n",
"Message received 7.73 seconds after request: 89\n",
"Message received 7.73 seconds after request: ,\n",
"Message received 7.73 seconds after request: \n",
"Message received 7.80 seconds after request: 90\n",
"Message received 7.80 seconds after request: ,\n",
"Message received 7.80 seconds after request: \n",
"Message received 7.80 seconds after request: 91\n",
"Message received 7.80 seconds after request: ,\n",
"Message received 7.80 seconds after request: \n",
"Message received 7.80 seconds after request: 92\n",
"Message received 7.80 seconds after request: ,\n",
"Message received 7.80 seconds after request: \n",
"Message received 7.80 seconds after request: 93\n",
"Message received 7.80 seconds after request: ,\n",
"Message received 7.80 seconds after request: \n",
"Message received 7.82 seconds after request: 94\n",
"Message received 7.82 seconds after request: ,\n",
"Message received 7.82 seconds after request: \n",
"Message received 7.90 seconds after request: 95\n",
"Message received 7.90 seconds after request: ,\n",
"Message received 7.90 seconds after request: \n",
"Message received 7.96 seconds after request: 96\n",
"Message received 7.96 seconds after request: ,\n",
"Message received 7.97 seconds after request: \n",
"Message received 8.13 seconds after request: 97\n",
"Message received 8.14 seconds after request: ,\n",
"Message received 8.14 seconds after request: \n",
"Message received 8.14 seconds after request: 98\n",
"Message received 8.14 seconds after request: ,\n",
"Message received 8.14 seconds after request: \n",
"Message received 8.16 seconds after request: 99\n",
"Message received 8.16 seconds after request: ,\n",
"Message received 8.16 seconds after request: \n",
"Message received 8.16 seconds after request: 100\n",
"Message received 8.16 seconds after request: .\n",
"Message received 8.16 seconds after request: None\n",
"Full response received 8.16 seconds after request\n",
"Message received 4.41 seconds after request: 99\n",
"Message received 4.41 seconds after request: ,\n",
"Message received 4.41 seconds after request: \n",
"Message received 4.41 seconds after request: 100\n",
"Message received 4.41 seconds after request: .\n",
"Message received 4.41 seconds after request: None\n",
"Full response received 4.41 seconds after request\n",
"Full conversation received: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100.\n"
]
}
],
"source": [
"# Example of an OpenAI ChatCompletion request with stream=True\n",
"# https://platform.openai.com/docs/guides/chat\n",
"# https://platform.openai.com/docs/api-reference/streaming#chat/create-stream\n",
"\n",
"# record the time before the request is sent\n",
"start_time = time.time()\n",
"\n",
"# send a ChatCompletion request to count to 100\n",
"completion = client.chat.completions.create(\n",
"response = client.chat.completions.create(\n",
" model='gpt-3.5-turbo',\n",
" messages=[\n",
" {'role': 'user', 'content': 'Count to 100, with a comma between each number and no newlines. E.g., 1, 2, 3, ...'}\n",
@ -541,7 +542,7 @@
"collected_chunks = []\n",
"collected_messages = []\n",
"# iterate through the stream of events\n",
"for chunk in completion:\n",
"for chunk in response:\n",
" chunk_time = time.time() - start_time # calculate the time delay of the chunk\n",
" collected_chunks.append(chunk) # save the event response\n",
" chunk_message = chunk.choices[0].delta.content # extract the message\n",
@ -563,10 +564,15 @@
"source": [
"#### Time comparison\n",
"\n",
"In the example above, both requests took about 3 seconds to fully complete. Request times will vary depending on load and other stochastic factors.\n",
"In the example above, both requests took about 4 to 5 seconds to fully complete. Request times will vary depending on load and other stochastic factors.\n",
"\n",
"However, with the streaming request, we received the first token after 0.1 seconds, and subsequent tokens every ~0.01-0.02 seconds."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
}
],
"metadata": {
@ -585,7 +591,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.12"
"version": "3.11.3"
},
"orig_nbformat": 4,
"vscode": {

@ -46,8 +46,9 @@
"import json\n",
"import os\n",
"\n",
"openai.api_key = os.getenv(\"OPENAI_API_KEY\")\n",
"COMPLETIONS_MODEL = \"text-davinci-002\"\n"
"COMPLETIONS_MODEL = \"gpt-4\"\n",
"\n",
"client = openai.OpenAI(api_key=os.environ.get(\"OPENAI_API_KEY\", \"<your OpenAI API key if you didn't set as an env var>\"))"
]
},
{
@ -193,15 +194,14 @@
"source": [
"def request_completion(prompt):\n",
"\n",
" completion_response = openai.completions.create(\n",
" completion_response = openai.chat.completions.create(\n",
" prompt=prompt,\n",
" temperature=0,\n",
" max_tokens=5,\n",
" top_p=1,\n",
" frequency_penalty=0,\n",
" presence_penalty=0,\n",
" model=COMPLETIONS_MODEL\n",
" )\n",
" model=COMPLETIONS_MODEL)\n",
"\n",
" return completion_response\n",
"\n",
@ -211,7 +211,7 @@
" prompt = prompt.replace('DESCRIPTION_TEXT',transaction['Description'])\n",
" prompt = prompt.replace('TRANSACTION_VALUE',str(transaction['Transaction value (£)']))\n",
"\n",
" classification = request_completion(prompt).choices[0].text.replace('\\n','')\n",
" classification = request_completion(prompt).choices[0].message.content.replace('\\n','')\n",
"\n",
" return classification\n",
"\n",
@ -351,7 +351,7 @@
" Building Improvement 14\n",
" Could not classify 5\n",
" Literature & Archive 3\n",
" Software/IT 2\n",
" Software/IT 2\n",
" Utility Bills 1\n",
"Name: Classification, dtype: int64"
]
@ -916,8 +916,8 @@
"source": [
"from utils.embeddings_utils import get_embedding\n",
"\n",
"df['babbage_similarity'] = df.combined.apply(lambda x: get_embedding(x, model='text-similarity-babbage-001'))\n",
"df['babbage_search'] = df.combined.apply(lambda x: get_embedding(x, model='text-search-babbage-doc-001'))\n",
"df['babbage_similarity'] = df.combined.apply(lambda x: get_embedding(x, model='gpt-4'))\n",
"df['babbage_search'] = df.combined.apply(lambda x: get_embedding(x, model='gpt-4'))\n",
"df.to_csv(embedding_path)\n"
]
},
@ -1813,7 +1813,7 @@
"metadata": {},
"outputs": [],
"source": [
"test_set['predicted_class'] = test_set.apply(lambda x: openai.Completion.create(model=fine_tuned_model, prompt=x['prompt'], max_tokens=1, temperature=0, logprobs=5),axis=1)\n",
"test_set['predicted_class'] = test_set.apply(lambda x: openai.chat.completions.create(model=fine_tuned_model, prompt=x['prompt'], max_tokens=1, temperature=0, logprobs=5),axis=1)\n",
"test_set['pred'] = test_set.apply(lambda x : x['predicted_class']['choices'][0]['text'],axis=1)\n"
]
},
@ -1963,7 +1963,7 @@
"outputs": [],
"source": [
"holdout_df['combined'] = \"Supplier: \" + holdout_df['Supplier'].str.strip() + \"; Description: \" + holdout_df['Description'].str.strip() + '\\n\\n###\\n\\n' # + \"; Value: \" + str(df['Transaction value (£)']).strip()\n",
"holdout_df['prediction_result'] = holdout_df.apply(lambda x: openai.Completion.create(model=fine_tuned_model, prompt=x['combined'], max_tokens=1, temperature=0, logprobs=5),axis=1)\n",
"holdout_df['prediction_result'] = holdout_df.apply(lambda x: openai.chat.completions.create(model=fine_tuned_model, prompt=x['combined'], max_tokens=1, temperature=0, logprobs=5),axis=1)\n",
"holdout_df['pred'] = holdout_df.apply(lambda x : x['prediction_result']['choices'][0]['text'],axis=1)\n"
]
},

@ -102,7 +102,8 @@
"logging.basicConfig(level=logging.INFO, format=' %(asctime)s - %(levelname)s - %(message)s')\n",
"\n",
"OPENAI_MODEL = 'gpt-3.5-turbo-0613'\n",
"openai.api_key = os.getenv(\"OPENAI_API_KEY\")"
"\n",
"client = openai.OpenAI(api_key=os.environ.get(\"OPENAI_API_KEY\", \"<your OpenAI API key if not set as env var>\"))"
]
},
{
@ -266,14 +267,14 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"In an OpenAI API call, we can describe `functions` to `gpt-3.5-turbo-0613` and `gpt-4-0613` and have the model intelligently choose to output a `JSON` object containing arguments to call those `functions`. It's important to note that the [chat completions API](https://platform.openai.com/docs/guides/gpt/chat-completions-api) doesn't actually execute the `function`. Instead, it provides the `JSON` output, which can then be used to call the `function` in our code. For more details, refer to the [OpenAI Function Calling Guide](https://platform.openai.com/docs/guides/gpt/function-calling)."
"In an OpenAI API call, we can describe `functions` to `gpt-3.5-turbo-0613` and `gpt-4-0613` and have the model intelligently choose to output a `JSON` object containing arguments to call those `functions`. It's important to note that the [chat completions API](https://platform.openai.com/docs/guides/gpt/chat-completions-api) doesn't actually execute the `function`. Instead, it provides the `JSON` output, which can then be used to call the `function` in our code. For more details, refer to the [OpenAI Function Calling Guide](https://platform.openai.com/docs/guides/function-calling)."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Our function, `enrich_entities(text, label_entities` gets a block of text and a dictionary containing identified labels and entities as parameters. It then associates the recognized entities with their corresponding links to the Wikipedia articles."
"Our function, `enrich_entities(text, label_entities)` gets a block of text and a dictionary containing identified labels and entities as parameters. It then associates the recognized entities with their corresponding links to the Wikipedia articles."
]
},
{
@ -349,7 +350,7 @@
"As previously highlighted, `gpt-3.5-turbo-0613` and `gpt-4-0613` have been fine-tuned to detect when a `function` should to be called. Moreover, they can produce a `JSON` response that conforms to the `function` signature. Here's the sequence we follow:\n",
"\n",
"1. Define our `function` and its associated `JSON` Schema.\n",
"2. Invoke the model using the `messages`, `functions` and `function_call` parameters.\n",
"2. Invoke the model using the `messages`, `tools` and `tool_choice` parameters.\n",
"3. Convert the output into a `JSON` object, and then call the `function` with the `arguments` provided by the model.\n",
"\n",
"In practice, one might want to re-invoke the model again by appending the `function` response as a new message, and let the model summarize the results back to the user. Nevertheless, for our purposes, this step is not needed.\n",
@ -381,7 +382,7 @@
" \"time\": [\"workday\"] \n",
"} \n",
"```\n",
"we need to define the corresponding `JSON` schema to be passed to the `functions` parameter: "
"we need to define the corresponding `JSON` schema to be passed to the `tools` parameter: "
]
},
{
@ -392,22 +393,25 @@
"source": [
"def generate_functions(labels: dict) -> list:\n",
" return [\n",
" {\n",
" \"name\": \"enrich_entities\",\n",
" \"description\": \"Enrich Text with Knowledge Base Links\",\n",
" \"parameters\": {\n",
" \"type\": \"object\",\n",
" \"properties\": {\n",
" \"r'^(?:' + '|'.join({labels}) + ')$'\": \n",
" {\n",
" \"type\": \"array\",\n",
" \"items\": {\n",
" \"type\": \"string\"\n",
" { \n",
" \"type\": \"function\",\n",
" \"function\": {\n",
" \"name\": \"enrich_entities\",\n",
" \"description\": \"Enrich Text with Knowledge Base Links\",\n",
" \"parameters\": {\n",
" \"type\": \"object\",\n",
" \"properties\": {\n",
" \"r'^(?:' + '|'.join({labels}) + ')$'\": \n",
" {\n",
" \"type\": \"array\",\n",
" \"items\": {\n",
" \"type\": \"string\"\n",
" }\n",
" }\n",
" }\n",
" },\n",
" \"additionalProperties\": False\n",
" },\n",
" },\n",
" \"additionalProperties\": False\n",
" },\n",
" }\n",
" }\n",
" ]"
]
@ -423,7 +427,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"Now, we invoke the model. It's important to note that we direct the API to use a specific function by setting the `function_call` parameter to `{\"name\": \"enrich_entities\"}`."
"Now, we invoke the model. It's important to note that we direct the API to use a specific function by setting the `tool_choice` parameter to `{\"type\": \"function\", \"function\" : {\"name\": \"enrich_entities\"}}`."
]
},
{
@ -440,25 +444,27 @@
" {\"role\": \"user\", \"content\": user_message(text=text)}\n",
" ]\n",
"\n",
" response = openai.ChatCompletion.create(\n",
" # TODO: functions and function_call are deprecated, need to be updated\n",
" # See: https://platform.openai.com/docs/api-reference/chat/create#chat-create-tools\n",
" response = openai.chat.completions.create(\n",
" model=\"gpt-3.5-turbo-0613\",\n",
" messages=messages,\n",
" functions=generate_functions(labels),\n",
" function_call={\"name\": \"enrich_entities\"}, \n",
" tools=generate_functions(labels),\n",
" tool_choice={\"type\": \"function\", \"function\" : {\"name\": \"enrich_entities\"}}, \n",
" temperature=0,\n",
" frequency_penalty=0,\n",
" presence_penalty=0,\n",
" )\n",
"\n",
" response_message = response[\"choices\"][0][\"message\"]\n",
" response_message = response.choices[0].message\n",
" \n",
" available_functions = {\"enrich_entities\": enrich_entities} \n",
" function_name = response_message[\"function_call\"][\"name\"]\n",
" function_name = response_message.tool_calls[0].function.name\n",
" \n",
" function_to_call = available_functions[function_name]\n",
" logging.info(f\"function_to_call: {function_to_call}\")\n",
"\n",
" function_args = json.loads(response_message[\"function_call\"][\"arguments\"])\n",
" function_args = json.loads(response_message.tool_calls[0].function.arguments)\n",
" logging.info(f\"function_args: {function_args}\")\n",
"\n",
" function_response = function_to_call(text, function_args)\n",
@ -564,8 +570,8 @@
],
"source": [
"# estimate inference cost assuming gpt-3.5-turbo (4K context)\n",
"i_tokens = result[\"model_response\"][\"usage\"][\"prompt_tokens\"] \n",
"o_tokens = result[\"model_response\"][\"usage\"][\"completion_tokens\"] \n",
"i_tokens = result[\"model_response\"].usage.prompt_tokens \n",
"o_tokens = result[\"model_response\"].usage.completion_tokens \n",
"\n",
"i_cost = (i_tokens / 1000) * 0.0015\n",
"o_cost = (o_tokens / 1000) * 0.002\n",

@ -63,11 +63,13 @@
"from IPython import display # for pretty printing\n",
"import json # for parsing the JSON api responses and model outputs\n",
"from numpy import dot # for cosine similarity\n",
"import openai # for using GPT and getting embeddings\n",
"from openai import OpenAI\n",
"import os # for loading environment variables\n",
"import requests # for making the API requests\n",
"from tqdm.notebook import tqdm # for printing progress bars\n",
"\n",
"client = OpenAI(api_key=os.environ.get(\"OPENAI_API_KEY\", \"<your OpenAI API key if not set as env var>\"))\n",
"\n",
"# Load environment variables\n",
"news_api_key = os.getenv(\"NEWS_API_KEY\")\n",
"\n",
@ -76,14 +78,12 @@
"\n",
"# Helper functions\n",
"def json_gpt(input: str):\n",
" completion = openai.ChatCompletion.create(\n",
" model=GPT_MODEL,\n",
" messages=[\n",
" {\"role\": \"system\", \"content\": \"Output only valid JSON\"},\n",
" {\"role\": \"user\", \"content\": input},\n",
" ],\n",
" temperature=0.5,\n",
" )\n",
" completion = client.chat.completions.create(model=GPT_MODEL,\n",
" messages=[\n",
" {\"role\": \"system\", \"content\": \"Output only valid JSON\"},\n",
" {\"role\": \"user\", \"content\": input},\n",
" ],\n",
" temperature=0.5)\n",
"\n",
" text = completion.choices[0].message.content\n",
" parsed = json.loads(text)\n",
@ -92,7 +92,7 @@
"\n",
"\n",
"def embeddings(input: list[str]) -> list[list[str]]:\n",
" response = openai.Embedding.create(model=\"text-embedding-ada-002\", input=input)\n",
" response = client.embeddings.create(model=\"text-embedding-ada-002\", input=input)\n",
" return [data.embedding for data in response.data]"
]
},
@ -489,7 +489,7 @@
"Include as much information as possible in the answer. Reference the relevant search result urls as markdown links.\n",
"\"\"\"\n",
"\n",
"completion = openai.ChatCompletion.create(\n",
"completion = client.chat.completions.create(\n",
" model=GPT_MODEL,\n",
" messages=[{\"role\": \"user\", \"content\": ANSWER_INPUT}],\n",
" temperature=0.5,\n",
@ -498,7 +498,7 @@
"\n",
"text = \"\"\n",
"for chunk in completion:\n",
" text += chunk.choices[0].delta.get(\"content\", \"\")\n",
" text += chunk.choices[0].delta.content\n",
" display.clear_output(wait=True)\n",
" display.display(display.Markdown(text))"
]

@ -49,6 +49,8 @@
"| `gpt-4` | 8,192 tokens (~10 pages) |\n",
"| `gpt-4-32k` | 32,768 tokens (~40 pages) |\n",
"\n",
"(New model is available with longer contexts, gpt-4-1106-preview have 128K context window)\n",
"\n",
"Continuing the analogy, you can think of the model like a student who can only look at a few pages of notes at a time, despite potentially having shelves of textbooks to draw upon.\n",
"\n",
"Therefore, to build a system capable of drawing upon large quantities of text to answer questions, we recommend using a Search-Ask approach.\n"
@ -136,7 +138,9 @@
"\n",
"# models\n",
"EMBEDDING_MODEL = \"text-embedding-ada-002\"\n",
"GPT_MODEL = \"gpt-3.5-turbo\""
"GPT_MODEL = \"gpt-3.5-turbo\"\n",
"\n",
"client = OpenAI(api_key=os.environ.get(\"OPENAI_API_KEY\", \"<your OpenAI API key if not set as env var>\"))\n"
]
},
{
@ -194,10 +198,7 @@
"# an example question about the 2022 Olympics\n",
"query = 'Which athletes won the gold medal in curling at the 2022 Winter Olympics?'\n",
"\n",
"openai = OpenAI(\n",
" api_key = os.environ.get(\"OPENAI_API_KEY\"), # this is also the default, it can be omitted\n",
")\n",
"response = openai.chat.completions.create(\n",
"response = client.chat.completions.create(\n",
" messages=[\n",
" {'role': 'system', 'content': 'You answer questions about the 2022 Winter Olympics.'},\n",
" {'role': 'user', 'content': query},\n",
@ -557,7 +558,7 @@
"\n",
"Question: Which athletes won the gold medal in curling at the 2022 Winter Olympics?\"\"\"\n",
"\n",
"response = openai.chat.completions.create(\n",
"response = client.chat.completions.create(\n",
" messages=[\n",
" {'role': 'system', 'content': 'You answer questions about the 2022 Winter Olympics.'},\n",
" {'role': 'user', 'content': query},\n",
@ -786,7 +787,7 @@
" top_n: int = 100\n",
") -> tuple[list[str], list[float]]:\n",
" \"\"\"Returns a list of strings and relatednesses, sorted from most related to least.\"\"\"\n",
" query_embedding_response = openai.embeddings.create(\n",
" query_embedding_response = client.embeddings.create(\n",
" model=EMBEDDING_MODEL,\n",
" input=query,\n",
" )\n",
@ -964,7 +965,7 @@
" {\"role\": \"system\", \"content\": \"You answer questions about the 2022 Winter Olympics.\"},\n",
" {\"role\": \"user\", \"content\": message},\n",
" ]\n",
" response = openai.chat.completions.create(\n",
" response = client.chat.completions.create(\n",
" model=model,\n",
" messages=messages,\n",
" temperature=0\n",

@ -626,16 +626,16 @@
"outputs": [],
"source": [
"from openai import OpenAI\n",
"client = OpenAI()\n",
"client = OpenAI(api_key=os.environ.get(\"OPENAI_API_KEY\", \"<your OpenAI API key if not set as env var>\"))\n",
"\n",
"# Define the entities to look for\n",
"def define_query(prompt, model=\"gpt-4-1106-preview\"):\n",
" completion = client.chat.completions.create(\n",
" model=model,\n",
" temperature=0,\n",
" response_format= {\n",
" \"type\": \"json_object\"\n",
" },\n",
" model=model,\n",
" temperature=0,\n",
" response_format= {\n",
" \"type\": \"json_object\"\n",
" },\n",
" messages=[\n",
" {\n",
" \"role\": \"system\",\n",

@ -54,9 +54,14 @@
"import arxiv\n",
"from math import exp\n",
"import openai\n",
"import os\n",
"import pandas as pd\n",
"from tenacity import retry, wait_random_exponential, stop_after_attempt\n",
"import tiktoken"
"import tiktoken\n",
"\n",
"client = OpenAI(api_key=os.environ.get(\"OPENAI_API_KEY\", \"<your OpenAI API key if not set as env var>\"))\n",
"\n",
"OPENAI_MODEL = \"gpt-4\""
]
},
{
@ -202,7 +207,7 @@
],
"source": [
"tokens = [\" Yes\", \" No\"]\n",
"tokenizer = tiktoken.encoding_for_model(\"text-davinci-003\")\n",
"tokenizer = tiktoken.encoding_for_model(OPENAI_MODEL)\n",
"ids = [tokenizer.encode(token) for token in tokens]\n",
"ids[0], ids[1]"
]
@ -245,19 +250,19 @@
"\n",
"@retry(wait=wait_random_exponential(min=1, max=40), stop=stop_after_attempt(3))\n",
"def document_relevance(query, document):\n",
" response = openai.Completion.create(\n",
" response = openai.chat.completions.create(\n",
" model=\"text-davinci-003\",\n",
" prompt=prompt.format(query=query, document=content),\n",
" message=prompt.format(query=query, document=document),\n",
" temperature=0,\n",
" logprobs=1,\n",
" logprobs=True,\n",
" logit_bias={3363: 1, 1400: 1},\n",
" )\n",
"\n",
" return (\n",
" query,\n",
" document,\n",
" response[\"choices\"][0][\"text\"],\n",
" response[\"choices\"][0][\"logprobs\"][\"token_logprobs\"][0],\n",
" response.choices[0].message.content,\n",
" response.choices[0].logprobs.token_logprobs[0],\n",
" )"
]
},
@ -271,8 +276,8 @@
"content = result_list[0][\"title\"] + \": \" + result_list[0][\"summary\"]\n",
"\n",
"# Set logprobs to 1 so our response will include the most probable token the model identified\n",
"response = openai.Completion.create(\n",
" model=\"text-davinci-003\",\n",
"response = openai.chat.completions.create(\n",
" model=OPENAI_MODEL,\n",
" prompt=prompt.format(query=query, document=content),\n",
" temperature=0,\n",
" logprobs=1,\n",
@ -317,9 +322,9 @@
}
],
"source": [
"result = response[\"choices\"][0]\n",
"print(f\"Result was {result['text']}\")\n",
"print(f\"Logprobs was {result['logprobs']['token_logprobs'][0]}\")\n",
"result = response.choices[0]\n",
"print(f\"Result was {result.message.content}\")\n",
"print(f\"Logprobs was {result.logprobs.token_logprobs[0]}\")\n",
"print(\"\\nBelow is the full logprobs object\\n\\n\")\n",
"print(result[\"logprobs\"])"
]

@ -26,13 +26,16 @@
},
{
"cell_type": "code",
"execution_count": 1,
"execution_count": 11,
"metadata": {},
"outputs": [],
"source": [
"# imports needed to run the code in this notebook\n",
"import ast # used for detecting whether generated Python code is valid\n",
"import openai # used for calling the OpenAI API\n",
"import os\n",
"from openai import OpenAI\n",
"\n",
"client = OpenAI(api_key=os.environ.get(\"OPENAI_API_KEY\", \"<your OpenAI API key if not set as env var>\"))\n",
"\n",
"color_prefix_by_role = {\n",
" \"system\": \"\\033[0m\", # gray\n",
@ -96,19 +99,17 @@
" if print_text:\n",
" print_messages(explain_messages)\n",
"\n",
" explanation_response = openai.ChatCompletion.create(\n",
" model=explain_model,\n",
" messages=explain_messages,\n",
" temperature=temperature,\n",
" stream=True,\n",
" )\n",
" explanation_response = client.chat.completions.create(model=explain_model,\n",
" messages=explain_messages,\n",
" temperature=temperature,\n",
" stream=True)\n",
" explanation = \"\"\n",
" for chunk in explanation_response:\n",
" delta = chunk[\"choices\"][0][\"delta\"]\n",
" delta = chunk.choices[0].delta\n",
" if print_text:\n",
" print_message_delta(delta)\n",
" if \"content\" in delta:\n",
" explanation += delta[\"content\"]\n",
" explanation += delta.content\n",
" explain_assistant_message = {\"role\": \"assistant\", \"content\": explanation}\n",
"\n",
" # Step 2: Generate a plan to write a unit test\n",
@ -133,19 +134,17 @@
" ]\n",
" if print_text:\n",
" print_messages([plan_user_message])\n",
" plan_response = openai.ChatCompletion.create(\n",
" model=plan_model,\n",
" messages=plan_messages,\n",
" temperature=temperature,\n",
" stream=True,\n",
" )\n",
" plan_response = client.chat.completions.create(model=plan_model,\n",
" messages=plan_messages,\n",
" temperature=temperature,\n",
" stream=True)\n",
" plan = \"\"\n",
" for chunk in plan_response:\n",
" delta = chunk[\"choices\"][0][\"delta\"]\n",
" delta = chunk.choices[0].delta\n",
" if print_text:\n",
" print_message_delta(delta)\n",
" if \"content\" in delta:\n",
" plan += delta[\"content\"]\n",
" explanation += delta.content\n",
" plan_assistant_message = {\"role\": \"assistant\", \"content\": plan}\n",
"\n",
" # Step 2b: If the plan is short, ask GPT to elaborate further\n",
@ -167,19 +166,17 @@
" ]\n",
" if print_text:\n",
" print_messages([elaboration_user_message])\n",
" elaboration_response = openai.ChatCompletion.create(\n",
" model=plan_model,\n",
" messages=elaboration_messages,\n",
" temperature=temperature,\n",
" stream=True,\n",
" )\n",
" elaboration_response = client.chat.completions.create(model=plan_model,\n",
" messages=elaboration_messages,\n",
" temperature=temperature,\n",
" stream=True)\n",
" elaboration = \"\"\n",
" for chunk in elaboration_response:\n",
" delta = chunk[\"choices\"][0][\"delta\"]\n",
" if print_text:\n",
" print_message_delta(delta)\n",
" if \"content\" in delta:\n",
" elaboration += delta[\"content\"]\n",
" delta = chunk.choices[0].delta\n",
" if print_text:\n",
" print_message_delta(delta)\n",
" if \"content\" in delta:\n",
" explanation += delta.content\n",
" elaboration_assistant_message = {\"role\": \"assistant\", \"content\": elaboration}\n",
"\n",
" # Step 3: Generate the unit test\n",
@ -222,19 +219,17 @@
" if print_text:\n",
" print_messages([execute_system_message, execute_user_message])\n",
"\n",
" execute_response = openai.ChatCompletion.create(\n",
" model=execute_model,\n",
" execute_response = client.chat.completions.create(model=execute_model,\n",
" messages=execute_messages,\n",
" temperature=temperature,\n",
" stream=True,\n",
" )\n",
" stream=True)\n",
" execution = \"\"\n",
" for chunk in execute_response:\n",
" delta = chunk[\"choices\"][0][\"delta\"]\n",
" delta = chunk.choices[0].delta\n",
" if print_text:\n",
" print_message_delta(delta)\n",
" if \"content\" in delta:\n",
" execution += delta[\"content\"]\n",
" if delta.content:\n",
" execution += delta.content\n",
"\n",
" # check the output for errors\n",
" code = execution.split(\"```python\")[1].split(\"```\")[0].strip()\n",
@ -263,7 +258,7 @@
},
{
"cell_type": "code",
"execution_count": 2,
"execution_count": 12,
"metadata": {},
"outputs": [
{
@ -297,18 +292,7 @@
" return ' '.join(translated_words)\n",
"\n",
"```\n",
"\u001b[92m\n",
"[assistant]\n",
"The `pig_latin` function takes a string of text and returns the text translated into pig latin. Here's how it works:\n",
"\n",
"* The function defines a nested function called `translate` that takes a single word as input and returns the word translated into pig latin.\n",
"* The `translate` function first defines a string of vowels.\n",
"* If the first letter of the input word is a vowel, the function adds \"way\" to the end of the word and returns the result.\n",
"* If the first letter of the input word is a consonant, the function loops through the word's letters until it finds a vowel.\n",
"* The function then takes the consonants at the beginning of the word and moves them to the end of the word, adding \"ay\" to the end of the word.\n",
"* The `pig_latin` function lowercases the input text and splits it into a list of words.\n",
"* The function then applies the `translate` function to each word in the list using a list comprehension.\n",
"* Finally, the function joins the translated words back together into a single string with spaces between each word and returns the result.\u001b[0m\n",
"\u001b[0m\n",
"[user]\n",
"A good unit test suite should aim to:\n",
"- Test the function's behavior for a wide range of possible inputs\n",
@ -318,50 +302,10 @@
"- Be deterministic, so that the tests always pass or fail in the same way\n",
"\n",
"To help unit test the function above, list diverse scenarios that the function should be able to handle (and under each scenario, include a few examples as sub-bullets).\n",
"\u001b[92m\n",
"[assistant]\n",
"Here are some scenarios that the `pig_latin` function should be able to handle, along with examples:\n",
"\n",
"* Words that start with a vowel:\n",
" * \"apple\" -> \"appleway\"\n",
" * \"elephant\" -> \"elephantway\"\n",
"* Words that start with a single consonant:\n",
" * \"pig\" -> \"igpay\"\n",
" * \"latin\" -> \"atinlay\"\n",
"* Words that start with multiple consonants:\n",
" * \"string\" -> \"ingstray\"\n",
" * \"glove\" -> \"oveglay\"\n",
"* Words that contain numbers or special characters:\n",
" * \"hello!\" -> \"ellohay!\"\n",
" * \"world123\" -> \"orldway123\"\n",
"* Sentences with multiple words:\n",
" * \"hello world\" -> \"ellohay orldway\"\n",
" * \"the quick brown fox\" -> \"hetay ickquay ownbray oxfay\"\n",
"* Sentences with punctuation:\n",
" * \"Hello, world!\" -> \"Ellohay, orldway!\"\n",
" * \"The quick brown fox...\" -> \"Hetay ickquay ownbray oxfay...\" \n",
"* Empty strings:\n",
" * \"\" -> \"\"\u001b[0m\n",
"\u001b[0m\n",
"[user]\n",
"In addition to those scenarios above, list a few rare or unexpected edge cases (and as before, under each edge case, include a few examples as sub-bullets).\n",
"\u001b[92m\n",
"[assistant]\n",
"Here are some rare or unexpected edge cases that the `pig_latin` function should be able to handle, along with examples:\n",
"\n",
"* Words that consist entirely of consonants:\n",
" * \"xyz\" -> \"xyzay\"\n",
" * \"rhythm\" -> \"ythmrhay\"\n",
"* Words that consist entirely of vowels:\n",
" * \"aeiou\" -> \"aeiouway\"\n",
" * \"ouiea\" -> \"ouieaway\"\n",
"* Words that contain mixed case:\n",
" * \"PyThOn\" -> \"ythonpay\"\n",
" * \"eLePhAnT\" -> \"elephantway\"\n",
"* Strings that contain only whitespace:\n",
" * \" \" -> \"\"\n",
"* Non-string inputs:\n",
" * None -> TypeError\n",
" * 42 -> AttributeError\u001b[0m\n",
"\u001b[0m\n",
"[system]\n",
"You are a world-class Python developer with an eagle eye for unintended bugs and edge cases. You write careful, accurate unit tests. When asked to reply only with code, you write all of your code in a single block.\n",
"\u001b[0m\n",
@ -397,74 +341,7 @@
"# below, each test case is represented by a tuple passed to the @pytest.mark.parametrize decorator\n",
"{insert unit test code here}\n",
"```\n",
"\u001b[92m\n",
"[assistant]\n",
"```python\n",
"# imports\n",
"import pytest\n",
"\n",
"# function to test\n",
"def pig_latin(text):\n",
" def translate(word):\n",
" vowels = 'aeiou'\n",
" if word[0] in vowels:\n",
" return word + 'way'\n",
" else:\n",
" consonants = ''\n",
" for letter in word:\n",
" if letter not in vowels:\n",
" consonants += letter\n",
" else:\n",
" break\n",
" return word[len(consonants):] + consonants + 'ay'\n",
"\n",
" words = text.lower().split()\n",
" translated_words = [translate(word) for word in words]\n",
" return ' '.join(translated_words)\n",
"\n",
"\n",
"# unit tests\n",
"# below, each test case is represented by a tuple passed to the @pytest.mark.parametrize decorator\n",
"\n",
"# Tests for normal cases\n",
"@pytest.mark.parametrize('text, expected', [\n",
" ('apple', 'appleway'),\n",
" ('elephant', 'elephantway'),\n",
" ('pig', 'igpay'),\n",
" ('latin', 'atinlay'),\n",
" ('string', 'ingstray'),\n",
" ('glove', 'oveglay'),\n",
" ('hello world', 'ellohay orldway'),\n",
" ('the quick brown fox', 'hetay ickquay ownbray oxfay'),\n",
" ('Hello, world!', 'Ellohay, orldway!'),\n",
" ('The quick brown fox...', 'Hetay ickquay ownbray oxfay...'),\n",
" ('', ''),\n",
"])\n",
"\n",
"def test_pig_latin_normal_cases(text, expected):\n",
" assert pig_latin(text) == expected\n",
"\n",
"\n",
"# Tests for edge cases\n",
"@pytest.mark.parametrize('text, expected', [\n",
" ('xyz', 'xyzay'),\n",
" ('rhythm', 'ythmrhay'),\n",
" ('aeiou', 'aeiouway'),\n",
" ('ouiea', 'ouieaway'),\n",
" ('PyThOn', 'ythonpay'),\n",
" ('eLePhAnT', 'elephantway'),\n",
" (' ', ''),\n",
" (None, TypeError),\n",
" (42, AttributeError)\n",
"])\n",
"\n",
"def test_pig_latin_edge_cases(text, expected):\n",
" if type(expected) == type:\n",
" with pytest.raises(expected):\n",
" pig_latin(text)\n",
" else:\n",
" assert pig_latin(text) == expected\n",
"```"
"execute messages: [{'role': 'system', 'content': 'You are a world-class Python developer with an eagle eye for unintended bugs and edge cases. You write careful, accurate unit tests. When asked to reply only with code, you write all of your code in a single block.'}, {'role': 'user', 'content': \"Please explain the following Python function. Review what each element of the function is doing precisely and what the author's intentions may have been. Organize your explanation as a markdown-formatted, bulleted list.\\n\\n```python\\ndef pig_latin(text):\\n def translate(word):\\n vowels = 'aeiou'\\n if word[0] in vowels:\\n return word + 'way'\\n else:\\n consonants = ''\\n for letter in word:\\n if letter not in vowels:\\n consonants += letter\\n else:\\n break\\n return word[len(consonants):] + consonants + 'ay'\\n\\n words = text.lower().split()\\n translated_words = [translate(word) for word in words]\\n return ' '.join(translated_words)\\n\\n```\"}, {'role': 'assistant', 'content': ''}, {'role': 'user', 'content': \"A good unit test suite should aim to:\\n- Test the function's behavior for a wide range of possible inputs\\n- Test edge cases that the author may not have foreseen\\n- Take advantage of the features of `pytest` to make the tests easy to write and maintain\\n- Be easy to read and understand, with clean code and descriptive names\\n- Be deterministic, so that the tests always pass or fail in the same way\\n\\nTo help unit test the function above, list diverse scenarios that the function should be able to handle (and under each scenario, include a few examples as sub-bullets).\"}, {'role': 'assistant', 'content': ''}, {'role': 'user', 'content': 'In addition to those scenarios above, list a few rare or unexpected edge cases (and as before, under each edge case, include a few examples as sub-bullets).'}, {'role': 'assistant', 'content': ''}, {'role': 'user', 'content': \"Using Python and the `pytest` package, write a suite of unit tests for the function, following the cases above. Include helpful comments to explain each line. Reply only with code, formatted as follows:\\n\\n```python\\n# imports\\nimport pytest # used for our unit tests\\n{insert other imports as needed}\\n\\n# function to test\\ndef pig_latin(text):\\n def translate(word):\\n vowels = 'aeiou'\\n if word[0] in vowels:\\n return word + 'way'\\n else:\\n consonants = ''\\n for letter in word:\\n if letter not in vowels:\\n consonants += letter\\n else:\\n break\\n return word[len(consonants):] + consonants + 'ay'\\n\\n words = text.lower().split()\\n translated_words = [translate(word) for word in words]\\n return ' '.join(translated_words)\\n\\n\\n# unit tests\\n# below, each test case is represented by a tuple passed to the @pytest.mark.parametrize decorator\\n{insert unit test code here}\\n```\"}]\n"
]
}
],
@ -497,7 +374,7 @@
},
{
"cell_type": "code",
"execution_count": 3,
"execution_count": 13,
"metadata": {},
"outputs": [
{
@ -528,46 +405,19 @@
"\n",
"\n",
"# unit tests\n",
"# below, each test case is represented by a tuple passed to the @pytest.mark.parametrize decorator\n",
"\n",
"# Tests for normal cases\n",
"@pytest.mark.parametrize('text, expected', [\n",
" ('apple', 'appleway'),\n",
" ('elephant', 'elephantway'),\n",
" ('pig', 'igpay'),\n",
" ('latin', 'atinlay'),\n",
" ('string', 'ingstray'),\n",
" ('glove', 'oveglay'),\n",
" ('hello world', 'ellohay orldway'),\n",
" ('the quick brown fox', 'hetay ickquay ownbray oxfay'),\n",
" ('Hello, world!', 'Ellohay, orldway!'),\n",
" ('The quick brown fox...', 'Hetay ickquay ownbray oxfay...'),\n",
" ('', ''),\n",
" ('hello world', 'ellohay orldway'), # basic test case\n",
" ('Python is awesome', 'ythonPay isway awesomeway'), # test case with multiple words\n",
" ('apple', 'appleway'), # test case with a word starting with a vowel\n",
" ('', ''), # test case with an empty string\n",
" ('123', '123'), # test case with non-alphabetic characters\n",
" ('Hello World!', 'elloHay orldWay!'), # test case with punctuation\n",
" ('The quick brown fox', 'ethay ickquay ownbray oxfay'), # test case with mixed case words\n",
" ('a e i o u', 'away eway iway oway uway'), # test case with all vowels\n",
" ('bcd fgh jkl mnp', 'bcday fghay jklway mnpay'), # test case with all consonants\n",
"])\n",
"\n",
"def test_pig_latin_normal_cases(text, expected):\n",
" assert pig_latin(text) == expected\n",
"\n",
"\n",
"# Tests for edge cases\n",
"@pytest.mark.parametrize('text, expected', [\n",
" ('xyz', 'xyzay'),\n",
" ('rhythm', 'ythmrhay'),\n",
" ('aeiou', 'aeiouway'),\n",
" ('ouiea', 'ouieaway'),\n",
" ('PyThOn', 'ythonpay'),\n",
" ('eLePhAnT', 'elephantway'),\n",
" (' ', ''),\n",
" (None, TypeError),\n",
" (42, AttributeError)\n",
"])\n",
"\n",
"def test_pig_latin_edge_cases(text, expected):\n",
" if type(expected) == type:\n",
" with pytest.raises(expected):\n",
" pig_latin(text)\n",
" else:\n",
" assert pig_latin(text) == expected\n"
"def test_pig_latin(text, expected):\n",
" assert pig_latin(text) == expected\n"
]
}
],
@ -600,7 +450,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.9"
"version": "3.11.3"
},
"orig_nbformat": 4,
"vscode": {

@ -1,452 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Unit test writing using a multi-step prompt (with the older API)\n",
"\n",
"Complex tasks, such as writing unit tests, can benefit from multi-step prompts. In contrast to a single prompt, a multi-step prompt generates text from GPT-3 and then feeds that text back into subsequent prompts. This can help in cases where you want GPT-3 to explain its reasoning before answering, or brainstorm a plan before executing it.\n",
"\n",
"In this notebook, we use a 3-step prompt to write unit tests in Python using the following steps:\n",
"\n",
"1. Given a Python function, we first prompt GPT-3 to explain what the function is doing.\n",
"2. Second, we prompt GPT-3 to plan a set of unit tests for the function.\n",
" - If the plan is too short, we ask GPT-3 to elaborate with more ideas for unit tests.\n",
"3. Finally, we prompt GPT-3 to write the unit tests.\n",
"\n",
"The code example illustrates a few optional embellishments on the chained, multi-step prompt:\n",
"\n",
"- Conditional branching (e.g., only asking for elaboration if the first plan is too short)\n",
"- Different models for different steps (e.g., `text-davinci-002` for the text planning steps and `code-davinci-002` for the code writing step)\n",
"- A check that re-runs the function if the output is unsatisfactory (e.g., if the output code cannot be parsed by Python's `ast` module)\n",
"- Streaming output so that you can start reading the output before it's fully generated (useful for long, multi-step outputs)\n",
"\n",
"The full 3-step prompt looks like this (using as an example `pytest` for the unit test framework and `is_palindrome` as the function):\n",
"\n",
" # How to write great unit tests with pytest\n",
"\n",
" In this advanced tutorial for experts, we'll use Python 3.9 and `pytest` to write a suite of unit tests to verify the behavior of the following function.\n",
" ```python\n",
" def is_palindrome(s):\n",
" return s == s[::-1]\n",
" ```\n",
"\n",
" Before writing any unit tests, let's review what each element of the function is doing exactly and what the author's intentions may have been.\n",
" - First,{GENERATED IN STEP 1}\n",
" \n",
" A good unit test suite should aim to:\n",
" - Test the function's behavior for a wide range of possible inputs\n",
" - Test edge cases that the author may not have foreseen\n",
" - Take advantage of the features of `pytest` to make the tests easy to write and maintain\n",
" - Be easy to read and understand, with clean code and descriptive names\n",
" - Be deterministic, so that the tests always pass or fail in the same way\n",
"\n",
" `pytest` has many convenient features that make it easy to write and maintain unit tests. We'll use them to write unit tests for the function above.\n",
"\n",
" For this particular function, we'll want our unit tests to handle the following diverse scenarios (and under each scenario, we include a few examples as sub-bullets):\n",
" -{GENERATED IN STEP 2}\n",
"\n",
" [OPTIONALLY APPENDED]In addition to the scenarios above, we'll also want to make sure we don't forget to test rare or unexpected edge cases (and under each edge case, we include a few examples as sub-bullets):\n",
" -{GENERATED IN STEP 2B}\n",
"\n",
" Before going into the individual tests, let's first look at the complete suite of unit tests as a cohesive whole. We've added helpful comments to explain what each line does.\n",
" ```python\n",
" import pytest # used for our unit tests\n",
"\n",
" def is_palindrome(s):\n",
" return s == s[::-1]\n",
"\n",
" #Below, each test case is represented by a tuple passed to the @pytest.mark.parametrize decorator\n",
" {GENERATED IN STEP 3}"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"# imports needed to run the code in this notebook\n",
"import ast # used for detecting whether generated Python code is valid\n",
"import openai # used for calling the OpenAI API\n",
"\n",
"# example of a function that uses a multi-step prompt to write unit tests\n",
"def unit_test_from_function(\n",
" function_to_test: str, # Python function to test, as a string\n",
" unit_test_package: str = \"pytest\", # unit testing package; use the name as it appears in the import statement\n",
" approx_min_cases_to_cover: int = 7, # minimum number of test case categories to cover (approximate)\n",
" print_text: bool = False, # optionally prints text; helpful for understanding the function & debugging\n",
" text_model: str = \"text-davinci-002\", # model used to generate text plans in steps 1, 2, and 2b\n",
" code_model: str = \"code-davinci-002\", # if you don't have access to code models, you can use text models here instead\n",
" max_tokens: int = 1000, # can set this high, as generations should be stopped earlier by stop sequences\n",
" temperature: float = 0.4, # temperature = 0 can sometimes get stuck in repetitive loops, so we use 0.4\n",
" reruns_if_fail: int = 1, # if the output code cannot be parsed, this will re-run the function up to N times\n",
") -> str:\n",
" \"\"\"Outputs a unit test for a given Python function, using a 3-step GPT-3 prompt.\"\"\"\n",
"\n",
" # Step 1: Generate an explanation of the function\n",
"\n",
" # create a markdown-formatted prompt that asks GPT-3 to complete an explanation of the function, formatted as a bullet list\n",
" prompt_to_explain_the_function = f\"\"\"# How to write great unit tests with {unit_test_package}\n",
"\n",
"In this advanced tutorial for experts, we'll use Python 3.9 and `{unit_test_package}` to write a suite of unit tests to verify the behavior of the following function.\n",
"```python\n",
"{function_to_test}\n",
"```\n",
"\n",
"Before writing any unit tests, let's review what each element of the function is doing exactly and what the author's intentions may have been.\n",
"- First,\"\"\"\n",
" if print_text:\n",
" text_color_prefix = \"\\033[30m\" # black; if you read against a dark background \\033[97m is white\n",
" print(text_color_prefix + prompt_to_explain_the_function, end=\"\") # end='' prevents a newline from being printed\n",
"\n",
" # send the prompt to the API, using \\n\\n as a stop sequence to stop at the end of the bullet list\n",
" explanation_response = openai.Completion.create(\n",
" model=text_model,\n",
" prompt=prompt_to_explain_the_function,\n",
" stop=[\"\\n\\n\", \"\\n\\t\\n\", \"\\n \\n\"],\n",
" max_tokens=max_tokens,\n",
" temperature=temperature,\n",
" stream=True,\n",
" )\n",
" explanation_completion = \"\"\n",
" if print_text:\n",
" completion_color_prefix = \"\\033[92m\" # green\n",
" print(completion_color_prefix, end=\"\")\n",
" for event in explanation_response:\n",
" event_text = event[\"choices\"][0][\"text\"]\n",
" explanation_completion += event_text\n",
" if print_text:\n",
" print(event_text, end=\"\")\n",
"\n",
" # Step 2: Generate a plan to write a unit test\n",
"\n",
" # create a markdown-formatted prompt that asks GPT-3 to complete a plan for writing unit tests, formatted as a bullet list\n",
" prompt_to_explain_a_plan = f\"\"\"\n",
" \n",
"A good unit test suite should aim to:\n",
"- Test the function's behavior for a wide range of possible inputs\n",
"- Test edge cases that the author may not have foreseen\n",
"- Take advantage of the features of `{unit_test_package}` to make the tests easy to write and maintain\n",
"- Be easy to read and understand, with clean code and descriptive names\n",
"- Be deterministic, so that the tests always pass or fail in the same way\n",
"\n",
"`{unit_test_package}` has many convenient features that make it easy to write and maintain unit tests. We'll use them to write unit tests for the function above.\n",
"\n",
"For this particular function, we'll want our unit tests to handle the following diverse scenarios (and under each scenario, we include a few examples as sub-bullets):\n",
"-\"\"\"\n",
" if print_text:\n",
" print(text_color_prefix + prompt_to_explain_a_plan, end=\"\")\n",
"\n",
" # append this planning prompt to the results from step 1\n",
" prior_text = prompt_to_explain_the_function + explanation_completion\n",
" full_plan_prompt = prior_text + prompt_to_explain_a_plan\n",
"\n",
" # send the prompt to the API, using \\n\\n as a stop sequence to stop at the end of the bullet list\n",
" plan_response = openai.Completion.create(\n",
" model=text_model,\n",
" prompt=full_plan_prompt,\n",
" stop=[\"\\n\\n\", \"\\n\\t\\n\", \"\\n \\n\"],\n",
" max_tokens=max_tokens,\n",
" temperature=temperature,\n",
" stream=True,\n",
" )\n",
" plan_completion = \"\"\n",
" if print_text:\n",
" print(completion_color_prefix, end=\"\")\n",
" for event in plan_response:\n",
" event_text = event[\"choices\"][0][\"text\"]\n",
" plan_completion += event_text\n",
" if print_text:\n",
" print(event_text, end=\"\")\n",
"\n",
" # Step 2b: If the plan is short, ask GPT-3 to elaborate further\n",
" # this counts top-level bullets (e.g., categories), but not sub-bullets (e.g., test cases)\n",
" elaboration_needed = plan_completion.count(\"\\n-\") +1 < approx_min_cases_to_cover # adds 1 because the first bullet is not counted\n",
" if elaboration_needed:\n",
" prompt_to_elaborate_on_the_plan = f\"\"\"\n",
"\n",
"In addition to the scenarios above, we'll also want to make sure we don't forget to test rare or unexpected edge cases (and under each edge case, we include a few examples as sub-bullets):\n",
"-\"\"\"\n",
" if print_text:\n",
" print(text_color_prefix + prompt_to_elaborate_on_the_plan, end=\"\")\n",
"\n",
" # append this elaboration prompt to the results from step 2\n",
" prior_text = full_plan_prompt + plan_completion\n",
" full_elaboration_prompt = prior_text + prompt_to_elaborate_on_the_plan\n",
"\n",
" # send the prompt to the API, using \\n\\n as a stop sequence to stop at the end of the bullet list\n",
" elaboration_response = openai.Completion.create(\n",
" model=text_model,\n",
" prompt=full_elaboration_prompt,\n",
" stop=[\"\\n\\n\", \"\\n\\t\\n\", \"\\n \\n\"],\n",
" max_tokens=max_tokens,\n",
" temperature=temperature,\n",
" stream=True,\n",
" )\n",
" elaboration_completion = \"\"\n",
" if print_text:\n",
" print(completion_color_prefix, end=\"\")\n",
" for event in elaboration_response:\n",
" event_text = event[\"choices\"][0][\"text\"]\n",
" elaboration_completion += event_text\n",
" if print_text:\n",
" print(event_text, end=\"\")\n",
"\n",
" # Step 3: Generate the unit test\n",
"\n",
" # create a markdown-formatted prompt that asks GPT-3 to complete a unit test\n",
" starter_comment = \"\"\n",
" if unit_test_package == \"pytest\":\n",
" starter_comment = \"Below, each test case is represented by a tuple passed to the @pytest.mark.parametrize decorator\"\n",
" prompt_to_generate_the_unit_test = f\"\"\"\n",
"\n",
"Before going into the individual tests, let's first look at the complete suite of unit tests as a cohesive whole. We've added helpful comments to explain what each line does.\n",
"```python\n",
"import {unit_test_package} # used for our unit tests\n",
"\n",
"{function_to_test}\n",
"\n",
"#{starter_comment}\"\"\"\n",
" if print_text:\n",
" print(text_color_prefix + prompt_to_generate_the_unit_test, end=\"\")\n",
"\n",
" # append this unit test prompt to the results from step 3\n",
" if elaboration_needed:\n",
" prior_text = full_elaboration_prompt + elaboration_completion\n",
" else:\n",
" prior_text = full_plan_prompt + plan_completion\n",
" full_unit_test_prompt = prior_text + prompt_to_generate_the_unit_test\n",
"\n",
" # send the prompt to the API, using ``` as a stop sequence to stop at the end of the code block\n",
" unit_test_response = openai.Completion.create(\n",
" model=code_model,\n",
" prompt=full_unit_test_prompt,\n",
" stop=\"```\",\n",
" max_tokens=max_tokens,\n",
" temperature=temperature,\n",
" stream=True\n",
" )\n",
" unit_test_completion = \"\"\n",
" if print_text:\n",
" print(completion_color_prefix, end=\"\")\n",
" for event in unit_test_response:\n",
" event_text = event[\"choices\"][0][\"text\"]\n",
" unit_test_completion += event_text\n",
" if print_text:\n",
" print(event_text, end=\"\")\n",
"\n",
" # check the output for errors\n",
" code_start_index = prompt_to_generate_the_unit_test.find(\"```python\\n\") + len(\"```python\\n\")\n",
" code_output = prompt_to_generate_the_unit_test[code_start_index:] + unit_test_completion\n",
" try:\n",
" ast.parse(code_output)\n",
" except SyntaxError as e:\n",
" print(f\"Syntax error in generated code: {e}\")\n",
" if reruns_if_fail > 0:\n",
" print(\"Rerunning...\")\n",
" return unit_test_from_function(\n",
" function_to_test=function_to_test,\n",
" unit_test_package=unit_test_package,\n",
" approx_min_cases_to_cover=approx_min_cases_to_cover,\n",
" print_text=print_text,\n",
" text_model=text_model,\n",
" code_model=code_model,\n",
" max_tokens=max_tokens,\n",
" temperature=temperature,\n",
" reruns_if_fail=reruns_if_fail-1, # decrement rerun counter when calling again\n",
" )\n",
"\n",
" # return the unit test as a string\n",
" return unit_test_completion\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[30m# How to write great unit tests with pytest\n",
"\n",
"In this advanced tutorial for experts, we'll use Python 3.9 and `pytest` to write a suite of unit tests to verify the behavior of the following function.\n",
"```python\n",
"def is_palindrome(s):\n",
" return s == s[::-1]\n",
"```\n",
"\n",
"Before writing any unit tests, let's review what each element of the function is doing exactly and what the author's intentions may have been.\n",
"- First,\u001b[92m we have a function definition. This is where we give the function a name, `is_palindrome`, and specify the arguments that the function accepts. In this case, the function accepts a single string argument, `s`.\n",
"- Next, we have a return statement. This is where we specify the value that the function returns. In this case, the function returns `s == s[::-1]`.\n",
"- Finally, we have a function call. This is where we actually call the function with a specific set of arguments. In this case, we're calling the function with the string `\"racecar\"`.\u001b[30m\n",
" \n",
"A good unit test suite should aim to:\n",
"- Test the function's behavior for a wide range of possible inputs\n",
"- Test edge cases that the author may not have foreseen\n",
"- Take advantage of the features of `pytest` to make the tests easy to write and maintain\n",
"- Be easy to read and understand, with clean code and descriptive names\n",
"- Be deterministic, so that the tests always pass or fail in the same way\n",
"\n",
"`pytest` has many convenient features that make it easy to write and maintain unit tests. We'll use them to write unit tests for the function above.\n",
"\n",
"For this particular function, we'll want our unit tests to handle the following diverse scenarios (and under each scenario, we include a few examples as sub-bullets):\n",
"-\u001b[92m The input is a palindrome\n",
" - `\"racecar\"`\n",
" - `\"madam\"`\n",
" - `\"anna\"`\n",
"- The input is not a palindrome\n",
" - `\"python\"`\n",
" - `\"test\"`\n",
" - `\"1234\"`\n",
"- The input is an empty string\n",
" - `\"\"`\n",
"- The input is `None`\n",
"- The input is not a string\n",
" - `1`\n",
" - `1.0`\n",
" - `True`\n",
" - `False`\n",
" - `[]`\n",
" - `{}`\u001b[30m\n",
"\n",
"In addition to the scenarios above, we'll also want to make sure we don't forget to test rare or unexpected edge cases (and under each edge case, we include a few examples as sub-bullets):\n",
"-\u001b[92m The input is a palindrome with spaces\n",
" - `\"race car\"`\n",
" - `\" madam \"`\n",
" - `\" anna \"`\n",
"- The input is not a palindrome with spaces\n",
" - `\" python \"`\n",
" - `\" test \"`\n",
" - `\" 1234 \"`\n",
"- The input is a palindrome with punctuation\n",
" - `\"racecar!\"`\n",
" - `\"Madam, I'm Adam.\"`\n",
" - `\"Anna's\"`\n",
"- The input is not a palindrome with punctuation\n",
" - `\"python!\"`\n",
" - `\"test.\"`\n",
" - `\"1234!\"`\n",
"- The input is a palindrome with mixed case\n",
" - `\"Racecar\"`\n",
" - `\"Madam\"`\n",
" - `\"Anna\"`\n",
"- The input is not a palindrome with mixed case\n",
" - `\"Python\"`\n",
" - `\"Test\"`\n",
" - `\"1234\"`\u001b[30m\n",
"\n",
"Before going into the individual tests, let's first look at the complete suite of unit tests as a cohesive whole. We've added helpful comments to explain what each line does.\n",
"```python\n",
"import pytest # used for our unit tests\n",
"\n",
"def is_palindrome(s):\n",
" return s == s[::-1]\n",
"\n",
"#Below, each test case is represented by a tuple passed to the @pytest.mark.parametrize decorator\u001b[92m.\n",
"#The first element of the tuple is a name for the test case, and the second element is a list of arguments for the test case.\n",
"#The @pytest.mark.parametrize decorator will generate a separate test function for each test case.\n",
"#The generated test function will be named test_is_palindrome_<name> where <name> is the name of the test case.\n",
"#The generated test function will be given the arguments specified in the list of arguments for the test case.\n",
"#The generated test function will be given the fixture specified in the decorator, in this case the function itself.\n",
"#The generated test function will call the function with the arguments and assert that the result is equal to the expected value.\n",
"@pytest.mark.parametrize(\n",
" \"name,args,expected\",\n",
" [\n",
" # Test the function's behavior for a wide range of possible inputs\n",
" (\"palindrome\", [\"racecar\"], True),\n",
" (\"palindrome\", [\"madam\"], True),\n",
" (\"palindrome\", [\"anna\"], True),\n",
" (\"non-palindrome\", [\"python\"], False),\n",
" (\"non-palindrome\", [\"test\"], False),\n",
" (\"non-palindrome\", [\"1234\"], False),\n",
" (\"empty string\", [\"\"], True),\n",
" (\"None\", [None], False),\n",
" (\"non-string\", [1], False),\n",
" (\"non-string\", [1.0], False),\n",
" (\"non-string\", [True], False),\n",
" (\"non-string\", [False], False),\n",
" (\"non-string\", [[]], False),\n",
" (\"non-string\", [{}], False),\n",
" # Test edge cases that the author may not have foreseen\n",
" (\"palindrome with spaces\", [\"race car\"], True),\n",
" (\"palindrome with spaces\", [\" madam \"], True),\n",
" (\"palindrome with spaces\", [\" anna \"], True),\n",
" (\"non-palindrome with spaces\", [\" python \"], False),\n",
" (\"non-palindrome with spaces\", [\" test \"], False),\n",
" (\"non-palindrome with spaces\", [\" 1234 \"], False),\n",
" (\"palindrome with punctuation\", [\"racecar!\"], True),\n",
" (\"palindrome with punctuation\", [\"Madam, I'm Adam.\"], True),\n",
" (\"palindrome with punctuation\", [\"Anna's\"], True),\n",
" (\"non-palindrome with punctuation\", [\"python!\"], False),\n",
" (\"non-palindrome with punctuation\", [\"test.\"], False),\n",
" (\"non-palindrome with punctuation\", [\"1234!\"], False),\n",
" (\"palindrome with mixed case\", [\"Racecar\"], True),\n",
" (\"palindrome with mixed case\", [\"Madam\"], True),\n",
" (\"palindrome with mixed case\", [\"Anna\"], True),\n",
" (\"non-palindrome with mixed case\", [\"Python\"], False),\n",
" (\"non-palindrome with mixed case\", [\"Test\"], False),\n",
" (\"non-palindrome with mixed case\", [\"1234\"], False),\n",
" ],\n",
")\n",
"def test_is_palindrome(is_palindrome, args, expected):\n",
" assert is_palindrome(*args) == expected\n"
]
},
{
"data": {
"text/plain": [
"'.\\n#The first element of the tuple is a name for the test case, and the second element is a list of arguments for the test case.\\n#The @pytest.mark.parametrize decorator will generate a separate test function for each test case.\\n#The generated test function will be named test_is_palindrome_<name> where <name> is the name of the test case.\\n#The generated test function will be given the arguments specified in the list of arguments for the test case.\\n#The generated test function will be given the fixture specified in the decorator, in this case the function itself.\\n#The generated test function will call the function with the arguments and assert that the result is equal to the expected value.\\n@pytest.mark.parametrize(\\n \"name,args,expected\",\\n [\\n # Test the function\\'s behavior for a wide range of possible inputs\\n (\"palindrome\", [\"racecar\"], True),\\n (\"palindrome\", [\"madam\"], True),\\n (\"palindrome\", [\"anna\"], True),\\n (\"non-palindrome\", [\"python\"], False),\\n (\"non-palindrome\", [\"test\"], False),\\n (\"non-palindrome\", [\"1234\"], False),\\n (\"empty string\", [\"\"], True),\\n (\"None\", [None], False),\\n (\"non-string\", [1], False),\\n (\"non-string\", [1.0], False),\\n (\"non-string\", [True], False),\\n (\"non-string\", [False], False),\\n (\"non-string\", [[]], False),\\n (\"non-string\", [{}], False),\\n # Test edge cases that the author may not have foreseen\\n (\"palindrome with spaces\", [\"race car\"], True),\\n (\"palindrome with spaces\", [\" madam \"], True),\\n (\"palindrome with spaces\", [\" anna \"], True),\\n (\"non-palindrome with spaces\", [\" python \"], False),\\n (\"non-palindrome with spaces\", [\" test \"], False),\\n (\"non-palindrome with spaces\", [\" 1234 \"], False),\\n (\"palindrome with punctuation\", [\"racecar!\"], True),\\n (\"palindrome with punctuation\", [\"Madam, I\\'m Adam.\"], True),\\n (\"palindrome with punctuation\", [\"Anna\\'s\"], True),\\n (\"non-palindrome with punctuation\", [\"python!\"], False),\\n (\"non-palindrome with punctuation\", [\"test.\"], False),\\n (\"non-palindrome with punctuation\", [\"1234!\"], False),\\n (\"palindrome with mixed case\", [\"Racecar\"], True),\\n (\"palindrome with mixed case\", [\"Madam\"], True),\\n (\"palindrome with mixed case\", [\"Anna\"], True),\\n (\"non-palindrome with mixed case\", [\"Python\"], False),\\n (\"non-palindrome with mixed case\", [\"Test\"], False),\\n (\"non-palindrome with mixed case\", [\"1234\"], False),\\n ],\\n)\\ndef test_is_palindrome(is_palindrome, args, expected):\\n assert is_palindrome(*args) == expected\\n'"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"example_function = \"\"\"def is_palindrome(s):\n",
" return s == s[::-1]\"\"\"\n",
"\n",
"unit_test_from_function(example_function, print_text=True)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3.9.9 ('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.9"
},
"orig_nbformat": 4,
"vscode": {
"interpreter": {
"hash": "365536dcbde60510dc9073d6b991cd35db2d9bac356a11f5b64279a5e6708b97"
}
}
},
"nbformat": 4,
"nbformat_minor": 2
}

@ -27,11 +27,11 @@
}
],
"source": [
"import openai\n",
"from openai import OpenAI\n",
"\n",
"embedding = openai.Embedding.create(\n",
" input=\"Your text goes here\", model=\"text-embedding-ada-002\"\n",
")[\"data\"][0][\"embedding\"]\n",
"client = OpenAI()\n",
"\n",
"embedding = client.embeddings.create(input=\"Your text goes here\", model=\"text-embedding-ada-002\").data[0].embedding\n",
"len(embedding)\n"
]
},
@ -50,13 +50,13 @@
"outputs": [],
"source": [
"# Negative example (slow and rate-limited)\n",
"import openai\n",
"from openai import OpenAI\n",
"\n",
"client = OpenAI()\n",
"\n",
"num_embeddings = 10000 # Some large number\n",
"for i in range(num_embeddings):\n",
" embedding = openai.Embedding.create(\n",
" input=\"Your text goes here\", model=\"text-embedding-ada-002\"\n",
" )[\"data\"][0][\"embedding\"]\n",
" embedding = client.embeddings.create(input=\"Your text goes here\", model=\"text-embedding-ada-002\").data[0].embedding\n",
" print(len(embedding))"
]
},
@ -75,13 +75,15 @@
],
"source": [
"# Best practice\n",
"import openai\n",
"from openai import OpenAI\n",
"\n",
"client = OpenAI()\n",
"from tenacity import retry, wait_random_exponential, stop_after_attempt\n",
"\n",
"# Retry up to 6 times with exponential backoff, starting at 1 second and maxing out at 20 seconds delay\n",
"@retry(wait=wait_random_exponential(min=1, max=20), stop=stop_after_attempt(6))\n",
"def get_embedding(text: str, model=\"text-embedding-ada-002\") -> list[float]:\n",
" return openai.Embedding.create(input=[text], model=model)[\"data\"][0][\"embedding\"]\n",
" return client.embeddings.create(input=[text], model=model).data[0].embedding\n",
"\n",
"embedding = get_embedding(\"Your text goes here\", model=\"text-embedding-ada-002\")\n",
"print(len(embedding))"

@ -50,9 +50,9 @@
"from math import exp\n",
"import numpy as np\n",
"from IPython.display import display, HTML\n",
"import os\n",
"\n",
"\n",
"client = OpenAI()"
"client = OpenAI(api_key=os.environ.get(\"OPENAI_API_KEY\", \"<your OpenAI API key if not set as env var>\"))"
]
},
{

@ -32,8 +32,11 @@
"outputs": [],
"source": [
"# imports\n",
"import openai # for making OpenAI API calls\n",
"import urllib # for downloading example audio files\n"
"from openai import OpenAI # for making OpenAI API calls\n",
"import urllib # for downloading example audio files\n",
"import os # for accessing environment variables\n",
"\n",
"client = OpenAI(api_key=os.environ.get(\"OPENAI_API_KEY\", \"<your OpenAI API key if not set as env var>\"))"
]
},
{
@ -90,7 +93,7 @@
"# define a wrapper function for seeing how prompts affect transcriptions\n",
"def transcribe(prompt: str, audio_filepath) -> str:\n",
" \"\"\"Given a prompt, transcribe the audio file.\"\"\"\n",
" transcript = openai.audio.transcriptions.create(\n",
" transcript = client.audio.transcriptions.create(\n",
" file=open(audio_filepath, \"rb\"),\n",
" model=\"whisper-1\",\n",
" prompt=prompt,\n",
@ -206,7 +209,7 @@
"source": [
"# define a wrapper function for seeing how prompts affect transcriptions\n",
"def transcribe_with_spellcheck(system_message, audio_filepath):\n",
" completion = openai.chat.completions.create(\n",
" completion = client.chat.completions.create(\n",
" model=\"gpt-4\",\n",
" temperature=0,\n",
" messages=[\n",

@ -48,8 +48,7 @@
"metadata": {},
"outputs": [],
"source": [
"client = OpenAI()\n",
"client.api_key = os.getenv(\"OPENAI_API_KEY\")"
"client = OpenAI(api_key=os.environ.get(\"OPENAI_API_KEY\", \"<your OpenAI API key if not set as env var>\"))"
]
},
{
@ -492,7 +491,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.5"
"version": "3.11.3"
},
"orig_nbformat": 4
},

@ -48,8 +48,11 @@
"outputs": [],
"source": [
"# imports\n",
"import openai # for making OpenAI API calls\n",
"import urllib # for downloading example audio files"
"from openai import OpenAI # for making OpenAI API calls\n",
"import urllib # for downloading example audio files\n",
"import os\n",
"\n",
"client = OpenAI(api_key=os.environ.get(\"OPENAI_API_KEY\", \"<your OpenAI API key if not set as env var>\"))"
]
},
{
@ -106,7 +109,7 @@
"# define a wrapper function for seeing how prompts affect transcriptions\n",
"def transcribe(audio_filepath, prompt: str) -> str:\n",
" \"\"\"Given a prompt, transcribe the audio file.\"\"\"\n",
" transcript = openai.audio.transcriptions.create(\n",
" transcript = client.audio.transcriptions.create(\n",
" file=open(audio_filepath, \"rb\"),\n",
" model=\"whisper-1\",\n",
" prompt=prompt,\n",
@ -457,7 +460,7 @@
"# define a function for GPT to generate fictitious prompts\n",
"def fictitious_prompt_from_instruction(instruction: str) -> str:\n",
" \"\"\"Given an instruction, generate a fictitious prompt.\"\"\"\n",
" response = openai.chat.completions.create(\n",
" response = client.chat.completions.create(\n",
" model=\"gpt-3.5-turbo-0613\",\n",
" temperature=0,\n",
" messages=[\n",

@ -1,320 +0,0 @@
{
"cells": [
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"# Azure completions example\n",
"\n",
"This example will cover completions using the Azure OpenAI service. It also includes information on content filtering."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Setup\n",
"\n",
"First, we install the necessary dependencies and import the libraries we will be using."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"! pip install \"openai>=1.0.0,<2.0.0\"\n",
"! pip install python-dotenv"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"import openai\n",
"import dotenv\n",
"\n",
"dotenv.load_dotenv()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Authentication\n",
"\n",
"The Azure OpenAI service supports multiple authentication mechanisms that include API keys and Azure Active Directory token credentials."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"use_azure_active_directory = False # Set this flag to True if you are using Azure Active Directory"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Authentication using API key\n",
"\n",
"To set up the OpenAI SDK to use an *Azure API Key*, we need to set `api_key` to a key associated with your endpoint (you can find this key in *\"Keys and Endpoints\"* under *\"Resource Management\"* in the [Azure Portal](https://portal.azure.com)). You'll also find the endpoint for your resource here."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"if not use_azure_active_directory:\n",
" endpoint = os.environ[\"AZURE_OPENAI_ENDPOINT\"]\n",
" api_key = os.environ[\"AZURE_OPENAI_API_KEY\"]\n",
"\n",
" client = openai.AzureOpenAI(\n",
" azure_endpoint=endpoint,\n",
" api_key=api_key,\n",
" api_version=\"2023-09-01-preview\"\n",
" )"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Authentication using Azure Active Directory\n",
"Let's now see how we can autheticate via Azure Active Directory. We'll start by installing the `azure-identity` library. This library will provide the token credentials we need to authenticate and help us build a token credential provider through the `get_bearer_token_provider` helper function. It's recommended to use `get_bearer_token_provider` over providing a static token to `AzureOpenAI` because this API will automatically cache and refresh tokens for you. \n",
"\n",
"For more information on how to set up Azure Active Directory authentication with Azure OpenAI, see the [documentation](https://learn.microsoft.com/azure/ai-services/openai/how-to/managed-identity)."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"! pip install \"azure-identity>=1.15.0\""
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"from azure.identity import DefaultAzureCredential, get_bearer_token_provider\n",
"\n",
"if use_azure_active_directory:\n",
" endpoint = os.environ[\"AZURE_OPENAI_ENDPOINT\"]\n",
" api_key = os.environ[\"AZURE_OPENAI_API_KEY\"]\n",
"\n",
" client = openai.AzureOpenAI(\n",
" azure_endpoint=endpoint,\n",
" azure_ad_token_provider=get_bearer_token_provider(DefaultAzureCredential(), \"https://cognitiveservices.azure.com/.default\"),\n",
" api_version=\"2023-09-01-preview\"\n",
" )"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"> Note: the AzureOpenAI infers the following arguments from their corresponding environment variables if they are not provided:\n",
"\n",
"- `api_key` from `AZURE_OPENAI_API_KEY`\n",
"- `azure_ad_token` from `AZURE_OPENAI_AD_TOKEN`\n",
"- `api_version` from `OPENAI_API_VERSION`\n",
"- `azure_endpoint` from `AZURE_OPENAI_ENDPOINT`\n"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## Deployments\n",
"\n",
"In this section we are going to create a deployment of a model that we can use to create completions."
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"### Deployments: Create in the Azure OpenAI Studio\n",
"Let's deploy a model to use with completions. Go to https://portal.azure.com, find your Azure OpenAI resource, and then navigate to the Azure OpenAI Studio. Click on the \"Deployments\" tab and then create a deployment for the model you want to use for completions. The deployment name that you give the model will be used in the code below."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"deployment = \"\" # Fill in the deployment name from the portal here"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## Completions\n",
"\n",
"Now let's create a completion using the client we built."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"prompt = \"The food was delicious and the waiter\"\n",
"completion = client.completions.create(\n",
" model=deployment,\n",
" prompt=prompt,\n",
" stop=\".\",\n",
" temperature=0\n",
")\n",
" \n",
"print(f\"{prompt}{completion.choices[0].text}.\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Create a streaming completion\n",
"\n",
"We can also stream the response."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"prompt = \"The food was delicious and the waiter\"\n",
"response = client.completions.create(\n",
" model=deployment,\n",
" prompt=prompt,\n",
" stream=True,\n",
")\n",
"for completion in response:\n",
" if len(completion.choices) > 0:\n",
" print(f\"{completion.choices[0].text}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Content filtering\n",
"\n",
"Azure OpenAI service includes content filtering of prompts and completion responses. You can learn more about content filtering and how to configure it [here](https://learn.microsoft.com/azure/ai-services/openai/concepts/content-filter).\n",
"\n",
"If the prompt is flagged by the content filter, the library will raise a `BadRequestError` exception with a `content_filter` error code. Otherwise, you can access the `prompt_filter_results` and `content_filter_results` on the response to see the results of the content filtering and what categories were flagged."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Prompt flagged by content filter"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import json\n",
"\n",
"try:\n",
" completion = client.completions.create(\n",
" prompt=\"<text violating the content policy>\",\n",
" model=deployment,\n",
" )\n",
"except openai.BadRequestError as e:\n",
" err = json.loads(e.response.text)\n",
" if err[\"error\"][\"code\"] == \"content_filter\":\n",
" print(\"Content filter triggered!\")\n",
" content_filter_result = err[\"error\"][\"innererror\"][\"content_filter_result\"]\n",
" for category, details in content_filter_result.items():\n",
" print(f\"{category}:\\n filtered={details['filtered']}\\n severity={details['severity']}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Checking the result of the content filter"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"completion = client.completions.create(\n",
" prompt=\"What's the biggest city in Washington?\",\n",
" model=deployment,\n",
")\n",
"\n",
"print(f\"Answer: {completion.choices[0].text}\")\n",
"\n",
"# prompt content filter result in \"model_extra\" for azure\n",
"prompt_filter_result = completion.model_extra[\"prompt_filter_results\"][0][\"content_filter_results\"]\n",
"print(\"\\nPrompt content filter results:\")\n",
"for category, details in prompt_filter_result.items():\n",
" print(f\"{category}:\\n filtered={details['filtered']}\\n severity={details['severity']}\")\n",
"\n",
"# completion content filter result\n",
"print(\"\\nCompletion content filter results:\")\n",
"completion_filter_result = completion.choices[0].model_extra[\"content_filter_results\"]\n",
"for category, details in completion_filter_result.items():\n",
" print(f\"{category}:\\n filtered={details['filtered']}\\n severity={details['severity']}\")"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"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.10.0"
},
"vscode": {
"interpreter": {
"hash": "3a5103089ab7e7c666b279eeded403fcec76de49a40685dbdfe9f9c78ad97c17"
}
}
},
"nbformat": 4,
"nbformat_minor": 2
}

@ -228,7 +228,7 @@
"source": [
"#### 2. Pass function definition(s) into chat completions API\n",
"\n",
"Now we can pass the function into the chat completions API. If the model determines it should call the function, a `finish_reason` of \"function_call\" will be populated on the choice and the details of which function to call and its arguments will be present in the `message`. Optionally, you can set the `function_call` keyword argument to force the model to call a particular function (e.g. `function_call={\"name\": get_current_weather}`). By default, this is set to `auto`, allowing the model to choose whether to call the function or not. "
"Now we can pass the function into the chat completions API. If the model determines it should call the function, a `finish_reason` of \"tool_calls\" will be populated on the choice and the details of which function to call and its arguments will be present in the `message`. Optionally, you can set the `tool_choice` keyword argument to force the model to call a particular function (e.g. `{\"type\": \"function\", \"function\": {\"name\": get_current_weather}}`). By default, this is set to `auto`, allowing the model to choose whether to call the function or not. "
]
},
{
@ -245,7 +245,7 @@
"chat_completion = client.chat.completions.create(\n",
" model=deployment,\n",
" messages=messages,\n",
" functions=functions,\n",
" tools=functions,\n",
")\n",
"print(chat_completion)"
]
@ -278,7 +278,7 @@
" unit = request.get(\"unit\")\n",
" return {\"temperature\": \"22\", \"unit\": \"celsius\", \"description\": \"Sunny\"}\n",
"\n",
"function_call = chat_completion.choices[0].message.function_call\n",
"function_call = chat_completion.choices[0].message.tool_calls[0].function\n",
"print(function_call.name)\n",
"print(function_call.arguments)\n",
"\n",
@ -313,7 +313,7 @@
"function_completion = client.chat.completions.create(\n",
" model=deployment,\n",
" messages=messages,\n",
" functions=functions,\n",
" tools=functions,\n",
")\n",
"\n",
"print(function_completion.choices[0].message.content.strip())"

@ -35,9 +35,12 @@
}
],
"source": [
"import openai\n",
"from openai import OpenAI\n",
"import os\n",
"from transformers import GPT2Tokenizer\n",
"\n",
"client = OpenAI(api_key=os.environ.get(\"OPENAI_API_KEY\", \"<your OpenAI API key if you didn't set as an env var>\"))\n",
"\n",
"# OpenAI GPT-2 tokenizer is the same as GPT-3 tokenizer\n",
"# we use it to count the number of tokens in the text\n",
"tokenizer = GPT2Tokenizer.from_pretrained(\"gpt2\")\n",
@ -212,7 +215,7 @@
}
],
"source": [
"def translate_chunk(chunk, engine='text-davinci-002',\n",
"def translate_chunk(chunk, model='gpt-3.5-turbo',\n",
" dest_language='English',\n",
" sample_translation=(\"\\poglavje{Osnove Geometrije} \\label{osn9Geom}\", \"\\poglavje{The basics of Geometry} \\label{osn9Geom}\")\n",
" ):\n",
@ -224,17 +227,17 @@
"\n",
"{sample_translation[1]}\n",
"'''\n",
" response = openai.Completion.create(\n",
" prompt=prompt,\n",
" engine=engine,\n",
" response = client.chat.completions.create(\n",
" messages=[{\"role\": \"user\", \"content\":prompt}],\n",
" model=model,\n",
" temperature=0,\n",
" top_p=1,\n",
" max_tokens=1500,\n",
" )\n",
" result = response['choices'][0]['text'].strip()\n",
" result = response.choices[0].message.content.strip()\n",
" result = result.replace('\"\"\"', '') # remove the double quotes, as we used them to surround the text\n",
" return result\n",
"print(translate_chunk(chunks[800], engine='text-davinci-002', dest_language='English'))"
"print(translate_chunk(chunks[800], model='gpt-3.5-turbo', dest_language='English'))"
]
},
{
@ -1134,7 +1137,7 @@
"for i, chunk in enumerate(chunks):\n",
" print(str(i+1) + \" / \" + str(len(chunks)))\n",
" # translate each chunk\n",
" translated_chunks.append(translate_chunk(chunk, engine='text-davinci-002', dest_language=dest_language))\n",
" translated_chunks.append(translate_chunk(chunk, model='gpt-3.5-turbo', dest_language=dest_language))\n",
"\n",
"# join the chunks together\n",
"result = '\\n\\n'.join(translated_chunks)\n",

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1,4 +1,5 @@
"""
TODO: This example is deprecated.
Note: To answer questions based on text documents, we recommend the procedure in
[Question Answering using Embeddings](https://github.com/openai/openai-cookbook/blob/main/examples/Question_answering_using_embeddings.ipynb).
Some of the code below may rely on [deprecated API endpoints](https://github.com/openai/openai-cookbook/tree/main/transition_guides_for_deprecated_API_endpoints).
@ -6,7 +7,10 @@ Some of the code below may rely on [deprecated API endpoints](https://github.com
import argparse
import openai
from openai import OpenAI
import os
client = OpenAI(api_key=os.environ.get("OPENAI_API_KEY", "<your OpenAI API key if not set as env var>"))
def create_context(
@ -21,7 +25,8 @@ def create_context(
:param max_rerank: The maximum number of reranking
:return: The context
"""
results = openai.Engine(search_model).search(
# TODO: openai.Engine(search_model) is deprecated
results = client.Engine(search_model).search(
search_model=search_model,
query=question,
max_rerank=max_rerank,
@ -80,16 +85,14 @@ def answer_question(
and fine_tuned_qa_model.split(":")[1].startswith("ft")
else {"engine": fine_tuned_qa_model}
)
response = openai.Completion.create(
prompt=f"Answer the question based on the context below\n\nText: {context}\n\n---\n\nQuestion: {question}\nAnswer:",
temperature=0,
max_tokens=max_tokens,
top_p=1,
frequency_penalty=0,
presence_penalty=0,
stop=stop_sequence,
**model_param,
)
response = client.chat.completions.create(prompt=f"Answer the question based on the context below\n\nText: {context}\n\n---\n\nQuestion: {question}\nAnswer:",
temperature=0,
max_tokens=max_tokens,
top_p=1,
frequency_penalty=0,
presence_penalty=0,
stop=stop_sequence,
**model_param)
return response["choices"][0]["text"]
except Exception as e:
print(e)

@ -92,7 +92,7 @@
"import time\n",
"\n",
"import pandas as pd\n",
"import openai\n",
"from openai import OpenAI\n",
"import tiktoken\n",
"import seaborn as sns\n",
"from tenacity import retry, wait_exponential\n",
@ -106,7 +106,9 @@
"import warnings\n",
"warnings.filterwarnings('ignore')\n",
"\n",
"tqdm.pandas()"
"tqdm.pandas()\n",
"\n",
"client = OpenAI(api_key=os.environ.get(\"OPENAI_API_KEY\", \"<your OpenAI API key if not set as env var>\"))\n"
]
},
{
@ -123,7 +125,6 @@
"metadata": {},
"outputs": [],
"source": [
"openai.api_key = \"sk-xxx\"\n",
"os.environ[\"QDRANT_URL\"] = \"https://xxx.cloud.qdrant.io:6333\"\n",
"os.environ[\"QDRANT_API_KEY\"] = \"xxx\""
]
@ -265,7 +266,7 @@
"# Function with tenacity for retries\n",
"@retry(wait=wait_exponential(multiplier=1, min=2, max=6))\n",
"def api_call(messages, model):\n",
" return openai.ChatCompletion.create(\n",
" return client.chat.completions.create(\n",
" model=model,\n",
" messages=messages,\n",
" stop=[\"\\n\\n\"],\n",
@ -275,10 +276,10 @@
"\n",
"\n",
"# Main function to answer question\n",
"def answer_question(row, prompt_func=get_prompt, model=\"gpt-3.5-turbo-0613\"):\n",
"def answer_question(row, prompt_func=get_prompt, model=\"gpt-3.5-turbo\"):\n",
" messages = prompt_func(row)\n",
" response = api_call(messages, model)\n",
" return response[\"choices\"][0][\"message\"][\"content\"]"
" return response.choices[0].message.content"
]
},
{
@ -557,7 +558,7 @@
" self.model_id = None\n",
"\n",
" def create_openai_file(self):\n",
" self.file_object = openai.File.create(\n",
" self.file_object = client.files.create(\n",
" file=open(self.training_file_path, \"r\"),\n",
" purpose=\"fine-tune\",\n",
" )\n",
@ -569,7 +570,7 @@
" print(\"File Status: \", self.file_object.status)\n",
"\n",
" def create_fine_tuning_job(self):\n",
" self.fine_tuning_job = openai.FineTuningJob.create(\n",
" self.fine_tuning_job = client.fine_tuning.jobs.create(\n",
" training_file=self.file_object[\"id\"],\n",
" model=self.model_name,\n",
" suffix=self.suffix,\n",
@ -582,7 +583,7 @@
" print(\"Job Status: \", self.fine_tuning_job.status)\n",
"\n",
" def retrieve_fine_tuned_model(self):\n",
" self.model_id = openai.FineTuningJob.retrieve(self.fine_tuning_job[\"id\"]).fine_tuned_model\n",
" self.model_id = client.fine_tuning.jobs.retrieve(self.fine_tuning_job[\"id\"]).fine_tuned_model\n",
" return self.model_id\n",
"\n",
" def fine_tune_model(self):\n",
@ -631,7 +632,7 @@
"metadata": {},
"outputs": [],
"source": [
"completion = openai.ChatCompletion.create(\n",
"completion = client.chat.completions.create(\n",
" model=model_id,\n",
" messages=[\n",
" {\"role\": \"system\", \"content\": \"You are a helpful assistant.\"},\n",
@ -1246,7 +1247,7 @@
"outputs": [],
"source": [
"# Let's try this out\n",
"completion = openai.ChatCompletion.create(\n",
"completion = client.chat.completions.create(\n",
" model=model_id,\n",
" messages=[\n",
" {\"role\": \"system\", \"content\": \"You are a helpful assistant.\"},\n",

@ -170,21 +170,21 @@
}
],
"source": [
"import openai\n",
"from openai import OpenAI\n",
"\n",
"client = OpenAI(api_key=os.environ.get(\"OPENAI_API_KEY\", \"<your OpenAI API key if not set as env var>\"))\n",
"\n",
"def get_questions(context):\n",
" try:\n",
" response = openai.Completion.create(\n",
" engine=\"davinci-instruct-beta-v3\",\n",
" prompt=f\"Write questions based on the text below\\n\\nText: {context}\\n\\nQuestions:\\n1.\",\n",
" temperature=0,\n",
" max_tokens=257,\n",
" top_p=1,\n",
" frequency_penalty=0,\n",
" presence_penalty=0,\n",
" stop=[\"\\n\\n\"]\n",
" )\n",
" return response['choices'][0]['text']\n",
" response = client.chat.completions.create(model=\"davinci-instruct-beta-v3\",\n",
" prompt=f\"Write questions based on the text below\\n\\nText: {context}\\n\\nQuestions:\\n1.\",\n",
" temperature=0,\n",
" max_tokens=257,\n",
" top_p=1,\n",
" frequency_penalty=0,\n",
" presence_penalty=0,\n",
" stop=[\"\\n\\n\"])\n",
" return response.choices[0].text\n",
" except:\n",
" return \"\"\n",
"\n",
@ -254,7 +254,7 @@
"source": [
"def get_answers(row):\n",
" try:\n",
" response = openai.Completion.create(\n",
" response = client.chat.completions.create(\n",
" engine=\"davinci-instruct-beta-v3\",\n",
" prompt=f\"Write answer based on the text below\\n\\nText: {row.context}\\n\\nQuestions:\\n{row.questions}\\n\\nAnswers:\\n1.\",\n",
" temperature=0,\n",
@ -263,7 +263,7 @@
" frequency_penalty=0,\n",
" presence_penalty=0\n",
" )\n",
" return response['choices'][0]['text']\n",
" return response.choices[0].text\n",
" except Exception as e:\n",
" print (e)\n",
" return \"\"\n",
@ -320,7 +320,7 @@
"df = df[df.tokens<2000]\n",
"df[['context', 'tokens']].rename(columns={'context':'text','tokens':'metadata'}).to_json('olympics-data/olympics_search.jsonl', orient='records', lines=True)\n",
"\n",
"search_file = openai.File.create(\n",
"search_file = client.files.create(\n",
" file=open(\"olympics-data/olympics_search.jsonl\"),\n",
" purpose='search'\n",
")\n",
@ -473,6 +473,7 @@
" \"\"\"\n",
" \n",
" try:\n",
" # TODO: openai.Engine(search_model) is deprecated\n",
" results = openai.Engine(search_model).search(\n",
" search_model=search_model, \n",
" query=question, \n",

@ -244,6 +244,7 @@
" Find similar contexts to the given context using the search file\n",
" \"\"\"\n",
" try:\n",
" # TODO: openai.Engine(search_model) is deprecated\n",
" results = openai.Engine(search_model).search(\n",
" search_model=search_model, \n",
" query=question, \n",
@ -438,7 +439,7 @@
" Apply the fine tuned discriminator to a question, to assess whether it can be answered from the context.\n",
" \"\"\"\n",
" prompt = f\"{context}\\nQuestion: {question}\\n Related:\"\n",
" result = openai.Completion.create(model=discriminator_model, prompt=prompt, max_tokens=1, temperature=0, top_p=1, n=1, logprobs=2)\n",
" result = openai.chat.completions.create(model=discriminator_model, prompt=prompt, max_tokens=1, temperature=0, top_p=1, n=1, logprobs=2)\n",
" return result['choices'][0]['logprobs']['top_logprobs']\n",
"\n",
"apply_ft_discriminator('The first human-made object in space was the Soviet Union satellite Sputnik 1 on 4 October 1957.', \n",
@ -474,7 +475,7 @@
" Apply the fine tuned discriminator to a question\n",
" \"\"\"\n",
" prompt = f\"{context}\\nQuestion: {question}\\nAnswer:\"\n",
" result = openai.Completion.create(model=answering_model, prompt=prompt, max_tokens=30, temperature=0, top_p=1, n=1, stop=['.','\\n'])\n",
" result = openai.chat.completions.create(model=answering_model, prompt=prompt, max_tokens=30, temperature=0, top_p=1, n=1, stop=['.','\\n'])\n",
" return result['choices'][0]['text']\n",
"\n",
"apply_ft_qa_answer('The first human-made object in space was the Soviet Union satellite Sputnik 1 on 4 October 1957.', \n",

@ -41,12 +41,23 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 1,
"id": "9617e95e",
"metadata": {},
"outputs": [],
"outputs": [
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 1,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import openai\n",
"from openai import OpenAI\n",
"import json\n",
"import boto3\n",
"import os\n",
@ -69,18 +80,18 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 2,
"id": "6d5b1991",
"metadata": {},
"outputs": [],
"source": [
"openai.api_key = os.environ.get(\"OPENAI_API_KEY\")\n",
"OpenAI.api_key = os.environ.get(\"OPENAI_API_KEY\")\n",
"GPT_MODEL = \"gpt-3.5-turbo\""
]
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 3,
"id": "a571b8d7",
"metadata": {},
"outputs": [],
@ -90,7 +101,10 @@
"# os.environ['AWS_SECRET_ACCESS_KEY'] = ''\n",
"\n",
"# Create S3 client\n",
"s3_client = boto3.client('s3')"
"s3_client = boto3.client('s3')\n",
"\n",
"# Create openai client\n",
"client = OpenAI()"
]
},
{
@ -113,73 +127,88 @@
},
{
"cell_type": "code",
"execution_count": 1,
"execution_count": 4,
"id": "da4a804b",
"metadata": {},
"outputs": [],
"source": [
"# Functions dict to pass S3 operations details for the GPT model\n",
"functions = [\n",
" {\n",
" \"name\": \"list_buckets\",\n",
" \"description\": \"List all available S3 buckets\",\n",
" \"parameters\": {\n",
" \"type\": \"object\",\n",
" \"properties\": {}\n",
" { \n",
" \"type\": \"function\",\n",
" \"function\":{\n",
" \"name\": \"list_buckets\",\n",
" \"description\": \"List all available S3 buckets\",\n",
" \"parameters\": {\n",
" \"type\": \"object\",\n",
" \"properties\": {}\n",
" }\n",
" }\n",
" },\n",
" {\n",
" \"name\": \"list_objects\",\n",
" \"description\": \"List the objects or files inside a given S3 bucket\",\n",
" \"parameters\": {\n",
" \"type\": \"object\",\n",
" \"properties\": {\n",
" \"bucket\": {\"type\": \"string\", \"description\": \"The name of the S3 bucket\"},\n",
" \"prefix\": {\"type\": \"string\", \"description\": \"The folder path in the S3 bucket\"},\n",
" \"type\": \"function\",\n",
" \"function\":{\n",
" \"name\": \"list_objects\",\n",
" \"description\": \"List the objects or files inside a given S3 bucket\",\n",
" \"parameters\": {\n",
" \"type\": \"object\",\n",
" \"properties\": {\n",
" \"bucket\": {\"type\": \"string\", \"description\": \"The name of the S3 bucket\"},\n",
" \"prefix\": {\"type\": \"string\", \"description\": \"The folder path in the S3 bucket\"},\n",
" },\n",
" \"required\": [\"bucket\"],\n",
" },\n",
" \"required\": [\"bucket\"],\n",
" },\n",
" }\n",
" },\n",
" {\n",
" \"name\": \"download_file\",\n",
" \"description\": \"Download a specific file from an S3 bucket to a local distribution folder.\",\n",
" \"parameters\": {\n",
" \"type\": \"object\",\n",
" \"properties\": {\n",
" \"bucket\": {\"type\": \"string\", \"description\": \"The name of the S3 bucket\"},\n",
" \"key\": {\"type\": \"string\", \"description\": \"The path to the file inside the bucket\"},\n",
" \"directory\": {\"type\": \"string\", \"description\": \"The local destination directory to download the file, should be specificed by the user.\"},\n",
" },\n",
" \"required\": [\"bucket\", \"key\", \"directory\"],\n",
" { \n",
" \"type\": \"function\",\n",
" \"function\":{\n",
" \"name\": \"download_file\",\n",
" \"description\": \"Download a specific file from an S3 bucket to a local distribution folder.\",\n",
" \"parameters\": {\n",
" \"type\": \"object\",\n",
" \"properties\": {\n",
" \"bucket\": {\"type\": \"string\", \"description\": \"The name of the S3 bucket\"},\n",
" \"key\": {\"type\": \"string\", \"description\": \"The path to the file inside the bucket\"},\n",
" \"directory\": {\"type\": \"string\", \"description\": \"The local destination directory to download the file, should be specificed by the user.\"},\n",
" },\n",
" \"required\": [\"bucket\", \"key\", \"directory\"],\n",
" }\n",
" }\n",
" },\n",
" {\n",
" \"name\": \"upload_file\",\n",
" \"description\": \"Upload a file to an S3 bucket\",\n",
" \"parameters\": {\n",
" \"type\": \"object\",\n",
" \"properties\": {\n",
" \"source\": {\"type\": \"string\", \"description\": \"The local source path or remote URL\"},\n",
" \"bucket\": {\"type\": \"string\", \"description\": \"The name of the S3 bucket\"},\n",
" \"key\": {\"type\": \"string\", \"description\": \"The path to the file inside the bucket\"},\n",
" \"is_remote_url\": {\"type\": \"boolean\", \"description\": \"Is the provided source a URL (True) or local path (False)\"},\n",
" },\n",
" \"required\": [\"source\", \"bucket\", \"key\", \"is_remote_url\"],\n",
" \"type\": \"function\",\n",
" \"function\":{\n",
" \"name\": \"upload_file\",\n",
" \"description\": \"Upload a file to an S3 bucket\",\n",
" \"parameters\": {\n",
" \"type\": \"object\",\n",
" \"properties\": {\n",
" \"source\": {\"type\": \"string\", \"description\": \"The local source path or remote URL\"},\n",
" \"bucket\": {\"type\": \"string\", \"description\": \"The name of the S3 bucket\"},\n",
" \"key\": {\"type\": \"string\", \"description\": \"The path to the file inside the bucket\"},\n",
" \"is_remote_url\": {\"type\": \"boolean\", \"description\": \"Is the provided source a URL (True) or local path (False)\"},\n",
" },\n",
" \"required\": [\"source\", \"bucket\", \"key\", \"is_remote_url\"],\n",
" }\n",
" }\n",
" },\n",
" {\n",
" \"name\": \"search_s3_objects\",\n",
" \"description\": \"Search for a specific file name inside an S3 bucket\",\n",
" \"parameters\": {\n",
" \"type\": \"object\",\n",
" \"properties\": {\n",
" \"search_name\": {\"type\": \"string\", \"description\": \"The name of the file you want to search for\"},\n",
" \"bucket\": {\"type\": \"string\", \"description\": \"The name of the S3 bucket\"},\n",
" \"prefix\": {\"type\": \"string\", \"description\": \"The folder path in the S3 bucket\"},\n",
" \"exact_match\": {\"type\": \"boolean\", \"description\": \"Set exact_match to True if the search should match the exact file name. Set exact_match to False to compare part of the file name string (the file contains)\"}\n",
" \"type\": \"function\",\n",
" \"function\":{\n",
" \"name\": \"search_s3_objects\",\n",
" \"description\": \"Search for a specific file name inside an S3 bucket\",\n",
" \"parameters\": {\n",
" \"type\": \"object\",\n",
" \"properties\": {\n",
" \"search_name\": {\"type\": \"string\", \"description\": \"The name of the file you want to search for\"},\n",
" \"bucket\": {\"type\": \"string\", \"description\": \"The name of the S3 bucket\"},\n",
" \"prefix\": {\"type\": \"string\", \"description\": \"The folder path in the S3 bucket\"},\n",
" \"exact_match\": {\"type\": \"boolean\", \"description\": \"Set exact_match to True if the search should match the exact file name. Set exact_match to False to compare part of the file name string (the file contains)\"}\n",
" },\n",
" \"required\": [\"search_name\"],\n",
" },\n",
" \"required\": [\"search_name\"],\n",
" },\n",
" }\n",
" }\n",
"]"
]
@ -195,7 +224,7 @@
},
{
"cell_type": "code",
"execution_count": 2,
"execution_count": 5,
"id": "cf30f14e",
"metadata": {},
"outputs": [],
@ -208,7 +237,7 @@
},
{
"cell_type": "code",
"execution_count": 3,
"execution_count": 6,
"id": "37736b74",
"metadata": {},
"outputs": [],
@ -275,7 +304,7 @@
},
{
"cell_type": "code",
"execution_count": 4,
"execution_count": 7,
"id": "03c3d555",
"metadata": {},
"outputs": [],
@ -300,7 +329,7 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 16,
"id": "796acfdd",
"metadata": {},
"outputs": [],
@ -309,13 +338,13 @@
" model_name=GPT_MODEL):\n",
" \n",
" if functions is not None:\n",
" return openai.ChatCompletion.create(\n",
" return client.chat.completions.create(\n",
" model=model_name,\n",
" messages=messages,\n",
" functions=functions,\n",
" function_call=function_call)\n",
" tools=functions,\n",
" tool_choice=function_call)\n",
" else:\n",
" return openai.ChatCompletion.create(\n",
" return client.chat.completions.create(\n",
" model=model_name,\n",
" messages=messages)"
]
@ -340,7 +369,7 @@
},
{
"cell_type": "code",
"execution_count": 6,
"execution_count": 17,
"id": "3e2e9192",
"metadata": {},
"outputs": [],
@ -354,15 +383,15 @@
" \n",
" # Call the model to get a response\n",
" response = chat_completion_request(messages, functions=functions)\n",
" response_message = response['choices'][0]['message']\n",
" response_message = response.choices[0].message\n",
" \n",
" if is_log:\n",
" print(response['choices'])\n",
" print(response.choices)\n",
" \n",
" # check if GPT wanted to call a function\n",
" if response_message.get(\"function_call\"):\n",
" function_name = response_message['function_call']['name']\n",
" function_args = json.loads(response_message['function_call']['arguments'])\n",
" if response_message.tool_calls:\n",
" function_name = response_message.tool_calls[0].function.name\n",
" function_args = json.loads(response_message.tool_calls[0].function.arguments)\n",
" \n",
" # Call the function\n",
" function_response = available_functions[function_name](**function_args)\n",
@ -370,16 +399,16 @@
" # Add the response to the conversation\n",
" messages.append(response_message)\n",
" messages.append({\n",
" \"role\": \"function\",\n",
" \"name\": function_name,\n",
" \"role\": \"tool\",\n",
" \"content\": function_response,\n",
" \"tool_call_id\": response_message.tool_calls[0].id,\n",
" })\n",
" \n",
" # Call the model again to summarize the results\n",
" second_response = chat_completion_request(messages)\n",
" final_message = second_response['choices'][0]['message']['content']\n",
" final_message = second_response.choices[0].message.content\n",
" else:\n",
" final_message = response_message['content']\n",
" final_message = response_message.content\n",
"\n",
" return final_message"
]

@ -9,58 +9,58 @@ from sklearn.manifold import TSNE
from sklearn.metrics import average_precision_score, precision_recall_curve
from tenacity import retry, stop_after_attempt, wait_random_exponential
import openai
from openai import OpenAI
import numpy as np
import pandas as pd
import os
client = OpenAI()
@retry(wait=wait_random_exponential(min=1, max=20), stop=stop_after_attempt(6))
def get_embedding(text: str, model="text-similarity-davinci-001", **kwargs) -> List[float]:
def get_embedding(text: str, model="text-embedding-ada-002", **kwargs) -> List[float]:
# replace newlines, which can negatively affect performance.
text = text.replace("\n", " ")
response = openai.embeddings.create(input=[text], model=model, **kwargs)
response = client.embeddings.create(input=[text], model=model, **kwargs)
return response.data[0].embedding
@retry(wait=wait_random_exponential(min=1, max=20), stop=stop_after_attempt(6))
async def aget_embedding(
text: str, model="text-similarity-davinci-001", **kwargs
text: str, model="text-embedding-ada-002", **kwargs
) -> List[float]:
# replace newlines, which can negatively affect performance.
text = text.replace("\n", " ")
return (await openai.embeddings.create(input=[text], model=model, **kwargs))["data"][0][
"embedding"
]
return (await client.embeddings.create(input=[text], model=model, **kwargs)).data[0].embedding
@retry(wait=wait_random_exponential(min=1, max=20), stop=stop_after_attempt(6))
def get_embeddings(
list_of_text: List[str], model="text-similarity-babbage-001", **kwargs
list_of_text: List[str], model="text-embedding-ada-002", **kwargs
) -> List[List[float]]:
assert len(list_of_text) <= 2048, "The batch size should not be larger than 2048."
# replace newlines, which can negatively affect performance.
list_of_text = [text.replace("\n", " ") for text in list_of_text]
data = openai.embeddings.create(input=list_of_text, model=model, **kwargs).data
data = client.embeddings.create(input=list_of_text, model=model, **kwargs).data
return [d.embedding for d in data]
@retry(wait=wait_random_exponential(min=1, max=20), stop=stop_after_attempt(6))
async def aget_embeddings(
list_of_text: List[str], model="text-similarity-babbage-001", **kwargs
list_of_text: List[str], model="text-embedding-ada-002", **kwargs
) -> List[List[float]]:
assert len(list_of_text) <= 2048, "The batch size should not be larger than 2048."
# replace newlines, which can negatively affect performance.
list_of_text = [text.replace("\n", " ") for text in list_of_text]
data = (await openai.embeddings.create(input=list_of_text, model=model, **kwargs)).data
data = (await client.embeddings.create(input=list_of_text, model=model, **kwargs)).data
return [d.embedding for d in data]

Loading…
Cancel
Save