檢索增強生成RAG系列6--RAG提升之查詢結構化(Query Construction)

系列5中講到會講解3個方面RAG的提升,它們可能與RAG的準確率有關系,但是更多的它們是有其它用途。本期來講解第二部分:查詢結構化(Query Construction)。在系列3文檔處理中,我們著重講解了文檔解析,但是我們說的文檔都是大部分是非結構化的文檔或者說它就是以一個文檔的形式存儲。而現實中我們很多有價值的數據可能以結構化(關系型數據庫、圖形數據庫等)或者半結構(關系型數據庫、文檔數據庫等)的形式存儲中,并且這些數據一般都是存儲于特定數據庫,那么如果數據存儲在結構化或者半結構化中,我們RAG又該如何與之配合。這一章就著重來講講結構化查詢(Query Construction)

目錄

  • 1 查詢結構化(Query Construction)
  • 2 Text-to-metadata-filter
  • 3 Text-to-SQL
  • 4 Text-to-Cypher
  • 5 Text-to-SQL+ Semantic

1 查詢結構化(Query Construction)

現實中我們很多有價值的數據可能以結構化(關系型數據庫、圖形數據庫等)或者半結構(關系型數據庫、文檔數據庫等)的形式存儲中,并且這些數據一般都是存儲于特定數據庫,同時數據庫提供結構化的查詢功能,使用其結構化查詢(比如SQL等)比使用向量化查詢更為準確。那這時候如果我們RAG想要去查詢這些數據,就不是將數據向量化后再去查詢,而是利用大模型將用戶問題轉換為結構化查詢,再通過結構化查詢去數據庫查詢結果,最后利用結果回答用戶問題。下圖流程可以讓你明顯感受不同之處:

在這里插入圖片描述

我們將不同結構化或者半結構化查詢歸納如下表,下面也是逐一講解各個方法

方法數據源
Text-to-metadata-filter向量數據庫
Text-to-SQL關系型數據庫
Text-to-Cypher圖形數據庫
Text-to-SQL+ Semantic關系型+向量混合數據庫

2 Text-to-metadata-filter

第一個要利用大模型將用戶問題轉換為結構化查詢的依舊是向量數據庫,但是這里并非做向量查詢,而是很多向量存儲其實都配備了元數據過濾功能,這些元數據其實就是結構化存儲,因此需要過濾的是存儲在向量數據庫的元數據

這里以查詢ChromaDB的metadata為例,做一個demo代碼演示。在運行代碼之前我們需要做以下前置條件

  • 這里采用智譜AI的API接口,因此可以先去申請一個API KEY(當然你使用其它模型也可以,目前智譜AI的GLM4送token,就拿它來試驗吧)
  • 下載m3e-base的embedding模型
  • 給一個文檔目錄,里面放入一個文檔即可,文檔內容不限
