메인 콘텐츠로 건너뛰기
Colab에서 열기 Weave는 LangChain Python 라이브러리를 통해 수행되는 모든 호출을 손쉽게 추적하고 로깅할 수 있도록 설계되었습니다. LLM으로 작업할 때 디버깅은 피할 수 없습니다. 모델 호출이 실패하거나, 출력 형식이 잘못되었거나, 중첩된 모델 호출로 인해 혼란이 생기는 등 문제의 원인을 정확히 찾아내기 어려울 수 있습니다. LangChain 애플리케이션은 보통 여러 단계와 다수의 LLM 호출로 구성되므로, 체인과 에이전트의 내부 동작을 이해하는 것이 중요합니다. Weave는 LangChain 애플리케이션에 대한 트레이스(trace)를 자동으로 수집하여 이 과정을 단순화합니다. 이를 통해 애플리케이션의 성능을 모니터링하고 분석할 수 있으며, LLM 워크플로를 더 쉽게 디버깅하고 최적화할 수 있습니다.

시작하기

시작하려면 스크립트의 시작 부분에서 weave.init()을 호출하면 됩니다. weave.init()의 인수로는 추적을 체계적으로 관리하는 데 도움이 되는 프로젝트 이름을 전달합니다.
import weave
from langchain_core.prompts import PromptTemplate
from langchain_openai import ChatOpenAI

# 프로젝트 이름으로 Weave 초기화
weave.init("langchain_demo")

llm = ChatOpenAI()
prompt = PromptTemplate.from_template("1 + {number} = ")

llm_chain = prompt | llm

output = llm_chain.invoke({"number": 2})

print(output)

호출 메타데이터 추적

LangChain 호출에서 생성되는 메타데이터를 추적하려면 weave.attributes 컨텍스트 매니저를 사용할 수 있습니다. 이 컨텍스트 매니저를 사용하면 체인 또는 단일 요청과 같은 특정 코드 블록에 대해 사용자 지정 메타데이터를 설정할 수 있습니다.
import weave
from langchain_core.prompts import PromptTemplate
from langchain_openai import ChatOpenAI

# 프로젝트 이름으로 Weave 초기화
weave.init("langchain_demo")

llm = ChatOpenAI()
prompt = PromptTemplate.from_template("1 + {number} = ")

llm_chain = prompt | llm

with weave.attributes({"my_awesome_attribute": "value"}):
    output = llm_chain.invoke()

print(output)
Weave는 LangChain 호출의 트레이스와 함께 메타데이터를 자동으로 추적합니다. 아래와 같이 Weave 웹 인터페이스에서 메타데이터를 확인할 수 있습니다. langchain_attributes.png

트레이스

LLM 애플리케이션의 트레이스를 중앙화된 데이터베이스에 저장하는 것은 개발 단계와 운영 단계 모두에서 매우 중요합니다. 이러한 트레이스는 유용한 데이터셋을 제공하여 애플리케이션을 디버깅하고 개선하는 데 필수적입니다. Weave는 LangChain 애플리케이션의 트레이스를 자동으로 수집합니다. LangChain 라이브러리를 통해 이루어지는 모든 호출(프롬프트 템플릿, 체인, LLM 호출, 도구, 에이전트 단계 포함)을 추적하고 기록합니다. Weave 웹 인터페이스에서 이러한 트레이스를 확인할 수 있습니다. langchain_trace.png

호출을 수동으로 추적하기

자동 추적 외에도 WeaveTracer 콜백 또는 weave_tracing_enabled 컨텍스트 매니저를 사용해 호출을 수동으로 추적할 수 있습니다. 이러한 방식은 LangChain 애플리케이션의 개별 부분에서 요청 콜백을 사용하는 것과 유사합니다. 참고: Weave는 기본적으로 LangChain Runnables를 추적하며, 이는 weave.init()을 호출할 때 활성화됩니다. weave.init()을 호출하기 전에 환경 변수 WEAVE_TRACE_LANGCHAIN"false"로 설정하면 이 동작을 비활성화할 수 있습니다. 이를 통해 애플리케이션에서 특정 체인이나 개별 요청의 추적 동작을 제어할 수 있습니다.

WeaveTracer 사용하기

개별 요청을 추적하기 위해 각 LangChain 컴포넌트에 WeaveTracer 콜백 함수를 전달할 수 있습니다.
import os

