自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

多用戶數(shù)據(jù)檢索:LangChain技術(shù)指南與案例分析

原創(chuàng) 精選
人工智能
文章探討了如何確保不同用戶數(shù)據(jù)的隔離,并提供靈活的配置選項(xiàng)以適應(yīng)各種檢索需求。

作者 | 崔皓

審校 | 重樓

摘要

文章探討了如何確保不同用戶數(shù)據(jù)的隔離,并提供靈活的配置選項(xiàng)以適應(yīng)各種檢索需求。

文章首先介紹了多用戶數(shù)據(jù)檢索的背景和挑戰(zhàn),包括數(shù)據(jù)權(quán)限管理、檢索系統(tǒng)靈活性和用戶體驗(yàn)問題。接著進(jìn)行了技術(shù)分析,特別強(qiáng)調(diào)了使用Pinecone作為向量數(shù)據(jù)庫(kù)來處理高維向量數(shù)據(jù)的優(yōu)勢(shì)。文中詳細(xì)討論了數(shù)據(jù)存儲(chǔ)和檢索的關(guān)鍵步驟,如多用戶支持的檢索器確認(rèn)、鏈條配置字段的添加和運(yùn)用可配置字段來調(diào)用鏈條。最后,通過實(shí)際代碼演示了如何在LangChain中實(shí)現(xiàn)多用戶檢索,包括環(huán)境設(shè)置、文本嵌入、配置索引器與Chain的構(gòu)建,以及通過特定命名空間對(duì)文檔庫(kù)進(jìn)行隔離的測(cè)試結(jié)果。

背景

多用戶環(huán)境下的數(shù)據(jù)檢索,要求系統(tǒng)能夠區(qū)分并管理不同用戶的數(shù)據(jù)。這不僅涉及到數(shù)據(jù)安全性和隱私保護(hù),還要求檢索系統(tǒng)能夠靈活應(yīng)對(duì)不同用戶的數(shù)據(jù)檢索需求。假設(shè)有一家大型企業(yè),擁有龐大的知識(shí)庫(kù)系統(tǒng),該系統(tǒng)存儲(chǔ)了從市場(chǎng)分析到技術(shù)文檔的各類信息。企業(yè)內(nèi)部有多個(gè)部門,如研發(fā)、市場(chǎng)、人力資源等,每個(gè)部門對(duì)知識(shí)庫(kù)的數(shù)據(jù)訪問需求不同。為了保證信息安全,企業(yè)需要實(shí)現(xiàn)對(duì)數(shù)據(jù)的權(quán)限控制,確保每個(gè)部門只能訪問對(duì)應(yīng)的相關(guān)數(shù)據(jù)。

在這個(gè)業(yè)務(wù)場(chǎng)景中,最大的挑戰(zhàn)是如何在保證數(shù)據(jù)安全的同時(shí),還能滿足不同用戶的數(shù)據(jù)檢索需求。具體問題包括:

數(shù)據(jù)權(quán)限管理:如何確保每個(gè)用戶只能訪問授權(quán)的數(shù)據(jù)?

檢索系統(tǒng)的靈活性:如何設(shè)計(jì)一個(gè)既能保護(hù)數(shù)據(jù)安全,又能靈活響應(yīng)不同用戶檢索需求的系統(tǒng)?

用戶體驗(yàn):如何在不泄露其他部門數(shù)據(jù)的前提下,提供快速準(zhǔn)確的檢索結(jié)果?

技術(shù)分析

LangChain是大模型應(yīng)用框架,特別擅長(zhǎng)處理檢索任務(wù),即從大量數(shù)據(jù)中找到與給定查詢最相關(guān)的信息。在這篇文章中,我們將重點(diǎn)介紹如何在LangChain框架中實(shí)現(xiàn)多用戶檢索。那么,為了實(shí)現(xiàn)多用戶檢索不同數(shù)據(jù),就需要解決數(shù)據(jù)存儲(chǔ)和數(shù)據(jù)檢索兩個(gè)問題。

數(shù)據(jù)存儲(chǔ)方面

在AI應(yīng)用中,如推薦系統(tǒng)或語(yǔ)義搜索,需要處理和檢索大量的高維向量數(shù)據(jù)。因此處理大規(guī)模向量數(shù)據(jù)時(shí)會(huì)面臨如下問題

  • 實(shí)時(shí)數(shù)據(jù)更新和查詢延遲問題:AI應(yīng)用需要快速反映數(shù)據(jù)的最新變更(如實(shí)時(shí)更新用戶偏好)。許多系統(tǒng)難以在保證準(zhǔn)確性的同時(shí)實(shí)現(xiàn)低延遲的數(shù)據(jù)更新和查詢。
  • 復(fù)雜的基礎(chǔ)設(shè)施管理和成本:構(gòu)建和維護(hù)用于存儲(chǔ)和檢索向量數(shù)據(jù)的基礎(chǔ)設(shè)施通常復(fù)雜且成本高昂,尤其是在云環(huán)境下。
  • 高維數(shù)據(jù)的存儲(chǔ)和索引優(yōu)化問題:存儲(chǔ)密集或稀疏的向量嵌入,需要優(yōu)化的存儲(chǔ)結(jié)構(gòu)和索引策略,以保持高效檢索和存儲(chǔ)性能。
  • 多語(yǔ)言和多平臺(tái)接入難題:AI應(yīng)用開發(fā)者可能需要在不同的編程環(huán)境(如Python,Node.js)中處理向量數(shù)據(jù),需要一個(gè)跨平臺(tái)、易于使用的API。

為了解決上述問題,本例我們選用Pinecone。Pinecone是一個(gè)為AI應(yīng)用設(shè)計(jì)的云原生向量數(shù)據(jù)庫(kù),提供簡(jiǎn)易API和自管理的基礎(chǔ)設(shè)施。它專門處理高維向量數(shù)據(jù),能夠以低延遲處理數(shù)十億向量的檢索請(qǐng)求。向量嵌入作為其核心,代表語(yǔ)義信息,賦予AI應(yīng)用長(zhǎng)期記憶功能,使其能在執(zhí)行復(fù)雜任務(wù)時(shí)利用以往經(jīng)驗(yàn)。

與傳統(tǒng)標(biāo)量數(shù)據(jù)庫(kù)相比,Pinecone提供了針對(duì)向量數(shù)據(jù)的優(yōu)化存儲(chǔ)和查詢,解決了處理復(fù)雜向量數(shù)據(jù)的難題。它的索引包含獨(dú)特ID和密集向量嵌入的浮點(diǎn)數(shù)數(shù)組,也支持稀疏向量嵌入和元數(shù)據(jù)鍵值對(duì),用于混合搜索和過濾查詢。Pinecone保證高性能、實(shí)時(shí)性,每個(gè)pod副本每秒可處理200個(gè)查詢,反映最新數(shù)據(jù)更新。用戶可通過HTTP、Python或Node.js進(jìn)行增刪改查操作,靈活處理向量數(shù)據(jù)。

數(shù)據(jù)檢索方面

為了實(shí)現(xiàn)多用戶檢索需要執(zhí)行如下關(guān)鍵步驟:

1. 多用戶支持的檢索器確認(rèn):檢查使用的檢索器是否支持多用戶功能。目前LangChain沒有統(tǒng)一的標(biāo)識(shí)或過濾器來實(shí)現(xiàn)這一點(diǎn),每個(gè)向量存儲(chǔ)和檢索器可能有自己的實(shí)現(xiàn)方式(如命名空間、多租戶等)。通常,這通過在`similarity_search`時(shí)傳遞的關(guān)鍵字參數(shù)來暴露。因此,需要通過閱讀文檔或源代碼來確定所用檢索器是否支持多用戶功能,以及如何使用它。

2. 為鏈條添加配置字段:在運(yùn)行時(shí)調(diào)用鏈條并配置任何相關(guān)標(biāo)志。查閱相關(guān)文檔了解更多關(guān)于配置的信息。需要說明的是, “鏈條”(Chains)是LangChain的一個(gè)關(guān)鍵概念,它們是一系列處理步驟的集合,用于執(zhí)行特定的任務(wù)。為了支持多用戶檢索,用戶需要在鏈條中添加配置字段。這些字段允許在運(yùn)行時(shí)動(dòng)態(tài)調(diào)整鏈條的行為,以適應(yīng)不同用戶的需求。

3. 使用可配置字段調(diào)用鏈條:運(yùn)行時(shí),通過前面設(shè)置的可配置字段,可以實(shí)現(xiàn)對(duì)鏈條的個(gè)性化調(diào)用。這意味著用戶可以根據(jù)不同的情境或用戶需求,調(diào)整鏈條的行為。這一步是實(shí)現(xiàn)多用戶檢索的關(guān)鍵,它確保了檢索結(jié)果能夠根據(jù)不同用戶的獨(dú)特需求進(jìn)行優(yōu)化和調(diào)整。

上面三點(diǎn)需要索引支持多用戶查詢,用戶查詢數(shù)據(jù)的參數(shù)可以通過配置字段的方式傳遞給Chains,同時(shí)Chains 可以接受配置字段并且執(zhí)行,完成數(shù)據(jù)檢索的操作。

根據(jù)前面對(duì)Pinecone向量存儲(chǔ)的描述,我們通過查閱LangChain 官方文檔了解

既然數(shù)據(jù)存儲(chǔ)和數(shù)據(jù)檢索的問題都得到了解決,下面就開始代碼實(shí)踐的環(huán)節(jié)。包langchain_community.vectorstores.pinecone.Pinecone 下面包含了as_retriever方法,該方法創(chuàng)建并返回一個(gè)VectorStoreRetriever對(duì)象,該對(duì)象從VectorStore初始化。這個(gè)檢索器提供了多種搜索類型,使得用戶可以根據(jù)不同需求進(jìn)行定制化的向量數(shù)據(jù)檢索。

