Ssul's Blog
[ChatGPT] OpenAI function_call 제대로 이해하기 본문
0. 들어가며,
앞전 글(https://issul.tistory.com/430)에서 function_call로 반말하기 챗봇을 작성하였는데, 여전히 헤깔리는 부분이 있어서, 내 머리속에서도 정리할겸 제대로 어떻게 돌아가는지 이해해보고자 한다.
내가 원하는 상황은 이런 것이다. ChatGPT가 평소 대화하는 것처럼 대화하다가,
- 오늘 서울 날씨를 물어보면, 정확하게 대답을 해주고,
- 특정 대답결과를 파일로 저장하기도 해주는 것이다.
그러면 평소처럼 대화도 가능해야 하고, 특정 상황이 되었을때는 function_call이 호출되는 구조이다. 그럼 차근차근 어떻게 function_call이 작동하는지 알아보자.
순서1. 일반대화를 하다가, 특정상황이 되었을때 function_call작동
이게 기존의 개발과는 다른 구조이다. 기존 개발에선 다양한 조건문으로 해당 상황을 파악하고, 함수를 호출했다면, 그것을 LLM이 해주는 것이다.
GPT는 평소와 같이 나와 대화를 계속한다. 그러다 내가 "오늘 서울 날씨가 어떻게 됨?"과 같은 맥락의 대화(꼭 저 문장일 필요가 없다. 이게 중요)를 했을때, function_call이 호출된다. 아래 그림처럼 평소에는 계속 일반대화를 하다, 내가 function_call로 지정된 맥락의 질문을 했을때 아래로 넘어간다.
그리고 실제 개발시에는 message.content에 내용이 없거나, message.function_call이 있다면 아래로 가게 된것
if not message.content:
if message.get("function_call"):
과 같은 코드로 펀션콜 여부 판단. 만약 아니면, message.content내용 반환하면서 일반적인 응답 진행하면 됨.
순서2. function_call이 호출되면, gpt가 알맞은 함수명과 매개변수를 생성하여 message.function_call에 담아서, 전달해줌
그림처럼 펀션콜이 호출되면, 지정해두었던 함수명과 함수 호출시 사용될 매개변수를 함께 전달한다.
예를 들어 대화중 "오늘 서울날씨는?"이라는 문장이 나오면,
weatherAPI를 호출하는 함수와, '2/1'(오늘날짜)과 '서울'이라는 매개변수를 gpt가 알아서 생성해서 넘겨준다.
이게 중요한 포인트이다. 사람이 오늘날짜, 서울을 생성하는 것이 아닌, GPT라는 LLM이 알아서 찾아서 전달해주는 것이다.
순서3. 전달받은 함수명과 매개변수를 사용해서, 기능을 실행
전달받은 함수명과 매개변수를 사용하여, 개발해 놓은 로직대로 실행
날씨를 검색할 수도 있고, 파일을 생성/저장 할 수도 있다.
순서4. 로직의 결과를 포함해서 ChatGPT에게 다시 전달
함수를 실행한 것으로 끝낼수도 있지만, 조금 더 실용성 있는 서비스가 되려면, 날씨검색/파일저장 이후에도 챗봇서비스는 계속 이어져야 한다. 물론 날씨를 검색한 것도, 파일을 저장한 그동안의 맥락도 이해 할수 있어야 한다.
그럴려면 아래와 같은 작업이 진행되어야 한다.
message.content가 없어서 function_call이 호출되었던 메세지도 입력하고,
function_call을 통해서 내가 개발한 로직을 수행한 결과 메세지 = function_response
"2/1, 서울 맑음" 또는 "파일 저장에 성공하였습니다" 또는 "파일 저장에 실패하였습니다"와 같은 내용을
role, name, content로 저장해서, GPT에게 맥락을 알려줘야 합니다.
이렇게 저장된 메세지log를 GPT에게 전달합니다.
순서5. GPT는 그동안 있었던 모든일을 확인하고, 적절한 대답을 사용자에게 전달합니다.
- 그동안 있었던 일반대화
- 펀션콜을 호출했던 일
- 펀션이 진행되어 나온 결과메세지
등을 기반으로 사용자에게 응답을 합니다.
"오늘 서울의 날씨는 맑을듯" 또는 "생성한 메세지를 파일로 저장 성공하였습니다"와 같은 응답 실행
[참고 코드- 도서 Do it! 챗GPT&파이썬으로 AI 직원 만들기에서 일부]
message_log = [
{
"role": "system",
"content": '''
You are a DJ assistant who creates playlists. Your user will be Korean, so communicate in Korean, but you must not translate artists' names and song titles into Korean.
- At first, suggest songs to make a playlist based on users' request. The playlist must contains the title, artist, and release year of each song in a list format. After you show a playlist to the user, You must ask users if they want to save the playlist as follow: "이 플레이리스트를 CSV로 저장하시겠습니까?"
- After saving the playlist as a CSV file, you must show the CSV file path and ask the users if they would like to download the MP3 files of the songs in the playlist.
- After downloading the mp3 files in the playlist, you must ask the users if they would like to generate album cover images for the songs.
'''
}
]
functions = [
{
"name": "save_playlist_as_csv",
"description": "Saves the given playlist data into a CSV file when the user confirms the playlist.",
"parameters": {
"type": "object",
"properties": {
"playlist_csv": {
"type": "string",
"description": "A playlist in CSV format separated by ';'. It must contains a header and the release year should follow the 'YYYY' format. The CSV content must starts with a new line. The header of the CSV file must be in English and it should be formatted as follows: 'Title;Artist;Released'.",
},
},
"required": ["playlist_csv"],
},
},
]
- gpt 시스템 메세지 및 function 설정
response=openai.ChatCompletion.create(
model=gpt_model,
messages=message_log,
temperature=temperature,
functions=functions,
function_call='auto',
)
response_message=response["choices"][0]["message"]
# 일반응답이 아닌, functioncall응답일 경우
if response_message.get("function_call"):
# 여기에 사용할 함수를 배치
available_functions={
"save_playlist_as_csv": save_playlist_as_csv,
"download_songs_in_csv": download_songs_in_csv,
"generate_images_for_songs": generate_images_for_songs,
}
# functioncall응답이므로, 함수 이름 가져오기
function_name=response_message["function_call"]["name"]
function_to_call=available_functions[function_name]
#함수 호출시 사용될 매개변수 가져오기: gpt가 알아서 만들어줌
function_args=json.loads(response_message["function_call"]["arguments"])
# gpt가 응답한 function name, argument를 사용하여 함수 호출 > csv파일 생성
function_response = function_to_call(**function_args)
if function_name == 'save_playlist_as_csv':
function_response, csv_file_path=function_response
# 지난 답변 추가
message_log.append(response_message)
# 함수 실행결과도 추가
message_log.append(
{
"role": "function",
"name": function_name,
"content": f'{function_response}',
}
)
# 새로운 답변 받기
response=openai.ChatCompletion.create(
model=gpt_model,
messages=message_log,
temperature=temperature,
)
# 일반응답
return response.choices[0].message.content
- 일상의 대화인지, 펀션콜을 호출해야 하는지 판단
- 펀션콜의 경우, gpt가 준 함수명과 매개변수로 함수 호출
- 함수의 결과값을 message_log에 저장
- 지금가지 저장된값을 gpt에 전달하여, 맥락을 이해하는 답변을 받아오기
'AI & ML > 사용하기' 카테고리의 다른 글
[Langchain #1] 기본채팅부터 커스텀parser사용 (0) | 2024.02.13 |
---|---|
Fine-tuning with LoRA(PEFT)로 스팸문자 분류기 만들기 (2) | 2024.02.04 |
[ChatGPT] OpenAI의 function_call활용해서, 반말 챗봇 만들기 (0) | 2024.01.11 |
[NLP, Fine-Tuning] 허깅페이스(Huggingface) 사용법 (0) | 2024.01.10 |
[NLP, Fine-Tuning] ChatGPT 만들기(w Llama2) (0) | 2024.01.02 |