昨天写了一篇文章,使用fastapi直接操作neo4j图数据库插入数据的例子, 本文实现LLM大模型结合neo4j图数据库实现AI问答功能。
废话不多说,先上代码
python
import gradio as gr
from fastapi import FastAPI, HTTPException, Request
from pydantic import BaseModel
from langchain_openai import ChatOpenAI
from langchain.prompts import (
ChatPromptTemplate,
MessagesPlaceholder,
SystemMessagePromptTemplate,
HumanMessagePromptTemplate,
)
from langchain.chains import LLMChain
from langchain.memory import ConversationBufferMemory
from langchain_community.graphs import Neo4jGraph
from langchain.chains import GraphCypherQAChain
import asyncio
from typing import List
import json
# Initialize FastAPI
app = FastAPI()
# Initialize Neo4j with timeout
try:
graph = Neo4jGraph(
url="bolt://localhost:7687",
username="neo4j",
password="password",
database="neo4j",
timeout=60 # 60 seconds timeout
)
except Exception as e:
print(f"Failed to connect to Neo4j: {e}")
graph = None
# Fallback in-memory storage
job_seekers = []
job_positions = []
# Initialize LangChain components
llm = ChatOpenAI(
temperature=0.95,
model="glm-4-flash",
openai_api_key="xxxxxx",
openai_api_base="https://open.bigmodel.cn/api/paas/v4/"
)
prompt = ChatPromptTemplate(
messages=[
SystemMessagePromptTemplate.from_template(
"You are a helpful AI assistant for a recruitment company. You can answer questions about job seekers and available positions."
),
MessagesPlaceholder(variable_name="chat_history"),
HumanMessagePromptTemplate.from_template("{question}")
]
)
memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True)
conversation = LLMChain(
llm=llm,
prompt=prompt,
verbose=True,
memory=memory
)
# Initialize GraphCypherQAChain if Neo4j is available
if graph:
graph_qa = GraphCypherQAChain.from_llm(
llm,
graph=graph,
verbose=True
)
# Define chat function with timeout
async def chat_with_timeout(message, history):
try:
if graph:
neo4j_response = await asyncio.wait_for(
asyncio.to_thread(graph_qa.run, message),
timeout=10.0 # 10 seconds timeout
)
return f"Based on our database: {neo4j_response}"
else:
# Fallback to in-memory data
if "job seekers" in message.lower():
return f"Based on our records: We have {len(job_seekers)} job seekers."
elif "job positions" in message.lower():
return f"Based on our records: We have {len(job_positions)} job positions."
else:
response = conversation.invoke({"question": message})
return response['text']
except asyncio.TimeoutError:
return "I'm sorry, but the database query took too long. Please try a simpler question or try again later."
except Exception as e:
print(f"Error in chat function: {e}")
response = conversation.invoke({"question": message})
return response['text']
# # Create Gradio interface
iface = gr.ChatInterface(chat_with_timeout)
#
# # Mount Gradio app to FastAPI
app = gr.mount_gradio_app(app, iface, path="/")
# Run the app
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)
还是老规矩,先AI解释下,构建一个基于FastAPI和Gradio的聊天应用,主要功能如下:
1、初始化FastAPI应用和Neo4j图数据库连接(带超时处理);
2、定义了用于对话的LangChain组件,包括LLM模型、提示模板及对话记忆;
3、根据Neo4j是否可用初始化图查询链;
4、实现异步聊天函数,支持数据库查询数据检索,并处理超时错误;
5、使用Gradio创建用户界面并将应用挂载到FastAPI上。
核心关注graph_qa.run方法,执行原理:
- 自然语言处理:
当调用 graph_qa.run(message)
时,首先会将用户的自然语言查询(message
)传递给大语言模型(LLM)。
- Cypher 查询生成:
LLM 分析用户的查询,并尝试将其转换为 Cypher 查询语言。Cypher 是 Neo4j 图数据库使用的查询语言。这个步骤涉及到理解用户意图和将其映射到图数据库的结构上。
- 数据库查询:
生成的 Cypher 查询被发送到 Neo4j 数据库执行。这个过程涉及到遍历图数据库,匹配节点和关系,并检索相关数据。
- 结果解释:
数据库返回查询结果后,这些结果会被传回给 LLM。LLM 会分析这些原始数据,理解其含义和上下文。
- 响应生成:
最后,LLM 会根据原始查询和数据库返回的结果,生成一个人类可读的响应。这个响应应该直接回答用户的问题,并可能包含从数据库中提取的具体信息。
在上一篇文章中,我已经在neo4j插入了一些数据,比如张三1的技能。 这里问一下