mirror of
https://github.com/danswer-ai/danswer.git
synced 2025-10-11 13:46:07 +02:00
Add document set-based filters in UI (#497)
This commit is contained in:
@@ -12,7 +12,7 @@ import { channel } from "diagnostics_channel";
|
|||||||
interface SetCreationPopupProps {
|
interface SetCreationPopupProps {
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
setPopup: (popupSpec: PopupSpec | null) => void;
|
setPopup: (popupSpec: PopupSpec | null) => void;
|
||||||
documentSets: DocumentSet<any, any>[];
|
documentSets: DocumentSet[];
|
||||||
existingSlackBotConfig?: SlackBotConfig;
|
existingSlackBotConfig?: SlackBotConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -29,7 +29,7 @@ const EditRow = ({
|
|||||||
}: {
|
}: {
|
||||||
existingSlackBotConfig: SlackBotConfig;
|
existingSlackBotConfig: SlackBotConfig;
|
||||||
setPopup: (popupSpec: PopupSpec | null) => void;
|
setPopup: (popupSpec: PopupSpec | null) => void;
|
||||||
documentSets: DocumentSet<any, any>[];
|
documentSets: DocumentSet[];
|
||||||
refreshSlackBotConfigs: () => void;
|
refreshSlackBotConfigs: () => void;
|
||||||
}) => {
|
}) => {
|
||||||
const [isEditPopupOpen, setEditPopupOpen] = useState(false);
|
const [isEditPopupOpen, setEditPopupOpen] = useState(false);
|
||||||
@@ -58,7 +58,7 @@ const EditRow = ({
|
|||||||
|
|
||||||
interface DocumentFeedbackTableProps {
|
interface DocumentFeedbackTableProps {
|
||||||
slackBotConfigs: SlackBotConfig[];
|
slackBotConfigs: SlackBotConfig[];
|
||||||
documentSets: DocumentSet<any, any>[];
|
documentSets: DocumentSet[];
|
||||||
refresh: () => void;
|
refresh: () => void;
|
||||||
setPopup: (popupSpec: PopupSpec | null) => void;
|
setPopup: (popupSpec: PopupSpec | null) => void;
|
||||||
}
|
}
|
||||||
|
@@ -10,7 +10,7 @@ interface SetCreationPopupProps {
|
|||||||
ccPairs: ConnectorIndexingStatus<any, any>[];
|
ccPairs: ConnectorIndexingStatus<any, any>[];
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
setPopup: (popupSpec: PopupSpec | null) => void;
|
setPopup: (popupSpec: PopupSpec | null) => void;
|
||||||
existingDocumentSet?: DocumentSet<any, any>;
|
existingDocumentSet?: DocumentSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DocumentSetCreationForm = ({
|
export const DocumentSetCreationForm = ({
|
||||||
|
@@ -4,10 +4,7 @@ import useSWR, { mutate } from "swr";
|
|||||||
|
|
||||||
export const useDocumentSets = () => {
|
export const useDocumentSets = () => {
|
||||||
const url = "/api/manage/document-set";
|
const url = "/api/manage/document-set";
|
||||||
const swrResponse = useSWR<DocumentSet<any, any>[]>(
|
const swrResponse = useSWR<DocumentSet[]>(url, errorHandlingFetcher);
|
||||||
url,
|
|
||||||
errorHandlingFetcher
|
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...swrResponse,
|
...swrResponse,
|
||||||
|
@@ -27,7 +27,7 @@ const EditRow = ({
|
|||||||
setPopup,
|
setPopup,
|
||||||
refreshDocumentSets,
|
refreshDocumentSets,
|
||||||
}: {
|
}: {
|
||||||
documentSet: DocumentSet<any, any>;
|
documentSet: DocumentSet;
|
||||||
ccPairs: ConnectorIndexingStatus<any, any>[];
|
ccPairs: ConnectorIndexingStatus<any, any>[];
|
||||||
setPopup: (popupSpec: PopupSpec | null) => void;
|
setPopup: (popupSpec: PopupSpec | null) => void;
|
||||||
refreshDocumentSets: () => void;
|
refreshDocumentSets: () => void;
|
||||||
@@ -81,7 +81,7 @@ const EditRow = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
interface DocumentFeedbackTableProps {
|
interface DocumentFeedbackTableProps {
|
||||||
documentSets: DocumentSet<any, any>[];
|
documentSets: DocumentSet[];
|
||||||
ccPairs: ConnectorIndexingStatus<any, any>[];
|
ccPairs: ConnectorIndexingStatus<any, any>[];
|
||||||
refresh: () => void;
|
refresh: () => void;
|
||||||
setPopup: (popupSpec: PopupSpec | null) => void;
|
setPopup: (popupSpec: PopupSpec | null) => void;
|
||||||
|
@@ -6,7 +6,7 @@ import { DISABLE_AUTH } from "@/lib/constants";
|
|||||||
import { HealthCheckBanner } from "@/components/health/healthcheck";
|
import { HealthCheckBanner } from "@/components/health/healthcheck";
|
||||||
import { ApiKeyModal } from "@/components/openai/ApiKeyModal";
|
import { ApiKeyModal } from "@/components/openai/ApiKeyModal";
|
||||||
import { buildUrl } from "@/lib/utilsSS";
|
import { buildUrl } from "@/lib/utilsSS";
|
||||||
import { Connector, User } from "@/lib/types";
|
import { Connector, DocumentSet, User } from "@/lib/types";
|
||||||
import { cookies } from "next/headers";
|
import { cookies } from "next/headers";
|
||||||
import { SearchType } from "@/lib/search/interfaces";
|
import { SearchType } from "@/lib/search/interfaces";
|
||||||
|
|
||||||
@@ -19,6 +19,12 @@ export default async function Home() {
|
|||||||
cookie: processCookies(cookies()),
|
cookie: processCookies(cookies()),
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
fetch(buildUrl("/manage/document-set"), {
|
||||||
|
next: { revalidate: 0 },
|
||||||
|
headers: {
|
||||||
|
cookie: processCookies(cookies()),
|
||||||
|
},
|
||||||
|
}),
|
||||||
];
|
];
|
||||||
|
|
||||||
// catch cases where the backend is completely unreachable here
|
// catch cases where the backend is completely unreachable here
|
||||||
@@ -32,6 +38,7 @@ export default async function Home() {
|
|||||||
}
|
}
|
||||||
const user = results[0] as User | null;
|
const user = results[0] as User | null;
|
||||||
const connectorsResponse = results[1] as Response | null;
|
const connectorsResponse = results[1] as Response | null;
|
||||||
|
const documentSetsResponse = results[2] as Response | null;
|
||||||
|
|
||||||
if (!DISABLE_AUTH && !user) {
|
if (!DISABLE_AUTH && !user) {
|
||||||
return redirect("/auth/login");
|
return redirect("/auth/login");
|
||||||
@@ -44,6 +51,15 @@ export default async function Home() {
|
|||||||
console.log(`Failed to fetch connectors - ${connectorsResponse?.status}`);
|
console.log(`Failed to fetch connectors - ${connectorsResponse?.status}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let documentSets: DocumentSet[] = [];
|
||||||
|
if (documentSetsResponse?.ok) {
|
||||||
|
documentSets = await documentSetsResponse.json();
|
||||||
|
} else {
|
||||||
|
console.log(
|
||||||
|
`Failed to fetch document sets - ${documentSetsResponse?.status}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// needs to be done in a non-client side component due to nextjs
|
// needs to be done in a non-client side component due to nextjs
|
||||||
const storedSearchType = cookies().get("searchType")?.value as
|
const storedSearchType = cookies().get("searchType")?.value as
|
||||||
| string
|
| string
|
||||||
@@ -65,6 +81,7 @@ export default async function Home() {
|
|||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<SearchSection
|
<SearchSection
|
||||||
connectors={connectors}
|
connectors={connectors}
|
||||||
|
documentSets={documentSets}
|
||||||
defaultSearchType={searchTypeDefault}
|
defaultSearchType={searchTypeDefault}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
35
web/src/components/HoverPopup.tsx
Normal file
35
web/src/components/HoverPopup.tsx
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
|
interface HoverPopupProps {
|
||||||
|
mainContent: string | JSX.Element;
|
||||||
|
popupContent: string | JSX.Element;
|
||||||
|
classNameModifications?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const HoverPopup = ({
|
||||||
|
mainContent,
|
||||||
|
popupContent,
|
||||||
|
classNameModifications,
|
||||||
|
}: HoverPopupProps) => {
|
||||||
|
const [hovered, setHovered] = useState(false);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className="relative flex"
|
||||||
|
onMouseEnter={() => setHovered(true)}
|
||||||
|
onMouseLeave={() => setHovered(false)}
|
||||||
|
>
|
||||||
|
{hovered && (
|
||||||
|
<div
|
||||||
|
className={
|
||||||
|
`absolute top-0 left-0 mt-8 bg-gray-700 px-3 py-2 rounded shadow-lg z-30 ` +
|
||||||
|
classNameModifications || ""
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{popupContent}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{mainContent}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
@@ -4,7 +4,6 @@ import {
|
|||||||
Notebook,
|
Notebook,
|
||||||
Key,
|
Key,
|
||||||
Trash,
|
Trash,
|
||||||
Info,
|
|
||||||
XSquare,
|
XSquare,
|
||||||
LinkBreak,
|
LinkBreak,
|
||||||
Link,
|
Link,
|
||||||
@@ -33,6 +32,7 @@ import {
|
|||||||
FiCopy,
|
FiCopy,
|
||||||
FiBookmark,
|
FiBookmark,
|
||||||
FiCpu,
|
FiCpu,
|
||||||
|
FiInfo,
|
||||||
} from "react-icons/fi";
|
} from "react-icons/fi";
|
||||||
import { SiBookstack } from "react-icons/si";
|
import { SiBookstack } from "react-icons/si";
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
@@ -47,7 +47,7 @@ interface IconProps {
|
|||||||
className?: string;
|
className?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultTailwindCSS = "my-auto flex flex-shrink-0 text-blue-400";
|
export const defaultTailwindCSS = "my-auto flex flex-shrink-0 text-blue-400";
|
||||||
|
|
||||||
export const PlugIcon = ({
|
export const PlugIcon = ({
|
||||||
size = 16,
|
size = 16,
|
||||||
@@ -123,7 +123,7 @@ export const InfoIcon = ({
|
|||||||
size = 16,
|
size = 16,
|
||||||
className = defaultTailwindCSS,
|
className = defaultTailwindCSS,
|
||||||
}: IconProps) => {
|
}: IconProps) => {
|
||||||
return <Info size={size} className={className} />;
|
return <FiInfo size={size} className={className} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const QuestionIcon = ({
|
export const QuestionIcon = ({
|
||||||
|
@@ -1,8 +1,16 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { getSourceIcon } from "../source";
|
import { getSourceIcon } from "../source";
|
||||||
import { Funnel } from "@phosphor-icons/react";
|
import { Funnel } from "@phosphor-icons/react";
|
||||||
import { ValidSources } from "@/lib/types";
|
import { DocumentSet, ValidSources } from "@/lib/types";
|
||||||
import { Source } from "@/lib/search/interfaces";
|
import { Source } from "@/lib/search/interfaces";
|
||||||
|
import {
|
||||||
|
BookmarkIcon,
|
||||||
|
InfoIcon,
|
||||||
|
NotebookIcon,
|
||||||
|
defaultTailwindCSS,
|
||||||
|
} from "../icons/icons";
|
||||||
|
import { HoverPopup } from "../HoverPopup";
|
||||||
|
import { FiFilter } from "react-icons/fi";
|
||||||
|
|
||||||
const sources: Source[] = [
|
const sources: Source[] = [
|
||||||
{ displayName: "Google Drive", internalName: "google_drive" },
|
{ displayName: "Google Drive", internalName: "google_drive" },
|
||||||
@@ -24,12 +32,18 @@ const sources: Source[] = [
|
|||||||
interface SourceSelectorProps {
|
interface SourceSelectorProps {
|
||||||
selectedSources: Source[];
|
selectedSources: Source[];
|
||||||
setSelectedSources: React.Dispatch<React.SetStateAction<Source[]>>;
|
setSelectedSources: React.Dispatch<React.SetStateAction<Source[]>>;
|
||||||
|
selectedDocumentSets: string[];
|
||||||
|
setSelectedDocumentSets: React.Dispatch<React.SetStateAction<string[]>>;
|
||||||
|
availableDocumentSets: DocumentSet[];
|
||||||
existingSources: ValidSources[];
|
existingSources: ValidSources[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function SourceSelector({
|
export function SourceSelector({
|
||||||
selectedSources,
|
selectedSources,
|
||||||
setSelectedSources,
|
setSelectedSources,
|
||||||
|
selectedDocumentSets,
|
||||||
|
setSelectedDocumentSets,
|
||||||
|
availableDocumentSets,
|
||||||
existingSources,
|
existingSources,
|
||||||
}: SourceSelectorProps) {
|
}: SourceSelectorProps) {
|
||||||
const handleSelect = (source: Source) => {
|
const handleSelect = (source: Source) => {
|
||||||
@@ -42,13 +56,27 @@ export function SourceSelector({
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleDocumentSetSelect = (documentSetName: string) => {
|
||||||
|
setSelectedDocumentSets((prev: string[]) => {
|
||||||
|
if (prev.includes(documentSetName)) {
|
||||||
|
return prev.filter((s) => s !== documentSetName);
|
||||||
|
} else {
|
||||||
|
return [...prev, documentSetName];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="bg-gray-900">
|
<div>
|
||||||
<div className="flex mb-2 pb-1 pl-2 border-b border-gray-800 mx-2">
|
<div className="flex mb-2 pb-1 border-b border-gray-800">
|
||||||
<h2 className="font-bold my-auto">Filters</h2>
|
<h2 className="font-bold my-auto">Filters</h2>
|
||||||
<Funnel className="my-auto ml-2" size="20" />
|
<FiFilter className="my-auto ml-2" size="18" />
|
||||||
</div>
|
</div>
|
||||||
<div className="px-2">
|
|
||||||
|
{existingSources.length > 0 && (
|
||||||
|
<>
|
||||||
|
<div className="font-medium text-sm flex">Sources</div>
|
||||||
|
<div className="px-1">
|
||||||
{sources
|
{sources
|
||||||
.filter((source) => existingSources.includes(source.internalName))
|
.filter((source) => existingSources.includes(source.internalName))
|
||||||
.map((source) => (
|
.map((source) => (
|
||||||
@@ -70,6 +98,55 @@ export function SourceSelector({
|
|||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{availableDocumentSets.length > 0 && (
|
||||||
|
<>
|
||||||
|
<div className="mt-4">
|
||||||
|
<div className="font-medium text-sm flex">Knowledge Sets</div>
|
||||||
|
</div>
|
||||||
|
<div className="px-1">
|
||||||
|
{availableDocumentSets.map((documentSet) => (
|
||||||
|
<div key={documentSet.name} className="my-1.5 flex">
|
||||||
|
<div
|
||||||
|
key={documentSet.name}
|
||||||
|
className={
|
||||||
|
"flex cursor-pointer w-full items-center text-white " +
|
||||||
|
"py-1.5 rounded-lg px-2 " +
|
||||||
|
(selectedDocumentSets.includes(documentSet.name)
|
||||||
|
? "bg-gray-700"
|
||||||
|
: "hover:bg-gray-800")
|
||||||
|
}
|
||||||
|
onClick={() => handleDocumentSetSelect(documentSet.name)}
|
||||||
|
>
|
||||||
|
<HoverPopup
|
||||||
|
mainContent={
|
||||||
|
<div className="flex my-auto mr-2">
|
||||||
|
<InfoIcon className={defaultTailwindCSS} />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
popupContent={
|
||||||
|
<div className="text-sm w-64">
|
||||||
|
<div className="flex font-medium text-gray-200">
|
||||||
|
Description
|
||||||
|
</div>
|
||||||
|
<div className="mt-1 text-gray-300">
|
||||||
|
{documentSet.description}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
classNameModifications="-ml-2"
|
||||||
|
/>
|
||||||
|
<span className="text-sm text-gray-200">
|
||||||
|
{documentSet.name}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@@ -4,7 +4,7 @@ import { useRef, useState } from "react";
|
|||||||
import { SearchBar } from "./SearchBar";
|
import { SearchBar } from "./SearchBar";
|
||||||
import { SearchResultsDisplay } from "./SearchResultsDisplay";
|
import { SearchResultsDisplay } from "./SearchResultsDisplay";
|
||||||
import { SourceSelector } from "./Filters";
|
import { SourceSelector } from "./Filters";
|
||||||
import { Connector } from "@/lib/types";
|
import { Connector, DocumentSet } from "@/lib/types";
|
||||||
import { SearchTypeSelector } from "./SearchTypeSelector";
|
import { SearchTypeSelector } from "./SearchTypeSelector";
|
||||||
import {
|
import {
|
||||||
DanswerDocument,
|
DanswerDocument,
|
||||||
@@ -38,13 +38,16 @@ const VALID_QUESTION_RESPONSE_DEFAULT: ValidQuestionResponse = {
|
|||||||
|
|
||||||
interface SearchSectionProps {
|
interface SearchSectionProps {
|
||||||
connectors: Connector<any>[];
|
connectors: Connector<any>[];
|
||||||
|
documentSets: DocumentSet[];
|
||||||
defaultSearchType: SearchType;
|
defaultSearchType: SearchType;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const SearchSection: React.FC<SearchSectionProps> = ({
|
export const SearchSection: React.FC<SearchSectionProps> = ({
|
||||||
connectors,
|
connectors,
|
||||||
|
documentSets,
|
||||||
defaultSearchType,
|
defaultSearchType,
|
||||||
}) => {
|
}) => {
|
||||||
|
console.log(documentSets);
|
||||||
// Search Bar
|
// Search Bar
|
||||||
const [query, setQuery] = useState<string>("");
|
const [query, setQuery] = useState<string>("");
|
||||||
|
|
||||||
@@ -59,6 +62,9 @@ export const SearchSection: React.FC<SearchSectionProps> = ({
|
|||||||
|
|
||||||
// Filters
|
// Filters
|
||||||
const [sources, setSources] = useState<Source[]>([]);
|
const [sources, setSources] = useState<Source[]>([]);
|
||||||
|
const [selectedDocumentSets, setSelectedDocumentSets] = useState<string[]>(
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
|
||||||
// Search Type
|
// Search Type
|
||||||
const [selectedSearchType, setSelectedSearchType] =
|
const [selectedSearchType, setSelectedSearchType] =
|
||||||
@@ -135,6 +141,7 @@ export const SearchSection: React.FC<SearchSectionProps> = ({
|
|||||||
const searchFnArgs = {
|
const searchFnArgs = {
|
||||||
query,
|
query,
|
||||||
sources,
|
sources,
|
||||||
|
documentSets: selectedDocumentSets,
|
||||||
updateCurrentAnswer: cancellable({
|
updateCurrentAnswer: cancellable({
|
||||||
cancellationToken: lastSearchCancellationToken.current,
|
cancellationToken: lastSearchCancellationToken.current,
|
||||||
fn: updateCurrentAnswer,
|
fn: updateCurrentAnswer,
|
||||||
@@ -183,10 +190,13 @@ export const SearchSection: React.FC<SearchSectionProps> = ({
|
|||||||
return (
|
return (
|
||||||
<div className="relative max-w-[2000px] xl:max-w-[1400px] mx-auto">
|
<div className="relative max-w-[2000px] xl:max-w-[1400px] mx-auto">
|
||||||
<div className="absolute left-0 hidden 2xl:block w-64">
|
<div className="absolute left-0 hidden 2xl:block w-64">
|
||||||
{connectors.length > 0 && (
|
{(connectors.length > 0 || documentSets.length > 0) && (
|
||||||
<SourceSelector
|
<SourceSelector
|
||||||
selectedSources={sources}
|
selectedSources={sources}
|
||||||
setSelectedSources={setSources}
|
setSelectedSources={setSources}
|
||||||
|
selectedDocumentSets={selectedDocumentSets}
|
||||||
|
setSelectedDocumentSets={setSelectedDocumentSets}
|
||||||
|
availableDocumentSets={documentSets}
|
||||||
existingSources={connectors.map((connector) => connector.source)}
|
existingSources={connectors.map((connector) => connector.source)}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
@@ -59,6 +59,7 @@ export interface SearchDefaultOverrides {
|
|||||||
export interface SearchRequestArgs {
|
export interface SearchRequestArgs {
|
||||||
query: string;
|
query: string;
|
||||||
sources: Source[];
|
sources: Source[];
|
||||||
|
documentSets: string[];
|
||||||
updateCurrentAnswer: (val: string) => void;
|
updateCurrentAnswer: (val: string) => void;
|
||||||
updateQuotes: (quotes: Quote[]) => void;
|
updateQuotes: (quotes: Quote[]) => void;
|
||||||
updateDocs: (documents: DanswerDocument[]) => void;
|
updateDocs: (documents: DanswerDocument[]) => void;
|
||||||
|
@@ -5,10 +5,12 @@ import {
|
|||||||
SearchRequestArgs,
|
SearchRequestArgs,
|
||||||
SearchType,
|
SearchType,
|
||||||
} from "./interfaces";
|
} from "./interfaces";
|
||||||
|
import { buildFilters } from "./utils";
|
||||||
|
|
||||||
export const searchRequest = async ({
|
export const searchRequest = async ({
|
||||||
query,
|
query,
|
||||||
sources,
|
sources,
|
||||||
|
documentSets,
|
||||||
updateCurrentAnswer,
|
updateCurrentAnswer,
|
||||||
updateQuotes,
|
updateQuotes,
|
||||||
updateDocs,
|
updateDocs,
|
||||||
@@ -27,19 +29,16 @@ export const searchRequest = async ({
|
|||||||
let quotes: Quote[] | null = null;
|
let quotes: Quote[] | null = null;
|
||||||
let relevantDocuments: DanswerDocument[] | null = null;
|
let relevantDocuments: DanswerDocument[] | null = null;
|
||||||
try {
|
try {
|
||||||
|
const filters = buildFilters(sources, documentSets);
|
||||||
const response = await fetch("/api/direct-qa", {
|
const response = await fetch("/api/direct-qa", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
query,
|
query,
|
||||||
collection: "danswer_index",
|
collection: "danswer_index",
|
||||||
use_keyword: useKeyword,
|
use_keyword: useKeyword,
|
||||||
...(sources.length > 0
|
...(filters.length > 0
|
||||||
? {
|
? {
|
||||||
filters: [
|
filters,
|
||||||
{
|
|
||||||
source_type: sources.map((source) => source.internalName),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
}
|
||||||
: {}),
|
: {}),
|
||||||
offset: offset,
|
offset: offset,
|
||||||
|
@@ -4,6 +4,7 @@ import {
|
|||||||
SearchRequestArgs,
|
SearchRequestArgs,
|
||||||
SearchType,
|
SearchType,
|
||||||
} from "./interfaces";
|
} from "./interfaces";
|
||||||
|
import { buildFilters } from "./utils";
|
||||||
|
|
||||||
const processSingleChunk = (
|
const processSingleChunk = (
|
||||||
chunk: string,
|
chunk: string,
|
||||||
@@ -54,6 +55,7 @@ const processRawChunkString = (
|
|||||||
export const searchRequestStreamed = async ({
|
export const searchRequestStreamed = async ({
|
||||||
query,
|
query,
|
||||||
sources,
|
sources,
|
||||||
|
documentSets,
|
||||||
updateCurrentAnswer,
|
updateCurrentAnswer,
|
||||||
updateQuotes,
|
updateQuotes,
|
||||||
updateDocs,
|
updateDocs,
|
||||||
@@ -73,19 +75,16 @@ export const searchRequestStreamed = async ({
|
|||||||
let quotes: Quote[] | null = null;
|
let quotes: Quote[] | null = null;
|
||||||
let relevantDocuments: DanswerDocument[] | null = null;
|
let relevantDocuments: DanswerDocument[] | null = null;
|
||||||
try {
|
try {
|
||||||
|
const filters = buildFilters(sources, documentSets);
|
||||||
const response = await fetch("/api/stream-direct-qa", {
|
const response = await fetch("/api/stream-direct-qa", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
query,
|
query,
|
||||||
collection: "danswer_index",
|
collection: "danswer_index",
|
||||||
use_keyword: useKeyword,
|
use_keyword: useKeyword,
|
||||||
...(sources.length > 0
|
...(filters.length > 0
|
||||||
? {
|
? {
|
||||||
filters: [
|
filters,
|
||||||
{
|
|
||||||
source_type: sources.map((source) => source.internalName),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
}
|
||||||
: {}),
|
: {}),
|
||||||
offset: offset,
|
offset: offset,
|
||||||
|
16
web/src/lib/search/utils.ts
Normal file
16
web/src/lib/search/utils.ts
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import { Source } from "./interfaces";
|
||||||
|
|
||||||
|
export const buildFilters = (sources: Source[], documentSets: string[]) => {
|
||||||
|
const filters = [];
|
||||||
|
if (sources.length > 0) {
|
||||||
|
filters.push({
|
||||||
|
source_type: sources.map((source) => source.internalName),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (documentSets.length > 0) {
|
||||||
|
filters.push({
|
||||||
|
document_sets: documentSets,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return filters;
|
||||||
|
};
|
@@ -222,11 +222,11 @@ export interface CCPairDescriptor<ConnectorType, CredentialType> {
|
|||||||
credential: Credential<CredentialType>;
|
credential: Credential<CredentialType>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DocumentSet<ConnectorType, CredentialType> {
|
export interface DocumentSet {
|
||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
description: string;
|
description: string;
|
||||||
cc_pair_descriptors: CCPairDescriptor<ConnectorType, CredentialType>[];
|
cc_pair_descriptors: CCPairDescriptor<any, any>[];
|
||||||
is_up_to_date: boolean;
|
is_up_to_date: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -239,7 +239,7 @@ export interface ChannelConfig {
|
|||||||
|
|
||||||
export interface SlackBotConfig {
|
export interface SlackBotConfig {
|
||||||
id: number;
|
id: number;
|
||||||
document_sets: DocumentSet<any, any>[];
|
document_sets: DocumentSet[];
|
||||||
channel_config: ChannelConfig;
|
channel_config: ChannelConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user