diff --git a/clients/search-component/README.md b/clients/search-component/README.md index 492b97bd7b..dfc028b1be 100644 --- a/clients/search-component/README.md +++ b/clients/search-component/README.md @@ -94,7 +94,8 @@ declare module "solid-js" { | defaultAiQuestions | string[] | [] | | brandLogoImgSrcUrl | string | null | | brandName | string | null | -| brand Color | string | #CB53EB | +| brandColor | string | #CB53EB | +| brandFontFamily | string | Maven Pro | | problemLink | string (example: "mailto:help@trieve.ai?subject=") | null | | responsive | boolean | false | diff --git a/clients/search-component/example/src/routes/index.lazy.tsx b/clients/search-component/example/src/routes/index.lazy.tsx index 4c01f69f1b..b726417efd 100644 --- a/clients/search-component/example/src/routes/index.lazy.tsx +++ b/clients/search-component/example/src/routes/index.lazy.tsx @@ -14,6 +14,7 @@ export default function Home() { const brandName = import.meta.env.VITE_BRAND_NAME; const brandLogoSrcUrl = import.meta.env.VITE_BRAND_LOGO_SRC_URL; const brandColor = import.meta.env.VITE_ACCENT_COLOR; + const brandFontFamily = import.meta.env.VITE_BRAND_FONT_FAMILY; const problemLink = import.meta.env.VITE_PROBLEM_LINK; const useGroupSearch = import.meta.env.VITE_USE_GROUP_SEARCH == "true"; const defaultSearchQueries: string[] = ( @@ -123,7 +124,7 @@ export default function Home() { { selector: ".random-trigger-location", mode: "chat", - } + }, ]} useGroupSearch={useGroupSearch} defaultAiQuestions={[ @@ -134,6 +135,7 @@ export default function Home() { brandLogoImgSrcUrl={brandLogoSrcUrl} brandName={brandName} brandColor={brandColor} + brandFontFamily={brandFontFamily} allowSwitchingModes={true} responsive={false} searchOptions={{ @@ -158,7 +160,7 @@ export default function Home() { {component > 0 ? (
  • ) : ( diff --git a/clients/search-component/package.json b/clients/search-component/package.json index ba52f6212c..030038f8b5 100644 --- a/clients/search-component/package.json +++ b/clients/search-component/package.json @@ -19,7 +19,7 @@ "import": "./dist/vanilla/index.js" } }, - "version": "0.2.19", + "version": "0.2.22", "license": "MIT", "homepage": "https://github.com/devflowinc/trieve/tree/main/clients/search-component", "scripts": { diff --git a/clients/search-component/src/TrieveModal/Chat/AIInitalMessage.tsx b/clients/search-component/src/TrieveModal/Chat/AIInitalMessage.tsx index cf70770c14..42108d648b 100644 --- a/clients/search-component/src/TrieveModal/Chat/AIInitalMessage.tsx +++ b/clients/search-component/src/TrieveModal/Chat/AIInitalMessage.tsx @@ -46,7 +46,10 @@ export const AIInitialMessage = () => { }} className="brand-name" > - {currentGroup?.name || props.brandName || "Trieve"} + {(currentGroup?.name || props.brandName || "Trieve").replace( + /<[^>]*>/g, + "" + )}

    diff --git a/clients/search-component/src/TrieveModal/Chat/ChatMode.tsx b/clients/search-component/src/TrieveModal/Chat/ChatMode.tsx index 3a6ffc3b22..e5a0496db6 100644 --- a/clients/search-component/src/TrieveModal/Chat/ChatMode.tsx +++ b/clients/search-component/src/TrieveModal/Chat/ChatMode.tsx @@ -80,7 +80,7 @@ export const ChatMode = () => {
    {currentGroup && (
    -
    Chatting with {currentGroup.name}
    +
    Chatting with {currentGroup.name.replace(/<[^>]*>/g, "")}
    ) : null} - {results.length - ? results.map((result, index) => getItemComponent(result, index)) - : null} - {query && !results.length && !loadingResults ? ( + {resultsDisplay} + {query && !resultsLength && !loadingResults ? (

    No results found

    {props.problemLink && ( @@ -236,7 +247,7 @@ export const SearchMode = () => {

    )}
    - ) : query && !results.length && loadingResults ? ( + ) : query && !resultsLength && loadingResults ? (

    Searching...

    ) : null} diff --git a/clients/search-component/src/TrieveModal/index.css b/clients/search-component/src/TrieveModal/index.css index e354ad70dc..bab809a07e 100644 --- a/clients/search-component/src/TrieveModal/index.css +++ b/clients/search-component/src/TrieveModal/index.css @@ -23,12 +23,13 @@ body { } #trieve-search-modal { - @apply animate-contentShow scroll-smooth fixed top-[calc(40%-30vh)] sm:top-[calc(25vh-225px)] left-[50%] max-h-[60vh] w-[90vw] sm:max-w-[800px] -translate-x-[50%] rounded-lg shadow-2xl focus:outline-none font-sans z-[999] overflow-hidden text-base; + @apply animate-contentShow scroll-smooth fixed top-[calc(40%-30vh)] sm:top-[calc(25vh-225px)] left-[50%] max-h-[60vh] w-[90vw] sm:max-w-[800px] -translate-x-[50%] rounded-lg shadow-2xl focus:outline-none z-[999] overflow-hidden text-base; color: var(--tv-zinc-950); background-color: var(--tv-zinc-50); + font-family: var(--tv-prop-brand-font-family); - .group-chat-carousel { + f .group-chat-carousel { @apply pl-2 flex gap-2 w-full overflow-x-auto; } @@ -152,7 +153,7 @@ body { .mode-switch-wrapper.ecommerce.search { @apply top-[2.625rem]; - right: calc(max(calc(50vw - 36rem), 1.25rem) + 0.5rem); + right: calc(max(calc(50vw - 36rem), 1.25rem) + 0.25rem); } .mode-switch-wrapper.ecommerce.chat { @@ -219,7 +220,7 @@ body { } .bottom-row { - @apply flex items-center px-4 2xl:px-0 w-full mx-auto max-w-6xl; + @apply flex items-center 2xl:px-0 w-full mx-auto max-w-6xl; .spacer { @apply flex-1; @@ -253,7 +254,7 @@ body { } .trieve-footer.ecommerce { - @apply py-0.5; + @apply -mx-4; } .commands.ecommerce { @@ -384,7 +385,9 @@ body { h2, h3, h4 { - @apply font-semibold pb-1 sm:pb-2 m-0 font-sans leading-normal pt-0 text-base; + @apply font-semibold pb-1 sm:pb-2 m-0 leading-normal pt-0 text-base; + + font-family: var(--tv-prop-brand-font-family); } a { @@ -399,7 +402,9 @@ body { @apply absolute right-2 flex py-1.5 pr-1.5; kbd { - @apply inline-flex items-center rounded border px-1 font-sans text-xs; + @apply inline-flex items-center rounded border px-1 text-xs; + + font-family: var(--tv-prop-brand-font-family); color: var(--tv-zinc-400); border-color: var(--tv-zinc-200); } @@ -649,9 +654,7 @@ body { .chat-footer-wrapper { .chat-group-disclaimer { - @apply flex items-center justify-between - bg-zinc-200/60 dark:bg-zinc-700 px-3 py-1 text-sm opacity-70 - border border-zinc-300 dark:border-zinc-500 border-b-transparent; + @apply flex items-center justify-between bg-zinc-200/60 dark:bg-zinc-700 px-3 py-1 text-sm opacity-70 mx-2 border border-zinc-300 dark:border-zinc-500 border-b-transparent; } input { @@ -735,6 +738,10 @@ body { mark { @apply bg-inherit; color: var(--tv-prop-brand-color); + + b { + @apply font-semibold; + } } &.group { @@ -1070,7 +1077,9 @@ body { } .open { - @apply inline-flex items-center rounded border px-1 font-sans text-xs py-0.5 gap-1; + @apply inline-flex items-center rounded border px-1 text-xs py-0.5 gap-1; + + font-family: var(--tv-prop-brand-font-family); color: var(--tv-zinc-400); border-color: var(--tv-zinc-200); diff --git a/clients/search-component/src/TrieveModal/index.tsx b/clients/search-component/src/TrieveModal/index.tsx index 79bddb4145..0ce1442603 100644 --- a/clients/search-component/src/TrieveModal/index.tsx +++ b/clients/search-component/src/TrieveModal/index.tsx @@ -26,7 +26,7 @@ const Modal = () => { script.setAttribute("data-auto-replace-svg", ""); document.head.appendChild(script); - }); + }, []); useEffect(() => { document.documentElement.style.setProperty( @@ -45,7 +45,14 @@ const Modal = () => { "var(--tv-zinc-300)" ); } - }, [props.brandColor]); + + document.documentElement.style.setProperty( + "--tv-prop-brand-font-family", + props.brandFontFamily ?? + `Maven Pro, ui-sans-serif, system-ui, sans-serif, + "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"` + ); + }, [props.brandColor, props.brandFontFamily]); return ( <> diff --git a/clients/search-component/src/utils/estimation.ts b/clients/search-component/src/utils/estimation.ts index d1c2b9874e..36ef05f51a 100644 --- a/clients/search-component/src/utils/estimation.ts +++ b/clients/search-component/src/utils/estimation.ts @@ -1,7 +1,7 @@ import { ChunkWithHighlights } from "./types"; export const guessTitleAndDesc = ( - item: ChunkWithHighlights, + item: ChunkWithHighlights ): { title: string; descriptionHtml: string; @@ -19,7 +19,7 @@ export const guessTitleAndDesc = ( const chunkHtmlHeadingsDiv = document.createElement("div"); chunkHtmlHeadingsDiv.innerHTML = item.chunk.chunk_html || ""; const chunkHtmlHeadings = chunkHtmlHeadingsDiv.querySelectorAll( - "h1, h2, h3, h4, h5, h6", + "h1, h2, h3, h4, h5, h6" ); const $firstHeading = chunkHtmlHeadings[0] ?? document.createElement("h1"); const cleanFirstHeading = $firstHeading?.innerHTML; @@ -41,42 +41,32 @@ export const guessTitleAndDesc = ( }; export const findCommonName = (names: string[]) => { - // Return null if array is empty if (!names || names.length === 0) return null; - // Get the first string as reference const firstString = names[0]; let commonPrefix = ""; - // Iterate through each character of the first string for (let i = 0; i < firstString.length; i++) { const currentChar = firstString[i]; - // Check if this character exists in the same position for all names - // Compare case-insensitively but keep original case const allMatch = names.every( - (str) => str[i]?.toLowerCase() === currentChar.toLowerCase(), + (str) => str[i]?.toLowerCase() === currentChar.toLowerCase() ); if (allMatch) { - commonPrefix += firstString[i]; // Use original case from first string + commonPrefix += firstString[i]; } else { break; } } - // Strip non-alphabetic characters from the end commonPrefix = commonPrefix.replace(/[^a-zA-Z]+$/, ""); if (commonPrefix.endsWith(" /X")) { commonPrefix = commonPrefix.slice(0, -3); } - // Strip html - commonPrefix = commonPrefix.replace(/<[^>]*>/g, ""); - - // Return null if no common prefix was found return commonPrefix.length > 0 ? commonPrefix : null; }; diff --git a/clients/search-component/src/utils/hooks/modal-context.tsx b/clients/search-component/src/utils/hooks/modal-context.tsx index 3dd149736d..ea07d04059 100644 --- a/clients/search-component/src/utils/hooks/modal-context.tsx +++ b/clients/search-component/src/utils/hooks/modal-context.tsx @@ -56,6 +56,7 @@ export type ModalProps = { brandName?: string; problemLink?: string; brandColor?: string; + brandFontFamily?: string; openKeyCombination?: { key?: string; label?: string; ctrl?: boolean }[]; tags?: { tag: string; @@ -271,8 +272,6 @@ const ModalProvider = ({ e != "AbortError" && e != "AbortError: signal is aborted without reason" ) { - console.log(e); - console.log(typeof e); console.error(e); } } @@ -312,7 +311,6 @@ const ModalProvider = ({ useEffect(() => { const abortController = new AbortController(); - setLoadingResults(true); const timeout = setTimeout(() => { search(abortController); }, props.debounceMs); diff --git a/clients/search-component/src/utils/hooks/useKeyboardNavigation.ts b/clients/search-component/src/utils/hooks/useKeyboardNavigation.ts index e6ee648500..89fd2aa9e6 100644 --- a/clients/search-component/src/utils/hooks/useKeyboardNavigation.ts +++ b/clients/search-component/src/utils/hooks/useKeyboardNavigation.ts @@ -45,11 +45,9 @@ export const useKeyboardNavigation = () => { const focusedElement = document.activeElement as HTMLElement; const id = focusedElement.id; - console.log("focusedElement", focusedElement); if (id && id.startsWith("trieve-search-item-")) { const index = parseInt(id.split("-")[3]); - console.log("index", index); document.getElementById(`trieve-search-item-${index + 1}`)?.focus(); } diff --git a/clients/search-component/src/utils/types.ts b/clients/search-component/src/utils/types.ts index 0d61f02af7..6ef9013d33 100644 --- a/clients/search-component/src/utils/types.ts +++ b/clients/search-component/src/utils/types.ts @@ -30,7 +30,7 @@ export type GroupSearchResults = { requestID: string; }; -export function isChunksWithHighlights( +export function isChunkWithHighlights( result: ChunkWithHighlights | GroupChunk[], ): result is ChunkWithHighlights { return !Array.isArray(result); diff --git a/clients/ts-sdk/openapi.json b/clients/ts-sdk/openapi.json index e0417e8c8f..bbc481bb88 100644 --- a/clients/ts-sdk/openapi.json +++ b/clients/ts-sdk/openapi.json @@ -10344,12 +10344,26 @@ "event_type" ], "properties": { + "detected_hallucinations": { + "type": "array", + "items": { + "type": "string" + }, + "description": "The detected hallucinations of the RAG event", + "nullable": true + }, "event_type": { "type": "string", "enum": [ "rag" ] }, + "hallucination_score": { + "type": "number", + "format": "double", + "description": "The hallucination score of the RAG event", + "nullable": true + }, "llm_response": { "type": "string", "description": "The response from the LLM", @@ -12228,6 +12242,10 @@ "type": "string", "nullable": true }, + "brandFontFamily": { + "type": "string", + "nullable": true + }, "brandLogoImgSrcUrl": { "type": "string", "nullable": true @@ -12875,6 +12893,8 @@ "results", "dataset_id", "llm_response", + "hallucination_score", + "detected_hallucinations", "created_at", "user_id" ], @@ -12886,6 +12906,16 @@ "type": "string", "format": "uuid" }, + "detected_hallucinations": { + "type": "array", + "items": { + "type": "string" + } + }, + "hallucination_score": { + "type": "number", + "format": "double" + }, "id": { "type": "string", "format": "uuid" diff --git a/clients/ts-sdk/src/types.gen.ts b/clients/ts-sdk/src/types.gen.ts index 14db79524f..c56de691b9 100644 --- a/clients/ts-sdk/src/types.gen.ts +++ b/clients/ts-sdk/src/types.gen.ts @@ -1369,7 +1369,15 @@ export type EventTypes = { */ user_id?: (string) | null; } | { + /** + * The detected hallucinations of the RAG event + */ + detected_hallucinations?: Array<(string)> | null; event_type: 'rag'; + /** + * The hallucination score of the RAG event + */ + hallucination_score?: (number) | null; /** * The response from the LLM */ @@ -2019,6 +2027,7 @@ export type PublicPageParameters = { apiKey?: (string) | null; baseUrl?: (string) | null; brandColor?: (string) | null; + brandFontFamily?: (string) | null; brandLogoImgSrcUrl?: (string) | null; brandName?: (string) | null; chat?: (boolean) | null; @@ -2181,6 +2190,8 @@ export type RAGUsageResponse = { export type RagQueryEvent = { created_at: string; dataset_id: string; + detected_hallucinations: Array<(string)>; + hallucination_score: number; id: string; llm_response: string; query_rating?: ((SearchQueryRating) | null); diff --git a/frontends/dashboard/src/pages/dataset/PublicPageSettings.tsx b/frontends/dashboard/src/pages/dataset/PublicPageSettings.tsx index ea3b0aaafb..3ad9a5e593 100644 --- a/frontends/dashboard/src/pages/dataset/PublicPageSettings.tsx +++ b/frontends/dashboard/src/pages/dataset/PublicPageSettings.tsx @@ -208,6 +208,29 @@ const PublicPageControls = () => { />
    +
    +
    + + + } + /> +
    +
    + { + setExtraParams("brandFontFamily", e.currentTarget.value); + }} + class="block w-full grow rounded border border-neutral-300 px-3 py-1.5 shadow-sm placeholder:text-neutral-400 focus:outline-magenta-500 sm:text-sm sm:leading-6" + /> +
    +
    @@ -256,27 +279,6 @@ const PublicPageControls = () => {
    -
    -
    - - } - /> -
    -
    - { - setExtraParams("brandLogoImgSrcUrl", e.currentTarget.value); - }} - class="block w-full grow rounded border border-neutral-300 px-3 py-1.5 shadow-sm placeholder:text-neutral-400 focus:outline-magenta-500 sm:text-sm sm:leading-6" - /> -
    -
    { + placeholder="#FFFFFF" + value={extraParams.heroPattern?.foregroundColor || "#FFFFFF"} + onInput={(e) => { setExtraParams( "heroPattern", "foregroundColor", e.currentTarget.value, ); }} - value={extraParams.heroPattern?.foregroundColor || "#ffffff"} - /> -
    -
    - - { - setExtraParams( - "heroPattern", - "foregroundOpacity", - parseInt(e.currentTarget.value) / 100, - ); - }} - value={ - (extraParams.heroPattern?.foregroundOpacity || 0.5) * 100 - } + class="block w-full rounded border border-neutral-300 px-3 py-1.5 shadow-sm placeholder:text-neutral-400 focus:outline-magenta-500 sm:text-sm sm:leading-6" />
    @@ -632,7 +615,8 @@ const PublicPageControls = () => { Background Color { setExtraParams( "heroPattern", @@ -640,10 +624,30 @@ const PublicPageControls = () => { e.currentTarget.value, ); }} - value={extraParams.heroPattern?.backgroundColor || "#ffffff"} + class="block w-full rounded border border-neutral-300 px-3 py-1.5 shadow-sm placeholder:text-neutral-400 focus:outline-magenta-500 sm:text-sm sm:leading-6" />
    +
    + + { + setExtraParams( + "heroPattern", + "foregroundOpacity", + parseInt(e.currentTarget.value) / 100, + ); + }} + value={ + (extraParams.heroPattern?.foregroundOpacity || 0.5) * 100 + } + /> +
    diff --git a/server/src/data/models.rs b/server/src/data/models.rs index a2ed2f8a52..1b2a9cd1dc 100644 --- a/server/src/data/models.rs +++ b/server/src/data/models.rs @@ -3180,6 +3180,9 @@ impl DatasetConfigurationDTO { creator_linked_in_url: page_parameters_self .creator_linked_in_url .or(page_parameters_curr.creator_linked_in_url), + brand_font_family: page_parameters_self + .brand_font_family + .or(page_parameters_curr.brand_font_family), }), }, DISABLE_ANALYTICS: self diff --git a/server/src/handlers/page_handler.rs b/server/src/handlers/page_handler.rs index e9e547708d..0a2b5548f4 100644 --- a/server/src/handlers/page_handler.rs +++ b/server/src/handlers/page_handler.rs @@ -214,6 +214,8 @@ pub struct PublicPageParameters { pub creator_name: Option, #[serde(skip_serializing_if = "Option::is_none")] pub creator_linked_in_url: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub brand_font_family: Option, } #[utoipa::path( diff --git a/server/src/public/navbar.html b/server/src/public/navbar.html index cae83a454a..3c8ba2ac5c 100644 --- a/server/src/public/navbar.html +++ b/server/src/public/navbar.html @@ -1,6 +1,6 @@