완성된 프론트엔드 인덱스 html

<!DOCTYPE html>
<html>
<head>
    <style>
        body {
            position: relative;
            height: 100vh;
            margin: 0;
            background-color: #f2f2f2;
            font-family: Arial, sans-serif;
        }

        #chat-icon {
            position: fixed;
            bottom: 20px;
            right: 20px;
            cursor: pointer;
            padding: 10px 20px;
            background-color: #f6e830;
            color: rgb(58, 53, 30);
            font-weight: bold;
            border-radius: 8px;
            box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
            z-index: 10;
        }

        #chat-box {
            position: fixed;
            bottom: 70px;
            right: 20px;
            width: 400px;
            height: 600px;
            background-color: #b1c6d9;
            border: 1px solid gray;
            padding: 10px;
            box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
            flex-direction: column;
            justify-content: space-between;
            display: none;
          }

          #messages {
              height: 80%;
              overflow-y: auto;
          }

          .user, .bard {
              margin: 10px 0;
              clear: both;
              position: relative;
              display: flex;
              align-items: flex-start;

          }

          .user {
              float: right;
              flex-direction: row-reverse;
          }

          .bard {
              float: left;
          }

          .avatar {
            width: 40px;
            height: 40px;
            border-radius: 50%;
          }

          .user .avatar {
            float: right;
          }

          .bard .avatar {
            float: left;
          }

          .message-bubble {
            max-width: 70%;
            background-color: #f0f0f2;
            padding: 10px;
            border-radius: 10px 10px 10px 0;
            margin: 5px 50px;
            position: relative;
        }

        .user .message-bubble {
            background-color: #f6e830;
            color: rgb(58, 53, 30);
            float: right;
            border-radius: 10px 10px 10px 10px;
        }

        .user .message-bubble::after {
            content: "";
            position: absolute;
            top: 0; 
            right: 0;
            border-width: 10px 10px 0 0;
            border-style: solid;
            border-color: #f6e830 transparent;
        }

        .bard .message-bubble {
            float: left;
            border-radius: 10px 10px 10px 10px;
        }

        .bard .message-bubble::after {
            content: "";
            position: absolute;
            top: 0;
            left: 0;
            border-width: 10px 0 0 10px;
            border-style: solid;
            border-color: #f0f0f2 transparent;
            }

          #chat-form {
              display: flex;
              justify-content: space-between;
              border-top: 1px solid #ccc;
              padding: 10px;
          }

          #chat-form input[type="text"] {
              width: 80%;
              padding: 5px;
              border: none;
              border-radius: 10px;
          }

        #chat-form input[type="submit"] {
            background-color: #f6e830;
            color: rgb(58, 53, 30);
            border: none;
            border-radius: 10px;
            padding: 5px 10px;
        }
    </style>
</head>
<body>
    <div id="chat-icon" onclick="toggleChatBox()">
        챗봇
    </div>

    <div id="chat-box">
        <div id="messages"></div>
        <form id="chat-form" onsubmit="event.preventDefault(); submitMessage()">
            <input type="text" id="input-message" placeholder="질문을 입력하세요" autocomplete="off" required>
            <input type="submit" value="입력">
        </form>
    </div>
    <script>
        var chatBoxVisible = false;

        function toggleChatBox() {
            var chatBox = document.getElementById("chat-box");
            var inputMessage = document.getElementById("input-message");
            if (!chatBoxVisible) {
                chatBox.style.display = "flex";
                chatBoxVisible = true;
                inputMessage.focus(); 
            } else {
                chatBox.style.display = "none";
                chatBoxVisible = false;
                inputMessage.blur(); 
            }
        }

        window.onload = function() {
            document.getElementById("chat-box").style.display = "none";
        }

        function scrollToBottom(element) {
            element.scrollTop = element.scrollHeight;
        }

        function submitMessage() {
            var input = document.getElementById("input-message");
            var message = input.value;
            input.value = "";

            var userMessage = document.createElement("div");
            userMessage.className = "user";

            var avatar = document.createElement("img");
            avatar.src = "file:///C:/Users/tngus/OneDrive/바탕%20화면/챗위드포천교육/인공지능%20api%20활용/templates/images/im.png"; 
            avatar.className = "avatar";
            userMessage.appendChild(avatar);

            var bubble = document.createElement("div");
            bubble.textContent = message;
            bubble.className = "message-bubble";
            userMessage.appendChild(bubble);

            var messages = document.getElementById("messages");
            messages.appendChild(userMessage);

            scrollToBottom(messages);

            fetch("/", {
                method: "POST",
                headers: { "Content-Type": "application/json" },
                body: JSON.stringify({ question: message })
            }).then(response => response.json())
            .then(data => {
                var bardMessage = document.createElement("div");
                bardMessage.className = "bard";

                var bardAvatar = document.createElement("img");
                bardAvatar.src = "im.png"; 
                bardAvatar.className = "avatar";
                bardMessage.appendChild(bardAvatar);

                var bardBubble = document.createElement("div");
                bardBubble.textContent = data.answer;
                bardBubble.className = "message-bubble";
                bardMessage.appendChild(bardBubble);

                messages.appendChild(bardMessage);
                scrollToBottom(messages);
            });
        }
    </script>
</body>
</html>

완성된 백엔드 app.py

from flask import Flask, render_template, request, jsonify
import os
import bardapi

# Bard API key 설정
os.environ['_BARD_API_KEY'] = "XwgyrM8N1vkwESsSa5RQIK-bUDSJkbNfpT2GD25LaWTydkW8zCJ-WQPpoo9_sWf_6XBYEw."

bard = bardapi.core.Bard()

app = Flask(__name__)

def load_text(filename):
    with open(filename, 'r', encoding='utf-8') as file:
        text = file.read()
    return text # 한글로 8000자 넘어가면 오류나옴

@app.route('/', methods=['GET', 'POST'])
def index():
    if request.method == 'POST':
        data = request.get_json()
        user_question = data['question']
        text = load_text('bard.txt')
        combined_text = "질문: 사립유치원과 관련하여"+user_question +"? 1. 위 질문에 대한 답변을 생성하되 참고 텍스트를 기준dmfh 답변해줘. 2. 참고 텍스트에 나온 질문은 참고 텍스트에 따라 답변하면 되고하면 되고 스스로 생성한 답변이 참고 텍스트와 상충하는 경우 참고 텍스트를 우선으로 답변해줘 헌법처럼. 3. 그리고 답변은 반드시!!! 150자 이하로 요약해서 작성해줘 답변의 길이가 150자를 넘으면 안됩니다. 4. 사립유치원과 관련 없는 질문에는 관련없는 질문이라 대답못하겠다고 답변해줘. 5. 앞에 쓴 1,2,3,4 요청사항은 답변할 때 설명하지마. 참고 텍스트="+ text
        response = bard.get_answer(combined_text)
        # 'choices' 키가 존재하고 그 안에 내용이 있는지 확인
        if 'choices' in response and len(response['choices']) > 0:
            answer = response['choices'][0]['content']
        else:
            answer = "The key 'choices' is not in the response or there are no choices."
        return jsonify({'answer': answer})

    return render_template('index.html')

if __name__ == "__main__":
    app.run(port=5000, debug=True)