From 42e1d8e8ceffd378323b3ea71986f03beaf54d1a Mon Sep 17 00:00:00 2001
From: Timothy Carambat <rambat1010@gmail.com>
Date: Tue, 30 Apr 2024 16:14:30 -0700
Subject: [PATCH] Customize refusal response for `query` mode (#1243)

* Customize refusal response for `query` mode

* remove border for desktop
---
 .../ChatQueryRefusalResponse/index.jsx        | 29 +++++++++++++++++++
 .../WorkspaceSettings/ChatSettings/index.jsx  |  5 ++++
 frontend/src/utils/chat/index.js              |  7 +++++
 server/models/workspace.js                    |  1 +
 .../20240430230707_init/migration.sql         |  2 ++
 server/prisma/schema.prisma                   |  1 +
 server/utils/chats/embed.js                   |  1 +
 server/utils/chats/index.js                   |  2 ++
 server/utils/chats/stream.js                  |  2 ++
 9 files changed, 50 insertions(+)
 create mode 100644 frontend/src/pages/WorkspaceSettings/ChatSettings/ChatQueryRefusalResponse/index.jsx
 create mode 100644 server/prisma/migrations/20240430230707_init/migration.sql

diff --git a/frontend/src/pages/WorkspaceSettings/ChatSettings/ChatQueryRefusalResponse/index.jsx b/frontend/src/pages/WorkspaceSettings/ChatSettings/ChatQueryRefusalResponse/index.jsx
new file mode 100644
index 000000000..2b8570dba
--- /dev/null
+++ b/frontend/src/pages/WorkspaceSettings/ChatSettings/ChatQueryRefusalResponse/index.jsx
@@ -0,0 +1,29 @@
+import { chatQueryRefusalResponse } from "@/utils/chat";
+
+export default function ChatQueryRefusalResponse({ workspace, setHasChanges }) {
+  return (
+    <div>
+      <div className="flex flex-col">
+        <label htmlFor="name" className="block input-label">
+          Query mode refusal response
+        </label>
+        <p className="text-white text-opacity-60 text-xs font-medium py-1.5">
+          When in <code className="bg-zinc-900 p-0.5 rounded-sm">query</code>{" "}
+          mode, you may want to return a custom refusal response when no context
+          is found.
+        </p>
+      </div>
+      <textarea
+        name="queryRefusalResponse"
+        rows={2}
+        defaultValue={chatQueryRefusalResponse(workspace)}
+        className="border-none bg-zinc-900 placeholder:text-white/20 text-white text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 mt-2"
+        placeholder="The text returned in query mode when there is no relevant context found for a response."
+        required={true}
+        wrap="soft"
+        autoComplete="off"
+        onChange={() => setHasChanges(true)}
+      />
+    </div>
+  );
+}
diff --git a/frontend/src/pages/WorkspaceSettings/ChatSettings/index.jsx b/frontend/src/pages/WorkspaceSettings/ChatSettings/index.jsx
index a6bab2c37..5a8347eb1 100644
--- a/frontend/src/pages/WorkspaceSettings/ChatSettings/index.jsx
+++ b/frontend/src/pages/WorkspaceSettings/ChatSettings/index.jsx
@@ -8,6 +8,7 @@ import ChatPromptSettings from "./ChatPromptSettings";
 import ChatTemperatureSettings from "./ChatTemperatureSettings";
 import ChatModeSelection from "./ChatModeSelection";
 import WorkspaceLLMSelection from "./WorkspaceLLMSelection";
+import ChatQueryRefusalResponse from "./ChatQueryRefusalResponse";
 
 export default function ChatSettings({ workspace }) {
   const [settings, setSettings] = useState({});
@@ -68,6 +69,10 @@ export default function ChatSettings({ workspace }) {
           workspace={workspace}
           setHasChanges={setHasChanges}
         />
+        <ChatQueryRefusalResponse
+          workspace={workspace}
+          setHasChanges={setHasChanges}
+        />
         <ChatTemperatureSettings
           settings={settings}
           workspace={workspace}
diff --git a/frontend/src/utils/chat/index.js b/frontend/src/utils/chat/index.js
index 90ed7d7e5..a2b18c7f4 100644
--- a/frontend/src/utils/chat/index.js
+++ b/frontend/src/utils/chat/index.js
@@ -140,3 +140,10 @@ export function chatPrompt(workspace) {
     "Given the following conversation, relevant context, and a follow up question, reply with an answer to the current question the user is asking. Return only your response to the question given the above information following the users instructions as needed."
   );
 }
+
+export function chatQueryRefusalResponse(workspace) {
+  return (
+    workspace?.queryRefusalResponse ??
+    "There is no relevant information in this workspace to answer your query."
+  );
+}
diff --git a/server/models/workspace.js b/server/models/workspace.js
index 28aebdf26..501d5fb9d 100644
--- a/server/models/workspace.js
+++ b/server/models/workspace.js
@@ -26,6 +26,7 @@ const Workspace = {
     "pfpFilename",
     "agentProvider",
     "agentModel",
+    "queryRefusalResponse",
   ],
 
   new: async function (name = null, creatorId = null) {
diff --git a/server/prisma/migrations/20240430230707_init/migration.sql b/server/prisma/migrations/20240430230707_init/migration.sql
new file mode 100644
index 000000000..af29a1360
--- /dev/null
+++ b/server/prisma/migrations/20240430230707_init/migration.sql
@@ -0,0 +1,2 @@
+-- AlterTable
+ALTER TABLE "workspaces" ADD COLUMN "queryRefusalResponse" TEXT;
diff --git a/server/prisma/schema.prisma b/server/prisma/schema.prisma
index 6c8689b9e..b830de9b7 100644
--- a/server/prisma/schema.prisma
+++ b/server/prisma/schema.prisma
@@ -130,6 +130,7 @@ model workspaces {
   pfpFilename                  String?
   agentProvider                String?
   agentModel                   String?
+  queryRefusalResponse         String?
   workspace_users              workspace_users[]
   documents                    workspace_documents[]
   workspace_suggested_messages workspace_suggested_messages[]
diff --git a/server/utils/chats/embed.js b/server/utils/chats/embed.js
index d894693e0..94df306f5 100644
--- a/server/utils/chats/embed.js
+++ b/server/utils/chats/embed.js
@@ -137,6 +137,7 @@ async function streamChatWithForEmbed(
       id: uuid,
       type: "textResponse",
       textResponse:
+        embed.workspace?.queryRefusalResponse ??
         "There is no relevant information in this workspace to answer your query.",
       sources: [],
       close: true,
diff --git a/server/utils/chats/index.js b/server/utils/chats/index.js
index 760891b5f..87d96c47c 100644
--- a/server/utils/chats/index.js
+++ b/server/utils/chats/index.js
@@ -70,6 +70,7 @@ async function chatWithWorkspace(
       close: true,
       error: null,
       textResponse:
+        workspace?.queryRefusalResponse ??
         "There is no relevant information in this workspace to answer your query.",
     };
   }
@@ -150,6 +151,7 @@ async function chatWithWorkspace(
       close: true,
       error: null,
       textResponse:
+        workspace?.queryRefusalResponse ??
         "There is no relevant information in this workspace to answer your query.",
     };
   }
diff --git a/server/utils/chats/stream.js b/server/utils/chats/stream.js
index 01244e752..0e471161a 100644
--- a/server/utils/chats/stream.js
+++ b/server/utils/chats/stream.js
@@ -79,6 +79,7 @@ async function streamChatWithWorkspace(
       id: uuid,
       type: "textResponse",
       textResponse:
+        workspace?.queryRefusalResponse ??
         "There is no relevant information in this workspace to answer your query.",
       sources: [],
       close: true,
@@ -162,6 +163,7 @@ async function streamChatWithWorkspace(
       id: uuid,
       type: "textResponse",
       textResponse:
+        workspace?.queryRefusalResponse ??
         "There is no relevant information in this workspace to answer your query.",
       sources: [],
       close: true,