arize-phoenix 10.6.2__py3-none-any.whl → 10.7.1__py3-none-any.whl

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.

Potentially problematic release.


This version of arize-phoenix might be problematic. Click here for more details.

Files changed (26) hide show
  1. {arize_phoenix-10.6.2.dist-info → arize_phoenix-10.7.1.dist-info}/METADATA +2 -2
  2. {arize_phoenix-10.6.2.dist-info → arize_phoenix-10.7.1.dist-info}/RECORD +26 -25
  3. phoenix/db/types/model_provider.py +1 -0
  4. phoenix/experiments/functions.py +21 -9
  5. phoenix/experiments/tracing.py +1 -1
  6. phoenix/server/api/helpers/playground_clients.py +132 -21
  7. phoenix/server/api/helpers/playground_spans.py +6 -3
  8. phoenix/server/api/helpers/prompts/models.py +21 -0
  9. phoenix/server/api/input_types/ChatCompletionInput.py +3 -2
  10. phoenix/server/api/input_types/GenerativeCredentialInput.py +9 -0
  11. phoenix/server/api/mutations/chat_mutations.py +20 -3
  12. phoenix/server/api/routers/v1/datasets.py +5 -0
  13. phoenix/server/api/subscriptions.py +19 -2
  14. phoenix/server/api/types/GenerativeProvider.py +44 -12
  15. phoenix/server/main.py +1 -0
  16. phoenix/server/static/.vite/manifest.json +9 -9
  17. phoenix/server/static/assets/{components-J06J_j9O.js → components-CuV9v4w3.js} +243 -243
  18. phoenix/server/static/assets/{index-DfT39tc3.js → index-BeIqg4nl.js} +2 -2
  19. phoenix/server/static/assets/{pages-nxs-tDxQ.js → pages-DTLdnakm.js} +401 -398
  20. phoenix/server/telemetry.py +1 -1
  21. phoenix/trace/projects.py +1 -1
  22. phoenix/version.py +1 -1
  23. {arize_phoenix-10.6.2.dist-info → arize_phoenix-10.7.1.dist-info}/WHEEL +0 -0
  24. {arize_phoenix-10.6.2.dist-info → arize_phoenix-10.7.1.dist-info}/entry_points.txt +0 -0
  25. {arize_phoenix-10.6.2.dist-info → arize_phoenix-10.7.1.dist-info}/licenses/IP_NOTICE +0 -0
  26. {arize_phoenix-10.6.2.dist-info → arize_phoenix-10.7.1.dist-info}/licenses/LICENSE +0 -0
@@ -8,6 +8,7 @@ from strawberry.scalars import JSON
8
8
  from phoenix.server.api.helpers.prompts.models import (
9
9
  PromptTemplateFormat,
10
10
  )
11
+ from phoenix.server.api.input_types.GenerativeCredentialInput import GenerativeCredentialInput
11
12
  from phoenix.server.api.types.Identifier import Identifier
12
13
 
13
14
  from .ChatCompletionMessageInput import ChatCompletionMessageInput
@@ -22,7 +23,7 @@ class ChatCompletionInput:
22
23
  model: GenerativeModelInput
23
24
  invocation_parameters: list[InvocationParameterInput] = strawberry.field(default_factory=list)
24
25
  tools: Optional[list[JSON]] = UNSET
25
- api_key: Optional[str] = strawberry.field(default=None)
26
+ credentials: Optional[list[GenerativeCredentialInput]] = UNSET
26
27
  template: Optional[PromptTemplateOptions] = UNSET
27
28
  prompt_name: Optional[Identifier] = None
28
29
 
@@ -33,7 +34,7 @@ class ChatCompletionOverDatasetInput:
33
34
  model: GenerativeModelInput
34
35
  invocation_parameters: list[InvocationParameterInput] = strawberry.field(default_factory=list)
35
36
  tools: Optional[list[JSON]] = UNSET
36
- api_key: Optional[str] = strawberry.field(default=None)
37
+ credentials: Optional[list[GenerativeCredentialInput]] = UNSET
37
38
  template_format: PromptTemplateFormat = PromptTemplateFormat.MUSTACHE
38
39
  dataset_id: GlobalID
39
40
  dataset_version_id: Optional[GlobalID] = None
