Enable persistence / removal of assistant icons + remove accidental regression (#2153)

* enable persistence / removal of assistant icons + remove accidental regression

* simpler env seeding for web building
This commit is contained in:
pablodanswer 2024-08-16 18:11:04 -07:00 committed by GitHub
parent 46c7089328
commit 3cbc341b60
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 50 additions and 12 deletions

View File

@ -64,6 +64,7 @@ def create_update_persona(
) -> PersonaSnapshot: ) -> PersonaSnapshot:
"""Higher level function than upsert_persona, although either is valid to use.""" """Higher level function than upsert_persona, although either is valid to use."""
# Permission to actually use these is checked later # Permission to actually use these is checked later
try: try:
persona = upsert_persona( persona = upsert_persona(
persona_id=persona_id, persona_id=persona_id,
@ -85,6 +86,7 @@ def create_update_persona(
icon_color=create_persona_request.icon_color, icon_color=create_persona_request.icon_color,
icon_shape=create_persona_request.icon_shape, icon_shape=create_persona_request.icon_shape,
uploaded_image_id=create_persona_request.uploaded_image_id, uploaded_image_id=create_persona_request.uploaded_image_id,
remove_image=create_persona_request.remove_image,
) )
versioned_make_persona_private = fetch_versioned_implementation( versioned_make_persona_private = fetch_versioned_implementation(
@ -338,6 +340,7 @@ def upsert_persona(
uploaded_image_id: str | None = None, uploaded_image_id: str | None = None,
display_priority: int | None = None, display_priority: int | None = None,
is_visible: bool = True, is_visible: bool = True,
remove_image: bool | None = None,
) -> Persona: ) -> Persona:
if persona_id is not None: if persona_id is not None:
persona = db_session.query(Persona).filter_by(id=persona_id).first() persona = db_session.query(Persona).filter_by(id=persona_id).first()
@ -395,7 +398,8 @@ def upsert_persona(
persona.is_public = is_public persona.is_public = is_public
persona.icon_color = icon_color persona.icon_color = icon_color
persona.icon_shape = icon_shape persona.icon_shape = icon_shape
persona.uploaded_image_id = uploaded_image_id if remove_image or uploaded_image_id:
persona.uploaded_image_id = uploaded_image_id
persona.display_priority = display_priority persona.display_priority = display_priority
persona.is_visible = is_visible persona.is_visible = is_visible

View File

@ -36,6 +36,7 @@ class CreatePersonaRequest(BaseModel):
icon_color: str | None = None icon_color: str | None = None
icon_shape: int | None = None icon_shape: int | None = None
uploaded_image_id: str | None = None # New field for uploaded image uploaded_image_id: str | None = None # New field for uploaded image
remove_image: bool | None = None
class PersonaSnapshot(BaseModel): class PersonaSnapshot(BaseModel):

View File

@ -35,7 +35,7 @@ class SeedConfiguration(BaseModel):
personas: list[CreatePersonaRequest] | None = None personas: list[CreatePersonaRequest] | None = None
settings: Settings | None = None settings: Settings | None = None
enterprise_settings: EnterpriseSettings | None = None enterprise_settings: EnterpriseSettings | None = None
analytics_script_key: str | None = None # Use existing `CUSTOM_ANALYTICS_SECRET_KEY` for reference
analytics_script_path: str | None = None analytics_script_path: str | None = None
@ -119,13 +119,14 @@ def _seed_logo(db_session: Session, logo_path: str | None) -> None:
def _seed_analytics_script(seed_config: SeedConfiguration) -> None: def _seed_analytics_script(seed_config: SeedConfiguration) -> None:
if seed_config.analytics_script_path and seed_config.analytics_script_key: custom_analytics_secret_key = os.environ.get("CUSTOM_ANALYTICS_SECRET_KEY")
if seed_config.analytics_script_path and custom_analytics_secret_key:
logger.info("Seeding analytics script") logger.info("Seeding analytics script")
try: try:
with open(seed_config.analytics_script_path, "r") as file: with open(seed_config.analytics_script_path, "r") as file:
script_content = file.read() script_content = file.read()
analytics_script = AnalyticsScriptUpload( analytics_script = AnalyticsScriptUpload(
script=script_content, secret_key=seed_config.analytics_script_key script=script_content, secret_key=custom_analytics_secret_key
) )
store_analytics_script(analytics_script) store_analytics_script(analytics_script)
except FileNotFoundError: except FileNotFoundError:

View File

@ -114,6 +114,7 @@ export function AssistantEditor({
const [finalPrompt, setFinalPrompt] = useState<string | null>(""); const [finalPrompt, setFinalPrompt] = useState<string | null>("");
const [finalPromptError, setFinalPromptError] = useState<string>(""); const [finalPromptError, setFinalPromptError] = useState<string>("");
const [removePersonaImage, setRemovePersonaImage] = useState(false);
const triggerFinalPromptUpdate = async ( const triggerFinalPromptUpdate = async (
systemPrompt: string, systemPrompt: string,
@ -228,6 +229,9 @@ export function AssistantEditor({
groups: existingPersona?.groups ?? [], groups: existingPersona?.groups ?? [],
}; };
const [existingPersonaImageId, setExistingPersonaImageId] = useState<
string | null
>(existingPersona?.uploaded_image_id || null);
return ( return (
<div> <div>
{popup} {popup}
@ -352,6 +356,7 @@ export function AssistantEditor({
user && !checkUserIsNoAuthUser(user.id) ? [user.id] : undefined, user && !checkUserIsNoAuthUser(user.id) ? [user.id] : undefined,
groups, groups,
tool_ids: enabledTools, tool_ids: enabledTools,
remove_image: removePersonaImage,
}); });
} else { } else {
[promptResponse, personaResponse] = await createPersona({ [promptResponse, personaResponse] = await createPersona({
@ -488,7 +493,9 @@ export function AssistantEditor({
<IconImageSelection <IconImageSelection
setFieldValue={setFieldValue} setFieldValue={setFieldValue}
existingPersona={existingPersona!} existingPersonaImageId={existingPersonaImageId!}
setExistingPersonaImageId={setExistingPersonaImageId}
setRemovePersonaImage={setRemovePersonaImage}
/> />
</div> </div>

View File

@ -18,6 +18,7 @@ interface PersonaCreationRequest {
tool_ids: number[]; tool_ids: number[];
icon_color: string | null; icon_color: string | null;
icon_shape: number | null; icon_shape: number | null;
remove_image?: boolean;
uploaded_image: File | null; uploaded_image: File | null;
} }
@ -41,6 +42,7 @@ interface PersonaUpdateRequest {
tool_ids: number[]; tool_ids: number[];
icon_color: string | null; icon_color: string | null;
icon_shape: number | null; icon_shape: number | null;
remove_image: boolean;
uploaded_image: File | null; uploaded_image: File | null;
} }
@ -119,6 +121,7 @@ function buildPersonaAPIBody(
tool_ids, tool_ids,
icon_color, icon_color,
icon_shape, icon_shape,
remove_image,
} = creationRequest; } = creationRequest;
return { return {
@ -140,6 +143,7 @@ function buildPersonaAPIBody(
icon_color, icon_color,
icon_shape, icon_shape,
uploaded_image_id, uploaded_image_id,
remove_image,
}; };
} }

View File

@ -71,7 +71,6 @@ export function PagesTab({
<div className="py-2 border-b border-border"> <div className="py-2 border-b border-border">
<div className="text-xs text-subtle flex pb-0.5 mb-1.5 mt-2 font-bold"> <div className="text-xs text-subtle flex pb-0.5 mb-1.5 mt-2 font-bold">
Chat Folders Chat Folders
{newFolderId ? newFolderId : "Hi"}
</div> </div>
<FolderList <FolderList
newFolderId={newFolderId} newFolderId={newFolderId}

View File

@ -1,19 +1,23 @@
import { Persona } from "@/app/admin/assistants/interfaces"; import { Persona } from "@/app/admin/assistants/interfaces";
import { buildImgUrl } from "@/app/chat/files/images/utils"; import { buildImgUrl } from "@/app/chat/files/images/utils";
import { useEffect, useState } from "react"; import { Dispatch, SetStateAction, useEffect, useState } from "react";
import Dropzone from "react-dropzone"; import Dropzone from "react-dropzone";
import { usePopup } from "../admin/connectors/Popup"; import { usePopup } from "../admin/connectors/Popup";
export const IconImageSelection = ({ export const IconImageSelection = ({
existingPersona,
setFieldValue, setFieldValue,
existingPersonaImageId,
setExistingPersonaImageId,
setRemovePersonaImage,
}: { }: {
existingPersona: Persona | null; setExistingPersonaImageId: Dispatch<SetStateAction<string | null>>;
existingPersonaImageId: string | null;
setFieldValue: ( setFieldValue: (
field: string, field: string,
value: any, value: any,
shouldValidate?: boolean shouldValidate?: boolean
) => Promise<any>; ) => Promise<any>;
setRemovePersonaImage: Dispatch<SetStateAction<boolean>>;
}) => { }) => {
const [uploadedImage, setUploadedImage] = useState<File | null>(null); const [uploadedImage, setUploadedImage] = useState<File | null>(null);
@ -22,19 +26,37 @@ export const IconImageSelection = ({
setFieldValue("uploaded_image", image); setFieldValue("uploaded_image", image);
}; };
const resetPreviousAssistantImage = () => {
setRemovePersonaImage(true);
setExistingPersonaImageId(null);
};
return ( return (
<div className="mt-2 gap-y-2 flex flex-col"> <div className="mt-2 gap-y-2 flex flex-col">
<p className="font-bold text-sm text-gray-800">Or Upload Image</p> <p className="font-bold text-sm text-gray-800">Or Upload Image</p>
{existingPersona && existingPersona.uploaded_image_id && ( {existingPersonaImageId && (
<div className="flex gap-x-2"> <div className="flex gap-x-2">
Current image: Current image:
<img <img
className="h-12 w-12" className="h-12 w-12"
src={buildImgUrl(existingPersona?.uploaded_image_id)} src={buildImgUrl(existingPersonaImageId)}
/> />
</div> </div>
)} )}
<IconImageUpload selectedFile={uploadedImage} updateFile={updateFile} /> <div className="flex gap-x-2">
<IconImageUpload selectedFile={uploadedImage} updateFile={updateFile} />
{existingPersonaImageId && (
<button
onClick={resetPreviousAssistantImage}
className={
"text-sm text-text-800 max-w-[200px] p-2 rounded " +
"shadow-lg border border-border cursor-pointer"
}
>
Remove current image
</button>
)}
</div>
<p className="text-sm text-gray-600"> <p className="text-sm text-gray-600">
Uploading an image will override the generated icon. Uploading an image will override the generated icon.
</p> </p>