diff --git a/libs/cli/langchain_cli/cli.py b/libs/cli/langchain_cli/cli.py index 3317ff01606..8d2103c4dce 100644 --- a/libs/cli/langchain_cli/cli.py +++ b/libs/cli/langchain_cli/cli.py @@ -5,8 +5,9 @@ from typing_extensions import Annotated from langchain_cli.namespaces import app as app_namespace from langchain_cli.namespaces import template as template_namespace +from langchain_cli.utils.packages import get_langserve_export, get_package_root -__version__ = "0.0.15" +__version__ = "0.0.16" app = typer.Typer(no_args_is_help=True, add_completion=False) app.add_typer( @@ -49,11 +50,17 @@ def serve( Start the LangServe app, whether it's a template or an app. """ - # try starting template package, if error, try langserve + # see if is a template try: - template_namespace.serve(port=port, host=host) + project_dir = get_package_root() + pyproject = project_dir / "pyproject.toml" + get_langserve_export(pyproject) except KeyError: + # not a template app_namespace.serve(port=port, host=host) + else: + # is a template + template_namespace.serve(port=port, host=host) if __name__ == "__main__": diff --git a/libs/cli/langchain_cli/namespaces/app.py b/libs/cli/langchain_cli/namespaces/app.py index 55fc4175008..2eeddcdb64d 100644 --- a/libs/cli/langchain_cli/namespaces/app.py +++ b/libs/cli/langchain_cli/namespaces/app.py @@ -41,10 +41,25 @@ def new( Optional[List[str]], typer.Option(help="Packages to seed the project with"), ] = None, + pip: Annotated[ + Optional[bool], + typer.Option( + "--pip/--no-pip", + help="Pip install the template(s) as editable dependencies", + is_flag=True, + ), + ] = None, ): """ Create a new LangServe application. """ + has_packages = package is not None and len(package) > 0 + pip_bool = False + if pip is None and has_packages: + pip_bool = typer.confirm( + "Would you like to `pip install -e` the template(s)?", + default=False, + ) # copy over template from ../project_template project_template_dir = Path(__file__).parents[1] / "project_template" destination_dir = Path.cwd() / name if name != "." else Path.cwd() @@ -56,8 +71,8 @@ def new( readme.write_text(readme_contents.replace("__app_name__", app_name)) # add packages if specified - if package is not None and len(package) > 0: - add(package, project_dir=destination_dir) + if has_packages: + add(package, project_dir=destination_dir, pip=pip_bool) @app_cli.command() @@ -77,6 +92,15 @@ def add( branch: Annotated[ List[str], typer.Option(help="Install templates from a specific branch") ] = [], + pip: Annotated[ + bool, + typer.Option( + "--pip/--no-pip", + help="Pip install the template(s) as editable dependencies", + is_flag=True, + prompt="Would you like to `pip install -e` the template(s)?", + ), + ], ): """ Adds the specified template to the current LangServe app. @@ -164,47 +188,49 @@ def add( # Can fail if the cwd is not a parent of the package typer.echo("Failed to print install command, continuing...") else: - cmd = ["pip", "install", "-e"] + installed_destination_strs - cmd_str = " \\\n ".join(installed_destination_strs) - install_str = f"To install:\n\npip install -e \\\n {cmd_str}" - typer.echo(install_str) - - if typer.confirm("Run it?"): + if pip: + cmd = ["pip", "install", "-e"] + installed_destination_strs + cmd_str = " \\\n ".join(installed_destination_strs) + typer.echo(f"Running: pip install -e \\\n {cmd_str}") subprocess.run(cmd, cwd=cwd) - if typer.confirm("\nGenerate route code for these packages?", default=True): - chain_names = [] - for e in installed_exports: - original_candidate = f'{e["package_name"].replace("-", "_")}_chain' - candidate = original_candidate - i = 2 - while candidate in chain_names: - candidate = original_candidate + "_" + str(i) - i += 1 - chain_names.append(candidate) + chain_names = [] + for e in installed_exports: + original_candidate = f'{e["package_name"].replace("-", "_")}_chain' + candidate = original_candidate + i = 2 + while candidate in chain_names: + candidate = original_candidate + "_" + str(i) + i += 1 + chain_names.append(candidate) - api_paths = [ - str(Path("/") / path.relative_to(package_dir)) - for path in installed_destination_paths - ] + api_paths = [ + str(Path("/") / path.relative_to(package_dir)) + for path in installed_destination_paths + ] - imports = [ - f"from {e['module']} import {e['attr']} as {name}" - for e, name in zip(installed_exports, chain_names) - ] - routes = [ - f'add_routes(app, {name}, path="{path}")' - for name, path in zip(chain_names, api_paths) - ] + imports = [ + f"from {e['module']} import {e['attr']} as {name}" + for e, name in zip(installed_exports, chain_names) + ] + routes = [ + f'add_routes(app, {name}, path="{path}")' + for name, path in zip(chain_names, api_paths) + ] - lines = ( - ["", "Great! Add the following to your app:\n\n```", ""] - + imports - + [""] - + routes - + ["```"] - ) - typer.echo("\n".join(lines)) + t = ( + "this template" + if len(chain_names) == 1 + else f"these {len(chain_names)} templates" + ) + lines = ( + ["", f"To use {t}, add the following to your app:\n\n```", ""] + + imports + + [""] + + routes + + ["```"] + ) + typer.echo("\n".join(lines)) @app_cli.command() diff --git a/libs/cli/pyproject.toml b/libs/cli/pyproject.toml index 5819b74f492..20f9398fab0 100644 --- a/libs/cli/pyproject.toml +++ b/libs/cli/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "langchain-cli" -version = "0.0.15" +version = "0.0.16" description = "CLI for interacting with LangChain" authors = ["Erick Friis "] readme = "README.md"