Skip to content

Commit

Permalink
NoSessionException when user does not init() (#307)
Browse files Browse the repository at this point in the history
* Fixed but needs refactor and testing

* added back ao to crew example notebook

* clear outputs

* only get first session if session

* doesnt throw exception

* version bump

* update text to not be safe function

* refactored state management

* black formatting

* cleanup and add test back

* Adding more explicit warning message when multiple sessions detected

---------

Co-authored-by: Braelyn Boynton <bboynton97@gmail.com>
  • Loading branch information
HowieG and bboynton97 committed Jul 23, 2024
1 parent 7228e2e commit a2f2f7f
Show file tree
Hide file tree
Showing 9 changed files with 265 additions and 39 deletions.
12 changes: 5 additions & 7 deletions agentops/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
from .agent import track_agent
from .log_config import logger
from .session import Session
from .state import get_state, set_state


try:
from .partners.langchain_callback_handler import (
Expand All @@ -20,8 +22,6 @@
except ModuleNotFoundError:
pass

is_initialized = False


def noop(*args, **kwargs):
return
Expand All @@ -30,7 +30,7 @@ def noop(*args, **kwargs):
def check_init(child_function):
@functools.wraps(child_function)
def wrapper(*args, **kwargs):
if is_initialized:
if get_state("is_initialized"): # is initialized in state.py is not working
return child_function(*args, **kwargs)
else:
return noop(*args, **kwargs)
Expand Down Expand Up @@ -103,8 +103,7 @@ def init(
tags=tags, config=c.config, inherited_session_id=inherited_session_id
)

global is_initialized
is_initialized = True
set_state("is_initialized", True)

return session

Expand Down Expand Up @@ -156,8 +155,7 @@ def start_session(
try:
sess_result = Client().start_session(tags, config, inherited_session_id)

global is_initialized
is_initialized = True
set_state("is_initialized", True)

return sess_result
except Exception:
Expand Down
5 changes: 5 additions & 0 deletions agentops/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from uuid import uuid4
from agentops import Client
from inspect import isclass, isfunction
from .state import get_state


def track_agent(name: Union[str, None] = None):
Expand All @@ -17,6 +18,10 @@ def decorator(obj):
def new_init(self, *args, **kwargs):
try:
original_init(self, *args, **kwargs)

if not get_state("is_initialized"):
return

self.agent_ops_agent_id = str(uuid4())

session = kwargs.get("session", None)
Expand Down
44 changes: 32 additions & 12 deletions agentops/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
from .llm_tracker import LlmTracker
from termcolor import colored
from typing import Tuple
from .state import get_state, set_state


@conditional_singleton
Expand Down Expand Up @@ -178,6 +179,8 @@ def add_tags(self, tags: List[str]) -> None:
return

session = self._safe_get_session()
if session is None:
return

session.add_tags(tags=tags)

Expand All @@ -191,11 +194,13 @@ def set_tags(self, tags: List[str]) -> None:
tags (List[str]): The list of tags to set.
"""

try:
session = self._safe_get_session()
session.set_tags(tags=tags)
except NoSessionException:
session = self._safe_get_session()

if session is None:
self._tags_for_future_session = tags
return

session.set_tags(tags=tags)

def record(self, event: Union[Event, ErrorEvent]) -> None:
"""
Expand All @@ -206,6 +211,9 @@ def record(self, event: Union[Event, ErrorEvent]) -> None:
"""

session = self._safe_get_session()
if session is None:
logger.error("Could not record event. No session.")
return
session.record(event)

def _record_event_sync(self, func, event_name, *args, **kwargs):
Expand Down Expand Up @@ -382,7 +390,7 @@ def end_session(
end_state_reason: Optional[str] = None,
video: Optional[str] = None,
is_auto_end: Optional[bool] = None,
) -> Decimal:
) -> Optional[Decimal]:
"""
End the current session with the AgentOps service.
Expand All @@ -397,6 +405,8 @@ def end_session(
"""

session = self._safe_get_session()
if session is None:
return
session.end_state = end_state
session.end_state_reason = end_state_reason

Expand Down Expand Up @@ -424,7 +434,11 @@ def end_session(
"This run's cost ${}".format(
"{:.2f}".format(token_cost_d)
if token_cost_d == 0
else "{:.6f}".format(token_cost_d.quantize(Decimal('0.000001'), rounding=ROUND_HALF_UP))
else "{:.6f}".format(
token_cost_d.quantize(
Decimal("0.000001"), rounding=ROUND_HALF_UP
)
)
)
)

Expand Down Expand Up @@ -453,6 +467,8 @@ def create_agent(
else:
# if no session passed, assume single session
session = self._safe_get_session()
if session is None:
return
session.create_agent(name=name, agent_id=agent_id)

return agent_id
Expand Down Expand Up @@ -553,7 +569,7 @@ def _update_session(self, session: Session):
)
] = session

def _safe_get_session(self) -> Session:
def _safe_get_session(self) -> Optional[Session]:
for s in self._sessions:
if s.end_state is not None:
self._sessions.remove(s)
Expand All @@ -563,15 +579,19 @@ def _safe_get_session(self) -> Session:
session = self._sessions[0]

if len(self._sessions) == 0:
raise NoSessionException("No session exists")
if get_state("is_initialized"):
return None

elif len(self._sessions) > 1:
raise MultiSessionException(
"If multiple sessions exist, you must use session.function(). Example: session.add_tags(...) instead "
"of agentops.add_tags(...). More info: "
"https://docs.agentops.ai/v1/concepts/core-concepts#session-management"
calling_function = inspect.stack()[
2
].function # Using index 2 because we have a wrapper at index 1
logger.warning(
f"Multiple sessions detected. You must use session.{calling_function}(). More info: https://docs.agentops.ai/v1/concepts/core-concepts#session-management"
)

return

return session

def end_all_sessions(self):
Expand Down
9 changes: 4 additions & 5 deletions agentops/meta_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,10 @@ def wrapper(self, *args, **kwargs):
logger.warning(f"Error: {e}")
config = getattr(self, "config", None)
if config is not None:
type(self).send_exception_to_server(
e,
self.config._api_key,
self._sessions[0], # TODO: find which session caused exception
)
session = None
if len(self._sessions) > 0:
session = self._sessions[0]
type(self).send_exception_to_server(e, self.config._api_key, session)
raise e

return wrapper
9 changes: 9 additions & 0 deletions agentops/state.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
state_dict = {}


def set_state(key: str, value: any):
state_dict[key] = value


def get_state(key: str) -> any:
return state_dict.get(key)
35 changes: 25 additions & 10 deletions examples/crew/job_posting.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,16 @@
"metadata": {},
"outputs": [],
"source": [
"%pip install -U agentops\n",
"# %pip install -e ../.."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%pip install -U 'crewai[tools]'\n",
"%pip install -U 'crewai[agentops]'"
]
},
Expand All @@ -18,9 +27,9 @@
"source": [
"import os\n",
"\n",
"os.environ[\"SERPER_API_KEY\"] = \"YOUR_SERPER_API_KEY\"\n",
"os.environ[\"OPENAI_API_KEY\"] = \"YOUR_OPENAI_API_KEY\"\n",
"os.environ[\"AGENTOPS_API_KEY\"] = \"YOUR_AGENTOPS_API_KEY\""
"os.environ[\"SERPER_API_KEY\"] = \"...\"\n",
"os.environ[\"OPENAI_API_KEY\"] = \"...\"\n",
"os.environ[\"AGENTOPS_API_KEY\"] = \"...\""
]
},
{
Expand All @@ -30,21 +39,22 @@
"outputs": [],
"source": [
"from crewai import Agent\n",
"from crewai_tools.tools import WebsiteSearchTool, SeperDevTool, FileReadTool\n",
"from crewai_tools.tools import WebsiteSearchTool, SerperDevTool, FileReadTool\n",
"\n",
"web_search_tool = WebsiteSearchTool()\n",
"seper_dev_tool = SeperDevTool()\n",
"serper_dev_tool = SerperDevTool()\n",
"file_read_tool = FileReadTool(\n",
" file_path=\"job_description_example.md\",\n",
" description=\"A tool to read the job description example file.\",\n",
")\n",
"\n",
"\n",
"class Agents:\n",
" def research_agent(self):\n",
" return Agent(\n",
" role=\"Research Analyst\",\n",
" goal=\"Analyze the company website and provided description to extract insights on culture, values, and specific needs.\",\n",
" tools=[web_search_tool, seper_dev_tool],\n",
" tools=[web_search_tool, serper_dev_tool],\n",
" backstory=\"Expert in analyzing company cultures and identifying key values and needs from various sources, including websites and brief descriptions.\",\n",
" verbose=True,\n",
" )\n",
Expand All @@ -53,7 +63,7 @@
" return Agent(\n",
" role=\"Job Description Writer\",\n",
" goal=\"Use insights from the Research Analyst to create a detailed, engaging, and enticing job posting.\",\n",
" tools=[web_search_tool, seper_dev_tool, file_read_tool],\n",
" tools=[web_search_tool, serper_dev_tool, file_read_tool],\n",
" backstory=\"Skilled in crafting compelling job descriptions that resonate with the company's values and attract the right candidates.\",\n",
" verbose=True,\n",
" )\n",
Expand All @@ -62,7 +72,7 @@
" return Agent(\n",
" role=\"Review and Editing Specialist\",\n",
" goal=\"Review the job posting for clarity, engagement, grammatical accuracy, and alignment with company values and refine it to ensure perfection.\",\n",
" tools=[web_search_tool, seper_dev_tool, file_read_tool],\n",
" tools=[web_search_tool, serper_dev_tool, file_read_tool],\n",
" backstory=\"A meticulous editor with an eye for detail, ensuring every piece of content is clear, engaging, and grammatically perfect.\",\n",
" verbose=True,\n",
" )"
Expand All @@ -77,6 +87,7 @@
"from textwrap import dedent\n",
"from crewai import Task\n",
"\n",
"\n",
"class Tasks:\n",
" def research_company_culture_task(self, agent, company_description, company_domain):\n",
" return Task(\n",
Expand Down Expand Up @@ -157,7 +168,6 @@
"outputs": [],
"source": [
"from crewai import Crew\n",
"\n",
"import agentops\n",
"\n",
"agentops.init(tags=[\"crew-job-posting-example\"])\n",
Expand Down Expand Up @@ -213,6 +223,11 @@
"\n",
"agentops.end_session(\"Success\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
}
],
"metadata": {
Expand Down
Loading

0 comments on commit a2f2f7f

Please sign in to comment.