Skip to content
Merged
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
80 changes: 73 additions & 7 deletions alignai/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
from alignai.config import Config
from alignai.constants import (
DEFAULT_ASSISTANT_ID,
FEEDBACK_THUMBS_DOWN,
FEEDBACK_THUMBS_UP,
ROLE_ASSISTANT,
ROLE_USER,
SERVER_BASE_URL,
Expand Down Expand Up @@ -203,13 +205,8 @@ def create_message(
raise ValidationError("content is required")
if custom_properties:
validate_custom_properties_or_raise(custom_properties)

if message_index <= 0:
self.logger.error(f"Invalid message index '{message_index}': Message index must be a positive integer")
return
if role not in [ROLE_USER, ROLE_ASSISTANT]:
self.logger.error(f"Invalid message role '{role}': Message role must be either 'user' or 'assistant'")
return
if role not in {ROLE_USER, ROLE_ASSISTANT}:
raise ValidationError(f"Invalid message role '{role}': Message role must be either 'user' or 'assistant'")

create_message_event = Event(
id=uuid.uuid4().hex,
Expand All @@ -232,6 +229,75 @@ def create_message(
)
self._collect(create_message_event)

def create_session_feedback(
self,
session_id: str,
feedback_type: str,
):
"""Record an feedback targeting a specific session.

Args:
session_id (str): Session ID associated with the message.
feedback_type (str): alignai.constants.FEEDBACK_THUMBS_UP or alignai.constants.FEEDBACK_THUMBS_DOWN.
""" # noqa: E501
validate_session_id_or_raise(session_id)
if feedback_type != FEEDBACK_THUMBS_UP and feedback_type != FEEDBACK_THUMBS_DOWN:
raise ValidationError(
f"Invalid feedback type '{feedback_type}': Feedback type must be either 'thumbs_up' or 'thumbs_down'"
)

create_feedback_event = Event(
id=uuid.uuid4().hex,
type=EventTypes.MESSAGE_CREATE,
create_time=datetime_to_timestamp(pendulum.now()),
properties=EventProperties(
feedback_properties=EventProperties.FeedbackProperties(
session_id=session_id,
feedback_target=EventProperties.FeedbackProperties.TARGET_SESSION,
type=feedback_type,
),
),
project_id=self.project_id,
)
self._collect(create_feedback_event)

def create_message_feedback(
self,
session_id: str,
message_index: int,
feedback_type: str,
):
"""Record an feedback targeting a specific message.

Args:
session_id (str): Session ID associated with the message.
message_index (int): Message index used to sort messages in a chronological order within a session. Must be a positive integer.
feedback_type (str): alignai.constants.FEEDBACK_THUMBS_UP or alignai.constants.FEEDBACK_THUMBS_DOWN.
""" # noqa: E501
validate_session_id_or_raise(session_id)
if message_index <= 0:
raise ValidationError("message_index must be greater than 0")
if feedback_type != FEEDBACK_THUMBS_UP and feedback_type != FEEDBACK_THUMBS_DOWN:
raise ValidationError(
f"Invalid feedback type '{feedback_type}': Feedback type must be either 'thumbs_up' or 'thumbs_down'"
)

create_feedback_event = Event(
id=uuid.uuid4().hex,
type=EventTypes.MESSAGE_CREATE,
create_time=datetime_to_timestamp(pendulum.now()),
properties=EventProperties(
feedback_properties=EventProperties.FeedbackProperties(
session_id=session_id,
message_index_hint=message_index,
feedback_target=EventProperties.FeedbackProperties.TARGET_MESSAGE,
type=feedback_type,
),
),
project_id=self.project_id,
)
self._collect(create_feedback_event)

def flush(self, timeout_seconds: int | None = None) -> None:
"""Dispatch all events from the buffer to Align AI.

Expand Down
2 changes: 2 additions & 0 deletions alignai/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ class EventTypes:
ROLE_ASSISTANT = "assistant"
DEFAULT_ASSISTANT_ID = "DEFAULT"

FEEDBACK_THUMBS_UP = "thumbs_up"
FEEDBACK_THUMBS_DOWN = "thumbs_down"

FLUSH_INTERVAL_MS = 3000
FLUSH_BATCH_SIZE = 50
Expand Down
188 changes: 98 additions & 90 deletions alignai/ingestion/v1alpha/event_pb2.py

Large diffs are not rendered by default.

14 changes: 6 additions & 8 deletions alignai/ingestion/v1alpha/event_pb2.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ class EventProperties(_message.Message):
user_display_name: str
def __init__(self, user_id: _Optional[str] = ..., user_email: _Optional[str] = ..., user_ip: _Optional[str] = ..., user_location: _Optional[_Union[EventProperties.UserProperties.Location, _Mapping]] = ..., user_create_time: _Optional[_Union[_timestamp_pb2.Timestamp, _Mapping]] = ..., user_display_name: _Optional[str] = ...) -> None: ...
class FeedbackProperties(_message.Message):
__slots__ = ("session_id", "feedback_target", "feedback_score", "message_id_hint", "message_index_hint")
__slots__ = ("session_id", "message_index_hint", "feedback_target", "type")
class Target(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
__slots__ = ()
TARGET_UNSPECIFIED: _ClassVar[EventProperties.FeedbackProperties.Target]
Expand All @@ -95,16 +95,14 @@ class EventProperties(_message.Message):
TARGET_SESSION: EventProperties.FeedbackProperties.Target
TARGET_MESSAGE: EventProperties.FeedbackProperties.Target
SESSION_ID_FIELD_NUMBER: _ClassVar[int]
FEEDBACK_TARGET_FIELD_NUMBER: _ClassVar[int]
FEEDBACK_SCORE_FIELD_NUMBER: _ClassVar[int]
MESSAGE_ID_HINT_FIELD_NUMBER: _ClassVar[int]
MESSAGE_INDEX_HINT_FIELD_NUMBER: _ClassVar[int]
FEEDBACK_TARGET_FIELD_NUMBER: _ClassVar[int]
TYPE_FIELD_NUMBER: _ClassVar[int]
session_id: str
feedback_target: EventProperties.FeedbackProperties.Target
feedback_score: int
message_id_hint: str
message_index_hint: int
def __init__(self, session_id: _Optional[str] = ..., feedback_target: _Optional[_Union[EventProperties.FeedbackProperties.Target, str]] = ..., feedback_score: _Optional[int] = ..., message_id_hint: _Optional[str] = ..., message_index_hint: _Optional[int] = ...) -> None: ...
feedback_target: EventProperties.FeedbackProperties.Target
type: str
def __init__(self, session_id: _Optional[str] = ..., message_index_hint: _Optional[int] = ..., feedback_target: _Optional[_Union[EventProperties.FeedbackProperties.Target, str]] = ..., type: _Optional[str] = ...) -> None: ...
class CustomPropertyValue(_message.Message):
__slots__ = ("string_value",)
STRING_VALUE_FIELD_NUMBER: _ClassVar[int]
Expand Down
3 changes: 0 additions & 3 deletions alignai/ingestion/v1alpha/event_pb2_grpc.py

This file was deleted.

43 changes: 24 additions & 19 deletions alignai/ingestion/v1alpha/ingestion_pb2.py

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

12 changes: 2 additions & 10 deletions alignai/ingestion/v1alpha/ingestion_pb2.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,7 @@ from alignai.ingestion.v1alpha import event_pb2 as _event_pb2
from google.protobuf.internal import containers as _containers
from google.protobuf import descriptor as _descriptor
from google.protobuf import message as _message
from typing import (
ClassVar as _ClassVar,
Iterable as _Iterable,
Mapping as _Mapping,
Optional as _Optional,
Union as _Union,
)
from typing import ClassVar as _ClassVar, Iterable as _Iterable, Mapping as _Mapping, Optional as _Optional, Union as _Union

DESCRIPTOR: _descriptor.FileDescriptor

Expand All @@ -20,6 +14,4 @@ class CollectEventsRequest(_message.Message):
EVENTS_FIELD_NUMBER: _ClassVar[int]
request_id: str
events: _containers.RepeatedCompositeFieldContainer[_event_pb2.Event]
def __init__(
self, request_id: _Optional[str] = ..., events: _Optional[_Iterable[_Union[_event_pb2.Event, _Mapping]]] = ...
) -> None: ...
def __init__(self, request_id: _Optional[str] = ..., events: _Optional[_Iterable[_Union[_event_pb2.Event, _Mapping]]] = ...) -> None: ...
67 changes: 0 additions & 67 deletions alignai/ingestion/v1alpha/ingestion_pb2_grpc.py

This file was deleted.

Loading