大家好!

在这个全民 RAG 的时代,人们似乎找到了一条蹭 AI 的捷径。大模型加上领域知识分分钟包装成知识库,智能体,垂直大模型?但在实际应用中,传统 RAG 并不能解决所有问题,尤其是需要复杂推理和关系分析的场景。知识图谱(Knowledge Graph)作为结构化语义网络,能更好地表达实体及其关系,补足 RAG 的不足。

本文将结合 Neo4j 图数据库和大语言模型(LLM),介绍如何实现一个简单的问答系统。当然我也还在学习跟尝试当中,如有不当的地方请友好探讨。

什么是 Knowledge Graph

知识图谱(Knowledge Graph)是一种通过节点和关系来表达知识的结构化方式。

节点(Node):节点代表知识图谱中的实体,可以是人、地点、事物、事件等。例如,“张三”、“北京”、“苹果公司”都可以作为节点。

边(Edge):边用于连接两个节点,表示它们之间存在某种关系。每条边都有方向和类型。例如,“张三”——[居住于]——>“北京”,“苹果公司”——[创始人]——>“乔布斯”。

关系(Relationship):关系是边的具体类型,描述节点之间的语义联系。关系可以是“属于”、“包含”、“朋友”、“创始人”等。关系通常带有属性,比如时间、权重等。

通过节点和边的组合,知识图谱能够以图结构的方式表达复杂的现实世界知识,实现语义理解和推理。

知识图谱与RAG的对比

RAG(Retrieval-Augmented Generation,检索增强生成)是一种结合检索与生成的AI问答技术。它通常通过向量数据库检索相关文档片段,然后用大模型进行生成式回答。

对比点:

  • 结构化 vs 非结构化:知识图谱以结构化的图数据存储知识,节点和关系清晰;RAG主要处理非结构化文本,通过语义检索相关内容。
  • 推理能力:知识图谱支持复杂的语义推理和关系查询,适合多跳问答和实体关系分析;RAG更依赖检索结果和大模型的生成能力,推理能力受限于检索和模型本身。
  • 更新与扩展:知识图谱需要人工或自动化方式维护结构和关系,扩展时需保证一致性;RAG可以直接添加新文档,扩展更灵活。
  • 应用场景:知识图谱适合企业知识管理、推荐、风控等场景;RAG适合快速搭建问答系统、文档检索、智能客服等。

实际应用中,知识图谱和RAG可以结合使用,既利用结构化知识进行推理,又用检索增强生成提升问答的广度和灵活性。

Neo4j

本次试验我们使用 Neo4j 作为图数据库。
Neo4j 是一个高性能的开源图数据库,专门用于存储和管理图结构数据。它以节点、关系和属性为核心,能够高效地处理复杂的连接和关系查询。

Neo4j 的主要特点:

  • 原生图存储:Neo4j 采用原生图结构进行存储和处理,节点和关系都是一等公民,查询效率高。
  • 强大的查询语言 Cypher:Cypher 是 Neo4j 的声明式图查询语言,语法简洁,易于表达复杂的图查询。
  • 高性能关系查询:相比传统关系型数据库,Neo4j 在多跳关系、路径查找等场景下有显著性能优势。
  • 灵活的数据模型:支持动态添加节点、关系和属性,适合不断变化的业务需求。
  • 可扩展性和高可用性:支持集群部署,适合大规模数据和高并发访问。

Neo4j 广泛应用于社交网络、推荐系统、知识图谱、风控反欺诈等领域,能够帮助企业高效地挖掘和分析数据中的关联关系。

初始化数据

安装 Neo4j

安装的话使用 docker 非常的方便,不多说。

docker run \
    --restart always \
    --publish=7474:7474 --publish=7687:7687 \
    neo4j:2025.06.2

在我们进行试验前,需要先准备一些数据到 neo4j 的数据库里。这里采用 Neo4j 安装向导自带的一个关于演员与电影之间的知识库。包含 38 部电影与 133 个演员的信息。


CREATE CONSTRAINT movie_title IF NOT EXISTS FOR (m:Movie) REQUIRE m.title IS UNIQUE;
CREATE CONSTRAINT person_name IF NOT EXISTS FOR (p:Person) REQUIRE p.name IS UNIQUE;

MERGE (TheMatrix:Movie {title:'The Matrix'}) ON CREATE SET TheMatrix.released=1999, TheMatrix.tagline='Welcome to the Real World'

MERGE (Keanu:Person {name:'Keanu Reeves'}) ON CREATE SET Keanu.born=1964
MERGE (Carrie:Person {name:'Carrie-Anne Moss'}) ON CREATE SET Carrie.born=1967
MERGE (Laurence:Person {name:'Laurence Fishburne'}) ON CREATE SET Laurence.born=1961
MERGE (Hugo:Person {name:'Hugo Weaving'}) ON CREATE SET Hugo.born=1960
MERGE (LillyW:Person {name:'Lilly Wachowski'}) ON CREATE SET LillyW.born=1967
MERGE (LanaW:Person {name:'Lana Wachowski'}) ON CREATE SET LanaW.born=1965
MERGE (JoelS:Person {name:'Joel Silver'}) ON CREATE SET JoelS.born=1952
...


访问数据库

