서비스 소개
졸업 프로젝트에 대한 포스트를 써보려 합니다. ^0^
우선 프로젝트 제목은 "뭐 찾으세요?"
실제 우리가 쇼핑하러 매장에 들리면 보통 점원에게 듣는 첫 마디일 것입니다.
이렇듯 저희가 만드려는 서비스는
실제 오프라인 매장의 경험을 온라인에서 느낄 수 있도록 하는게 목표입니다!
기존의 온라인 쇼핑몰은 카테고리에 맞춰 옵션을 클릭하거나 원하는 상품을 찾을때까지 스크롤을 내리고 클릭하는 과정을 반복합니다. 이 과정에서 고객은 오랜 시간 동안 사이트에 체류하게 되면서 피로를 느끼게 되거나 사이트를 이탈할 확률도 높아지죠.
저희 서비스는 챗봇이 가상 점원이 되어 사용자와의 대화를 통해 기존 쇼핑몰 사이트에서 사용자가 말한 내용과 관련있는 상품들만 가져와 보여주게 됩니다.
즉, 원하는 상품을 찾기 위해 직접 일일이 클릭하고 쇼핑몰을 뒤지는 일이 없이 챗봇에게 말만 하면 되는거죠!
기술
서비스에 대한 요약 설명을 했으니 이제 기술적인 부분을 설명해보겠습니다.
이 프로젝트의 중요 기능은 사용자가 input을 입력했을때 그것과 관련된 쇼핑몰 페이지를 불러와야 하고, 불러온 해당 페이지에서 관련있는 정보만 추출해 나타내는 것입니다!
그렇다면 챗봇이 '얼마나 사용자의 말을 잘 이해했는지', '얼마나 정확하고 빠르게 결과값을 가져왔는지' 가 중요하겠지요?
chatGPT와 langchain 기술을 통해 사용자가 입력한 값에 따른 쇼핑몰 url을 가져오도록 해보겠습니다.
1. URL 분석하기
무신사 스토어의 매거진을 기본 url로 두고 모델을 실행해보겠습니다.
무신사 스토어 매거진 페이지에서 '레트로'를 검색했을 때 나타나는 페이지입니다.
이 페이지의 url이 'https://www.musinsa.com/search/musinsa/magazine?q=레트로' 인 것으로 봐서 q가 검색 내용에 해당하는 부분인 것을 알 수 있습니다.
url에 또 어떤 값들을 적용할 수 있는지 살펴보기 위해, 카테고리와 정렬 필터를 눌러보겠습니다.
'상의' 카테고리를 select하고 '조회순'으로 정렬해보니 페이지의 url이 'https://www.musinsa.com/search/musinsa/magazine?q=레트로&category1DepthCode=001&selectedFilters=상의%3Acategory1DepthCode&category1DepthName=상의&sortCode=hit' 으로 바뀌었습니다.
이는 상의 카테고리가 001로 정의되어 있고 조회순 필터가 hit로 정의되어 있는 것을 알 수 있습니다.
이번에는 '상의'의 하위 카테고리인 '반소매 티셔츠'를 선택해보겠습니다. 이 페이지의 url은 'https://www.musinsa.com/search/musinsa/magazine?q=레트로&category1DepthCode=001&category2DepthCodes=001001&selectedFilters=상의%3A001%3Acategory1DepthCode%7C반소매+티셔츠%3A001001%3Acategory2DepthCodes&category1DepthName=상의&sortCode=hit' 입니다. 이를 통해 하위필터가 url에 어떻게 적용되는지 알 수 있습니다.
이런 과정들을 반복하여 url을 분석한 결과 다음과 같이 필터를 정리할 수 있습니다.
//data
const filters: Filter[] = [
(
"name": "카테고리",
"choices": (
"001": "상의",
"002": "아우터",
"003": "바지",
"004": "가방",
"005": "신발",
"006": "시계",
"007": "모자",
"008": "양말/레그웨어",
"009": "선글라스/안경테"
"011": "액세서리",
"012": "디지털/테크",
"015": "뷰티",
"017": "스포츠/용품",
"015": "스니커즈",
"020": "원피스",
"022": "스커트",
"025": "주얼리",
"026": "속옷",
"054": "여성가방",
"058": "리빙"
)
),
(
"name" : "상의",
"choices" : (
"001001" : "반소매티셔츠",
"001002" : "셔츠/블라우스",
"001003" : "피케/카라티셔츠",
"001004" : "후드티셔츠",
"001005" : "맨투맨/스웨트셔츠",
"001006" : "니트/스웨터",
"001008" : "기타상의",
"001010" : "긴소매티셔츠",
"001011" : "민소매티셔츠"
)
),
(
"name" : "아우터",
"choices" : (
"002001" : "블루종/MA-1",
"002002" : "레더/라이더스재킷",
"002003" : "슈트/블레이저재킷",
"002004" : "스타디움재킷",
"002005" : "나일론/코치재킷",
"002006" : "겨울싱글코트",
"002007" : "환절기코트",
"002008" : "겨울기타코트",
)
),
(
"name" : "바지",
"choices" : (
"003002" : "데님팬츠",
"003004" : "트레이닝/조거팬츠",
"003005" : "레깅스",
"003006" : "기타바지",
"003007" : "코튼팬츠",
"003008" : "슈트팬츠/슬랙스",
"003009" : "숏팬츠",
"003010" : "점프슈트/오버올",
"003011" : "스포츠하의",
)
),
//(일부생략)
(
"name": "정렬",
"choices": (
"create_date": "최신순",
"hit": "조회순",
"total_comment_count": "많은댓글순",
"comment_date": "최신댓글순"
)
)
]```
2. ChatGPT Prompt Engineering + Langchain 사용하기
해당 온라인 쇼핑몰에 어떤 필터가 url과 연관있는지 살펴보았으니, 이제 사용자의 입력에 따른 url 생성 모델을 만들어보겠습니다.
우선 Langchain에 대해 쉽게 설명하자면, 사용자와 LLM(ChatGPT) 사이에 여러가지 tool들을 이용해 Prompt Engineering (프롬프트 엔지니어링)을 하며 원하는 답을 찾는 것을 말합니다.
LLM : 대규모 언어 모델은 인간과 유사한 응답을 생성하기 위해 방대한 양의 텍스트 데이터에 대해 훈련된 인공 지능 ex) ChatGPT
Prompt Engineering : 생성 AI에게 품질 좋은 결과를 만드는데 필요한 명령어를 만드는 작업
https://python.langchain.com/en/latest/index.html
Welcome to LangChain — 🦜🔗 LangChain 0.0.179
python.langchain.com
LangChain은 여러 모듈로 구성되어있는데, langchain 사이트에서는 7개 카테고리의 컴포넌트들과 다양한 사용 사례들을 소개하고 있습니다. 그 중에서 몇가지에 대해 설명하겠습니다.
1. Prompts
모델에 들어가는 입력을 설정합니다. PromptTemplate 기능 제공하고 프롬프트 템플릿은 프롬프트 관리 및 최적화를 용이하게 하며 LLM에서 사용자 입력을 처리하는 방식을 향상시킵니다.
2. Memory
메모리는 체인 또는 에이전트 호출 간의 상태를 유지하는 개념으로, 고급 응용 프로그램을 허용합니다. 기본적으로 langchain의 모든 모듈은 서로 독립적이며 각 모듈은 입력을 처리하고 따로 저장하지 않습니다. 메모리는 이전 interaction을 저장하고 단기 및 장기 기억력을 갖기 위해 만들어진 모듈입니다.
3. Chains
일부 간단한 응용 프로그램에서는 LLM을 분리하여 사용하는 것이 좋지만 더 복잡한 응용 프로그램에서는 서로 또는 다른 전문가와 LLM을 연결해야 합니다. LangChain은 체인을 위한 표준 인터페이스와 사용 편의성을 위한 몇 가지 일반적인 체인 구현을 제공합니다.
4. Agents
일부 응용 프로그램에는 LLM/기타 도구에 대한 미리 결정된 호출 체인뿐만 아니라 잠재적으로 사용자 입력에 따라 알려지지 않은 체인이 필요합니다. 사용자 입력에 따라 에이전트는 호출할 도구를 결정할 수 있습니다.
이제 필터 데이터를 기반으로 url이 생성되도록 template을 작성해주겠습니다. 이때 여러 유형의 user input을 입력해주고 그에 맞는 url을 같이 보여주어 LLM이 더 잘 이해할 수 있도록 예시 몇가지를 넣어주겠습니다.
(입력 키워드에 띄어쓰기가 포함되는 경우에는 +로 표시해주었습니다.)
template = """You are the helpful agent that creates the filter that matches the user's input. You define the filters and choices in Typescript, and present the selected filters and choices as results using the given filter data.
- An OR operation is performed between the choices.
- output should be only one URL. do not add any description about output.
- The filter name and choices given to the data in typescript file should be written exactly as it is.
```TypeScript
interface Filter (
name: string;
choices: ( [code: string]: string );
);
//filter data
If there is something not including in Filter, you have to add "includeKeywords=" and the component like this.
Example 1)
user input: 키치 찾아줘
URL: https://www.musinsa.com/search/musinsa/magazine?q=키치
Example 2)
user input: 연예인이 착용한 가방 보여줘
URL: https://www.musinsa.com/search/musinsa/magazine?q=연예인착용&category1DepthCode=054&selectedFilters=여성가방%3Acategory1DepthCode&category1DepthName=여성+가방&openFilterLayout=N
Example 3)
user input: 레트로한 신발 찾아줘
URL: https://www.musinsa.com/search/musinsa/magazine?q=레트로&category1DepthCode=005&selectedFilters=신발%3Acategory1DepthCode&category1DepthName=신발&openFilterLayout=N
Example 4)
user input: 요즘 트렌디한 상의 찾아줘
URL: https://www.musinsa.com/search/musinsa/magazine?q=트렌디&category1DepthCode=001&selectedFilters=상의%3A001%3Acategory1DepthCode&category1DepthName=상의&openFilterLayout=N
Example 5)
user input: 힙한 옷 최신댓글순으로 보여줘
URL: https://www.musinsa.com/search/musinsa/magazine?q=힙한&sortCode=comment_date
Example 6)
user input: 유행하는 긴소매 보여줘
URL: https://www.musinsa.com/search/musinsa/magazine?q=유행하는&category1DepthCode=001&category2DepthCodes=001010&selectedFilters=상의%3A001%3Acategory1DepthCode%7C긴소매%3A001010%3Acategory2DepthCodes&category1DepthName=상의&openFilterLayout=N
Example 7)
user input: 여름에 입을만한 반소매티셔츠나 블라우스 보여줘
URL: https://www.musinsa.com/search/musinsa/magazine?q=여름에+입을만한&category1DepthCode=001&category2DepthCodes=001001%2C001002&selectedFilters=상의%3A001%3Acategory1DepthCode%7C반소매+티셔츠%3A001001%3Acategory2DepthCodes%7C셔츠%2F블라우스%3A001002%3Acategory2DepthCodes&category1DepthName=상의&openFilterLayout=N
Example 8)
user input: y2k 패션 추천해줘
URL: https://www.musinsa.com/search/musinsa/magazine?q=키치
Example 9)
user input: 요즘 트렌디한 옷이 뭐야?
URL: https://www.musinsa.com/search/musinsa/magazine?q=트렌디
Example 10)
user input: 뉴진스가 입을 것 같은 옷 알려줘
URL: https://www.musinsa.com/search/musinsa/magazine?q=뉴진스
Example 11)
user input: 바캉스 갈 때 입을 옷 추천해봐
URL: https://www.musinsa.com/search/musinsa/magazine?q=바캉스
Example 12)
user input: 일본 여행 갈 때 뭐입을지 정해줘
URL: https://www.musinsa.com/search/musinsa/magazine?q=일본+여행
Relavant Information:
{history}
Conversation:
user input: {input}
URL:"""
특정 엔티티에 대한 정보를 기억하는 메모리 모듈로 작업하겠습니다. 엔티티에 대한 정보를 추출하고(LLM 사용) 시간이 지남에 따라 해당 엔티티에 대한 지식을 축적합니다. 먼저 이 기능을 사용하는 방법을 살펴보겠습니다.
memory = ConversationKGMemory(llm=llm)
memory.save_context({"input":"요즘 인기있는 스타일 보여줘"}, {"output":"https://www.musinsa.com/search/musinsa/magazine?q=인기있는"})
memory.save_context({"input":"연예인이 착용한 옷들 보여줘"}, {"output":"https://www.musinsa.com/search/musinsa/magazine?q=연예인착용"})
이제 체인에서 사용해보겠습니다!
conversation_with_kg = ConversationChain(
llm=llm,
verbose=True,
prompt=prompt,
memory=memory
)
return conversation_with_kg.predict(input=user_input)
자 이제 사용자 input을 넣어 모델을 실행해보겠습니다.
Filtering("힙합 스타일의 조거팬츠 조회순으로 보여줘")
결과값으로 나온 url로 들어가보겠습니다.
검색어로 '힙합', 카테고리에 '조거팬츠', 상위 카테고리에 해당하는 '바지', '조회순' 정렬까지 모두 잘 나온 것을 확인할 수 있습니다.
이렇게 Langchain, ChatGPT를 통해 사용자가 입력한 내용에 따른 쇼핑몰의 url을 생성하는 작업을 해보았습니다.
이 과정에서 토큰 사용량이 꽤나 많이 나와서(^^;;) 앞으로 이어질 작업으로는 template을 다듬어 조금 더 효율적이고 최적화하는 방안을 마련해볼 예정입니다.
또한 해당 url 페이지에서 관련있는 정보를 요약하고 사용자의 질문에 응답할 수 있는 기능도 구현해볼 예정입니다. 그렇다면 Langchain 기술을 이해하는데 한발짝 더 다가설 수 있을 것 같습니다 ㅎㅎ
'인공지능 > Generative AI' 카테고리의 다른 글
[6탄] FastAPI 애플리케이션 Google Cloud Run(Docker)에 배포하기 (1) | 2023.11.26 |
---|---|
[5탄] Langchain+GPT+텍스트 임베딩으로 상품에 대한 질의응답하기 (0) | 2023.11.13 |
[4탄] Selenium을 이용한 동적 페이지 크롤링 (1) | 2023.11.13 |
[3탄] Beautifulsoup로 웹 크롤링하기 (0) | 2023.09.20 |
[2탄]Langchain+GPT로 summary와 QA 해보기 (0) | 2023.09.10 |
댓글