import os
from typing import List
from langchain_openai import ChatOpenAI
from langchain_core.documents import Document
from langchain_community.vectorstores import Chroma
from langchain_core.prompts import ChatPromptTemplate
from langchain_huggingface import HuggingFaceEmbeddings
from langchain_core.pydantic_v1 import BaseModel, Field
from langchain_core.runnables import RunnablePassthrough
from langchain_community.document_loaders import DirectoryLoader# 前置工作1:文檔存儲,給文檔設置author屬性
encode_kwargs = {"normalize_embeddings": False}
model_kwargs = {"device": "cuda:0"}
embeddings = HuggingFaceEmbeddings(model_name='/root/autodl-tmp/model/AI-ModelScope/m3e-base',  # 換成自己的embedding模型路徑model_kwargs=model_kwargs,encode_kwargs=encode_kwargs
)
if os.path.exists('VectorStore'):db = Chroma(persist_directory='VectorStore', embedding_function=embeddings)
loader = DirectoryLoader("/root/autodl-tmp/doc")  # 換成自己的文檔路徑
documents = loader.load()
# 這里假設設置一個author作者的屬性
documents[0].metadata["author"] = "劉震云"
database = Chroma.from_documents(documents, embeddings, persist_directory="VectorStore")
database.persist()# 前置工作2:創建llm
llm = ChatOpenAI(temperature=0.95,model="glm-4",openai_api_key="你的API KEY",openai_api_base="https://open.bigmodel.cn/api/paas/v4/"
)# 前置工作3:為了將用戶問題轉換為結構化查詢,使用LangChain可以通過Pydantic類輕松指定所需的function call schema:
# 這里假設書籍有2個字段匹配,一個是內容content_search,一個是作者author_search
class BookSearch(BaseModel):content_search: str = Field(...,description=("書籍文本內容進行相似性搜索"),)author_search: str = Field(...,description=("書籍作者,僅在使用人名查詢時,才進行關鍵字匹配,其它情況不使用"),)# 第一步:讓模型將用戶問題轉換成與查詢字段匹配的格式
system = """你是將用戶問題轉換為數據庫查詢的專家。
你可以訪問關于的書籍數據庫。
給定一個問題,返回一個優化為檢索最相關結果的數據庫查詢。"""
prompt = ChatPromptTemplate.from_messages([("system", system),("human", "{question}"),]
)# 綁定前面定義的輸出數據格式,意思就是要求模型根據類結構返回數據。
structured_llm = llm.with_structured_output(BookSearch)
# 定義chain
query_analyzer = {"question": RunnablePassthrough()} | prompt | structured_llm
print(query_analyzer.invoke("作家劉震云的書"))# 第二步:轉換匹配,拼接向量查詢條件查詢Chroma
def retrieval(search: BookSearch) -> List[Document]:if search.author_search is not None:_filter = {"author": {"$eq": search.author_search}}else:_filter = Nonereturn database.similarity_search(search.content_search, filter=_filter)retrieval_chain = query_analyzer | retrieval
# 未查詢到結果
print(retrieval_chain.invoke("作家莫言的書"))
# 查詢到結果
print(retrieval_chain.invoke("作家劉震云的書"))

3 Text-to-SQL

關于關系型數據庫就不用在累贅了,但是使用大模型生成SQL可能會出現以下問題:

  • 幻覺:大模型容易對虛構的表或字段產生“幻覺”,從而產生無效的查詢。方法必須將這些大模型 建立在現實中,確保它們生成與實際數據庫模式一致的有效 SQL。
  • 用戶錯誤:文本轉 SQL 方法應能夠防止用戶拼寫錯誤或用戶輸入中可能導致無效查詢的其他不規范情況。

對于以上問題,有不少的解決方案供參考:

  • 數據庫描述:要生成SQL查詢,必須向大模型提供數據庫的準確描述。常見的做法:為大模型提供每張表的CREATE TABLE描述,包括列名、類型等,然后再給出幾個SELECT語句的示例。
  • Few-shot樣例:在prompt中添加question-query的幾個樣例可以提高query生成的準確性。在prompt中簡單的添加標準的靜態示例指導大模型如何基于question創建query。
  • 錯誤處理:當遇到錯誤時,利用工具(例如SQL Agent)修復錯誤。
  • 查找專有名詞中的拼寫錯誤:當查詢名稱等專有名詞時,用戶可能會不小心寫錯。我們允許大模型Agent根據向量庫搜索正確的名稱,向量庫在SQL數據庫中存儲相關專有名詞的正確拼寫。

下面以查詢sqlite數據庫為例子,,做一個demo代碼演示。在運行代碼之前我們需要做以下前置條件

  • 這里采用智譜AI的API接口,因此可以先去申請一個API KEY(當然你使用其它模型也可以,目前智譜AI的GLM4送token,就拿它來試驗吧)
  • 準備一個本地sqlite數據庫,并創建數據庫test.db,以及表和存入數據,腳本如下

sqllite3 test.db
create table student(id Integer,name char,score Integer);
insert into student values(1,“student1”,100);
insert into student values(2,“student2”,80);
insert into student values(3,“student3”,50);

代碼如下:


