Redis 向量存储
此笔记本介绍了如何开始使用 Redis 向量存储。
Redis 是一种流行的开源内存数据结构存储,可用作数据库、缓存、消息代理和队列。它现在包含向量相似性搜索功能,使其适用于用作向量存储。
什么是 Redis?
大多数开发人员都熟悉Redis
。从本质上讲,Redis
是键值家族中的一个 NoSQL 数据库,可用作缓存、消息代理、流处理和主数据库。开发人员选择Redis
是因为它速度快,拥有庞大的客户端库生态系统,并且已被大型企业部署多年。
除了这些传统用例之外,Redis
还提供了其他功能,例如搜索和查询功能,允许用户在Redis
中创建辅助索引结构。这使得Redis
能够以缓存的速度成为向量数据库。
Redis 作为向量数据库
Redis
使用压缩的倒排索引来实现快速索引和较低的内存占用。它还支持许多高级功能,例如
- Redis 哈希和
JSON
中多个字段的索引 - 向量相似性搜索(使用
HNSW
(ANN)或FLAT
(KNN)) - 向量范围搜索(例如,查找查询向量半径内的所有向量)
- 增量索引,且不会降低性能
- 文档排名(使用tf-idf,并可以选择用户提供的权重)
- 字段加权
- 使用
AND
、OR
和NOT
运算符的复杂布尔查询 - 前缀匹配、模糊匹配和精确短语查询
- 支持双元音模糊匹配
- 自动完成建议(带模糊前缀建议)
- 在多种语言中基于词干的查询扩展(使用Snowball)
- 支持中文分词和查询(使用Friso)
- 数字过滤器和范围
- 使用 Redis 地理空间索引进行地理空间搜索
- 强大的聚合引擎
- 支持所有
utf-8
编码文本 - 检索完整文档、选定字段或仅文档 ID
- 对结果进行排序(例如,按创建日期排序)
客户端
由于Redis
不仅仅是一个向量数据库,因此通常会有用例需要使用Redis
客户端,而不仅仅是LangChain
集成。您可以使用任何标准的Redis
客户端库来运行搜索和查询命令,但最简单的方法是使用包装搜索和查询 API 的库。以下是一些示例,您可以在此处找到更多客户端库。
项目 | 语言 | 许可证 | 作者 | 星标 |
---|---|---|---|---|
jedis | Java | MIT | Redis | |
redisvl | Python | MIT | Redis | |
redis-py | Python | MIT | Redis | |
node-redis | Node.js | MIT | Redis | |
nredisstack | .NET | MIT | Redis |
部署选项
有很多方法可以部署带有 RediSearch 的 Redis。最简单的入门方法是使用 Docker,但还有许多潜在的部署选项,例如
- Redis 云
- Docker(Redis Stack)
- 云市场:AWS 市场、Google 市场 或 Azure 市场
- 本地部署:Redis 企业软件
- Kubernetes:Kubernetes 上的 Redis 企业软件
Redis 连接 URL 模式
有效的 Redis URL 模式为
redis://
- 连接到 Redis 独立服务器,未加密rediss://
- 连接到 Redis 独立服务器,使用 TLS 加密redis+sentinel://
- 通过 Redis Sentinel 连接到 Redis 服务器,未加密rediss+sentinel://
- 通过 Redis Sentinel 连接到 Redis 服务器,两个连接都使用 TLS 加密
有关其他连接参数的更多信息,请参阅redis-py 文档。
设置
要使用 RedisVectorStore,您需要安装langchain-redis
合作伙伴包,以及本笔记本中使用的其他包。
%pip install -qU langchain-redis langchain-huggingface sentence-transformers scikit-learn
Note: you may need to restart the kernel to use updated packages.
凭据
Redis 连接凭据作为 Redis 连接 URL 的一部分传递。Redis 连接 URL 非常通用,可以适应各种 Redis 服务器拓扑和身份验证方法。这些 URL 遵循特定的格式,其中包含连接协议、身份验证详细信息、主机、端口和数据库信息。Redis 连接 URL 的基本结构为
[protocol]://[auth]@[host]:[port]/[database]
其中
- protocol 可以是 redis 用于标准连接,rediss 用于 SSL/TLS 连接,或 redis+sentinel 用于 Sentinel 连接。
- auth 包括用户名和密码(如果适用)。
- host 是 Redis 服务器主机名或 IP 地址。
- port 是 Redis 服务器端口。
- database 是 Redis 数据库编号。
Redis 连接 URL 支持各种配置,包括
- 独立 Redis 服务器(带或不带身份验证)
- Redis Sentinel 设置
- SSL/TLS 加密连接
- 不同的身份验证方法(仅密码或用户名密码)
以下是不同配置的 Redis 连接 URL 示例
# connection to redis standalone at localhost, db 0, no password
redis_url = "redis://localhost:6379"
# connection to host "redis" port 7379 with db 2 and password "secret" (old style authentication scheme without username / pre 6.x)
redis_url = "redis://:secret@redis:7379/2"
# connection to host redis on default port with user "joe", pass "secret" using redis version 6+ ACLs
redis_url = "redis://joe:secret@redis/0"
# connection to sentinel at localhost with default group mymaster and db 0, no password
redis_url = "redis+sentinel://localhost:26379"
# connection to sentinel at host redis with default port 26379 and user "joe" with password "secret" with default group mymaster and db 0
redis_url = "redis+sentinel://joe:secret@redis"
# connection to sentinel, no auth with sentinel monitoring group "zone-1" and database 2
redis_url = "redis+sentinel://redis:26379/zone-1/2"
# connection to redis standalone at localhost, db 0, no password but with TLS support
redis_url = "rediss://localhost:6379"
# connection to redis sentinel at localhost and default port, db 0, no password
# but with TLS support for booth Sentinel and Redis server
redis_url = "rediss+sentinel://localhost"
使用 Docker 启动 Redis 实例
要将 Redis 与 LangChain 一起使用,您需要一个正在运行的 Redis 实例。您可以使用以下命令使用 Docker 启动一个实例:
docker run -d -p 6379:6379 redis/redis-stack:latest
在此示例中,我们将使用本地 Redis 实例。如果您使用的是远程实例,则需要相应地修改 Redis URL。
import os
REDIS_URL = os.getenv("REDIS_URL", "redis://localhost:6379")
print(f"Connecting to Redis at: {REDIS_URL}")
Connecting to Redis at: redis://redis:6379
如果您想获取模型调用的自动跟踪,您还可以通过取消注释以下内容来设置您的LangSmith API 密钥
# os.environ["LANGSMITH_API_KEY"] = getpass.getpass("Enter your LangSmith API key: ")
# os.environ["LANGSMITH_TRACING"] = "true"
让我们通过 ping 它来检查 Redis 是否已启动并正在运行
import redis
redis_client = redis.from_url(REDIS_URL)
redis_client.ping()
True
示例数据
20 个新闻组数据集包含大约 18000 个关于 20 个主题的新闻组帖子。我们将使用其中的一部分进行演示,并重点关注两个类别:“alt.atheism”和“sci.space”
from langchain.docstore.document import Document
from sklearn.datasets import fetch_20newsgroups
categories = ["alt.atheism", "sci.space"]
newsgroups = fetch_20newsgroups(
subset="train", categories=categories, shuffle=True, random_state=42
)
# Use only the first 250 documents
texts = newsgroups.data[:250]
metadata = [
{"category": newsgroups.target_names[target]} for target in newsgroups.target[:250]
]
len(texts)
250
初始化
RedisVectorStore 实例可以通过多种方式初始化
RedisVectorStore.__init__
- 直接初始化RedisVectorStore.from_texts
- 从文本列表初始化(可以选择元数据)RedisVectorStore.from_documents
- 从langchain_core.documents.Document
对象列表初始化RedisVectorStore.from_existing_index
- 从现有 Redis 索引初始化
下面我们将使用使用RedisConfig
实例的RedisVectorStore.__init__
方法。
- OpenAI
- HuggingFace
- 伪嵌入
pip install -qU langchain-openai
import getpass
os.environ["OPENAI_API_KEY"] = getpass.getpass()
from langchain_openai import OpenAIEmbeddings
embeddings = OpenAIEmbeddings(model="text-embedding-3-large")
pip install -qU langchain-huggingface
from langchain_huggingface import HuggingFaceEmbeddings
embeddings = HuggingFaceEmbeddings(model="sentence-transformers/all-mpnet-base-v2")
pip install -qU langchain-core
from langchain_core.embeddings import FakeEmbeddings
embeddings = FakeEmbeddings(size=4096)
我们将使用 SentenceTransformer 模型来创建嵌入。此模型在本地运行,不需要 API 密钥。
from langchain_redis import RedisConfig, RedisVectorStore
config = RedisConfig(
index_name="newsgroups",
redis_url=REDIS_URL,
metadata_schema=[
{"name": "category", "type": "tag"},
],
)
vector_store = RedisVectorStore(embeddings, config=config)
管理向量存储
将项目添加到向量数据库
ids = vector_store.add_texts(texts, metadata)
print(ids[0:10])
['newsgroups:f1e788ee61fe410daa8ef941dd166223', 'newsgroups:80b39032181f4299a359a9aaed6e2401', 'newsgroups:99a3efc1883647afba53d115b49e6e92', 'newsgroups:503a6c07cd71418eb71e11b42589efd7', 'newsgroups:7351210e32d1427bbb3c7426cf93a44f', 'newsgroups:4e79fdf67abe471b8ee98ba0e8a1a055', 'newsgroups:03559a1d574e4f9ca0479d7b3891402e', 'newsgroups:9a1c2a7879b8409a805db72feac03580', 'newsgroups:3578a1e129f5435f9743cf803413f37a', 'newsgroups:9f68baf4d6b04f1683d6b871ce8ad92d']
让我们检查第一个文档
texts[0], metadata[0]
('From: [email protected] (Bill Conner)\nSubject: Re: Not the Omni!\nNntp-Posting-Host: okcforum.osrhe.edu\nOrganization: Okcforum Unix Users Group\nX-Newsreader: TIN [version 1.1 PL6]\nLines: 18\n\nCharley Wingate ([email protected]) wrote:\n: \n: >> Please enlighten me. How is omnipotence contradictory?\n: \n: >By definition, all that can occur in the universe is governed by the rules\n: >of nature. Thus god cannot break them. Anything that god does must be allowed\n: >in the rules somewhere. Therefore, omnipotence CANNOT exist! It contradicts\n: >the rules of nature.\n: \n: Obviously, an omnipotent god can change the rules.\n\nWhen you say, "By definition", what exactly is being defined;\ncertainly not omnipotence. You seem to be saying that the "rules of\nnature" are pre-existant somehow, that they not only define nature but\nactually cause it. If that\'s what you mean I\'d like to hear your\nfurther thoughts on the question.\n\nBill\n',
{'category': 'alt.atheism'})
从向量数据库中删除项目
# Delete documents by passing one or more keys/ids
vector_store.index.drop_keys(ids[0])
1
检查创建的索引
一旦Redis
VectorStore对象构建完成,如果Redis中尚不存在索引,则会创建一个索引。可以使用rvl
和redis-cli
命令行工具检查索引。如果您在上面安装了redisvl
,则可以使用rvl
命令行工具检查索引。
# assumes you're running Redis locally (use --host, --port, --password, --username, to change this)
!rvl index listall --port 6379
[32m17:54:50[0m [34m[RedisVL][0m [1;30mINFO[0m Using Redis address from environment variable, REDIS_URL
[32m17:54:50[0m [34m[RedisVL][0m [1;30mINFO[0m Indices:
[32m17:54:50[0m [34m[RedisVL][0m [1;30mINFO[0m 1. newsgroups
Redis
VectorStore实现将尝试为通过from_texts
、from_texts_return_keys
和from_documents
方法传递的任何元数据生成索引模式(用于过滤的字段)。这样,传递的任何元数据都将被索引到Redis搜索索引中,从而允许根据这些字段进行过滤。
下面我们展示了从上面定义的元数据中创建了哪些字段
!rvl index info -i newsgroups --port 6379
[32m17:54:50[0m [34m[RedisVL][0m [1;30mINFO[0m Using Redis address from environment variable, REDIS_URL
Index Information:
╭──────────────┬────────────────┬────────────────┬─────────────────┬────────────╮
│ Index Name │ Storage Type │ Prefixes │ Index Options │ Indexing │
├──────────────┼────────────────┼────────────────┼─────────────────┼────────────┤
│ newsgroups │ HASH │ ['newsgroups'] │ [] │ 0 │
╰──────────────┴────────────────┴────────────────┴─────────────────┴────────────╯
Index Fields:
╭───────────┬─────────────┬────────┬────────────────┬────────────────┬────────────────┬────────────────┬────────────────┬────────────────┬─────────────────┬────────────────╮
│ Name │ Attribute │ Type │ Field Option │ Option Value │ Field Option │ Option Value │ Field Option │ Option Value │ Field Option │ Option Value │
├───────────┼─────────────┼────────┼────────────────┼────────────────┼────────────────┼────────────────┼────────────────┼────────────────┼─────────────────┼────────────────┤
│ text │ text │ TEXT │ WEIGHT │ 1 │ │ │ │ │ │ │
│ embedding │ embedding │ VECTOR │ algorithm │ FLAT │ data_type │ FLOAT32 │ dim │ 768 │ distance_metric │ COSINE │
│ category │ category │ TAG │ SEPARATOR │ | │ │ │ │ │ │ │
╰───────────┴─────────────┴────────┴────────────────┴────────────────┴────────────────┴────────────────┴────────────────┴────────────────┴─────────────────┴────────────────╯
!rvl stats -i newsgroups --port 6379
[32m17:54:51[0m [34m[RedisVL][0m [1;30mINFO[0m Using Redis address from environment variable, REDIS_URL
Statistics:
╭─────────────────────────────┬────────────╮
│ Stat Key │ Value │
├─────────────────────────────┼────────────┤
│ num_docs │ 249 │
│ num_terms │ 16178 │
│ max_doc_id │ 250 │
│ num_records │ 50394 │
│ percent_indexed │ 1 │
│ hash_indexing_failures │ 0 │
│ number_of_uses │ 2 │
│ bytes_per_record_avg │ 38.2743 │
│ doc_table_size_mb │ 0.0263586 │
│ inverted_sz_mb │ 1.83944 │
│ key_table_size_mb │ 0.00932026 │
│ offset_bits_per_record_avg │ 10.6699 │
│ offset_vectors_sz_mb │ 0.089057 │
│ offsets_per_term_avg │ 1.38937 │
│ records_per_doc_avg │ 202.386 │
│ sortable_values_size_mb │ 0 │
│ total_indexing_time │ 72.444 │
│ total_inverted_index_blocks │ 16207 │
│ vector_index_sz_mb │ 3.01776 │
╰─────────────────────────────┴────────────╯
查询向量数据库
创建向量数据库并添加相关文档后,您很可能希望在链或代理运行期间查询它。
直接查询
执行简单的相似性搜索可以按如下方式进行
query = "Tell me about space exploration"
results = vector_store.similarity_search(query, k=2)
print("Simple Similarity Search Results:")
for doc in results:
print(f"Content: {doc.page_content[:100]}...")
print(f"Metadata: {doc.metadata}")
print()
Simple Similarity Search Results:
Content: From: [email protected] (Terry Ford)
Subject: A flawed propulsion system: Space Shuttle
X-Ad...
Metadata: {'category': 'sci.space'}
Content: From: [email protected]
Subject: Space Design Movies?
Article-I.D.: aurora.1993Apr23.124722.1
...
Metadata: {'category': 'sci.space'}
如果要执行相似性搜索并接收相应的评分,可以运行
# Similarity search with score and filter
scored_results = vector_store.similarity_search_with_score(query, k=2)
print("Similarity Search with Score Results:")
for doc, score in scored_results:
print(f"Content: {doc.page_content[:100]}...")
print(f"Metadata: {doc.metadata}")
print(f"Score: {score}")
print()
Similarity Search with Score Results:
Content: From: [email protected] (Terry Ford)
Subject: A flawed propulsion system: Space Shuttle
X-Ad...
Metadata: {'category': 'sci.space'}
Score: 0.569670975208
Content: From: [email protected]
Subject: Space Design Movies?
Article-I.D.: aurora.1993Apr23.124722.1
...
Metadata: {'category': 'sci.space'}
Score: 0.590400338173
通过转换为检索器进行查询
您还可以将向量数据库转换为检索器,以便在链中更轻松地使用。
retriever = vector_store.as_retriever(search_type="similarity", search_kwargs={"k": 2})
retriever.invoke("What planet in the solar system has the largest number of moons?")
[Document(metadata={'category': 'sci.space'}, page_content='Subject: Re: Comet in Temporary Orbit Around Jupiter?\nFrom: Robert Coe <[email protected]>\nDistribution: world\nOrganization: 1776 Enterprises, Sudbury MA\nLines: 23\n\[email protected] writes:\n\n> >> Also, perihelions of Gehrels3 were:\n> >> \n> >> April 1973 83 jupiter radii\n> >> August 1970 ~3 jupiter radii\n> > \n> > Where 1 Jupiter radius = 71,000 km = 44,000 mi = 0.0005 AU. So the\n> > 1970 figure seems unlikely to actually be anything but a perijove.\n> > Is that the case for the 1973 figure as well?\n> > -- \n> Sorry, _perijoves_...I\'m not used to talking this language.\n\nHmmmm.... The prefix "peri-" is Greek, not Latin, so it\'s usually used\nwith the Greek form of the name of the body being orbited. (That\'s why\nit\'s "perihelion" rather than "perisol", "perigee" rather than "periterr",\nand "pericynthion" rather than "perilune".) So for Jupiter I\'d expect it\nto be something like "perizeon".) :^)\n\n ___ _ - Bob\n /__) _ / / ) _ _\n(_/__) (_)_(_) (___(_)_(/_______________________________________ [email protected]\nRobert K. Coe ** 14 Churchill St, Sudbury, Massachusetts 01776 ** 508-443-3265\n'),
Document(metadata={'category': 'sci.space'}, page_content='From: [email protected] (Dillon Pyron)\nSubject: Re: Why not give $1 billion to first year-long moon residents?\nLines: 42\nNntp-Posting-Host: skndiv.dseg.ti.com\nReply-To: [email protected]\nOrganization: TI/DSEG VAX Support\n\n\nIn article <[email protected]>, [email protected] (Peter Schaefer) writes:\n>In article <[email protected]>, [email protected] writes:\n>|> In article <[email protected]>, [email protected] (Gene Wright) writes:\n>|> > With the continuin talk about the "End of the Space Age" and complaints \n>|> > by government over the large cost, why not try something I read about \n>|> > that might just work.\n>|> > \n>|> > Announce that a reward of $1 billion would go to the first corporation \n>|> > who successfully keeps at least 1 person alive on the moon for a year. \n>|> > Then you\'d see some of the inexpensive but not popular technologies begin \n>|> > to be developed. THere\'d be a different kind of space race then!\n>|> > \n>|> > --\n>|> > [email protected] (Gene Wright)\n>|> > theporch.raider.net 615/297-7951 The MacInteresteds of Nashville\n>|> ====\n>|> If that were true, I\'d go for it.. I have a few friends who we could pool our\n>|> resources and do it.. Maybe make it a prize kind of liek the "Solar Car Race"\n>|> in Australia..\n>|> Anybody game for a contest!\n>|> \n>|> ==\n>|> Michael Adams, [email protected] -- I\'m not high, just jacked\n>\n>\n>Oh gee, a billion dollars! That\'d be just about enough to cover the cost of the\n>feasability study! Happy, Happy, JOY! JOY!\n>\n\nFeasability study?? What a wimp!! While you are studying, others would be\ndoing. Too damn many engineers doing way too little engineering.\n\n"He who sits on his arse sits on his fortune" - Sir Richard Francis Burton\n--\nDillon Pyron | The opinions expressed are those of the\nTI/DSEG Lewisville VAX Support | sender unless otherwise stated.\n(214)462-3556 (when I\'m here) |\n(214)492-4656 (when I\'m home) |Texans: Vote NO on Robin Hood. We need\[email protected] |solutions, not gestures.\nPADI DM-54909 |\n\n')]
检索增强生成的使用
有关如何将此向量数据库用于检索增强生成 (RAG) 的指南,请参阅以下部分
Redis 特定功能
Redis 提供了一些用于向量搜索的独特功能
使用元数据过滤的相似性搜索
我们可以根据元数据过滤搜索结果
from redisvl.query.filter import Tag
query = "Tell me about space exploration"
# Create a RedisVL filter expression
filter_condition = Tag("category") == "sci.space"
filtered_results = vector_store.similarity_search(query, k=2, filter=filter_condition)
print("Filtered Similarity Search Results:")
for doc in filtered_results:
print(f"Content: {doc.page_content[:100]}...")
print(f"Metadata: {doc.metadata}")
print()
Filtered Similarity Search Results:
Content: From: [email protected] (Terry Ford)
Subject: A flawed propulsion system: Space Shuttle
X-Ad...
Metadata: {'category': 'sci.space'}
Content: From: [email protected]
Subject: Space Design Movies?
Article-I.D.: aurora.1993Apr23.124722.1
...
Metadata: {'category': 'sci.space'}
最大边际相关性搜索
最大边际相关性搜索有助于获取多样化的结果
# Maximum marginal relevance search with filter
mmr_results = vector_store.max_marginal_relevance_search(
query, k=2, fetch_k=10, filter=filter_condition
)
print("Maximum Marginal Relevance Search Results:")
for doc in mmr_results:
print(f"Content: {doc.page_content[:100]}...")
print(f"Metadata: {doc.metadata}")
print()
Maximum Marginal Relevance Search Results:
Content: From: [email protected] (Terry Ford)
Subject: A flawed propulsion system: Space Shuttle
X-Ad...
Metadata: {'category': 'sci.space'}
Content: From: [email protected] (Michael Moroney)
Subject: Re: Vulcan? (No, not the guy with the ears!)
...
Metadata: {'category': 'sci.space'}
链的使用
以下代码展示了如何在简单的 RAG 链中使用向量数据库作为检索器
- OpenAI
- Anthropic
- Azure
- Cohere
- NVIDIA
- FireworksAI
- Groq
- MistralAI
- TogetherAI
pip install -qU langchain-openai
import getpass
import os
os.environ["OPENAI_API_KEY"] = getpass.getpass()
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(model="gpt-4o-mini")
pip install -qU langchain-anthropic
import getpass
import os
os.environ["ANTHROPIC_API_KEY"] = getpass.getpass()
from langchain_anthropic import ChatAnthropic
llm = ChatAnthropic(model="claude-3-5-sonnet-20240620")
pip install -qU langchain-openai
import getpass
import os
os.environ["AZURE_OPENAI_API_KEY"] = getpass.getpass()
from langchain_openai import AzureChatOpenAI
llm = AzureChatOpenAI(
azure_endpoint=os.environ["AZURE_OPENAI_ENDPOINT"],
azure_deployment=os.environ["AZURE_OPENAI_DEPLOYMENT_NAME"],
openai_api_version=os.environ["AZURE_OPENAI_API_VERSION"],
)
pip install -qU langchain-google-vertexai
import getpass
import os
os.environ["GOOGLE_API_KEY"] = getpass.getpass()
from langchain_google_vertexai import ChatVertexAI
llm = ChatVertexAI(model="gemini-1.5-flash")
pip install -qU langchain-cohere
import getpass
import os
os.environ["COHERE_API_KEY"] = getpass.getpass()
from langchain_cohere import ChatCohere
llm = ChatCohere(model="command-r-plus")
pip install -qU langchain-nvidia-ai-endpoints
import getpass
import os
os.environ["NVIDIA_API_KEY"] = getpass.getpass()
from langchain import ChatNVIDIA
llm = ChatNVIDIA(model="meta/llama3-70b-instruct")
pip install -qU langchain-fireworks
import getpass
import os
os.environ["FIREWORKS_API_KEY"] = getpass.getpass()
from langchain_fireworks import ChatFireworks
llm = ChatFireworks(model="accounts/fireworks/models/llama-v3p1-70b-instruct")
pip install -qU langchain-groq
import getpass
import os
os.environ["GROQ_API_KEY"] = getpass.getpass()
from langchain_groq import ChatGroq
llm = ChatGroq(model="llama3-8b-8192")
pip install -qU langchain-mistralai
import getpass
import os
os.environ["MISTRAL_API_KEY"] = getpass.getpass()
from langchain_mistralai import ChatMistralAI
llm = ChatMistralAI(model="mistral-large-latest")
pip install -qU langchain-openai
import getpass
import os
os.environ["TOGETHER_API_KEY"] = getpass.getpass()
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(
base_url="https://api.together.xyz/v1",
api_key=os.environ["TOGETHER_API_KEY"],
model="mistralai/Mixtral-8x7B-Instruct-v0.1",
)
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
# Prompt
prompt = ChatPromptTemplate.from_messages(
[
(
"human",
"""You are an assistant for question-answering tasks. Use the following pieces of retrieved context to answer the question. If you don't know the answer, just say that you don't know. Use three sentences maximum and keep the answer concise.
Question: {question}
Context: {context}
Answer:""",
),
]
)
def format_docs(docs):
return "\n\n".join(doc.page_content for doc in docs)
rag_chain = (
{"context": retriever | format_docs, "question": RunnablePassthrough()}
| prompt
| llm
| StrOutputParser()
)
rag_chain.invoke("Describe the Space Shuttle program?")
'The Space Shuttle program was a NASA initiative that enabled reusable spacecraft to transport astronauts and cargo to and from low Earth orbit. It conducted a variety of missions, including satellite deployment, scientific research, and assembly of the International Space Station, and typically carried a crew of five astronauts. Although it achieved many successes, the program faced criticism for its safety concerns and the complexity of its propulsion system.'
连接到现有索引
为了在使用Redis
VectorStore时索引相同的元数据。您需要将相同的index_schema
作为 yaml 文件的路径或字典传递。以下显示了如何从索引中获取模式并连接到现有索引。
# write the schema to a yaml file
vector_store.index.schema.to_yaml("redis_schema.yaml")
# now we can connect to our existing index as follows
new_rdvs = RedisVectorStore(
embeddings,
redis_url=REDIS_URL,
schema_path="redis_schema.yaml",
)
results = new_rdvs.similarity_search("Space Shuttle Propulsion System", k=3)
print(results[0])
18:19:58 redisvl.index.index INFO Index already exists, not overwriting.
page_content='From: [email protected] (Terry Ford)
Subject: A flawed propulsion system: Space Shuttle
X-Added: Forwarded by Space Digest
Organization: [via International Space University]
Original-Sender: [email protected]
Distribution: sci
Lines: 13
For an essay, I am writing about the space shuttle and a need for a better
propulsion system. Through research, I have found that it is rather clumsy
(i.e. all the checks/tests before launch), the safety hazards ("sitting
on a hydrogen bomb"), etc.. If you have any beefs about the current
space shuttle program Re: propulsion, please send me your ideas.
Thanks a lot.
--
Terry Ford [[email protected]]
Nepean, Ontario, Canada.
' metadata={'category': 'sci.space'}
# compare the two schemas to verify they are the same
new_rdvs.index.schema == vector_store.index.schema
True
清理向量数据库
# Clear vector store
vector_store.index.delete(drop=True)
API 参考
有关所有 RedisVectorStore 功能和配置的详细文档,请访问 API 参考:https://python.langchain.ac.cn/api_reference/redis/vectorstores/langchain_redis.vectorstores.RedisVectorStore.html