Query Decomposition:
- Query Translation 처럼 여러개의 쿼리를 생성한다는 점은 동일함.
- Query Translation 은 여러개의 쿼리를 유사한 의미를 가진 다른 단어로 쿼리를 생성해 내거나, multi-query 접근 방식처럼 다른 관점에서 쿼리를 생성해 나가는 방법이 있음. 하지만 이런 방법들은 유저의 쿼리가 복잡한 단계적인 과정을 포함할 때 해결하기 힘듬.
- Query Decomposition 은 복잡한 쿼리를 multiple sub-problem queries 로 분리해 나가고, 이런 쿼리들을 연속적/병렬적으로 처리해 나가면서 오리지널 쿼리의 답변을 만드는 방식이다.
Query Decomposition 1) Least-to-Most Prompting:
Least-to-Most Prompting:
- 복잡한 문제를 해결하기 위한 프롬프트 기법으로, 문제를 더 작은 하위 문제로 나누어서 접근하고 해결하는 방법임.
- 이 기법을 Query Decomposition 에서 사용하는 방법을 보자.
LangChain 에서 Least-to-most prompting 사용 방법은 다음과 같다:
from langchain.prompts import ChatPromptTemplate
decompostion_prompt = ChatPromptTemplate.from_template(
"""
You are a helpful assistant that can break down complex questions into simpler parts. \n
Your goal is to decompose the given question into multiple sub-questions that can be answerd in isolation to answer the main question in the end. \n
Provide these sub-questions separated by the newline character. \n
Original question: {question}\n
Output (3 queries):
"""
)
query_generation_chain = (
{"question": RunnablePassthrough()}
| decompostion_prompt
| ChatOpenAI(model='gpt-4', temperature=0.7)
| StrOutputParser()
| (lambda x: x.split("\n"))
)
questions = query_generation_chain.invoke("What are the benefits of QLoRA?")
questions
decompostion_prompt 로 생성된 쿼리들의 출력 결과:
['What is QLoRA?',
'What are the features of QLoRA?',
'How do these features of QLoRA provide benefits?']
다음으로 이제 이렇게 생성된 하위 문제 쿼리들을 단계적으로 해결해나가면서 최종적으로 복잡한 답변을 생성해 나가는 코드를 보자.
from operator import itemgetter
# Create the final prompt template to answer the question with provided context and background Q&A pairs
template = """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}
"""
least_to_most_prompt = ChatPromptTemplate.from_template(template)
llm = ChatOpenAI(model='gpt-4', temperature=0)
least_to_most_chain = (
{'context': itemgetter('question') | retriever,
'q_a_pairs': itemgetter('q_a_pairs'),
'question': itemgetter('question'),
}
| least_to_most_prompt
| llm
| StrOutputParser()
)
q_a_pairs = ""
for q in questions:
answer = least_to_most_chain.invoke({"question": q, "q_a_pairs": q_a_pairs})
q_a_pairs+=f"Question: {q}\n\nAnswer: {answer}\n\n"
Query Decomposition 2) Step back prompting:
Step back prompting:
- 직접적인 문제 해결 대신 '한 걸음 물러서서' 더 넓은 맥락에서 문제를 바라보는 방법임. 구체적인 질문이나 문제에 대해 즉각적으로 답하기보다, 먼저 관련된 일반적인 원칙이나 개념을 고려하는 방법이다.
- 이런 broader perspective를 통해 문제의 본질을 더 잘 이해하고, 더 효과적인 해결책을 찾기 위해서 사용되는 방법임.
- Step back prompting 을 이용해서 Original Query 에 다가 추가로 추상화된 Query 를 만들고, 이를 이용해서 Vectore Store 에 Context 를 가져와서 답변을 하도록 만들 수 있음.
LangChain 에서 Stepback prompting 을 사용하는 방법은 다음과 같다:
from langchain_core.prompts import ChatPromptTemplate, FewShotChatMessagePromptTemplate
examples = [
{
'input': 'What happens to the pressure, P, of an ideal gas if the temperature is increased by a factor of 2 and the volume is increased by a factor of 8?',
'output': 'What are the physics principles behind this question?'
},
{
'input': 'Estella Leopold went to which school between Aug 1954 and Nov 1954?',
'output': "What was Estella Leopold's education history?"
}
]
example_prompt = ChatPromptTemplate.from_messages(
[
('human', '{input}'), ('ai', '{output}')
]
)
few_shot_prompt = FewShotChatMessagePromptTemplate(
examples=examples,
# This is a prompt template used to format each individual example.
example_prompt=example_prompt,
)
final_prompt = ChatPromptTemplate.from_messages(
[
('system', """You are an expert at world knowledge. Your task is to step back and paraphrase a question to a more generic step-back question, which is easier to answer. Here are a few examples:"""),
few_shot_prompt,
('user', '{question}'),
]
)
final_prompt.format(question= "What are the benefits of QLoRA?")
step_back_query_chain = (
{'question': RunnablePassthrough()}
| final_prompt
| ChatOpenAI(model='gpt-4', temperature=0.7)
| StrOutputParser()
)
step_back_query_chain.invoke("What are the optimal parameters for QLoRA?")
Step back prompting 을 이용하는 예시는 다음과 같다:
response_prompt_template = """You are an expert of world knowledge.
I am going to ask you a question. Your response should be comprehensive and not contradicted with the following context if they are relevant.
Otherwise, ignore them if they are not relevant.
# {normal_context}
# {step_back_context}
# Original Question: {question}
# Answer:"""
response_prompt = ChatPromptTemplate.from_template(response_prompt_template)
step_back_chain = (
{'normal_context': RunnablePassthrough() | retriever,
'step_back_context': RunnablePassthrough() | step_back_query_chain | retriever,
'question': RunnablePassthrough()
}
| response_prompt
| ChatOpenAI(model='gpt-4', temperature=0)
| StrOutputParser()
)
step_back_chain.invoke("What are the optimal parameters for QLoRA?")
'Generative AI > RAG' 카테고리의 다른 글
Hybrid Search (0) | 2024.07.10 |
---|---|
Searching for Best Practices in Retrieval-AugmentedGeneration (0) | 2024.07.09 |
BM42: New Baseline for Hybrid Search (0) | 2024.07.06 |
Advanced RAG Series: Generation and Evaluation (0) | 2024.06.19 |
Advanced RAG Series: Retrieval (0) | 2024.06.18 |