watsonx를 사용하여 Python에서 Granite 모델 프롬프트 조정

작성자

Anna Gutowska

AI Engineer, Developer Advocate

IBM

프롬프트 조정이란 무엇인가요?

이 튜토리얼에서는 반려견 미용 사업에 대한 고객 리뷰가 포함된 합성 데이터 세트를 사용하여 IBM Granite 모델을 신속하게 조정해 보겠습니다.

프롬프트 조정은 전체 모델을 재교육하고 가중치를 업데이트하지 않고도 인공 지능(AI) 파운데이션 모델을 새로운 다운스트림 작업에 적응시키는 효율적이고 저렴한 방법입니다.

LLM 최적화 개요

파운데이션 모델은 대규모 언어 모델(LLM)을 기반으로 구축되며 대량의 학습 데이터를 수신합니다. 파운데이션 모델의 일반적인 사용 사례는 챗봇과 가상 어시스턴트입니다.

파운데이션 모델의 입력 해석 및 응답 품질을 개선하는 방법에는 여러 가지가 있습니다. 이러한 뉘앙스를 더 잘 이해하기 위해 몇 가지 방법을 비교해 보겠습니다.

  • 프롬프트 엔지니어링은 잘 설계된 프롬프트를 제공하여 사전 학습된 모델의 응답을 최적화하는 것입니다. 이 기술을 사용하여 새로운 데이터가 도입되지 않으며 모델은 그대로 유지됩니다. 이 방법을 사용하면 모델은 입력 프롬프트와 그 앞에 엔지니어링 프롬프트를 수신합니다. 예를 들어 "영어를 스페인어로 번역해 주세요"이라는 프롬프트를 사용하고 "good morning"을 입력할 수 있습니다. 이 방법을 사용하려면 사용자의 작업이 더 많이 필요합니다. 그러나 효과적인 프롬프트를 공식화하기 위한 인간의 수동 노력은 생성형 AI 모델이 전체 파운데이션 모델을 재훈련하지 않고도 작업별 응답을 생성하는 데 도움이 됩니다.
  • 대규모 언어 모델을 미세 조정하려면 레이블이 지정된 데이터 세트를 대량으로 제공하여 동일한 모델을 조정해야 합니다. 미세 조정은 모델 가중치를 변경하며, 작업이 다양해짐에 따라 관리하기가 어려워집니다. 이를 위해서는 상당량의 계산 리소스가 필요합니다. 결과적으로 이 방법은 매우 구체적인 사용 사례에 대해 모델을 훈련할 수 있기 때문에 정확도가 가장 높은 경향이 있습니다.
  • 미세 조정과 달리 프롬프트 조정은 사전 훈련된 모델 가중치를 변경하지 않습니다. 대신 이 기술은 프롬프트 매개변수를 조정하여 모델의 응답을 선호하는 방향으로 안내하므로 매개변수 효율적입니다. 모델에는 AI 자체에서 생성된 입력 및 조정 가능한 프롬프트가 제공됩니다. 이 작업별 컨텍스트는 제한된 데이터로도 범위가 좁은 작업에 대한 응답을 조정하도록 대규모 모델을 가이드합니다.
  • 프롬프트 조정과 마찬가지로 접두사 조정은 모델이 선호하는 아웃풋의 몇 가지 예를 수신하는 것을 포함합니다. 여기서 차이점은 일련의 작업별 벡터인 접두사도 포함된다는 것입니다. 접두사 조정에는 소프트 프롬프트와 딥 러닝 모델의 계층에 주입된 프롬프트가 모두 포함됩니다. 이와 같은 소위 "가상 토큰"을 통해 조정된 모델은 한 번에 다양한 새로운 작업을 지원할 수 있는 유연성을 얻을 수 있습니다. 이 방법은 모든 계층을 미세 조정하는 것과 유사한 성능을 달성하며, 매개변수의 약 0.1%만 학습합니다. 접두사 조정은 데이터가 적은 설정에서도 미세 조정보다 성능이 뛰어납니다.

소프트 프롬프트와 하드 프롬프트의 비교

하드 프롬프트는 사용자를 대상으로 하며, 사용자의 조치가 필요합니다. 하드 프롬프트는 LLM이 응답을 생성하기 위한 템플릿 또는 지침으로 볼 수 있습니다. 하드 프롬프트의 예를 소개합니다. IBM 문서 페이지를 확인해 보실 것을 권장합니다. 이 프롬프트 유형과 기타 여러 유형에 대한 자세한 내용은 다음을 참조하세요.

