在本章中,我们将开始探索如何将 Haystack 与 Neo4j 集成,结合大语言模型(LLMs)和图数据库的能力,构建一个 AI 驱动的搜索系统。Haystack 是一个开源框架,支持开发者利用现代自然语言处理技术、机器学习模型和基于图的数据,创建智能应用。对于我们的智能搜索系统,Haystack 将作为一个统一的平台,协调 LLM、搜索引擎和数据库,实现高度上下文化且相关性强的搜索结果。
基于上一章对 Neo4j 数据进行清洗和结构化的工作,我们将从使用 OpenAI 的 GPT 模型生成向量(embeddings)开始。这些向量将丰富图数据库,使其更强大,能够处理细腻且具上下文意识的搜索查询。Haystack 将作为 OpenAI 模型与 Neo4j 图数据库之间的桥梁,结合双方的优势。
本章内容包括如何设置和配置 Haystack,以实现与 Neo4j 的无缝集成。我们将引导你构建强大的搜索功能,最终使用 Gradio 部署完整的搜索系统,并托管在 Hugging Face Spaces 上。
本章主要涵盖以下内容:
- 使用 Haystack 生成向量,增强 Neo4j 图数据
- 将 Haystack 连接至 Neo4j,实现高级向量搜索
- 构建强大的搜索体验
- 对 Haystack 集成进行微调
技术要求
为了顺利实现 Haystack 和 Neo4j 的集成,并构建 AI 驱动的搜索系统,你需要确保开发环境已正确配置。以下是本章所需的技术条件:
-
Python:需要安装 Python 3.11,Python 用于脚本编写和与 Neo4j 交互。可从 Python 官方网站下载安装:www.python.org/downloads/。
-
Neo4j AuraDB 或本地 Neo4j 实例:你需要有一个 Neo4j 数据库用于存储和查询图数据,可以是本地安装的 Neo4j,也可以是云端的 Neo4j AuraDB。如果你从上一章继续,可以使用之前搭建并导入数据的 Neo4j 实例,保持工作连贯。
-
Cypher 查询语言:熟悉 Cypher 查询语言非常重要,本章会大量使用 Cypher 创建和查询图数据。详细语法请参考:neo4j.com/docs/cypher...。
-
Neo4j Python 驱动:安装 Neo4j Python 驱动,通过 Python 连接 Neo4j,安装命令如下:
pip install neo4j
-
Haystack:本章使用 Haystack 版本 v2.5.0,安装命令如下:
pip install haystack-ai
-
OpenAI API 密钥:为了使用基于 GPT 的模型生成向量,你需要一个有效的 OpenAI API 密钥。
-
如果还没有账号,请在 OpenAI 注册:platform.openai.com/signup。
-
免费套餐的 API 密钥多数场景无法满足本项目需求,需要订阅付费版本以访问必要的接口和额度。
-
登录后进入 API 密钥管理页面:platform.openai.com/api-keys,生成新的 API 密钥。
-
同时安装 OpenAI Python 包:
pip install openai
-
-
Gradio:用于创建用户友好的聊天界面,安装命令:
pip install gradio
-
Hugging Face 账户:要将聊天机器人部署到 Hugging Face Spaces,需要注册 Hugging Face 账户,网址:huggingface.co/。
-
Google Cloud Storage(可选):如果你将 CSV 文件存储在 Google Cloud Storage,需要在脚本中正确配置文件路径。
-
python-dotenv 包:用于管理项目中的环境变量,安装命令:
pip install python-dotenv
本章所有代码示例和资源均托管在 GitHub 仓库:github.com/PacktPublis...
在该仓库中,进入名为 ch6 的文件夹,可以找到本章相关的脚本、文件和配置,包含 Neo4j 与 Haystack 集成及基于电影数据集构建 AI 搜索系统的全部内容。请克隆或下载仓库以便跟随示例操作。
使用 Haystack 生成向量,增强你的 Neo4j 图数据
本节重点介绍如何为上一章中添加到 Neo4j 图中的电影剧情生成向量。向量是现代搜索系统的关键,它将文本转换成高维向量,支持相似度搜索,从而让搜索引擎能够理解词语和短语之间的上下文关系,提高搜索结果的准确性和相关性。
我们将集成 Haystack 与 OpenAI 的 GPT 模型生成向量,并将这些向量存储到 Neo4j 图中,从而实现更准确且具上下文感知的搜索功能。
初始化 Haystack 和 OpenAI 以生成向量
在生成向量之前,你需要确保 Haystack 已正确安装并与 OpenAI API 集成,从他们基于 GPT 的模型获取向量。请按以下步骤设置 Haystack:
-
安装所需的库(如果尚未安装),执行以下命令:
pip install haystack haystack-ai openai neo4j-haystack
-
配置你的 OpenAI API 密钥,并确保在项目根目录下的
.env
文件中正确设置:
ini
OPENAI_API_KEY=your_openai_api_key_here
- 通过创建 Python 脚本初始化 Haystack 并连接 OpenAI 来生成向量,示例如下:
ini
# 使用 OpenAI 初始化 Haystack 以生成文本向量
def initialize_haystack():
# 初始化文档存储(这里使用内存存储,后续可配置其他存储)
document_store = InMemoryDocumentStore()
# 初始化 OpenAITextEmbedder 以生成文本向量
embedder = OpenAITextEmbedder(
api_key=Secret.from_env_var("OPENAI_API_KEY"),
model="text-embedding-ada-002"
)
return embedder
该配置使用内存中的文档存储初始化了 Haystack,并通过 OpenAI 向量模型配置了向量检索器。
为电影剧情生成向量
接下来,我们将为存储在 Neo4j 图中的电影剧情生成向量。目标是检索剧情描述,生成对应的向量,并将这些向量关联回对应的电影节点:
从 Neo4j 查询电影剧情:
首先,需要从 Neo4j 查询电影剧情。使用以下 Cypher 查询语句获取电影标题和剧情摘要:
ini
# 从 Neo4j 获取电影剧情和标题
def retrieve_movie_plots():
# 查询每个 Movie 节点的 "title"、"overview" 和 "tmdbId" 属性
query = """
MATCH (m:Movie)
WHERE m.embedding IS NULL
RETURN m.tmdbId AS tmdbId, m.title AS title, m.overview AS overview
"""
with driver.session() as session:
results = session.run(query)
# 将每部电影的标题、剧情摘要和 ID 存入列表
movies = [
{
"tmdbId": row["tmdbId"],
"title": row["title"],
"overview": row["overview"]
}
for row in results
]
return movies
该查询会返回图中每部电影的 tmdbId 和剧情摘要(overview)。
使用 OpenAI 和 Haystack 生成向量:
在获取剧情摘要后,使用 Haystack 中的 OpenAITextEmbedder 生成向量:
python
# 使用 ThreadPoolExecutor 并行生成向量
def generate_and_store_embeddings(embedder, movies, max_workers=10):
results_to_store = []
def process_movie(movie):
title = movie.get("title", "Unknown Title")
overview = str(movie.get("overview", "")).strip()
tmdbId = movie.get("tmdbId")
if not overview:
print(f"Skipping {title} --- No overview available.")
return None
try:
print(f"Generating embedding for: {title}")
embedding_result = embedder.run(overview)
embedding = embedding_result.get("embedding")
if embedding:
return (tmdbId, embedding)
else:
print(f"No embedding generated for: {title}")
except Exception as e:
print(f"Error processing {title}: {e}")
return None
将向量存入 Neo4j:
生成向量后,下一步是将其存回 Neo4j 图中。每个电影节点将更新一个存储向量的属性:
python
# 将向量存储回 Neo4j
def store_embedding_in_neo4j(tmdbId, embedding):
query = """
MATCH (m:Movie {tmdbId: $tmdbId})
SET m.embedding = $embedding
"""
with driver.session() as session:
session.run(query, tmdbId=tmdbId, embedding=embedding)
print(f"Stored embedding for TMDB ID: {tmdbId}")
这会将向量以名为 embedding
的属性保存到每个 Movie 节点中。
验证 Neo4j 中的向量存储情况:
向量存储后,你可以查询部分节点,确认向量属性是否存在:
ini
# 验证 Neo4j 中存储的向量
def verify_embeddings():
query = """
MATCH (m:Movie)
WHERE exists(m.embedding)
RETURN m.title, m.embedding
LIMIT 10
"""
with driver.session() as session:
results = session.run(query)
for record in results:
title = record["title"]
embedding = np.array(record["embedding"])[:5]
print(f" {title}: {embedding}...")
该查询会返回部分电影的标题和对应的向量(仅展示前5个维度),便于确认向量已成功存储。
注意
以上代码仅为核心片段,完整版本可参考 GitHub 仓库:github.com/PacktPublis...。
至此,我们已用向量丰富了图数据库,新增了相似度搜索能力,能够执行更具上下文意识和智能化的查询。这一步对于提升搜索体验、实现基于文本语义的高级检索操作(而非简单关键词匹配)至关重要。
接下来,Neo4j 图已经被向量增强,下一步是将 Haystack 与 Neo4j 连接,实现高级向量搜索。在后续章节中,我们将重点介绍如何利用这些向量,在 Neo4j 中执行高效且精准的向量搜索,帮助我们基于向量相似度检索电影或其他节点。
将 Haystack 连接至 Neo4j 实现高级向量搜索
电影向量现已存储于 Neo4j 中,我们需要在 embedding 属性上配置一个向量索引,以便根据向量相似度高效地搜索电影。通过在 Neo4j 创建向量索引,我们可以快速检索在高维向量空间中相近的节点,从而支持复杂查询,比如查找剧情相似的电影。
向量索引创建完成后,将其与 Haystack 集成,实现基于向量相似度(如余弦相似度)的检索。
在 Neo4j 中创建向量搜索索引
首先,你需要删除(如果存在) embedding 属性上已有的向量索引,然后创建一个新的索引以支持向量搜索。以下是在 Python 脚本中使用 Cypher 查询完成该操作的示例:
python
def create_or_reset_vector_index():
with driver.session() as session:
try:
# 如果已有索引,则删除
session.run("DROP INDEX overview_embeddings IF EXISTS ")
print("旧索引已删除")
except:
print("无可删除的索引")
# 创建 embedding 属性上的新向量索引
print("创建新向量索引中")
query_index = """
CREATE VECTOR INDEX overview_embeddings IF NOT EXISTS
FOR (m:Movie) ON (m.embedding)
OPTIONS {indexConfig: {
`vector.dimensions`: 1536,
`vector.similarity_function`: 'cosine'}}
"""
session.run(query_index)
print("向量索引创建成功")
使用 Haystack 和 Neo4j 向量索引执行相似度搜索
创建向量索引后,可以利用 Haystack 基于电影剧情向量执行相似度搜索。该方法能够将给定的电影剧情或任意文本查询转换为向量,并与 Neo4j 中已存向量进行比较,返回最相关的结果。
以下示例演示如何使用 Haystack 的 OpenAITextEmbedder 生成查询向量,并执行相似度搜索:
ini
text_embedder = OpenAITextEmbedder(
api_key=Secret.from_env_var("OPENAI_API_KEY"),
model="text-embedding-ada-002"
)
# 第一步:为查询文本生成向量
query_embedding = text_embedder.run(query).get("embedding")
if query_embedding is None:
print("查询向量生成失败。")
return
print("查询向量生成成功。")
使用 Haystack 和 Neo4j 执行向量搜索查询
在创建向量索引并将向量存入 Neo4j 后,你可以传入查询文本或电影剧情样本,系统将生成查询向量,和 Neo4j 中的向量比对,返回最相关的结果。
下面是一个不使用 Cypher,直接用 Haystack 进行向量搜索并展示最相似电影剧情的示例:
python
# 第二步:利用查询向量搜索最相似文档
similar_documents = document_store.query_by_embedding(
query_embedding, top_k=3
)
if not similar_documents:
print("未找到相似文档。")
return
print(f"找到 {len(similar_documents)} 个相似文档。\n\n")
# 第三步:展示结果
for doc in similar_documents:
title = doc.meta.get("title", "N/A")
overview = doc.meta.get("overview", "N/A")
score = doc.score
print(
f"标题: {title}\n剧情摘要: {overview}\n"
f"相似度得分: {score:.2f}\n{'-'*40}"
)
print("\n\n")
接下来,我们将结合 Neo4j 的 Cypher 查询与 Haystack,执行向量搜索,实现相似电影剧情的检索功能。
使用 Cypher 和 Haystack 运行向量搜索查询
为了执行向量搜索,我们将结合 Cypher 的图查询能力,并利用 OpenAITextEmbedder 生成的向量嵌入进行相似度搜索。
与直接用 Haystack 查询向量索引不同,这种方法结合了 Cypher 的灵活性,能够返回更复杂的数据(例如电影元信息,如演员和类型),同时保持向量相似度搜索的高效性。
具体步骤如下:
- 使用 OpenAITextEmbedder 嵌入查询:
将用户的文本查询(例如电影剧情)转换为高维向量嵌入。 - 使用 Neo4j 和 Cypher 搜索:
通过 Cypher 查询 Neo4j 的向量索引,比较查询向量与存储的电影剧情向量,检索相似电影。 - 返回丰富数据:
对于每个结果,获取额外的电影信息,如标题、剧情摘要、演员、类型以及相似度得分。
向量搜索实现示例:
定义 Cypher 查询:
首先定义一个 Cypher 查询,调用 Neo4j 向量索引(overview_embeddings),基于查询向量与电影向量的余弦相似度,返回 top_k 个最相似的电影:
ini
cypher_query = """
CALL db.index.vector.queryNodes("overview_embeddings", $top_k, $query_embedding)
YIELD node AS movie, score
MATCH (movie:Movie)
RETURN movie.title AS title, movie.overview AS overview, score
"""
生成查询向量:
使用 OpenAITextEmbedder 将用户输入的查询文本(如电影剧情)转换为向量。该向量随后会传递给 Neo4j 向量索引用于比较:
ini
text_embedder = OpenAITextEmbedder(
api_key=Secret.from_env_var("OPENAI_API_KEY"),
model="text-embedding-ada-002"
)
使用 Haystack 流水线运行向量搜索:
配置 Haystack 流水线来管理各组件:
query_embedder
负责从用户查询生成向量retriever
使用 Cypher 查询 Neo4j,基于查询向量返回最相似电影
ini
retriever = Neo4jDynamicDocumentRetriever(
client_config=client_config,
runtime_parameters=["query_embedding"],
compose_doc_from_result=True,
verify_connectivity=True,
)
pipeline = Pipeline()
pipeline.add_component("query_embedder", text_embedder)
pipeline.add_component("retriever", retriever)
pipeline.connect(
"query_embedder.embedding", "retriever.query_embedding"
)
result = pipeline.run(
{
"query_embedder": {"text": query},
"retriever": {
"query": cypher_query,
"parameters": {
"index": "overview_embeddings", "top_k": 3
},
},
}
)
展示结果:
搜索完成后,从结果中提取文档,并打印电影标题、剧情摘要和相似度得分:
python
# 从检索结果中提取文档
documents = result["retriever"]["documents"]
for doc in documents:
title = doc.meta.get("title", "N/A")
overview = doc.meta.get("overview", "N/A")
score = getattr(doc, "score", None)
score_display = f"{score:.2f}" if score is not None else "N/A"
print(
f"Title: {title}\nOverview: {overview}\n"
f"Score: {score_display}\n{'-'*40}\n"
)
使用 Cypher 和 Haystack 的优势:
- Cypher 灵活性:结合 Cypher 与 Haystack,不仅能查询向量嵌入,还能检索图数据库中额外的关系信息,如演员、类型及实体间关系。
- 结果丰富:除了找到最相似电影外,还能轻松扩展查询,获取相关元数据(如演员、评分),或者加入更多过滤条件(如上映年份、类型)细化搜索。
- 大图优化:Neo4j 的向量索引支持对大规模复杂关系数据集的高效查询,Haystack 的嵌入模型则提供精准的剧情语义理解。
接下来,我们将看一个具体的应用示例。
示例用例
假设你想查找剧情类似于"一个英雄必须拯救世界免于毁灭"的电影。通过我们刚才创建的流水线,你可以检索到相关结果:
标题:黑客帝国(The Matrix) 剧情简介:一名电脑黑客从神秘反抗者那里了解到自己现实的真相,以及他在对抗控制者战争中的角色。 相似度得分:0.98
标题:盗梦空间(Inception) 剧情简介:一名通过梦境共享技术窃取企业秘密的小偷,被赋予了将一个想法植入CEO大脑的逆向任务。 相似度得分:0.96
标题:黑暗骑士(The Dark Knight) 剧情简介:蝙蝠侠在警官吉姆·戈登和地区检察官哈维·登特的帮助下,加大了对犯罪的打击力度。 相似度得分:0.94
该流水线结合了两方面的优势------通过向量嵌入实现的相似度搜索,以及 Cypher 进行图数据查询的丰富功能,支持对电影等大规模数据集进行强大且灵活的搜索。
注意
以上代码仅为片段,完整版本请见 GitHub 仓库:github.com/PacktPublis...。
至此,我们已将 Haystack 与 Neo4j 连接,实现了高级向量搜索功能。有了向量索引,Neo4j 能高效地基于向量相似度搜索相似电影节点。Haystack 的集成使你能够通过 Neo4jDynamicDocumentRetriever 无缝执行此类搜索,该检索器借助向量嵌入和 Neo4j 的图能力在图中寻找相似项。
下一节,我们将探讨如何构建一个以搜索为驱动的聊天机器人,结合 Haystack 和 Neo4j 的强大功能,提供丰富且具上下文感知的回答。通过 Gradio,我们将创建一个直观的聊天界面,实现用户交互和自然语言查询的高级搜索。这将融合大语言模型、向量搜索和 Neo4j 的优势,打造用户友好、AI 驱动的搜索体验。
使用 Gradio 和 Haystack 构建以搜索驱动的聊天机器人
本节将介绍如何集成 Gradio,构建一个由 Haystack 和 Neo4j 驱动的交互式聊天机器人界面。Gradio 使得创建基于网页的聊天界面变得简单。该聊天机器人允许用户输入查询,随后触发对存储在 Neo4j 中电影向量的基于向量的搜索。聊天机器人会返回详细的回复,包括电影标题、剧情摘要和相似度得分,提供信息丰富且用户友好的体验。
搭建 Gradio 界面
如果你尚未安装 Gradio,可通过以下命令安装:
pip install gradio
注意:本章脚本适用于 Gradio v5.23.1。
接下来,我们搭建一个基本的 Gradio 界面,用于触发搜索流水线并显示结果:
ini
import gradio as gr
# 定义 Gradio 聊天机器人接口
def chatbot(user_input):
return perform_vector_search_cypher(user_input)
# 创建 Gradio 界面
chat_interface = gr.Interface(
fn=chatbot,
inputs=gr.Textbox(
placeholder="你想看什么类型的电影?",
lines=3,
label="你的电影偏好"
),
outputs=gr.Textbox(
label="推荐结果",
lines=12
),
title="AI 电影推荐系统",
description="问我关于电影的问题!我可以根据你的喜好推荐电影。",
examples=[
["我想看带有时间旅行的科幻电影"],
["推荐一部有美好结局的浪漫喜剧"],
["我想看带超级英雄但不要太严肃的电影"],
["我想看紧张刺激的惊悚片"],
["给我推荐一些关于人工智能统治世界的电影"]
],
flagging_mode="never"
)
该界面允许用户输入文本查询,聊天机器人将调用 perform_vector_search_cypher()
函数搜索最相关的电影。
与 Haystack 和 Neo4j 集成
为了让聊天机器人具备强大功能,我们将它连接到 Haystack 的向量生成模块和 Neo4j 的向量搜索功能。我们使用 OpenAITextEmbedder 来生成用户查询及 Neo4j 中电影剧情的向量。电影向量存储在 Neo4j 的向量索引中,我们通过该索引查询最相似的电影。
以下是如何将聊天机器人与之前的 Haystack 设置集成的示例:
ini
# 使用 Cypher 支持的搜索和 Haystack 的对话聊天机器人处理器
def perform_vector_search(query):
print("接收到消息:", query)
cypher_query = """
CALL db.index.vector.queryNodes("overview_embeddings", $top_k, $query_embedding)
YIELD node AS movie, score
MATCH (movie:Movie)
RETURN movie.title AS title, movie.overview AS overview, score
"""
# 向量生成器
embedder = OpenAITextEmbedder(
api_key=Secret.from_env_var("OPENAI_API_KEY"),
model="text-embedding-ada-002"
)
# 检索器
retriever = Neo4jDynamicDocumentRetriever(
client_config=client_config,
runtime_parameters=["query_embedding"],
compose_doc_from_result=True,
verify_connectivity=True,
)
# 流水线配置
pipeline = Pipeline()
pipeline.add_component("query_embedder", embedder)
pipeline.add_component("retriever", retriever)
pipeline.connect(
"query_embedder.embedding", "retriever.query_embedding"
)
将 Gradio 连接到完整流水线
现在,将这个 Gradio 聊天机器人与之前搭建的 Haystack 和 Neo4j 流水线连接起来。Gradio 界面将调用 perform_vector_search_cypher()
函数,该函数利用 Neo4jDynamicDocumentRetriever
根据用户查询搜索相似电影。
更新 main()
函数以初始化聊天机器人:
csharp
# 主函数,协调整个流程
def main():
# 第一步:在 Neo4j AuraDB 中创建或重置向量索引
create_or_reset_vector_index()
# 第二步:启动 Gradio 聊天机器人界面
chat_interface.launch()
if __name__ == "__main__":
main()
运行聊天机器人
运行聊天机器人只需执行你的 Python 脚本,Gradio 界面将在浏览器中启动,允许你实时与聊天机器人交互:
python search_chatbot.py
Gradio 界面会在浏览器中打开,你可以输入如下查询:
"告诉我一个拯救世界的英雄的故事。"
聊天机器人会基于向量搜索返回与该查询相似的电影剧情。
注意
以上代码仅为核心片段,完整版本请见 GitHub 仓库:github.com/PacktPublis...。
至此,本节我们已经构建了一个功能完善的以搜索为驱动的聊天机器人,结合了 Gradio、Haystack 和 Neo4j。该机器人利用存储在 Neo4j 中的向量,实现高级向量搜索,基于上下文为用户返回相关结果,如从 Neo4j 中检索有意义的电影标题和演员信息,响应用户查询。
不过,这仅仅是开始。下一节,我们将深入探讨如何微调 Haystack 集成,并探索优化搜索性能、调整检索模型以及优化聊天机器人回复等高级技术,以打造更流畅、高效的搜索驱动体验。
微调你的 Haystack 集成
现在是时候探索如何微调该集成,以提升性能和用户体验。虽然当前的配置已经能提供丰富且具上下文感知的回答,但你可以通过多种高级技术来优化搜索流程,提高检索准确性,使聊天机器人的交互更加流畅。
本节将重点调整 Haystack 的关键组件,包括尝试不同的向量模型、优化 Neo4j 查询以加快响应速度,以及改进聊天机器人回复的展示方式。这些增强措施将帮助你扩展聊天机器人的能力,以应对更复杂的查询,提升响应速度,并提供更加相关的搜索结果。
尝试不同的向量模型
目前我们使用的是 OpenAI 的 text-embedding-ada-002
模型来生成向量。自发布以来,该模型在广泛任务中表现稳定且高效,但值得注意的是,OpenAI 最近推出了新模型,如 text-embedding-3-small
和 text-embedding-3-large
,在性能和成本效益上都有显著提升。例如,text-embedding-3-small
在多语言和英语任务中表现更佳,同时成本仅为 text-embedding-ada-002
的五分之一。尽管本项目为了保持一致性未更换模型,但在实现类似流水线时,读者可以考虑使用 text-embedding-3-small
,以在不牺牲性能的前提下提升效率------特别是当向量生成频繁或规模较大时。
此外,Haystack 支持多种其他模型,你可以尝试不同模型,寻找对你的具体用例最准确或最相关的结果。例如,可以切换为维度更高、功能更强的 OpenAI 模型,或尝试 Haystack 支持的其他向量服务。
以下示例演示如何轻松切换到另一种模型:
ini
embedder = OpenAITextEmbedder(
api_key=Secret.from_env_var("OPENAI_API_KEY"),
model="text-embedding-babbage-001" # 试验不同的模型
)
你还可以探索 OpenAI 其他模型,甚至集成不同的向量生成服务,比较它们在你的电影聊天机器人中的表现,以选择最佳方案。
优化 Neo4j 以加快查询速度
虽然 Neo4j 已经能高效处理基于图的查询,但针对大规模数据集,你仍然可以应用多种优化手段。通过为更多常用属性建立索引,可以提升查询性能。
为额外属性建立索引
除了 embedding 属性上的向量索引外,你还可以为其他常被查询的属性建立索引,比如 title
或 tmdbId
,以加快检索速度。这样在基于这些属性过滤或查询电影时,搜索会更加迅速高效:
scss
def create_additional_indexes():
with driver.session() as session:
session.run("CREATE INDEX IF NOT EXISTS movie_title_index FOR (m:Movie) ON (m.title)")
session.run("CREATE INDEX IF NOT EXISTS movie_tmdbId_index FOR (m:Movie) ON (m.tmdbId)")
print("额外索引创建成功")
为这些属性建立索引,可以优化在非向量搜索场景下的查找,比如按标题过滤或精确获取某部电影。
持续改进聊天机器人的搜索体验,你还可以记录用户查询并进行分析,下面详细说明。
查询日志记录与分析
日志记录帮助你追踪最常见的搜索模式。通过对用户查询日志及其分析,你可以调整索引策略、优化检索器,或微调向量模型以提高准确率。
以下是实现简单日志记录机制的示例:
python
import logging
logging.basicConfig(filename='chatbot_queries.log', level=logging.INFO)
def log_query(query):
logging.info(f"用户查询: {query}")
每当用户输入查询时,都会被记录下来,便于后续分析。你可以基于这些日志做出有针对性的系统调整,确保系统随着时间推移变得更灵敏、更准确。
这些技术能显著提升你的搜索驱动型聊天机器人的性能、准确性和用户体验。无论是尝试不同的向量模型、优化 Neo4j 查询,还是改善结果格式化,每一次调整都让你的交互更顺畅、更强大。
通过这些高级技术,你的聊天机器人能够更好地扩展,应对更复杂的查询,并返回更加相关且吸引人的结果。
总结
在本章中,我们成功构建了一个功能完善的以搜索驱动的聊天机器人,集成了 Gradio、Haystack 和 Neo4j。首先,我们利用 OpenAI 模型生成的电影向量丰富了 Neo4j 图,实现了高级的基于向量的搜索功能。随后,我们将 Haystack 连接到 Neo4j,实现对图中存储的向量进行相似度搜索。最后,我们使用 Gradio 创建了一个用户友好的聊天界面,能够根据用户查询动态检索电影详情,如标题和演员信息。
下一章,我们将聚焦于 Haystack 的高级搜索能力和搜索优化,同时讨论针对大规模图的查询优化技术。