package service import ( "context" "fmt" "io" "github.com/topfans/backend/services/aiChatService/model" ) // DifyStreamReaderAdapter 适配 DifyStreamReader → StreamReader 接口 // DifyStreamReader.Next() returns (content, done, convID) // StreamReader.Next() returns (content, done, error) type DifyStreamReaderAdapter struct { reader *DifyStreamReader } func (a *DifyStreamReaderAdapter) Next() (string, bool, error) { content, done, _ := a.reader.Next() return content, done, nil } func (a *DifyStreamReaderAdapter) Close() error { return a.reader.Close() } // DifyAdapter Dify 适配器:适配 DifyClient → StreamReader 接口 // 将 BuildPrompt 输出的 []model.Message 转换为 Dify StreamRequest type DifyAdapter struct { difyClient *DifyClient conversationID string } // NewDifyAdapter 创建 Dify 适配器 func NewDifyAdapter(difyClient *DifyClient) *DifyAdapter { return &DifyAdapter{ difyClient: difyClient, } } // StreamChat 将 []model.Message 转换为 Dify 流式调用 // messages 的最后一条必须是 user 消息(当前输入) // Dify Workflow 端点不维护多轮上下文,需要通过 inputs.query 传入完整对话文本 func (s *DifyAdapter) StreamChat(ctx context.Context, messages []model.Message) (StreamReader, error) { if len(messages) == 0 { return nil, fmt.Errorf("empty messages") } // 取最后一条作为当前 query lastMsg := messages[len(messages)-1] if lastMsg.Role != "user" { return nil, fmt.Errorf("last message must be user role") } req := StreamRequest{ Query: lastMsg.Content, ConversationID: s.conversationID, } reader, err := s.difyClient.StreamChat(ctx, req) if err != nil { return nil, err } return &DifyStreamReaderAdapter{reader: reader}, nil } // 确保接口实现正确 var _ StreamReader = (*DifyStreamReaderAdapter)(nil) var _ io.Closer = (*DifyStreamReaderAdapter)(nil)