๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐˜ผ๐™„/๐™‹๐™ง๐™ค๐™Ÿ๐™š๐™˜๐™ฉ

ํŒŒ์ด์ฌ์œผ๋กœ ๊ฐ„๋‹จํ•˜๊ฒŒ ์ฑ—๋ด‡ ๋งŒ๋“ค๊ธฐ

by beomcoder 2023. 5. 9.
728x90
๋ฐ˜์‘ํ˜•

์šฐ์„  ์ฑ—๋ด‡์„ ํ˜ผ์ž ๋งŒ๋“ค์–ด๋ณด๋ ค๊ณ  ๋งŒ๋“  ์ž๋ฃŒ๋“ค๊ณผ ๋…ผ๋ฌธ์„ ์ฝ์–ด๋ณด์•˜๋‹ค.

ํ•˜์ง€๋งŒ ์ปดํ“จํŒ…์ž์›์ด ๋ถ€์กฑํ•˜๊ณ  ์ผ์ผํžˆ ๋Œ€ํ™”์ž๋ฃŒ๋ฅผ ๋งŒ๋“ค์–ด๋‚ด๊ธฐ๋Š” ์–ด๋ ค์› ๋‹ค.

๊ทธ๋ž˜์„œ ์ฐพ์•„๋ณด์•˜๋Š”๋ฐ ๋น„์Šทํ•œ ์ž๋ฃŒ๊ฐ€ ์žˆ์–ด์„œ ์ด๊ฑธ ์ฑ—๋ด‡์œผ๋กœ ๊ตฌํ˜„ํ•ด๋ณด์•˜๋‹ค.

 

๋ณด์‹œ๊ธฐ ์ „์— ๋ฏธ๋ฆฌ ๋งํ•˜์ง€๋งŒ ์ฑ—๋ด‡์ด๋ผ๊ณ  ํ•˜๊ธฐ์—๋Š” ๋‹ค์†Œ ๋ฌธ์ œ๊ฐ€ ์žˆ๊ธด ํ•˜์ง€๋งŒ,

๊ฐ„๋‹จํ•˜๊ฒŒ ์žฌ๋ฏธ๋ฅผ ๋ถ™์—ฌ๋ณผ ์ˆ˜๋Š” ์žˆ๋‹ค.

์šฐ์„  ๋‹ค ํ•œ ์ž๋ฃŒ๋ฅผ ๋จผ์ € ๋ณด๊ณ ๋‚˜์„œ ๋๊นŒ์ง€ ๋ณผ ์‚ฌ๋žŒ์€ ๋ด๋„ ๋œ๋‹ค.

 

 

 

์ด์ œ ํŒ์Šค ์ง„ํ–‰์„ ํ•ด์•ผํ•ด์„œ ์กฐ๊ธˆ๋” ๊ณ ๋„ํ™”ํ•˜์ง€๋Š” ๋ชปํ–ˆ๋‹ค.

 

ํ† ํฐํ™”, ๋”ฅ๋Ÿฌ๋‹, ๋™์‚ฌ, ๋ช…์‚ฌ, ์กฐ์‚ฌ, ์ด๋Ÿฐ๊ฑฐ ๋‹ค ํ•„์š”์—†๋‹ค.

ํ•˜์ง€๋งŒ ์กฐ๊ธˆ๋” ๋Œ€ํ™”๋ฅผ ๋งค๋„๋Ÿฝ๊ฒŒ ํ•˜๊ธฐ์œ„ํ•ด์„œ๋Š” ๊ทธ์ •๋„๋Š” ํ•ด์ค˜๋„ ๋œ๋‹ค.

 

๋จผ์ € ์–ด๋ ต๊ฒŒ ์ฐพ์€ API์ด๋‹ค.

์ด๊ฑด ๋ฌด๋ฃŒ์ด๊ณ  ์„ฑ๋Šฅ๋„ ๊ดœ์ฐฎ๊ณ , ํ•œ๊ตญ์—์„œ ๋›ฐ์–ด๋‚œ ์„,๋ฐ•์‚ฌ๋‹˜๋“ค์ด ๋งŒ๋“  ๊ฒƒ์ด๋‹ค.

 

https://aiopen.etri.re.kr/guide/MRCServlet
 

