일기 대신 코드 슬쩍

[백엔드][Django][장고 채널스]Section2.영어 상황극 채팅 CLI 애플리케이션 만들기 본문

Backend/Django

[백엔드][Django][장고 채널스]Section2.영어 상황극 채팅 CLI 애플리케이션 만들기

코코자 2023. 7. 24. 15:34
  • 이렇게 변수를 사용할 것임

  • 영어 상황극 채팅 CLI(Command Line Interface) 로 개발
    • ↔ GUI(Graphic User Interface)
    • 투박하고 사용성은 떨어지지만, 최소한의 코드로 유저와 상호작용하는 애플리케이션을 만들 수 있음

def main():
    while line := input("[user]").strip():
        print(line)

if __name__ == "__main__":
    main()
  • 이 코드는 user가 쓴 문자열을 그대로 리턴함

  • 여기에
def gpt_query(user_query:str) -> str:
    "유저 메세지에 대한 응답을 반환합니다."

    return "GPT 응답"
def main():
    while line := input("[user]").strip():
        response = gpt_query(line)
        print(f"[assistant] {response}")

if __name__ == "__main__":
    main()
  • 이 코드는 무슨말을 하던 ‘GPT 응답’을 return함

  • 위 코드에서 gpt_query 함수 안에 OpenAI API를 호출해 gpt응답을 받을 수 있음

import os
import openai

from dotenv import load_dotenv
load_dotenv()

openai.api_key = os.getenv("OPENAI_API_KEY")


# 상황극 설정
language = "English"
gpt_name = "Steve"
level_string = f"a beginner in {language}"
level_word = "simple"
situation_en = "make new friends"
my_role_en = "me"
gpt_role_en = "new friend"


SYSTEM_PROMPT = (
    f"You are helpful assistant supporting people learning {language}. "
    f"Your name is {gpt_name}. Please assume that the user you are assisting "
    f"is {level_string}. And please write only the sentence without "
    f"the character role."
)

USER_PROMPT = (
    f"Let's have a conversation in {language}. Please answer in {language} only "
    f"without providing a translation. And please don't write down the "
    f"pronunciation either. Let us assume that the situation in '{situation_en}'. "
    f"I am {my_role_en}. The character I want you to act as is {gpt_role_en}. "
    f"Please make sure that "
    f"I'm {level_string}, so please use {level_word} words as much as possible. "
    f"Now, start a conversation with the first sentence!"
)


messages = [
    {"role": "system", "content": SYSTEM_PROMPT},
]


def gpt_query(user_query: str) -> str:
    "유저 메세지에 대한 응답을 반환합니다."

    global messages

    messages.append({
        "role": "user",
        "content": user_query,
    })

    response = openai.ChatCompletion.create(
        model="gpt-3.5-turbo",
        messages=messages,
    )
    assistant_message = response["choices"][0]["message"]["content"]

    messages.append({
        "role": "assistant",
        "content": assistant_message,
    })

    return assistant_message


def main():
    assistant_message = gpt_query(USER_PROMPT)
    print(f"[assistant] {assistant_message}")

    while line := input("[user] ").strip():
        response = gpt_query(line)
        print(f"[assistant] {response}")


if __name__ == "__main__":
    main()
  • 완성한 cli.py
  • 다음과 같이 대화 가능

  • 명령행에서 최근 메세지를 음성으로 읽어주는 기능을 추가해보자.
  • TTS: 텍스트 문자열을 음성으로 생성하는 기능
  • gTTS를 이용할 것임(크롤링해서 음성파일로 다운로드 받을 수 있는 라이브러리)
  • pygame도 사용할 것임(2D 게임 라이브러리로 오디오 재생과 같은 멀티미디어 기능)
import os
from io import BytesIO
from tempfile import NamedTemporaryFile

import openai
import pygame

from dotenv import load_dotenv
from gtts import gTTS

load_dotenv()

