variably-sdk 2.6.0__tar.gz → 2.6.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.
Files changed (21) hide show
  1. {variably_sdk-2.6.0 → variably_sdk-2.6.1}/PKG-INFO +108 -36
  2. {variably_sdk-2.6.0 → variably_sdk-2.6.1}/README.md +107 -35
  3. {variably_sdk-2.6.0 → variably_sdk-2.6.1}/pyproject.toml +1 -1
  4. {variably_sdk-2.6.0 → variably_sdk-2.6.1}/src/variably/version.py +1 -1
  5. {variably_sdk-2.6.0 → variably_sdk-2.6.1}/src/variably_sdk.egg-info/PKG-INFO +108 -36
  6. {variably_sdk-2.6.0 → variably_sdk-2.6.1}/setup.cfg +0 -0
  7. {variably_sdk-2.6.0 → variably_sdk-2.6.1}/setup.py +0 -0
  8. {variably_sdk-2.6.0 → variably_sdk-2.6.1}/src/variably/__init__.py +0 -0
  9. {variably_sdk-2.6.0 → variably_sdk-2.6.1}/src/variably/cache.py +0 -0
  10. {variably_sdk-2.6.0 → variably_sdk-2.6.1}/src/variably/client.py +0 -0
  11. {variably_sdk-2.6.0 → variably_sdk-2.6.1}/src/variably/config.py +0 -0
  12. {variably_sdk-2.6.0 → variably_sdk-2.6.1}/src/variably/errors.py +0 -0
  13. {variably_sdk-2.6.0 → variably_sdk-2.6.1}/src/variably/http_client.py +0 -0
  14. {variably_sdk-2.6.0 → variably_sdk-2.6.1}/src/variably/logger.py +0 -0
  15. {variably_sdk-2.6.0 → variably_sdk-2.6.1}/src/variably/observe.py +0 -0
  16. {variably_sdk-2.6.0 → variably_sdk-2.6.1}/src/variably/types.py +0 -0
  17. {variably_sdk-2.6.0 → variably_sdk-2.6.1}/src/variably_sdk.egg-info/SOURCES.txt +0 -0
  18. {variably_sdk-2.6.0 → variably_sdk-2.6.1}/src/variably_sdk.egg-info/dependency_links.txt +0 -0
  19. {variably_sdk-2.6.0 → variably_sdk-2.6.1}/src/variably_sdk.egg-info/requires.txt +0 -0
  20. {variably_sdk-2.6.0 → variably_sdk-2.6.1}/src/variably_sdk.egg-info/top_level.txt +0 -0
  21. {variably_sdk-2.6.0 → variably_sdk-2.6.1}/tests/test_streaming.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: variably-sdk
3
- Version: 2.6.0
3
+ Version: 2.6.1
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>
@@ -45,7 +45,7 @@ Dynamic: requires-python
45
45
 
46
46
  # Variably Python SDK
47
47
 
48
- Official Python SDK for Variably — feature flags, LLM experimentation, and prompt optimization.
48
+ Official Python SDK for Variably — LLM evaluation, experimentation, and prompt optimization.
49
49
 
50
50
  ## Installation
51
51
 
@@ -53,52 +53,124 @@ Official Python SDK for Variably — feature flags, LLM experimentation, and pro
53
53
  pip install variably-sdk
54
54
  ```
55
55
 
56
- ## Quick Start
56
+ ## Quick Start — Observe Mode
57
+
58
+ Add **one line** to your existing LLM app and get **multi-dimension evaluation** across 40+ metrics in 6 categories: Quality, Safety, Semantic, Grounding, Coherence, and Advanced.
59
+
60
+ No experiment setup. No prompt migration. Just log and see scores.
61
+
62
+ ### 1. Set your environment variables
63
+
64
+ ```bash
65
+ VARIABLY_API_KEY=vbl_your_key_here
66
+ VARIABLY_BASE_URL=https://api.variably.tech
67
+ ```
68
+
69
+ ### 2. Add one line after your LLM call
57
70
 
58
71
  ```python
59
- from variably import VariablyClient
72
+ from variably import observe
60
73
 
61
- # Initialize the client
62
- client = VariablyClient({
63
- "api_key": "your-api-key",
64
- "base_url": "https://api.variably.com", # optional, defaults to localhost:8080
65
- "environment": "production" # optional
66
- })
74
+ # Your existing code (unchanged)
75
+ response = your_llm_call(user_query)
67
76
 
