Skip to content

Commit dd8e593

Browse files
committed
Auto-commit
1 parent cb2b599 commit dd8e593

File tree

4 files changed

+522
-24
lines changed

4 files changed

+522
-24
lines changed

CLAUDE.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,51 @@ Key files:
165165
- `internal/services/debate_team_config.go` - Team configuration
166166
- `internal/services/debate_dialogue.go` - Dialogue formatter
167167

168+
### Multi-Pass Validation System
169+
170+
The AI Debate system includes a **multi-pass validation** mechanism that re-evaluates, polishes, and improves debate responses before delivering the final consensus:
171+
172+
**Validation Phases:**
173+
| Phase | Icon | Description |
174+
|-------|------|-------------|
175+
| 1. INITIAL RESPONSE | 🔍 | Each AI participant provides their initial perspective |
176+
| 2. VALIDATION || Cross-validation of responses for accuracy and completeness |
177+
| 3. POLISH & IMPROVE || Refinement and improvement based on validation feedback |
178+
| 4. FINAL CONCLUSION | 📜 | Synthesized consensus with confidence scores |
179+
180+
**API Integration:**
181+
```json
182+
POST /v1/debates
183+
{
184+
"topic": "Should AI have consciousness?",
185+
"participants": [...],
186+
"enable_multi_pass_validation": true,
187+
"validation_config": {
188+
"enable_validation": true,
189+
"enable_polish": true,
190+
"validation_timeout": 120,
191+
"polish_timeout": 60,
192+
"min_confidence_to_skip": 0.9,
193+
"max_validation_rounds": 3,
194+
"show_phase_indicators": true
195+
}
196+
}
197+
```
198+
199+
**Response includes:**
200+
- `current_phase` - Current validation phase (when running)
201+
- `multi_pass_result` - Detailed results including:
202+
- `phases_completed` - Number of completed phases
203+
- `overall_confidence` - Final confidence score (0-1)
204+
- `quality_improvement` - Quality improvement from initial to final
205+
- `final_response` - The polished, validated consensus
206+
207+
**Key Files:**
208+
- `internal/services/debate_multipass_validation.go` - Core multi-pass validation system
209+
- `internal/services/debate_multipass_validation_test.go` - Unit tests
210+
- `internal/handlers/debate_handler.go` - API integration
211+
- `challenges/scripts/multipass_validation_challenge.sh` - 66-test validation
212+
168213
### Semantic Intent Detection (ZERO Hardcoding)
169214

170215
HelixAgent uses **LLM-based semantic intent classification** to understand user messages. When a user confirms, refuses, or asks questions, the system uses AI to understand the semantic meaning - not pattern matching.

helixagent

304 KB
Binary file not shown.

internal/handlers/debate_handler.go

Lines changed: 132 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,16 @@ type DebateHandler struct {
2525
}
2626

2727
type debateState struct {
28-
Config *services.DebateConfig `json:"config"`
29-
Status string `json:"status"`
30-
Result *services.DebateResult `json:"result,omitempty"`
31-
Error string `json:"error,omitempty"`
32-
StartTime time.Time `json:"start_time"`
33-
EndTime *time.Time `json:"end_time,omitempty"`
28+
Config *services.DebateConfig `json:"config"`
29+
ValidationConfig *services.ValidationConfig `json:"validation_config,omitempty"`
30+
EnableMultiPassValidation bool `json:"enable_multi_pass_validation"`
31+
Status string `json:"status"`
32+
CurrentPhase string `json:"current_phase,omitempty"`
33+
Result *services.DebateResult `json:"result,omitempty"`
34+
MultiPassResult *services.MultiPassResult `json:"multi_pass_result,omitempty"`
35+
Error string `json:"error,omitempty"`
36+
StartTime time.Time `json:"start_time"`
37+
EndTime *time.Time `json:"end_time,omitempty"`
3438
}
3539

