AI-Master-Book
  • about AI-Master-Book
  • AI Master Book
    • 이상치 탐지 with Python
    • 베이지안 뉴럴네트워크 (BNN) with Python
    • 그래프 뉴럴네트워크 (GNN) with Python
    • 데이터 마케팅 분석 with Python
  • LLM MASTER BOOK
    • OpenAI API 쿡북 with Python
    • 기초부터 심화까지 RAG 쿡북 with Python
    • MCP 에이전트 쿡북 with Python
  • LLMs
    • OpenAI API
      • 1️⃣ChatCompletion
      • 2️⃣DALL-E
      • 3️⃣Text to Speech
      • 4️⃣Video to Transcripts
      • 5️⃣Assistants API
      • 6️⃣Prompt Engineering
      • 7️⃣OpenAI New GPT-4o
    • LangChain
      • LangChain Basic
        • 1️⃣Basic Modules
        • 2️⃣Model I/O
        • 3️⃣Prompts
        • 4️⃣Chains
        • 5️⃣Agents
        • 6️⃣Tools
        • 7️⃣Memory
      • LangChain Intermediate
        • 1️⃣OpenAI LLM
        • 2️⃣Prompt Template
        • 3️⃣Retrieval
        • 4️⃣RAG ChatBot
        • 5️⃣RAG with Gemini
        • 6️⃣New Huggingface-LangChain
        • 7️⃣Huggingface Hub
        • 8️⃣SQL Agent & Chain
        • 9️⃣Expression Language(LCEL)
        • 🔟Llama3-8B with LangChain
      • LangChain Advanced
        • 1️⃣LLM Evaluation
        • 2️⃣RAG Evaluation with RAGAS
        • 3️⃣LangChain with RAGAS
        • 4️⃣RAG Paradigms
        • 5️⃣LangChain: Advance Techniques
        • 6️⃣LangChain with NeMo-Guardrails
        • 7️⃣LangChain vs. LlamaIndex
        • 8️⃣LangChain LCEL vs. LangGraph
    • LlamaIndex
      • LlamaIndex Basic
        • 1️⃣Introduction
        • 2️⃣Customization
        • 3️⃣Data Connectors
        • 4️⃣Documents & Nodes
        • 5️⃣Naive RAG
        • 6️⃣Advanced RAG
        • 7️⃣Llama3-8B with LlamaIndex
        • 8️⃣LlmaPack
      • LlamaIndex Intermediate
        • 1️⃣QueryEngine
        • 2️⃣Agent
        • 3️⃣Evaluation
        • 4️⃣Evaluation-Driven Development
        • 5️⃣Fine-tuning
        • 6️⃣Prompt Compression with LLMLingua
      • LlamaIndex Advanced
        • 1️⃣Agentic RAG: Router Engine
        • 2️⃣Agentic RAG: Tool Calling
        • 3️⃣Building Agent Reasoning Loop
        • 4️⃣Building Multi-document Agent
    • Hugging Face
      • Huggingface Basic
        • 1️⃣Datasets
        • 2️⃣Tokenizer
        • 3️⃣Sentence Embeddings
        • 4️⃣Transformers
        • 5️⃣Sentence Transformers
        • 6️⃣Evaluate
        • 7️⃣Diffusers
      • Huggingface Tasks
        • NLP
          • 1️⃣Sentiment Analysis
          • 2️⃣Zero-shot Classification
          • 3️⃣Aspect-Based Sentiment Analysis
          • 4️⃣Feature Extraction
          • 5️⃣Intent Classification
          • 6️⃣Topic Modeling: BERTopic
          • 7️⃣NER: Token Classification
          • 8️⃣Summarization
          • 9️⃣Translation
          • 🔟Text Generation
        • Audio & Tabular
          • 1️⃣Text-to-Speech: TTS
          • 2️⃣Speech Recognition: Whisper
          • 3️⃣Audio Classification
          • 4️⃣Tabular Qustaion & Answering
        • Vision & Multimodal
          • 1️⃣Image-to-Text
          • 2️⃣Text to Image
          • 3️⃣Image to Image
          • 4️⃣Text or Image-to-Video
          • 5️⃣Depth Estimation
          • 6️⃣Image Classification
          • 7️⃣Object Detection
          • 8️⃣Segmentatio
      • Huggingface Optimization
        • 1️⃣Accelerator
        • 2️⃣Bitsandbytes
        • 3️⃣Flash Attention
        • 4️⃣Quantization
        • 5️⃣Safetensors
        • 6️⃣Optimum-ONNX
        • 7️⃣Optimum-NVIDIA
        • 8️⃣Optimum-Intel
      • Huggingface Fine-tuning
        • 1️⃣Transformer Fine-tuning
        • 2️⃣PEFT Fine-tuning
        • 3️⃣PEFT: Fine-tuning with QLoRA
        • 4️⃣PEFT: Fine-tuning Phi-2 with QLoRA
        • 5️⃣Axoltl Fine-tuning with QLoRA
        • 6️⃣TRL: RLHF Alignment Fine-tuning
        • 7️⃣TRL: DPO Fine-tuning with Phi-3-4k-instruct
        • 8️⃣TRL: ORPO Fine-tuning with Llama3-8B
        • 9️⃣Convert GGUF gemma-2b with llama.cpp
        • 🔟Apple Silicon Fine-tuning Gemma-2B with MLX
        • 🔢LLM Mergekit
    • Agentic LLM
      • Agentic LLM
        • 1️⃣Basic Agentic LLM
        • 2️⃣Multi-agent with CrewAI
        • 3️⃣LangGraph: Multi-agent Basic
        • 4️⃣LangGraph: Agentic RAG with LangChain
        • 5️⃣LangGraph: Agentic RAG with Llama3-8B by Groq
      • Autonomous Agent
        • 1️⃣LLM Autonomous Agent?
        • 2️⃣AutoGPT: Worldcup Winner Search with LangChain
        • 3️⃣BabyAGI: Weather Report with LangChain
        • 4️⃣AutoGen: Writing Blog Post with LangChain
        • 5️⃣LangChain: Autonomous-agent Debates with Tools
        • 6️⃣CAMEL Role-playing Autonomous Cooperative Agents
        • 7️⃣LangChain: Two-player Harry Potter D&D based CAMEL
        • 8️⃣LangChain: Multi-agent Bid for K-Pop Debate
        • 9️⃣LangChain: Multi-agent Authoritarian Speaker Selection
        • 🔟LangChain: Multi-Agent Simulated Environment with PettingZoo
    • Multimodal
      • 1️⃣PaliGemma: Open Vision LLM
      • 2️⃣FLUX.1: Generative Image
    • Building LLM
      • 1️⃣DSPy
      • 2️⃣DSPy RAG
      • 3️⃣DSPy with LangChain
      • 4️⃣Mamba
      • 5️⃣Mamba RAG with LangChain
      • 7️⃣PostgreSQL VectorDB with pgvorco.rs
