跳转到主要内容

这是本节的多页打印视图。 .

返回本页常规视图.

HugeGraph-AI

hugegraph-ai 提供 HugeGraph 的 Python 客户端、图机器学习工具,以及面向知识图谱构建和 GraphRAG 的 LLM 工具。

Apache License 2.0 · Ask DeepWiki

模块

仓库使用 uv workspace,其成员是 hugegraph-llmhugegraph-python-clienthugegraph-mlvermeer-python-client 是可编辑的路径依赖,不在 workspace members 中。当前仓库版本为 1.7.0

环境要求

  • HugeGraph-LLM:Python 3.10 或 3.11(>=3.10,<3.12
  • HugeGraph-ML:Python 3.10 或更高版本
  • HugeGraph Python 客户端、Vermeer Python 客户端:Python 3.9 或更高版本
  • uv 0.7 或更高版本
  • HugeGraph Server 1.3 或更高版本(推荐 1.5 或更高版本)

可选依赖组

根项目为每个模块声明一个 extra,另有几个组合项:

Extra安装内容
llmhugegraph-llm
mlhugegraph-ml
python-clienthugegraph-python-client
vermeervermeer-python-client
devpytest、pytest-cov、coverage、pylint、ruff、mypy、ty、pre-commit
nk-llmhugegraph-llmhugegraph-python-client,以及编译镜像所需的 Nuitka
all四个模块包

hugegraph-llm 自身还声明了 vectordb extra,用于安装 pymilvusqdrant-client

Docker Compose 部署

仓库提供同时启动 HugeGraph Server 和 RAG 服务的 Compose 文件:

git clone https://github.com/apache/hugegraph-ai.git
cd hugegraph-ai
cp docker/env.template docker/.env
# 编辑 docker/.env,将 PROJECT_PATH 改为当前仓库的绝对路径
touch hugegraph-llm/.env
cd docker
docker compose -f docker-compose-network.yml up -d

默认地址:

  • HugeGraph Server:http://localhost:8080
  • RAG 服务和 Web 界面:http://localhost:8001

从源码启动 RAG 服务

git clone https://github.com/apache/hugegraph-ai.git
cd hugegraph-ai
uv sync --extra llm
source .venv/bin/activate
cd hugegraph-llm
python -m hugegraph_llm.demo.rag_demo.app

uv sync 会创建根目录下的 .venv。不要在 hugegraph-llm 子目录另建一套环境,否则容易绕过 workspace 锁定的依赖。

安装 ML 依赖

cd hugegraph-ai
uv sync --extra ml
source .venv/bin/activate
cd hugegraph-ml/src

示例脚本位于 hugegraph-ml/src/hugegraph_ml/examples/

后续阅读

1 - HugeGraph-LLM

HugeGraph-LLM 用于知识图谱构建、GraphRAG 和自然语言图查询。演示服务把 Gradio 页面和 FastAPI 接口挂在同一个进程上,默认监听 8001 端口。

环境要求

AI 总结项目文档:Ask DeepWiki

  • Python 3.10 或 3.11(>=3.10,<3.12
  • uv 0.7 或更高版本
  • HugeGraph Server 1.3 或更高版本(推荐 1.5 或更高版本)

Docker Compose 部署

在 HugeGraph-AI 仓库根目录准备环境文件:

git clone https://github.com/apache/hugegraph-ai.git
cd hugegraph-ai
cp docker/env.template docker/.env
# 编辑 docker/.env,将 PROJECT_PATH 改为当前仓库的绝对路径
touch hugegraph-llm/.env
cd docker
docker compose -f docker-compose-network.yml up -d
docker compose -f docker-compose-network.yml ps

启动后可访问:

  • HugeGraph Server:http://localhost:8080
  • RAG 服务和 Web 页面:http://localhost:8001

Compose 文件会把 ${PROJECT_PATH}/hugegraph-llm/.env 挂载到容器内的 /home/work/hugegraph-llm/.env,因此该文件必须在容器启动前存在。资源目录 hugegraph-llm/src/hugegraph_llm/resources 也可以用同样方式挂载,该挂载默认被注释掉。

容器镜像

镜像构建文件内容
hugegraph/ragdocker/Dockerfile.llm包含源码的 Python 3.10 运行环境,入口是 python -m hugegraph_llm.demo.rag_demo.app --host 0.0.0.0 --port 8001
hugegraph/rag-bindocker/Dockerfile.nk基于 nk-llm extra 用 Nuitka 编译的二进制,入口是 ./app.dist/app.bin

两个镜像都暴露 8001 端口,以非 root 用户 work 运行,为 hugegraph-llm/src/hugegraph_llm/resources 声明数据卷,并使用 curl -f http://localhost:8001/ 作为健康检查。

scripts/build_llm_image.sh 会用 docker/Dockerfile.llm 构建并打上 hugegraph/graphrag:1.7.0 标签。

Kubernetes 部署

docker/charts/hg-llm 是 RAG 服务的 Helm chart,部署 hugegraph/graphrag 镜像。默认发布 NodePort 类型的 Service,把节点端口 8039 和服务端口 8080 映射到容器端口 8001,名称固定为 hg-llm-service。Ingress 和水平自动扩缩容已定义但默认关闭。

chart 中 image.tag 仍默认为 v0.0.1,因此需要通过 --set image.tag=1.7.0 或修改 values.yaml 指向实际构建的标签。

chart 的 values.yaml 中,.env 和提示词 YAML 的挂载默认被注释掉。要使用自定义配置,先创建两个 ConfigMap,再取消对应 volumesvolumeMounts 段落的注释:

kubectl create configmap hugegraph-llm-env --from-file=/path/to/.env
kubectl create configmap hugegraph-llm-prompt-config --from-file=/path/to/config_prompt.yaml

从源码启动

依赖应从仓库根目录按 workspace 安装:

git clone https://github.com/apache/hugegraph-ai.git
cd hugegraph-ai
uv sync --extra llm
source .venv/bin/activate
cd hugegraph-llm
python -m hugegraph_llm.demo.rag_demo.app

自定义监听地址和端口:

python -m hugegraph_llm.demo.rag_demo.app \
  --host 127.0.0.1 \
  --port 18001

设置 HG_DEV_RELOAD=1 可让 uvicorn 以自动重载方式启动,便于开发调试。

服务以 hugegraph-llm/.env 保存模型、HugeGraph 和登录配置。提示词放在 hugegraph-llm/src/hugegraph_llm/resources/demo/config_prompt.yaml。缺少文件时,配置代码会按默认值创建。

.env 路径按以下顺序解析:先看是否设置了 HUGEGRAPH_LLM_ENV_PATH;未设置时,从源码运行则使用 hugegraph-llm/.env;否则使用当前工作目录下的 .env

主要功能

构建 RAG 索引

Web 页面的第一个标签页可以处理文本或文件,并执行以下操作:

  1. 切分文本并写入 chunk 向量索引。
  2. 按给定 Schema 从文本抽取顶点和边。
  3. 将抽取结果写入 HugeGraph,并更新顶点向量索引。

文本可以在 text 子页直接输入,也可以在 file 子页上传。上传支持 .txt.docx.pdf,并可一次选择多个文件。加密 PDF 以及没有可提取文本层的扫描件 PDF 会被拒绝。

Schema 可以是内联 JSON,也可以是现有图名。通过 REST API 使用图名时,必须同时传入匹配的 client_config.graph;内联 JSON 不会连接 HugeGraph,也不能附带 client_config

该标签页还提供两个生成器。Graph Schema Generator 根据查询示例和少样本示例生成 Schema。Graph Extraction Prompt Generator 根据描述的场景和选定的参考示例生成抽取提示词。Graph Extraction Split Type 下拉框可在抽取前选择 documentparagraphsentence 粒度。

GraphRAG

查询流程可以组合直接回答、chunk 向量召回和图召回。图召回先抽取关键词并匹配顶点,再尝试 Text2Gremlin;生成或执行失败时可回退到预定义的图遍历方式。请求参数可控制返回数量、向量距离阈值、模板数量和重排序方式。

同一标签页还有批量回归测试面板,可从 .xlsx.csv 文件读取问题、逐条作答,并返回可下载的结果文件。上传控件旁提供模板文件下载。

知识图谱构建器

Text2Gremlin

POST /text2gremlin 根据自然语言、图 Schema 和可选示例生成 Gremlin。自定义提示词必须保留 {query}{schema}{example}{vertices} 四个占位符。

对应的页面标签可以先用问题与 Gremlin 对照文件(.json.csv)构建示例向量索引。未上传文件时使用内置的 resources/demo/text2gremlin.csv

图工具与管理工具

Graph Tools 标签页可直接执行 Gremlin 查询、手动触发图备份,以及初始化 HugeGraph 演示数据。Admin Tools 标签页在校验 ADMIN_TOKEN 后展示 logs/llm-server.log 的末尾内容,并可刷新或清空该文件。

进程运行期间还有两个后台任务:每天 01:00 执行图备份的定时任务,以及持续更新顶点 id 向量的任务。

模型与向量后端

聊天、信息抽取和 Text2Gremlin 可以分别使用 OpenAI 兼容接口、Ollama 或 LiteLLM。嵌入模型可独立选择,同样支持这三种提供方。重排序支持 Cohere 和 SiliconFlow。

默认向量索引使用 FAISS。CUR_VECTOR_INDEX 可选 FaissMilvusQdrant,Web 页面的 5. Set up the vector engine. 面板提供同样的选择。Milvus 和 Qdrant 需要安装可选依赖:

cd hugegraph-ai
uv sync --package hugegraph-llm --extra vectordb

页面操作流程见使用流程,完整环境变量见配置参考,HTTP 请求格式见REST API

程序化调用

原有的 RAGPipelineKgBuilder 类已被流水线调度器取代。通过 SchedulerSingleton 按名称调用流程:

from hugegraph_llm.flows.scheduler import SchedulerSingleton

scheduler = SchedulerSingleton.get_instance()
res = scheduler.schedule_flow(
    "rag_graph_only",
    query="Tell me about Al Pacino.",
    graph_only_answer=True,
    vector_only_answer=False,
    raw_answer=False,
    gremlin_tmpl_num=-1,
    gremlin_prompt=None,
)
print(res.get("graph_only_answer"))

已注册的流程名包括 rag_rawrag_vector_onlyrag_graph_onlyrag_graph_vectortext2gremlinbuild_examples_indexbuild_vector_indexgraph_extractimport_graph_dataupdate_vid_embeddingsget_graph_index_infobuild_schemaprompt_generateschedule_stream_flow 是对应的异步流式版本。

开发检查

先在仓库根目录安装模块和开发工具,再运行与 CI 一致的检查:

cd hugegraph-ai
uv sync --extra llm --extra dev
uv run ruff format --check .
uv run ruff check .

cd hugegraph-llm
SKIP_EXTERNAL_SERVICES=true uv run pytest src/tests/config/ src/tests/document/ src/tests/middleware/ \
  src/tests/operators/ src/tests/models/ src/tests/indices/ src/tests/test_utils.py -v --tb=short
SKIP_EXTERNAL_SERVICES=true uv run pytest src/tests/integration/test_graph_rag_pipeline.py \
  src/tests/integration/test_kg_construction.py src/tests/integration/test_rag_pipeline.py -v --tb=short

Git hook 通过 pre-commit 启用:

cd hugegraph-ai
pre-commit install
pre-commit run --all-files

2 - HugeGraph-ML

HugeGraph-ML 从 HugeGraph 读取图数据并转换为 DGL 图,供节点嵌入、节点分类、图分类、链接预测和欺诈检测等任务使用。模型实现位于 hugegraph-ml/src/hugegraph_ml/models/

环境要求

  • Python 3.10 或更高版本
  • HugeGraph Server 1.0 或更高版本,推荐 1.5 及以上版本
  • uv 0.7 或更高版本

所有服务端访问都通过同一仓库中的 hugegraph-python-client(即 pyhugegraph 包)完成。HugeGraph2DGL 使用 Gremlin 接口的 g.V().hasLabel(...)g.E().hasLabel(...) 拉取点边,数据集导入函数则通过 schema 接口和顶点、边的批量接口写入,每批 500 条。

ML 依赖在仓库根目录的 [tool.uv] constraint-dependencies 中固定版本:

依赖版本约束
torch==2.2.0
dgl~=2.1.0
ogb~=1.3.6
torchdata~=0.7.0
catboost~=1.2.3
category-encoders~=2.6.3
numpy~=1.24.4
pandas~=2.2.3

上述约束安装的是 CPU 版本。每个任务都有 gpu 参数,默认值 -1 表示使用 CPU;只有自行安装 CUDA 版的 torchdgl 之后,才可以传入设备编号。

安装

git clone https://github.com/apache/hugegraph-ai.git
cd hugegraph-ai
uv sync --extra ml
source .venv/bin/activate
cd hugegraph-ml/src

HugeGraph-ML 是根项目的路径依赖,但不属于 uv workspace members。应在仓库根目录选择 ml extra,不要在子目录建立另一套锁文件。

已实现模型

下列模块均位于 hugegraph-ml/src/hugegraph_ml/models/models/__init__.py 不做任何再导出,需要直接从模块文件导入。

模型模块入口类用途论文
AGNNagnn.pyAGNN节点分类1803.03735
APPNPappnp.pyAPPNP节点分类1810.05997
ARMAarma.pyARMA4NC节点分类1901.01343
BGNNbgnn.pyBGNNPredictor梯度提升与 GNN 结合处理节点特征,自带示例执行回归任务2101.08543
BGRLbgrl.pyBGRL自监督节点嵌入2102.06514
CARE-GNNcare_gnn.pyCAREGNN欺诈检测2008.08692
Cluster-GCNcluster_gcn.pySAGE基于子图采样的节点分类1905.07953
C&Scorrect_and_smooth.pyMLPCorrectAndSmoothLabelPropagation对基础预测结果做校正与平滑2010.13993
DAGNNdagnn.pyDAGNN节点分类2007.09296
DeeperGCNdeepergcn.pyDeeperGCN带边特征的节点分类2006.07739
DGIdgi.pyDGI自监督节点嵌入1809.10341
DiffPooldiffpool.pyDiffPool图分类1806.08804
GATNEgatne.pyDGLGATNE异构网络嵌入1905.01669
GINgin_global_pool.pyGIN图分类
GRACEgrace.pyGRACE自监督节点嵌入2006.04131
GRANDgrand.pyGRAND节点分类2005.11079
JKNetjknet.pyJKNet节点分类1806.03536
MLPmlp.pyMLPClassifier基于已学习嵌入的下游分类器
P-GNNpgnn.pyPGNN链接预测you19b
SEALseal.pyDGCNNSEALData链接预测1802.09691

GINpooling 参数可取 sum(默认)、meanmaxglobal_attentionset2set

读取图数据

hugegraph-ml/src/hugegraph_ml/data/hugegraph2dgl.py 中的 HugeGraph2DGL 会创建 PyHugeClient,并把查询结果转换为 DGL 对象:

from hugegraph_ml.data.hugegraph2dgl import HugeGraph2DGL

hg2d = HugeGraph2DGL(
    url="http://127.0.0.1:8080",
    graph="hugegraph",
    user="",
    pwd="",
    graphspace=None,
)
方法返回值说明
convert_graph(vertex_label, edge_label, feat_key="feat", label_key="label", mask_keys=None)dgl.DGLGraphmask_keys 为空时取 ["train_mask", "val_mask", "test_mask"]
convert_hetero_graph(vertex_labels, edge_labels, feat_key="feat", label_key="label", mask_keys=None)DGL 异构图参数为标签列表
convert_graph_dataset(graph_vertex_label, vertex_label, edge_label, feat_key="feat", label_key="label")HugeGraphDatasetinfo 中写入 n_graphsmax_n_nodesn_feat_dimn_classes
convert_graph_nx(vertex_label, edge_label)networkx.GraphP-GNN 使用
convert_graph_with_edge_feat(vertex_label, edge_label, node_feat_key="feat", edge_feat_key="edge_feat", label_key="label", mask_keys=None)dgl.DGLGraph同时填充 edata["feat"]
convert_graph_ogb(vertex_label, edge_label, split_label)(dgl.DGLGraph, split_edge)SEAL 使用
convert_hetero_graph_bgnn(vertex_labels, edge_labels, feat_key="feat", label_key="class", cat_key="cat_features", mask_keys=None)DGL 异构图BGNN 使用

节点特征写入 ndata["feat"],标签写入 ndata["label"],各掩码写入 ndata[<mask key>]NodeEmbed 只要求 featNodeClassifyNodeClassifyWithEdgeNodeClassifyWithSample 要求 featlabeltrain_maskval_masktest_mask,缺少任意一项都会抛出 ValueError

导入示例数据集

hugegraph_ml.utils.dgl2hugegraph_utils 负责把 DGL、OGB 和 NetworkX 数据集写入 HugeGraph,供转换层读取。这些函数都接受与 HugeGraph2DGL 相同的 urlgraphuserpwdgraphspace 参数,并且多数会先把数据集名转为大写再匹配。

函数支持的数据集创建的标签
import_graph_from_dglCORACITESEERPUBMED<NAME>_vertex<NAME>_edge
import_graphs_from_dglMUTAGCOLLABNCI1PROTEINSPTCENZYMESDD<NAME>_graph_vertex<NAME>_vertex<NAME>_edge
import_hetero_graph_from_dglACM<NAME>_<ntype>_v<NAME>_<etype>_e
import_hetero_graph_from_dgl_no_featAMAZONGATNE<NAME>_<ntype>_v<NAME>_<etype>_e
import_hetero_graph_from_dgl_bgnnAVAZU<NAME>_<ntype>_v<NAME>_<etype>_e
import_graph_from_nxCAVEMAN<NAME>_vertex<NAME>_edge
import_graph_from_dgl_with_edge_featCORACITESEERPUBMED<NAME>_edge_feat_vertex<NAME>_edge_feat_edge
import_graph_from_ogbogbl-collab,不做大写转换<NAME>_vertex<NAME>_edge
import_split_edge_from_ogbogbl-collab,不做大写转换<NAME>_split_edge

传入其他名称会抛出 ValueError("dataset not supported")import_split_edge_from_ogb 还需要顶点导入返回的 idx_to_vertex_id 映射和 max_nodes 上限。

clear_all_data() 会清空目标图中的全部点和边。测试 fixture 先调用它,再导入 CORAMUTAGACM,结束时再次调用。

AMAZONGATNEAVAZU 不会自动下载,压缩包地址写在 import_hetero_graph_from_dgl_no_featimport_hetero_graph_from_dgl_bgnn 上方的注释里。

任务

任务类位于 hugegraph-ml/src/hugegraph_ml/tasks/,均接收转换后的图和模型实例。

模块入口方法
NodeEmbednode_embed.pytrain_and_embed(add_self_loop=True, lr=1e-3, weight_decay=0, n_epochs=200, patience=inf, gpu=-1),返回 ndata["feat"] 被替换为嵌入结果的图
NodeClassifynode_classify.pytrain(lr, weight_decay, n_epochs, patience, early_stopping_monitor, gpu),再 evaluate() 返回 {"accuracy": ..., "loss": ...}
NodeClassifyWithEdgenode_classify_with_edge.py结构相同,适用于同时读取 edata["feat"] 的模型
NodeClassifyWithSamplenode_classify_with_sample.py基于 ClusterGCNSampler 分区的训练,仅使用 CPU,没有 gpu 参数
GraphClassifygraph_classify.pytrain(batch_size=20, lr, weight_decay, n_epochs, patience, early_stopping_monitor, clip=2.0, gpu),在 HugeGraphDataset 上按 70/20/10 划分
DetectorCaregnnfraud_detector_caregnn.pyCARE-GNN 训练,evaluate() 输出 recall 和 ROC AUC,并读取 ndata["feature"] 而非 ndata["feat"]
HeteroSampleEmbedGATNEhetero_sample_embed_gatne.pytrain_and_embed(lr=1e-3, n_epochs=200, gpu=-1)
LinkPredictionPGNNlink_prediction_pgnn.pytrain(lr, weight_decay, n_epochs, gpu)
LinkPredictionSeallink_prediction_seal.py构造函数内部已调用 data_prepare(),随后执行 train(lr=1e-3, n_epochs=200, gpu=-1)

patience 默认值为 float("inf")utils/early_stopping.py 中的 EarlyStopping 可以监控 lossaccuracy,保存最优权重并在训练结束时恢复。

可运行示例

脚本位于 hugegraph-ml/src/hugegraph_ml/examples/。在 hugegraph-ml/src 目录下执行:

python ./hugegraph_ml/examples/dgi_example.py

每个脚本同时提供同名函数,可以导入后用较小的 epoch 数调用。

脚本模型任务读取的标签
agnn_example.pyAGNNNodeClassifyCORA_vertexCORA_edge
appnp_example.pyAPPNPNodeClassifyCORA_vertexCORA_edge
arma_example.pyARMA4NCNodeClassifyCORA_vertexCORA_edge
bgnn_example.pyBGNNPredictor模型自带的 fit()AVAZU__N_vAVAZU__E_e
bgrl_example.pyBGRLNodeEmbedNodeClassifyCORA_vertexCORA_edge
care_gnn_example.pyCAREGNNDetectorCaregnnAMAZON_user_v 以及 AMAZON_net_upu_eAMAZON_net_usu_eAMAZON_net_uvu_e
cluster_gcn_example.pySAGENodeClassifyWithSampleCORA_vertexCORA_edge
correct_and_smooth_example.pycorrect_and_smooth 中的 MLPNodeClassifyCORA_vertexCORA_edge
dagnn_example.pyDAGNNNodeClassifyCORA_vertexCORA_edge
deepergcn_example.pyDeeperGCNNodeClassifyWithEdge通过 convert_graph_with_edge_feat 读取 CORA_vertexCORA_edge
dgi_example.pyDGINodeEmbedNodeClassifyCORA_vertexCORA_edge
diffpool_example.pyDiffPoolGraphClassifyMUTAG_graph_vertexMUTAG_vertexMUTAG_edge
gatne_example.pyDGLGATNEHeteroSampleEmbedGATNEAMAZONGATNE__N_vAMAZONGATNE_1_eAMAZONGATNE_2_e
gin_example.pyGINGraphClassifyMUTAG_graph_vertexMUTAG_vertexMUTAG_edge
grace_example.pyGRACENodeEmbedNodeClassifyCORA_vertexCORA_edge
grand_example.pyGRANDNodeClassifyCORA_vertexCORA_edge
jknet_example.pyJKNetNodeClassifyCORA_vertexCORA_edge
pgnn_example.pyPGNNLinkPredictionPGNNCAVEMAN_vertexCAVEMAN_edge
seal_example.pyDGCNNLinkPredictionSealogbl-collab_vertexogbl-collab_edgeogbl-collab_split_edge

DGI 节点嵌入示例

先把 DGL 的 Cora 数据集导入 HugeGraph。数据集名会先转为大写,因此 coraCORA 都会生成 CORA_vertexCORA_edge 标签:

from hugegraph_ml.utils.dgl2hugegraph_utils import import_graph_from_dgl

import_graph_from_dgl("cora")

读取图并训练 DGI:

from hugegraph_ml.data.hugegraph2dgl import HugeGraph2DGL
from hugegraph_ml.models.dgi import DGI
from hugegraph_ml.models.mlp import MLPClassifier
from hugegraph_ml.tasks.node_classify import NodeClassify
from hugegraph_ml.tasks.node_embed import NodeEmbed

hg2d = HugeGraph2DGL()
graph = hg2d.convert_graph(
    vertex_label="CORA_vertex",
    edge_label="CORA_edge",
)

embed_model = DGI(n_in_feats=graph.ndata["feat"].shape[1])
embed_task = NodeEmbed(graph=graph, model=embed_model)
embedded_graph = embed_task.train_and_embed(
    add_self_loop=True,
    n_epochs=300,
    patience=30,
)

classifier = MLPClassifier(
    n_in_feat=embedded_graph.ndata["feat"].shape[1],
    n_out_feat=embedded_graph.ndata["label"].unique().shape[0],
)
classify_task = NodeClassify(graph=embedded_graph, model=classifier)
classify_task.train(lr=1e-3, n_epochs=400, patience=40)
print(classify_task.evaluate())

evaluate() 返回类似 {'accuracy': 0.82, 'loss': 0.5714246034622192} 的字典。完整脚本是 hugegraph-ml/src/hugegraph_ml/examples/dgi_example.py

GRAND 节点分类示例

from hugegraph_ml.data.hugegraph2dgl import HugeGraph2DGL
from hugegraph_ml.models.grand import GRAND
from hugegraph_ml.tasks.node_classify import NodeClassify

hg2d = HugeGraph2DGL()
graph = hg2d.convert_graph(
    vertex_label="CORA_vertex",
    edge_label="CORA_edge",
)
model = GRAND(
    n_in_feats=graph.ndata["feat"].shape[1],
    n_out_feats=graph.ndata["label"].unique().shape[0],
)
task = NodeClassify(graph, model)
task.train(lr=1e-2, weight_decay=5e-4, n_epochs=2000, patience=100)
print(task.evaluate())

GRAND 每次增强采样都会返回一组 logits,NodeClassify 会对列表中的每个元素分别应用掩码后再计算损失。完整脚本是 hugegraph-ml/src/hugegraph_ml/examples/grand_example.py

排查问题

  • 连接失败:检查 HugeGraph Server 地址、端口和认证信息。
  • Schema 不匹配:示例默认使用 CORA_vertexCORA_edge,自有数据需要传入实际标签。
  • ValueError: Graph is missing required node attribute ...:节点分类任务需要 ndata 中包含 featlabeltrain_maskval_masktest_mask。请导入带掩码的数据集,或给 convert_graph 传入自定义的 mask_keys
  • ValueError: dataset not supported:导入函数只接受上表列出的名称,且 import_graph_from_ogb 匹配 ogbl-collab 时不做大写转换。
  • DGL 或 PyTorch 导入失败:回到仓库根目录重新执行 uv sync --extra ml,并确认当前 Python 来自根目录 .venv
  • bgrl_example.py 目前在导入阶段就会失败:它从 hugegraph_ml.models.bgrl 导入 MLP_Predictor,而该模块中的类名是 MLPPredictor
  • care_gnn_example.py 读取 AMAZON_user_v 和三个 AMAZON_net_*_e 边标签,仓库内没有对应的导入函数,需要自行准备该数据集后再运行。

3 - HugeGraph-LLM 使用流程

本文说明 HugeGraph-LLM Web 页面的处理流程。服务启动方式见 HugeGraph-LLM

0. 配置面板

标签页上方是可折叠的配置面板,共五个部分:1. Set up the HugeGraph server.2. Set up the LLM.3. Set up the Embedding.4. Set up the Reranker.5. Set up the vector engine.。每部分都有独立的应用按钮,应用后会把受支持的字段写回 .env。页面顶部还会显示当前提示词语言。

1. 构建 RAG 索引

第一个标签页负责两类索引:

  • 将文档切分后写入 chunk 向量索引。
  • 按 Schema 从文档抽取顶点和边,写入 HugeGraph,并维护顶点向量索引。
flowchart TD
    A[输入文档] --> B[文本切分]
    B --> C[生成 chunk 向量]
    C --> D[写入向量索引]
    B --> E[LLM 按 Schema 抽取顶点和边]
    E --> F[写入 HugeGraph]
    F --> G[更新顶点向量索引]

输入来自 text 子页或 file 子页。上传支持 .txt.docx.pdf,可一次选择多个文件。

页面包含文档、Schema、抽取提示词和结果区域。常用操作有:

  1. Import into Vector:切分文档并建立 chunk 向量索引。
  2. Extract Graph Data (1):按 Schema 抽取图数据。
  3. Load into GraphDB (2):把抽取结果写入 HugeGraph,并自动更新顶点向量。
  4. Update Vid Embedding:重新生成顶点向量,通常只在图中已有数据时才需要单独执行。

这些按钮旁的 Graph Extraction Split Type 下拉框可选 documentparagraphsentencedocument 把输入整体作为一个单元,另外两种会在抽取前先切分长文档。

页面还可以查看或清除 chunk 索引、顶点索引和图数据。清除操作会删除已有数据,执行前先确认当前图和索引是否仍被其他查询使用。

主控件下方还有两个折叠的辅助工具:

  • Graph Schema Generator:根据查询示例和少样本示例生成 Schema,填入 Graph Schema 字段。
  • Graph Extraction Prompt Generator:根据期望场景(例如社交关系、金融知识图谱)和选定的参考示例生成 Graph Extract Prompt Header。

2. GraphRAG 查询

第二个标签页提供四种回答范围:

  • 直接使用 LLM 回答。
  • 只使用 chunk 向量召回。
  • 只使用图召回。
  • 合并图召回与向量召回。
flowchart TD
    Q[问题] --> V[查询 chunk 向量索引]
    Q --> K[抽取关键词]
    K --> M[匹配图顶点]
    M --> T[生成并执行 Gremlin]
    T -->|失败| B[BFS 图遍历回退]
    T --> R[整理图结果]
    B --> R
    V --> S[合并与重排序]
    R --> S
    S --> A[生成答案]

图召回先用关键词精确匹配 HugeGraph 顶点,找不到时再用顶点向量做近似匹配。匹配结果会进入 Text2Gremlin;生成或执行失败时,流程可以回退到预定义的图遍历。

Template Num 控制 Text2Gremlin 在图召回中的参与方式:

  • 小于 0:完全跳过 Text2Gremlin,图召回直接使用预定义的图遍历。
  • 等于 0:不带任何示例生成 Gremlin(zero-shot)。
  • 大于 0:从示例索引中取相应数量的相近示例,并采用带模板的生成结果。示例数量会被限制在 0 到 10 之间。

该标签页的其他控件还有 Rerank methodbleureranker)、Graph RatioNear neighbor firstQuery related information,以及可编辑的 Query PromptKeywords Extraction Prompt

单条问答面板下方是批量回归测试面板。上传 .xlsx.csv 问题文件,设置 Max Lines To Show,点击 Generate Answer (Batch)。答案会显示在预览表格中,并可下载为文件。上传控件旁提供模板文件下载。

3. Text2Gremlin

第三个标签页分为两部分。上半部分用问题与 Gremlin 对照文件(.json.csv)构建示例向量索引;未上传文件时使用内置的 resources/demo/text2gremlin.csv

下半部分把自然语言转换成 Gremlin:

  1. 读取当前图的 Schema。
  2. 从示例向量索引取回相近的自然语言与 Gremlin 对。
  3. 把问题、Schema、示例和已匹配顶点填入提示词。
  4. 调用 LLM 生成 Gremlin,并按所选输出类型决定是否执行。

Number of refer examples 设置取回的示例数量,范围 0 到 10,默认 2。结果显示在四个字段中:带模板的 Gremlin、不带模板的 Gremlin,以及两者各自的执行输出。

RAG 查询范围选择

自定义提示词必须包含 {query}{schema}{example}{vertices}。缺少任一占位符时,REST API 会拒绝请求。

4. 图工具与管理工具

Graph Tools 标签页可直接对当前图执行 Gremlin 查询、手动触发图备份,并通过 beta 操作初始化 HugeGraph 演示数据。后台还有两个任务:每天 01:00 自动备份图数据,以及在进程运行期间持续更新顶点 id 向量。

Admin Tools 需要密码。输入已配置的 ADMIN_TOKEN 后可查看 logs/llm-server.log 的末尾内容(每 60 秒自动刷新),并可手动刷新或清空该文件。ADMIN_TOKEN 为空或仍是占位值 xxxx 时,访问会被拒绝。

设置 ENABLE_LOGIN=True 后,Web 页面会要求基础认证,用户名固定为 rag,密码是 USER_TOKEN;REST API 则要求把 USER_TOKEN 作为 Bearer token。日志接口还要求单独配置安全的 ADMIN_TOKEN

RAG 界面中抽取的关键词

5. 提示词语言

hugegraph-llm/.env 中设置:

# 英文提示词
LANGUAGE=EN

# 中文提示词
LANGUAGE=CN

修改后重启服务。该配置选择内置提示词语言,不会自动翻译输入文档,也不是 /rag 请求体字段。

6. REST 调用

Web 页面和 REST API 使用同一套流程。需要程序集成时使用 /rag/rag/graph/graph/extract/text2gremlin;请求结构见 REST API

4 - 配置参考

HugeGraph-LLM 从 hugegraph-llm/.env 读取运行配置。提示词单独保存在 hugegraph-llm/src/hugegraph_llm/resources/demo/config_prompt.yaml,不会写入 .env

.env 路径按以下顺序解析:

  1. 若设置了环境变量 HUGEGRAPH_LLM_ENV_PATH,则使用该路径,开头的 ~ 会被展开。
  2. 从源码运行时,使用 hugegraph-llm/.env
  3. 以已安装的包运行时,使用当前工作目录下的 .env

运行以下命令可按配置类的默认值创建或更新文件:

cd hugegraph-ai/hugegraph-llm
python -m hugegraph_llm.config.generate --update

--update 默认开启,因此不带参数运行效果相同。该命令会写入 HugeGraph、管理员、LLM 和索引配置,然后重新生成提示词 YAML。若 .env 已存在,会先询问是否覆盖。

.env 包含密钥和密码,不要提交到版本库。

基础选项

配置项默认值说明
LANGUAGEEN提示词语言,可选 ENCN
CHAT_LLM_TYPEopenai回答模型,可选 openailitellmollama/local
EXTRACT_LLM_TYPEopenai信息抽取模型,取值同上
TEXT2GQL_LLM_TYPEopenaiText2Gremlin 模型,取值同上
EMBEDDING_TYPEopenai嵌入模型,取值同上,也可以留空
RERANKER_TYPE可选 coheresiliconflow
KEYWORD_EXTRACT_TYPEllm可选 llmtextrankhybrid
WINDOW_SIZE3TextRank 滑窗,范围 1 到 10
HYBRID_LLM_WEIGHTS0.5hybrid 模式中 LLM 结果的权重,范围 0 到 1

OpenAI 兼容接口

聊天、抽取和 Text2Gremlin 可以使用不同端点、密钥和模型。

用途API 地址密钥模型最大 token 默认值
回答OPENAI_CHAT_API_BASEOPENAI_CHAT_API_KEYOPENAI_CHAT_LANGUAGE_MODELOPENAI_CHAT_TOKENS=8192
抽取OPENAI_EXTRACT_API_BASEOPENAI_EXTRACT_API_KEYOPENAI_EXTRACT_LANGUAGE_MODELOPENAI_EXTRACT_TOKENS=256
Text2GremlinOPENAI_TEXT2GQL_API_BASEOPENAI_TEXT2GQL_API_KEYOPENAI_TEXT2GQL_LANGUAGE_MODELOPENAI_TEXT2GQL_TOKENS=4096
嵌入OPENAI_EMBEDDING_API_BASEOPENAI_EMBEDDING_API_KEYOPENAI_EMBEDDING_MODEL不适用

API 地址默认是 https://api.openai.com/v1;三个语言模型默认是 gpt-4.1-mini,嵌入模型默认是 text-embedding-3-small

OPENAI_BASE_URLOPENAI_API_KEY 可作为通用回退值。嵌入模型另有 OPENAI_EMBEDDING_BASE_URLOPENAI_EMBEDDING_API_KEY 回退值。

LiteLLM

用途API 地址密钥模型最大 token 默认值
回答LITELLM_CHAT_API_BASELITELLM_CHAT_API_KEYLITELLM_CHAT_LANGUAGE_MODELLITELLM_CHAT_TOKENS=8192
抽取LITELLM_EXTRACT_API_BASELITELLM_EXTRACT_API_KEYLITELLM_EXTRACT_LANGUAGE_MODELLITELLM_EXTRACT_TOKENS=256
Text2GremlinLITELLM_TEXT2GQL_API_BASELITELLM_TEXT2GQL_API_KEYLITELLM_TEXT2GQL_LANGUAGE_MODELLITELLM_TEXT2GQL_TOKENS=4096
嵌入LITELLM_EMBEDDING_API_BASELITELLM_EMBEDDING_API_KEYLITELLM_EMBEDDING_MODEL不适用

三个语言模型默认是 openai/gpt-4.1-mini,嵌入模型默认是 openai/text-embedding-3-small。模型名通常使用 供应商/模型 格式,具体取值由 LiteLLM 服务决定。

Ollama

用途主机端口模型
回答OLLAMA_CHAT_HOSTOLLAMA_CHAT_PORTOLLAMA_CHAT_LANGUAGE_MODEL
抽取OLLAMA_EXTRACT_HOSTOLLAMA_EXTRACT_PORTOLLAMA_EXTRACT_LANGUAGE_MODEL
Text2GremlinOLLAMA_TEXT2GQL_HOSTOLLAMA_TEXT2GQL_PORTOLLAMA_TEXT2GQL_LANGUAGE_MODEL
嵌入OLLAMA_EMBEDDING_HOSTOLLAMA_EMBEDDING_PORTOLLAMA_EMBEDDING_MODEL

主机默认是 127.0.0.1,端口默认是 11434,模型名没有默认值。使用前先在 Ollama 中拉取对应模型。

重排序

配置项默认值说明
COHERE_BASE_URLhttps://api.cohere.com/v1/rerankCohere rerank 接口;CO_API_URL 可作为回退值
RERANKER_API_KEYCohere 或 SiliconFlow 密钥
RERANKER_MODEL服务端支持的模型名

HugeGraph 连接与召回限制

配置项默认值说明
GRAPH_URL127.0.0.1:8080HugeGraph 地址,不拆分为 IP 和端口
GRAPH_NAMEhugegraph图名
GRAPH_USERadmin用户名
GRAPH_PWDxxx密码
GRAPH_SPACEGraphSpace 名称
LIMIT_PROPERTYFalse是否限制返回属性;配置类按字符串读取
MAX_GRAPH_PATH10最大图路径长度
MAX_GRAPH_ITEMS30图召回的最大项目数
EDGE_LIMIT_PRE_LABEL8每个边标签的返回上限
VECTOR_DIS_THRESHOLD0.9向量距离阈值;超过阈值的结果会被忽略
TOPK_PER_KEYWORD1每个关键词的候选数
TOPK_RETURN_RESULTS20重排序后返回的结果数

向量索引后端

配置项默认值说明
CUR_VECTOR_INDEXFaiss当前使用的向量库:FaissMilvusQdrant
QDRANT_HOST
QDRANT_PORT6333
QDRANT_API_KEY
MILVUS_HOST
MILVUS_PORT19530
MILVUS_USER
MILVUS_PASSWORD

FAISS 在本地运行,无需额外依赖。未安装可选依赖就选择 MilvusQdrant 时,会报错并指出缺少的包,因此需要先安装:

cd hugegraph-ai
uv sync --package hugegraph-llm --extra vectordb

Web 页面的 5. Set up the vector engine. 面板提供同样的选择,并会保存所选引擎的连接配置。

登录与日志接口

配置项默认值说明
ENABLE_LOGINFalse是否要求 Bearer token;配置类按字符串读取
USER_TOKEN4321Web 页面和普通 API 的 token
ADMIN_TOKENxxxx/logs 使用的管理员 token

ADMIN_TOKEN 为空或仍为 xxxx 时,/logs 会直接返回 403。生产环境应同时替换用户 token 和管理员 token。

最小 OpenAI 配置

LANGUAGE=CN
CHAT_LLM_TYPE=openai
EXTRACT_LLM_TYPE=openai
TEXT2GQL_LLM_TYPE=openai
EMBEDDING_TYPE=openai

OPENAI_API_KEY=your-api-key
OPENAI_BASE_URL=https://api.openai.com/v1
OPENAI_CHAT_LANGUAGE_MODEL=gpt-4.1-mini
OPENAI_EXTRACT_LANGUAGE_MODEL=gpt-4.1-mini
OPENAI_TEXT2GQL_LANGUAGE_MODEL=gpt-4.1-mini
OPENAI_EMBEDDING_MODEL=text-embedding-3-small

GRAPH_URL=127.0.0.1:8080
GRAPH_NAME=hugegraph
GRAPH_USER=admin
GRAPH_PWD=your-password

配置加载

配置类先提供代码默认值,再从 .env 和进程环境读取覆盖值。Web 页面和配置 API 可以在运行时更新当前设置,并把受支持的字段同步回 .env。手工改动 .env 后应重启服务;提示词 YAML 可由页面加载逻辑刷新。

.env 中的未知键会被忽略而不是报错,空值会回退到代码默认值,键名匹配不区分大小写。

配置定义位于:

  • hugegraph-llm/src/hugegraph_llm/config/llm_config.py
  • hugegraph-llm/src/hugegraph_llm/config/hugegraph_config.py
  • hugegraph-llm/src/hugegraph_llm/config/index_config.py
  • hugegraph-llm/src/hugegraph_llm/config/admin_config.py
  • hugegraph-llm/src/hugegraph_llm/config/prompt_config.py
  • hugegraph-llm/src/hugegraph_llm/config/models/base_config.py:加载与文件同步逻辑

5 - HugeGraph-LLM REST API

HugeGraph-LLM 演示进程同时提供 Web 页面和 REST API。默认地址是 http://localhost:8001

cd hugegraph-ai/hugegraph-llm
python -m hugegraph_llm.demo.rag_demo.app \
  --host 127.0.0.1 \
  --port 8001

所有接口都使用 POST

路径成功状态码用途
/rag200按所选召回方式回答问题
/rag/graph200只做图召回,不生成最终答案
/graph/extract200从文本抽取顶点和边
/text2gremlin200由自然语言生成 Gremlin
/config/graph201更新 HugeGraph 连接
/config/llm201更新语言模型
/config/embedding201更新嵌入模型
/config/rerank201更新重排序模型
/logs200流式返回服务日志

认证

.env 中启用登录:

ENABLE_LOGIN=True
USER_TOKEN=replace-with-a-secret

启用后,请求需要 Bearer token:

Authorization: Bearer replace-with-a-secret

同一开关也会给 Gradio 页面加上基础认证,用户名固定为 rag,密码是 USER_TOKEN。token 不正确时返回 401,并带上 WWW-Authenticate: Bearer 响应头。ENABLE_LOGIN 保持 False 时所有接口都不做鉴权。

RAG

POST /rag

根据开关返回一种或多种回答。未显式指定时只启用 graph_only

curl -X POST http://localhost:8001/rag \
  -H 'Content-Type: application/json' \
  -d '{
    "query": "Al Pacino 出演过哪些电影?",
    "raw_answer": false,
    "vector_only": false,
    "graph_only": true,
    "graph_vector_answer": false,
    "max_graph_items": 30,
    "topk_return_results": 20,
    "vector_dis_threshold": 0.9,
    "topk_per_keyword": 1,
    "gremlin_tmpl_num": 1,
    "client_config": {
      "url": "127.0.0.1:8080",
      "graph": "hugegraph",
      "user": "admin",
      "pwd": "admin",
      "gs": "DEFAULT"
    }
  }'

响应只包含已启用的回答字段:

{
  "query": "Al Pacino 出演过哪些电影?",
  "graph_only": "..."
}

其他可选参数包括 graph_ratio(默认 0.5)、rerank_methodbleureranker,默认 bleu)、near_neighbor_first(默认 false)、custom_priority_info,以及三个自定义提示词字段 answer_promptkeywords_extract_promptgremlin_prompt。省略提示词字段时使用 config_prompt.yaml 中的值。

gremlin_tmpl_num 决定图召回阶段 Text2Gremlin 的执行方式:小于 0 表示跳过 Text2Gremlin,直接使用预定义的图遍历;等于 0 表示不带示例生成 Gremlin;大于 0 表示从示例索引中取相应数量的示例。

query 为空或只有空白字符时返回 400。

POST /rag/graph

只执行图召回,不生成最终自然语言答案:

curl -X POST http://localhost:8001/rag/graph \
  -H 'Content-Type: application/json' \
  -d '{
    "query": "Al Pacino 出演过哪些电影?",
    "get_vertex_only": false,
    "gremlin_tmpl_num": 1,
    "rerank_method": "bleu"
  }'

响应的 graph_recall 可能包含 querykeywordsmatch_vidsgraph_result_flaggremlingraph_resultvertex_degree_list。设置 get_vertex_only=true 可在顶点匹配后提前返回,此时接口会把 match_vids 替换为完整的顶点详情。