openai.api_key = os.getenv("OPENAI_API_KEY")
# 상황극 설정
language = "English"
gpt_name = "Steve"
level_string = f"a beginner in {language}"
level_word = "simple"
situation_en = "make new friends"
my_role_en = "me"
gpt_role_en = "new friend"
SYSTEM_PROMPT = (
    f"You are helpful assistant supporting people learning {language}. "
    f"Your name is {gpt_name}. Please assume that the user you are assisting "
    f"is {level_string}. And please write only the sentence without "
    f"the character role."
)
USER_PROMPT = (
    f"Let's have a conversation in {language}. Please answer in {language} only "
    f"without providing a translation. And please don't write down the "
    f"pronunciation either. Let us assume that the situation in '{situation_en}'. "
    f"I am {my_role_en}. The character I want you to act as is {gpt_role_en}. "
    f"Please make sure that "
    f"I'm {level_string}, so please use {level_word} words as much as possible. "
    f"Now, start a conversation with the first sentence!"
)
messages = [
    {"role": "system", "content": SYSTEM_PROMPT},
]
def gpt_query(user_query: str) -> str:
    "유저 메세지에 대한 응답을 반환합니다."
    global messages
    messages.append({
        "role": "user",
        "content": user_query,
    })
    response = openai.ChatCompletion.create(
        model="gpt-3.5-turbo",
        messages=messages,
    )
    assistant_message = response["choices"][0]["message"]["content"]
    messages.append({
        "role": "assistant",
        "content": assistant_message,
    })
    return assistant_message


def play_file(file_path: str) -> None:
    pygame.mixer.init()
    pygame.mixer.music.load(file_path)
    pygame.mixer.music.play()

    while pygame.mixer.music.get_busy():
        pass

    pygame.mixer.quit()


def say(message: str, lang: str) -> None:
    io = BytesIO()

    gTTS(message, lang=lang).write_to_fp(io)

    with NamedTemporaryFile(delete=False) as f:  # 자동 삭제되지 않도록 delete=False 인자를 지정
        f.write(io.getvalue())
        f.close()

        play_file(f.name)

        os.remove(f.name)  # 수동으로 파일을 삭제합니다.

def main():
    assistant_message = gpt_query(USER_PROMPT)
    print(f"[assistant] {assistant_message}")

    while line := input("[user] ").strip():
        if line == "!say":
            say(messages[-1]["content"], "en")
        else:
            response = gpt_query(line)
            print(f"[assistant] {response}")


if __name__ == "__main__":
    main()
  • cli.py다음과 같이 작성하고, 명령해서 !say입력하면 음성 나옴

  • 명령행에서 표현 추천받기
  • !recommand 를 입력하면 표현을 추천하게 구현
import os
from io import BytesIO
from tempfile import NamedTemporaryFile

import openai
import pygame

from dotenv import load_dotenv
from gtts import gTTS

load_dotenv()

openai.api_key = os.getenv("OPENAI_API_KEY")
# 상황극 설정
language = "English"
gpt_name = "Steve"
level_string = f"a beginner in {language}"
level_word = "simple"
situation_en = "make new friends"
my_role_en = "me"
gpt_role_en = "new friend"
SYSTEM_PROMPT = (
    f"You are helpful assistant supporting people learning {language}. "
    f"Your name is {gpt_name}. Please assume that the user you are assisting "
    f"is {level_string}. And please write only the sentence without "
    f"the character role."
)
USER_PROMPT = (
    f"Let's have a conversation in {language}. Please answer in {language} only "
    f"without providing a translation. And please don't write down the "
    f"pronunciation either. Let us assume that the situation in '{situation_en}'. "
    f"I am {my_role_en}. The character I want you to act as is {gpt_role_en}. "
    f"Please make sure that "
    f"I'm {level_string}, so please use {level_word} words as much as possible. "
    f"Now, start a conversation with the first sentence!"
)

RECOMMEND_PROMPT = (
    f"Can you please provide me an {level_word} example "
    f"of how to respond to the last sentence "
    f"in this situation, without providing a translation "
    f"and any introductory phrases or sentences."
)

messages = [
    {"role": "system", "content": SYSTEM_PROMPT},
]
def gpt_query(user_query: str, skip_save: bool = False) -> str:
    "유저 메세지에 대한 응답을 반환합니다."
    global messages
    messages.append({
        "role": "user",
        "content": user_query,
    })
    response = openai.ChatCompletion.create(
        model="gpt-3.5-turbo",
        messages=messages,
    )
    assistant_message = response["choices"][0]["message"]["content"]
    if skip_save is False:
        messages.append({
            "role": "assistant",
            "content": assistant_message,
        })
    return assistant_message