@@ -0,0 +1,9 @@
1
+ import strawberry
2
+
3
+
4
+ @strawberry.input
5
+ class GenerativeCredentialInput:
6
+ env_var_name: str
7
+ """The name of the environment variable to set."""
8
+ value: str
9
+ """The value of the environment variable to set."""
@@ -30,6 +30,7 @@ from phoenix.server.api.context import Context
30
30
  from phoenix.server.api.exceptions import BadRequest, CustomGraphQLError, NotFound
31
31
  from phoenix.server.api.helpers.dataset_helpers import get_dataset_example_output
32
32
  from phoenix.server.api.helpers.playground_clients import (
33
+ PlaygroundClientCredential,
33
34
  PlaygroundStreamingClient,
34
35
  initialize_playground_clients,
35
36
  )
@@ -132,9 +133,17 @@ class ChatCompletionMutationMixin:
132
133
  if llm_client_class is None:
133
134
  raise BadRequest(f"Unknown LLM provider: '{provider_key.value}'")
134
135
  try:
136
+ # Convert GraphQL credentials to PlaygroundCredential objects
137
+ credentials = None
138
+ if input.credentials:
139
+ credentials = [
140
+ PlaygroundClientCredential(env_var_name=cred.env_var_name, value=cred.value)
141
+ for cred in input.credentials
142
+ ]
143
+
135
144
  llm_client = llm_client_class(
136
145
  model=input.model,
137
- api_key=input.api_key,
146
+ credentials=credentials,
138
147
  )
139
148
  except CustomGraphQLError:
140
149
  raise
@@ -200,7 +209,7 @@ class ChatCompletionMutationMixin:
200
209
  llm_client,
201
210
  ChatCompletionInput(
202
211
  model=input.model,
203
- api_key=input.api_key,
212
+ credentials=input.credentials,
204
213
  messages=input.messages,
205
214
  tools=input.tools,
206
215
  invocation_parameters=input.invocation_parameters,
@@ -281,9 +290,17 @@ class ChatCompletionMutationMixin:
281
290
  if llm_client_class is None:
282
291
  raise BadRequest(f"Unknown LLM provider: '{provider_key.value}'")
283
292
  try:
293
+ # Convert GraphQL credentials to PlaygroundCredential objects
294
+ credentials = None
295
+ if input.credentials:
296
+ credentials = [
297
+ PlaygroundClientCredential(env_var_name=cred.env_var_name, value=cred.value)
298
+ for cred in input.credentials
299
+ ]
300
+
284
301
  llm_client = llm_client_class(
285
302
  model=input.model,
286
- api_key=input.api_key,
303
+ credentials=credentials,
287
304
  )
288
305
  except CustomGraphQLError:
289
306
  raise
@@ -57,6 +57,11 @@ from .utils import (
57
57
  add_text_csv_content_to_responses,
58
58
  )
59
59
 
60
+ csv.field_size_limit(
61
+ 1_000_000_000 # allows large field sizes for CSV upload (1GB)
62
+ )
63
+
64
+
60
65
  logger = logging.getLogger(__name__)
61
66
 
62
67
  DATASET_NODE_NAME = DatasetNodeType.__name__
@@ -30,6 +30,7 @@ from phoenix.server.api.auth import IsLocked, IsNotReadOnly
30
30
  from phoenix.server.api.context import Context
31
31
  from phoenix.server.api.exceptions import BadRequest, CustomGraphQLError, NotFound
32
32
  from phoenix.server.api.helpers.playground_clients import (
33
+ PlaygroundClientCredential,
33
34
  PlaygroundStreamingClient,
34
35
  initialize_playground_clients,
35
36
  )
@@ -98,9 +99,17 @@ class Subscription:
98
99
  if llm_client_class is None:
99
100
  raise BadRequest(f"Unknown LLM provider: '{provider_key.value}'")
100
101
  try:
102
+ # Convert GraphQL credentials to PlaygroundCredential objects
103
+ playground_credentials = None
104
+ if input.credentials:
105
+ playground_credentials = [
106
+ PlaygroundClientCredential(env_var_name=cred.env_var_name, value=cred.value)
107
+ for cred in input.credentials
108
+ ]
109
+
101
110
  llm_client = llm_client_class(
102
111
  model=input.model,
103
- api_key=input.api_key,
112
+ credentials=playground_credentials,
104
113
  )
105
114
  except CustomGraphQLError:
106
115
  raise
@@ -176,9 +185,17 @@ class Subscription:
176
185
  if llm_client_class is None:
177
186
  raise BadRequest(f"Unknown LLM provider: '{provider_key.value}'")
178
187
  try:
188
+ # Convert GraphQL credentials to PlaygroundCredential objects
189
+ playground_credentials = None
190
+ if input.credentials:
191
+ playground_credentials = [
192
+ PlaygroundClientCredential(env_var_name=cred.env_var_name, value=cred.value)
193
+ for cred in input.credentials
194
+ ]
195
+
179
196
  llm_client = llm_client_class(
180
197
  model=input.model,
181
- api_key=input.api_key,
198
+ credentials=playground_credentials,
182
199
  )
183
200
  except CustomGraphQLError:
184
201
  raise
@@ -16,6 +16,13 @@ class GenerativeProviderKey(Enum):
16
16
  GOOGLE = "Google AI Studio"
17
17
  DEEPSEEK = "DeepSeek"
18
18
  XAI = "xAI"
19
+ OLLAMA = "Ollama"
20
+
21
+
22
+ @strawberry.type
23
+ class GenerativeProviderCredentialConfig:
24
+ env_var_name: str
25
+ is_required: bool
19
26
 
20
27
 
21
28
  @strawberry.type
@@ -30,6 +37,7 @@ class GenerativeProvider:
30
37
  GenerativeProviderKey.GOOGLE: ["gemini"],
31
38
  GenerativeProviderKey.DEEPSEEK: ["deepseek"],
32
39
  GenerativeProviderKey.XAI: ["grok"],
40
+ GenerativeProviderKey.OLLAMA: ["llama", "mistral", "codellama", "phi", "qwen", "gemma"],
33
41
  }