該方法的關(guān)鍵參數(shù)如下

search_type(可選字符串)
定義:指定檢索器執(zhí)行的搜索類型。
選項(xiàng):
"similarity":標(biāo)準(zhǔn)的相似度搜索,默認(rèn)選項(xiàng)。
"mmr":最大邊緣相關(guān)性(Maximum Marginal Relevance),用于生成多樣化的搜索結(jié)果。
"similarity_score_threshold":設(shè)置相似度分?jǐn)?shù)閾值,僅返回超過此閾值的文檔。
search_kwargs(可選字典)
功能:提供給搜索函數(shù)的關(guān)鍵字參數(shù)。
包含內(nèi)容:
k:返回的文檔數(shù)量,默認(rèn)為4。
score_threshold:用于similarity_score_threshold的最小相關(guān)性閾值。
fetch_k:傳遞給MMR算法的文檔數(shù)量,默認(rèn)為20。
lambda_mult:MMR結(jié)果的多樣性程度,從1(最小多樣性)到0(最大多樣性),默認(rèn)為0.5。
filter:基于文檔元數(shù)據(jù)的過濾條件。
返回值
類型:VectorStoreRetriever
功能:一個(gè)檢索類,用于在VectorStore上執(zhí)行數(shù)據(jù)檢索操作。

代碼實(shí)踐

技術(shù)分析之后就需要分幾個(gè)步驟進(jìn)行代碼實(shí)踐,具體步驟如下:

Pinecone信息獲取

首先需要注冊(cè)Pinecone的賬號(hào),然后獲取對(duì)應(yīng)API Keys在調(diào)用Pinecone服務(wù)的時(shí)候會(huì)用到它。注冊(cè)Pinecone的過程比較簡(jiǎn)單,填寫基本信息就可以完成,這里不再贅述。如下圖所示,在用戶控制臺(tái)的“API Keys” 菜單中選擇key對(duì)應(yīng)的“復(fù)制”圖標(biāo),從而復(fù)制“API Keys”留作備用。

接著“Indexes”頁(yè)面去創(chuàng)建index,如下圖所示,選擇“Setup by model”。

在彈出的對(duì)話框中,我們選擇OpenAI 的embedding 作為index 的配置項(xiàng)。

最終,如下圖所示,點(diǎn)擊“Create indexes” 按鈕創(chuàng)建index。

創(chuàng)建index 完成之后,可以通過下圖看到對(duì)應(yīng)的信息,其中“rag-per-user”是index的名字,gcp-starter作為環(huán)境的名字。這兩個(gè)信息在初始化Pinecone的時(shí)候是需要的。

環(huán)境安裝與參數(shù)配置

需要將代碼需要的組件包安裝好,通過如下命令實(shí)現(xiàn)安裝

!pip install openai langchain pinecone-client pypdf tiktoken -q -U

Openai這是OpenAI提供的官方Python庫(kù),用于與OpenAI的API(如GPT和DALL-E等)進(jìn)行交互。

Langchain這個(gè)庫(kù)可能是用于處理語(yǔ)言相關(guān)任務(wù)的。它可能包含了一些用于自然語(yǔ)言處理、機(jī)器翻譯或其他語(yǔ)言技術(shù)的工具和模型。

pinecone-clientPinecone是一個(gè)向量數(shù)據(jù)庫(kù),用于構(gòu)建和部署大規(guī)模相似性搜索應(yīng)用。pinecone-client 是其客戶端庫(kù),用于與Pinecone服務(wù)進(jìn)行交互。

Pypdf:這是一個(gè)Python庫(kù),用于處理PDF文件。它可能允許用戶讀取、寫入、分割、合并和轉(zhuǎn)換PDF文檔。

Tiktoken:用來對(duì)文本進(jìn)行分詞。

接著再對(duì)一些參數(shù)進(jìn)行賦值如下:

import os
import getpass
os.environ["PINECONE_API_KEY"] = getpass.getpass("輸入Pinecone key")
os.environ["OPENAI_API_KEY"] = getpass.getpass("輸入OpenAI Key")
PINECONE_API_KEY=os.environ.get("PINECONE_API_KEY")
PINECONE_ENVIRONMENT="gcp-starter"
PINECONE_INDEX="rag-per-user"

(1) 導(dǎo)入模塊

import os: 導(dǎo)入 Python 的 os 模塊,它提供了許多與操作系統(tǒng)交互的功能,包括管理環(huán)境變量。

import getpass導(dǎo)入 getpass 模塊,它用于安全地獲取用戶輸入,而不在屏幕上顯示輸入(如密碼或密鑰)。

(2) 獲取并設(shè)置環(huán)境變量

os.environ["PINECONE_API_KEY"] = getpass.getpass("輸入Pinecone key"): 這行代碼首先顯示提示“輸入Pinecone key”,然后等待用戶輸入 Pinecone 的 API 密鑰。輸入的內(nèi)容不會(huì)在屏幕上顯示。輸入完成后,該密鑰被設(shè)置為環(huán)境變量 PINECONE_API_KEY。

