mirror of
https://github.com/OpenBB-finance/OpenBB.git
synced 2026-10-27 04:31:13 +00:00
langchain agent using openbb functions (#7131)
* langchain agent using openbb functions A simple notebook that shows how to leverage openbb functions by building an agent via langchain * added prompt for strong buy in utilities * added prompt for strong buy in utilities * Simplified notebook --------- Co-authored-by: Danglewood <85772166+deeleeramone@users.noreply.github.com> Co-authored-by: Theodore Aptekarev <aptekarev@gmail.com>
This commit is contained in:
384
examples/openbb_vs_langchain.ipynb
vendored
Normal file
384
examples/openbb_vs_langchain.ipynb
vendored
Normal file
@@ -0,0 +1,384 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "0PSrErguxVcn"
|
||||
},
|
||||
"source": [
|
||||
"### Brief Description\n",
|
||||
"\n",
|
||||
"This notebook shows few examples on how to leverage OpenBB functionality via an Agent built with Langchain.\n",
|
||||
"It requires the user to have\n",
|
||||
"- an OpenAI Key. This is required as OpenAI is used as LLM\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"For help on how to configure Colab Secrets, please refer to this article\n",
|
||||
"https://margaretmz.medium.com/use-colab-secrets-to-store-kaggle-api-key-b57c7464f9fa\n",
|
||||
"\n",
|
||||
"This work was inspired by examples from this repo https://github.com/AlgoTrading101/Magentic-AlgoTrading101\n",
|
||||
"\n",
|
||||
"Functionality shown in this notebook is purely an example of what can be done.\n",
|
||||
"\n",
|
||||
"### Author\n",
|
||||
"Marco Mistroni"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### Installing dependencies"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "pw_DrWCXVijQ"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"!pip install openbb\n",
|
||||
"!pip install openbb-yfinance\n",
|
||||
"!pip install openbb-finviz\n",
|
||||
"!pip install langchain\n",
|
||||
"!pip install langchain_core\n",
|
||||
"!pip install langchain_openai\n"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "sNhm_dyvVlI1"
|
||||
},
|
||||
"execution_count": null,
|
||||
"outputs": []
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### Getting keys"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "Ua8Hmj2lWI6R"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"from google.colab import userdata\n",
|
||||
"OPENAI_KEY = userdata.get('OPENAI_KEY')"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "fTUdeQpdWL81"
|
||||
},
|
||||
"execution_count": null,
|
||||
"outputs": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "TEBnI33fxVcr"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import os\n",
|
||||
"from openbb import obb\n",
|
||||
"from langchain_openai import ChatOpenAI\n",
|
||||
"import logging\n",
|
||||
"from langchain.agents import tool\n",
|
||||
"from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder\n",
|
||||
"\n",
|
||||
"llm = ChatOpenAI(model=\"gpt-4.1\", temperature=0, openai_api_key=OPENAI_KEY)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "6zNCxSmOxVct"
|
||||
},
|
||||
"source": [
|
||||
"### OpenBB Useful functions"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "28N-T7aIxVcu"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"@tool\n",
|
||||
"def get_industry_performance() -> list:\n",
|
||||
" \"\"\" Return performance by industry for last week, last month, last quarter, last half year and last year\"\"\"\n",
|
||||
" return obb.equity.compare.groups(group='industry', metric='performance').to_llm()\n",
|
||||
"\n",
|
||||
"@tool\n",
|
||||
"def get_strong_buy_for_sector(sector : str) -> list :\n",
|
||||
" \"\"\" Return the strong buy recommendation for a given sector\"\"\"\n",
|
||||
" new_sector = '_'.join(sector.lower().split()).lower()\n",
|
||||
" data = obb.equity.screener(provider='finviz', sector=new_sector, recommendation='buy')\n",
|
||||
" return data.to_llm()\n",
|
||||
"\n",
|
||||
"@tool\n",
|
||||
"def get_strong_buy_for_industry(industry : str) -> list :\n",
|
||||
" \"\"\" Return the strong buy recommendation for a given industry\"\"\"\n",
|
||||
" data = obb.equity.screener(provider='finviz', industry=industry, recommendation='buy')\n",
|
||||
" return data.to_llm()\n",
|
||||
"\n",
|
||||
"@tool\n",
|
||||
"def get_best_stock_performers_for_sector(sector:str) -> list :\n",
|
||||
" \"\"\" Return the best 5 stock performers for last week and last month for a given sector\"\"\"\n",
|
||||
" data = obb.equity.screener(provider='finviz', filters_dict={'Sector' : sector, 'Performance' : 'Week Up', 'Performance 2' : 'Month Up'}, limit=5)\n",
|
||||
" return data.to_llm()\n",
|
||||
"\n",
|
||||
"@tool\n",
|
||||
"def get_best_stock_performers_for_industry(industry:str) -> list :\n",
|
||||
" \"\"\" Return the best 5 stock performers for last week and last month for an industry\"\"\"\n",
|
||||
" data = obb.equity.screener(provider='finviz', filters_dict={'Industry' : industry, 'Performance' : 'Week Up', 'Performance 2' : 'Month Up'}, limit=3)\n",
|
||||
" return data.to_llm()\n",
|
||||
"\n",
|
||||
"@tool\n",
|
||||
"def get_candidate_stocks_to_invest_relaxed(industry:str) -> list:\n",
|
||||
" ''' Use relaxed criteria to find best companies in an industry which are worth investing into'''\n",
|
||||
" desc_filters = {\n",
|
||||
" 'Market Cap.': '+Small (over $300mln)',\n",
|
||||
" 'Average Volume': 'Over 200K',\n",
|
||||
" }\n",
|
||||
" fund_filters = {\n",
|
||||
" 'InstitutionalOwnership': 'Under 60%',\n",
|
||||
" 'Current Ratio' : 'Over 1.5',\n",
|
||||
" 'Debt/Equity' : 'Over 0.3',\n",
|
||||
" #'EPS growthnext 5 years' : 'Positive (>0%)',\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
" desc_filters.update(fund_filters)\n",
|
||||
"\n",
|
||||
" try:\n",
|
||||
" data = obb.equity.screener(provider='finviz', industry='semiconductors',\n",
|
||||
" filters_dict=desc_filters\n",
|
||||
" )\n",
|
||||
" return data.to_llm()\n",
|
||||
" except Exception as e:\n",
|
||||
" logging.info(f'No data found:{str(e)}')\n",
|
||||
" return []\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"@tool\n",
|
||||
"def get_valuation_for_industries(input:str) -> list:\n",
|
||||
" \"\"\" Return valuation metrics for the industry provided as input\"\"\"\n",
|
||||
" data = obb.equity.compare.groups(group='industry', metric='valuation', provider='finviz').to_df()\n",
|
||||
" filtered = data[data.name == input]\n",
|
||||
" return filtered.to_json(\n",
|
||||
" orient=\"records\",\n",
|
||||
" date_format=\"iso\",\n",
|
||||
" date_unit=\"s\",\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
"@tool\n",
|
||||
"def get_consensus(ticker:str) -> list:\n",
|
||||
" \"\"\" Return analyst consensus for the ticker provided\n",
|
||||
" It returns the following fields:\n",
|
||||
" - target_high: float, High target of the price target consensus.\n",
|
||||
" - target_low: float Low target of the price target consensus.\n",
|
||||
" - target_consensus: float Consensus target of the price target consensus.\n",
|
||||
" - target_median: float Median target of the price target consensus\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" \"\"\"\n",
|
||||
" data = obb.equity.estimates.consensus(symbol=ticker, limit=3, provider='yfinance').to_df()\n",
|
||||
" return data.to_json(\n",
|
||||
" orient=\"records\",\n",
|
||||
" date_format=\"iso\",\n",
|
||||
" date_unit=\"s\",\n",
|
||||
" )\n",
|
||||
"\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "1hXQnSGFxVcv"
|
||||
},
|
||||
"source": [
|
||||
"### Chat Memory"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "YBF6S6DxxVcv"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from langchain_core.prompts import MessagesPlaceholder\n",
|
||||
"from langchain.memory import ConversationTokenBufferMemory\n",
|
||||
"from langchain.agents.format_scratchpad.openai_tools import (\n",
|
||||
" format_to_openai_tool_messages,\n",
|
||||
")\n",
|
||||
"from langchain.agents.output_parsers.openai_tools import OpenAIToolsAgentOutputParser\n",
|
||||
"from langchain_core.output_parsers import StrOutputParser, CommaSeparatedListOutputParser\n",
|
||||
"from langchain.agents import AgentExecutor\n",
|
||||
"from langchain_core.messages import AIMessage, HumanMessage\n",
|
||||
"\n",
|
||||
"MEMORY_KEY = \"chat_history\"\n",
|
||||
"prompt = ChatPromptTemplate.from_messages(\n",
|
||||
" [\n",
|
||||
" (\n",
|
||||
" \"system\",\n",
|
||||
" \"\"\" You are very powerful stock financial researcher.\n",
|
||||
" You will take the user questions and answer using the tools available.\n",
|
||||
" Once you have the information you need, you will answer user's questions using the data returned.\n",
|
||||
" Use the following tools to answer user queries:\n",
|
||||
" - get_strong_buy_for_sector to find strong buy recommendations for a sector\n",
|
||||
" - get_strong_buy_for_industry to find strong buy recommendations for an industry\n",
|
||||
" - get_industry_performance to find the performance for an industry\n",
|
||||
" - get_valuation_for_industries to find valuation metrics for industries\n",
|
||||
" - get_candidate_stocks_to_invest_relaxed to fetch all companies using relaxed criteria\n",
|
||||
" - def get_consensus(ticker:str) - to find analyst consensus for a company\n",
|
||||
" You should call each function only once, and you should not call the function if you already have the information you need.\n",
|
||||
" \"\"\",\n",
|
||||
" ),\n",
|
||||
" MessagesPlaceholder(variable_name=MEMORY_KEY),\n",
|
||||
" (\"user\", \"{input}\"),\n",
|
||||
" MessagesPlaceholder(variable_name=\"agent_scratchpad\"),\n",
|
||||
" ]\n",
|
||||
")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "1yrlv9jUxVcw"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"tools = [get_industry_performance, get_strong_buy_for_sector, get_strong_buy_for_industry, get_best_stock_performers_for_industry, get_valuation_for_industries,\n",
|
||||
" get_candidate_stocks_to_invest_relaxed, get_consensus]\n",
|
||||
"llm_with_tools = llm.bind_tools(tools)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "ToVLUWZfxVcw"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"chat_history = []\n",
|
||||
"chat_history.append(HumanMessage(content=\"Your question here\"))\n",
|
||||
"chat_history.append(AIMessage(content=\"AI response here\"))\n",
|
||||
"memory = ConversationTokenBufferMemory(\n",
|
||||
" llm=llm, # Required for token counting\n",
|
||||
" max_token_limit=16000, # Leave buffer for functions + responses\n",
|
||||
" memory_key=\"chat_history\", # Must match your prompt's key\n",
|
||||
" return_messages=True\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"agent = (\n",
|
||||
" {\n",
|
||||
" \"input\": lambda x: x[\"input\"],\n",
|
||||
" \"agent_scratchpad\": lambda x: format_to_openai_tool_messages(\n",
|
||||
" x[\"intermediate_steps\"]\n",
|
||||
" ),\n",
|
||||
" \"chat_history\": lambda x: memory.load_memory_variables(x)[\"chat_history\"],\n",
|
||||
" }\n",
|
||||
" | prompt\n",
|
||||
" | llm_with_tools\n",
|
||||
" | OpenAIToolsAgentOutputParser()\n",
|
||||
")\n",
|
||||
"agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "kbFXeyMUxVcy"
|
||||
},
|
||||
"source": [
|
||||
"### Let's try a chain of thought approach. We start with the industry with best performance.\n",
|
||||
"Then find the best performing company and check some metrics"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "MlAvYHU0xVcy"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"input1 = '''\n",
|
||||
"First, find an industry that has consistently shown positive performance across quarterly, monthly, and weekly timeframes.\n",
|
||||
"Second, once you have identified the industry, extract its relevant valuation metrics (e.g., P/E, P/B, EV/EBITDA).\n",
|
||||
"Third, extract companies from the selected industry using relaxed criteria.\n",
|
||||
"Fourth, for the best performing companies get the analyst consensus\n",
|
||||
"Finally, summarize your findings in no more than 80 words detailing:\n",
|
||||
"- Best performing industry\n",
|
||||
"- Best performing companies in industry\n",
|
||||
"- A table displaying the analyst consensus for each of the companies you found at previous step'''\n",
|
||||
"result = agent_executor.invoke({\"input\": input1, \"chat_history\": chat_history})\n",
|
||||
"print(result['output'])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "au-Qbu9KxVcy"
|
||||
},
|
||||
"source": [
|
||||
"### Finding strong buys in the Utilities sector "
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"input1 = '''\n",
|
||||
"First, find the stocks recommended fro strong buy in the Utilities Sector\n",
|
||||
"Second, find the valuation metrics for this stock.\n",
|
||||
"Third, summarize your findings in a short paragraph.\n",
|
||||
"'''\n",
|
||||
"result = agent_executor.invoke({\"input\": input1, \"chat_history\": chat_history})\n",
|
||||
"print(result['output'])"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "doUw61HPU6fR"
|
||||
},
|
||||
"execution_count": null,
|
||||
"outputs": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [],
|
||||
"metadata": {
|
||||
"id": "rc7X4Ep4VNbS"
|
||||
},
|
||||
"execution_count": null,
|
||||
"outputs": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "myenv",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.12.1"
|
||||
},
|
||||
"colab": {
|
||||
"provenance": []
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 0
|
||||
}
|
||||
Reference in New Issue
Block a user