mirror of
https://github.com/hwchase17/langchain.git
synced 2025-07-15 17:33:53 +00:00
*Description:** Updates the YahooFinanceNewsTool to handle the current yfinance news data structure. The tool was failing with a KeyError due to changes in the yfinance API's response format. This PR updates the code to correctly extract news URLs from the new structure. **Issue:** #29495 **Dependencies:** No new dependencies required. Works with existing yfinance package. The changes maintain backwards compatibility while fixing the KeyError that users were experiencing. The modified code properly handles the new data structure where: - News type is now at `content.contentType` - News URL is now at `content.canonicalUrl.url` --------- Co-authored-by: Chester Curme <chester.curme@gmail.com>
91 lines
3.1 KiB
Python
91 lines
3.1 KiB
Python
from typing import Iterable, Optional, Type
|
|
|
|
from langchain_core.callbacks import CallbackManagerForToolRun
|
|
from langchain_core.documents import Document
|
|
from langchain_core.tools import BaseTool
|
|
from pydantic import BaseModel, Field
|
|
from requests.exceptions import HTTPError, ReadTimeout
|
|
from urllib3.exceptions import ConnectionError
|
|
|
|
from langchain_community.document_loaders.web_base import WebBaseLoader
|
|
|
|
|
|
class YahooFinanceNewsInput(BaseModel):
|
|
"""Input for the YahooFinanceNews tool."""
|
|
|
|
query: str = Field(description="company ticker query to look up")
|
|
|
|
|
|
class YahooFinanceNewsTool(BaseTool): # type: ignore[override, override]
|
|
"""Tool that searches financial news on Yahoo Finance."""
|
|
|
|
name: str = "yahoo_finance_news"
|
|
description: str = (
|
|
"Useful for when you need to find financial news "
|
|
"about a public company. "
|
|
"Input should be a company ticker. "
|
|
"For example, AAPL for Apple, MSFT for Microsoft."
|
|
)
|
|
top_k: int = 10
|
|
"""The number of results to return."""
|
|
|
|
args_schema: Type[BaseModel] = YahooFinanceNewsInput
|
|
|
|
def _run(
|
|
self,
|
|
query: str,
|
|
run_manager: Optional[CallbackManagerForToolRun] = None,
|
|
) -> str:
|
|
"""
|
|
Use the Yahoo Finance News tool.
|
|
|
|
Args:
|
|
query: Company ticker symbol (e.g., 'AAPL' for Apple).
|
|
run_manager: Optional callback manager.
|
|
|
|
Returns:
|
|
str: Formatted news results or error message.
|
|
"""
|
|
try:
|
|
import yfinance
|
|
except ImportError:
|
|
raise ImportError(
|
|
"Could not import yfinance python package. "
|
|
"Please install it with `pip install yfinance`."
|
|
)
|
|
company = yfinance.Ticker(query)
|
|
try:
|
|
if company.isin is None:
|
|
return f"Company ticker {query} not found."
|
|
except (HTTPError, ReadTimeout, ConnectionError):
|
|
return f"Company ticker {query} not found."
|
|
|
|
links = []
|
|
try:
|
|
links = [
|
|
n["content"]["canonicalUrl"]["url"]
|
|
for n in company.news
|
|
if n["content"]["contentType"] == "STORY"
|
|
]
|
|
except (HTTPError, ReadTimeout, ConnectionError):
|
|
if not links:
|
|
return f"No news found for company that searched with {query} ticker."
|
|
if not links:
|
|
return f"No news found for company that searched with {query} ticker."
|
|
loader = WebBaseLoader(web_paths=links)
|
|
docs = loader.load()
|
|
result = self._format_results(docs, query)
|
|
if not result:
|
|
return f"No news found for company that searched with {query} ticker."
|
|
return result
|
|
|
|
@staticmethod
|
|
def _format_results(docs: Iterable[Document], query: str) -> str:
|
|
doc_strings = [
|
|
"\n".join([doc.metadata["title"], doc.metadata.get("description", "")])
|
|
for doc in docs
|
|
if query in doc.metadata.get("description", "")
|
|
or query in doc.metadata["title"]
|
|
]
|
|
return "\n\n".join(doc_strings)
|