Functions, Tools and agents with Langchain - 1

이정진·2023년 11월 10일
1

DeepLearning.AI의 강의 정리내용 입니다.

L1. OpenAI Function Calling

  • GPT-4-0613 and GPT-3.5 Turbo-0613 새로 출시되면서 생긴 기능
  • Function Calling을 사용하면, 질문에 적합한 애플리케이션 함수와 매개변수를 추천받을 수 있다.
  • User prompt로부터 함수를 호출할지 여부를 결정하고, 구조화된 호출 요청을 응답한다.

사용목적

  • Function calling 이전에는 fine-tuning이나 embedding이 잘 되어 있어야 답이 가능했음
  • 하지만 Function calling을 통해서 대답하는 대신 함수 실행 여부를 물어보게 됨. 이를 통해 대화에 딱 들어맞게 함수의 결과를 사용할 수 있게 된다.
    Function Calling을 사용하지 않았을 때
    Function Calling을 사용했을 때

예제

import json

# 그냥 날씨 정보를 리턴하는 예시용 함수
# 백앤드 API나 외부 API로 구현해서 사용 가능하다.
def get_current_weather(location, unit="fahrenheit"):
    """Get the current weather in a given location"""
    weather_info = {
        "location": location,
        "temperature": "72",
        "unit": unit,
        "forecast": ["sunny", "windy"],
    }
    return json.dumps(weather_info)

# define a function
functions = [
    {
        "name": "get_current_weather",
        "description": "Get the current weather in a given location",
        "parameters": {
            "type": "object",
            "properties": {
                "location": {
                    "type": "string",
                    "description": "The city and state, e.g. San Francisco, CA",
                },
                "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]},
            },
            "required": ["location"],
        },
    }
]

messages = [
    {
        "role": "user",
        "content": "What's the weather like in Boston?"
    }
]

import openai

response = openai.ChatCompletion.create(
    model="gpt-3.5-turbo-0613",
    messages=messages,
    functions=functions
)
print(response)

# 결과
{
  "id": "chatcmpl-8IEB6wKaKL910tyNmUowMenD5JsbK",
  "object": "chat.completion",
  "created": 1699355096,
  "model": "gpt-3.5-turbo-0613",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": null, # 콘텐츠 대신 function call이 호출된 걸 볼 수 있음
        "function_call": {
          "name": "get_current_weather", # 함수 이름
          "arguments": "{\n\"location\": \"Boston, MA\"\n}" # 프롬프트의 Boston을 보고 맞는 인자를 반환해줌
        }
      },
      "finish_reason": "function_call"
    }
  ],
  "usage": {
    "prompt_tokens": 82,
    "completion_tokens": 17,
    "total_tokens": 99
  }
}
# 결과를 보면,
json.loads(response_message["function_call"]["arguments"])
{'location': 'Boston, MA'}

# function call 을 통해 받은 인자를 사용
args = json.loads(response_message["function_call"]["arguments"])
get_current_weather(args)

# function_call 모드가 auto라 함수 호출 여부를 알아서 판단해주는 걸 볼 수 있따.
messages = [
    {
        "role": "user",
        "content": "hi!",
    }
]
response = openai.ChatCompletion.create(
    model="gpt-3.5-turbo-0613",
    messages=messages,
    functions=functions,
    function_call="auto", # 또는 none 가능
		# function_call = {"name": "get_current_weather"} # 함수를 강제 지정할 수 있음, 사실 여러개도 가능
)
print(response)
# 결과
{
  "id": "chatcmpl-8IECACxqm3XVh3WDEUMpvbBi0L6Mv",
  "object": "chat.completion",
  "created": 1699355162,
  "model": "gpt-3.5-turbo-0613",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": "Hello! How can I assist you today?" #  function_call 이 없고 content가 반환됨
      },
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_tokens": 76,
    "completion_tokens": 10,
    "total_tokens": 86
  }
}

# 그다음 메시지에 Function calling에서 온 응답을 추가해주고 실행하면,
messages.append(response["choices"][0]["message"]) # Function calling 결과
args = json.loads(response["choices"][0]["message"]['function_call']['arguments'])
observation = get_current_weather(args)

