arize-phoenix 8.32.1__py3-none-any.whl → 9.0.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 (79) hide show
  1. {arize_phoenix-8.32.1.dist-info → arize_phoenix-9.0.0.dist-info}/METADATA +2 -2
  2. {arize_phoenix-8.32.1.dist-info → arize_phoenix-9.0.0.dist-info}/RECORD +76 -56
  3. phoenix/db/constants.py +1 -0
  4. phoenix/db/facilitator.py +55 -0
  5. phoenix/db/insertion/document_annotation.py +31 -13
  6. phoenix/db/insertion/evaluation.py +15 -3
  7. phoenix/db/insertion/helpers.py +2 -1
  8. phoenix/db/insertion/span_annotation.py +26 -9
  9. phoenix/db/insertion/trace_annotation.py +25 -9
  10. phoenix/db/insertion/types.py +7 -0
  11. phoenix/db/migrations/versions/2f9d1a65945f_annotation_config_migration.py +322 -0
  12. phoenix/db/migrations/versions/8a3764fe7f1a_change_jsonb_to_json_for_prompts.py +76 -0
  13. phoenix/db/migrations/versions/bb8139330879_create_project_trace_retention_policies_table.py +77 -0
  14. phoenix/db/models.py +151 -10
  15. phoenix/db/types/annotation_configs.py +97 -0
  16. phoenix/db/types/db_models.py +41 -0
  17. phoenix/db/types/trace_retention.py +267 -0
  18. phoenix/experiments/functions.py +5 -1
  19. phoenix/server/api/auth.py +9 -0
  20. phoenix/server/api/context.py +5 -0
  21. phoenix/server/api/dataloaders/__init__.py +4 -0
  22. phoenix/server/api/dataloaders/annotation_summaries.py +203 -24
  23. phoenix/server/api/dataloaders/project_ids_by_trace_retention_policy_id.py +42 -0
  24. phoenix/server/api/dataloaders/trace_retention_policy_id_by_project_id.py +34 -0
  25. phoenix/server/api/helpers/annotations.py +9 -0
  26. phoenix/server/api/helpers/prompts/models.py +34 -67
  27. phoenix/server/api/input_types/CreateSpanAnnotationInput.py +9 -0
  28. phoenix/server/api/input_types/CreateTraceAnnotationInput.py +3 -0
  29. phoenix/server/api/input_types/PatchAnnotationInput.py +3 -0
  30. phoenix/server/api/input_types/SpanAnnotationFilter.py +67 -0
  31. phoenix/server/api/mutations/__init__.py +6 -0
  32. phoenix/server/api/mutations/annotation_config_mutations.py +413 -0
  33. phoenix/server/api/mutations/dataset_mutations.py +62 -39
  34. phoenix/server/api/mutations/project_trace_retention_policy_mutations.py +245 -0
  35. phoenix/server/api/mutations/span_annotations_mutations.py +272 -70
  36. phoenix/server/api/mutations/trace_annotations_mutations.py +203 -74
  37. phoenix/server/api/queries.py +86 -0
  38. phoenix/server/api/routers/v1/__init__.py +4 -0
  39. phoenix/server/api/routers/v1/annotation_configs.py +449 -0
  40. phoenix/server/api/routers/v1/annotations.py +161 -0
  41. phoenix/server/api/routers/v1/evaluations.py +6 -0
  42. phoenix/server/api/routers/v1/projects.py +1 -50
  43. phoenix/server/api/routers/v1/spans.py +35 -8
  44. phoenix/server/api/routers/v1/traces.py +22 -13
  45. phoenix/server/api/routers/v1/utils.py +60 -0
  46. phoenix/server/api/types/Annotation.py +7 -0
  47. phoenix/server/api/types/AnnotationConfig.py +124 -0
  48. phoenix/server/api/types/AnnotationSource.py +9 -0
  49. phoenix/server/api/types/AnnotationSummary.py +28 -14
  50. phoenix/server/api/types/AnnotatorKind.py +1 -0
  51. phoenix/server/api/types/CronExpression.py +15 -0
  52. phoenix/server/api/types/Evaluation.py +4 -30
  53. phoenix/server/api/types/Project.py +50 -2
  54. phoenix/server/api/types/ProjectTraceRetentionPolicy.py +110 -0
  55. phoenix/server/api/types/Span.py +78 -0
  56. phoenix/server/api/types/SpanAnnotation.py +24 -0
  57. phoenix/server/api/types/Trace.py +2 -2
  58. phoenix/server/api/types/TraceAnnotation.py +23 -0
  59. phoenix/server/app.py +20 -0
  60. phoenix/server/retention.py +76 -0
  61. phoenix/server/static/.vite/manifest.json +36 -36
  62. phoenix/server/static/assets/components-B2MWTXnm.js +4326 -0
  63. phoenix/server/static/assets/{index-B0CbpsxD.js → index-Bfvpea_-.js} +10 -10
  64. phoenix/server/static/assets/pages-CZ2vKu8H.js +7268 -0
  65. phoenix/server/static/assets/vendor-BRDkBC5J.js +903 -0
  66. phoenix/server/static/assets/{vendor-arizeai-CxXYQNUl.js → vendor-arizeai-BvTqp_W8.js} +3 -3
  67. phoenix/server/static/assets/{vendor-codemirror-B0NIFPOL.js → vendor-codemirror-COt9UfW7.js} +1 -1
  68. phoenix/server/static/assets/{vendor-recharts-CrrDFWK1.js → vendor-recharts-BoHX9Hvs.js} +2 -2
  69. phoenix/server/static/assets/{vendor-shiki-C5bJ-RPf.js → vendor-shiki-Cw1dsDAz.js} +1 -1
  70. phoenix/trace/dsl/filter.py +25 -5
  71. phoenix/utilities/__init__.py +18 -0
  72. phoenix/version.py +1 -1
  73. phoenix/server/static/assets/components-x-gKFJ8C.js +0 -3414
  74. phoenix/server/static/assets/pages-BU4VdyeH.js +0 -5867
  75. phoenix/server/static/assets/vendor-BfhM_F1u.js +0 -902
  76. {arize_phoenix-8.32.1.dist-info → arize_phoenix-9.0.0.dist-info}/WHEEL +0 -0
  77. {arize_phoenix-8.32.1.dist-info → arize_phoenix-9.0.0.dist-info}/entry_points.txt +0 -0
  78. {arize_phoenix-8.32.1.dist-info → arize_phoenix-9.0.0.dist-info}/licenses/IP_NOTICE +0 -0
  79. {arize_phoenix-8.32.1.dist-info → arize_phoenix-9.0.0.dist-info}/licenses/LICENSE +0 -0
@@ -3,9 +3,10 @@ from __future__ import annotations
3
3
  from enum import Enum
4
4
  from typing import Any, Literal, Mapping, Optional, Union
5
5
 
6
- from pydantic import BaseModel, ConfigDict, Field, RootModel, model_validator
6
+ from pydantic import Field, RootModel, model_validator
7
7
  from typing_extensions import Annotated, Self, TypeAlias, TypeGuard, assert_never
8
8
 
9
+ from phoenix.db.types.db_models import UNDEFINED, DBBaseModel
9
10
  from phoenix.db.types.model_provider import ModelProvider
10
11
  from phoenix.server.api.helpers.prompts.conversions.anthropic import AnthropicToolChoiceConversion
11
12
  from phoenix.server.api.helpers.prompts.conversions.openai import OpenAIToolChoiceConversion
@@ -13,25 +14,6 @@ from phoenix.server.api.helpers.prompts.conversions.openai import OpenAIToolChoi
13
14
  JSONSerializable = Union[None, bool, int, float, str, dict[str, Any], list[Any]]
14
15
 
15
16
 
16
- class Undefined:
17
- """
18
- A singleton class that represents an unset or undefined value. Needed since Pydantic
19
- can't natively distinguish between an undefined value and a value that is set to
20
- None.
21
- """
22
-
23
- def __new__(cls) -> Any:
24
- if not hasattr(cls, "_instance"):
25
- cls._instance = super().__new__(cls)
26
- return cls._instance
27
-
28
- def __bool__(self) -> bool:
29
- return False
30
-
31
-
32
- UNDEFINED: Any = Undefined()
33
-
34
-
35
17
  class PromptTemplateType(str, Enum):
36
18
  STRING = "STR"
37
19
  CHAT = "CHAT"
@@ -50,33 +32,18 @@ class PromptTemplateFormat(str, Enum):
50
32
  NONE = "NONE"
51
33
 
52
34
 
53
- class PromptModel(BaseModel):
54
- model_config = ConfigDict(
55
- extra="forbid", # disallow extra attributes
56
- use_enum_values=True,
57
- validate_assignment=True,
58
- )
59
-
60
- def __init__(self, *args: Any, **kwargs: Any) -> None:
61
- kwargs = {k: v for k, v in kwargs.items() if v is not UNDEFINED}
62
- super().__init__(*args, **kwargs)
63
-
64
- def model_dump(self, *args: Any, **kwargs: Any) -> dict[str, Any]:
65
- return super().model_dump(*args, exclude_unset=True, by_alias=True, **kwargs)
66
-
67
-
68
- class TextContentPart(PromptModel):
35
+ class TextContentPart(DBBaseModel):
69
36
  type: Literal["text"]
70
37
  text: str
71
38
 
72
39
 
73
- class ToolCallFunction(PromptModel):
40
+ class ToolCallFunction(DBBaseModel):
74
41
  type: Literal["function"]
75
42
  name: str
76
43
  arguments: str
77
44
 
78
45
 
79
- class ToolCallContentPart(PromptModel):
46
+ class ToolCallContentPart(DBBaseModel):
80
47
  type: Literal["tool_call"]
81
48
  tool_call_id: str
82
49
  tool_call: Annotated[
@@ -85,7 +52,7 @@ class ToolCallContentPart(PromptModel):
85
52
  ]
86
53
 
87
54
 
88
- class ToolResultContentPart(PromptModel):
55
+ class ToolResultContentPart(DBBaseModel):
89
56
  type: Literal["tool_result"]
90
57
  tool_call_id: str
91
58
  tool_result: JSONSerializable
@@ -131,17 +98,17 @@ class RoleConversion:
131
98
  assert_never(role)
132
99
 
133
100
 
134
- class PromptMessage(PromptModel):
101
+ class PromptMessage(DBBaseModel):
135
102
  role: Role
136
103
  content: Union[str, Annotated[list[ContentPart], Field(..., min_length=1)]]
137
104
 
138
105
 
139
- class PromptChatTemplate(PromptModel):
106
+ class PromptChatTemplate(DBBaseModel):
140
107
  type: Literal["chat"]
141
108
  messages: list[PromptMessage]
142
109
 
143
110
 
144
- class PromptStringTemplate(PromptModel):
111
+ class PromptStringTemplate(DBBaseModel):
145
112
  type: Literal["string"]
146
113
  template: str
147
114
 
@@ -159,12 +126,12 @@ class PromptTemplateRootModel(RootModel[PromptTemplate]):
159
126
  root: PromptTemplate
160
127
 
161
128
 
162
- class PromptToolFunction(PromptModel):
129
+ class PromptToolFunction(DBBaseModel):
163
130
  type: Literal["function"]
164
131
  function: PromptToolFunctionDefinition
165
132
 
166
133
 
167
- class PromptToolFunctionDefinition(PromptModel):
134
+ class PromptToolFunctionDefinition(DBBaseModel):
168
135
  name: str
169
136
  description: str = UNDEFINED
170
137
  parameters: dict[str, Any] = UNDEFINED
@@ -174,26 +141,26 @@ class PromptToolFunctionDefinition(PromptModel):
174
141
  PromptTool: TypeAlias = Annotated[Union[PromptToolFunction], Field(..., discriminator="type")]
175
142
 
176
143
 
177
- class PromptTools(PromptModel):
144
+ class PromptTools(DBBaseModel):
178
145
  type: Literal["tools"]
179
146
  tools: Annotated[list[PromptTool], Field(..., min_length=1)]
180
147
  tool_choice: PromptToolChoice = UNDEFINED
181
148
  disable_parallel_tool_calls: bool = UNDEFINED
182
149
 
183
150
 
184
- class PromptToolChoiceNone(PromptModel):
151
+ class PromptToolChoiceNone(DBBaseModel):
185
152
  type: Literal["none"]
186
153
 
187
154
 
188
- class PromptToolChoiceZeroOrMore(PromptModel):
155
+ class PromptToolChoiceZeroOrMore(DBBaseModel):
189
156
  type: Literal["zero_or_more"]
190
157
 
191
158
 
192
- class PromptToolChoiceOneOrMore(PromptModel):
159
+ class PromptToolChoiceOneOrMore(DBBaseModel):
193
160
  type: Literal["one_or_more"]
194
161
 
195
162
 
196
- class PromptToolChoiceSpecificFunctionTool(PromptModel):
163
+ class PromptToolChoiceSpecificFunctionTool(DBBaseModel):
197
164
  type: Literal["specific_function"]
198
165
  function_name: str
199
166
 
@@ -209,7 +176,7 @@ PromptToolChoice: TypeAlias = Annotated[
209
176
  ]
210
177
 
211
178
 
212
- class PromptOpenAIJSONSchema(PromptModel):
179
+ class PromptOpenAIJSONSchema(DBBaseModel):
213
180
  """
214
181
  Based on https://github.com/openai/openai-python/blob/d16e6edde5a155626910b5758a0b939bfedb9ced/src/openai/types/shared/response_format_json_schema.py#L13
215
182
  """
@@ -223,7 +190,7 @@ class PromptOpenAIJSONSchema(PromptModel):
223
190
  strict: Optional[bool] = UNDEFINED
224
191
 
225
192
 
226
- class PromptOpenAIResponseFormatJSONSchema(PromptModel):
193
+ class PromptOpenAIResponseFormatJSONSchema(DBBaseModel):
227
194
  """
228
195
  Based on https://github.com/openai/openai-python/blob/d16e6edde5a155626910b5758a0b939bfedb9ced/src/openai/types/shared/response_format_json_schema.py#L40
229
196
  """
@@ -232,12 +199,12 @@ class PromptOpenAIResponseFormatJSONSchema(PromptModel):
232
199
  type: Literal["json_schema"]
233
200
 
234
201
 
235
- class PromptResponseFormatJSONSchema(PromptModel):
202
+ class PromptResponseFormatJSONSchema(DBBaseModel):
236
203
  type: Literal["json_schema"]
237
204
  json_schema: PromptResponseFormatJSONSchemaDefinition
238
205
 
239
206
 
240
- class PromptResponseFormatJSONSchemaDefinition(PromptModel):
207
+ class PromptResponseFormatJSONSchemaDefinition(DBBaseModel):
241
208
  name: str
242
209
  description: str = UNDEFINED
243
210
  schema_: dict[str, Any] = Field(UNDEFINED, alias="schema")
@@ -305,7 +272,7 @@ def denormalize_response_format(
305
272
 
306
273
 
307
274
  # OpenAI tool definitions
308
- class OpenAIFunctionDefinition(PromptModel):
275
+ class OpenAIFunctionDefinition(DBBaseModel):
309
276
  """
310
277
  Based on https://github.com/openai/openai-python/blob/1e07c9d839e7e96f02d0a4b745f379a43086334c/src/openai/types/shared_params/function_definition.py#L13
311
278
  """
@@ -316,7 +283,7 @@ class OpenAIFunctionDefinition(PromptModel):
316
283
  strict: Optional[bool] = UNDEFINED
317
284
 
318
285
 
319
- class OpenAIToolDefinition(PromptModel):
286
+ class OpenAIToolDefinition(DBBaseModel):
320
287
  """
321
288
  Based on https://github.com/openai/openai-python/blob/1e07c9d839e7e96f02d0a4b745f379a43086334c/src/openai/types/chat/chat_completion_tool_param.py#L12
322
289
  """
@@ -326,7 +293,7 @@ class OpenAIToolDefinition(PromptModel):
326
293
 
327
294
 
328
295
  # Anthropic tool definitions
329
- class AnthropicCacheControlParam(PromptModel):
296
+ class AnthropicCacheControlParam(DBBaseModel):
330
297
  """
331
298
  Based on https://github.com/anthropics/anthropic-sdk-python/blob/93cbbbde964e244f02bf1bd2b579c5fabce4e267/src/anthropic/types/cache_control_ephemeral_param.py#L10
332
299
  """
@@ -334,7 +301,7 @@ class AnthropicCacheControlParam(PromptModel):
334
301
  type: Literal["ephemeral"]
335
302
 
336
303
 
337
- class AnthropicToolDefinition(PromptModel):
304
+ class AnthropicToolDefinition(DBBaseModel):
338
305
  """
339
306
  Based on https://github.com/anthropics/anthropic-sdk-python/blob/93cbbbde964e244f02bf1bd2b579c5fabce4e267/src/anthropic/types/tool_param.py#L22
340
307
  """
@@ -345,7 +312,7 @@ class AnthropicToolDefinition(PromptModel):
345
312
  description: str = UNDEFINED
346
313
 
347
314
 
348
- class PromptOpenAIInvocationParametersContent(PromptModel):
315
+ class PromptOpenAIInvocationParametersContent(DBBaseModel):
349
316
  temperature: float = UNDEFINED
350
317
  max_tokens: int = UNDEFINED
351
318
  max_completion_tokens: int = UNDEFINED
@@ -356,7 +323,7 @@ class PromptOpenAIInvocationParametersContent(PromptModel):
356
323
  reasoning_effort: Literal["low", "medium", "high"] = UNDEFINED
357
324
 
358
325
 
359
- class PromptOpenAIInvocationParameters(PromptModel):
326
+ class PromptOpenAIInvocationParameters(DBBaseModel):
360
327
  type: Literal["openai"]
361
328
  openai: PromptOpenAIInvocationParametersContent
362
329
 
@@ -365,21 +332,21 @@ class PromptAzureOpenAIInvocationParametersContent(PromptOpenAIInvocationParamet
365
332
  pass
366
333
 
367
334
 
368
- class PromptAzureOpenAIInvocationParameters(PromptModel):
335
+ class PromptAzureOpenAIInvocationParameters(DBBaseModel):
369
336
  type: Literal["azure_openai"]
370
337
  azure_openai: PromptAzureOpenAIInvocationParametersContent
371
338
 
372
339
 
373
- class PromptAnthropicThinkingConfigDisabled(PromptModel):
340
+ class PromptAnthropicThinkingConfigDisabled(DBBaseModel):
374
341
  type: Literal["disabled"]
375
342
 
376
343
 
377
- class PromptAnthropicThinkingConfigEnabled(PromptModel):
344
+ class PromptAnthropicThinkingConfigEnabled(DBBaseModel):
378
345
  type: Literal["enabled"]
379
346
  budget_tokens: int = Field(..., ge=1024)
380
347
 
381
348
 
382
- class PromptAnthropicInvocationParametersContent(PromptModel):
349
+ class PromptAnthropicInvocationParametersContent(DBBaseModel):
383
350
  max_tokens: int
384
351
  temperature: float = UNDEFINED
385
352
  top_p: float = UNDEFINED
@@ -398,12 +365,12 @@ class PromptAnthropicInvocationParametersContent(PromptModel):
398
365
  return self
399
366
 
400
367
 
401
- class PromptAnthropicInvocationParameters(PromptModel):
368
+ class PromptAnthropicInvocationParameters(DBBaseModel):
402
369
  type: Literal["anthropic"]
403
370
  anthropic: PromptAnthropicInvocationParametersContent
404
371
 
405
372
 
406
- class PromptGoogleInvocationParametersContent(PromptModel):
373
+ class PromptGoogleInvocationParametersContent(DBBaseModel):
407
374
  temperature: float = UNDEFINED
408
375
  max_output_tokens: int = UNDEFINED
409
376
  stop_sequences: list[str] = UNDEFINED
@@ -413,7 +380,7 @@ class PromptGoogleInvocationParametersContent(PromptModel):
413
380
  top_k: int = UNDEFINED
414
381
 
415
382
 
416
- class PromptGoogleInvocationParameters(PromptModel):
383
+ class PromptGoogleInvocationParameters(DBBaseModel):
417
384
  type: Literal["google"]
418
385
  google: PromptGoogleInvocationParametersContent
419
386
 
@@ -524,7 +491,7 @@ def denormalize_tools(
524
491
  tools: PromptTools, model_provider: ModelProvider
525
492
  ) -> tuple[list[dict[str, Any]], Optional[Any]]:
526
493
  assert tools.type == "tools"
527
- denormalized_tools: list[PromptModel]
494
+ denormalized_tools: list[DBBaseModel]
528
495
  tool_choice: Optional[Any] = None
529
496
  if model_provider is ModelProvider.OPENAI or model_provider is ModelProvider.AZURE_OPENAI:
530
497
  denormalized_tools = [_prompt_to_openai_tool(tool) for tool in tools.tools]
@@ -4,6 +4,7 @@ import strawberry
4
4
  from strawberry.relay import GlobalID
5
5
  from strawberry.scalars import JSON
6
6
 
7
+ from phoenix.server.api.types.AnnotationSource import AnnotationSource
7
8
  from phoenix.server.api.types.AnnotatorKind import AnnotatorKind
8
9
 
9
10
 
@@ -16,3 +17,11 @@ class CreateSpanAnnotationInput:
16
17
  score: Optional[float] = None
17
18
  explanation: Optional[str] = None
18
19
  metadata: JSON = strawberry.field(default_factory=dict)
20
+ source: AnnotationSource
21
+ identifier: Optional[str] = strawberry.UNSET
22
+
23
+
24
+ @strawberry.input
25
+ class CreateSpanNoteInput:
26
+ span_id: GlobalID
27
+ note: str
@@ -4,6 +4,7 @@ import strawberry
4
4
  from strawberry.relay import GlobalID
5
5
  from strawberry.scalars import JSON
6
6
 
7
+ from phoenix.server.api.types.AnnotationSource import AnnotationSource
7
8
  from phoenix.server.api.types.AnnotatorKind import AnnotatorKind
8
9
 
9
10
 
@@ -16,3 +17,5 @@ class CreateTraceAnnotationInput:
16
17
  score: Optional[float] = None
17
18
  explanation: Optional[str] = None
18
19
  metadata: JSON = strawberry.field(default_factory=dict)
20
+ source: AnnotationSource
21
+ identifier: Optional[str] = strawberry.UNSET
@@ -5,6 +5,7 @@ from strawberry import UNSET
5
5
  from strawberry.relay import GlobalID
6
6
  from strawberry.scalars import JSON
7
7
 
8
+ from phoenix.server.api.types.AnnotationSource import AnnotationSource
8
9
  from phoenix.server.api.types.AnnotatorKind import AnnotatorKind
9
10
 
10
11
 
@@ -17,3 +18,5 @@ class PatchAnnotationInput:
17
18
  score: Optional[float] = UNSET
18
19
  explanation: Optional[str] = UNSET
19
20
  metadata: Optional[JSON] = UNSET
21
+ identifier: Optional[str] = UNSET
22
+ source: Optional[AnnotationSource] = UNSET
@@ -0,0 +1,67 @@
1
+ from typing import Optional
2
+
3
+ import strawberry
4
+ from strawberry import UNSET
5
+ from strawberry.relay import GlobalID
6
+
7
+ from phoenix.db import models
8
+ from phoenix.server.api.exceptions import BadRequest
9
+ from phoenix.server.api.types.AnnotationSource import AnnotationSource
10
+ from phoenix.server.api.types.node import from_global_id_with_expected_type
11
+
12
+
13
+ @strawberry.input
14
+ class SpanAnnotationFilterCondition:
15
+ names: Optional[list[str]] = UNSET
16
+ sources: Optional[list[AnnotationSource]] = UNSET
17
+ user_ids: Optional[list[Optional[GlobalID]]] = UNSET
18
+
19
+ def __post_init__(self) -> None:
20
+ if isinstance(self.names, list) and not self.names:
21
+ raise BadRequest("names must be a non-empty list")
22
+ if isinstance(self.sources, list) and not self.sources:
23
+ raise BadRequest("sources must be a non-empty list")
24
+ if isinstance(self.user_ids, list) and not self.user_ids:
25
+ raise BadRequest("user ids must be a non-empty list")
26
+
27
+
28
+ @strawberry.input
29
+ class SpanAnnotationFilter:
30
+ include: Optional[SpanAnnotationFilterCondition] = UNSET
31
+ exclude: Optional[SpanAnnotationFilterCondition] = UNSET
32
+
33
+ def __post_init__(self) -> None:
34
+ if self.include is UNSET and self.exclude is UNSET:
35
+ raise BadRequest("include and exclude cannot both be unset")
36
+
37
+
38
+ def satisfies_filter(span_annotation: models.SpanAnnotation, filter: SpanAnnotationFilter) -> bool:
39
+ """
40
+ Returns true if the span annotation satisfies the filter and false otherwise.
41
+ """
42
+ span_annotation_source = AnnotationSource(span_annotation.source)
43
+ if include := filter.include:
44
+ if include.names and span_annotation.name not in include.names:
45
+ return False
46
+ if include.sources and span_annotation_source not in include.sources:
47
+ return False
48
+ if include.user_ids:
49
+ user_rowids = [
50
+ from_global_id_with_expected_type(user_id, "User") if user_id is not None else None
51
+ for user_id in include.user_ids
52
+ ]
53
+ if span_annotation.user_id not in user_rowids:
54
+ return False
55
+ if exclude := filter.exclude:
56
+ if exclude.names and span_annotation.name in exclude.names:
57
+ return False
58
+ if exclude.sources and span_annotation_source in exclude.sources:
59
+ return False
60
+ if exclude.user_ids:
61
+ user_rowids = [
62
+ from_global_id_with_expected_type(user_id, "User") if user_id is not None else None
63
+ for user_id in exclude.user_ids
64
+ ]
65
+ if span_annotation.user_id in user_rowids:
66
+ return False
67
+ return True
@@ -1,5 +1,6 @@
1
1
  import strawberry
2
2
 
3
+ from phoenix.server.api.mutations.annotation_config_mutations import AnnotationConfigMutationMixin
3
4
  from phoenix.server.api.mutations.api_key_mutations import ApiKeyMutationMixin
4
5
  from phoenix.server.api.mutations.chat_mutations import (
5
6
  ChatCompletionMutationMixin,
@@ -8,6 +9,9 @@ from phoenix.server.api.mutations.dataset_mutations import DatasetMutationMixin
8
9
  from phoenix.server.api.mutations.experiment_mutations import ExperimentMutationMixin
9
10
  from phoenix.server.api.mutations.export_events_mutations import ExportEventsMutationMixin
10
11
  from phoenix.server.api.mutations.project_mutations import ProjectMutationMixin
12
+ from phoenix.server.api.mutations.project_trace_retention_policy_mutations import (
13
+ ProjectTraceRetentionPolicyMutationMixin,
14
+ )
11
15
  from phoenix.server.api.mutations.prompt_label_mutations import PromptLabelMutationMixin
12
16
  from phoenix.server.api.mutations.prompt_mutations import PromptMutationMixin
13
17
  from phoenix.server.api.mutations.prompt_version_tag_mutations import PromptVersionTagMutationMixin
@@ -19,12 +23,14 @@ from phoenix.server.api.mutations.user_mutations import UserMutationMixin
19
23
 
20
24
  @strawberry.type
21
25
  class Mutation(
26
+ AnnotationConfigMutationMixin,
22
27
  ApiKeyMutationMixin,
23
28
  ChatCompletionMutationMixin,
24
29
  DatasetMutationMixin,
25
30
  ExperimentMutationMixin,
26
31
  ExportEventsMutationMixin,
27
32
  ProjectMutationMixin,
33
+ ProjectTraceRetentionPolicyMutationMixin,
28
34
  PromptMutationMixin,
29
35
  PromptVersionTagMutationMixin,
30
36
  PromptLabelMutationMixin,