news 2026/4/3 1:22:05

831-LangChain框架Use-Cases - 电影问答系统案例分析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
831-LangChain框架Use-Cases - 电影问答系统案例分析

目录

  • 1. 案例目标
  • 2. 技术栈与核心依赖
  • 3. 环境配置
  • 4. 案例实现
  • 5. 案例效果
  • 6. 案例实现思路
  • 7. 扩展建议
  • 8. 总结

1. 案例目标

本案例旨在构建一个基于Neo4j图数据库的电影问答系统,使用LangChain框架将自然语言查询转换为Cypher查询语句,从而实现对电影数据的智能问答。该系统能够理解用户关于电影的自然语言问题,自动生成相应的Cypher查询,从Neo4j数据库中检索相关信息,并以自然语言形式返回答案。

核心功能:

  • 自然语言到Cypher查询的自动转换
  • 基于电影和关键词的复杂查询处理
  • 支持多条件组合查询(如电影类型与流行度组合)
  • 支持聚合查询(如计算平均流行度)

2. 技术栈与核心依赖

本案例使用了以下主要技术和依赖:

技术/库版本用途
Python3.11.11编程语言
langchain0.1.0核心框架,提供链式处理能力
langchain-openai0.0.5OpenAI模型集成
langchain-neo4j0.0.1Neo4j图数据库集成
neo4j5.15.0Neo4j Python驱动
kagglehub0.2.5从Kaggle下载数据集
openai1.6.1OpenAI API客户端
tiktoken0.5.2OpenAI的token计算工具

注意:本案例使用了GPT-4模型作为语言模型,需要配置有效的OpenAI API密钥。

3. 环境配置

在运行本案例之前,需要进行以下环境配置:

3.1 安装依赖包

%pip install -qU langchain langchain-openai langchain-neo4j neo4j kagglehub

3.2 配置API密钥

import getpass import os os.environ["OPENAI_API_KEY"] = getpass.getpass() os.environ["NEO4J_URI"] = "bolt://localhost:7687" os.environ["NEO4J_USERNAME"] = "neo4j" os.environ["NEO4J_PASSWORD"] = getpass.getpass()

3.3 Neo4j数据库配置

本案例假设已在本地安装并运行了Neo4j数据库,默认端口为7687。需要提供用户名和密码进行连接。

警告:确保Neo4j数据库服务已启动,并且提供的用户名和密码正确无误。

4. 案例实现

4.1 连接Neo4j数据库

首先,创建与Neo4j数据库的连接:

from langchain_neo4j import Neo4jGraph graph = Neo4jGraph() # 清除现有数据 graph.query("MATCH (n) DETACH DELETE n")

4.2 加载示例电影数据

使用提供的示例数据创建电影和人物节点及其关系:

# 创建电影节点 movies_query = """ MERGE (m:Movie {title: $movie.title}) ON CREATE SET m.released = $movie.released, m.tagline = $movie.tagline """ # 创建人物节点和关系 actors_query = """ MERGE (p:Person {name: $person.name}) ON CREATE SET p.born = $person.born WITH p MERGE (m:Movie {title: $movie.title}) MERGE (p)-[r:ACTED_IN]->(m) ON CREATE SET r.roles = $person.roles """ directors_query = """ MERGE (p:Person {name: $person.name}) ON CREATE SET p.born = $person.born WITH p MERGE (m:Movie {title: $movie.title}) MERGE (p)-[:DIRECTED]->(m) """ # 执行查询 for movie, actors, director in zip(movies, actors, directors): graph.query(movies_query, params={"movie": movie}) for actor in actors: graph.query(actors_query, params={"movie": movie, "person": actor}) graph.query(directors_query, params={"movie": movie, "person": director})

4.3 定义图模式

查看和定义图数据库的模式结构:

graph.refresh_schema() print(graph.schema)

节点属性:

Movie {tagline: STRING, title: STRING, released: INTEGER}

Person {born: INTEGER, name: STRING}

关系属性:

ACTED_IN {roles: LIST}

关系:

(:Person)-[:ACTED_IN]->(:Movie)

(:Person)-[:DIRECTED]->(:Movie)

4.4 创建GraphCypherQAChain

使用LangChain的GraphCypherQAChain将自然语言转换为Cypher查询:

from langchain_neo4j import GraphCypherQAChain from langchain_openai import ChatOpenAI llm = ChatOpenAI(model="gpt-4o", temperature=0) chain = GraphCypherQAChain.from_llm( graph=graph, llm=llm, verbose=True, allow_dangerous_requests=True )

4.5 执行查询

使用创建的链执行自然语言查询:

response = chain.invoke({"query": "Who was the director of the movie Forrest Gump?"}) response