###For demonstration purposes only. It is not necessary to run this code block.
hard_prompt_template = """Generate a summary of the context that answers the question. Explain the answer in multiple steps if possible.
Answer style should match the context. Ideal Answer length is 2-3 sentences.\n\n{context}\nQuestion: {question}\nAnswer:
"""

이 하드 프롬프트 템플릿을 사용하면 LLM에 선호하는 아웃풋 구조 및 스타일에 대한 특정 지침을 제공할 수 있습니다. 이 프롬프트를 통해 LLM이 보다 양질의 바람직한 응답을 생성할 가능성이 높아집니다.

하드 프롬프트와 달리 소프트 프롬프트는 자연어로 작성되지 않습니다. 대신 프롬프트는 각 입력 임베딩의 시작 부분에 추가된 AI 생성 수치 벡터로 초기화됩니다. 이 입력 임베딩은 더 큰 모델에서 지식을 추출합니다. 이러한 해석 가능성 부족은 주어진 작업에 최적화된 프롬프트를 선택하는 AI에게로 확장됩니다. 즉, AI가 이러한 임베딩을 선택한 이유를 설명하지 못하는 경우가 많습니다. 다른 프롬프트 방법과 비교할 때 이러한 토큰은 모델 자체가 고정된 가중치로 동결된 상태로 유지되기 때문에 미세 조정보다 계산 비용이 낮습니다. 또한 소프트 프롬프트의 성능은 인간이 설계한 하드 프롬프트를 능가하는 경향이 있습니다.

이 튜토리얼에서는 프롬프트 조정을 위해 소프트 프롬프트로 작업하겠습니다.

전제조건

watsonx.ai 프로젝트를 생성하려면 IBM Cloud 계정이 필요합니다.

단계

1단계. 환경 설정

여러 툴 중에서 선택할 수 있지만, 이 튜토리얼에서는 Jupyter Notebook을 사용하기 위해 IBM 계정을 설정하는 방법을 안내합니다.

  1. IBM Cloud 계정을 사용하여 watsonx.ai에 로그인합니다.

  2. watsonx.ai 프로젝트를 생성합니다.

    프로젝트 내에서 프로젝트 ID를 가져올 수 있습니다. 관리 탭을 클릭합니다. 그런 다음 일반 페이지의 세부 정보 섹션에서 프로젝트 ID를 복사합니다. 이 튜토리얼에는 이 ID가 필요합니다.

  3. Jupyter Notebook을 만듭니다.

    이 단계에서는 이 튜토리얼의 코드를 복사하여 프롬프트 조정을 직접 구현할 수 있는 Notebook 환경이 열립니다. 또는 이 노트북을 로컬 시스템에 다운로드하여 watsonx.ai 프로젝트에 에셋으로 업로드할 수 있습니다. 이 Jupyter Notebook과 함께 사용된 데이터 세트는 GitHub에서 확인할 수 있습니다.

2단계. watsonx.ai 런타임 인스턴스 및 API 키 설정

  1. watsonx.ai 런타임 서비스 인스턴스를 만듭니다(적절한 지역을 선택하고 무료 인스턴스인 Lite 요금제를 선택합니다).

  2. API 키를 생성합니다.

  3. watsonx.ai 런타임 서비스 인스턴스를 watsonx.ai에서 생성한 프로젝트에 연결합니다.

3단계. 관련 라이브러리 설치, 가져오기 및 자격 증명 설정

이 튜토리얼에는 몇 가지 라이브러리와 모듈이 필요합니다. 다음 항목을 가져와야 합니다. 설치되지 않은 경우, 빠른 PIP 설치로 이 문제를 해결할 수 있습니다.

#installations
%pip install ibm-watsonx-ai | tail -n 1
%pip install pandas | tail -n 1
%pip install wget | tail -n 1
%pip install scikit-learn | tail -n 1
%pip install matplotlib | tail -n 1 #imports
import wget
import pandas as pd

from ibm_watsonx_ai import APIClient
from ibm_watsonx_ai.foundation_models.utils.enums import ModelTypes
from ibm_watsonx_ai.experiment import TuneExperiment
from ibm_watsonx_ai.helpers import DataConnection
from ibm_watsonx_ai.foundation_models import ModelInference
from sklearn.metrics import accuracy_score, f1_score
from datetime import datetime

