From 02f46cc599485e26ab191e57c9b4cb43fd3d91e3 Mon Sep 17 00:00:00 2001 From: Ali Waleed <134522290+alizenhom@users.noreply.github.com> Date: Tue, 11 Jun 2024 17:45:53 +0300 Subject: [PATCH 1/7] working example for prompt id --- src/examples/pinecone_example/__init__.py | 13 ++++++-- src/examples/pinecone_example/basic.py | 30 +++++++++++++------ .../utils/with_root_span.py | 1 + 3 files changed, 33 insertions(+), 11 deletions(-) diff --git a/src/examples/pinecone_example/__init__.py b/src/examples/pinecone_example/__init__.py index 0b137678..6a3a270a 100644 --- a/src/examples/pinecone_example/__init__.py +++ b/src/examples/pinecone_example/__init__.py @@ -1,4 +1,8 @@ -from langtrace_python_sdk import with_langtrace_root_span +from langtrace_python_sdk import ( + get_prompt_from_registry, + with_langtrace_root_span, + with_additional_attributes, +) class PineconeRunner: @@ -6,4 +10,9 @@ class PineconeRunner: def run(self): from .basic import basic as basic_app - basic_app() + res = get_prompt_from_registry("clxadbzv6000110n5z1ym58pg") + main = with_additional_attributes( + {"prompt_id": res["id"], "version": res["version"]} + )(basic_app) + + main() diff --git a/src/examples/pinecone_example/basic.py b/src/examples/pinecone_example/basic.py index 621f03a8..1c38f262 100644 --- a/src/examples/pinecone_example/basic.py +++ b/src/examples/pinecone_example/basic.py @@ -7,6 +7,7 @@ from pinecone import Pinecone, ServerlessSpec from langtrace_python_sdk import ( + get_prompt_from_registry, langtrace, with_langtrace_root_span, with_additional_attributes, @@ -14,8 +15,9 @@ from langtrace_python_sdk.utils.with_root_span import SendUserFeedback _ = load_dotenv(find_dotenv()) - -langtrace.init() +langtrace.init( + api_host="http://localhost:3000/api/trace", +) client = OpenAI() pinecone = Pinecone() @@ -32,10 +34,14 @@ def create_index(): ) -@with_additional_attributes({"db.embedding_model": "text-embedding-ada-002"}) -@with_langtrace_root_span("Pinecone Basic") -def basic(span_id=None, trace_id=None): +# user_id = '123' +# session_id = '123' + +# @with_additional_attributes({"session_id": session_id, "user_id": user_id}) +@with_langtrace_root_span("Pinecone Basic") +def basic(): + # global attributes = {"session_id": session_id, "user_id": user_id} result = client.embeddings.create( model="text-embedding-ada-002", input="Some random text string goes here", @@ -53,10 +59,16 @@ def basic(span_id=None, trace_id=None): resp = index.query( vector=embedding, top_k=1, include_values=False, namespace="test-namespace" ) - SendUserFeedback().evaluate( - {"spanId": span_id, "traceId": trace_id, "userScore": 1, "userId": "123"} - ) + # SendUserFeedback().evaluate( + # {"spanId": span_id, "traceId": trace_id, "userScore": 1, "userId": "123"} + # ) return [res, resp] -# create_index() +# # failure +# def main(): +# user_id = 123 +# prompt_id = get_prompt_from_registry('clxadbzv6000110n5z1ym58pg') +# print(prompt_id) +# @with_additional_attributes({'user_id': user_id}) # this won't work +# fetch_prompt_id_and_openai_completion() diff --git a/src/langtrace_python_sdk/utils/with_root_span.py b/src/langtrace_python_sdk/utils/with_root_span.py index 8dde43de..54d53b2b 100644 --- a/src/langtrace_python_sdk/utils/with_root_span.py +++ b/src/langtrace_python_sdk/utils/with_root_span.py @@ -58,6 +58,7 @@ def sync_wrapper(*args, **kwargs): "span_id" in func.__code__.co_varnames and "trace_id" in func.__code__.co_varnames ): + attributes = {} return func(*args, span_id, trace_id, **kwargs) else: return func(*args, **kwargs) From ee908da0bfae936e8244bf816a438de29f38c6ed Mon Sep 17 00:00:00 2001 From: Ali Waleed <134522290+alizenhom@users.noreply.github.com> Date: Wed, 12 Jun 2024 14:36:10 +0300 Subject: [PATCH 2/7] additional attrs --- src/examples/pinecone_example/__init__.py | 7 ++--- .../utils/with_root_span.py | 26 +++---------------- 2 files changed, 5 insertions(+), 28 deletions(-) diff --git a/src/examples/pinecone_example/__init__.py b/src/examples/pinecone_example/__init__.py index 6a3a270a..d339a1c7 100644 --- a/src/examples/pinecone_example/__init__.py +++ b/src/examples/pinecone_example/__init__.py @@ -11,8 +11,5 @@ def run(self): from .basic import basic as basic_app res = get_prompt_from_registry("clxadbzv6000110n5z1ym58pg") - main = with_additional_attributes( - {"prompt_id": res["id"], "version": res["version"]} - )(basic_app) - - main() + + with_additional_attributes(basic_app, {"prompt_id": res}) diff --git a/src/langtrace_python_sdk/utils/with_root_span.py b/src/langtrace_python_sdk/utils/with_root_span.py index 54d53b2b..d255b252 100644 --- a/src/langtrace_python_sdk/utils/with_root_span.py +++ b/src/langtrace_python_sdk/utils/with_root_span.py @@ -35,6 +35,7 @@ LangTraceEvaluation, ) from colorama import Fore +import inspect def with_langtrace_root_span( @@ -89,29 +90,8 @@ async def async_wrapper(*args, **kwargs): def with_additional_attributes(attributes={}): - def decorator(func): - @wraps(func) - def sync_wrapper(*args, **kwargs): - new_ctx = baggage.set_baggage( - LANGTRACE_ADDITIONAL_SPAN_ATTRIBUTES_KEY, attributes - ) - context.attach(new_ctx) - return func(*args, **kwargs) - - @wraps(func) - async def async_wrapper(*args, **kwargs): - new_ctx = baggage.set_baggage( - LANGTRACE_ADDITIONAL_SPAN_ATTRIBUTES_KEY, attributes - ) - context.attach(new_ctx) - return await func(*args, **kwargs) - - if asyncio.iscoroutinefunction(func): - return async_wrapper - else: - return sync_wrapper - - return decorator + new_ctx = baggage.set_baggage(LANGTRACE_ADDITIONAL_SPAN_ATTRIBUTES_KEY, attributes) + context.attach(new_ctx) class SendUserFeedback: From fc06085387f53663a7caf03fd09c5c1177d27867 Mon Sep 17 00:00:00 2001 From: Ali Waleed <134522290+alizenhom@users.noreply.github.com> Date: Wed, 12 Jun 2024 18:38:27 +0300 Subject: [PATCH 3/7] finalizing injecting additional attributes --- README.md | 40 ++++++++++++---- src/examples/pinecone_example/__init__.py | 9 ++-- src/examples/pinecone_example/basic.py | 4 +- src/langtrace_python_sdk/__init__.py | 6 ++- .../utils/with_root_span.py | 47 ++++++++++++++++--- 5 files changed, 82 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index b256306a..d59e6ca0 100644 --- a/README.md +++ b/README.md @@ -139,14 +139,14 @@ langtrace.init(custom_remote_exporter=, batch=) ### Configure Langtrace -| Parameter | Type | Default Value | Description | -| -------------------------- | ----------------------------------- | ----------------------------- | ------------------------------------------------------------------------------ | -| `api_key` | `str` | `LANGTRACE_API_KEY` or `None` | The API key for authentication. | -| `batch` | `bool` | `True` | Whether to batch spans before sending them. | -| `write_spans_to_console` | `bool` | `False` | Whether to write spans to the console. | -| `custom_remote_exporter` | `Optional[Exporter]` | `None` | Custom remote exporter. If `None`, a default `LangTraceExporter` will be used. | -| `api_host` | `Optional[str]` | `https://langtrace.ai/` | The API host for the remote exporter. | -| `disable_instrumentations` | `Optional[DisableInstrumentations]` | `None` | You can pass an object to disable instrumentation for specific vendors ex: `{'only': ['openai']}` or `{'all_except': ['openai']}` +| Parameter | Type | Default Value | Description | +| -------------------------- | ----------------------------------- | ----------------------------- | --------------------------------------------------------------------------------------------------------------------------------- | +| `api_key` | `str` | `LANGTRACE_API_KEY` or `None` | The API key for authentication. | +| `batch` | `bool` | `True` | Whether to batch spans before sending them. | +| `write_spans_to_console` | `bool` | `False` | Whether to write spans to the console. | +| `custom_remote_exporter` | `Optional[Exporter]` | `None` | Custom remote exporter. If `None`, a default `LangTraceExporter` will be used. | +| `api_host` | `Optional[str]` | `https://langtrace.ai/` | The API host for the remote exporter. | +| `disable_instrumentations` | `Optional[DisableInstrumentations]` | `None` | You can pass an object to disable instrumentation for specific vendors ex: `{'only': ['openai']}` or `{'all_except': ['openai']}` | ### Additional Customization @@ -165,7 +165,28 @@ def example(): return response ``` -- `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. +- `inject_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. + +```python +from langtrace_python_sdk import inject_additional_attributes + + + +def do_llm_stuff(): + response = client.chat.completions.create( + model="gpt-4", + messages=[{"role": "user", "content": "Say this is a test three times"}], + stream=False, + ) + return response + + +def main(): + response = inject_additional_attributes(do_llm_stuff, {'user.id': 'userId'}) + +``` + +- `with_additional_attributes` - is behaving the same as `inject_additional_attributes` but as a decorator, this will be deprecated soon. ```python from langtrace_python_sdk import with_langtrace_root_span, with_additional_attributes @@ -237,7 +258,6 @@ We welcome contributions to this project. To get started, fork this repository a If you want to run any of the examples go to `run_example.py` file, you will find `ENABLED_EXAMPLES`. choose the example you want to run and just toggle the flag to `True` and run the file using `python src/run_example.py` - --- ## Security diff --git a/src/examples/pinecone_example/__init__.py b/src/examples/pinecone_example/__init__.py index d339a1c7..73d839b1 100644 --- a/src/examples/pinecone_example/__init__.py +++ b/src/examples/pinecone_example/__init__.py @@ -2,14 +2,15 @@ get_prompt_from_registry, with_langtrace_root_span, with_additional_attributes, + inject_additional_attributes, ) class PineconeRunner: @with_langtrace_root_span("Pinecone") def run(self): - from .basic import basic as basic_app + from .basic import basic as do_llm_stuff - res = get_prompt_from_registry("clxadbzv6000110n5z1ym58pg") - - with_additional_attributes(basic_app, {"prompt_id": res}) + response = inject_additional_attributes(do_llm_stuff, {"user.id": 1234}) + print(response) + return response diff --git a/src/examples/pinecone_example/basic.py b/src/examples/pinecone_example/basic.py index 1c38f262..2f26f5bc 100644 --- a/src/examples/pinecone_example/basic.py +++ b/src/examples/pinecone_example/basic.py @@ -15,9 +15,7 @@ from langtrace_python_sdk.utils.with_root_span import SendUserFeedback _ = load_dotenv(find_dotenv()) -langtrace.init( - api_host="http://localhost:3000/api/trace", -) +langtrace.init() client = OpenAI() pinecone = Pinecone() diff --git a/src/langtrace_python_sdk/__init__.py b/src/langtrace_python_sdk/__init__.py index bdca4653..74f2623f 100644 --- a/src/langtrace_python_sdk/__init__.py +++ b/src/langtrace_python_sdk/__init__.py @@ -21,12 +21,16 @@ ) from langtrace_python_sdk.utils.prompt_registry import get_prompt_from_registry -from langtrace_python_sdk.utils.with_root_span import SendUserFeedback +from langtrace_python_sdk.utils.with_root_span import ( + SendUserFeedback, + inject_additional_attributes, +) __all__ = [ "langtrace", "with_langtrace_root_span", "with_additional_attributes", + "inject_additional_attributes", "get_prompt_from_registry", "SendUserFeedback", ] diff --git a/src/langtrace_python_sdk/utils/with_root_span.py b/src/langtrace_python_sdk/utils/with_root_span.py index d255b252..ca45be29 100644 --- a/src/langtrace_python_sdk/utils/with_root_span.py +++ b/src/langtrace_python_sdk/utils/with_root_span.py @@ -16,6 +16,7 @@ import asyncio import os +from deprecated import deprecated from functools import wraps from typing import Optional @@ -23,9 +24,6 @@ from opentelemetry import baggage, context, trace from opentelemetry.trace import SpanKind -from langtrace_python_sdk.constants.exporter.langtrace_exporter import ( - LANGTRACE_REMOTE_URL, -) from langtrace_python_sdk.constants.instrumentation.common import ( LANGTRACE_ADDITIONAL_SPAN_ATTRIBUTES_KEY, ) @@ -35,7 +33,6 @@ LangTraceEvaluation, ) from colorama import Fore -import inspect def with_langtrace_root_span( @@ -89,9 +86,47 @@ async def async_wrapper(*args, **kwargs): return decorator +@deprecated(reason="Use inject_additional_attributes instead") def with_additional_attributes(attributes={}): - new_ctx = baggage.set_baggage(LANGTRACE_ADDITIONAL_SPAN_ATTRIBUTES_KEY, attributes) - context.attach(new_ctx) + print( + Fore.YELLOW + + "with_additional_attributes is deprecated, use inject_additional_attributes instead" + + Fore.RESET + ) + + def decorator(func): + @wraps(func) + def sync_wrapper(*args, **kwargs): + new_ctx = baggage.set_baggage( + LANGTRACE_ADDITIONAL_SPAN_ATTRIBUTES_KEY, attributes + ) + context.attach(new_ctx) + return func(*args, **kwargs) + + @wraps(func) + async def async_wrapper(*args, **kwargs): + new_ctx = baggage.set_baggage( + LANGTRACE_ADDITIONAL_SPAN_ATTRIBUTES_KEY, attributes + ) + context.attach(new_ctx) + return await func(*args, **kwargs) + + if asyncio.iscoroutinefunction(func): + return async_wrapper + else: + return sync_wrapper + + return decorator + + +def inject_additional_attributes(fn, attributes=None): + if attributes: + new_ctx = baggage.set_baggage( + LANGTRACE_ADDITIONAL_SPAN_ATTRIBUTES_KEY, attributes + ) + context.attach(new_ctx) + + return fn() class SendUserFeedback: From fb180049349a76fda0411332f12e693ca82eb2f1 Mon Sep 17 00:00:00 2001 From: Ali Waleed <134522290+alizenhom@users.noreply.github.com> Date: Wed, 12 Jun 2024 18:38:52 +0300 Subject: [PATCH 4/7] bump version --- 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 1fde5cdb..a2586c2c 100644 --- a/src/langtrace_python_sdk/version.py +++ b/src/langtrace_python_sdk/version.py @@ -1 +1 @@ -__version__ = "2.1.15" +__version__ = "2.1.16" From 34d093204553f6f00863572ed7363818b0c98cc1 Mon Sep 17 00:00:00 2001 From: Ali Waleed <134522290+alizenhom@users.noreply.github.com> Date: Wed, 12 Jun 2024 18:40:19 +0300 Subject: [PATCH 5/7] cleanup --- src/examples/langchain_example/basic.py | 2 -- src/examples/openai_example/chat_completion.py | 1 - src/examples/pinecone_example/basic.py | 15 --------------- 3 files changed, 18 deletions(-) diff --git a/src/examples/langchain_example/basic.py b/src/examples/langchain_example/basic.py index e91677d8..cced1030 100644 --- a/src/examples/langchain_example/basic.py +++ b/src/examples/langchain_example/basic.py @@ -18,7 +18,6 @@ langtrace.init() -# @with_additional_attributes({"user.id": "1234", "user.feedback.rating": 1}) def api_call_1(): llm = ChatOpenAI() prompt = ChatPromptTemplate.from_messages( @@ -33,7 +32,6 @@ def api_call_1(): print(res) -# @with_additional_attributes({"user.id": "37373", "user.feedback.rating": 1}) def api_call_2(): llm = ChatOpenAI() prompt = ChatPromptTemplate.from_messages( diff --git a/src/examples/openai_example/chat_completion.py b/src/examples/openai_example/chat_completion.py index c5260d17..2bc11dcd 100644 --- a/src/examples/openai_example/chat_completion.py +++ b/src/examples/openai_example/chat_completion.py @@ -13,7 +13,6 @@ client = OpenAI() -@with_additional_attributes({"user.id": "1234", "user.feedback.rating": 1}) def api(): response = client.chat.completions.create( model="gpt-4", diff --git a/src/examples/pinecone_example/basic.py b/src/examples/pinecone_example/basic.py index 2f26f5bc..a6c78044 100644 --- a/src/examples/pinecone_example/basic.py +++ b/src/examples/pinecone_example/basic.py @@ -32,14 +32,8 @@ def create_index(): ) -# user_id = '123' -# session_id = '123' - - -# @with_additional_attributes({"session_id": session_id, "user_id": user_id}) @with_langtrace_root_span("Pinecone Basic") def basic(): - # global attributes = {"session_id": session_id, "user_id": user_id} result = client.embeddings.create( model="text-embedding-ada-002", input="Some random text string goes here", @@ -61,12 +55,3 @@ def basic(): # {"spanId": span_id, "traceId": trace_id, "userScore": 1, "userId": "123"} # ) return [res, resp] - - -# # failure -# def main(): -# user_id = 123 -# prompt_id = get_prompt_from_registry('clxadbzv6000110n5z1ym58pg') -# print(prompt_id) -# @with_additional_attributes({'user_id': user_id}) # this won't work -# fetch_prompt_id_and_openai_completion() From b1818da88fbe39daa3aab21f6c220007ee394a35 Mon Sep 17 00:00:00 2001 From: Ali Waleed <134522290+alizenhom@users.noreply.github.com> Date: Wed, 12 Jun 2024 18:41:22 +0300 Subject: [PATCH 6/7] cleanup --- src/langtrace_python_sdk/utils/with_root_span.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/langtrace_python_sdk/utils/with_root_span.py b/src/langtrace_python_sdk/utils/with_root_span.py index ca45be29..010ce0c9 100644 --- a/src/langtrace_python_sdk/utils/with_root_span.py +++ b/src/langtrace_python_sdk/utils/with_root_span.py @@ -56,7 +56,6 @@ def sync_wrapper(*args, **kwargs): "span_id" in func.__code__.co_varnames and "trace_id" in func.__code__.co_varnames ): - attributes = {} return func(*args, span_id, trace_id, **kwargs) else: return func(*args, **kwargs) From 3a4db69c85f5641d92a069134ee4c76901df6e02 Mon Sep 17 00:00:00 2001 From: Ali Waleed <134522290+alizenhom@users.noreply.github.com> Date: Wed, 12 Jun 2024 18:43:59 +0300 Subject: [PATCH 7/7] adjust readme --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d59e6ca0..43c3a4ba 100644 --- a/README.md +++ b/README.md @@ -172,7 +172,7 @@ from langtrace_python_sdk import inject_additional_attributes -def do_llm_stuff(): +def do_llm_stuff(name=""): response = client.chat.completions.create( model="gpt-4", messages=[{"role": "user", "content": "Say this is a test three times"}], @@ -182,8 +182,10 @@ def do_llm_stuff(): def main(): - response = inject_additional_attributes(do_llm_stuff, {'user.id': 'userId'}) + response = inject_additional_attributes(lambda: do_llm_stuff(name="llm"), {'user.id': 'userId'}) + # if the function do not take arguments then this syntax will work + response = inject_additional_attributes(do_llm_stuff, {'user.id': 'userId'}) ``` - `with_additional_attributes` - is behaving the same as `inject_additional_attributes` but as a decorator, this will be deprecated soon.