4.6 使用Kaggle电影数据集

案例还展示了如何从Kaggle下载并导入更大的电影数据集:

import kagglehub # 下载数据集 path = kagglehub.dataset_download("rounakbanik/the-movies-dataset") # 移动文件到Neo4j导入目录 import shutil import os neo4j_import_dir = "/var/lib/neo4j/import/" # Linux路径 # Windows路径可能是: "C:\\Users\\Neo4j\\.Neo4jDesktop\\relate-data\\dbmss\\dbms-xxx\\import\\" shutil.copy(os.path.join(path, "movies_metadata.csv"), neo4j_import_dir) shutil.copy(os.path.join(path, "keywords.csv"), neo4j_import_dir)

4.7 导入Kaggle数据到Neo4j

# 导入电影数据 movies_query = """ LOAD CSV WITH HEADERS FROM 'file:///movies_metadata.csv' AS row WITH row WHERE row.id IS NOT NULL MERGE (m:Movie {id: row.id}) SET m.title = row.title, m.popularity = toFloat(row.popularity) """ # 导入关键词数据 keywords_query = """ CALL apoc.periodic.iterate( "LOAD CSV WITH HEADERS FROM 'file:///keywords.csv' AS row RETURN row", "WITH row, apoc.convert.fromJsonList(row.keywords) AS keywords UNWIND keywords AS keyword MERGE (k:Keyword {name: keyword.name}) MERGE (m:Movie {id: row.id}) MERGE (m)-[:HAS_KEYWORD]->(k)", {batchSize: 1000, parallel: true} ) """ graph.query(movies_query) graph.query(keywords_query)

4.8 使用增强模式

使用增强模式获取更详细的图结构信息:

enhanced_graph = Neo4jGraph(enhanced_schema=True) print(enhanced_graph.schema)

节点属性:

-Movie
- `id`: STRING 示例: "862"
- `title`: STRING 示例: "Toy Story"
- `popularity`: FLOAT 示例: "21.946943"

-Keyword
- `name`: STRING 示例: "terror"

关系:

(:Movie)-[:HAS_KEYWORD]->(:Keyword)

4.9 执行复杂查询

使用增强图数据执行更复杂的查询:

llm = ChatOpenAI(model="gpt-4o", temperature=0) chain = GraphCypherQAChain.from_llm( graph=enhanced_graph, llm=llm, verbose=True, allow_dangerous_requests=True ) # 查询示例1 response = chain.invoke({ "query": "What movies have a popularity score above 8.0 and are tagged with 'comedy'?" }) # 查询示例2 response = chain.invoke({ "query": "What is the average popularity score of movies tagged with 'romance'?" }) # 查询示例3 response = chain.invoke({ "query": "What movies are tagged with both 'comedy' and 'romance'?" })

5. 案例效果

本案例实现了以下效果:

5.1 自然语言查询转换

系统能够将自然语言问题自动转换为Cypher查询语句,例如:

  • 输入:"Who was the director of the movie Forrest Gump?"
  • 生成的Cypher查询:
    cypher MATCH (p:Person)-[:DIRECTED]->(m:Movie {title: 'Forrest Gump'}) RETURN p.name
  • 输出:"Robert Zemeckis was the director of the movie Forrest Gump."

5.2 复杂条件查询

系统能够处理包含多个条件的复杂查询:

  • 输入:"What movies have a popularity score above 8.0 and are tagged with 'comedy'?"
  • 生成的Cypher查询:
    cypher MATCH (m:Movie)-[:HAS_KEYWORD]->(k:Keyword {name: 'comedy'}) WHERE m.popularity > 8.0 RETURN m.title
  • 输出:"Ratchet & Clank, Kick-Ass, Jackass 3D, Aliens in the Attic, A Dog's Will have a popularity score above 8.0 and are tagged with 'comedy'."

5.3 聚合查询

系统能够处理需要聚合计算的查询:

  • 输入:"What is the average popularity score of movies tagged with 'romance'?"
  • 生成的Cypher查询:
    cypher MATCH (m:Movie)-[:HAS_KEYWORD]->(k:Keyword {name: 'romance'}) RETURN avg(m.popularity) AS average_popularity
  • 输出:"The average popularity score of movies tagged with 'romance' is 12.390850747422673."

5.4 多关系查询

系统能够处理涉及多个关系的查询:

  • 输入:"What movies are tagged with both 'comedy' and 'romance'?"
  • 生成的Cypher查询:
    cypher MATCH (m:Movie)-[:HAS_KEYWORD]->(k1:Keyword {name: 'comedy'}), (m)-[:HAS_KEYWORD]->(k2:Keyword {name: 'romance'}) RETURN m.title
  • 输出:"Lisbela and the Prisoner, Love Hina Christmas Special: Silent Eve, Love Is in the Air are tagged with both 'comedy' and 'romance'."

