284 lines
6.8 KiB
Python
284 lines
6.8 KiB
Python
from __future__ import annotations
|
|
|
|
import abc
|
|
from collections.abc import Mapping, Sequence
|
|
from typing import TYPE_CHECKING, Any
|
|
|
|
if TYPE_CHECKING:
|
|
from openai.types.responses import Response, ResponseInputItemParam
|
|
|
|
|
|
class SpanData(abc.ABC):
|
|
@abc.abstractmethod
|
|
def export(self) -> dict[str, Any]:
|
|
pass
|
|
|
|
@property
|
|
@abc.abstractmethod
|
|
def type(self) -> str:
|
|
pass
|
|
|
|
|
|
class AgentSpanData(SpanData):
|
|
__slots__ = ("name", "handoffs", "tools", "output_type")
|
|
|
|
def __init__(
|
|
self,
|
|
name: str,
|
|
handoffs: list[str] | None = None,
|
|
tools: list[str] | None = None,
|
|
output_type: str | None = None,
|
|
):
|
|
self.name = name
|
|
self.handoffs: list[str] | None = handoffs
|
|
self.tools: list[str] | None = tools
|
|
self.output_type: str | None = output_type
|
|
|
|
@property
|
|
def type(self) -> str:
|
|
return "agent"
|
|
|
|
def export(self) -> dict[str, Any]:
|
|
return {
|
|
"type": self.type,
|
|
"name": self.name,
|
|
"handoffs": self.handoffs,
|
|
"tools": self.tools,
|
|
"output_type": self.output_type,
|
|
}
|
|
|
|
|
|
class FunctionSpanData(SpanData):
|
|
__slots__ = ("name", "input", "output")
|
|
|
|
def __init__(self, name: str, input: str | None, output: Any | None):
|
|
self.name = name
|
|
self.input = input
|
|
self.output = output
|
|
|
|
@property
|
|
def type(self) -> str:
|
|
return "function"
|
|
|
|
def export(self) -> dict[str, Any]:
|
|
return {
|
|
"type": self.type,
|
|
"name": self.name,
|
|
"input": self.input,
|
|
"output": str(self.output) if self.output else None,
|
|
}
|
|
|
|
|
|
class GenerationSpanData(SpanData):
|
|
__slots__ = (
|
|
"input",
|
|
"output",
|
|
"model",
|
|
"model_config",
|
|
"usage",
|
|
)
|
|
|
|
def __init__(
|
|
self,
|
|
input: Sequence[Mapping[str, Any]] | None = None,
|
|
output: Sequence[Mapping[str, Any]] | None = None,
|
|
model: str | None = None,
|
|
model_config: Mapping[str, Any] | None = None,
|
|
usage: dict[str, Any] | None = None,
|
|
):
|
|
self.input = input
|
|
self.output = output
|
|
self.model = model
|
|
self.model_config = model_config
|
|
self.usage = usage
|
|
|
|
@property
|
|
def type(self) -> str:
|
|
return "generation"
|
|
|
|
def export(self) -> dict[str, Any]:
|
|
return {
|
|
"type": self.type,
|
|
"input": self.input,
|
|
"output": self.output,
|
|
"model": self.model,
|
|
"model_config": self.model_config,
|
|
"usage": self.usage,
|
|
}
|
|
|
|
|
|
class ResponseSpanData(SpanData):
|
|
__slots__ = ("response", "input")
|
|
|
|
def __init__(
|
|
self,
|
|
response: Response | None = None,
|
|
input: str | list[ResponseInputItemParam] | None = None,
|
|
) -> None:
|
|
self.response = response
|
|
# This is not used by the OpenAI trace processors, but is useful for other tracing
|
|
# processor implementations
|
|
self.input = input
|
|
|
|
@property
|
|
def type(self) -> str:
|
|
return "response"
|
|
|
|
def export(self) -> dict[str, Any]:
|
|
return {
|
|
"type": self.type,
|
|
"response_id": self.response.id if self.response else None,
|
|
}
|
|
|
|
|
|
class HandoffSpanData(SpanData):
|
|
__slots__ = ("from_agent", "to_agent")
|
|
|
|
def __init__(self, from_agent: str | None, to_agent: str | None):
|
|
self.from_agent = from_agent
|
|
self.to_agent = to_agent
|
|
|
|
@property
|
|
def type(self) -> str:
|
|
return "handoff"
|
|
|
|
def export(self) -> dict[str, Any]:
|
|
return {
|
|
"type": self.type,
|
|
"from_agent": self.from_agent,
|
|
"to_agent": self.to_agent,
|
|
}
|
|
|
|
|
|
class CustomSpanData(SpanData):
|
|
__slots__ = ("name", "data")
|
|
|
|
def __init__(self, name: str, data: dict[str, Any]):
|
|
self.name = name
|
|
self.data = data
|
|
|
|
@property
|
|
def type(self) -> str:
|
|
return "custom"
|
|
|
|
def export(self) -> dict[str, Any]:
|
|
return {
|
|
"type": self.type,
|
|
"name": self.name,
|
|
"data": self.data,
|
|
}
|
|
|
|
|
|
class GuardrailSpanData(SpanData):
|
|
__slots__ = ("name", "triggered")
|
|
|
|
def __init__(self, name: str, triggered: bool = False):
|
|
self.name = name
|
|
self.triggered = triggered
|
|
|
|
@property
|
|
def type(self) -> str:
|
|
return "guardrail"
|
|
|
|
def export(self) -> dict[str, Any]:
|
|
return {
|
|
"type": self.type,
|
|
"name": self.name,
|
|
"triggered": self.triggered,
|
|
}
|
|
|
|
|
|
class TranscriptionSpanData(SpanData):
|
|
__slots__ = (
|
|
"input",
|
|
"output",
|
|
"model",
|
|
"model_config",
|
|
)
|
|
|
|
def __init__(
|
|
self,
|
|
input: str | None = None,
|
|
input_format: str | None = "pcm",
|
|
output: str | None = None,
|
|
model: str | None = None,
|
|
model_config: Mapping[str, Any] | None = None,
|
|
):
|
|
self.input = input
|
|
self.input_format = input_format
|
|
self.output = output
|
|
self.model = model
|
|
self.model_config = model_config
|
|
|
|
@property
|
|
def type(self) -> str:
|
|
return "transcription"
|
|
|
|
def export(self) -> dict[str, Any]:
|
|
return {
|
|
"type": self.type,
|
|
"input": {
|
|
"data": self.input or "",
|
|
"format": self.input_format,
|
|
},
|
|
"output": self.output,
|
|
"model": self.model,
|
|
"model_config": self.model_config,
|
|
}
|
|
|
|
|
|
class SpeechSpanData(SpanData):
|
|
__slots__ = ("input", "output", "model", "model_config", "first_byte_at")
|
|
|
|
def __init__(
|
|
self,
|
|
input: str | None = None,
|
|
output: str | None = None,
|
|
output_format: str | None = "pcm",
|
|
model: str | None = None,
|
|
model_config: Mapping[str, Any] | None = None,
|
|
first_content_at: str | None = None,
|
|
):
|
|
self.input = input
|
|
self.output = output
|
|
self.output_format = output_format
|
|
self.model = model
|
|
self.model_config = model_config
|
|
self.first_content_at = first_content_at
|
|
|
|
@property
|
|
def type(self) -> str:
|
|
return "speech"
|
|
|
|
def export(self) -> dict[str, Any]:
|
|
return {
|
|
"type": self.type,
|
|
"input": self.input,
|
|
"output": {
|
|
"data": self.output or "",
|
|
"format": self.output_format,
|
|
},
|
|
"model": self.model,
|
|
"model_config": self.model_config,
|
|
"first_content_at": self.first_content_at,
|
|
}
|
|
|
|
|
|
class SpeechGroupSpanData(SpanData):
|
|
__slots__ = "input"
|
|
|
|
def __init__(
|
|
self,
|
|
input: str | None = None,
|
|
):
|
|
self.input = input
|
|
|
|
@property
|
|
def type(self) -> str:
|
|
return "speech-group"
|
|
|
|
def export(self) -> dict[str, Any]:
|
|
return {
|
|
"type": self.type,
|
|
"input": self.input,
|
|
}
|