Merge branch 'features/big-upgrade-chat-ux' of github.com:khoj-ai/khoj into document-styling-on-chat-ux

This commit is contained in:
Debanjum Singh Solanky 2024-07-15 10:42:56 +05:30
commit ba0ba6b59f
12 changed files with 508 additions and 211 deletions

View file

@ -65,7 +65,7 @@ dependencies = [
"tenacity == 8.3.0", "tenacity == 8.3.0",
"anyio == 3.7.1", "anyio == 3.7.1",
"pymupdf >= 1.23.5", "pymupdf >= 1.23.5",
"django == 5.0.6", "django == 5.0.7",
"authlib == 1.2.1", "authlib == 1.2.1",
"llama-cpp-python == 0.2.76", "llama-cpp-python == 0.2.76",
"itsdangerous == 2.1.2", "itsdangerous == 2.1.2",

View file

@ -15,6 +15,23 @@
<script src="./utils.js"></script> <script src="./utils.js"></script>
<script src="chatutils.js"></script> <script src="chatutils.js"></script>
<script> <script>
// Add keyboard shortcuts to the chat view
window.addEventListener("keydown", function(event) {
// If enter key is pressed, send the message
if (event.key === "Enter" && !event.shiftKey) {
event.preventDefault();
chat();
// If ^O then Open the chat sessions panel
} else if (event.key === "o" && event.ctrlKey) {
handleCollapseSidePanel();
// If ^N then Create a new conversation
} else if (event.key === "n" && event.ctrlKey) {
createNewConversation();
// If ^D then Delete the conversation history
} else if (event.key === "d" && event.ctrlKey) {
clearConversationHistory();
}
});
let chatOptions = []; let chatOptions = [];
function createCopyParentText(message) { function createCopyParentText(message) {
return function(event) { return function(event) {

View file

@ -33,7 +33,6 @@ interface ChatBodyDataProps {
isLoggedIn: boolean; isLoggedIn: boolean;
} }
function ChatBodyData(props: ChatBodyDataProps) { function ChatBodyData(props: ChatBodyDataProps) {
const searchParams = useSearchParams(); const searchParams = useSearchParams();
const conversationId = searchParams.get('conversationId'); const conversationId = searchParams.get('conversationId');

View file

@ -9,12 +9,12 @@ import { ScrollArea } from "@/components/ui/scroll-area"
import renderMathInElement from 'katex/contrib/auto-render'; import renderMathInElement from 'katex/contrib/auto-render';
import 'katex/dist/katex.min.css'; import 'katex/dist/katex.min.css';
import 'highlight.js/styles/github.css'
import { InlineLoading } from '../loading/loading'; import { InlineLoading } from '../loading/loading';
import { Lightbulb } from "@phosphor-icons/react";
import ProfileCard from '../profileCard/profileCard'; import ProfileCard from '../profileCard/profileCard';
import { Lightbulb } from '@phosphor-icons/react';
interface ChatResponse { interface ChatResponse {
status: string; status: string;

View file

@ -7,7 +7,6 @@ import mditHljs from "markdown-it-highlightjs";
import React, { useEffect, useRef, useState } from 'react'; import React, { useEffect, useRef, useState } from 'react';
import 'katex/dist/katex.min.css'; import 'katex/dist/katex.min.css';
import 'highlight.js/styles/github.css'
import { TeaserReferencesSection, constructAllReferences } from '../referencePanel/referencePanel'; import { TeaserReferencesSection, constructAllReferences } from '../referencePanel/referencePanel';
@ -111,7 +110,6 @@ export interface StreamMessage {
timestamp: string; timestamp: string;
} }
export interface ChatHistoryData { export interface ChatHistoryData {
chat: SingleChatMessage[]; chat: SingleChatMessage[];
agent: AgentData; agent: AgentData;
@ -189,7 +187,6 @@ function chooseIconFromHeader(header: string, iconColor: string) {
return <Brain className={`${classNames}`} />; return <Brain className={`${classNames}`} />;
} }
export function TrainOfThought(props: TrainOfThoughtProps) { export function TrainOfThought(props: TrainOfThoughtProps) {
// The train of thought comes in as a markdown-formatted string. It starts with a heading delimited by two asterisks at the start and end and a colon, followed by the message. Example: **header**: status. This function will parse the message and render it as a div. // The train of thought comes in as a markdown-formatted string. It starts with a heading delimited by two asterisks at the start and end and a colon, followed by the message. Example: **header**: status. This function will parse the message and render it as a div.
let extractedHeader = props.message.match(/\*\*(.*)\*\*/); let extractedHeader = props.message.match(/\*\*(.*)\*\*/);
@ -198,7 +195,7 @@ export function TrainOfThought(props: TrainOfThoughtProps) {
const icon = chooseIconFromHeader(header, iconColor); const icon = chooseIconFromHeader(header, iconColor);
let markdownRendered = DomPurify.sanitize(md.render(props.message)); let markdownRendered = DomPurify.sanitize(md.render(props.message));
return ( return (
<div className={`flex mt-1 ${props.primary ? 'text-gray-400' : 'text-gray-300'} ${styles.trainOfThought} ${props.primary ? styles.primary : ''}`} > <div className={`flex items-center ${props.primary ? 'text-gray-400' : 'text-gray-300'} ${styles.trainOfThought} ${props.primary ? styles.primary : ''}`} >
{icon} {icon}
<div dangerouslySetInnerHTML={{ __html: markdownRendered }} /> <div dangerouslySetInnerHTML={{ __html: markdownRendered }} />
</div> </div>
@ -253,7 +250,7 @@ export default function ChatMessage(props: ChatMessageProps) {
preElements.forEach((preElement) => { preElements.forEach((preElement) => {
const copyButton = document.createElement('button'); const copyButton = document.createElement('button');
const copyImage = document.createElement('img'); const copyImage = document.createElement('img');
copyImage.src = '/copy-button.svg'; copyImage.src = '/static/copy-button.svg';
copyImage.alt = 'Copy'; copyImage.alt = 'Copy';
copyImage.width = 24; copyImage.width = 24;
copyImage.height = 24; copyImage.height = 24;
@ -267,11 +264,12 @@ export default function ChatMessage(props: ChatMessageProps) {
textContent = textContent.replace(/^Copy/, ''); textContent = textContent.replace(/^Copy/, '');
textContent = textContent.trim(); textContent = textContent.trim();
navigator.clipboard.writeText(textContent); navigator.clipboard.writeText(textContent);
copyImage.src = '/static/copy-button-success.svg';
}); });
preElement.prepend(copyButton); preElement.prepend(copyButton);
}); });
} }
}, [markdownRendered]); }, [markdownRendered, isHovering, messageRef]);
if (!props.chatMessage.message) { if (!props.chatMessage.message) {
return null; return null;

View file

@ -2,7 +2,7 @@
import styles from './navMenu.module.css'; import styles from './navMenu.module.css';
import Link from 'next/link'; import Link from 'next/link';
import { useAuthenticatedData, UserProfile } from '@/app/common/auth'; import { useAuthenticatedData } from '@/app/common/auth';
import { useState, useEffect } from 'react'; import { useState, useEffect } from 'react';
import { import {
@ -55,7 +55,6 @@ export default function NavMenu(props: NavMenuProps) {
document.documentElement.classList.add('dark'); document.documentElement.classList.add('dark');
setDarkMode(true); setDarkMode(true);
} }
}, []); }, []);
useEffect(() => { useEffect(() => {
@ -126,12 +125,12 @@ export default function NavMenu(props: NavMenuProps) {
<MenubarTrigger>Profile</MenubarTrigger> <MenubarTrigger>Profile</MenubarTrigger>
<MenubarContent> <MenubarContent>
<MenubarItem> <MenubarItem>
<Toggle <Toggle
pressed={darkMode} pressed={darkMode}
onClick={() => { onClick={() => {
console.log("clicked on dark mode method"); setDarkMode(!darkMode)
setDarkMode(!darkMode)} }
}> }>
<Moon /> <Moon />
</Toggle> </Toggle>
</MenubarItem> </MenubarItem>

View file

@ -2,13 +2,12 @@
import styles from "./sidePanel.module.css"; import styles from "./sidePanel.module.css";
import { Suspense, useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { UserProfile, useAuthenticatedData } from "@/app/common/auth"; import { UserProfile, useAuthenticatedData } from "@/app/common/auth";
import { Avatar, AvatarImage, AvatarFallback } from "@/components/ui/avatar"; import { Avatar, AvatarImage, AvatarFallback } from "@/components/ui/avatar";
import Link from "next/link"; import Link from "next/link";
import useSWR from "swr"; import useSWR from "swr";
import Image from "next/image";
import { import {
Command, Command,
@ -72,8 +71,9 @@ import {
import { Pencil, Trash, Share } from "@phosphor-icons/react"; import { Pencil, Trash, Share } from "@phosphor-icons/react";
import { Button } from "@/components/ui/button"; import { Button, buttonVariants } from "@/components/ui/button";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger } from "@/components/ui/alert-dialog"; import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger } from "@/components/ui/alert-dialog";
import { modifyFileFilterForConversation } from "@/app/common/chatFunctions"; import { modifyFileFilterForConversation } from "@/app/common/chatFunctions";
import { ScrollAreaScrollbar } from "@radix-ui/react-scroll-area"; import { ScrollAreaScrollbar } from "@radix-ui/react-scroll-area";
@ -338,7 +338,7 @@ function SessionsAndFiles(props: SessionsAndFilesProps) {
<div className={styles.sessionsList}> <div className={styles.sessionsList}>
{props.subsetOrganizedData != null && Object.keys(props.subsetOrganizedData).map((timeGrouping) => ( {props.subsetOrganizedData != null && Object.keys(props.subsetOrganizedData).map((timeGrouping) => (
<div key={timeGrouping} className={`my-4`}> <div key={timeGrouping} className={`my-4`}>
<div className={`text-muted-foreground text-sm font-bold p-[0.5rem] `}> <div className={`text-muted-foreground text-sm font-bold p-[0.5rem]`}>
{timeGrouping} {timeGrouping}
</div> </div>
{props.subsetOrganizedData && props.subsetOrganizedData[timeGrouping].map((chatHistory) => ( {props.subsetOrganizedData && props.subsetOrganizedData[timeGrouping].map((chatHistory) => (

View file

@ -35,6 +35,143 @@
--khoj-orange: #FFE7D1; --khoj-orange: #FFE7D1;
--border-color: #e2e2e2; --border-color: #e2e2e2;
--box-shadow-color: rgba(0, 0, 0, 0.03); --box-shadow-color: rgba(0, 0, 0, 0.03);
/* Imported from Highlight.js */
pre code.hljs {
display: block;
overflow-x: auto;
padding: 1em
}
code.hljs {
padding: 3px 5px
}
/*!
Theme: GitHub
Description: Light theme as seen on github.com
Author: github.com
Maintainer: @Hirse
Updated: 2021-05-15
Outdated base version: https://github.com/primer/github-syntax-light
Current colors taken from GitHub's CSS
*/
.hljs {
color: #24292e;
background: #ffffff
}
.hljs-doctag,
.hljs-keyword,
.hljs-meta .hljs-keyword,
.hljs-template-tag,
.hljs-template-variable,
.hljs-type,
.hljs-variable.language_ {
/* prettylights-syntax-keyword */
color: #d73a49
}
.hljs-title,
.hljs-title.class_,
.hljs-title.class_.inherited__,
.hljs-title.function_ {
/* prettylights-syntax-entity */
color: #6f42c1
}
.hljs-attr,
.hljs-attribute,
.hljs-literal,
.hljs-meta,
.hljs-number,
.hljs-operator,
.hljs-variable,
.hljs-selector-attr,
.hljs-selector-class,
.hljs-selector-id {
/* prettylights-syntax-constant */
color: #005cc5
}
.hljs-regexp,
.hljs-string,
.hljs-meta .hljs-string {
/* prettylights-syntax-string */
color: #032f62
}
.hljs-built_in,
.hljs-symbol {
/* prettylights-syntax-variable */
color: #e36209
}
.hljs-comment,
.hljs-code,
.hljs-formula {
/* prettylights-syntax-comment */
color: #6a737d
}
.hljs-name,
.hljs-quote,
.hljs-selector-tag,
.hljs-selector-pseudo {
/* prettylights-syntax-entity-tag */
color: #22863a
}
.hljs-subst {
/* prettylights-syntax-storage-modifier-import */
color: #24292e
}
.hljs-section {
/* prettylights-syntax-markup-heading */
color: #005cc5;
font-weight: bold
}
.hljs-bullet {
/* prettylights-syntax-markup-list */
color: #735c0f
}
.hljs-emphasis {
/* prettylights-syntax-markup-italic */
color: #24292e;
font-style: italic
}
.hljs-strong {
/* prettylights-syntax-markup-bold */
color: #24292e;
font-weight: bold
}
.hljs-addition {
/* prettylights-syntax-markup-inserted */
color: #22863a;
background-color: #f0fff4
}
.hljs-deletion {
/* prettylights-syntax-markup-deleted */
color: #b31d28;
background-color: #ffeef0
}
.hljs-char.escape_,
.hljs-link,
.hljs-params,
.hljs-property,
.hljs-punctuation,
.hljs-tag {
/* purposely ignored */
}
} }
.dark { .dark {
@ -59,6 +196,143 @@
--ring: 263.4 70% 50.4%; --ring: 263.4 70% 50.4%;
--font-family: "Noto Sans", "Noto Sans Arabic", sans-serif !important; --font-family: "Noto Sans", "Noto Sans Arabic", sans-serif !important;
--box-shadow-color: rgba(255, 255, 255, 0.05); --box-shadow-color: rgba(255, 255, 255, 0.05);
/* Imported from highlight.js */
pre code.hljs {
display: block;
overflow-x: auto;
padding: 1em
}
code.hljs {
padding: 3px 5px
}
/*!
Theme: GitHub Dark
Description: Dark theme as seen on github.com
Author: github.com
Maintainer: @Hirse
Updated: 2021-05-15
Outdated base version: https://github.com/primer/github-syntax-dark
Current colors taken from GitHub's CSS
*/
.hljs {
color: #c9d1d9;
background: #0d1117
}
.hljs-doctag,
.hljs-keyword,
.hljs-meta .hljs-keyword,
.hljs-template-tag,
.hljs-template-variable,
.hljs-type,
.hljs-variable.language_ {
/* prettylights-syntax-keyword */
color: #ff7b72
}
.hljs-title,
.hljs-title.class_,
.hljs-title.class_.inherited__,
.hljs-title.function_ {
/* prettylights-syntax-entity */
color: #d2a8ff
}
.hljs-attr,
.hljs-attribute,
.hljs-literal,
.hljs-meta,
.hljs-number,
.hljs-operator,
.hljs-variable,
.hljs-selector-attr,
.hljs-selector-class,
.hljs-selector-id {
/* prettylights-syntax-constant */
color: #79c0ff
}
.hljs-regexp,
.hljs-string,
.hljs-meta .hljs-string {
/* prettylights-syntax-string */
color: #a5d6ff
}
.hljs-built_in,
.hljs-symbol {
/* prettylights-syntax-variable */
color: #ffa657
}
.hljs-comment,
.hljs-code,
.hljs-formula {
/* prettylights-syntax-comment */
color: #8b949e
}
.hljs-name,
.hljs-quote,
.hljs-selector-tag,
.hljs-selector-pseudo {
/* prettylights-syntax-entity-tag */
color: #7ee787
}
.hljs-subst {
/* prettylights-syntax-storage-modifier-import */
color: #c9d1d9
}
.hljs-section {
/* prettylights-syntax-markup-heading */
color: #1f6feb;
font-weight: bold
}
.hljs-bullet {
/* prettylights-syntax-markup-list */
color: #f2cc60
}
.hljs-emphasis {
/* prettylights-syntax-markup-italic */
color: #c9d1d9;
font-style: italic
}
.hljs-strong {
/* prettylights-syntax-markup-bold */
color: #c9d1d9;
font-weight: bold
}
.hljs-addition {
/* prettylights-syntax-markup-inserted */
color: #aff5b4;
background-color: #033a16
}
.hljs-deletion {
/* prettylights-syntax-markup-deleted */
color: #ffdcd7;
background-color: #67060c
}
.hljs-char.escape_,
.hljs-link,
.hljs-params,
.hljs-property,
.hljs-punctuation,
.hljs-tag {
/* purposely ignored */
}
} }
} }

View file

@ -1,230 +1,224 @@
.main { .main {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
padding: 6rem; padding: 6rem;
min-height: 100vh; min-height: 100vh;
} }
.description { .description {
display: inherit; display: inherit;
justify-content: inherit; justify-content: inherit;
align-items: inherit; align-items: inherit;
font-size: 0.85rem; font-size: 0.85rem;
max-width: var(--max-width); max-width: var(--max-width);
width: 100%; width: 100%;
z-index: 2; z-index: 2;
font-family: var(--font-mono); font-family: var(--font-mono);
} }
.description a { .description a {
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
gap: 0.5rem; gap: 0.5rem;
} }
.description p { .description p {
position: relative; position: relative;
margin: 0; margin: 0;
padding: 1rem; padding: 1rem;
background-color: rgba(var(--callout-rgb), 0.5); background-color: rgba(var(--callout-rgb), 0.5);
border: 1px solid rgba(var(--callout-border-rgb), 0.3); border: 1px solid rgba(var(--callout-border-rgb), 0.3);
border-radius: var(--border-radius); border-radius: var(--border-radius);
} }
.code { .code {
font-weight: 700; font-weight: 700;
font-family: var(--font-mono); font-family: var(--font-mono);
} }
.grid { .grid {
display: grid; display: grid;
grid-template-columns: repeat(4, minmax(25%, auto)); grid-template-columns: repeat(4, minmax(25%, auto));
max-width: 100%; max-width: 100%;
width: var(--max-width); width: var(--max-width);
} }
.card { .card {
padding: 1rem 1.2rem; padding: 1rem 1.2rem;
border-radius: var(--border-radius); border-radius: var(--border-radius);
background: rgba(var(--card-rgb), 0); background: rgba(var(--card-rgb), 0);
border: 1px solid rgba(var(--card-border-rgb), 0); border: 1px solid rgba(var(--card-border-rgb), 0);
transition: background 200ms, border 200ms; transition: background 200ms, border 200ms;
} }
.card span { .card span {
display: inline-block; display: inline-block;
transition: transform 200ms; transition: transform 200ms;
} }
.card h2 { .card h2 {
font-weight: 600; font-weight: 600;
margin-bottom: 0.7rem; margin-bottom: 0.7rem;
} }
.card p { .card p {
margin: 0; margin: 0;
opacity: 0.6; opacity: 0.6;
font-size: 0.9rem; font-size: 0.9rem;
line-height: 1.5; line-height: 1.5;
max-width: 30ch; max-width: 30ch;
text-wrap: balance; text-wrap: balance;
} }
.center { .center {
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
position: relative; position: relative;
padding: 4rem 0; padding: 4rem 0;
} }
.center::before { .center::before {
background: var(--secondary-glow); background: var(--secondary-glow);
border-radius: 50%; border-radius: 50%;
width: 480px; width: 480px;
height: 360px; height: 360px;
margin-left: -400px; margin-left: -400px;
} }
.center::after { .center::after {
background: var(--primary-glow); background: var(--primary-glow);
width: 240px; width: 240px;
height: 180px; height: 180px;
z-index: -1; z-index: -1;
} }
.center::before, .center::before,
.center::after { .center::after {
content: ""; content: "";
left: 50%; left: 50%;
position: absolute; position: absolute;
filter: blur(45px); filter: blur(45px);
transform: translateZ(0); transform: translateZ(0);
} }
.logo { .logo {
position: relative; position: relative;
} }
/* Enable hover only on non-touch devices */ /* Enable hover only on non-touch devices */
@media (hover: hover) and (pointer: fine) { @media (hover: hover) and (pointer: fine) {
.card:hover { .card:hover {
background: rgba(var(--card-rgb), 0.1); background: rgba(var(--card-rgb), 0.1);
border: 1px solid rgba(var(--card-border-rgb), 0.15); border: 1px solid rgba(var(--card-border-rgb), 0.15);
} }
.card:hover span { .card:hover span {
transform: translateX(4px); transform: translateX(4px);
} }
} }
@media (prefers-reduced-motion) { @media (prefers-reduced-motion) {
.card:hover span { .card:hover span {
transform: none; transform: none;
} }
} }
/* Mobile */ /* Mobile */
@media (max-width: 700px) { @media (max-width: 700px) {
.content { .content {
padding: 4rem; padding: 4rem;
} }
.grid { .grid {
grid-template-columns: 1fr; grid-template-columns: 1fr;
margin-bottom: 120px; margin-bottom: 120px;
max-width: 320px; max-width: 320px;
text-align: center; text-align: center;
} }
.card { .card {
padding: 1rem 2.5rem; padding: 1rem 2.5rem;
} }
.card h2 { .card h2 {
margin-bottom: 0.5rem; margin-bottom: 0.5rem;
} }
.center { .center {
padding: 8rem 0 6rem; padding: 8rem 0 6rem;
} }
.center::before { .center::before {
transform: none; transform: none;
height: 300px; height: 300px;
} }
.description { .description {
font-size: 0.8rem; font-size: 0.8rem;
} }
.description a { .description a {
padding: 1rem; padding: 1rem;
} }
.description p, .description p,
.description div { .description div {
display: flex; display: flex;
justify-content: center; justify-content: center;
position: fixed; position: fixed;
width: 100%; width: 100%;
} }
.description p { .description p {
align-items: center; align-items: center;
inset: 0 0 auto; inset: 0 0 auto;
padding: 2rem 1rem 1.4rem; padding: 2rem 1rem 1.4rem;
border-radius: 0; border-radius: 0;
border: none; border: none;
border-bottom: 1px solid rgba(var(--callout-border-rgb), 0.25); border-bottom: 1px solid rgba(var(--callout-border-rgb), 0.25);
background: linear-gradient( background: linear-gradient(to bottom,
to bottom, rgba(var(--background-start-rgb), 1),
rgba(var(--background-start-rgb), 1), rgba(var(--callout-rgb), 0.5));
rgba(var(--callout-rgb), 0.5) background-clip: padding-box;
); backdrop-filter: blur(24px);
background-clip: padding-box; }
backdrop-filter: blur(24px);
}
.description div { .description div {
align-items: flex-end; align-items: flex-end;
pointer-events: none; pointer-events: none;
inset: auto 0 0; inset: auto 0 0;
padding: 2rem; padding: 2rem;
height: 200px; height: 200px;
background: linear-gradient( background: linear-gradient(to bottom,
to bottom, transparent 0%,
transparent 0%, rgb(var(--background-end-rgb)) 40%);
rgb(var(--background-end-rgb)) 40% z-index: 1;
); }
z-index: 1;
}
} }
/* Tablet and Smaller Desktop */ /* Tablet and Smaller Desktop */
@media (min-width: 701px) and (max-width: 1120px) { @media (min-width: 701px) and (max-width: 1120px) {
.grid { .grid {
grid-template-columns: repeat(2, 50%); grid-template-columns: repeat(2, 50%);
} }
} }
@media (prefers-color-scheme: dark) { @media (prefers-color-scheme: dark) {
.vercelLogo { .logo {
filter: invert(1); filter: invert(1) drop-shadow(0 0 0.3rem #ffffff70);
} }
.logo {
filter: invert(1) drop-shadow(0 0 0.3rem #ffffff70);
}
} }
@keyframes rotate { @keyframes rotate {
from { from {
transform: rotate(360deg); transform: rotate(360deg);
} }
to {
transform: rotate(0deg); to {
} transform: rotate(0deg);
}
} }

View file

@ -0,0 +1,27 @@
# Generated by Django 4.2.11 on 2024-07-08 09:27
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("database", "0051_merge_20240702_1220"),
]
operations = [
migrations.AlterField(
model_name="searchmodelconfig",
name="bi_encoder_docs_encode_config",
field=models.JSONField(blank=True, default=dict),
),
migrations.AlterField(
model_name="searchmodelconfig",
name="bi_encoder_model_config",
field=models.JSONField(blank=True, default=dict),
),
migrations.AlterField(
model_name="searchmodelconfig",
name="bi_encoder_query_encode_config",
field=models.JSONField(blank=True, default=dict),
),
]

View file

@ -121,9 +121,9 @@ User's Notes:
## Image Generation ## Image Generation
## -- ## --
image_generation_improve_prompt_dalle = PromptTemplate.from_template( image_generation_improve_prompt_base = """
""" You are a talented creator with the ability to describe images to compose in vivid, fine detail.
You are a talented creator. Generate a detailed prompt to generate an image based on the following description. Update the query below to improve the image generation. Add additional context to the query to improve the image generation. Make sure to retain any important information originally from the query. You are provided with the following information to help you generate the prompt: Use the provided context and user prompt to generate a more detailed prompt to create an image:
Today's Date: {current_date} Today's Date: {current_date}
User's Location: {location} User's Location: {location}
@ -137,39 +137,29 @@ Online References:
Conversation Log: Conversation Log:
{chat_history} {chat_history}
Query: {query} User Prompt: "{query}"
Remember, now you are generating a prompt to improve the image generation. Add additional context to the query to improve the image generation. Make sure to retain any important information originally from the query. Use the additional context from the user's notes, online references and conversation log to improve the image generation. Now generate an improved prompt describing the image to generate in vivid, fine detail.
Improved Query:""" - Use today's date, user's location, user's notes and online references to weave in any context that will improve the image generation.
- Retain any important information and follow any instructions in the conversation log or user prompt.
- Add specific, fine position details to compose the image.
- Ensure your improved prompt is in prose format."""
image_generation_improve_prompt_dalle = PromptTemplate.from_template(
f"""
{image_generation_improve_prompt_base}
Improved Prompt:
""".strip()
) )
image_generation_improve_prompt_sd = PromptTemplate.from_template( image_generation_improve_prompt_sd = PromptTemplate.from_template(
""" f"""
You are a talented creator. Write 2-5 sentences with precise image composition, position details to create an image. {image_generation_improve_prompt_base}
Use the provided context below to add specific, fine details to the image composition. - If any text is to be rendered in the image put it within double quotes in your improved prompt.
Retain any important information and follow any instructions from the original prompt.
Put any text to be rendered in the image within double quotes in your improved prompt.
You are provided with the following context to help enhance the original prompt:
Today's Date: {current_date} Improved Prompt:
User's Location: {location} """.strip()
User's Notes:
{references}
Online References:
{online_results}
Conversation Log:
{chat_history}
Original Prompt: "{query}"
Now create an improved prompt using the context provided above to generate an image.
Retain any important information and follow any instructions from the original prompt.
Use the additional context from the user's notes, online references and conversation log to improve the image generation.
Improved Prompt:"""
) )
## Online Search Conversation ## Online Search Conversation

View file

@ -459,7 +459,7 @@ async def generate_better_image_prompt(
Generate a better image prompt from the given query Generate a better image prompt from the given query
""" """
today_date = datetime.now(tz=timezone.utc).strftime("%Y-%m-%d") today_date = datetime.now(tz=timezone.utc).strftime("%Y-%m-%d, %A")
model_type = model_type or TextToImageModelConfig.ModelType.OPENAI model_type = model_type or TextToImageModelConfig.ModelType.OPENAI
if location_data: if location_data:
@ -776,8 +776,8 @@ async def text_to_image(
chat_history += f"Q: {chat['intent']['query']}\n" chat_history += f"Q: {chat['intent']['query']}\n"
chat_history += f"A: {chat['message']}\n" chat_history += f"A: {chat['message']}\n"
elif chat["by"] == "khoj" and "text-to-image" in chat["intent"].get("type"): elif chat["by"] == "khoj" and "text-to-image" in chat["intent"].get("type"):
chat_history += f"Q: Query: {chat['intent']['query']}\n" chat_history += f"Q: Prompt: {chat['intent']['query']}\n"
chat_history += f"A: Improved Query: {chat['intent']['inferred-queries'][0]}\n" chat_history += f"A: Improved Prompt: {chat['intent']['inferred-queries'][0]}\n"
with timer("Improve the original user query", logger): with timer("Improve the original user query", logger):
if send_status_func: if send_status_func:
@ -836,7 +836,6 @@ async def text_to_image(
"model": text2image_model, "model": text2image_model,
"mode": "text-to-image", "mode": "text-to-image",
"output_format": "png", "output_format": "png",
"seed": 1032622926,
"aspect_ratio": "1:1", "aspect_ratio": "1:1",
}, },
) )