query 为空返回 400,请求类型错误返回 400,其他失败返回 500。

图抽取

POST /graph/extract

使用内联 Schema 时不会连接 HugeGraph:

curl -X POST http://localhost:8001/graph/extract \
  -H 'Content-Type: application/json' \
  -d '{
    "texts": ["Alice 在 Acme 工作。"],
    "schema": {
      "vertexlabels": [
        {"name": "person", "properties": ["name"]},
        {"name": "company", "properties": ["name"]}
      ],
      "edgelabels": [
        {
          "name": "works_at",
          "source_label": "person",
          "target_label": "company",
          "properties": []
        }
      ]
    },
    "language": "zh",
    "split_type": "sentence",
    "include_meta": true
  }'

请求字段:

字段默认值说明
texts必填字符串或字符串数组;空白项会被丢弃,全部为空时报错
schema必填内联 JSON 对象或字符串,或现有图名
example_prompt提示词 YAML 中的值抽取提示词头部
extract_typeproperty_graph目前仅接受该值
languagezhzhen,用于文本切分
split_typedocumentdocumentparagraphsentence
include_metafalsemeta 中加入 vertex_countedge_counttext_count
client_config仅在 schema 为图名时允许传入

内联 Schema 必须是包含 vertexlabelsedgelabels 两个列表的对象。每个顶点标签需要非空的 name 和非空的 properties 列表;每条边标签需要非空的 namesource_labeltarget_labelpropertykeys 可选,若存在必须是列表。

