游乐游手机版
首页/AI热点日报/热点详情

BAML与Neo4j:快速将网页内容转化为知识图谱

类型:热点整理2026-06-28
BAML语言从网页内容中提取实体与关系,格式化为Cytoscape兼容的JSON,再通过FastAPI端点上传至Neo4j图数据库,实现网页内容向知识图谱的自动化转换,从而支持高效的知识抽取与存储。

BAML(Boundary推出的专用语言)能够从非结构化数据中精准提取干净、结构化的输出。而Neo4j作为图数据库领域的标杆,其核心能力在于利用图结构——即节点与节点之间的关系——来存储和管理数据。

本文旨在演示如何扩展一个现有的BAML示例项目,将网页内容转化为图表示,并快速加载到Neo4j实例中。通俗地说,就是借助AI从网页中抽取知识,然后直接存入图数据库。

前提条件

  • 已安装 BAML CLI
  • 一个正在运行的 Neo4j 数据库

工作流程概览

我们先梳理整体思路。整个处理流水线为:从URL抓取内容 → 转换为Markdown → 使用BAML提取实体和关系 → 格式化成兼容Cytoscape的JSON → 最终上传到Neo4j。接下来,我们将逐一拆解这些环节。

1. FastAPI 服务

Boundary官方提供了一个示例代码,用于搭建简单的FastAPI服务器,通过BAML从硬编码的简历中提取数据。FastAPI框架非常出色,其内置的交互式API文档让开发者可以直接在浏览器中测试端点,大大减少了调试工作量。

初始阶段,我fork了该项目,并添加了一个实验性端点,专门用于从网页内容中提取实体和关系。该端点接收一个URL字符串列表作为参数。

底层逻辑十分直接:调用BAML函数将网页数据提取为结构化的JSON对象,随后上传至Neo4j。整个过程就像一条自动化的数据流水线。

@app.post("/url_to_graph")
async def extract_url_content(urls: list[str]):
    """General purpose conversion of contents from a list of urls to a graph"""
    
    # 1. Prep html to text conversion
    h = html2text.HTML2Text()
    h.ignore_links = False

    # 2. Extract text from each url
    markdown_contents = []
    for url in urls:
        try:
            response = requests.get(url)
            response.raise_for_status()
            html_content = response.text
            markdown_content = h.handle(html_content)
            markdown_contents.append(markdown_content)
        except Exception as e:
            markdown_contents.append(f"Error processing {url}: {str(e)}")

    # 3. Composite the text 
    combined_markdown = "nn".join(markdown_contents)

    # 4. Run BAML to get a Cytoscape graph JSON representation of text
    json_output = b.GenerateCytoscapeGraph(combined_markdown)
    json_str = str(json_output.model_dump_json())
    json_dict = json.loads(json_str)

    # 5. Upload the JSON data to Neo4j
    finished = upload_cytoscape_to_neo4j(json_dict)
    return {"finished": finished}

2. BAML 配置与函数定义

使用BAML时,项目根目录下会自动生成两个子文件夹:baml_srcbaml_client

baml_client文件夹的内容可以通过VS Code插件自动生成,或者在更新baml_src中的.baml文件后手动运行baml cli generate命令生成。

baml_src文件夹必须包含两个核心文件:main.bamlclients.bamlclients.baml用于定义基础模型规范,而main.baml则用于指定各种配置选项。

注意:版本号必须与CLI版本保持一致,否则自动生成的baml-client会无法正常工作。

添加的.baml文件可以包含以下三种元素中的一种或全部:

  • 模型规范(必需)
  • 函数(必需)
  • 测试(可选)

BAML函数定义了输入到输出的映射关系、使用的客户端模型以及LLM提示词。下面展示的是FastAPI端点调用的函数,其任务是将HTML文本转化为结构化的图数据。

