Browse Source

all

yangrongze
hanyuqing 3 months ago
parent
commit
883e54860e
  1. 34
      controller/GraphController.py
  2. 41
      util/neo4j_utils.py
  3. 15
      vue/src/api/builder.js
  4. 8
      vue/src/system/GraphBuilder.vue

34
controller/GraphController.py

@ -1,6 +1,9 @@
import json import json
import sys import sys
from datetime import datetime from datetime import datetime
import httpx
from app import app from app import app
from robyn import Robyn, jsonify, Response from robyn import Robyn, jsonify, Response
@ -74,7 +77,6 @@ def get_data():
direction="both", direction="both",
rel_type=None rel_type=None
) )
return Response( return Response(
status_code=200, status_code=200,
description=jsonify(graph_data), description=jsonify(graph_data),
@ -205,3 +207,33 @@ def health():
print(redis_get(DRUG_TREE_KEY)) print(redis_get(DRUG_TREE_KEY))
print(redis_get(CHECK_TREE_KEY)) print(redis_get(CHECK_TREE_KEY))
return {"status": "ok", "drug_cached": redis_get(DRUG_TREE_KEY) is not None} return {"status": "ok", "drug_cached": redis_get(DRUG_TREE_KEY) is not None}
@app.post("/api/analyze")
async def analyze(request):
try:
# 假设前端传入 JSON: {"text": "病例文本..."}
body = request.json()
input_text = body.get("text", "").strip()
if not input_text:
return jsonify({"error": "缺少 text 字段"}), 400
client = httpx.AsyncClient(base_url="http://192.168.50.113:8088")
# 调用实体关系抽取服务
response = await client.post(
"/extract_entities_and_relations",
json={"text": input_text}
)
print(response)
if response.status_code == 200:
result = response.json()
return jsonify(result)
else:
return jsonify({
"error": "实体抽取服务返回错误",
"status": response.status_code,
"detail": response.text
}), response.status_code
except Exception as e:
return jsonify({"error": str(e)}), 500

41
util/neo4j_utils.py

@ -1,4 +1,5 @@
# neo4j_util.py # neo4j_util.py
import traceback
from datetime import datetime from datetime import datetime
import logging import logging
from typing import Dict, List, Optional, Any from typing import Dict, List, Optional, Any
@ -263,7 +264,7 @@ class Neo4jUtil:
node_properties: Dict[str, Any], node_properties: Dict[str, Any],
direction: str = "both", direction: str = "both",
rel_type: Optional[str] = None, rel_type: Optional[str] = None,
limit: int = 500, # 👈 新增参数,默认 1000 limit: int = 2000, # 👈 新增参数,默认 1000
) -> List[Dict[str, Any]]: ) -> List[Dict[str, Any]]:
""" """
查询指定节点的邻居最多返回 limit 查询指定节点的邻居最多返回 limit
@ -288,17 +289,19 @@ class Neo4jUtil:
else: else:
raise ValueError("direction 必须是 'out', 'in''both'") raise ValueError("direction 必须是 'out', 'in''both'")
# ✅ 添加 LIMIT
cypher = f""" cypher = f"""
MATCH {pattern} MATCH {pattern}
WHERE {where_clause} WHERE {where_clause}
WITH r, startNode(r) AS s, endNode(r) AS t
RETURN RETURN
elementId(n) AS sourceId, elementId(s) AS sourceId,
head(labels(n)) AS sourceLabel, head(labels(s)) AS sourceLabel,
n{{.*}} AS sourceProps, s{{.*}} AS sourceProps,
elementId(m) AS targetId,
head(labels(m)) AS targetLabel, elementId(t) AS targetId,
m{{.*}} AS targetProps, head(labels(t)) AS targetLabel,
t{{.*}} AS targetProps,
elementId(r) AS relId, elementId(r) AS relId,
type(r) AS relType, type(r) AS relType,
r{{.*}} AS relProps r{{.*}} AS relProps
@ -306,28 +309,38 @@ class Neo4jUtil:
""" """
params["limit"] = limit # 注入 limit 参数(安全) params["limit"] = limit # 注入 limit 参数(安全)
raw_results = self.execute_read(cypher, params) # ✅ 安全执行查询
try:
raw_results = self.execute_read(cypher, params)
except Exception as e:
# 可选:记录原始错误(如果你有 logger)
# self.logger.error(f"Neo4j 查询失败: {str(e)}\nCypher: {cypher}\nParams: {params}")
traceback.print_exc() # 这会打印完整的 traceback 到 stderr
# 抛出更友好的运行时错误
raise RuntimeError(
f"查询邻居节点时发生数据库错误: {str(e)}"
) from e # 使用 'from e' 保留原始异常链
print(raw_results)
neighbors = [] neighbors = []
print("Ssssssssss")
print(len(raw_results))
for row in raw_results: for row in raw_results:
source = dict(row["sourceProps"]) source = dict(row["sourceProps"])
source.update({"id": row["sourceId"], "label": row["sourceLabel"]}) source.update({"id": row["sourceId"], "label": row["sourceLabel"]})
target = dict(row["targetProps"]) target = dict(row["targetProps"])
target.update({"id": row["targetId"], "label": row["targetLabel"]}) target.update({"id": row["targetId"], "label": row["targetLabel"]})
relationship = { relationship = {
"id": row["relId"], "id": row["relId"],
"type": row["relType"], "type": row["relType"],
"properties": dict(row["relProps"]) if row["relProps"] else {} "properties": dict(row["relProps"]) if row["relProps"] else {}
} }
neighbors.append({ neighbors.append({
"source": source, "source": source,
"target": target, "target": target,
"relationship": relationship "relationship": relationship
}) })
print(relationship)
print(neighbors)
return neighbors return neighbors
# def find_neighbors_with_relationships( # def find_neighbors_with_relationships(
# self, # self,

15
vue/src/api/builder.js

@ -0,0 +1,15 @@
// src/api/graph.js
import request from '@/utils/request';
/**
* 获取测试图谱数据固定返回 Disease 及其所有关系
* 后端接口GET /test 无参数
*/
export function analyze(data) {
return request({
url: '/api/analyze',
method: 'post',
data
});
}

8
vue/src/system/GraphBuilder.vue

@ -59,6 +59,8 @@
<script> <script>
import Menu from "@/components/Menu.vue"; import Menu from "@/components/Menu.vue";
import axios from "axios";
import {analyze} from "@/api/builder";
export default { export default {
name: 'QwenChat', name: 'QwenChat',
@ -75,11 +77,13 @@ export default {
sendMessage() { sendMessage() {
const text = this.inputText.trim(); const text = this.inputText.trim();
if (!text) return; if (!text) return;
let data={
"text":text
}
analyze(data)
// //
this.messages.push({ role: 'user', content: text }); this.messages.push({ role: 'user', content: text });
this.inputText = ''; this.inputText = '';
// AI API // AI API
setTimeout(() => { setTimeout(() => {
this.messages.push({ this.messages.push({

Loading…
Cancel
Save