68
- # Evaluate a boolean feature flag
69
- user_context = {
70
- "user_id": "user-123",
71
- "email": "user@example.com",
72
- "country": "US"
73
- }
77
+ # Add this line:
78
+ observe(prompt=user_query, response=response)
79
+ ```
74
80
 
75
- is_feature_enabled = client.evaluate_flag_bool(
76
- "new-checkout-flow",
77
- False, # default value
78
- user_context
81
+ ### Auto-extract tokens & model from provider response
82
+
83
+ ```python
84
+ # OpenAI
85
+ from openai import OpenAI
86
+ from variably import observe
87
+
88
+ client = OpenAI()
89
+ completion = client.chat.completions.create(
90
+ model="gpt-4o",
91
+ messages=[{"role": "user", "content": user_query}],
79
92
  )
80
93
 
81
- if is_feature_enabled:
82
- # Show new checkout flow
83
- pass
94
+ observe(
95
+ prompt=user_query,
96
+ response=completion.choices[0].message.content,
97
+ provider_response=completion, # auto-extracts model, tokens
98
+ )
99
+ ```
84
100
 
85
- # Evaluate a feature gate
86
- has_access = client.evaluate_gate("premium-features", user_context)
101
+ ```python
102
+ # Anthropic
103
+ import anthropic
104
+ from variably import observe
105
+
106
+ client = anthropic.Anthropic()
107
+ message = client.messages.create(
108
+ model="claude-sonnet-4-20250514",
109
+ max_tokens=1024,
110
+ messages=[{"role": "user", "content": user_query}],
111
+ )
87
112
 
88
- # Track events
89
- client.track({
90
- "name": "button_clicked",
91
- "user_id": "user-123",
92
- "properties": {
93
- "button_name": "checkout",
94
- "page": "product-detail"
95
- }
96
- })
113
+ observe(
114
+ prompt=user_query,
115
+ response=message.content[0].text,
116
+ provider_response=message, # auto-extracts model, tokens
117
+ )
118
+ ```
97
119
 
98
- # Clean up resources
99
- client.close()
120
+ ### RAG applications — grounding & hallucination scoring
121
+
122
+ ```python
123
+ observe(
124
+ prompt=user_query,
125
+ response=llm_answer,
126
+ provider_response=completion,
127
+ reference_materials=[
128
+ {"id": "chunk-1", "content": "Retrieved text...", "source": "docs.pdf"},
129
+ {"id": "chunk-2", "content": "Another chunk...", "source": "faq.md"},
130
+ ],
131
+ retrieval_query=user_query,
132
+ )
100
133
  ```
101
134
 
135
+ ### Multi-turn chat — coherence scoring
136
+
137
+ ```python
138
+ observe(
139
+ prompt=latest_user_message,
140
+ response=llm_answer,
141
+ provider_response=completion,
142
+ conversation_history=[
143
+ {"role": "user", "content": "What is diabetes?"},
144
+ {"role": "assistant", "content": "Diabetes is a chronic condition..."},
145
+ {"role": "user", "content": "What are the symptoms?"},
146
+ ],
147
+ session_id="conv-123",
148
+ )
149
+ ```
150
+
151
+ ### Full parameter reference
152
+
153
+ | Parameter | Type | Required | Description |
154
+ |-----------|------|----------|-------------|
155
+ | `prompt` | str | Yes | The user's input / question |
156
+ | `response` | str | Yes | The LLM's generated response |
157
+ | `provider_response` | object | No | Raw OpenAI/Anthropic/Google response — auto-extracts model, tokens |
158
+ | `model` | str | No | Model name (auto-extracted if provider_response given) |
159
+ | `provider` | str | No | "openai", "anthropic", etc. (auto-detected) |
160
+ | `latency_ms` | int | No | Response generation time in milliseconds |
161
+ | `prompt_tokens` | int | No | Input token count (auto-extracted if provider_response given) |
162
+ | `completion_tokens` | int | No | Output token count (auto-extracted) |
163
+ | `cost` | float | No | Cost in USD |
164
+ | `reference_materials` | list[dict] | No | RAG chunks: `[{"id", "content", "source"}]` — enables grounding scoring |
165
+ | `retrieval_query` | str | No | Query sent to retriever — enables retrieval quality scoring |
166
+ | `conversation_history` | list[dict] | No | Prior turns: `[{"role", "content"}]` — enables coherence scoring |
167
+ | `tags` | list[str] | No | Grouping labels, e.g. `["production", "rag"]` |
168
+ | `user_id` | str | No | Your user's ID |
169
+ | `session_id` | str | No | Conversation session ID (groups multi-turn) |
170
+ | `metadata` | dict | No | Any extra key-value data |
171
+
172
+ ---
173
+
102
174
  ## Prompt Experimentation
103
175
 
104
176
  Variably provides two modes for LLM prompt experimentation:
@@ -1,6 +1,6 @@
1
1
  # Variably Python SDK
2
2
 
3
- Official Python SDK for Variably — feature flags, LLM experimentation, and prompt optimization.
3
+ Official Python SDK for Variably — LLM evaluation, experimentation, and prompt optimization.
4
4
 
5
5
  ## Installation
6
6
 
@@ -8,52 +8,124 @@ Official Python SDK for Variably — feature flags, LLM experimentation, and pro
8
8
  pip install variably-sdk
9
9
  ```
