AI/Prompt Engineering

ChatGPT Prompt Engineering for Developers 정리 [3]

sangwonYoon 2023. 5. 3. 09:30
  • 스탠퍼드 대학교의 Andrew Ng 교수님이 강의하신 ChatGPT Prompt Engineering for Developers 강의를 듣고 정리한 글입니다.
  • 단순히 강의 내용을 번역한것이 아니라 내용을 이해한 뒤 정리하였고, 제 개인적인 생각은 +) 표시 뒤에 덧붙였습니다.
  • 해당 글은 ChatGPT Prompt Engineering for Developers의 마지막 강의인 Conclusion까지 듣고 정리한 글입니다.
  • 훌륭한 강의이므로 아래 링크에서 직접 들어보시는 것을 추천드립니다.
 

ChatGPT Prompt Engineering for Developers

What you’ll learn in this course In ChatGPT Prompt Engineering for Developers, you will learn how to use a large language model (LLM) to quickly build new and powerful applications.  Using the OpenAI API, you’ll...

www.deeplearning.ai


Transforming

LLM을 활용하면 번역, 맞춤법 및 문법 교정, HTML 포맷을 JSON 포맷으로 변경하는 등의 작업을 손쉽게 수행할 수 있다.

번역

ChatGPT는 다양한 언어의 텍스트로 학습되었기 때문에 번역을 수행할 수 있다.

아래는 Hi, I would like to order a blender라는 문장을 스페인어와 프랑스어로 번역해달라고 모델에 요청하는 코드이다.

prompt = f"""
Translate the following English text to Spanish \ 
and French: \ 
```Hi, I would like to order a blender```
"""
response = get_completion(prompt)
print(response)
출력:
Spanish: Hola, me gustaría ordenar una licuadora
French: Bonjour, je voudrais commander un mixeur

 

언어 감지

주어진 문장이 어떤 언어로 쓰였는지 판단할 수도 있다.

prompt = f"""
Tell me which language this is: 
```Combien coûte le lampadaire?```
"""
response = get_completion(prompt)
print(response)
출력:
This is French.

 

다중 언어 번역

다양한 언어로 작성된 문장들이 있을 때, 각 문장이 어떤 언어로 쓰였는지 판단하고, 원하는 언어로 번역할 수 있다.

user_messages = [
  "La performance du système est plus lente que d'habitude.",  # System performance is slower than normal         
  "Mi monitor tiene píxeles que no se iluminan.",              # My monitor has pixels that are not lighting
  "Il mio mouse non funziona",                                 # My mouse is not working
  "Mój klawisz Ctrl jest zepsuty",                             # My keyboard has a broken control key
  "我的屏幕在闪烁"                                               # My screen is flashing
]

for issue in user_messages:
    prompt = f"""Tell me what language this is with \
    only one word: ```{issue}```"""
    lang = get_completion(prompt)
    print(f"Original message ({lang}): {issue}")

    prompt = f"""
    Translate the following  text to English \
    and Korean: ```{issue}```
    """
    response = get_completion(prompt)
    print(response, "\n")
출력:
Original message (French.): La performance du système est plus lente que d'habitude.
English: The system performance is slower than usual.
Korean: 시스템 성능이 평소보다 느립니다. 

Original message (Spanish.): Mi monitor tiene píxeles que no se iluminan.
English: My monitor has pixels that don't light up.
Korean: 내 모니터에는 불이 켜지지 않는 픽셀이 있습니다. 

Original message (Italian): Il mio mouse non funziona
English: My mouse is not working.
Korean: 내 마우스가 작동하지 않습니다. 

Original message (Polish): Mój klawisz Ctrl jest zepsuty
English: My Ctrl key is broken.
Korean: 제 Ctrl 키가 고장 났어요. 

Original message (Chinese): 我的屏幕在闪烁
English: My screen is flickering.
Korean: 내 화면이 깜빡입니다.

