diff --git a/llama-index-integrations/tools/llama-index-tools-brave-search/.gitignore b/llama-index-integrations/tools/llama-index-tools-brave-search/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..990c18de229088f55c6c514fd0f2d49981d1b0e7 --- /dev/null +++ b/llama-index-integrations/tools/llama-index-tools-brave-search/.gitignore @@ -0,0 +1,153 @@ +llama_index/_static +.DS_Store +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +bin/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +etc/ +include/ +lib/ +lib64/ +parts/ +sdist/ +share/ +var/ +wheels/ +pip-wheel-metadata/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +.ruff_cache + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints +notebooks/ + +# IPython +profile_default/ +ipython_config.py + +# pyenv +.python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ +pyvenv.cfg + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# Jetbrains +.idea +modules/ +*.swp + +# VsCode +.vscode + +# pipenv +Pipfile +Pipfile.lock + +# pyright +pyrightconfig.json diff --git a/llama-index-integrations/tools/llama-index-tools-brave-search/BUILD b/llama-index-integrations/tools/llama-index-tools-brave-search/BUILD new file mode 100644 index 0000000000000000000000000000000000000000..0896ca890d8bffd60a44fa824f8d57fecd73ee53 --- /dev/null +++ b/llama-index-integrations/tools/llama-index-tools-brave-search/BUILD @@ -0,0 +1,3 @@ +poetry_requirements( + name="poetry", +) diff --git a/llama-index-integrations/tools/llama-index-tools-brave-search/Makefile b/llama-index-integrations/tools/llama-index-tools-brave-search/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..b9eab05aa370629a4a3de75df3ff64cd53887b68 --- /dev/null +++ b/llama-index-integrations/tools/llama-index-tools-brave-search/Makefile @@ -0,0 +1,17 @@ +GIT_ROOT ?= $(shell git rev-parse --show-toplevel) + +help: ## Show all Makefile targets. + @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[33m%-30s\033[0m %s\n", $$1, $$2}' + +format: ## Run code autoformatters (black). + pre-commit install + git ls-files | xargs pre-commit run black --files + +lint: ## Run linters: pre-commit (black, ruff, codespell) and mypy + pre-commit install && git ls-files | xargs pre-commit run --show-diff-on-failure --files + +test: ## Run tests via pytest. + pytest tests + +watch-docs: ## Build and watch documentation. + sphinx-autobuild docs/ docs/_build/html --open-browser --watch $(GIT_ROOT)/llama_index/ diff --git a/llama-index-integrations/tools/llama-index-tools-brave-search/README.md b/llama-index-integrations/tools/llama-index-tools-brave-search/README.md new file mode 100644 index 0000000000000000000000000000000000000000..1a14496786f4166beafa81c9e50e28173c1521e0 --- /dev/null +++ b/llama-index-integrations/tools/llama-index-tools-brave-search/README.md @@ -0,0 +1,24 @@ +# LlamaIndex Tools Integration: Brave_Search + +This tool enables agents to search and retrieve results from the Brave search engine. + +You will need to set up an Brave account to get an search api key. Please check more here: https://brave.com/search/api + +## Usage + +This tool has a more extensive example usage documented in a Jupyter notebook [here](./examples/brave_search.ipynb) + +Here's an example usage of the BraveSearchToolSpec. + +```python +from llama_index.tools.brave_search import BraveSearchToolSpec +from llama_index.agent.openai import OpenAIAgent + +tool_spec = BraveSearchToolSpec(api_key="your-key") + +agent = OpenAIAgent.from_tools(tool_spec.to_tool_list()) + +agent.chat("what's the latest news about superconductors") +agent.chat("what does lk-99 look like") +agent.chat("is there any videos of it levitating") +``` diff --git a/llama-index-integrations/tools/llama-index-tools-brave-search/examples/brave_search.ipynb b/llama-index-integrations/tools/llama-index-tools-brave-search/examples/brave_search.ipynb new file mode 100644 index 0000000000000000000000000000000000000000..e1a7794a2f02475737e699b77c2722f001bf6437 --- /dev/null +++ b/llama-index-integrations/tools/llama-index-tools-brave-search/examples/brave_search.ipynb @@ -0,0 +1,54 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Setup OpenAI Agent\n", + "import openai\n", + "\n", + "openai.api_key = \"sk-xxx\"\n", + "from llama_index.agent.openai import OpenAIAgent" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from llama_index.tools.brave_search.base import BraveSearchToolSpec\n", + "\n", + "brave_tool = BraveSearchToolSpec(api_key=\"your-api-key\")\n", + "agent = OpenAIAgent.from_tools(\n", + " brave_tool.to_tool_list(),\n", + " verbose=True,\n", + ")\n", + "\n", + "print(agent.chat(\"whats the latest news about superconductors\"))" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "app-aCoYrWM5-py3.11", + "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" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/llama-index-integrations/tools/llama-index-tools-brave-search/llama_index/tools/brave_search/BUILD b/llama-index-integrations/tools/llama-index-tools-brave-search/llama_index/tools/brave_search/BUILD new file mode 100644 index 0000000000000000000000000000000000000000..db46e8d6c978c67e301dd6c47bee08c1b3fd141c --- /dev/null +++ b/llama-index-integrations/tools/llama-index-tools-brave-search/llama_index/tools/brave_search/BUILD @@ -0,0 +1 @@ +python_sources() diff --git a/llama-index-integrations/tools/llama-index-tools-brave-search/llama_index/tools/brave_search/__init__.py b/llama-index-integrations/tools/llama-index-tools-brave-search/llama_index/tools/brave_search/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..9a13ac6fe826c298ed4e4f64542e5bdefa3a538c --- /dev/null +++ b/llama-index-integrations/tools/llama-index-tools-brave-search/llama_index/tools/brave_search/__init__.py @@ -0,0 +1,4 @@ +## init +from llama_index.tools.brave_search.base import BraveSearchToolSpec + +__all__ = ["BraveSearchToolSpec"] diff --git a/llama-index-integrations/tools/llama-index-tools-brave-search/llama_index/tools/brave_search/base.py b/llama-index-integrations/tools/llama-index-tools-brave-search/llama_index/tools/brave_search/base.py new file mode 100644 index 0000000000000000000000000000000000000000..c6a99dd065ddba9f2eef9f49dca96c44b6cb40e8 --- /dev/null +++ b/llama-index-integrations/tools/llama-index-tools-brave-search/llama_index/tools/brave_search/base.py @@ -0,0 +1,65 @@ +import requests +import urllib.parse +from typing import Dict +from llama_index.core.schema import Document +from llama_index.core.tools.tool_spec.base import BaseToolSpec + +SEARCH_URL_TMPL = "https://api.search.brave.com/res/v1/web/search?{params}" + + +class BraveSearchToolSpec(BaseToolSpec): + """ + Brave Search tool spec. + """ + + spec_functions = ["brave_search"] + + def __init__(self, api_key: str) -> None: + """ + Initialize with parameters. + """ + self.api_key = api_key + + def _make_request(self, params: Dict) -> requests.Response: + """ + Make a request to the Brave Search API. + + Args: + params (dict): The parameters to be passed to the API. + + Returns: + requests.Response: The response from the API. + """ + headers = { + "Accept": "application/json", + "Accept-Encoding": "gzip", + "X-Subscription-Token": self.api_key, + } + url = SEARCH_URL_TMPL.format(params=urllib.parse.urlencode(params)) + + response = requests.get(url, headers=headers) + response.raise_for_status() + return response + + def brave_search( + self, query: str, search_lang: str = "en", num_results: int = 5 + ) -> [Document]: + """ + Make a query to the Brave Search engine to receive a list of results. + + Args: + query (str): The query to be passed to Brave Search. + search_lang (str): The search language preference (ISO 639-1), default is "en". + num_results (int): The number of search results returned in response, default is 5. + + Returns: + [Document]: A list of documents containing search results. + """ + search_params = { + "q": query, + "search_lang": search_lang, + "count": num_results, + } + + response = self._make_request(search_params) + return [Document(text=response.text)] diff --git a/llama-index-integrations/tools/llama-index-tools-brave-search/pyproject.toml b/llama-index-integrations/tools/llama-index-tools-brave-search/pyproject.toml new file mode 100644 index 0000000000000000000000000000000000000000..fb8e44f548c73f73809ea06b38b11b46fa625c38 --- /dev/null +++ b/llama-index-integrations/tools/llama-index-tools-brave-search/pyproject.toml @@ -0,0 +1,57 @@ +[build-system] +build-backend = "poetry.core.masonry.api" +requires = ["poetry-core"] + +[tool.codespell] +check-filenames = true +check-hidden = true +# Feel free to un-skip examples, and experimental, you will just need to +# work through many typos (--write-changes and --interactive will help) +skip = "*.csv,*.html,*.json,*.jsonl,*.pdf,*.txt,*.ipynb" + +[tool.llamahub] +contains_example = false +import_path = "llama_index.tools.brave_search" + +[tool.llamahub.class_authors] +BraveSearchToolSpec = "leehuwuj" + +[tool.mypy] +disallow_untyped_defs = true +# Remove venv skip when integrated with pre-commit +exclude = ["_static", "build", "examples", "notebooks", "venv"] +ignore_missing_imports = true +python_version = "3.8" + +[tool.poetry] +authors = ["Your Name <you@example.com>"] +description = "llama-index tools brave_search integration" +exclude = ["**/BUILD"] +license = "MIT" +name = "llama-index-tools-brave-search" +packages = [{include = "llama_index/"}] +readme = "README.md" +version = "0.1.0" + +[tool.poetry.dependencies] +python = ">=3.8.1,<4.0" +llama-index-core = "^0.10.0" + +[tool.poetry.group.dev.dependencies] +black = {extras = ["jupyter"], version = "<=23.9.1,>=23.7.0"} +codespell = {extras = ["toml"], version = ">=v2.2.6"} +ipython = "8.10.0" +jupyter = "^1.0.0" +mypy = "0.991" +pre-commit = "3.2.0" +pylint = "2.15.10" +pytest = "7.2.1" +pytest-mock = "3.11.1" +ruff = "0.0.292" +tree-sitter-languages = "^1.8.0" +types-Deprecated = ">=0.1.0" +types-PyYAML = "^6.0.12.12" +types-protobuf = "^4.24.0.4" +types-redis = "4.5.5.0" +types-requests = "2.28.11.8" # TODO: unpin when mypy>0.991 +types-setuptools = "67.1.0.0" diff --git a/llama-index-integrations/tools/llama-index-tools-brave-search/tests/BUILD b/llama-index-integrations/tools/llama-index-tools-brave-search/tests/BUILD new file mode 100644 index 0000000000000000000000000000000000000000..dabf212d7e7162849c24a733909ac4f645d75a31 --- /dev/null +++ b/llama-index-integrations/tools/llama-index-tools-brave-search/tests/BUILD @@ -0,0 +1 @@ +python_tests() diff --git a/llama-index-integrations/tools/llama-index-tools-brave-search/tests/__init__.py b/llama-index-integrations/tools/llama-index-tools-brave-search/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/llama-index-integrations/tools/llama-index-tools-brave-search/tests/test_tools_brave_search.py b/llama-index-integrations/tools/llama-index-tools-brave-search/tests/test_tools_brave_search.py new file mode 100644 index 0000000000000000000000000000000000000000..facf7837ce8d94de304e82a77b963ffc0c4cbef1 --- /dev/null +++ b/llama-index-integrations/tools/llama-index-tools-brave-search/tests/test_tools_brave_search.py @@ -0,0 +1,7 @@ +from llama_index.core.tools.tool_spec.base import BaseToolSpec +from llama_index.tools.brave_search import BraveSearchToolSpec + + +def test_class(): + names_of_base_classes = [b.__name__ for b in BraveSearchToolSpec.__mro__] + assert BaseToolSpec.__name__ in names_of_base_classes