Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions backend/src/common/crud_enum.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,11 @@
from modules.ml.tag_recommendation.tag_recommendation_crud import (
crud_tag_recommendation_link,
)
from modules.perspectives.aspect_crud import crud_aspect
from modules.perspectives.cluster_crud import crud_cluster
from modules.perspectives.document_aspect_crud import crud_document_aspect
from modules.perspectives.aspect.aspect_crud import crud_aspect
from modules.perspectives.cluster.cluster_crud import crud_cluster
from modules.perspectives.document_aspect.document_aspect_crud import (
crud_document_aspect,
)
from modules.timeline_analysis.timeline_analysis_crud import (
crud_timeline_analysis,
)
Expand Down
31 changes: 30 additions & 1 deletion backend/src/core/doc/source_document_data_crud.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
from sqlalchemy.orm import Session

from common.doc_type import DocType
from core.doc.source_document_data_dto import (
SourceDocumentDataCreate,
SourceDocumentDataUpdate,
)
from core.doc.source_document_data_orm import SourceDocumentDataORM
from core.doc.source_document_orm import SourceDocumentORM
from core.tag.tag_orm import TagORM
from repos.db.crud_base import CRUDBase


Expand All @@ -13,7 +18,31 @@ class CRUDSourceDocumentData(
SourceDocumentDataUpdate,
]
):
pass
def read_by_doctype_and_tag(
self,
db: Session,
*,
project_id: int,
tag_id: int | None,
doctype: DocType,
) -> list[SourceDocumentDataORM]:
query = (
db.query(SourceDocumentDataORM)
.join(SourceDocumentORM, SourceDocumentORM.id == SourceDocumentDataORM.id)
.filter(
SourceDocumentORM.project_id == project_id,
SourceDocumentORM.doctype == doctype,
)
)

if tag_id is not None:
query = query.join(
SourceDocumentORM.tags,
).filter(
SourceDocumentORM.tags.any(TagORM.id == tag_id),
)

return query.all()


crud_sdoc_data = CRUDSourceDocumentData(SourceDocumentDataORM)
12 changes: 8 additions & 4 deletions backend/src/core/doc/source_document_orm.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,14 @@
from modules.ml.tag_recommendation.tag_recommendation_orm import (
TagRecommendationLinkORM,
)
from modules.perspectives.aspect_orm import AspectORM
from modules.perspectives.cluster_orm import ClusterORM
from modules.perspectives.document_aspect_orm import DocumentAspectORM
from modules.perspectives.document_cluster_orm import DocumentClusterORM
from modules.perspectives.aspect.aspect_orm import AspectORM
from modules.perspectives.cluster.cluster_orm import ClusterORM
from modules.perspectives.document_aspect.document_aspect_orm import (
DocumentAspectORM,
)
from modules.perspectives.document_cluster.document_cluster_orm import (
DocumentClusterORM,
)
from modules.word_frequency.word_frequency_orm import WordFrequencyORM


Expand Down
2 changes: 1 addition & 1 deletion backend/src/core/project/project_orm.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
from core.tag.tag_orm import TagORM
from core.user.user_orm import UserORM
from modules.classifier.classifier_orm import ClassifierORM
from modules.perspectives.aspect_orm import AspectORM
from modules.perspectives.aspect.aspect_orm import AspectORM
from modules.whiteboard.whiteboard_orm import WhiteboardORM


Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
"""add history table

Revision ID: 02320d77b8dd
Revises: 7e88b47a2f6c
Create Date: 2025-12-11 15:04:12.210086

"""

from typing import Sequence

import sqlalchemy as sa
from alembic import op

# revision identifiers, used by Alembic.
revision: str = "02320d77b8dd"
down_revision: str | None = "7e88b47a2f6c"
branch_labels: str | Sequence[str] | None = None
depends_on: str | Sequence[str] | None = None


