2025-07-22 17:29:38 +08:00
|
|
|
|
import { apiGet, apiPost } from './base'
|
2025-06-30 22:29:23 +08:00
|
|
|
|
|
|
|
|
|
|
/**
|
2025-07-22 17:29:38 +08:00
|
|
|
|
* 图数据库API模块
|
|
|
|
|
|
* 包含LightRAG图知识库和Neo4j图数据库两种接口
|
|
|
|
|
|
* 采用命名空间分组模式,清晰区分接口类型
|
2025-06-30 22:29:23 +08:00
|
|
|
|
*/
|
|
|
|
|
|
|
2025-07-22 17:29:38 +08:00
|
|
|
|
// =============================================================================
|
2025-12-15 23:25:56 +08:00
|
|
|
|
// === 统一图谱接口 (Unified Graph API) ===
|
2025-07-22 17:29:38 +08:00
|
|
|
|
// =============================================================================
|
|
|
|
|
|
|
2025-12-15 23:25:56 +08:00
|
|
|
|
export const unifiedApi = {
|
2025-07-22 17:29:38 +08:00
|
|
|
|
/**
|
2025-12-15 23:25:56 +08:00
|
|
|
|
* 获取所有可用的知识图谱列表
|
|
|
|
|
|
* @returns {Promise} - 图谱列表
|
|
|
|
|
|
*/
|
|
|
|
|
|
getGraphs: async () => {
|
|
|
|
|
|
return await apiGet('/api/graph/list', {}, true)
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取子图数据 (统一接口)
|
2025-07-22 17:29:38 +08:00
|
|
|
|
* @param {Object} params - 查询参数
|
2025-12-15 23:25:56 +08:00
|
|
|
|
* @param {string} params.db_id - 图谱ID
|
|
|
|
|
|
* @param {string} params.node_label - 节点标签/关键词
|
2025-07-22 17:29:38 +08:00
|
|
|
|
* @param {number} params.max_depth - 最大深度
|
|
|
|
|
|
* @param {number} params.max_nodes - 最大节点数
|
|
|
|
|
|
* @returns {Promise} - 子图数据
|
|
|
|
|
|
*/
|
|
|
|
|
|
getSubgraph: async (params) => {
|
2026-01-15 06:01:34 +08:00
|
|
|
|
const { db_id, node_label = '*', max_depth = 2, max_nodes = 100 } = params
|
2025-07-22 17:29:38 +08:00
|
|
|
|
|
|
|
|
|
|
if (!db_id) {
|
|
|
|
|
|
throw new Error('db_id is required')
|
|
|
|
|
|
}
|
2025-06-30 22:29:23 +08:00
|
|
|
|
|
2025-07-22 17:29:38 +08:00
|
|
|
|
const queryParams = new URLSearchParams({
|
|
|
|
|
|
db_id: db_id,
|
|
|
|
|
|
node_label: node_label,
|
|
|
|
|
|
max_depth: max_depth.toString(),
|
|
|
|
|
|
max_nodes: max_nodes.toString()
|
2025-06-30 22:29:23 +08:00
|
|
|
|
})
|
|
|
|
|
|
|
2025-12-15 23:25:56 +08:00
|
|
|
|
return await apiGet(`/api/graph/subgraph?${queryParams.toString()}`, {}, true)
|
2025-07-22 17:29:38 +08:00
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2025-12-15 23:25:56 +08:00
|
|
|
|
* 获取图谱统计信息 (统一接口)
|
|
|
|
|
|
* @param {string} db_id - 图谱ID
|
|
|
|
|
|
* @returns {Promise} - 统计信息
|
2025-07-22 17:29:38 +08:00
|
|
|
|
*/
|
2025-12-15 23:25:56 +08:00
|
|
|
|
getStats: async (db_id) => {
|
2025-07-22 17:29:38 +08:00
|
|
|
|
if (!db_id) {
|
|
|
|
|
|
throw new Error('db_id is required')
|
2025-06-30 22:29:23 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-22 17:29:38 +08:00
|
|
|
|
const queryParams = new URLSearchParams({
|
|
|
|
|
|
db_id: db_id
|
|
|
|
|
|
})
|
|
|
|
|
|
|
2025-12-15 23:25:56 +08:00
|
|
|
|
return await apiGet(`/api/graph/stats?${queryParams.toString()}`, {}, true)
|
2025-07-22 17:29:38 +08:00
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2025-12-15 23:25:56 +08:00
|
|
|
|
* 获取图谱标签列表 (统一接口)
|
|
|
|
|
|
* @param {string} db_id - 图谱ID
|
|
|
|
|
|
* @returns {Promise} - 标签列表
|
2025-07-22 17:29:38 +08:00
|
|
|
|
*/
|
2025-12-15 23:25:56 +08:00
|
|
|
|
getLabels: async (db_id) => {
|
2025-07-22 17:29:38 +08:00
|
|
|
|
if (!db_id) {
|
|
|
|
|
|
throw new Error('db_id is required')
|
2025-06-30 22:29:23 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-22 17:29:38 +08:00
|
|
|
|
const queryParams = new URLSearchParams({
|
|
|
|
|
|
db_id: db_id
|
|
|
|
|
|
})
|
2025-06-30 22:29:23 +08:00
|
|
|
|
|
2025-12-15 23:25:56 +08:00
|
|
|
|
return await apiGet(`/api/graph/labels?${queryParams.toString()}`, {}, true)
|
2025-06-30 22:29:23 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-22 17:29:38 +08:00
|
|
|
|
// =============================================================================
|
|
|
|
|
|
// === Neo4j图数据库接口分组 ===
|
|
|
|
|
|
// =============================================================================
|
|
|
|
|
|
|
|
|
|
|
|
export const neo4jApi = {
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取Neo4j图数据库样例节点
|
|
|
|
|
|
* @param {string} kgdb_name - Neo4j数据库名称(默认为'neo4j')
|
|
|
|
|
|
* @param {number} num - 节点数量
|
|
|
|
|
|
* @returns {Promise} - 样例节点数据
|
|
|
|
|
|
*/
|
|
|
|
|
|
getSampleNodes: async (kgdb_name = 'neo4j', num = 100) => {
|
|
|
|
|
|
const queryParams = new URLSearchParams({
|
|
|
|
|
|
kgdb_name: kgdb_name,
|
|
|
|
|
|
num: num.toString()
|
|
|
|
|
|
})
|
2025-06-30 22:29:23 +08:00
|
|
|
|
|
2025-07-22 17:29:38 +08:00
|
|
|
|
return await apiGet(`/api/graph/neo4j/nodes?${queryParams.toString()}`, {}, true)
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 根据实体名称查询Neo4j图节点
|
|
|
|
|
|
* @param {string} entity_name - 实体名称
|
|
|
|
|
|
* @returns {Promise} - 节点数据
|
|
|
|
|
|
*/
|
|
|
|
|
|
queryNode: async (entity_name) => {
|
|
|
|
|
|
if (!entity_name) {
|
|
|
|
|
|
throw new Error('entity_name is required')
|
|
|
|
|
|
}
|
2025-06-30 22:29:23 +08:00
|
|
|
|
|
2025-07-22 17:29:38 +08:00
|
|
|
|
const queryParams = new URLSearchParams({
|
|
|
|
|
|
entity_name: entity_name
|
|
|
|
|
|
})
|
2025-06-30 22:29:23 +08:00
|
|
|
|
|
2025-07-22 17:29:38 +08:00
|
|
|
|
return await apiGet(`/api/graph/neo4j/node?${queryParams.toString()}`, {}, true)
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 通过JSONL文件添加图谱实体到Neo4j
|
|
|
|
|
|
* @param {string} file_path - JSONL文件路径
|
|
|
|
|
|
* @param {string} kgdb_name - Neo4j数据库名称(默认为'neo4j')
|
2026-01-01 22:19:48 +08:00
|
|
|
|
* @param {string} embed_model_name - 嵌入模型名称 (可选)
|
2026-01-01 23:39:17 +08:00
|
|
|
|
* @param {number} batch_size - 批处理大小 (可选)
|
2025-07-22 17:29:38 +08:00
|
|
|
|
* @returns {Promise} - 添加结果
|
|
|
|
|
|
*/
|
2026-01-15 06:01:34 +08:00
|
|
|
|
addEntities: async (
|
|
|
|
|
|
file_path,
|
|
|
|
|
|
kgdb_name = 'neo4j',
|
|
|
|
|
|
embed_model_name = null,
|
|
|
|
|
|
batch_size = null
|
|
|
|
|
|
) => {
|
|
|
|
|
|
return await apiPost(
|
|
|
|
|
|
'/api/graph/neo4j/add-entities',
|
|
|
|
|
|
{
|
|
|
|
|
|
file_path: file_path,
|
|
|
|
|
|
kgdb_name: kgdb_name,
|
|
|
|
|
|
embed_model_name: embed_model_name,
|
|
|
|
|
|
batch_size: batch_size
|
|
|
|
|
|
},
|
|
|
|
|
|
{},
|
|
|
|
|
|
true
|
|
|
|
|
|
)
|
2025-07-22 17:29:38 +08:00
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 为Neo4j图谱节点添加嵌入向量索引
|
|
|
|
|
|
* @param {string} kgdb_name - Neo4j数据库名称(默认为'neo4j')
|
|
|
|
|
|
* @returns {Promise} - 索引结果
|
|
|
|
|
|
*/
|
|
|
|
|
|
indexEntities: async (kgdb_name = 'neo4j') => {
|
2026-01-15 06:01:34 +08:00
|
|
|
|
return await apiPost(
|
|
|
|
|
|
'/api/graph/neo4j/index-entities',
|
|
|
|
|
|
{
|
|
|
|
|
|
kgdb_name: kgdb_name
|
|
|
|
|
|
},
|
|
|
|
|
|
{},
|
|
|
|
|
|
true
|
|
|
|
|
|
)
|
2025-07-22 17:29:38 +08:00
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取Neo4j图数据库信息
|
|
|
|
|
|
* @returns {Promise} - 图数据库信息
|
|
|
|
|
|
*/
|
|
|
|
|
|
getInfo: async () => {
|
|
|
|
|
|
return await apiGet('/api/graph/neo4j/info', {}, true)
|
2025-06-30 22:29:23 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-22 17:29:38 +08:00
|
|
|
|
// =============================================================================
|
|
|
|
|
|
// === 工具函数分组 ===
|
|
|
|
|
|
// =============================================================================
|
2025-06-30 22:29:23 +08:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 根据实体类型获取颜色
|
|
|
|
|
|
* @param {string} entityType - 实体类型
|
|
|
|
|
|
* @returns {string} - 颜色值
|
|
|
|
|
|
*/
|
|
|
|
|
|
export const getEntityTypeColor = (entityType) => {
|
|
|
|
|
|
const colorMap = {
|
2026-01-15 06:01:34 +08:00
|
|
|
|
person: '#FF6B6B', // 红色 - 人物
|
|
|
|
|
|
organization: '#4ECDC4', // 青色 - 组织
|
|
|
|
|
|
location: '#45B7D1', // 蓝色 - 地点
|
|
|
|
|
|
geo: '#45B7D1', // 蓝色 - 地理位置
|
|
|
|
|
|
event: '#96CEB4', // 绿色 - 事件
|
|
|
|
|
|
category: '#FFEAA7', // 黄色 - 分类
|
|
|
|
|
|
equipment: '#DDA0DD', // 紫色 - 设备
|
|
|
|
|
|
athlete: '#FF7675', // 红色 - 运动员
|
|
|
|
|
|
record: '#FD79A8', // 粉色 - 记录
|
|
|
|
|
|
year: '#FDCB6E', // 橙色 - 年份
|
|
|
|
|
|
UNKNOWN: '#B2BEC3', // 灰色 - 未知
|
|
|
|
|
|
unknown: '#B2BEC3' // 灰色 - 未知
|
2025-06-30 22:29:23 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return colorMap[entityType] || colorMap['unknown']
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 根据权重计算边的粗细
|
|
|
|
|
|
* @param {number} weight - 权重值
|
|
|
|
|
|
* @param {number} minWeight - 最小权重
|
2025-07-22 17:29:38 +08:00
|
|
|
|
* @param {number} maxWeight - 最大权重
|
2025-06-30 22:29:23 +08:00
|
|
|
|
* @returns {number} - 边的粗细
|
|
|
|
|
|
*/
|
|
|
|
|
|
export const calculateEdgeWidth = (weight, minWeight = 1, maxWeight = 10) => {
|
|
|
|
|
|
const minWidth = 1
|
|
|
|
|
|
const maxWidth = 5
|
|
|
|
|
|
const normalizedWeight = (weight - minWeight) / (maxWeight - minWeight)
|
|
|
|
|
|
return minWidth + normalizedWeight * (maxWidth - minWidth)
|
2025-07-22 17:29:38 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// =============================================================================
|
|
|
|
|
|
// === 兼容性导出(可选,用于平滑迁移)===
|
|
|
|
|
|
// =============================================================================
|
|
|
|
|
|
|
|
|
|
|
|
// 保持向后兼容的导出,后续可以移除
|
|
|
|
|
|
export const getGraphNodes = async (params = {}) => {
|
|
|
|
|
|
console.warn('getGraphNodes is deprecated, use neo4jApi.getSampleNodes instead')
|
|
|
|
|
|
return neo4jApi.getSampleNodes(params.kgdb_name || 'neo4j', params.num || 100)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export const getGraphNode = async (params = {}) => {
|
|
|
|
|
|
console.warn('getGraphNode is deprecated, use neo4jApi.queryNode instead')
|
|
|
|
|
|
return neo4jApi.queryNode(params.entity_name)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export const addByJsonl = async (file_path, kgdb_name = 'neo4j') => {
|
|
|
|
|
|
console.warn('addByJsonl is deprecated, use neo4jApi.addEntities instead')
|
|
|
|
|
|
return neo4jApi.addEntities(file_path, kgdb_name)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export const indexNodes = async (kgdb_name = 'neo4j') => {
|
|
|
|
|
|
console.warn('indexNodes is deprecated, use neo4jApi.indexEntities instead')
|
|
|
|
|
|
return neo4jApi.indexEntities(kgdb_name)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export const getGraphStats = async () => {
|
|
|
|
|
|
console.warn('getGraphStats is deprecated, use neo4jApi.getInfo instead')
|
|
|
|
|
|
return neo4jApi.getInfo()
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-15 23:25:56 +08:00
|
|
|
|
// 兼容性导出 - 使用统一接口替代旧有的 graphApi
|
2025-07-22 17:29:38 +08:00
|
|
|
|
export const graphApi = {
|
2025-12-15 23:25:56 +08:00
|
|
|
|
// 使用统一接口替代 LightRAG 接口
|
|
|
|
|
|
getSubgraph: unifiedApi.getSubgraph,
|
|
|
|
|
|
getDatabases: async () => {
|
|
|
|
|
|
// 使用统一接口获取所有图谱,然后过滤出 LightRAG 类型的
|
|
|
|
|
|
const response = await unifiedApi.getGraphs()
|
|
|
|
|
|
if (response.success) {
|
2026-01-15 06:01:34 +08:00
|
|
|
|
const lightragDbs = response.data.filter((graph) => graph.type === 'lightrag')
|
2025-12-15 23:25:56 +08:00
|
|
|
|
return { success: true, data: { databases: lightragDbs } }
|
|
|
|
|
|
}
|
|
|
|
|
|
return response
|
|
|
|
|
|
},
|
|
|
|
|
|
getLabels: unifiedApi.getLabels,
|
|
|
|
|
|
getStats: unifiedApi.getStats,
|
|
|
|
|
|
// 保留 Neo4j 接口
|
|
|
|
|
|
...neo4jApi
|
2026-01-15 06:01:34 +08:00
|
|
|
|
}
|