mirror of
https://github.com/khoj-ai/khoj.git
synced 2024-11-27 17:35:07 +01:00
Automatically generate titles for conversations from history
This commit is contained in:
parent
7159b0b735
commit
807687a0ac
6 changed files with 84 additions and 5 deletions
|
@ -8,7 +8,7 @@ import ChatHistory from "../components/chatHistory/chatHistory";
|
||||||
import { useSearchParams } from "next/navigation";
|
import { useSearchParams } from "next/navigation";
|
||||||
import Loading from "../components/loading/loading";
|
import Loading from "../components/loading/loading";
|
||||||
|
|
||||||
import { processMessageChunk } from "../common/chatFunctions";
|
import { generateNewTitle, processMessageChunk } from "../common/chatFunctions";
|
||||||
|
|
||||||
import "katex/dist/katex.min.css";
|
import "katex/dist/katex.min.css";
|
||||||
|
|
||||||
|
@ -244,6 +244,9 @@ export default function Chat() {
|
||||||
setQueryToProcess("");
|
setQueryToProcess("");
|
||||||
setProcessQuerySignal(false);
|
setProcessQuerySignal(false);
|
||||||
setImages([]);
|
setImages([]);
|
||||||
|
|
||||||
|
if (conversationId) generateNewTitle(conversationId, setTitle);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -319,6 +319,23 @@ export async function packageFilesForUpload(files: FileList): Promise<FormData>
|
||||||
return formData;
|
return formData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function generateNewTitle(conversationId: string, setTitle: (title: string) => void) {
|
||||||
|
fetch(`/api/chat/title?conversation_id=${conversationId}`, {
|
||||||
|
method: "POST",
|
||||||
|
})
|
||||||
|
.then((res) => {
|
||||||
|
if (!res.ok) throw new Error(`Failed to call API with error ${res.statusText}`);
|
||||||
|
return res.json();
|
||||||
|
})
|
||||||
|
.then((data) => {
|
||||||
|
setTitle(data.title);
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error(err);
|
||||||
|
return;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export function uploadDataForIndexing(
|
export function uploadDataForIndexing(
|
||||||
files: FileList,
|
files: FileList,
|
||||||
setWarning: (warning: string) => void,
|
setWarning: (warning: string) => void,
|
||||||
|
|
|
@ -458,7 +458,11 @@ class Conversation(BaseModel):
|
||||||
user = models.ForeignKey(KhojUser, on_delete=models.CASCADE)
|
user = models.ForeignKey(KhojUser, on_delete=models.CASCADE)
|
||||||
conversation_log = models.JSONField(default=dict)
|
conversation_log = models.JSONField(default=dict)
|
||||||
client = models.ForeignKey(ClientApplication, on_delete=models.CASCADE, default=None, null=True, blank=True)
|
client = models.ForeignKey(ClientApplication, on_delete=models.CASCADE, default=None, null=True, blank=True)
|
||||||
|
|
||||||
|
# Slug is an app-generated conversation identifier. Need not be unique. Used as display title essentially.
|
||||||
slug = models.CharField(max_length=200, default=None, null=True, blank=True)
|
slug = models.CharField(max_length=200, default=None, null=True, blank=True)
|
||||||
|
|
||||||
|
# The title field is explicitly set by the user.
|
||||||
title = models.CharField(max_length=200, default=None, null=True, blank=True)
|
title = models.CharField(max_length=200, default=None, null=True, blank=True)
|
||||||
agent = models.ForeignKey(Agent, on_delete=models.SET_NULL, default=None, null=True, blank=True)
|
agent = models.ForeignKey(Agent, on_delete=models.SET_NULL, default=None, null=True, blank=True)
|
||||||
file_filters = models.JSONField(default=list)
|
file_filters = models.JSONField(default=list)
|
||||||
|
|
|
@ -988,16 +988,27 @@ You are an extremely smart and helpful title generator assistant. Given a user q
|
||||||
|
|
||||||
# Examples:
|
# Examples:
|
||||||
User: Show a new Calvin and Hobbes quote every morning at 9am. My Current Location: Shanghai, China
|
User: Show a new Calvin and Hobbes quote every morning at 9am. My Current Location: Shanghai, China
|
||||||
Khoj: Your daily Calvin and Hobbes Quote
|
Assistant: Your daily Calvin and Hobbes Quote
|
||||||
|
|
||||||
User: Notify me when version 2.0.0 of the sentence transformers python package is released. My Current Location: Mexico City, Mexico
|
User: Notify me when version 2.0.0 of the sentence transformers python package is released. My Current Location: Mexico City, Mexico
|
||||||
Khoj: Sentence Transformers Python Package Version 2.0.0 Release
|
Assistant: Sentence Transformers Python Package Version 2.0.0 Release
|
||||||
|
|
||||||
User: Gather the latest tech news on the first sunday of every month.
|
User: Gather the latest tech news on the first sunday of every month.
|
||||||
Khoj: Your Monthly Dose of Tech News
|
Assistant: Your Monthly Dose of Tech News
|
||||||
|
|
||||||
User Query: {query}
|
User Query: {query}
|
||||||
Khoj:
|
Assistant:
|
||||||
|
""".strip()
|
||||||
|
)
|
||||||
|
|
||||||
|
conversation_title_generation = PromptTemplate.from_template(
|
||||||
|
"""
|
||||||
|
You are an extremely smart and helpful title generator assistant. Given a conversation, extract the subject of the conversation. Crisp, informative, ten words or less.
|
||||||
|
|
||||||
|
Conversation History:
|
||||||
|
{chat_history}
|
||||||
|
|
||||||
|
Assistant:
|
||||||
""".strip()
|
""".strip()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,7 @@ from khoj.routers.helpers import (
|
||||||
ConversationCommandRateLimiter,
|
ConversationCommandRateLimiter,
|
||||||
DeleteMessageRequestBody,
|
DeleteMessageRequestBody,
|
||||||
FeedbackData,
|
FeedbackData,
|
||||||
|
acreate_title_from_history,
|
||||||
agenerate_chat_response,
|
agenerate_chat_response,
|
||||||
aget_relevant_information_sources,
|
aget_relevant_information_sources,
|
||||||
aget_relevant_output_modes,
|
aget_relevant_output_modes,
|
||||||
|
@ -530,6 +531,32 @@ async def set_conversation_title(
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@api_chat.post("/title")
|
||||||
|
@requires(["authenticated"])
|
||||||
|
async def generate_chat_title(
|
||||||
|
request: Request,
|
||||||
|
common: CommonQueryParams,
|
||||||
|
conversation_id: str,
|
||||||
|
):
|
||||||
|
user: KhojUser = request.user.object
|
||||||
|
conversation = await ConversationAdapters.aget_conversation_by_user(user=user, conversation_id=conversation_id)
|
||||||
|
|
||||||
|
# Conversation.title is explicitly set by the user. Do not override.
|
||||||
|
if conversation.title:
|
||||||
|
return {"status": "ok", "title": conversation.title}
|
||||||
|
|
||||||
|
if not conversation:
|
||||||
|
raise HTTPException(status_code=404, detail="Conversation not found")
|
||||||
|
|
||||||
|
new_title = await acreate_title_from_history(request.user.object, conversation=conversation)
|
||||||
|
|
||||||
|
conversation.slug = new_title
|
||||||
|
|
||||||
|
conversation.asave()
|
||||||
|
|
||||||
|
return {"status": "ok", "title": new_title}
|
||||||
|
|
||||||
|
|
||||||
@api_chat.delete("/conversation/message", response_class=Response)
|
@api_chat.delete("/conversation/message", response_class=Response)
|
||||||
@requires(["authenticated"])
|
@requires(["authenticated"])
|
||||||
def delete_message(request: Request, delete_request: DeleteMessageRequestBody) -> Response:
|
def delete_message(request: Request, delete_request: DeleteMessageRequestBody) -> Response:
|
||||||
|
|
|
@ -299,6 +299,23 @@ def construct_chat_history(conversation_history: dict, n: int = 4, agent_name="A
|
||||||
return chat_history
|
return chat_history
|
||||||
|
|
||||||
|
|
||||||
|
async def acreate_title_from_history(
|
||||||
|
user: KhojUser,
|
||||||
|
conversation: Conversation,
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Create a title from the given conversation history
|
||||||
|
"""
|
||||||
|
chat_history = construct_chat_history(conversation.conversation_log)
|
||||||
|
|
||||||
|
title_generation_prompt = prompts.conversation_title_generation.format(chat_history=chat_history)
|
||||||
|
|
||||||
|
with timer("Chat actor: Generate title from conversation history", logger):
|
||||||
|
response = await send_message_to_model_wrapper(title_generation_prompt, user=user)
|
||||||
|
|
||||||
|
return response.strip()
|
||||||
|
|
||||||
|
|
||||||
async def acreate_title_from_query(query: str, user: KhojUser = None) -> str:
|
async def acreate_title_from_query(query: str, user: KhojUser = None) -> str:
|
||||||
"""
|
"""
|
||||||
Create a title from the given query
|
Create a title from the given query
|
||||||
|
|
Loading…
Reference in a new issue