mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-07-12 22:55:45 +08:00
### What problem does this PR solve? - Tools management - Pregel engine wrapper for better usage - UT race - Coding style ### Type of change - [x] Refactoring
116 lines
4.1 KiB
Go
116 lines
4.1 KiB
Go
package core
|
|
|
|
import (
|
|
"context"
|
|
|
|
"ragflow/internal/harness/core/schema"
|
|
)
|
|
|
|
// ---- NewEventSenderModelWrapper creates a handler that sends model output events.
|
|
// Place this in the Handlers chain to control WHERE events are emitted:
|
|
// - Innermost position (last in Handlers list): events contain original (unmodified) model output
|
|
// - Outermost position (first in Handlers list): events contain fully processed output
|
|
//
|
|
// When detected in Handlers, the framework skips its built-in event sender to avoid duplicates.
|
|
func NewEventSenderModelWrapper[M MessageType]() *eventSenderModelHandler[M] {
|
|
return &eventSenderModelHandler[M]{}
|
|
}
|
|
|
|
type eventSenderModelHandler[M MessageType] struct{}
|
|
|
|
func (h *eventSenderModelHandler[M]) WrapModel(ctx context.Context, m Model[M], mc *TypedModelContext[M]) (Model[M], error) {
|
|
ec := getReActExecCtx[M](ctx)
|
|
if ec == nil {
|
|
return m, nil
|
|
}
|
|
return wrapModelWithEventSender(m, ec), nil
|
|
}
|
|
|
|
// All other middleware methods are no-op
|
|
func (h *eventSenderModelHandler[M]) BeforeAgent(ctx context.Context, rc *ReActAgentContext) (context.Context, *ReActAgentContext, error) {
|
|
return ctx, rc, nil
|
|
}
|
|
func (h *eventSenderModelHandler[M]) AfterAgent(ctx context.Context, state *TypedReActAgentState[M]) (context.Context, error) {
|
|
return ctx, nil
|
|
}
|
|
func (h *eventSenderModelHandler[M]) BeforeModelRewrite(ctx context.Context, state *TypedReActAgentState[M], mc *TypedModelContext[M]) (context.Context, *TypedReActAgentState[M], error) {
|
|
return ctx, state, nil
|
|
}
|
|
func (h *eventSenderModelHandler[M]) AfterModelRewrite(ctx context.Context, state *TypedReActAgentState[M], mc *TypedModelContext[M]) (context.Context, *TypedReActAgentState[M], error) {
|
|
return ctx, state, nil
|
|
}
|
|
|
|
// HasUserEventSenderModelWrapper checks if the handlers list contains a user-provided
|
|
// NewEventSenderModelWrapper. When present, the framework skips its internal default
|
|
// model event sender to avoid duplicate events.
|
|
func HasUserEventSenderModelWrapper[M MessageType](handlers []TypedReActMiddleware[M]) bool {
|
|
for _, h := range handlers {
|
|
if _, ok := h.(*eventSenderModelHandler[M]); ok {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// ---- Tool event constructors ----
|
|
|
|
// TypedToolInvokeEvent creates an event for a synchronous tool result.
|
|
func TypedToolInvokeEvent(result string, tc *ToolContext) *TypedAgentEvent[*schema.Message] {
|
|
msg := schema.ToolMessage(result, tc.CallID)
|
|
return typedEventFromMessage(msg, nil, schema.RoleTool, tc.Name)
|
|
}
|
|
|
|
// TypedToolStreamEvent creates an event for a streaming tool result.
|
|
func TypedToolStreamEvent(resultChunks []string, tc *ToolContext) *TypedAgentEvent[*schema.Message] {
|
|
content := ""
|
|
for _, ch := range resultChunks {
|
|
content += ch
|
|
}
|
|
msg := schema.ToolMessage(content, tc.CallID)
|
|
return typedEventFromMessage(msg, nil, schema.RoleTool, tc.Name)
|
|
}
|
|
|
|
// TypedEnhancedToolInvokeEvent creates an event for an enhanced tool result.
|
|
// Propagates Extra metadata for multimodal support.
|
|
func TypedEnhancedToolInvokeEvent(result *schema.ToolResult, tc *ToolContext) *TypedAgentEvent[*schema.Message] {
|
|
content := result.Content
|
|
if content == "" {
|
|
content = result.Error
|
|
}
|
|
msg := schema.ToolMessage(content, tc.CallID)
|
|
msg.Name = tc.Name
|
|
if result.Extra != nil {
|
|
if msg.Extra == nil {
|
|
msg.Extra = make(map[string]any, len(result.Extra))
|
|
}
|
|
for k, v := range result.Extra {
|
|
msg.Extra[k] = v
|
|
}
|
|
}
|
|
return typedEventFromMessage(msg, nil, schema.RoleTool, tc.Name)
|
|
}
|
|
|
|
// TypedEnhancedToolStreamEvent creates an event for a streaming enhanced tool result.
|
|
// Propagates the last result's Extra metadata.
|
|
func TypedEnhancedToolStreamEvent(results []*schema.ToolResult, tc *ToolContext) *TypedAgentEvent[*schema.Message] {
|
|
if len(results) == 0 {
|
|
return nil
|
|
}
|
|
last := results[len(results)-1]
|
|
content := last.Content
|
|
if content == "" {
|
|
content = last.Error
|
|
}
|
|
msg := schema.ToolMessage(content, tc.CallID)
|
|
msg.Name = tc.Name
|
|
if last.Extra != nil {
|
|
if msg.Extra == nil {
|
|
msg.Extra = make(map[string]any, len(last.Extra))
|
|
}
|
|
for k, v := range last.Extra {
|
|
msg.Extra[k] = v
|
|
}
|
|
}
|
|
return typedEventFromMessage(msg, nil, schema.RoleTool, tc.Name)
|
|
}
|