os.environ["OPENAI_API_KEY"] = getpass.getpass("輸入OpenAI Key"): 同樣,這行代碼用于獲取并設(shè)置 OpenAI 的 API 密鑰作為環(huán)境變量 OPENAI_API_KEY。

(3) 讀取環(huán)境變量

PINECONE_API_KEY = os.environ.get("PINECONE_API_KEY")從環(huán)境變量中讀取 PINECONE_API_KEY 的值,并將其賦給變量 PINECONE_API_KEY。如果該環(huán)境變量不存在,它將返回 None。

(4) 設(shè)置其他Pinecone相關(guān)的變量

PINECONE_ENVIRONMENT="gcp-starter"設(shè)置了一個(gè)字符串變量 PINECONE_ENVIRONMENT,其值為 "gcp-starter"。這通常用于指定 Pinecone 服務(wù)的運(yùn)行環(huán)境。

PINECONE_INDEX="rag-per-user": 設(shè)置 PINECONE_INDEX 變量為 "rag-per-user",這個(gè)值通常用于指定在 Pinecone 中使用的特定索引。

整體上,這段代碼的目的是安全地獲取和存儲(chǔ)與 Pinecone 和 OpenAI 服務(wù)相關(guān)的敏感信息(如 API 密鑰),同時(shí)還設(shè)定了一些與 Pinecone 服務(wù)相關(guān)的配置變量。這樣做可以在代碼的其他部分安全地使用這些密鑰和配置,而不必硬編碼在代碼中,從而增強(qiáng)了安全性和靈活性。

文本嵌入

接下來,使用 Pinecone 作為向量存儲(chǔ)(Vector Store)和 OpenAI 作為嵌入生成器,用于搭建一個(gè)語(yǔ)言處理系統(tǒng)。

import pinecone
from langchain.embeddings.openai import OpenAIEmbeddings
from langchain_community.chat_models import ChatOpenAI
from langchain.vectorstores import Pinecone

pinecone.init(api_key=PINECONE_API_KEY, environment=PINECONE_ENVIRONMENT)
index = pinecone.Index(PINECONE_INDEX)
embeddings = OpenAIEmbeddings()
vectorstore = Pinecone(index, embeddings, "text")
vectorstore.add_texts(["我的工作職責(zé)是為用戶提供產(chǎn)品方面的介紹。"], namespace="product-service")
vectorstore.add_texts(["我的工作職責(zé)是為用戶提供技術(shù)方面的支持。"], namespace="tech-service")
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import (
    ConfigurableField,
    RunnableBinding,
    RunnableLambda,
    RunnablePassthrough,
)
template = """基于如下信息回答問題:
{context}
Question: {question}
"""
prompt = ChatPromptTemplate.from_template(template)
model = ChatOpenAI()
retriever = vectorstore.as_retriever()

代碼解釋如下:

(1) 導(dǎo)入所需模塊和類

import pinecone: 導(dǎo)入 pinecone 模塊,用于與 Pinecone 服務(wù)交互。

from langchain.embeddings.openai import OpenAIEmbeddings: 從 langchain 庫(kù)中導(dǎo)入 OpenAIEmbeddings 類,用于生成文本嵌入(embeddings)。

from langchain_community.chat_models import ChatOpenAI: 導(dǎo)入 ChatOpenAI,這可能是用于處理聊天或問答類型任務(wù)的模型。

from langchain.vectorstores import Pinecone: 導(dǎo)入 Pinecone 類,用于在 Pinecone 服務(wù)上操作向量存儲(chǔ)。

(2) 初始化 Pinecone 服務(wù)并創(chuàng)建索引

pinecone.init(api_key=PINECONE_API_KEY, envirnotallow=PINECONE_ENVIRONMENT): 使用提供的 API 密鑰和環(huán)境變量初始化 Pinecone 服務(wù)。

index = pinecone.Index(PINECONE_INDEX): 創(chuàng)建或訪問一個(gè)名為 PINECONE_INDEX 的 Pinecone 索引。

(3) 設(shè)置嵌入生成器和向量存儲(chǔ)

embeddings = OpenAIEmbeddings(): 實(shí)例化 OpenAIEmbeddings 以生成文本嵌入。

vectorstore = Pinecone(index, embeddings, "text"): 創(chuàng)建一個(gè) Pinecone 實(shí)例,用于存儲(chǔ)和檢索文本嵌入。這里使用了之前創(chuàng)建的 index 和 embeddings。

(4) 向量存儲(chǔ)中添加文本

vectorstore.add_texts(["我的工作職責(zé)是為用戶提供產(chǎn)品方面的介紹。"], namespace="product-service"): 將一段文本添加到向量存儲(chǔ)中,用于表示“產(chǎn)品服務(wù)”相關(guān)的信息。

