feat: Implement LLM configuration validation in create and update routes

- Added `validate_llm_config` function to `llm_service.py` for validating LLM configurations via test API calls.
- Integrated validation in `create_llm_config` and `update_llm_config` routes in `llm_config_routes.py`, raising HTTP exceptions for invalid configurations.
- Enhanced error handling to provide detailed feedback on configuration issues.
This commit is contained in:
DESKTOP-RTLN3BA\$punk 2025-11-05 12:15:05 -08:00
parent 666dba7150
commit 9466bf595c
9 changed files with 235 additions and 52 deletions

View file

@ -49,10 +49,10 @@ export default function DashboardLayout({
title: "Upload Documents",
url: `/dashboard/${search_space_id}/documents/upload`,
},
{
title: "Add Webpages",
url: `/dashboard/${search_space_id}/documents/webpage`,
},
// {
// title: "Add Webpages",
// url: `/dashboard/${search_space_id}/documents/webpage`,
// },
{
title: "Add Youtube Videos",
url: `/dashboard/${search_space_id}/documents/youtube`,

View file

@ -5,7 +5,9 @@ import { useParams, useRouter } from "next/navigation";
import { useEffect, useMemo } from "react";
import ChatInterface from "@/components/chat/ChatInterface";
import { useChatAPI, useChatState } from "@/hooks/use-chat";
import { useDocumentTypes } from "@/hooks/use-document-types";
import type { Document } from "@/hooks/use-documents";
import { useSearchSourceConnectors } from "@/hooks/use-search-source-connectors";
export default function ResearcherPage() {
const { search_space_id, chat_id } = useParams();
@ -35,6 +37,19 @@ export default function ResearcherPage() {
search_space_id: search_space_id as string,
});
// Fetch all available sources (document types + live search connectors)
const { documentTypes } = useDocumentTypes(Number(search_space_id));
const { connectors: searchConnectors } = useSearchSourceConnectors(
false,
Number(search_space_id)
);
// Filter for non-indexable connectors (live search)
const liveSearchConnectors = useMemo(
() => searchConnectors.filter((connector) => !connector.is_indexable),
[searchConnectors]
);
// Memoize document IDs to prevent infinite re-renders
const documentIds = useMemo(() => {
return selectedDocuments.map((doc) => doc.id);
@ -135,6 +150,27 @@ export default function ResearcherPage() {
}
}, [chatIdParam, search_space_id, setSelectedDocuments, setSelectedConnectors, setSearchMode]);
// Set all sources as default for new chats
useEffect(() => {
if (isNewChat && selectedConnectors.length === 0 && documentTypes.length > 0) {
// Combine all document types and live search connectors
const allSourceTypes = [
...documentTypes.map((dt) => dt.type),
...liveSearchConnectors.map((c) => c.connector_type),
];
if (allSourceTypes.length > 0) {
setSelectedConnectors(allSourceTypes);
}
}
}, [
isNewChat,
documentTypes,
liveSearchConnectors,
selectedConnectors.length,
setSelectedConnectors,
]);
const loadChatData = async (chatId: string) => {
try {
const chatData = await fetchChatDetails(chatId);

View file

@ -115,18 +115,19 @@ const ConnectorSelector = React.memo(
const { search_space_id } = useParams();
const [isOpen, setIsOpen] = useState(false);
// Fetch immediately (not lazy) so the button can show the correct count
const { documentTypes, isLoading, isLoaded, fetchDocumentTypes } = useDocumentTypes(
Number(search_space_id),
true
false
);
// Fetch live search connectors (non-indexable)
// Fetch live search connectors immediately (non-indexable)
const {
connectors: searchConnectors,
isLoading: connectorsLoading,
isLoaded: connectorsLoaded,
fetchConnectors,
} = useSearchSourceConnectors(true, Number(search_space_id));
} = useSearchSourceConnectors(false, Number(search_space_id));
// Filter for non-indexable connectors (live search)
const liveSearchConnectors = React.useMemo(
@ -134,18 +135,10 @@ const ConnectorSelector = React.memo(
[searchConnectors]
);
const handleOpenChange = useCallback(
(open: boolean) => {
setIsOpen(open);
if (open && !isLoaded) {
fetchDocumentTypes(Number(search_space_id));
}
if (open && !connectorsLoaded) {
fetchConnectors(Number(search_space_id));
}
},
[fetchDocumentTypes, isLoaded, fetchConnectors, connectorsLoaded, search_space_id]
);
const handleOpenChange = useCallback((open: boolean) => {
setIsOpen(open);
// Data is already loaded on mount, no need to fetch again
}, []);
const handleConnectorToggle = useCallback(
(connectorType: string) => {

View file

@ -77,10 +77,10 @@ const defaultData = {
title: "Upload Documents",
url: "#",
},
{
title: "Add Webpages",
url: "#",
},
// {
// title: "Add Webpages",
// url: "#",
// },
{
title: "Manage Documents",
url: "#",

View file

@ -47,6 +47,8 @@ export const useGithubStars = () => {
error,
compactFormat: Intl.NumberFormat("en-US", {
notation: "compact",
maximumFractionDigits: 1,
minimumFractionDigits: 1,
}).format(stars || 0),
};
};