成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

基于Agent的金融問答系統(tǒng):RAG的檢索增強(qiáng)之上下文重排和壓縮 原創(chuàng)

發(fā)布于 2024-11-26 08:58
瀏覽
0收藏

前言

在上一章??【項(xiàng)目實(shí)戰(zhàn)】基于Agent的金融問答系統(tǒng):RAG的檢索增強(qiáng)之ElasticSearch??中,我們在已經(jīng)構(gòu)建的Agent框架上,通過集成檢索器將ES檢索器和多路召回檢索器集成進(jìn)來,提升了檢索的召回率。本章,我們將基于項(xiàng)目問題,進(jìn)一步優(yōu)化Agent的檢索能力。

問題

隨著該項(xiàng)目檢索能力的增強(qiáng),我們計(jì)劃對天池大賽提供的1000個(gè)問題進(jìn)行執(zhí)行,依次評估我們的系統(tǒng)能力如何。 在這個(gè)測試過程中,我們發(fā)現(xiàn)了多個(gè)待優(yōu)化的問題,其中有2個(gè)問題的解決值得分享,在此作為記錄以供讀者參考。

問題1:執(zhí)行過程中,偶爾會(huì)出現(xiàn)RAG檢索結(jié)果內(nèi)容過長,超出大模型能夠接收的范圍(如下圖中顯示的status_code=400),導(dǎo)致執(zhí)行中斷

基于Agent的金融問答系統(tǒng):RAG的檢索增強(qiáng)之上下文重排和壓縮-AI.x社區(qū)

基于Agent的金融問答系統(tǒng):RAG的檢索增強(qiáng)之上下文重排和壓縮-AI.x社區(qū)

問題2:Agent遇到計(jì)算漲幅、收益率等問題時(shí),會(huì)反復(fù)構(gòu)造SQL語句,試圖從數(shù)據(jù)庫中直接查詢出對應(yīng)的數(shù)據(jù),從而導(dǎo)致思考迭代此處超過限制,程序異常

基于Agent的金融問答系統(tǒng):RAG的檢索增強(qiáng)之上下文重排和壓縮-AI.x社區(qū)

優(yōu)化方案

分析上述問題后,我們計(jì)劃對整體程序進(jìn)行優(yōu)化,優(yōu)化方案如下:

基于Agent的金融問答系統(tǒng):RAG的檢索增強(qiáng)之上下文重排和壓縮-AI.x社區(qū)

說明:

  • 針對問題1,我們計(jì)劃給集成檢索器增加上下文重排和壓縮,以解決長文本問題。
  • 針對問題2,我們計(jì)劃為Agent掛載更多的工具,進(jìn)而讓Agent使用工具計(jì)算漲幅、收益率等。

優(yōu)化步驟

1、檢索器增加上下文壓縮

優(yōu)化代碼文件:??app/rag/retrievers.py??

from langchain_core.callbacks importCallbackManagerForRetrieverRun
from utils.logger_config importLoggerManager
from langchain_core.retrievers importBaseRetriever
from langchain_core.documents importDocument
from langchain.retrievers importEnsembleRetriever
from langchain.retrievers.multi_query importMultiQueryRetriever
from langchain.retrievers.contextual_compression importContextualCompressionRetriever
from langchain.retrievers.document_compressors importLLMChainExtractor
from rag.elasticsearch_db importElasticsearchDB
# ES需要導(dǎo)入的庫
from typing importList
import logging
import settings
from langchain_community.document_transformers import(
LongContextReorder,
)
from utils.util import get_rerank_model

logger =LoggerManager().logger


classSimpleRetrieverWrapper():
"""自定義檢索器實(shí)現(xiàn)"""

def__init__(self, store, llm, **kwargs):
        self.store = store
        self.llm = llm
        logger.info(f'檢索器所使用的Chat模型:{self.llm}')

defcreate_retriever(self):
        logger.info(f'初始化自定義的Retriever')

# 初始化一個(gè)空的檢索器列表
        retrievers =[]
        weights =[]