模型类的定义逻辑类似于Pydantic,但语法更简洁——因为BAML本身就是基于Pydantic构建的。目标输出如下所示的结构化JSON:

    {
      "elements": {
        "nodes": [
          {
            "data": {
              "id": "neo4j_graph_database",
              "name": "Neo4j Graph Database",
              "label": "product",
              "description": "Self or fully-managed, deploy anywhere"
            }
          },
          {
            "data": {
              "id": "neo4j_auradb",
              "name": "Neo4j AuraDB",
              "label": "product",
              "description": "Fully-managed graph database as a service"
            }
          },
        ],
        "edges": [
          {
            "data": {
              "id": "edge_1",
              "source": "neo4j_graph_database",
              "target": "neo4j_auradb",
              "label": "RELATED_TO"
            }
          }
        ]
      }
    }

为此,我们需要在BAML中定义相应的模型类。

注意:BAML的类和函数名称在全局范围内必须唯一,即使定义在不同的.baml文件中也不行。此外,属性名以_开头(如_id)目前也是不允许的。

3. Cytoscape 格式

Cytoscape是一个广受欢迎的开源平台,专门用于可视化图(网络)数据。它使用的JSON数据格式简洁而灵活,除了节点必需的idlabel属性外,还可以附带其他自定义数据。

上述BAML模型描述中展示的JSON示例正是这种格式。之所以选择Cytoscape.js作为中间图数据格式,是因为Neo4j本身并没有“官方首选”的JSON格式,而且后续演示中我还计划直接用Cytoscape对这些图数据进行可视化——一举两得。

4. Neo4j 数据导入

Neo4j是图数据库领域的领导者。它原生使用Cypher查询语言来输入、操作和输出图数据。因此,在本演示中,我选择了官方支持的neo4j bolt Python包,在cytoscape2neo4j.py文件中编写上传逻辑,将Cytoscape格式的JSON数据导入Neo4j。

详细说明upload_cytoscape_to_neo4j函数需要较大篇幅,恐怕得单独写一篇文章。简单来说,该函数会遍历源JSON中的每个节点和每条关系,为每个节点生成Cypher创建查询,为每条边创建对应的关系。

当然,除了这种方法,也可以考虑使用对象图映射(OGM)包(如Neomodel),或者搭建Apollo GraphQL服务器作为JSON与Neo4j之间的桥梁。

运行示例

完整应用代码已托管在公共Github仓库中。按照安装和运行说明操作后,打开任意浏览器,访问localhost:8000/docs,即可看到FastAPI简洁美观的交互式API文档页面。

服务器上还包含其他实验性端点,但本文重点介绍/url_to_graph选项。

测试方法很简单:打开端点详情,点击“Try It Out”按钮,输入一个或多个有效的网页URL,然后点击“Execute”。

根据源网页的数量和大小,等待几秒钟后,应该会收到finished:true的响应。

同时,在终端或控制台中,您会看到类似下边的输出:

    ...
    ---Parsed Response (class CytoscapeJSON)---
    {
      "elements": {
        "nodes": [
          {
            "data": {
              "id": "neo4j_graph_database",
              "name": "Neo4j Graph Database",
              "label": "product",
              "description": "Self or fully-managed, deploy anywhere"
            }
          },
          {
            "data": {
              "id": "neo4j_auradb",
              "name": "Neo4j AuraDB",
              "label": "product",
              "description": "Fully-managed graph database as a service"
            }
          },
          {
            "data": {
              "id": "generative_ai",
              "name": "Generative AI",
              "label": "use_case",
              "description": "Back your LLMs with a knowledge graph for better business AI"
            }
          }
        ],
        "edges": [
          {
            "data": {
              "id": "prod_use_case_1",
              "source": "neo4j_graph_database",
              "target": "generative_ai",
              "label": "ENABLED_BY"
            }
          },
          {
            "data": {
              "id": "prod_use_case_2",
              "source": "neo4j_auradb",
              "target": "generative_ai",
              "label": "ENABLED_BY"
            }
          }
        ]
      }
    }
INFO:     127.0.0.1:63190 - "POST /url_to_graph HTTP/1.1" 200 OK

最后,打开Neo4j的控制台,您会看到数据已经成功存入图数据库中。

来源:https://www.53ai.com/news/knowledgegraph/2024122634280.html

相关热点

继续查看同栏目近期热点。

延伸阅读

补充最近整理过的热点入口。