def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.create_table(
"perspectivehistory",
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("history_number", sa.Integer(), nullable=False),
sa.Column("is_undone", sa.Boolean(), nullable=False),
sa.Column("undo_data", sa.JSON(), nullable=False),
sa.Column("redo_data", sa.JSON(), nullable=False),
sa.Column("aspect_id", sa.Integer(), nullable=False),
sa.ForeignKeyConstraint(
["aspect_id"],
["aspect.id"],
),
sa.PrimaryKeyConstraint("id"),
)
# ### end Alembic commands ###


def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table("perspectivehistory")
# ### end Alembic commands ###
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
"""add perspectives_action to perspectivehistory

Revision ID: 4e79b051e348
Revises: 02320d77b8dd
Create Date: 2025-12-17 13:02:39.967887

"""

from typing import Sequence

import sqlalchemy as sa
from alembic import op

# revision identifiers, used by Alembic.
revision: str = "4e79b051e348"
down_revision: str | None = "02320d77b8dd"
branch_labels: str | Sequence[str] | None = None
depends_on: str | Sequence[str] | None = None


def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.add_column(
"perspectivehistory",
sa.Column("perspectives_action", sa.String(), nullable=False),
)
# ### end Alembic commands ###


def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column("perspectivehistory", "perspectives_action")
# ### end Alembic commands ###
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
"""remove is_hierarchical column from aspect table

Revision ID: 6617866c6b24
Revises: 4e79b051e348
Create Date: 2025-12-17 13:57:21.059533

"""

from typing import Sequence

import sqlalchemy as sa
from alembic import op

# revision identifiers, used by Alembic.
revision: str = "6617866c6b24"
down_revision: str | None = "4e79b051e348"
branch_labels: str | Sequence[str] | None = None
depends_on: str | Sequence[str] | None = None


def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column("aspect", "is_hierarchical")
# ### end Alembic commands ###


def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.add_column(
"aspect",
sa.Column("is_hierarchical", sa.BOOLEAN(), autoincrement=False, nullable=False),
)
# ### end Alembic commands ###
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
"""remove cluster hierarchy

Revision ID: 7e88b47a2f6c
Revises: 781d4852a256
Create Date: 2025-12-11 09:22:57.085470

"""

from typing import Sequence

import sqlalchemy as sa
from alembic import op

# revision identifiers, used by Alembic.
revision: str = "7e88b47a2f6c"
down_revision: str | None = "781d4852a256"
branch_labels: str | Sequence[str] | None = None
depends_on: str | Sequence[str] | None = None


def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_index("ix_cluster_parent_cluster_id", table_name="cluster")
op.drop_constraint("cluster_parent_cluster_id_fkey", "cluster", type_="foreignkey")
op.drop_column("cluster", "parent_cluster_id")
op.drop_column("cluster", "level")
# ### end Alembic commands ###


