Langchain을 소개하는 칼럼 하나를 읽다가 Langchain으로 Tabular Dataset을 증강시키는 방법이 있다고 해서 궁금했다.
https://tiabet0929.tistory.com/72
위 대회에 참가할 때도 학습을 하려고 했던 이유가 LLM을 통한 승부예측을 하려는 것도 있지만 학습이 잘 되어야 증강도 잘 이루어질 수 있을 것이라고 생각해서였던 것도 있었기 때문이었다. 그리고 실제로 LLM으로 데이터 증강을 하는 사람들이 많다고 들었었는데, 명확하게 방법을 알지는 못했다. 그러다 익숙한 Langchain을 통해 증강도 할 수 있다는 말에 여러 자료를 찾아봤다.
https://python.langchain.com/docs/tutorials/data_generation/
langchain의 튜토리얼 공식문서에 이 방법이 나와있다. 그런데 이 문서는 좀 오래된 것 같았고, 연결된 colab 페이지도 삭제되어서 열리지가 않았다. 워낙 랭체인이 패키지 버전에 민감한 걸로 알고 있어서 (함수랑 패키지 이름이 계속 바뀜) 조금 더 최신 버전 자료를 찾아보려고 했는데 랭체인 공식 문서는 찾을 수가 없었다. (바빠서 업데이트를 안해놓은 듯)
Chatgpt4o에도 물어봤는데 코드를 잘 생성해주지만 역시나 패키지 호환성 때문에 최신 버전의 langchain에선 돌아가지가 않았다.
그러다 Medium에서 올해 5월에 작성된 글 하나를 찾았다.
Medium이 참 좋은 게 어떤 글은 유료라서 읽을 수 없지만 무료로 풀린 글들 중에서도 이런 내용도 좋고 따라하기도 좋은, 고수분들이 써주신 글들이 많다.
글에는 Synthetic Data와 Langchain 전반에 대한 설명도 많으므로 나는 중요한 부분만 요약해서 실행해봤다.
우선 데이터셋은 캐글에 올라와있는 전자상거래 데이터셋을 그대로 사용했다.
pip install --upgrade --quiet langchain langchain_experimental langchain-openai
필요한 패키지는 위와 같다. langchain이 참 불편하다고 느껴지는게 바로 이런 부분인데, 싸이킷런 같은 패키지처럼 scikit-learn 하나만 설치하면 dependency한 패키지들이 다 설치되는 데에 반해 langchain은 같은 langchain 생태계 내의 패키지임에도 불구하고 따로따로 설치하고 불러와서 사용해야된다는 것이 참 어렵고 귀찮은 부분이다.
from langchain_core.prompts import FewShotPromptTemplate, PromptTemplate
from langchain_core.pydantic_v1 import BaseModel
from langchain_experimental.tabular_synthetic_data.openai import (
OPENAI_TEMPLATE,
create_openai_data_generator,
)
from langchain_experimental.tabular_synthetic_data.prompts import (
SYNTHETIC_FEW_SHOT_PREFIX,
SYNTHETIC_FEW_SHOT_SUFFIX,
)
from langchain_openai import ChatOpenAI
필요한 패키지들을 로딩한다. 여기서도 불편한 점을 느낄 수 있는데 설치할 때는 langchain을 설치했으면서 langchain_core에서 기능을 불러오는 점이다. 처음 보면 langchain_core나 langchain_experimental이나 모두 langchain 안에 있을 것 같은데 그렇지 않다는 점이 참 불편하다.
아무튼 필요한 내용을 살펴보면, langchain에서 제공하는 프롬프트 템플릿과 데이터 정에 사용되는 pydantic의 Basemodel을 불러온다. pydantic이라는 말이 한국어로 번역이 안 되는데, 파이썬에서 Input 데이터가 유효한 지를 검증할 필요가 있을 때 pydantic이라는 라이브러리를 불러와서 사용할 수 있다고 한다.
그 다음 패키지들은 잘은 모르는데 패키지 이름으로 볼 때 Few-shot prompting에 필요한 Prefix와 Suffix, LLM을 불러오기 위한 템플릿과 generator를 불러오는 것 같다.
class TransactionRecord(BaseModel):
transaction_id: str
customer_id: str
transaction_amount: float
transaction_date: str
payment_method: str
product_category: str
quantity: int
customer_age: int
customer_location: str
device_used: str
ip_address: str
shipping_address: str
billing_address: str
is_fraudulent: int
account_age_days: int
transaction_hour: int
다음으로 Pydantic의 Basemodel을 파라미터로 넣은 클래스 하나를 생성하는데, 보면 알겠지만 key-value 형식으로 어떤 키엔 어떤 형식의 value가 들어가는지를 사전에 미리 정의한다. 이렇게 하면 혹시 null값이 있을 때처럼 데이터가 비정상적인 경우를 제외시킬 수 있게 된다.
examples = [
{ "example": """transaction_id: 15d2e414-8735-46fc-9e02-80b472b2580f, customer_id: d1b87f62-51b2-493b-ad6a-77e0fe13e785, transaction_amount: 58.09, transaction_date: 2024-02-20 05:58:41, payment_method: bank transfer, product_category: home & garden, quantity: 4, customer_age: 37, customer_location: Christopherland, device_used: desktop, ip_address: 211.189.218.190, shipping_address: 471 Mary Courts Apt. 872\nMaryhaven, KS 16126, billing_address: 471 Mary Courts Apt. 872\nMaryhaven, KS 16126, is_fraudulent: 1, account_age_days: 30, transaction_hour: 5"""},
{"example": """transaction_id: aa81b9ff-034d-4d8e-bec6-ed29b8ae5d54, customer_id: 37de64d5-e901-4a56-9ea0-af0c24c069cf, transaction_amount: 389.96, transaction_date: 2024-02-25 08:09:45, payment_method: debit card, product_category: electronics, quantity: 32, customer_age: 40, customer_location: East Timothy, device_used: desktop, ip_address: 208.106.249.121, shipping_address: 634 May Keys\nPort Cherylview, NV 75063, billing_address: 634 May Keys\nPort Cherylview, NV 75063, is_fraudulent: 0, account_age_days: 72, transaction_hour: 8"""},
{"example": """transaction_id: 7ac1febd-3e94-457e-bfe4-acf081dc8da0, customer_id: 1bac88d6-4b22-409a-a06b-425119c57225, transaction_amount: 134.19, transaction_date: 07/01/2024 15:41, payment_method: PayPal, product_category: electronics, quantity: 1, customer_age: 43, customer_location: Paynefurt, device_used: tablet, ip_address: 195.31.145.184, shipping_address: Unit 5864 Box 9572\nDPO AE 69746, billing_address: Unit 5864 Box 9572\nDPO AE 69746, is_fraudulent: 1, account_age_days: 15, transaction_hour: 15"""},
]
다음으로는 examples라는 리스트 하나를 만들어서 데이터를 저장해야한다. Medium 원본에는 어떻게 하는지는 나와있지 않지만 파이썬의 formatting을 사용하면 무난하게 완료할 수 있을 것이다. 그런데 Medium 에 올라와있는 examples에는 결함이 있다. 칼럼이 왠지 모르게 한 칸씩 밀린 모습인데, 혹시나 따라할 분이 있을까 싶어 직접 수정해줬다.
OPENAI_TEMPLATE = PromptTemplate(input_variables=["example"], template="{example}")
prompt_template = FewShotPromptTemplate(
prefix=SYNTHETIC_FEW_SHOT_PREFIX,
examples=examples,
suffix=SYNTHETIC_FEW_SHOT_SUFFIX,
input_variables=["subject", "extra"],
example_prompt=OPENAI_TEMPLATE,
)
템플릿을 완성하는 단계이다. 나머진 다 쉽게 이해가 되는데 input_variables가 뭔지 잠깐 헷갈려서 더 찾아봤는데 subject는 대화의 주제 (데이터의 주제), extra는 증강하길 원하는 방향 정도를 의미하는 것으로 해석된다. (공식문서 참조)
synthetic_data_generator = create_openai_data_generator(
output_schema=TransactionRecord,
llm=ChatOpenAI(
temperature=1,
api_key="add your API key here"
),
prompt=prompt_template,
)
다음으로 이 단계다. 직접적으로 synthetic한 data를 만드는 챗봇을 생성하는 단계다. 하지만 Medium에 나온 위 코드 그대로 실행하면 오류가 발생한다. 이 또한 역시 패키지 호환성 문젠데, 다음처럼 코드를 수정하고 고칠 수 있었다.
transaction_record_schema = TransactionRecord.schema()
synthetic_data_generator = create_openai_data_generator(
output_schema=transaction_record_schema,
llm=ChatOpenAI(
temperature=1,
api_key="add your API key here"
),
prompt=prompt_template,
)
github 이슈를 뒤져보니 pydantic 패키지가 업데이트되면서 저렇게 schema라고 명시를 해줘야하는 것으로 바뀌었다고 한다.
synthetic_results = synthetic_data_generator.generate(
subject="TransactionRecord",
extra="Include details typical of fraudulent e-commerce transactions, such as unusually large transaction amounts or suspicious IP addresses",
runs=15,
)
준비는 끝났고, Medium의 예시와 똑같이 코드를 돌려봤다.
정말로 그럴듯하게 생성된 모습이다. extra에 써줬던 요구사항인 비정상적으로 많은 거래금액이나 수상한 IP address도 생성해줬는지 확인해보면,
example의 transaction amount는 모두 3자리 수였던 것에 비해
1000이 훌쩍 넘어가는 거래도 생성해줬으며
ip 주소도 엉망진창인 경우가 많은 것을 확인할 수 있다.
굉장히 놀라운 결과며 langchain에 들어있는 openai data generator가 대체 어떤 모델을 쓰는지 열어보고 싶게 만든다. 근데 역시 공식문서를 찾아봐도 default에 무슨 모델이 들어있는지 확인이 안 된다. OPENAI 플랫폼에도 들어가봤는데 other model로 되어 있다.
참고로 아래는 example이 잘못된 줄 모르고 그대로 사용했을 때의 결과다.
데이터에 결함이 있었음에도 불구하고 기특하게도 잘 생성했다.
https://cookbook.openai.com/examples/sdg1
마지마그로 oepnai에서도 직접 synthetic data를 만드는 가이드를 cookbook에 올려놨다. 다음엔 위 방법을 한 번 사용해보려 한다.
'LLM' 카테고리의 다른 글
[LLM] LLM으로 Tabular Data 학습해보기 - 2. 이진분류 (경정데이터분석) (7) | 2024.09.29 |
---|---|
[LLM] LLM으로 Tabular Data 학습해보기 - 1. GPT4o Finetuning (경정데이터분석) (9) | 2024.09.20 |
[LLM] OPENAI 새로운 모델 ChatGPT o1 사용 후기 (10) | 2024.09.15 |
LLM - ChatGPT로 학습 데이터를 생성하는 방법 - 텍스트 데이터, 프롬프트 엔지니어링 (0) | 2024.03.27 |
[LLM] Deeplearning.AI Langchain 강의 내용 정리 (0) | 2024.02.10 |