所有文章 > API产品 > LangChain RAG与React, FastAPI, Cosmos DB Vector

LangChain RAG与React, FastAPI, Cosmos DB Vector

使用 React、FastAPI 和 Cosmos DB 矢量存储的 LangChain RAG 模式系列的第一部分基于使用 Cosmos DB for MongoDB 进行 LangChain 矢量搜索。本文介绍如何使用 LangChain 将文档加载到 Cosmos DB for MongoDB VCore 矢量存储中,为整个系列奠定了基础。第 2 部分将使用 FastAPI 构建 LangChain RAG 和 API。本教程将逐步引导您完成项目的每一步,确保您熟悉所有核心组件及流程。通过整个系列的学习,您将掌握如何将这些技术无缝集成,从而在处理类似项目时充满信心并具备相应技能。这份全面的指南将帮助您应对项目的复杂性,实现强大且高效的端到端解决方案。

先决条件

  • 若您尚未拥有Azure订阅,请先行创建一个Azure免费帐户以便开始。
  • 为OpenAI API设置帐户(概述可参考OpenAI API官方指南)。
  • 根据快速入门指南,创建Azure Cosmos DB for MongoDB vCore实例。
  • 准备一款用于开发的IDE,例如VS Code。

第一部分:

检索增强一代 (RAG):它是什么?

大型语言模型(LLM)系统虽覆盖广泛主题,但其知识范畴仅限于截至某一时间节点的公开信息。若要开发能够理解机密数据或最新信息的AI工具,则需将相关数据融入模型中。我们通常将此过程命名为检索增强生成(RAG),也可称之为模型“接地”。

下载项目

对于此项目,代码和示例数据集可在我的 GitHub 上获取。

设置 Python

在本教程中,我们将充分利用 Python,并需要在您的计算机上进行相关设置。我们将借助 Python 和 LangChain,将向量数据导入 Azure Cosmos DB for MongoDB vCore,并执行相似性搜索。本演练的开发与测试均基于 Python 3.11.4 版本。

首先在 demo_loader 目录中设置 python 虚拟环境。

python -m venv venv

激活您的环境并在 demo_loader 目录中安装依赖项:

venv\Scripts\activate
python -m pip install -r requirements.txt

在 demo_loader 目录中创建名为 ‘.env’ 的文件,以存储环境变量。

OPENAI_API_KEY="**Your Open AI Key**"
MONGO_CONNECTION_STRING="mongodb+srv:**your connection string from Azure Cosmos DB**"
AZURE_STORAGE_CONNECTION_STRING="**"
环境变量描述
OPENAI_API_KEY连接到 OpenAI API 的关键。如果您没有 Open AI 的 API 密钥,您可以按照概述的指南继续。
MONGO_CONNECTION_STRINGAzure Cosmos DB for MongoDB vCore 的连接字符串(见下文)
AZURE_STORAGE_CONNECTION_STRINGAzure 存储帐户的连接字符串(见下文)
.env 文件变量

Azure Cosmos DB for MongoDB vCore 连接字符串

从“.env”文件中的环境变量MONGO_CONNECTION_STRING将包含Azure Cosmos DB for MongoDB vCore的连接字符串。您可以通过在Azure门户中选择Cosmos DB实例的“连接字符串”来获取此值,过程中可能需要在相应字段中输入您的用户名和密码。

Azure Cosmos DB for MongoDB vCore - 检索连接字符串

Azure 存储帐户连接字符串

“.env” 文件中的 AZURE_STORAGE_CONNECTION_STRING 环境变量将包含 Azure 存储帐户的连接字符串。您可以通过在 Azure 门户中选择存储帐户实例的“访问密钥”来获取此值。

Azure 存储帐户 - 检索连接字符串

使用 LangChain 加载程序加载 Cosmos DB 矢量存储

Python 文档作为将数据加载到 Cosmos DB 矢量存储和 Azure 存储帐户的主要接入点。所提供的代码片段有助于将文档数据导入到 Cosmos DB 中,并将相关联的图像文件上传到 Azure Blob 存储容器中。此流程涵盖了对给定文件名列表中每个文档的有序处理。文件名为 vectorstoreloader.py。

vectorstoreloader.py
file_names = ['documents/Rocket_Propulsion_Elements_with_images.json','documents/Introduction_To_Rocket_Science_And_Engineering_with_images.json']

file_names += file_names

for file_name in file_names:

CosmosDBLoader(f"{file_name}").load()

