arize-phoenix 11.23.1__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.
Files changed (221) hide show
  1. {arize_phoenix-11.23.1.dist-info → arize_phoenix-12.28.1.dist-info}/METADATA +61 -36
  2. {arize_phoenix-11.23.1.dist-info → arize_phoenix-12.28.1.dist-info}/RECORD +212 -162
  3. {arize_phoenix-11.23.1.dist-info → arize_phoenix-12.28.1.dist-info}/WHEEL +1 -1
  4. {arize_phoenix-11.23.1.dist-info → arize_phoenix-12.28.1.dist-info}/licenses/IP_NOTICE +1 -1
  5. phoenix/__generated__/__init__.py +0 -0
  6. phoenix/__generated__/classification_evaluator_configs/__init__.py +20 -0
  7. phoenix/__generated__/classification_evaluator_configs/_document_relevance_classification_evaluator_config.py +17 -0
  8. phoenix/__generated__/classification_evaluator_configs/_hallucination_classification_evaluator_config.py +17 -0
  9. phoenix/__generated__/classification_evaluator_configs/_models.py +18 -0
  10. phoenix/__generated__/classification_evaluator_configs/_tool_selection_classification_evaluator_config.py +17 -0
  11. phoenix/__init__.py +2 -1
  12. phoenix/auth.py +27 -2
  13. phoenix/config.py +1594 -81
  14. phoenix/db/README.md +546 -28
  15. phoenix/db/bulk_inserter.py +119 -116
  16. phoenix/db/engines.py +140 -33
  17. phoenix/db/facilitator.py +22 -1
  18. phoenix/db/helpers.py +818 -65
  19. phoenix/db/iam_auth.py +64 -0
  20. phoenix/db/insertion/dataset.py +133 -1
  21. phoenix/db/insertion/document_annotation.py +9 -6
  22. phoenix/db/insertion/evaluation.py +2 -3
  23. phoenix/db/insertion/helpers.py +2 -2
  24. phoenix/db/insertion/session_annotation.py +176 -0
  25. phoenix/db/insertion/span_annotation.py +3 -4
  26. phoenix/db/insertion/trace_annotation.py +3 -4
  27. phoenix/db/insertion/types.py +41 -18
  28. phoenix/db/migrations/versions/01a8342c9cdf_add_user_id_on_datasets.py +40 -0
  29. phoenix/db/migrations/versions/0df286449799_add_session_annotations_table.py +105 -0
  30. phoenix/db/migrations/versions/272b66ff50f8_drop_single_indices.py +119 -0
  31. phoenix/db/migrations/versions/58228d933c91_dataset_labels.py +67 -0
  32. phoenix/db/migrations/versions/699f655af132_experiment_tags.py +57 -0
  33. phoenix/db/migrations/versions/735d3d93c33e_add_composite_indices.py +41 -0
  34. phoenix/db/migrations/versions/ab513d89518b_add_user_id_on_dataset_versions.py +40 -0
  35. phoenix/db/migrations/versions/d0690a79ea51_users_on_experiments.py +40 -0
  36. phoenix/db/migrations/versions/deb2c81c0bb2_dataset_splits.py +139 -0
  37. phoenix/db/migrations/versions/e76cbd66ffc3_add_experiments_dataset_examples.py +87 -0
  38. phoenix/db/models.py +364 -56
  39. phoenix/db/pg_config.py +10 -0
  40. phoenix/db/types/trace_retention.py +7 -6
  41. phoenix/experiments/functions.py +69 -19
  42. phoenix/inferences/inferences.py +1 -2
  43. phoenix/server/api/auth.py +9 -0
  44. phoenix/server/api/auth_messages.py +46 -0
  45. phoenix/server/api/context.py +60 -0
  46. phoenix/server/api/dataloaders/__init__.py +36 -0
  47. phoenix/server/api/dataloaders/annotation_summaries.py +60 -8
  48. phoenix/server/api/dataloaders/average_experiment_repeated_run_group_latency.py +50 -0
  49. phoenix/server/api/dataloaders/average_experiment_run_latency.py +17 -24
  50. phoenix/server/api/dataloaders/cache/two_tier_cache.py +1 -2
  51. phoenix/server/api/dataloaders/dataset_dataset_splits.py +52 -0
  52. phoenix/server/api/dataloaders/dataset_example_revisions.py +0 -1
  53. phoenix/server/api/dataloaders/dataset_example_splits.py +40 -0
  54. phoenix/server/api/dataloaders/dataset_examples_and_versions_by_experiment_run.py +47 -0
  55. phoenix/server/api/dataloaders/dataset_labels.py +36 -0
  56. phoenix/server/api/dataloaders/document_evaluation_summaries.py +2 -2
  57. phoenix/server/api/dataloaders/document_evaluations.py +6 -9
  58. phoenix/server/api/dataloaders/experiment_annotation_summaries.py +88 -34
  59. phoenix/server/api/dataloaders/experiment_dataset_splits.py +43 -0
  60. phoenix/server/api/dataloaders/experiment_error_rates.py +21 -28
  61. phoenix/server/api/dataloaders/experiment_repeated_run_group_annotation_summaries.py +77 -0
  62. phoenix/server/api/dataloaders/experiment_repeated_run_groups.py +57 -0
  63. phoenix/server/api/dataloaders/experiment_runs_by_experiment_and_example.py +44 -0
  64. phoenix/server/api/dataloaders/latency_ms_quantile.py +40 -8
  65. phoenix/server/api/dataloaders/record_counts.py +37 -10
  66. phoenix/server/api/dataloaders/session_annotations_by_session.py +29 -0
  67. phoenix/server/api/dataloaders/span_cost_summary_by_experiment_repeated_run_group.py +64 -0
  68. phoenix/server/api/dataloaders/span_cost_summary_by_project.py +28 -14
  69. phoenix/server/api/dataloaders/span_costs.py +3 -9
  70. phoenix/server/api/dataloaders/table_fields.py +2 -2
  71. phoenix/server/api/dataloaders/token_prices_by_model.py +30 -0
  72. phoenix/server/api/dataloaders/trace_annotations_by_trace.py +27 -0
  73. phoenix/server/api/exceptions.py +5 -1
  74. phoenix/server/api/helpers/playground_clients.py +263 -83
  75. phoenix/server/api/helpers/playground_spans.py +2 -1
  76. phoenix/server/api/helpers/playground_users.py +26 -0
  77. phoenix/server/api/helpers/prompts/conversions/google.py +103 -0
  78. phoenix/server/api/helpers/prompts/models.py +61 -19
  79. phoenix/server/api/input_types/{SpanAnnotationFilter.py → AnnotationFilter.py} +22 -14
  80. phoenix/server/api/input_types/ChatCompletionInput.py +3 -0
  81. phoenix/server/api/input_types/CreateProjectSessionAnnotationInput.py +37 -0
  82. phoenix/server/api/input_types/DatasetFilter.py +5 -2
  83. phoenix/server/api/input_types/ExperimentRunSort.py +237 -0
  84. phoenix/server/api/input_types/GenerativeModelInput.py +3 -0
  85. phoenix/server/api/input_types/ProjectSessionSort.py +158 -1
  86. phoenix/server/api/input_types/PromptVersionInput.py +47 -1
  87. phoenix/server/api/input_types/SpanSort.py +3 -2
  88. phoenix/server/api/input_types/UpdateAnnotationInput.py +34 -0
  89. phoenix/server/api/input_types/UserRoleInput.py +1 -0
  90. phoenix/server/api/mutations/__init__.py +8 -0
  91. phoenix/server/api/mutations/annotation_config_mutations.py +8 -8
  92. phoenix/server/api/mutations/api_key_mutations.py +15 -20
  93. phoenix/server/api/mutations/chat_mutations.py +106 -37
  94. phoenix/server/api/mutations/dataset_label_mutations.py +243 -0
  95. phoenix/server/api/mutations/dataset_mutations.py +21 -16
  96. phoenix/server/api/mutations/dataset_split_mutations.py +351 -0
  97. phoenix/server/api/mutations/experiment_mutations.py +2 -2
  98. phoenix/server/api/mutations/export_events_mutations.py +3 -3
  99. phoenix/server/api/mutations/model_mutations.py +11 -9
  100. phoenix/server/api/mutations/project_mutations.py +4 -4
  101. phoenix/server/api/mutations/project_session_annotations_mutations.py +158 -0
  102. phoenix/server/api/mutations/project_trace_retention_policy_mutations.py +8 -4
  103. phoenix/server/api/mutations/prompt_label_mutations.py +74 -65
  104. phoenix/server/api/mutations/prompt_mutations.py +65 -129
  105. phoenix/server/api/mutations/prompt_version_tag_mutations.py +11 -8
  106. phoenix/server/api/mutations/span_annotations_mutations.py +15 -10
  107. phoenix/server/api/mutations/trace_annotations_mutations.py +13 -8
  108. phoenix/server/api/mutations/trace_mutations.py +3 -3
  109. phoenix/server/api/mutations/user_mutations.py +55 -26
  110. phoenix/server/api/queries.py +501 -617
  111. phoenix/server/api/routers/__init__.py +2 -2
  112. phoenix/server/api/routers/auth.py +141 -87
  113. phoenix/server/api/routers/ldap.py +229 -0
  114. phoenix/server/api/routers/oauth2.py +349 -101
  115. phoenix/server/api/routers/v1/__init__.py +22 -4
  116. phoenix/server/api/routers/v1/annotation_configs.py +19 -30
  117. phoenix/server/api/routers/v1/annotations.py +455 -13
  118. phoenix/server/api/routers/v1/datasets.py +355 -68
  119. phoenix/server/api/routers/v1/documents.py +142 -0
  120. phoenix/server/api/routers/v1/evaluations.py +20 -28
  121. phoenix/server/api/routers/v1/experiment_evaluations.py +16 -6
  122. phoenix/server/api/routers/v1/experiment_runs.py +335 -59
  123. phoenix/server/api/routers/v1/experiments.py +475 -47
  124. phoenix/server/api/routers/v1/projects.py +16 -50
  125. phoenix/server/api/routers/v1/prompts.py +50 -39
  126. phoenix/server/api/routers/v1/sessions.py +108 -0
  127. phoenix/server/api/routers/v1/spans.py +156 -96
  128. phoenix/server/api/routers/v1/traces.py +51 -77
  129. phoenix/server/api/routers/v1/users.py +64 -24
  130. phoenix/server/api/routers/v1/utils.py +3 -7
  131. phoenix/server/api/subscriptions.py +257 -93
  132. phoenix/server/api/types/Annotation.py +90 -23
  133. phoenix/server/api/types/ApiKey.py +13 -17
  134. phoenix/server/api/types/AuthMethod.py +1 -0
  135. phoenix/server/api/types/ChatCompletionSubscriptionPayload.py +1 -0
  136. phoenix/server/api/types/Dataset.py +199 -72
  137. phoenix/server/api/types/DatasetExample.py +88 -18
  138. phoenix/server/api/types/DatasetExperimentAnnotationSummary.py +10 -0
  139. phoenix/server/api/types/DatasetLabel.py +57 -0
  140. phoenix/server/api/types/DatasetSplit.py +98 -0
  141. phoenix/server/api/types/DatasetVersion.py +49 -4
  142. phoenix/server/api/types/DocumentAnnotation.py +212 -0
  143. phoenix/server/api/types/Experiment.py +215 -68
  144. phoenix/server/api/types/ExperimentComparison.py +3 -9
  145. phoenix/server/api/types/ExperimentRepeatedRunGroup.py +155 -0
  146. phoenix/server/api/types/ExperimentRepeatedRunGroupAnnotationSummary.py +9 -0
  147. phoenix/server/api/types/ExperimentRun.py +120 -70
  148. phoenix/server/api/types/ExperimentRunAnnotation.py +158 -39
  149. phoenix/server/api/types/GenerativeModel.py +95 -42
  150. phoenix/server/api/types/GenerativeProvider.py +1 -1
  151. phoenix/server/api/types/ModelInterface.py +7 -2
  152. phoenix/server/api/types/PlaygroundModel.py +12 -2
  153. phoenix/server/api/types/Project.py +218 -185
  154. phoenix/server/api/types/ProjectSession.py +146 -29
  155. phoenix/server/api/types/ProjectSessionAnnotation.py +187 -0
  156. phoenix/server/api/types/ProjectTraceRetentionPolicy.py +1 -1
  157. phoenix/server/api/types/Prompt.py +119 -39
  158. phoenix/server/api/types/PromptLabel.py +42 -25
  159. phoenix/server/api/types/PromptVersion.py +11 -8
  160. phoenix/server/api/types/PromptVersionTag.py +65 -25
  161. phoenix/server/api/types/Span.py +130 -123
  162. phoenix/server/api/types/SpanAnnotation.py +189 -42
  163. phoenix/server/api/types/SystemApiKey.py +65 -1
  164. phoenix/server/api/types/Trace.py +184 -53
  165. phoenix/server/api/types/TraceAnnotation.py +149 -50
  166. phoenix/server/api/types/User.py +128 -33
  167. phoenix/server/api/types/UserApiKey.py +73 -26
  168. phoenix/server/api/types/node.py +10 -0
  169. phoenix/server/api/types/pagination.py +11 -2
  170. phoenix/server/app.py +154 -36
  171. phoenix/server/authorization.py +5 -4
  172. phoenix/server/bearer_auth.py +13 -5
  173. phoenix/server/cost_tracking/cost_model_lookup.py +42 -14
  174. phoenix/server/cost_tracking/model_cost_manifest.json +1085 -194
  175. phoenix/server/daemons/generative_model_store.py +61 -9
  176. phoenix/server/daemons/span_cost_calculator.py +10 -8
  177. phoenix/server/dml_event.py +13 -0
  178. phoenix/server/email/sender.py +29 -2
  179. phoenix/server/grpc_server.py +9 -9
  180. phoenix/server/jwt_store.py +8 -6
  181. phoenix/server/ldap.py +1449 -0
  182. phoenix/server/main.py +9 -3
  183. phoenix/server/oauth2.py +330 -12
  184. phoenix/server/prometheus.py +43 -6
  185. phoenix/server/rate_limiters.py +4 -9
  186. phoenix/server/retention.py +33 -20
  187. phoenix/server/session_filters.py +49 -0
  188. phoenix/server/static/.vite/manifest.json +51 -53
  189. phoenix/server/static/assets/components-BreFUQQa.js +6702 -0
  190. phoenix/server/static/assets/{index-BPCwGQr8.js → index-CTQoemZv.js} +42 -35
  191. phoenix/server/static/assets/pages-DBE5iYM3.js +9524 -0
  192. phoenix/server/static/assets/vendor-BGzfc4EU.css +1 -0
  193. phoenix/server/static/assets/vendor-DCE4v-Ot.js +920 -0
  194. phoenix/server/static/assets/vendor-codemirror-D5f205eT.js +25 -0
  195. phoenix/server/static/assets/{vendor-recharts-Bw30oz1A.js → vendor-recharts-V9cwpXsm.js} +7 -7
  196. phoenix/server/static/assets/{vendor-shiki-DZajAPeq.js → vendor-shiki-Do--csgv.js} +1 -1
  197. phoenix/server/static/assets/vendor-three-CmB8bl_y.js +3840 -0
  198. phoenix/server/templates/index.html +7 -1
  199. phoenix/server/thread_server.py +1 -2
  200. phoenix/server/utils.py +74 -0
  201. phoenix/session/client.py +55 -1
  202. phoenix/session/data_extractor.py +5 -0
  203. phoenix/session/evaluation.py +8 -4
  204. phoenix/session/session.py +44 -8
  205. phoenix/settings.py +2 -0
  206. phoenix/trace/attributes.py +80 -13
  207. phoenix/trace/dsl/query.py +2 -0
  208. phoenix/trace/projects.py +5 -0
  209. phoenix/utilities/template_formatters.py +1 -1
  210. phoenix/version.py +1 -1
  211. phoenix/server/api/types/Evaluation.py +0 -39
  212. phoenix/server/static/assets/components-D0DWAf0l.js +0 -5650
  213. phoenix/server/static/assets/pages-Creyamao.js +0 -8612
  214. phoenix/server/static/assets/vendor-CU36oj8y.js +0 -905
  215. phoenix/server/static/assets/vendor-CqDb5u4o.css +0 -1
  216. phoenix/server/static/assets/vendor-arizeai-Ctgw0e1G.js +0 -168
  217. phoenix/server/static/assets/vendor-codemirror-Cojjzqb9.js +0 -25
  218. phoenix/server/static/assets/vendor-three-BLWp5bic.js +0 -2998
  219. phoenix/utilities/deprecation.py +0 -31
  220. {arize_phoenix-11.23.1.dist-info → arize_phoenix-12.28.1.dist-info}/entry_points.txt +0 -0
  221. {arize_phoenix-11.23.1.dist-info → arize_phoenix-12.28.1.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,98 @@
1
+ from datetime import datetime
2
+ from typing import Optional
3
+
4
+ import strawberry
5
+ from strawberry.relay import Node, NodeID
6
+ from strawberry.scalars import JSON
7
+ from strawberry.types import Info
8
+
9
+ from phoenix.db import models
10
+ from phoenix.server.api.context import Context
11
+
12
+
13
+ @strawberry.type
14
+ class DatasetSplit(Node):
15
+ id: NodeID[int]
16
+ db_record: strawberry.Private[Optional[models.DatasetSplit]] = None
17
+
18
+ def __post_init__(self) -> None:
19
+ if self.db_record and self.id != self.db_record.id:
20
+ raise ValueError("DatasetSplit ID mismatch")
21
+
22
+ @strawberry.field
23
+ async def name(
24
+ self,
25
+ info: Info[Context, None],
26
+ ) -> str:
27
+ if self.db_record:
28
+ val = self.db_record.name
29
+ else:
30
+ val = await info.context.data_loaders.dataset_split_fields.load(
31
+ (self.id, models.DatasetSplit.name),
32
+ )
33
+ return val
34
+
35
+ @strawberry.field
36
+ async def description(
37
+ self,
38
+ info: Info[Context, None],
39
+ ) -> Optional[str]:
40
+ if self.db_record:
41
+ val = self.db_record.description
42
+ else:
43
+ val = await info.context.data_loaders.dataset_split_fields.load(
44
+ (self.id, models.DatasetSplit.description),
45
+ )
46
+ return val
47
+
48
+ @strawberry.field
49
+ async def metadata(
50
+ self,
51
+ info: Info[Context, None],
52
+ ) -> JSON:
53
+ if self.db_record:
54
+ val = self.db_record.metadata_
55
+ else:
56
+ val = await info.context.data_loaders.dataset_split_fields.load(
57
+ (self.id, models.DatasetSplit.metadata_),
58
+ )
59
+ return val
60
+
61
+ @strawberry.field
62
+ async def color(
63
+ self,
64
+ info: Info[Context, None],
65
+ ) -> str:
66
+ if self.db_record:
67
+ val = self.db_record.color
68
+ else:
69
+ val = await info.context.data_loaders.dataset_split_fields.load(
70
+ (self.id, models.DatasetSplit.color),
71
+ )
72
+ return val
73
+
74
+ @strawberry.field
75
+ async def created_at(
76
+ self,
77
+ info: Info[Context, None],
78
+ ) -> datetime:
79
+ if self.db_record:
80
+ val = self.db_record.created_at
81
+ else:
82
+ val = await info.context.data_loaders.dataset_split_fields.load(
83
+ (self.id, models.DatasetSplit.created_at),
84
+ )
85
+ return val
86
+
87
+ @strawberry.field
88
+ async def updated_at(
89
+ self,
90
+ info: Info[Context, None],
91
+ ) -> datetime:
92
+ if self.db_record:
93
+ val = self.db_record.updated_at
94
+ else:
95
+ val = await info.context.data_loaders.dataset_split_fields.load(
96
+ (self.id, models.DatasetSplit.updated_at),
97
+ )
98
+ return val
@@ -4,11 +4,56 @@ from typing import Optional
4
4
  import strawberry
5
5
  from strawberry.relay import Node, NodeID
6
6
  from strawberry.scalars import JSON
7
+ from strawberry.types import Info
8
+
9
+ from phoenix.db import models
10
+ from phoenix.server.api.context import Context
7
11
 
8
12
 
9
13
  @strawberry.type
10
14
  class DatasetVersion(Node):
11
- id_attr: NodeID[int]
12
- description: Optional[str]
13
- metadata: JSON
14
- created_at: datetime
15
+ id: NodeID[int]
16
+ db_record: strawberry.Private[Optional[models.DatasetVersion]] = None
17
+
18
+ def __post_init__(self) -> None:
19
+ if self.db_record and self.id != self.db_record.id:
20
+ raise ValueError("DatasetVersion ID mismatch")
21
+
22
+ @strawberry.field
23
+ async def description(
24
+ self,
25
+ info: Info[Context, None],
26
+ ) -> Optional[str]:
27
+ if self.db_record:
28
+ val = self.db_record.description
29
+ else:
30
+ val = await info.context.data_loaders.dataset_version_fields.load(
31
+ (self.id, models.DatasetVersion.description),
32
+ )
33
+ return val
34
+
35
+ @strawberry.field
36
+ async def metadata(
37
+ self,
38
+ info: Info[Context, None],
39
+ ) -> JSON:
40
+ if self.db_record:
41
+ val = self.db_record.metadata_
42
+ else:
43
+ val = await info.context.data_loaders.dataset_version_fields.load(
44
+ (self.id, models.DatasetVersion.metadata_),
45
+ )
46
+ return val
47
+
48
+ @strawberry.field
49
+ async def created_at(
50
+ self,
51
+ info: Info[Context, None],
52
+ ) -> datetime:
53
+ if self.db_record:
54
+ val = self.db_record.created_at
55
+ else:
56
+ val = await info.context.data_loaders.dataset_version_fields.load(
57
+ (self.id, models.DatasetVersion.created_at),
58
+ )
59
+ return val
@@ -0,0 +1,212 @@
1
+ from datetime import datetime
2
+ from math import isfinite
3
+ from typing import TYPE_CHECKING, Annotated, Optional
4
+
5
+ import strawberry
6
+ from strawberry.relay import Node, NodeID
7
+ from strawberry.scalars import JSON
8
+ from strawberry.types import Info
9
+
10
+ from phoenix.db import models
11
+ from phoenix.server.api.context import Context
12
+
13
+ from .Annotation import Annotation
14
+ from .AnnotationSource import AnnotationSource
15
+ from .AnnotatorKind import AnnotatorKind
16
+
17
+ if TYPE_CHECKING:
18
+ from .Span import Span
19
+ from .User import User
20
+
21
+
22
+ @strawberry.type
23
+ class DocumentAnnotation(Node, Annotation):
24
+ id: NodeID[int]
25
+ db_record: strawberry.Private[Optional[models.DocumentAnnotation]] = None
26
+
27
+ def __post_init__(self) -> None:
28
+ if self.db_record and self.id != self.db_record.id:
29
+ raise ValueError("DocumentAnnotation ID mismatch")
30
+
31
+ @strawberry.field(description="Name of the annotation, e.g. 'helpfulness' or 'relevance'.") # type: ignore
32
+ async def name(
33
+ self,
34
+ info: Info[Context, None],
35
+ ) -> str:
36
+ if self.db_record:
37
+ val = self.db_record.name
38
+ else:
39
+ val = await info.context.data_loaders.document_annotation_fields.load(
40
+ (self.id, models.DocumentAnnotation.name),
41
+ )
42
+ return val
43
+
44
+ @strawberry.field(description="The kind of annotator that produced the annotation.") # type: ignore
45
+ async def annotator_kind(
46
+ self,
47
+ info: Info[Context, None],
48
+ ) -> AnnotatorKind:
49
+ if self.db_record:
50
+ val = self.db_record.annotator_kind
51
+ else:
52
+ val = await info.context.data_loaders.document_annotation_fields.load(
53
+ (self.id, models.DocumentAnnotation.annotator_kind),
54
+ )
55
+ return AnnotatorKind(val)
56
+
57
+ @strawberry.field(
58
+ description="Value of the annotation in the form of a string, e.g. "
59
+ "'helpful' or 'not helpful'. Note that the label is not necessarily binary."
60
+ ) # type: ignore
61
+ async def label(
62
+ self,
63
+ info: Info[Context, None],
64
+ ) -> Optional[str]:
65
+ if self.db_record:
66
+ val = self.db_record.label
67
+ else:
68
+ val = await info.context.data_loaders.document_annotation_fields.load(
69
+ (self.id, models.DocumentAnnotation.label),
70
+ )
71
+ return val
72
+
73
+ @strawberry.field(
74
+ description="Value of the annotation in the form of a numeric score.",
75
+ ) # type: ignore
76
+ async def score(
77
+ self,
78
+ info: Info[Context, None],
79
+ ) -> Optional[float]:
80
+ if self.db_record:
81
+ val = self.db_record.score
82
+ else:
83
+ val = await info.context.data_loaders.document_annotation_fields.load(
84
+ (self.id, models.DocumentAnnotation.score),
85
+ )
86
+ return val if val is not None and isfinite(val) else None
87
+
88
+ @strawberry.field(
89
+ description="The annotator's explanation for the annotation result (i.e. "
90
+ "score or label, or both) given to the subject."
91
+ ) # type: ignore
92
+ async def explanation(
93
+ self,
94
+ info: Info[Context, None],
95
+ ) -> Optional[str]:
96
+ if self.db_record:
97
+ val = self.db_record.explanation
98
+ else:
99
+ val = await info.context.data_loaders.document_annotation_fields.load(
100
+ (self.id, models.DocumentAnnotation.explanation),
101
+ )
102
+ return val
103
+
104
+ @strawberry.field(description="The metadata associated with the annotation.") # type: ignore
105
+ async def metadata(
106
+ self,
107
+ info: Info[Context, None],
108
+ ) -> JSON:
109
+ if self.db_record:
110
+ val = self.db_record.metadata_
111
+ else:
112
+ val = await info.context.data_loaders.document_annotation_fields.load(
113
+ (self.id, models.DocumentAnnotation.metadata_),
114
+ )
115
+ return val
116
+
117
+ @strawberry.field(description="The position of the annotation in the document.") # type: ignore
118
+ async def document_position(
119
+ self,
120
+ info: Info[Context, None],
121
+ ) -> int:
122
+ if self.db_record:
123
+ val = self.db_record.document_position
124
+ else:
125
+ val = await info.context.data_loaders.document_annotation_fields.load(
126
+ (self.id, models.DocumentAnnotation.document_position),
127
+ )
128
+ return val
129
+
130
+ @strawberry.field(description="The identifier of the annotation.") # type: ignore
131
+ async def identifier(
132
+ self,
133
+ info: Info[Context, None],
134
+ ) -> str:
135
+ if self.db_record:
136
+ val = self.db_record.identifier
137
+ else:
138
+ val = await info.context.data_loaders.document_annotation_fields.load(
139
+ (self.id, models.DocumentAnnotation.identifier),
140
+ )
141
+ return val
142
+
143
+ @strawberry.field(description="The source of the annotation.") # type: ignore
144
+ async def source(
145
+ self,
146
+ info: Info[Context, None],
147
+ ) -> AnnotationSource:
148
+ if self.db_record:
149
+ val = self.db_record.source
150
+ else:
151
+ val = await info.context.data_loaders.document_annotation_fields.load(
152
+ (self.id, models.DocumentAnnotation.source),
153
+ )
154
+ return AnnotationSource(val)
155
+
156
+ @strawberry.field(description="The date and time when the annotation was created.") # type: ignore
157
+ async def created_at(
158
+ self,
159
+ info: Info[Context, None],
160
+ ) -> datetime:
161
+ if self.db_record:
162
+ val = self.db_record.created_at
163
+ else:
164
+ val = await info.context.data_loaders.document_annotation_fields.load(
165
+ (self.id, models.DocumentAnnotation.created_at),
166
+ )
167
+ return val
168
+
169
+ @strawberry.field(description="The date and time when the annotation was last updated.") # type: ignore
170
+ async def updated_at(
171
+ self,
172
+ info: Info[Context, None],
173
+ ) -> datetime:
174
+ if self.db_record:
175
+ val = self.db_record.updated_at
176
+ else:
177
+ val = await info.context.data_loaders.document_annotation_fields.load(
178
+ (self.id, models.DocumentAnnotation.updated_at),
179
+ )
180
+ return val
181
+
182
+ @strawberry.field(description="The span associated with the annotation.") # type: ignore
183
+ async def span(
184
+ self,
185
+ info: Info[Context, None],
186
+ ) -> Annotated["Span", strawberry.lazy(".Span")]:
187
+ if self.db_record:
188
+ span_rowid = self.db_record.span_rowid
189
+ else:
190
+ span_rowid = await info.context.data_loaders.document_annotation_fields.load(
191
+ (self.id, models.DocumentAnnotation.span_rowid),
192
+ )
193
+ from .Span import Span
194
+
195
+ return Span(id=span_rowid)
196
+
197
+ @strawberry.field(description="The user that produced the annotation.") # type: ignore
198
+ async def user(
199
+ self,
200
+ info: Info[Context, None],
201
+ ) -> Optional[Annotated["User", strawberry.lazy(".User")]]:
202
+ if self.db_record:
203
+ user_id = self.db_record.user_id
204
+ else:
205
+ user_id = await info.context.data_loaders.document_annotation_fields.load(
206
+ (self.id, models.DocumentAnnotation.user_id),
207
+ )
208
+ if user_id is None:
209
+ return None
210
+ from .User import User
211
+
212
+ return User(id=user_id)