schema 传现有图名,必须同时传入 client_config,且 client_config.graph 必须和图名相同。这里的 client_config 只接受 graphuserpwdgs,未知字段会被拒绝,且没有 url 字段:

{
  "texts": "Alice 在 Acme 工作。",
  "schema": "hugegraph",
  "client_config": {
    "graph": "hugegraph",
    "user": "admin",
    "pwd": "admin",
    "gs": "DEFAULT"
  }
}

成功响应固定包含 status(始终为 succeeded)、result.verticesresult.edgeswarningsmetainclude_meta 不为 truemeta 为空。

Text2Gremlin

POST /text2gremlin

curl -X POST http://localhost:8001/text2gremlin \
  -H 'Content-Type: application/json' \
  -d '{
    "query": "查找所有 person 顶点",
    "example_num": 1,
    "output_types": ["template_gremlin", "template_execution_result"]
  }'

output_types 可包含:

  • match_result
  • template_gremlin
  • raw_gremlin
  • template_execution_result
  • raw_execution_result

省略该字段时默认只返回 template_gremlin;传空数组表示由实现返回全部输出。自定义 gremlin_prompt 必须包含 {query}{schema}{example}{vertices},缺少占位符时请求校验失败,并会列出缺失的占位符。

example_num 默认是 0,表示不使用模板,取值会被限制在 0 到 10 之间。client_config 只在单次请求内覆盖 HugeGraph 连接,生成时使用的 Schema 是当前生效的图名。query 为空返回 400,生成失败返回 500。

