langtrace-python-sdk 1.0.9__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.
- instrumentation/__init__.py +0 -0
- instrumentation/chroma/__init__.py +0 -0
- instrumentation/chroma/instrumentation.py +33 -0
- instrumentation/chroma/lib/__init__.py +0 -0
- instrumentation/chroma/lib/apis.py +40 -0
- instrumentation/chroma/patch.py +46 -0
- instrumentation/constants.py +18 -0
- instrumentation/langchain/__init__.py +0 -0
- instrumentation/langchain/instrumentation.py +74 -0
- instrumentation/langchain/patch.py +84 -0
- instrumentation/langchain_community/__init__.py +0 -0
- instrumentation/langchain_community/instrumentation.py +99 -0
- instrumentation/langchain_community/patch.py +78 -0
- instrumentation/langchain_core/__init__.py +0 -0
- instrumentation/langchain_core/instrumentation.py +101 -0
- instrumentation/langchain_core/patch.py +168 -0
- instrumentation/llamaindex/__init__.py +0 -0
- instrumentation/llamaindex/instrumentation.py +73 -0
- instrumentation/llamaindex/patch.py +40 -0
- instrumentation/openai/__init__.py +0 -0
- instrumentation/openai/instrumentation.py +41 -0
- instrumentation/openai/lib/__init__.py +0 -0
- instrumentation/openai/lib/apis.py +16 -0
- instrumentation/openai/lib/constants.py +30 -0
- instrumentation/openai/patch.py +209 -0
- instrumentation/pinecone/__init__.py +0 -0
- instrumentation/pinecone/instrumentation.py +43 -0
- instrumentation/pinecone/lib/__init__.py +0 -0
- instrumentation/pinecone/lib/apis.py +19 -0
- instrumentation/pinecone/patch.py +45 -0
- instrumentation/setup.py +50 -0
- instrumentation/utils.py +27 -0
- instrumentation/with_root_span.py +28 -0
- langtrace_python_sdk-1.0.9.dist-info/LICENSE +674 -0
- langtrace_python_sdk-1.0.9.dist-info/METADATA +169 -0
- langtrace_python_sdk-1.0.9.dist-info/RECORD +38 -0
- langtrace_python_sdk-1.0.9.dist-info/WHEEL +5 -0
- langtrace_python_sdk-1.0.9.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import json
|
|
2
|
+
|
|
3
|
+
from langtrace.trace_attributes import DatabaseSpanAttributes
|
|
4
|
+
from opentelemetry.trace import SpanKind, StatusCode
|
|
5
|
+
from opentelemetry.trace.status import Status, StatusCode
|
|
6
|
+
|
|
7
|
+
from instrumentation.constants import SERVICE_PROVIDERS
|
|
8
|
+
from instrumentation.pinecone.lib.apis import APIS
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def generic_patch(original_method, method, version, tracer):
|
|
12
|
+
def traced_method(wrapped, instance, args, kwargs):
|
|
13
|
+
api = APIS[method]
|
|
14
|
+
service_provider = SERVICE_PROVIDERS['PINECONE']
|
|
15
|
+
span_attributes = {
|
|
16
|
+
'langtrace.service.name': service_provider,
|
|
17
|
+
'langtrace.service.type': 'vectordb',
|
|
18
|
+
'langtrace.service.version': version,
|
|
19
|
+
'langtrace.version': '1.0.0',
|
|
20
|
+
"db.system": "pinecone",
|
|
21
|
+
"db.operation": api['OPERATION'],
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
attributes = DatabaseSpanAttributes(**span_attributes)
|
|
25
|
+
|
|
26
|
+
with tracer.start_as_current_span(api['METHOD'], kind=SpanKind.CLIENT) as span:
|
|
27
|
+
for field, value in attributes.model_dump(by_alias=True).items():
|
|
28
|
+
if value is not None:
|
|
29
|
+
span.set_attribute(field, value)
|
|
30
|
+
try:
|
|
31
|
+
# Attempt to call the original method
|
|
32
|
+
result = original_method(instance, *args, **kwargs)
|
|
33
|
+
span.set_status(StatusCode.OK)
|
|
34
|
+
return result
|
|
35
|
+
except Exception as e:
|
|
36
|
+
# Record the exception in the span
|
|
37
|
+
span.record_exception(e)
|
|
38
|
+
|
|
39
|
+
# Set the span status to indicate an error
|
|
40
|
+
span.set_status(Status(StatusCode.ERROR, str(e)))
|
|
41
|
+
|
|
42
|
+
# Reraise the exception to ensure it's not swallowed
|
|
43
|
+
raise
|
|
44
|
+
|
|
45
|
+
return traced_method
|
instrumentation/setup.py
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
|
|
2
|
+
from opentelemetry import trace
|
|
3
|
+
from opentelemetry.sdk.trace import TracerProvider
|
|
4
|
+
from opentelemetry.sdk.trace.export import (ConsoleSpanExporter,
|
|
5
|
+
SimpleSpanProcessor)
|
|
6
|
+
|
|
7
|
+
from instrumentation.chroma.instrumentation import ChromaInstrumentation
|
|
8
|
+
from instrumentation.langchain.instrumentation import LangchainInstrumentation
|
|
9
|
+
from instrumentation.langchain_community.instrumentation import \
|
|
10
|
+
LangchainCommunityInstrumentation
|
|
11
|
+
from instrumentation.langchain_core.instrumentation import \
|
|
12
|
+
LangchainCoreInstrumentation
|
|
13
|
+
from instrumentation.llamaindex.instrumentation import \
|
|
14
|
+
LlamaindexInstrumentation
|
|
15
|
+
from instrumentation.openai.instrumentation import OpenAIInstrumentation
|
|
16
|
+
from instrumentation.pinecone.instrumentation import PineconeInstrumentation
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def setup_instrumentation():
|
|
20
|
+
|
|
21
|
+
# Set up OpenTelemetry tracing
|
|
22
|
+
tracer_provider = TracerProvider()
|
|
23
|
+
|
|
24
|
+
# Use the ConsoleSpanExporter to print traces to the console
|
|
25
|
+
console_exporter = ConsoleSpanExporter()
|
|
26
|
+
tracer_provider.add_span_processor(SimpleSpanProcessor(console_exporter))
|
|
27
|
+
|
|
28
|
+
# Initialize tracer
|
|
29
|
+
trace.set_tracer_provider(tracer_provider)
|
|
30
|
+
|
|
31
|
+
# Initialize and enable your custom OpenAI instrumentation
|
|
32
|
+
# Create an instance of OpenAIInstrumentation
|
|
33
|
+
openai_instrumentation = OpenAIInstrumentation()
|
|
34
|
+
pinecone_instrumentation = PineconeInstrumentation()
|
|
35
|
+
llamaindex_instrumentation = LlamaindexInstrumentation()
|
|
36
|
+
chroma_instrumentation = ChromaInstrumentation()
|
|
37
|
+
langchain_instrumentation = LangchainInstrumentation()
|
|
38
|
+
langchain_core_instrumentation = LangchainCoreInstrumentation()
|
|
39
|
+
langchain_community_instrumentation = LangchainCommunityInstrumentation()
|
|
40
|
+
|
|
41
|
+
# Call the instrument method with some arguments
|
|
42
|
+
openai_instrumentation.instrument()
|
|
43
|
+
pinecone_instrumentation.instrument()
|
|
44
|
+
llamaindex_instrumentation.instrument()
|
|
45
|
+
chroma_instrumentation.instrument()
|
|
46
|
+
langchain_instrumentation.instrument()
|
|
47
|
+
langchain_core_instrumentation.instrument()
|
|
48
|
+
langchain_community_instrumentation.instrument()
|
|
49
|
+
|
|
50
|
+
print("setup complete")
|
instrumentation/utils.py
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
from tiktoken import TiktokenEncoding, get_encoding
|
|
2
|
+
from .constants import TIKTOKEN_MODEL_MAPPING, OPENAI_COST_TABLE
|
|
3
|
+
|
|
4
|
+
def estimate_tokens(prompt: str) -> int:
|
|
5
|
+
if prompt and len(prompt) > 0:
|
|
6
|
+
# Simplified token estimation: count the words.
|
|
7
|
+
return len(prompt.split())
|
|
8
|
+
return 0
|
|
9
|
+
|
|
10
|
+
def estimate_tokens_using_tiktoken(prompt: str, model: TiktokenEncoding) -> int:
|
|
11
|
+
encoding = get_encoding(model)
|
|
12
|
+
tokens = encoding.encode(prompt)
|
|
13
|
+
return len(tokens)
|
|
14
|
+
|
|
15
|
+
def calculate_prompt_tokens(prompt_content: str, model: str) -> int:
|
|
16
|
+
try:
|
|
17
|
+
tiktoken_model = TIKTOKEN_MODEL_MAPPING[model]
|
|
18
|
+
return estimate_tokens_using_tiktoken(prompt_content, tiktoken_model)
|
|
19
|
+
except KeyError:
|
|
20
|
+
return estimate_tokens(prompt_content) # Fallback method
|
|
21
|
+
|
|
22
|
+
def calculate_price_from_usage(model: str, usage: dict) -> float:
|
|
23
|
+
cost_table = OPENAI_COST_TABLE.get(model)
|
|
24
|
+
if cost_table:
|
|
25
|
+
return ((cost_table['input'] * usage['prompt_tokens'] +
|
|
26
|
+
cost_table['output'] * usage['completion_tokens']) / 1000)
|
|
27
|
+
return 0
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
from functools import wraps
|
|
3
|
+
|
|
4
|
+
from opentelemetry import trace
|
|
5
|
+
from opentelemetry.trace import SpanKind
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def with_langtrace_root_span(name="LangtraceRootSpan", kind=SpanKind.INTERNAL):
|
|
9
|
+
def decorator(func):
|
|
10
|
+
@wraps(func)
|
|
11
|
+
def sync_wrapper(*args, **kwargs):
|
|
12
|
+
tracer = trace.get_tracer(__name__)
|
|
13
|
+
operation_name = name if name else func.__name__
|
|
14
|
+
with tracer.start_as_current_span(operation_name, kind=kind):
|
|
15
|
+
return func(*args, **kwargs)
|
|
16
|
+
|
|
17
|
+
@wraps(func)
|
|
18
|
+
async def async_wrapper(*args, **kwargs):
|
|
19
|
+
tracer = trace.get_tracer(__name__)
|
|
20
|
+
operation_name = name if name else func.__name__
|
|
21
|
+
with tracer.start_as_current_span(operation_name, kind=kind):
|
|
22
|
+
return await func(*args, **kwargs)
|
|
23
|
+
|
|
24
|
+
if asyncio.iscoroutinefunction(func):
|
|
25
|
+
return async_wrapper
|
|
26
|
+
else:
|
|
27
|
+
return sync_wrapper
|
|
28
|
+
return decorator
|