Powered by GitBook
On this page
  • Configuring LM and RM
  • Loading the Dataset
  • Building Signatures
  • Building the Pipeline
  • Optimizing the Pipeline
  • Executing the Pipeline
  • Evaluating the Pipeline
  • Evaluating the Retrieval
  1. LLMs
  2. Building LLM

DSPy RAG

Retrieval Augmented Generation(RAG)은 LLM이 소스의 대규모 지식 코퍼스를 활용하고 지식 저장소를 쿼리하여 관련 구절/콘텐츠를 찾고 잘 정제된 답변을 생성할 수 있도록 하는 접근 방식입니다.

RAG는 LLM이 원래 해당 주제에 대한 교육을 받지 않았더라도 실시간 지식을 동적으로 활용하여 사려 깊은 답변을 제공할 수 있도록 합니다. 그러나 이러한 미묘한 차이로 인해 정교한 RAG 파이프라인을 설정하는 데는 더 큰 복잡성이 따릅니다. 이러한 복잡성을 줄이기 위해 저희는 프롬프트 파이프라인 설정에 대한 원활한 접근 방식을 제공하는 DSPy를 사용합니다!

Configuring LM and RM

먼저 DSPy가 여러 LM 및 RM API와 로컬 모델 호스팅을 통해 지원하는 언어 모델(LM)과 검색 모델(RM)을 설정하는 것부터 시작하겠습니다.

이 노트북에서는 GPT-3.5(gpt-3.5-turbo) 및 ColBERTv2 리트리버(이 2017 덤프에서 각 문서의 첫 문단이 포함된 Wikipedia 2017 "초록" 검색 색인을 호스팅하는 무료 서버)로 작업할 것입니다. 생성 또는 검색에 필요할 때 DSPy가 내부적으로 해당 모듈을 호출할 수 있도록 DSPy 내에서 LM과 RM을 구성합니다.

import dspy

turbo = dspy.OpenAI(model='gpt-3.5-turbo')
colbertv2_wiki17_abstracts = dspy.ColBERTv2(url='http://20.102.90.50:2017/wiki17_abstracts')

