arize-phoenix 3.16.1__py3-none-any.whl → 7.7.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 (338) hide show
  1. arize_phoenix-7.7.0.dist-info/METADATA +261 -0
  2. arize_phoenix-7.7.0.dist-info/RECORD +345 -0
  3. {arize_phoenix-3.16.1.dist-info → arize_phoenix-7.7.0.dist-info}/WHEEL +1 -1
  4. arize_phoenix-7.7.0.dist-info/entry_points.txt +3 -0
  5. phoenix/__init__.py +86 -14
  6. phoenix/auth.py +309 -0
  7. phoenix/config.py +675 -45
  8. phoenix/core/model.py +32 -30
  9. phoenix/core/model_schema.py +102 -109
  10. phoenix/core/model_schema_adapter.py +48 -45
  11. phoenix/datetime_utils.py +24 -3
  12. phoenix/db/README.md +54 -0
  13. phoenix/db/__init__.py +4 -0
  14. phoenix/db/alembic.ini +85 -0
  15. phoenix/db/bulk_inserter.py +294 -0
  16. phoenix/db/engines.py +208 -0
  17. phoenix/db/enums.py +20 -0
  18. phoenix/db/facilitator.py +113 -0
  19. phoenix/db/helpers.py +159 -0
  20. phoenix/db/insertion/constants.py +2 -0
  21. phoenix/db/insertion/dataset.py +227 -0
  22. phoenix/db/insertion/document_annotation.py +171 -0
  23. phoenix/db/insertion/evaluation.py +191 -0
  24. phoenix/db/insertion/helpers.py +98 -0
  25. phoenix/db/insertion/span.py +193 -0
  26. phoenix/db/insertion/span_annotation.py +158 -0
  27. phoenix/db/insertion/trace_annotation.py +158 -0
  28. phoenix/db/insertion/types.py +256 -0
  29. phoenix/db/migrate.py +86 -0
  30. phoenix/db/migrations/data_migration_scripts/populate_project_sessions.py +199 -0
  31. phoenix/db/migrations/env.py +114 -0
  32. phoenix/db/migrations/script.py.mako +26 -0
  33. phoenix/db/migrations/versions/10460e46d750_datasets.py +317 -0
  34. phoenix/db/migrations/versions/3be8647b87d8_add_token_columns_to_spans_table.py +126 -0
  35. phoenix/db/migrations/versions/4ded9e43755f_create_project_sessions_table.py +66 -0
  36. phoenix/db/migrations/versions/cd164e83824f_users_and_tokens.py +157 -0
  37. phoenix/db/migrations/versions/cf03bd6bae1d_init.py +280 -0
  38. phoenix/db/models.py +807 -0
  39. phoenix/exceptions.py +5 -1
  40. phoenix/experiments/__init__.py +6 -0
  41. phoenix/experiments/evaluators/__init__.py +29 -0
  42. phoenix/experiments/evaluators/base.py +158 -0
  43. phoenix/experiments/evaluators/code_evaluators.py +184 -0
  44. phoenix/experiments/evaluators/llm_evaluators.py +473 -0
  45. phoenix/experiments/evaluators/utils.py +236 -0
  46. phoenix/experiments/functions.py +772 -0
  47. phoenix/experiments/tracing.py +86 -0
  48. phoenix/experiments/types.py +726 -0
  49. phoenix/experiments/utils.py +25 -0
  50. phoenix/inferences/__init__.py +0 -0
  51. phoenix/{datasets → inferences}/errors.py +6 -5
  52. phoenix/{datasets → inferences}/fixtures.py +49 -42
  53. phoenix/{datasets/dataset.py → inferences/inferences.py} +121 -105
  54. phoenix/{datasets → inferences}/schema.py +11 -11
  55. phoenix/{datasets → inferences}/validation.py +13 -14
  56. phoenix/logging/__init__.py +3 -0
  57. phoenix/logging/_config.py +90 -0
  58. phoenix/logging/_filter.py +6 -0
  59. phoenix/logging/_formatter.py +69 -0
  60. phoenix/metrics/__init__.py +5 -4
  61. phoenix/metrics/binning.py +4 -3
  62. phoenix/metrics/metrics.py +2 -1
  63. phoenix/metrics/mixins.py +7 -6
  64. phoenix/metrics/retrieval_metrics.py +2 -1
  65. phoenix/metrics/timeseries.py +5 -4
  66. phoenix/metrics/wrappers.py +9 -3
  67. phoenix/pointcloud/clustering.py +5 -5
  68. phoenix/pointcloud/pointcloud.py +7 -5
  69. phoenix/pointcloud/projectors.py +5 -6
  70. phoenix/pointcloud/umap_parameters.py +53 -52
  71. phoenix/server/api/README.md +28 -0
  72. phoenix/server/api/auth.py +44 -0
  73. phoenix/server/api/context.py +152 -9
  74. phoenix/server/api/dataloaders/__init__.py +91 -0
  75. phoenix/server/api/dataloaders/annotation_summaries.py +139 -0
  76. phoenix/server/api/dataloaders/average_experiment_run_latency.py +54 -0
  77. phoenix/server/api/dataloaders/cache/__init__.py +3 -0
  78. phoenix/server/api/dataloaders/cache/two_tier_cache.py +68 -0
  79. phoenix/server/api/dataloaders/dataset_example_revisions.py +131 -0
  80. phoenix/server/api/dataloaders/dataset_example_spans.py +38 -0
  81. phoenix/server/api/dataloaders/document_evaluation_summaries.py +144 -0
  82. phoenix/server/api/dataloaders/document_evaluations.py +31 -0
  83. phoenix/server/api/dataloaders/document_retrieval_metrics.py +89 -0
  84. phoenix/server/api/dataloaders/experiment_annotation_summaries.py +79 -0
  85. phoenix/server/api/dataloaders/experiment_error_rates.py +58 -0
  86. phoenix/server/api/dataloaders/experiment_run_annotations.py +36 -0
  87. phoenix/server/api/dataloaders/experiment_run_counts.py +49 -0
  88. phoenix/server/api/dataloaders/experiment_sequence_number.py +44 -0
  89. phoenix/server/api/dataloaders/latency_ms_quantile.py +188 -0
  90. phoenix/server/api/dataloaders/min_start_or_max_end_times.py +85 -0
  91. phoenix/server/api/dataloaders/project_by_name.py +31 -0
  92. phoenix/server/api/dataloaders/record_counts.py +116 -0
  93. phoenix/server/api/dataloaders/session_io.py +79 -0
  94. phoenix/server/api/dataloaders/session_num_traces.py +30 -0
  95. phoenix/server/api/dataloaders/session_num_traces_with_error.py +32 -0
  96. phoenix/server/api/dataloaders/session_token_usages.py +41 -0
  97. phoenix/server/api/dataloaders/session_trace_latency_ms_quantile.py +55 -0
  98. phoenix/server/api/dataloaders/span_annotations.py +26 -0
  99. phoenix/server/api/dataloaders/span_dataset_examples.py +31 -0
  100. phoenix/server/api/dataloaders/span_descendants.py +57 -0
  101. phoenix/server/api/dataloaders/span_projects.py +33 -0
  102. phoenix/server/api/dataloaders/token_counts.py +124 -0
  103. phoenix/server/api/dataloaders/trace_by_trace_ids.py +25 -0
  104. phoenix/server/api/dataloaders/trace_root_spans.py +32 -0
  105. phoenix/server/api/dataloaders/user_roles.py +30 -0
  106. phoenix/server/api/dataloaders/users.py +33 -0
  107. phoenix/server/api/exceptions.py +48 -0
  108. phoenix/server/api/helpers/__init__.py +12 -0
  109. phoenix/server/api/helpers/dataset_helpers.py +217 -0
  110. phoenix/server/api/helpers/experiment_run_filters.py +763 -0
  111. phoenix/server/api/helpers/playground_clients.py +948 -0
  112. phoenix/server/api/helpers/playground_registry.py +70 -0
  113. phoenix/server/api/helpers/playground_spans.py +455 -0
  114. phoenix/server/api/input_types/AddExamplesToDatasetInput.py +16 -0
  115. phoenix/server/api/input_types/AddSpansToDatasetInput.py +14 -0
  116. phoenix/server/api/input_types/ChatCompletionInput.py +38 -0
  117. phoenix/server/api/input_types/ChatCompletionMessageInput.py +24 -0
  118. phoenix/server/api/input_types/ClearProjectInput.py +15 -0
  119. phoenix/server/api/input_types/ClusterInput.py +2 -2
  120. phoenix/server/api/input_types/CreateDatasetInput.py +12 -0
  121. phoenix/server/api/input_types/CreateSpanAnnotationInput.py +18 -0
  122. phoenix/server/api/input_types/CreateTraceAnnotationInput.py +18 -0
  123. phoenix/server/api/input_types/DataQualityMetricInput.py +5 -2
  124. phoenix/server/api/input_types/DatasetExampleInput.py +14 -0
  125. phoenix/server/api/input_types/DatasetSort.py +17 -0
  126. phoenix/server/api/input_types/DatasetVersionSort.py +16 -0
  127. phoenix/server/api/input_types/DeleteAnnotationsInput.py +7 -0
  128. phoenix/server/api/input_types/DeleteDatasetExamplesInput.py +13 -0
  129. phoenix/server/api/input_types/DeleteDatasetInput.py +7 -0
  130. phoenix/server/api/input_types/DeleteExperimentsInput.py +7 -0
  131. phoenix/server/api/input_types/DimensionFilter.py +4 -4
  132. phoenix/server/api/input_types/GenerativeModelInput.py +17 -0
  133. phoenix/server/api/input_types/Granularity.py +1 -1
  134. phoenix/server/api/input_types/InvocationParameters.py +162 -0
  135. phoenix/server/api/input_types/PatchAnnotationInput.py +19 -0
  136. phoenix/server/api/input_types/PatchDatasetExamplesInput.py +35 -0
  137. phoenix/server/api/input_types/PatchDatasetInput.py +14 -0
  138. phoenix/server/api/input_types/PerformanceMetricInput.py +5 -2
  139. phoenix/server/api/input_types/ProjectSessionSort.py +29 -0
  140. phoenix/server/api/input_types/SpanAnnotationSort.py +17 -0
  141. phoenix/server/api/input_types/SpanSort.py +134 -69
  142. phoenix/server/api/input_types/TemplateOptions.py +10 -0
  143. phoenix/server/api/input_types/TraceAnnotationSort.py +17 -0
  144. phoenix/server/api/input_types/UserRoleInput.py +9 -0
  145. phoenix/server/api/mutations/__init__.py +28 -0
  146. phoenix/server/api/mutations/api_key_mutations.py +167 -0
  147. phoenix/server/api/mutations/chat_mutations.py +593 -0
  148. phoenix/server/api/mutations/dataset_mutations.py +591 -0
  149. phoenix/server/api/mutations/experiment_mutations.py +75 -0
  150. phoenix/server/api/{types/ExportEventsMutation.py → mutations/export_events_mutations.py} +21 -18
  151. phoenix/server/api/mutations/project_mutations.py +57 -0
  152. phoenix/server/api/mutations/span_annotations_mutations.py +128 -0
  153. phoenix/server/api/mutations/trace_annotations_mutations.py +127 -0
  154. phoenix/server/api/mutations/user_mutations.py +329 -0
  155. phoenix/server/api/openapi/__init__.py +0 -0
  156. phoenix/server/api/openapi/main.py +17 -0
  157. phoenix/server/api/openapi/schema.py +16 -0
  158. phoenix/server/api/queries.py +738 -0
  159. phoenix/server/api/routers/__init__.py +11 -0
  160. phoenix/server/api/routers/auth.py +284 -0
  161. phoenix/server/api/routers/embeddings.py +26 -0
  162. phoenix/server/api/routers/oauth2.py +488 -0
  163. phoenix/server/api/routers/v1/__init__.py +64 -0
  164. phoenix/server/api/routers/v1/datasets.py +1017 -0
  165. phoenix/server/api/routers/v1/evaluations.py +362 -0
  166. phoenix/server/api/routers/v1/experiment_evaluations.py +115 -0
  167. phoenix/server/api/routers/v1/experiment_runs.py +167 -0
  168. phoenix/server/api/routers/v1/experiments.py +308 -0
  169. phoenix/server/api/routers/v1/pydantic_compat.py +78 -0
  170. phoenix/server/api/routers/v1/spans.py +267 -0
  171. phoenix/server/api/routers/v1/traces.py +208 -0
  172. phoenix/server/api/routers/v1/utils.py +95 -0
  173. phoenix/server/api/schema.py +44 -241
  174. phoenix/server/api/subscriptions.py +597 -0
  175. phoenix/server/api/types/Annotation.py +21 -0
  176. phoenix/server/api/types/AnnotationSummary.py +55 -0
  177. phoenix/server/api/types/AnnotatorKind.py +16 -0
  178. phoenix/server/api/types/ApiKey.py +27 -0
  179. phoenix/server/api/types/AuthMethod.py +9 -0
  180. phoenix/server/api/types/ChatCompletionMessageRole.py +11 -0
  181. phoenix/server/api/types/ChatCompletionSubscriptionPayload.py +46 -0
  182. phoenix/server/api/types/Cluster.py +25 -24
  183. phoenix/server/api/types/CreateDatasetPayload.py +8 -0
  184. phoenix/server/api/types/DataQualityMetric.py +31 -13
  185. phoenix/server/api/types/Dataset.py +288 -63
  186. phoenix/server/api/types/DatasetExample.py +85 -0
  187. phoenix/server/api/types/DatasetExampleRevision.py +34 -0
  188. phoenix/server/api/types/DatasetVersion.py +14 -0
  189. phoenix/server/api/types/Dimension.py +32 -31
  190. phoenix/server/api/types/DocumentEvaluationSummary.py +9 -8
  191. phoenix/server/api/types/EmbeddingDimension.py +56 -49
  192. phoenix/server/api/types/Evaluation.py +25 -31
  193. phoenix/server/api/types/EvaluationSummary.py +30 -50
  194. phoenix/server/api/types/Event.py +20 -20
  195. phoenix/server/api/types/ExampleRevisionInterface.py +14 -0
  196. phoenix/server/api/types/Experiment.py +152 -0
  197. phoenix/server/api/types/ExperimentAnnotationSummary.py +13 -0
  198. phoenix/server/api/types/ExperimentComparison.py +17 -0
  199. phoenix/server/api/types/ExperimentRun.py +119 -0
  200. phoenix/server/api/types/ExperimentRunAnnotation.py +56 -0
  201. phoenix/server/api/types/GenerativeModel.py +9 -0
  202. phoenix/server/api/types/GenerativeProvider.py +85 -0
  203. phoenix/server/api/types/Inferences.py +80 -0
  204. phoenix/server/api/types/InferencesRole.py +23 -0
  205. phoenix/server/api/types/LabelFraction.py +7 -0
  206. phoenix/server/api/types/MimeType.py +2 -2
  207. phoenix/server/api/types/Model.py +54 -54
  208. phoenix/server/api/types/PerformanceMetric.py +8 -5
  209. phoenix/server/api/types/Project.py +407 -142
  210. phoenix/server/api/types/ProjectSession.py +139 -0
  211. phoenix/server/api/types/Segments.py +4 -4
  212. phoenix/server/api/types/Span.py +221 -176
  213. phoenix/server/api/types/SpanAnnotation.py +43 -0
  214. phoenix/server/api/types/SpanIOValue.py +15 -0
  215. phoenix/server/api/types/SystemApiKey.py +9 -0
  216. phoenix/server/api/types/TemplateLanguage.py +10 -0
  217. phoenix/server/api/types/TimeSeries.py +19 -15
  218. phoenix/server/api/types/TokenUsage.py +11 -0
  219. phoenix/server/api/types/Trace.py +154 -0
  220. phoenix/server/api/types/TraceAnnotation.py +45 -0
  221. phoenix/server/api/types/UMAPPoints.py +7 -7
  222. phoenix/server/api/types/User.py +60 -0
  223. phoenix/server/api/types/UserApiKey.py +45 -0
  224. phoenix/server/api/types/UserRole.py +15 -0
  225. phoenix/server/api/types/node.py +4 -112
  226. phoenix/server/api/types/pagination.py +156 -57
  227. phoenix/server/api/utils.py +34 -0
  228. phoenix/server/app.py +864 -115
  229. phoenix/server/bearer_auth.py +163 -0
  230. phoenix/server/dml_event.py +136 -0
  231. phoenix/server/dml_event_handler.py +256 -0
  232. phoenix/server/email/__init__.py +0 -0
  233. phoenix/server/email/sender.py +97 -0
  234. phoenix/server/email/templates/__init__.py +0 -0
  235. phoenix/server/email/templates/password_reset.html +19 -0
  236. phoenix/server/email/types.py +11 -0
  237. phoenix/server/grpc_server.py +102 -0
  238. phoenix/server/jwt_store.py +505 -0
  239. phoenix/server/main.py +305 -116
  240. phoenix/server/oauth2.py +52 -0
  241. phoenix/server/openapi/__init__.py +0 -0
  242. phoenix/server/prometheus.py +111 -0
  243. phoenix/server/rate_limiters.py +188 -0
  244. phoenix/server/static/.vite/manifest.json +87 -0
  245. phoenix/server/static/assets/components-Cy9nwIvF.js +2125 -0
  246. phoenix/server/static/assets/index-BKvHIxkk.js +113 -0
  247. phoenix/server/static/assets/pages-CUi2xCVQ.js +4449 -0
  248. phoenix/server/static/assets/vendor-DvC8cT4X.js +894 -0
  249. phoenix/server/static/assets/vendor-DxkFTwjz.css +1 -0
  250. phoenix/server/static/assets/vendor-arizeai-Do1793cv.js +662 -0
  251. phoenix/server/static/assets/vendor-codemirror-BzwZPyJM.js +24 -0
  252. phoenix/server/static/assets/vendor-recharts-_Jb7JjhG.js +59 -0
  253. phoenix/server/static/assets/vendor-shiki-Cl9QBraO.js +5 -0
  254. phoenix/server/static/assets/vendor-three-DwGkEfCM.js +2998 -0
  255. phoenix/server/telemetry.py +68 -0
  256. phoenix/server/templates/index.html +82 -23
  257. phoenix/server/thread_server.py +3 -3
  258. phoenix/server/types.py +275 -0
  259. phoenix/services.py +27 -18
  260. phoenix/session/client.py +743 -68
  261. phoenix/session/data_extractor.py +31 -7
  262. phoenix/session/evaluation.py +3 -9
  263. phoenix/session/session.py +263 -219
  264. phoenix/settings.py +22 -0
  265. phoenix/trace/__init__.py +2 -22
  266. phoenix/trace/attributes.py +338 -0
  267. phoenix/trace/dsl/README.md +116 -0
  268. phoenix/trace/dsl/filter.py +663 -213
  269. phoenix/trace/dsl/helpers.py +73 -21
  270. phoenix/trace/dsl/query.py +574 -201
  271. phoenix/trace/exporter.py +24 -19
  272. phoenix/trace/fixtures.py +368 -32
  273. phoenix/trace/otel.py +71 -219
  274. phoenix/trace/projects.py +3 -2
  275. phoenix/trace/schemas.py +33 -11
  276. phoenix/trace/span_evaluations.py +21 -16
  277. phoenix/trace/span_json_decoder.py +6 -4
  278. phoenix/trace/span_json_encoder.py +2 -2
  279. phoenix/trace/trace_dataset.py +47 -32
  280. phoenix/trace/utils.py +21 -4
  281. phoenix/utilities/__init__.py +0 -26
  282. phoenix/utilities/client.py +132 -0
  283. phoenix/utilities/deprecation.py +31 -0
  284. phoenix/utilities/error_handling.py +3 -2
  285. phoenix/utilities/json.py +109 -0
  286. phoenix/utilities/logging.py +8 -0
  287. phoenix/utilities/project.py +2 -2
  288. phoenix/utilities/re.py +49 -0
  289. phoenix/utilities/span_store.py +0 -23
  290. phoenix/utilities/template_formatters.py +99 -0
  291. phoenix/version.py +1 -1
  292. arize_phoenix-3.16.1.dist-info/METADATA +0 -495
  293. arize_phoenix-3.16.1.dist-info/RECORD +0 -178
  294. phoenix/core/project.py +0 -619
  295. phoenix/core/traces.py +0 -96
  296. phoenix/experimental/evals/__init__.py +0 -73
  297. phoenix/experimental/evals/evaluators.py +0 -413
  298. phoenix/experimental/evals/functions/__init__.py +0 -4
  299. phoenix/experimental/evals/functions/classify.py +0 -453
  300. phoenix/experimental/evals/functions/executor.py +0 -353
  301. phoenix/experimental/evals/functions/generate.py +0 -138
  302. phoenix/experimental/evals/functions/processing.py +0 -76
  303. phoenix/experimental/evals/models/__init__.py +0 -14
  304. phoenix/experimental/evals/models/anthropic.py +0 -175
  305. phoenix/experimental/evals/models/base.py +0 -170
  306. phoenix/experimental/evals/models/bedrock.py +0 -221
  307. phoenix/experimental/evals/models/litellm.py +0 -134
  308. phoenix/experimental/evals/models/openai.py +0 -448
  309. phoenix/experimental/evals/models/rate_limiters.py +0 -246
  310. phoenix/experimental/evals/models/vertex.py +0 -173
  311. phoenix/experimental/evals/models/vertexai.py +0 -186
  312. phoenix/experimental/evals/retrievals.py +0 -96
  313. phoenix/experimental/evals/templates/__init__.py +0 -50
  314. phoenix/experimental/evals/templates/default_templates.py +0 -472
  315. phoenix/experimental/evals/templates/template.py +0 -195
  316. phoenix/experimental/evals/utils/__init__.py +0 -172
  317. phoenix/experimental/evals/utils/threads.py +0 -27
  318. phoenix/server/api/helpers.py +0 -11
  319. phoenix/server/api/routers/evaluation_handler.py +0 -109
  320. phoenix/server/api/routers/span_handler.py +0 -70
  321. phoenix/server/api/routers/trace_handler.py +0 -60
  322. phoenix/server/api/types/DatasetRole.py +0 -23
  323. phoenix/server/static/index.css +0 -6
  324. phoenix/server/static/index.js +0 -7447
  325. phoenix/storage/span_store/__init__.py +0 -23
  326. phoenix/storage/span_store/text_file.py +0 -85
  327. phoenix/trace/dsl/missing.py +0 -60
  328. phoenix/trace/langchain/__init__.py +0 -3
  329. phoenix/trace/langchain/instrumentor.py +0 -35
  330. phoenix/trace/llama_index/__init__.py +0 -3
  331. phoenix/trace/llama_index/callback.py +0 -102
  332. phoenix/trace/openai/__init__.py +0 -3
  333. phoenix/trace/openai/instrumentor.py +0 -30
  334. {arize_phoenix-3.16.1.dist-info → arize_phoenix-7.7.0.dist-info}/licenses/IP_NOTICE +0 -0
  335. {arize_phoenix-3.16.1.dist-info → arize_phoenix-7.7.0.dist-info}/licenses/LICENSE +0 -0
  336. /phoenix/{datasets → db/insertion}/__init__.py +0 -0
  337. /phoenix/{experimental → db/migrations}/__init__.py +0 -0
  338. /phoenix/{storage → db/migrations/data_migration_scripts}/__init__.py +0 -0
@@ -0,0 +1,85 @@
1
+ from enum import Enum
2
+ from typing import Any, ClassVar, Optional, Union
3
+
4
+ import strawberry
5
+ from openinference.semconv.trace import OpenInferenceLLMProviderValues, SpanAttributes
6
+
7
+ from phoenix.trace.attributes import get_attribute_value
8
+
9
+
10
+ @strawberry.enum
11
+ class GenerativeProviderKey(Enum):
12
+ OPENAI = "OpenAI"
13
+ ANTHROPIC = "Anthropic"
14
+ AZURE_OPENAI = "Azure OpenAI"
15
+ GEMINI = "Google AI Studio"
16
+
17
+
18
+ @strawberry.type
19
+ class GenerativeProvider:
20
+ name: str
21
+ key: GenerativeProviderKey
22
+
23
+ model_provider_to_model_prefix_map: ClassVar[dict[GenerativeProviderKey, list[str]]] = {
24
+ GenerativeProviderKey.AZURE_OPENAI: [],
25
+ GenerativeProviderKey.ANTHROPIC: ["claude"],
26
+ GenerativeProviderKey.OPENAI: ["gpt", "o1"],
27
+ GenerativeProviderKey.GEMINI: ["gemini"],
28
+ }
29
+
30
+ attribute_provider_to_generative_provider_map: ClassVar[dict[str, GenerativeProviderKey]] = {
31
+ OpenInferenceLLMProviderValues.OPENAI.value: GenerativeProviderKey.OPENAI,
32
+ OpenInferenceLLMProviderValues.ANTHROPIC.value: GenerativeProviderKey.ANTHROPIC,
33
+ OpenInferenceLLMProviderValues.AZURE.value: GenerativeProviderKey.AZURE_OPENAI,
34
+ OpenInferenceLLMProviderValues.GOOGLE.value: GenerativeProviderKey.GEMINI,
35
+ }
36
+
37
+ @strawberry.field
38
+ async def dependencies(self) -> list[str]:
39
+ from phoenix.server.api.helpers.playground_registry import (
40
+ PLAYGROUND_CLIENT_REGISTRY,
41
+ PROVIDER_DEFAULT,
42
+ )
43
+
44
+ default_client = PLAYGROUND_CLIENT_REGISTRY.get_client(self.key, PROVIDER_DEFAULT)
45
+ if default_client:
46
+ return [dependency.name for dependency in default_client.dependencies()]
47
+ return []
48
+
49
+ @strawberry.field
50
+ async def dependencies_installed(self) -> bool:
51
+ from phoenix.server.api.helpers.playground_registry import (
52
+ PLAYGROUND_CLIENT_REGISTRY,
53
+ PROVIDER_DEFAULT,
54
+ )
55
+
56
+ default_client = PLAYGROUND_CLIENT_REGISTRY.get_client(self.key, PROVIDER_DEFAULT)
57
+ if default_client:
58
+ return default_client.dependencies_are_installed()
59
+ return False
60
+
61
+ @classmethod
62
+ def _infer_model_provider_from_model_name(
63
+ cls,
64
+ model_name: str,
65
+ ) -> Union[GenerativeProviderKey, None]:
66
+ for provider, prefixes in cls.model_provider_to_model_prefix_map.items():
67
+ if any(prefix.lower() in model_name.lower() for prefix in prefixes):
68
+ return provider
69
+ return None
70
+
71
+ @classmethod
72
+ def get_model_provider_from_attributes(
73
+ cls,
74
+ attributes: dict[str, Any],
75
+ ) -> Union[GenerativeProviderKey, None]:
76
+ llm_provider: Optional[str] = get_attribute_value(attributes, SpanAttributes.LLM_PROVIDER)
77
+
78
+ if isinstance(llm_provider, str) and (
79
+ provider := cls.attribute_provider_to_generative_provider_map.get(llm_provider)
80
+ ):
81
+ return provider
82
+ llm_model = get_attribute_value(attributes, SpanAttributes.LLM_MODEL_NAME)
83
+ if isinstance(llm_model, str):
84
+ return cls._infer_model_provider_from_model_name(llm_model)
85
+ return None
@@ -0,0 +1,80 @@
1
+ from collections.abc import Iterable
2
+ from datetime import datetime
3
+ from typing import Optional, Union
4
+
5
+ import strawberry
6
+ from strawberry import ID, UNSET
7
+
8
+ import phoenix.core.model_schema as ms
9
+ from phoenix.core.model_schema import FEATURE, TAG, ScalarDimension
10
+
11
+ from ..input_types.DimensionInput import DimensionInput
12
+ from .Dimension import Dimension, to_gql_dimension
13
+ from .Event import Event, create_event, create_event_id, parse_event_ids_by_inferences_role
14
+ from .InferencesRole import AncillaryInferencesRole, InferencesRole
15
+
16
+
17
+ @strawberry.type
18
+ class Inferences:
19
+ start_time: datetime = strawberry.field(description="The start bookend of the data")
20
+ end_time: datetime = strawberry.field(description="The end bookend of the data")
21
+ record_count: int = strawberry.field(description="The record count of the data")
22
+ inferences: strawberry.Private[ms.Inferences]
23
+ inferences_role: strawberry.Private[Union[InferencesRole, AncillaryInferencesRole]]
24
+ model: strawberry.Private[ms.Model]
25
+
26
+ # type ignored here to get around the following: https://github.com/strawberry-graphql/strawberry/issues/1929
27
+ @strawberry.field(description="Returns a human friendly name for the inferences.") # type: ignore
28
+ def name(self) -> str:
29
+ return self.inferences.display_name
30
+
31
+ @strawberry.field
32
+ def events(
33
+ self,
34
+ event_ids: list[ID],
35
+ dimensions: Optional[list[DimensionInput]] = UNSET,
36
+ ) -> list[Event]:
37
+ """
38
+ Returns events for specific event IDs and dimensions. If no input
39
+ dimensions are provided, returns all features and tags.
40
+ """
41
+ if not event_ids:
42
+ return []
43
+ row_ids = parse_event_ids_by_inferences_role(event_ids)
44
+ if len(row_ids) > 1 or self.inferences_role not in row_ids:
45
+ raise ValueError("eventIds contains IDs from incorrect inferences.")
46
+ events = self.inferences[row_ids[self.inferences_role]]
47
+ requested_gql_dimensions = _get_requested_features_and_tags(
48
+ core_dimensions=self.model.scalar_dimensions,
49
+ requested_dimension_names=set(dim.name for dim in dimensions)
50
+ if isinstance(dimensions, list)
51
+ else None,
52
+ )
53
+ return [
54
+ create_event(
55
+ event_id=create_event_id(event.id.row_id, self.inferences_role),
56
+ event=event,
57
+ dimensions=requested_gql_dimensions,
58
+ is_document_record=self.inferences_role is AncillaryInferencesRole.corpus,
59
+ )
60
+ for event in events
61
+ ]
62
+
63
+
64
+ def _get_requested_features_and_tags(
65
+ core_dimensions: Iterable[ScalarDimension],
66
+ requested_dimension_names: Optional[set[str]] = UNSET,
67
+ ) -> list[Dimension]:
68
+ """
69
+ Returns requested features and tags as a list of strawberry Inferences. If no
70
+ dimensions are explicitly requested, returns all features and tags.
71
+ """
72
+ requested_features_and_tags: list[Dimension] = []
73
+ for id, dim in enumerate(core_dimensions):
74
+ is_requested = (
75
+ not isinstance(requested_dimension_names, set)
76
+ ) or dim.name in requested_dimension_names
77
+ is_feature_or_tag = dim.role in (FEATURE, TAG)
78
+ if is_requested and is_feature_or_tag:
79
+ requested_features_and_tags.append(to_gql_dimension(id_attr=id, dimension=dim))
80
+ return requested_features_and_tags
@@ -0,0 +1,23 @@
1
+ from enum import Enum
2
+ from typing import Union
3
+
4
+ import strawberry
5
+
6
+ from phoenix.core.model_schema import PRIMARY, REFERENCE
7
+
8
+
9
+ @strawberry.enum
10
+ class InferencesRole(Enum):
11
+ primary = PRIMARY
12
+ reference = REFERENCE
13
+
14
+
15
+ class AncillaryInferencesRole(Enum):
16
+ corpus = "InferencesRole.CORPUS"
17
+
18
+
19
+ STR_TO_INFEREENCES_ROLE: dict[str, Union[InferencesRole, AncillaryInferencesRole]] = {
20
+ str(InferencesRole.primary.value): InferencesRole.primary,
21
+ str(InferencesRole.reference.value): InferencesRole.reference,
22
+ str(AncillaryInferencesRole.corpus.value): AncillaryInferencesRole.corpus,
23
+ }
@@ -0,0 +1,7 @@
1
+ import strawberry
2
+
3
+
4
+ @strawberry.type
5
+ class LabelFraction:
6
+ label: str
7
+ fraction: float
@@ -8,8 +8,8 @@ import phoenix.trace.schemas as trace_schemas
8
8
 
9
9
  @strawberry.enum
10
10
  class MimeType(Enum):
11
- text = trace_schemas.MimeType.TEXT
12
- json = trace_schemas.MimeType.JSON
11
+ text = trace_schemas.MimeType.TEXT.value
12
+ json = trace_schemas.MimeType.JSON.value
13
13
 
14
14
  @classmethod
15
15
  def _missing_(cls, v: Any) -> Optional["MimeType"]:
@@ -1,9 +1,9 @@
1
1
  import asyncio
2
- from typing import List, Optional
2
+ from typing import Optional
3
3
 
4
4
  import strawberry
5
- from strawberry.types import Info
6
- from strawberry.unset import UNSET
5
+ from strawberry import UNSET, Info
6
+ from strawberry.relay import Connection
7
7
  from typing_extensions import Annotated
8
8
 
9
9
  from phoenix.config import get_exported_files
@@ -14,12 +14,12 @@ from ..input_types.DimensionFilter import DimensionFilter
14
14
  from ..input_types.Granularity import Granularity
15
15
  from ..input_types.PerformanceMetricInput import PerformanceMetricInput
16
16
  from ..input_types.TimeRange import TimeRange
17
- from .Dataset import Dataset
18
- from .DatasetRole import AncillaryDatasetRole, DatasetRole
19
17
  from .Dimension import Dimension, to_gql_dimension
