diff --git a/docs/modules/utils/examples/bing_search.ipynb b/docs/modules/utils/examples/bing_search.ipynb new file mode 100644 index 00000000..23c3abed --- /dev/null +++ b/docs/modules/utils/examples/bing_search.ipynb @@ -0,0 +1,140 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Bing Search" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This notebook goes over how to use the bing search component.\n", + "\n", + "First, you need to set up the proper API keys and environment variables. To set it up, follow the instructions found here.\n", + "\n", + "Then we will need to set some environment variables." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "os.environ[\"BING_SUBSCRIPTION_KEY\"] = \"\"" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "from langchain.utilities import BingSearchAPIWrapper" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "search = BingSearchAPIWrapper()" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'Thanks to the flexibility of Python and the powerful ecosystem of packages, the Azure CLI supports features such as autocompletion (in shells that support it), persistent credentials, JMESPath result parsing, lazy initialization, network-less unit tests, and more. Building an open-source and cross-platform Azure CLI with Python by Dan Taylor. Python Brochure. Python is a programming language that lets you work more quickly and integrate your systems more effectively. You can learn to use Python and see almost immediate gains in productivity and lower maintenance costs. Learn more about Python . Learning. Before getting started, you may want to find out which IDEs and text editors are tailored to make Python editing easy, browse the list of introductory books, or look at code samples that you might find helpful.. There is a list of tutorials suitable for experienced programmers on the BeginnersGuide/Tutorials page. There is also a list of resources in other languages which might be ... Python is a popular programming language. Python can be used on a server to create web applications. Start learning Python now ยป. With Python, you can use while loops to run the same task multiple times and for loops to loop once over list data. In this module, you'll learn about the two loop types and when to apply each. Manage data with Python dictionaries. Python dictionaries allow you to model complex data. This module explores common scenarios where you could use ... This module is part of these learning paths. Build real world applications with Python. Introduction 1 min. What is Python? 3 min. Use the REPL 2 min. Variables and basic data types in Python 4 min. Exercise - output 1 min. Reading keyboard input 3 min. Exercise - Build a calculator 1 min. Python's source code is freely available to the public, and its usage and distribution are unrestricted, including for commercial purposes. It is widely used for web development, and using it, practically anything can be created, including mobile apps, online apps, tools, data analytics, machine learning, and so on. ... Python is a high-level, general-purpose programming language. Its design philosophy emphasizes code readability with the use of significant indentation. Python is dynamically-typed and garbage-collected. It supports multiple programming paradigms, including structured (particularly procedural), object-oriented and functional programming.'" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "search.run(\"python\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Number of results\n", + "You can use the `k` parameter to set the number of results" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "search = BingSearchAPIWrapper(k=1)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'Thanks to the flexibility of Python and the powerful ecosystem of packages, the Azure CLI supports features such as autocompletion (in shells that support it), persistent credentials, JMESPath result parsing, lazy initialization, network-less unit tests, and more. Building an open-source and cross-platform Azure CLI with Python by Dan Taylor.'" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "search.run(\"python\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "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.10.9" + }, + "vscode": { + "interpreter": { + "hash": "a0a0263b650d907a3bfe41c0f8d6a63a071b884df3cfdc1579f00cdc1aed6b03" + } + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/langchain/utilities/__init__.py b/langchain/utilities/__init__.py index 797d64b0..0e7eff1d 100644 --- a/langchain/utilities/__init__.py +++ b/langchain/utilities/__init__.py @@ -3,6 +3,7 @@ from langchain.python import PythonREPL from langchain.requests import RequestsWrapper from langchain.serpapi import SerpAPIWrapper from langchain.utilities.bash import BashProcess +from langchain.utilities.bing_search import BingSearchAPIWrapper from langchain.utilities.google_search import GoogleSearchAPIWrapper from langchain.utilities.wolfram_alpha import WolframAlphaAPIWrapper @@ -13,4 +14,5 @@ __all__ = [ "GoogleSearchAPIWrapper", "WolframAlphaAPIWrapper", "SerpAPIWrapper", + "BingSearchAPIWrapper", ] diff --git a/langchain/utilities/bing_search.py b/langchain/utilities/bing_search.py new file mode 100644 index 00000000..936606ae --- /dev/null +++ b/langchain/utilities/bing_search.py @@ -0,0 +1,73 @@ +"""Util that calls Bing Search. + +In order to set this up, follow instructions at: +https://levelup.gitconnected.com/api-tutorial-how-to-use-bing-web-search-api-in-python-4165d5592a7e +""" +from typing import Dict, List + +import requests +from pydantic import BaseModel, Extra, root_validator + +from langchain.utils import get_from_dict_or_env + + +class BingSearchAPIWrapper(BaseModel): + """Wrapper for Bing Search API. + + In order to set this up, follow instructions at: + https://levelup.gitconnected.com/api-tutorial-how-to-use-bing-web-search-api-in-python-4165d5592a7e + """ + + bing_subscription_key: str + bing_search_url: str + k: int = 10 + + class Config: + """Configuration for this pydantic object.""" + + extra = Extra.forbid + + def _bing_search_results(self, search_term: str, count: int) -> List[dict]: + headers = {"Ocp-Apim-Subscription-Key": self.bing_subscription_key} + params = { + "q": search_term, + "count": count, + "textDecorations": True, + "textFormat": "HTML", + } + response = requests.get( + self.bing_search_url, headers=headers, params=params # type: ignore + ) + response.raise_for_status() + search_results = response.json() + return search_results["webPages"]["value"] + + @root_validator(pre=True) + def validate_environment(cls, values: Dict) -> Dict: + """Validate that api key and endpoint exists in environment.""" + bing_subscription_key = get_from_dict_or_env( + values, "bing_subscription_key", "BING_SUBSCRIPTION_KEY" + ) + values["bing_subscription_key"] = bing_subscription_key + + bing_search_url = get_from_dict_or_env( + values, + "bing_search_url", + "BING_SEARCH_URL", + default="https://api.bing.microsoft.com/v7.0/search", + ) + + values["bing_search_url"] = bing_search_url + + return values + + def run(self, query: str) -> str: + """Run query through BingSearch and parse result.""" + snippets = [] + results = self._bing_search_results(query, count=self.k) + if len(results) == 0: + return "No good Bing Search Result was found" + for result in results: + snippets.append(result["snippet"]) + + return " ".join(snippets) diff --git a/langchain/utils.py b/langchain/utils.py index 8588f4e9..08fa4327 100644 --- a/langchain/utils.py +++ b/langchain/utils.py @@ -1,14 +1,18 @@ """Generic utility functions.""" import os -from typing import Any, Dict +from typing import Any, Dict, Optional -def get_from_dict_or_env(data: Dict[str, Any], key: str, env_key: str) -> str: +def get_from_dict_or_env( + data: Dict[str, Any], key: str, env_key: str, default: Optional[str] = None +) -> str: """Get a value from a dictionary or an environment variable.""" if key in data and data[key]: return data[key] elif env_key in os.environ and os.environ[env_key]: return os.environ[env_key] + elif default is not None: + return default else: raise ValueError( f"Did not find {key}, please add an environment variable"