variably-sdk 2.7.1__tar.gz → 2.9.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.
- {variably_sdk-2.7.1 → variably_sdk-2.9.0}/PKG-INFO +1 -1
- {variably_sdk-2.7.1 → variably_sdk-2.9.0}/pyproject.toml +1 -1
- {variably_sdk-2.7.1 → variably_sdk-2.9.0}/src/variably/client.py +63 -3
- {variably_sdk-2.7.1 → variably_sdk-2.9.0}/src/variably/version.py +1 -1
- {variably_sdk-2.7.1 → variably_sdk-2.9.0}/src/variably_sdk.egg-info/PKG-INFO +1 -1
- {variably_sdk-2.7.1 → variably_sdk-2.9.0}/README.md +0 -0
- {variably_sdk-2.7.1 → variably_sdk-2.9.0}/setup.cfg +0 -0
- {variably_sdk-2.7.1 → variably_sdk-2.9.0}/setup.py +0 -0
- {variably_sdk-2.7.1 → variably_sdk-2.9.0}/src/variably/__init__.py +0 -0
- {variably_sdk-2.7.1 → variably_sdk-2.9.0}/src/variably/cache.py +0 -0
- {variably_sdk-2.7.1 → variably_sdk-2.9.0}/src/variably/config.py +0 -0
- {variably_sdk-2.7.1 → variably_sdk-2.9.0}/src/variably/errors.py +0 -0
- {variably_sdk-2.7.1 → variably_sdk-2.9.0}/src/variably/http_client.py +0 -0
- {variably_sdk-2.7.1 → variably_sdk-2.9.0}/src/variably/logger.py +0 -0
- {variably_sdk-2.7.1 → variably_sdk-2.9.0}/src/variably/observe.py +0 -0
- {variably_sdk-2.7.1 → variably_sdk-2.9.0}/src/variably/types.py +0 -0
- {variably_sdk-2.7.1 → variably_sdk-2.9.0}/src/variably_sdk.egg-info/SOURCES.txt +0 -0
- {variably_sdk-2.7.1 → variably_sdk-2.9.0}/src/variably_sdk.egg-info/dependency_links.txt +0 -0
- {variably_sdk-2.7.1 → variably_sdk-2.9.0}/src/variably_sdk.egg-info/requires.txt +0 -0
- {variably_sdk-2.7.1 → variably_sdk-2.9.0}/src/variably_sdk.egg-info/top_level.txt +0 -0
- {variably_sdk-2.7.1 → variably_sdk-2.9.0}/tests/test_streaming.py +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "variably-sdk"
|
|
7
|
-
version = "2.
|
|
7
|
+
version = "2.9.0"
|
|
8
8
|
description = "Official Python SDK for Variably feature flags, LLM experimentation, and prompt optimization platform"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.7"
|
|
@@ -554,6 +554,20 @@ class VariablyClient:
|
|
|
554
554
|
|
|
555
555
|
return StreamingEvaluateResponse(raw_response)
|
|
556
556
|
|
|
557
|
+
# Allowed values for the `kind` parameter on submit_response. Marks
|
|
558
|
+
# what type of LLM turn this is so the dashboard can suppress
|
|
559
|
+
# grounding/hallucination/attribution scoring on turns where those
|
|
560
|
+
# dimensions don't apply (router, classifier, tool-use). Default
|
|
561
|
+
# "generative" preserves existing behavior for callers not yet on
|
|
562
|
+
# this version.
|
|
563
|
+
_SUBMIT_RESPONSE_KINDS = (
|
|
564
|
+
"generative", # default — narrative answer; full 41D scoring
|
|
565
|
+
"classifier", # intent / safety / routing decision; no claims
|
|
566
|
+
"router", # workflow control turn; no claims
|
|
567
|
+
"tool_use", # function/tool call; no narrative response
|
|
568
|
+
"transformer", # query rewrite / expansion / summarization step
|
|
569
|
+
)
|
|
570
|
+
|
|
557
571
|
def submit_response(
|
|
558
572
|
self,
|
|
559
573
|
experiment_key: str,
|
|
@@ -568,8 +582,33 @@ class VariablyClient:
|
|
|
568
582
|
prompt_tokens: Optional[int] = None,
|
|
569
583
|
completion_tokens: Optional[int] = None,
|
|
570
584
|
evaluation_context: Optional[Dict[str, Any]] = None,
|
|
585
|
+
tags: Optional[List[str]] = None,
|
|
586
|
+
metadata: Optional[Dict[str, Any]] = None,
|
|
587
|
+
kind: Optional[str] = None,
|
|
571
588
|
) -> SubmitResponseResult:
|
|
572
|
-
"""Submit your own LLM response for 41-dimensional evaluation (BYOR step 3).
|
|
589
|
+
"""Submit your own LLM response for 41-dimensional evaluation (BYOR step 3).
|
|
590
|
+
|
|
591
|
+
Args:
|
|
592
|
+
tags: Grouping labels for filtering (e.g. ["production", "rag-v2"]).
|
|
593
|
+
metadata: Arbitrary key-value data attached to this evaluation
|
|
594
|
+
(e.g. {"customer_id": "...", "release": "..."}).
|
|
595
|
+
kind: What type of LLM turn this is. One of:
|
|
596
|
+
- "generative" (default) — a narrative answer with claims
|
|
597
|
+
to ground. Full 41-dimensional scoring applies.
|
|
598
|
+
- "classifier" — an intent / safety / routing decision
|
|
599
|
+
(e.g. {"is_relevant": true, "should_generate": true}).
|
|
600
|
+
No factual claims, so grounding/hallucination/attribution
|
|
601
|
+
scores will be suppressed in dashboards.
|
|
602
|
+
- "router" — a workflow control turn (chooses next node).
|
|
603
|
+
- "tool_use" — a function/tool call with no narrative.
|
|
604
|
+
- "transformer" — a query rewrite / expansion / summary
|
|
605
|
+
step that's part of the pipeline, not the answer.
|
|
606
|
+
|
|
607
|
+
When non-generative kinds are passed, the SDK injects the
|
|
608
|
+
kind into tags (as `kind:<value>`) and metadata so the
|
|
609
|
+
dashboard can filter and skip grounding scores. Latency,
|
|
610
|
+
token, and variant-level analytics still work.
|
|
611
|
+
"""
|
|
573
612
|
if not experiment_key or not isinstance(experiment_key, str):
|
|
574
613
|
raise ConfigurationError(
|
|
575
614
|
"Experiment key must be a non-empty string", "experiment_key"
|
|
@@ -578,6 +617,22 @@ class VariablyClient:
|
|
|
578
617
|
raise ConfigurationError(
|
|
579
618
|
"Variant key must be a non-empty string", "variant_key"
|
|
580
619
|
)
|
|
620
|
+
if kind is not None and kind not in self._SUBMIT_RESPONSE_KINDS:
|
|
621
|
+
raise ConfigurationError(
|
|
622
|
+
f"kind must be one of {self._SUBMIT_RESPONSE_KINDS}, got {kind!r}",
|
|
623
|
+
"kind",
|
|
624
|
+
)
|
|
625
|
+
|
|
626
|
+
# Inject kind into tags + metadata so the dashboard can filter
|
|
627
|
+
# without needing a backend deploy. Preserves any caller-supplied
|
|
628
|
+
# values; we only add, never overwrite.
|
|
629
|
+
if kind and kind != "generative":
|
|
630
|
+
kind_tag = f"kind:{kind}"
|
|
631
|
+
tags = list(tags) if tags else []
|
|
632
|
+
if kind_tag not in tags:
|
|
633
|
+
tags.append(kind_tag)
|
|
634
|
+
metadata = dict(metadata) if metadata else {}
|
|
635
|
+
metadata.setdefault("kind", kind)
|
|
581
636
|
|
|
582
637
|
data: Dict[str, Any] = {
|
|
583
638
|
"experiment_key": experiment_key,
|
|
@@ -586,8 +641,7 @@ class VariablyClient:
|
|
|
586
641
|
"response": response,
|
|
587
642
|
}
|
|
588
643
|
if user_context:
|
|
589
|
-
|
|
590
|
-
data["user_context"] = self.http_client._convert_user_context(dict(user_context))
|
|
644
|
+
data["user_context"] = dict(user_context)
|
|
591
645
|
if input_variables:
|
|
592
646
|
data["input_variables"] = input_variables
|
|
593
647
|
if provider:
|
|
@@ -602,6 +656,12 @@ class VariablyClient:
|
|
|
602
656
|
data["completion_tokens"] = completion_tokens
|
|
603
657
|
if evaluation_context:
|
|
604
658
|
data["evaluation_context"] = evaluation_context
|
|
659
|
+
if tags:
|
|
660
|
+
data["tags"] = tags
|
|
661
|
+
if metadata:
|
|
662
|
+
data["metadata"] = metadata
|
|
663
|
+
if kind:
|
|
664
|
+
data["kind"] = kind
|
|
605
665
|
|
|
606
666
|
result = self.http_client.submit_response(data)
|
|
607
667
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|