[AI] LangChain 사용해보기3 (LLM과 네이버 검색 API를 활용한 맛집 데이터 수집 테스트)

2025. 1. 23. 20:39·AI

팀원들과 나는 API를 사용해서 데이터를 수집해야 하는데 여행이 워낙 데이터 수집 양이 방대해서 멘토님에게 질문을 했다. 멘토님은 LLM에게 질문을 하고 또 다시 질문해서 몇번 걸쳐서 추천 리스트를 뽑으라고 하셨다. 그래서 그렇게 테스트를 해보기로 했다.

 

멘토님의 조언

1. LLM에게 질문을 하고 나온 결과를 다시 질문을해서 데이터 검증을 해라

2. LangChain에 검색 엔진이 있으니 사용해봐라

3. 프롬프트를 구체적으로 잘 짜야 한다.

4. 프롬프트는 영어로 해야 더 답변을 잘해준다.

 

테스트 과정

1번째 테스트

1. 필요한 라이브러리를 import하고 .env에 넣어둔 API_KEY를 사용할 수 있게 연결

원래 gpt-3.5-turbo 모델 사용했는데 이번엔 gpt-4o-mini를 사용해보았다.

import os
from dotenv import load_dotenv
from langchain.chat_models import ChatOpenAI

load_dotenv()

OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")

llm = ChatOpenAI(model="gpt-4o-mini", openai_api_key=OPENAI_API_KEY)

 

2. 사용자가 제공하는 예시 데이터

여행 계획 입력하는 화면에서 이런 정보를 받아올 것이다.

keywords = {
    "location": "부산 해운대",
    "dates": "2025년 1월 22일 ~ 2025년 1월 25일",
    "age_group": "10대 미만",
    "themes": ["가족 여행", "리조트"],
    "group": {"adults": 2, "children": 1, "pets": 1},
}

 

3. GPT에게 질문할 프롬프트 작성

처음에 한글로 작성하고 따로 GPT에게 영어로 바꿔서 달라고 부탁했다.

def generate_restaurant_recommendations(keywords):
    """Generate restaurant recommendations based on user data using GPT."""
    user_data_description = f"""
    You are an expert in Korean cuisine and a recommendation AI. Based on the travel data provided by the user, recommend the most suitable restaurants.

    The user has provided the following travel plan data:
    - Location: {keywords['location']}
    - Travel Dates: {keywords['dates']}
    - Age Group: {keywords['age_group']}
    - Group Composition: Adults {keywords['group']['adults']}, Children {keywords['group']['children']}, Pets {keywords['group']['pets']}
    - Travel Themes: {', '.join(keywords['themes'])}

    Based on this data, recommend restaurants in the {keywords['location']} area.
    Ensure that the recommendations are accurate and realistic. If you cannot find a valid picture URL for a restaurant, return "N/A" for the picture URL.

    The recommendation schedule must follow these rules:
    - For full travel days (22nd to 24th January 2025), recommend three restaurants per day (breakfast, lunch, and dinner).
    - For the last travel day (25th January 2025), recommend two restaurants (breakfast and lunch).

    The recommendation results should be formatted in JSON and include the following information for each restaurant:

    {{
      "day": "<Day: Day 1, Day 2, etc.>",
      "order": "<Visit Order: 1, 2, 3, etc.>",
      "name": "<Restaurant Name>",
      "description": "<Restaurant Description>",
      "address": "<Address>",
      "category": "<Cuisine Category: Korean/Japanese/Western/etc.>",
      "reason": "<Reason for Recommendation: family-friendly, offers children’s menu, pet-friendly, etc.>",
      "picture_url": "<Picture URL or 'N/A'>",
      "place_description": "<Detailed description of the place, including its ambiance, specialty dishes, and suitability for the group.>"
    }}

    The recommendation results must be in Korean and include information about which restaurants to visit on each day and in which order. Ensure the output is clear, concise, and easy for the user to understand.
    """
    try:
        response = llm.predict(user_data_description)
        if isinstance(response, str):
            return response.strip()
        else:
            print("Invalid response type from GPT.")
            return "추천 실패: GPT 응답 오류."
    except Exception as e:
        print(f"GPT 호출 오류: {e}")
        return "추천 실패: GPT 호출 중 문제가 발생했습니다."

 

4. generate_restaurant_recommendations라는 함수에 사용자가 입력한 여행 데이터를 담은 keywords를 전달하고 결과를 출력

recommendation = generate_restaurant_recommendations(keywords)

print("\n=== 추천 맛집 ===")
print(recommendation)

 

 

5. 실행 결과

