반응형

Pynecone Gallery에 보면 시계, Chart, Todo List, GPT 등 많은 예제를 소개하고 있습니다. 그 중에서 Chat completion API를 이용하여 이미지를 생성 App을 만들어 보겠습니다. (Example Code는 Github에서 확인 가능합니다.)


1. OpenAI API 키 발급

먼저 OpenAI API를 사용하기 위해 API 키 발급이 필요합니다. 먼저 OpenAI API 사이트로 이동합니다. OpenAI 계정이 필요하며 계정이 없다면 계정 생성이 필요합니다. 간단히 Google이나 Microsoft 계정을 연동 할 수 있습니다. 이미 계정이 있다면 로그인 후 진행하시면 됩니다.

 

OpenAI API

An API for accessing new AI models developed by OpenAI

platform.openai.com

로그인이 되었다면 우측 상단 Personal -> [ View API Keys ] 를 클릭합니다.

[ + Create new secret key ] 를 클릭하여 API Key를 생성합니다. API key generated 창이 활성화되면 Key 를 반드시 복사하여 두시기 바랍니다. 창을 닫으면 다시 확인할 수 없습니다. (만약 복사하지 못했다면 다시 Create new secret key 버튼을 눌러 생성하면 되니 걱정하지 않으셔도 됩니다.)

2. Installation

pip install --upgrade openai
더보기
더보기

설치 후 command 창에서 openai 명령어를 입력하면 아래와 같이 출력되어야 정상적으로 설치가 된 것 입니다.

3. Create a Project

dalle 라는 directory를 만들고 gpt.py 파일과 helpers.py 파일을 추가했습니다.

getting_started_with_pynecone
├── .web
├── assets
├── getting_started_with_pynecone
│   ├── __init__.py
│   └── getting_started_with_pynecone.py
├── gpt                       # 추가
│   ├── __init__.py           # 추가
│   └── gpt.py                # 추가
│   └── helpers.py            # 추가
└── pcconfig.py

gpt.py 파일을 아래와 같이 수정합니다. openai.api_key 값은 위 OpenAI 에서 발급 받은 API  KEY 값으로 입력합니다.

"""Welcome to Pynecone! This app is a demonstration of OpenAI's GPT."""
import pynecone as pc
from .helpers import navbar
import openai
import datetime

# OpenAI에서 발급 받은 API KEY를 입력
openai.api_key = "YOUR_API_KEY"
MAX_QUESTIONS = 10


class User(pc.Model, table=True):
    """A table for users in the database."""

    username: str
    password: str


class Question(pc.Model, table=True):
    """A table for questions and answers in the database."""

    username: str
    prompt: str
    answer: str
    timestamp: datetime.datetime = datetime.datetime.now()


class State(pc.State):
    """The app state."""

    username: str = ""
    password: str = ""
    logged_in: bool = False

    prompt: str = ""
    result: str = ""

    @pc.var
    def questions(self) -> list[Question]:
        """Get the users saved questions and answers from the database."""
        with pc.session() as session:
            if self.logged_in:
                qa = (
                    session.query(Question)
                    .where(Question.username == self.username)
                    .distinct(Question.prompt)
                    .order_by(Question.timestamp.desc())
                    .limit(MAX_QUESTIONS)
                    .all()
                )
                return [[q.prompt, q.answer] for q in qa]
            else:
                return []

    def login(self):
        with pc.session() as session:
            user = session.query(User).where(User.username == self.username).first()
            if (user and user.password == self.password) or self.username == "admin":
                self.logged_in = True
                return pc.redirect("/home")
            else:
                return pc.window_alert("Invalid username or password.")

    def logout(self):
        self.reset()
        return pc.redirect("/")

    def signup(self):
        with pc.session() as session:
            user = User(username=self.username, password=self.password)
            session.add(user)
            session.commit()
        self.logged_in = True
        return pc.redirect("/home")

    def get_result(self):
        if (
            pc.session()
            .query(Question)
            .where(Question.username == self.username)
            .where(Question.prompt == self.prompt)
            .first()
            or pc.session()
            .query(Question)
            .where(Question.username == self.username)
            .where(
                Question.timestamp
                > datetime.datetime.now() - datetime.timedelta(days=1)
            )
            .count()
            > MAX_QUESTIONS
        ):
            return pc.window_alert(
                "You have already asked this question or have asked too many questions in the past 24 hours."
            )
        try:
            response = openai.Completion.create(
                model="text-davinci-003",
                prompt=self.prompt,
                temperature=0,
                max_tokens=100,
                top_p=1,
            )
            self.result = response["choices"][0]["text"].replace("\n", "")
        except:
            return pc.window_alert("Error occured with OpenAI execution.")

    def save_result(self):
        with pc.session() as session:
            answer = Question(
                username=self.username, prompt=self.prompt, answer=self.result
            )
            session.add(answer)
            session.commit()

    def set_username(self, username):
        self.username = username.strip()

    def set_password(self, password):
        self.password = password.strip()

