Skip to content

Commit

Permalink
feat: add agent template to cli
Browse files Browse the repository at this point in the history
  • Loading branch information
Yeuoly committed Dec 13, 2024
1 parent 922110c commit e91068d
Show file tree
Hide file tree
Showing 11 changed files with 141 additions and 12 deletions.
7 changes: 5 additions & 2 deletions cmd/commandline/plugin/category.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,15 @@ const PLUGIN_GUIDE = `But before starting, you need some basic knowledge about t
` + "\n" + BOLD + `- Tool` + RESET + `: ` + GREEN + `Tool Providers like Google Search, Stable Diffusion, etc. it can be used to perform a specific task.` + RESET + `
` + BOLD + `- Model` + RESET + `: ` + GREEN + `Model Providers like OpenAI, Anthropic, etc. you can use their models to enhance the AI capabilities.` + RESET + `
` + BOLD + `- Endpoint` + RESET + `: ` + GREEN + `Like Service API in Dify and Ingress in Kubernetes, you can extend a http service as an endpoint and control its logics using your own code.` + RESET + `
` + BOLD + `- Agent Strategy` + RESET + `: ` + GREEN + `You can implement your own agent strategy like Function Calling, ReAct, ToT, Cot, etc. anyway you want.` + RESET + `
Based on the ability you want to extend, we have divided the Plugin into three types: ` + BOLD + `Tool` + RESET + `, ` + BOLD + `Model` + RESET + `, and ` + BOLD + `Extension` + RESET + `.
Based on the ability you want to extend, we have divided the Plugin into four types: ` + BOLD + `Tool` + RESET + `, ` + BOLD + `Model` + RESET + `, ` + BOLD + `Extension` + RESET + `, and ` + BOLD + `Agent Strategy` + RESET + `.
` + BOLD + `- Tool` + RESET + `: ` + YELLOW + `It's a tool provider, but not only limited to tools, you can implement an endpoint there, for example, you need both ` + BLUE + `Sending Message` + RESET + YELLOW + ` and ` + BLUE + `Receiving Message` + RESET + YELLOW + ` if you are building a Discord Bot, ` + BOLD + `Tool` + RESET + YELLOW + ` and ` + BOLD + `Endpoint` + RESET + YELLOW + ` are both required.` + RESET + `
` + BOLD + `- Model` + RESET + `: ` + YELLOW + `Just a model provider, extending others is not allowed.` + RESET + `
` + BOLD + `- Extension` + RESET + `: ` + YELLOW + `Other times, you may only need a simple http service to extend the functionalities, ` + BOLD + `Extension` + RESET + YELLOW + ` is the right choice for you.` + RESET + `
` + `
` + BOLD + `- Agent Strategy` + RESET + `: ` + YELLOW + `Implement your own logics here, just by focusing on Agent itself` + RESET + `
What's more, we have provided the template for you, you can choose one of them below:
`

Expand All @@ -37,6 +39,7 @@ type category struct {

var categories = []string{
"tool",
"agent-strategy",
"llm",
"text-embedding",
"rerank",
Expand Down
25 changes: 24 additions & 1 deletion cmd/commandline/plugin/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ func initialize() model {
SUB_MENU_KEY_PROFILE: newProfile(),
SUB_MENU_KEY_LANGUAGE: newLanguage(),
SUB_MENU_KEY_CATEGORY: newCategory(),
SUB_MENU_KEY_PERMISSION: newPermission(),
SUB_MENU_KEY_PERMISSION: newPermission(plugin_entities.PluginPermissionRequirement{}),
}
m.currentSubMenu = SUB_MENU_KEY_PROFILE

Expand Down Expand Up @@ -86,6 +86,25 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
// move the current sub menu to the next one
for i, key := range m.subMenuSeq {
if key == m.currentSubMenu {
// check if the next sub menu is permission
if key == SUB_MENU_KEY_CATEGORY {
// get the type of current category
category := m.subMenus[SUB_MENU_KEY_CATEGORY].(category).Category()
if category == "agent-strategy" {
// update the permission to add tool and model invocation
perm := m.subMenus[SUB_MENU_KEY_PERMISSION].(permission)
perm.UpdatePermission(plugin_entities.PluginPermissionRequirement{
Tool: &plugin_entities.PluginPermissionToolRequirement{
Enabled: true,
},
Model: &plugin_entities.PluginPermissionModelRequirement{
Enabled: true,
LLM: true,
},
})
m.subMenus[SUB_MENU_KEY_PERMISSION] = perm
}
}
m.currentSubMenu = m.subMenuSeq[i+1]
break
}
Expand Down Expand Up @@ -151,6 +170,10 @@ func (m model) createPlugin() {
manifest.Plugins.Endpoints = []string{fmt.Sprintf("group/%s.yaml", manifest.Name)}
}

if categoryString == "agent-strategy" {
manifest.Plugins.AgentStrategies = []string{fmt.Sprintf("provider/%s.yaml", manifest.Name)}
}

manifest.Meta = plugin_entities.PluginMeta{
Version: "0.0.1",
Arch: []constants.Arch{
Expand Down
2 changes: 1 addition & 1 deletion cmd/commandline/plugin/language.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func (l language) Language() constants.Language {

func (l language) View() string {
s := `Select the language you want to use for plugin development, and press ` + GREEN + `Enter` + RESET + ` to continue,
BTW, you need Python 3.10+ to develop the Plugin if you choose Python.
BTW, you need Python 3.12+ to develop the Plugin if you choose Python.
`
for i, language := range languages {
if i == l.cursor {
Expand Down
14 changes: 11 additions & 3 deletions cmd/commandline/plugin/permission.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,10 @@ type permission struct {
storageSizeEditor ti.Model
}

func newPermission() permission {
func newPermission(defaultPermission plugin_entities.PluginPermissionRequirement) permission {
return permission{
cursor: permissionKeySeq[0],
permission: defaultPermission,
storageSizeEditor: ti.New(),
}
}
Expand Down Expand Up @@ -285,6 +286,10 @@ func (p permission) Update(msg tea.Msg) (subMenu, subMenuEvent, tea.Cmd) {
return p, SUB_MENU_EVENT_NONE, nil
}

func (p *permission) UpdatePermission(permission plugin_entities.PluginPermissionRequirement) {
p.permission = permission
}

func (p permission) Init() tea.Cmd {
return nil
}
Expand Down Expand Up @@ -322,11 +327,14 @@ func EditPermission(pluginPath string) {
return
}

if manifest.Resource.Permission == nil {
manifest.Resource.Permission = &plugin_entities.PluginPermissionRequirement{}
}

// create a new permission
m := permissionModel{
permission: newPermission(),
permission: newPermission(*manifest.Resource.Permission),
}
m.permission.permission = *manifest.Resource.Permission

p := tea.NewProgram(m)
if result, err := p.Run(); err != nil {
Expand Down
16 changes: 15 additions & 1 deletion cmd/commandline/plugin/python.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,15 @@ var PYTHON_ENDPOINT_TEMPLATE []byte
//go:embed templates/python/endpoint.yaml
var PYTHON_ENDPOINT_MANIFEST_TEMPLATE []byte

//go:embed templates/python/agent_provider.yaml
var PYTHON_AGENT_PROVIDER_MANIFEST_TEMPLATE []byte

//go:embed templates/python/agent_strategy.yaml
var PYTHON_AGENT_STRATEGY_MANIFEST_TEMPLATE []byte

//go:embed templates/python/agent_strategy.py
var PYTHON_AGENT_STRATEGY_TEMPLATE []byte

//go:embed templates/python/GUIDE.md
var PYTHON_GUIDE []byte

Expand All @@ -102,7 +111,6 @@ func renderTemplate(
"PluginDescription": manifest.Description.EnUS,
"SupportedModelTypes": supported_model_types,
"Version": manifest.Version,
"Date": manifest.CreatedAt,
"Category": manifest.Category(),
}); err != nil {
return "", err
Expand Down Expand Up @@ -203,5 +211,11 @@ func createPythonEnvironment(
}
}

if category == "agent-strategy" {
if err := createPythonAgentStrategy(root, manifest); err != nil {
return err
}
}

return nil
}
31 changes: 31 additions & 0 deletions cmd/commandline/plugin/python_categories.go
Original file line number Diff line number Diff line change
Expand Up @@ -239,3 +239,34 @@ func createPythonModelProvider(root string, manifest *plugin_entities.PluginDecl

return nil
}

func createPythonAgentStrategy(root string, manifest *plugin_entities.PluginDeclaration) error {
agentFileContent, err := renderTemplate(PYTHON_AGENT_PROVIDER_MANIFEST_TEMPLATE, manifest, []string{"agent"})
if err != nil {
return err
}
agentFilePath := filepath.Join(root, "provider", fmt.Sprintf("%s.yaml", manifest.Name))
if err := writeFile(agentFilePath, agentFileContent); err != nil {
return err
}

agentStrategyFileContent, err := renderTemplate(PYTHON_AGENT_STRATEGY_MANIFEST_TEMPLATE, manifest, []string{"agent"})
if err != nil {
return err
}
agentStrategyFilePath := filepath.Join(root, "strategies", fmt.Sprintf("%s.yaml", manifest.Name))
if err := writeFile(agentStrategyFilePath, agentStrategyFileContent); err != nil {
return err
}

agentStrategyPyFileContent, err := renderTemplate(PYTHON_AGENT_STRATEGY_TEMPLATE, manifest, []string{"agent"})
if err != nil {
return err
}
agentStrategyPyFilePath := filepath.Join(root, "strategies", fmt.Sprintf("%s.py", manifest.Name))
if err := writeFile(agentStrategyPyFilePath, agentStrategyPyFileContent); err != nil {
return err
}

return nil
}
1 change: 0 additions & 1 deletion cmd/commandline/plugin/templates/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

**Author:** {{ .Author }}
**Version:** {{ .Version }}
**Date:** {{ .Date }}
**Type:** {{ .Category }}

### Description
Expand Down
13 changes: 13 additions & 0 deletions cmd/commandline/plugin/templates/python/agent_provider.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
identity:
author: {{ .Author }}
name: {{ .PluginName }}
label:
en_US: {{ .PluginName | SnakeToCamel }}
description:
en_US: {{ .PluginName | SnakeToCamel }}
icon: icon.svg
strategies:
- strategies/{{ .PluginName }}.yaml
extra:
python:
source: provider/{{ .PluginName }}.py
11 changes: 11 additions & 0 deletions cmd/commandline/plugin/templates/python/agent_strategy.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from collections.abc import Generator
from typing import Any


from dify_plugin.entities.agent import AgentInvokeMessage
from dify_plugin.interfaces.agent import AgentStrategy


class {{ .PluginName | SnakeToCamel }}AgentStrategy(AgentStrategy):
def _invoke(self, parameters: dict[str, Any]) -> Generator[AgentInvokeMessage]:
pass
26 changes: 26 additions & 0 deletions cmd/commandline/plugin/templates/python/agent_strategy.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
identity:
name: {{ .PluginName }}
author: {{ .Author }}
label:
en_US: {{ .PluginName | SnakeToCamel }}
description:
en_US: {{ .PluginName | SnakeToCamel }}
parameters:
- name: model
type: model-selector
scope: tool-call&llm
required: true
label:
en_US: Model
zh_Hans: 模型
pt_BR: Model
- name: tools
type: array[tools]
required: true
label:
en_US: Tools list
zh_Hans: 工具列表
pt_BR: Tools list
extra:
python:
source: strategies/{{ .PluginName }}.py
7 changes: 4 additions & 3 deletions internal/types/entities/plugin_entities/plugin_declaration.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,9 +132,10 @@ type PluginMeta struct {
}

type PluginExtensions struct {
Tools []string `json:"tools" yaml:"tools,omitempty" validate:"omitempty,dive,max=128"`
Models []string `json:"models" yaml:"models,omitempty" validate:"omitempty,dive,max=128"`
Endpoints []string `json:"endpoints" yaml:"endpoints,omitempty" validate:"omitempty,dive,max=128"`
Tools []string `json:"tools" yaml:"tools,omitempty" validate:"omitempty,dive,max=128"`
Models []string `json:"models" yaml:"models,omitempty" validate:"omitempty,dive,max=128"`
Endpoints []string `json:"endpoints" yaml:"endpoints,omitempty" validate:"omitempty,dive,max=128"`
AgentStrategies []string `json:"agent_strategies" yaml:"agent_strategies,omitempty" validate:"omitempty,dive,max=128"`
}

type PluginDeclarationWithoutAdvancedFields struct {
Expand Down

0 comments on commit e91068d

Please sign in to comment.