BigData

chatGPT 와 채팅의 연결

IT오이시이 2023. 10. 13. 05:27
728x90

chatGPT 와 채팅의 연결

 

chatGPT API를 이용하여 학습된 상품 정보에 대한 질문과 답변을 할 수 있는 간단한 채팅화면을 연결하는 방법을 정리 합니다.

 

1. chatGPT API연결

import os
import openai
import sys
import utils

import panel as pn  # application GUI 
pn.extension()

openai.api_key  = os.environ['OPENAI_API_KEY']

* pakage panel 패키지는 Python에서 대화형 대시보드 및 웹 애플리케이션을 만들기 위한 도구입니다.

 

2. 사용할 학습 모델의 정의

 한글고 응답을 하므로 영어보다 길게 설정 필요하여  max_tokens=1000으로 조정함

def get_completion_from_messages(messages, model="gpt-3.5-turbo", temperature=0, max_tokens=1000):
    response = openai.ChatCompletion.create(
        model=model,
        messages=messages,
        temperature=temperature, 
        max_tokens=max_tokens, 
    )
    return response.choices[0].message["content"]

 

 

3. API응답 메세지 프로세스  정의

응답을 한국어로 인식하기 위해서 다음과 같은 내용을 추가 합니다.

  1. 응답에 이용할 Product Category 정보를 한글로 번역을 하여 저장을 하였고 

  2. 응답 메시지 조건으로 한국어로 답변하라는 내용으로 수정 하였다.

    system_message = f"""
    반드시 응답은 한국어로: ~~~
    """

 다음과 같은 순서로 프로그램을 구현합니다.

Step 1: Input passed moderation check.
Step 2: Extracted list of products.
Step 3: Looked up product information.
Step 4: Generated response to user question.
Step 5: Response passed moderation check.
Step 6: Model evaluated the response.
Step 7: Model approved the response.

 

 

def process_user_message(user_input, all_messages, debug=True):
    delimiter = "```"
    
    # ****************************************
    # Step 1: Check input to see if it flags the Moderation API or is a prompt injection
    # ****************************************
    response = openai.Moderation.create(input=user_input)
    moderation_output = response["results"][0]

    if moderation_output["flagged"]:
        print("Step 1: Input flagged by Moderation API.")
        return "Sorry, we cannot process this request."

    if debug: print("Step 1: Input passed moderation check.")
        
    products_and_category_ko={
  "컴퓨터 및 노트북": ["TechPro 울트라북", "BlueWave 게이밍 노트북", "PowerLite 컨버터블", "TechPro 데스크탑", "BlueWave 크롬북"],
  "스마트폰 및 액세서리": ["SmartX ProPhone", "MobiTech 파워케이스", "SmartX 미니폰", "MobiTech 무선 충전기", "SmartX 이어버드"],
  "텔레비전 및 홈 시어터 시스템": ["CineView 4K TV", "SoundMax 홈 시어터", "CineView 8K TV", "SoundMax 사운드바", "CineView OLED TV"],
  "게임 콘솔 및 액세서리": ["GameSphere X", "ProGamer 컨트롤러", "GameSphere Y", "ProGamer 레이싱 휠", "GameSphere VR 헤드셋" ],
  "오디오 장비": [ "AudioPhonic 소음 차단 헤드폰", "WaveSound 블루투스 스피커", "AudioPhonic 트루 와이어리스 이어버드", "WaveSound 사운드바", "AudioPhonic 턴테이블" ],
  "카메라 및 캠코더": ["FotoSnap DSLR 카메라", "ActionCam 4K", "FotoSnap 미러리스 카메라","ZoomMaster 캠코더", "FotoSnap 인스턴트 카메라" ]}
    
    #* category_and_product_response = utils.find_category_and_product_only(user_input, utils.get_products_and_category())
    category_and_product_response = utils.find_category_and_product_only(user_input, products_and_category_ko)
    #print(print(category_and_product_response)
    
    
    # ****************************************
    # Step 2: Extract the list of products
    # ****************************************
    category_and_product_list = utils.read_string_to_list(category_and_product_response)
    #print(category_and_product_list)

    if debug: print("Step 2: Extracted list of products.")


    # ****************************************
    # Step 3: If products are found, look them up
    # ****************************************
    product_information = utils.generate_output_string(category_and_product_list)
    if debug: print("Step 3: Looked up product information.")


    # ****************************************
    # Step 4: Answer the user question
    # ****************************************
    #system_message = f"""
    # You are a customer service assistant for a large electronic store. \
    # Respond in a friendly and helpful tone, with concise answers. \
    # Make sure to ask the user relevant follow-up questions.
    #"""
    system_message = f"""
    반드시 응답은 한국어로:
    안녕하세요! 여러분을 대상으로 하는 대형 전자제품 매장의 고객 서비스 어시스턴트입니다. 친근하고 도움이 되는 톤으로 응답하며 간결한 답변을 제공하겠습니다. 사용자에게 관련성 있는 후속 질문을 꼭 하시기 바랍니다.
    """
    
    messages = [
        {'role': 'system', 'content': system_message},
        {'role': 'user', 'content': f"{delimiter}{user_input}{delimiter}"},
        {'role': 'assistant', 'content': f"Relevant product information:\n{product_information}"}
    ]

    final_response = get_completion_from_messages(all_messages + messages)
    if debug:print("Step 4: Generated response to user question.")
    all_messages = all_messages + messages[1:]

    # ****************************************
    # Step 5: Put the answer through the Moderation API
    # ****************************************
    response = openai.Moderation.create(input=final_response)
    moderation_output = response["results"][0]

    if moderation_output["flagged"]:
        if debug: print("Step 5: Response flagged by Moderation API.")
        return "Sorry, we cannot provide this information."

    if debug: print("Step 5: Response passed moderation check.")


    # ****************************************
    # Step 6: Ask the model if the response answers the initial user query well
    # ****************************************
    user_message = f"""
    Customer message: {delimiter}{user_input}{delimiter}
    Agent response: {delimiter}{final_response}{delimiter}

    Does the response sufficiently answer the question?
    """
    messages = [
        {'role': 'system', 'content': system_message},
        {'role': 'user', 'content': user_message}
    ]
    evaluation_response = get_completion_from_messages(messages)
    if debug: print("Step 6: Model evaluated the response.")



    # ****************************************
    # Step 7: If yes, use this answer; if not, say that you will connect the user to a human
    # ****************************************
    if "Y" in evaluation_response:  # Using "in" instead of "==" to be safer for model output variation (e.g., "Y." or "Yes")
        if debug: print("Step 7: Model approved the response. as korean")
        return final_response, all_messages
    else:
        if debug: print("Step 7: Model disapproved the response.")
        #* neg_str = "I'm unable to provide the information you're looking for. I'll connect you with a human representative for further assistance."
        neg_str = "죄송합니다. 원하시는 정보를 제공할 수 없습니다. 추가 지원이 필요하시면 인간 대표와 연결해 드리겠습니다."
        return neg_str, all_messages

