arize-phoenix 10.0.4__py3-none-any.whl → 12.28.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.
- {arize_phoenix-10.0.4.dist-info → arize_phoenix-12.28.1.dist-info}/METADATA +124 -72
- arize_phoenix-12.28.1.dist-info/RECORD +499 -0
- {arize_phoenix-10.0.4.dist-info → arize_phoenix-12.28.1.dist-info}/WHEEL +1 -1
- {arize_phoenix-10.0.4.dist-info → arize_phoenix-12.28.1.dist-info}/licenses/IP_NOTICE +1 -1
- phoenix/__generated__/__init__.py +0 -0
- phoenix/__generated__/classification_evaluator_configs/__init__.py +20 -0
- phoenix/__generated__/classification_evaluator_configs/_document_relevance_classification_evaluator_config.py +17 -0
- phoenix/__generated__/classification_evaluator_configs/_hallucination_classification_evaluator_config.py +17 -0
- phoenix/__generated__/classification_evaluator_configs/_models.py +18 -0
- phoenix/__generated__/classification_evaluator_configs/_tool_selection_classification_evaluator_config.py +17 -0
- phoenix/__init__.py +5 -4
- phoenix/auth.py +39 -2
- phoenix/config.py +1763 -91
- phoenix/datetime_utils.py +120 -2
- phoenix/db/README.md +595 -25
- phoenix/db/bulk_inserter.py +145 -103
- phoenix/db/engines.py +140 -33
- phoenix/db/enums.py +3 -12
- phoenix/db/facilitator.py +302 -35
- phoenix/db/helpers.py +1000 -65
- phoenix/db/iam_auth.py +64 -0
- phoenix/db/insertion/dataset.py +135 -2
- phoenix/db/insertion/document_annotation.py +9 -6
- phoenix/db/insertion/evaluation.py +2 -3
- phoenix/db/insertion/helpers.py +17 -2
- phoenix/db/insertion/session_annotation.py +176 -0
- phoenix/db/insertion/span.py +15 -11
- phoenix/db/insertion/span_annotation.py +3 -4
- phoenix/db/insertion/trace_annotation.py +3 -4
- phoenix/db/insertion/types.py +50 -20
- phoenix/db/migrations/versions/01a8342c9cdf_add_user_id_on_datasets.py +40 -0
- phoenix/db/migrations/versions/0df286449799_add_session_annotations_table.py +105 -0
- phoenix/db/migrations/versions/272b66ff50f8_drop_single_indices.py +119 -0
- phoenix/db/migrations/versions/58228d933c91_dataset_labels.py +67 -0
- phoenix/db/migrations/versions/699f655af132_experiment_tags.py +57 -0
- phoenix/db/migrations/versions/735d3d93c33e_add_composite_indices.py +41 -0
- phoenix/db/migrations/versions/a20694b15f82_cost.py +196 -0
- phoenix/db/migrations/versions/ab513d89518b_add_user_id_on_dataset_versions.py +40 -0
- phoenix/db/migrations/versions/d0690a79ea51_users_on_experiments.py +40 -0
- phoenix/db/migrations/versions/deb2c81c0bb2_dataset_splits.py +139 -0
- phoenix/db/migrations/versions/e76cbd66ffc3_add_experiments_dataset_examples.py +87 -0
- phoenix/db/models.py +669 -56
- phoenix/db/pg_config.py +10 -0
- phoenix/db/types/model_provider.py +4 -0
- phoenix/db/types/token_price_customization.py +29 -0
- phoenix/db/types/trace_retention.py +23 -15
- phoenix/experiments/evaluators/utils.py +3 -3
- phoenix/experiments/functions.py +160 -52
- phoenix/experiments/tracing.py +2 -2
- phoenix/experiments/types.py +1 -1
- phoenix/inferences/inferences.py +1 -2
- phoenix/server/api/auth.py +38 -7
- phoenix/server/api/auth_messages.py +46 -0
- phoenix/server/api/context.py +100 -4
- phoenix/server/api/dataloaders/__init__.py +79 -5
- phoenix/server/api/dataloaders/annotation_configs_by_project.py +31 -0
- phoenix/server/api/dataloaders/annotation_summaries.py +60 -8
- phoenix/server/api/dataloaders/average_experiment_repeated_run_group_latency.py +50 -0
- phoenix/server/api/dataloaders/average_experiment_run_latency.py +17 -24
- phoenix/server/api/dataloaders/cache/two_tier_cache.py +1 -2
- phoenix/server/api/dataloaders/dataset_dataset_splits.py +52 -0
- phoenix/server/api/dataloaders/dataset_example_revisions.py +0 -1
- phoenix/server/api/dataloaders/dataset_example_splits.py +40 -0
- phoenix/server/api/dataloaders/dataset_examples_and_versions_by_experiment_run.py +47 -0
- phoenix/server/api/dataloaders/dataset_labels.py +36 -0
- phoenix/server/api/dataloaders/document_evaluation_summaries.py +2 -2
- phoenix/server/api/dataloaders/document_evaluations.py +6 -9
- phoenix/server/api/dataloaders/experiment_annotation_summaries.py +88 -34
- phoenix/server/api/dataloaders/experiment_dataset_splits.py +43 -0
- phoenix/server/api/dataloaders/experiment_error_rates.py +21 -28
- phoenix/server/api/dataloaders/experiment_repeated_run_group_annotation_summaries.py +77 -0
- phoenix/server/api/dataloaders/experiment_repeated_run_groups.py +57 -0
- phoenix/server/api/dataloaders/experiment_runs_by_experiment_and_example.py +44 -0
- phoenix/server/api/dataloaders/last_used_times_by_generative_model_id.py +35 -0
- phoenix/server/api/dataloaders/latency_ms_quantile.py +40 -8
- phoenix/server/api/dataloaders/record_counts.py +37 -10
- phoenix/server/api/dataloaders/session_annotations_by_session.py +29 -0
- phoenix/server/api/dataloaders/span_cost_by_span.py +24 -0
- phoenix/server/api/dataloaders/span_cost_detail_summary_entries_by_generative_model.py +56 -0
- phoenix/server/api/dataloaders/span_cost_detail_summary_entries_by_project_session.py +57 -0
- phoenix/server/api/dataloaders/span_cost_detail_summary_entries_by_span.py +43 -0
- phoenix/server/api/dataloaders/span_cost_detail_summary_entries_by_trace.py +56 -0
- phoenix/server/api/dataloaders/span_cost_details_by_span_cost.py +27 -0
- phoenix/server/api/dataloaders/span_cost_summary_by_experiment.py +57 -0
- phoenix/server/api/dataloaders/span_cost_summary_by_experiment_repeated_run_group.py +64 -0
- phoenix/server/api/dataloaders/span_cost_summary_by_experiment_run.py +58 -0
- phoenix/server/api/dataloaders/span_cost_summary_by_generative_model.py +55 -0
- phoenix/server/api/dataloaders/span_cost_summary_by_project.py +152 -0
- phoenix/server/api/dataloaders/span_cost_summary_by_project_session.py +56 -0
- phoenix/server/api/dataloaders/span_cost_summary_by_trace.py +55 -0
- phoenix/server/api/dataloaders/span_costs.py +29 -0
- phoenix/server/api/dataloaders/table_fields.py +2 -2
- phoenix/server/api/dataloaders/token_prices_by_model.py +30 -0
- phoenix/server/api/dataloaders/trace_annotations_by_trace.py +27 -0
- phoenix/server/api/dataloaders/types.py +29 -0
- phoenix/server/api/exceptions.py +11 -1
- phoenix/server/api/helpers/dataset_helpers.py +5 -1
- phoenix/server/api/helpers/playground_clients.py +1243 -292
- phoenix/server/api/helpers/playground_registry.py +2 -2
- phoenix/server/api/helpers/playground_spans.py +8 -4
- phoenix/server/api/helpers/playground_users.py +26 -0
- phoenix/server/api/helpers/prompts/conversions/aws.py +83 -0
- phoenix/server/api/helpers/prompts/conversions/google.py +103 -0
- phoenix/server/api/helpers/prompts/models.py +205 -22
- phoenix/server/api/input_types/{SpanAnnotationFilter.py → AnnotationFilter.py} +22 -14
- phoenix/server/api/input_types/ChatCompletionInput.py +6 -2
- phoenix/server/api/input_types/CreateProjectInput.py +27 -0
- phoenix/server/api/input_types/CreateProjectSessionAnnotationInput.py +37 -0
- phoenix/server/api/input_types/DatasetFilter.py +17 -0
- phoenix/server/api/input_types/ExperimentRunSort.py +237 -0
- phoenix/server/api/input_types/GenerativeCredentialInput.py +9 -0
- phoenix/server/api/input_types/GenerativeModelInput.py +5 -0
- phoenix/server/api/input_types/ProjectSessionSort.py +161 -1
- phoenix/server/api/input_types/PromptFilter.py +14 -0
- phoenix/server/api/input_types/PromptVersionInput.py +52 -1
- phoenix/server/api/input_types/SpanSort.py +44 -7
- phoenix/server/api/input_types/TimeBinConfig.py +23 -0
- phoenix/server/api/input_types/UpdateAnnotationInput.py +34 -0
- phoenix/server/api/input_types/UserRoleInput.py +1 -0
- phoenix/server/api/mutations/__init__.py +10 -0
- phoenix/server/api/mutations/annotation_config_mutations.py +8 -8
- phoenix/server/api/mutations/api_key_mutations.py +19 -23
- phoenix/server/api/mutations/chat_mutations.py +154 -47
- phoenix/server/api/mutations/dataset_label_mutations.py +243 -0
- phoenix/server/api/mutations/dataset_mutations.py +21 -16
- phoenix/server/api/mutations/dataset_split_mutations.py +351 -0
- phoenix/server/api/mutations/experiment_mutations.py +2 -2
- phoenix/server/api/mutations/export_events_mutations.py +3 -3
- phoenix/server/api/mutations/model_mutations.py +210 -0
- phoenix/server/api/mutations/project_mutations.py +49 -10
- phoenix/server/api/mutations/project_session_annotations_mutations.py +158 -0
- phoenix/server/api/mutations/project_trace_retention_policy_mutations.py +8 -4
- phoenix/server/api/mutations/prompt_label_mutations.py +74 -65
- phoenix/server/api/mutations/prompt_mutations.py +65 -129
- phoenix/server/api/mutations/prompt_version_tag_mutations.py +11 -8
- phoenix/server/api/mutations/span_annotations_mutations.py +15 -10
- phoenix/server/api/mutations/trace_annotations_mutations.py +14 -10
- phoenix/server/api/mutations/trace_mutations.py +47 -3
- phoenix/server/api/mutations/user_mutations.py +66 -41
- phoenix/server/api/queries.py +768 -293
- phoenix/server/api/routers/__init__.py +2 -2
- phoenix/server/api/routers/auth.py +154 -88
- phoenix/server/api/routers/ldap.py +229 -0
- phoenix/server/api/routers/oauth2.py +369 -106
- phoenix/server/api/routers/v1/__init__.py +24 -4
- phoenix/server/api/routers/v1/annotation_configs.py +23 -31
- phoenix/server/api/routers/v1/annotations.py +481 -17
- phoenix/server/api/routers/v1/datasets.py +395 -81
- phoenix/server/api/routers/v1/documents.py +142 -0
- phoenix/server/api/routers/v1/evaluations.py +24 -31
- phoenix/server/api/routers/v1/experiment_evaluations.py +19 -8
- phoenix/server/api/routers/v1/experiment_runs.py +337 -59
- phoenix/server/api/routers/v1/experiments.py +479 -48
- phoenix/server/api/routers/v1/models.py +7 -0
- phoenix/server/api/routers/v1/projects.py +18 -49
- phoenix/server/api/routers/v1/prompts.py +54 -40
- phoenix/server/api/routers/v1/sessions.py +108 -0
- phoenix/server/api/routers/v1/spans.py +1091 -81
- phoenix/server/api/routers/v1/traces.py +132 -78
- phoenix/server/api/routers/v1/users.py +389 -0
- phoenix/server/api/routers/v1/utils.py +3 -7
- phoenix/server/api/subscriptions.py +305 -88
- phoenix/server/api/types/Annotation.py +90 -23
- phoenix/server/api/types/ApiKey.py +13 -17
- phoenix/server/api/types/AuthMethod.py +1 -0
- phoenix/server/api/types/ChatCompletionSubscriptionPayload.py +1 -0
- phoenix/server/api/types/CostBreakdown.py +12 -0
- phoenix/server/api/types/Dataset.py +226 -72
- phoenix/server/api/types/DatasetExample.py +88 -18
- phoenix/server/api/types/DatasetExperimentAnnotationSummary.py +10 -0
- phoenix/server/api/types/DatasetLabel.py +57 -0
- phoenix/server/api/types/DatasetSplit.py +98 -0
- phoenix/server/api/types/DatasetVersion.py +49 -4
- phoenix/server/api/types/DocumentAnnotation.py +212 -0
- phoenix/server/api/types/Experiment.py +264 -59
- phoenix/server/api/types/ExperimentComparison.py +5 -10
- phoenix/server/api/types/ExperimentRepeatedRunGroup.py +155 -0
- phoenix/server/api/types/ExperimentRepeatedRunGroupAnnotationSummary.py +9 -0
- phoenix/server/api/types/ExperimentRun.py +169 -65
- phoenix/server/api/types/ExperimentRunAnnotation.py +158 -39
- phoenix/server/api/types/GenerativeModel.py +245 -3
- phoenix/server/api/types/GenerativeProvider.py +70 -11
- phoenix/server/api/types/{Model.py → InferenceModel.py} +1 -1
- phoenix/server/api/types/ModelInterface.py +16 -0
- phoenix/server/api/types/PlaygroundModel.py +20 -0
- phoenix/server/api/types/Project.py +1278 -216
- phoenix/server/api/types/ProjectSession.py +188 -28
- phoenix/server/api/types/ProjectSessionAnnotation.py +187 -0
- phoenix/server/api/types/ProjectTraceRetentionPolicy.py +1 -1
- phoenix/server/api/types/Prompt.py +119 -39
- phoenix/server/api/types/PromptLabel.py +42 -25
- phoenix/server/api/types/PromptVersion.py +11 -8
- phoenix/server/api/types/PromptVersionTag.py +65 -25
- phoenix/server/api/types/ServerStatus.py +6 -0
- phoenix/server/api/types/Span.py +167 -123
- phoenix/server/api/types/SpanAnnotation.py +189 -42
- phoenix/server/api/types/SpanCostDetailSummaryEntry.py +10 -0
- phoenix/server/api/types/SpanCostSummary.py +10 -0
- phoenix/server/api/types/SystemApiKey.py +65 -1
- phoenix/server/api/types/TokenPrice.py +16 -0
- phoenix/server/api/types/TokenUsage.py +3 -3
- phoenix/server/api/types/Trace.py +223 -51
- phoenix/server/api/types/TraceAnnotation.py +149 -50
- phoenix/server/api/types/User.py +137 -32
- phoenix/server/api/types/UserApiKey.py +73 -26
- phoenix/server/api/types/node.py +10 -0
- phoenix/server/api/types/pagination.py +11 -2
- phoenix/server/app.py +290 -45
- phoenix/server/authorization.py +38 -3
- phoenix/server/bearer_auth.py +34 -24
- phoenix/server/cost_tracking/cost_details_calculator.py +196 -0
- phoenix/server/cost_tracking/cost_model_lookup.py +179 -0
- phoenix/server/cost_tracking/helpers.py +68 -0
- phoenix/server/cost_tracking/model_cost_manifest.json +3657 -830
- phoenix/server/cost_tracking/regex_specificity.py +397 -0
- phoenix/server/cost_tracking/token_cost_calculator.py +57 -0
- phoenix/server/daemons/__init__.py +0 -0
- phoenix/server/daemons/db_disk_usage_monitor.py +214 -0
- phoenix/server/daemons/generative_model_store.py +103 -0
- phoenix/server/daemons/span_cost_calculator.py +99 -0
- phoenix/server/dml_event.py +17 -0
- phoenix/server/dml_event_handler.py +5 -0
- phoenix/server/email/sender.py +56 -3
- phoenix/server/email/templates/db_disk_usage_notification.html +19 -0
- phoenix/server/email/types.py +11 -0
- phoenix/server/experiments/__init__.py +0 -0
- phoenix/server/experiments/utils.py +14 -0
- phoenix/server/grpc_server.py +11 -11
- phoenix/server/jwt_store.py +17 -15
- phoenix/server/ldap.py +1449 -0
- phoenix/server/main.py +26 -10
- phoenix/server/oauth2.py +330 -12
- phoenix/server/prometheus.py +66 -6
- phoenix/server/rate_limiters.py +4 -9
- phoenix/server/retention.py +33 -20
- phoenix/server/session_filters.py +49 -0
- phoenix/server/static/.vite/manifest.json +55 -51
- phoenix/server/static/assets/components-BreFUQQa.js +6702 -0
- phoenix/server/static/assets/{index-E0M82BdE.js → index-CTQoemZv.js} +140 -56
- phoenix/server/static/assets/pages-DBE5iYM3.js +9524 -0
- phoenix/server/static/assets/vendor-BGzfc4EU.css +1 -0
- phoenix/server/static/assets/vendor-DCE4v-Ot.js +920 -0
- phoenix/server/static/assets/vendor-codemirror-D5f205eT.js +25 -0
- phoenix/server/static/assets/vendor-recharts-V9cwpXsm.js +37 -0
- phoenix/server/static/assets/vendor-shiki-Do--csgv.js +5 -0
- phoenix/server/static/assets/vendor-three-CmB8bl_y.js +3840 -0
- phoenix/server/templates/index.html +40 -6
- phoenix/server/thread_server.py +1 -2
- phoenix/server/types.py +14 -4
- phoenix/server/utils.py +74 -0
- phoenix/session/client.py +56 -3
- phoenix/session/data_extractor.py +5 -0
- phoenix/session/evaluation.py +14 -5
- phoenix/session/session.py +45 -9
- phoenix/settings.py +5 -0
- phoenix/trace/attributes.py +80 -13
- phoenix/trace/dsl/helpers.py +90 -1
- phoenix/trace/dsl/query.py +8 -6
- phoenix/trace/projects.py +5 -0
- phoenix/utilities/template_formatters.py +1 -1
- phoenix/version.py +1 -1
- arize_phoenix-10.0.4.dist-info/RECORD +0 -405
- phoenix/server/api/types/Evaluation.py +0 -39
- phoenix/server/cost_tracking/cost_lookup.py +0 -255
- phoenix/server/static/assets/components-DULKeDfL.js +0 -4365
- phoenix/server/static/assets/pages-Cl0A-0U2.js +0 -7430
- phoenix/server/static/assets/vendor-WIZid84E.css +0 -1
- phoenix/server/static/assets/vendor-arizeai-Dy-0mSNw.js +0 -649
- phoenix/server/static/assets/vendor-codemirror-DBtifKNr.js +0 -33
- phoenix/server/static/assets/vendor-oB4u9zuV.js +0 -905
- phoenix/server/static/assets/vendor-recharts-D-T4KPz2.js +0 -59
- phoenix/server/static/assets/vendor-shiki-BMn4O_9F.js +0 -5
- phoenix/server/static/assets/vendor-three-C5WAXd5r.js +0 -2998
- phoenix/utilities/deprecation.py +0 -31
- {arize_phoenix-10.0.4.dist-info → arize_phoenix-12.28.1.dist-info}/entry_points.txt +0 -0
- {arize_phoenix-10.0.4.dist-info → arize_phoenix-12.28.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -55,15 +55,40 @@
|
|
|
55
55
|
<meta property="og:description" content="AI Observability & Evaluation" />
|
|
56
56
|
<meta property="og:image" content="https://raw.githubusercontent.com/Arize-ai/phoenix-assets/main/images/socal/social-preview-horizontal.jpg" />
|
|
57
57
|
<meta name="theme-color" content="#ffffff" />
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
58
|
+
{% if allow_external_resources %}
|
|
59
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
60
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
61
|
+
<link href="https://fonts.googleapis.com/css2?family=Geist:wght@100..900&family=Geist+Mono:wght@100..900&display=swap" rel="stylesheet">
|
|
62
|
+
{% endif %}
|
|
62
63
|
{% if not is_development -%}
|
|
63
64
|
{% set _ = collect_assets('index.tsx') -%}
|
|
64
65
|
{{- render_css() -}}
|
|
65
66
|
{%- endif -%}
|
|
66
67
|
<script src="{{basename}}/modernizr.js"></script>
|
|
68
|
+
{% if fullstory_org -%}
|
|
69
|
+
<script>
|
|
70
|
+
window['_fs_host'] = 'fullstory.com';
|
|
71
|
+
window['_fs_script'] = 'edge.fullstory.com/s/fs.js';
|
|
72
|
+
window['_fs_org'] = '{{ fullstory_org }}';
|
|
73
|
+
window['_fs_namespace'] = 'FS';
|
|
74
|
+
!function(m,n,e,t,l,o,g,y){var s,f,a=function(h){
|
|
75
|
+
return!(h in m)||(m.console&&m.console.log&&m.console.log('FullStory namespace conflict. Please set window["_fs_namespace"].'),!1)}(e)
|
|
76
|
+
;function p(b){var h,d=[];function j(){h&&(d.forEach((function(b){var d;try{d=b[h[0]]&&b[h[0]](h[1])}catch(h){return void(b[3]&&b[3](h))}
|
|
77
|
+
d&&d.then?d.then(b[2],b[3]):b[2]&&b[2](d)})),d.length=0)}function r(b){return function(d){h||(h=[b,d],j())}}return b(r(0),r(1)),{
|
|
78
|
+
then:function(b,h){return p((function(r,i){d.push([b,h,r,i]),j()}))}}}a&&(g=m[e]=function(){var b=function(b,d,j,r){function i(i,c){
|
|
79
|
+
h(b,d,j,i,c,r)}r=r||2;var c,u=/Async$/;return u.test(b)?(b=b.replace(u,""),"function"==typeof Promise?new Promise(i):p(i)):h(b,d,j,c,c,r)}
|
|
80
|
+
;function h(h,d,j,r,i,c){return b._api?b._api(h,d,j,r,i,c):(b.q&&b.q.push([h,d,j,r,i,c]),null)}return b.q=[],b}(),y=function(b){function h(h){
|
|
81
|
+
"function"==typeof h[4]&&h[4](new Error(b))}var d=g.q;if(d){for(var j=0;j<d.length;j++)h(d[j]);d.length=0,d.push=h}},function(){
|
|
82
|
+
(o=n.createElement(t)).async=!0,o.crossOrigin="anonymous",o.src="https://"+l,o.onerror=function(){y("Error loading "+l)}
|
|
83
|
+
;var b=n.getElementsByTagName(t)[0];b&&b.parentNode?b.parentNode.insertBefore(o,b):n.head.appendChild(o)}(),function(){function b(){}
|
|
84
|
+
function h(b,h,d){g(b,h,d,1)}function d(b,d,j){h("setProperties",{type:b,properties:d},j)}function j(b,h){d("user",b,h)}function r(b,h,d){j({
|
|
85
|
+
uid:b},d),h&&j(h,d)}g.identify=r,g.setUserVars=j,g.identifyAccount=b,g.clearUserCookie=b,g.setVars=d,g.event=function(b,d,j){h("trackEvent",{
|
|
86
|
+
name:b,properties:d},j)},g.anonymize=function(){r(!1)},g.shutdown=function(){h("shutdown")},g.restart=function(){h("restart")},
|
|
87
|
+
g.log=function(b,d){h("log",{level:b,msg:d})},g.consent=function(b){h("setIdentity",{consent:!arguments.length||b})}}(),s="fetch",
|
|
88
|
+
f="XMLHttpRequest",g._w={},g._w[f]=m[f],g._w[s]=m[s],m[s]&&(m[s]=function(){return g._w[s].apply(this,arguments)}),g._v="2.0.0")
|
|
89
|
+
}(window,document,window._fs_namespace,"script",window._fs_script);
|
|
90
|
+
</script>
|
|
91
|
+
{%- endif %}
|
|
67
92
|
</head>
|
|
68
93
|
<body>
|
|
69
94
|
<div id="root"></div>
|
|
@@ -85,11 +110,20 @@
|
|
|
85
110
|
authenticationEnabled: Boolean("{{authentication_enabled}}" == "True"),
|
|
86
111
|
oAuth2Idps: {{ oauth2_idps | tojson }},
|
|
87
112
|
basicAuthDisabled: Boolean("{{basic_auth_disabled}}" == "True"),
|
|
88
|
-
|
|
113
|
+
ldapEnabled: Boolean("{{ldap_enabled}}" == "True"),
|
|
114
|
+
ldapManualUserCreationEnabled: Boolean("{{ldap_manual_user_creation_enabled}}" == "True"),
|
|
115
|
+
managementUrl: {{management_url | tojson}},
|
|
116
|
+
supportEmail: {{support_email | tojson}},
|
|
117
|
+
hasDbThreshold: Boolean("{{has_db_threshold}}" == "True"),
|
|
118
|
+
allowExternalResources: Boolean("{{allow_external_resources}}" == "True"),
|
|
119
|
+
authErrorMessages: {{auth_error_messages | tojson}},
|
|
89
120
|
}),
|
|
90
121
|
writable: false
|
|
91
122
|
});
|
|
92
123
|
})()</script>
|
|
124
|
+
{% if scarf_sh_pixel_id -%}
|
|
125
|
+
<img referrerpolicy="no-referrer-when-downgrade" src="https://static.scarf.sh/a.png?x-pxid={{scarf_sh_pixel_id}}" />
|
|
126
|
+
{%- endif %}
|
|
93
127
|
{% if is_development -%}
|
|
94
128
|
<script type="module">
|
|
95
129
|
import RefreshRuntime from 'http://localhost:5173/@react-refresh'
|
|
@@ -103,5 +137,5 @@
|
|
|
103
137
|
{%- else -%}
|
|
104
138
|
{{- render_js() -}}
|
|
105
139
|
{%- endif -%}
|
|
106
|
-
|
|
140
|
+
</body>
|
|
107
141
|
</html>
|
phoenix/server/thread_server.py
CHANGED
|
@@ -6,7 +6,6 @@ from time import sleep, time
|
|
|
6
6
|
|
|
7
7
|
from fastapi import FastAPI
|
|
8
8
|
from uvicorn import Config, Server
|
|
9
|
-
from uvicorn.config import LoopSetupType
|
|
10
9
|
|
|
11
10
|
|
|
12
11
|
def _nest_asyncio_applied() -> bool:
|
|
@@ -31,7 +30,7 @@ class ThreadServer(Server):
|
|
|
31
30
|
) -> None:
|
|
32
31
|
# Must use asyncio loop if nest_asyncio is applied
|
|
33
32
|
# Otherwise the app crashes when the server is run in a thread
|
|
34
|
-
loop
|
|
33
|
+
loop = "asyncio" if _nest_asyncio_applied() else "auto"
|
|
35
34
|
config = Config(
|
|
36
35
|
app=app,
|
|
37
36
|
host=host,
|
phoenix/server/types.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import asyncio
|
|
3
4
|
from abc import ABC, abstractmethod
|
|
4
5
|
from asyncio import Task, create_task, sleep
|
|
5
6
|
from collections import defaultdict
|
|
@@ -13,8 +14,9 @@ from cachetools import LRUCache
|
|
|
13
14
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
14
15
|
|
|
15
16
|
from phoenix.auth import CanReadToken, ClaimSet, Token, TokenAttributes
|
|
16
|
-
from phoenix.db import
|
|
17
|
+
from phoenix.db import models
|
|
17
18
|
from phoenix.db.helpers import SupportedSQLDialect
|
|
19
|
+
from phoenix.db.models import UserRoleName
|
|
18
20
|
|
|
19
21
|
|
|
20
22
|
class CanSetLastUpdatedAt(Protocol):
|
|
@@ -28,14 +30,22 @@ class CanGetLastUpdatedAt(Protocol):
|
|
|
28
30
|
class DbSessionFactory:
|
|
29
31
|
def __init__(
|
|
30
32
|
self,
|
|
31
|
-
db: Callable[[], AbstractAsyncContextManager[AsyncSession]],
|
|
33
|
+
db: Callable[[Optional[asyncio.Lock]], AbstractAsyncContextManager[AsyncSession]],
|
|
32
34
|
dialect: str,
|
|
33
35
|
):
|
|
34
36
|
self._db = db
|
|
35
37
|
self.dialect = SupportedSQLDialect(dialect)
|
|
38
|
+
self.lock: Optional[asyncio.Lock] = None
|
|
39
|
+
self.should_not_insert_or_update = False
|
|
40
|
+
"""An informational flag that allows different tasks to coordinate whether insert
|
|
41
|
+
and update operations should be allowed. For example, this can be set to True when disk
|
|
42
|
+
usage is high to prevent further writes to the database, and set to False when disk
|
|
43
|
+
usage returns to normal. Note that this flag does not preclude the actual execution of any
|
|
44
|
+
insert or update operations.
|
|
45
|
+
"""
|
|
36
46
|
|
|
37
47
|
def __call__(self) -> AbstractAsyncContextManager[AsyncSession]:
|
|
38
|
-
return self._db()
|
|
48
|
+
return self._db(self.lock)
|
|
39
49
|
|
|
40
50
|
|
|
41
51
|
_AnyT = TypeVar("_AnyT")
|
|
@@ -145,7 +155,7 @@ class ApiKey(Token): ...
|
|
|
145
155
|
|
|
146
156
|
@dataclass(frozen=True)
|
|
147
157
|
class UserTokenAttributes(TokenAttributes):
|
|
148
|
-
user_role:
|
|
158
|
+
user_role: UserRoleName
|
|
149
159
|
|
|
150
160
|
|
|
151
161
|
@dataclass(frozen=True)
|
phoenix/server/utils.py
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
from typing import Any, Mapping
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def prepend_root_path(scope: Mapping[str, Any], path: str) -> str:
|
|
5
|
+
"""
|
|
6
|
+
Prepends the ASGI root path to the given path if one is configured.
|
|
7
|
+
|
|
8
|
+
Normalizes the input path by ensuring it has a leading slash and removing
|
|
9
|
+
trailing slashes. The root path is already normalized by get_root_path().
|
|
10
|
+
|
|
11
|
+
Args:
|
|
12
|
+
scope: The ASGI scope dictionary containing the root_path key
|
|
13
|
+
path: The path to prepend the root path to (e.g., "/login", "logout")
|
|
14
|
+
|
|
15
|
+
Returns:
|
|
16
|
+
The normalized path with root path prepended if configured,
|
|
17
|
+
otherwise just the normalized path. Never has a trailing slash
|
|
18
|
+
except when the result is just "/".
|
|
19
|
+
|
|
20
|
+
Examples:
|
|
21
|
+
With root_path="/apps/phoenix":
|
|
22
|
+
- prepend_root_path(request.scope, "/login") -> "/apps/phoenix/login"
|
|
23
|
+
- prepend_root_path(request.scope, "login") -> "/apps/phoenix/login"
|
|
24
|
+
- prepend_root_path(request.scope, "/") -> "/apps/phoenix"
|
|
25
|
+
- prepend_root_path(request.scope, "") -> "/apps/phoenix"
|
|
26
|
+
- prepend_root_path(request.scope, "login/") -> "/apps/phoenix/login"
|
|
27
|
+
- prepend_root_path(request.scope, "/login/") -> "/apps/phoenix/login"
|
|
28
|
+
- prepend_root_path(request.scope, "abc/def/") -> "/apps/phoenix/abc/def"
|
|
29
|
+
|
|
30
|
+
With no root_path:
|
|
31
|
+
- prepend_root_path(request.scope, "/login") -> "/login"
|
|
32
|
+
- prepend_root_path(request.scope, "login") -> "/login"
|
|
33
|
+
- prepend_root_path(request.scope, "/") -> "/"
|
|
34
|
+
- prepend_root_path(request.scope, "") -> "/"
|
|
35
|
+
- prepend_root_path(request.scope, "login/") -> "/login"
|
|
36
|
+
- prepend_root_path(request.scope, "/login/") -> "/login"
|
|
37
|
+
- prepend_root_path(request.scope, "abc/def/") -> "/abc/def"
|
|
38
|
+
"""
|
|
39
|
+
path = path if path.startswith("/") else f"/{path}"
|
|
40
|
+
path = path.rstrip("/") or "/"
|
|
41
|
+
root_path = get_root_path(scope)
|
|
42
|
+
if path == "/":
|
|
43
|
+
return root_path or "/"
|
|
44
|
+
return f"{root_path}{path}"
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def get_root_path(scope: Mapping[str, Any]) -> str:
|
|
48
|
+
"""
|
|
49
|
+
Extracts and normalizes the root path from the ASGI scope.
|
|
50
|
+
|
|
51
|
+
The root path is typically set by reverse proxies or when the application
|
|
52
|
+
is mounted at a sub-path (e.g., "/apps/phoenix" when behind a proxy).
|
|
53
|
+
If present, ensures the path has a leading slash and removes trailing slashes.
|
|
54
|
+
|
|
55
|
+
Args:
|
|
56
|
+
scope: The ASGI scope dictionary containing the root_path key
|
|
57
|
+
|
|
58
|
+
Returns:
|
|
59
|
+
The normalized root path as a string (with leading slash, no trailing slash)
|
|
60
|
+
if configured, otherwise empty string.
|
|
61
|
+
|
|
62
|
+
Examples:
|
|
63
|
+
- Behind proxy at "/apps/phoenix": returns "/apps/phoenix"
|
|
64
|
+
- Missing leading slash "apps/phoenix": returns "/apps/phoenix"
|
|
65
|
+
- With trailing slash "/apps/phoenix/": returns "/apps/phoenix"
|
|
66
|
+
- Direct deployment: returns ""
|
|
67
|
+
- None in scope: returns ""
|
|
68
|
+
"""
|
|
69
|
+
root_path = str(scope.get("root_path") or "")
|
|
70
|
+
if not root_path:
|
|
71
|
+
return ""
|
|
72
|
+
if not root_path.startswith("/"):
|
|
73
|
+
root_path = f"/{root_path}"
|
|
74
|
+
return root_path.rstrip("/")
|
phoenix/session/client.py
CHANGED
|
@@ -19,7 +19,7 @@ from opentelemetry.proto.common.v1.common_pb2 import AnyValue, KeyValue
|
|
|
19
19
|
from opentelemetry.proto.resource.v1.resource_pb2 import Resource
|
|
20
20
|
from opentelemetry.proto.trace.v1.trace_pb2 import ResourceSpans, ScopeSpans
|
|
21
21
|
from pyarrow import ArrowInvalid, Table
|
|
22
|
-
from typing_extensions import TypeAlias, assert_never
|
|
22
|
+
from typing_extensions import TypeAlias, assert_never, deprecated
|
|
23
23
|
|
|
24
24
|
from phoenix.config import (
|
|
25
25
|
get_env_collector_endpoint,
|
|
@@ -68,8 +68,7 @@ class Client(TraceDataExtractor):
|
|
|
68
68
|
"""
|
|
69
69
|
if kwargs.pop("use_active_session_if_available", None) is not None:
|
|
70
70
|
print(
|
|
71
|
-
"`use_active_session_if_available` is deprecated "
|
|
72
|
-
"and will be removed in the future."
|
|
71
|
+
"`use_active_session_if_available` is deprecated and will be removed in the future."
|
|
73
72
|
)
|
|
74
73
|
if kwargs:
|
|
75
74
|
raise TypeError(f"Unexpected keyword arguments: {', '.join(kwargs)}")
|
|
@@ -111,6 +110,7 @@ class Client(TraceDataExtractor):
|
|
|
111
110
|
return session.url
|
|
112
111
|
return str(self._client.base_url)
|
|
113
112
|
|
|
113
|
+
@deprecated("Migrate to using client.spans.get_spans_dataframe via arize-phoenix-client")
|
|
114
114
|
def query_spans(
|
|
115
115
|
self,
|
|
116
116
|
*queries: SpanQuery,
|
|
@@ -125,6 +125,11 @@ class Client(TraceDataExtractor):
|
|
|
125
125
|
orphan_span_as_root_span: bool = True,
|
|
126
126
|
) -> Optional[Union[pd.DataFrame, list[pd.DataFrame]]]:
|
|
127
127
|
"""
|
|
128
|
+
.. deprecated::
|
|
129
|
+
This method is deprecated. Use ``client.spans.get_spans_dataframe()`` via
|
|
130
|
+
arize-phoenix-client instead.
|
|
131
|
+
See https://arize-phoenix.readthedocs.io/projects/client/en/latest/
|
|
132
|
+
|
|
128
133
|
Queries spans from the Phoenix server or active session based on specified criteria.
|
|
129
134
|
|
|
130
135
|
Args:
|
|
@@ -223,6 +228,7 @@ class Client(TraceDataExtractor):
|
|
|
223
228
|
return None if df.shape == (0, 0) else df
|
|
224
229
|
return results
|
|
225
230
|
|
|
231
|
+
@deprecated("Migrate to using client.spans.get_span_annotations via arize-phoenix-client")
|
|
226
232
|
def get_evaluations(
|
|
227
233
|
self,
|
|
228
234
|
project_name: Optional[str] = None,
|
|
@@ -230,6 +236,11 @@ class Client(TraceDataExtractor):
|
|
|
230
236
|
timeout: Optional[int] = DEFAULT_TIMEOUT_IN_SECONDS,
|
|
231
237
|
) -> list[Evaluations]:
|
|
232
238
|
"""
|
|
239
|
+
.. deprecated::
|
|
240
|
+
This method is deprecated. Use ``client.spans.get_span_annotations()`` via
|
|
241
|
+
arize-phoenix-client instead.
|
|
242
|
+
See https://arize-phoenix.readthedocs.io/projects/client/en/latest/
|
|
243
|
+
|
|
233
244
|
Retrieves evaluations for a given project from the Phoenix server or active session.
|
|
234
245
|
|
|
235
246
|
Args:
|
|
@@ -277,6 +288,7 @@ class Client(TraceDataExtractor):
|
|
|
277
288
|
f"with `import phoenix as px; px.launch_app()`"
|
|
278
289
|
)
|
|
279
290
|
|
|
291
|
+
@deprecated("Migrate to using client.spans.log_span_annotations via arize-phoenix-client")
|
|
280
292
|
def log_evaluations(
|
|
281
293
|
self,
|
|
282
294
|
*evals: Evaluations,
|
|
@@ -284,6 +296,11 @@ class Client(TraceDataExtractor):
|
|
|
284
296
|
**kwargs: Any,
|
|
285
297
|
) -> None:
|
|
286
298
|
"""
|
|
299
|
+
.. deprecated::
|
|
300
|
+
This method is deprecated. Use ``client.spans.log_span_annotations()`` via
|
|
301
|
+
arize-phoenix-client instead.
|
|
302
|
+
See https://arize-phoenix.readthedocs.io/projects/client/en/latest/
|
|
303
|
+
|
|
287
304
|
Logs evaluation data to the Phoenix server.
|
|
288
305
|
|
|
289
306
|
Args:
|
|
@@ -310,8 +327,14 @@ class Client(TraceDataExtractor):
|
|
|
310
327
|
timeout=timeout,
|
|
311
328
|
).raise_for_status()
|
|
312
329
|
|
|
330
|
+
@deprecated("Migrate to using client.spans.log_spans via arize-phoenix-client")
|
|
313
331
|
def log_traces(self, trace_dataset: TraceDataset, project_name: Optional[str] = None) -> None:
|
|
314
332
|
"""
|
|
333
|
+
.. deprecated::
|
|
334
|
+
This method is deprecated. Use ``client.spans.log_spans()`` via
|
|
335
|
+
arize-phoenix-client instead.
|
|
336
|
+
See https://arize-phoenix.readthedocs.io/projects/client/en/latest/
|
|
337
|
+
|
|
315
338
|
Logs traces from a TraceDataset to the Phoenix server.
|
|
316
339
|
|
|
317
340
|
Args:
|
|
@@ -380,6 +403,7 @@ class Client(TraceDataExtractor):
|
|
|
380
403
|
dataset = records[0]
|
|
381
404
|
return str(dataset["id"])
|
|
382
405
|
|
|
406
|
+
@deprecated("Migrate to using client.datasets.get_dataset via arize-phoenix-client")
|
|
383
407
|
def get_dataset(
|
|
384
408
|
self,
|
|
385
409
|
*,
|
|
@@ -388,6 +412,11 @@ class Client(TraceDataExtractor):
|
|
|
388
412
|
version_id: Optional[str] = None,
|
|
389
413
|
) -> Dataset:
|
|
390
414
|
"""
|
|
415
|
+
.. deprecated::
|
|
416
|
+
This method is deprecated. Use ``client.datasets.get_dataset()`` via
|
|
417
|
+
arize-phoenix-client instead.
|
|
418
|
+
See https://arize-phoenix.readthedocs.io/projects/client/en/latest/
|
|
419
|
+
|
|
391
420
|
Gets the dataset for a specific version, or gets the latest version of
|
|
392
421
|
the dataset if no version is specified.
|
|
393
422
|
|
|
@@ -434,6 +463,7 @@ class Client(TraceDataExtractor):
|
|
|
434
463
|
examples=examples,
|
|
435
464
|
)
|
|
436
465
|
|
|
466
|
+
@deprecated("Migrate to using client.datasets.get_dataset_versions via arize-phoenix-client")
|
|
437
467
|
def get_dataset_versions(
|
|
438
468
|
self,
|
|
439
469
|
dataset_id: str,
|
|
@@ -441,6 +471,11 @@ class Client(TraceDataExtractor):
|
|
|
441
471
|
limit: Optional[int] = 100,
|
|
442
472
|
) -> pd.DataFrame:
|
|
443
473
|
"""
|
|
474
|
+
.. deprecated::
|
|
475
|
+
This method is deprecated. Use ``client.datasets.get_dataset_versions()`` via
|
|
476
|
+
arize-phoenix-client instead.
|
|
477
|
+
See https://arize-phoenix.readthedocs.io/projects/client/en/latest/
|
|
478
|
+
|
|
444
479
|
Get dataset versions as pandas DataFrame.
|
|
445
480
|
|
|
446
481
|
Args:
|
|
@@ -460,6 +495,7 @@ class Client(TraceDataExtractor):
|
|
|
460
495
|
df["created_at"] = df["created_at"].apply(datetime.fromisoformat)
|
|
461
496
|
return df
|
|
462
497
|
|
|
498
|
+
@deprecated("Migrate to using client.datasets.create_dataset via arize-phoenix-client")
|
|
463
499
|
def upload_dataset(
|
|
464
500
|
self,
|
|
465
501
|
*,
|
|
@@ -475,6 +511,11 @@ class Client(TraceDataExtractor):
|
|
|
475
511
|
dataset_description: Optional[str] = None,
|
|
476
512
|
) -> Dataset:
|
|
477
513
|
"""
|
|
514
|
+
.. deprecated::
|
|
515
|
+
This method is deprecated. Use ``client.datasets.create_dataset()`` via
|
|
516
|
+
arize-phoenix-client instead.
|
|
517
|
+
See https://arize-phoenix.readthedocs.io/projects/client/en/latest/
|
|
518
|
+
|
|
478
519
|
Upload examples as dataset to the Phoenix server. If `dataframe` or
|
|
479
520
|
`csv_file_path` are provided, must also provide `input_keys` (and
|
|
480
521
|
optionally with `output_keys` or `metadata_keys` or both), which is a
|
|
@@ -536,6 +577,7 @@ class Client(TraceDataExtractor):
|
|
|
536
577
|
dataset_description=dataset_description,
|
|
537
578
|
)
|
|
538
579
|
|
|
580
|
+
@deprecated("Migrate to using client.datasets.add_examples_to_dataset via arize-phoenix-client")
|
|
539
581
|
def append_to_dataset(
|
|
540
582
|
self,
|
|
541
583
|
*,
|
|
@@ -550,6 +592,11 @@ class Client(TraceDataExtractor):
|
|
|
550
592
|
metadata: Iterable[Mapping[str, Any]] = (),
|
|
551
593
|
) -> Dataset:
|
|
552
594
|
"""
|
|
595
|
+
.. deprecated::
|
|
596
|
+
This method is deprecated. Use ``client.datasets.add_examples_to_dataset()`` via
|
|
597
|
+
arize-phoenix-client instead.
|
|
598
|
+
See https://arize-phoenix.readthedocs.io/projects/client/en/latest/
|
|
599
|
+
|
|
553
600
|
Append examples to dataset on the Phoenix server. If `dataframe` or
|
|
554
601
|
`csv_file_path` are provided, must also provide `input_keys` (and
|
|
555
602
|
optionally with `output_keys` or `metadata_keys` or both), which is a
|
|
@@ -610,8 +657,14 @@ class Client(TraceDataExtractor):
|
|
|
610
657
|
action="append",
|
|
611
658
|
)
|
|
612
659
|
|
|
660
|
+
@deprecated("Migrate to using client.experiments.get_experiment via arize-phoenix-client")
|
|
613
661
|
def get_experiment(self, *, experiment_id: str) -> Experiment:
|
|
614
662
|
"""
|
|
663
|
+
.. deprecated::
|
|
664
|
+
This method is deprecated. Use ``client.experiments.get_experiment()`` via
|
|
665
|
+
arize-phoenix-client instead.
|
|
666
|
+
See https://arize-phoenix.readthedocs.io/projects/client/en/latest/
|
|
667
|
+
|
|
615
668
|
Get an experiment by ID.
|
|
616
669
|
|
|
617
670
|
Retrieve an Experiment object by ID, enables running `evaluate_experiment` after finishing
|
|
@@ -3,6 +3,7 @@ from datetime import datetime
|
|
|
3
3
|
from typing import Optional, Union, cast
|
|
4
4
|
|
|
5
5
|
import pandas as pd
|
|
6
|
+
from typing_extensions import deprecated
|
|
6
7
|
|
|
7
8
|
from phoenix.trace import Evaluations
|
|
8
9
|
from phoenix.trace.dsl import SpanQuery
|
|
@@ -18,6 +19,7 @@ class TraceDataExtractor(ABC):
|
|
|
18
19
|
`Session` so that they both implement the same methods.
|
|
19
20
|
"""
|
|
20
21
|
|
|
22
|
+
@deprecated("Migrate to client.spans.get_spans_dataframe() from arize-phoenix-client")
|
|
21
23
|
@abstractmethod
|
|
22
24
|
def query_spans(
|
|
23
25
|
self,
|
|
@@ -30,6 +32,7 @@ class TraceDataExtractor(ABC):
|
|
|
30
32
|
timeout: Optional[int] = DEFAULT_TIMEOUT_IN_SECONDS,
|
|
31
33
|
) -> Optional[Union[pd.DataFrame, list[pd.DataFrame]]]: ...
|
|
32
34
|
|
|
35
|
+
@deprecated("Migrate to client.spans.get_spans_dataframe() from arize-phoenix-client")
|
|
33
36
|
def get_spans_dataframe(
|
|
34
37
|
self,
|
|
35
38
|
filter_condition: Optional[str] = None,
|
|
@@ -55,11 +58,13 @@ class TraceDataExtractor(ABC):
|
|
|
55
58
|
)
|
|
56
59
|
|
|
57
60
|
@abstractmethod
|
|
61
|
+
@deprecated("Migrate to client.spans.get_span_annotations() from arize-phoenix-client")
|
|
58
62
|
def get_evaluations(
|
|
59
63
|
self,
|
|
60
64
|
project_name: Optional[str] = None,
|
|
61
65
|
) -> list[Evaluations]: ...
|
|
62
66
|
|
|
67
|
+
@deprecated("Migrate to client.spans.get_spans() from arize-phoenix-client")
|
|
63
68
|
def get_trace_dataset(
|
|
64
69
|
self,
|
|
65
70
|
project_name: Optional[str] = None,
|
phoenix/session/evaluation.py
CHANGED
|
@@ -19,17 +19,23 @@ from typing import (
|
|
|
19
19
|
|
|
20
20
|
import pandas as pd
|
|
21
21
|
from google.protobuf.wrappers_pb2 import DoubleValue, StringValue
|
|
22
|
+
from typing_extensions import deprecated
|
|
22
23
|
|
|
23
24
|
import phoenix.trace.v1 as pb
|
|
24
25
|
from phoenix.config import get_env_collector_endpoint, get_env_host, get_env_port
|
|
25
26
|
from phoenix.session.client import Client
|
|
26
|
-
from phoenix.trace.dsl.helpers import
|
|
27
|
+
from phoenix.trace.dsl.helpers import (
|
|
28
|
+
get_called_tools,
|
|
29
|
+
get_qa_with_reference,
|
|
30
|
+
get_retrieved_documents,
|
|
31
|
+
)
|
|
27
32
|
from phoenix.trace.exporter import HttpExporter
|
|
28
33
|
from phoenix.trace.span_evaluations import Evaluations
|
|
29
34
|
|
|
30
35
|
__all__ = [
|
|
31
36
|
"get_retrieved_documents",
|
|
32
37
|
"get_qa_with_reference",
|
|
38
|
+
"get_called_tools",
|
|
33
39
|
"add_evaluations",
|
|
34
40
|
]
|
|
35
41
|
|
|
@@ -131,16 +137,19 @@ def _extract_result(row: "pd.Series[Any]") -> Optional[pb.Evaluation.Result]:
|
|
|
131
137
|
)
|
|
132
138
|
|
|
133
139
|
|
|
140
|
+
@deprecated("Migrate to using client.spans.log_span_annotations via arize-phoenix-client")
|
|
134
141
|
def log_evaluations(
|
|
135
142
|
*evals: Evaluations,
|
|
136
143
|
endpoint: Optional[str] = None,
|
|
137
144
|
host: Optional[str] = None,
|
|
138
145
|
port: Optional[int] = None,
|
|
139
146
|
) -> None:
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
147
|
+
"""
|
|
148
|
+
.. deprecated::
|
|
149
|
+
This function is deprecated. Use ``client.spans.log_span_annotations()`` via
|
|
150
|
+
arize-phoenix-client instead.
|
|
151
|
+
See https://arize-phoenix.readthedocs.io/projects/client/en/latest/
|
|
152
|
+
"""
|
|
144
153
|
host = host or get_env_host()
|
|
145
154
|
if host == "0.0.0.0":
|
|
146
155
|
host = "127.0.0.1"
|
phoenix/session/session.py
CHANGED
|
@@ -12,10 +12,11 @@ from importlib.util import find_spec
|
|
|
12
12
|
from itertools import chain
|
|
13
13
|
from pathlib import Path
|
|
14
14
|
from tempfile import TemporaryDirectory
|
|
15
|
-
from typing import TYPE_CHECKING, Any, NamedTuple, Optional, Union
|
|
15
|
+
from typing import TYPE_CHECKING, Any, Awaitable, Callable, NamedTuple, Optional, Union
|
|
16
16
|
from urllib.parse import urljoin
|
|
17
17
|
|
|
18
18
|
import pandas as pd
|
|
19
|
+
from typing_extensions import deprecated
|
|
19
20
|
|
|
20
21
|
from phoenix.config import (
|
|
21
22
|
ENV_NOTEBOOK_ENV,
|
|
@@ -25,6 +26,7 @@ from phoenix.config import (
|
|
|
25
26
|
ensure_working_dir_if_needed,
|
|
26
27
|
get_env_database_connection_str,
|
|
27
28
|
get_env_host,
|
|
29
|
+
get_env_host_root_path,
|
|
28
30
|
get_env_port,
|
|
29
31
|
get_exported_files,
|
|
30
32
|
get_working_dir,
|
|
@@ -117,6 +119,7 @@ class Session(TraceDataExtractor, ABC):
|
|
|
117
119
|
default_umap_parameters: Optional[Mapping[str, Any]] = None,
|
|
118
120
|
host: Optional[str] = None,
|
|
119
121
|
port: Optional[int] = None,
|
|
122
|
+
root_path: Optional[str] = None,
|
|
120
123
|
notebook_env: Optional[NotebookEnvironment] = None,
|
|
121
124
|
):
|
|
122
125
|
self._database_url = database_url
|
|
@@ -132,12 +135,21 @@ class Session(TraceDataExtractor, ABC):
|
|
|
132
135
|
self.export_path.mkdir(parents=True, exist_ok=True)
|
|
133
136
|
self.exported_data = ExportedData()
|
|
134
137
|
self.notebook_env = notebook_env or _get_notebook_environment()
|
|
135
|
-
self.root_path =
|
|
138
|
+
self.root_path = (
|
|
139
|
+
(get_env_host_root_path() or _get_root_path(self.notebook_env, self.port))
|
|
140
|
+
if root_path is None
|
|
141
|
+
else root_path
|
|
142
|
+
)
|
|
143
|
+
if self.root_path and self.root_path != "/":
|
|
144
|
+
if not self.root_path.startswith("/"):
|
|
145
|
+
self.root_path = f"/{self.root_path}"
|
|
146
|
+
self.root_path = self.root_path.rstrip("/")
|
|
136
147
|
host = "127.0.0.1" if self.host == "0.0.0.0" else self.host
|
|
137
148
|
self._client = Client(
|
|
138
149
|
endpoint=f"http://{host}:{self.port}", warn_if_server_not_running=False
|
|
139
150
|
)
|
|
140
151
|
|
|
152
|
+
@deprecated("Migrate to using client.spans.get_spans_dataframe via arize-phoenix-client")
|
|
141
153
|
def query_spans(
|
|
142
154
|
self,
|
|
143
155
|
*queries: SpanQuery,
|
|
@@ -151,6 +163,11 @@ class Session(TraceDataExtractor, ABC):
|
|
|
151
163
|
timeout: Optional[int] = DEFAULT_TIMEOUT_IN_SECONDS,
|
|
152
164
|
) -> Optional[Union[pd.DataFrame, list[pd.DataFrame]]]:
|
|
153
165
|
"""
|
|
166
|
+
.. deprecated::
|
|
167
|
+
This method is deprecated. Use ``client.spans.get_spans_dataframe()`` via
|
|
168
|
+
arize-phoenix-client instead.
|
|
169
|
+
See https://arize-phoenix.readthedocs.io/projects/client/en/latest/
|
|
170
|
+
|
|
154
171
|
Queries the spans in the project based on the provided parameters.
|
|
155
172
|
|
|
156
173
|
Parameters
|
|
@@ -192,11 +209,17 @@ class Session(TraceDataExtractor, ABC):
|
|
|
192
209
|
project_name=project_name,
|
|
193
210
|
)
|
|
194
211
|
|
|
212
|
+
@deprecated("Migrate to using client.spans.get_span_annotations via arize-phoenix-client")
|
|
195
213
|
def get_evaluations(
|
|
196
214
|
self,
|
|
197
215
|
project_name: Optional[str] = None,
|
|
198
216
|
) -> list[Evaluations]:
|
|
199
217
|
"""
|
|
218
|
+
.. deprecated::
|
|
219
|
+
This method is deprecated. Use ``client.spans.get_span_annotations()`` via
|
|
220
|
+
arize-phoenix-client instead.
|
|
221
|
+
See https://arize-phoenix.readthedocs.io/projects/client/en/latest/
|
|
222
|
+
|
|
200
223
|
Get the evaluations for a project.
|
|
201
224
|
|
|
202
225
|
Parameters
|
|
@@ -255,7 +278,7 @@ class Session(TraceDataExtractor, ABC):
|
|
|
255
278
|
@property
|
|
256
279
|
def url(self) -> str:
|
|
257
280
|
"""Returns the url for the phoenix app"""
|
|
258
|
-
return _get_url(self.host, self.port, self.notebook_env)
|
|
281
|
+
return _get_url(self.host, self.port, self.notebook_env, self.root_path)
|
|
259
282
|
|
|
260
283
|
@property
|
|
261
284
|
def database_url(self) -> str:
|
|
@@ -288,6 +311,7 @@ class ProcessSession(Session):
|
|
|
288
311
|
default_umap_parameters=default_umap_parameters,
|
|
289
312
|
host=host,
|
|
290
313
|
port=port,
|
|
314
|
+
root_path=root_path,
|
|
291
315
|
notebook_env=notebook_env,
|
|
292
316
|
)
|
|
293
317
|
primary_inferences.to_disc()
|
|
@@ -354,6 +378,7 @@ class ThreadSession(Session):
|
|
|
354
378
|
default_umap_parameters=default_umap_parameters,
|
|
355
379
|
host=host,
|
|
356
380
|
port=port,
|
|
381
|
+
root_path=root_path,
|
|
357
382
|
notebook_env=notebook_env,
|
|
358
383
|
)
|
|
359
384
|
self.model = create_model_from_inferences(
|
|
@@ -369,7 +394,10 @@ class ThreadSession(Session):
|
|
|
369
394
|
)
|
|
370
395
|
# Initialize an app service that keeps the server running
|
|
371
396
|
engine = create_engine_and_run_migrations(database_url)
|
|
372
|
-
|
|
397
|
+
shutdown_callbacks: list[Callable[[], None | Awaitable[None]]] = []
|
|
398
|
+
shutdown_callbacks.extend(instrument_engine_if_enabled(engine))
|
|
399
|
+
# Ensure engine is disposed on shutdown to properly close database connections
|
|
400
|
+
shutdown_callbacks.append(engine.dispose)
|
|
373
401
|
factory = DbSessionFactory(db=_db(engine), dialect=engine.dialect.name)
|
|
374
402
|
self.app = create_app(
|
|
375
403
|
db=factory,
|
|
@@ -384,7 +412,7 @@ class ThreadSession(Session):
|
|
|
384
412
|
if (trace_dataset and (initial_evaluations := trace_dataset.evaluations))
|
|
385
413
|
else None
|
|
386
414
|
),
|
|
387
|
-
shutdown_callbacks=
|
|
415
|
+
shutdown_callbacks=shutdown_callbacks,
|
|
388
416
|
)
|
|
389
417
|
self.server = ThreadServer(
|
|
390
418
|
app=self.app,
|
|
@@ -436,6 +464,7 @@ def launch_app(
|
|
|
436
464
|
default_umap_parameters: Optional[Mapping[str, Any]] = None,
|
|
437
465
|
host: Optional[str] = None,
|
|
438
466
|
port: Optional[int] = None,
|
|
467
|
+
root_path: Optional[str] = None,
|
|
439
468
|
run_in_thread: bool = True,
|
|
440
469
|
notebook_environment: Optional[Union[NotebookEnvironment, str]] = None,
|
|
441
470
|
use_temp_dir: bool = True,
|
|
@@ -461,6 +490,9 @@ def launch_app(
|
|
|
461
490
|
The port on which the server listens. When using traces this should not be
|
|
462
491
|
used and should instead set the environment variable `PHOENIX_PORT`.
|
|
463
492
|
Defaults to 6006.
|
|
493
|
+
root_path: str, optional
|
|
494
|
+
The root path to serve the application under (useful when behind a proxy).
|
|
495
|
+
Can also be set using environment variable `PHOENIX_HOST_ROOT_PATH`.
|
|
464
496
|
run_in_thread: bool, optional, default=True
|
|
465
497
|
Whether the server should run in a Thread or Process.
|
|
466
498
|
default_umap_parameters: dict[str, Union[int, float]], optional, default=None
|
|
@@ -573,6 +605,7 @@ def launch_app(
|
|
|
573
605
|
default_umap_parameters,
|
|
574
606
|
host=host,
|
|
575
607
|
port=port,
|
|
608
|
+
root_path=root_path,
|
|
576
609
|
notebook_env=nb_env,
|
|
577
610
|
)
|
|
578
611
|
# TODO: catch exceptions from thread
|
|
@@ -586,6 +619,7 @@ def launch_app(
|
|
|
586
619
|
default_umap_parameters,
|
|
587
620
|
host=host,
|
|
588
621
|
port=port,
|
|
622
|
+
root_path=root_path,
|
|
589
623
|
notebook_env=nb_env,
|
|
590
624
|
)
|
|
591
625
|
|
|
@@ -601,7 +635,7 @@ def launch_app(
|
|
|
601
635
|
print(f"🌍 To view the Phoenix app in your browser, visit {_session.url}")
|
|
602
636
|
if not use_temp_dir:
|
|
603
637
|
print(f"💽 Your data is being persisted to {get_printable_db_url(database_url)}")
|
|
604
|
-
print("📖 For more information on how to use Phoenix, check out https://
|
|
638
|
+
print("📖 For more information on how to use Phoenix, check out https://arize.com/docs/phoenix")
|
|
605
639
|
return _session
|
|
606
640
|
|
|
607
641
|
|
|
@@ -636,7 +670,7 @@ def close_app(delete_data: bool = False) -> None:
|
|
|
636
670
|
delete_all(prompt_before_delete=False)
|
|
637
671
|
|
|
638
672
|
|
|
639
|
-
def _get_url(host: str, port: int, notebook_env: NotebookEnvironment) -> str:
|
|
673
|
+
def _get_url(host: str, port: int, notebook_env: NotebookEnvironment, root_path: str) -> str:
|
|
640
674
|
"""Determines the IFrame URL based on whether this is in a Colab or in a local notebook"""
|
|
641
675
|
if notebook_env == NotebookEnvironment.COLAB:
|
|
642
676
|
from google.colab.output import eval_js
|
|
@@ -648,10 +682,12 @@ def _get_url(host: str, port: int, notebook_env: NotebookEnvironment) -> str:
|
|
|
648
682
|
if notebook_env == NotebookEnvironment.DATABRICKS:
|
|
649
683
|
context = _get_databricks_context()
|
|
650
684
|
return f"{_get_databricks_notebook_base_url(context)}/{port}/"
|
|
685
|
+
if not root_path.startswith("/"):
|
|
686
|
+
root_path = f"/{root_path}"
|
|
651
687
|
if host == "0.0.0.0" or host == "127.0.0.1":
|
|
652
688
|
# The app is running locally, so use localhost
|
|
653
|
-
return f"http://localhost:{port}
|
|
654
|
-
return f"http://{host}:{port}
|
|
689
|
+
return f"http://localhost:{port}{root_path}"
|
|
690
|
+
return f"http://{host}:{port}{root_path}"
|
|
655
691
|
|
|
656
692
|
|
|
657
693
|
def _is_colab() -> bool:
|