AI API/DATA

JSON parsing์„ ์œ„ํ•ด Gson ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ œ๊ณตํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. Gson ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ๋Œ€ํ•œ ์ž์„ธํ•œ ์„ค๋ช…์€ https://github.com/google/gson ์—์„œ ํ™•์ธ ํ•˜์‹ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. import java.io.DataOutputStream; import java.i

aiopen.etri.re.kr

 

 

์—ฌ๊ธฐ๋ฅผ ๊ฐ€์„œ APIํ‚ค๋ฅผ ๋ฐœ๊ธ‰๋ฐ›๋Š”๋‹ค.

 

 

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ํ‚ค๋ฅผ ์“ธ ์ˆ˜ ์žˆ๊ณ , ๋‚˜๋Š” ๊ธฐ๊ณ„๋…ํ•ด API๋ฅผ ์ด์šฉํ•ด์„œ ์ฑ—๋ด‡์„ ๋งŒ๋“œ๋ ค๊ณ  ํ•œ๋‹ค.

 

#-*- coding:utf-8 -*-
import urllib3
import json

openApiURL = "http://aiopen.etri.re.kr:8000/MRCServlet"
accessKey = "๋ณธ์ธ์˜ ํ‚ค"
passage = ''.join(open('info.txt', 'r').readlines()) # ํ•ด๋‹ต์ง€
# ์˜ˆ์‹œ) passage = "์•ˆ๋…•ํ•˜์„ธ์š”: ๋ฐ˜๊ฐ‘์Šต๋‹ˆ๋‹ค."

http = urllib3.PoolManager()

question = "์งˆ๋ฌธ๋‚ด์šฉ"
requestJson = {"argument": { "question": question, "passage": passage }}

response = http.request(
    "POST",
    openApiURL,
    headers={"Content-Type": "application/json; charset=UTF-8","Authorization": accessKey},
    body=json.dumps(requestJson)
)

r = json.loads(str(response.data,"utf-8"))
answer = r['return_object']['MRCInfo']['answer']
print(answer)

๋จผ์ € ๊ธฐ๋ณธ์ ์ธ ํ‹€์ด๋‹ค. accessKey์— ๋ณธ์ธ์ด ๋ฐ›์€ ํ‚ค๊ฐ’์„ ๋„ฃ์œผ๋ฉด ๋œ๋‹ค.

passage์— ์งˆ๋ฌธ์— ๋Œ€๋‹ตํ•  ๋‚ด์šฉ๋“ค์„ ๊ธฐ์ž…ํ•˜๋ฉด ๋œ๋‹ค.

๊ทธ๋ฆฌ๊ณ  question์— ์งˆ๋ฌธ์„ ์ ์–ด์„œ ๋ณด๋‚ด๊ธฐ๋งŒ ํ•˜๋ฉด ๋์ด๋‹ค.

 

์—ฌ๊ธฐ๊นŒ์ง€๋งŒ ํ•ด์„œ ์ฝ”๋“œ๋ฅผ API๋กœ ๋งŒ๋“ค์–ด์„œ ํ†ต์‹ ํ•˜๋ฉด ๊ฐ„๋‹จํ•œ ์ฑ—๋ด‡์ด ๋œ๋‹ค.

๋‚˜๋Š” ๊ทธ๋ƒฅ ๊ฐ„๋‹จํ•˜๊ฒŒ ํ”Œ๋ผ์Šคํฌ๋กœ ๊ตฌํ˜„ํ•˜์—ฌ AWS์—์„œ ๋Œ๋ ค๋ณด์•˜๋‹ค.

 

๋จผ์ € ๋‚ด๊ฐ€ ๋งŒ๋“  textํŒŒ์ผ์ด๋‹ค.

