Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 221
[feature] Adubatl/model fetching poc#326
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
3457a871b10fc5ddf08a0692b85b498a90bb4a479a0f978544e06f55508bad7File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,26 +1,12 @@ | ||
| from typing import Optional | ||
| import os, sys | ||
| from art import text2art | ||
| import inquirer | ||
| import questionary | ||
| from agentstack import conf, log | ||
| from agentstack.conf import ConfigFile | ||
| from agentstack.exceptions import ValidationError | ||
| from agentstack.utils import validator_not_empty, is_snake_case | ||
| from agentstack.utils import is_snake_case | ||
| from agentstack.generation import InsertionPoint | ||
| from agentstack import repo | ||
| PREFERRED_MODELS = [ | ||
| 'groq/deepseek-r1-distill-llama-70b', | ||
| 'deepseek/deepseek-chat', | ||
| 'deepseek/deepseek-coder', | ||
| 'deepseek/deepseek-reasoner', | ||
| 'openai/gpt-4o', | ||
| 'anthropic/claude-3-5-sonnet', | ||
| 'openai/o1-preview', | ||
| 'openai/gpt-4-turbo', | ||
| 'anthropic/claude-3-opus', | ||
| ] | ||
| from agentstack.providers import get_available_models | ||
| def welcome_message(): | ||
| @@ -38,16 +24,18 @@ def welcome_message(): | ||
| def undo() -> None: | ||
| """Undo the last committed changes.""" | ||
| conf.assert_project() | ||
| changed_files = repo.get_uncommitted_files() | ||
| if changed_files: | ||
| log.warning("There are uncommitted changes that may be overwritten.") | ||
| for changed in changed_files: | ||
| log.info(f" - {changed}") | ||
| should_continue = inquirer.confirm( | ||
| message="Do you want to continue?", | ||
| should_continue = questionary.confirm( | ||
| "Do you want to continue?", | ||
| default=False, | ||
| ) | ||
| ).ask() | ||
| if not should_continue: | ||
| return | ||
| @@ -59,18 +47,27 @@ def configure_default_model(): | ||
| agentstack_config = ConfigFile() | ||
| if agentstack_config.default_model: | ||
| log.debug("Using default model from project config.") | ||
| return # Default model already set | ||
adubatl marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| return | ||
| log.info("Project does not have a default model configured.") | ||
| other_msg = "Other (enter a model name)" | ||
adubatl marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| model = inquirer.list_input( | ||
| message="Which model would you like to use?", | ||
| choices=PREFERRED_MODELS + [other_msg], | ||
| ) | ||
| if model == other_msg: # If the user selects "Other", prompt for a model name | ||
| available_models = get_available_models() | ||
| other_msg = "Other (enter a model name)" | ||
| model = questionary.select( | ||
| "Which model would you like to use?", | ||
| choices=available_models + [other_msg], | ||
| use_indicator=True, | ||
| use_shortcuts=False, | ||
| use_jk_keys=False, | ||
| use_emacs_keys=False, | ||
| use_arrow_keys=True, | ||
| use_search_filter=True, | ||
| ).ask() | ||
| if model == other_msg: | ||
| log.info('A list of available models is available at: "https://docs.litellm.ai/docs/providers"') | ||
| model = inquirer.text(message="Enter the model name") | ||
| model = questionary.text("Enter the model name:").ask() | ||
| log.debug("Writing default model to project config.") | ||
| with ConfigFile() as agentstack_config: | ||
| @@ -92,13 +89,23 @@ def get_validated_input( | ||
| snake_case: Whether to enforce snake_case naming | ||
| """ | ||
| while True: | ||
| value = inquirer.text( | ||
| message=message, | ||
| validate=validate_func or validator_not_empty(min_length) if min_length else None, | ||
| ) | ||
| if snake_case and not is_snake_case(value): | ||
| raise ValidationError("Input must be in snake_case") | ||
| return value | ||
| def validate(text: str) -> bool: | ||
| if min_length and len(text) < min_length: | ||
| return False | ||
| if snake_case and not is_snake_case(text): | ||
| return False | ||
| if validate_func and not validate_func(text): | ||
| return False | ||
| return True | ||
| value = questionary.text( | ||
| message, | ||
| validate=validate if validate_func or min_length or snake_case else None, | ||
| ).ask() | ||
| if value: | ||
| return value | ||
| def parse_insertion_point(position: Optional[str] = None) -> Optional[InsertionPoint]: | ||
| @@ -113,4 +120,3 @@ def parse_insertion_point(position: Optional[str] = None) -> Optional[InsertionP | ||
| raise ValueError(f"Position must be one of {','.join(valid_positions)}.") | ||
| return next(x for x in InsertionPoint if x.value == position) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,7 @@ | ||
| import os, sys | ||
| import os | ||
| import sys | ||
| from typing import Optional | ||
| from pathlib import Path | ||
| import inquirer | ||
| import questionary | ||
| from textwrap import shorten | ||
| from agentstack import conf, log | ||
| @@ -38,37 +38,28 @@ def require_uv(): | ||
| def prompt_slug_name() -> str: | ||
| """Prompt the user for a project name.""" | ||
| def _validate(slug_name: Optional[str]) -> bool: | ||
| if not slug_name: | ||
| def validate(text: str) -> bool: | ||
adubatl marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| if not text: | ||
| log.error("Project name cannot be empty") | ||
| return False | ||
| if not is_snake_case(slug_name): | ||
| if not is_snake_case(text): | ||
| log.error("Project name must be snake_case") | ||
| return False | ||
| if os.path.exists(conf.PATH / slug_name): | ||
| log.error(f"Project path already exists: {conf.PATH / slug_name}") | ||
| if os.path.exists(conf.PATH / text): | ||
| log.error(f"Project path already exists: {conf.PATH / text}") | ||
| return False | ||
| return True | ||
| def _prompt() -> str: | ||
| return inquirer.text( | ||
| message="Project name (snake_case)", | ||
| ) | ||
| log.info( | ||
| "Provide a project name. This will be used to create a new directory in the " | ||
| "current path and will be used as the project name. 🐍 Must be snake_case." | ||
| ) | ||
| slug_name = None | ||
| while not _validate(slug_name): | ||
| slug_name = _prompt() | ||
| assert slug_name # appease type checker | ||
| return slug_name | ||
| return questionary.text("Project name (snake_case)", validate=validate).ask() | ||
| def select_template(slug_name: str, framework: Optional[str] = None) -> TemplateConfig: | ||
| @@ -77,16 +68,23 @@ def select_template(slug_name: str, framework: Optional[str] = None) -> Template | ||
| EMPTY = 'empty' | ||
| choices = [ | ||
| (EMPTY, "🆕 Empty Project"), | ||
| questionary.Choice('🆕 Empty Project', EMPTY), | ||
| ] | ||
| for template in templates: | ||
| choices.append((template.name, shorten(f"⚡️ {template.name} - {template.description}", 80))) | ||
| choices.append( | ||
| questionary.Choice(f"⚡️ {template.name} - {shorten(template.description, 80)}", template.name) | ||
| ) | ||
| choice = inquirer.list_input( | ||
| message="Do you want to start with a template?", | ||
| choices=[c[1] for c in choices], | ||
| ) | ||
| template_name = next(c[0] for c in choices if c[1] == choice) | ||
| template_name = questionary.select( | ||
| "Do you want to start with a template?", | ||
| choices=choices, | ||
| use_indicator=True, | ||
| use_shortcuts=False, | ||
| use_jk_keys=False, | ||
| use_emacs_keys=False, | ||
| use_arrow_keys=True, | ||
| use_search_filter=True, | ||
| ).ask() | ||
| if template_name == EMPTY: | ||
| return TemplateConfig( | ||
| @@ -148,11 +146,11 @@ def init_project( | ||
| if framework is None: | ||
| framework = template_data.framework | ||
| if framework in frameworks.ALIASED_FRAMEWORKS: | ||
| framework = frameworks.ALIASED_FRAMEWORKS[framework] | ||
| if not framework in frameworks.SUPPORTED_FRAMEWORKS: | ||
| if framework not in frameworks.SUPPORTED_FRAMEWORKS: | ||
| raise Exception(f"Framework '{framework}' is not supported.") | ||
| log.info(f"Using framework: {framework}") | ||
| @@ -163,7 +161,7 @@ def init_project( | ||
| packaging.create_venv() | ||
| log.info("Installing dependencies...") | ||
| packaging.install_project() | ||
| if repo.find_parent_repo(conf.PATH): | ||
| # if a repo already exists, we don't want to initialize a new one | ||
| log.info("Found existing git repository; disabling tracking.") | ||
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.