테스트셋 생성을 위한 Pre-chunked 데이터 사용

테스트셋 생성을 위한 Pre-chunked 데이터 사용

이미 잘 정의된 청킹(chunking) 전략을 갖고 있다면, Ragas의 내부 문서 분할 메커니즘을 건너뛰고 자신의 청크를 그대로 사용할 수 있어요. 이 기능은 특히 다음 상황에서 유용해요.

  • 특정 도메인에 맞춰 청킹 전략을 최적화했을 때
  • RAG 파이프라인과 평가 간의 일관성을 유지하고 싶을 때
  • 커스텀 메타데이터로 전처리된 문서가 있을 때
  • 청크가 특정 비즈니스 로직이나 문서 구조와 정렬되도록 해야 할 때

출처: 문서

본문

개요

TestsetGeneratorgenerate_with_chunks 메서드는 pre-chunked 데이터를 받아서 각 청크를 NodeType.CHUNK 로 직접 취급하고 내부 분할 변환을 건너뛰어요. 즉, 여러분이 제공한 그대로 청크가 유지되며 콘텐츠와 메타데이터 무결성이 모두 보존돼요.

동작 방식

generate_with_chunks 를 사용하면 Ragas는:

  • 청크를 그대로 받아요(Document 객체 또는 문자열)
  • SummaryExtractor, ThemesExtractor, NERExtractor, EmbeddingExtractor 같은 추출기를 적용해 각 청크에 추가 속성을 풍부하게 만들어요
  • CosineSimilarityBuilderOverlapScoreBuilder 를 사용해 청크 사이 관계를 만들어요
  • 콘텐츠 테마를 기준으로 persona를 생성해요
  • 다양한 쿼리 유형(단일 홉, 멀티 홉)에 대한 시나리오를 만들어요
  • 질문, 컨텍스트, 참조 답변을 포함한 테스트 샘플을 합성해요

예시: Pre-chunked 문서 사용

LangChain Document 객체 목록을 전달할 수 있어요. 이 방식은 청크의 메타데이터를 보존해서 원본 문서나 기타 커스텀 정보를 추적하는 데 유용해요.

import os
from langchain_core.documents import Document
from ragas.testset.synthesizers.generate import TestsetGenerator
from ragas.llms import llm_factory
from ragas.embeddings import OpenAIEmbeddings
from openai import OpenAI

# Initialize OpenAI client
client = OpenAI(api_key=os.environ.get("OPENAI_API_KEY"))

# Initialize generator with your preferred models
generator = TestsetGenerator(
    llm=llm_factory("gpt-4o-mini", client=client),
    embedding_model=OpenAIEmbeddings(client=client)
)

# Your pre-chunked documents
chunks = [
    Document(
        page_content="""The Eiffel Tower (Tour Eiffel) is a wrought-iron lattice tower on the Champ de Mars in Paris, France. It is named after the engineer Gustave Eiffel, whose company designed and built the tower. Locally nicknamed "La Dame de Fer" (French for "The Iron Lady"), it was constructed from 1887 to 1889 as the centerpiece of the 1889 World's Fair. Although initially criticized by some of France's leading artists and intellectuals for its design, it has since become a global cultural icon of France and one of the most recognizable structures in the world.""", 
        metadata={"source": "doc1", "chunk_id": 1}
    ),
    Document(
        page_content="""The tower is 330 metres (1,083 ft) tall, about the same height as an 81-storey building, and the tallest structure in Paris. Its base is square, measuring 125 metres (410 ft) on each side. During its construction, the Eiffel Tower surpassed the Washington Monument to become the tallest man-made structure in the world, a title it held for 41 years until the Chrysler Building in New York City was finished in 1930. It was the first structure to reach a height of 300 metres. Due to the addition of a broadcasting aerial at the top of the tower in 1957, it is now taller than the Chrysler Building by 5.2 metres (17 ft).""", 
        metadata={"source": "doc1", "chunk_id": 2}
    )
]

# Generate testset
testset = generator.generate_with_chunks(
    chunks=chunks,
    testset_size=10
)

# Save to CSV
output_file = "testset.csv"
testset.to_csv(output_file)
print(f"Testset saved to {output_file}")
print(testset.to_pandas().head())

생성 과정

생성 중에는 다양한 변환 및 합성 단계를 보여주는 진행 로그를 볼 수 있어요.

Applying SummaryExtractor: 100%|████████████████████████████████| 2/2 [00:07<00:00,  3.67s/it]
Applying CustomNodeFilter: 100%|█████████████████████████████| 2/2 [00:00<00:00, 2226.87it/s]
Applying EmbeddingExtractor: 100%|███████████████████████████| 2/2 [00:02<00:00,  1.19s/it]
Applying ThemesExtractor: 100%|██████████████████████████████| 2/2 [00:06<00:00,  3.07s/it]
Applying NERExtractor: 100%|█████████████████████████████████| 2/2 [00:06<00:00,  3.10s/it]
Applying CosineSimilarityBuilder: 100%|█████████████████████| 1/1 [00:00<00:00, 613.29it/s]
Applying OverlapScoreBuilder: 100%|████████████████████████| 1/1 [00:00<00:00, 1491.57it/s]
Generating personas: 100%|███████████████████████████████████| 2/2 [00:05<00:00,  2.77s/it]
Generating Scenarios: 100%|██████████████████████████████████| 2/2 [00:08<00:00,  4.19s/it]
Generating Samples: 100%|████████████████████████████████| 11/11 [00:45<00:00,  4.13s/it]
Testset saved to testset.csv

테스트셋에는 다양한 유형의 쿼리가 포함돼요.

  • 단일 홉 쿼리 : 하나의 청크로 답할 수 있는 질문
  • 멀티 홉 쿼리 : 여러 청크의 정보가 필요한 질문(관계가 존재할 때)

예시: 문자열 직접 사용

메타데이터를 보존할 필요가 없다면 문자열을 직접 전달할 수도 있어요.

from ragas.testset.synthesizers.generate import TestsetGenerator
from ragas.llms import llm_factory
from ragas.embeddings import OpenAIEmbeddings
from openai import OpenAI

# Initialize models
client = OpenAI()
generator = TestsetGenerator(
    llm=llm_factory("gpt-4o-mini", client=client),
    embedding_model=OpenAIEmbeddings(client=client)
)

# Simple text chunks
text_chunks = [
    "Artificial Intelligence (AI) is the simulation of human intelligence by machines. It involves machine learning, natural language processing, and computer vision.",
    "Machine Learning is a subset of AI that enables systems to learn from data without explicit programming. Popular algorithms include neural networks and decision trees.",
    "Deep Learning uses neural networks with multiple layers to process complex patterns in large datasets. It powers modern applications like image recognition and language translation."
]

# Generate testset
testset = generator.generate_with_chunks(
    chunks=text_chunks,
    testset_size=5
)

# Save to CSV
output_file = "testset.csv"
testset.to_csv(output_file)
print(f"Testset saved to {output_file}")
print(testset.to_pandas())

엣지 케이스 처리

  • 빈 콘텐츠 : page_content 가 비어 있거나 공백만 있는 청크는 자동으로 걸러져요.
  • 빈 시퀀스 : 빈 청크 시퀀스를 제공하면 빈 테스트셋이 생성돼요.

더 알아보기 (Learn more)