image_loader = BlobLoader()

with open(file_name) as file:
data = json.load(file)

resource_id = data['resource_id']
for page in data['pages']:

base64_string = page['image'].replace("b'","").replace("'","")

# Decode the Base64 string into bytes
decoded_bytes = base64.b64decode(base64_string)

image_loader.load_binay_data(decoded_bytes,f"{resource_id}/{page['page_id']}.png","images")

VectorstoreLoader 故障

  1. file_names 包含两个示例 JSON 文件,每个文件代表一个拥有相关图像的文档,总计大约包含 160 个文档页面。
  2. 该过程会遍历 file_names 列表中的每个文件名。
  3. 对于列表中的每个文件名,它会执行以下操作:
    • 使用 CosmosDBLoader(已在文章“使用 Cosmos DB for MongoDB 进行 LangChain 向量搜索”中介绍)从 JSON 文件中加载文档数据到 CosmosDB 中。
    • 初始化相关的类对象,例如 image_loader 和 BlobLoader
    • 打开 JSON 文件,并将文件数据加载到名为 .data 的变量中。
    • 从文档数据中提取 resource_id
    • 遍历文档数据中的各个页面。
    • 从每个页面中提取 base64 编码的图像数据,并使用 base64.b64decode 将其解码为字节。
    • 将解码后的图像字节加载到 image_loader 对象中,同时指定图像的目标路径和容器类型。

使用 BlobLoader 加载 Azure 存储帐户

BlobLoader 以一种简单的方式运行,它会将 JSON 文档中经过 base64 编码转换后的图像,以字节形式存储在 Azure 存储帐户的“images”容器中,这一过程是通过调用“load_binary_data”函数来实现的。以下代码段定义了一个类,该类利用从环境变量中获取到的 Azure 存储连接字符串,将二进制数据上传到 Azure Blob 存储的指定容器中。

GitHub 存储库中的代码当前默认使用名为“映像”的 Azure 存储帐户容器,若您希望继续操作,可以选择创建一个名为“images”的容器,或者根据已有的容器名称调整此段代码。

例如,在调用 image_loader.load_binary_data 函数时,您可以这样指定参数:

image_loader.load_binary_data(decoded_bytes, f"{resource_id}/{page['page_id']}.png", "images")

其中,“decoded_bytes”代表解码后的图像字节数据,“f”{resource_id}/{page[‘page_id’]}.png””定义了 Blob 的名称,而最后的“images”则是目标容器的名称。

BlobLoader.py
from os import environ
from dotenv import load_dotenv
from azure.storage.blob import BlobServiceClient

load_dotenv(override=True)


class BlobLoader():

def __init__(self):
connection_string = environ.get("AZURE_STORAGE_CONNECTION_STRING")

# Create the BlobServiceClient object
self.blob_service_client = BlobServiceClient.from_connection_string(connection_string)


def load_binay_data(self,data, blob_name:str, container_name:str):

blob_client = self.blob_service_client.get_blob_client(container=container_name, blob=blob_name)

# Upload the blob data - default blob type is BlockBlob
blob_client.upload_blob(data,overwrite=True)

BlobLoader 细分说明

  1. 使用 load_dotenv 从 .env 文件中加载环境变量到脚本的运行环境中。
  2. BlobLoader 类是一个用于将二进制数据上传到 Azure Blob 存储容器的封装器。
  3. 在 BlobLoader 类的 __init__ 方法中:
    • 它通过 environ.get("AZURE_STORAGE_CONNECTION_STRING") 从环境变量中检索 Azure 存储连接字符串。
    • 使用检索到的连接字符串初始化 BlobServiceClient 对象。
  4. 在 BlobLoader 类的 load_binary_data 方法中:
    • 该方法接收三个参数:data(二进制数据)、blob_name(Blob 名称)和 container_name(容器名称)。
    • 它使用 BlobServiceClient 的 get_blob_client 方法获取一个 blob_client 对象。
    • 然后,使用 blob_client 的 upload_blob 方法上传 data,并通过 overwrite=True 参数指示如果已存在同名的 Blob,则应覆盖它。

将文档加载到 Cosmos DB 矢量存储中,将图像加载到存储帐户中

现在我们已经查看了代码,让我们只需从 demo_loader 目录执行以下命令即可加载文档。

python vectorstoreloader.py

使用 MongoDB Compass(或类似工具)验证文档是否成功加载。