ํœด๋Œ€ํฐ์„ ์ธ์ฆํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๋จผ์ € ์ด์šฉ๋™์˜๋ฅผ ํ•˜์‹œ๊ณ , ํœด๋Œ€ํฐ๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ž…๋ ฅํ•œ ํœด๋Œ€ํฐ๋ฒˆํ˜ธ์— ์ธ์ฆ๋ฒˆํ˜ธ๊ฐ€ ๋ฌธ์ž๋ฉ”์‹œ์ง€๋กœ ์˜ค๋ฉด ๊ทธ ์ธ์ฆ๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•˜์‹œ๋ฉด ํœด๋Œ€ํฐ ์ธ์ฆ์ด ๋ฉ๋‹ˆ๋‹ค. [END]
๋ชจ์ž„์„ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์€ ๋ชจ์ž„์˜ ์ด๋ฆ„์„ ์ž…๋ ฅํ•˜๊ณ , ๊ด€์‹ฌ์‚ฌ๋ฅผ ์„ค์ •ํ•˜๊ณ  ๊ฐœ์„คํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. [END]
๋ชจ์ž„์„ ์‚ญ์ œํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๋ชจ์ž„ ์„ค์ •์— ๋“ค์–ด๊ฐ€์„œ ๋ชจ์ž„ํ•ด์ฒดํ•˜๊ธฐ๋ฅผ ๋ˆ„๋ฅด์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค. [END]
๋ชจ์ž„์ด๋ž€ ์˜คํ”„๋ผ์ธ์—์„œ ์‚ฌ๋žŒ๋“ค๋ผ๋ฆฌ ๋งŒ๋‚˜์„œ ์ทจ๋ฏธํ™œ๋™์„ ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํ•œ๋ฒˆ ๋ชจ์ž„์„ ํ•ด๋ณด์‹œ๋Š”๊ฑด ์–ด๋–จ๊นŒ์š”? [END]

์–ดํ”Œ๋‚ด์—์„œ ์ฑ—๋ด‡์„ ๋งŒ๋“ค์–ด๋ณด๋ฉด ์ข‹๊ฒ ๋‹ค๋Š” ์ทจ์ง€์—์„œ ์‹œ์ž‘ํ–ˆ์œผ๋ฏ€๋กœ

์–ดํ”Œ์‚ฌ์šฉ์— ๊ด€ํ•œ ๊ฐ„๋‹จํ•œ ๋‚ด์šฉ์„ ํ…์ŠคํŠธํŒŒ์ผ๋กœ ๋งŒ๋“ค์—ˆ๋‹ค.

[END]๋ฅผ ๋ถ™์ธ ์ด์œ ๋Š” question์˜ ๋‚ด์šฉ์ด passage์—์„œ ์ œ๋Œ€๋กœ ๊ฒ€์ƒ‰์ด ์•ˆ๋ ๋•Œ

์ „์ฒด ๋‚ด์šฉ์„ ๊ธ์–ด์˜ค๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ๋Š”๋ฐ ์ด๋ฅผ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด END๋ผ๋Š” ๋‹ต๋ณ€์˜ ๋์„ ์„ค์ •ํ•ด์ฃผ์—ˆ๋‹ค.

 

ํ˜น์‹œ ๋‚˜๋ฅผ ๋๊นŒ์ง€ ๋”ฐ๋ผํ•ด๋ณด๋ ค๋Š” ์‚ฌ๋žŒ์ด ์žˆ์„๊ฒƒ ๊ฐ™์•„์„œ ํด๋”๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ตฌ์„ฑํ–ˆ๋‹ค.

chatbot.py์—์„œ ์•„๊นŒ์™€ ๊ฐ™์€ ์ฝ”๋“œ๋กœ ๊ตฌ์„ฑํ•˜๊ณ , main.py๋กœ flask๋กœ ๊ฐ„๋‹จํ•˜๊ฒŒ ๊ตฌํ˜„ํ–ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  html์—์„œ ์ฒ˜์Œ ํ™”๋ฉด๊ณผ ๊ฐ™์ด ๊พธ๋ฉฐ์ฃผ์—ˆ๋‹ค.

 

main.py
# main.py
#-*- coding:utf-8 -*-
from flask import Flask, render_template, request, redirect, url_for
import chatbot

app = Flask(__name__)
board = []
 
@app.route('/')
def index():
    return render_template('main.html', rows=board, qnas=chatbot.src)

@app.route('/question',methods=["POST"])
def question():
    if request.method == "POST":
        board.append([request.form["context"], chatbot.action(request.form["context"])])
        return redirect(url_for("index"))
    else:
        return render_template("main.html", rows=board, qnas=chatbot.src)
 
if __name__ == '__main__':
    app.run(host='0.0.0.0', debug=True, port=8888)

 

