> ## Documentation Index
> Fetch the complete documentation index at: https://docs.coreweave.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Chain Of Density

> W&B Weave로 Chain of Density 요약 기법을 구현하여 텍스트를 반복적으로 압축하고 평가합니다.

<Note>
  이 문서는 대화형 노트북입니다. 로컬에서 실행하거나 아래 링크를 사용하세요.

  * [Google Colab에서 열기](https://colab.research.google.com/github/wandb/docs/blob/main/weave/cookbooks/source/chain_of_density.ipynb)
  * [GitHub에서 소스 보기](https://github.com/wandb/docs/blob/main/weave/cookbooks/source/chain_of_density.ipynb)
</Note>

복잡한 기술 문서를 요약하면서 핵심 세부 정보를 놓치지 않기란 쉽지 않습니다. Chain of Density(CoD) 요약 기법은 요약을 반복적으로 다듬어 더 간결하고 정보 밀도가 높은 요약을 만들어 냄으로써 이 문제를 해결합니다. 이 가이드에서는 CoD를 구현하고 Weave로 애플리케이션을 추적하고 평가하는 방법을 소개합니다.

<Frame>
  <img src="https://mintcdn.com/coreweave-dbfa0e8d/3Dv_sw2eg8feUJlx/products/wandb/weave/_media/summarization-eval_dash.png?fit=max&auto=format&n=3Dv_sw2eg8feUJlx&q=85&s=9ddd7edfc095bc7110e2c805b5ac4a01" alt="Chain of Density 요약 결과, 메트릭, 성능 비교를 보여 주는 Weave 평가 대시보드" width="2893" height="1770" data-path="products/wandb/weave/_media/summarization-eval_dash.png" />
</Frame>

<h2 id="what-is-chain-of-density-summarization">
  Chain of Density 요약이란
</h2>

[![arXiv](https://img.shields.io/badge/arXiv-2309.04269-b31b1b.svg)](https://arxiv.org/abs/2309.04269)

Chain of Density(CoD)는 요약을 반복적으로 개선하여 점점 더 간결하고 정보 밀도가 높은 요약을 만들어 내는 기법입니다. 작동 방식은 다음과 같습니다.

1. 초기 요약을 작성합니다.
2. 핵심 정보는 유지하면서 요약을 반복적으로 다듬어 더 간결하게 만듭니다.
3. 반복할 때마다 엔티티와 기술적 세부 정보의 밀도를 높입니다.

이 방식은 세부 정보를 빠짐없이 보존해야 하는 과학 논문이나 기술 문서를 요약할 때 특히 유용합니다.

<h2 id="why-use-weave">
  Weave를 사용하는 이유
</h2>

이 튜토리얼에서는 Weave를 사용하여 ArXiv 논문용 Chain of Density 요약 파이프라인을 구현하고 평가합니다. 이 튜토리얼에서 배우는 내용은 다음과 같습니다.

* **LLM 파이프라인 추적**: Weave를 사용하여 요약 프로세스의 입력, 출력, 중간 단계를 자동으로 로깅합니다.
* **LLM 출력 평가**: Weave의 기본 제공 도구로 요약을 일관되게 평가합니다.
* **조합 가능한 오퍼레이션 구축**: Weave 오퍼레이션을 조합하여 요약 파이프라인의 여러 부분에서 재사용합니다.
* **기존 코드와 통합**: 최소한의 오버헤드로 기존 Python 코드에 Weave를 추가합니다.

이 튜토리얼을 마치면 Weave의 모델 서빙, 평가, 결과 추적 기능을 활용하는 CoD 요약 파이프라인을 완성하게 됩니다.

<h2 id="set-up-the-environment">
  환경 설정
</h2>

먼저 환경을 설정하고 필요한 라이브러리를 임포트하세요. 이 단계에서는 파이프라인에 필요한 의존성을 설치합니다. 추적용 Weave, LLM용 Anthropic, ArXiv PDF 읽기용 PyPDF2가 여기에 포함됩니다.

```python lines theme={"system"}
!pip install -qU anthropic weave pydantic requests PyPDF2 set-env-colab-kaggle-dotenv
```

이 파이프라인은 Anthropic의 Claude 모델을 호출하므로, 다음 코드를 실행하기 전에 Anthropic API 키를 준비해야 합니다.

> Anthropic API 키를 발급받으려면 다음 단계를 따르세요.
>
> 1. [https://www.anthropic.com](https://www.anthropic.com) 에서 계정을 만드세요.
> 2. 계정 설정에서 API 섹션으로 이동하세요.
> 3. 새 API 키를 생성하세요.
> 4. API 키를 `.env` 파일에 안전하게 저장하세요.

```python lines theme={"system"}
import io
import os
from datetime import datetime, timezone

import anthropic
import requests
from pydantic import BaseModel
from PyPDF2 import PdfReader
from set_env import set_env

import weave

set_env("WANDB_API_KEY")
set_env("ANTHROPIC_API_KEY")

weave.init("summarization-chain-of-density-cookbook")
anthropic_client = anthropic.Anthropic(api_key=os.getenv("ANTHROPIC_API_KEY"))
```

이 코드는 Weave로 실험을 추적하고, Anthropic의 Claude 모델로 텍스트를 생성합니다. `weave.init([PROJECT_NAME])` 호출은 요약 작업에 사용할 새 Weave 프로젝트를 설정합니다.

<h2 id="define-the-arxivpaper-model">
  ArxivPaper 모델 정의하기
</h2>

환경이 준비되었으면 이제 파이프라인에서 다룰 데이터 구조를 정의합니다. 데이터를 표현할 `ArxivPaper` 클래스를 만드세요.

```python lines theme={"system"}
# ArxivPaper 모델 정의
class ArxivPaper(BaseModel):
    entry_id: str
    updated: datetime
    published: datetime
    title: str
    authors: list[str]
    summary: str
    pdf_url: str

# 샘플 ArxivPaper 생성
arxiv_paper = ArxivPaper(
    entry_id="http://arxiv.org/abs/2406.04744v1",
    updated=datetime(2024, 6, 7, 8, 43, 7, tzinfo=timezone.utc),
    published=datetime(2024, 6, 7, 8, 43, 7, tzinfo=timezone.utc),
    title="CRAG -- Comprehensive RAG Benchmark",
    authors=["Xiao Yang", "Kai Sun", "Hao Xin"],  # 간결하게 표시하기 위해 일부 생략
    summary="Retrieval-Augmented Generation (RAG) has recently emerged as a promising solution...",  # 일부 생략
    pdf_url="https://arxiv.org/pdf/2406.04744",
)
```

이 클래스는 요약 파이프라인의 입력이 되는 ArXiv 논문의 메타데이터와 내용을 캡슐화합니다.

<h2 id="load-pdf-content">
  PDF 콘텐츠 로드
</h2>

`ArxivPaper` 모델에는 메타데이터와 PDF URL이 담겨 있지만, 요약 파이프라인에는 논문의 전체 텍스트가 필요합니다. 논문 전체 내용을 활용하려면 PDF를 로드하고 텍스트를 추출하는 함수를 추가하세요.

```python lines theme={"system"}
@weave.op()
def load_pdf(pdf_url: str) -> str:
    # PDF 다운로드
    response = requests.get(pdf_url)
    pdf_file = io.BytesIO(response.content)

    # PDF 읽기
    pdf_reader = PdfReader(pdf_file)

    # 모든 페이지에서 텍스트 추출
    text = ""
    for page in pdf_reader.pages:
        text += page.extract_text()

    return text
```

<h2 id="implement-chain-of-density-summarization">
  Chain of Density 요약 구현하기
</h2>

이제 Weave 오퍼레이션을 사용하여 CoD 요약의 핵심 로직을 구현하세요.

<Frame>
  <img src="https://mintcdn.com/coreweave-dbfa0e8d/3Dv_sw2eg8feUJlx/products/wandb/weave/_media/summarization_trace.png?fit=max&auto=format&n=3Dv_sw2eg8feUJlx&q=85&s=70286439756a5dd0cc09269f865e1540" alt="Chain of Density 요약 파이프라인 실행을 보여 주는 Weave 트레이스 시각화" width="1266" height="1348" data-path="products/wandb/weave/_media/summarization_trace.png" />
</Frame>

```python lines theme={"system"}
# Chain of Density 요약
@weave.op()
def summarize_current_summary(
    document: str,
    instruction: str,
    current_summary: str = "",
    iteration: int = 1,
    model: str = "claude-3-sonnet-20240229",
):
    prompt = f"""
    Document: {document}
    Current summary: {current_summary}
    Instruction to focus on: {instruction}
    Iteration: {iteration}

    Generate an increasingly concise, entity-dense, and highly technical summary from the provided document that specifically addresses the given instruction.
    """
    response = anthropic_client.messages.create(
        model=model, max_tokens=4096, messages=[{"role": "user", "content": prompt}]
    )
    return response.content[0].text

@weave.op()
def iterative_density_summarization(
    document: str,
    instruction: str,
    current_summary: str,
    density_iterations: int,
    model: str = "claude-3-sonnet-20240229",
):
    iteration_summaries = []
    for iteration in range(1, density_iterations + 1):
        current_summary = summarize_current_summary(
            document, instruction, current_summary, iteration, model
        )
        iteration_summaries.append(current_summary)
    return current_summary, iteration_summaries

@weave.op()
def final_summary(
    instruction: str, current_summary: str, model: str = "claude-3-sonnet-20240229"
):
    prompt = f"""
    Given this summary: {current_summary}
    And this instruction to focus on: {instruction}
    Create an extremely dense, final summary that captures all key technical information in the most concise form possible, while specifically addressing the given instruction.
    """
    return (
        anthropic_client.messages.create(
            model=model, max_tokens=4096, messages=[{"role": "user", "content": prompt}]
        )
        .content[0]
        .text
    )

@weave.op()
def chain_of_density_summarization(
    document: str,
    instruction: str,
    current_summary: str = "",
    model: str = "claude-3-sonnet-20240229",
    density_iterations: int = 2,
):
    current_summary, iteration_summaries = iterative_density_summarization(
        document, instruction, current_summary, density_iterations, model
    )
    final_summary_text = final_summary(instruction, current_summary, model)
    return {
        "final_summary": final_summary_text,
        "accumulated_summary": current_summary,
        "iteration_summaries": iteration_summaries,
    }
```

각 함수의 역할은 다음과 같습니다.

* `summarize_current_summary`: 현재 상태를 바탕으로 요약 반복을 한 번 수행합니다.
* `iterative_density_summarization`: `summarize_current_summary`를 여러 번 호출하여 CoD 기법을 적용합니다.
* `chain_of_density_summarization`: 전체 요약 프로세스를 조율하고 결과를 반환합니다.

`@weave.op()` 데코레이터를 사용하면 Weave가 이 함수들의 입력, 출력, 실행을 추적합니다.

<h2 id="create-a-weave-model">
  Weave Model 만들기
</h2>

요약 함수가 준비되었으면, 다음 단계로 이 함수들을 Weave Model로 패키징하여 run, 매개변수, 버전을 함께 추적합니다. 이제 요약 파이프라인을 Weave Model로 래핑하세요.

<Frame>
  <img src="https://mintcdn.com/coreweave-dbfa0e8d/3Dv_sw2eg8feUJlx/products/wandb/weave/_media/model.png?fit=max&auto=format&n=3Dv_sw2eg8feUJlx&q=85&s=bc5684332ae6201770d4531c8d08651a" alt="모델 설정과 매개변수가 표시된 Chain of Density 요약용 Weave Model 설정 화면" width="2893" height="1772" data-path="products/wandb/weave/_media/model.png" />
</Frame>

```python lines theme={"system"}
# Weave 모델
class ArxivChainOfDensityPipeline(weave.Model):
    model: str = "claude-3-sonnet-20240229"
    density_iterations: int = 3

    @weave.op()
    def predict(self, paper: ArxivPaper, instruction: str) -> dict:
        text = load_pdf(paper.pdf_url)
        result = chain_of_density_summarization(
            text,
            instruction,
            model=self.model,
            density_iterations=self.density_iterations,
        )
        return result
```

이 `ArxivChainOfDensityPipeline` 클래스는 요약 로직을 Weave Model로 캡슐화하며, 다음과 같은 주요 이점을 제공합니다.

* 자동 실험 추적: Weave는 모델을 실행할 때마다 각 run의 입력, 출력, 매개변수를 캡처합니다.
* 버전 관리: 모델의 속성이나 코드가 변경되면 자동으로 버전이 관리되므로, 요약 파이프라인이 시간에 따라 어떻게 발전해 왔는지 명확한 이력을 확인할 수 있습니다.
* 재현성: 버전 관리와 추적 기능 덕분에 요약 파이프라인의 이전 결과나 설정을 언제든지 재현할 수 있습니다.
* 하이퍼파라미터 관리: 모델 속성(예: `model`, `density_iterations`)이 명확하게 정의되고 여러 run에 걸쳐 추적되므로 실험을 진행하기가 수월합니다.
* Weave 에코시스템과의 인테그레이션: `weave.Model`을 사용하면 평가, 서빙 기능 등 다른 Weave 도구와 연동할 수 있습니다.

<h2 id="implement-evaluation-metrics">
  평가 메트릭 구현
</h2>

이제 파이프라인에서 요약이 생성되므로, 요약의 품질을 체계적으로 측정할 방법이 필요합니다. 요약의 품질을 평가하기 위해 다음과 같이 단순한 평가 메트릭을 구현하세요.

```python lines theme={"system"}
import json

@weave.op()
def evaluate_summary(
    summary: str, instruction: str, model: str = "claude-3-sonnet-20240229"
) -> dict:
    prompt = f"""
    Summary: {summary}
    Instruction: {instruction}

    Evaluate the summary based on the following criteria:
    1. Relevance (1-5): How well does the summary address the given instruction?
    2. Conciseness (1-5): How concise is the summary while retaining key information?
    3. Technical Accuracy (1-5): How accurately does the summary convey technical details?

    Your response MUST be in the following JSON format:
    {{
        "relevance": {{
            "score": <int>,
            "explanation": "<string>"
        }},
        "conciseness": {{
            "score": <int>,
            "explanation": "<string>"
        }},
        "technical_accuracy": {{
            "score": <int>,
            "explanation": "<string>"
        }}
    }}

    Ensure that the scores are integers between 1 and 5, and that the explanations are concise.
    """
    response = anthropic_client.messages.create(
        model=model, max_tokens=1000, messages=[{"role": "user", "content": prompt}]
    )
    print(response.content[0].text)

    eval_dict = json.loads(response.content[0].text)

    return {
        "relevance": eval_dict["relevance"]["score"],
        "conciseness": eval_dict["conciseness"]["score"],
        "technical_accuracy": eval_dict["technical_accuracy"]["score"],
        "average_score": sum(eval_dict[k]["score"] for k in eval_dict) / 3,
        "evaluation_text": response.content[0].text,
    }
```

이 평가 함수는 Claude 모델을 사용해 생성된 요약의 품질을 관련성, 간결성, 기술적 정확도 기준으로 평가합니다.

<h2 id="create-a-weave-dataset-and-run-evaluation">
  Weave Dataset 생성 및 평가 실행
</h2>

점수화 함수를 정의했으니 이제 마지막 단계로 샘플 입력에 이 함수를 적용하고 평가를 실행합니다. 파이프라인을 평가하려면 Weave Dataset을 생성하고 평가를 실행하세요.

<Frame>
  <img src="https://mintcdn.com/coreweave-dbfa0e8d/3Dv_sw2eg8feUJlx/products/wandb/weave/_media/dataset.png?fit=max&auto=format&n=3Dv_sw2eg8feUJlx&q=85&s=0879365a9ca4cb92063f1dd9d9e68c54" alt="데이터셋 선택 및 설정 옵션이 포함된 평가용 Weave Dataset 설정 화면" width="2893" height="1772" data-path="products/wandb/weave/_media/dataset.png" />
</Frame>

```python lines theme={"system"}
# Weave Dataset 생성
dataset = weave.Dataset(
    name="arxiv_papers",
    rows=[
        {
            "paper": arxiv_paper,
            "instruction": "What was the approach to experimenting with different data mixtures?",
        },
    ],
)

weave.publish(dataset)
```

평가에는 LLM-as-a-judge 방식을 사용합니다. 이 기법은 언어 모델을 사용해 다른 모델이나 시스템이 생성한 출력의 품질을 평가하는 방식입니다. LLM의 이해 및 추론 능력을 활용해 세밀한 평가를 제공하므로, 기존 메트릭만으로는 충분하지 않은 작업에 특히 유용합니다.

[![arXiv](https://img.shields.io/badge/arXiv-2306.05685-b31b1b.svg)](https://arxiv.org/abs/2306.05685)

<Frame>
  <img src="https://mintcdn.com/coreweave-dbfa0e8d/3Dv_sw2eg8feUJlx/products/wandb/weave/_media/summarization-eval_dash.png?fit=max&auto=format&n=3Dv_sw2eg8feUJlx&q=85&s=9ddd7edfc095bc7110e2c805b5ac4a01" alt="Chain of Density 요약 결과, 메트릭, 성능 비교가 표시된 Weave 평가 대시보드" width="2893" height="1770" data-path="products/wandb/weave/_media/summarization-eval_dash.png" />
</Frame>

```python lines theme={"system"}
# Scorer 함수 정의
@weave.op()
def quality_scorer(instruction: str, output: dict) -> dict:
    result = evaluate_summary(output["final_summary"], instruction)
    return result
```

```python lines theme={"system"}
# 평가 실행
evaluation = weave.Evaluation(dataset=dataset, scorers=[quality_scorer])
arxiv_chain_of_density_pipeline = ArxivChainOfDensityPipeline()
results = await evaluation.evaluate(arxiv_chain_of_density_pipeline)
```

이 코드는 샘플 ArXiv 논문으로 데이터셋을 생성하고, 품질 Scorer를 정의한 다음, 요약 파이프라인의 평가를 실행합니다.

<h2 id="conclusion">
  결론
</h2>

이 예제에서는 Weave를 사용하여 ArXiv 논문용 Chain of Density 요약 파이프라인을 구현하는 방법을 살펴보았습니다. 이 예제에서 배운 내용은 다음과 같습니다.

* 요약 과정의 각 단계별로 Weave 오퍼레이션 생성하기
* 추적 및 평가를 위해 파이프라인을 Weave Model로 래핑하기
* Weave 오퍼레이션을 사용하여 맞춤형 평가 메트릭 구현하기
* 데이터셋을 생성하고 파이프라인 평가 실행하기

Weave는 요약 과정 전반의 입력, 출력, 중간 단계를 추적하므로 LLM 애플리케이션을 더 쉽게 디버깅하고 최적화하고 평가할 수 있습니다.

이 예제를 확장하여 더 큰 데이터셋을 처리하거나, 더 정교한 평가 메트릭을 구현하거나, 다른 LLM 워크플로와 통합할 수도 있습니다.

<a href="https://forge.coreweave.com/wandb/wandb_fc/arxiv-reader/reports/Building-a-bot-to-summarize-arXiv-papers-as-PDFs-using-Anthrophic-and-W-B-Weave--Vmlldzo4Nzg0ODI4" target="_blank" rel="noopener noreferrer" className="button button--primary button--lg">
  W\&B에서 전체 리포트 보기
</a>
