반응형
김한호, 최태온, 윤택한, 『Hey, 파이썬! 생성형 AI 활용 앱 만들어 줘』, 성안당(2024), p142-333.
- ChatGPT 가격: https://openai.com/api/pricing/
- GPT Playground: 프롬프트를 쉽게 테스트하고, API 작동 방식을 익힐 수 있는 웹 기반 서비스
- getpass.getpass(): 사용자의 입력을 받을 때까지 기다렸다가 사용자의 입력이 완료되면 그 값을 변수에 대입하는 기능
- OpenAI.chat.completions.create()
- max tokens: chatGPT가 최대로 답변할 수 있는 토큰 수 (default: 무한)
- temperature: 답변에 창의적 일지, 정확할지 결정, 값이 높을수록 창의적 (0~2, default: 1)
- top_p: 토큰의 확률 분포 제한, 응답의 다양성을 제어 (0~1, default: 1)
- presence_penalty: 이미 나온 내용을 반복하는 것에 대한 페널티 부여 (-2~2, default: 0)
- frequency_penalty: 자주 나타나는 단어나 구절을 반복하는 것에 대한 페널티 부여 (-2~2, default: 0)
- n: 생성할 응답의 개수 (default: 1)
- stop: 특정 문자열이나 문자열 목록을 만나면 응답 중단 (default: null)
그라디오(Gradio)
- 사용자가 UI를 빠르게 제작하여 ML or API 등을 사용할 수 있게 해주는 파이썬 오픈소스 패키지
- gradio.Interface(): 파이썬으로 작성한 함수를 미리 설정된 UI와 함께 제공하는 역할
- fn: 그라디오에서 매핑된 함수명 (호출할 함수명)
- inputs: input에 사용할 컴포넌트
- outputs: output에 사용할 컴포넌트
- gradio.Blocks(): 유연하게 레이아웃을 구성하는 데 사용
- gradio.Tab(): 레이아웃을 탭으로 구성할 때 사용
- gradio.Row(): 앱 안에서 수평으로 컴포넌트를 배치할 때 사용
- gradio.Column(): 앱 안에서 수직으로 컴포넌트를 배치할 때 사용
- gradio.ChatInterface(): 챗봇을 구현할 때 사용
- fn: 버튼 클릭 시, 호출되는 함수
- textbox: 대화 입력 창 설정
- title: 챗봇 제목
- description: 챗봇 설명
- theme: 테마
- retry_btn: 마지막에 물어본 대화 다시하기 설정
- undo_btn: 마지막 대화 삭제
- clear_btn: 대화 전체 삭제
- additional_inputs: 추가 블록 정의
- gradio.Group(): 레이아웃을 구성할 때나 컴포넌트들을 여백 없이 결합할 때 사용
- 컴포넌트
- gradio.Text(), gradio.Textbox(): 텍스트
- gradio.Dataframe(): pandas dataframe
- gradio.Image(): 이미지
- gradio.Video(): 비디오
- gradio.Audio(): 오디오
- gradio.Checkbox(): 체크 박스
- gradio.CheckboxGroup(): select box
- gradio.Slider(): 슬라이더 바 (min~max)
- gradio.Dropdown(): dropdown menu
- gradio.Button(): 버튼을 클릭할 때 특정 이벤트를 수행할 수 있음
- gradio.ClearButton(): 내용 초기화 버튼
Bot 만들기
- Code: 🔗
1. 상담봇
from openai import OpenAI
import gradio as gr
client = OpenAI(api_key="")
# chat + response
def counseling_bot_chat(message, chat_history):
if message == "":
return "", chat_history
else:
completion = client.chat.completions.create(
model="gpt-3.5-turbo",
messages=[
{"role": "system", "content": "당신은 헤이마트의 상담원입니다. 마트 상품과 관련되지 않은 질문에는 정중히 거절하세요."},
{"role": "user", "content": message}
])
chat_history.append([message, completion.choices[0].message.content])
return "", chat_history
# chat history undo
def counseling_bot_undo(chat_history):
if len(chat_history) > 1:
chat_history.pop()
return chat_history
# chat reset
def counseling_bot_reset(chat_history):
chat_history = [[None, "안녕하세요, 헤이마트입니다. 상담을 도와드리겠습니다."]]
return chat_history
# Layout
with gr.Blocks(theme=gr.themes.Default()) as app:
with gr.Tab("상담봇"):
gr.Markdown(
value="""
# <center>상담봇</center>
<center>헤이마트 상담봇입니다. 마트에서 판매하는 상품과 관련된 질문에 답변드립니다.</center>
"""
)
cb_chatbot = gr.Chatbot(
value = [[None, "안녕하세요, 헤이마트입니다. 상담을 도와드리겠습니다"]], # 사용자 입력 데이터, 챗봇 입력 데이터
show_label=False # 채팅 레이아웃 좌측 상단의 작은 Chatbot label 제거
)
with gr.Row():
cb_user_input = gr.Text(
lines=1, # 화면에 표시할 입력칸의 행 개수
placeholder="입력 창", # 입력 칸에 예시로 표시할 텍스트
container=False, # 텍스트 박스의 테두리 표시 여부
scale=9 # 같은 레이아웃 영역 안의 컴포넌트들 사이에서 차지할 공간의 비중 (e.g. 9 > gr.Row() 영역 내 컴포넌트는 9:1 비중)
)
cb_send_btn = gr.Button(
value="보내기", # 버튼에 들어갈 글자의 값
scale=1,
variant="primary", # gr.Blocks()에서 사전 정의된 테마의 설정값을 참조하여 버튼의 스타일을 변경 (primary: 주황, secondary: 회색, neutral: 흰색, stop: 핑크)
icon="https://cdn-icons-png.flaticon.com/128/12439/12439334.png" # 버튼의 텍스트 앞에 이미지
)
with gr.Row():
# create button, event listener
gr.Button(value="↩ 되돌리기").click(fn=counseling_bot_undo, inputs=cb_chatbot, outputs=cb_chatbot)
gr.Button(value="🔄 초기화").click(fn=counseling_bot_reset, inputs=cb_chatbot, outputs=cb_chatbot)
# define event
cb_send_btn.click(fn=counseling_bot_chat, inputs=[cb_user_input, cb_chatbot], outputs=[cb_user_input, cb_chatbot]) # 보내기 버튼 클릭 이벤트 정의
cb_user_input.submit(fn=counseling_bot_chat, inputs=[cb_user_input, cb_chatbot], outputs=[cb_user_input, cb_chatbot]) # 입력 창에 글을 쓴 후 키보드 enter를 눌렀을 때 발생할 이벤트 정의
pass
with gr.Tab("번역봇"):
pass
with gr.Tab("소설봇"):
pass
app.launch()
2. 번역봇
import gradio as gr
from openai import OpenAI
client = OpenAI(api_key="")
def translate_bot(output_conditions, output_language, input_text):
if input_text == "":
return ""
else:
if output_conditions != "":
output_conditions == "번역할 때의 조건은 다음과 같습니다. " + output_conditions
completion = client.chat.completions.create(
model="gpt-3.5-turbo",
messages=[
{"role": "system", "content": "당신은 번역가입니다. 입력한 언어를 다른 설명없이 곧바로 {0}로 번역해서 알려 주세요. 번역이 불가능한 언어라면 번역이 불가능하다고 말한 후 그 이유를 설명해 주세요. {1}".format(output_language, output_conditions)},
{"role": "user", "content": input_text}
])
return completion.choices[0].message.content
#레이아웃
with gr.Blocks(theme=gr.themes.Default()) as app:
with gr.Tab("번역봇"):
gr.Markdown(
value="""
# <center>번역봇</center>
<center>다국어 번역봇입니다.</center>
"""
)
with gr.Row():
tb_output_conditions = gr.Text(
label="번역 조건",
placeholder="예시: 자연스럽게",
lines=1,
max_lines=3 # 최대 입력할 수 있는 줄 개수
)
tb_output_language = gr.Dropdown(
label="출력 언어",
choices=["한국어", "영어", "일본어", "중국어"], # dropdown list 설정
value="한국어", # default value
allow_custom_value=True, # 번역 가능한 국가 리스트 외의 국가도 직접 설정 가능하도록 설정
interactive=True # 상호 작용 활성화
)
tb_submit = gr.Button(
value="번역하기",
variant="stop"
)
with gr.Row():
tb_input_text = gr.Text(
placeholder="번역할 내용을 적어 주세요.",
lines=10,
max_lines=20, # 유동적인 UI (10~20 lines)
show_copy_button=True,
label=""
)
tb_output_text = gr.Text(
lines=10,
max_lines=20, # 유동적인 UI (10~20 lines)
show_copy_button=True,
label="",
interactive=False # 번역된 내용이 편집되지 않도록 설정
)
# event listener
tb_submit.click(
fn=translate_bot,
inputs=[tb_output_conditions, tb_output_language, tb_input_text],
outputs=tb_output_text
)
# Execution
app.launch()
3. 소설봇
import gradio as gr
from openai import OpenAI
client = OpenAI(api_key="")
def novel_bot(model, temperature, detail):
completion = client.chat.completions.create(
model=model,
temperature=temperature,
messages=[
{"role": "system", "content": "당신은 소설가입니다. 요청하는 조건에 맞춰 소설을 작성해 주세요."},
{"role": "user", "content": detail}
]
)
return completion.choices[0].message.content
with gr.Blocks(theme=gr.themes.Default()) as app:
with gr.Tab("소설봇"):
gr.Markdown(
value="""
# <center>소설봇</center>
<center>소설을 생성해주는 봇입니다.</center>
"""
)
with gr.Accordion(label="사용자 설정"): # 접었다 폈다 할 수 있는 기능
with gr.Row():
with gr.Column(scale=1):
nb_model = gr.Dropdown(
label="모델 선택",
choices=["gpt-3.5-turbo", "gpt-3.5.turbo-16k", "gpt-4", "gpt-4-32k", "gpt-4-1106-preview"],
value="gpt-4-1106-preview",
interactive=True
)
nb_temperature = gr.Slider(
label="창의성",
info="숫자가 높을 수록 창의적",
minimum=0,
maximum=2,
step=0.1,
value=1,
interactive=True
)
nb_detail = gr.Text(
container=False, # container를 없애서 공간을 확보
placeholder="소설의 세부적인 설정을 작성합니다.",
lines=8,
scale=4
)
nb_submit = gr.Button(
value="생성하기",
variant="stop"
)
nb_output = gr.Text(
label="",
placeholder="이곳에 소설의 내용이 출력됩니다.",
lines=10,
max_lines=200,
show_copy_button=True
)
# event listener
nb_submit.click(
fn=novel_bot,
inputs=[nb_model, nb_temperature, nb_detail],
outputs=nb_output
)
# Execution
app.launch()
LangChain
LLM과 외부의 도구(web site, pdf reader, etc)를 체인으로 엮은 것처럼 결합해 주는 SDK의 한 종류
- langchain.callbacks.streaming_stdout.StreamingStdOutCallbackHandler: 실시간으로 타이핑하듯이 답변이 나옴
- langchain.prompts.PromptTemplate: 프롬프트 템플릿, 생성할 때, {}를 이용하여 매개변수 생성 가능
- langchain.prompts.ChatPromptTemplate: Chat LLM 모델에 사용되는 SystemMessage, HumanMessage 등의 프롬프트를 생성하는 데 사용
- Few shot: 언어 모델을 사용하여 결과값을결괏값을 추론할 때 추론된 결괏값을 원하는 형태로 나타나게 하는 것
- langchain.prompts.few_shot.FewShotPromptTemplate
- RAG(Retreival Augmented Generation): 외부 소스에서 검색하거나 가져온 정보를 LLM 모델의 인풋으로 적용하여 정확하고 맥락에 맞는 답을 할 수 있도록 LLM의 능력을 보완해 주는 역할
- document loading
- text file: langchain.document_loaders.TextLoader
- csv: langchain.document_loaders.csv_loader.CSVLoader
- pdf: langchain.document_loaders.PyPDFLoader
- document transformers: 문서 변환기
- langchain.text_splitter.RecursiveCharacterTextSplitter: 설정한 사이즈에 맞게 chunk로 분할
- langchain.embeddings.OpenAIEmbeddings: openAPI에서 제공되는 embedding
- langchain.vectorstores.Chroma: Chroma Vector DB
- document loading
- Agent: LLM에서 Tool을 사용할 순서를 결정하는 역할
- 최종 답변에 도달할 때까지 아래 과정을 반복
- Input(작업 할당) ➡️ Action(툴 결정) ➡️ Observation(툴 출력 결과 확인) ➡️ Thought(최종 답변을 얻기 위해 작업 할당)
- LangChain agent type
- Zero-shot ReAct: 작업과 도구 설명을 보고 사용할 도구 결정
- Structured input ReAct: input이 여러 개인 툴을 사용할 때
- Conversational: 대화 + ReAct로 대화를 저장하기 위한 메모리 필요
- Self-ask with search: 인터넷 검색 후 답변하는 에이전트, 검색 툴 필요
- ReAct document store: 문서 저장소 + 리액트, 검색 툴 필요
- LangChain tool: https://python.langchain.com/docs/integrations/tools/
- 최종 답변에 도달할 때까지 아래 과정을 반복
- Chain: 모듈을 체인으로 연결할 수 있는 인터페이스를 제공하여 모듈을 호출할 수 있도록 함
- langchain.chains.SimpleSequentialChain
- Memory: 대화를 제대로 이어서 하려면 기존의 대화를 기억해야 함
- langchain.memory.ConversationBufferMemory: 대화 내용을 그대로 저장, 메모리에 직접 데이터를 입력할 수 있음
- langchain.memory.ConversationBufferWindowMemory: 지정한 개수만큼의 대화만 기억
- langchain.memory.ConversationTokenBufferMemory: 대화를 기억할 때 토큰의 수로 기억
- langchain.memory.ConversationSummaryBufferMemory: 이전의 대화 내용을 LLM을 이용해 요약해서 기억
반응형
'AI > LLM' 카테고리의 다른 글
『Hey, 파이썬! 생성형 AI 활용 앱 만들어 줘』 후기 (2) | 2024.10.09 |
---|---|
『Hey, 파이썬! 생성형 AI 활용 앱 만들어 줘』 Part 4. 챗GPT와 스테이블 디퓨젼으로 책 만들기 (3) | 2024.10.09 |
『Hey, 파이썬! 생성형 AI 활용 앱 만들어 줘』 Part 3. 음성 인식 AI 비서 만들기 (2) | 2024.10.08 |
『Hey, 파이썬! 생성형 AI 활용 앱 만들어 줘』 Part 1. 파이썬 (3) | 2024.09.28 |
댓글