Refactor conversation management and migrate to store-based architecture in Neo API
- Replaced the conversation handling logic with a new store-based approach, enhancing data management and retrieval capabilities. - Updated all relevant methods to utilize the new store interface, including GetChats, GetChat, GetHistory, and SaveAssistant, ensuring consistent functionality across the API. - Removed deprecated conversation-related files and structures, streamlining the codebase and improving maintainability. - Enhanced the AssistantFilter and AssistantResponse types to support the new store architecture, improving filtering and pagination capabilities. - Updated tests to cover the new store-based methods and ensure robust functionality across different storage backends.
This commit is contained in:
parent
238347c834
commit
e530ccc1cd
12 changed files with 222 additions and 214 deletions
32
neo/api.go
32
neo/api.go
|
|
@ -15,8 +15,8 @@ import (
|
||||||
"github.com/yaoapp/gou/connector"
|
"github.com/yaoapp/gou/connector"
|
||||||
"github.com/yaoapp/gou/process"
|
"github.com/yaoapp/gou/process"
|
||||||
"github.com/yaoapp/yao/helper"
|
"github.com/yaoapp/yao/helper"
|
||||||
"github.com/yaoapp/yao/neo/conversation"
|
|
||||||
"github.com/yaoapp/yao/neo/message"
|
"github.com/yaoapp/yao/neo/message"
|
||||||
|
"github.com/yaoapp/yao/neo/store"
|
||||||
)
|
)
|
||||||
|
|
||||||
// API registers the Neo API endpoints
|
// API registers the Neo API endpoints
|
||||||
|
|
@ -227,7 +227,7 @@ func (neo *DSL) handleChatList(c *gin.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create filter from query parameters
|
// Create filter from query parameters
|
||||||
filter := conversation.ChatFilter{
|
filter := store.ChatFilter{
|
||||||
Keywords: c.Query("keywords"),
|
Keywords: c.Query("keywords"),
|
||||||
Order: c.Query("order"),
|
Order: c.Query("order"),
|
||||||
}
|
}
|
||||||
|
|
@ -245,7 +245,7 @@ func (neo *DSL) handleChatList(c *gin.Context) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
response, err := neo.Conversation.GetChats(sid, filter)
|
response, err := neo.Store.GetChats(sid, filter)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(500, gin.H{"message": err.Error(), "code": 500})
|
c.JSON(500, gin.H{"message": err.Error(), "code": 500})
|
||||||
c.Done()
|
c.Done()
|
||||||
|
|
@ -266,7 +266,7 @@ func (neo *DSL) handleChatHistory(c *gin.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
cid := c.Query("chat_id")
|
cid := c.Query("chat_id")
|
||||||
history, err := neo.Conversation.GetHistory(sid, cid)
|
history, err := neo.Store.GetHistory(sid, cid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(500, gin.H{"message": err.Error(), "code": 500})
|
c.JSON(500, gin.H{"message": err.Error(), "code": 500})
|
||||||
c.Done()
|
c.Done()
|
||||||
|
|
@ -450,7 +450,7 @@ func (neo *DSL) handleChatDetail(c *gin.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
chat, err := neo.Conversation.GetChat(sid, chatID)
|
chat, err := neo.Store.GetChat(sid, chatID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(500, gin.H{"message": err.Error(), "code": 500})
|
c.JSON(500, gin.H{"message": err.Error(), "code": 500})
|
||||||
c.Done()
|
c.Done()
|
||||||
|
|
@ -475,14 +475,14 @@ func (neo *DSL) handleMentions(c *gin.Context) {
|
||||||
mentionable := true
|
mentionable := true
|
||||||
|
|
||||||
// Query mentionable assistants
|
// Query mentionable assistants
|
||||||
filter := conversation.AssistantFilter{
|
filter := store.AssistantFilter{
|
||||||
Keywords: keywords,
|
Keywords: keywords,
|
||||||
Mentionable: &mentionable,
|
Mentionable: &mentionable,
|
||||||
Page: 1,
|
Page: 1,
|
||||||
PageSize: 20,
|
PageSize: 20,
|
||||||
}
|
}
|
||||||
|
|
||||||
response, err := neo.Conversation.GetAssistants(filter)
|
response, err := neo.Store.GetAssistants(filter)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(500, gin.H{"message": err.Error(), "code": 500})
|
c.JSON(500, gin.H{"message": err.Error(), "code": 500})
|
||||||
c.Done()
|
c.Done()
|
||||||
|
|
@ -552,7 +552,7 @@ func (neo *DSL) handleChatUpdate(c *gin.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err := neo.Conversation.UpdateChatTitle(sid, chatID, body.Title)
|
err := neo.Store.UpdateChatTitle(sid, chatID, body.Title)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(500, gin.H{"message": err.Error(), "code": 500})
|
c.JSON(500, gin.H{"message": err.Error(), "code": 500})
|
||||||
c.Done()
|
c.Done()
|
||||||
|
|
@ -579,7 +579,7 @@ func (neo *DSL) handleChatDelete(c *gin.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err := neo.Conversation.DeleteChat(sid, chatID)
|
err := neo.Store.DeleteChat(sid, chatID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(500, gin.H{"message": err.Error(), "code": 500})
|
c.JSON(500, gin.H{"message": err.Error(), "code": 500})
|
||||||
c.Done()
|
c.Done()
|
||||||
|
|
@ -599,7 +599,7 @@ func (neo *DSL) handleChatsDeleteAll(c *gin.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err := neo.Conversation.DeleteAllChats(sid)
|
err := neo.Store.DeleteAllChats(sid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(500, gin.H{"message": err.Error(), "code": 500})
|
c.JSON(500, gin.H{"message": err.Error(), "code": 500})
|
||||||
c.Done()
|
c.Done()
|
||||||
|
|
@ -840,7 +840,7 @@ func (neo *DSL) handleGenerateCustom(c *gin.Context) {
|
||||||
// handleAssistantList handles listing assistants
|
// handleAssistantList handles listing assistants
|
||||||
func (neo *DSL) handleAssistantList(c *gin.Context) {
|
func (neo *DSL) handleAssistantList(c *gin.Context) {
|
||||||
// Parse filter parameters
|
// Parse filter parameters
|
||||||
filter := conversation.AssistantFilter{
|
filter := store.AssistantFilter{
|
||||||
Page: 1,
|
Page: 1,
|
||||||
PageSize: 20,
|
PageSize: 20,
|
||||||
}
|
}
|
||||||
|
|
@ -894,7 +894,7 @@ func (neo *DSL) handleAssistantList(c *gin.Context) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
response, err := neo.Conversation.GetAssistants(filter)
|
response, err := neo.Store.GetAssistants(filter)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(500, gin.H{"message": err.Error(), "code": 500})
|
c.JSON(500, gin.H{"message": err.Error(), "code": 500})
|
||||||
c.Done()
|
c.Done()
|
||||||
|
|
@ -930,13 +930,13 @@ func (neo *DSL) handleAssistantDetail(c *gin.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
filter := conversation.AssistantFilter{
|
filter := store.AssistantFilter{
|
||||||
AssistantID: assistantID,
|
AssistantID: assistantID,
|
||||||
Page: 1,
|
Page: 1,
|
||||||
PageSize: 1,
|
PageSize: 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
response, err := neo.Conversation.GetAssistants(filter)
|
response, err := neo.Store.GetAssistants(filter)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(500, gin.H{"message": err.Error(), "code": 500})
|
c.JSON(500, gin.H{"message": err.Error(), "code": 500})
|
||||||
c.Done()
|
c.Done()
|
||||||
|
|
@ -962,7 +962,7 @@ func (neo *DSL) handleAssistantSave(c *gin.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
id, err := neo.Conversation.SaveAssistant(assistant)
|
id, err := neo.Store.SaveAssistant(assistant)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(500, gin.H{"message": err.Error(), "code": 500})
|
c.JSON(500, gin.H{"message": err.Error(), "code": 500})
|
||||||
c.Done()
|
c.Done()
|
||||||
|
|
@ -987,7 +987,7 @@ func (neo *DSL) handleAssistantDelete(c *gin.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err := neo.Conversation.DeleteAssistant(assistantID)
|
err := neo.Store.DeleteAssistant(assistantID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(500, gin.H{"message": err.Error(), "code": 500})
|
c.JSON(500, gin.H{"message": err.Error(), "code": 500})
|
||||||
c.Done()
|
c.Done()
|
||||||
|
|
|
||||||
26
neo/assistant/assistant.go
Normal file
26
neo/assistant/assistant.go
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
package assistant
|
||||||
|
|
||||||
|
import "github.com/yaoapp/yao/neo/store"
|
||||||
|
|
||||||
|
// loadedAssistant the loaded assistant
|
||||||
|
var loadedAssistant = map[string]*Assistant{}
|
||||||
|
|
||||||
|
// LoadLocal create a new assistant from local
|
||||||
|
func LoadLocal(path string) *Assistant {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadZip create a new assistant from zip
|
||||||
|
func LoadZip(zip string) *Assistant {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadRemote create a new assistant from remote
|
||||||
|
func LoadRemote(url string) *Assistant {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadStore create a new assistant from store
|
||||||
|
func LoadStore(store store.Store) *Assistant {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
12
neo/load.go
12
neo/load.go
|
|
@ -9,7 +9,7 @@ import (
|
||||||
"github.com/yaoapp/gou/application"
|
"github.com/yaoapp/gou/application"
|
||||||
"github.com/yaoapp/yao/config"
|
"github.com/yaoapp/yao/config"
|
||||||
"github.com/yaoapp/yao/neo/assistant"
|
"github.com/yaoapp/yao/neo/assistant"
|
||||||
"github.com/yaoapp/yao/neo/conversation"
|
"github.com/yaoapp/yao/neo/store"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Neo the neo AI assistant
|
// Neo the neo AI assistant
|
||||||
|
|
@ -23,7 +23,7 @@ func Load(cfg config.Config) error {
|
||||||
Prompts: []assistant.Prompt{},
|
Prompts: []assistant.Prompt{},
|
||||||
Option: map[string]interface{}{},
|
Option: map[string]interface{}{},
|
||||||
Allows: []string{},
|
Allows: []string{},
|
||||||
ConversationSetting: conversation.Setting{
|
StoreSetting: store.Setting{
|
||||||
Table: "yao_neo_conversation",
|
Table: "yao_neo_conversation",
|
||||||
Connector: "default",
|
Connector: "default",
|
||||||
},
|
},
|
||||||
|
|
@ -39,14 +39,14 @@ func Load(cfg config.Config) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if setting.ConversationSetting.MaxSize == 0 {
|
if setting.StoreSetting.MaxSize == 0 {
|
||||||
setting.ConversationSetting.MaxSize = 100
|
setting.StoreSetting.MaxSize = 100
|
||||||
}
|
}
|
||||||
|
|
||||||
Neo = &setting
|
Neo = &setting
|
||||||
|
|
||||||
// Conversation Setting
|
// Store Setting
|
||||||
err = Neo.createConversation()
|
err = Neo.createStore()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
26
neo/neo.go
26
neo/neo.go
|
|
@ -13,8 +13,8 @@ import (
|
||||||
"github.com/yaoapp/yao/neo/assistant"
|
"github.com/yaoapp/yao/neo/assistant"
|
||||||
"github.com/yaoapp/yao/neo/assistant/local"
|
"github.com/yaoapp/yao/neo/assistant/local"
|
||||||
"github.com/yaoapp/yao/neo/assistant/openai"
|
"github.com/yaoapp/yao/neo/assistant/openai"
|
||||||
"github.com/yaoapp/yao/neo/conversation"
|
|
||||||
"github.com/yaoapp/yao/neo/message"
|
"github.com/yaoapp/yao/neo/message"
|
||||||
|
"github.com/yaoapp/yao/neo/store"
|
||||||
"github.com/yaoapp/yao/share"
|
"github.com/yaoapp/yao/share"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -473,7 +473,7 @@ func (neo *DSL) createDefaultAssistant() (assistant.API, error) {
|
||||||
// chatMessages get the chat messages
|
// chatMessages get the chat messages
|
||||||
func (neo *DSL) chatMessages(ctx Context, content ...string) ([]map[string]interface{}, error) {
|
func (neo *DSL) chatMessages(ctx Context, content ...string) ([]map[string]interface{}, error) {
|
||||||
|
|
||||||
history, err := neo.Conversation.GetHistory(ctx.Sid, ctx.ChatID)
|
history, err := neo.Store.GetHistory(ctx.Sid, ctx.ChatID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -493,7 +493,7 @@ func (neo *DSL) chatMessages(ctx Context, content ...string) ([]map[string]inter
|
||||||
func (neo *DSL) saveHistory(sid string, chatID string, content []byte, messages []map[string]interface{}) {
|
func (neo *DSL) saveHistory(sid string, chatID string, content []byte, messages []map[string]interface{}) {
|
||||||
|
|
||||||
if len(content) > 0 && sid != "" && len(messages) > 0 {
|
if len(content) > 0 && sid != "" && len(messages) > 0 {
|
||||||
err := neo.Conversation.SaveHistory(
|
err := neo.Store.SaveHistory(
|
||||||
sid,
|
sid,
|
||||||
[]map[string]interface{}{
|
[]map[string]interface{}{
|
||||||
{"role": "user", "content": messages[len(messages)-1]["content"], "name": sid},
|
{"role": "user", "content": messages[len(messages)-1]["content"], "name": sid},
|
||||||
|
|
@ -509,39 +509,39 @@ func (neo *DSL) saveHistory(sid string, chatID string, content []byte, messages
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// createConversation create a new conversation
|
// createStore create a new store
|
||||||
func (neo *DSL) createConversation() error {
|
func (neo *DSL) createStore() error {
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
if neo.ConversationSetting.Connector == "default" || neo.ConversationSetting.Connector == "" {
|
if neo.StoreSetting.Connector == "default" || neo.StoreSetting.Connector == "" {
|
||||||
neo.Conversation, err = conversation.NewXun(neo.ConversationSetting)
|
neo.Store, err = store.NewXun(neo.StoreSetting)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// other connector
|
// other connector
|
||||||
conn, err := connector.Select(neo.ConversationSetting.Connector)
|
conn, err := connector.Select(neo.StoreSetting.Connector)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if conn.Is(connector.DATABASE) {
|
if conn.Is(connector.DATABASE) {
|
||||||
neo.Conversation, err = conversation.NewXun(neo.ConversationSetting)
|
neo.Store, err = store.NewXun(neo.StoreSetting)
|
||||||
return err
|
return err
|
||||||
|
|
||||||
} else if conn.Is(connector.REDIS) {
|
} else if conn.Is(connector.REDIS) {
|
||||||
neo.Conversation = conversation.NewRedis()
|
neo.Store = store.NewRedis()
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
} else if conn.Is(connector.MONGO) {
|
} else if conn.Is(connector.MONGO) {
|
||||||
neo.Conversation = conversation.NewMongo()
|
neo.Store = store.NewMongo()
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
} else if conn.Is(connector.WEAVIATE) {
|
} else if conn.Is(connector.WEAVIATE) {
|
||||||
neo.Conversation = conversation.NewWeaviate()
|
neo.Store = store.NewWeaviate()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Errorf("%s conversation connector %s not support", neo.ID, neo.ConversationSetting.Connector)
|
return fmt.Errorf("%s store connector %s not support", neo.ID, neo.StoreSetting.Connector)
|
||||||
}
|
}
|
||||||
|
|
||||||
// sendMessage sends a message to the client
|
// sendMessage sends a message to the client
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,8 @@ import (
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/yaoapp/gou/process"
|
"github.com/yaoapp/gou/process"
|
||||||
"github.com/yaoapp/kun/exception"
|
"github.com/yaoapp/kun/exception"
|
||||||
"github.com/yaoapp/yao/neo/conversation"
|
|
||||||
"github.com/yaoapp/yao/neo/message"
|
"github.com/yaoapp/yao/neo/message"
|
||||||
|
"github.com/yaoapp/yao/neo/store"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetNeo returns the Neo instance
|
// GetNeo returns the Neo instance
|
||||||
|
|
@ -32,7 +32,6 @@ func init() {
|
||||||
|
|
||||||
// ProcessWrite process the write request
|
// ProcessWrite process the write request
|
||||||
func ProcessWrite(process *process.Process) interface{} {
|
func ProcessWrite(process *process.Process) interface{} {
|
||||||
|
|
||||||
process.ValidateArgNums(2)
|
process.ValidateArgNums(2)
|
||||||
|
|
||||||
w, ok := process.Args[0].(gin.ResponseWriter)
|
w, ok := process.Args[0].(gin.ResponseWriter)
|
||||||
|
|
@ -63,11 +62,11 @@ func processAssistantCreate(process *process.Process) interface{} {
|
||||||
data := process.ArgsMap(0)
|
data := process.ArgsMap(0)
|
||||||
|
|
||||||
neo := GetNeo()
|
neo := GetNeo()
|
||||||
if neo.Conversation == nil {
|
if neo.Store == nil {
|
||||||
exception.New("Neo conversation is not initialized", 500).Throw()
|
exception.New("Neo store is not initialized", 500).Throw()
|
||||||
}
|
}
|
||||||
|
|
||||||
id, err := neo.Conversation.SaveAssistant(data)
|
id, err := neo.Store.SaveAssistant(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
exception.New("Failed to create assistant: %s", 500, err.Error()).Throw()
|
exception.New("Failed to create assistant: %s", 500, err.Error()).Throw()
|
||||||
}
|
}
|
||||||
|
|
@ -81,11 +80,11 @@ func processAssistantSave(process *process.Process) interface{} {
|
||||||
data := process.ArgsMap(0)
|
data := process.ArgsMap(0)
|
||||||
|
|
||||||
neo := GetNeo()
|
neo := GetNeo()
|
||||||
if neo.Conversation == nil {
|
if neo.Store == nil {
|
||||||
exception.New("Neo conversation is not initialized", 500).Throw()
|
exception.New("Neo store is not initialized", 500).Throw()
|
||||||
}
|
}
|
||||||
|
|
||||||
id, err := neo.Conversation.SaveAssistant(data)
|
id, err := neo.Store.SaveAssistant(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
exception.New("Failed to save assistant: %s", 500, err.Error()).Throw()
|
exception.New("Failed to save assistant: %s", 500, err.Error()).Throw()
|
||||||
}
|
}
|
||||||
|
|
@ -99,11 +98,11 @@ func processAssistantDelete(process *process.Process) interface{} {
|
||||||
assistantID := process.ArgsString(0)
|
assistantID := process.ArgsString(0)
|
||||||
|
|
||||||
neo := GetNeo()
|
neo := GetNeo()
|
||||||
if neo.Conversation == nil {
|
if neo.Store == nil {
|
||||||
exception.New("Neo conversation is not initialized", 500).Throw()
|
exception.New("Neo store is not initialized", 500).Throw()
|
||||||
}
|
}
|
||||||
|
|
||||||
err := neo.Conversation.DeleteAssistant(assistantID)
|
err := neo.Store.DeleteAssistant(assistantID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
exception.New("Failed to delete assistant: %s", 500, err.Error()).Throw()
|
exception.New("Failed to delete assistant: %s", 500, err.Error()).Throw()
|
||||||
}
|
}
|
||||||
|
|
@ -114,7 +113,7 @@ func processAssistantDelete(process *process.Process) interface{} {
|
||||||
// processAssistantSearch process the assistant search request
|
// processAssistantSearch process the assistant search request
|
||||||
func processAssistantSearch(process *process.Process) interface{} {
|
func processAssistantSearch(process *process.Process) interface{} {
|
||||||
params := process.ArgsMap(0)
|
params := process.ArgsMap(0)
|
||||||
filter := conversation.AssistantFilter{}
|
filter := store.AssistantFilter{}
|
||||||
|
|
||||||
// Parse page and pagesize
|
// Parse page and pagesize
|
||||||
if page, ok := params["page"]; ok {
|
if page, ok := params["page"]; ok {
|
||||||
|
|
@ -165,11 +164,11 @@ func processAssistantSearch(process *process.Process) interface{} {
|
||||||
|
|
||||||
// Get assistants
|
// Get assistants
|
||||||
neo := GetNeo()
|
neo := GetNeo()
|
||||||
if neo.Conversation == nil {
|
if neo.Store == nil {
|
||||||
exception.New("Neo conversation is not initialized", 500).Throw()
|
exception.New("Neo store is not initialized", 500).Throw()
|
||||||
}
|
}
|
||||||
|
|
||||||
res, err := neo.Conversation.GetAssistants(filter)
|
res, err := neo.Store.GetAssistants(filter)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
exception.New("get assistants error: %s", 500, err).Throw()
|
exception.New("get assistants error: %s", 500, err).Throw()
|
||||||
}
|
}
|
||||||
|
|
@ -183,17 +182,17 @@ func processAssistantFind(process *process.Process) interface{} {
|
||||||
assistantID := process.ArgsString(0)
|
assistantID := process.ArgsString(0)
|
||||||
|
|
||||||
neo := GetNeo()
|
neo := GetNeo()
|
||||||
if neo.Conversation == nil {
|
if neo.Store == nil {
|
||||||
exception.New("Neo conversation is not initialized", 500).Throw()
|
exception.New("Neo store is not initialized", 500).Throw()
|
||||||
}
|
}
|
||||||
|
|
||||||
filter := conversation.AssistantFilter{
|
filter := store.AssistantFilter{
|
||||||
AssistantID: assistantID,
|
AssistantID: assistantID,
|
||||||
Page: 1,
|
Page: 1,
|
||||||
PageSize: 1,
|
PageSize: 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
res, err := neo.Conversation.GetAssistants(filter)
|
res, err := neo.Store.GetAssistants(filter)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
exception.New("Failed to find assistant: %s", 500, err.Error()).Throw()
|
exception.New("Failed to find assistant: %s", 500, err.Error()).Throw()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
package conversation
|
package store
|
||||||
|
|
||||||
// Mongo represents a MongoDB-based conversation storage
|
// Mongo represents a MongoDB-based conversation storage
|
||||||
type Mongo struct{}
|
type Mongo struct{}
|
||||||
|
|
||||||
// NewMongo creates a new MongoDB conversation storage
|
// NewMongo create a new mongo store
|
||||||
func NewMongo() *Mongo {
|
func NewMongo() Store {
|
||||||
return &Mongo{}
|
return &Mongo{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
package conversation
|
package store
|
||||||
|
|
||||||
// Redis represents a Redis-based conversation storage
|
// Redis represents a Redis-based conversation storage
|
||||||
type Redis struct{}
|
type Redis struct{}
|
||||||
|
|
||||||
// NewRedis creates a new Redis conversation storage
|
// NewRedis create a new redis store
|
||||||
func NewRedis() *Redis {
|
func NewRedis() Store {
|
||||||
return &Redis{}
|
return &Redis{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package conversation
|
package store
|
||||||
|
|
||||||
// Setting represents the conversation configuration structure
|
// Setting represents the conversation configuration structure
|
||||||
// Used to configure basic conversation parameters including connector, user field, table name, etc.
|
// Used to configure basic conversation parameters including connector, user field, table name, etc.
|
||||||
|
|
@ -69,9 +69,9 @@ type AssistantResponse struct {
|
||||||
Total int64 `json:"total"` // Total number of items
|
Total int64 `json:"total"` // Total number of items
|
||||||
}
|
}
|
||||||
|
|
||||||
// Conversation defines the conversation storage interface
|
// Store defines the conversation storage interface
|
||||||
// Provides basic operations required for conversation management
|
// Provides basic operations required for conversation management
|
||||||
type Conversation interface {
|
type Store interface {
|
||||||
// GetChats retrieves a list of chats
|
// GetChats retrieves a list of chats
|
||||||
// sid: Session ID
|
// sid: Session ID
|
||||||
// filter: Filter conditions
|
// filter: Filter conditions
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
package conversation
|
package store
|
||||||
|
|
||||||
// Weaviate represents a Weaviate-based conversation storage
|
// Weaviate represents a Weaviate-based conversation storage
|
||||||
type Weaviate struct{}
|
type Weaviate struct{}
|
||||||
|
|
||||||
// NewWeaviate creates a new Weaviate conversation storage
|
// NewWeaviate create a new weaviate store
|
||||||
func NewWeaviate() *Weaviate {
|
func NewWeaviate() Store {
|
||||||
return &Weaviate{}
|
return &Weaviate{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package conversation
|
package store
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
@ -45,8 +45,8 @@ type Xun struct {
|
||||||
// DeleteAssistant deletes an assistant by assistant_id
|
// DeleteAssistant deletes an assistant by assistant_id
|
||||||
// GetAssistants retrieves a paginated list of assistants with filtering
|
// GetAssistants retrieves a paginated list of assistants with filtering
|
||||||
|
|
||||||
// NewXun create a new conversation
|
// NewXun create a new xun store
|
||||||
func NewXun(setting Setting) (*Xun, error) {
|
func NewXun(setting Setting) (Store, error) {
|
||||||
conv := &Xun{setting: setting}
|
conv := &Xun{setting: setting}
|
||||||
if setting.Connector == "default" {
|
if setting.Connector == "default" {
|
||||||
conv.query = capsule.Global.Query()
|
conv.query = capsule.Global.Query()
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package conversation
|
package store
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
@ -38,7 +38,7 @@ func TestNewXunDefault(t *testing.T) {
|
||||||
// Add a small delay to ensure table is created
|
// Add a small delay to ensure table is created
|
||||||
time.Sleep(100 * time.Millisecond)
|
time.Sleep(100 * time.Millisecond)
|
||||||
|
|
||||||
conv, err := NewXun(Setting{
|
store, err := NewXun(Setting{
|
||||||
Connector: "default",
|
Connector: "default",
|
||||||
Table: "__unit_test_conversation",
|
Table: "__unit_test_conversation",
|
||||||
})
|
})
|
||||||
|
|
@ -69,38 +69,47 @@ func TestNewXunDefault(t *testing.T) {
|
||||||
}
|
}
|
||||||
assert.Equal(t, true, has)
|
assert.Equal(t, true, has)
|
||||||
|
|
||||||
// validate the history table
|
// Validate table structure by attempting operations
|
||||||
tab, err := conv.schema.GetTable(conv.getHistoryTable())
|
// Test history operations
|
||||||
if err != nil {
|
messages := []map[string]interface{}{
|
||||||
t.Fatal(err)
|
{"role": "user", "content": "test message"},
|
||||||
|
}
|
||||||
|
err = store.SaveHistory("test_user", messages, "test_chat", nil)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
history, err := store.GetHistory("test_user", "test_chat")
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.NotEmpty(t, history)
|
||||||
|
|
||||||
|
// Test chat operations
|
||||||
|
err = store.UpdateChatTitle("test_user", "test_chat", "Test Chat")
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
chat, err := store.GetChat("test_user", "test_chat")
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.NotNil(t, chat)
|
||||||
|
|
||||||
|
// Test assistant operations
|
||||||
|
assistant := map[string]interface{}{
|
||||||
|
"name": "Test Assistant",
|
||||||
|
"type": "assistant",
|
||||||
|
"connector": "test",
|
||||||
|
"description": "Test Description",
|
||||||
|
"tags": []string{"test"},
|
||||||
|
"mentionable": true,
|
||||||
|
"automated": true,
|
||||||
}
|
}
|
||||||
|
|
||||||
fields := []string{"id", "sid", "cid", "uid", "role", "name", "content", "context", "created_at", "updated_at", "expired_at"}
|
id, err := store.SaveAssistant(assistant)
|
||||||
for _, field := range fields {
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, true, tab.HasColumn(field))
|
assert.NotNil(t, id)
|
||||||
}
|
|
||||||
|
|
||||||
// validate the chat table
|
// Clean up test data
|
||||||
tab, err = conv.schema.GetTable(conv.getChatTable())
|
err = store.DeleteChat("test_user", "test_chat")
|
||||||
if err != nil {
|
assert.Nil(t, err)
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
chatFields := []string{"id", "chat_id", "title", "sid", "created_at", "updated_at"}
|
err = store.DeleteAssistant(id.(string))
|
||||||
for _, field := range chatFields {
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, true, tab.HasColumn(field))
|
|
||||||
}
|
|
||||||
|
|
||||||
// validate the assistant table
|
|
||||||
tab, err = conv.schema.GetTable(conv.getAssistantTable())
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
assistantFields := []string{"id", "assistant_id", "type", "name", "avatar", "connector", "description", "options", "prompts", "flows", "files", "functions", "tags", "readonly", "permissions", "automated", "mentionable", "created_at", "updated_at"}
|
|
||||||
for _, field := range assistantFields {
|
|
||||||
assert.Equal(t, true, tab.HasColumn(field))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewXunConnector(t *testing.T) {
|
func TestNewXunConnector(t *testing.T) {
|
||||||
|
|
@ -128,7 +137,7 @@ func TestNewXunConnector(t *testing.T) {
|
||||||
// Add a small delay to ensure table is created
|
// Add a small delay to ensure table is created
|
||||||
time.Sleep(100 * time.Millisecond)
|
time.Sleep(100 * time.Millisecond)
|
||||||
|
|
||||||
conv, err := NewXun(Setting{
|
store, err := NewXun(Setting{
|
||||||
Connector: "mysql",
|
Connector: "mysql",
|
||||||
Table: "__unit_test_conversation",
|
Table: "__unit_test_conversation",
|
||||||
})
|
})
|
||||||
|
|
@ -159,38 +168,19 @@ func TestNewXunConnector(t *testing.T) {
|
||||||
}
|
}
|
||||||
assert.Equal(t, true, has)
|
assert.Equal(t, true, has)
|
||||||
|
|
||||||
// validate the history table
|
// Test basic operations
|
||||||
tab, err := conv.schema.GetTable(conv.getHistoryTable())
|
messages := []map[string]interface{}{
|
||||||
if err != nil {
|
{"role": "user", "content": "test message"},
|
||||||
t.Fatal(err)
|
|
||||||
}
|
}
|
||||||
|
err = store.SaveHistory("test_user", messages, "test_chat", nil)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
fields := []string{"id", "sid", "cid", "uid", "role", "name", "content", "context", "created_at", "updated_at", "expired_at"}
|
history, err := store.GetHistory("test_user", "test_chat")
|
||||||
for _, field := range fields {
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, true, tab.HasColumn(field))
|
assert.NotEmpty(t, history)
|
||||||
}
|
|
||||||
|
|
||||||
// validate the chat table
|
err = store.DeleteChat("test_user", "test_chat")
|
||||||
tab, err = conv.schema.GetTable(conv.getChatTable())
|
assert.Nil(t, err)
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
chatFields := []string{"id", "chat_id", "title", "sid", "created_at", "updated_at"}
|
|
||||||
for _, field := range chatFields {
|
|
||||||
assert.Equal(t, true, tab.HasColumn(field))
|
|
||||||
}
|
|
||||||
|
|
||||||
// validate the assistant table
|
|
||||||
tab, err = conv.schema.GetTable(conv.getAssistantTable())
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
assistantFields := []string{"id", "assistant_id", "type", "name", "avatar", "connector", "description", "options", "prompts", "flows", "files", "functions", "tags", "readonly", "permissions", "automated", "mentionable", "created_at", "updated_at"}
|
|
||||||
for _, field := range assistantFields {
|
|
||||||
assert.Equal(t, true, tab.HasColumn(field))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestXunSaveAndGetHistory(t *testing.T) {
|
func TestXunSaveAndGetHistory(t *testing.T) {
|
||||||
|
|
@ -209,7 +199,7 @@ func TestXunSaveAndGetHistory(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
conv, err := NewXun(Setting{
|
store, err := NewXun(Setting{
|
||||||
Connector: "default",
|
Connector: "default",
|
||||||
Table: "__unit_test_conversation",
|
Table: "__unit_test_conversation",
|
||||||
TTL: 3600,
|
TTL: 3600,
|
||||||
|
|
@ -217,14 +207,14 @@ func TestXunSaveAndGetHistory(t *testing.T) {
|
||||||
|
|
||||||
// save the history
|
// save the history
|
||||||
cid := "123456"
|
cid := "123456"
|
||||||
err = conv.SaveHistory("123456", []map[string]interface{}{
|
err = store.SaveHistory("123456", []map[string]interface{}{
|
||||||
{"role": "user", "name": "user1", "content": "hello"},
|
{"role": "user", "name": "user1", "content": "hello"},
|
||||||
{"role": "assistant", "name": "user1", "content": "Hello there, how"},
|
{"role": "assistant", "name": "user1", "content": "Hello there, how"},
|
||||||
}, cid, nil)
|
}, cid, nil)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
// get the history
|
// get the history
|
||||||
data, err := conv.GetHistory("123456", cid)
|
data, err := store.GetHistory("123456", cid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -247,7 +237,7 @@ func TestXunSaveAndGetHistoryWithCID(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
conv, err := NewXun(Setting{
|
store, err := NewXun(Setting{
|
||||||
Connector: "default",
|
Connector: "default",
|
||||||
Table: "__unit_test_conversation",
|
Table: "__unit_test_conversation",
|
||||||
TTL: 3600,
|
TTL: 3600,
|
||||||
|
|
@ -260,11 +250,11 @@ func TestXunSaveAndGetHistoryWithCID(t *testing.T) {
|
||||||
{"role": "user", "name": "user1", "content": "hello"},
|
{"role": "user", "name": "user1", "content": "hello"},
|
||||||
{"role": "assistant", "name": "assistant1", "content": "Hi! How can I help you?"},
|
{"role": "assistant", "name": "assistant1", "content": "Hi! How can I help you?"},
|
||||||
}
|
}
|
||||||
err = conv.SaveHistory(sid, messages, cid, nil)
|
err = store.SaveHistory(sid, messages, cid, nil)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
// get the history for specific cid
|
// get the history for specific cid
|
||||||
data, err := conv.GetHistory(sid, cid)
|
data, err := store.GetHistory(sid, cid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -275,25 +265,25 @@ func TestXunSaveAndGetHistoryWithCID(t *testing.T) {
|
||||||
moreMessages := []map[string]interface{}{
|
moreMessages := []map[string]interface{}{
|
||||||
{"role": "user", "name": "user1", "content": "another message"},
|
{"role": "user", "name": "user1", "content": "another message"},
|
||||||
}
|
}
|
||||||
err = conv.SaveHistory(sid, moreMessages, anotherCID, nil)
|
err = store.SaveHistory(sid, moreMessages, anotherCID, nil)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
// get history for the first cid - should still be 2 messages
|
// get history for the first cid - should still be 2 messages
|
||||||
data, err = conv.GetHistory(sid, cid)
|
data, err = store.GetHistory(sid, cid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
assert.Equal(t, 2, len(data))
|
assert.Equal(t, 2, len(data))
|
||||||
|
|
||||||
// get history for the second cid - should be 1 message
|
// get history for the second cid - should be 1 message
|
||||||
data, err = conv.GetHistory(sid, anotherCID)
|
data, err = store.GetHistory(sid, anotherCID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
assert.Equal(t, 1, len(data))
|
assert.Equal(t, 1, len(data))
|
||||||
|
|
||||||
// get all history for the sid without specifying cid
|
// get all history for the sid without specifying cid
|
||||||
allData, err := conv.GetHistory(sid, cid)
|
allData, err := store.GetHistory(sid, cid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -316,7 +306,7 @@ func TestXunGetChats(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
conv, err := NewXun(Setting{
|
store, err := NewXun(Setting{
|
||||||
Connector: "default",
|
Connector: "default",
|
||||||
Table: "__unit_test_conversation",
|
Table: "__unit_test_conversation",
|
||||||
})
|
})
|
||||||
|
|
@ -333,22 +323,15 @@ func TestXunGetChats(t *testing.T) {
|
||||||
// Create chats with different dates
|
// Create chats with different dates
|
||||||
for i := 0; i < 5; i++ {
|
for i := 0; i < 5; i++ {
|
||||||
chatID := fmt.Sprintf("chat_%d", i)
|
chatID := fmt.Sprintf("chat_%d", i)
|
||||||
// First create the chat with a title
|
title := fmt.Sprintf("Test Chat %d", i)
|
||||||
err = conv.newQueryChat().Insert(map[string]interface{}{
|
|
||||||
"chat_id": chatID,
|
|
||||||
"title": fmt.Sprintf("Test Chat %d", i),
|
|
||||||
"sid": sid,
|
|
||||||
"created_at": time.Now(),
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Then save the history
|
// Save history first to create the chat
|
||||||
err = conv.SaveHistory(sid, messages, chatID, nil)
|
err = store.SaveHistory(sid, messages, chatID, nil)
|
||||||
if err != nil {
|
assert.Nil(t, err)
|
||||||
t.Fatal(err)
|
|
||||||
}
|
// Update the chat title
|
||||||
|
err = store.UpdateChatTitle(sid, chatID, title)
|
||||||
|
assert.Nil(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test getting chats with default filter
|
// Test getting chats with default filter
|
||||||
|
|
@ -356,7 +339,7 @@ func TestXunGetChats(t *testing.T) {
|
||||||
PageSize: 10,
|
PageSize: 10,
|
||||||
Order: "desc",
|
Order: "desc",
|
||||||
}
|
}
|
||||||
groups, err := conv.GetChats(sid, filter)
|
groups, err := store.GetChats(sid, filter)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -365,7 +348,7 @@ func TestXunGetChats(t *testing.T) {
|
||||||
|
|
||||||
// Test with keywords
|
// Test with keywords
|
||||||
filter.Keywords = "test"
|
filter.Keywords = "test"
|
||||||
groups, err = conv.GetChats(sid, filter)
|
groups, err = store.GetChats(sid, filter)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -379,7 +362,7 @@ func TestXunDeleteChat(t *testing.T) {
|
||||||
defer capsule.Schema().DropTableIfExists("__unit_test_conversation_history")
|
defer capsule.Schema().DropTableIfExists("__unit_test_conversation_history")
|
||||||
defer capsule.Schema().DropTableIfExists("__unit_test_conversation_chat")
|
defer capsule.Schema().DropTableIfExists("__unit_test_conversation_chat")
|
||||||
|
|
||||||
conv, err := NewXun(Setting{
|
store, err := NewXun(Setting{
|
||||||
Connector: "default",
|
Connector: "default",
|
||||||
Table: "__unit_test_conversation",
|
Table: "__unit_test_conversation",
|
||||||
})
|
})
|
||||||
|
|
@ -395,20 +378,20 @@ func TestXunDeleteChat(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save the chat and history
|
// Save the chat and history
|
||||||
err = conv.SaveHistory(sid, messages, cid, nil)
|
err = store.SaveHistory(sid, messages, cid, nil)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
// Verify chat exists
|
// Verify chat exists
|
||||||
chat, err := conv.GetChat(sid, cid)
|
chat, err := store.GetChat(sid, cid)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.NotNil(t, chat)
|
assert.NotNil(t, chat)
|
||||||
|
|
||||||
// Delete the chat
|
// Delete the chat
|
||||||
err = conv.DeleteChat(sid, cid)
|
err = store.DeleteChat(sid, cid)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
// Verify chat is deleted
|
// Verify chat is deleted
|
||||||
chat, err = conv.GetChat(sid, cid)
|
chat, err = store.GetChat(sid, cid)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, (*ChatInfo)(nil), chat)
|
assert.Equal(t, (*ChatInfo)(nil), chat)
|
||||||
}
|
}
|
||||||
|
|
@ -419,7 +402,7 @@ func TestXunDeleteAllChats(t *testing.T) {
|
||||||
defer capsule.Schema().DropTableIfExists("__unit_test_conversation_history")
|
defer capsule.Schema().DropTableIfExists("__unit_test_conversation_history")
|
||||||
defer capsule.Schema().DropTableIfExists("__unit_test_conversation_chat")
|
defer capsule.Schema().DropTableIfExists("__unit_test_conversation_chat")
|
||||||
|
|
||||||
conv, err := NewXun(Setting{
|
store, err := NewXun(Setting{
|
||||||
Connector: "default",
|
Connector: "default",
|
||||||
Table: "__unit_test_conversation",
|
Table: "__unit_test_conversation",
|
||||||
})
|
})
|
||||||
|
|
@ -436,21 +419,21 @@ func TestXunDeleteAllChats(t *testing.T) {
|
||||||
// Save multiple chats
|
// Save multiple chats
|
||||||
for i := 0; i < 3; i++ {
|
for i := 0; i < 3; i++ {
|
||||||
cid := fmt.Sprintf("test_chat_%d", i)
|
cid := fmt.Sprintf("test_chat_%d", i)
|
||||||
err = conv.SaveHistory(sid, messages, cid, nil)
|
err = store.SaveHistory(sid, messages, cid, nil)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify chats exist
|
// Verify chats exist
|
||||||
response, err := conv.GetChats(sid, ChatFilter{})
|
response, err := store.GetChats(sid, ChatFilter{})
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Greater(t, response.Total, int64(0))
|
assert.Greater(t, response.Total, int64(0))
|
||||||
|
|
||||||
// Delete all chats
|
// Delete all chats
|
||||||
err = conv.DeleteAllChats(sid)
|
err = store.DeleteAllChats(sid)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
// Verify all chats are deleted
|
// Verify all chats are deleted
|
||||||
response, err = conv.GetChats(sid, ChatFilter{})
|
response, err = store.GetChats(sid, ChatFilter{})
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, int64(0), response.Total)
|
assert.Equal(t, int64(0), response.Total)
|
||||||
}
|
}
|
||||||
|
|
@ -470,7 +453,7 @@ func TestXunAssistantCRUD(t *testing.T) {
|
||||||
// Add a small delay to ensure table is created
|
// Add a small delay to ensure table is created
|
||||||
time.Sleep(100 * time.Millisecond)
|
time.Sleep(100 * time.Millisecond)
|
||||||
|
|
||||||
conv, err := NewXun(Setting{
|
store, err := NewXun(Setting{
|
||||||
Connector: "default",
|
Connector: "default",
|
||||||
Table: "__unit_test_conversation",
|
Table: "__unit_test_conversation",
|
||||||
})
|
})
|
||||||
|
|
@ -495,7 +478,7 @@ func TestXunAssistantCRUD(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test SaveAssistant (Create) with string JSON
|
// Test SaveAssistant (Create) with string JSON
|
||||||
v, err := conv.SaveAssistant(assistant)
|
v, err := store.SaveAssistant(assistant)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assistantID := v.(string)
|
assistantID := v.(string)
|
||||||
assert.NotEmpty(t, assistantID)
|
assert.NotEmpty(t, assistantID)
|
||||||
|
|
@ -519,7 +502,7 @@ func TestXunAssistantCRUD(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test SaveAssistant (Create) with native types
|
// Test SaveAssistant (Create) with native types
|
||||||
v, err = conv.SaveAssistant(assistant2)
|
v, err = store.SaveAssistant(assistant2)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assistant2ID := v.(string)
|
assistant2ID := v.(string)
|
||||||
assert.NotEmpty(t, assistant2ID)
|
assert.NotEmpty(t, assistant2ID)
|
||||||
|
|
@ -542,13 +525,13 @@ func TestXunAssistantCRUD(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test SaveAssistant (Create) with nil fields
|
// Test SaveAssistant (Create) with nil fields
|
||||||
v, err = conv.SaveAssistant(assistant3)
|
v, err = store.SaveAssistant(assistant3)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assistant3ID := v.(string)
|
assistant3ID := v.(string)
|
||||||
assert.NotEmpty(t, assistant3ID)
|
assert.NotEmpty(t, assistant3ID)
|
||||||
|
|
||||||
// Test GetAssistants to verify JSON fields are properly stored
|
// Test GetAssistants to verify JSON fields are properly stored
|
||||||
resp, err := conv.GetAssistants(AssistantFilter{})
|
resp, err := store.GetAssistants(AssistantFilter{})
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, 3, len(resp.Data))
|
assert.Equal(t, 3, len(resp.Data))
|
||||||
|
|
||||||
|
|
@ -614,11 +597,11 @@ func TestXunAssistantCRUD(t *testing.T) {
|
||||||
|
|
||||||
// Test updating with mixed JSON formats
|
// Test updating with mixed JSON formats
|
||||||
assistant2["assistant_id"] = assistant2ID
|
assistant2["assistant_id"] = assistant2ID
|
||||||
_, err = conv.SaveAssistant(assistant2)
|
_, err = store.SaveAssistant(assistant2)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
// Verify update
|
// Verify update
|
||||||
resp, err = conv.GetAssistants(AssistantFilter{})
|
resp, err = store.GetAssistants(AssistantFilter{})
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
for _, item := range resp.Data {
|
for _, item := range resp.Data {
|
||||||
if item["assistant_id"].(string) == assistant2ID {
|
if item["assistant_id"].(string) == assistant2ID {
|
||||||
|
|
@ -630,14 +613,14 @@ func TestXunAssistantCRUD(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test DeleteAssistant
|
// Test DeleteAssistant
|
||||||
err = conv.DeleteAssistant(assistantID)
|
err = store.DeleteAssistant(assistantID)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
err = conv.DeleteAssistant(assistant2ID)
|
err = store.DeleteAssistant(assistant2ID)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
err = conv.DeleteAssistant(assistant3ID)
|
err = store.DeleteAssistant(assistant3ID)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
resp, err = conv.GetAssistants(AssistantFilter{})
|
resp, err = store.GetAssistants(AssistantFilter{})
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, 0, len(resp.Data))
|
assert.Equal(t, 0, len(resp.Data))
|
||||||
}
|
}
|
||||||
|
|
@ -658,7 +641,7 @@ func TestXunAssistantPagination(t *testing.T) {
|
||||||
// Add a small delay to ensure table is created
|
// Add a small delay to ensure table is created
|
||||||
time.Sleep(100 * time.Millisecond)
|
time.Sleep(100 * time.Millisecond)
|
||||||
|
|
||||||
conv, err := NewXun(Setting{
|
store, err := NewXun(Setting{
|
||||||
Connector: "default",
|
Connector: "default",
|
||||||
Table: "__unit_test_conversation",
|
Table: "__unit_test_conversation",
|
||||||
})
|
})
|
||||||
|
|
@ -692,12 +675,12 @@ func TestXunAssistantPagination(t *testing.T) {
|
||||||
"mentionable": mentionable,
|
"mentionable": mentionable,
|
||||||
"automated": automated,
|
"automated": automated,
|
||||||
}
|
}
|
||||||
_, err = conv.SaveAssistant(assistant)
|
_, err = store.SaveAssistant(assistant)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test first page
|
// Test first page
|
||||||
resp, err := conv.GetAssistants(AssistantFilter{
|
resp, err := store.GetAssistants(AssistantFilter{
|
||||||
Page: 1,
|
Page: 1,
|
||||||
PageSize: 10,
|
PageSize: 10,
|
||||||
})
|
})
|
||||||
|
|
@ -709,7 +692,7 @@ func TestXunAssistantPagination(t *testing.T) {
|
||||||
assert.Equal(t, 0, resp.Prev)
|
assert.Equal(t, 0, resp.Prev)
|
||||||
|
|
||||||
// Test second page
|
// Test second page
|
||||||
resp, err = conv.GetAssistants(AssistantFilter{
|
resp, err = store.GetAssistants(AssistantFilter{
|
||||||
Page: 2,
|
Page: 2,
|
||||||
PageSize: 10,
|
PageSize: 10,
|
||||||
})
|
})
|
||||||
|
|
@ -719,7 +702,7 @@ func TestXunAssistantPagination(t *testing.T) {
|
||||||
assert.Equal(t, 1, resp.Prev)
|
assert.Equal(t, 1, resp.Prev)
|
||||||
|
|
||||||
// Test last page
|
// Test last page
|
||||||
resp, err = conv.GetAssistants(AssistantFilter{
|
resp, err = store.GetAssistants(AssistantFilter{
|
||||||
Page: 3,
|
Page: 3,
|
||||||
PageSize: 10,
|
PageSize: 10,
|
||||||
})
|
})
|
||||||
|
|
@ -729,7 +712,7 @@ func TestXunAssistantPagination(t *testing.T) {
|
||||||
assert.Equal(t, 2, resp.Prev)
|
assert.Equal(t, 2, resp.Prev)
|
||||||
|
|
||||||
// Test filtering with tags
|
// Test filtering with tags
|
||||||
resp, err = conv.GetAssistants(AssistantFilter{
|
resp, err = store.GetAssistants(AssistantFilter{
|
||||||
Tags: []string{"tag0"},
|
Tags: []string{"tag0"},
|
||||||
Page: 1,
|
Page: 1,
|
||||||
PageSize: 10,
|
PageSize: 10,
|
||||||
|
|
@ -738,7 +721,7 @@ func TestXunAssistantPagination(t *testing.T) {
|
||||||
assert.Equal(t, 5, len(resp.Data))
|
assert.Equal(t, 5, len(resp.Data))
|
||||||
|
|
||||||
// Test filtering with keywords
|
// Test filtering with keywords
|
||||||
resp, err = conv.GetAssistants(AssistantFilter{
|
resp, err = store.GetAssistants(AssistantFilter{
|
||||||
Keywords: "Assistant 1",
|
Keywords: "Assistant 1",
|
||||||
Page: 1,
|
Page: 1,
|
||||||
PageSize: 10,
|
PageSize: 10,
|
||||||
|
|
@ -747,7 +730,7 @@ func TestXunAssistantPagination(t *testing.T) {
|
||||||
assert.Greater(t, len(resp.Data), 0)
|
assert.Greater(t, len(resp.Data), 0)
|
||||||
|
|
||||||
// Test filtering with connector
|
// Test filtering with connector
|
||||||
resp, err = conv.GetAssistants(AssistantFilter{
|
resp, err = store.GetAssistants(AssistantFilter{
|
||||||
Connector: "connector0",
|
Connector: "connector0",
|
||||||
Page: 1,
|
Page: 1,
|
||||||
PageSize: 10,
|
PageSize: 10,
|
||||||
|
|
@ -757,7 +740,7 @@ func TestXunAssistantPagination(t *testing.T) {
|
||||||
|
|
||||||
// Test filtering with mentionable
|
// Test filtering with mentionable
|
||||||
mentionableTrue := true
|
mentionableTrue := true
|
||||||
resp, err = conv.GetAssistants(AssistantFilter{
|
resp, err = store.GetAssistants(AssistantFilter{
|
||||||
Mentionable: &mentionableTrue,
|
Mentionable: &mentionableTrue,
|
||||||
Page: 1,
|
Page: 1,
|
||||||
PageSize: 10,
|
PageSize: 10,
|
||||||
|
|
@ -767,7 +750,7 @@ func TestXunAssistantPagination(t *testing.T) {
|
||||||
|
|
||||||
// Test filtering with automated
|
// Test filtering with automated
|
||||||
automatedTrue := true
|
automatedTrue := true
|
||||||
resp, err = conv.GetAssistants(AssistantFilter{
|
resp, err = store.GetAssistants(AssistantFilter{
|
||||||
Automated: &automatedTrue,
|
Automated: &automatedTrue,
|
||||||
Page: 1,
|
Page: 1,
|
||||||
PageSize: 10,
|
PageSize: 10,
|
||||||
|
|
@ -780,7 +763,7 @@ func TestXunAssistantPagination(t *testing.T) {
|
||||||
firstAssistantID := resp.Data[0]["assistant_id"].(string)
|
firstAssistantID := resp.Data[0]["assistant_id"].(string)
|
||||||
|
|
||||||
// Test exact match with assistant_id
|
// Test exact match with assistant_id
|
||||||
resp, err = conv.GetAssistants(AssistantFilter{
|
resp, err = store.GetAssistants(AssistantFilter{
|
||||||
AssistantID: firstAssistantID,
|
AssistantID: firstAssistantID,
|
||||||
Page: 1,
|
Page: 1,
|
||||||
PageSize: 10,
|
PageSize: 10,
|
||||||
|
|
@ -790,7 +773,7 @@ func TestXunAssistantPagination(t *testing.T) {
|
||||||
assert.Equal(t, firstAssistantID, resp.Data[0]["assistant_id"])
|
assert.Equal(t, firstAssistantID, resp.Data[0]["assistant_id"])
|
||||||
|
|
||||||
// Test assistant_id with other filters
|
// Test assistant_id with other filters
|
||||||
resp, err = conv.GetAssistants(AssistantFilter{
|
resp, err = store.GetAssistants(AssistantFilter{
|
||||||
AssistantID: firstAssistantID,
|
AssistantID: firstAssistantID,
|
||||||
Select: []string{"name", "assistant_id", "description"},
|
Select: []string{"name", "assistant_id", "description"},
|
||||||
Page: 1,
|
Page: 1,
|
||||||
|
|
@ -807,7 +790,7 @@ func TestXunAssistantPagination(t *testing.T) {
|
||||||
assert.NotContains(t, resp.Data[0], "options")
|
assert.NotContains(t, resp.Data[0], "options")
|
||||||
|
|
||||||
// Test non-existent assistant_id
|
// Test non-existent assistant_id
|
||||||
resp, err = conv.GetAssistants(AssistantFilter{
|
resp, err = store.GetAssistants(AssistantFilter{
|
||||||
AssistantID: "non-existent-id",
|
AssistantID: "non-existent-id",
|
||||||
Page: 1,
|
Page: 1,
|
||||||
PageSize: 10,
|
PageSize: 10,
|
||||||
|
|
@ -816,7 +799,7 @@ func TestXunAssistantPagination(t *testing.T) {
|
||||||
assert.Equal(t, 0, len(resp.Data))
|
assert.Equal(t, 0, len(resp.Data))
|
||||||
|
|
||||||
// Test combined filters
|
// Test combined filters
|
||||||
resp, err = conv.GetAssistants(AssistantFilter{
|
resp, err = store.GetAssistants(AssistantFilter{
|
||||||
Tags: []string{"tag0"},
|
Tags: []string{"tag0"},
|
||||||
Keywords: "Assistant",
|
Keywords: "Assistant",
|
||||||
Connector: "connector0",
|
Connector: "connector0",
|
||||||
|
|
@ -828,7 +811,7 @@ func TestXunAssistantPagination(t *testing.T) {
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
// Test filtering with select fields
|
// Test filtering with select fields
|
||||||
resp, err = conv.GetAssistants(AssistantFilter{
|
resp, err = store.GetAssistants(AssistantFilter{
|
||||||
Select: []string{"name", "description", "tags"},
|
Select: []string{"name", "description", "tags"},
|
||||||
Page: 1,
|
Page: 1,
|
||||||
PageSize: 10,
|
PageSize: 10,
|
||||||
|
|
@ -851,7 +834,7 @@ func TestXunAssistantPagination(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test filtering with select fields and other filters combined
|
// Test filtering with select fields and other filters combined
|
||||||
resp, err = conv.GetAssistants(AssistantFilter{
|
resp, err = store.GetAssistants(AssistantFilter{
|
||||||
Tags: []string{"tag0"},
|
Tags: []string{"tag0"},
|
||||||
Keywords: "Assistant",
|
Keywords: "Assistant",
|
||||||
Select: []string{"name", "tags"},
|
Select: []string{"name", "tags"},
|
||||||
|
|
@ -5,7 +5,7 @@ import (
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/yaoapp/yao/neo/assistant"
|
"github.com/yaoapp/yao/neo/assistant"
|
||||||
"github.com/yaoapp/yao/neo/conversation"
|
"github.com/yaoapp/yao/neo/store"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DSL AI assistant
|
// DSL AI assistant
|
||||||
|
|
@ -15,7 +15,7 @@ type DSL struct {
|
||||||
Use string `json:"use,omitempty" yaml:"use,omitempty"` // Which assistant to use default
|
Use string `json:"use,omitempty" yaml:"use,omitempty"` // Which assistant to use default
|
||||||
Guard string `json:"guard,omitempty" yaml:"guard,omitempty"`
|
Guard string `json:"guard,omitempty" yaml:"guard,omitempty"`
|
||||||
Connector string `json:"connector" yaml:"connector"`
|
Connector string `json:"connector" yaml:"connector"`
|
||||||
ConversationSetting conversation.Setting `json:"conversation" yaml:"conversation"`
|
StoreSetting store.Setting `json:"store" yaml:"store"`
|
||||||
Option map[string]interface{} `json:"option" yaml:"option"`
|
Option map[string]interface{} `json:"option" yaml:"option"`
|
||||||
Prepare string `json:"prepare,omitempty" yaml:"prepare,omitempty"`
|
Prepare string `json:"prepare,omitempty" yaml:"prepare,omitempty"`
|
||||||
Create string `json:"create,omitempty" yaml:"create,omitempty"`
|
Create string `json:"create,omitempty" yaml:"create,omitempty"`
|
||||||
|
|
@ -25,7 +25,7 @@ type DSL struct {
|
||||||
Prompts []assistant.Prompt `json:"prompts,omitempty" yaml:"prompts,omitempty"`
|
Prompts []assistant.Prompt `json:"prompts,omitempty" yaml:"prompts,omitempty"`
|
||||||
Allows []string `json:"allows,omitempty" yaml:"allows,omitempty"`
|
Allows []string `json:"allows,omitempty" yaml:"allows,omitempty"`
|
||||||
Assistant assistant.API `json:"-" yaml:"-"` // The default assistant
|
Assistant assistant.API `json:"-" yaml:"-"` // The default assistant
|
||||||
Conversation conversation.Conversation `json:"-" yaml:"-"`
|
Store store.Store `json:"-" yaml:"-"`
|
||||||
GuardHandlers []gin.HandlerFunc `json:"-" yaml:"-"`
|
GuardHandlers []gin.HandlerFunc `json:"-" yaml:"-"`
|
||||||
AssistantList []assistant.Assistant `json:"-" yaml:"-"`
|
AssistantList []assistant.Assistant `json:"-" yaml:"-"`
|
||||||
AssistantMaps map[string]assistant.Assistant `json:"-" yaml:"-"`
|
AssistantMaps map[string]assistant.Assistant `json:"-" yaml:"-"`
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue