7. ๊ตฌ์กฐํ๋ ์ถ๋ ฅ - QuizGPT ๋ง๋ค๊ธฐ
๐ฏ ์ด ์ฑํฐ์์ ๋ฐฐ์ธ ๊ฒ
- LLM์ด ์์ฑํ๋ ํ ์คํธ๋ฅผ ์ฐ๋ฆฌ๊ฐ ์ํ๋ ์ ํํ ํ์(JSON)์ผ๋ก ์ ์ดํ๋ ๋ฐฉ๋ฒ
WikipediaRetriever
๋ฅผ ์ฌ์ฉํ์ฌ ์ธ๋ถ ์ง์ ์์ค์์ ๋์ ์ผ๋ก ์ฝํ ์ธ ๋ฅผ ๊ฐ์ ธ์ค๋ ๋ฐฉ๋ฒ- Pydantic/JSON Output Parser: ํ๋กฌํํธ ์์ง๋์ด๋ง๊ณผ ํ์๋ฅผ ํตํด LLM์ ์ถ๋ ฅ์ ๊ตฌ์กฐํํ๋ ๊ธฐ๋ฒ
- Function Calling: ๋ชจ๋ธ์ด ํน์ ํจ์์ ์ธ์(argument) ํ์์ ๋ง์ถฐ JSON์ ์์ฑํ๋๋ก ๊ฐ์ ํ๋ ๋ ๊ฐ๋ ฅํ๊ณ ์์ ์ ์ธ ๊ธฐ๋ฒ
- ๋ ๊ฐ์ ์ฒด์ธ(ํด์ฆ ์์ฑ, ์ฑ์ )์ ์ฐ๊ฒฐํ์ฌ ๋ณตํฉ์ ์ธ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌ์ถํ๋ ๋ฐฉ๋ฒ
- Streamlit์
st.form
์ ์ฌ์ฉํ์ฌ ์ฌ๋ฌ ๊ฐ์ ์ง๋ฌธ์ ํ ๋ฒ์ ์ ์ถํ๊ณ ์ฒ๋ฆฌํ๋ ๋ฐฉ๋ฒ
๋ฐ์ดํฐ ์์ค ์ฐ๊ฒฐ ๋ฐ ๋ชจ๋ธ ์ค์
๐ฏ ์ด๋ฒ ๋จ๊ณ์์ ๋ฐฐ์ธ ๊ฒ
WikipediaRetriever
๋ฅผ ์ฌ์ฉํ์ฌ ์ฌ์ฉ์๊ฐ ์ ๋ ฅํ ์ฃผ์ ์ ๋ํ Wikipedia ๋ฌธ์๋ฅผ ์ค์๊ฐ์ผ๋ก ๊ฐ์ ธ์ค๋ ๋ฐฉ๋ฒgpt-3.5-turbo-1106
๊ณผ ๊ฐ์ ์ต์ ๋ชจ๋ธ์ ์ฌ์ฉํ์ฌ ์ฑ๋ฅ๊ณผ ๋น์ฉ ํจ์จ์ฑ์ ๋์ด๋ ๋ฐฉ๋ฒ- Streamlit์
st.sidebar
์st.selectbox
๋ฅผ ํ์ฉํ์ฌ ์ฌ์ฉ์์๊ฒ ๋ฐ์ดํฐ ์์ค(ํ์ผ ๋๋ Wikipedia) ์ ํ ์ต์ ์ ์ ๊ณตํ๋ ๋ฐฉ๋ฒ
๐ 1๋จ๊ณ: Wikipedia Retriever ์ฐ๋
์ ์ฒด ์ฝ๋ (pages/03_QuizGPT.py):
1 | import streamlit as st |
๐ ์ฝ๋ ์์ธ ์ค๋ช
1. WikipediaRetriever
- LangChain์์ ์ ๊ณตํ๋ ํน์ํ ๊ฒ์๊ธฐ(Retriever)๋ก, ์ฌ์ฉ์์ ์ฟผ๋ฆฌ๋ฅผ ๋ฐ์ Wikipedia์์ ๊ด๋ จ ๋ฌธ์๋ฅผ ๊ฒ์ํ๊ณ
Document
๊ฐ์ฒด ๋ฆฌ์คํธ๋ก ๋ฐํํฉ๋๋ค. top_k_results
: ๊ฒ์ ๊ฒฐ๊ณผ ์ค์์ ์์ ๋ช ๊ฐ์ ๋ฌธ์๋ฅผ ๊ฐ์ ธ์ฌ์ง ์ง์ ํฉ๋๋ค.- ์ด๋ฅผ ํตํด ์ฌ์ฉ์๋ ํ์ผ ์ ๋ก๋๋ฟ๋ง ์๋๋ผ, ํน์ ์ฃผ์ ์ ๋ํด ์ฆ์์์ ํด์ฆ๋ฅผ ์์ฑํ ์ ์๊ฒ ๋ฉ๋๋ค.
2. GPT-4 Turbo (gpt-3.5-turbo-1106
)
- ์ด ๋ชจ๋ธ์ ๋ ๊ธด ์ปจํ ์คํธ ์๋์ฐ๋ฅผ ์ง์ํ๊ณ , JSON ๋ชจ๋์ ๊ฐ์ ์๋ก์ด ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ฉฐ, ์ด์ ๋ชจ๋ธ๋ณด๋ค ๋น์ฉ ํจ์จ์ ์ ๋๋ค. ๊ตฌ์กฐํ๋ ๋ฐ์ดํฐ๋ฅผ ๋ค๋ฃจ๋ ์ด๋ฒ ์ฑํฐ์ ๋งค์ฐ ์ ํฉํฉ๋๋ค.
โ ์ฒดํฌ๋ฆฌ์คํธ
-
wikipedia
๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ค์นํ๋์? -
WikipediaRetriever
๋ฅผ ์ฌ์ฉํ์ฌ ์ฃผ์ ๋ฅผ ๊ฒ์ํ๊ณDocument
๋ฅผ ์ฑ๊ณต์ ์ผ๋ก ๊ฐ์ ธ์๋์? -
st.selectbox
๋ฅผ ํตํด ๋ ๊ฐ์ง ๋ฐ์ดํฐ ์์ค(ํ์ผ, Wikipedia) ์ค ํ๋๋ฅผ ์ ํํ๋ UI๋ฅผ ๊ตฌํํ๋์?
Output Parsers: LLM ๊ธธ๋ค์ด๊ธฐ
๐ฏ ์ด๋ฒ ๋จ๊ณ์์ ๋ฐฐ์ธ ๊ฒ
- LLM์ด ์์ฑํ ํ๋ฒํ ํ ์คํธ๋ฅผ ์๊ฒฉํ JSON ํ์์ผ๋ก ๋ณํํ๋ 2๋จ๊ณ ์ฒด์ธ(์์ฑ -> ํฌ๋งทํ ) ์ค๊ณ
questions_prompt
: ์ฃผ์ด์ง ์ปจํ ์คํธ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํน์ ํ์์ ํ ์คํธ ํด์ฆ๋ฅผ ์์ฑํ๋๋ก ์ง์formatting_prompt
: ์์ฑ๋ ํ ์คํธ ํด์ฆ๋ฅผ JSON ํ์์ผ๋ก ๋ณํํ๋๋ก ์ง์JsonOutputParser
: LLM์ด ์์ฑํ JSON ๋ฌธ์์ด์ Python ๋์ ๋๋ฆฌ๋ก ํ์ฑํ๋ ๋ฐฉ๋ฒ
๐ 1๋จ๊ณ: 2๋จ๊ณ ์ฒด์ธ๊ณผ JSON ํ์ ๊ตฌํ
์ ์ฒด ์ฝ๋ (pages/03_QuizGPT.py):
1 | import json |
๐ ์ฝ๋ ์์ธ ์ค๋ช
1. ์ 2๋จ๊ณ ์ฒด์ธ์ ์ฌ์ฉํ๋๊ฐ?
LLM์๊ฒ ํ ๋ฒ์ ํ๋กฌํํธ๋ก ๋ณต์กํ ์์
(๋ด์ฉ ๊ธฐ๋ฐ ์ง๋ฌธ ์์ฑ + ์๋ฒฝํ JSON ํ์ ์ค์)์ ๋ชจ๋ ์ํค๋ฉด ์คํจํ ํ๋ฅ ์ด ๋์ต๋๋ค. ์์
์ ๋ ๋จ๊ณ๋ก ๋๋๋ฉด ๊ฐ ๋จ๊ณ์ ์ญํ ์ด ๋ช
ํํด์ ธ ํจ์ฌ ์์ ์ ์ธ ๊ฒฐ๊ณผ๋ฅผ ์ป์ ์ ์์ต๋๋ค.
questions_chain
: ๋ด์ฉ์ ์ง์คํ์ฌ ํด์ฆ ์ง๋ฌธ๊ณผ ๋ต๋ณ์ ํ ์คํธ๋ก ์์ฑํฉ๋๋ค.formatting_chain
: ์์ ์์ฑ๋ ํ ์คํธ๋ฅผ ์ ๋ ฅ์ผ๋ก ๋ฐ์, ์ค์ง JSON ํ์์ผ๋ก ๋ณํํ๋ ๋ฐ์๋ง ์ง์คํฉ๋๋ค.
2. JsonOutputParser
- LLM์ ์ข
์ข
JSON ์๋ต์
```json ... ```
์ฝ๋ ๋ธ๋ก์ผ๋ก ๊ฐ์ธ์ ๋ฐํํฉ๋๋ค. ์ด ํ์๋parse
๋ฉ์๋์์ ์ด๋ฌํ ๋ถํ์ํ ๋ฌธ์์ด์ ์ ๊ฑฐํ๊ณjson.loads()
๋ฅผ ์ฌ์ฉํ์ฌ ์์ํ JSON ๋ฌธ์์ด์ Python ๊ฐ์ฒด(๋์ ๋๋ฆฌ/๋ฆฌ์คํธ)๋ก ๋ณํํฉ๋๋ค.
โ ์ฒดํฌ๋ฆฌ์คํธ
- ์ง๋ฌธ ์์ฑ๊ณผ JSON ํฌ๋งทํ
์ ์ํ ๋ ๊ฐ์ ๋ถ๋ฆฌ๋
ChatPromptTemplate
์ ๋ง๋ค์๋์? -
BaseOutputParser
๋ฅผ ์์๋ฐ์JsonOutputParser
๋ฅผ ๊ตฌํํ๋์? - LCEL์ ์ฌ์ฉํ์ฌ
questions_chain
,formatting_chain
,output_parser
๋ฅผ ์์๋๋ก ์ฐ๊ฒฐํ๋์?
ํด์ฆ UI ๋ฐ ์ฑ์
๐ฏ ์ด๋ฒ ๋จ๊ณ์์ ๋ฐฐ์ธ ๊ฒ
@st.cache_data
๋ฅผ ์ฌ์ฉํ์ฌ ๋น์ฉ์ด ๋ง์ด ๋๋ ์ฒด์ธ ์คํ ๊ฒฐ๊ณผ๋ฅผ ์บ์ฑํ๋ ๋ฐฉ๋ฒst.form
์ ์ฌ์ฉํ์ฌ ์ฌ๋ฌ ๊ฐ์ ์ง๋ฌธ๊ณผ ๋ผ๋์ค ๋ฒํผ์ ๊ทธ๋ฃนํํ๊ณ ํ ๋ฒ์ ์ ์ถํ๋ ๋ฐฉ๋ฒ- ์ฌ์ฉ์๊ฐ ์ ์ถํ ๋ต์์ ์ ๋ต๊ณผ ๋น๊ตํ์ฌ ์ฆ์ ํผ๋๋ฐฑ์ ์ ๊ณตํ๋ ๋ฐฉ๋ฒ
๐ 1๋จ๊ณ: ํด์ฆ ํผ(Form) ์์ฑ ๋ฐ ์ฑ์ ๋ก์ง ๊ตฌํ
์ ์ฒด ์ฝ๋ (pages/03_QuizGPT.py):
1 | # ... (์ด์ ์ฝ๋) |
๐ ์ฝ๋ ์์ธ ์ค๋ช
1. st.form
with st.form(...)
๋ธ๋ก ์์ ์๋ ๋ชจ๋ ์์ ฏ๋ค์ ํ๋์ ํผ์ผ๋ก ๊ทธ๋ฃนํ๋ฉ๋๋ค. ์ฌ์ฉ์๊ฐ ์ฌ๋ฌ ๊ฐ์ ๋ผ๋์ค ๋ฒํผ์ด๋ ํ ์คํธ ์ ๋ ฅ์ ๋ณ๊ฒฝํด๋ ์ฑ์ ์ฌ์คํ๋์ง ์์ต๋๋ค.- ์ค์ง
st.form_submit_button()
์ ํด๋ฆญํ์ ๋๋ง ์คํฌ๋ฆฝํธ๊ฐ ์ฌ์คํ๋๋ฉฐ, ๊ทธ ์์ ์ ๋ชจ๋ ์์ ฏ ๊ฐ๋ค์ด ํ ๋ฒ์ ์ ์ถ๋ฉ๋๋ค. ์ด๋ ํด์ฆ๋ ์ค๋ฌธ์กฐ์ฌ์ ๊ฐ์ด ์ฌ๋ฌ ์ ๋ ฅ์ ํ ๋ฒ์ ์ฒ๋ฆฌํด์ผ ํ ๋ ๋งค์ฐ ์ ์ฉํฉ๋๋ค.
2. ์ฑ์ ๋ก์ง
st.radio
๋ ์ฌ์ฉ์๊ฐ ์ ํํ ๋ต๋ณ์ ๋ฌธ์์ด์value
์ ์ ์ฅํฉ๋๋ค.{"answer": value, "correct": True} in question["answers"]
์ฝ๋๋ ์ฌ์ฉ์๊ฐ ์ ํํ ๋ต๋ณ์ด ์ ๋ต ๋ฆฌ์คํธ ์์ ์๋์ง ํ์ธํ๋ ๊ฐ๊ฒฐํ๊ณ ํจ๊ณผ์ ์ธ ๋ฐฉ๋ฒ์ ๋๋ค.
โ ์ฒดํฌ๋ฆฌ์คํธ
-
run_quiz_chain
ํจ์์@st.cache_data
๋ฅผ ์ ์ฉํ์ฌ ํด์ฆ ์์ฑ์ ์บ์ฑํ๋์? -
st.form
์ ์ฌ์ฉํ์ฌ ํด์ฆ ์ ์ฒด๋ฅผ ๊ฐ์๋์? -
for
๋ฃจํ ์์์st.radio
๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ ์ง๋ฌธ์ ๋ํ ์ ํ์ง๋ฅผ ํ์ํ๋์? - ์ฌ์ฉ์์ ์ ํ(
value
)์ ์ ๋ต๊ณผ ๋น๊ตํ์ฌ โCorrect!โ ๋๋ โWrong!โ ๋ฉ์์ง๋ฅผ ํ์ํ๋์?
Function Calling: ๋ ์์ ์ ์ธ ๊ตฌ์กฐํ
๐ฏ ์ด๋ฒ ๋จ๊ณ์์ ๋ฐฐ์ธ ๊ฒ
- OpenAI์ Function Calling ๊ธฐ๋ฅ์ ์ฌ์ฉํ์ฌ LLM์ด ํญ์ ์ง์ ๋ JSON ์คํค๋ง์ ๋ง์ถฐ ์๋ตํ๋๋ก ๊ฐ์ ํ๋ ๋ฐฉ๋ฒ
๐ 1๋จ๊ณ: Function Calling์ผ๋ก ํด์ฆ ์์ฑํ๊ธฐ
์ ์ฒด ์ฝ๋ (notebook.ipynb):
1 | from langchain.chat_models import ChatOpenAI |
๐ ์ฝ๋ ์์ธ ์ค๋ช
1. Function Calling์ด๋?
Function Calling์ LLM์๊ฒ ๋จ์ํ ํ
์คํธ๋ก ๋ต๋ณํ๋ ๋์ , ์ฐ๋ฆฌ๊ฐ ์ ์ํ ํน์ ํจ์์ ์ธ์(arguments) ํ์์ ๋ง๋ JSON ๊ฐ์ฒด๋ฅผ ์์ฑํ๋๋ก ์์ฒญํ๋ ๊ธฐ๋ฅ์
๋๋ค. ์ด๋ LLM์ ์ถ๋ ฅ ํ์์ ๋งค์ฐ ์์ ์ ์ผ๋ก ์ ์ดํ ์ ์๋ ๊ฐ๋ ฅํ ๋ฐฉ๋ฒ์
๋๋ค.
- ์ฅ์ : ๋ณต์กํ ํ๋กฌํํธ ์์ง๋์ด๋ง(์: 2๋จ๊ณ ์ฒด์ธ)์ด๋ ์ถ๋ ฅ ํ์ ์์ด๋, ๋ชจ๋ธ์ด ๊ฑฐ์ ํญ์ ์๋ฒฝํ JSON ์คํค๋ง๋ฅผ ์ค์ํ๋๋ก ๊ฐ์ ํ ์ ์์ต๋๋ค.
2. .bind(function_call=...)
- LCEL์
.bind()
๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ LLM์ ํธ์ถํ ๋ ํน์ ํจ์๋ฅผ ํธ์ถํ๋๋ก ์ค์ ํ ์ ์์ต๋๋ค. function_call={"name": "create_quiz"}
: LLM์๊ฒcreate_quiz
ํจ์์ ์ธ์ ํ์์ ๋ง์ถฐ ์๋ตํ๋ผ๊ณ ๊ฐ์ ํฉ๋๋ค.functions=[function]
: LLM์๊ฒcreate_quiz
ํจ์์ ์คํค๋ง(๊ตฌ์กฐ)๋ฅผ ์๋ ค์ค๋๋ค.
3. ๊ฒฐ๊ณผ
- ์ฒด์ธ์ ์คํํ๋ฉด,
response
์content
๋ ๋น์ด์๊ณ ,additional_kwargs["function_call"]["arguments"]
์์ ์ํ๋ JSON ํ์์ ๋ฌธ์์ด์ด ๋ด๊ฒจ ๋ฐํ๋ฉ๋๋ค.
โ ์ฒดํฌ๋ฆฌ์คํธ
- JSON ์คํค๋ง ํ์์ผ๋ก ํจ์์ ์ด๋ฆ, ์ค๋ช , ํ๋ผ๋ฏธํฐ๋ฅผ ์์ธํ ์ ์ํ๋์?
-
.bind()
๋ฅผ ์ฌ์ฉํ์ฌ LLM์ ํจ์ ์คํค๋ง์ ํจ์ ํธ์ถ์ ๊ฐ์ ํ๋์? -
response.additional_kwargs
์์ ์์ฑ๋ JSON ๊ฒฐ๊ณผ๋ฅผ ์ฑ๊ณต์ ์ผ๋ก ์ถ์ถํ๋์?
์ถ์ฒ : https://nomadcoders.co/fullstack-gpt