자격 증명을 설정합니다. API 키와 프로젝트 ID를 입력합니다.

credentials = {
    "url": "https://us-south.ml.cloud.ibm.com",
    "apikey": "YOUR_API_KEY_HERE"
}

project_id = "YOUR_PROJECT_ID_HERE"

4단계. 환경 설정 및 데이터 세트 가져오기

환경 설정의 첫 번째 단계로 인증 세부 정보를 사용하여 APIClient 인스턴스를 만들고 project_id를 설정합니다.

client = APIClient(credentials)
client.set.default_project(project_id)

아웃풋

'SUCCESS'

이 튜토리얼에서는 반려견 미용 비즈니스 리뷰로 구성된 합성 데이터 세트를 사용합니다. 적절한 URL을 사용하여 데이터 세트를 API 클라이언트에 연결할 수 있습니다.

원하는 데이터 세트를 자유롭게 사용할 수 있습니다. HuggingFace와 같은 플랫폼에서 여러 오픈 소스 데이터 세트를 사용할 수 있습니다.

train_filename = 'dog_grooming_reviews_train_data.json'

url = "https://raw.githubusercontent.com/AnnaGutowska/think/main/tutorials/prompt-tuning-tutorial/" + train_filename
wget.download(url)

asset_details = client.data_assets.create(name=train_filename, file_path=train_filename)
asset_id = client.data_assets.get_id(asset_details)

아웃풋:

데이터 자산 생성 중...

SUCCESS

print(asset_id)

아웃풋

3b1db894-8d9e-428d-8fee-d96f328c7726

이러한 고객 후기의 형식에 대한 통찰력을 얻기 위해 데이터를 Pandas 데이터 프레임에 로드하고 긍정적인 후기와 부정적인 후기를 모두 보여주는 행 몇 개를 인쇄해 보겠습니다. 아웃풋 '1'은 긍정적인 후기를 나타내고 '0'은 부정적인 후기를 나타냅니다.

pd.set_option('display.max_colwidth', None)
df = pd.read_json(train_filename)
df[5:10]

아웃풋:

댓글 예시와 관련 값 1과 0(1은 긍정적인 댓글, 0은 부정적인 댓글)이 포함된 학습 데이터 세트의 스크린샷 학습 데이터 세트

5단계. 모델 조정

TuneExperiment 클래스는 실험을 생성하고 조정을 예약하는 데 사용됩니다. 이를 사용하여 실험을 초기화하고 기본 파운데이션 모델, 훈련 데이터 및 매개변수를 설정해 보겠습니다. 이 프롬프트 조정 연습의 목표는 LLM이 데이터 세트에서 추출한 고객 만족도 등급에 따라 응답을 조정하는 것입니다. 후기는 긍정적인 후기("1") 또는 부정적인 후기("0")로 분류될 수 있으므로, 이 작업은 분류 작업입니다.

이 튜토리얼에서는 비슷한 결과를 얻기 위해 IBM Granite Model을 대규모 언어 모델로 사용하도록 제안합니다.

experiment = TuneExperiment(credentials,
    project_id=project_id
)

prompt_tuner = experiment.prompt_tuner(name="prompt tuning tutorial",
    task_id=experiment.Tasks.CLASSIFICATION,
    base_model="ibm/granite-3-8b-instruct",
    accumulate_steps=16,
    batch_size=8,
    learning_rate=0.001,
    max_input_tokens=128,
    max_output_tokens=2,
    num_epochs=12,
    tuning_type=experiment.PromptTuningTypes.PT,
    init_text="Extract the satisfaction from the comment. Return simple '1' for satisfied customer or '0' for unsatisfied. Comment:",
    init_method="text",
    verbalizer="classify {0, 1} {{input}}",
    auto_update_model=True
)

이제 조정 실험을 설정했으므로 데이터 세트에 연결해야 합니다. 이를 위해 DataConnection 클래스를 사용하겠습니다. 이를 위해서는 앞서 API 클라이언트로 데이터 자산을 시작할 때 생성한 asset_id이 필요합니다.

data_conn = DataConnection(data_asset_id=asset_id)