vectorstore.add_texts(["我的工作職責(zé)是為用戶提供技術(shù)方面的支持。"], namespace="tech-service"): 將另一段文本添加到向量存儲(chǔ)中,用于表示“技術(shù)服務(wù)”相關(guān)的信息。

(5) 設(shè)置輸出解析器、提示模板和模型

導(dǎo)入了多個(gè) langchain_core 中的類和函數(shù),這些可能用于處理和解析語(yǔ)言模型的輸出。

template = "..." 和 prompt = ChatPromptTemplate.from_template(template): 定義一個(gè)聊天提示模板,用于指導(dǎo)語(yǔ)言模型如何回答問題。

model = ChatOpenAI(): 實(shí)例化一個(gè) ChatOpenAI 模型,可能用于處理聊天或問答任務(wù)。

retriever = vectorstore.as_retriever(): 將 vectorstore 轉(zhuǎn)換為一個(gè)檢索器(Retriever),用于從存儲(chǔ)的嵌入中檢索相關(guān)信息。

這段代碼設(shè)置了一個(gè)基于 Pinecone 和 OpenAI 的語(yǔ)言處理系統(tǒng),它能夠存儲(chǔ)和檢索文本信息,并且使用特定的模型和模板處理聊天或問答類型的任務(wù)。

配置索引器與Chain

緊跟著,需要建立一個(gè)處理鏈(chain),使用配置的檢索器(configurable_retriever),提示模板(Prompt),模型(Model),和輸出解析器(StrOutputParser)。這個(gè)Chain 就是用來執(zhí)行按照namespace 進(jìn)行索引的。代碼如下:

(1) 配置檢索器

configurable_retriever = retriever.configurable_fields(...): 這行代碼創(chuàng)建了一個(gè)可配置的檢索器 configurable_retriever。它通過 ConfigurableField 定義一個(gè)可配置的字段 search_kwargs,該字段用于定義檢索器的搜索參數(shù)(例如,如何從向量存儲(chǔ)中檢索數(shù)據(jù))。

(2) 構(gòu)建處理鏈

處理鏈由幾個(gè)部分組成,通過 | 符號(hào)連接,表示數(shù)據(jù)將按順序通過這些組件。

{"context": configurable_retriever, "question": RunnablePassthrough()}: 這是鏈的第一部分,包含兩個(gè)輸入:context 和 question。context 通過 configurable_retriever 獲取,而 question 直接通過 RunnablePassthrough 傳遞,后者意味著問題(question)不進(jìn)行任何處理就傳遞到鏈的下一個(gè)部分。

  • prompt: 然后,輸入數(shù)據(jù)傳遞到 prompt。這個(gè)ChatPromptTemplate 對(duì)象負(fù)責(zé)根據(jù)上下文和問題格式化提示,準(zhǔn)備好交給語(yǔ)言模型處理。
  • model: 接下來,格式化好的提示傳遞給 model,這里的 model 是 ChatOpenAI 實(shí)例,它會(huì)根據(jù)提供的提示生成回答。
  • StrOutputParser(): 最后,模型的輸出傳遞給StrOutputParser,這個(gè)解析器將模型的輸出轉(zhuǎn)換成字符串形式。

整體來看,這個(gè)處理鏈的作用是:根據(jù)檢索到的上下文和未處理的問題生成一個(gè)格式化的提示,然后使用 ChatOpenAI 模型來生成回答,并將這個(gè)回答轉(zhuǎn)換為字符串。這種方式非常適合于問答系統(tǒng),其中上下文信息是根據(jù)需要?jiǎng)討B(tài)檢索的,而問題直接傳遞給模型以生成答案。

測(cè)試結(jié)果

創(chuàng)建好Chain之后,我們來嘗試對(duì)其提出問題,由于我們之前定義了不同namespace對(duì)應(yīng)的工作職責(zé)。這里我們就直接詢問工作職責(zé)的問題,首先測(cè)試product-service 這個(gè)namespace,看看它返回什么答案。

chain.invoke(
    "你的工作職責(zé)是什么?",
    config={"configurable": {"search_kwargs": {"namespace": "product-service"}}},
)

結(jié)果如下

我的工作職責(zé)是為用戶提供產(chǎn)品方面的介紹。

結(jié)果和我們預(yù)期一致,product-service 這個(gè)namespace 確實(shí)是用來處理產(chǎn)品方面的問題的。

接著再測(cè)試tech-service 這個(gè)namespace的回答。

chain.invoke(
    "你的工作職責(zé)是什么?",
    config={"configurable": {"search_kwargs": {"namespace": "tech-service"}}},
)

結(jié)果如下

我的工作職責(zé)是為用戶提供技術(shù)方面的支持。

看來返回結(jié)果也是正確的。

文檔庫(kù)隔離

