Skip to content

Commit f76ed66

Browse files
vid277cdxker
authored andcommitted
feature: default search and ai questions sends images
1 parent 1cb915a commit f76ed66

File tree

15 files changed

+137
-71
lines changed

15 files changed

+137
-71
lines changed

clients/search-component/example/src/routes/ecommerce.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export default function ECommerce() {
2525
import.meta.env.VITE_SHOW_FLOATING_SEARCH_ICON == "true";
2626
const showFloatingInput = import.meta.env.VITE_SHOW_FLOATING_INPUT == "true";
2727
const usePagefind = import.meta.env.VITE_USE_PAGEFIND == "true";
28-
const defaultSearchQueries: string[] = (
28+
const defaultSearchQueries: any= (
2929
import.meta.env.VITE_DEFAULT_SEARCH_QUERIES ?? ""
3030
).split(",");
3131
const defaultTags: any[] = JSON.parse(

clients/search-component/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@
8787
"react-two-thumb-input-range": "^1.0.7",
8888
"remark-gfm": "^4.0.1",
8989
"tailwind-merge": "^3.0.2",
90-
"trieve-ts-sdk": "^0.0.110"
90+
"trieve-ts-sdk": "*"
9191
},
9292
"peerDependencies": {
9393
"react": "^18.3.1 || ^19.0.0-rc",

clients/search-component/src/TrieveModal/Chat/SuggestedQuestions.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import React from "react";
2-
import React from "react";
32
import { useSuggestedQuestions } from "../../utils/hooks/useSuggestedQuestions";
43
import { useChatState } from "../../utils/hooks/chat-context";
54
import {
@@ -34,7 +33,6 @@ export const SuggestedQuestions = ({
3433
const handleSuggestedQuestion = async (
3534
q: AiQuestion | DefaultSearchQuery | string,
3635
) => {
37-
console.log("q", q);
3836
setCurrentQuestion(isAiQuestion(q) ? q.questionText : isDefaultSearchQuery(q) ? q.query ?? "" : q);
3937

4038
if (!isDefaultSearchQuery(q)) {

clients/search-component/src/TrieveModal/Search/SuggestedQueries.tsx

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ import { DefaultSearchQuery } from "trieve-ts-sdk";
55
import { getSuggestedQueries } from "../../utils/trieve";
66

77
export const SuggestedQueries = () => {
8-
const { props, query, setQuery, imageUrl, trieveSDK } = useModalState();
8+
const { props, query, setQuery, imageUrl, setImageUrl, trieveSDK } =
9+
useModalState();
910
const [isLoading, setIsLoading] = useState(false);
1011
const [suggestedQueries, setSuggestedQueries] = useState<
1112
(DefaultSearchQuery | string)[]
@@ -78,15 +79,15 @@ export const SuggestedQueries = () => {
7879
<div className="suggested-query loading">Loading...</div>
7980
) : (
8081
suggestedQueries.map((q) => {
81-
let query = isDefaultSearchQuery(q) ? q.query?.replace(/^-|\*$/g, "") : q;
82+
let query = isDefaultSearchQuery(q) ? q.query?.replace(/^-|\*$/g, "") : q.replace(/^-|\*$/g, "");
8283
query = query?.trim();
8384
return (
8485
<button
85-
onClick={() => setQuery(q)}
86-
key={q}
86+
onClick={() => handleSendSuggestedQuery(q)}
87+
key={query}
8788
className={`suggested-query${isLoading ? " loading" : ""}`}
8889
>
89-
{q}
90+
{query}
9091
</button>
9192
);
9293
})

clients/search-component/src/TrieveModal/index.tsx

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,16 @@ import { createPortal } from "react-dom";
2121

2222
const Modal = () => {
2323
useKeyboardNavigation();
24-
const { open, setOpen, setMode, setQuery, props, display, abTreatment } =
25-
useModalState();
24+
const {
25+
open,
26+
setOpen,
27+
setMode,
28+
setImageUrl,
29+
setQuery,
30+
props,
31+
display,
32+
abTreatment,
33+
} = useModalState();
2634
const { askQuestion, chatWithGroup, cancelGroupChat, clearConversation } =
2735
useChatState();
2836

@@ -167,20 +175,21 @@ const Modal = () => {
167175
try {
168176
const customEvent = e as CustomEvent<{
169177
text: string;
178+
imageUrl?: string;
170179
}>;
171180

172181
const defaultMode = props.defaultSearchMode || "search";
173182
if (props.inline) return;
174183

175184
if (defaultMode === "chat") {
176-
setOpen(true);
177185
setMode("chat");
178186
cancelGroupChat();
179-
180-
askQuestion(customEvent.detail.text);
187+
setOpen(true);
188+
askQuestion(customEvent.detail.text, undefined, undefined, "", true, customEvent.detail.imageUrl);
181189
} else {
182190
setOpen(true);
183191
setMode("search");
192+
setImageUrl(customEvent.detail.imageUrl ?? "");
184193
setQuery(customEvent.detail.text);
185194
}
186195
} catch (e) {

clients/search-component/src/utils/hooks/chat-context.tsx

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ const ChatContext = createContext<{
7575
groupIds?: string[],
7676
systemPrompt?: string,
7777
displayUserMessage?: boolean,
78+
imageUrl?: string,
7879
) => Promise<void>;
7980
isLoading: boolean;
8081
loadingText: string;
@@ -140,6 +141,7 @@ function ChatProvider({ children }: { children: React.ReactNode }) {
140141
ChunkIdWithIndex[]
141142
>([]);
142143
const [groupIdsInChat, setGroupIdsInChat] = useState<string[]>([]);
144+
let localImageUrl = imageUrl;
143145

144146
const createTopic = async ({
145147
question,
@@ -521,7 +523,6 @@ function ChatProvider({ children }: { children: React.ReactNode }) {
521523
let referenceImageUrls: string[] = [];
522524
let referenceChunks: Chunk[] = [];
523525

524-
525526
if (!groupIds || groupIds.length === 0) {
526527
chatMessageAbortController.current = new AbortController();
527528
const toolCallTimeout = setTimeout(
@@ -541,7 +542,7 @@ function ChatProvider({ children }: { children: React.ReactNode }) {
541542
if (props.type === "ecommerce" && !curGroup) {
542543
return await trieveSDK.getToolCallFunctionParams({
543544
user_message_text: questionProp || currentQuestion,
544-
image_url: imageUrl ? imageUrl : null,
545+
image_url: localImageUrl ? localImageUrl : null,
545546
audio_input: curAudioBase64 ? curAudioBase64 : null,
546547
tool_function: {
547548
name: "get_price_filters",
@@ -601,7 +602,7 @@ function ChatProvider({ children }: { children: React.ReactNode }) {
601602
}
602603
},
603604
)} \n\n${props.searchToolCallOptions?.userMessageTextPrefix ?? defaultSearchToolCallOptions.userMessageTextPrefix}: ${questionProp || currentQuestion}.`,
604-
image_url: imageUrl ? imageUrl : null,
605+
image_url: localImageUrl ? localImageUrl : null,
605606
audio_input: curAudioBase64 ? curAudioBase64 : null,
606607
tool_function: {
607608
name: "skip_search",
@@ -622,10 +623,10 @@ function ChatProvider({ children }: { children: React.ReactNode }) {
622623
})
623624

624625
const imageFiltersPromise = retryOperation(async () => {
625-
if (imageUrl) {
626+
if (localImageUrl) {
626627
return await trieveSDK.getToolCallFunctionParams({
627628
user_message_text: questionProp || currentQuestion,
628-
image_url: imageUrl ? imageUrl : null,
629+
image_url: localImageUrl ? localImageUrl : null,
629630
tool_function: {
630631
name: "get_image_filters",
631632
description:
@@ -666,7 +667,7 @@ function ChatProvider({ children }: { children: React.ReactNode }) {
666667
(message) => `\n\n${message.text}`,
667668
)} \n\n ${questionProp || currentQuestion}`
668669
: null,
669-
image_url: imageUrl ? imageUrl : null,
670+
image_url: localImageUrl ? localImageUrl : null,
670671
audio_input: curAudioBase64 ? curAudioBase64 : null,
671672
tool_function: {
672673
name: "get_filters",
@@ -716,7 +717,7 @@ function ChatProvider({ children }: { children: React.ReactNode }) {
716717
text: transcribedQuery ?? "",
717718
additional: null,
718719
queryId: null,
719-
imageUrl: imageUrl ? imageUrl : null,
720+
imageUrl: localImageUrl ? localImageUrl : null,
720721
},
721722
{
722723
type: "system",
@@ -729,7 +730,7 @@ function ChatProvider({ children }: { children: React.ReactNode }) {
729730
}
730731

731732
useImage = (imageFiltersResp?.parameters &&
732-
(imageFiltersResp.parameters as any)["image"] === true && imageUrl) as boolean;
733+
(imageFiltersResp.parameters as any)["image"] === true && localImageUrl) as boolean;
733734

734735
const match_any_tags = [];
735736
if (tagFiltersResp?.parameters) {
@@ -1060,7 +1061,6 @@ function ChatProvider({ children }: { children: React.ReactNode }) {
10601061
}
10611062

10621063
const handleImageEdit = async () => {
1063-
console.log("REFERENCE IMAGE URLS", referenceImageUrls);
10641064
if (useImage) {
10651065
setLoadingText("Editing image...");
10661066

@@ -1069,7 +1069,7 @@ function ChatProvider({ children }: { children: React.ReactNode }) {
10691069
input_images: [
10701070
{
10711071
image_src: {
1072-
url: imageUrl,
1072+
url: localImageUrl,
10731073
},
10741074
file_name: "input_image",
10751075
},
@@ -1313,7 +1313,13 @@ function ChatProvider({ children }: { children: React.ReactNode }) {
13131313
groupIds?: string[],
13141314
systemPrompt?: string,
13151315
displayUserMessage?: boolean,
1316+
imageUrl?: string,
13161317
) => {
1318+
if (imageUrl) {
1319+
localImageUrl = imageUrl;
1320+
setImageUrl(imageUrl);
1321+
}
1322+
13171323
const questionProp = question;
13181324
setIsDoneReading(false);
13191325
setCurrentQuestion("");
@@ -1367,7 +1373,7 @@ function ChatProvider({ children }: { children: React.ReactNode }) {
13671373
(displayUserMessage ?? true) ? questionProp || currentQuestion : "",
13681374
additional: null,
13691375
queryId: null,
1370-
imageUrl: imageUrl ? imageUrl : null,
1376+
imageUrl: localImageUrl ? localImageUrl : null,
13711377
},
13721378
{
13731379
type: "system",
@@ -1384,7 +1390,7 @@ function ChatProvider({ children }: { children: React.ReactNode }) {
13841390
text: "Loading...",
13851391
additional: null,
13861392
queryId: null,
1387-
imageUrl: imageUrl ? imageUrl : null,
1393+
imageUrl: localImageUrl ? localImageUrl : null,
13881394
},
13891395
{
13901396
type: "system",
@@ -1410,6 +1416,7 @@ function ChatProvider({ children }: { children: React.ReactNode }) {
14101416
systemPrompt,
14111417
});
14121418
}
1419+
setImageUrl("");
14131420
};
14141421

14151422
const switchToChatAndAskQuestion = async (query: string) => {

clients/search-component/src/utils/hooks/modal-context.tsx

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
ChunkGroup,
1313
SearchChunksReqPayload,
1414
TrieveSDK,
15+
DefaultSearchQuery,
1516
} from "trieve-ts-sdk";
1617
import {
1718
groupSearchWithPagefind,
@@ -125,7 +126,6 @@ export interface SearchPageProps {
125126
filterSidebarProps?: FilterSidebarProps;
126127
display?: boolean;
127128
}
128-
129129
export interface AiQuestion {
130130
questionText: string;
131131
promptForAI?: string;
@@ -136,11 +136,18 @@ export interface AiQuestion {
136136
}
137137

138138
export function isAiQuestion(
139-
question: string | AiQuestion,
139+
question: string | AiQuestion | DefaultSearchQuery,
140140
): question is AiQuestion {
141141
return typeof question === "object" && "questionText" in question;
142142
}
143143

144+
export function isDefaultSearchQuery(
145+
question: string | AiQuestion | DefaultSearchQuery,
146+
): question is DefaultSearchQuery {
147+
return typeof question === "object" && "query" in question;
148+
}
149+
150+
144151
export type ModalProps = {
145152
datasetId: string;
146153
apiKey: string;

clients/search-component/src/utils/hooks/useSuggestedQuestions.ts

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
import { useEffect, useState } from "react";
22
import { getSuggestedQuestions } from "../trieve";
33
import { ModalProps, useModalState } from "./modal-context";
4+
import { DefaultSearchQuery } from "trieve-ts-sdk";
45

56
export const useSuggestedQuestions = () => {
67
const { props, query, trieveSDK, currentGroup } = useModalState();
78
const [isLoadingSuggestedQueries, setIsLoadingSuggestedQueries] =
89
useState(false);
910

1011
const [suggestedQuestions, setSuggestedQuestions] = useState<
11-
ModalProps["defaultAiQuestions"]
12+
ModalProps["defaultAiQuestions"] | DefaultSearchQuery[]
1213
>(props.defaultAiQuestions ?? []);
1314

1415
const getQuestions = async () => {
@@ -22,11 +23,7 @@ export const useSuggestedQuestions = () => {
2223
query,
2324
props,
2425
});
25-
setSuggestedQuestions(
26-
queries.queries.map((q) => {
27-
return q.replace(/^[\d.-]+\s*/, "").trim();
28-
}),
29-
);
26+
setSuggestedQuestions(queries.queries);
3027
setIsLoadingSuggestedQueries(false);
3128
};
3229

@@ -50,11 +47,7 @@ export const useSuggestedQuestions = () => {
5047
: currentGroup?.tracking_id,
5148
props,
5249
});
53-
setSuggestedQuestions(
54-
queries.queries.map((q) => {
55-
return q.replace(/^[\d.-]+\s*/, "").trim();
56-
}),
57-
);
50+
setSuggestedQuestions(queries.queries);
5851
setIsLoadingSuggestedQueries(false);
5952
});
6053

clients/ts-sdk/openapi.json

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12311,6 +12311,19 @@
1231112311
"lte": "2021-01-01 00:00:00.000"
1231212312
}
1231312313
},
12314+
"DefaultSearchQuery": {
12315+
"type": "object",
12316+
"properties": {
12317+
"imageUrl": {
12318+
"type": "string",
12319+
"nullable": true
12320+
},
12321+
"query": {
12322+
"type": "string",
12323+
"nullable": true
12324+
}
12325+
}
12326+
},
1231412327
"DeleteTopicData": {
1231512328
"type": "object",
1231612329
"required": [
@@ -16435,7 +16448,7 @@
1643516448
"defaultAiQuestions": {
1643616449
"type": "array",
1643716450
"items": {
16438-
"type": "string"
16451+
"$ref": "#/components/schemas/DefaultSearchQuery"
1643916452
},
1644016453
"nullable": true
1644116454
},
@@ -16454,7 +16467,7 @@
1645416467
"defaultSearchQueries": {
1645516468
"type": "array",
1645616469
"items": {
16457-
"type": "string"
16470+
"$ref": "#/components/schemas/DefaultSearchQuery"
1645816471
},
1645916472
"nullable": true
1646016473
},

clients/ts-sdk/src/types.gen.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1491,6 +1491,11 @@ export type DateRange = {
14911491
lte?: (string) | null;
14921492
};
14931493

1494+
export type DefaultSearchQuery = {
1495+
imageUrl?: (string) | null;
1496+
query?: (string) | null;
1497+
};
1498+
14941499
export type DeleteTopicData = {
14951500
/**
14961501
* The id of the topic to target.
@@ -3058,11 +3063,11 @@ export type PublicPageParameters = {
30583063
currencyPosition?: (string) | null;
30593064
datasetId?: (string) | null;
30603065
debounceMs?: (number) | null;
3061-
defaultAiQuestions?: Array<(string)> | null;
3066+
defaultAiQuestions?: Array<DefaultSearchQuery> | null;
30623067
defaultCurrency?: (string) | null;
30633068
defaultImageQuestion?: (string) | null;
30643069
defaultSearchMode?: (string) | null;
3065-
defaultSearchQueries?: Array<(string)> | null;
3070+
defaultSearchQueries?: Array<DefaultSearchQuery> | null;
30663071
defaultSearchQuery?: (string) | null;
30673072
floatingButtonPosition?: (string) | null;
30683073
floatingButtonVersion?: (string) | null;

0 commit comments

Comments
 (0)