运行时配置

POST /config/graph

{
  "url": "127.0.0.1:8080",
  "graph": "hugegraph",
  "user": "admin",
  "pwd": "admin",
  "gs": "DEFAULT"
}

userpwd 默认是空字符串,gs 可选。

POST /config/llmPOST /config/embedding

两个端点使用同一个请求模型。/config/llm 会把 chat_llm_typeextract_llm_typetext2gql_llm_type 一起设为相同的值;要分别设置各任务的类型,只能通过 .env 或 Web 页面。OpenAI 或 LiteLLM 示例:

{
  "llm_type": "openai",
  "api_key": "your-key",
  "api_base": "https://api.openai.com/v1",
  "language_model": "gpt-4.1-mini",
  "max_tokens": "4096"
}

Ollama 请求仍要提供公共字段;api_keyapi_base 可传空字符串:

{
  "llm_type": "ollama/local",
  "api_key": "",
  "api_base": "",
  "language_model": "qwen2.5:7b",
  "host": "127.0.0.1",
  "port": "11434"
}

POST /config/rerank

{
  "reranker_type": "siliconflow",
  "reranker_model": "BAAI/bge-reranker-v2-m3",
  "api_key": "your-key"
}

reranker_type 可选 coheresiliconflow。Cohere 还可以传 cohere_base_url

