mirror of
https://github.com/Mintplex-Labs/anything-llm.git
synced 2024-09-28 15:10:10 +02:00
- added metaResponse toggle button to ChatSettings
- generic components folder - generic togglebutton,toggleblock,badge
This commit is contained in:
parent
afc52c643e
commit
872db95dfe
108
frontend/src/components/Generic/Badges/Badge/index.jsx
Normal file
108
frontend/src/components/Generic/Badges/Badge/index.jsx
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
import React from "react";
|
||||||
|
|
||||||
|
// Updated utility function for dark theme
|
||||||
|
const colorMapping = (bg) => {
|
||||||
|
const mappings = {
|
||||||
|
"emerald-600": { text: "text-emerald-100", icon: "text-emerald-200 group-hover:text-emerald-50" },
|
||||||
|
"red-600": { text: "text-red-100", icon: "text-red-200 group-hover:text-red-50" },
|
||||||
|
"blue-600": { text: "text-blue-100", icon: "text-blue-200 group-hover:text-blue-50" },
|
||||||
|
"yellow-600": { text: "text-yellow-100", icon: "text-yellow-200 group-hover:text-yellow-50" },
|
||||||
|
"gray-600": { text: "text-gray-100", icon: "text-gray-200 group-hover:text-gray-50" },
|
||||||
|
"purple-600": { text: "text-purple-100", icon: "text-purple-200 group-hover:text-purple-50" },
|
||||||
|
"pink-600": { text: "text-pink-100", icon: "text-pink-200 group-hover:text-pink-50" },
|
||||||
|
"indigo-600": { text: "text-indigo-100", icon: "text-indigo-200 group-hover:text-indigo-50" },
|
||||||
|
};
|
||||||
|
|
||||||
|
return mappings[bg] || { text: "text-gray-100", icon: "text-gray-200" };
|
||||||
|
};
|
||||||
|
|
||||||
|
// Badge Component
|
||||||
|
|
||||||
|
export default function Badge({
|
||||||
|
label = "Beta",
|
||||||
|
size = "sm", // "sm", "md", "lg" or "xl"
|
||||||
|
rounded = "full", // "none", "sm", "md", "lg", "full"
|
||||||
|
shadow = "none", // "none", "sm", "md", "lg", "xl"
|
||||||
|
showDot = false,
|
||||||
|
showClose = false,
|
||||||
|
bg = "emerald-600",
|
||||||
|
animated = false,
|
||||||
|
onClose = () => {}, // Callback for close icon
|
||||||
|
}) {
|
||||||
|
// Adjustments based on props
|
||||||
|
const { text: textColor, icon: iconColor } = colorMapping(bg);
|
||||||
|
const animatedClasses = animated ? "animate-pulse" : "";
|
||||||
|
const sizeClasses = {
|
||||||
|
sm: "py-0.5 pl-2 pr-0.5 text-xs",
|
||||||
|
md: "py-1 pl-2 pr-1 text-sm",
|
||||||
|
lg: "py-1 px-3 text-sm",
|
||||||
|
xl: "py-1.5 px-4 text-base",
|
||||||
|
}[size];
|
||||||
|
const iconSizeClasses = {
|
||||||
|
sm: "h-2 w-2",
|
||||||
|
md: "h-3 w-3",
|
||||||
|
lg: "h-4 w-4",
|
||||||
|
xl: "h-4 w-4",
|
||||||
|
}[size];
|
||||||
|
const roundedClasses = {
|
||||||
|
none: "rounded-none",
|
||||||
|
sm: "rounded-sm",
|
||||||
|
md: "rounded-md",
|
||||||
|
lg: "rounded-lg",
|
||||||
|
full: "rounded-full",
|
||||||
|
}[rounded];
|
||||||
|
const shadowClasses = {
|
||||||
|
none: "",
|
||||||
|
sm: "shadow-sm",
|
||||||
|
md: "shadow-md",
|
||||||
|
lg: "shadow-lg",
|
||||||
|
xl: "shadow-xl",
|
||||||
|
}[shadow];
|
||||||
|
const backgroundClasses = `bg-${bg}`;
|
||||||
|
|
||||||
|
// SVG Icons
|
||||||
|
const DotIcon = () => (
|
||||||
|
<svg
|
||||||
|
viewBox="0 0 8 8"
|
||||||
|
fill="currentColor"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
className={`${iconSizeClasses} ${iconColor} ${animatedClasses}`}
|
||||||
|
>
|
||||||
|
<circle cx="4" cy="4" r="4" />
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
|
||||||
|
const CloseIcon = () => (
|
||||||
|
<svg
|
||||||
|
viewBox="0 0 12 12"
|
||||||
|
fill="currentColor"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
className={`${iconSizeClasses} ${iconColor}`}
|
||||||
|
>
|
||||||
|
<path d="M6 4.586L2.929 1.515 1.515 2.929 4.586 6l-3.071 3.071 1.414 1.414L6 7.414l3.071 3.071 1.414-1.414L7.414 6l3.071-3.071-1.414-1.414L6 4.586z" />
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={`flex flex-row gap-0.5 w-fit h-fit justify-center items-center group ${sizeClasses} ${backgroundClasses} ${roundedClasses} ${shadowClasses}`}
|
||||||
|
>
|
||||||
|
{showDot && (
|
||||||
|
<div>
|
||||||
|
<DotIcon />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<p className={`block text-center font-medium px-1 ${textColor}`}>
|
||||||
|
{label}
|
||||||
|
</p>
|
||||||
|
{showClose && (
|
||||||
|
<div
|
||||||
|
className="flex flex-row justify-start items-start p-1 rounded-lg cursor-pointer"
|
||||||
|
onClick={onClose}
|
||||||
|
>
|
||||||
|
<CloseIcon />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
40
frontend/src/components/Generic/Blocks/ToggleBlock/index.jsx
Normal file
40
frontend/src/components/Generic/Blocks/ToggleBlock/index.jsx
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
import React from "react";
|
||||||
|
import ToggleButton from "../../Buttons/ToggleButton";
|
||||||
|
import Badge from "../../Badges/Badge";
|
||||||
|
|
||||||
|
// ToggleBlock: A component that includes a ToggleButton with additional context
|
||||||
|
export default function ToggleBlock({
|
||||||
|
initialChecked,
|
||||||
|
label,
|
||||||
|
onToggle,
|
||||||
|
description,
|
||||||
|
name,
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<div className="relative w-full max-h-full">
|
||||||
|
<div className="relative rounded-lg">
|
||||||
|
<div className="flex items-start justify-between px-6 py-4"></div>
|
||||||
|
<div className="space-y-6 flex h-full w-full">
|
||||||
|
<div className="w-full flex flex-col gap-y-4">
|
||||||
|
<div>
|
||||||
|
<div className="flex flex-row gap-3" >
|
||||||
|
<label className="block input-label mb-4">{label}</label>
|
||||||
|
<Badge showDot animated />
|
||||||
|
</div>
|
||||||
|
<ToggleButton
|
||||||
|
initialChecked={initialChecked}
|
||||||
|
onToggle={onToggle}
|
||||||
|
name={name}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center justify-between space-x-14">
|
||||||
|
<p className="text-white text-opacity-60 text-xs font-medium py-1.5">
|
||||||
|
{description}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
import React, { useState, useEffect } from "react";
|
||||||
|
|
||||||
|
// ToggleButton: A reusable and semi-controlled toggle button
|
||||||
|
export default function ToggleButton({ initialChecked, onToggle, name }) {
|
||||||
|
const [isChecked, setIsChecked] = useState(initialChecked);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setIsChecked(initialChecked);
|
||||||
|
}, [initialChecked]);
|
||||||
|
|
||||||
|
const handleToggle = () => {
|
||||||
|
setIsChecked(!isChecked);
|
||||||
|
if (onToggle) {
|
||||||
|
onToggle(!isChecked);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<label className="relative inline-flex cursor-pointer items-center">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
name={name}
|
||||||
|
onChange={handleToggle}
|
||||||
|
checked={isChecked}
|
||||||
|
className="peer sr-only pointer-events-none"
|
||||||
|
/>
|
||||||
|
<div className="pointer-events-none peer h-6 w-11 rounded-full bg-stone-400 after:absolute after:left-[2px] after:top-[2px] after:h-5 after:w-5 after:rounded-full after:shadow-xl after:border after:border-gray-600 after:bg-white after:box-shadow-md after:transition-all after:content-[''] peer-checked:bg-lime-300 peer-checked:after:translate-x-full peer-checked:after:border-white peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-blue-800"></div>
|
||||||
|
</label>
|
||||||
|
);
|
||||||
|
}
|
314
frontend/src/models/metaResponse.js
Normal file
314
frontend/src/models/metaResponse.js
Normal file
@ -0,0 +1,314 @@
|
|||||||
|
import { API_BASE } from "@/utils/constants";
|
||||||
|
import { baseHeaders } from "@/utils/request";
|
||||||
|
import { fetchEventSource } from "@microsoft/fetch-event-source";
|
||||||
|
import WorkspaceThread from "@/models/workspaceThread";
|
||||||
|
import { v4 } from "uuid";
|
||||||
|
import { ABORT_STREAM_EVENT } from "@/utils/chat";
|
||||||
|
|
||||||
|
const MetaResponse = {
|
||||||
|
toggle: async function (slug) {
|
||||||
|
const result = await fetch(
|
||||||
|
`${API_BASE}/workspace/${slug}/metaResponse/toggle`,
|
||||||
|
{
|
||||||
|
method: "PATCH",
|
||||||
|
headers: baseHeaders(),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.then((res) => res.ok)
|
||||||
|
.catch(() => false);
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
new: async function (data = {}) {
|
||||||
|
const { workspace, message } = await fetch(`${API_BASE}/workspace/new`, {
|
||||||
|
method: "POST",
|
||||||
|
body: JSON.stringify(data),
|
||||||
|
headers: baseHeaders(),
|
||||||
|
})
|
||||||
|
.then((res) => res.json())
|
||||||
|
.catch((e) => {
|
||||||
|
return { workspace: null, message: e.message };
|
||||||
|
});
|
||||||
|
|
||||||
|
return { workspace, message };
|
||||||
|
},
|
||||||
|
update: async function (slug, data = {}) {
|
||||||
|
const { workspace, message } = await fetch(
|
||||||
|
`${API_BASE}/workspace/${slug}/update`,
|
||||||
|
{
|
||||||
|
method: "POST",
|
||||||
|
body: JSON.stringify(data),
|
||||||
|
headers: baseHeaders(),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.then((res) => res.json())
|
||||||
|
.catch((e) => {
|
||||||
|
return { workspace: null, message: e.message };
|
||||||
|
});
|
||||||
|
|
||||||
|
return { workspace, message };
|
||||||
|
},
|
||||||
|
modifyEmbeddings: async function (slug, changes = {}) {
|
||||||
|
const { workspace, message } = await fetch(
|
||||||
|
`${API_BASE}/workspace/${slug}/update-embeddings`,
|
||||||
|
{
|
||||||
|
method: "POST",
|
||||||
|
body: JSON.stringify(changes), // contains 'adds' and 'removes' keys that are arrays of filepaths
|
||||||
|
headers: baseHeaders(),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.then((res) => res.json())
|
||||||
|
.catch((e) => {
|
||||||
|
return { workspace: null, message: e.message };
|
||||||
|
});
|
||||||
|
|
||||||
|
return { workspace, message };
|
||||||
|
},
|
||||||
|
chatHistory: async function (slug) {
|
||||||
|
const history = await fetch(`${API_BASE}/workspace/${slug}/chats`, {
|
||||||
|
method: "GET",
|
||||||
|
headers: baseHeaders(),
|
||||||
|
})
|
||||||
|
.then((res) => res.json())
|
||||||
|
.then((res) => res.history || [])
|
||||||
|
.catch(() => []);
|
||||||
|
return history;
|
||||||
|
},
|
||||||
|
updateChatFeedback: async function (chatId, slug, feedback) {
|
||||||
|
const result = await fetch(
|
||||||
|
`${API_BASE}/workspace/${slug}/chat-feedback/${chatId}`,
|
||||||
|
{
|
||||||
|
method: "POST",
|
||||||
|
headers: baseHeaders(),
|
||||||
|
body: JSON.stringify({ feedback }),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.then((res) => res.ok)
|
||||||
|
.catch(() => false);
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
streamChat: async function ({ slug }, message, handleChat) {
|
||||||
|
const ctrl = new AbortController();
|
||||||
|
|
||||||
|
// Listen for the ABORT_STREAM_EVENT key to be emitted by the client
|
||||||
|
// to early abort the streaming response. On abort we send a special `stopGeneration`
|
||||||
|
// event to be handled which resets the UI for us to be able to send another message.
|
||||||
|
// The backend response abort handling is done in each LLM's handleStreamResponse.
|
||||||
|
window.addEventListener(ABORT_STREAM_EVENT, () => {
|
||||||
|
ctrl.abort();
|
||||||
|
handleChat({ id: v4(), type: "stopGeneration" });
|
||||||
|
});
|
||||||
|
|
||||||
|
await fetchEventSource(`${API_BASE}/workspace/${slug}/stream-chat`, {
|
||||||
|
method: "POST",
|
||||||
|
body: JSON.stringify({ message }),
|
||||||
|
headers: baseHeaders(),
|
||||||
|
signal: ctrl.signal,
|
||||||
|
openWhenHidden: true,
|
||||||
|
async onopen(response) {
|
||||||
|
if (response.ok) {
|
||||||
|
return; // everything's good
|
||||||
|
} else if (
|
||||||
|
response.status >= 400 &&
|
||||||
|
response.status < 500 &&
|
||||||
|
response.status !== 429
|
||||||
|
) {
|
||||||
|
handleChat({
|
||||||
|
id: v4(),
|
||||||
|
type: "abort",
|
||||||
|
textResponse: null,
|
||||||
|
sources: [],
|
||||||
|
close: true,
|
||||||
|
error: `An error occurred while streaming response. Code ${response.status}`,
|
||||||
|
});
|
||||||
|
ctrl.abort();
|
||||||
|
throw new Error("Invalid Status code response.");
|
||||||
|
} else {
|
||||||
|
handleChat({
|
||||||
|
id: v4(),
|
||||||
|
type: "abort",
|
||||||
|
textResponse: null,
|
||||||
|
sources: [],
|
||||||
|
close: true,
|
||||||
|
error: `An error occurred while streaming response. Unknown Error.`,
|
||||||
|
});
|
||||||
|
ctrl.abort();
|
||||||
|
throw new Error("Unknown error");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async onmessage(msg) {
|
||||||
|
try {
|
||||||
|
const chatResult = JSON.parse(msg.data);
|
||||||
|
handleChat(chatResult);
|
||||||
|
} catch { }
|
||||||
|
},
|
||||||
|
onerror(err) {
|
||||||
|
handleChat({
|
||||||
|
id: v4(),
|
||||||
|
type: "abort",
|
||||||
|
textResponse: null,
|
||||||
|
sources: [],
|
||||||
|
close: true,
|
||||||
|
error: `An error occurred while streaming response. ${err.message}`,
|
||||||
|
});
|
||||||
|
ctrl.abort();
|
||||||
|
throw new Error();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
all: async function () {
|
||||||
|
const workspaces = await fetch(`${API_BASE}/workspaces`, {
|
||||||
|
method: "GET",
|
||||||
|
headers: baseHeaders(),
|
||||||
|
})
|
||||||
|
.then((res) => res.json())
|
||||||
|
.then((res) => res.workspaces || [])
|
||||||
|
.catch(() => []);
|
||||||
|
|
||||||
|
return workspaces;
|
||||||
|
},
|
||||||
|
bySlug: async function (slug = "") {
|
||||||
|
const workspace = await fetch(`${API_BASE}/workspace/${slug}`, {
|
||||||
|
headers: baseHeaders(),
|
||||||
|
})
|
||||||
|
.then((res) => res.json())
|
||||||
|
.then((res) => res.workspace)
|
||||||
|
.catch(() => null);
|
||||||
|
return workspace;
|
||||||
|
},
|
||||||
|
delete: async function (slug) {
|
||||||
|
const result = await fetch(`${API_BASE}/workspace/${slug}`, {
|
||||||
|
method: "DELETE",
|
||||||
|
headers: baseHeaders(),
|
||||||
|
})
|
||||||
|
.then((res) => res.ok)
|
||||||
|
.catch(() => false);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
uploadFile: async function (slug, formData) {
|
||||||
|
const response = await fetch(`${API_BASE}/workspace/${slug}/upload`, {
|
||||||
|
method: "POST",
|
||||||
|
body: formData,
|
||||||
|
headers: baseHeaders(),
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
return { response, data };
|
||||||
|
},
|
||||||
|
uploadLink: async function (slug, link) {
|
||||||
|
const response = await fetch(`${API_BASE}/workspace/${slug}/upload-link`, {
|
||||||
|
method: "POST",
|
||||||
|
body: JSON.stringify({ link }),
|
||||||
|
headers: baseHeaders(),
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
return { response, data };
|
||||||
|
},
|
||||||
|
|
||||||
|
getSuggestedMessages: async function (slug) {
|
||||||
|
return await fetch(`${API_BASE}/workspace/${slug}/suggested-messages`, {
|
||||||
|
method: "GET",
|
||||||
|
cache: "no-cache",
|
||||||
|
headers: baseHeaders(),
|
||||||
|
})
|
||||||
|
.then((res) => {
|
||||||
|
if (!res.ok) throw new Error("Could not fetch suggested messages.");
|
||||||
|
return res.json();
|
||||||
|
})
|
||||||
|
.then((res) => res.suggestedMessages)
|
||||||
|
.catch((e) => {
|
||||||
|
console.error(e);
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
setSuggestedMessages: async function (slug, messages) {
|
||||||
|
return fetch(`${API_BASE}/workspace/${slug}/suggested-messages`, {
|
||||||
|
method: "POST",
|
||||||
|
headers: baseHeaders(),
|
||||||
|
body: JSON.stringify({ messages }),
|
||||||
|
})
|
||||||
|
.then((res) => {
|
||||||
|
if (!res.ok) {
|
||||||
|
throw new Error(
|
||||||
|
res.statusText || "Error setting suggested messages."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return { success: true, ...res.json() };
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
console.error(e);
|
||||||
|
return { success: false, error: e.message };
|
||||||
|
});
|
||||||
|
},
|
||||||
|
setPinForDocument: async function (slug, docPath, pinStatus) {
|
||||||
|
return fetch(`${API_BASE}/workspace/${slug}/update-pin`, {
|
||||||
|
method: "POST",
|
||||||
|
headers: baseHeaders(),
|
||||||
|
body: JSON.stringify({ docPath, pinStatus }),
|
||||||
|
})
|
||||||
|
.then((res) => {
|
||||||
|
if (!res.ok) {
|
||||||
|
throw new Error(
|
||||||
|
res.statusText || "Error setting pin status for document."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
console.error(e);
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
threads: WorkspaceThread,
|
||||||
|
|
||||||
|
uploadPfp: async function (formData, slug) {
|
||||||
|
return await fetch(`${API_BASE}/workspace/${slug}/upload-pfp`, {
|
||||||
|
method: "POST",
|
||||||
|
body: formData,
|
||||||
|
headers: baseHeaders(),
|
||||||
|
})
|
||||||
|
.then((res) => {
|
||||||
|
if (!res.ok) throw new Error("Error uploading pfp.");
|
||||||
|
return { success: true, error: null };
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
console.log(e);
|
||||||
|
return { success: false, error: e.message };
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
fetchPfp: async function (slug) {
|
||||||
|
return await fetch(`${API_BASE}/workspace/${slug}/pfp`, {
|
||||||
|
method: "GET",
|
||||||
|
cache: "no-cache",
|
||||||
|
headers: baseHeaders(),
|
||||||
|
})
|
||||||
|
.then((res) => {
|
||||||
|
if (res.ok && res.status !== 204) return res.blob();
|
||||||
|
throw new Error("Failed to fetch pfp.");
|
||||||
|
})
|
||||||
|
.then((blob) => (blob ? URL.createObjectURL(blob) : null))
|
||||||
|
.catch((e) => {
|
||||||
|
console.log(e);
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
removePfp: async function (slug) {
|
||||||
|
return await fetch(`${API_BASE}/workspace/${slug}/remove-pfp`, {
|
||||||
|
method: "DELETE",
|
||||||
|
headers: baseHeaders(),
|
||||||
|
})
|
||||||
|
.then((res) => {
|
||||||
|
if (res.ok) return { success: true, error: null };
|
||||||
|
throw new Error("Failed to remove pfp.");
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
console.log(e);
|
||||||
|
return { success: false, error: e.message };
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default MetaResponse;
|
@ -0,0 +1,25 @@
|
|||||||
|
import GenericBadge from "@/components/Generic/Badges/Badge";
|
||||||
|
import ToggleBlock from "@/components/Generic/Blocks/ToggleBlock";
|
||||||
|
|
||||||
|
export default function ChatEnableMetaResponse({ workspace, setHasChanges }) {
|
||||||
|
// Toggle metaResponse value
|
||||||
|
|
||||||
|
const toggleMetaResponse = () => {
|
||||||
|
setHasChanges(true);
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<div className="relative w-full max-h-full">
|
||||||
|
<ToggleBlock
|
||||||
|
initialChecked={workspace?.metaResponse}
|
||||||
|
label={
|
||||||
|
workspace.metaResponse
|
||||||
|
? "Meta Response is Enabled"
|
||||||
|
: "Enable Meta Response"
|
||||||
|
}
|
||||||
|
onToggle={toggleMetaResponse}
|
||||||
|
name="metaResponse"
|
||||||
|
description="Turn on this feature to dynamically adjust the chat interface based on conversation context, using options like dropdowns, sliders, and suggestions for a tailored user experience."
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
@ -8,6 +8,7 @@ import ChatHistorySettings from "./ChatHistorySettings";
|
|||||||
import ChatPromptSettings from "./ChatPromptSettings";
|
import ChatPromptSettings from "./ChatPromptSettings";
|
||||||
import ChatTemperatureSettings from "./ChatTemperatureSettings";
|
import ChatTemperatureSettings from "./ChatTemperatureSettings";
|
||||||
import ChatModeSelection from "./ChatModeSelection";
|
import ChatModeSelection from "./ChatModeSelection";
|
||||||
|
import ChatEnableMetaResponse from "./ChatEnableMetaResponse";
|
||||||
|
|
||||||
export default function ChatSettings({ workspace }) {
|
export default function ChatSettings({ workspace }) {
|
||||||
const [settings, setSettings] = useState({});
|
const [settings, setSettings] = useState({});
|
||||||
@ -28,7 +29,14 @@ export default function ChatSettings({ workspace }) {
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const data = {};
|
const data = {};
|
||||||
const form = new FormData(formEl.current);
|
const form = new FormData(formEl.current);
|
||||||
for (var [key, value] of form.entries()) data[key] = castToType(key, value);
|
data["metaResponse"] = form.get("metaResponse") === "on" ? true : false;
|
||||||
|
for (var [key, value] of form.entries()) {
|
||||||
|
if (key === "metaResponse") {
|
||||||
|
data[key] = value === "on" ? true : false;
|
||||||
|
} else {
|
||||||
|
data[key] = castToType(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
const { workspace: updatedWorkspace, message } = await Workspace.update(
|
const { workspace: updatedWorkspace, message } = await Workspace.update(
|
||||||
workspace.slug,
|
workspace.slug,
|
||||||
data
|
data
|
||||||
@ -65,6 +73,10 @@ export default function ChatSettings({ workspace }) {
|
|||||||
workspace={workspace}
|
workspace={workspace}
|
||||||
setHasChanges={setHasChanges}
|
setHasChanges={setHasChanges}
|
||||||
/>
|
/>
|
||||||
|
<ChatEnableMetaResponse
|
||||||
|
workspace={workspace}
|
||||||
|
setHasChanges={setHasChanges}
|
||||||
|
/>
|
||||||
{hasChanges && (
|
{hasChanges && (
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
|
@ -87,6 +87,23 @@ function workspaceEndpoints(app) {
|
|||||||
response.sendStatus(400).end();
|
response.sendStatus(400).end();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (
|
||||||
|
!currWorkspace.metaResponse &&
|
||||||
|
!currWorkspace.metaResponseSettings
|
||||||
|
) {
|
||||||
|
metaResponseDefaultSettings.inputs.config.systemPrompt.openAiPrompt =
|
||||||
|
currWorkspace.openAiPrompt || "";
|
||||||
|
data.metaResponseSettings = JSON.stringify(
|
||||||
|
metaResponseDefaultSettings
|
||||||
|
);
|
||||||
|
await EventLogs.logEvent(
|
||||||
|
"workspace_meta_response_enabled",
|
||||||
|
{
|
||||||
|
workspaceName: currWorkspace?.name || "Unknown Workspace",
|
||||||
|
},
|
||||||
|
user?.id
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const { workspace, message } = await Workspace.update(
|
const { workspace, message } = await Workspace.update(
|
||||||
currWorkspace.id,
|
currWorkspace.id,
|
||||||
@ -212,8 +229,8 @@ function workspaceEndpoints(app) {
|
|||||||
message:
|
message:
|
||||||
failedToEmbed.length > 0
|
failedToEmbed.length > 0
|
||||||
? `${failedToEmbed.length} documents failed to add.\n\n${errors
|
? `${failedToEmbed.length} documents failed to add.\n\n${errors
|
||||||
.map((msg) => `${msg}`)
|
.map((msg) => `${msg}`)
|
||||||
.join("\n\n")}`
|
.join("\n\n")}`
|
||||||
: null,
|
: null,
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -567,4 +584,76 @@ function workspaceEndpoints(app) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const metaResponseDefaultSettings = {
|
||||||
|
inputs: {
|
||||||
|
isEnabled: false,
|
||||||
|
config: {
|
||||||
|
systemPrompt: {
|
||||||
|
isEnabled: false,
|
||||||
|
content: "",
|
||||||
|
openAiPrompt: "",
|
||||||
|
overrideSystemPrompt: false,
|
||||||
|
suggestionsList: [
|
||||||
|
{
|
||||||
|
title: "",
|
||||||
|
content: "",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
canEdit: ["admin", "manager"],
|
||||||
|
},
|
||||||
|
promptSchema: {
|
||||||
|
content: "",
|
||||||
|
suggestionsList: [
|
||||||
|
{
|
||||||
|
title: "",
|
||||||
|
content: "",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
overrideWorkspacePrompt: false,
|
||||||
|
canEdit: ["admin", "manager"],
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
dropDownMenu: {
|
||||||
|
isEnabled: false,
|
||||||
|
options: [],
|
||||||
|
|
||||||
|
},
|
||||||
|
optionsList: {
|
||||||
|
isEnabled: false,
|
||||||
|
options: [],
|
||||||
|
},
|
||||||
|
optionsButtons: {
|
||||||
|
isEnabled: false,
|
||||||
|
options: [],
|
||||||
|
},
|
||||||
|
multiSelectCheckboxes: {
|
||||||
|
isEnabled: false,
|
||||||
|
options: [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
permissions: ["user"],
|
||||||
|
},
|
||||||
|
sentiments: {
|
||||||
|
isEnabled: false,
|
||||||
|
config: {
|
||||||
|
sentimentAnalysis: {
|
||||||
|
isEnabled: false,
|
||||||
|
|
||||||
|
scoreThreshold: 0.5,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
permissions: ["user"],
|
||||||
|
},
|
||||||
|
avatars: {
|
||||||
|
isEnabled: false,
|
||||||
|
config: {
|
||||||
|
avatarType: "circle",
|
||||||
|
avatarSize: "medium",
|
||||||
|
avatarName: "user",
|
||||||
|
},
|
||||||
|
permissions: ["user"],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
module.exports = { workspaceEndpoints };
|
module.exports = { workspaceEndpoints };
|
||||||
|
Loading…
Reference in New Issue
Block a user