2023-10-25 18:06:58 +00:00
|
|
|
"""
|
2023-10-30 23:39:39 +00:00
|
|
|
Develop installable templates.
|
2023-10-25 18:06:58 +00:00
|
|
|
"""
|
|
|
|
|
2023-10-27 00:01:31 +00:00
|
|
|
import re
|
2023-10-25 18:06:58 +00:00
|
|
|
import shutil
|
|
|
|
import subprocess
|
2023-10-27 00:01:31 +00:00
|
|
|
from pathlib import Path
|
|
|
|
from typing import Optional
|
|
|
|
|
|
|
|
import typer
|
2023-10-27 19:06:46 +00:00
|
|
|
from langserve.packages import get_langserve_export
|
2023-10-27 00:01:31 +00:00
|
|
|
from typing_extensions import Annotated
|
2023-10-25 18:06:58 +00:00
|
|
|
|
2023-10-27 19:06:46 +00:00
|
|
|
from langchain_cli.utils.packages import get_package_root
|
|
|
|
|
2023-10-30 23:39:39 +00:00
|
|
|
package_cli = typer.Typer(no_args_is_help=True, add_completion=False)
|
2023-10-25 18:06:58 +00:00
|
|
|
|
|
|
|
|
2023-10-30 23:39:39 +00:00
|
|
|
@package_cli.command()
|
2023-10-25 18:06:58 +00:00
|
|
|
def new(
|
|
|
|
name: Annotated[str, typer.Argument(help="The name of the folder to create")],
|
|
|
|
with_poetry: Annotated[
|
|
|
|
bool,
|
2023-10-27 19:06:46 +00:00
|
|
|
typer.Option("--with-poetry/--no-poetry", help="Don't run poetry install"),
|
2023-10-25 18:06:58 +00:00
|
|
|
] = False,
|
|
|
|
):
|
|
|
|
"""
|
2023-10-30 23:39:39 +00:00
|
|
|
Creates a new template package.
|
2023-10-25 18:06:58 +00:00
|
|
|
"""
|
|
|
|
computed_name = name if name != "." else Path.cwd().name
|
|
|
|
destination_dir = Path.cwd() / name if name != "." else Path.cwd()
|
|
|
|
|
|
|
|
# copy over template from ../package_template
|
2023-10-26 20:30:36 +00:00
|
|
|
project_template_dir = Path(__file__).parents[1] / "package_template"
|
2023-10-25 18:06:58 +00:00
|
|
|
shutil.copytree(project_template_dir, destination_dir, dirs_exist_ok=name == ".")
|
|
|
|
|
|
|
|
package_name_split = computed_name.split("/")
|
2023-10-30 23:39:39 +00:00
|
|
|
package_name = (
|
2023-10-25 18:06:58 +00:00
|
|
|
package_name_split[-2]
|
|
|
|
if len(package_name_split) > 1 and package_name_split[-1] == ""
|
|
|
|
else package_name_split[-1]
|
|
|
|
)
|
2023-10-30 23:39:39 +00:00
|
|
|
module_name = re.sub(
|
2023-10-25 18:06:58 +00:00
|
|
|
r"[^a-zA-Z0-9_]",
|
|
|
|
"_",
|
2023-10-30 23:39:39 +00:00
|
|
|
package_name,
|
|
|
|
)
|
|
|
|
|
|
|
|
# generate app route code
|
|
|
|
chain_name = f"{module_name}_chain"
|
|
|
|
app_route_code = (
|
|
|
|
f"from {module_name} import chain as {chain_name}\n\n"
|
|
|
|
f'add_routes(app, {chain_name}, path="/{package_name}")'
|
2023-10-25 18:06:58 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
# replace template strings
|
|
|
|
pyproject = destination_dir / "pyproject.toml"
|
|
|
|
pyproject_contents = pyproject.read_text()
|
|
|
|
pyproject.write_text(
|
2023-11-01 16:48:37 +00:00
|
|
|
pyproject_contents.replace("__package_name__", package_name).replace(
|
2023-10-30 23:39:39 +00:00
|
|
|
"__module_name__", module_name
|
|
|
|
)
|
2023-10-25 18:06:58 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
# move module folder
|
2023-10-30 23:39:39 +00:00
|
|
|
package_dir = destination_dir / module_name
|
2023-10-25 18:06:58 +00:00
|
|
|
shutil.move(destination_dir / "package_template", package_dir)
|
|
|
|
|
|
|
|
# replace readme
|
|
|
|
readme = destination_dir / "README.md"
|
|
|
|
readme_contents = readme.read_text()
|
|
|
|
readme.write_text(
|
2023-10-31 07:06:02 +00:00
|
|
|
readme_contents.replace("__package_name__", package_name).replace(
|
2023-10-30 23:39:39 +00:00
|
|
|
"__app_route_code__", app_route_code
|
|
|
|
)
|
2023-10-25 18:06:58 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
# poetry install
|
|
|
|
if with_poetry:
|
|
|
|
subprocess.run(["poetry", "install"], cwd=destination_dir)
|
|
|
|
|
|
|
|
|
2023-10-30 23:39:39 +00:00
|
|
|
@package_cli.command()
|
|
|
|
def serve(
|
2023-10-25 18:06:58 +00:00
|
|
|
*,
|
|
|
|
port: Annotated[
|
|
|
|
Optional[int], typer.Option(help="The port to run the server on")
|
|
|
|
] = None,
|
|
|
|
host: Annotated[
|
|
|
|
Optional[str], typer.Option(help="The host to run the server on")
|
|
|
|
] = None,
|
|
|
|
) -> None:
|
|
|
|
"""
|
2023-10-30 23:39:39 +00:00
|
|
|
Starts a demo app for this template.
|
2023-10-25 18:06:58 +00:00
|
|
|
"""
|
2023-10-27 19:06:46 +00:00
|
|
|
# load pyproject.toml
|
|
|
|
project_dir = get_package_root()
|
|
|
|
pyproject = project_dir / "pyproject.toml"
|
|
|
|
|
|
|
|
# get langserve export - throws KeyError if invalid
|
|
|
|
get_langserve_export(pyproject)
|
|
|
|
|
|
|
|
port_str = str(port) if port is not None else "8000"
|
|
|
|
host_str = host if host is not None else "127.0.0.1"
|
|
|
|
|
|
|
|
command = [
|
|
|
|
"uvicorn",
|
2023-10-27 20:37:03 +00:00
|
|
|
"--factory",
|
2023-10-27 19:06:46 +00:00
|
|
|
"langchain_cli.dev_scripts:create_demo_server",
|
|
|
|
"--reload",
|
|
|
|
"--port",
|
|
|
|
port_str,
|
|
|
|
"--host",
|
|
|
|
host_str,
|
|
|
|
]
|
|
|
|
subprocess.run(command)
|