from langchain_openai import ChatOpenAI
from langchain_core.prompts import PromptTemplate
from langchain.chains import create_sql_query_chain
from langchain_community.utilities import SQLDatabase# 前置工作1:創建llm
llm = ChatOpenAI(temperature=0.01,model="glm-4",openai_api_key="你的API KEY",openai_api_base="https://open.bigmodel.cn/api/paas/v4/"
)# 前置工作2:改寫了一下prompt(因為默認的prompt似乎不適合智譜AI)
_sqlite_prompt = """你是一個SQLite專家。給定一個輸入問題,首先創建一個語法正確的SQLite查詢來運行,然后查看查詢的結果并返回輸入問題的答案。
除非用戶在問題中指定要獲取的特定數量的示例,否則根據SQLite使用LIMIT子句查詢最多{top_k}個結果。您可以對結果進行排序,以返回數據庫中信息量最大的數據。
永遠不要查詢表中的所有列。您必須只查詢回答問題所需的列。將每個列名用雙引號(")括起來,以表示它們為分隔符。
注意,只使用您可以在下面的表中看到的列名。注意不要查詢不存在的列。另外,要注意哪個列在哪個表中。
如果問題涉及“今天”,注意使用date('now')函數來獲取當前日期
使用以下格式:問題:問題
SQLQuery:要運行的SQL查詢
答案:最終答案只使用以下表格:
{table_info}問題: {input}
"""SQLITE_PROMPT = PromptTemplate(input_variables=["input", "table_info", "top_k"],template=_sqlite_prompt,
)db = SQLDatabase.from_uri("sqlite:///sqlite-autoconf-3460000/test.db")  # 你的數據庫地址
# 使用create_sql_query_chain的方式,langchain還有agent方式,大家可以去探索使用
chain = create_sql_query_chain(llm, db, SQLITE_PROMPT)
response = chain.invoke({"question": "總共有多少學生"})
print(response)

4 Text-to-Cypher

對于圖形數據庫的作用,一般就是表示實體之間的關系,適合于知識圖譜、人際關系等應用場景。
下面以查詢neo4j圖數據庫為例子,,做一個demo代碼演示。在運行代碼之前我們需要做以下前置條件

  • 這里采用智譜AI的API接口,因此可以先去申請一個API KEY(當然你使用其它模型也可以,目前智譜AI的GLM4送token,就拿它來試驗吧)
  • 準備一個本地neo4j數據庫,并創建數據庫test_relationship,錄入一些作家、書籍以及相關關系
from langchain.chains import GraphCypherQAChain
from langchain_community.graphs import Neo4jGraph
from langchain_openai import ChatOpenAI# 前置工作1:創建llm
llm = ChatOpenAI(temperature=0.95,model="glm-4",openai_api_key="你的API KEY",openai_api_base="https://open.bigmodel.cn/api/paas/v4/"
)# 前置工作2:準備好圖形數據庫
graph = Neo4jGraph(url="bolt://localhost:7687", username="test_relationship", password="***"
)
graph.refresh_schema()# 使用langchain的GraphCypherQAChain進行封裝,這里面的提示效果對于智譜AI來說一般般,沒調試出來最終結果
chain = GraphCypherQAChain.from_llm(llm, graph=graph, verbose=True)print(chain.run("誰是一地雞毛的作者?"))

5 Text-to-SQL+ Semantic

現在混合類型(結構化和非結構化)數據存儲越來越普遍。向關系數據庫添加向量支持是支持混合檢索方法的關鍵推動因素。比如PostgreSQL 的開源 pgvector 擴展將 SQL 的表現力與語義搜索提供的對語義的細致入微的理解相結合。那么在如何將用戶問題轉換為這種混合類型數據庫就提出了更高的挑戰。
在對這種類型數據庫,更加復雜的query生成,需要創建few-shot prompt或者增加query-checking等環節來提升準確度,這里就不舉例子,有興趣深入的同學可以搜索研究。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/39739.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/39739.shtml
英文地址,請注明出處:http://en.pswp.cn/web/39739.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

C++ dll導出類的方法

