LLM Series | 08: How to build an ordering robot with ChatGPT?

Introduction

The wind is hunting the small pond, the lotus is full of fragrance after the rain, and the sinking and floating melons are cold in ice and snow. Hello friends, I am the editor of the WeChat public account "Xiao Chuang You Ji Machine Learning": the little boy who sells Tieguanyin.
For more and updated articles, please pay attention to the WeChat public account: Xiaochuang Youji Machine Learning . Follow-up will continue to organize a series of topics such as model acceleration, model deployment, model compression, LLM, AI art, etc. , so stay tuned.

Immediately after the previous ChatGPT Prompt engineering series articles: 04: ChatGPT Prompt writing guide , 05: How to optimize ChatGPT Prompt? , 06: ChatGPT Prompt Practice: Text Summary & Inference & Conversion , 07: Ng Enda ChatGPT Prompt Course Practice: Taking Smart Customer Service Email as an Example . Today's small essay is the fifth note of the course "ChatGPT Prompt Engineering for Developers" co-course between Ng Enda and OpenAI. It mainly introduces how to use ChatGPT to build a customized chat robot and ordering robot .

From this, we can feel that using a large language model LLM to build a custom chatbot really requires very little work.

Preparation

set API key

import os
import openai

openai.api_key  = "sk-xxx" 

# 如果需要设置代理的话
import os
os.environ['HTTP_PROXY'] = "http://XXX"
os.environ['HTTPS_PROXY'] = "http://XXX"

define helper functions

Chat models like ChatGPT are actually assembled to take a sequence of messages as input and return a model-generated message as output. While the chat format is designed to facilitate this kind of multi-turn dialogue, we know from previous studies that it is equally useful for single-turn tasks without any dialogue.

Next, we'll define two helper functions. The first one is a single round where we put the prompt in what looks like some kind of user message. The other takes a list of messages. These messages can come from different roles, which we describe.

The first message is a system message which gives a general indication, then after this message we have the alternation between user and assistant. If you've ever used the ChatGPT web interface, your messages are user messages, while ChatGPT's messages are assistant messages. System messages help set up the Assistant's behavior and role, and serve as high-level instructions for conversations. You can imagine it whispering in the assistant's ear, directing its responses without the user noticing the system message.

Therefore, as a user, if you have ever used ChatGPT, you may not know what ChatGPT's system messages are, and this is intentional. The benefit of system messages is that they provide a way for developers to guide the Assistant and direct its responses without making the request itself part of the conversation.

def get_completion(prompt, model="gpt-3.5-turbo"):
    messages = [{"role": "user", "content": prompt}]
    response = openai.ChatCompletion.create(
        model=model,
        messages=messages,
        temperature=0, # 控制模型输出的随机程度
    )
    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, # 控制模型输出的随机程度
    )
#     print(str(response.choices[0].message))
    return response.choices[0].message["content"]

chat

Try using these messages in a conversation now. We'll use the above function to get the answers from these messages, and at the same time, use a higher temperature (the higher the result, the more varied the results).

The system is contentset up so that you are an assistant who talks like Shakespeare. This is the way we describe to the assistant how it should behave. Then, the first user message is, tell me a joke. The next news is, why did the chicken cross the road? Then the last user message was, I don't know.

English version:

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 = get_completion_from_messages(messages, temperature=1)
print(response)

The output is as follows:

To reach the other side, my dear lord.

Chinese Version:

因为它想到对面的鸡店吃炸鸡!哈哈哈! :)

The Chinese version is replaced with a "Lu Xun" style assistant:

# 中文
messages =  [  
{'role':'system', 'content':'你是一个像鲁迅一样说话的助手。'},    
{'role':'user', 'content':'给我讲个笑话'},   
{'role':'assistant', 'content':'鸡为什么过马路'},   
{'role':'user', 'content':'我不知道'}  ]

The output is as follows:

因为它要到对面去“鸡”客店呀!哈哈哈

Give another example. The message set to the assistant was, "You're a friendly chatbot," and the first user message was, "Hi, my name is Johnny." We want to get the first user message.

