Prompt Engineering

At the time of writing, there is a time-limited free course about ChatGPT prompt engineering for developers, shared by deeplearning.ai.

Introduction

Two types of LLMs:

  • Base LLM: predicts next word, based on test training data, not able to answer user questions.

  • Instruction Tuned LLM: tries to follow instruction, fine tune on instructions and good attempt at following those instructions. RLHF(refinement learning with human feedback).

The course is focusing on the second type.

For how to write openai code, the Python library can be found here: https://platform.openai.com/docs/libraries

The boilerplate:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import openai
import os

from dotenv import load_dotenv, find_dotenv
_ = load_dotenv(find_dotenv()) # read local .env file for openai api key

openai.api_key = os.getenv('YOUR_OPENAI_API_KEY')

def perform_task(prompt, model="gpt-3.5-turbo", temperature=0):
messages = [{"role": "user", "content": prompt}]
response = openai.ChatCompletion.create(
model=model,
messages=messages,
temperature=temperature,
)
return response.choices[0].message["content"]

Here is the openai chat completion guide: https://platform.openai.com/docs/guides/chat

Guidelines

Prompting principles and tactics:

  • Use clear and specific instructions.

    • Use delimiters to avoid prompt injection.

      • Such as: """, --- or <tag>, <>, etc.
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      text = f"""
      You should ```express what you want``` a model to do by \
      providing instructions that are as clear and \
      specific as you can possibly make them. \
      This will guide the model towards the desired output, \
      and reduce the chances of receiving irrelevant \
      or incorrect responses. Don't confuse writing a \
      clear prompt with writing a short prompt. \
      In many cases, longer prompts provide more clarity \
      and context for the model, which can lead to \
      more detailed and relevant outputs.
      """
      prompt = f"""
      Summarize the text delimited by single backtick \
      into a single sentence.
      `{text}`
      """

      response = perform_task(prompt)
      print(response)
    • Ask for structed output.

      • JSON, YAML, etc, so the they can be used later.
      1
      2
      3
      4
      5
      6
      7
      8
      prompt = f"""
      Generate a list of three made-up book titles along \
      with their authors and genres.
      Provide them in JSON format with the following keys:
      book_id, title, author, genre.
      """
      response = perform_task(prompt)
      print(response)
    • Ask the model to check whether conditions are satisfied.

      • For example, does the input contain a sequence of instructions?
      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
      text_1 = f"""
      Making a cup of tea is easy! First, you need to get some \
      water boiling. While that's happening, \
      grab a cup and put a tea bag in it. Once the water is \
      hot enough, just pour it over the tea bag. \
      Let it sit for a bit so the tea can steep. After a \
      few minutes, take out the tea bag. If you \
      like, you can add some sugar or milk to taste. \
      And that's it! You've got yourself a delicious \
      cup of tea to enjoy.
      """
      prompt = f"""
      You will be provided with text delimited by triple quotes.
      If it contains a sequence of instructions, \
      re-write those instructions in the following format:

      Step 1 - ...
      Step 2 - …

      Step N - …

      If the text does not contain a sequence of instructions, \
      then simply write \"No steps provided.\"

      \"\"\"{text_1}\"\"\"
      """
      response = perform_task(prompt)
      print("Completion for Text 1:")
      print(response)
    • “Few-shot” prompting.

      • Give successful example of completing tasks then ask model to perform the task.
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      prompt = f"""
      Your task is to answer in a consistent style.

      <child>: Teach me about patience.

      <grandparent>: The river that carves the deepest \
      valley flows from a modest spring; the \
      grandest symphony originates from a single note; \
      the most intricate tapestry begins with a solitary thread.

      <child>: Teach me about resilience.
      """
      response = perform_task(prompt)
      print(response)
  • Give the model time to “think”.

    • Specify the steps required to complete a task.
    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
    text = f"""
    In a charming village, siblings Jack and Jill set out on \
    a quest to fetch water from a hilltop \
    well. As they climbed, singing joyfully, misfortune \
    struck—Jack tripped on a stone and tumbled \
    down the hill, with Jill following suit. \
    Though slightly battered, the pair returned home to \
    comforting embraces. Despite the mishap, \
    their adventurous spirits remained undimmed, and they \
    continued exploring with delight.
    """
    # example 1
    prompt_1 = f"""
    Perform the following actions:
    1 - Summarize the following text delimited by single \
    backtick with 1 sentence.
    2 - Translate the summary into French.
    3 - List each name in the French summary.
    4 - Output a json object that contains the following \
    keys: french_summary, num_names.

    Separate your answers with line breaks.

    Text:
    `{text}`
    """
    response = perform_task(prompt_1)
    print("Completion for prompt 1:")
    print(response)
    • Instruct the model to work out its own solution before rushing to a conclusion.
    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
    prompt = f"""
    Your task is to determine if the student's solution \
    is correct or not.
    To solve the problem do the following:
    - First, work out your own solution to the problem.
    - Then compare your solution to the student's solution \
    and evaluate if the student's solution is correct or not.
    Don't decide if the student's solution is correct until
    you have done the problem yourself.

    Use the following format:
    Question:
    ``
    question here
    ``
    Student's solution:
    ``
    student's solution here
    ``
    Actual solution:
    ``
    steps to work out the solution and your solution here
    ``
    Is the student's solution the same as actual solution \
    just calculated:
    ``
    yes or no
    ``
    Student grade:
    ``
    correct or incorrect
    ``

    Question:
    ``
    I'm building a solar power installation and I need help \
    working out the financials.
    - Land costs $100 / square foot
    - I can buy solar panels for $250 / square foot
    - I negotiated a contract for maintenance that will cost \
    me a flat $100k per year, and an additional $10 / square \
    foot
    What is the total cost for the first year of operations \
    as a function of the number of square feet.
    ``
    Student's solution:
    ``
    Let x be the size of the installation in square feet.
    Costs:
    1. Land cost: 100x
    2. Solar panel cost: 250x
    3. Maintenance cost: 100,000 + 100x
    Total cost: 100x + 250x + 100,000 + 100x = 450x + 100,000
    ``
    Actual solution:
    """
    response = perform_task(prompt)
    print(response)

NOTE: it is possible that the answer sounds plausible but are not true.

Reduce the hallucinations: Ask the LLM first find relevant information, then answer the question based on the relevant information.

Iterative

Iterative prompt development steps:

  • Try something.
  • Analyze where the result does not give what you want.
  • Clarify instructions, give more time to think.
  • Refine prompt with a batch of examples.

For example, below examples show how to evolve the prompt to get desired outcome for a e-commerce website:

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
fact_sheet_chair = """
OVERVIEW
- Part of a beautiful family of mid-century inspired office furniture,
including filing cabinets, desks, bookcases, meeting tables, and more.
- Several options of shell color and base finishes.
- Available with plastic back and front upholstery (SWC-100)
or full upholstery (SWC-110) in 10 fabric and 6 leather options.
- Base finish options are: stainless steel, matte black,
gloss white, or chrome.
- Chair is available with or without armrests.
- Suitable for home or business settings.
- Qualified for contract use.