def home():
    return pc.center(
        navbar(State),
        pc.vstack(
            pc.center(
                pc.vstack(
                    pc.heading("Ask GPT", font_size="1.5em"),
                    pc.text_area(
                        default_value=State.result,
                        placeholder="GPT Result",
                        height="30em",
                        width="100%",
                        is_read_only=True,
                    ),
                    pc.input(
                        on_blur=State.set_prompt, placeholder="Question",
                    ),
                    pc.button("Get Answer", on_click=State.get_result),
                    # pc.button("Save Answer", on_click=State.save_result, width="100%"),
                    shadow="lg",
                    padding="1em",
                    border_radius="lg",
                    width="100%",
                ),
                width="100%",
            ),
            # pc.center(
            #     pc.vstack(
            #         pc.heading("Saved Q&A", font_size="1.5em"),
            #         pc.divider(),
            #         pc.data_table(
            #             data=State.questions,
            #             columns=["Question", "Answer"],
            #             pagination=True,
            #             search=True,
            #             sort=True,
            #             width="100%",
            #         ),
            #         shadow="lg",
            #         padding="1em",
            #         border_radius="lg",
            #         width="100%",
            #     ),
            #     width="100%",
            # ),
            width="50%",
            spacing="2em",
        ),
        padding_top="6em",
        text_align="top",
        position="relative",
    )


def login():
    return pc.center(
        pc.vstack(
            pc.input(on_blur=State.set_username, placeholder="Username", width="100%"),
            pc.input(type_="password", on_blur=State.set_password, placeholder="Password", width="100%"),
            pc.button("Login", on_click=State.login, width="100%"),
            pc.link(pc.button("Sign Up", width="100%"), href="/signup", width="100%"),
        ),
        shadow="lg",
        padding="1em",
        border_radius="lg",
        background="white",
    )


def signup():
    return pc.box(
        pc.vstack(
            pc.center(
                pc.vstack(
                    pc.heading("GPT Sign Up", font_size="1.5em"),
                    pc.input(
                        on_blur=State.set_username, placeholder="Username", width="100%"
                    ),
                    pc.input(
                        type_="password", on_blur=State.set_password, placeholder="Password", width="100%"
                    ),
                    pc.input(
                        type_="password",
                        on_blur=State.set_password,
                        placeholder="Confirm Password",
                        width="100%",
                    ),
                    pc.button("Sign Up", on_click=State.signup, width="100%"),
                ),
                shadow="lg",
                padding="1em",
                border_radius="lg",
                background="white",
            )
        ),
        padding_top="10em",
        text_align="top",
        position="relative",
        width="100%",
        height="100vh",
        background="radial-gradient(circle at 22% 11%,rgba(62, 180, 137,.20),hsla(0,0%,100%,0) 19%),radial-gradient(circle at 82% 25%,rgba(33,150,243,.18),hsla(0,0%,100%,0) 35%),radial-gradient(circle at 25% 61%,rgba(250, 128, 114, .28),hsla(0,0%,100%,0) 55%)",
    )


def index():
    return pc.box(
        pc.vstack(
            navbar(State),
            login(),
        ),
        padding_top="10em",
        text_align="top",
        position="relative",
        width="100%",
        height="100vh",
        background="radial-gradient(circle at 22% 11%,rgba(62, 180, 137,.20),hsla(0,0%,100%,0) 19%),radial-gradient(circle at 82% 25%,rgba(33,150,243,.18),hsla(0,0%,100%,0) 35%),radial-gradient(circle at 25% 61%,rgba(250, 128, 114, .28),hsla(0,0%,100%,0) 55%)",
    )


# Add state and page to the app.
app = pc.App(state=State)
app.add_page(index)
app.add_page(signup)
app.add_page(home)
app.compile()

helpers.py 파일은 아래와 같이 수정합니다.

import pynecone as pc


def navbar(State):
    return pc.box(
        pc.hstack(
            pc.link(
                pc.hstack(pc.image(src="favicon.ico"), pc.heading("Yunwoong GPT")), href="/"
            ),
            pc.menu(
                pc.menu_button(
                    pc.cond(
                        State.logged_in,
                        pc.avatar(name=State.username, size="md"),
                        pc.box(),
                    )
                ),
                pc.menu_list(
                    pc.center(
                        pc.vstack(
                            pc.avatar(name=State.username, size="md"),
                            pc.text(State.username),
                        )
                    ),
                    pc.menu_divider(),
                    pc.link(pc.menu_item("About GPT"), href="https://openai.com/api/"),
                    pc.link(pc.menu_item("Sign Out"), on_click=State.logout),
                ),
            ),
            justify="space-between",
            border_bottom="0.2em solid #F0F0F0",
            padding_x="2em",
            padding_y="1em",
            bg="rgba(255,255,255, 0.90)",
        ),
        position="fixed",
        width="100%",
        top="0px",
        z_index="500",
    )

4. Config

pcconfig.py의 app_name을 수정합니다. 

import pynecone as pc

config = pc.Config(
    app_name="gpt",
    db_url="sqlite:///pynecone.db",
    env=pc.Env.DEV,
)

5. Run the App

app을 실행해 보도록 하겠습니다. 브라우저 주소창에 http://localhost:3000를 입력 후 페이지 결과를 확인합니다.

$ pc run

반응형