mirror of
https://github.com/Mintplex-Labs/anything-llm.git
synced 2024-11-11 01:10:11 +01:00
[FEAT] Rename new threads on thread creation (#1607)
* make thread name 'Thread' when new thread is created * implement auto generated thread titles * implement truncated prompt as thread name * move rename of thread into workspaceThread function --------- Co-authored-by: Timothy Carambat <rambat1010@gmail.com>
This commit is contained in:
parent
13da9cb396
commit
3c98d15c6a
@ -27,7 +27,6 @@ export default function ThreadItem({
|
|||||||
const { slug } = useParams();
|
const { slug } = useParams();
|
||||||
const optionsContainer = useRef(null);
|
const optionsContainer = useRef(null);
|
||||||
const [showOptions, setShowOptions] = useState(false);
|
const [showOptions, setShowOptions] = useState(false);
|
||||||
const [name, setName] = useState(thread.name);
|
|
||||||
const linkTo = !thread.slug
|
const linkTo = !thread.slug
|
||||||
? paths.workspace.chat(slug)
|
? paths.workspace.chat(slug)
|
||||||
: paths.workspace.thread(slug, thread.slug);
|
: paths.workspace.thread(slug, thread.slug);
|
||||||
@ -97,7 +96,7 @@ export default function ThreadItem({
|
|||||||
isActive ? "font-medium text-white" : "text-slate-400"
|
isActive ? "font-medium text-white" : "text-slate-400"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{truncate(name, 25)}
|
{truncate(thread.name, 25)}
|
||||||
</p>
|
</p>
|
||||||
</a>
|
</a>
|
||||||
)}
|
)}
|
||||||
@ -133,7 +132,6 @@ export default function ThreadItem({
|
|||||||
workspace={workspace}
|
workspace={workspace}
|
||||||
thread={thread}
|
thread={thread}
|
||||||
onRemove={onRemove}
|
onRemove={onRemove}
|
||||||
onRename={setName}
|
|
||||||
close={() => setShowOptions(false)}
|
close={() => setShowOptions(false)}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
@ -144,14 +142,7 @@ export default function ThreadItem({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function OptionsMenu({
|
function OptionsMenu({ containerRef, workspace, thread, onRemove, close }) {
|
||||||
containerRef,
|
|
||||||
workspace,
|
|
||||||
thread,
|
|
||||||
onRename,
|
|
||||||
onRemove,
|
|
||||||
close,
|
|
||||||
}) {
|
|
||||||
const menuRef = useRef(null);
|
const menuRef = useRef(null);
|
||||||
|
|
||||||
// Ref menu options
|
// Ref menu options
|
||||||
@ -208,7 +199,7 @@ function OptionsMenu({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
onRename(name);
|
thread.name = name;
|
||||||
close();
|
close();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -12,6 +12,26 @@ export default function ThreadContainer({ workspace }) {
|
|||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
const [ctrlPressed, setCtrlPressed] = useState(false);
|
const [ctrlPressed, setCtrlPressed] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const chatHandler = (event) => {
|
||||||
|
const { threadSlug, newName } = event.detail;
|
||||||
|
setThreads((prevThreads) =>
|
||||||
|
prevThreads.map((thread) => {
|
||||||
|
if (thread.slug === threadSlug) {
|
||||||
|
return { ...thread, name: newName };
|
||||||
|
}
|
||||||
|
return thread;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
window.addEventListener("renameThread", chatHandler);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
window.removeEventListener("renameThread", chatHandler);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
async function fetchThreads() {
|
async function fetchThreads() {
|
||||||
if (!workspace.slug) return;
|
if (!workspace.slug) return;
|
||||||
|
@ -12,6 +12,7 @@ import handleSocketResponse, {
|
|||||||
AGENT_SESSION_END,
|
AGENT_SESSION_END,
|
||||||
AGENT_SESSION_START,
|
AGENT_SESSION_START,
|
||||||
} from "@/utils/chat/agent";
|
} from "@/utils/chat/agent";
|
||||||
|
import truncate from "truncate";
|
||||||
|
|
||||||
export default function ChatContainer({ workspace, knownHistory = [] }) {
|
export default function ChatContainer({ workspace, knownHistory = [] }) {
|
||||||
const { threadSlug = null } = useParams();
|
const { threadSlug = null } = useParams();
|
||||||
@ -39,6 +40,18 @@ export default function ChatContainer({ workspace, knownHistory = [] }) {
|
|||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
if (!message || message === "") return false;
|
if (!message || message === "") return false;
|
||||||
|
|
||||||
|
// If first message and it is a thread
|
||||||
|
// and message is not blank/whitespace,
|
||||||
|
// then send event to rename the thread
|
||||||
|
if (threadSlug && chatHistory.length === 0 && message.trim().length > 0) {
|
||||||
|
const truncatedName = truncate(message, 22);
|
||||||
|
window.dispatchEvent(
|
||||||
|
new CustomEvent("renameThread", {
|
||||||
|
detail: { threadSlug, newName: truncatedName },
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const prevChatHistory = [
|
const prevChatHistory = [
|
||||||
...chatHistory,
|
...chatHistory,
|
||||||
{ content: message, role: "user" },
|
{ content: message, role: "user" },
|
||||||
|
@ -15,6 +15,8 @@ const {
|
|||||||
validWorkspaceSlug,
|
validWorkspaceSlug,
|
||||||
} = require("../utils/middleware/validWorkspace");
|
} = require("../utils/middleware/validWorkspace");
|
||||||
const { writeResponseChunk } = require("../utils/helpers/chat/responses");
|
const { writeResponseChunk } = require("../utils/helpers/chat/responses");
|
||||||
|
const { WorkspaceThread } = require("../models/workspaceThread");
|
||||||
|
const truncate = require("truncate");
|
||||||
|
|
||||||
function chatEndpoints(app) {
|
function chatEndpoints(app) {
|
||||||
if (!app) return;
|
if (!app) return;
|
||||||
@ -196,6 +198,14 @@ function chatEndpoints(app) {
|
|||||||
user,
|
user,
|
||||||
thread
|
thread
|
||||||
);
|
);
|
||||||
|
|
||||||
|
await WorkspaceThread.autoRenameThread({
|
||||||
|
thread,
|
||||||
|
workspace,
|
||||||
|
user,
|
||||||
|
newName: truncate(message, 22),
|
||||||
|
});
|
||||||
|
|
||||||
await Telemetry.sendTelemetry("sent_chat", {
|
await Telemetry.sendTelemetry("sent_chat", {
|
||||||
multiUserMode: multiUserMode(response),
|
multiUserMode: multiUserMode(response),
|
||||||
LLMSelection: process.env.LLM_PROVIDER || "openai",
|
LLMSelection: process.env.LLM_PROVIDER || "openai",
|
||||||
|
@ -8,7 +8,7 @@ const WorkspaceThread = {
|
|||||||
try {
|
try {
|
||||||
const thread = await prisma.workspace_threads.create({
|
const thread = await prisma.workspace_threads.create({
|
||||||
data: {
|
data: {
|
||||||
name: "New thread",
|
name: "Thread",
|
||||||
slug: uuidv4(),
|
slug: uuidv4(),
|
||||||
user_id: userId ? Number(userId) : null,
|
user_id: userId ? Number(userId) : null,
|
||||||
workspace_id: workspace.id,
|
workspace_id: workspace.id,
|
||||||
@ -84,6 +84,25 @@ const WorkspaceThread = {
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Will fire on first message (included or not) for a thread and rename the thread with the newName prop.
|
||||||
|
autoRenameThread: async function ({
|
||||||
|
workspace = null,
|
||||||
|
thread = null,
|
||||||
|
user = null,
|
||||||
|
newName = null,
|
||||||
|
}) {
|
||||||
|
if (!workspace || !thread || !newName) return false;
|
||||||
|
const { WorkspaceChats } = require("./workspaceChats");
|
||||||
|
const chatCount = await WorkspaceChats.count({
|
||||||
|
workspaceId: workspace.id,
|
||||||
|
user_id: user?.id || null,
|
||||||
|
thread_id: thread.id,
|
||||||
|
});
|
||||||
|
if (chatCount !== 1) return false;
|
||||||
|
await this.update(thread, { name: newName });
|
||||||
|
return true;
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = { WorkspaceThread };
|
module.exports = { WorkspaceThread };
|
||||||
|
@ -75,6 +75,7 @@
|
|||||||
"sqlite3": "^5.1.6",
|
"sqlite3": "^5.1.6",
|
||||||
"swagger-autogen": "^2.23.5",
|
"swagger-autogen": "^2.23.5",
|
||||||
"swagger-ui-express": "^5.0.0",
|
"swagger-ui-express": "^5.0.0",
|
||||||
|
"truncate": "^3.0.0",
|
||||||
"url-pattern": "^1.0.3",
|
"url-pattern": "^1.0.3",
|
||||||
"uuid": "^9.0.0",
|
"uuid": "^9.0.0",
|
||||||
"uuid-apikey": "^1.5.3",
|
"uuid-apikey": "^1.5.3",
|
||||||
|
@ -6211,6 +6211,11 @@ triple-beam@^1.3.0:
|
|||||||
resolved "https://registry.yarnpkg.com/triple-beam/-/triple-beam-1.4.1.tgz#6fde70271dc6e5d73ca0c3b24e2d92afb7441984"
|
resolved "https://registry.yarnpkg.com/triple-beam/-/triple-beam-1.4.1.tgz#6fde70271dc6e5d73ca0c3b24e2d92afb7441984"
|
||||||
integrity sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==
|
integrity sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==
|
||||||
|
|
||||||
|
truncate@^3.0.0:
|
||||||
|
version "3.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/truncate/-/truncate-3.0.0.tgz#7dbe19e2f72c614e36b79bab00fbfbeb1cbaf078"
|
||||||
|
integrity sha512-C+0Xojw7wZPl6MDq5UjMTuxZvBPK04mtdFet7k+GSZPINcvLZFCXg+15kWIL4wAqDB7CksIsKiRLbQ1wa7rKdw==
|
||||||
|
|
||||||
tslib@^2.2.0, tslib@^2.4.0, tslib@^2.5.3, tslib@^2.6.2:
|
tslib@^2.2.0, tslib@^2.4.0, tslib@^2.5.3, tslib@^2.6.2:
|
||||||
version "2.6.2"
|
version "2.6.2"
|
||||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae"
|
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae"
|
||||||
|
Loading…
Reference in New Issue
Block a user