Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix crash endtimestamp #189

Merged
merged 16 commits into from
May 7, 2024
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
37 changes: 22 additions & 15 deletions agentops/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ def __init__(self,
self._worker: Optional[Worker] = None
self._tags: Optional[List[str]] = tags

self._env_data_opt_out = os.getenv('AGENTOPS_ENV_DATA_OPT_OUT') and os.getenv('AGENTOPS_ENV_DATA_OPT_OUT').lower() == 'true'
self._env_data_opt_out = os.getenv('AGENTOPS_ENV_DATA_OPT_OUT') and os.getenv(
'AGENTOPS_ENV_DATA_OPT_OUT').lower() == 'true'

try:
self.config = Configuration(api_key=api_key,
Expand Down Expand Up @@ -136,19 +137,24 @@ def record(self, event: Union[Event, ErrorEvent]):
Args:
event (Event): The event to record.
"""
if isinstance(event, Event) and not event.end_timestamp or event.init_timestamp == event.end_timestamp:
event.end_timestamp = get_ISO_time()
if self._session is not None and not self._session.has_ended and self._worker is not None:
if isinstance(event, ErrorEvent):
if event.trigger_event:
event.trigger_event_id = event.trigger_event.id
event.trigger_event_type = event.trigger_event.event_type
self._worker.add_event(event.trigger_event.__dict__)
event.trigger_event = None # removes trigger_event from serialization
self._worker.add_event(event.__dict__)
else:
logger.warning(
"🖇 AgentOps: Cannot record event - no current session")
if self._session is None or self._session.has_ended:
logger.warning("🖇 AgentOps: Cannot record event - no current session")
return

if isinstance(event, Event):
if not event.end_timestamp or event.init_timestamp == event.end_timestamp:
event.end_timestamp = get_ISO_time()
elif isinstance(event, ErrorEvent):
if event.trigger_event:
if not event.trigger_event.end_timestamp or event.trigger_event.init_timestamp == event.trigger_event.end_timestamp:
event.trigger_event.end_timestamp = get_ISO_time()

event.trigger_event_id = event.trigger_event.id
event.trigger_event_type = event.trigger_event.event_type
self._worker.add_event(event.trigger_event.__dict__)
event.trigger_event = None # removes trigger_event from serialization

self._worker.add_event(event.__dict__)

def _record_event_sync(self, func, event_name, *args, **kwargs):
init_time = get_ISO_time()
Expand Down Expand Up @@ -240,7 +246,8 @@ def start_session(self, tags: Optional[List[str]] = None, config: Optional[Confi
if not config and not self.config:
return logger.warning("🖇 AgentOps: Cannot start session - missing configuration")

self._session = Session(inherited_session_id or uuid4(), tags or self._tags_for_future_session, host_env=get_host_env(self._env_data_opt_out))
self._session = Session(inherited_session_id or uuid4(),
tags or self._tags_for_future_session, host_env=get_host_env(self._env_data_opt_out))
self._worker = Worker(config or self.config)
start_session_result = self._worker.start_session(self._session)
if not start_session_result:
Expand Down
9 changes: 4 additions & 5 deletions agentops/event.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,12 @@ class Event:
"""

event_type: str # EventType.ENUM.value
params: Optional[Union[str, Dict[str, Any]]] = None
returns: Optional[Union[str, Dict[str, Any]]] = None
init_timestamp: Optional[str] = field(default_factory=get_ISO_time)
end_timestamp: str = field(default_factory=get_ISO_time)
params: Optional[dict] = None
returns: Optional[str] = None
init_timestamp: str = field(default_factory=get_ISO_time)
end_timestamp: Optional[str] = None
agent_id: Optional[UUID] = field(default_factory=check_call_stack_for_agent_id)
id: UUID = field(default_factory=uuid4)
# TODO: has_been_recorded: bool = False


@dataclass
Expand Down
143 changes: 75 additions & 68 deletions examples/recording-events.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -2,44 +2,50 @@
"cells": [
{
"cell_type": "markdown",
"source": [
"# Recording Events\n",
"AgentOps has a number of different [Event Types](https://docs.agentops.ai/v1/details/events)"
],
"id": "dc8cfd2cfa8a594b",
"metadata": {
"collapsed": false
},
"id": "dc8cfd2cfa8a594b"
"source": [
"# Recording Events\n",
"AgentOps has a number of different [Event Types](https://docs.agentops.ai/v1/details/events)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "168ecd05cc123de0",
"metadata": {
"collapsed": false,
"is_executing": true
},
"outputs": [],
"source": [
"import agentops\n",
"# Create new session\n",
"agentops.start_session()\n",
"agentops.init()\n",
"\n",
"# Optionally, we can add tags to the session\n",
"# agentops.start_session(['Hello Tracker'])"
],
"metadata": {
"collapsed": false,
"is_executing": true
},
"id": "168ecd05cc123de0",
"execution_count": null
"# agentops.init(tags=['Hello Tracker'])"
]
},
{
"cell_type": "markdown",
"source": [
"The easiest way to record actions is through the use of AgentOp's decorators"
],
"id": "c6d06ee8c66dad17",
"metadata": {
"collapsed": false
},
"id": "c6d06ee8c66dad17"
"source": [
"The easiest way to record actions is through the use of AgentOp's decorators"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "b460318317adc624",
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"from agentops import record_function\n",
Expand All @@ -49,25 +55,25 @@
" return x + y\n",
"\n",
"add(2,4)"
],
"metadata": {
"collapsed": false
},
"id": "b460318317adc624",
"execution_count": 0
]
},
{
"cell_type": "markdown",
"source": [
"We can also manually craft an event exactly the way we want"
],
"id": "9068a4cdd328f652",
"metadata": {
"collapsed": false
},
"id": "9068a4cdd328f652"
"source": [
"We can also manually craft an event exactly the way we want"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "b62ad88921ff26f2",
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"from agentops import ActionEvent\n",
Expand All @@ -78,38 +84,38 @@
"\n",
"if \"hello\" in str(response.choices[0].message.content).lower():\n",
" agentops.record(ActionEvent(action_type=\"Agent says hello\", params=str(message), returns=str(response.choices[0].message.content) ))"
],
"metadata": {
"collapsed": false
},
"id": "b62ad88921ff26f2",
"execution_count": 0
]
},
{
"cell_type": "code",
"outputs": [],
"source": [
"agentops.end_session('Success')"
],
"execution_count": null,
"id": "e10a89e06fe6b2be",
"metadata": {
"collapsed": false
},
"id": "e10a89e06fe6b2be",
"execution_count": null
"outputs": [],
"source": [
"agentops.end_session('Success')"
]
},
{
"cell_type": "markdown",
"source": [
"## Tool Event\n",
"Agents use tools. These tools are useful to track with information such as name, end status, runtime, etc. To record tool usage, you can create and record a `ToolEvent` similar to above."
],
"id": "f7c947d815f581e7",
"metadata": {
"collapsed": false
},
"id": "f7c947d815f581e7"
"source": [
"## Tool Event\n",
"Agents use tools. These tools are useful to track with information such as name, end status, runtime, etc. To record tool usage, you can create and record a `ToolEvent` similar to above."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "5d387a071a1c70cf",
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"from agentops import ToolEvent, record\n",
Expand All @@ -118,41 +124,42 @@
" result = integration.scrape_website(data) # perform tool logic\n",
" tool_event.returns = result\n",
" record(tool_event)"
],
"metadata": {
"collapsed": false
},
"id": "5d387a071a1c70cf"
]
},
{
"cell_type": "markdown",
"source": [
"## Error Events\n",
"Error events can be used alone or in reference to another event. Lets add a catch block to the code above"
],
"id": "968d1503dd0aae9a",
"metadata": {
"collapsed": false
},
"id": "968d1503dd0aae9a"
"source": [
"## Error Events\n",
"Error events can be used alone or in reference to another event. Lets add a catch block to the code above"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "eb23c1325298e22f",
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"from agentops import ToolEvent, record, ErrorEvent\n",
"\n",
"def scrape_website(url: str):\n",
" tool_event = ToolEvent(name='scrape_website', params={'url':url}) # the start timestamp is set when the obj is created\n",
"\n",
" try:\n",
" result = integration.scrape_website(data) # perform tool logic\n",
" tool_event.returns = result\n",
" except Error as e:\n",
" record(ErrorEvent(message=e, trigger_event=tool_event))\n",
" record(tool_event)"
],
"metadata": {
"collapsed": false
},
"id": "eb23c1325298e22f"
" 1 / 0 # Ooops! Something went wrong\n",
" except Exception as e:\n",
" record(ErrorEvent(exception=e, trigger_event=tool_event))\n",
"\n",
"scrape_website('https://app.agentops.ai') \n",
"\n",
"agentops.end_session('Success')"
]
}
],
"metadata": {
Expand All @@ -164,14 +171,14 @@
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 2
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython2",
"version": "2.7.6"
"pygments_lexer": "ipython3",
"version": "3.12.3"
}
},
"nbformat": 4,
Expand Down
Loading