diff --git a/src/examples/crewai_example/simple_agent/agents.py b/src/examples/crewai_example/simple_agent/agents.py index 8557f82d..5d761acd 100644 --- a/src/examples/crewai_example/simple_agent/agents.py +++ b/src/examples/crewai_example/simple_agent/agents.py @@ -28,5 +28,5 @@ def create_poet_agent(self): goal="""Create a poem that captures the essence of a given theme or emotion""", allow_delegation=False, verbose=True, - llm=self.ollama, + llm=self.open_ai, ) diff --git a/src/examples/crewai_example/simple_agent/main.py b/src/examples/crewai_example/simple_agent/main.py index 61230bef..2d694d6e 100644 --- a/src/examples/crewai_example/simple_agent/main.py +++ b/src/examples/crewai_example/simple_agent/main.py @@ -1,14 +1,11 @@ from crewai import Crew -from textwrap import dedent from .agents import PoetryAgents from .tasks import PoetryTasks from langtrace_python_sdk import langtrace from dotenv import load_dotenv -import agentops load_dotenv() -agentops.init() -langtrace.init(write_spans_to_console=False, batch=False) +langtrace.init() class PoetryCrew: @@ -29,18 +26,11 @@ def run(self): # This is the main function that you will use to run your custom crew. +# You can run this file using `python -m src.examples.crewai_example.simple_agent.main` if __name__ == "__main__": print("## Welcome to Poetry Crew") print("-------------------------------") - topic = input( - dedent( - """ - What topic do you want to write a poem on? - """ - ) - ) - - poetry_crew = PoetryCrew(topic=topic) + poetry_crew = PoetryCrew(topic="cold") result = poetry_crew.run() print("\n\n########################") print("## Here is you poem") diff --git a/src/examples/crewai_example/simple_agent/tasks.py b/src/examples/crewai_example/simple_agent/tasks.py index b44952c1..f91c2ff4 100644 --- a/src/examples/crewai_example/simple_agent/tasks.py +++ b/src/examples/crewai_example/simple_agent/tasks.py @@ -18,4 +18,5 @@ def create_poem(self, agent, topic): ), expected_output="A creative and expressive poem that captures the essence of the given topic.", agent=agent, + output_file="poem.txt", ) diff --git a/src/examples/crewai_example/trip_planner/main.py b/src/examples/crewai_example/trip_planner/main.py index d8b78b1b..00d08647 100644 --- a/src/examples/crewai_example/trip_planner/main.py +++ b/src/examples/crewai_example/trip_planner/main.py @@ -1,5 +1,4 @@ from crewai import Crew -from textwrap import dedent from .agents import TravelAgents from .tasks import TravelTasks from langtrace_python_sdk import langtrace @@ -59,36 +58,8 @@ def run(self): if __name__ == "__main__": print("## Welcome to Trip Planner Crew") print("-------------------------------") - origin = input( - dedent( - """ - From where will you be traveling from? - """ - ) - ) - cities = input( - dedent( - """ - What are the cities options you are interested in visiting? - """ - ) - ) - date_range = input( - dedent( - """ - What is the date range you are interested in traveling? - """ - ) - ) - interests = input( - dedent( - """ - What are some of your high level interests and hobbies? - """ - ) - ) - trip_crew = TripCrew(origin, cities, date_range, interests) + trip_crew = TripCrew("cairo", "marsa alam", "sep", "scuba diving") result = trip_crew.run() print("\n\n########################") print("## Here is you Trip Plan") diff --git a/src/langtrace_python_sdk/instrumentation/crewai/instrumentation.py b/src/langtrace_python_sdk/instrumentation/crewai/instrumentation.py index 78cb1f87..4292dcb0 100644 --- a/src/langtrace_python_sdk/instrumentation/crewai/instrumentation.py +++ b/src/langtrace_python_sdk/instrumentation/crewai/instrumentation.py @@ -46,7 +46,7 @@ def _instrument(self, **kwargs): ) _W( "crewai.task", - "Task.execute", + "Task.execute_sync", patch_crew("Task.execute", version, tracer), ) except Exception as e: diff --git a/src/langtrace_python_sdk/instrumentation/crewai/patch.py b/src/langtrace_python_sdk/instrumentation/crewai/patch.py index 5bc07b81..f85e1435 100644 --- a/src/langtrace_python_sdk/instrumentation/crewai/patch.py +++ b/src/langtrace_python_sdk/instrumentation/crewai/patch.py @@ -2,15 +2,14 @@ from importlib_metadata import version as v from langtrace_python_sdk.constants import LANGTRACE_SDK_NAME from langtrace_python_sdk.utils import set_span_attribute -from langtrace_python_sdk.utils.llm import get_span_name -from langtrace_python_sdk.utils.silently_fail import silently_fail +from langtrace_python_sdk.utils.llm import get_span_name, set_span_attributes from langtrace_python_sdk.constants.instrumentation.common import ( LANGTRACE_ADDITIONAL_SPAN_ATTRIBUTES_KEY, SERVICE_PROVIDERS, ) from opentelemetry import baggage from langtrace.trace_attributes import FrameworkSpanAttributes -from opentelemetry.trace import SpanKind +from opentelemetry.trace import SpanKind, Span, Tracer from opentelemetry.trace.status import Status, StatusCode @@ -33,8 +32,8 @@ "share_crew": "bool", "step_callback": "object", "task_callback": "object", - "prompt_file": "object", - "output_log_file": "object", + "prompt_file": "str", + "output_log_file": "bool", } task_properties = { @@ -90,9 +89,8 @@ } -def patch_crew(operation_name, version, tracer): +def patch_crew(operation_name, version, tracer: Tracer): def traced_method(wrapped, instance, args, kwargs): - service_provider = SERVICE_PROVIDERS["CREWAI"] extra_attributes = baggage.get_baggage(LANGTRACE_ADDITIONAL_SPAN_ATTRIBUTES_KEY) span_attributes = { @@ -104,52 +102,15 @@ def traced_method(wrapped, instance, args, kwargs): **(extra_attributes if extra_attributes is not None else {}), } - crew_config = {} - for key, value in instance.__dict__.items(): - if instance.__class__.__name__ == "Crew": - if key in crew_properties and value is not None: - if crew_properties[key] == "json": - crew_config[key] = json.dumps(value) - elif crew_properties[key] == "object": - crew_config[key] = str(value) - else: - crew_config[key] = value - elif instance.__class__.__name__ == "Agent": - if key in agent_properties and value is not None: - if agent_properties[key] == "json": - crew_config[key] = json.dumps(value) - elif agent_properties[key] == "object": - crew_config[key] = str(value) - else: - crew_config[key] = value - elif instance.__class__.__name__ == "Task": - if key in task_properties and value is not None: - if task_properties[key] == "json": - crew_config[key] = json.dumps(value) - elif task_properties[key] == "object": - crew_config[key] = str(value) - else: - crew_config[key] = value - if crew_config: - if instance.__class__.__name__ == "Crew": - if "inputs" in kwargs and kwargs["inputs"]: - crew_config["inputs"] = json.dumps(kwargs["inputs"]) - span_attributes["crewai.crew.config"] = json.dumps(crew_config) - elif instance.__class__.__name__ == "Agent": - if "context" in kwargs and kwargs["context"]: - crew_config["context"] = json.dumps(kwargs["context"]) - span_attributes["crewai.agent.config"] = json.dumps(crew_config) - elif instance.__class__.__name__ == "Task": - span_attributes["crewai.task.config"] = json.dumps(crew_config) - attributes = FrameworkSpanAttributes(**span_attributes) with tracer.start_as_current_span( get_span_name(operation_name), kind=SpanKind.CLIENT ) as span: - _set_input_attributes(span, kwargs, attributes) try: + set_span_attributes(span, attributes) + CrewAISpanAttributes(span=span, instance=instance) result = wrapped(*args, **kwargs) if result: span.set_status(Status(StatusCode.OK)) @@ -158,6 +119,7 @@ def traced_method(wrapped, instance, args, kwargs): return result except Exception as err: + print("Error", err) # Record the exception in the span span.record_exception(err) @@ -170,7 +132,103 @@ def traced_method(wrapped, instance, args, kwargs): return traced_method -@silently_fail -def _set_input_attributes(span, kwargs, attributes): - for field, value in attributes.model_dump(by_alias=True).items(): - set_span_attribute(span, field, value) +class CrewAISpanAttributes: + span: Span + crew: dict + + def __init__(self, span: Span, instance) -> None: + self.span = span + self.instance = instance + self.crew = { + "tasks": [], + "agents": [], + } + + self.run() + + def run(self): + instance_name = self.instance.__class__.__name__ + if instance_name == "Crew": + self.set_crew_attributes() + set_span_attribute(self.span, "crewai.crew.config", json.dumps(self.crew)) + + elif instance_name == "Agent": + agent = self.set_agent_attributes() + # for key, value in agent.items(): + # set_span_attribute(self.span, key, value) + set_span_attribute(self.span, "crewai.agent.config", json.dumps(agent)) + elif instance_name == "Task": + task = self.set_task_attributes() + # uncomment if you want to spread attributes for the UI instead of dumping the whole object + # for key, value in task.items(): + # set_span_attribute(self.span, key, value) + set_span_attribute(self.span, "crewai.task.config", json.dumps(task)) + + def set_crew_attributes(self): + for key, value in self.instance.__dict__.items(): + if key == "tasks": + self._parse_tasks(value) + + elif key == "agents": + self._parse_agents(value) + else: + self.crew[key] = str(value) + + def set_agent_attributes(self): + agent = {} + for key, value in self.instance.__dict__.items(): + if value is None: + continue + agent[key] = str(value) + + return agent + + def set_task_attributes(self): + task = {} + for key, value in self.instance.__dict__.items(): + if value is None: + continue + + if key == "agent": + task[key] = value.role + else: + task[key] = str(value) + return task + + def _parse_agents(self, agents): + for agent in agents: + model = None + if agent.llm is not None: + if hasattr(agent.llm, "model"): + model = agent.llm.model + elif hasattr(agent.llm, "model_name"): + model = agent.llm.model_name + self.crew["agents"].append( + { + "id": str(agent.id), + "role": agent.role, + "goal": agent.goal, + "backstory": agent.backstory, + "cache": agent.cache, + "config": agent.config, + "verbose": agent.verbose, + "allow_delegation": agent.allow_delegation, + "tools": agent.tools, + "max_iter": agent.max_iter, + "llm": str(model if model is not None else ""), + } + ) + + def _parse_tasks(self, tasks): + for task in tasks: + self.crew["tasks"].append( + { + "agent": task.agent.role, + "description": task.description, + "async_execution": task.async_execution, + "expected_output": task.expected_output, + "human_input": task.human_input, + "tools": task.tools, + "output_file": task.output_file, + } + ) diff --git a/src/langtrace_python_sdk/version.py b/src/langtrace_python_sdk/version.py index 20c5c68c..9185c8e8 100644 --- a/src/langtrace_python_sdk/version.py +++ b/src/langtrace_python_sdk/version.py @@ -1 +1 @@ -__version__ = "2.2.29" +__version__ = "2.2.30"