dspy.settings.configure(lm=turbo, rm=colbertv2_wiki17_abstracts)

Loading the Dataset

이 튜토리얼에서는 일반적으로 멀티홉 방식으로 답변하는 복잡한 질문-답변 쌍의 모음인 HotPotQA 데이터 세트를 사용합니다. 이 데이터 세트는 HotPotQA 클래스를 통해 DSPy에서 제공하는 데이터 세트를 로드할 수 있습니다:

from dspy.datasets import HotPotQA

# Load the dataset.
dataset = HotPotQA(train_seed=1, train_size=20, eval_seed=2023, dev_size=50, test_size=0)

# Tell DSPy that the 'question' field is the input. Any other fields are labels and/or metadata.
trainset = [x.with_inputs('question') for x in dataset.train]
devset = [x.with_inputs('question') for x in dataset.dev]

len(trainset), len(devset)

Output:

(20, 50)

Building Signatures

이제 데이터가 로드되었으므로 파이프라인의 하위 작업에 대한 signature을 정의해 보겠습니다.

간단한 입력 질문과 출력 답변을 식별할 수 있지만, RAG 파이프라인을 구축 중이므로 콜버트 말뭉치의 컨텍스트 정보를 활용하고자 합니다. 따라서 context, question --> answer이라는 서명을 정의해 보겠습니다.

class GenerateAnswer(dspy.Signature):
    """Answer questions with short factoid answers."""

    context = dspy.InputField(desc="may contain relevant facts")
    question = dspy.InputField()
    answer = dspy.OutputField(desc="often between 1 and 5 words")

context 및 answer 필드에 대한 간단한 설명을 추가하여 모델이 수신하고 생성해야 하는 내용에 대한 보다 강력한 지침을 정의합니다.

Building the Pipeline

RAG 파이프라인을 DSPy 모듈로 구축할 것이며, 여기에는 두 가지 방법이 필요합니다:

  • __init__ 메서드는 필요한 하위 모듈을 선언하기만 하면 됩니다: dspy.Retrieve와 dspy.ChainOfThought입니다. 후자는 GenerateAnswer 서명을 구현하도록 정의되어 있습니다.

  • forward 메서드는 우리가 가진 모듈을 사용해 질문에 답하는 제어 흐름을 설명합니다: 질문이 주어지면 관련성이 높은 상위 3개 구절을 검색한 다음 이를 답변 생성을 위한 컨텍스트로 제공합니다.

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)

Optimizing the Pipeline

Compiling the RAG program

이 프로그램을 정의했으니 이제 컴파일해 봅시다. 프로그램 컴파일을 하면 각 모듈에 저장된 매개변수가 업데이트됩니다. 저희 설정에서는 주로 프롬프트에 포함할 좋은 데모를 수집하고 선택하는 형태입니다.

컴파일은 세 가지 사항에 따라 달라집니다:

  1. 트레이닝 세트. 위의 trainset에 있는 20개의 질문과 답변 예제를 사용하겠습니다.

  2. 검증을 위한 메트릭 예측된 답이 맞는지, 검색된 컨텍스트에 실제로 답이 포함되어 있는지 확인하는 간단한 validate_context_and_answer를 정의하겠습니다.

  3. 특정 텔레프롬프터 DSPy 컴파일러에는 프로그램을 최적화할 수 있는 여러 텔레프롬프터가 포함되어 있습니다.

from dspy.teleprompt import BootstrapFewShot

# Validation logic: check that the predicted answer is correct.
# Also check that the retrieved context does actually contain that answer.
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

# Set up a basic teleprompter, which will compile our RAG program.
teleprompter = BootstrapFewShot(metric=validate_context_and_answer)

# Compile!
compiled_rag = teleprompter.compile(RAG(), trainset=trainset)

:::Teleprompters: 텔레프롬프터는 모든 프로그램을 부트스트랩하고 해당 모듈에 효과적인 프롬프트를 선택하는 방법을 배울 수 있는 강력한 최적화 프로그램입니다. 따라서 "원거리에서 프롬프트"라는 뜻의 이름입니다.

텔레프롬프터마다 비용 대비 품질 등을 최적화하는 정도에 따라 다양한 절충안을 제공합니다. 위 예제에서는 간단한 기본값인 BootstrapFewShot을 사용하겠습니다.

비유를 하자면, 이를 표준 DNN 지도 학습 설정에서 학습 데이터, 손실 함수, 최적화 도구라고 생각할 수 있습니다. SGD가 기본적인 최적화 도구인 반면, Adam이나 RMSProp._ :: 같은 더 정교한(그리고 더 비싼!) 최적화 도구가 있습니다:::

