-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Feature] Add multiple LLM API providers (#13)
This PR expands the LLM features to multiple selectable providers. - Groq running Llama 3 70B - Anthropic Claude 3 Opus - OpenAI GPT-4 Turbo It should be relatively simple to add more providers in the future. Officially removing the 'experimental' tag from the LLM features. GPT-4 Turbo is the clear best pick so made that the default setting.
- Loading branch information
Showing
19 changed files
with
773 additions
and
318 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -24,9 +24,11 @@ | |
# Go workspace file | ||
go.work | ||
|
||
# build directory | ||
dist/ | ||
|
||
# Project specific | ||
build | ||
test_build | ||
tbd | ||
|
||
dist/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,14 +4,15 @@ import ( | |
"errors" | ||
"fmt" | ||
"strconv" | ||
"strings" | ||
|
||
"github.com/charmbracelet/huh" | ||
"github.com/fatih/color" | ||
) | ||
|
||
type FormResponse struct { | ||
Path string | ||
Username string | ||
Password string | ||
Host string | ||
BuildDir string | ||
SslMode string | ||
Database string | ||
|
@@ -21,21 +22,23 @@ type FormResponse struct { | |
ProjectName string | ||
Warehouse string | ||
Account string | ||
GroqKeyEnvVar string | ||
Password string | ||
DbtProfileName string | ||
LlmKeyEnvVar string | ||
DbtProfileOutput string | ||
DbtProfileName string | ||
Path string | ||
Port string | ||
Host string | ||
Username string | ||
Prefix string | ||
Llm string | ||
GenerateDescriptions bool | ||
ScaffoldProject bool | ||
CreateProfile bool | ||
UseDbtProfile bool | ||
Confirm bool | ||
} | ||
|
||
var not_empty = func(s string) error { | ||
func notEmpty(s string) error { | ||
s = strings.TrimSpace(s) | ||
if len(s) == 0 { | ||
return fmt.Errorf("cannot be empty, please enter a value") | ||
} | ||
|
@@ -55,17 +58,16 @@ func getProfileOptions(ps DbtProfiles) []huh.Option[string] { | |
|
||
func Forms(ps DbtProfiles) (FormResponse, error) { | ||
dfr := FormResponse{ | ||
BuildDir: "build", | ||
GroqKeyEnvVar: "GROQ_API_KEY", | ||
Prefix: "stg", | ||
Host: "localhost", | ||
Port: "5432", | ||
BuildDir: "build", | ||
LlmKeyEnvVar: "OPENAI_API_KEY", | ||
Prefix: "stg", | ||
Host: "localhost", | ||
Port: "5432", | ||
} | ||
pinkUnderline := color.New(color.FgMagenta).Add(color.Bold, color.Underline).SprintFunc() | ||
greenBold := color.New(color.FgGreen).Add(color.Bold).SprintFunc() | ||
yellowItalic := color.New(color.FgHiYellow).Add(color.Italic).SprintFunc() | ||
greenBoldItalic := color.New(color.FgHiGreen).Add(color.Bold).SprintFunc() | ||
redBold := color.New(color.FgHiRed).Add(color.Bold).SprintFunc() | ||
err := huh.NewForm( | ||
huh.NewGroup( | ||
huh.NewNote(). | ||
|
@@ -94,14 +96,14 @@ https://github.com/gwenwindflower/tbd | |
Title("What *prefix* for your staging files?"). | ||
Value(&dfr.Prefix). | ||
Placeholder("stg"). | ||
Validate(not_empty), | ||
Validate(notEmpty), | ||
), | ||
|
||
huh.NewGroup(huh.NewInput(). | ||
Title("What is the *name* of your dbt project?"). | ||
Value(&dfr.ProjectName). | ||
Placeholder("rivendell"). | ||
Validate(not_empty), | ||
Validate(notEmpty), | ||
).WithHideFunc(func() bool { | ||
return !dfr.ScaffoldProject | ||
}), | ||
|
@@ -123,17 +125,17 @@ https://github.com/gwenwindflower/tbd | |
Title("Which *output* in that profile do you want to use?"). | ||
Value(&dfr.DbtProfileOutput). | ||
Placeholder("dev"). | ||
Validate(not_empty), | ||
Validate(notEmpty), | ||
huh.NewInput(). | ||
Title("What *schema* do you want to generate?"). | ||
Value(&dfr.Schema). | ||
Placeholder("raw"). | ||
Validate(not_empty), | ||
Validate(notEmpty), | ||
huh.NewInput(). | ||
Title("What *database* is that schema in?"). | ||
Value(&dfr.Database). | ||
Placeholder("jaffle_shop"). | ||
Validate(not_empty), | ||
Validate(notEmpty), | ||
).WithHideFunc(func() bool { | ||
return !dfr.UseDbtProfile | ||
}), | ||
|
@@ -157,22 +159,22 @@ https://github.com/gwenwindflower/tbd | |
Title("What is your username?"). | ||
Value(&dfr.Username). | ||
Placeholder("[email protected]"). | ||
Validate(not_empty), | ||
Validate(notEmpty), | ||
huh.NewInput(). | ||
Title("What is your Snowflake account id?"). | ||
Value(&dfr.Account). | ||
Placeholder("elfstone-consulting.us-west-1"). | ||
Validate(not_empty), | ||
Validate(notEmpty), | ||
huh.NewInput(). | ||
Title("What is the *schema* you want to generate?"). | ||
Value(&dfr.Schema). | ||
Placeholder("minas-tirith"). | ||
Validate(not_empty), | ||
Validate(notEmpty), | ||
huh.NewInput(). | ||
Title("What *database* is that schema in?"). | ||
Value(&dfr.Database). | ||
Placeholder("gondor"). | ||
Validate(not_empty), | ||
Validate(notEmpty), | ||
).WithHideFunc(func() bool { | ||
return dfr.Warehouse != "snowflake" | ||
}), | ||
|
@@ -182,12 +184,12 @@ https://github.com/gwenwindflower/tbd | |
Title("What GCP *project id* do you want to generate?"). | ||
Value(&dfr.Project). | ||
Placeholder("legolas_inc"). | ||
Validate(not_empty), | ||
Validate(notEmpty), | ||
huh.NewInput(). | ||
Title("What is the *dataset* you want to generate?"). | ||
Value(&dfr.Dataset). | ||
Placeholder("mirkwood"). | ||
Validate(not_empty), | ||
Validate(notEmpty), | ||
).WithHideFunc(func() bool { | ||
return dfr.Warehouse != "bigquery" | ||
}), | ||
|
@@ -198,17 +200,17 @@ https://github.com/gwenwindflower/tbd | |
Relative to pwd e.g. if db is in this dir -> cool_ducks.db`). | ||
Value(&dfr.Path). | ||
Placeholder("/path/to/duckdb.db"). | ||
Validate(not_empty), | ||
Validate(notEmpty), | ||
huh.NewInput(). | ||
Title("What is the *database* you want to generate?"). | ||
Value(&dfr.Database). | ||
Placeholder("gimli_corp"). | ||
Validate(not_empty), | ||
Validate(notEmpty), | ||
huh.NewInput(). | ||
Title("What is the *schema* you want to generate?"). | ||
Value(&dfr.Schema). | ||
Placeholder("moria"). | ||
Validate(not_empty), | ||
Validate(notEmpty), | ||
).WithHideFunc(func() bool { | ||
return dfr.Warehouse != "duckdb" | ||
}), | ||
|
@@ -217,7 +219,7 @@ Relative to pwd e.g. if db is in this dir -> cool_ducks.db`). | |
huh.NewInput(). | ||
Title("What is your Postgres *host*?"). | ||
Value(&dfr.Host). | ||
Validate(not_empty), | ||
Validate(notEmpty), | ||
huh.NewInput(). | ||
Title("What is your Postgres *port*?"). | ||
Value(&dfr.Port). | ||
|
@@ -232,22 +234,22 @@ Relative to pwd e.g. if db is in this dir -> cool_ducks.db`). | |
Title("What is your Postgres *username*?"). | ||
Value(&dfr.Username). | ||
Placeholder("galadriel"). | ||
Validate(not_empty), | ||
Validate(notEmpty), | ||
huh.NewInput(). | ||
Title("What is your Postgres *password*?"). | ||
Value(&dfr.Password). | ||
Validate(not_empty). | ||
Validate(notEmpty). | ||
EchoMode(huh.EchoModePassword), | ||
huh.NewInput(). | ||
Title("What is the *database* you want to generate?"). | ||
Value(&dfr.Database). | ||
Placeholder("lothlorien"). | ||
Validate(not_empty), | ||
Validate(notEmpty), | ||
huh.NewInput(). | ||
Title("What is the *schema* you want to generate?"). | ||
Value(&dfr.Schema). | ||
Placeholder("mallorn_trees"). | ||
Validate(not_empty), | ||
Validate(notEmpty), | ||
huh.NewSelect[string](). | ||
Title("What ssl mode do you want to use?"). | ||
Value(&dfr.SslMode). | ||
|
@@ -258,32 +260,36 @@ Relative to pwd e.g. if db is in this dir -> cool_ducks.db`). | |
huh.NewOption("Verify-full", "verify-full"), | ||
huh.NewOption("Prefer", "prefer"), | ||
huh.NewOption("Allow", "allow")). | ||
Validate(not_empty), | ||
Validate(notEmpty), | ||
).WithHideFunc(func() bool { | ||
return dfr.Warehouse != "postgres" | ||
}), | ||
|
||
huh.NewGroup( | ||
huh.NewNote(). | ||
Title(fmt.Sprintf("🤖 %s LLM generation 🦙✨", redBold("Experimental"))). | ||
Description(fmt.Sprintf(`%s features via Groq. | ||
Currently generates: | ||
Title(fmt.Sprintf("🤖 %s LLM generation 🦙✨", yellowItalic("Optional"))). | ||
Description(fmt.Sprintf(`Infers: | ||
✴︎ column %s | ||
✴︎ relevant %s | ||
_Requires a_ %s _stored in an env var_: | ||
Get one at https://groq.com.`, yellowItalic("Optional"), pinkUnderline("descriptions"), pinkUnderline("tests"), greenBoldItalic("Groq API key"))), | ||
_Requires an_ %s _stored in an env var_.`, pinkUnderline("descriptions"), pinkUnderline("tests"), greenBoldItalic("API key"))), | ||
huh.NewConfirm(). | ||
Title("Do you want to infer descriptions and tests?"). | ||
Value(&dfr.GenerateDescriptions), | ||
), | ||
|
||
huh.NewGroup( | ||
huh.NewSelect[string](). | ||
Options( | ||
huh.NewOption("OpenAI", "openai"), | ||
huh.NewOption("Groq", "groq"), | ||
huh.NewOption("Anthropic", "anthropic"), | ||
).Value(&dfr.Llm), | ||
huh.NewInput(). | ||
Title("What env var holds your Groq key?"). | ||
Placeholder("GROQ_API_KEY"). | ||
Value(&dfr.GroqKeyEnvVar). | ||
Validate(not_empty), | ||
Title("What env var holds your LLM API key?"). | ||
Placeholder("OPENAI_API_KEY"). | ||
Value(&dfr.LlmKeyEnvVar). | ||
Validate(notEmpty), | ||
).WithHideFunc(func() bool { | ||
return !dfr.GenerateDescriptions | ||
}), | ||
|
@@ -293,7 +299,7 @@ Get one at https://groq.com.`, yellowItalic("Optional"), pinkUnderline("descript | |
Title("What directory do you want to build into?\n Must be new or empty."). | ||
Value(&dfr.BuildDir). | ||
Placeholder("build"). | ||
Validate(not_empty), | ||
Validate(notEmpty), | ||
huh.NewConfirm(). | ||
Title("🚦Are you ready to do this thing?🚦"). | ||
Value(&dfr.Confirm), | ||
|
Oops, something went wrong.