You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
langchain/libs/community/langchain_community/utilities/asknews.py

116 lines
3.5 KiB
Python

community[minor]: add AskNews retriever and AskNews tool (#21581) We add a tool and retriever for the [AskNews](https://asknews.app) platform with example notebooks. The retriever can be invoked with: ```py from langchain_community.retrievers import AskNewsRetriever retriever = AskNewsRetriever(k=3) retriever.invoke("impact of fed policy on the tech sector") ``` To retrieve 3 documents in then news related to fed policy impacts on the tech sector. The included notebook also includes deeper details about controlling filters such as category and time, as well as including the retriever in a chain. The tool is quite interesting, as it allows the agent to decide how to obtain the news by forming a query and deciding how far back in time to look for the news: ```py from langchain_community.tools.asknews import AskNewsSearch from langchain import hub from langchain.agents import AgentExecutor, create_openai_functions_agent from langchain_openai import ChatOpenAI tool = AskNewsSearch() instructions = """You are an assistant.""" base_prompt = hub.pull("langchain-ai/openai-functions-template") prompt = base_prompt.partial(instructions=instructions) llm = ChatOpenAI(temperature=0) asknews_tool = AskNewsSearch() tools = [asknews_tool] agent = create_openai_functions_agent(llm, tools, prompt) agent_executor = AgentExecutor( agent=agent, tools=tools, verbose=True, ) agent_executor.invoke({"input": "How is the tech sector being affected by fed policy?"}) ``` --------- Co-authored-by: Emre <e@emre.pm>
4 months ago
"""Util that calls AskNews api."""
from __future__ import annotations
from datetime import datetime, timedelta
from typing import Any, Dict, Optional
from langchain_core.pydantic_v1 import BaseModel, Extra, root_validator
from langchain_core.utils import get_from_dict_or_env
class AskNewsAPIWrapper(BaseModel):
"""Wrapper for AskNews API."""
asknews_sync: Any #: :meta private:
asknews_async: Any #: :meta private:
asknews_client_id: Optional[str] = None
"""Client ID for the AskNews API."""
asknews_client_secret: Optional[str] = None
"""Client Secret for the AskNews API."""
class Config:
"""Configuration for this pydantic object."""
extra = Extra.forbid
@root_validator()
def validate_environment(cls, values: Dict) -> Dict:
"""Validate that api credentials and python package exists in environment."""
asknews_client_id = get_from_dict_or_env(
values, "asknews_client_id", "ASKNEWS_CLIENT_ID"
)
asknews_client_secret = get_from_dict_or_env(
values, "asknews_client_secret", "ASKNEWS_CLIENT_SECRET"
)
try:
import asknews_sdk
except ImportError:
raise ImportError(
"AskNews python package not found. "
"Please install it with `pip install asknews`."
)
an_sync = asknews_sdk.AskNewsSDK(
client_id=asknews_client_id,
client_secret=asknews_client_secret,
scopes=["news"],
)
an_async = asknews_sdk.AsyncAskNewsSDK(
client_id=asknews_client_id,
client_secret=asknews_client_secret,
scopes=["news"],
)
values["asknews_sync"] = an_sync
values["asknews_async"] = an_async
values["asknews_client_id"] = asknews_client_id
values["asknews_client_secret"] = asknews_client_secret
return values
def search_news(
self, query: str, max_results: int = 10, hours_back: int = 0
) -> str:
"""Search news in AskNews API synchronously."""
if hours_back > 48:
method = "kw"
historical = True
start = int((datetime.now() - timedelta(hours=hours_back)).timestamp())
stop = int(datetime.now().timestamp())
else:
historical = False
method = "nl"
start = None
stop = None
response = self.asknews_sync.news.search_news(
query=query,
n_articles=max_results,
method=method,
historical=historical,
start_timestamp=start,
end_timestamp=stop,
return_type="string",
)
return response.as_string
async def asearch_news(
self, query: str, max_results: int = 10, hours_back: int = 0
) -> str:
"""Search news in AskNews API asynchronously."""
if hours_back > 48:
method = "kw"
historical = True
start = int((datetime.now() - timedelta(hours=hours_back)).timestamp())
stop = int(datetime.now().timestamp())
else:
historical = False
method = "nl"
start = None
stop = None
response = await self.asknews_async.news.search_news(
query=query,
n_articles=max_results,
method=method,
historical=historical,
start_timestamp=start,
end_timestamp=stop,
return_type="string",
)
return response.as_string