diff --git a/agentops/llms/__init__.py b/agentops/llms/__init__.py index e3e6f7cf9..8c7ba5f4a 100644 --- a/agentops/llms/__init__.py +++ b/agentops/llms/__init__.py @@ -43,7 +43,6 @@ class LlmTracker: def __init__(self, client): self.client = client - self.completion = "" def override_api(self): """ diff --git a/agentops/llms/anthropic.py b/agentops/llms/anthropic.py index 322d21815..e0e78891f 100644 --- a/agentops/llms/anthropic.py +++ b/agentops/llms/anthropic.py @@ -31,27 +31,27 @@ def handle_response( from anthropic.resources import AsyncMessages from anthropic.types import Message - self.llm_event = LLMEvent(init_timestamp=init_timestamp, params=kwargs) + llm_event = LLMEvent(init_timestamp=init_timestamp, params=kwargs) if session is not None: - self.llm_event.session_id = session.session_id + llm_event.session_id = session.session_id def handle_stream_chunk(chunk: Message): try: # We take the first chunk and accumulate the deltas from all subsequent chunks to build one full chat completion if chunk.type == "message_start": - self.llm_event.returns = chunk - self.llm_event.agent_id = check_call_stack_for_agent_id() - self.llm_event.model = kwargs["model"] - self.llm_event.prompt = kwargs["messages"] - self.llm_event.prompt_tokens = chunk.message.usage.input_tokens - self.llm_event.completion = { + llm_event.returns = chunk + llm_event.agent_id = check_call_stack_for_agent_id() + llm_event.model = kwargs["model"] + llm_event.prompt = kwargs["messages"] + llm_event.prompt_tokens = chunk.message.usage.input_tokens + llm_event.completion = { "role": chunk.message.role, "content": "", # Always returned as [] in this instance type } elif chunk.type == "content_block_start": if chunk.content_block.type == "text": - self.llm_event.completion["content"] += chunk.content_block.text + llm_event.completion["content"] += chunk.content_block.text elif chunk.content_block.type == "tool_use": self.tool_id = chunk.content_block.id @@ -62,7 +62,7 @@ def handle_stream_chunk(chunk: Message): elif chunk.type == "content_block_delta": if chunk.delta.type == "text_delta": - self.llm_event.completion["content"] += chunk.delta.text + llm_event.completion["content"] += chunk.delta.text elif chunk.delta.type == "input_json_delta": self.tool_event[self.tool_id].logs[ @@ -73,15 +73,15 @@ def handle_stream_chunk(chunk: Message): pass elif chunk.type == "message_delta": - self.llm_event.completion_tokens = chunk.usage.output_tokens + llm_event.completion_tokens = chunk.usage.output_tokens elif chunk.type == "message_stop": - self.llm_event.end_timestamp = get_ISO_time() - self._safe_record(session, self.llm_event) + llm_event.end_timestamp = get_ISO_time() + self._safe_record(session, llm_event) except Exception as e: self._safe_record( - session, ErrorEvent(trigger_event=self.llm_event, exception=e) + session, ErrorEvent(trigger_event=llm_event, exception=e) ) kwargs_str = pprint.pformat(kwargs) @@ -124,23 +124,21 @@ async def async_generator(): # Handle object responses try: - self.llm_event.returns = response.model_dump() - self.llm_event.agent_id = check_call_stack_for_agent_id() - self.llm_event.prompt = kwargs["messages"] - self.llm_event.prompt_tokens = response.usage.input_tokens - self.llm_event.completion = { + llm_event.returns = response.model_dump() + llm_event.agent_id = check_call_stack_for_agent_id() + llm_event.prompt = kwargs["messages"] + llm_event.prompt_tokens = response.usage.input_tokens + llm_event.completion = { "role": "assistant", "content": response.content[0].text, } - self.llm_event.completion_tokens = response.usage.output_tokens - self.llm_event.model = response.model - self.llm_event.end_timestamp = get_ISO_time() + llm_event.completion_tokens = response.usage.output_tokens + llm_event.model = response.model + llm_event.end_timestamp = get_ISO_time() - self._safe_record(session, self.llm_event) + self._safe_record(session, llm_event) except Exception as e: - self._safe_record( - session, ErrorEvent(trigger_event=self.llm_event, exception=e) - ) + self._safe_record(session, ErrorEvent(trigger_event=llm_event, exception=e)) kwargs_str = pprint.pformat(kwargs) response = pprint.pformat(response) logger.warning( diff --git a/agentops/llms/cohere.py b/agentops/llms/cohere.py index 68658761e..d76c221db 100644 --- a/agentops/llms/cohere.py +++ b/agentops/llms/cohere.py @@ -52,9 +52,9 @@ def handle_response( # from cohere.types.chat import ChatGenerationChunk # NOTE: Cohere only returns one message and its role will be CHATBOT which we are coercing to "assistant" - self.llm_event = LLMEvent(init_timestamp=init_timestamp, params=kwargs) + llm_event = LLMEvent(init_timestamp=init_timestamp, params=kwargs) if session is not None: - self.llm_event.session_id = session.session_id + llm_event.session_id = session.session_id self.action_events = {} @@ -62,22 +62,22 @@ def handle_stream_chunk(chunk, session: Optional[Session] = None): # We take the first chunk and accumulate the deltas from all subsequent chunks to build one full chat completion if isinstance(chunk, StreamedChatResponse_StreamStart): - self.llm_event.returns = chunk - self.llm_event.agent_id = check_call_stack_for_agent_id() - self.llm_event.model = kwargs.get("model", "command-r-plus") - self.llm_event.prompt = kwargs["message"] - self.llm_event.completion = "" + llm_event.returns = chunk + llm_event.agent_id = check_call_stack_for_agent_id() + llm_event.model = kwargs.get("model", "command-r-plus") + llm_event.prompt = kwargs["message"] + llm_event.completion = "" return try: if isinstance(chunk, StreamedChatResponse_StreamEnd): # StreamedChatResponse_TextGeneration = LLMEvent - self.llm_event.completion = { + llm_event.completion = { "role": "assistant", "content": chunk.response.text, } - self.llm_event.end_timestamp = get_ISO_time() - self._safe_record(session, self.llm_event) + llm_event.end_timestamp = get_ISO_time() + self._safe_record(session, llm_event) # StreamedChatResponse_SearchResults = ActionEvent search_results = chunk.response.search_results @@ -115,7 +115,7 @@ def handle_stream_chunk(chunk, session: Optional[Session] = None): self._safe_record(session, action_event) elif isinstance(chunk, StreamedChatResponse_TextGeneration): - self.llm_event.completion += chunk.text + llm_event.completion += chunk.text elif isinstance(chunk, StreamedChatResponse_ToolCallsGeneration): pass elif isinstance(chunk, StreamedChatResponse_CitationGeneration): @@ -139,7 +139,7 @@ def handle_stream_chunk(chunk, session: Optional[Session] = None): except Exception as e: self._safe_record( - session, ErrorEvent(trigger_event=self.llm_event, exception=e) + session, ErrorEvent(trigger_event=llm_event, exception=e) ) kwargs_str = pprint.pformat(kwargs) @@ -175,15 +175,15 @@ def generator(): # Not enough to record StreamedChatResponse_ToolCallsGeneration because the tool may have not gotten called try: - self.llm_event.returns = response - self.llm_event.agent_id = check_call_stack_for_agent_id() - self.llm_event.prompt = [] + llm_event.returns = response + llm_event.agent_id = check_call_stack_for_agent_id() + llm_event.prompt = [] if response.chat_history: role_map = {"USER": "user", "CHATBOT": "assistant", "SYSTEM": "system"} for i in range(len(response.chat_history) - 1): message = response.chat_history[i] - self.llm_event.prompt.append( + llm_event.prompt.append( { "role": role_map.get(message.role, message.role), "content": message.message, @@ -191,19 +191,17 @@ def generator(): ) last_message = response.chat_history[-1] - self.llm_event.completion = { + llm_event.completion = { "role": role_map.get(last_message.role, last_message.role), "content": last_message.message, } - self.llm_event.prompt_tokens = response.meta.tokens.input_tokens - self.llm_event.completion_tokens = response.meta.tokens.output_tokens - self.llm_event.model = kwargs.get("model", "command-r-plus") + llm_event.prompt_tokens = response.meta.tokens.input_tokens + llm_event.completion_tokens = response.meta.tokens.output_tokens + llm_event.model = kwargs.get("model", "command-r-plus") - self._safe_record(session, self.llm_event) + self._safe_record(session, llm_event) except Exception as e: - self._safe_record( - session, ErrorEvent(trigger_event=self.llm_event, exception=e) - ) + self._safe_record(session, ErrorEvent(trigger_event=llm_event, exception=e)) kwargs_str = pprint.pformat(kwargs) response = pprint.pformat(response) logger.warning( diff --git a/agentops/llms/groq.py b/agentops/llms/groq.py index 7d5f68005..ca8696387 100644 --- a/agentops/llms/groq.py +++ b/agentops/llms/groq.py @@ -37,21 +37,21 @@ def handle_response( from groq.resources.chat import AsyncCompletions from groq.types.chat import ChatCompletionChunk - self.llm_event = LLMEvent(init_timestamp=init_timestamp, params=kwargs) + llm_event = LLMEvent(init_timestamp=init_timestamp, params=kwargs) if session is not None: - self.llm_event.session_id = session.session_id + llm_event.session_id = session.session_id def handle_stream_chunk(chunk: ChatCompletionChunk): # NOTE: prompt/completion usage not returned in response when streaming # We take the first ChatCompletionChunk and accumulate the deltas from all subsequent chunks to build one full chat completion - if self.llm_event.returns == None: - self.llm_event.returns = chunk + if llm_event.returns == None: + llm_event.returns = chunk try: - accumulated_delta = self.llm_event.returns.choices[0].delta - self.llm_event.agent_id = check_call_stack_for_agent_id() - self.llm_event.model = chunk.model - self.llm_event.prompt = kwargs["messages"] + accumulated_delta = llm_event.returns.choices[0].delta + llm_event.agent_id = check_call_stack_for_agent_id() + llm_event.model = chunk.model + llm_event.prompt = kwargs["messages"] # NOTE: We assume for completion only choices[0] is relevant choice = chunk.choices[0] @@ -70,21 +70,19 @@ def handle_stream_chunk(chunk: ChatCompletionChunk): if choice.finish_reason: # Streaming is done. Record LLMEvent - self.llm_event.returns.choices[0].finish_reason = ( - choice.finish_reason - ) - self.llm_event.completion = { + llm_event.returns.choices[0].finish_reason = choice.finish_reason + llm_event.completion = { "role": accumulated_delta.role, "content": accumulated_delta.content, "function_call": accumulated_delta.function_call, "tool_calls": accumulated_delta.tool_calls, } - self.llm_event.end_timestamp = get_ISO_time() + llm_event.end_timestamp = get_ISO_time() - self._safe_record(session, self.llm_event) + self._safe_record(session, llm_event) except Exception as e: self._safe_record( - session, ErrorEvent(trigger_event=self.llm_event, exception=e) + session, ErrorEvent(trigger_event=llm_event, exception=e) ) kwargs_str = pprint.pformat(kwargs) @@ -127,19 +125,17 @@ async def async_generator(): # v1.0.0+ responses are objects try: - self.llm_event.returns = response.model_dump() - self.llm_event.agent_id = check_call_stack_for_agent_id() - self.llm_event.prompt = kwargs["messages"] - self.llm_event.prompt_tokens = response.usage.prompt_tokens - self.llm_event.completion = response.choices[0].message.model_dump() - self.llm_event.completion_tokens = response.usage.completion_tokens - self.llm_event.model = response.model - - self._safe_record(session, self.llm_event) + llm_event.returns = response.model_dump() + llm_event.agent_id = check_call_stack_for_agent_id() + llm_event.prompt = kwargs["messages"] + llm_event.prompt_tokens = response.usage.prompt_tokens + llm_event.completion = response.choices[0].message.model_dump() + llm_event.completion_tokens = response.usage.completion_tokens + llm_event.model = response.model + + self._safe_record(session, llm_event) except Exception as e: - self._safe_record( - session, ErrorEvent(trigger_event=self.llm_event, exception=e) - ) + self._safe_record(session, ErrorEvent(trigger_event=llm_event, exception=e)) kwargs_str = pprint.pformat(kwargs) response = pprint.pformat(response) diff --git a/agentops/llms/litellm.py b/agentops/llms/litellm.py index 053c42516..30b4c25a2 100644 --- a/agentops/llms/litellm.py +++ b/agentops/llms/litellm.py @@ -49,21 +49,21 @@ def handle_response( from openai.types.chat import ChatCompletionChunk from litellm.utils import CustomStreamWrapper - self.llm_event = LLMEvent(init_timestamp=init_timestamp, params=kwargs) + llm_event = LLMEvent(init_timestamp=init_timestamp, params=kwargs) if session is not None: - self.llm_event.session_id = session.session_id + llm_event.session_id = session.session_id def handle_stream_chunk(chunk: ChatCompletionChunk): # NOTE: prompt/completion usage not returned in response when streaming # We take the first ChatCompletionChunk and accumulate the deltas from all subsequent chunks to build one full chat completion - if self.llm_event.returns == None: - self.llm_event.returns = chunk + if llm_event.returns == None: + llm_event.returns = chunk try: - accumulated_delta = self.llm_event.returns.choices[0].delta - self.llm_event.agent_id = check_call_stack_for_agent_id() - self.llm_event.model = chunk.model - self.llm_event.prompt = kwargs["messages"] + accumulated_delta = llm_event.returns.choices[0].delta + llm_event.agent_id = check_call_stack_for_agent_id() + llm_event.model = chunk.model + llm_event.prompt = kwargs["messages"] # NOTE: We assume for completion only choices[0] is relevant choice = chunk.choices[0] @@ -82,21 +82,19 @@ def handle_stream_chunk(chunk: ChatCompletionChunk): if choice.finish_reason: # Streaming is done. Record LLMEvent - self.llm_event.returns.choices[0].finish_reason = ( - choice.finish_reason - ) - self.llm_event.completion = { + llm_event.returns.choices[0].finish_reason = choice.finish_reason + llm_event.completion = { "role": accumulated_delta.role, "content": accumulated_delta.content, "function_call": accumulated_delta.function_call, "tool_calls": accumulated_delta.tool_calls, } - self.llm_event.end_timestamp = get_ISO_time() + llm_event.end_timestamp = get_ISO_time() - self._safe_record(session, self.llm_event) + self._safe_record(session, llm_event) except Exception as e: self._safe_record( - session, ErrorEvent(trigger_event=self.llm_event, exception=e) + session, ErrorEvent(trigger_event=llm_event, exception=e) ) kwargs_str = pprint.pformat(kwargs) @@ -149,19 +147,17 @@ async def async_generator(): # v1.0.0+ responses are objects try: - self.llm_event.returns = response - self.llm_event.agent_id = check_call_stack_for_agent_id() - self.llm_event.prompt = kwargs["messages"] - self.llm_event.prompt_tokens = response.usage.prompt_tokens - self.llm_event.completion = response.choices[0].message.model_dump() - self.llm_event.completion_tokens = response.usage.completion_tokens - self.llm_event.model = response.model - - self._safe_record(session, self.llm_event) + llm_event.returns = response + llm_event.agent_id = check_call_stack_for_agent_id() + llm_event.prompt = kwargs["messages"] + llm_event.prompt_tokens = response.usage.prompt_tokens + llm_event.completion = response.choices[0].message.model_dump() + llm_event.completion_tokens = response.usage.completion_tokens + llm_event.model = response.model + + self._safe_record(session, llm_event) except Exception as e: - self._safe_record( - session, ErrorEvent(trigger_event=self.llm_event, exception=e) - ) + self._safe_record(session, ErrorEvent(trigger_event=llm_event, exception=e)) kwargs_str = pprint.pformat(kwargs) response = pprint.pformat(response) diff --git a/agentops/llms/ollama.py b/agentops/llms/ollama.py index bdcb21909..d17aba9ad 100644 --- a/agentops/llms/ollama.py +++ b/agentops/llms/ollama.py @@ -19,25 +19,25 @@ class OllamaProvider(InstrumentedProvider): def handle_response( self, response, kwargs, init_timestamp, session: Optional[Session] = None ) -> dict: - self.llm_event = LLMEvent(init_timestamp=init_timestamp, params=kwargs) + llm_event = LLMEvent(init_timestamp=init_timestamp, params=kwargs) def handle_stream_chunk(chunk: dict): message = chunk.get("message", {"role": None, "content": ""}) if chunk.get("done"): - self.llm_event.completion["content"] += message.get("content") - self.llm_event.end_timestamp = get_ISO_time() - self.llm_event.model = f'ollama/{chunk.get("model")}' - self.llm_event.returns = chunk - self.llm_event.returns["message"] = self.llm_event.completion - self.llm_event.prompt = kwargs["messages"] - self.llm_event.agent_id = check_call_stack_for_agent_id() - self.client.record(self.llm_event) - - if self.llm_event.completion is None: - self.llm_event.completion = message + llm_event.completion["content"] += message.get("content") + llm_event.end_timestamp = get_ISO_time() + llm_event.model = f'ollama/{chunk.get("model")}' + llm_event.returns = chunk + llm_event.returns["message"] = llm_event.completion + llm_event.prompt = kwargs["messages"] + llm_event.agent_id = check_call_stack_for_agent_id() + self.client.record(llm_event) + + if llm_event.completion is None: + llm_event.completion = message else: - self.llm_event.completion["content"] += message.get("content") + llm_event.completion["content"] += message.get("content") if inspect.isgenerator(response): @@ -48,15 +48,15 @@ def generator(): return generator() - self.llm_event.end_timestamp = get_ISO_time() + llm_event.end_timestamp = get_ISO_time() - self.llm_event.model = f'ollama/{response["model"]}' - self.llm_event.returns = response - self.llm_event.agent_id = check_call_stack_for_agent_id() - self.llm_event.prompt = kwargs["messages"] - self.llm_event.completion = response["message"] + llm_event.model = f'ollama/{response["model"]}' + llm_event.returns = response + llm_event.agent_id = check_call_stack_for_agent_id() + llm_event.prompt = kwargs["messages"] + llm_event.completion = response["message"] - self._safe_record(session, self.llm_event) + self._safe_record(session, llm_event) return response def override(self): diff --git a/agentops/llms/openai.py b/agentops/llms/openai.py index 0fd31a1d2..c99523d72 100644 --- a/agentops/llms/openai.py +++ b/agentops/llms/openai.py @@ -30,21 +30,21 @@ def handle_response( from openai.resources import AsyncCompletions from openai.types.chat import ChatCompletionChunk - self.llm_event = LLMEvent(init_timestamp=init_timestamp, params=kwargs) + llm_event = LLMEvent(init_timestamp=init_timestamp, params=kwargs) if session is not None: - self.llm_event.session_id = session.session_id + llm_event.session_id = session.session_id def handle_stream_chunk(chunk: ChatCompletionChunk): # NOTE: prompt/completion usage not returned in response when streaming # We take the first ChatCompletionChunk and accumulate the deltas from all subsequent chunks to build one full chat completion - if self.llm_event.returns == None: - self.llm_event.returns = chunk + if llm_event.returns == None: + llm_event.returns = chunk try: - accumulated_delta = self.llm_event.returns.choices[0].delta - self.llm_event.agent_id = check_call_stack_for_agent_id() - self.llm_event.model = chunk.model - self.llm_event.prompt = kwargs["messages"] + accumulated_delta = llm_event.returns.choices[0].delta + llm_event.agent_id = check_call_stack_for_agent_id() + llm_event.model = chunk.model + llm_event.prompt = kwargs["messages"] # NOTE: We assume for completion only choices[0] is relevant choice = chunk.choices[0] @@ -63,21 +63,19 @@ def handle_stream_chunk(chunk: ChatCompletionChunk): if choice.finish_reason: # Streaming is done. Record LLMEvent - self.llm_event.returns.choices[0].finish_reason = ( - choice.finish_reason - ) - self.llm_event.completion = { + llm_event.returns.choices[0].finish_reason = choice.finish_reason + llm_event.completion = { "role": accumulated_delta.role, "content": accumulated_delta.content, "function_call": accumulated_delta.function_call, "tool_calls": accumulated_delta.tool_calls, } - self.llm_event.end_timestamp = get_ISO_time() + llm_event.end_timestamp = get_ISO_time() - self._safe_record(session, self.llm_event) + self._safe_record(session, llm_event) except Exception as e: self._safe_record( - session, ErrorEvent(trigger_event=self.llm_event, exception=e) + session, ErrorEvent(trigger_event=llm_event, exception=e) ) kwargs_str = pprint.pformat(kwargs) @@ -120,19 +118,17 @@ async def async_generator(): # v1.0.0+ responses are objects try: - self.llm_event.returns = response - self.llm_event.agent_id = check_call_stack_for_agent_id() - self.llm_event.prompt = kwargs["messages"] - self.llm_event.prompt_tokens = response.usage.prompt_tokens - self.llm_event.completion = response.choices[0].message.model_dump() - self.llm_event.completion_tokens = response.usage.completion_tokens - self.llm_event.model = response.model - - self._safe_record(session, self.llm_event) + llm_event.returns = response + llm_event.agent_id = check_call_stack_for_agent_id() + llm_event.prompt = kwargs["messages"] + llm_event.prompt_tokens = response.usage.prompt_tokens + llm_event.completion = response.choices[0].message.model_dump() + llm_event.completion_tokens = response.usage.completion_tokens + llm_event.model = response.model + + self._safe_record(session, llm_event) except Exception as e: - self._safe_record( - session, ErrorEvent(trigger_event=self.llm_event, exception=e) - ) + self._safe_record(session, ErrorEvent(trigger_event=llm_event, exception=e)) kwargs_str = pprint.pformat(kwargs) response = pprint.pformat(response) diff --git a/docs/snippets/add-env-tooltip.mdx b/docs/snippets/add-env-tooltip.mdx index 240a4019b..a3b1c6a0d 100644 --- a/docs/snippets/add-env-tooltip.mdx +++ b/docs/snippets/add-env-tooltip.mdx @@ -1,3 +1,3 @@ - Set your API Key as an `.env` variable for easy access. + Set your API key as an `.env` variable for easy access. \ No newline at end of file diff --git a/docs/snippets/github-stars.mdx b/docs/snippets/github-stars.mdx index e31a312c6..1e73b3ccd 100644 --- a/docs/snippets/github-stars.mdx +++ b/docs/snippets/github-stars.mdx @@ -1 +1 @@ -Look useful? [Star us on Github](https://github.com/AgentOps-AI/agentops)! (you may be our 2,000th 😊) \ No newline at end of file +Look useful? [Star us on GitHub](https://github.com/AgentOps-AI/agentops)! (you may be our 2,000th 😊) \ No newline at end of file diff --git a/docs/v0/recording-events.mdx b/docs/v0/recording-events.mdx index c831a5a2a..ff5eccbe6 100644 --- a/docs/v0/recording-events.mdx +++ b/docs/v0/recording-events.mdx @@ -18,7 +18,7 @@ def sample_function(...): ... ``` -The the decorator will record the function's parameters, returns, and the time duration. We suggest using this on functions that take a long time and contain nested functions. For example, if you decorate a function that makes several openai calls, then each openai call will show in the replay graph as a child of the decorated function. +The decorator will record the function's parameters, returns, and the time duration. We suggest using this on functions that take a long time and contain nested functions. For example, if you decorate a function that makes several openai calls, then each openai call will show in the replay graph as a child of the decorated function. record_action: @@ -36,7 +36,7 @@ ao_client.record(Event("event_type1")) ``` In AgentOps, each session is associated with a number of "Events". Events have -must have an "event_type" which is any abitrary string of your choice. It might be something +must have an "event_type" which is any arbitrary string of your choice. It might be something like "OpenAI Call". Events can also have other information such as the parameters of the operation, the returned data, alongside tags, etc. diff --git a/docs/v1/concepts/decorators.mdx b/docs/v1/concepts/decorators.mdx index 49425e7a5..01f372e30 100644 --- a/docs/v1/concepts/decorators.mdx +++ b/docs/v1/concepts/decorators.mdx @@ -17,13 +17,13 @@ If your implementation uses Classes to denote Agents, this decorator enables aut Learn more about tracking agents [here](/v1/usage/tracking-agents). ## `@record_action()` -Sometimes your agent system will use functions that are important to track as [`Actions`](/v1/concepts/events/#actionevent). +Sometimes, your agent system uses functions that are important to track as [`Actions`](/v1/concepts/events/#actionevent). Adding this decorator above any function will allow every instance of that function call to be tracked and displayed in your [Session](v1/concepts/sessions) Drill-Down on the dashboard. ## `@record_tool()` -Some functions are used as Tools. If you're not using an agent framework that records [`ToolEvents`](/v1/concepts/events/#toolevent) with AgentOps automatically, this decorator will record `ToolEvents` when the function is called. +Some functions are used as Tools. If you are not using an agent framework that records [`ToolEvents`](/v1/concepts/events/#toolevent) with AgentOps automatically, this decorator will record `ToolEvents` when the function is called. Adding this decorator above any function will allow every instance of that function call to be tracked and displayed in your [Session](v1/concepts/sessions) Drill-Down on the dashboard. diff --git a/docs/v1/concepts/sessions.mdx b/docs/v1/concepts/sessions.mdx index 25f95f88f..1da20fb34 100644 --- a/docs/v1/concepts/sessions.mdx +++ b/docs/v1/concepts/sessions.mdx @@ -58,7 +58,7 @@ Calling `agentops.init(auto_start_session=False)` will initialize the AgentOps S To start a session later, call `agentops.start_session()` [(reference)](/v1/usage/sdk-reference/#start-session) -Both `agentops.init()` and `agentops.start_session()` works as a factory pattern and returns a `Session` object. The above methods can all be called on this session object. +Both `agentops.init()` and `agentops.start_session()` work as a factory pattern and return a `Session` object. The above methods can all be called on this session object. ## Ending a Session If a process ends without any call to agentops, it will show in the dashboard as `Indeterminate`. @@ -71,7 +71,7 @@ with an existing session_id. `agentops.init(inherited_session_id=)` `agentops.start_session(inherited_session_id=)` -You can retrieve the current session_id by assigning the returned value from `init()` or `start_session()` +You can retrieve the current `session_id` by assigning the returned value from `init()` or `start_session()` ```python python @@ -90,8 +90,7 @@ Both processes will now contribute data to the same session. ## The AgentOps SDK Client _More info for the curious_ -Under the hood, `agentops.init()` sets up a `Client` object with various configuration options like your API key, worker thread options -for when to send out batches of events, etc. Whenever you start a new session, these configuration options will automatically +Under the hood, `agentops.init()` creates a `Client` object with various configuration options. Whenever you start a new session, these configuration options will automatically be applied. You can also apply different configuration options when you start a new session by passing in a [Configuration](/v1/usage/sdk-reference/#configuration) object. diff --git a/docs/v1/examples/langchain.mdx b/docs/v1/examples/langchain.mdx index bd121bb0e..dd59d4bd2 100644 --- a/docs/v1/examples/langchain.mdx +++ b/docs/v1/examples/langchain.mdx @@ -1,6 +1,6 @@ --- -title: 'Langchain Example' -description: 'Using the Langchain Callback Handler' +title: 'LangChain Example' +description: 'Using the LangChain Callback Handler' mode: "wide" --- _View Notebook on Github_ diff --git a/docs/v1/integrations/cohere.mdx b/docs/v1/integrations/cohere.mdx index f80cad05a..35771a8af 100644 --- a/docs/v1/integrations/cohere.mdx +++ b/docs/v1/integrations/cohere.mdx @@ -7,7 +7,7 @@ import CodeTooltip from '/snippets/add-code-tooltip.mdx' import EnvTooltip from '/snippets/add-env-tooltip.mdx' -This is a living integration. Should you need any added functionality message us on [Discord](https://discord.gg/UgJyyxx7uc)! +This is a living integration. Should you need any added functionality, message us on [Discord](https://discord.gg/UgJyyxx7uc)! @@ -41,7 +41,7 @@ This is a living integration. Should you need any added functionality message us - Requires cohere>=5.4.0 + Requires `cohere>=5.4.0` @@ -54,7 +54,7 @@ This is a living integration. Should you need any added functionality message us - Execute your program and visit [app.agentops.ai/drilldown](https://app.agentops.ai/drilldown) to observe your Agents! 🕵️ + Execute your program and visit [app.agentops.ai/drilldown](https://app.agentops.ai/drilldown) to observe your Agent! 🕵️ After your run, AgentOps prints a clickable url to console linking directly to your session in the Dashboard diff --git a/docs/v1/integrations/langchain.mdx b/docs/v1/integrations/langchain.mdx index 575091f3b..1b3106917 100644 --- a/docs/v1/integrations/langchain.mdx +++ b/docs/v1/integrations/langchain.mdx @@ -1,16 +1,16 @@ --- -title: Langchain -description: "AgentOps provides first class support for Lanchain applications" +title: LangChain +description: "AgentOps provides first class support for LangChain applications" --- import EnvTooltip from '/snippets/add-env-tooltip.mdx' -AgentOps works seamlessly with applications built using Langchain. +AgentOps works seamlessly with applications built using LangChain. -## Adding AgentOps to Langchain applications +## Adding AgentOps to LangChain applications - + ```bash pip pip install agentops @@ -24,7 +24,7 @@ AgentOps works seamlessly with applications built using Langchain. [Give us a star](https://github.com/AgentOps-AI/agentops) on GitHub while you're at it (you may be our 2,000th 😊) - Import the following Langchain and AgentOps dependencies + Import the following LangChain and AgentOps dependencies ```python python import os @@ -34,15 +34,15 @@ AgentOps works seamlessly with applications built using Langchain. ``` - + - Note that you don't need to set up a separate agentops.init() call, as the Langchain callback handler will automatically initialize the AgentOps client for you. + Note that you don't need to set up a separate agentops.init() call, as the LangChain callback handler will automatically initialize the AgentOps client for you. - Set up your Langchain agent with the AgentOps callback handler and AgentOps will automatically record your Langchain sessions. + Set up your LangChain agent with the AgentOps callback handler, and AgentOps will automatically record your LangChain sessions. ```python python - handler = LangchainCallbackHandler(api_key=AGENTOPS_API_KEY, tags=['Langchain Example']) + handler = LangchainCallbackHandler(api_key=AGENTOPS_API_KEY, tags=['LangChain Example']) @@ -70,9 +70,9 @@ AgentOps works seamlessly with applications built using Langchain. - Execute your program and visit [app.agentops.ai/drilldown](https://app.agentops.ai/drilldown) to observe your Langchain Agent! 🕵️ + Execute your program and visit [app.agentops.ai/drilldown](https://app.agentops.ai/drilldown) to observe your LangChain Agent! 🕵️ - After your run, AgentOps prints a clickable url to console linking directly to your session in the Dashboard + After your run, AgentOps prints a clickable URL to the console linking directly to your session in the Dashboard
{/* Intentionally blank div for newline */} @@ -90,7 +90,7 @@ AgentOps works seamlessly with applications built using Langchain. from langchain.agents import initialize_agent, AgentType from agentops.langchain_callback_handler import LangchainCallbackHandler - handler = LangchainCallbackHandler(api_key=AGENTOPS_API_KEY, tags=['Langchain Example']) + handler = LangchainCallbackHandler(api_key=AGENTOPS_API_KEY, tags=['LangChain Example']) llm = ChatOpenAI(openai_api_key=OPENAI_API_KEY, callbacks=[handler], diff --git a/docs/v1/integrations/litellm.mdx b/docs/v1/integrations/litellm.mdx index e82916c55..ed851b84c 100644 --- a/docs/v1/integrations/litellm.mdx +++ b/docs/v1/integrations/litellm.mdx @@ -1,27 +1,27 @@ --- title: LiteLLM description: "Call the latest models using the OpenAI format including: -Llama, Mistral, Claude, Gemini, Gemma, Dall-E, Whisper" +Llama, Mistral, Claude, Gemini, Gemma, DALL-E, Whisper" --- ## LiteLLM From [LiteLLM's docs](https://docs.litellm.ai/docs/): -Call 100+ LLMs using the same Input/Output Format +Call 400+ LLMs using the same input/output Format - Translate inputs to provider's `completion`, `embedding`, and `image_generation` endpoints -- Consistent output. Text responses will always be available at `['choices'][0]['message']['content']` +- Consistent output. Text responses will always be available at `['choices'][0]['message']['content']`. - Retry/fallback logic across multiple deployments (e.g. Azure/OpenAI) - Track spend & set budgets per project -LiteLLM also supports many [providers](https://docs.litellm.ai/docs/providers) +LiteLLM also supports many [providers](https://docs.litellm.ai/docs/providers). ## Using AgentOps with LiteLLM -### Requires litellm>=1.3.1 +### Requires `litellm>=1.3.1` -AgentOps requires you to make a minor adjustment to how you call LiteLLM. +AgentOps requires a minor adjustment to how you call LiteLLM. ```python python # Do not use LiteLLM like this diff --git a/docs/v1/introduction.mdx b/docs/v1/introduction.mdx index e7992adce..db5367b43 100644 --- a/docs/v1/introduction.mdx +++ b/docs/v1/introduction.mdx @@ -32,7 +32,7 @@ And we do it all in just two lines of code... ## The AgentOps Dashboard -With just two lines of code, you can free yourself from the chains of the terminal and instead visualize your agents' behavior +With just two lines of code, you can free yourself from the chains of the terminal and, instead, visualize your agents' behavior in your AgentOps Dashboard. After setting up AgentOps, each execution of your program is recorded as a session and the above data is automatically recorded for you. @@ -53,7 +53,7 @@ Find any past sessions from your Session Drawer. Most powerful of all is the Session Waterfall. On the left, a time visualization of all your LLM calls, Action events, Tool calls, and Errors. -On the right, specific details about the event you've selected on the waterfall. For instance the exact prompt and completion for a given LLM call. +On the right, specific details about the event you've selected on the waterfall. For instance the exact prompt and completion for a given LLM call. Most of which has been automatically recorded for you. diff --git a/docs/v1/quickstart.mdx b/docs/v1/quickstart.mdx index 3bc5e2428..5df0c48c5 100644 --- a/docs/v1/quickstart.mdx +++ b/docs/v1/quickstart.mdx @@ -32,7 +32,7 @@ import EnvTooltip from '/snippets/add-env-tooltip.mdx' Execute your program and visit [app.agentops.ai/drilldown](https://app.agentops.ai/drilldown) to observe your Agent! 🕵️ - After your run, AgentOps prints a clickable url to console linking directly to your session in the Dashboard + After your run, AgentOps prints a clickable URL to console linking directly to your session in the Dashboard
{/* Intentionally blank div for newline */} @@ -52,7 +52,7 @@ import EnvTooltip from '/snippets/add-env-tooltip.mdx' will see these function calls alongside your LLM calls from instantiating the AgentOps client. ```python python # (record specific functions) - @agentops.record_action('sample function being record') + @agentops.record_action('sample function being recorded') def sample_function(...): ... ``` @@ -70,7 +70,7 @@ import EnvTooltip from '/snippets/add-env-tooltip.mdx' - Finally, you should end your session by calling `.end_session()` with whether your session + Finally, you should end your session by calling `.end_session()` indicating whether your session was successful or not `(Success|Fail)`. We suggest setting session state depending on how your agent exits or whether your agent succeeded or not. You can also specify a end state reason, such as user interrupted, ran to completion, or unhandled exception. diff --git a/docs/v1/usage/langchain-callback-handler.mdx b/docs/v1/usage/langchain-callback-handler.mdx index 9b36644d2..8337a2871 100644 --- a/docs/v1/usage/langchain-callback-handler.mdx +++ b/docs/v1/usage/langchain-callback-handler.mdx @@ -1,12 +1,12 @@ --- -title: 'Langchain Callback Handler' -description: 'How to use AgentOps with Langchain' +title: 'LangChain Callback Handler' +description: 'How to use AgentOps with LangChain' --- -By default, AgentOps is compatible with agents using Langchain with our LLM Instrumentor as long as they're using +By default, AgentOps is compatible with agents using LangChain with our LLM Instrumentor as long as they're using supported models. -As an alternative to instrumenting, the Langchain Callback Handler is available. +As an alternative to instrumenting, the LangChain Callback Handler is available. ## Constructor @@ -41,7 +41,7 @@ properly include `instrument_llm_calls=False`. In this case, call ### Implement Callback Handler -Initialize the handler with its constructor and pass it into the callbacks array from Langchain. +Initialize the handler with its constructor and pass it into the callbacks array from LangChain. ```python from agentops.langchain_callback_handler import LangchainCallbackHandler ChatOpenAI(callbacks=[LangchainCallbackHandler()]) @@ -63,9 +63,9 @@ response = chain.invoke({"animal": "bears"}) ## Why use the handler? -If your project uses Langchain for Agents, Events and Tools, it may be easier to use the callback Handler for observability. +If your project uses LangChain for Agents, Events and Tools, it may be easier to use the callback Handler for observability. -If your project uses models with Langchain that are not yet supported by AgentOps, they can be supported by the Handler. +If your project uses models with LangChain that are not yet supported by AgentOps, they can be supported by the Handler. diff --git a/docs/v1/usage/multiple-sessions.mdx b/docs/v1/usage/multiple-sessions.mdx index 38c29aac6..f84c18a6b 100644 --- a/docs/v1/usage/multiple-sessions.mdx +++ b/docs/v1/usage/multiple-sessions.mdx @@ -159,7 +159,7 @@ session.record(Event(...)) # Assigning LLM Calls When we have multiple active sessions, it's impossible for AgentOps to know which session a particular LLM call belongs to without a little help. -To track an LLM Call, use [`session.patch()`](/v1/concepts/sessions#patch) +To track an LLM call, use [`session.patch()`](/v1/concepts/sessions#patch) ```python import agentops diff --git a/docs/v1/usage/recording-events.mdx b/docs/v1/usage/recording-events.mdx index f7fec071a..361188ec4 100644 --- a/docs/v1/usage/recording-events.mdx +++ b/docs/v1/usage/recording-events.mdx @@ -16,12 +16,12 @@ and record an event for your function. ```python python from agentops import record_action -@record_action('sample function being record') +@record_action('sample function being recorded') def sample_function(...): ... ``` -The decorator will record the function's parameters, returns, and the time duration. We suggest using this on functions that take a long time and contain nested functions. For example, if you decorate a function that makes several openai calls, then each openai call will show in the replay graph as a child of the decorated function. +The decorator will record the function's parameters, return values, and the time duration. We suggest using this on functions that take a long time and contain nested functions. For example, if you decorate a function that makes several OpenAI calls, then each OpenAI call will show in the replay graph as a child of the decorated function. ## `@record_tool` Decorator @@ -37,12 +37,12 @@ def sample_tool(...): ... ``` -The decorator will record the function's parameters, returns, and the time duration. We suggest using this on functions that take a long time and contain nested functions. For example, if you decorate a function that makes several openai calls, then each openai call will show in the replay graph as a child of the decorated function. +The decorator will record the function's parameters, returns, and the time duration. We suggest using this on functions that take a long time and contain nested functions. For example, if you decorate a function that makes several OpenAI calls, then each OpenAI call will show in the replay graph as a child of the decorated function. ## `record()` Method -From this point, simply call the .record() method in the AgentOps client: +From this point, simply call the `.record()` method in the AgentOps client: Record any child of the [Event type](/v1/concepts/events) or ErrorEvent. diff --git a/docs/v1/usage/sdk-reference.mdx b/docs/v1/usage/sdk-reference.mdx index 647ba101c..876aee697 100644 --- a/docs/v1/usage/sdk-reference.mdx +++ b/docs/v1/usage/sdk-reference.mdx @@ -51,7 +51,7 @@ Start a new [Session](/v1/concepts/sessions) for recording events. ### `end_session()` -End the current session with the AgentOps service. +Ends the current session with the AgentOps service. **Parameters**: @@ -113,8 +113,8 @@ Set the parent API key which has visibility over projects it is a parent of. ### `stop_instrumenting()` -Stop instrumenting LLM calls. This is typically used by agent frameworks (i.e. [CrewAI](/v1/integrations/crewai), -[autogen](/v1/integrations/autogen)) to stop using the AgentOps auto instrumentation of LLM libraries like OpenAI. This +Stops instrumenting LLM calls. This is typically used by agent frameworks (i.e., [CrewAI](/v1/integrations/crewai) and +[autogen](/v1/integrations/autogen)) to stop using AgentOps' auto-instrumentation of LLM libraries such as OpenAI. This allows these frameworks to use their own instrumenting or callback handler. @@ -151,7 +151,7 @@ Stores the configuration settings for AgentOps clients. [Reference](/v1/usage/langchain-callback-handler) This callback handler is intended to be used as an option in place of AgentOps auto-instrumenting. This is only useful -when using Langchain as your LLM calling library. +when using LangChain as your LLM calling library. diff --git a/docs/v1/usage/tracking-llm-calls.mdx b/docs/v1/usage/tracking-llm-calls.mdx index 9cb93ab8b..b448fd18f 100644 --- a/docs/v1/usage/tracking-llm-calls.mdx +++ b/docs/v1/usage/tracking-llm-calls.mdx @@ -14,7 +14,7 @@ Try these steps: 1. Make sure you have the latest version of the AgentOps SDK installed. We are constantly updating it to support new LLM libraries and releases. 2. Make sure you are calling `agentops.init()` *after* importing the LLM module but *before* you are calling the LLM method. 3. Make sure the `instrument_llm_calls` parameter of `agentops.init()` is set to `True` (default). -4. Make sure if you have more than one concurrent session, to patch the LLM call as described [here](/v1/usage/multiple-sssions). +4. Make sure if you have more than one concurrent session, you patch the LLM call as described [here](/v1/usage/multiple-sssions). Still not working? Please let us know! You can find us on [Discord](https://discord.gg/DR2abmETjZ), [GitHub](https://github.com/AgentOps-AI/agentops), @@ -32,7 +32,7 @@ To get started, just follow the quick start guide. To stop tracking LLM calls after running `agentops.init()`, you can call `agentops.stop_instrumenting()`. -This function reverts the changes made to your LLM Provider's module, removing AgentOps instrumentation. +This function reverts the changes made to your LLM provider's module, removing AgentOps instrumentation. _Special consideration for Cohere: Calling `stop_instrumenting()` has no effect on previously instantiated Cohere clients. You must create a new Cohere client after calling this function._ diff --git a/pyproject.toml b/pyproject.toml index 9f3661570..f3d7b9fa4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "agentops" -version = "0.3.10" +version = "0.3.11" authors = [ { name="Alex Reibman", email="areibman@gmail.com" }, { name="Shawn Qiu", email="siyangqiu@gmail.com" },