mirror of
https://github.com/hwchase17/langchain.git
synced 2025-06-02 21:23:32 +00:00
parent
9f85f7c543
commit
d9018ae5f1
@ -1,5 +1,12 @@
|
||||
"""A CLI for creating a new project with LangChain."""
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
|
||||
from typing_extensions import Annotated
|
||||
|
||||
from langchain.cli.create_repo.base import create, is_poetry_installed
|
||||
from langchain.cli.create_repo.pypi_name import is_name_taken, lint_name
|
||||
from langchain.cli.create_repo.user_info import get_git_user_email, get_git_user_name
|
||||
|
||||
try:
|
||||
import typer
|
||||
@ -9,45 +16,94 @@ except ImportError:
|
||||
"You can install it with `pip install typer`."
|
||||
)
|
||||
|
||||
from typing_extensions import Annotated
|
||||
|
||||
from langchain.cli.create_repo.base import create, is_poetry_installed
|
||||
from langchain.cli.create_repo.user_info import get_git_user_email, get_git_user_name
|
||||
|
||||
app = typer.Typer(no_args_is_help=False, add_completion=False)
|
||||
|
||||
|
||||
AUTHOR_NAME_OPTION = typer.Option(
|
||||
default_factory=get_git_user_name,
|
||||
prompt=True,
|
||||
help="If not specified, will be inferred from git config if possible. ",
|
||||
)
|
||||
AUTHOR_EMAIL_OPTION = typer.Option(
|
||||
default_factory=get_git_user_email,
|
||||
prompt=True,
|
||||
help="If not specified, will be inferred from git config if possible. ",
|
||||
)
|
||||
USE_POETRY_OPTION = typer.Option(
|
||||
default_factory=is_poetry_installed,
|
||||
prompt=True,
|
||||
help=(
|
||||
"Whether to use Poetry to manage the project. "
|
||||
"If not specified, Poetry will be used if poetry is installed."
|
||||
),
|
||||
)
|
||||
def _select_project_name(suggested_project_name: str) -> str:
|
||||
"""Help the user select a valid project name."""
|
||||
while True:
|
||||
project_name = typer.prompt("Project Name", default=suggested_project_name)
|
||||
|
||||
project_name_diagnostics = lint_name(project_name)
|
||||
if project_name_diagnostics:
|
||||
typer.echo(
|
||||
f"{typer.style('Warning:', fg=typer.colors.MAGENTA)}"
|
||||
f" The project name"
|
||||
f" {typer.style(project_name, fg=typer.colors.BRIGHT_CYAN)}"
|
||||
f" is not valid.",
|
||||
err=True,
|
||||
)
|
||||
|
||||
for diagnostic in project_name_diagnostics:
|
||||
typer.echo(f" - {diagnostic}")
|
||||
|
||||
if typer.confirm(
|
||||
"Select another name?",
|
||||
default=True,
|
||||
):
|
||||
continue
|
||||
|
||||
if is_name_taken(project_name):
|
||||
typer.echo(
|
||||
f"{typer.style('Error:', fg=typer.colors.RED)}"
|
||||
f" The project name"
|
||||
f" {typer.style(project_name, fg=typer.colors.BRIGHT_CYAN)}"
|
||||
f" is already taken on pypi",
|
||||
err=True,
|
||||
)
|
||||
|
||||
if typer.confirm(
|
||||
"Select another name?",
|
||||
default=True,
|
||||
):
|
||||
continue
|
||||
|
||||
# If we got here then the project name is valid and not taken
|
||||
return project_name
|
||||
|
||||
|
||||
#
|
||||
#
|
||||
@app.command()
|
||||
def new(
|
||||
project_directory: Annotated[
|
||||
Path, typer.Argument(help="The directory to create the project in.")
|
||||
],
|
||||
author_name: Annotated[str, AUTHOR_NAME_OPTION],
|
||||
author_email: Annotated[str, AUTHOR_EMAIL_OPTION],
|
||||
use_poetry: Annotated[bool, USE_POETRY_OPTION],
|
||||
author_name: Optional[str] = None,
|
||||
author_email: Optional[str] = None,
|
||||
use_poetry: Annotated[
|
||||
Optional[bool], typer.Option(help="Specify whether to use Poetry or not.")
|
||||
] = None,
|
||||
) -> None:
|
||||
"""Create a new project with LangChain."""
|
||||
create(project_directory, author_name, author_email, use_poetry)
|
||||
|
||||
project_directory_path = Path(project_directory)
|
||||
project_name_suggestion = project_directory_path.name.replace("-", "_")
|
||||
project_name = _select_project_name(project_name_suggestion)
|
||||
|
||||
if not author_name:
|
||||
author_name = typer.prompt("Author Name", default=get_git_user_name())
|
||||
|
||||
if not author_email:
|
||||
author_email = typer.prompt("Author Email", default=get_git_user_email())
|
||||
|
||||
if use_poetry is None:
|
||||
if is_poetry_installed():
|
||||
typer.echo("🎉 Found Poetry installed. Project can be set up using poetry.")
|
||||
use_poetry = typer.confirm("Use Poetry? (no to use pip)", default=True)
|
||||
else:
|
||||
typer.echo("ℹ️ Could not find Poetry installed.")
|
||||
use_pip = typer.confirm("Use Pip? (no to use poetry)", default=True)
|
||||
use_poetry = not use_pip
|
||||
|
||||
if author_name is None:
|
||||
raise typer.BadParameter("Author name is required")
|
||||
|
||||
if author_email is None:
|
||||
raise typer.BadParameter("Author email is required")
|
||||
|
||||
create(project_directory, project_name, author_name, author_email, use_poetry)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
@ -9,7 +9,6 @@ from typing import List, Sequence
|
||||
import typer
|
||||
|
||||
import langchain
|
||||
from langchain.cli.create_repo.pypi_name import is_name_taken, lint_name
|
||||
|
||||
|
||||
class UnderscoreTemplate(string.Template):
|
||||
@ -145,7 +144,7 @@ def _pip_install(project_directory_path: Path) -> None:
|
||||
def _init_git(project_directory_path: Path) -> None:
|
||||
"""Initialize git repository."""
|
||||
typer.echo(
|
||||
f"\n{typer.style('3.', bold=True, fg=typer.colors.GREEN)} Initializing git..."
|
||||
f"\n{typer.style('Initializing git...', bold=True, fg=typer.colors.GREEN)}"
|
||||
)
|
||||
subprocess.run(["git", "init"], cwd=project_directory_path)
|
||||
|
||||
@ -157,58 +156,12 @@ def _init_git(project_directory_path: Path) -> None:
|
||||
)
|
||||
|
||||
|
||||
def _select_project_name(suggested_project_name: str) -> str:
|
||||
"""Help the user select a valid project name."""
|
||||
while True:
|
||||
project_name = typer.prompt(
|
||||
"Please choose a project name: ", default=suggested_project_name
|
||||
)
|
||||
|
||||
project_name_diagnostics = lint_name(project_name)
|
||||
if project_name_diagnostics:
|
||||
typer.echo(
|
||||
f"{typer.style('Error:', fg=typer.colors.RED)}"
|
||||
f" The project name"
|
||||
f" {typer.style(project_name, fg=typer.colors.BRIGHT_CYAN)}"
|
||||
f" is not valid:",
|
||||
err=True,
|
||||
)
|
||||
|
||||
for diagnostic in project_name_diagnostics:
|
||||
typer.echo(f" - {diagnostic}")
|
||||
|
||||
if typer.confirm(
|
||||
"Would you like to choose another name? "
|
||||
"Choose NO to proceed with existing name.",
|
||||
default=True,
|
||||
):
|
||||
continue
|
||||
|
||||
if is_name_taken(project_name):
|
||||
typer.echo(
|
||||
f"{typer.style('Error:', fg=typer.colors.RED)}"
|
||||
f" The project name"
|
||||
f" {typer.style(project_name, fg=typer.colors.BRIGHT_CYAN)}"
|
||||
f" is already taken on pypi",
|
||||
err=True,
|
||||
)
|
||||
|
||||
if typer.confirm(
|
||||
"Would you like to choose another name? "
|
||||
"Choose NO to proceed with existing name.",
|
||||
default=True,
|
||||
):
|
||||
continue
|
||||
|
||||
# If we got here then the project name is valid and not taken
|
||||
return project_name
|
||||
|
||||
|
||||
# PUBLIC API
|
||||
|
||||
|
||||
def create(
|
||||
project_directory: pathlib.Path,
|
||||
project_name: str,
|
||||
author_name: str,
|
||||
author_email: str,
|
||||
use_poetry: bool,
|
||||
@ -217,27 +170,29 @@ def create(
|
||||
|
||||
Args:
|
||||
project_directory (str): The directory to create the project in.
|
||||
project_name: The name of the project.
|
||||
author_name (str): The name of the author.
|
||||
author_email (str): The email of the author.
|
||||
use_poetry (bool): Whether to use Poetry to manage the project.
|
||||
"""
|
||||
|
||||
project_directory_path = Path(project_directory)
|
||||
project_name_suggestion = project_directory_path.name.replace("-", "_")
|
||||
project_name = _select_project_name(project_name_suggestion)
|
||||
project_name_identifier = project_name
|
||||
|
||||
resolved_path = project_directory_path.resolve()
|
||||
|
||||
if not typer.confirm(
|
||||
f"\n{typer.style('>', bold=True, fg=typer.colors.GREEN)} "
|
||||
f"Creating new LangChain project "
|
||||
f"{typer.style(project_name, fg=typer.colors.BRIGHT_CYAN)}"
|
||||
f" in"
|
||||
f" {typer.style(resolved_path, fg=typer.colors.BRIGHT_CYAN)}",
|
||||
f"\n"
|
||||
f"Creating a new LangChain project 🦜️🔗\n"
|
||||
f"Name: {typer.style(project_name, fg=typer.colors.BRIGHT_CYAN)}\n"
|
||||
f"Path: {typer.style(resolved_path, fg=typer.colors.BRIGHT_CYAN)}\n"
|
||||
f"Project name: {typer.style(project_name, fg=typer.colors.BRIGHT_CYAN)}\n"
|
||||
f"Author name: {typer.style(author_name, fg=typer.colors.BRIGHT_CYAN)}\n"
|
||||
f"Author email: {typer.style(author_email, fg=typer.colors.BRIGHT_CYAN)}\n"
|
||||
f"Use Poetry: {typer.style(str(use_poetry), fg=typer.colors.BRIGHT_CYAN)}\n"
|
||||
"Continue?",
|
||||
default=True,
|
||||
):
|
||||
typer.echo("OK! Canceling project creation.")
|
||||
typer.echo("Cancelled project creation. See you later! 👋")
|
||||
raise typer.Exit(code=0)
|
||||
|
||||
_create_project_dir(
|
||||
@ -258,7 +213,7 @@ def create(
|
||||
_init_git(project_directory_path)
|
||||
|
||||
typer.echo(
|
||||
f"\n{typer.style('Done!', bold=True, fg=typer.colors.GREEN)}"
|
||||
f"\n{typer.style('Done!🙌', bold=True, fg=typer.colors.GREEN)}"
|
||||
f" Your new LangChain project"
|
||||
f" {typer.style(project_name, fg=typer.colors.BRIGHT_CYAN)}"
|
||||
f" has been created in"
|
||||
|
Loading…
Reference in New Issue
Block a user