langtrace-python-sdk 2.1.20__py3-none-any.whl → 2.1.22__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- examples/crewai_example/basic.py +70 -0
- examples/dspy_example/math_problems_cot.py +42 -0
- examples/dspy_example/program_of_thought_basic.py +35 -0
- examples/dspy_example/quiz_gen.py +113 -0
- examples/dspy_example/react.py +39 -0
- langtrace_python_sdk/constants/instrumentation/common.py +2 -0
- langtrace_python_sdk/instrumentation/__init__.py +4 -0
- langtrace_python_sdk/instrumentation/crewai/__init__.py +3 -0
- langtrace_python_sdk/instrumentation/crewai/instrumentation.py +53 -0
- langtrace_python_sdk/instrumentation/crewai/patch.py +173 -0
- langtrace_python_sdk/instrumentation/dspy/__init__.py +3 -0
- langtrace_python_sdk/instrumentation/dspy/instrumentation.py +85 -0
- langtrace_python_sdk/instrumentation/dspy/patch.py +206 -0
- langtrace_python_sdk/instrumentation/openai/patch.py +106 -187
- langtrace_python_sdk/langtrace.py +4 -0
- langtrace_python_sdk/version.py +1 -1
- {langtrace_python_sdk-2.1.20.dist-info → langtrace_python_sdk-2.1.22.dist-info}/METADATA +1 -1
- {langtrace_python_sdk-2.1.20.dist-info → langtrace_python_sdk-2.1.22.dist-info}/RECORD +21 -10
- {langtrace_python_sdk-2.1.20.dist-info → langtrace_python_sdk-2.1.22.dist-info}/WHEEL +1 -1
- {langtrace_python_sdk-2.1.20.dist-info → langtrace_python_sdk-2.1.22.dist-info}/entry_points.txt +0 -0
- {langtrace_python_sdk-2.1.20.dist-info → langtrace_python_sdk-2.1.22.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
os.environ["OPENAI_MODEL_NAME"] = "gpt-3.5-turbo"
|
|
4
|
+
os.environ["SERPER_API_KEY"] = "" # serper.dev API key
|
|
5
|
+
from langtrace_python_sdk import langtrace
|
|
6
|
+
from langtrace_python_sdk.utils.with_root_span import with_langtrace_root_span
|
|
7
|
+
from crewai import Crew, Process
|
|
8
|
+
from crewai import Task
|
|
9
|
+
from crewai import Agent
|
|
10
|
+
from crewai_tools import SerperDevTool
|
|
11
|
+
from crewai_tools import YoutubeVideoSearchTool
|
|
12
|
+
|
|
13
|
+
langtrace.init()
|
|
14
|
+
|
|
15
|
+
search_tool = SerperDevTool()
|
|
16
|
+
|
|
17
|
+
# Targeted search within a specific Youtube video's content
|
|
18
|
+
youtube_tool = YoutubeVideoSearchTool(
|
|
19
|
+
youtube_video_url="https://www.youtube.com/watch?v=blqIZGXWUpU"
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
# Creating a senior researcher agent with memory and verbose mode
|
|
23
|
+
researcher = Agent(
|
|
24
|
+
role="Senior Researcher",
|
|
25
|
+
goal="Uncover groundbreaking technologies in {topic}",
|
|
26
|
+
verbose=True,
|
|
27
|
+
memory=True,
|
|
28
|
+
backstory=(
|
|
29
|
+
"Driven by curiosity, you're at the forefront of"
|
|
30
|
+
"innovation, eager to explore and share knowledge that could change"
|
|
31
|
+
"the world."
|
|
32
|
+
),
|
|
33
|
+
tools=[youtube_tool],
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
# Research task
|
|
37
|
+
research_task = Task(
|
|
38
|
+
description=(
|
|
39
|
+
"Do a {topic} of the given youtube video."
|
|
40
|
+
"Focus on identifying the overall narrative."
|
|
41
|
+
"Your final report should clearly articulate the key points."
|
|
42
|
+
),
|
|
43
|
+
expected_output="10 key points from the shared video.",
|
|
44
|
+
tools=[youtube_tool],
|
|
45
|
+
agent=researcher,
|
|
46
|
+
callback="research_callback", # Example of task callback
|
|
47
|
+
human_input=True,
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
# Forming the tech-focused crew with some enhanced configurations
|
|
52
|
+
crew = Crew(
|
|
53
|
+
agents=[researcher],
|
|
54
|
+
tasks=[research_task],
|
|
55
|
+
process=Process.sequential, # Optional: Sequential task execution is default
|
|
56
|
+
memory=False,
|
|
57
|
+
cache=False,
|
|
58
|
+
max_rpm=20,
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
# Starting the task execution process with enhanced feedback
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
@with_langtrace_root_span("Crew")
|
|
65
|
+
def test_crew():
|
|
66
|
+
result = crew.kickoff(inputs={"topic": "summary"})
|
|
67
|
+
return result
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
test_crew()
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import dspy
|
|
2
|
+
from dspy.datasets.gsm8k import GSM8K, gsm8k_metric
|
|
3
|
+
from dspy.teleprompt import BootstrapFewShot
|
|
4
|
+
|
|
5
|
+
# flake8: noqa
|
|
6
|
+
from langtrace_python_sdk import langtrace, with_langtrace_root_span
|
|
7
|
+
|
|
8
|
+
langtrace.init()
|
|
9
|
+
|
|
10
|
+
turbo = dspy.OpenAI(model="gpt-3.5-turbo", max_tokens=250)
|
|
11
|
+
dspy.settings.configure(lm=turbo)
|
|
12
|
+
|
|
13
|
+
# Load math questions from the GSM8K dataset
|
|
14
|
+
gsm8k = GSM8K()
|
|
15
|
+
gsm8k_trainset, gsm8k_devset = gsm8k.train[:10], gsm8k.dev[:10]
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class CoT(dspy.Module):
|
|
19
|
+
def __init__(self):
|
|
20
|
+
super().__init__()
|
|
21
|
+
self.prog = dspy.ChainOfThought("question -> answer")
|
|
22
|
+
|
|
23
|
+
def forward(self, question):
|
|
24
|
+
return self.prog(question=question)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@with_langtrace_root_span(name="math_problems_cot_example")
|
|
28
|
+
def example():
|
|
29
|
+
|
|
30
|
+
# Set up the optimizer: we want to "bootstrap" (i.e., self-generate) 4-shot examples of our CoT program.
|
|
31
|
+
config = dict(max_bootstrapped_demos=4, max_labeled_demos=4)
|
|
32
|
+
|
|
33
|
+
# Optimize! Use the `gsm8k_metric` here. In general, the metric is going to tell the optimizer how well it's doing.
|
|
34
|
+
teleprompter = BootstrapFewShot(metric=gsm8k_metric, **config)
|
|
35
|
+
optimized_cot = teleprompter.compile(CoT(), trainset=gsm8k_trainset)
|
|
36
|
+
|
|
37
|
+
ans = optimized_cot(question="What is the sqrt of 345?")
|
|
38
|
+
print(ans)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
if __name__ == "__main__":
|
|
42
|
+
example()
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import dspy
|
|
2
|
+
|
|
3
|
+
# flake8: noqa
|
|
4
|
+
from langtrace_python_sdk import langtrace, with_langtrace_root_span
|
|
5
|
+
|
|
6
|
+
langtrace.init()
|
|
7
|
+
|
|
8
|
+
turbo = dspy.OpenAI(model="gpt-3.5-turbo", max_tokens=250)
|
|
9
|
+
dspy.settings.configure(lm=turbo)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
# Define a simple signature for basic question answering
|
|
13
|
+
class BasicQA(dspy.Signature):
|
|
14
|
+
"""Answer questions with short factoid answers."""
|
|
15
|
+
|
|
16
|
+
question = dspy.InputField()
|
|
17
|
+
answer = dspy.OutputField(desc="often between 1 and 5 words")
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@with_langtrace_root_span(name="pot_example")
|
|
21
|
+
def example():
|
|
22
|
+
|
|
23
|
+
# Pass signature to ProgramOfThought Module
|
|
24
|
+
pot = dspy.ProgramOfThought(BasicQA)
|
|
25
|
+
|
|
26
|
+
# Call the ProgramOfThought module on a particular input
|
|
27
|
+
question = "Sarah has 5 apples. She buys 7 more apples from the store. How many apples does Sarah have now?"
|
|
28
|
+
result = pot(question=question)
|
|
29
|
+
|
|
30
|
+
print(f"Question: {question}")
|
|
31
|
+
print(f"Final Predicted Answer (after ProgramOfThought process): {result.answer}")
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
if __name__ == "__main__":
|
|
35
|
+
example()
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import dspy
|
|
2
|
+
import json
|
|
3
|
+
from dspy.datasets import HotPotQA
|
|
4
|
+
from dspy.teleprompt import BootstrapFewShot
|
|
5
|
+
from dspy.evaluate.evaluate import Evaluate
|
|
6
|
+
|
|
7
|
+
# flake8: noqa
|
|
8
|
+
from langtrace_python_sdk import langtrace, with_langtrace_root_span
|
|
9
|
+
|
|
10
|
+
langtrace.init()
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
colbertv2_wiki17_abstracts = dspy.ColBERTv2(
|
|
14
|
+
url="http://20.102.90.50:2017/wiki17_abstracts"
|
|
15
|
+
)
|
|
16
|
+
dspy.settings.configure(rm=colbertv2_wiki17_abstracts)
|
|
17
|
+
turbo = dspy.OpenAI(model="gpt-3.5-turbo-0613", max_tokens=500)
|
|
18
|
+
dspy.settings.configure(lm=turbo, trace=[], temperature=0.7)
|
|
19
|
+
|
|
20
|
+
dataset = HotPotQA(
|
|
21
|
+
train_seed=1,
|
|
22
|
+
train_size=300,
|
|
23
|
+
eval_seed=2023,
|
|
24
|
+
dev_size=300,
|
|
25
|
+
test_size=0,
|
|
26
|
+
keep_details=True,
|
|
27
|
+
)
|
|
28
|
+
trainset = [x.with_inputs("question", "answer") for x in dataset.train]
|
|
29
|
+
devset = [x.with_inputs("question", "answer") for x in dataset.dev]
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class GenerateAnswerChoices(dspy.Signature):
|
|
33
|
+
"""Generate answer choices in JSON format that include the correct answer and plausible distractors for the specified question."""
|
|
34
|
+
|
|
35
|
+
question = dspy.InputField()
|
|
36
|
+
correct_answer = dspy.InputField()
|
|
37
|
+
number_of_choices = dspy.InputField()
|
|
38
|
+
answer_choices = dspy.OutputField(desc="JSON key-value pairs")
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class QuizAnswerGenerator(dspy.Module):
|
|
42
|
+
def __init__(self):
|
|
43
|
+
super().__init__()
|
|
44
|
+
self.prog = dspy.ChainOfThought(GenerateAnswerChoices)
|
|
45
|
+
|
|
46
|
+
def forward(self, question, answer):
|
|
47
|
+
choices = self.prog(
|
|
48
|
+
question=question, correct_answer=answer, number_of_choices="4"
|
|
49
|
+
).answer_choices
|
|
50
|
+
# dspy.Suggest(
|
|
51
|
+
# format_checker(choices),
|
|
52
|
+
# "The format of the answer choices should be in JSON format. Please revise accordingly.",
|
|
53
|
+
# target_module=GenerateAnswerChoices,
|
|
54
|
+
# )
|
|
55
|
+
return dspy.Prediction(choices=choices)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def format_checker(choice_string):
|
|
59
|
+
try:
|
|
60
|
+
choices = json.loads(choice_string)
|
|
61
|
+
if isinstance(choices, dict) and all(
|
|
62
|
+
isinstance(key, str) and isinstance(value, str)
|
|
63
|
+
for key, value in choices.items()
|
|
64
|
+
):
|
|
65
|
+
return True
|
|
66
|
+
except json.JSONDecodeError:
|
|
67
|
+
return False
|
|
68
|
+
|
|
69
|
+
return False
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def format_valid_metric(gold, pred, trace=None):
|
|
73
|
+
generated_choices = pred.choices
|
|
74
|
+
format_valid = format_checker(generated_choices)
|
|
75
|
+
score = format_valid
|
|
76
|
+
return score
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
@with_langtrace_root_span(name="quiz_generator_1")
|
|
80
|
+
def quiz_generator_1():
|
|
81
|
+
quiz_generator = QuizAnswerGenerator()
|
|
82
|
+
|
|
83
|
+
example = devset[67]
|
|
84
|
+
print("Example Question: ", example.question)
|
|
85
|
+
print("Example Answer: ", example.answer)
|
|
86
|
+
# quiz_choices = quiz_generator(question=example.question, answer=example.answer)
|
|
87
|
+
# print("Generated Quiz Choices: ", quiz_choices.choices)
|
|
88
|
+
|
|
89
|
+
optimizer = BootstrapFewShot(
|
|
90
|
+
metric=format_valid_metric, max_bootstrapped_demos=4, max_labeled_demos=4
|
|
91
|
+
)
|
|
92
|
+
compiled_quiz_generator = optimizer.compile(
|
|
93
|
+
quiz_generator,
|
|
94
|
+
trainset=trainset,
|
|
95
|
+
)
|
|
96
|
+
quiz_choices = compiled_quiz_generator(
|
|
97
|
+
question=example.question, answer=example.answer
|
|
98
|
+
)
|
|
99
|
+
print("Generated Quiz Choices: ", quiz_choices.choices)
|
|
100
|
+
|
|
101
|
+
# Evaluate
|
|
102
|
+
evaluate = Evaluate(
|
|
103
|
+
metric=format_valid_metric,
|
|
104
|
+
devset=devset[67:70],
|
|
105
|
+
num_threads=1,
|
|
106
|
+
display_progress=True,
|
|
107
|
+
display_table=5,
|
|
108
|
+
)
|
|
109
|
+
evaluate(quiz_generator)
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
if __name__ == "__main__":
|
|
113
|
+
quiz_generator_1()
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import os
|
|
3
|
+
import dspy
|
|
4
|
+
|
|
5
|
+
# Add the local src folder to the Python path
|
|
6
|
+
sys.path.insert(0, os.path.abspath('/Users/karthikkalyanaraman/work/langtrace/langtrace-python-sdk/src'))
|
|
7
|
+
|
|
8
|
+
# flake8: noqa
|
|
9
|
+
from langtrace_python_sdk import langtrace, with_langtrace_root_span
|
|
10
|
+
langtrace.init()
|
|
11
|
+
|
|
12
|
+
turbo = dspy.OpenAI(model='gpt-3.5-turbo', max_tokens=250)
|
|
13
|
+
dspy.settings.configure(lm=turbo)
|
|
14
|
+
|
|
15
|
+
colbertv2_wiki17_abstracts = dspy.ColBERTv2(url='http://20.102.90.50:2017/wiki17_abstracts')
|
|
16
|
+
dspy.settings.configure(rm=colbertv2_wiki17_abstracts)
|
|
17
|
+
retriever = dspy.Retrieve(k=3)
|
|
18
|
+
|
|
19
|
+
# Define a simple signature for basic question answering
|
|
20
|
+
class BasicQA(dspy.Signature):
|
|
21
|
+
"""Answer questions with short factoid answers."""
|
|
22
|
+
question = dspy.InputField()
|
|
23
|
+
answer = dspy.OutputField(desc="often between 1 and 5 words")
|
|
24
|
+
|
|
25
|
+
@with_langtrace_root_span(name="react_example")
|
|
26
|
+
def example():
|
|
27
|
+
|
|
28
|
+
# Pass signature to ReAct module
|
|
29
|
+
react_module = dspy.ReAct(BasicQA)
|
|
30
|
+
|
|
31
|
+
# Call the ReAct module on a particular input
|
|
32
|
+
question = 'Aside from the Apple Remote, what other devices can control the program Apple Remote was originally designed to interact with?'
|
|
33
|
+
result = react_module(question=question)
|
|
34
|
+
|
|
35
|
+
print(f"Question: {question}")
|
|
36
|
+
print(f"Final Predicted Answer (after ReAct process): {result.answer}")
|
|
37
|
+
|
|
38
|
+
if __name__ == '__main__':
|
|
39
|
+
example()
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from .anthropic import AnthropicInstrumentation
|
|
2
2
|
from .chroma import ChromaInstrumentation
|
|
3
3
|
from .cohere import CohereInstrumentation
|
|
4
|
+
from .crewai import CrewAIInstrumentation
|
|
4
5
|
from .groq import GroqInstrumentation
|
|
5
6
|
from .langchain import LangchainInstrumentation
|
|
6
7
|
from .langchain_community import LangchainCommunityInstrumentation
|
|
@@ -12,11 +13,13 @@ from .pinecone import PineconeInstrumentation
|
|
|
12
13
|
from .qdrant import QdrantInstrumentation
|
|
13
14
|
from .weaviate import WeaviateInstrumentation
|
|
14
15
|
from .ollama import OllamaInstrumentor
|
|
16
|
+
from .dspy import DspyInstrumentation
|
|
15
17
|
|
|
16
18
|
__all__ = [
|
|
17
19
|
"AnthropicInstrumentation",
|
|
18
20
|
"ChromaInstrumentation",
|
|
19
21
|
"CohereInstrumentation",
|
|
22
|
+
"CrewAIInstrumentation",
|
|
20
23
|
"GroqInstrumentation",
|
|
21
24
|
"LangchainInstrumentation",
|
|
22
25
|
"LangchainCommunityInstrumentation",
|
|
@@ -28,4 +31,5 @@ __all__ = [
|
|
|
28
31
|
"QdrantInstrumentation",
|
|
29
32
|
"WeaviateInstrumentation",
|
|
30
33
|
"OllamaInstrumentor",
|
|
34
|
+
"DspyInstrumentation",
|
|
31
35
|
]
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Copyright (c) 2024 Scale3 Labs
|
|
3
|
+
|
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
you may not use this file except in compliance with the License.
|
|
6
|
+
You may obtain a copy of the License at
|
|
7
|
+
|
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
|
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
See the License for the specific language governing permissions and
|
|
14
|
+
limitations under the License.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
|
|
18
|
+
from opentelemetry.trace import get_tracer
|
|
19
|
+
from wrapt import wrap_function_wrapper as _W
|
|
20
|
+
from typing import Collection
|
|
21
|
+
from importlib_metadata import version as v
|
|
22
|
+
from .patch import patch_crew
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class CrewAIInstrumentation(BaseInstrumentor):
|
|
26
|
+
"""
|
|
27
|
+
The CrewAIInstrumentation class represents the CrewAI instrumentation"""
|
|
28
|
+
|
|
29
|
+
def instrumentation_dependencies(self) -> Collection[str]:
|
|
30
|
+
return ["crewai >= 0.32.0"]
|
|
31
|
+
|
|
32
|
+
def _instrument(self, **kwargs):
|
|
33
|
+
tracer_provider = kwargs.get("tracer_provider")
|
|
34
|
+
tracer = get_tracer(__name__, "", tracer_provider)
|
|
35
|
+
version = v("crewai")
|
|
36
|
+
_W(
|
|
37
|
+
"crewai.crew",
|
|
38
|
+
"Crew.kickoff",
|
|
39
|
+
patch_crew("Crew.kickoff", version, tracer),
|
|
40
|
+
)
|
|
41
|
+
_W(
|
|
42
|
+
"crewai.agent",
|
|
43
|
+
"Agent.execute_task",
|
|
44
|
+
patch_crew("Agent.execute_task", version, tracer),
|
|
45
|
+
)
|
|
46
|
+
_W(
|
|
47
|
+
"crewai.task",
|
|
48
|
+
"Task.execute",
|
|
49
|
+
patch_crew("Task.execute", version, tracer),
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
def _uninstrument(self, **kwargs):
|
|
53
|
+
pass
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from importlib_metadata import version as v
|
|
3
|
+
from langtrace_python_sdk.constants import LANGTRACE_SDK_NAME
|
|
4
|
+
from langtrace_python_sdk.utils import set_span_attribute
|
|
5
|
+
from langtrace_python_sdk.utils.silently_fail import silently_fail
|
|
6
|
+
from langtrace_python_sdk.constants.instrumentation.common import (
|
|
7
|
+
LANGTRACE_ADDITIONAL_SPAN_ATTRIBUTES_KEY,
|
|
8
|
+
SERVICE_PROVIDERS,
|
|
9
|
+
)
|
|
10
|
+
from opentelemetry import baggage
|
|
11
|
+
from langtrace.trace_attributes import FrameworkSpanAttributes
|
|
12
|
+
from opentelemetry.trace import SpanKind
|
|
13
|
+
from opentelemetry.trace.status import Status, StatusCode
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
crew_properties = {
|
|
17
|
+
"tasks": "object",
|
|
18
|
+
"agents": "object",
|
|
19
|
+
"cache": "bool",
|
|
20
|
+
"process": "object",
|
|
21
|
+
"verbose": "bool",
|
|
22
|
+
"memory": "bool",
|
|
23
|
+
"embedder": "json",
|
|
24
|
+
"full_output": "bool",
|
|
25
|
+
"manager_llm": "object",
|
|
26
|
+
"manager_agent": "object",
|
|
27
|
+
"manager_callbacks": "object",
|
|
28
|
+
"function_calling_llm": "object",
|
|
29
|
+
"config": "json",
|
|
30
|
+
"id": "object",
|
|
31
|
+
"max_rpm": "int",
|
|
32
|
+
"share_crew": "bool",
|
|
33
|
+
"step_callback": "object",
|
|
34
|
+
"task_callback": "object",
|
|
35
|
+
"prompt_file": "object",
|
|
36
|
+
"output_log_file": "object",
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
task_properties = {
|
|
40
|
+
"id": "object",
|
|
41
|
+
"used_tools": "int",
|
|
42
|
+
"tools_errors": "int",
|
|
43
|
+
"delegations": "int",
|
|
44
|
+
"i18n": "object",
|
|
45
|
+
"thread": "object",
|
|
46
|
+
"prompt_context": "object",
|
|
47
|
+
"description": "str",
|
|
48
|
+
"expected_output": "str",
|
|
49
|
+
"config": "object",
|
|
50
|
+
"callback": "str",
|
|
51
|
+
"agent": "object",
|
|
52
|
+
"context": "object",
|
|
53
|
+
"async_execution": "bool",
|
|
54
|
+
"output_json": "object",
|
|
55
|
+
"output_pydantic": "object",
|
|
56
|
+
"output_file": "object",
|
|
57
|
+
"output": "object",
|
|
58
|
+
"tools": "object",
|
|
59
|
+
"human_input": "bool",
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
agent_properties = {
|
|
63
|
+
"formatting_errors": "int",
|
|
64
|
+
"id": "object",
|
|
65
|
+
"role": "str",
|
|
66
|
+
"goal": "str",
|
|
67
|
+
"backstory": "str",
|
|
68
|
+
"cache": "bool",
|
|
69
|
+
"config": "object",
|
|
70
|
+
"max_rpm": "int",
|
|
71
|
+
"verbose": "bool",
|
|
72
|
+
"allow_delegation": "bool",
|
|
73
|
+
"tools": "object",
|
|
74
|
+
"max_iter": "int",
|
|
75
|
+
"max_execution_time": "object",
|
|
76
|
+
"agent_executor": "object",
|
|
77
|
+
"tools_handler": "object",
|
|
78
|
+
"force_answer_max_iterations": "int",
|
|
79
|
+
"crew": "object",
|
|
80
|
+
"cache_handler": "object",
|
|
81
|
+
"step_callback": "object",
|
|
82
|
+
"i18n": "object",
|
|
83
|
+
"llm": "object",
|
|
84
|
+
"function_calling_llm": "object",
|
|
85
|
+
"callbacks": "object",
|
|
86
|
+
"system_template": "object",
|
|
87
|
+
"prompt_template": "object",
|
|
88
|
+
"response_template": "object",
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def patch_crew(operation_name, version, tracer):
|
|
93
|
+
def traced_method(wrapped, instance, args, kwargs):
|
|
94
|
+
|
|
95
|
+
service_provider = SERVICE_PROVIDERS["CREWAI"]
|
|
96
|
+
extra_attributes = baggage.get_baggage(LANGTRACE_ADDITIONAL_SPAN_ATTRIBUTES_KEY)
|
|
97
|
+
span_attributes = {
|
|
98
|
+
"langtrace.sdk.name": "langtrace-python-sdk",
|
|
99
|
+
"langtrace.service.name": service_provider,
|
|
100
|
+
"langtrace.service.type": "framework",
|
|
101
|
+
"langtrace.service.version": version,
|
|
102
|
+
"langtrace.version": v(LANGTRACE_SDK_NAME),
|
|
103
|
+
**(extra_attributes if extra_attributes is not None else {}),
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
crew_config = {}
|
|
107
|
+
for key, value in instance.__dict__.items():
|
|
108
|
+
if instance.__class__.__name__ == "Crew":
|
|
109
|
+
if key in crew_properties and value is not None:
|
|
110
|
+
if crew_properties[key] == "json":
|
|
111
|
+
crew_config[key] = json.dumps(value)
|
|
112
|
+
elif crew_properties[key] == "object":
|
|
113
|
+
crew_config[key] = str(value)
|
|
114
|
+
else:
|
|
115
|
+
crew_config[key] = value
|
|
116
|
+
elif instance.__class__.__name__ == "Agent":
|
|
117
|
+
if key in agent_properties and value is not None:
|
|
118
|
+
if agent_properties[key] == "json":
|
|
119
|
+
crew_config[key] = json.dumps(value)
|
|
120
|
+
elif agent_properties[key] == "object":
|
|
121
|
+
crew_config[key] = str(value)
|
|
122
|
+
else:
|
|
123
|
+
crew_config[key] = value
|
|
124
|
+
elif instance.__class__.__name__ == "Task":
|
|
125
|
+
if key in task_properties and value is not None:
|
|
126
|
+
if task_properties[key] == "json":
|
|
127
|
+
crew_config[key] = json.dumps(value)
|
|
128
|
+
elif task_properties[key] == "object":
|
|
129
|
+
crew_config[key] = str(value)
|
|
130
|
+
else:
|
|
131
|
+
crew_config[key] = value
|
|
132
|
+
if crew_config:
|
|
133
|
+
if instance.__class__.__name__ == "Crew":
|
|
134
|
+
if "inputs" in kwargs and kwargs["inputs"]:
|
|
135
|
+
crew_config["inputs"] = json.dumps(kwargs["inputs"])
|
|
136
|
+
span_attributes["crewai.crew.config"] = json.dumps(crew_config)
|
|
137
|
+
elif instance.__class__.__name__ == "Agent":
|
|
138
|
+
if "context" in kwargs and kwargs["context"]:
|
|
139
|
+
crew_config["context"] = json.dumps(kwargs["context"])
|
|
140
|
+
span_attributes["crewai.agent.config"] = json.dumps(crew_config)
|
|
141
|
+
elif instance.__class__.__name__ == "Task":
|
|
142
|
+
span_attributes["crewai.task.config"] = json.dumps(crew_config)
|
|
143
|
+
|
|
144
|
+
attributes = FrameworkSpanAttributes(**span_attributes)
|
|
145
|
+
|
|
146
|
+
with tracer.start_as_current_span(operation_name, kind=SpanKind.CLIENT) as span:
|
|
147
|
+
_set_input_attributes(span, kwargs, attributes)
|
|
148
|
+
|
|
149
|
+
try:
|
|
150
|
+
result = wrapped(*args, **kwargs)
|
|
151
|
+
if result:
|
|
152
|
+
span.set_status(Status(StatusCode.OK))
|
|
153
|
+
|
|
154
|
+
span.end()
|
|
155
|
+
return result
|
|
156
|
+
|
|
157
|
+
except Exception as err:
|
|
158
|
+
# Record the exception in the span
|
|
159
|
+
span.record_exception(err)
|
|
160
|
+
|
|
161
|
+
# Set the span status to indicate an error
|
|
162
|
+
span.set_status(Status(StatusCode.ERROR, str(err)))
|
|
163
|
+
|
|
164
|
+
# Reraise the exception to ensure it's not swallowed
|
|
165
|
+
raise
|
|
166
|
+
|
|
167
|
+
return traced_method
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
@silently_fail
|
|
171
|
+
def _set_input_attributes(span, kwargs, attributes):
|
|
172
|
+
for field, value in attributes.model_dump(by_alias=True).items():
|
|
173
|
+
set_span_attribute(span, field, value)
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Copyright (c) 2024 Scale3 Labs
|
|
3
|
+
|
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
you may not use this file except in compliance with the License.
|
|
6
|
+
You may obtain a copy of the License at
|
|
7
|
+
|
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
|
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
See the License for the specific language governing permissions and
|
|
14
|
+
limitations under the License.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
|
|
18
|
+
from opentelemetry.trace import get_tracer
|
|
19
|
+
from wrapt import wrap_function_wrapper as _W
|
|
20
|
+
from typing import Collection
|
|
21
|
+
from importlib_metadata import version as v
|
|
22
|
+
from .patch import patch_bootstrapfewshot_optimizer, patch_signature, patch_evaluate
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class DspyInstrumentation(BaseInstrumentor):
|
|
26
|
+
"""
|
|
27
|
+
The DspyInstrumentor class represents the DSPy instrumentation"""
|
|
28
|
+
|
|
29
|
+
def instrumentation_dependencies(self) -> Collection[str]:
|
|
30
|
+
return ["dspy >= 0.1.5"]
|
|
31
|
+
|
|
32
|
+
def _instrument(self, **kwargs):
|
|
33
|
+
tracer_provider = kwargs.get("tracer_provider")
|
|
34
|
+
tracer = get_tracer(__name__, "", tracer_provider)
|
|
35
|
+
version = v("dspy")
|
|
36
|
+
_W(
|
|
37
|
+
"dspy.teleprompt.bootstrap",
|
|
38
|
+
"BootstrapFewShot.compile",
|
|
39
|
+
patch_bootstrapfewshot_optimizer(
|
|
40
|
+
"BootstrapFewShot.compile", version, tracer
|
|
41
|
+
),
|
|
42
|
+
)
|
|
43
|
+
_W(
|
|
44
|
+
"dspy.predict.predict",
|
|
45
|
+
"Predict.forward",
|
|
46
|
+
patch_signature("Predict.forward", version, tracer),
|
|
47
|
+
)
|
|
48
|
+
_W(
|
|
49
|
+
"dspy.predict.chain_of_thought",
|
|
50
|
+
"ChainOfThought.forward",
|
|
51
|
+
patch_signature("ChainOfThought.forward", version, tracer),
|
|
52
|
+
)
|
|
53
|
+
_W(
|
|
54
|
+
"dspy.predict.chain_of_thought_with_hint",
|
|
55
|
+
"ChainOfThoughtWithHint.forward",
|
|
56
|
+
patch_signature("ChainOfThoughtWithHint.forward", version, tracer),
|
|
57
|
+
)
|
|
58
|
+
_W(
|
|
59
|
+
"dspy.predict.react",
|
|
60
|
+
"ReAct.forward",
|
|
61
|
+
patch_signature("ReAct.forward", version, tracer),
|
|
62
|
+
)
|
|
63
|
+
_W(
|
|
64
|
+
"dspy.predict.program_of_thought",
|
|
65
|
+
"ProgramOfThought.forward",
|
|
66
|
+
patch_signature("ProgramOfThought.forward", version, tracer),
|
|
67
|
+
)
|
|
68
|
+
_W(
|
|
69
|
+
"dspy.predict.multi_chain_comparison",
|
|
70
|
+
"MultiChainComparison.forward",
|
|
71
|
+
patch_signature("MultiChainComparison.forward", version, tracer),
|
|
72
|
+
)
|
|
73
|
+
_W(
|
|
74
|
+
"dspy.predict.retry",
|
|
75
|
+
"Retry.forward",
|
|
76
|
+
patch_signature("Retry.forward", version, tracer),
|
|
77
|
+
)
|
|
78
|
+
_W(
|
|
79
|
+
"dspy.evaluate.evaluate",
|
|
80
|
+
"Evaluate.__call__",
|
|
81
|
+
patch_evaluate("Evaluate", version, tracer),
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
def _uninstrument(self, **kwargs):
|
|
85
|
+
pass
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from importlib_metadata import version as v
|
|
3
|
+
from langtrace_python_sdk.constants import LANGTRACE_SDK_NAME
|
|
4
|
+
from langtrace_python_sdk.utils import set_span_attribute
|
|
5
|
+
from langtrace_python_sdk.utils.silently_fail import silently_fail
|
|
6
|
+
from langtrace_python_sdk.constants.instrumentation.common import (
|
|
7
|
+
LANGTRACE_ADDITIONAL_SPAN_ATTRIBUTES_KEY,
|
|
8
|
+
SERVICE_PROVIDERS,
|
|
9
|
+
)
|
|
10
|
+
from opentelemetry import baggage
|
|
11
|
+
from langtrace.trace_attributes import FrameworkSpanAttributes
|
|
12
|
+
from opentelemetry.trace import SpanKind
|
|
13
|
+
from opentelemetry.trace.status import Status, StatusCode
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def patch_bootstrapfewshot_optimizer(operation_name, version, tracer):
|
|
17
|
+
def traced_method(wrapped, instance, args, kwargs):
|
|
18
|
+
|
|
19
|
+
service_provider = SERVICE_PROVIDERS["DSPY"]
|
|
20
|
+
extra_attributes = baggage.get_baggage(LANGTRACE_ADDITIONAL_SPAN_ATTRIBUTES_KEY)
|
|
21
|
+
span_attributes = {
|
|
22
|
+
"langtrace.sdk.name": "langtrace-python-sdk",
|
|
23
|
+
"langtrace.service.name": service_provider,
|
|
24
|
+
"langtrace.service.type": "framework",
|
|
25
|
+
"langtrace.service.version": version,
|
|
26
|
+
"langtrace.version": v(LANGTRACE_SDK_NAME),
|
|
27
|
+
**(extra_attributes if extra_attributes is not None else {}),
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if instance.__class__.__name__:
|
|
31
|
+
span_attributes["dspy.optimizer"] = instance.__class__.__name__
|
|
32
|
+
if len(args) > 0:
|
|
33
|
+
span_attributes["dspy.optimizer.module"] = args[0].__class__.__name__
|
|
34
|
+
if args[0].prog:
|
|
35
|
+
prog = {
|
|
36
|
+
"name": args[0].prog.__class__.__name__,
|
|
37
|
+
"signature": str(args[0].prog.signature) if args[0].prog.signature else None,
|
|
38
|
+
}
|
|
39
|
+
span_attributes["dspy.optimizer.module.prog"] = json.dumps(prog)
|
|
40
|
+
if "metric" in instance and instance.metric:
|
|
41
|
+
span_attributes["dspy.optimizer.metric"] = instance.metric.__name__
|
|
42
|
+
if kwargs.get("trainset") and len(kwargs.get("trainset")) > 0:
|
|
43
|
+
span_attributes["dspy.optimizer.trainset"] = str(kwargs.get("trainset"))
|
|
44
|
+
config = {}
|
|
45
|
+
if "metric_threshold" in instance and instance.metric_threshold:
|
|
46
|
+
config["metric_threshold"] = instance.metric_threshold
|
|
47
|
+
if "teacher_settings" in instance and instance.teacher_settings:
|
|
48
|
+
config["teacher_settings"] = instance.teacher_settings
|
|
49
|
+
if "max_bootstrapped_demos" in instance and instance.max_bootstrapped_demos:
|
|
50
|
+
config["max_bootstrapped_demos"] = instance.max_bootstrapped_demos
|
|
51
|
+
if "max_labeled_demos" in instance and instance.max_labeled_demos:
|
|
52
|
+
config["max_labeled_demos"] = instance.max_labeled_demos
|
|
53
|
+
if "max_rounds" in instance and instance.max_rounds:
|
|
54
|
+
config["max_rounds"] = instance.max_rounds
|
|
55
|
+
if "max_errors" in instance and instance.max_errors:
|
|
56
|
+
config["max_errors"] = instance.max_errors
|
|
57
|
+
if "error_count" in instance and instance.error_count:
|
|
58
|
+
config["error_count"] = instance.error_count
|
|
59
|
+
if config and len(config) > 0:
|
|
60
|
+
span_attributes["dspy.optimizer.config"] = json.dumps(config)
|
|
61
|
+
|
|
62
|
+
attributes = FrameworkSpanAttributes(**span_attributes)
|
|
63
|
+
with tracer.start_as_current_span(
|
|
64
|
+
operation_name, kind=SpanKind.CLIENT
|
|
65
|
+
) as span:
|
|
66
|
+
_set_input_attributes(span, kwargs, attributes)
|
|
67
|
+
|
|
68
|
+
try:
|
|
69
|
+
result = wrapped(*args, **kwargs)
|
|
70
|
+
if result:
|
|
71
|
+
span.set_status(Status(StatusCode.OK))
|
|
72
|
+
|
|
73
|
+
span.end()
|
|
74
|
+
return result
|
|
75
|
+
|
|
76
|
+
except Exception as err:
|
|
77
|
+
# Record the exception in the span
|
|
78
|
+
span.record_exception(err)
|
|
79
|
+
|
|
80
|
+
# Set the span status to indicate an error
|
|
81
|
+
span.set_status(Status(StatusCode.ERROR, str(err)))
|
|
82
|
+
|
|
83
|
+
# Reraise the exception to ensure it's not swallowed
|
|
84
|
+
raise
|
|
85
|
+
|
|
86
|
+
return traced_method
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def patch_signature(operation_name, version, tracer):
|
|
90
|
+
def traced_method(wrapped, instance, args, kwargs):
|
|
91
|
+
|
|
92
|
+
service_provider = SERVICE_PROVIDERS["DSPY"]
|
|
93
|
+
extra_attributes = baggage.get_baggage(LANGTRACE_ADDITIONAL_SPAN_ATTRIBUTES_KEY)
|
|
94
|
+
span_attributes = {
|
|
95
|
+
"langtrace.sdk.name": "langtrace-python-sdk",
|
|
96
|
+
"langtrace.service.name": service_provider,
|
|
97
|
+
"langtrace.service.type": "framework",
|
|
98
|
+
"langtrace.service.version": version,
|
|
99
|
+
"langtrace.version": v(LANGTRACE_SDK_NAME),
|
|
100
|
+
**(extra_attributes if extra_attributes is not None else {}),
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if instance.__class__.__name__:
|
|
104
|
+
span_attributes["dspy.signature.name"] = instance.__class__.__name__
|
|
105
|
+
span_attributes["dspy.signature"] = str(instance)
|
|
106
|
+
|
|
107
|
+
if kwargs and len(kwargs) > 0:
|
|
108
|
+
span_attributes["dspy.signature.args"] = str(kwargs)
|
|
109
|
+
|
|
110
|
+
attributes = FrameworkSpanAttributes(**span_attributes)
|
|
111
|
+
with tracer.start_as_current_span(
|
|
112
|
+
operation_name, kind=SpanKind.CLIENT
|
|
113
|
+
) as span:
|
|
114
|
+
_set_input_attributes(span, kwargs, attributes)
|
|
115
|
+
|
|
116
|
+
try:
|
|
117
|
+
result = wrapped(*args, **kwargs)
|
|
118
|
+
if result:
|
|
119
|
+
set_span_attribute(span, "dspy.signature.result", str(result))
|
|
120
|
+
span.set_status(Status(StatusCode.OK))
|
|
121
|
+
|
|
122
|
+
span.end()
|
|
123
|
+
return result
|
|
124
|
+
|
|
125
|
+
except Exception as err:
|
|
126
|
+
# Record the exception in the span
|
|
127
|
+
span.record_exception(err)
|
|
128
|
+
|
|
129
|
+
# Set the span status to indicate an error
|
|
130
|
+
span.set_status(Status(StatusCode.ERROR, str(err)))
|
|
131
|
+
|
|
132
|
+
# Reraise the exception to ensure it's not swallowed
|
|
133
|
+
raise
|
|
134
|
+
|
|
135
|
+
return traced_method
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def patch_evaluate(operation_name, version, tracer):
|
|
139
|
+
def traced_method(wrapped, instance, args, kwargs):
|
|
140
|
+
|
|
141
|
+
service_provider = SERVICE_PROVIDERS["DSPY"]
|
|
142
|
+
extra_attributes = baggage.get_baggage(LANGTRACE_ADDITIONAL_SPAN_ATTRIBUTES_KEY)
|
|
143
|
+
span_attributes = {
|
|
144
|
+
"langtrace.sdk.name": "langtrace-python-sdk",
|
|
145
|
+
"langtrace.service.name": service_provider,
|
|
146
|
+
"langtrace.service.type": "framework",
|
|
147
|
+
"langtrace.service.version": version,
|
|
148
|
+
"langtrace.version": v(LANGTRACE_SDK_NAME),
|
|
149
|
+
**(extra_attributes if extra_attributes is not None else {}),
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
if "devset" in instance and instance.devset is not None:
|
|
153
|
+
span_attributes["dspy.evaluate.devset"] = str(instance.devset)
|
|
154
|
+
if "display" in instance and instance.display is not None:
|
|
155
|
+
span_attributes["dspy.evaluate.display"] = str(instance.display)
|
|
156
|
+
if "num_threads" in instance and instance.num_threads is not None:
|
|
157
|
+
span_attributes["dspy.evaluate.num_threads"] = str(instance.num_threads)
|
|
158
|
+
if "return_outputs" in instance and instance.return_outputs is not None:
|
|
159
|
+
span_attributes["dspy.evaluate.return_outputs"] = str(instance.return_outputs)
|
|
160
|
+
if "display_table" in instance and instance.display_table is not None:
|
|
161
|
+
span_attributes["dspy.evaluate.display_table"] = str(instance.display_table)
|
|
162
|
+
if "display_progress" in instance and instance.display_progress is not None:
|
|
163
|
+
span_attributes["dspy.evaluate.display_progress"] = str(instance.display_progress)
|
|
164
|
+
if "metric" in instance and instance.metric is not None:
|
|
165
|
+
span_attributes["dspy.evaluate.metric"] = instance.metric.__name__
|
|
166
|
+
if "error_count" in instance and instance.error_count is not None:
|
|
167
|
+
span_attributes["dspy.evaluate.error_count"] = str(instance.error_count)
|
|
168
|
+
if "error_lock" in instance and instance.error_lock is not None:
|
|
169
|
+
span_attributes["dspy.evaluate.error_lock"] = str(instance.error_lock)
|
|
170
|
+
if "max_errors" in instance and instance.max_errors is not None:
|
|
171
|
+
span_attributes["dspy.evaluate.max_errors"] = str(instance.max_errors)
|
|
172
|
+
if args and len(args) > 0:
|
|
173
|
+
span_attributes["dspy.evaluate.args"] = str(args)
|
|
174
|
+
|
|
175
|
+
attributes = FrameworkSpanAttributes(**span_attributes)
|
|
176
|
+
with tracer.start_as_current_span(
|
|
177
|
+
operation_name, kind=SpanKind.CLIENT
|
|
178
|
+
) as span:
|
|
179
|
+
_set_input_attributes(span, kwargs, attributes)
|
|
180
|
+
|
|
181
|
+
try:
|
|
182
|
+
result = wrapped(*args, **kwargs)
|
|
183
|
+
if result is not None:
|
|
184
|
+
set_span_attribute(span, "dspy.evaluate.result", str(result))
|
|
185
|
+
span.set_status(Status(StatusCode.OK))
|
|
186
|
+
|
|
187
|
+
span.end()
|
|
188
|
+
return result
|
|
189
|
+
|
|
190
|
+
except Exception as err:
|
|
191
|
+
# Record the exception in the span
|
|
192
|
+
span.record_exception(err)
|
|
193
|
+
|
|
194
|
+
# Set the span status to indicate an error
|
|
195
|
+
span.set_status(Status(StatusCode.ERROR, str(err)))
|
|
196
|
+
|
|
197
|
+
# Reraise the exception to ensure it's not swallowed
|
|
198
|
+
raise
|
|
199
|
+
|
|
200
|
+
return traced_method
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
@silently_fail
|
|
204
|
+
def _set_input_attributes(span, kwargs, attributes):
|
|
205
|
+
for field, value in attributes.model_dump(by_alias=True).items():
|
|
206
|
+
set_span_attribute(span, field, value)
|
|
@@ -275,6 +275,110 @@ def images_edit(original_method, version, tracer):
|
|
|
275
275
|
return traced_method
|
|
276
276
|
|
|
277
277
|
|
|
278
|
+
class StreamWrapper:
|
|
279
|
+
def __init__(self, stream, span, prompt_tokens, function_call=False, tool_calls=False):
|
|
280
|
+
self.stream = stream
|
|
281
|
+
self.span = span
|
|
282
|
+
self.prompt_tokens = prompt_tokens
|
|
283
|
+
self.function_call = function_call
|
|
284
|
+
self.tool_calls = tool_calls
|
|
285
|
+
self.result_content = []
|
|
286
|
+
self.completion_tokens = 0
|
|
287
|
+
|
|
288
|
+
def __enter__(self):
|
|
289
|
+
self.span.add_event(Event.STREAM_START.value)
|
|
290
|
+
return self
|
|
291
|
+
|
|
292
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
293
|
+
self.span.add_event(Event.STREAM_END.value)
|
|
294
|
+
self.span.set_attribute(
|
|
295
|
+
"llm.token.counts",
|
|
296
|
+
json.dumps(
|
|
297
|
+
{
|
|
298
|
+
"input_tokens": self.prompt_tokens,
|
|
299
|
+
"output_tokens": self.completion_tokens,
|
|
300
|
+
"total_tokens": self.prompt_tokens + self.completion_tokens,
|
|
301
|
+
}
|
|
302
|
+
),
|
|
303
|
+
)
|
|
304
|
+
self.span.set_attribute(
|
|
305
|
+
"llm.responses",
|
|
306
|
+
json.dumps(
|
|
307
|
+
[
|
|
308
|
+
{
|
|
309
|
+
"role": "assistant",
|
|
310
|
+
"content": "".join(self.result_content),
|
|
311
|
+
}
|
|
312
|
+
]
|
|
313
|
+
),
|
|
314
|
+
)
|
|
315
|
+
self.span.set_status(StatusCode.OK)
|
|
316
|
+
self.span.end()
|
|
317
|
+
|
|
318
|
+
def __iter__(self):
|
|
319
|
+
return self
|
|
320
|
+
|
|
321
|
+
def __next__(self):
|
|
322
|
+
try:
|
|
323
|
+
chunk = next(self.stream)
|
|
324
|
+
self.process_chunk(chunk)
|
|
325
|
+
return chunk
|
|
326
|
+
except StopIteration:
|
|
327
|
+
raise
|
|
328
|
+
|
|
329
|
+
def process_chunk(self, chunk):
|
|
330
|
+
if hasattr(chunk, "model") and chunk.model is not None:
|
|
331
|
+
self.span.set_attribute("llm.model", chunk.model)
|
|
332
|
+
if hasattr(chunk, "choices") and chunk.choices is not None:
|
|
333
|
+
content = []
|
|
334
|
+
if not self.function_call and not self.tool_calls:
|
|
335
|
+
for choice in chunk.choices:
|
|
336
|
+
if choice.delta and choice.delta.content is not None:
|
|
337
|
+
token_counts = estimate_tokens(choice.delta.content)
|
|
338
|
+
self.completion_tokens += token_counts
|
|
339
|
+
content = [choice.delta.content]
|
|
340
|
+
elif self.function_call:
|
|
341
|
+
for choice in chunk.choices:
|
|
342
|
+
if (
|
|
343
|
+
choice.delta
|
|
344
|
+
and choice.delta.function_call is not None
|
|
345
|
+
and choice.delta.function_call.arguments is not None
|
|
346
|
+
):
|
|
347
|
+
token_counts = estimate_tokens(
|
|
348
|
+
choice.delta.function_call.arguments
|
|
349
|
+
)
|
|
350
|
+
self.completion_tokens += token_counts
|
|
351
|
+
content = [choice.delta.function_call.arguments]
|
|
352
|
+
elif self.tool_calls:
|
|
353
|
+
for choice in chunk.choices:
|
|
354
|
+
if choice.delta and choice.delta.tool_calls is not None:
|
|
355
|
+
toolcalls = choice.delta.tool_calls
|
|
356
|
+
content = []
|
|
357
|
+
for tool_call in toolcalls:
|
|
358
|
+
if (
|
|
359
|
+
tool_call
|
|
360
|
+
and tool_call.function is not None
|
|
361
|
+
and tool_call.function.arguments is not None
|
|
362
|
+
):
|
|
363
|
+
token_counts = estimate_tokens(
|
|
364
|
+
tool_call.function.arguments
|
|
365
|
+
)
|
|
366
|
+
self.completion_tokens += token_counts
|
|
367
|
+
content.append(tool_call.function.arguments)
|
|
368
|
+
self.span.add_event(
|
|
369
|
+
Event.STREAM_OUTPUT.value,
|
|
370
|
+
{
|
|
371
|
+
"response": (
|
|
372
|
+
"".join(content)
|
|
373
|
+
if len(content) > 0 and content[0] is not None
|
|
374
|
+
else ""
|
|
375
|
+
)
|
|
376
|
+
},
|
|
377
|
+
)
|
|
378
|
+
if content:
|
|
379
|
+
self.result_content.append(content[0])
|
|
380
|
+
|
|
381
|
+
|
|
278
382
|
def chat_completions_create(original_method, version, tracer):
|
|
279
383
|
"""Wrap the `create` method of the `ChatCompletion` class to trace it."""
|
|
280
384
|
|
|
@@ -427,7 +531,7 @@ def chat_completions_create(original_method, version, tracer):
|
|
|
427
531
|
json.dumps(function), kwargs.get("model")
|
|
428
532
|
)
|
|
429
533
|
|
|
430
|
-
return
|
|
534
|
+
return StreamWrapper(
|
|
431
535
|
result,
|
|
432
536
|
span,
|
|
433
537
|
prompt_tokens,
|
|
@@ -441,98 +545,6 @@ def chat_completions_create(original_method, version, tracer):
|
|
|
441
545
|
span.end()
|
|
442
546
|
raise
|
|
443
547
|
|
|
444
|
-
def handle_streaming_response(
|
|
445
|
-
result, span, prompt_tokens, function_call=False, tool_calls=False
|
|
446
|
-
):
|
|
447
|
-
"""Process and yield streaming response chunks."""
|
|
448
|
-
result_content = []
|
|
449
|
-
span.add_event(Event.STREAM_START.value)
|
|
450
|
-
completion_tokens = 0
|
|
451
|
-
try:
|
|
452
|
-
for chunk in result:
|
|
453
|
-
if hasattr(chunk, "model") and chunk.model is not None:
|
|
454
|
-
span.set_attribute("llm.model", chunk.model)
|
|
455
|
-
if hasattr(chunk, "choices") and chunk.choices is not None:
|
|
456
|
-
if not function_call and not tool_calls:
|
|
457
|
-
for choice in chunk.choices:
|
|
458
|
-
if choice.delta and choice.delta.content is not None:
|
|
459
|
-
token_counts = estimate_tokens(choice.delta.content)
|
|
460
|
-
completion_tokens += token_counts
|
|
461
|
-
content = [choice.delta.content]
|
|
462
|
-
elif function_call:
|
|
463
|
-
for choice in chunk.choices:
|
|
464
|
-
if (
|
|
465
|
-
choice.delta
|
|
466
|
-
and choice.delta.function_call is not None
|
|
467
|
-
and choice.delta.function_call.arguments is not None
|
|
468
|
-
):
|
|
469
|
-
token_counts = estimate_tokens(
|
|
470
|
-
choice.delta.function_call.arguments
|
|
471
|
-
)
|
|
472
|
-
completion_tokens += token_counts
|
|
473
|
-
content = [choice.delta.function_call.arguments]
|
|
474
|
-
elif tool_calls:
|
|
475
|
-
for choice in chunk.choices:
|
|
476
|
-
tool_call = ""
|
|
477
|
-
if choice.delta and choice.delta.tool_calls is not None:
|
|
478
|
-
toolcalls = choice.delta.tool_calls
|
|
479
|
-
content = []
|
|
480
|
-
for tool_call in toolcalls:
|
|
481
|
-
if (
|
|
482
|
-
tool_call
|
|
483
|
-
and tool_call.function is not None
|
|
484
|
-
and tool_call.function.arguments is not None
|
|
485
|
-
):
|
|
486
|
-
token_counts = estimate_tokens(
|
|
487
|
-
tool_call.function.arguments
|
|
488
|
-
)
|
|
489
|
-
completion_tokens += token_counts
|
|
490
|
-
content = content + [
|
|
491
|
-
tool_call.function.arguments
|
|
492
|
-
]
|
|
493
|
-
else:
|
|
494
|
-
content = content + []
|
|
495
|
-
else:
|
|
496
|
-
content = []
|
|
497
|
-
span.add_event(
|
|
498
|
-
Event.STREAM_OUTPUT.value,
|
|
499
|
-
{
|
|
500
|
-
"response": (
|
|
501
|
-
"".join(content)
|
|
502
|
-
if len(content) > 0 and content[0] is not None
|
|
503
|
-
else ""
|
|
504
|
-
)
|
|
505
|
-
},
|
|
506
|
-
)
|
|
507
|
-
result_content.append(content[0] if len(content) > 0 else "")
|
|
508
|
-
yield chunk
|
|
509
|
-
finally:
|
|
510
|
-
# Finalize span after processing all chunks
|
|
511
|
-
span.add_event(Event.STREAM_END.value)
|
|
512
|
-
span.set_attribute(
|
|
513
|
-
"llm.token.counts",
|
|
514
|
-
json.dumps(
|
|
515
|
-
{
|
|
516
|
-
"input_tokens": prompt_tokens,
|
|
517
|
-
"output_tokens": completion_tokens,
|
|
518
|
-
"total_tokens": prompt_tokens + completion_tokens,
|
|
519
|
-
}
|
|
520
|
-
),
|
|
521
|
-
)
|
|
522
|
-
span.set_attribute(
|
|
523
|
-
"llm.responses",
|
|
524
|
-
json.dumps(
|
|
525
|
-
[
|
|
526
|
-
{
|
|
527
|
-
"role": "assistant",
|
|
528
|
-
"content": "".join(result_content),
|
|
529
|
-
}
|
|
530
|
-
]
|
|
531
|
-
),
|
|
532
|
-
)
|
|
533
|
-
span.set_status(StatusCode.OK)
|
|
534
|
-
span.end()
|
|
535
|
-
|
|
536
548
|
# return the wrapped method
|
|
537
549
|
return traced_method
|
|
538
550
|
|
|
@@ -687,7 +699,7 @@ def async_chat_completions_create(original_method, version, tracer):
|
|
|
687
699
|
json.dumps(function), kwargs.get("model")
|
|
688
700
|
)
|
|
689
701
|
|
|
690
|
-
return
|
|
702
|
+
return StreamWrapper(
|
|
691
703
|
result,
|
|
692
704
|
span,
|
|
693
705
|
prompt_tokens,
|
|
@@ -701,99 +713,6 @@ def async_chat_completions_create(original_method, version, tracer):
|
|
|
701
713
|
span.end()
|
|
702
714
|
raise
|
|
703
715
|
|
|
704
|
-
async def ahandle_streaming_response(
|
|
705
|
-
result, span, prompt_tokens, function_call=False, tool_calls=False
|
|
706
|
-
):
|
|
707
|
-
"""Process and yield streaming response chunks."""
|
|
708
|
-
result_content = []
|
|
709
|
-
span.add_event(Event.STREAM_START.value)
|
|
710
|
-
completion_tokens = 0
|
|
711
|
-
try:
|
|
712
|
-
content = []
|
|
713
|
-
async for chunk in result:
|
|
714
|
-
if hasattr(chunk, "model") and chunk.model is not None:
|
|
715
|
-
span.set_attribute("llm.model", chunk.model)
|
|
716
|
-
if hasattr(chunk, "choices") and chunk.choices is not None:
|
|
717
|
-
if not function_call and not tool_calls:
|
|
718
|
-
for choice in chunk.choices:
|
|
719
|
-
if choice.delta and choice.delta.content is not None:
|
|
720
|
-
token_counts = estimate_tokens(choice.delta.content)
|
|
721
|
-
completion_tokens += token_counts
|
|
722
|
-
content = [choice.delta.content]
|
|
723
|
-
elif function_call:
|
|
724
|
-
for choice in chunk.choices:
|
|
725
|
-
if (
|
|
726
|
-
choice.delta
|
|
727
|
-
and choice.delta.function_call
|
|
728
|
-
and choice.delta.function_call.arguments is not None
|
|
729
|
-
):
|
|
730
|
-
token_counts = estimate_tokens(
|
|
731
|
-
choice.delta.function_call.arguments
|
|
732
|
-
)
|
|
733
|
-
completion_tokens += token_counts
|
|
734
|
-
content = [choice.delta.function_call.arguments]
|
|
735
|
-
elif tool_calls:
|
|
736
|
-
for choice in chunk.choices:
|
|
737
|
-
tool_call = ""
|
|
738
|
-
if choice.delta and choice.delta.tool_calls is not None:
|
|
739
|
-
toolcalls = choice.delta.tool_calls
|
|
740
|
-
content = []
|
|
741
|
-
for tool_call in toolcalls:
|
|
742
|
-
if (
|
|
743
|
-
tool_call
|
|
744
|
-
and tool_call.function is not None
|
|
745
|
-
and tool_call.function.arguments is not None
|
|
746
|
-
):
|
|
747
|
-
token_counts = estimate_tokens(
|
|
748
|
-
tool_call.function.arguments
|
|
749
|
-
)
|
|
750
|
-
completion_tokens += token_counts
|
|
751
|
-
content = content + [
|
|
752
|
-
tool_call.function.arguments
|
|
753
|
-
]
|
|
754
|
-
else:
|
|
755
|
-
content = content + []
|
|
756
|
-
else:
|
|
757
|
-
content = []
|
|
758
|
-
span.add_event(
|
|
759
|
-
Event.STREAM_OUTPUT.value,
|
|
760
|
-
{
|
|
761
|
-
"response": (
|
|
762
|
-
"".join(content)
|
|
763
|
-
if len(content) > 0 and content[0] is not None
|
|
764
|
-
else ""
|
|
765
|
-
)
|
|
766
|
-
},
|
|
767
|
-
)
|
|
768
|
-
result_content.append(content[0] if len(content) > 0 else "")
|
|
769
|
-
yield chunk
|
|
770
|
-
finally:
|
|
771
|
-
# Finalize span after processing all chunks
|
|
772
|
-
span.add_event(Event.STREAM_END.value)
|
|
773
|
-
span.set_attribute(
|
|
774
|
-
"llm.token.counts",
|
|
775
|
-
json.dumps(
|
|
776
|
-
{
|
|
777
|
-
"input_tokens": prompt_tokens,
|
|
778
|
-
"output_tokens": completion_tokens,
|
|
779
|
-
"total_tokens": prompt_tokens + completion_tokens,
|
|
780
|
-
}
|
|
781
|
-
),
|
|
782
|
-
)
|
|
783
|
-
span.set_attribute(
|
|
784
|
-
"llm.responses",
|
|
785
|
-
json.dumps(
|
|
786
|
-
[
|
|
787
|
-
{
|
|
788
|
-
"role": "assistant",
|
|
789
|
-
"content": "".join(result_content),
|
|
790
|
-
}
|
|
791
|
-
]
|
|
792
|
-
),
|
|
793
|
-
)
|
|
794
|
-
span.set_status(StatusCode.OK)
|
|
795
|
-
span.end()
|
|
796
|
-
|
|
797
716
|
# return the wrapped method
|
|
798
717
|
return traced_method
|
|
799
718
|
|
|
@@ -40,6 +40,7 @@ from langtrace_python_sdk.instrumentation import (
|
|
|
40
40
|
AnthropicInstrumentation,
|
|
41
41
|
ChromaInstrumentation,
|
|
42
42
|
CohereInstrumentation,
|
|
43
|
+
CrewAIInstrumentation,
|
|
43
44
|
GroqInstrumentation,
|
|
44
45
|
LangchainInstrumentation,
|
|
45
46
|
LangchainCommunityInstrumentation,
|
|
@@ -51,6 +52,7 @@ from langtrace_python_sdk.instrumentation import (
|
|
|
51
52
|
QdrantInstrumentation,
|
|
52
53
|
WeaviateInstrumentation,
|
|
53
54
|
OllamaInstrumentor,
|
|
55
|
+
DspyInstrumentation,
|
|
54
56
|
)
|
|
55
57
|
from opentelemetry.instrumentation.sqlalchemy import SQLAlchemyInstrumentor
|
|
56
58
|
from colorama import Fore
|
|
@@ -108,6 +110,8 @@ def init(
|
|
|
108
110
|
"weaviate": WeaviateInstrumentation(),
|
|
109
111
|
"sqlalchemy": SQLAlchemyInstrumentor(),
|
|
110
112
|
"ollama": OllamaInstrumentor(),
|
|
113
|
+
"dspy": DspyInstrumentation(),
|
|
114
|
+
"crewai": CrewAIInstrumentation(),
|
|
111
115
|
}
|
|
112
116
|
|
|
113
117
|
init_instrumentations(disable_instrumentations, all_instrumentations)
|
langtrace_python_sdk/version.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "2.1.
|
|
1
|
+
__version__ = "2.1.22"
|
|
@@ -9,6 +9,11 @@ examples/cohere_example/chat_stream.py,sha256=daWGrj2yucN9sWKGiPzTw18clh23Grv-MI
|
|
|
9
9
|
examples/cohere_example/embed.py,sha256=p9BJvOg09JVb8BfTCb63v3uh_wOsi_OyrCAJdXXrE6E,496
|
|
10
10
|
examples/cohere_example/rerank.py,sha256=e7OU0A2FzfiQDuOmCy3Kg5LLNYGRmRIK5LqeLnTWlP4,1118
|
|
11
11
|
examples/cohere_example/tools.py,sha256=a5uvS058tcwU6PJbF9EDO6LPVmPj2LoW4Vn8Web3Iq8,1656
|
|
12
|
+
examples/crewai_example/basic.py,sha256=PBu4f8yQfZO1L_22UDm_ReU9lnEcycjZcGuy5UpgDJM,1948
|
|
13
|
+
examples/dspy_example/math_problems_cot.py,sha256=Z98nB6myt8WJse2dWS6Ap7CFUhC27lBNb37R1Gg80VQ,1282
|
|
14
|
+
examples/dspy_example/program_of_thought_basic.py,sha256=oEbtJdeKENMUbex25-zyStWwurRWW6OdP0KDs-jUkko,984
|
|
15
|
+
examples/dspy_example/quiz_gen.py,sha256=OyGhepeX8meKOtLdmlYUjMD2ECk-ZQuQXUZif1hFQY4,3371
|
|
16
|
+
examples/dspy_example/react.py,sha256=dmhO6AyO5K3w0WNkwe-Usd2cIgVmEPoWzusrLxXIfPo,1340
|
|
12
17
|
examples/fastapi_example/__init__.py,sha256=INIfvJP7zC_KkJCtulS1qbh61-MJTPAHnzAgzeKi0yU,87
|
|
13
18
|
examples/fastapi_example/basic_route.py,sha256=_IRXjkOtJQ-bTIGa1WbvUF_2LF4bjghjyXt4YrHaRvw,1170
|
|
14
19
|
examples/hiveagent_example/basic.py,sha256=Sd7I5w8w5Xx7ODaydTY30yiq9HwJDMKHQywrZjgehP0,441
|
|
@@ -45,15 +50,15 @@ examples/qdrant_example/basic.py,sha256=DCMjHSuBZKkhEjCkwy5d5La9WMyW0lCWqtcZWiFC
|
|
|
45
50
|
examples/weaviate_example/__init__.py,sha256=8JMDBsRSEV10HfTd-YC7xb4txBjD3la56snk-Bbg2Kw,618
|
|
46
51
|
examples/weaviate_example/query_text.py,sha256=qz9o-fTDzX5AW5m8BJF-TfmBdokxh492NfnmnPUMU3s,64814
|
|
47
52
|
langtrace_python_sdk/__init__.py,sha256=VZM6i71NR7pBQK6XvJWRelknuTYUhqwqE7PlicKa5Wg,1166
|
|
48
|
-
langtrace_python_sdk/langtrace.py,sha256=
|
|
49
|
-
langtrace_python_sdk/version.py,sha256=
|
|
53
|
+
langtrace_python_sdk/langtrace.py,sha256=pG_dWzzQxUP8r5SAMUwRScb6IopINcda1CZvJERjXBo,7486
|
|
54
|
+
langtrace_python_sdk/version.py,sha256=8X_w-VRCyU1lQMWejIqkf5tmhnrgO7csLi27xV88LJs,23
|
|
50
55
|
langtrace_python_sdk/constants/__init__.py,sha256=P8QvYwt5czUNDZsKS64vxm9Dc41ptGbuF1TFtAF6nv4,44
|
|
51
56
|
langtrace_python_sdk/constants/exporter/langtrace_exporter.py,sha256=5MNjnAOg-4am78J3gVMH6FSwq5N8TOj72ugkhsw4vi0,46
|
|
52
57
|
langtrace_python_sdk/constants/instrumentation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
53
58
|
langtrace_python_sdk/constants/instrumentation/anthropic.py,sha256=YX3llt3zwDY6XrYk3CB8WEVqgrzRXEw_ffyk56JoF3k,126
|
|
54
59
|
langtrace_python_sdk/constants/instrumentation/chroma.py,sha256=hiPGYdHS0Yj4Kh3eaYBbuCAl_swqIygu80yFqkOgdak,955
|
|
55
60
|
langtrace_python_sdk/constants/instrumentation/cohere.py,sha256=tf9sDfb5K3qOAHChEE5o8eYWPZ1io58VsOjZDCZPxfw,577
|
|
56
|
-
langtrace_python_sdk/constants/instrumentation/common.py,sha256=
|
|
61
|
+
langtrace_python_sdk/constants/instrumentation/common.py,sha256=KodH_uGGjWGGP8rqTi7Ua-osjUwtPKslx69DJRbDiT4,850
|
|
57
62
|
langtrace_python_sdk/constants/instrumentation/groq.py,sha256=VFXmIl4aqGY_fS0PAmjPj_Qm7Tibxbx7Ur_e7rQpqXc,134
|
|
58
63
|
langtrace_python_sdk/constants/instrumentation/ollama.py,sha256=zFfSUKX5v1c612doKSxsmIwQeeQxSPkFp_ZzjWQSPNE,142
|
|
59
64
|
langtrace_python_sdk/constants/instrumentation/openai.py,sha256=uEOH5UXapU2DSf2AdgXTRhhJEHGWXUNFkUGD5QafflM,1164
|
|
@@ -63,7 +68,7 @@ langtrace_python_sdk/constants/instrumentation/weaviate.py,sha256=Iytf2OpB_irZYE
|
|
|
63
68
|
langtrace_python_sdk/extensions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
64
69
|
langtrace_python_sdk/extensions/langtrace_exporter.py,sha256=gWVRU2DlB4xjZ4ww7M63DaLiAN5zQ2k1HPrythmjEdo,4202
|
|
65
70
|
langtrace_python_sdk/extensions/langtrace_filesystem.py,sha256=qpnkpkuTZ2yhGgpBK64QJLt0T1iL-1zpEMPz4quJ_ng,6925
|
|
66
|
-
langtrace_python_sdk/instrumentation/__init__.py,sha256=
|
|
71
|
+
langtrace_python_sdk/instrumentation/__init__.py,sha256=BYTzQSmHDbKAbtV98UDjxzV1UoNq_wtsWV7V4PZPzbc,1243
|
|
67
72
|
langtrace_python_sdk/instrumentation/anthropic/__init__.py,sha256=donrurJAGYlxrSRA3BIf76jGeUcAx9Tq8CVpah68S0Y,101
|
|
68
73
|
langtrace_python_sdk/instrumentation/anthropic/instrumentation.py,sha256=-srgE8qumAn0ulQYZxMa8ch-9IBH0XgBW_rfEnGk6LI,1684
|
|
69
74
|
langtrace_python_sdk/instrumentation/anthropic/patch.py,sha256=52GRkW7fhF2VB9JvYGMaPwOvWH3Q5rsIEaVlnFm_Zz0,8548
|
|
@@ -73,6 +78,12 @@ langtrace_python_sdk/instrumentation/chroma/patch.py,sha256=HhIkXGbVfzpEB4edxzlG
|
|
|
73
78
|
langtrace_python_sdk/instrumentation/cohere/__init__.py,sha256=sGUSLdTUyYf36Tm6L5jQflhzCqvmWrhnBOMYHjvp6Hs,95
|
|
74
79
|
langtrace_python_sdk/instrumentation/cohere/instrumentation.py,sha256=YQFHZIBd7SSPD4b6Va-ZR0thf_AuBCqj5yzHLHJVWnM,2121
|
|
75
80
|
langtrace_python_sdk/instrumentation/cohere/patch.py,sha256=uGjZm_c1-xpZilHD8ljGr4AqQB3UNU04SKl9s2alGzs,26726
|
|
81
|
+
langtrace_python_sdk/instrumentation/crewai/__init__.py,sha256=_UBKfvQv7l0g2_wnmA5F6CdSAFH0atNOVPd49zsN3aM,88
|
|
82
|
+
langtrace_python_sdk/instrumentation/crewai/instrumentation.py,sha256=W8PLTLzgEdrEx1DCo79wNs9xcuWK0YuxEICLavOESDw,1715
|
|
83
|
+
langtrace_python_sdk/instrumentation/crewai/patch.py,sha256=Vnpip9Pbk4UFbTFHoUrHtAnDgsaihwSvZBgtUeOtLr8,6109
|
|
84
|
+
langtrace_python_sdk/instrumentation/dspy/__init__.py,sha256=tM1srfi_QgyCzrde4izojMrRq2Wm7Dj5QUvVQXIJzkk,84
|
|
85
|
+
langtrace_python_sdk/instrumentation/dspy/instrumentation.py,sha256=Y-_qcH5jCT4TbGvci6Iw0_OWUUlCmovMxnysj6NCnXI,2923
|
|
86
|
+
langtrace_python_sdk/instrumentation/dspy/patch.py,sha256=0zBlrzvGmQEhJpb44L8fkTIhMH5i5pWOkYoSH9e8D6U,9216
|
|
76
87
|
langtrace_python_sdk/instrumentation/groq/__init__.py,sha256=ZXeq_nrej6Lm_uoMFEg8wbSejhjB2UJ5IoHQBPc2-C0,91
|
|
77
88
|
langtrace_python_sdk/instrumentation/groq/instrumentation.py,sha256=Ttf07XVKhdYY1_fqJc7QWiSdmgEhEVyQB_3Az2_wqYo,1832
|
|
78
89
|
langtrace_python_sdk/instrumentation/groq/patch.py,sha256=EKH9tjoDbwWavIAwUadaR5tFiy-S69h1IxxzH_1SSRg,26354
|
|
@@ -96,7 +107,7 @@ langtrace_python_sdk/instrumentation/ollama/instrumentation.py,sha256=jdsvkqUJAA
|
|
|
96
107
|
langtrace_python_sdk/instrumentation/ollama/patch.py,sha256=CGLgt0qZg3WDr6XLn32qqs4D9USdMmeTmJxctbAsDeM,7908
|
|
97
108
|
langtrace_python_sdk/instrumentation/openai/__init__.py,sha256=VPHRNCQEdkizIVP2d0Uw_a7t8XOTSTprEIB8oboJFbs,95
|
|
98
109
|
langtrace_python_sdk/instrumentation/openai/instrumentation.py,sha256=A0BJHRLcZ74TNVg6I0I9M5YWvSpAtXwMmME6N5CEQ_M,2945
|
|
99
|
-
langtrace_python_sdk/instrumentation/openai/patch.py,sha256
|
|
110
|
+
langtrace_python_sdk/instrumentation/openai/patch.py,sha256=-eKopJp6m56mg4553wrDr0ibGoCPpYH2iyNMh1lX9yc,36526
|
|
100
111
|
langtrace_python_sdk/instrumentation/pinecone/__init__.py,sha256=DzXyGh9_MGWveJvXULkFwdkf7PbG2s3bAWtT1Dmz7Ok,99
|
|
101
112
|
langtrace_python_sdk/instrumentation/pinecone/instrumentation.py,sha256=HDXkRITrVPwdQEoOYJOfMzZE_2-vDDvuqHTlD8W1lQw,1845
|
|
102
113
|
langtrace_python_sdk/instrumentation/pinecone/patch.py,sha256=KiIRRz8kk47FllFT746Cb_w6F6M60AN_pcsguD979E4,5172
|
|
@@ -152,8 +163,8 @@ tests/pinecone/cassettes/test_query.yaml,sha256=b5v9G3ssUy00oG63PlFUR3JErF2Js-5A
|
|
|
152
163
|
tests/pinecone/cassettes/test_upsert.yaml,sha256=neWmQ1v3d03V8WoLl8FoFeeCYImb8pxlJBWnFd_lITU,38607
|
|
153
164
|
tests/qdrant/conftest.py,sha256=9n0uHxxIjWk9fbYc4bx-uP8lSAgLBVx-cV9UjnsyCHM,381
|
|
154
165
|
tests/qdrant/test_qdrant.py,sha256=pzjAjVY2kmsmGfrI2Gs2xrolfuaNHz7l1fqGQCjp5_o,3353
|
|
155
|
-
langtrace_python_sdk-2.1.
|
|
156
|
-
langtrace_python_sdk-2.1.
|
|
157
|
-
langtrace_python_sdk-2.1.
|
|
158
|
-
langtrace_python_sdk-2.1.
|
|
159
|
-
langtrace_python_sdk-2.1.
|
|
166
|
+
langtrace_python_sdk-2.1.22.dist-info/METADATA,sha256=OBp1W_aK6Om6TkkaFfhhyo-7tSDZ3TC49Hdbs6KdFR0,13161
|
|
167
|
+
langtrace_python_sdk-2.1.22.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
|
|
168
|
+
langtrace_python_sdk-2.1.22.dist-info/entry_points.txt,sha256=1_b9-qvf2fE7uQNZcbUei9vLpFZBbbh9LrtGw95ssAo,70
|
|
169
|
+
langtrace_python_sdk-2.1.22.dist-info/licenses/LICENSE,sha256=QwcOLU5TJoTeUhuIXzhdCEEDDvorGiC6-3YTOl4TecE,11356
|
|
170
|
+
langtrace_python_sdk-2.1.22.dist-info/RECORD,,
|
{langtrace_python_sdk-2.1.20.dist-info → langtrace_python_sdk-2.1.22.dist-info}/entry_points.txt
RENAMED
|
File without changes
|
{langtrace_python_sdk-2.1.20.dist-info → langtrace_python_sdk-2.1.22.dist-info}/licenses/LICENSE
RENAMED
|
File without changes
|