执行 LangChain Python 代码后,加载的文档会生成包含矢量内容的 MongoDB Compass

请验证是否已成功将“png”图像上传到 Azure 存储帐户的“image”容器。

Azure 存储帐户映像容器 - resource_id 文件夹

访问该目录以显示图像列表。

Azure 存储帐户映像容器、页面映像

对一两张图像进行采样,以验证字节是否已正确解码。

Azure Stroage Account 页面图像 'png'

祝贺!在本指南的第二部分和第三部分中,您已成功利用 LangChain 将文档从 JSON 文件导入至 Azure Cosmos DB for MongoDB vCore,并进一步将二进制文档上传至 Azure 存储帐户,以供应用程序便捷使用。

第二部分:

FastAPI:它是什么?

FastAPI 是一款前沿的 Web 框架,专为 Python 3.8+ 量身打造,助力开发者迅速构建高效 API。它凭借卓越的性能脱颖而出,得益于与 Starlette 和 Pydantic 的深度融合,其速度可媲美 NodeJS 和 Go。FastAPI 不仅将开发效率提升了高达 300%,更将人为错误率降低了 40%。加之出色的编辑器支持、详尽的文档资源,FastAPI 确保了直观易用的开发体验,有效减少了代码冗余,并最大限度地激发了生产力。

demo_api 项目经过设置,能够轻松应对 Web 请求,并高效处理与 Azure Cosmos DB for MongoDB 矢量数据库及 Azure 存储帐户相关的数据事务。这一设计使得代码结构清晰明了,为开发新功能及修复现有问题提供了极大的便利。

设置 Python 环境

在本教程中,Python 用于开发 FastAPI Web 界面,这需要在用户的计算机上进行设置。本教程涉及使用 Python 和 LangChain 对 Azure Cosmos DB for MongoDB vCore 进行矢量搜索,以及执行 Q&A RAG 链。在本演练的整个开发和测试过程中使用了 Python 版本 3.11.4。

首先在 demo_api 目录中设置 python 虚拟环境。

python -m venv venv

使用 demo_api 目录中的需求文件激活您的环境并安装依赖项:

venv\Scripts\activate
python -m pip install -r requirements.txt

在 demo_api 目录中创建一个名为“.env”的文件,以存储环境变量。

VECTORDB_ENDPOINT='https://[your-web-app].azurewebsites.net/'
VECTORDB_API_KEY='**your_key**'
OPENAI_API_KEY="**Your Open AI Key**"
MONGO_CONNECTION_STRING="mongodb+srv:**your connection string from Azure Cosmos DB**"
AZURE_STORAGE_CONNECTION_STRING="**"
AZURE_STORAGE_CONTAINER="images"
环境变量描述
VECTORDB_ENDPOINTWeaviate 的 URL 端点。您可以保留默认值:’https://%5Byour-web-app%5D.azurewebsites.net/’因为本练习中不使用 Weaviate。
VECTORDB_API_KEYWeaviate 身份验证 api 密钥。您可以保留默认值:‘**your_key**’,因为本练习中不使用 Weaviate。
OPENAI_API_KEY连接到 OpenAI API 的关键。如果您没有 Open AI 的 API 密钥,您可以按照概述的指南继续。
MONGO_CONNECTION_STRINGAzure Cosmos DB for MongoDB vCore 的连接字符串
AZURE_STORAGE_CONNECTION_STRINGAzure 存储帐户的连接字符串
AZURE_STORAGE_CONTAINER第 1 部分中使用的容器名称默认为 ‘images‘。
.env 文件变量

在 GitHub 存储库中,安排设置是为了促进不同矢量存储系统之间的转换,特别是 Azure Cosmos DB for MongoDB 和 Weaviate。但是,对此功能的深入探索计划在下一篇文章中介绍。

配置环境并设置变量后,我们就可以启动 FastAPI 服务器了。从 demo_api 目录运行以下命令以启动服务器。

python main.py

默认情况下,FastAPI 服务器在 localhost 环回 127.0.0.1 端口 8000 上启动。您可以使用以下 localhost 地址访问 Swagger 文档:http://127.0.0.1:8000/docs

FasterAPI Swagger 默认页面

执行矢量搜索

借助在本地运行的 FastAPI 服务,我们可以通过其终端节点对 vector 数据库执行向量搜索。在此场景下,我们输入查询词 “what is a turbofan”,随后系统将返回一系列与之匹配的条目,并在 Web 界面上展示。访问路径为 /search/{query}。

