variably-sdk 2.3.0__tar.gz → 2.5.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.
Files changed (20) hide show
  1. {variably_sdk-2.3.0 → variably_sdk-2.5.0}/PKG-INFO +1 -1
  2. {variably_sdk-2.3.0 → variably_sdk-2.5.0}/pyproject.toml +1 -1
  3. {variably_sdk-2.3.0 → variably_sdk-2.5.0}/setup.py +1 -1
  4. {variably_sdk-2.3.0 → variably_sdk-2.5.0}/src/variably/client.py +99 -0
  5. {variably_sdk-2.3.0 → variably_sdk-2.5.0}/src/variably/http_client.py +9 -0
  6. {variably_sdk-2.3.0 → variably_sdk-2.5.0}/src/variably/types.py +16 -1
  7. {variably_sdk-2.3.0 → variably_sdk-2.5.0}/src/variably_sdk.egg-info/PKG-INFO +1 -1
  8. {variably_sdk-2.3.0 → variably_sdk-2.5.0}/README.md +0 -0
  9. {variably_sdk-2.3.0 → variably_sdk-2.5.0}/setup.cfg +0 -0
  10. {variably_sdk-2.3.0 → variably_sdk-2.5.0}/src/variably/__init__.py +0 -0
  11. {variably_sdk-2.3.0 → variably_sdk-2.5.0}/src/variably/cache.py +0 -0
  12. {variably_sdk-2.3.0 → variably_sdk-2.5.0}/src/variably/config.py +0 -0
  13. {variably_sdk-2.3.0 → variably_sdk-2.5.0}/src/variably/errors.py +0 -0
  14. {variably_sdk-2.3.0 → variably_sdk-2.5.0}/src/variably/logger.py +0 -0
  15. {variably_sdk-2.3.0 → variably_sdk-2.5.0}/src/variably/version.py +0 -0
  16. {variably_sdk-2.3.0 → variably_sdk-2.5.0}/src/variably_sdk.egg-info/SOURCES.txt +0 -0
  17. {variably_sdk-2.3.0 → variably_sdk-2.5.0}/src/variably_sdk.egg-info/dependency_links.txt +0 -0
  18. {variably_sdk-2.3.0 → variably_sdk-2.5.0}/src/variably_sdk.egg-info/requires.txt +0 -0
  19. {variably_sdk-2.3.0 → variably_sdk-2.5.0}/src/variably_sdk.egg-info/top_level.txt +0 -0
  20. {variably_sdk-2.3.0 → variably_sdk-2.5.0}/tests/test_streaming.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: variably-sdk
3
- Version: 2.3.0
3
+ Version: 2.5.0
4
4
  Summary: Official Python SDK for Variably feature flags, LLM experimentation, and prompt optimization platform
5
5
  Author: Variably
6
6
  Author-email: Variably <support@variably.com>
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "variably-sdk"
7
- version = "2.3.0"
7
+ version = "2.5.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"
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
2
2
 
