Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
62e8dbc
initiate adapter pipeline types
ultmaster Dec 25, 2025
1d7b7e1
update adapter types
ultmaster Dec 26, 2025
b7ad2d3
.
ultmaster Dec 26, 2025
257ebeb
add more definitions
ultmaster Dec 26, 2025
0b27bed
reorganize folder
ultmaster Dec 29, 2025
a38dacf
update repair hierarchy
ultmaster Dec 29, 2025
62d5581
.
ultmaster Dec 29, 2025
70efeb5
fix tree
ultmaster Dec 29, 2025
8b2963e
implement CurateAnnotations
ultmaster Dec 30, 2025
d81c6dc
.
ultmaster Dec 30, 2025
3747315
.
ultmaster Jan 4, 2026
932752b
.
ultmaster Jan 5, 2026
bea0833
.
ultmaster Jan 7, 2026
cf343fc
.
ultmaster Jan 7, 2026
3559256
.
ultmaster Jan 7, 2026
16741ab
fix adapter
ultmaster Jan 7, 2026
fc6ae38
.
ultmaster Jan 7, 2026
c2f6940
.
ultmaster Jan 7, 2026
e27c2d7
fix call support
ultmaster Jan 8, 2026
ad19438
runnable
ultmaster Jan 8, 2026
7150c32
.
ultmaster Jan 8, 2026
e36d013
.
ultmaster Jan 8, 2026
907d178
fix call parsing
ultmaster Jan 9, 2026
7beafd7
add tests for preprocess
ultmaster Jan 9, 2026
3767c6d
add annotation tests
ultmaster Jan 9, 2026
1db39a5
fix annotation tests
ultmaster Jan 9, 2026
dda4308
find and fix two bugs
ultmaster Jan 12, 2026
3dea061
update test_call
ultmaster Jan 12, 2026
c8b9625
fix adapter types
ultmaster Jan 12, 2026
45c6a66
update adapter impl
ultmaster Jan 12, 2026
24697ac
fix type hints
ultmaster Jan 12, 2026
70fdf7d
update postprocess
ultmaster Jan 12, 2026
fe2fb30
update tokens/messages accumulation
ultmaster Jan 13, 2026
fba55d0
implement postprocess
ultmaster Jan 13, 2026
bbfb4a3
postprocess
ultmaster Jan 13, 2026
0f278fa
edit postprocess
ultmaster Jan 13, 2026
4351a91
update postprocess tests
ultmaster Jan 14, 2026
8c8300c
fix postprocess tests
ultmaster Jan 14, 2026
e2d5118
fix call converter tests
ultmaster Jan 14, 2026
081aebe
fix type hints
ultmaster Jan 16, 2026
3fc4603
fix ToSpans type
ultmaster Jan 16, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
551 changes: 551 additions & 0 deletions agentlightning/adapter/annotation.py

Large diffs are not rendered by default.

188 changes: 185 additions & 3 deletions agentlightning/adapter/base.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
# Copyright (c) Microsoft. All rights reserved.

from typing import Generic, Sequence, TypeVar
from typing import Any, Callable, Generic, Sequence, TypeVar, overload

from opentelemetry.sdk.trace import ReadableSpan

from agentlightning.types import Span
from agentlightning.types.adapter import BaseAdaptingSequence, BaseAdaptingSequenceItem

T_from = TypeVar("T_from")
T_to = TypeVar("T_to")
T_inv = TypeVar("T_inv")
T_from = TypeVar("T_from", contravariant=True)
T_to = TypeVar("T_to", covariant=True)
T_seq_from = TypeVar("T_seq_from", contravariant=True, bound=BaseAdaptingSequenceItem)
T_seq_to = TypeVar("T_seq_to", covariant=True, bound=BaseAdaptingSequenceItem)


class Adapter(Generic[T_from, T_to]):
Expand Down Expand Up @@ -66,6 +70,184 @@ def adapt(self, source: T_from, /) -> T_to:
raise NotImplementedError("Adapter.adapt() is not implemented")


class SequenceAdapter(
Adapter[BaseAdaptingSequence[T_seq_from], BaseAdaptingSequence[T_seq_to]],
Generic[T_seq_from, T_seq_to],
):
"""Base class for adapters that convert adapting sequences of data from one format to another.
This class specializes [`Adapter`][agentlightning.Adapter] for working with
[`AdaptingSequence`][agentlightning.AdaptingSequence] instances.
"""

def adapt(self, source: BaseAdaptingSequence[T_seq_from]) -> BaseAdaptingSequence[T_seq_to]:
return source.map(self.adapt_one)

def adapt_one(self, source: T_seq_from) -> T_seq_to:
raise NotImplementedError(f"{self.__class__.__name__}.adapt_one() is not implemented")


class Filter(Adapter[Sequence[T_inv], Sequence[T_inv]], Generic[T_inv]):
"""Filter items of type T to items of type T based on a predicate."""

def __init__(self, predicate: Callable[[T_inv], bool]) -> None:
self.predicate = predicate

def adapt(self, source: Sequence[T_inv]) -> Sequence[T_inv]:
return [item for item in source if self.predicate(item)]


class Sort(Adapter[Sequence[T_inv], Sequence[T_inv]], Generic[T_inv]):
"""Sort items of type T based on a key function."""

