프롬프트 엔지니어링

DSPy로 LLM 최적화: AI 시스템 구축, 최적화, 평가를 위한 단계별 가이드

mm
Unite.AI를 Google의 선호 소스에 추가
DSPy is a framework for algorithmically optimizing LM prompts and weights

대규모 언어 모델(Large Language Model, LLM)의 능력이 계속 확장됨에 따라, 그 잠재력을 활용하는 강력한 AI 시스템을 개발하는 것이 점점 더 복잡해지고 있습니다. 전통적인 접근 방식은 복잡한 프롬프트 기술, 미세 조정 데이터 생성, 및 도메인별 제약 조건을 준수하기 위한 수동 가이드를 포함합니다. 그러나 이 과정은 번거로울 수 있으며, 오류가 발생하기 쉽고, 인간의 개입에 크게 의존합니다.

이제 DSPy를 소개합니다. DSPy는 LLM을 기반으로 하는 AI 시스템 개발을 간소화하기 위해 설계된 혁신적인 프레임워크입니다. DSPy는 LM 프롬프트와 가중치를 최적화하는 체계적인 접근 방식을 도입하여 개발자가 최소한의 수동 노력으로 복잡한 응용 프로그램을 구축할 수 있도록 합니다.

이 всесторон적인 가이드에서는 DSPy의 핵심 원리, 모듈식 아키텍처, 및 강력한 기능을 탐구합니다. 또한 DSPy를 사용하여 LLM과 함께 AI 시스템을 개발하는 방법을 보여주는 실제 예를 살펴보겠습니다.

DSPy란 무엇이며, 왜 필요한가요?

DSPy는 프로그램의 흐름(모듈)을 각 단계의 매개변수(LM 프롬프트 및 가중치)와 분리하는 프레임워크입니다. 이 분리는 LM 프롬프트와 가중치를 체계적으로 최적화할 수 있도록 허용하여, 개발자가 복잡한 AI 시스템을 더 높은 신뢰성, 예측 가능성, 및 도메인별 제약 조건을 준수하여 구축할 수 있도록 합니다.

전통적으로, LLM을 기반으로 하는 AI 시스템을 개발하는 것은 문제를 단계로 나누고, 각 단계에 대한 복잡한 프롬프트를 작성하고, 미세 조정을 위한 합성 예제를 생성하고, LM을 특정 제약 조건을 준수하도록 수동으로 안내하는 번거로운 과정입니다. 이 접근 방식은 시간이 걸리고 오류가 발생하기 쉽습니다. 즉, 파이프라인, LM, 또는 데이터의 작은 변경은 프롬프트와 미세 조정 단계의 광범위한 재작업을 필요로 할 수 있습니다.

DSPy는 이러한 도전 과제를 해결하기 위해 새로운 패러다임을 도입합니다: 최적화기. 이러한 LM 기반 알고리즘은 개발자가 원하는 메트릭을 최대화하기 위해 LM 호출의 프롬프트와 가중치를 조정할 수 있습니다. 최적화 과정을 자동화함으로써, DSPy는 개발자가 최소한의 수동 개입으로 강력한 AI 시스템을 구축할 수 있도록 합니다.

DSPy의 모듈식 아키텍처

DSPy의 핵심에는 복잡한 AI 시스템을 구성하기 위한 모듈식 아키텍처가 있습니다. 이 프레임워크는 다양한 프롬프트 기술을 추상화하는 내장 모듈 세트를 제공합니다. 이러한 모듈은 더 큰 프로그램으로 결합하고 구성될 수 있어, 개발자가 특정 요구 사항에 맞게 복잡한 파이프라인을 구축할 수 있도록 합니다.

각 모듈은 학습 가능한 매개변수를 캡슐화합니다. 즉, 지침, 몇 가지 샘플, 및 LM 가중치가 포함됩니다. 모듈이 호출되면, DSPy의 최적화기는 이러한 매개변수를 원하는 메트릭을 최대화하기 위해 미세 조정할 수 있습니다. 이는 LM의 출력이 지정된 제약 조건 및 요구 사항을 준수하도록 보장합니다.

DSPy로 최적화

DSPy는 AI 시스템의 성능 및 신뢰성을 향상시키기 위해 설계된 강력한 최적화기를 도입합니다. 이러한 최적화기는 LM 기반 알고리즘을 사용하여 LM 호출의 프롬프트와 가중치를 조정하여, 지정된 메트릭을 최대화하고 도메인별 제약 조건을 준수합니다.