要在C動態庫中導出類,可以使用以下步驟: 定義一個類并實現其成員函數。在類的聲明前加上__declspec(dllexport)標記(Windows平臺)或__attribute__((visibility("default")))標記(Linux平臺)&…

C語言學習筆記--第一個程序

第一個C語言程序 #include<stdio.h> //引用輸入輸出頭文件&#xff0c;每一次都需要引用這個文件 //.h是頭文件 // .c是源文件 // .cpp是C源文件&#xff0c;兼容C //C的第一個程序 // 行注釋&#xff08;只能注釋這一行&#xff09; /*塊注釋 */ int main() {printf(&…

能保存到相冊的風景視頻在哪下載?下載風景視頻網站分享

在當今以視覺為核心的時代&#xff0c;高清美麗的風景視頻不僅能夠豐富我們的日常生活&#xff0c;還能提供心靈上的慰藉。無論是為了制作視頻項目&#xff0c;還是僅僅想要珍藏一些精美的風景畫面&#xff0c;獲取高質量的風景視頻素材顯得尤為重要。許多人可能會問&#xff1…

PTrade量化軟件常見問題整理系列2

一、研究界面使用get_fundamentals函數報錯&#xff1a;error_info:獲取token失敗&#xff1f; 研究界面使用get_fundamentals函數報錯&#xff1a;error_info:獲取token失敗&#xff1f; 1、測試版本202202.01.052&#xff0c;升級202202.01.051版本后&#xff0c;為了解決不…

在虛擬仿真中學習人工智能,可以達到什么目標?

人工智能已經成為引領社會創新的關鍵力量&#xff0c;想要在這個充滿機遇的領域中脫穎而出&#xff0c;掌握扎實的專業技能和積累豐富的實踐經驗至關重要。然而&#xff0c;許多學習者在追求這一目標的過程中面臨著幾個主要問題&#xff1a;專業技術掌握有難度、實踐經驗積累存…

linux中awk,sed, grep使用

《linux私房菜》這本書中將sed和awk一同歸為行的修改這一點&#xff0c;雖然對&#xff0c;但不利于實際處理問題時的思考。因為這樣的話&#xff0c;當我們實際處理問題時&#xff0c;遇到比如說統計文本打印內容時&#xff0c;我們選擇sed還是awk進行處理呢&#xff1f; 也因…

?香橙派AIpro測評:usb魚眼攝像頭的Camera圖像獲取

一、前言 近期收到了一塊受到業界人士關注的開發板"香橙派AIpro",因為這塊板子具有極高的性價比&#xff0c;同時還可以兼容ubuntu、安卓等多種操作系統&#xff0c;今天博主便要在一塊832g的香橙派AI香橙派AIpro進行YoloV5s算法的部署并使用一個外接的魚眼USB攝像頭…

React 中如何使用 Monaco

Monaco 是微軟開源的一個編輯器&#xff0c;VSCode 也是基于 Monaco 進行開發的。如果在 React 中如何使用 Monaco&#xff0c;本文將介紹如何在 React 中引入 Monaco。 安裝 React 依賴 yarn add react-app-rewired --dev yarn add monaco-editor-webpack-plugin --dev yarn…

學習和發展人工智能:新興趨勢和成功秘訣

人工智能(AI)繼續吸引組織&#xff0c;因為它似乎無窮無盡地提高生產力和業務成果。在本博客中&#xff0c;了解學習和發展(L&D)部門如何利用人工智能改進流程&#xff0c;簡化工作流程&#xff1f; 學習與發展(L&D)部門領導開始探索如何提高和支持人工智能能力的勞動…

1-認識網絡爬蟲

1.什么是網絡爬蟲 ? 網絡爬蟲&#xff08;Web Crawler&#xff09;又稱網絡蜘蛛、網絡機器人&#xff0c;它是一種按照一定規則&#xff0c;自動瀏覽萬維網的程序或腳本。通俗地講&#xff0c;網絡爬蟲就是一個模擬真人瀏覽萬維網行為的程序&#xff0c;這個程序可以代替真人…

工業智能網關在現代工業生產中的重要性-天拓四方

