From 85623274d17e293024968a98ebe0bde25af8f3df Mon Sep 17 00:00:00 2001 From: Bagatur Date: Sat, 27 Jan 2024 12:49:55 -0800 Subject: [PATCH 1/7] infra: add ci --- .github/ISSUE_TEMPLATE/bug-report.yml | 118 ++++++++++++ .github/ISSUE_TEMPLATE/config.yml | 15 ++ .github/ISSUE_TEMPLATE/documentation.yml | 19 ++ .github/ISSUE_TEMPLATE/privileged.yml | 25 +++ .github/actions/poetry_setup/action.yml | 93 ++++++++++ .github/workflows/_test_release.yml | 90 ++++++++++ .github/workflows/lint.yml | 97 ++++++++++ .github/workflows/release.yml | 220 +++++++++++++++++++++++ .github/workflows/test.yml | 55 ++++++ Makefile | 11 +- 10 files changed, 740 insertions(+), 3 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE/bug-report.yml create mode 100644 .github/ISSUE_TEMPLATE/config.yml create mode 100644 .github/ISSUE_TEMPLATE/documentation.yml create mode 100644 .github/ISSUE_TEMPLATE/privileged.yml create mode 100644 .github/actions/poetry_setup/action.yml create mode 100644 .github/workflows/_test_release.yml create mode 100644 .github/workflows/lint.yml create mode 100644 .github/workflows/release.yml create mode 100644 .github/workflows/test.yml diff --git a/.github/ISSUE_TEMPLATE/bug-report.yml b/.github/ISSUE_TEMPLATE/bug-report.yml new file mode 100644 index 000000000..ea280821a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug-report.yml @@ -0,0 +1,118 @@ +name: "\U0001F41B Bug Report" +description: Report a bug in LangChain. To report a security issue, please instead use the security option below. For questions, please use the GitHub Discussions. +labels: ["02 Bug Report"] +body: + - type: markdown + attributes: + value: > + Thank you for taking the time to file a bug report. + + Use this to report bugs in LangChain. + + If you're not certain that your issue is due to a bug in LangChain, please use [GitHub Discussions](https://github.com/langchain-ai/langchain/discussions) + to ask for help with your issue. + + Relevant links to check before filing a bug report to see if your issue has already been reported, fixed or + if there's another way to solve your problem: + + [LangChain documentation with the integrated search](https://python.langchain.com/docs/get_started/introduction), + [API Reference](https://api.python.langchain.com/en/stable/), + [GitHub search](https://github.com/langchain-ai/langchain), + [LangChain Github Discussions](https://github.com/langchain-ai/langchain/discussions), + [LangChain Github Issues](https://github.com/langchain-ai/langchain/issues?q=is%3Aissue), + [LangChain ChatBot](https://chat.langchain.com/) + - type: checkboxes + id: checks + attributes: + label: Checked other resources + description: Please confirm and check all the following options. + options: + - label: I added a very descriptive title to this issue. + required: true + - label: I searched the LangChain documentation with the integrated search. + required: true + - label: I used the GitHub search to find a similar question and didn't find it. + required: true + - label: I am sure that this is a bug in LangChain rather than my code. + required: true + - type: textarea + id: reproduction + validations: + required: true + attributes: + label: Example Code + description: | + Please add a self-contained, [minimal, reproducible, example](https://stackoverflow.com/help/minimal-reproducible-example) with your use case. + + If a maintainer can copy it, run it, and see it right away, there's a much higher chance that you'll be able to get help. + + **Important!** + + * Use code tags (e.g., ```python ... ```) to correctly [format your code](https://help.github.com/en/github/writing-on-github/creating-and-highlighting-code-blocks#syntax-highlighting). + * INCLUDE the language label (e.g. `python`) after the first three backticks to enable syntax highlighting. (e.g., ```python rather than ```). + * Reduce your code to the minimum required to reproduce the issue if possible. This makes it much easier for others to help you. + * Avoid screenshots when possible, as they are hard to read and (more importantly) don't allow others to copy-and-paste your code. + + placeholder: | + The following code: + + ```python + from langchain_core.runnables import RunnableLambda + + def bad_code(inputs) -> int: + raise NotImplementedError('For demo purpose') + + chain = RunnableLambda(bad_code) + chain.invoke('Hello!') + ``` + - type: textarea + id: error + validations: + required: false + attributes: + label: Error Message and Stack Trace (if applicable) + description: | + If you are reporting an error, please include the full error message and stack trace. + placeholder: | + Exception + full stack trace + - type: textarea + id: description + attributes: + label: Description + description: | + What is the problem, question, or error? + + Write a short description telling what you are doing, what you expect to happen, and what is currently happening. + placeholder: | + * I'm trying to use the `langchain` library to do X. + * I expect to see Y. + * Instead, it does Z. + validations: + required: true + - type: textarea + id: system-info + attributes: + label: System Info + description: | + Please share your system info with us. + + "pip freeze | grep langchain" + platform (windows / linux / mac) + python version + + OR if you're on a recent version of langchain-core you can paste the output of: + + python -m langchain_core.sys_info + placeholder: | + "pip freeze | grep langchain" + platform + python version + + Alternatively, if you're on a recent version of langchain-core you can paste the output of: + + python -m langchain_core.sys_info + + These will only surface LangChain packages, don't forget to include any other relevant + packages you're using (if you're not sure what's relevant, you can paste the entire output of `pip freeze`). + validations: + required: true diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 000000000..746565c48 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,15 @@ +blank_issues_enabled: false +version: 2.1 +contact_links: + - name: 🤔 Question or Problem + about: Ask a question or ask about a problem in GitHub Discussions. + url: https://www.github.com/langchain-ai/langchain/discussions/categories/q-a + - name: Discord + url: https://discord.gg/6adMQxSpJS + about: General community discussions + - name: Feature Request + url: https://www.github.com/langchain-ai/langchain/discussions/categories/ideas + about: Suggest a feature or an idea + - name: Show and tell + about: Show what you built with LangChain + url: https://www.github.com/langchain-ai/langchain/discussions/categories/show-and-tell diff --git a/.github/ISSUE_TEMPLATE/documentation.yml b/.github/ISSUE_TEMPLATE/documentation.yml new file mode 100644 index 000000000..61a3ad496 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/documentation.yml @@ -0,0 +1,19 @@ +name: Documentation +description: Report an issue related to the LangChain documentation. +title: "DOC: " +labels: [03 - Documentation] + +body: +- type: textarea + attributes: + label: "Issue with current documentation:" + description: > + Please make sure to leave a reference to the document/code you're + referring to. + +- type: textarea + attributes: + label: "Idea or request for content:" + description: > + Please describe as clearly as possible what topics you think are missing + from the current documentation. \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/privileged.yml b/.github/ISSUE_TEMPLATE/privileged.yml new file mode 100644 index 000000000..692a5bde6 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/privileged.yml @@ -0,0 +1,25 @@ +name: 🔒 Privileged +description: You are a LangChain maintainer, or was asked directly by a maintainer to create an issue here. If not, check the other options. +body: + - type: markdown + attributes: + value: | + Thanks for your interest in LangChain! 🚀 + + If you are not a LangChain maintainer or were not asked directly by a maintainer to create an issue, then please start the conversation in a [Question in GitHub Discussions](https://github.com/langchain-ai/langchain/discussions/categories/q-a) instead. + + You are a LangChain maintainer if you maintain any of the packages inside of the LangChain repository + or are a regular contributor to LangChain with previous merged merged pull requests. + - type: checkboxes + id: privileged + attributes: + label: Privileged issue + description: Confirm that you are allowed to create an issue here. + options: + - label: I am a LangChain maintainer, or was asked directly by a LangChain maintainer to create an issue here. + required: true + - type: textarea + id: content + attributes: + label: Issue Content + description: Add the content of the issue here. diff --git a/.github/actions/poetry_setup/action.yml b/.github/actions/poetry_setup/action.yml new file mode 100644 index 000000000..5aef4970b --- /dev/null +++ b/.github/actions/poetry_setup/action.yml @@ -0,0 +1,93 @@ +# An action for setting up poetry install with caching. +# Using a custom action since the default action does not +# take poetry install groups into account. +# Action code from: +# https://github.com/actions/setup-python/issues/505#issuecomment-1273013236 +name: poetry-install-with-caching +description: Poetry install with support for caching of dependency groups. + +inputs: + python-version: + description: Python version, supporting MAJOR.MINOR only + required: true + + poetry-version: + description: Poetry version + required: true + + cache-key: + description: Cache key to use for manual handling of caching + required: true + + working-directory: + description: Directory whose poetry.lock file should be cached + required: true + +runs: + using: composite + steps: + - uses: actions/setup-python@v5 + name: Setup python ${{ inputs.python-version }} + id: setup-python + with: + python-version: ${{ inputs.python-version }} + + - uses: actions/cache@v3 + id: cache-bin-poetry + name: Cache Poetry binary - Python ${{ inputs.python-version }} + env: + SEGMENT_DOWNLOAD_TIMEOUT_MIN: "1" + with: + path: | + /opt/pipx/venvs/poetry + # This step caches the poetry installation, so make sure it's keyed on the poetry version as well. + key: bin-poetry-${{ runner.os }}-${{ runner.arch }}-py-${{ inputs.python-version }}-${{ inputs.poetry-version }} + + - name: Refresh shell hashtable and fixup softlinks + if: steps.cache-bin-poetry.outputs.cache-hit == 'true' + shell: bash + env: + POETRY_VERSION: ${{ inputs.poetry-version }} + PYTHON_VERSION: ${{ inputs.python-version }} + run: | + set -eux + + # Refresh the shell hashtable, to ensure correct `which` output. + hash -r + + # `actions/cache@v3` doesn't always seem able to correctly unpack softlinks. + # Delete and recreate the softlinks pipx expects to have. + rm /opt/pipx/venvs/poetry/bin/python + cd /opt/pipx/venvs/poetry/bin + ln -s "$(which "python$PYTHON_VERSION")" python + chmod +x python + cd /opt/pipx_bin/ + ln -s /opt/pipx/venvs/poetry/bin/poetry poetry + chmod +x poetry + + # Ensure everything got set up correctly. + /opt/pipx/venvs/poetry/bin/python --version + /opt/pipx_bin/poetry --version + + - name: Install poetry + if: steps.cache-bin-poetry.outputs.cache-hit != 'true' + shell: bash + env: + POETRY_VERSION: ${{ inputs.poetry-version }} + PYTHON_VERSION: ${{ inputs.python-version }} + # Install poetry using the python version installed by setup-python step. + run: pipx install "poetry==$POETRY_VERSION" --python '${{ steps.setup-python.outputs.python-path }}' --verbose + + - name: Restore pip and poetry cached dependencies + uses: actions/cache@v3 + env: + SEGMENT_DOWNLOAD_TIMEOUT_MIN: "4" + WORKDIR: ${{ inputs.working-directory == '' && '.' || inputs.working-directory }} + with: + path: | + ~/.cache/pip + ~/.cache/pypoetry/virtualenvs + ~/.cache/pypoetry/cache + ~/.cache/pypoetry/artifacts + ${{ env.WORKDIR }}/.venv + key: py-deps-${{ runner.os }}-${{ runner.arch }}-py-${{ inputs.python-version }}-poetry-${{ inputs.poetry-version }}-${{ inputs.cache-key }}-${{ hashFiles(format('{0}/**/poetry.lock', env.WORKDIR)) }} diff --git a/.github/workflows/_test_release.yml b/.github/workflows/_test_release.yml new file mode 100644 index 000000000..ad56abd2e --- /dev/null +++ b/.github/workflows/_test_release.yml @@ -0,0 +1,90 @@ +name: test-release + +on: + workflow_call: + +env: + POETRY_VERSION: "1.7.1" + PYTHON_VERSION: "3.10" + +jobs: + build: + if: github.ref == 'refs/heads/master' + defaults: + run: + working-directory: ./langgraph + runs-on: ubuntu-latest + + outputs: + pkg-name: ${{ steps.check-version.outputs.pkg-name }} + version: ${{ steps.check-version.outputs.version }} + + steps: + - uses: actions/checkout@v4 + + - name: Set up Python + Poetry ${{ env.POETRY_VERSION }} + uses: "./.github/actions/poetry_setup" + with: + python-version: ${{ env.PYTHON_VERSION }} + poetry-version: ${{ env.POETRY_VERSION }} + cache-key: release + + # We want to keep this build stage *separate* from the release stage, + # so that there's no sharing of permissions between them. + # The release stage has trusted publishing and GitHub repo contents write access, + # and we want to keep the scope of that access limited just to the release job. + # Otherwise, a malicious `build` step (e.g. via a compromised dependency) + # could get access to our GitHub or PyPI credentials. + # + # Per the trusted publishing GitHub Action: + # > It is strongly advised to separate jobs for building [...] + # > from the publish job. + # https://github.com/pypa/gh-action-pypi-publish#non-goals + - name: Build project for distribution + run: poetry build + + - name: Upload build + uses: actions/upload-artifact@v3 + with: + name: test-dist + path: ./langgraph/dist/ + + - name: Check Version + id: check-version + shell: bash + run: | + echo pkg-name="$(poetry version | cut -d ' ' -f 1)" >> $GITHUB_OUTPUT + echo version="$(poetry version --short)" >> $GITHUB_OUTPUT + + publish: + needs: + - build + runs-on: ubuntu-latest + permissions: + # This permission is used for trusted publishing: + # https://blog.pypi.org/posts/2023-04-20-introducing-trusted-publishers/ + # + # Trusted publishing has to also be configured on PyPI for each package: + # https://docs.pypi.org/trusted-publishers/adding-a-publisher/ + id-token: write + + steps: + - uses: actions/checkout@v4 + + - uses: actions/download-artifact@v3 + with: + name: test-dist + path: ./langgraph/dist/ + + - name: Publish to test PyPI + uses: pypa/gh-action-pypi-publish@release/v1 + with: + packages-dir: ./langgraph/dist/ + verbose: true + print-hash: true + repository-url: https://test.pypi.org/legacy/ + + # We overwrite any existing distributions with the same name and version. + # This is *only for CI use* and is *extremely dangerous* otherwise! + # https://github.com/pypa/gh-action-pypi-publish#tolerating-release-package-file-duplicates + skip-existing: true diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 000000000..5e01fb35d --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,97 @@ +name: lint + +on: + push: + branches: [master] + pull_request: + +env: + POETRY_VERSION: "1.7.1" + + # This env var allows us to get inline annotations when ruff has complaints. + RUFF_OUTPUT_FORMAT: github + +jobs: + build: + runs-on: ubuntu-latest + defaults: + run: + working-directory: ./langgraph + strategy: + matrix: + # Only lint on the min and max supported Python versions. + # It's extremely unlikely that there's a lint issue on any version in between + # that doesn't show up on the min or max versions. + # + # GitHub rate-limits how many jobs can be running at any one time. + # Starting new jobs is also relatively slow, + # so linting on fewer versions makes CI faster. + python-version: + - "3.8" + - "3.11" + steps: + - uses: actions/checkout@v4 + + - name: Set up Python ${{ matrix.python-version }} + Poetry ${{ env.POETRY_VERSION }} + uses: "./.github/actions/poetry_setup" + with: + python-version: ${{ matrix.python-version }} + poetry-version: ${{ env.POETRY_VERSION }} + cache-key: lint-with-extras + + - name: Check Poetry File + shell: bash + run: poetry check + + - name: Check lock file + shell: bash + run: poetry lock --check + + - name: Install dependencies + # Also installs dev/lint/test/typing dependencies, to ensure we have + # type hints for as many of our libraries as possible. + # This helps catch errors that require dependencies to be spotted, for example: + # https://github.com/langchain-ai/langchain/pull/10249/files#diff-935185cd488d015f026dcd9e19616ff62863e8cde8c0bee70318d3ccbca98341 + # + # If you change this configuration, make sure to change the `cache-key` + # in the `poetry_setup` action above to stop using the old cache. + # It doesn't matter how you change it, any change will cause a cache-bust. + run: poetry install --with lint,typing + + - name: Get .mypy_cache to speed up mypy + uses: actions/cache@v3 + env: + SEGMENT_DOWNLOAD_TIMEOUT_MIN: "2" + with: + path: | + ./.mypy_cache + key: mypy-lint-${{ runner.os }}-${{ runner.arch }}-py${{ matrix.python-version }}-${{ hashFiles('./poetry.lock') }} + + + - name: Analysing the code with our lint + run: | + make lint_package + + - name: Install test dependencies + # Also installs dev/lint/test/typing dependencies, to ensure we have + # type hints for as many of our libraries as possible. + # This helps catch errors that require dependencies to be spotted, for example: + # https://github.com/langchain-ai/langchain/pull/10249/files#diff-935185cd488d015f026dcd9e19616ff62863e8cde8c0bee70318d3ccbca98341 + # + # If you change this configuration, make sure to change the `cache-key` + # in the `poetry_setup` action above to stop using the old cache. + # It doesn't matter how you change it, any change will cause a cache-bust. + run: | + poetry install --with test + + - name: Get .mypy_cache_test to speed up mypy + uses: actions/cache@v3 + env: + SEGMENT_DOWNLOAD_TIMEOUT_MIN: "2" + with: + path: ./.mypy_cache_test + key: mypy-test-${{ runner.os }}-${{ runner.arch }}-py${{ matrix.python-version }}-${{ hashFiles('./poetry.lock') }} + + - name: Analysing the code with our lint + run: | + make lint_tests diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 000000000..19b076333 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,220 @@ +name: release +run-name: Release by @${{ github.actor }} +on: + workflow_dispatch + +env: + PYTHON_VERSION: "3.10" + POETRY_VERSION: "1.7.1" + +jobs: + build: + if: github.ref == 'refs/heads/master' + defaults: + run: + working-directory: ./langgraph + runs-on: ubuntu-latest + + outputs: + pkg-name: ${{ steps.check-version.outputs.pkg-name }} + version: ${{ steps.check-version.outputs.version }} + + steps: + - uses: actions/checkout@v4 + + - name: Set up Python + Poetry ${{ env.POETRY_VERSION }} + uses: "./.github/actions/poetry_setup" + with: + python-version: ${{ env.PYTHON_VERSION }} + poetry-version: ${{ env.POETRY_VERSION }} + cache-key: release + + # We want to keep this build stage *separate* from the release stage, + # so that there's no sharing of permissions between them. + # The release stage has trusted publishing and GitHub repo contents write access, + # and we want to keep the scope of that access limited just to the release job. + # Otherwise, a malicious `build` step (e.g. via a compromised dependency) + # could get access to our GitHub or PyPI credentials. + # + # Per the trusted publishing GitHub Action: + # > It is strongly advised to separate jobs for building [...] + # > from the publish job. + # https://github.com/pypa/gh-action-pypi-publish#non-goals + - name: Build project for distribution + run: poetry build + + - name: Upload build + uses: actions/upload-artifact@v3 + with: + name: dist + path: ./langgraph/dist/ + + - name: Check Version + id: check-version + shell: bash + run: | + echo pkg-name="$(poetry version | cut -d ' ' -f 1)" >> $GITHUB_OUTPUT + echo version="$(poetry version --short)" >> $GITHUB_OUTPUT + + test-pypi-publish: + needs: + - build + uses: + ./.github/workflows/_test_release.yml + secrets: inherit + + pre-release-checks: + needs: + - build + - test-pypi-publish + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + # We explicitly *don't* set up caching here. This ensures our tests are + # maximally sensitive to catching breakage. + # + # For example, here's a way that caching can cause a falsely-passing test: + # - Make the langchain package manifest no longer list a dependency package + # as a requirement. This means it won't be installed by `pip install`, + # and attempting to use it would cause a crash. + # - That dependency used to be required, so it may have been cached. + # When restoring the venv packages from cache, that dependency gets included. + # - Tests pass, because the dependency is present even though it wasn't specified. + # - The package is published, and it breaks on the missing dependency when + # used in the real world. + + - name: Set up Python + Poetry ${{ env.POETRY_VERSION }} + uses: "./.github/actions/poetry_setup" + with: + python-version: ${{ env.PYTHON_VERSION }} + poetry-version: ${{ env.POETRY_VERSION }} + + - name: Import published package + shell: bash + env: + PKG_NAME: ${{ needs.build.outputs.pkg-name }} + VERSION: ${{ needs.build.outputs.version }} + # Here we use: + # - The default regular PyPI index as the *primary* index, meaning + # that it takes priority (https://pypi.org/simple) + # - The test PyPI index as an extra index, so that any dependencies that + # are not found on test PyPI can be resolved and installed anyway. + # (https://test.pypi.org/simple). This will include the PKG_NAME==VERSION + # package because VERSION will not have been uploaded to regular PyPI yet. + # - attempt install again after 5 seconds if it fails because there is + # sometimes a delay in availability on test pypi + run: | + poetry run pip install \ + --extra-index-url https://test.pypi.org/simple/ \ + "$PKG_NAME==$VERSION" || \ + ( \ + sleep 5 && \ + poetry run pip install \ + --extra-index-url https://test.pypi.org/simple/ \ + "$PKG_NAME==$VERSION" \ + ) + + # Replace all dashes in the package name with underscores, + # since that's how Python imports packages with dashes in the name. + IMPORT_NAME="$(echo "$PKG_NAME" | sed s/-/_/g)" + + poetry run python -c "import $IMPORT_NAME; print(dir($IMPORT_NAME))" + + - name: Import test dependencies + run: poetry install --with test,test_integration + + # Overwrite the local version of the package with the test PyPI version. + - name: Import published package (again) + shell: bash + env: + PKG_NAME: ${{ needs.build.outputs.pkg-name }} + VERSION: ${{ needs.build.outputs.version }} + run: | + poetry run pip install \ + --extra-index-url https://test.pypi.org/simple/ \ + "$PKG_NAME==$VERSION" + + - name: Run unit tests + run: make tests + + publish: + needs: + - build + - test-pypi-publish + - pre-release-checks + runs-on: ubuntu-latest + permissions: + # This permission is used for trusted publishing: + # https://blog.pypi.org/posts/2023-04-20-introducing-trusted-publishers/ + # + # Trusted publishing has to also be configured on PyPI for each package: + # https://docs.pypi.org/trusted-publishers/adding-a-publisher/ + id-token: write + + defaults: + run: + working-directory: ./langgraph + + steps: + - uses: actions/checkout@v4 + + - name: Set up Python + Poetry ${{ env.POETRY_VERSION }} + uses: "./.github/actions/poetry_setup" + with: + python-version: ${{ env.PYTHON_VERSION }} + poetry-version: ${{ env.POETRY_VERSION }} + cache-key: release + + - uses: actions/download-artifact@v3 + with: + name: dist + path: ./langgraph/dist/ + + - name: Publish package distributions to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 + with: + packages-dir: ./langgraph/dist/ + verbose: true + print-hash: true + + mark-release: + needs: + - build + - test-pypi-publish + - pre-release-checks + - publish + runs-on: ubuntu-latest + permissions: + # This permission is needed by `ncipollo/release-action` to + # create the GitHub release. + contents: write + + defaults: + run: + working-directory: ./langgraph + + steps: + - uses: actions/checkout@v4 + + - name: Set up Python + Poetry ${{ env.POETRY_VERSION }} + uses: "./.github/actions/poetry_setup" + with: + python-version: ${{ env.PYTHON_VERSION }} + poetry-version: ${{ env.POETRY_VERSION }} + cache-key: release + + - uses: actions/download-artifact@v3 + with: + name: dist + path: ./langgraph/dist/ + + - name: Create Release + uses: ncipollo/release-action@v1 + with: + artifacts: "dist/*" + token: ${{ secrets.GITHUB_TOKEN }} + draft: false + generateReleaseNotes: true + tag: v${{ needs.build.outputs.version }} + commit: master diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 000000000..2eac17272 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,55 @@ +name: test + +on: + push: + branches: [master] + pull_request: + +env: + POETRY_VERSION: "1.7.1" + +jobs: + build: + defaults: + run: + working-directory: ./langgraph + runs-on: ubuntu-latest + strategy: + matrix: + python-version: + - "3.8" + - "3.9" + - "3.10" + - "3.11" + - "3.12" + name: Python ${{ matrix.python-version }} + steps: + - uses: actions/checkout@v4 + + - name: Set up Python ${{ matrix.python-version }} + Poetry ${{ env.POETRY_VERSION }} + uses: "./.github/actions/poetry_setup" + with: + python-version: ${{ matrix.python-version }} + poetry-version: ${{ env.POETRY_VERSION }} + cache-key: core + + - name: Install dependencies + shell: bash + run: poetry install --with test + + - name: Run core tests + shell: bash + run: | + make test + + - name: Ensure the tests did not create any additional files + shell: bash + run: | + set -eu + + STATUS="$(git status)" + echo "$STATUS" + + # grep will exit non-zero if the target message isn't found, + # and `set -e` above will cause the step to fail. + echo "$STATUS" | grep 'nothing to commit, working tree clean' diff --git a/Makefile b/Makefile index f228a3fed..8546ec58d 100644 --- a/Makefile +++ b/Makefile @@ -26,13 +26,18 @@ test_watch: # Define a variable for Python and notebook files. PYTHON_FILES=. +MYPY_CACHE=.mypy_cache lint format: PYTHON_FILES=. lint_diff format_diff: PYTHON_FILES=$(shell git diff --name-only --diff-filter=d master | grep -E '\.py$$|\.ipynb$$') +lint_package: PYTHON_FILES=langchain_community +lint_tests: PYTHON_FILES=tests +lint_tests: MYPY_CACHE=.mypy_cache_test -lint lint_diff: +lint lint_diff lint_package lint_tests: poetry run ruff . - poetry run ruff format $(PYTHON_FILES) --check - poetry run mypy $(PYTHON_FILES) + [ "$(PYTHON_FILES)" = "" ] || poetry run ruff format $(PYTHON_FILES) --diff + [ "$(PYTHON_FILES)" = "" ] || poetry run ruff --select I $(PYTHON_FILES) + [ "$(PYTHON_FILES)" = "" ] || mkdir -p $(MYPY_CACHE) || poetry run mypy $(PYTHON_FILES) --cache-dir $(MYPY_CACHE) format format_diff: poetry run ruff format $(PYTHON_FILES) From 9119dc18ef9f33e86ba636440560f64953b60162 Mon Sep 17 00:00:00 2001 From: Bagatur Date: Sat, 27 Jan 2024 12:53:17 -0800 Subject: [PATCH 2/7] fix --- .github/workflows/release.yml | 7 ++++--- .github/workflows/test.yml | 1 - 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 19b076333..44e13edb8 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -68,6 +68,9 @@ jobs: - build - test-pypi-publish runs-on: ubuntu-latest + defaults: + run: + working-directory: ./langgraph steps: - uses: actions/checkout@v4 @@ -122,7 +125,7 @@ jobs: poetry run python -c "import $IMPORT_NAME; print(dir($IMPORT_NAME))" - name: Import test dependencies - run: poetry install --with test,test_integration + run: poetry install --with test # Overwrite the local version of the package with the test PyPI version. - name: Import published package (again) @@ -151,7 +154,6 @@ jobs: # Trusted publishing has to also be configured on PyPI for each package: # https://docs.pypi.org/trusted-publishers/adding-a-publisher/ id-token: write - defaults: run: working-directory: ./langgraph @@ -189,7 +191,6 @@ jobs: # This permission is needed by `ncipollo/release-action` to # create the GitHub release. contents: write - defaults: run: working-directory: ./langgraph diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2eac17272..09a97d514 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -21,7 +21,6 @@ jobs: - "3.9" - "3.10" - "3.11" - - "3.12" name: Python ${{ matrix.python-version }} steps: - uses: actions/checkout@v4 From ad88ebf29550994986c0a2458891e2417531e8c4 Mon Sep 17 00:00:00 2001 From: Bagatur Date: Sat, 27 Jan 2024 12:59:32 -0800 Subject: [PATCH 3/7] fix --- .github/actions/poetry_setup/action.yml | 9 ++------- .github/workflows/_test_release.yml | 3 --- .github/workflows/lint.yml | 3 --- .github/workflows/release.yml | 20 ++++---------------- .github/workflows/test.yml | 3 --- 5 files changed, 6 insertions(+), 32 deletions(-) diff --git a/.github/actions/poetry_setup/action.yml b/.github/actions/poetry_setup/action.yml index 5aef4970b..df04e1e71 100644 --- a/.github/actions/poetry_setup/action.yml +++ b/.github/actions/poetry_setup/action.yml @@ -19,10 +19,6 @@ inputs: description: Cache key to use for manual handling of caching required: true - working-directory: - description: Directory whose poetry.lock file should be cached - required: true - runs: using: composite steps: @@ -82,12 +78,11 @@ runs: uses: actions/cache@v3 env: SEGMENT_DOWNLOAD_TIMEOUT_MIN: "4" - WORKDIR: ${{ inputs.working-directory == '' && '.' || inputs.working-directory }} with: path: | ~/.cache/pip ~/.cache/pypoetry/virtualenvs ~/.cache/pypoetry/cache ~/.cache/pypoetry/artifacts - ${{ env.WORKDIR }}/.venv - key: py-deps-${{ runner.os }}-${{ runner.arch }}-py-${{ inputs.python-version }}-poetry-${{ inputs.poetry-version }}-${{ inputs.cache-key }}-${{ hashFiles(format('{0}/**/poetry.lock', env.WORKDIR)) }} + ./.venv + key: py-deps-${{ runner.os }}-${{ runner.arch }}-py-${{ inputs.python-version }}-poetry-${{ inputs.poetry-version }}-${{ inputs.cache-key }}-${{ hashFiles('./poetry.lock') }} diff --git a/.github/workflows/_test_release.yml b/.github/workflows/_test_release.yml index ad56abd2e..322b25bf0 100644 --- a/.github/workflows/_test_release.yml +++ b/.github/workflows/_test_release.yml @@ -10,9 +10,6 @@ env: jobs: build: if: github.ref == 'refs/heads/master' - defaults: - run: - working-directory: ./langgraph runs-on: ubuntu-latest outputs: diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 5e01fb35d..964707ad0 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -14,9 +14,6 @@ env: jobs: build: runs-on: ubuntu-latest - defaults: - run: - working-directory: ./langgraph strategy: matrix: # Only lint on the min and max supported Python versions. diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 44e13edb8..5bb9dace2 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -10,9 +10,6 @@ env: jobs: build: if: github.ref == 'refs/heads/master' - defaults: - run: - working-directory: ./langgraph runs-on: ubuntu-latest outputs: @@ -47,7 +44,7 @@ jobs: uses: actions/upload-artifact@v3 with: name: dist - path: ./langgraph/dist/ + path: ./dist/ - name: Check Version id: check-version @@ -68,9 +65,6 @@ jobs: - build - test-pypi-publish runs-on: ubuntu-latest - defaults: - run: - working-directory: ./langgraph steps: - uses: actions/checkout@v4 @@ -154,9 +148,6 @@ jobs: # Trusted publishing has to also be configured on PyPI for each package: # https://docs.pypi.org/trusted-publishers/adding-a-publisher/ id-token: write - defaults: - run: - working-directory: ./langgraph steps: - uses: actions/checkout@v4 @@ -171,12 +162,12 @@ jobs: - uses: actions/download-artifact@v3 with: name: dist - path: ./langgraph/dist/ + path: ./dist/ - name: Publish package distributions to PyPI uses: pypa/gh-action-pypi-publish@release/v1 with: - packages-dir: ./langgraph/dist/ + packages-dir: ./dist/ verbose: true print-hash: true @@ -191,9 +182,6 @@ jobs: # This permission is needed by `ncipollo/release-action` to # create the GitHub release. contents: write - defaults: - run: - working-directory: ./langgraph steps: - uses: actions/checkout@v4 @@ -208,7 +196,7 @@ jobs: - uses: actions/download-artifact@v3 with: name: dist - path: ./langgraph/dist/ + path: ./dist/ - name: Create Release uses: ncipollo/release-action@v1 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 09a97d514..cd8bf9b08 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -10,9 +10,6 @@ env: jobs: build: - defaults: - run: - working-directory: ./langgraph runs-on: ubuntu-latest strategy: matrix: From 21bcf33bc22b148e3a7d4f06fd35a66f52536031 Mon Sep 17 00:00:00 2001 From: Bagatur Date: Sat, 27 Jan 2024 13:08:41 -0800 Subject: [PATCH 4/7] fix --- Makefile | 2 +- langgraph/prebuilt/chat_agent_executor.py | 6 +++--- poetry.lock | 16 ++++++++-------- pyproject.toml | 2 +- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Makefile b/Makefile index 8546ec58d..29a0f5c91 100644 --- a/Makefile +++ b/Makefile @@ -29,7 +29,7 @@ PYTHON_FILES=. MYPY_CACHE=.mypy_cache lint format: PYTHON_FILES=. lint_diff format_diff: PYTHON_FILES=$(shell git diff --name-only --diff-filter=d master | grep -E '\.py$$|\.ipynb$$') -lint_package: PYTHON_FILES=langchain_community +lint_package: PYTHON_FILES=langgraph lint_tests: PYTHON_FILES=tests lint_tests: MYPY_CACHE=.mypy_cache_test diff --git a/langgraph/prebuilt/chat_agent_executor.py b/langgraph/prebuilt/chat_agent_executor.py index 253473416..cda768fe0 100644 --- a/langgraph/prebuilt/chat_agent_executor.py +++ b/langgraph/prebuilt/chat_agent_executor.py @@ -2,7 +2,7 @@ import json import operator from typing import Annotated, Sequence, TypedDict -from langchain.tools.render import format_tool_to_openai_function +from langchain_core.utils.function_calling import convert_to_openai_function from langchain_core.agents import AgentAction from langchain_core.messages import BaseMessage, FunctionMessage from langchain_core.runnables import RunnableLambda @@ -18,8 +18,8 @@ def create_function_calling_executor(model, tools): else: tool_executor = ToolExecutor(tools) tool_classes = tools - model = model.bind_functions( - [format_tool_to_openai_function(t) for t in tool_classes] + model = model.bind( + functions=[convert_to_openai_function(t) for t in tool_classes] ) # Define the function that determines whether to continue or not diff --git a/poetry.lock b/poetry.lock index 163943b30..d3d153410 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1559,19 +1559,19 @@ extended-testing = ["aiosqlite (>=0.19.0,<0.20.0)", "aleph-alpha-client (>=2.15. [[package]] name = "langchain-core" -version = "0.1.8" +version = "0.1.16" description = "Building applications with LLMs through composability" optional = false python-versions = ">=3.8.1,<4.0" files = [ - {file = "langchain_core-0.1.8-py3-none-any.whl", hash = "sha256:f4d1837d6d814ed36528b642211933d1f0bd84e1eff361f4630a8c750acc27d0"}, - {file = "langchain_core-0.1.8.tar.gz", hash = "sha256:93ab72f5ab202526310fad389a45626501fd76ecf56d451111c0d4abe8183407"}, + {file = "langchain_core-0.1.16-py3-none-any.whl", hash = "sha256:c1b2e7363771d64a72cb45032ed5a46facf67de005017fb5e74595cbf433f834"}, + {file = "langchain_core-0.1.16.tar.gz", hash = "sha256:8cb546eed318009ee1a8a381d108074eddf0395ae61eb243db00d76e1e265e89"}, ] [package.dependencies] anyio = ">=3,<5" jsonpatch = ">=1.33,<2.0" -langsmith = ">=0.0.63,<0.1.0" +langsmith = ">=0.0.83,<0.1" packaging = ">=23.2,<24.0" pydantic = ">=1,<3" PyYAML = ">=5.3" @@ -1615,13 +1615,13 @@ types-requests = ">=2.31.0.2,<3.0.0.0" [[package]] name = "langsmith" -version = "0.0.77" +version = "0.0.83" description = "Client library to connect to the LangSmith LLM Tracing and Evaluation Platform." optional = false python-versions = ">=3.8.1,<4.0" files = [ - {file = "langsmith-0.0.77-py3-none-any.whl", hash = "sha256:750c0aa9177240c64e131d831e009ed08dd59038f7cabbd0bbcf62ccb7c8dcac"}, - {file = "langsmith-0.0.77.tar.gz", hash = "sha256:c4c8d3a96ad8671a41064f3ccc673e2e22a4153e823b19f915c9c9b8a4f33a2c"}, + {file = "langsmith-0.0.83-py3-none-any.whl", hash = "sha256:a5bb7ac58c19a415a9d5f51db56dd32ee2cd7343a00825bbc2018312eb3d122a"}, + {file = "langsmith-0.0.83.tar.gz", hash = "sha256:94427846b334ad9bdbec3266fee12903fe9f5448f628667689d0412012aaf392"}, ] [package.dependencies] @@ -3751,4 +3751,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" python-versions = ">=3.9.0,<4.0" -content-hash = "3329b683659a6d0f15ce64a0e7135cfc26affe4c8d19c32dd481e1398cc41b3f" +content-hash = "d3249f92a4868cf796f4e0a51f8c154ac36692560505ba58574edf080ceafc9b" diff --git a/pyproject.toml b/pyproject.toml index 27299d70f..e57b839c6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,7 +9,7 @@ repository = "https://www.github.com/langchain-ai/langgraph" [tool.poetry.dependencies] python = ">=3.9.0,<4.0" -langchain-core = "^0.1.8" +langchain-core = "^0.1.16" [tool.poetry.group.test.dependencies] From ac179f15cbf6b63d54bc9ebeae283e7d6cdf0222 Mon Sep 17 00:00:00 2001 From: Bagatur Date: Sat, 27 Jan 2024 13:34:18 -0800 Subject: [PATCH 5/7] test dep --- poetry.lock | 2 +- pyproject.toml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/poetry.lock b/poetry.lock index d3d153410..61ff075e6 100644 --- a/poetry.lock +++ b/poetry.lock @@ -3751,4 +3751,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" python-versions = ">=3.9.0,<4.0" -content-hash = "d3249f92a4868cf796f4e0a51f8c154ac36692560505ba58574edf080ceafc9b" +content-hash = "faf7cebfb8e64c2edefb69bacdbdd10d8399ea8b3ba9f46c4383e72bd3cd925a" diff --git a/pyproject.toml b/pyproject.toml index e57b839c6..c7a1cdf17 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -24,6 +24,7 @@ pytest-mock = "^3.10.0" syrupy = "^4.0.2" httpx = "^0.26.0" pytest-watcher = "^0.3.4" +langchain = "^0.1.0" [tool.poetry.group.lint.dependencies] ruff = "^0.1.4" From aed2844c20367385db7ba5530eb7d3eee0d89e09 Mon Sep 17 00:00:00 2001 From: Bagatur Date: Sat, 27 Jan 2024 13:38:40 -0800 Subject: [PATCH 6/7] fmt --- langgraph/prebuilt/chat_agent_executor.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/langgraph/prebuilt/chat_agent_executor.py b/langgraph/prebuilt/chat_agent_executor.py index cda768fe0..bc7208107 100644 --- a/langgraph/prebuilt/chat_agent_executor.py +++ b/langgraph/prebuilt/chat_agent_executor.py @@ -2,10 +2,10 @@ import json import operator from typing import Annotated, Sequence, TypedDict -from langchain_core.utils.function_calling import convert_to_openai_function from langchain_core.agents import AgentAction from langchain_core.messages import BaseMessage, FunctionMessage from langchain_core.runnables import RunnableLambda +from langchain_core.utils.function_calling import convert_to_openai_function from langgraph.graph import END, StateGraph from langgraph.prebuilt.tool_executor import ToolExecutor @@ -18,9 +18,7 @@ def create_function_calling_executor(model, tools): else: tool_executor = ToolExecutor(tools) tool_classes = tools - model = model.bind( - functions=[convert_to_openai_function(t) for t in tool_classes] - ) + model = model.bind(functions=[convert_to_openai_function(t) for t in tool_classes]) # Define the function that determines whether to continue or not def should_continue(state): From 303e75c314d1b1b739c14210cb47d625f8ceadc6 Mon Sep 17 00:00:00 2001 From: Bagatur Date: Sat, 27 Jan 2024 14:02:28 -0800 Subject: [PATCH 7/7] rm py3.8 --- .github/workflows/lint.yml | 2 +- .github/workflows/test.yml | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 964707ad0..2d527582e 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -24,7 +24,7 @@ jobs: # Starting new jobs is also relatively slow, # so linting on fewer versions makes CI faster. python-version: - - "3.8" + - "3.9" - "3.11" steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index cd8bf9b08..0109f16e4 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -14,7 +14,6 @@ jobs: strategy: matrix: python-version: - - "3.8" - "3.9" - "3.10" - "3.11"