Complete snapshot of /opt/microdao-daarion/ from NODE1 (144.76.224.179).
This represents the actual running production code that has diverged
significantly from the previous main branch.
Key changes from old main:
- Gateway (http_api.py): expanded from ~40KB to 164KB with full agent support
- Router: new /v1/agents/{id}/infer endpoint with vision + DeepSeek routing
- Behavior Policy: SOWA v2.2 (3-level: FULL/ACK/SILENT)
- Agent Registry: config/agent_registry.yml as single source of truth
- 13 agents configured (was 3)
- Memory service integration
- CrewAI teams and roles
Excluded from snapshot: venv/, .env, data/, backups, .tgz archives
Co-authored-by: Cursor <cursoragent@cursor.com>
107 lines
3.6 KiB
Python
107 lines
3.6 KiB
Python
"""
|
|
DAARION Platform - Contradiction Detector
|
|
Prevents agent from contradicting user corrections
|
|
"""
|
|
import re
|
|
from typing import Optional, Tuple
|
|
|
|
# Patterns that indicate user correction
|
|
CORRECTION_PATTERNS = [
|
|
r"це\s+всього\s+(\d+)",
|
|
r"тільки\s+(\d+)\s+частин",
|
|
r"(\d+)\s+поки\s+немає",
|
|
r"(\d+)\s+частин\s+всього",
|
|
r"всього\s+(\d+)",
|
|
r"поки\s+(\d+)",
|
|
r"немає\s+(\d+)",
|
|
r"(\d+)\s+частини\s+тільки"
|
|
]
|
|
|
|
# Patterns that indicate agent is contradicting
|
|
CONTRADICTION_PATTERNS = [
|
|
r"чекаю\s+(\d+)\s+частину",
|
|
r"чекаю\s+(\d+)\s+частину",
|
|
r"чекаю\s+продовження",
|
|
r"чекаю\s+наступну"
|
|
]
|
|
|
|
|
|
def detect_correction(user_message: str) -> Optional[int]:
|
|
"""
|
|
Detect if user message contains a correction about number of parts.
|
|
|
|
Returns:
|
|
Number of parts mentioned, or None if no correction detected
|
|
"""
|
|
user_lower = user_message.lower()
|
|
|
|
for pattern in CORRECTION_PATTERNS:
|
|
match = re.search(pattern, user_lower)
|
|
if match:
|
|
try:
|
|
num = int(match.group(1))
|
|
return num
|
|
except (ValueError, IndexError):
|
|
continue
|
|
|
|
return None
|
|
|
|
|
|
def check_contradiction(agent_response: str, user_correction: Optional[int]) -> Tuple[bool, Optional[str]]:
|
|
"""
|
|
Check if agent response contradicts user correction.
|
|
|
|
Returns:
|
|
(is_contradiction, error_message)
|
|
"""
|
|
if user_correction is None:
|
|
return False, None
|
|
|
|
response_lower = agent_response.lower()
|
|
|
|
# Check for contradiction patterns
|
|
for pattern in CONTRADICTION_PATTERNS:
|
|
match = re.search(pattern, response_lower)
|
|
if match:
|
|
# Extract number from agent response
|
|
try:
|
|
agent_num = int(match.group(1)) if match.groups() else None
|
|
|
|
# If agent mentions a number higher than user correction, it's a contradiction
|
|
if agent_num and agent_num > user_correction:
|
|
return True, f"Користувач сказав 'всього {user_correction}', але агент каже 'чекаю {agent_num} частину'"
|
|
except (ValueError, IndexError):
|
|
# Pattern matched but no number - still check for "продовження"
|
|
if "продовження" in response_lower or "наступну" in response_lower:
|
|
return True, f"Користувач сказав 'всього {user_correction}', але агент каже 'чекаю продовження'"
|
|
|
|
return False, None
|
|
|
|
|
|
def filter_contradiction(response: str, user_correction: Optional[int]) -> str:
|
|
"""
|
|
Filter out contradiction from response.
|
|
|
|
Returns:
|
|
Filtered response
|
|
"""
|
|
if user_correction is None:
|
|
return response
|
|
|
|
# Remove contradiction phrases
|
|
filtered = response
|
|
|
|
# Remove "чекаю N частину" where N > user_correction
|
|
pattern = re.compile(r"чекаю\s+\d+\s+частину", re.IGNORECASE)
|
|
filtered = pattern.sub("", filtered)
|
|
|
|
# Remove "чекаю продовження" if user said "всього N"
|
|
if "продовження" in filtered.lower() or "наступну" in filtered.lower():
|
|
filtered = re.sub(r"чекаю\s+продовження", "", filtered, flags=re.IGNORECASE)
|
|
filtered = re.sub(r"чекаю\s+наступну", "", filtered, flags=re.IGNORECASE)
|
|
|
|
# Clean up extra spaces
|
|
filtered = re.sub(r"\s+", " ", filtered).strip()
|
|
|
|
return filtered
|