DSPy에서 사용할 수 있는 일부 주요 최적화기는 다음과 같습니다.

  1. BootstrapFewShot: 제공된 레이블된 입력 및 출력 데이터 포인트를 사용하여 몇 가지 샘플 예제를 생성합니다.
  2. BootstrapFewShotWithRandomSearch: BootstrapFewShot를 여러 번 적용하여 생성된 시연에 대한 임의 검색을 수행합니다.
  3. MIPRO: 각 단계에서 지침 및 몇 가지 샘플을 생성하고, 베이즈 최적화를 사용하여 이를 최적화합니다.
  4. BootstrapFinetune: 프롬프트 기반 DSPy 프로그램을 작은 LM의 가중치 업데이트로 디스틸합니다.

이러한 최적화기를 사용하여, 개발자는 체계적으로 AI 시스템을 최적화할 수 있으며, 높은 품질의 출력을 보장하고 도메인별 제약 조건 및 요구 사항을 준수합니다.

DSPy 시작하기

DSPy의 강점을 설명하기 위해, RAG(检索 증강 생성) 시스템을 구축하는 실제 예를 살펴보겠습니다.

단계 1: 언어 모델 및 검색 모델 설정

첫 번째 단계는 DSPy 내에서 언어 모델(LM) 및 검색 모델(RM)을 구성하는 것입니다.

DSPy를 설치하려면 다음을 실행하십시오.


pip install dspy-ai

DSPy는 여러 LM 및 RM API를 지원하며, 로컬 모델 호스팅도 지원하므로, 원하는 모델을 쉽게 통합할 수 있습니다.


import dspy

<p># LM 및 RM 구성
turbo = dspy.OpenAI(model='gpt-3.5-turbo')
colbertv2_wiki17_abstracts = dspy.ColBERTv2(url='http://20.102.90.50:2017/wiki17_abstracts')</p>

<p>dspy.settings.configure(lm=turbo, rm=colbertv2_wiki17_abstracts)</p>

단계 2: 데이터 세트 로드

다음으로, HotPotQA 데이터 세트를 로드하여, 복잡한 질문-답변 쌍을 포함하는 데이터 세트를 생성합니다.


from dspy.datasets import HotPotQA

<p># 데이터 세트 로드
dataset = HotPotQA(train_seed=1, train_size=20, eval_seed=2023, dev_size=50, test_size=0)</p>

<p># '질문' 필드를 입력으로 지정
trainset = [x.with_inputs('question') for x in dataset.train]
devset = [x.with_inputs('question') for x in dataset.dev]</p>

단계 3: 서명 생성

DSPy는 서명을 사용하여 모듈의 동작을 정의합니다. 이 예에서는, 답변 생성 작업을 위한 서명을 정의하여, 입력 필드(문맥 및 질문) 및 출력 필드(답변)를 지정합니다.


<p>class GenerateAnswer(dspy.Signature):
"""짧은 팩트 답변을 가진 질문에 답변합니다."""

context = dspy.InputField(desc="관련 사실을 포함할 수 있음")
question = dspy.InputField()
answer = dspy.OutputField(desc="종종 1~5 단어 사이임")

단계 4: 파이프라인 구축

RAG 파이프라인을 DSPy 모듈로 구축하여, 서브 모듈(dspy.Retrieve 및 dspy.ChainOfThought)을 선언하는 초기화 메서드(__init__) 및 제어 흐름을 설명하는 전진 메서드(forward)를 포함합니다.


<p>class RAG(dspy.Module):
def __init__(self, num_passages=3):
super().__init__()

self.retrieve = dspy.Retrieve(k=num_passages)
self.generate_answer = dspy.ChainOfThought(GenerateAnswer)

def forward(self, question):
context = self.retrieve(question).passages
prediction = self.generate_answer(context=context, question=question)
return dspy.Prediction(context=context, answer=prediction.answer)

단계 5: 파이프라인 최적화

파이프라인을 정의한 후, 이제 DSPy의 최적화기를 사용하여 이를 최적화할 수 있습니다. 이 예에서는, BootstrapFewShot 최적화기를 사용하여, 훈련 세트 및 검증 메트릭을 기반으로 효과적인 프롬프트를 생성합니다.


<p>from dspy.teleprompt import BootstrapFewShot</p>

<p># 검증 메트릭
def validate_context_and_answer(example, pred, trace=None):
answer_EM = dspy.evaluate.answer_exact_match(example, pred)
answer_PM = dspy.evaluate.answer_passage_match(example, pred)
return answer_EM and answer_PM

<p># 최적화기 설정
teleprompter = BootstrapFewShot(metric=validate_context_and_answer)

<p># 프로그램 컴파일
compiled_rag = teleprompter.compile(RAG(), trainset=trainset)

단계 6: 파이프라인 평가

프로그램을 컴파일한 후, 원하는 정확도 및 신뢰성을 확보하기 위해 개발 세트에서 성능을 평가하는 것이 중요합니다.