四个配置端点成功时都返回 201。它们会改动进程当前配置,并可能同步到 .env/config/llm/config/embedding/config/rerank 在应用过程中抛出异常时会回滚到原有取值,/config/graph 不会。

/rag/rag/graph/text2gremlinclient_config 只在单次请求期间覆盖 HugeGraph 连接,且仅应用请求中实际出现的字段。当前实现仍会临时改动进程全局设置,不适合用不同连接并发发起长请求。

日志

POST /logs

该接口要求 .env 中的 ADMIN_TOKEN 已改成安全值。请求体示例:

{
  "admin_token": "replace-with-an-admin-secret",
  "log_file": "llm-server.log"
}

log_file 默认是 llm-server.log,只能是 logs/ 目录下的文件名,不能是绝对路径、不能包含路径分隔符,也不能解析为 ...。非法文件名返回 400。

ADMIN_TOKEN 未设置或仍是占位值时,在比对 token 之前就返回 403;token 不匹配时返回内容为 Invalid admin_token 的 403 响应。

成功时返回 text/plain 流:先回放文件末尾 125 行,然后像 tail -f 一样持续输出新内容。

6 - Vermeer Python 客户端

vermeer-python-clientVermeer 的 Python SDK。Vermeer 是使用 Go 编写、以内存计算为主的图计算引擎。该 SDK 封装了 Vermeer master 的 REST API,可以在 Python 中列出图、提交加载和计算任务、读取任务状态。导入时使用的包名是 pyvermeer