CONSTRUCTION
- 5-wheel plastic coated aluminum base.
- Pneumatic chair adjust for easy raise/lower action.

DIMENSIONS
- WIDTH 53 CM | 20.87”
- DEPTH 51 CM | 20.08”
- HEIGHT 80 CM | 31.50”
- SEAT HEIGHT 44 CM | 17.32”
- SEAT DEPTH 41 CM | 16.14”

OPTIONS
- Soft or hard-floor caster options.
- Two choices of seat foam densities:
medium (1.8 lb/ft3) or high (2.8 lb/ft3)
- Armless or 8 position PU armrests

MATERIALS
SHELL BASE GLIDER
- Cast Aluminum with modified nylon PA6/PA66 coating.
- Shell thickness: 10 mm.
SEAT
- HD36 foam

COUNTRY OF ORIGIN
- Italy
"""

Original prompt:

1
2
3
4
5
6
7
8
9
10
11
12
13
prompt = f"""
Your task is to help a marketing team create a
description for a retail website of a product based
on a technical fact sheet.

Write a product description based on the information
provided in the technical specifications delimited by
single backtick.

Technical specifications: `{fact_sheet_chair}`
"""
response = perform_task(prompt)
print(response)

If the output is too long, you can limit the length explicitly:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
prompt = f"""
Your task is to help a marketing team create a
description for a retail website of a product based
on a technical fact sheet.

Write a product description based on the information
provided in the technical specifications delimited by
single backtick.

Use at most 50 words.

Technical specifications: `{fact_sheet_chair}`
"""
response = perform_task(prompt)
print(response)

After many rounds of improvements, the last prompt gets specified details and table/HTML format:

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
prompt = f"""
Your task is to help a marketing team create a
description for a retail website of a product based
on a technical fact sheet.

Write a product description based on the information
provided in the technical specifications delimited by
single backtick.

The description is intended for furniture retailers,
so should be technical in nature and focus on the
materials the product is constructed from.

At the end of the description, include every 7-character
Product ID in the technical specification.

After the description, include a table that gives the
product's dimensions. The table should have two columns.
In the first column include the name of the dimension.
In the second column include the measurements in inches only.

Give the table the title 'Product Dimensions'.

