|
from operator import itemgetter |
|
|
|
from langchain_core.prompts import ChatPromptTemplate |
|
from langchain_core.output_parsers import StrOutputParser |
|
from langchain_core.runnables import RunnablePassthrough, RunnableLambda, RunnableBranch |
|
from langchain_core.prompts.prompt import PromptTemplate |
|
from langchain_core.prompts.base import format_document |
|
|
|
from climateqa.engine.reformulation import make_reformulation_chain |
|
from climateqa.engine.prompts import answer_prompt_template_custom,answer_prompt_without_docs_template |
|
from climateqa.engine.utils import pass_values, flatten_dict,prepare_chain,rename_chain |
|
from climateqa.engine.keywords import make_keywords_chain |
|
|
|
DEFAULT_DOCUMENT_PROMPT = PromptTemplate.from_template( |
|
template="{page_content}") |
|
|
|
|
|
def _combine_documents( |
|
docs, document_prompt=DEFAULT_DOCUMENT_PROMPT, sep="\n\n" |
|
): |
|
|
|
doc_strings = [] |
|
|
|
for i, doc in enumerate(docs): |
|
chunk_type = "Doc" |
|
if isinstance(doc, str): |
|
doc_formatted = doc |
|
else: |
|
doc_formatted = format_document(doc, document_prompt) |
|
doc_string = f"{chunk_type} {i+1}: " + doc_formatted |
|
doc_string = doc_string.replace("\n", " ") |
|
doc_strings.append(doc_string) |
|
|
|
return sep.join(doc_strings) |
|
|
|
|
|
def make_rag_chain(retriever, llm): |
|
|
|
|
|
prompt = ChatPromptTemplate.from_template(answer_prompt_template_custom) |
|
prompt_without_docs = ChatPromptTemplate.from_template( |
|
answer_prompt_without_docs_template) |
|
|
|
|
|
reformulation = make_reformulation_chain(llm) |
|
reformulation = prepare_chain(reformulation, "reformulation") |
|
|
|
|
|
keywords = make_keywords_chain(llm) |
|
keywords = {"keywords": itemgetter("question") | keywords} |
|
keywords = prepare_chain(keywords, "keywords") |
|
|
|
|
|
|
|
find_documents = {"docs": itemgetter( |
|
"question") | retriever} | RunnablePassthrough() |
|
find_documents = prepare_chain(find_documents, "find_documents") |
|
|
|
|
|
|
|
input_documents = { |
|
"context": lambda x: _combine_documents(x["docs"]), |
|
**pass_values(["question", "audience", "language", "keywords"]) |
|
} |
|
|
|
|
|
|
|
llm_final = rename_chain(llm, "answer") |
|
|
|
answer_with_docs = { |
|
"answer": input_documents | prompt | llm_final | StrOutputParser(), |
|
**pass_values(["question", "audience", "language", "query", "docs", "keywords"]), |
|
} |
|
|
|
answer_without_docs = { |
|
"answer": prompt_without_docs | llm_final | StrOutputParser(), |
|
**pass_values(["question", "audience", "language", "query", "docs", "keywords"]), |
|
} |
|
|
|
answer = RunnableBranch( |
|
(lambda x: len(x["docs"]) > 0, answer_with_docs), |
|
answer_with_docs, |
|
) |
|
|
|
|
|
|
|
rag_chain = reformulation | keywords | find_documents | answer |
|
|
|
return rag_chain |
|
|
|
|
|
def make_rag_papers_chain(llm): |
|
|
|
|
|
|
|
input_documents = { |
|
"context": lambda x: _combine_documents(x["docs"]), |
|
**pass_values(["question", "language"]) |
|
} |
|
|
|
chain = input_documents | llm | StrOutputParser() |
|
chain = rename_chain(chain,"answer") |
|
|
|
return chain |
|
|
|
|
|
|
|
|
|
|
|
|
|
def make_illustration_chain(llm): |
|
|
|
|
|
|
|
input_description_images = { |
|
"images":lambda x : _combine_documents(get_image_docs(x["docs"])), |
|
**pass_values(["question","audience","language","answer"]), |
|
} |
|
|
|
illustration_chain = input_description_images | llm | StrOutputParser() |
|
return illustration_chain |
|
|