Using self-correcting RAG wih local LLM to analyze World Economic Outlook from IMF¶
In this project I use a RAG-model which collects 3 blog-posts from the International Monetary Fund's website regarding the world economic outlook for 2024. I will implement a corrective feature which assesses the relevance of the documents, and does an aditional web-search if necessary.
The flow is as follows:
- I retrieve 3 blog posts from the IMF-website.
- I embed and index the documents into a vector-store.
- I retreive relevant parts of the documents.
- I use an AI-agent to grade the document-strips for relevancy, filtering out irrelevant documents from the first selection.
- If any of the document-strips have been filtered out, a web-search is inovked to search the web for more relevant information.
- Then an AI-agent genereates an answer to the initial question.
I use Langchain, Langgraph, Langsmith. I can use a local LLM or Mistral API.
I will test the model in three ways:
- I will first ask a relevant question to see if the model can give me a good answer.
- I will ask a question which can not be answered from the blog posts, but will have to be answered from a web-search.
- Lastly I will ask a totally irellevant question to see if the model can admit that it can not find an answer from the documents nor from the web, I wish to see if it avoids giving me an hallucinated answer.
Corrective-RAG is a strategy for RAG that incorporates self-reflection / self-grading on retrieved documents.
Below is a flow-chart of the process:
LLMs & Embeddings¶
We can choose to either:
- Run locally with Ollama Mistral as local LLM and GPT4AllEmbeddings from Nomic as local embedder.
- Run with Mistral API for both the LLM and embedder.
# I choose to run loacllay:
run_local = "Yes"
local_llm = "mistral:latest"
Search¶
I will use Tavily Search for web search. The Search API helps connect LLMs and AI applications to trusted and real-time knowledge, thus reducing hallucinations and overall bias
import os
TAVILY_API_KEY = os.environ.get("TAVILY_API_KEY")
os.environ['LANGCHAIN_TRACING_V2'] = 'true'
os.environ['LANGCHAIN_ENDPOINT'] = 'https://api.smith.langchain.com'
LANGSMITH_API_KEY = os.environ.get("LANGSMITH_API_KEY")
LANGCHAIN_API_KEY = LANGSMITH_API_KEY
Collecting blog posts, and indexing them¶
from langchain_community.document_loaders import WebBaseLoader
from langchain_community.vectorstores import Chroma
from langchain_community.embeddings import GPT4AllEmbeddings
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_mistralai import MistralAIEmbeddings
# Load
# 3 web pages from the IMF blog about the global economic outlook for 2024:
url = [
"https://www.imf.org/en/Blogs/Articles/2024/04/16/global-economy-remains-resilient-despite-uneven-growth-challenges-ahead",
"https://www.imf.org/en/Blogs/Articles/2024/04/08/housing-is-one-reason-not-all-countries-feel-same-pinch-of-higher-interest-rates",
"https://www.imf.org/en/Blogs/Articles/2024/04/10/world-must-prioritize-productivity-reforms-to-revive-medium-term-growth"
]
loader = WebBaseLoader(url)
docs = loader.load()
# Split
text_splitter = RecursiveCharacterTextSplitter.from_tiktoken_encoder(
chunk_size=500, chunk_overlap=100
)
all_splits = text_splitter.split_documents(docs)
# Embed and index
if run_local == "Yes":
embedding = GPT4AllEmbeddings()
else:
embedding = MistralAIEmbeddings(mistral_api_key=mistral_api_key)
# Indexing:
vectorstore = Chroma.from_documents(
documents=all_splits,
collection_name="rag-chroma",
embedding=embedding,
)
retriever = vectorstore.as_retriever()
# Just to follow the progress, let's have a look at what we've got so far:
print(f"len(docs): {len(docs)}")
print(f"len(all_splits): {len(all_splits)}")
print(f"len(vectorstore): {len(vectorstore)}")
len(docs): 3 len(all_splits): 17 len(vectorstore): 17
# Example of how to retrieve relevant documents:
# Type in keywords that you want to search for:
retrieved_docs = retriever.get_relevant_documents("productivity reforms")
retrieved_docs
/opt/anaconda3/envs/py311_ml/lib/python3.11/site-packages/langchain_core/_api/deprecation.py:119: LangChainDeprecationWarning: The method `BaseRetriever.get_relevant_documents` was deprecated in langchain-core 0.1.46 and will be removed in 0.3.0. Use invoke instead. warn_deprecated(
[Document(page_content='World Must Prioritize Productivity Reforms to Revive Medium-Term Growth\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n Chart of the Week\n\n\n Regions\n\n\n Topics\n\n\n Authors\n\n\n Archive\n\n\n IMF Home\n\n\n\n\n\n\n\n\n\n\n\n\nCredit: olaser/iStock by Getty Images \n\n\n\n\n\n\n\n\n\n\n\nEnglish \n\nالعربية\nespañol\nfrançais\n日本語\nрусский\n中文\n\n\n\n\n\n\n\n\n Economic growth\n\n\n\n\n\r\n World Must Prioritize Productivity Reforms to Revive Medium-Term Growth\r\n \n\n\n\n\n\n\n\n\n\n Without ambitious steps to enhance productivity, global growth is set to fall far below its historical average \n\nNan Li,\r\n Diaa Noureldin\n\nApril 10, 2024\n\n\n\n\n\n\n\n\n\nThe world economy faces a sobering reality. The global growth rate—stripped\nof cyclical ups and downs—has slowed steadily since the 2008-09 global\nfinancial crisis. Without policy intervention and leveraging emerging\ntechnologies, the stronger growth rates of the past are unlikely to return.', metadata={'language': 'en', 'source': 'https://www.imf.org/en/Blogs/Articles/2024/04/10/world-must-prioritize-productivity-reforms-to-revive-medium-term-growth', 'title': 'World Must Prioritize Productivity Reforms to Revive Medium-Term Growth'}), Document(page_content='Absent major technological advances or structural reforms, we expect global\neconomic growth to reach 2.8 percent by 2030, well below the historical\naverage of 3.8 percent.\n\n\nReviving global growth\n\n\nOur analysis evaluates the impact of policies on labor supply and resource\nallocation, set against the backdrop of the rapid advance of\n\nartificial intelligence, public debt overhang, and geoeconomic fragmentation.\n\n\nWe examine scenarios featuring ambitious, but achievable, policy shifts that\naddress resource misallocation by improving the flexibility of product and\nlabor markets, trade openness, and financial development. We also consider\npolicies aimed at enhancing labor supply or productivity by reforming\nretirement and unemployment benefits, supporting childcare, expanding\nre-training and re-skilling programs, and improving integration of migrant\nworkers, as well as the removal of social and gender barriers.\n\n\nOur findings indicate that the benefits of increasing labor force\nparticipation, integrating more migrant workers into advanced economies, and\noptimizing talent allocation in emerging markets are comparatively modest.\n\n\nBy contrast, reforms that enhance productivity and fully leverage AI are key\nfor reviving growth in the medium term. Our analysis suggests that focused\npolicy actions to enhance market competition, trade openness, financial\naccess, and labor market flexibility could lift global growth by about 1.2\npercentage points by 2030. The potential of AI to boost labor productivity\nis uncertain but potentially substantial as well, possibly adding up to 0.8\npercentage points to global growth, depending on its adoption and impact on\nthe workforce.\n\n\nIn the long run, innovation-driven policies will\nbe crucial to sustaining global growth.\n\n\n\n—This blog, based on Chapter 3 of the World Economic Outlook, “Slowdown\nin Global Medium-Term Growth: What Will it Take to Turn the Tide?”,\nreflects research by Chiara Maggi, Cedric Okou, Alexandre B. Sollaci,\nand Robert Zymek.\xa0\n\n\n\n\n\n\nRecent\n\n\n\n\n\n\n\n\n\n Economic growth\n\n\nA\n文\n\n\nScars of Conflict Are Deeper and Longer Lasting in Middle East and Central Asia\nJune 5, 2024\nThe negative economic effects of conflicts are larger and more persistent, partly reflecting a sharper impact of higher-intensity conflicts in these regions.\n\n\n\n\n\n\n\n\n\n\n\n Economic growth', metadata={'language': 'en', 'source': 'https://www.imf.org/en/Blogs/Articles/2024/04/10/world-must-prioritize-productivity-reforms-to-revive-medium-term-growth', 'title': 'World Must Prioritize Productivity Reforms to Revive Medium-Term Growth'}), Document(page_content='Resource allocation is crucial for growth, our analysis shows. Yet, in\nrecent years, increasingly inefficient distribution of resources across\nfirms has dragged down TFP and, with it, global growth.\n\n\nMuch of this rising misallocation stems from persistent barriers, such as\npolicies that favor or penalize some firms irrespective of their\nproductivity, that prevent capital and labor from reaching the most\nproductive companies. This limits their growth potential. If resource\nmisallocation hadn’t worsened, TFP growth could have been 50 percent higher\nand the deceleration in growth would have been less severe.\n\n\nTwo additional factors have also slowed growth. Demographic pressures in\nmajor economies, where the proportion of working-age population is\nshrinking, have weighed on labor growth. Meanwhile, weak business investment\nhas stunted capital formation.\n\n\nMedium-term pressures\n\n\nDemographic pressures are set to increase in most of the major economies,\naccording to United Nations projections, causing an imbalance in world labor\nsupply and dampening global growth. The working-age population will increase\nin low-income and some emerging economies, whereas China and most advanced\neconomies (excluding the United States) will face a labor squeeze. By 2030,\nwe expect the growth rate of the global labor supply to slide to just 0.3\npercent—a fraction of its pre-pandemic average.\n\n\nSome resource misallocation may correct itself over time, as labor and\ncapital gravitate toward more productive firms. This will go some way toward\nmitigating the TFP slowdown even as structural and policy barriers continue\nto slow the process. Technological innovation may also lessen the slowdown.\n\n\nBut overall the pace of TFP growth is likely to continue to decline, driven\nby challenges such as the increasing difficulty of coming up with\ntechnological breakthroughs, stagnation in educational attainment, and a\nslower process by which less developed economies can catch up with their\nmore developed peers.\n\n\nAbsent major technological advances or structural reforms, we expect global\neconomic growth to reach 2.8 percent by 2030, well below the historical\naverage of 3.8 percent.\n\n\nReviving global growth\n\n\nOur analysis evaluates the impact of policies on labor supply and resource\nallocation, set against the backdrop of the rapid advance of', metadata={'language': 'en', 'source': 'https://www.imf.org/en/Blogs/Articles/2024/04/10/world-must-prioritize-productivity-reforms-to-revive-medium-term-growth', 'title': 'World Must Prioritize Productivity Reforms to Revive Medium-Term Growth'}), Document(page_content='The first such priority is to rebuild fiscal buffers. Even as inflation\nrecedes, real interest rates remain high and sovereign\ndebt dynamics have become less favorable. Credible fiscal consolidations can help lower funding costs, improve\nfiscal headroom and\n\nfinancial stability. Unfortunately, fiscal plans so far are insufficient and could be derailed\nfurther given the record number of elections this year.\n\n\n\nFiscal\n\nconsolidations are never easy\xa0but it is best not to wait until markets dictate their conditions. The right\napproach is to start now, gradually, and credibly. Once inflation is under\ncontrol, credible multiyear consolidations will help pave the way for\nfurther monetary policy easing. The successful 1993 US fiscal consolidation\nand monetary accommodation episode comes to mind as an example to emulate.\n\n\nThe second priority is to reverse the decline in medium term growth\nprospects. Some of that decline comes from increased\n\nmisallocation of capital and labor\xa0within sectors and countries. Facilitating faster and more efficient\nresource allocation will boost growth. For low-income countries, structural\nreforms to promote domestic and foreign direct investment, and to strengthen\ndomestic resource mobilization, will help lower borrowing costs and reduce\nfunding needs. These countries also must improve the human capital of their\nlarge young populations, especially as the rest of the world is aging\nrapidly.\n\n\nArtificial intelligence also gives hope for boosting productivity. It may do\nso, but the potential for serious disruptions in labor and financial markets\nis high.\n\nHarnessing the potential of AI\xa0for all will require that countries improve their digital infrastructure,\ninvest in human capital, and coordinate on global rules of the road.\n\n\nMedium-term growth prospects are also harmed by rising geoeconomic\nfragmentation and the surge in trade restrictive and industrial policy\nmeasures. Trade linkages are already changing as a result, with potential\nlosses in efficiency. The net effect could well be to make the global\neconomy less, not more, resilient. But the broader damage is to global\ncooperation. It is still time to reverse course.\n\n\nThird, a great achievement of the past few years has been the strengthening\nof monetary, fiscal and financial policy frameworks especially for emerging\nmarket economies. This has helped make the', metadata={'language': 'en', 'source': 'https://www.imf.org/en/Blogs/Articles/2024/04/16/global-economy-remains-resilient-despite-uneven-growth-challenges-ahead', 'title': 'Global Economy Remains Resilient Despite Uneven Growth, Challenges Ahead'})]
# So, we have 4 relevant doc-splits in this case.
# # Example of how to display one of the documents:
print( retrieved_docs[1].page_content )
Absent major technological advances or structural reforms, we expect global economic growth to reach 2.8 percent by 2030, well below the historical average of 3.8 percent. Reviving global growth Our analysis evaluates the impact of policies on labor supply and resource allocation, set against the backdrop of the rapid advance of artificial intelligence, public debt overhang, and geoeconomic fragmentation. We examine scenarios featuring ambitious, but achievable, policy shifts that address resource misallocation by improving the flexibility of product and labor markets, trade openness, and financial development. We also consider policies aimed at enhancing labor supply or productivity by reforming retirement and unemployment benefits, supporting childcare, expanding re-training and re-skilling programs, and improving integration of migrant workers, as well as the removal of social and gender barriers. Our findings indicate that the benefits of increasing labor force participation, integrating more migrant workers into advanced economies, and optimizing talent allocation in emerging markets are comparatively modest. By contrast, reforms that enhance productivity and fully leverage AI are key for reviving growth in the medium term. Our analysis suggests that focused policy actions to enhance market competition, trade openness, financial access, and labor market flexibility could lift global growth by about 1.2 percentage points by 2030. The potential of AI to boost labor productivity is uncertain but potentially substantial as well, possibly adding up to 0.8 percentage points to global growth, depending on its adoption and impact on the workforce. In the long run, innovation-driven policies will be crucial to sustaining global growth. —This blog, based on Chapter 3 of the World Economic Outlook, “Slowdown in Global Medium-Term Growth: What Will it Take to Turn the Tide?”, reflects research by Chiara Maggi, Cedric Okou, Alexandre B. Sollaci, and Robert Zymek. Recent Economic growth A 文 Scars of Conflict Are Deeper and Longer Lasting in Middle East and Central Asia June 5, 2024 The negative economic effects of conflicts are larger and more persistent, partly reflecting a sharper impact of higher-intensity conflicts in these regions. Economic growth
LLMs¶
from langchain.prompts import PromptTemplate
from langchain_community.chat_models import ChatOllama
from langchain_mistralai.chat_models import ChatMistralAI
from langchain_core.output_parsers import JsonOutputParser
### Retrieval Grader
# LLM
if run_local == "Yes":
llm = ChatOllama(model=local_llm, format="json", temperature=0)
else:
llm = ChatMistralAI(
model="mistral-medium", temperature=0, mistral_api_key=mistral_api_key
)
prompt = PromptTemplate(
template="""You are a grader assessing relevance of a retrieved document to a user question. \n
Here is the retrieved document: \n\n {document} \n\n
Here is the user question: {question} \n
If the document contains keywords related to the user question, grade it as relevant. \n
It does not need to be a stringent test. The goal is to filter out erroneous retrievals. \n
Give a binary score 'yes' or 'no' score to indicate whether the document is relevant to the question. \n
Provide the binary score as a JSON with a single key 'score' and no premable or explanation.""",
input_variables=["question", "document"],
)
retrieval_grader = prompt | llm | JsonOutputParser()
question = "Why has high interest rates had different effects on different countries?"
docs = retriever.get_relevant_documents(question)
# Below is an example of how the retrieval grader grades a document:
doc_txt = docs[1].page_content
print(retrieval_grader.invoke({"question": question, "document": doc_txt}))
{'score': 'yes'}
# For quiriosity's sake, I just want to have a look at the text:
doc_txt
'Effects may be delayed in some countries: if interest rates remain higher for longer, homeowners will likely feel their effects as mortgage rates adjust \n\nMehdi Benatiya Andaloussi,\r\n Nina Biljanovska,\r\n Alessia De Stefani,\r\n Rui C. Mano\n\nApril 8, 2024\n\n\n\n\n\n\n\n\nCentral banks have raised interest rates significantly over the past two\nyears to combat post-pandemic inflation. Many thought this would lead to a\nslowdown in economic activity. Yet, global growth has held broadly steady,\nwith deceleration only materializing in some countries.\n\n\nWhy are some feeling the pinch from higher rates and not others? The answer\npartly lies in differences in mortgage and housing market characteristics.\nThe effects of rising monetary policy rates on activity partly depend on\nhousing and mortgage market characteristics, which vary significantly across\ncountries, as we show in a chapter of our latest World Economic Outlook.\n\n\nHousing is an important channel of monetary policy transmission. Mortgages\nare the largest liability for households, with housing often serving as\ntheir only significant form of wealth. Real estate also accounts for a large\nshare of consumption, investment, employment, and consumer prices in most\neconomies.'
# ... and we can see that it was relevant for the question.
# For quriosity's sake let's look at the other relevant documents:
doc_txt2 = [docs[i].page_content for i in range(len(docs))]
for txt in doc_txt2:
print(retrieval_grader.invoke({"question": question, "document": txt}))
{'score': 'yes'} {'score': 'yes'} {'score': 'yes'} {'score': 'yes'}
# Let's just manually inspect some of the relevant documents for fun sake:
docs
[Document(page_content='Housing is One Reason Not All Countries Feel Same Pinch of Higher Interest Rates\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n Chart of the Week\n\n\n Regions\n\n\n Topics\n\n\n Authors\n\n\n Archive\n\n\n IMF Home\n\n\n\n\n\n\n\n\n\n\n\n\nCredit: Kajdi-Szabolcs/iStock by Getty Images \n\n\n\n\n\n\n\n\n\n\n\nEnglish \n\nالعربية\nespañol\nfrançais\n日本語\nрусский\n中文\n\n\n\n\n\n\n\n\n Monetary policy\n\n\n\n\n\r\n Housing is One Reason Not All Countries Feel Same Pinch of Higher Interest Rates\r\n \n\n\n\n\n\n\n\n\n\n Effects may be delayed in some countries: if interest rates remain higher for longer, homeowners will likely feel their effects as mortgage rates adjust', metadata={'language': 'en', 'source': 'https://www.imf.org/en/Blogs/Articles/2024/04/08/housing-is-one-reason-not-all-countries-feel-same-pinch-of-higher-interest-rates', 'title': 'Housing is One Reason Not All Countries Feel Same Pinch of Higher Interest Rates'}), Document(page_content='Effects may be delayed in some countries: if interest rates remain higher for longer, homeowners will likely feel their effects as mortgage rates adjust \n\nMehdi Benatiya Andaloussi,\r\n Nina Biljanovska,\r\n Alessia De Stefani,\r\n Rui C. Mano\n\nApril 8, 2024\n\n\n\n\n\n\n\n\nCentral banks have raised interest rates significantly over the past two\nyears to combat post-pandemic inflation. Many thought this would lead to a\nslowdown in economic activity. Yet, global growth has held broadly steady,\nwith deceleration only materializing in some countries.\n\n\nWhy are some feeling the pinch from higher rates and not others? The answer\npartly lies in differences in mortgage and housing market characteristics.\nThe effects of rising monetary policy rates on activity partly depend on\nhousing and mortgage market characteristics, which vary significantly across\ncountries, as we show in a chapter of our latest World Economic Outlook.\n\n\nHousing is an important channel of monetary policy transmission. Mortgages\nare the largest liability for households, with housing often serving as\ntheir only significant form of wealth. Real estate also accounts for a large\nshare of consumption, investment, employment, and consumer prices in most\neconomies.', metadata={'language': 'en', 'source': 'https://www.imf.org/en/Blogs/Articles/2024/04/08/housing-is-one-reason-not-all-countries-feel-same-pinch-of-higher-interest-rates', 'title': 'Housing is One Reason Not All Countries Feel Same Pinch of Higher Interest Rates'}), Document(page_content='Housing is an important channel of monetary policy transmission. Mortgages\nare the largest liability for households, with housing often serving as\ntheir only significant form of wealth. Real estate also accounts for a large\nshare of consumption, investment, employment, and consumer prices in most\neconomies.\n\n\nTo assess how key housing characteristics impact the effects of monetary\npolicy on activity, our research leverages new data on housing and mortgage\nmarkets compiled across countries: we find that those characteristics vary\nsignificantly across countries. For example, the share of fixed-rate\nmortgages in all country-level mortgages can vary from close to zero in\nSouth Africa to more than 95 percent in Mexico or the United States.\n\n\nOur results indicate that monetary policy has greater effects on activity in\ncountries where the share of fixed-rate mortgages is low. This is due to\nhomeowners seeing their monthly payments rise with monetary policy rates if\ntheir mortgage rates adjust. By contrast, households with fixed-rate\nmortgages will not see any immediate difference in their monthly payments\nwhen policy rates change.\n\n\nThe effects of monetary policy are also stronger in countries where\nmortgages are larger compared to home values, and in countries where\nhousehold debt is high as a share of GDP. In such settings, more households\nwill be exposed to changes in mortgage rates, and the effects will be\nstronger if their debt is higher relative to their assets.\n\n\nHousing market characteristics also matter: the transmission of monetary\npolicy is stronger where housing supply is more restricted. For example,\nlower rates will decrease borrowing costs for first-time home buyers and\nincrease demand. Where supply is restricted, this will lead to home price\nappreciation. Existing owners will see their wealth increase as a result,\nleading them to consume more, including if they can use their home as\ncollateral to borrow more.\n\n\nThe same holds true where home prices have recently been overvalued. Sharp\nprice increases are often driven by overly optimistic views about future\nhouse prices. These are typically accompanied by excessive leverage,\nprompting spirals of falling home prices and foreclosures when monetary\npolicy tightens, which can lead to starker income and consumption declines.\n\n\nWeaker housing transmission', metadata={'language': 'en', 'source': 'https://www.imf.org/en/Blogs/Articles/2024/04/08/housing-is-one-reason-not-all-countries-feel-same-pinch-of-higher-interest-rates', 'title': 'Housing is One Reason Not All Countries Feel Same Pinch of Higher Interest Rates'}), Document(page_content='The same holds true where home prices have recently been overvalued. Sharp\nprice increases are often driven by overly optimistic views about future\nhouse prices. These are typically accompanied by excessive leverage,\nprompting spirals of falling home prices and foreclosures when monetary\npolicy tightens, which can lead to starker income and consumption declines.\n\n\nWeaker housing transmission\n\n\nMortgage and real estate markets have undergone several shifts since the\nglobal financial crisis and the pandemic. At the beginning of the recent\nhiking cycle and after a long period of low interest rates, mortgage\ninterest payments were historically low, the average maturity was long, and\nthe average share of fixed-rate mortgages was high in many countries. In\naddition, the pandemic led to population shifts away from city centers and\nto relatively less-supply-constrained areas.\n\n\nAs a result, the housing channels of monetary policy may have weakened, or\nat least been delayed, in several countries.\n\n\nCountry experiences vary widely. Changes in mortgage market characteristics\nin countries such as Canada and Japan suggest a strengthening of the\ntransmission of monetary policy through housing. This is driven mainly by a\ndeclining share of fixed-rate mortgages, an increase in debt, and more\nconstrained housing supply. By contrast, transmission seems to have weakened\nin countries such as Hungary, Ireland, Portugal, and the United States,\nwhere characteristics have moved in the opposite direction.\n\n\nCalibrating policy\n\n\nOur findings suggest that a deep, country-specific understanding of housing\nchannels is important to help calibrate and adjust monetary policy. In\ncountries where the housing channels are strong, monitoring housing market\ndevelopments and changes in household debt service can help identify early\nsigns of overtightening. Where monetary policy transmission is weak, more\nforceful early action can be taken when signs of overheating and\ninflationary pressures first emerge.\n\n\nWhat about now? Most central banks have made significant progress toward\ntheir inflation target. It could follow from the discussion that, if\ntransmission is weak, erring on the side of too much tightening is always\nless costly. However, overtightening, or leaving rates higher for longer,\ncould nevertheless be a greater risk now.', metadata={'language': 'en', 'source': 'https://www.imf.org/en/Blogs/Articles/2024/04/08/housing-is-one-reason-not-all-countries-feel-same-pinch-of-higher-interest-rates', 'title': 'Housing is One Reason Not All Countries Feel Same Pinch of Higher Interest Rates'})]
print( docs[1].page_content )
Effects may be delayed in some countries: if interest rates remain higher for longer, homeowners will likely feel their effects as mortgage rates adjust Mehdi Benatiya Andaloussi, Nina Biljanovska, Alessia De Stefani, Rui C. Mano April 8, 2024 Central banks have raised interest rates significantly over the past two years to combat post-pandemic inflation. Many thought this would lead to a slowdown in economic activity. Yet, global growth has held broadly steady, with deceleration only materializing in some countries. Why are some feeling the pinch from higher rates and not others? The answer partly lies in differences in mortgage and housing market characteristics. The effects of rising monetary policy rates on activity partly depend on housing and mortgage market characteristics, which vary significantly across countries, as we show in a chapter of our latest World Economic Outlook. Housing is an important channel of monetary policy transmission. Mortgages are the largest liability for households, with housing often serving as their only significant form of wealth. Real estate also accounts for a large share of consumption, investment, employment, and consumer prices in most economies.
# Let's check another one:
print( docs[2].page_content )
Housing is an important channel of monetary policy transmission. Mortgages are the largest liability for households, with housing often serving as their only significant form of wealth. Real estate also accounts for a large share of consumption, investment, employment, and consumer prices in most economies. To assess how key housing characteristics impact the effects of monetary policy on activity, our research leverages new data on housing and mortgage markets compiled across countries: we find that those characteristics vary significantly across countries. For example, the share of fixed-rate mortgages in all country-level mortgages can vary from close to zero in South Africa to more than 95 percent in Mexico or the United States. Our results indicate that monetary policy has greater effects on activity in countries where the share of fixed-rate mortgages is low. This is due to homeowners seeing their monthly payments rise with monetary policy rates if their mortgage rates adjust. By contrast, households with fixed-rate mortgages will not see any immediate difference in their monthly payments when policy rates change. The effects of monetary policy are also stronger in countries where mortgages are larger compared to home values, and in countries where household debt is high as a share of GDP. In such settings, more households will be exposed to changes in mortgage rates, and the effects will be stronger if their debt is higher relative to their assets. Housing market characteristics also matter: the transmission of monetary policy is stronger where housing supply is more restricted. For example, lower rates will decrease borrowing costs for first-time home buyers and increase demand. Where supply is restricted, this will lead to home price appreciation. Existing owners will see their wealth increase as a result, leading them to consume more, including if they can use their home as collateral to borrow more. The same holds true where home prices have recently been overvalued. Sharp price increases are often driven by overly optimistic views about future house prices. These are typically accompanied by excessive leverage, prompting spirals of falling home prices and foreclosures when monetary policy tightens, which can lead to starker income and consumption declines. Weaker housing transmission
from langchain import hub
from langchain_core.output_parsers import StrOutputParser
### Generator
# Prompt
prompt = hub.pull("rlm/rag-prompt")
# LLM
if run_local == "Yes":
llm = ChatOllama(model=local_llm, temperature=0)
else:
llm = ChatMistralAI(
model="mistral-medium", temperature=0, mistral_api_key=mistral_api_key
)
# Post-processing
def format_docs(docs):
return "\n\n".join(doc.page_content for doc in docs)
# Chain
rag_chain = prompt | llm | StrOutputParser()
# Run
generation = rag_chain.invoke({"context": docs, "question": question})
print(generation)
The text discusses how housing characteristics can impact the effects of monetary policy on economic activity. It highlights that countries with a lower share of fixed-rate mortgages, larger mortgages compared to home values, and high household debt as a percentage of GDP are more affected by changes in interest rates. This is because households with adjustable-rate mortgages will see their monthly payments rise when policy rates change, while those with fixed-rate mortgages will not experience an immediate difference. The text also mentions that the transmission of monetary policy is stronger where housing supply is more restricted and home prices have recently been overvalued. In such cases, tightening monetary policy can lead to sharp price decreases, foreclosures, income, and consumption declines. The text suggests that understanding housing channels is crucial for calibrating and adjusting monetary policy. In countries where the housing channels are strong, monitoring housing market developments and changes in household debt service can help identify early signs of overtightening or inflationary pressures. On the other hand, in countries where transmission is weak, more forceful action may be needed when signs of overheating emerge. The text concludes by suggesting that central banks should consider these factors when setting monetary policy, as erring on the side of too much tightening could lead to greater risks, especially now that many central banks have made significant progress toward their inflation targets.
# Let's just inspect how this output looks:
print(f"type(generation): {type(generation)}")
print(f"len(generation): {len(generation)}")
type(generation): <class 'str'> len(generation): 1549
from langchain_core.output_parsers import StrOutputParser
### Question Re-writer
# LLM
if run_local == "Yes":
llm = ChatOllama(model=local_llm, temperature=0)
else:
llm = ChatMistralAI(
model="mistral-medium", temperature=0, mistral_api_key=mistral_api_key
)
# Prompt
re_write_prompt = PromptTemplate(
template="""You a question re-writer that converts an input question to a better version that is optimized \n
for vectorstore retrieval. Look at the initial and formulate an improved question. \n
Here is the initial question: \n\n {question}. Improved question with no preamble: \n """,
input_variables=["generation", "question"],
)
question_rewriter = re_write_prompt | llm | StrOutputParser()
question_rewriter.invoke({"question": question})
' What are the specific differences in economic impacts of high interest rates across various countries?'
Web Search Tool¶
### Specify web search tool:
from langchain_community.tools.tavily_search import TavilySearchResults
web_search_tool = TavilySearchResults(k=3)
from typing_extensions import TypedDict
from typing import List
class GraphState(TypedDict):
"""
Represents the state of our graph.
Attributes:
question: question
generation: LLM generation
web_search: whether to add search
documents: list of documents
"""
question: str
generation: str
web_search: str
documents: List[str]
from langchain.schema import Document
def retrieve(state):
"""
Retrieve documents
Args:
state (dict): The current graph state
Returns:ß
state (dict): New key added to state, documents, that contains retrieved documents
"""
print("---RETRIEVE---")
question = state["question"]
# Retrieval
documents = retriever.get_relevant_documents(question)
return {"documents": documents, "question": question}
def grade_documents(state):
"""
Determines whether the retrieved documents are relevant to the question.
Args:
state (dict): The current graph state
Returns:
state (dict): Updates documents key with only filtered relevant documents
"""
print("---CHECK DOCUMENT RELEVANCE TO QUESTION---")
question = state["question"]
documents = state["documents"]
# Score each doc
filtered_docs = []
web_search = "No"
for d in documents:
score = retrieval_grader.invoke(
{"question": question, "document": d.page_content}
)
grade = score["score"]
if grade == "yes":
print("---GRADE: DOCUMENT RELEVANT---")
filtered_docs.append(d)
else:
print("---GRADE: DOCUMENT NOT RELEVANT---")
web_search = "Yes"
continue
return {"documents": filtered_docs, "question": question, "web_search": web_search}
def transform_query(state):
"""
Transform the query to produce a better question.
Args:
state (dict): The current graph state
Returns:
state (dict): Updates question key with a re-phrased question
"""
print("---TRANSFORM QUERY---")
question = state["question"]
documents = state["documents"]
# Re-write question
better_question = question_rewriter.invoke({"question": question})
return {"documents": documents, "question": better_question}
def web_search(state):
"""
Web search based on the re-phrased question.
Args:
state (dict): The current graph state
Returns:
state (dict): Updates documents key with appended web results
"""
print("---WEB SEARCH---")
question = state["question"]
documents = state["documents"]
# Web search
docs = web_search_tool.invoke({"query": question})
web_results = "\n".join([d["content"] for d in docs])
web_results = Document(page_content=web_results)
documents.append(web_results)
return {"documents": documents, "question": question}
def decide_to_generate(state):
"""
Determines whether to generate an answer, or re-generate a question.
Args:
state (dict): The current graph state
Returns:
str: Binary decision for next node to call
"""
print("---ASSESS GRADED DOCUMENTS---")
question = state["question"]
web_search = state["web_search"]
filtered_documents = state["documents"]
if web_search == "Yes":
# All documents have been filtered check_relevance
# We will re-generate a new query
print(
"---DECISION: ALL DOCUMENTS ARE NOT RELEVANT TO QUESTION, TRANSFORM QUERY---"
)
return "transform_query"
else:
# We have relevant documents, so generate answer
print("---DECISION: GENERATE---")
return "generate"
def generate(state):
"""
Generate answer
Args:
state (dict): The current graph state
Returns:
state (dict): New key added to state, generation, that contains LLM generation
"""
print("---GENERATE---")
question = state["question"]
documents = state["documents"]
# RAG generation
generation = rag_chain.invoke({"context": documents, "question": question})
return {"documents": documents, "question": question, "generation": generation}
Build Graph¶
from langgraph.graph import END, StateGraph
workflow = StateGraph(GraphState)
# Define the nodes
workflow.add_node("retrieve", retrieve) # retrieve
workflow.add_node("grade_documents", grade_documents) # grade documents
workflow.add_node("generate", generate) # generatae
workflow.add_node("transform_query", transform_query) # transform_query
workflow.add_node("web_search_node", web_search) # web search
# Build graph
workflow.set_entry_point("retrieve")
workflow.add_edge("retrieve", "grade_documents")
workflow.add_conditional_edges(
"grade_documents",
decide_to_generate,
{
"transform_query": "transform_query",
"generate": "generate",
},
)
workflow.add_edge("transform_query", "web_search_node")
workflow.add_edge("web_search_node", "generate")
workflow.add_edge("generate", END)
# Compile
app = workflow.compile()
from pprint import pprint
# Run
inputs = {"question": "Why has high interest rates had different effects on different countries?"}
for output in app.stream(inputs):
for key, value in output.items():
# Node
pprint(f"Node '{key}':")
# Optional: print full state at each node
# pprint.pprint(value["keys"], indent=2, width=80, depth=None)
pprint("\n---\n")
# Final generation
pprint(value["generation"])
---RETRIEVE--- "Node 'retrieve':" '\n---\n' ---CHECK DOCUMENT RELEVANCE TO QUESTION--- ---GRADE: DOCUMENT RELEVANT--- ---GRADE: DOCUMENT RELEVANT--- ---GRADE: DOCUMENT RELEVANT--- ---GRADE: DOCUMENT RELEVANT--- ---ASSESS GRADED DOCUMENTS--- ---DECISION: GENERATE--- "Node 'grade_documents':" '\n---\n' ---GENERATE--- "Node 'generate':" '\n---\n' (' The text discusses how housing characteristics can impact the effects of ' 'monetary policy on economic activity. It highlights that countries with a ' 'lower share of fixed-rate mortgages, larger mortgages compared to home ' 'values, and high household debt as a percentage of GDP are more affected by ' 'changes in interest rates. This is because households with adjustable-rate ' 'mortgages will see their monthly payments rise when policy rates change, ' 'while those with fixed-rate mortgages will not experience an immediate ' 'difference.\n' '\n' 'The text also mentions that the transmission of monetary policy is stronger ' 'where housing supply is more restricted and home prices have recently been ' 'overvalued. In such cases, tightening monetary policy can lead to sharp ' 'price decreases, foreclosures, income, and consumption declines.\n' '\n' 'The text suggests that understanding housing channels is crucial for ' 'calibrating and adjusting monetary policy. In countries where the housing ' 'channels are strong, monitoring housing market developments and changes in ' 'household debt service can help identify early signs of overtightening or ' 'inflationary pressures. On the other hand, in countries where transmission ' 'is weak, more forceful action may be needed when signs of overheating ' 'emerge.\n' '\n' 'The text concludes by suggesting that central banks should consider these ' 'factors when setting monetary policy, as erring on the side of too much ' 'tightening could lead to greater risks, especially now that many central ' 'banks have made significant progress toward their inflation targets.')
Trace: If I want to follow the workflow of the AI-agents, I can check out the flow with Langsmith:
https://smith.langchain.com/public/731df833-57de-4612-8fe8-07cb424bc9a6/r
Overall I am happy with the output from above.
Next, let's try to force the algorithm to search the web instead, i.e. I will give it a question which is totally unrelated to the documents.
# Testing the web search function:
from pprint import pprint
# Run
inputs = {"question": "Is Pluto a planet in our solar system? What has been a debate on this subject recently. What is the summary of that debate"}
for output in app.stream(inputs):
for key, value in output.items():
# Node
pprint(f"Node '{key}':")
# Optional: print full state at each node
# pprint.pprint(value["keys"], indent=2, width=80, depth=None)
pprint("\n---\n")
# Final generation
pprint(value["generation"])
---RETRIEVE--- "Node 'retrieve':" '\n---\n' ---CHECK DOCUMENT RELEVANCE TO QUESTION--- ---GRADE: DOCUMENT NOT RELEVANT--- ---GRADE: DOCUMENT NOT RELEVANT--- ---GRADE: DOCUMENT NOT RELEVANT--- ---GRADE: DOCUMENT NOT RELEVANT--- ---ASSESS GRADED DOCUMENTS--- ---DECISION: ALL DOCUMENTS ARE NOT RELEVANT TO QUESTION, TRANSFORM QUERY--- "Node 'grade_documents':" '\n---\n' ---TRANSFORM QUERY--- "Node 'transform_query':" '\n---\n' ---WEB SEARCH--- "Node 'web_search_node':" '\n---\n' ---GENERATE--- "Node 'generate':" '\n---\n' (' As of now, Pluto is classified as a dwarf planet by the International ' 'Astronomical Union (IAU). The debate surrounding this classification ' 'revolves around the definition of a planet and whether objects like Pluto ' 'should be considered planets or not. Some scientists argue that Pluto should ' 'regain its status as a full-fledged planet, while others support the current ' 'classification.')
I am happy with this result, the algorithm does indeed notice that the documents are not relevant, and it searches the web for an answer.
Lastly, I will see what happens if I pose a question to which there is no answer. Will it halluciante, or just admitt that it hasn't found an answer. I will invent an imaginary author, and an imaginary book, and see what happens if I ask for the name of the main character of the book.
from pprint import pprint
# Run
inputs = {"question": "The author Diggio Wennigg wrote a book called 'The Brown Floor'. What is the name of the main character in the book?"}
for output in app.stream(inputs):
for key, value in output.items():
# Node
pprint(f"Node '{key}':")
# Optional: print full state at each node
# pprint.pprint(value["keys"], indent=2, width=80, depth=None)
pprint("\n---\n")
# Final generation
pprint(value["generation"])
---RETRIEVE--- "Node 'retrieve':" '\n---\n' ---CHECK DOCUMENT RELEVANCE TO QUESTION--- ---GRADE: DOCUMENT NOT RELEVANT--- ---GRADE: DOCUMENT NOT RELEVANT--- ---GRADE: DOCUMENT NOT RELEVANT--- ---GRADE: DOCUMENT NOT RELEVANT--- ---ASSESS GRADED DOCUMENTS--- ---DECISION: ALL DOCUMENTS ARE NOT RELEVANT TO QUESTION, TRANSFORM QUERY--- "Node 'grade_documents':" '\n---\n' ---TRANSFORM QUERY--- "Node 'transform_query':" '\n---\n' ---WEB SEARCH--- "Node 'web_search_node':" '\n---\n' ---GENERATE--- "Node 'generate':" '\n---\n' (' The main character in Diggio Wennigg\'s book, "The Brown Floor," is not ' 'explicitly mentioned in the provided context.')
Finally I am happy that the algorithm did not hallucinate, but simply stated that it not find an answer.