def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.add_column(
"cluster", sa.Column("level", sa.INTEGER(), autoincrement=False, nullable=False)
)
op.add_column(
"cluster",
sa.Column(
"parent_cluster_id", sa.INTEGER(), autoincrement=False, nullable=True
),
)
op.create_foreign_key(
"cluster_parent_cluster_id_fkey",
"cluster",
"cluster",
["parent_cluster_id"],
["id"],
ondelete="SET NULL",
)
op.create_index(
"ix_cluster_parent_cluster_id", "cluster", ["parent_cluster_id"], unique=False
)
# ### end Alembic commands ###
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from modules.perspectives.aspect_dto import AspectCreate, AspectUpdateIntern
from modules.perspectives.aspect_orm import AspectORM
from modules.perspectives.aspect.aspect_dto import AspectCreate, AspectUpdateIntern
from modules.perspectives.aspect.aspect_orm import AspectORM
from repos.db.crud_base import CRUDBase


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ class AspectBase(BaseModel):
doc_modification_prompt: str | None = Field(
default=None, description="Prompt for document modification"
)
is_hierarchical: bool = Field(description="Whether the aspect is hierarchical")
modality: DocType = Field(description="Modality of the documents of this aspect")
pipeline_settings: PipelineSettings = Field(
description="Pipeline settings for this aspect"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from weaviate import WeaviateClient
from weaviate.classes.query import Filter

from modules.perspectives.aspect_collection import AspectCollection
from modules.perspectives.aspect_embedding_dto import AspectObjectIdentifier
from modules.perspectives.aspect.aspect_collection import AspectCollection
from modules.perspectives.aspect.aspect_embedding_dto import AspectObjectIdentifier
from repos.vector.embedding_crud_base import CRUDBase
from systems.event_system.events import project_deleted, source_document_deleted

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from typing import TYPE_CHECKING

from sqlalchemy import Boolean, ForeignKey, Integer, String, Text, text
from sqlalchemy import ForeignKey, Integer, String, Text, text
from sqlalchemy.dialects.postgresql import JSONB
from sqlalchemy.orm import Mapped, mapped_column, relationship

Expand All @@ -10,8 +10,11 @@
if TYPE_CHECKING:
from core.doc.source_document_orm import SourceDocumentORM
from core.project.project_orm import ProjectORM
from modules.perspectives.cluster_orm import ClusterORM
from modules.perspectives.document_aspect_orm import DocumentAspectORM
from modules.perspectives.cluster.cluster_orm import ClusterORM
from modules.perspectives.document_aspect.document_aspect_orm import (
DocumentAspectORM,
)
from modules.perspectives.history.history_orm import PerspectiveHistoryORM


class AspectORM(ORMBase):
Expand All @@ -20,9 +23,6 @@ class AspectORM(ORMBase):
name: Mapped[str] = mapped_column(String, nullable=False)
doc_embedding_prompt: Mapped[str] = mapped_column(Text, nullable=False)
doc_modification_prompt: Mapped[str | None] = mapped_column(Text, nullable=True)
is_hierarchical: Mapped[bool] = mapped_column(
Boolean, default=False, nullable=False
)
most_recent_job_id: Mapped[str | None] = mapped_column(String, nullable=True)
embedding_model: Mapped[str] = mapped_column(
String, server_default="default", nullable=False
Expand Down Expand Up @@ -54,6 +54,10 @@ class AspectORM(ORMBase):
"ClusterORM", back_populates="aspect", cascade="all, delete-orphan"
)

histories: Mapped[list["PerspectiveHistoryORM"]] = relationship(
"PerspectiveHistoryORM", back_populates="aspect", cascade="all, delete-orphan"
)

# many to many
document_aspects: Mapped[list["DocumentAspectORM"]] = relationship(
"DocumentAspectORM", back_populates="aspect", cascade="all, delete-orphan"
Expand Down
37 changes: 37 additions & 0 deletions backend/src/modules/perspectives/cluster/cluster_crud.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
from modules.perspectives.cluster.cluster_dto import (
ClusterCreateIntern,
ClusterUpdateIntern,
)
from modules.perspectives.cluster.cluster_orm import ClusterORM
from modules.perspectives.document_cluster.document_cluster_orm import (
DocumentClusterORM,
)
from repos.db.crud_base import CRUDBase


class CRUDCluster(CRUDBase[ClusterORM, ClusterCreateIntern, ClusterUpdateIntern]):
def read_outlier_cluster(self, db, *, aspect_id: int) -> ClusterORM | None:
return (
db.query(self.model)
.filter(
self.model.aspect_id == aspect_id,
self.model.is_outlier.is_(True),
)
.first()
)

def read_by_aspect_and_sdoc(
self, db, *, aspect_id: int, sdoc_id: int
) -> list[ClusterORM]:
return (
db.query(self.model)
.join(DocumentClusterORM, DocumentClusterORM.cluster_id == self.model.id)
.filter(
self.model.aspect_id == aspect_id,
DocumentClusterORM.sdoc_id == sdoc_id,
)
.all()
)


crud_cluster = CRUDCluster(ClusterORM)
Loading
Loading