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.
- {arize_phoenix-11.23.1.dist-info → arize_phoenix-12.28.1.dist-info}/METADATA +61 -36
- {arize_phoenix-11.23.1.dist-info → arize_phoenix-12.28.1.dist-info}/RECORD +212 -162
- {arize_phoenix-11.23.1.dist-info → arize_phoenix-12.28.1.dist-info}/WHEEL +1 -1
- {arize_phoenix-11.23.1.dist-info → arize_phoenix-12.28.1.dist-info}/licenses/IP_NOTICE +1 -1
- phoenix/__generated__/__init__.py +0 -0
- phoenix/__generated__/classification_evaluator_configs/__init__.py +20 -0
- phoenix/__generated__/classification_evaluator_configs/_document_relevance_classification_evaluator_config.py +17 -0
- phoenix/__generated__/classification_evaluator_configs/_hallucination_classification_evaluator_config.py +17 -0
- phoenix/__generated__/classification_evaluator_configs/_models.py +18 -0
- phoenix/__generated__/classification_evaluator_configs/_tool_selection_classification_evaluator_config.py +17 -0
- phoenix/__init__.py +2 -1
- phoenix/auth.py +27 -2
- phoenix/config.py +1594 -81
- phoenix/db/README.md +546 -28
- phoenix/db/bulk_inserter.py +119 -116
- phoenix/db/engines.py +140 -33
- phoenix/db/facilitator.py +22 -1
- phoenix/db/helpers.py +818 -65
- phoenix/db/iam_auth.py +64 -0
- phoenix/db/insertion/dataset.py +133 -1
- phoenix/db/insertion/document_annotation.py +9 -6
- phoenix/db/insertion/evaluation.py +2 -3
- phoenix/db/insertion/helpers.py +2 -2
- phoenix/db/insertion/session_annotation.py +176 -0
- phoenix/db/insertion/span_annotation.py +3 -4
- phoenix/db/insertion/trace_annotation.py +3 -4
- phoenix/db/insertion/types.py +41 -18
- phoenix/db/migrations/versions/01a8342c9cdf_add_user_id_on_datasets.py +40 -0
- phoenix/db/migrations/versions/0df286449799_add_session_annotations_table.py +105 -0
- phoenix/db/migrations/versions/272b66ff50f8_drop_single_indices.py +119 -0
- phoenix/db/migrations/versions/58228d933c91_dataset_labels.py +67 -0
- phoenix/db/migrations/versions/699f655af132_experiment_tags.py +57 -0
- phoenix/db/migrations/versions/735d3d93c33e_add_composite_indices.py +41 -0
- phoenix/db/migrations/versions/ab513d89518b_add_user_id_on_dataset_versions.py +40 -0
- phoenix/db/migrations/versions/d0690a79ea51_users_on_experiments.py +40 -0
- phoenix/db/migrations/versions/deb2c81c0bb2_dataset_splits.py +139 -0
- phoenix/db/migrations/versions/e76cbd66ffc3_add_experiments_dataset_examples.py +87 -0
- phoenix/db/models.py +364 -56
- phoenix/db/pg_config.py +10 -0
- phoenix/db/types/trace_retention.py +7 -6
- phoenix/experiments/functions.py +69 -19
- phoenix/inferences/inferences.py +1 -2
- phoenix/server/api/auth.py +9 -0
- phoenix/server/api/auth_messages.py +46 -0
- phoenix/server/api/context.py +60 -0
- phoenix/server/api/dataloaders/__init__.py +36 -0
- phoenix/server/api/dataloaders/annotation_summaries.py +60 -8
- phoenix/server/api/dataloaders/average_experiment_repeated_run_group_latency.py +50 -0
- phoenix/server/api/dataloaders/average_experiment_run_latency.py +17 -24
- phoenix/server/api/dataloaders/cache/two_tier_cache.py +1 -2
- phoenix/server/api/dataloaders/dataset_dataset_splits.py +52 -0
- phoenix/server/api/dataloaders/dataset_example_revisions.py +0 -1
- phoenix/server/api/dataloaders/dataset_example_splits.py +40 -0
- phoenix/server/api/dataloaders/dataset_examples_and_versions_by_experiment_run.py +47 -0
- phoenix/server/api/dataloaders/dataset_labels.py +36 -0
- phoenix/server/api/dataloaders/document_evaluation_summaries.py +2 -2
- phoenix/server/api/dataloaders/document_evaluations.py +6 -9
- phoenix/server/api/dataloaders/experiment_annotation_summaries.py +88 -34
- phoenix/server/api/dataloaders/experiment_dataset_splits.py +43 -0
- phoenix/server/api/dataloaders/experiment_error_rates.py +21 -28
- phoenix/server/api/dataloaders/experiment_repeated_run_group_annotation_summaries.py +77 -0
- phoenix/server/api/dataloaders/experiment_repeated_run_groups.py +57 -0
- phoenix/server/api/dataloaders/experiment_runs_by_experiment_and_example.py +44 -0
- phoenix/server/api/dataloaders/latency_ms_quantile.py +40 -8
- phoenix/server/api/dataloaders/record_counts.py +37 -10
- phoenix/server/api/dataloaders/session_annotations_by_session.py +29 -0
- phoenix/server/api/dataloaders/span_cost_summary_by_experiment_repeated_run_group.py +64 -0
- phoenix/server/api/dataloaders/span_cost_summary_by_project.py +28 -14
- phoenix/server/api/dataloaders/span_costs.py +3 -9
- phoenix/server/api/dataloaders/table_fields.py +2 -2
- phoenix/server/api/dataloaders/token_prices_by_model.py +30 -0
- phoenix/server/api/dataloaders/trace_annotations_by_trace.py +27 -0
- phoenix/server/api/exceptions.py +5 -1
- phoenix/server/api/helpers/playground_clients.py +263 -83
- phoenix/server/api/helpers/playground_spans.py +2 -1
- phoenix/server/api/helpers/playground_users.py +26 -0
- phoenix/server/api/helpers/prompts/conversions/google.py +103 -0
- phoenix/server/api/helpers/prompts/models.py +61 -19
- phoenix/server/api/input_types/{SpanAnnotationFilter.py → AnnotationFilter.py} +22 -14
- phoenix/server/api/input_types/ChatCompletionInput.py +3 -0
- phoenix/server/api/input_types/CreateProjectSessionAnnotationInput.py +37 -0
- phoenix/server/api/input_types/DatasetFilter.py +5 -2
- phoenix/server/api/input_types/ExperimentRunSort.py +237 -0
- phoenix/server/api/input_types/GenerativeModelInput.py +3 -0
- phoenix/server/api/input_types/ProjectSessionSort.py +158 -1
- phoenix/server/api/input_types/PromptVersionInput.py +47 -1
- phoenix/server/api/input_types/SpanSort.py +3 -2
- phoenix/server/api/input_types/UpdateAnnotationInput.py +34 -0
- phoenix/server/api/input_types/UserRoleInput.py +1 -0
- phoenix/server/api/mutations/__init__.py +8 -0
- phoenix/server/api/mutations/annotation_config_mutations.py +8 -8
- phoenix/server/api/mutations/api_key_mutations.py +15 -20
- phoenix/server/api/mutations/chat_mutations.py +106 -37
- phoenix/server/api/mutations/dataset_label_mutations.py +243 -0
- phoenix/server/api/mutations/dataset_mutations.py +21 -16
- phoenix/server/api/mutations/dataset_split_mutations.py +351 -0
- phoenix/server/api/mutations/experiment_mutations.py +2 -2
- phoenix/server/api/mutations/export_events_mutations.py +3 -3
- phoenix/server/api/mutations/model_mutations.py +11 -9
- phoenix/server/api/mutations/project_mutations.py +4 -4
- phoenix/server/api/mutations/project_session_annotations_mutations.py +158 -0
- phoenix/server/api/mutations/project_trace_retention_policy_mutations.py +8 -4
- phoenix/server/api/mutations/prompt_label_mutations.py +74 -65
- phoenix/server/api/mutations/prompt_mutations.py +65 -129
- phoenix/server/api/mutations/prompt_version_tag_mutations.py +11 -8
- phoenix/server/api/mutations/span_annotations_mutations.py +15 -10
- phoenix/server/api/mutations/trace_annotations_mutations.py +13 -8
- phoenix/server/api/mutations/trace_mutations.py +3 -3
- phoenix/server/api/mutations/user_mutations.py +55 -26
- phoenix/server/api/queries.py +501 -617
- phoenix/server/api/routers/__init__.py +2 -2
- phoenix/server/api/routers/auth.py +141 -87
- phoenix/server/api/routers/ldap.py +229 -0
- phoenix/server/api/routers/oauth2.py +349 -101
- phoenix/server/api/routers/v1/__init__.py +22 -4
- phoenix/server/api/routers/v1/annotation_configs.py +19 -30
- phoenix/server/api/routers/v1/annotations.py +455 -13
- phoenix/server/api/routers/v1/datasets.py +355 -68
- phoenix/server/api/routers/v1/documents.py +142 -0
- phoenix/server/api/routers/v1/evaluations.py +20 -28
- phoenix/server/api/routers/v1/experiment_evaluations.py +16 -6
- phoenix/server/api/routers/v1/experiment_runs.py +335 -59
- phoenix/server/api/routers/v1/experiments.py +475 -47
- phoenix/server/api/routers/v1/projects.py +16 -50
- phoenix/server/api/routers/v1/prompts.py +50 -39
- phoenix/server/api/routers/v1/sessions.py +108 -0
- phoenix/server/api/routers/v1/spans.py +156 -96
- phoenix/server/api/routers/v1/traces.py +51 -77
- phoenix/server/api/routers/v1/users.py +64 -24
- phoenix/server/api/routers/v1/utils.py +3 -7
- phoenix/server/api/subscriptions.py +257 -93
- phoenix/server/api/types/Annotation.py +90 -23
- phoenix/server/api/types/ApiKey.py +13 -17
- phoenix/server/api/types/AuthMethod.py +1 -0
- phoenix/server/api/types/ChatCompletionSubscriptionPayload.py +1 -0
- phoenix/server/api/types/Dataset.py +199 -72
- phoenix/server/api/types/DatasetExample.py +88 -18
- phoenix/server/api/types/DatasetExperimentAnnotationSummary.py +10 -0
- phoenix/server/api/types/DatasetLabel.py +57 -0
- phoenix/server/api/types/DatasetSplit.py +98 -0
- phoenix/server/api/types/DatasetVersion.py +49 -4
- phoenix/server/api/types/DocumentAnnotation.py +212 -0
- phoenix/server/api/types/Experiment.py +215 -68
- phoenix/server/api/types/ExperimentComparison.py +3 -9
- phoenix/server/api/types/ExperimentRepeatedRunGroup.py +155 -0
- phoenix/server/api/types/ExperimentRepeatedRunGroupAnnotationSummary.py +9 -0
- phoenix/server/api/types/ExperimentRun.py +120 -70
- phoenix/server/api/types/ExperimentRunAnnotation.py +158 -39
- phoenix/server/api/types/GenerativeModel.py +95 -42
- phoenix/server/api/types/GenerativeProvider.py +1 -1
- phoenix/server/api/types/ModelInterface.py +7 -2
- phoenix/server/api/types/PlaygroundModel.py +12 -2
- phoenix/server/api/types/Project.py +218 -185
- phoenix/server/api/types/ProjectSession.py +146 -29
- phoenix/server/api/types/ProjectSessionAnnotation.py +187 -0
- phoenix/server/api/types/ProjectTraceRetentionPolicy.py +1 -1
- phoenix/server/api/types/Prompt.py +119 -39
- phoenix/server/api/types/PromptLabel.py +42 -25
- phoenix/server/api/types/PromptVersion.py +11 -8
- phoenix/server/api/types/PromptVersionTag.py +65 -25
- phoenix/server/api/types/Span.py +130 -123
- phoenix/server/api/types/SpanAnnotation.py +189 -42
- phoenix/server/api/types/SystemApiKey.py +65 -1
- phoenix/server/api/types/Trace.py +184 -53
- phoenix/server/api/types/TraceAnnotation.py +149 -50
- phoenix/server/api/types/User.py +128 -33
- phoenix/server/api/types/UserApiKey.py +73 -26
- phoenix/server/api/types/node.py +10 -0
- phoenix/server/api/types/pagination.py +11 -2
- phoenix/server/app.py +154 -36
- phoenix/server/authorization.py +5 -4
- phoenix/server/bearer_auth.py +13 -5
- phoenix/server/cost_tracking/cost_model_lookup.py +42 -14
- phoenix/server/cost_tracking/model_cost_manifest.json +1085 -194
- phoenix/server/daemons/generative_model_store.py +61 -9
- phoenix/server/daemons/span_cost_calculator.py +10 -8
- phoenix/server/dml_event.py +13 -0
- phoenix/server/email/sender.py +29 -2
- phoenix/server/grpc_server.py +9 -9
- phoenix/server/jwt_store.py +8 -6
- phoenix/server/ldap.py +1449 -0
- phoenix/server/main.py +9 -3
- phoenix/server/oauth2.py +330 -12
- phoenix/server/prometheus.py +43 -6
- phoenix/server/rate_limiters.py +4 -9
- phoenix/server/retention.py +33 -20
- phoenix/server/session_filters.py +49 -0
- phoenix/server/static/.vite/manifest.json +51 -53
- phoenix/server/static/assets/components-BreFUQQa.js +6702 -0
- phoenix/server/static/assets/{index-BPCwGQr8.js → index-CTQoemZv.js} +42 -35
- phoenix/server/static/assets/pages-DBE5iYM3.js +9524 -0
- phoenix/server/static/assets/vendor-BGzfc4EU.css +1 -0
- phoenix/server/static/assets/vendor-DCE4v-Ot.js +920 -0
- phoenix/server/static/assets/vendor-codemirror-D5f205eT.js +25 -0
- phoenix/server/static/assets/{vendor-recharts-Bw30oz1A.js → vendor-recharts-V9cwpXsm.js} +7 -7
- phoenix/server/static/assets/{vendor-shiki-DZajAPeq.js → vendor-shiki-Do--csgv.js} +1 -1
- phoenix/server/static/assets/vendor-three-CmB8bl_y.js +3840 -0
- phoenix/server/templates/index.html +7 -1
- phoenix/server/thread_server.py +1 -2
- phoenix/server/utils.py +74 -0
- phoenix/session/client.py +55 -1
- phoenix/session/data_extractor.py +5 -0
- phoenix/session/evaluation.py +8 -4
- phoenix/session/session.py +44 -8
- phoenix/settings.py +2 -0
- phoenix/trace/attributes.py +80 -13
- phoenix/trace/dsl/query.py +2 -0
- phoenix/trace/projects.py +5 -0
- phoenix/utilities/template_formatters.py +1 -1
- phoenix/version.py +1 -1
- phoenix/server/api/types/Evaluation.py +0 -39
- phoenix/server/static/assets/components-D0DWAf0l.js +0 -5650
- phoenix/server/static/assets/pages-Creyamao.js +0 -8612
- phoenix/server/static/assets/vendor-CU36oj8y.js +0 -905
- phoenix/server/static/assets/vendor-CqDb5u4o.css +0 -1
- phoenix/server/static/assets/vendor-arizeai-Ctgw0e1G.js +0 -168
- phoenix/server/static/assets/vendor-codemirror-Cojjzqb9.js +0 -25
- phoenix/server/static/assets/vendor-three-BLWp5bic.js +0 -2998
- phoenix/utilities/deprecation.py +0 -31
- {arize_phoenix-11.23.1.dist-info → arize_phoenix-12.28.1.dist-info}/entry_points.txt +0 -0
- {arize_phoenix-11.23.1.dist-info → arize_phoenix-12.28.1.dist-info}/licenses/LICENSE +0 -0
phoenix/db/models.py
CHANGED
|
@@ -20,6 +20,7 @@ from sqlalchemy import (
|
|
|
20
20
|
Integer,
|
|
21
21
|
MetaData,
|
|
22
22
|
Null,
|
|
23
|
+
PrimaryKeyConstraint,
|
|
23
24
|
String,
|
|
24
25
|
TypeDecorator,
|
|
25
26
|
UniqueConstraint,
|
|
@@ -43,6 +44,7 @@ from sqlalchemy.orm import (
|
|
|
43
44
|
)
|
|
44
45
|
from sqlalchemy.sql import Values, column, compiler, expression, literal, roles, union_all
|
|
45
46
|
from sqlalchemy.sql.compiler import SQLCompiler
|
|
47
|
+
from sqlalchemy.sql.elements import Case
|
|
46
48
|
from sqlalchemy.sql.functions import coalesce
|
|
47
49
|
from typing_extensions import TypeAlias
|
|
48
50
|
|
|
@@ -154,7 +156,7 @@ def render_values_w_union(
|
|
|
154
156
|
return compiler.process(subquery, from_linter=from_linter, **kw)
|
|
155
157
|
|
|
156
158
|
|
|
157
|
-
UserRoleName: TypeAlias = Literal["SYSTEM", "ADMIN", "MEMBER"]
|
|
159
|
+
UserRoleName: TypeAlias = Literal["SYSTEM", "ADMIN", "MEMBER", "VIEWER"]
|
|
158
160
|
AuthMethod: TypeAlias = Literal["LOCAL", "OAUTH2"]
|
|
159
161
|
|
|
160
162
|
|
|
@@ -188,7 +190,7 @@ class JsonDict(TypeDecorator[dict[str, Any]]):
|
|
|
188
190
|
impl = JSON_
|
|
189
191
|
|
|
190
192
|
def process_bind_param(self, value: Optional[dict[str, Any]], _: Dialect) -> dict[str, Any]:
|
|
191
|
-
return
|
|
193
|
+
return value if isinstance(value, dict) else {}
|
|
192
194
|
|
|
193
195
|
def process_result_value(self, value: Optional[Any], _: Dialect) -> Optional[dict[str, Any]]:
|
|
194
196
|
return orjson.loads(orjson.dumps(value)) if isinstance(value, dict) and value else value
|
|
@@ -200,7 +202,7 @@ class JsonList(TypeDecorator[list[Any]]):
|
|
|
200
202
|
impl = JSON_
|
|
201
203
|
|
|
202
204
|
def process_bind_param(self, value: Optional[list[Any]], _: Dialect) -> list[Any]:
|
|
203
|
-
return
|
|
205
|
+
return value if isinstance(value, list) else []
|
|
204
206
|
|
|
205
207
|
def process_result_value(self, value: Optional[Any], _: Dialect) -> Optional[list[Any]]:
|
|
206
208
|
return orjson.loads(orjson.dumps(value)) if isinstance(value, list) and value else value
|
|
@@ -442,12 +444,32 @@ class _RegexStr(TypeDecorator[re.Pattern[str]]):
|
|
|
442
444
|
return re.compile(value)
|
|
443
445
|
|
|
444
446
|
|
|
447
|
+
_HEX_COLOR_PATTERN = re.compile(r"^#([0-9a-f]{6})$")
|
|
448
|
+
|
|
449
|
+
|
|
450
|
+
class _HexColor(TypeDecorator[str]):
|
|
451
|
+
# See https://docs.sqlalchemy.org/en/20/core/custom_types.html
|
|
452
|
+
cache_ok = True
|
|
453
|
+
impl = String
|
|
454
|
+
|
|
455
|
+
def process_bind_param(self, value: Optional[str], _: Dialect) -> Optional[str]:
|
|
456
|
+
if value is None:
|
|
457
|
+
return None
|
|
458
|
+
if not _HEX_COLOR_PATTERN.match(value):
|
|
459
|
+
raise ValueError(f"Expected a hex color, got {value}")
|
|
460
|
+
return value
|
|
461
|
+
|
|
462
|
+
def process_result_value(self, value: Optional[str], _: Dialect) -> Optional[str]:
|
|
463
|
+
if value is None:
|
|
464
|
+
return None
|
|
465
|
+
return value
|
|
466
|
+
|
|
467
|
+
|
|
445
468
|
class ExperimentRunOutput(TypedDict, total=False):
|
|
446
469
|
task_output: Any
|
|
447
470
|
|
|
448
471
|
|
|
449
472
|
class Base(DeclarativeBase):
|
|
450
|
-
id: Mapped[int] = mapped_column(primary_key=True)
|
|
451
473
|
# Enforce best practices for naming constraints
|
|
452
474
|
# https://alembic.sqlalchemy.org/en/latest/naming.html#integration-of-naming-conventions-into-operations-autogenerate
|
|
453
475
|
metadata = MetaData(
|
|
@@ -467,7 +489,12 @@ class Base(DeclarativeBase):
|
|
|
467
489
|
}
|
|
468
490
|
|
|
469
491
|
|
|
470
|
-
class
|
|
492
|
+
class HasId(Base):
|
|
493
|
+
__abstract__ = True
|
|
494
|
+
id: Mapped[int] = mapped_column(primary_key=True)
|
|
495
|
+
|
|
496
|
+
|
|
497
|
+
class ProjectTraceRetentionPolicy(HasId):
|
|
471
498
|
__tablename__ = "project_trace_retention_policies"
|
|
472
499
|
name: Mapped[str] = mapped_column(String, nullable=False)
|
|
473
500
|
cron_expression: Mapped[TraceRetentionCronExpression] = mapped_column(
|
|
@@ -479,7 +506,7 @@ class ProjectTraceRetentionPolicy(Base):
|
|
|
479
506
|
)
|
|
480
507
|
|
|
481
508
|
|
|
482
|
-
class Project(
|
|
509
|
+
class Project(HasId):
|
|
483
510
|
__tablename__ = "projects"
|
|
484
511
|
name: Mapped[str]
|
|
485
512
|
description: Mapped[Optional[str]]
|
|
@@ -519,7 +546,7 @@ class Project(Base):
|
|
|
519
546
|
)
|
|
520
547
|
|
|
521
548
|
|
|
522
|
-
class ProjectSession(
|
|
549
|
+
class ProjectSession(HasId):
|
|
523
550
|
__tablename__ = "project_sessions"
|
|
524
551
|
session_id: Mapped[str] = mapped_column(String, nullable=False, unique=True)
|
|
525
552
|
project_id: Mapped[int] = mapped_column(
|
|
@@ -536,7 +563,7 @@ class ProjectSession(Base):
|
|
|
536
563
|
)
|
|
537
564
|
|
|
538
565
|
|
|
539
|
-
class Trace(
|
|
566
|
+
class Trace(HasId):
|
|
540
567
|
__tablename__ = "traces"
|
|
541
568
|
project_rowid: Mapped[int] = mapped_column(
|
|
542
569
|
ForeignKey("projects.id", ondelete="CASCADE"),
|
|
@@ -591,13 +618,13 @@ class Trace(Base):
|
|
|
591
618
|
)
|
|
592
619
|
|
|
593
620
|
|
|
594
|
-
class Span(
|
|
621
|
+
class Span(HasId):
|
|
595
622
|
__tablename__ = "spans"
|
|
596
623
|
trace_rowid: Mapped[int] = mapped_column(
|
|
597
624
|
ForeignKey("traces.id", ondelete="CASCADE"),
|
|
598
625
|
index=True,
|
|
599
626
|
)
|
|
600
|
-
span_id: Mapped[str]
|
|
627
|
+
span_id: Mapped[str]
|
|
601
628
|
parent_id: Mapped[Optional[str]] = mapped_column(index=True)
|
|
602
629
|
name: Mapped[str]
|
|
603
630
|
span_kind: Mapped[str]
|
|
@@ -803,14 +830,27 @@ class NumDocuments(expression.FunctionElement[int]):
|
|
|
803
830
|
@compiles(NumDocuments)
|
|
804
831
|
def _(element: Any, compiler: SQLCompiler, **kw: Any) -> Any:
|
|
805
832
|
# See https://docs.sqlalchemy.org/en/20/core/compiler.html
|
|
806
|
-
array_length = (
|
|
807
|
-
func.json_array_length if isinstance(compiler, SQLiteCompiler) else func.jsonb_array_length
|
|
808
|
-
)
|
|
809
833
|
attributes, span_kind = list(element.clauses)
|
|
810
834
|
retrieval_docs = attributes[RETRIEVAL_DOCUMENTS]
|
|
811
|
-
num_retrieval_docs
|
|
835
|
+
num_retrieval_docs: Case[Any] | coalesce[Any]
|
|
812
836
|
reranker_docs = attributes[RERANKER_OUTPUT_DOCUMENTS]
|
|
813
|
-
num_reranker_docs
|
|
837
|
+
num_reranker_docs: Case[Any] | coalesce[Any]
|
|
838
|
+
if isinstance(compiler, SQLiteCompiler):
|
|
839
|
+
# SQLite's json_array_length returns 0 for non-array values
|
|
840
|
+
num_retrieval_docs = coalesce(func.json_array_length(retrieval_docs), 0)
|
|
841
|
+
num_reranker_docs = coalesce(func.json_array_length(reranker_docs), 0)
|
|
842
|
+
else:
|
|
843
|
+
# PostgreSQL's jsonb_array_length throws "cannot get array length of a scalar"
|
|
844
|
+
# for non-array values, so check the type first
|
|
845
|
+
num_retrieval_docs = sql.case(
|
|
846
|
+
(func.jsonb_typeof(retrieval_docs) == "array", func.jsonb_array_length(retrieval_docs)),
|
|
847
|
+
else_=0,
|
|
848
|
+
)
|
|
849
|
+
num_reranker_docs = sql.case(
|
|
850
|
+
(func.jsonb_typeof(reranker_docs) == "array", func.jsonb_array_length(reranker_docs)),
|
|
851
|
+
else_=0,
|
|
852
|
+
)
|
|
853
|
+
|
|
814
854
|
return compiler.process(
|
|
815
855
|
sql.case(
|
|
816
856
|
(func.upper(span_kind) == "RERANKER", num_reranker_docs),
|
|
@@ -894,15 +934,15 @@ async def init_models(engine: AsyncEngine) -> None:
|
|
|
894
934
|
)
|
|
895
935
|
|
|
896
936
|
|
|
897
|
-
class SpanAnnotation(
|
|
937
|
+
class SpanAnnotation(HasId):
|
|
898
938
|
__tablename__ = "span_annotations"
|
|
899
939
|
span_rowid: Mapped[int] = mapped_column(
|
|
900
940
|
ForeignKey("spans.id", ondelete="CASCADE"),
|
|
901
941
|
index=True,
|
|
902
942
|
)
|
|
903
943
|
name: Mapped[str]
|
|
904
|
-
label: Mapped[Optional[str]]
|
|
905
|
-
score: Mapped[Optional[float]]
|
|
944
|
+
label: Mapped[Optional[str]]
|
|
945
|
+
score: Mapped[Optional[float]]
|
|
906
946
|
explanation: Mapped[Optional[str]]
|
|
907
947
|
metadata_: Mapped[dict[str, Any]] = mapped_column("metadata")
|
|
908
948
|
annotator_kind: Mapped[Literal["LLM", "CODE", "HUMAN"]] = mapped_column(
|
|
@@ -934,15 +974,15 @@ class SpanAnnotation(Base):
|
|
|
934
974
|
)
|
|
935
975
|
|
|
936
976
|
|
|
937
|
-
class TraceAnnotation(
|
|
977
|
+
class TraceAnnotation(HasId):
|
|
938
978
|
__tablename__ = "trace_annotations"
|
|
939
979
|
trace_rowid: Mapped[int] = mapped_column(
|
|
940
980
|
ForeignKey("traces.id", ondelete="CASCADE"),
|
|
941
981
|
index=True,
|
|
942
982
|
)
|
|
943
983
|
name: Mapped[str]
|
|
944
|
-
label: Mapped[Optional[str]]
|
|
945
|
-
score: Mapped[Optional[float]]
|
|
984
|
+
label: Mapped[Optional[str]]
|
|
985
|
+
score: Mapped[Optional[float]]
|
|
946
986
|
explanation: Mapped[Optional[str]]
|
|
947
987
|
metadata_: Mapped[dict[str, Any]] = mapped_column("metadata")
|
|
948
988
|
annotator_kind: Mapped[Literal["LLM", "CODE", "HUMAN"]] = mapped_column(
|
|
@@ -971,7 +1011,7 @@ class TraceAnnotation(Base):
|
|
|
971
1011
|
)
|
|
972
1012
|
|
|
973
1013
|
|
|
974
|
-
class DocumentAnnotation(
|
|
1014
|
+
class DocumentAnnotation(HasId):
|
|
975
1015
|
__tablename__ = "document_annotations"
|
|
976
1016
|
span_rowid: Mapped[int] = mapped_column(
|
|
977
1017
|
ForeignKey("spans.id", ondelete="CASCADE"),
|
|
@@ -979,8 +1019,8 @@ class DocumentAnnotation(Base):
|
|
|
979
1019
|
)
|
|
980
1020
|
document_position: Mapped[int]
|
|
981
1021
|
name: Mapped[str]
|
|
982
|
-
label: Mapped[Optional[str]]
|
|
983
|
-
score: Mapped[Optional[float]]
|
|
1022
|
+
label: Mapped[Optional[str]]
|
|
1023
|
+
score: Mapped[Optional[float]]
|
|
984
1024
|
explanation: Mapped[Optional[str]]
|
|
985
1025
|
metadata_: Mapped[dict[str, Any]] = mapped_column("metadata")
|
|
986
1026
|
annotator_kind: Mapped[Literal["LLM", "CODE", "HUMAN"]] = mapped_column(
|
|
@@ -1012,7 +1052,44 @@ class DocumentAnnotation(Base):
|
|
|
1012
1052
|
)
|
|
1013
1053
|
|
|
1014
1054
|
|
|
1015
|
-
class
|
|
1055
|
+
class ProjectSessionAnnotation(HasId):
|
|
1056
|
+
__tablename__ = "project_session_annotations"
|
|
1057
|
+
project_session_id: Mapped[int] = mapped_column(
|
|
1058
|
+
ForeignKey("project_sessions.id", ondelete="CASCADE"),
|
|
1059
|
+
index=True,
|
|
1060
|
+
)
|
|
1061
|
+
name: Mapped[str]
|
|
1062
|
+
label: Mapped[Optional[str]]
|
|
1063
|
+
score: Mapped[Optional[float]]
|
|
1064
|
+
explanation: Mapped[Optional[str]]
|
|
1065
|
+
metadata_: Mapped[dict[str, Any]] = mapped_column("metadata")
|
|
1066
|
+
annotator_kind: Mapped[Literal["LLM", "CODE", "HUMAN"]] = mapped_column(
|
|
1067
|
+
CheckConstraint("annotator_kind IN ('LLM', 'CODE', 'HUMAN')", name="valid_annotator_kind"),
|
|
1068
|
+
)
|
|
1069
|
+
created_at: Mapped[datetime] = mapped_column(UtcTimeStamp, server_default=func.now())
|
|
1070
|
+
updated_at: Mapped[datetime] = mapped_column(
|
|
1071
|
+
UtcTimeStamp, server_default=func.now(), onupdate=func.now()
|
|
1072
|
+
)
|
|
1073
|
+
identifier: Mapped[str] = mapped_column(
|
|
1074
|
+
String,
|
|
1075
|
+
server_default="",
|
|
1076
|
+
nullable=False,
|
|
1077
|
+
)
|
|
1078
|
+
source: Mapped[Literal["API", "APP"]] = mapped_column(
|
|
1079
|
+
CheckConstraint("source IN ('API', 'APP')", name="valid_source"),
|
|
1080
|
+
)
|
|
1081
|
+
user_id: Mapped[Optional[int]] = mapped_column(ForeignKey("users.id", ondelete="SET NULL"))
|
|
1082
|
+
|
|
1083
|
+
__table_args__ = (
|
|
1084
|
+
UniqueConstraint(
|
|
1085
|
+
"name",
|
|
1086
|
+
"project_session_id",
|
|
1087
|
+
"identifier",
|
|
1088
|
+
),
|
|
1089
|
+
)
|
|
1090
|
+
|
|
1091
|
+
|
|
1092
|
+
class Dataset(HasId):
|
|
1016
1093
|
__tablename__ = "datasets"
|
|
1017
1094
|
name: Mapped[str] = mapped_column(unique=True)
|
|
1018
1095
|
description: Mapped[Optional[str]]
|
|
@@ -1021,6 +1098,14 @@ class Dataset(Base):
|
|
|
1021
1098
|
updated_at: Mapped[datetime] = mapped_column(
|
|
1022
1099
|
UtcTimeStamp, server_default=func.now(), onupdate=func.now()
|
|
1023
1100
|
)
|
|
1101
|
+
user_id: Mapped[Optional[int]] = mapped_column(ForeignKey("users.id", ondelete="SET NULL"))
|
|
1102
|
+
user: Mapped[Optional["User"]] = relationship("User")
|
|
1103
|
+
experiment_tags: Mapped[list["ExperimentTag"]] = relationship(
|
|
1104
|
+
"ExperimentTag", back_populates="dataset"
|
|
1105
|
+
)
|
|
1106
|
+
datasets_dataset_labels: Mapped[list["DatasetsDatasetLabel"]] = relationship(
|
|
1107
|
+
"DatasetsDatasetLabel", back_populates="dataset"
|
|
1108
|
+
)
|
|
1024
1109
|
|
|
1025
1110
|
@hybrid_property
|
|
1026
1111
|
def example_count(self) -> Optional[int]:
|
|
@@ -1071,7 +1156,45 @@ class Dataset(Base):
|
|
|
1071
1156
|
)
|
|
1072
1157
|
|
|
1073
1158
|
|
|
1074
|
-
class
|
|
1159
|
+
class DatasetLabel(HasId):
|
|
1160
|
+
__tablename__ = "dataset_labels"
|
|
1161
|
+
name: Mapped[str] = mapped_column(unique=True)
|
|
1162
|
+
description: Mapped[Optional[str]]
|
|
1163
|
+
color: Mapped[str] = mapped_column(_HexColor, nullable=False)
|
|
1164
|
+
datasets_dataset_labels: Mapped[list["DatasetsDatasetLabel"]] = relationship(
|
|
1165
|
+
"DatasetsDatasetLabel", back_populates="dataset_label"
|
|
1166
|
+
)
|
|
1167
|
+
user_id: Mapped[Optional[int]] = mapped_column(
|
|
1168
|
+
ForeignKey("users.id", ondelete="SET NULL"),
|
|
1169
|
+
nullable=True,
|
|
1170
|
+
)
|
|
1171
|
+
user: Mapped[Optional["User"]] = relationship("User")
|
|
1172
|
+
|
|
1173
|
+
|
|
1174
|
+
class DatasetsDatasetLabel(Base):
|
|
1175
|
+
__tablename__ = "datasets_dataset_labels"
|
|
1176
|
+
dataset_id: Mapped[int] = mapped_column(
|
|
1177
|
+
ForeignKey("datasets.id", ondelete="CASCADE"),
|
|
1178
|
+
)
|
|
1179
|
+
dataset_label_id: Mapped[int] = mapped_column(
|
|
1180
|
+
ForeignKey("dataset_labels.id", ondelete="CASCADE"),
|
|
1181
|
+
# index on the second element of the composite primary key
|
|
1182
|
+
index=True,
|
|
1183
|
+
)
|
|
1184
|
+
dataset: Mapped["Dataset"] = relationship("Dataset", back_populates="datasets_dataset_labels")
|
|
1185
|
+
dataset_label: Mapped["DatasetLabel"] = relationship(
|
|
1186
|
+
"DatasetLabel", back_populates="datasets_dataset_labels"
|
|
1187
|
+
)
|
|
1188
|
+
|
|
1189
|
+
__table_args__ = (
|
|
1190
|
+
PrimaryKeyConstraint(
|
|
1191
|
+
"dataset_id",
|
|
1192
|
+
"dataset_label_id",
|
|
1193
|
+
),
|
|
1194
|
+
)
|
|
1195
|
+
|
|
1196
|
+
|
|
1197
|
+
class DatasetVersion(HasId):
|
|
1075
1198
|
__tablename__ = "dataset_versions"
|
|
1076
1199
|
dataset_id: Mapped[int] = mapped_column(
|
|
1077
1200
|
ForeignKey("datasets.id", ondelete="CASCADE"),
|
|
@@ -1080,9 +1203,11 @@ class DatasetVersion(Base):
|
|
|
1080
1203
|
description: Mapped[Optional[str]]
|
|
1081
1204
|
metadata_: Mapped[dict[str, Any]] = mapped_column("metadata")
|
|
1082
1205
|
created_at: Mapped[datetime] = mapped_column(UtcTimeStamp, server_default=func.now())
|
|
1206
|
+
user_id: Mapped[Optional[int]] = mapped_column(ForeignKey("users.id", ondelete="SET NULL"))
|
|
1207
|
+
user: Mapped[Optional["User"]] = relationship("User")
|
|
1083
1208
|
|
|
1084
1209
|
|
|
1085
|
-
class DatasetExample(
|
|
1210
|
+
class DatasetExample(HasId):
|
|
1086
1211
|
__tablename__ = "dataset_examples"
|
|
1087
1212
|
dataset_id: Mapped[int] = mapped_column(
|
|
1088
1213
|
ForeignKey("datasets.id", ondelete="CASCADE"),
|
|
@@ -1096,13 +1221,20 @@ class DatasetExample(Base):
|
|
|
1096
1221
|
created_at: Mapped[datetime] = mapped_column(UtcTimeStamp, server_default=func.now())
|
|
1097
1222
|
|
|
1098
1223
|
span: Mapped[Optional[Span]] = relationship(back_populates="dataset_examples")
|
|
1224
|
+
dataset_splits_dataset_examples: Mapped[list["DatasetSplitDatasetExample"]] = relationship(
|
|
1225
|
+
"DatasetSplitDatasetExample",
|
|
1226
|
+
back_populates="dataset_example",
|
|
1227
|
+
)
|
|
1228
|
+
experiment_dataset_examples: Mapped[list["ExperimentDatasetExample"]] = relationship(
|
|
1229
|
+
"ExperimentDatasetExample",
|
|
1230
|
+
back_populates="dataset_example",
|
|
1231
|
+
)
|
|
1099
1232
|
|
|
1100
1233
|
|
|
1101
|
-
class DatasetExampleRevision(
|
|
1234
|
+
class DatasetExampleRevision(HasId):
|
|
1102
1235
|
__tablename__ = "dataset_example_revisions"
|
|
1103
1236
|
dataset_example_id: Mapped[int] = mapped_column(
|
|
1104
1237
|
ForeignKey("dataset_examples.id", ondelete="CASCADE"),
|
|
1105
|
-
index=True,
|
|
1106
1238
|
)
|
|
1107
1239
|
dataset_version_id: Mapped[int] = mapped_column(
|
|
1108
1240
|
ForeignKey("dataset_versions.id", ondelete="CASCADE"),
|
|
@@ -1118,6 +1250,11 @@ class DatasetExampleRevision(Base):
|
|
|
1118
1250
|
)
|
|
1119
1251
|
created_at: Mapped[datetime] = mapped_column(UtcTimeStamp, server_default=func.now())
|
|
1120
1252
|
|
|
1253
|
+
experiment_dataset_examples: Mapped[list["ExperimentDatasetExample"]] = relationship(
|
|
1254
|
+
"ExperimentDatasetExample",
|
|
1255
|
+
back_populates="dataset_example_revision",
|
|
1256
|
+
)
|
|
1257
|
+
|
|
1121
1258
|
__table_args__ = (
|
|
1122
1259
|
UniqueConstraint(
|
|
1123
1260
|
"dataset_example_id",
|
|
@@ -1126,7 +1263,56 @@ class DatasetExampleRevision(Base):
|
|
|
1126
1263
|
)
|
|
1127
1264
|
|
|
1128
1265
|
|
|
1129
|
-
class
|
|
1266
|
+
class DatasetSplit(HasId):
|
|
1267
|
+
__tablename__ = "dataset_splits"
|
|
1268
|
+
|
|
1269
|
+
user_id: Mapped[Optional[int]] = mapped_column(
|
|
1270
|
+
ForeignKey("users.id", ondelete="SET NULL"),
|
|
1271
|
+
nullable=True,
|
|
1272
|
+
index=True,
|
|
1273
|
+
)
|
|
1274
|
+
name: Mapped[str] = mapped_column(String, nullable=False, unique=True)
|
|
1275
|
+
description: Mapped[Optional[str]]
|
|
1276
|
+
color: Mapped[str] = mapped_column(String, nullable=False)
|
|
1277
|
+
metadata_: Mapped[dict[str, Any]] = mapped_column("metadata")
|
|
1278
|
+
created_at: Mapped[datetime] = mapped_column(UtcTimeStamp, server_default=func.now())
|
|
1279
|
+
updated_at: Mapped[datetime] = mapped_column(
|
|
1280
|
+
UtcTimeStamp, server_default=func.now(), onupdate=func.now()
|
|
1281
|
+
)
|
|
1282
|
+
dataset_splits_dataset_examples: Mapped[list["DatasetSplitDatasetExample"]] = relationship(
|
|
1283
|
+
"DatasetSplitDatasetExample",
|
|
1284
|
+
back_populates="dataset_split",
|
|
1285
|
+
)
|
|
1286
|
+
experiment_dataset_splits: Mapped[list["ExperimentDatasetSplit"]] = relationship(
|
|
1287
|
+
"ExperimentDatasetSplit",
|
|
1288
|
+
back_populates="dataset_split",
|
|
1289
|
+
)
|
|
1290
|
+
|
|
1291
|
+
|
|
1292
|
+
class DatasetSplitDatasetExample(Base):
|
|
1293
|
+
__tablename__ = "dataset_splits_dataset_examples"
|
|
1294
|
+
dataset_split_id: Mapped[int] = mapped_column(
|
|
1295
|
+
ForeignKey("dataset_splits.id", ondelete="CASCADE"),
|
|
1296
|
+
)
|
|
1297
|
+
dataset_example_id: Mapped[int] = mapped_column(
|
|
1298
|
+
ForeignKey("dataset_examples.id", ondelete="CASCADE"),
|
|
1299
|
+
index=True,
|
|
1300
|
+
)
|
|
1301
|
+
dataset_split: Mapped["DatasetSplit"] = relationship(
|
|
1302
|
+
"DatasetSplit", back_populates="dataset_splits_dataset_examples"
|
|
1303
|
+
)
|
|
1304
|
+
dataset_example: Mapped["DatasetExample"] = relationship(
|
|
1305
|
+
"DatasetExample", back_populates="dataset_splits_dataset_examples"
|
|
1306
|
+
)
|
|
1307
|
+
__table_args__ = (
|
|
1308
|
+
PrimaryKeyConstraint(
|
|
1309
|
+
"dataset_split_id",
|
|
1310
|
+
"dataset_example_id",
|
|
1311
|
+
),
|
|
1312
|
+
)
|
|
1313
|
+
|
|
1314
|
+
|
|
1315
|
+
class Experiment(HasId):
|
|
1130
1316
|
__tablename__ = "experiments"
|
|
1131
1317
|
dataset_id: Mapped[int] = mapped_column(
|
|
1132
1318
|
ForeignKey("datasets.id", ondelete="CASCADE"),
|
|
@@ -1141,18 +1327,83 @@ class Experiment(Base):
|
|
|
1141
1327
|
repetitions: Mapped[int]
|
|
1142
1328
|
metadata_: Mapped[dict[str, Any]] = mapped_column("metadata")
|
|
1143
1329
|
project_name: Mapped[Optional[str]] = mapped_column(index=True)
|
|
1330
|
+
user_id: Mapped[Optional[int]] = mapped_column(ForeignKey("users.id", ondelete="SET NULL"))
|
|
1144
1331
|
created_at: Mapped[datetime] = mapped_column(UtcTimeStamp, server_default=func.now())
|
|
1145
1332
|
updated_at: Mapped[datetime] = mapped_column(
|
|
1146
1333
|
UtcTimeStamp, server_default=func.now(), onupdate=func.now()
|
|
1147
1334
|
)
|
|
1335
|
+
user: Mapped[Optional["User"]] = relationship("User")
|
|
1336
|
+
experiment_dataset_splits: Mapped[list["ExperimentDatasetSplit"]] = relationship(
|
|
1337
|
+
"ExperimentDatasetSplit",
|
|
1338
|
+
back_populates="experiment",
|
|
1339
|
+
)
|
|
1340
|
+
experiment_dataset_examples: Mapped[list["ExperimentDatasetExample"]] = relationship(
|
|
1341
|
+
"ExperimentDatasetExample",
|
|
1342
|
+
back_populates="experiment",
|
|
1343
|
+
)
|
|
1344
|
+
experiment_tags: Mapped[list["ExperimentTag"]] = relationship(
|
|
1345
|
+
"ExperimentTag", back_populates="experiment"
|
|
1346
|
+
)
|
|
1148
1347
|
|
|
1149
1348
|
|
|
1150
|
-
class
|
|
1151
|
-
__tablename__ = "
|
|
1349
|
+
class ExperimentDatasetSplit(Base):
|
|
1350
|
+
__tablename__ = "experiments_dataset_splits"
|
|
1351
|
+
experiment_id: Mapped[int] = mapped_column(
|
|
1352
|
+
ForeignKey("experiments.id", ondelete="CASCADE"),
|
|
1353
|
+
)
|
|
1354
|
+
dataset_split_id: Mapped[int] = mapped_column(
|
|
1355
|
+
ForeignKey("dataset_splits.id", ondelete="CASCADE"),
|
|
1356
|
+
index=True,
|
|
1357
|
+
)
|
|
1358
|
+
experiment: Mapped["Experiment"] = relationship(
|
|
1359
|
+
"Experiment", back_populates="experiment_dataset_splits"
|
|
1360
|
+
)
|
|
1361
|
+
dataset_split: Mapped["DatasetSplit"] = relationship(
|
|
1362
|
+
"DatasetSplit", back_populates="experiment_dataset_splits"
|
|
1363
|
+
)
|
|
1364
|
+
__table_args__ = (
|
|
1365
|
+
PrimaryKeyConstraint(
|
|
1366
|
+
"experiment_id",
|
|
1367
|
+
"dataset_split_id",
|
|
1368
|
+
),
|
|
1369
|
+
)
|
|
1370
|
+
|
|
1371
|
+
|
|
1372
|
+
class ExperimentDatasetExample(Base):
|
|
1373
|
+
__tablename__ = "experiments_dataset_examples"
|
|
1152
1374
|
experiment_id: Mapped[int] = mapped_column(
|
|
1153
1375
|
ForeignKey("experiments.id", ondelete="CASCADE"),
|
|
1376
|
+
)
|
|
1377
|
+
dataset_example_id: Mapped[int] = mapped_column(
|
|
1378
|
+
ForeignKey("dataset_examples.id", ondelete="CASCADE"),
|
|
1154
1379
|
index=True,
|
|
1155
1380
|
)
|
|
1381
|
+
dataset_example_revision_id: Mapped[int] = mapped_column(
|
|
1382
|
+
ForeignKey("dataset_example_revisions.id", ondelete="CASCADE"),
|
|
1383
|
+
index=True,
|
|
1384
|
+
)
|
|
1385
|
+
experiment: Mapped["Experiment"] = relationship(
|
|
1386
|
+
"Experiment", back_populates="experiment_dataset_examples"
|
|
1387
|
+
)
|
|
1388
|
+
dataset_example: Mapped["DatasetExample"] = relationship(
|
|
1389
|
+
"DatasetExample", back_populates="experiment_dataset_examples"
|
|
1390
|
+
)
|
|
1391
|
+
dataset_example_revision: Mapped["DatasetExampleRevision"] = relationship(
|
|
1392
|
+
"DatasetExampleRevision", back_populates="experiment_dataset_examples"
|
|
1393
|
+
)
|
|
1394
|
+
__table_args__ = (
|
|
1395
|
+
PrimaryKeyConstraint(
|
|
1396
|
+
"experiment_id",
|
|
1397
|
+
"dataset_example_id",
|
|
1398
|
+
),
|
|
1399
|
+
)
|
|
1400
|
+
|
|
1401
|
+
|
|
1402
|
+
class ExperimentRun(HasId):
|
|
1403
|
+
__tablename__ = "experiment_runs"
|
|
1404
|
+
experiment_id: Mapped[int] = mapped_column(
|
|
1405
|
+
ForeignKey("experiments.id", ondelete="CASCADE"),
|
|
1406
|
+
)
|
|
1156
1407
|
dataset_example_id: Mapped[int] = mapped_column(
|
|
1157
1408
|
ForeignKey("dataset_examples.id", ondelete="CASCADE"),
|
|
1158
1409
|
index=True,
|
|
@@ -1192,11 +1443,10 @@ class ExperimentRun(Base):
|
|
|
1192
1443
|
)
|
|
1193
1444
|
|
|
1194
1445
|
|
|
1195
|
-
class ExperimentRunAnnotation(
|
|
1446
|
+
class ExperimentRunAnnotation(HasId):
|
|
1196
1447
|
__tablename__ = "experiment_run_annotations"
|
|
1197
1448
|
experiment_run_id: Mapped[int] = mapped_column(
|
|
1198
1449
|
ForeignKey("experiment_runs.id", ondelete="CASCADE"),
|
|
1199
|
-
index=True,
|
|
1200
1450
|
)
|
|
1201
1451
|
name: Mapped[str]
|
|
1202
1452
|
annotator_kind: Mapped[str] = mapped_column(
|
|
@@ -1223,13 +1473,36 @@ class ExperimentRunAnnotation(Base):
|
|
|
1223
1473
|
)
|
|
1224
1474
|
|
|
1225
1475
|
|
|
1226
|
-
class
|
|
1476
|
+
class ExperimentTag(HasId):
|
|
1477
|
+
__tablename__ = "experiment_tags"
|
|
1478
|
+
experiment_id: Mapped[int] = mapped_column(
|
|
1479
|
+
ForeignKey("experiments.id", ondelete="CASCADE"),
|
|
1480
|
+
index=True,
|
|
1481
|
+
)
|
|
1482
|
+
dataset_id: Mapped[int] = mapped_column(
|
|
1483
|
+
ForeignKey("datasets.id", ondelete="CASCADE"),
|
|
1484
|
+
)
|
|
1485
|
+
user_id: Mapped[Optional[int]] = mapped_column(
|
|
1486
|
+
ForeignKey("users.id", ondelete="SET NULL"),
|
|
1487
|
+
index=True,
|
|
1488
|
+
nullable=True,
|
|
1489
|
+
)
|
|
1490
|
+
name: Mapped[str]
|
|
1491
|
+
description: Mapped[Optional[str]]
|
|
1492
|
+
experiment: Mapped["Experiment"] = relationship("Experiment", back_populates="experiment_tags")
|
|
1493
|
+
dataset: Mapped["Dataset"] = relationship("Dataset", back_populates="experiment_tags")
|
|
1494
|
+
user: Mapped[Optional["User"]] = relationship("User")
|
|
1495
|
+
|
|
1496
|
+
__table_args__ = (UniqueConstraint("dataset_id", "name"),)
|
|
1497
|
+
|
|
1498
|
+
|
|
1499
|
+
class UserRole(HasId):
|
|
1227
1500
|
__tablename__ = "user_roles"
|
|
1228
1501
|
name: Mapped[UserRoleName] = mapped_column(unique=True, index=True)
|
|
1229
1502
|
users: Mapped[list["User"]] = relationship("User", back_populates="role")
|
|
1230
1503
|
|
|
1231
1504
|
|
|
1232
|
-
class User(
|
|
1505
|
+
class User(HasId):
|
|
1233
1506
|
__tablename__ = "users"
|
|
1234
1507
|
user_role_id: Mapped[int] = mapped_column(
|
|
1235
1508
|
ForeignKey("user_roles.id", ondelete="CASCADE"),
|
|
@@ -1339,7 +1612,41 @@ class OAuth2User(User):
|
|
|
1339
1612
|
)
|
|
1340
1613
|
|
|
1341
1614
|
|
|
1342
|
-
|
|
1615
|
+
def LDAPUser(
|
|
1616
|
+
*,
|
|
1617
|
+
email: str,
|
|
1618
|
+
username: str,
|
|
1619
|
+
unique_id: str | None = None,
|
|
1620
|
+
user_role_id: int | None = None,
|
|
1621
|
+
) -> OAuth2User:
|
|
1622
|
+
"""Factory function to create an LDAP user stored as OAuth2User.
|
|
1623
|
+
|
|
1624
|
+
This is a zero-migration approach: LDAP users are stored in the existing
|
|
1625
|
+
OAuth2User table with a special Unicode marker in oauth2_client_id to
|
|
1626
|
+
distinguish them from actual OAuth2 users. This avoids schema changes
|
|
1627
|
+
while allowing LDAP authentication to coexist with OAuth2.
|
|
1628
|
+
|
|
1629
|
+
Args:
|
|
1630
|
+
email: User's email address
|
|
1631
|
+
username: User's display name
|
|
1632
|
+
unique_id: User's LDAP unique ID (stored in oauth2_user_id)
|
|
1633
|
+
user_role_id: Phoenix role ID (ADMIN, MEMBER, VIEWER)
|
|
1634
|
+
|
|
1635
|
+
Returns:
|
|
1636
|
+
OAuth2User instance configured as an LDAP user
|
|
1637
|
+
"""
|
|
1638
|
+
from phoenix.server.ldap import LDAP_CLIENT_ID_MARKER
|
|
1639
|
+
|
|
1640
|
+
return OAuth2User(
|
|
1641
|
+
email=email,
|
|
1642
|
+
username=username,
|
|
1643
|
+
oauth2_client_id=LDAP_CLIENT_ID_MARKER,
|
|
1644
|
+
oauth2_user_id=unique_id,
|
|
1645
|
+
user_role_id=user_role_id,
|
|
1646
|
+
)
|
|
1647
|
+
|
|
1648
|
+
|
|
1649
|
+
class PasswordResetToken(HasId):
|
|
1343
1650
|
__tablename__ = "password_reset_tokens"
|
|
1344
1651
|
user_id: Mapped[int] = mapped_column(
|
|
1345
1652
|
ForeignKey("users.id", ondelete="CASCADE"),
|
|
@@ -1348,11 +1655,11 @@ class PasswordResetToken(Base):
|
|
|
1348
1655
|
)
|
|
1349
1656
|
user: Mapped["User"] = relationship("User", back_populates="password_reset_token")
|
|
1350
1657
|
created_at: Mapped[datetime] = mapped_column(UtcTimeStamp, server_default=func.now())
|
|
1351
|
-
expires_at: Mapped[
|
|
1658
|
+
expires_at: Mapped[datetime] = mapped_column(UtcTimeStamp, nullable=False, index=True)
|
|
1352
1659
|
__table_args__ = (dict(sqlite_autoincrement=True),)
|
|
1353
1660
|
|
|
1354
1661
|
|
|
1355
|
-
class RefreshToken(
|
|
1662
|
+
class RefreshToken(HasId):
|
|
1356
1663
|
__tablename__ = "refresh_tokens"
|
|
1357
1664
|
user_id: Mapped[int] = mapped_column(
|
|
1358
1665
|
ForeignKey("users.id", ondelete="CASCADE"),
|
|
@@ -1360,11 +1667,11 @@ class RefreshToken(Base):
|
|
|
1360
1667
|
)
|
|
1361
1668
|
user: Mapped["User"] = relationship("User", back_populates="refresh_tokens")
|
|
1362
1669
|
created_at: Mapped[datetime] = mapped_column(UtcTimeStamp, server_default=func.now())
|
|
1363
|
-
expires_at: Mapped[
|
|
1670
|
+
expires_at: Mapped[datetime] = mapped_column(UtcTimeStamp, nullable=False, index=True)
|
|
1364
1671
|
__table_args__ = (dict(sqlite_autoincrement=True),)
|
|
1365
1672
|
|
|
1366
1673
|
|
|
1367
|
-
class AccessToken(
|
|
1674
|
+
class AccessToken(HasId):
|
|
1368
1675
|
__tablename__ = "access_tokens"
|
|
1369
1676
|
user_id: Mapped[int] = mapped_column(
|
|
1370
1677
|
ForeignKey("users.id", ondelete="CASCADE"),
|
|
@@ -1372,7 +1679,7 @@ class AccessToken(Base):
|
|
|
1372
1679
|
)
|
|
1373
1680
|
user: Mapped["User"] = relationship("User", back_populates="access_tokens")
|
|
1374
1681
|
created_at: Mapped[datetime] = mapped_column(UtcTimeStamp, server_default=func.now())
|
|
1375
|
-
expires_at: Mapped[
|
|
1682
|
+
expires_at: Mapped[datetime] = mapped_column(UtcTimeStamp, nullable=False, index=True)
|
|
1376
1683
|
refresh_token_id: Mapped[int] = mapped_column(
|
|
1377
1684
|
ForeignKey("refresh_tokens.id", ondelete="CASCADE"),
|
|
1378
1685
|
index=True,
|
|
@@ -1381,7 +1688,7 @@ class AccessToken(Base):
|
|
|
1381
1688
|
__table_args__ = (dict(sqlite_autoincrement=True),)
|
|
1382
1689
|
|
|
1383
1690
|
|
|
1384
|
-
class ApiKey(
|
|
1691
|
+
class ApiKey(HasId):
|
|
1385
1692
|
__tablename__ = "api_keys"
|
|
1386
1693
|
user_id: Mapped[int] = mapped_column(
|
|
1387
1694
|
ForeignKey("users.id", ondelete="CASCADE"),
|
|
@@ -1398,7 +1705,7 @@ class ApiKey(Base):
|
|
|
1398
1705
|
CostType: TypeAlias = Literal["DEFAULT", "OVERRIDE"]
|
|
1399
1706
|
|
|
1400
1707
|
|
|
1401
|
-
class GenerativeModel(
|
|
1708
|
+
class GenerativeModel(HasId):
|
|
1402
1709
|
__tablename__ = "generative_models"
|
|
1403
1710
|
name: Mapped[str] = mapped_column(String, nullable=False)
|
|
1404
1711
|
provider: Mapped[str]
|
|
@@ -1447,7 +1754,7 @@ class GenerativeModel(Base):
|
|
|
1447
1754
|
)
|
|
1448
1755
|
|
|
1449
1756
|
|
|
1450
|
-
class TokenPrice(
|
|
1757
|
+
class TokenPrice(HasId):
|
|
1451
1758
|
__tablename__ = "token_prices"
|
|
1452
1759
|
model_id: Mapped[int] = mapped_column(
|
|
1453
1760
|
ForeignKey("generative_models.id", ondelete="CASCADE"),
|
|
@@ -1473,7 +1780,7 @@ class TokenPrice(Base):
|
|
|
1473
1780
|
)
|
|
1474
1781
|
|
|
1475
1782
|
|
|
1476
|
-
class PromptLabel(
|
|
1783
|
+
class PromptLabel(HasId):
|
|
1477
1784
|
__tablename__ = "prompt_labels"
|
|
1478
1785
|
name: Mapped[str] = mapped_column(String, unique=True, index=True, nullable=False)
|
|
1479
1786
|
description: Mapped[Optional[str]]
|
|
@@ -1487,7 +1794,7 @@ class PromptLabel(Base):
|
|
|
1487
1794
|
)
|
|
1488
1795
|
|
|
1489
1796
|
|
|
1490
|
-
class Prompt(
|
|
1797
|
+
class Prompt(HasId):
|
|
1491
1798
|
__tablename__ = "prompts"
|
|
1492
1799
|
source_prompt_id: Mapped[Optional[int]] = mapped_column(
|
|
1493
1800
|
ForeignKey("prompts.id", ondelete="SET NULL"),
|
|
@@ -1524,7 +1831,7 @@ class Prompt(Base):
|
|
|
1524
1831
|
)
|
|
1525
1832
|
|
|
1526
1833
|
|
|
1527
|
-
class PromptPromptLabel(
|
|
1834
|
+
class PromptPromptLabel(HasId):
|
|
1528
1835
|
__tablename__ = "prompts_prompt_labels"
|
|
1529
1836
|
prompt_label_id: Mapped[int] = mapped_column(
|
|
1530
1837
|
ForeignKey("prompt_labels.id", ondelete="CASCADE"),
|
|
@@ -1545,7 +1852,7 @@ class PromptPromptLabel(Base):
|
|
|
1545
1852
|
__table_args__ = (UniqueConstraint("prompt_label_id", "prompt_id"),)
|
|
1546
1853
|
|
|
1547
1854
|
|
|
1548
|
-
class PromptVersion(
|
|
1855
|
+
class PromptVersion(HasId):
|
|
1549
1856
|
__tablename__ = "prompt_versions"
|
|
1550
1857
|
|
|
1551
1858
|
prompt_id: Mapped[int] = mapped_column(
|
|
@@ -1594,7 +1901,7 @@ class PromptVersion(Base):
|
|
|
1594
1901
|
)
|
|
1595
1902
|
|
|
1596
1903
|
|
|
1597
|
-
class PromptVersionTag(
|
|
1904
|
+
class PromptVersionTag(HasId):
|
|
1598
1905
|
__tablename__ = "prompt_version_tags"
|
|
1599
1906
|
|
|
1600
1907
|
name: Mapped[Identifier] = mapped_column(_Identifier, nullable=False)
|
|
@@ -1623,13 +1930,13 @@ class PromptVersionTag(Base):
|
|
|
1623
1930
|
__table_args__ = (UniqueConstraint("name", "prompt_id"),)
|
|
1624
1931
|
|
|
1625
1932
|
|
|
1626
|
-
class AnnotationConfig(
|
|
1933
|
+
class AnnotationConfig(HasId):
|
|
1627
1934
|
__tablename__ = "annotation_configs"
|
|
1628
1935
|
name: Mapped[str] = mapped_column(String, nullable=False, unique=True)
|
|
1629
1936
|
config: Mapped[AnnotationConfigType] = mapped_column(_AnnotationConfig, nullable=False)
|
|
1630
1937
|
|
|
1631
1938
|
|
|
1632
|
-
class ProjectAnnotationConfig(
|
|
1939
|
+
class ProjectAnnotationConfig(HasId):
|
|
1633
1940
|
__tablename__ = "project_annotation_configs"
|
|
1634
1941
|
project_id: Mapped[int] = mapped_column(
|
|
1635
1942
|
ForeignKey("projects.id", ondelete="CASCADE"), nullable=False, index=True
|
|
@@ -1641,16 +1948,18 @@ class ProjectAnnotationConfig(Base):
|
|
|
1641
1948
|
__table_args__ = (UniqueConstraint("project_id", "annotation_config_id"),)
|
|
1642
1949
|
|
|
1643
1950
|
|
|
1644
|
-
class SpanCost(
|
|
1951
|
+
class SpanCost(HasId):
|
|
1645
1952
|
__tablename__ = "span_costs"
|
|
1646
1953
|
|
|
1647
1954
|
span_rowid: Mapped[int] = mapped_column(
|
|
1648
1955
|
ForeignKey("spans.id", ondelete="CASCADE"),
|
|
1649
1956
|
nullable=False,
|
|
1957
|
+
index=True,
|
|
1650
1958
|
)
|
|
1651
1959
|
trace_rowid: Mapped[int] = mapped_column(
|
|
1652
1960
|
ForeignKey("traces.id", ondelete="CASCADE"),
|
|
1653
1961
|
nullable=False,
|
|
1962
|
+
index=True,
|
|
1654
1963
|
)
|
|
1655
1964
|
span_start_time: Mapped[datetime] = mapped_column(
|
|
1656
1965
|
UtcTimeStamp,
|
|
@@ -1753,14 +2062,13 @@ class SpanCost(Base):
|
|
|
1753
2062
|
self.total_tokens = (self.total_tokens or 0) + tokens
|
|
1754
2063
|
|
|
1755
2064
|
|
|
1756
|
-
class SpanCostDetail(
|
|
2065
|
+
class SpanCostDetail(HasId):
|
|
1757
2066
|
__tablename__ = "span_cost_details"
|
|
1758
2067
|
span_cost_id: Mapped[int] = mapped_column(
|
|
1759
2068
|
ForeignKey("span_costs.id", ondelete="CASCADE"),
|
|
1760
2069
|
nullable=False,
|
|
1761
|
-
index=True,
|
|
1762
2070
|
)
|
|
1763
|
-
token_type: Mapped[str]
|
|
2071
|
+
token_type: Mapped[str] = mapped_column(index=True)
|
|
1764
2072
|
is_prompt: Mapped[bool]
|
|
1765
2073
|
|
|
1766
2074
|
cost: Mapped[Optional[float]]
|