๋จผ์ € main.py์ด๋‹ค.

๊ฐ„๋‹จํ•œ ์„œ๋ธŒํ”„๋กœ์ ํŠธ์—ฌ์„œ django๋‚˜ ๊ณต๋ถ€ํ•˜๊ณ  ์žˆ๋Š” fastapi๋Š” ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  flask๋กœ ๊ตฌํ˜„ํ•˜์˜€๋‹ค.

flask๋‚˜ api, html์— ๋Œ€ํ•ด์„œ๋Š” ๋”ฐ๋กœ ์„ค๋ช…ํ•˜์ง€๋Š” ์•Š๊ฒ ๋‹ค.

 

์ฒ˜์Œ์— ํ™”๋ฉด์„ ๋“ค์–ด๊ฐ€๋ฉด main.html์„ ๋ถˆ๋Ÿฌ์˜จ๋‹ค.

 

 

import urllib3, json
from konlpy.tag import Okt

openApiURL = "http://aiopen.etri.re.kr:8000/MRCServlet"
accessKey = "KEY"

src = open('info.txt', 'r', encoding='utf-8').readlines()
passage = ''.join(src)
http = urllib3.PoolManager()
okt = Okt()

# def action(q):
#     requestJson = {"argument": { "question": q, "passage": passage }}
#     response = http.request("POST", openApiURL, headers={"Content-Type": "application/json; charset=UTF-8","Authorization": accessKey}, body=json.dumps(requestJson))
#     response = json.loads(str(response.data,"utf-8"))

#     print(response)

#     answer = response['return_object']['MRCInfo']['answer']
#     print('๋ณ€๊ฒฝ์ „:', answer)

#     if '[END]' in answer:
#         answer = answer[:answer.index('[END]')]

#     answer = passage[passage.index(answer): passage.index('[END]', passage.index(answer))]
#     print('๋ณ€๊ฒฝํ›„:', answer)

#     return answer

def action(q):
    q = okt.normalize(q)

    if len(okt.nouns(q)):
        # print(okt.pos(q))
        requestJson = {"argument": { "question": q, "passage": passage }}
        response = http.request("POST", openApiURL, headers={"Content-Type": "application/json; charset=UTF-8","Authorization": accessKey}, body=json.dumps(requestJson))
        response = json.loads(str(response.data,"utf-8"))

        # print(response)

        if float(response['return_object']['MRCInfo']['confidence']) > 0.10:
            answer = response['return_object']['MRCInfo']['answer']
            print('๋ณ€๊ฒฝ์ „:', answer)

            if '[END]' in answer:
                answer = answer[:answer.index('[END]')]

            answer = passage[passage.index(answer): passage.index('[END]', passage.index(answer))]
            print('๋ณ€๊ฒฝํ›„:', answer)

            return answer
        
    
    # print(q)
    # end_word = [word for word in q if '๊ฐ€'<=word<='ํžฃ'][-1]
    # josa = '์ด' if (ord(end_word)-ord("๊ฐ€")) % 28 > 0 else ''

    josa = ''
    return '"' + q + '"' + josa + '๋ผ๋Š” ๋ฌธ์žฅ์€ ์•„์ง ์ œ๋Œ€๋กœ ์ดํ•ดํ•˜์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด ์‚ฌํ•ญ์€ ์ฑ—๋ด‡ ์‘๋‹ต์— ์ถ”๊ฐ€๋  ์˜ˆ์ •์ž…๋‹ˆ๋‹ค.'

 

chatbot.py ํŒŒ์ผ์ด๋‹ค.

์•„๊นŒ ์˜ˆ์ œ ์†Œ์Šค์—์„œ ์•ฝ๊ฐ„๋งŒ ๋ณ€ํ˜•ํ–ˆ๋‹ค.

์‹œ๊ฐ„๋งŒ ๋” ์žˆ์—ˆ์œผ๋ฉด ๋‚˜๋„ ํ˜•ํƒœ์†Œ๋ฅผ ๋ถ„์„ํ•˜์—ฌ ์กฐ๊ธˆ๋” ์งˆ๋ฌธ์˜ ์–‘์‹์„ ์ผ์ •ํ™” ์‹œํ‚ค๊ณ ,

