Enhance chat update functionality and introduce chat title generation in Neo API
- Updated handleChatUpdate method to include content field in the request body, allowing for dynamic chat title generation based on user input. - Implemented GenerateChatTitle method to create a concise title for chats, improving user experience and interaction. - Modified JSON response structure in handleChatDetail and handleChatUpdate methods for better clarity and consistency. - Enhanced error handling for chat updates, ensuring robust validation and feedback for users.
This commit is contained in:
parent
869ed3717a
commit
b3bc843235
2 changed files with 114 additions and 3 deletions
19
neo/api.go
19
neo/api.go
|
|
@ -338,7 +338,7 @@ func (neo *DSL) handleChatDetail(c *gin.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.JSON(200, chat)
|
c.JSON(200, map[string]interface{}{"data": chat})
|
||||||
c.Done()
|
c.Done()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -383,6 +383,7 @@ func (neo *DSL) handleChatUpdate(c *gin.Context) {
|
||||||
// Get title from request body
|
// Get title from request body
|
||||||
var body struct {
|
var body struct {
|
||||||
Title string `json:"title"`
|
Title string `json:"title"`
|
||||||
|
Content string `json:"content"`
|
||||||
}
|
}
|
||||||
if err := c.BindJSON(&body); err != nil {
|
if err := c.BindJSON(&body); err != nil {
|
||||||
c.JSON(400, gin.H{"message": "invalid request body", "code": 400})
|
c.JSON(400, gin.H{"message": "invalid request body", "code": 400})
|
||||||
|
|
@ -390,6 +391,20 @@ func (neo *DSL) handleChatUpdate(c *gin.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If content is not empty, Generate the chat title
|
||||||
|
if body.Content != "" {
|
||||||
|
ctx, cancel := NewContextWithCancel(sid, c.Query("chat_id"), "")
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
title, err := neo.GenerateChatTitle(ctx, body.Content, c)
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(500, gin.H{"message": err.Error(), "code": 500})
|
||||||
|
c.Done()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
body.Title = title
|
||||||
|
}
|
||||||
|
|
||||||
if body.Title == "" {
|
if body.Title == "" {
|
||||||
c.JSON(400, gin.H{"message": "title is required", "code": 400})
|
c.JSON(400, gin.H{"message": "title is required", "code": 400})
|
||||||
c.Done()
|
c.Done()
|
||||||
|
|
@ -403,6 +418,6 @@ func (neo *DSL) handleChatUpdate(c *gin.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.JSON(200, gin.H{"message": "success"})
|
c.JSON(200, gin.H{"message": "ok", "title": body.Title, "chat_id": chatID})
|
||||||
c.Done()
|
c.Done()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
96
neo/neo.go
96
neo/neo.go
|
|
@ -58,6 +58,102 @@ func (neo *DSL) GetMentions(keywords string) ([]Mention, error) {
|
||||||
return neo.HookMention(context.Background(), keywords)
|
return neo.HookMention(context.Background(), keywords)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GenerateChatTitle generate the chat title
|
||||||
|
func (neo *DSL) GenerateChatTitle(ctx Context, input string, c *gin.Context) (string, error) {
|
||||||
|
|
||||||
|
prompts := `
|
||||||
|
Help me generate a title for the chat
|
||||||
|
1. The title should be a short and concise description of the chat.
|
||||||
|
2. The title should be a single sentence.
|
||||||
|
3. The title should be in same language as the chat.
|
||||||
|
4. The title should be no more than 50 characters.
|
||||||
|
`
|
||||||
|
|
||||||
|
messages := []map[string]interface{}{
|
||||||
|
{"role": "system", "content": prompts},
|
||||||
|
{"role": "user", "content": input},
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := neo.HookCreate(ctx, messages, c)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Select Assistant
|
||||||
|
ast, err := neo.selectAssistant(res.AssistantID)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
if ast == nil {
|
||||||
|
msg := message.New().Error("assistant is not initialized").Done()
|
||||||
|
msg.Write(c.Writer)
|
||||||
|
return "", fmt.Errorf("assistant is not initialized")
|
||||||
|
}
|
||||||
|
|
||||||
|
clientBreak := make(chan bool, 1)
|
||||||
|
done := make(chan bool, 1)
|
||||||
|
fail := make(chan error, 1)
|
||||||
|
|
||||||
|
content := []byte{}
|
||||||
|
|
||||||
|
// Chat with AI in background
|
||||||
|
go func() {
|
||||||
|
err := ast.Chat(c.Request.Context(), messages, neo.Option, func(data []byte) int {
|
||||||
|
select {
|
||||||
|
case <-clientBreak:
|
||||||
|
return 0 // break
|
||||||
|
|
||||||
|
default:
|
||||||
|
msg := message.NewOpenAI(data)
|
||||||
|
if msg == nil {
|
||||||
|
return 1 // continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle error
|
||||||
|
if msg.Type == "error" {
|
||||||
|
fail <- fmt.Errorf("%s", msg.Message.Text)
|
||||||
|
return 0 // break
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append content and send message
|
||||||
|
content = msg.Append(content)
|
||||||
|
|
||||||
|
// Complete the stream
|
||||||
|
if msg.Message.Done {
|
||||||
|
done <- true
|
||||||
|
return 0 // break
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1 // continue
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Chat error: %s", err.Error())
|
||||||
|
message.New().Error(err).Done().Write(c.Writer)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save chat history
|
||||||
|
if len(content) > 0 {
|
||||||
|
neo.saveHistory(ctx.Sid, ctx.ChatID, content, messages)
|
||||||
|
}
|
||||||
|
|
||||||
|
done <- true
|
||||||
|
}()
|
||||||
|
|
||||||
|
// Wait for completion or client disconnect
|
||||||
|
select {
|
||||||
|
case <-done:
|
||||||
|
return string(content), nil
|
||||||
|
case err := <-fail:
|
||||||
|
return "", err
|
||||||
|
case <-c.Writer.CloseNotify():
|
||||||
|
clientBreak <- true
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Upload upload a file
|
// Upload upload a file
|
||||||
func (neo *DSL) Upload(ctx Context, c *gin.Context) (*assistant.File, error) {
|
func (neo *DSL) Upload(ctx Context, c *gin.Context) (*assistant.File, error) {
|
||||||
// Get the file
|
// Get the file
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue