arize-phoenix 3.16.1__py3-none-any.whl → 7.7.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

Files changed (338) hide show
  1. arize_phoenix-7.7.1.dist-info/METADATA +261 -0
  2. arize_phoenix-7.7.1.dist-info/RECORD +345 -0
  3. {arize_phoenix-3.16.1.dist-info → arize_phoenix-7.7.1.dist-info}/WHEEL +1 -1
  4. arize_phoenix-7.7.1.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.1.dist-info}/licenses/IP_NOTICE +0 -0
  335. {arize_phoenix-3.16.1.dist-info → arize_phoenix-7.7.1.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,70 @@
1
+ from typing import TYPE_CHECKING, Any, Callable, Optional, Union
2
+
3
+ from phoenix.server.api.types.GenerativeProvider import GenerativeProviderKey
4
+
5
+ if TYPE_CHECKING:
6
+ from phoenix.server.api.helpers.playground_clients import PlaygroundStreamingClient
7
+
8
+ ModelName = Union[str, None]
9
+ ModelKey = tuple[GenerativeProviderKey, ModelName]
10
+
11
+ PROVIDER_DEFAULT = None
12
+
13
+
14
+ class SingletonMeta(type):
15
+ _instances: dict[Any, Any] = dict()
16
+
17
+ def __call__(cls, *args: Any, **kwargs: Any) -> Any:
18
+ if cls not in cls._instances:
19
+ cls._instances[cls] = super(SingletonMeta, cls).__call__(*args, **kwargs)
20
+ return cls._instances[cls]
21
+
22
+
23
+ class PlaygroundClientRegistry(metaclass=SingletonMeta):
24
+ def __init__(self) -> None:
25
+ self._registry: dict[
26
+ GenerativeProviderKey, dict[ModelName, Optional[type["PlaygroundStreamingClient"]]]
27
+ ] = {}
28
+
29
+ def get_client(
30
+ self,
31
+ provider_key: GenerativeProviderKey,
32
+ model_name: ModelName,
33
+ ) -> Optional[type["PlaygroundStreamingClient"]]:
34
+ provider_registry = self._registry.get(provider_key, {})
35
+ client_class = provider_registry.get(model_name)
36
+ if client_class is None and None in provider_registry:
37
+ client_class = provider_registry[PROVIDER_DEFAULT] # Fallback to provider default
38
+ return client_class
39
+
40
+ def list_all_providers(
41
+ self,
42
+ ) -> list[GenerativeProviderKey]:
43
+ return [provider_key for provider_key in self._registry]
44
+
45
+ def list_models(self, provider_key: GenerativeProviderKey) -> list[str]:
46
+ provider_registry = self._registry.get(provider_key, {})
47
+ return [model_name for model_name in provider_registry.keys() if model_name is not None]
48
+
49
+ def list_all_models(self) -> list[ModelKey]:
50
+ return [
51
+ (provider_key, model_name)
52
+ for provider_key, provider_registry in self._registry.items()
53
+ for model_name in provider_registry.keys()
54
+ ]
55
+
56
+
57
+ PLAYGROUND_CLIENT_REGISTRY: PlaygroundClientRegistry = PlaygroundClientRegistry()
58
+
59
+
60
+ def register_llm_client(
61
+ provider_key: GenerativeProviderKey,
62
+ model_names: list[ModelName],
63
+ ) -> Callable[[type["PlaygroundStreamingClient"]], type["PlaygroundStreamingClient"]]:
64
+ def decorator(cls: type["PlaygroundStreamingClient"]) -> type["PlaygroundStreamingClient"]:
65
+ provider_registry = PLAYGROUND_CLIENT_REGISTRY._registry.setdefault(provider_key, {})
66
+ for model_name in model_names:
67
+ provider_registry[model_name] = cls
68
+ return cls
69
+
70
+ return decorator
@@ -0,0 +1,455 @@
1
+ import json
2
+ from collections import defaultdict
3
+ from collections.abc import Mapping
4
+ from dataclasses import asdict
5
+ from datetime import datetime, timezone
6
+ from itertools import chain
7
+ from traceback import format_exc
8
+ from types import TracebackType
9
+ from typing import (
10
+ Any,
11
+ Iterable,
12
+ Iterator,
13
+ Optional,
14
+ Union,
15
+ cast,
16
+ )
17
+
18
+ from openinference.instrumentation import safe_json_dumps
19
+ from openinference.semconv.trace import (
20
+ MessageAttributes,
21
+ OpenInferenceMimeTypeValues,
22
+ OpenInferenceSpanKindValues,
23
+ SpanAttributes,
24
+ ToolAttributes,
25
+ ToolCallAttributes,
26
+ )
27
+ from opentelemetry.sdk.trace.id_generator import RandomIdGenerator as DefaultOTelIDGenerator
28
+ from opentelemetry.trace import StatusCode
29
+ from strawberry.scalars import JSON as JSONScalarType
30
+ from typing_extensions import Self, TypeAlias, assert_never
31
+
32
+ from phoenix.datetime_utils import local_now, normalize_datetime
33
+ from phoenix.db import models
34
+ from phoenix.server.api.helpers.dataset_helpers import get_dataset_example_output
35
+ from phoenix.server.api.input_types.ChatCompletionInput import (
36
+ ChatCompletionInput,
37
+ ChatCompletionOverDatasetInput,
38
+ )
39
+ from phoenix.server.api.types.ChatCompletionMessageRole import ChatCompletionMessageRole
40
+ from phoenix.server.api.types.ChatCompletionSubscriptionPayload import (
41
+ TextChunk,
42
+ ToolCallChunk,
43
+ )
44
+ from phoenix.trace.attributes import get_attribute_value, unflatten
45
+ from phoenix.trace.schemas import (
46
+ SpanEvent,
47
+ SpanException,
48
+ )
49
+ from phoenix.utilities.json import jsonify
50
+
51
+ ChatCompletionMessage: TypeAlias = tuple[
52
+ ChatCompletionMessageRole, str, Optional[str], Optional[list[str]]
53
+ ]
54
+ ToolCallID: TypeAlias = str
55
+
56
+
57
+ class streaming_llm_span:
58
+ """
59
+ A context manager that records OpenInference attributes for streaming chat
60
+ completion LLM spans.
61
+ """
62
+
63
+ def __init__(
64
+ self,
65
+ *,
66
+ input: Union[ChatCompletionInput, ChatCompletionOverDatasetInput],
67
+ messages: list[ChatCompletionMessage],
68
+ invocation_parameters: Mapping[str, Any],
69
+ attributes: Optional[dict[str, Any]] = None,
70
+ ) -> None:
71
+ self._input = input
72
+ self._attributes: dict[str, Any] = attributes if attributes is not None else {}
73
+ self._attributes.update(
74
+ chain(
75
+ llm_span_kind(),
76
+ llm_model_name(input.model.name),
77
+ llm_tools(input.tools or []),
78
+ llm_input_messages(messages),
79
+ llm_invocation_parameters(invocation_parameters),
80
+ input_value_and_mime_type(input),
81
+ )
82
+ )
83
+ self._events: list[SpanEvent] = []
84
+ self._start_time: Optional[datetime] = None
85
+ self._end_time: Optional[datetime] = None
86
+ self._text_chunks: list[TextChunk] = []
87
+ self._tool_call_chunks: defaultdict[ToolCallID, list[ToolCallChunk]] = defaultdict(list)
88
+ self._status_code: StatusCode = StatusCode.UNSET
89
+ self._status_message: Optional[str] = None
90
+ self._trace_id = _generate_trace_id()
91
+ self._span_id = _generate_span_id()
92
+
93
+ async def __aenter__(self) -> Self:
94
+ self._start_time = cast(datetime, normalize_datetime(dt=local_now(), tz=timezone.utc))
95
+ return self
96
+
97
+ async def __aexit__(
98
+ self,
99
+ exc_type: Optional[type[BaseException]],
100
+ exc_value: Optional[BaseException],
101
+ traceback: Optional[TracebackType],
102
+ ) -> bool:
103
+ self._end_time = cast(datetime, normalize_datetime(dt=local_now(), tz=timezone.utc))
104
+ self._status_code = StatusCode.OK
105
+ if exc_type is not None:
106
+ self._status_code = StatusCode.ERROR
107
+ self._status_message = str(exc_value)
108
+ self._events.append(
109
+ SpanException(
110
+ timestamp=self._end_time,
111
+ message=self._status_message,
112
+ exception_type=type(exc_value).__name__,
113
+ exception_escaped=False,
114
+ exception_stacktrace=format_exc(),
115
+ )
116
+ )
117
+ if self._text_chunks or self._tool_call_chunks:
118
+ self._attributes.update(
119
+ chain(
120
+ _output_value_and_mime_type(self._text_chunks, self._tool_call_chunks),
121
+ _llm_output_messages(self._text_chunks, self._tool_call_chunks),
122
+ )
123
+ )
124
+ return True
125
+
126
+ def set_attributes(self, attributes: Mapping[str, Any]) -> None:
127
+ self._attributes.update(attributes)
128
+
129
+ def add_response_chunk(self, chunk: Union[TextChunk, ToolCallChunk]) -> None:
130
+ if isinstance(chunk, TextChunk):
131
+ self._text_chunks.append(chunk)
132
+ elif isinstance(chunk, ToolCallChunk):
133
+ self._tool_call_chunks[chunk.id].append(chunk)
134
+ else:
135
+ assert_never(chunk)
136
+
137
+ @property
138
+ def span_id(self) -> str:
139
+ return self._span_id
140
+
141
+ @property
142
+ def trace_id(self) -> str:
143
+ return self._trace_id
144
+
145
+ @property
146
+ def start_time(self) -> datetime:
147
+ if self._start_time is None:
148
+ raise ValueError("Cannot access start time before the context manager is entered")
149
+ return self._start_time
150
+
151
+ @property
152
+ def end_time(self) -> datetime:
153
+ if self._end_time is None:
154
+ raise ValueError("Cannot access end time before the context manager is exited")
155
+ return self._end_time
156
+
157
+ @property
158
+ def status_code(self) -> StatusCode:
159
+ return self._status_code
160
+
161
+ @property
162
+ def status_message(self) -> Optional[str]:
163
+ if self._status_code is StatusCode.UNSET:
164
+ raise ValueError("Cannot access status message before the context manager is exited")
165
+ return self._status_message
166
+
167
+ @property
168
+ def events(self) -> list[SpanEvent]:
169
+ return self._events
170
+
171
+ @property
172
+ def attributes(self) -> dict[str, Any]:
173
+ return unflatten(self._attributes.items())
174
+
175
+
176
+ def get_db_trace(span: streaming_llm_span, project_id: int) -> models.Trace:
177
+ return models.Trace(
178
+ project_rowid=project_id,
179
+ trace_id=span.trace_id,
180
+ start_time=span.start_time,
181
+ end_time=span.end_time,
182
+ )
183
+
184
+
185
+ def get_db_span(
186
+ span: streaming_llm_span,
187
+ db_trace: models.Trace,
188
+ ) -> models.Span:
189
+ prompt_tokens = get_attribute_value(span.attributes, LLM_TOKEN_COUNT_PROMPT) or 0
190
+ completion_tokens = get_attribute_value(span.attributes, LLM_TOKEN_COUNT_COMPLETION) or 0
191
+ return models.Span(
192
+ trace_rowid=db_trace.id,
193
+ span_id=span.span_id,
194
+ parent_id=None,
195
+ name="ChatCompletion",
196
+ span_kind=LLM,
197
+ start_time=span.start_time,
198
+ end_time=span.end_time,
199
+ attributes=span.attributes,
200
+ events=[_serialize_event(event) for event in span.events],
201
+ status_code=span.status_code.name,
202
+ status_message=span.status_message or "",
203
+ cumulative_error_count=int(span.status_code is StatusCode.ERROR),
204
+ cumulative_llm_token_count_prompt=prompt_tokens,
205
+ cumulative_llm_token_count_completion=completion_tokens,
206
+ llm_token_count_prompt=prompt_tokens,
207
+ llm_token_count_completion=completion_tokens,
208
+ trace=db_trace,
209
+ )
210
+
211
+
212
+ def get_db_experiment_run(
213
+ db_span: models.Span,
214
+ db_trace: models.Trace,
215
+ *,
216
+ experiment_id: int,
217
+ example_id: int,
218
+ ) -> models.ExperimentRun:
219
+ return models.ExperimentRun(
220
+ experiment_id=experiment_id,
221
+ dataset_example_id=example_id,
222
+ trace_id=db_trace.trace_id,
223
+ output=models.ExperimentRunOutput(
224
+ task_output=get_dataset_example_output(db_span),
225
+ ),
226
+ repetition_number=1,
227
+ start_time=db_span.start_time,
228
+ end_time=db_span.end_time,
229
+ error=db_span.status_message or None,
230
+ prompt_token_count=get_attribute_value(db_span.attributes, LLM_TOKEN_COUNT_PROMPT),
231
+ completion_token_count=get_attribute_value(db_span.attributes, LLM_TOKEN_COUNT_COMPLETION),
232
+ trace=db_trace,
233
+ )
234
+
235
+
236
+ def llm_span_kind() -> Iterator[tuple[str, Any]]:
237
+ yield OPENINFERENCE_SPAN_KIND, LLM
238
+
239
+
240
+ def llm_model_name(model_name: str) -> Iterator[tuple[str, Any]]:
241
+ yield LLM_MODEL_NAME, model_name
242
+
243
+
244
+ def llm_invocation_parameters(
245
+ invocation_parameters: Mapping[str, Any],
246
+ ) -> Iterator[tuple[str, Any]]:
247
+ if invocation_parameters:
248
+ yield LLM_INVOCATION_PARAMETERS, safe_json_dumps(invocation_parameters)
249
+
250
+
251
+ def llm_tools(tools: list[JSONScalarType]) -> Iterator[tuple[str, Any]]:
252
+ for tool_index, tool in enumerate(tools):
253
+ yield f"{LLM_TOOLS}.{tool_index}.{TOOL_JSON_SCHEMA}", json.dumps(tool)
254
+
255
+
256
+ def input_value_and_mime_type(
257
+ input: Union[ChatCompletionInput, ChatCompletionOverDatasetInput],
258
+ ) -> Iterator[tuple[str, Any]]:
259
+ assert (api_key := "api_key") in (input_data := jsonify(input))
260
+ disallowed_keys = {"api_key", "invocation_parameters"}
261
+ input_data = {k: v for k, v in input_data.items() if k not in disallowed_keys}
262
+ assert api_key not in input_data
263
+ yield INPUT_MIME_TYPE, JSON
264
+ yield INPUT_VALUE, safe_json_dumps(input_data)
265
+
266
+
267
+ def _merge_tool_call_chunks(
268
+ chunks_by_id: defaultdict[str, list[ToolCallChunk]],
269
+ ) -> list[dict[str, Any]]:
270
+ merged_tool_calls = []
271
+
272
+ for tool_id, chunks in chunks_by_id.items():
273
+ if not chunks:
274
+ continue
275
+ first_chunk = chunks[0]
276
+ if not first_chunk:
277
+ continue
278
+
279
+ if not hasattr(first_chunk, "function") or not hasattr(first_chunk.function, "name"):
280
+ continue
281
+ # Combine all argument chunks
282
+ merged_arguments = "".join(
283
+ chunk.function.arguments
284
+ for chunk in chunks
285
+ if chunk and hasattr(chunk, "function") and hasattr(chunk.function, "arguments")
286
+ )
287
+
288
+ merged_tool_calls.append(
289
+ {
290
+ "id": tool_id,
291
+ # Only the first chunk has the tool name
292
+ "function": {
293
+ "name": first_chunk.function.name,
294
+ "arguments": merged_arguments or "{}",
295
+ },
296
+ }
297
+ )
298
+
299
+ return merged_tool_calls
300
+
301
+
302
+ def _output_value_and_mime_type(
303
+ text_chunks: list[TextChunk],
304
+ tool_call_chunks: defaultdict[ToolCallID, list[ToolCallChunk]],
305
+ ) -> Iterator[tuple[str, Any]]:
306
+ content = "".join(chunk.content for chunk in text_chunks)
307
+ merged_tool_calls = _merge_tool_call_chunks(tool_call_chunks)
308
+ if content and merged_tool_calls:
309
+ yield OUTPUT_MIME_TYPE, JSON
310
+ yield (
311
+ OUTPUT_VALUE,
312
+ safe_json_dumps(
313
+ {
314
+ "content": content,
315
+ "tool_calls": jsonify(
316
+ merged_tool_calls,
317
+ ),
318
+ }
319
+ ),
320
+ )
321
+ elif merged_tool_calls:
322
+ yield OUTPUT_MIME_TYPE, JSON
323
+ yield OUTPUT_VALUE, safe_json_dumps(jsonify(merged_tool_calls))
324
+ elif content:
325
+ yield OUTPUT_MIME_TYPE, TEXT
326
+ yield OUTPUT_VALUE, content
327
+
328
+
329
+ def llm_input_messages(
330
+ messages: Iterable[
331
+ tuple[ChatCompletionMessageRole, str, Optional[str], Optional[list[JSONScalarType]]]
332
+ ],
333
+ ) -> Iterator[tuple[str, Any]]:
334
+ for i, (role, content, tool_call_id, tool_calls) in enumerate(messages):
335
+ yield f"{LLM_INPUT_MESSAGES}.{i}.{MESSAGE_ROLE}", role.value.lower()
336
+ yield f"{LLM_INPUT_MESSAGES}.{i}.{MESSAGE_CONTENT}", content
337
+ if role == ChatCompletionMessageRole.TOOL and tool_call_id:
338
+ # Anthropic tool result spans
339
+ yield f"{LLM_INPUT_MESSAGES}.{i}.{MESSAGE_TOOL_CALL_ID}", tool_call_id
340
+
341
+ if tool_calls is not None:
342
+ for tool_call_index, tool_call in enumerate(tool_calls):
343
+ if tool_call.get("type") == "tool_use":
344
+ # Anthropic tool call spans
345
+ yield (
346
+ f"{LLM_INPUT_MESSAGES}.{i}.{MESSAGE_TOOL_CALLS}.{tool_call_index}.{TOOL_CALL_FUNCTION_NAME}",
347
+ tool_call["name"],
348
+ )
349
+ yield (
350
+ f"{LLM_INPUT_MESSAGES}.{i}.{MESSAGE_TOOL_CALLS}.{tool_call_index}.{TOOL_CALL_FUNCTION_ARGUMENTS_JSON}",
351
+ safe_json_dumps(jsonify(tool_call["input"])),
352
+ )
353
+ yield (
354
+ f"{LLM_INPUT_MESSAGES}.{i}.{MESSAGE_TOOL_CALLS}.{tool_call_index}.{TOOL_CALL_ID}",
355
+ tool_call["id"],
356
+ )
357
+ elif tool_call_function := tool_call.get("function"):
358
+ # OpenAI tool call spans
359
+ yield (
360
+ f"{LLM_INPUT_MESSAGES}.{i}.{MESSAGE_TOOL_CALLS}.{tool_call_index}.{TOOL_CALL_FUNCTION_NAME}",
361
+ tool_call_function["name"],
362
+ )
363
+ if arguments := tool_call_function["arguments"]:
364
+ yield (
365
+ f"{LLM_INPUT_MESSAGES}.{i}.{MESSAGE_TOOL_CALLS}.{tool_call_index}.{TOOL_CALL_FUNCTION_ARGUMENTS_JSON}",
366
+ safe_json_dumps(jsonify(arguments)),
367
+ )
368
+ if tool_call_id := tool_call.get("id"):
369
+ yield (
370
+ f"{LLM_INPUT_MESSAGES}.{i}.{MESSAGE_TOOL_CALLS}.{tool_call_index}.{TOOL_CALL_ID}",
371
+ tool_call_id,
372
+ )
373
+
374
+
375
+ def _llm_output_messages(
376
+ text_chunks: list[TextChunk],
377
+ tool_call_chunks: defaultdict[ToolCallID, list[ToolCallChunk]],
378
+ ) -> Iterator[tuple[str, Any]]:
379
+ yield f"{LLM_OUTPUT_MESSAGES}.0.{MESSAGE_ROLE}", "assistant"
380
+ if content := "".join(chunk.content for chunk in text_chunks):
381
+ yield f"{LLM_OUTPUT_MESSAGES}.0.{MESSAGE_CONTENT}", content
382
+ for tool_call_index, (_tool_call_id, tool_call_chunks_) in enumerate(tool_call_chunks.items()):
383
+ if _tool_call_id:
384
+ yield (
385
+ f"{LLM_OUTPUT_MESSAGES}.0.{MESSAGE_TOOL_CALLS}.{tool_call_index}.{TOOL_CALL_ID}",
386
+ _tool_call_id,
387
+ )
388
+ if tool_call_chunks_ and (name := tool_call_chunks_[0].function.name):
389
+ yield (
390
+ f"{LLM_OUTPUT_MESSAGES}.0.{MESSAGE_TOOL_CALLS}.{tool_call_index}.{TOOL_CALL_FUNCTION_NAME}",
391
+ name,
392
+ )
393
+ if arguments := "".join(chunk.function.arguments for chunk in tool_call_chunks_):
394
+ yield (
395
+ f"{LLM_OUTPUT_MESSAGES}.0.{MESSAGE_TOOL_CALLS}.{tool_call_index}.{TOOL_CALL_FUNCTION_ARGUMENTS_JSON}",
396
+ arguments,
397
+ )
398
+
399
+
400
+ def _generate_trace_id() -> str:
401
+ """
402
+ Generates a random trace ID in hexadecimal format.
403
+ """
404
+ return _hex(DefaultOTelIDGenerator().generate_trace_id())
405
+
406
+
407
+ def _generate_span_id() -> str:
408
+ """
409
+ Generates a random span ID in hexadecimal format.
410
+ """
411
+ return _hex(DefaultOTelIDGenerator().generate_span_id())
412
+
413
+
414
+ def _hex(number: int) -> str:
415
+ """
416
+ Converts an integer to a hexadecimal string.
417
+ """
418
+ return hex(number)[2:]
419
+
420
+
421
+ def _serialize_event(event: SpanEvent) -> dict[str, Any]:
422
+ """
423
+ Serializes a SpanEvent to a dictionary.
424
+ """
425
+ return {k: (v.isoformat() if isinstance(v, datetime) else v) for k, v in asdict(event).items()}
426
+
427
+
428
+ JSON = OpenInferenceMimeTypeValues.JSON.value
429
+ TEXT = OpenInferenceMimeTypeValues.TEXT.value
430
+
431
+ LLM = OpenInferenceSpanKindValues.LLM.value
432
+
433
+ OPENINFERENCE_SPAN_KIND = SpanAttributes.OPENINFERENCE_SPAN_KIND
434
+ INPUT_MIME_TYPE = SpanAttributes.INPUT_MIME_TYPE
435
+ INPUT_VALUE = SpanAttributes.INPUT_VALUE
436
+ OUTPUT_MIME_TYPE = SpanAttributes.OUTPUT_MIME_TYPE
437
+ OUTPUT_VALUE = SpanAttributes.OUTPUT_VALUE
438
+ LLM_INPUT_MESSAGES = SpanAttributes.LLM_INPUT_MESSAGES
439
+ LLM_OUTPUT_MESSAGES = SpanAttributes.LLM_OUTPUT_MESSAGES
440
+ LLM_MODEL_NAME = SpanAttributes.LLM_MODEL_NAME
441
+ LLM_INVOCATION_PARAMETERS = SpanAttributes.LLM_INVOCATION_PARAMETERS
442
+ LLM_TOOLS = SpanAttributes.LLM_TOOLS
443
+ LLM_TOKEN_COUNT_PROMPT = SpanAttributes.LLM_TOKEN_COUNT_PROMPT
444
+ LLM_TOKEN_COUNT_COMPLETION = SpanAttributes.LLM_TOKEN_COUNT_COMPLETION
445
+
446
+ MESSAGE_CONTENT = MessageAttributes.MESSAGE_CONTENT
447
+ MESSAGE_ROLE = MessageAttributes.MESSAGE_ROLE
448
+ MESSAGE_TOOL_CALLS = MessageAttributes.MESSAGE_TOOL_CALLS
449
+
450
+ TOOL_CALL_ID = ToolCallAttributes.TOOL_CALL_ID
451
+ TOOL_CALL_FUNCTION_NAME = ToolCallAttributes.TOOL_CALL_FUNCTION_NAME
452
+ TOOL_CALL_FUNCTION_ARGUMENTS_JSON = ToolCallAttributes.TOOL_CALL_FUNCTION_ARGUMENTS_JSON
453
+ TOOL_CALL_ID = ToolCallAttributes.TOOL_CALL_ID
454
+ MESSAGE_TOOL_CALL_ID = MessageAttributes.MESSAGE_TOOL_CALL_ID
455
+ TOOL_JSON_SCHEMA = ToolAttributes.TOOL_JSON_SCHEMA
@@ -0,0 +1,16 @@
1
+ from typing import Optional
2
+
3
+ import strawberry
4
+ from strawberry import UNSET
5
+ from strawberry.relay import GlobalID
6
+ from strawberry.scalars import JSON
7
+
8
+ from .DatasetExampleInput import DatasetExampleInput
9
+
10
+
11
+ @strawberry.input
12
+ class AddExamplesToDatasetInput:
13
+ dataset_id: GlobalID
14
+ examples: list[DatasetExampleInput]
15
+ dataset_version_description: Optional[str] = UNSET
16
+ dataset_version_metadata: Optional[JSON] = UNSET
@@ -0,0 +1,14 @@
1
+ from typing import Optional
2
+
3
+ import strawberry
4
+ from strawberry import UNSET
5
+ from strawberry.relay import GlobalID
6
+ from strawberry.scalars import JSON
7
+
8
+
9
+ @strawberry.input
10
+ class AddSpansToDatasetInput:
11
+ dataset_id: GlobalID
12
+ span_ids: list[GlobalID]
13
+ dataset_version_description: Optional[str] = UNSET
14
+ dataset_version_metadata: Optional[JSON] = UNSET
@@ -0,0 +1,38 @@
1
+ from typing import Optional
2
+
3
+ import strawberry
4
+ from strawberry import UNSET
5
+ from strawberry.relay.types import GlobalID
6
+ from strawberry.scalars import JSON
7
+
8
+ from phoenix.server.api.types.TemplateLanguage import TemplateLanguage
9
+
10
+ from .ChatCompletionMessageInput import ChatCompletionMessageInput
11
+ from .GenerativeModelInput import GenerativeModelInput
12
+ from .InvocationParameters import InvocationParameterInput
13
+ from .TemplateOptions import TemplateOptions
14
+
15
+
16
+ @strawberry.input
17
+ class ChatCompletionInput:
18
+ messages: list[ChatCompletionMessageInput]
19
+ model: GenerativeModelInput
20
+ invocation_parameters: list[InvocationParameterInput] = strawberry.field(default_factory=list)
21
+ tools: Optional[list[JSON]] = UNSET
22
+ api_key: Optional[str] = strawberry.field(default=None)
23
+ template: Optional[TemplateOptions] = UNSET
24
+
25
+
26
+ @strawberry.input
27
+ class ChatCompletionOverDatasetInput:
28
+ messages: list[ChatCompletionMessageInput]
29
+ model: GenerativeModelInput
30
+ invocation_parameters: list[InvocationParameterInput] = strawberry.field(default_factory=list)
31
+ tools: Optional[list[JSON]] = UNSET
32
+ api_key: Optional[str] = strawberry.field(default=None)
33
+ template_language: TemplateLanguage
34
+ dataset_id: GlobalID
35
+ dataset_version_id: Optional[GlobalID] = None
36
+ experiment_name: Optional[str] = None
37
+ experiment_description: Optional[str] = None
38
+ experiment_metadata: Optional[JSON] = strawberry.field(default_factory=dict)
@@ -0,0 +1,24 @@
1
+ from typing import Optional
2
+
3
+ import strawberry
4
+ from strawberry import UNSET
5
+ from strawberry.scalars import JSON
6
+
7
+ from phoenix.server.api.types.ChatCompletionMessageRole import ChatCompletionMessageRole
8
+
9
+
10
+ @strawberry.input
11
+ class ChatCompletionMessageInput:
12
+ role: ChatCompletionMessageRole
13
+ content: JSON = strawberry.field(
14
+ default="",
15
+ description="The content of the message as JSON to support various kinds of text",
16
+ )
17
+ tool_calls: Optional[list[JSON]] = strawberry.field(
18
+ description="The tool calls that were made in the message",
19
+ default=UNSET,
20
+ )
21
+ tool_call_id: Optional[str] = strawberry.field(
22
+ description="The ID that corresponds to a prior tool call. Used to link a tool message to a pre-existing tool call.", # noqa: E501
23
+ default=UNSET,
24
+ )
@@ -0,0 +1,15 @@
1
+ from datetime import datetime
2
+ from typing import Optional
3
+
4
+ import strawberry
5
+ from strawberry import UNSET
6
+ from strawberry.relay import GlobalID
7
+
8
+
9
+ @strawberry.input
10
+ class ClearProjectInput:
11
+ id: GlobalID
12
+ end_time: Optional[datetime] = strawberry.field(
13
+ default=UNSET,
14
+ description="The time up to which to purge data. Time is right-open /non-inclusive.",
15
+ )
@@ -1,4 +1,4 @@
1
- from typing import List, Optional
1
+ from typing import Optional
2
2
 
3
3
  import strawberry
4
4
  from strawberry import ID, UNSET
@@ -6,5 +6,5 @@ from strawberry import ID, UNSET
6
6
 
7
7
  @strawberry.input
8
8
  class ClusterInput:
9
- event_ids: List[ID]
9
+ event_ids: list[ID]
10
10
  id: Optional[ID] = UNSET
@@ -0,0 +1,12 @@
1
+ from typing import Optional
2
+
3
+ import strawberry
4
+ from strawberry import UNSET
5
+ from strawberry.scalars import JSON
6
+
7
+
8
+ @strawberry.input
9
+ class CreateDatasetInput:
10
+ name: str
11
+ description: Optional[str] = UNSET
12
+ metadata: Optional[JSON] = UNSET
@@ -0,0 +1,18 @@
1
+ from typing import Optional
2
+
3
+ import strawberry
4
+ from strawberry.relay import GlobalID
5
+ from strawberry.scalars import JSON
6
+
7
+ from phoenix.server.api.types.AnnotatorKind import AnnotatorKind
8
+
9
+
10
+ @strawberry.input
11
+ class CreateSpanAnnotationInput:
12
+ span_id: GlobalID
13
+ name: str
14
+ annotator_kind: AnnotatorKind
15
+ label: Optional[str] = None
16
+ score: Optional[float] = None
17
+ explanation: Optional[str] = None
18
+ metadata: JSON = strawberry.field(default_factory=dict)