diff --git a/scripts/milvus/standalone_embed.sh b/scripts/milvus/standalone_embed.sh new file mode 100644 index 00000000..610f26f8 --- /dev/null +++ b/scripts/milvus/standalone_embed.sh @@ -0,0 +1,143 @@ +#!/usr/bin/env bash + +# Licensed to the LF AI & Data foundation under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +run_embed() { + cat << EOF > embedEtcd.yaml +listen-client-urls: http://0.0.0.0:2379 +advertise-client-urls: http://0.0.0.0:2379 +quota-backend-bytes: 4294967296 +auto-compaction-mode: revision +auto-compaction-retention: '1000' +EOF + + cat << EOF > user.yaml +# Extra config to override default milvus.yaml +EOF + + sudo docker run -d \ + --name milvus-standalone \ + --security-opt seccomp:unconfined \ + -e ETCD_USE_EMBED=true \ + -e ETCD_DATA_DIR=/var/lib/milvus/etcd \ + -e ETCD_CONFIG_PATH=/milvus/configs/embedEtcd.yaml \ + -e COMMON_STORAGETYPE=local \ + -v $(pwd)/volumes/milvus:/var/lib/milvus \ + -v $(pwd)/embedEtcd.yaml:/milvus/configs/embedEtcd.yaml \ + -v $(pwd)/user.yaml:/milvus/configs/user.yaml \ + -p 19530:19530 \ + -p 9091:9091 \ + -p 2379:2379 \ + --health-cmd="curl -f http://localhost:9091/healthz" \ + --health-interval=30s \ + --health-start-period=90s \ + --health-timeout=20s \ + --health-retries=3 \ + milvusdb/milvus:v2.4.5 \ + milvus run standalone 1> /dev/null +} + +wait_for_milvus_running() { + echo "Wait for Milvus Starting..." + while true + do + res=`sudo docker ps|grep milvus-standalone|grep healthy|wc -l` + if [ $res -eq 1 ] + then + echo "Start successfully." + echo "To change the default Milvus configuration, add your settings to the user.yaml file and then restart the service." + break + fi + sleep 1 + done +} + +start() { + res=`sudo docker ps|grep milvus-standalone|grep healthy|wc -l` + if [ $res -eq 1 ] + then + echo "Milvus is running." + exit 0 + fi + + res=`sudo docker ps -a|grep milvus-standalone|wc -l` + if [ $res -eq 1 ] + then + sudo docker start milvus-standalone 1> /dev/null + else + run_embed + fi + + if [ $? -ne 0 ] + then + echo "Start failed." + exit 1 + fi + + wait_for_milvus_running +} + +stop() { + sudo docker stop milvus-standalone 1> /dev/null + + if [ $? -ne 0 ] + then + echo "Stop failed." + exit 1 + fi + echo "Stop successfully." + +} + +delete() { + res=`sudo docker ps|grep milvus-standalone|wc -l` + if [ $res -eq 1 ] + then + echo "Please stop Milvus service before delete." + exit 1 + fi + sudo docker rm milvus-standalone 1> /dev/null + if [ $? -ne 0 ] + then + echo "Delete failed." + exit 1 + fi + sudo rm -rf $(pwd)/volumes + sudo rm -rf $(pwd)/embedEtcd.yaml + sudo rm -rf $(pwd)/user.yaml + echo "Delete successfully." +} + + +case $1 in + restart) + stop + start + ;; + start) + start + ;; + stop) + stop + ;; + delete) + delete + ;; + *) + echo "please use bash standalone_embed.sh restart|start|stop|delete" + ;; +esac \ No newline at end of file diff --git a/src/core/database.py b/src/core/database.py index 629b5912..ac7ec9b4 100644 --- a/src/core/database.py +++ b/src/core/database.py @@ -64,6 +64,7 @@ class DataBaseManager: def get_databases(self): self._update_database() + assert self.config.enable_knowledge_base, "知识库未启用" knowledge_base_collections = self.knowledge_base.get_collection_names() if len(self.data["databases"]) != len(knowledge_base_collections): logger.warning(f"Database number not match, {knowledge_base_collections}") diff --git a/src/main.py b/src/main.py new file mode 100644 index 00000000..abb36f33 --- /dev/null +++ b/src/main.py @@ -0,0 +1,32 @@ +import uvicorn +from dotenv import load_dotenv +from fastapi import FastAPI +from fastapi.middleware.cors import CORSMiddleware +from src.routers import router +from src.utils.logging_config import setup_logger + +load_dotenv() + +import os + +os.environ["ZHIPUAI_API_KEY"] = "270ea71e9560c0ff406acbcdd48bfd97.e3XOMdWKuZb7Q1Sk" + +app = FastAPI() +app.include_router(router) + +# CORS 设置 +app.add_middleware( + CORSMiddleware, + allow_origins=["*"], + allow_credentials=True, + allow_methods=["*"], + allow_headers=["*"], +) + + +logger = setup_logger("server:main") + + +if __name__ == "__main__": + uvicorn.run(app, host="0.0.0.0", port=5000) + diff --git a/src/models/chat_model.py b/src/models/chat_model.py index 02e3a6d9..b387d8bb 100644 --- a/src/models/chat_model.py +++ b/src/models/chat_model.py @@ -58,7 +58,7 @@ class DeepSeek(OpenAIBase): class Zhipu(OpenAIBase): def __init__(self, model_name=None): model_name = model_name or "glm-4-flash" - api_key = os.getenv("ZHIPUAI_API_KEY") + api_key = os.getenv("ZHIPUAI_API_KEY", "270ea71e9560c0ff406acbcdd48bfd97.e3XOMdWKuZb7Q1Sk") base_url = "https://open.bigmodel.cn/api/paas/v4/" super().__init__(api_key=api_key, base_url=base_url, model_name=model_name) diff --git a/src/routers/__init__.py b/src/routers/__init__.py new file mode 100644 index 00000000..c39810cd --- /dev/null +++ b/src/routers/__init__.py @@ -0,0 +1,11 @@ +from fastapi import APIRouter +from src.routers.chat_router import chat +from src.routers.data_router import data +from src.routers.base_router import base +from src.routers.tool_router import tool + +router = APIRouter() +router.include_router(base) +router.include_router(chat) +router.include_router(data) +router.include_router(tool) diff --git a/src/routers/base_router.py b/src/routers/base_router.py new file mode 100644 index 00000000..dda125a5 --- /dev/null +++ b/src/routers/base_router.py @@ -0,0 +1,45 @@ +from fastapi import APIRouter + +base = APIRouter() + +from fastapi import FastAPI, HTTPException +from fastapi.responses import JSONResponse +from fastapi import Request +from src.core import HistoryManager +from src.utils.logging_config import setup_logger +from src.core.startup import startup + +logger = setup_logger("server-base") + +@base.get("/") +async def route_index(): + return {"message": "You Got It!"} + +@base.get("/config") +async def get_config(): + return startup.config + +@base.post("/config") +async def update_config(request: Request): + request_data = await request.json() + startup.config.update(request_data) + startup.config.save() + return startup.config + +@base.post("/restart") +async def restart(): + startup.restart() + return {"message": "Restarted!"} + +@base.get("/log") +async def get_log(): + from src.utils.logging_config import LOG_FILE + from collections import deque + + with open(LOG_FILE, 'r') as f: + last_lines = deque(f, maxlen=1000) + + log = ''.join(last_lines) + return {"log": log} + + diff --git a/src/routers/chat_router.py b/src/routers/chat_router.py new file mode 100644 index 00000000..d6dcc0d5 --- /dev/null +++ b/src/routers/chat_router.py @@ -0,0 +1,55 @@ +from fastapi import APIRouter, HTTPException, Request +from fastapi.responses import StreamingResponse +import json +from src.core import HistoryManager +from src.core.startup import startup +from src.utils.logging_config import setup_logger + +chat = APIRouter(prefix="/chat") +logger = setup_logger("server-chat") + +@chat.get("/") +async def chat_get(): + return "Chat Get!" + +@chat.post("/") +async def chat_post(request: Request): + request_data = await request.json() + query = request_data['query'] + meta = request_data.get('meta') + history_manager = HistoryManager(request_data['history']) + + new_query, refs = startup.retriever(query, history_manager.messages, meta) + + messages = history_manager.get_history_with_msg(new_query, max_rounds=meta.get('history_round')) + history_manager.add_user(query) + logger.debug(f"Web history: {history_manager.messages}") + + async def generate_response(): + content = "" + for delta in startup.model.predict(messages, stream=True): + if not delta.content: + continue + + if hasattr(delta, 'is_full') and delta.is_full: + content = delta.content + else: + content += delta.content + + response_chunk = json.dumps({ + "history": history_manager.update_ai(content), + "response": content, + "refs": refs # TODO: 优化 refs,不需要每次都返回 + }, ensure_ascii=False).encode('utf8') + b'\n' + yield response_chunk + + return StreamingResponse(generate_response(), media_type='application/json') + +@chat.post("/call") +async def call(request: Request): + request_data = await request.json() + query = request_data['query'] + response = startup.model.predict(query) + logger.debug({"query": query, "response": response.content}) + + return {"response": response.content} \ No newline at end of file diff --git a/src/routers/data_router.py b/src/routers/data_router.py new file mode 100644 index 00000000..98776c7b --- /dev/null +++ b/src/routers/data_router.py @@ -0,0 +1,120 @@ +import os +from typing import List, Optional +from fastapi import APIRouter, File, UploadFile, HTTPException, Depends, Body +from pydantic import BaseModel + +from src.utils import setup_logger, hashstr +from src.core.startup import startup + +data = APIRouter(prefix="/data") + +logger = setup_logger("server-database") + +@data.get("/") +async def get_databases(): + try: + database = startup.dbm.get_databases() + except Exception as e: + return {"message": f"获取数据库列表失败 {e}", "databases": []} + return database + +@data.post("/") +async def create_database( + database_name: str = Body(...), + description: str = Body(...), + db_type: str = Body(...), + dimension: int = Body(None) +): + logger.debug(f"Create database {database_name}") + database_info = startup.dbm.create_database( + database_name, + description, + db_type, + dimension=dimension + ) + return database_info + +@data.delete("/") +async def delete_database(db_id: str = Body(...)): + logger.debug(f"Delete database {db_id}") + startup.dbm.delete_database(db_id) + return {"message": "删除成功"} + +@data.post("/query-test") +async def query_test(query: str = Body(...), meta: dict = Body(...)): + logger.debug(f"Query test in {meta}: {query}") + result = startup.retriever.query_knowledgebase(query, history=None, refs={"meta": meta}) + return result + +@data.post("/add-by-file") +async def create_document_by_file(db_id: str = Body(...), files: List[str] = Body(...)): + logger.debug(f"Add document in {db_id} by file: {files}") + msg = startup.dbm.add_files(db_id, files) + return msg + +@data.get("/database-info") +async def get_database_info(db_id: str): + logger.debug(f"Get database {db_id} info") + database = startup.dbm.get_database_info(db_id) + if database is None: + raise HTTPException(status_code=404, detail="Database not found") + return database + +@data.delete("/document") +async def delete_document(db_id: str = Body(...), file_id: str = Body(...)): + logger.debug(f"DELETE document {file_id} info in {db_id}") + startup.dbm.delete_file(db_id, file_id) + return {"message": "删除成功"} + +@data.get("/document") +async def get_document_info(db_id: str, file_id: str): + logger.debug(f"GET document {file_id} info in {db_id}") + info = startup.dbm.get_file_info(db_id, file_id) + return info + +@data.post("/upload") +async def upload_file(file: UploadFile = File(...)): + if not file.filename: + raise HTTPException(status_code=400, detail="No selected file") + + upload_dir = os.path.join(startup.config.save_dir, "data/uploads") + os.makedirs(upload_dir, exist_ok=True) + filename = f"{hashstr(file.filename, 4, with_salt=True)}_{file.filename}".lower() + file_path = os.path.join(upload_dir, filename) + + with open(file_path, "wb") as buffer: + buffer.write(await file.read()) + + return {"message": "File successfully uploaded", "file_path": file_path} + +@data.get("/graph") +async def get_graph_info(): + graph_info = startup.dbm.get_graph() + return graph_info + +@data.get("/graph/node") +async def get_graph_node(entity_name: str): + logger.debug(f"Get graph node {entity_name}") + result = startup.dbm.graph_base.query_node(entity_name=entity_name) + return {"result": startup.retriever.format_query_results(result), "message": "success"} + +@data.get("/graph/nodes") +async def get_graph_nodes(kgdb_name: str, num: int): + if not startup.config.enable_knowledge_graph: + raise HTTPException(status_code=400, detail="Knowledge graph is not enabled") + + logger.debug(f"Get graph nodes in {kgdb_name} with {num} nodes") + result = startup.dbm.graph_base.get_sample_nodes(kgdb_name, num) + return {"result": startup.retriever.format_general_results(result), "message": "success"} + +@data.post("/graph/add") +async def add_graph_entity(kgdb_name: str = Body(...), file_path: str = Body(...)): + if not startup.config.enable_knowledge_graph: + raise HTTPException(status_code=400, detail="Knowledge graph is not enabled") + + if not file_path.endswith('.jsonl'): + raise HTTPException(status_code=400, detail="file_path must be a jsonl file") + + startup.dbm.graph_base.jsonl_file_add_entity(file_path, kgdb_name) + return {"message": "Entity successfully added"} + diff --git a/src/routers/tool_router.py b/src/routers/tool_router.py new file mode 100644 index 00000000..6732fed9 --- /dev/null +++ b/src/routers/tool_router.py @@ -0,0 +1,50 @@ +import os +from fastapi import APIRouter, Body +from pydantic import BaseModel +from typing import List, Dict, Any, Optional + +from src.utils import setup_logger + +tool = APIRouter(prefix="/tool") + +logger = setup_logger("server-tools") + +class Tool(BaseModel): + name: str + title: str + description: str + url: str + method: str + +@tool.get("/", response_model=List[Tool]) +async def route_index(): + tools = [ + Tool( + name="text-chunking", + title="文本分块", + description="将文本分块以更好地理解。可以输入文本或者上传文件。", + url="/tools/text-chunking", + method="POST", + ), + Tool( + name="pdf2txt", + title="PDF转文本", + description="将PDF文件转换为文本文件。", + url="/tools/pdf2txt", + method="POST", + ) + ] + + return tools + +@tool.post("/text-chunking") +async def text_chunking(text: str = Body(...), params: Dict[str, Any] = Body(...)): + from src.core.indexing import chunk + nodes = chunk(text, params=params) + return {"nodes": [node.to_dict() for node in nodes]} + +@tool.post("/pdf2txt") +async def handle_pdf2txt(file: str = Body(...)): + from src.plugins import pdf2txt + text = pdf2txt(file, return_text=True) + return {"text": text} diff --git a/web/src/components/ChatComponent.vue b/web/src/components/ChatComponent.vue index 1135ce30..0129ed25 100644 --- a/web/src/components/ChatComponent.vue +++ b/web/src/components/ChatComponent.vue @@ -351,7 +351,7 @@ const updateStatus = (id, status) => { const simpleCall = (message) => { return new Promise((resolve, reject) => { - fetch('/api/call', { + fetch('/api/chat/call', { method: 'POST', body: JSON.stringify({ query: message, }), headers: { 'Content-Type': 'application/json' } @@ -363,7 +363,7 @@ const simpleCall = (message) => { } const loadDatabases = () => { - fetch('/api/database/', { method: "GET", }) + fetch('/api/data/', { method: "GET", }) .then(response => response.json()) .then(data => { console.log(data) @@ -371,63 +371,74 @@ const loadDatabases = () => { }) } -const sendMessage = () => { - const user_input = conv.value.inputText.trim() - if (user_input) { - isStreaming.value = true - appendUserMessage(user_input) - appendAiMessage("", null) - const cur_res_id = conv.value.messages[conv.value.messages.length - 1].id - conv.value.inputText = '' - meta.db_name = opts.databases[meta.selectedKB]?.metaname - fetch('/api/chat', { - method: 'POST', - body: JSON.stringify({ - query: user_input, - history: conv.value.history, - meta: meta - }), - headers: { - 'Content-Type': 'application/json' - } - }).then((response) => {const reader = response.body.getReader() - const decoder = new TextDecoder() - let buffer = '' - // 逐步读取响应文本 - const readChunk = () => { - return reader.read().then(({ done, value }) => { - if (done) { - console.log(conv.value) - console.log('Finished') - updateStatus(cur_res_id, "finished") - isStreaming.value = false - if (conv.value.messages.length === 2) { renameTitle() } - return - } +// 新函数用于处理 fetch 请求 +const fetchChatResponse = (user_input, cur_res_id) => { + fetch('/api/chat', { + method: 'POST', + body: JSON.stringify({ + query: user_input, + history: conv.value.history, + meta: meta + }), + headers: { + 'Content-Type': 'application/json' + } + }).then((response) => { + const reader = response.body.getReader(); + const decoder = new TextDecoder(); + let buffer = ''; - buffer += decoder.decode(value, { stream: true }) - const message = buffer.trim().split('\n').pop() + // 逐步读取响应文本 + const readChunk = () => { + return reader.read().then(({ done, value }) => { + if (done) { + // 处理完成 + updateStatus(cur_res_id, "finished"); + isStreaming.value = false; + if (conv.value.messages.length === 2) { renameTitle(); } + return; // 结束读取 + } + buffer += decoder.decode(value, { stream: true }); + const messages = buffer.trim().split('\n'); + + messages.forEach((message) => { try { - const data = JSON.parse(message) - updateMessage(data.response, cur_res_id, data.refs, "loading") - conv.value.history = data.history - buffer = '' + const data = JSON.parse(message); + updateMessage(data.response, cur_res_id, data.refs, "loading"); + conv.value.history = data.history; } catch (e) { - // console.log(e) + console.error('JSON 解析错误:', e); } - return readChunk() - }) - } - return readChunk() - }) - .catch((error) => { - console.error(error) - updateStatus(cur_res_id, "error") - isStreaming.value = false - }) + }); + buffer = ''; // 清空缓冲区 + return readChunk(); // 继续读取 + }); + }; + return readChunk(); + }) + .catch((error) => { + console.error(error); + updateStatus(cur_res_id, "error"); + isStreaming.value = false; + }); +} + +// 更新后的 sendMessage 函数 +const sendMessage = () => { + const user_input = conv.value.inputText.trim(); + const dbName = opts.databases.length > 0 ? opts.databases[meta.selectedKB]?.metaname : null; + if (user_input) { + isStreaming.value = true; + appendUserMessage(user_input); + appendAiMessage("", null); + const cur_res_id = conv.value.messages[conv.value.messages.length - 1].id; + conv.value.inputText = ''; + meta.db_name = dbName; + + fetchChatResponse(user_input, cur_res_id) } else { - console.log('请输入消息') + console.log('请输入消息'); } } @@ -436,11 +447,6 @@ const autoSend = (message) => { sendMessage() } -// const clearChat = () => { -// conv.value.messages = [] -// conv.value.history = [] -// } - // 从本地存储加载数据 onMounted(() => { scrollToBottom() diff --git a/web/src/components/ConvertToTxtComponent.vue b/web/src/components/ConvertToTxtComponent.vue index a7c87741..589ac7bc 100644 --- a/web/src/components/ConvertToTxtComponent.vue +++ b/web/src/components/ConvertToTxtComponent.vue @@ -15,7 +15,7 @@ name="file" :max-count="1" :disabled="state.uploading" - action="/api/database/upload" + action="/api/data/upload" @change="handleFileUpload" @drop="handleDrop" > @@ -92,7 +92,7 @@ const convertPdfToText = async () => { try { state.loading = true; - const response = await fetch('/api/tools/pdf2txt', { + const response = await fetch('/api/tool/pdf2txt', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ file: file }) diff --git a/web/src/components/TextChunkingComponent.vue b/web/src/components/TextChunkingComponent.vue index f9e46b30..d06c5dfd 100644 --- a/web/src/components/TextChunkingComponent.vue +++ b/web/src/components/TextChunkingComponent.vue @@ -40,7 +40,7 @@ name="file" :max-count="1" :disabled="state.uploading" - action="/api/database/upload" + action="/api/data/upload" @change="handleFileUpload" @drop="handleDrop" > @@ -125,14 +125,16 @@ const chunkText = async () => { try { state.loading = true - const response = await fetch('/api/tools/text_chunking', { + const response = await fetch('/api/tool/text-chunking', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ text: text_or_file, - chunk_size: params.chunkSize, - chunk_overlap: params.chunkOverlap, - use_parser: params.useParser + params: { + chunk_size: params.chunkSize, + chunk_overlap: params.chunkOverlap, + use_parser: params.useParser + } }) }); diff --git a/web/src/layouts/AppLayout.vue b/web/src/layouts/AppLayout.vue index f1f74ca2..5869f7b0 100644 --- a/web/src/layouts/AppLayout.vue +++ b/web/src/layouts/AppLayout.vue @@ -43,7 +43,7 @@ const getRemoteDatabase = () => { if (!configStore.config.enable_knowledge_base) { return } - fetch('/api/database').then(res => res.json()).then(data => { + fetch('/api/data').then(res => res.json()).then(data => { console.log("database", data) databaseStore.setDatabase(data.databases) }) diff --git a/web/src/router/index.js b/web/src/router/index.js index 25b495a6..b0439279 100644 --- a/web/src/router/index.js +++ b/web/src/router/index.js @@ -87,7 +87,7 @@ const router = createRouter({ meta: { keepAlive: true } }, { - path: 'text_chunking', + path: 'text-chunking', name: 'TextChunking', component: () => import('../components/TextChunkingComponent.vue'), }, diff --git a/web/src/views/DataBaseInfoView.vue b/web/src/views/DataBaseInfoView.vue index b2be26f2..c8e33bb9 100644 --- a/web/src/views/DataBaseInfoView.vue +++ b/web/src/views/DataBaseInfoView.vue @@ -32,7 +32,7 @@ name="file" :multiple="true" :disabled="state.loading" - action="/api/database/upload" + action="/api/data/upload" @change="handleFileUpload" @drop="handleDrop" > @@ -300,7 +300,7 @@ const onQuery = () => { return } meta.db_name = database.value.metaname - fetch('/api/database/query-test', { + fetch('/api/data/query-test', { method: "POST", body: JSON.stringify({ query: queryText.value.trim(), @@ -359,7 +359,7 @@ const deleteDatabse = () => { cancelText: '取消', onOk: () => { state.lock = true - fetch('/api/database/', { + fetch('/api/data/', { method: "DELETE", body: JSON.stringify({ db_id: databaseId.value @@ -387,7 +387,7 @@ const deleteDatabse = () => { const openFileDetail = (record) => { state.lock = true - fetch(`/api/database/document?db_id=${databaseId.value}&file_id=${record.file_id}`, { + fetch(`/api/data/document?db_id=${databaseId.value}&file_id=${record.file_id}`, { method: "GET", }) .then(response => response.json()) @@ -427,7 +427,7 @@ const getDatabaseInfo = () => { const db_id = databaseId.value state.lock = true return new Promise((resolve, reject) => { - fetch(`/api/database/info?db_id=${db_id}`, { + fetch(`/api/data/info?db_id=${db_id}`, { method: "GET", }) .then(response => response.json()) @@ -449,7 +449,7 @@ const getDatabaseInfo = () => { const deleteFile = (fileId) => { console.log(fileId) state.lock = true - fetch('/api/database/document', { + fetch('/api/data/document', { method: "DELETE", body: JSON.stringify({ db_id: databaseId.value, @@ -478,7 +478,7 @@ const addDocumentByFile = () => { state.refreshInterval = setInterval(() => { getDatabaseInfo(); }, 1000); - fetch('/api/database/add_by_file', { + fetch('/api/data/add_by_file', { method: "POST", body: JSON.stringify({ db_id: databaseId.value, diff --git a/web/src/views/DataBaseView.vue b/web/src/views/DataBaseView.vue index 98ee15eb..b22b8a22 100644 --- a/web/src/views/DataBaseView.vue +++ b/web/src/views/DataBaseView.vue @@ -111,7 +111,7 @@ const newDatabase = reactive({ const loadDatabases = () => { // loadGraph() - fetch('/api/database/', { + fetch('/api/data/', { method: "GET", }) .then(response => response.json()) @@ -130,7 +130,7 @@ const createDatabase = () => { newDatabase.loading = false return } - fetch('/api/database/', { + fetch('/api/data/', { method: "POST", body: JSON.stringify({ database_name: newDatabase.name, @@ -163,7 +163,7 @@ const navigateToGraph = () => { // const loadGraph = () => { // graphloading.value = true -// fetch('/api/database/graph', { +// fetch('/api/data/graph', { // method: "GET", // }) // .then(response => response.json()) diff --git a/web/src/views/GraphView.vue b/web/src/views/GraphView.vue index 147578fa..0c0362ba 100644 --- a/web/src/views/GraphView.vue +++ b/web/src/views/GraphView.vue @@ -59,7 +59,7 @@ :fileList="fileList" :max-count="1" :disabled="state.precessing" - action="/api/database/upload" + action="/api/data/upload" @change="handleFileUpload" @drop="handleDrop" > @@ -106,7 +106,7 @@ const state = reactive({ const loadGraphInfo = () => { state.loadingGraphInfo = true - fetch('/api/database/graph', { + fetch('/api/data/graph', { method: "GET", }) .then(response => response.json()) @@ -147,7 +147,7 @@ const getGraphData = () => { const addDocumentByFile = () => { state.precessing = true const files = fileList.value.filter(file => file.status === 'done').map(file => file.response.file_path) - fetch('/api/database/graph/add', { + fetch('/api/data/graph/add', { method: 'POST', body: JSON.stringify({ file_path: files[0] @@ -166,7 +166,7 @@ const addDocumentByFile = () => { const loadSampleNodes = () => { state.fetching = true - fetch(`/api/database/graph/nodes?kgdb_name=neo4j&num=${sampleNodeCount.value}`) + fetch(`/api/data/graph/nodes?kgdb_name=neo4j&num=${sampleNodeCount.value}`) .then((res) => { if (res.ok) { return res.json(); @@ -199,7 +199,7 @@ const onSearch = () => { } state.searchLoading = true - fetch(`/api/database/graph/node?entity_name=${state.searchInput}`) + fetch(`/api/data/graph/node?entity_name=${state.searchInput}`) .then((res) => { if (!res.ok) { return res.json().then(errorData => { diff --git a/web/src/views/ToolsView.vue b/web/src/views/ToolsView.vue index 98df0d32..adc15233 100644 --- a/web/src/views/ToolsView.vue +++ b/web/src/views/ToolsView.vue @@ -31,7 +31,7 @@ import HeaderComponent from '@/components/HeaderComponent.vue'; const router = useRouter(); const tools = ref([]); const iconMap = ref({ - "text_chunking": FileSearchOutlined + "text-chunking": FileSearchOutlined }) const state = reactive({ @@ -40,7 +40,7 @@ const state = reactive({ const getTools = () => { state.loadingTools = true - fetch('/api/tools/') + fetch('/api/tool/') .then(response => response.json()) .then(data => { tools.value = data;