mirror of
https://github.com/Tencent/WeKnora.git
synced 2025-11-25 03:15:00 +08:00
feat: Added web page for configuring model information
This commit is contained in:
278
frontend/src/api/initialization/index.ts
Normal file
278
frontend/src/api/initialization/index.ts
Normal file
@@ -0,0 +1,278 @@
|
||||
import { get, post } from '../../utils/request';
|
||||
|
||||
// 初始化配置数据类型
|
||||
export interface InitializationConfig {
|
||||
llm: {
|
||||
source: string;
|
||||
modelName: string;
|
||||
baseUrl?: string;
|
||||
apiKey?: string;
|
||||
};
|
||||
embedding: {
|
||||
source: string;
|
||||
modelName: string;
|
||||
baseUrl?: string;
|
||||
apiKey?: string;
|
||||
dimension?: number; // 添加embedding维度字段
|
||||
};
|
||||
rerank: {
|
||||
modelName: string;
|
||||
baseUrl: string;
|
||||
apiKey?: string;
|
||||
};
|
||||
multimodal: {
|
||||
enabled: boolean;
|
||||
vlm?: {
|
||||
modelName: string;
|
||||
baseUrl: string;
|
||||
apiKey?: string;
|
||||
interfaceType?: string; // "ollama" or "openai"
|
||||
};
|
||||
cos?: {
|
||||
secretId: string;
|
||||
secretKey: string;
|
||||
region: string;
|
||||
bucketName: string;
|
||||
appId: string;
|
||||
pathPrefix?: string;
|
||||
};
|
||||
};
|
||||
documentSplitting: {
|
||||
chunkSize: number;
|
||||
chunkOverlap: number;
|
||||
separators: string[];
|
||||
};
|
||||
}
|
||||
|
||||
// 下载任务状态类型
|
||||
export interface DownloadTask {
|
||||
id: string;
|
||||
modelName: string;
|
||||
status: 'pending' | 'downloading' | 'completed' | 'failed';
|
||||
progress: number;
|
||||
message: string;
|
||||
startTime: string;
|
||||
endTime?: string;
|
||||
}
|
||||
|
||||
// 系统初始化状态检查
|
||||
export function checkInitializationStatus(): Promise<{ initialized: boolean }> {
|
||||
return new Promise((resolve, reject) => {
|
||||
get('/api/v1/initialization/status')
|
||||
.then((response: any) => {
|
||||
resolve(response.data || { initialized: false });
|
||||
})
|
||||
.catch((error: any) => {
|
||||
console.warn('检查初始化状态失败,假设需要初始化:', error);
|
||||
resolve({ initialized: false });
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// 执行系统初始化
|
||||
export function initializeSystem(config: InitializationConfig): Promise<any> {
|
||||
return new Promise((resolve, reject) => {
|
||||
console.log('开始系统初始化...', config);
|
||||
post('/api/v1/initialization/initialize', config)
|
||||
.then((response: any) => {
|
||||
console.log('系统初始化完成', response);
|
||||
// 设置本地初始化状态标记
|
||||
localStorage.setItem('system_initialized', 'true');
|
||||
resolve(response);
|
||||
})
|
||||
.catch((error: any) => {
|
||||
console.error('系统初始化失败:', error);
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// 检查Ollama服务状态
|
||||
export function checkOllamaStatus(): Promise<{ available: boolean; version?: string; error?: string }> {
|
||||
return new Promise((resolve, reject) => {
|
||||
get('/api/v1/initialization/ollama/status')
|
||||
.then((response: any) => {
|
||||
resolve(response.data || { available: false });
|
||||
})
|
||||
.catch((error: any) => {
|
||||
console.error('检查Ollama状态失败:', error);
|
||||
resolve({ available: false, error: error.message || '检查失败' });
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// 检查Ollama模型状态
|
||||
export function checkOllamaModels(models: string[]): Promise<{ models: Record<string, boolean> }> {
|
||||
return new Promise((resolve, reject) => {
|
||||
post('/api/v1/initialization/ollama/models/check', { models })
|
||||
.then((response: any) => {
|
||||
resolve(response.data || { models: {} });
|
||||
})
|
||||
.catch((error: any) => {
|
||||
console.error('检查Ollama模型状态失败:', error);
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// 启动Ollama模型下载(异步)
|
||||
export function downloadOllamaModel(modelName: string): Promise<{ taskId: string; modelName: string; status: string; progress: number }> {
|
||||
return new Promise((resolve, reject) => {
|
||||
post('/api/v1/initialization/ollama/models/download', { modelName })
|
||||
.then((response: any) => {
|
||||
resolve(response.data || { taskId: '', modelName, status: 'failed', progress: 0 });
|
||||
})
|
||||
.catch((error: any) => {
|
||||
console.error('启动Ollama模型下载失败:', error);
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// 查询下载进度
|
||||
export function getDownloadProgress(taskId: string): Promise<DownloadTask> {
|
||||
return new Promise((resolve, reject) => {
|
||||
get(`/api/v1/initialization/ollama/download/progress/${taskId}`)
|
||||
.then((response: any) => {
|
||||
resolve(response.data);
|
||||
})
|
||||
.catch((error: any) => {
|
||||
console.error('查询下载进度失败:', error);
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// 获取所有下载任务
|
||||
export function listDownloadTasks(): Promise<DownloadTask[]> {
|
||||
return new Promise((resolve, reject) => {
|
||||
get('/api/v1/initialization/ollama/download/tasks')
|
||||
.then((response: any) => {
|
||||
resolve(response.data || []);
|
||||
})
|
||||
.catch((error: any) => {
|
||||
console.error('获取下载任务列表失败:', error);
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// 获取当前系统配置
|
||||
export function getCurrentConfig(): Promise<InitializationConfig & { hasFiles: boolean }> {
|
||||
return new Promise((resolve, reject) => {
|
||||
get('/api/v1/initialization/config')
|
||||
.then((response: any) => {
|
||||
resolve(response.data || {});
|
||||
})
|
||||
.catch((error: any) => {
|
||||
console.error('获取当前配置失败:', error);
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// 检查远程API模型
|
||||
export function checkRemoteModel(modelConfig: {
|
||||
modelName: string;
|
||||
baseUrl: string;
|
||||
apiKey?: string;
|
||||
}): Promise<{
|
||||
available: boolean;
|
||||
message?: string;
|
||||
}> {
|
||||
return new Promise((resolve, reject) => {
|
||||
post('/api/v1/initialization/remote/check', modelConfig)
|
||||
.then((response: any) => {
|
||||
resolve(response.data || {});
|
||||
})
|
||||
.catch((error: any) => {
|
||||
console.error('检查远程模型失败:', error);
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export function checkRerankModel(modelConfig: {
|
||||
modelName: string;
|
||||
baseUrl: string;
|
||||
apiKey?: string;
|
||||
}): Promise<{
|
||||
available: boolean;
|
||||
message?: string;
|
||||
}> {
|
||||
return new Promise((resolve, reject) => {
|
||||
post('/api/v1/initialization/rerank/check', modelConfig)
|
||||
.then((response: any) => {
|
||||
resolve(response.data || {});
|
||||
})
|
||||
.catch((error: any) => {
|
||||
console.error('检查Rerank模型失败:', error);
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export function testMultimodalFunction(testData: {
|
||||
image: File;
|
||||
vlm_model: string;
|
||||
vlm_base_url: string;
|
||||
vlm_api_key?: string;
|
||||
vlm_interface_type?: string;
|
||||
cos_secret_id: string;
|
||||
cos_secret_key: string;
|
||||
cos_region: string;
|
||||
cos_bucket_name: string;
|
||||
cos_app_id: string;
|
||||
cos_path_prefix?: string;
|
||||
chunk_size: number;
|
||||
chunk_overlap: number;
|
||||
separators: string[];
|
||||
}): Promise<{
|
||||
success: boolean;
|
||||
caption?: string;
|
||||
ocr?: string;
|
||||
processing_time?: number;
|
||||
message?: string;
|
||||
}> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const formData = new FormData();
|
||||
formData.append('image', testData.image);
|
||||
formData.append('vlm_model', testData.vlm_model);
|
||||
formData.append('vlm_base_url', testData.vlm_base_url);
|
||||
if (testData.vlm_api_key) {
|
||||
formData.append('vlm_api_key', testData.vlm_api_key);
|
||||
}
|
||||
if (testData.vlm_interface_type) {
|
||||
formData.append('vlm_interface_type', testData.vlm_interface_type);
|
||||
}
|
||||
formData.append('cos_secret_id', testData.cos_secret_id);
|
||||
formData.append('cos_secret_key', testData.cos_secret_key);
|
||||
formData.append('cos_region', testData.cos_region);
|
||||
formData.append('cos_bucket_name', testData.cos_bucket_name);
|
||||
formData.append('cos_app_id', testData.cos_app_id);
|
||||
if (testData.cos_path_prefix) {
|
||||
formData.append('cos_path_prefix', testData.cos_path_prefix);
|
||||
}
|
||||
formData.append('chunk_size', testData.chunk_size.toString());
|
||||
formData.append('chunk_overlap', testData.chunk_overlap.toString());
|
||||
formData.append('separators', JSON.stringify(testData.separators));
|
||||
|
||||
// 使用原生fetch因为需要发送FormData
|
||||
fetch('/api/v1/initialization/multimodal/test', {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then((data: any) => {
|
||||
if (data.success) {
|
||||
resolve(data.data || {});
|
||||
} else {
|
||||
resolve({ success: false, message: data.message || '测试失败' });
|
||||
}
|
||||
})
|
||||
.catch((error: any) => {
|
||||
console.error('多模态测试失败:', error);
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -173,7 +173,12 @@ const getIcon = (path) => {
|
||||
getIcon(route.name)
|
||||
const gotopage = (path) => {
|
||||
pathPrefix.value = path;
|
||||
router.push(`/platform/${path}`);
|
||||
// 如果是系统设置,跳转到初始化配置页面
|
||||
if (path === 'settings') {
|
||||
router.push('/initialization');
|
||||
} else {
|
||||
router.push(`/platform/${path}`);
|
||||
}
|
||||
getIcon(path)
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ export default function () {
|
||||
});
|
||||
const getKnowled = (query = { page: 1, page_size: 35 }) => {
|
||||
getKnowledgeBase(query)
|
||||
.then((result: object) => {
|
||||
.then((result: any) => {
|
||||
let { data, total: totalResult } = result;
|
||||
let cardList_ = data.map((item) => {
|
||||
item["file_name"] = item.file_name.substring(
|
||||
@@ -50,7 +50,7 @@ export default function () {
|
||||
cardList.value[index].isMore = false;
|
||||
moreIndex.value = -1;
|
||||
delKnowledgeDetails(item.id)
|
||||
.then((result) => {
|
||||
.then((result: any) => {
|
||||
if (result.success) {
|
||||
MessagePlugin.info("知识删除成功!");
|
||||
getKnowled();
|
||||
@@ -76,17 +76,29 @@ export default function () {
|
||||
return;
|
||||
}
|
||||
uploadKnowledgeBase({ file })
|
||||
.then((result) => {
|
||||
.then((result: any) => {
|
||||
if (result.success) {
|
||||
MessagePlugin.info("上传成功!");
|
||||
getKnowled();
|
||||
} else {
|
||||
MessagePlugin.error("上传失败!");
|
||||
// 检查错误码,如果是重复文件则显示特定提示
|
||||
if (result.code === 'duplicate_file') {
|
||||
MessagePlugin.error("文件已存在");
|
||||
} else {
|
||||
MessagePlugin.error(result.message || (result.error && result.error.message) || "上传失败!");
|
||||
}
|
||||
}
|
||||
uploadInput.value.value = "";
|
||||
})
|
||||
.catch((err) => {
|
||||
MessagePlugin.error("上传失败!");
|
||||
.catch((err: any) => {
|
||||
// 检查错误响应中的错误码
|
||||
if (err.code === 'duplicate_file') {
|
||||
MessagePlugin.error("文件已存在");
|
||||
} else if (err.message) {
|
||||
MessagePlugin.error(err.message);
|
||||
} else {
|
||||
MessagePlugin.error("上传失败!");
|
||||
}
|
||||
uploadInput.value.value = "";
|
||||
});
|
||||
} else {
|
||||
@@ -101,7 +113,7 @@ export default function () {
|
||||
id: "",
|
||||
});
|
||||
getKnowledgeDetails(item.id)
|
||||
.then((result) => {
|
||||
.then((result: any) => {
|
||||
if (result.success && result.data) {
|
||||
let { data } = result;
|
||||
Object.assign(details, {
|
||||
@@ -116,7 +128,7 @@ export default function () {
|
||||
};
|
||||
const getfDetails = (id, page) => {
|
||||
getKnowledgeDetailsCon(id, page)
|
||||
.then((result) => {
|
||||
.then((result: any) => {
|
||||
if (result.success && result.data) {
|
||||
let { data, total: totalResult } = result;
|
||||
if (page == 1) {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
import { checkInitializationStatus } from '@/api/initialization'
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHistory(import.meta.env.BASE_URL),
|
||||
@@ -7,40 +8,82 @@ const router = createRouter({
|
||||
path: "/",
|
||||
redirect: "/platform",
|
||||
},
|
||||
{
|
||||
path: "/initialization",
|
||||
name: "initialization",
|
||||
component: () => import("../views/initialization/InitializationConfig.vue"),
|
||||
meta: { requiresInit: false } // 初始化页面不需要检查初始化状态
|
||||
},
|
||||
{
|
||||
path: "/knowledgeBase",
|
||||
name: "home",
|
||||
component: () => import("../views/knowledge/KnowledgeBase.vue"),
|
||||
meta: { requiresInit: true }
|
||||
},
|
||||
{
|
||||
path: "/platform",
|
||||
name: "Platform",
|
||||
redirect: "/platform/knowledgeBase",
|
||||
component: () => import("../views/platform/index.vue"),
|
||||
meta: { requiresInit: true },
|
||||
children: [
|
||||
{
|
||||
path: "knowledgeBase",
|
||||
name: "knowledgeBase",
|
||||
component: () => import("../views/knowledge/KnowledgeBase.vue"),
|
||||
meta: { requiresInit: true }
|
||||
},
|
||||
{
|
||||
path: "creatChat",
|
||||
name: "creatChat",
|
||||
component: () => import("../views/creatChat/creatChat.vue"),
|
||||
meta: { requiresInit: true }
|
||||
},
|
||||
{
|
||||
path: "chat/:chatid",
|
||||
name: "chat",
|
||||
component: () => import("../views/chat/index.vue"),
|
||||
meta: { requiresInit: true }
|
||||
},
|
||||
{
|
||||
path: "settings",
|
||||
name: "settings",
|
||||
component: () => import("../views/settings/Settings.vue"),
|
||||
meta: { requiresInit: true }
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
// 路由守卫:检查系统初始化状态
|
||||
router.beforeEach(async (to, from, next) => {
|
||||
// 如果访问的是初始化页面,直接放行
|
||||
if (to.meta.requiresInit === false) {
|
||||
next();
|
||||
return;
|
||||
}
|
||||
|
||||
1
|
||||
|
||||
try {
|
||||
// 检查系统是否已初始化
|
||||
const { initialized } = await checkInitializationStatus();
|
||||
|
||||
if (initialized) {
|
||||
// 系统已初始化,记录到本地存储并正常跳转
|
||||
localStorage.setItem('system_initialized', 'true');
|
||||
next();
|
||||
} else {
|
||||
// 系统未初始化,跳转到初始化页面
|
||||
console.log('系统未初始化,跳转到初始化页面');
|
||||
next('/initialization');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('检查初始化状态失败:', error);
|
||||
// 如果检查失败,默认认为需要初始化
|
||||
next('/initialization');
|
||||
}
|
||||
});
|
||||
|
||||
export default router
|
||||
|
||||
2626
frontend/src/views/initialization/InitializationConfig.vue
Normal file
2626
frontend/src/views/initialization/InitializationConfig.vue
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user