ํ’ˆ์งˆ์„ ์˜ฌ๋ฆฌ๋ ค ํ–ˆ์ง€๋งŒ ์‹œ๊ฐ„์ด ๋งŽ์ง€ ์•Š์•˜๋‹ค.

 

๊ทธ๋ž˜์„œ ๊ทธ๋ƒฅ ๊ฐ„๋‹จํ•˜๊ฒŒ ์ผ์ • ์ •ํ™•๋„๊ฐ€ ๋„˜์œผ๋ฉด answer์˜ ์งˆ์ด ๊ฐ€์น˜๊ฐ€ ์žˆ๋‹ค๊ณ  ํŒ๋‹จํ•˜์—ฌ

๊ฐ„๋‹จํ•œ ์ •์ œ ํ›„์— html์— ๋ฟŒ๋ ค์ค€๋‹ค.

 

๋‚˜๋Š” ํ…Œ์ŠคํŠธ๋ฅผ ํ•ด๋ณด๋‹ˆ passage์˜ ๋‚ด์šฉ๊ณผ ๋˜‘๊ฐ™์€ ์งˆ๋ฌธ์„ ํ• ๋•Œ๋Š” ํผ์„ผํŠธ๊ฐ€ ๋†’์•˜์ง€๋งŒ ๋œป์ด ๋น„์Šทํ•œ ๋ฌธ์žฅ์œผ๋กœ ์งˆ๋ฌธํ•˜์˜€์„๋•Œ๋Š”

13~20%์˜ ํ™•๋ฅ ์ด ๋‚˜์™”๊ธฐ ๋•Œ๋ฌธ์— ์šฐ์„  10%๋งŒ ๋„˜์–ด๋„ ๋‹ตํ•  ๊ฐ€์น˜๊ฐ€ ์žˆ๋‹ค๊ณ  ํŒ๋‹จํ•˜์˜€๋‹ค.

 

๊ทธ๋ฆฌ๊ณ  ์ด์ œ 10~20%์˜ ์ •ํ™•๋„์ผ๋•Œ๋Š” ๋ชจ๋ธ์—์„œ ์ฐพ์€ ๋‹ต์˜ ์ฒ˜์Œ๋ถ€ํ„ฐ,

text๊ฐ€ ๋๋‚˜๋Š” ๋ชจ๋“  ๋‚ด์šฉ์„ ๋‹ด์•„์„œ ์ •๋‹ต์ด๋ผ๊ณ  ๋งํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ด๋ฅผ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด

[END]๊ธฐํ˜ธ๋กœ ์ •๋‹ต์˜ ๋๋ถ€๋ถ„์„ ์ง€์ •ํ•ด ์ฃผ์—ˆ๋‹ค.

 

๊ทธ๋ฆฌ๊ณ  10%๋ฏธ๋งŒ์ผ๋•Œ๋Š” passage์— ์žˆ๋Š” ๋‚ด์šฉ์ด ์•„๋‹ˆ๋ผ๊ณ  ์ƒ๊ฐํ•˜๊ณ  ๋‹ตํ• ์ˆ˜ ์—†๋‹ค๋Š” ๋ฌธ์žฅ์„ ๋‹ด์•„์ฃผ์—ˆ๋‹ค.

 

 

<!-- ./template/main.html -->
<!doctype html>

