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
This commit is contained in:
pablodanswer 2024-09-20 09:39:34 -07:00 committed by GitHub
parent 5f2644985c
commit 00229d2abe
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 73 additions and 6 deletions

View File

@ -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")

View File

@ -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)

View File

@ -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)

View File

@ -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,
)

View File

@ -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,
)

View File

@ -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({
</Italic>
)}
<div className="mt-4 flex flex-col gap-y-4">
<div className="mt-4 flex flex-col gap-y-4">
<TextFormField
small={true}
name="num_chunks"
@ -930,6 +940,17 @@ export function AssistantEditor({
}}
/>
<TextFormField
width="max-w-xl"
type="date"
small
subtext="Documents prior to this date will not be referenced by the search tool"
optional
label="Search Start Date"
value={values.search_start_date}
name="search_start_date"
/>
<BooleanFormField
small
removeIndent

View File

@ -21,6 +21,7 @@ export interface Prompt {
export interface Persona {
id: number;
name: string;
search_start_date: Date | null;
owner: MinimalUserSnapshot | null;
is_visible: boolean;
is_public: boolean;

View File

@ -21,6 +21,7 @@ interface PersonaCreationRequest {
icon_shape: number | null;
remove_image?: boolean;
uploaded_image: File | null;
search_start_date: Date | null;
is_default_persona: boolean;
}
@ -46,6 +47,7 @@ interface PersonaUpdateRequest {
icon_shape: number | null;
remove_image: boolean;
uploaded_image: File | null;
search_start_date: Date | null;
}
function promptNameFromPersonaName(personaName: string) {
@ -124,6 +126,7 @@ function buildPersonaAPIBody(
icon_color,
icon_shape,
remove_image,
search_start_date,
} = creationRequest;
const is_default_persona =
@ -151,7 +154,7 @@ function buildPersonaAPIBody(
icon_shape,
uploaded_image_id,
remove_image,
is_default_persona,
search_start_date,
};
}

View File

@ -139,6 +139,7 @@ export function TextFormField({
removeLabel,
min,
onChange,
width,
}: {
value?: string;
name: string;
@ -163,6 +164,7 @@ export function TextFormField({
small?: boolean;
min?: number;
onChange?: (e: React.ChangeEvent<HTMLInputElement>) => void;
width?: string;
}) {
let heightString = defaultHeight || "";
if (isTextArea && !heightString) {
@ -182,7 +184,7 @@ export function TextFormField({
};
return (
<div className="w-full">
<div className={`w-full ${width}`}>
<div className="flex gap-x-2 items-center">
{!removeLabel && (
<Label className="text-text-950" small={small}>