from dspy.evaluate import Evaluate

<p># 평가기 설정
evaluate = Evaluate(devset=devset, metric=validate_context_and_answer, num_threads=4, display_progress=True, display_table=0)

<p># 컴파일된 RAG 프로그램 평가
evaluation_result = evaluate(compiled_rag)

<p>print(f"평가 결과: {evaluation_result}")

단계 7: 모델 기록 검사

더 깊은 이해를 위해, 모델의 상호 작용을 검사하여, 가장 최근의 생성을 검사할 수 있습니다.


<p># 모델 기록 검사
turbo.inspect_history(n=1)

단계 8: 예측

파이프라인을 최적화하고 평가한 후, 이제 이를 새로운 질문에 대해 예측할 수 있습니다.


<p># 예제 질문
question = "게리 주카브의 첫 번째 책은 어떤 상을 받았나요?"

<p># 컴파일된 RAG 프로그램을 사용하여 예측
prediction = compiled_rag(question)

<p>print(f"질문: {question}")
print(f"답변: {prediction.answer}")
print(f"검색된 문맥: {prediction.context}")

DSPy를 사용한 최소한의 예

이제, DSPy를 사용하여 GSM8K 데이터 세트와 OpenAI GPT-3.5-turbo 모델을 사용하여 프롬프팅 작업을 시뮬레이션하는 또 다른 최소한의 예를 살펴보겠습니다.

설정

먼저, 환경을 올바르게 구성해야 합니다.


<p>import dspy
from dspy.datasets.gsm8k import GSM8K, gsm8k_metric

<p># LM 설정
turbo = dspy.OpenAI(model='gpt-3.5-turbo-instruct', max_tokens=250)
dspy.settings.configure(lm=turbo)

<p># GSM8K 데이터 세트 로드
gsm8k = GSM8K()
gsm8k_trainset, gsm8k_devset = gsm8k.train[:10], gsm8k.dev[:10]

print(gsm8k_trainset)

모듈 정의

다음으로, 체인 오브 사고 모듈을 사용하여 단계별推論을 수행하는 사용자 정의 프로그램을 정의합니다.


<p>class CoT(dspy.Module):
def __init__(self):
super().__init__()
self.prog = dspy.ChainOfThought("질문 -&gt; 답변")

def forward(self, question):
return self.prog(question=question)

모델 컴파일 및 평가

이제, BootstrapFewShot 텔레프롬프터를 사용하여 이를 컴파일합니다.


<p>from dspy.teleprompt import BootstrapFewShot</p>

<p># 최적화기 설정
config = dict(max_bootstrapped_demos=4, max_labeled_demos=4)

<p># 최적화
teleprompter = BootstrapFewShot(metric=gsm8k_metric, **config)
optimized_cot = teleprompter.compile(CoT(), trainset=gsm8k_trainset)

<p># 평가기 설정
from dspy.evaluate import Evaluate

<p># 평가
evaluate = Evaluate(devset=gsm8k_devset, metric=gsm8k_metric, num_threads=4, display_progress=True, display_table=0)
evaluate(optimized_cot)

<p># 모델 기록 검사
turbo.inspect_history(n=1)

이 예는 환경을 설정하고, 사용자 정의 모듈을 정의하고, 모델을 컴파일 및 평가하는 방법을 보여줍니다.

DSPy의 데이터 관리

DSPy는 훈련, 개발, 및 테스트 세트를 사용합니다. 각 데이터 예제에는 일반적으로 세 가지 유형의 값이 있습니다: 입력, 중간 레이블, 및 최종 레이블.

예제 객체 생성

DSPy의 예제 객체는 유용한 유틸리티를 제공하는 Python 사전과 유사합니다.


<p>qa_pair = dspy.Example(question="이것은 질문입니다?", answer="이것은 답변입니다.")

<p>print(qa_pair)
print(qa_pair.question)
print(qa_pair.answer)

출력:


<p>Example({'question': '이것은 질문입니다?', 'answer': '이것은 답변입니다.'}) (input_keys=None)
이것은 질문입니다?
이것은 답변입니다.

입력 키 지정

DSPy의 예제 객체에는 특정 필드를 입력으로 표시하는 with_inputs() 메서드가 있습니다.


<p>print(qa_pair.with_inputs("question"))
print(qa_pair.with_inputs("question", "answer"))

값은 점 연산자를 사용하여 액세스할 수 있으며, inputs() 및 labels()와 같은 메서드는 입력 또는 非입력 키만 포함하는 새 예제 객체를 반환합니다.

DSPy의 최적화기

DSPy 최적화기는 DSPy 프로그램의 매개변수(즉, 프롬프트 및/또는 LM 가중치)를 지정된 메트릭을 최대화하기 위해 조정합니다. DSPy에는 다양한 내장 최적화기가 있습니다.