工業智能網關是一款具備挖掘工業設備數據并接入到自主開發的云平臺的智能嵌入式網絡設備。它具備數據采集、協議解析、邊緣計算&#xff0c;以及4G/5G/WiFi數據傳輸等功能&#xff0c;并能接入工業云平臺。這種網關不僅支持采集PLC、傳感器、儀器儀表和各種控制器&#xff0c;還…

iss文件本機可以訪問,其他電腦無法訪問解決

1.搜索的時候有很多答案&#xff0c;總結就是2種 引用來自這位大佬的博客跳轉 2.我實際解決了的方法 將這里的ip地址修改為你局域網wifi的ip 如何看自己wifi的ip&#xff0c;大家自行百度&#xff01;

linux中與網絡有關的命令

本文的命令總覽 ifconfig命令 在 Linux 系統中&#xff0c;ifconfig 命令用于配置和顯示網絡接口的信息&#xff0c;包括 IP 地址、MAC 地址、網絡狀態等。同時我們也可以利用ifconfig 命令設置網絡接口對應的ip地址&#xff0c;子網掩碼等 當你使用 ifconfig 命令時&#xf…

06-6.3.3 圖的深度優先遍歷

&#x1f44b; Hi, I’m Beast Cheng &#x1f440; I’m interested in photography, hiking, landscape… &#x1f331; I’m currently learning python, javascript, kotlin… &#x1f4eb; How to reach me --> 458290771qq.com 喜歡《數據結構》部分筆記的小伙伴可以…

UE5.4新功能 - Texture Graph上手簡介

TextureGraph是UE5.4還在實驗(Experimental)階段的新功能&#xff0c;該功能旨在材質生成方面達到類似Subtance Designer的效果&#xff0c;從而程序化的生成一些紋理。 本文就來簡要學習一下。 1.使用UE5.4或以上版本&#xff0c;激活TextureGraph插件 2.內容視圖中右鍵找到…

萬字 | 菊花廠C語言編程10大規范

本文是大廠C代碼規范&#xff0c;有點長&#xff0c;有時間可以學習下。 1 代碼總體原則 1、清晰第一 清晰性是易于維護、易于重構的程序必需具備的特征。代碼首先是給人讀的&#xff0c;好的代碼應當可以像文章一樣發聲朗誦出來。 目前軟件維護期成本占整個生命周期成本的…

【INTEL(ALTERA)】為什么Nios? II構建流程報告無法在 Windows WSL 上確定程序大小?

目錄 說明 解決方法 說明 由于英特爾 Quartus Prime 專業版軟件 19.3 版中的 nios2-elf-stackreport 實用程序出現問題&#xff0c;nios2-elf-stackreport 實用程序確實如此 不報告程序大小或堆棧堆棧大小。 解決方法 要解決此問題&#xff0c;編輯 nios2-stackreport.pl …

1)并發事務的問題

1) 并發事務的問題&#xff1f; &#xff08;1&#xff09;讀“臟”數據 事務T1修改數據后T2讀取了該數據&#xff0c;但是T1撤消了修改&#xff0c; 事務T1進行了回滾&#xff0c;導致事務T2讀取的數據與數據庫中的數據不一致。&#xff08;2&#xff09;丟失修改 兩個事務…

面向對象(Java)

構造方法只能在對象實例化的時候調用 this可以作為方法參數&#xff0c;表示調用方法的當前對象 this可以作為方法返回值&#xff0c;表示返回當前對象 封裝 通過方法訪問數據&#xff0c;隱藏類的實現細節 static&#xff1a;類對象共享&#xff0c;類加載時產生&#xff0c;…

Qt 實戰(7)元對象系統 | 7.2、MOC(Meta-Object Compiler 元對象編譯器)

文章目錄 一、MOC1、MOC的作用2、MOC的工作原理3、MOC的使用方式4、MOC生成的文件結構 前言&#xff1a; 在Qt框架中&#xff0c;MOC&#xff08;Meta-Object Compiler&#xff09;是一個至關重要的工具&#xff0c;它負責處理Qt特有的元對象系統&#xff08;Meta-Object Syste…