上面通過在不同的namespace 中加入不同的text文本信息,讓不同用戶通過訪問不同的namespace 來做到“知識(shí)”內(nèi)容的隔離。但是,真實(shí)的應(yīng)用場(chǎng)景是針對(duì)不同的namespace上傳不同的文檔,當(dāng)我們提問的時(shí)候需要制定namespace,來確定由哪個(gè)文檔來回應(yīng)消息。

于是,我們針對(duì)product-service 和tech-service 兩個(gè)不同的namespace 上傳兩個(gè)不同的文檔,分別是product-service.pdf 和 tech-service.pdf。兩個(gè)文檔的內(nèi)容如下:

product-service.pdf 是一個(gè)產(chǎn)品服務(wù)知識(shí)庫(kù),采用問答形式。它提供了關(guān)于客戶服務(wù)的具體指導(dǎo),特別是關(guān)于退貨政策的細(xì)節(jié)。

產(chǎn)品服務(wù)知識(shí)庫(kù)(問答形式) 
問:如果客戶詢問關(guān)于退貨政策的具體細(xì)節(jié),我們應(yīng)該如何回答? 
答:?先,禮貌地感謝客戶對(duì)產(chǎn)品的購(gòu)買。然后, 詳細(xì)解釋我們的退貨政策:客戶可以在購(gòu)買后的30 天內(nèi)?條件退貨,產(chǎn)品必須保持原始狀態(tài)且包裝完整。提醒客戶保留收據(jù),因?yàn)檫@是退貨的必要憑證。 最后,告知客戶退貨流程,并提供相關(guān)表格和聯(lián)系信息。

tech-service.pdf 是一個(gè)技術(shù)服務(wù)知識(shí)庫(kù),同樣采用問答形式。它主要提供了關(guān)于技術(shù)問題解決方案的指導(dǎo),特別是針對(duì)智能鎖失靈的問題。

技術(shù)服務(wù)知識(shí)庫(kù)(問答形式) 
問:客戶如何解決智能鎖頻繁失靈的問題? 
答:?先,指導(dǎo)客戶檢查智能鎖的電源和電池狀態(tài),確認(rèn)電量是否充?。如果電量正常,請(qǐng)引導(dǎo)客戶重置智能鎖,具體?法是?按重置鍵 5 秒鐘。如果問題仍然存在,請(qǐng)建議客戶檢查智能鎖的軟件版本是否最新,并引導(dǎo)進(jìn)?系統(tǒng)更新。若以上步驟?法解決問題,建議客戶聯(lián)系技術(shù)?持以獲取進(jìn)?步的幫助。

有了文檔之后,我們就需要將其上傳并且嵌入到向量庫(kù)Pinecone中, 代碼如下:

from langchain.document_loaders import PyPDFLoader
from google.colab import drive
drive.mount('/content/drive')
file_path = '/content/drive/My Drive/files/product-service.pdf'
loader = PyPDFLoader(file_path)
documents = loader.load_and_split()
vectorstore.add_documents(documents, namespace="product-service")
file_path = '/content/drive/My Drive/files/tech-service.pdf'
loader = PyPDFLoader(file_path)
documents = loader.load_and_split()
vectorstore.add_documents(documents, namespace="tech-service")

由于我使用的是colab 環(huán)境,所以這段代碼是關(guān)于如何在 Google Colab 環(huán)境中加載 PDF 文件并將它們的內(nèi)容添加到一個(gè)向量存儲(chǔ)(vector store)中。下面是對(duì)代碼的詳細(xì)解釋:

(1) **導(dǎo)入所需模塊和類**

  • `from langchain.document_loaders import PyPDFLoader`: 導(dǎo)入 `PyPDFLoader` 類,這個(gè)類用于加載 PDF 文件并將其內(nèi)容轉(zhuǎn)換為可處理的文檔格式。
  •  `from google.colab import drive`: 導(dǎo)入用于在 Google Colab 環(huán)境中掛載 Google Drive 的模塊。

(2) **掛載 Google Drive**

  • `drive.mount('/content/drive')`: 這行代碼將 Google Drive 掛載到 Colab 的文件系統(tǒng)中。這使得在 Colab 中可以直接訪問存儲(chǔ)在 Google Drive 中的文件。

(3) **加載并處理第一個(gè) PDF 文件**

  •  `file_path = '/content/drive/My Drive/files/product-service.pdf'`: 設(shè)置第一個(gè) PDF 文件的路徑。
  •  `loader = PyPDFLoader(file_path)`: 創(chuàng)建 `PyPDFLoader` 實(shí)例并傳入文件路徑,準(zhǔn)備加載文件。
  • `documents = loader.load_and_split()`: 使用 `load_and_split` 方法加載 PDF 文件并將其內(nèi)容分割成單獨(dú)的文檔。這些文檔通常是 PDF 的每一頁(yè)或者每個(gè)段落。

(4) **將文檔添加到向量存儲(chǔ)**

  •  `vectorstore.add_documents(documents, namespace="product-service")`: 將從 PDF 文件中加載的文檔添加到向量存儲(chǔ)中,指定命名空間為 "product-service"。

