1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        從0開始學(xué)RAG之Query分解

        共 6106字,需瀏覽 13分鐘

         ·

        2024-04-11 20:42


        作者:lucas大叔

        原文地址:https://zhuanlan.zhihu.com/p/685746861

        類型: 技術(shù)分享

        本文為 @lucas大叔 投稿原創(chuàng)轉(zhuǎn)載!如有侵權(quán),麻煩告知?jiǎng)h除! 


        Query分解是通過將問題分解為子問題來改善問答效果的策略,分兩條實(shí)現(xiàn)路徑:(1)序列求解,將上一個(gè)子問題的答案與當(dāng)前問題一并扔給LLM生成答案,再把當(dāng)前生成答案與下一個(gè)子問題一起給LLM生成答案,直到最后一個(gè)子問題生成最終答案;(2)并行的獨(dú)立回答問題,然后將多路答案合并為最終答案。

        下面的示意圖很好地詮釋了兩種技術(shù)實(shí)現(xiàn)路徑的原理。

        序列求解

        獨(dú)立求解

        序列求解的思想來自least-to-most prompting和IRCoT這兩篇論文。

        在least-to-most prompting中,作者認(rèn)為CoT提示在自然語(yǔ)言推理任務(wù)上表現(xiàn)搶眼,但在解決比給的樣例更難的問題時(shí)就乏善可陳了。為了解決easy-to-hard泛化問題,大佬們提出了least-to-most prompting。分兩步解決問題:首先將復(fù)雜問題分解成一系列更容易的子問題,然后依次求解這些子問題,用先前解決的子問題答案助力當(dāng)前子問題的解決。這兩步都是通過few-shot prompting來實(shí)現(xiàn),不需要訓(xùn)練或者微調(diào)。

        在IRCoT中作者提出了類似的想法,對(duì)多步問答在CoT中交錯(cuò)檢索,使用檢索到的結(jié)果改善CoT。

        更多技術(shù)細(xì)節(jié),大家可以參考上述的兩篇論文。下面我們轉(zhuǎn)入代碼實(shí)戰(zhàn)環(huán)節(jié)。


        首先寫提示模板,將問題分解為若干個(gè)子問題。

        from langchain.prompts import ChatPromptTemplate
        # Decompositiontemplate = """You are a helpful assistant that generates multiple sub-questions related to an input question. \nThe goal is to break down the input into a set of sub-problems / sub-questions that can be answers in isolation. \nGenerate multiple search queries related to: {question} \nOutput (3 queries):"""prompt_decomposition = ChatPromptTemplate.from_template(template)

        構(gòu)造分解問題的chain,并將問題分解為幾個(gè)子問題。

        from langchain_openai import ChatOpenAIfrom langchain_core.output_parsers import StrOutputParser
        # LLMllm = ChatOpenAI(temperature=0)
        # Chaingenerate_queries_decomposition = ( prompt_decomposition | llm | StrOutputParser() | (lambda x: x.split("\n")))
        # Runquestion = "What are the main components of an LLM-powered autonomous agent system?"questions = generate_queries_decomposition.invoke({"question":question})

        Answer recursively

        如上面序列求解流程所示,構(gòu)建序列回答的prompt模板,基于context和qa對(duì)回答問題。

        # Prompttemplate = """Here is the question you need to answer:
        \n --- \n {question} \n --- \n
        Here is any available background question + answer pairs:
        \n --- \n {q_a_pairs} \n --- \n
        Here is additional context relevant to the question:
        \n --- \n {context} \n --- \n
        Use the above context and any background question + answer pairs to answer the question: \n {question}"""
        decomposition_prompt = ChatPromptTemplate.from_template(template)初始化q_a_pairs為空,查詢第一個(gè)問題時(shí),沒有qa對(duì)信息。從第二個(gè)問題開
        始,除了當(dāng)前的問題,還有前面所有輪的qa對(duì)信息,再加上當(dāng)前問題檢索回來的context一起給LLM得到答案。
        from operator import itemgetterfrom langchain_core.output_parsers import StrOutputParser
        def format_qa_pair(question, answer): """Format Q and A pair""" formatted_string = "" formatted_string += f"Question: {question}\nAnswer: {answer}\n\n" return formatted_string.strip()
        # llmllm = ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0)
        # q_a_pairs = ""for q in questions: rag_chain = ( {"context": itemgetter("question") | retriever, "question": itemgetter("question"), "q_a_pairs": itemgetter("q_a_pairs")} | decomposition_prompt | llm | StrOutputParser())
        answer = rag_chain.invoke({"question":q,"q_a_pairs":q_a_pairs}) q_a_pair = format_qa_pair(q,answer) q_a_pairs = q_a_pairs + "\n---\n"+ q_a_pair

        Answer individually

        相比于序列回答,并行獨(dú)立回答邏輯簡(jiǎn)單的多。每個(gè)子問題各自調(diào)用LLM回答自己的提問,匯總得到的答案。

        # Answer each sub-question individually 
        from langchain import hubfrom langchain_core.prompts import ChatPromptTemplatefrom langchain_core.runnables import RunnablePassthrough, RunnableLambdafrom langchain_core.output_parsers import StrOutputParserfrom langchain_openai import ChatOpenAI
        # RAG promptprompt_rag = hub.pull("rlm/rag-prompt")
        def retrieve_and_rag(question,prompt_rag,sub_question_generator_chain): """RAG on each sub-question""" # Use our decomposition / sub_questions = sub_question_generator_chain.invoke({"question":question}) # Initialize a list to hold RAG chain results rag_results = [] for sub_question in sub_questions: # Retrieve documents for each sub-question retrieved_docs = retriever.get_relevant_documents(sub_question) # Use retrieved documents and sub-question in RAG chain answer = (prompt_rag | llm | StrOutputParser()).invoke({"context": retrieved_docs, "question": sub_question}) rag_results.append(answer) return rag_results,sub_questions
        # Wrap the retrieval and RAG process in a RunnableLambda for integration into a chainanswers, questions = retrieve_and_rag(question, prompt_rag, generate_queries_decomposition)

        提示模板的指令也簡(jiǎn)單粗暴,告訴模型這是一組QA對(duì),你用它們來合成原始問題的答案吧!

        def format_qa_pairs(questions, answers):    """Format Q and A pairs"""        formatted_string = ""    for i, (question, answer) in enumerate(zip(questions, answers), start=1):        formatted_string += f"Question {i}: {question}\nAnswer {i}: {answer}\n\n"    return formatted_string.strip()
        context = format_qa_pairs(questions, answers)
        # Prompttemplate = """Here is a set of Q+A pairs:
        {context}
        Use these to synthesize an answer to the question: {question}"""
        prompt = ChatPromptTemplate.from_template(template)
        final_rag_chain = ( prompt | llm | StrOutputParser())
        final_rag_chain.invoke({"context":context,"question":question})

        瀏覽 72
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            特黄一毛二片一毛片 | 《乳色吐息》在线观看 | 国产精成人品电影 | 一级a免一级a做免费线看内裤软件 | 亚洲在线大香蕉 | 欧美日韩国产一级 | 性一交一乱一视频免费观看 | 麻豆精品在线 | 亚洲第九十七页 | 国产盗摄一区二区 |