튜토리얼: 수학 추론

튜토리얼: 수학 추론 (Math Reasoning)

dspy.ChainOfThought 모듈을 설정하고 이를 대수(algebra) 문제 답변을 위해 최적화하는 quick example을 함께 살펴볼게요.

최신 DSPy를 pip install -U dspy로 설치하고 따라와 보세요. 또한 pip install datasets도 실행해야 해요.

출처: 문서

본문

권장: 내부에서 무슨 일이 일어나는지 이해하려면 MLflow Tracing을 설정하세요.

MLflow DSPy 통합

MLflow는 DSPy와 네이티브로 통합되는 LLMOps 도구로, 설명 가능성과 실험 추적을 제공해요. 이 튜토리얼에서는 MLflow를 사용해 프롬프트와 최적화 진행 상황을 트레이스로 시각화해 DSPy의 동작을 더 잘 이해할 수 있어요.

아래 네 단계를 따라 MLflow를 쉽게 설정할 수 있습니다.

  1. MLflow 설치
%pip install mlflow>=2.20
  1. 별도 터미널에서 MLflow UI 시작
mlflow ui --port 5000
  1. 노트북을 MLflow에 연결
import mlflow

mlflow.set_tracking_uri("http://localhost:5000")
mlflow.set_experiment("DSPy")
  1. 트레이싱 활성화.
mlflow.dspy.autolog()

위 단계를 완료하면 노트북에서 각 프로그램 실행에 대한 트레이스를 볼 수 있어요. 이는 모델의 동작에 대한 훌륭한 가시성을 제공하고 튜토리얼 전반에 걸쳐 DSPy의 개념을 더 잘 이해하는 데 도움을 줍니다.

MLflow Trace

통합에 대해 더 알아보려면 MLflow DSPy 문서도 방문하세요.

모듈에서 OpenAI의 gpt-4o-mini를 사용할 것이라고 DSPy에 알려볼게요. 인증을 위해 DSPy는 OPENAI_API_KEY를 확인할 거예요. 다른 제공자나 로컬 모델로 쉽게 바꿀 수 있어요.

import dspy

gpt4o_mini = dspy.LM('openai/gpt-4o-mini', max_tokens=2000)
gpt4o = dspy.LM('openai/gpt-4o', max_tokens=2000)
dspy.configure(lm=gpt4o_mini)  # we'll use gpt-4o-mini as the default LM, unless otherwise specified

다음으로 MATH 벤치마크에서 몇 가지 데이터 예제를 로드할게요. 최적화를 위해 훈련 분할을 사용하고, 보류된(held-out) dev 세트에서 평가할 거예요.

다음 단계에는 다음이 필요하다는 점에 유의하세요:

%pip install git+https://github.com/hendrycks/math.git
from dspy.datasets import MATH

dataset = MATH(subset='algebra')
print(len(dataset.train), len(dataset.dev))
350 350

훈련 세트의 한 예제를 살펴볼게요.

example = dataset.train[0]
print("Question:", example.question)
print("Answer:", example.answer)
Question: The doctor has told Cal O'Ree that during his ten weeks of working out at the gym, he can expect each week's weight loss to be $1\%$ of his weight at the end of the previous week. His weight at the beginning of the workouts is $244$ pounds. How many pounds does he expect to weigh at the end of the ten weeks? Express your answer to the nearest whole number.
Answer: 221

이제 모듈을 정의해 볼게요. 아주 간단해요: question을 받아 answer를 생성하는 하나의 chain-of-thought 단계일 뿐입니다.

module = dspy.ChainOfThought("question -> answer")
module(question=example.question)
Prediction(
    reasoning="Cal O'Ree's weight loss each week is $1\%$ of his weight at the end of the previous week. This means that at the end of each week, he retains $99\%$ of his weight from the previous week. \n\nIf we denote his weight at the beginning as \( W_0 = 244 \) pounds, then his weight at the end of week \( n \) can be expressed as:\n\[W_n = W_{n-1} \times 0.99\]\nThis can be simplified to:\n\[W_n = W_0 \times (0.99)^n\]\nAfter 10 weeks, his weight will be:\n\[W_{10} = 244 \times (0.99)^{10}\]\n\nNow, we calculate \( (0.99)^{10} \):\n\[(0.99)^{10} \approx 0.904382\]\n\nNow, we can calculate his expected weight after 10 weeks:\n\[W_{10} \approx 244 \times 0.904382 \approx 220.5\]\n\nRounding to the nearest whole number, Cal O'Ree can expect to weigh approximately \( 221 \) pounds at the end of the ten weeks.",
    answer='221'
)

다음으로, 프롬프트 최적화 전에 위 제로샷 모듈을 위한 평가자를 설정할게요.