点击 “Try It out” 按钮,针对 /search/{query} 路径进行测试。

FasterAPI Swagger 搜索“试用”

为查询输入 “what is a turbofan” ,然后单击 Execute(执行)。

FastAPI Swagger 搜索结果

响应包含一个 JSON 数组,其中包含下面描述的资源。

{resource_id": "b801d68a8a0d4f1dac72dc6c170c395b",
"page_id": "cd3eea19611c423aaaf85e6da691f23d",
"title": "Rocket Propulsion Elements",
"source": "Chapter 1 - Classification (page-2)",
"content":"..text.."}

利用 RAG 回答问题

检索到的资源(或文件)可以作为大型语言模型(LLM)处理查询的基础。在这方面,我们的 RAG 端点特别适用于问答(Q&A)场景。当用户提交查询,例如“什么是涡轮风扇”时,响应中除了会包含相关的文档,还会包含一个“text”字段。这个“text”字段构成了 LLM 的答案,这些答案是从我们与查询相匹配的向量搜索结果中得出的。具体的 Q&A 端点路径为 /search/qa/{query}

FasterAPI Swagger Q&A RAG 结果

来自 RAG 终端节点的响应包含两部分内容:一部分是存储在 ‘text’ 值中的、针对查询的大型语言模型(LLM)“答案”,另一部分则是位于“ResourceCollection”下、用于支撑该答案的资源列表。

{
"text": "A turbofan is a type of air-breathing engine that uses a fan to compress air and mix it with fuel for combustion. It is a type of ducted engine that is more fuel-efficient than a turbojet. Turbofans are commonly used in commercial aircraft for propulsion.",
"ResourceCollection": [
{
"resource_id": "b801d68a8a0d4f1dac72dc6c170c395b",
"page_id": "cd3eea19611c423aaaf85e6da691f23d",
"title": "Rocket Propulsion Elements",
"source": "Chapter 1 - Classification (page-2)",
"content": "....text..."
},...]
}

查询首先会通过向量搜索来检索相关文档,然后会提示大型语言模型(LLM)利用这些文档和查询来生成答案。

使用 LangChain 的 Q&A RAG 流程

演练 LangChain 与 RAG 的问答

在 API 中集成 RAG 时,Web 搜索组件会启动所有请求,然后是搜索服务,最后是数据组件。在本示例中,我们采用的是 MongoDB 数据搜索,它具体连接到的是 Azure Cosmos DB for MongoDB vCore。在这几层架构中,Model 组件会在各层之间传递,而大部分的 LangChain 代码则主要驻留在服务层。我采用这种方法的目的,是为了在使用相同的链时能够方便地切换不同的数据源。

Web 层

Web 层负责路由请求并管理与调用方的通信。在 Q&A RAG 的上下文中,我们只有两个代码文件:主要的 FastAPI 应用程序 (main.py) 和用于搜索的 API 路由器 (search.py)。

main.py
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

from web import search, content

app = FastAPI()

origins = ["*"]

app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)



app.include_router(search.router)
app.include_router(content.router)


@app.get("/")
def get() -> str:
return "running"


if __name__ == "__main__":
import uvicorn
uvicorn.run("main:app", reload=True)

main.py 这段代码启动并配置了一个集成了 CORS(跨源资源共享)中间件的 FastAPI Web 应用程序,使其能够顺畅地处理来自不同源的请求。该应用程序通过整合搜索和内容相关的终端节点路由器,能够高效地应对多种类型的请求。同时,它还定义了一个默认端点(“/”),该端点会返回一个简单的 “running” 消息,这对于测试应用程序的功能来说是一个实用的工具。在开发和测试阶段,我充分利用了这个简洁的消息来验证应用状态。利用 uvicorn 运行 FastAPI 应用程序,并启用自动重载功能,极大地提升了开发效率,减少了在测试和优化应用程序过程中所需的时间和精力。

web/search.py
from fastapi import APIRouter
from service import search as search
from model.resource import Resource
from model.airesults import AIResults

router = APIRouter(prefix="/search")


@router.get("/{query}")
def get_search(query) -> list[Resource]:
return search.get_query(query)


@router.get("/summary/{query}")
def get_query_summary(query) -> AIResults:
return search.get_query_summary(query)


@router.get("/qa/{query}")
def get_query_qa(query) -> AIResults:
return search.get_qa_from_query(query)

