arize-phoenix 7.12.3__py3-none-any.whl → 8.0.0__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 (80) hide show
  1. {arize_phoenix-7.12.3.dist-info → arize_phoenix-8.0.0.dist-info}/METADATA +31 -28
  2. {arize_phoenix-7.12.3.dist-info → arize_phoenix-8.0.0.dist-info}/RECORD +70 -47
  3. phoenix/db/migrations/versions/bc8fea3c2bc8_add_prompt_tables.py +197 -0
  4. phoenix/db/models.py +307 -0
  5. phoenix/db/types/__init__.py +0 -0
  6. phoenix/db/types/identifier.py +7 -0
  7. phoenix/db/types/model_provider.py +8 -0
  8. phoenix/server/api/context.py +2 -0
  9. phoenix/server/api/dataloaders/__init__.py +2 -0
  10. phoenix/server/api/dataloaders/prompt_version_sequence_number.py +35 -0
  11. phoenix/server/api/helpers/jsonschema.py +135 -0
  12. phoenix/server/api/helpers/playground_clients.py +15 -15
  13. phoenix/server/api/helpers/playground_spans.py +9 -0
  14. phoenix/server/api/helpers/prompts/__init__.py +0 -0
  15. phoenix/server/api/helpers/prompts/conversions/__init__.py +0 -0
  16. phoenix/server/api/helpers/prompts/conversions/anthropic.py +87 -0
  17. phoenix/server/api/helpers/prompts/conversions/openai.py +78 -0
  18. phoenix/server/api/helpers/prompts/models.py +575 -0
  19. phoenix/server/api/input_types/ChatCompletionInput.py +9 -4
  20. phoenix/server/api/input_types/PromptTemplateOptions.py +10 -0
  21. phoenix/server/api/input_types/PromptVersionInput.py +133 -0
  22. phoenix/server/api/mutations/__init__.py +6 -0
  23. phoenix/server/api/mutations/chat_mutations.py +18 -16
  24. phoenix/server/api/mutations/prompt_label_mutations.py +191 -0
  25. phoenix/server/api/mutations/prompt_mutations.py +312 -0
  26. phoenix/server/api/mutations/prompt_version_tag_mutations.py +148 -0
  27. phoenix/server/api/mutations/user_mutations.py +7 -6
  28. phoenix/server/api/openapi/schema.py +1 -0
  29. phoenix/server/api/queries.py +84 -31
  30. phoenix/server/api/routers/oauth2.py +3 -2
  31. phoenix/server/api/routers/v1/__init__.py +2 -0
  32. phoenix/server/api/routers/v1/datasets.py +1 -1
  33. phoenix/server/api/routers/v1/experiment_evaluations.py +1 -1
  34. phoenix/server/api/routers/v1/experiment_runs.py +1 -1
  35. phoenix/server/api/routers/v1/experiments.py +1 -1
  36. phoenix/server/api/routers/v1/models.py +45 -0
  37. phoenix/server/api/routers/v1/prompts.py +412 -0
  38. phoenix/server/api/routers/v1/spans.py +1 -1
  39. phoenix/server/api/routers/v1/traces.py +1 -1
  40. phoenix/server/api/routers/v1/utils.py +1 -1
  41. phoenix/server/api/subscriptions.py +21 -24
  42. phoenix/server/api/types/GenerativeProvider.py +4 -4
  43. phoenix/server/api/types/Identifier.py +15 -0
  44. phoenix/server/api/types/Project.py +5 -7
  45. phoenix/server/api/types/Prompt.py +134 -0
  46. phoenix/server/api/types/PromptLabel.py +41 -0
  47. phoenix/server/api/types/PromptVersion.py +148 -0
  48. phoenix/server/api/types/PromptVersionTag.py +27 -0
  49. phoenix/server/api/types/PromptVersionTemplate.py +148 -0
  50. phoenix/server/api/types/ResponseFormat.py +9 -0
  51. phoenix/server/api/types/ToolDefinition.py +9 -0
  52. phoenix/server/app.py +3 -0
  53. phoenix/server/static/.vite/manifest.json +45 -45
  54. phoenix/server/static/assets/components-B-qgPyHv.js +2699 -0
  55. phoenix/server/static/assets/index-D4KO1IcF.js +1125 -0
  56. phoenix/server/static/assets/pages-DdcuL3Rh.js +5634 -0
  57. phoenix/server/static/assets/vendor-DQp7CrDA.js +894 -0
  58. phoenix/server/static/assets/vendor-arizeai-C1nEIEQq.js +657 -0
  59. phoenix/server/static/assets/vendor-codemirror-BZXYUIkP.js +24 -0
  60. phoenix/server/static/assets/vendor-recharts-BUFpwCVD.js +59 -0
  61. phoenix/server/static/assets/{vendor-shiki-Cl9QBraO.js → vendor-shiki-C8L-c9jT.js} +2 -2
  62. phoenix/server/static/assets/{vendor-three-DwGkEfCM.js → vendor-three-C-AGeJYv.js} +1 -1
  63. phoenix/session/client.py +25 -21
  64. phoenix/utilities/client.py +6 -0
  65. phoenix/version.py +1 -1
  66. phoenix/server/api/input_types/TemplateOptions.py +0 -10
  67. phoenix/server/api/routers/v1/pydantic_compat.py +0 -78
  68. phoenix/server/api/types/TemplateLanguage.py +0 -10
  69. phoenix/server/static/assets/components-DckIzNmE.js +0 -2125
  70. phoenix/server/static/assets/index-Bf25Ogon.js +0 -113
  71. phoenix/server/static/assets/pages-DL7J9q9w.js +0 -4463
  72. phoenix/server/static/assets/vendor-DvC8cT4X.js +0 -894
  73. phoenix/server/static/assets/vendor-arizeai-Do1793cv.js +0 -662
  74. phoenix/server/static/assets/vendor-codemirror-BzwZPyJM.js +0 -24
  75. phoenix/server/static/assets/vendor-recharts-_Jb7JjhG.js +0 -59
  76. {arize_phoenix-7.12.3.dist-info → arize_phoenix-8.0.0.dist-info}/WHEEL +0 -0
  77. {arize_phoenix-7.12.3.dist-info → arize_phoenix-8.0.0.dist-info}/entry_points.txt +0 -0
  78. {arize_phoenix-7.12.3.dist-info → arize_phoenix-8.0.0.dist-info}/licenses/IP_NOTICE +0 -0
  79. {arize_phoenix-7.12.3.dist-info → arize_phoenix-8.0.0.dist-info}/licenses/LICENSE +0 -0
  80. /phoenix/server/static/assets/{vendor-DxkFTwjz.css → vendor-Cg6lcjUC.css} +0 -0
