trulens-core 1.0.1__tar.gz
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.
- trulens_core-1.0.1/PKG-INFO +35 -0
- trulens_core-1.0.1/README.md +1 -0
- trulens_core-1.0.1/pyproject.toml +49 -0
- trulens_core-1.0.1/trulens/apps/basic.py +169 -0
- trulens_core-1.0.1/trulens/apps/custom.py +543 -0
- trulens_core-1.0.1/trulens/apps/py.typed +0 -0
- trulens_core-1.0.1/trulens/apps/virtual.py +574 -0
- trulens_core-1.0.1/trulens/core/__init__.py +36 -0
- trulens_core-1.0.1/trulens/core/_utils/optional.py +27 -0
- trulens_core-1.0.1/trulens/core/app.py +1617 -0
- trulens_core-1.0.1/trulens/core/database/__init__.py +0 -0
- trulens_core-1.0.1/trulens/core/database/base.py +403 -0
- trulens_core-1.0.1/trulens/core/database/connector/__init__.py +4 -0
- trulens_core-1.0.1/trulens/core/database/connector/base.py +402 -0
- trulens_core-1.0.1/trulens/core/database/connector/default.py +80 -0
- trulens_core-1.0.1/trulens/core/database/exceptions.py +66 -0
- trulens_core-1.0.1/trulens/core/database/legacy/__init__.py +0 -0
- trulens_core-1.0.1/trulens/core/database/legacy/migration.py +399 -0
- trulens_core-1.0.1/trulens/core/database/migrations/__init__.py +180 -0
- trulens_core-1.0.1/trulens/core/database/migrations/alembic.ini +104 -0
- trulens_core-1.0.1/trulens/core/database/migrations/data.py +184 -0
- trulens_core-1.0.1/trulens/core/database/migrations/env.py +99 -0
- trulens_core-1.0.1/trulens/core/database/migrations/script.py.mako +45 -0
- trulens_core-1.0.1/trulens/core/database/migrations/versions/1_first_revision.py +80 -0
- trulens_core-1.0.1/trulens/core/database/migrations/versions/2_add_run_location_column_to_feedback_defs_table.py +40 -0
- trulens_core-1.0.1/trulens/core/database/migrations/versions/3_add_groundtruth_and_dataset_tables.py +50 -0
- trulens_core-1.0.1/trulens/core/database/migrations/versions/4_set_ff_id_not_null.py +41 -0
- trulens_core-1.0.1/trulens/core/database/migrations/versions/5_add_app_name_and_version_fields.py +53 -0
- trulens_core-1.0.1/trulens/core/database/migrations/versions/6_populate_app_name_and_version_data.py +55 -0
- trulens_core-1.0.1/trulens/core/database/migrations/versions/7_app_name_version_not_null.py +52 -0
- trulens_core-1.0.1/trulens/core/database/migrations/versions/8_update_records_app_id.py +56 -0
- trulens_core-1.0.1/trulens/core/database/migrations/versions/9_update_app_json.py +69 -0
- trulens_core-1.0.1/trulens/core/database/orm.py +462 -0
- trulens_core-1.0.1/trulens/core/database/sqlalchemy.py +1204 -0
- trulens_core-1.0.1/trulens/core/database/utils.py +230 -0
- trulens_core-1.0.1/trulens/core/feedback/__init__.py +15 -0
- trulens_core-1.0.1/trulens/core/feedback/endpoint.py +769 -0
- trulens_core-1.0.1/trulens/core/feedback/feedback.py +1249 -0
- trulens_core-1.0.1/trulens/core/feedback/provider.py +71 -0
- trulens_core-1.0.1/trulens/core/guardrails/__init__.py +0 -0
- trulens_core-1.0.1/trulens/core/guardrails/base.py +99 -0
- trulens_core-1.0.1/trulens/core/instruments.py +1046 -0
- trulens_core-1.0.1/trulens/core/py.typed +0 -0
- trulens_core-1.0.1/trulens/core/schema/__init__.py +38 -0
- trulens_core-1.0.1/trulens/core/schema/app.py +440 -0
- trulens_core-1.0.1/trulens/core/schema/base.py +111 -0
- trulens_core-1.0.1/trulens/core/schema/dataset.py +48 -0
- trulens_core-1.0.1/trulens/core/schema/feedback.py +442 -0
- trulens_core-1.0.1/trulens/core/schema/groundtruth.py +70 -0
- trulens_core-1.0.1/trulens/core/schema/record.py +259 -0
- trulens_core-1.0.1/trulens/core/schema/select.py +156 -0
- trulens_core-1.0.1/trulens/core/schema/types.py +88 -0
- trulens_core-1.0.1/trulens/core/session.py +1046 -0
- trulens_core-1.0.1/trulens/core/utils/__init__.py +0 -0
- trulens_core-1.0.1/trulens/core/utils/asynchro.py +163 -0
- trulens_core-1.0.1/trulens/core/utils/constants.py +18 -0
- trulens_core-1.0.1/trulens/core/utils/containers.py +193 -0
- trulens_core-1.0.1/trulens/core/utils/deprecation.py +344 -0
- trulens_core-1.0.1/trulens/core/utils/imports.py +681 -0
- trulens_core-1.0.1/trulens/core/utils/json.py +428 -0
- trulens_core-1.0.1/trulens/core/utils/keys.py +436 -0
- trulens_core-1.0.1/trulens/core/utils/pace.py +137 -0
- trulens_core-1.0.1/trulens/core/utils/pyschema.py +730 -0
- trulens_core-1.0.1/trulens/core/utils/python.py +928 -0
- trulens_core-1.0.1/trulens/core/utils/requirements.optional.txt +92 -0
- trulens_core-1.0.1/trulens/core/utils/requirements.txt +5 -0
- trulens_core-1.0.1/trulens/core/utils/serial.py +1226 -0
- trulens_core-1.0.1/trulens/core/utils/text.py +118 -0
- trulens_core-1.0.1/trulens/core/utils/threading.py +222 -0
- trulens_core-1.0.1/trulens/core/utils/trulens.py +33 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: trulens-core
|
|
3
|
+
Version: 1.0.1
|
|
4
|
+
Summary: Library to systematically track and evaluate LLM based applications.
|
|
5
|
+
Home-page: https://trulens.org/
|
|
6
|
+
License: MIT
|
|
7
|
+
Author: Snowflake Inc.
|
|
8
|
+
Author-email: ml-observability-wg-dl@snowflake.com
|
|
9
|
+
Requires-Python: >=3.9,<4.0
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
+
Classifier: Operating System :: OS Independent
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Requires-Dist: alembic (>=1.8.1,<2.0.0)
|
|
19
|
+
Requires-Dist: dill (>=0.3.8,<0.4.0)
|
|
20
|
+
Requires-Dist: munch (>=2.5,<3.0)
|
|
21
|
+
Requires-Dist: nest-asyncio (>=1.5,<2.0)
|
|
22
|
+
Requires-Dist: numpy (>=1.23)
|
|
23
|
+
Requires-Dist: pandas (>=2.1,<3.0)
|
|
24
|
+
Requires-Dist: pydantic (>=2,<3)
|
|
25
|
+
Requires-Dist: python-dotenv (>=0.21,<2.0)
|
|
26
|
+
Requires-Dist: rich (>=13.6,<14.0)
|
|
27
|
+
Requires-Dist: sqlalchemy (>=2.0,<3.0)
|
|
28
|
+
Requires-Dist: tqdm (>=4.2.0)
|
|
29
|
+
Requires-Dist: typing_extensions (>=4.9,<5.0)
|
|
30
|
+
Project-URL: Documentation, https://trulens.org/trulens/getting_started/
|
|
31
|
+
Project-URL: Repository, https://github.com/truera/trulens
|
|
32
|
+
Description-Content-Type: text/markdown
|
|
33
|
+
|
|
34
|
+
# trulens-core
|
|
35
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# trulens-core
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
build-backend = "poetry.core.masonry.api"
|
|
3
|
+
requires = [
|
|
4
|
+
"poetry-core",
|
|
5
|
+
]
|
|
6
|
+
|
|
7
|
+
[tool.poetry]
|
|
8
|
+
name = "trulens-core"
|
|
9
|
+
version = "1.0.1"
|
|
10
|
+
description = "Library to systematically track and evaluate LLM based applications."
|
|
11
|
+
authors = [
|
|
12
|
+
"Snowflake Inc. <ml-observability-wg-dl@snowflake.com>",
|
|
13
|
+
]
|
|
14
|
+
license = "MIT"
|
|
15
|
+
readme = "README.md"
|
|
16
|
+
packages = [
|
|
17
|
+
{ include = "trulens" },
|
|
18
|
+
]
|
|
19
|
+
homepage = "https://trulens.org/"
|
|
20
|
+
documentation = "https://trulens.org/trulens/getting_started/"
|
|
21
|
+
repository = "https://github.com/truera/trulens"
|
|
22
|
+
classifiers = [
|
|
23
|
+
"Programming Language :: Python :: 3",
|
|
24
|
+
"Operating System :: OS Independent",
|
|
25
|
+
"Development Status :: 3 - Alpha",
|
|
26
|
+
"License :: OSI Approved :: MIT License",
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
[tool.poetry.dependencies]
|
|
30
|
+
python = "^3.9"
|
|
31
|
+
numpy = ">=1.23"
|
|
32
|
+
munch = "^2.5"
|
|
33
|
+
dill = "^0.3.8"
|
|
34
|
+
typing_extensions = "^4.9"
|
|
35
|
+
pydantic = "^2"
|
|
36
|
+
pandas = "^2.1"
|
|
37
|
+
rich = "^13.6"
|
|
38
|
+
sqlalchemy = "^2.0"
|
|
39
|
+
alembic = "^1.8.1"
|
|
40
|
+
nest-asyncio = "^1.5"
|
|
41
|
+
python-dotenv = ">=0.21,<2.0"
|
|
42
|
+
tqdm = { version = ">=4.2.0", optional = true }
|
|
43
|
+
|
|
44
|
+
[tool.poetry.group.openai]
|
|
45
|
+
optional = true
|
|
46
|
+
|
|
47
|
+
[tool.poetry.group.openai.dependencies]
|
|
48
|
+
openai = "^1.37"
|
|
49
|
+
httpx = "^0.27"
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
"""
|
|
2
|
+
# Basic input output instrumentation and monitoring.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from inspect import BoundArguments
|
|
6
|
+
from inspect import Signature
|
|
7
|
+
from inspect import signature
|
|
8
|
+
import logging
|
|
9
|
+
from pprint import PrettyPrinter
|
|
10
|
+
from typing import Any, Callable, ClassVar, Dict, Optional
|
|
11
|
+
|
|
12
|
+
from pydantic import Field
|
|
13
|
+
from trulens.core.app import App
|
|
14
|
+
from trulens.core.instruments import ClassFilter
|
|
15
|
+
from trulens.core.instruments import Instrument
|
|
16
|
+
from trulens.core.utils.pyschema import Class
|
|
17
|
+
from trulens.core.utils.pyschema import FunctionOrMethod
|
|
18
|
+
|
|
19
|
+
logger = logging.getLogger(__name__)
|
|
20
|
+
|
|
21
|
+
pp = PrettyPrinter()
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class TruWrapperApp:
|
|
25
|
+
"""Wrapper of basic apps.
|
|
26
|
+
|
|
27
|
+
This will be wrapped by instrumentation.
|
|
28
|
+
|
|
29
|
+
Warning:
|
|
30
|
+
Because `TruWrapperApp` may wrap different types of callables, we cannot
|
|
31
|
+
patch the signature to anything consistent. Because of this, the
|
|
32
|
+
dashboard/record for this call will have `*args`, `**kwargs` instead of
|
|
33
|
+
what the app actually uses. We also need to adjust the main_input lookup
|
|
34
|
+
to get the correct signature. See note there.
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
def _call(self, *args, **kwargs):
|
|
38
|
+
return self._call_fn(*args, **kwargs)
|
|
39
|
+
|
|
40
|
+
def __call__(self, *args, **kwargs):
|
|
41
|
+
return self._call(*args, **kwargs)
|
|
42
|
+
|
|
43
|
+
def __init__(self, call_fn: Callable):
|
|
44
|
+
self._call_fn = call_fn
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class TruBasicCallableInstrument(Instrument):
|
|
48
|
+
"""Basic app instrumentation."""
|
|
49
|
+
|
|
50
|
+
class Default:
|
|
51
|
+
"""Default instrumentation specification for basic apps."""
|
|
52
|
+
|
|
53
|
+
CLASSES = lambda: {TruWrapperApp}
|
|
54
|
+
|
|
55
|
+
# Instrument only methods with these names and of these classes.
|
|
56
|
+
METHODS: Dict[str, ClassFilter] = {"_call": TruWrapperApp}
|
|
57
|
+
|
|
58
|
+
def __init__(self, *args, **kwargs):
|
|
59
|
+
super().__init__(
|
|
60
|
+
include_classes=TruBasicCallableInstrument.Default.CLASSES(),
|
|
61
|
+
include_methods=TruBasicCallableInstrument.Default.METHODS,
|
|
62
|
+
*args,
|
|
63
|
+
**kwargs,
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class TruBasicApp(App):
|
|
68
|
+
"""Instantiates a Basic app that makes little assumptions.
|
|
69
|
+
|
|
70
|
+
Assumes input text and output text.
|
|
71
|
+
|
|
72
|
+
Example:
|
|
73
|
+
```python
|
|
74
|
+
def custom_application(prompt: str) -> str:
|
|
75
|
+
return "a response"
|
|
76
|
+
|
|
77
|
+
from trulens.apps.basic import TruBasicApp
|
|
78
|
+
# f_lang_match, f_qa_relevance, f_context_relevance are feedback functions
|
|
79
|
+
tru_recorder = TruBasicApp(custom_application,
|
|
80
|
+
app_name="Custom Application",
|
|
81
|
+
app_version="1",
|
|
82
|
+
feedbacks=[f_lang_match, f_qa_relevance, f_context_relevance])
|
|
83
|
+
|
|
84
|
+
# Basic app works by turning your callable into an app
|
|
85
|
+
# This app is accessible with the `app` attribute in the recorder
|
|
86
|
+
with tru_recorder as recording:
|
|
87
|
+
tru_recorder.app(question)
|
|
88
|
+
|
|
89
|
+
tru_record = recording.records[0]
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
See [Feedback
|
|
93
|
+
Functions](https://www.trulens.org/trulens/api/feedback/) for
|
|
94
|
+
instantiating feedback functions.
|
|
95
|
+
|
|
96
|
+
Args:
|
|
97
|
+
text_to_text: A str to str callable.
|
|
98
|
+
|
|
99
|
+
app: A TruWrapperApp instance. If not provided, `text_to_text` must
|
|
100
|
+
be provided.
|
|
101
|
+
|
|
102
|
+
**kwargs: Additional arguments to pass to [App][trulens.core.app.App]
|
|
103
|
+
and [AppDefinition][trulens.core.schema.app.AppDefinition]
|
|
104
|
+
"""
|
|
105
|
+
|
|
106
|
+
model_config: ClassVar[dict] = dict(arbitrary_types_allowed=True)
|
|
107
|
+
|
|
108
|
+
app: TruWrapperApp
|
|
109
|
+
"""The app to be instrumented."""
|
|
110
|
+
|
|
111
|
+
root_callable: ClassVar[FunctionOrMethod] = Field(
|
|
112
|
+
default_factory=lambda: FunctionOrMethod.of_callable(
|
|
113
|
+
TruWrapperApp._call
|
|
114
|
+
)
|
|
115
|
+
)
|
|
116
|
+
"""The root callable to be instrumented.
|
|
117
|
+
|
|
118
|
+
This is the method that will be called by the main_input method."""
|
|
119
|
+
|
|
120
|
+
def __init__(
|
|
121
|
+
self,
|
|
122
|
+
text_to_text: Optional[Callable[[str], str]] = None,
|
|
123
|
+
app: Optional[TruWrapperApp] = None,
|
|
124
|
+
**kwargs: Any,
|
|
125
|
+
):
|
|
126
|
+
if text_to_text is not None:
|
|
127
|
+
app = TruWrapperApp(text_to_text)
|
|
128
|
+
else:
|
|
129
|
+
assert (
|
|
130
|
+
app is not None
|
|
131
|
+
), "Need to provide either `app: TruWrapperApp` or a `text_to_text: Callable`."
|
|
132
|
+
|
|
133
|
+
kwargs["app"] = app
|
|
134
|
+
kwargs["root_class"] = Class.of_object(app)
|
|
135
|
+
kwargs["instrument"] = TruBasicCallableInstrument(app=self)
|
|
136
|
+
|
|
137
|
+
super().__init__(**kwargs)
|
|
138
|
+
|
|
139
|
+
def main_call(self, human: str) -> str:
|
|
140
|
+
# If available, a single text to a single text invocation of this app.
|
|
141
|
+
|
|
142
|
+
return self.app._call(human)
|
|
143
|
+
|
|
144
|
+
def main_input(
|
|
145
|
+
self, func: Callable, sig: Signature, bindings: BoundArguments
|
|
146
|
+
) -> str:
|
|
147
|
+
if func == getattr(TruWrapperApp._call, Instrument.INSTRUMENT):
|
|
148
|
+
# If func is the wrapper app _call, replace the signature and
|
|
149
|
+
# bindings based on the actual containing callable instead of
|
|
150
|
+
# self.app._call . This needs to be done since the a TruWrapperApp
|
|
151
|
+
# may be wrapping apps with different signatures on their callables
|
|
152
|
+
# so TruWrapperApp._call cannot have a consistent signature
|
|
153
|
+
# statically. Note also we are looking up the Instrument.INSTRUMENT
|
|
154
|
+
# attribute here since the method is instrumented and overridden by
|
|
155
|
+
# another wrapper in the process with the original accessible at
|
|
156
|
+
# this attribute.
|
|
157
|
+
|
|
158
|
+
sig = signature(self.app._call_fn)
|
|
159
|
+
# Skipping self as TruWrapperApp._call takes in self, but
|
|
160
|
+
# self.app._call_fn does not.
|
|
161
|
+
bindings = sig.bind(*bindings.args[1:], **bindings.kwargs)
|
|
162
|
+
|
|
163
|
+
return super().main_input(func, sig, bindings)
|
|
164
|
+
|
|
165
|
+
def call_with_record(self, *args, **kwargs) -> None:
|
|
166
|
+
self._throw_dep_message(method="call", is_async=False, with_record=True)
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
TruBasicApp.model_rebuild()
|