messages.append(
        {
            "role": "function",
            "name": "get_current_weather",
            "content": observation,
        }
)
print(messages)

# 메시지 형태
[{'role': 'user', 'content': "What's the weather like in Boston!"}, <OpenAIObject at 0x7f52781fb7c0> JSON: {
  "role": "assistant",
  "content": null,
  "function_call": {
    "name": "get_current_weather",
    "arguments": "{\n\"location\": \"Boston\"\n}"
  }
}, {'role': 'function', 'name': 'get_current_weather', 'content': '{"location": {"location": "Boston"}, "temperature": "72", "unit": "fahrenheit", "forecast": ["sunny", "windy"]}'}]

# 메시지를 앱에 넘겨주면
response = openai.ChatCompletion.create(
    model="gpt-3.5-turbo-0613",
    messages=messages,
)
print(response)

# 최종 결과
{
  "id": "chatcmpl-8IECz3rHXCRKiyBjMqbJccxZt7N3V",
  "object": "chat.completion",
  "created": 1699355213,
  "model": "gpt-3.5-turbo-0613",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": "The current temperature in Boston is 72\u00b0F. The weather is sunny and windy."
      },
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_tokens": 76,
    "completion_tokens": 17,
    "total_tokens": 93
  }
}
  • 함수에서 온 결과가 응답 결과에 잘 반영되었다!

예제 2

import openai
import json

# 항상 같은 날씨를 리턴하는 예시용 더미 함수이다.
# 실제 개발환경에서는 상황에 맞는 코드를 구현해야한다.
def get_current_weather(location, unit="fahrenheit"):
    """Get the current weather in a given location"""
    weather_info = {
        "location": location,
        "temperature": "72",
        "unit": unit,
        "forecast": ["sunny", "windy"],
    }
    return json.dumps(weather_info)

def run_conversation():
    # Step 1: chatgpt에게 질문과 이용할 수 있는 함수 목록을 전달한다.
    messages = [{"role": "사용자", "content": "서울 날씨는 어때? "}]
    functions = [
        {
            "name": "get_current_weather",
            "description": "위치를 전달하면, 현재 날씨를 알려준다",
            "parameters": {
                "type": "object",
                "properties": {
                    "location": {
                        "type": "string",
                        "description": "구군시  전달한다. ex. 서울특별시",
                    },
                    "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]},
                },
                "required": ["location"],
            },
        }
    ]
    response = openai.ChatCompletion.create(
        model="gpt-3.5-turbo-0613",
        messages=messages,
        functions=functions, # 이 곳에서 함수 정보를 전달한다.
        function_call="auto",
    )
    response_message = response["choices"][0]["message"]

    # Step 2: GPT에서 함수 호출을 하라고 했는지 확인하기
    if response_message.get("function_call"):
        # Step 3: GPT에서 호출하라고 한 함수를 실제로 호출하기
        available_functions = {
            "get_current_weather": get_current_weather,
        }  # 이 예제에서는 호출할 수 있는 함수를 1개만 두었지만, 실제로는 여러개를 추가할 수 있다.
        function_name = response_message["function_call"]["name"] // GPT가 제안한 함수 이름 확인하기
        fuction_to_call = available_functions[function_name] // GPT가 제안한 함수 할당하기
        function_args = json.loads(response_message["function_call"]["arguments"])
        function_response = fuction_to_call(
            location=function_args.get("location"),
            unit=function_args.get("unit"),
        ) # GPT가 제안한 함수를 GPT에서 찾은 매개변수로 전달하기

        # Step 4: 함수 호출로 얻은 결과를 gpt에게 다시 보내주기 send the info on the function call and function response to GPT
        messages.append(response_message)  # API으로 호출받은 값을 확장하기
        messages.append(
            {
                "role": "function",
                "name": function_name,
                "content": function_response,
            }
        )
        second_response = openai.ChatCompletion.create(
            model="gpt-3.5-turbo-0613",
            messages=messages,
        )  # gpt에게 응답 결과 다시 전달하기
        return second_response

print(run_conversation())

Reference

Function Calling: Integrate Your GPT Chatbot With Anything - Semaphore

profile
LLM 및 프롬프트 엔지니어링 공부중

0개의 댓글