def __init__(self, key: Callable[[T_inv], Any]) -> None:
self.key = key

def adapt(self, source: Sequence[T_inv]) -> Sequence[T_inv]:
return sorted(source, key=self.key)


T_chain1 = TypeVar("T_chain1")
T_chain2 = TypeVar("T_chain2")
T_chain3 = TypeVar("T_chain3")
T_chain4 = TypeVar("T_chain4")
T_chain5 = TypeVar("T_chain5")
T_chain6 = TypeVar("T_chain6")
T_chain7 = TypeVar("T_chain7")
T_chain8 = TypeVar("T_chain8")
T_chain9 = TypeVar("T_chain9")


class Chain(Adapter[T_from, T_to]):
"""Chain multiple adapters together to form a single adapter.
The output of each adapter is passed as input to the next adapter in the chain.
"""

@overload
def __init__(
self,
adapter1: Adapter[T_from, T_chain1],
adapter2: Adapter[T_chain1, T_to],
/,
) -> None: ...

@overload
def __init__(
self,
adapter1: Adapter[T_from, T_chain1],
adapter2: Adapter[T_chain1, T_chain2],
adapter3: Adapter[T_chain2, T_to],
/,
) -> None: ...

@overload
def __init__(
self,
adapter1: Adapter[T_from, T_chain1],
adapter2: Adapter[T_chain1, T_chain2],
adapter3: Adapter[T_chain2, T_chain3],
adapter4: Adapter[T_chain3, T_to],
/,
) -> None: ...

@overload
def __init__(
self,
adapter1: Adapter[T_from, T_chain1],
adapter2: Adapter[T_chain1, T_chain2],
adapter3: Adapter[T_chain2, T_chain3],
adapter4: Adapter[T_chain3, T_chain4],
adapter5: Adapter[T_chain4, T_to],
/,
) -> None: ...

@overload
def __init__(
self,
adapter1: Adapter[T_from, T_chain1],
adapter2: Adapter[T_chain1, T_chain2],
adapter3: Adapter[T_chain2, T_chain3],
adapter4: Adapter[T_chain3, T_chain4],
adapter5: Adapter[T_chain4, T_chain5],
adapter6: Adapter[T_chain5, T_to],
/,
) -> None: ...

@overload
def __init__(
self,
adapter1: Adapter[T_from, T_chain1],
adapter2: Adapter[T_chain1, T_chain2],
adapter3: Adapter[T_chain2, T_chain3],
adapter4: Adapter[T_chain3, T_chain4],
adapter5: Adapter[T_chain4, T_chain5],
adapter6: Adapter[T_chain5, T_chain6],
adapter7: Adapter[T_chain6, T_to],
/,
) -> None: ...

@overload
def __init__(
self,
adapter1: Adapter[T_from, T_chain1],
adapter2: Adapter[T_chain1, T_chain2],
adapter3: Adapter[T_chain2, T_chain3],
adapter4: Adapter[T_chain3, T_chain4],
adapter5: Adapter[T_chain4, T_chain5],
adapter6: Adapter[T_chain5, T_chain6],
adapter7: Adapter[T_chain6, T_chain7],
adapter8: Adapter[T_chain7, T_to],
/,
) -> None: ...

@overload
def __init__(
self,
adapter1: Adapter[T_from, T_chain1],
adapter2: Adapter[T_chain1, T_chain2],
adapter3: Adapter[T_chain2, T_chain3],
adapter4: Adapter[T_chain3, T_chain4],
adapter5: Adapter[T_chain4, T_chain5],
adapter6: Adapter[T_chain5, T_chain6],
adapter7: Adapter[T_chain6, T_chain7],
adapter8: Adapter[T_chain7, T_chain8],
adapter9: Adapter[T_chain8, T_to],
/,
) -> None: ...

@overload
def __init__(
self,
adapter1: Adapter[T_from, T_chain1],
adapter2: Adapter[T_chain1, T_chain2],
adapter3: Adapter[T_chain2, T_chain3],
adapter4: Adapter[T_chain3, T_chain4],
adapter5: Adapter[T_chain4, T_chain5],
adapter6: Adapter[T_chain5, T_chain6],
adapter7: Adapter[T_chain6, T_chain7],
adapter8: Adapter[T_chain7, T_chain8],
adapter9: Adapter[T_chain8, T_chain9],
adapter10: Adapter[T_chain9, T_to],
/,
) -> None: ...

def __init__(self, adapter1: Adapter[Any, Any], *adapters: Adapter[Any, Any]) -> None:
# Enforce that a Chain always has at least one adapter.
self.adapters: tuple[Adapter[Any, Any], ...] = (adapter1, *adapters)

def adapt(self, source: T_from) -> T_to:
result: Any = source
for idx, adapter in enumerate(self.adapters):
try:
result = adapter.adapt(result)
except Exception as exc:
raise RuntimeError(
f"Adapter chain failed at adapter index {idx} ({adapter.__class__.__name__}). See inner exception for details."
) from exc
return result


class OtelTraceAdapter(Adapter[Sequence[ReadableSpan], T_to], Generic[T_to]):
"""Base class for adapters that convert OpenTelemetry trace spans into other formats.
Expand Down
Loading
Loading