@botonic/react
Version:
Build Chatbots using React
125 lines • 5.4 kB
JavaScript
import { __awaiter } from "tslib";
import { jsx as _jsx } from "react/jsx-runtime";
import { KnowledgebaseFailReason } from '@botonic/core';
import { useContext, useEffect, useMemo, useState } from 'react';
import { WebchatContext } from '../../../webchat/context';
import { FilePdfSvg, FileWordSvg, LinkSvg } from '../icons';
export const useKnowledgeBaseInfo = ({ sourceIds, chunkIds, messageId, existingChunksWithSources, failReason, }) => {
const { updateMessage, webchatState, previewUtils } = useContext(WebchatContext);
// Check if we have cached data
const hasCachedData = existingChunksWithSources !== undefined;
// Initialize state from existing chunks with sources if available
const initialChunksWithSources = existingChunksWithSources || [];
const initialSources = initialChunksWithSources.map(item => item.source);
const initialChunks = initialChunksWithSources.flatMap(item => item.chunks);
const [chunksWithSources, setChunksWithSources] = useState(initialChunksWithSources);
const [sources, setSources] = useState(initialSources);
const [chunks, setChunks] = useState(initialChunks);
const [isLoading, setIsLoading] = useState(false);
const updateMessageWithKnowledgeData = (fetchedChunksWithSources) => {
if (!messageId) {
return;
}
const message = webchatState.messagesJSON.find(m => m.id === messageId);
if (!message) {
return;
}
// Parse the existing data if it's a string (shouldn't be, but handle it)
const parsedData = typeof message.data === 'string' ? JSON.parse(message.data) : message.data;
// Update with fetched chunks with sources and preserve original IDs
const updatedData = Object.assign(Object.assign({}, parsedData), {
// eslint-disable-next-line @typescript-eslint/naming-convention
knowledgebase_sources_ids: sourceIds,
// eslint-disable-next-line @typescript-eslint/naming-convention
knowledgebase_chunks_ids: chunkIds,
// eslint-disable-next-line @typescript-eslint/naming-convention
knowledge_base_chunks_with_sources: fetchedChunksWithSources });
// Update the message in webchat state - keep data as object
updateMessage(Object.assign(Object.assign({}, message), { data: updatedData }));
};
const fetchChunksWithSources = () => __awaiter(void 0, void 0, void 0, function* () {
if (chunkIds.length === 0 || !previewUtils)
return [];
setIsLoading(true);
try {
const fetchedChunksWithSources = yield previewUtils.getChunkIdsGroupedBySource(chunkIds);
return fetchedChunksWithSources;
}
catch (error) {
console.error('Error fetching chunks with sources:', error);
return [];
}
finally {
setIsLoading(false);
}
});
const getIconForSourceType = (source) => {
switch (source.type) {
case 'file':
if (source.activeExtractionJob.fileName.endsWith('.pdf')) {
return _jsx(FilePdfSvg, {});
}
else {
return _jsx(FileWordSvg, {});
}
case 'url':
return _jsx(LinkSvg, {});
default:
return null;
}
};
const { hasKnowledge, isFaithful } = useMemo(() => {
const typedFailReason = failReason;
if (typedFailReason === KnowledgebaseFailReason.NoKnowledge) {
return {
hasKnowledge: false,
isFaithful: false,
};
}
if (typedFailReason === KnowledgebaseFailReason.Hallucination) {
return {
hasKnowledge: true,
isFaithful: false,
};
}
return {
hasKnowledge: true,
isFaithful: true,
};
}, [failReason]);
useEffect(() => {
// If we already have cached data (even if empty), don't fetch again
if (hasCachedData) {
return;
}
// Only fetch if previewUtils is available
if (!previewUtils) {
return;
}
// Otherwise, fetch the data
const fetchData = () => __awaiter(void 0, void 0, void 0, function* () {
const fetchedChunksWithSources = yield fetchChunksWithSources();
// Extract sources and chunks from chunks with sources
const fetchedSources = fetchedChunksWithSources.map(item => item.source);
const fetchedChunks = fetchedChunksWithSources.flatMap(item => item.chunks);
setChunksWithSources(fetchedChunksWithSources);
setSources(fetchedSources);
setChunks(fetchedChunks);
// Always update the message with the fetched data (even if empty arrays)
// This marks the data as fetched so we don't fetch again
updateMessageWithKnowledgeData(fetchedChunksWithSources);
});
fetchData();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
return {
sources,
chunks,
chunksWithSources,
isLoading,
getIconForSourceType,
hasKnowledge,
isFaithful,
};
};
//# sourceMappingURL=use-knowledge-base-info.js.map