Skip to content
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

feat: add spring-ai-alibaba-studio go CLI #117

Open
wants to merge 23 commits into
base: workflow
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
7632778
init(cli): go cobra cli
ev1lQuark Nov 6, 2024
01bc686
feat: chatmodel list
ev1lQuark Nov 8, 2024
2e47761
feat(cli): add table and json printer
ev1lQuark Nov 11, 2024
004a315
feat(cli): adapt chatmodel list to multiple printers
ev1lQuark Nov 11, 2024
f3fc55e
feat(cli): update chatmodel opts
ev1lQuark Nov 11, 2024
878c33b
feat(cli): update get model detail and error handler
ev1lQuark Nov 11, 2024
89c96f7
feat(cli): update get model args
ev1lQuark Nov 11, 2024
b0723ba
update cmd usage message
ev1lQuark Nov 12, 2024
65996d1
add support for version message
ev1lQuark Nov 12, 2024
21c7a7f
feat(cli): add chatmodel run
ev1lQuark Nov 18, 2024
8e604b0
refactor(cli): code more testable
ev1lQuark Nov 19, 2024
4b60dd0
test(cli): add chatmodel handler unit tests
ev1lQuark Nov 20, 2024
f810d45
feat(cli): add loading display for net request
ev1lQuark Nov 20, 2024
58b0004
feat(cli): run image model
ev1lQuark Nov 20, 2024
43c9e70
fix(cli): license
ev1lQuark Nov 20, 2024
cc5d890
fix(cli): loading config file
ev1lQuark Nov 21, 2024
6409886
fix(cli): version help message
ev1lQuark Nov 21, 2024
b20f8e7
fix(cli): fix panic when config file not exist
ev1lQuark Dec 10, 2024
78e4574
feat(cli): add ui start command and makefile
ev1lQuark Dec 17, 2024
8192c9a
fix(cli): fix unit test error by embed
ev1lQuark Dec 17, 2024
32ce3c0
feat(cli): add init command to create example project
ev1lQuark Dec 18, 2024
ab777c6
doc(cli): add basic README
ev1lQuark Dec 18, 2024
650f5de
fix(cli): add licenses
ev1lQuark Dec 18, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions spring-ai-alibaba-studio/cli/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
**/dist/
**/templates/
build
20 changes: 20 additions & 0 deletions spring-ai-alibaba-studio/cli/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Spring AI Alibaba CLI

## Build
```shell
make
```

## Run

### Windows
```shell
cd build
./spring-ai-alibaba-cli.exe
```

### Linux
```shell
cd build
./spring-ai-alibaba-cli
```
47 changes: 47 additions & 0 deletions spring-ai-alibaba-studio/cli/cmd/chatmodel/chatmodel.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Copyright 2024 the original author or authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package chatmodel

import (
"github.com/spf13/cobra"
)

const chatModelCmdName = "chatmodel"

// chatmodelCmd represents the chatmodel command
var chatmodelCmd = &cobra.Command{
Use: chatModelCmdName,
Short: "Used to manage chat models",
}

func GetChatModelCmd() *cobra.Command {
return chatmodelCmd
}