6. 案例实现思路

本案例的实现思路可以分为以下几个关键步骤:

6.1 数据模型设计

案例采用了图数据库的数据模型,将电影、人物和关键词表示为节点,将它们之间的关系表示为边:

  • 电影节点(Movie):包含标题、发布年份、标语和流行度等属性
  • 人物节点(Person):包含姓名和出生年份等属性
  • 关键词节点(Keyword):包含关键词名称属性
  • 关系:ACTED_IN(出演)、DIRECTED(导演)、HAS_KEYWORD(拥有关键词)

6.2 自然语言到Cypher的转换

案例的核心是使用LangChain的GraphCypherQAChain将自然语言转换为Cypher查询:

  1. 接收用户自然语言查询
  2. 利用图数据库模式信息生成提示词
  3. 将提示词发送给LLM(如GPT-4)生成Cypher查询
  4. 在Neo4j数据库中执行生成的Cypher查询
  5. 将查询结果转换为自然语言回答

6.3 增强模式的使用

案例使用了Neo4j的增强模式功能,提供更详细的图结构信息:

  • 包含属性的数据类型信息
  • 提供属性值的示例
  • 帮助LLM更准确地生成Cypher查询

6.4 大规模数据处理

案例展示了如何处理大规模数据集:

  • 使用KaggleHub下载大型电影数据集
  • 使用Neo4j的LOAD CSV命令批量导入数据
  • 使用APOC过程的periodic.iterate进行并行处理

注意:在导入大规模数据时,可能会遇到死锁问题,如案例中所示。可以通过调整批处理大小和并行度来缓解此类问题。

7. 扩展建议

基于本案例的实现,以下是一些可能的扩展方向:

7.1 增强查询能力

  • 支持更复杂的查询:扩展系统以支持更复杂的自然语言查询,如时间序列分析、路径查询等
  • 多轮对话:实现多轮对话功能,允许用户基于之前的回答进行追问
  • 模糊查询:支持模糊匹配和容错查询,提高用户体验
  • 查询优化:实现查询优化策略,提高复杂查询的执行效率

7.2 扩展数据模型

  • 添加更多实体类型:如导演、演员、制片公司、奖项等
  • 丰富关系类型:如"合作"、"获奖"、"评价"等
  • 时间维度:添加时间维度,支持历史数据查询和趋势分析
  • 用户数据:集成用户评分、评论等数据,支持个性化推荐

7.3 改进用户体验

  • 可视化界面:开发Web界面,提供可视化查询和结果展示
  • 查询建议:基于用户输入提供查询建议和自动补全
  • 结果解释:提供查询结果的解释和可视化展示
  • 多语言支持:支持多种自然语言的查询和回答

7.4 技术优化

  • 缓存机制:实现查询结果缓存,提高常用查询的响应速度
  • 模型微调:针对特定领域微调LLM,提高查询转换的准确性
  • 分布式处理:实现分布式图数据库和查询处理,支持更大规模数据
  • 实时更新:支持数据的实时更新和增量导入

7.5 应用场景扩展

  • 推荐系统:基于图数据构建电影推荐系统
  • 知识图谱:扩展为更广泛的电影知识图谱
  • 情感分析:集成用户评论的情感分析结果
  • 跨领域查询:支持电影与其他领域(如音乐、书籍)的关联查询

8. 总结

本案例成功展示了如何使用LangChain和Neo4j构建一个电影问答系统。该系统通过将自然语言查询转换为Cypher查询语句,实现了对电影数据的智能问答。案例涵盖了从环境配置、数据导入、模式定义到查询执行的完整流程,并展示了如何处理小规模示例数据和大规模真实数据集。

主要成就:

  • 成功实现了自然语言到Cypher查询的自动转换
  • 展示了图数据库在复杂关系查询中的优势
  • 演示了LangChain框架与Neo4j图数据库的集成方法
  • 提供了处理大规模图数据的实践经验

技术亮点:

  • 使用增强模式提供更详细的图结构信息,提高查询转换准确性
  • 利用APOC过程实现高效的数据导入和处理
  • 结合GPT-4模型实现高质量的自然语言理解和查询生成
  • 展示了从简单到复杂查询的渐进式实现方法

该案例为构建基于图数据库的智能问答系统提供了完整的参考实现,可以作为其他领域问答系统开发的基础模板。通过适当的调整和扩展,该方法可以应用于各种需要复杂关系查询的场景,如社交网络分析、生物信息学研究、金融风控等领域。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!