diff --git a/docs/API.md b/docs/API.md index d42beffe..cb83625c 100644 --- a/docs/API.md +++ b/docs/API.md @@ -362,12 +362,9 @@ curl --location 'http://localhost:8080/api/v1/knowledge-bases' \ "embedding_model_id": "dff7bc94-7885-4dd1-bfd5-bd96e4df2fc3", "summary_model_id": "8aea788c-bb30-4898-809e-e40c14ffb48c", "rerank_model_id": "b30171a1-787b-426e-a293-735cd5ac16c0", - "vlm_model_id": "f2083ad7-63e3-486d-a610-e6c56e58d72e", "vlm_config": { - "model_name": "qwen2.5vl:3b", - "interface_type": "ollama", - "base_url": "", - "api_key": "" + "enabled": true, + "model_id": "f2083ad7-63e3-486d-a610-e6c56e58d72e" }, "cos_config": { "secret_id": "", @@ -403,12 +400,9 @@ curl --location 'http://localhost:8080/api/v1/knowledge-bases' \ "embedding_model_id": "dff7bc94-7885-4dd1-bfd5-bd96e4df2fc3", "summary_model_id": "8aea788c-bb30-4898-809e-e40c14ffb48c", "rerank_model_id": "b30171a1-787b-426e-a293-735cd5ac16c0", - "vlm_model_id": "f2083ad7-63e3-486d-a610-e6c56e58d72e", "vlm_config": { - "model_name": "qwen2.5vl:3b", - "base_url": "", - "api_key": "", - "interface_type": "ollama" + "enabled": true, + "model_id": "f2083ad7-63e3-486d-a610-e6c56e58d72e" }, "cos_config": { "secret_id": "", @@ -466,12 +460,9 @@ curl --location 'http://localhost:8080/api/v1/knowledge-bases' \ "embedding_model_id": "dff7bc94-7885-4dd1-bfd5-bd96e4df2fc3", "summary_model_id": "8aea788c-bb30-4898-809e-e40c14ffb48c", "rerank_model_id": "b30171a1-787b-426e-a293-735cd5ac16c0", - "vlm_model_id": "f2083ad7-63e3-486d-a610-e6c56e58d72e", "vlm_config": { - "model_name": "qwen2.5vl:3b", - "base_url": "http://host.docker.internal:11435/v1", - "api_key": "", - "interface_type": "ollama" + "enabled": true, + "model_id": "f2083ad7-63e3-486d-a610-e6c56e58d72e" }, "cos_config": { "secret_id": "", @@ -529,12 +520,9 @@ curl --location 'http://localhost:8080/api/v1/knowledge-bases/kb-00000001' \ "embedding_model_id": "dff7bc94-7885-4dd1-bfd5-bd96e4df2fc3", "summary_model_id": "8aea788c-bb30-4898-809e-e40c14ffb48c", "rerank_model_id": "b30171a1-787b-426e-a293-735cd5ac16c0", - "vlm_model_id": "f2083ad7-63e3-486d-a610-e6c56e58d72e", "vlm_config": { - "model_name": "qwen2.5vl:3b", - "base_url": "http://host.docker.internal:11435/v1", - "api_key": "", - "interface_type": "ollama" + "enabled": true, + "model_id": "f2083ad7-63e3-486d-a610-e6c56e58d72e" }, "cos_config": { "secret_id": "", @@ -614,12 +602,9 @@ curl --location --request PUT 'http://localhost:8080/api/v1/knowledge-bases/b582 "embedding_model_id": "dff7bc94-7885-4dd1-bfd5-bd96e4df2fc3", "summary_model_id": "8aea788c-bb30-4898-809e-e40c14ffb48c", "rerank_model_id": "b30171a1-787b-426e-a293-735cd5ac16c0", - "vlm_model_id": "f2083ad7-63e3-486d-a610-e6c56e58d72e", "vlm_config": { - "model_name": "qwen2.5vl:3b", - "base_url": "", - "api_key": "", - "interface_type": "ollama" + "enabled": true, + "model_id": "f2083ad7-63e3-486d-a610-e6c56e58d72e" }, "cos_config": { "secret_id": "", diff --git a/docs/开启知识图谱功能.md b/docs/开启知识图谱功能.md new file mode 100644 index 00000000..cf764eec --- /dev/null +++ b/docs/开启知识图谱功能.md @@ -0,0 +1,85 @@ +# 开启知识图谱功能指南 + +本文档介绍如何在 WeKnora 中启用并验证知识图谱(Neo4j)功能,帮助你完成从环境准备到前端配置的全流程。 + +## 前置条件 + +- 已完成 WeKnora 后端与前端的基础部署。 +- 具备可用的 Docker/Docker Compose 运行环境。 +- 本地或远端可访问的 Neo4j 服务(推荐使用项目自带的 Docker Compose)。 + +## 步骤一:配置环境变量 + +在项目根目录的 `.env` 文件中新增或修改以下变量: + +``` +NEO4J_ENABLE=true +NEO4J_URI=bolt://neo4j:7687 +NEO4J_USERNAME=neo4j +NEO4J_PASSWORD=your_strong_password +# 可选:NEO4J_DATABASE=neo4j +``` + +说明: + +- `NEO4J_ENABLE` 设置为 `true` 才会启用知识图谱相关逻辑。 +- `NEO4J_URI` 中的 `neo4j` 为 docker-compose 服务名,如使用外部实例请替换为实际地址。 +- 如果生产环境使用密钥管理,请确保密码通过安全方式注入。 + +## 步骤二:启动 Neo4j 服务 + +项目附带 Neo4j 组件,可直接用以下命令启动: + +```bash +docker-compose --profile neo4j up -d +``` + +常见验证命令: + +```bash +docker ps | grep neo4j +``` + +若需要自定义挂载或内存,可编辑 `docker-compose.yml` 中 `neo4j` 服务配置。 + +## 步骤三:重启 WeKnora 服务 + +为了让新的环境变量生效,重启后端与前端(示例仅供参考): + +```bash +make stop && make start +# 或者 +docker compose up -d --build +``` + +确保后端日志中出现 `neo4j` 初始化成功的提示。 + +## 步骤四:在前端启用实体/关系抽取 + +1. 登录 WeKnora 前端管理页面。 +2. 打开「知识库设置」或创建新的知识库。 +3. 勾选「启用实体抽取」与「启用关系抽取」开关。 +4. 根据界面提示补充所需的 LLM、回调或模型参数(若有)。 + +保存后,系统会在文档入库阶段自动触发实体与关系抽取任务。 + +## 步骤五:验证知识图谱 + +### 方式一:Neo4j 控制台 + +1. 访问 `http://localhost:7474`(或对应主机/端口)。 +2. 使用 `.env` 中的账号密码登录。 +3. 执行 `MATCH (n) RETURN n LIMIT 50;` 检查是否有新节点/关系。 + +### 方式二:WeKnora 界面 + +在知识库或对话页面中上传文档后,前端应展示图谱可视化入口;对话时系统会自动根据意图查询图谱并返回补充信息。 + +## 常见问题排查 + +- **无法连接 Neo4j**:确认网络可达、`NEO4J_URI` 与用户名密码正确,并检查 Neo4j 容器日志。 +- **未生成节点**:确认知识库已开启实体/关系抽取,且上传的文档已完成解析;查看后端日志中是否有抽取任务异常。 +- **查询无结果**:尝试在 Neo4j 控制台执行 `CALL db.schema.visualization;` 查看 schema 是否存在,必要时重新导入文档。 + +完成以上步骤后,知识图谱功能即成功启用,可结合 RAG 及 Agent 流程提升问答质量。 + diff --git a/frontend/src/api/initialization/index.ts b/frontend/src/api/initialization/index.ts index 3a2e300f..a3d0ac33 100644 --- a/frontend/src/api/initialization/index.ts +++ b/frontend/src/api/initialization/index.ts @@ -74,7 +74,10 @@ export interface DownloadTask { export interface KBModelConfigRequest { llmModelId: string embeddingModelId: string - vllmModelId?: string + vlm_config?: { + enabled: boolean + model_id?: string + } documentSplitting: { chunkSize: number chunkOverlap: number diff --git a/frontend/src/api/knowledge-base/index.ts b/frontend/src/api/knowledge-base/index.ts index f0f93ddb..4dbbc577 100644 --- a/frontend/src/api/knowledge-base/index.ts +++ b/frontend/src/api/knowledge-base/index.ts @@ -12,8 +12,10 @@ export function createKnowledgeBase(data: { chunking_config?: any; embedding_model_id?: string; summary_model_id?: string; - vlm_model_id?: string; - vlm_config?: any; + vlm_config?: { + enabled: boolean; + model_id?: string; + }; cos_config?: any; extract_config?: any; faq_config?: { index_mode: string; question_index_mode?: string }; diff --git a/frontend/src/i18n/locales/en-US.ts b/frontend/src/i18n/locales/en-US.ts index 0ef81d92..e637ddc7 100644 --- a/frontend/src/i18n/locales/en-US.ts +++ b/frontend/src/i18n/locales/en-US.ts @@ -698,16 +698,20 @@ export default { uninitializedBanner: 'Some knowledge bases are not initialized. Configure model information in settings before adding documents.', empty: { title: 'No knowledge bases yet', - description: 'Click “Create Knowledge Base” in the top-right corner to add your first one.' + description: 'Click "Create Knowledge Base" in the top-right corner to add your first one.' }, delete: { confirmTitle: 'Delete Confirmation', - confirmMessage: 'Are you sure you want to delete the knowledge base “{name}”? This action cannot be undone.', + confirmMessage: 'Are you sure you want to delete the knowledge base "{name}"? This action cannot be undone.', confirmButton: 'Delete' }, messages: { deleted: 'Knowledge base deleted', deleteFailed: 'Failed to delete knowledge base' + }, + features: { + knowledgeGraph: 'Knowledge Graph Enabled', + multimodal: 'Multimodal Enabled' } }, knowledgeEditor: { @@ -868,8 +872,11 @@ export default { separatorsDescription: 'Separators used when chunking documents', separatorsPlaceholder: 'Select separators', separators: { - doubleNewline: 'Double newline (\\n\\n)', - singleNewline: 'Single newline (\\n)', + doubleNewline: 'Double newline (\ +\ +)', + singleNewline: 'Single newline (\ +)', periodCn: 'Chinese period (。)', exclamationCn: 'Exclamation mark (!)', questionCn: 'Question mark (?)', @@ -936,8 +943,29 @@ export default { tagsLabel: 'Tags', tagsDescription: 'Predefined entity tags (separate multiple tags with commas)', tagsPlaceholder: 'Enter a tag and press Enter', - disabledWarning: 'Graph database is not enabled. Please enable the graph database first to use this feature.', - howToEnable: 'How to enable' + nodesLabel: 'Node Configuration', + nodesDescription: 'Define entity node types and attributes to extract', + addNode: 'Add Node', + nodeNameLabel: 'Node Name', + nodeNamePlaceholder: 'e.g., Person, Organization', + nodeChunksLabel: 'Associated Chunks', + nodeChunksPlaceholder: 'Enter chunk ID and press Enter', + nodeAttributesLabel: 'Node Attributes', + nodeAttributesPlaceholder: 'Enter attribute name and press Enter', + relationsLabel: 'Relation Configuration', + relationsDescription: 'Define relationship types between nodes', + addRelation: 'Add Relation', + relationNode1Label: 'Source Node', + relationNode1Placeholder: 'e.g., Person', + relationNode2Label: 'Target Node', + relationNode2Placeholder: 'e.g., Organization', + relationTypeLabel: 'Relation Type', + relationTypePlaceholder: 'e.g., WORKS_FOR, BELONGS_TO', + deleteNode: 'Delete Node', + deleteRelation: 'Delete Relation', + disabledWarning: + 'Graph database is not enabled. Please follow the "Enable Knowledge Graph" guide before using this feature.', + howToEnable: 'View guide' } } }, @@ -1014,7 +1042,16 @@ export default { nullValuePlaceholder: '', documentTitleLabel: 'Document title:', chunkCountLabel: 'Chunk count:', - chunkCountValue: 'At least {count}', + chunkCountValue: '{count} chunks', + documentDescriptionLabel: 'Description:', + documentStatusLabel: 'Status:', + documentSourceLabel: 'Source:', + documentFileLabel: 'File:', + documentMetadataLabel: 'Metadata', + documentInfoSummaryLabel: 'Document info', + documentInfoCount: '{count} of {requested} documents retrieved', + documentInfoErrors: 'Errors', + documentInfoEmpty: 'No document information available', statusDescription: 'Status notes', statusIndexed: 'Document is indexed and searchable', statusSearchable: 'Search tools can locate document content', @@ -1232,7 +1269,7 @@ export default { dimensionDetected: 'Detection succeeded. Vector dimension: {value}', dimensionFailed: 'Detection failed, please enter the dimension manually', remoteDimensionDetected: 'Detected vector dimension: {value}', - dimensionHint: 'Model selected. Click “Detect Dimension” to fetch the vector dimension automatically.', + dimensionHint: 'Model selected. Click "Detect Dimension" to fetch the vector dimension automatically.', setAsDefault: 'Set as default model', loadModelListFailed: 'Failed to load model list', listRefreshed: 'List refreshed', @@ -1459,7 +1496,7 @@ export default { }, fallbackPrompt: { label: 'Fallback Prompt', - desc: 'Prompt used when fallback strategy is “model”' + desc: 'Prompt used when fallback strategy is "model"' }, advanced: { description: 'Configure query rewrite, fallback strategy and other advanced settings' @@ -1559,7 +1596,7 @@ export default { deleted: 'MCP service deleted', deleteFailed: 'Failed to delete MCP service' }, - deleteConfirmBody: 'Delete MCP service “{name}”? This action cannot be undone.', + deleteConfirmBody: 'Delete MCP service "{name}"? This action cannot be undone.', unnamed: 'Unnamed' }, // New: Model Settings @@ -1616,7 +1653,7 @@ export default { description: 'Manage local Ollama service and view/download models', status: { label: 'Ollama Service Status', - desc: 'Automatically detect local Ollama service availability. If the service is down or the URL is incorrect, status will be “Unavailable”.', + desc: 'Automatically detect local Ollama service availability. If the service is down or the URL is incorrect, status will be "Unavailable".', testing: 'Testing', available: 'Available', unavailable: 'Unavailable', diff --git a/frontend/src/i18n/locales/ru-RU.ts b/frontend/src/i18n/locales/ru-RU.ts index 7c72b534..412fc182 100644 --- a/frontend/src/i18n/locales/ru-RU.ts +++ b/frontend/src/i18n/locales/ru-RU.ts @@ -795,6 +795,10 @@ export default { messages: { deleted: 'База знаний удалена', deleteFailed: 'Не удалось удалить базу знаний' + }, + features: { + knowledgeGraph: 'Граф знаний включен', + multimodal: 'Мультимодальность включена' } }, knowledgeEditor: { @@ -1099,7 +1103,16 @@ export default { nullValuePlaceholder: '', documentTitleLabel: 'Название документа:', chunkCountLabel: 'Количество фрагментов:', - chunkCountValue: 'Не менее {count}', + chunkCountValue: '{count} фрагментов', + documentDescriptionLabel: 'Описание:', + documentStatusLabel: 'Статус:', + documentSourceLabel: 'Источник:', + documentFileLabel: 'Файл:', + documentMetadataLabel: 'Метаданные', + documentInfoSummaryLabel: 'Информация о документах', + documentInfoCount: '{count} из {requested} документов получено', + documentInfoErrors: 'Ошибки', + documentInfoEmpty: 'Нет данных о документах', statusDescription: 'Информация о статусе', statusIndexed: 'Документ проиндексирован и доступен для поиска', statusSearchable: 'Можно искать содержимое документа с помощью инструментов', diff --git a/frontend/src/i18n/locales/zh-CN.ts b/frontend/src/i18n/locales/zh-CN.ts index e119c2cb..96b65249 100644 --- a/frontend/src/i18n/locales/zh-CN.ts +++ b/frontend/src/i18n/locales/zh-CN.ts @@ -217,7 +217,16 @@ export default { nullValuePlaceholder: "", documentTitleLabel: "文档标题:", chunkCountLabel: "片段数量:", - chunkCountValue: "至少 {count} 个", + chunkCountValue: "{count} 个片段", + documentDescriptionLabel: "文档描述:", + documentStatusLabel: "处理状态:", + documentSourceLabel: "来源:", + documentFileLabel: "文件信息:", + documentMetadataLabel: "元数据", + documentInfoSummaryLabel: "文档信息", + documentInfoCount: "成功 {count} / 请求 {requested}", + documentInfoErrors: "错误详情", + documentInfoEmpty: "暂无文档信息", statusDescription: "状态说明", statusIndexed: "文档已索引并可搜索", statusSearchable: "可使用搜索工具查找文档内容", @@ -1021,6 +1030,10 @@ export default { deleted: "已删除", deleteFailed: "删除失败", }, + features: { + knowledgeGraph: "已启用知识图谱", + multimodal: "已启用多模态", + }, }, knowledgeEditor: { titleCreate: "新建知识库", @@ -1253,8 +1266,29 @@ export default { tagsLabel: "标签", tagsDescription: "预定义的实体标签(多个标签用逗号分隔)", tagsPlaceholder: "输入标签后按回车", - disabledWarning: "图数据库未启用,无法使用知识图谱功能。请先启用图数据库后再使用此功能。", - howToEnable: "查看如何开启", + nodesLabel: "节点配置", + nodesDescription: "定义需要提取的实体节点类型及其属性", + addNode: "添加节点", + nodeNameLabel: "节点名称", + nodeNamePlaceholder: "如:Person、Organization", + nodeChunksLabel: "关联文档块", + nodeChunksPlaceholder: "输入 chunk ID 后按回车", + nodeAttributesLabel: "节点属性", + nodeAttributesPlaceholder: "输入属性名后按回车", + relationsLabel: "关系配置", + relationsDescription: "定义节点之间的关系类型", + addRelation: "添加关系", + relationNode1Label: "起始节点", + relationNode1Placeholder: "如:Person", + relationNode2Label: "目标节点", + relationNode2Placeholder: "如:Organization", + relationTypeLabel: "关系类型", + relationTypePlaceholder: "如:WORKS_FOR、BELONGS_TO", + deleteNode: "删除节点", + deleteRelation: "删除关系", + disabledWarning: + "图数据库未启用,无法使用知识图谱功能。请先根据《开启知识图谱功能指南》完成配置。", + howToEnable: "查看启用说明", }, }, }, diff --git a/frontend/src/types/tool-results.ts b/frontend/src/types/tool-results.ts index f3bff705..fa96905f 100644 --- a/frontend/src/types/tool-results.ts +++ b/frontend/src/types/tool-results.ts @@ -92,11 +92,28 @@ export interface KnowledgeBaseListData { } // Document info data -export interface DocumentInfoData { - display_type: 'document_info'; +export interface DocumentInfoDocument { knowledge_id: string; title: string; - chunk_count_min: number; + description?: string; + type?: string; + source?: string; + file_name?: string; + file_type?: string; + file_size?: number; + parse_status?: string; + chunk_count?: number; + metadata?: Record; + type_icon?: string; +} + +export interface DocumentInfoData { + display_type: 'document_info'; + documents?: DocumentInfoDocument[]; + total_docs: number; + requested: number; + errors?: string[]; + title?: string; } // Graph query results data diff --git a/frontend/src/views/chat/components/tool-results/DocumentInfo.vue b/frontend/src/views/chat/components/tool-results/DocumentInfo.vue index 6d707caf..30ae4a62 100644 --- a/frontend/src/views/chat/components/tool-results/DocumentInfo.vue +++ b/frontend/src/views/chat/components/tool-results/DocumentInfo.vue @@ -1,73 +1,276 @@ - diff --git a/frontend/src/views/knowledge/KnowledgeBaseEditorModal.vue b/frontend/src/views/knowledge/KnowledgeBaseEditorModal.vue index ee67df0b..6d0a736e 100644 --- a/frontend/src/views/knowledge/KnowledgeBaseEditorModal.vue +++ b/frontend/src/views/knowledge/KnowledgeBaseEditorModal.vue @@ -275,7 +275,17 @@ const initFormData = (type: 'document' | 'faq' = 'document') => { nodeExtractConfig: { enabled: false, text: '', - tags: [] as string[] + tags: [] as string[], + nodes: [] as Array<{ + name: string + chunks: string[] + attributes: string[] + }>, + relations: [] as Array<{ + node1: string + node2: string + type: string + }> } } } @@ -331,9 +341,9 @@ const loadKBData = async () => { separators: kb.chunking_config?.separators || ['\n\n', '\n', '。', '!', '?', ';', ';'] }, multimodalConfig: { - enabled: !!(kb.vlm_model_id || (kb.cos_config?.provider && kb.cos_config?.bucket_name)), + enabled: !!(kb.vlm_config?.enabled || (kb.cos_config?.provider && kb.cos_config?.bucket_name)), storageType: (kb.cos_config?.provider || 'minio') as 'minio' | 'cos', - vllmModelId: kb.vlm_model_id || '', + vllmModelId: kb.vlm_config?.model_id || '', minio: { bucketName: kb.cos_config?.bucket_name || '', useSSL: kb.cos_config?.use_ssl || false, @@ -351,7 +361,9 @@ const loadKBData = async () => { nodeExtractConfig: { enabled: kb.extract_config?.enabled || false, text: kb.extract_config?.text || '', - tags: kb.extract_config?.tags || [] + tags: kb.extract_config?.tags || [], + nodes: kb.extract_config?.nodes || [], + relations: kb.extract_config?.relations || [] } } } catch (error) { @@ -450,11 +462,14 @@ const buildSubmitData = () => { } // 添加多模态配置 + data.vlm_config = { + enabled: formData.value.multimodalConfig.enabled, + model_id: formData.value.multimodalConfig.enabled + ? (formData.value.multimodalConfig.vllmModelId || '') + : '' + } + if (formData.value.multimodalConfig.enabled) { - if (formData.value.multimodalConfig.vllmModelId) { - data.vlm_model_id = formData.value.multimodalConfig.vllmModelId - } - const storageType = formData.value.multimodalConfig.storageType if (storageType === 'minio') { data.cos_config = { @@ -481,7 +496,9 @@ const buildSubmitData = () => { data.extract_config = { enabled: true, text: formData.value.nodeExtractConfig.text, - tags: formData.value.nodeExtractConfig.tags + tags: formData.value.nodeExtractConfig.tags, + nodes: formData.value.nodeExtractConfig.nodes, + relations: formData.value.nodeExtractConfig.relations } } @@ -540,14 +557,14 @@ const handleSubmit = async () => { const config: KBModelConfigRequest = { llmModelId: data.summary_model_id, embeddingModelId: data.embedding_model_id, - vllmModelId: data.vlm_model_id || '', + vlm_config: data.vlm_config, documentSplitting: { chunkSize: data.chunking_config.chunk_size, chunkOverlap: data.chunking_config.chunk_overlap, separators: data.chunking_config.separators }, multimodal: { - enabled: !!data.cos_config, + enabled: !!data.cos_config || !!data.vlm_config?.enabled, storageType: data.cos_config?.provider || 'minio', cos: data.cos_config?.provider === 'cos' ? { secretId: data.cos_config.secret_id, diff --git a/frontend/src/views/knowledge/KnowledgeBaseList.vue b/frontend/src/views/knowledge/KnowledgeBaseList.vue index 0b56de08..179c49be 100644 --- a/frontend/src/views/knowledge/KnowledgeBaseList.vue +++ b/frontend/src/views/knowledge/KnowledgeBaseList.vue @@ -71,9 +71,23 @@
-
- - {{ kb.type === 'faq' ? $t('knowledgeEditor.basic.typeFAQ') : $t('knowledgeEditor.basic.typeDocument') }} +
+
+ + {{ kb.type === 'faq' ? $t('knowledgeEditor.basic.typeFAQ') : $t('knowledgeEditor.basic.typeDocument') }} +
+
+ +
+ +
+
+ +
+ +
+
+
{{ kb.updated_at }}
@@ -150,6 +164,9 @@ interface KB { summary_model_id?: string; type?: 'document' | 'faq'; showMore?: boolean; + vlm_config?: { enabled?: boolean; model_id?: string }; + extract_config?: { enabled?: boolean }; + cos_config?: { provider?: string; bucket_name?: string }; } const kbs = ref([]) @@ -483,6 +500,12 @@ const handleKBEditorSuccess = (kbId: string) => { margin-top: auto; } +.bottom-left { + display: flex; + align-items: center; + gap: 8px; +} + .type-badge { display: inline-flex; align-items: center; @@ -507,6 +530,42 @@ const handleKBEditorSuccess = (kbId: string) => { } } +.feature-badges { + display: flex; + align-items: center; + gap: 6px; +} + +.feature-badge { + display: flex; + align-items: center; + justify-content: center; + width: 24px; + height: 24px; + border-radius: 4px; + cursor: pointer; + + &.kg { + background: rgba(124, 77, 255, 0.1); + color: #7c4dff; + border: 1px solid rgba(124, 77, 255, 0.2); + + &:hover { + background: rgba(124, 77, 255, 0.15); + } + } + + &.multimodal { + background: rgba(255, 152, 0, 0.1); + color: #ff9800; + border: 1px solid rgba(255, 152, 0, 0.2); + + &:hover { + background: rgba(255, 152, 0, 0.15); + } + } +} + .card-time { color: #00000066; font-family: "PingFang SC"; diff --git a/frontend/src/views/knowledge/settings/KBAdvancedSettings.vue b/frontend/src/views/knowledge/settings/KBAdvancedSettings.vue index f8f5beae..71ec0fba 100644 --- a/frontend/src/views/knowledge/settings/KBAdvancedSettings.vue +++ b/frontend/src/views/knowledge/settings/KBAdvancedSettings.vue @@ -219,11 +219,11 @@ -