나의 작은 valley

[Information Retrieval] Json Mode와 function Calling 본문

Computer Science/[인공지능]

[Information Retrieval] Json Mode와 function Calling

붕옥 아이젠 2024. 6. 24. 17:23
728x90

LLM 어플리케이션

: LLM의 언어 이해 능력 및 추론 능력을 활용하여 다양한 형태의 어플리케이션을 만들 수 있다. open ai 역시 이를 인지하고 입력에서 주요 키워드 만을 뽑아 json 형태로 만들어주는 json_mode를 지원하고 있다.

type : json_object

 

Function Calling

: LLM의 추론 능력을 외부 툴 또는 API를 호출하는 기능과 혼합하여 실시간 정보 파악 및 답변의 정확도를 높힐 수 있다. gpt-3.5-turbo-1106 이후 모델에서부터 함수 호출이 필요하다고 판단되는 경우를 감지하는 기능이 탑재되었다. 

 

사용법)

api 호출 시 tools에 사용할 함수들을 명시.tool_choice를 지정하여 특정 함수를 무조건 calling하게 설정할 수 있음.

 

cf) 반환정보에서 finish_reason을 통해 모델이 tool을 사용했는지 확인할 수 있음.

cf) content를 통해 어떤 tool이 사용되었고 tool의 입력값이 무엇인지 확인할 수 있음. 

 

 

실습)

# 각 테스트 케이스에 대해 openai API를 수행하는 함수를 정의

def test(case, persona, response_format=None):
    messages = [
        {"role": "system", "content": persona},
        {"role": "user", "content": case}
    ]

    print(f'Test case: {case}')

    # response_format이 지정되었으면 해당 형식으로 결과를 반환합니다.
    if response_format:
        result = client.chat.completions.create(
            model=llm_model,
            messages=messages,
            temperature=0.1,
            response_format=response_format,
            seed=1
        )
    else:
        result = client.chat.completions.create(
            model=llm_model,
            messages=messages,
            temperature=0.1,
            seed=1
        )

    # 결과를 출력합니다.
    print(f'Result: \n{result.choices[0].message.content}')

 

#Json mode 

#json mode OFF
persona = """
## Role: 리뷰 감성 분류

## Instruction
- 주어진 리뷰가 '긍정', '부정', '중립'인지 판단해줘.
- 추가적인 설명은 필요없고 감성 분류 결과만 알려줘.
"""

# 결과를 JSON 형식으로 출력하도록 지침을 수정합니다.
#JSON 모드 ON
persona_json = """
## Role: 리뷰 감성 분류

## Instruction
- 주어진 리뷰가 '긍정', '부정', '중립'인지 판단해줘.
- 추가적인 설명은 필요없고 감성 분류 결과만 알려줘.
- 결과는 JSON 형태로 출력해줘.

## Output Format
{"Sentiment": $sentiment}
"""

 

출력)

# JSON 출력 명시하지 않은 경우
for tc in test_case:
    test(tc, persona)
    print('')
    
"""
Test case: 가성비 굳!
Result: 
긍정

Test case: 다시는 이제품을 사나봐라
Result: 
부정

Test case: 재구입 의사 있습니다.
Result: 
주어진 리뷰는 '긍정'으로 분류됩니다.

Test case: 비추는 아니지만 그렇다고 추천할만 하지는 않음
Result: 
중립
"""
# JSON 출력 명시한 경우
for tc in test_case:
    test(tc, persona_json)
    print('')
"""
Test case: 가성비 굳!
Result: 
{"Sentiment": "긍정"}

Test case: 다시는 이제품을 사나봐라
Result: 
{"Sentiment": "부정"}

Test case: 재구입 의사 있습니다.
Result: 
{"Sentiment": "긍정"}

Test case: 비추는 아니지만 그렇다고 추천할만 하지는 않음
Result: 
{"Sentiment": "중립"}
"""
# JSON 출력 명시한 경우 + OpenAI JSON mode를 사용
for tc in test_case:
    test(tc, persona_json, {"type": "json_object"})
    print('')
"""
# JSON 출력 명시한 경우 + OpenAI JSON mode를 사용
for tc in test_case:
    test(tc, persona_json, {"type": "json_object"})
    print('')
"""

 

 

의도 분류)

# prompt

persona_json = """
## Role: 의도 분류

## Instruction
- 의도는 '요약', '번역', 질답', '기타' 네가지 중 하나로 결정해야 돼!
- 추가적인 설명은 필요없고 의도만 알려줘.
- 결과는 JSON 형태로 출력해줘.

## Output Format
{"Intent": $intent}
"""

 

출력)

for tc in test_case:
    test(tc, persona_json)
    print()