10
10
 
11
- ## Quick Start
11
+ ## Quick Start — Observe Mode
12
+
13
+ Add **one line** to your existing LLM app and get **multi-dimension evaluation** across 40+ metrics in 6 categories: Quality, Safety, Semantic, Grounding, Coherence, and Advanced.
14
+
15
+ No experiment setup. No prompt migration. Just log and see scores.
16
+
17
+ ### 1. Set your environment variables
18
+
19
+ ```bash
20
+ VARIABLY_API_KEY=vbl_your_key_here
21
+ VARIABLY_BASE_URL=https://api.variably.tech
22
+ ```
23
+
24
+ ### 2. Add one line after your LLM call
12
25
 
13
26
  ```python
14
- from variably import VariablyClient
27
+ from variably import observe
15
28
 
16
- # Initialize the client
17
- client = VariablyClient({
18
- "api_key": "your-api-key",
19
- "base_url": "https://api.variably.com", # optional, defaults to localhost:8080
20
- "environment": "production" # optional
21
- })
29
+ # Your existing code (unchanged)
30
+ response = your_llm_call(user_query)
22
31
 
23
- # Evaluate a boolean feature flag
24
- user_context = {
25
- "user_id": "user-123",
26
- "email": "user@example.com",
27
- "country": "US"
28
- }
32
+ # Add this line:
33
+ observe(prompt=user_query, response=response)
34
+ ```
29
35
 