# Step1:創(chuàng)建一個(gè) 多路召回檢索器 MultiQueryRetriever
        chromadb_retriever = self.store.as_retriever()
        mq_retriever =MultiQueryRetrieverWrapper.from_llm(retriever=chromadb_retriever, llm=self.llm)

# Step2:創(chuàng)建一個(gè) 上下文壓縮檢索器ContextualCompressionRetriever
if settings.COMPRESSOR_ENABLE isTrue:
            compressor =LLMChainExtractor.from_llm(llm=self.llm)
            compression_retriever =ContextualCompressionRetrieverWrapper(
                base_compressor=compressor, base_retriever=mq_retriever
)
# 開啟開關(guān)就使用壓縮檢索器
            retrievers.append(compression_retriever)
            weights.append(0.5)
            logger.info(f'已啟用 ContextualCompressionRetriever')
else:
# 關(guān)閉開關(guān)就使用多路召回檢索器
            retrievers.append(mq_retriever)
            weights.append(0.5)
            logger.info(f'已啟用 MultiQueryRetriever')

# Step3:創(chuàng)建一個(gè) ES 檢索器
if settings.ELASTIC_ENABLE_ES isTrue:
            es_retriever =ElasticsearchRetriever()
            retrievers.append(es_retriever)
            weights.append(0.5)
            logger.info(f'已啟用 ElasticsearchRetriever')

# 使用集成檢索器,將所有啟用的檢索器集合在一起
        ensemble_retriever =EnsembleRetriever(retrievers=retrievers, weights=weights)
return ensemble_retriever

說明:

  • 首先,我們創(chuàng)建一個(gè)空的檢索器列表,用于存儲(chǔ)啟用的檢索器。
  • 其次,創(chuàng)建一個(gè) ??MultiQueryRetrieverWrapper?? ,用于將ES檢索器與多路召回檢索器集成。
  • 然后,通過 ??ContextualCompressionRetrieverWrapper?? ,為多路檢索器添加上下文壓縮功能。
  • 最后,將檢索器列表與權(quán)重列表傳入集成檢索器,完成集成。

此處,MultiQueryRetrieverWrapper 和 ContextualCompressionRetrieverWrapper 分別是基于 ??MultiQueryRetriever??? 和 ??ContextualCompressionRetriever?? 進(jìn)一步封裝實(shí)現(xiàn)的,在3、中會(huì)詳細(xì)介紹。

2、檢索器增加上下文重排

對之前實(shí)現(xiàn)的ElasticsearchRetriever增加上下文重排功能,具體代碼如下:

優(yōu)化代碼文件:??app/rag/retrievers.py??

class ElasticsearchRetriever(BaseRetriever):
def_get_relevant_documents(self, query: str, )->List[Document]:
"""Return the first k documents from the list of documents"""
        es_connector =ElasticsearchDB()
        query_result = es_connector.search(query)

# 增加長上下文重排序
        reordering =LongContextReorder()
        reordered_docs = reordering.transform_documents(query_result)
# logger.info(f"ElasticSearch檢索到的原始文檔:")
# for poriginal in query_result:
#     logger.info(f"{poriginal}")

        logger.info(f"ElasticSearch檢索重排后的文檔:")
for preordered in reordered_docs:
            logger.info(f"{preordered}")

        logger.info(f"ElasticSearch檢索到資料文件個(gè)數(shù):{len(query_result)}")

if reordered_docs:
return[Document(page_cnotallow=doc)for doc in reordered_docs]
return []

3、優(yōu)化日志輸出

由于 ??MultiQueryRetriever?? 是langchain已經(jīng)封裝好的檢索器,如果我們需要在其基礎(chǔ)上增加一些功能,比如:增加日志,我們需要對其進(jìn)行重寫,具體方法:

重寫MultiQueryRetriever

創(chuàng)建一個(gè)新的Class ??MultiQueryRetrieverWrapper???,繼承 ??MultiQueryRetriever??? ,重寫 ??_get_relevant_documents?? 方法,具體代碼如下:

