arize-phoenix 4.4.3__py3-none-any.whl → 4.4.4rc0__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 (109) hide show
  1. {arize_phoenix-4.4.3.dist-info → arize_phoenix-4.4.4rc0.dist-info}/METADATA +4 -4
  2. {arize_phoenix-4.4.3.dist-info → arize_phoenix-4.4.4rc0.dist-info}/RECORD +108 -55
  3. phoenix/__init__.py +0 -27
  4. phoenix/config.py +21 -7
  5. phoenix/core/model.py +25 -25
  6. phoenix/core/model_schema.py +64 -62
  7. phoenix/core/model_schema_adapter.py +27 -25
  8. phoenix/datasets/__init__.py +0 -0
  9. phoenix/datasets/evaluators.py +275 -0
  10. phoenix/datasets/experiments.py +469 -0
  11. phoenix/datasets/tracing.py +66 -0
  12. phoenix/datasets/types.py +212 -0
  13. phoenix/db/bulk_inserter.py +54 -14
  14. phoenix/db/insertion/dataset.py +234 -0
  15. phoenix/db/insertion/evaluation.py +6 -6
  16. phoenix/db/insertion/helpers.py +13 -2
  17. phoenix/db/migrations/types.py +29 -0
  18. phoenix/db/migrations/versions/10460e46d750_datasets.py +291 -0
  19. phoenix/db/migrations/versions/cf03bd6bae1d_init.py +2 -28
  20. phoenix/db/models.py +230 -3
  21. phoenix/inferences/fixtures.py +23 -23
  22. phoenix/inferences/inferences.py +7 -7
  23. phoenix/inferences/validation.py +1 -1
  24. phoenix/server/api/context.py +16 -0
  25. phoenix/server/api/dataloaders/__init__.py +16 -0
  26. phoenix/server/api/dataloaders/dataset_example_revisions.py +100 -0
  27. phoenix/server/api/dataloaders/dataset_example_spans.py +43 -0
  28. phoenix/server/api/dataloaders/experiment_annotation_summaries.py +85 -0
  29. phoenix/server/api/dataloaders/experiment_error_rates.py +43 -0
  30. phoenix/server/api/dataloaders/experiment_sequence_number.py +49 -0
  31. phoenix/server/api/dataloaders/project_by_name.py +31 -0
  32. phoenix/server/api/dataloaders/span_descendants.py +2 -3
  33. phoenix/server/api/dataloaders/span_projects.py +33 -0
  34. phoenix/server/api/dataloaders/trace_row_ids.py +39 -0
  35. phoenix/server/api/helpers/dataset_helpers.py +178 -0
  36. phoenix/server/api/input_types/AddExamplesToDatasetInput.py +16 -0
  37. phoenix/server/api/input_types/AddSpansToDatasetInput.py +14 -0
  38. phoenix/server/api/input_types/CreateDatasetInput.py +12 -0
  39. phoenix/server/api/input_types/DatasetExampleInput.py +14 -0
  40. phoenix/server/api/input_types/DatasetSort.py +17 -0
  41. phoenix/server/api/input_types/DatasetVersionSort.py +16 -0
  42. phoenix/server/api/input_types/DeleteDatasetExamplesInput.py +13 -0
  43. phoenix/server/api/input_types/DeleteDatasetInput.py +7 -0
  44. phoenix/server/api/input_types/DeleteExperimentsInput.py +9 -0
  45. phoenix/server/api/input_types/PatchDatasetExamplesInput.py +35 -0
  46. phoenix/server/api/input_types/PatchDatasetInput.py +14 -0
  47. phoenix/server/api/mutations/__init__.py +13 -0
  48. phoenix/server/api/mutations/auth.py +11 -0
  49. phoenix/server/api/mutations/dataset_mutations.py +520 -0
  50. phoenix/server/api/mutations/experiment_mutations.py +65 -0
  51. phoenix/server/api/{types/ExportEventsMutation.py → mutations/export_events_mutations.py} +17 -14
  52. phoenix/server/api/mutations/project_mutations.py +42 -0
  53. phoenix/server/api/queries.py +503 -0
  54. phoenix/server/api/routers/v1/__init__.py +77 -2
  55. phoenix/server/api/routers/v1/dataset_examples.py +178 -0
  56. phoenix/server/api/routers/v1/datasets.py +861 -0
  57. phoenix/server/api/routers/v1/evaluations.py +4 -2
  58. phoenix/server/api/routers/v1/experiment_evaluations.py +65 -0
  59. phoenix/server/api/routers/v1/experiment_runs.py +108 -0
  60. phoenix/server/api/routers/v1/experiments.py +174 -0
  61. phoenix/server/api/routers/v1/spans.py +3 -1
  62. phoenix/server/api/routers/v1/traces.py +1 -4
  63. phoenix/server/api/schema.py +2 -303
  64. phoenix/server/api/types/AnnotatorKind.py +10 -0
  65. phoenix/server/api/types/Cluster.py +19 -19
  66. phoenix/server/api/types/CreateDatasetPayload.py +8 -0
  67. phoenix/server/api/types/Dataset.py +282 -63
  68. phoenix/server/api/types/DatasetExample.py +85 -0
  69. phoenix/server/api/types/DatasetExampleRevision.py +34 -0
  70. phoenix/server/api/types/DatasetVersion.py +14 -0
  71. phoenix/server/api/types/Dimension.py +30 -29
  72. phoenix/server/api/types/EmbeddingDimension.py +40 -34
  73. phoenix/server/api/types/Event.py +16 -16
  74. phoenix/server/api/types/ExampleRevisionInterface.py +14 -0
  75. phoenix/server/api/types/Experiment.py +135 -0
  76. phoenix/server/api/types/ExperimentAnnotationSummary.py +13 -0
  77. phoenix/server/api/types/ExperimentComparison.py +19 -0
  78. phoenix/server/api/types/ExperimentRun.py +91 -0
  79. phoenix/server/api/types/ExperimentRunAnnotation.py +57 -0
  80. phoenix/server/api/types/Inferences.py +80 -0
  81. phoenix/server/api/types/InferencesRole.py +23 -0
  82. phoenix/server/api/types/Model.py +43 -42
  83. phoenix/server/api/types/Project.py +26 -12
  84. phoenix/server/api/types/Span.py +78 -2
  85. phoenix/server/api/types/TimeSeries.py +6 -6
  86. phoenix/server/api/types/Trace.py +15 -4
  87. phoenix/server/api/types/UMAPPoints.py +1 -1
  88. phoenix/server/api/types/node.py +5 -111
  89. phoenix/server/api/types/pagination.py +10 -52
  90. phoenix/server/app.py +99 -49
  91. phoenix/server/main.py +49 -27
  92. phoenix/server/openapi/docs.py +3 -0
  93. phoenix/server/static/index.js +2246 -1368
  94. phoenix/server/templates/index.html +1 -0
  95. phoenix/services.py +15 -15
  96. phoenix/session/client.py +316 -21
  97. phoenix/session/session.py +47 -37
  98. phoenix/trace/exporter.py +14 -9
  99. phoenix/trace/fixtures.py +133 -7
  100. phoenix/trace/span_evaluations.py +3 -3
  101. phoenix/trace/trace_dataset.py +6 -6
  102. phoenix/utilities/json.py +61 -0
  103. phoenix/utilities/re.py +50 -0
  104. phoenix/version.py +1 -1
  105. phoenix/server/api/types/DatasetRole.py +0 -23
  106. {arize_phoenix-4.4.3.dist-info → arize_phoenix-4.4.4rc0.dist-info}/WHEEL +0 -0
  107. {arize_phoenix-4.4.3.dist-info → arize_phoenix-4.4.4rc0.dist-info}/licenses/IP_NOTICE +0 -0
  108. {arize_phoenix-4.4.3.dist-info → arize_phoenix-4.4.4rc0.dist-info}/licenses/LICENSE +0 -0
  109. /phoenix/server/api/{helpers.py → helpers/__init__.py} +0 -0
@@ -44,7 +44,7 @@ async def post_evaluations(request: Request) -> Response:
44
44
  summary: Add evaluations to a span, trace, or document
45
45
  operationId: addEvaluations
46
46
  tags:
47
- - evaluations
47
+ - private
48
48
  parameters:
49
49
  - name: project-name
50
50
  in: query
@@ -105,7 +105,7 @@ async def get_evaluations(request: Request) -> Response:
105
105
  summary: Get evaluations from Phoenix
106
106
  operationId: getEvaluation
107
107
  tags:
108
- - evaluations
108
+ - private
109
109
  parameters:
110
110
  - name: project-name
111
111
  in: query
@@ -116,6 +116,8 @@ async def get_evaluations(request: Request) -> Response:
116
116
  responses:
117
117
  200:
118
118
  description: Success
119
+ 403:
120
+ description: Forbidden
119
121
  404:
120
122
  description: Not found
121
123
  """
@@ -0,0 +1,65 @@
1
+ from datetime import datetime
2
+
3
+ from starlette.requests import Request
4
+ from starlette.responses import JSONResponse, Response
5
+ from starlette.status import HTTP_404_NOT_FOUND
6
+ from strawberry.relay import GlobalID
7
+
8
+ from phoenix.datasets.types import EvaluationResult, ExperimentEvaluationRun
9
+ from phoenix.db import models
10
+ from phoenix.server.api.types.node import from_global_id_with_expected_type
11
+ from phoenix.utilities.json import jsonify
12
+
13
+
14
+ async def create_experiment_evaluation(request: Request) -> Response:
15
+ payload = await request.json()
16
+ experiment_run_gid = GlobalID.from_id(payload["experiment_run_id"])
17
+ try:
18
+ experiment_run_id = from_global_id_with_expected_type(experiment_run_gid, "ExperimentRun")
19
+ except ValueError:
20
+ return Response(
21
+ content=f"ExperimentRun with ID {experiment_run_gid} does not exist",
22
+ status_code=HTTP_404_NOT_FOUND,
23
+ )
24
+ name = payload["name"]
25
+ annotator_kind = payload["annotator_kind"]
26
+ result = payload.get("result")
27
+ label = result.get("label") if result else None
28
+ score = result.get("score") if result else None
29
+ explanation = result.get("explanation") if result else None
30
+ error = payload.get("error")
31
+ metadata = payload.get("metadata") or {}
32
+ start_time = payload["start_time"]
33
+ end_time = payload["end_time"]
34
+ async with request.app.state.db() as session:
35
+ exp_eval_run = models.ExperimentRunAnnotation(
36
+ experiment_run_id=experiment_run_id,
37
+ name=name,
38
+ annotator_kind=annotator_kind,
39
+ label=label,
40
+ score=score,
41
+ explanation=explanation,
42
+ error=error,
43
+ metadata_=metadata,
44
+ start_time=datetime.fromisoformat(start_time),
45
+ end_time=datetime.fromisoformat(end_time),
46
+ )
47
+ session.add(exp_eval_run)
48
+ await session.flush()
49
+ evaluation_gid = GlobalID("ExperimentEvaluation", str(exp_eval_run.id))
50
+ eval_payload = ExperimentEvaluationRun(
51
+ id=str(evaluation_gid),
52
+ experiment_run_id=str(experiment_run_gid),
53
+ start_time=exp_eval_run.start_time,
54
+ end_time=exp_eval_run.end_time,
55
+ name=exp_eval_run.name,
56
+ annotator_kind=exp_eval_run.annotator_kind,
57
+ error=exp_eval_run.error,
58
+ result=EvaluationResult(
59
+ label=exp_eval_run.label,
60
+ score=exp_eval_run.score,
61
+ explanation=exp_eval_run.explanation,
62
+ metadata=exp_eval_run.metadata_,
63
+ ),
64
+ )
65
+ return JSONResponse(content=jsonify(eval_payload), status_code=200)
@@ -0,0 +1,108 @@
1
+ from datetime import datetime
2
+
3
+ from sqlalchemy import select
4
+ from starlette.requests import Request
5
+ from starlette.responses import JSONResponse, Response
6
+ from starlette.status import HTTP_404_NOT_FOUND
7
+ from strawberry.relay import GlobalID
8
+
9
+ from phoenix.datasets.types import ExperimentResult, ExperimentRun
10
+ from phoenix.db import models
11
+ from phoenix.server.api.types.node import from_global_id_with_expected_type
12
+ from phoenix.utilities.json import jsonify
13
+
14
+
15
+ async def create_experiment_run(request: Request) -> Response:
16
+ experiment_gid = GlobalID.from_id(request.path_params["experiment_id"])
17
+ try:
18
+ experiment_id = from_global_id_with_expected_type(experiment_gid, "Experiment")
19
+ except ValueError:
20
+ return Response(
21
+ content=f"Experiment with ID {experiment_gid} does not exist",
22
+ status_code=HTTP_404_NOT_FOUND,
23
+ )
24
+
25
+ payload = await request.json()
26
+
27
+ example_gid = GlobalID.from_id(payload["dataset_example_id"])
28
+ try:
29
+ dataset_example_id = from_global_id_with_expected_type(example_gid, "DatasetExample")
30
+ except ValueError:
31
+ return Response(
32
+ content=f"DatasetExample with ID {example_gid} does not exist",
33
+ status_code=HTTP_404_NOT_FOUND,
34
+ )
35
+
36
+ trace_id = payload.get("trace_id", None)
37
+ output = payload["output"]
38
+ repetition_number = payload["repetition_number"]
39
+ start_time = payload["start_time"]
40
+ end_time = payload["end_time"]
41
+ error = payload.get("error")
42
+
43
+ async with request.app.state.db() as session:
44
+ exp_run = models.ExperimentRun(
45
+ experiment_id=experiment_id,
46
+ dataset_example_id=dataset_example_id,
47
+ trace_id=trace_id,
48
+ output=output,
49
+ repetition_number=repetition_number,
50
+ start_time=datetime.fromisoformat(start_time),
51
+ end_time=datetime.fromisoformat(end_time),
52
+ error=error,
53
+ )
54
+ session.add(exp_run)
55
+ await session.flush()
56
+
57
+ run_gid = GlobalID("ExperimentRun", str(exp_run.id))
58
+ run_payload = ExperimentRun(
59
+ start_time=exp_run.start_time,
60
+ end_time=exp_run.end_time,
61
+ experiment_id=str(experiment_gid),
62
+ dataset_example_id=str(example_gid),
63
+ repetition_number=exp_run.repetition_number,
64
+ output=ExperimentResult(result=exp_run.output),
65
+ error=exp_run.error,
66
+ id=str(run_gid),
67
+ trace_id=exp_run.trace_id,
68
+ )
69
+ return JSONResponse(content=jsonify(run_payload), status_code=200)
70
+
71
+
72
+ async def list_experiment_runs(request: Request) -> Response:
73
+ experiment_gid = GlobalID.from_id(request.path_params["experiment_id"])
74
+ try:
75
+ experiment_id = from_global_id_with_expected_type(experiment_gid, "Experiment")
76
+ except ValueError:
77
+ return Response(
78
+ content=f"Experiment with ID {experiment_gid} does not exist",
79
+ status_code=HTTP_404_NOT_FOUND,
80
+ )
81
+
82
+ async with request.app.state.db() as session:
83
+ experiment_runs = await session.execute(
84
+ select(models.ExperimentRun)
85
+ .where(models.ExperimentRun.experiment_id == experiment_id)
86
+ # order by dataset_example_id to be consistent with `list_dataset_examples`
87
+ .order_by(models.ExperimentRun.dataset_example_id.asc())
88
+ )
89
+ experiment_runs = experiment_runs.scalars().all()
90
+ runs = []
91
+ for exp_run in experiment_runs:
92
+ run_gid = GlobalID("ExperimentRun", str(exp_run.id))
93
+ experiment_gid = GlobalID("Experiment", str(exp_run.experiment_id))
94
+ example_gid = GlobalID("DatasetExample", str(exp_run.dataset_example_id))
95
+ runs.append(
96
+ ExperimentRun(
97
+ start_time=exp_run.start_time,
98
+ end_time=exp_run.end_time,
99
+ experiment_id=str(experiment_gid),
100
+ dataset_example_id=str(example_gid),
101
+ repetition_number=exp_run.repetition_number,
102
+ output=ExperimentResult(result=exp_run.output),
103
+ error=exp_run.error,
104
+ id=str(run_gid),
105
+ trace_id=exp_run.trace_id,
106
+ )
107
+ )
108
+ return JSONResponse(content=jsonify(runs), status_code=200)
@@ -0,0 +1,174 @@
1
+ from random import getrandbits
2
+
3
+ from sqlalchemy import select
4
+ from starlette.requests import Request
5
+ from starlette.responses import JSONResponse, Response
6
+ from starlette.status import HTTP_404_NOT_FOUND
7
+ from strawberry.relay import GlobalID
8
+
9
+ from phoenix.db import models
10
+ from phoenix.db.helpers import SupportedSQLDialect
11
+ from phoenix.db.insertion.helpers import insert_stmt
12
+ from phoenix.server.api.types.node import from_global_id_with_expected_type
13
+
14
+
15
+ def _short_uuid() -> str:
16
+ return str(getrandbits(32).to_bytes(4, "big").hex())
17
+
18
+
19
+ def _generate_experiment_name(dataset_name: str) -> str:
20
+ """
21
+ Generate a semi-unique name for the experiment.
22
+ """
23
+ short_ds_name = dataset_name[:8].replace(" ", "-")
24
+ return f"{short_ds_name}-{_short_uuid()}"
25
+
26
+
27
+ async def create_experiment(request: Request) -> Response:
28
+ dataset_globalid = GlobalID.from_id(request.path_params["dataset_id"])
29
+ try:
30
+ dataset_id = from_global_id_with_expected_type(dataset_globalid, "Dataset")
31
+ except ValueError:
32
+ return Response(
33
+ content="Dataset with ID {dataset_globalid} does not exist",
34
+ status_code=HTTP_404_NOT_FOUND,
35
+ )
36
+
37
+ payload = await request.json()
38
+ repetitions = payload.get("repetitions", 1)
39
+ metadata = payload.get("metadata") or {}
40
+ dataset_version_globalid_str = payload.get("version-id")
41
+ if dataset_version_globalid_str is not None:
42
+ try:
43
+ dataset_version_globalid = GlobalID.from_id(dataset_version_globalid_str)
44
+ dataset_version_id = from_global_id_with_expected_type(
45
+ dataset_version_globalid, "DatasetVersion"
46
+ )
47
+ except ValueError:
48
+ return Response(
49
+ content="DatasetVersion with ID {dataset_version_globalid} does not exist",
50
+ status_code=HTTP_404_NOT_FOUND,
51
+ )
52
+
53
+ async with request.app.state.db() as session:
54
+ result = (
55
+ await session.execute(select(models.Dataset).where(models.Dataset.id == dataset_id))
56
+ ).scalar()
57
+ if result is None:
58
+ return Response(
59
+ content=f"Dataset with ID {dataset_globalid} does not exist",
60
+ status_code=HTTP_404_NOT_FOUND,
61
+ )
62
+ dataset_name = result.name
63
+ if dataset_version_globalid_str is None:
64
+ dataset_version_result = await session.execute(
65
+ select(models.DatasetVersion)
66
+ .where(models.DatasetVersion.dataset_id == dataset_id)
67
+ .order_by(models.DatasetVersion.id.desc())
68
+ )
69
+ dataset_version = dataset_version_result.scalar()
70
+ if not dataset_version:
71
+ return Response(
72
+ content=f"Dataset {dataset_globalid} does not have any versions",
73
+ status_code=HTTP_404_NOT_FOUND,
74
+ )
75
+ dataset_version_id = dataset_version.id
76
+ dataset_version_globalid = GlobalID("DatasetVersion", str(dataset_version_id))
77
+ else:
78
+ dataset_version = await session.execute(
79
+ select(models.DatasetVersion).where(models.DatasetVersion.id == dataset_version_id)
80
+ )
81
+ dataset_version = dataset_version.scalar()
82
+ if not dataset_version:
83
+ return Response(
84
+ content=f"DatasetVersion with ID {dataset_version_globalid} does not exist",
85
+ status_code=HTTP_404_NOT_FOUND,
86
+ )
87
+
88
+ # generate a semi-unique name for the experiment
89
+ experiment_name = payload.get("name") or _generate_experiment_name(dataset_name)
90
+ project_name = f"Experiment-{getrandbits(96).to_bytes(12, 'big').hex()}"
91
+ project_description = (
92
+ f"dataset_id: {dataset_globalid}\ndataset_version_id: {dataset_version_globalid}"
93
+ )
94
+ experiment = models.Experiment(
95
+ dataset_id=int(dataset_id),
96
+ dataset_version_id=int(dataset_version_id),
97
+ name=experiment_name,
98
+ description=payload.get("description"),
99
+ repetitions=repetitions,
100
+ metadata_=metadata,
101
+ project_name=project_name,
102
+ )
103
+ session.add(experiment)
104
+ await session.flush()
105
+
106
+ dialect = SupportedSQLDialect(session.bind.dialect.name)
107
+ project_rowid = await session.scalar(
108
+ insert_stmt(
109
+ dialect=dialect,
110
+ table=models.Project,
111
+ constraint="uq_projects_name",
112
+ column_names=("name",),
113
+ values=dict(
114
+ name=project_name,
115
+ description=project_description,
116
+ created_at=experiment.created_at,
117
+ updated_at=experiment.updated_at,
118
+ ),
119
+ ).returning(models.Project.id)
120
+ )
121
+ assert project_rowid is not None
122
+
123
+ experiment_globalid = GlobalID("Experiment", str(experiment.id))
124
+ if dataset_version_globalid_str is None:
125
+ dataset_version_globalid = GlobalID(
126
+ "DatasetVersion", str(experiment.dataset_version_id)
127
+ )
128
+ experiment_payload = {
129
+ "id": str(experiment_globalid),
130
+ "dataset_id": str(dataset_globalid),
131
+ "dataset_version_id": str(dataset_version_globalid),
132
+ "repetitions": experiment.repetitions,
133
+ "metadata": experiment.metadata_,
134
+ "project_name": experiment.project_name,
135
+ "created_at": experiment.created_at.isoformat(),
136
+ "updated_at": experiment.updated_at.isoformat(),
137
+ }
138
+ return JSONResponse(content=experiment_payload, status_code=200)
139
+
140
+
141
+ async def read_experiment(request: Request) -> Response:
142
+ experiment_globalid = GlobalID.from_id(request.path_params["experiment_id"])
143
+ try:
144
+ experiment_id = from_global_id_with_expected_type(experiment_globalid, "Experiment")
145
+ except ValueError:
146
+ return Response(
147
+ content="Experiment with ID {experiment_globalid} does not exist",
148
+ status_code=HTTP_404_NOT_FOUND,
149
+ )
150
+
151
+ async with request.app.state.db() as session:
152
+ experiment = await session.execute(
153
+ select(models.Experiment).where(models.Experiment.id == experiment_id)
154
+ )
155
+ experiment = experiment.scalar()
156
+ if not experiment:
157
+ return Response(
158
+ content=f"Experiment with ID {experiment_globalid} does not exist",
159
+ status_code=HTTP_404_NOT_FOUND,
160
+ )
161
+
162
+ dataset_globalid = GlobalID("Dataset", str(experiment.dataset_id))
163
+ dataset_version_globalid = GlobalID("DatasetVersion", str(experiment.dataset_version_id))
164
+ experiment_payload = {
165
+ "id": str(experiment_globalid),
166
+ "dataset_id": str(dataset_globalid),
167
+ "dataset_version_id": str(dataset_version_globalid),
168
+ "repetitions": experiment.repetitions,
169
+ "metadata": experiment.metadata_,
170
+ "project_name": experiment.project_name,
171
+ "created_at": experiment.created_at.isoformat(),
172
+ "updated_at": experiment.updated_at.isoformat(),
173
+ }
174
+ return JSONResponse(content=experiment_payload, status_code=200)
@@ -19,7 +19,7 @@ async def query_spans_handler(request: Request) -> Response:
19
19
  summary: Query spans using query DSL
20
20
  operationId: querySpans
21
21
  tags:
22
- - spans
22
+ - private
23
23
  parameters:
24
24
  - name: project-name
25
25
  in: query
@@ -68,6 +68,8 @@ async def query_spans_handler(request: Request) -> Response:
68
68
  responses:
69
69
  200:
70
70
  description: Success
71
+ 403:
72
+ description: Forbidden
71
73
  404:
72
74
  description: Not found
73
75
  422:
@@ -11,7 +11,6 @@ from starlette.datastructures import State
11
11
  from starlette.requests import Request
12
12
  from starlette.responses import Response
13
13
  from starlette.status import (
14
- HTTP_403_FORBIDDEN,
15
14
  HTTP_415_UNSUPPORTED_MEDIA_TYPE,
16
15
  HTTP_422_UNPROCESSABLE_ENTITY,
17
16
  )
@@ -25,7 +24,7 @@ async def post_traces(request: Request) -> Response:
25
24
  summary: Send traces to Phoenix
26
25
  operationId: addTraces
27
26
  tags:
28
- - traces
27
+ - private
29
28
  requestBody:
30
29
  required: true
31
30
  content:
@@ -43,8 +42,6 @@ async def post_traces(request: Request) -> Response:
43
42
  422:
44
43
  description: Request body is invalid
45
44
  """
46
- if request.app.state.read_only:
47
- return Response(status_code=HTTP_403_FORBIDDEN)
48
45
  content_type = request.headers.get("content-type")
49
46
  if content_type != "application/x-protobuf":
50
47
  return Response(