From 1249106224c7f2baaa6cfbb5fc2b9c638afa8a50 Mon Sep 17 00:00:00 2001 From: Ali Waleed Date: Thu, 22 Aug 2024 11:46:05 +0300 Subject: [PATCH 1/8] crewAI curation --- .../instrumentation/crewai/patch.py | 150 ++++++++++++++---- 1 file changed, 121 insertions(+), 29 deletions(-) diff --git a/src/langtrace_python_sdk/instrumentation/crewai/patch.py b/src/langtrace_python_sdk/instrumentation/crewai/patch.py index 5bc07b81..587ebc11 100644 --- a/src/langtrace_python_sdk/instrumentation/crewai/patch.py +++ b/src/langtrace_python_sdk/instrumentation/crewai/patch.py @@ -33,8 +33,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 +90,125 @@ } +def parse_crewai_tasks(tasks): + task_dict = {} + for task in tasks: + for key, value in task.__dict__.items(): + if value is None: + continue + + elif key == "id": + task_dict[key] = str(value) + + elif key == "agent": + task_dict[key] = value.__dict__["role"] + + elif key in [ + "used_tools", + "tools_errors", + "delegations", + "description", + "expected_output", + "human_input", + "async_execution", + "prompt_context", + "expected_output", + "output_file", + ]: + task_dict[key] = value + else: + task_dict[key] = str(value) + return [task_dict] + + +def parse_crewai_agents(agents): + agent_dict = {} + for agent in agents: + for key, value in agent.__dict__.items(): + if value is None: + continue + + elif key == "id": + agent_dict[key] = str(value) + + elif key in [ + "role" "formatting_errors", + "goal", + "backstory", + "cache", + "verbose", + "max_rpm", + "allow_delegation", + "max_iter", + "max_execution_time", + ]: + agent_dict[key] = value + else: + agent_dict[key] = str(value) + return [agent_dict] + + +def set_crewai_attributes(instance): + crew_config = {} + class_name = instance.__class__.__name__ + for key, value in instance.__dict__.items(): + if value is None: + continue + + if class_name == "Crew": + set_crew_attributes(key, value, crew_config) + elif class_name == "Agent": + set_agent_attributes(key, value, crew_config) + elif class_name == "Task": + set_task_attributes(key, value, crew_config) + + return crew_config + + +def set_crew_attributes(key, value, config: dict): + if key not in crew_properties: + return + + if key == "tasks": + config[key] = parse_crewai_tasks(value) + + if key == "agents": + config[key] = parse_crewai_agents(value) + + # if crew_properties[key] == "json": + # config[key] = json.dumps(value) + # elif crew_properties[key] == "object": + # config[key] = str(value) + # else: + # config[key] = value + + +def set_agent_attributes(key, value, config: dict): + if key not in agent_properties: + return + + if agent_properties[key] == "json": + config[key] = json.dumps(value) + elif agent_properties[key] == "object": + config[key] = str(value) + else: + config[key] = value + + +def set_task_attributes(key, value, config: dict): + if key not in task_properties: + return + + if task_properties[key] == "json": + config[key] = json.dumps(value) + elif task_properties[key] == "object": + config[key] = str(value) + else: + config[key] = value + + def patch_crew(operation_name, version, 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,32 +220,8 @@ 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 + crew_config = set_crewai_attributes(instance) + if crew_config: if instance.__class__.__name__ == "Crew": if "inputs" in kwargs and kwargs["inputs"]: From 5048479fb1a72b18e4e592ad3f256f52fa5529aa Mon Sep 17 00:00:00 2001 From: Ali Waleed Date: Wed, 28 Aug 2024 18:08:23 +0300 Subject: [PATCH 2/8] curation --- .../crewai_example/simple_agent/main.py | 21 +- .../crewai_example/simple_agent/tasks.py | 1 + .../crewai_example/trip_planner/main.py | 58 ++--- .../instrumentation/crewai/instrumentation.py | 3 +- .../instrumentation/crewai/patch.py | 240 ++++++++---------- 5 files changed, 142 insertions(+), 181 deletions(-) diff --git a/src/examples/crewai_example/simple_agent/main.py b/src/examples/crewai_example/simple_agent/main.py index 61230bef..1c8bf805 100644 --- a/src/examples/crewai_example/simple_agent/main.py +++ b/src/examples/crewai_example/simple_agent/main.py @@ -7,8 +7,7 @@ import agentops load_dotenv() -agentops.init() -langtrace.init(write_spans_to_console=False, batch=False) +langtrace.init() class PoetryCrew: @@ -32,15 +31,15 @@ def run(self): 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) + # topic = input( + # dedent( + # """ + # What topic do you want to write a poem on? + # """ + # ) + # ) + + 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..ed015488 100644 --- a/src/examples/crewai_example/trip_planner/main.py +++ b/src/examples/crewai_example/trip_planner/main.py @@ -59,36 +59,36 @@ 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? - """ - ) - ) + # 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..7d7cbb00 100644 --- a/src/langtrace_python_sdk/instrumentation/crewai/instrumentation.py +++ b/src/langtrace_python_sdk/instrumentation/crewai/instrumentation.py @@ -20,6 +20,7 @@ from typing import Collection from importlib_metadata import version as v from .patch import patch_crew +import crewai class CrewAIInstrumentation(BaseInstrumentor): @@ -46,7 +47,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 587ebc11..88b18d99 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 @@ -90,124 +89,7 @@ } -def parse_crewai_tasks(tasks): - task_dict = {} - for task in tasks: - for key, value in task.__dict__.items(): - if value is None: - continue - - elif key == "id": - task_dict[key] = str(value) - - elif key == "agent": - task_dict[key] = value.__dict__["role"] - - elif key in [ - "used_tools", - "tools_errors", - "delegations", - "description", - "expected_output", - "human_input", - "async_execution", - "prompt_context", - "expected_output", - "output_file", - ]: - task_dict[key] = value - else: - task_dict[key] = str(value) - return [task_dict] - - -def parse_crewai_agents(agents): - agent_dict = {} - for agent in agents: - for key, value in agent.__dict__.items(): - if value is None: - continue - - elif key == "id": - agent_dict[key] = str(value) - - elif key in [ - "role" "formatting_errors", - "goal", - "backstory", - "cache", - "verbose", - "max_rpm", - "allow_delegation", - "max_iter", - "max_execution_time", - ]: - agent_dict[key] = value - else: - agent_dict[key] = str(value) - return [agent_dict] - - -def set_crewai_attributes(instance): - crew_config = {} - class_name = instance.__class__.__name__ - for key, value in instance.__dict__.items(): - if value is None: - continue - - if class_name == "Crew": - set_crew_attributes(key, value, crew_config) - elif class_name == "Agent": - set_agent_attributes(key, value, crew_config) - elif class_name == "Task": - set_task_attributes(key, value, crew_config) - - return crew_config - - -def set_crew_attributes(key, value, config: dict): - if key not in crew_properties: - return - - if key == "tasks": - config[key] = parse_crewai_tasks(value) - - if key == "agents": - config[key] = parse_crewai_agents(value) - - # if crew_properties[key] == "json": - # config[key] = json.dumps(value) - # elif crew_properties[key] == "object": - # config[key] = str(value) - # else: - # config[key] = value - - -def set_agent_attributes(key, value, config: dict): - if key not in agent_properties: - return - - if agent_properties[key] == "json": - config[key] = json.dumps(value) - elif agent_properties[key] == "object": - config[key] = str(value) - else: - config[key] = value - - -def set_task_attributes(key, value, config: dict): - if key not in task_properties: - return - - if task_properties[key] == "json": - config[key] = json.dumps(value) - elif task_properties[key] == "object": - config[key] = str(value) - else: - config[key] = value - - -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) @@ -220,28 +102,15 @@ def traced_method(wrapped, instance, args, kwargs): **(extra_attributes if extra_attributes is not None else {}), } - crew_config = set_crewai_attributes(instance) - - 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)) @@ -250,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) @@ -262,7 +132,97 @@ 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: + 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(agent.llm.model), + } + ) + + 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, + } + ) From 10884858e4bc734e4aced2d44b3a3f771b5875ab Mon Sep 17 00:00:00 2001 From: Ali Waleed Date: Wed, 28 Aug 2024 18:17:19 +0300 Subject: [PATCH 3/8] remove import --- .../instrumentation/crewai/instrumentation.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/langtrace_python_sdk/instrumentation/crewai/instrumentation.py b/src/langtrace_python_sdk/instrumentation/crewai/instrumentation.py index 7d7cbb00..4292dcb0 100644 --- a/src/langtrace_python_sdk/instrumentation/crewai/instrumentation.py +++ b/src/langtrace_python_sdk/instrumentation/crewai/instrumentation.py @@ -20,7 +20,6 @@ from typing import Collection from importlib_metadata import version as v from .patch import patch_crew -import crewai class CrewAIInstrumentation(BaseInstrumentor): From 776f3741732222a686e6d9de6e294c1cf65a2f7f Mon Sep 17 00:00:00 2001 From: Karthik Kalyanaraman Date: Wed, 28 Aug 2024 17:00:11 -0700 Subject: [PATCH 4/8] Minor fixes --- src/examples/crewai_example/simple_agent/agents.py | 2 +- src/examples/crewai_example/simple_agent/main.py | 10 ++++++---- .../instrumentation/crewai/patch.py | 8 +++++++- 3 files changed, 14 insertions(+), 6 deletions(-) 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 1c8bf805..cad48882 100644 --- a/src/examples/crewai_example/simple_agent/main.py +++ b/src/examples/crewai_example/simple_agent/main.py @@ -1,10 +1,12 @@ +import sys + +sys.path.insert(0, '/Users/karthikkalyanaraman/work/langtrace/langtrace-python-sdk/src') + from crewai import Crew -from textwrap import dedent -from .agents import PoetryAgents -from .tasks import PoetryTasks +from agents import PoetryAgents +from tasks import PoetryTasks from langtrace_python_sdk import langtrace from dotenv import load_dotenv -import agentops load_dotenv() langtrace.init() diff --git a/src/langtrace_python_sdk/instrumentation/crewai/patch.py b/src/langtrace_python_sdk/instrumentation/crewai/patch.py index 88b18d99..f85e1435 100644 --- a/src/langtrace_python_sdk/instrumentation/crewai/patch.py +++ b/src/langtrace_python_sdk/instrumentation/crewai/patch.py @@ -197,6 +197,12 @@ def set_task_attributes(self): 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), @@ -209,7 +215,7 @@ def _parse_agents(self, agents): "allow_delegation": agent.allow_delegation, "tools": agent.tools, "max_iter": agent.max_iter, - "llm": str(agent.llm.model), + "llm": str(model if model is not None else ""), } ) From 979a26f6e48cc7845af3ab8e53a79be2f86d6612 Mon Sep 17 00:00:00 2001 From: Ali Waleed Date: Thu, 29 Aug 2024 11:45:09 +0300 Subject: [PATCH 5/8] fix example --- src/examples/crewai_example/simple_agent/main.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/examples/crewai_example/simple_agent/main.py b/src/examples/crewai_example/simple_agent/main.py index cad48882..3be7d613 100644 --- a/src/examples/crewai_example/simple_agent/main.py +++ b/src/examples/crewai_example/simple_agent/main.py @@ -1,10 +1,6 @@ -import sys - -sys.path.insert(0, '/Users/karthikkalyanaraman/work/langtrace/langtrace-python-sdk/src') - from crewai import Crew -from agents import PoetryAgents -from tasks import PoetryTasks +from .agents import PoetryAgents +from .tasks import PoetryTasks from langtrace_python_sdk import langtrace from dotenv import load_dotenv @@ -30,6 +26,7 @@ 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("-------------------------------") From 91ec5caf74a678c773a586a5b7cd7d5f6a1088d2 Mon Sep 17 00:00:00 2001 From: Ali Waleed Date: Thu, 29 Aug 2024 11:46:12 +0300 Subject: [PATCH 6/8] remove commented code --- .../crewai_example/simple_agent/main.py | 8 ------ .../crewai_example/trip_planner/main.py | 28 ------------------- 2 files changed, 36 deletions(-) diff --git a/src/examples/crewai_example/simple_agent/main.py b/src/examples/crewai_example/simple_agent/main.py index 3be7d613..2d694d6e 100644 --- a/src/examples/crewai_example/simple_agent/main.py +++ b/src/examples/crewai_example/simple_agent/main.py @@ -30,14 +30,6 @@ def run(self): 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="cold") result = poetry_crew.run() print("\n\n########################") diff --git a/src/examples/crewai_example/trip_planner/main.py b/src/examples/crewai_example/trip_planner/main.py index ed015488..c620e3b4 100644 --- a/src/examples/crewai_example/trip_planner/main.py +++ b/src/examples/crewai_example/trip_planner/main.py @@ -59,34 +59,6 @@ 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("cairo", "marsa alam", "sep", "scuba diving") result = trip_crew.run() From 7e92cf8b951c94fed1a8eb78dea27c77532b0e77 Mon Sep 17 00:00:00 2001 From: Ali Waleed Date: Thu, 29 Aug 2024 11:46:30 +0300 Subject: [PATCH 7/8] cleanup --- src/examples/crewai_example/trip_planner/main.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/examples/crewai_example/trip_planner/main.py b/src/examples/crewai_example/trip_planner/main.py index c620e3b4..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 From e9ab473e97922741249a76fad0b0eb4c33f60bf5 Mon Sep 17 00:00:00 2001 From: Ali Waleed Date: Thu, 29 Aug 2024 11:47:04 +0300 Subject: [PATCH 8/8] bump --- src/langtrace_python_sdk/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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"