Elasticsearch:带有自查询检索器的聊天机器人示例

本工作簿演示了 Elasticsearch 的自查询检索器 (self-query retriever) 将问题转换为结构化查询并将结构化查询应用于 Elasticsearch 索引的示例。

在开始之前,我们首先使用 langchain 将文档分割成块,然后使用 ElasticsearchStore.from_documents 创建一个向量存储并将数据索引到 elasticsearch。

然后,我们将看到一些示例查询,展示了由 elasticsearch 驱动的自查询检索器的全部功能。

安装

如果你还没有安装好自己的 Elasticsearch 及 Kibana,请参考文章:

安装 Elasticsearch 及 Kibana

如果你还没有安装好自己的 Elasticsearch 及 Kibana,那么请参考一下的文章来进行安装:

在安装的时候,请选择 Elastic Stack 8.x 进行安装。在安装的时候,我们可以看到如下的安装信息:

Python 安装包

我们需要安装 Python 版本 3.6 及以上版本。我们还需要安装如下的 Python 安装包:

复制代码
python3 -m pip install -qU lark elasticsearch langchain openai
markdown 复制代码
1.  $ pwd
2.  /Users/liuxg/python/elser
3.  $ python3 -m pip install -qU lark elasticsearch langchain openai
4.  $ pip3 list | grep elasticsearch
5.  elasticsearch             8.11.1
6.  rag-elasticsearch         0.0.1        /Users/liuxg/python/rag-elasticsearch/my-app/packages/rag-elasticsearch

在本练习中,我们将使用最新的 Elastic Stack 8.11 来进行展示。

环境变量

在启动 Jupyter 之前,我们设置如下的环境变量:

ini 复制代码
1.  export ES_USER="elastic"
2.  export ES_PASSWORD="yarOjyX5CLqTsKVE3v*d"
3.  export ES_ENDPOINT="localhost"
4.  export OPENAI_API_KEY="YOUR_OPEN_AI_KEY"

请在上面修改相应的变量的值。特别是你需要输入自己的 OPENAI_API_KEY。

拷贝 Elasticsearch 证书

我们把 Elasticsearch 的证书拷贝到当前的目录下:

bash 复制代码
1.  $ pwd
2.  /Users/liuxg/python/elser
3.  $ cp ~/elastic/elasticsearch-8.11.0/config/certs/http_ca.crt .
4.  overwrite ./http_ca.crt? (y/n [n]) y
5.  $ ls http_ca.crt 
6.  http_ca.crt

创建应用

导入 python 包

我们在当前的目录下创建 jupyter notebook:Chatbot Example with Self Query Retriever.ipynb

javascript 复制代码
1.  from langchain.schema import Document
2.  from langchain.embeddings.openai import OpenAIEmbeddings
3.  from langchain.vectorstores import ElasticsearchStore
4.  from langchain.llms import OpenAI
5.  from langchain.retrievers.self_query.base import SelfQueryRetriever
6.  from langchain.chains.query_constructor.base import AttributeInfo

创建文档

接下来,我们将使用 langchain 模式文档创建包含电影摘要的文档列表,其中包含每个文档的 page_content 和元数据。

ini 复制代码
1.  docs = [
2.      Document(
3.          page_content="A bunch of scientists bring back dinosaurs and mayhem breaks loose",
4.          metadata={"year": 1993, "rating": 7.7, "genre": "science fiction", "director": "Steven Spielberg", "title": "Jurassic Park"},
5.      ),
6.      Document(
7.          page_content="Leo DiCaprio gets lost in a dream within a dream within a dream within a ...",
8.          metadata={"year": 2010, "director": "Christopher Nolan", "rating": 8.2, "title": "Inception"},
9.      ),
10.      Document(
11.          page_content="A psychologist / detective gets lost in a series of dreams within dreams within dreams and Inception reused the idea",
12.          metadata={"year": 2006, "director": "Satoshi Kon", "rating": 8.6, "title": "Paprika"},
13.      ),
14.      Document(
15.          page_content="A bunch of normal-sized women are supremely wholesome and some men pine after them",
16.          metadata={"year": 2019, "director": "Greta Gerwig", "rating": 8.3, "title": "Little Women"},
17.      ),
18.      Document(
19.          page_content="Toys come alive and have a blast doing so",
20.          metadata={"year": 1995, "genre": "animated", "director": "John Lasseter", "rating": 8.3, "title": "Toy Story"},
21.      ),
22.      Document(
23.          page_content="Three men walk into the Zone, three men walk out of the Zone",
24.          metadata={
25.              "year": 1979,
26.              "rating": 9.9,
27.              "director": "Andrei Tarkovsky",
28.              "genre": "science fiction",
29.              "rating": 9.9,
30.              "title": "Stalker",
31.          },
32.      ),
33.  ]

连接到 Elasticsearch

我们将使用我们本地构建的 Elasticsearch 集群进行连接。我们可以参考之前的文章 "Elasticsearch:使用 Open AI 和 Langchain 的 RAG - Retrieval Augmented Generation (三)"。

javascript 复制代码
1.  from dotenv import load_dotenv
2.  from langchain.embeddings import OpenAIEmbeddings
3.  from langchain.vectorstores import ElasticKnnSearch
4.  from langchain.text_splitter import CharacterTextSplitter
5.  from urllib.request import urlopen
6.  import os, json

8.  load_dotenv()

