diff --git a/llm-service/app/services/caii.py b/llm-service/app/services/caii.py index 7522f8885..aa497a824 100644 --- a/llm-service/app/services/caii.py +++ b/llm-service/app/services/caii.py @@ -115,11 +115,16 @@ def get_caii_llm_models(): def get_caii_embedding_models(): # notes: # NameResolutionError is we can't contact the CAII_DOMAIN - # HTTPException (404) is we can't find the endpoint by name domain = os.environ['CAII_DOMAIN'] endpoint_name = os.environ['CAII_EMBEDDING_ENDPOINT_NAME'] - models = describe_endpoint(domain=domain, endpoint_name=endpoint_name) + try: + models = describe_endpoint(domain=domain, endpoint_name=endpoint_name) + except HTTPException as e: + if e.status_code == 404: + return [{"model_id": endpoint_name}] + else: + raise e return build_model_response(models) def build_model_response(models): diff --git a/ui/src/api/modelsApi.ts b/ui/src/api/modelsApi.ts index acfbe6cfd..3827509e0 100644 --- a/ui/src/api/modelsApi.ts +++ b/ui/src/api/modelsApi.ts @@ -45,7 +45,7 @@ import { } from "src/api/utils.ts"; export interface Model { - name: string; + name?: string; model_id: string; available?: boolean; replica_count?: number; diff --git a/ui/src/pages/DataSources/ManageTab/UploadedFilesTable.tsx b/ui/src/pages/DataSources/ManageTab/UploadedFilesTable.tsx index eea15d854..d5e7a82de 100644 --- a/ui/src/pages/DataSources/ManageTab/UploadedFilesTable.tsx +++ b/ui/src/pages/DataSources/ManageTab/UploadedFilesTable.tsx @@ -67,6 +67,7 @@ import messageQueue from "src/utils/messageQueue.ts"; import { useQueryClient } from "@tanstack/react-query"; import { QueryKeys } from "src/api/utils.ts"; import useModal from "src/utils/useModal.ts"; +import { cdlWhite } from "src/cuix/variables.ts"; function SummaryPopover({ dataSourceId, @@ -101,7 +102,24 @@ const columns = ( handleDeleteFile: (document: RagDocumentResponseType) => void, ): TableProps["columns"] => [ { - title: , + title: ( + + + Document Summary + + + Note: Document summarization can take a significant amount of + time, but will not impact the ability to use the document for + Chat. + + + } + > + + + ), dataIndex: "summaryCreationTimestamp", key: "summaryCreationTimestamp", render: (timestamp: number | null, data) => { diff --git a/ui/src/pages/Models/EmbeddingModelTable.tsx b/ui/src/pages/Models/EmbeddingModelTable.tsx index 9b16becdd..8f266c48e 100644 --- a/ui/src/pages/Models/EmbeddingModelTable.tsx +++ b/ui/src/pages/Models/EmbeddingModelTable.tsx @@ -36,72 +36,40 @@ * DATA. ******************************************************************************/ -import { Button, Flex, Table, TableProps, Tooltip } from "antd"; +import { Table, TableProps } from "antd"; import { Model, useTestEmbeddingModel } from "src/api/modelsApi.ts"; import { useState } from "react"; -import { CheckCircleOutlined, CloseCircleOutlined } from "@ant-design/icons"; -import { cdlGreen600, cdlRed600 } from "src/cuix/variables.ts"; +import { modelColumns, TestCell } from "pages/Models/ModelTable.tsx"; -const ModelTestCell = (props: { - available: boolean | undefined; - model_id: string; -}) => { +const EmbeddingModelTestCell = ({ model }: { model: Model }) => { const [testModel, setTestModel] = useState(""); - const { data, isLoading } = useTestEmbeddingModel(testModel); + const { + data: testResult, + isLoading, + error, + } = useTestEmbeddingModel(testModel); const handleTestModel = () => { - setTestModel(props.model_id); + setTestModel(model.model_id); }; - if (data === "ok") { - return ; - } - return ( - - - {data && data !== "ok" && ( - - - - )} - + ); }; -const columns: TableProps["columns"] = [ - { - title: "Model ID", - dataIndex: "model_id", - key: "model_id", - }, - { - title: "Name", - dataIndex: "name", - key: "name", - }, - { - title: "Status", - dataIndex: "available", - key: "available", - render: (available?: boolean) => { - if (available === undefined) { - return "Unknown"; - } - return available ? "Available" : "Not Ready"; - }, - }, +const testCell: TableProps["columns"] = [ { title: "Test", width: 140, - render: (_, { model_id, available }) => { - return ; + render: (_, model) => { + return ; }, }, ]; @@ -116,7 +84,7 @@ const EmbeddingModelTable = ({ return ( record.model_id} diff --git a/ui/src/pages/Models/InferenceModelTable.tsx b/ui/src/pages/Models/InferenceModelTable.tsx index 73fc314e5..4abd05035 100644 --- a/ui/src/pages/Models/InferenceModelTable.tsx +++ b/ui/src/pages/Models/InferenceModelTable.tsx @@ -36,72 +36,36 @@ * DATA. ******************************************************************************/ -import { Button, Flex, Table, TableProps, Tooltip } from "antd"; +import { Table, TableProps } from "antd"; import { Model, useTestLlmModel } from "src/api/modelsApi.ts"; import { useState } from "react"; -import { CheckCircleOutlined, CloseCircleOutlined } from "@ant-design/icons"; -import { cdlGreen600, cdlRed600 } from "src/cuix/variables.ts"; +import { modelColumns, TestCell } from "pages/Models/ModelTable.tsx"; -const ModelTestCell = (props: { - available: boolean | undefined; - model_id: string; -}) => { +const InferenceModelTestCell = ({ model }: { model: Model }) => { const [testModel, setTestModel] = useState(""); - const { data, isLoading, error } = useTestLlmModel(testModel); + const { data: testResult, isLoading, error } = useTestLlmModel(testModel); const handleTestModel = () => { - setTestModel(props.model_id); + setTestModel(model.model_id); }; - if (data === "ok") { - return ; - } - return ( - - - {error || (data && data !== "ok") ? ( - - - - ) : null} - + ); }; -const columns: TableProps["columns"] = [ - { - title: "Model ID", - dataIndex: "model_id", - key: "model_id", - }, - { - title: "Name", - dataIndex: "name", - key: "name", - }, - { - title: "Status", - dataIndex: "available", - key: "available", - render: (available?: boolean) => { - if (available === undefined) { - return "Unknown"; - } - return available ? "Available" : "Not Ready"; - }, - }, +const testCell: TableProps["columns"] = [ { title: "Test", width: 140, - render: (_, { model_id, available }) => { - return ; + render: (_, model) => { + return ; }, }, ]; @@ -116,7 +80,7 @@ const InferenceModelTable = ({ return (
record.model_id} diff --git a/ui/src/pages/Models/ModelTable.tsx b/ui/src/pages/Models/ModelTable.tsx new file mode 100644 index 000000000..5f497195e --- /dev/null +++ b/ui/src/pages/Models/ModelTable.tsx @@ -0,0 +1,112 @@ +/******************************************************************************* + * CLOUDERA APPLIED MACHINE LEARNING PROTOTYPE (AMP) + * (C) Cloudera, Inc. 2024 + * All rights reserved. + * + * Applicable Open Source License: Apache 2.0 + * + * NOTE: Cloudera open source products are modular software products + * made up of hundreds of individual components, each of which was + * individually copyrighted. Each Cloudera open source product is a + * collective work under U.S. Copyright Law. Your license to use the + * collective work is as provided in your written agreement with + * Cloudera. Used apart from the collective work, this file is + * licensed for your use pursuant to the open source license + * identified above. + * + * This code is provided to you pursuant a written agreement with + * (i) Cloudera, Inc. or (ii) a third-party authorized to distribute + * this code. If you do not have a written agreement with Cloudera nor + * with an authorized and properly licensed third party, you do not + * have any rights to access nor to use this code. + * + * Absent a written agreement with Cloudera, Inc. ("Cloudera") to the + * contrary, A) CLOUDERA PROVIDES THIS CODE TO YOU WITHOUT WARRANTIES OF ANY + * KIND; (B) CLOUDERA DISCLAIMS ANY AND ALL EXPRESS AND IMPLIED + * WARRANTIES WITH RESPECT TO THIS CODE, INCLUDING BUT NOT LIMITED TO + * IMPLIED WARRANTIES OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE; (C) CLOUDERA IS NOT LIABLE TO YOU, + * AND WILL NOT DEFEND, INDEMNIFY, NOR HOLD YOU HARMLESS FOR ANY CLAIMS + * ARISING FROM OR RELATED TO THE CODE; AND (D)WITH RESPECT TO YOUR EXERCISE + * OF ANY RIGHTS GRANTED TO YOU FOR THE CODE, CLOUDERA IS NOT LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE OR + * CONSEQUENTIAL DAMAGES INCLUDING, BUT NOT LIMITED TO, DAMAGES + * RELATED TO LOST REVENUE, LOST PROFITS, LOSS OF INCOME, LOSS OF + * BUSINESS ADVANTAGE OR UNAVAILABILITY, OR LOSS OR CORRUPTION OF + * DATA. + ******************************************************************************/ +import { Button, Flex, TableProps, Tooltip, Typography } from "antd"; +import { Model } from "src/api/modelsApi.ts"; +import { CheckCircleOutlined, CloseCircleOutlined } from "@ant-design/icons"; +import { cdlGreen600, cdlRed600 } from "src/cuix/variables.ts"; + +export const TestCell = ({ + onClick, + model, + loading, + error, + testResult, +}: { + onClick: () => void; + model: Model; + loading: boolean; + error: Error | null; + testResult: string | undefined; +}) => { + if (!model.name) { + return null; + } + + if (testResult === "ok") { + return ; + } + + return ( + + + {error || (testResult && testResult !== "ok") ? ( + + + + ) : null} + + ); +}; + +export const modelColumns: TableProps["columns"] = [ + { + title: "Model ID", + dataIndex: "model_id", + key: "model_id", + width: 350, + }, + { + title: "Name", + dataIndex: "name", + key: "name", + width: 350, + render: (name?: string) => + name ?? No model found, + }, + { + title: "Status", + dataIndex: "available", + width: 150, + key: "available", + render: (_, model) => { + if (!model.name) { + return null; + } + if (model.available === undefined) { + return "Unknown"; + } + return model.available ? "Available" : "Not Ready"; + }, + }, +]; diff --git a/ui/src/pages/RagChatTab/FooterComponents/RagChatQueryInput.tsx b/ui/src/pages/RagChatTab/FooterComponents/RagChatQueryInput.tsx index ef26a3d28..9e8cb9274 100644 --- a/ui/src/pages/RagChatTab/FooterComponents/RagChatQueryInput.tsx +++ b/ui/src/pages/RagChatTab/FooterComponents/RagChatQueryInput.tsx @@ -129,8 +129,10 @@ const RagChatQueryInput = () => { onChange={(e) => { setUserInput(e.target.value); }} - onPressEnter={() => { - handleChat(userInput); + onKeyDown={(e) => { + if (e.key === "Enter") { + handleChat(userInput); + } }} disabled={!dataSourceSize || chatMutation.isPending} />