From e9e4cf3b1cd6394324fbce903ea34d52f85ae030 Mon Sep 17 00:00:00 2001 From: Jerry Yan <792602257@qq.com> Date: Mon, 23 Feb 2026 01:15:31 +0800 Subject: [PATCH] =?UTF-8?q?fix(kg):=20=E4=BF=AE=E5=A4=8D=E7=9F=A5=E8=AF=86?= =?UTF-8?q?=E5=9B=BE=E8=B0=B1=E9=83=A8=E7=BD=B2=E6=B5=81=E7=A8=8B=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修复从全新部署到运行的完整流程中的配置和路由问题。 ## P0 修复(功能失效) ### P0-1: GraphRAG KG 服务 URL 错误 - config.py - GRAPHRAG_KG_SERVICE_URL 从 http://datamate-kg:8080 改为 http://datamate-backend:8080(容器名修正) - kg_client.py - 修复 API 路径:/knowledge-graph/... → /api/knowledge-graph/... - kb_access.py - 同类问题修复:/knowledge-base/... → /api/knowledge-base/... - test_kb_access.py - 测试断言同步更新 根因:容器名 datamate-kg 不存在,且 httpx 绝对路径会丢弃 base_url 中的 /api 路径 ### P0-2: Vite 开发代理剥离 /api 前缀 - vite.config.ts - 删除 /api/knowledge-graph 专用代理规则(剥离 /api 导致 404),统一走 ^/api 规则 ## P1 修复(功能受损) ### P1-1: Gateway 缺少 KG Python 端点路由 - ApiGatewayApplication.java - 添加 /api/kg/** 路由(指向 kg-extraction Python 服务) - ApiGatewayApplication.java - 添加 /api/graphrag/** 路由(指向 GraphRAG 服务) ### P1-2: DATA_MANAGEMENT_URL 默认值缺 /api - KnowledgeGraphProperties.java - dataManagementUrl 默认值 http://localhost:8080 → http://localhost:8080/api - KnowledgeGraphProperties.java - annotationServiceUrl 默认值 http://localhost:8081 → http://localhost:8080/api(同 JVM) - application-knowledgegraph.yml - YAML 默认值同步更新 ### P1-3: Neo4j k8s 安装链路失败 - Makefile - VALID_K8S_TARGETS 添加 neo4j - Makefile - %-k8s-install 添加 neo4j case(显式 skip,提示使用 Docker 或外部实例) - Makefile - %-k8s-uninstall 添加 neo4j case(显式 skip) 根因:install 目标无条件调用 neo4j-$(INSTALLER)-install,但 k8s 模式下 neo4j 不在 VALID_K8S_TARGETS 中,导致 "Unknown k8s target 'neo4j'" 错误 ## P2 修复(次要) ### P2-1: Neo4j 加入 Docker install 流程 - Makefile - install target 增加 neo4j-$(INSTALLER)-install,在 datamate 之前启动 - Makefile - VALID_SERVICE_TARGETS 增加 neo4j - Makefile - %-docker-install / %-docker-uninstall 增加 neo4j case ## 验证结果 - mvn test: 311 tests, 0 failures ✅ - eslint: 0 errors ✅ - tsc --noEmit: 通过 ✅ - vite build: 成功 (17.71s) ✅ - Python tests: 46 passed ✅ - make -n install INSTALLER=k8s: 不再报 unknown target ✅ - make -n neo4j-k8s-install: 正确显示 skip 消息 ✅ --- Makefile | 24 +++++++++++++++---- .../gateway/ApiGatewayApplication.java | 8 +++++++ .../neo4j/KnowledgeGraphProperties.java | 4 ++-- .../resources/application-knowledgegraph.yml | 4 ++-- frontend/vite.config.ts | 6 ----- runtime/datamate-python/app/core/config.py | 2 +- .../app/module/kg_graphrag/kb_access.py | 2 +- .../app/module/kg_graphrag/kg_client.py | 6 ++--- .../app/module/kg_graphrag/test_kb_access.py | 2 +- 9 files changed, 37 insertions(+), 21 deletions(-) diff --git a/Makefile b/Makefile index b0962fa..fa210fa 100644 --- a/Makefile +++ b/Makefile @@ -211,8 +211,9 @@ endif .PHONY: install install: ifeq ($(origin INSTALLER), undefined) - $(call prompt-installer,datamate-$$INSTALLER-install milvus-$$INSTALLER-install) + $(call prompt-installer,neo4j-$$INSTALLER-install datamate-$$INSTALLER-install milvus-$$INSTALLER-install) else + $(MAKE) neo4j-$(INSTALLER)-install $(MAKE) datamate-$(INSTALLER)-install $(MAKE) milvus-$(INSTALLER)-install endif @@ -240,6 +241,7 @@ else fi @$(MAKE) label-studio-$(INSTALLER)-uninstall DELETE_VOLUMES_CHOICE=$$DELETE_VOLUMES_CHOICE; \ $(MAKE) milvus-$(INSTALLER)-uninstall DELETE_VOLUMES_CHOICE=$$DELETE_VOLUMES_CHOICE; \ + $(MAKE) neo4j-$(INSTALLER)-uninstall DELETE_VOLUMES_CHOICE=$$DELETE_VOLUMES_CHOICE; \ $(MAKE) deer-flow-$(INSTALLER)-uninstall DELETE_VOLUMES_CHOICE=$$DELETE_VOLUMES_CHOICE; \ $(MAKE) datamate-$(INSTALLER)-uninstall DELETE_VOLUMES_CHOICE=$$DELETE_VOLUMES_CHOICE endif @@ -247,7 +249,7 @@ endif # ========== Docker Install/Uninstall Targets ========== # Valid service targets for docker install/uninstall -VALID_SERVICE_TARGETS := datamate backend frontend runtime mineru "deer-flow" milvus "label-studio" "data-juicer" dj +VALID_SERVICE_TARGETS := datamate backend frontend runtime mineru "deer-flow" milvus neo4j "label-studio" "data-juicer" dj # Generic docker service install target .PHONY: %-docker-install @@ -272,6 +274,8 @@ VALID_SERVICE_TARGETS := datamate backend frontend runtime mineru "deer-flow" mi REGISTRY=$(REGISTRY) docker compose -f deployment/docker/deer-flow/docker-compose.yml up -d; \ elif [ "$*" = "milvus" ]; then \ docker compose -f deployment/docker/milvus/docker-compose.yml up -d; \ + elif [ "$*" = "neo4j" ]; then \ + docker compose -f deployment/docker/neo4j/docker-compose.yml up -d; \ elif [ "$*" = "data-juicer" ] || [ "$*" = "dj" ]; then \ REGISTRY=$(REGISTRY) && docker compose -f deployment/docker/datamate/docker-compose.yml up -d datamate-data-juicer; \ else \ @@ -311,6 +315,12 @@ VALID_SERVICE_TARGETS := datamate backend frontend runtime mineru "deer-flow" mi else \ docker compose -f deployment/docker/milvus/docker-compose.yml down; \ fi; \ + elif [ "$*" = "neo4j" ]; then \ + if [ "$(DELETE_VOLUMES_CHOICE)" = "1" ]; then \ + docker compose -f deployment/docker/neo4j/docker-compose.yml down -v; \ + else \ + docker compose -f deployment/docker/neo4j/docker-compose.yml down; \ + fi; \ elif [ "$*" = "data-juicer" ] || [ "$*" = "dj" ]; then \ $(call docker-compose-service,datamate-data-juicer,down,deployment/docker/datamate); \ else \ @@ -320,7 +330,7 @@ VALID_SERVICE_TARGETS := datamate backend frontend runtime mineru "deer-flow" mi # ========== Kubernetes Install/Uninstall Targets ========== # Valid k8s targets -VALID_K8S_TARGETS := mineru datamate deer-flow milvus label-studio data-juicer dj +VALID_K8S_TARGETS := mineru datamate deer-flow milvus neo4j label-studio data-juicer dj # Generic k8s install target .PHONY: %-k8s-install @@ -333,7 +343,9 @@ VALID_K8S_TARGETS := mineru datamate deer-flow milvus label-studio data-juicer d done; \ exit 1; \ fi - @if [ "$*" = "label-studio" ]; then \ + @if [ "$*" = "neo4j" ]; then \ + echo "Skipping Neo4j: no Helm chart available. Use 'make neo4j-docker-install' or provide an external Neo4j instance."; \ + elif [ "$*" = "label-studio" ]; then \ helm upgrade label-studio deployment/helm/label-studio/ -n $(NAMESPACE) --install; \ elif [ "$*" = "mineru" ]; then \ kubectl apply -f deployment/kubernetes/mineru/deploy.yaml -n $(NAMESPACE); \ @@ -362,7 +374,9 @@ VALID_K8S_TARGETS := mineru datamate deer-flow milvus label-studio data-juicer d done; \ exit 1; \ fi - @if [ "$*" = "mineru" ]; then \ + @if [ "$*" = "neo4j" ]; then \ + echo "Skipping Neo4j: no Helm chart available. Use 'make neo4j-docker-uninstall' or manage your external Neo4j instance."; \ + elif [ "$*" = "mineru" ]; then \ kubectl delete -f deployment/kubernetes/mineru/deploy.yaml -n $(NAMESPACE); \ elif [ "$*" = "datamate" ]; then \ helm uninstall datamate -n $(NAMESPACE) --ignore-not-found; \ diff --git a/backend/api-gateway/src/main/java/com/datamate/gateway/ApiGatewayApplication.java b/backend/api-gateway/src/main/java/com/datamate/gateway/ApiGatewayApplication.java index caac81e..02ceb2f 100644 --- a/backend/api-gateway/src/main/java/com/datamate/gateway/ApiGatewayApplication.java +++ b/backend/api-gateway/src/main/java/com/datamate/gateway/ApiGatewayApplication.java @@ -37,6 +37,14 @@ public class ApiGatewayApplication { .route("data-collection", r -> r.path("/api/data-collection/**") .uri("http://datamate-backend-python:18000")) + // 知识图谱抽取服务路由 + .route("kg-extraction", r -> r.path("/api/kg/**") + .uri("http://datamate-backend-python:18000")) + + // GraphRAG 融合查询服务路由 + .route("graphrag", r -> r.path("/api/graphrag/**") + .uri("http://datamate-backend-python:18000")) + .route("deer-flow-frontend", r -> r.path("/chat/**") .uri("http://deer-flow-frontend:3000")) diff --git a/backend/services/knowledge-graph-service/src/main/java/com/datamate/knowledgegraph/infrastructure/neo4j/KnowledgeGraphProperties.java b/backend/services/knowledge-graph-service/src/main/java/com/datamate/knowledgegraph/infrastructure/neo4j/KnowledgeGraphProperties.java index 94f91f2..748c7ec 100644 --- a/backend/services/knowledge-graph-service/src/main/java/com/datamate/knowledgegraph/infrastructure/neo4j/KnowledgeGraphProperties.java +++ b/backend/services/knowledge-graph-service/src/main/java/com/datamate/knowledgegraph/infrastructure/neo4j/KnowledgeGraphProperties.java @@ -57,10 +57,10 @@ public class KnowledgeGraphProperties { public static class Sync { /** 数据管理服务基础 URL */ - private String dataManagementUrl = "http://localhost:8080"; + private String dataManagementUrl = "http://localhost:8080/api"; /** 标注服务基础 URL */ - private String annotationServiceUrl = "http://localhost:8081"; + private String annotationServiceUrl = "http://localhost:8080/api"; /** 同步每页拉取数量 */ private int pageSize = 200; diff --git a/backend/services/knowledge-graph-service/src/main/resources/application-knowledgegraph.yml b/backend/services/knowledge-graph-service/src/main/resources/application-knowledgegraph.yml index 6c17c05..a8da529 100644 --- a/backend/services/knowledge-graph-service/src/main/resources/application-knowledgegraph.yml +++ b/backend/services/knowledge-graph-service/src/main/resources/application-knowledgegraph.yml @@ -47,9 +47,9 @@ datamate: # MySQL → Neo4j 同步配置 sync: # 数据管理服务地址 - data-management-url: ${DATA_MANAGEMENT_URL:http://localhost:8080} + data-management-url: ${DATA_MANAGEMENT_URL:http://localhost:8080/api} # 标注服务地址 - annotation-service-url: ${ANNOTATION_SERVICE_URL:http://localhost:8081} + annotation-service-url: ${ANNOTATION_SERVICE_URL:http://localhost:8080/api} # 每页拉取数量 page-size: ${KG_SYNC_PAGE_SIZE:200} # HTTP 连接超时(毫秒) diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts index f3b5013..3735b4c 100644 --- a/frontend/vite.config.ts +++ b/frontend/vite.config.ts @@ -18,12 +18,6 @@ export default defineConfig({ // "Origin, X-Requested-With, Content-Type, Accept", // }, proxy: { - "/api/knowledge-graph": { - target: "http://localhost:8080", - changeOrigin: true, - secure: false, - rewrite: (path) => path.replace(/^\/api/, ""), - }, "^/api": { target: "http://localhost:8080", // 本地后端服务地址 changeOrigin: true, diff --git a/runtime/datamate-python/app/core/config.py b/runtime/datamate-python/app/core/config.py index ed5210a..4c1f264 100644 --- a/runtime/datamate-python/app/core/config.py +++ b/runtime/datamate-python/app/core/config.py @@ -91,7 +91,7 @@ class Settings(BaseSettings): # GraphRAG 融合查询配置 graphrag_enabled: bool = False graphrag_milvus_uri: str = "http://milvus-standalone:19530" - graphrag_kg_service_url: str = "http://datamate-kg:8080" + graphrag_kg_service_url: str = "http://datamate-backend:8080" graphrag_kg_internal_token: str = "" # GraphRAG - 检索策略默认值 diff --git a/runtime/datamate-python/app/module/kg_graphrag/kb_access.py b/runtime/datamate-python/app/module/kg_graphrag/kb_access.py index 0a100f2..12aa52a 100644 --- a/runtime/datamate-python/app/module/kg_graphrag/kb_access.py +++ b/runtime/datamate-python/app/module/kg_graphrag/kb_access.py @@ -69,7 +69,7 @@ class KnowledgeBaseAccessValidator: try: client = self._get_client() resp = await client.get( - f"/knowledge-base/{knowledge_base_id}", + f"/api/knowledge-base/{knowledge_base_id}", headers={"X-User-Id": user_id}, ) if resp.status_code == 200: diff --git a/runtime/datamate-python/app/module/kg_graphrag/kg_client.py b/runtime/datamate-python/app/module/kg_graphrag/kg_client.py index f47f047..4107848 100644 --- a/runtime/datamate-python/app/module/kg_graphrag/kg_client.py +++ b/runtime/datamate-python/app/module/kg_graphrag/kg_client.py @@ -23,7 +23,7 @@ class KGServiceClient: def __init__( self, *, - base_url: str = "http://datamate-kg:8080", + base_url: str = "http://datamate-backend:8080", internal_token: str = "", timeout: float = 30.0, ) -> None: @@ -95,7 +95,7 @@ class KGServiceClient: ) -> list[EntitySummary]: client = self._get_client() resp = await client.get( - f"/knowledge-graph/{graph_id}/query/search", + f"/api/knowledge-graph/{graph_id}/query/search", params={"q": query, "size": size}, headers=self._headers(user_id), ) @@ -159,7 +159,7 @@ class KGServiceClient: ) -> tuple[list[EntitySummary], list[RelationSummary]]: client = self._get_client() resp = await client.post( - f"/knowledge-graph/{graph_id}/query/subgraph/export", + f"/api/knowledge-graph/{graph_id}/query/subgraph/export", params={"depth": depth}, json={"entityIds": entity_ids}, headers=self._headers(user_id), diff --git a/runtime/datamate-python/app/module/kg_graphrag/test_kb_access.py b/runtime/datamate-python/app/module/kg_graphrag/test_kb_access.py index 8c85122..8300676 100644 --- a/runtime/datamate-python/app/module/kg_graphrag/test_kb_access.py +++ b/runtime/datamate-python/app/module/kg_graphrag/test_kb_access.py @@ -148,7 +148,7 @@ class TestCheckAccess: _run(validator.check_access("kb-123", "user-456")) call_kwargs = mock_http.get.call_args - assert "/knowledge-base/kb-123" in call_kwargs.args[0] + assert "/api/knowledge-base/kb-123" in call_kwargs.args[0] assert call_kwargs.kwargs["headers"]["X-User-Id"] == "user-456" def test_cross_user_access_denied(self, validator: KnowledgeBaseAccessValidator):