From 00229d2abedf898f1cb2510bfd3577311beb9716 Mon Sep 17 00:00:00 2001 From: pablodanswer Date: Fri, 20 Sep 2024 09:39:34 -0700 Subject: [PATCH] Add start date to persona (#2407) * add start date to persona * remove logs * rename * update assistant editor * update alembic * update alembic * update alembic * udpate alembic * remove rebase artifacts --- .../797089dfb4d2_persona_start_date.py | 27 +++++++++++++++++++ backend/danswer/db/models.py | 3 +++ backend/danswer/db/persona.py | 4 +++ .../search/preprocessing/preprocessing.py | 5 +++- .../danswer/server/features/persona/models.py | 5 +++- .../app/admin/assistants/AssistantEditor.tsx | 25 +++++++++++++++-- web/src/app/admin/assistants/interfaces.ts | 1 + web/src/app/admin/assistants/lib.ts | 5 +++- web/src/components/admin/connectors/Field.tsx | 4 ++- 9 files changed, 73 insertions(+), 6 deletions(-) create mode 100644 backend/alembic/versions/797089dfb4d2_persona_start_date.py diff --git a/backend/alembic/versions/797089dfb4d2_persona_start_date.py b/backend/alembic/versions/797089dfb4d2_persona_start_date.py new file mode 100644 index 000000000..52ade3dea --- /dev/null +++ b/backend/alembic/versions/797089dfb4d2_persona_start_date.py @@ -0,0 +1,27 @@ +"""persona_start_date + +Revision ID: 797089dfb4d2 +Revises: 55546a7967ee +Create Date: 2024-09-11 14:51:49.785835 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = "797089dfb4d2" +down_revision = "55546a7967ee" +branch_labels = None +depends_on = None + + +def upgrade() -> None: + op.add_column( + "persona", + sa.Column("search_start_date", sa.DateTime(timezone=True), nullable=True), + ) + + +def downgrade() -> None: + op.drop_column("persona", "search_start_date") diff --git a/backend/danswer/db/models.py b/backend/danswer/db/models.py index 70e583ad9..aecb1d9f9 100644 --- a/backend/danswer/db/models.py +++ b/backend/danswer/db/models.py @@ -1314,6 +1314,9 @@ class Persona(Base): starter_messages: Mapped[list[StarterMessage] | None] = mapped_column( postgresql.JSONB(), nullable=True ) + search_start_date: Mapped[datetime.datetime | None] = mapped_column( + DateTime(timezone=True), default=None + ) # Built-in personas are configured via backend during deployment # Treated specially (cannot be user edited etc.) builtin_persona: Mapped[bool] = mapped_column(Boolean, default=False) diff --git a/backend/danswer/db/persona.py b/backend/danswer/db/persona.py index 316919e58..36d2d25c4 100644 --- a/backend/danswer/db/persona.py +++ b/backend/danswer/db/persona.py @@ -1,4 +1,5 @@ from collections.abc import Sequence +from datetime import datetime from functools import lru_cache from uuid import UUID @@ -414,6 +415,7 @@ def upsert_persona( display_priority: int | None = None, is_visible: bool = True, remove_image: bool | None = None, + search_start_date: datetime | None = None, builtin_persona: bool = False, is_default_persona: bool = False, chunks_above: int = CONTEXT_CHUNKS_ABOVE, @@ -484,6 +486,7 @@ def upsert_persona( persona.uploaded_image_id = uploaded_image_id persona.display_priority = display_priority persona.is_visible = is_visible + persona.search_start_date = search_start_date persona.is_default_persona = is_default_persona # Do not delete any associations manually added unless @@ -524,6 +527,7 @@ def upsert_persona( uploaded_image_id=uploaded_image_id, display_priority=display_priority, is_visible=is_visible, + search_start_date=search_start_date, is_default_persona=is_default_persona, ) db_session.add(persona) diff --git a/backend/danswer/search/preprocessing/preprocessing.py b/backend/danswer/search/preprocessing/preprocessing.py index 43a6a43ce..37fb25488 100644 --- a/backend/danswer/search/preprocessing/preprocessing.py +++ b/backend/danswer/search/preprocessing/preprocessing.py @@ -67,6 +67,9 @@ def retrieval_preprocessing( ] time_filter = preset_filters.time_cutoff + if time_filter is None and persona: + time_filter = persona.search_start_date + source_filter = preset_filters.source_type auto_detect_time_filter = True @@ -154,7 +157,7 @@ def retrieval_preprocessing( final_filters = IndexFilters( source_type=preset_filters.source_type or predicted_source_filters, document_set=preset_filters.document_set, - time_cutoff=preset_filters.time_cutoff or predicted_time_cutoff, + time_cutoff=time_filter or predicted_time_cutoff, tags=preset_filters.tags, # Tags are never auto-extracted access_control_list=user_acl_filters, ) diff --git a/backend/danswer/server/features/persona/models.py b/backend/danswer/server/features/persona/models.py index 0112cc110..016defda3 100644 --- a/backend/danswer/server/features/persona/models.py +++ b/backend/danswer/server/features/persona/models.py @@ -1,3 +1,4 @@ +from datetime import datetime from uuid import UUID from pydantic import BaseModel @@ -12,7 +13,6 @@ from danswer.server.features.tool.api import ToolSnapshot from danswer.server.models import MinimalUserSnapshot from danswer.utils.logger import setup_logger - logger = setup_logger() @@ -40,6 +40,7 @@ class CreatePersonaRequest(BaseModel): remove_image: bool | None = None is_default_persona: bool = False display_priority: int | None = None + search_start_date: datetime | None = None class PersonaSnapshot(BaseModel): @@ -66,6 +67,7 @@ class PersonaSnapshot(BaseModel): icon_shape: int | None uploaded_image_id: str | None = None is_default_persona: bool + search_start_date: datetime | None = None @classmethod def from_model( @@ -112,6 +114,7 @@ class PersonaSnapshot(BaseModel): icon_color=persona.icon_color, icon_shape=persona.icon_shape, uploaded_image_id=persona.uploaded_image_id, + search_start_date=persona.search_start_date, ) diff --git a/web/src/app/admin/assistants/AssistantEditor.tsx b/web/src/app/admin/assistants/AssistantEditor.tsx index 4951f459b..1f961614d 100644 --- a/web/src/app/admin/assistants/AssistantEditor.tsx +++ b/web/src/app/admin/assistants/AssistantEditor.tsx @@ -2,7 +2,7 @@ import { generateRandomIconShape, createSVG } from "@/lib/assistantIconUtils"; -import { CCPairBasicInfo, DocumentSet, User, UserRole } from "@/lib/types"; +import { CCPairBasicInfo, DocumentSet, User } from "@/lib/types"; import { Button, Divider, Italic } from "@tremor/react"; import { IsPublicGroupSelector } from "@/components/IsPublicGroupSelector"; import { @@ -230,6 +230,9 @@ export function AssistantEditor({ existingPersona?.document_sets?.map((documentSet) => documentSet.id) ?? ([] as number[]), num_chunks: existingPersona?.num_chunks ?? null, + search_start_date: existingPersona?.search_start_date + ? existingPersona?.search_start_date.toString().split("T")[0] + : null, include_citations: existingPersona?.prompts[0]?.include_citations ?? true, llm_relevance_filter: existingPersona?.llm_relevance_filter ?? false, llm_model_provider_override: @@ -284,6 +287,7 @@ export function AssistantEditor({ ), }) ), + search_start_date: Yup.date().nullable(), icon_color: Yup.string(), icon_shape: Yup.number(), uploaded_image: Yup.mixed().nullable(), @@ -373,6 +377,9 @@ export function AssistantEditor({ id: existingPersona.id, existingPromptId: existingPrompt?.id, ...values, + search_start_date: values.search_start_date + ? new Date(values.search_start_date) + : null, num_chunks: numChunks, users: user && !checkUserIsNoAuthUser(user.id) ? [user.id] : undefined, @@ -385,6 +392,9 @@ export function AssistantEditor({ ...values, is_default_persona: admin!, num_chunks: numChunks, + search_start_date: values.search_start_date + ? new Date(values.search_start_date) + : null, users: user && !checkUserIsNoAuthUser(user.id) ? [user.id] : undefined, groups, @@ -912,7 +922,7 @@ export function AssistantEditor({ )} -
+
+ + ) => void; + width?: string; }) { let heightString = defaultHeight || ""; if (isTextArea && !heightString) { @@ -182,7 +184,7 @@ export function TextFormField({ }; return ( -
+
{!removeLabel && (