Format everything as HTML that can be used in a website.
Place the description in a <div> element.

Technical specifications: `{fact_sheet_chair}`
"""

response = perform_task(prompt)
print(response)

Summarizing

For example, the text to be summarized:

1
2
3
4
5
6
7
8
9
10
prod_review = """
Got this panda plush toy for my daughter's birthday, \
who loves it and takes it everywhere. It's soft and \
super cute, and its face has a friendly look. It's \
a bit small for what I paid though. I think there \
might be other options that are bigger for the \
same price. It arrived a day earlier than expected, \
so I got to play with it myself before I gave it \
to her.
"""

You can ask LLM like this:

1
2
3
4
5
6
7
8
9
10
11
12
prompt = f"""
Your task is to generate a short summary of a product \
review from an ecommerce site.

Summarize the review below, delimited by single
backtick, in at most 30 words.

Review: `{prod_review}`
"""

response = perform_task(prompt)
print(response)

Focusing on shipping and delivery details:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
prompt = f"""
Your task is to generate a short summary of a product \
review from an ecommerce site to give feedback to the \
Shipping deparmtment.

Summarize the review below, delimited by single
backtick, in at most 30 words, and focusing on any aspects \
that mention shipping and delivery of the product.

Review: `{prod_review}`
"""

response = perform_task(prompt)
print(response)

Focusing on price and value:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
prompt = f"""
Your task is to generate a short summary of a product \
review from an ecommerce site to give feedback to the \
pricing deparmtment, responsible for determining the \
price of the product.

Summarize the review below, delimited by single
backtick, in at most 30 words, and focusing on any aspects \
that are relevant to the price and perceived value.

Review: `{prod_review}`
"""

response = perform_task(prompt)
print(response)

If the summaries are not relevant to focus, you can adjust the word by using extract instead of summarize:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
prompt = f"""
Your task is to extract relevant information from \
a product review from an ecommerce site to give \
feedback to the Shipping department.

From the review below, delimited by single quote \
extract the information relevant to shipping and \
delivery. Limit to 30 words.

Review: `{prod_review}`
"""

response = perform_task(prompt)
print(response)

To summarize multiple payloads:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# reviews contains multiple texts
for i in range(len(reviews)):
prompt = f"""
Your task is to generate a short summary of a product \
review from an ecommerce site.

Summarize the review below, delimited by triple \
quotes in at most 20 words.

Review: '''{reviews[i]}'''
"""

response = perform_task(prompt)
print(i, response, "\n")

Inferring

For example, extract sentiment(positive or negative), LLMs are pretty good at extracting these.

For example giving the customer review:

1
2
3
4
5
6
7
8
9
10
11
lamp_review = """
Needed a nice lamp for my bedroom, and this one had \
additional storage and not too high of a price point. \
Got it fast. The string to our lamp broke during the \
transit and the company happily sent over a new one. \
Came within a few days as well. It was easy to put \
together. I had a missing part, so I contacted their \
support and they very quickly got me the missing piece! \
Lumina seems to me to be a great company that cares \
about their customers and products!!
"""

You can do multiple tasks at once:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
prompt = f"""
Identify the following items from the review text:
- Sentiment (positive or negative)
- Is the reviewer expressing anger? (true or false)
- Item purchased by reviewer
- Company that made the item

The review is delimited with triple backticks. \
Format your response as a JSON object with \
"Sentiment", "Anger", "Item" and "Brand" as the keys.
If the information isn't present, use "unknown" \
as the value.
Make your response as short as possible.
Format the Anger value as a boolean.

Review text: '''{lamp_review}'''
"""
response = perform_task(prompt)
print(response)

You can also infer topics:

1
2
3
4
5
6
7
8
9
10
11
12
prompt = f"""
Determine five topics that are being discussed in the \
following text, which is delimited by triple backticks.

Make each item one or two words long.

Format your response as a list of items separated by commas.

Text sample: '''{story}'''
"""
response = perform_task(prompt)
print(response)

And you can have a list of keywords and check if the text to be verified is in one of them:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# topic_list contains a list of key words to be identified.
prompt = f"""
Determine whether each item in the following list of \
topics is a topic in the text below, which
is delimited with triple backticks.

Give your answer as list with 0 or 1 for each topic.\

List of topics: {", ".join(topic_list)}

