yao/aigc/aigc.go
Max 7bee60c67c refactor: Update AI connector handling and add support for Moapi models
The code changes in `aigc.go` and `types.go` refactor the AI connector handling in the `DSL` struct. The `Connector` field now accepts an optional `moapi` prefix, allowing for the selection of Moapi models. If the `Connector` field starts with `moapi`, the code initializes a new Moapi instance with the specified model. Additionally, the `Connector` field is now marked as `omitempty` in the `types.go` file.

This update improves the flexibility of the AI connector configuration and enables the use of Moapi models in the AI system.
2024-06-15 15:57:36 +08:00

123 lines
2.6 KiB
Go

package aigc
import (
"fmt"
"strings"
jsoniter "github.com/json-iterator/go"
"github.com/yaoapp/gou/connector"
"github.com/yaoapp/gou/process"
"github.com/yaoapp/kun/exception"
"github.com/yaoapp/yao/openai"
)
// Autopilots the loaded autopilots
var Autopilots = []string{}
// AIGCs the loaded AIGCs
var AIGCs = map[string]*DSL{}
// Select select the AIGC
func Select(id string) (*DSL, error) {
if AIGCs[id] == nil {
return nil, fmt.Errorf("aigc %s not found", id)
}
return AIGCs[id], nil
}
// Call the AIGC
func (ai *DSL) Call(content string, user string, option map[string]interface{}) (interface{}, *exception.Exception) {
messages := []map[string]interface{}{}
for _, prompt := range ai.Prompts {
message := map[string]interface{}{"role": prompt.Role, "content": prompt.Content}
if prompt.Name != "" {
message["name"] = prompt.Name
}
messages = append(messages, message)
}
// add the user message
message := map[string]interface{}{"role": "user", "content": content}
if user != "" {
message["user"] = user
}
messages = append(messages, message)
bytes, err := jsoniter.Marshal(messages)
if err != nil {
return nil, exception.New(err.Error(), 400)
}
token, err := ai.AI.Tiktoken(string(bytes))
if err != nil {
return nil, exception.New(err.Error(), 400)
}
if token > ai.AI.MaxToken() {
return nil, exception.New("token limit exceeded", 400)
}
// call the AI
res, ex := ai.AI.ChatCompletions(messages, option, nil)
if ex != nil {
return nil, ex
}
resText, ex := ai.AI.GetContent(res)
if ex != nil {
return nil, ex
}
if ai.Process == "" {
return resText, nil
}
var param interface{} = resText
if ai.Optional.JSON {
err = jsoniter.Unmarshal([]byte(resText), &param)
if err != nil {
return nil, exception.New("%s parse error: %s", 400, resText, err.Error())
}
}
p, err := process.Of(ai.Process, param)
if err != nil {
return nil, exception.New(err.Error(), 400)
}
resProcess, err := p.Exec()
if err != nil {
return nil, exception.New(err.Error(), 500)
}
return resProcess, nil
}
// NewAI create a new AI
func (ai *DSL) newAI() (AI, error) {
if ai.Connector == "" || strings.HasPrefix(ai.Connector, "moapi") {
model := "gpt-3.5-turbo"
if ai.Connector != "" {
model = strings.TrimPrefix(ai.Connector, "moapi:")
}
mo, err := openai.NewMoapi(model)
if err != nil {
return nil, err
}
return mo, nil
}
conn, err := connector.Select(ai.Connector)
if err != nil {
return nil, err
}
if conn.Is(connector.OPENAI) {
return openai.New(ai.Connector)
}
return nil, fmt.Errorf("%s connector %s not support, should be a openai", ai.ID, ai.Connector)
}