mirror of
https://github.com/coaidev/coai.git
synced 2025-05-19 13:00:14 +09:00
164 lines
3.4 KiB
Go
164 lines
3.4 KiB
Go
package dify
|
|
|
|
import (
|
|
adaptercommon "chat/adapter/common"
|
|
"chat/globals"
|
|
"chat/utils"
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
type ChatInstance struct {
|
|
Endpoint string
|
|
ApiKey string
|
|
responseComplete bool
|
|
}
|
|
|
|
func (c *ChatInstance) GetEndpoint() string {
|
|
return c.Endpoint
|
|
}
|
|
|
|
func (c *ChatInstance) GetApiKey() string {
|
|
return c.ApiKey
|
|
}
|
|
|
|
func (c *ChatInstance) GetHeader() map[string]string {
|
|
return map[string]string{
|
|
"Content-Type": "application/json",
|
|
"Authorization": fmt.Sprintf("Bearer %s", c.GetApiKey()),
|
|
}
|
|
}
|
|
|
|
func NewChatInstance(endpoint, apiKey string) *ChatInstance {
|
|
return &ChatInstance{
|
|
Endpoint: endpoint,
|
|
ApiKey: apiKey,
|
|
}
|
|
}
|
|
|
|
func NewChatInstanceFromConfig(conf globals.ChannelConfig) adaptercommon.Factory {
|
|
return NewChatInstance(
|
|
conf.GetEndpoint(),
|
|
conf.GetRandomSecret(),
|
|
)
|
|
}
|
|
|
|
func (c *ChatInstance) GetChatEndpoint() string {
|
|
return fmt.Sprintf("%s/chat-messages", c.GetEndpoint())
|
|
}
|
|
|
|
func (c *ChatInstance) GetChatBody(props *adaptercommon.ChatProps, stream bool) interface{} {
|
|
timestamp := time.Now().UnixNano()
|
|
userID := fmt.Sprintf("user_%d", timestamp)
|
|
|
|
query := ""
|
|
for _, msg := range props.Message {
|
|
if msg.Role == "user" {
|
|
query = msg.Content
|
|
break
|
|
}
|
|
}
|
|
|
|
return ChatRequest{
|
|
Inputs: map[string]interface{}{},
|
|
Query: query,
|
|
ResponseMode: "streaming",
|
|
User: userID,
|
|
AutoGenerateName: true,
|
|
}
|
|
}
|
|
|
|
func (c *ChatInstance) ProcessLine(data string) (string, error) {
|
|
if c.responseComplete {
|
|
return "", nil
|
|
}
|
|
|
|
if data == "" {
|
|
return "", nil
|
|
}
|
|
|
|
chunk, complete, err := processStreamResponse(data)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
if complete {
|
|
c.responseComplete = true
|
|
}
|
|
|
|
return chunk.Content, nil
|
|
}
|
|
|
|
func (c *ChatInstance) CreateChatRequest(props *adaptercommon.ChatProps) (string, error) {
|
|
res, err := utils.Post(
|
|
c.GetChatEndpoint(),
|
|
c.GetHeader(),
|
|
c.GetChatBody(props, false),
|
|
props.Proxy,
|
|
)
|
|
|
|
if err != nil || res == nil {
|
|
return "", fmt.Errorf("dify error: %s", err.Error())
|
|
}
|
|
|
|
responseBody := utils.Marshal(res)
|
|
response := processChatResponse(responseBody)
|
|
if response == nil {
|
|
return "", fmt.Errorf("dify error: cannot parse response")
|
|
}
|
|
|
|
return response.Answer, nil
|
|
}
|
|
|
|
func (c *ChatInstance) CreateStreamChatRequest(props *adaptercommon.ChatProps, callback globals.Hook) error {
|
|
c.responseComplete = false
|
|
|
|
err := utils.EventScanner(&utils.EventScannerProps{
|
|
Method: "POST",
|
|
Uri: c.GetChatEndpoint(),
|
|
Headers: c.GetHeader(),
|
|
Body: c.GetChatBody(props, true),
|
|
Callback: func(data string) error {
|
|
partial, err := c.ProcessLine(data)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if partial != "" {
|
|
err = callback(&globals.Chunk{Content: partial})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
},
|
|
}, props.Proxy)
|
|
|
|
c.responseComplete = true
|
|
|
|
if err != nil {
|
|
if strings.Contains(err.Body, "\"code\":") {
|
|
errorResp := processChatErrorResponse(err.Body)
|
|
if errorResp != nil {
|
|
return errors.New(fmt.Sprintf("dify error: %s (code: %s)", errorResp.Message, errorResp.Code))
|
|
}
|
|
|
|
var genericResp map[string]interface{}
|
|
if jsonErr := json.Unmarshal([]byte(err.Body), &genericResp); jsonErr == nil {
|
|
errMsg, _ := json.Marshal(genericResp)
|
|
return errors.New(fmt.Sprintf("dify error: %s", string(errMsg)))
|
|
}
|
|
}
|
|
|
|
if err.Error != nil {
|
|
return err.Error
|
|
}
|
|
return errors.New(fmt.Sprintf("dify error: unexpected error in stream request"))
|
|
}
|
|
|
|
return nil
|
|
}
|