mirror of
https://github.com/hwchase17/langchain.git
synced 2025-04-28 03:51:50 +00:00
community: adds support for getting github releases for the configured repository (#29318)
**Description:** adds support for github tool to query github releases on the configure respository **Issue:** N/A **Dependencies:** N/A **Twitter handle:** @macsdickinson --------- Co-authored-by: Chester Curme <chester.curme@gmail.com>
This commit is contained in:
parent
ef1610e24a
commit
7378c955db
@ -200,6 +200,37 @@
|
||||
"8. **Delete File**- deletes a file from the repository."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Include release tools\n",
|
||||
"\n",
|
||||
"By default, the toolkit does not include release-related tools. You can include them by setting `include_release_tools=True` when initializing the toolkit:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"toolkit = GitHubToolkit.from_github_api_wrapper(github, include_release_tools=True)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Settings `include_release_tools=True` will include the following tools:\n",
|
||||
"\n",
|
||||
"* **Get Latest Release**- fetches the latest release from the repository.\n",
|
||||
"\n",
|
||||
"* **Get Releases**- fetches the latest 5 releases from the repository.\n",
|
||||
"\n",
|
||||
"* **Get Release**- fetches a specific release from the repository by tag name, e.g. `v1.0.0`.\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
@ -321,7 +352,7 @@
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.10.4"
|
||||
"version": "3.13.1"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
|
@ -16,7 +16,10 @@ from langchain_community.tools.github.prompt import (
|
||||
GET_FILES_FROM_DIRECTORY_PROMPT,
|
||||
GET_ISSUE_PROMPT,
|
||||
GET_ISSUES_PROMPT,
|
||||
GET_LATEST_RELEASE_PROMPT,
|
||||
GET_PR_PROMPT,
|
||||
GET_RELEASE_PROMPT,
|
||||
GET_RELEASES_PROMPT,
|
||||
LIST_BRANCHES_IN_REPO_PROMPT,
|
||||
LIST_PRS_PROMPT,
|
||||
LIST_PULL_REQUEST_FILES,
|
||||
@ -152,6 +155,15 @@ class SearchIssuesAndPRs(BaseModel):
|
||||
)
|
||||
|
||||
|
||||
class TagName(BaseModel):
|
||||
"""Schema for operations that require a tag name as input."""
|
||||
|
||||
tag_name: str = Field(
|
||||
...,
|
||||
description="The tag name of the release, e.g. `v1.0.0`.",
|
||||
)
|
||||
|
||||
|
||||
class GitHubToolkit(BaseToolkit):
|
||||
"""GitHub Toolkit.
|
||||
|
||||
@ -218,6 +230,25 @@ class GitHubToolkit(BaseToolkit):
|
||||
Search code
|
||||
Create review request
|
||||
|
||||
Include release tools:
|
||||
By default, the toolkit does not include release-related tools.
|
||||
You can include them by setting ``include_release_tools=True`` when
|
||||
initializing the toolkit:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
toolkit = GitHubToolkit.from_github_api_wrapper(
|
||||
github, include_release_tools=True
|
||||
)
|
||||
|
||||
Setting ``include_release_tools=True`` will include the following tools:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
Get latest release
|
||||
Get releases
|
||||
Get release
|
||||
|
||||
Use within an agent:
|
||||
.. code-block:: python
|
||||
|
||||
@ -268,12 +299,14 @@ class GitHubToolkit(BaseToolkit):
|
||||
|
||||
@classmethod
|
||||
def from_github_api_wrapper(
|
||||
cls, github_api_wrapper: GitHubAPIWrapper
|
||||
cls, github_api_wrapper: GitHubAPIWrapper, include_release_tools: bool = False
|
||||
) -> "GitHubToolkit":
|
||||
"""Create a GitHubToolkit from a GitHubAPIWrapper.
|
||||
|
||||
Args:
|
||||
github_api_wrapper: GitHubAPIWrapper. The GitHub API wrapper.
|
||||
include_release_tools: bool. Whether to include release-related tools.
|
||||
Defaults to False.
|
||||
|
||||
Returns:
|
||||
GitHubToolkit. The GitHub toolkit.
|
||||
@ -406,6 +439,29 @@ class GitHubToolkit(BaseToolkit):
|
||||
"args_schema": CreateReviewRequest,
|
||||
},
|
||||
]
|
||||
|
||||
release_operations: List[Dict] = [
|
||||
{
|
||||
"mode": "get_latest_release",
|
||||
"name": "Get latest release",
|
||||
"description": GET_LATEST_RELEASE_PROMPT,
|
||||
"args_schema": NoInput,
|
||||
},
|
||||
{
|
||||
"mode": "get_releases",
|
||||
"name": "Get releases",
|
||||
"description": GET_RELEASES_PROMPT,
|
||||
"args_schema": NoInput,
|
||||
},
|
||||
{
|
||||
"mode": "get_release",
|
||||
"name": "Get release",
|
||||
"description": GET_RELEASE_PROMPT,
|
||||
"args_schema": TagName,
|
||||
},
|
||||
]
|
||||
|
||||
operations = operations + (release_operations if include_release_tools else [])
|
||||
tools = [
|
||||
GitHubAction(
|
||||
name=action["name"],
|
||||
|
@ -98,3 +98,12 @@ This tool will create a new branch in the repository. **VERY IMPORTANT**: You mu
|
||||
|
||||
GET_FILES_FROM_DIRECTORY_PROMPT = """
|
||||
This tool will fetch a list of all files in a specified directory. **VERY IMPORTANT**: You must specify the path of the directory as a string input parameter."""
|
||||
|
||||
GET_LATEST_RELEASE_PROMPT = """
|
||||
This tool will fetch the latest release of the repository. No input parameters are required."""
|
||||
|
||||
GET_RELEASES_PROMPT = """
|
||||
This tool will fetch the latest 5 releases of the repository. No input parameters are required."""
|
||||
|
||||
GET_RELEASE_PROMPT = """
|
||||
This tool will fetch a specific release of the repository. **VERY IMPORTANT**: You must specify the tag name of the release as a string input parameter."""
|
||||
|
@ -813,6 +813,56 @@ class GitHubAPIWrapper(BaseModel):
|
||||
except Exception as e:
|
||||
return f"Failed to create a review request with error {e}"
|
||||
|
||||
def get_latest_release(self) -> str:
|
||||
"""
|
||||
Fetches the latest release of the repository.
|
||||
|
||||
Returns:
|
||||
str: The latest release
|
||||
"""
|
||||
release = self.github_repo_instance.get_latest_release()
|
||||
return (
|
||||
f"Latest title: {release.title} "
|
||||
f"tag: {release.tag_name} "
|
||||
f"body: {release.body}"
|
||||
)
|
||||
|
||||
def get_releases(self) -> str:
|
||||
"""
|
||||
Fetches all releases of the repository.
|
||||
|
||||
Returns:
|
||||
str: The releases
|
||||
"""
|
||||
releases = self.github_repo_instance.get_releases()
|
||||
max_results = min(5, releases.totalCount)
|
||||
results = [f"Top {max_results} results:"]
|
||||
for release in releases[:max_results]:
|
||||
results.append(
|
||||
f"Title: {release.title}, "
|
||||
f"Tag: {release.tag_name}, "
|
||||
f"Body: {release.body}"
|
||||
)
|
||||
|
||||
return "\n".join(results)
|
||||
|
||||
def get_release(self, tag_name: str) -> str:
|
||||
"""
|
||||
Fetches a specific release of the repository.
|
||||
|
||||
Parameters:
|
||||
tag_name(str): The tag name of the release
|
||||
|
||||
Returns:
|
||||
str: The release
|
||||
"""
|
||||
release = self.github_repo_instance.get_release(tag_name)
|
||||
return (
|
||||
f"Release: {release.title} "
|
||||
f"tag: {release.tag_name} "
|
||||
f"body: {release.body}"
|
||||
)
|
||||
|
||||
def run(self, mode: str, query: str) -> str:
|
||||
if mode == "get_issue":
|
||||
return json.dumps(self.get_issue(int(query)))
|
||||
@ -854,5 +904,11 @@ class GitHubAPIWrapper(BaseModel):
|
||||
return self.search_code(query)
|
||||
elif mode == "create_review_request":
|
||||
return self.create_review_request(query)
|
||||
elif mode == "get_latest_release":
|
||||
return self.get_latest_release()
|
||||
elif mode == "get_releases":
|
||||
return self.get_releases()
|
||||
elif mode == "get_release":
|
||||
return self.get_release(query)
|
||||
else:
|
||||
raise ValueError("Invalid mode" + mode)
|
||||
|
@ -22,6 +22,18 @@ def test_get_open_issues(api_client: GitHubAPIWrapper) -> None:
|
||||
assert len(issues) != 0
|
||||
|
||||
|
||||
def test_get_latest_release(api_client: GitHubAPIWrapper) -> None:
|
||||
"""Basic test to fetch latest release"""
|
||||
release = api_client.get_latest_release()
|
||||
assert release is not None
|
||||
|
||||
|
||||
def test_get_releases(api_client: GitHubAPIWrapper) -> None:
|
||||
"""Basic test to fetch releases"""
|
||||
releases = api_client.get_releases()
|
||||
assert releases is not None
|
||||
|
||||
|
||||
def test_search_issues_and_prs(api_client: GitHubAPIWrapper) -> None:
|
||||
"""Basic test to search issues and PRs"""
|
||||
results = api_client.search_issues_and_prs("is:pr is:merged")
|
||||
|
@ -0,0 +1,26 @@
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
from langchain_community.agent_toolkits.github.toolkit import GitHubToolkit
|
||||
from langchain_community.utilities.github import GitHubAPIWrapper
|
||||
|
||||
|
||||
def test_github_toolkit() -> None:
|
||||
# Create a mock GitHub wrapper with required attributes
|
||||
mock_github = MagicMock(spec=GitHubAPIWrapper)
|
||||
mock_github.github_repository = "fake/repo"
|
||||
mock_github.github_app_id = "fake_id"
|
||||
mock_github.github_app_private_key = "fake_key"
|
||||
mock_github.active_branch = "main"
|
||||
mock_github.github_base_branch = "main"
|
||||
|
||||
# Test without release tools
|
||||
toolkit = GitHubToolkit.from_github_api_wrapper(mock_github)
|
||||
tools = toolkit.get_tools()
|
||||
assert len(tools) == 21 # Base number of tools
|
||||
|
||||
# Test with release tools
|
||||
toolkit_with_releases = GitHubToolkit.from_github_api_wrapper(
|
||||
mock_github, include_release_tools=True
|
||||
)
|
||||
tools_with_releases = toolkit_with_releases.get_tools()
|
||||
assert len(tools_with_releases) == 24 # Base tools + 3 release tools
|
Loading…
Reference in New Issue
Block a user