|
|
Google Colab에서 실행
|
|
|
GitHub에서 소스 보기
|
이 가이드에서는 도구 호출을 위해 FunctionGemma를 미세 조정하는 방법을 보여줍니다.
FunctionGemma는 기본적으로 도구를 호출할 수 있습니다. 하지만 진정한 능력은 도구 사용법에 관한 기계적 지식 (구문)과 도구를 사용해야 하는 이유와 시기를 해석하는 인지 능력 (의도)이라는 두 가지 별개의 기술에서 비롯됩니다.
모델, 특히 작은 모델은 복잡한 의도 이해를 유지하는 데 사용할 수 있는 파라미터가 적습니다. 따라서 미세 조정이 필요합니다.
도구 호출 미세 조정의 일반적인 사용 사례는 다음과 같습니다.
- 모델 증류: 더 큰 모델로 합성 학습 데이터를 생성하고 더 작은 모델을 미세 조정하여 특정 워크플로를 효율적으로 복제합니다.
- 비표준 스키마 처리: 도메인별 모바일 작업 처리와 같이 공개 데이터에서 찾을 수 없는 기존의 매우 복잡한 데이터 구조 또는 독점 형식으로 인해 기본 모델이 겪는 어려움을 극복합니다.
- 컨텍스트 사용 최적화: 모델의 가중치에 도구 정의를 '베이킹'합니다. 이렇게 하면 프롬프트에서 약식 설명을 사용하여 실제 대화를 위한 컨텍스트 창을 확보할 수 있습니다.
- 선택 모호성 해결: 외부 검색엔진보다 내부 기술 자료를 우선시하는 등 특정 기업 정책에 맞게 모델을 편향시킵니다.
이 예에서는 도구 선택의 모호성을 관리하는 데 중점을 둡니다.
개발 환경 설정
첫 번째 단계는 다양한 RLHF 및 정렬 기법을 비롯한 공개 모델을 미세 조정하기 위해 TRL 및 데이터 세트를 비롯한 Hugging Face 라이브러리를 설치하는 것입니다.
# Install Pytorch & other libraries
%pip install torch tensorboard
# Install Hugging Face libraries
%pip install transformers datasets accelerate evaluate trl protobuf sentencepiece
# COMMENT IN: if you are running on a GPU that supports BF16 data type and flash attn, such as NVIDIA L4 or NVIDIA A100
#% pip install flash-attn
참고: Ampere 아키텍처 (예: NVIDIA L4) 이상의 GPU를 사용하는 경우 플래시 어텐션을 사용할 수 있습니다. Flash Attention은 계산 속도를 크게 높이고 메모리 사용량을 시퀀스 길이의 2차에서 선형으로 줄여 학습 속도를 최대 3배까지 높이는 방법입니다. FlashAttention에서 자세히 알아보세요.
학습을 시작하기 전에 Gemma 이용약관에 동의했는지 확인해야 합니다. http://huggingface.co/google/functiongemma-270m-it의 모델 페이지에서 동의 및 액세스 저장소 버튼을 클릭하여 Hugging Face에서 라이선스를 수락할 수 있습니다.
라이선스에 동의한 후 모델에 액세스하려면 유효한 Hugging Face 토큰이 필요합니다. Google Colab 내에서 실행하는 경우 Colab 보안 비밀을 사용하여 Hugging Face 토큰을 안전하게 사용할 수 있으며, 그렇지 않은 경우 login 메서드에서 직접 토큰을 설정할 수 있습니다. 미세 조정 후 모델을 Hugging Face Hub에 푸시하므로 토큰에 쓰기 액세스 권한도 있어야 합니다.
# Login into Hugging Face Hub
from huggingface_hub import login
login()
Colab의 로컬 가상 머신에 결과를 보관할 수 있습니다. 하지만 중간 결과를 Google Drive에 저장하는 것이 좋습니다. 이렇게 하면 학습 결과가 안전해지고 최고의 모델을 쉽게 비교하고 선택할 수 있습니다.
체크포인트 디렉터리와 학습률도 조정합니다.
from google.colab import drive
mount_google_drive = False
checkpoint_dir = "functiongemma-270m-it-simple-tool-calling"
if mount_google_drive:
drive.mount('/content/drive')
checkpoint_dir = f"/content/drive/MyDrive/{checkpoint_dir}"
print(f"Checkpoints will be saved to {checkpoint_dir}")
base_model = "google/functiongemma-270m-it"
learning_rate = 5e-5
Checkpoints will be saved to functiongemma-270m-it-simple-tool-calling
미세 조정 데이터 세트 준비
search_knowledge_base와 search_google 두 도구 중에서 선택해야 하는 샘플 대화가 포함된 다음 예시 데이터 세트를 사용합니다.
간단한 도구 호출 데이터 세트
'Python에서 간단한 재귀 함수를 작성하기 위한 권장사항은 무엇인가요?'라는 질문을 생각해 보세요.
적절한 도구는 전적으로 특정 정책에 따라 다릅니다. 일반 모델은 기본적으로 search_google로 설정되지만 엔터프라이즈 애플리케이션은 일반적으로 search_knowledge_base을 먼저 확인해야 합니다.
데이터 분할 관련 참고사항: 이 데모에서는 50/50 학습-테스트 분할을 사용합니다. 프로덕션 워크플로에서는 80/20 분할이 표준이지만, 이 균등 분할은 보이지 않는 데이터에 대한 모델의 성능 개선을 강조하기 위해 특별히 선택되었습니다.
import json
from datasets import Dataset
from transformers.utils import get_json_schema
# --- Tool Definitions ---
def search_knowledge_base(query: str) -> str:
"""
Search internal company documents, policies and project data.
Args:
query: query string
"""
return "Internal Result"
def search_google(query: str) -> str:
"""
Search public information.
Args:
query: query string
"""
return "Public Result"
TOOLS = [get_json_schema(search_knowledge_base), get_json_schema(search_google)]
DEFAULT_SYSTEM_MSG = "You are a model that can do function calling with the following functions"
def create_conversation(sample):
return {
"messages": [
{"role": "developer", "content": DEFAULT_SYSTEM_MSG},
{"role": "user", "content": sample["user_content"]},
{"role": "assistant", "tool_calls": [{"type": "function", "function": {"name": sample["tool_name"], "arguments": json.loads(sample["tool_arguments"])} }]},
],
"tools": TOOLS
}
dataset = Dataset.from_list(simple_tool_calling)
# You can also load the dataset from Hugging Face Hub
# dataset = load_dataset("bebechien/SimpleToolCalling", split="train")
# Convert dataset to conversational format
dataset = dataset.map(create_conversation, remove_columns=dataset.features, batched=False)
# Split dataset into 50% training samples and 50% test samples
dataset = dataset.train_test_split(test_size=0.5, shuffle=True)
Map: 0%| | 0/40 [00:00<?, ? examples/s]
데이터 세트 배포에 관한 중요사항
shuffle=False을 자체 맞춤 데이터 세트에 사용하는 경우 소스 데이터가 미리 혼합되어 있어야 합니다. 분포를 알 수 없거나 정렬된 경우 shuffle=True를 사용하여 모델이 학습 중에 모든 도구의 균형 잡힌 표현을 학습하도록 해야 합니다.
TRL 및 SFTTrainer를 사용하여 FunctionGemma 미세 조정
이제 모델을 미세 조정할 준비가 되었습니다. Hugging Face TRL SFTTrainer를 사용하면 오픈 LLM을 감독 기반으로 미세 조정하는 것이 간단해집니다. SFTTrainer는 transformers 라이브러리의 Trainer 서브클래스이며 동일한 기능을 모두 지원합니다.
다음 코드는 Hugging Face에서 FunctionGemma 모델과 토큰화 도구를 로드합니다.
import torch
from transformers import AutoTokenizer, AutoModelForCausalLM
# Load model and tokenizer
model = AutoModelForCausalLM.from_pretrained(
base_model,
dtype="auto",
device_map="auto",
attn_implementation="eager"
)
tokenizer = AutoTokenizer.from_pretrained(base_model)
print(f"Device: {model.device}")
print(f"DType: {model.dtype}")
# Print formatted user prompt
print("--- dataset input ---")
print(json.dumps(dataset["train"][0], indent=2))
debug_msg = tokenizer.apply_chat_template(dataset["train"][0]["messages"], tools=dataset["train"][0]["tools"], add_generation_prompt=False, tokenize=False)
print("--- Formatted prompt ---")
print(debug_msg)
Device: cuda:0
DType: torch.bfloat16
--- dataset input ---
{
"messages": [
{
"content": "You are a model that can do function calling with the following functions",
"role": "developer",
"tool_calls": null
},
{
"content": "What is the reimbursement limit for travel meals?",
"role": "user",
"tool_calls": null
},
{
"content": null,
"role": "assistant",
"tool_calls": [
{
"function": {
"arguments": {
"query": "travel meal reimbursement limit policy"
},
"name": "search_knowledge_base"
},
"type": "function"
}
]
}
],
"tools": [
{
"function": {
"description": "Search internal company documents, policies and project data.",
"name": "search_knowledge_base",
"parameters": {
"properties": {
"query": {
"description": "query string",
"type": "string"
}
},
"required": [
"query"
],
"type": "object"
},
"return": {
"type": "string"
}
},
"type": "function"
},
{
"function": {
"description": "Search public information.",
"name": "search_google",
"parameters": {
"properties": {
"query": {
"description": "query string",
"type": "string"
}
},
"required": [
"query"
],
"type": "object"
},
"return": {
"type": "string"
}
},
"type": "function"
}
]
}
--- Formatted prompt ---
<bos><start_of_turn>developer
You are a model that can do function calling with the following functions<start_function_declaration>declaration:search_knowledge_base{description:<escape>Search internal company documents, policies and project data.<escape>,parameters:{properties:{query:{description:<escape>query string<escape>,type:<escape>STRING<escape>} },required:[<escape>query<escape>],type:<escape>OBJECT<escape>} }<end_function_declaration><start_function_declaration>declaration:search_google{description:<escape>Search public information.<escape>,parameters:{properties:{query:{description:<escape>query string<escape>,type:<escape>STRING<escape>} },required:[<escape>query<escape>],type:<escape>OBJECT<escape>} }<end_function_declaration><end_of_turn>
<start_of_turn>user
What is the reimbursement limit for travel meals?<end_of_turn>
<start_of_turn>model
<start_function_call>call:search_knowledge_base{query:<escape>travel meal reimbursement limit policy<escape>}<end_function_call><start_function_response>
미세 조정 전
아래 출력은 기본 제공 기능이 이 사용 사례에 적합하지 않을 수 있음을 보여줍니다.
def check_success_rate():
success_count = 0
for idx, item in enumerate(dataset['test']):
messages = [
item["messages"][0],
item["messages"][1],
]
inputs = tokenizer.apply_chat_template(messages, tools=TOOLS, add_generation_prompt=True, return_dict=True, return_tensors="pt")
out = model.generate(**inputs.to(model.device), pad_token_id=tokenizer.eos_token_id, max_new_tokens=128)
output = tokenizer.decode(out[0][len(inputs["input_ids"][0]) :], skip_special_tokens=False)
print(f"{idx+1} Prompt: {item['messages'][1]['content']}")
print(f" Output: {output}")
expected_tool = item['messages'][2]['tool_calls'][0]['function']['name']
other_tool = "search_knowledge_base" if expected_tool == "search_google" else "search_google"
if expected_tool in output and other_tool not in output:
print(" `-> ✅ correct!")
success_count += 1
elif expected_tool not in output:
print(f" -> ❌ wrong (expected '{expected_tool}' missing)")
else:
if output.startswith(f"<start_function_call>call:{expected_tool}"):
print(f" -> ⚠️ tool is correct {expected_tool}, but other_tool exists in output")
else:
print(f" -> ❌ wrong (hallucinated '{other_tool}')")
print(f"Success : {success_count} / {len(dataset['test'])}")
check_success_rate()
1 Prompt: How do I access my paystubs on the ADP portal?
Output: I cannot assist with accessing or retrieving paystubs or other company documents on the ADP portal. My current capabilities are limited to assisting with searching internal company documents and knowledge base queries.<end_of_turn>
-> ❌ wrong (expected 'search_knowledge_base' missing)
2 Prompt: What is the syntax for Python list comprehensions?
Output: I cannot assist with programming or providing programming syntax information. My current capabilities are focused on searching internal company documents and project data.<end_of_turn>
-> ❌ wrong (expected 'search_google' missing)
3 Prompt: Where can I find the floor plan for Building B?
Output: <start_function_call>call:search_knowledge_base{query:<escape>Floor plan for Building B<escape>}<end_function_call><start_function_call>call:search_google{query:<escape>Floor plan for Building B<escape>}<end_function_call><start_function_response>
-> ⚠️ tool is correct search_knowledge_base, but other_tool exists in output
4 Prompt: Check the latest stock price for Apple.
Output: <start_function_call>call:search_google{query:<escape>AAPL stock price<escape>}<end_function_call><start_function_response>
`-> ✅ correct!
5 Prompt: What is the procedure for reporting a phishing email?
Output: I cannot assist with providing instructions or procedures for reporting phishing emails. My capabilities are limited to assisting with specific search and document management functions.<end_of_turn>
-> ❌ wrong (expected 'search_knowledge_base' missing)
6 Prompt: Show me examples of using the useEffect hook in React.
Output: I am sorry, but I cannot assist with providing examples of using the `useEffect` hook in React. My current capabilities are focused on assisting with searching and retrieving internal company documents and project data using the specified tools. I cannot generate or explain code examples related to React hooks.<end_of_turn>
-> ❌ wrong (expected 'search_google' missing)
7 Prompt: Who are the direct reports for the VP of Engineering?
Output: <start_function_call>call:search_knowledge_base{query:<escape>VP of Engineering<escape>}<end_function_call><start_function_call>call:search_google{query:<escape>VP of Engineering<escape>}<end_function_call><start_function_response>
-> ⚠️ tool is correct search_knowledge_base, but other_tool exists in output
8 Prompt: How do I list open ports on a Linux server?
Output: I cannot assist with listing or querying open ports on Linux servers. My current capabilities are limited to assisting with searching internal company documents and project data using the specified tools.<end_of_turn>
-> ❌ wrong (expected 'search_google' missing)
9 Prompt: What is our Slack message retention policy?
Output: I cannot assist with finding or recommending company policies or terms of service regarding Slack messaging retention. My current capabilities are focused on searching internal company documents and project data.<end_of_turn>
-> ❌ wrong (expected 'search_knowledge_base' missing)
10 Prompt: Compare the features of iPhone 15 vs Samsung S24.
Output: I cannot assist with comparing device features or specifications. My current capabilities are focused on assisting with searching and managing company knowledge. I cannot browse or compare external product information.<end_of_turn>
-> ❌ wrong (expected 'search_google' missing)
11 Prompt: I need the expense code for team building events.
Output: I can certainly assist with searching for expense codes. Could you please specify the exact query you would like to use for searching the company expense database?<end_of_turn>
-> ❌ wrong (expected 'search_knowledge_base' missing)
12 Prompt: Best practices for writing a Dockerfile for Node.js.
Output: I am sorry, but I cannot assist with recommending best practices for writing Dockerfiles for Node.js. My current capabilities are focused on searching company documents and project data using specific tools. I cannot recommend or provide expert advice on software development best practices.<end_of_turn>
-> ❌ wrong (expected 'search_google' missing)
13 Prompt: How do I request a new monitor setup?
Output: I cannot assist with recommending or requesting hardware setup or configurations. My current capabilities are limited to assisting with searching company documents and project data using the specified tools. I cannot provide technical advice or recommendations for hardware setup.<end_of_turn>
-> ❌ wrong (expected 'search_knowledge_base' missing)
14 Prompt: What is the difference between VLOOKUP and XLOOKUP in Google Sheets?
Output: I cannot assist with comparing or contrasting Google Sheets and VLOOKUP/XLOOKUP in specific technical terms. My current capabilities are limited to assisting with specific data management functions like searching internal company documents and searching public knowledge base. I cannot provide expert comparisons or explanations of Google Sheets and VLOOKUP/XLOOKUP.<end_of_turn>
-> ❌ wrong (expected 'search_google' missing)
15 Prompt: Find the onboarding checklist for new engineering hires.
Output: <start_function_call>call:search_knowledge_base{query:<escape>onboarding checklist for new engineering hires<escape>}<end_function_call><start_function_response>
`-> ✅ correct!
16 Prompt: What are the latest release notes for the OpenAI API?
Output: <start_function_call>call:search_knowledge_base{query:<escape>OpenAI API release notes latest<escape>}<end_function_call><start_function_response>
-> ❌ wrong (expected 'search_google' missing)
17 Prompt: Do we have preferred hotel partners in Paris?
Output: I apologize, but I cannot assist with finding hotel partner information. My current capabilities are focused on searching company documents and project data using specific keywords. I cannot connect with or query business databases for hotel partnerships.<end_of_turn>
-> ❌ wrong (expected 'search_knowledge_base' missing)
18 Prompt: How to undo the last git commit but keep the changes?
Output: I cannot assist with managing or undoing Git repositories. My current capabilities are limited to assisting with searching and managing organizational knowledge bases. I cannot provide specific instructions or assistance with technical issues related to software development or Git operations.<end_of_turn>
-> ❌ wrong (expected 'search_google' missing)
19 Prompt: What is the process for creating a new Jira project?
Output: I cannot assist with creating or managing Jira project processes. My current capabilities are limited to assisting with searching company documents and project data using the specified tools.<end_of_turn>
-> ❌ wrong (expected 'search_knowledge_base' missing)
20 Prompt: Tutorial on SQL window functions.
Output: I cannot assist with tutorials or programming advice regarding SQL window functions. My capabilities are limited to assisting with searching company documents and knowledge base information.<end_of_turn>
-> ❌ wrong (expected 'search_google' missing)
Success : 2 / 20
학습
학습을 시작하기 전에 SFTConfig 인스턴스에서 사용할 초매개변수를 정의해야 합니다.
from trl import SFTConfig
torch_dtype = model.dtype
args = SFTConfig(
output_dir=checkpoint_dir, # directory to save and repository id
max_length=512, # max sequence length for model and packing of the dataset
packing=False, # Groups multiple samples in the dataset into a single sequence
num_train_epochs=8, # number of training epochs
per_device_train_batch_size=4, # batch size per device during training
gradient_checkpointing=False, # Caching is incompatible with gradient checkpointing
optim="adamw_torch_fused", # use fused adamw optimizer
logging_steps=1, # log every step
#save_strategy="epoch", # save checkpoint every epoch
eval_strategy="epoch", # evaluate checkpoint every epoch
learning_rate=learning_rate, # learning rate
fp16=True if torch_dtype == torch.float16 else False, # use float16 precision
bf16=True if torch_dtype == torch.bfloat16 else False, # use bfloat16 precision
lr_scheduler_type="constant", # use constant learning rate scheduler
push_to_hub=True, # push model to hub
report_to="tensorboard", # report metrics to tensorboard
)
이제 모델 학습을 시작하기 위한 SFTTrainer를 만드는 데 필요한 모든 구성요소가 준비되었습니다.
from trl import SFTTrainer
# Create Trainer object
trainer = SFTTrainer(
model=model,
args=args,
train_dataset=dataset['train'],
eval_dataset=dataset['test'],
processing_class=tokenizer,
)
Tokenizing train dataset: 0%| | 0/20 [00:00<?, ? examples/s] Truncating train dataset: 0%| | 0/20 [00:00<?, ? examples/s] Tokenizing eval dataset: 0%| | 0/20 [00:00<?, ? examples/s] Truncating eval dataset: 0%| | 0/20 [00:00<?, ? examples/s] The model is already on multiple devices. Skipping the move to device specified in `args`.
train() 메서드를 호출하여 학습을 시작합니다.
# Start training, the model will be automatically saved to the Hub and the output directory
trainer.train()
# Save the final model again to the Hugging Face Hub
trainer.save_model()
The tokenizer has new PAD/BOS/EOS tokens that differ from the model config and generation config. The model config and generation config were aligned accordingly, being updated with the tokenizer's values. Updated tokens: {'bos_token_id': 2, 'pad_token_id': 0}.
학습 및 검증 손실을 플롯하려면 일반적으로 TrainerState 객체 또는 학습 중에 생성된 로그에서 이러한 값을 추출합니다.
그런 다음 Matplotlib과 같은 라이브러리를 사용하여 학습 단계 또는 에포크에 걸쳐 이러한 값을 시각화할 수 있습니다. x축은 학습 단계 또는 에포크를 나타내고 y축은 해당 손실 값을 나타냅니다.
import matplotlib.pyplot as plt
# Access the log history
log_history = trainer.state.log_history
# Extract training / validation loss
train_losses = [log["loss"] for log in log_history if "loss" in log]
epoch_train = [log["epoch"] for log in log_history if "loss" in log]
eval_losses = [log["eval_loss"] for log in log_history if "eval_loss" in log]
epoch_eval = [log["epoch"] for log in log_history if "eval_loss" in log]
# Plot the training loss
plt.plot(epoch_train, train_losses, label="Training Loss")
plt.plot(epoch_eval, eval_losses, label="Validation Loss")
plt.xlabel("Epoch")
plt.ylabel("Loss")
plt.title("Training and Validation Loss per Epoch")
plt.legend()
plt.grid(True)
plt.show()