(5) **重復(fù)以上步驟加載第二個(gè) PDF 文件**

  • 設(shè)置第二個(gè) PDF 文件 `tech-service.pdf` 的路徑。
  • 再次創(chuàng)建 `PyPDFLoader` 實(shí)例,加載第二個(gè)文件。
  • 將從第二個(gè)文件中加載的文檔添加到向量存儲(chǔ)中,這次指定命名空間為 "tech-service"。

整體來看,這段代碼的目的是將兩個(gè) PDF 文件(分別關(guān)于產(chǎn)品服務(wù)和技術(shù)服務(wù)的知識(shí)庫(kù))的內(nèi)容加載到一個(gè)向量存儲(chǔ)系統(tǒng)中,可能用于后續(xù)的搜索或檢索任務(wù)。通過將文件內(nèi)容分割成單獨(dú)的文檔,并使用命名空間區(qū)分不同的文件內(nèi)容,代碼有效地組織了信息,便于后續(xù)處理。

既然PDF文檔已經(jīng)嵌入了,接下來就是重頭戲了。我們義了一個(gè)名為ask_question 的函數(shù),它使用一系列處理步驟(即一個(gè)處理鏈)來根據(jù)給定的問題和命名空間從一個(gè)向量存儲(chǔ)中檢索并回答問題。代碼如下:

from langchain.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough

def ask_question(question, namespace):
  retriever = vectorstore.as_retriever()
  template = """基于如下的上下文內(nèi)容進(jìn)行回答[CONTEXT][/CONTEXT]:
  [CONTEXT]{context}[/CONTEXT]
  如果你不知道答案,你就回答:我不知道。
  Question: {question}
  """
  prompt = ChatPromptTemplate.from_template(template)
  model = ChatOpenAI()
   configurable_retriever = retriever.configurable_fields(
      search_kwargs=ConfigurableField(
          id="search_kwargs",
          name="Search Kwargs",
          description="The search kwargs to use",
      )
  )
  chain = (
      {"context": configurable_retriever, "question": RunnablePassthrough()}
      | prompt
      | model
      | StrOutputParser()
  )
  response = chain.invoke(
      question,
      config={"configurable": {"search_kwargs": {"namespace": namespace}}},
  )
  print(response)

代碼解釋如下:

(1) 導(dǎo)入所需模塊和類

導(dǎo)入 ChatPromptTemplate,StrOutputParser,RunnablePassthrough 等類,這些類用于處理和解析語(yǔ)言模型的輸出。

(2) 定義 ask_question 函數(shù)

def ask_question(question, namespace): 定義一個(gè)函數(shù),接受兩個(gè)參數(shù):question(要問的問題)和 namespace(用于指定搜索的命名空間,可能代表不同類型的知識(shí)庫(kù))。

(3) 設(shè)置檢索器和提示模板

retriever = vectorstore.as_retriever(): 獲取向量存儲(chǔ)的檢索器。

template = """...""": 定義一個(gè)聊天提示模板,該模板指定如何格式化問題和上下文。需要特別注意的是,這里設(shè)計(jì)的prompt template 為“如果你不知道答案,你就回答:我不知道。”這是在告訴大模型,如果不能從知識(shí)庫(kù)中獲取答案,就如實(shí)回答“不知道”,不要試圖去編造答案。

prompt = ChatPromptTemplate.from_template(template): 使用上述模板創(chuàng)建一個(gè) ChatPromptTemplate 實(shí)例。

(4) 配置檢索器

configurable_retriever = retriever.configurable_fields(...): 創(chuàng)建一個(gè)可配置的檢索器,它允許調(diào)整搜索參數(shù)(如命名空間)。

(5) 構(gòu)建處理鏈

chain = (...): 創(chuàng)建一個(gè)處理鏈,它包括以下部分:

將 configurable_retriever 和 RunnablePassthrough 作為輸入,前者用于獲取上下文,后者直接傳遞問題。

使用 prompt 來格式化輸入。

model(這里是 ChatOpenAI 實(shí)例)用于生成回答。

StrOutputParser 將模型的輸出轉(zhuǎn)換為字符串。

(6) 調(diào)用處理鏈并打印響應(yīng)

response = chain.invoke(...): 使用 invoke 方法調(diào)用處理鏈,并傳入問題和配置(包括指定的命名空間)。

print(response): 打印出生成的響應(yīng)。

函數(shù)利用一個(gè)配置好的處理鏈來自動(dòng)回答問題。它從指定命名空間的向量存儲(chǔ)中檢索相關(guān)上下文,然后使用這些上下文和提供的問題生成一個(gè)合適的回答。這對(duì)于基于特定知識(shí)庫(kù)自動(dòng)回答用戶問題的場(chǎng)景非常有用。

最后,我們來看運(yùn)行結(jié)果。

執(zhí)行如下語(yǔ)句

ask_question("退貨政策", "product-service")

傳入提出的問題,以及對(duì)應(yīng)的namespace。由于之前PDF文件中就對(duì)退貨政策進(jìn)行了描述,現(xiàn)在就通過product-service 這個(gè)namespace 搜索與之相關(guān)的內(nèi)容。得到如下結(jié)果:

答:客戶可以在購(gòu)買后的30天內(nèi)無條件退貨,產(chǎn)品必須保持原始狀態(tài)且包裝完整。請(qǐng)?zhí)嵝芽蛻舯A羰論?jù),因?yàn)檫@是退貨的必要憑證。退貨流程和相關(guān)表格以及聯(lián)系信息可以提供給客戶。

從結(jié)果上看與PDF文檔中的內(nèi)容保持一致。

接著,我們?cè)偬釂枴爸悄苕i失靈”的問題,這里我們不向“tech-service”提問,而向“product-service”提問。顯然,product-service的namespace 存放的文檔是關(guān)于產(chǎn)品服務(wù)相關(guān)的,并不知道“智能鎖失靈”這樣的技術(shù)支持問題。所以,先執(zhí)行代碼再看結(jié)果,代碼如下:

我不知道。

很顯然結(jié)果是“我不知道”,通過上面prompt template 的定義,我們讓大模型在沒有搜索到文檔內(nèi)容的時(shí)候,不要編造任何信息,而是如實(shí)回答:“我不知道”。這也證明了在product-service的namespace中不存在與技術(shù)支持相關(guān)的信息。

最后,我們通過如下代碼詢問 tech-service,

ask_question("智能鎖失靈", "tech-service")

看結(jié)果如下

回答:首先,指導(dǎo)客戶檢查智能鎖的電源和電池狀態(tài),確認(rèn)電量是否充足。如果電量正常,請(qǐng)引導(dǎo)客戶重置智能鎖,具體方法是長(zhǎng)按重置鍵5秒鐘。如果問題仍然存在,請(qǐng)建議客戶檢查智能鎖的軟件版本是否最新,并引導(dǎo)進(jìn)行系統(tǒng)更新。若以上步驟無法解決問題,建議客戶聯(lián)系技術(shù)支持以獲取進(jìn)一步的幫助。

從結(jié)果上看,與我們的設(shè)想相同,和技術(shù)支持相關(guān)的問題從tech-service 的namespace中獲取。

總結(jié)

文章提供了一種有效的方法可以在LangChain框架下實(shí)現(xiàn)多用戶數(shù)據(jù)檢索,確保了數(shù)據(jù)安全性和隱私保護(hù)的同時(shí),也保證了檢索系統(tǒng)的靈活性和用戶體驗(yàn)。通過使用Pinecone作為向量數(shù)據(jù)庫(kù),它克服了傳統(tǒng)標(biāo)量數(shù)據(jù)庫(kù)在處理高維向量數(shù)據(jù)時(shí)遇到的難題。文章詳細(xì)介紹了多用戶檢索的實(shí)現(xiàn)步驟,從檢索器的配置到鏈條的構(gòu)建,再到實(shí)際的代碼演示,全面覆蓋了從理論到實(shí)踐的各個(gè)方面。通過提供具體的示例和代碼,文檔使讀者能夠更容易地理解和應(yīng)用這些概念到實(shí)際的多用戶檢索任務(wù)中。

作者介紹

崔皓,51CTO社區(qū)編輯,資深架構(gòu)師,擁有18年的軟件開發(fā)和架構(gòu)經(jīng)驗(yàn),10年分布式架構(gòu)經(jīng)驗(yàn)。

責(zé)任編輯:華軒 來源: 51CTO
相關(guān)推薦

2021-08-16 09:36:06

數(shù)據(jù)泄露T-Mobile信息安全

2015-01-05 09:56:41

UDPLinux TCP

2021-05-25 13:54:01

數(shù)字化

2021-01-20 23:40:27

數(shù)據(jù)泄露OpenWRT攻擊

2011-03-25 15:21:43

2016-01-22 12:20:11

PHP數(shù)據(jù)爬取分析

2009-11-25 11:28:00

并發(fā)用戶數(shù)

2022-12-01 12:14:09

2021-01-06 10:01:09

數(shù)據(jù)泄露漏洞信息安全

2021-05-11 11:05:58

蘋果iOS隱私

2023-10-23 19:18:05

2015-10-19 18:18:44

2012-05-24 10:08:51

ibmdw

2023-09-08 09:53:41

API開發(fā)

2012-06-13 13:52:48

LinuxVNC

2015-10-29 13:22:09

php數(shù)據(jù)分析爬蟲

2016-03-16 10:56:12

數(shù)據(jù)營(yíng)銷數(shù)據(jù)分析LinkedIn

2015-10-30 17:58:43

用戶數(shù)據(jù)收集信息安全WhatsApp

2019-08-14 16:08:43

大數(shù)據(jù)安全互聯(lián)網(wǎng)

2021-04-02 11:09:35

MobiKwik 移動(dòng)支付數(shù)據(jù)泄露
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)