add youtube tools (#4320)

This commit is contained in:
Harrison Chase 2023-05-08 08:29:30 -07:00 committed by GitHub
parent 1d1166ded6
commit c8b0b6e6c1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 188 additions and 1 deletions

View File

@ -0,0 +1,125 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "acb64858",
"metadata": {},
"source": [
"# YouTubeSearchTool\n",
"\n",
"This notebook shows how to use a tool to search YouTube\n",
"\n",
"Adapted from [https://github.com/venuv/langchain_yt_tools](https://github.com/venuv/langchain_yt_tools)"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "9bb15d4a",
"metadata": {},
"outputs": [],
"source": [
"#! pip install youtube_search"
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "cc1c83e2",
"metadata": {},
"outputs": [],
"source": [
"from langchain.tools import YouTubeSearchTool"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "becb262b",
"metadata": {},
"outputs": [],
"source": [
"tool = YouTubeSearchTool()"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "6bbc4211",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"\"['/watch?v=VcVfceTsD0A&pp=ygUMbGV4IGZyaWVkbWFu', '/watch?v=gPfriiHBBek&pp=ygUMbGV4IGZyaWVkbWFu']\""
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"tool.run(\"lex friedman\")"
]
},
{
"cell_type": "markdown",
"id": "7f772147",
"metadata": {},
"source": [
"You can also specify the number of results that are returned"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "682fdb33",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"\"['/watch?v=VcVfceTsD0A&pp=ygUMbGV4IGZyaWVkbWFu', '/watch?v=YVJ8gTnDC4Y&pp=ygUMbGV4IGZyaWVkbWFu', '/watch?v=Udh22kuLebg&pp=ygUMbGV4IGZyaWVkbWFu', '/watch?v=gPfriiHBBek&pp=ygUMbGV4IGZyaWVkbWFu', '/watch?v=L_Guz73e6fw&pp=ygUMbGV4IGZyaWVkbWFu']\""
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"tool.run(\"lex friedman,5\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "bb5e1659",
"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.9.1"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

View File

@ -35,6 +35,7 @@ from langchain.tools.vectorstore.tool import (
) )
from langchain.tools.wikipedia.tool import WikipediaQueryRun from langchain.tools.wikipedia.tool import WikipediaQueryRun
from langchain.tools.wolfram_alpha.tool import WolframAlphaQueryRun from langchain.tools.wolfram_alpha.tool import WolframAlphaQueryRun
from langchain.tools.youtube.search import YouTubeSearchTool
from langchain.tools.zapier.tool import ZapierNLAListActions, ZapierNLARunAction from langchain.tools.zapier.tool import ZapierNLAListActions, ZapierNLARunAction
__all__ = [ __all__ = [
@ -80,4 +81,5 @@ __all__ = [
"ZapierNLAListActions", "ZapierNLAListActions",
"ZapierNLARunAction", "ZapierNLARunAction",
"tool", "tool",
"YouTubeSearchTool",
] ]

View File

View File

@ -0,0 +1,59 @@
"""
Adapted from https://github.com/venuv/langchain_yt_tools
CustomYTSearchTool searches YouTube videos related to a person
and returns a specified number of video URLs.
Input to this tool should be a comma separated list,
- the first part contains a person name
- and the second(optional) a number that is the
maximum number of video results to return
"""
import json
from typing import Optional
from langchain.callbacks.manager import (
AsyncCallbackManagerForToolRun,
CallbackManagerForToolRun,
)
from langchain.tools import BaseTool
class YouTubeSearchTool(BaseTool):
name = "YouTubeSearch"
description = (
"search for youtube videos associated with a person. "
"the input to this tool should be a comma separated list, "
"the first part contains a person name and the second a "
"number that is the maximum number of video results "
"to return aka num_results. the second part is optional"
)
def _search(self, person: str, num_results: int) -> str:
from youtube_search import YoutubeSearch
results = YoutubeSearch(person, num_results).to_json()
data = json.loads(results)
url_suffix_list = [video["url_suffix"] for video in data["videos"]]
return str(url_suffix_list)
def _run(
self,
query: str,
run_manager: Optional[CallbackManagerForToolRun] = None,
) -> str:
"""Use the tool."""
values = query.split(",")
person = values[0]
if len(values) > 1:
num_results = int(values[1])
else:
num_results = 2
return self._search(person, num_results)
async def _arun(
self,
query: str,
run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
) -> str:
"""Use the tool asynchronously."""
raise NotImplementedError("YouTubeSearchTool does not yet support async")

View File

@ -44,10 +44,11 @@ _EXPECTED = [
"ZapierNLAListActions", "ZapierNLAListActions",
"ZapierNLARunAction", "ZapierNLARunAction",
"tool", "tool",
"YouTubeSearchTool",
] ]
def test_public_api() -> None: def test_public_api() -> None:
"""Test for regressions or changes in the public API.""" """Test for regressions or changes in the public API."""
# Check that the public API is as expected # Check that the public API is as expected
assert public_api == sorted(_EXPECTED) assert sorted(public_api) == sorted(_EXPECTED)