Executing the Pipeline

이제 RAG 프로그램을 컴파일했으니 직접 사용해 보겠습니다.

# Ask any question you like to this simple RAG program.
my_question = "What castle did David Gregory inherit?"

# Get the prediction. This contains `pred.context` and `pred.answer`.
pred = compiled_rag(my_question)

# Print the contexts and the answer.
print(f"Question: {my_question}")
print(f"Predicted Answer: {pred.answer}")
print(f"Retrieved Contexts (truncated): {[c[:200] + '...' for c in pred.context]}")

훌륭합니다. LM의 마지막 프롬프트를 살펴보는 건 어떨까요?

turbo.inspect_history(n=1)

Output:

Answer questions with short factoid answers.

---

Question: At My Window was released by which American singer-songwriter?
Answer: John Townes Van Zandt

Question: "Everything Has Changed" is a song from an album released under which record label ?
Answer: Big Machine Records
...(truncated)

자세한 데모를 작성하지는 않았지만, DSPy가 이 3,000개의 토큰 프롬프트를 부트스트랩하여 3샷 검색을 위한 증강 생성(어려운 부정 구절이 포함된 생성)을 할 수 있었고 매우 간단하게 작성된 프로그램 내에서 연쇄 추론을 사용한다는 것을 알 수 있습니다.

이는 구성과 학습의 힘을 보여줍니다. 물론 이것은 특정 텔레프롬프터에 의해 생성된 것으로, 각 설정에 따라 완벽할 수도 있고 그렇지 않을 수도 있습니다. DSPy에서 볼 수 있듯이 프로그램의 품질과 비용과 관련하여 최적화하고 검증해야 하는 옵션의 공간은 넓지만 체계적으로 구성되어 있습니다.

학습된 객체 자체를 쉽게 검사할 수도 있습니다.

for name, parameter in compiled_rag.named_predictors():
    print(name)
    print(parameter.demos[0])
    print()

Evaluating the Pipeline

이제 개발 세트에서 compiled_rag 프로그램을 평가할 수 있습니다. 물론 이 작은 세트는 신뢰할 수 있는 벤치마크가 될 수는 없지만, 설명을 위해 사용하는 것은 도움이 될 것입니다.

예측된 답변의 정확도(정확히 일치하는지)를 평가해 보겠습니다.

from dspy.evaluate.evaluate import Evaluate

# Set up the `evaluate_on_hotpotqa` function. We'll use this many times below.
evaluate_on_hotpotqa = Evaluate(devset=devset, num_threads=1, display_progress=False, display_table=5)

# Evaluate the `compiled_rag` program with the `answer_exact_match` metric.
metric = dspy.evaluate.answer_exact_match
evaluate_on_hotpotqa(compiled_rag, metric=metric)

Output:

Average Metric: 22 / 50  (44.0): 100%|██████████| 50/50 [00:00<00:00, 116.45it/s]
Average Metric: 22 / 50  (44.0%)

44.0

Evaluating the Retrieval

검색의 정확도를 살펴보는 것도 도움이 될 수 있습니다. 이를 수행하는 방법에는 여러 가지가 있지만 검색된 구절에 답이 포함되어 있는지 간단히 확인할 수 있습니다.

검색해야 하는 골드 타이틀이 포함된 개발자 세트를 활용할 수 있습니다.

def gold_passages_retrieved(example, pred, trace=None):
    gold_titles = set(map(dspy.evaluate.normalize_text, example['gold_titles']))
    found_titles = set(map(dspy.evaluate.normalize_text, [c.split(' | ')[0] for c in pred.context]))

    return gold_titles.issubset(found_titles)

compiled_rag_retrieval_score = evaluate_on_hotpotqa(compiled_rag, metric=gold_passages_retrieved)

Output:

Average Metric: 13 / 50  (26.0): 100%|██████████| 50/50 [00:00<00:00, 671.76it/s]Average Metric: 13 / 50  (26.0%)

이 간단한 compiled_rag 프로그램은 질문의 상당 부분(이 작은 세트에서는 40% 이상)에 정답을 맞출 수 있지만, 검색 품질은 훨씬 낮습니다.

이는 LM이 훈련 중에 암기한 지식에 의존하여 질문에 답하는 경우가 많다는 것을 암시할 수 있습니다. 이러한 낮은 검색 품질을 해결하기 위해 보다 고급 검색 동작을 포함하는 두 번째 프로그램을 살펴 보겠습니다.

PreviousDSPyNextDSPy with LangChain

Last updated 1 year ago

2️⃣