프랑스어, 스페인어, 이탈리아어, 폴란드어, 중국어 문장을 영어와 한국어로 매끄럽게 번역하는 것을 확인할 수 있다.

 

어조 변환

다양한 상황에 맞는 어조를 갖는 문장을 생성할 수 있다.

prompt = f"""
Translate the following from slang to a business letter: 
'Dude, This is Joe, check out this spec on this standing lamp.'
"""
response = get_completion(prompt)
print(response)
출력:
Dear Sir/Madam,

I am writing to bring to your attention a standing lamp that I believe may be of \
interest to you. Please find attached the specifications for your review.

Thank you for your time and consideration.

Sincerely,

Joe

Dude, This is Joe, check out this spec on this standing lamp.라는 단 한 문장을 비지니스 레터 형식으로 다시 써줄 것을 모델에게 요청한 결과, 격식을 갖춘 긴 글이 생성되었다.

 

포맷 변환

JSON, HTML, XML, Markdown과 같은 포맷들 사이에서 서로 다른 포맷으로 변환할 때 사용할 수 있다.

data_json = { "resturant employees" :[ 
    {"name":"Shyam", "email":"shyamjaiswal@gmail.com"},
    {"name":"Bob", "email":"bob32@gmail.com"},
    {"name":"Jai", "email":"jai87@gmail.com"}
]}

prompt = f"""
Translate the following python dictionary from JSON to an HTML \
table with column headers and title: {data_json}
"""
response = get_completion(prompt)
print(response)
출력:
<table>
  <caption>Restaurant Employees</caption>
  <thead>
    <tr>
      <th>Name</th>
      <th>Email</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Shyam</td>
      <td>shyamjaiswal@gmail.com</td>
    </tr>
    <tr>
      <td>Bob</td>
      <td>bob32@gmail.com</td>
    </tr>
    <tr>
      <td>Jai</td>
      <td>jai87@gmail.com</td>
    </tr>
  </tbody>
</table>

JSON 형식의 데이터를 table을 생성하는 HTML 코드로 변환해주었다.

 

맞춤법 검사 / 문법 검사

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 = get_completion(prompt)
    print(response)
출력:
The girl with the black and white puppies has a ball.
No errors found.
It's going to be a long day. Does the car need its oil changed?
Their goes my freedom. There going to bring they're suitcases.

Corrected version: 
There goes my freedom. They're going to bring their suitcases.
You're going to need your notebook.
That medicine affects my ability to sleep. Have you heard of the butterfly effect?
This phrase is to check ChatGPT for spelling ability.

 

 

Expanding

짧은 텍스트를 정해진 주제에 맞는 긴 텍스트로 늘릴 수 있다.

 

이메일 자동 답장

아래 코드는 이메일 내용에 맞는 답장 내용을 모델에게 생성하도록 요청하는 코드이다.

이메일 내용의 감정 분류는 Inferring 강의에서 다뤘던 내용을 사전에 진행했다고 가정한다.

# given the sentiment from the lesson on "inferring",
# and the original customer message, customize the email
sentiment = "negative"

# review for a blender
review = f"""
So, they still had the 17 piece system on seasonal \
sale for around $49 in the month of November, about \
half off, but for some reason (call it price gouging) \
around the second week of December the prices all went \
up to about anywhere from between $70-$89 for the same \
system. And the 11 piece system went up around $10 or \
so in price also from the earlier sale price of $29. \
So it looks okay, but if you look at the base, the part \
where the blade locks into place doesn’t look as good \
as in previous editions from a few years ago, but I \
plan to be very gentle with it (example, I crush \
very hard items like beans, ice, rice, etc. in the \ 
blender first then pulverize them in the serving size \
I want in the blender then switch to the whipping \
blade for a finer flour, and use the cross cutting blade \
first when making smoothies, then use the flat blade \
if I need them finer/less pulpy). Special tip when making \
smoothies, finely cut and freeze the fruits and \
vegetables (if using spinach-lightly stew soften the \ 
spinach then freeze until ready for use-and if making \
sorbet, use a small to medium sized food processor) \ 
that you plan to use that way you can avoid adding so \
much ice if at all-when making your smoothie. \
After about a year, the motor was making a funny noise. \
I called customer service but the warranty expired \
already, so I had to buy another one. FYI: The overall \
quality has gone done in these types of products, so \
they are kind of counting on brand recognition and \
consumer loyalty to maintain sales. Got it in about \
two days.
"""
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 = get_completion(prompt)
print(response)
출력:
Dear Valued Customer,