phoenix/session/client.py CHANGED
@@ -2,7 +2,6 @@ import csv
2
2
  import gzip
3
3
  import logging
4
4
  import re
5
- import weakref
6
5
  from collections import Counter
7
6
  from collections.abc import Iterable, Mapping, Sequence
8
7
  from datetime import datetime
@@ -84,11 +83,16 @@ class Client(TraceDataExtractor):
84
83
  if host == "0.0.0.0":
85
84
  host = "127.0.0.1"
86
85
  base_url = endpoint or get_env_collector_endpoint() or f"http://{host}:{get_env_port()}"
87
- self._base_url = base_url if base_url.endswith("/") else base_url + "/"
88
- self._client = VersionedClient(headers=headers)
89
- weakref.finalize(self, self._client.close)
86
+ self._client = VersionedClient(headers=headers, base_url=httpx.URL(base_url))
90
87
  if warn_if_server_not_running:
91
88
  self._warn_if_phoenix_is_not_running()
89
+ try:
90
+ # place import here temporarily before phoenix-client is fully published on pypi
91
+ from phoenix.client.resources.prompts import Prompts
92
+
93
+ self.prompts = Prompts(self._client)
94
+ except ImportError:
95
+ pass
92
96
 
93
97
  @property
94
98
  def web_url(self) -> str:
@@ -105,7 +109,7 @@ class Client(TraceDataExtractor):
105
109
 
106
110
  if session := active_session():
107
111
  return session.url
108
- return self._base_url
112
+ return str(self._client.base_url)
109
113
 