30
- is_feature_enabled = client.evaluate_flag_bool(
31
- "new-checkout-flow",
32
- False, # default value
33
- user_context
36
+ ### Auto-extract tokens & model from provider response
37
+
38
+ ```python
39
+ # OpenAI
40
+ from openai import OpenAI
41
+ from variably import observe
42
+
43
+ client = OpenAI()
44
+ completion = client.chat.completions.create(
45
+ model="gpt-4o",
46
+ messages=[{"role": "user", "content": user_query}],
34
47
  )
35
48
 
36
- if is_feature_enabled:
37
- # Show new checkout flow
38
- pass
49
+ observe(
50
+ prompt=user_query,
51
+ response=completion.choices[0].message.content,
52
+ provider_response=completion, # auto-extracts model, tokens
53
+ )
54
+ ```
39
55
 
40
- # Evaluate a feature gate
41
- has_access = client.evaluate_gate("premium-features", user_context)
56
+ ```python
57
+ # Anthropic
58
+ import anthropic
59
+ from variably import observe
60
+
61
+ client = anthropic.Anthropic()
62
+ message = client.messages.create(
63
+ model="claude-sonnet-4-20250514",
64
+ max_tokens=1024,
65
+ messages=[{"role": "user", "content": user_query}],
66
+ )
42
67
 
43
- # Track events
44
- client.track({
45
- "name": "button_clicked",
46
- "user_id": "user-123",
47
- "properties": {
48
- "button_name": "checkout",
49
- "page": "product-detail"
50
- }
51
- })
68
+ observe(
69
+ prompt=user_query,
70
+ response=message.content[0].text,
71
+ provider_response=message, # auto-extracts model, tokens
72
+ )
73
+ ```
52
74
 
53
- # Clean up resources
54
- client.close()
75
+ ### RAG applications — grounding & hallucination scoring
76
+
77
+ ```python
78
+ observe(
79
+ prompt=user_query,
80
+ response=llm_answer,
81
+ provider_response=completion,
82
+ reference_materials=[
83
+ {"id": "chunk-1", "content": "Retrieved text...", "source": "docs.pdf"},
84
+ {"id": "chunk-2", "content": "Another chunk...", "source": "faq.md"},
85
+ ],
86
+ retrieval_query=user_query,
87
+ )
55
88
  ```
56
89
 
90
+ ### Multi-turn chat — coherence scoring
91
+
92
+ ```python
93
+ observe(
94
+ prompt=latest_user_message,
95
+ response=llm_answer,
96
+ provider_response=completion,
97
+ conversation_history=[
98
+ {"role": "user", "content": "What is diabetes?"},
99
+ {"role": "assistant", "content": "Diabetes is a chronic condition..."},
100
+ {"role": "user", "content": "What are the symptoms?"},
101
+ ],
102
+ session_id="conv-123",
103
+ )
104
+ ```
105
+
106
+ ### Full parameter reference
107
+
108
+ | Parameter | Type | Required | Description |
109
+ |-----------|------|----------|-------------|
110
+ | `prompt` | str | Yes | The user's input / question |
111
+ | `response` | str | Yes | The LLM's generated response |
112
+ | `provider_response` | object | No | Raw OpenAI/Anthropic/Google response — auto-extracts model, tokens |
113
+ | `model` | str | No | Model name (auto-extracted if provider_response given) |
114
+ | `provider` | str | No | "openai", "anthropic", etc. (auto-detected) |
115
+ | `latency_ms` | int | No | Response generation time in milliseconds |
116
+ | `prompt_tokens` | int | No | Input token count (auto-extracted if provider_response given) |
117
+ | `completion_tokens` | int | No | Output token count (auto-extracted) |
118
+ | `cost` | float | No | Cost in USD |
119
+ | `reference_materials` | list[dict] | No | RAG chunks: `[{"id", "content", "source"}]` — enables grounding scoring |
120
+ | `retrieval_query` | str | No | Query sent to retriever — enables retrieval quality scoring |
121
+ | `conversation_history` | list[dict] | No | Prior turns: `[{"role", "content"}]` — enables coherence scoring |
122
+ | `tags` | list[str] | No | Grouping labels, e.g. `["production", "rag"]` |
123
+ | `user_id` | str | No | Your user's ID |
124
+ | `session_id` | str | No | Conversation session ID (groups multi-turn) |
125
+ | `metadata` | dict | No | Any extra key-value data |
126
+
127
+ ---
128
+
57
129
  ## Prompt Experimentation
58
130
 
59
131
  Variably provides two modes for LLM prompt experimentation:
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "variably-sdk"
7
- version = "2.6.0"
7
+ version = "2.6.1"
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"
@@ -1,3 +1,3 @@
1
1
  """Version information for Variably SDK."""
2
2
 
3
- __version__ = "2.6.0"
3
+ __version__ = "2.6.1"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: variably-sdk
3
- Version: 2.6.0
3
+ Version: 2.6.1
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>
@@ -45,7 +45,7 @@ Dynamic: requires-python
45
45
 
46
46
  # Variably Python SDK
47
47
 
48
- Official Python SDK for Variably — feature flags, LLM experimentation, and prompt optimization.
48
+ Official Python SDK for Variably — LLM evaluation, experimentation, and prompt optimization.
49
49
 
50
50
  ## Installation
51
51
 
@@ -53,52 +53,124 @@ Official Python SDK for Variably — feature flags, LLM experimentation, and pro
53
53
  pip install variably-sdk
54
54
  ```
55
55
 
56
- ## Quick Start
56
+ ## Quick Start — Observe Mode
57
+
58
+ Add **one line** to your existing LLM app and get **multi-dimension evaluation** across 40+ metrics in 6 categories: Quality, Safety, Semantic, Grounding, Coherence, and Advanced.
59
+
60
+ No experiment setup. No prompt migration. Just log and see scores.
61
+
62
+ ### 1. Set your environment variables
63
+
64
+ ```bash
65
+ VARIABLY_API_KEY=vbl_your_key_here
66
+ VARIABLY_BASE_URL=https://api.variably.tech
67
+ ```
68
+
69
+ ### 2. Add one line after your LLM call
57
70
 
58
71
  ```python
59
- from variably import VariablyClient
72
+ from variably import observe
60
73
 
61
- # Initialize the client
62
- client = VariablyClient({
63
- "api_key": "your-api-key",
64
- "base_url": "https://api.variably.com", # optional, defaults to localhost:8080
65
- "environment": "production" # optional
66
- })
74
+ # Your existing code (unchanged)
75
+ response = your_llm_call(user_query)
67
76
 
68
- # Evaluate a boolean feature flag
69
- user_context = {
70
- "user_id": "user-123",
71
- "email": "user@example.com",
72
- "country": "US"
73
- }
77
+ # Add this line:
78
+ observe(prompt=user_query, response=response)
79
+ ```
74
80
 
75
- is_feature_enabled = client.evaluate_flag_bool(
76
- "new-checkout-flow",
77
- False, # default value
78
- user_context
81
+ ### Auto-extract tokens & model from provider response
82
+
83
+ ```python
84
+ # OpenAI
85
+ from openai import OpenAI
86
+ from variably import observe
87
+
88
+ client = OpenAI()
89
+ completion = client.chat.completions.create(
90
+ model="gpt-4o",
91
+ messages=[{"role": "user", "content": user_query}],
79
92
  )
80
93
 
81
- if is_feature_enabled:
82
- # Show new checkout flow
83
- pass
94
+ observe(
95
+ prompt=user_query,
96
+ response=completion.choices[0].message.content,
97
+ provider_response=completion, # auto-extracts model, tokens
98
+ )
99
+ ```
84
100
 
85
- # Evaluate a feature gate
86
- has_access = client.evaluate_gate("premium-features", user_context)
101
+ ```python
102
+ # Anthropic
103
+ import anthropic
104
+ from variably import observe
105
+
106
+ client = anthropic.Anthropic()
107
+ message = client.messages.create(
108
+ model="claude-sonnet-4-20250514",
109
+ max_tokens=1024,
110
+ messages=[{"role": "user", "content": user_query}],
111
+ )
87
112
 
88
- # Track events
89
- client.track({
90
- "name": "button_clicked",
91
- "user_id": "user-123",
92
- "properties": {
93
- "button_name": "checkout",
94
- "page": "product-detail"
95
- }
96
- })
113
+ observe(
114
+ prompt=user_query,
115
+ response=message.content[0].text,
116
+ provider_response=message, # auto-extracts model, tokens
117
+ )
118
+ ```
97
119
 
98
- # Clean up resources
99
- client.close()
120
+ ### RAG applications — grounding & hallucination scoring
121
+
122
+ ```python
123
+ observe(
124
+ prompt=user_query,
125
+ response=llm_answer,
126
+ provider_response=completion,
127
+ reference_materials=[
128
+ {"id": "chunk-1", "content": "Retrieved text...", "source": "docs.pdf"},
129
+ {"id": "chunk-2", "content": "Another chunk...", "source": "faq.md"},
130
+ ],
131
+ retrieval_query=user_query,
132
+ )
100
133
  ```
101
134
 
135
+ ### Multi-turn chat — coherence scoring
136
+
137
+ ```python
138
+ observe(
139
+ prompt=latest_user_message,
140
+ response=llm_answer,
141
+ provider_response=completion,
142
+ conversation_history=[
143
+ {"role": "user", "content": "What is diabetes?"},
144
+ {"role": "assistant", "content": "Diabetes is a chronic condition..."},
145
+ {"role": "user", "content": "What are the symptoms?"},
146
+ ],
147
+ session_id="conv-123",
148
+ )
149
+ ```
150
+
151
+ ### Full parameter reference
152
+
153
+ | Parameter | Type | Required | Description |
154
+ |-----------|------|----------|-------------|
155
+ | `prompt` | str | Yes | The user's input / question |
156
+ | `response` | str | Yes | The LLM's generated response |
157
+ | `provider_response` | object | No | Raw OpenAI/Anthropic/Google response — auto-extracts model, tokens |
158
+ | `model` | str | No | Model name (auto-extracted if provider_response given) |
159
+ | `provider` | str | No | "openai", "anthropic", etc. (auto-detected) |
160
+ | `latency_ms` | int | No | Response generation time in milliseconds |
161
+ | `prompt_tokens` | int | No | Input token count (auto-extracted if provider_response given) |
162
+ | `completion_tokens` | int | No | Output token count (auto-extracted) |
163
+ | `cost` | float | No | Cost in USD |
164
+ | `reference_materials` | list[dict] | No | RAG chunks: `[{"id", "content", "source"}]` — enables grounding scoring |
165
+ | `retrieval_query` | str | No | Query sent to retriever — enables retrieval quality scoring |
166
+ | `conversation_history` | list[dict] | No | Prior turns: `[{"role", "content"}]` — enables coherence scoring |
167
+ | `tags` | list[str] | No | Grouping labels, e.g. `["production", "rag"]` |
168
+ | `user_id` | str | No | Your user's ID |
169
+ | `session_id` | str | No | Conversation session ID (groups multi-turn) |
170
+ | `metadata` | dict | No | Any extra key-value data |
171
+
172
+ ---
173
+
102
174
  ## Prompt Experimentation
103
175
 
104
176
  Variably provides two modes for LLM prompt experimentation:
File without changes
File without changes