Merge pull request #826 from trheyi/main
Refactor Neo API assistant message handling and content processing
This commit is contained in:
commit
a8b82248a2
4 changed files with 121 additions and 15 deletions
|
|
@ -387,7 +387,11 @@ func (ast *Assistant) withHistory(ctx chatctx.Context, input string) ([]chatMess
|
|||
|
||||
// Add history messages
|
||||
for _, h := range history {
|
||||
messages = append(messages, *chatMessage.New().Map(h))
|
||||
msgs, err := chatMessage.NewHistory(h)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
messages = append(messages, msgs...)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -416,6 +420,7 @@ func (ast *Assistant) Chat(ctx context.Context, messages []chatMessage.Message,
|
|||
}
|
||||
|
||||
func (ast *Assistant) requestMessages(ctx context.Context, messages []chatMessage.Message) ([]map[string]interface{}, error) {
|
||||
|
||||
newMessages := []map[string]interface{}{}
|
||||
length := len(messages)
|
||||
|
||||
|
|
@ -425,7 +430,7 @@ func (ast *Assistant) requestMessages(ctx context.Context, messages []chatMessag
|
|||
return nil, fmt.Errorf("role must be string")
|
||||
}
|
||||
|
||||
content := message.Text
|
||||
content := message.String()
|
||||
if content == "" {
|
||||
return nil, fmt.Errorf("content must be string")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -276,6 +276,12 @@ func (ast *Assistant) call(ctx context.Context, method string, c *gin.Context, c
|
|||
return bridge.JsException(info.Context(), err.Error())
|
||||
}
|
||||
|
||||
// Save history by default
|
||||
saveHistory := true
|
||||
if len(args) > 1 && args[1].IsBoolean() {
|
||||
saveHistory = args[1].Boolean()
|
||||
}
|
||||
|
||||
switch v := input.(type) {
|
||||
case string:
|
||||
// Check if the message is json
|
||||
|
|
@ -285,13 +291,17 @@ func (ast *Assistant) call(ctx context.Context, method string, c *gin.Context, c
|
|||
}
|
||||
|
||||
// Append the message to the contents
|
||||
msg.AppendTo(contents)
|
||||
if saveHistory {
|
||||
msg.AppendTo(contents)
|
||||
}
|
||||
msg.Write(c.Writer)
|
||||
return nil
|
||||
|
||||
case map[string]interface{}:
|
||||
msg := message.New().Map(v)
|
||||
msg.AppendTo(contents)
|
||||
if saveHistory {
|
||||
msg.AppendTo(contents)
|
||||
}
|
||||
msg.Write(c.Writer)
|
||||
return nil
|
||||
|
||||
|
|
|
|||
|
|
@ -65,6 +65,73 @@ func New() *Message {
|
|||
return &Message{Actions: []Action{}, Props: map[string]interface{}{}}
|
||||
}
|
||||
|
||||
// NewHistory create a new message from history
|
||||
func NewHistory(history map[string]interface{}) ([]Message, error) {
|
||||
if history == nil {
|
||||
return []Message{}, nil
|
||||
}
|
||||
|
||||
var copy map[string]interface{} = map[string]interface{}{}
|
||||
for key, value := range history {
|
||||
if key != "content" {
|
||||
copy[key] = value
|
||||
}
|
||||
}
|
||||
|
||||
globalMessage := New().Map(copy)
|
||||
messages := []Message{}
|
||||
if content, ok := history["content"].(string); ok {
|
||||
if strings.HasPrefix(content, "{") && strings.HasSuffix(content, "}") {
|
||||
var msg Message = *globalMessage
|
||||
if err := jsoniter.UnmarshalFromString(content, &msg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
messages = append(messages, msg)
|
||||
} else if strings.HasPrefix(content, "[") && strings.HasSuffix(content, "]") {
|
||||
var msgs []Message
|
||||
if err := jsoniter.UnmarshalFromString(content, &msgs); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, msg := range msgs {
|
||||
msg.AssistantID = globalMessage.AssistantID
|
||||
msg.AssistantName = globalMessage.AssistantName
|
||||
msg.AssistantAvatar = globalMessage.AssistantAvatar
|
||||
msg.Role = globalMessage.Role
|
||||
msg.Name = globalMessage.Name
|
||||
msg.Mentions = globalMessage.Mentions
|
||||
messages = append(messages, msg)
|
||||
}
|
||||
} else {
|
||||
messages = append(messages, Message{Text: content})
|
||||
}
|
||||
}
|
||||
|
||||
return messages, nil
|
||||
}
|
||||
|
||||
// NewContent create a new message from content
|
||||
func NewContent(content string) ([]Message, error) {
|
||||
messages := []Message{}
|
||||
if strings.HasPrefix(content, "{") && strings.HasSuffix(content, "}") {
|
||||
var msg Message
|
||||
if err := jsoniter.UnmarshalFromString(content, &msg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
messages = append(messages, msg)
|
||||
} else if strings.HasPrefix(content, "[") && strings.HasSuffix(content, "]") {
|
||||
var msgs []Message
|
||||
if err := jsoniter.UnmarshalFromString(content, &msgs); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, msg := range msgs {
|
||||
messages = append(messages, msg)
|
||||
}
|
||||
} else {
|
||||
messages = append(messages, Message{Text: content})
|
||||
}
|
||||
return messages, nil
|
||||
}
|
||||
|
||||
// NewString create a new message from string
|
||||
func NewString(content string) (*Message, error) {
|
||||
if strings.HasPrefix(content, "{") && strings.HasSuffix(content, "}") {
|
||||
|
|
@ -86,10 +153,6 @@ func NewOpenAI(data []byte) *Message {
|
|||
msg := New()
|
||||
text := string(data)
|
||||
data = []byte(strings.TrimPrefix(text, "data: "))
|
||||
// fmt.Println("--------------------------------")
|
||||
// fmt.Println(string(data))
|
||||
// fmt.Println("--------------------------------")
|
||||
|
||||
switch {
|
||||
|
||||
case strings.Contains(text, `"delta":{`) && strings.Contains(text, `"tool_calls"`):
|
||||
|
|
@ -138,10 +201,18 @@ func NewOpenAI(data []byte) *Message {
|
|||
|
||||
// String returns the string representation
|
||||
func (m *Message) String() string {
|
||||
if m.Text != "" {
|
||||
return m.Text
|
||||
typ := m.Type
|
||||
if typ == "" {
|
||||
typ = "text"
|
||||
}
|
||||
|
||||
switch typ {
|
||||
case "text":
|
||||
return m.Text
|
||||
default:
|
||||
raw, _ := jsoniter.MarshalToString(map[string]interface{}{"type": m.Type, "props": m.Props})
|
||||
return raw
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// SetText set the text
|
||||
|
|
@ -222,7 +293,7 @@ func (m *Message) AppendTo(contents *Contents) *Message {
|
|||
contents.AppendFunction([]byte(m.Text))
|
||||
return m
|
||||
|
||||
case "loading":
|
||||
case "loading", "error": // Ignore loading and error messages
|
||||
return m
|
||||
|
||||
default:
|
||||
|
|
@ -307,6 +378,11 @@ func (m *Message) Map(msg map[string]interface{}) *Message {
|
|||
|
||||
if assistantID, ok := msg["assistant_id"].(string); ok {
|
||||
m.AssistantID = assistantID
|
||||
|
||||
// Set name
|
||||
if m.Role == "assistant" {
|
||||
m.Name = m.AssistantID
|
||||
}
|
||||
}
|
||||
|
||||
if assistantName, ok := msg["assistant_name"].(string); ok {
|
||||
|
|
|
|||
21
neo/neo.go
21
neo/neo.go
|
|
@ -104,10 +104,25 @@ func (neo *DSL) GenerateWithAI(ctx chatctx.Context, input string, messageType st
|
|||
|
||||
// Chat with AI in background
|
||||
go func() {
|
||||
msgList := make([]message.Message, len(messages))
|
||||
for i, msg := range messages {
|
||||
msgList[i] = *message.New().Map(msg)
|
||||
msgList := []message.Message{}
|
||||
for _, vv := range messages {
|
||||
msg := message.New().Map(vv)
|
||||
if content, ok := vv["content"].(string); ok {
|
||||
msgs, err := message.NewContent(content)
|
||||
if err == nil {
|
||||
for _, v := range msgs {
|
||||
v.AssistantID = msg.AssistantID
|
||||
v.AssistantName = msg.AssistantName
|
||||
v.AssistantAvatar = msg.AssistantAvatar
|
||||
v.Role = msg.Role
|
||||
v.Name = msg.Name
|
||||
v.Mentions = msg.Mentions
|
||||
msgList = append(msgList, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
err := ast.Chat(c.Request.Context(), msgList, neo.Option, func(data []byte) int {
|
||||
select {
|
||||
case <-clientBreak:
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue