feat(chatbot): 增强智能体工具和知识库集成能力
- 在智能体上下文中添加知识库字段,支持从知识库中选择工具 - 重构工具获取逻辑,支持根据上下文动态加载工具 - 优化前端知识库创建和加载逻辑,移入 store 管理 - 改进工具调用结果渲染,支持知识库工具识别 - 添加 clear-btn 样式改进
This commit is contained in:
parent
34fbd1a13e
commit
8087ef4b00
@ -3,6 +3,7 @@ from typing import Annotated
|
||||
|
||||
from src.agents.common import BaseContext, gen_tool_info
|
||||
from src.agents.common.mcp import MCP_SERVERS
|
||||
from src.knowledge import knowledge_base
|
||||
|
||||
from .tools import get_tools
|
||||
|
||||
@ -14,7 +15,17 @@ class Context(BaseContext):
|
||||
metadata={
|
||||
"name": "工具",
|
||||
"options": lambda: gen_tool_info(get_tools()), # 这里的选择是所有的工具
|
||||
"description": "工具列表",
|
||||
"description": "内置的部分工具,包含 common 工具和本智能体的特有工具(不含 MCP)。",
|
||||
},
|
||||
)
|
||||
|
||||
knowledges: list[str] = field(
|
||||
default_factory=list,
|
||||
metadata={
|
||||
"name": "知识库",
|
||||
"options": lambda: [k["name"] for k in knowledge_base.get_retrievers().values()],
|
||||
"description": "知识库列表,可以在左侧知识库页面中创建知识库。",
|
||||
"type": "list", # Explicitly mark as list type for frontend if needed
|
||||
},
|
||||
)
|
||||
|
||||
@ -23,6 +34,8 @@ class Context(BaseContext):
|
||||
metadata={
|
||||
"name": "MCP服务器",
|
||||
"options": lambda: list(MCP_SERVERS.keys()),
|
||||
"description": "MCP服务器列表",
|
||||
"description": (
|
||||
"MCP服务器列表,建议使用支持 SSE 的 MCP 服务器,"
|
||||
"如果需要使用 uvx 或 npx 运行的服务器,也请在项目外部启动 MCP 服务器,并在项目中配置 MCP 服务器。"),
|
||||
},
|
||||
)
|
||||
|
||||
@ -2,14 +2,13 @@ from langchain.agents import create_agent
|
||||
from langchain.agents.middleware import ModelRetryMiddleware
|
||||
|
||||
from src.agents.common import BaseAgent, load_chat_model
|
||||
from src.agents.common.mcp import MCP_SERVERS
|
||||
from src.agents.common.mcp import get_mcp_tools
|
||||
from src.agents.common.middlewares import (
|
||||
DynamicToolMiddleware,
|
||||
context_aware_prompt,
|
||||
context_based_model,
|
||||
inject_attachment_context,
|
||||
)
|
||||
from src.agents.common.subagents import calc_agent_tool
|
||||
from src.agents.common.tools import get_kb_based_tools
|
||||
|
||||
from .context import Context
|
||||
from .tools import get_tools
|
||||
@ -18,7 +17,7 @@ from .tools import get_tools
|
||||
class ChatbotAgent(BaseAgent):
|
||||
name = "智能体助手"
|
||||
description = "基础的对话机器人,可以回答问题,默认不使用任何工具,可在配置中启用需要的工具。"
|
||||
capabilities = ["file_upload"] # 支持文件上传功能
|
||||
capabilities = ["file_upload", "reload_graph"] # 支持文件上传功能和重载图
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
@ -26,34 +25,48 @@ class ChatbotAgent(BaseAgent):
|
||||
self.checkpointer = None
|
||||
self.context_schema = Context
|
||||
|
||||
def get_tools(self):
|
||||
"""返回基本工具"""
|
||||
base_tools = get_tools()
|
||||
base_tools.append(calc_agent_tool)
|
||||
return base_tools
|
||||
async def get_tools(self, tools: list[str] = None, mcps=None, knowledges=None):
|
||||
|
||||
# 1. 基础工具 (从 context.tools 中筛选)
|
||||
all_basic_tools = get_tools()
|
||||
selected_tools = []
|
||||
|
||||
if tools:
|
||||
# 创建工具映射表
|
||||
tools_map = {t.name: t for t in all_basic_tools}
|
||||
for tool_name in tools:
|
||||
if tool_name in tools_map:
|
||||
selected_tools.append(tools_map[tool_name])
|
||||
|
||||
# 2. 知识库工具
|
||||
if knowledges:
|
||||
kb_tools = get_kb_based_tools(db_names=knowledges)
|
||||
selected_tools.extend(kb_tools)
|
||||
|
||||
# 3. MCP 工具
|
||||
if mcps:
|
||||
for server_name in mcps:
|
||||
mcp_tools = await get_mcp_tools(server_name)
|
||||
selected_tools.extend(mcp_tools)
|
||||
|
||||
return selected_tools
|
||||
|
||||
async def get_graph(self, **kwargs):
|
||||
"""构建图"""
|
||||
if self.graph:
|
||||
return self.graph
|
||||
|
||||
# 创建动态工具中间件实例,并传入所有可用的 MCP 服务器列表
|
||||
dynamic_tool_middleware = DynamicToolMiddleware(
|
||||
base_tools=self.get_tools(), mcp_servers=list(MCP_SERVERS.keys())
|
||||
)
|
||||
# 获取上下文配置
|
||||
context = self.context_schema.from_file(module_name=self.module_name)
|
||||
|
||||
# 预加载所有 MCP 工具并注册到 middleware.tools
|
||||
await dynamic_tool_middleware.initialize_mcp_tools()
|
||||
|
||||
# 使用 create_agent 创建智能体,并传入 middleware
|
||||
# 使用 create_agent 创建智能体
|
||||
graph = create_agent(
|
||||
model=load_chat_model("siliconflow/Qwen/Qwen3-235B-A22B-Instruct-2507"), # 默认模型,会被 middleware 覆盖
|
||||
tools=get_tools(), # 注册基础工具
|
||||
model=load_chat_model(context.model), # 使用 context 中的模型配置
|
||||
tools=await self.get_tools(context.tools, context.mcps, context.knowledges),
|
||||
middleware=[
|
||||
context_aware_prompt, # 动态系统提示词
|
||||
inject_attachment_context, # 附件上下文注入(LangChain 标准中间件)
|
||||
inject_attachment_context, # 附件上下文注入
|
||||
context_based_model, # 动态模型选择
|
||||
dynamic_tool_middleware, # 动态工具选择(支持 MCP 工具注册)
|
||||
ModelRetryMiddleware(), # 模型重试中间件
|
||||
],
|
||||
checkpointer=await self._get_checkpointer(),
|
||||
@ -69,4 +82,4 @@ def main():
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
# asyncio.run(main())
|
||||
# asyncio.run(main())
|
||||
@ -6,6 +6,7 @@ import requests
|
||||
from langchain.tools import tool
|
||||
|
||||
from src.agents.common import get_buildin_tools
|
||||
from src.agents.common.subagents import calc_agent_tool
|
||||
from src.storage.minio import aupload_file_to_minio
|
||||
from src.utils import logger
|
||||
|
||||
@ -51,4 +52,5 @@ def get_tools() -> list[Any]:
|
||||
"""获取所有可运行的工具(给大模型使用)"""
|
||||
tools = get_buildin_tools()
|
||||
tools.append(text_to_img_demo)
|
||||
tools.append(calc_agent_tool)
|
||||
return tools
|
||||
|
||||
@ -46,7 +46,11 @@ class BaseContext:
|
||||
|
||||
model: Annotated[str, {"__template_metadata__": {"kind": "llm"}}] = field(
|
||||
default=sys_config.default_model,
|
||||
metadata={"name": "智能体模型", "options": [], "description": "智能体的驱动模型"},
|
||||
metadata={
|
||||
"name": "智能体模型",
|
||||
"options": [],
|
||||
"description": "智能体的驱动模型,建议选择 Agent 能力较强的模型,不建议使用小参数模型。"
|
||||
},
|
||||
)
|
||||
|
||||
@classmethod
|
||||
|
||||
@ -11,7 +11,7 @@ from pydantic import BaseModel, Field
|
||||
from src import config, graph_base, knowledge_base
|
||||
from src.utils import logger
|
||||
|
||||
search = TavilySearch(max_results=10)
|
||||
search = TavilySearch()
|
||||
search.metadata = {"name": "Tavily 网页搜索"}
|
||||
|
||||
|
||||
@ -122,11 +122,12 @@ class KnowledgeRetrieverModel(BaseModel):
|
||||
)
|
||||
|
||||
|
||||
def get_kb_based_tools() -> list:
|
||||
def get_kb_based_tools(db_names: list[str] | None = None) -> list:
|
||||
"""获取所有知识库基于的工具"""
|
||||
# 获取所有知识库
|
||||
kb_tools = []
|
||||
retrievers = knowledge_base.get_retrievers()
|
||||
db_ids = [kb_id for kb_id, kb in retrievers.items() if kb["name"] in db_names] or None
|
||||
|
||||
def _create_retriever_wrapper(db_id: str, retriever_info: dict[str, Any]):
|
||||
"""创建检索器包装函数的工厂函数,避免闭包变量捕获问题"""
|
||||
@ -185,6 +186,9 @@ def get_kb_based_tools() -> list:
|
||||
return async_retriever_wrapper
|
||||
|
||||
for db_id, retrieve_info in retrievers.items():
|
||||
if db_ids is not None and db_id not in db_ids:
|
||||
continue
|
||||
|
||||
try:
|
||||
# 构建工具描述
|
||||
description = (
|
||||
@ -227,8 +231,6 @@ def get_buildin_tools() -> list:
|
||||
tools = []
|
||||
|
||||
try:
|
||||
# 获取所有知识库基于的工具
|
||||
tools.extend(get_kb_based_tools())
|
||||
tools.extend(get_static_tools())
|
||||
|
||||
from src.agents.common.toolkits.mysql.tools import get_mysql_tools
|
||||
|
||||
@ -152,6 +152,7 @@
|
||||
<a-button
|
||||
type="link"
|
||||
size="small"
|
||||
class="clear-btn"
|
||||
@click="clearSelection(key)"
|
||||
v-if="getSelectedCount(key) > 0"
|
||||
>
|
||||
@ -819,12 +820,6 @@ const resetConfig = async () => {
|
||||
color: var(--gray-900);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.clear-btn {
|
||||
padding: 0;
|
||||
height: auto;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.select-tools-btn {
|
||||
@ -1133,6 +1128,19 @@ const resetConfig = async () => {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.clear-btn {
|
||||
padding: 0;
|
||||
height: auto;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
color: var(--main-700);
|
||||
|
||||
&:hover {
|
||||
color: var(--main-800);
|
||||
}
|
||||
}
|
||||
|
||||
// 响应式适配
|
||||
@media (max-width: 768px) {
|
||||
.agent-config-sidebar.open {
|
||||
|
||||
@ -35,6 +35,7 @@
|
||||
import { computed, ref } from 'vue';
|
||||
import BaseToolCall from './BaseToolCall.vue';
|
||||
import { useAgentStore } from '@/stores/agent';
|
||||
import { useDatabaseStore } from '@/stores/database';
|
||||
|
||||
import WebSearchTool from './tools/WebSearchTool.vue';
|
||||
import KnowledgeBaseTool from './tools/KnowledgeBaseTool.vue';
|
||||
@ -53,13 +54,18 @@ const props = defineProps({
|
||||
});
|
||||
|
||||
const agentStore = useAgentStore();
|
||||
const databaseStore = useDatabaseStore();
|
||||
|
||||
const toolName = computed(() => props.toolCall.name || props.toolCall.function?.name || '');
|
||||
const tool = computed(() => {
|
||||
const toolsList = agentStore?.availableTools ? Object.values(agentStore.availableTools) : [];
|
||||
return toolsList.find(t => t.name === toolName.value) || null;
|
||||
const tool = toolsList.find(t => t.name === toolName.value)
|
||||
return tool || null;
|
||||
});
|
||||
|
||||
const databases = computed(() => databaseStore.databases || []);
|
||||
|
||||
|
||||
const parseData = (content) => {
|
||||
if (typeof content === 'string') {
|
||||
try {
|
||||
@ -90,17 +96,9 @@ const isTaskResult = computed(() => {
|
||||
});
|
||||
|
||||
const isKnowledgeBaseResult = computed(() => {
|
||||
const currentTool = tool.value;
|
||||
|
||||
if (currentTool && currentTool.metadata) {
|
||||
const metadata = currentTool.metadata;
|
||||
const hasKnowledgebaseTag = metadata.tag && metadata.tag.includes('knowledgebase');
|
||||
const isNotLightrag = metadata.kb_type !== 'lightrag';
|
||||
if (hasKnowledgebaseTag && isNotLightrag) {
|
||||
// const data = parseData(props.toolCall.tool_call_result?.content);
|
||||
// return Array.isArray(data) && data.length > 0;
|
||||
return true
|
||||
}
|
||||
const databaseInfo = databases.value.find(db => db.name === toolName.value);
|
||||
if (databaseInfo && databaseInfo.kb_type !== 'lightrag') {
|
||||
return true
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
@ -1,9 +1,7 @@
|
||||
<script setup>
|
||||
import { ref, reactive, onMounted, useTemplateRef, computed, provide } from 'vue'
|
||||
import { RouterLink, RouterView, useRoute } from 'vue-router'
|
||||
import {
|
||||
GithubOutlined,
|
||||
} from '@ant-design/icons-vue'
|
||||
import { GithubOutlined } from '@ant-design/icons-vue'
|
||||
import { Bot, Waypoints, LibraryBig, BarChart3, CircleCheck } from 'lucide-vue-next';
|
||||
import { onLongPress } from '@vueuse/core'
|
||||
|
||||
@ -69,7 +67,7 @@ const getRemoteConfig = () => {
|
||||
}
|
||||
|
||||
const getRemoteDatabase = () => {
|
||||
databaseStore.getDatabaseInfo(undefined, false) // Explicitly load query params for remote database
|
||||
databaseStore.loadDatabases()
|
||||
}
|
||||
|
||||
// Fetch GitHub stars count
|
||||
|
||||
@ -5,21 +5,25 @@ import { message, Modal } from 'ant-design-vue';
|
||||
import { databaseApi, documentApi, queryApi } from '@/apis/knowledge_api';
|
||||
import { useTaskerStore } from '@/stores/tasker';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { parseToShanghai } from '@/utils/time';
|
||||
|
||||
export const useDatabaseStore = defineStore('database', () => {
|
||||
const router = useRouter();
|
||||
const taskerStore = useTaskerStore();
|
||||
|
||||
// State
|
||||
const databases = ref([]);
|
||||
const database = ref({});
|
||||
const databaseId = ref(null);
|
||||
const selectedFile = ref(null);
|
||||
|
||||
const queryParams = ref([]);
|
||||
const meta = reactive({});
|
||||
const selectedRowKeys = ref([]);
|
||||
const selectedRowKeys = ref([]);
|
||||
|
||||
const state = reactive({
|
||||
listLoading: false,
|
||||
creating: false,
|
||||
databaseLoading: false,
|
||||
refrashing: false,
|
||||
searchLoading: false,
|
||||
@ -38,6 +42,64 @@ export const useDatabaseStore = defineStore('database', () => {
|
||||
let autoRefreshManualOverride = false; // Indicates user explicitly disabled auto-refresh
|
||||
|
||||
// Actions
|
||||
async function loadDatabases() {
|
||||
state.listLoading = true;
|
||||
try {
|
||||
const data = await databaseApi.getDatabases();
|
||||
databases.value = data.databases.sort((a, b) => {
|
||||
const timeA = parseToShanghai(a.created_at);
|
||||
const timeB = parseToShanghai(b.created_at);
|
||||
if (!timeA && !timeB) return 0;
|
||||
if (!timeA) return 1;
|
||||
if (!timeB) return -1;
|
||||
return timeB.valueOf() - timeA.valueOf(); // 降序排列,最新的在前面
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('加载数据库列表失败:', error);
|
||||
if (error.message.includes('权限')) {
|
||||
message.error('需要管理员权限访问知识库');
|
||||
}
|
||||
throw error;
|
||||
} finally {
|
||||
state.listLoading = false;
|
||||
}
|
||||
}
|
||||
|
||||
async function createDatabase(formData) {
|
||||
// 验证
|
||||
if (!formData.database_name?.trim()) {
|
||||
message.error('数据库名称不能为空');
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!formData.kb_type) {
|
||||
message.error('请选择知识库类型');
|
||||
return false;
|
||||
}
|
||||
|
||||
// 向量数据库的重排序模型验证
|
||||
if (['chroma', 'milvus'].includes(formData.kb_type)) {
|
||||
if (formData.reranker_config?.enabled && !formData.reranker_config?.model) {
|
||||
message.error('请选择重排序模型');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
state.creating = true;
|
||||
try {
|
||||
const data = await databaseApi.createDatabase(formData);
|
||||
message.success('创建成功');
|
||||
await loadDatabases(); // 刷新列表
|
||||
return data;
|
||||
} catch (error) {
|
||||
console.error('创建数据库失败:', error);
|
||||
message.error(error.message || '创建失败');
|
||||
throw error;
|
||||
} finally {
|
||||
state.creating = false;
|
||||
}
|
||||
}
|
||||
|
||||
async function getDatabaseInfo(id, skipQueryParams = false) {
|
||||
const db_id = id || databaseId.value;
|
||||
if (!db_id) return;
|
||||
@ -404,6 +466,7 @@ export const useDatabaseStore = defineStore('database', () => {
|
||||
}
|
||||
|
||||
return {
|
||||
databases,
|
||||
database,
|
||||
databaseId,
|
||||
selectedFile,
|
||||
@ -411,6 +474,8 @@ export const useDatabaseStore = defineStore('database', () => {
|
||||
meta,
|
||||
selectedRowKeys,
|
||||
state,
|
||||
loadDatabases,
|
||||
createDatabase,
|
||||
getDatabaseInfo,
|
||||
updateDatabaseInfo,
|
||||
deleteDatabase,
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="database-container layout-container">
|
||||
<HeaderComponent title="文档知识库" :loading="state.loading">
|
||||
<HeaderComponent title="文档知识库" :loading="dbState.listLoading">
|
||||
<template #actions>
|
||||
<a-button type="primary" @click="state.openNewDatabaseModel=true">
|
||||
新建知识库
|
||||
@ -8,7 +8,7 @@
|
||||
</template>
|
||||
</HeaderComponent>
|
||||
|
||||
<a-modal :open="state.openNewDatabaseModel" title="新建知识库" @ok="createDatabase" @cancel="cancelCreateDatabase" class="new-database-modal" width="800px">
|
||||
<a-modal :open="state.openNewDatabaseModel" title="新建知识库" @ok="handleCreateDatabase" @cancel="cancelCreateDatabase" class="new-database-modal" width="800px">
|
||||
|
||||
<!-- 知识库类型选择 -->
|
||||
<h3>知识库类型<span style="color: var(--color-error-500)">*</span></h3>
|
||||
@ -162,12 +162,12 @@
|
||||
</div>
|
||||
<template #footer>
|
||||
<a-button key="back" @click="cancelCreateDatabase">取消</a-button>
|
||||
<a-button key="submit" type="primary" :loading="state.creating" @click="createDatabase">创建</a-button>
|
||||
<a-button key="submit" type="primary" :loading="dbState.creating" @click="handleCreateDatabase">创建</a-button>
|
||||
</template>
|
||||
</a-modal>
|
||||
|
||||
<!-- 加载状态 -->
|
||||
<div v-if="state.loading" class="loading-container">
|
||||
<div v-if="dbState.listLoading" class="loading-container">
|
||||
<a-spin size="large" />
|
||||
<p>正在加载知识库...</p>
|
||||
</div>
|
||||
@ -235,11 +235,12 @@
|
||||
<script setup>
|
||||
import { ref, onMounted, reactive, watch, computed } from 'vue'
|
||||
import { useRouter, useRoute } from 'vue-router';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { useConfigStore } from '@/stores/config';
|
||||
import { message } from 'ant-design-vue'
|
||||
import { Database, Zap, FileDigit, Waypoints, Building2 } from 'lucide-vue-next';
|
||||
import { useDatabaseStore } from '@/stores/database';
|
||||
import { Database, FileDigit, Waypoints, Building2 } from 'lucide-vue-next';
|
||||
import { LockOutlined, InfoCircleOutlined, QuestionCircleOutlined, PlusOutlined } from '@ant-design/icons-vue';
|
||||
import { databaseApi, typeApi } from '@/apis/knowledge_api';
|
||||
import { typeApi } from '@/apis/knowledge_api';
|
||||
import HeaderComponent from '@/components/HeaderComponent.vue';
|
||||
import ModelSelectorComponent from '@/components/ModelSelectorComponent.vue';
|
||||
import EmbeddingModelSelector from '@/components/EmbeddingModelSelector.vue';
|
||||
@ -248,12 +249,13 @@ import AiTextarea from '@/components/AiTextarea.vue';
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const databases = ref([])
|
||||
const configStore = useConfigStore()
|
||||
const databaseStore = useDatabaseStore()
|
||||
|
||||
// 使用 store 的状态
|
||||
const { databases, state: dbState } = storeToRefs(databaseStore)
|
||||
|
||||
const state = reactive({
|
||||
loading: false,
|
||||
creating: false,
|
||||
openNewDatabaseModel: false,
|
||||
})
|
||||
|
||||
@ -357,32 +359,6 @@ const loadSupportedKbTypes = async () => {
|
||||
|
||||
// 重排序模型信息现在直接从 configStore.config.reranker_names 获取,无需单独加载
|
||||
|
||||
const loadDatabases = () => {
|
||||
state.loading = true
|
||||
// loadGraph()
|
||||
databaseApi.getDatabases()
|
||||
.then(data => {
|
||||
console.log(data)
|
||||
// 按照创建时间排序,最新的在前面
|
||||
databases.value = data.databases.sort((a, b) => {
|
||||
const timeA = parseToShanghai(a.created_at)
|
||||
const timeB = parseToShanghai(b.created_at)
|
||||
if (!timeA && !timeB) return 0
|
||||
if (!timeA) return 1
|
||||
if (!timeB) return -1
|
||||
return timeB.valueOf() - timeA.valueOf() // 降序排列,最新的在前面
|
||||
})
|
||||
state.loading = false
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('加载数据库列表失败:', error);
|
||||
if (error.message.includes('权限')) {
|
||||
message.error('需要管理员权限访问知识库')
|
||||
}
|
||||
state.loading = false
|
||||
})
|
||||
}
|
||||
|
||||
const resetNewDatabase = () => {
|
||||
Object.assign(newDatabase, createEmptyDatabaseForm())
|
||||
}
|
||||
@ -473,19 +449,8 @@ const handleLLMSelect = (spec) => {
|
||||
newDatabase.llm_info.model_name = modelName
|
||||
}
|
||||
|
||||
const createDatabase = () => {
|
||||
if (!newDatabase.name?.trim()) {
|
||||
message.error('数据库名称不能为空')
|
||||
return
|
||||
}
|
||||
|
||||
if (!newDatabase.kb_type) {
|
||||
message.error('请选择知识库类型')
|
||||
return
|
||||
}
|
||||
|
||||
state.creating = true
|
||||
|
||||
// 构建请求数据(只负责表单数据转换)
|
||||
const buildRequestData = () => {
|
||||
const requestData = {
|
||||
database_name: newDatabase.name.trim(),
|
||||
description: newDatabase.description?.trim() || '',
|
||||
@ -496,18 +461,12 @@ const createDatabase = () => {
|
||||
}
|
||||
}
|
||||
|
||||
// 添加类型特有的配置
|
||||
if (newDatabase.kb_type === 'chroma' || newDatabase.kb_type === 'milvus') {
|
||||
// 根据类型添加特定配置
|
||||
if (['chroma', 'milvus'].includes(newDatabase.kb_type)) {
|
||||
if (newDatabase.storage) {
|
||||
requestData.additional_params.storage = newDatabase.storage
|
||||
}
|
||||
|
||||
if (newDatabase.reranker.enabled) {
|
||||
if (!newDatabase.reranker.model) {
|
||||
message.error('请选择重排序模型')
|
||||
state.creating = false
|
||||
return
|
||||
}
|
||||
requestData.additional_params.reranker_config = {
|
||||
enabled: true,
|
||||
model: newDatabase.reranker.model,
|
||||
@ -519,7 +478,6 @@ const createDatabase = () => {
|
||||
|
||||
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,
|
||||
@ -528,21 +486,19 @@ const createDatabase = () => {
|
||||
}
|
||||
}
|
||||
|
||||
databaseApi.createDatabase(requestData)
|
||||
.then(data => {
|
||||
console.log('创建成功:', data)
|
||||
loadDatabases()
|
||||
resetNewDatabase()
|
||||
message.success('创建成功')
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('创建数据库失败:', error)
|
||||
message.error(error.message || '创建失败')
|
||||
})
|
||||
.finally(() => {
|
||||
state.creating = false
|
||||
state.openNewDatabaseModel = false
|
||||
})
|
||||
return requestData
|
||||
}
|
||||
|
||||
// 创建按钮处理
|
||||
const handleCreateDatabase = async () => {
|
||||
const requestData = buildRequestData()
|
||||
try {
|
||||
await databaseStore.createDatabase(requestData)
|
||||
resetNewDatabase()
|
||||
state.openNewDatabaseModel = false
|
||||
} catch (error) {
|
||||
// 错误已在 store 中处理
|
||||
}
|
||||
}
|
||||
|
||||
const navigateToDatabase = (databaseId) => {
|
||||
@ -585,15 +541,15 @@ watch(
|
||||
}
|
||||
)
|
||||
|
||||
watch(() => route.path, (newPath, oldPath) => {
|
||||
watch(() => route.path, (newPath) => {
|
||||
if (newPath === '/database') {
|
||||
loadDatabases();
|
||||
databaseStore.loadDatabases();
|
||||
}
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
loadSupportedKbTypes()
|
||||
loadDatabases()
|
||||
databaseStore.loadDatabases()
|
||||
// 重排序模型信息现在直接从 configStore 获取,无需单独加载
|
||||
})
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user