Web 搜索代码负责管理各种与搜索相关的终端节点。它有助于集成 service 模块中的功能,并且包含处理资源和 AI 结果的模型。路由器的前缀明显为 “/search”,并包含三个基本的 GET 路由,每个路由都有其特定的用途:searchResource 和 searchAIResults

第一个端点 /search/{query} 在根据提供的查询检索搜索结果方面起着关键作用。此过程涉及调用 service 模块中的函数,然后该函数会编排并返回一个对象列表,这些对象封装了所获得的搜索结果的本质。

继续介绍该路线,/search/summary/{query} 途径旨在获取与提供的查询相关联的搜索结果的摘要。这是通过调用 service 模块中相应的函数来实现的,该函数最终返回一个封装了搜索过程汇总结果的对象。

最后,/search/qa/{query} 路由侧重于使用 LangChain 的 RAG 模式来检索问答结果。这是通过调用 service 模块中的某个函数来实现的。

服务层

服务层构成了我们主要业务逻辑的基础。在这个特定用例的上下文中,服务层扮演着 LangChain 代码存储库的重要角色,将它们定位为我们技术框架中的核心组件。

service/search.py

from data.mongodb import search as search

from langchain.docstore.document import Document
from langchain.chains.combine_documents.stuff import StuffDocumentsChain
from langchain.chains.llm import LLMChain
from langchain.prompts import PromptTemplate
from langchain_openai import ChatOpenAI
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough
from langchain_openai import ChatOpenAI
from langchain.prompts import PromptTemplate

from model.airesults import AIResults
from model.resource import Resource


template:str = """Use the following pieces of context to answer the question at the end.
If none of the pieces of context answer the question, just say you don't know.
If you don't know the answer, just say that you don't know, don't try to make up an answer.
Use three sentences maximum and keep the answer as concise as possible.

{context}

Question: {question}

Answer:"""


def get_query(query:str)-> list[Resource]:
resources, docs = search.similarity_search(query)
return resources


def get_query_summary(query:str) -> str:
prompt_template = """Write a summary of the following:
"{text}"
CONCISE SUMMARY:"""
prompt = PromptTemplate.from_template(prompt_template)

resources, docs = search.similarity_search(query)

if len(resources)==0:return AIResults(text="No Documents Found",ResourceCollection=resources)

llm = ChatOpenAI(temperature=0, model_name="gpt-3.5-turbo-16k")
llm_chain = LLMChain(llm=llm, prompt=prompt)

stuff_chain = StuffDocumentsChain(llm_chain=llm_chain, document_variable_name="text")

return AIResults(stuff_chain.run(docs),resources)


def get_qa_from_query(query:str) -> str:

resources, docs = search.similarity_search(query)

if len(resources) ==0 :return AIResults(text="No Documents Found",ResourceCollection=resources)

custom_rag_prompt = PromptTemplate.from_template(template)
llm = ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0)

def format_docs(docs):
return "\n\n".join(doc.page_content for doc in docs)

content = format_docs(docs)

rag_chain = (
{"context": lambda x: content , "question": RunnablePassthrough()}
| custom_rag_prompt
| llm
| StrOutputParser()
)

return AIResults(text=rag_chain.invoke(query),ResourceCollection=resources)

该 search.py 服务展示了数据库交互、语言模型以及提示模板的集成,从而能够根据用户查询提供摘要和问答等功能。起初,它定义了一个模板字符串,该模板用于创建与 RAG(检索增强型生成模型)相关的问题和答案。此模板内嵌了上下文和问题提示的占位符。搜索服务包含以下三个功能:

第一个搜索服务函数:该函数接收查询字符串作为输入,随后在数据库中执行与查询相似的资源向量搜索,并返回匹配资源的列表。函数签名为 get_query(query: str) -> list[Resource]

第二个函数 :该函数生成与给定查询相关联的文档的简洁摘要。它首先通过向量搜索找到相关文档,然后利用某个文档链(在描述中被误写为 StuffDocumentChain,可能是指具体的文档处理链或模块)来总结这些文档。函数签名为 get_query_summary(query: str) -> str

最后一个函数 :该函数检索与查询相关的文档,并基于这些文档构建问题的答案。它运用全局提示来生成问题和答案,同时利用从向量搜索返回的文档作为输入。函数签名为 get_qa_from_query(query: str) -> str

数据层