3640
// NewDebateHandler creates a new debate handler
@@ -45,14 +49,27 @@ func NewDebateHandler(debateService *services.DebateService, advancedDebate *ser
4549

4650
// CreateDebateRequest represents the request to create a debate
4751
type CreateDebateRequest struct {
48-
DebateID string `json:"debate_id,omitempty"`
49-
Topic string `json:"topic" binding:"required"`
50-
Participants []ParticipantConfigRequest `json:"participants" binding:"required,min=2"`
51-
MaxRounds int `json:"max_rounds,omitempty"`
52-
Timeout int `json:"timeout,omitempty"` // seconds
53-
Strategy string `json:"strategy,omitempty"`
54-
EnableCognee bool `json:"enable_cognee,omitempty"`
55-
Metadata map[string]any `json:"metadata,omitempty"`
52+
DebateID string `json:"debate_id,omitempty"`
53+
Topic string `json:"topic" binding:"required"`
54+
Participants []ParticipantConfigRequest `json:"participants" binding:"required,min=2"`
55+
MaxRounds int `json:"max_rounds,omitempty"`
56+
Timeout int `json:"timeout,omitempty"` // seconds
57+
Strategy string `json:"strategy,omitempty"`
58+
EnableCognee bool `json:"enable_cognee,omitempty"`
59+
EnableMultiPassValidation bool `json:"enable_multi_pass_validation,omitempty"`
60+
ValidationConfig *ValidationConfigRequest `json:"validation_config,omitempty"`
61+
Metadata map[string]any `json:"metadata,omitempty"`
62+
}
63+
64+
// ValidationConfigRequest configures multi-pass validation
65+
type ValidationConfigRequest struct {
66+
EnableValidation bool `json:"enable_validation"`
67+
EnablePolish bool `json:"enable_polish"`
68+
ValidationTimeout int `json:"validation_timeout,omitempty"` // seconds
69+
PolishTimeout int `json:"polish_timeout,omitempty"` // seconds
70+
MinConfidenceToSkip float64 `json:"min_confidence_to_skip,omitempty"`
71+
MaxValidationRounds int `json:"max_validation_rounds,omitempty"`
72+
ShowPhaseIndicators bool `json:"show_phase_indicators,omitempty"`
5673
}
5774

5875
// ParticipantConfigRequest represents a participant in the request
@@ -159,17 +176,42 @@ func (h *DebateHandler) CreateDebate(c *gin.Context) {
159176
Metadata: req.Metadata,
160177
}
161178

179+
// Build validation config if multi-pass validation is enabled
180+
var validationConfig *services.ValidationConfig
181+
if req.EnableMultiPassValidation {
182+
validationConfig = services.DefaultValidationConfig()
183+
if req.ValidationConfig != nil {
184+
validationConfig.EnableValidation = req.ValidationConfig.EnableValidation
185+
validationConfig.EnablePolish = req.ValidationConfig.EnablePolish
186+
if req.ValidationConfig.ValidationTimeout > 0 {
187+
validationConfig.ValidationTimeout = time.Duration(req.ValidationConfig.ValidationTimeout) * time.Second
188+
}
189+
if req.ValidationConfig.PolishTimeout > 0 {
190+
validationConfig.PolishTimeout = time.Duration(req.ValidationConfig.PolishTimeout) * time.Second
191+
}
192+
if req.ValidationConfig.MinConfidenceToSkip > 0 {
193+
validationConfig.MinConfidenceToSkip = req.ValidationConfig.MinConfidenceToSkip
194+
}
195+
if req.ValidationConfig.MaxValidationRounds > 0 {
196+
validationConfig.MaxValidationRounds = req.ValidationConfig.MaxValidationRounds
197+
}
198+
validationConfig.ShowPhaseIndicators = req.ValidationConfig.ShowPhaseIndicators
199+
}
200+
}
201+
162202
// Store debate state
163203
h.mu.Lock()
164204
h.activeDebates[debateID] = &debateState{
165-
Config: config,
166-
Status: "pending",
167-
StartTime: time.Now(),
205+
Config: config,
206+
ValidationConfig: validationConfig,
207+
EnableMultiPassValidation: req.EnableMultiPassValidation,
208+
Status: "pending",
209+
StartTime: time.Now(),
168210
}
169211
h.mu.Unlock()
170212

171213
// Start debate asynchronously
172-
go h.runDebate(debateID, config)
214+
go h.runDebate(debateID, config, validationConfig)
173215

174216
c.JSON(http.StatusAccepted, gin.H{
175217
"debate_id": debateID,
@@ -184,18 +226,38 @@ func (h *DebateHandler) CreateDebate(c *gin.Context) {
184226
}
185227

186228
// runDebate executes the debate asynchronously
187-
func (h *DebateHandler) runDebate(debateID string, config *services.DebateConfig) {
229+
func (h *DebateHandler) runDebate(debateID string, config *services.DebateConfig, validationConfig *services.ValidationConfig) {
188230
h.mu.Lock()
189231
if state, exists := h.activeDebates[debateID]; exists {
190232
state.Status = "running"
233+
if validationConfig != nil {
234+
state.CurrentPhase = string(services.PhaseInitialResponse)
235+
}
191236
}
192237
h.mu.Unlock()
193238

194239
// Conduct the debate
195240
var result *services.DebateResult
241+
var multiPassResult *services.MultiPassResult
196242
var err error
197243

198-
if h.advancedDebate != nil {
244+
if validationConfig != nil && h.debateService != nil {
245+
// Use multi-pass validation
246+
h.logger.WithField("debate_id", debateID).Info("Running debate with multi-pass validation")
247+
multiPassResult, err = h.debateService.ConductDebateWithMultiPassValidation(
248+
context.Background(),
249+
config,
250+
validationConfig,
251+
)
252+
if multiPassResult != nil && len(multiPassResult.Phases) > 0 {
253+
// Update current phase as we progress
254+
h.mu.Lock()
255+
if state, exists := h.activeDebates[debateID]; exists {
256+
state.CurrentPhase = string(multiPassResult.Phases[len(multiPassResult.Phases)-1].Phase)
257+
}
258+
h.mu.Unlock()
259+
}
260+
} else if h.advancedDebate != nil {
199261
result, err = h.advancedDebate.ConductAdvancedDebate(context.Background(), config)
200262
} else if h.debateService != nil {
201263
result, err = h.debateService.ConductDebate(context.Background(), config)
@@ -217,7 +279,18 @@ func (h *DebateHandler) runDebate(debateID string, config *services.DebateConfig
217279
} else {
218280
state.Status = "completed"
219281
state.Result = result
220-
h.logger.WithField("debate_id", debateID).Info("Debate completed successfully")
282+
state.MultiPassResult = multiPassResult
283+
if multiPassResult != nil {
284+
state.CurrentPhase = string(services.PhaseFinalConclusion)
285+
h.logger.WithFields(logrus.Fields{
286+
"debate_id": debateID,
287+
"phases_completed": len(multiPassResult.Phases),
288+
"overall_confidence": multiPassResult.OverallConfidence,
289+
"quality_improvement": multiPassResult.QualityImprovement,
290+
}).Info("Multi-pass debate completed successfully")
291+
} else {
292+
h.logger.WithField("debate_id", debateID).Info("Debate completed successfully")
293+
}
221294
}
222295
}
223296
}
@@ -254,6 +327,11 @@ func (h *DebateHandler) GetDebate(c *gin.Context) {
254327
"topic": state.Config.Topic,
255328
"max_rounds": state.Config.MaxRounds,
256329
"start_time": state.StartTime.Unix(),
330+
"enable_multi_pass_validation": state.EnableMultiPassValidation,
331+
}
332+
333+
if state.CurrentPhase != "" {
334+
response["current_phase"] = state.CurrentPhase
257335
}
258336

259337
if state.EndTime != nil {
@@ -269,6 +347,16 @@ func (h *DebateHandler) GetDebate(c *gin.Context) {
269347
response["result"] = state.Result
270348
}
271349

350+
if state.MultiPassResult != nil {
351+
response["multi_pass_result"] = gin.H{
352+
"phases_completed": len(state.MultiPassResult.Phases),
353+
"final_response": state.MultiPassResult.FinalResponse,
354+
"overall_confidence": state.MultiPassResult.OverallConfidence,
355+
"quality_improvement": state.MultiPassResult.QualityImprovement,
356+
"phases": state.MultiPassResult.Phases,
357+
}
358+
}
359+
272360
c.JSON(http.StatusOK, response)
273361
}
274362

@@ -291,9 +379,14 @@ func (h *DebateHandler) GetDebateStatus(c *gin.Context) {
291379
}
292380

293381
status := gin.H{
294-
"debate_id": debateID,
295-
"status": state.Status,
296-
"start_time": state.StartTime.Unix(),
382+
"debate_id": debateID,
383+
"status": state.Status,
384+
"start_time": state.StartTime.Unix(),
385+
"enable_multi_pass_validation": state.EnableMultiPassValidation,
386+
}
387+
388+
if state.CurrentPhase != "" {
389+
status["current_phase"] = state.CurrentPhase
297390
}
298391

299392
if state.EndTime != nil {
@@ -309,6 +402,21 @@ func (h *DebateHandler) GetDebateStatus(c *gin.Context) {
309402
if state.Status == "running" && state.Config != nil {
310403
status["max_rounds"] = state.Config.MaxRounds
311404
status["timeout_seconds"] = state.Config.Timeout.Seconds()
405+
if state.EnableMultiPassValidation {
406+
status["validation_phases"] = []string{
407+
string(services.PhaseInitialResponse),
408+
string(services.PhaseValidation),
409+
string(services.PhasePolishImprove),
410+
string(services.PhaseFinalConclusion),
411+
}
412+
}
413+
}
414+
415+
// Add multi-pass validation summary if completed
416+
if state.MultiPassResult != nil {
417+
status["overall_confidence"] = state.MultiPassResult.OverallConfidence
418+
status["quality_improvement"] = state.MultiPassResult.QualityImprovement
419+
status["phases_completed"] = len(state.MultiPassResult.Phases)
312420
}
313421

314422
c.JSON(http.StatusOK, status)

0 commit comments

Comments
 (0)