Home / Class/ Tee Class — langchain Architecture

Tee Class — langchain Architecture

Architecture documentation for the Tee class in iter.py from the langchain codebase.

Entity Profile

Dependency Diagram

graph TD
  dd9ce176_1561_3f80_3843_c05966e88612["Tee"]
  b289db43_7cd8_e404_08a4_ad932b851c13["iter.py"]
  dd9ce176_1561_3f80_3843_c05966e88612 -->|defined in| b289db43_7cd8_e404_08a4_ad932b851c13
  260deecc_1a31_b67a_f8f2_9d251be84e64["__init__()"]
  dd9ce176_1561_3f80_3843_c05966e88612 -->|method| 260deecc_1a31_b67a_f8f2_9d251be84e64
  ef036ca3_8ab4_8247_11f4_1c59496421c3["__len__()"]
  dd9ce176_1561_3f80_3843_c05966e88612 -->|method| ef036ca3_8ab4_8247_11f4_1c59496421c3
  d583a6a4_7c09_4524_a845_6f4acc8be4a0["__getitem__()"]
  dd9ce176_1561_3f80_3843_c05966e88612 -->|method| d583a6a4_7c09_4524_a845_6f4acc8be4a0
  a6e41960_acd5_9c3e_003d_bf1487b0c582["__iter__()"]
  dd9ce176_1561_3f80_3843_c05966e88612 -->|method| a6e41960_acd5_9c3e_003d_bf1487b0c582
  a3db0721_34c2_af48_df9e_11f033ec5d42["__enter__()"]
  dd9ce176_1561_3f80_3843_c05966e88612 -->|method| a3db0721_34c2_af48_df9e_11f033ec5d42
  0d99fc47_ba0f_ac93_6426_10b6fb57413f["__exit__()"]
  dd9ce176_1561_3f80_3843_c05966e88612 -->|method| 0d99fc47_ba0f_ac93_6426_10b6fb57413f
  884c0eba_4881_a0c7_628a_a68b059c4131["close()"]
  dd9ce176_1561_3f80_3843_c05966e88612 -->|method| 884c0eba_4881_a0c7_628a_a68b059c4131

Relationship Graph

Source Code

libs/core/langchain_core/utils/iter.py lines 91–199

class Tee(Generic[T]):
    """Create `n` separate asynchronous iterators over `iterable`.

    This splits a single `iterable` into multiple iterators, each providing the same
    items in the same order.

    All child iterators may advance separately but share the same items from `iterable`
    -- when the most advanced iterator retrieves an item, it is buffered until the least
    advanced iterator has yielded it as well. A `tee` works lazily and can handle an
    infinite `iterable`, provided that all iterators advance.

    ```python
    async def derivative(sensor_data):
        previous, current = a.tee(sensor_data, n=2)
        await a.anext(previous)  # advance one iterator
        return a.map(operator.sub, previous, current)
    ```

    Unlike `itertools.tee`, `.tee` returns a custom type instead of a `tuple`. Like a
    tuple, it can be indexed, iterated and unpacked to get the child iterators. In
    addition, its `.tee.aclose` method immediately closes all children, and it can be
    used in an `async with` context for the same effect.

    If `iterable` is an iterator and read elsewhere, `tee` will *not* provide these
    items. Also, `tee` must internally buffer each item until the last iterator has
    yielded it; if the most and least advanced iterator differ by most data, using a
    `list` is more efficient (but not lazy).

    If the underlying iterable is concurrency safe (`anext` may be awaited concurrently)
    the resulting iterators are concurrency safe as well. Otherwise, the iterators are
    safe if there is only ever one single "most advanced" iterator. To enforce
    sequential use of `anext`, provide a `lock`

    - e.g., an `asyncio.Lock` instance in an `asyncio` application - and access is
        automatically synchronised.

    """

    def __init__(
        self,
        iterable: Iterator[T],
        n: int = 2,
        *,
        lock: AbstractContextManager[Any] | None = None,
    ):
        """Create a `tee`.

        Args:
            iterable: The iterable to split.
            n: The number of iterators to create.
            lock: The lock to synchronise access to the shared buffers.

        """
        self._iterator = iter(iterable)
        self._buffers: list[deque[T]] = [deque() for _ in range(n)]
        self._children = tuple(
            tee_peer(
                iterator=self._iterator,
                buffer=buffer,
                peers=self._buffers,
                lock=lock if lock is not None else NoLock(),
            )
            for buffer in self._buffers
        )

    def __len__(self) -> int:
        """Return the number of child iterators."""
        return len(self._children)

    @overload
    def __getitem__(self, item: int) -> Iterator[T]: ...

    @overload
    def __getitem__(self, item: slice) -> tuple[Iterator[T], ...]: ...

    def __getitem__(self, item: int | slice) -> Iterator[T] | tuple[Iterator[T], ...]:
        """Return the child iterator(s) at the given index or slice."""
        return self._children[item]

    def __iter__(self) -> Iterator[Iterator[T]]:
        """Return an iterator over the child iterators.

Frequently Asked Questions

What is the Tee class?
Tee is a class in the langchain codebase, defined in libs/core/langchain_core/utils/iter.py.
Where is Tee defined?
Tee is defined in libs/core/langchain_core/utils/iter.py at line 91.

Analyze Your Own Codebase

Get architecture documentation, dependency graphs, and domain analysis for your codebase in minutes.

Try Supermodel Free