Thank you for taking the time to leave a review about our product. We are sorry \
to hear that you experienced an increase in price and that the quality of the \
product did not meet your expectations. We apologize for any inconvenience this \
may have caused you.

We would like to assure you that we take all feedback seriously and we will be \
sure to pass your comments along to our team. If you have any further concerns, \
please do not hesitate to reach out to our customer service team for assistance.

Thank you again for your review and for choosing our product. We hope to have the \
opportunity to serve you better in the future.

Best regards,

AI customer agent

 

Temperature

temperature란, 언어 모델에 주어지는 파라미터로, 모델이 생성하는 답변의 다양성을 조절하는 역할을 한다.

+) temperature 값이 작아질수록 모델은 다음에 등장할 단어를 가장 높은 확률을 가진 단어 위주로 선택하게 되고, temperature 값이 커질수록 모든 단어가 선택될 확률이 비슷해진다.

일반적으로 안정적이고 답변의 범위가 예측 가능해야 하는 어플리케이션에서 LLM을 활용할 때에는 temperature의 값을 0으로 두는 것을 추천한다. 반대로 답변이 창의적이어야 한다면 temperature의 값을 크게 주는 것이 좋다.

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 = get_completion(prompt, temperature=0.7)
print(response)
출력:
Dear valued customer,

Thank you for taking the time to leave a review about our 17 piece system. \
We apologize for any inconvenience caused by the fluctuation in prices. We value \
your feedback and will take it into consideration as we strive to improve our \
pricing strategies.

We are sorry to hear about the issue you experienced with the motor after a year \
of use. Please remember that our customer service team is always available to \
assist you with any concerns you may have, even if the warranty has expired.

Thank you again for your review, and we hope to have the opportunity to serve you \
better in the future.

Best regards,

AI customer agent

temperature의 값을 0.7로 주고 답변을 여러번 생성한 결과, 매번 답변이 달라지는 것을 확인할 수 있다.

 

 

Chatbot

LLM을 활용하여 커스텀 챗봇을 만들어보자.

기존에 gpt-3.5-turbo 모델로부터 답변을 받아왔던 함수 외에 새로운 함수를 추가로 사용한다.

def get_completion(prompt, model="gpt-3.5-turbo"):
    messages = [{"role": "user", "content": prompt}]
    response = openai.ChatCompletion.create(
        model=model,
        messages=messages,
        temperature=0, # this is the degree of randomness of the model's output
    )
    return response.choices[0].message["content"]

def get_completion_from_messages(messages, model="gpt-3.5-turbo", temperature=0):
    response = openai.ChatCompletion.create(
        model=model,
        messages=messages,
        temperature=temperature, # this is the degree of randomness of the model's output
    )
#     print(str(response.choices[0].message))
    return response.choices[0].message["content"]

기존에 사용했던 함수는 get_completion() 함수로, prompt로 입력했던 지시사항을 messages라는 리스트에 dictionary 형태로 넣어 모델에 전달했지만, 새로 추가된 get_completion_from_messages() 함수는 메세지의 리스트를 인자로 받아 여러 메세지를 모델에게 한번에 전달할 수 있다.

아래는 메세지 리스트의 예이다.

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'}  ]