os.environ["WEAVE_TRACE_LANGCHAIN"] = "false" # <- 전역 추적을 명시적으로 비활성화합니다.

from weave.integrations.langchain import WeaveTracer
from langchain_core.prompts import PromptTemplate
from langchain_openai import ChatOpenAI
import weave

# 프로젝트 이름으로 Weave를 초기화합니다
weave.init("langchain_demo")  # <-- 환경 변수가 명시적으로 `false`로 설정되어 있으므로 여기서는 추적을 활성화하지 않습니다

weave_tracer = WeaveTracer()

config = {"callbacks": [weave_tracer]}

llm = ChatOpenAI()
prompt = PromptTemplate.from_template("1 + {number} = ")

llm_chain = prompt | llm

output = llm_chain.invoke({"number": 2}, config=config) # <-- 이 chain 호출에 대해서만 추적을 활성화합니다.

llm_chain.invoke({"number": 4})  # <-- langchain 호출에 대한 추적은 비활성화되지만 openai 호출은 계속 추적됩니다

weave_tracing_enabled 컨텍스트 매니저 사용하기

또는 weave_tracing_enabled 컨텍스트 매니저를 사용하여 특정 코드 블록에만 트레이싱을 활성화할 수 있습니다.
import os

os.environ["WEAVE_TRACE_LANGCHAIN"] = "false" # <- 전역 추적을 명시적으로 비활성화합니다.

from weave.integrations.langchain import weave_tracing_enabled
from langchain_core.prompts import PromptTemplate
from langchain_openai import ChatOpenAI
import weave

# 프로젝트 이름으로 Weave를 초기화합니다
weave.init("langchain_demo")  # <-- 환경 변수가 명시적으로 `false`로 설정되어 있으므로 여기서는 추적을 활성화하지 않습니다

llm = ChatOpenAI()
prompt = PromptTemplate.from_template("1 + {number} = ")

llm_chain = prompt | llm

with weave_tracing_enabled():  # <-- 이 체인 호출에 대해서만 추적을 활성화합니다.
    output = llm_chain.invoke({"number": 2})


llm_chain.invoke({"number": 4})  # <-- langchain 호출에 대해서는 추적이 활성화되지 않지만 openai 호출은 계속 추적됩니다

구성

weave.init을 호출하면 환경 변수 WEAVE_TRACE_LANGCHAIN"true"로 설정하여 트레이싱이 활성화됩니다. 이렇게 하면 Weave가 LangChain 애플리케이션에 대한 트레이스를 자동으로 수집합니다. 이 동작을 비활성화하려면 환경 변수를 "false"로 설정하십시오.

LangChain 콜백과의 관련성

자동 로깅

weave.init()이 제공하는 자동 로깅은 LangChain 애플리케이션의 모든 컴포넌트에 생성자 콜백을 전달하는 것과 유사합니다. 즉, 프롬프트 템플릿, 체인, LLM 호출, 도구, 에이전트 단계 등 모든 상호작용이 애플리케이션 전반에서 전역적으로 추적됩니다.

수동 로깅

수동 로깅 메서드(WeaveTracerweave_tracing_enabled)는 LangChain 애플리케이션의 개별 부분에서 요청 콜백을 사용하는 것과 유사합니다. 이러한 메서드를 사용하면 애플리케이션의 어떤 부분을 추적할지 더 세밀하게 제어할 수 있습니다:
  • 생성자 콜백(Constructor Callbacks): 체인 또는 컴포넌트 전체에 적용되어, 모든 상호작용을 일관되게 로깅합니다.
  • 요청 콜백(Request Callbacks): 특정 요청에만 적용되어, 개별 호출에 대한 세부적인 추적을 가능하게 합니다.
Weave를 LangChain과 통합하면 LLM 애플리케이션에 대해 포괄적인 로깅과 모니터링을 수행할 수 있으므로, 디버깅과 성능 최적화를 더 쉽게 할 수 있습니다. 더 자세한 내용은 LangChain 문서를 참고하세요.

모델 및 평가

다양한 사용 사례에 맞는 애플리케이션에서 LLM을 구성하고 평가하는 작업은 프롬프트, 모델 구성, 추론 매개변수 등 여러 구성 요소 때문에 까다롭습니다. weave.Model을(를) 사용하면 시스템 프롬프트나 사용한 모델과 같은 실험 세부 정보를 캡처하고 정리할 수 있어, 서로 다른 반복 결과를 더 쉽게 비교할 수 있습니다. 다음 예시는 LangChain 체인을 WeaveModel로 래핑하는 방법을 보여줍니다.
import json
import asyncio