模块没有固定 Vermeer 服务端版本,它通过 HTTP 访问 Vermeer master,调用的接口见 API 概览

环境要求

  • 单独使用该模块需要 Python 3.9 或更高版本;HugeGraph-AI 仓库整体要求 Python 3.10 或更高版本
  • 一个可通过 HTTP 访问的 Vermeer master。默认 HTTP 端口为 6688;Docker 部署需发布 6688:6688,见 Vermeer 快速开始
  • uv(推荐)或 pip

运行时依赖:requestsurllib3python-dateutildecoratorrichsetuptools

安装

打包元数据中的发行包名是 vermeer-python-client,其版本号独立于仓库版本号管理。该包尚未发布到 PyPI,请从源码安装。

在 HugeGraph-AI 仓库根目录,使用 vermeer extra 把它安装到共用的虚拟环境中:

git clone https://github.com/apache/hugegraph-ai.git
cd hugegraph-ai
uv sync --extra vermeer
source .venv/bin/activate

vermeer-python-client 是以可编辑路径依赖的方式接入的,并不是 uv workspace member,因此在仓库根目录直接执行 uv sync 不会安装它,必须显式指定该 extra(或使用 --all-extras)。

单独安装该模块:

git clone https://github.com/apache/hugegraph-ai.git
cd hugegraph-ai/vermeer-python-client
uv sync
source .venv/bin/activate

连接 Vermeer master

from pyvermeer.client.client import PyVermeerClient

client = PyVermeerClient(
    ip="127.0.0.1",
    port=6688,
    token="",
    timeout=(0.5, 15.0),
    log_level="INFO",
)

构造函数参数:

参数类型默认值说明
ipstr必填Vermeer master 的主机名或 IP 地址
portint必填Vermeer master 的 REST 端口
tokenstr必填原样作为 Authorization 请求头发送
timeout(float, float)NoneNone连接超时和读取超时,单位为秒
log_levelstr"INFO"应用到共享 VermeerClient 日志器的级别

连接前需要了解的行为:

  • 当 master 不校验鉴权时,token 可以是空字符串,但不能是 None,否则会话会抛出 ValueError("Vermeer Token must be provided.")
  • timeout(连接超时, 读取超时) 二元组。VermeerConfig 自身的默认值是 (0.5, 15.0),但客户端总是把自己的参数传下去,因此不传 timeout 时实际存入的是 None,请求会一直等待。需要超时就显式传入该二元组。
  • 基础 URL 固定拼接为 http://{ip}:{port}/,即客户端只使用明文 HTTP。
  • 每个请求都会设置 Content-Type: application/json,并把 params 序列化进请求体,GET 请求也是如此。
  • 底层会话在 HTTP 500、502、504 时最多重试 3 次,退避系数为 0.1
  • log_level 设置的是名为 VermeerClient 的共享日志器的级别。它的控制台 handler 固定为 INFO,因此目前 DEBUG 级别的记录不会打印到控制台。

端到端示例

模块自带一个可运行的示例:vermeer-python-client/src/pyvermeer/demo/task_demo.py。下面的版本在其基础上增加了带超时和失败处理的任务状态轮询,等待加载成功后再读取图,并从环境变量读取 HugeGraph 密码:

import os
import time

from pyvermeer.client.client import PyVermeerClient
from pyvermeer.structure.task_data import TaskCreateRequest

client = PyVermeerClient(
    ip="127.0.0.1",
    port=6688,
    token="",
    timeout=(0.5, 15.0),
    log_level="INFO",
)

# 列出 master 上的任务
tasks = client.tasks.get_tasks()
print(tasks.to_dict())

# 从 HugeGraph 把图数据加载到 Vermeer
create_response = client.tasks.create_task(
    create_task=TaskCreateRequest(
        task_type="load",
        graph_name="DEFAULT-example",
        params={
            "load.hg_pd_peers": '["127.0.0.1:8686"]',
            "load.hugegraph_name": "DEFAULT/example/g",
            "load.hugegraph_username": "admin",
            "load.hugegraph_password": os.environ["HUGEGRAPH_PASSWORD"],
            "load.parallel": "10",
            "load.type": "hugegraph",
        },
    )
)
print(create_response.errcode, create_response.message)
if create_response.errcode != 0:
    raise RuntimeError(f"Could not create load task: {create_response.message}")

# 轮询本次创建的加载任务,直到成功、失败或超时
task_id = create_response.task.id
poll_timeout = 300.0
deadline = time.monotonic() + poll_timeout
while time.monotonic() < deadline:
    task = client.tasks.get_task(task_id)
    if task.errcode != 0:
        raise RuntimeError(f"Could not read task {task_id}: {task.message}")
    state = task.task.state
    print(task_id, state)
    if state == "loaded":
        break
    if state in ("error", "canceled"):
        raise RuntimeError(f"Load task {task_id} ended with state {state}")
    remaining = deadline - time.monotonic()
    if remaining > 0:
        time.sleep(min(1.0, remaining))
else:
    raise TimeoutError(f"Load task {task_id} did not finish within {poll_timeout}s")

# 图加载完成后查看图信息
print(client.graph.get_graph("DEFAULT-example").to_dict())

加载任务以 loaded 表示成功;errorcanceled 会中止示例,不再读取图。可按数据量调整 poll_timeout(此处为 300 秒)。轮询期限与 HTTP 连接、读取超时相互独立,已发出的请求及 SDK 重试可能使实际等待时间超过该期限。超时只停止客户端等待,不会取消服务端任务。

不要把真实的 HugeGraph 密码写死在脚本或配置文件中,请像上面这样从环境变量或凭据管理系统读取。

模块自带的 task_demo.py 使用 8688。运行前,请将其中 PyVermeerClientport 改为 6688,与默认 master HTTP 端口保持一致。根据安装后所在的目录选择对应命令:

仓库根目录安装(在 hugegraph-ai/ 下运行):

python vermeer-python-client/src/pyvermeer/demo/task_demo.py

独立安装(在 hugegraph-ai/vermeer-python-client/ 下运行):

python src/pyvermeer/demo/task_demo.py

API 概览

PyVermeerClient 以属性的方式暴露各个 API 组,目前注册了 graphtasks 两个组。

client.graph

方法Vermeer 接口返回值
get_graphs()GET /graphsGraphsResponse
get_graph(graph_name)GET /graphs/{graph_name}GraphResponse

client.tasks

方法Vermeer 接口返回值
get_tasks()GET /tasksTasksResponse
get_task(task_id)GET /task/{task_id}TaskResponse
create_task(create_task)POST /tasks/createTaskCreateResponse

pyvermeer/api/master.pypyvermeer/api/worker.py 目前只有许可证头,也没有注册到客户端上。因此尽管 pyvermeer/structure/ 下已经有 MasterResponseWorkersResponse,master 和 worker 信息暂时还无法通过客户端获取。

client.send_request(method, endpoint, params) 是这两个组共用的请求入口。对于还没有封装的 Vermeer 接口,可以直接调用它,返回值是解析后的 JSON 字典。

请求与响应对象

TaskCreateRequest(task_type, graph_name, params) 序列化为 {"task_type": ..., "graph": ..., "params": ...}。注意 graph_name 在报文中的字段名是 graph,与 Vermeer REST API 的请求体一致。

所有响应类型都继承 BaseResponse,提供 errcodemessage 属性和 to_dict() 方法。errcode0 表示成功,1 表示错误,-1 表示响应体中没有该字段。

  • GraphsResponse.graphsGraphResponse.graph 返回 VermeerGraph 对象,包含 namespace_namestatuscreate_timeupdate_timevertex_countedge_countworkersworker_groupuse_out_edgesuse_propertyuse_out_degreeuse_undirectedon_diskbackend_option
  • TasksResponse.tasksTaskResponse.taskTaskCreateResponse.task 返回 TaskInfo 对象,包含 idstatecreate_usercreate_typecreate_timestart_timeupdate_timegraph_namespace_nametypeparamsworkers
  • 时间字段由 python-dateutil 解析为 datetime 对象,空字符串会解析为 None

任务参数

客户端不会校验 params,键和值都会原样传给 Vermeer,因此可用的参数名由引擎决定,而不是由 SDK 决定。加载参数以及各算法的参数请参考 Vermeer 快速开始

使用流程与直接调用 REST API 相同:先创建 load 任务把图读入 Vermeer,等待任务完成,再针对已加载的图创建计算任务。

异常

pyvermeer.utils.exception 定义了四种异常,都由底层的 requests 或 JSON 解析失败包装而来:

异常触发场景
ConnectErrorrequests.ConnectionError,无法连接 master
TimeOutErrorrequests.Timeout,连接或读取超时
JsonDecodeError响应体不是合法的 JSON
UnknownError请求过程中的其他失败
from pyvermeer.utils.exception import ConnectError, TimeOutError

try:
    graphs = client.graph.get_graphs()
except (ConnectError, TimeOutError) as error:
    print(error)

客户端不检查响应的 HTTP 状态码,请通过返回对象的 errcodemessage 判断是成功还是 Vermeer 端返回了错误。

代码检查

在 HugeGraph-AI 仓库根目录执行格式化和静态检查:

./style/code_format_and_analysis.sh

源码位于 vermeer-python-client/src/pyvermeer/。该模块目前没有测试用例。

参考