모델 추론 테스트
학습이 완료되면 모델을 평가하고 테스트해야 합니다. 테스트 데이터 세트에서 다양한 샘플을 로드하고 해당 샘플에서 모델을 평가할 수 있습니다.
check_success_rate()
1 Prompt: How do I access my paystubs on the ADP portal?
Output: <start_function_call>call:search_knowledge_base{query:<escape>paystubs API portal access codes<escape>}<end_function_call><start_function_response>
`-> ✅ correct!
2 Prompt: What is the syntax for Python list comprehensions?
Output: <start_function_call>call:search_google{query:<escape>Python list comprehensions syntax<escape>}<end_function_call><start_function_response>
`-> ✅ correct!
3 Prompt: Where can I find the floor plan for Building B?
Output: <start_function_call>call:search_knowledge_base{query:<escape>floor plan Building B floor plan<escape>}<end_function_call><start_function_response>
`-> ✅ correct!
4 Prompt: Check the latest stock price for Apple.
Output: <start_function_call>call:search_google{query:<escape>latest stock price Apple<escape>}<end_function_call><start_function_response>
`-> ✅ correct!
5 Prompt: What is the procedure for reporting a phishing email?
Output: <start_function_call>call:search_knowledge_base{query:<escape>phishing email procedure reporting policy<escape>}<end_function_call><start_function_response>
`-> ✅ correct!
6 Prompt: Show me examples of using the useEffect hook in React.
Output: <start_function_call>call:search_knowledge_base{query:<escape>useEffect hook examples React<escape>}<end_function_call><start_function_response>
-> ❌ wrong (expected 'search_google' missing)
7 Prompt: Who are the direct reports for the VP of Engineering?
Output: <start_function_call>call:search_knowledge_base{query:<escape>VP of Engineering direct reports<escape>}<end_function_call><start_function_response>
`-> ✅ correct!
8 Prompt: How do I list open ports on a Linux server?
Output: <start_function_call>call:search_google{query:<escape>open ports Linux server equivalents<escape>}<end_function_call><start_function_response>
`-> ✅ correct!
9 Prompt: What is our Slack message retention policy?
Output: <start_function_call>call:search_knowledge_base{query:<escape>slack message retention policy policy excerpt<escape>}<end_function_call><start_function_response>
`-> ✅ correct!
10 Prompt: Compare the features of iPhone 15 vs Samsung S24.
Output: <start_function_call>call:search_google{query:<escape>iPhone 15 vs Samsung S24 feature comparison<escape>}<end_function_call><start_function_response>
`-> ✅ correct!
11 Prompt: I need the expense code for team building events.
Output: <start_function_call>call:search_knowledge_base{query:<escape>expense code team building events<escape>}<end_function_call><start_function_response>
`-> ✅ correct!
12 Prompt: Best practices for writing a Dockerfile for Node.js.
Output: <start_function_call>call:search_knowledge_base{query:<escape>Docker file best practices Node.js<escape>}<end_function_call><start_function_response>
-> ❌ wrong (expected 'search_google' missing)
13 Prompt: How do I request a new monitor setup?
Output: <start_function_call>call:search_knowledge_base{query:<escape>new monitor setup request procedure<escape>}<end_function_call><start_function_response>
`-> ✅ correct!
14 Prompt: What is the difference between VLOOKUP and XLOOKUP in Google Sheets?
Output: <start_function_call>call:search_google{query:<escape>VLOOKUP vs XLOOKUP difference Google Sheets中<escape>}<end_function_call><start_function_response>
`-> ✅ correct!
15 Prompt: Find the onboarding checklist for new engineering hires.
Output: <start_function_call>call:search_knowledge_base{query:<escape>engineering hire onboarding checklist New hires.<escape>}<end_function_call><start_function_response>
`-> ✅ correct!
16 Prompt: What are the latest release notes for the OpenAI API?
Output: <start_function_call>call:search_google{query:<escape>latest OpenAI API release notes latest version<escape>}<end_function_call><start_function_response>
`-> ✅ correct!
17 Prompt: Do we have preferred hotel partners in Paris?
Output: <start_function_call>call:search_knowledge_base{query:<escape>preferred hotel partners in Paris<escape>}<end_function_call><start_function_response>
`-> ✅ correct!
18 Prompt: How to undo the last git commit but keep the changes?
Output: <start_function_call>call:search_knowledge_base{query:<escape>undo git commit last commit<escape>}<end_function_call><start_function_response>
-> ❌ wrong (expected 'search_google' missing)
19 Prompt: What is the process for creating a new Jira project?
Output: <start_function_call>call:search_knowledge_base{query:<escape>Jira project creation process<escape>}<end_function_call><start_function_response>
`-> ✅ correct!
20 Prompt: Tutorial on SQL window functions.
Output: <start_function_call>call:search_knowledge_base{query:<escape>SQL window functions tutorial<escape>}<end_function_call><start_function_response>
-> ❌ wrong (expected 'search_google' missing)
Success : 16 / 20
요약 및 다음 단계
특정 엔터프라이즈 정책에 따라 모델이 중복되는 도구 (예: 내부 검색과 외부 검색) 중에서 선택해야 하는 시나리오인 도구 선택 모호성을 해결하기 위해 FunctionGemma를 미세 조정하는 방법을 배웠습니다. 이 튜토리얼에서는 Hugging Face TRL 라이브러리와 SFTTrainer를 사용하여 데이터 세트를 준비하고, 초매개변수를 구성하고, 지도 미세 조정 루프를 실행하는 과정을 안내했습니다.
결과는 '유능한' 기본 모델과 '프로덕션 준비' 미세 조정 모델 간의 중요한 차이점을 보여줍니다.
- 세부 조정 전: 기본 모델은 특정 정책을 준수하는 데 어려움을 겪었으며, 도구를 호출하지 못하거나 잘못된 도구를 선택하는 경우가 많아 성공률이 낮았습니다 (예: 2/20).
- 미세 조정 후: 8번의 에포크 동안 학습한 후 모델은 search_knowledge_base가 필요한 질문과 search_google이 필요한 질문을 올바르게 구분하여 성공률을 높였습니다 (예: 16/20).
미세 조정된 모델이 있으므로 다음 단계를 고려하여 프로덕션으로 이동하세요.
- 데이터 세트 확장: 현재 데이터 세트는 데모에 사용된 작은 합성 분할 (50/50)입니다. 강력한 엔터프라이즈 애플리케이션을 위해서는 특이 사례와 드문 정책 예외를 포함하는 더 크고 다양한 데이터 세트를 선별하세요.
- RAG를 사용한 평가: 미세 조정된 모델을 검색 증강 생성 (RAG) 파이프라인에 통합하여
search_knowledge_base도구 호출이 실제로 관련 문서를 검색하고 정확한 최종 답변을 생성하는지 확인합니다.
다음 문서를 확인하세요.
Google Colab에서 실행
GitHub에서 소스 보기