role로 각 메세지의 역할을 지정할 수 있다.

  • system은 모델에게 내리는 지시사항과 관련된 내용의 메세지이다.
  • user는 모델과 대화하는 사용자의 메세지이다.
  • assistant는 모델이 생성한 메세지이다.

response = get_completion_from_messages(messages, temperature=1)
print(response)
출력:
To get to the other side, of course!

주어진 메세지들을 읽고, 맥락에 맞는 답변을 생성했다.

+) **Why did the chicken cross the road?**는 뜬금 없는 질문을 던지고 그냥 반대편으로 넘어가려고 길을 건넜지.. 라는 썰렁한 대답을 하는 미국식 개그라고 한다..

모델에게 위와 같은 방식으로 대화했던 히스토리를 전달해야 대화 상황에 알맞은 답변을 생성해낼 수 있다.

 

def collect_messages(_):
    prompt = inp.value_input
    inp.value = ''
    context.append({'role':'user', 'content':f"{prompt}"})
    response = get_completion_from_messages(context) 
    context.append({'role':'assistant', 'content':f"{response}"})
    panels.append(
        pn.Row('User:', pn.pane.Markdown(prompt, width=600)))
    panels.append(
        pn.Row('Assistant:', pn.pane.Markdown(response, width=600, style={'background-color': '#F6F6F6'})))
 
    return pn.Column(*panels)

collect_messages() 함수는 대화 내용을 모아 모델에 전달하는 함수이다.

import panel as pn  # GUI
pn.extension()

panels = [] # collect display 

context = [ {'role':'system', 'content':"""
You are OrderBot, an automated service to collect orders for a pizza restaurant. \
You first greet the customer, then collects the order, \
and then asks if it's a pickup or delivery. \
You wait to collect the entire order, then summarize it and check for a final \
time if the customer wants to add anything else. \
If it's a delivery, you ask for an address. \
Finally you collect the payment.\
Make sure to clarify all options, extras and sizes to uniquely \
identify the item from the menu.\
You respond in a short, very conversational friendly style. \
The menu includes \
pepperoni pizza  12.95, 10.00, 7.00 \
cheese pizza   10.95, 9.25, 6.50 \
eggplant pizza   11.95, 9.75, 6.75 \
fries 4.50, 3.50 \
greek salad 7.25 \
Toppings: \
extra cheese 2.00, \
mushrooms 1.50 \
sausage 3.00 \
canadian bacon 3.50 \
AI sauce 1.50 \
peppers 1.00 \
Drinks: \
coke 3.00, 2.00, 1.00 \
sprite 3.00, 2.00, 1.00 \
bottled water 5.00 \
"""} ]  # accumulate messages


inp = pn.widgets.TextInput(value="Hi", placeholder='Enter text here…')
button_conversation = pn.widgets.Button(name="Chat!")

interactive_conversation = pn.bind(collect_messages, button_conversation)

dashboard = pn.Column(
    inp,
    pn.Row(button_conversation),
    pn.panel(interactive_conversation, loading_indicator=True, height=300),
)

dashboard

위 코드는 GUI 라이브러리를 활용하여 주문 챗봇을 구현한 코드이다.

결과는 아래와 같다.

아래 코드와 같이 주문 내용을 JSON 형식으로 요약해 달라고 요청할 수도 있다.

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 '},    
)
 #The fields should be 1) pizza, price 2) list of toppings 3) list of drinks, include size include price  4) list of sides include size include price, 5)total price '},    

response = get_completion_from_messages(messages, temperature=0)
print(response)
출력:
Here's a JSON summary of your order:

```
{
  "pizza": {
    "type": "cheese",
    "size": "medium",
    "price": 9.25
  },
  "toppings": [],
  "drinks": [
    {
      "type": "coke",
      "size": "small",
      "price": 1.00
    }
  ],
  "sides": [],
  "total_price": 10.25
}
```