### What problem does this PR solve? Feat: Add Tavily Api Key to chat configuration modal. #5198 ### Type of change - [x] New Feature (non-breaking change which adds functionality)tags/v0.17.0
| documentId={item.doc_id} | documentId={item.doc_id} | ||||
| documentName={item.doc_name} | documentName={item.doc_name} | ||||
| prefix="document" | prefix="document" | ||||
| link={item.url} | |||||
| > | > | ||||
| {item.doc_name} | {item.doc_name} | ||||
| </NewDocumentLink> | </NewDocumentLink> |
| count: number; | count: number; | ||||
| doc_id: string; | doc_id: string; | ||||
| doc_name: string; | doc_name: string; | ||||
| url?: string; | |||||
| } | } | ||||
| // interface Chunk { | // interface Chunk { |
| reasoning: 'Reasoning', | reasoning: 'Reasoning', | ||||
| reasoningTip: | reasoningTip: | ||||
| 'It will trigger reasoning process like Deepseek-R1/OpenAI o1. Integrates an agentic search process into the reasoning workflow, allowing models itself to dynamically retrieve external knowledge whenever they encounter uncertain information.', | 'It will trigger reasoning process like Deepseek-R1/OpenAI o1. Integrates an agentic search process into the reasoning workflow, allowing models itself to dynamically retrieve external knowledge whenever they encounter uncertain information.', | ||||
| tavilyApiKeyTip: | |||||
| 'If API key is set correctly, it will utilize Tavily to do web search as a supplement to knowledge bases.', | |||||
| tavilyApiKeyMessage: 'Please enter your Tavily Api Key', | |||||
| tavilyApiKeyHelp: 'How to get it?', | |||||
| }, | }, | ||||
| setting: { | setting: { | ||||
| profile: 'Profile', | profile: 'Profile', |
| selectFiles: '選擇文件', | selectFiles: '選擇文件', | ||||
| changeSpecificCategory: '更改特定類別', | changeSpecificCategory: '更改特定類別', | ||||
| uploadTitle: '點擊或拖拽文件至此區域即可上傳', | uploadTitle: '點擊或拖拽文件至此區域即可上傳', | ||||
| uploadDescription: '支持單次或批量上傳。單個檔案大小不超過10MB,最多上傳128份檔案。', | |||||
| uploadDescription: | |||||
| '支持單次或批量上傳。單個檔案大小不超過10MB,最多上傳128份檔案。', | |||||
| chunk: '解析塊', | chunk: '解析塊', | ||||
| bulk: '批量', | bulk: '批量', | ||||
| cancel: '取消', | cancel: '取消', | ||||
| reasoning: '推理', | reasoning: '推理', | ||||
| reasoningTip: | reasoningTip: | ||||
| '它將觸發類似Deepseek-R1/OpenAI o1的推理過程。將代理搜尋過程整合到推理工作流程中,使得模型本身能夠在遇到不確定資訊時動態地檢索外部知識。', | '它將觸發類似Deepseek-R1/OpenAI o1的推理過程。將代理搜尋過程整合到推理工作流程中,使得模型本身能夠在遇到不確定資訊時動態地檢索外部知識。', | ||||
| tavilyApiKeyTip: | |||||
| '如果 API 金鑰設定正確,它將利用 Tavily 進行網路搜尋作為知識庫的補充。', | |||||
| tavilyApiKeyMessage: '請輸入你的 Tavily Api Key', | |||||
| tavilyApiKeyHelp: '如何獲取?', | |||||
| }, | }, | ||||
| setting: { | setting: { | ||||
| profile: '概述', | profile: '概述', | ||||
| newFolder: '新建文件夾', | newFolder: '新建文件夾', | ||||
| uploadFile: '上傳文件', | uploadFile: '上傳文件', | ||||
| uploadTitle: '點擊或拖拽文件至此區域即可上傳', | uploadTitle: '點擊或拖拽文件至此區域即可上傳', | ||||
| uploadDescription: '支持單次或批量上傳。單個檔案大小不超過10MB,最多上傳128份檔案。', | |||||
| uploadDescription: | |||||
| '支持單次或批量上傳。單個檔案大小不超過10MB,最多上傳128份檔案。', | |||||
| file: '文件', | file: '文件', | ||||
| directory: '文件夾', | directory: '文件夾', | ||||
| local: '本地上傳', | local: '本地上傳', |
| reasoning: '推理', | reasoning: '推理', | ||||
| reasoningTip: | reasoningTip: | ||||
| '它将像Deepseek-R1 / OpenAI o1一样触发推理过程。将代理搜索过程集成到推理工作流中,允许模型本身在遇到不确定信息时动态地检索外部知识。', | '它将像Deepseek-R1 / OpenAI o1一样触发推理过程。将代理搜索过程集成到推理工作流中,允许模型本身在遇到不确定信息时动态地检索外部知识。', | ||||
| tavilyApiKeyTip: | |||||
| '如果 API 密钥设置正确,它将利用 Tavily 进行网络搜索作为知识库的补充。', | |||||
| tavilyApiKeyMessage: '请输入你的 Tavily Api Key', | |||||
| tavilyApiKeyHelp: '如何获取?', | |||||
| }, | }, | ||||
| setting: { | setting: { | ||||
| profile: '概要', | profile: '概要', |
| import { useTranslate } from '@/hooks/common-hooks'; | import { useTranslate } from '@/hooks/common-hooks'; | ||||
| import { useFetchTenantInfo } from '@/hooks/user-setting-hooks'; | import { useFetchTenantInfo } from '@/hooks/user-setting-hooks'; | ||||
| import { PlusOutlined } from '@ant-design/icons'; | import { PlusOutlined } from '@ant-design/icons'; | ||||
| import { Form, Input, message, Select, Switch, Upload } from 'antd'; | |||||
| import { Form, Input, message, Select, Switch, Typography, Upload } from 'antd'; | |||||
| import classNames from 'classnames'; | import classNames from 'classnames'; | ||||
| import { useCallback } from 'react'; | import { useCallback } from 'react'; | ||||
| import { ISegmentedContentProps } from '../interface'; | import { ISegmentedContentProps } from '../interface'; | ||||
| > | > | ||||
| <Switch onChange={handleTtsChange} /> | <Switch onChange={handleTtsChange} /> | ||||
| </Form.Item> | </Form.Item> | ||||
| <Form.Item label={'Tavily Api Key'} tooltip={t('tavilyApiKeyTip')}> | |||||
| <div className="flex flex-col gap-1"> | |||||
| <Form.Item name={['prompt_config', 'tavily_api_key']} noStyle> | |||||
| <Input.Password placeholder={t('tavilyApiKeyMessage')} /> | |||||
| </Form.Item> | |||||
| <Typography.Link href="https://app.tavily.com/home" target={'_blank'}> | |||||
| {t('tavilyApiKeyHelp')} | |||||
| </Typography.Link> | |||||
| </div> | |||||
| </Form.Item> | |||||
| <KnowledgeBaseItem | <KnowledgeBaseItem | ||||
| required={false} | required={false} | ||||
| onChange={handleChange} | onChange={handleChange} |
| }, [reference, setDocumentIds]); | }, [reference, setDocumentIds]); | ||||
| const handleDocumentButtonClick = useCallback( | const handleDocumentButtonClick = useCallback( | ||||
| (documentId: string, chunk: IReferenceChunk, isPdf: boolean) => () => { | |||||
| if (!isPdf) { | |||||
| return; | |||||
| } | |||||
| clickDocumentButton?.(documentId, chunk); | |||||
| }, | |||||
| ( | |||||
| documentId: string, | |||||
| chunk: IReferenceChunk, | |||||
| isPdf: boolean, | |||||
| documentUrl?: string, | |||||
| ) => | |||||
| () => { | |||||
| if (!isPdf) { | |||||
| if (!documentUrl) { | |||||
| return; | |||||
| } | |||||
| window.open(documentUrl, '_blank'); | |||||
| } else { | |||||
| clickDocumentButton?.(documentId, chunk); | |||||
| } | |||||
| }, | |||||
| [clickDocumentButton], | [clickDocumentButton], | ||||
| ); | ); | ||||
| (x) => x?.doc_id === chunkItem?.document_id, | (x) => x?.doc_id === chunkItem?.document_id, | ||||
| ); | ); | ||||
| const documentId = document?.doc_id; | const documentId = document?.doc_id; | ||||
| const documentUrl = document?.url; | |||||
| const fileThumbnail = documentId ? fileThumbnails[documentId] : ''; | const fileThumbnail = documentId ? fileThumbnails[documentId] : ''; | ||||
| const fileExtension = documentId ? getExtension(document?.doc_name) : ''; | const fileExtension = documentId ? getExtension(document?.doc_name) : ''; | ||||
| const imageId = chunkItem?.image_id; | const imageId = chunkItem?.image_id; | ||||
| documentId, | documentId, | ||||
| chunkItem, | chunkItem, | ||||
| fileExtension === 'pdf', | fileExtension === 'pdf', | ||||
| documentUrl, | |||||
| )} | )} | ||||
| > | > | ||||
| {document?.doc_name} | {document?.doc_name} |