안녕하세요.
이번 포스팅에서는 유튜브를 보다가 재밌는 걸 발견해서 LLM을 활용한 애플리케이션 간단하게 제작하고 시연해보고자 합니다.
요즘 어딜 가든 핫한 대화의 주제가 되는 ChatGPT를 만든 회사인 OpenAI의 API를 이용해서 개발해보았습니다.
OpenAI의 API를 사용하기 위해서는 먼저 결제가 필요합니다.
API 사용은 아래 사이트에서 신청 가능합니다.
아이디어 참고 및 전체적인 프로세스는 아래 유튜브를 참고했습니다.
https://www.youtube.com/watch?v=t3O-0mzLJzI
전체 프로세스
코드는 파이썬으로 작성했으며 웹페이지는 dash 라이브러리를, LLM과 질의는 파이썬 기반의 랭체인(langchain)을 사용했습니다.
프로세스는 다음과 같습니다.
1. dash로 생성한 웹페이지에 파일(csv, excel)을 업로드 하면 랭체인을 통해 해당 파일을 텍스트 형식으로 LLM에 전달합니다.
2. LLM은 사용자의 질의를 받아서 질의에 대한 차트를 생성하는 코드를 작성합니다. 답변 결과는 메모리에 저장합니다.
3. 생성된 코드를 dash에 전달해서 차트를 생성합니다. 만약 올바른 코드가 전달되지 않는다면, 예외 처리를 통해 다시 질의합니다.
4. 새로운 사용자 질의를 받고, 기존에 메모리에 저장된 문답데이터를 참고해서 새로운 답변을 반환합니다.
시연
다음은 시연화면입니다.
1) 기본 화면
2) 파일 업로드
3) 질의
4) 결과
5) 재요청
코드
1) llm 설정
llm = ChatOpenAI(
temperature=0,
max_tokens=2048,
model_name='gpt-3.5-turbo'
)
결제한 openai api key를 전역변수로 설정해서 llm 모델을 가져옵니다.
2) 질의 템플릿 설정
prompt = ChatPromptTemplate.from_messages(
[
# 전역설정
(
'system',
'당신은 데이터 시각화 전문가입니다.'
'{data}를 요청에 맞게 시각화해주세요 답변은 코드로만 반환합니다.'
'시각화 라이브러리는 python의 plotly.express입니다.'
'그래프를 그리는 코드만 작성해주세요.'
'코드에 import plotly문, show() 함수를 포함하지 않습니다.'
'당신의 코드는 파이썬 exec() 함수 안에서 실행되며 리턴은 fig 객체 하나입니다.'
),
# 이전 대화 설정
MessagesPlaceholder(variable_name='history'),
# 질문
('human', '{input}')
]
)
이전 대화를 저장하는 템플릿 사용을 위해 MessagesPlaceholder 클래스를 사용합니다. 템플릿을 생성하는데 가장 오랜 시간이 걸렸습니다. 예외 상황이 너무 많아 하나씩 찾아서 추가하는 데 오래 걸렸습니다.
dash에 차트만 추가하기 위해 fig 객체 하나만 반환하도록 했습니다.
3) 대화 결과 메모리 저장
with_message_history = (
RunnableWithMessageHistory( # RunnableWithMessageHistory 객체 생성
runnable, # 실행할 Runnable 객체
get_session_history, # 세션 기록을 가져오는 함수
input_messages_key="input", # 입력 메시지의 키
history_messages_key="history", # 기록 메시지의 키
)
)
session 저장소를 만들어주는 get_session_history 함수를 만들어서 history에 저장해주는 코드입니다.
4) 질의 시작, 데이터 파싱
try:
response = with_message_history.invoke(
{"data": df, "input": query},
config={"configurable": {"session_id": "choi"}},
)
# gpt에게 반환받은 결과 저장
local_vars = {}
code_block_match = re.search(r'```(?:python)?(.*?)```', response.content, re.DOTALL | re.IGNORECASE)
if code_block_match:
python_code = code_block_match.group(1).strip()
print(python_code)
else:
raise Exception
exec(python_code, globals(), local_vars)
except Exception as e:
print(e)
fig = local_vars['fig']
gpt의 반환값은 텍스트이기 때문에 "코드"만 반환하도록 역할을 부여해야합니다. 코드만 반환하면 파이썬의 exec 함수를 사용해서 파이썬 변수에 문자열의 결과를 반환할 수 있습니다.
5) 데이터 렌더링
@app.callback(
Output('graph', 'children'),
Input('submit-query', 'n_clicks'),
State('gpt-query', 'value'),
State('upload-data', 'contents'),
State('upload-data', 'filename'),
)
def update_graph(n_clicks, query, contents, filename):
if n_clicks > 0 and contents is not None and query is not None:
df = parse_contents(contents, filename)
if df is not None:
try:
fig = invoke(query=query, df=df)
return fig
except Exception as e:
return html.Div(['그래프를 생성하는데 오류가 발생했습니다.'])
return html.Div()
invoke함수가 gpt에게 질의를 하고 결과를 받는 함수입니다. dash에서 제공하는 콜백 함수를 이용해서 gpt로부터 받은 fig 객체를 리턴해줍니다.
6) 차트 생성
dcc.Loading(
id='loading',
type='default',
children=html.Div(id='graph', style={'marginTop': '20px', 'marginBottom': '20px'})
)
dash의 dcc 함수를 통해 차트를 생성해줍니다. callback으로 생성했기 때문에 서버의 재시작 없이 차트가 바로 변경 가능합니다.
이렇게 openai api와 dash 라이브러리를 이용한 간단한 차트 생성기를 만들어보았습니다.
솔직히 기존에 사용하던 chat gpt의 성능을 보고 여러번 질의했을 때 1~2번 정도 정확하게 만들어주겠지라는 생각을 가지고 있었는데, 생각 이상으로 좋은 결과가 나와 놀랐습니다. 앞으로 이런 LLM서비스가 더 발전되면 더 다양한 애플리케이션을 손쉽게 만들 수 있겠다는 생각이드네요.
참고자료 :
https://wikidocs.net/book/14314
https://dash.plotly.com/basic-callbacks
무료 ChatGPT
'프로그래밍' 카테고리의 다른 글
[Springboot] 공통 응답 코드 설정 (0) | 2024.10.16 |
---|---|
[SQL] 특정 문자 이후의 모든 문자열 제거 (1) | 2024.10.07 |
[sts] Maven 업데이트 시 무한 로딩 (0) | 2024.07.18 |
[kubernetes] 스테이트풀셋(Statefulset) (0) | 2024.07.10 |
[kubernetes] 쿠버네티스 기본 용어 정리 (0) | 2024.06.19 |