514 lines
26 KiB
Markdown
514 lines
26 KiB
Markdown
# Refactoring Plan: Integrate Intent Analysis into Existing Prompts and Simplify AI Loop Mode
|
|
|
|
## Overview
|
|
**Integrate** IntentAnalyzer logic into existing prompts (userintention, taskplan, dynamic) instead of making separate AI calls (saves 3 AI calls). Simplify AI loop logic to: **Complete JSON = Stop, Cut-off JSON = Continue**. Remove Definition of Done (DoD) logic entirely.
|
|
|
|
**Key Change**: Keep intent analysis logic (dataType, expectedFormats, qualityRequirements, etc.) but merge it into existing prompts instead of separate calls.
|
|
|
|
**Overlap Analysis**:
|
|
- **UserIntention prompt** already does: language detection, normalization, intent extraction
|
|
- **Intent Analysis prompt** does: primaryGoal, dataType, expectedFormats, qualityRequirements, successCriteria, language detection
|
|
- **Overlap**: Language detection (both do it)
|
|
- **Solution**: Merge intent analysis fields into userintention prompt (one call instead of two)
|
|
|
|
## Changes Required
|
|
|
|
### Phase 1: Integrate Intent Analysis into Existing Prompts
|
|
|
|
#### 1. Update UserIntention Prompt (Integrate Intent Analysis)
|
|
- **File**: `gateway/modules/workflows/workflowManager.py`
|
|
- **Lines**: 353-378
|
|
- **Changes**:
|
|
- Merge intent analysis fields (from intentAnalyzer.py lines 2-31) into userintention prompt
|
|
- Add fields: `primaryGoal`, `dataType`, `expectedFormats`, `qualityRequirements`, `successCriteria`
|
|
- Keep existing fields: `detectedLanguage`, `normalizedRequest`, `intent`, `contextItems`
|
|
- **Integration**: Combine both prompts into one - userintention already does language detection and normalization, now also does full intent analysis
|
|
- **Note**: Adding 5 items is no problem for AI - prompt complexity is acceptable
|
|
- **CRITICAL**: Intent check should be different on workflow, task, and action levels (keep separate)
|
|
- **New Prompt Structure**:
|
|
```python
|
|
analyzerPrompt = (
|
|
"You are an input analyzer. From the user's message, perform ALL of the following in one pass:\n"
|
|
"1) detectedLanguage: detect ISO 639-1 language code (e.g., de, en).\n"
|
|
"2) normalizedRequest: full, explicit restatement of the user's request in the detected language; do NOT summarize; preserve ALL constraints and details.\n"
|
|
"3) intent: concise single-paragraph core request in the detected language for high-level routing.\n"
|
|
"4) contextItems: supportive data blocks to attach as separate documents if significantly larger than the intent.\n"
|
|
"5) primaryGoal: The main objective the user wants to achieve.\n"
|
|
"6) dataType: What type of data/content they want (numbers|text|documents|analysis|code|unknown).\n"
|
|
"7) expectedFormats: What file format(s) they expect - provide matching file format extensions list (e.g., [\"xlsx\", \"pdf\"]). If format is unclear or not specified, use empty list [].\n"
|
|
"8) qualityRequirements: Quality requirements they have (accuracy, completeness) as {accuracyThreshold: 0.0-1.0, completenessThreshold: 0.0-1.0}.\n"
|
|
"9) successCriteria: Specific success criteria that define completion (array of strings).\n\n"
|
|
"Rules:\n"
|
|
"- If total content (intent + data) is < 10% of model max tokens, do not extract; return empty contextItems and keep intent compact and self-contained.\n"
|
|
"- If content exceeds that threshold, move bulky parts into contextItems; keep intent short and clear.\n"
|
|
"- Preserve critical references (URLs, filenames) in intent.\n"
|
|
"- Normalize to the primary detected language if mixed-language.\n\n"
|
|
"Return ONLY JSON (no markdown) with this shape:\n"
|
|
"{\n"
|
|
" \"detectedLanguage\": \"de|en|fr|it|...\",\n"
|
|
" \"normalizedRequest\": \"Full explicit instruction in detected language\",\n"
|
|
" \"intent\": \"Concise normalized request...\",\n"
|
|
" \"contextItems\": [...],\n"
|
|
" \"primaryGoal\": \"The main objective the user wants to achieve\",\n"
|
|
" \"dataType\": \"numbers|text|documents|analysis|code|unknown\",\n"
|
|
" \"expectedFormats\": [\"pdf\", \"docx\", \"xlsx\", ...],\n"
|
|
" \"qualityRequirements\": {\n"
|
|
" \"accuracyThreshold\": 0.0-1.0,\n"
|
|
" \"completenessThreshold\": 0.0-1.0\n"
|
|
" },\n"
|
|
" \"successCriteria\": [\"specific criterion 1\", \"specific criterion 2\"]\n"
|
|
"}\n\n"
|
|
f"User message:\n{self.services.utils.sanitizePromptContent(userInput.prompt, 'userinput')}"
|
|
)
|
|
```
|
|
- **Update parsing** (lines 397-402): Extract new fields and store in workflow object
|
|
- Store as `workflow._workflowIntent` for reuse
|
|
|
|
#### 2. Remove IntentAnalyzer Class and Calls
|
|
- **File**: `gateway/modules/workflows/processing/adaptive/intentAnalyzer.py`
|
|
- **Action**: Delete entire file (logic now integrated into prompts)
|
|
- **File**: `gateway/modules/workflows/processing/adaptive/__init__.py`
|
|
- **Action**: Remove `IntentAnalyzer` from exports
|
|
|
|
- **File**: `gateway/modules/workflows/processing/core/taskPlanner.py`
|
|
- **Line 56**: Remove `workflowIntent = await intentAnalyzer.analyzeUserIntent(actualUserPrompt, None)`
|
|
- **Line 60**: Use `workflowIntent` from workflow object (set in workflowManager)
|
|
- **Lines 167-173**: Use workflowIntent from workflow object for dataType/expectedFormats/qualityRequirements
|
|
|
|
- **File**: `gateway/modules/workflows/processing/modes/modeDynamic.py`
|
|
- **Line 36**: Remove `self.intentAnalyzer = IntentAnalyzer(services)`
|
|
- **Line 66**: Use `workflow._workflowIntent` from workflow object (already set)
|
|
- **Line 72**: Remove `self.taskIntent = await self.intentAnalyzer.analyzeUserIntent(taskStep.objective, context)`
|
|
- **Line 362**: Remove `actionIntent = await self.intentAnalyzer.analyzeUserIntent(actionObjective, context)`
|
|
- **Lines 60-67**: Use existing workflowIntent from workflow object
|
|
- **Lines 359-373**: Remove actionIntent creation logic (will be integrated into dynamic prompts)
|
|
|
|
#### 3. Remove IntentAnalyzer Imports
|
|
- **File**: `taskPlanner.py` (line 12): Remove `from modules.workflows.processing.adaptive import IntentAnalyzer`
|
|
- **File**: `modeDynamic.py` (line 25): Remove `IntentAnalyzer` from imports
|
|
|
|
### Phase 2: Integrate Information Gathering into Existing Prompts
|
|
|
|
#### 4. Update Taskplan Prompt (Use Workflow Intent from UserIntention, Allow Override)
|
|
- **File**: `gateway/modules/workflows/processing/shared/promptGenerationTaskplan.py`
|
|
- **Changes**:
|
|
- Use `workflowIntent` from workflow object (already set in workflowManager from userintention analysis)
|
|
- Pass workflowIntent fields as context to taskplan prompt via placeholders
|
|
- **CRITICAL**: Allow taskplan to **override workflow intent** if task-specific needs differ
|
|
- Example: Workflow wants PDF, but task needs CSV for intermediate step
|
|
- Taskplan prompt can reference workflow intent but can override with task-specific values
|
|
- **If taskplan needs task-specific intent analysis, add fields to task JSON**:
|
|
```json
|
|
{
|
|
"overview": "...",
|
|
"userMessage": "...",
|
|
"tasks": [
|
|
{
|
|
"id": "task_1",
|
|
"objective": "...",
|
|
"dataType": "numbers|text|documents|analysis|code|unknown", // Inherit from workflow or task-specific
|
|
"expectedFormats": ["pdf", "docx", ...], // Inherit from workflow or task-specific
|
|
"qualityRequirements": {...}, // Inherit from workflow or task-specific
|
|
...
|
|
}
|
|
]
|
|
}
|
|
```
|
|
- Update `taskPlanner.py` to use workflowIntent from workflow object (line 60)
|
|
- Extract task-specific fields from task plan response if provided
|
|
|
|
#### 5. Update Dynamic Plan Selection Prompt (Integrate Action Intent Analysis)
|
|
- **File**: `gateway/modules/workflows/processing/shared/promptGenerationActionsDynamic.py`
|
|
- **Function**: `generateDynamicPlanSelectionPrompt`
|
|
- **Changes**:
|
|
- Integrate intent analysis into action selection prompt
|
|
- Add intent analysis instructions to prompt template
|
|
- Add to JSON response structure:
|
|
```json
|
|
{
|
|
"action": "...",
|
|
"actionObjective": "...",
|
|
"dataType": "numbers|text|documents|analysis|code|unknown", // Analyze from actionObjective
|
|
"expectedFormats": ["pdf", "docx", "xlsx", ...], // Analyze from actionObjective
|
|
"qualityRequirements": {
|
|
"accuracyThreshold": 0.0-1.0,
|
|
"completenessThreshold": 0.0-1.0
|
|
}, // Analyze from actionObjective
|
|
"successCriteria": ["specific criterion 1", ...], // Analyze from actionObjective
|
|
"userMessage": "...",
|
|
"learnings": [...],
|
|
"requiredInputDocuments": [...],
|
|
"requiredConnection": "...",
|
|
"parametersContext": "..."
|
|
}
|
|
```
|
|
- Update prompt instructions to analyze actionObjective for these fields
|
|
- Extract these fields in `modeDynamic.py` when processing selection
|
|
- Store as `workflow._actionIntent` for use in AI loop (but without DoD)
|
|
|
|
#### 6. Update Dynamic Parameters Prompt
|
|
- **File**: `gateway/modules/workflows/processing/shared/promptGenerationActionsDynamic.py`
|
|
- **Function**: `generateDynamicParametersPrompt`
|
|
- **Changes**:
|
|
- Add completion criteria description (natural language, not DoD metrics)
|
|
- Ask AI to describe what "complete" means for this action
|
|
- Example: "This action is complete when: [description]"
|
|
- Use natural language completion criteria instead of DoD metrics
|
|
|
|
### Phase 3: Simplify AI Loop Logic
|
|
|
|
#### 7. Simplify `_shouldContinueGeneration`
|
|
- **File**: `gateway/modules/services/serviceAi/mainServiceAi.py`
|
|
- **Lines**: 904-943
|
|
- **Changes**:
|
|
- Remove DoD/KPI checking logic
|
|
- Remove `workflowIntent` parameter usage for DoD
|
|
- Remove `_analyzeTaskCompletion` call (verified: not called anywhere)
|
|
- **CRITICAL**: JSON completeness is determined by **parsing**, NOT by checking last character!
|
|
- Last character check (line 860) is **WRONG** - `}` or `]` could be by chance, JSON still incomplete
|
|
- **New Logic**:
|
|
```python
|
|
def _shouldContinueGeneration(
|
|
self,
|
|
allSections: List[Dict[str, Any]],
|
|
iteration: int,
|
|
wasJsonComplete: bool,
|
|
rawResponse: str = None
|
|
) -> bool:
|
|
"""
|
|
Determine if AI generation loop should continue.
|
|
|
|
Simple logic:
|
|
- If JSON parsing failed or incomplete → continue (needs more content)
|
|
- If JSON parses successfully and is complete → stop (all content delivered)
|
|
- Loop detection prevents infinite loops
|
|
|
|
CRITICAL: JSON completeness is determined by parsing, NOT by last character check!
|
|
Returns True if we should continue, False if AI Loop is done.
|
|
"""
|
|
if len(allSections) == 0:
|
|
return True # No sections yet, continue
|
|
|
|
# CRITERION 1: If JSON was incomplete/broken (parsing failed or incomplete) - continue to repair/complete
|
|
if not wasJsonComplete:
|
|
logger.info(f"Iteration {iteration}: JSON incomplete/broken - continuing to complete")
|
|
return True
|
|
|
|
# CRITERION 2: JSON is complete (parsed successfully) - check for loop detection
|
|
if self._isStuckInLoop(allSections, iteration):
|
|
logger.warning(f"Iteration {iteration}: Detected potential infinite loop - stopping AI loop")
|
|
return False
|
|
|
|
# JSON is complete and not stuck in loop - done
|
|
logger.info(f"Iteration {iteration}: JSON complete - AI loop done")
|
|
return False
|
|
```
|
|
- Remove `userPrompt` and `workflowIntent` parameters (no longer needed)
|
|
- **Update `_extractSectionsFromResponse`**: Remove last character check (line 860), rely only on JSON parsing
|
|
|
|
#### 8. Remove `_analyzeTaskCompletion` and Check DoD Usage
|
|
- **File**: `gateway/modules/services/serviceAi/mainServiceAi.py`
|
|
- **Lines**: 945-1090
|
|
- **Action**: Delete entire method (verified: not called anywhere in codebase)
|
|
- **Action**: Remove all references to this method
|
|
- **CRITICAL**: Check deeply in code how completeness checks are handled:
|
|
- `_refineDecide` (modeDynamic.py line 693) uses content validation and analysis
|
|
- ContentValidator checks content quality and requirements
|
|
- ProgressTracker tracks progress state
|
|
- **Verify**: DoD checking happens in refinement/validation phase, NOT in AI loop
|
|
- **Action**: Ensure validation/refinement phase still checks requirements after DoD removal
|
|
|
|
#### 9. Revise `buildContinuationContext`
|
|
- **File**: `gateway/modules/shared/jsonUtils.py`
|
|
- **Lines**: 448-1016
|
|
- **Changes**:
|
|
|
|
**A. New Summary Format** (per-section counts):
|
|
```
|
|
Following data has already been delivered:
|
|
|
|
- heading "id" <list of elements.level . elements.text>
|
|
- paragraph with <count> texts
|
|
- bullet_list with <count> items
|
|
- table "id" with <count> rows
|
|
- code_block "id" with <count> code lines
|
|
|
|
Check if with already delivered data and the last delivered data part the full response is delivered.
|
|
If not, deliver the remaining part.
|
|
```
|
|
|
|
**Rules**:
|
|
- If section has no ID, **omit it** from summary (don't show "unknown")
|
|
- If summary is too long (exceeds token limit), truncate: show **first 100 items and last 100 items** (remove middle)
|
|
|
|
**B. New Extraction Algorithm**:
|
|
1. Loop over all sections of the JSON (as it is, cut off), until a section is not complete
|
|
2. **CRITICAL**: There is always only **one section incomplete** (JSON cut-off point)
|
|
3. In the cut off section, loop through all elements, until an element is cut off
|
|
4. **Edge case**: If cut-off is in first element, just show cut-off element (no element before exists)
|
|
5. **Normal case**: Return cut-off element AND the element before it to give to the next iteration prompt
|
|
6. **CRITICAL**: In 99% of cases, JSON is cut off mid-string or mid-number - deliver the cut-off part **as-is** (don't try to "complete" it)
|
|
7. **Performance**: No problem - we only parse one AI response, not all accumulated sections
|
|
|
|
**C. Implementation**:
|
|
```python
|
|
def buildContinuationContext(allSections: List[Dict[str, Any]], lastRawResponse: Optional[str] = None) -> Dict[str, Any]:
|
|
"""
|
|
Build context information from accumulated sections for continuation prompt.
|
|
|
|
Returns summary of delivered data and cut-off point for continuation.
|
|
"""
|
|
context = {
|
|
"section_count": len(allSections),
|
|
}
|
|
|
|
# Build summary of delivered data (per-section counts)
|
|
summary_lines = []
|
|
summary_lines.append("Following data has already been delivered:\n")
|
|
|
|
for section in allSections:
|
|
section_id = section.get("id")
|
|
# CRITICAL: If section has no ID, omit it from summary
|
|
if not section_id:
|
|
continue
|
|
|
|
content_type = section.get("content_type", "")
|
|
elements = section.get("elements", [])
|
|
|
|
if isinstance(elements, list) and elements:
|
|
elem = elements[-1] if elements else {}
|
|
else:
|
|
elem = elements if isinstance(elements, dict) else {}
|
|
|
|
if isinstance(elem, dict):
|
|
if content_type == "heading":
|
|
level = elem.get("level", "")
|
|
text = elem.get("text", "")
|
|
summary_lines.append(f'- heading "{section_id}" level {level}: {text}')
|
|
|
|
elif content_type == "paragraph":
|
|
# Count text elements
|
|
text_count = sum(1 for e in (elements if isinstance(elements, list) else [elem])
|
|
if isinstance(e, dict) and e.get("text"))
|
|
summary_lines.append(f'- paragraph with {text_count} text(s)')
|
|
|
|
elif content_type in ["bullet_list", "numbered_list"]:
|
|
items = elem.get("items", [])
|
|
item_count = len(items) if isinstance(items, list) else 0
|
|
summary_lines.append(f'- bullet_list with {item_count} items')
|
|
|
|
elif content_type == "table":
|
|
rows = elem.get("rows", [])
|
|
row_count = len(rows) if isinstance(rows, list) else 0
|
|
summary_lines.append(f'- table "{section_id}" with {row_count} rows')
|
|
|
|
elif content_type == "code_block":
|
|
code = elem.get("code", "")
|
|
if code:
|
|
lines = [l for l in code.split('\n') if l.strip()]
|
|
line_count = len(lines)
|
|
summary_lines.append(f'- code_block "{section_id}" with {line_count} code lines")
|
|
|
|
# CRITICAL: If summary is too long, truncate: show first 100 and last 100 items
|
|
summary_text = "\n".join(summary_lines)
|
|
if len(summary_lines) > 200: # More than 200 lines
|
|
first_100 = "\n".join(summary_lines[:100])
|
|
last_100 = "\n".join(summary_lines[-100:])
|
|
summary_text = f"{first_100}\n... (truncated {len(summary_lines) - 200} items) ...\n{last_100}"
|
|
|
|
context["delivered_summary"] = summary_text
|
|
|
|
# Extract cut-off point using new algorithm
|
|
# 1. Loop over all sections until finding incomplete section
|
|
incomplete_section = None
|
|
incomplete_section_index = -1
|
|
for i, section in enumerate(allSections):
|
|
if self._isSectionIncomplete(section):
|
|
incomplete_section = section
|
|
incomplete_section_index = i
|
|
break
|
|
|
|
# 2. In incomplete section, loop through elements until finding cut-off element
|
|
# CRITICAL: There is always only ONE section incomplete (JSON cut-off point)
|
|
cut_off_element = None
|
|
element_before_cutoff = None
|
|
|
|
if incomplete_section:
|
|
elements = incomplete_section.get("elements", [])
|
|
if isinstance(elements, list):
|
|
for i, elem in enumerate(elements):
|
|
if self._isElementIncomplete(elem):
|
|
cut_off_element = elem
|
|
# Edge case: If cut-off is in first element, no element before exists
|
|
if i > 0:
|
|
element_before_cutoff = elements[i-1]
|
|
break
|
|
|
|
# 3. Extract from lastRawResponse if available
|
|
# CRITICAL: In 99% of cases, JSON is cut off mid-string or mid-number
|
|
# Deliver the cut-off part AS-IS (don't try to "complete" it)
|
|
if lastRawResponse and not cut_off_element:
|
|
# Try to extract cut-off element from raw response
|
|
# Extract exactly as-is, even if mid-string/mid-number
|
|
cut_off_element = self._extractCutOffElementFromRaw(lastRawResponse, incomplete_section)
|
|
|
|
context["element_before_cutoff"] = element_before_cutoff
|
|
context["cut_off_element"] = cut_off_element
|
|
|
|
return context
|
|
```
|
|
|
|
**D. Keep Existing Merge Logic**:
|
|
- Keep `_mergeSectionsIntelligently` (works well)
|
|
- Keep `_mergeSectionContent` (works well)
|
|
- Keep `_mergeCodeBlocks` (works well)
|
|
|
|
#### 10. Update `buildGenerationPrompt`
|
|
- **File**: `gateway/modules/services/serviceGeneration/subPromptBuilderGeneration.py`
|
|
- **Lines**: 48-171
|
|
- **Changes**:
|
|
- Remove DoD references (line 78)
|
|
- Update continuation prompt to use new summary format:
|
|
```python
|
|
if hasContinuation:
|
|
delivered_summary = continuationContext.get("delivered_summary", "")
|
|
element_before_cutoff = continuationContext.get("element_before_cutoff")
|
|
cut_off_element = continuationContext.get("cut_off_element")
|
|
|
|
continuationText = f"""{delivered_summary}
|
|
|
|
Check if with already delivered data and the last delivered data part the full response is delivered.
|
|
If not, deliver the remaining part.
|
|
|
|
Last complete element before cut-off: {element_before_cutoff}
|
|
Cut-off element (incomplete): {cut_off_element}
|
|
|
|
Continue from the incomplete element above - complete it first, then add NEW items."""
|
|
```
|
|
- Remove progress stats based on DoD
|
|
- Use simple section counts instead
|
|
|
|
#### 11. Clean Up `_callAiWithLooping`
|
|
- **File**: `gateway/modules/services/serviceAi/mainServiceAi.py`
|
|
- **Lines**: 162-365
|
|
- **Changes**:
|
|
- Remove `workflowIntent` parameter usage for DoD (line 223-224)
|
|
- Remove `_analyzeTaskCompletion` call (if any)
|
|
- Simplify `_shouldContinueGeneration` call (remove workflowIntent parameter)
|
|
- Update continuation context building:
|
|
```python
|
|
continuationContext = buildContinuationContext(allSections, lastRawResponse)
|
|
# Remove taskIntent from continuationContext - no longer needed
|
|
```
|
|
|
|
### Phase 4: Clean Up References
|
|
|
|
#### 12. Remove DoD References
|
|
- **File**: `gateway/modules/workflows/processing/modes/modeDynamic.py`
|
|
- Remove DoD extraction from intents (line 365)
|
|
- Remove workflowIntent/taskIntent/actionIntent DoD usage
|
|
|
|
- **File**: `gateway/modules/services/serviceGeneration/subPromptBuilderGeneration.py`
|
|
- Remove DoD from continuation context (line 78)
|
|
|
|
- **File**: `gateway/modules/services/serviceAi/mainServiceAi.py`
|
|
- Remove all DoD-related code
|
|
|
|
#### 13. Update Workflow Intent Storage
|
|
- **File**: `modeDynamic.py`
|
|
- **Changes**:
|
|
- Remove `workflow._workflowIntent` storage (or keep empty structure if needed elsewhere)
|
|
- Remove `workflow._taskIntent` storage
|
|
- Remove `workflow._actionIntent` storage
|
|
- Or keep them but remove DoD fields
|
|
|
|
## Implementation Order
|
|
|
|
1. ✅ **Remove IntentAnalyzer class and all calls** (Phase 1)
|
|
2. ✅ **Update prompts to gather info directly** (Phase 2)
|
|
- Update UserIntention prompt (integrate intent analysis)
|
|
- Update Taskplan prompt (allow workflow intent override)
|
|
- Update Dynamic prompts (integrate action-level intent)
|
|
3. ✅ **Fix JSON completeness check** (Phase 3, Step 7)
|
|
- Remove last character check (line 860)
|
|
- Use JSON parsing only (`json.loads()`)
|
|
4. ✅ **Simplify `_shouldContinueGeneration`** (Phase 3, Step 7)
|
|
5. ✅ **Remove `_analyzeTaskCompletion`** (Phase 3, Step 8)
|
|
- Verify DoD checking in refinement phase (`_refineDecide`, ContentValidator)
|
|
6. ✅ **Revise `buildContinuationContext`** (Phase 3, Step 9)
|
|
- Implement new summary format
|
|
- Implement new extraction algorithm
|
|
- Handle edge cases (first element, mid-string/number cuts)
|
|
- Omit sections without ID
|
|
- Truncate summary if too long (first 100 + last 100)
|
|
7. ✅ **Update `buildGenerationPrompt`** (Phase 3, Step 10)
|
|
8. ✅ **Clean up `_callAiWithLooping`** (Phase 3, Step 11)
|
|
9. ✅ **Remove all DoD references** (Phase 4)
|
|
10. ✅ **Testing and validation** (Post-implementation)
|
|
- Test UserIntention prompt quality (verify all fields extracted correctly)
|
|
- Test extraction edge cases
|
|
- Test task-level intent override
|
|
- Add comprehensive unit tests
|
|
11. ✅ **Documentation** (Post-implementation)
|
|
- Update docs to explain new loop behavior
|
|
- Document JSON completeness check (parsing-based)
|
|
- Document continuation summary format
|
|
|
|
## Expected Benefits
|
|
|
|
- **Saves 3 AI calls per workflow** (workflow intent, task intent, action intent - now integrated into existing calls)
|
|
- **Simpler loop logic** (JSON completeness only, no DoD checking)
|
|
- **Clearer continuation prompts** (section counts instead of DoD metrics)
|
|
- **More precise cut-off detection** (element-level detection)
|
|
- **Better performance** (fewer AI calls = faster execution)
|
|
- **Same information gathered** (intent analysis logic preserved, just integrated)
|
|
|
|
## Testing Checklist
|
|
|
|
### Functional Tests
|
|
- [ ] Task planning works without intent analysis
|
|
- [ ] Dynamic mode action selection works without intent analysis
|
|
- [ ] Dynamic mode parameter generation works without intent analysis
|
|
- [ ] AI loop stops when JSON is complete (parsing-based check)
|
|
- [ ] AI loop continues when JSON is cut off (parsing fails)
|
|
- [ ] Continuation prompts show correct section counts
|
|
- [ ] Cut-off element extraction works correctly
|
|
- [ ] Merge logic still works correctly
|
|
- [ ] No DoD references remain in codebase
|
|
|
|
### Edge Case Tests (from Critical Analysis)
|
|
- [ ] JSON completeness: Nested structures that don't parse correctly
|
|
- [ ] JSON completeness: Mid-string cuts (e.g., `"text": "incomplete`)
|
|
- [ ] JSON completeness: Mid-number cuts (e.g., `"value": 1234`)
|
|
- [ ] Extraction: Cut-off in first element (no element before)
|
|
- [ ] Extraction: Only one incomplete section (not multiple)
|
|
- [ ] Summary: Sections without ID are omitted
|
|
- [ ] Summary: Truncation works (first 100 + last 100 if > 200 items)
|
|
- [ ] Task-level intent override works (task can override workflow intent)
|
|
|
|
### Quality Tests
|
|
- [ ] UserIntention prompt: All 9 fields extracted correctly
|
|
- [ ] UserIntention prompt: Quality maintained after adding 5 fields
|
|
- [ ] Taskplan prompt: Can override workflow intent when needed
|
|
- [ ] Dynamic prompts: Action-level intent analysis works correctly
|
|
|
|
## Notes
|
|
|
|
### Implementation Notes
|
|
- **Keep existing merge logic** - it works well and doesn't need changes
|
|
- **New extraction algorithm** focuses on finding the cut-off point more precisely
|
|
- **Summary format** provides clear progress without DoD thresholds
|
|
- **Intent analysis logic preserved** - just integrated into existing prompts instead of separate calls
|
|
- **UserIntention prompt** already does language detection and normalization - now also does full intent analysis
|
|
- **Taskplan prompt** can use workflowIntent from userintention (no re-analysis needed), but can override if task-specific needs differ
|
|
- **Dynamic prompts** integrate action-level intent analysis (no separate call needed)
|
|
- **DoD removed** - but dataType/expectedFormats/qualityRequirements still gathered for other purposes
|
|
|
|
### Critical Requirements (from Critical Analysis)
|
|
- ✅ **JSON completeness**: Use parsing (`json.loads()`), NOT last character check
|
|
- ✅ **Intent levels**: Keep separate checks for workflow, task, and action levels
|
|
- ✅ **Task-level override**: Critical requirement - allow taskplan to override workflow intent
|
|
- ✅ **Sections without ID**: Omit from summary (don't show "unknown")
|
|
- ✅ **Summary truncation**: Show first 100 and last 100 items if > 200 items
|
|
- ✅ **Extraction edge cases**: Handle first element, only one incomplete section, deliver mid-string/number as-is
|
|
- ✅ **DoD checking**: Verified in refinement phase (`_refineDecide`, ContentValidator), not in AI loop
|