langtrace-python-sdk 1.2.7__py3-none-any.whl → 1.2.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.
@@ -8,15 +8,18 @@ from langchain_core.runnables import RunnablePassthrough
8
8
  from langchain_openai import ChatOpenAI, OpenAIEmbeddings
9
9
 
10
10
  from langtrace_python_sdk import langtrace
11
- from langtrace_python_sdk.utils.with_root_span import with_langtrace_root_span
11
+ from langtrace_python_sdk.utils.with_root_span import (
12
+ with_langtrace_root_span,
13
+ with_additional_attributes,
14
+ )
12
15
 
13
16
  _ = load_dotenv(find_dotenv())
14
17
 
15
- langtrace.init(batch=False, debug_log_to_console=True, write_to_langtrace_cloud=False)
18
+ langtrace.init()
16
19
 
17
20
 
18
- @with_langtrace_root_span()
19
- def basic():
21
+ @with_additional_attributes({"user.id": "1234", "user.feedback.rating": 1})
22
+ def api_call_1():
20
23
  llm = ChatOpenAI()
21
24
  prompt = ChatPromptTemplate.from_messages(
22
25
  [
@@ -30,6 +33,27 @@ def basic():
30
33
  print(res)
31
34
 
32
35
 
36
+ @with_additional_attributes({"user.id": "37373", "user.feedback.rating": 1})
37
+ def api_call_2():
38
+ llm = ChatOpenAI()
39
+ prompt = ChatPromptTemplate.from_messages(
40
+ [
41
+ ("system", "You are world class technical documentation writer."),
42
+ ("user", "{input}"),
43
+ ]
44
+ )
45
+ output_parser = StrOutputParser()
46
+ chain = prompt | llm | output_parser
47
+ res = chain.invoke({"input": "how can langsmith help with testing?"})
48
+ print(res)
49
+
50
+
51
+ @with_langtrace_root_span()
52
+ def basic():
53
+ api_call_1()
54
+ api_call_2()
55
+
56
+
33
57
  @with_langtrace_root_span()
34
58
  def rag():
35
59
  vectorstore = FAISS.from_texts(
@@ -2,38 +2,58 @@ from dotenv import find_dotenv, load_dotenv
2
2
  from openai import OpenAI
3
3
 
4
4
  from langtrace_python_sdk import langtrace
5
- from langtrace_python_sdk.utils.with_root_span import with_langtrace_root_span
5
+ from langtrace_python_sdk.utils.with_root_span import (
6
+ with_additional_attributes, with_langtrace_root_span)
6
7
 
7
8
  _ = load_dotenv(find_dotenv())
8
9
 
9
- langtrace.init(batch=False, debug_log_to_console=True, write_to_langtrace_cloud=False)
10
-
10
+ langtrace.init()
11
11
  client = OpenAI()
12
12
 
13
13
 
14
- @with_langtrace_root_span()
15
- def chat_completion():
14
+ @with_additional_attributes({"user.id": "1234", "user.feedback.rating": 1})
15
+ def api1():
16
16
  response = client.chat.completions.create(
17
17
  model="gpt-4",
18
18
  messages=[{"role": "user", "content": "Say this is a test three times"}],
19
- stream=True,
19
+ stream=False,
20
20
  )
21
- print(response)
22
- # stream = client.chat.completions.create(
23
- # model="gpt-4",
24
- # messages=[{"role": "user", "content": "Say this is a test three times"}, {"role": "assistant", "content": "This is a test. This is a test. This is a test"},
25
- # {"role": "user", "content": "Say this is a mock 4 times"}],
26
- # stream=False,
27
- # )
28
-
29
- # result = []
30
- # for chunk in response:
31
- # if chunk.choices[0].delta.content is not None:
32
- # content = [
33
- # choice.delta.content if choice.delta and
34
- # choice.delta.content else ""
35
- # for choice in chunk.choices]
36
- # result.append(
37
- # content[0] if len(content) > 0 else "")
38
-
39
- # print("".join(result))
21
+ return response
22
+
23
+
24
+ @with_additional_attributes({"user.id": "5678", "user.feedback.rating": -1})
25
+ def api2():
26
+ response = client.chat.completions.create(
27
+ model="gpt-4",
28
+ messages=[{"role": "user", "content": "Say this is a test three times"}],
29
+ stream=False,
30
+ )
31
+ return response
32
+
33
+
34
+ @with_langtrace_root_span()
35
+ def chat_completion():
36
+ response = api1()
37
+ response = api2()
38
+ return response
39
+
40
+
41
+ # print(response)
42
+ # stream = client.chat.completions.create(
43
+ # model="gpt-4",
44
+ # messages=[{"role": "user", "content": "Say this is a test three times"}, {"role": "assistant", "content": "This is a test. This is a test. This is a test"},
45
+ # {"role": "user", "content": "Say this is a mock 4 times"}],
46
+ # stream=False,
47
+ # )
48
+
49
+ # result = []
50
+ # for chunk in response:
51
+ # if chunk.choices[0].delta.content is not None:
52
+ # content = [
53
+ # choice.delta.content if choice.delta and
54
+ # choice.delta.content else ""
55
+ # for choice in chunk.choices]
56
+ # result.append(
57
+ # content[0] if len(content) > 0 else "")
58
+
59
+ # print("".join(result))
@@ -17,3 +17,5 @@ SERVICE_PROVIDERS = {
17
17
  "OPENAI": "OpenAI",
18
18
  "PINECONE": "Pinecone",
19
19
  }
20
+
21
+ LANGTRACE_ADDITIONAL_SPAN_ATTRIBUTES_KEY = "langtrace_additional_attributes"
@@ -4,12 +4,13 @@ This module contains the patching logic for the Anthropic library."""
4
4
  import json
5
5
 
6
6
  from langtrace.trace_attributes import Event, LLMSpanAttributes
7
+ from opentelemetry import baggage
7
8
  from opentelemetry.trace import SpanKind
8
9
  from opentelemetry.trace.status import Status, StatusCode
9
10
 
10
11
  from langtrace_python_sdk.constants.instrumentation.anthropic import APIS
11
- from langtrace_python_sdk.constants.instrumentation.common import \
12
- SERVICE_PROVIDERS
12
+ from langtrace_python_sdk.constants.instrumentation.common import (
13
+ LANGTRACE_ADDITIONAL_SPAN_ATTRIBUTES_KEY, SERVICE_PROVIDERS)
13
14
 
14
15
 
15
16
  def messages_create(original_method, version, tracer):
@@ -31,6 +32,7 @@ def messages_create(original_method, version, tracer):
31
32
  prompts = json.dumps(
32
33
  [{"role": "system", "content": system}] + kwargs.get("messages", [])
33
34
  )
35
+ extra_attributes = baggage.get_baggage(LANGTRACE_ADDITIONAL_SPAN_ATTRIBUTES_KEY)
34
36
 
35
37
  span_attributes = {
36
38
  "langtrace.service.name": service_provider,
@@ -42,6 +44,7 @@ def messages_create(original_method, version, tracer):
42
44
  "llm.model": kwargs.get("model"),
43
45
  "llm.prompts": prompts,
44
46
  "llm.stream": kwargs.get("stream"),
47
+ **(extra_attributes if extra_attributes is not None else {})
45
48
  }
46
49
 
47
50
  attributes = LLMSpanAttributes(**span_attributes)
@@ -3,11 +3,13 @@ This module contains the patching logic for the Chroma client.
3
3
  """
4
4
 
5
5
  from langtrace.trace_attributes import DatabaseSpanAttributes
6
+ from opentelemetry import baggage
6
7
  from opentelemetry.trace import SpanKind
7
8
  from opentelemetry.trace.status import Status, StatusCode
8
9
 
9
10
  from langtrace_python_sdk.constants.instrumentation.chroma import APIS
10
- from langtrace_python_sdk.constants.instrumentation.common import SERVICE_PROVIDERS
11
+ from langtrace_python_sdk.constants.instrumentation.common import (
12
+ LANGTRACE_ADDITIONAL_SPAN_ATTRIBUTES_KEY, SERVICE_PROVIDERS)
11
13
 
12
14
 
13
15
  def collection_patch(method, version, tracer):
@@ -18,6 +20,8 @@ def collection_patch(method, version, tracer):
18
20
  def traced_method(wrapped, instance, args, kwargs):
19
21
  api = APIS[method]
20
22
  service_provider = SERVICE_PROVIDERS["CHROMA"]
23
+ extra_attributes = baggage.get_baggage(LANGTRACE_ADDITIONAL_SPAN_ATTRIBUTES_KEY)
24
+
21
25
  span_attributes = {
22
26
  "langtrace.service.name": service_provider,
23
27
  "langtrace.service.type": "vectordb",
@@ -25,6 +29,7 @@ def collection_patch(method, version, tracer):
25
29
  "langtrace.version": "1.0.0",
26
30
  "db.system": "chromadb",
27
31
  "db.operation": api["OPERATION"],
32
+ **(extra_attributes if extra_attributes is not None else {})
28
33
  }
29
34
 
30
35
  if hasattr(instance, "name") and instance.name is not None:
@@ -5,10 +5,12 @@ This module contains the patching logic for the langchain package.
5
5
  import json
6
6
 
7
7
  from langtrace.trace_attributes import FrameworkSpanAttributes
8
+ from opentelemetry import baggage
8
9
  from opentelemetry.trace import SpanKind, StatusCode
9
10
  from opentelemetry.trace.status import Status
10
11
 
11
- from langtrace_python_sdk.constants.instrumentation.common import SERVICE_PROVIDERS
12
+ from langtrace_python_sdk.constants.instrumentation.common import (
13
+ LANGTRACE_ADDITIONAL_SPAN_ATTRIBUTES_KEY, SERVICE_PROVIDERS)
12
14
 
13
15
 
14
16
  def generic_patch(
@@ -20,12 +22,15 @@ def generic_patch(
20
22
 
21
23
  def traced_method(wrapped, instance, args, kwargs):
22
24
  service_provider = SERVICE_PROVIDERS["LANGCHAIN"]
25
+ extra_attributes = baggage.get_baggage(LANGTRACE_ADDITIONAL_SPAN_ATTRIBUTES_KEY)
26
+
23
27
  span_attributes = {
24
28
  "langtrace.service.name": service_provider,
25
29
  "langtrace.service.type": "framework",
26
30
  "langtrace.service.version": version,
27
31
  "langtrace.version": "1.0.0",
28
32
  "langchain.task.name": task,
33
+ **(extra_attributes if extra_attributes is not None else {})
29
34
  }
30
35
 
31
36
  if len(args) > 0 and trace_input:
@@ -1,10 +1,12 @@
1
1
  import json
2
2
 
3
3
  from langtrace.trace_attributes import FrameworkSpanAttributes
4
+ from opentelemetry import baggage
4
5
  from opentelemetry.trace import SpanKind
5
6
  from opentelemetry.trace.status import Status, StatusCode
6
7
 
7
- from langtrace_python_sdk.constants.instrumentation.common import SERVICE_PROVIDERS
8
+ from langtrace_python_sdk.constants.instrumentation.common import (
9
+ LANGTRACE_ADDITIONAL_SPAN_ATTRIBUTES_KEY, SERVICE_PROVIDERS)
8
10
 
9
11
 
10
12
  def generic_patch(
@@ -12,12 +14,15 @@ def generic_patch(
12
14
  ):
13
15
  def traced_method(wrapped, instance, args, kwargs):
14
16
  service_provider = SERVICE_PROVIDERS["LANGCHAIN_COMMUNITY"]
17
+ extra_attributes = baggage.get_baggage(LANGTRACE_ADDITIONAL_SPAN_ATTRIBUTES_KEY)
18
+
15
19
  span_attributes = {
16
20
  "langtrace.service.name": service_provider,
17
21
  "langtrace.service.type": "framework",
18
22
  "langtrace.service.version": version,
19
23
  "langtrace.version": "1.0.0",
20
24
  "langchain.task.name": task,
25
+ **(extra_attributes if extra_attributes is not None else {})
21
26
  }
22
27
 
23
28
  if trace_input and len(args) > 0:
@@ -5,10 +5,12 @@ This module contains the patching functions for the langchain_core package.
5
5
  import json
6
6
 
7
7
  from langtrace.trace_attributes import FrameworkSpanAttributes
8
+ from opentelemetry import baggage
8
9
  from opentelemetry.trace import SpanKind, StatusCode
9
10
  from opentelemetry.trace.status import Status
10
11
 
11
- from langtrace_python_sdk.constants.instrumentation.common import SERVICE_PROVIDERS
12
+ from langtrace_python_sdk.constants.instrumentation.common import (
13
+ LANGTRACE_ADDITIONAL_SPAN_ATTRIBUTES_KEY, SERVICE_PROVIDERS)
12
14
 
13
15
 
14
16
  def generic_patch(
@@ -26,12 +28,15 @@ def generic_patch(
26
28
 
27
29
  def traced_method(wrapped, instance, args, kwargs):
28
30
  service_provider = SERVICE_PROVIDERS["LANGCHAIN_CORE"]
31
+ extra_attributes = baggage.get_baggage(LANGTRACE_ADDITIONAL_SPAN_ATTRIBUTES_KEY)
32
+
29
33
  span_attributes = {
30
34
  "langtrace.service.name": service_provider,
31
35
  "langtrace.service.type": "framework",
32
36
  "langtrace.service.version": version,
33
37
  "langtrace.version": "1.0.0",
34
38
  "langchain.task.name": task,
39
+ **(extra_attributes if extra_attributes is not None else {})
35
40
  }
36
41
 
37
42
  if len(args) > 0 and trace_input:
@@ -3,10 +3,12 @@ This module contains a generic patch method that wraps a function with a span.
3
3
  """
4
4
 
5
5
  from langtrace.trace_attributes import FrameworkSpanAttributes
6
+ from opentelemetry import baggage
6
7
  from opentelemetry.trace import SpanKind
7
8
  from opentelemetry.trace.status import Status, StatusCode
8
9
 
9
- from langtrace_python_sdk.constants.instrumentation.common import SERVICE_PROVIDERS
10
+ from langtrace_python_sdk.constants.instrumentation.common import (
11
+ LANGTRACE_ADDITIONAL_SPAN_ATTRIBUTES_KEY, SERVICE_PROVIDERS)
10
12
 
11
13
 
12
14
  def generic_patch(method, task, tracer, version):
@@ -15,12 +17,15 @@ def generic_patch(method, task, tracer, version):
15
17
 
16
18
  def traced_method(wrapped, instance, args, kwargs):
17
19
  service_provider = SERVICE_PROVIDERS["LLAMAINDEX"]
20
+ extra_attributes = baggage.get_baggage(LANGTRACE_ADDITIONAL_SPAN_ATTRIBUTES_KEY)
21
+
18
22
  span_attributes = {
19
23
  "langtrace.service.name": service_provider,
20
24
  "langtrace.service.type": "framework",
21
25
  "langtrace.service.version": version,
22
26
  "langtrace.version": "1.0.0",
23
27
  "llamaindex.task.name": task,
28
+ **(extra_attributes if extra_attributes is not None else {})
24
29
  }
25
30
 
26
31
  attributes = FrameworkSpanAttributes(**span_attributes)
@@ -4,12 +4,15 @@ This module contains the patching logic for the OpenAI library."""
4
4
  import json
5
5
 
6
6
  from langtrace.trace_attributes import Event, LLMSpanAttributes
7
+ from opentelemetry import baggage, trace
7
8
  from opentelemetry.trace import SpanKind
8
9
  from opentelemetry.trace.status import Status, StatusCode
9
10
 
10
- from langtrace_python_sdk.constants.instrumentation.common import SERVICE_PROVIDERS
11
+ from langtrace_python_sdk.constants.instrumentation.common import (
12
+ LANGTRACE_ADDITIONAL_SPAN_ATTRIBUTES_KEY, SERVICE_PROVIDERS)
11
13
  from langtrace_python_sdk.constants.instrumentation.openai import APIS
12
- from langtrace_python_sdk.utils.llm import calculate_prompt_tokens, estimate_tokens
14
+ from langtrace_python_sdk.utils.llm import (calculate_prompt_tokens,
15
+ estimate_tokens)
13
16
 
14
17
 
15
18
  def images_generate(original_method, version, tracer):
@@ -24,6 +27,8 @@ def images_generate(original_method, version, tracer):
24
27
  else ""
25
28
  )
26
29
  service_provider = SERVICE_PROVIDERS["OPENAI"]
30
+ extra_attributes = baggage.get_baggage(LANGTRACE_ADDITIONAL_SPAN_ATTRIBUTES_KEY)
31
+
27
32
  span_attributes = {
28
33
  "langtrace.service.name": service_provider,
29
34
  "langtrace.service.type": "llm",
@@ -34,6 +39,7 @@ def images_generate(original_method, version, tracer):
34
39
  "llm.model": kwargs.get("model"),
35
40
  "llm.stream": kwargs.get("stream"),
36
41
  "llm.prompts": json.dumps([kwargs.get("prompt", [])]),
42
+ **(extra_attributes if extra_attributes is not None else {})
37
43
  }
38
44
 
39
45
  attributes = LLMSpanAttributes(**span_attributes)
@@ -90,6 +96,8 @@ def chat_completions_create(original_method, version, tracer):
90
96
  else ""
91
97
  )
92
98
  service_provider = SERVICE_PROVIDERS["OPENAI"]
99
+ extra_attributes = baggage.get_baggage(LANGTRACE_ADDITIONAL_SPAN_ATTRIBUTES_KEY)
100
+
93
101
  span_attributes = {
94
102
  "langtrace.service.name": service_provider,
95
103
  "langtrace.service.type": "llm",
@@ -99,6 +107,7 @@ def chat_completions_create(original_method, version, tracer):
99
107
  "llm.api": APIS["CHAT_COMPLETION"]["ENDPOINT"],
100
108
  "llm.prompts": json.dumps(kwargs.get("messages", [])),
101
109
  "llm.stream": kwargs.get("stream"),
110
+ **(extra_attributes if extra_attributes is not None else {})
102
111
  }
103
112
 
104
113
  attributes = LLMSpanAttributes(**span_attributes)
@@ -130,10 +139,12 @@ def chat_completions_create(original_method, version, tracer):
130
139
  responses = [
131
140
  {
132
141
  "message": {
133
- "role": choice.message.role
142
+ "role": (
143
+ choice.message.role
134
144
  if choice.message and choice.message.role
135
- else "assistant",
136
- "content": (
145
+ else "assistant"
146
+ ),
147
+ "content": (
137
148
  choice.message.content
138
149
  if choice.message and choice.message.content
139
150
  else (
@@ -299,6 +310,8 @@ def embeddings_create(original_method, version, tracer):
299
310
  )
300
311
 
301
312
  service_provider = SERVICE_PROVIDERS["OPENAI"]
313
+ extra_attributes = baggage.get_baggage(LANGTRACE_ADDITIONAL_SPAN_ATTRIBUTES_KEY)
314
+
302
315
  span_attributes = {
303
316
  "langtrace.service.name": service_provider,
304
317
  "langtrace.service.type": "llm",
@@ -308,6 +321,7 @@ def embeddings_create(original_method, version, tracer):
308
321
  "llm.api": APIS["EMBEDDINGS_CREATE"]["ENDPOINT"],
309
322
  "llm.model": kwargs.get("model"),
310
323
  "llm.prompts": "",
324
+ **(extra_attributes if extra_attributes is not None else {})
311
325
  }
312
326
 
313
327
  attributes = LLMSpanAttributes(**span_attributes)
@@ -323,6 +337,9 @@ def embeddings_create(original_method, version, tracer):
323
337
  with tracer.start_as_current_span(
324
338
  APIS["EMBEDDINGS_CREATE"]["METHOD"], kind=SpanKind.CLIENT
325
339
  ) as span:
340
+
341
+ print("Inside embeddings_create", trace.get_current_span())
342
+
326
343
  for field, value in attributes.model_dump(by_alias=True).items():
327
344
  if value is not None:
328
345
  span.set_attribute(field, value)
@@ -2,10 +2,12 @@
2
2
  This module contains the patching logic for the Pinecone client."""
3
3
 
4
4
  from langtrace.trace_attributes import DatabaseSpanAttributes
5
+ from opentelemetry import baggage
5
6
  from opentelemetry.trace import SpanKind
6
7
  from opentelemetry.trace.status import Status, StatusCode
7
8
 
8
- from langtrace_python_sdk.constants.instrumentation.common import SERVICE_PROVIDERS
9
+ from langtrace_python_sdk.constants.instrumentation.common import (
10
+ LANGTRACE_ADDITIONAL_SPAN_ATTRIBUTES_KEY, SERVICE_PROVIDERS)
9
11
  from langtrace_python_sdk.constants.instrumentation.pinecone import APIS
10
12
 
11
13
 
@@ -16,6 +18,8 @@ def generic_patch(original_method, method, version, tracer):
16
18
  def traced_method(wrapped, instance, args, kwargs):
17
19
  api = APIS[method]
18
20
  service_provider = SERVICE_PROVIDERS["PINECONE"]
21
+ extra_attributes = baggage.get_baggage(LANGTRACE_ADDITIONAL_SPAN_ATTRIBUTES_KEY)
22
+
19
23
  span_attributes = {
20
24
  "langtrace.service.name": service_provider,
21
25
  "langtrace.service.type": "vectordb",
@@ -23,6 +27,7 @@ def generic_patch(original_method, method, version, tracer):
23
27
  "langtrace.version": "1.0.0",
24
28
  "db.system": "pinecone",
25
29
  "db.operation": api["OPERATION"],
30
+ **(extra_attributes if extra_attributes is not None else {})
26
31
  }
27
32
 
28
33
  attributes = DatabaseSpanAttributes(**span_attributes)
@@ -1,3 +1,4 @@
1
+
1
2
  from opentelemetry import trace
2
3
  from opentelemetry.sdk.trace import TracerProvider
3
4
  from opentelemetry.sdk.trace.export import (
@@ -1,21 +1,27 @@
1
1
  import asyncio
2
2
  from functools import wraps
3
3
 
4
- from opentelemetry import trace
4
+
5
+ from langtrace_python_sdk.constants.instrumentation.common import (
6
+ LANGTRACE_ADDITIONAL_SPAN_ATTRIBUTES_KEY,
7
+ )
5
8
  from opentelemetry.trace import SpanKind
9
+ from opentelemetry import trace, context, baggage
6
10
 
7
11
 
8
12
  def with_langtrace_root_span(
9
- name="LangtraceRootSpan", kind=SpanKind.INTERNAL, attributes={}
13
+ name="LangtraceRootSpan",
14
+ kind=SpanKind.INTERNAL,
10
15
  ):
16
+
11
17
  def decorator(func):
12
18
  @wraps(func)
13
19
  def sync_wrapper(*args, **kwargs):
14
20
  tracer = trace.get_tracer(__name__)
15
21
  operation_name = name if name else func.__name__
16
- with tracer.start_as_current_span(
17
- operation_name, kind=kind, attributes=attributes
18
- ):
22
+
23
+ with tracer.start_as_current_span(operation_name, kind=kind):
24
+
19
25
  return func(*args, **kwargs)
20
26
 
21
27
  @wraps(func)
@@ -31,3 +37,29 @@ def with_langtrace_root_span(
31
37
  return sync_wrapper
32
38
 
33
39
  return decorator
40
+
41
+
42
+ def with_additional_attributes(attributes={}):
43
+ def decorator(func):
44
+ @wraps(func)
45
+ def sync_wrapper(*args, **kwargs):
46
+ new_ctx = baggage.set_baggage(
47
+ LANGTRACE_ADDITIONAL_SPAN_ATTRIBUTES_KEY, attributes
48
+ )
49
+ context.attach(new_ctx)
50
+ return func(*args, **kwargs)
51
+
52
+ @wraps(func)
53
+ async def async_wrapper(*args, **kwargs):
54
+ new_ctx = baggage.set_baggage(
55
+ LANGTRACE_ADDITIONAL_SPAN_ATTRIBUTES_KEY, attributes
56
+ )
57
+ context.attach(new_ctx)
58
+ return await func(*args, **kwargs)
59
+
60
+ if asyncio.iscoroutinefunction(func):
61
+ return async_wrapper
62
+ else:
63
+ return sync_wrapper
64
+
65
+ return decorator
@@ -1 +1 @@
1
- __version__ = "1.2.7"
1
+ __version__ = "1.2.9"
@@ -0,0 +1,130 @@
1
+ Metadata-Version: 2.3
2
+ Name: langtrace-python-sdk
3
+ Version: 1.2.9
4
+ Summary: Python SDK for LangTrace
5
+ Project-URL: Homepage, https://github.com/Scale3-Labs/langtrace-python-sdk
6
+ Author-email: Scale3 Labs <engineering@scale3labs.com>
7
+ License-Expression: Apache-2.0
8
+ License-File: LICENSE
9
+ Classifier: License :: OSI Approved :: Apache Software License
10
+ Classifier: Operating System :: OS Independent
11
+ Classifier: Programming Language :: Python :: 3
12
+ Requires-Python: >=3.9
13
+ Requires-Dist: opentelemetry-api
14
+ Requires-Dist: opentelemetry-instrumentation
15
+ Requires-Dist: opentelemetry-sdk
16
+ Requires-Dist: pinecone-client
17
+ Requires-Dist: tiktoken
18
+ Requires-Dist: trace-attributes
19
+ Provides-Extra: dev
20
+ Requires-Dist: anthropic; extra == 'dev'
21
+ Requires-Dist: chromadb; extra == 'dev'
22
+ Requires-Dist: langchain; extra == 'dev'
23
+ Requires-Dist: langchain-openai; extra == 'dev'
24
+ Requires-Dist: llama-index; extra == 'dev'
25
+ Requires-Dist: openai; extra == 'dev'
26
+ Requires-Dist: python-dotenv; extra == 'dev'
27
+ Description-Content-Type: text/markdown
28
+
29
+ # What is Langtrace?
30
+
31
+ Langtrace stands as a developer-centric, open-source solution, fully compatible with OpenTelemetry. It enables developers to effortlessly trace, monitor, and debug their LLM applications, offering robust support for automatic instrumentation.
32
+
33
+ ## Supported LLM Modules
34
+
35
+ Langtrace supports a comprehensive range of LLMs, VectorDBs, and frameworks, ensuring wide coverage for your development needs:
36
+
37
+ ### LLMs
38
+
39
+ 1. OpenAI
40
+ 2. Anthropic
41
+ 3. Azure OpenAI
42
+
43
+ ### VectorDBs
44
+
45
+ 1. Pinecone
46
+ 2. Chromadb
47
+
48
+ ### Frameworks
49
+
50
+ 1. LangChain
51
+ 2. LlamaIndex
52
+ 3. Haystack
53
+
54
+ We are actively working to extend our support to additional libraries!
55
+
56
+ ## Getting Started
57
+
58
+ To begin utilizing Langtrace, follow these straightforward steps:
59
+
60
+ 1. Install the package using `pip install langtrace-python-sdk`.
61
+ 2. Incorporate Langtrace into your project with `from langtrace_python_sdk import langtrace`.
62
+ - This import should precede any other LLM module imports (such as OpenAI, LlamaIndex, etc.) to ensure proper functionality.
63
+ 3. Initialize Langtrace by adding `langtrace.init(write_to_langtrace_cloud=false)` to your code.
64
+ 4. Congratulations, you've completed the basic setup! You will now begin to see traces from your LLM modules logged directly to the console.
65
+
66
+
67
+ ## Exporting Traces to Langtrace
68
+
69
+ To configure trace exporting, you have two options:
70
+
71
+ You'll need a Langtrace `api_key`, which can be acquired by logging into your Langtrace account.
72
+
73
+ 1. Direct Initialization: Utilize `langtrace.init(api_key=<YOUR_API_KEY>)`.
74
+ 2. Environment Variables: Set `LANGTRACE_API_KEY`, then add `langtrace.init()` at the beginning of your file.
75
+
76
+ ### Additional Customization
77
+
78
+ - `@with_langtrace_root_span` - this decorator is designed to organize and relate different spans, in a hierarchical manner. When you're performing multiple operations that you want to monitor together as a unit, this function helps by establishing a "parent" (`LangtraceRootSpan` or whatever is passed to `name`) span. Then, any calls to the LLM APIs made within the given function (fn) will be considered "children" of this parent span. This setup is especially useful for tracking the performance or behavior of a group of operations collectively, rather than individually.
79
+
80
+ ```python
81
+ from langtrace_python_sdk.utils.with_root_span import with_langtrace_root_span
82
+
83
+ @with_langtrace_root_span()
84
+ def example():
85
+ response = client.chat.completions.create(
86
+ model="gpt-4",
87
+ messages=[{"role": "user", "content": "Say this is a test three times"}],
88
+ stream=False,
89
+ )
90
+ return response
91
+ ```
92
+
93
+
94
+ - `with_additional_attributes` - this function is designed to enhance the traces by adding custom attributes to the current context. These custom attributes provide extra details about the operations being performed, making it easier to analyze and understand their behavior.
95
+
96
+ ```python
97
+ from langtrace_python_sdk.utils.with_root_span import (
98
+ with_langtrace_root_span,
99
+ with_additional_attributes,
100
+ )
101
+
102
+ @with_additional_attributes({"user.id": "1234", "user.feedback.rating": 1})
103
+ def api_call1():
104
+ response = client.chat.completions.create(
105
+ model="gpt-4",
106
+ messages=[{"role": "user", "content": "Say this is a test three times"}],
107
+ stream=False,
108
+ )
109
+ return response
110
+
111
+
112
+ @with_additional_attributes({"user.id": "5678", "user.feedback.rating": -1})
113
+ def api_call2():
114
+ response = client.chat.completions.create(
115
+ model="gpt-4",
116
+ messages=[{"role": "user", "content": "Say this is a test three times"}],
117
+ stream=False,
118
+ )
119
+ return response
120
+
121
+
122
+ @with_langtrace_root_span()
123
+ def chat_completion():
124
+ api_call1()
125
+ api_call2()
126
+ ```
127
+
128
+ ## Langtrace Cloud
129
+
130
+ Currently under development 🚧