실제 있는 데이터인지 직접 검색해보았는데 영업중인 가게이름이 아닌것들을 결과로 줬다.

그리고 주소도 다 엉뚱한 곳이었다. 그래서 네이버 검색 API를 사용해보기로 했다.

(agent) C:\Users\201-1\Desktop\travelPlaner_BackEnd\app\services\agents>python restaurant_agent.py
C:\Users\201-1\miniforge3\envs\agent\Lib\site-packages\langchain\chat_models\__init__.py:33: LangChainDeprecationWarning: Importing chat models from langchain is deprecated. Importing from langchain will no longer be supported as of langchain==0.2.0. Please import from langchain-community instead:

`from langchain_community.chat_models import ChatOpenAI`.

To install langchain-community run `pip install -U langchain-community`.
  warnings.warn(
C:\Users\201-1\miniforge3\envs\agent\Lib\site-packages\langchain\chat_models\__init__.py:33: LangChainDeprecationWarning: Importing chat models from langchain is deprecated. Importing from langchain will no longer be supported as of langchain==0.2.0. Please import from langchain-community instead:

`from langchain_community.chat_models import ChatOpenAI`.

To install langchain-community run `pip install -U langchain-community`.
  warnings.warn(
C:\Users\201-1\Desktop\travelPlaner_BackEnd\app\services\agents\restaurant_agent.py:12: LangChainDeprecationWarning: The class `ChatOpenAI` was deprecated in LangChain 0.0.10 and will be removed in 1.0. An updated version 
of the class exists in the :class:`~langchain-openai package and should be used instead. To use it run `pip install -U :class:`~langchain-openai` and import as `from :class:`~langchain_openai import ChatOpenAI``.
  llm = ChatOpenAI(model="gpt-4o-mini", openai_api_key=OPENAI_API_KEY)
C:\Users\201-1\Desktop\travelPlaner_BackEnd\app\services\agents\restaurant_agent.py:52: LangChainDeprecationWarning: The method `BaseChatModel.predict` was deprecated in langchain-core 0.1.7 and will be removed in 1.0. Use :meth:`~invoke` instead.
  response = llm.predict(user_data_description)

=== 추천 맛집 ===
```json
[
  {
    "day": "Day 1",
    "order": "1",
    "name": "해운대 파라다이스 호텔 조식 뷔페",
    "description": "해운대 파라다이스 호텔에서 제공하는 조식 뷔페",
    "address": "부산 해운대구 중동 1401-1",
    "category": "Western",
    "reason": "가족 단위 손님을 위한 다양한 메뉴와 편안한 분위기",
    "picture_url": "N/A",
    "place_description": "해운대 바다를 바라보며 식사할 수 있는 넓고 쾌적한 공간으로, 다양한 옵션의 뷔페 메뉴가 제공됩니다. 아이들도 좋아할 만한 디저트와 과일이 풍부합니다."
  },
  {
    "day": "Day 1",
    "order": "2",
    "name": "해운대 해물탕",
    "description": "신선한 해산물을 이용한 해물탕 전문점",
    "address": "부산 해운대구 해운대해변로 221",
    "category": "Korean",
    "reason": "신선한 해산물 요리로 가족과 함께 즐기기 좋은 장소",
    "picture_url": "N/A",
    "place_description": "해운대 해변 근처에 위치해 있으며, 다양한 해산물 요리를 제공합니다. 신선한 해물탕과 함께 어린이를 위한 간단한 메뉴도 마련되어 있습니다."
  },
  {
    "day": "Day 1",
    "order": "3",
    "name": "미소야",
    "description": "일본식 라멘과 덮밥 전문점",
    "address": "부산 해운대구 해운대해변로 140",
    "category": "Japanese",
    "reason": "아이들이 좋아하는 라멘과 덮밥 메뉴가 풍부",
    "picture_url": "N/A",
    "place_description": "편안한 분위기에서 일본식 식사를 즐길 수 있는 곳으로, 어린이와 어른 모두가 좋아할 만한 메뉴가 다양합니다. 특히, 반찬이 풍부해 가족 단위 손님에게 적합합니다."
  },
  {
    "day": "Day 2",
    "order": "1",
    "name": "해운대 블루베리",
    "description": "건강식과 샐러드를 전문으로 하는 카페",
    "address": "부산 해운대구 해운대해변로 170",
    "category": "Western",
    "reason": "아이와 함께 가기 좋은 건강한 메뉴",
    "picture_url": "N/A",
    "place_description": "모던한 인테리어로 아늑한 분위기를 자랑하며, 신선한 재료로 만든 샐러드와 스무디가 인기입니다. 아이들이 좋아할만한 맛있는 디저트도 다양합니다."
  },
  {
    "day": "Day 2",
    "order": "2",
    "name": "부산 해물찜",
    "description": "해물찜 전문점",
    "address": "부산 해운대구 중동 1752",
    "category": "Korean",
    "reason": "가족 단위 손님을 위한 풍성한 해물찜",
    "picture_url": "N/A",
    "place_description": "신선한 해물과 함께 다양한 채소가 가득한 해물찜을 전문으로 합니다. 가족 단위 손님이 많이 찾아오는 맛집으로, 아이들에게도 적합한 메뉴가 준비되어 있습니다."
  },
  {
    "day": "Day 2",
    "order": "3",
    "name": "김밥천국",
    "description": "간편한 한식 메뉴를 제공하는 패스트푸드",
    "address": "부산 해운대구 해운대해변로 123",
    "category": "Korean",
    "reason": "아이들이 좋아하는 김밥과 간단한 한식 메뉴",
    "picture_url": "N/A",
    "place_description": "빠르고 간편하게 식사를 할 수 있는 곳으로, 다양한 종류의 김밥과 떡볶이, 우동 등을 제공합니다. 가족 단위 손님들에게 적합한 공간입니다."
  },
  {
    "day": "Day 3",
    "order": "1",
    "name": "해운대 해수욕장 근처 카페",
    "description": "바다 전망을 즐길 수 있는 카페",
    "address": "부산 해운대구 해운대해변로 200",
    "category": "Western",
    "reason": "아침 식사와 바다 전망을 모두 즐길 수 있는 장소",
    "picture_url": "N/A",
    "place_description": "해운대 해수욕장 근처에 위치해 있어 바다를 보며 편안한 아침을 즐길 수 있습니다. 커피와 함께 간단한 아침 메뉴가 제공되어 가족이 함께하기 좋은 곳입니다."
  },
  {
    "day": "Day 3",
    "order": "2",
    "name": "푸른 바다",
    "description": "신선한 해산물과 한식을 제공하는 레스토랑",
    "address": "부산 해운대구 해운대해변로 150",
    "category": "Korean",
    "reason": "가족과 함께 즐기기 좋은 해산물 요리",
    "picture_url": "N/A",
    "place_description": "아름다운 바다 전망을 감상하면서 신선한 해산물 요리를 즐길 수 있는 곳으로, 가족 단위 손님에게 추천합니다. 아이들이 좋아할만한 메뉴도 다양하게 마련되어 있습니다."
  }
]
```

 

 


 

2번째 테스트

1. 필요한 라이브러리 import하고 네이버 API_KEY도 .env 파일에 추가 후 연결

import os
from dotenv import load_dotenv
from langchain_community.chat_models import ChatOpenAI
import requests
import json

load_dotenv()

OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
NAVER_SEARCH_CLIENT_ID = os.getenv("NAVER_SEARCH_CLIENT_ID")
NAVER_SEARCH_CLIENT_SECRET = os.getenv("NAVER_SEARCH_CLIENT_SECRET")

llm = ChatOpenAI(model="gpt-4o-mini", openai_api_key=OPENAI_API_KEY)

 

2. 네이버 지역 검색 API를 호출해 입력된 키워드와 관련된 장소 정보를 JSON 형식으로 반환하는 함수 작성

  • query: 검색 키워드
  • display: 반환할 검색 결과의 개수
def search_naver_places(query, display=5):
    url = "https://openapi.naver.com/v1/search/local.json"
    headers = {
        "X-Naver-Client-Id": NAVER_SEARCH_CLIENT_ID,
        "X-Naver-Client-Secret": NAVER_SEARCH_CLIENT_SECRET,
    }
    params = {"query": query, "display": display}

    response = requests.get(url, headers=headers, params=params)
    return response.json() if response.status_code == 200 else None

 

3. GPT에게 질문할 프롬프트 작성

영어 프롬프트도 제대로 결과 못가져와서 그냥 한글로 작성한 프롬프트를 넣었다.

items는 네이버 API가 반환하는 검색 결과 리스트를 의미한다.

def generate_restaurant_recommendations(keywords):
    restaurants_data = []

    search_query = f"{keywords['location']} 맛집"
    places_data = search_naver_places(search_query)

    if places_data and "items" in places_data:
        restaurants_data = places_data["items"]

    user_data_description = f"""
    당신은 대한민국에 있는 식당에 대한 전문가이자 추천 AI입니다. 사용자의 여행 데이터를 기반으로 여행 일정에 가장 적합한 식당을 추천해주세요.

    여행 계획 데이터:
    - 위치: {keywords['location']}
    - 여행 날짜: {keywords['dates']}
    - 연령대: {keywords['age_group']}
    - 그룹 구성: 성인 {keywords['group']['adults']}, 아동 {keywords['group']['children']}, 반려동물 {keywords['group']['pets']}
    - 여행 테마: {', '.join(keywords['themes'])}

    실제 식당 데이터:
    {json.dumps(restaurants_data, ensure_ascii=False, indent=2)}

    위 실제 식당 데이터를 기반으로 {keywords['location']} 지역의 식당을 추천해주세요.
    제공된 실제 식당 정보만 사용하여 추천해주세요.

    추천 일정 규칙:
    - 전체 여행일(1월 22일~24일)은 하루 3끼(아침, 점심, 저녁) 추천
    - 마지막 여행일(1월 25일)은 2끼(아침, 점심) 추천

    다음과 같은 JSON 형식으로 응답해주세요:
    {{
        "recommendations": [
            {{
                "day": "1일차",
                "order": "1",
                "name": "식당명",
                "description": "식당 설명",
                "address": "주소",
                "category": "음식 종류",
                "reason": "추천 이유",
                "place_description": "장소 상세 설명"
            }}
        ]
    }}
    """

    try:
        response = llm.predict(user_data_description)
        return response.strip()
    except Exception as e:
        print(f"GPT 호출 오류: {e}")
        return "추천 실패: GPT 호출 중 문제가 발생했습니다."

 

4. 사용자가 제공하는 예시 데이터는 첫번쨰 테스트와 동일하게 하고 결과를 출력

keywords = {
    "location": "부산 해운대",
    "dates": "2025년 1월 22일 ~ 2025년 1월 25일",
    "age_group": "10대 미만",
    "themes": ["가족 여행", "리조트"],
    "group": {"adults": 2, "children": 1, "pets": 1},
}

recommendation = generate_restaurant_recommendations(keywords)
print("\n=== 추천 맛집 ===")
print(recommendation)

 

5. 실행 결과

네이버 검색API를 사용한것이라 실제 식당 이름은 가져오는데 내가 반환할 검색 결과의 개수를 5개로 제한해둬서 그런지 같은 식당을 중복으로 가져왔다.

(agent) C:\Users\201-1\Desktop\travelPlaner_BackEnd\app\services\agents>python restaurant_agent.py
C:\Users\201-1\Desktop\travelPlaner_BackEnd\app\services\agents\restaurant_agent.py:13: LangChainDeprecationWarning: The class `ChatOpenAI` was deprecated in LangChain 0.0.10 and will be removed in 1.0. An updated version 
of the class exists in the :class:`~langchain-openai package and should be used instead. To use it run `pip install -U :class:`~langchain-openai` and import as `from :class:`~langchain_openai import ChatOpenAI``.
  llm = ChatOpenAI(model="gpt-4o-mini", openai_api_key=OPENAI_API_KEY)
C:\Users\201-1\Desktop\travelPlaner_BackEnd\app\services\agents\restaurant_agent.py:75: LangChainDeprecationWarning: The method `BaseChatModel.predict` was deprecated in langchain-core 0.1.7 and will be removed in 1.0. Use :meth:`~invoke` instead.
  response = llm.predict(user_data_description)

=== 추천 맛집 ===
```json
{
    "recommendations": [
        {
            "day": "1일차",
            "order": "1",
            "name": "한우리가",
            "description": "부드럽고 신선한 한우를 즐길 수 있는 곳",
            "address": "부산광역시 해운대구 중동 1226-6",
            "category": "한식>소고기구이",
            "reason": "가족 모두가 즐길 수 있는 고기 요리, 아동도 좋아할 맛",
            "place_description": "해운대 중심에 위치하여 접근성이 좋고, 아늑한 분위기에서 식사를 즐길 수 있습니다."
        },
        {
            "day": "1일차",
            "order": "2",
            "name": "쇼미더고기 뒷고기",
            "description": "돼지고기 구이를 전문으로 하는 맛집",
            "address": "부산광역시 해운대구 우동 598-13",
            "category": "한식>돼지고기구이",
            "reason": "아이와 함께 나누기 좋은 양념된 돼지고기, 가성비 좋은 메뉴",
            "place_description": "편안하고 가족 친화적인 분위기로, 반려동물과 함께 방문할 수 있는 공간도 마련되어 있습니다."
        },
        {
            "day": "1일차",
            "order": "3",
            "name": "황금조개구이횟집 해운대점",
            "description": "신선한 조개구이를 맛볼 수 있는 해산물 전문점",
            "address": "부산광역시 해운대구 중동 1391-42 베스트웨스턴 호텔 1층 102, 103호",
            "category": "한식>조개요리",
            "reason": "바다의 맛을 느낄 수 있는 조개구이가 가족 모두에게 인기가 많음",
            "place_description": "부산 해운대의 바다를 느낄 수 있는 멋진 위치에 자리잡고 있습니다."
        },
        {
            "day": "2일차",
            "order": "1",
            "name": "무겐",
            "description": "신선한 일식을 제공하는 일본식 레스토랑",
            "address": "부산광역시 해운대구 우동 1436-2 아라트리움 203호",
            "category": "음식점>일식>일식당",
            "reason": "아이가 좋아하는 초밥과 다양한 일식 메뉴가 있어 가족 단위 방문에 적합",
            "place_description": "모던한 인테리어와 함께 편안한 분위기에서 식사를 즐길 수 있습니다."
        },
        {
            "day": "2일차",
            "order": "2",
            "name": "제주송치비 해운대본점",
            "description": "제주도 특산물인 송치비를 활용한 다양한 육류 요리",
            "address": "부산광역시 해운대구 중동 1764-6 1층",
            "category": "한식>육류,고기요리",
            "reason": "아이와 함께 즐기기 좋은 고기 요리, 특별한 맛을 경험할 수 있음",
            "place_description": "부산 해운대의 활기찬 분위기 속에서 제주도의 맛을 느낄 수 있는 곳입니다."
        },
        {
            "day": "3일차",
            "order": "1",
            "name": "한우리가",
            "description": "부드럽고 신선한 한우를 즐길 수 있는 곳",
            "address": "부산광역시 해운대구 중동 1226-6",
            "category": "한식>소고기구이",
            "reason": "여행의 마지막 날, 다시 한번 고급 한우를 즐기며 마무리하기 좋은 장소",
            "place_description": "가족 단위 손님을 위한 아늑한 공간과 친절한 서비스가 특징입니다."
        },
        {
            "day": "3일차",
            "order": "2",
            "name": "쇼미더고기 뒷고기",
            "description": "돼지고기 구이를 전문으로 하는 맛집",
            "address": "부산광역시 해운대구 우동 598-13",
            "category": "한식>돼지고기구이",
            "reason": "아이와 함께 나누기 좋은 맛있는 돼지고기를 즐길 수 있는 곳",
            "place_description": "편안한 분위기에서 가족과 함께 즐거운 시간을 보낼 수 있는 식당입니다."
        }
    ]
}
```

 

추가로 몇번 더 실행했지만 LLM을 사용하면 알맞지 않은 가게명과 주소를 가져오고 검색 API를 사용하면 많은 데이터를 뽑아올 수가 없어서 다른 팀원들은 어떻게 테스트하는지 의견을 나눠봐야겠다.

'AI' 카테고리의 다른 글

[AI] CrewAI에서의 Tool, Agent, Task 개념  (0) 2025.02.02
[AI] CrewAI 설치 시 Microsoft Visual C++ 관련 오류 해결  (0) 2025.02.01
[AI] LangChain 사용해보기2  (0) 2025.01.15
[AI] LangChain 사용해보기  (0) 2025.01.12
[AI] LangChain이란 무엇인가?  (0) 2025.01.12
'AI' 카테고리의 다른 글
  • [AI] CrewAI에서의 Tool, Agent, Task 개념
  • [AI] CrewAI 설치 시 Microsoft Visual C++ 관련 오류 해결
  • [AI] LangChain 사용해보기2
  • [AI] LangChain 사용해보기
dud9902
dud9902
개발자 취준생 기록일지
  • dud9902
    dud's DevStory
    dud9902
  • 전체
    오늘
    어제
    • 분류 전체보기 (79)
      • SpringBoot (14)
      • React (12)
      • Python (14)
      • AI (21)
      • DB (5)
      • Figma (1)
      • Markdown (1)
      • AWS (6)
      • 기타 (5)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    springboot
    redis
    Python
    twilio
    pydantic
    AWS
    스프링부트
    AI
    의존성 주입
    miniforge
    docker
    pytorch
    langchain
    db
    recognize anything
    CrewAI
    Agent
    SQLAlchemy
    FastAPI
    react
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
dud9902
[AI] LangChain 사용해보기3 (LLM과 네이버 검색 API를 활용한 맛집 데이터 수집 테스트)
상단으로

티스토리툴바