Skip to content

Commit 8ce4a0b

Browse files
authored
Merge pull request #297 from Scale3-Labs/rohit/S3EN-2726-estimate-token-usage
Token estimation langchain
2 parents 9bd7169 + 5bd4e1c commit 8ce4a0b

File tree

8 files changed

+88
-38
lines changed

8 files changed

+88
-38
lines changed

pyproject.toml

Lines changed: 27 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@ description = "Python SDK for LangTrace"
1212
readme = "README.md"
1313
authors = [{ name = "Scale3 Labs", email = "[email protected]" }]
1414
license = "Apache-2.0"
15-
classifiers=[
16-
"Programming Language :: Python :: 3",
17-
"License :: OSI Approved :: Apache Software License",
18-
"Operating System :: OS Independent",
15+
classifiers = [
16+
"Programming Language :: Python :: 3",
17+
"License :: OSI Approved :: Apache Software License",
18+
"Operating System :: OS Independent",
1919
]
2020
dependencies = [
2121
'trace-attributes==7.0.4',
@@ -28,40 +28,36 @@ dependencies = [
2828
'tiktoken>=0.1.1',
2929
'colorama>=0.4.6',
3030
'sqlalchemy',
31-
'fsspec>=2024.6.0'
31+
'fsspec>=2024.6.0',
32+
"transformers>=4.11.3",
3233
]
3334

3435
requires-python = ">=3.9"
3536

3637
[project.optional-dependencies]
3738
dev = [
38-
"openai==1.30.1",
39-
"anthropic",
40-
"chromadb",
41-
"qdrant-client",
42-
"python-dotenv",
43-
"pinecone-client",
44-
"langchain",
45-
"langchain-community",
46-
"langchain-openai",
47-
"langchain-openai",
48-
"chromadb",
49-
"cohere",
50-
"qdrant_client",
51-
"weaviate-client",
52-
"ollama",
53-
"groq",
54-
"google-generativeai",
55-
"google-cloud-aiplatform",
56-
"mistralai"
57-
]
58-
59-
test = [
60-
"pytest",
61-
"pytest-vcr",
62-
"pytest-asyncio",
39+
"openai==1.30.1",
40+
"anthropic",
41+
"chromadb",
42+
"qdrant-client",
43+
"python-dotenv",
44+
"pinecone-client",
45+
"langchain",
46+
"langchain-community",
47+
"langchain-openai",
48+
"langchain-openai",
49+
"chromadb",
50+
"cohere",
51+
"qdrant_client",
52+
"weaviate-client",
53+
"ollama",
54+
"groq",
55+
"google-generativeai",
56+
"google-cloud-aiplatform",
57+
"mistralai",
6358
]
6459

60+
test = ["pytest", "pytest-vcr", "pytest-asyncio"]
6561

6662

6763
[project.urls]
@@ -72,9 +68,7 @@ Homepage = "https://github.com/Scale3-Labs/langtrace-python-sdk"
7268
path = "src/langtrace_python_sdk/version.py"
7369

7470
[tool.hatch.build.targets.sdist]
75-
include = [
76-
"/src",
77-
]
71+
include = ["/src"]
7872

7973
[tool.hatch.build.targets.wheel]
8074
packages = ["src/langtrace_python_sdk", "src/examples", "src/tests"]

src/langtrace_python_sdk/instrumentation/langchain_community/patch.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
from opentelemetry.trace import SpanKind
2525
from opentelemetry.trace.status import Status, StatusCode
26+
from langtrace.trace_attributes import SpanAttributes
2627

2728
from langtrace_python_sdk.constants.instrumentation.common import (
2829
LANGTRACE_ADDITIONAL_SPAN_ATTRIBUTES_KEY,
@@ -71,6 +72,16 @@ def traced_method(wrapped, instance, args, kwargs):
7172
if trace_output:
7273
span.set_attribute("langchain.outputs", to_json_string(result))
7374

75+
prompt_tokens = instance.get_num_tokens(args[0])
76+
completion_tokens = instance.get_num_tokens(result)
77+
if hasattr(result, 'usage'):
78+
prompt_tokens = result.usage.prompt_tokens
79+
completion_tokens = result.usage.completion_tokens
80+
81+
span.set_attribute(SpanAttributes.LLM_USAGE_COMPLETION_TOKENS, prompt_tokens)
82+
span.set_attribute(SpanAttributes.LLM_USAGE_PROMPT_TOKENS, completion_tokens)
83+
84+
7485
span.set_status(StatusCode.OK)
7586
return result
7687
except Exception as err:

src/langtrace_python_sdk/instrumentation/langchain_core/patch.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
from importlib_metadata import version as v
3131

3232
from langtrace_python_sdk.constants import LANGTRACE_SDK_NAME
33+
from langtrace.trace_attributes import SpanAttributes
3334

3435

3536
def generic_patch(
@@ -78,8 +79,22 @@ def traced_method(wrapped, instance, args, kwargs):
7879
try:
7980
# Attempt to call the original method
8081
result = wrapped(*args, **kwargs)
82+
8183
if trace_output:
8284
span.set_attribute("langchain.outputs", to_json_string(result))
85+
if hasattr(result, 'usage'):
86+
prompt_tokens = result.usage.prompt_tokens
87+
completion_tokens = result.usage.completion_tokens
88+
span.set_attribute(SpanAttributes.LLM_USAGE_PROMPT_TOKENS, prompt_tokens)
89+
span.set_attribute(SpanAttributes.LLM_USAGE_COMPLETION_TOKENS, completion_tokens)
90+
91+
elif result.generations[0][0].text:
92+
span.set_attribute(SpanAttributes.LLM_USAGE_COMPLETION_TOKENS, instance.get_num_tokens(result.generations[0][0].text))
93+
elif isinstance(args[0][0], str):
94+
span.set_attribute(SpanAttributes.LLM_USAGE_PROMPT_TOKENS, instance.get_num_tokens(args[0][0]))
95+
96+
else:
97+
span.set_attribute(SpanAttributes.LLM_USAGE_PROMPT_TOKENS, instance.get_num_tokens(args[0][0].text))
8398

8499
span.set_status(StatusCode.OK)
85100
return result
@@ -156,6 +171,7 @@ def traced_method(wrapped, instance, args, kwargs):
156171
try:
157172
# Attempt to call the original method
158173
result = wrapped(*args, **kwargs)
174+
159175
if trace_output:
160176
outputs = {}
161177
if isinstance(result, dict):

src/langtrace_python_sdk/instrumentation/openai/patch.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
StreamWrapper,
4545
set_span_attributes,
4646
)
47-
from openai._types import NOT_GIVEN
47+
from langtrace_python_sdk.types import NOT_GIVEN
4848

4949

5050
def images_generate(original_method, version, tracer):

src/langtrace_python_sdk/types/__init__.py

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import List, Literal, TypedDict
1+
from typing import List, Literal, TypeVar, TypedDict, Union
22
from enum import Enum
33

44

@@ -111,3 +111,32 @@ class InstrumentationMethods(TypedDict):
111111
anthropic: List[VendorMethods.AnthropicMethods]
112112
cohere: List[VendorMethods.CohereMethods]
113113
weaviate: List[str]
114+
115+
_T = TypeVar("_T")
116+
class NotGiven:
117+
"""
118+
A sentinel singleton class used to distinguish omitted keyword arguments
119+
from those passed in with the value None (which may have different behavior).
120+
121+
For example:
122+
123+
```py
124+
def get(timeout: Union[int, NotGiven, None] = NotGiven()) -> Response:
125+
...
126+
127+
128+
get(timeout=1) # 1s timeout
129+
get(timeout=None) # No timeout
130+
get() # Default timeout behavior, which may not be statically known at the method definition.
131+
```
132+
"""
133+
134+
def __bool__(self) -> Literal[False]:
135+
return False
136+
137+
def __repr__(self) -> str:
138+
return "NOT_GIVEN"
139+
140+
141+
NotGivenOr = Union[_T, NotGiven]
142+
NOT_GIVEN = NotGiven()

src/langtrace_python_sdk/utils/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from openai import NOT_GIVEN
1+
from langtrace_python_sdk.types import NOT_GIVEN
22
from .sdk_version_checker import SDKVersionChecker
33
from opentelemetry.trace import Span
44
from langtrace.trace_attributes import SpanAttributes

src/langtrace_python_sdk/utils/llm.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
from langtrace_python_sdk.constants import LANGTRACE_SDK_NAME
1818
from langtrace_python_sdk.utils import set_span_attribute
19-
from openai import NOT_GIVEN
19+
from langtrace_python_sdk.types import NOT_GIVEN
2020
from tiktoken import get_encoding
2121
from tiktoken import get_encoding, list_encoding_names
2222

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "2.2.29"
1+
__version__ = "2.2.30"

0 commit comments

Comments
 (0)