34
42
 
35
43
  attribute_provider_to_generative_provider_map: ClassVar[dict[str, GenerativeProviderKey]] = {
@@ -41,15 +49,35 @@ class GenerativeProvider:
41
49
  # The provider will be determined through model name prefix matching instead
42
50
  # Note: xAI uses OpenAI compatibility but we can't duplicate the key in the dict
43
51
  # The provider will be determined through model name prefix matching instead
52
+ # Note: Ollama uses OpenAI compatibility but we can't duplicate the key in the dict
53
+ # The provider will be determined through model name prefix matching instead
44
54
  }
45
55
 
46
- model_provider_to_api_key_env_var_map: ClassVar[dict[GenerativeProviderKey, str]] = {
47
- GenerativeProviderKey.AZURE_OPENAI: "AZURE_OPENAI_API_KEY",
48
- GenerativeProviderKey.ANTHROPIC: "ANTHROPIC_API_KEY",
49
- GenerativeProviderKey.OPENAI: "OPENAI_API_KEY",
50
- GenerativeProviderKey.GOOGLE: "GEMINI_API_KEY",
51
- GenerativeProviderKey.DEEPSEEK: "DEEPSEEK_API_KEY",
52
- GenerativeProviderKey.XAI: "XAI_API_KEY",
56
+ """
57
+ A map of model provider keys to their credential requirements.
58
+ E.x. OpenAI requires a single API key
59
+ """
60
+ model_provider_to_credential_requirements_map: ClassVar[
61
+ dict[GenerativeProviderKey, GenerativeProviderCredentialConfig]
62
+ ] = {
63
+ GenerativeProviderKey.AZURE_OPENAI: GenerativeProviderCredentialConfig(
64
+ env_var_name="AZURE_OPENAI_API_KEY", is_required=True
65
+ ),
66
+ GenerativeProviderKey.ANTHROPIC: GenerativeProviderCredentialConfig(
67
+ env_var_name="ANTHROPIC_API_KEY", is_required=True
68
+ ),
69
+ GenerativeProviderKey.OPENAI: GenerativeProviderCredentialConfig(
70
+ env_var_name="OPENAI_API_KEY", is_required=True
71
+ ),
72
+ GenerativeProviderKey.GOOGLE: GenerativeProviderCredentialConfig(
73
+ env_var_name="GEMINI_API_KEY", is_required=True
74
+ ),
75
+ GenerativeProviderKey.DEEPSEEK: GenerativeProviderCredentialConfig(
76
+ env_var_name="DEEPSEEK_API_KEY", is_required=True
77
+ ),
78
+ GenerativeProviderKey.XAI: GenerativeProviderCredentialConfig(
79
+ env_var_name="XAI_API_KEY", is_required=True
80
+ ),
53
81
  }
54
82
 
55
83
  @strawberry.field
@@ -76,13 +104,17 @@ class GenerativeProvider:
76
104
  return default_client.dependencies_are_installed()
77
105
  return False
78
106
 
79
- @strawberry.field(description="The API key for the provider") # type: ignore
80
- async def api_key_env_var(self) -> str:
81
- return self.model_provider_to_api_key_env_var_map[self.key]
107
+ @strawberry.field(description="The credential requirements for the provider") # type: ignore
108
+ async def credential_requirements(self) -> list[GenerativeProviderCredentialConfig]:
109
+ return [self.model_provider_to_credential_requirements_map[self.key]]
82
110
 
83
111
  @strawberry.field(description="Whether the credentials are set on the server for the provider") # type: ignore
84
- async def api_key_set(self) -> bool:
85
- return getenv(self.model_provider_to_api_key_env_var_map[self.key]) is not None
112
+ async def credentials_set(self) -> bool:
113
+ # Check if every required credential is set
114
+ return all(
115
+ getenv(credential_config.env_var_name) is not None or not credential_config.is_required
116
+ for credential_config in await self.credential_requirements()
117
+ )
86
118
 
87
119
  @classmethod
88
120
  def _infer_model_provider_from_model_name(
phoenix/server/main.py CHANGED
@@ -459,6 +459,7 @@ def main() -> None:
459
459
  host=host, # type: ignore[arg-type]
460
460
  port=port,
461
461
  root_path=host_root_path,
462
+ log_level=Settings.logging_level,
462
463
  )
463
464
 
464
465
  if tls_enabled_for_http:
@@ -1,22 +1,22 @@
1
1
  {
2
- "_components-J06J_j9O.js": {
3
- "file": "assets/components-J06J_j9O.js",
2
+ "_components-CuV9v4w3.js": {
3
+ "file": "assets/components-CuV9v4w3.js",
4
4
  "name": "components",
5
5
  "imports": [
6
6
  "_vendor-B52WHALA.js",
7
- "_pages-nxs-tDxQ.js",
7
+ "_pages-DTLdnakm.js",
8
8
  "_vendor-arizeai-DGHetzZW.js",
9
9
  "_vendor-codemirror-QIdVJrP_.js",
10
10
  "_vendor-three-C5WAXd5r.js"
11
11
  ]
12
12
  },
13
- "_pages-nxs-tDxQ.js": {
14
- "file": "assets/pages-nxs-tDxQ.js",
13
+ "_pages-DTLdnakm.js": {
14
+ "file": "assets/pages-DTLdnakm.js",
15
15
  "name": "pages",
16
16
  "imports": [
17
17
  "_vendor-B52WHALA.js",
18
18
  "_vendor-arizeai-DGHetzZW.js",
19
- "_components-J06J_j9O.js",
19
+ "_components-CuV9v4w3.js",
20
20
  "_vendor-codemirror-QIdVJrP_.js",
21
21
  "_vendor-recharts-GmWamXB4.js"
22
22
  ]
@@ -69,15 +69,15 @@
69
69
  "name": "vendor-three"
70
70
  },
71
71
  "index.tsx": {
72
- "file": "assets/index-DfT39tc3.js",
72
+ "file": "assets/index-BeIqg4nl.js",
73
73
  "name": "index",
74
74
  "src": "index.tsx",
75
75
  "isEntry": true,
76
76
  "imports": [
77
77
  "_vendor-B52WHALA.js",
78
78
  "_vendor-arizeai-DGHetzZW.js",
79
- "_pages-nxs-tDxQ.js",
80
- "_components-J06J_j9O.js",
79
+ "_pages-DTLdnakm.js",
80
+ "_components-CuV9v4w3.js",
81
81
  "_vendor-three-C5WAXd5r.js",
82
82
  "_vendor-codemirror-QIdVJrP_.js",
83
83
  "_vendor-shiki-C8cTrXI5.js",