feat: apikey

This commit is contained in:
scarqin
2024-12-31 15:07:43 +08:00
parent 3ebafcbc03
commit 9b6d07dc4c
7 changed files with 61 additions and 37 deletions
@@ -15,7 +15,9 @@ import {
useNodesState
} from '@xyflow/react'
import '@xyflow/react/dist/style.css'
import { Button, Space } from 'antd'
import { useCallback, useEffect, useState } from 'react'
import { useNavigate } from 'react-router-dom'
import CustomEdge from './components/CustomEdge'
import { KeyStatusNode } from './components/KeyStatusNode'
import { ModelCardNode } from './components/ModelCardNode'
@@ -68,11 +70,13 @@ const AIFlowChart = () => {
const [edges, setEdges, onEdgesChange] = useEdgesState<Edge>([])
const { fetchData } = useFetch()
const { aiConfigFlushed } = useGlobalContext()
const navigate = useNavigate()
useEffect(() => {
fetchData<ApiResponse>('ai/providers/configured', {
method: 'GET',
eoTransformKeys: ['default_llm']
// eoApiPrefix: 'http://uat.apikit.com:11204/mockApi/aoplatform/api/v1/'
}).then((response) => {
const mockApiResponse: ApiResponse = response as ApiResponse
setModelData(mockApiResponse.data.providers)
@@ -207,26 +211,35 @@ const AIFlowChart = () => {
return (
<div className="w-full h-full">
<ReactFlow
nodes={nodes}
edges={edges}
onNodesChange={onNodesChange}
onEdgesChange={onEdgesChange}
onNodeDragStop={onNodeDragStop}
proOptions={{ hideAttribution: true }}
draggable={false}
nodeTypes={nodeTypes}
edgeTypes={edgeTypes}
zoomOnScroll={false}
zoomOnPinch={false}
zoomOnDoubleClick={false}
panOnScroll={true}
panOnScrollMode={PanOnScrollMode.Vertical}
defaultEdgeOptions={{
type: 'custom'
}}
translateExtent={calculateExtent()}
/>
{modelData.length === 0 ? (
<Space className="flex flex-col justify-center items-center h-[200px]">
<div>No AI model configured</div>
<Button type="primary" onClick={() => navigate('/aisetting?status=unconfigure')}>
Go to Settings
</Button>
</Space>
) : (
<ReactFlow
nodes={nodes}
edges={edges}
onNodesChange={onNodesChange}
onEdgesChange={onEdgesChange}
onNodeDragStop={onNodeDragStop}
proOptions={{ hideAttribution: true }}
draggable={false}
nodeTypes={nodeTypes}
edgeTypes={edgeTypes}
zoomOnScroll={false}
zoomOnPinch={false}
zoomOnDoubleClick={false}
panOnScroll={true}
panOnScrollMode={PanOnScrollMode.Vertical}
defaultEdgeOptions={{
type: 'custom'
}}
translateExtent={calculateExtent()}
/>
)}
</div>
)
}
@@ -6,16 +6,17 @@ import { useFetch } from '@common/hooks/http'
import { $t } from '@common/locales'
import { App, Button, Card, Empty, Spin, Tag } from 'antd'
import { memo, useEffect, useState } from 'react'
import { useNavigate } from 'react-router-dom'
import { useAiSetting } from './contexts/AiSettingContext'
import { AiSettingListItem } from './types'
const CardBox = memo(({ provider }: { provider: AiSettingListItem }) => {
const { openConfigModal } = useAiSetting()
const { aiConfigFlushed, setAiConfigFlushed } = useGlobalContext()
const navigate = useNavigate()
const handleOpenModal = async (provider: AiSettingListItem) => {
await openConfigModal(provider)
setAiConfigFlushed(!aiConfigFlushed)
navigate('/aisetting?status=configure')
}
return (
@@ -1,6 +1,8 @@
import InsidePage from '@common/components/aoplatform/InsidePage'
import { $t } from '@common/locales'
import { Tabs } from 'antd'
import { useEffect, useState } from 'react'
import { useSearchParams } from 'react-router-dom'
import AIFlowChart from './AIFlowChart'
import AIUnConfigure from './AIUnconfigure'
import { AiSettingProvider } from './contexts/AiSettingContext'
@@ -8,6 +10,14 @@ import { AiSettingProvider } from './contexts/AiSettingContext'
const CONTENT_STYLE = { height: 'calc(-300px + 100vh)' } as const
const AiSettingContent = () => {
const [searchParams, setSearchParams] = useSearchParams()
const [activeKey, setActiveKey] = useState(searchParams.get('status') === 'unconfigure' ? 'config' : 'flow')
useEffect(() => {
const newActiveKey = searchParams.get('status') === 'unconfigure' ? 'config' : 'flow'
setActiveKey(newActiveKey)
}, [searchParams])
return (
<InsidePage
className="h-full pb-PAGE_INSIDE_B"
@@ -18,6 +28,11 @@ const AiSettingContent = () => {
>
<div className="flex flex-col h-full">
<Tabs
activeKey={activeKey}
onChange={(key) => {
setActiveKey(key)
setSearchParams({ status: key === 'config' ? 'unconfigure' : 'configure' })
}}
className="sticky top-0 flex-shrink-0"
items={[
{
@@ -5,10 +5,10 @@ import { useFetch } from '@common/hooks/http'
import { $t } from '@common/locales'
import { App, Form, InputNumber, Select, Switch, Tag, Tooltip } from 'antd'
import { forwardRef, useEffect, useImperativeHandle, useState } from 'react'
import { AiProviderConfig, AiProviderLlmsItems, ModelDetailData } from './types'
import { AiProviderLlmsItems, ModelDetailData } from './types'
export type AiSettingModalContentProps = {
entity: AiProviderConfig & { defaultLlm: string }
entity: ModelDetailData & { defaultLlm: string }
readOnly: boolean
}
@@ -173,7 +173,7 @@ const AiSettingModalContent = forwardRef<AiSettingModalContentHandle, AiSettingM
/>
</Form.Item>
{entity.id && (
{entity.configured && (
<Form.Item className="p-4 bg-white rounded-lg" label={$t('LLM 状态管理')}>
<div className="flex justify-between items-center">
<div>
@@ -44,7 +44,7 @@ export const ModelCardNode: React.FC<{ data: ModelCardNodeData }> = ({ data }) =
></span>
</div>
<span className="text-base text-gray-900 max-w-[180px] truncate">{name}</span>
<Icon icon={statusConfig.icon} className={`text-xl ${statusConfig.color}`} />
<Icon icon={statusConfig?.icon} className={`text-xl ${statusConfig?.color}`} />
</div>
{/* Action buttons */}
@@ -7,7 +7,7 @@ import { checkAccess } from '@common/utils/permission'
import { App } from 'antd'
import { createContext, useContext, useRef } from 'react'
import AiSettingModalContent, { AiSettingModalContentHandle } from '../AiSettingModal'
import { AiProviderConfig, AiSettingListItem } from '../types'
import { AiSettingListItem, ModelDetailData } from '../types'
interface AiSettingContextType {
openConfigModal: (entity: AiSettingListItem) => Promise<void>
@@ -23,7 +23,7 @@ export const AiSettingProvider: React.FC<{ children: React.ReactNode }> = ({ chi
const openConfigModal = async (entity: AiSettingListItem) => {
message.loading($t(RESPONSE_TIPS.loading))
const { code, data, msg } = await fetchData<BasicResponse<{ provider: AiProviderConfig }>>('ai/provider/config', {
const { code, data, msg } = await fetchData<BasicResponse<{ provider: ModelDetailData }>>('ai/provider/config', {
method: 'GET',
eoParams: { provider: entity!.id },
eoTransformKeys: ['get_apikey_url']
@@ -21,6 +21,9 @@ export interface ModelDetailData extends ModelListData{
enable:boolean
config: string,
priority?: number
getApikeyUrl: string
status: ModelStatus
configured: boolean
}
@@ -51,12 +54,4 @@ export type AiProviderDefaultConfig = {
scopes: string[]
}
export interface AiProviderConfig {
id: string
name: string
config: string
getApikeyUrl: string
priority: number
enable: boolean
status: ModelStatus
}