From 39d94a136656ff03a43419bf8c88865b88899382 Mon Sep 17 00:00:00 2001 From: Anastasiia Solop <35258279+anastasiya1155@users.noreply.github.com> Date: Mon, 20 Nov 2023 13:08:16 +0100 Subject: [PATCH] Support lang and file filters in chat (#1132) * Respect path filters in agent queries * Fix autocomplete for langs * Add directory indicator * Add directory indicator to autocomplete * Use central lang map instead of a separate one * Simplify this logic * Add position information to literals * Add `raw_query` to exchange * Add offsets to lang filters * Respect the clippy * Aggregate and rank languages from the executed queries * Only offer lang suggestions if there's a lang filter in the query * Partially parsed lang functions will not return results * Allow excluding results from certain kind of results * Normalize results somewhat * Show lang filters more aggressively * Add arbitrary language suggestions * Tuning * Make it a greedy regex * render parsed user query in history * add autocomplete component * automatically convert user query between input and display * show only file name in the autocomplete input * use another character for autocomplete regex * reorder query * add content=false query param * make the suggestions container bigger * Apply partial lang filter * fix and test splitUserInputAfterAutocomplete function * improve styles for highlight background * update autocomplete chip style * Add langs queries to fuzzy matcher * Autocomplete on lang even if there are no matches * More fine tuning * More fine tuning * More tweaks * Update server/bleep/src/webserver/autocomplete.rs Co-authored-by: Gabriel Gordon-Hall * Nicer interface * Move `raw_query` to `query` * Fix tests * move raw_query inside query * Propagate certain filters to LLM --------- Co-authored-by: rsdy Co-authored-by: rsdy Co-authored-by: Gabriel Gordon-Hall --- .../Chat/ChatBody/AllCoversations/index.tsx | 9 +- .../components/Chat/ChatBody/Conversation.tsx | 3 + .../UserParsedQuery/LangChip.tsx | 22 + .../UserParsedQuery/PathChip.tsx | 31 + .../UserParsedQuery/index.tsx | 32 + .../ChatBody/ConversationMessage/index.tsx | 16 +- .../components/Chat/ChatFooter/NLInput.tsx | 229 +++++- .../Chat/ChatFooter/SuggestionItem.tsx | 64 ++ .../Chat/ChatFooter/Suggestions.tsx | 80 ++ .../src/components/Chat/ChatFooter/index.tsx | 19 +- client/src/components/Chat/index.tsx | 18 +- client/src/locales/en.json | 7 +- client/src/locales/es.json | 7 +- client/src/locales/it.json | 7 +- client/src/locales/ja.json | 7 +- client/src/locales/zh-CN.json | 7 +- client/src/mappers/conversation.ts | 59 +- client/src/types/api.ts | 30 +- client/src/types/general.ts | 11 +- client/src/utils/index.test.ts | 102 +++ client/src/utils/index.ts | 58 +- package-lock.json | 54 ++ package.json | 4 +- server/bleep/src/agent.rs | 45 +- server/bleep/src/agent/exchange.rs | 15 +- server/bleep/src/indexes/file.rs | 10 + server/bleep/src/indexes/reader.rs | 9 +- server/bleep/src/indexes/schema.rs | 2 +- server/bleep/src/query/execute.rs | 4 + server/bleep/src/query/languages.rs | 14 +- server/bleep/src/query/parser.rs | 744 ++++++++++++++---- server/bleep/src/webserver/answer.rs | 4 +- server/bleep/src/webserver/autocomplete.rs | 261 +++--- server/bleep/src/webserver/search.rs | 1 + 34 files changed, 1639 insertions(+), 346 deletions(-) create mode 100644 client/src/components/Chat/ChatBody/ConversationMessage/UserParsedQuery/LangChip.tsx create mode 100644 client/src/components/Chat/ChatBody/ConversationMessage/UserParsedQuery/PathChip.tsx create mode 100644 client/src/components/Chat/ChatBody/ConversationMessage/UserParsedQuery/index.tsx create mode 100644 client/src/components/Chat/ChatFooter/SuggestionItem.tsx create mode 100644 client/src/components/Chat/ChatFooter/Suggestions.tsx create mode 100644 client/src/utils/index.test.ts diff --git a/client/src/components/Chat/ChatBody/AllCoversations/index.tsx b/client/src/components/Chat/ChatBody/AllCoversations/index.tsx index 4924683d49..552d5da691 100644 --- a/client/src/components/Chat/ChatBody/AllCoversations/index.tsx +++ b/client/src/components/Chat/ChatBody/AllCoversations/index.tsx @@ -21,7 +21,10 @@ import { OpenChatHistoryItem, } from '../../../../types/general'; import { conversationsCache } from '../../../../services/cache'; -import { mapLoadingSteps } from '../../../../mappers/conversation'; +import { + mapLoadingSteps, + mapUserQuery, +} from '../../../../mappers/conversation'; import { LocaleContext } from '../../../../context/localeContext'; import { getDateFnsLocale } from '../../../../utils'; import ConversationListItem from './ConversationListItem'; @@ -63,9 +66,11 @@ const AllConversations = ({ resp.forEach((m) => { // @ts-ignore const userQuery = m.search_steps.find((s) => s.type === 'QUERY'); + const parsedQuery = mapUserQuery(m); conv.push({ author: ChatMessageAuthor.User, - text: m.query?.target?.Plain || userQuery?.content?.query || '', + text: m.query.raw_query || userQuery?.content?.query || '', + parsedQuery, isFromHistory: true, }); conv.push({ diff --git a/client/src/components/Chat/ChatBody/Conversation.tsx b/client/src/components/Chat/ChatBody/Conversation.tsx index 6346ab00b3..314d43f795 100644 --- a/client/src/components/Chat/ChatBody/Conversation.tsx +++ b/client/src/components/Chat/ChatBody/Conversation.tsx @@ -59,6 +59,9 @@ const Conversation = ({ isHistory={isHistory} author={m.author} message={m.text} + parsedQuery={ + m.author === ChatMessageAuthor.Server ? undefined : m.parsedQuery + } error={m.author === ChatMessageAuthor.Server ? m.error : ''} showInlineFeedback={ m.author === ChatMessageAuthor.Server && diff --git a/client/src/components/Chat/ChatBody/ConversationMessage/UserParsedQuery/LangChip.tsx b/client/src/components/Chat/ChatBody/ConversationMessage/UserParsedQuery/LangChip.tsx new file mode 100644 index 0000000000..025cf9b229 --- /dev/null +++ b/client/src/components/Chat/ChatBody/ConversationMessage/UserParsedQuery/LangChip.tsx @@ -0,0 +1,22 @@ +import FileIcon from '../../../../FileIcon'; +import { getFileExtensionForLang } from '../../../../../utils'; + +type Props = { + lang: string; +}; + +const LangChip = ({ lang }: Props) => { + return ( + + + + {lang} + + + ); +}; + +export default LangChip; diff --git a/client/src/components/Chat/ChatBody/ConversationMessage/UserParsedQuery/PathChip.tsx b/client/src/components/Chat/ChatBody/ConversationMessage/UserParsedQuery/PathChip.tsx new file mode 100644 index 0000000000..a20f299c07 --- /dev/null +++ b/client/src/components/Chat/ChatBody/ConversationMessage/UserParsedQuery/PathChip.tsx @@ -0,0 +1,31 @@ +import { useMemo } from 'react'; +import { FolderClosed, ArrowOut } from '../../../../../icons'; +import FileIcon from '../../../../FileIcon'; +import { splitPath } from '../../../../../utils'; + +type Props = { + path: string; +}; + +const PathChip = ({ path }: Props) => { + const isFolder = useMemo(() => path.endsWith('/'), [path]); + return ( + + + {isFolder ? ( + + ) : ( + + )} + + {isFolder ? path.replace(/\/$/, '') : splitPath(path).pop()} + + + + ); +}; + +export default PathChip; diff --git a/client/src/components/Chat/ChatBody/ConversationMessage/UserParsedQuery/index.tsx b/client/src/components/Chat/ChatBody/ConversationMessage/UserParsedQuery/index.tsx new file mode 100644 index 0000000000..17a671b16d --- /dev/null +++ b/client/src/components/Chat/ChatBody/ConversationMessage/UserParsedQuery/index.tsx @@ -0,0 +1,32 @@ +import { memo } from 'react'; +import { + ParsedQueryType, + ParsedQueryTypeEnum, +} from '../../../../../types/general'; +import PathChip from './PathChip'; +import LangChip from './LangChip'; + +type Props = { + textQuery: string; + parsedQuery?: ParsedQueryType[]; +}; + +const UserParsedQuery = ({ textQuery, parsedQuery }: Props) => { + return ( +
+ {parsedQuery + ? parsedQuery.map((p, i) => + p.type === ParsedQueryTypeEnum.TEXT ? ( + p.text + ) : p.type === ParsedQueryTypeEnum.PATH ? ( + + ) : p.type === ParsedQueryTypeEnum.LANG ? ( + + ) : null, + ) + : textQuery} +
+ ); +}; + +export default memo(UserParsedQuery); diff --git a/client/src/components/Chat/ChatBody/ConversationMessage/index.tsx b/client/src/components/Chat/ChatBody/ConversationMessage/index.tsx index af21e0a507..eb34863e50 100644 --- a/client/src/components/Chat/ChatBody/ConversationMessage/index.tsx +++ b/client/src/components/Chat/ChatBody/ConversationMessage/index.tsx @@ -10,7 +10,11 @@ import { WrenchAndScrewdriver, } from '../../../../icons'; import { DeviceContext } from '../../../../context/deviceContext'; -import { ChatLoadingStep, ChatMessageAuthor } from '../../../../types/general'; +import { + ChatLoadingStep, + ChatMessageAuthor, + ParsedQueryType, +} from '../../../../types/general'; import { ChatContext } from '../../../../context/chatContext'; import Button from '../../../Button'; import { LocaleContext } from '../../../../context/localeContext'; @@ -24,10 +28,12 @@ import { } from '../../../../services/storage'; import MessageFeedback from './MessageFeedback'; import FileChip from './FileChip'; +import UserParsedQuery from './UserParsedQuery'; type Props = { author: ChatMessageAuthor; message?: string; + parsedQuery?: ParsedQueryType[]; error?: string; threadId: string; queryId: string; @@ -61,6 +67,7 @@ const ConversationMessage = ({ onMessageEdit, responseTimestamp, singleFileExplanation, + parsedQuery, }: Props) => { const { t } = useTranslation(); const [isLoadingStepsShown, setLoadingStepsShown] = useState( @@ -172,7 +179,7 @@ const ConversationMessage = ({ )} - {message && ( + {!!message && (
{author === ChatMessageAuthor.Server ? ( ) : ( <> -
{message}
+ {!isHistory && !!queryId && (