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

NoSessionException when user does not init() #307

Merged
merged 11 commits into from
Jul 23, 2024
13 changes: 8 additions & 5 deletions agentops/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,14 @@
from .agent import track_agent
from .log_config import logger
from .session import Session
from .state import (
is_initialized,
) # sketch, Python's own docs say not to do this but this is the only way Python will accept it

# https://docs.python.org/3/faq/programming.html#how-do-i-share-global-variables-across-modules
# Stackoverflow (this might not be applicable bc you can't un-init): Don't use a from import unless the variable is intended to be a constant. from shared_stuff import a would create a new a variable initialized to whatever shared_stuff.a referred to at the time of the import, and this new a variable would not be affected by assignments to shared_stuff.a.
# https://stackoverflow.com/questions/15959534/visibility-of-global-variables-in-imported-modules


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

is_initialized = False


def noop(*args, **kwargs):
return
Expand Down Expand Up @@ -103,7 +109,6 @@ def init(
tags=tags, config=c.config, inherited_session_id=inherited_session_id
)

global is_initialized
is_initialized = True

return session
Expand Down Expand Up @@ -155,8 +160,6 @@ def start_session(

try:
sess_result = Client().start_session(tags, config, inherited_session_id)

global is_initialized
is_initialized = True

return sess_result
Expand Down
11 changes: 11 additions & 0 deletions agentops/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@
from uuid import uuid4
from agentops import Client
from inspect import isclass, isfunction
from .state import (
is_initialized,
) # sketch, Python's own docs say not to do this but this is the only way Python will accept it

# https://docs.python.org/3/faq/programming.html#how-do-i-share-global-variables-across-modules
# Stackoverflow (this might not be applicable bc you can't un-init): Don't use a from import unless the variable is intended to be a constant. from shared_stuff import a would create a new a variable initialized to whatever shared_stuff.a referred to at the time of the import, and this new a variable would not be affected by assignments to shared_stuff.a.
# https://stackoverflow.com/questions/15959534/visibility-of-global-variables-in-imported-modules


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

if not is_initialized:
return

self.agent_ops_agent_id = str(uuid4())

session = kwargs.get("session", None)
Expand Down
31 changes: 29 additions & 2 deletions agentops/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@
from .llm_tracker import LlmTracker
from termcolor import colored
from typing import Tuple
from .state import (
is_initialized,
)


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

session = self._safe_get_session()

# TODO: refactor. maybe move this
if session is None:
return

session.add_tags(tags=tags)

self._update_session(session)
Expand All @@ -193,6 +200,10 @@ def set_tags(self, tags: List[str]) -> None:

try:
session = self._safe_get_session()

if session is None:
return

session.set_tags(tags=tags)
except NoSessionException:
self._tags_for_future_session = tags
Expand All @@ -206,6 +217,8 @@ def record(self, event: Union[Event, ErrorEvent]) -> None:
"""

session = self._safe_get_session()
if session is None:
bboynton97 marked this conversation as resolved.
Show resolved Hide resolved
return
session.record(event)

def _record_event_sync(self, func, event_name, *args, **kwargs):
Expand Down Expand Up @@ -397,6 +410,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 +439,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 +472,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 @@ -563,7 +584,13 @@ def _safe_get_session(self) -> Session:
session = self._sessions[0]

if len(self._sessions) == 0:
raise NoSessionException("No session exists")
if is_initialized:
raise NoSessionException("No session exists")
# We're getting here for many paths bc we call _safe_get_session a lot
# we could wrap this whole thing in a "if is_initialized" but we would return None
# and then all the calling functions would have to do "if session is not None"
# i think the real fix is not even creating a Client() if is_initialized is False if possible
# all the calls to _safe_get_session come from Client()

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

Expand Down
1 change: 1 addition & 0 deletions agentops/state.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
is_initialized = False
33 changes: 23 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,10 +39,10 @@
"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",
Expand All @@ -44,7 +53,7 @@
" 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 +62,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 +71,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 Down Expand Up @@ -157,7 +166,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 +221,11 @@
"\n",
"agentops.end_session(\"Success\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
}
],
"metadata": {
Expand Down
Loading
Loading