물론 원하는 AI 모델을 자유롭게 사용해도 됩니다. watsonx를 통해 조정할 수 있는 파운데이션 모델은 여기에서 확인할 수 있으며, 다음 명령을 실행하여 찾을 수도 있습니다.

client.foundation_models.PromptTunableModels.show()

아웃풋:

{'FLAN_T5_XL': 'google/flan-t5-xl', 'GRANITE_13B_INSTRUCT_V2': 'ibm/granite-13b-instruct-v2', 'LLAMA_2_13B_CHAT': 'meta-llama/llama-2-13b-chat'}

tuning_details = prompt_tuner.run(
    training_data_references=[data_conn],
    background_mode=False)

아웃풋:

##############################################

Running '20671f17-ff53-470b-9bfe-04318ecb91d9'

##############################################


pending......
running....................................................................................................................................
completed
Training of '20671f17-ff53-470b-9bfe-04318ecb91d9' finished successfully.

6단계. 조정 결과 평가

신속한 조정이 완료되었는지 확인하기 위해 상태를 확인할 수 있습니다. 인쇄되는 상태가 "completed"가 아닌 경우 조정이 완료될 때까지 기다렸다가 계속하십시오.

status = prompt_tuner.get_run_status()
print(status)

아웃풋

완료

이제 프롬프트 조정 요약을 검색할 수 있습니다. 이 요약에는 손실 값이 표시됩니다. 손실 함수는 각 훈련 실행에 대해 예측 결과와 실제 결과 간의 차이를 측정합니다. 따라서 손실 값이 낮은 것이 좋습니다.

prompt_tuner.summary()

plot_learning_curve() 함수를 사용하여 모델 조정의 학습 곡선을 표시할 수도 있습니다. 0에 가깝게 평준화되는 하향 경사 곡선은 모델이 예상 아웃풋 생성을 개선하고 있음을 나타냅니다. 손실 함수 그래프 해석에 대해 자세히 알아보려면 관련 IBM watsonx 문서를 참조하세요.

prompt_tuner.plot_learning_curve()

아웃풋:

학습 곡선도 학습 곡선도

7단계. 조정된 모델 배포

조정된 모델을 배포하는 이 단계는 조정된 모델의 성능을 사전 조정된 모델과 비교하는 다음 단계를 완료하는 데 중요합니다.

참고: SERVING_NAME는 고유한 값이어야 하므로 현재 날짜 및 시간으로 설정됩니다.

model_id = prompt_tuner.get_model_id()

meta_props = {
    client.deployments.ConfigurationMetaNames.NAME: "PROMP TUNE DEPLOYMENT",
    client.deployments.ConfigurationMetaNames.ONLINE: {},
    client.deployments.ConfigurationMetaNames.SERVING_NAME : datetime.now().strftime('%Y_%m_%d_%H%M%S')
}

deployment_details = client.deployments.create(model_id, meta_props)

아웃풋

######################################################################################

Synchronous deployment creation for id: '6aa5dd5c-0cc4-44e0-9730-18303e88e14a' started

######################################################################################


initializing.......................
ready

-----------------------------------------------------------------------------------------------
Successfully finished deployment creation, deployment_id='24a97b84-47d0-4490-9f5f-21ed2376fdd6'
-----------------------------------------------------------------------------------------------

8단계. 조정된 모델 테스트

이제 조정된 모델과 원래 파운데이션 모델의 성능을 모두 테스트하여 조정 프로세스의 영향을 확인해 보겠습니다. 먼저 테스트 데이터 세트를 로드해 보겠습니다. 이 데이터 세트는 조정 중에 존재하지 않았던 데이터의 하위 집합이어야 합니다. 테스트 세트도 훈련 세트보다 작은 경우가 많습니다. 또한 테스트 데이터 세트의 각 입력에는 사용자 주석의 접두사로 프롬프트가 있습니다.

test_filename = 'dog_grooming_reviews_test_data.json'
url = "https://raw.githubusercontent.com/AnnaGutowska/think/main/tutorials/prompt-tuning-tutorial/" + test_filename
wget.download(url)
data = pd.read_json(test_filename)

데이터 세트의 구조를 더 잘 이해할 수 있도록 데이터 세트의 일부를 표시해 보겠습니다.

data.head()

아웃풋:

댓글 예시와 관련 값 1과 0(1은 긍정적인 댓글, 0은 부정적인 댓글)이 포함된 학습 데이터 세트의 스크린샷 테스트 데이터 세트

