메인 콘텐츠로 건너뛰기
W&B Weave는 sync 및 async 제너레이터 함수를 모두, 깊이 중첩된 패턴까지 포함해 트레이싱할 수 있습니다.
제너레이터는 값을 지연 평가(lazy) 방식으로 yield하기 때문에, Weave는 제너레이터가 완전히 소비되었을 때만 출력을 로그에 기록합니다(예: 리스트로 변환할 때). Weave가 트레이스에서 출력을 캡처하도록 하려면, 제너레이터를 완전히 소비해야 합니다(예: list() 호출).
from typing import Generator
import weave

weave.init("my-project")

# 이 함수는 간단한 sync 제너레이터를 사용합니다.
# Weave는 호출과 그 입력(`x`)을 트레이싱하지만,
# 출력 값은 제너레이터가 소비되었을 때만 캡처됩니다(예: `list()` 호출).
@weave.op
def basic_gen(x: int) -> Generator[int, None, None]:
    yield from range(x)

# 제너레이터 파이프라인 내에서 사용되는 일반적인 sync 함수입니다.
# 이 함수의 호출도 Weave에 의해 독립적으로 트레이싱됩니다.
@weave.op
def inner(x: int) -> int:
    return x + 1

# 다른 트레이스된 함수(`inner`)를 호출하는 sync 제너레이터입니다.
# 각 `yield`된 값은 `inner`에 대한 개별 트레이스 호출에서 나옵니다.
@weave.op
def nested_generator(x: int) -> Generator[int, None, None]:
    for i in range(x):
        yield inner(i)

# 위의 제너레이터를 조합한 더 복잡한 제너레이터입니다.
# 여기에서의 트레이싱은 계층적 호출 트리를 생성합니다:
# - `deeply_nested_generator` (부모)
#   - `nested_generator` (자식)
#     - `inner` (손자)
@weave.op
def deeply_nested_generator(x: int) -> Generator[int, None, None]:
    for i in range(x):
        for j in nested_generator(i):
            yield j

# Weave가 출력을 캡처하려면 제너레이터가 *소비*되어야 합니다.
# 이는 sync 및 async 제너레이터 모두에 해당합니다.
res = deeply_nested_generator(4)
list(res)  # 모든 중첩 호출과 yield에 대한 트레이싱을 트리거합니다
다음 스크린샷은 앞의 코드에 대한 트레이스 하나를 선택한 Traces 페이지를 보여줍니다. 가운데 패널에는 선택된 트레이스의 트레이스 트리가 표시됩니다. 이 트레이스 트리에는 계층 구조에서 deeply_nested_generator, nested_generator, inner Op가 표시됩니다. Weave Traces 페이지에서 깊이 중첩된 Op를 보여 주는 선택된 트레이스 트리

제너레이터 소비하기

Weave는 제너레이터를 끝까지 소비한 이후에만 제너레이터 출력값을 캡처합니다. 제너레이터는 이를 반복(iterate)해서 소비할 수 있습니다(예: list()로 감싸거나, for 루프를 사용하거나, 소진될 때까지 next()를 호출). async for 또는 이에 상응하는 방식으로 소비할 때도 async 제너레이터에 동일하게 적용됩니다. 함수와 메서드에 @weave.op 데코레이터를 사용하는 방법에 대한 자세한 내용은 Create calls를 참조하세요.