|
4 | 4 | defaultPriceToolCallOptions, |
5 | 5 | defaultRelevanceToolCallOptions, |
6 | 6 | defaultSearchToolCallOptions, |
| 7 | + defaultNotFilterToolCallOptions, |
7 | 8 | useModalState, |
8 | 9 | } from "./modal-context"; |
9 | 10 | import { Chunk } from "../types"; |
@@ -91,18 +92,18 @@ const ChatContext = createContext<{ |
91 | 92 | rateChatCompletion: (isPositive: boolean, queryId: string | null) => void; |
92 | 93 | productsWithClicks: ChunkIdWithIndex[]; |
93 | 94 | }>({ |
94 | | - askQuestion: async () => { }, |
| 95 | + askQuestion: async () => {}, |
95 | 96 | currentQuestion: "", |
96 | 97 | isLoading: false, |
97 | 98 | loadingText: "", |
98 | 99 | messages: [], |
99 | | - setCurrentQuestion: () => { }, |
100 | | - cancelGroupChat: () => { }, |
101 | | - clearConversation: () => { }, |
102 | | - chatWithGroup: () => { }, |
103 | | - switchToChatAndAskQuestion: async () => { }, |
104 | | - stopGeneratingMessage: () => { }, |
105 | | - rateChatCompletion: () => { }, |
| 100 | + setCurrentQuestion: () => {}, |
| 101 | + cancelGroupChat: () => {}, |
| 102 | + clearConversation: () => {}, |
| 103 | + chatWithGroup: () => {}, |
| 104 | + switchToChatAndAskQuestion: async () => {}, |
| 105 | + stopGeneratingMessage: () => {}, |
| 106 | + rateChatCompletion: () => {}, |
106 | 107 | productsWithClicks: [], |
107 | 108 | }); |
108 | 109 |
|
@@ -521,6 +522,7 @@ function ChatProvider({ children }: { children: React.ReactNode }) { |
521 | 522 | let useImage = false; |
522 | 523 | let referenceImageUrls: string[] = []; |
523 | 524 | let referenceChunks: Chunk[] = []; |
| 525 | + let notFilter = false; |
524 | 526 |
|
525 | 527 | if (!groupIds || groupIds.length === 0) { |
526 | 528 | chatMessageAbortController.current = new AbortController(); |
@@ -645,6 +647,54 @@ function ChatProvider({ children }: { children: React.ReactNode }) { |
645 | 647 | } |
646 | 648 | }); |
647 | 649 |
|
| 650 | + const notFilterPromise = retryOperation(async () => { |
| 651 | + if (!curGroup && messages.length > 1) { |
| 652 | + return await trieveSDK.getToolCallFunctionParams({ |
| 653 | + user_message_text: `Here's the previous message thread so far: ${messages.map( |
| 654 | + (message) => { |
| 655 | + if ( |
| 656 | + message.type === "system" && |
| 657 | + message.additional?.length && |
| 658 | + props.type === "ecommerce" |
| 659 | + ) { |
| 660 | + const chunks = message.additional |
| 661 | + .map((chunk) => { |
| 662 | + return JSON.stringify({ |
| 663 | + title: chunk.metadata?.title || "", |
| 664 | + description: chunk.chunk_html || "", |
| 665 | + price: chunk.num_value |
| 666 | + ? `${props.defaultCurrency || ""} ${chunk.num_value}` |
| 667 | + : "", |
| 668 | + link: chunk.link || "", |
| 669 | + }); |
| 670 | + }) |
| 671 | + .join("\n\n"); |
| 672 | + return `\n\n${chunks}${message.text}`; |
| 673 | + } else { |
| 674 | + return `\n\n${message.text}`; |
| 675 | + } |
| 676 | + }, |
| 677 | + )} \n\n${props.notFilterToolCallOptions?.userMessageTextPrefix ?? defaultNotFilterToolCallOptions.userMessageTextPrefix}: ${questionProp || currentQuestion}.`, |
| 678 | + image_url: localImageUrl ? localImageUrl : null, |
| 679 | + audio_input: curAudioBase64 ? curAudioBase64 : null, |
| 680 | + tool_function: { |
| 681 | + name: "not_filter", |
| 682 | + description: |
| 683 | + props.notFilterToolCallOptions?.toolDescription ?? |
| 684 | + defaultNotFilterToolCallOptions.toolDescription, |
| 685 | + parameters: [ |
| 686 | + { |
| 687 | + name: "not_filter", |
| 688 | + parameter_type: "boolean", |
| 689 | + description: |
| 690 | + "Whether or not the user is interested in the products previously shown to them. Set this to true if the user is not interested in the products they were shown or want something different.", |
| 691 | + }, |
| 692 | + ], |
| 693 | + }, |
| 694 | + }); |
| 695 | + } |
| 696 | + }); |
| 697 | + |
648 | 698 | const tagFiltersPromise = retryOperation(async () => { |
649 | 699 | if ( |
650 | 700 | (!defaultMatchAnyTags || !defaultMatchAnyTags?.length) && |
@@ -693,11 +743,13 @@ function ChatProvider({ children }: { children: React.ReactNode }) { |
693 | 743 | imageFiltersResp, |
694 | 744 | tagFiltersResp, |
695 | 745 | skipSearchResp, |
| 746 | + notFilterResp, |
696 | 747 | ] = await Promise.all([ |
697 | 748 | priceFiltersPromise, |
698 | 749 | imageFiltersPromise, |
699 | 750 | tagFiltersPromise, |
700 | 751 | skipSearchPromise, |
| 752 | + notFilterPromise, |
701 | 753 | ]); |
702 | 754 |
|
703 | 755 | if (transcribedQuery && curAudioBase64) { |
@@ -725,7 +777,8 @@ function ChatProvider({ children }: { children: React.ReactNode }) { |
725 | 777 | } |
726 | 778 |
|
727 | 779 | useImage = (imageFiltersResp?.parameters && |
728 | | - (imageFiltersResp.parameters as any)["image"] === true && localImageUrl) as boolean; |
| 780 | + (imageFiltersResp.parameters as any)["image"] === true && |
| 781 | + localImageUrl) as boolean; |
729 | 782 |
|
730 | 783 | const match_any_tags = []; |
731 | 784 | if (tagFiltersResp?.parameters) { |
@@ -786,6 +839,15 @@ function ChatProvider({ children }: { children: React.ReactNode }) { |
786 | 839 | } |
787 | 840 | } |
788 | 841 |
|
| 842 | + if (notFilterResp?.parameters) { |
| 843 | + const notFilterParam = (notFilterResp.parameters as any)[ |
| 844 | + "not_filter" |
| 845 | + ]; |
| 846 | + if (typeof notFilterParam === "boolean" && notFilterParam) { |
| 847 | + notFilter = true; |
| 848 | + } |
| 849 | + } |
| 850 | + |
789 | 851 | clearTimeout(toolCallTimeout); |
790 | 852 | } catch (e) { |
791 | 853 | console.error("error getting getToolCallFunctionParams", e); |
@@ -821,6 +883,19 @@ function ChatProvider({ children }: { children: React.ReactNode }) { |
821 | 883 | filters = null; |
822 | 884 | } |
823 | 885 |
|
| 886 | + if (notFilter) { |
| 887 | + if (filters == null) { |
| 888 | + filters = { must_not: [] }; |
| 889 | + } else if (filters.must_not == null) { |
| 890 | + filters.must_not = []; |
| 891 | + } |
| 892 | + |
| 893 | + (filters as ChunkFilter)?.must_not?.push({ |
| 894 | + field: "group_ids", |
| 895 | + match_any: groupIdsInChat, |
| 896 | + }); |
| 897 | + } |
| 898 | + |
824 | 899 | searchAbortController.current = new AbortController(); |
825 | 900 | if (curGroup) { |
826 | 901 | setLoadingText("Reading the product's information..."); |
@@ -883,7 +958,9 @@ function ChatProvider({ children }: { children: React.ReactNode }) { |
883 | 958 | const searchOverGroupsResp = await retryOperation(async () => { |
884 | 959 | return await trieveSDK.searchOverGroups( |
885 | 960 | { |
886 | | - query: questionProp || currentQuestion, |
| 961 | + query: notFilter |
| 962 | + ? `${messages[messages.length - 2]?.text} ${questionProp || currentQuestion}` |
| 963 | + : questionProp || currentQuestion, |
887 | 964 | search_type: "fulltext", |
888 | 965 | filters: filters, |
889 | 966 | page_size: 20, |
@@ -1296,7 +1373,7 @@ function ChatProvider({ children }: { children: React.ReactNode }) { |
1296 | 1373 | } |
1297 | 1374 | if (audioBase64) { |
1298 | 1375 | setAudioBase64(""); |
1299 | | - setTranscribedQuery(""); |
| 1376 | + setTranscribedQuery(""); |
1300 | 1377 | } |
1301 | 1378 | }; |
1302 | 1379 |
|
|
0 commit comments