<html lang="ko">
    <head>
        <meta charset="UTF-8">
        <meta name="Generator" content="EditPlus®">
        <meta name="Author" content="">
        <meta name="Keywords" content="">
        <meta name="Description" content="">
        <script src="https://kit.fontawesome.com/77ad8525ff.js" crossorigin="anonymous"></script>
        <title>OE CHATBOT</title>
    
        <style type="text/css">
            * {
                padding: 0;
                margin: 0;
                box-sizing: border-box;
                
            }

            .top{
                border-radius: 10px;
                display: block;
                margin: auto;
                padding: 40px;
                width: 1000px;
                overflow: auto;
                background-color: #e2db72;
                margin-bottom: 20px;
                margin-top: 20px;

            }

            .top .title{
                text-align: center;
                margin-bottom: 5px;
            }
            
            .top .sub-title{
                text-align: center;
                margin-bottom: 5px;
            }

            a {
                text-decoration: none;
            }

            div::-webkit-scrollbar {
                display: none;
            }

            .bottom{
                border-bottom-right-radius: 10px;
                border-bottom-left-radius: 10px;

                display: block;
                margin: auto;
                padding: 40px 0;
                width: 500px;
                background-color: #A8C0D6;;
            }

            .screen{
                border-top-left-radius: 10px;
                border-top-right-radius: 10px;
                display: block;
                margin: auto;
                padding: 40px 0;
                width: 500px;
                height: 500px;
                overflow: auto;
                background-color: #A8C0D6;
            }

            .screen .chat {
                display: flex;
                align-items: flex-start;
                padding: 20px;
            }

            .screen .chat .icon {
                position: relative;
                overflow: hidden;
                width: 50px;
                height: 50px;
                border-radius: 50%;
                background-color: #eee;
            }

            .screen .chat .icon i {
                position: absolute;
                top: 10px;
                left: 50%;
                font-size: 2.5rem;
                color: #aaa;
                transform: translateX(-50%);
            }

            .screen .chat .textbox {
                position: relative;
                display: inline-block;
                max-width: calc(100% - 70px);
                padding: 10px;
                margin-top: 7px;
                font-size: 13px;
                border-radius: 10px;
            }

            .screen .chat .textbox::before {
                position: absolute;
                display: block;
                top: 0;
                font-size: 1.5rem;
            }

            .screen .ch1 .textbox {
                margin-left: 20px;
                background-color: #ffffff;
            }

            .screen .ch1 .textbox::before {
                left: -15px;
                content: "โ—€";
                color: #ffffff;
            }

            .screen .ch2 {
                flex-direction: row-reverse;
            }

            .screen .ch2 .textbox {
                margin-right: 20px;
                background-color: #F9EB54;
            }

            .screen .ch2 .textbox::before {
                right: -15px;
                content: "โ–ถ";
                color: #F9EB54;
            }

            .input-box {
                border: 1px solid #ccc;
                border-radius: 4px;
                padding: 10px;
                font-size: 16px;
                width: 400px;
                margin-left: 11px;
            }

            .submit-button {
                background-color: #4CAF50;
                color: white;
                border: none;
                border-radius: 4px;
                padding: 10px 20px;
                font-size: 16px;
                cursor: pointer;
            }

            .submit-button:hover {
                background-color: #3e8e41;
            }

        </style>
    </head>
 
    <body>
        <div class="top">
            <h3 class="title">์ฑ—๋ด‡ ํ…Œ์ŠคํŠธ</h3>
            <h4 class="sub-title">์ฑ—๋ด‡๋‹ต๋ณ€๋ฆฌ์ŠคํŠธ</h4>
            {% for qna in qnas %}
                <a>{{ loop.index }}. {{ qna }}</a><br>
            {% endfor %}
        </div>

        <div class="screen" id="screen">
            {% for row in rows %}
            <div class="chat ch2">
                <div class="icon"><i class="fa-solid fa-user"></i></div>
                <div class="textbox">{{ row[0] }}</div>
            </div>
            <div class="chat ch1">
                <div class="icon"><img src="{{ url_for('static', filename='image/beomcoder.jpg')}}" alt="TEST"></div>
                <div class="textbox">{{ row[1] }}</div>
            </div>
            {% endfor %}
        </div>
        <div class="bottom">
            <form action="/question" method="POST">
                <input type="text" class="input-box" name="context">
                <input type="submit" class="submit-button"value="์ „์†ก" /><br>
            </form> 
        </div>
        <script>
            var div = document.getElementById("screen");
            div.scrollTop = div.scrollHeight;
        </script>
    </body>
</html>

main.html์ด๋‹ค. ๊ฐ„๋‹จํ•œ ํ…Œ์ŠคํŠธ์šฉ์ด๋ผ ์›ํŽ˜์ด์ง€๋กœ ๊ตฌ์„ฑํ•˜์˜€๋‹ค.

๋‚ด๊ฐ€ html์€ ์ฐ๋จน์ •๋„๋งŒ ํ• ์ค„ ์•Œ์•„์„œ ๋”ฐ๋กœ cssํŒŒ์ผ์„ ๋งŒ๋“ค๊ธฐ์—๋Š” ๊ท€์ฐฎ์•˜๋‹ค.