user_input = "tell me about the smartx pro phone and the fotosnap camera, the dslr one. Also what tell me about your tvs"
response,_ = process_user_message(user_input,[])
print(response)

 

Step 7: Model approved the response. as korean
SmartX ProPhone은 SmartX 브랜드의 강력한 스마트폰으로, 6.1인치 디스플레이, 128GB 저장 용량, 12MP 듀얼 카메라, 5G 지원 등의 특징을 가지고 있습니다. 가격은 899.99달러이며 1년 보증이 제공됩니다. FotoSnap DSLR 카메라는 FotoSnap 브랜드의 다목적 DSLR 카메라로, 24.2MP 센서, 1080p 비디오, 3인치 LCD, 교환 가능한 렌즈 등의 특징을 가지고 있습니다. 가격은 599.99달러이며 1년 보증이 제공됩니다.
저희 매장의 TV 제품군에는 CineView 4K TV, CineView 8K TV, CineView OLED TV 등이 있습니다. CineView 4K TV는 55인치 디스플레이, 4K 해상도, HDR, 스마트 TV 기능을 제공하며 가격은 599.99달러이고 2년 보증이 제공됩니다.
CineView 8K TV는 65인치 디스플레이, 8K 해상도, HDR, 스마트 TV 기능을 제공하며 가격은 2999.99달러이고 2년 보증이 제공됩니다. CineView OLED TV는 55인치 디스플레이, 4K 해상도, HDR, 스마트 TV 기능을 제공하며 가격은 1499.99달러이고 2년 보증이 제공됩니다. 또한, SoundMax Home Theater와 SoundMax Soundbar도 제공하고 있습니다. SoundMax Home Theater는 5.1 채널, 1000W 출력, 무선 서브우퍼, 블루투스 기능을 제공하며 가격은 399.99달러이고 1년 보증이 제공됩니다. SoundMax Soundbar는 2.1 채널, 300W 출력, 무선 서브우퍼, 블루투스 기능을 제공하며 가격은 199.99달러이고 1년 보증이 제공됩니다.
더 궁금한 사항이 있으신가요?

 

 

4. 대화 흐름에 따라 사용자 및 어시스턴트 메시지를 수집하는 함수

def collect_messages(debug=False):
    user_input = inp.value_input
    if debug: print(f"User Input = {user_input}")
    if user_input == "":
        return
    inp.value = ''
    global context
    #response, context = process_user_message(user_input, context, utils.get_products_and_category(),debug=True)
    response, context = process_user_message(user_input, context, debug=False)
    context.append({'role':'assistant', 'content':f"{response}"})
    panels.append(
        pn.Row('User:', pn.pane.Markdown(user_input, width=600)))
    panels.append(
        pn.Row('Assistant:', pn.pane.Markdown(response, width=600, style={'background-color': '#F6F6F6'})))
 
    return pn.Column(*panels)

 

 

5. panel패키지를 이용하여 챗봇 입력과 출력 화면을 구현

    채팅화면의 버튼과 "collect_messages()" 를 바인드하여 채팅 메시지를 처리합니다.

panels = [] # collect display 

context = [ {'role':'system', 'content':"You are Service Assistant"} ]  

inp = pn.widgets.TextInput( placeholder='Enter text here…')
button_conversation = pn.widgets.Button(name="Service Assistant")

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

[참고]

Building Systems with the ChatGPT API 
 - https://learn.deeplearning.ai/chatgpt-building-system/lesson/8/evaluation

728x90
반응형