def play_file(file_path: str) -> None:
    pygame.mixer.init()
    pygame.mixer.music.load(file_path)
    pygame.mixer.music.play()

    while pygame.mixer.music.get_busy():
        pass

    pygame.mixer.quit()


def say(message: str, lang: str) -> None:
    io = BytesIO()

    gTTS(message, lang=lang).write_to_fp(io)

    with NamedTemporaryFile(delete=False) as f:  # 자동 삭제되지 않도록 delete=False 인자를 지정
        f.write(io.getvalue())
        f.close()

        play_file(f.name)

        os.remove(f.name)  # 수동으로 파일을 삭제합니다.

def main():
    assistant_message = gpt_query(USER_PROMPT)
    print(f"[assistant] {assistant_message}")

    while line := input("[user] ").strip():
        if line == "!recommend":
            recommended_message = gpt_query(RECOMMEND_PROMPT, skip_save=True)
            print("추천 표현: ", recommended_message)
        elif line == "!say":
            say(messages[-1]["content"], "en")
        else:
            response = gpt_query(line)
            print(f"[assistant] {response}")


if __name__ == "__main__":
    main()


  • 명령행에서 assistant 메세지를 자동으로 읽어주기
import os
from io import BytesIO
from tempfile import NamedTemporaryFile

import openai
import pygame

from dotenv import load_dotenv
from gtts import gTTS

load_dotenv()

openai.api_key = os.getenv("OPENAI_API_KEY")
# 상황극 설정
language = "English"
gpt_name = "Steve"
level_string = f"a beginner in {language}"
level_word = "simple"
situation_en = "make new friends"
my_role_en = "me"
gpt_role_en = "new friend"
SYSTEM_PROMPT = (
    f"You are helpful assistant supporting people learning {language}. "
    f"Your name is {gpt_name}. Please assume that the user you are assisting "
    f"is {level_string}. And please write only the sentence without "
    f"the character role."
)
USER_PROMPT = (
    f"Let's have a conversation in {language}. Please answer in {language} only "
    f"without providing a translation. And please don't write down the "
    f"pronunciation either. Let us assume that the situation in '{situation_en}'. "
    f"I am {my_role_en}. The character I want you to act as is {gpt_role_en}. "
    f"Please make sure that "
    f"I'm {level_string}, so please use {level_word} words as much as possible. "
    f"Now, start a conversation with the first sentence!"
)

RECOMMEND_PROMPT = (
    f"Can you please provide me an {level_word} example "
    f"of how to respond to the last sentence "
    f"in this situation, without providing a translation "
    f"and any introductory phrases or sentences."
)

messages = [
    {"role": "system", "content": SYSTEM_PROMPT},
]
def gpt_query(user_query: str, skip_save: bool = False) -> str:
    "유저 메세지에 대한 응답을 반환합니다."
    global messages
    messages.append({
        "role": "user",
        "content": user_query,
    })
    response = openai.ChatCompletion.create(
        model="gpt-3.5-turbo",
        messages=messages,
    )
    assistant_message = response["choices"][0]["message"]["content"]
    if skip_save is False:
        messages.append({
            "role": "assistant",
            "content": assistant_message,
        })
    return assistant_message


def play_file(file_path: str) -> None:
    pygame.mixer.init()
    pygame.mixer.music.load(file_path)
    pygame.mixer.music.play()

    while pygame.mixer.music.get_busy():
        pass

    pygame.mixer.quit()


def say(message: str, lang: str) -> None:
    io = BytesIO()

    gTTS(message, lang=lang).write_to_fp(io)

    with NamedTemporaryFile(delete=False) as f:  # 자동 삭제되지 않도록 delete=False 인자를 지정
        f.write(io.getvalue())
        f.close()

        play_file(f.name)

        os.remove(f.name)  # 수동으로 파일을 삭제합니다.

def main():
    assistant_message = gpt_query(USER_PROMPT)
    print(f"[assistant] {assistant_message}")
    say(assistant_message, "en")

    while line := input("[user] ").strip():
        if line == "!recommend":
            recommended_message = gpt_query(RECOMMEND_PROMPT, skip_save=True)
            print("추천 표현: ", recommended_message)
        elif line == "!say":
            say(messages[-1]["content"], "en")
        else:
            response = gpt_query(line)
            print(f"[assistant] {response}")
            say(response, "en")

if __name__ == "__main__":
    main()