最后,我们到达了数据层。尽管 GitHub 存储库包含 Weaviate 和 Cosmos DB for MongoDB 的代码(但在此讨论中仅涉及 MongoDB 的部分),本系列将专注于与 Cosmos DB 的连接。在数据层中,我们利用 init.py 文件中的模块作为单例来处理与数据库相关的连接,这是一种清晰的方法,尽管有时我也会考虑使用全局变量作为替代方案。除了 init.py 文件,search.py 文件还负责执行对 Cosmos DB 的向量搜索。

data/mongodb/init.py
from os import environ
from dotenv import load_dotenv
from pymongo import MongoClient
from pymongo.collection import Collection
from langchain_openai import OpenAIEmbeddings
from langchain_community.vectorstores.azure_cosmos_db import AzureCosmosDBVectorSearch


load_dotenv(override=True)


collection: Collection | None = None
vector_store: AzureCosmosDBVectorSearch | None=None

def mongodb_init():
MONGO_CONNECTION_STRING = environ.get("MONGO_CONNECTION_STRING")
DB_NAME = "research"
COLLECTION_NAME = "resources"
INDEX_NAME = "vectorSearchIndex"

global collection, vector_store
client = MongoClient(MONGO_CONNECTION_STRING)
db = client[DB_NAME]
collection = db[COLLECTION_NAME]
vector_store = AzureCosmosDBVectorSearch.from_connection_string(MONGO_CONNECTION_STRING,
DB_NAME + "." + COLLECTION_NAME,
OpenAIEmbeddings(disallowed_special=()),
index_name=INDEX_NAME
)


mongodb_init()

该文件首先使用 load_dotenv(override=True) 方法从 .env 文件中加载环境变量。随后,它声明了两个全局变量:一个表示 CosmosDB MongoDB 集合的 collection,另一个表示 CosmosDB 向量搜索的 vector_store。接着,使用 MongoDB 的连接字符串初始化 MongoClient,并通过该客户端检索数据库和集合对象。之后,这些对象被传递到 AzureCosmosDBVectorSearch.from_connection_string() 方法中。

data/mongodb/search.py
from model.resource import Resource
from .init import collection, vector_store
from langchain.docstore.document import Document
from typing import List, Optional, Union




def results_to_model(result:Document) -> Resource:
return Resource(resource_id = result.metadata["resource_id"],
page_id = result.metadata["page_id"],
title=result.metadata["title"],
source=f"{result.metadata['chapter']} (page-{result.metadata['pagenumber']})",
content=result.page_content)



def similarity_search(query:str)-> tuple[list[Resource], list[Document]]:

docs = vector_store.similarity_search_with_score(query,4)

# Cosine Similarity:
#It measures the cosine of the angle between two vectors in an n-dimensional space.
#The values of similarity metrics typically range between 0 and 1, with higher values indicating greater similarity between the vectors.
docs_filters = [doc for doc, score in docs if score >=.75]

# List the scores for documents
for doc, score in docs:
print(score)

# Print number of documents passing score threshold
print(len(docs_filters))

return [results_to_model(document) for document in docs_filters],docs_filters

数据检索代码通过我们的单例访问全局变量,当前包含两个关键函数,分别涉及相似性搜索和数据转换。

第一个函数接收一个 LangChain 对象作为输入,并输出一个 ResourceDocument 对象。该函数从提供的 Document 中抽取元数据属性,例如 resource_idpage_id、标题、章节以及页码。此函数的目的是确保向量搜索返回的资源能够在 LangChain 外部得到重用。函数签名为 results_to_model(result: Document) -> Resource

第二个函数利用指定的查询来执行相似性搜索。它调用 vector_store 的某个方法来检索与给定查询相似的文档,以及这些文档各自的相似性分数。该函数根据阈值分数(0.75)对检索到的文档进行筛选,并利用 results_to_model 函数将筛选后的文档转换为 Resource 对象。最终,该函数返回一个元组,包含转换后的 Resource 对象列表和原始的 Document 对象列表。函数签名为 similarity_search(query: str) -> Tuple[List[Resource], List[Document]]

恭喜您顺利完成了 Web 框架的设置!这确实是一项艰巨的任务,但为第3部分中即将展开的工作奠定了坚实的基础。

原文链接:https://stochasticcoder.com/2024/02/27/langchain-rag-with-react-fastapi-cosmos-db-vector-part-1/

https://stochasticcoder.com/2024/02/29/langchain-rag-with-react-fastapi-cosmos-db-vector-part-2/