Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 2 additions & 0 deletions protos/api.proto
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ message Prediction {
optional string posterior = 2;
// logit
optional string logit = 3;
// regression score for continuous tasks (e.g. intensity), in (0,1)
optional string score = 4;
}

message InferenceResult {
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "behavioralsignals"
version = "0.3.0"
version = "0.4.0"
description = "Python SDK for Behavioral Signals API"
readme = "README.md"
authors = []
Expand Down
24 changes: 12 additions & 12 deletions src/behavioralsignals/generated/api_pb2.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions src/behavioralsignals/generated/api_pb2.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,16 @@ class AudioStream(_message.Message):
def __init__(self, cid: _Optional[int] = ..., x_auth_token: _Optional[str] = ..., config: _Optional[_Union[AudioConfig, _Mapping]] = ..., audio_content: _Optional[bytes] = ...) -> None: ...

class Prediction(_message.Message):
__slots__ = ("label", "posterior", "logit")
__slots__ = ("label", "posterior", "logit", "score")
LABEL_FIELD_NUMBER: _ClassVar[int]
POSTERIOR_FIELD_NUMBER: _ClassVar[int]
LOGIT_FIELD_NUMBER: _ClassVar[int]
SCORE_FIELD_NUMBER: _ClassVar[int]
label: str
posterior: str
logit: str
def __init__(self, label: _Optional[str] = ..., posterior: _Optional[str] = ..., logit: _Optional[str] = ...) -> None: ...
score: str
def __init__(self, label: _Optional[str] = ..., posterior: _Optional[str] = ..., logit: _Optional[str] = ..., score: _Optional[str] = ...) -> None: ...

class InferenceResult(_message.Message):
__slots__ = ("id", "start_time", "end_time", "task", "prediction", "final_label", "embedding", "level")
Expand Down
33 changes: 26 additions & 7 deletions src/behavioralsignals/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,19 +100,21 @@ def validate_meta_json(cls, v):
raise ValueError("meta must be valid JSON string")
return v


class DeepfakeAudioUploadParams(AudioUploadParams):
enable_generator_detection: bool = Field(
False, description="Whether to include prediction for the source of the deepfake (generator model)"
False,
description="Whether to include prediction for the source of the deepfake (generator model)",
)


class DeepfakeS3UrlUploadParams(S3UrlUploadParams):
enable_generator_detection: bool = Field(
False, description="Whether to include prediction for the source of the deepfake (generator model)"
False,
description="Whether to include prediction for the source of the deepfake (generator model)",
)



class ProcessItem(BaseModel):
"""Individual process in the list"""

Expand Down Expand Up @@ -188,17 +190,34 @@ def failed_processes(self) -> List[ProcessItem]:
return [p for p in self.processes if p.is_failed]


class ModelPredictions(BaseModel):
class _SerializableModel(BaseModel):
"""Base for result models that omits null fields on serialization by default."""

def model_dump(self, **kwargs):
kwargs.setdefault("exclude_none", True)
return super().model_dump(**kwargs)

def model_dump_json(self, **kwargs):
kwargs.setdefault("exclude_none", True)
return super().model_dump_json(**kwargs)


class ModelPredictions(_SerializableModel):
label: Optional[str] = Field(None, description="The name of the class", example="happy")
posterior: Optional[str] = Field(
None, description="The probability of this class being present", example="0.754"
)
score: Optional[str] = Field(
None,
description="The regression score for continuous tasks (e.g. intensity), bounded in (0,1)",
example="0.62",
)
dominantInSegments: Optional[List[int]] = Field(
None, description="The segments in which this class is dominant"
)


class ResultItem(BaseModel):
class ResultItem(_SerializableModel):
id: Optional[str] = Field(None, description="The id of the segment/utterance", example="1")
startTime: Optional[str] = Field(
None, description="The start time of the segment/utterance in seconds", example="0.209"
Expand Down Expand Up @@ -238,15 +257,15 @@ def et(self) -> float:
return float(self.endTime)


class ResultResponse(BaseModel):
class ResultResponse(_SerializableModel):
pid: Optional[int] = Field(None, description="Unique ID for the processing job")
cid: Optional[int] = Field(None, description="Client ID that requested the processing")
code: Optional[int] = Field(None, description="Code indicating status")
message: Optional[str] = Field(None, description="Description of status")
results: Optional[List[ResultItem]] = None


class StreamingResultResponse(BaseModel):
class StreamingResultResponse(_SerializableModel):
pid: Optional[int] = Field(None, description="Unique ID for the processing job")
cid: Optional[int] = Field(None, description="Client ID that requested the processing")
message_id: Optional[int] = Field(
Expand Down