Elasticsearch
Elasticsearch 是一个分布式的、RESTful 的搜索和分析引擎,能够同时执行向量搜索和词汇搜索。它构建在 Apache Lucene 库之上。
本笔记展示了如何使用与 Elasticsearch 向量存储相关的功能。
设置
要使用 Elasticsearch 向量搜索,您必须安装 langchain-elasticsearch 包。
%pip install -qU langchain-elasticsearch
凭据
有两种主要方法可以设置 Elasticsearch 实例以供配合使用:
-
Elastic Cloud:Elastic Cloud 是一项托管的 Elasticsearch 服务。注册即可获得免费试用。
若要连接到不需要登录凭证的 Elasticsearch 实例(启动已启用安全性的 docker 实例),请将 Elasticsearch URL 和索引名称与嵌入对象一起传递给构造函数。
-
本地安装 Elasticsearch:通过在本地运行 Elasticsearch 来开始使用。最简单的方法是使用官方 Elasticsearch Docker 镜像。有关更多信息,请参阅Elasticsearch Docker 文档。
通过 Docker 运行 Elasticsearch
示例:运行一个禁用了安全性的单节点 Elasticsearch 实例。不建议在生产环境中使用。
%docker run -p 9200:9200 -e "discovery.type=single-node" -e "xpack.security.enabled=false" -e "xpack.security.http.ssl.enabled=false" docker.elastic.co/elasticsearch/elasticsearch:8.12.1
启用认证运行
为了生产环境的运行安全,我们建议启用安全设置。您可以使用 es_api_key 或 es_user 和 es_password 参数来连接并提供登录凭证。
pip install -qU langchain-openai
import getpass
import os
if not os.environ.get("OPENAI_API_KEY"):
os.environ["OPENAI_API_KEY"] = getpass.getpass("Enter API key for OpenAI: ")
from langchain_openai import OpenAIEmbeddings
embeddings = OpenAIEmbeddings(model="text-embedding-3-large")
from langchain_elasticsearch import ElasticsearchStore
elastic_vector_search = ElasticsearchStore(
es_url="http://localhost:9200",
index_name="langchain_index",
embedding=embeddings,
es_user="elastic",
es_password="changeme",
)
如何获取默认“elastic”用户的密码?
要获取默认“elastic”用户的 Elastic Cloud 密码:
- 登录 Elastic Cloud 控制台 https://cloud.elastic.co
- 转到“Security”>“Users”
- 找到“elastic”用户并点击“Edit”
- 点击“Reset password”
- 按照提示重置密码
如何获取 API 密钥?
要获取 API 密钥:
- 登录 Elastic Cloud 控制台 https://cloud.elastic.co
- 打开 Kibana 并转到 Stack Management > API Keys
- 点击“Create API key”
- 输入 API 密钥的名称并点击“Create”
- 复制 API 密钥并将其粘贴到
api_key参数中
Elastic Cloud
要连接到 Elastic Cloud 上的 Elasticsearch 实例,您可以使用 es_cloud_id 参数或 es_url。
elastic_vector_search = ElasticsearchStore(
es_cloud_id="<cloud_id>",
index_name="test_index",
embedding=embeddings,
es_user="elastic",
es_password="changeme",
)
如果你想获得一流的模型调用自动化追踪,你也可以通过取消下面一行的注释来设置你的 LangSmith API 密钥:
# os.environ["LANGSMITH_API_KEY"] = getpass.getpass("Enter your LangSmith API key: ")
# os.environ["LANGSMITH_TRACING"] = "true"
初始化
Elasticsearch 在本地 localhost:9200 上运行,使用了 Docker。有关如何从 Elastic Cloud 连接到 Elasticsearch 的更多详细信息,请参阅上面的 带身份验证的运行。
from langchain_elasticsearch import ElasticsearchStore
vector_store = ElasticsearchStore(
"langchain-demo", embedding=embeddings, es_url="http://localhost:9201"
)
管理向量存储
向向量存储添加条目
from uuid import uuid4
from langchain_core.documents import Document
document_1 = Document(
page_content="I had chocolate chip pancakes and scrambled eggs for breakfast this morning.",
metadata={"source": "tweet"},
)
document_2 = Document(
page_content="The weather forecast for tomorrow is cloudy and overcast, with a high of 62 degrees.",
metadata={"source": "news"},
)
document_3 = Document(
page_content="Building an exciting new project with LangChain - come check it out!",
metadata={"source": "tweet"},
)
document_4 = Document(
page_content="Robbers broke into the city bank and stole $1 million in cash.",
metadata={"source": "news"},
)
document_5 = Document(
page_content="Wow! That was an amazing movie. I can't wait to see it again.",
metadata={"source": "tweet"},
)
document_6 = Document(
page_content="Is the new iPhone worth the price? Read this review to find out.",
metadata={"source": "website"},
)
document_7 = Document(
page_content="The top 10 soccer players in the world right now.",
metadata={"source": "website"},
)
document_8 = Document(
page_content="LangGraph is the best framework for building stateful, agentic applications!",
metadata={"source": "tweet"},
)
document_9 = Document(
page_content="The stock market is down 500 points today due to fears of a recession.",
metadata={"source": "news"},
)
document_10 = Document(
page_content="I have a bad feeling I am going to get deleted :(",
metadata={"source": "tweet"},
)
documents = [
document_1,
document_2,
document_3,
document_4,
document_5,
document_6,
document_7,
document_8,
document_9,
document_10,
]
uuids = [str(uuid4()) for _ in range(len(documents))]
vector_store.add_documents(documents=documents, ids=uuids)
['21cca03c-9089-42d2-b41c-3d156be2b519',
'a6ceb967-b552-4802-bb06-c0e95fce386e',
'3a35fac4-e5f0-493b-bee0-9143b41aedae',
'176da099-66b1-4d6a-811b-dfdfe0808d30',
'ecfa1a30-3c97-408b-80c0-5c43d68bf5ff',
'c0f08baa-e70b-4f83-b387-c6e0a0f36f73',
'489b2c9c-1925-43e1-bcf0-0fa94cf1cbc4',
'408c6503-9ba4-49fd-b1cc-95584cd914c5',
'5248c899-16d5-4377-a9e9-736ca443ad4f',
'ca182769-c4fc-4e25-8f0a-8dd0a525955c']
从向量库中删除条目
vector_store.delete(ids=[uuids[-1]])
True
查询向量存储
创建向量存储并将相关文档添加进去后,您很可能希望在链或代理运行时查询它。这些示例还展示了如何在搜索时使用过滤。
直接查询
相似性搜索
可以按以下方式执行带有元数据过滤的简单相似性搜索:
results = vector_store.similarity_search(
query="LangChain provides abstractions to make working with LLMs easy",
k=2,
filter=[{"term": {"metadata.source.keyword": "tweet"}}],
)
for res in results:
print(f"* {res.page_content} [{res.metadata}]")
* Building an exciting new project with LangChain - come check it out! [{'source': 'tweet'}]
* LangGraph is the best framework for building stateful, agentic applications! [{'source': 'tweet'}]
相似性搜索与评分
如果你想执行相似性搜索并获得相应的评分,可以运行:
results = vector_store.similarity_search_with_score(
query="Will it be hot tomorrow",
k=1,
filter=[{"term": {"metadata.source.keyword": "news"}}],
)
for doc, score in results:
print(f"* [SIM={score:3f}] {doc.page_content} [{doc.metadata}]")
* [SIM=0.765887] The weather forecast for tomorrow is cloudy and overcast, with a high of 62 degrees. [{'source': 'news'}]