flask๋ฅผ ์“ธ๋•Œ์—๋Š” templates์— html๋“ค์ด ์œ„์น˜ํ•ด์•ผํ•œ๋‹ค. ์ด๊ฑด๋งŒ ์ง€ํ‚ค๋ฉด ๋‹ค๋ฅธ ํŒŒ์ผ์€ ์ด๋ฆ„์„ ๋ณ€๊ฒฝํ•ด๋„ ๋œ๋‹ค.

 

https://rgy0409.tistory.com/4854
 

HTML + CSS ์นด์นด์˜คํ†ก ์ฑ„ํŒ…์ฐฝ ํ™”๋ฉด ๋งŒ๋“ค๊ธฐ 2์žฅ - ๋Œ€ํ™”์ฐฝ (๋งํ’์„ )

์ง€๋‚œ ์‹œ๊ฐ„์— ์ด์–ด ์˜ค๋Š˜๋„ ์—ฐ์ด์–ด์„œ HTML + CSS๋กœ ์นด์นด์˜คํ†ก ์ฑ„ํŒ… ๋Œ€ํ™”์ฐฝ์„ ๋งŒ๋“ค์–ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์ด์ „ ๊ฐ•์˜์—์„œ๋Š” ํ”„๋กœํ•„ ์•„์ด์ฝ˜์„ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์•Œ์•„๋ณด์•˜์Šต๋‹ˆ๋‹ค. ์ด๋ฒˆ์—๋Š” ํ”„์‚ฌ ๋ฐ”๋กœ ์˜†์— ํ‘œ

rgy0409.tistory.com

 

์œ„ ์‚ฌ์ดํŠธ์—์„œ ๊ฐ„๋‹จํ•˜๊ฒŒ ์นด์นด์˜คํ†ก์Šค๋Ÿฌ์šด ์ด๋ฏธ์ง€๋ฅผ ๊ตฌํ˜„ํ•˜๊ณ  ์žˆ์–ด ์œ„ ์†Œ์Šค๋ฅผ ์ฐธ์กฐํ•˜์—ฌ ๋งŒ๋“ค์—ˆ๋‹ค.

์œ„ ์†Œ์Šค์—์„œ ๋งํ’์„ ๊ณผ ํ”„๋กœํ•„์ด๋ฏธ์ง€๋งŒ ๊ฐ€์ ธ์˜ค๊ณ  ๋‚˜๋จธ์ง€๋Š” ์ง์ ‘ ์ œ์ž‘ํ•˜์˜€๋‹ค.

 

์ž…๋ ฅ์ฐฝ, ํœด๋Œ€ํฐ์ฒ˜๋Ÿผ ๋ณด์ด๊ฒŒํ•˜๊ณ , ์Šคํฌ๋กคํ‘œ์‹œ๋ฅผ ์—†์• ๊ณ  ํ•˜์˜€์œผ๋‹ˆ ์•Œ์•„์„œ ๋” ๋งŒ๋“ค๊ณ  ์‹ถ์€ ์‚ฌ๋žŒ์ด ์žˆ์œผ๋ฉด๋” ๋งŒ๋“ค์–ด๋„ ์ƒ๊ด€์—†๋‹ค.

 

์‹œ๊ฐ„์ด ๋œ๋‹ค๋ฉด ํ˜•ํƒœ์†Œ ๋ถ„์„๋„ ํ•˜๊ณ , ๊ฐ„๋‹จํ•œ qna๋ฐ์ดํ„ฐ๋ฅผ ํ•™์Šต์‹œ์ผœ์„œ sub model๋กœ ๋‘๊ณ 

api์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜์—ฌ ์–‘์งˆ์˜ chatbot์„ ๋งŒ๋“ค๊ณ  ์‹ถ์—ˆ๋‹ค.

 

์ž ์‹œ ๋ฉˆ์ถฐ๋‘๊ณ  ๋‹ค์Œ์— ๋‹ค์‹œ ๋งŒ๋“ค์–ด๋ณด์•„์•ผ๊ฒ ๋‹ค.

 

 

 

 

728x90
๋ฐ˜์‘ํ˜•

๋Œ“๊ธ€