3
3
  setup(
4
4
  name="variably",
5
- version="1.0.0",
5
+ version="2.4.0",
6
6
  description="Variably Python SDK for LLM experimentation platform",
7
7
  author="Variably",
8
8
  packages=find_packages(),
@@ -14,6 +14,7 @@ from .types import (
14
14
  EvaluateResponse,
15
15
  Event,
16
16
  FlagResult,
17
+ LogResult,
17
18
  PromptVariant,
18
19
  SDKMetrics,
19
20
  StreamingEvaluateResponse,
@@ -595,6 +596,104 @@ class VariablyClient:
595
596
 
596
597
  return SubmitResponseResult(status=result.get("status", "ok"))
597
598
 
599
+ def log(
600
+ self,
601
+ prompt: Union[str, List[Dict[str, Any]]],
602
+ response: str,
603
+ *,
604
+ conversation_history: Optional[List[Dict[str, Any]]] = None,
605
+ reference_materials: Optional[List[Dict[str, Any]]] = None,
606
+ retrieval_query: Optional[str] = None,
607
+ tags: Optional[List[str]] = None,
608
+ user_id: Optional[str] = None,
609
+ session_id: Optional[str] = None,
610
+ provider: Optional[str] = None,
611
+ model: Optional[str] = None,
612
+ latency_ms: Optional[int] = None,
613
+ prompt_tokens: Optional[int] = None,
614
+ completion_tokens: Optional[int] = None,
615
+ cost: Optional[float] = None,
616
+ metadata: Optional[Dict[str, Any]] = None,
617
+ ) -> LogResult:
618
+ """Log a prompt/response pair for 43-dimension evaluation (Observe Mode).
619
+
620
+ Zero-friction entry point — no experiment creation needed. Just log your
621
+ prompts and responses and see quality scores in the dashboard.
622
+
623
+ Args:
624
+ prompt: The prompt sent to the LLM (str or messages list).
625
+ response: The LLM's response text.
626
+ conversation_history: Prior conversation turns for cross-turn coherence scoring.
627
+ reference_materials: Retrieved RAG chunks for grounding/hallucination scoring.
628
+ retrieval_query: The query sent to the retriever (for retrieval relevance scoring).
629
+ tags: Optional tags for grouping observations (e.g. ["production", "chatbot"]).
630
+ user_id: End-user ID for per-user analytics.
631
+ session_id: Session ID for multi-turn tracking.
632
+ provider: LLM provider name (e.g. "openai", "anthropic").
633
+ model: Model name (e.g. "gpt-4", "claude-3-opus").
634
+ latency_ms: LLM call latency in milliseconds.
635
+ prompt_tokens: Number of input tokens.
636
+ completion_tokens: Number of output tokens.
637
+ cost: Cost in USD for this LLM call.
638
+ metadata: Arbitrary key-value metadata.
639
+
640
+ Returns:
641
+ LogResult with observation_id and status.
642
+ """
643
+ # Normalize prompt to string
644
+ prompt_str = prompt if isinstance(prompt, str) else str(prompt)
645
+
646
+ data: Dict[str, Any] = {
647
+ "prompt": prompt_str,
648
+ "response": response,
649
+ }
650
+
651
+ # Build evaluation_context from multi-turn/RAG params
652
+ evaluation_context: Dict[str, Any] = {}
653
+ if conversation_history:
654
+ evaluation_context["conversation_history"] = conversation_history
655
+ if reference_materials:
656
+ evaluation_context["reference_materials"] = reference_materials
657
+ if retrieval_query:
658
+ evaluation_context["retrieval_query"] = retrieval_query
659
+ if evaluation_context:
660
+ data["evaluation_context"] = evaluation_context
661
+
662
+ if tags:
663
+ data["tags"] = tags
664
+ if user_id:
665
+ data["user_id"] = user_id
666
+ if session_id:
667
+ data["session_id"] = session_id
668
+ if provider:
669
+ data["provider"] = provider
670
+ if model:
671
+ data["model"] = model
672
+ if latency_ms is not None:
673
+ data["latency_ms"] = latency_ms
674
+ if prompt_tokens is not None:
675
+ data["prompt_tokens"] = prompt_tokens
676
+ if completion_tokens is not None:
677
+ data["completion_tokens"] = completion_tokens
678
+ if cost is not None:
679
+ data["cost"] = cost
680
+ if metadata:
681
+ data["metadata"] = metadata
682
+
683
+ try:
684
+ result = self.http_client.log_observation(data)
685
+ return LogResult(
686
+ observation_id=result.get("observation_id", ""),
687
+ experiment_id=result.get("experiment_id", ""),
688
+ status=result.get("status", "queued"),
689
+ )
690
+ except Exception as error:
691
+ self.logger.error(
692
+ "Observation logging failed",
693
+ {"error": str(error)},
694
+ )
695
+ raise
696
+
598
697
  def clear_cache(self) -> None:
599
698
  """Clear the cache."""
600
699
  self.cache.clear()
@@ -243,6 +243,15 @@ class HTTPClient:
243
243
  retryable=False,
244
244
  )
245
245
 
246
+ def log_observation(self, data: Dict[str, Any]) -> Dict[str, Any]:
247
+ """Log a prompt/response pair for observe-mode evaluation."""
248
+ return self._make_request(
249
+ "POST",
250
+ "/api/v1/internal/sdk/observe/log",
251
+ json=data,
252
+ retryable=False,
253
+ )
254
+
246
255
  def _make_request(
247
256
  self,
248
257
  method: str,
@@ -346,4 +346,19 @@ class SubmitResponseResult:
346
346
  self.status = status
347
347
 
348
348
  def __repr__(self) -> str:
349
- return f"SubmitResponseResult(status='{self.status}')"
349
+ return f"SubmitResponseResult(status='{self.status}')"
350
+
351
+
352
+ class LogResult:
353
+ """Result from observe/log endpoint."""
354
+
355
+ def __init__(self, observation_id: str, experiment_id: str, status: str):
356
+ self.observation_id = observation_id
357
+ self.experiment_id = experiment_id
358
+ self.status = status
359
+
360
+ def __repr__(self) -> str:
361
+ return (
362
+ f"LogResult(observation_id='{self.observation_id}', "
363
+ f"experiment_id='{self.experiment_id}', status='{self.status}')"
364
+ )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: variably-sdk
3
- Version: 2.3.0
3
+ Version: 2.5.0
4
4
  Summary: Official Python SDK for Variably feature flags, LLM experimentation, and prompt optimization platform
5
5
  Author: Variably
6
6
  Author-email: Variably <support@variably.com>
File without changes
File without changes