mirror of
https://github.com/hwchase17/langchain.git
synced 2025-04-29 12:25:37 +00:00
**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>
361 lines
15 KiB
Plaintext
361 lines
15 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"# Github Toolkit\n",
|
|
"\n",
|
|
"The `Github` toolkit contains tools that enable an LLM agent to interact with a github repository. \n",
|
|
"The tool is a wrapper for the [PyGitHub](https://github.com/PyGithub/PyGithub) library. \n",
|
|
"\n",
|
|
"For detailed documentation of all GithubToolkit features and configurations head to the [API reference](https://python.langchain.com/api_reference/community/agent_toolkits/langchain_community.agent_toolkits.github.toolkit.GitHubToolkit.html).\n",
|
|
"\n",
|
|
"## Setup\n",
|
|
"\n",
|
|
"At a high-level, we will:\n",
|
|
"\n",
|
|
"1. Install the pygithub library\n",
|
|
"2. Create a Github app\n",
|
|
"3. Set your environmental variables\n",
|
|
"4. Pass the tools to your agent with `toolkit.get_tools()`"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"If you want to get automated tracing from runs of individual tools, you can also set your [LangSmith](https://docs.smith.langchain.com/) API key by uncommenting below:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# os.environ[\"LANGSMITH_API_KEY\"] = getpass.getpass(\"Enter your LangSmith API key: \")\n",
|
|
"# os.environ[\"LANGSMITH_TRACING\"] = \"true\""
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### Installation\n",
|
|
"\n",
|
|
"#### 1. Install dependencies\n",
|
|
"\n",
|
|
"This integration is implemented in `langchain-community`. We will also need the `pygithub` dependency:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"%pip install --upgrade --quiet pygithub langchain-community"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"#### 2. Create a Github App\n",
|
|
"\n",
|
|
"[Follow the instructions here](https://docs.github.com/en/apps/creating-github-apps/registering-a-github-app/registering-a-github-app) to create and register a Github app. Make sure your app has the following [repository permissions:](https://docs.github.com/en/rest/overview/permissions-required-for-github-apps?apiVersion=2022-11-28)\n",
|
|
"\n",
|
|
"* Commit statuses (read only)\n",
|
|
"* Contents (read and write)\n",
|
|
"* Issues (read and write)\n",
|
|
"* Metadata (read only)\n",
|
|
"* Pull requests (read and write)\n",
|
|
"\n",
|
|
"Once the app has been registered, you must give your app permission to access each of the repositories you whish it to act upon. Use the App settings on [github.com here](https://github.com/settings/installations).\n",
|
|
"\n",
|
|
"\n",
|
|
"#### 3. Set Environment Variables\n",
|
|
"\n",
|
|
"Before initializing your agent, the following environment variables need to be set:\n",
|
|
"\n",
|
|
"* **GITHUB_APP_ID**- A six digit number found in your app's general settings\n",
|
|
"* **GITHUB_APP_PRIVATE_KEY**- The location of your app's private key .pem file, or the full text of that file as a string.\n",
|
|
"* **GITHUB_REPOSITORY**- The name of the Github repository you want your bot to act upon. Must follow the format \\{username\\}/\\{repo-name\\}. *Make sure the app has been added to this repository first!*\n",
|
|
"* Optional: **GITHUB_BRANCH**- The branch where the bot will make its commits. Defaults to `repo.default_branch`.\n",
|
|
"* Optional: **GITHUB_BASE_BRANCH**- The base branch of your repo upon which PRs will based from. Defaults to `repo.default_branch`."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"import getpass\n",
|
|
"import os\n",
|
|
"\n",
|
|
"for env_var in [\n",
|
|
" \"GITHUB_APP_ID\",\n",
|
|
" \"GITHUB_APP_PRIVATE_KEY\",\n",
|
|
" \"GITHUB_REPOSITORY\",\n",
|
|
"]:\n",
|
|
" if not os.getenv(env_var):\n",
|
|
" os.environ[env_var] = getpass.getpass()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Instantiation\n",
|
|
"\n",
|
|
"Now we can instantiate our toolkit:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 2,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"from langchain_community.agent_toolkits.github.toolkit import GitHubToolkit\n",
|
|
"from langchain_community.utilities.github import GitHubAPIWrapper\n",
|
|
"\n",
|
|
"github = GitHubAPIWrapper()\n",
|
|
"toolkit = GitHubToolkit.from_github_api_wrapper(github)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Tools\n",
|
|
"\n",
|
|
"View available tools:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 3,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Get Issues\n",
|
|
"Get Issue\n",
|
|
"Comment on Issue\n",
|
|
"List open pull requests (PRs)\n",
|
|
"Get Pull Request\n",
|
|
"Overview of files included in PR\n",
|
|
"Create Pull Request\n",
|
|
"List Pull Requests' Files\n",
|
|
"Create File\n",
|
|
"Read File\n",
|
|
"Update File\n",
|
|
"Delete File\n",
|
|
"Overview of existing files in Main branch\n",
|
|
"Overview of files in current working branch\n",
|
|
"List branches in this repository\n",
|
|
"Set active branch\n",
|
|
"Create a new branch\n",
|
|
"Get files from a directory\n",
|
|
"Search issues and pull requests\n",
|
|
"Search code\n",
|
|
"Create review request\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"tools = toolkit.get_tools()\n",
|
|
"\n",
|
|
"for tool in tools:\n",
|
|
" print(tool.name)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"The purpose of these tools is as follows:\n",
|
|
"\n",
|
|
"Each of these steps will be explained in great detail below.\n",
|
|
"\n",
|
|
"1. **Get Issues**- fetches issues from the repository.\n",
|
|
"\n",
|
|
"2. **Get Issue**- fetches details about a specific issue.\n",
|
|
"\n",
|
|
"3. **Comment on Issue**- posts a comment on a specific issue.\n",
|
|
"\n",
|
|
"4. **Create Pull Request**- creates a pull request from the bot's working branch to the base branch.\n",
|
|
"\n",
|
|
"5. **Create File**- creates a new file in the repository.\n",
|
|
"\n",
|
|
"6. **Read File**- reads a file from the repository.\n",
|
|
"\n",
|
|
"7. **Update File**- updates a file in the repository.\n",
|
|
"\n",
|
|
"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": {},
|
|
"source": [
|
|
"## Use within an agent\n",
|
|
"\n",
|
|
"We will need a LLM or chat model:\n",
|
|
"\n",
|
|
"import ChatModelTabs from \"@theme/ChatModelTabs\";\n",
|
|
"\n",
|
|
"<ChatModelTabs customVarName=\"llm\" />\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 4,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# | output: false\n",
|
|
"# | echo: false\n",
|
|
"\n",
|
|
"from langchain_openai import ChatOpenAI\n",
|
|
"\n",
|
|
"llm = ChatOpenAI(model=\"gpt-4o-mini\", temperature=0)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Initialize the agent with a subset of tools:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 6,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"from langgraph.prebuilt import create_react_agent\n",
|
|
"\n",
|
|
"tools = [tool for tool in toolkit.get_tools() if tool.name == \"Get Issue\"]\n",
|
|
"assert len(tools) == 1\n",
|
|
"tools[0].name = \"get_issue\"\n",
|
|
"\n",
|
|
"agent_executor = create_react_agent(llm, tools)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"And issue it a query:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 7,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"================================\u001b[1m Human Message \u001b[0m=================================\n",
|
|
"\n",
|
|
"What is the title of issue 24888?\n",
|
|
"==================================\u001b[1m Ai Message \u001b[0m==================================\n",
|
|
"Tool Calls:\n",
|
|
" get_issue (call_iSYJVaM7uchfNHOMJoVPQsOi)\n",
|
|
" Call ID: call_iSYJVaM7uchfNHOMJoVPQsOi\n",
|
|
" Args:\n",
|
|
" issue_number: 24888\n",
|
|
"=================================\u001b[1m Tool Message \u001b[0m=================================\n",
|
|
"Name: get_issue\n",
|
|
"\n",
|
|
"{\"number\": 24888, \"title\": \"Standardize KV-Store Docs\", \"body\": \"To make our KV-store integrations as easy to use as possible we need to make sure the docs for them are thorough and standardized. There are two parts to this: updating the KV-store docstrings and updating the actual integration docs.\\r\\n\\r\\nThis needs to be done for each KV-store integration, ideally with one PR per KV-store.\\r\\n\\r\\nRelated to broader issues #21983 and #22005.\\r\\n\\r\\n## Docstrings\\r\\nEach KV-store class docstring should have the sections shown in the [Appendix](#appendix) below. The sections should have input and output code blocks when relevant.\\r\\n\\r\\nTo build a preview of the API docs for the package you're working on run (from root of repo):\\r\\n\\r\\n```shell\\r\\nmake api_docs_clean; make api_docs_quick_preview API_PKG=openai\\r\\n```\\r\\n\\r\\nwhere `API_PKG=` should be the parent directory that houses the edited package (e.g. community, openai, anthropic, huggingface, together, mistralai, groq, fireworks, etc.). This should be quite fast for all the partner packages.\\r\\n\\r\\n## Doc pages\\r\\nEach KV-store [docs page](https://python.langchain.com/docs/integrations/stores/) should follow [this template](https://github.com/langchain-ai/langchain/blob/master/libs/cli/langchain_cli/integration_template/docs/kv_store.ipynb).\\r\\n\\r\\nHere is an example: https://python.langchain.com/docs/integrations/stores/in_memory/\\r\\n\\r\\nYou can use the `langchain-cli` to quickly get started with a new chat model integration docs page (run from root of repo):\\r\\n\\r\\n```shell\\r\\npoetry run pip install -e libs/cli\\r\\npoetry run langchain-cli integration create-doc --name \\\"foo-bar\\\" --name-class FooBar --component-type kv_store --destination-dir ./docs/docs/integrations/stores/\\r\\n```\\r\\n\\r\\nwhere `--name` is the integration package name without the \\\"langchain-\\\" prefix and `--name-class` is the class name without the \\\"ByteStore\\\" suffix. This will create a template doc with some autopopulated fields at docs/docs/integrations/stores/foo_bar.ipynb.\\r\\n\\r\\nTo build a preview of the docs you can run (from root):\\r\\n\\r\\n```shell\\r\\nmake docs_clean\\r\\nmake docs_build\\r\\ncd docs/build/output-new\\r\\nyarn\\r\\nyarn start\\r\\n```\\r\\n\\r\\n## Appendix\\r\\nExpected sections for the KV-store class docstring.\\r\\n\\r\\n```python\\r\\n \\\"\\\"\\\"__ModuleName__ completion KV-store integration.\\r\\n\\r\\n # TODO: Replace with relevant packages, env vars.\\r\\n Setup:\\r\\n Install ``__package_name__`` and set environment variable ``__MODULE_NAME___API_KEY``.\\r\\n\\r\\n .. code-block:: bash\\r\\n\\r\\n pip install -U __package_name__\\r\\n export __MODULE_NAME___API_KEY=\\\"your-api-key\\\"\\r\\n\\r\\n # TODO: Populate with relevant params.\\r\\n Key init args \\u2014 client params:\\r\\n api_key: Optional[str]\\r\\n __ModuleName__ API key. If not passed in will be read from env var __MODULE_NAME___API_KEY.\\r\\n\\r\\n See full list of supported init args and their descriptions in the params section.\\r\\n\\r\\n # TODO: Replace with relevant init params.\\r\\n Instantiate:\\r\\n .. code-block:: python\\r\\n\\r\\n from __module_name__ import __ModuleName__ByteStore\\r\\n\\r\\n kv_store = __ModuleName__ByteStore(\\r\\n # api_key=\\\"...\\\",\\r\\n # other params...\\r\\n )\\r\\n\\r\\n Set keys:\\r\\n .. code-block:: python\\r\\n\\r\\n kv_pairs = [\\r\\n [\\\"key1\\\", \\\"value1\\\"],\\r\\n [\\\"key2\\\", \\\"value2\\\"],\\r\\n ]\\r\\n\\r\\n kv_store.mset(kv_pairs)\\r\\n\\r\\n .. code-block:: python\\r\\n\\r\\n Get keys:\\r\\n .. code-block:: python\\r\\n\\r\\n kv_store.mget([\\\"key1\\\", \\\"key2\\\"])\\r\\n\\r\\n .. code-block:: python\\r\\n\\r\\n # TODO: Example output.\\r\\n\\r\\n Delete keys:\\r\\n ..code-block:: python\\r\\n\\r\\n kv_store.mdelete([\\\"key1\\\", \\\"key2\\\"])\\r\\n\\r\\n ..code-block:: python\\r\\n \\\"\\\"\\\" # noqa: E501\\r\\n```\", \"comments\": \"[]\", \"opened_by\": \"jacoblee93\"}\n",
|
|
"==================================\u001b[1m Ai Message \u001b[0m==================================\n",
|
|
"\n",
|
|
"The title of issue 24888 is \"Standardize KV-Store Docs\".\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"example_query = \"What is the title of issue 24888?\"\n",
|
|
"\n",
|
|
"events = agent_executor.stream(\n",
|
|
" {\"messages\": [(\"user\", example_query)]},\n",
|
|
" stream_mode=\"values\",\n",
|
|
")\n",
|
|
"for event in events:\n",
|
|
" event[\"messages\"][-1].pretty_print()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## API reference\n",
|
|
"\n",
|
|
"For detailed documentation of all `GithubToolkit` features and configurations head to the [API reference](https://python.langchain.com/api_reference/community/agent_toolkits/langchain_community.agent_toolkits.github.toolkit.GitHubToolkit.html)."
|
|
]
|
|
}
|
|
],
|
|
"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.13.1"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 4
|
|
}
|