# 中文
messages =  [  
{'role':'system', 'content':'你是个友好的聊天机器人。'},    
{'role':'user', 'content':'Hi, 我是张三。'}  ]
response = get_completion_from_messages(messages, temperature=1)
print(response)

The output is as follows:

你好张三!我很高兴能和你聊天。有什么我可以帮助你的吗?

Try another example. The message set to the system was, "You're a friendly chatbot," and the first user message was, "Yes, can you remind me what my name is?"

# 中文
messages =  [  
{'role':'system', 'content':'你是个友好的聊天机器人。'},    
{'role':'user', 'content':'好,你能提醒我,我的名字是什么吗?'}  ]
response = get_completion_from_messages(messages, temperature=1)
print(response)

The output is as follows:

您没有告诉我您的名字,因此我不知道您的名字是什么。您可以告诉我您的名字,以便我们以后更方便地交流。

As you can see above, the model doesn't actually know my name.

Therefore, each interaction with the language model is an independent interaction, which means that we must provide all relevant messages for the model to refer to in the current dialogue. If you want your model to reference or "remember" earlier parts of the conversation, you must provide earlier exchanges in the model's input. Let's call it context, let's try it.

# 中文
messages =  [  
{'role':'system', 'content':'你是个友好的聊天机器人。'},
{'role':'user', 'content':'Hi, 我是张三'},
{'role':'assistant', 'content': "Hi Isa! 很高兴认识你。今天有什么可以帮到你的吗?"},
{'role':'user', 'content':'是的,你可以提醒我, 我的名字是什么?'}  ]
response = get_completion_from_messages(messages, temperature=1)
print(response)

The output is as follows:

当然,您告诉我您的名字是张三。记得了吗?

Now that we have given context to the model, which is my name mentioned in the previous conversation, we will then ask the same question, which is what is my name. Because the model has all the context it needs, it is able to respond as we see it in the list of incoming messages.

ordering robot

Now, let's build a "ordering robot", we need it to automatically collect user information and accept orders from pizzerias.

The function below will collect our user messages so we can avoid typing them manually like we did just above. This function will collect hints from the UI we build below, then append them to a list called context, and use that context each time the model is called. The model's responses are also added to the context, so both model messages and user messages are added to the context, so the context grows progressively longer. This way, the model has the information it needs to determine what to do next.

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)

Now, we'll set up and run the UI to display the order bot. The initial context contains system messages containing menus. Note that the context grows over time.

pip3 install panel

Now we can ask the model to create a JSON digest to send to the order system.

So we now append another system message, it's another prompt, we say create a JSON summary of the order we just ordered, listing the price of each item, the fields should include 1) pizza, including dimensions, 2) list of toppings, 3) A list of drinks, 4) a list of side dishes, including sizes, and finally the total price. User messages can also be used here, not necessarily system messages.

Note that here we use a lower temperature because for these types of tasks we want the output to be relatively predictable.

# 中文
import panel as pn  # GUI
pn.extension()

panels = [] # collect display 