func init() {
chatmodelCmd.AddCommand(getCmd)
chatmodelCmd.AddCommand(listCmd)
chatmodelCmd.AddCommand(runCmd)

// Here you will define your flags and configuration settings.

// Cobra supports Persistent Flags which will work for this command
// and all subcommands, e.g.:
// chatmodelCmd.PersistentFlags().String("foo", "", "A help for foo")

// Cobra supports local flags which will only run when this command
// is called directly, e.g.:
// chatmodelCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}
58 changes: 58 additions & 0 deletions spring-ai-alibaba-studio/cli/cmd/chatmodel/get.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// Copyright 2024 the original author or authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package chatmodel

import (
"fmt"
"strings"

"github.com/alibaba/spring-ai-alibaba/pkg/constant"
"github.com/alibaba/spring-ai-alibaba/pkg/handler"
"github.com/alibaba/spring-ai-alibaba/pkg/util/printer"
"github.com/spf13/cobra"
)

// getCmd represents the list command
var getCmd = &cobra.Command{
Use: "get modelName...",
Short: "Get chat model detail by model name",
Long: `Get chat model detail by model name

Arguments:
[modelName] Name of the chat models to get details for (required)
`,
Example: fmt.Sprintf(` # Get details of the chat model named "model1"
%s %s get model1
# Get details of the chat model named "model1" and "model2"
%s %s get model1 model2
`, constant.RootCmdName, chatModelCmdName, constant.RootCmdName, chatModelCmdName),
Args: cobra.MinimumNArgs(1),
Run: func(cmd *cobra.Command, args []string) {
handler.NewChatModelHandlerManager().ChatModelGetHandler(cmd, args)
},
}

func init() {
// Here you will define your flags and configuration settings.

// Cobra supports Persistent Flags which will work for this command
// and all subcommands, e.g.:
// listCmd.PersistentFlags().String("foo", "", "A help for foo")

// Cobra supports local flags which will only run when this command
// is called directly, e.g.:
// listCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
getCmd.Flags().StringP(constant.OutputFlag, "o", string(printer.YamlPrinterKind), fmt.Sprintf("Output format supported values: %s", strings.Join(printer.PrinterDetailKindsAsString(), ", ")))
}
50 changes: 50 additions & 0 deletions spring-ai-alibaba-studio/cli/cmd/chatmodel/list.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Copyright 2024 the original author or authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package chatmodel

import (
"fmt"

"github.com/alibaba/spring-ai-alibaba/pkg/constant"
"github.com/alibaba/spring-ai-alibaba/pkg/handler"
"github.com/spf13/cobra"
)

// listCmd represents the list command
var listCmd = &cobra.Command{
Use: "list",
Short: "List all available chat models",
Long: "List all available chat models",
Example: fmt.Sprintf(` # List all available chat models
%s %s list
# List all available chat models in JSON format
%s %s list -o json
`, constant.RootCmdName, chatModelCmdName, constant.RootCmdName, chatModelCmdName),
Run: func(cmd *cobra.Command, args []string) {
handler.NewChatModelHandlerManager().ChatModelListHandler(cmd, args)
},
}

func init() {
// Here you will define your flags and configuration settings.

// Cobra supports Persistent Flags which will work for this command
// and all subcommands, e.g.:
// listCmd.PersistentFlags().String("foo", "", "A help for foo")

// Cobra supports local flags which will only run when this command
// is called directly, e.g.:
// listCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}
60 changes: 60 additions & 0 deletions spring-ai-alibaba-studio/cli/cmd/chatmodel/run.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// Copyright 2024 the original author or authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package chatmodel

import (
"fmt"
"strings"

"github.com/alibaba/spring-ai-alibaba/pkg/constant"
"github.com/alibaba/spring-ai-alibaba/pkg/handler"
"github.com/alibaba/spring-ai-alibaba/pkg/util/printer"
"github.com/spf13/cobra"
)

// runCmd represents the run command
var runCmd = &cobra.Command{
Use: "run",
Short: "Run a chat model with the given input",
Long: `Run a chat model with the given input
Arguments:
[modelName] Name of the chat model to run (required)
[input] Input text to run the chat model with (required)
`,
Example: fmt.Sprintf(` # Run the chat model named "model1" with input "hello"
%s %s run model1 hello
# Run the chat model named "model1" with input "a longer input" and additional prompt message
%s %s run model1 "a longer input" -p "additional prompt message"`, constant.RootCmdName, chatModelCmdName, constant.RootCmdName, chatModelCmdName),
Args: cobra.MinimumNArgs(2),
Run: func(cmd *cobra.Command, args []string) {
handler.NewChatModelHandlerManager().ChatModelRunHandler(cmd, args)
},
}

func init() {
// Here you will define your flags and configuration settings.

// Cobra supports Persistent Flags which will work for this command
// and all subcommands, e.g.:
// runCmd.PersistentFlags().String("foo", "", "A help for foo")

// Cobra supports local flags which will only run when this command
// is called directly, e.g.:
// runCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
runCmd.Flags().StringP(constant.PromptFlag, "p", "", "additional prompt message for chat model running")
runCmd.Flags().CountP(constant.VerboseFlag, "v", "verbose output level (use -v, -vv for higher verbosity)")
runCmd.Flags().StringP(constant.OutputFlag, "o", string(printer.JsonPrinterKind), fmt.Sprintf("Output format supported values: %s", strings.Join(printer.PrinterDetailKindsAsString(), ", ")))
runCmd.Flags().StringP(constant.FileFlag, "f", "./test.jpg", "file name to save the image generate output")
}
35 changes: 35 additions & 0 deletions spring-ai-alibaba-studio/cli/cmd/init.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright 2024 the original author or authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package cmd

import (
"github.com/alibaba/spring-ai-alibaba/pkg/handler"
"github.com/spf13/cobra"
)

var initCmd = &cobra.Command{
Use: "init",
Short: "Initialize a new Spring AI Alibaba project",
Run: func(cmd *cobra.Command, args []string) {
handler.InitHandler(cmd, args)
},
}

func init() {
rootCmd.AddCommand(initCmd)

initCmd.Flags().StringP("name", "n", "", "Project name")
initCmd.MarkFlagRequired("name")
}
111 changes: 111 additions & 0 deletions spring-ai-alibaba-studio/cli/cmd/root.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
// Copyright 2024 the original author or authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package cmd

import (
"fmt"
"os"
"strings"

"github.com/alibaba/spring-ai-alibaba/cmd/chatmodel"
"github.com/alibaba/spring-ai-alibaba/cmd/ui"
"github.com/alibaba/spring-ai-alibaba/pkg/api"
"github.com/alibaba/spring-ai-alibaba/pkg/constant"
"github.com/alibaba/spring-ai-alibaba/pkg/util/printer"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)

const (
defaultConfigFileName = ".spring-ai-alibaba"
defaultConfigFileExt = "json"
)

var cfgFile string

// rootCmd represents the base command when called without any subcommands
var rootCmd = &cobra.Command{
Use: constant.RootCmdName,
Short: "Command line interface for Spring AI Alibaba Studio",
Long: "\nCommand line interface for Spring AI Alibaba Studio\n" + constant.ASCIILOGO,
// Uncomment the following line if your bare application
// has an action associated with it:
// Run: func(cmd *cobra.Command, args []string) { },
Run: func(cmd *cobra.Command, args []string) {
// Check if the version flag is set
if version, _ := cmd.Flags().GetBool(constant.VersionFlag); version {
fmt.Println(constant.Version)
return
}
// if not
cmd.Help()
},
}

// Execute adds all child commands to the root command and sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() {
err := rootCmd.Execute()
if err != nil {
os.Exit(1)
}
}

func init() {
cobra.OnInitialize(initConfig)

// Here you will define your flags and configuration settings.
// Cobra supports persistent flags, which, if defined here,
// will be global for your application.

rootCmd.PersistentFlags().StringVarP(&cfgFile, constant.ConfigFlag, "c", "", fmt.Sprintf("Config file path (default $HOME/%s.%s)", defaultConfigFileName, defaultConfigFileExt))
rootCmd.PersistentFlags().StringP(constant.BaseURLFlag, "u", api.DefaultBaseURL, "Base URL for the Spring AI Alibaba Studio server") // order: command flag > env var > config file
rootCmd.PersistentFlags().StringP(constant.OutputFlag, "o", string(printer.TablePrinterKind), fmt.Sprintf("Output format supported values: %v", strings.Join(printer.PrinterKindsAsString(), ", ")))

rootCmd.Flags().BoolP(constant.VersionFlag, "v", false, "Print the version number of Spring AI Alibaba Studio")

// add subcommands
rootCmd.AddCommand(chatmodel.GetChatModelCmd())
rootCmd.AddCommand(ui.GetUICmd())
}

// initConfig reads in config file and ENV variables if set.
func initConfig() {
if cfgFile != "" {
// Use config file from the flag.
viper.SetConfigFile(cfgFile)
} else {
// Find home directory.
home, err := os.UserHomeDir()
cobra.CheckErr(err)

viper.AddConfigPath(home)
viper.SetConfigType(defaultConfigFileExt)
viper.SetConfigName(defaultConfigFileName)
}

// If a config file is found, read it in.
if err := viper.ReadInConfig(); err != nil {
// Check if the error is because the config file was not found
if _, ok := err.(viper.ConfigFileNotFoundError); !ok {
// Config file was found but another error was produced
fmt.Fprintln(os.Stderr, "Failed loading config file:", viper.ConfigFileUsed(), err)
os.Exit(1)
}
}

viper.AutomaticEnv() // read in environment variables that match
viper.BindPFlag(constant.BaseURLFlag, rootCmd.PersistentFlags().Lookup(constant.BaseURLFlag))
}
Loading