From c31236264e4835c945729779331f9fca2b558e73 Mon Sep 17 00:00:00 2001 From: Mason Daugherty Date: Fri, 8 Aug 2025 10:20:10 -0400 Subject: [PATCH] chore: formatting across codebase (#32466) --- .devcontainer/README.md | 4 +- .devcontainer/docker-compose.yaml | 2 +- .github/CODE_OF_CONDUCT.md | 2 +- .github/ISSUE_TEMPLATE/bug-report.yml | 8 +- .github/ISSUE_TEMPLATE/documentation.yml | 2 +- .github/ISSUE_TEMPLATE/privileged.yml | 2 +- .github/actions/people/Dockerfile | 2 +- .github/actions/people/action.yml | 6 +- .github/scripts/check_diff.py | 25 +- .../scripts/check_prerelease_dependencies.py | 1 + .github/scripts/get_min_versions.py | 26 +- .github/scripts/prep_api_docs_build.py | 47 +- .github/tools/git-restore-mtime | 416 ++++++++++++------ .github/workflows/_test.yml | 2 +- .github/workflows/_test_pydantic.yml | 2 +- .markdownlint.json | 2 +- cookbook/README.md | 2 +- .../integration_template/README.md | 1 + .../namespaces/migrate/.grit/grit.yaml | 2 +- .../langchain_cli/package_template/README.md | 14 +- .../langchain_cli/project_template/README.md | 8 +- libs/core/langchain_core/callbacks/file.py | 15 +- libs/core/langchain_core/callbacks/manager.py | 71 ++- libs/core/langchain_core/chat_history.py | 12 +- .../langchain_core/documents/compressor.py | 15 +- libs/core/langchain_core/indexing/base.py | 4 +- .../langchain_core/language_models/base.py | 52 ++- .../language_models/chat_models.py | 36 +- .../language_models/fake_chat_models.py | 9 +- libs/core/langchain_core/load/dump.py | 7 +- libs/core/langchain_core/messages/utils.py | 33 +- libs/core/langchain_core/runnables/base.py | 7 +- libs/core/tests/unit_tests/test_imports.py | 5 +- libs/core/tests/unit_tests/test_tools.py | 1 + libs/langchain/README.md | 5 +- .../agents/agent_toolkits/vectorstore/base.py | 10 +- .../langchain/agents/output_parsers/xml.py | 10 +- libs/langchain/langchain/chains/api/base.py | 5 +- .../chains/constitutional_ai/base.py | 5 +- .../langchain/chains/llm_math/base.py | 5 +- .../tests/unit_tests/llms/fake_chat_model.py | 14 +- libs/langchain_v1/README.md | 5 +- .../langchain/_internal/_documents.py | 7 +- .../langchain/_internal/_prompts.py | 17 +- .../langchain/_internal/_typing.py | 22 +- .../langchain/chains/documents/map_reduce.py | 2 +- .../langchain/chains/documents/stuff.py | 2 +- libs/partners/ai21/README.md | 2 +- libs/partners/astradb/README.md | 2 +- libs/partners/ibm/README.md | 2 +- .../langchain_openai/embeddings/azure.py | 7 +- .../openai/langchain_openai/llms/azure.py | 9 +- libs/partners/openai/pyproject.toml | 2 +- .../chat_models/test_base_standard.py | 2 +- .../chat_models/test_responses_standard.py | 2 +- libs/partners/openai/uv.lock | 8 +- libs/partners/prompty/README.md | 2 +- libs/partners/together/README.md | 2 +- .../langchain_text_splitters/__init__.py | 4 +- .../tests/unit_tests/test_text_splitters.py | 8 +- 60 files changed, 635 insertions(+), 369 deletions(-) diff --git a/.devcontainer/README.md b/.devcontainer/README.md index 5c05c844439..8f1b9e43303 100644 --- a/.devcontainer/README.md +++ b/.devcontainer/README.md @@ -15,12 +15,12 @@ You may use the button above, or follow these steps to open this repo in a Codes 1. Click **Create codespace on master**. For more info, check out the [GitHub documentation](https://docs.github.com/en/free-pro-team@latest/github/developing-online-with-codespaces/creating-a-codespace#creating-a-codespace). - + ## VS Code Dev Containers [![Open in Dev Containers](https://img.shields.io/static/v1?label=Dev%20Containers&message=Open&color=blue&logo=visualstudiocode)](https://vscode.dev/redirect?url=vscode://ms-vscode-remote.remote-containers/cloneInVolume?url=https://github.com/langchain-ai/langchain) -> [!NOTE] +> [!NOTE] > If you click the link above you will open the main repo (`langchain-ai/langchain`) and *not* your local cloned repo. This is fine if you only want to run and test the library, but if you want to contribute you can use the link below and replace with your username and cloned repo name: ```txt diff --git a/.devcontainer/docker-compose.yaml b/.devcontainer/docker-compose.yaml index 979950a3b03..199407377b7 100644 --- a/.devcontainer/docker-compose.yaml +++ b/.devcontainer/docker-compose.yaml @@ -4,7 +4,7 @@ services: build: dockerfile: libs/langchain/dev.Dockerfile context: .. - + networks: - langchain-network diff --git a/.github/CODE_OF_CONDUCT.md b/.github/CODE_OF_CONDUCT.md index 23a2a4aec83..12af532b48d 100644 --- a/.github/CODE_OF_CONDUCT.md +++ b/.github/CODE_OF_CONDUCT.md @@ -129,4 +129,4 @@ For answers to common questions about this code of conduct, see the FAQ at [v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html [Mozilla CoC]: https://github.com/mozilla/diversity [FAQ]: https://www.contributor-covenant.org/faq -[translations]: https://www.contributor-covenant.org/translations \ No newline at end of file +[translations]: https://www.contributor-covenant.org/translations diff --git a/.github/ISSUE_TEMPLATE/bug-report.yml b/.github/ISSUE_TEMPLATE/bug-report.yml index e67b62e9930..039fe97d51a 100644 --- a/.github/ISSUE_TEMPLATE/bug-report.yml +++ b/.github/ISSUE_TEMPLATE/bug-report.yml @@ -5,7 +5,7 @@ body: - type: markdown attributes: value: | - Thank you for taking the time to file a bug report. + Thank you for taking the time to file a bug report. Use this to report BUGS in LangChain. For usage questions, feature requests and general design questions, please use the [LangChain Forum](https://forum.langchain.com/). @@ -50,7 +50,7 @@ body: 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!** + **Important!** * Avoid screenshots when possible, as they are hard to read and (more importantly) don't allow others to copy-and-paste your code. * Reduce your code to the minimum required to reproduce the issue if possible. This makes it much easier for others to help you. @@ -58,14 +58,14 @@ body: * INCLUDE the language label (e.g. `python`) after the first three backticks to enable syntax highlighting. (e.g., ```python rather than ```). placeholder: | - The following code: + 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!') ``` diff --git a/.github/ISSUE_TEMPLATE/documentation.yml b/.github/ISSUE_TEMPLATE/documentation.yml index 24510c2f781..a18b49351f5 100644 --- a/.github/ISSUE_TEMPLATE/documentation.yml +++ b/.github/ISSUE_TEMPLATE/documentation.yml @@ -14,7 +14,7 @@ body: Do **NOT** use this to ask usage questions or reporting issues with your code. - If you have usage questions or need help solving some problem, + If you have usage questions or need help solving some problem, please use the [LangChain Forum](https://forum.langchain.com/). If you're in the wrong place, here are some helpful links to find a better diff --git a/.github/ISSUE_TEMPLATE/privileged.yml b/.github/ISSUE_TEMPLATE/privileged.yml index 86859139c41..8950090d6d2 100644 --- a/.github/ISSUE_TEMPLATE/privileged.yml +++ b/.github/ISSUE_TEMPLATE/privileged.yml @@ -8,7 +8,7 @@ body: If you are not a LangChain maintainer or were not asked directly by a maintainer to create an issue, then please start the conversation on the [LangChain Forum](https://forum.langchain.com/) instead. - You are a LangChain maintainer if you maintain any of the packages inside of the LangChain repository + 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 pull requests. - type: checkboxes id: privileged diff --git a/.github/actions/people/Dockerfile b/.github/actions/people/Dockerfile index bf214eea7dc..1455106bde3 100644 --- a/.github/actions/people/Dockerfile +++ b/.github/actions/people/Dockerfile @@ -4,4 +4,4 @@ RUN pip install httpx PyGithub "pydantic==2.0.2" pydantic-settings "pyyaml>=5.3. COPY ./app /app -CMD ["python", "/app/main.py"] \ No newline at end of file +CMD ["python", "/app/main.py"] diff --git a/.github/actions/people/action.yml b/.github/actions/people/action.yml index 15a00c108b4..a517c496a15 100644 --- a/.github/actions/people/action.yml +++ b/.github/actions/people/action.yml @@ -4,8 +4,8 @@ description: "Generate the data for the LangChain People page" author: "Jacob Lee " inputs: token: - description: 'User token, to read the GitHub API. Can be passed in using {{ secrets.LANGCHAIN_PEOPLE_GITHUB_TOKEN }}' + description: "User token, to read the GitHub API. Can be passed in using {{ secrets.LANGCHAIN_PEOPLE_GITHUB_TOKEN }}" required: true runs: - using: 'docker' - image: 'Dockerfile' \ No newline at end of file + using: "docker" + image: "Dockerfile" diff --git a/.github/scripts/check_diff.py b/.github/scripts/check_diff.py index befcc3d590a..418dad30e42 100644 --- a/.github/scripts/check_diff.py +++ b/.github/scripts/check_diff.py @@ -3,14 +3,12 @@ import json import os import sys from collections import defaultdict -from typing import Dict, List, Set from pathlib import Path +from typing import Dict, List, Set + import tomllib - -from packaging.requirements import Requirement - from get_min_versions import get_min_version_from_toml - +from packaging.requirements import Requirement LANGCHAIN_DIRS = [ "libs/core", @@ -38,7 +36,7 @@ IGNORED_PARTNERS = [ ] PY_312_MAX_PACKAGES = [ - "libs/partners/chroma", # https://github.com/chroma-core/chroma/issues/4382 + "libs/partners/chroma", # https://github.com/chroma-core/chroma/issues/4382 ] @@ -85,9 +83,9 @@ def dependents_graph() -> dict: for depline in extended_deps: if depline.startswith("-e "): # editable dependency - assert depline.startswith( - "-e ../partners/" - ), "Extended test deps should only editable install partner packages" + assert depline.startswith("-e ../partners/"), ( + "Extended test deps should only editable install partner packages" + ) partner = depline.split("partners/")[1] dep = f"langchain-{partner}" else: @@ -271,7 +269,7 @@ if __name__ == "__main__": dirs_to_run["extended-test"].add(dir_) elif file.startswith("libs/standard-tests"): # TODO: update to include all packages that rely on standard-tests (all partner packages) - # note: won't run on external repo partners + # Note: won't run on external repo partners dirs_to_run["lint"].add("libs/standard-tests") dirs_to_run["test"].add("libs/standard-tests") dirs_to_run["lint"].add("libs/cli") @@ -285,7 +283,7 @@ if __name__ == "__main__": elif file.startswith("libs/cli"): dirs_to_run["lint"].add("libs/cli") dirs_to_run["test"].add("libs/cli") - + elif file.startswith("libs/partners"): partner_dir = file.split("/")[2] if os.path.isdir(f"libs/partners/{partner_dir}") and [ @@ -303,7 +301,10 @@ if __name__ == "__main__": f"Unknown lib: {file}. check_diff.py likely needs " "an update for this new library!" ) - elif file.startswith("docs/") or file in ["pyproject.toml", "uv.lock"]: # docs or root uv files + elif file.startswith("docs/") or file in [ + "pyproject.toml", + "uv.lock", + ]: # docs or root uv files docs_edited = True dirs_to_run["lint"].add(".") diff --git a/.github/scripts/check_prerelease_dependencies.py b/.github/scripts/check_prerelease_dependencies.py index 1567b100450..20fcad5a97f 100644 --- a/.github/scripts/check_prerelease_dependencies.py +++ b/.github/scripts/check_prerelease_dependencies.py @@ -1,4 +1,5 @@ import sys + import tomllib if __name__ == "__main__": diff --git a/.github/scripts/get_min_versions.py b/.github/scripts/get_min_versions.py index 68270ea4186..91212625b8b 100644 --- a/.github/scripts/get_min_versions.py +++ b/.github/scripts/get_min_versions.py @@ -1,5 +1,5 @@ -from collections import defaultdict import sys +from collections import defaultdict from typing import Optional if sys.version_info >= (3, 11): @@ -8,17 +8,13 @@ else: # for python 3.10 and below, which doesnt have stdlib tomllib import tomli as tomllib -from packaging.requirements import Requirement -from packaging.specifiers import SpecifierSet -from packaging.version import Version - - -import requests -from packaging.version import parse +import re from typing import List -import re - +import requests +from packaging.requirements import Requirement +from packaging.specifiers import SpecifierSet +from packaging.version import Version, parse MIN_VERSION_LIBS = [ "langchain-core", @@ -72,11 +68,13 @@ def get_minimum_version(package_name: str, spec_string: str) -> Optional[str]: spec_string = re.sub(r"\^0\.0\.(\d+)", r"0.0.\1", spec_string) # rewrite occurrences of ^0.y.z to >=0.y.z,<0.y+1 (can be anywhere in constraint string) for y in range(1, 10): - spec_string = re.sub(rf"\^0\.{y}\.(\d+)", rf">=0.{y}.\1,<0.{y+1}", spec_string) + spec_string = re.sub( + rf"\^0\.{y}\.(\d+)", rf">=0.{y}.\1,<0.{y + 1}", spec_string + ) # rewrite occurrences of ^x.y.z to >=x.y.z,={x}.\1.\2,<{x+1}", spec_string + rf"\^{x}\.(\d+)\.(\d+)", rf">={x}.\1.\2,<{x + 1}", spec_string ) spec_set = SpecifierSet(spec_string) @@ -169,12 +167,12 @@ def check_python_version(version_string, constraint_string): # rewrite occurrences of ^0.y.z to >=0.y.z,<0.y+1.0 (can be anywhere in constraint string) for y in range(1, 10): constraint_string = re.sub( - rf"\^0\.{y}\.(\d+)", rf">=0.{y}.\1,<0.{y+1}.0", constraint_string + rf"\^0\.{y}\.(\d+)", rf">=0.{y}.\1,<0.{y + 1}.0", constraint_string ) # rewrite occurrences of ^x.y.z to >=x.y.z,={x}.0.\1,<{x+1}.0.0", constraint_string + rf"\^{x}\.0\.(\d+)", rf">={x}.0.\1,<{x + 1}.0.0", constraint_string ) try: diff --git a/.github/scripts/prep_api_docs_build.py b/.github/scripts/prep_api_docs_build.py index 83c342e019d..4dad98f53c5 100644 --- a/.github/scripts/prep_api_docs_build.py +++ b/.github/scripts/prep_api_docs_build.py @@ -3,9 +3,10 @@ import os import shutil -import yaml from pathlib import Path -from typing import Dict, Any +from typing import Any, Dict + +import yaml def load_packages_yaml() -> Dict[str, Any]: @@ -28,7 +29,6 @@ def get_target_dir(package_name: str) -> Path: def clean_target_directories(packages: list) -> None: """Remove old directories that will be replaced.""" for package in packages: - target_dir = get_target_dir(package["name"]) if target_dir.exists(): print(f"Removing {target_dir}") @@ -38,7 +38,6 @@ def clean_target_directories(packages: list) -> None: def move_libraries(packages: list) -> None: """Move libraries from their source locations to the target directories.""" for package in packages: - repo_name = package["repo"].split("/")[1] source_path = package["path"] target_dir = get_target_dir(package["name"]) @@ -68,23 +67,33 @@ def main(): package_yaml = load_packages_yaml() # Clean target directories - clean_target_directories([ - p - for p in package_yaml["packages"] - if (p["repo"].startswith("langchain-ai/") or p.get("include_in_api_ref")) - and p["repo"] != "langchain-ai/langchain" - and p["name"] != "langchain-ai21" # Skip AI21 due to dependency conflicts - ]) + clean_target_directories( + [ + p + for p in package_yaml["packages"] + if ( + p["repo"].startswith("langchain-ai/") or p.get("include_in_api_ref") + ) + and p["repo"] != "langchain-ai/langchain" + and p["name"] + != "langchain-ai21" # Skip AI21 due to dependency conflicts + ] + ) # Move libraries to their new locations - move_libraries([ - p - for p in package_yaml["packages"] - if not p.get("disabled", False) - and (p["repo"].startswith("langchain-ai/") or p.get("include_in_api_ref")) - and p["repo"] != "langchain-ai/langchain" - and p["name"] != "langchain-ai21" # Skip AI21 due to dependency conflicts - ]) + move_libraries( + [ + p + for p in package_yaml["packages"] + if not p.get("disabled", False) + and ( + p["repo"].startswith("langchain-ai/") or p.get("include_in_api_ref") + ) + and p["repo"] != "langchain-ai/langchain" + and p["name"] + != "langchain-ai21" # Skip AI21 due to dependency conflicts + ] + ) # Delete ones without a pyproject.toml for partner in Path("langchain/libs/partners").iterdir(): diff --git a/.github/tools/git-restore-mtime b/.github/tools/git-restore-mtime index 4d01cb60195..05c25ed635d 100755 --- a/.github/tools/git-restore-mtime +++ b/.github/tools/git-restore-mtime @@ -81,56 +81,93 @@ import time __version__ = "2022.12+dev" # Update symlinks only if the platform supports not following them -UPDATE_SYMLINKS = bool(os.utime in getattr(os, 'supports_follow_symlinks', [])) +UPDATE_SYMLINKS = bool(os.utime in getattr(os, "supports_follow_symlinks", [])) # Call os.path.normpath() only if not in a POSIX platform (Windows) -NORMALIZE_PATHS = (os.path.sep != '/') +NORMALIZE_PATHS = os.path.sep != "/" # How many files to process in each batch when re-trying merge commits STEPMISSING = 100 # (Extra) keywords for the os.utime() call performed by touch() -UTIME_KWS = {} if not UPDATE_SYMLINKS else {'follow_symlinks': False} +UTIME_KWS = {} if not UPDATE_SYMLINKS else {"follow_symlinks": False} # Command-line interface ###################################################### + def parse_args(): - parser = argparse.ArgumentParser( - description=__doc__.split('\n---')[0]) + parser = argparse.ArgumentParser(description=__doc__.split("\n---")[0]) group = parser.add_mutually_exclusive_group() - group.add_argument('--quiet', '-q', dest='loglevel', - action="store_const", const=logging.WARNING, default=logging.INFO, - help="Suppress informative messages and summary statistics.") - group.add_argument('--verbose', '-v', action="count", help=""" + group.add_argument( + "--quiet", + "-q", + dest="loglevel", + action="store_const", + const=logging.WARNING, + default=logging.INFO, + help="Suppress informative messages and summary statistics.", + ) + group.add_argument( + "--verbose", + "-v", + action="count", + help=""" Print additional information for each processed file. Specify twice to further increase verbosity. - """) + """, + ) - parser.add_argument('--cwd', '-C', metavar="DIRECTORY", help=""" + parser.add_argument( + "--cwd", + "-C", + metavar="DIRECTORY", + help=""" Run as if %(prog)s was started in directory %(metavar)s. This affects how --work-tree, --git-dir and PATHSPEC arguments are handled. See 'man 1 git' or 'git --help' for more information. - """) + """, + ) - parser.add_argument('--git-dir', dest='gitdir', metavar="GITDIR", help=""" + parser.add_argument( + "--git-dir", + dest="gitdir", + metavar="GITDIR", + help=""" Path to the git repository, by default auto-discovered by searching the current directory and its parents for a .git/ subdirectory. - """) + """, + ) - parser.add_argument('--work-tree', dest='workdir', metavar="WORKTREE", help=""" + parser.add_argument( + "--work-tree", + dest="workdir", + metavar="WORKTREE", + help=""" Path to the work tree root, by default the parent of GITDIR if it's automatically discovered, or the current directory if GITDIR is set. - """) + """, + ) - parser.add_argument('--force', '-f', default=False, action="store_true", help=""" + parser.add_argument( + "--force", + "-f", + default=False, + action="store_true", + help=""" Force updating files with uncommitted modifications. Untracked files and uncommitted deletions, renames and additions are always ignored. - """) + """, + ) - parser.add_argument('--merge', '-m', default=False, action="store_true", help=""" + parser.add_argument( + "--merge", + "-m", + default=False, + action="store_true", + help=""" Include merge commits. Leads to more recent times and more files per commit, thus with the same time, which may or may not be what you want. @@ -138,71 +175,130 @@ def parse_args(): are found sooner, which can improve performance, sometimes substantially. But as merge commits are usually huge, processing them may also take longer. By default, merge commits are only used for files missing from regular commits. - """) + """, + ) - parser.add_argument('--first-parent', default=False, action="store_true", help=""" + parser.add_argument( + "--first-parent", + default=False, + action="store_true", + help=""" Consider only the first parent, the "main branch", when evaluating merge commits. Only effective when merge commits are processed, either when --merge is used or when finding missing files after the first regular log search. See --skip-missing. - """) + """, + ) - parser.add_argument('--skip-missing', '-s', dest="missing", default=True, - action="store_false", help=""" + parser.add_argument( + "--skip-missing", + "-s", + dest="missing", + default=True, + action="store_false", + help=""" Do not try to find missing files. If merge commits were not evaluated with --merge and some files were not found in regular commits, by default %(prog)s searches for these files again in the merge commits. This option disables this retry, so files found only in merge commits will not have their timestamp updated. - """) + """, + ) - parser.add_argument('--no-directories', '-D', dest='dirs', default=True, - action="store_false", help=""" + parser.add_argument( + "--no-directories", + "-D", + dest="dirs", + default=True, + action="store_false", + help=""" Do not update directory timestamps. By default, use the time of its most recently created, renamed or deleted file. Note that just modifying a file will NOT update its directory time. - """) + """, + ) - parser.add_argument('--test', '-t', default=False, action="store_true", - help="Test run: do not actually update any file timestamp.") + parser.add_argument( + "--test", + "-t", + default=False, + action="store_true", + help="Test run: do not actually update any file timestamp.", + ) - parser.add_argument('--commit-time', '-c', dest='commit_time', default=False, - action='store_true', help="Use commit time instead of author time.") + parser.add_argument( + "--commit-time", + "-c", + dest="commit_time", + default=False, + action="store_true", + help="Use commit time instead of author time.", + ) - parser.add_argument('--oldest-time', '-o', dest='reverse_order', default=False, - action='store_true', help=""" + parser.add_argument( + "--oldest-time", + "-o", + dest="reverse_order", + default=False, + action="store_true", + help=""" Update times based on the oldest, instead of the most recent commit of a file. This reverses the order in which the git log is processed to emulate a file "creation" date. Note this will be inaccurate for files deleted and re-created at later dates. - """) + """, + ) - parser.add_argument('--skip-older-than', metavar='SECONDS', type=int, help=""" + parser.add_argument( + "--skip-older-than", + metavar="SECONDS", + type=int, + help=""" Ignore files that are currently older than %(metavar)s. Useful in workflows that assume such files already have a correct timestamp, as it may improve performance by processing fewer files. - """) + """, + ) - parser.add_argument('--skip-older-than-commit', '-N', default=False, - action='store_true', help=""" + parser.add_argument( + "--skip-older-than-commit", + "-N", + default=False, + action="store_true", + help=""" Ignore files older than the timestamp it would be updated to. Such files may be considered "original", likely in the author's repository. - """) + """, + ) - parser.add_argument('--unique-times', default=False, action="store_true", help=""" + parser.add_argument( + "--unique-times", + default=False, + action="store_true", + help=""" Set the microseconds to a unique value per commit. Allows telling apart changes that would otherwise have identical timestamps, as git's time accuracy is in seconds. - """) + """, + ) - parser.add_argument('pathspec', nargs='*', metavar='PATHSPEC', help=""" + parser.add_argument( + "pathspec", + nargs="*", + metavar="PATHSPEC", + help=""" Only modify paths matching %(metavar)s, relative to current directory. By default, update all but untracked files and submodules. - """) + """, + ) - parser.add_argument('--version', '-V', action='version', - version='%(prog)s version {version}'.format(version=get_version())) + parser.add_argument( + "--version", + "-V", + action="version", + version="%(prog)s version {version}".format(version=get_version()), + ) args_ = parser.parse_args() if args_.verbose: @@ -212,17 +308,18 @@ def parse_args(): def get_version(version=__version__): - if not version.endswith('+dev'): + if not version.endswith("+dev"): return version try: cwd = os.path.dirname(os.path.realpath(__file__)) - return Git(cwd=cwd, errors=False).describe().lstrip('v') + return Git(cwd=cwd, errors=False).describe().lstrip("v") except Git.Error: - return '-'.join((version, "unknown")) + return "-".join((version, "unknown")) # Helper functions ############################################################ + def setup_logging(): """Add TRACE logging level and corresponding method, return the root logger""" logging.TRACE = TRACE = logging.DEBUG // 2 @@ -255,11 +352,13 @@ def normalize(path): if path and path[0] == '"': # Python 2: path = path[1:-1].decode("string-escape") # Python 3: https://stackoverflow.com/a/46650050/624066 - path = (path[1:-1] # Remove enclosing double quotes - .encode('latin1') # Convert to bytes, required by 'unicode-escape' - .decode('unicode-escape') # Perform the actual octal-escaping decode - .encode('latin1') # 1:1 mapping to bytes, UTF-8 encoded - .decode('utf8', 'surrogateescape')) # Decode from UTF-8 + path = ( + path[1:-1] # Remove enclosing double quotes + .encode("latin1") # Convert to bytes, required by 'unicode-escape' + .decode("unicode-escape") # Perform the actual octal-escaping decode + .encode("latin1") # 1:1 mapping to bytes, UTF-8 encoded + .decode("utf8", "surrogateescape") + ) # Decode from UTF-8 if NORMALIZE_PATHS: # Make sure the slash matches the OS; for Windows we need a backslash path = os.path.normpath(path) @@ -282,12 +381,12 @@ def touch_ns(path, mtime_ns): def isodate(secs: int): # time.localtime() accepts floats, but discards fractional part - return time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(secs)) + return time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(secs)) def isodate_ns(ns: int): # for integers fromtimestamp() is equivalent and ~16% slower than isodate() - return datetime.datetime.fromtimestamp(ns / 1000000000).isoformat(sep=' ') + return datetime.datetime.fromtimestamp(ns / 1000000000).isoformat(sep=" ") def get_mtime_ns(secs: int, idx: int): @@ -305,35 +404,49 @@ def get_mtime_path(path): # Git class and parse_log(), the heart of the script ########################## + class Git: def __init__(self, workdir=None, gitdir=None, cwd=None, errors=True): - self.gitcmd = ['git'] + self.gitcmd = ["git"] self.errors = errors self._proc = None - if workdir: self.gitcmd.extend(('--work-tree', workdir)) - if gitdir: self.gitcmd.extend(('--git-dir', gitdir)) - if cwd: self.gitcmd.extend(('-C', cwd)) + if workdir: + self.gitcmd.extend(("--work-tree", workdir)) + if gitdir: + self.gitcmd.extend(("--git-dir", gitdir)) + if cwd: + self.gitcmd.extend(("-C", cwd)) self.workdir, self.gitdir = self._get_repo_dirs() def ls_files(self, paths: list = None): - return (normalize(_) for _ in self._run('ls-files --full-name', paths)) + return (normalize(_) for _ in self._run("ls-files --full-name", paths)) def ls_dirty(self, force=False): - return (normalize(_[3:].split(' -> ', 1)[-1]) - for _ in self._run('status --porcelain') - if _[:2] != '??' and (not force or (_[0] in ('R', 'A') - or _[1] == 'D'))) + return ( + normalize(_[3:].split(" -> ", 1)[-1]) + for _ in self._run("status --porcelain") + if _[:2] != "??" and (not force or (_[0] in ("R", "A") or _[1] == "D")) + ) - def log(self, merge=False, first_parent=False, commit_time=False, - reverse_order=False, paths: list = None): - cmd = 'whatchanged --pretty={}'.format('%ct' if commit_time else '%at') - if merge: cmd += ' -m' - if first_parent: cmd += ' --first-parent' - if reverse_order: cmd += ' --reverse' + def log( + self, + merge=False, + first_parent=False, + commit_time=False, + reverse_order=False, + paths: list = None, + ): + cmd = "whatchanged --pretty={}".format("%ct" if commit_time else "%at") + if merge: + cmd += " -m" + if first_parent: + cmd += " --first-parent" + if reverse_order: + cmd += " --reverse" return self._run(cmd, paths) def describe(self): - return self._run('describe --tags', check=True)[0] + return self._run("describe --tags", check=True)[0] def terminate(self): if self._proc is None: @@ -345,18 +458,22 @@ class Git: pass def _get_repo_dirs(self): - return (os.path.normpath(_) for _ in - self._run('rev-parse --show-toplevel --absolute-git-dir', check=True)) + return ( + os.path.normpath(_) + for _ in self._run( + "rev-parse --show-toplevel --absolute-git-dir", check=True + ) + ) def _run(self, cmdstr: str, paths: list = None, output=True, check=False): cmdlist = self.gitcmd + shlex.split(cmdstr) if paths: - cmdlist.append('--') + cmdlist.append("--") cmdlist.extend(paths) - popen_args = dict(universal_newlines=True, encoding='utf8') + popen_args = dict(universal_newlines=True, encoding="utf8") if not self.errors: - popen_args['stderr'] = subprocess.DEVNULL - log.trace("Executing: %s", ' '.join(cmdlist)) + popen_args["stderr"] = subprocess.DEVNULL + log.trace("Executing: %s", " ".join(cmdlist)) if not output: return subprocess.call(cmdlist, **popen_args) if check: @@ -379,30 +496,26 @@ def parse_log(filelist, dirlist, stats, git, merge=False, filterlist=None): mtime = 0 datestr = isodate(0) for line in git.log( - merge, - args.first_parent, - args.commit_time, - args.reverse_order, - filterlist + merge, args.first_parent, args.commit_time, args.reverse_order, filterlist ): - stats['loglines'] += 1 + stats["loglines"] += 1 # Blank line between Date and list of files if not line: continue # Date line - if line[0] != ':': # Faster than `not line.startswith(':')` - stats['commits'] += 1 + if line[0] != ":": # Faster than `not line.startswith(':')` + stats["commits"] += 1 mtime = int(line) if args.unique_times: - mtime = get_mtime_ns(mtime, stats['commits']) + mtime = get_mtime_ns(mtime, stats["commits"]) if args.debug: datestr = isodate(mtime) continue # File line: three tokens if it describes a renaming, otherwise two - tokens = line.split('\t') + tokens = line.split("\t") # Possible statuses: # M: Modified (content changed) @@ -411,7 +524,7 @@ def parse_log(filelist, dirlist, stats, git, merge=False, filterlist=None): # T: Type changed: to/from regular file, symlinks, submodules # R099: Renamed (moved), with % of unchanged content. 100 = pure rename # Not possible in log: C=Copied, U=Unmerged, X=Unknown, B=pairing Broken - status = tokens[0].split(' ')[-1] + status = tokens[0].split(" ")[-1] file = tokens[-1] # Handles non-ASCII chars and OS path separator @@ -419,56 +532,76 @@ def parse_log(filelist, dirlist, stats, git, merge=False, filterlist=None): def do_file(): if args.skip_older_than_commit and get_mtime_path(file) <= mtime: - stats['skip'] += 1 + stats["skip"] += 1 return if args.debug: - log.debug("%d\t%d\t%d\t%s\t%s", - stats['loglines'], stats['commits'], stats['files'], - datestr, file) + log.debug( + "%d\t%d\t%d\t%s\t%s", + stats["loglines"], + stats["commits"], + stats["files"], + datestr, + file, + ) try: touch(os.path.join(git.workdir, file), mtime) - stats['touches'] += 1 + stats["touches"] += 1 except Exception as e: log.error("ERROR: %s: %s", e, file) - stats['errors'] += 1 + stats["errors"] += 1 def do_dir(): if args.debug: - log.debug("%d\t%d\t-\t%s\t%s", - stats['loglines'], stats['commits'], - datestr, "{}/".format(dirname or '.')) + log.debug( + "%d\t%d\t-\t%s\t%s", + stats["loglines"], + stats["commits"], + datestr, + "{}/".format(dirname or "."), + ) try: touch(os.path.join(git.workdir, dirname), mtime) - stats['dirtouches'] += 1 + stats["dirtouches"] += 1 except Exception as e: log.error("ERROR: %s: %s", e, dirname) - stats['direrrors'] += 1 + stats["direrrors"] += 1 if file in filelist: - stats['files'] -= 1 + stats["files"] -= 1 filelist.remove(file) do_file() - if args.dirs and status in ('A', 'D'): + if args.dirs and status in ("A", "D"): dirname = os.path.dirname(file) if dirname in dirlist: dirlist.remove(dirname) do_dir() # All files done? - if not stats['files']: + if not stats["files"]: git.terminate() return # Main Logic ################################################################## + def main(): start = time.time() # yes, Wall time. CPU time is not realistic for users. - stats = {_: 0 for _ in ('loglines', 'commits', 'touches', 'skip', 'errors', - 'dirtouches', 'direrrors')} + stats = { + _: 0 + for _ in ( + "loglines", + "commits", + "touches", + "skip", + "errors", + "dirtouches", + "direrrors", + ) + } - logging.basicConfig(level=args.loglevel, format='%(message)s') + logging.basicConfig(level=args.loglevel, format="%(message)s") log.trace("Arguments: %s", args) # First things first: Where and Who are we? @@ -499,13 +632,16 @@ def main(): # Symlink (to file, to dir or broken - git handles the same way) if not UPDATE_SYMLINKS and os.path.islink(fullpath): - log.warning("WARNING: Skipping symlink, no OS support for updates: %s", - path) + log.warning( + "WARNING: Skipping symlink, no OS support for updates: %s", path + ) continue # skip files which are older than given threshold - if (args.skip_older_than - and start - get_mtime_path(fullpath) > args.skip_older_than): + if ( + args.skip_older_than + and start - get_mtime_path(fullpath) > args.skip_older_than + ): continue # Always add files relative to worktree root @@ -519,15 +655,17 @@ def main(): else: dirty = set(git.ls_dirty()) if dirty: - log.warning("WARNING: Modified files in the working directory were ignored." - "\nTo include such files, commit your changes or use --force.") + log.warning( + "WARNING: Modified files in the working directory were ignored." + "\nTo include such files, commit your changes or use --force." + ) filelist -= dirty # Build dir list to be processed dirlist = set(os.path.dirname(_) for _ in filelist) if args.dirs else set() - stats['totalfiles'] = stats['files'] = len(filelist) - log.info("{0:,} files to be processed in work dir".format(stats['totalfiles'])) + stats["totalfiles"] = stats["files"] = len(filelist) + log.info("{0:,} files to be processed in work dir".format(stats["totalfiles"])) if not filelist: # Nothing to do. Exit silently and without errors, just like git does @@ -544,10 +682,18 @@ def main(): if args.missing and not args.merge: filterlist = list(filelist) missing = len(filterlist) - log.info("{0:,} files not found in log, trying merge commits".format(missing)) + log.info( + "{0:,} files not found in log, trying merge commits".format(missing) + ) for i in range(0, missing, STEPMISSING): - parse_log(filelist, dirlist, stats, git, - merge=True, filterlist=filterlist[i:i + STEPMISSING]) + parse_log( + filelist, + dirlist, + stats, + git, + merge=True, + filterlist=filterlist[i : i + STEPMISSING], + ) # Still missing some? for file in filelist: @@ -556,29 +702,33 @@ def main(): # Final statistics # Suggestion: use git-log --before=mtime to brag about skipped log entries def log_info(msg, *a, width=13): - ifmt = '{:%d,}' % (width,) # not using 'n' for consistency with ffmt - ffmt = '{:%d,.2f}' % (width,) + ifmt = "{:%d,}" % (width,) # not using 'n' for consistency with ffmt + ffmt = "{:%d,.2f}" % (width,) # %-formatting lacks a thousand separator, must pre-render with .format() - log.info(msg.replace('%d', ifmt).replace('%f', ffmt).format(*a)) + log.info(msg.replace("%d", ifmt).replace("%f", ffmt).format(*a)) log_info( - "Statistics:\n" - "%f seconds\n" - "%d log lines processed\n" - "%d commits evaluated", - time.time() - start, stats['loglines'], stats['commits']) + "Statistics:\n%f seconds\n%d log lines processed\n%d commits evaluated", + time.time() - start, + stats["loglines"], + stats["commits"], + ) if args.dirs: - if stats['direrrors']: log_info("%d directory update errors", stats['direrrors']) - log_info("%d directories updated", stats['dirtouches']) + if stats["direrrors"]: + log_info("%d directory update errors", stats["direrrors"]) + log_info("%d directories updated", stats["dirtouches"]) - if stats['touches'] != stats['totalfiles']: - log_info("%d files", stats['totalfiles']) - if stats['skip']: log_info("%d files skipped", stats['skip']) - if stats['files']: log_info("%d files missing", stats['files']) - if stats['errors']: log_info("%d file update errors", stats['errors']) + if stats["touches"] != stats["totalfiles"]: + log_info("%d files", stats["totalfiles"]) + if stats["skip"]: + log_info("%d files skipped", stats["skip"]) + if stats["files"]: + log_info("%d files missing", stats["files"]) + if stats["errors"]: + log_info("%d file update errors", stats["errors"]) - log_info("%d files updated", stats['touches']) + log_info("%d files updated", stats["touches"]) if args.test: log.info("TEST RUN - No files modified!") diff --git a/.github/workflows/_test.yml b/.github/workflows/_test.yml index 0deb2b53592..2b26e6cfa51 100644 --- a/.github/workflows/_test.yml +++ b/.github/workflows/_test.yml @@ -79,4 +79,4 @@ jobs: # 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/.github/workflows/_test_pydantic.yml b/.github/workflows/_test_pydantic.yml index a6b6b183755..2e2b7cfe841 100644 --- a/.github/workflows/_test_pydantic.yml +++ b/.github/workflows/_test_pydantic.yml @@ -64,4 +64,4 @@ jobs: # 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' \ No newline at end of file + echo "$STATUS" | grep 'nothing to commit, working tree clean' diff --git a/.markdownlint.json b/.markdownlint.json index cef22e62961..1da2ca701c0 100644 --- a/.markdownlint.json +++ b/.markdownlint.json @@ -11,4 +11,4 @@ "MD046": { "style": "fenced" } -} \ No newline at end of file +} diff --git a/cookbook/README.md b/cookbook/README.md index 6b18e508af7..09df1167e1e 100644 --- a/cookbook/README.md +++ b/cookbook/README.md @@ -63,4 +63,4 @@ Notebook | Description [rag-locally-on-intel-cpu.ipynb](https://github.com/langchain-ai/langchain/tree/master/cookbook/rag-locally-on-intel-cpu.ipynb) | Perform Retrieval-Augmented-Generation (RAG) on locally downloaded open-source models using langchain and open source tools and execute it on Intel Xeon CPU. We showed an example of how to apply RAG on Llama 2 model and enable it to answer the queries related to Intel Q1 2024 earnings release. [visual_RAG_vdms.ipynb](https://github.com/langchain-ai/langchain/tree/master/cookbook/visual_RAG_vdms.ipynb) | Performs Visual Retrieval-Augmented-Generation (RAG) using videos and scene descriptions generated by open source models. [contextual_rag.ipynb](https://github.com/langchain-ai/langchain/tree/master/cookbook/contextual_rag.ipynb) | Performs contextual retrieval-augmented generation (RAG) prepending chunk-specific explanatory context to each chunk before embedding. -[rag-agents-locally-on-intel-cpu.ipynb](https://github.com/langchain-ai/langchain/tree/master/cookbook/local_rag_agents_intel_cpu.ipynb) | Build a RAG agent locally with open source models that routes questions through one of two paths to find answers. The agent generates answers based on documents retrieved from either the vector database or retrieved from web search. If the vector database lacks relevant information, the agent opts for web search. Open-source models for LLM and embeddings are used locally on an Intel Xeon CPU to execute this pipeline. \ No newline at end of file +[rag-agents-locally-on-intel-cpu.ipynb](https://github.com/langchain-ai/langchain/tree/master/cookbook/local_rag_agents_intel_cpu.ipynb) | Build a RAG agent locally with open source models that routes questions through one of two paths to find answers. The agent generates answers based on documents retrieved from either the vector database or retrieved from web search. If the vector database lacks relevant information, the agent opts for web search. Open-source models for LLM and embeddings are used locally on an Intel Xeon CPU to execute this pipeline. diff --git a/libs/cli/langchain_cli/integration_template/README.md b/libs/cli/langchain_cli/integration_template/README.md index 19c73c4a5ba..f8d70df8005 100644 --- a/libs/cli/langchain_cli/integration_template/README.md +++ b/libs/cli/langchain_cli/integration_template/README.md @@ -35,6 +35,7 @@ embeddings.embed_query("What is the meaning of life?") ``` ## LLMs + `__ModuleName__LLM` class exposes LLMs from __ModuleName__. ```python diff --git a/libs/cli/langchain_cli/namespaces/migrate/.grit/grit.yaml b/libs/cli/langchain_cli/namespaces/migrate/.grit/grit.yaml index 64198e46ce4..c93f16d6ecd 100644 --- a/libs/cli/langchain_cli/namespaces/migrate/.grit/grit.yaml +++ b/libs/cli/langchain_cli/namespaces/migrate/.grit/grit.yaml @@ -1,3 +1,3 @@ version: 0.0.1 patterns: - - name: github.com/getgrit/stdlib#* \ No newline at end of file + - name: github.com/getgrit/stdlib#* diff --git a/libs/cli/langchain_cli/package_template/README.md b/libs/cli/langchain_cli/package_template/README.md index 38d5efe839b..c0c98eb6844 100644 --- a/libs/cli/langchain_cli/package_template/README.md +++ b/libs/cli/langchain_cli/package_template/README.md @@ -27,16 +27,16 @@ langchain app add __package_name__ ``` And add the following code to your `server.py` file: + ```python __app_route_code__ ``` -(Optional) Let's now configure LangSmith. -LangSmith will help us trace, monitor and debug LangChain applications. -You can sign up for LangSmith [here](https://smith.langchain.com/). +(Optional) Let's now configure LangSmith. +LangSmith will help us trace, monitor and debug LangChain applications. +You can sign up for LangSmith [here](https://smith.langchain.com/). If you don't have access, you can skip this section - ```shell export LANGSMITH_TRACING=true export LANGSMITH_API_KEY= @@ -49,11 +49,11 @@ If you are inside this directory, then you can spin up a LangServe instance dire langchain serve ``` -This will start the FastAPI app with a server is running locally at +This will start the FastAPI app with a server is running locally at [http://localhost:8000](http://localhost:8000) We can see all templates at [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs) -We can access the playground at [http://127.0.0.1:8000/__package_name__/playground](http://127.0.0.1:8000/__package_name__/playground) +We can access the playground at [http://127.0.0.1:8000/__package_name__/playground](http://127.0.0.1:8000/__package_name__/playground) We can access the template from code with: @@ -61,4 +61,4 @@ We can access the template from code with: from langserve.client import RemoteRunnable runnable = RemoteRunnable("http://localhost:8000/__package_name__") -``` \ No newline at end of file +``` diff --git a/libs/cli/langchain_cli/project_template/README.md b/libs/cli/langchain_cli/project_template/README.md index 73a49981452..d9b3f59e550 100644 --- a/libs/cli/langchain_cli/project_template/README.md +++ b/libs/cli/langchain_cli/project_template/README.md @@ -11,7 +11,7 @@ pip install -U langchain-cli ## Adding packages ```bash -# adding packages from +# adding packages from # https://github.com/langchain-ai/langchain/tree/master/templates langchain app add $PROJECT_NAME @@ -31,10 +31,10 @@ langchain app remove my/custom/path/rag ``` ## Setup LangSmith (Optional) -LangSmith will help us trace, monitor and debug LangChain applications. -You can sign up for LangSmith [here](https://smith.langchain.com/). -If you don't have access, you can skip this section +LangSmith will help us trace, monitor and debug LangChain applications. +You can sign up for LangSmith [here](https://smith.langchain.com/). +If you don't have access, you can skip this section ```shell export LANGSMITH_TRACING=true diff --git a/libs/core/langchain_core/callbacks/file.py b/libs/core/langchain_core/callbacks/file.py index 7e948dc29ac..d6edf2d0455 100644 --- a/libs/core/langchain_core/callbacks/file.py +++ b/libs/core/langchain_core/callbacks/file.py @@ -49,7 +49,7 @@ class FileCallbackHandler(BaseCallbackHandler): mode: The file open mode. Defaults to ``'a'`` (append). color: Default color for text output. Defaults to ``None``. - Note: + .. note:: When not used as a context manager, a deprecation warning will be issued on first use. The file will be opened immediately in ``__init__`` and closed in ``__del__`` or when ``close()`` is called explicitly. @@ -65,6 +65,7 @@ class FileCallbackHandler(BaseCallbackHandler): filename: Path to the output file. mode: File open mode (e.g., ``'w'``, ``'a'``, ``'x'``). Defaults to ``'a'``. color: Default text color for output. Defaults to ``None``. + """ self.filename = filename self.mode = mode @@ -82,9 +83,10 @@ class FileCallbackHandler(BaseCallbackHandler): Returns: The FileCallbackHandler instance. - Note: + .. note:: The file is already opened in ``__init__``, so this just marks that the handler is being used as a context manager. + """ self._file_opened_in_context = True return self @@ -101,6 +103,7 @@ class FileCallbackHandler(BaseCallbackHandler): exc_type: Exception type if an exception occurred. exc_val: Exception value if an exception occurred. exc_tb: Exception traceback if an exception occurred. + """ self.close() @@ -113,6 +116,7 @@ class FileCallbackHandler(BaseCallbackHandler): This method is safe to call multiple times and will only close the file if it's currently open. + """ if hasattr(self, "file") and self.file and not self.file.closed: self.file.close() @@ -133,6 +137,7 @@ class FileCallbackHandler(BaseCallbackHandler): Raises: RuntimeError: If the file is closed or not available. + """ global _GLOBAL_DEPRECATION_WARNED # noqa: PLW0603 if not self._file_opened_in_context and not _GLOBAL_DEPRECATION_WARNED: @@ -163,6 +168,7 @@ class FileCallbackHandler(BaseCallbackHandler): serialized: The serialized chain information. inputs: The inputs to the chain. **kwargs: Additional keyword arguments that may contain ``'name'``. + """ name = ( kwargs.get("name") @@ -178,6 +184,7 @@ class FileCallbackHandler(BaseCallbackHandler): Args: outputs: The outputs of the chain. **kwargs: Additional keyword arguments. + """ self._write("\n> Finished chain.", end="\n") @@ -192,6 +199,7 @@ class FileCallbackHandler(BaseCallbackHandler): color: Color override for this specific output. If ``None``, uses ``self.color``. **kwargs: Additional keyword arguments. + """ self._write(action.log, color=color or self.color) @@ -213,6 +221,7 @@ class FileCallbackHandler(BaseCallbackHandler): observation_prefix: Optional prefix to write before the output. llm_prefix: Optional prefix to write after the output. **kwargs: Additional keyword arguments. + """ if observation_prefix is not None: self._write(f"\n{observation_prefix}") @@ -232,6 +241,7 @@ class FileCallbackHandler(BaseCallbackHandler): ``self.color``. end: String appended after the text. Defaults to ``""``. **kwargs: Additional keyword arguments. + """ self._write(text, color=color or self.color, end=end) @@ -246,5 +256,6 @@ class FileCallbackHandler(BaseCallbackHandler): color: Color override for this specific output. If ``None``, uses ``self.color``. **kwargs: Additional keyword arguments. + """ self._write(finish.log, color=color or self.color, end="\n") diff --git a/libs/core/langchain_core/callbacks/manager.py b/libs/core/langchain_core/callbacks/manager.py index 56fc1bb67ba..90009fd5a0f 100644 --- a/libs/core/langchain_core/callbacks/manager.py +++ b/libs/core/langchain_core/callbacks/manager.py @@ -11,15 +11,7 @@ from abc import ABC, abstractmethod from concurrent.futures import ThreadPoolExecutor from contextlib import asynccontextmanager, contextmanager from contextvars import copy_context -from typing import ( - TYPE_CHECKING, - Any, - Callable, - Optional, - TypeVar, - Union, - cast, -) +from typing import TYPE_CHECKING, Any, Callable, Optional, TypeVar, Union, cast from uuid import UUID from langsmith.run_helpers import get_tracing_context @@ -92,7 +84,8 @@ def trace_as_chain_group( metadata (dict[str, Any], optional): The metadata to apply to all runs. Defaults to None. - Note: must have LANGCHAIN_TRACING_V2 env var set to true to see the trace in LangSmith. + .. note: + Must have ``LANGCHAIN_TRACING_V2`` env var set to true to see the trace in LangSmith. Returns: CallbackManagerForChainGroup: The callback manager for the chain group. @@ -177,7 +170,8 @@ async def atrace_as_chain_group( Returns: AsyncCallbackManager: The async callback manager for the chain group. - Note: must have LANGCHAIN_TRACING_V2 env var set to true to see the trace in LangSmith. + .. note: + Must have ``LANGCHAIN_TRACING_V2`` env var set to true to see the trace in LangSmith. Example: .. code-block:: python @@ -234,6 +228,7 @@ def shielded(func: Func) -> Func: Returns: Callable: The shielded function + """ @functools.wraps(func) @@ -252,15 +247,17 @@ def handle_event( ) -> None: """Generic event handler for CallbackManager. - Note: This function is used by LangServe to handle events. + .. note:: + This function is used by ``LangServe`` to handle events. Args: handlers: The list of handlers that will handle the event. - event_name: The name of the event (e.g., "on_llm_start"). + event_name: The name of the event (e.g., ``'on_llm_start'``). ignore_condition_name: Name of the attribute defined on handler that if True will cause the handler to be skipped for the given event. *args: The arguments to pass to the event handler. **kwargs: The keyword arguments to pass to the event handler + """ coros: list[Coroutine[Any, Any, Any]] = [] @@ -415,17 +412,19 @@ async def ahandle_event( *args: Any, **kwargs: Any, ) -> None: - """Async generic event handler for AsyncCallbackManager. + """Async generic event handler for ``AsyncCallbackManager``. - Note: This function is used by LangServe to handle events. + .. note:: + This function is used by ``LangServe`` to handle events. Args: handlers: The list of handlers that will handle the event. - event_name: The name of the event (e.g., "on_llm_start"). + event_name: The name of the event (e.g., ``'on_llm_start'``). ignore_condition_name: Name of the attribute defined on handler that if True will cause the handler to be skipped for the given event. *args: The arguments to pass to the event handler. **kwargs: The keyword arguments to pass to the event handler. + """ for handler in [h for h in handlers if h.run_inline]: await _ahandle_event_for_handler( @@ -477,6 +476,7 @@ class BaseRunManager(RunManagerMixin): Defaults to None. inheritable_metadata (Optional[dict[str, Any]]): The inheritable metadata. Defaults to None. + """ self.run_id = run_id self.handlers = handlers @@ -493,6 +493,7 @@ class BaseRunManager(RunManagerMixin): Returns: BaseRunManager: The noop manager. + """ return cls( run_id=uuid.uuid4(), @@ -545,6 +546,7 @@ class RunManager(BaseRunManager): Args: retry_state (RetryCallState): The retry state. **kwargs (Any): Additional keyword arguments. + """ if not self.handlers: return @@ -572,6 +574,7 @@ class ParentRunManager(RunManager): Returns: CallbackManager: The child callback manager. + """ manager = CallbackManager(handlers=[], parent_run_id=self.run_id) manager.set_handlers(self.inheritable_handlers) @@ -591,6 +594,7 @@ class AsyncRunManager(BaseRunManager, ABC): Returns: RunManager: The sync RunManager. + """ async def on_text( @@ -606,6 +610,7 @@ class AsyncRunManager(BaseRunManager, ABC): Returns: Any: The result of the callback. + """ if not self.handlers: return @@ -630,6 +635,7 @@ class AsyncRunManager(BaseRunManager, ABC): Args: retry_state (RetryCallState): The retry state. **kwargs (Any): Additional keyword arguments. + """ if not self.handlers: return @@ -657,6 +663,7 @@ class AsyncParentRunManager(AsyncRunManager): Returns: AsyncCallbackManager: The child callback manager. + """ manager = AsyncCallbackManager(handlers=[], parent_run_id=self.run_id) manager.set_handlers(self.inheritable_handlers) @@ -684,6 +691,7 @@ class CallbackManagerForLLMRun(RunManager, LLMManagerMixin): chunk (Optional[Union[GenerationChunk, ChatGenerationChunk]], optional): The chunk. Defaults to None. **kwargs (Any): Additional keyword arguments. + """ if not self.handlers: return @@ -705,6 +713,7 @@ class CallbackManagerForLLMRun(RunManager, LLMManagerMixin): Args: response (LLMResult): The LLM result. **kwargs (Any): Additional keyword arguments. + """ if not self.handlers: return @@ -754,6 +763,7 @@ class AsyncCallbackManagerForLLMRun(AsyncRunManager, LLMManagerMixin): Returns: CallbackManagerForLLMRun: The sync RunManager. + """ return CallbackManagerForLLMRun( run_id=self.run_id, @@ -780,6 +790,7 @@ class AsyncCallbackManagerForLLMRun(AsyncRunManager, LLMManagerMixin): chunk (Optional[Union[GenerationChunk, ChatGenerationChunk]], optional): The chunk. Defaults to None. **kwargs (Any): Additional keyword arguments. + """ if not self.handlers: return @@ -802,6 +813,7 @@ class AsyncCallbackManagerForLLMRun(AsyncRunManager, LLMManagerMixin): Args: response (LLMResult): The LLM result. **kwargs (Any): Additional keyword arguments. + """ if not self.handlers: return @@ -856,6 +868,7 @@ class CallbackManagerForChainRun(ParentRunManager, ChainManagerMixin): Args: outputs (Union[dict[str, Any], Any]): The outputs of the chain. **kwargs (Any): Additional keyword arguments. + """ if not self.handlers: return @@ -880,6 +893,7 @@ class CallbackManagerForChainRun(ParentRunManager, ChainManagerMixin): Args: error (Exception or KeyboardInterrupt): The error. **kwargs (Any): Additional keyword arguments. + """ if not self.handlers: return @@ -903,6 +917,7 @@ class CallbackManagerForChainRun(ParentRunManager, ChainManagerMixin): Returns: Any: The result of the callback. + """ if not self.handlers: return @@ -926,6 +941,7 @@ class CallbackManagerForChainRun(ParentRunManager, ChainManagerMixin): Returns: Any: The result of the callback. + """ if not self.handlers: return @@ -970,6 +986,7 @@ class AsyncCallbackManagerForChainRun(AsyncParentRunManager, ChainManagerMixin): Args: outputs (Union[dict[str, Any], Any]): The outputs of the chain. **kwargs (Any): Additional keyword arguments. + """ if not self.handlers: return @@ -995,6 +1012,7 @@ class AsyncCallbackManagerForChainRun(AsyncParentRunManager, ChainManagerMixin): Args: error (Exception or KeyboardInterrupt): The error. **kwargs (Any): Additional keyword arguments. + """ if not self.handlers: return @@ -1018,6 +1036,7 @@ class AsyncCallbackManagerForChainRun(AsyncParentRunManager, ChainManagerMixin): Returns: Any: The result of the callback. + """ if not self.handlers: return @@ -1041,6 +1060,7 @@ class AsyncCallbackManagerForChainRun(AsyncParentRunManager, ChainManagerMixin): Returns: Any: The result of the callback. + """ if not self.handlers: return @@ -1069,6 +1089,7 @@ class CallbackManagerForToolRun(ParentRunManager, ToolManagerMixin): Args: output (Any): The output of the tool. **kwargs (Any): The keyword arguments to pass to the event handler + """ if not self.handlers: return @@ -1093,6 +1114,7 @@ class CallbackManagerForToolRun(ParentRunManager, ToolManagerMixin): Args: error (Exception or KeyboardInterrupt): The error. **kwargs (Any): Additional keyword arguments. + """ if not self.handlers: return @@ -1134,6 +1156,7 @@ class AsyncCallbackManagerForToolRun(AsyncParentRunManager, ToolManagerMixin): Args: output (Any): The output of the tool. **kwargs (Any): Additional keyword arguments. + """ if not self.handlers: return @@ -1158,6 +1181,7 @@ class AsyncCallbackManagerForToolRun(AsyncParentRunManager, ToolManagerMixin): Args: error (Exception or KeyboardInterrupt): The error. **kwargs (Any): Additional keyword arguments. + """ if not self.handlers: return @@ -1186,6 +1210,7 @@ class CallbackManagerForRetrieverRun(ParentRunManager, RetrieverManagerMixin): Args: documents (Sequence[Document]): The retrieved documents. **kwargs (Any): Additional keyword arguments. + """ if not self.handlers: return @@ -1210,6 +1235,7 @@ class CallbackManagerForRetrieverRun(ParentRunManager, RetrieverManagerMixin): Args: error (BaseException): The error. **kwargs (Any): Additional keyword arguments. + """ if not self.handlers: return @@ -1236,6 +1262,7 @@ class AsyncCallbackManagerForRetrieverRun( Returns: CallbackManagerForRetrieverRun: The sync RunManager. + """ return CallbackManagerForRetrieverRun( run_id=self.run_id, @@ -1257,6 +1284,7 @@ class AsyncCallbackManagerForRetrieverRun( Args: documents (Sequence[Document]): The retrieved documents. **kwargs (Any): Additional keyword arguments. + """ if not self.handlers: return @@ -1282,6 +1310,7 @@ class AsyncCallbackManagerForRetrieverRun( Args: error (BaseException): The error. **kwargs (Any): Additional keyword arguments. + """ if not self.handlers: return @@ -1318,6 +1347,7 @@ class CallbackManager(BaseCallbackManager): Returns: list[CallbackManagerForLLMRun]: A callback manager for each prompt as an LLM run. + """ managers = [] for i, prompt in enumerate(prompts): @@ -1369,6 +1399,7 @@ class CallbackManager(BaseCallbackManager): Returns: list[CallbackManagerForLLMRun]: A callback manager for each list of messages as an LLM run. + """ managers = [] for message_list in messages: @@ -1422,6 +1453,7 @@ class CallbackManager(BaseCallbackManager): Returns: CallbackManagerForChainRun: The callback manager for the chain run. + """ if run_id is None: run_id = uuid.uuid4() @@ -1476,6 +1508,7 @@ class CallbackManager(BaseCallbackManager): Returns: CallbackManagerForToolRun: The callback manager for the tool run. + """ if run_id is None: run_id = uuid.uuid4() @@ -1522,6 +1555,7 @@ class CallbackManager(BaseCallbackManager): run_id (UUID, optional): The ID of the run. Defaults to None. parent_run_id (UUID, optional): The ID of the parent run. Defaults to None. **kwargs (Any): Additional keyword arguments. + """ if run_id is None: run_id = uuid.uuid4() @@ -1569,6 +1603,7 @@ class CallbackManager(BaseCallbackManager): run_id: The ID of the run. Defaults to None. .. versionadded:: 0.2.14 + """ if not self.handlers: return @@ -1623,6 +1658,7 @@ class CallbackManager(BaseCallbackManager): Returns: CallbackManager: The configured callback manager. + """ return _configure( cls, @@ -1657,6 +1693,7 @@ class CallbackManagerForChainGroup(CallbackManager): parent_run_id (Optional[UUID]): The ID of the parent run. Defaults to None. parent_run_manager (CallbackManagerForChainRun): The parent run manager. **kwargs (Any): Additional keyword arguments. + """ super().__init__( handlers, @@ -1745,6 +1782,7 @@ class CallbackManagerForChainGroup(CallbackManager): Args: outputs (Union[dict[str, Any], Any]): The outputs of the chain. **kwargs (Any): Additional keyword arguments. + """ self.ended = True return self.parent_run_manager.on_chain_end(outputs, **kwargs) @@ -1759,6 +1797,7 @@ class CallbackManagerForChainGroup(CallbackManager): Args: error (Exception or KeyboardInterrupt): The error. **kwargs (Any): Additional keyword arguments. + """ self.ended = True return self.parent_run_manager.on_chain_error(error, **kwargs) diff --git a/libs/core/langchain_core/chat_history.py b/libs/core/langchain_core/chat_history.py index 1ddee584f77..19138005162 100644 --- a/libs/core/langchain_core/chat_history.py +++ b/libs/core/langchain_core/chat_history.py @@ -117,9 +117,9 @@ class BaseChatMessageHistory(ABC): def add_user_message(self, message: Union[HumanMessage, str]) -> None: """Convenience method for adding a human message string to the store. - Please note that this is a convenience method. Code should favor the - bulk add_messages interface instead to save on round-trips to the underlying - persistence layer. + .. note:: + This is a convenience method. Code should favor the bulk ``add_messages`` + interface instead to save on round-trips to the persistence layer. This method may be deprecated in a future release. @@ -134,9 +134,9 @@ class BaseChatMessageHistory(ABC): def add_ai_message(self, message: Union[AIMessage, str]) -> None: """Convenience method for adding an AI message string to the store. - Please note that this is a convenience method. Code should favor the bulk - add_messages interface instead to save on round-trips to the underlying - persistence layer. + .. note:: + This is a convenience method. Code should favor the bulk ``add_messages`` + interface instead to save on round-trips to the persistence layer. This method may be deprecated in a future release. diff --git a/libs/core/langchain_core/documents/compressor.py b/libs/core/langchain_core/documents/compressor.py index 707d96cf088..c7a22ff6afd 100644 --- a/libs/core/langchain_core/documents/compressor.py +++ b/libs/core/langchain_core/documents/compressor.py @@ -19,17 +19,18 @@ if TYPE_CHECKING: class BaseDocumentCompressor(BaseModel, ABC): """Base class for document compressors. - This abstraction is primarily used for - post-processing of retrieved documents. + This abstraction is primarily used for post-processing of retrieved documents. Documents matching a given query are first retrieved. + Then the list of documents can be further processed. - For example, one could re-rank the retrieved documents - using an LLM. + For example, one could re-rank the retrieved documents using an LLM. + + .. note:: + Users should favor using a RunnableLambda instead of sub-classing from this + interface. - **Note** users should favor using a RunnableLambda - instead of sub-classing from this interface. """ @abstractmethod @@ -48,6 +49,7 @@ class BaseDocumentCompressor(BaseModel, ABC): Returns: The compressed documents. + """ async def acompress_documents( @@ -65,6 +67,7 @@ class BaseDocumentCompressor(BaseModel, ABC): Returns: The compressed documents. + """ return await run_in_executor( None, self.compress_documents, documents, query, callbacks diff --git a/libs/core/langchain_core/indexing/base.py b/libs/core/langchain_core/indexing/base.py index 4ed4772ee44..5110e8c3630 100644 --- a/libs/core/langchain_core/indexing/base.py +++ b/libs/core/langchain_core/indexing/base.py @@ -488,8 +488,8 @@ class DeleteResponse(TypedDict, total=False): failed: Sequence[str] """The IDs that failed to be deleted. - Please note that deleting an ID that - does not exist is **NOT** considered a failure. + .. warning:: + Deleting an ID that does not exist is **NOT** considered a failure. """ num_failed: int diff --git a/libs/core/langchain_core/language_models/base.py b/libs/core/langchain_core/language_models/base.py index a9e7e4e64cc..9f9856d7c6c 100644 --- a/libs/core/langchain_core/language_models/base.py +++ b/libs/core/langchain_core/language_models/base.py @@ -57,8 +57,8 @@ class LangSmithParams(TypedDict, total=False): def get_tokenizer() -> Any: """Get a GPT-2 tokenizer instance. - This function is cached to avoid re-loading the tokenizer - every time it is called. + This function is cached to avoid re-loading the tokenizer every time it is called. + """ try: from transformers import GPT2TokenizerFast # type: ignore[import-not-found] @@ -99,7 +99,8 @@ class BaseLanguageModel( ): """Abstract base class for interfacing with language models. - All language model wrappers inherited from BaseLanguageModel. + All language model wrappers inherited from ``BaseLanguageModel``. + """ cache: Union[BaseCache, bool, None] = Field(default=None, exclude=True) @@ -108,9 +109,10 @@ class BaseLanguageModel( * If true, will use the global cache. * If false, will not use a cache * If None, will use the global cache if it's set, otherwise no cache. - * If instance of BaseCache, will use the provided cache. + * If instance of ``BaseCache``, will use the provided cache. Caching is not currently supported for streaming methods of models. + """ verbose: bool = Field(default_factory=_get_verbosity, exclude=True, repr=False) """Whether to print out response text.""" @@ -140,6 +142,7 @@ class BaseLanguageModel( Returns: The verbosity setting to use. + """ if verbose is None: return _get_verbosity() @@ -195,7 +198,8 @@ class BaseLanguageModel( Returns: An LLMResult, which contains a list of candidate Generations for each input - prompt and additional model provider-specific output. + prompt and additional model provider-specific output. + """ @abstractmethod @@ -229,8 +233,9 @@ class BaseLanguageModel( to the model provider API call. Returns: - An LLMResult, which contains a list of candidate Generations for each input - prompt and additional model provider-specific output. + An ``LLMResult``, which contains a list of candidate Generations for each + input prompt and additional model provider-specific output. + """ def with_structured_output( @@ -248,8 +253,8 @@ class BaseLanguageModel( ) -> str: """Pass a single string input to the model and return a string. - Use this method when passing in raw text. If you want to pass in specific - types of chat messages, use predict_messages. + Use this method when passing in raw text. If you want to pass in specific types + of chat messages, use predict_messages. Args: text: String input to pass to the model. @@ -260,6 +265,7 @@ class BaseLanguageModel( Returns: Top model prediction as a string. + """ @deprecated("0.1.7", alternative="invoke", removal="1.0") @@ -274,7 +280,7 @@ class BaseLanguageModel( """Pass a message sequence to the model and return a message. Use this method when passing in chat messages. If you want to pass in raw text, - use predict. + use predict. Args: messages: A sequence of chat messages corresponding to a single model input. @@ -285,6 +291,7 @@ class BaseLanguageModel( Returns: Top model prediction as a message. + """ @deprecated("0.1.7", alternative="ainvoke", removal="1.0") @@ -295,7 +302,7 @@ class BaseLanguageModel( """Asynchronously pass a string to the model and return a string. Use this method when calling pure text generation models and only the top - candidate generation is needed. + candidate generation is needed. Args: text: String input to pass to the model. @@ -306,6 +313,7 @@ class BaseLanguageModel( Returns: Top model prediction as a string. + """ @deprecated("0.1.7", alternative="ainvoke", removal="1.0") @@ -319,8 +327,8 @@ class BaseLanguageModel( ) -> BaseMessage: """Asynchronously pass messages to the model and return a message. - Use this method when calling chat models and only the top - candidate generation is needed. + Use this method when calling chat models and only the top candidate generation + is needed. Args: messages: A sequence of chat messages corresponding to a single model input. @@ -331,6 +339,7 @@ class BaseLanguageModel( Returns: Top model prediction as a message. + """ @property @@ -346,7 +355,8 @@ class BaseLanguageModel( Returns: A list of ids corresponding to the tokens in the text, in order they occur - in the text. + in the text. + """ if self.custom_get_token_ids is not None: return self.custom_get_token_ids(text) @@ -362,6 +372,7 @@ class BaseLanguageModel( Returns: The integer number of tokens in the text. + """ return len(self.get_token_ids(text)) @@ -374,16 +385,18 @@ class BaseLanguageModel( Useful for checking if an input fits in a model's context window. - **Note**: the base implementation of get_num_tokens_from_messages ignores - tool schemas. + .. note:: + The base implementation of ``get_num_tokens_from_messages`` ignores tool + schemas. Args: messages: The message inputs to tokenize. - tools: If provided, sequence of dict, BaseModel, function, or BaseTools - to be converted to tool schemas. + tools: If provided, sequence of dict, ``BaseModel``, function, or + ``BaseTools`` to be converted to tool schemas. Returns: The sum of the number of tokens across the messages. + """ if tools is not None: warnings.warn( @@ -396,6 +409,7 @@ class BaseLanguageModel( def _all_required_field_names(cls) -> set: """DEPRECATED: Kept for backwards compatibility. - Use get_pydantic_field_names. + Use ``get_pydantic_field_names``. + """ return get_pydantic_field_names(cls) diff --git a/libs/core/langchain_core/language_models/chat_models.py b/libs/core/langchain_core/language_models/chat_models.py index 7873e7aaf5d..310f392fd25 100644 --- a/libs/core/langchain_core/language_models/chat_models.py +++ b/libs/core/langchain_core/language_models/chat_models.py @@ -97,17 +97,18 @@ def _generate_response_from_error(error: BaseException) -> list[ChatGeneration]: def _format_for_tracing(messages: list[BaseMessage]) -> list[BaseMessage]: - """Format messages for tracing in on_chat_model_start. + """Format messages for tracing in ``on_chat_model_start``. - Update image content blocks to OpenAI Chat Completions format (backward compatibility). - - Add "type" key to content blocks that have a single key. + - Add ``type`` key to content blocks that have a single key. Args: messages: List of messages to format. Returns: List of messages formatted for tracing. + """ messages_to_trace = [] for message in messages: @@ -153,10 +154,11 @@ def generate_from_stream(stream: Iterator[ChatGenerationChunk]) -> ChatResult: """Generate from a stream. Args: - stream: Iterator of ChatGenerationChunk. + stream: Iterator of ``ChatGenerationChunk``. Returns: ChatResult: Chat result. + """ generation = next(stream, None) if generation: @@ -180,10 +182,11 @@ async def agenerate_from_stream( """Async generate from a stream. Args: - stream: Iterator of ChatGenerationChunk. + stream: Iterator of ``ChatGenerationChunk``. Returns: ChatResult: Chat result. + """ chunks = [chunk async for chunk in stream] return await run_in_executor(None, generate_from_stream, iter(chunks)) @@ -311,15 +314,16 @@ class BaseChatModel(BaseLanguageModel[BaseMessage], ABC): provided. This offers the best of both worlds. - If False (default), will always use streaming case if available. - The main reason for this flag is that code might be written using ``.stream()`` and + The main reason for this flag is that code might be written using ``stream()`` and a user may want to swap out a given model for another model whose the implementation does not properly support streaming. + """ @model_validator(mode="before") @classmethod def raise_deprecation(cls, values: dict) -> Any: - """Raise deprecation warning if callback_manager is used. + """Raise deprecation warning if ``callback_manager`` is used. Args: values (Dict): Values to validate. @@ -328,7 +332,8 @@ class BaseChatModel(BaseLanguageModel[BaseMessage], ABC): Dict: Validated values. Raises: - DeprecationWarning: If callback_manager is used. + DeprecationWarning: If ``callback_manager`` is used. + """ if values.get("callback_manager") is not None: warnings.warn( @@ -653,6 +658,7 @@ class BaseChatModel(BaseLanguageModel[BaseMessage], ABC): Returns: List of ChatGeneration objects. + """ converted_generations = [] for gen in cache_val: @@ -778,7 +784,8 @@ class BaseChatModel(BaseLanguageModel[BaseMessage], ABC): Returns: An LLMResult, which contains a list of candidate Generations for each input - prompt and additional model provider-specific output. + prompt and additional model provider-specific output. + """ ls_structured_output_format = kwargs.pop( "ls_structured_output_format", None @@ -892,7 +899,8 @@ class BaseChatModel(BaseLanguageModel[BaseMessage], ABC): Returns: An LLMResult, which contains a list of candidate Generations for each input - prompt and additional model provider-specific output. + prompt and additional model provider-specific output. + """ ls_structured_output_format = kwargs.pop( "ls_structured_output_format", None @@ -1248,6 +1256,7 @@ class BaseChatModel(BaseLanguageModel[BaseMessage], ABC): Returns: The model output message. + """ generation = self.generate( [messages], stop=stop, callbacks=callbacks, **kwargs @@ -1288,6 +1297,7 @@ class BaseChatModel(BaseLanguageModel[BaseMessage], ABC): Returns: The model output string. + """ return self.predict(message, stop=stop, **kwargs) @@ -1307,6 +1317,7 @@ class BaseChatModel(BaseLanguageModel[BaseMessage], ABC): Returns: The predicted output string. + """ stop_ = None if stop is None else list(stop) result = self([HumanMessage(content=text)], stop=stop_, **kwargs) @@ -1382,6 +1393,7 @@ class BaseChatModel(BaseLanguageModel[BaseMessage], ABC): Returns: A Runnable that returns a message. + """ raise NotImplementedError @@ -1544,8 +1556,10 @@ class BaseChatModel(BaseLanguageModel[BaseMessage], ABC): class SimpleChatModel(BaseChatModel): """Simplified implementation for a chat model to inherit from. - **Note** This implementation is primarily here for backwards compatibility. - For new implementations, please use `BaseChatModel` directly. + .. note:: + This implementation is primarily here for backwards compatibility. For new + implementations, please use ``BaseChatModel`` directly. + """ def _generate( diff --git a/libs/core/langchain_core/language_models/fake_chat_models.py b/libs/core/langchain_core/language_models/fake_chat_models.py index 184a4fcb154..c6e78b5389a 100644 --- a/libs/core/langchain_core/language_models/fake_chat_models.py +++ b/libs/core/langchain_core/language_models/fake_chat_models.py @@ -223,11 +223,12 @@ class GenericFakeChatModel(BaseChatModel): This can be expanded to accept other types like Callables / dicts / strings to make the interface more generic if needed. - Note: if you want to pass a list, you can use `iter` to convert it to an iterator. + .. note:: + if you want to pass a list, you can use ``iter`` to convert it to an iterator. - Please note that streaming is not implemented yet. We should try to implement it - in the future by delegating to invoke and then breaking the resulting output - into message chunks. + .. warning:: + Streaming is not implemented yet. We should try to implement it in the future by + delegating to invoke and then breaking the resulting output into message chunks. """ @override diff --git a/libs/core/langchain_core/load/dump.py b/libs/core/langchain_core/load/dump.py index b1993c38244..f8ab13a7f97 100644 --- a/libs/core/langchain_core/load/dump.py +++ b/libs/core/langchain_core/load/dump.py @@ -73,10 +73,9 @@ def dumps(obj: Any, *, pretty: bool = False, **kwargs: Any) -> str: def dumpd(obj: Any) -> Any: """Return a dict representation of an object. - Note: - Unfortunately this function is not as efficient as it could be - because it first dumps the object to a json string and then loads it - back into a dictionary. + .. note:: + Unfortunately this function is not as efficient as it could be because it first + dumps the object to a json string and then loads it back into a dictionary. Args: obj: The object to dump. diff --git a/libs/core/langchain_core/messages/utils.py b/libs/core/langchain_core/messages/utils.py index 11c044eb438..37f16c632bd 100644 --- a/libs/core/langchain_core/messages/utils.py +++ b/libs/core/langchain_core/messages/utils.py @@ -656,22 +656,23 @@ def trim_messages( properties: 1. The resulting chat history should be valid. Most chat models expect that chat - history starts with either (1) a `HumanMessage` or (2) a `SystemMessage` followed - by a `HumanMessage`. To achieve this, set `start_on="human"`. - In addition, generally a `ToolMessage` can only appear after an `AIMessage` + history starts with either (1) a ``HumanMessage`` or (2) a ``SystemMessage`` followed + by a ``HumanMessage``. To achieve this, set ``start_on="human"``. + In addition, generally a ``ToolMessage`` can only appear after an ``AIMessage`` that involved a tool call. Please see the following link for more information about messages: https://python.langchain.com/docs/concepts/#messages 2. It includes recent messages and drops old messages in the chat history. - To achieve this set the `strategy="last"`. - 3. Usually, the new chat history should include the `SystemMessage` if it - was present in the original chat history since the `SystemMessage` includes - special instructions to the chat model. The `SystemMessage` is almost always + To achieve this set the ``strategy="last"``. + 3. Usually, the new chat history should include the ``SystemMessage`` if it + was present in the original chat history since the ``SystemMessage`` includes + special instructions to the chat model. The ``SystemMessage`` is almost always the first message in the history if present. To achieve this set the - `include_system=True`. + ``include_system=True``. - **Note** The examples below show how to configure `trim_messages` to achieve - a behavior consistent with the above properties. + .. note:: + The examples below show how to configure ``trim_messages`` to achieve a behavior + consistent with the above properties. Args: messages: Sequence of Message-like objects to trim. @@ -1580,26 +1581,26 @@ def count_tokens_approximately( chars_per_token: Number of characters per token to use for the approximation. Default is 4 (one token corresponds to ~4 chars for common English text). You can also specify float values for more fine-grained control. - See more here: https://platform.openai.com/tokenizer + `See more here. `__ extra_tokens_per_message: Number of extra tokens to add per message. Default is 3 (special tokens, including beginning/end of message). You can also specify float values for more fine-grained control. - See more here: - https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb + `See more here. `__ count_name: Whether to include message names in the count. Enabled by default. Returns: Approximate number of tokens in the messages. - Note: - This is a simple approximation that may not match the exact token count - used by specific models. For accurate counts, use model-specific tokenizers. + .. note:: + This is a simple approximation that may not match the exact token count used by + specific models. For accurate counts, use model-specific tokenizers. Warning: This function does not currently support counting image tokens. .. versionadded:: 0.3.46 + """ token_count = 0.0 for message in convert_to_messages(messages): diff --git a/libs/core/langchain_core/runnables/base.py b/libs/core/langchain_core/runnables/base.py index fd66cf6dad5..6e0be997af6 100644 --- a/libs/core/langchain_core/runnables/base.py +++ b/libs/core/langchain_core/runnables/base.py @@ -2698,9 +2698,10 @@ class RunnableSequence(RunnableSerializable[Input, Output]): streaming will only begin after this component is run. If there are multiple blocking components, streaming begins after the last one. - Please note: RunnableLambdas do not support `transform` by default! So if - you need to use a RunnableLambdas be careful about where you place them in a - RunnableSequence (if you need to use the .stream()/.astream() methods). + .. note:: + ``RunnableLambdas`` do not support ``transform`` by default! So if you need to + use a ``RunnableLambdas`` be careful about where you place them in a + ``RunnableSequence`` (if you need to use the ``stream``/``astream`` methods). If you need arbitrary logic and need streaming, you can subclass Runnable, and implement `transform` for whatever logic you need. diff --git a/libs/core/tests/unit_tests/test_imports.py b/libs/core/tests/unit_tests/test_imports.py index 30e320ee68e..d5a9ffbd18e 100644 --- a/libs/core/tests/unit_tests/test_imports.py +++ b/libs/core/tests/unit_tests/test_imports.py @@ -30,8 +30,9 @@ def try_to_import(module_name: str) -> tuple[int, str]: def test_importable_all_via_subprocess() -> None: """Test import in isolation. - Note: ImportErrors due to circular imports can be raised - for one sequence of imports but not another. + .. note:: + ImportErrors due to circular imports can be raised for one sequence of imports + but not another. """ module_names = [] for path in Path("../core/langchain_core/").glob("*"): diff --git a/libs/core/tests/unit_tests/test_tools.py b/libs/core/tests/unit_tests/test_tools.py index 57b4573d70d..72c6a5a387c 100644 --- a/libs/core/tests/unit_tests/test_tools.py +++ b/libs/core/tests/unit_tests/test_tools.py @@ -1898,6 +1898,7 @@ def test_args_schema_explicitly_typed() -> None: Please note that this will test using pydantic 2 even though BaseTool is a pydantic 1 model! + """ # Check with whatever pydantic model is passed in and not via v1 namespace from pydantic import BaseModel diff --git a/libs/langchain/README.md b/libs/langchain/README.md index 541befa107f..ec2870ae6cf 100644 --- a/libs/langchain/README.md +++ b/libs/langchain/README.md @@ -14,11 +14,10 @@ [![Dependency Status](https://img.shields.io/librariesio/github/langchain-ai/langchain)](https://libraries.io/github/langchain-ai/langchain) [![Open Issues](https://img.shields.io/github/issues-raw/langchain-ai/langchain)](https://github.com/langchain-ai/langchain/issues) - Looking for the JS/TS version? Check out [LangChain.js](https://github.com/langchain-ai/langchainjs). -To help you ship LangChain apps to production faster, check out [LangSmith](https://smith.langchain.com). -[LangSmith](https://smith.langchain.com) is a unified developer platform for building, testing, and monitoring LLM applications. +To help you ship LangChain apps to production faster, check out [LangSmith](https://smith.langchain.com). +[LangSmith](https://smith.langchain.com) is a unified developer platform for building, testing, and monitoring LLM applications. Fill out [this form](https://www.langchain.com/contact-sales) to speak with our sales team. ## Quick Install diff --git a/libs/langchain/langchain/agents/agent_toolkits/vectorstore/base.py b/libs/langchain/langchain/agents/agent_toolkits/vectorstore/base.py index 75f642bc082..67834a4c1ed 100644 --- a/libs/langchain/langchain/agents/agent_toolkits/vectorstore/base.py +++ b/libs/langchain/langchain/agents/agent_toolkits/vectorstore/base.py @@ -41,8 +41,9 @@ def create_vectorstore_agent( ) -> AgentExecutor: """Construct a VectorStore agent from an LLM and tools. - Note: this class is deprecated. See below for a replacement that uses tool - calling methods and LangGraph. Install LangGraph with: + .. note:: + This class is deprecated. See below for a replacement that uses tool + calling methods and LangGraph. Install LangGraph with: .. code-block:: bash @@ -135,8 +136,9 @@ def create_vectorstore_router_agent( ) -> AgentExecutor: """Construct a VectorStore router agent from an LLM and tools. - Note: this class is deprecated. See below for a replacement that uses tool - calling methods and LangGraph. Install LangGraph with: + .. note:: + This class is deprecated. See below for a replacement that uses tool calling + methods and LangGraph. Install LangGraph with: .. code-block:: bash diff --git a/libs/langchain/langchain/agents/output_parsers/xml.py b/libs/langchain/langchain/agents/output_parsers/xml.py index 3db5117e7c2..d7238e9d751 100644 --- a/libs/langchain/langchain/agents/output_parsers/xml.py +++ b/libs/langchain/langchain/agents/output_parsers/xml.py @@ -46,11 +46,11 @@ class XMLAgentOutputParser(AgentOutputParser): Final answer (returns AgentFinish): The answer is 4 - Note: - Minimal escaping allows tool names containing XML tags to be safely - represented. For example, a tool named "searchnested" would be - escaped as "search[[tool]]nested[[/tool]]" in the XML and automatically - unescaped during parsing. + .. note:: + Minimal escaping allows tool names containing XML tags to be safely represented. + For example, a tool named ``searchnested`` would be escaped as + ``search[[tool]]nested[[/tool]]`` in the XML and automatically unescaped during + parsing. Raises: ValueError: If the input doesn't match either expected XML format or diff --git a/libs/langchain/langchain/chains/api/base.py b/libs/langchain/langchain/chains/api/base.py index b70beeabfc9..b1a8fa949a1 100644 --- a/libs/langchain/langchain/chains/api/base.py +++ b/libs/langchain/langchain/chains/api/base.py @@ -82,8 +82,9 @@ try: See https://python.langchain.com/docs/security for more information. - Note: this class is deprecated. See below for a replacement implementation - using LangGraph. The benefits of this implementation are: + .. note:: + This class is deprecated. See below for a replacement implementation using + LangGraph. The benefits of this implementation are: - Uses LLM tool calling features to encourage properly-formatted API requests; - Support for both token-by-token and step-by-step streaming; diff --git a/libs/langchain/langchain/chains/constitutional_ai/base.py b/libs/langchain/langchain/chains/constitutional_ai/base.py index 2113c70738f..e302087b610 100644 --- a/libs/langchain/langchain/chains/constitutional_ai/base.py +++ b/libs/langchain/langchain/chains/constitutional_ai/base.py @@ -26,8 +26,9 @@ from langchain.chains.llm import LLMChain class ConstitutionalChain(Chain): """Chain for applying constitutional principles. - Note: this class is deprecated. See below for a replacement implementation - using LangGraph. The benefits of this implementation are: + .. note:: + This class is deprecated. See below for a replacement implementation using + LangGraph. The benefits of this implementation are: - Uses LLM tool calling features instead of parsing string responses; - Support for both token-by-token and step-by-step streaming; diff --git a/libs/langchain/langchain/chains/llm_math/base.py b/libs/langchain/langchain/chains/llm_math/base.py index 084c7719dda..b5e0e19faa6 100644 --- a/libs/langchain/langchain/chains/llm_math/base.py +++ b/libs/langchain/langchain/chains/llm_math/base.py @@ -33,8 +33,9 @@ from langchain.chains.llm_math.prompt import PROMPT class LLMMathChain(Chain): """Chain that interprets a prompt and executes python code to do math. - Note: this class is deprecated. See below for a replacement implementation - using LangGraph. The benefits of this implementation are: + .. note:: + This class is deprecated. See below for a replacement implementation using + LangGraph. The benefits of this implementation are: - Uses LLM tool calling features; - Support for both token-by-token and step-by-step streaming; diff --git a/libs/langchain/tests/unit_tests/llms/fake_chat_model.py b/libs/langchain/tests/unit_tests/llms/fake_chat_model.py index f11141a01d1..63455c3a482 100644 --- a/libs/langchain/tests/unit_tests/llms/fake_chat_model.py +++ b/libs/langchain/tests/unit_tests/llms/fake_chat_model.py @@ -58,7 +58,7 @@ class GenericFakeChatModel(BaseChatModel): """A generic fake chat model that can be used to test the chat model interface. * Chat model should be usable in both sync and async tests - * Invokes on_llm_new_token to allow for testing of callback related code for new + * Invokes ``on_llm_new_token`` to allow for testing of callback related code for new tokens. * Includes logic to break messages into message chunk to facilitate testing of streaming. @@ -67,14 +67,16 @@ class GenericFakeChatModel(BaseChatModel): messages: Iterator[AIMessage] """Get an iterator over messages. - This can be expanded to accept other types like Callables / dicts / strings + This can be expanded to accept other types like ``Callables`` / dicts / strings to make the interface more generic if needed. - Note: if you want to pass a list, you can use `iter` to convert it to an iterator. + .. note:: + If you want to pass a list, you can use ``iter`` to convert it to an iterator. + + .. warning:: + Streaming is not implemented yet. We should try to implement it in the future by + delegating to invoke and then breaking the resulting output into message chunks. - Please note that streaming is not implemented yet. We should try to implement it - in the future by delegating to invoke and then breaking the resulting output - into message chunks. """ @override diff --git a/libs/langchain_v1/README.md b/libs/langchain_v1/README.md index 541befa107f..ec2870ae6cf 100644 --- a/libs/langchain_v1/README.md +++ b/libs/langchain_v1/README.md @@ -14,11 +14,10 @@ [![Dependency Status](https://img.shields.io/librariesio/github/langchain-ai/langchain)](https://libraries.io/github/langchain-ai/langchain) [![Open Issues](https://img.shields.io/github/issues-raw/langchain-ai/langchain)](https://github.com/langchain-ai/langchain/issues) - Looking for the JS/TS version? Check out [LangChain.js](https://github.com/langchain-ai/langchainjs). -To help you ship LangChain apps to production faster, check out [LangSmith](https://smith.langchain.com). -[LangSmith](https://smith.langchain.com) is a unified developer platform for building, testing, and monitoring LLM applications. +To help you ship LangChain apps to production faster, check out [LangSmith](https://smith.langchain.com). +[LangSmith](https://smith.langchain.com) is a unified developer platform for building, testing, and monitoring LLM applications. Fill out [this form](https://www.langchain.com/contact-sales) to speak with our sales team. ## Quick Install diff --git a/libs/langchain_v1/langchain/_internal/_documents.py b/libs/langchain_v1/langchain/_internal/_documents.py index 2ec72f77232..9db3f9792b7 100644 --- a/libs/langchain_v1/langchain/_internal/_documents.py +++ b/libs/langchain_v1/langchain/_internal/_documents.py @@ -22,9 +22,10 @@ def format_document_xml(doc: Document) -> str: ... - Note: - Does not generate valid XML or escape special characters. - Intended for semi-structured LLM input only. + .. note:: + Does not generate valid XML or escape special characters. Intended for + semi-structured LLM input only. + """ id_str = f"{doc.id}" if doc.id is not None else "" metadata_str = "" diff --git a/libs/langchain_v1/langchain/_internal/_prompts.py b/libs/langchain_v1/langchain/_internal/_prompts.py index f2de112ea25..5d67101a84b 100644 --- a/libs/langchain_v1/langchain/_internal/_prompts.py +++ b/libs/langchain_v1/langchain/_internal/_prompts.py @@ -6,6 +6,7 @@ and asynchronous prompt resolution with automatic detection of callable types. The module is designed to handle common prompt patterns across LangChain components, particularly for summarization chains and other document processing workflows. + """ from __future__ import annotations @@ -65,10 +66,10 @@ def resolve_prompt( messages = resolve_prompt(None, state, runtime, "content", "Default") ``` - Note: - Callable prompts have full control over message structure and content - parameter is ignored. String/None prompts create standard system + user - structure. + .. note:: + Callable prompts have full control over message structure and content parameter + is ignored. String/None prompts create standard system + user structure. + """ if callable(prompt): return prompt(state, runtime) @@ -141,10 +142,10 @@ async def aresolve_prompt( messages = await aresolve_prompt("Custom", state, runtime, "content", "default") ``` - Note: - Callable prompts have full control over message structure and content - parameter is ignored. Automatically detects and handles async - callables. + .. note:: + Callable prompts have full control over message structure and content parameter + is ignored. Automatically detects and handles async callables. + """ if callable(prompt): result = prompt(state, runtime) diff --git a/libs/langchain_v1/langchain/_internal/_typing.py b/libs/langchain_v1/langchain/_internal/_typing.py index 9ca0990eb38..b9a267e2256 100644 --- a/libs/langchain_v1/langchain/_internal/_typing.py +++ b/libs/langchain_v1/langchain/_internal/_typing.py @@ -13,9 +13,10 @@ if TYPE_CHECKING: class TypedDictLikeV1(Protocol): - """Protocol to represent types that behave like TypedDicts. + """Protocol to represent types that behave like ``TypedDict``s. + + Version 1: using ``ClassVar`` for keys. - Version 1: using `ClassVar` for keys. """ __required_keys__: ClassVar[frozenset[str]] @@ -23,9 +24,10 @@ class TypedDictLikeV1(Protocol): class TypedDictLikeV2(Protocol): - """Protocol to represent types that behave like TypedDicts. + """Protocol to represent types that behave like ``TypedDict``s. + + Version 2: not using ``ClassVar`` for keys. - Version 2: not using `ClassVar` for keys. """ __required_keys__: frozenset[str] @@ -35,8 +37,9 @@ class TypedDictLikeV2(Protocol): class DataclassLike(Protocol): """Protocol to represent types that behave like dataclasses. - Inspired by the private _DataclassT from dataclasses that uses a similar + Inspired by the private ``_DataclassT`` from dataclasses that uses a similar protocol as a bound. + """ __dataclass_fields__: ClassVar[dict[str, Field[Any]]] @@ -45,9 +48,12 @@ class DataclassLike(Protocol): StateLike: TypeAlias = Union[TypedDictLikeV1, TypedDictLikeV2, DataclassLike, BaseModel] """Type alias for state-like types. -It can either be a `TypedDict`, `dataclass`, or Pydantic `BaseModel`. -Note: we cannot use either `TypedDict` or `dataclass` directly due to limitations in -type checking. +It can either be a ``TypedDict``, ``dataclass``, or Pydantic ``BaseModel``. + +.. note:: + We cannot use either ``TypedDict`` or ``dataclass`` directly due to limitations in + type checking. + """ StateT = TypeVar("StateT", bound=StateLike) diff --git a/libs/langchain_v1/langchain/chains/documents/map_reduce.py b/libs/langchain_v1/langchain/chains/documents/map_reduce.py index eb035c7d44c..648bedc1ade 100644 --- a/libs/langchain_v1/langchain/chains/documents/map_reduce.py +++ b/libs/langchain_v1/langchain/chains/documents/map_reduce.py @@ -567,7 +567,7 @@ def create_map_reduce_chain( A LangGraph that can be invoked with documents to get map-reduce extraction results. - Note: + .. note:: This implementation is well-suited for large document collections as it processes documents in parallel during the map phase. The Send API enables efficient parallelization while maintaining clean state management. diff --git a/libs/langchain_v1/langchain/chains/documents/stuff.py b/libs/langchain_v1/langchain/chains/documents/stuff.py index c30b6f711a8..194e85f02bc 100644 --- a/libs/langchain_v1/langchain/chains/documents/stuff.py +++ b/libs/langchain_v1/langchain/chains/documents/stuff.py @@ -454,7 +454,7 @@ def create_stuff_documents_chain( Returns: A LangGraph that can be invoked with documents to extract information. - Note: + .. note:: This is a "stuff" documents chain that puts all documents into the context window and processes them together. It supports refining existing results. Default prompts are optimized for summarization but can be customized for diff --git a/libs/partners/ai21/README.md b/libs/partners/ai21/README.md index a4a3cc65aec..64aba9e3224 100644 --- a/libs/partners/ai21/README.md +++ b/libs/partners/ai21/README.md @@ -1,3 +1,3 @@ This package has moved! -https://github.com/langchain-ai/langchain-ai21/tree/main/libs/ai21 \ No newline at end of file +https://github.com/langchain-ai/langchain-ai21/tree/main/libs/ai21 diff --git a/libs/partners/astradb/README.md b/libs/partners/astradb/README.md index 62566a56776..05b44631d73 100644 --- a/libs/partners/astradb/README.md +++ b/libs/partners/astradb/README.md @@ -1,3 +1,3 @@ This package has moved! -https://github.com/langchain-ai/langchain-datastax/tree/main/libs/astradb \ No newline at end of file +https://github.com/langchain-ai/langchain-datastax/tree/main/libs/astradb diff --git a/libs/partners/ibm/README.md b/libs/partners/ibm/README.md index 91cdbedf6c1..e78740013d3 100644 --- a/libs/partners/ibm/README.md +++ b/libs/partners/ibm/README.md @@ -1,3 +1,3 @@ This package has moved! -https://github.com/langchain-ai/langchain-ibm/tree/main/libs/ibm \ No newline at end of file +https://github.com/langchain-ai/langchain-ibm/tree/main/libs/ibm diff --git a/libs/partners/openai/langchain_openai/embeddings/azure.py b/libs/partners/openai/langchain_openai/embeddings/azure.py index 7fd567e03d5..be8ddcc8b9e 100644 --- a/libs/partners/openai/langchain_openai/embeddings/azure.py +++ b/libs/partners/openai/langchain_openai/embeddings/azure.py @@ -115,7 +115,10 @@ class AzureOpenAIEmbeddings(OpenAIEmbeddings): # type: ignore[override] """A model deployment. If given sets the base client URL to include `/deployments/{azure_deployment}`. - Note: this means you won't be able to use non-deployment endpoints. + + .. note:: + This means you won't be able to use non-deployment endpoints. + """ # Check OPENAI_KEY for backwards compatibility. # TODO: Remove OPENAI_API_KEY support to avoid possible conflict when using @@ -132,7 +135,7 @@ class AzureOpenAIEmbeddings(OpenAIEmbeddings): # type: ignore[override] alias="api_version", ) """Automatically inferred from env var ``OPENAI_API_VERSION`` if not provided. - + Set to ``'2023-05-15'`` by default if env variable ``OPENAI_API_VERSION`` is not set. """ diff --git a/libs/partners/openai/langchain_openai/llms/azure.py b/libs/partners/openai/langchain_openai/llms/azure.py index 02e3ab9e1e1..92c2a091e7b 100644 --- a/libs/partners/openai/langchain_openai/llms/azure.py +++ b/libs/partners/openai/langchain_openai/llms/azure.py @@ -43,10 +43,13 @@ class AzureOpenAI(BaseOpenAI): Example: ``'https://example-resource.azure.openai.com/'`` """ deployment_name: Union[str, None] = Field(default=None, alias="azure_deployment") - """A model deployment. + """A model deployment. If given sets the base client URL to include `/deployments/{azure_deployment}`. - Note: this means you won't be able to use non-deployment endpoints. + + .. note:: + This means you won't be able to use non-deployment endpoints. + """ openai_api_version: Optional[str] = Field( alias="api_version", @@ -87,7 +90,7 @@ class AzureOpenAI(BaseOpenAI): ) """Legacy, for ``openai<1.0.0`` support.""" validate_base_url: bool = True - """For backwards compatibility. If legacy val openai_api_base is passed in, try to + """For backwards compatibility. If legacy val openai_api_base is passed in, try to infer if it is a base_url or azure_endpoint and update accordingly. """ diff --git a/libs/partners/openai/pyproject.toml b/libs/partners/openai/pyproject.toml index 5bffdabcf44..4f9d3a54d28 100644 --- a/libs/partners/openai/pyproject.toml +++ b/libs/partners/openai/pyproject.toml @@ -90,4 +90,4 @@ filterwarnings = [ "tests/**/*.py" = [ "S101", # Tests need assertions "S311", # Standard pseudo-random generators are not suitable for cryptographic purposes -] \ No newline at end of file +] diff --git a/libs/partners/openai/tests/integration_tests/chat_models/test_base_standard.py b/libs/partners/openai/tests/integration_tests/chat_models/test_base_standard.py index abc0a666a84..b51efff1ceb 100644 --- a/libs/partners/openai/tests/integration_tests/chat_models/test_base_standard.py +++ b/libs/partners/openai/tests/integration_tests/chat_models/test_base_standard.py @@ -66,7 +66,7 @@ class TestOpenAIStandard(ChatModelIntegrationTests): readme = f.read() input_ = f"""What's langchain? Here's the langchain README: - + {readme} """ llm = ChatOpenAI(model="gpt-4o-mini", stream_usage=True) diff --git a/libs/partners/openai/tests/integration_tests/chat_models/test_responses_standard.py b/libs/partners/openai/tests/integration_tests/chat_models/test_responses_standard.py index 22e18155bd7..d06ed1e40f5 100644 --- a/libs/partners/openai/tests/integration_tests/chat_models/test_responses_standard.py +++ b/libs/partners/openai/tests/integration_tests/chat_models/test_responses_standard.py @@ -31,7 +31,7 @@ class TestOpenAIResponses(TestOpenAIStandard): readme = f.read() input_ = f"""What's langchain? Here's the langchain README: - + {readme} """ llm = ChatOpenAI(model="gpt-4.1-mini", output_version="responses/v1") diff --git a/libs/partners/openai/uv.lock b/libs/partners/openai/uv.lock index 58a1807abe3..79442d17b04 100644 --- a/libs/partners/openai/uv.lock +++ b/libs/partners/openai/uv.lock @@ -588,7 +588,7 @@ typing = [ [package.metadata] requires-dist = [ { name = "langchain-core", editable = "../../core" }, - { name = "openai", specifier = ">=1.86.0,<2.0.0" }, + { name = "openai", specifier = ">=1.99.3,<2.0.0" }, { name = "tiktoken", specifier = ">=0.7,<1" }, ] @@ -995,7 +995,7 @@ wheels = [ [[package]] name = "openai" -version = "1.99.2" +version = "1.99.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, @@ -1007,9 +1007,9 @@ dependencies = [ { name = "tqdm" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/de/2c/8cd1684364551237a5e6db24ce25c25ff54efcf1805b39110ec713dc2972/openai-1.99.2.tar.gz", hash = "sha256:118075b48109aa237636607b1346cf03b37cb9d74b0414cb11095850a0a22c96", size = 504752, upload-time = "2025-08-07T17:16:14.668Z" } +sdist = { url = "https://files.pythonhosted.org/packages/72/d3/c372420c8ca1c60e785fd8c19e536cea8f16b0cfdcdad6458e1d8884f2ea/openai-1.99.3.tar.gz", hash = "sha256:1a0e2910e4545d828c14218f2ac3276827c94a043f5353e43b9413b38b497897", size = 504932, upload-time = "2025-08-07T20:35:15.893Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b7/06/f3338c1b8685dc1634fa5174dc5ba2d3eecc7887c9fc539bb5da6f75ebb3/openai-1.99.2-py3-none-any.whl", hash = "sha256:110d85b8ed400e1d7b02f8db8e245bd757bcde347cb6923155f42cd66a10aa0b", size = 785594, upload-time = "2025-08-07T17:16:13.083Z" }, + { url = "https://files.pythonhosted.org/packages/92/bc/e52f49940b4e320629da7db09c90a2407a48c612cff397b4b41b7e58cdf9/openai-1.99.3-py3-none-any.whl", hash = "sha256:c786a03f6cddadb5ee42c6d749aa4f6134fe14fdd7d69a667e5e7ce7fd29a719", size = 785776, upload-time = "2025-08-07T20:35:13.653Z" }, ] [[package]] diff --git a/libs/partners/prompty/README.md b/libs/partners/prompty/README.md index 7f4493be65f..3885e79f625 100644 --- a/libs/partners/prompty/README.md +++ b/libs/partners/prompty/README.md @@ -41,7 +41,7 @@ sample: --- system: You are an AI assistant who helps people find information. -As the assistant, you answer questions briefly, succinctly, +As the assistant, you answer questions briefly, succinctly, and in a personable manner using markdown and even add some personal flair with appropriate emojis. {% for item in chat_history %} diff --git a/libs/partners/together/README.md b/libs/partners/together/README.md index 92284c00420..967f7c299d6 100644 --- a/libs/partners/together/README.md +++ b/libs/partners/together/README.md @@ -1,3 +1,3 @@ This package has moved! -https://github.com/langchain-ai/langchain-together/tree/main/libs/together \ No newline at end of file +https://github.com/langchain-ai/langchain-together/tree/main/libs/together diff --git a/libs/text-splitters/langchain_text_splitters/__init__.py b/libs/text-splitters/langchain_text_splitters/__init__.py index 030d948d898..d45ce9d3414 100644 --- a/libs/text-splitters/langchain_text_splitters/__init__.py +++ b/libs/text-splitters/langchain_text_splitters/__init__.py @@ -7,7 +7,9 @@ BaseDocumentTransformer --> TextSplitter --> TextSplitter # Example: CharacterTextSplitter RecursiveCharacterTextSplitter --> TextSplitter -Note: **MarkdownHeaderTextSplitter** and **HTMLHeaderTextSplitter do not derive from TextSplitter. + +.. note:: + **MarkdownHeaderTextSplitter** and **HTMLHeaderTextSplitter do not derive from TextSplitter. **Main helpers:** diff --git a/libs/text-splitters/tests/unit_tests/test_text_splitters.py b/libs/text-splitters/tests/unit_tests/test_text_splitters.py index 0d72e806309..2ed35e3c13e 100644 --- a/libs/text-splitters/tests/unit_tests/test_text_splitters.py +++ b/libs/text-splitters/tests/unit_tests/test_text_splitters.py @@ -3053,18 +3053,18 @@ End Function Public Sub Main() Dim i As Integer Dim limit As Integer - + i = 0 limit = 50 - + While i < limit i = SumTwoIntegers(i, 1) - + If i = limit \\ 2 Then MsgBox "Halfway there! i = " & i End If Wend - + MsgBox "Done! Final value of i: " & i End Sub """