diff --git a/README.md b/README.md index 3ecfd664..24ac863d 100644 --- a/README.md +++ b/README.md @@ -37,10 +37,10 @@ https://github.com/user-attachments/assets/15f7f315-003d-4e41-a260-739c2529f824 1. **克隆项目** ```bash - git clone -b stable https://github.com/xerrors/Yuxi-Know.git + git clone -b 0.2.0.preview https://github.com/xerrors/Yuxi-Know.git cd Yuxi-Know ``` - 如果想要使用 v0.2 预览版,可以使用分支:`0.2.0.preview` + 如果想要使用之前的稳定版,可以使用分支:`stable` 分支,`main` 分支是最新的开发版本。 2. **配置 API 密钥** diff --git a/docs/changelog/update.md b/docs/changelog/update.md index 2685de11..e0938a0a 100644 --- a/docs/changelog/update.md +++ b/docs/changelog/update.md @@ -19,7 +19,8 @@ - [x] 切换知识库之后,检索结果没有刷新 - [x] 文件上传模块 UI的边距、配色有问题 - [x] 知识图谱页面的节点数量统计方法 #236 -- [ ] 当没有手动添加节点的时候,尝试检索,会出现为创建索引的情况 #236 +- [x] 当没有手动添加节点的时候,尝试检索,会出现为创建索引的情况 #236 +- [ ] 删除知识库的时候,没有正常将数据从 Neo4j / Milvus 数据库中删除(需要添加检测脚本) # 💯 More: diff --git a/server/routers/knowledge_router.py b/server/routers/knowledge_router.py index f5a4bd87..41da8df4 100644 --- a/server/routers/knowledge_router.py +++ b/server/routers/knowledge_router.py @@ -33,10 +33,11 @@ async def create_database( embed_model_name: str = Body(...), kb_type: str = Body("lightrag"), additional_params: dict = Body({}), + llm_info: dict = Body(None), current_user: User = Depends(get_admin_user) ): """创建知识库""" - logger.debug(f"Create database {database_name} with kb_type {kb_type}, additional_params {additional_params}") + logger.debug(f"Create database {database_name} with kb_type {kb_type}, additional_params {additional_params}, llm_info {llm_info}") try: embed_info = config.embed_model_names[embed_model_name] database_info = await knowledge_base.create_database( @@ -44,6 +45,7 @@ async def create_database( description, kb_type=kb_type, embed_info=embed_info, + llm_info=llm_info, **additional_params ) diff --git a/src/knowledge/chroma_kb.py b/src/knowledge/chroma_kb.py index fd91d2f0..00613188 100644 --- a/src/knowledge/chroma_kb.py +++ b/src/knowledge/chroma_kb.py @@ -64,7 +64,7 @@ class ChromaKB(KnowledgeBase): embedding_function = self._get_embedding_function(embed_info) # 创建或获取集合 - collection_name = f"kb_{db_id}" + collection_name = db_id try: # 尝试获取现有集合 diff --git a/src/knowledge/knowledge_base.py b/src/knowledge/knowledge_base.py index 39e81af6..bf6857f1 100644 --- a/src/knowledge/knowledge_base.py +++ b/src/knowledge/knowledge_base.py @@ -85,7 +85,7 @@ class KnowledgeBase(ABC): pass def create_database(self, database_name: str, description: str, - embed_info: dict | None = None, **kwargs) -> dict: + embed_info: dict | None = None, llm_info: dict | None = None, **kwargs) -> dict: """ 创建数据库 @@ -108,6 +108,7 @@ class KnowledgeBase(ABC): "description": description, "kb_type": self.kb_type, "embed_info": embed_info, + "llm_info": llm_info, "metadata": kwargs, "created_at": datetime.now().isoformat() } @@ -187,7 +188,6 @@ class KnowledgeBase(ABC): """ pass - @abstractmethod async def export_data(self, db_id: str, format: str = 'zip', **kwargs) -> str: pass diff --git a/src/knowledge/lightrag_kb.py b/src/knowledge/lightrag_kb.py index 3e0729ca..5fbfc740 100644 --- a/src/knowledge/lightrag_kb.py +++ b/src/knowledge/lightrag_kb.py @@ -55,6 +55,16 @@ class LightRagKB(KnowledgeBase): llm_info = self.databases_meta[db_id].get("llm_info", {}) embed_info = self.databases_meta[db_id].get("embed_info", {}) + # 读取在创建数据库时透传的附加参数(包括语言) + metadata = self.databases_meta[db_id].get("metadata", {}) or {} + addon_params = {} + if isinstance(metadata.get("addon_params"), dict): + addon_params.update(metadata.get("addon_params", {})) + # 兼容直接放在 metadata 下的 language + if isinstance(metadata.get("language"), str) and metadata.get("language"): + addon_params.setdefault("language", metadata.get("language")) + # 默认语言从环境变量读取,默认 English + addon_params.setdefault("language", os.getenv("SUMMARY_LANGUAGE", "English")) # 创建工作目录 working_dir = os.path.join(self.work_dir, db_id) @@ -71,6 +81,7 @@ class LightRagKB(KnowledgeBase): graph_storage="Neo4JStorage", doc_status_storage="JsonDocStatusStorage", log_file_path=os.path.join(working_dir, "lightrag.log"), + addon_params=addon_params, ) return rag @@ -107,7 +118,18 @@ class LightRagKB(KnowledgeBase): def _get_llm_func(self, llm_info: dict): """获取 LLM 函数""" from src.models import select_model - model = select_model(LIGHTRAG_LLM_PROVIDER, LIGHTRAG_LLM_NAME) + + # 如果用户选择了LLM,使用用户选择的;否则使用环境变量默认值 + if llm_info and llm_info.get("provider") and llm_info.get("model_name"): + provider = llm_info["provider"] + model_name = llm_info["model_name"] + logger.info(f"Using user-selected LLM: {provider}/{model_name}") + else: + provider = LIGHTRAG_LLM_PROVIDER + model_name = LIGHTRAG_LLM_NAME + logger.info(f"Using default LLM from environment: {provider}/{model_name}") + + model = select_model(provider, model_name) async def llm_model_func(prompt, system_prompt=None, history_messages=[], **kwargs): return await openai_complete_if_cache( diff --git a/src/knowledge/milvus_kb.py b/src/knowledge/milvus_kb.py index 9b0401ae..e91a0a31 100644 --- a/src/knowledge/milvus_kb.py +++ b/src/knowledge/milvus_kb.py @@ -101,7 +101,7 @@ class MilvusKB(KnowledgeBase): raise ValueError(f"Database {db_id} not found") embed_info = self.databases_meta[db_id].get("embed_info", {}) - collection_name = f"kb_{db_id}" + collection_name = db_id try: # 检查集合是否存在 @@ -256,7 +256,7 @@ class MilvusKB(KnowledgeBase): self._save_metadata() file_record["file_id"] = file_id - + # 添加到处理队列 self._add_to_processing_queue(file_id) diff --git a/test/data/lightrag_kb_test_tiny.txt b/test/data/lightrag_kb_test_tiny.txt new file mode 100644 index 00000000..07d345e4 --- /dev/null +++ b/test/data/lightrag_kb_test_tiny.txt @@ -0,0 +1 @@ +《红楼梦》是中国古典四大名著之一,由曹雪芹创作 \ No newline at end of file diff --git a/web/src/components/DebugComponent.vue b/web/src/components/DebugComponent.vue index 4f41a49b..3f8b96fd 100644 --- a/web/src/components/DebugComponent.vue +++ b/web/src/components/DebugComponent.vue @@ -370,10 +370,7 @@ const printDatabaseInfo = async () => { if (!checkAdminPermission()) return; try { - console.log('=== 知识库信息 ==='); - - // 直接调用API获取最新的数据库信息 - await databaseStore.refreshDatabase(); + console.log('知识库信息', databaseStore.database); } catch (error) { console.error('获取知识库信息失败:', error); diff --git a/web/src/components/KnowledgeGraphSection.vue b/web/src/components/KnowledgeGraphSection.vue index f0c0b2c3..0f137d08 100644 --- a/web/src/components/KnowledgeGraphSection.vue +++ b/web/src/components/KnowledgeGraphSection.vue @@ -15,6 +15,7 @@ size="small" @click="loadGraph" :disabled="!isGraphSupported" + :icon='h(ReloadOutlined)' > 加载图谱 @@ -153,7 +154,6 @@ import { ref, computed, watch } from 'vue'; import { useDatabaseStore } from '@/stores/database'; import { useUserStore } from '@/stores/user'; -import { getKbTypeLabel } from '@/utils/kb_utils'; import { ReloadOutlined, DeleteOutlined, ExpandOutlined, UpOutlined, DownOutlined, SettingOutlined } from '@ant-design/icons-vue'; import { message } from 'ant-design-vue'; import KnowledgeGraphViewer from '@/components/KnowledgeGraphViewer.vue'; @@ -208,6 +208,9 @@ const toggleVisible = () => { }; const loadGraph = () => { + if (!(Object.keys(store.database?.files).length > 0)) { + return; + } if (graphViewerRef.value && typeof graphViewerRef.value.loadFullGraph === 'function') { graphViewerRef.value.loadFullGraph(); } diff --git a/web/src/stores/database.js b/web/src/stores/database.js index 5bb22617..adbfa6f1 100644 --- a/web/src/stores/database.js +++ b/web/src/stores/database.js @@ -241,17 +241,17 @@ export const useDatabaseStore = defineStore('database', () => { try { const response = await queryApi.getKnowledgeBaseQueryParams(db_id); queryParams.value = response.params?.options || []; - + // Create a set of currently supported parameter keys const supportedParamKeys = new Set(queryParams.value.map(param => param.key)); - + // Remove unsupported parameters from meta for (const key in meta) { if (key !== 'db_id' && !supportedParamKeys.has(key)) { delete meta[key]; } } - + // Add default values for supported parameters that are not in meta queryParams.value.forEach(param => { if (!(param.key in meta)) { @@ -291,16 +291,16 @@ export const useDatabaseStore = defineStore('database', () => { stopAutoRefresh(); } } - + function selectAllFailedFiles() { const files = Object.values(database.value.files || {}); const failedFiles = files .filter(file => file.status === 'failed') .map(file => file.file_id); - + const newSelectedKeys = [...new Set([...selectedRowKeys.value, ...failedFiles])]; selectedRowKeys.value = newSelectedKeys; - + if (failedFiles.length > 0) { message.success(`已选择 ${failedFiles.length} 个失败的文件`); } else { diff --git a/web/src/views/DataBaseView.vue b/web/src/views/DataBaseView.vue index 880a4427..ccdeeb10 100644 --- a/web/src/views/DataBaseView.vue +++ b/web/src/views/DataBaseView.vue @@ -47,18 +47,26 @@

嵌入模型

- - + +
+

语言

+ + +

语言模型 (LLM)

+

可以在设置中配置语言模型

+ +

知识库描述

在智能体流程中,这里的描述会作为工具的描述。智能体会根据知识库的标题和描述来选择合适的工具。所以这里描述的越详细,智能体越容易选择到合适的工具。

@@ -72,13 +80,13 @@ 创建 - +

正在加载知识库...

- +
@@ -115,7 +123,7 @@

{{ database.description || '暂无描述' }}

{{ database.embed_info.name }} - {{ database.embed_info.dimension }} + { })) }) +// 语言选项(值使用英文,以保证后端/LightRAG 兼容;标签为中英文方便理解) +const languageOptions = [ + { label: '英语 English', value: 'English' }, + { label: '中文 Chinese', value: 'Chinese' }, + { label: '日语 Japanese', value: 'Japanese' }, + { label: '韩语 Korean', value: 'Korean' }, + { label: '德语 German', value: 'German' }, + { label: '法语 French', value: 'French' }, + { label: '西班牙语 Spanish', value: 'Spanish' }, + { label: '葡萄牙语 Portuguese', value: 'Portuguese' }, + { label: '俄语 Russian', value: 'Russian' }, + { label: '阿拉伯语 Arabic', value: 'Arabic' }, + { label: '印地语 Hindi', value: 'Hindi' }, +] + const emptyEmbedInfo = { name: '', description: '', @@ -165,6 +189,12 @@ const emptyEmbedInfo = { kb_type: 'chroma', // 默认为 Milvus // Vector 知识库特有配置 storage: '', // 存储方式配置 + // LightRAG 特有配置 + language: 'English', + llm_info: { + provider: '', + model_name: '' + }, } const newDatabase = reactive({ @@ -312,6 +342,13 @@ const handleKbTypeChange = (type) => { newDatabase.kb_type = type } +// 处理LLM选择 +const handleLLMSelect = (selection) => { + console.log('LLM选择:', selection) + newDatabase.llm_info.provider = selection.provider + newDatabase.llm_info.model_name = selection.name +} + const createDatabase = () => { if (!newDatabase.name?.trim()) { message.error('数据库名称不能为空') @@ -338,6 +375,17 @@ const createDatabase = () => { requestData.additional_params.storage = newDatabase.storage || 'DemoA' } + if (newDatabase.kb_type === 'lightrag') { + requestData.additional_params.language = newDatabase.language || 'English' + // 添加LLM信息到请求数据 + if (newDatabase.llm_info.provider && newDatabase.llm_info.model_name) { + requestData.llm_info = { + provider: newDatabase.llm_info.provider, + model_name: newDatabase.llm_info.model_name + } + } + } + databaseApi.createDatabase(requestData) .then(data => { console.log('创建成功:', data)