context = [{'role':'system', 'content':"""
你是订餐机器人,为披萨餐厅自动收集订单信息。
你要首先问候顾客。然后等待用户回复收集订单信息。收集完信息需确认顾客是否还需要添加其他内容。
最后需要询问是否自取或外送,如果是外送,你要询问地址。
最后告诉顾客订单总金额,并送上祝福。

请确保明确所有选项、附加项和尺寸,以便从菜单中识别出该项唯一的内容。
你的回应应该以简短、非常随意和友好的风格呈现。

菜单包括:

菜品:
意式辣香肠披萨(大、中、小) 12.95、10.00、7.00
芝士披萨(大、中、小) 10.95、9.25、6.50
茄子披萨(大、中、小) 11.95、9.75、6.75
薯条(大、小) 4.50、3.50
希腊沙拉 7.25

配料:
奶酪 2.00
蘑菇 1.50
香肠 3.00
加拿大熏肉 3.50
AI酱 1.50
辣椒 1.00

饮料:
可乐(大、中、小) 3.00、2.00、1.00
雪碧(大、中、小) 3.00、2.00、1.00
瓶装水 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),
)

The chat results are as follows:

insert image description here

A summary of the above chat results:

messages =  context.copy()
messages.append(
{'role':'system', 'content':'创建上一个食品订单的 json 摘要。\
逐项列出每件商品的价格,字段应该是 1) 披萨,包括大小 2) 配料列表 3) 饮料列表,包括大小 4) 配菜列表包括大小 5) 总价'},    
)

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

The output is as follows:

以下是上一个食品订单的 JSON 摘要:

{
  "披萨": {
    "意式辣香肠披萨": {
      "大小": "大",
      "价格": 12.95
    }
  },
  "配料列表": {
    "AI酱": 1.5,
    "香肠": 3.0,
    "总价": 4.5
  },
  "饮料列表": {
    "瓶装水": {
      "大小": "标准",
      "价格": 5.0
    }
  },
  "配菜列表": {},
  "总价": 22.45
}

注意,配菜列表为空,因为在上一个订单中没有点配菜。

It can be seen that although the above ordering robot can communicate smoothly, there are still significant defects in mathematical calculations. Next we optimize again.

Optimizing the ordering robot

Modify the prompt as follows:

import panel as pn  # GUI
pn.extension()

panels = [] # collect display 

context = [{'role':'system', 'content':"""
你是订餐机器人,为可达鸭餐厅自动收集订单信息。
你要首先问候顾客。然后等待用户回复收集订单信息,包括餐品和数量。如果用户没有说数量,你要问下。
收集完信息需确认顾客是否还需要添加其他内容。
最后需要询问是否自取或外送,如果是外送,你要询问地址并告诉用户配送费是8块。
最后告诉顾客订单总金额,并送上祝福。

请确保明确所有选项、附加项和尺寸,以便从菜单中识别出该项唯一的内容。
你的回应应该以简短、非常随意和友好的风格呈现。

菜单包括:

主食:
鸡排堡(大、中、小) 12.95、10.00、7.00
鸡腿堡(大、中、小) 10.95、9.25、6.50
嫩牛堡(大、中、小) 19.95、15.75、10.75
鸡肉卷(大、中、小) 11.95、9.75、6.75

小食:
薯条(大、小) 4.50、3.50
希腊沙拉 7.25
香肠 3.00
加拿大熏肉 3.50

配料:
奶酪 2.00
蘑菇 1.50
AI酱 1.50
辣椒 1.00

饮料:
可乐(大、中、小) 3.00、2.00、1.00
雪碧(大、中、小) 3.00、2.00、1.00
农夫山贼矿泉水 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),
)

Execute dashboard, the result is as follows:

insert image description here

Summarize the above chat content:

messages =  context.copy()
messages.append(
{'role':'system', 'content':'创建上一个食品订单的 json 摘要。\
逐项列出用户订餐的每件商品的详情,包括大小、数量和消费金额。字段应该是 1) 主食 2) 小食 3) 配料 4) 饮料 5) 总价'},    
)

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

The output is as follows:

{
    "主食": {
        "嫩牛堡": {
            "大小": "大份",
            "数量": 1,
            "消费金额": 19.95
        }
    },
    "小食": {
        "香肠": {
            "数量": 2,
            "消费金额": 6.00
        }
    },
    "配料": {
        "AI酱": {
            "数量": 1,
            "消费金额": 1.50
        }
    },
    "饮料": {
        "农夫山贼矿泉水": {
            "数量": 2,
            "消费金额": 10.00
        }
    },
    "总价": 45.45
}

At this point, get the correct order content and amount.

Summarize

A summary of this course follows. Overall, in this course, two key principles about prompts have been learned:

  • Write clear and specific instructions
  • Give the model some time to think

also,

  1. You also learned how to iteratively develop prompts. Knowing how to find the right process for your application prompt is critical.

  2. Many features of LLMs, including summarization, inference, transformation, and text expansion, are also introduced.

  3. Finally, the course provides examples of how to build a custom chatbot.

Large-scale language models LLM are very powerful. I hope everyone will maintain their original intentions and use them responsibly. Please only build things that have a positive impact on others and conform to the core values ​​​​of socialism.

Guess you like

Origin blog.csdn.net/ljp1919/article/details/131159830