arize-phoenix 8.7.0__py3-none-any.whl → 8.9.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 (25) hide show
  1. {arize_phoenix-8.7.0.dist-info → arize_phoenix-8.9.0.dist-info}/METADATA +2 -2
  2. {arize_phoenix-8.7.0.dist-info → arize_phoenix-8.9.0.dist-info}/RECORD +25 -25
  3. phoenix/config.py +11 -0
  4. phoenix/server/api/helpers/playground_clients.py +21 -0
  5. phoenix/server/api/helpers/prompts/models.py +23 -2
  6. phoenix/server/api/input_types/InvocationParameters.py +1 -0
  7. phoenix/server/api/mutations/prompt_label_mutations.py +6 -5
  8. phoenix/server/api/mutations/prompt_mutations.py +6 -5
  9. phoenix/server/api/mutations/prompt_version_tag_mutations.py +3 -2
  10. phoenix/server/api/queries.py +14 -1
  11. phoenix/server/api/routers/v1/experiments.py +103 -2
  12. phoenix/server/static/.vite/manifest.json +44 -44
  13. phoenix/server/static/assets/{components-Bj66FcRz.js → components-C4AzQH6p.js} +245 -238
  14. phoenix/server/static/assets/{index-Dwk10lgb.js → index-DYSOLesW.js} +1 -1
  15. phoenix/server/static/assets/{pages-BNZVqOUi.js → pages-DEHszGOs.js} +385 -341
  16. phoenix/server/static/assets/{vendor-yn6w6Ozi.js → vendor-VJCVsFqd.js} +161 -161
  17. phoenix/server/static/assets/{vendor-arizeai-DoGO67dU.js → vendor-arizeai-CLxvyk4B.js} +1 -1
  18. phoenix/server/static/assets/{vendor-codemirror-BLdSYxpm.js → vendor-codemirror-0mUqu36F.js} +11 -11
  19. phoenix/server/static/assets/{vendor-recharts-CjOpOw1c.js → vendor-recharts-CfKQSOmq.js} +1 -1
  20. phoenix/server/static/assets/{vendor-shiki-BwTCxCQY.js → vendor-shiki-BsgMOuir.js} +1 -1
  21. phoenix/version.py +1 -1
  22. {arize_phoenix-8.7.0.dist-info → arize_phoenix-8.9.0.dist-info}/WHEEL +0 -0
  23. {arize_phoenix-8.7.0.dist-info → arize_phoenix-8.9.0.dist-info}/entry_points.txt +0 -0
  24. {arize_phoenix-8.7.0.dist-info → arize_phoenix-8.9.0.dist-info}/licenses/IP_NOTICE +0 -0
  25. {arize_phoenix-8.7.0.dist-info → arize_phoenix-8.9.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: arize-phoenix
3
- Version: 8.7.0
3
+ Version: 8.9.0
4
4
  Summary: AI Observability and Evaluation
5
5
  Project-URL: Documentation, https://docs.arize.com/phoenix/
6
6
  Project-URL: Issues, https://github.com/Arize-ai/phoenix/issues
@@ -164,7 +164,7 @@ Phoenix is an open-source AI observability platform designed for experimentation
164
164
  - [**_Playground_**](https://docs.arize.com/phoenix/prompt-engineering/overview-prompts)- Optimize prompts, compare models, adjust parameters, and replay traced LLM calls.
165
165
  - [**_Prompt Mangement_**](https://docs.arize.com/phoenix/prompt-engineering/overview-prompts/prompt-management)- Manage and test prompt changes systematically using version control, tagging, and experimentation.
166
166
 
167
- Phoenix is vendor and language agnostic with out-of-the-box support for popular frameworks (🦙[LlamaIndex](https://docs.arize.com/phoenix/tracing/integrations-tracing/llamaindex), 🦜⛓[LangChain](https://docs.arize.com/phoenix/tracing/integrations-tracing/langchain), [Haystack](https://docs.arize.com/phoenix/tracing/integrations-tracing/haystack), 🧩[DSPy](https://docs.arize.com/phoenix/tracing/integrations-tracing/dspy)) and LLM providers ([OpenAI](https://docs.arize.com/phoenix/tracing/integrations-tracing/openai), [Bedrock](https://docs.arize.com/phoenix/tracing/integrations-tracing/bedrock), [MistralAI](https://docs.arize.com/phoenix/tracing/integrations-tracing/mistralai), [VertexAI](https://docs.arize.com/phoenix/tracing/integrations-tracing/vertexai), [LiteLLM](https://docs.arize.com/phoenix/tracing/integrations-tracing/litellm), and more). For details on auto-instrumentation, check out the [OpenInference](https://github.com/Arize-ai/openinference) project.
167
+ Phoenix is vendor and language agnostic with out-of-the-box support for popular frameworks (🦙[LlamaIndex](https://docs.arize.com/phoenix/tracing/integrations-tracing/llamaindex), 🦜⛓[LangChain](https://docs.arize.com/phoenix/tracing/integrations-tracing/langchain), [Haystack](https://docs.arize.com/phoenix/tracing/integrations-tracing/haystack), 🧩[DSPy](https://docs.arize.com/phoenix/tracing/integrations-tracing/dspy), 🤗[smolagents](https://docs.arize.com/phoenix/tracing/integrations-tracing/hfsmolagents)) and LLM providers ([OpenAI](https://docs.arize.com/phoenix/tracing/integrations-tracing/openai), [Bedrock](https://docs.arize.com/phoenix/tracing/integrations-tracing/bedrock), [MistralAI](https://docs.arize.com/phoenix/tracing/integrations-tracing/mistralai), [VertexAI](https://docs.arize.com/phoenix/tracing/integrations-tracing/vertexai), [LiteLLM](https://docs.arize.com/phoenix/tracing/integrations-tracing/litellm), and more). For details on auto-instrumentation, check out the [OpenInference](https://github.com/Arize-ai/openinference) project.
168
168
 
169
169
  Phoenix runs practically anywhere, including your Jupyter notebook, local machine, containerized deployment, or in the cloud.
170
170
 
@@ -1,12 +1,12 @@
1
1
  phoenix/__init__.py,sha256=X3eUEwd2rG8KKWWYVNNDJoqo08ihfjgHhlP29dcdNJE,5481
2
2
  phoenix/auth.py,sha256=VVMHrWN31tln3Zo4z6ofecrV4daiqJjLd8r85mqlxek,10939
3
- phoenix/config.py,sha256=V5DtJ5JZOqFr7CdXdYo_fPEDHVvxyY856xftHl3g9NY,29007
3
+ phoenix/config.py,sha256=dKSC-46EQrHVSYbUoQKoNOTTOGGWQC4tiiXe-UCLD2w,29483
4
4
  phoenix/datetime_utils.py,sha256=iJzNG6YJ6V7_u8B2iA7P2Z26FyxYbOPtx0dhJ7kNDHA,3398
5
5
  phoenix/exceptions.py,sha256=n2L2KKuecrdflB9MsCdAYCiSEvGJptIsfRkXMoJle7A,169
6
6
  phoenix/py.typed,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
7
7
  phoenix/services.py,sha256=kpW1WL0kiB8XJsO6XycvZVJ-lBkNoenhQ7atCvBoSe8,5365
8
8
  phoenix/settings.py,sha256=ht-0oN-sMV6SPXrk7Tu1EZlngpAYkGNLYPhO8DyrdQI,661
9
- phoenix/version.py,sha256=nW2S9cxog2B_2xeN534jt1o6PE7ow-7Hd0PLILs5K5o,22
9
+ phoenix/version.py,sha256=UaNl2yn2v4Ia_5--i67UcyA4R7I_VLgKz75bbOAoRXU,22
10
10
  phoenix/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
11
  phoenix/core/embedding_dimension.py,sha256=zKGbcvwOXgLf-yrJBpQyKtd-LEOPRKHnUToyAU8Owis,87
12
12
  phoenix/core/model.py,sha256=qBFraOtmwCCnWJltKNP18DDG0mULXigytlFsa6YOz6k,4837
@@ -99,7 +99,7 @@ phoenix/server/api/auth.py,sha256=nywpmfMI1trZTbZRD3oBj4kFjzg_vnxDljcM431T1eY,12
99
99
  phoenix/server/api/context.py,sha256=OopBkMnY48TzulTtfuay3MXmhbFIWPtPoAsbhCW-Pl0,6459
100
100
  phoenix/server/api/exceptions.py,sha256=TA0JuY2YRnj35qGuMSQ8d0ToHum9gWm9W--3fSKHrX0,1171
101
101
  phoenix/server/api/interceptor.py,sha256=ykDnoC_apUd-llVli3m1CW18kNSIgjz2qZ6m5JmPDu8,1294
102
- phoenix/server/api/queries.py,sha256=QKZkLGzqDRa7EDfUADnk3jI0Rzsc_g_fe4y4oOBGbKw,34866
102
+ phoenix/server/api/queries.py,sha256=2D0vmNN853NA9-8OGri5ByEA4Di96uzzOLs4cmqL5Ls,35327
103
103
  phoenix/server/api/schema.py,sha256=fcs36xQwFF_Qe41_5cWR8wYpDvOrnbcyTeo5WNMbDsA,1702
104
104
  phoenix/server/api/subscriptions.py,sha256=DSIgQF6lQqkbc7D0AaI5R4g3hIHbU04H5Y2UIpwmpy0,22989
105
105
  phoenix/server/api/utils.py,sha256=quCBRcusc6PUq9tJq7M8PgwFZp7nXgVAxtbw8feribY,833
@@ -144,11 +144,11 @@ phoenix/server/api/dataloaders/cache/two_tier_cache.py,sha256=cmo8FUT3E91R139IEz
144
144
  phoenix/server/api/helpers/__init__.py,sha256=m2-xaSPqUiSs91k62JaRDjFNfl-1byxBfY-m_Vxw16U,272
145
145
  phoenix/server/api/helpers/dataset_helpers.py,sha256=DoMBTg-qXTnC_K4Evx1WKpCCYgRbITpVqyY-8efJRf0,8984
146
146
  phoenix/server/api/helpers/experiment_run_filters.py,sha256=DOnVwrmn39eAkk2mwuZP8kIcAnR5jrOgllEwWSjsw94,29893
147
- phoenix/server/api/helpers/playground_clients.py,sha256=tNl37HG2e14ehx1sVLhLHcRkZv2u9Dd8_521j1W1Qxw,40142
147
+ phoenix/server/api/helpers/playground_clients.py,sha256=VSOZnRITe1FvHunzG_7gTHfy6vMQEfFK6RnzCjtj97A,40842
148
148
  phoenix/server/api/helpers/playground_registry.py,sha256=CPLMziFB2wmr-dfbx7VbzO2f8YIG_k5RftzvGXYGQ1w,2570
149
149
  phoenix/server/api/helpers/playground_spans.py,sha256=PjGNDc7cpqn5lmRM6TO_J1eVRGlgsNdQ8IT--5JVz0o,16881
150
150
  phoenix/server/api/helpers/prompts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
151
- phoenix/server/api/helpers/prompts/models.py,sha256=10dIZlDy1a3sKmFk--Af5jk-8ATBqbNPXlOZYSIDwGk,18734
151
+ phoenix/server/api/helpers/prompts/models.py,sha256=zwWBA5GQvEHT4xyZwP-_kr1rJZ7SHnguATsQwsFw5aw,19519
152
152
  phoenix/server/api/helpers/prompts/conversions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
153
153
  phoenix/server/api/helpers/prompts/conversions/anthropic.py,sha256=uGTPzlw_9RaRPUsAIHyiRgD0NpDoajQzf7Am8nlJ4Cg,3279
154
154
  phoenix/server/api/helpers/prompts/conversions/openai.py,sha256=a43WAftFn_me6ePHDufqvlg-4Z2C31owUSsqYC0YUP8,2589
@@ -174,7 +174,7 @@ phoenix/server/api/input_types/DimensionFilter.py,sha256=eBYcn7ECSJQlEePvbStqkHB
174
174
  phoenix/server/api/input_types/DimensionInput.py,sha256=Vfx5FmiMKey4-EHDQsQRPzSAMRJMN5oVMLDUl4NKAa8,164
175
175
  phoenix/server/api/input_types/GenerativeModelInput.py,sha256=n6OCkX44I1AIovMAHCxy8SvqPKDb_BYDPA-fn_JnckQ,634
176
176
  phoenix/server/api/input_types/Granularity.py,sha256=dbBlD_GsIBa8_xrx4JlLuR59bQ0NRB5H-cv1zvcb-cw,2299
177
- phoenix/server/api/input_types/InvocationParameters.py,sha256=I_FvPvY2sXxNd-kFSB96-1DOW7lo-VbqVWzppU_5hy8,5196
177
+ phoenix/server/api/input_types/InvocationParameters.py,sha256=62xL0iIKvuQherkuJaJ6Lha4TTEoYLpvH-pEP9awK6k,5260
178
178
  phoenix/server/api/input_types/PatchAnnotationInput.py,sha256=NWhkcbcGNPwfOYsN3wm5YFNNrSc5T-8Y5my74RK99HE,520
179
179
  phoenix/server/api/input_types/PatchDatasetExamplesInput.py,sha256=_uMqkAInhLDvzUSASl6HgLNulTsekMcYzyd5J6LF90I,884
180
180
  phoenix/server/api/input_types/PatchDatasetInput.py,sha256=OURtTVY8Z_oFEDtKwT1LCMaOK5D4QYo5TVQ6mDrex-g,328
@@ -195,9 +195,9 @@ phoenix/server/api/mutations/dataset_mutations.py,sha256=V52mL0vizxL9cvWWBkmd19r
195
195
  phoenix/server/api/mutations/experiment_mutations.py,sha256=p3CoLAa8nFPa3D759Y2A7De_PVJNGOL98mA3HoZBrRQ,3188
196
196
  phoenix/server/api/mutations/export_events_mutations.py,sha256=xoDnVWC7eA_8wNQP0-oyiHojyUZ0EhVVSrsAnztetC0,3993
197
197
  phoenix/server/api/mutations/project_mutations.py,sha256=u7kLvJbBFR418F9lMamiisZerF18E8h5wGKV4sDTF-g,2674
198
- phoenix/server/api/mutations/prompt_label_mutations.py,sha256=9k8Q_w8JbNbq8U9pKlu21sQ5450xfriWm19OYl7vi4g,6967
199
- phoenix/server/api/mutations/prompt_mutations.py,sha256=KwrcXbb361TxaFihei5Yt2a6Fg6LyObJz2VqICOOSYc,11754
200
- phoenix/server/api/mutations/prompt_version_tag_mutations.py,sha256=Jt4NBJn2EoAjiEI4ojNUXZs0TXZab-Erd-o2hvmapKw,5593
198
+ phoenix/server/api/mutations/prompt_label_mutations.py,sha256=uCiVcULtmgaNaav4M08ipPYM68sZv1MVLrCgvW-Xyn8,7317
199
+ phoenix/server/api/mutations/prompt_mutations.py,sha256=Yg-6L2PiKUZfFyNarptu3OdE0uA2_Nyl3VrLVP8FJ9Y,12114
200
+ phoenix/server/api/mutations/prompt_version_tag_mutations.py,sha256=t77osYb5he2Am4UeNis7pzY9MnaA9PNEQhsQelRH8k8,5767
201
201
  phoenix/server/api/mutations/span_annotations_mutations.py,sha256=sumBLUqRKlgMASWdWwYItmIJ2l7AyAp_PlIYeXYfguc,5970
202
202
  phoenix/server/api/mutations/trace_annotations_mutations.py,sha256=sEcEt8hbMt8YMiRX5o3xcJ5rWWZbDeBPMNz2teZoi3U,5945
203
203
  phoenix/server/api/mutations/user_mutations.py,sha256=FgZXQjCqmJ_0dyqiXv6NoGF7TjOO2a0aX7xDMDKtl-A,13603
@@ -214,7 +214,7 @@ phoenix/server/api/routers/v1/datasets.py,sha256=gHlF4x0EmWiJ-8vwJygoh0bO3gvDBmi
214
214
  phoenix/server/api/routers/v1/evaluations.py,sha256=RpOkTylp5Da6BvPZGuN8ksnxz_BVXRIwyOvwX9Iko8U,12647
215
215
  phoenix/server/api/routers/v1/experiment_evaluations.py,sha256=vx4CKlE84sAL1vtPiM_XWnbfrATQujOSzzduJDYgcyM,4829
216
216
  phoenix/server/api/routers/v1/experiment_runs.py,sha256=bInuasRv7ogiYf8fq-LwpJ5tptmMQsBNDlJAqwdymko,6378
217
- phoenix/server/api/routers/v1/experiments.py,sha256=cwpRWTjreXPqBoeYPv6pNrb3445MT1E6eDRuvj-3Paw,11799
217
+ phoenix/server/api/routers/v1/experiments.py,sha256=yJh48HSFjBB5PtQld9Kt2CxAYdpekl0jjIyeVHB30oE,15826
218
218
  phoenix/server/api/routers/v1/models.py,sha256=r0nM2kFJ3mxDqgc5vFr1cjNuyOPs3RIKE_DS2VMdF48,1749
219
219
  phoenix/server/api/routers/v1/prompts.py,sha256=kRsssgRulr-ys0ouLz4qG-TP-uG30UZcfTqc6hGwo08,14485
220
220
  phoenix/server/api/routers/v1/spans.py,sha256=uoU_bwIgz86fuvPjP5sX8goDyuCcnsTig-x3f17p60U,9625
@@ -313,17 +313,17 @@ phoenix/server/static/apple-touch-icon-76x76.png,sha256=CT_xT12I0u2i0WU8JzBZBuOQ
313
313
  phoenix/server/static/apple-touch-icon.png,sha256=fOfpjqGpWYbJ0eAurKsyoZP1EAs6ZVooBJ_SGk2ZkDs,3801
314
314
  phoenix/server/static/favicon.ico,sha256=bY0vvCKRftemZfPShwZtE93DiiQdaYaozkPGwNFr6H8,34494
315
315
  phoenix/server/static/modernizr.js,sha256=mvK-XtkNqjOral-QvzoqsyOMECXIMu5BQwSVN_wcU9c,2564
316
- phoenix/server/static/.vite/manifest.json,sha256=aU48BUyfaG96N3g_2XYlrdowrN2yZQzUos7La08GTWY,2165
317
- phoenix/server/static/assets/components-Bj66FcRz.js,sha256=K5b3NuB8Ci2Vhx6bK-I1Jyrbo9qqX4sWc67klHkY_vg,423203
318
- phoenix/server/static/assets/index-Dwk10lgb.js,sha256=fIZlUncLCnFulYIknEqBeoLnl8m74aMlNu5AdGDp-fM,59207
319
- phoenix/server/static/assets/pages-BNZVqOUi.js,sha256=8fxg80bgMommRcZdjGdhvbEwYvnr8AIihF36a1V_qpQ,832580
316
+ phoenix/server/static/.vite/manifest.json,sha256=K4ttZ0jyEeGm7WAbq9qhDV721dbvybl6a5vyCYaEyhI,2165
317
+ phoenix/server/static/assets/components-C4AzQH6p.js,sha256=DYuNkVh6wvxk5Q2yemDP_z1NKJNaIF-xXnkh7MW-TUI,424183
318
+ phoenix/server/static/assets/index-DYSOLesW.js,sha256=ADG8F-Vtdnr3tYNT7J3FVudTZTOCIe_kThUh_Q0hOMs,59207
319
+ phoenix/server/static/assets/pages-DEHszGOs.js,sha256=WGmWP8Modo0wt8HTltBn61YHReEqRtnV1uFtlfxe7Xw,837387
320
320
  phoenix/server/static/assets/vendor-Cg6lcjUC.css,sha256=nZrkr0u6NNElFGvpWHk9GTHeGoibCXCli1bE7mXZGZg,1816
321
- phoenix/server/static/assets/vendor-arizeai-DoGO67dU.js,sha256=Rw1UPVWqJ4kV_n5mdr5t89ADWRBxbdHVObTbx--81S8,202331
322
- phoenix/server/static/assets/vendor-codemirror-BLdSYxpm.js,sha256=VObEa3PGY2JNemLuOXNczCALhI5I9k8yI6a6G8C-Kwc,393505
323
- phoenix/server/static/assets/vendor-recharts-CjOpOw1c.js,sha256=aA2Y0gIqOCq8VYDwRT66P7LypCHnY_Zysz79YBxe_0o,282095
324
- phoenix/server/static/assets/vendor-shiki-BwTCxCQY.js,sha256=2okHp2yxVOikaMS2HlgctZmrC2YfSfzAyfCuO6nFP0k,8980312
321
+ phoenix/server/static/assets/vendor-VJCVsFqd.js,sha256=d5PqgO3T3CRxy2q7Jk4b-1MVab_E3kKeDg3OtBILa0E,2265494
322
+ phoenix/server/static/assets/vendor-arizeai-CLxvyk4B.js,sha256=Ri6Kt_hswP0fMbH8BW1lYxzcoOClTP4MPubhjRRqXRg,202331
323
+ phoenix/server/static/assets/vendor-codemirror-0mUqu36F.js,sha256=WOPvKseqLr9P1W5beQJSTX3m_6JIkbx7xjWWZK8qHeE,393496
324
+ phoenix/server/static/assets/vendor-recharts-CfKQSOmq.js,sha256=TWJ68mOSnbpn8XscPz1N3Zs-EkLLqYDtgQ25vDJCL4I,282095
325
+ phoenix/server/static/assets/vendor-shiki-BsgMOuir.js,sha256=cFiYo70OgEzfurmjGOmzkxAWdlOcSEfZBSY6RFqA0mk,8980312
325
326
  phoenix/server/static/assets/vendor-three-C-AGeJYv.js,sha256=c9nLPH5YDRFCzTNuwWO8_5KqcnunPo53mQsb7y9JFW8,620972
326
- phoenix/server/static/assets/vendor-yn6w6Ozi.js,sha256=z2z4fixLGqjG1VhhAy0Mm2sjYlkgmi97-hbwWsIFCE8,2259231
327
327
  phoenix/server/templates/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
328
328
  phoenix/server/templates/index.html,sha256=e8_jdi7Eo19SK7DI_gglkTW094D17E0VAegoMmmmvIc,4330
329
329
  phoenix/session/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -363,9 +363,9 @@ phoenix/utilities/project.py,sha256=auVpARXkDb-JgeX5f2aStyFIkeKvGwN9l7qrFeJMVxI,
363
363
  phoenix/utilities/re.py,sha256=6YyUWIkv0zc2SigsxfOWIHzdpjKA_TZo2iqKq7zJKvw,2081
364
364
  phoenix/utilities/span_store.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
365
365
  phoenix/utilities/template_formatters.py,sha256=gh9PJD6WEGw7TEYXfSst1UR4pWWwmjxMLrDVQ_CkpkQ,2779
366
- arize_phoenix-8.7.0.dist-info/METADATA,sha256=wZqSajYS49SZIeKPOs8K3YstHSO5_bvjXABCC1UY9bA,23646
367
- arize_phoenix-8.7.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
368
- arize_phoenix-8.7.0.dist-info/entry_points.txt,sha256=Pgpn8Upxx9P8z8joPXZWl2LlnAlGc3gcQoVchb06X1Q,94
369
- arize_phoenix-8.7.0.dist-info/licenses/IP_NOTICE,sha256=JBqyyCYYxGDfzQ0TtsQgjts41IJoa-hiwDrBjCb9gHM,469
370
- arize_phoenix-8.7.0.dist-info/licenses/LICENSE,sha256=HFkW9REuMOkvKRACuwLPT0hRydHb3zNg-fdFt94td18,3794
371
- arize_phoenix-8.7.0.dist-info/RECORD,,
366
+ arize_phoenix-8.9.0.dist-info/METADATA,sha256=qCJ76TtsyknUCFvpwJF8QSBKy7vJfXPqE9gAiZbmLC4,23738
367
+ arize_phoenix-8.9.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
368
+ arize_phoenix-8.9.0.dist-info/entry_points.txt,sha256=Pgpn8Upxx9P8z8joPXZWl2LlnAlGc3gcQoVchb06X1Q,94
369
+ arize_phoenix-8.9.0.dist-info/licenses/IP_NOTICE,sha256=JBqyyCYYxGDfzQ0TtsQgjts41IJoa-hiwDrBjCb9gHM,469
370
+ arize_phoenix-8.9.0.dist-info/licenses/LICENSE,sha256=HFkW9REuMOkvKRACuwLPT0hRydHb3zNg-fdFt94td18,3794
371
+ arize_phoenix-8.9.0.dist-info/RECORD,,
phoenix/config.py CHANGED
@@ -86,6 +86,13 @@ ENV_PHOENIX_SQL_DATABASE_SCHEMA = "PHOENIX_SQL_DATABASE_SCHEMA"
86
86
  The schema to use for the PostgresSQL database. (This is ignored for SQLite.)
87
87
  See e.g. https://www.postgresql.org/docs/current/ddl-schemas.html
88
88
  """
89
+ ENV_PHOENIX_DATABASE_ALLOCATED_STORAGE_CAPACITY_GIBIBYTES = (
90
+ "PHOENIX_DATABASE_ALLOCATED_STORAGE_CAPACITY_GIBIBYTES"
91
+ )
92
+ """
93
+ The allocated storage capacity for the Phoenix database in gibibytes (2^30 bytes). Use float for
94
+ fractional value. This is currently used only by the UI for informational displays.
95
+ """
89
96
  ENV_PHOENIX_ENABLE_PROMETHEUS = "PHOENIX_ENABLE_PROMETHEUS"
90
97
  """
91
98
  Whether to enable Prometheus. Defaults to false.
@@ -690,6 +697,10 @@ def get_env_database_schema() -> Optional[str]:
690
697
  return getenv(ENV_PHOENIX_SQL_DATABASE_SCHEMA)
691
698
 
692
699
 
700
+ def get_env_database_allocated_storage_capacity_gibibytes() -> Optional[float]:
701
+ return _float_val(ENV_PHOENIX_DATABASE_ALLOCATED_STORAGE_CAPACITY_GIBIBYTES)
702
+
703
+
693
704
  def get_env_enable_prometheus() -> bool:
694
705
  if (enable_promotheus := getenv(ENV_PHOENIX_ENABLE_PROMETHEUS)) is None or (
695
706
  enable_promotheus_lower := enable_promotheus.lower()
@@ -862,6 +862,27 @@ class AnthropicStreamingClient(PlaygroundStreamingClient):
862
862
  return content
863
863
 
864
864
 
865
+ @register_llm_client(
866
+ provider_key=GenerativeProviderKey.ANTHROPIC,
867
+ model_names=[
868
+ "claude-3-7-sonnet-latest",
869
+ "claude-3-7-sonnet-20250219",
870
+ ],
871
+ )
872
+ class AnthropicReasoningStreamingClient(AnthropicStreamingClient):
873
+ @classmethod
874
+ def supported_invocation_parameters(cls) -> list[InvocationParameter]:
875
+ invocation_params = super().supported_invocation_parameters()
876
+ invocation_params.append(
877
+ JSONInvocationParameter(
878
+ invocation_name="thinking",
879
+ canonical_name=CanonicalParameterName.ANTHROPIC_EXTENDED_THINKING,
880
+ label="Thinking Budget",
881
+ )
882
+ )
883
+ return invocation_params
884
+
885
+
865
886
  @register_llm_client(
866
887
  provider_key=GenerativeProviderKey.GOOGLE,
867
888
  model_names=[
@@ -3,8 +3,8 @@ from __future__ import annotations
3
3
  from enum import Enum
4
4
  from typing import Any, Literal, Mapping, Optional, Union
5
5
 
6
- from pydantic import BaseModel, ConfigDict, Field, RootModel
7
- from typing_extensions import Annotated, TypeAlias, TypeGuard, assert_never
6
+ from pydantic import BaseModel, ConfigDict, Field, RootModel, model_validator
7
+ from typing_extensions import Annotated, Self, TypeAlias, TypeGuard, assert_never
8
8
 
9
9
  from phoenix.db.types.model_provider import ModelProvider
10
10
  from phoenix.server.api.helpers.prompts.conversions.anthropic import AnthropicToolChoiceConversion
@@ -370,11 +370,32 @@ class PromptAzureOpenAIInvocationParameters(PromptModel):
370
370
  azure_openai: PromptAzureOpenAIInvocationParametersContent
371
371
 
372
372
 
373
+ class PromptAnthropicThinkingConfigDisabled(PromptModel):
374
+ type: Literal["disabled"]
375
+
376
+
377
+ class PromptAnthropicThinkingConfigEnabled(PromptModel):
378
+ type: Literal["enabled"]
379
+ budget_tokens: int = Field(..., ge=1024)
380
+
381
+
373
382
  class PromptAnthropicInvocationParametersContent(PromptModel):
374
383
  max_tokens: int
375
384
  temperature: float = UNDEFINED
376
385
  top_p: float = UNDEFINED
377
386
  stop_sequences: list[str] = UNDEFINED
387
+ thinking: Annotated[
388
+ Union[PromptAnthropicThinkingConfigDisabled, PromptAnthropicThinkingConfigEnabled],
389
+ Field(..., discriminator="type"),
390
+ ] = UNDEFINED
391
+
392
+ @model_validator(mode="after")
393
+ def check_thinking_budget_tokens_lt_max_tokens(self) -> Self:
394
+ if self.thinking is UNDEFINED:
395
+ return self
396
+ if self.thinking.type == "enabled" and self.thinking.budget_tokens >= self.max_tokens:
397
+ raise ValueError("The thinking budget must be less than max tokens.")
398
+ return self
378
399
 
379
400
 
380
401
  class PromptAnthropicInvocationParameters(PromptModel):
@@ -16,6 +16,7 @@ class CanonicalParameterName(str, Enum):
16
16
  TOOL_CHOICE = "tool_choice"
17
17
  RESPONSE_FORMAT = "response_format"
18
18
  REASONING_EFFORT = "reasoning_effort"
19
+ ANTHROPIC_EXTENDED_THINKING = "anthropic_extended_thinking"
19
20
 
20
21
 
21
22
  @strawberry.enum
@@ -11,6 +11,7 @@ from strawberry.types import Info
11
11
 
12
12
  from phoenix.db import models
13
13
  from phoenix.db.types.identifier import Identifier as IdentifierModel
14
+ from phoenix.server.api.auth import IsLocked, IsNotReadOnly
14
15
  from phoenix.server.api.context import Context
15
16
  from phoenix.server.api.exceptions import Conflict, NotFound
16
17
  from phoenix.server.api.queries import Query
@@ -58,7 +59,7 @@ class PromptLabelMutationPayload:
58
59
 
59
60
  @strawberry.type
60
61
  class PromptLabelMutationMixin:
61
- @strawberry.mutation
62
+ @strawberry.mutation(permission_classes=[IsNotReadOnly, IsLocked]) # type: ignore
62
63
  async def create_prompt_label(
63
64
  self, info: Info[Context, None], input: CreatePromptLabelInput
64
65
  ) -> PromptLabelMutationPayload:
@@ -77,7 +78,7 @@ class PromptLabelMutationMixin:
77
78
  query=Query(),
78
79
  )
79
80
 
80
- @strawberry.mutation
81
+ @strawberry.mutation(permission_classes=[IsNotReadOnly, IsLocked]) # type: ignore
81
82
  async def patch_prompt_label(
82
83
  self, info: Info[Context, None], input: PatchPromptLabelInput
83
84
  ) -> PromptLabelMutationPayload:
@@ -106,7 +107,7 @@ class PromptLabelMutationMixin:
106
107
  query=Query(),
107
108
  )
108
109
 
109
- @strawberry.mutation
110
+ @strawberry.mutation(permission_classes=[IsNotReadOnly]) # type: ignore
110
111
  async def delete_prompt_label(
111
112
  self, info: Info[Context, None], input: DeletePromptLabelInput
112
113
  ) -> PromptLabelMutationPayload:
@@ -130,7 +131,7 @@ class PromptLabelMutationMixin:
130
131
  query=Query(),
131
132
  )
132
133
 
133
- @strawberry.mutation
134
+ @strawberry.mutation(permission_classes=[IsNotReadOnly, IsLocked]) # type: ignore
134
135
  async def set_prompt_label(
135
136
  self, info: Info[Context, None], input: SetPromptLabelInput
136
137
  ) -> PromptLabelMutationPayload:
@@ -160,7 +161,7 @@ class PromptLabelMutationMixin:
160
161
  query=Query(),
161
162
  )
162
163
 
163
- @strawberry.mutation
164
+ @strawberry.mutation(permission_classes=[IsNotReadOnly]) # type: ignore
164
165
  async def unset_prompt_label(
165
166
  self, info: Info[Context, None], input: UnsetPromptLabelInput
166
167
  ) -> PromptLabelMutationPayload:
@@ -13,6 +13,7 @@ from strawberry.types import Info
13
13
  from phoenix.db import models
14
14
  from phoenix.db.types.identifier import Identifier as IdentifierModel
15
15
  from phoenix.db.types.model_provider import ModelProvider
16
+ from phoenix.server.api.auth import IsLocked, IsNotReadOnly
16
17
  from phoenix.server.api.context import Context
17
18
  from phoenix.server.api.exceptions import BadRequest, Conflict, NotFound
18
19
  from phoenix.server.api.helpers.prompts.models import (
@@ -74,7 +75,7 @@ class DeletePromptMutationPayload:
74
75
 
75
76
  @strawberry.type
76
77
  class PromptMutationMixin:
77
- @strawberry.mutation
78
+ @strawberry.mutation(permission_classes=[IsNotReadOnly, IsLocked]) # type: ignore
78
79
  async def create_chat_prompt(
79
80
  self, info: Info[Context, None], input: CreateChatPromptInput
80
81
  ) -> Prompt:
@@ -141,7 +142,7 @@ class PromptMutationMixin:
141
142
  raise Conflict(f"A prompt named '{input.name}' already exists")
142
143
  return to_gql_prompt_from_orm(prompt)
143
144
 
144
- @strawberry.mutation
145
+ @strawberry.mutation(permission_classes=[IsNotReadOnly, IsLocked]) # type: ignore
145
146
  async def create_chat_prompt_version(
146
147
  self,
147
148
  info: Info[Context, None],
@@ -219,7 +220,7 @@ class PromptMutationMixin:
219
220
 
220
221
  return to_gql_prompt_from_orm(prompt)
221
222
 
222
- @strawberry.mutation
223
+ @strawberry.mutation(permission_classes=[IsNotReadOnly]) # type: ignore
223
224
  async def delete_prompt(
224
225
  self, info: Info[Context, None], input: DeletePromptInput
225
226
  ) -> DeletePromptMutationPayload:
@@ -236,7 +237,7 @@ class PromptMutationMixin:
236
237
  await session.commit()
237
238
  return DeletePromptMutationPayload(query=Query())
238
239
 
239
- @strawberry.mutation
240
+ @strawberry.mutation(permission_classes=[IsNotReadOnly, IsLocked]) # type: ignore
240
241
  async def clone_prompt(self, info: Info[Context, None], input: ClonePromptInput) -> Prompt:
241
242
  prompt_id = from_global_id_with_expected_type(
242
243
  global_id=input.prompt_id, expected_type_name=Prompt.__name__
@@ -289,7 +290,7 @@ class PromptMutationMixin:
289
290
  raise Conflict(f"A prompt named '{input.name}' already exists")
290
291
  return to_gql_prompt_from_orm(new_prompt)
291
292
 
292
- @strawberry.mutation
293
+ @strawberry.mutation(permission_classes=[IsNotReadOnly, IsLocked]) # type: ignore
293
294
  async def patch_prompt(self, info: Info[Context, None], input: PatchPromptInput) -> Prompt:
294
295
  prompt_id = from_global_id_with_expected_type(
295
296
  global_id=input.prompt_id, expected_type_name=Prompt.__name__
@@ -10,6 +10,7 @@ from strawberry.types import Info
10
10
 
11
11
  from phoenix.db import models
12
12
  from phoenix.db.types.identifier import Identifier as IdentifierModel
13
+ from phoenix.server.api.auth import IsLocked, IsNotReadOnly
13
14
  from phoenix.server.api.context import Context
14
15
  from phoenix.server.api.exceptions import BadRequest, Conflict, NotFound
15
16
  from phoenix.server.api.queries import Query
@@ -41,7 +42,7 @@ class PromptVersionTagMutationPayload:
41
42
 
42
43
  @strawberry.type
43
44
  class PromptVersionTagMutationMixin:
44
- @strawberry.mutation
45
+ @strawberry.mutation(permission_classes=[IsNotReadOnly]) # type: ignore
45
46
  async def delete_prompt_version_tag(
46
47
  self, info: Info[Context, None], input: DeletePromptVersionTagInput
47
48
  ) -> PromptVersionTagMutationPayload:
@@ -77,7 +78,7 @@ class PromptVersionTagMutationMixin:
77
78
  prompt_version_tag=None, query=Query(), prompt=to_gql_prompt_from_orm(prompt)
78
79
  )
79
80
 
80
- @strawberry.mutation
81
+ @strawberry.mutation(permission_classes=[IsNotReadOnly, IsLocked]) # type: ignore
81
82
  async def set_prompt_version_tag(
82
83
  self, info: Info[Context, None], input: SetPromptVersionTagInput
83
84
  ) -> PromptVersionTagMutationPayload:
@@ -13,7 +13,11 @@ from strawberry.relay import Connection, GlobalID, Node
13
13
  from strawberry.types import Info
14
14
  from typing_extensions import Annotated, TypeAlias, assert_never
15
15
 
16
- from phoenix.config import ENV_PHOENIX_SQL_DATABASE_SCHEMA, getenv
16
+ from phoenix.config import (
17
+ ENV_PHOENIX_SQL_DATABASE_SCHEMA,
18
+ get_env_database_allocated_storage_capacity_gibibytes,
19
+ getenv,
20
+ )
17
21
  from phoenix.db import enums, models
18
22
  from phoenix.db.helpers import SupportedSQLDialect
19
23
  from phoenix.db.models import DatasetExample as OrmExample
@@ -789,6 +793,15 @@ class Query:
789
793
  clustered_events=clustered_events,
790
794
  )
791
795
 
796
+ @strawberry.field(
797
+ description="The allocated storage capacity of the database in bytes. "
798
+ "Return None if this information is unavailable.",
799
+ ) # type: ignore
800
+ async def db_storage_capacity_bytes(self) -> Optional[float]:
801
+ if gibibytes := get_env_database_allocated_storage_capacity_gibibytes():
802
+ return gibibytes * 2**30
803
+ return None
804
+
792
805
  @strawberry.field
793
806
  async def db_table_stats(
794
807
  self,
@@ -1,11 +1,13 @@
1
+ import json
1
2
  from datetime import datetime
2
3
  from random import getrandbits
3
4
  from typing import Any, Optional
4
5
 
5
- from fastapi import APIRouter, HTTPException, Path
6
+ from fastapi import APIRouter, HTTPException, Path, Response
6
7
  from pydantic import Field
7
- from sqlalchemy import select
8
+ from sqlalchemy import and_, func, select
8
9
  from starlette.requests import Request
10
+ from starlette.responses import PlainTextResponse
9
11
  from starlette.status import HTTP_404_NOT_FOUND
10
12
  from strawberry.relay import GlobalID
11
13
 
@@ -306,3 +308,102 @@ async def list_experiments(
306
308
  ]
307
309
 
308
310
  return ListExperimentsResponseBody(data=data)
311
+
312
+
313
+ @router.get(
314
+ "/experiments/{experiment_id}/json",
315
+ operation_id="getExperimentJSON",
316
+ summary="Download experiment runs as a JSON file",
317
+ response_class=PlainTextResponse,
318
+ responses=add_errors_to_responses(
319
+ [
320
+ {"status_code": HTTP_404_NOT_FOUND, "description": "Experiment not found"},
321
+ ]
322
+ ),
323
+ )
324
+ async def get_experiment_jsonl(
325
+ request: Request,
326
+ response: Response,
327
+ experiment_id: str = Path(..., title="Experiment ID"),
328
+ ) -> str:
329
+ experiment_globalid = GlobalID.from_id(experiment_id)
330
+ try:
331
+ experiment_rowid = from_global_id_with_expected_type(experiment_globalid, "Experiment")
332
+ except ValueError:
333
+ raise HTTPException(
334
+ detail=f"Experiment with ID {experiment_globalid} does not exist",
335
+ status_code=HTTP_404_NOT_FOUND,
336
+ )
337
+
338
+ async with request.app.state.db() as session:
339
+ experiment = await session.get(models.Experiment, experiment_rowid)
340
+ if not experiment:
341
+ raise HTTPException(
342
+ detail=f"Experiment with ID {experiment_globalid} does not exist",
343
+ status_code=HTTP_404_NOT_FOUND,
344
+ )
345
+ revision_ids = (
346
+ select(func.max(models.DatasetExampleRevision.id))
347
+ .join(
348
+ models.DatasetExample,
349
+ models.DatasetExample.id == models.DatasetExampleRevision.dataset_example_id,
350
+ )
351
+ .where(
352
+ and_(
353
+ models.DatasetExampleRevision.dataset_version_id
354
+ <= experiment.dataset_version_id,
355
+ models.DatasetExample.dataset_id == experiment.dataset_id,
356
+ )
357
+ )
358
+ .group_by(models.DatasetExampleRevision.dataset_example_id)
359
+ .scalar_subquery()
360
+ )
361
+ runs_and_revisions = (
362
+ await session.execute(
363
+ select(models.ExperimentRun, models.DatasetExampleRevision)
364
+ .join(
365
+ models.DatasetExample,
366
+ models.DatasetExample.id == models.ExperimentRun.dataset_example_id,
367
+ )
368
+ .join(
369
+ models.DatasetExampleRevision,
370
+ and_(
371
+ models.DatasetExample.id
372
+ == models.DatasetExampleRevision.dataset_example_id,
373
+ models.DatasetExampleRevision.id.in_(revision_ids),
374
+ models.DatasetExampleRevision.revision_kind != "DELETE",
375
+ ),
376
+ )
377
+ .where(models.ExperimentRun.experiment_id == experiment_rowid)
378
+ .order_by(
379
+ models.ExperimentRun.dataset_example_id, models.ExperimentRun.repetition_number
380
+ )
381
+ )
382
+ ).all()
383
+ if not runs_and_revisions:
384
+ raise HTTPException(
385
+ detail=f"Experiment with ID {experiment_globalid} has no runs",
386
+ status_code=HTTP_404_NOT_FOUND,
387
+ )
388
+ records = []
389
+ for run, revision in runs_and_revisions:
390
+ record = {
391
+ "example_id": str(
392
+ GlobalID(models.DatasetExample.__name__, str(run.dataset_example_id))
393
+ ),
394
+ "repetition_number": run.repetition_number,
395
+ "input": revision.input,
396
+ "reference_output": revision.output,
397
+ "output": run.output,
398
+ "error": run.error,
399
+ "latency_ms": run.latency_ms,
400
+ "start_time": run.start_time.isoformat(),
401
+ "end_time": run.end_time.isoformat(),
402
+ "trace_id": run.trace_id,
403
+ "prompt_token_count": run.prompt_token_count,
404
+ "completion_token_count": run.completion_token_count,
405
+ }
406
+ records.append(record)
407
+
408
+ response.headers["content-disposition"] = f'attachment; filename="{experiment.name}.json"'
409
+ return json.dumps(records, ensure_ascii=False, indent=2)