사용 가능한 최적화기

  • BootstrapFewShot: 제공된 레이블된 입력 및 출력 데이터 포인트를 사용하여 몇 가지 샘플 예제를 생성합니다.
  • BootstrapFewShotWithRandomSearch: BootstrapFewShot를 여러 번 적용하여 생성된 시연에 대한 임의 검색을 수행합니다.
  • COPRO: 각 단계에서 지침 및 몇 가지 샘플을 생성하고, 좌표 상승을 사용하여 이를 최적화합니다.
  • MIPRO: 지침 및 몇 가지 샘플을 최적화하기 위해 베이즈 최적화를 사용합니다.

최적화기 선택

만약 시작하는 데에서 막히면, BootstrapFewShotWithRandomSearch를 사용하십시오.

데이터가 거의 없는 경우(10개의 예제), BootstrapFewShot를 사용하십시오.
데이터가 조금 더 많은 경우(50개의 예제), BootstrapFewShotWithRandomSearch를 사용하십시오.
대규모 데이터 세트(300개 이상의 예제)에서는 MIPRO를 사용하십시오.

BootstrapFewShotWithRandomSearch를 사용하는 방법은 다음과 같습니다.


<p>from dspy.teleprompt import BootstrapFewShotWithRandomSearch</p>

<p>config = dict(max_bootstrapped_demos=4, max_labeled_demos=4, num_candidate_programs=10, num_threads=4)
teleprompter = BootstrapFewShotWithRandomSearch(metric=YOUR_METRIC_HERE, **config)
optimized_program = teleprompter.compile(YOUR_PROGRAM_HERE, trainset=YOUR_TRAINSET_HERE)

최적화된 프로그램 저장 및 로드

최적화기를 실행한 후, 프로그램을 저장하여 나중에 사용할 수 있습니다.

optimized_program.save(YOUR_SAVE_PATH)

저장된 프로그램을 로드합니다.


<p>loaded_program = YOUR_PROGRAM_CLASS()
loaded_program.load(path=YOUR_SAVE_PATH)

고급 기능: DSPy 어서션

DSPy 어서션은 LM의 계산 제약을 자동으로 적용하여, LM 출력의 신뢰성, 예측 가능성, 및 올바름을 향상시킵니다.

어서션 사용

검증 함수를 정의하고, 모델 생성 후에 어서션을 선언합니다.


<p>dspy.Suggest(
len(query) &lt;= 100,
&quot;질문은 짧고 100자 이하여야 합니다.&quot;,
)

<p>dspy.Suggest(
validate_query_distinction_local(prev_queries, query),
"질문은 다음에서 구별되어야 합니다.: " + "; ".join(f"{i+1}) {q}" for i, q in enumerate(prev_queries)),
)

프로그램 변환


<p>from dspy.primitives.assertions import assert_transform_module, backtrack_handler</p>

<p>baleen_with_assertions = assert_transform_module(SimplifiedBaleenAssertions(), backtrack_handler)

<p>또는 프로그램에 직접 어서션을 활성화합니다.</p>

[code language="Python"]

<p>baleen_with_assertions = SimplifiedBaleenAssertions().activate_assertions()

어서션 기반 최적화

DSPy 어서션은 DSPy 최적화와 함께 작동하며, 특히 BootstrapFewShotWithRandomSearch와 함께 작동합니다.

  • 어서션으로 컴파일
  • 어서션으로 컴파일 및 추론

결론

DSPy는 언어 모델 및 프롬프트를 최적화하는 체계적인 접근 방식을 제공합니다. 이 예제에서 설명한 단계를 따라, 복잡한 AI 시스템을 쉽게 구축, 최적화, 및 평가할 수 있습니다. DSPy의 모듈식 설계 및 고급 최적화기는 다양한 언어 모델을 효율적이고 효과적으로 통합할 수 있도록 하므로, NLP 및 AI 분야에서 작업하는 모든 사람에게 유용한 도구입니다.

단순한 질문-답변 시스템을 구축하든, 더 복잡한 파이프라인을 구축하든, DSPy는 높은 성능 및 신뢰성을 달성하는 데 필요한 유연성 및 강건성을 제공합니다.

지난 5년 동안私は Machine Learning과 Deep Learning의 매혹적인 세계에 몰두해 왔습니다.私の熱情と専門知識は私を50以上의多様한 소프트웨어 엔지니어링 프로젝트에 기여하게 했으며, 특히 AI/ML에 중점을 두었습니다.私の継続的な 호기심은 또한私를自然어 처리로 끌어들였습니다.私は이 분야를さらに 탐구하기를熱望합니다.