class MultiQueryRetrieverWrapper(MultiQueryRetriever):
def_get_relevant_documents(
        self,
        query: str,
        *,
        run_manager: CallbackManagerForRetrieverRun,
    )->List[Document]:
"""
        對MultiQueryRetriever進(jìn)行重寫,增加日志打印
        """
        queries = self.generate_queries(query, run_manager)
if self.include_original:
            queries.append(query)
        documents = self.retrieve_documents(queries, run_manager)

# 增加長上下文重排序
        reordering =LongContextReorder()
        reordered_docs = reordering.transform_documents(documents)

        logger.info(f'MultiQuery生成的檢索語句:')
for q in queries:
            logger.info(f"{q}")
        logger.info(f'MultiQuery檢索到的資料文件:')
for doc in documents:
            logger.info(f"{doc}")
        logger.info(f"MultiQuery檢索到資料文件個(gè)數(shù):{len(documents)}")

return self.unique_union(reordered_docs)

重寫ContextualCompressionRetriever

創(chuàng)建一個(gè)新的Class ??ContextualCompressionRetrieverWrapper???,繼承 ??ContextualCompressionRetriever??? ,重寫 ??_get_relevant_documents?? 方法,具體代碼如下:

class ContextualCompressionRetrieverWrapper(ContextualCompressionRetriever):
from typing importAny,List
def_get_relevant_documents(
        self,
        query: str,
        *,
        run_manager: CallbackManagerForRetrieverRun,
        **kwargs: Any,
    )->List[Document]:
"""
        對ContextualCompressionRetriever進(jìn)行重寫,增加日志打印
        """

        docs = self.base_retriever.invoke(
            query, cnotallow={"callbacks": run_manager.get_child()},**kwargs
)
if docs:
            compressed_docs = self.base_compressor.compress_documents(
                docs, query, callbacks=run_manager.get_child()
)
            logger.info(f'壓縮后的文檔長度:{len(compressed_docs)}')
            logger.info(f'壓縮后的文檔:{compressed_docs}')
returnlist(compressed_docs)
else:
return []

4、給Agent增加更多工具

實(shí)現(xiàn)工具函數(shù):計(jì)算股票年化收益率

代碼文件:??app/finance_bot_ex.py??

# 定義股票年化收益率計(jì)算函數(shù)
# 年化收益率定義為:((有記錄的一年的最終收盤價(jià)-有記錄的一年的年初當(dāng)天開盤價(jià))/有記錄的一年的當(dāng)天開盤價(jià))* 100%。
def calculate_stock_annualized_return(final_closing_price: float, initial_opening_price: float) -> float:
    """
    計(jì)算股票年化收益率
    """
    annualized_return = ((final_closing_price - initial_opening_price) / initial_opening_price) * 100
    return annualized_return

Agent增加工具

在??init_agent??函數(shù)中,增加工具函數(shù),具體代碼如下:

代碼優(yōu)化文件:??app/finance_bot_ex.py??

definit_agent(self):
# 初始化 RAG 工具
        retriever_tool = self.init_rag_tools()

# 初始化 SQL 工具
        sql_tools = self.init_sql_tool(settings.SQLDATABASE_URI)

# 創(chuàng)建系統(tǒng)Prompt提示語
        system_prompt = self.create_sys_prompt()

# 創(chuàng)建Agent
        agent_executor = create_react_agent(
            self.chat,
            tools=[
                get_datetime,
                calculate_stock_annualized_return,# 增加自定義的計(jì)算年化收益率工具
                retriever_tool]+ sql_tools,
            state_modifier=system_prompt,
            checkpointer=MemorySaver()
# state_modifier=modify_state_messages,
)
return agent_executor

4、驗(yàn)證測試

完成上述檢索器的優(yōu)化之后,我們使用test_framework.py進(jìn)行驗(yàn)證,驗(yàn)證結(jié)果如下:

問題1解決效果

1. 用戶輸入問題,觸發(fā)RAG檢索的 MultiQueryRetriever 檢索器

基于Agent的金融問答系統(tǒng):RAG的檢索增強(qiáng)之上下文重排和壓縮-AI.x社區(qū)