"""
Test case: 다음 뉴스 요약해줘.
60만 패캐머가 선택한 강의, 이제 우리 회사에서 만나보세요! Fastcampus 강의로 취업부터 직무역량 강화까지! 전화, 카톡 상담가능. 강의자료 제공. 약 200개 인강 무제한 수강. 분야별 전문 강사진 강의. PC/태블릿/모바일 수강가능. 누적 수강생 20만명. 맞춤형 커리큘럼 제공.
Result: 
{"Intent": "요약"}

Test case: 아래 문장 번역 좀 해줄래? 
I love Fast Campus.
Result: 
{"Intent": "번역"}

Test case: 패스트캠퍼스가 뭐야?
Result: 
{"Intent": "질답"}

Test case: 안녕, 반가워!
Result: 
{"Intent": "기타"}

"""

 

질의 분석)

#prompt

persona_json = """
## Role: 질의 분석

## Instruction
- 사용자 메시지가 식당에 대한 검색 요청인지 아닌지 판단해줘.
- 주어진 질문으로부터 '식당 위치'와 '음식 종류'를 추출해줘.
- 추가적인 설명은 추출된 결과만 알려줘.
- 결과는 JSON 형태로 출력해줘.

## Output Format
{"검색 요청": true/false, "식당 위치": $location, "음식 종류": $food_kind}
"""

 

#출력

for tc in test_case:
    test(tc, persona_json)
    print()
"""
Test case: 강남역 근처 맛집 추천해줘
Result: 
{"검색 요청": true, "식당 위치": "강남역 근처", "음식 종류": null}

Test case: 청담동 일식집 찾아줘
Result: 
{"검색 요청": true, "식당 위치": "청담동", "음식 종류": "일식"}

Test case: 제주에서 흑돼지 잘하는집 알려줘
Result: 
{"검색 요청": true, "식당 위치": "제주", "음식 종류": "흑돼지"}

Test case: 제주로 여행가고 싶다
Result: 
{"검색 요청": false}
"""

 

 

Function Calling 예제)

#공통 함수 정의 (바뀐 부분만 표시)

def test_with_function_calling(messages, persona, tools, tool_choice=None):
    msg = [{"role": "system", "content": persona}] + messages

    if tool_choice:
        result = client.chat.completions.create(
            model=llm_model,
            messages=msg,
            tools=tools,
            tool_choice=tool_choice,
            temperature=0,
            seed=1
        )

    else:

 

# prompt 정의

persona_function_calling = """
## Name: Good Place

## Role: 식당 검색 도우미

## Instruction
- 사용자의 요청이 식당 추천이나 검색인 경우에는 질의 분석 결과를 생성한다.
- 질의 분석 결과에 대해서는 지금까지 주고받은 전체 사용자 메시지를 분석하여 검색에 사용하기 적합한 최종 질의, 식당 위치, 음식 종류를 function calling 결과에 포함하여 출력한다.
- 식당 추천이나 검색이 아닌 나머지 질의는 적절한 대답을 생성한다.
"""

 

# tool 정의

tools = [
    {
        "type": "function",
        "function": {
            "name": "search_restaurant",
            "description": "식당을 검색한다.",
            "parameters": {
                "properties": {
                    "standalone_query": {
                        "type": "string",
                        "description": "기존 메시지 히스토리를 감안한 검색에 사용하기 적합한 최종 질의"
                    },
                    "location": {
                        "type": "string",
                        "description": "서울, 제주, 강남역, 신사역 등 식당의 위치"
                    },
                    "cuisine": {
                        "type": "string",
                        "description": "음식의 종류",
                        "enum": ["한식", "일식", "중식", "태국음식", "이탈리안"]
                    }
                },
                "required": ["standalone_query", "location", "cuisine"],
                "type": "object"
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "detail_restaurant",
            "description": "식당 상세 정보 제공",
            "parameters": {
                "properties": {
                    "place_name": {
                        "type": "string",
                        "description": "식당 이름",
                    },
                    "question": {
                        "type": "string",
                        "description": "상세 정보 요청을 위한 질문"
                    }
                },
                "required": ["place_name", "question"],
                "type": "object"
            }
        }
    }
]

 

#실행

test_with_function_calling(messages, persona_function_calling, tools)

"""
ChatCompletionMessage(
    content=None, 
    role='assistant', 
    function_call=None, 
    tool_calls=[ChatCompletionMessageToolCall(id='call_6H3WMQknJzCaUxFyzsYYVq3L', 
    function=Function(arguments='{"standalone_query":"태국음식","location":"강남역","cuisine":"태국음식"}',
    name='search_restaurant'), type='function')])
"""
728x90
Comments