diff --git a/backend/danswer/chat/load_yamls.py b/backend/danswer/chat/load_yamls.py index d2e93c474..ce9798f17 100644 --- a/backend/danswer/chat/load_yamls.py +++ b/backend/danswer/chat/load_yamls.py @@ -78,9 +78,11 @@ def load_personas_from_yaml( if not prompts: prompts = None + p_id = persona.get("id") upsert_persona( user_id=None, - persona_id=persona.get("id"), + # Negative to not conflict with existing personas + persona_id=(-1 * p_id) if p_id is not None else None, name=persona["name"], description=persona["description"], num_chunks=persona.get("num_chunks") diff --git a/backend/danswer/chat/personas.yaml b/backend/danswer/chat/personas.yaml index 1f358e4b1..a824f3482 100644 --- a/backend/danswer/chat/personas.yaml +++ b/backend/danswer/chat/personas.yaml @@ -5,9 +5,9 @@ personas: # this is for DanswerBot to use when tagged in a non-configured channel # Careful setting specific IDs, this won't autoincrement the next ID value for postgres - id: 0 - name: "Default" + name: "Knowledge Assistant" description: > - Default Danswer Question Answering functionality. + Assistant with access to documents from your Connected Sources. # Default Prompt objects attached to the persona, see prompts.yaml prompts: - "Answer-Question" @@ -39,22 +39,23 @@ personas: document_sets: [] - - name: "Summarize" + - id: 1 + name: "AI Assistant (No Sources)" description: > - A less creative assistant which summarizes relevant documents but does not try to - extrapolate any answers for you. + Assistant with no access to documents. Chat with just the Language Model. prompts: - - "Summarize" - num_chunks: 10 + - "OnlyLLM" + num_chunks: 0 llm_relevance_filter: true llm_filter_extraction: true recency_bias: "auto" document_sets: [] - - name: "Paraphrase" + - id: 2 + name: "Paraphrase Assistant" description: > - The least creative default assistant that only provides quotes from the documents. + Assistant that is heavily constrained and only provides exact quotes from Connected Sources. prompts: - "Paraphrase" num_chunks: 10 diff --git a/backend/danswer/chat/prompts.yaml b/backend/danswer/chat/prompts.yaml index 4ab9d7918..2fca2d563 100644 --- a/backend/danswer/chat/prompts.yaml +++ b/backend/danswer/chat/prompts.yaml @@ -30,6 +30,14 @@ prompts: include_citations: true + - name: "OnlyLLM" + description: "Chat directly with the LLM!" + system: "You are a helpful assistant." + task: "" + datetime_aware: true + include_citations: true + + - name: "Summarize" description: "Summarize relevant information from retrieved context!" system: > diff --git a/backend/danswer/db/chat.py b/backend/danswer/db/chat.py index 921f4f7df..1fcf933c8 100644 --- a/backend/danswer/db/chat.py +++ b/backend/danswer/db/chat.py @@ -6,6 +6,7 @@ from sqlalchemy import not_ from sqlalchemy import nullsfirst from sqlalchemy import or_ from sqlalchemy import select +from sqlalchemy import update from sqlalchemy.exc import MultipleResultsFound from sqlalchemy.orm import Session @@ -534,6 +535,34 @@ def mark_persona_as_deleted( db_session.commit() +def mark_delete_persona_by_name( + persona_name: str, db_session: Session, is_default: bool = True +) -> None: + stmt = ( + update(Persona) + .where(Persona.name == persona_name, Persona.default_persona == is_default) + .values(deleted=True) + ) + + db_session.execute(stmt) + db_session.commit() + + +def delete_old_default_personas( + db_session: Session, +) -> None: + """Note, this locks out the Summarize and Paraphrase personas for now + Need a more graceful fix later or those need to never have IDs""" + stmt = ( + update(Persona) + .where(Persona.default_persona, Persona.id > 0) + .values(deleted=True) + ) + + db_session.execute(stmt) + db_session.commit() + + def update_persona_visibility( persona_id: int, is_visible: bool, @@ -709,3 +738,15 @@ def translate_db_message_to_chat_message_detail( ) return chat_msg_detail + + +def delete_persona_by_name( + persona_name: str, db_session: Session, is_default: bool = True +) -> None: + stmt = delete(Persona).where( + Persona.name == persona_name, Persona.default_persona == is_default + ) + + db_session.execute(stmt) + + db_session.commit() diff --git a/backend/danswer/main.py b/backend/danswer/main.py index 6268263ae..7f5b52ed0 100644 --- a/backend/danswer/main.py +++ b/backend/danswer/main.py @@ -38,6 +38,7 @@ from danswer.configs.model_configs import FAST_GEN_AI_MODEL_VERSION from danswer.configs.model_configs import GEN_AI_API_ENDPOINT from danswer.configs.model_configs import GEN_AI_MODEL_PROVIDER from danswer.configs.model_configs import GEN_AI_MODEL_VERSION +from danswer.db.chat import delete_old_default_personas from danswer.db.connector import create_initial_default_connector from danswer.db.connector_credential_pair import associate_default_cc_pair from danswer.db.credentials import create_initial_public_credential @@ -292,6 +293,7 @@ def get_application() -> FastAPI: associate_default_cc_pair(db_session) logger.info("Loading default Prompts and Personas") + delete_old_default_personas(db_session) load_chat_yamls() logger.info("Verifying Document Index(s) is/are available.") diff --git a/backend/danswer/server/features/persona/api.py b/backend/danswer/server/features/persona/api.py index 2614a2233..7f10f1e29 100644 --- a/backend/danswer/server/features/persona/api.py +++ b/backend/danswer/server/features/persona/api.py @@ -156,11 +156,14 @@ def delete_persona( def list_personas( user: User | None = Depends(current_user), db_session: Session = Depends(get_session), + include_deleted: bool = False, ) -> list[PersonaSnapshot]: user_id = user.id if user is not None else None return [ PersonaSnapshot.from_model(persona) - for persona in get_personas(user_id=user_id, db_session=db_session) + for persona in get_personas( + user_id=user_id, include_deleted=include_deleted, db_session=db_session + ) ]