110
114
  def query_spans(
111
115
  self,
@@ -148,7 +152,7 @@ class Client(TraceDataExtractor):
148
152
  try:
149
153
  response = self._client.post(
150
154
  headers={"accept": "application/json"},
151
- url=urljoin(self._base_url, "v1/spans"),
155
+ url="v1/spans",
152
156
  params={
153
157
  "project_name": project_name,
154
158
  "project-name": project_name, # for backward-compatibility
@@ -236,7 +240,7 @@ class Client(TraceDataExtractor):
236
240
  """
237
241
  project_name = project_name or get_env_project_name()
238
242
  response = self._client.get(
239
- url=urljoin(self._base_url, "v1/evaluations"),
243
+ url="v1/evaluations",
240
244
  params={
241
245
  "project_name": project_name,
242
246
  "project-name": project_name, # for backward-compatibility
@@ -261,10 +265,10 @@ class Client(TraceDataExtractor):
261
265
 
262
266
  def _warn_if_phoenix_is_not_running(self) -> None:
263
267
  try:
264
- self._client.get(urljoin(self._base_url, "arize_phoenix_version")).raise_for_status()
268
+ self._client.get("arize_phoenix_version").raise_for_status()
265
269
  except Exception:
266
270
  logger.warning(
267
- f"Arize Phoenix is not running on {self._base_url}. Launch Phoenix "
271
+ f"Arize Phoenix is not running on {self.web_url}. Launch Phoenix "
268
272
  f"with `import phoenix as px; px.launch_app()`"
269
273
  )
270
274
 
@@ -295,7 +299,7 @@ class Client(TraceDataExtractor):
295
299
  with pa.ipc.new_stream(sink, table.schema) as writer:
296
300
  writer.write_table(table)
297
301
  self._client.post(
298
- url=urljoin(self._base_url, "v1/evaluations"),
302
+ url="v1/evaluations",
299
303
  content=cast(bytes, sink.getvalue().to_pybytes()),
300
304
  headers=headers,
301
305
  timeout=timeout,
@@ -339,7 +343,7 @@ class Client(TraceDataExtractor):
339
343
  serialized = otlp_span.SerializeToString()
340
344
  content = gzip.compress(serialized)
341
345
  response = self._client.post(
342
- url=urljoin(self._base_url, "v1/traces"),
346
+ url="v1/traces",
343
347
  content=content,
344
348
  headers={
345
349
  "content-type": "application/x-protobuf",
@@ -360,7 +364,7 @@ class Client(TraceDataExtractor):
360
364
  Dataset: The dataset object.
361
365
  """
362
366
  response = self._client.get(
363
- urljoin(self._base_url, "v1/datasets"),
367
+ "v1/datasets",
364
368
  params={"name": name},
365
369
  )
366
370
  response.raise_for_status()
@@ -402,7 +406,7 @@ class Client(TraceDataExtractor):
402
406
  raise ValueError("Dataset id or name must be provided.")
403
407
 
404
408
  response = self._client.get(
405
- urljoin(self._base_url, f"v1/datasets/{quote(id)}/examples"),
409
+ f"v1/datasets/{quote(id)}/examples",
406
410
  params={"version_id": version_id} if version_id else None,
407
411
  )
408
412
  response.raise_for_status()
@@ -442,7 +446,7 @@ class Client(TraceDataExtractor):
442
446
  Returns:
443
447
  pandas DataFrame
444
448
  """
445
- url = urljoin(self._base_url, f"v1/datasets/{dataset_id}/versions")
449
+ url = f"v1/datasets/{dataset_id}/versions"
446
450
  response = self._client.get(url=url, params={"limit": limit})
447
451
  response.raise_for_status()
448
452
  if not (records := response.json()["data"]):
@@ -612,7 +616,7 @@ class Client(TraceDataExtractor):
612
616
  experiment_id (str): ID of the experiment. This can be found in the UI.
613
617
  """
614
618
  response = self._client.get(
615
- url=urljoin(self._base_url, f"v1/experiments/{experiment_id}"),
619
+ url=f"v1/experiments/{experiment_id}",
616
620
  )
617
621
  experiment = response.json()["data"]
618
622
  return Experiment.from_dict(experiment)
@@ -676,7 +680,7 @@ class Client(TraceDataExtractor):
676
680
  assert_never(table)
677
681
  print("📤 Uploading dataset...")
678
682
  response = self._client.post(
679
- url=urljoin(self._base_url, "v1/datasets/upload"),
683
+ url="v1/datasets/upload",
680
684
  files={"file": file},
681
685
  data={
682
686
  "action": action,
@@ -733,7 +737,7 @@ class Client(TraceDataExtractor):
733
737
  )
734
738
  print("📤 Uploading dataset...")
735
739
  response = self._client.post(
736
- url=urljoin(self._base_url, "v1/datasets/upload"),
740
+ url="v1/datasets/upload",
737
741
  headers={"Content-Encoding": "gzip"},
738
742
  json={
739
743
  "action": action,
@@ -756,14 +760,14 @@ class Client(TraceDataExtractor):
756
760
  raise
757
761
  data = response.json()["data"]
758
762
  dataset_id = data["dataset_id"]
759
- response = self._client.get(
760
- url=urljoin(self._base_url, f"v1/datasets/{dataset_id}/examples")
761
- )
763
+ path = f"v1/datasets/{dataset_id}/examples"
764
+ response = self._client.get(path)
762
765
  response.raise_for_status()
763
766
  data = response.json()["data"]
764
767
  version_id = data["version_id"]
765
768
  examples = data["examples"]
766
- print(f"💾 Examples uploaded: {self.web_url}datasets/{dataset_id}/examples")
769
+ examples_url = urljoin(self.web_url, f"datasets/{dataset_id}/examples")
770
+ print(f"💾 Examples uploaded: {examples_url}")
767
771
  print(f"🗄️ Dataset version ID: {version_id}")
768
772
 
769
773
  return Dataset(
@@ -27,6 +27,12 @@ class VersionedClient(httpx.Client):
27
27
  self._client_phoenix_version = phoenix_version
28
28
  self._warned_on_minor_version_mismatch = False
29
29
 
30
+ def __del__(self) -> None:
31
+ try:
32
+ self.close()
33
+ except BaseException:
34
+ pass
35
+
30
36
  def _check_version(self, response: httpx.Response) -> None:
31
37
  server_version = response.headers.get(PHOENIX_SERVER_VERSION_HEADER)
32
38
 
phoenix/version.py CHANGED
@@ -1 +1 @@
1
- __version__ = "7.12.3"
1
+ __version__ = "8.0.0"
@@ -1,10 +0,0 @@
1
- import strawberry
2
- from strawberry.scalars import JSON
3
-
4
- from phoenix.server.api.types.TemplateLanguage import TemplateLanguage
5
-
6
-
7
- @strawberry.input
8
- class TemplateOptions:
9
- variables: JSON
10
- language: TemplateLanguage
@@ -1,78 +0,0 @@
1
- from datetime import datetime
2
- from enum import Enum
3
- from importlib.metadata import PackageNotFoundError, version
4
-
5
- from pydantic import BaseModel
6
- from typing_extensions import assert_never
7
-
8
-
9
- def datetime_encoder(dt: datetime) -> str:
10
- """
11
- Encodes a `datetime` object to an ISO-formatted timestamp string.
12
-
13
- By default, Pydantic v2 serializes `datetime` objects in a format that
14
- cannot be parsed by `datetime.fromisoformat`. Adding this encoder to the
15
- `json_encoders` config for a Pydantic model ensures that the serialized
16
- `datetime` objects are parseable.
17
- """
18
- return dt.isoformat()
19
-
20
-
21
- class PydanticMajorVersion(Enum):
22
- """
23
- The major version of `pydantic`.
24
- """
25
-
26
- V1 = "v1"
27
- V2 = "v2"
28
-
29
-
30
- def get_pydantic_major_version() -> PydanticMajorVersion:
31
- """
32
- Returns the major version of `pydantic` or raises an error if `pydantic` is
33
- not installed.
34
- """
35
- try:
36
- pydantic_version = version("pydantic")
37
- except PackageNotFoundError:
38
- raise RuntimeError("Please install pydantic with `pip install pydantic`.")
39
- if pydantic_version.startswith("1"):
40
- return PydanticMajorVersion.V1
41
- elif pydantic_version.startswith("2"):
42
- return PydanticMajorVersion.V2
43
- raise ValueError(f"Unsupported Pydantic version: {pydantic_version}")
44
-
45
-
46
- if (pydantic_major_version := get_pydantic_major_version()) is PydanticMajorVersion.V1:
47
-
48
- class V1RoutesBaseModel(BaseModel):
49
- class Config:
50
- json_encoders = {datetime: datetime_encoder}
51
-
52
- elif pydantic_major_version is PydanticMajorVersion.V2:
53
- from pydantic import ConfigDict
54
-
55
- # `json_encoders` is a configuration setting from Pydantic v1 that was
56
- # removed in Pydantic v2.0.* but restored in Pydantic v2.1.0 with a
57
- # deprecation warning. At this time, it remains the simplest way to
58
- # configure custom JSON serialization for specific data types in a manner
59
- # that is consistent between Pydantic v1 and v2.
60
- #
61
- # For details, see:
62
- # - https://github.com/pydantic/pydantic/pull/6811
63
- # - https://github.com/pydantic/pydantic/releases/tag/v2.1.0
64
- #
65
- # The assertion below is added in case a future release of Pydantic v2 fully
66
- # removes the `json_encoders` parameter.
67
- assert "json_encoders" in ConfigDict.__annotations__, (
68
- "If you encounter this error with `pydantic==2.0.*`, "
69
- "please upgrade `pydantic` with `pip install -U pydantic>=2.1.0`. "
70
- "If you encounter this error with `pydantic>=2.1.0`, "
71
- "please upgrade `arize-phoenix` with `pip install -U arize-phoenix`, "
72
- "or downgrade `pydantic` to a version that supports the `json_encoders` config setting."
73
- )
74
-
75
- class V1RoutesBaseModel(BaseModel): # type: ignore[no-redef]
76
- model_config = ConfigDict({"json_encoders": {datetime: datetime_encoder}})
77
- else:
78
- assert_never(pydantic_major_version)
@@ -1,10 +0,0 @@
1
- from enum import Enum
2
-
3
- import strawberry
4
-
5
-
6
- @strawberry.enum
7
- class TemplateLanguage(Enum):
8
- NONE = "NONE"
9
- MUSTACHE = "MUSTACHE"
10
- F_STRING = "F_STRING"