Przeglądaj źródła

feat: add model templates

Yeuoly 10 miesięcy temu
rodzic
commit
8eb3c7a0dd

+ 1 - 1
cmd/commandline/cmd/encoder.go

@@ -1,4 +1,4 @@
-package cmd
+package init
 
 import (
 	"bytes"

+ 1 - 1
cmd/commandline/cmd/init.go

@@ -1,4 +1,4 @@
-package cmd
+package init
 
 import (
 	"fmt"

+ 1 - 1
cmd/commandline/cmd/language.go

@@ -1,4 +1,4 @@
-package cmd
+package init
 
 import (
 	"fmt"

+ 1 - 1
cmd/commandline/cmd/permission.go

@@ -1,4 +1,4 @@
-package cmd
+package init
 
 import (
 	"fmt"

+ 1 - 1
cmd/commandline/cmd/profile.go

@@ -1,4 +1,4 @@
-package cmd
+package init
 
 import (
 	"fmt"

+ 1 - 1
cmd/commandline/cmd/python.go

@@ -1,4 +1,4 @@
-package cmd
+package init
 
 import (
 	_ "embed"

+ 1 - 1
cmd/commandline/cmd/submenu.go

@@ -1,4 +1,4 @@
-package cmd
+package init
 
 import tea "github.com/charmbracelet/bubbletea"
 

cmd/commandline/cmd/templates/python/main.py → cmd/commandline/init/templates/python/main.py


cmd/commandline/cmd/templates/python/requirements.txt → cmd/commandline/init/templates/python/requirements.txt


+ 43 - 0
cmd/commandline/model.go

@@ -0,0 +1,43 @@
+package main
+
+import (
+	"github.com/langgenius/dify-plugin-daemon/cmd/commandline/model"
+	"github.com/spf13/cobra"
+)
+
+var (
+	modelTemplatesCommand = &cobra.Command{
+		Use:   "templates [-t provider|model] [-m model_type] [name]",
+		Short: "Templates",
+		Long:  "List all model templates, you can use it to create new model",
+		Run: func(cmd *cobra.Command, args []string) {
+			// get provider or model
+			typ, _ := cmd.Flags().GetString("type")
+			// get model_type
+			model_type, _ := cmd.Flags().GetString("model_type")
+			name := ""
+			if len(args) > 0 {
+				name = args[0]
+			}
+			model.ListTemplates(typ, model_type, name)
+		},
+	}
+
+	newProviderCommand = &cobra.Command{
+		Use:   "provider [template] name",
+		Short: "Provider",
+		Long:  "Using template to create new provider, one plugin only support one provider",
+	}
+
+	newModelCommand = &cobra.Command{
+		Use:   "new [template] name",
+		Short: "Model",
+		Long:  "Using template to create new model, you need to create a provider first",
+	}
+)
+
+func init() {
+	pluginModelCommand.AddCommand(modelTemplatesCommand)
+	pluginModelCommand.AddCommand(newProviderCommand)
+	pluginModelCommand.AddCommand(newModelCommand)
+}

+ 113 - 0
cmd/commandline/model/template.go

@@ -0,0 +1,113 @@
+package model
+
+import (
+	"embed"
+	"fmt"
+	"strings"
+
+	"github.com/langgenius/dify-plugin-daemon/internal/utils/log"
+)
+
+//go:embed templates
+var templates embed.FS
+
+// provider_templates is a map of provider type to the template name
+var provider_templates map[string]string
+
+// model_templates is a map of model type to a map of template name to the template content
+var model_templates map[string]map[string]string
+
+func init() {
+	provider_templates = make(map[string]string)
+	model_templates = make(map[string]map[string]string)
+
+	files, err := templates.ReadDir("templates")
+	if err != nil {
+		log.Error("Failed to read templates: %v", err)
+		return
+	}
+
+	for _, file := range files {
+		if file.IsDir() {
+			continue
+		}
+
+		// get the file name
+		filename := file.Name()
+		// read the file content
+		file_content, err := templates.ReadFile("templates/" + filename)
+		if err != nil {
+			log.Error("Failed to read template: %v", err)
+			continue
+		}
+		filenames := strings.Split(filename, "_")
+		// check the first element is a provider
+		if filenames[0] == "provider" {
+			if len(filenames) != 2 {
+				log.Error("Invalid provider template: %s", filename)
+				continue
+			}
+			provider_templates[filenames[1]] = string(file_content)
+		} else if filenames[0] == "model" {
+			if len(filenames) != 3 {
+				log.Error("Invalid model template: %s", filename)
+				continue
+			}
+			if _, ok := model_templates[filenames[1]]; !ok {
+				model_templates[filenames[1]] = make(map[string]string)
+			}
+
+			model_templates[filenames[1]][filenames[2]] = string(file_content)
+		}
+	}
+}
+
+func ListTemplates(typ string, model_type string, name string) {
+	color_reset := "\033[0m"
+	color_cyan := "\033[36m"
+	color_yellow := "\033[33m"
+	color_green := "\033[32m"
+
+	if typ == "provider" || typ == "" {
+		fmt.Printf("%sProvider Templates:%s\n", color_cyan, color_reset)
+		for template := range provider_templates {
+			if name == "" || strings.Contains(template, name) {
+				fmt.Printf("  %s%s%s\n", color_yellow, template, color_reset)
+			}
+		}
+		fmt.Println()
+	}
+
+	if typ == "model" || typ == "" {
+		fmt.Printf("%sModel Templates:%s\n", color_cyan, color_reset)
+		if model_type == "" {
+			for model_type, templates := range model_templates {
+				fmt.Printf("%s%s:%s\n", color_yellow, model_type, color_reset)
+				for template := range templates {
+					if name == "" || strings.Contains(template, name) {
+						fmt.Printf("  %s%s%s\n", color_green, template, color_reset)
+					}
+				}
+				fmt.Println()
+			}
+		} else {
+			if templates, ok := model_templates[model_type]; ok {
+				fmt.Printf("%s%s:%s\n", color_yellow, model_type, color_reset)
+				for template := range templates {
+					if name == "" || strings.Contains(template, name) {
+						fmt.Printf("  %s%s%s\n", color_green, template, color_reset)
+					}
+				}
+				fmt.Println()
+			}
+		}
+	}
+}
+
+func GetTemplate(typ string, name string) {
+
+}
+
+func CreateFromTemplate(root string, typ string, name string) {
+
+}

+ 18 - 0
cmd/commandline/model/templates/model_llm_default.yaml

@@ -0,0 +1,18 @@
+model: gpt-4
+label:
+  zh_Hans: gpt-4
+  en_US: gpt-4
+model_type: llm
+model_properties:
+  mode: chat
+  context_size: 8192
+parameter_rules:
+  - name: temperature
+    use_template: temperature
+  - name: top_p
+    use_template: top_p
+pricing:
+  input: '0.001'
+  output: '0.002'
+  unit: '0.001'
+  currency: USD

+ 43 - 0
cmd/commandline/model/templates/model_llm_gpt35.yaml

@@ -0,0 +1,43 @@
+model: gpt-3.5-turbo
+label:
+  zh_Hans: gpt-3.5-turbo
+  en_US: gpt-3.5-turbo
+model_type: llm
+features:
+  - multi-tool-call
+  - agent-thought
+  - stream-tool-call
+model_properties:
+  mode: chat
+  context_size: 16385
+parameter_rules:
+  - name: temperature
+    use_template: temperature
+  - name: top_p
+    use_template: top_p
+  - name: presence_penalty
+    use_template: presence_penalty
+  - name: frequency_penalty
+    use_template: frequency_penalty
+  - name: max_tokens
+    use_template: max_tokens
+    default: 512
+    min: 1
+    max: 4096
+  - name: response_format
+    label:
+      zh_Hans: 回复格式
+      en_US: response_format
+    type: string
+    help:
+      zh_Hans: 指定模型必须输出的格式
+      en_US: specifying the format that the model must output
+    required: false
+    options:
+      - text
+      - json_object
+pricing:
+  input: '0.001'
+  output: '0.002'
+  unit: '0.001'
+  currency: USD

+ 56 - 0
cmd/commandline/model/templates/model_llm_gpt4.yaml

@@ -0,0 +1,56 @@
+model: gpt-4
+label:
+  zh_Hans: gpt-4
+  en_US: gpt-4
+model_type: llm
+features:
+  - multi-tool-call
+  - agent-thought
+  - stream-tool-call
+model_properties:
+  mode: chat
+  context_size: 8192
+parameter_rules:
+  - name: temperature
+    use_template: temperature
+  - name: top_p
+    use_template: top_p
+  - name: presence_penalty
+    use_template: presence_penalty
+  - name: frequency_penalty
+    use_template: frequency_penalty
+  - name: max_tokens
+    use_template: max_tokens
+    default: 512
+    min: 1
+    max: 8192
+  - name: seed
+    label:
+      zh_Hans: 种子
+      en_US: Seed
+    type: int
+    help:
+      zh_Hans: 如果指定,模型将尽最大努力进行确定性采样,使得重复的具有相同种子和参数的请求应该返回相同的结果。不能保证确定性,您应该参考 system_fingerprint
+        响应参数来监视变化。
+      en_US: If specified, model will make a best effort to sample deterministically,
+        such that repeated requests with the same seed and parameters should return
+        the same result. Determinism is not guaranteed, and you should refer to the
+        system_fingerprint response parameter to monitor changes in the backend.
+    required: false
+  - name: response_format
+    label:
+      zh_Hans: 回复格式
+      en_US: response_format
+    type: string
+    help:
+      zh_Hans: 指定模型必须输出的格式
+      en_US: specifying the format that the model must output
+    required: false
+    options:
+      - text
+      - json_object
+pricing:
+  input: '0.03'
+  output: '0.06'
+  unit: '0.001'
+  currency: USD

+ 5 - 0
cmd/commandline/model/templates/model_moderation_default.yaml

@@ -0,0 +1,5 @@
+model: default
+model_type: moderation
+model_properties:
+  max_chunks: 32
+  max_characters_per_chunk: 2000

+ 4 - 0
cmd/commandline/model/templates/model_rerank_default.yaml

@@ -0,0 +1,4 @@
+model: default
+model_type: rerank
+model_properties:
+  context_size: 8192

+ 5 - 0
cmd/commandline/model/templates/model_speech2text_default.yaml

@@ -0,0 +1,5 @@
+model: default
+model_type: speech2text
+model_properties:
+  file_upload_limit: 25
+  supported_file_extensions: flac,mp3,mp4,mpeg,mpga,m4a,ogg,wav,webm

+ 9 - 0
cmd/commandline/model/templates/model_textembedding_default.yaml

@@ -0,0 +1,9 @@
+model: default
+model_type: text-embedding
+model_properties:
+  context_size: 8191
+  max_chunks: 32
+pricing:
+  input: '0.00002'
+  unit: '0.001'
+  currency: USD

+ 31 - 0
cmd/commandline/model/templates/model_tts_default.yaml

@@ -0,0 +1,31 @@
+model: default
+model_type: tts
+model_properties:
+  default_voice: 'alloy'
+  voices:
+    - mode: 'alloy'
+      name: 'Alloy'
+      language: ['zh-Hans', 'en-US', 'de-DE', 'fr-FR', 'es-ES', 'it-IT', 'th-TH', 'id-ID']
+    - mode: 'echo'
+      name: 'Echo'
+      language: ['zh-Hans', 'en-US', 'de-DE', 'fr-FR', 'es-ES', 'it-IT', 'th-TH', 'id-ID']
+    - mode: 'fable'
+      name: 'Fable'
+      language: ['zh-Hans', 'en-US', 'de-DE', 'fr-FR', 'es-ES', 'it-IT', 'th-TH', 'id-ID']
+    - mode: 'onyx'
+      name: 'Onyx'
+      language: ['zh-Hans', 'en-US', 'de-DE', 'fr-FR', 'es-ES', 'it-IT', 'th-TH', 'id-ID']
+    - mode: 'nova'
+      name: 'Nova'
+      language: ['zh-Hans', 'en-US', 'de-DE', 'fr-FR', 'es-ES', 'it-IT', 'th-TH', 'id-ID']
+    - mode: 'shimmer'
+      name: 'Shimmer'
+      language: ['zh-Hans', 'en-US', 'de-DE', 'fr-FR', 'es-ES', 'it-IT', 'th-TH', 'id-ID']
+  word_limit: 3500
+  audio_type: 'mp3'
+  max_workers: 5
+pricing:
+  input: '0.015'
+  output: '0'
+  unit: '0.001'
+  currency: USD

+ 91 - 0
cmd/commandline/model/templates/provider_openai.yaml

@@ -0,0 +1,91 @@
+type: model
+provider:
+  provider: openai
+  label:
+    en_US: OpenAI
+  description:
+    en_US: Models provided by OpenAI, such as GPT-3.5-Turbo and GPT-4.
+    zh_Hans: OpenAI 提供的模型,例如 GPT-3.5-Turbo 和 GPT-4。
+  icon_small:
+    en_US: icon_s_en.svg
+  icon_large:
+    en_US: icon_l_en.svg
+  background: "#E5E7EB"
+  help:
+    title:
+      en_US: Get your API Key from OpenAI
+      zh_Hans: 从 OpenAI 获取 API Key
+    url:
+      en_US: https://platform.openai.com/account/api-keys
+  supported_model_types:
+    - llm
+    - text-embedding
+    - speech2text
+    - moderation
+    - tts
+  configurate_methods:
+    - predefined-model
+    - customizable-model
+  model_credential_schema:
+    model:
+      label:
+        en_US: Model Name
+        zh_Hans: 模型名称
+      placeholder:
+        en_US: Enter your model name
+        zh_Hans: 输入模型名称
+    credential_form_schemas:
+      - variable: openai_api_key
+        label:
+          en_US: API Key
+        type: secret-input
+        required: true
+        placeholder:
+          zh_Hans: 在此输入您的 API Key
+          en_US: Enter your API Key
+      - variable: openai_organization
+        label:
+          zh_Hans: 组织 ID
+          en_US: Organization
+        type: text-input
+        required: false
+        placeholder:
+          zh_Hans: 在此输入您的组织 ID
+          en_US: Enter your Organization ID
+      - variable: openai_api_base
+        label:
+          zh_Hans: API Base
+          en_US: API Base
+        type: text-input
+        required: false
+        placeholder:
+          zh_Hans: 在此输入您的 API Base
+          en_US: Enter your API Base
+  provider_credential_schema:
+    credential_form_schemas:
+      - variable: openai_api_key
+        label:
+          en_US: API Key
+        type: secret-input
+        required: true
+        placeholder:
+          zh_Hans: 在此输入您的 API Key
+          en_US: Enter your API Key
+      - variable: openai_organization
+        label:
+          zh_Hans: 组织 ID
+          en_US: Organization
+        type: text-input
+        required: false
+        placeholder:
+          zh_Hans: 在此输入您的组织 ID
+          en_US: Enter your Organization ID
+      - variable: openai_api_base
+        label:
+          zh_Hans: API Base
+          en_US: API Base
+        type: text-input
+        required: false
+        placeholder:
+          zh_Hans: 在此输入您的 API Base, 如:https://api.openai.com
+          en_US: Enter your API Base, e.g. https://api.openai.com

+ 34 - 6
cmd/commandline/plugin.go

@@ -1,7 +1,7 @@
 package main
 
 import (
-	"github.com/langgenius/dify-plugin-daemon/cmd/commandline/cmd"
+	init_pkg "github.com/langgenius/dify-plugin-daemon/cmd/commandline/init"
 	"github.com/spf13/cobra"
 )
 
@@ -11,10 +11,34 @@ var (
 		Short: "Init",
 		Long:  "Init",
 		Run: func(c *cobra.Command, args []string) {
-			cmd.InitPlugin()
+			init_pkg.InitPlugin()
 		},
 	}
 
+	pluginModelCommand = &cobra.Command{
+		Use:   "model",
+		Short: "Model",
+		Long:  "Model management for plugin",
+	}
+
+	pluginToolCommand = &cobra.Command{
+		Use:   "tool",
+		Short: "Tool",
+		Long:  "Tool management for plugin",
+	}
+
+	pluginEndpointCommand = &cobra.Command{
+		Use:   "endpoint",
+		Short: "Endpoint",
+		Long:  "Endpoint management for plugin",
+	}
+
+	pluginPackageCommand = &cobra.Command{
+		Use:   "package",
+		Short: "Package",
+		Long:  "Package plugins",
+	}
+
 	pluginPermissionCommand = &cobra.Command{
 		Use:   "permission",
 		Short: "Permission",
@@ -33,20 +57,24 @@ endpoint				- allow plugin to register endpoint`,
 	}
 
 	pluginPermissionAddCommand = &cobra.Command{
-		Use:   "add",
-		Short: "Add permission to plugin",
+		Use:   "add permission",
+		Short: "",
 		Long:  "Add permission to plugin, you can find the available permission by running `dify plugin permission`",
 	}
 
 	pluginPermissionDropCommand = &cobra.Command{
-		Use:   "drop",
-		Short: "Drop permission from plugin",
+		Use:   "drop permission",
+		Short: "",
 		Long:  "Drop permission from plugin, you can find the available permission by running `dify plugin permission`",
 	}
 )
 
 func init() {
 	pluginCommand.AddCommand(pluginInitCommand)
+	pluginCommand.AddCommand(pluginModelCommand)
+	pluginCommand.AddCommand(pluginToolCommand)
+	pluginCommand.AddCommand(pluginEndpointCommand)
+	pluginCommand.AddCommand(pluginPackageCommand)
 	pluginCommand.AddCommand(pluginPermissionCommand)
 	pluginPermissionCommand.AddCommand(pluginPermissionAddCommand)
 	pluginPermissionCommand.AddCommand(pluginPermissionDropCommand)