테스트 데이터 세트를 로드한 후 입력과 아웃풋을 추출해 보겠습니다.

prompts = list(data.input)
satisfaction = list(data.output)
prompts_batch = ["\n".join([prompt]) for prompt in prompts]

데이터 세트의 콘텐츠를 추출한 방법을 보다 면밀히 이해하기 위해 샘플 테스트 입력과 아웃풋을 인쇄할 수도 있습니다.

prompts[0]

아웃풋:

'Extract the satisfaction from the comment. Return simple 1 for satisfied customer or 0 for unsatisfied.\nComment: Long wait times.\nSatisfaction:\n'

이 예에서는 프롬프트가 도입된 후 긴 대기 시간을 언급하는 고객 후기가 나오고, 마지막으로 만족도가 0으로 표시되어 부정적인 후기를 나타냅니다.

satisfaction[0]

아웃풋

0

이제 데이터 세트가 있으므로 조정된 모델의 정확도와 F1 점수를 테스트해 보겠습니다. F1 점수는 모델의 정밀도와 재현율의 평균입니다. 이 테스트를 실시하려면 deployment_id가 필요합니다. API의 속도 제한에 도달하지 않도록 concurrency_limit 는 2로 설정됩니다. 이는 병렬로 전송될 요청 수입니다.

deployment_id = deployment_details['metadata']['id']

tuned_model = ModelInference(
    deployment_id=deployment_id,
    api_client=client
)

tuned_model_results = tuned_model.generate_text(prompt=prompts_batch, concurrency_limit=2)
print(f'accuracy_score: {accuracy_score(satisfaction, [int(float(x)) for x in tuned_model_results])}, f1_score: {f1_score(satisfaction, [int(float(x)) for x in tuned_model_results])}')

아웃풋:

accuracy_score: 0.9827586206896551, f1_score: 0.9827586206896551

모델의 높은 정확도와 F1 점수를 고려하여 조정 없이 동일한 Granite 모델의 성능을 테스트해 보겠습니다.

base_model = ModelInference(
    model_id="ibm/granite-3-8b-instruct",
    api_client=client
)

base_model_results = base_model.generate_text(prompt=prompts_batch, concurrency_limit=2)

print(f'base model accuracy_score: {accuracy_score(satisfaction, [int(x) for x in base_model_results])}, base model f1_score: {f1_score(satisfaction, [int(x) for x in base_model_results])}')

아웃풋:

base model accuracy_score: 0.9310344827586207, base model f1_score: 0.9298245614035088

조정된 모델은 사전 조정된 파운데이션 모델보다 성능이 뛰어납니다. 조정된 모델은 만족도 점수 추출에 특화되어 있으므로 다른 만족도 추출 작업에 사용할 수 있습니다. 잘하셨습니다!

요약

이 튜토리얼에서는 watsonx API를 사용하여 IBM Granite 모델에서 프롬프트 조정을 수행했습니다. 조정 및 배포된 모델은 약 5% 더 높은 정확도로 파운데이션 모델을 성공적으로 능가했습니다.

관련 솔루션
IBM® watsonx.ai

AI 빌더를 위한 차세대 엔터프라이즈 스튜디오인 IBM watsonx.ai로 생성형 AI, 파운데이션 모델 및 머신 러닝 기능을 학습, 검증, 조정 및 배포하세요. 적은 데이터로 짧은 시간 내에 AI 애플리케이션을 구축하세요.

watsonx.ai 살펴보기
인공 지능 솔루션

업계 최고의 AI 전문성과 솔루션 포트폴리오를 보유한 IBM과 함께 AI를 비즈니스에 활용하세요.

AI 솔루션 살펴보기
인공 지능(AI) 컨설팅 및 서비스

IBM Consulting AI 서비스는 기업이 AI 활용 방식을 재구상하여 혁신을 달성하도록 지원합니다.

AI 서비스 살펴보기
다음 단계 안내

IBM Concert는 AI를 사용하여 운영에 관한 중요한 인사이트를 발견하고 개선을 위한 애플리케이션별 권장 사항을 제공합니다. Concert를 통해 비즈니스를 발전시키는 방법을 알아보세요.

Concert 살펴보기 비즈니스 프로세스 자동화 솔루션 살펴보기