2. 通過上下文壓縮之后,原本 MultiQueryRetriever 檢索到的資料文件數(shù)量由12個(gè)減少到1個(gè)。

基于Agent的金融問答系統(tǒng):RAG的檢索增強(qiáng)之上下文重排和壓縮-AI.x社區(qū)

3. 通過上下文壓縮之后,原本 ElasticsearchRetriever 檢索到的資料文件數(shù)量由3個(gè)減少到2個(gè)。

基于Agent的金融問答系統(tǒng):RAG的檢索增強(qiáng)之上下文重排和壓縮-AI.x社區(qū)

4. 最后,將兩個(gè)檢索器的結(jié)果進(jìn)行整合后,大模型給出最終答案。

基于Agent的金融問答系統(tǒng):RAG的檢索增強(qiáng)之上下文重排和壓縮-AI.x社區(qū)

問題2解決效果

1. 我們輸入問題:計(jì)算代碼000798股票在2020年的年化收益率,保留兩位小數(shù)。

基于Agent的金融問答系統(tǒng):RAG的檢索增強(qiáng)之上下文重排和壓縮-AI.x社區(qū)

2. Agent分析問題后,形成SQL查詢語句:獲取2020年第一天開盤價(jià)以及2020年最后一天的收盤價(jià)

基于Agent的金融問答系統(tǒng):RAG的檢索增強(qiáng)之上下文重排和壓縮-AI.x社區(qū)

3. Agent獲得開盤價(jià)和收盤價(jià)之后,調(diào)用我們提供的 calculate_stock_annualized_return 函數(shù)計(jì)算年化收益率,并返回結(jié)果。

基于Agent的金融問答系統(tǒng):RAG的檢索增強(qiáng)之上下文重排和壓縮-AI.x社區(qū)

結(jié)束語

基于Agent的金融問答系統(tǒng)系列文章在此告一段落了。 在這個(gè)項(xiàng)目中,我們不只利用AI技術(shù)完成了項(xiàng)目課題,其中也不乏應(yīng)用了軟件工程的一些方法論,而最為重要的是:我們解決了一個(gè)又一個(gè)的問題。 最后,附帶一張黑神話悟空的圖片,希望看到此篇文章的你我一同共勉。

?

本文轉(zhuǎn)載自公眾號一起AI技術(shù) 作者:Dongming

原文鏈接:??https://mp.weixin.qq.com/s/M7kgzGc8sY4CxXOLcs8ZSQ??

?著作權(quán)歸作者所有,如需轉(zhuǎn)載,請注明出處,否則將追究法律責(zé)任
標(biāo)簽
收藏
回復(fù)
舉報(bào)
回復(fù)
相關(guān)推薦
主站蜘蛛池模板: 欧美国产日韩一区二区三区 | 第一福利社区1024 | 视频一区二区三区中文字幕 | 免费av播放| 国产精品久久久久久久一区探花 | 欧美性一区二区三区 | 国产激情网 | 亚洲视频 欧美视频 | 亚洲一区二区三区在线视频 | www.4虎影院| 91精品国产乱码久久久久久 | 国产精品欧美一区二区三区不卡 | 美女福利网站 | 浴室洗澡偷拍一区二区 | 国产精品视频一二三区 | 亚洲国产aⅴ成人精品无吗 欧美激情欧美激情在线五月 | 欧美日日 | 欧美一区二区三区在线 | av资源中文在线天堂 | 日韩中文不卡 | 中文字幕在线一区 | av午夜电影 | 2020天天操 | 国产精品激情小视频 | 国产精品美女久久久久aⅴ国产馆 | 国户精品久久久久久久久久久不卡 | 久久精品久久精品 | 亚洲高清在线 | 久久av一区二区三区 | 91精品国产综合久久久久 | 久久久久久久久淑女av国产精品 | 欧美日韩国产一区二区 | 在线观看www | 综合网伊人 | 天天天操 | 精品久久久久久久久久久久 | 综合久 | 亚洲精品第一 | 91精品综合久久久久久五月天 | 色资源在线观看 | 日韩中文字幕久久 |