10.  openai_api_key=os.getenv('OPENAI_API_KEY')
11.  elastic_user=os.getenv('ES_USER')
12.  elastic_password=os.getenv('ES_PASSWORD')
13.  elastic_endpoint=os.getenv("ES_ENDPOINT")
14.  elastic_index_name='elastic-knn-search'
ini 复制代码
1.  from elasticsearch import Elasticsearch

3.  url = f"https://{elastic_user}:{elastic_password}@{elastic_endpoint}:9200"
4.  connection = Elasticsearch(url, ca_certs = "./http_ca.crt", verify_certs = True)

6.  print(connection.info())

8.  embeddings = OpenAIEmbeddings(openai_api_key=openai_api_key)
9.  dims=1536

12.  es = ElasticsearchStore.from_documents( 
13.                              docs,
14.                              embedding = embeddings, 
15.                              es_url = url, 
16.                              es_connection = connection,
17.                              index_name = elastic_index_name, 
18.                              es_user = elastic_user,
19.                              es_password = elastic_password)

设置查询检索器

接下来,我们将通过提供有关文档属性的一些信息和有关文档的简短描述来实例化自查询检索器。

然后我们将使用 SelfQueryRetriever.from_llm 实例化检索器 (retriever)

markdown 复制代码
1.  metadata_field_info = [
2.      AttributeInfo(
3.          ,
4.          description="The genre of the movie. Can be either 'science fiction' or 'animated'.",
5.          type="string or list[string]",
6.      ),
7.      AttributeInfo(
8.          ,
9.          description="The year the movie was released",
10.          type="integer",
11.      ),
12.      AttributeInfo(
13.          ,
14.          description="The name of the movie director",
15.          type="string",
16.      ),
17.      AttributeInfo(

19.      ),
20.  ]

22.  document_content_description = "Brief summary of a movie"

24.  # Set up openAI llm with sampling temperature 0
25.  llm = OpenAI(temperature=0, openai_api_key=openai_api_key)

27.  # instantiate retriever
28.  retriever = SelfQueryRetriever.from_llm(
29.      llm, es, document_content_description, metadata_field_info, verbose=True
30.  )

使用自查询检索器回答问题

现在我们将演示如何使用 RAG 的自查询检索器。

ini 复制代码
1.  from langchain.chat_models import ChatOpenAI
2.  from langchain.schema.runnable import RunnableParallel, RunnablePassthrough
3.  from langchain.prompts import ChatPromptTemplate, PromptTemplate
4.  from langchain.schema import format_document

6.  LLM_CONTEXT_PROMPT = ChatPromptTemplate.from_template("""
7.  Use the following context movies that matched the user question. Use the movies below only to answer the user's question.

9.  If you don't know the answer, just say that you don't know, don't try to make up an answer.

11.  ----
12.  {context}
13.  ----
14.  Question: {question}
15.  Answer:
16.  """)

18.  DOCUMENT_PROMPT = PromptTemplate.from_template("""
19.  ---
20.  title: {title}                                                                                   
21.  year: {year}  
22.  director: {director}    
23.  ---
24.  """)

26.  def _combine_documents(
27.      docs, document_prompt=DOCUMENT_PROMPT, document_separator="\n\n"
28.  ):
29.      doc_strings = [format_document(doc, document_prompt) for doc in docs]
30.      return document_separator.join(doc_strings)

33.  _context = RunnableParallel(
34.      context=retriever | _combine_documents,
35.      question=RunnablePassthrough(),
36.  )

38.  chain = (_context | LLM_CONTEXT_PROMPT | llm)

40.  chain.invoke("What movies are about dreams and it was released after the year 2009 but before the year 2011?")

上面的代码可以在地址:github.com/liu-xiao-gu...下载。

相关推荐
ofoxcoding20 小时前
借助 CLAUDE.md 约束 Sonnet 5.5 多文件重构行为的提示词实践
大数据·elasticsearch·ai·重构
Elasticsearch20 小时前
隆重推出 AlertZero:让你的告警队列实现 “收件箱清零” 式管理
elasticsearch
ly768921 小时前
从 TF-IDF 到 BM25:Elasticsearch 相关性评分的字段长度归一化与 boost 调参边界
java·elasticsearch·query dsl·bm25·相关性评分
SL-staff21 小时前
技术实践:将Excel自动升级为可搜索的知识节点(JVS平台实现)
mongodb·elasticsearch·知识图谱·jvs平台·语义解析·企业文档管理·excel结构化
Elasticsearch21 小时前
2026 年唯一获得端点预防与响应(EPR)满分的厂商是 Elastic
elasticsearch
vx_Biye_Design21 小时前
springboot旅游管理系统18006-计算机课程设计、毕业设计
java·spring boot·后端·python·elasticsearch·django·课程设计
ly76891 天前
倒排索引与 FST 在 Lucene 中的内存布局:segment、docValues 与词典压缩的工程取舍
elasticsearch·lucene·倒排索引·doc values·fst
Elasticsearch1 天前
利用预计算上下文,更快速、更低成本地开展支持问题调查
elasticsearch
小小小米粒1 天前
重置本地git
大数据·git·elasticsearch
ly76891 天前
Spring Boot 集成 Elasticsearch 的生产实践:客户端选型、索引生命周期与批量写入容错
spring boot·elasticsearch·索引生命周期·java api client·批量写入