import weave

from langchain_core.prompts import PromptTemplate
from langchain_openai import ChatOpenAI

# 프로젝트 이름으로 Weave를 초기화합니다
weave.init("langchain_demo")

class ExtractFruitsModel(weave.Model):
    model_name: str
    prompt_template: str

    @weave.op()
    async def predict(self, sentence: str) -> dict:
        llm = ChatOpenAI(model=self.model_name, temperature=0.0)
        prompt = PromptTemplate.from_template(self.prompt_template)

        llm_chain = prompt | llm
        response = llm_chain.invoke({"sentence": sentence})
        result = response.content

        if result is None:
            raise ValueError("No response from model")
        parsed = json.loads(result)
        return parsed

model = ExtractFruitsModel(
    model_name="gpt-3.5-turbo-1106",
    prompt_template='Extract fields ("fruit": <str>, "color": <str>, "flavor": <str>) from the following text, as json: {sentence}',
)
sentence = "There are many fruits that were found on the recently discovered planet Goocrux. There are neoskizzles that grow there, which are purple and taste like candy."

prediction = asyncio.run(model.predict(sentence))

# Jupyter Notebook에서 실행하는 경우:
# prediction = await model.predict(sentence)

print(prediction)
이 코드는 Weave UI에서 시각화할 수 있는 모델을 생성합니다: langchain_model.png 또한 Weave 모델을 serveEvaluations와 함께 사용할 수도 있습니다.

평가

평가는 모델의 성능을 측정하는 데 도움이 됩니다. weave.Evaluation 클래스를 사용하면 모델이 특정 작업이나 데이터셋에서 얼마나 잘 수행하는지 기록할 수 있어, 서로 다른 모델과 애플리케이션의 여러 이터레이션을 더 쉽게 비교할 수 있습니다. 다음 예제는 앞에서 생성한 모델을 어떻게 평가하는지 보여줍니다:

from weave.scorers import MultiTaskBinaryClassificationF1

sentences = [
    "There are many fruits that were found on the recently discovered planet Goocrux. There are neoskizzles that grow there, which are purple and taste like candy.",
    "Pounits are a bright green color and are more savory than sweet.",
    "Finally, there are fruits called glowls, which have a very sour and bitter taste which is acidic and caustic, and a pale orange tinge to them.",
]
labels = [
    {"fruit": "neoskizzles", "color": "purple", "flavor": "candy"},
    {"fruit": "pounits", "color": "bright green", "flavor": "savory"},
    {"fruit": "glowls", "color": "pale orange", "flavor": "sour and bitter"},
]
examples = [
    {"id": "0", "sentence": sentences[0], "target": labels[0]},
    {"id": "1", "sentence": sentences[1], "target": labels[1]},
    {"id": "2", "sentence": sentences[2], "target": labels[2]},
]

@weave.op()
def fruit_name_score(target: dict, output: dict) -> dict:
    return {"correct": target["fruit"] == output["fruit"]}


evaluation = weave.Evaluation(
    dataset=examples,
    scorers=[
        MultiTaskBinaryClassificationF1(class_names=["fruit", "color", "flavor"]),
        fruit_name_score,
    ],
)
scores = asyncio.run(evaluation.evaluate(model)))
# Jupyter Notebook에서 실행하는 경우:
# scores = await evaluation.evaluate(model)

print(scores)
이 코드는 Weave UI에서 시각화할 수 있는 평가 트레이스를 생성합니다: langchain_evaluation.png Weave를 Langchain과 통합하면 LLM 기반 애플리케이션에 대한 로깅과 모니터링을 포괄적으로 수행할 수 있어 디버깅과 성능 최적화를 더 쉽게 할 수 있습니다.

알려진 이슈

  • 비동기 호출 추적(Tracing Async Calls) - LangChain의 AsyncCallbackManager 구현에 있는 버그로 인해 비동기 호출이 올바른 순서로 추적되지 않습니다. 이를 수정하기 위해 PR을 제출했습니다. 따라서 LangChain Runnables에서 ainvoke, astream, abatch 메서드를 사용할 때 트레이스 내 호출 순서가 정확하지 않을 수 있습니다.