Refactor Neo API assistant message handling and content processing
- Enhanced message generation by introducing NewHistory and NewContent methods for improved handling of message content and history. - Updated the withHistory method to utilize the new NewHistory method, streamlining the addition of historical messages. - Improved the call method to conditionally save message history based on input parameters, enhancing flexibility in message management. - Refactored the String method in the Message struct to better represent message types and properties, improving serialization consistency. These changes enhance the maintainability and robustness of the Neo API assistant, paving the way for improved message handling and content processing.
This commit is contained in:
parent
1eba627e38
commit
1404c549a7
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
|
||||
if saveHistory {
|
||||
msg.AppendTo(contents)
|
||||
}
|
||||
msg.Write(c.Writer)
|
||||
return nil
|
||||
|
||||
case map[string]interface{}:
|
||||
msg := message.New().Map(v)
|
||||
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