Text sample: '''{story}'''
"""
response = perform_task(prompt)
print(response)

You can output as JSON format to further process.

Transforming

Such as language translation, spelling and grammar checking, tone adjustment, and format conversion.

For example, a universal translator:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
user_messages = [
# System performance is slower than normal
"La performance du système est plus lente que d'habitude.",
# My monitor has pixels that are not lighting
"Mi monitor tiene píxeles que no se iluminan.",
# My mouse is not working
"Il mio mouse non funziona",
# My keyboard has a broken control key
"Mój klawisz Ctrl jest zepsuty",
# My screen is flashing
"我的屏幕在闪烁"
]

for issue in user_messages:
prompt = f"Tell me what language this is: ```{issue}```"
lang = perform_task(prompt)
print(f"Original message ({lang}): {issue}")

prompt = f"""
Translate the following text to English \
and Korean: '''{issue}'''
"""
response = perform_task(prompt)
print(response, "\n")

Tone transformation, for informal to formal:

1
2
3
4
5
6
prompt = f"""
Translate the following from slang to a business letter:
'Dude, This is Joe, check out this spec on this standing lamp.'
"""
response = perform_task(prompt)
print(response)

Spelling and grammar check, to signal to the LLM that you want it to proofread your text, you instruct the model to ‘proofread’ or ‘proofread and correct’.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
text = [ 
"The girl with the black and white puppies have a ball.", # The girl has a ball.
"Yolanda has her notebook.", # ok
"Its going to be a long day. Does the car need it’s oil changed?", # Homonyms
"Their goes my freedom. There going to bring they’re suitcases.", # Homonyms
"Your going to need you’re notebook.", # Homonyms
"That medicine effects my ability to sleep. Have you heard of the butterfly affect?", # Homonyms
"This phrase is to cherck chatGPT for speling abilitty" # spelling
]
for t in text:
prompt = f"""Proofread and correct the following text
and rewrite the corrected version. If you don't find
and errors, just say "No errors found". Don't use
any punctuation around the text:
```{t}```"""
response = perform_task(prompt)
print(response)

Another example, proofread and correct long text:

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
text = f"""
Got this for my daughter for her birthday cuz she keeps taking \
mine from my room. Yes, adults also like pandas too. She takes \
it everywhere with her, and it's super soft and cute. One of the \
ears is a bit lower than the other, and I don't think that was \
designed to be asymmetrical. It's a bit small for what I paid for it \
though. I think there might be other options that are bigger for \
the same price. It arrived a day earlier than expected, so I got \
to play with it myself before I gave it to my daughter.
"""
prompt = f"proofread and correct this review: ```{text}```"
response = perform_task(prompt)
print(response)

from redlines import Redlines

diff = Redlines(text,response)
# This helps highlights the differences
display(Markdown(diff.output_markdown))

prompt = f"""
proofread and correct this review. Make it more compelling.
Ensure it follows APA style guide and targets an advanced reader.
Output in markdown format.
Text: '''{text}'''
"""
response = perform_task(prompt)
display(Markdown(response))

Expanding

Expand short text to long, for example, generate customer service emails that are tailored to each customer’s review.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# Assume the 'review' and 'sentiment' are ready to use.
prompt = f"""
You are a customer service AI assistant.
Your task is to send an email reply to a valued customer.
Given the customer email delimited by ```, \
Generate a reply to thank the customer for their review.
If the sentiment is positive or neutral, thank them for \
their review.
If the sentiment is negative, apologize and suggest that \
they can reach out to customer service.
Make sure to use specific details from the review.
Write in a concise and professional tone.
Sign the email as `AI customer agent`.
Customer review: '''{review}'''
Review sentiment: {sentiment}
"""
response = perform_task(prompt, temperature=0.7)
print(response)

About the temperature parameter, uses 0 if you require reliability and predictability, use high value if requires variety.

Charbot

Utilizing the chat format to have extended conversations with chatbots personalized or specialized for specific tasks or behaviors.

Basically, you need to provide the complete context for each conversation, for example, by appending the messages(from user and assistant) to a list, and dumping the list to LLM for response.

1
2
3
4
5
6
7
8
9
10
11
# The 'system' role is used to provide overall context and details.
# The 'user' role is used to carry user input.
# The 'assistant' role is to specify/record LLM response.
messages = [
{'role':'system', 'content':'You are an assistant that speaks like Shakespeare.'},
{'role':'user', 'content':'tell me a joke'},
{'role':'assistant', 'content':'Why did the chicken cross the road'},
{'role':'user', 'content':'I don\'t know'} ]

response = perform_chatbot_task(messages, temperature=0)
print(response)

And you can summarize the chat session, for example:

1
2
3
4
5
6
7
8
9
10
messages =  context.copy()
messages.append(
{'role':'system', 'content':'create a json summary of the previous food order.\
Itemize the price for each item the fields should be 1) pizza, include size 2) \
list of toppings 3) list of drinks, include size 4) list of sides include \
size 5)total price '},
)

response = get_completion_from_messages(messages, temperature=0)
print(response)
0%