使用 C# 去访问 Neo4j 呢也相当简单。安装相关的驱动把 cypher 发过去就行了。

  <ItemGroup>
    <PackageReference Include="Neo4j.Driver" Version="5.28.2" />
  </ItemGroup>

代码:

const string dbUri = "neo4j://125.gen8.com:7687";
const string dbUser = "neo4j";
const string dbPassword = "neo4j@123";

await using var driver = GraphDatabase.Driver(dbUri, AuthTokens.Basic(dbUser, dbPassword));
await driver.VerifyConnectivityAsync();
Console.WriteLine("Connection established.");

var query = "MATCH (n)-[r]-(m) RETURN *";
var result = await driver.ExecutableQuery(query)
    .WithConfig(new QueryConfig(database: "neo4j"))
    .ExecuteAsync();

实现 chatbot

要实现这个 chatbot 呢,首先让我们来理一下整个流程:

graph TD
    A[用户输入问题] --> B[LLM 生成 Cypher 查询语句]
    B --> C[C# 代码访问 Neo4j 数据库]
    C --> D[Neo4j 返回查询结果]
    D --> E[LLM 总结并生成回答]
    E --> F[返回给用户]

流程说明:

  1. 用户输入自然语言问题。
  2. LLM(大语言模型)将问题转化为 Cypher 查询语句。
  3. C# 程序将 Cypher 语句发送到 Neo4j 数据库。
  4. Neo4j 执行查询并返回结果。
  5. LLM 根据查询结果生成最终回答。
  6. 答案返回给用户。

直接看完整代码吧,测试模型试验 gpt-4.1,SK 什么的背景知识就不解释了,可以翻以前的文章。

// Populate values from your OpenAI deployment
var modelId = "gpt-4.1";
var endpoint = "https://kklldog-openai.openai.azure.com/";
var apiKey = "";

// Create a kernel with Azure OpenAI chat completion
var builder = Kernel.CreateBuilder();
builder.AddAzureOpenAIChatCompletion(modelId, endpoint, apiKey);

var sk = builder.Build();

var chatCompletionService = sk.GetRequiredService<IChatCompletionService>();

//var q = "Who is Tom Cruise ?";

var q = Console.ReadLine();

// round1 => get cypher query
ChatHistory chatHistory = [
    new() {
        Role = AuthorRole.System,
        Content = "你是一个neo4j的专家,当收到问题后,请尝试给出可以帮助回答问题的 cypher 查询语句。" +
        "你可以使用以下标签:" +
        "Movie,Person " +
        "你可以使用以下关系:" +
        "ACTED_IN,DIRECTED,FOLLOWS,PRODUCED,REVIEWED,WROTE " +
        "请直接返回cypher语句,不需要多余的内容"
    },
    new() {
        Role = AuthorRole.User,
        Content = q
    }
];
var chatResponse = await chatCompletionService.GetChatMessageContentAsync(
    chatHistory
);

string query = chatResponse.ToString();
Console.WriteLine(query);

const string dbUri = "neo4j://125.gen8.com:7687";
const string dbUser = "neo4j";
const string dbPassword = "neo4j@123";

await using var driver = GraphDatabase.Driver(dbUri, AuthTokens.Basic(dbUser, dbPassword));
await driver.VerifyConnectivityAsync();
Console.WriteLine("Connection established.");

var result = await driver.ExecutableQuery(query)
    .WithConfig(new QueryConfig(database: "neo4j"))
    .ExecuteAsync();

var answerTxt = JsonConvert.SerializeObject(result.Result);
Console.WriteLine(answerTxt);

// round2 => get answer
ChatHistory chatHistory_1 = [
    new() {
        Role = AuthorRole.System,
        Content = "我会给你一段 cypher 语句,以及它的查询结果。请根据这些内容对问题进行回答,如果无法回答就说不知道。" +
        "query:" + query +  
        "answer:" + answerTxt
    },
    new() {
        Role = AuthorRole.User,
        Content = q
    }
];
var chatResponse_1 = await chatCompletionService.GetChatMessageContentAsync(
    chatHistory_1
);

Console.WriteLine(chatResponse_1);

运行程序

让我们试跑一下,输入问题:How many movies does tom cruise acted in?

Hello, World!
How many movies does tom cruise acted in?
MATCH (p:Person {name: "Tom Cruise"})-[:ACTED_IN]->(m:Movie)
RETURN count(m) AS num_movies
Connection established.
[{"num_movies":3}]
Tom Cruise has acted in 3 movies.

总结

本文介绍了如何结合 Neo4j 图数据库与大语言模型(LLM)实现一个简单的问答系统。通过知识图谱结构化存储信息,利用 LLM 自动生成 Cypher 查询语句,并用 C# 代码访问 Neo4j 获取结果,最后由 LLM 进行答案总结,实现了从自然语言到结构化知识的闭环。

这种方案的优势在于:

  • 能够充分发挥知识图谱的语义推理和关系查询能力;
  • LLM 自动生成查询语句,降低了用户的技术门槛;
  • 查询结果可直接用于生成自然语言答案,提升问答系统的智能化水平。

未来可以进一步扩展:

  • 丰富知识图谱的数据和关系类型;
  • 优化 LLM 的提示词和上下文设计,提高查询准确率;
  • 支持更复杂的问题和多轮对话。

总之,Neo4j + LLM 的结合为智能问答和知识管理提供了强大的技术基础,值得在更多场景中探索和应用。