decimalai 0.3.0__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.
- decimalai-0.3.0/.github/workflows/ci.yml +46 -0
- decimalai-0.3.0/.github/workflows/publish.yml +65 -0
- decimalai-0.3.0/.gitignore +37 -0
- decimalai-0.3.0/LICENSE +0 -0
- decimalai-0.3.0/PKG-INFO +78 -0
- decimalai-0.3.0/README.md +41 -0
- decimalai-0.3.0/decimalai/__init__.py +298 -0
- decimalai-0.3.0/decimalai/_client.py +334 -0
- decimalai-0.3.0/decimalai/_config.py +149 -0
- decimalai-0.3.0/decimalai/autogen.py +40 -0
- decimalai-0.3.0/decimalai/cli/__init__.py +0 -0
- decimalai-0.3.0/decimalai/cli/dataset_cmd.py +0 -0
- decimalai-0.3.0/decimalai/cli/main.py +75 -0
- decimalai-0.3.0/decimalai/cli/manifest_cmd.py +0 -0
- decimalai-0.3.0/decimalai/cli/replay_cmd.py +0 -0
- decimalai-0.3.0/decimalai/evals/__init__.py +557 -0
- decimalai-0.3.0/decimalai/evals/adapters.py +208 -0
- decimalai-0.3.0/decimalai/evals/builtin.py +84 -0
- decimalai-0.3.0/decimalai/export/__init__.py +0 -0
- decimalai-0.3.0/decimalai/export/jsonl.py +0 -0
- decimalai-0.3.0/decimalai/export/parquet.py +0 -0
- decimalai-0.3.0/decimalai/generic.py +338 -0
- decimalai-0.3.0/decimalai/integrations/__init__.py +5 -0
- decimalai-0.3.0/decimalai/integrations/_lc_compat.py +340 -0
- decimalai-0.3.0/decimalai/integrations/langgraph.py +0 -0
- decimalai-0.3.0/decimalai/integrations/openai.py +0 -0
- decimalai-0.3.0/decimalai/integrations/otel.py +297 -0
- decimalai-0.3.0/decimalai/langchain.py +842 -0
- decimalai-0.3.0/decimalai/llamaindex.py +40 -0
- decimalai-0.3.0/decimalai/manifest/__init__.py +0 -0
- decimalai-0.3.0/decimalai/manifest/detector.py +0 -0
- decimalai-0.3.0/decimalai/manifest/extractor.py +0 -0
- decimalai-0.3.0/decimalai/manifest/hasher.py +0 -0
- decimalai-0.3.0/decimalai/openai_agents.py +42 -0
- decimalai-0.3.0/decimalai/replay/__init__.py +0 -0
- decimalai-0.3.0/decimalai/replay/tasks.py +0 -0
- decimalai-0.3.0/decimalai/schema/__init__.py +16 -0
- decimalai-0.3.0/decimalai/schema/common.py +55 -0
- decimalai-0.3.0/decimalai/schema/dataset.py +0 -0
- decimalai-0.3.0/decimalai/schema/manifest.py +306 -0
- decimalai-0.3.0/decimalai/schema/trace.py +110 -0
- decimalai-0.3.0/examples/demo_mock_agent.py +561 -0
- decimalai-0.3.0/examples/demo_real_agent.py +299 -0
- decimalai-0.3.0/pyproject.toml +44 -0
- decimalai-0.3.0/pyrightconfig.json +11 -0
- decimalai-0.3.0/tests/test_audit_improvements.py +455 -0
- decimalai-0.3.0/tests/test_cli.py +39 -0
- decimalai-0.3.0/tests/test_client.py +124 -0
- decimalai-0.3.0/tests/test_future_proofing.py +386 -0
- decimalai-0.3.0/tests/test_langchain_compat.py +474 -0
- decimalai-0.3.0/tests/test_manifest.py +232 -0
- decimalai-0.3.0/tests/test_rate_limit_handling.py +164 -0
- decimalai-0.3.0/tests/test_sdk.py +274 -0
- decimalai-0.3.0/tests/test_sdk_core.py +428 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
name: Test (Python ${{ matrix.python-version }})
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
strategy:
|
|
14
|
+
matrix:
|
|
15
|
+
python-version: ["3.9", "3.11", "3.12"]
|
|
16
|
+
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@v4
|
|
19
|
+
|
|
20
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
21
|
+
uses: actions/setup-python@v5
|
|
22
|
+
with:
|
|
23
|
+
python-version: ${{ matrix.python-version }}
|
|
24
|
+
|
|
25
|
+
- name: Install dependencies
|
|
26
|
+
run: pip install -e ".[dev]"
|
|
27
|
+
|
|
28
|
+
- name: Run tests
|
|
29
|
+
run: pytest tests/ -v
|
|
30
|
+
|
|
31
|
+
lint:
|
|
32
|
+
name: Lint
|
|
33
|
+
runs-on: ubuntu-latest
|
|
34
|
+
steps:
|
|
35
|
+
- uses: actions/checkout@v4
|
|
36
|
+
|
|
37
|
+
- name: Set up Python
|
|
38
|
+
uses: actions/setup-python@v5
|
|
39
|
+
with:
|
|
40
|
+
python-version: "3.12"
|
|
41
|
+
|
|
42
|
+
- name: Install dependencies
|
|
43
|
+
run: pip install ruff
|
|
44
|
+
|
|
45
|
+
- name: Check formatting
|
|
46
|
+
run: ruff check decimalai/ --select I,E,W,F --ignore E501
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
id-token: write # Required for Trusted Publisher (OIDC)
|
|
9
|
+
contents: read
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
test:
|
|
13
|
+
name: Run Tests
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
strategy:
|
|
16
|
+
matrix:
|
|
17
|
+
python-version: ["3.9", "3.11", "3.12"]
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@v4
|
|
20
|
+
|
|
21
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
22
|
+
uses: actions/setup-python@v5
|
|
23
|
+
with:
|
|
24
|
+
python-version: ${{ matrix.python-version }}
|
|
25
|
+
|
|
26
|
+
- name: Install dependencies
|
|
27
|
+
run: |
|
|
28
|
+
pip install -e ".[dev]"
|
|
29
|
+
|
|
30
|
+
- name: Run tests
|
|
31
|
+
run: pytest tests/ -v
|
|
32
|
+
|
|
33
|
+
publish:
|
|
34
|
+
name: Publish to PyPI
|
|
35
|
+
needs: test # Only publish if tests pass
|
|
36
|
+
runs-on: ubuntu-latest
|
|
37
|
+
environment: pypi # Optional: use GitHub Environment for approvals
|
|
38
|
+
|
|
39
|
+
steps:
|
|
40
|
+
- uses: actions/checkout@v4
|
|
41
|
+
|
|
42
|
+
- name: Set up Python
|
|
43
|
+
uses: actions/setup-python@v5
|
|
44
|
+
with:
|
|
45
|
+
python-version: "3.12"
|
|
46
|
+
|
|
47
|
+
- name: Install build tools
|
|
48
|
+
run: pip install build
|
|
49
|
+
|
|
50
|
+
- name: Build package
|
|
51
|
+
run: python -m build
|
|
52
|
+
|
|
53
|
+
- name: Verify package version matches release tag
|
|
54
|
+
run: |
|
|
55
|
+
PKG_VERSION=$(python -c "import tomllib; print(tomllib.load(open('pyproject.toml','rb'))['project']['version'])")
|
|
56
|
+
TAG_VERSION="${GITHUB_REF_NAME#v}"
|
|
57
|
+
if [ "$PKG_VERSION" != "$TAG_VERSION" ]; then
|
|
58
|
+
echo "❌ Version mismatch: pyproject.toml=$PKG_VERSION, tag=$TAG_VERSION"
|
|
59
|
+
exit 1
|
|
60
|
+
fi
|
|
61
|
+
echo "✅ Version match: $PKG_VERSION"
|
|
62
|
+
|
|
63
|
+
- name: Publish to PyPI
|
|
64
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
65
|
+
# No API token needed — uses Trusted Publisher (OIDC)
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.so
|
|
6
|
+
*.egg-info/
|
|
7
|
+
*.egg
|
|
8
|
+
dist/
|
|
9
|
+
build/
|
|
10
|
+
.eggs/
|
|
11
|
+
|
|
12
|
+
# Virtual environments
|
|
13
|
+
.venv/
|
|
14
|
+
venv/
|
|
15
|
+
env/
|
|
16
|
+
|
|
17
|
+
# IDE
|
|
18
|
+
.idea/
|
|
19
|
+
.vscode/
|
|
20
|
+
*.swp
|
|
21
|
+
*.swo
|
|
22
|
+
*~
|
|
23
|
+
|
|
24
|
+
# Testing
|
|
25
|
+
.pytest_cache/
|
|
26
|
+
.coverage
|
|
27
|
+
htmlcov/
|
|
28
|
+
.mypy_cache/
|
|
29
|
+
|
|
30
|
+
# OS
|
|
31
|
+
.DS_Store
|
|
32
|
+
Thumbs.db
|
|
33
|
+
|
|
34
|
+
# Env
|
|
35
|
+
.env
|
|
36
|
+
.env.*
|
|
37
|
+
!.env.example
|
decimalai-0.3.0/LICENSE
ADDED
|
File without changes
|
decimalai-0.3.0/PKG-INFO
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: decimalai
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: Open source SDK for agent dataset lifecycle management
|
|
5
|
+
Project-URL: Homepage, https://github.com/decimal-labs/decimalai-python
|
|
6
|
+
Project-URL: Documentation, https://docs.decimal.ai
|
|
7
|
+
Project-URL: Repository, https://github.com/decimal-labs/decimalai-python
|
|
8
|
+
Author: Decimal AI
|
|
9
|
+
License: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Requires-Python: >=3.9
|
|
12
|
+
Requires-Dist: click>=8.0
|
|
13
|
+
Requires-Dist: httpx>=0.24
|
|
14
|
+
Requires-Dist: pydantic>=2.0
|
|
15
|
+
Provides-Extra: all
|
|
16
|
+
Requires-Dist: langchain-core>=0.3; extra == 'all'
|
|
17
|
+
Requires-Dist: langgraph>=0.1; extra == 'all'
|
|
18
|
+
Requires-Dist: openai>=1.0; extra == 'all'
|
|
19
|
+
Provides-Extra: dev
|
|
20
|
+
Requires-Dist: langchain-core>=0.3; extra == 'dev'
|
|
21
|
+
Requires-Dist: pytest-asyncio>=0.21; extra == 'dev'
|
|
22
|
+
Requires-Dist: pytest-mock>=3.0; extra == 'dev'
|
|
23
|
+
Requires-Dist: pytest>=7.0; extra == 'dev'
|
|
24
|
+
Requires-Dist: responses>=0.23; extra == 'dev'
|
|
25
|
+
Provides-Extra: langchain
|
|
26
|
+
Requires-Dist: langchain-core>=0.3; extra == 'langchain'
|
|
27
|
+
Provides-Extra: langgraph
|
|
28
|
+
Requires-Dist: langgraph>=0.1; extra == 'langgraph'
|
|
29
|
+
Provides-Extra: openai
|
|
30
|
+
Requires-Dist: openai>=1.0; extra == 'openai'
|
|
31
|
+
Provides-Extra: openai-agents
|
|
32
|
+
Requires-Dist: openai-agents>=0.1; extra == 'openai-agents'
|
|
33
|
+
Provides-Extra: otel
|
|
34
|
+
Requires-Dist: opentelemetry-api>=1.20; extra == 'otel'
|
|
35
|
+
Requires-Dist: opentelemetry-sdk>=1.20; extra == 'otel'
|
|
36
|
+
Description-Content-Type: text/markdown
|
|
37
|
+
|
|
38
|
+
# DecimalAI Python SDK
|
|
39
|
+
|
|
40
|
+
The open source SDK for [Decimal AI](https://decimal.ai) — the dataset control plane for agents.
|
|
41
|
+
|
|
42
|
+
## Installation
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
pip install decimal-ai
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
With framework integrations:
|
|
49
|
+
```bash
|
|
50
|
+
pip install "decimal-ai[langchain]" # LangChain/LangGraph
|
|
51
|
+
pip install "decimal-ai[openai]" # OpenAI SDK
|
|
52
|
+
pip install "decimal-ai[all]" # All integrations
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Quick Start
|
|
56
|
+
|
|
57
|
+
```python
|
|
58
|
+
import decimalai
|
|
59
|
+
|
|
60
|
+
decimalai.init(api_key="dai_sk_...")
|
|
61
|
+
|
|
62
|
+
# LangChain/LangGraph — add callback handler
|
|
63
|
+
from decimalai.langchain import CallbackHandler
|
|
64
|
+
|
|
65
|
+
llm = ChatOpenAI(model="gpt-4o", callbacks=[CallbackHandler()])
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## What It Does
|
|
69
|
+
|
|
70
|
+
- **Trace capture** — Auto-captures LLM calls, tool calls, and agent steps
|
|
71
|
+
- **Version spec extraction** — Auto-detects tool schemas, prompts, models, and graph topology
|
|
72
|
+
- **Change detection** — Detects when your agent configuration changes
|
|
73
|
+
- **Replay helpers** — Pull and submit replay tasks for data rescue
|
|
74
|
+
- **Dataset export** — Export clean JSONL/parquet for fine-tuning
|
|
75
|
+
|
|
76
|
+
## License
|
|
77
|
+
|
|
78
|
+
MIT
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# DecimalAI Python SDK
|
|
2
|
+
|
|
3
|
+
The open source SDK for [Decimal AI](https://decimal.ai) — the dataset control plane for agents.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install decimal-ai
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
With framework integrations:
|
|
12
|
+
```bash
|
|
13
|
+
pip install "decimal-ai[langchain]" # LangChain/LangGraph
|
|
14
|
+
pip install "decimal-ai[openai]" # OpenAI SDK
|
|
15
|
+
pip install "decimal-ai[all]" # All integrations
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Quick Start
|
|
19
|
+
|
|
20
|
+
```python
|
|
21
|
+
import decimalai
|
|
22
|
+
|
|
23
|
+
decimalai.init(api_key="dai_sk_...")
|
|
24
|
+
|
|
25
|
+
# LangChain/LangGraph — add callback handler
|
|
26
|
+
from decimalai.langchain import CallbackHandler
|
|
27
|
+
|
|
28
|
+
llm = ChatOpenAI(model="gpt-4o", callbacks=[CallbackHandler()])
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## What It Does
|
|
32
|
+
|
|
33
|
+
- **Trace capture** — Auto-captures LLM calls, tool calls, and agent steps
|
|
34
|
+
- **Version spec extraction** — Auto-detects tool schemas, prompts, models, and graph topology
|
|
35
|
+
- **Change detection** — Detects when your agent configuration changes
|
|
36
|
+
- **Replay helpers** — Pull and submit replay tasks for data rescue
|
|
37
|
+
- **Dataset export** — Export clean JSONL/parquet for fine-tuning
|
|
38
|
+
|
|
39
|
+
## License
|
|
40
|
+
|
|
41
|
+
MIT
|
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
"""DecimalAI SDK — Agent dataset lifecycle platform.
|
|
2
|
+
|
|
3
|
+
Quick start::
|
|
4
|
+
|
|
5
|
+
import decimalai
|
|
6
|
+
decimalai.init() # reads DECIMAL_API_KEY from env
|
|
7
|
+
|
|
8
|
+
# LangChain — one-liner
|
|
9
|
+
decimalai.init(langchain=True)
|
|
10
|
+
|
|
11
|
+
# Or manual install
|
|
12
|
+
from decimalai.langchain import install
|
|
13
|
+
install()
|
|
14
|
+
|
|
15
|
+
# Generic / any framework
|
|
16
|
+
@decimalai.trace(agent_name="my-agent")
|
|
17
|
+
def run_agent(query):
|
|
18
|
+
decimalai.log_llm_call(model="gpt-4o", input=msgs, output=resp)
|
|
19
|
+
return resp.choices[0].message.content
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
__version__ = "0.3.0"
|
|
23
|
+
|
|
24
|
+
import logging
|
|
25
|
+
import os
|
|
26
|
+
from typing import Optional
|
|
27
|
+
|
|
28
|
+
logger = logging.getLogger("decimalai")
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def init(
|
|
32
|
+
api_key: Optional[str] = None,
|
|
33
|
+
base_url: Optional[str] = None,
|
|
34
|
+
project: Optional[str] = None,
|
|
35
|
+
enabled: bool = True,
|
|
36
|
+
langchain: bool = False,
|
|
37
|
+
agent_name: Optional[str] = None,
|
|
38
|
+
) -> None:
|
|
39
|
+
"""Initialize the DecimalAI SDK.
|
|
40
|
+
|
|
41
|
+
Must be called once before using any integration. Configuration is
|
|
42
|
+
resolved in order: explicit parameter → environment variable → default.
|
|
43
|
+
|
|
44
|
+
Args:
|
|
45
|
+
api_key: API key. Falls back to ``DECIMAL_API_KEY`` env var.
|
|
46
|
+
base_url: Backend URL. Falls back to ``DECIMAL_BASE_URL``, then
|
|
47
|
+
``https://api.decimal.ai``.
|
|
48
|
+
project: Optional project grouping.
|
|
49
|
+
enabled: Set ``False`` to disable all tracing (integrations become no-ops).
|
|
50
|
+
langchain: If ``True``, auto-calls ``decimalai.langchain.install()``.
|
|
51
|
+
agent_name: Default agent name for langchain auto-install.
|
|
52
|
+
|
|
53
|
+
Raises:
|
|
54
|
+
DecimalConfigError: If ``api_key`` is not provided and not in env.
|
|
55
|
+
"""
|
|
56
|
+
from ._config import DecimalConfig, DecimalConfigError
|
|
57
|
+
from ._client import DecimalAIClient
|
|
58
|
+
|
|
59
|
+
import decimalai._config as _cfg
|
|
60
|
+
|
|
61
|
+
# Resolve API key
|
|
62
|
+
resolved_key = api_key or os.environ.get("DECIMAL_API_KEY", "")
|
|
63
|
+
if not resolved_key and enabled:
|
|
64
|
+
raise DecimalConfigError(
|
|
65
|
+
"No API key provided. Pass api_key= to decimalai.init() "
|
|
66
|
+
"or set the DECIMAL_API_KEY environment variable."
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
# Resolve base URL
|
|
70
|
+
resolved_url = (
|
|
71
|
+
base_url
|
|
72
|
+
or os.environ.get("DECIMAL_BASE_URL", "")
|
|
73
|
+
or "https://api.decimal.ai"
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
config = DecimalConfig(
|
|
77
|
+
api_key=resolved_key,
|
|
78
|
+
base_url=resolved_url.rstrip("/"),
|
|
79
|
+
project=project,
|
|
80
|
+
enabled=enabled,
|
|
81
|
+
)
|
|
82
|
+
_cfg._config = config
|
|
83
|
+
|
|
84
|
+
if enabled:
|
|
85
|
+
_cfg._client = DecimalAIClient(
|
|
86
|
+
api_key=config.api_key,
|
|
87
|
+
base_url=config.base_url,
|
|
88
|
+
project=config.project,
|
|
89
|
+
)
|
|
90
|
+
logger.info(
|
|
91
|
+
"DecimalAI SDK initialized: base_url=%s project=%s",
|
|
92
|
+
config.base_url,
|
|
93
|
+
config.project,
|
|
94
|
+
)
|
|
95
|
+
else:
|
|
96
|
+
_cfg._client = None
|
|
97
|
+
logger.info("DecimalAI SDK initialized in disabled mode (no-op)")
|
|
98
|
+
|
|
99
|
+
# Auto-install langchain tracing if requested
|
|
100
|
+
if langchain:
|
|
101
|
+
from .langchain import install as _lc_install
|
|
102
|
+
_lc_install(agent_name=agent_name)
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def send(trace) -> None:
|
|
106
|
+
"""Manually send a trace to the backend.
|
|
107
|
+
|
|
108
|
+
For advanced usage when ``auto_send=False``.
|
|
109
|
+
"""
|
|
110
|
+
from ._config import _get_client
|
|
111
|
+
|
|
112
|
+
client = _get_client()
|
|
113
|
+
client.ingest_trace(trace)
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
# ── Eval convenience functions ─────────────────────────────────
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def eval(
|
|
120
|
+
trace_id: str,
|
|
121
|
+
name: str,
|
|
122
|
+
score: float,
|
|
123
|
+
*,
|
|
124
|
+
source: str = "custom",
|
|
125
|
+
source_label: Optional[str] = None,
|
|
126
|
+
passed: Optional[bool] = None,
|
|
127
|
+
reason: Optional[str] = None,
|
|
128
|
+
category: str = "quality",
|
|
129
|
+
) -> dict:
|
|
130
|
+
"""Push a single eval score to a trace.
|
|
131
|
+
|
|
132
|
+
This is the simplest way to attach evaluation results to a trace.
|
|
133
|
+
All scores are visible in the dashboard's Evaluation Breakdown card
|
|
134
|
+
grouped by source.
|
|
135
|
+
|
|
136
|
+
Args:
|
|
137
|
+
trace_id: The trace to attach the score to.
|
|
138
|
+
name: Metric name (e.g., "factual_accuracy", "coherence").
|
|
139
|
+
score: Score value between 0.0 and 1.0.
|
|
140
|
+
source: Eval source identifier. Defaults to "custom".
|
|
141
|
+
source_label: Human-readable display name (e.g., "My RAG Eval").
|
|
142
|
+
passed: Binary pass/fail. Defaults to score >= 0.5.
|
|
143
|
+
reason: Human-readable explanation of the score.
|
|
144
|
+
category: "quality" (default) or "compatibility".
|
|
145
|
+
|
|
146
|
+
Returns:
|
|
147
|
+
API response with stored score details and recomputed verdict.
|
|
148
|
+
|
|
149
|
+
Example::
|
|
150
|
+
|
|
151
|
+
import decimalai
|
|
152
|
+
decimalai.init()
|
|
153
|
+
|
|
154
|
+
decimalai.eval(
|
|
155
|
+
trace_id="abc123",
|
|
156
|
+
name="factual_accuracy",
|
|
157
|
+
score=0.75,
|
|
158
|
+
reason="3/4 facts verified against source docs",
|
|
159
|
+
)
|
|
160
|
+
"""
|
|
161
|
+
from ._config import _get_client
|
|
162
|
+
|
|
163
|
+
client = _get_client()
|
|
164
|
+
score_entry = {
|
|
165
|
+
"name": name,
|
|
166
|
+
"score": score,
|
|
167
|
+
"passed": passed if passed is not None else score >= 0.5,
|
|
168
|
+
}
|
|
169
|
+
if reason:
|
|
170
|
+
score_entry["reason"] = reason
|
|
171
|
+
|
|
172
|
+
metadata = {}
|
|
173
|
+
if source_label:
|
|
174
|
+
metadata["source_label"] = source_label
|
|
175
|
+
|
|
176
|
+
return client.push_eval_scores(
|
|
177
|
+
trace_id=trace_id,
|
|
178
|
+
source=source,
|
|
179
|
+
scores=[score_entry],
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
def score(
|
|
184
|
+
trace_id: str,
|
|
185
|
+
name: str,
|
|
186
|
+
value: float,
|
|
187
|
+
reason: Optional[str] = None,
|
|
188
|
+
) -> dict:
|
|
189
|
+
"""Shorthand for pushing a single eval score.
|
|
190
|
+
|
|
191
|
+
Args:
|
|
192
|
+
trace_id: The trace to attach the score to.
|
|
193
|
+
name: Metric name.
|
|
194
|
+
value: Score between 0.0 and 1.0.
|
|
195
|
+
reason: Optional explanation.
|
|
196
|
+
|
|
197
|
+
Returns:
|
|
198
|
+
API response.
|
|
199
|
+
|
|
200
|
+
Example::
|
|
201
|
+
|
|
202
|
+
decimalai.score("abc123", "factual_accuracy", 0.75)
|
|
203
|
+
"""
|
|
204
|
+
return eval(
|
|
205
|
+
trace_id=trace_id,
|
|
206
|
+
name=name,
|
|
207
|
+
score=value,
|
|
208
|
+
reason=reason,
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
def get_eval_breakdown(trace_id: str) -> dict:
|
|
213
|
+
"""Get the full eval breakdown for a trace with provenance info.
|
|
214
|
+
|
|
215
|
+
Returns scores grouped by source (Manifest Diff, DeepEval, LangSmith,
|
|
216
|
+
Custom, etc.) with icons, labels, and decision reasons.
|
|
217
|
+
|
|
218
|
+
Returns:
|
|
219
|
+
Dict with eval_verdict, quality_avg, compat_avg, source_groups,
|
|
220
|
+
and decision_reasons.
|
|
221
|
+
|
|
222
|
+
Example::
|
|
223
|
+
|
|
224
|
+
import decimalai
|
|
225
|
+
decimalai.init()
|
|
226
|
+
|
|
227
|
+
bd = decimalai.get_eval_breakdown("abc123")
|
|
228
|
+
print(f"Verdict: {bd['eval_verdict']}")
|
|
229
|
+
"""
|
|
230
|
+
from ._config import _get_client
|
|
231
|
+
|
|
232
|
+
client = _get_client()
|
|
233
|
+
return client.get_eval_breakdown(trace_id)
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
# ── Re-export generic tracing API ──────────────────────────────
|
|
237
|
+
|
|
238
|
+
from .generic import ( # noqa: E402, F401
|
|
239
|
+
log_llm_call,
|
|
240
|
+
log_tool_call,
|
|
241
|
+
start_trace,
|
|
242
|
+
trace,
|
|
243
|
+
)
|
|
244
|
+
|
|
245
|
+
# Re-export eval adapters from new location
|
|
246
|
+
from .evals.adapters import ( # noqa: E402, F401
|
|
247
|
+
push_deepeval_results,
|
|
248
|
+
push_langsmith_scores,
|
|
249
|
+
push_custom_scores,
|
|
250
|
+
)
|
|
251
|
+
|
|
252
|
+
from .evals import batch_eval # noqa: E402, F401
|
|
253
|
+
|
|
254
|
+
__all__ = [
|
|
255
|
+
"__version__",
|
|
256
|
+
"init",
|
|
257
|
+
"send",
|
|
258
|
+
"eval",
|
|
259
|
+
"score",
|
|
260
|
+
"get_eval_breakdown",
|
|
261
|
+
"trace",
|
|
262
|
+
"start_trace",
|
|
263
|
+
"log_llm_call",
|
|
264
|
+
"log_tool_call",
|
|
265
|
+
"push_deepeval_results",
|
|
266
|
+
"push_langsmith_scores",
|
|
267
|
+
"push_custom_scores",
|
|
268
|
+
"batch_eval",
|
|
269
|
+
]
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
# ── Auto-init from environment variable ────────────────────────
|
|
273
|
+
# Setting DECIMAL_AUTO_TRACE=langchain will auto-init and install tracing.
|
|
274
|
+
|
|
275
|
+
def _auto_init_from_env() -> None:
|
|
276
|
+
"""Auto-initialize from environment variables if configured."""
|
|
277
|
+
auto_trace = os.environ.get("DECIMAL_AUTO_TRACE", "").strip().lower()
|
|
278
|
+
if not auto_trace:
|
|
279
|
+
return
|
|
280
|
+
|
|
281
|
+
api_key = os.environ.get("DECIMAL_API_KEY", "")
|
|
282
|
+
if not api_key:
|
|
283
|
+
logger.debug(
|
|
284
|
+
"DECIMAL_AUTO_TRACE=%s set but no DECIMAL_API_KEY found, skipping",
|
|
285
|
+
auto_trace,
|
|
286
|
+
)
|
|
287
|
+
return
|
|
288
|
+
|
|
289
|
+
try:
|
|
290
|
+
init(
|
|
291
|
+
langchain=(auto_trace == "langchain"),
|
|
292
|
+
)
|
|
293
|
+
logger.info("DecimalAI auto-initialized via DECIMAL_AUTO_TRACE=%s", auto_trace)
|
|
294
|
+
except Exception:
|
|
295
|
+
logger.debug("Auto-init failed", exc_info=True)
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
_auto_init_from_env()
|