20
18
  from .EmbeddingDimension import EmbeddingDimension, to_gql_embedding_dimension
21
19
  from .ExportedFile import ExportedFile
22
- from .pagination import Connection, ConnectionArgs, Cursor, connection_from_list
20
+ from .Inferences import Inferences
21
+ from .InferencesRole import AncillaryInferencesRole, InferencesRole
22
+ from .pagination import ConnectionArgs, CursorString, connection_from_list
23
23
  from .TimeSeries import (
24
24
  PerformanceTimeSeries,
25
25
  ensure_timeseries_parameters,
@@ -35,8 +35,8 @@ class Model:
35
35
  info: Info[Context, None],
36
36
  first: Optional[int] = 50,
37
37
  last: Optional[int] = UNSET,
38
- after: Optional[Cursor] = UNSET,
39
- before: Optional[Cursor] = UNSET,
38
+ after: Optional[CursorString] = UNSET,
39
+ before: Optional[CursorString] = UNSET,
40
40
  include: Optional[DimensionFilter] = UNSET,
41
41
  exclude: Optional[DimensionFilter] = UNSET,
42
42
  ) -> Connection[Dimension]:
@@ -50,52 +50,52 @@ class Model:
50
50
  ],
51
51
  args=ConnectionArgs(
52
52
  first=first,
53
- after=after if isinstance(after, Cursor) else None,
53
+ after=after if isinstance(after, CursorString) else None,
54
54
  last=last,
55
- before=before if isinstance(before, Cursor) else None,
55
+ before=before if isinstance(before, CursorString) else None,
56
56
  ),