THREADS = 24
kwargs = dict(num_threads=THREADS, display_progress=True, display_table=5)
evaluate = dspy.Evaluate(devset=dataset.dev, metric=dataset.metric, **kwargs)

evaluate(module)
Average Metric: 259.00 / 350 (74.0%): 100%|██████████| 350/350 [01:30<00:00,  3.85it/s]
2024/11/28 18:41:55 INFO dspy.evaluate.evaluate: Average Metric: 259 / 350 (74.0%)
74.0
MLflow 실험에서 평가 결과 추적하기

시간 경과에 따른 평가 결과를 추적하고 시각화하려면 결과를 MLflow 실험에 기록할 수 있어요.

import mlflow

# Start an MLflow Run to record the evaluation
with mlflow.start_run(run_name="math_evaluation"):
    kwargs = dict(num_threads=THREADS, display_progress=True)
    evaluate = dspy.Evaluate(devset=dataset.dev, metric=dataset.metric, **kwargs)

    # Evaluate the program as usual
    result = evaluate(module)

    # Log the aggregated score
    mlflow.log_metric("correctness", result.score)
    # Log the detailed evaluation results as a table
    mlflow.log_table(
        {
            "Question": [example.question for example in dataset.dev],
            "Gold Answer": [example.answer for example in dataset.dev],
            "Predicted Answer": [output[1] for output in result.results],
            "Correctness": [output[2] for output in result.results],
        },
        artifact_file="eval_results.json",
    )

통합에 대해 더 알아보려면 MLflow DSPy 문서도 방문하세요.

마지막으로 모듈을 최적화해 볼게요. 강력한 추론을 원하므로 대형 GPT-4o를 선생님(teacher) 모델로 사용해요(최적화 시점에 작은 LM의 추론을 부트스트랩하는 데 사용) — 하지만 프롬프트 모델(지침을 만드는 데 사용)이나 작업 모델(훈련되는)로는 사용하지 않아요.

GPT-4o는 아주 적은 횟수만 호출될 거예요. 최적화에 직접 관여하고 결과(최적화된) 프로그램에 포함되는 모델은 GPT-4o-mini입니다.

또한 max_bootstrapped_demos=4를 지정할 건데, 이는 프롬프트에 최대 4개의 부트스트랩 예제를 원한다는 뜻이고, max_labeled_demos=4는 부트스트랩된 것과 사전 라벨링된 예제를 합쳐 총 최대 4개를 원한다는 뜻입니다.

kwargs = dict(num_threads=THREADS, teacher_settings=dict(lm=gpt4o), prompt_model=gpt4o_mini)
optimizer = dspy.MIPROv2(metric=dataset.metric, auto="medium", **kwargs)

kwargs = dict(max_bootstrapped_demos=4, max_labeled_demos=4)
optimized_module = optimizer.compile(module, trainset=dataset.train, **kwargs)
evaluate(optimized_module)
Average Metric: 310.00 / 350 (88.6%): 100%|██████████| 350/350 [01:31<00:00,  3.84it/s]
2024/11/28 18:59:19 INFO dspy.evaluate.evaluate: Average Metric: 310 / 350 (88.6%)
88.57

멋지네요. 보류된 세트에서 품질을 74%에서 88% 이상으로 끌어올리는 게 꽤 간단했어요.

그렇긴 하지만, 이 같은 추론 작업에서는 더 고급 전략을 고려하고 싶을 때가 많아요. 예를 들어:

  • 계산기 함수나 dspy.LocalSandbox에 접근할 수 있는 dspy.ReAct 모듈
  • 다수결 투표(또는 그 위의 Aggregator 모듈)로 여러 최적화된 프롬프트를 앙상블하기

무엇이 바뀌었는지 이해하기 위해, 최적화 후의 프롬프트를 살펴볼게요. 또는 위 지침에 따라 MLflow 트레이싱을 활성화했다면, 풍부한 트레이스 UI에서 최적화 전후의 프롬프트를 비교할 수 있어요.

dspy.inspect_history()
[2024-11-28T18:59:19.176586]

System message:

Your input fields are:
1. `question` (str)

Your output fields are:
1. `reasoning` (str)
2. `answer` (str)

...

In adhering to this structure, your objective is: 
        Analyze the `question` provided, and systematically apply mathematical reasoning to derive the `answer`. Ensure to articulate each step of your thought process in the `reasoning` field, detailing how you identify relationships and formulate equations to arrive at the solution.

...

User message:

[[ ## question ## ]]
If $|4x+2|=10$ and $x<0$, what is the value of $x$?

...

최적화된 지침이 체계적으로 수학적 추론을 적용하고 각 단계를 reasoning 필드에 설명하도록 모델을 이끄는 것을 확인할 수 있어요. few-shot 예제들(reflection)도 삽입되어 모델의 행동을 안내합니다.

더 알아보기 (Learn more)