57
57
  )
58
58
 
59
59
  @strawberry.field
60
- def primary_dataset(self, info: Info[Context, None]) -> Dataset:
61
- dataset = info.context.model[PRIMARY]
62
- start, stop = dataset.time_range
63
- return Dataset(
60
+ def primary_inferences(self, info: Info[Context, None]) -> Inferences:
61
+ inferences = info.context.model[PRIMARY]
62
+ start, stop = inferences.time_range
63
+ return Inferences(
64
64
  start_time=start,
65
65
  end_time=stop,
66
- record_count=len(dataset),
67
- dataset=dataset,
68
- dataset_role=DatasetRole.primary,
66
+ record_count=len(inferences),
67
+ inferences=inferences,
68
+ inferences_role=InferencesRole.primary,
69
69
  model=info.context.model,
70
70
  )
71
71
 
72
72
  @strawberry.field
73
- def reference_dataset(self, info: Info[Context, None]) -> Optional[Dataset]:
74
- if (dataset := info.context.model[REFERENCE]).empty:
73
+ def reference_inferences(self, info: Info[Context, None]) -> Optional[Inferences]:
74
+ if (inferences := info.context.model[REFERENCE]).empty:
75
75
  return None
76
- start, stop = dataset.time_range
77
- return Dataset(
76
+ start, stop = inferences.time_range
77
+ return Inferences(
78
78
  start_time=start,
79
79
  end_time=stop,
80
- record_count=len(dataset),
81
- dataset=dataset,
82
- dataset_role=DatasetRole.reference,
80
+ record_count=len(inferences),
81
+ inferences=inferences,
82
+ inferences_role=InferencesRole.reference,
83
83
  model=info.context.model,
84
84
  )
85
85
 
86
86
  @strawberry.field
87
- def corpus_dataset(self, info: Info[Context, None]) -> Optional[Dataset]:
87
+ def corpus_inferences(self, info: Info[Context, None]) -> Optional[Inferences]:
88
88
  if info.context.corpus is None:
89
89
  return None
90
- if (dataset := info.context.corpus[PRIMARY]).empty:
90
+ if (inferences := info.context.corpus[PRIMARY]).empty:
91
91
  return None
92
- start, stop = dataset.time_range
93
- return Dataset(
92
+ start, stop = inferences.time_range
93
+ return Inferences(
94
94
  start_time=start,
95
95
  end_time=stop,
96
- record_count=len(dataset),
97
- dataset=dataset,
98
- dataset_role=AncillaryDatasetRole.corpus,
96
+ record_count=len(inferences),
97
+ inferences=inferences,
98
+ inferences_role=AncillaryInferencesRole.corpus,
99
99
  model=info.context.corpus,
100
100
  )
101
101
 
@@ -105,8 +105,8 @@ class Model:
105
105
  info: Info[Context, None],
106
106
  first: Optional[int] = 50,
107
107
  last: Optional[int] = UNSET,
108
- after: Optional[Cursor] = UNSET,
109
- before: Optional[Cursor] = UNSET,
108
+ after: Optional[CursorString] = UNSET,
109
+ before: Optional[CursorString] = UNSET,
110
110
  ) -> Connection[EmbeddingDimension]:
111
111
  """
112
112
  A non-trivial implementation should efficiently fetch only
@@ -123,9 +123,9 @@ class Model:
123
123
  ],
124
124
  args=ConnectionArgs(
125
125
  first=first,
126
- after=after if isinstance(after, Cursor) else None,
126
+ after=after if isinstance(after, CursorString) else None,
127
127
  last=last,
128
- before=before if isinstance(before, Cursor) else None,
128
+ before=before if isinstance(before, CursorString) else None,
129
129
  ),
130
130
  )
131
131
 
@@ -135,7 +135,7 @@ class Model:
135
135
  async def exported_files(
136
136
  self,
137
137
  info: Info[Context, None],
138
- ) -> List[ExportedFile]:
138
+ ) -> list[ExportedFile]:
139
139
  loop = asyncio.get_running_loop()
140
140
  return [
141
141
  ExportedFile(file_name=path.stem)
@@ -156,24 +156,24 @@ class Model:
156
156
  info: Info[Context, None],
157
157
  metric: PerformanceMetricInput,
158
158
  time_range: Optional[TimeRange] = UNSET,
159
- dataset_role: Annotated[
160
- Optional[DatasetRole],
159
+ inferences_role: Annotated[
160
+ Optional[InferencesRole],
161
161
  strawberry.argument(
162
- description="The dataset (primary or reference) to query",
162
+ description="The inferences (primary or reference) to query",
163
163
  ),
164
- ] = DatasetRole.primary,
164
+ ] = InferencesRole.primary,
165
165
  ) -> Optional[float]:
166
- if not isinstance(dataset_role, DatasetRole):
167
- dataset_role = DatasetRole.primary
166
+ if not isinstance(inferences_role, InferencesRole):
167
+ inferences_role = InferencesRole.primary
168
168
  model = info.context.model
169
- dataset = model[dataset_role.value]
169
+ inferences = model[inferences_role.value]
170
170
  time_range, granularity = ensure_timeseries_parameters(
171
- dataset,
171
+ inferences,
172
172
  time_range,
173
173
  )
174
174
  metric_instance = metric.metric_instance(model)
175
175
  data = get_timeseries_data(
176
- dataset,
176
+ inferences,
177
177
  metric_instance,
178
178
  time_range,
179
179
  granularity,
@@ -194,26 +194,26 @@ class Model:
194
194
  metric: PerformanceMetricInput,
195
195
  time_range: TimeRange,
196
196
  granularity: Granularity,
197
- dataset_role: Annotated[
198
- Optional[DatasetRole],
197
+ inferences_role: Annotated[
198
+ Optional[InferencesRole],
199
199
  strawberry.argument(
200
- description="The dataset (primary or reference) to query",
200
+ description="The inferences (primary or reference) to query",
201
201
  ),
202
- ] = DatasetRole.primary,
202
+ ] = InferencesRole.primary,
203
203
  ) -> PerformanceTimeSeries:
204
- if not isinstance(dataset_role, DatasetRole):
205
- dataset_role = DatasetRole.primary
204
+ if not isinstance(inferences_role, InferencesRole):
205
+ inferences_role = InferencesRole.primary
206
206
  model = info.context.model
207
- dataset = model[dataset_role.value]
207
+ inferences = model[inferences_role.value]
208
208
  time_range, granularity = ensure_timeseries_parameters(
209
- dataset,
209
+ inferences,
210
210
  time_range,
211
211
  granularity,
212
212
  )
213
213
  metric_instance = metric.metric_instance(model)
214
214
  return PerformanceTimeSeries(
215
215
  data=get_timeseries_data(
216
- dataset,
216
+ inferences,
217
217
  metric_instance,
218
218
  time_range,
219
219
  granularity,
@@ -1,5 +1,5 @@
1
- from enum import Enum
2
- from functools import partial
1
+ from enum import Enum, auto
2
+ from typing import Callable, Mapping, cast
3
3
 
4
4
  import strawberry
5
5
 
@@ -8,6 +8,9 @@ from phoenix.metrics.wrappers import SkEval
8
8
 
9
9
  @strawberry.enum
10
10
  class PerformanceMetric(Enum):
11
- # To become enum values, functions need to be wrapped in partial.
12
- # See https://stackoverflow.com/a/40339397
13
- accuracyScore = partial(SkEval.accuracy_score) # type: ignore
11
+ accuracyScore = auto()
12
+
13
+
14
+ PERFORMANCE_METRIC_FUNCTIONS: Mapping[PerformanceMetric, Callable[..., float]] = {
15
+ PerformanceMetric.accuracyScore: cast(Callable[..., float], SkEval.accuracy_score),
16
+ }